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 {
50 @@ -54,6 +55,7 @@ union nf_conntrack_help {
51 struct nf_ct_h323_master ct_h323_info;
52 struct nf_ct_sane_master ct_sane_info;
53 struct nf_ct_sip_master ct_sip_info;
54 + struct nf_ct_mms_master ct_mms_info;
57 #include <linux/types.h>
58 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
59 --- linux-2.6.21.a/include/net/netfilter/nf_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
60 +++ linux-2.6.21.b/include/net/netfilter/nf_conntrack_mms.h 2007-05-30 11:50:55.000000000 +0200
62 +#ifndef _IP_CONNTRACK_MMS_H
63 +#define _IP_CONNTRACK_MMS_H
68 +#define MMS_PORT 1755
69 +#define MMS_SRV_MSG_ID 196610
71 +#define MMS_SRV_MSG_OFFSET 36
72 +#define MMS_SRV_UNICODE_STRING_OFFSET 60
73 +#define MMS_SRV_CHUNKLENLV_OFFSET 16
74 +#define MMS_SRV_CHUNKLENLM_OFFSET 32
75 +#define MMS_SRV_MESSAGELENGTH_OFFSET 8
77 +/* This structure is per expected connection */
78 +struct nf_ct_mms_expect {
85 +/* This structure exists only once per master */
86 +struct nf_ct_mms_master {
89 +struct nf_conntrack_expect;
90 +extern unsigned int (*nf_nat_mms_hook)(struct sk_buff **pskb,
91 + enum ip_conntrack_info ctinfo,
92 + const struct nf_ct_mms_expect *exp_mms_info,
93 + struct nf_conntrack_expect *exp);
95 +#endif /* _IP_CONNTRACK_MMS_H */
96 diff -NurpP --minimal linux-2.6.21.a/net/ipv4/netfilter/Kconfig linux-2.6.21.b/net/ipv4/netfilter/Kconfig
97 --- linux-2.6.21.a/net/ipv4/netfilter/Kconfig 2007-05-30 11:44:12.000000000 +0200
98 +++ linux-2.6.21.b/net/ipv4/netfilter/Kconfig 2007-05-30 11:50:55.000000000 +0200
99 @@ -543,6 +543,11 @@ config NF_NAT_H323
100 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
101 default NF_NAT && NF_CONNTRACK_H323
105 + depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
106 + default NF_NAT && NF_CONNTRACK_MMS
110 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
111 @@ -847,5 +852,23 @@ config IP_NF_TARGET_TARPIT
112 hardware or IPs. Any TCP port that you would normally DROP or REJECT
113 can instead become a tarpit.
115 +config IP_NF_NAT_MMS
117 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
118 + default IP_NF_NAT if IP_NF_MMS=y
119 + default m if IP_NF_MMS=m
122 + tristate 'MMS protocol support'
123 + depends on IP_NF_CONNTRACK
125 + Tracking MMS (Microsoft Windows Media Services) connections
126 + could be problematic if random ports are used to send the
127 + streaming content. This option allows users to track streaming
128 + connections over random UDP or TCP ports.
130 + If you want to compile it as a module, say M here and read
131 + <file:Documentation/modules.txt>. If unsure, say `Y'.
135 diff -NurpP --minimal linux-2.6.21.a/net/ipv4/netfilter/Makefile linux-2.6.21.b/net/ipv4/netfilter/Makefile
136 --- linux-2.6.21.a/net/ipv4/netfilter/Makefile 2007-05-30 11:44:12.000000000 +0200
137 +++ linux-2.6.21.b/net/ipv4/netfilter/Makefile 2007-05-30 11:50:55.000000000 +0200
139 +obj-$(CONFIG_NF_NAT_MMS) += nf_nat_mms.o
140 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
141 --- linux-2.6.21.a/net/ipv4/netfilter/nf_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
142 +++ linux-2.6.21.b/net/ipv4/netfilter/nf_nat_mms.c 2007-05-30 11:50:55.000000000 +0200
144 +/* MMS extension for TCP NAT alteration.
145 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
146 + * based on ip_nat_ftp.c and ip_nat_irc.c
148 + * ip_nat_mms.c v0.3 2002-09-22
150 + * This program is free software; you can redistribute it and/or
151 + * modify it under the terms of the GNU General Public License
152 + * as published by the Free Software Foundation; either version
153 + * 2 of the License, or (at your option) any later version.
155 + * Module load syntax:
156 + * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
158 + * Please give the ports of all MMS servers You wish to connect to.
159 + * If you don't specify ports, the default will be TCP port 1755.
161 + * More info on MMS protocol, firewalls and NAT:
162 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
163 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
165 + * The SDP project people are reverse-engineering MMS:
166 + * http://get.to/sdp
168 + * 2005-02-13: Harald Welte <laforge@netfilter.org>
170 + * - update to work with post 2.6.11 helper API changes
172 + * 2007-03-30: Marek Guevara Braun <mguevara@pld-linux.org>
173 + * - port to nf_conntrack
176 +/* FIXME: issue with UDP & fragmentation with this URL:
177 + http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx
178 + may be related to out-of-order first packets:
179 + basically the expectation is set up correctly, then the server sends
180 + a first UDP packet which is fragmented plus arrives out-of-order.
181 + the MASQUERADING firewall with ip_nat_mms loaded responds with
182 + an ICMP unreachable back to the server */
184 +#include <linux/module.h>
185 +#include <linux/netfilter_ipv4.h>
186 +#include <linux/ip.h>
187 +#include <linux/tcp.h>
188 +#include <net/tcp.h>
189 +#include <net/netfilter/nf_nat.h>
190 +#include <net/netfilter/nf_nat_helper.h>
191 +#include <net/netfilter/nf_nat_rule.h>
192 +#include <net/netfilter/nf_conntrack_helper.h>
193 +#include <net/netfilter/nf_conntrack_expect.h>
194 +#include <linux/netfilter/nf_conntrack_mms.h>
197 +#define DEBUGP printk
198 +#define DUMP_BYTES(address, counter) \
200 + int temp_counter; \
201 + for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
202 + DEBUGP("%u ", (u8)*(address+temp_counter)); \
207 +#define DEBUGP(format, args...)
208 +#define DUMP_BYTES(address, counter)
211 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
212 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
213 +MODULE_LICENSE("GPL");
215 +static unsigned int mms_data_fixup(struct sk_buff **pskb,
216 + enum ip_conntrack_info ctinfo,
217 + const struct nf_ct_mms_expect *ct_mms_info,
218 + struct nf_conntrack_expect *expect)
221 + struct nf_conn *ct = expect->master;
222 + struct iphdr *iph = ip_hdr(*pskb);
223 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
224 + char *data = (char *)tcph + tcph->doff * 4;
226 + u_int16_t mms_proto;
228 + u_int32_t *mms_chunkLenLV = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
229 + u_int32_t *mms_chunkLenLM = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
230 + u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
234 + char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2
236 + char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
237 + char proto_string[6];
239 + /* what was the protocol again ? */
240 + mms_proto = expect->tuple.dst.protonum;
241 + sprintf(proto_string, "%u", mms_proto);
243 + DEBUGP("nf_nat_mms: mms_data_fixup: info (seq %u + %u) "
244 + "in %u, proto %s\n",
245 + expect->seq, ct_mms_info->len, ntohl(tcph->seq),
246 + mms_proto == IPPROTO_UDP ? "UDP"
247 + : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
249 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip;
250 + expect->saved_proto.tcp.port = expect->tuple.dst.u.tcp.port;
251 + expect->expectfn = nf_nat_follow_master;
253 + /* Alter conntrack's expectations. */
254 + for (port = ct_mms_info->port; port != 0; port++) {
255 + expect->tuple.dst.u.tcp.port = htons(port);
256 + if (nf_ct_expect_related(expect) == 0) {
257 + DEBUGP("nf_nat_mms: mms_data_fixup: using port %d\n",
266 + sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
268 + expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
269 + : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
271 + DEBUGP("nf_nat_mms: new unicode string=%s\n", buffer);
273 + memset(unicode_buffer, 0, sizeof(char)*75);
275 + for (i=0; i<strlen(buffer); ++i)
276 + *(unicode_buffer+i*2)=*(buffer+i);
278 + DEBUGP("nf_nat_mms: mms_data_fixup: padding: %u len: %u\n",
279 + ct_mms_info->padding, ct_mms_info->len);
280 + DEBUGP("nf_nat_mms: mms_data_fixup: offset: %u\n",
281 + MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
282 + DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
284 + /* add end of packet to it */
285 + for (j=0; j<ct_mms_info->padding; ++j) {
286 + DEBUGP("nf_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n",
287 + i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
288 + *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
291 + /* pad with zeroes at the end ? see explanation of weird math below */
292 + zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
293 + for (k=0; k<zero_padding; ++k)
294 + *(unicode_buffer+i*2+j+k)= (char)0;
296 + DEBUGP("nf_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
297 + DEBUGP("nf_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u "
298 + "messageLength=%u\n", *mms_chunkLenLV, *mms_chunkLenLM,
299 + *mms_messageLength);
301 + /* explanation, before I forget what I did:
302 + strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
303 + divide by 8 and add 3 to compute the mms_chunkLenLM field,
304 + but note that things may have to be padded with zeroes to align by 8
305 + bytes, hence we add 7 and divide by 8 to get the correct length */
306 + *mms_chunkLenLM = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
307 + *mms_chunkLenLV = *mms_chunkLenLM+2;
308 + *mms_messageLength = *mms_chunkLenLV*8;
310 + DEBUGP("nf_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u"
311 + " messageLength=%u\n", *mms_chunkLenLV, *mms_chunkLenLM,
312 + *mms_messageLength);
314 + nf_nat_mangle_tcp_packet(*pskb, ct, ctinfo,
315 + ct_mms_info->offset,
316 + ct_mms_info->len + ct_mms_info->padding,
317 + unicode_buffer, strlen(buffer)*2 +
318 + ct_mms_info->padding + zero_padding);
319 + DUMP_BYTES(unicode_buffer, 60);
324 +static void __exit fini(void)
326 + nf_nat_mms_hook = NULL;
330 +static int __init init(void)
332 + BUG_ON(nf_nat_mms_hook);
333 + nf_nat_mms_hook = &mms_data_fixup;
340 diff -NurpP --minimal linux-2.6.21.a/net/netfilter/Kconfig linux-2.6.21.b/net/netfilter/Kconfig
341 --- linux-2.6.21.a/net/netfilter/Kconfig 2007-05-30 11:13:04.000000000 +0200
342 +++ linux-2.6.21.b/net/netfilter/Kconfig 2007-05-30 11:50:55.000000000 +0200
343 @@ -271,6 +271,18 @@ config NF_CONNTRACK_TFTP
345 To compile it as a module, choose M here. If unsure, say N.
347 +config NF_CONNTRACK_MMS
348 + tristate 'MMS protocol support'
349 + depends on NF_CONNTRACK
351 + Tracking MMS (Microsoft Windows Media Services) connections
352 + could be problematic if random ports are used to send the
353 + streaming content. This option allows users to track streaming
354 + connections over random UDP or TCP ports.
356 + If you want to compile it as a module, say M here and read
357 + <file:Documentation/modules.txt>. If unsure, say `Y'.
360 tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
361 depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK
362 diff -NurpP --minimal linux-2.6.21.a/net/netfilter/Makefile linux-2.6.21.b/net/netfilter/Makefile
363 --- linux-2.6.21.a/net/netfilter/Makefile 2007-05-30 11:13:04.000000000 +0200
364 +++ linux-2.6.21.b/net/netfilter/Makefile 2007-05-30 11:50:55.000000000 +0200
365 @@ -26,6 +26,7 @@ nf_conntrack_h323-objs := nf_conntrack_h
366 obj-$(CONFIG_NF_CONNTRACK_AMANDA) += nf_conntrack_amanda.o
367 obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
368 obj-$(CONFIG_NF_CONNTRACK_H323) += nf_conntrack_h323.o
369 +obj-$(CONFIG_NF_CONNTRACK_MMS) += nf_conntrack_mms.o
370 obj-$(CONFIG_NF_CONNTRACK_IRC) += nf_conntrack_irc.o
371 obj-$(CONFIG_NF_CONNTRACK_NETBIOS_NS) += nf_conntrack_netbios_ns.o
372 obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_conntrack_pptp.o
373 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
374 --- linux-2.6.21.a/net/netfilter/nf_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
375 +++ linux-2.6.21.b/net/netfilter/nf_conntrack_mms.c 2007-05-30 11:50:55.000000000 +0200
377 +/* MMS extension for IP connection tracking
378 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
379 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
381 + * ip_conntrack_mms.c v0.3 2002-09-22
383 + * This program is free software; you can redistribute it and/or
384 + * modify it under the terms of the GNU General Public License
385 + * as published by the Free Software Foundation; either version
386 + * 2 of the License, or (at your option) any later version.
388 + * Module load syntax:
389 + * insmod nf_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
391 + * Please give the ports of all MMS servers You wish to connect to.
392 + * If you don't specify ports, the default will be TCP port 1755.
394 + * More info on MMS protocol, firewalls and NAT:
395 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
396 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
398 + * The SDP project people are reverse-engineering MMS:
399 + * http://get.to/sdp
401 + * 2005-02-13: Harald Welte <laforge@netfilter.org>
403 + * - update to work with post 2.6.11 helper API changes
405 + * 2007-03-30: Marek Guevara Braun <mguevara@pld-linux.org>
406 + * - port to nf_conntrack
410 +#include <linux/module.h>
411 +#include <linux/netfilter.h>
412 +#include <linux/ip.h>
413 +#include <linux/ctype.h>
414 +#include <net/checksum.h>
415 +#include <net/tcp.h>
417 +#include <net/netfilter/nf_conntrack.h>
418 +#include <net/netfilter/nf_conntrack_helper.h>
419 +#include <net/netfilter/nf_conntrack_expect.h>
420 +#include <linux/netfilter/nf_conntrack_mms.h>
423 +static int ports[MAX_PORTS];
425 +module_param_array(ports, int, &ports_c, 0400);
426 +MODULE_PARM_DESC(ports, "port numbers of MMS");
428 +static char mms_buffer[65536];
429 +static DEFINE_SPINLOCK(mms_buffer_lock);
431 +unsigned int (*nf_nat_mms_hook)(struct sk_buff **pskb,
432 + enum ip_conntrack_info ctinfo,
433 + const struct nf_ct_mms_expect *exp_mms_info,
434 + struct nf_conntrack_expect *exp);
435 +EXPORT_SYMBOL(nf_nat_mms_hook);
438 +#define DEBUGP printk
440 +#define DEBUGP(format, args...)
443 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
444 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
445 +MODULE_LICENSE("GPL");
447 +/* #define isdigit(c) (c >= '0' && c <= '9') */
449 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
450 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
453 + for (i = 0; i < unicode_size; ++i) {
454 + string[i] = (char)(unicode[i]);
456 + string[unicode_size] = 0x00;
459 +__inline static int atoi(char *s)
462 + while (isdigit(*s)) {
463 + i = i*10 + *(s++) - '0';
468 +/* convert ip address string like "192.168.0.10" to unsigned int */
469 +__inline static u_int32_t asciiiptoi(char *s)
471 + unsigned int i, j, k;
473 + for(i=k=0; k<3; ++k, ++s, i<<=8) {
475 + for(j=0; (*(++s) != '.') && (j<3); ++j)
482 +int parse_mms(const char *data,
483 + const unsigned int datalen,
485 + u_int16_t *mms_proto,
486 + u_int16_t *mms_port,
487 + char **mms_string_b,
488 + char **mms_string_e,
489 + char **mms_padding_e)
491 + int unicode_size, i;
492 + char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
493 + char getlengthstring[28];
495 + for(unicode_size=0;
496 + (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
498 + if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
499 + return -1; /* out of bounds - incomplete packet */
501 + unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
502 + DEBUGP("nf_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
505 + *mms_ip = asciiiptoi(tempstring+2);
507 + i=sprintf(getlengthstring, "%pI4", mms_ip);
510 + if(strncmp(tempstring+3+i, "TCP", 3)==0)
511 + *mms_proto = IPPROTO_TCP;
512 + else if(strncmp(tempstring+3+i, "UDP", 3)==0)
513 + *mms_proto = IPPROTO_UDP;
516 + *mms_port = atoi(tempstring+7+i);
518 + /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port"
519 + unicode string, one to the end of the string, and one to the end
520 + of the packet, since we must keep track of the number of bytes
521 + between end of the unicode string and the end of packet (padding) */
522 + *mms_string_b = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
523 + *mms_string_e = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
524 + *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
529 +/* FIXME: This should be in userspace. Later. */
530 +static int help(struct sk_buff **pskb,
531 + unsigned int protoff,
532 + struct nf_conn *ct,
533 + enum ip_conntrack_info ctinfo)
536 + struct tcphdr _tcph, *th;
537 + char *data, *mb_ptr;
538 + unsigned int datalen, dataoff;
541 + //struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
542 + //unsigned int tcplen = len - iph->ihl * 4;
543 + //unsigned int datalen = tcplen - tcph->doff * 4;
544 + int dir = CTINFO2DIR(ctinfo);
545 + struct nf_conntrack_expect *exp;
546 + struct nf_conntrack_tuple *tuple;
547 + struct nf_ct_mms_expect _emmi, *exp_mms_info = &_emmi;
550 + u_int16_t mms_proto;
551 + char mms_proto_string[8];
552 + u_int16_t mms_port;
554 + char *mms_string_b, *mms_string_e, *mms_padding_e;
555 + typeof(nf_nat_mms_hook) nf_nat_mms;
557 + /* Until there's been traffic both ways, don't look in packets. */
558 + if (ctinfo != IP_CT_ESTABLISHED &&
559 + ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
560 + DEBUGP("nf_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
564 + /* Not whole TCP header? */
565 + th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph);
570 + dataoff = protoff + th->doff*4;
571 + if (dataoff >= (*pskb)->len)
574 + datalen = (*pskb)->len - dataoff;
575 + DEBUGP("nf_conntrack_mms: datalen:%u\n", datalen);
577 + spin_lock_bh(&mms_buffer_lock);
578 + mb_ptr = skb_header_pointer(*pskb, dataoff,
579 + (*pskb)->len - dataoff, mms_buffer);
580 + BUG_ON(mb_ptr == NULL);
585 + /* Checksum invalid? Ignore. */
586 + /* FIXME: Source route IP option packets --RR */
587 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
588 + csum_partial((char *)tcph, tcplen, 0))) {
589 + DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
590 + tcph, tcplen, NIPQUAD(iph->saddr),
591 + NIPQUAD(iph->daddr));
596 + /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP
599 + /* FIXME: There is an issue with only looking at this packet: before
600 + * this packet, the client has already sent a packet to the server with
601 + * the server's hostname according to the client (think of it as the
602 + * "Host: " header in HTTP/1.1). The server will break the connection
603 + * if this doesn't correspond to its own host header. The client can
604 + * also connect to an IP address; if it's the server's IP address, it
605 + * will not break the connection. When doing DNAT on a connection where
606 + * the client uses a server's IP address, the nat module should detect
607 + * this and change this string accordingly to the DNATed address. This
608 + * should probably be done by checking for an IP address, then storing
609 + * it as a member of struct ip_ct_mms_expect and checking for it in
612 + if ((MMS_SRV_MSG_OFFSET >= datalen) ||
613 + ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) != MMS_SRV_MSG_ID))
616 + DEBUGP("nf_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n",
617 + (u8)*(data+36), (u8)*(data+37), (u8)*(data+38), (u8)*(data+39),
619 + if (parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
620 + &mms_string_b, &mms_string_e, &mms_padding_e))
621 + if (net_ratelimit())
622 + /* FIXME: more verbose debugging ? */
623 + printk(KERN_WARNING
624 + "nf_conntrack_mms: Unable to parse "
627 + sprintf(mms_proto_string, "(%u)", mms_proto);
628 + DEBUGP("nf_conntrack_mms: adding %s expectation "
629 + "%u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
630 + mms_proto == IPPROTO_TCP ? "TCP"
631 + : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
632 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
636 + /* it's possible that the client will just ask the server to
637 + * tunnel the stream over the same TCP session (from port
638 + * 1755): there's shouldn't be a need to add an expectation in
639 + * that case, but it makes NAT packet mangling so much easier
642 + DEBUGP("nf_conntrack_mms: tcph->seq = %u\n", tcph->seq);
644 + exp = nf_ct_expect_alloc(ct);
650 + exp_mms_info->offset = (mms_string_b - data);
651 + exp_mms_info->len = (mms_string_e - mms_string_b);
652 + exp_mms_info->padding = (mms_padding_e - mms_string_e);
653 + exp_mms_info->port = mms_port;
655 + DEBUGP("nf_conntrack_mms: wrote info seq=%u (ofs=%u), "
656 + "len=%d, padding=%u\n", exp->seq, (mms_string_e - data),
657 + exp_mms_info->len, exp_mms_info->padding);
659 + tuple = &ct->tuplehash[!dir].tuple;
660 + port = htons(mms_port);
661 + nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, tuple->src.l3num,
662 + NULL, &tuple->dst.u3,
663 + IPPROTO_TCP, NULL, &port);
665 + nf_nat_mms = rcu_dereference(nf_nat_mms_hook);
666 + if (nf_nat_mms && ct->status & IPS_NAT_MASK)
667 + ret = nf_nat_mms(pskb, ctinfo, exp_mms_info, exp);
668 + else if (nf_ct_expect_related(exp) != 0)
670 + nf_ct_expect_put(exp);
672 + exp->tuple = ((struct nf_conntrack_tuple)
673 + { { ct->tuplehash[!dir].tuple.src.u3.ip, { 0 } },
675 + { .tcp = { (__u16) ntohs(mms_port) } },
678 + exp->mask = ((struct nf_conntrack_tuple)
679 + { { 0xFFFFFFFF, { 0 } },
680 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
681 + exp->expectfn = NULL;
684 + if (nf_nat_mms_hook)
685 + ret = nf_nat_mms_hook(pskb, ctinfo, exp_mms_info, exp);
686 + else if (nf_conntrack_expect_related(exp) != 0)
689 + nf_conntrack_expect_put(exp);
692 + spin_unlock_bh(&mms_buffer_lock);
696 +static struct nf_conntrack_helper mms[MAX_PORTS];
697 +static char mms_names[MAX_PORTS][10];
698 +static const struct nf_conntrack_expect_policy mms_exp_policy = {
703 +/* Not __exit: called from init() */
704 +static void fini(void)
707 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
708 + DEBUGP("nf_conntrack_mms: unregistering helper for port %d\n",
710 + nf_conntrack_helper_unregister(&mms[i]);
714 +static int __init init(void)
720 + ports[0] = MMS_PORT;
722 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
723 + memset(&mms[i], 0, sizeof(struct nf_conntrack_helper));
724 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
725 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
726 + mms[i].me = THIS_MODULE;
727 + mms[i].expect_policy = &mms_exp_policy;
728 + mms[i].help = help;
730 + tmpname = &mms_names[i][0];
731 + if (ports[i] == MMS_PORT)
732 + sprintf(tmpname, "mms");
734 + sprintf(tmpname, "mms-%d", ports[i]);
735 + mms[i].name = tmpname;
737 + DEBUGP("nf_conntrack_mms: registering helper for port %d\n",
739 + ret = nf_conntrack_helper_register(&mms[i]);