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