]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-pom-ng-mms-conntrack-nat.patch
- update vserver patch - patch-3.4.22-vs2.3.3.9.diff
[packages/kernel.git] / kernel-pom-ng-mms-conntrack-nat.patch
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
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 */
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>
47  
48  /* per conntrack: application helper private data */
49  union nf_conntrack_help {
50 @@ -69,6 +69,9 @@
51  #if defined(CONFIG_NF_CONNTRACK_SIP) || defined(CONFIG_NF_CONNTRACK_SIP_MODULE)
52         struct nf_ct_sip_master ct_sip_info;
53  #endif
54 +#if defined(CONFIG_NF_NAT_MMS) || defined(CONFIG_NF_NAT_MMS_MODULE)
55 +       struct nf_ct_mms_master ct_mms_info;
56 +#endif
57  };
58  
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
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 */
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
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  
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
140 @@ -0,0 +1 @@
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
145 @@ -0,0 +1,202 @@
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 +
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 +
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);
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
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
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
384 @@ -0,0 +1,375 @@
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 +
515 +       i=sprintf(getlengthstring, "%pI4", mms_ip);
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.083935 seconds and 3 git commands to generate.