diff options
| author | Jeff Garzik <jgarzik@pobox.com> | 2005-09-08 05:37:58 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-08 05:37:58 -0400 |
| commit | 5a2cec83a9bb1b4295aa8ab728fcb8ca1811a33c (patch) | |
| tree | 2f83dc6949763e77cf6422e696dc6146684dcf4e /net/ipv4 | |
| parent | f2c853bca542f5ac0b036377637192a74f2091c2 (diff) | |
| parent | caf39e87cc1182f7dae84eefc43ca14d54c78ef9 (diff) | |
Merge /spare/repo/linux-2.6/
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 9e6e683cc34d..e7d26d9943c2 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 e046f5521814..30aa8e2ee214 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 a7bd38f50522..1ba0db746817 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 be4c9eb3243f..dc20881004bc 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 a0648600190e..19cba16e6e1e 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 3a2627db1729..1b79ec36085f 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 25438eec21a1..d7a8a98c05e1 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 000000000000..2b5cf9c51309 --- /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 a4e9278db4ed..15aef3564742 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 f23ef1f88c46..1985abc59d24 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 ee5895afd0c3..ae3e3e655db5 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 f8ff170f390a..d2b590533452 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 60d70fa41a15..cb66b8bddeb3 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 89db052add81..0ff368b131f6 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, |
