Blame view

net/netfilter/nf_conntrack_amanda.c 5.92 KB
169589005   Patrick McHardy   [NETFILTER]: nf_c...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /* Amanda extension for IP connection tracking
   *
   * (C) 2002 by Brian J. Murrell <netfilter@interlinx.bc.ca>
   * based on HW's ip_conntrack_irc.c as well as other modules
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version
   * 2 of the License, or (at your option) any later version.
   */
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/moduleparam.h>
  #include <linux/textsearch.h>
  #include <linux/skbuff.h>
  #include <linux/in.h>
  #include <linux/udp.h>
1863f0965   Yasuyuki Kozakai   [NETFILTER]: nf_c...
18
  #include <linux/netfilter.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
19
  #include <linux/gfp.h>
169589005   Patrick McHardy   [NETFILTER]: nf_c...
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  
  #include <net/netfilter/nf_conntrack.h>
  #include <net/netfilter/nf_conntrack_expect.h>
  #include <net/netfilter/nf_conntrack_ecache.h>
  #include <net/netfilter/nf_conntrack_helper.h>
  #include <linux/netfilter/nf_conntrack_amanda.h>
  
  static unsigned int master_timeout __read_mostly = 300;
  static char *ts_algo = "kmp";
  
  MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
  MODULE_DESCRIPTION("Amanda connection tracking module");
  MODULE_LICENSE("GPL");
  MODULE_ALIAS("ip_conntrack_amanda");
4dc06f963   Pablo Neira Ayuso   netfilter: nf_con...
34
  MODULE_ALIAS_NFCT_HELPER("amanda");
169589005   Patrick McHardy   [NETFILTER]: nf_c...
35
36
37
38
39
  
  module_param(master_timeout, uint, 0600);
  MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
  module_param(ts_algo, charp, 0400);
  MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)");
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
40
  unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb,
169589005   Patrick McHardy   [NETFILTER]: nf_c...
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  				   enum ip_conntrack_info ctinfo,
  				   unsigned int matchoff,
  				   unsigned int matchlen,
  				   struct nf_conntrack_expect *exp)
  				   __read_mostly;
  EXPORT_SYMBOL_GPL(nf_nat_amanda_hook);
  
  enum amanda_strings {
  	SEARCH_CONNECT,
  	SEARCH_NEWLINE,
  	SEARCH_DATA,
  	SEARCH_MESG,
  	SEARCH_INDEX,
  };
  
  static struct {
58c0fb0dd   Jan Engelhardt   [NETFILTER]: anno...
57
  	const char		*string;
169589005   Patrick McHardy   [NETFILTER]: nf_c...
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  	size_t			len;
  	struct ts_config	*ts;
  } search[] __read_mostly = {
  	[SEARCH_CONNECT] = {
  		.string	= "CONNECT ",
  		.len	= 8,
  	},
  	[SEARCH_NEWLINE] = {
  		.string	= "
  ",
  		.len	= 1,
  	},
  	[SEARCH_DATA] = {
  		.string	= "DATA ",
  		.len	= 5,
  	},
  	[SEARCH_MESG] = {
  		.string	= "MESG ",
  		.len	= 5,
  	},
  	[SEARCH_INDEX] = {
  		.string = "INDEX ",
  		.len	= 6,
  	},
  };
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
83
  static int amanda_help(struct sk_buff *skb,
169589005   Patrick McHardy   [NETFILTER]: nf_c...
84
85
86
87
88
89
90
91
92
93
94
  		       unsigned int protoff,
  		       struct nf_conn *ct,
  		       enum ip_conntrack_info ctinfo)
  {
  	struct ts_state ts;
  	struct nf_conntrack_expect *exp;
  	struct nf_conntrack_tuple *tuple;
  	unsigned int dataoff, start, stop, off, i;
  	char pbuf[sizeof("65535")], *tmp;
  	u_int16_t len;
  	__be16 port;
169589005   Patrick McHardy   [NETFILTER]: nf_c...
95
96
97
98
99
100
101
102
103
  	int ret = NF_ACCEPT;
  	typeof(nf_nat_amanda_hook) nf_nat_amanda;
  
  	/* Only look at packets from the Amanda server */
  	if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
  		return NF_ACCEPT;
  
  	/* increase the UDP timeout of the master connection as replies from
  	 * Amanda clients to the server can be quite delayed */
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
104
  	nf_ct_refresh(ct, skb, master_timeout * HZ);
169589005   Patrick McHardy   [NETFILTER]: nf_c...
105
106
107
  
  	/* No data? */
  	dataoff = protoff + sizeof(struct udphdr);
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
108
  	if (dataoff >= skb->len) {
169589005   Patrick McHardy   [NETFILTER]: nf_c...
109
  		if (net_ratelimit())
654d0fbdc   Stephen Hemminger   netfilter: cleanu...
110
111
  			printk(KERN_ERR "amanda_help: skblen = %u
  ", skb->len);
169589005   Patrick McHardy   [NETFILTER]: nf_c...
112
113
114
115
  		return NF_ACCEPT;
  	}
  
  	memset(&ts, 0, sizeof(ts));
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
116
  	start = skb_find_text(skb, dataoff, skb->len,
169589005   Patrick McHardy   [NETFILTER]: nf_c...
117
118
119
120
121
122
  			      search[SEARCH_CONNECT].ts, &ts);
  	if (start == UINT_MAX)
  		goto out;
  	start += dataoff + search[SEARCH_CONNECT].len;
  
  	memset(&ts, 0, sizeof(ts));
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
123
  	stop = skb_find_text(skb, start, skb->len,
169589005   Patrick McHardy   [NETFILTER]: nf_c...
124
125
126
127
128
129
130
  			     search[SEARCH_NEWLINE].ts, &ts);
  	if (stop == UINT_MAX)
  		goto out;
  	stop += start;
  
  	for (i = SEARCH_DATA; i <= SEARCH_INDEX; i++) {
  		memset(&ts, 0, sizeof(ts));
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
131
  		off = skb_find_text(skb, start, stop, search[i].ts, &ts);
169589005   Patrick McHardy   [NETFILTER]: nf_c...
132
133
134
135
136
  		if (off == UINT_MAX)
  			continue;
  		off += start + search[i].len;
  
  		len = min_t(unsigned int, sizeof(pbuf) - 1, stop - off);
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
137
  		if (skb_copy_bits(skb, off, pbuf, len))
169589005   Patrick McHardy   [NETFILTER]: nf_c...
138
139
140
141
142
143
144
  			break;
  		pbuf[len] = '\0';
  
  		port = htons(simple_strtoul(pbuf, &tmp, 10));
  		len = tmp - pbuf;
  		if (port == 0 || len > 5)
  			break;
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
145
  		exp = nf_ct_expect_alloc(ct);
169589005   Patrick McHardy   [NETFILTER]: nf_c...
146
147
148
149
150
  		if (exp == NULL) {
  			ret = NF_DROP;
  			goto out;
  		}
  		tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
151
152
  		nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
  				  nf_ct_l3num(ct),
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
153
  				  &tuple->src.u3, &tuple->dst.u3,
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
154
  				  IPPROTO_TCP, NULL, &port);
169589005   Patrick McHardy   [NETFILTER]: nf_c...
155
156
157
  
  		nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook);
  		if (nf_nat_amanda && ct->status & IPS_NAT_MASK)
3db05fea5   Herbert Xu   [NETFILTER]: Repl...
158
  			ret = nf_nat_amanda(skb, ctinfo, off - dataoff,
169589005   Patrick McHardy   [NETFILTER]: nf_c...
159
  					    len, exp);
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
160
  		else if (nf_ct_expect_related(exp) != 0)
169589005   Patrick McHardy   [NETFILTER]: nf_c...
161
  			ret = NF_DROP;
6823645d6   Patrick McHardy   [NETFILTER]: nf_c...
162
  		nf_ct_expect_put(exp);
169589005   Patrick McHardy   [NETFILTER]: nf_c...
163
164
165
166
167
  	}
  
  out:
  	return ret;
  }
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
168
169
170
171
  static const struct nf_conntrack_expect_policy amanda_exp_policy = {
  	.max_expected		= 3,
  	.timeout		= 180,
  };
169589005   Patrick McHardy   [NETFILTER]: nf_c...
172
173
174
  static struct nf_conntrack_helper amanda_helper[2] __read_mostly = {
  	{
  		.name			= "amanda",
169589005   Patrick McHardy   [NETFILTER]: nf_c...
175
176
177
  		.me			= THIS_MODULE,
  		.help			= amanda_help,
  		.tuple.src.l3num	= AF_INET,
09640e636   Harvey Harrison   net: replace uses...
178
  		.tuple.src.u.udp.port	= cpu_to_be16(10080),
169589005   Patrick McHardy   [NETFILTER]: nf_c...
179
  		.tuple.dst.protonum	= IPPROTO_UDP,
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
180
  		.expect_policy		= &amanda_exp_policy,
169589005   Patrick McHardy   [NETFILTER]: nf_c...
181
182
183
  	},
  	{
  		.name			= "amanda",
169589005   Patrick McHardy   [NETFILTER]: nf_c...
184
185
186
  		.me			= THIS_MODULE,
  		.help			= amanda_help,
  		.tuple.src.l3num	= AF_INET6,
09640e636   Harvey Harrison   net: replace uses...
187
  		.tuple.src.u.udp.port	= cpu_to_be16(10080),
169589005   Patrick McHardy   [NETFILTER]: nf_c...
188
  		.tuple.dst.protonum	= IPPROTO_UDP,
6002f266b   Patrick McHardy   [NETFILTER]: nf_c...
189
  		.expect_policy		= &amanda_exp_policy,
169589005   Patrick McHardy   [NETFILTER]: nf_c...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
  	},
  };
  
  static void __exit nf_conntrack_amanda_fini(void)
  {
  	int i;
  
  	nf_conntrack_helper_unregister(&amanda_helper[0]);
  	nf_conntrack_helper_unregister(&amanda_helper[1]);
  	for (i = 0; i < ARRAY_SIZE(search); i++)
  		textsearch_destroy(search[i].ts);
  }
  
  static int __init nf_conntrack_amanda_init(void)
  {
  	int ret, i;
169589005   Patrick McHardy   [NETFILTER]: nf_c...
206
207
208
209
  	for (i = 0; i < ARRAY_SIZE(search); i++) {
  		search[i].ts = textsearch_prepare(ts_algo, search[i].string,
  						  search[i].len,
  						  GFP_KERNEL, TS_AUTOLOAD);
c764c9ade   Akinobu Mita   [NETFILTER]: nf_c...
210
211
  		if (IS_ERR(search[i].ts)) {
  			ret = PTR_ERR(search[i].ts);
169589005   Patrick McHardy   [NETFILTER]: nf_c...
212
  			goto err1;
c764c9ade   Akinobu Mita   [NETFILTER]: nf_c...
213
  		}
169589005   Patrick McHardy   [NETFILTER]: nf_c...
214
215
216
217
218
219
220
221
222
223
224
225
  	}
  	ret = nf_conntrack_helper_register(&amanda_helper[0]);
  	if (ret < 0)
  		goto err1;
  	ret = nf_conntrack_helper_register(&amanda_helper[1]);
  	if (ret < 0)
  		goto err2;
  	return 0;
  
  err2:
  	nf_conntrack_helper_unregister(&amanda_helper[0]);
  err1:
c764c9ade   Akinobu Mita   [NETFILTER]: nf_c...
226
227
  	while (--i >= 0)
  		textsearch_destroy(search[i].ts);
169589005   Patrick McHardy   [NETFILTER]: nf_c...
228
229
230
231
232
  	return ret;
  }
  
  module_init(nf_conntrack_amanda_init);
  module_exit(nf_conntrack_amanda_fini);