diff options
author | David S. Miller <davem@davemloft.net> | 2013-02-18 23:42:09 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-02-18 23:42:09 -0500 |
commit | 2ccba5433ba567046e49643eb21502d5ea91dc83 (patch) | |
tree | 7297a374160c7785ebc39534d86a175b9c760c8c /net | |
parent | 6338a53a2bd02d5878ab449371323364b7cc7694 (diff) | |
parent | b20ab9cc63ca4605aec154cf54faa8455749f3f6 (diff) |
Merge branch 'master' of git://1984.lsi.us.es/nf-next
Pablo Neira Ayuso says:
====================
The following patchset contain updates for your net-next tree, they are:
* Fix (for just added) connlabel dependencies, from Florian Westphal.
* Add aliasing support for conntrack, thus users can either use -m state
or -m conntrack from iptables while using the same kernel module, from
Jozsef Kadlecsik.
* Some code refactoring for the CT target to merge common code in
revision 0 and 1, from myself.
* Add aliasing support for CT, based on patch from Jozsef Kadlecsik.
* Add one mutex per nfnetlink subsystem, from myself.
* Improved logging for packets that are dropped by helpers, from myself.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 10 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 8 | ||||
-rw-r--r-- | net/netfilter/Kconfig | 1 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_core.c | 26 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_amanda.c | 5 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_ftp.c | 10 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_h323_main.c | 6 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_helper.c | 19 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_irc.c | 7 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 12 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_pptp.c | 2 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_sane.c | 5 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_sip.c | 73 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_tftp.c | 8 | ||||
-rw-r--r-- | net/netfilter/nf_nat_amanda.c | 8 | ||||
-rw-r--r-- | net/netfilter/nf_nat_ftp.c | 5 | ||||
-rw-r--r-- | net/netfilter/nf_nat_irc.c | 8 | ||||
-rw-r--r-- | net/netfilter/nf_nat_sip.c | 49 | ||||
-rw-r--r-- | net/netfilter/nf_nat_tftp.c | 4 | ||||
-rw-r--r-- | net/netfilter/nfnetlink.c | 52 | ||||
-rw-r--r-- | net/netfilter/xt_CT.c | 177 |
21 files changed, 298 insertions, 197 deletions
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 48990ada0e1e..2820aa18b542 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -100,7 +100,6 @@ static unsigned int ipv4_helper(unsigned int hooknum, | |||
100 | enum ip_conntrack_info ctinfo; | 100 | enum ip_conntrack_info ctinfo; |
101 | const struct nf_conn_help *help; | 101 | const struct nf_conn_help *help; |
102 | const struct nf_conntrack_helper *helper; | 102 | const struct nf_conntrack_helper *helper; |
103 | unsigned int ret; | ||
104 | 103 | ||
105 | /* This is where we call the helper: as the packet goes out. */ | 104 | /* This is where we call the helper: as the packet goes out. */ |
106 | ct = nf_ct_get(skb, &ctinfo); | 105 | ct = nf_ct_get(skb, &ctinfo); |
@@ -116,13 +115,8 @@ static unsigned int ipv4_helper(unsigned int hooknum, | |||
116 | if (!helper) | 115 | if (!helper) |
117 | return NF_ACCEPT; | 116 | return NF_ACCEPT; |
118 | 117 | ||
119 | ret = helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb), | 118 | return helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb), |
120 | ct, ctinfo); | 119 | ct, ctinfo); |
121 | if (ret != NF_ACCEPT && (ret & NF_VERDICT_MASK) != NF_QUEUE) { | ||
122 | nf_log_packet(NFPROTO_IPV4, hooknum, skb, in, out, NULL, | ||
123 | "nf_ct_%s: dropping packet", helper->name); | ||
124 | } | ||
125 | return ret; | ||
126 | } | 120 | } |
127 | 121 | ||
128 | static unsigned int ipv4_confirm(unsigned int hooknum, | 122 | static unsigned int ipv4_confirm(unsigned int hooknum, |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 8a45bb20bedb..2b6c226f5198 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -104,7 +104,6 @@ static unsigned int ipv6_helper(unsigned int hooknum, | |||
104 | const struct nf_conn_help *help; | 104 | const struct nf_conn_help *help; |
105 | const struct nf_conntrack_helper *helper; | 105 | const struct nf_conntrack_helper *helper; |
106 | enum ip_conntrack_info ctinfo; | 106 | enum ip_conntrack_info ctinfo; |
107 | unsigned int ret; | ||
108 | __be16 frag_off; | 107 | __be16 frag_off; |
109 | int protoff; | 108 | int protoff; |
110 | u8 nexthdr; | 109 | u8 nexthdr; |
@@ -130,12 +129,7 @@ static unsigned int ipv6_helper(unsigned int hooknum, | |||
130 | return NF_ACCEPT; | 129 | return NF_ACCEPT; |
131 | } | 130 | } |
132 | 131 | ||
133 | ret = helper->help(skb, protoff, ct, ctinfo); | 132 | return helper->help(skb, protoff, ct, ctinfo); |
134 | if (ret != NF_ACCEPT && (ret & NF_VERDICT_MASK) != NF_QUEUE) { | ||
135 | nf_log_packet(NFPROTO_IPV6, hooknum, skb, in, out, NULL, | ||
136 | "nf_ct_%s: dropping packet", helper->name); | ||
137 | } | ||
138 | return ret; | ||
139 | } | 133 | } |
140 | 134 | ||
141 | static unsigned int ipv6_confirm(unsigned int hooknum, | 135 | static unsigned int ipv6_confirm(unsigned int hooknum, |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index eb2c8ebf6d99..d4dd702574e4 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -860,6 +860,7 @@ config NETFILTER_XT_MATCH_CONNBYTES | |||
860 | config NETFILTER_XT_MATCH_CONNLABEL | 860 | config NETFILTER_XT_MATCH_CONNLABEL |
861 | tristate '"connlabel" match support' | 861 | tristate '"connlabel" match support' |
862 | select NF_CONNTRACK_LABELS | 862 | select NF_CONNTRACK_LABELS |
863 | depends on NF_CONNTRACK | ||
863 | depends on NETFILTER_ADVANCED | 864 | depends on NETFILTER_ADVANCED |
864 | ---help--- | 865 | ---help--- |
865 | This match allows you to test and assign userspace-defined labels names | 866 | This match allows you to test and assign userspace-defined labels names |
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index 6d6d8f2b033e..f82b2e606cfd 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c | |||
@@ -88,14 +88,14 @@ find_set_type(const char *name, u8 family, u8 revision) | |||
88 | static bool | 88 | static bool |
89 | load_settype(const char *name) | 89 | load_settype(const char *name) |
90 | { | 90 | { |
91 | nfnl_unlock(); | 91 | nfnl_unlock(NFNL_SUBSYS_IPSET); |
92 | pr_debug("try to load ip_set_%s\n", name); | 92 | pr_debug("try to load ip_set_%s\n", name); |
93 | if (request_module("ip_set_%s", name) < 0) { | 93 | if (request_module("ip_set_%s", name) < 0) { |
94 | pr_warning("Can't find ip_set type %s\n", name); | 94 | pr_warning("Can't find ip_set type %s\n", name); |
95 | nfnl_lock(); | 95 | nfnl_lock(NFNL_SUBSYS_IPSET); |
96 | return false; | 96 | return false; |
97 | } | 97 | } |
98 | nfnl_lock(); | 98 | nfnl_lock(NFNL_SUBSYS_IPSET); |
99 | return true; | 99 | return true; |
100 | } | 100 | } |
101 | 101 | ||
@@ -532,7 +532,7 @@ ip_set_nfnl_get(const char *name) | |||
532 | ip_set_id_t i, index = IPSET_INVALID_ID; | 532 | ip_set_id_t i, index = IPSET_INVALID_ID; |
533 | struct ip_set *s; | 533 | struct ip_set *s; |
534 | 534 | ||
535 | nfnl_lock(); | 535 | nfnl_lock(NFNL_SUBSYS_IPSET); |
536 | for (i = 0; i < ip_set_max; i++) { | 536 | for (i = 0; i < ip_set_max; i++) { |
537 | s = nfnl_set(i); | 537 | s = nfnl_set(i); |
538 | if (s != NULL && STREQ(s->name, name)) { | 538 | if (s != NULL && STREQ(s->name, name)) { |
@@ -541,7 +541,7 @@ ip_set_nfnl_get(const char *name) | |||
541 | break; | 541 | break; |
542 | } | 542 | } |
543 | } | 543 | } |
544 | nfnl_unlock(); | 544 | nfnl_unlock(NFNL_SUBSYS_IPSET); |
545 | 545 | ||
546 | return index; | 546 | return index; |
547 | } | 547 | } |
@@ -561,13 +561,13 @@ ip_set_nfnl_get_byindex(ip_set_id_t index) | |||
561 | if (index > ip_set_max) | 561 | if (index > ip_set_max) |
562 | return IPSET_INVALID_ID; | 562 | return IPSET_INVALID_ID; |
563 | 563 | ||
564 | nfnl_lock(); | 564 | nfnl_lock(NFNL_SUBSYS_IPSET); |
565 | set = nfnl_set(index); | 565 | set = nfnl_set(index); |
566 | if (set) | 566 | if (set) |
567 | __ip_set_get(set); | 567 | __ip_set_get(set); |
568 | else | 568 | else |
569 | index = IPSET_INVALID_ID; | 569 | index = IPSET_INVALID_ID; |
570 | nfnl_unlock(); | 570 | nfnl_unlock(NFNL_SUBSYS_IPSET); |
571 | 571 | ||
572 | return index; | 572 | return index; |
573 | } | 573 | } |
@@ -584,11 +584,11 @@ void | |||
584 | ip_set_nfnl_put(ip_set_id_t index) | 584 | ip_set_nfnl_put(ip_set_id_t index) |
585 | { | 585 | { |
586 | struct ip_set *set; | 586 | struct ip_set *set; |
587 | nfnl_lock(); | 587 | nfnl_lock(NFNL_SUBSYS_IPSET); |
588 | set = nfnl_set(index); | 588 | set = nfnl_set(index); |
589 | if (set != NULL) | 589 | if (set != NULL) |
590 | __ip_set_put(set); | 590 | __ip_set_put(set); |
591 | nfnl_unlock(); | 591 | nfnl_unlock(NFNL_SUBSYS_IPSET); |
592 | } | 592 | } |
593 | EXPORT_SYMBOL_GPL(ip_set_nfnl_put); | 593 | EXPORT_SYMBOL_GPL(ip_set_nfnl_put); |
594 | 594 | ||
@@ -1763,10 +1763,10 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len) | |||
1763 | goto done; | 1763 | goto done; |
1764 | } | 1764 | } |
1765 | req_get->set.name[IPSET_MAXNAMELEN - 1] = '\0'; | 1765 | req_get->set.name[IPSET_MAXNAMELEN - 1] = '\0'; |
1766 | nfnl_lock(); | 1766 | nfnl_lock(NFNL_SUBSYS_IPSET); |
1767 | find_set_and_id(req_get->set.name, &id); | 1767 | find_set_and_id(req_get->set.name, &id); |
1768 | req_get->set.index = id; | 1768 | req_get->set.index = id; |
1769 | nfnl_unlock(); | 1769 | nfnl_unlock(NFNL_SUBSYS_IPSET); |
1770 | goto copy; | 1770 | goto copy; |
1771 | } | 1771 | } |
1772 | case IP_SET_OP_GET_BYINDEX: { | 1772 | case IP_SET_OP_GET_BYINDEX: { |
@@ -1778,11 +1778,11 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len) | |||
1778 | ret = -EINVAL; | 1778 | ret = -EINVAL; |
1779 | goto done; | 1779 | goto done; |
1780 | } | 1780 | } |
1781 | nfnl_lock(); | 1781 | nfnl_lock(NFNL_SUBSYS_IPSET); |
1782 | set = nfnl_set(req_get->set.index); | 1782 | set = nfnl_set(req_get->set.index); |
1783 | strncpy(req_get->set.name, set ? set->name : "", | 1783 | strncpy(req_get->set.name, set ? set->name : "", |
1784 | IPSET_MAXNAMELEN); | 1784 | IPSET_MAXNAMELEN); |
1785 | nfnl_unlock(); | 1785 | nfnl_unlock(NFNL_SUBSYS_IPSET); |
1786 | goto copy; | 1786 | goto copy; |
1787 | } | 1787 | } |
1788 | default: | 1788 | default: |
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c index c514fe6033d2..dbdaa1149260 100644 --- a/net/netfilter/nf_conntrack_amanda.c +++ b/net/netfilter/nf_conntrack_amanda.c | |||
@@ -145,6 +145,7 @@ static int amanda_help(struct sk_buff *skb, | |||
145 | 145 | ||
146 | exp = nf_ct_expect_alloc(ct); | 146 | exp = nf_ct_expect_alloc(ct); |
147 | if (exp == NULL) { | 147 | if (exp == NULL) { |
148 | nf_ct_helper_log(skb, ct, "cannot alloc expectation"); | ||
148 | ret = NF_DROP; | 149 | ret = NF_DROP; |
149 | goto out; | 150 | goto out; |
150 | } | 151 | } |
@@ -158,8 +159,10 @@ static int amanda_help(struct sk_buff *skb, | |||
158 | if (nf_nat_amanda && ct->status & IPS_NAT_MASK) | 159 | if (nf_nat_amanda && ct->status & IPS_NAT_MASK) |
159 | ret = nf_nat_amanda(skb, ctinfo, protoff, | 160 | ret = nf_nat_amanda(skb, ctinfo, protoff, |
160 | off - dataoff, len, exp); | 161 | off - dataoff, len, exp); |
161 | else if (nf_ct_expect_related(exp) != 0) | 162 | else if (nf_ct_expect_related(exp) != 0) { |
163 | nf_ct_helper_log(skb, ct, "cannot add expectation"); | ||
162 | ret = NF_DROP; | 164 | ret = NF_DROP; |
165 | } | ||
163 | nf_ct_expect_put(exp); | 166 | nf_ct_expect_put(exp); |
164 | } | 167 | } |
165 | 168 | ||
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 1ce3befb7c8a..62fb8faedb80 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c | |||
@@ -435,8 +435,8 @@ skip_nl_seq: | |||
435 | connection tracking, not packet filtering. | 435 | connection tracking, not packet filtering. |
436 | However, it is necessary for accurate tracking in | 436 | However, it is necessary for accurate tracking in |
437 | this case. */ | 437 | this case. */ |
438 | pr_debug("conntrack_ftp: partial %s %u+%u\n", | 438 | nf_ct_helper_log(skb, ct, "partial matching of `%s'", |
439 | search[dir][i].pattern, ntohl(th->seq), datalen); | 439 | search[dir][i].pattern); |
440 | ret = NF_DROP; | 440 | ret = NF_DROP; |
441 | goto out; | 441 | goto out; |
442 | } else if (found == 0) { /* No match */ | 442 | } else if (found == 0) { /* No match */ |
@@ -450,6 +450,7 @@ skip_nl_seq: | |||
450 | 450 | ||
451 | exp = nf_ct_expect_alloc(ct); | 451 | exp = nf_ct_expect_alloc(ct); |
452 | if (exp == NULL) { | 452 | if (exp == NULL) { |
453 | nf_ct_helper_log(skb, ct, "cannot alloc expectation"); | ||
453 | ret = NF_DROP; | 454 | ret = NF_DROP; |
454 | goto out; | 455 | goto out; |
455 | } | 456 | } |
@@ -500,9 +501,10 @@ skip_nl_seq: | |||
500 | protoff, matchoff, matchlen, exp); | 501 | protoff, matchoff, matchlen, exp); |
501 | else { | 502 | else { |
502 | /* Can't expect this? Best to drop packet now. */ | 503 | /* Can't expect this? Best to drop packet now. */ |
503 | if (nf_ct_expect_related(exp) != 0) | 504 | if (nf_ct_expect_related(exp) != 0) { |
505 | nf_ct_helper_log(skb, ct, "cannot add expectation"); | ||
504 | ret = NF_DROP; | 506 | ret = NF_DROP; |
505 | else | 507 | } else |
506 | ret = NF_ACCEPT; | 508 | ret = NF_ACCEPT; |
507 | } | 509 | } |
508 | 510 | ||
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 962795e839ab..7df7b36d2e24 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c | |||
@@ -623,7 +623,7 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff, | |||
623 | 623 | ||
624 | drop: | 624 | drop: |
625 | spin_unlock_bh(&nf_h323_lock); | 625 | spin_unlock_bh(&nf_h323_lock); |
626 | net_info_ratelimited("nf_ct_h245: packet dropped\n"); | 626 | nf_ct_helper_log(skb, ct, "cannot process H.245 message"); |
627 | return NF_DROP; | 627 | return NF_DROP; |
628 | } | 628 | } |
629 | 629 | ||
@@ -1197,7 +1197,7 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff, | |||
1197 | 1197 | ||
1198 | drop: | 1198 | drop: |
1199 | spin_unlock_bh(&nf_h323_lock); | 1199 | spin_unlock_bh(&nf_h323_lock); |
1200 | net_info_ratelimited("nf_ct_q931: packet dropped\n"); | 1200 | nf_ct_helper_log(skb, ct, "cannot process Q.931 message"); |
1201 | return NF_DROP; | 1201 | return NF_DROP; |
1202 | } | 1202 | } |
1203 | 1203 | ||
@@ -1795,7 +1795,7 @@ static int ras_help(struct sk_buff *skb, unsigned int protoff, | |||
1795 | 1795 | ||
1796 | drop: | 1796 | drop: |
1797 | spin_unlock_bh(&nf_h323_lock); | 1797 | spin_unlock_bh(&nf_h323_lock); |
1798 | net_info_ratelimited("nf_ct_ras: packet dropped\n"); | 1798 | nf_ct_helper_log(skb, ct, "cannot process RAS message"); |
1799 | return NF_DROP; | 1799 | return NF_DROP; |
1800 | } | 1800 | } |
1801 | 1801 | ||
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 1343a4bb4031..013cdf69fe29 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <net/netfilter/nf_conntrack_helper.h> | 28 | #include <net/netfilter/nf_conntrack_helper.h> |
29 | #include <net/netfilter/nf_conntrack_core.h> | 29 | #include <net/netfilter/nf_conntrack_core.h> |
30 | #include <net/netfilter/nf_conntrack_extend.h> | 30 | #include <net/netfilter/nf_conntrack_extend.h> |
31 | #include <net/netfilter/nf_log.h> | ||
31 | 32 | ||
32 | static DEFINE_MUTEX(nf_ct_helper_mutex); | 33 | static DEFINE_MUTEX(nf_ct_helper_mutex); |
33 | struct hlist_head *nf_ct_helper_hash __read_mostly; | 34 | struct hlist_head *nf_ct_helper_hash __read_mostly; |
@@ -334,6 +335,24 @@ nf_ct_helper_expectfn_find_by_symbol(const void *symbol) | |||
334 | } | 335 | } |
335 | EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_symbol); | 336 | EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_symbol); |
336 | 337 | ||
338 | __printf(3, 4) | ||
339 | void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct, | ||
340 | const char *fmt, ...) | ||
341 | { | ||
342 | const struct nf_conn_help *help; | ||
343 | const struct nf_conntrack_helper *helper; | ||
344 | |||
345 | /* Called from the helper function, this call never fails */ | ||
346 | help = nfct_help(ct); | ||
347 | |||
348 | /* rcu_read_lock()ed by nf_hook_slow */ | ||
349 | helper = rcu_dereference(help->helper); | ||
350 | |||
351 | nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, | ||
352 | "nf_ct_%s: dropping packet: %s ", helper->name, fmt); | ||
353 | } | ||
354 | EXPORT_SYMBOL_GPL(nf_ct_helper_log); | ||
355 | |||
337 | int nf_conntrack_helper_register(struct nf_conntrack_helper *me) | 356 | int nf_conntrack_helper_register(struct nf_conntrack_helper *me) |
338 | { | 357 | { |
339 | int ret = 0; | 358 | int ret = 0; |
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index 3b20aa77cfc8..70985c5d0ffa 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c | |||
@@ -194,6 +194,8 @@ static int help(struct sk_buff *skb, unsigned int protoff, | |||
194 | 194 | ||
195 | exp = nf_ct_expect_alloc(ct); | 195 | exp = nf_ct_expect_alloc(ct); |
196 | if (exp == NULL) { | 196 | if (exp == NULL) { |
197 | nf_ct_helper_log(skb, ct, | ||
198 | "cannot alloc expectation"); | ||
197 | ret = NF_DROP; | 199 | ret = NF_DROP; |
198 | goto out; | 200 | goto out; |
199 | } | 201 | } |
@@ -210,8 +212,11 @@ static int help(struct sk_buff *skb, unsigned int protoff, | |||
210 | addr_beg_p - ib_ptr, | 212 | addr_beg_p - ib_ptr, |
211 | addr_end_p - addr_beg_p, | 213 | addr_end_p - addr_beg_p, |
212 | exp); | 214 | exp); |
213 | else if (nf_ct_expect_related(exp) != 0) | 215 | else if (nf_ct_expect_related(exp) != 0) { |
216 | nf_ct_helper_log(skb, ct, | ||
217 | "cannot add expectation"); | ||
214 | ret = NF_DROP; | 218 | ret = NF_DROP; |
219 | } | ||
215 | nf_ct_expect_put(exp); | 220 | nf_ct_expect_put(exp); |
216 | goto out; | 221 | goto out; |
217 | } | 222 | } |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 79c2d507ac49..5d60e04f9679 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -1256,13 +1256,13 @@ ctnetlink_parse_nat_setup(struct nf_conn *ct, | |||
1256 | if (!parse_nat_setup) { | 1256 | if (!parse_nat_setup) { |
1257 | #ifdef CONFIG_MODULES | 1257 | #ifdef CONFIG_MODULES |
1258 | rcu_read_unlock(); | 1258 | rcu_read_unlock(); |
1259 | nfnl_unlock(); | 1259 | nfnl_unlock(NFNL_SUBSYS_CTNETLINK); |
1260 | if (request_module("nf-nat") < 0) { | 1260 | if (request_module("nf-nat") < 0) { |
1261 | nfnl_lock(); | 1261 | nfnl_lock(NFNL_SUBSYS_CTNETLINK); |
1262 | rcu_read_lock(); | 1262 | rcu_read_lock(); |
1263 | return -EOPNOTSUPP; | 1263 | return -EOPNOTSUPP; |
1264 | } | 1264 | } |
1265 | nfnl_lock(); | 1265 | nfnl_lock(NFNL_SUBSYS_CTNETLINK); |
1266 | rcu_read_lock(); | 1266 | rcu_read_lock(); |
1267 | if (nfnetlink_parse_nat_setup_hook) | 1267 | if (nfnetlink_parse_nat_setup_hook) |
1268 | return -EAGAIN; | 1268 | return -EAGAIN; |
@@ -1274,13 +1274,13 @@ ctnetlink_parse_nat_setup(struct nf_conn *ct, | |||
1274 | if (err == -EAGAIN) { | 1274 | if (err == -EAGAIN) { |
1275 | #ifdef CONFIG_MODULES | 1275 | #ifdef CONFIG_MODULES |
1276 | rcu_read_unlock(); | 1276 | rcu_read_unlock(); |
1277 | nfnl_unlock(); | 1277 | nfnl_unlock(NFNL_SUBSYS_CTNETLINK); |
1278 | if (request_module("nf-nat-%u", nf_ct_l3num(ct)) < 0) { | 1278 | if (request_module("nf-nat-%u", nf_ct_l3num(ct)) < 0) { |
1279 | nfnl_lock(); | 1279 | nfnl_lock(NFNL_SUBSYS_CTNETLINK); |
1280 | rcu_read_lock(); | 1280 | rcu_read_lock(); |
1281 | return -EOPNOTSUPP; | 1281 | return -EOPNOTSUPP; |
1282 | } | 1282 | } |
1283 | nfnl_lock(); | 1283 | nfnl_lock(NFNL_SUBSYS_CTNETLINK); |
1284 | rcu_read_lock(); | 1284 | rcu_read_lock(); |
1285 | #else | 1285 | #else |
1286 | err = -EOPNOTSUPP; | 1286 | err = -EOPNOTSUPP; |
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index cc7669ef0b95..e6678d2b624e 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c | |||
@@ -14,7 +14,7 @@ | |||
14 | * Limitations: | 14 | * Limitations: |
15 | * - We blindly assume that control connections are always | 15 | * - We blindly assume that control connections are always |
16 | * established in PNS->PAC direction. This is a violation | 16 | * established in PNS->PAC direction. This is a violation |
17 | * of RFFC2673 | 17 | * of RFC 2637 |
18 | * - We can only support one single call within each session | 18 | * - We can only support one single call within each session |
19 | * TODO: | 19 | * TODO: |
20 | * - testing of incoming PPTP calls | 20 | * - testing of incoming PPTP calls |
diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c index 295429f39088..4a2134fd3fcb 100644 --- a/net/netfilter/nf_conntrack_sane.c +++ b/net/netfilter/nf_conntrack_sane.c | |||
@@ -138,6 +138,7 @@ static int help(struct sk_buff *skb, | |||
138 | 138 | ||
139 | exp = nf_ct_expect_alloc(ct); | 139 | exp = nf_ct_expect_alloc(ct); |
140 | if (exp == NULL) { | 140 | if (exp == NULL) { |
141 | nf_ct_helper_log(skb, ct, "cannot alloc expectation"); | ||
141 | ret = NF_DROP; | 142 | ret = NF_DROP; |
142 | goto out; | 143 | goto out; |
143 | } | 144 | } |
@@ -151,8 +152,10 @@ static int help(struct sk_buff *skb, | |||
151 | nf_ct_dump_tuple(&exp->tuple); | 152 | nf_ct_dump_tuple(&exp->tuple); |
152 | 153 | ||
153 | /* Can't expect this? Best to drop packet now. */ | 154 | /* Can't expect this? Best to drop packet now. */ |
154 | if (nf_ct_expect_related(exp) != 0) | 155 | if (nf_ct_expect_related(exp) != 0) { |
156 | nf_ct_helper_log(skb, ct, "cannot add expectation"); | ||
155 | ret = NF_DROP; | 157 | ret = NF_DROP; |
158 | } | ||
156 | 159 | ||
157 | nf_ct_expect_put(exp); | 160 | nf_ct_expect_put(exp); |
158 | 161 | ||
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 72a67bbe3518..069229d919b6 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c | |||
@@ -1095,8 +1095,10 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, | |||
1095 | port = simple_strtoul(*dptr + mediaoff, NULL, 10); | 1095 | port = simple_strtoul(*dptr + mediaoff, NULL, 10); |
1096 | if (port == 0) | 1096 | if (port == 0) |
1097 | continue; | 1097 | continue; |
1098 | if (port < 1024 || port > 65535) | 1098 | if (port < 1024 || port > 65535) { |
1099 | nf_ct_helper_log(skb, ct, "wrong port %u", port); | ||
1099 | return NF_DROP; | 1100 | return NF_DROP; |
1101 | } | ||
1100 | 1102 | ||
1101 | /* The media description overrides the session description. */ | 1103 | /* The media description overrides the session description. */ |
1102 | maddr_len = 0; | 1104 | maddr_len = 0; |
@@ -1107,15 +1109,20 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, | |||
1107 | memcpy(&rtp_addr, &maddr, sizeof(rtp_addr)); | 1109 | memcpy(&rtp_addr, &maddr, sizeof(rtp_addr)); |
1108 | } else if (caddr_len) | 1110 | } else if (caddr_len) |
1109 | memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); | 1111 | memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); |
1110 | else | 1112 | else { |
1113 | nf_ct_helper_log(skb, ct, "cannot parse SDP message"); | ||
1111 | return NF_DROP; | 1114 | return NF_DROP; |
1115 | } | ||
1112 | 1116 | ||
1113 | ret = set_expected_rtp_rtcp(skb, protoff, dataoff, | 1117 | ret = set_expected_rtp_rtcp(skb, protoff, dataoff, |
1114 | dptr, datalen, | 1118 | dptr, datalen, |
1115 | &rtp_addr, htons(port), t->class, | 1119 | &rtp_addr, htons(port), t->class, |
1116 | mediaoff, medialen); | 1120 | mediaoff, medialen); |
1117 | if (ret != NF_ACCEPT) | 1121 | if (ret != NF_ACCEPT) { |
1122 | nf_ct_helper_log(skb, ct, | ||
1123 | "cannot add expectation for voice"); | ||
1118 | return ret; | 1124 | return ret; |
1125 | } | ||
1119 | 1126 | ||
1120 | /* Update media connection address if present */ | 1127 | /* Update media connection address if present */ |
1121 | if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) { | 1128 | if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) { |
@@ -1123,8 +1130,10 @@ static int process_sdp(struct sk_buff *skb, unsigned int protoff, | |||
1123 | dptr, datalen, mediaoff, | 1130 | dptr, datalen, mediaoff, |
1124 | SDP_HDR_CONNECTION, SDP_HDR_MEDIA, | 1131 | SDP_HDR_CONNECTION, SDP_HDR_MEDIA, |
1125 | &rtp_addr); | 1132 | &rtp_addr); |
1126 | if (ret != NF_ACCEPT) | 1133 | if (ret != NF_ACCEPT) { |
1134 | nf_ct_helper_log(skb, ct, "cannot mangle SDP"); | ||
1127 | return ret; | 1135 | return ret; |
1136 | } | ||
1128 | } | 1137 | } |
1129 | i++; | 1138 | i++; |
1130 | } | 1139 | } |
@@ -1258,9 +1267,10 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff, | |||
1258 | ret = ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, | 1267 | ret = ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, |
1259 | SIP_HDR_CONTACT, NULL, | 1268 | SIP_HDR_CONTACT, NULL, |
1260 | &matchoff, &matchlen, &daddr, &port); | 1269 | &matchoff, &matchlen, &daddr, &port); |
1261 | if (ret < 0) | 1270 | if (ret < 0) { |
1271 | nf_ct_helper_log(skb, ct, "cannot parse contact"); | ||
1262 | return NF_DROP; | 1272 | return NF_DROP; |
1263 | else if (ret == 0) | 1273 | } else if (ret == 0) |
1264 | return NF_ACCEPT; | 1274 | return NF_ACCEPT; |
1265 | 1275 | ||
1266 | /* We don't support third-party registrations */ | 1276 | /* We don't support third-party registrations */ |
@@ -1273,8 +1283,10 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff, | |||
1273 | 1283 | ||
1274 | if (ct_sip_parse_numerical_param(ct, *dptr, | 1284 | if (ct_sip_parse_numerical_param(ct, *dptr, |
1275 | matchoff + matchlen, *datalen, | 1285 | matchoff + matchlen, *datalen, |
1276 | "expires=", NULL, NULL, &expires) < 0) | 1286 | "expires=", NULL, NULL, &expires) < 0) { |
1287 | nf_ct_helper_log(skb, ct, "cannot parse expires"); | ||
1277 | return NF_DROP; | 1288 | return NF_DROP; |
1289 | } | ||
1278 | 1290 | ||
1279 | if (expires == 0) { | 1291 | if (expires == 0) { |
1280 | ret = NF_ACCEPT; | 1292 | ret = NF_ACCEPT; |
@@ -1282,8 +1294,10 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff, | |||
1282 | } | 1294 | } |
1283 | 1295 | ||
1284 | exp = nf_ct_expect_alloc(ct); | 1296 | exp = nf_ct_expect_alloc(ct); |
1285 | if (!exp) | 1297 | if (!exp) { |
1298 | nf_ct_helper_log(skb, ct, "cannot alloc expectation"); | ||
1286 | return NF_DROP; | 1299 | return NF_DROP; |
1300 | } | ||
1287 | 1301 | ||
1288 | saddr = NULL; | 1302 | saddr = NULL; |
1289 | if (sip_direct_signalling) | 1303 | if (sip_direct_signalling) |
@@ -1300,9 +1314,10 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff, | |||
1300 | ret = nf_nat_sip_expect(skb, protoff, dataoff, dptr, datalen, | 1314 | ret = nf_nat_sip_expect(skb, protoff, dataoff, dptr, datalen, |
1301 | exp, matchoff, matchlen); | 1315 | exp, matchoff, matchlen); |
1302 | else { | 1316 | else { |
1303 | if (nf_ct_expect_related(exp) != 0) | 1317 | if (nf_ct_expect_related(exp) != 0) { |
1318 | nf_ct_helper_log(skb, ct, "cannot add expectation"); | ||
1304 | ret = NF_DROP; | 1319 | ret = NF_DROP; |
1305 | else | 1320 | } else |
1306 | ret = NF_ACCEPT; | 1321 | ret = NF_ACCEPT; |
1307 | } | 1322 | } |
1308 | nf_ct_expect_put(exp); | 1323 | nf_ct_expect_put(exp); |
@@ -1356,9 +1371,10 @@ static int process_register_response(struct sk_buff *skb, unsigned int protoff, | |||
1356 | SIP_HDR_CONTACT, &in_contact, | 1371 | SIP_HDR_CONTACT, &in_contact, |
1357 | &matchoff, &matchlen, | 1372 | &matchoff, &matchlen, |
1358 | &addr, &port); | 1373 | &addr, &port); |
1359 | if (ret < 0) | 1374 | if (ret < 0) { |
1375 | nf_ct_helper_log(skb, ct, "cannot parse contact"); | ||
1360 | return NF_DROP; | 1376 | return NF_DROP; |
1361 | else if (ret == 0) | 1377 | } else if (ret == 0) |
1362 | break; | 1378 | break; |
1363 | 1379 | ||
1364 | /* We don't support third-party registrations */ | 1380 | /* We don't support third-party registrations */ |
@@ -1373,8 +1389,10 @@ static int process_register_response(struct sk_buff *skb, unsigned int protoff, | |||
1373 | matchoff + matchlen, | 1389 | matchoff + matchlen, |
1374 | *datalen, "expires=", | 1390 | *datalen, "expires=", |
1375 | NULL, NULL, &c_expires); | 1391 | NULL, NULL, &c_expires); |
1376 | if (ret < 0) | 1392 | if (ret < 0) { |
1393 | nf_ct_helper_log(skb, ct, "cannot parse expires"); | ||
1377 | return NF_DROP; | 1394 | return NF_DROP; |
1395 | } | ||
1378 | if (c_expires == 0) | 1396 | if (c_expires == 0) |
1379 | break; | 1397 | break; |
1380 | if (refresh_signalling_expectation(ct, &addr, proto, port, | 1398 | if (refresh_signalling_expectation(ct, &addr, proto, port, |
@@ -1408,15 +1426,21 @@ static int process_sip_response(struct sk_buff *skb, unsigned int protoff, | |||
1408 | if (*datalen < strlen("SIP/2.0 200")) | 1426 | if (*datalen < strlen("SIP/2.0 200")) |
1409 | return NF_ACCEPT; | 1427 | return NF_ACCEPT; |
1410 | code = simple_strtoul(*dptr + strlen("SIP/2.0 "), NULL, 10); | 1428 | code = simple_strtoul(*dptr + strlen("SIP/2.0 "), NULL, 10); |
1411 | if (!code) | 1429 | if (!code) { |
1430 | nf_ct_helper_log(skb, ct, "cannot get code"); | ||
1412 | return NF_DROP; | 1431 | return NF_DROP; |
1432 | } | ||
1413 | 1433 | ||
1414 | if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ, | 1434 | if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ, |
1415 | &matchoff, &matchlen) <= 0) | 1435 | &matchoff, &matchlen) <= 0) { |
1436 | nf_ct_helper_log(skb, ct, "cannot parse cseq"); | ||
1416 | return NF_DROP; | 1437 | return NF_DROP; |
1438 | } | ||
1417 | cseq = simple_strtoul(*dptr + matchoff, NULL, 10); | 1439 | cseq = simple_strtoul(*dptr + matchoff, NULL, 10); |
1418 | if (!cseq) | 1440 | if (!cseq) { |
1441 | nf_ct_helper_log(skb, ct, "cannot get cseq"); | ||
1419 | return NF_DROP; | 1442 | return NF_DROP; |
1443 | } | ||
1420 | matchend = matchoff + matchlen + 1; | 1444 | matchend = matchoff + matchlen + 1; |
1421 | 1445 | ||
1422 | for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) { | 1446 | for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) { |
@@ -1471,11 +1495,15 @@ static int process_sip_request(struct sk_buff *skb, unsigned int protoff, | |||
1471 | continue; | 1495 | continue; |
1472 | 1496 | ||
1473 | if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ, | 1497 | if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ, |
1474 | &matchoff, &matchlen) <= 0) | 1498 | &matchoff, &matchlen) <= 0) { |
1499 | nf_ct_helper_log(skb, ct, "cannot parse cseq"); | ||
1475 | return NF_DROP; | 1500 | return NF_DROP; |
1501 | } | ||
1476 | cseq = simple_strtoul(*dptr + matchoff, NULL, 10); | 1502 | cseq = simple_strtoul(*dptr + matchoff, NULL, 10); |
1477 | if (!cseq) | 1503 | if (!cseq) { |
1504 | nf_ct_helper_log(skb, ct, "cannot get cseq"); | ||
1478 | return NF_DROP; | 1505 | return NF_DROP; |
1506 | } | ||
1479 | 1507 | ||
1480 | return handler->request(skb, protoff, dataoff, dptr, datalen, | 1508 | return handler->request(skb, protoff, dataoff, dptr, datalen, |
1481 | cseq); | 1509 | cseq); |
@@ -1498,8 +1526,10 @@ static int process_sip_msg(struct sk_buff *skb, struct nf_conn *ct, | |||
1498 | if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) { | 1526 | if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) { |
1499 | nf_nat_sip = rcu_dereference(nf_nat_sip_hook); | 1527 | nf_nat_sip = rcu_dereference(nf_nat_sip_hook); |
1500 | if (nf_nat_sip && !nf_nat_sip(skb, protoff, dataoff, | 1528 | if (nf_nat_sip && !nf_nat_sip(skb, protoff, dataoff, |
1501 | dptr, datalen)) | 1529 | dptr, datalen)) { |
1530 | nf_ct_helper_log(skb, ct, "cannot NAT SIP message"); | ||
1502 | ret = NF_DROP; | 1531 | ret = NF_DROP; |
1532 | } | ||
1503 | } | 1533 | } |
1504 | 1534 | ||
1505 | return ret; | 1535 | return ret; |
@@ -1563,11 +1593,14 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, | |||
1563 | end += strlen("\r\n\r\n") + clen; | 1593 | end += strlen("\r\n\r\n") + clen; |
1564 | 1594 | ||
1565 | msglen = origlen = end - dptr; | 1595 | msglen = origlen = end - dptr; |
1566 | if (msglen > datalen) | 1596 | if (msglen > datalen) { |
1597 | nf_ct_helper_log(skb, ct, "incomplete/bad SIP message"); | ||
1567 | return NF_DROP; | 1598 | return NF_DROP; |
1599 | } | ||
1568 | 1600 | ||
1569 | ret = process_sip_msg(skb, ct, protoff, dataoff, | 1601 | ret = process_sip_msg(skb, ct, protoff, dataoff, |
1570 | &dptr, &msglen); | 1602 | &dptr, &msglen); |
1603 | /* process_sip_* functions report why this packet is dropped */ | ||
1571 | if (ret != NF_ACCEPT) | 1604 | if (ret != NF_ACCEPT) |
1572 | break; | 1605 | break; |
1573 | diff = msglen - origlen; | 1606 | diff = msglen - origlen; |
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c index 81fc61c05263..e9936c830208 100644 --- a/net/netfilter/nf_conntrack_tftp.c +++ b/net/netfilter/nf_conntrack_tftp.c | |||
@@ -60,8 +60,10 @@ static int tftp_help(struct sk_buff *skb, | |||
60 | nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); | 60 | nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); |
61 | 61 | ||
62 | exp = nf_ct_expect_alloc(ct); | 62 | exp = nf_ct_expect_alloc(ct); |
63 | if (exp == NULL) | 63 | if (exp == NULL) { |
64 | nf_ct_helper_log(skb, ct, "cannot alloc expectation"); | ||
64 | return NF_DROP; | 65 | return NF_DROP; |
66 | } | ||
65 | tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; | 67 | tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; |
66 | nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, | 68 | nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, |
67 | nf_ct_l3num(ct), | 69 | nf_ct_l3num(ct), |
@@ -74,8 +76,10 @@ static int tftp_help(struct sk_buff *skb, | |||
74 | nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook); | 76 | nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook); |
75 | if (nf_nat_tftp && ct->status & IPS_NAT_MASK) | 77 | if (nf_nat_tftp && ct->status & IPS_NAT_MASK) |
76 | ret = nf_nat_tftp(skb, ctinfo, exp); | 78 | ret = nf_nat_tftp(skb, ctinfo, exp); |
77 | else if (nf_ct_expect_related(exp) != 0) | 79 | else if (nf_ct_expect_related(exp) != 0) { |
80 | nf_ct_helper_log(skb, ct, "cannot add expectation"); | ||
78 | ret = NF_DROP; | 81 | ret = NF_DROP; |
82 | } | ||
79 | nf_ct_expect_put(exp); | 83 | nf_ct_expect_put(exp); |
80 | break; | 84 | break; |
81 | case TFTP_OPCODE_DATA: | 85 | case TFTP_OPCODE_DATA: |
diff --git a/net/netfilter/nf_nat_amanda.c b/net/netfilter/nf_nat_amanda.c index 42d337881171..3b67c9d11273 100644 --- a/net/netfilter/nf_nat_amanda.c +++ b/net/netfilter/nf_nat_amanda.c | |||
@@ -56,15 +56,19 @@ static unsigned int help(struct sk_buff *skb, | |||
56 | } | 56 | } |
57 | } | 57 | } |
58 | 58 | ||
59 | if (port == 0) | 59 | if (port == 0) { |
60 | nf_ct_helper_log(skb, exp->master, "all ports in use"); | ||
60 | return NF_DROP; | 61 | return NF_DROP; |
62 | } | ||
61 | 63 | ||
62 | sprintf(buffer, "%u", port); | 64 | sprintf(buffer, "%u", port); |
63 | ret = nf_nat_mangle_udp_packet(skb, exp->master, ctinfo, | 65 | ret = nf_nat_mangle_udp_packet(skb, exp->master, ctinfo, |
64 | protoff, matchoff, matchlen, | 66 | protoff, matchoff, matchlen, |
65 | buffer, strlen(buffer)); | 67 | buffer, strlen(buffer)); |
66 | if (ret != NF_ACCEPT) | 68 | if (ret != NF_ACCEPT) { |
69 | nf_ct_helper_log(skb, exp->master, "cannot mangle packet"); | ||
67 | nf_ct_unexpect_related(exp); | 70 | nf_ct_unexpect_related(exp); |
71 | } | ||
68 | return ret; | 72 | return ret; |
69 | } | 73 | } |
70 | 74 | ||
diff --git a/net/netfilter/nf_nat_ftp.c b/net/netfilter/nf_nat_ftp.c index e839b97b2863..e84a578dbe35 100644 --- a/net/netfilter/nf_nat_ftp.c +++ b/net/netfilter/nf_nat_ftp.c | |||
@@ -96,8 +96,10 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb, | |||
96 | } | 96 | } |
97 | } | 97 | } |
98 | 98 | ||
99 | if (port == 0) | 99 | if (port == 0) { |
100 | nf_ct_helper_log(skb, ct, "all ports in use"); | ||
100 | return NF_DROP; | 101 | return NF_DROP; |
102 | } | ||
101 | 103 | ||
102 | buflen = nf_nat_ftp_fmt_cmd(ct, type, buffer, sizeof(buffer), | 104 | buflen = nf_nat_ftp_fmt_cmd(ct, type, buffer, sizeof(buffer), |
103 | &newaddr, port); | 105 | &newaddr, port); |
@@ -113,6 +115,7 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb, | |||
113 | return NF_ACCEPT; | 115 | return NF_ACCEPT; |
114 | 116 | ||
115 | out: | 117 | out: |
118 | nf_ct_helper_log(skb, ct, "cannot mangle packet"); | ||
116 | nf_ct_unexpect_related(exp); | 119 | nf_ct_unexpect_related(exp); |
117 | return NF_DROP; | 120 | return NF_DROP; |
118 | } | 121 | } |
diff --git a/net/netfilter/nf_nat_irc.c b/net/netfilter/nf_nat_irc.c index 1fedee6e7fb6..f02b3605823e 100644 --- a/net/netfilter/nf_nat_irc.c +++ b/net/netfilter/nf_nat_irc.c | |||
@@ -56,14 +56,18 @@ static unsigned int help(struct sk_buff *skb, | |||
56 | } | 56 | } |
57 | } | 57 | } |
58 | 58 | ||
59 | if (port == 0) | 59 | if (port == 0) { |
60 | nf_ct_helper_log(skb, exp->master, "all ports in use"); | ||
60 | return NF_DROP; | 61 | return NF_DROP; |
62 | } | ||
61 | 63 | ||
62 | ret = nf_nat_mangle_tcp_packet(skb, exp->master, ctinfo, | 64 | ret = nf_nat_mangle_tcp_packet(skb, exp->master, ctinfo, |
63 | protoff, matchoff, matchlen, buffer, | 65 | protoff, matchoff, matchlen, buffer, |
64 | strlen(buffer)); | 66 | strlen(buffer)); |
65 | if (ret != NF_ACCEPT) | 67 | if (ret != NF_ACCEPT) { |
68 | nf_ct_helper_log(skb, exp->master, "cannot mangle packet"); | ||
66 | nf_ct_unexpect_related(exp); | 69 | nf_ct_unexpect_related(exp); |
70 | } | ||
67 | return ret; | 71 | return ret; |
68 | } | 72 | } |
69 | 73 | ||
diff --git a/net/netfilter/nf_nat_sip.c b/net/netfilter/nf_nat_sip.c index 5951146e7688..96ccdf78a29f 100644 --- a/net/netfilter/nf_nat_sip.c +++ b/net/netfilter/nf_nat_sip.c | |||
@@ -159,8 +159,10 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, | |||
159 | &matchoff, &matchlen, | 159 | &matchoff, &matchlen, |
160 | &addr, &port) > 0 && | 160 | &addr, &port) > 0 && |
161 | !map_addr(skb, protoff, dataoff, dptr, datalen, | 161 | !map_addr(skb, protoff, dataoff, dptr, datalen, |
162 | matchoff, matchlen, &addr, port)) | 162 | matchoff, matchlen, &addr, port)) { |
163 | nf_ct_helper_log(skb, ct, "cannot mangle SIP message"); | ||
163 | return NF_DROP; | 164 | return NF_DROP; |
165 | } | ||
164 | request = 1; | 166 | request = 1; |
165 | } else | 167 | } else |
166 | request = 0; | 168 | request = 0; |
@@ -193,8 +195,10 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, | |||
193 | 195 | ||
194 | olen = *datalen; | 196 | olen = *datalen; |
195 | if (!map_addr(skb, protoff, dataoff, dptr, datalen, | 197 | if (!map_addr(skb, protoff, dataoff, dptr, datalen, |
196 | matchoff, matchlen, &addr, port)) | 198 | matchoff, matchlen, &addr, port)) { |
199 | nf_ct_helper_log(skb, ct, "cannot mangle Via header"); | ||
197 | return NF_DROP; | 200 | return NF_DROP; |
201 | } | ||
198 | 202 | ||
199 | matchend = matchoff + matchlen + *datalen - olen; | 203 | matchend = matchoff + matchlen + *datalen - olen; |
200 | 204 | ||
@@ -209,8 +213,10 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, | |||
209 | &ct->tuplehash[!dir].tuple.dst.u3, | 213 | &ct->tuplehash[!dir].tuple.dst.u3, |
210 | true); | 214 | true); |
211 | if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, | 215 | if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, |
212 | poff, plen, buffer, buflen)) | 216 | poff, plen, buffer, buflen)) { |
217 | nf_ct_helper_log(skb, ct, "cannot mangle maddr"); | ||
213 | return NF_DROP; | 218 | return NF_DROP; |
219 | } | ||
214 | } | 220 | } |
215 | 221 | ||
216 | /* The received= parameter (RFC 2361) contains the address | 222 | /* The received= parameter (RFC 2361) contains the address |
@@ -225,6 +231,7 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, | |||
225 | false); | 231 | false); |
226 | if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, | 232 | if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, |
227 | poff, plen, buffer, buflen)) | 233 | poff, plen, buffer, buflen)) |
234 | nf_ct_helper_log(skb, ct, "cannot mangle received"); | ||
228 | return NF_DROP; | 235 | return NF_DROP; |
229 | } | 236 | } |
230 | 237 | ||
@@ -238,8 +245,10 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, | |||
238 | __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port; | 245 | __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port; |
239 | buflen = sprintf(buffer, "%u", ntohs(p)); | 246 | buflen = sprintf(buffer, "%u", ntohs(p)); |
240 | if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, | 247 | if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, |
241 | poff, plen, buffer, buflen)) | 248 | poff, plen, buffer, buflen)) { |
249 | nf_ct_helper_log(skb, ct, "cannot mangle rport"); | ||
242 | return NF_DROP; | 250 | return NF_DROP; |
251 | } | ||
243 | } | 252 | } |
244 | } | 253 | } |
245 | 254 | ||
@@ -253,27 +262,35 @@ next: | |||
253 | &addr, &port) > 0) { | 262 | &addr, &port) > 0) { |
254 | if (!map_addr(skb, protoff, dataoff, dptr, datalen, | 263 | if (!map_addr(skb, protoff, dataoff, dptr, datalen, |
255 | matchoff, matchlen, | 264 | matchoff, matchlen, |
256 | &addr, port)) | 265 | &addr, port)) { |
266 | nf_ct_helper_log(skb, ct, "cannot mangle contact"); | ||
257 | return NF_DROP; | 267 | return NF_DROP; |
268 | } | ||
258 | } | 269 | } |
259 | 270 | ||
260 | if (!map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_FROM) || | 271 | if (!map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_FROM) || |
261 | !map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_TO)) | 272 | !map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_TO)) { |
273 | nf_ct_helper_log(skb, ct, "cannot mangle SIP from/to"); | ||
262 | return NF_DROP; | 274 | return NF_DROP; |
275 | } | ||
263 | 276 | ||
264 | /* Mangle destination port for Cisco phones, then fix up checksums */ | 277 | /* Mangle destination port for Cisco phones, then fix up checksums */ |
265 | if (dir == IP_CT_DIR_REPLY && ct_sip_info->forced_dport) { | 278 | if (dir == IP_CT_DIR_REPLY && ct_sip_info->forced_dport) { |
266 | struct udphdr *uh; | 279 | struct udphdr *uh; |
267 | 280 | ||
268 | if (!skb_make_writable(skb, skb->len)) | 281 | if (!skb_make_writable(skb, skb->len)) { |
282 | nf_ct_helper_log(skb, ct, "cannot mangle packet"); | ||
269 | return NF_DROP; | 283 | return NF_DROP; |
284 | } | ||
270 | 285 | ||
271 | uh = (void *)skb->data + protoff; | 286 | uh = (void *)skb->data + protoff; |
272 | uh->dest = ct_sip_info->forced_dport; | 287 | uh->dest = ct_sip_info->forced_dport; |
273 | 288 | ||
274 | if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, protoff, | 289 | if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, protoff, |
275 | 0, 0, NULL, 0)) | 290 | 0, 0, NULL, 0)) { |
291 | nf_ct_helper_log(skb, ct, "cannot mangle packet"); | ||
276 | return NF_DROP; | 292 | return NF_DROP; |
293 | } | ||
277 | } | 294 | } |
278 | 295 | ||
279 | return NF_ACCEPT; | 296 | return NF_ACCEPT; |
@@ -372,15 +389,19 @@ static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int protoff, | |||
372 | } | 389 | } |
373 | } | 390 | } |
374 | 391 | ||
375 | if (port == 0) | 392 | if (port == 0) { |
393 | nf_ct_helper_log(skb, ct, "all ports in use for SIP"); | ||
376 | return NF_DROP; | 394 | return NF_DROP; |
395 | } | ||
377 | 396 | ||
378 | if (!nf_inet_addr_cmp(&exp->tuple.dst.u3, &exp->saved_addr) || | 397 | if (!nf_inet_addr_cmp(&exp->tuple.dst.u3, &exp->saved_addr) || |
379 | exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) { | 398 | exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) { |
380 | buflen = sip_sprintf_addr_port(ct, buffer, &newaddr, port); | 399 | buflen = sip_sprintf_addr_port(ct, buffer, &newaddr, port); |
381 | if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, | 400 | if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, |
382 | matchoff, matchlen, buffer, buflen)) | 401 | matchoff, matchlen, buffer, buflen)) { |
402 | nf_ct_helper_log(skb, ct, "cannot mangle packet"); | ||
383 | goto err; | 403 | goto err; |
404 | } | ||
384 | } | 405 | } |
385 | return NF_ACCEPT; | 406 | return NF_ACCEPT; |
386 | 407 | ||
@@ -573,14 +594,18 @@ static unsigned int nf_nat_sdp_media(struct sk_buff *skb, unsigned int protoff, | |||
573 | } | 594 | } |
574 | } | 595 | } |
575 | 596 | ||
576 | if (port == 0) | 597 | if (port == 0) { |
598 | nf_ct_helper_log(skb, ct, "all ports in use for SDP media"); | ||
577 | goto err1; | 599 | goto err1; |
600 | } | ||
578 | 601 | ||
579 | /* Update media port. */ | 602 | /* Update media port. */ |
580 | if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port && | 603 | if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port && |
581 | !nf_nat_sdp_port(skb, protoff, dataoff, dptr, datalen, | 604 | !nf_nat_sdp_port(skb, protoff, dataoff, dptr, datalen, |
582 | mediaoff, medialen, port)) | 605 | mediaoff, medialen, port)) { |
606 | nf_ct_helper_log(skb, ct, "cannot mangle SDP message"); | ||
583 | goto err2; | 607 | goto err2; |
608 | } | ||
584 | 609 | ||
585 | return NF_ACCEPT; | 610 | return NF_ACCEPT; |
586 | 611 | ||
diff --git a/net/netfilter/nf_nat_tftp.c b/net/netfilter/nf_nat_tftp.c index ccabbda71a3e..7f67e1d5310d 100644 --- a/net/netfilter/nf_nat_tftp.c +++ b/net/netfilter/nf_nat_tftp.c | |||
@@ -28,8 +28,10 @@ static unsigned int help(struct sk_buff *skb, | |||
28 | = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port; | 28 | = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port; |
29 | exp->dir = IP_CT_DIR_REPLY; | 29 | exp->dir = IP_CT_DIR_REPLY; |
30 | exp->expectfn = nf_nat_follow_master; | 30 | exp->expectfn = nf_nat_follow_master; |
31 | if (nf_ct_expect_related(exp) != 0) | 31 | if (nf_ct_expect_related(exp) != 0) { |
32 | nf_ct_helper_log(skb, exp->master, "cannot add expectation"); | ||
32 | return NF_DROP; | 33 | return NF_DROP; |
34 | } | ||
33 | return NF_ACCEPT; | 35 | return NF_ACCEPT; |
34 | } | 36 | } |
35 | 37 | ||
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 58a09b7c3f6d..d578ec251712 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
@@ -36,8 +36,10 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER); | |||
36 | 36 | ||
37 | static char __initdata nfversion[] = "0.30"; | 37 | static char __initdata nfversion[] = "0.30"; |
38 | 38 | ||
39 | static const struct nfnetlink_subsystem __rcu *subsys_table[NFNL_SUBSYS_COUNT]; | 39 | static struct { |
40 | static DEFINE_MUTEX(nfnl_mutex); | 40 | struct mutex mutex; |
41 | const struct nfnetlink_subsystem __rcu *subsys; | ||
42 | } table[NFNL_SUBSYS_COUNT]; | ||
41 | 43 | ||
42 | static const int nfnl_group2type[NFNLGRP_MAX+1] = { | 44 | static const int nfnl_group2type[NFNLGRP_MAX+1] = { |
43 | [NFNLGRP_CONNTRACK_NEW] = NFNL_SUBSYS_CTNETLINK, | 45 | [NFNLGRP_CONNTRACK_NEW] = NFNL_SUBSYS_CTNETLINK, |
@@ -48,27 +50,32 @@ static const int nfnl_group2type[NFNLGRP_MAX+1] = { | |||
48 | [NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP, | 50 | [NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP, |
49 | }; | 51 | }; |
50 | 52 | ||
51 | void nfnl_lock(void) | 53 | void nfnl_lock(__u8 subsys_id) |
52 | { | 54 | { |
53 | mutex_lock(&nfnl_mutex); | 55 | mutex_lock(&table[subsys_id].mutex); |
54 | } | 56 | } |
55 | EXPORT_SYMBOL_GPL(nfnl_lock); | 57 | EXPORT_SYMBOL_GPL(nfnl_lock); |
56 | 58 | ||
57 | void nfnl_unlock(void) | 59 | void nfnl_unlock(__u8 subsys_id) |
58 | { | 60 | { |
59 | mutex_unlock(&nfnl_mutex); | 61 | mutex_unlock(&table[subsys_id].mutex); |
60 | } | 62 | } |
61 | EXPORT_SYMBOL_GPL(nfnl_unlock); | 63 | EXPORT_SYMBOL_GPL(nfnl_unlock); |
62 | 64 | ||
65 | static struct mutex *nfnl_get_lock(__u8 subsys_id) | ||
66 | { | ||
67 | return &table[subsys_id].mutex; | ||
68 | } | ||
69 | |||
63 | int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n) | 70 | int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n) |
64 | { | 71 | { |
65 | nfnl_lock(); | 72 | nfnl_lock(n->subsys_id); |
66 | if (subsys_table[n->subsys_id]) { | 73 | if (table[n->subsys_id].subsys) { |
67 | nfnl_unlock(); | 74 | nfnl_unlock(n->subsys_id); |
68 | return -EBUSY; | 75 | return -EBUSY; |
69 | } | 76 | } |
70 | rcu_assign_pointer(subsys_table[n->subsys_id], n); | 77 | rcu_assign_pointer(table[n->subsys_id].subsys, n); |
71 | nfnl_unlock(); | 78 | nfnl_unlock(n->subsys_id); |
72 | 79 | ||
73 | return 0; | 80 | return 0; |
74 | } | 81 | } |
@@ -76,9 +83,9 @@ EXPORT_SYMBOL_GPL(nfnetlink_subsys_register); | |||
76 | 83 | ||
77 | int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n) | 84 | int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n) |
78 | { | 85 | { |
79 | nfnl_lock(); | 86 | nfnl_lock(n->subsys_id); |
80 | subsys_table[n->subsys_id] = NULL; | 87 | table[n->subsys_id].subsys = NULL; |
81 | nfnl_unlock(); | 88 | nfnl_unlock(n->subsys_id); |
82 | synchronize_rcu(); | 89 | synchronize_rcu(); |
83 | return 0; | 90 | return 0; |
84 | } | 91 | } |
@@ -91,7 +98,7 @@ static inline const struct nfnetlink_subsystem *nfnetlink_get_subsys(u_int16_t t | |||
91 | if (subsys_id >= NFNL_SUBSYS_COUNT) | 98 | if (subsys_id >= NFNL_SUBSYS_COUNT) |
92 | return NULL; | 99 | return NULL; |
93 | 100 | ||
94 | return rcu_dereference(subsys_table[subsys_id]); | 101 | return rcu_dereference(table[subsys_id].subsys); |
95 | } | 102 | } |
96 | 103 | ||
97 | static inline const struct nfnl_callback * | 104 | static inline const struct nfnl_callback * |
@@ -175,6 +182,7 @@ replay: | |||
175 | struct nlattr *cda[ss->cb[cb_id].attr_count + 1]; | 182 | struct nlattr *cda[ss->cb[cb_id].attr_count + 1]; |
176 | struct nlattr *attr = (void *)nlh + min_len; | 183 | struct nlattr *attr = (void *)nlh + min_len; |
177 | int attrlen = nlh->nlmsg_len - min_len; | 184 | int attrlen = nlh->nlmsg_len - min_len; |
185 | __u8 subsys_id = NFNL_SUBSYS_ID(type); | ||
178 | 186 | ||
179 | err = nla_parse(cda, ss->cb[cb_id].attr_count, | 187 | err = nla_parse(cda, ss->cb[cb_id].attr_count, |
180 | attr, attrlen, ss->cb[cb_id].policy); | 188 | attr, attrlen, ss->cb[cb_id].policy); |
@@ -189,10 +197,9 @@ replay: | |||
189 | rcu_read_unlock(); | 197 | rcu_read_unlock(); |
190 | } else { | 198 | } else { |
191 | rcu_read_unlock(); | 199 | rcu_read_unlock(); |
192 | nfnl_lock(); | 200 | nfnl_lock(subsys_id); |
193 | if (rcu_dereference_protected( | 201 | if (rcu_dereference_protected(table[subsys_id].subsys, |
194 | subsys_table[NFNL_SUBSYS_ID(type)], | 202 | lockdep_is_held(nfnl_get_lock(subsys_id))) != ss || |
195 | lockdep_is_held(&nfnl_mutex)) != ss || | ||
196 | nfnetlink_find_client(type, ss) != nc) | 203 | nfnetlink_find_client(type, ss) != nc) |
197 | err = -EAGAIN; | 204 | err = -EAGAIN; |
198 | else if (nc->call) | 205 | else if (nc->call) |
@@ -200,7 +207,7 @@ replay: | |||
200 | (const struct nlattr **)cda); | 207 | (const struct nlattr **)cda); |
201 | else | 208 | else |
202 | err = -EINVAL; | 209 | err = -EINVAL; |
203 | nfnl_unlock(); | 210 | nfnl_unlock(subsys_id); |
204 | } | 211 | } |
205 | if (err == -EAGAIN) | 212 | if (err == -EAGAIN) |
206 | goto replay; | 213 | goto replay; |
@@ -267,6 +274,11 @@ static struct pernet_operations nfnetlink_net_ops = { | |||
267 | 274 | ||
268 | static int __init nfnetlink_init(void) | 275 | static int __init nfnetlink_init(void) |
269 | { | 276 | { |
277 | int i; | ||
278 | |||
279 | for (i=0; i<NFNL_SUBSYS_COUNT; i++) | ||
280 | mutex_init(&table[i].mutex); | ||
281 | |||
270 | pr_info("Netfilter messages via NETLINK v%s.\n", nfversion); | 282 | pr_info("Netfilter messages via NETLINK v%s.\n", nfversion); |
271 | return register_pernet_subsys(&nfnetlink_net_ops); | 283 | return register_pernet_subsys(&nfnetlink_net_ops); |
272 | } | 284 | } |
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index bde009ed8d3b..a60261cb0e80 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c | |||
@@ -20,12 +20,8 @@ | |||
20 | #include <net/netfilter/nf_conntrack_timeout.h> | 20 | #include <net/netfilter/nf_conntrack_timeout.h> |
21 | #include <net/netfilter/nf_conntrack_zones.h> | 21 | #include <net/netfilter/nf_conntrack_zones.h> |
22 | 22 | ||
23 | static unsigned int xt_ct_target_v0(struct sk_buff *skb, | 23 | static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct) |
24 | const struct xt_action_param *par) | ||
25 | { | 24 | { |
26 | const struct xt_ct_target_info *info = par->targinfo; | ||
27 | struct nf_conn *ct = info->ct; | ||
28 | |||
29 | /* Previously seen (loopback)? Ignore. */ | 25 | /* Previously seen (loopback)? Ignore. */ |
30 | if (skb->nfct != NULL) | 26 | if (skb->nfct != NULL) |
31 | return XT_CONTINUE; | 27 | return XT_CONTINUE; |
@@ -37,21 +33,22 @@ static unsigned int xt_ct_target_v0(struct sk_buff *skb, | |||
37 | return XT_CONTINUE; | 33 | return XT_CONTINUE; |
38 | } | 34 | } |
39 | 35 | ||
40 | static unsigned int xt_ct_target_v1(struct sk_buff *skb, | 36 | static unsigned int xt_ct_target_v0(struct sk_buff *skb, |
41 | const struct xt_action_param *par) | 37 | const struct xt_action_param *par) |
42 | { | 38 | { |
43 | const struct xt_ct_target_info_v1 *info = par->targinfo; | 39 | const struct xt_ct_target_info *info = par->targinfo; |
44 | struct nf_conn *ct = info->ct; | 40 | struct nf_conn *ct = info->ct; |
45 | 41 | ||
46 | /* Previously seen (loopback)? Ignore. */ | 42 | return xt_ct_target(skb, ct); |
47 | if (skb->nfct != NULL) | 43 | } |
48 | return XT_CONTINUE; | ||
49 | 44 | ||
50 | atomic_inc(&ct->ct_general.use); | 45 | static unsigned int xt_ct_target_v1(struct sk_buff *skb, |
51 | skb->nfct = &ct->ct_general; | 46 | const struct xt_action_param *par) |
52 | skb->nfctinfo = IP_CT_NEW; | 47 | { |
48 | const struct xt_ct_target_info_v1 *info = par->targinfo; | ||
49 | struct nf_conn *ct = info->ct; | ||
53 | 50 | ||
54 | return XT_CONTINUE; | 51 | return xt_ct_target(skb, ct); |
55 | } | 52 | } |
56 | 53 | ||
57 | static u8 xt_ct_find_proto(const struct xt_tgchk_param *par) | 54 | static u8 xt_ct_find_proto(const struct xt_tgchk_param *par) |
@@ -104,67 +101,6 @@ xt_ct_set_helper(struct nf_conn *ct, const char *helper_name, | |||
104 | return 0; | 101 | return 0; |
105 | } | 102 | } |
106 | 103 | ||
107 | static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) | ||
108 | { | ||
109 | struct xt_ct_target_info *info = par->targinfo; | ||
110 | struct nf_conntrack_tuple t; | ||
111 | struct nf_conn *ct; | ||
112 | int ret = -EOPNOTSUPP; | ||
113 | |||
114 | if (info->flags & ~XT_CT_NOTRACK) | ||
115 | return -EINVAL; | ||
116 | |||
117 | if (info->flags & XT_CT_NOTRACK) { | ||
118 | ct = nf_ct_untracked_get(); | ||
119 | atomic_inc(&ct->ct_general.use); | ||
120 | goto out; | ||
121 | } | ||
122 | |||
123 | #ifndef CONFIG_NF_CONNTRACK_ZONES | ||
124 | if (info->zone) | ||
125 | goto err1; | ||
126 | #endif | ||
127 | |||
128 | ret = nf_ct_l3proto_try_module_get(par->family); | ||
129 | if (ret < 0) | ||
130 | goto err1; | ||
131 | |||
132 | memset(&t, 0, sizeof(t)); | ||
133 | ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL); | ||
134 | ret = PTR_ERR(ct); | ||
135 | if (IS_ERR(ct)) | ||
136 | goto err2; | ||
137 | |||
138 | ret = 0; | ||
139 | if ((info->ct_events || info->exp_events) && | ||
140 | !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events, | ||
141 | GFP_KERNEL)) | ||
142 | goto err3; | ||
143 | |||
144 | if (info->helper[0]) { | ||
145 | ret = xt_ct_set_helper(ct, info->helper, par); | ||
146 | if (ret < 0) | ||
147 | goto err3; | ||
148 | } | ||
149 | |||
150 | __set_bit(IPS_TEMPLATE_BIT, &ct->status); | ||
151 | __set_bit(IPS_CONFIRMED_BIT, &ct->status); | ||
152 | |||
153 | /* Overload tuple linked list to put us in template list. */ | ||
154 | hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, | ||
155 | &par->net->ct.tmpl); | ||
156 | out: | ||
157 | info->ct = ct; | ||
158 | return 0; | ||
159 | |||
160 | err3: | ||
161 | nf_conntrack_free(ct); | ||
162 | err2: | ||
163 | nf_ct_l3proto_module_put(par->family); | ||
164 | err1: | ||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | 104 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
169 | static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout) | 105 | static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout) |
170 | { | 106 | { |
@@ -242,16 +178,13 @@ out: | |||
242 | #endif | 178 | #endif |
243 | } | 179 | } |
244 | 180 | ||
245 | static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) | 181 | static int xt_ct_tg_check(const struct xt_tgchk_param *par, |
182 | struct xt_ct_target_info_v1 *info) | ||
246 | { | 183 | { |
247 | struct xt_ct_target_info_v1 *info = par->targinfo; | ||
248 | struct nf_conntrack_tuple t; | 184 | struct nf_conntrack_tuple t; |
249 | struct nf_conn *ct; | 185 | struct nf_conn *ct; |
250 | int ret = -EOPNOTSUPP; | 186 | int ret = -EOPNOTSUPP; |
251 | 187 | ||
252 | if (info->flags & ~XT_CT_NOTRACK) | ||
253 | return -EINVAL; | ||
254 | |||
255 | if (info->flags & XT_CT_NOTRACK) { | 188 | if (info->flags & XT_CT_NOTRACK) { |
256 | ct = nf_ct_untracked_get(); | 189 | ct = nf_ct_untracked_get(); |
257 | atomic_inc(&ct->ct_general.use); | 190 | atomic_inc(&ct->ct_general.use); |
@@ -309,20 +242,49 @@ err1: | |||
309 | return ret; | 242 | return ret; |
310 | } | 243 | } |
311 | 244 | ||
312 | static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par) | 245 | static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) |
313 | { | 246 | { |
314 | struct xt_ct_target_info *info = par->targinfo; | 247 | struct xt_ct_target_info *info = par->targinfo; |
315 | struct nf_conn *ct = info->ct; | 248 | struct xt_ct_target_info_v1 info_v1 = { |
316 | struct nf_conn_help *help; | 249 | .flags = info->flags, |
250 | .zone = info->zone, | ||
251 | .ct_events = info->ct_events, | ||
252 | .exp_events = info->exp_events, | ||
253 | }; | ||
254 | int ret; | ||
317 | 255 | ||
318 | if (!nf_ct_is_untracked(ct)) { | 256 | if (info->flags & ~XT_CT_NOTRACK) |
319 | help = nfct_help(ct); | 257 | return -EINVAL; |
320 | if (help) | ||
321 | module_put(help->helper->me); | ||
322 | 258 | ||
323 | nf_ct_l3proto_module_put(par->family); | 259 | memcpy(info_v1.helper, info->helper, sizeof(info->helper)); |
324 | } | 260 | |
325 | nf_ct_put(info->ct); | 261 | ret = xt_ct_tg_check(par, &info_v1); |
262 | if (ret < 0) | ||
263 | return ret; | ||
264 | |||
265 | info->ct = info_v1.ct; | ||
266 | |||
267 | return ret; | ||
268 | } | ||
269 | |||
270 | static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) | ||
271 | { | ||
272 | struct xt_ct_target_info_v1 *info = par->targinfo; | ||
273 | |||
274 | if (info->flags & ~XT_CT_NOTRACK) | ||
275 | return -EINVAL; | ||
276 | |||
277 | return xt_ct_tg_check(par, par->targinfo); | ||
278 | } | ||
279 | |||
280 | static int xt_ct_tg_check_v2(const struct xt_tgchk_param *par) | ||
281 | { | ||
282 | struct xt_ct_target_info_v1 *info = par->targinfo; | ||
283 | |||
284 | if (info->flags & ~XT_CT_MASK) | ||
285 | return -EINVAL; | ||
286 | |||
287 | return xt_ct_tg_check(par, par->targinfo); | ||
326 | } | 288 | } |
327 | 289 | ||
328 | static void xt_ct_destroy_timeout(struct nf_conn *ct) | 290 | static void xt_ct_destroy_timeout(struct nf_conn *ct) |
@@ -343,9 +305,9 @@ static void xt_ct_destroy_timeout(struct nf_conn *ct) | |||
343 | #endif | 305 | #endif |
344 | } | 306 | } |
345 | 307 | ||
346 | static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) | 308 | static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par, |
309 | struct xt_ct_target_info_v1 *info) | ||
347 | { | 310 | { |
348 | struct xt_ct_target_info_v1 *info = par->targinfo; | ||
349 | struct nf_conn *ct = info->ct; | 311 | struct nf_conn *ct = info->ct; |
350 | struct nf_conn_help *help; | 312 | struct nf_conn_help *help; |
351 | 313 | ||
@@ -361,6 +323,26 @@ static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) | |||
361 | nf_ct_put(info->ct); | 323 | nf_ct_put(info->ct); |
362 | } | 324 | } |
363 | 325 | ||
326 | static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par) | ||
327 | { | ||
328 | struct xt_ct_target_info *info = par->targinfo; | ||
329 | struct xt_ct_target_info_v1 info_v1 = { | ||
330 | .flags = info->flags, | ||
331 | .zone = info->zone, | ||
332 | .ct_events = info->ct_events, | ||
333 | .exp_events = info->exp_events, | ||
334 | .ct = info->ct, | ||
335 | }; | ||
336 | memcpy(info_v1.helper, info->helper, sizeof(info->helper)); | ||
337 | |||
338 | xt_ct_tg_destroy(par, &info_v1); | ||
339 | } | ||
340 | |||
341 | static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) | ||
342 | { | ||
343 | xt_ct_tg_destroy(par, par->targinfo); | ||
344 | } | ||
345 | |||
364 | static struct xt_target xt_ct_tg_reg[] __read_mostly = { | 346 | static struct xt_target xt_ct_tg_reg[] __read_mostly = { |
365 | { | 347 | { |
366 | .name = "CT", | 348 | .name = "CT", |
@@ -383,6 +365,17 @@ static struct xt_target xt_ct_tg_reg[] __read_mostly = { | |||
383 | .table = "raw", | 365 | .table = "raw", |
384 | .me = THIS_MODULE, | 366 | .me = THIS_MODULE, |
385 | }, | 367 | }, |
368 | { | ||
369 | .name = "CT", | ||
370 | .family = NFPROTO_UNSPEC, | ||
371 | .revision = 2, | ||
372 | .targetsize = sizeof(struct xt_ct_target_info_v1), | ||
373 | .checkentry = xt_ct_tg_check_v2, | ||
374 | .destroy = xt_ct_tg_destroy_v1, | ||
375 | .target = xt_ct_target_v1, | ||
376 | .table = "raw", | ||
377 | .me = THIS_MODULE, | ||
378 | }, | ||
386 | }; | 379 | }; |
387 | 380 | ||
388 | static unsigned int | 381 | static unsigned int |