Root/target/linux/generic-2.4/patches/615-netfilter_nat_mms.patch

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

Archive Download this file



interactive