1 |
1275 |
phoenix |
/* Amanda extension for IP connection tracking, Version 0.2
|
2 |
|
|
* (C) 2002 by Brian J. Murrell <netfilter@interlinx.bc.ca>
|
3 |
|
|
* based on HW's ip_conntrack_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 |
|
|
* Module load syntax:
|
11 |
|
|
* insmod ip_conntrack_amanda.o [master_timeout=n]
|
12 |
|
|
*
|
13 |
|
|
* Where master_timeout is the timeout (in seconds) of the master
|
14 |
|
|
* connection (port 10080). This defaults to 5 minutes but if
|
15 |
|
|
* your clients take longer than 5 minutes to do their work
|
16 |
|
|
* before getting back to the Amanda server, you can increase
|
17 |
|
|
* this value.
|
18 |
|
|
*
|
19 |
|
|
*/
|
20 |
|
|
|
21 |
|
|
#include <linux/kernel.h>
|
22 |
|
|
#include <linux/module.h>
|
23 |
|
|
#include <linux/netfilter.h>
|
24 |
|
|
#include <linux/ip.h>
|
25 |
|
|
#include <net/checksum.h>
|
26 |
|
|
#include <net/udp.h>
|
27 |
|
|
|
28 |
|
|
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
|
29 |
|
|
#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
|
30 |
|
|
|
31 |
|
|
static unsigned int master_timeout = 300;
|
32 |
|
|
|
33 |
|
|
MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
|
34 |
|
|
MODULE_DESCRIPTION("Amanda connection tracking module");
|
35 |
|
|
MODULE_LICENSE("GPL");
|
36 |
|
|
MODULE_PARM(master_timeout, "i");
|
37 |
|
|
MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
|
38 |
|
|
|
39 |
|
|
static struct { char *match; int len; } conns[] = {
|
40 |
|
|
{ "DATA ", 5},
|
41 |
|
|
{ "MESG ", 5},
|
42 |
|
|
{ "INDEX ", 6},
|
43 |
|
|
};
|
44 |
|
|
|
45 |
|
|
#define NUM_MSGS 3
|
46 |
|
|
|
47 |
|
|
|
48 |
|
|
static int help(const struct iphdr *iph, size_t len,
|
49 |
|
|
struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
|
50 |
|
|
{
|
51 |
|
|
struct ip_conntrack_expect exp;
|
52 |
|
|
struct ip_ct_amanda_expect *exp_amanda_info;
|
53 |
|
|
struct udphdr *udph = (void *)iph + iph->ihl * 4;
|
54 |
|
|
u_int32_t udplen = len - iph->ihl * 4;
|
55 |
|
|
u_int32_t datalen = udplen - sizeof(struct udphdr);
|
56 |
|
|
char *data = (char *)udph + sizeof(struct udphdr);
|
57 |
|
|
char *data_limit = data + datalen;
|
58 |
|
|
char *start = data, *tmp;
|
59 |
|
|
int i;
|
60 |
|
|
|
61 |
|
|
/* Only look at packets from the Amanda server */
|
62 |
|
|
if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
|
63 |
|
|
return NF_ACCEPT;
|
64 |
|
|
|
65 |
|
|
if (udplen < sizeof(struct udphdr)) {
|
66 |
|
|
if (net_ratelimit())
|
67 |
|
|
printk("amanda_help: udplen = %u\n", udplen);
|
68 |
|
|
return NF_ACCEPT;
|
69 |
|
|
}
|
70 |
|
|
|
71 |
|
|
if (udph->check &&
|
72 |
|
|
csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
|
73 |
|
|
csum_partial((char *)udph, udplen, 0)))
|
74 |
|
|
return NF_ACCEPT;
|
75 |
|
|
|
76 |
|
|
/* increase the UDP timeout of the master connection as replies from
|
77 |
|
|
* Amanda clients to the server can be quite delayed */
|
78 |
|
|
ip_ct_refresh(ct, master_timeout * HZ);
|
79 |
|
|
|
80 |
|
|
/* Search for "CONNECT " string */
|
81 |
|
|
do {
|
82 |
|
|
if (data + 8 >= data_limit)
|
83 |
|
|
return NF_ACCEPT;
|
84 |
|
|
if (!memcmp(data, "CONNECT ", 8)) {
|
85 |
|
|
data += 8;
|
86 |
|
|
break;
|
87 |
|
|
}
|
88 |
|
|
data++;
|
89 |
|
|
} while(1);
|
90 |
|
|
|
91 |
|
|
memset(&exp, 0, sizeof(exp));
|
92 |
|
|
exp.tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
|
93 |
|
|
exp.tuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
|
94 |
|
|
exp.tuple.dst.protonum = IPPROTO_TCP;
|
95 |
|
|
exp.mask.src.ip = 0xFFFFFFFF;
|
96 |
|
|
exp.mask.dst.ip = 0xFFFFFFFF;
|
97 |
|
|
exp.mask.dst.protonum = 0xFFFF;
|
98 |
|
|
exp.mask.dst.u.tcp.port = 0xFFFF;
|
99 |
|
|
|
100 |
|
|
exp_amanda_info = &exp.help.exp_amanda_info;
|
101 |
|
|
for (i = 0; data + conns[i].len < data_limit && *data != '\n'; data++) {
|
102 |
|
|
if (memcmp(data, conns[i].match, conns[i].len))
|
103 |
|
|
continue;
|
104 |
|
|
tmp = data += conns[i].len;
|
105 |
|
|
exp_amanda_info->offset = data - start;
|
106 |
|
|
exp_amanda_info->port = simple_strtoul(data, &data, 10);
|
107 |
|
|
exp_amanda_info->len = data - tmp;
|
108 |
|
|
if (exp_amanda_info->port == 0 || exp_amanda_info->len > 5)
|
109 |
|
|
break;
|
110 |
|
|
|
111 |
|
|
exp.tuple.dst.u.tcp.port = htons(exp_amanda_info->port);
|
112 |
|
|
ip_conntrack_expect_related(ct, &exp);
|
113 |
|
|
if (++i == NUM_MSGS)
|
114 |
|
|
break;
|
115 |
|
|
}
|
116 |
|
|
|
117 |
|
|
return NF_ACCEPT;
|
118 |
|
|
}
|
119 |
|
|
|
120 |
|
|
static struct ip_conntrack_helper amanda_helper;
|
121 |
|
|
|
122 |
|
|
static void __exit fini(void)
|
123 |
|
|
{
|
124 |
|
|
ip_conntrack_helper_unregister(&amanda_helper);
|
125 |
|
|
}
|
126 |
|
|
|
127 |
|
|
static int __init init(void)
|
128 |
|
|
{
|
129 |
|
|
amanda_helper.tuple.src.u.udp.port = htons(10080);
|
130 |
|
|
amanda_helper.tuple.dst.protonum = IPPROTO_UDP;
|
131 |
|
|
amanda_helper.mask.src.u.udp.port = 0xFFFF;
|
132 |
|
|
amanda_helper.mask.dst.protonum = 0xFFFF;
|
133 |
|
|
amanda_helper.max_expected = NUM_MSGS;
|
134 |
|
|
amanda_helper.timeout = 180;
|
135 |
|
|
amanda_helper.flags = IP_CT_HELPER_F_REUSE_EXPECT;
|
136 |
|
|
amanda_helper.me = THIS_MODULE;
|
137 |
|
|
amanda_helper.help = help;
|
138 |
|
|
amanda_helper.name = "amanda";
|
139 |
|
|
|
140 |
|
|
return ip_conntrack_helper_register(&amanda_helper);
|
141 |
|
|
}
|
142 |
|
|
|
143 |
|
|
module_init(init);
|
144 |
|
|
module_exit(fini);
|