1 diff -NurpP --minimal linux-2.6.21.a/include/linux/netfilter/nf_conntrack_mms.h linux-2.6.21.b/include/linux/netfilter/nf_conntrack_mms.h
2 --- linux-2.6.21.a/include/linux/netfilter/nf_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.21.b/include/linux/netfilter/nf_conntrack_mms.h 2007-05-30 11:50:55.000000000 +0200
5 +#ifndef _IP_CONNTRACK_MMS_H
6 +#define _IP_CONNTRACK_MMS_H
11 +#define MMS_PORT 1755
12 +#define MMS_SRV_MSG_ID 196610
14 +#define MMS_SRV_MSG_OFFSET 36
15 +#define MMS_SRV_UNICODE_STRING_OFFSET 60
16 +#define MMS_SRV_CHUNKLENLV_OFFSET 16
17 +#define MMS_SRV_CHUNKLENLM_OFFSET 32
18 +#define MMS_SRV_MESSAGELENGTH_OFFSET 8
20 +/* This structure is per expected connection */
21 +struct nf_ct_mms_expect {
28 +/* This structure exists only once per master */
29 +struct nf_ct_mms_master {
32 +struct nf_conntrack_expect;
33 +extern unsigned int (*nf_nat_mms_hook)(struct sk_buff **pskb,
34 + enum ip_conntrack_info ctinfo,
35 + const struct nf_ct_mms_expect *exp_mms_info,
36 + struct nf_conntrack_expect *exp);
38 +#endif /* _IP_CONNTRACK_MMS_H */
39 diff -NurpP --minimal linux-2.6.21.a/include/net/netfilter/nf_conntrack.h linux-2.6.21.b/include/net/netfilter/nf_conntrack.h
40 --- linux-2.6.21.a/include/net/netfilter/nf_conntrack.h 2007-05-30 11:14:07.000000000 +0200
41 +++ linux-2.6.21.b/include/net/netfilter/nf_conntrack.h 2007-05-30 11:50:55.000000000 +0200
42 @@ -46,6 +46,7 @@ union nf_conntrack_expect_proto {
43 #include <linux/netfilter/nf_conntrack_h323.h>
44 #include <linux/netfilter/nf_conntrack_sane.h>
45 #include <linux/netfilter/nf_conntrack_sip.h>
46 +#include <linux/netfilter/nf_conntrack_mms.h>
48 /* per conntrack: application helper private data */
49 union nf_conntrack_help {
51 #if defined(CONFIG_NF_CONNTRACK_SIP) || defined(CONFIG_NF_CONNTRACK_SIP_MODULE)
52 struct nf_ct_sip_master ct_sip_info;
54 +#if defined(CONFIG_NF_NAT_MMS) || defined(CONFIG_NF_NAT_MMS_MODULE)
55 + struct nf_ct_mms_master ct_mms_info;
59 #include <linux/types.h>
60 diff -NurpP --minimal linux-2.6.21.a/include/net/netfilter/nf_conntrack_mms.h linux-2.6.21.b/include/net/netfilter/nf_conntrack_mms.h
61 --- linux-2.6.21.a/include/net/netfilter/nf_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
62 +++ linux-2.6.21.b/include/net/netfilter/nf_conntrack_mms.h 2007-05-30 11:50:55.000000000 +0200
64 +#ifndef _IP_CONNTRACK_MMS_H
65 +#define _IP_CONNTRACK_MMS_H
70 +#define MMS_PORT 1755
71 +#define MMS_SRV_MSG_ID 196610
73 +#define MMS_SRV_MSG_OFFSET 36
74 +#define MMS_SRV_UNICODE_STRING_OFFSET 60
75 +#define MMS_SRV_CHUNKLENLV_OFFSET 16
76 +#define MMS_SRV_CHUNKLENLM_OFFSET 32
77 +#define MMS_SRV_MESSAGELENGTH_OFFSET 8
79 +/* This structure is per expected connection */
80 +struct nf_ct_mms_expect {
87 +/* This structure exists only once per master */
88 +struct nf_ct_mms_master {
91 +struct nf_conntrack_expect;
92 +extern unsigned int (*nf_nat_mms_hook)(struct sk_buff **pskb,
93 + enum ip_conntrack_info ctinfo,
94 + const struct nf_ct_mms_expect *exp_mms_info,
95 + struct nf_conntrack_expect *exp);
97 +#endif /* _IP_CONNTRACK_MMS_H */
98 diff -NurpP --minimal linux-2.6.21.a/net/ipv4/netfilter/Kconfig linux-2.6.21.b/net/ipv4/netfilter/Kconfig
99 --- linux-2.6.21.a/net/ipv4/netfilter/Kconfig 2007-05-30 11:44:12.000000000 +0200
100 +++ linux-2.6.21.b/net/ipv4/netfilter/Kconfig 2007-05-30 11:50:55.000000000 +0200
101 @@ -543,6 +543,11 @@ config NF_NAT_H323
102 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
103 default NF_NAT && NF_CONNTRACK_H323
107 + depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
108 + default NF_NAT && NF_CONNTRACK_MMS
112 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
113 @@ -847,5 +852,23 @@ config IP_NF_TARGET_TARPIT
114 hardware or IPs. Any TCP port that you would normally DROP or REJECT
115 can instead become a tarpit.
117 +config IP_NF_NAT_MMS
119 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
120 + default IP_NF_NAT if IP_NF_MMS=y
121 + default m if IP_NF_MMS=m
124 + tristate 'MMS protocol support'
125 + depends on IP_NF_CONNTRACK
127 + Tracking MMS (Microsoft Windows Media Services) connections
128 + could be problematic if random ports are used to send the
129 + streaming content. This option allows users to track streaming
130 + connections over random UDP or TCP ports.
132 + If you want to compile it as a module, say M here and read
133 + <file:Documentation/modules.txt>. If unsure, say `Y'.
137 diff -NurpP --minimal linux-2.6.21.a/net/ipv4/netfilter/Makefile linux-2.6.21.b/net/ipv4/netfilter/Makefile
138 --- linux-2.6.21.a/net/ipv4/netfilter/Makefile 2007-05-30 11:44:12.000000000 +0200
139 +++ linux-2.6.21.b/net/ipv4/netfilter/Makefile 2007-05-30 11:50:55.000000000 +0200
141 +obj-$(CONFIG_NF_NAT_MMS) += nf_nat_mms.o
142 diff -NurpP --minimal linux-2.6.21.a/net/ipv4/netfilter/nf_nat_mms.c linux-2.6.21.b/net/ipv4/netfilter/nf_nat_mms.c
143 --- linux-2.6.21.a/net/ipv4/netfilter/nf_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
144 +++ linux-2.6.21.b/net/ipv4/netfilter/nf_nat_mms.c 2007-05-30 11:50:55.000000000 +0200
146 +/* MMS extension for TCP NAT alteration.
147 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
148 + * based on ip_nat_ftp.c and ip_nat_irc.c
150 + * ip_nat_mms.c v0.3 2002-09-22
152 + * This program is free software; you can redistribute it and/or
153 + * modify it under the terms of the GNU General Public License
154 + * as published by the Free Software Foundation; either version
155 + * 2 of the License, or (at your option) any later version.
157 + * Module load syntax:
158 + * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
160 + * Please give the ports of all MMS servers You wish to connect to.
161 + * If you don't specify ports, the default will be TCP port 1755.
163 + * More info on MMS protocol, firewalls and NAT:
164 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
165 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
167 + * The SDP project people are reverse-engineering MMS:
168 + * http://get.to/sdp
170 + * 2005-02-13: Harald Welte <laforge@netfilter.org>
172 + * - update to work with post 2.6.11 helper API changes
174 + * 2007-03-30: Marek Guevara Braun <mguevara@pld-linux.org>
175 + * - port to nf_conntrack
178 +/* FIXME: issue with UDP & fragmentation with this URL:
179 + http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx
180 + may be related to out-of-order first packets:
181 + basically the expectation is set up correctly, then the server sends
182 + a first UDP packet which is fragmented plus arrives out-of-order.
183 + the MASQUERADING firewall with ip_nat_mms loaded responds with
184 + an ICMP unreachable back to the server */
186 +#include <linux/module.h>
187 +#include <linux/netfilter_ipv4.h>
188 +#include <linux/ip.h>
189 +#include <linux/tcp.h>
190 +#include <net/tcp.h>
191 +#include <net/netfilter/nf_nat.h>
192 +#include <net/netfilter/nf_nat_helper.h>
193 +#include <net/netfilter/nf_nat_rule.h>
194 +#include <net/netfilter/nf_conntrack_helper.h>
195 +#include <net/netfilter/nf_conntrack_expect.h>
196 +#include <linux/netfilter/nf_conntrack_mms.h>
198 +#define NIPQUAD(addr) \
199 + ((unsigned char *)&addr)[0], \
200 + ((unsigned char *)&addr)[1], \
201 + ((unsigned char *)&addr)[2], \
202 + ((unsigned char *)&addr)[3]
205 +#define DEBUGP printk
206 +#define DUMP_BYTES(address, counter) \
208 + int temp_counter; \
209 + for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
210 + DEBUGP("%u ", (u8)*(address+temp_counter)); \
215 +#define DEBUGP(format, args...)
216 +#define DUMP_BYTES(address, counter)
219 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
220 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
221 +MODULE_LICENSE("GPL");
223 +static unsigned int mms_data_fixup(struct sk_buff **pskb,
224 + enum ip_conntrack_info ctinfo,
225 + const struct nf_ct_mms_expect *ct_mms_info,
226 + struct nf_conntrack_expect *expect)
229 + struct nf_conn *ct = expect->master;
230 + struct iphdr *iph = ip_hdr(*pskb);
231 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
232 + char *data = (char *)tcph + tcph->doff * 4;
234 + u_int16_t mms_proto;
236 + u_int32_t *mms_chunkLenLV = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
237 + u_int32_t *mms_chunkLenLM = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
238 + u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
242 + char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2
244 + char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
245 + char proto_string[6];
247 + /* what was the protocol again ? */
248 + mms_proto = expect->tuple.dst.protonum;
249 + sprintf(proto_string, "%u", mms_proto);
251 + DEBUGP("nf_nat_mms: mms_data_fixup: info (seq %u + %u) "
252 + "in %u, proto %s\n",
253 + expect->seq, ct_mms_info->len, ntohl(tcph->seq),
254 + mms_proto == IPPROTO_UDP ? "UDP"
255 + : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
257 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip;
258 + expect->saved_proto.tcp.port = expect->tuple.dst.u.tcp.port;
259 + expect->expectfn = nf_nat_follow_master;
261 + /* Alter conntrack's expectations. */
262 + for (port = ct_mms_info->port; port != 0; port++) {
263 + expect->tuple.dst.u.tcp.port = htons(port);
264 + if (nf_ct_expect_related(expect) == 0) {
265 + DEBUGP("nf_nat_mms: mms_data_fixup: using port %d\n",
274 + sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
276 + expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
277 + : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
279 + DEBUGP("nf_nat_mms: new unicode string=%s\n", buffer);
281 + memset(unicode_buffer, 0, sizeof(char)*75);
283 + for (i=0; i<strlen(buffer); ++i)
284 + *(unicode_buffer+i*2)=*(buffer+i);
286 + DEBUGP("nf_nat_mms: mms_data_fixup: padding: %u len: %u\n",
287 + ct_mms_info->padding, ct_mms_info->len);
288 + DEBUGP("nf_nat_mms: mms_data_fixup: offset: %u\n",
289 + MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
290 + DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
292 + /* add end of packet to it */
293 + for (j=0; j<ct_mms_info->padding; ++j) {
294 + DEBUGP("nf_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n",
295 + i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
296 + *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
299 + /* pad with zeroes at the end ? see explanation of weird math below */
300 + zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
301 + for (k=0; k<zero_padding; ++k)
302 + *(unicode_buffer+i*2+j+k)= (char)0;
304 + DEBUGP("nf_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
305 + DEBUGP("nf_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u "
306 + "messageLength=%u\n", *mms_chunkLenLV, *mms_chunkLenLM,
307 + *mms_messageLength);
309 + /* explanation, before I forget what I did:
310 + strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
311 + divide by 8 and add 3 to compute the mms_chunkLenLM field,
312 + but note that things may have to be padded with zeroes to align by 8
313 + bytes, hence we add 7 and divide by 8 to get the correct length */
314 + *mms_chunkLenLM = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
315 + *mms_chunkLenLV = *mms_chunkLenLM+2;
316 + *mms_messageLength = *mms_chunkLenLV*8;
318 + DEBUGP("nf_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u"
319 + " messageLength=%u\n", *mms_chunkLenLV, *mms_chunkLenLM,
320 + *mms_messageLength);
322 + nf_nat_mangle_tcp_packet(*pskb, ct, ctinfo,
323 + ct_mms_info->offset,
324 + ct_mms_info->len + ct_mms_info->padding,
325 + unicode_buffer, strlen(buffer)*2 +
326 + ct_mms_info->padding + zero_padding);
327 + DUMP_BYTES(unicode_buffer, 60);
332 +static void __exit fini(void)
334 + nf_nat_mms_hook = NULL;
338 +static int __init init(void)
340 + BUG_ON(nf_nat_mms_hook);
341 + nf_nat_mms_hook = &mms_data_fixup;
348 diff -NurpP --minimal linux-2.6.21.a/net/netfilter/Kconfig linux-2.6.21.b/net/netfilter/Kconfig
349 --- linux-2.6.21.a/net/netfilter/Kconfig 2007-05-30 11:13:04.000000000 +0200
350 +++ linux-2.6.21.b/net/netfilter/Kconfig 2007-05-30 11:50:55.000000000 +0200
351 @@ -271,6 +271,18 @@ config NF_CONNTRACK_TFTP
353 To compile it as a module, choose M here. If unsure, say N.
355 +config NF_CONNTRACK_MMS
356 + tristate 'MMS protocol support'
357 + depends on NF_CONNTRACK
359 + Tracking MMS (Microsoft Windows Media Services) connections
360 + could be problematic if random ports are used to send the
361 + streaming content. This option allows users to track streaming
362 + connections over random UDP or TCP ports.
364 + If you want to compile it as a module, say M here and read
365 + <file:Documentation/modules.txt>. If unsure, say `Y'.
368 tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
369 depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK
370 diff -NurpP --minimal linux-2.6.21.a/net/netfilter/Makefile linux-2.6.21.b/net/netfilter/Makefile
371 --- linux-2.6.21.a/net/netfilter/Makefile 2007-05-30 11:13:04.000000000 +0200
372 +++ linux-2.6.21.b/net/netfilter/Makefile 2007-05-30 11:50:55.000000000 +0200
373 @@ -26,6 +26,7 @@ nf_conntrack_h323-objs := nf_conntrack_h
374 obj-$(CONFIG_NF_CONNTRACK_AMANDA) += nf_conntrack_amanda.o
375 obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
376 obj-$(CONFIG_NF_CONNTRACK_H323) += nf_conntrack_h323.o
377 +obj-$(CONFIG_NF_CONNTRACK_MMS) += nf_conntrack_mms.o
378 obj-$(CONFIG_NF_CONNTRACK_IRC) += nf_conntrack_irc.o
379 obj-$(CONFIG_NF_CONNTRACK_NETBIOS_NS) += nf_conntrack_netbios_ns.o
380 obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_conntrack_pptp.o
381 diff -NurpP --minimal linux-2.6.21.a/net/netfilter/nf_conntrack_mms.c linux-2.6.21.b/net/netfilter/nf_conntrack_mms.c
382 --- linux-2.6.21.a/net/netfilter/nf_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
383 +++ linux-2.6.21.b/net/netfilter/nf_conntrack_mms.c 2007-05-30 11:50:55.000000000 +0200
385 +/* MMS extension for IP connection tracking
386 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
387 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
389 + * ip_conntrack_mms.c v0.3 2002-09-22
391 + * This program is free software; you can redistribute it and/or
392 + * modify it under the terms of the GNU General Public License
393 + * as published by the Free Software Foundation; either version
394 + * 2 of the License, or (at your option) any later version.
396 + * Module load syntax:
397 + * insmod nf_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
399 + * Please give the ports of all MMS servers You wish to connect to.
400 + * If you don't specify ports, the default will be TCP port 1755.
402 + * More info on MMS protocol, firewalls and NAT:
403 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
404 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
406 + * The SDP project people are reverse-engineering MMS:
407 + * http://get.to/sdp
409 + * 2005-02-13: Harald Welte <laforge@netfilter.org>
411 + * - update to work with post 2.6.11 helper API changes
413 + * 2007-03-30: Marek Guevara Braun <mguevara@pld-linux.org>
414 + * - port to nf_conntrack
418 +#include <linux/module.h>
419 +#include <linux/netfilter.h>
420 +#include <linux/ip.h>
421 +#include <linux/ctype.h>
422 +#include <net/checksum.h>
423 +#include <net/tcp.h>
425 +#include <net/netfilter/nf_conntrack.h>
426 +#include <net/netfilter/nf_conntrack_helper.h>
427 +#include <net/netfilter/nf_conntrack_expect.h>
428 +#include <linux/netfilter/nf_conntrack_mms.h>
431 +static int ports[MAX_PORTS];
433 +module_param_array(ports, int, &ports_c, 0400);
434 +MODULE_PARM_DESC(ports, "port numbers of MMS");
436 +static char mms_buffer[65536];
437 +static DEFINE_SPINLOCK(mms_buffer_lock);
439 +unsigned int (*nf_nat_mms_hook)(struct sk_buff **pskb,
440 + enum ip_conntrack_info ctinfo,
441 + const struct nf_ct_mms_expect *exp_mms_info,
442 + struct nf_conntrack_expect *exp);
443 +EXPORT_SYMBOL(nf_nat_mms_hook);
446 +#define DEBUGP printk
448 +#define DEBUGP(format, args...)
451 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
452 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
453 +MODULE_LICENSE("GPL");
455 +/* #define isdigit(c) (c >= '0' && c <= '9') */
457 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
458 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
461 + for (i = 0; i < unicode_size; ++i) {
462 + string[i] = (char)(unicode[i]);
464 + string[unicode_size] = 0x00;
467 +__inline static int atoi(char *s)
470 + while (isdigit(*s)) {
471 + i = i*10 + *(s++) - '0';
476 +/* convert ip address string like "192.168.0.10" to unsigned int */
477 +__inline static u_int32_t asciiiptoi(char *s)
479 + unsigned int i, j, k;
481 + for(i=k=0; k<3; ++k, ++s, i<<=8) {
483 + for(j=0; (*(++s) != '.') && (j<3); ++j)
490 +int parse_mms(const char *data,
491 + const unsigned int datalen,
493 + u_int16_t *mms_proto,
494 + u_int16_t *mms_port,
495 + char **mms_string_b,
496 + char **mms_string_e,
497 + char **mms_padding_e)
499 + int unicode_size, i;
500 + char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
501 + char getlengthstring[28];
503 + for(unicode_size=0;
504 + (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
506 + if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
507 + return -1; /* out of bounds - incomplete packet */
509 + unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
510 + DEBUGP("nf_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
513 + *mms_ip = asciiiptoi(tempstring+2);
515 + i=sprintf(getlengthstring, "%pI4", mms_ip);
518 + if(strncmp(tempstring+3+i, "TCP", 3)==0)
519 + *mms_proto = IPPROTO_TCP;
520 + else if(strncmp(tempstring+3+i, "UDP", 3)==0)
521 + *mms_proto = IPPROTO_UDP;
524 + *mms_port = atoi(tempstring+7+i);
526 + /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port"
527 + unicode string, one to the end of the string, and one to the end
528 + of the packet, since we must keep track of the number of bytes
529 + between end of the unicode string and the end of packet (padding) */
530 + *mms_string_b = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
531 + *mms_string_e = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
532 + *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
537 +/* FIXME: This should be in userspace. Later. */
538 +static int help(struct sk_buff **pskb,
539 + unsigned int protoff,
540 + struct nf_conn *ct,
541 + enum ip_conntrack_info ctinfo)
544 + struct tcphdr _tcph, *th;
545 + char *data, *mb_ptr;
546 + unsigned int datalen, dataoff;
549 + //struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
550 + //unsigned int tcplen = len - iph->ihl * 4;
551 + //unsigned int datalen = tcplen - tcph->doff * 4;
552 + int dir = CTINFO2DIR(ctinfo);
553 + struct nf_conntrack_expect *exp;
554 + struct nf_conntrack_tuple *tuple;
555 + struct nf_ct_mms_expect _emmi, *exp_mms_info = &_emmi;
558 + u_int16_t mms_proto;
559 + char mms_proto_string[8];
560 + u_int16_t mms_port;
562 + char *mms_string_b, *mms_string_e, *mms_padding_e;
563 + typeof(nf_nat_mms_hook) nf_nat_mms;
565 + /* Until there's been traffic both ways, don't look in packets. */
566 + if (ctinfo != IP_CT_ESTABLISHED &&
567 + ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
568 + DEBUGP("nf_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
572 + /* Not whole TCP header? */
573 + th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph);
578 + dataoff = protoff + th->doff*4;
579 + if (dataoff >= (*pskb)->len)
582 + datalen = (*pskb)->len - dataoff;
583 + DEBUGP("nf_conntrack_mms: datalen:%u\n", datalen);
585 + spin_lock_bh(&mms_buffer_lock);
586 + mb_ptr = skb_header_pointer(*pskb, dataoff,
587 + (*pskb)->len - dataoff, mms_buffer);
588 + BUG_ON(mb_ptr == NULL);
593 + /* Checksum invalid? Ignore. */
594 + /* FIXME: Source route IP option packets --RR */
595 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
596 + csum_partial((char *)tcph, tcplen, 0))) {
597 + DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
598 + tcph, tcplen, NIPQUAD(iph->saddr),
599 + NIPQUAD(iph->daddr));
604 + /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP
607 + /* FIXME: There is an issue with only looking at this packet: before
608 + * this packet, the client has already sent a packet to the server with
609 + * the server's hostname according to the client (think of it as the
610 + * "Host: " header in HTTP/1.1). The server will break the connection
611 + * if this doesn't correspond to its own host header. The client can
612 + * also connect to an IP address; if it's the server's IP address, it
613 + * will not break the connection. When doing DNAT on a connection where
614 + * the client uses a server's IP address, the nat module should detect
615 + * this and change this string accordingly to the DNATed address. This
616 + * should probably be done by checking for an IP address, then storing
617 + * it as a member of struct ip_ct_mms_expect and checking for it in
620 + if ((MMS_SRV_MSG_OFFSET >= datalen) ||
621 + ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) != MMS_SRV_MSG_ID))
624 + DEBUGP("nf_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n",
625 + (u8)*(data+36), (u8)*(data+37), (u8)*(data+38), (u8)*(data+39),
627 + if (parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
628 + &mms_string_b, &mms_string_e, &mms_padding_e))
629 + if (net_ratelimit())
630 + /* FIXME: more verbose debugging ? */
631 + printk(KERN_WARNING
632 + "nf_conntrack_mms: Unable to parse "
635 + sprintf(mms_proto_string, "(%u)", mms_proto);
636 + DEBUGP("nf_conntrack_mms: adding %s expectation "
637 + "%u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
638 + mms_proto == IPPROTO_TCP ? "TCP"
639 + : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
640 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
644 + /* it's possible that the client will just ask the server to
645 + * tunnel the stream over the same TCP session (from port
646 + * 1755): there's shouldn't be a need to add an expectation in
647 + * that case, but it makes NAT packet mangling so much easier
650 + DEBUGP("nf_conntrack_mms: tcph->seq = %u\n", tcph->seq);
652 + exp = nf_ct_expect_alloc(ct);
658 + exp_mms_info->offset = (mms_string_b - data);
659 + exp_mms_info->len = (mms_string_e - mms_string_b);
660 + exp_mms_info->padding = (mms_padding_e - mms_string_e);
661 + exp_mms_info->port = mms_port;
663 + DEBUGP("nf_conntrack_mms: wrote info seq=%u (ofs=%u), "
664 + "len=%d, padding=%u\n", exp->seq, (mms_string_e - data),
665 + exp_mms_info->len, exp_mms_info->padding);
667 + tuple = &ct->tuplehash[!dir].tuple;
668 + port = htons(mms_port);
669 + nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, tuple->src.l3num,
670 + NULL, &tuple->dst.u3,
671 + IPPROTO_TCP, NULL, &port);
673 + nf_nat_mms = rcu_dereference(nf_nat_mms_hook);
674 + if (nf_nat_mms && ct->status & IPS_NAT_MASK)
675 + ret = nf_nat_mms(pskb, ctinfo, exp_mms_info, exp);
676 + else if (nf_ct_expect_related(exp) != 0)
678 + nf_ct_expect_put(exp);
680 + exp->tuple = ((struct nf_conntrack_tuple)
681 + { { ct->tuplehash[!dir].tuple.src.u3.ip, { 0 } },
683 + { .tcp = { (__u16) ntohs(mms_port) } },
686 + exp->mask = ((struct nf_conntrack_tuple)
687 + { { 0xFFFFFFFF, { 0 } },
688 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
689 + exp->expectfn = NULL;
692 + if (nf_nat_mms_hook)
693 + ret = nf_nat_mms_hook(pskb, ctinfo, exp_mms_info, exp);
694 + else if (nf_conntrack_expect_related(exp) != 0)
697 + nf_conntrack_expect_put(exp);
700 + spin_unlock_bh(&mms_buffer_lock);
704 +static struct nf_conntrack_helper mms[MAX_PORTS];
705 +static char mms_names[MAX_PORTS][10];
706 +static const struct nf_conntrack_expect_policy mms_exp_policy = {
711 +/* Not __exit: called from init() */
712 +static void fini(void)
715 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
716 + DEBUGP("nf_conntrack_mms: unregistering helper for port %d\n",
718 + nf_conntrack_helper_unregister(&mms[i]);
722 +static int __init init(void)
728 + ports[0] = MMS_PORT;
730 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
731 + memset(&mms[i], 0, sizeof(struct nf_conntrack_helper));
732 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
733 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
734 + mms[i].me = THIS_MODULE;
735 + mms[i].expect_policy = &mms_exp_policy;
736 + mms[i].help = help;
738 + tmpname = &mms_names[i][0];
739 + if (ports[i] == MMS_PORT)
740 + sprintf(tmpname, "mms");
742 + sprintf(tmpname, "mms-%d", ports[i]);
743 + mms[i].name = tmpname;
745 + DEBUGP("nf_conntrack_mms: registering helper for port %d\n",
747 + ret = nf_conntrack_helper_register(&mms[i]);