diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index efbbfa770d66..e99afc1414cd 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -93,6 +93,7 @@ enum nf_hook_ops_type { NF_HOOK_OP_NF_TABLES, NF_HOOK_OP_BPF, NF_HOOK_OP_NFT_FT, + NF_HOOK_OP_NAT, }; struct nf_hook_ops { @@ -140,6 +141,12 @@ struct nf_hook_entries { */ }; +struct nf_nat_lookup_hook_priv { + struct nf_hook_entries __rcu *entries; + + struct rcu_head rcu_head; +}; + #ifdef CONFIG_NETFILTER static inline struct nf_hook_ops **nf_hook_entries_get_hook_ops(const struct nf_hook_entries *e) { diff --git a/include/linux/netfilter/nf_conntrack_h323.h b/include/linux/netfilter/nf_conntrack_h323.h index 81286c499325..b15f37604cde 100644 --- a/include/linux/netfilter/nf_conntrack_h323.h +++ b/include/linux/netfilter/nf_conntrack_h323.h @@ -9,8 +9,6 @@ #include #include -#define RAS_PORT 1719 -#define Q931_PORT 1720 #define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */ /* This structure exists only once per master */ diff --git a/include/linux/netfilter/nf_conntrack_pptp.h b/include/linux/netfilter/nf_conntrack_pptp.h index c3bdb4370938..c0b305ce7c3c 100644 --- a/include/linux/netfilter/nf_conntrack_pptp.h +++ b/include/linux/netfilter/nf_conntrack_pptp.h @@ -50,8 +50,6 @@ struct nf_nat_pptp { __be16 pac_call_id; /* NAT'ed PAC call id */ }; -#define PPTP_CONTROL_PORT 1723 - #define PPTP_PACKET_CONTROL 1 #define PPTP_PACKET_MGMT 2 diff --git a/include/linux/netfilter/nf_conntrack_sane.h b/include/linux/netfilter/nf_conntrack_sane.h index 46c7acd1b4a7..8501035d7335 100644 --- a/include/linux/netfilter/nf_conntrack_sane.h +++ b/include/linux/netfilter/nf_conntrack_sane.h @@ -3,8 +3,6 @@ #define _NF_CONNTRACK_SANE_H /* SANE tracking. */ -#define SANE_PORT 6566 - enum sane_state { SANE_STATE_NORMAL, SANE_STATE_START_REQUESTED, diff --git a/include/linux/netfilter/nf_conntrack_tftp.h b/include/linux/netfilter/nf_conntrack_tftp.h index 90b334bbce3c..e3d1739c557d 100644 --- a/include/linux/netfilter/nf_conntrack_tftp.h +++ b/include/linux/netfilter/nf_conntrack_tftp.h @@ -2,8 +2,6 @@ #ifndef _NF_CONNTRACK_TFTP_H #define _NF_CONNTRACK_TFTP_H -#define TFTP_PORT 69 - #include #include #include diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 49297fec448a..ed2e9bc1bb4e 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -2123,7 +2123,7 @@ void ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin); int ip_vs_confirm_conntrack(struct sk_buff *skb); void ip_vs_nfct_expect_related(struct sk_buff *skb, struct nf_conn *ct, - struct ip_vs_conn *cp, u_int8_t proto, + struct ip_vs_conn *cp, u8 proto, const __be16 port, int from_rs); void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp); diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index c761cd8158b2..bc5427d239f4 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -43,11 +43,10 @@ struct nf_conntrack_helper { refcount_t ct_refcnt; - /* Tuple of things we will help (compared against server response) */ - struct nf_conntrack_tuple tuple; + u8 nfproto; /* NFPROTO_*, can be NFPROTO_UNSPEC */ + u8 l4proto; /* IPPROTO_UDP/TCP */ - /* Function to call when data passes; return verdict, or -1 to - invalidate. */ + /* Function to call when data passes; return verdict */ int __rcu (*help)(struct sk_buff *skb, unsigned int protoff, struct nf_conn *ct, enum ip_conntrack_info conntrackinfo); @@ -94,8 +93,7 @@ struct nf_conntrack_helper *nf_conntrack_helper_try_module_get(const char *name, void nf_conntrack_helper_put(struct nf_conntrack_helper *helper); void nf_ct_helper_init(struct nf_conntrack_helper *helper, - u16 l3num, u16 protonum, const char *name, - u16 default_port, u16 spec_port, u32 id, + u8 l3num, u16 protonum, const char *name, const struct nf_conntrack_expect_policy *exp_pol, u32 expect_class_max, int (*help)(struct sk_buff *skb, unsigned int protoff, diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index f20c039e44c8..042d31278713 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -39,6 +39,8 @@ #define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter))) #define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \ COUNTER_OFFSET(n) * cpu)) +#define MAX_EBT_ENTRIES (((INT_MAX - sizeof(struct ebt_table_info)) / \ + NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter)) struct ebt_pernet { struct list_head tables; @@ -1124,10 +1126,9 @@ static int do_replace(struct net *net, sockptr_t arg, unsigned int len) return -EINVAL; /* overflow check */ - if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / - NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter)) + if (tmp.nentries >= MAX_EBT_ENTRIES) return -ENOMEM; - if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter)) + if (tmp.num_counters >= MAX_EBT_ENTRIES) return -ENOMEM; tmp.name[sizeof(tmp.name) - 1] = 0; @@ -2265,10 +2266,9 @@ static int compat_copy_ebt_replace_from_user(struct ebt_replace *repl, if (tmp.entries_size == 0) return -EINVAL; - if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / - NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter)) + if (tmp.nentries >= MAX_EBT_ENTRIES) return -ENOMEM; - if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter)) + if (tmp.num_counters >= MAX_EBT_ENTRIES) return -ENOMEM; memcpy(repl, &tmp, offsetof(struct ebt_replace, hook_entry)); diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic_main.c b/net/ipv4/netfilter/nf_nat_snmp_basic_main.c index 0ede138dfd29..e540b86bd15b 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic_main.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic_main.c @@ -213,7 +213,7 @@ static int __init nf_nat_snmp_basic_init(void) RCU_INIT_POINTER(nf_nat_snmp_hook, help); nf_ct_helper_init(&snmp_trap_helper, AF_INET, IPPROTO_UDP, - "snmp_trap", SNMP_TRAP_PORT, SNMP_TRAP_PORT, SNMP_TRAP_PORT, + "snmp_trap", &snmp_exp_policy, 0, help, NULL, THIS_MODULE); err = nf_conntrack_helper_register(&snmp_trap_helper, &snmp_trap_helper_ptr); diff --git a/net/netfilter/ipvs/ip_vs_nfct.c b/net/netfilter/ipvs/ip_vs_nfct.c index 81974f69e5bb..347185fd0c8c 100644 --- a/net/netfilter/ipvs/ip_vs_nfct.c +++ b/net/netfilter/ipvs/ip_vs_nfct.c @@ -208,7 +208,7 @@ static void ip_vs_nfct_expect_callback(struct nf_conn *ct, * Use port 0 to expect connection from any port. */ void ip_vs_nfct_expect_related(struct sk_buff *skb, struct nf_conn *ct, - struct ip_vs_conn *cp, u_int8_t proto, + struct ip_vs_conn *cp, u8 proto, const __be16 port, int from_rs) { struct nf_conntrack_expect *exp; diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c index ddafbdfc96dc..06d6ec12c86d 100644 --- a/net/netfilter/nf_conntrack_amanda.c +++ b/net/netfilter/nf_conntrack_amanda.c @@ -89,7 +89,7 @@ static int amanda_help(struct sk_buff *skb, struct nf_conntrack_tuple *tuple; unsigned int dataoff, start, stop, off, i; char pbuf[sizeof("65535")], *tmp; - u_int16_t len; + u16 len; __be16 port; int ret = NF_ACCEPT; nf_nat_amanda_hook_fn *nf_nat_amanda; @@ -199,10 +199,10 @@ static int __init nf_conntrack_amanda_init(void) } nf_ct_helper_init(&amanda_helper[0], AF_INET, IPPROTO_UDP, - HELPER_NAME, 10080, 10080, 10080, + HELPER_NAME, &amanda_exp_policy, 0, amanda_help, NULL, THIS_MODULE); nf_ct_helper_init(&amanda_helper[1], AF_INET6, IPPROTO_UDP, - HELPER_NAME, 10080, 10080, 10080, + HELPER_NAME, &amanda_exp_policy, 0, amanda_help, NULL, THIS_MODULE); ret = nf_conntrack_helpers_register(amanda_helper, diff --git a/net/netfilter/nf_conntrack_broadcast.c b/net/netfilter/nf_conntrack_broadcast.c index bf78828c7549..6ff954f1bfb8 100644 --- a/net/netfilter/nf_conntrack_broadcast.c +++ b/net/netfilter/nf_conntrack_broadcast.c @@ -66,8 +66,6 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb, exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; helper = rcu_dereference(help->helper); - if (helper) - exp->tuple.src.u.udp.port = helper->tuple.src.u.udp.port; exp->mask.src.u3.ip = mask; exp->mask.src.u.udp.port = htons(0xFFFF); diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 0847f845613d..f3944598c172 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -35,11 +35,6 @@ MODULE_ALIAS("ip_conntrack_ftp"); MODULE_ALIAS_NFCT_HELPER(HELPER_NAME); static DEFINE_SPINLOCK(nf_ftp_lock); -#define MAX_PORTS 8 -static u_int16_t ports[MAX_PORTS]; -static unsigned int ports_c; -module_param_array(ports, ushort, &ports_c, 0400); - static bool loose; module_param(loose, bool, 0600); @@ -560,8 +555,8 @@ static int nf_ct_ftp_from_nlattr(struct nlattr *attr, struct nf_conn *ct) return 0; } -static struct nf_conntrack_helper ftp[MAX_PORTS * 2] __read_mostly; -static struct nf_conntrack_helper *ftp_ptr[MAX_PORTS * 2] __read_mostly; +static struct nf_conntrack_helper ftp __read_mostly; +static struct nf_conntrack_helper *ftp_ptr __read_mostly; static const struct nf_conntrack_expect_policy ftp_exp_policy = { .max_expected = 1, @@ -570,32 +565,23 @@ static const struct nf_conntrack_expect_policy ftp_exp_policy = { static void __exit nf_conntrack_ftp_fini(void) { - nf_conntrack_helpers_unregister(ftp_ptr, ports_c * 2); + nf_conntrack_helper_unregister(ftp_ptr); } static int __init nf_conntrack_ftp_init(void) { - int i, ret = 0; + int ret = 0; NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_ftp_master)); - if (ports_c == 0) - ports[ports_c++] = FTP_PORT; - /* FIXME should be configurable whether IPv4 and IPv6 FTP connections are tracked or not - YK */ - for (i = 0; i < ports_c; i++) { - nf_ct_helper_init(&ftp[2 * i], AF_INET, IPPROTO_TCP, - HELPER_NAME, FTP_PORT, ports[i], ports[i], - &ftp_exp_policy, 0, help, - nf_ct_ftp_from_nlattr, THIS_MODULE); - nf_ct_helper_init(&ftp[2 * i + 1], AF_INET6, IPPROTO_TCP, - HELPER_NAME, FTP_PORT, ports[i], ports[i], - &ftp_exp_policy, 0, help, - nf_ct_ftp_from_nlattr, THIS_MODULE); - } + nf_ct_helper_init(&ftp, NFPROTO_UNSPEC, IPPROTO_TCP, + HELPER_NAME, + &ftp_exp_policy, 0, help, + nf_ct_ftp_from_nlattr, THIS_MODULE); - ret = nf_conntrack_helpers_register(ftp, ports_c * 2, ftp_ptr); + ret = nf_conntrack_helper_register(&ftp, &ftp_ptr); if (ret < 0) { pr_err("failed to register helpers\n"); return ret; diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 24931e379985..4cb1665bba02 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -671,7 +671,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct, static int callforward_do_filter(struct net *net, const union nf_inet_addr *src, const union nf_inet_addr *dst, - u_int8_t family) + u8 family) { int ret = 0; @@ -1713,19 +1713,19 @@ static int __init h323_helper_init(void) int ret; nf_ct_helper_init(&nf_conntrack_helper_ras[0], AF_INET, IPPROTO_UDP, - "RAS", RAS_PORT, RAS_PORT, RAS_PORT, + "RAS", &ras_exp_policy, 0, ras_help, NULL, THIS_MODULE); nf_ct_helper_init(&nf_conntrack_helper_ras[1], AF_INET6, IPPROTO_UDP, - "RAS", RAS_PORT, RAS_PORT, RAS_PORT, + "RAS", &ras_exp_policy, 0, ras_help, NULL, THIS_MODULE); nf_ct_helper_init(&nf_conntrack_helper_h245, AF_UNSPEC, IPPROTO_UDP, - "H.245", 0, 0, 0, + "H.245", &h245_exp_policy, 0, h245_help, NULL, THIS_MODULE); nf_ct_helper_init(&nf_conntrack_helper_q931[0], AF_INET, IPPROTO_TCP, - "Q.931", Q931_PORT, Q931_PORT, Q931_PORT, + "Q.931", &q931_exp_policy, 0, q931_help, NULL, THIS_MODULE); nf_ct_helper_init(&nf_conntrack_helper_q931[1], AF_INET6, IPPROTO_TCP, - "Q.931", Q931_PORT, Q931_PORT, Q931_PORT, + "Q.931", &q931_exp_policy, 0, q931_help, NULL, THIS_MODULE); ret = nf_conntrack_helper_register(&nf_conntrack_helper_h245, diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 500509b17663..506c58034761 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -40,12 +40,16 @@ static unsigned int nf_ct_helper_count __read_mostly; static DEFINE_MUTEX(nf_ct_nat_helpers_mutex); static struct list_head nf_ct_nat_helpers __read_mostly; -/* Stupid hash, but collision free for the default registrations of the - * helpers currently in the kernel. */ -static unsigned int helper_hash(const struct nf_conntrack_tuple *tuple) +static unsigned int helper_hash(const char *name, u8 protonum) { - return (((tuple->src.l3num << 8) | tuple->dst.protonum) ^ - (__force __u16)tuple->src.u.all) % nf_ct_helper_hsize; + static u32 seed; + u32 initval; + + get_random_once(&seed, sizeof(seed)); + + initval = seed ^ protonum; + + return jhash(name, strlen(name), initval) % nf_ct_helper_hsize; } struct nf_conntrack_helper * @@ -54,18 +58,18 @@ __nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum) struct nf_conntrack_helper *h; unsigned int i; - for (i = 0; i < nf_ct_helper_hsize; i++) { - hlist_for_each_entry_rcu(h, &nf_ct_helper_hash[i], hnode) { - if (strcmp(h->name, name)) - continue; + if (!nf_ct_helper_hash) + return NULL; - if (h->tuple.src.l3num != NFPROTO_UNSPEC && - h->tuple.src.l3num != l3num) - continue; + i = helper_hash(name, protonum); - if (h->tuple.dst.protonum == protonum) - return h; - } + hlist_for_each_entry_rcu(h, &nf_ct_helper_hash[i], hnode) { + if (strcmp(h->name, name)) + continue; + if (h->nfproto != NFPROTO_UNSPEC && h->nfproto != l3num) + continue; + if (h->l4proto == protonum) + return h; } return NULL; } @@ -363,9 +367,8 @@ EXPORT_SYMBOL_GPL(nf_ct_helper_log); int __nf_conntrack_helper_register(struct nf_conntrack_helper *me) { - struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) }; - unsigned int h = helper_hash(&me->tuple); struct nf_conntrack_helper *cur; + unsigned int h; int ret = 0, i; BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES); @@ -382,29 +385,18 @@ int __nf_conntrack_helper_register(struct nf_conntrack_helper *me) return -EINVAL; } + h = helper_hash(me->name, me->l4proto); mutex_lock(&nf_ct_helper_mutex); - for (i = 0; i < nf_ct_helper_hsize; i++) { - hlist_for_each_entry(cur, &nf_ct_helper_hash[i], hnode) { - if (!strcmp(cur->name, me->name) && - (cur->tuple.src.l3num == NFPROTO_UNSPEC || - cur->tuple.src.l3num == me->tuple.src.l3num) && - cur->tuple.dst.protonum == me->tuple.dst.protonum) { - ret = -EBUSY; - goto out; - } + hlist_for_each_entry(cur, &nf_ct_helper_hash[h], hnode) { + if (!strcmp(cur->name, me->name) && + (cur->nfproto == NFPROTO_UNSPEC || + cur->nfproto == me->nfproto) && + cur->l4proto == me->l4proto) { + ret = -EBUSY; + goto out; } } - /* avoid unpredictable behaviour for auto_assign_helper */ - if (!(me->flags & NF_CT_HELPER_F_USERSPACE)) { - hlist_for_each_entry(cur, &nf_ct_helper_hash[h], hnode) { - if (nf_ct_tuple_src_mask_cmp(&cur->tuple, &me->tuple, - &mask)) { - ret = -EBUSY; - goto out; - } - } - } refcount_set(&me->ct_refcnt, 1); hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]); nf_ct_helper_count++; @@ -479,8 +471,7 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); void nf_ct_helper_init(struct nf_conntrack_helper *helper, - u16 l3num, u16 protonum, const char *name, - u16 default_port, u16 spec_port, u32 id, + u8 l3num, u16 protonum, const char *name, const struct nf_conntrack_expect_policy *exp_pol, u32 expect_class_max, int (*help)(struct sk_buff *skb, unsigned int protoff, @@ -492,9 +483,8 @@ void nf_ct_helper_init(struct nf_conntrack_helper *helper, { memset(helper, 0, sizeof(*helper)); - helper->tuple.src.l3num = l3num; - helper->tuple.dst.protonum = protonum; - helper->tuple.src.u.all = htons(spec_port); + helper->nfproto = l3num; + helper->l4proto = protonum; rcu_assign_pointer(helper->help, help); helper->from_nlattr = from_nlattr; @@ -502,10 +492,7 @@ void nf_ct_helper_init(struct nf_conntrack_helper *helper, snprintf(helper->nat_mod_name, sizeof(helper->nat_mod_name), NF_NAT_HELPER_PREFIX "%s", name); - if (spec_port == default_port) - snprintf(helper->name, sizeof(helper->name), "%s", name); - else - snprintf(helper->name, sizeof(helper->name), "%s-%u", name, id); + snprintf(helper->name, sizeof(helper->name), "%s", name); if (WARN_ON_ONCE(expect_class_max >= NF_CT_MAX_EXPECT_CLASSES)) return; diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index 193ab34db795..4e6bafe41437 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c @@ -21,9 +21,6 @@ #include #include -#define MAX_PORTS 8 -static unsigned short ports[MAX_PORTS]; -static unsigned int ports_c; static unsigned int max_dcc_channels = 8; static unsigned int dcc_timeout __read_mostly = 300; /* This is slow, but it's simple. --RR */ @@ -42,8 +39,6 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("ip_conntrack_irc"); MODULE_ALIAS_NFCT_HELPER(HELPER_NAME); -module_param_array(ports, ushort, &ports_c, 0400); -MODULE_PARM_DESC(ports, "port numbers of IRC servers"); module_param(max_dcc_channels, uint, 0400); MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per " "IRC session"); @@ -254,13 +249,13 @@ static int help(struct sk_buff *skb, unsigned int protoff, return ret; } -static struct nf_conntrack_helper irc[MAX_PORTS] __read_mostly; -static struct nf_conntrack_helper *irc_ptr[MAX_PORTS] __read_mostly; +static struct nf_conntrack_helper irc __read_mostly; +static struct nf_conntrack_helper *irc_ptr __read_mostly; static struct nf_conntrack_expect_policy irc_exp_policy; static int __init nf_conntrack_irc_init(void) { - int i, ret; + int ret; nf_conntrack_helper_deprecated(HELPER_NAME); @@ -282,17 +277,11 @@ static int __init nf_conntrack_irc_init(void) if (!irc_buffer) return -ENOMEM; - /* If no port given, default to standard irc port */ - if (ports_c == 0) - ports[ports_c++] = IRC_PORT; + nf_ct_helper_init(&irc, AF_INET, IPPROTO_TCP, HELPER_NAME, + &irc_exp_policy, + 0, help, NULL, THIS_MODULE); - for (i = 0; i < ports_c; i++) { - nf_ct_helper_init(&irc[i], AF_INET, IPPROTO_TCP, HELPER_NAME, - IRC_PORT, ports[i], i, &irc_exp_policy, - 0, help, NULL, THIS_MODULE); - } - - ret = nf_conntrack_helpers_register(&irc[0], ports_c, irc_ptr); + ret = nf_conntrack_helper_register(&irc, &irc_ptr); if (ret) { pr_err("failed to register helpers\n"); kfree(irc_buffer); @@ -304,7 +293,7 @@ static int __init nf_conntrack_irc_init(void) static void __exit nf_conntrack_irc_fini(void) { - nf_conntrack_helpers_unregister(irc_ptr, ports_c); + nf_conntrack_helper_unregister(irc_ptr); kfree(irc_buffer); } diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c index 89d1cf7d6512..caa2b101fa9e 100644 --- a/net/netfilter/nf_conntrack_netbios_ns.c +++ b/net/netfilter/nf_conntrack_netbios_ns.c @@ -21,7 +21,6 @@ #include #define HELPER_NAME "netbios-ns" -#define NMBD_PORT 137 MODULE_AUTHOR("Patrick McHardy "); MODULE_DESCRIPTION("NetBIOS name service broadcast connection tracking helper"); @@ -54,7 +53,6 @@ static int __init nf_conntrack_netbios_ns_init(void) exp_policy.timeout = timeout; nf_ct_helper_init(&helper, AF_INET, IPPROTO_UDP, HELPER_NAME, - NMBD_PORT, NMBD_PORT, NMBD_PORT, &exp_policy, 0, netbios_ns_help, NULL, THIS_MODULE); return nf_conntrack_helper_register(&helper, &helper_ptr); diff --git a/net/netfilter/nf_conntrack_ovs.c b/net/netfilter/nf_conntrack_ovs.c index 49d1511e9921..b4085af3ad1c 100644 --- a/net/netfilter/nf_conntrack_ovs.c +++ b/net/netfilter/nf_conntrack_ovs.c @@ -31,8 +31,8 @@ int nf_ct_helper(struct sk_buff *skb, struct nf_conn *ct, if (!helper) return NF_ACCEPT; - if (helper->tuple.src.l3num != NFPROTO_UNSPEC && - helper->tuple.src.l3num != proto) + if (helper->nfproto != NFPROTO_UNSPEC && + helper->nfproto != proto) return NF_ACCEPT; switch (proto) { @@ -60,7 +60,7 @@ int nf_ct_helper(struct sk_buff *skb, struct nf_conn *ct, return NF_DROP; } - if (helper->tuple.dst.protonum != proto) + if (helper->l4proto != proto) return NF_ACCEPT; helper_cb = rcu_dereference(helper->help); diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 80fc14c87ddc..cbf32a3cb1f6 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c @@ -540,7 +540,7 @@ static int __init nf_conntrack_pptp_init(void) NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_pptp_master)); nf_ct_helper_init(&pptp, AF_INET, IPPROTO_TCP, - "pptp", PPTP_CONTROL_PORT, PPTP_CONTROL_PORT, PPTP_CONTROL_PORT, + "pptp", &pptp_exp_policy, 0, conntrack_pptp_help, NULL, THIS_MODULE); pptp.destroy = gre_pptp_destroy_siblings; diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c index 39085acf7a71..a0658f69d78f 100644 --- a/net/netfilter/nf_conntrack_sane.c +++ b/net/netfilter/nf_conntrack_sane.c @@ -34,11 +34,6 @@ MODULE_AUTHOR("Michal Schmidt "); MODULE_DESCRIPTION("SANE connection tracking helper"); MODULE_ALIAS_NFCT_HELPER(HELPER_NAME); -#define MAX_PORTS 8 -static u_int16_t ports[MAX_PORTS]; -static unsigned int ports_c; -module_param_array(ports, ushort, &ports_c, 0400); - struct sane_request { __be32 RPC_code; #define SANE_NET_START 7 /* RPC code */ @@ -169,8 +164,8 @@ static int help(struct sk_buff *skb, return ret; } -static struct nf_conntrack_helper sane[MAX_PORTS * 2] __read_mostly; -static struct nf_conntrack_helper *sane_ptr[MAX_PORTS * 2] __read_mostly; +static struct nf_conntrack_helper sane __read_mostly; +static struct nf_conntrack_helper *sane_ptr __read_mostly; static const struct nf_conntrack_expect_policy sane_exp_policy = { .max_expected = 1, @@ -179,32 +174,21 @@ static const struct nf_conntrack_expect_policy sane_exp_policy = { static void __exit nf_conntrack_sane_fini(void) { - nf_conntrack_helpers_unregister(sane_ptr, ports_c * 2); + nf_conntrack_helper_unregister(sane_ptr); } static int __init nf_conntrack_sane_init(void) { - int i, ret = 0; + int ret = 0; NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_sane_master)); - if (ports_c == 0) - ports[ports_c++] = SANE_PORT; + nf_ct_helper_init(&sane, NFPROTO_UNSPEC, IPPROTO_TCP, + HELPER_NAME, + &sane_exp_policy, 0, help, NULL, + THIS_MODULE); - /* FIXME should be configurable whether IPv4 and IPv6 connections - are tracked or not - YK */ - for (i = 0; i < ports_c; i++) { - nf_ct_helper_init(&sane[2 * i], AF_INET, IPPROTO_TCP, - HELPER_NAME, SANE_PORT, ports[i], ports[i], - &sane_exp_policy, 0, help, NULL, - THIS_MODULE); - nf_ct_helper_init(&sane[2 * i + 1], AF_INET6, IPPROTO_TCP, - HELPER_NAME, SANE_PORT, ports[i], ports[i], - &sane_exp_policy, 0, help, NULL, - THIS_MODULE); - } - - ret = nf_conntrack_helpers_register(sane, ports_c * 2, sane_ptr); + ret = nf_conntrack_helper_register(&sane, &sane_ptr); if (ret < 0) { pr_err("failed to register helpers\n"); return ret; diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index f3f90a866338..0ff089e03891 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -35,12 +35,6 @@ MODULE_DESCRIPTION("SIP connection tracking helper"); MODULE_ALIAS("ip_conntrack_sip"); MODULE_ALIAS_NFCT_HELPER(HELPER_NAME); -#define MAX_PORTS 8 -static unsigned short ports[MAX_PORTS]; -static unsigned int ports_c; -module_param_array(ports, ushort, &ports_c, 0400); -MODULE_PARM_DESC(ports, "port numbers of SIP servers"); - static unsigned int sip_timeout __read_mostly = SIP_TIMEOUT; module_param(sip_timeout, uint, 0600); MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session"); @@ -1767,8 +1761,8 @@ static int sip_help_udp(struct sk_buff *skb, unsigned int protoff, return process_sip_msg(skb, ct, protoff, dataoff, &dptr, &datalen); } -static struct nf_conntrack_helper sip[MAX_PORTS * 4] __read_mostly; -static struct nf_conntrack_helper *sip_ptr[MAX_PORTS * 4] __read_mostly; +static struct nf_conntrack_helper sip[2] __read_mostly; +static struct nf_conntrack_helper *sip_ptr[2] __read_mostly; static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = { [SIP_EXPECT_SIGNALLING] = { @@ -1795,38 +1789,25 @@ static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1 static void __exit nf_conntrack_sip_fini(void) { - nf_conntrack_helpers_unregister(sip_ptr, ports_c * 4); + nf_conntrack_helpers_unregister(sip_ptr, 2); } static int __init nf_conntrack_sip_init(void) { - int i, ret; + int ret; NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_sip_master)); - if (ports_c == 0) - ports[ports_c++] = SIP_PORT; + nf_ct_helper_init(&sip[0], NFPROTO_UNSPEC, IPPROTO_UDP, + HELPER_NAME, + sip_exp_policy, SIP_EXPECT_MAX, sip_help_udp, + NULL, THIS_MODULE); + nf_ct_helper_init(&sip[1], NFPROTO_UNSPEC, IPPROTO_TCP, + HELPER_NAME, + sip_exp_policy, SIP_EXPECT_MAX, sip_help_tcp, + NULL, THIS_MODULE); - for (i = 0; i < ports_c; i++) { - nf_ct_helper_init(&sip[4 * i], AF_INET, IPPROTO_UDP, - HELPER_NAME, SIP_PORT, ports[i], i, - sip_exp_policy, SIP_EXPECT_MAX, sip_help_udp, - NULL, THIS_MODULE); - nf_ct_helper_init(&sip[4 * i + 1], AF_INET, IPPROTO_TCP, - HELPER_NAME, SIP_PORT, ports[i], i, - sip_exp_policy, SIP_EXPECT_MAX, sip_help_tcp, - NULL, THIS_MODULE); - nf_ct_helper_init(&sip[4 * i + 2], AF_INET6, IPPROTO_UDP, - HELPER_NAME, SIP_PORT, ports[i], i, - sip_exp_policy, SIP_EXPECT_MAX, sip_help_udp, - NULL, THIS_MODULE); - nf_ct_helper_init(&sip[4 * i + 3], AF_INET6, IPPROTO_TCP, - HELPER_NAME, SIP_PORT, ports[i], i, - sip_exp_policy, SIP_EXPECT_MAX, sip_help_tcp, - NULL, THIS_MODULE); - } - - ret = nf_conntrack_helpers_register(sip, ports_c * 4, sip_ptr); + ret = nf_conntrack_helpers_register(sip, 2, sip_ptr); if (ret < 0) { pr_err("failed to register helpers\n"); return ret; diff --git a/net/netfilter/nf_conntrack_snmp.c b/net/netfilter/nf_conntrack_snmp.c index b6fce5703fce..109986d5d55e 100644 --- a/net/netfilter/nf_conntrack_snmp.c +++ b/net/netfilter/nf_conntrack_snmp.c @@ -14,8 +14,6 @@ #include #include -#define SNMP_PORT 161 - MODULE_AUTHOR("Jiri Olsa "); MODULE_DESCRIPTION("SNMP service broadcast connection tracking helper"); MODULE_LICENSE("GPL"); @@ -55,7 +53,7 @@ static int __init nf_conntrack_snmp_init(void) exp_policy.timeout = timeout; nf_ct_helper_init(&helper, AF_INET, IPPROTO_UDP, - "snmp", SNMP_PORT, SNMP_PORT, SNMP_PORT, + "snmp", &exp_policy, 0, snmp_conntrack_help, NULL, THIS_MODULE); diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c index 4393c435aa35..a69559edf9b3 100644 --- a/net/netfilter/nf_conntrack_tftp.c +++ b/net/netfilter/nf_conntrack_tftp.c @@ -26,12 +26,6 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("ip_conntrack_tftp"); MODULE_ALIAS_NFCT_HELPER(HELPER_NAME); -#define MAX_PORTS 8 -static unsigned short ports[MAX_PORTS]; -static unsigned int ports_c; -module_param_array(ports, ushort, &ports_c, 0400); -MODULE_PARM_DESC(ports, "Port numbers of TFTP servers"); - nf_nat_tftp_hook_fn __rcu *nf_nat_tftp_hook __read_mostly; EXPORT_SYMBOL_GPL(nf_nat_tftp_hook); @@ -95,8 +89,8 @@ static int tftp_help(struct sk_buff *skb, return ret; } -static struct nf_conntrack_helper tftp[MAX_PORTS * 2] __read_mostly; -static struct nf_conntrack_helper *tftp_ptr[MAX_PORTS * 2] __read_mostly; +static struct nf_conntrack_helper tftp __read_mostly; +static struct nf_conntrack_helper *tftp_ptr __read_mostly; static const struct nf_conntrack_expect_policy tftp_exp_policy = { .max_expected = 1, @@ -105,30 +99,21 @@ static const struct nf_conntrack_expect_policy tftp_exp_policy = { static void __exit nf_conntrack_tftp_fini(void) { - nf_conntrack_helpers_unregister(tftp_ptr, ports_c * 2); + nf_conntrack_helper_unregister(tftp_ptr); } static int __init nf_conntrack_tftp_init(void) { - int i, ret; + int ret; NF_CT_HELPER_BUILD_BUG_ON(0); - if (ports_c == 0) - ports[ports_c++] = TFTP_PORT; + nf_ct_helper_init(&tftp, NFPROTO_UNSPEC, IPPROTO_UDP, + HELPER_NAME, + &tftp_exp_policy, 0, tftp_help, NULL, + THIS_MODULE); - for (i = 0; i < ports_c; i++) { - nf_ct_helper_init(&tftp[2 * i], AF_INET, IPPROTO_UDP, - HELPER_NAME, TFTP_PORT, ports[i], i, - &tftp_exp_policy, 0, tftp_help, NULL, - THIS_MODULE); - nf_ct_helper_init(&tftp[2 * i + 1], AF_INET6, IPPROTO_UDP, - HELPER_NAME, TFTP_PORT, ports[i], i, - &tftp_exp_policy, 0, tftp_help, NULL, - THIS_MODULE); - } - - ret = nf_conntrack_helpers_register(tftp, ports_c * 2, tftp_ptr); + ret = nf_conntrack_helper_register(&tftp, &tftp_ptr); if (ret < 0) { pr_err("failed to register helpers\n"); return ret; diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index 63ff6b4d5d21..8ac326e1eb5b 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c @@ -39,12 +39,6 @@ static struct hlist_head *nf_nat_bysource __read_mostly; static unsigned int nf_nat_htable_size __read_mostly; static siphash_aligned_key_t nf_nat_hash_rnd; -struct nf_nat_lookup_hook_priv { - struct nf_hook_entries __rcu *entries; - - struct rcu_head rcu_head; -}; - struct nf_nat_hooks_net { struct nf_hook_ops *nat_hook_ops; unsigned int users; diff --git a/net/netfilter/nf_nat_proto.c b/net/netfilter/nf_nat_proto.c index 07f51fe75fbe..64b9bac228ea 100644 --- a/net/netfilter/nf_nat_proto.c +++ b/net/netfilter/nf_nat_proto.c @@ -770,6 +770,7 @@ static const struct nf_hook_ops nf_nat_ipv4_ops[] = { .pf = NFPROTO_IPV4, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_NAT_DST, + .hook_ops_type = NF_HOOK_OP_NAT, }, /* After packet filtering, change source */ { @@ -777,6 +778,7 @@ static const struct nf_hook_ops nf_nat_ipv4_ops[] = { .pf = NFPROTO_IPV4, .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_NAT_SRC, + .hook_ops_type = NF_HOOK_OP_NAT, }, /* Before packet filtering, change destination */ { @@ -784,6 +786,7 @@ static const struct nf_hook_ops nf_nat_ipv4_ops[] = { .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_NAT_DST, + .hook_ops_type = NF_HOOK_OP_NAT, }, /* After packet filtering, change source */ { @@ -791,6 +794,7 @@ static const struct nf_hook_ops nf_nat_ipv4_ops[] = { .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_NAT_SRC, + .hook_ops_type = NF_HOOK_OP_NAT, }, }; @@ -1031,6 +1035,7 @@ static const struct nf_hook_ops nf_nat_ipv6_ops[] = { .pf = NFPROTO_IPV6, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP6_PRI_NAT_DST, + .hook_ops_type = NF_HOOK_OP_NAT, }, /* After packet filtering, change source */ { @@ -1038,6 +1043,7 @@ static const struct nf_hook_ops nf_nat_ipv6_ops[] = { .pf = NFPROTO_IPV6, .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP6_PRI_NAT_SRC, + .hook_ops_type = NF_HOOK_OP_NAT, }, /* Before packet filtering, change destination */ { @@ -1045,6 +1051,7 @@ static const struct nf_hook_ops nf_nat_ipv6_ops[] = { .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP6_PRI_NAT_DST, + .hook_ops_type = NF_HOOK_OP_NAT, }, /* After packet filtering, change source */ { @@ -1052,6 +1059,7 @@ static const struct nf_hook_ops nf_nat_ipv6_ops[] = { .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP6_PRI_NAT_SRC, + .hook_ops_type = NF_HOOK_OP_NAT, }, }; diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c index 2cbcca9110db..82f3cfd25e3c 100644 --- a/net/netfilter/nfnetlink_cthelper.c +++ b/net/netfilter/nfnetlink_cthelper.c @@ -67,7 +67,7 @@ nfnl_userspace_cthelper(struct sk_buff *skb, unsigned int protoff, } static const struct nla_policy nfnl_cthelper_tuple_pol[NFCTH_TUPLE_MAX+1] = { - [NFCTH_TUPLE_L3PROTONUM] = { .type = NLA_U16, }, + [NFCTH_TUPLE_L3PROTONUM] = NLA_POLICY_MAX(NLA_BE16, NFPROTO_IPV6), [NFCTH_TUPLE_L4PROTONUM] = { .type = NLA_U8, }, }; @@ -256,7 +256,8 @@ nfnl_cthelper_create(const struct nlattr * const tb[], helper->data_len = size; helper->flags |= NF_CT_HELPER_F_USERSPACE; - memcpy(&helper->tuple, tuple, sizeof(struct nf_conntrack_tuple)); + helper->nfproto = tuple->src.l3num; + helper->l4proto = tuple->dst.protonum; helper->me = THIS_MODULE; helper->help = nfnl_userspace_cthelper; @@ -451,8 +452,8 @@ static int nfnl_cthelper_new(struct sk_buff *skb, const struct nfnl_info *info, if (strncmp(cur->name, helper_name, NF_CT_HELPER_NAME_LEN)) continue; - if ((tuple.src.l3num != cur->tuple.src.l3num || - tuple.dst.protonum != cur->tuple.dst.protonum)) + if ((tuple.src.l3num != cur->nfproto || + tuple.dst.protonum != cur->l4proto)) continue; if (info->nlh->nlmsg_flags & NLM_F_EXCL) @@ -481,10 +482,10 @@ nfnl_cthelper_dump_tuple(struct sk_buff *skb, goto nla_put_failure; if (nla_put_be16(skb, NFCTH_TUPLE_L3PROTONUM, - htons(helper->tuple.src.l3num))) + htons(helper->nfproto))) goto nla_put_failure; - if (nla_put_u8(skb, NFCTH_TUPLE_L4PROTONUM, helper->tuple.dst.protonum)) + if (nla_put_u8(skb, NFCTH_TUPLE_L4PROTONUM, helper->l4proto)) goto nla_put_failure; nla_nest_end(skb, nest_parms); @@ -663,8 +664,8 @@ static int nfnl_cthelper_get(struct sk_buff *skb, const struct nfnl_info *info, continue; if (tuple_set && - (tuple.src.l3num != cur->tuple.src.l3num || - tuple.dst.protonum != cur->tuple.dst.protonum)) + (tuple.src.l3num != cur->nfproto || + tuple.dst.protonum != cur->l4proto)) continue; skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); @@ -723,8 +724,8 @@ static int nfnl_cthelper_del(struct sk_buff *skb, const struct nfnl_info *info, continue; if (tuple_set && - (tuple.src.l3num != cur->tuple.src.l3num || - tuple.dst.protonum != cur->tuple.dst.protonum)) + (tuple.src.l3num != cur->nfproto || + tuple.dst.protonum != cur->l4proto)) continue; found = true; diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index 170d3db860c5..66c2016f6049 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c @@ -168,7 +168,7 @@ static int cttimeout_new_timeout(struct sk_buff *skb, if (ret < 0) goto err_free_timeout_policy; - strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME])); + nla_strscpy(timeout->name, cda[CTA_TIMEOUT_NAME], sizeof(timeout->name)); timeout->timeout->l3num = l3num; timeout->timeout->l4proto = l4proto; refcount_set(&timeout->timeout->refcnt, 1); diff --git a/net/netfilter/nfnetlink_hook.c b/net/netfilter/nfnetlink_hook.c index 5623c18fcd12..95005e9a6066 100644 --- a/net/netfilter/nfnetlink_hook.c +++ b/net/netfilter/nfnetlink_hook.c @@ -190,7 +190,7 @@ static int nfnl_hook_put_nft_ft_info(struct sk_buff *nlskb, static int nfnl_hook_dump_one(struct sk_buff *nlskb, const struct nfnl_dump_hook_data *ctx, - const struct nf_hook_ops *ops, + const struct nf_hook_ops *ops, int priority, int family, unsigned int seq) { u16 event = nfnl_msg_type(NFNL_SUBSYS_HOOK, NFNL_MSG_HOOK_GET); @@ -244,7 +244,7 @@ static int nfnl_hook_dump_one(struct sk_buff *nlskb, if (ret) goto nla_put_failure; - ret = nla_put_be32(nlskb, NFNLA_HOOK_PRIORITY, htonl(ops->priority)); + ret = nla_put_be32(nlskb, NFNLA_HOOK_PRIORITY, htonl(priority)); if (ret) goto nla_put_failure; @@ -337,6 +337,30 @@ nfnl_hook_entries_head(u8 pf, unsigned int hook, struct net *net, const char *de return hook_head; } +static int nfnl_hook_dump_nat(struct sk_buff *nlskb, + const struct nfnl_dump_hook_data *ctx, + const struct nf_hook_ops *ops, + int family, unsigned int seq) +{ + struct nf_nat_lookup_hook_priv *priv = ops->priv; + struct nf_hook_entries *e = rcu_dereference(priv->entries); + struct nf_hook_ops **nat_ops; + int i, err; + + if (!e) + return 0; + + nat_ops = nf_hook_entries_get_hook_ops(e); + + for (i = 0; i < e->num_hook_entries; i++) { + err = nfnl_hook_dump_one(nlskb, ctx, nat_ops[i], + ops->priority, family, seq); + if (err) + return err; + } + return 0; +} + static int nfnl_hook_dump(struct sk_buff *nlskb, struct netlink_callback *cb) { @@ -365,8 +389,13 @@ static int nfnl_hook_dump(struct sk_buff *nlskb, ops = nf_hook_entries_get_hook_ops(e); for (; i < e->num_hook_entries; i++) { - err = nfnl_hook_dump_one(nlskb, ctx, ops[i], family, - cb->nlh->nlmsg_seq); + if (ops[i]->hook_ops_type == NF_HOOK_OP_NAT) + err = nfnl_hook_dump_nat(nlskb, ctx, ops[i], family, + cb->nlh->nlmsg_seq); + else + err = nfnl_hook_dump_one(nlskb, ctx, ops[i], + ops[i]->priority, family, + cb->nlh->nlmsg_seq); if (err) break; } diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index 03a88c77e0f0..358b9287e12e 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c @@ -1297,6 +1297,17 @@ static int nft_ct_expect_obj_dump(struct sk_buff *skb, return 0; } +#if IS_ENABLED(CONFIG_NF_NAT) +static void nft_ct_nat_follow_master(struct nf_conn *ct, struct nf_conntrack_expect *this) +{ + const struct nf_ct_helper_expectfn *expfn; + + expfn = nf_ct_helper_expectfn_find_by_name("nat-follow-master"); + if (expfn) + expfn->expectfn(ct, this); +} +#endif + static void nft_ct_expect_obj_eval(struct nft_object *obj, struct nft_regs *regs, const struct nft_pktinfo *pkt) @@ -1342,6 +1353,13 @@ static void nft_ct_expect_obj_eval(struct nft_object *obj, priv->l4proto, NULL, &priv->dport); exp->timeout += priv->timeout; +#if IS_ENABLED(CONFIG_NF_NAT) + if (ct->status & IPS_NAT_MASK) { + exp->saved_proto.tcp.port = priv->dport; + exp->dir = !dir; + exp->expectfn = nft_ct_nat_follow_master; + } +#endif if (nf_ct_expect_related(exp, 0) != 0) regs->verdict.code = NF_DROP; @@ -1375,6 +1393,13 @@ static struct nft_object_type nft_ct_expect_obj_type __read_mostly = { .owner = THIS_MODULE, }; +#if IS_ENABLED(CONFIG_NF_NAT) +static struct nf_ct_helper_expectfn nft_ct_nat __read_mostly = { + .name = "nft_ct-follow-master", + .expectfn = nft_ct_nat_follow_master, +}; +#endif + static int __init nft_ct_module_init(void) { int err; @@ -1400,6 +1425,9 @@ static int __init nft_ct_module_init(void) err = nft_register_obj(&nft_ct_timeout_obj_type); if (err < 0) goto err4; +#endif +#if IS_ENABLED(CONFIG_NF_NAT) + nf_ct_helper_expectfn_register(&nft_ct_nat); #endif return 0; @@ -1425,6 +1453,13 @@ static void __exit nft_ct_module_exit(void) nft_unregister_obj(&nft_ct_helper_obj_type); nft_unregister_expr(&nft_notrack_type); nft_unregister_expr(&nft_ct_type); + +#if IS_ENABLED(CONFIG_NF_NAT) + nf_ct_helper_expectfn_unregister(&nft_ct_nat); + synchronize_rcu(); + nf_ct_helper_expectfn_destroy(&nft_ct_nat); + synchronize_rcu(); +#endif } module_init(nft_ct_module_init); diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c index 018bbb6df4ce..efc25e788a1c 100644 --- a/net/netfilter/nft_set_rbtree.c +++ b/net/netfilter/nft_set_rbtree.c @@ -544,8 +544,7 @@ static int nft_array_intervals_alloc(struct nft_array *array, u32 max_intervals) if (!intervals) return -ENOMEM; - if (array->intervals) - kvfree(array->intervals); + kvfree(array->intervals); array->intervals = intervals; array->max_intervals = max_intervals; diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 4e6708c23922..e64116bf2637 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -1920,9 +1920,9 @@ static const struct seq_operations xt_target_seq_ops = { .show = xt_target_seq_show, }; -#define FORMAT_TABLES "_tables_names" -#define FORMAT_MATCHES "_tables_matches" -#define FORMAT_TARGETS "_tables_targets" +#define FORMAT_TABLES "%s_tables_names" +#define FORMAT_MATCHES "%s_tables_matches" +#define FORMAT_TARGETS "%s_tables_targets" #endif /* CONFIG_PROC_FS */ @@ -2033,8 +2033,7 @@ int xt_proto_init(struct net *net, u_int8_t af) root_uid = make_kuid(net->user_ns, 0); root_gid = make_kgid(net->user_ns, 0); - strscpy(buf, xt_prefix[af], sizeof(buf)); - strlcat(buf, FORMAT_TABLES, sizeof(buf)); + snprintf(buf, sizeof(buf), FORMAT_TABLES, xt_prefix[af]); proc = proc_create_net_data(buf, 0440, net->proc_net, &xt_table_seq_ops, sizeof(struct seq_net_private), (void *)(unsigned long)af); @@ -2043,8 +2042,7 @@ int xt_proto_init(struct net *net, u_int8_t af) if (uid_valid(root_uid) && gid_valid(root_gid)) proc_set_user(proc, root_uid, root_gid); - strscpy(buf, xt_prefix[af], sizeof(buf)); - strlcat(buf, FORMAT_MATCHES, sizeof(buf)); + snprintf(buf, sizeof(buf), FORMAT_MATCHES, xt_prefix[af]); proc = proc_create_seq_private(buf, 0440, net->proc_net, &xt_match_seq_ops, sizeof(struct nf_mttg_trav), (void *)(unsigned long)af); @@ -2053,8 +2051,7 @@ int xt_proto_init(struct net *net, u_int8_t af) if (uid_valid(root_uid) && gid_valid(root_gid)) proc_set_user(proc, root_uid, root_gid); - strscpy(buf, xt_prefix[af], sizeof(buf)); - strlcat(buf, FORMAT_TARGETS, sizeof(buf)); + snprintf(buf, sizeof(buf), FORMAT_TARGETS, xt_prefix[af]); proc = proc_create_seq_private(buf, 0440, net->proc_net, &xt_target_seq_ops, sizeof(struct nf_mttg_trav), (void *)(unsigned long)af); @@ -2068,13 +2065,11 @@ int xt_proto_init(struct net *net, u_int8_t af) #ifdef CONFIG_PROC_FS out_remove_matches: - strscpy(buf, xt_prefix[af], sizeof(buf)); - strlcat(buf, FORMAT_MATCHES, sizeof(buf)); + snprintf(buf, sizeof(buf), FORMAT_MATCHES, xt_prefix[af]); remove_proc_entry(buf, net->proc_net); out_remove_tables: - strscpy(buf, xt_prefix[af], sizeof(buf)); - strlcat(buf, FORMAT_TABLES, sizeof(buf)); + snprintf(buf, sizeof(buf), FORMAT_TABLES, xt_prefix[af]); remove_proc_entry(buf, net->proc_net); out: return -1; @@ -2087,16 +2082,13 @@ void xt_proto_fini(struct net *net, u_int8_t af) #ifdef CONFIG_PROC_FS char buf[XT_FUNCTION_MAXNAMELEN]; - strscpy(buf, xt_prefix[af], sizeof(buf)); - strlcat(buf, FORMAT_TABLES, sizeof(buf)); + snprintf(buf, sizeof(buf), FORMAT_TABLES, xt_prefix[af]); remove_proc_entry(buf, net->proc_net); - strscpy(buf, xt_prefix[af], sizeof(buf)); - strlcat(buf, FORMAT_TARGETS, sizeof(buf)); + snprintf(buf, sizeof(buf), FORMAT_TARGETS, xt_prefix[af]); remove_proc_entry(buf, net->proc_net); - strscpy(buf, xt_prefix[af], sizeof(buf)); - strlcat(buf, FORMAT_MATCHES, sizeof(buf)); + snprintf(buf, sizeof(buf), FORMAT_MATCHES, xt_prefix[af]); remove_proc_entry(buf, net->proc_net); #endif /*CONFIG_PROC_FS*/ } diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c index 93f064306901..265d21697847 100644 --- a/net/netfilter/xt_TCPOPTSTRIP.c +++ b/net/netfilter/xt_TCPOPTSTRIP.c @@ -16,7 +16,7 @@ #include #include -static inline unsigned int optlen(const u_int8_t *opt, unsigned int offset) +static inline unsigned int optlen(const u8 *opt, unsigned int offset) { /* Beware zero-length options: make finite progress */ if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0) @@ -33,8 +33,8 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb, const struct xt_tcpoptstrip_target_info *info = par->targinfo; struct tcphdr *tcph, _th; unsigned int optl, i, j; - u_int16_t n, o; - u_int8_t *opt; + u16 n, o; + u8 *opt; int tcp_hdrlen; /* This is a fragment, no TCP header is available */ @@ -97,7 +97,7 @@ tcpoptstrip_tg6(struct sk_buff *skb, const struct xt_action_param *par) { struct ipv6hdr *ipv6h = ipv6_hdr(skb); int tcphoff; - u_int8_t nexthdr; + u8 nexthdr; __be16 frag_off; nexthdr = ipv6h->nexthdr; diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c index fb0169a8f9bb..878f27016e99 100644 --- a/net/netfilter/xt_dscp.c +++ b/net/netfilter/xt_dscp.c @@ -49,6 +49,16 @@ static int dscp_mt_check(const struct xt_mtchk_param *par) return 0; } +static int tos_mt_check(const struct xt_mtchk_param *par) +{ + const struct xt_tos_match_info *info = par->matchinfo; + + if (info->invert > 1) + return -EINVAL; + + return 0; +} + static bool tos_mt(const struct sk_buff *skb, struct xt_action_param *par) { const struct xt_tos_match_info *info = par->matchinfo; @@ -82,6 +92,7 @@ static struct xt_match dscp_mt_reg[] __read_mostly = { .name = "tos", .revision = 1, .family = NFPROTO_IPV4, + .checkentry = tos_mt_check, .match = tos_mt, .matchsize = sizeof(struct xt_tos_match_info), .me = THIS_MODULE, @@ -90,6 +101,7 @@ static struct xt_match dscp_mt_reg[] __read_mostly = { .name = "tos", .revision = 1, .family = NFPROTO_IPV6, + .checkentry = tos_mt_check, .match = tos_mt, .matchsize = sizeof(struct xt_tos_match_info), .me = THIS_MODULE, diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index f72752fa4374..d34831ce3adf 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -400,7 +400,7 @@ static int recent_mt_check(const struct xt_mtchk_param *par, t->nstamps_max_mask = nstamp_mask; memcpy(&t->mask, &info->mask, sizeof(t->mask)); - strcpy(t->name, info->name); + strscpy(t->name, info->name); INIT_LIST_HEAD(&t->lru_list); for (i = 0; i < ip_list_hash_size; i++) INIT_LIST_HEAD(&t->iphash[i]); diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c index b9da8269161d..b08b077d7f0a 100644 --- a/net/netfilter/xt_tcpmss.c +++ b/net/netfilter/xt_tcpmss.c @@ -78,10 +78,23 @@ tcpmss_mt(const struct sk_buff *skb, struct xt_action_param *par) return false; } +static int tcpmss_mt_check(const struct xt_mtchk_param *par) +{ + const struct xt_tcpmss_match_info *info = par->matchinfo; + + if (info->mss_min > info->mss_max) + return -EINVAL; + if (info->invert > 1) + return -EINVAL; + + return 0; +} + static struct xt_match tcpmss_mt_reg[] __read_mostly = { { .name = "tcpmss", .family = NFPROTO_IPV4, + .checkentry = tcpmss_mt_check, .match = tcpmss_mt, .matchsize = sizeof(struct xt_tcpmss_match_info), .proto = IPPROTO_TCP, diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c index be535a261fa0..4ca7964e83c8 100644 --- a/net/sched/act_ct.c +++ b/net/sched/act_ct.c @@ -1527,8 +1527,8 @@ static int tcf_ct_dump_helper(struct sk_buff *skb, return 0; if (nla_put_string(skb, TCA_CT_HELPER_NAME, helper->name) || - nla_put_u8(skb, TCA_CT_HELPER_FAMILY, helper->tuple.src.l3num) || - nla_put_u8(skb, TCA_CT_HELPER_PROTO, helper->tuple.dst.protonum)) + nla_put_u8(skb, TCA_CT_HELPER_FAMILY, helper->nfproto) || + nla_put_u8(skb, TCA_CT_HELPER_PROTO, helper->l4proto)) return -1; return 0;