finally move buildroot-ng to trunk
[openwrt/staging/dedeckeh.git] / target / linux / generic-2.4 / patches / 615-netfilter_nat_mms.patch
1 diff -urN linux-2.4.32/net/ipv4/netfilter/Config.in linux-2.4.32.new/net/ipv4/netfilter/Config.in
2 --- linux-2.4.32/net/ipv4/netfilter/Config.in 2006-03-01 01:12:48.268947944 +0100
3 +++ linux-2.4.32.new/net/ipv4/netfilter/Config.in 2006-03-01 01:14:53.455916632 +0100
4 @@ -17,6 +17,7 @@
5 dep_tristate ' PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE
6 dep_tristate ' H.323 (netmeeting) support' CONFIG_IP_NF_H323 $CONFIG_IP_NF_CONNTRACK
7 dep_tristate ' RTSP protocol support' CONFIG_IP_NF_RTSP $CONFIG_IP_NF_CONNTRACK
8 + dep_tristate ' MMS protocol support' CONFIG_IP_NF_MMS $CONFIG_IP_NF_CONNTRACK
9 fi
10
11 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
12 @@ -127,6 +128,13 @@
13 define_tristate CONFIG_IP_NF_NAT_RTSP $CONFIG_IP_NF_NAT
14 fi
15 fi
16 + if [ "$CONFIG_IP_NF_MMS" = "m" ]; then
17 + define_tristate CONFIG_IP_NF_NAT_MMS m
18 + else
19 + if [ "$CONFIG_IP_NF_MMS" = "y" ]; then
20 + define_tristate CONFIG_IP_NF_NAT_MMS $CONFIG_IP_NF_NAT
21 + fi
22 + fi
23 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
24 dep_tristate ' Basic SNMP-ALG support (EXPERIMENTAL)' CONFIG_IP_NF_NAT_SNMP_BASIC $CONFIG_IP_NF_NAT
25 fi
26 diff -urN linux-2.4.32/net/ipv4/netfilter/Makefile linux-2.4.32.new/net/ipv4/netfilter/Makefile
27 --- linux-2.4.32/net/ipv4/netfilter/Makefile 2006-03-01 01:12:48.270947640 +0100
28 +++ linux-2.4.32.new/net/ipv4/netfilter/Makefile 2006-03-01 01:15:25.263081208 +0100
29 @@ -61,6 +61,10 @@
30 ifdef CONFIG_IP_NF_NAT_RTSP
31 export-objs += ip_conntrack_rtsp.o
32 endif
33 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
34 +ifdef CONFIG_IP_NF_NAT_MMS
35 + export-objs += ip_conntrack_mms.o
36 +endif
37
38
39
40 @@ -73,6 +77,7 @@
41 obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
42 obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
43 obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
44 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
45
46 # generic IP tables
47 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
48 diff -urN linux-2.4.32/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.4.32.new/net/ipv4/netfilter/ip_conntrack_mms.c
49 --- linux-2.4.32/net/ipv4/netfilter/ip_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
50 +++ linux-2.4.32.new/net/ipv4/netfilter/ip_conntrack_mms.c 2006-03-01 01:13:32.991149136 +0100
51 @@ -0,0 +1,292 @@
52 +/* MMS extension for IP connection tracking
53 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
54 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
55 + *
56 + * ip_conntrack_mms.c v0.3 2002-09-22
57 + *
58 + * This program is free software; you can redistribute it and/or
59 + * modify it under the terms of the GNU General Public License
60 + * as published by the Free Software Foundation; either version
61 + * 2 of the License, or (at your option) any later version.
62 + *
63 + * Module load syntax:
64 + * insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
65 + *
66 + * Please give the ports of all MMS servers You wish to connect to.
67 + * If you don't specify ports, the default will be TCP port 1755.
68 + *
69 + * More info on MMS protocol, firewalls and NAT:
70 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
71 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
72 + *
73 + * The SDP project people are reverse-engineering MMS:
74 + * http://get.to/sdp
75 + */
76 +
77 +#include <linux/config.h>
78 +#include <linux/module.h>
79 +#include <linux/netfilter.h>
80 +#include <linux/ip.h>
81 +#include <linux/ctype.h>
82 +#include <net/checksum.h>
83 +#include <net/tcp.h>
84 +
85 +#include <linux/netfilter_ipv4/lockhelp.h>
86 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
87 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
88 +
89 +DECLARE_LOCK(ip_mms_lock);
90 +struct module *ip_conntrack_mms = THIS_MODULE;
91 +
92 +#define MAX_PORTS 8
93 +static int ports[MAX_PORTS];
94 +static int ports_c;
95 +#ifdef MODULE_PARM
96 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
97 +#endif
98 +
99 +#define DEBUGP(format, args...)
100 +
101 +#ifdef CONFIG_IP_NF_NAT_NEEDED
102 +EXPORT_SYMBOL(ip_mms_lock);
103 +#endif
104 +
105 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
106 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
107 +MODULE_LICENSE("GPL");
108 +
109 +/* #define isdigit(c) (c >= '0' && c <= '9') */
110 +
111 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
112 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
113 +{
114 + int i;
115 + for (i = 0; i < unicode_size; ++i) {
116 + string[i] = (char)(unicode[i]);
117 + }
118 + string[unicode_size] = 0x00;
119 +}
120 +
121 +__inline static int atoi(char *s)
122 +{
123 + int i=0;
124 + while (isdigit(*s)) {
125 + i = i*10 + *(s++) - '0';
126 + }
127 + return i;
128 +}
129 +
130 +/* convert ip address string like "192.168.0.10" to unsigned int */
131 +__inline static u_int32_t asciiiptoi(char *s)
132 +{
133 + unsigned int i, j, k;
134 +
135 + for(i=k=0; k<3; ++k, ++s, i<<=8) {
136 + i+=atoi(s);
137 + for(j=0; (*(++s) != '.') && (j<3); ++j)
138 + ;
139 + }
140 + i+=atoi(s);
141 + return ntohl(i);
142 +}
143 +
144 +int parse_mms(const char *data,
145 + const unsigned int datalen,
146 + u_int32_t *mms_ip,
147 + u_int16_t *mms_proto,
148 + u_int16_t *mms_port,
149 + char **mms_string_b,
150 + char **mms_string_e,
151 + char **mms_padding_e)
152 +{
153 + int unicode_size, i;
154 + char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
155 + char getlengthstring[28];
156 +
157 + for(unicode_size=0;
158 + (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
159 + unicode_size++)
160 + if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
161 + return -1; /* out of bounds - incomplete packet */
162 +
163 + unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
164 + DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
165 +
166 + /* IP address ? */
167 + *mms_ip = asciiiptoi(tempstring+2);
168 +
169 + i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
170 +
171 + /* protocol ? */
172 + if(strncmp(tempstring+3+i, "TCP", 3)==0)
173 + *mms_proto = IPPROTO_TCP;
174 + else if(strncmp(tempstring+3+i, "UDP", 3)==0)
175 + *mms_proto = IPPROTO_UDP;
176 +
177 + /* port ? */
178 + *mms_port = atoi(tempstring+7+i);
179 +
180 + /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port"
181 + unicode string, one to the end of the string, and one to the end
182 + of the packet, since we must keep track of the number of bytes
183 + between end of the unicode string and the end of packet (padding) */
184 + *mms_string_b = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
185 + *mms_string_e = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
186 + *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
187 + return 0;
188 +}
189 +
190 +
191 +static int help(const struct iphdr *iph, size_t len,
192 + struct ip_conntrack *ct,
193 + enum ip_conntrack_info ctinfo)
194 +{
195 + /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
196 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
197 + const char *data = (const char *)tcph + tcph->doff * 4;
198 + unsigned int tcplen = len - iph->ihl * 4;
199 + unsigned int datalen = tcplen - tcph->doff * 4;
200 + int dir = CTINFO2DIR(ctinfo);
201 + struct ip_conntrack_expect expect, *exp = &expect;
202 + struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
203 +
204 + u_int32_t mms_ip;
205 + u_int16_t mms_proto;
206 + char mms_proto_string[8];
207 + u_int16_t mms_port;
208 + char *mms_string_b, *mms_string_e, *mms_padding_e;
209 +
210 + /* Until there's been traffic both ways, don't look in packets. */
211 + if (ctinfo != IP_CT_ESTABLISHED
212 + && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
213 + DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
214 + return NF_ACCEPT;
215 + }
216 +
217 + /* Not whole TCP header? */
218 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
219 + DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
220 + return NF_ACCEPT;
221 + }
222 +
223 + /* Checksum invalid? Ignore. */
224 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
225 + csum_partial((char *)tcph, tcplen, 0))) {
226 + DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
227 + tcph, tcplen, NIPQUAD(iph->saddr),
228 + NIPQUAD(iph->daddr));
229 + return NF_ACCEPT;
230 + }
231 +
232 + /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
233 + if( (MMS_SRV_MSG_OFFSET < datalen) &&
234 + ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
235 + DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n",
236 + (u8)*(data+36), (u8)*(data+37),
237 + (u8)*(data+38), (u8)*(data+39),
238 + datalen);
239 + if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
240 + &mms_string_b, &mms_string_e, &mms_padding_e))
241 + if(net_ratelimit())
242 + printk(KERN_WARNING
243 + "ip_conntrack_mms: Unable to parse data payload\n");
244 +
245 + memset(&expect, 0, sizeof(expect));
246 +
247 + sprintf(mms_proto_string, "(%u)", mms_proto);
248 + DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
249 + mms_proto == IPPROTO_TCP ? "TCP"
250 + : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
251 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
252 + NIPQUAD(mms_ip),
253 + mms_port);
254 +
255 + /* it's possible that the client will just ask the server to tunnel
256 + the stream over the same TCP session (from port 1755): there's
257 + shouldn't be a need to add an expectation in that case, but it
258 + makes NAT packet mangling so much easier */
259 + LOCK_BH(&ip_mms_lock);
260 +
261 + DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
262 +
263 + exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
264 + exp_mms_info->len = (mms_string_e - mms_string_b);
265 + exp_mms_info->padding = (mms_padding_e - mms_string_e);
266 + exp_mms_info->port = mms_port;
267 +
268 + DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
269 + exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
270 +
271 + exp->tuple = ((struct ip_conntrack_tuple)
272 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
273 + { mms_ip,
274 + { (__u16) ntohs(mms_port) },
275 + mms_proto } }
276 + );
277 + exp->mask = ((struct ip_conntrack_tuple)
278 + { { 0xFFFFFFFF, { 0 } },
279 + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
280 + exp->expectfn = NULL;
281 + ip_conntrack_expect_related(ct, &expect);
282 + UNLOCK_BH(&ip_mms_lock);
283 + }
284 +
285 + return NF_ACCEPT;
286 +}
287 +
288 +static struct ip_conntrack_helper mms[MAX_PORTS];
289 +static char mms_names[MAX_PORTS][10];
290 +
291 +/* Not __exit: called from init() */
292 +static void fini(void)
293 +{
294 + int i;
295 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
296 + DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
297 + ports[i]);
298 + ip_conntrack_helper_unregister(&mms[i]);
299 + }
300 +}
301 +
302 +static int __init init(void)
303 +{
304 + int i, ret;
305 + char *tmpname;
306 +
307 + if (ports[0] == 0)
308 + ports[0] = MMS_PORT;
309 +
310 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
311 + memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
312 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
313 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
314 + mms[i].mask.src.u.tcp.port = 0xFFFF;
315 + mms[i].mask.dst.protonum = 0xFFFF;
316 + mms[i].max_expected = 1;
317 + mms[i].timeout = 0;
318 + mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
319 + mms[i].me = THIS_MODULE;
320 + mms[i].help = help;
321 +
322 + tmpname = &mms_names[i][0];
323 + if (ports[i] == MMS_PORT)
324 + sprintf(tmpname, "mms");
325 + else
326 + sprintf(tmpname, "mms-%d", ports[i]);
327 + mms[i].name = tmpname;
328 +
329 + DEBUGP("ip_conntrack_mms: registering helper for port %d\n",
330 + ports[i]);
331 + ret = ip_conntrack_helper_register(&mms[i]);
332 +
333 + if (ret) {
334 + fini();
335 + return ret;
336 + }
337 + ports_c++;
338 + }
339 + return 0;
340 +}
341 +
342 +module_init(init);
343 +module_exit(fini);
344 diff -urN linux-2.4.32/net/ipv4/netfilter/ip_nat_mms.c linux-2.4.32.new/net/ipv4/netfilter/ip_nat_mms.c
345 --- linux-2.4.32/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
346 +++ linux-2.4.32.new/net/ipv4/netfilter/ip_nat_mms.c 2006-03-01 01:13:32.992148984 +0100
347 @@ -0,0 +1,330 @@
348 +/* MMS extension for TCP NAT alteration.
349 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
350 + * based on ip_nat_ftp.c and ip_nat_irc.c
351 + *
352 + * ip_nat_mms.c v0.3 2002-09-22
353 + *
354 + * This program is free software; you can redistribute it and/or
355 + * modify it under the terms of the GNU General Public License
356 + * as published by the Free Software Foundation; either version
357 + * 2 of the License, or (at your option) any later version.
358 + *
359 + * Module load syntax:
360 + * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
361 + *
362 + * Please give the ports of all MMS servers You wish to connect to.
363 + * If you don't specify ports, the default will be TCP port 1755.
364 + *
365 + * More info on MMS protocol, firewalls and NAT:
366 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
367 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
368 + *
369 + * The SDP project people are reverse-engineering MMS:
370 + * http://get.to/sdp
371 + */
372 +
373 +
374 +#include <linux/module.h>
375 +#include <linux/netfilter_ipv4.h>
376 +#include <linux/ip.h>
377 +#include <linux/tcp.h>
378 +#include <net/tcp.h>
379 +#include <linux/netfilter_ipv4/ip_nat.h>
380 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
381 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
382 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
383 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
384 +
385 +#define DEBUGP(format, args...)
386 +#define DUMP_BYTES(address, counter)
387 +
388 +#define MAX_PORTS 8
389 +static int ports[MAX_PORTS];
390 +static int ports_c = 0;
391 +
392 +#ifdef MODULE_PARM
393 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
394 +#endif
395 +
396 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
397 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
398 +MODULE_LICENSE("GPL");
399 +
400 +DECLARE_LOCK_EXTERN(ip_mms_lock);
401 +
402 +
403 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
404 + struct ip_conntrack *ct,
405 + struct sk_buff **pskb,
406 + enum ip_conntrack_info ctinfo,
407 + struct ip_conntrack_expect *expect)
408 +{
409 + u_int32_t newip;
410 + struct ip_conntrack_tuple t;
411 + struct iphdr *iph = (*pskb)->nh.iph;
412 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
413 + char *data = (char *)tcph + tcph->doff * 4;
414 + int i, j, k, port;
415 + u_int16_t mms_proto;
416 +
417 + u_int32_t *mms_chunkLenLV = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
418 + u_int32_t *mms_chunkLenLM = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
419 + u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
420 +
421 + int zero_padding;
422 +
423 + char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
424 + char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
425 + char proto_string[6];
426 +
427 + MUST_BE_LOCKED(&ip_mms_lock);
428 +
429 + /* what was the protocol again ? */
430 + mms_proto = expect->tuple.dst.protonum;
431 + sprintf(proto_string, "%u", mms_proto);
432 +
433 + DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
434 + expect->seq, ct_mms_info->len, ntohl(tcph->seq),
435 + mms_proto == IPPROTO_UDP ? "UDP"
436 + : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
437 +
438 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
439 +
440 + /* Alter conntrack's expectations. */
441 + t = expect->tuple;
442 + t.dst.ip = newip;
443 + for (port = ct_mms_info->port; port != 0; port++) {
444 + t.dst.u.tcp.port = htons(port);
445 + if (ip_conntrack_change_expect(expect, &t) == 0) {
446 + DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
447 + break;
448 + }
449 + }
450 +
451 + if(port == 0)
452 + return 0;
453 +
454 + sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
455 + NIPQUAD(newip),
456 + expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
457 + : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
458 + port);
459 + DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
460 +
461 + memset(unicode_buffer, 0, sizeof(char)*75);
462 +
463 + for (i=0; i<strlen(buffer); ++i)
464 + *(unicode_buffer+i*2)=*(buffer+i);
465 +
466 + DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
467 + DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
468 + DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
469 +
470 + /* add end of packet to it */
471 + for (j=0; j<ct_mms_info->padding; ++j) {
472 + DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n",
473 + i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
474 + *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
475 + }
476 +
477 + /* pad with zeroes at the end ? see explanation of weird math below */
478 + zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
479 + for (k=0; k<zero_padding; ++k)
480 + *(unicode_buffer+i*2+j+k)= (char)0;
481 +
482 + DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
483 + DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
484 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
485 +
486 + /* explanation, before I forget what I did:
487 + strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
488 + divide by 8 and add 3 to compute the mms_chunkLenLM field,
489 + but note that things may have to be padded with zeroes to align by 8
490 + bytes, hence we add 7 and divide by 8 to get the correct length */
491 + *mms_chunkLenLM = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
492 + *mms_chunkLenLV = *mms_chunkLenLM+2;
493 + *mms_messageLength = *mms_chunkLenLV*8;
494 +
495 + DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
496 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
497 +
498 + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
499 + expect->seq - ntohl(tcph->seq),
500 + ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
501 + strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
502 + DUMP_BYTES(unicode_buffer, 60);
503 +
504 + return 1;
505 +}
506 +
507 +static unsigned int
508 +mms_nat_expected(struct sk_buff **pskb,
509 + unsigned int hooknum,
510 + struct ip_conntrack *ct,
511 + struct ip_nat_info *info)
512 +{
513 + struct ip_nat_multi_range mr;
514 + u_int32_t newdstip, newsrcip, newip;
515 +
516 + struct ip_conntrack *master = master_ct(ct);
517 +
518 + IP_NF_ASSERT(info);
519 + IP_NF_ASSERT(master);
520 +
521 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
522 +
523 + DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
524 +
525 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
526 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
527 + DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
528 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
529 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
530 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
531 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
532 +
533 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
534 + newip = newsrcip;
535 + else
536 + newip = newdstip;
537 +
538 + DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
539 +
540 + mr.rangesize = 1;
541 + /* We don't want to manip the per-protocol, just the IPs. */
542 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
543 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
544 +
545 + return ip_nat_setup_info(ct, &mr, hooknum);
546 +}
547 +
548 +
549 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
550 + struct ip_conntrack_expect *exp,
551 + struct ip_nat_info *info,
552 + enum ip_conntrack_info ctinfo,
553 + unsigned int hooknum,
554 + struct sk_buff **pskb)
555 +{
556 + struct iphdr *iph = (*pskb)->nh.iph;
557 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
558 + unsigned int datalen;
559 + int dir;
560 + struct ip_ct_mms_expect *ct_mms_info;
561 +
562 + if (!exp)
563 + DEBUGP("ip_nat_mms: no exp!!");
564 +
565 + ct_mms_info = &exp->help.exp_mms_info;
566 +
567 + /* Only mangle things once: original direction in POST_ROUTING
568 + and reply direction on PRE_ROUTING. */
569 + dir = CTINFO2DIR(ctinfo);
570 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
571 + ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
572 + DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
573 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
574 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
575 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
576 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
577 + return NF_ACCEPT;
578 + }
579 + DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
580 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
581 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
582 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
583 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
584 +
585 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
586 +
587 + DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
588 + exp->seq + ct_mms_info->len,
589 + ntohl(tcph->seq),
590 + ntohl(tcph->seq) + datalen);
591 +
592 + LOCK_BH(&ip_mms_lock);
593 + /* Check wether the whole IP/proto/port pattern is carried in the payload */
594 + if (between(exp->seq + ct_mms_info->len,
595 + ntohl(tcph->seq),
596 + ntohl(tcph->seq) + datalen)) {
597 + if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
598 + UNLOCK_BH(&ip_mms_lock);
599 + return NF_DROP;
600 + }
601 + } else {
602 + /* Half a match? This means a partial retransmisison.
603 + It's a cracker being funky. */
604 + if (net_ratelimit()) {
605 + printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
606 + exp->seq, ct_mms_info->len,
607 + ntohl(tcph->seq),
608 + ntohl(tcph->seq) + datalen);
609 + }
610 + UNLOCK_BH(&ip_mms_lock);
611 + return NF_DROP;
612 + }
613 + UNLOCK_BH(&ip_mms_lock);
614 +
615 + return NF_ACCEPT;
616 +}
617 +
618 +static struct ip_nat_helper mms[MAX_PORTS];
619 +static char mms_names[MAX_PORTS][10];
620 +
621 +/* Not __exit: called from init() */
622 +static void fini(void)
623 +{
624 + int i;
625 +
626 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
627 + DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
628 + ip_nat_helper_unregister(&mms[i]);
629 + }
630 +}
631 +
632 +static int __init init(void)
633 +{
634 + int i, ret = 0;
635 + char *tmpname;
636 +
637 + if (ports[0] == 0)
638 + ports[0] = MMS_PORT;
639 +
640 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
641 +
642 + memset(&mms[i], 0, sizeof(struct ip_nat_helper));
643 +
644 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
645 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
646 + mms[i].mask.dst.protonum = 0xFFFF;
647 + mms[i].mask.src.u.tcp.port = 0xFFFF;
648 + mms[i].help = mms_nat_help;
649 + mms[i].me = THIS_MODULE;
650 + mms[i].flags = 0;
651 + mms[i].expect = mms_nat_expected;
652 +
653 + tmpname = &mms_names[i][0];
654 + if (ports[i] == MMS_PORT)
655 + sprintf(tmpname, "mms");
656 + else
657 + sprintf(tmpname, "mms-%d", i);
658 + mms[i].name = tmpname;
659 +
660 + DEBUGP("ip_nat_mms: register helper for port %d\n",
661 + ports[i]);
662 + ret = ip_nat_helper_register(&mms[i]);
663 +
664 + if (ret) {
665 + printk("ip_nat_mms: error registering "
666 + "helper for port %d\n", ports[i]);
667 + fini();
668 + return ret;
669 + }
670 + ports_c++;
671 + }
672 +
673 + return ret;
674 +}
675 +
676 +module_init(init);
677 +module_exit(fini);
678 diff -urN linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack.h
679 --- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h 2006-03-01 01:12:47.910002512 +0100
680 +++ linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack.h 2006-03-01 01:16:16.710260048 +0100
681 @@ -73,6 +73,7 @@
682 #include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
683 #include <linux/netfilter_ipv4/ip_conntrack_h323.h>
684 #include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
685 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
686
687 /* per expectation: application helper private data */
688 union ip_conntrack_expect_help {
689 @@ -83,6 +84,7 @@
690 struct ip_ct_pptp_expect exp_pptp_info;
691 struct ip_ct_h225_expect exp_h225_info;
692 struct ip_ct_rtsp_expect exp_rtsp_info;
693 + struct ip_ct_mms_expect exp_mms_info;
694
695 #ifdef CONFIG_IP_NF_NAT_NEEDED
696 union {
697 @@ -99,6 +101,7 @@
698 struct ip_ct_pptp_master ct_pptp_info;
699 struct ip_ct_h225_master ct_h225_info;
700 struct ip_ct_rtsp_master ct_rtsp_info;
701 + struct ip_ct_mms_master ct_mms_info;
702 };
703
704 #ifdef CONFIG_IP_NF_NAT_NEEDED
705 diff -urN linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack_mms.h
706 --- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
707 +++ linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack_mms.h 2006-03-01 01:13:32.993148832 +0100
708 @@ -0,0 +1,31 @@
709 +#ifndef _IP_CONNTRACK_MMS_H
710 +#define _IP_CONNTRACK_MMS_H
711 +/* MMS tracking. */
712 +
713 +#ifdef __KERNEL__
714 +#include <linux/netfilter_ipv4/lockhelp.h>
715 +
716 +DECLARE_LOCK_EXTERN(ip_mms_lock);
717 +
718 +#define MMS_PORT 1755
719 +#define MMS_SRV_MSG_ID 196610
720 +
721 +#define MMS_SRV_MSG_OFFSET 36
722 +#define MMS_SRV_UNICODE_STRING_OFFSET 60
723 +#define MMS_SRV_CHUNKLENLV_OFFSET 16
724 +#define MMS_SRV_CHUNKLENLM_OFFSET 32
725 +#define MMS_SRV_MESSAGELENGTH_OFFSET 8
726 +#endif
727 +
728 +/* This structure is per expected connection */
729 +struct ip_ct_mms_expect {
730 + u_int32_t len;
731 + u_int32_t padding;
732 + u_int16_t port;
733 +};
734 +
735 +/* This structure exists only once per master */
736 +struct ip_ct_mms_master {
737 +};
738 +
739 +#endif /* _IP_CONNTRACK_MMS_H */