diff options
author | Patrick McHardy <kaber@trash.net> | 2006-12-03 01:08:26 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-12-03 01:08:26 -0500 |
commit | 16958900578b94585c2ab9a2d20d837b4d5e3ba6 (patch) | |
tree | 91d198f1287535821ccc4d2f4dcdf9d8aa3b8483 | |
parent | d6a9b6500a8941599bcef98e7de49e1260d104ed (diff) |
[NETFILTER]: nf_conntrack/nf_nat: add amanda helper port
Add IPv4 and IPv6 capable nf_conntrack port of the Amanda conntrack/NAT helper.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/netfilter/nf_conntrack_amanda.h | 10 | ||||
-rw-r--r-- | net/ipv4/netfilter/Kconfig | 5 | ||||
-rw-r--r-- | net/ipv4/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_amanda.c | 78 | ||||
-rw-r--r-- | net/netfilter/Kconfig | 15 | ||||
-rw-r--r-- | net/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_amanda.c | 237 |
7 files changed, 347 insertions, 0 deletions
diff --git a/include/linux/netfilter/nf_conntrack_amanda.h b/include/linux/netfilter/nf_conntrack_amanda.h new file mode 100644 index 000000000000..26c223544ae8 --- /dev/null +++ b/include/linux/netfilter/nf_conntrack_amanda.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef _NF_CONNTRACK_AMANDA_H | ||
2 | #define _NF_CONNTRACK_AMANDA_H | ||
3 | /* AMANDA tracking. */ | ||
4 | |||
5 | extern unsigned int (*nf_nat_amanda_hook)(struct sk_buff **pskb, | ||
6 | enum ip_conntrack_info ctinfo, | ||
7 | unsigned int matchoff, | ||
8 | unsigned int matchlen, | ||
9 | struct nf_conntrack_expect *exp); | ||
10 | #endif /* _NF_CONNTRACK_AMANDA_H */ | ||
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 52f876db68f4..6993ec53dc06 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -512,6 +512,11 @@ config IP_NF_NAT_AMANDA | |||
512 | default IP_NF_NAT if IP_NF_AMANDA=y | 512 | default IP_NF_NAT if IP_NF_AMANDA=y |
513 | default m if IP_NF_AMANDA=m | 513 | default m if IP_NF_AMANDA=m |
514 | 514 | ||
515 | config NF_NAT_AMANDA | ||
516 | tristate | ||
517 | depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT | ||
518 | default NF_NAT && NF_CONNTRACK_AMANDA | ||
519 | |||
515 | config IP_NF_NAT_PPTP | 520 | config IP_NF_NAT_PPTP |
516 | tristate | 521 | tristate |
517 | depends on IP_NF_NAT!=n && IP_NF_PPTP!=n | 522 | depends on IP_NF_NAT!=n && IP_NF_PPTP!=n |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index c0c6194bb275..8893249bbe98 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
@@ -50,6 +50,7 @@ obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o | |||
50 | obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o | 50 | obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o |
51 | 51 | ||
52 | # NAT helpers (nf_conntrack) | 52 | # NAT helpers (nf_conntrack) |
53 | obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o | ||
53 | obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o | 54 | obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o |
54 | 55 | ||
55 | # generic IP tables | 56 | # generic IP tables |
diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/ipv4/netfilter/nf_nat_amanda.c new file mode 100644 index 000000000000..0f17098917bc --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_amanda.c | |||
@@ -0,0 +1,78 @@ | |||
1 | /* Amanda extension for TCP NAT alteration. | ||
2 | * (C) 2002 by Brian J. Murrell <netfilter@interlinx.bc.ca> | ||
3 | * based on a copy of HW's ip_nat_irc.c as well as other modules | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version | ||
8 | * 2 of the License, or (at your option) any later version. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/skbuff.h> | ||
14 | #include <linux/udp.h> | ||
15 | |||
16 | #include <net/netfilter/nf_nat_helper.h> | ||
17 | #include <net/netfilter/nf_nat_rule.h> | ||
18 | #include <net/netfilter/nf_conntrack_helper.h> | ||
19 | #include <net/netfilter/nf_conntrack_expect.h> | ||
20 | #include <linux/netfilter/nf_conntrack_amanda.h> | ||
21 | |||
22 | MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>"); | ||
23 | MODULE_DESCRIPTION("Amanda NAT helper"); | ||
24 | MODULE_LICENSE("GPL"); | ||
25 | MODULE_ALIAS("ip_nat_amanda"); | ||
26 | |||
27 | static unsigned int help(struct sk_buff **pskb, | ||
28 | enum ip_conntrack_info ctinfo, | ||
29 | unsigned int matchoff, | ||
30 | unsigned int matchlen, | ||
31 | struct nf_conntrack_expect *exp) | ||
32 | { | ||
33 | char buffer[sizeof("65535")]; | ||
34 | u_int16_t port; | ||
35 | unsigned int ret; | ||
36 | |||
37 | /* Connection comes from client. */ | ||
38 | exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; | ||
39 | exp->dir = IP_CT_DIR_ORIGINAL; | ||
40 | |||
41 | /* When you see the packet, we need to NAT it the same as the | ||
42 | * this one (ie. same IP: it will be TCP and master is UDP). */ | ||
43 | exp->expectfn = nf_nat_follow_master; | ||
44 | |||
45 | /* Try to get same port: if not, try to change it. */ | ||
46 | for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { | ||
47 | exp->tuple.dst.u.tcp.port = htons(port); | ||
48 | if (nf_conntrack_expect_related(exp) == 0) | ||
49 | break; | ||
50 | } | ||
51 | |||
52 | if (port == 0) | ||
53 | return NF_DROP; | ||
54 | |||
55 | sprintf(buffer, "%u", port); | ||
56 | ret = nf_nat_mangle_udp_packet(pskb, exp->master, ctinfo, | ||
57 | matchoff, matchlen, | ||
58 | buffer, strlen(buffer)); | ||
59 | if (ret != NF_ACCEPT) | ||
60 | nf_conntrack_unexpect_related(exp); | ||
61 | return ret; | ||
62 | } | ||
63 | |||
64 | static void __exit nf_nat_amanda_fini(void) | ||
65 | { | ||
66 | rcu_assign_pointer(nf_nat_amanda_hook, NULL); | ||
67 | synchronize_rcu(); | ||
68 | } | ||
69 | |||
70 | static int __init nf_nat_amanda_init(void) | ||
71 | { | ||
72 | BUG_ON(rcu_dereference(nf_nat_amanda_hook)); | ||
73 | rcu_assign_pointer(nf_nat_amanda_hook, help); | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | module_init(nf_nat_amanda_init); | ||
78 | module_exit(nf_nat_amanda_fini); | ||
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index efe56f768f34..f85fd43b344b 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -131,6 +131,21 @@ config NF_CT_PROTO_SCTP | |||
131 | If you want to compile it as a module, say M here and read | 131 | If you want to compile it as a module, say M here and read |
132 | Documentation/modules.txt. If unsure, say `N'. | 132 | Documentation/modules.txt. If unsure, say `N'. |
133 | 133 | ||
134 | config NF_CONNTRACK_AMANDA | ||
135 | tristate "Amanda backup protocol support (EXPERIMENTAL)" | ||
136 | depends on EXPERIMENTAL && NF_CONNTRACK | ||
137 | select TEXTSEARCH | ||
138 | select TEXTSEARCH_KMP | ||
139 | help | ||
140 | If you are running the Amanda backup package <http://www.amanda.org/> | ||
141 | on this machine or machines that will be MASQUERADED through this | ||
142 | machine, then you may want to enable this feature. This allows the | ||
143 | connection tracking and natting code to allow the sub-channels that | ||
144 | Amanda requires for communication of the backup data, messages and | ||
145 | index. | ||
146 | |||
147 | To compile it as a module, choose M here. If unsure, say N. | ||
148 | |||
134 | config NF_CONNTRACK_FTP | 149 | config NF_CONNTRACK_FTP |
135 | tristate "FTP support on new connection tracking (EXPERIMENTAL)" | 150 | tristate "FTP support on new connection tracking (EXPERIMENTAL)" |
136 | depends on EXPERIMENTAL && NF_CONNTRACK | 151 | depends on EXPERIMENTAL && NF_CONNTRACK |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 7f0089c584bf..a5ee93817427 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -20,6 +20,7 @@ obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o | |||
20 | obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o | 20 | obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o |
21 | 21 | ||
22 | # connection tracking helpers | 22 | # connection tracking helpers |
23 | obj-$(CONFIG_NF_CONNTRACK_AMANDA) += nf_conntrack_amanda.o | ||
23 | obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o | 24 | obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o |
24 | 25 | ||
25 | # generic X tables | 26 | # generic X tables |
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c new file mode 100644 index 000000000000..5c495dc9d942 --- /dev/null +++ b/net/netfilter/nf_conntrack_amanda.c | |||
@@ -0,0 +1,237 @@ | |||
1 | /* Amanda extension for IP connection tracking | ||
2 | * | ||
3 | * (C) 2002 by Brian J. Murrell <netfilter@interlinx.bc.ca> | ||
4 | * based on HW's ip_conntrack_irc.c as well as other modules | ||
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 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/textsearch.h> | ||
15 | #include <linux/skbuff.h> | ||
16 | #include <linux/in.h> | ||
17 | #include <linux/udp.h> | ||
18 | |||
19 | #include <net/netfilter/nf_conntrack.h> | ||
20 | #include <net/netfilter/nf_conntrack_expect.h> | ||
21 | #include <net/netfilter/nf_conntrack_ecache.h> | ||
22 | #include <net/netfilter/nf_conntrack_helper.h> | ||
23 | #include <linux/netfilter/nf_conntrack_amanda.h> | ||
24 | |||
25 | static unsigned int master_timeout __read_mostly = 300; | ||
26 | static char *ts_algo = "kmp"; | ||
27 | |||
28 | MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>"); | ||
29 | MODULE_DESCRIPTION("Amanda connection tracking module"); | ||
30 | MODULE_LICENSE("GPL"); | ||
31 | MODULE_ALIAS("ip_conntrack_amanda"); | ||
32 | |||
33 | module_param(master_timeout, uint, 0600); | ||
34 | MODULE_PARM_DESC(master_timeout, "timeout for the master connection"); | ||
35 | module_param(ts_algo, charp, 0400); | ||
36 | MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)"); | ||
37 | |||
38 | unsigned int (*nf_nat_amanda_hook)(struct sk_buff **pskb, | ||
39 | enum ip_conntrack_info ctinfo, | ||
40 | unsigned int matchoff, | ||
41 | unsigned int matchlen, | ||
42 | struct nf_conntrack_expect *exp) | ||
43 | __read_mostly; | ||
44 | EXPORT_SYMBOL_GPL(nf_nat_amanda_hook); | ||
45 | |||
46 | enum amanda_strings { | ||
47 | SEARCH_CONNECT, | ||
48 | SEARCH_NEWLINE, | ||
49 | SEARCH_DATA, | ||
50 | SEARCH_MESG, | ||
51 | SEARCH_INDEX, | ||
52 | }; | ||
53 | |||
54 | static struct { | ||
55 | char *string; | ||
56 | size_t len; | ||
57 | struct ts_config *ts; | ||
58 | } search[] __read_mostly = { | ||
59 | [SEARCH_CONNECT] = { | ||
60 | .string = "CONNECT ", | ||
61 | .len = 8, | ||
62 | }, | ||
63 | [SEARCH_NEWLINE] = { | ||
64 | .string = "\n", | ||
65 | .len = 1, | ||
66 | }, | ||
67 | [SEARCH_DATA] = { | ||
68 | .string = "DATA ", | ||
69 | .len = 5, | ||
70 | }, | ||
71 | [SEARCH_MESG] = { | ||
72 | .string = "MESG ", | ||
73 | .len = 5, | ||
74 | }, | ||
75 | [SEARCH_INDEX] = { | ||
76 | .string = "INDEX ", | ||
77 | .len = 6, | ||
78 | }, | ||
79 | }; | ||
80 | |||
81 | static int amanda_help(struct sk_buff **pskb, | ||
82 | unsigned int protoff, | ||
83 | struct nf_conn *ct, | ||
84 | enum ip_conntrack_info ctinfo) | ||
85 | { | ||
86 | struct ts_state ts; | ||
87 | struct nf_conntrack_expect *exp; | ||
88 | struct nf_conntrack_tuple *tuple; | ||
89 | unsigned int dataoff, start, stop, off, i; | ||
90 | char pbuf[sizeof("65535")], *tmp; | ||
91 | u_int16_t len; | ||
92 | __be16 port; | ||
93 | int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; | ||
94 | int ret = NF_ACCEPT; | ||
95 | typeof(nf_nat_amanda_hook) nf_nat_amanda; | ||
96 | |||
97 | /* Only look at packets from the Amanda server */ | ||
98 | if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) | ||
99 | return NF_ACCEPT; | ||
100 | |||
101 | /* increase the UDP timeout of the master connection as replies from | ||
102 | * Amanda clients to the server can be quite delayed */ | ||
103 | nf_ct_refresh(ct, *pskb, master_timeout * HZ); | ||
104 | |||
105 | /* No data? */ | ||
106 | dataoff = protoff + sizeof(struct udphdr); | ||
107 | if (dataoff >= (*pskb)->len) { | ||
108 | if (net_ratelimit()) | ||
109 | printk("amanda_help: skblen = %u\n", (*pskb)->len); | ||
110 | return NF_ACCEPT; | ||
111 | } | ||
112 | |||
113 | memset(&ts, 0, sizeof(ts)); | ||
114 | start = skb_find_text(*pskb, dataoff, (*pskb)->len, | ||
115 | search[SEARCH_CONNECT].ts, &ts); | ||
116 | if (start == UINT_MAX) | ||
117 | goto out; | ||
118 | start += dataoff + search[SEARCH_CONNECT].len; | ||
119 | |||
120 | memset(&ts, 0, sizeof(ts)); | ||
121 | stop = skb_find_text(*pskb, start, (*pskb)->len, | ||
122 | search[SEARCH_NEWLINE].ts, &ts); | ||
123 | if (stop == UINT_MAX) | ||
124 | goto out; | ||
125 | stop += start; | ||
126 | |||
127 | for (i = SEARCH_DATA; i <= SEARCH_INDEX; i++) { | ||
128 | memset(&ts, 0, sizeof(ts)); | ||
129 | off = skb_find_text(*pskb, start, stop, search[i].ts, &ts); | ||
130 | if (off == UINT_MAX) | ||
131 | continue; | ||
132 | off += start + search[i].len; | ||
133 | |||
134 | len = min_t(unsigned int, sizeof(pbuf) - 1, stop - off); | ||
135 | if (skb_copy_bits(*pskb, off, pbuf, len)) | ||
136 | break; | ||
137 | pbuf[len] = '\0'; | ||
138 | |||
139 | port = htons(simple_strtoul(pbuf, &tmp, 10)); | ||
140 | len = tmp - pbuf; | ||
141 | if (port == 0 || len > 5) | ||
142 | break; | ||
143 | |||
144 | exp = nf_conntrack_expect_alloc(ct); | ||
145 | if (exp == NULL) { | ||
146 | ret = NF_DROP; | ||
147 | goto out; | ||
148 | } | ||
149 | tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; | ||
150 | nf_conntrack_expect_init(exp, family, | ||
151 | &tuple->src.u3, &tuple->dst.u3, | ||
152 | IPPROTO_TCP, NULL, &port); | ||
153 | |||
154 | nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook); | ||
155 | if (nf_nat_amanda && ct->status & IPS_NAT_MASK) | ||
156 | ret = nf_nat_amanda(pskb, ctinfo, off - dataoff, | ||
157 | len, exp); | ||
158 | else if (nf_conntrack_expect_related(exp) != 0) | ||
159 | ret = NF_DROP; | ||
160 | nf_conntrack_expect_put(exp); | ||
161 | } | ||
162 | |||
163 | out: | ||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | static struct nf_conntrack_helper amanda_helper[2] __read_mostly = { | ||
168 | { | ||
169 | .name = "amanda", | ||
170 | .max_expected = 3, | ||
171 | .timeout = 180, | ||
172 | .me = THIS_MODULE, | ||
173 | .help = amanda_help, | ||
174 | .tuple.src.l3num = AF_INET, | ||
175 | .tuple.src.u.udp.port = __constant_htons(10080), | ||
176 | .tuple.dst.protonum = IPPROTO_UDP, | ||
177 | .mask.src.l3num = 0xFFFF, | ||
178 | .mask.src.u.udp.port = __constant_htons(0xFFFF), | ||
179 | .mask.dst.protonum = 0xFF, | ||
180 | }, | ||
181 | { | ||
182 | .name = "amanda", | ||
183 | .max_expected = 3, | ||
184 | .timeout = 180, | ||
185 | .me = THIS_MODULE, | ||
186 | .help = amanda_help, | ||
187 | .tuple.src.l3num = AF_INET6, | ||
188 | .tuple.src.u.udp.port = __constant_htons(10080), | ||
189 | .tuple.dst.protonum = IPPROTO_UDP, | ||
190 | .mask.src.l3num = 0xFFFF, | ||
191 | .mask.src.u.udp.port = __constant_htons(0xFFFF), | ||
192 | .mask.dst.protonum = 0xFF, | ||
193 | }, | ||
194 | }; | ||
195 | |||
196 | static void __exit nf_conntrack_amanda_fini(void) | ||
197 | { | ||
198 | int i; | ||
199 | |||
200 | nf_conntrack_helper_unregister(&amanda_helper[0]); | ||
201 | nf_conntrack_helper_unregister(&amanda_helper[1]); | ||
202 | for (i = 0; i < ARRAY_SIZE(search); i++) | ||
203 | textsearch_destroy(search[i].ts); | ||
204 | } | ||
205 | |||
206 | static int __init nf_conntrack_amanda_init(void) | ||
207 | { | ||
208 | int ret, i; | ||
209 | |||
210 | ret = -ENOMEM; | ||
211 | for (i = 0; i < ARRAY_SIZE(search); i++) { | ||
212 | search[i].ts = textsearch_prepare(ts_algo, search[i].string, | ||
213 | search[i].len, | ||
214 | GFP_KERNEL, TS_AUTOLOAD); | ||
215 | if (search[i].ts == NULL) | ||
216 | goto err1; | ||
217 | } | ||
218 | ret = nf_conntrack_helper_register(&amanda_helper[0]); | ||
219 | if (ret < 0) | ||
220 | goto err1; | ||
221 | ret = nf_conntrack_helper_register(&amanda_helper[1]); | ||
222 | if (ret < 0) | ||
223 | goto err2; | ||
224 | return 0; | ||
225 | |||
226 | err2: | ||
227 | nf_conntrack_helper_unregister(&amanda_helper[0]); | ||
228 | err1: | ||
229 | for (; i >= 0; i--) { | ||
230 | if (search[i].ts) | ||
231 | textsearch_destroy(search[i].ts); | ||
232 | } | ||
233 | return ret; | ||
234 | } | ||
235 | |||
236 | module_init(nf_conntrack_amanda_init); | ||
237 | module_exit(nf_conntrack_amanda_fini); | ||