Skip to content

Commit 1695890

Browse files
kaberdavem330
authored andcommitted
[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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d6a9b65 commit 1695890

File tree

7 files changed

+347
-0
lines changed

7 files changed

+347
-0
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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 */

net/ipv4/netfilter/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,11 @@ config IP_NF_NAT_AMANDA
512512
default IP_NF_NAT if IP_NF_AMANDA=y
513513
default m if IP_NF_AMANDA=m
514514

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+
515520
config IP_NF_NAT_PPTP
516521
tristate
517522
depends on IP_NF_NAT!=n && IP_NF_PPTP!=n

net/ipv4/netfilter/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
5050
obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o
5151

5252
# NAT helpers (nf_conntrack)
53+
obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o
5354
obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o
5455

5556
# generic IP tables

net/ipv4/netfilter/nf_nat_amanda.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* Amanda extension for TCP NAT alteration.
2+
* (C) 2002 by Brian J. Murrell <[email protected]>
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 <[email protected]>");
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);

net/netfilter/Kconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,21 @@ config NF_CT_PROTO_SCTP
131131
If you want to compile it as a module, say M here and read
132132
Documentation/modules.txt. If unsure, say `N'.
133133

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+
134149
config NF_CONNTRACK_FTP
135150
tristate "FTP support on new connection tracking (EXPERIMENTAL)"
136151
depends on EXPERIMENTAL && NF_CONNTRACK

net/netfilter/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
2020
obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
2121

2222
# connection tracking helpers
23+
obj-$(CONFIG_NF_CONNTRACK_AMANDA) += nf_conntrack_amanda.o
2324
obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
2425

2526
# generic X tables
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
/* Amanda extension for IP connection tracking
2+
*
3+
* (C) 2002 by Brian J. Murrell <[email protected]>
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 <[email protected]>");
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);

0 commit comments

Comments
 (0)