diff options
-rw-r--r-- | include/net/netfilter/ipv4/nf_defrag_ipv4.h | 6 | ||||
-rw-r--r-- | net/ipv4/netfilter/Kconfig | 5 | ||||
-rw-r--r-- | net/ipv4/netfilter/Makefile | 3 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 56 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_defrag_ipv4.c | 96 |
5 files changed, 113 insertions, 53 deletions
diff --git a/include/net/netfilter/ipv4/nf_defrag_ipv4.h b/include/net/netfilter/ipv4/nf_defrag_ipv4.h new file mode 100644 index 00000000000..6b00ea38546 --- /dev/null +++ b/include/net/netfilter/ipv4/nf_defrag_ipv4.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _NF_DEFRAG_IPV4_H | ||
2 | #define _NF_DEFRAG_IPV4_H | ||
3 | |||
4 | extern void nf_defrag_ipv4_enable(void); | ||
5 | |||
6 | #endif /* _NF_DEFRAG_IPV4_H */ | ||
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 4e842d56642..07757ac8d5d 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -5,10 +5,15 @@ | |||
5 | menu "IP: Netfilter Configuration" | 5 | menu "IP: Netfilter Configuration" |
6 | depends on INET && NETFILTER | 6 | depends on INET && NETFILTER |
7 | 7 | ||
8 | config NF_DEFRAG_IPV4 | ||
9 | tristate | ||
10 | default n | ||
11 | |||
8 | config NF_CONNTRACK_IPV4 | 12 | config NF_CONNTRACK_IPV4 |
9 | tristate "IPv4 connection tracking support (required for NAT)" | 13 | tristate "IPv4 connection tracking support (required for NAT)" |
10 | depends on NF_CONNTRACK | 14 | depends on NF_CONNTRACK |
11 | default m if NETFILTER_ADVANCED=n | 15 | default m if NETFILTER_ADVANCED=n |
16 | select NF_DEFRAG_IPV4 | ||
12 | ---help--- | 17 | ---help--- |
13 | Connection tracking keeps a record of what packets have passed | 18 | Connection tracking keeps a record of what packets have passed |
14 | through your machine, in order to figure out how they are related | 19 | through your machine, in order to figure out how they are related |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 1107edbe478..5f9b650d90f 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
@@ -18,6 +18,9 @@ obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o | |||
18 | 18 | ||
19 | obj-$(CONFIG_NF_NAT) += nf_nat.o | 19 | obj-$(CONFIG_NF_NAT) += nf_nat.o |
20 | 20 | ||
21 | # defrag | ||
22 | obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o | ||
23 | |||
21 | # NAT helpers (nf_conntrack) | 24 | # NAT helpers (nf_conntrack) |
22 | obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o | 25 | obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o |
23 | obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o | 26 | obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index af69acc1d0f..4a7c3527539 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -1,3 +1,4 @@ | |||
1 | |||
1 | /* (C) 1999-2001 Paul `Rusty' Russell | 2 | /* (C) 1999-2001 Paul `Rusty' Russell |
2 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> | 3 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> |
3 | * | 4 | * |
@@ -24,6 +25,7 @@ | |||
24 | #include <net/netfilter/nf_conntrack_core.h> | 25 | #include <net/netfilter/nf_conntrack_core.h> |
25 | #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> | 26 | #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> |
26 | #include <net/netfilter/nf_nat_helper.h> | 27 | #include <net/netfilter/nf_nat_helper.h> |
28 | #include <net/netfilter/ipv4/nf_defrag_ipv4.h> | ||
27 | 29 | ||
28 | int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb, | 30 | int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb, |
29 | struct nf_conn *ct, | 31 | struct nf_conn *ct, |
@@ -63,23 +65,6 @@ static int ipv4_print_tuple(struct seq_file *s, | |||
63 | NIPQUAD(tuple->dst.u3.ip)); | 65 | NIPQUAD(tuple->dst.u3.ip)); |
64 | } | 66 | } |
65 | 67 | ||
66 | /* Returns new sk_buff, or NULL */ | ||
67 | static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) | ||
68 | { | ||
69 | int err; | ||
70 | |||
71 | skb_orphan(skb); | ||
72 | |||
73 | local_bh_disable(); | ||
74 | err = ip_defrag(skb, user); | ||
75 | local_bh_enable(); | ||
76 | |||
77 | if (!err) | ||
78 | ip_send_check(ip_hdr(skb)); | ||
79 | |||
80 | return err; | ||
81 | } | ||
82 | |||
83 | static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, | 68 | static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, |
84 | unsigned int *dataoff, u_int8_t *protonum) | 69 | unsigned int *dataoff, u_int8_t *protonum) |
85 | { | 70 | { |
@@ -144,28 +129,6 @@ out: | |||
144 | return nf_conntrack_confirm(skb); | 129 | return nf_conntrack_confirm(skb); |
145 | } | 130 | } |
146 | 131 | ||
147 | static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, | ||
148 | struct sk_buff *skb, | ||
149 | const struct net_device *in, | ||
150 | const struct net_device *out, | ||
151 | int (*okfn)(struct sk_buff *)) | ||
152 | { | ||
153 | /* Previously seen (loopback)? Ignore. Do this before | ||
154 | fragment check. */ | ||
155 | if (skb->nfct) | ||
156 | return NF_ACCEPT; | ||
157 | |||
158 | /* Gather fragments. */ | ||
159 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { | ||
160 | if (nf_ct_ipv4_gather_frags(skb, | ||
161 | hooknum == NF_INET_PRE_ROUTING ? | ||
162 | IP_DEFRAG_CONNTRACK_IN : | ||
163 | IP_DEFRAG_CONNTRACK_OUT)) | ||
164 | return NF_STOLEN; | ||
165 | } | ||
166 | return NF_ACCEPT; | ||
167 | } | ||
168 | |||
169 | static unsigned int ipv4_conntrack_in(unsigned int hooknum, | 132 | static unsigned int ipv4_conntrack_in(unsigned int hooknum, |
170 | struct sk_buff *skb, | 133 | struct sk_buff *skb, |
171 | const struct net_device *in, | 134 | const struct net_device *in, |
@@ -195,13 +158,6 @@ static unsigned int ipv4_conntrack_local(unsigned int hooknum, | |||
195 | make it the first hook. */ | 158 | make it the first hook. */ |
196 | static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = { | 159 | static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = { |
197 | { | 160 | { |
198 | .hook = ipv4_conntrack_defrag, | ||
199 | .owner = THIS_MODULE, | ||
200 | .pf = PF_INET, | ||
201 | .hooknum = NF_INET_PRE_ROUTING, | ||
202 | .priority = NF_IP_PRI_CONNTRACK_DEFRAG, | ||
203 | }, | ||
204 | { | ||
205 | .hook = ipv4_conntrack_in, | 161 | .hook = ipv4_conntrack_in, |
206 | .owner = THIS_MODULE, | 162 | .owner = THIS_MODULE, |
207 | .pf = PF_INET, | 163 | .pf = PF_INET, |
@@ -209,13 +165,6 @@ static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = { | |||
209 | .priority = NF_IP_PRI_CONNTRACK, | 165 | .priority = NF_IP_PRI_CONNTRACK, |
210 | }, | 166 | }, |
211 | { | 167 | { |
212 | .hook = ipv4_conntrack_defrag, | ||
213 | .owner = THIS_MODULE, | ||
214 | .pf = PF_INET, | ||
215 | .hooknum = NF_INET_LOCAL_OUT, | ||
216 | .priority = NF_IP_PRI_CONNTRACK_DEFRAG, | ||
217 | }, | ||
218 | { | ||
219 | .hook = ipv4_conntrack_local, | 168 | .hook = ipv4_conntrack_local, |
220 | .owner = THIS_MODULE, | 169 | .owner = THIS_MODULE, |
221 | .pf = PF_INET, | 170 | .pf = PF_INET, |
@@ -422,6 +371,7 @@ static int __init nf_conntrack_l3proto_ipv4_init(void) | |||
422 | int ret = 0; | 371 | int ret = 0; |
423 | 372 | ||
424 | need_conntrack(); | 373 | need_conntrack(); |
374 | nf_defrag_ipv4_enable(); | ||
425 | 375 | ||
426 | ret = nf_register_sockopt(&so_getorigdst); | 376 | ret = nf_register_sockopt(&so_getorigdst); |
427 | if (ret < 0) { | 377 | if (ret < 0) { |
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c new file mode 100644 index 00000000000..aa2c50a180f --- /dev/null +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
2 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/types.h> | ||
10 | #include <linux/ip.h> | ||
11 | #include <linux/netfilter.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/skbuff.h> | ||
14 | #include <net/route.h> | ||
15 | #include <net/ip.h> | ||
16 | |||
17 | #include <linux/netfilter_ipv4.h> | ||
18 | #include <net/netfilter/ipv4/nf_defrag_ipv4.h> | ||
19 | |||
20 | /* Returns new sk_buff, or NULL */ | ||
21 | static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) | ||
22 | { | ||
23 | int err; | ||
24 | |||
25 | skb_orphan(skb); | ||
26 | |||
27 | local_bh_disable(); | ||
28 | err = ip_defrag(skb, user); | ||
29 | local_bh_enable(); | ||
30 | |||
31 | if (!err) | ||
32 | ip_send_check(ip_hdr(skb)); | ||
33 | |||
34 | return err; | ||
35 | } | ||
36 | |||
37 | static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, | ||
38 | struct sk_buff *skb, | ||
39 | const struct net_device *in, | ||
40 | const struct net_device *out, | ||
41 | int (*okfn)(struct sk_buff *)) | ||
42 | { | ||
43 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
44 | /* Previously seen (loopback)? Ignore. Do this before | ||
45 | fragment check. */ | ||
46 | if (skb->nfct) | ||
47 | return NF_ACCEPT; | ||
48 | #endif | ||
49 | |||
50 | /* Gather fragments. */ | ||
51 | if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { | ||
52 | if (nf_ct_ipv4_gather_frags(skb, | ||
53 | hooknum == NF_INET_PRE_ROUTING ? | ||
54 | IP_DEFRAG_CONNTRACK_IN : | ||
55 | IP_DEFRAG_CONNTRACK_OUT)) | ||
56 | return NF_STOLEN; | ||
57 | } | ||
58 | return NF_ACCEPT; | ||
59 | } | ||
60 | |||
61 | static struct nf_hook_ops ipv4_defrag_ops[] = { | ||
62 | { | ||
63 | .hook = ipv4_conntrack_defrag, | ||
64 | .owner = THIS_MODULE, | ||
65 | .pf = PF_INET, | ||
66 | .hooknum = NF_INET_PRE_ROUTING, | ||
67 | .priority = NF_IP_PRI_CONNTRACK_DEFRAG, | ||
68 | }, | ||
69 | { | ||
70 | .hook = ipv4_conntrack_defrag, | ||
71 | .owner = THIS_MODULE, | ||
72 | .pf = PF_INET, | ||
73 | .hooknum = NF_INET_LOCAL_OUT, | ||
74 | .priority = NF_IP_PRI_CONNTRACK_DEFRAG, | ||
75 | }, | ||
76 | }; | ||
77 | |||
78 | static int __init nf_defrag_init(void) | ||
79 | { | ||
80 | return nf_register_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops)); | ||
81 | } | ||
82 | |||
83 | static void __exit nf_defrag_fini(void) | ||
84 | { | ||
85 | nf_unregister_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops)); | ||
86 | } | ||
87 | |||
88 | void nf_defrag_ipv4_enable(void) | ||
89 | { | ||
90 | } | ||
91 | EXPORT_SYMBOL_GPL(nf_defrag_ipv4_enable); | ||
92 | |||
93 | module_init(nf_defrag_init); | ||
94 | module_exit(nf_defrag_fini); | ||
95 | |||
96 | MODULE_LICENSE("GPL"); | ||