From 8a82b39ef90b95cd4533fb5a6f5afa2b74ebd61d Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Wed, 2 Oct 2013 17:31:15 +0200 Subject: Compatibility code is modified not to rely on kernel version numbers Instead the kernel source code is checked to verify the different compatibility issues for the supported kernel releases. This way hopefully backported features will be handled properly. --- kernel/net/netfilter/ipset/ip_set_core.c | 41 +++++++++++++++++++++++-- kernel/net/netfilter/ipset/ip_set_getport.c | 5 ++-- kernel/net/netfilter/ipset/pfxlen.c | 2 +- kernel/net/netfilter/xt_set.c | 46 +++++++++++++++-------------- 4 files changed, 66 insertions(+), 28 deletions(-) (limited to 'kernel/net') diff --git a/kernel/net/netfilter/ipset/ip_set_core.c b/kernel/net/netfilter/ipset/ip_set_core.c index 9506973..c1989d9 100644 --- a/kernel/net/netfilter/ipset/ip_set_core.c +++ b/kernel/net/netfilter/ipset/ip_set_core.c @@ -1388,11 +1388,11 @@ ip_set_dump(struct sock *ctnl, struct sk_buff *skb, if (unlikely(protocol_failed(attr))) return -IPSET_ERR_PROTOCOL; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) +#if HAVE_NETLINK_DUMP_START_ARGS == 5 return netlink_dump_start(ctnl, skb, nlh, ip_set_dump_start, ip_set_dump_done); -#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) +#elif HAVE_NETLINK_DUMP_START_ARGS == 6 return netlink_dump_start(ctnl, skb, nlh, ip_set_dump_start, ip_set_dump_done, 0); @@ -1977,20 +1977,42 @@ static struct nf_sockopt_ops so_set __read_mostly = { static int __net_init ip_set_net_init(struct net *net) { - struct ip_set_net *inst = ip_set_pernet(net); + struct ip_set_net *inst; struct ip_set **list; +#ifdef HAVE_NET_OPS_ID + inst = ip_set_pernet(net); +#else + int err; + + inst = kzalloc(sizeof(struct ip_set_net), GFP_KERNEL); + if (!inst) + return -ENOMEM; + err = net_assign_generic(net, ip_set_net_id, inst); + if (err < 0) + goto err_alloc; +#endif inst->ip_set_max = max_sets ? max_sets : CONFIG_IP_SET_MAX; if (inst->ip_set_max >= IPSET_INVALID_ID) inst->ip_set_max = IPSET_INVALID_ID - 1; list = kzalloc(sizeof(struct ip_set *) * inst->ip_set_max, GFP_KERNEL); if (!list) +#ifdef HAVE_NET_OPS_ID return -ENOMEM; +#else + goto err_alloc; +#endif inst->is_deleted = 0; rcu_assign_pointer(inst->ip_set_list, list); pr_notice("ip_set: protocol %u\n", IPSET_PROTOCOL); return 0; + +#ifndef HAVE_NET_OPS_ID +err_alloc: + kfree(inst); + return err; +#endif } static void __net_exit @@ -2009,13 +2031,18 @@ ip_set_net_exit(struct net *net) ip_set_destroy_set(inst, i); } kfree(rcu_dereference_protected(inst->ip_set_list, 1)); +#ifndef HAVE_NET_OPS_ID + kfree(inst); +#endif } static struct pernet_operations ip_set_net_ops = { .init = ip_set_net_init, .exit = ip_set_net_exit, +#ifdef HAVE_NET_OPS_ID .id = &ip_set_net_id, .size = sizeof(struct ip_set_net) +#endif }; @@ -2033,7 +2060,11 @@ ip_set_init(void) nfnetlink_subsys_unregister(&ip_set_netlink_subsys); return ret; } +#ifdef HAVE_NET_OPS_ID ret = register_pernet_subsys(&ip_set_net_ops); +#else + ret = register_pernet_gen_device(&ip_set_net_id, &ip_set_net_ops); +#endif if (ret) { pr_err("ip_set: cannot register pernet_subsys.\n"); nf_unregister_sockopt(&so_set); @@ -2046,7 +2077,11 @@ ip_set_init(void) static void __exit ip_set_fini(void) { +#ifdef HAVE_NET_OPS_ID unregister_pernet_subsys(&ip_set_net_ops); +#else + unregister_pernet_gen_device(ip_set_net_id, &ip_set_net_ops); +#endif nf_unregister_sockopt(&so_set); nfnetlink_subsys_unregister(&ip_set_netlink_subsys); pr_debug("these are the famous last words\n"); diff --git a/kernel/net/netfilter/ipset/ip_set_getport.c b/kernel/net/netfilter/ipset/ip_set_getport.c index a0d96eb..5d5ff82 100644 --- a/kernel/net/netfilter/ipset/ip_set_getport.c +++ b/kernel/net/netfilter/ipset/ip_set_getport.c @@ -8,7 +8,7 @@ /* Get Layer-4 data from the packets */ #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) +#ifdef HAVE_EXPORT_H #include #endif #include @@ -21,6 +21,7 @@ #include #include +#include /* We must handle non-linear skbs */ static bool @@ -138,7 +139,7 @@ ip_set_get_ip6_port(const struct sk_buff *skb, bool src, __be16 frag_off = 0; nexthdr = ipv6_hdr(skb)->nexthdr; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) +#if HAVE_IPV6_SKIP_EXTHDR_ARGS == 4 protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, &frag_off); #else diff --git a/kernel/net/netfilter/ipset/pfxlen.c b/kernel/net/netfilter/ipset/pfxlen.c index 1fe890f..e69f5ef 100644 --- a/kernel/net/netfilter/ipset/pfxlen.c +++ b/kernel/net/netfilter/ipset/pfxlen.c @@ -1,5 +1,5 @@ #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) +#ifdef HAVE_EXPORT_H #include #endif #include diff --git a/kernel/net/netfilter/xt_set.c b/kernel/net/netfilter/xt_set.c index 4a4cee9..46fdbe0 100644 --- a/kernel/net/netfilter/xt_set.c +++ b/kernel/net/netfilter/xt_set.c @@ -28,16 +28,18 @@ MODULE_ALIAS("ip6t_set"); MODULE_ALIAS("ipt_SET"); MODULE_ALIAS("ip6t_SET"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) +#ifdef HAVE_CHECKENTRY_BOOL #define CHECK_OK 1 #define CHECK_FAIL(err) 0 #define CONST const #define FTYPE bool +#define XT_PAR_NET(par) NULL #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) */ #define CHECK_OK 0 #define CHECK_FAIL(err) (err) #define CONST #define FTYPE int +#define XT_PAR_NET(par) (par)->net #endif static inline int @@ -94,7 +96,7 @@ set_match_v0_checkentry(const struct xt_mtchk_param *par) struct xt_set_info_match_v0 *info = par->matchinfo; ip_set_id_t index; - index = ip_set_nfnl_get_byindex(par->net, info->match_set.index); + index = ip_set_nfnl_get_byindex(XT_PAR_NET(par), info->match_set.index); if (index == IPSET_INVALID_ID) { pr_warning("Cannot find set indentified by id %u to match\n", @@ -104,7 +106,7 @@ set_match_v0_checkentry(const struct xt_mtchk_param *par) if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) { pr_warning("Protocol error: set match dimension " "is over the limit!\n"); - ip_set_nfnl_put(par->net, info->match_set.index); + ip_set_nfnl_put(XT_PAR_NET(par), info->match_set.index); return CHECK_FAIL(-ERANGE); } @@ -119,7 +121,7 @@ set_match_v0_destroy(const struct xt_mtdtor_param *par) { struct xt_set_info_match_v0 *info = par->matchinfo; - ip_set_nfnl_put(par->net, info->match_set.index); + ip_set_nfnl_put(XT_PAR_NET(par), info->match_set.index); } /* Revision 1 */ @@ -144,7 +146,7 @@ set_match_v1_checkentry(const struct xt_mtchk_param *par) struct xt_set_info_match_v1 *info = par->matchinfo; ip_set_id_t index; - index = ip_set_nfnl_get_byindex(par->net, info->match_set.index); + index = ip_set_nfnl_get_byindex(XT_PAR_NET(par), info->match_set.index); if (index == IPSET_INVALID_ID) { pr_warning("Cannot find set indentified by id %u to match\n", @@ -154,7 +156,7 @@ set_match_v1_checkentry(const struct xt_mtchk_param *par) if (info->match_set.dim > IPSET_DIM_MAX) { pr_warning("Protocol error: set match dimension " "is over the limit!\n"); - ip_set_nfnl_put(par->net, info->match_set.index); + ip_set_nfnl_put(XT_PAR_NET(par), info->match_set.index); return CHECK_FAIL(-ERANGE); } @@ -166,7 +168,7 @@ set_match_v1_destroy(const struct xt_mtdtor_param *par) { struct xt_set_info_match_v1 *info = par->matchinfo; - ip_set_nfnl_put(par->net, info->match_set.index); + ip_set_nfnl_put(XT_PAR_NET(par), info->match_set.index); } /* Revision 3 match */ @@ -217,7 +219,7 @@ set_match_v3(const struct sk_buff *skb, CONST struct xt_action_param *par) /* Revision 0 interface: backward compatible with netfilter/iptables */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) +#ifdef HAVE_XT_TARGET_PARAM #undef xt_action_param #define xt_action_param xt_target_param #define CAST_TO_MATCH (const struct xt_match_param *) @@ -249,7 +251,7 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par) ip_set_id_t index; if (info->add_set.index != IPSET_INVALID_ID) { - index = ip_set_nfnl_get_byindex(par->net, info->add_set.index); + index = ip_set_nfnl_get_byindex(XT_PAR_NET(par), info->add_set.index); if (index == IPSET_INVALID_ID) { pr_warning("Cannot find add_set index %u as target\n", info->add_set.index); @@ -258,12 +260,12 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par) } if (info->del_set.index != IPSET_INVALID_ID) { - index = ip_set_nfnl_get_byindex(par->net, info->del_set.index); + index = ip_set_nfnl_get_byindex(XT_PAR_NET(par), info->del_set.index); if (index == IPSET_INVALID_ID) { pr_warning("Cannot find del_set index %u as target\n", info->del_set.index); if (info->add_set.index != IPSET_INVALID_ID) - ip_set_nfnl_put(par->net, info->add_set.index); + ip_set_nfnl_put(XT_PAR_NET(par), info->add_set.index); return CHECK_FAIL(-ENOENT); } } @@ -272,9 +274,9 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par) pr_warning("Protocol error: SET target dimension " "is over the limit!\n"); if (info->add_set.index != IPSET_INVALID_ID) - ip_set_nfnl_put(par->net, info->add_set.index); + ip_set_nfnl_put(XT_PAR_NET(par), info->add_set.index); if (info->del_set.index != IPSET_INVALID_ID) - ip_set_nfnl_put(par->net, info->del_set.index); + ip_set_nfnl_put(XT_PAR_NET(par), info->del_set.index); return CHECK_FAIL(-ERANGE); } @@ -291,9 +293,9 @@ set_target_v0_destroy(const struct xt_tgdtor_param *par) const struct xt_set_info_target_v0 *info = par->targinfo; if (info->add_set.index != IPSET_INVALID_ID) - ip_set_nfnl_put(par->net, info->add_set.index); + ip_set_nfnl_put(XT_PAR_NET(par), info->add_set.index); if (info->del_set.index != IPSET_INVALID_ID) - ip_set_nfnl_put(par->net, info->del_set.index); + ip_set_nfnl_put(XT_PAR_NET(par), info->del_set.index); } /* Revision 1 target */ @@ -322,7 +324,7 @@ set_target_v1_checkentry(const struct xt_tgchk_param *par) ip_set_id_t index; if (info->add_set.index != IPSET_INVALID_ID) { - index = ip_set_nfnl_get_byindex(par->net, info->add_set.index); + index = ip_set_nfnl_get_byindex(XT_PAR_NET(par), info->add_set.index); if (index == IPSET_INVALID_ID) { pr_warning("Cannot find add_set index %u as target\n", info->add_set.index); @@ -331,12 +333,12 @@ set_target_v1_checkentry(const struct xt_tgchk_param *par) } if (info->del_set.index != IPSET_INVALID_ID) { - index = ip_set_nfnl_get_byindex(par->net, info->del_set.index); + index = ip_set_nfnl_get_byindex(XT_PAR_NET(par), info->del_set.index); if (index == IPSET_INVALID_ID) { pr_warning("Cannot find del_set index %u as target\n", info->del_set.index); if (info->add_set.index != IPSET_INVALID_ID) - ip_set_nfnl_put(par->net, info->add_set.index); + ip_set_nfnl_put(XT_PAR_NET(par), info->add_set.index); return CHECK_FAIL(-ENOENT); } } @@ -345,9 +347,9 @@ set_target_v1_checkentry(const struct xt_tgchk_param *par) pr_warning("Protocol error: SET target dimension " "is over the limit!\n"); if (info->add_set.index != IPSET_INVALID_ID) - ip_set_nfnl_put(par->net, info->add_set.index); + ip_set_nfnl_put(XT_PAR_NET(par), info->add_set.index); if (info->del_set.index != IPSET_INVALID_ID) - ip_set_nfnl_put(par->net, info->del_set.index); + ip_set_nfnl_put(XT_PAR_NET(par), info->del_set.index); return CHECK_FAIL(-ERANGE); } @@ -360,9 +362,9 @@ set_target_v1_destroy(const struct xt_tgdtor_param *par) const struct xt_set_info_target_v1 *info = par->targinfo; if (info->add_set.index != IPSET_INVALID_ID) - ip_set_nfnl_put(par->net, info->add_set.index); + ip_set_nfnl_put(XT_PAR_NET(par), info->add_set.index); if (info->del_set.index != IPSET_INVALID_ID) - ip_set_nfnl_put(par->net, info->del_set.index); + ip_set_nfnl_put(XT_PAR_NET(par), info->del_set.index); } /* Revision 2 target */ -- cgit v1.2.3