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