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