Blame view
net/netfilter/nf_conntrack_amanda.c
5.92 KB
169589005
|
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
|
18 |
#include <linux/netfilter.h> |
5a0e3ad6a
|
19 |
#include <linux/gfp.h> |
169589005
|
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
|
34 |
MODULE_ALIAS_NFCT_HELPER("amanda"); |
169589005
|
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
|
40 |
unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb, |
169589005
|
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
|
57 |
const char *string; |
169589005
|
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
|
83 |
static int amanda_help(struct sk_buff *skb, |
169589005
|
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
|
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
|
104 |
nf_ct_refresh(ct, skb, master_timeout * HZ); |
169589005
|
105 106 107 |
/* No data? */ dataoff = protoff + sizeof(struct udphdr); |
3db05fea5
|
108 |
if (dataoff >= skb->len) { |
169589005
|
109 |
if (net_ratelimit()) |
654d0fbdc
|
110 111 |
printk(KERN_ERR "amanda_help: skblen = %u ", skb->len); |
169589005
|
112 113 114 115 |
return NF_ACCEPT; } memset(&ts, 0, sizeof(ts)); |
3db05fea5
|
116 |
start = skb_find_text(skb, dataoff, skb->len, |
169589005
|
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
|
123 |
stop = skb_find_text(skb, start, skb->len, |
169589005
|
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
|
131 |
off = skb_find_text(skb, start, stop, search[i].ts, &ts); |
169589005
|
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
|
137 |
if (skb_copy_bits(skb, off, pbuf, len)) |
169589005
|
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
|
145 |
exp = nf_ct_expect_alloc(ct); |
169589005
|
146 147 148 149 150 |
if (exp == NULL) { ret = NF_DROP; goto out; } tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; |
5e8fbe2ac
|
151 152 |
nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct), |
6002f266b
|
153 |
&tuple->src.u3, &tuple->dst.u3, |
6823645d6
|
154 |
IPPROTO_TCP, NULL, &port); |
169589005
|
155 156 157 |
nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook); if (nf_nat_amanda && ct->status & IPS_NAT_MASK) |
3db05fea5
|
158 |
ret = nf_nat_amanda(skb, ctinfo, off - dataoff, |
169589005
|
159 |
len, exp); |
6823645d6
|
160 |
else if (nf_ct_expect_related(exp) != 0) |
169589005
|
161 |
ret = NF_DROP; |
6823645d6
|
162 |
nf_ct_expect_put(exp); |
169589005
|
163 164 165 166 167 |
} out: return ret; } |
6002f266b
|
168 169 170 171 |
static const struct nf_conntrack_expect_policy amanda_exp_policy = { .max_expected = 3, .timeout = 180, }; |
169589005
|
172 173 174 |
static struct nf_conntrack_helper amanda_helper[2] __read_mostly = { { .name = "amanda", |
169589005
|
175 176 177 |
.me = THIS_MODULE, .help = amanda_help, .tuple.src.l3num = AF_INET, |
09640e636
|
178 |
.tuple.src.u.udp.port = cpu_to_be16(10080), |
169589005
|
179 |
.tuple.dst.protonum = IPPROTO_UDP, |
6002f266b
|
180 |
.expect_policy = &amanda_exp_policy, |
169589005
|
181 182 183 |
}, { .name = "amanda", |
169589005
|
184 185 186 |
.me = THIS_MODULE, .help = amanda_help, .tuple.src.l3num = AF_INET6, |
09640e636
|
187 |
.tuple.src.u.udp.port = cpu_to_be16(10080), |
169589005
|
188 |
.tuple.dst.protonum = IPPROTO_UDP, |
6002f266b
|
189 |
.expect_policy = &amanda_exp_policy, |
169589005
|
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
|
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
|
210 211 |
if (IS_ERR(search[i].ts)) { ret = PTR_ERR(search[i].ts); |
169589005
|
212 |
goto err1; |
c764c9ade
|
213 |
} |
169589005
|
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
|
226 227 |
while (--i >= 0) textsearch_destroy(search[i].ts); |
169589005
|
228 229 230 231 232 |
return ret; } module_init(nf_conntrack_amanda_init); module_exit(nf_conntrack_amanda_fini); |