diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/ip_fragment.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/Kconfig | 20 | ||||
-rw-r--r-- | net/ipv4/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_amanda.c | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_core.c | 38 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_ftp.c | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_irc.c | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_netbios_ns.c | 131 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_netlink.c | 13 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_proto_tcp.c | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_standalone.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_tftp.c | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_rule.c | 21 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_standalone.c | 8 |
14 files changed, 213 insertions, 28 deletions
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 9e6e683cc3..e7d26d9943 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -457,7 +457,7 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
457 | 457 | ||
458 | if (pskb_pull(skb, ihl) == NULL) | 458 | if (pskb_pull(skb, ihl) == NULL) |
459 | goto err; | 459 | goto err; |
460 | if (pskb_trim(skb, end-offset)) | 460 | if (pskb_trim_rcsum(skb, end-offset)) |
461 | goto err; | 461 | goto err; |
462 | 462 | ||
463 | /* Find out which fragments are in front and at the back of us | 463 | /* Find out which fragments are in front and at the back of us |
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index e046f55218..30aa8e2ee2 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -34,6 +34,7 @@ config IP_NF_CT_ACCT | |||
34 | 34 | ||
35 | config IP_NF_CONNTRACK_MARK | 35 | config IP_NF_CONNTRACK_MARK |
36 | bool 'Connection mark tracking support' | 36 | bool 'Connection mark tracking support' |
37 | depends on IP_NF_CONNTRACK | ||
37 | help | 38 | help |
38 | This option enables support for connection marks, used by the | 39 | This option enables support for connection marks, used by the |
39 | `CONNMARK' target and `connmark' match. Similar to the mark value | 40 | `CONNMARK' target and `connmark' match. Similar to the mark value |
@@ -85,6 +86,25 @@ config IP_NF_IRC | |||
85 | 86 | ||
86 | To compile it as a module, choose M here. If unsure, say Y. | 87 | To compile it as a module, choose M here. If unsure, say Y. |
87 | 88 | ||
89 | config IP_NF_NETBIOS_NS | ||
90 | tristate "NetBIOS name service protocol support (EXPERIMENTAL)" | ||
91 | depends on IP_NF_CONNTRACK && EXPERIMENTAL | ||
92 | help | ||
93 | NetBIOS name service requests are sent as broadcast messages from an | ||
94 | unprivileged port and responded to with unicast messages to the | ||
95 | same port. This make them hard to firewall properly because connection | ||
96 | tracking doesn't deal with broadcasts. This helper tracks locally | ||
97 | originating NetBIOS name service requests and the corresponding | ||
98 | responses. It relies on correct IP address configuration, specifically | ||
99 | netmask and broadcast address. When properly configured, the output | ||
100 | of "ip address show" should look similar to this: | ||
101 | |||
102 | $ ip -4 address show eth0 | ||
103 | 4: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 1000 | ||
104 | inet 172.16.2.252/24 brd 172.16.2.255 scope global eth0 | ||
105 | |||
106 | To compile it as a module, choose M here. If unsure, say N. | ||
107 | |||
88 | config IP_NF_TFTP | 108 | config IP_NF_TFTP |
89 | tristate "TFTP protocol support" | 109 | tristate "TFTP protocol support" |
90 | depends on IP_NF_CONNTRACK | 110 | depends on IP_NF_CONNTRACK |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index a7bd38f505..1ba0db7468 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
@@ -21,6 +21,7 @@ obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o | |||
21 | obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o | 21 | obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o |
22 | obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o | 22 | obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o |
23 | obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o | 23 | obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o |
24 | obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o | ||
24 | 25 | ||
25 | # NAT helpers | 26 | # NAT helpers |
26 | obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o | 27 | obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o |
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c index be4c9eb324..dc20881004 100644 --- a/net/ipv4/netfilter/ip_conntrack_amanda.c +++ b/net/ipv4/netfilter/ip_conntrack_amanda.c | |||
@@ -108,6 +108,7 @@ static int help(struct sk_buff **pskb, | |||
108 | } | 108 | } |
109 | 109 | ||
110 | exp->expectfn = NULL; | 110 | exp->expectfn = NULL; |
111 | exp->flags = 0; | ||
111 | 112 | ||
112 | exp->tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; | 113 | exp->tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; |
113 | exp->tuple.src.u.tcp.port = 0; | 114 | exp->tuple.src.u.tcp.port = 0; |
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index a064860019..19cba16e6e 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c | |||
@@ -197,7 +197,7 @@ ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse, | |||
197 | 197 | ||
198 | 198 | ||
199 | /* ip_conntrack_expect helper functions */ | 199 | /* ip_conntrack_expect helper functions */ |
200 | static void unlink_expect(struct ip_conntrack_expect *exp) | 200 | void ip_ct_unlink_expect(struct ip_conntrack_expect *exp) |
201 | { | 201 | { |
202 | ASSERT_WRITE_LOCK(&ip_conntrack_lock); | 202 | ASSERT_WRITE_LOCK(&ip_conntrack_lock); |
203 | IP_NF_ASSERT(!timer_pending(&exp->timeout)); | 203 | IP_NF_ASSERT(!timer_pending(&exp->timeout)); |
@@ -207,18 +207,12 @@ static void unlink_expect(struct ip_conntrack_expect *exp) | |||
207 | ip_conntrack_expect_put(exp); | 207 | ip_conntrack_expect_put(exp); |
208 | } | 208 | } |
209 | 209 | ||
210 | void __ip_ct_expect_unlink_destroy(struct ip_conntrack_expect *exp) | ||
211 | { | ||
212 | unlink_expect(exp); | ||
213 | ip_conntrack_expect_put(exp); | ||
214 | } | ||
215 | |||
216 | static void expectation_timed_out(unsigned long ul_expect) | 210 | static void expectation_timed_out(unsigned long ul_expect) |
217 | { | 211 | { |
218 | struct ip_conntrack_expect *exp = (void *)ul_expect; | 212 | struct ip_conntrack_expect *exp = (void *)ul_expect; |
219 | 213 | ||
220 | write_lock_bh(&ip_conntrack_lock); | 214 | write_lock_bh(&ip_conntrack_lock); |
221 | unlink_expect(exp); | 215 | ip_ct_unlink_expect(exp); |
222 | write_unlock_bh(&ip_conntrack_lock); | 216 | write_unlock_bh(&ip_conntrack_lock); |
223 | ip_conntrack_expect_put(exp); | 217 | ip_conntrack_expect_put(exp); |
224 | } | 218 | } |
@@ -264,10 +258,14 @@ find_expectation(const struct ip_conntrack_tuple *tuple) | |||
264 | master ct never got confirmed, we'd hold a reference to it | 258 | master ct never got confirmed, we'd hold a reference to it |
265 | and weird things would happen to future packets). */ | 259 | and weird things would happen to future packets). */ |
266 | if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) | 260 | if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) |
267 | && is_confirmed(i->master) | 261 | && is_confirmed(i->master)) { |
268 | && del_timer(&i->timeout)) { | 262 | if (i->flags & IP_CT_EXPECT_PERMANENT) { |
269 | unlink_expect(i); | 263 | atomic_inc(&i->use); |
270 | return i; | 264 | return i; |
265 | } else if (del_timer(&i->timeout)) { | ||
266 | ip_ct_unlink_expect(i); | ||
267 | return i; | ||
268 | } | ||
271 | } | 269 | } |
272 | } | 270 | } |
273 | return NULL; | 271 | return NULL; |
@@ -284,7 +282,7 @@ void ip_ct_remove_expectations(struct ip_conntrack *ct) | |||
284 | 282 | ||
285 | list_for_each_entry_safe(i, tmp, &ip_conntrack_expect_list, list) { | 283 | list_for_each_entry_safe(i, tmp, &ip_conntrack_expect_list, list) { |
286 | if (i->master == ct && del_timer(&i->timeout)) { | 284 | if (i->master == ct && del_timer(&i->timeout)) { |
287 | unlink_expect(i); | 285 | ip_ct_unlink_expect(i); |
288 | ip_conntrack_expect_put(i); | 286 | ip_conntrack_expect_put(i); |
289 | } | 287 | } |
290 | } | 288 | } |
@@ -925,7 +923,7 @@ void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp) | |||
925 | /* choose the the oldest expectation to evict */ | 923 | /* choose the the oldest expectation to evict */ |
926 | list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) { | 924 | list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) { |
927 | if (expect_matches(i, exp) && del_timer(&i->timeout)) { | 925 | if (expect_matches(i, exp) && del_timer(&i->timeout)) { |
928 | unlink_expect(i); | 926 | ip_ct_unlink_expect(i); |
929 | write_unlock_bh(&ip_conntrack_lock); | 927 | write_unlock_bh(&ip_conntrack_lock); |
930 | ip_conntrack_expect_put(i); | 928 | ip_conntrack_expect_put(i); |
931 | return; | 929 | return; |
@@ -934,6 +932,9 @@ void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp) | |||
934 | write_unlock_bh(&ip_conntrack_lock); | 932 | write_unlock_bh(&ip_conntrack_lock); |
935 | } | 933 | } |
936 | 934 | ||
935 | /* We don't increase the master conntrack refcount for non-fulfilled | ||
936 | * conntracks. During the conntrack destruction, the expectations are | ||
937 | * always killed before the conntrack itself */ | ||
937 | struct ip_conntrack_expect *ip_conntrack_expect_alloc(struct ip_conntrack *me) | 938 | struct ip_conntrack_expect *ip_conntrack_expect_alloc(struct ip_conntrack *me) |
938 | { | 939 | { |
939 | struct ip_conntrack_expect *new; | 940 | struct ip_conntrack_expect *new; |
@@ -944,17 +945,14 @@ struct ip_conntrack_expect *ip_conntrack_expect_alloc(struct ip_conntrack *me) | |||
944 | return NULL; | 945 | return NULL; |
945 | } | 946 | } |
946 | new->master = me; | 947 | new->master = me; |
947 | atomic_inc(&new->master->ct_general.use); | ||
948 | atomic_set(&new->use, 1); | 948 | atomic_set(&new->use, 1); |
949 | return new; | 949 | return new; |
950 | } | 950 | } |
951 | 951 | ||
952 | void ip_conntrack_expect_put(struct ip_conntrack_expect *exp) | 952 | void ip_conntrack_expect_put(struct ip_conntrack_expect *exp) |
953 | { | 953 | { |
954 | if (atomic_dec_and_test(&exp->use)) { | 954 | if (atomic_dec_and_test(&exp->use)) |
955 | ip_conntrack_put(exp->master); | ||
956 | kmem_cache_free(ip_conntrack_expect_cachep, exp); | 955 | kmem_cache_free(ip_conntrack_expect_cachep, exp); |
957 | } | ||
958 | } | 956 | } |
959 | 957 | ||
960 | static void ip_conntrack_expect_insert(struct ip_conntrack_expect *exp) | 958 | static void ip_conntrack_expect_insert(struct ip_conntrack_expect *exp) |
@@ -982,7 +980,7 @@ static void evict_oldest_expect(struct ip_conntrack *master) | |||
982 | list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) { | 980 | list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) { |
983 | if (i->master == master) { | 981 | if (i->master == master) { |
984 | if (del_timer(&i->timeout)) { | 982 | if (del_timer(&i->timeout)) { |
985 | unlink_expect(i); | 983 | ip_ct_unlink_expect(i); |
986 | ip_conntrack_expect_put(i); | 984 | ip_conntrack_expect_put(i); |
987 | } | 985 | } |
988 | break; | 986 | break; |
@@ -1099,7 +1097,7 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me) | |||
1099 | /* Get rid of expectations */ | 1097 | /* Get rid of expectations */ |
1100 | list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list, list) { | 1098 | list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list, list) { |
1101 | if (exp->master->helper == me && del_timer(&exp->timeout)) { | 1099 | if (exp->master->helper == me && del_timer(&exp->timeout)) { |
1102 | unlink_expect(exp); | 1100 | ip_ct_unlink_expect(exp); |
1103 | ip_conntrack_expect_put(exp); | 1101 | ip_conntrack_expect_put(exp); |
1104 | } | 1102 | } |
1105 | } | 1103 | } |
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c index 3a2627db17..1b79ec3608 100644 --- a/net/ipv4/netfilter/ip_conntrack_ftp.c +++ b/net/ipv4/netfilter/ip_conntrack_ftp.c | |||
@@ -421,6 +421,7 @@ static int help(struct sk_buff **pskb, | |||
421 | { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }}); | 421 | { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }}); |
422 | 422 | ||
423 | exp->expectfn = NULL; | 423 | exp->expectfn = NULL; |
424 | exp->flags = 0; | ||
424 | 425 | ||
425 | /* Now, NAT might want to mangle the packet, and register the | 426 | /* Now, NAT might want to mangle the packet, and register the |
426 | * (possibly changed) expectation itself. */ | 427 | * (possibly changed) expectation itself. */ |
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c index 25438eec21..d7a8a98c05 100644 --- a/net/ipv4/netfilter/ip_conntrack_irc.c +++ b/net/ipv4/netfilter/ip_conntrack_irc.c | |||
@@ -221,6 +221,7 @@ static int help(struct sk_buff **pskb, | |||
221 | { { 0, { 0 } }, | 221 | { { 0, { 0 } }, |
222 | { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }}); | 222 | { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }}); |
223 | exp->expectfn = NULL; | 223 | exp->expectfn = NULL; |
224 | exp->flags = 0; | ||
224 | if (ip_nat_irc_hook) | 225 | if (ip_nat_irc_hook) |
225 | ret = ip_nat_irc_hook(pskb, ctinfo, | 226 | ret = ip_nat_irc_hook(pskb, ctinfo, |
226 | addr_beg_p - ib_ptr, | 227 | addr_beg_p - ib_ptr, |
diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c new file mode 100644 index 0000000000..2b5cf9c513 --- /dev/null +++ b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * NetBIOS name service broadcast connection tracking helper | ||
3 | * | ||
4 | * (c) 2005 Patrick McHardy <kaber@trash.net> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | /* | ||
12 | * This helper tracks locally originating NetBIOS name service | ||
13 | * requests by issuing permanent expectations (valid until | ||
14 | * timing out) matching all reply connections from the | ||
15 | * destination network. The only NetBIOS specific thing is | ||
16 | * actually the port number. | ||
17 | */ | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/skbuff.h> | ||
22 | #include <linux/netdevice.h> | ||
23 | #include <linux/inetdevice.h> | ||
24 | #include <linux/in.h> | ||
25 | #include <linux/ip.h> | ||
26 | #include <linux/udp.h> | ||
27 | #include <net/route.h> | ||
28 | |||
29 | #include <linux/netfilter.h> | ||
30 | #include <linux/netfilter_ipv4.h> | ||
31 | #include <linux/netfilter_ipv4/ip_conntrack.h> | ||
32 | #include <linux/netfilter_ipv4/ip_conntrack_helper.h> | ||
33 | |||
34 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
35 | MODULE_DESCRIPTION("NetBIOS name service broadcast connection tracking helper"); | ||
36 | MODULE_LICENSE("GPL"); | ||
37 | |||
38 | static unsigned int timeout = 3; | ||
39 | module_param(timeout, int, 0600); | ||
40 | MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds"); | ||
41 | |||
42 | static int help(struct sk_buff **pskb, | ||
43 | struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) | ||
44 | { | ||
45 | struct ip_conntrack_expect *exp; | ||
46 | struct iphdr *iph = (*pskb)->nh.iph; | ||
47 | struct udphdr _uh, *uh; | ||
48 | struct rtable *rt = (struct rtable *)(*pskb)->dst; | ||
49 | struct in_device *in_dev; | ||
50 | u_int32_t mask = 0; | ||
51 | |||
52 | /* we're only interested in locally generated packets */ | ||
53 | if ((*pskb)->sk == NULL) | ||
54 | goto out; | ||
55 | if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST)) | ||
56 | goto out; | ||
57 | if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) | ||
58 | goto out; | ||
59 | |||
60 | rcu_read_lock(); | ||
61 | in_dev = __in_dev_get(rt->u.dst.dev); | ||
62 | if (in_dev != NULL) { | ||
63 | for_primary_ifa(in_dev) { | ||
64 | if (ifa->ifa_broadcast == iph->daddr) { | ||
65 | mask = ifa->ifa_mask; | ||
66 | break; | ||
67 | } | ||
68 | } endfor_ifa(in_dev); | ||
69 | } | ||
70 | rcu_read_unlock(); | ||
71 | |||
72 | if (mask == 0) | ||
73 | goto out; | ||
74 | |||
75 | uh = skb_header_pointer(*pskb, iph->ihl * 4, sizeof(_uh), &_uh); | ||
76 | BUG_ON(uh == NULL); | ||
77 | |||
78 | exp = ip_conntrack_expect_alloc(ct); | ||
79 | if (exp == NULL) | ||
80 | goto out; | ||
81 | memset(&exp->tuple, 0, sizeof(exp->tuple)); | ||
82 | exp->tuple.src.ip = iph->daddr & mask; | ||
83 | exp->tuple.dst.ip = iph->saddr; | ||
84 | exp->tuple.dst.u.udp.port = uh->source; | ||
85 | exp->tuple.dst.protonum = IPPROTO_UDP; | ||
86 | |||
87 | memset(&exp->mask, 0, sizeof(exp->mask)); | ||
88 | exp->mask.src.ip = mask; | ||
89 | exp->mask.dst.ip = 0xFFFFFFFF; | ||
90 | exp->mask.dst.u.udp.port = 0xFFFF; | ||
91 | exp->mask.dst.protonum = 0xFF; | ||
92 | |||
93 | exp->expectfn = NULL; | ||
94 | exp->flags = IP_CT_EXPECT_PERMANENT; | ||
95 | |||
96 | ip_conntrack_expect_related(exp); | ||
97 | ip_conntrack_expect_put(exp); | ||
98 | |||
99 | ip_ct_refresh_acct(ct, ctinfo, NULL, timeout * HZ); | ||
100 | out: | ||
101 | return NF_ACCEPT; | ||
102 | } | ||
103 | |||
104 | static struct ip_conntrack_helper helper = { | ||
105 | .name = "netbios-ns", | ||
106 | .tuple = { | ||
107 | .src.u.udp.port = __constant_htons(137), | ||
108 | .dst.protonum = IPPROTO_UDP, | ||
109 | }, | ||
110 | .mask = { | ||
111 | .src.u.udp.port = 0xFFFF, | ||
112 | .dst.protonum = 0xFF, | ||
113 | }, | ||
114 | .max_expected = 1, | ||
115 | .me = THIS_MODULE, | ||
116 | .help = help, | ||
117 | }; | ||
118 | |||
119 | static int __init init(void) | ||
120 | { | ||
121 | helper.timeout = timeout; | ||
122 | return ip_conntrack_helper_register(&helper); | ||
123 | } | ||
124 | |||
125 | static void __exit fini(void) | ||
126 | { | ||
127 | ip_conntrack_helper_unregister(&helper); | ||
128 | } | ||
129 | |||
130 | module_init(init); | ||
131 | module_exit(fini); | ||
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index a4e9278db4..15aef35647 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c | |||
@@ -1349,8 +1349,10 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1349 | list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list, | 1349 | list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list, |
1350 | list) { | 1350 | list) { |
1351 | if (exp->master->helper == h | 1351 | if (exp->master->helper == h |
1352 | && del_timer(&exp->timeout)) | 1352 | && del_timer(&exp->timeout)) { |
1353 | __ip_ct_expect_unlink_destroy(exp); | 1353 | ip_ct_unlink_expect(exp); |
1354 | ip_conntrack_expect_put(exp); | ||
1355 | } | ||
1354 | } | 1356 | } |
1355 | write_unlock(&ip_conntrack_lock); | 1357 | write_unlock(&ip_conntrack_lock); |
1356 | } else { | 1358 | } else { |
@@ -1358,8 +1360,10 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1358 | write_lock_bh(&ip_conntrack_lock); | 1360 | write_lock_bh(&ip_conntrack_lock); |
1359 | list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list, | 1361 | list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list, |
1360 | list) { | 1362 | list) { |
1361 | if (del_timer(&exp->timeout)) | 1363 | if (del_timer(&exp->timeout)) { |
1362 | __ip_ct_expect_unlink_destroy(exp); | 1364 | ip_ct_unlink_expect(exp); |
1365 | ip_conntrack_expect_put(exp); | ||
1366 | } | ||
1363 | } | 1367 | } |
1364 | write_unlock_bh(&ip_conntrack_lock); | 1368 | write_unlock_bh(&ip_conntrack_lock); |
1365 | } | 1369 | } |
@@ -1413,6 +1417,7 @@ ctnetlink_create_expect(struct nfattr *cda[]) | |||
1413 | } | 1417 | } |
1414 | 1418 | ||
1415 | exp->expectfn = NULL; | 1419 | exp->expectfn = NULL; |
1420 | exp->flags = 0; | ||
1416 | exp->master = ct; | 1421 | exp->master = ct; |
1417 | memcpy(&exp->tuple, &tuple, sizeof(struct ip_conntrack_tuple)); | 1422 | memcpy(&exp->tuple, &tuple, sizeof(struct ip_conntrack_tuple)); |
1418 | memcpy(&exp->mask, &mask, sizeof(struct ip_conntrack_tuple)); | 1423 | memcpy(&exp->mask, &mask, sizeof(struct ip_conntrack_tuple)); |
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index f23ef1f88c..1985abc59d 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c | |||
@@ -349,6 +349,7 @@ static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa, | |||
349 | return 0; | 349 | return 0; |
350 | 350 | ||
351 | nfattr_failure: | 351 | nfattr_failure: |
352 | read_unlock_bh(&tcp_lock); | ||
352 | return -1; | 353 | return -1; |
353 | } | 354 | } |
354 | #endif | 355 | #endif |
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index ee5895afd0..ae3e3e655d 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c | |||
@@ -998,7 +998,7 @@ EXPORT_SYMBOL(ip_conntrack_expect_related); | |||
998 | EXPORT_SYMBOL(ip_conntrack_unexpect_related); | 998 | EXPORT_SYMBOL(ip_conntrack_unexpect_related); |
999 | EXPORT_SYMBOL_GPL(ip_conntrack_expect_list); | 999 | EXPORT_SYMBOL_GPL(ip_conntrack_expect_list); |
1000 | EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find); | 1000 | EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find); |
1001 | EXPORT_SYMBOL_GPL(__ip_ct_expect_unlink_destroy); | 1001 | EXPORT_SYMBOL_GPL(ip_ct_unlink_expect); |
1002 | 1002 | ||
1003 | EXPORT_SYMBOL(ip_conntrack_tuple_taken); | 1003 | EXPORT_SYMBOL(ip_conntrack_tuple_taken); |
1004 | EXPORT_SYMBOL(ip_ct_gather_frags); | 1004 | EXPORT_SYMBOL(ip_ct_gather_frags); |
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c index f8ff170f39..d2b5905334 100644 --- a/net/ipv4/netfilter/ip_conntrack_tftp.c +++ b/net/ipv4/netfilter/ip_conntrack_tftp.c | |||
@@ -75,6 +75,7 @@ static int tftp_help(struct sk_buff **pskb, | |||
75 | exp->mask.dst.u.udp.port = 0xffff; | 75 | exp->mask.dst.u.udp.port = 0xffff; |
76 | exp->mask.dst.protonum = 0xff; | 76 | exp->mask.dst.protonum = 0xff; |
77 | exp->expectfn = NULL; | 77 | exp->expectfn = NULL; |
78 | exp->flags = 0; | ||
78 | 79 | ||
79 | DEBUGP("expect: "); | 80 | DEBUGP("expect: "); |
80 | DUMP_TUPLE(&exp->tuple); | 81 | DUMP_TUPLE(&exp->tuple); |
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c index 60d70fa41a..cb66b8bdde 100644 --- a/net/ipv4/netfilter/ip_nat_rule.c +++ b/net/ipv4/netfilter/ip_nat_rule.c | |||
@@ -255,6 +255,27 @@ alloc_null_binding(struct ip_conntrack *conntrack, | |||
255 | return ip_nat_setup_info(conntrack, &range, hooknum); | 255 | return ip_nat_setup_info(conntrack, &range, hooknum); |
256 | } | 256 | } |
257 | 257 | ||
258 | unsigned int | ||
259 | alloc_null_binding_confirmed(struct ip_conntrack *conntrack, | ||
260 | struct ip_nat_info *info, | ||
261 | unsigned int hooknum) | ||
262 | { | ||
263 | u_int32_t ip | ||
264 | = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC | ||
265 | ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip | ||
266 | : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip); | ||
267 | u_int16_t all | ||
268 | = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC | ||
269 | ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all | ||
270 | : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.all); | ||
271 | struct ip_nat_range range | ||
272 | = { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } }; | ||
273 | |||
274 | DEBUGP("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n", | ||
275 | conntrack, NIPQUAD(ip)); | ||
276 | return ip_nat_setup_info(conntrack, &range, hooknum); | ||
277 | } | ||
278 | |||
258 | int ip_nat_rule_find(struct sk_buff **pskb, | 279 | int ip_nat_rule_find(struct sk_buff **pskb, |
259 | unsigned int hooknum, | 280 | unsigned int hooknum, |
260 | const struct net_device *in, | 281 | const struct net_device *in, |
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 89db052add..0ff368b131 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c | |||
@@ -123,8 +123,12 @@ ip_nat_fn(unsigned int hooknum, | |||
123 | if (!ip_nat_initialized(ct, maniptype)) { | 123 | if (!ip_nat_initialized(ct, maniptype)) { |
124 | unsigned int ret; | 124 | unsigned int ret; |
125 | 125 | ||
126 | /* LOCAL_IN hook doesn't have a chain! */ | 126 | if (unlikely(is_confirmed(ct))) |
127 | if (hooknum == NF_IP_LOCAL_IN) | 127 | /* NAT module was loaded late */ |
128 | ret = alloc_null_binding_confirmed(ct, info, | ||
129 | hooknum); | ||
130 | else if (hooknum == NF_IP_LOCAL_IN) | ||
131 | /* LOCAL_IN hook doesn't have a chain! */ | ||
128 | ret = alloc_null_binding(ct, info, hooknum); | 132 | ret = alloc_null_binding(ct, info, hooknum); |
129 | else | 133 | else |
130 | ret = ip_nat_rule_find(pskb, hooknum, | 134 | ret = ip_nat_rule_find(pskb, hooknum, |