aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter/Kconfig2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_amanda.c143
2 files changed, 96 insertions, 49 deletions
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index d4072533da2..1540e227890 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -142,6 +142,8 @@ config IP_NF_TFTP
142config IP_NF_AMANDA 142config IP_NF_AMANDA
143 tristate "Amanda backup protocol support" 143 tristate "Amanda backup protocol support"
144 depends on IP_NF_CONNTRACK 144 depends on IP_NF_CONNTRACK
145 select TEXTSEARCH
146 select TEXTSEARCH_KMP
145 help 147 help
146 If you are running the Amanda backup package <http://www.amanda.org/> 148 If you are running the Amanda backup package <http://www.amanda.org/>
147 on this machine or machines that will be MASQUERADED through this 149 on this machine or machines that will be MASQUERADED through this
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index a604b1ccfda..0a7bd7f0406 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -17,33 +17,29 @@
17 * this value. 17 * this value.
18 * 18 *
19 */ 19 */
20
21#include <linux/in.h>
22#include <linux/kernel.h> 20#include <linux/kernel.h>
23#include <linux/module.h> 21#include <linux/module.h>
24#include <linux/netfilter.h>
25#include <linux/ip.h>
26#include <linux/moduleparam.h> 22#include <linux/moduleparam.h>
23#include <linux/textsearch.h>
24#include <linux/skbuff.h>
25#include <linux/in.h>
26#include <linux/ip.h>
27#include <linux/udp.h> 27#include <linux/udp.h>
28#include <net/checksum.h>
29#include <net/udp.h>
30 28
29#include <linux/netfilter.h>
31#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 30#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
32#include <linux/netfilter_ipv4/ip_conntrack_amanda.h> 31#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
33 32
34static unsigned int master_timeout = 300; 33static unsigned int master_timeout = 300;
34static char *ts_algo = "kmp";
35 35
36MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>"); 36MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
37MODULE_DESCRIPTION("Amanda connection tracking module"); 37MODULE_DESCRIPTION("Amanda connection tracking module");
38MODULE_LICENSE("GPL"); 38MODULE_LICENSE("GPL");
39module_param(master_timeout, uint, 0600); 39module_param(master_timeout, uint, 0600);
40MODULE_PARM_DESC(master_timeout, "timeout for the master connection"); 40MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
41 41module_param(ts_algo, charp, 0400);
42static const char *conns[] = { "DATA ", "MESG ", "INDEX " }; 42MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)");
43
44/* This is slow, but it's simple. --RR */
45static char *amanda_buffer;
46static DEFINE_SPINLOCK(amanda_buffer_lock);
47 43
48unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb, 44unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb,
49 enum ip_conntrack_info ctinfo, 45 enum ip_conntrack_info ctinfo,
@@ -52,12 +48,48 @@ unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb,
52 struct ip_conntrack_expect *exp); 48 struct ip_conntrack_expect *exp);
53EXPORT_SYMBOL_GPL(ip_nat_amanda_hook); 49EXPORT_SYMBOL_GPL(ip_nat_amanda_hook);
54 50
51enum amanda_strings {
52 SEARCH_CONNECT,
53 SEARCH_NEWLINE,
54 SEARCH_DATA,
55 SEARCH_MESG,
56 SEARCH_INDEX,
57};
58
59static struct {
60 char *string;
61 size_t len;
62 struct ts_config *ts;
63} search[] = {
64 [SEARCH_CONNECT] = {
65 .string = "CONNECT ",
66 .len = 8,
67 },
68 [SEARCH_NEWLINE] = {
69 .string = "\n",
70 .len = 1,
71 },
72 [SEARCH_DATA] = {
73 .string = "DATA ",
74 .len = 5,
75 },
76 [SEARCH_MESG] = {
77 .string = "MESG ",
78 .len = 5,
79 },
80 [SEARCH_INDEX] = {
81 .string = "INDEX ",
82 .len = 6,
83 },
84};
85
55static int help(struct sk_buff **pskb, 86static int help(struct sk_buff **pskb,
56 struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) 87 struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
57{ 88{
89 struct ts_state ts;
58 struct ip_conntrack_expect *exp; 90 struct ip_conntrack_expect *exp;
59 char *data, *data_limit, *tmp; 91 unsigned int dataoff, start, stop, off, i;
60 unsigned int dataoff, i; 92 char pbuf[sizeof("65535")], *tmp;
61 u_int16_t port, len; 93 u_int16_t port, len;
62 int ret = NF_ACCEPT; 94 int ret = NF_ACCEPT;
63 95
@@ -77,29 +109,34 @@ static int help(struct sk_buff **pskb,
77 return NF_ACCEPT; 109 return NF_ACCEPT;
78 } 110 }
79 111
80 spin_lock_bh(&amanda_buffer_lock); 112 memset(&ts, 0, sizeof(ts));
81 skb_copy_bits(*pskb, dataoff, amanda_buffer, (*pskb)->len - dataoff); 113 start = skb_find_text(*pskb, dataoff, (*pskb)->len,
82 data = amanda_buffer; 114 search[SEARCH_CONNECT].ts, &ts);
83 data_limit = amanda_buffer + (*pskb)->len - dataoff; 115 if (start == UINT_MAX)
84 *data_limit = '\0';
85
86 /* Search for the CONNECT string */
87 data = strstr(data, "CONNECT ");
88 if (!data)
89 goto out; 116 goto out;
90 data += strlen("CONNECT "); 117 start += dataoff + search[SEARCH_CONNECT].len;
91 118
92 /* Only search first line. */ 119 memset(&ts, 0, sizeof(ts));
93 if ((tmp = strchr(data, '\n'))) 120 stop = skb_find_text(*pskb, start, (*pskb)->len,
94 *tmp = '\0'; 121 search[SEARCH_NEWLINE].ts, &ts);
122 if (stop == UINT_MAX)
123 goto out;
124 stop += start;
95 125
96 for (i = 0; i < ARRAY_SIZE(conns); i++) { 126 for (i = SEARCH_DATA; i <= SEARCH_INDEX; i++) {
97 char *match = strstr(data, conns[i]); 127 memset(&ts, 0, sizeof(ts));
98 if (!match) 128 off = skb_find_text(*pskb, start, stop, search[i].ts, &ts);
129 if (off == UINT_MAX)
99 continue; 130 continue;
100 tmp = data = match + strlen(conns[i]); 131 off += start + search[i].len;
101 port = simple_strtoul(data, &data, 10); 132
102 len = data - tmp; 133 len = min_t(unsigned int, sizeof(pbuf) - 1, stop - off);
134 if (skb_copy_bits(*pskb, off, pbuf, len))
135 break;
136 pbuf[len] = '\0';
137
138 port = simple_strtoul(pbuf, &tmp, 10);
139 len = tmp - pbuf;
103 if (port == 0 || len > 5) 140 if (port == 0 || len > 5)
104 break; 141 break;
105 142
@@ -125,8 +162,7 @@ static int help(struct sk_buff **pskb,
125 exp->mask.dst.u.tcp.port = 0xFFFF; 162 exp->mask.dst.u.tcp.port = 0xFFFF;
126 163
127 if (ip_nat_amanda_hook) 164 if (ip_nat_amanda_hook)
128 ret = ip_nat_amanda_hook(pskb, ctinfo, 165 ret = ip_nat_amanda_hook(pskb, ctinfo, off - dataoff,
129 tmp - amanda_buffer,
130 len, exp); 166 len, exp);
131 else if (ip_conntrack_expect_related(exp) != 0) 167 else if (ip_conntrack_expect_related(exp) != 0)
132 ret = NF_DROP; 168 ret = NF_DROP;
@@ -134,12 +170,11 @@ static int help(struct sk_buff **pskb,
134 } 170 }
135 171
136out: 172out:
137 spin_unlock_bh(&amanda_buffer_lock);
138 return ret; 173 return ret;
139} 174}
140 175
141static struct ip_conntrack_helper amanda_helper = { 176static struct ip_conntrack_helper amanda_helper = {
142 .max_expected = ARRAY_SIZE(conns), 177 .max_expected = 3,
143 .timeout = 180, 178 .timeout = 180,
144 .me = THIS_MODULE, 179 .me = THIS_MODULE,
145 .help = help, 180 .help = help,
@@ -155,26 +190,36 @@ static struct ip_conntrack_helper amanda_helper = {
155 190
156static void __exit ip_conntrack_amanda_fini(void) 191static void __exit ip_conntrack_amanda_fini(void)
157{ 192{
193 int i;
194
158 ip_conntrack_helper_unregister(&amanda_helper); 195 ip_conntrack_helper_unregister(&amanda_helper);
159 kfree(amanda_buffer); 196 for (i = 0; i < ARRAY_SIZE(search); i++)
197 textsearch_destroy(search[i].ts);
160} 198}
161 199
162static int __init ip_conntrack_amanda_init(void) 200static int __init ip_conntrack_amanda_init(void)
163{ 201{
164 int ret; 202 int ret, i;
165 203
166 amanda_buffer = kmalloc(65536, GFP_KERNEL); 204 ret = -ENOMEM;
167 if (!amanda_buffer) 205 for (i = 0; i < ARRAY_SIZE(search); i++) {
168 return -ENOMEM; 206 search[i].ts = textsearch_prepare(ts_algo, search[i].string,
169 207 search[i].len,
170 ret = ip_conntrack_helper_register(&amanda_helper); 208 GFP_KERNEL, TS_AUTOLOAD);
171 if (ret < 0) { 209 if (search[i].ts == NULL)
172 kfree(amanda_buffer); 210 goto err;
173 return ret;
174 } 211 }
212 ret = ip_conntrack_helper_register(&amanda_helper);
213 if (ret < 0)
214 goto err;
175 return 0; 215 return 0;
176 216
177 217err:
218 for (; i >= 0; i--) {
219 if (search[i].ts)
220 textsearch_destroy(search[i].ts);
221 }
222 return ret;
178} 223}
179 224
180module_init(ip_conntrack_amanda_init); 225module_init(ip_conntrack_amanda_init);