]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-pom-ng-mms-conntrack-nat.patch
- require kmod, it has all needed bits from our module-init-tools,
[packages/kernel.git] / kernel-pom-ng-mms-conntrack-nat.patch
CommitLineData
2380c486
JR
1diff -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
4@@ -0,0 +1,34 @@
5+#ifndef _IP_CONNTRACK_MMS_H
6+#define _IP_CONNTRACK_MMS_H
7+/* MMS tracking. */
8+
9+#ifdef __KERNEL__
10+
11+#define MMS_PORT 1755
12+#define MMS_SRV_MSG_ID 196610
13+
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
19+
20+/* This structure is per expected connection */
21+struct nf_ct_mms_expect {
22+ u_int32_t offset;
23+ u_int32_t len;
24+ u_int32_t padding;
25+ u_int16_t port;
26+};
27+
28+/* This structure exists only once per master */
29+struct nf_ct_mms_master {
30+};
31+
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);
37+#endif
38+#endif /* _IP_CONNTRACK_MMS_H */
39diff -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>
47
48 /* per conntrack: application helper private data */
49 union nf_conntrack_help {
bd014f2d
AM
50@@ -69,6 +69,9 @@
51 #if defined(CONFIG_NF_CONNTRACK_SIP) || defined(CONFIG_NF_CONNTRACK_SIP_MODULE)
2380c486 52 struct nf_ct_sip_master ct_sip_info;
bd014f2d
AM
53 #endif
54+#if defined(CONFIG_NF_NAT_MMS) || defined(CONFIG_NF_NAT_MMS_MODULE)
2380c486 55+ struct nf_ct_mms_master ct_mms_info;
bd014f2d 56+#endif
2380c486
JR
57 };
58
59 #include <linux/types.h>
60diff -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
63@@ -0,0 +1,34 @@
64+#ifndef _IP_CONNTRACK_MMS_H
65+#define _IP_CONNTRACK_MMS_H
66+/* MMS tracking. */
67+
68+#ifdef __KERNEL__
69+
70+#define MMS_PORT 1755
71+#define MMS_SRV_MSG_ID 196610
72+
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
78+
79+/* This structure is per expected connection */
80+struct nf_ct_mms_expect {
81+ u_int32_t offset;
82+ u_int32_t len;
83+ u_int32_t padding;
84+ u_int16_t port;
85+};
86+
87+/* This structure exists only once per master */
88+struct nf_ct_mms_master {
89+};
90+
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);
96+#endif
97+#endif /* _IP_CONNTRACK_MMS_H */
98diff -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
104
105+config NF_NAT_MMS
106+ tristate
107+ depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
108+ default NF_NAT && NF_CONNTRACK_MMS
109+
110 config NF_NAT_SIP
111 tristate
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.
116
117+config IP_NF_NAT_MMS
118+ tristate
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
122+
123+config IP_NF_MMS
124+ tristate 'MMS protocol support'
125+ depends on IP_NF_CONNTRACK
126+ help
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.
131+
132+ If you want to compile it as a module, say M here and read
133+ <file:Documentation/modules.txt>. If unsure, say `Y'.
134+
135 endmenu
136
137diff -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
a1f66529 140@@ -0,0 +1 @@
2380c486
JR
141+obj-$(CONFIG_NF_NAT_MMS) += nf_nat_mms.o
142diff -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
a1f66529 145@@ -0,0 +1,202 @@
2380c486
JR
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
149+ *
150+ * ip_nat_mms.c v0.3 2002-09-22
151+ *
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.
156+ *
157+ * Module load syntax:
158+ * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
159+ *
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.
162+ *
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
166+ *
167+ * The SDP project people are reverse-engineering MMS:
168+ * http://get.to/sdp
169+ *
170+ * 2005-02-13: Harald Welte <laforge@netfilter.org>
171+ * - port to 2.6.x
172+ * - update to work with post 2.6.11 helper API changes
173+ *
174+ * 2007-03-30: Marek Guevara Braun <mguevara@pld-linux.org>
175+ * - port to nf_conntrack
176+ */
177+
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 */
185+
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>
197+
a1f66529
AM
198+#define NIPQUAD(addr) \
199+ ((unsigned char *)&addr)[0], \
200+ ((unsigned char *)&addr)[1], \
201+ ((unsigned char *)&addr)[2], \
202+ ((unsigned char *)&addr)[3]
203+
2380c486
JR
204+#if 0
205+#define DEBUGP printk
206+#define DUMP_BYTES(address, counter) \
207+({ \
208+ int temp_counter; \
209+ for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
210+ DEBUGP("%u ", (u8)*(address+temp_counter)); \
211+ }; \
212+ DEBUGP("\n"); \
213+})
214+#else
215+#define DEBUGP(format, args...)
216+#define DUMP_BYTES(address, counter)
217+#endif
218+
219+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
220+MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
221+MODULE_LICENSE("GPL");
222+
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)
227+{
228+ u_int32_t newip;
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;
233+ int i, j, k, port;
234+ u_int16_t mms_proto;
235+
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);
239+
240+ int zero_padding;
241+
242+ char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2
243+ (for unicode) */
244+ char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
245+ char proto_string[6];
246+
247+ /* what was the protocol again ? */
248+ mms_proto = expect->tuple.dst.protonum;
249+ sprintf(proto_string, "%u", mms_proto);
250+
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);
256+
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;
260+
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",
266+ port);
267+ break;
268+ }
269+ }
270+
271+ if (port == 0)
272+ return NF_DROP;
273+
274+ sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
275+ NIPQUAD(newip),
276+ expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
277+ : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
278+ port);
279+ DEBUGP("nf_nat_mms: new unicode string=%s\n", buffer);
280+
281+ memset(unicode_buffer, 0, sizeof(char)*75);
282+
283+ for (i=0; i<strlen(buffer); ++i)
284+ *(unicode_buffer+i*2)=*(buffer+i);
285+
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);
291+
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);
297+ }
298+
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;
303+
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);
308+
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;
317+
318+ DEBUGP("nf_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u"
319+ " messageLength=%u\n", *mms_chunkLenLV, *mms_chunkLenLM,
320+ *mms_messageLength);
321+
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);
328+
329+ return NF_ACCEPT;
330+}
331+
332+static void __exit fini(void)
333+{
334+ nf_nat_mms_hook = NULL;
335+ synchronize_net();
336+}
337+
338+static int __init init(void)
339+{
340+ BUG_ON(nf_nat_mms_hook);
341+ nf_nat_mms_hook = &mms_data_fixup;
342+
343+ return 0;
344+}
345+
346+module_init(init);
347+module_exit(fini);
348diff -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
352
353 To compile it as a module, choose M here. If unsure, say N.
354
355+config NF_CONNTRACK_MMS
356+ tristate 'MMS protocol support'
357+ depends on NF_CONNTRACK
358+ help
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.
363+
364+ If you want to compile it as a module, say M here and read
365+ <file:Documentation/modules.txt>. If unsure, say `Y'.
366+
367 config NF_CT_NETLINK
368 tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
369 depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK
370diff -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
381diff -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
a1f66529 384@@ -0,0 +1,375 @@
2380c486
JR
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
388+ *
389+ * ip_conntrack_mms.c v0.3 2002-09-22
390+ *
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.
395+ *
396+ * Module load syntax:
397+ * insmod nf_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
398+ *
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.
401+ *
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
405+ *
406+ * The SDP project people are reverse-engineering MMS:
407+ * http://get.to/sdp
408+ *
409+ * 2005-02-13: Harald Welte <laforge@netfilter.org>
410+ * - port to 2.6.x
411+ * - update to work with post 2.6.11 helper API changes
412+ *
413+ * 2007-03-30: Marek Guevara Braun <mguevara@pld-linux.org>
414+ * - port to nf_conntrack
415+ */
416+
417+
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>
424+
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>
429+
430+#define MAX_PORTS 8
431+static int ports[MAX_PORTS];
432+static int ports_c;
433+module_param_array(ports, int, &ports_c, 0400);
434+MODULE_PARM_DESC(ports, "port numbers of MMS");
435+
436+static char mms_buffer[65536];
437+static DEFINE_SPINLOCK(mms_buffer_lock);
438+
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);
444+
445+#if 0
446+#define DEBUGP printk
447+#else
448+#define DEBUGP(format, args...)
449+#endif
450+
451+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
452+MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
453+MODULE_LICENSE("GPL");
454+
455+/* #define isdigit(c) (c >= '0' && c <= '9') */
456+
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)
459+{
460+ int i;
461+ for (i = 0; i < unicode_size; ++i) {
462+ string[i] = (char)(unicode[i]);
463+ }
464+ string[unicode_size] = 0x00;
465+}
466+
467+__inline static int atoi(char *s)
468+{
469+ int i=0;
470+ while (isdigit(*s)) {
471+ i = i*10 + *(s++) - '0';
472+ }
473+ return i;
474+}
475+
476+/* convert ip address string like "192.168.0.10" to unsigned int */
477+__inline static u_int32_t asciiiptoi(char *s)
478+{
479+ unsigned int i, j, k;
480+
481+ for(i=k=0; k<3; ++k, ++s, i<<=8) {
482+ i+=atoi(s);
483+ for(j=0; (*(++s) != '.') && (j<3); ++j)
484+ ;
485+ }
486+ i+=atoi(s);
487+ return ntohl(i);
488+}
489+
490+int parse_mms(const char *data,
491+ const unsigned int datalen,
492+ u_int32_t *mms_ip,
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)
498+{
499+ int unicode_size, i;
500+ char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
501+ char getlengthstring[28];
502+
503+ for(unicode_size=0;
504+ (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
505+ unicode_size++)
506+ if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
507+ return -1; /* out of bounds - incomplete packet */
508+
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));
511+
512+ /* IP address ? */
513+ *mms_ip = asciiiptoi(tempstring+2);
514+
0b91b834 515+ i=sprintf(getlengthstring, "%pI4", mms_ip);
2380c486
JR
516+
517+ /* protocol ? */
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;
522+
523+ /* port ? */
524+ *mms_port = atoi(tempstring+7+i);
525+
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 */
533+ return 0;
534+}
535+
536+
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)
542+{
543+ int ret = NF_DROP;
544+ struct tcphdr _tcph, *th;
545+ char *data, *mb_ptr;
546+ unsigned int datalen, dataoff;
547+
548+
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;
556+
557+ u_int32_t mms_ip;
558+ u_int16_t mms_proto;
559+ char mms_proto_string[8];
560+ u_int16_t mms_port;
561+ __be16 port;
562+ char *mms_string_b, *mms_string_e, *mms_padding_e;
563+ typeof(nf_nat_mms_hook) nf_nat_mms;
564+
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);
569+ return NF_ACCEPT;
570+ }
571+
572+ /* Not whole TCP header? */
573+ th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph);
574+ if (th == NULL)
575+ return NF_ACCEPT;
576+
577+ /* No data ? */
578+ dataoff = protoff + th->doff*4;
579+ if (dataoff >= (*pskb)->len)
580+ return NF_ACCEPT;
581+
582+ datalen = (*pskb)->len - dataoff;
583+ DEBUGP("nf_conntrack_mms: datalen:%u\n", datalen);
584+
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);
589+
590+ data = mb_ptr;
591+
592+#if 0
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));
600+ return NF_ACCEPT;
601+ }
602+#endif
603+
604+ /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP
605+ * payload */
606+
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
618+ * ip_nat_mms...
619+ */
620+ if ((MMS_SRV_MSG_OFFSET >= datalen) ||
621+ ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) != MMS_SRV_MSG_ID))
622+ goto out;
623+
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),
626+ datalen);
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 "
633+ "data payload\n");
634+
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),
641+ NIPQUAD(mms_ip),
642+ mms_port);
643+
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
648+ * */
649+
650+ DEBUGP("nf_conntrack_mms: tcph->seq = %u\n", tcph->seq);
651+
652+ exp = nf_ct_expect_alloc(ct);
653+ if (exp == NULL) {
654+ ret = NF_DROP;
655+ goto out;
656+ }
657+
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;
662+
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);
666+
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);
672+
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)
677+ ret = NF_DROP;
678+ nf_ct_expect_put(exp);
679+/*
680+ exp->tuple = ((struct nf_conntrack_tuple)
681+ { { ct->tuplehash[!dir].tuple.src.u3.ip, { 0 } },
682+ { mms_ip,
683+ { .tcp = { (__u16) ntohs(mms_port) } },
684+ mms_proto } }
685+ );
686+ exp->mask = ((struct nf_conntrack_tuple)
687+ { { 0xFFFFFFFF, { 0 } },
688+ { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }});
689+ exp->expectfn = NULL;
690+ exp->master = ct;
691+
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)
695+ ret = NF_DROP;
696+
697+ nf_conntrack_expect_put(exp);
698+*/
699+out:
700+ spin_unlock_bh(&mms_buffer_lock);
701+ return ret;
702+}
703+
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 = {
707+ .max_expected = 1,
708+ .timeout = 120,
709+};
710+
711+/* Not __exit: called from init() */
712+static void fini(void)
713+{
714+ int i;
715+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
716+ DEBUGP("nf_conntrack_mms: unregistering helper for port %d\n",
717+ ports[i]);
718+ nf_conntrack_helper_unregister(&mms[i]);
719+ }
720+}
721+
722+static int __init init(void)
723+{
724+ int i, ret;
725+ char *tmpname;
726+
727+ if (ports[0] == 0)
728+ ports[0] = MMS_PORT;
729+
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;
737+
738+ tmpname = &mms_names[i][0];
739+ if (ports[i] == MMS_PORT)
740+ sprintf(tmpname, "mms");
741+ else
742+ sprintf(tmpname, "mms-%d", ports[i]);
743+ mms[i].name = tmpname;
744+
745+ DEBUGP("nf_conntrack_mms: registering helper for port %d\n",
746+ ports[i]);
747+ ret = nf_conntrack_helper_register(&mms[i]);
748+
749+ if (ret) {
750+ fini();
751+ return ret;
752+ }
753+ ports_c++;
754+ }
755+ return 0;
756+}
757+
758+module_init(init);
759+module_exit(fini);
This page took 0.198463 seconds and 4 git commands to generate.