move old kamikaze out of trunk - will put buildroot-ng in there as soon as all the...
[openwrt/staging/dedeckeh.git] / openwrt / target / linux / generic-2.4 / patches / 615-netfilter_nat_mms.patch
diff --git a/openwrt/target/linux/generic-2.4/patches/615-netfilter_nat_mms.patch b/openwrt/target/linux/generic-2.4/patches/615-netfilter_nat_mms.patch
deleted file mode 100644 (file)
index 3871d59..0000000
+++ /dev/null
@@ -1,739 +0,0 @@
-diff -urN linux-2.4.32/net/ipv4/netfilter/Config.in linux-2.4.32.new/net/ipv4/netfilter/Config.in
---- linux-2.4.32/net/ipv4/netfilter/Config.in  2006-03-01 01:12:48.268947944 +0100
-+++ linux-2.4.32.new/net/ipv4/netfilter/Config.in      2006-03-01 01:14:53.455916632 +0100
-@@ -17,6 +17,7 @@
-   dep_tristate '   PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE
-   dep_tristate '  H.323 (netmeeting) support' CONFIG_IP_NF_H323 $CONFIG_IP_NF_CONNTRACK
-   dep_tristate '  RTSP protocol support' CONFIG_IP_NF_RTSP $CONFIG_IP_NF_CONNTRACK
-+  dep_tristate '  MMS protocol support' CONFIG_IP_NF_MMS $CONFIG_IP_NF_CONNTRACK
- fi
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-@@ -127,6 +128,13 @@
-          define_tristate CONFIG_IP_NF_NAT_RTSP $CONFIG_IP_NF_NAT
-        fi
-       fi
-+      if [ "$CONFIG_IP_NF_MMS" = "m" ]; then
-+       define_tristate CONFIG_IP_NF_NAT_MMS m
-+      else
-+       if [ "$CONFIG_IP_NF_MMS" = "y" ]; then
-+         define_tristate CONFIG_IP_NF_NAT_MMS $CONFIG_IP_NF_NAT
-+       fi
-+      fi
-       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-         dep_tristate '    Basic SNMP-ALG support (EXPERIMENTAL)' CONFIG_IP_NF_NAT_SNMP_BASIC $CONFIG_IP_NF_NAT
-       fi
-diff -urN linux-2.4.32/net/ipv4/netfilter/Makefile linux-2.4.32.new/net/ipv4/netfilter/Makefile
---- linux-2.4.32/net/ipv4/netfilter/Makefile   2006-03-01 01:12:48.270947640 +0100
-+++ linux-2.4.32.new/net/ipv4/netfilter/Makefile       2006-03-01 01:15:25.263081208 +0100
-@@ -61,6 +61,10 @@
- ifdef CONFIG_IP_NF_NAT_RTSP
-        export-objs += ip_conntrack_rtsp.o
- endif
-+obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
-+ifdef CONFIG_IP_NF_NAT_MMS
-+       export-objs += ip_conntrack_mms.o
-+endif
-@@ -73,6 +77,7 @@
- obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
- obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
- obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
-+obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
- # generic IP tables 
- obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
-diff -urN linux-2.4.32/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.4.32.new/net/ipv4/netfilter/ip_conntrack_mms.c
---- linux-2.4.32/net/ipv4/netfilter/ip_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/net/ipv4/netfilter/ip_conntrack_mms.c     2006-03-01 01:13:32.991149136 +0100
-@@ -0,0 +1,292 @@
-+/* MMS extension for IP connection tracking
-+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
-+ * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
-+ *
-+ * ip_conntrack_mms.c v0.3 2002-09-22
-+ *
-+ *      This program is free software; you can redistribute it and/or
-+ *      modify it under the terms of the GNU General Public License
-+ *      as published by the Free Software Foundation; either version
-+ *      2 of the License, or (at your option) any later version.
-+ *
-+ *      Module load syntax:
-+ *      insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
-+ *
-+ *      Please give the ports of all MMS servers You wish to connect to.
-+ *      If you don't specify ports, the default will be TCP port 1755.
-+ *
-+ *      More info on MMS protocol, firewalls and NAT:
-+ *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
-+ *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
-+ *
-+ *      The SDP project people are reverse-engineering MMS:
-+ *      http://get.to/sdp
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/netfilter.h>
-+#include <linux/ip.h>
-+#include <linux/ctype.h>
-+#include <net/checksum.h>
-+#include <net/tcp.h>
-+
-+#include <linux/netfilter_ipv4/lockhelp.h>
-+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
-+#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
-+
-+DECLARE_LOCK(ip_mms_lock);
-+struct module *ip_conntrack_mms = THIS_MODULE;
-+
-+#define MAX_PORTS 8
-+static int ports[MAX_PORTS];
-+static int ports_c;
-+#ifdef MODULE_PARM
-+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
-+#endif
-+
-+#define DEBUGP(format, args...)
-+
-+#ifdef CONFIG_IP_NF_NAT_NEEDED
-+EXPORT_SYMBOL(ip_mms_lock);
-+#endif
-+
-+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
-+MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
-+MODULE_LICENSE("GPL");
-+
-+/* #define isdigit(c) (c >= '0' && c <= '9') */
-+
-+/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
-+static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
-+{
-+      int i;
-+      for (i = 0; i < unicode_size; ++i) {
-+              string[i] = (char)(unicode[i]);
-+      }
-+      string[unicode_size] = 0x00;
-+}
-+
-+__inline static int atoi(char *s) 
-+{
-+      int i=0;
-+      while (isdigit(*s)) {
-+              i = i*10 + *(s++) - '0';
-+      }
-+      return i;
-+}
-+
-+/* convert ip address string like "192.168.0.10" to unsigned int */
-+__inline static u_int32_t asciiiptoi(char *s)
-+{
-+      unsigned int i, j, k;
-+
-+      for(i=k=0; k<3; ++k, ++s, i<<=8) {
-+              i+=atoi(s);
-+              for(j=0; (*(++s) != '.') && (j<3); ++j)
-+                      ;
-+      }
-+      i+=atoi(s);
-+      return ntohl(i);
-+}
-+
-+int parse_mms(const char *data, 
-+            const unsigned int datalen,
-+            u_int32_t *mms_ip,
-+            u_int16_t *mms_proto,
-+            u_int16_t *mms_port,
-+            char **mms_string_b,
-+            char **mms_string_e,
-+            char **mms_padding_e)
-+{
-+      int unicode_size, i;
-+      char tempstring[28];       /* "\\255.255.255.255\UDP\65535" */
-+      char getlengthstring[28];
-+      
-+      for(unicode_size=0; 
-+          (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
-+          unicode_size++)
-+              if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen)) 
-+                      return -1; /* out of bounds - incomplete packet */
-+      
-+      unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
-+      DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
-+      
-+      /* IP address ? */
-+      *mms_ip = asciiiptoi(tempstring+2);
-+      
-+      i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
-+              
-+      /* protocol ? */
-+      if(strncmp(tempstring+3+i, "TCP", 3)==0)
-+              *mms_proto = IPPROTO_TCP;
-+      else if(strncmp(tempstring+3+i, "UDP", 3)==0)
-+              *mms_proto = IPPROTO_UDP;
-+
-+      /* port ? */
-+      *mms_port = atoi(tempstring+7+i);
-+
-+      /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port" 
-+         unicode string, one to the end of the string, and one to the end 
-+         of the packet, since we must keep track of the number of bytes 
-+         between end of the unicode string and the end of packet (padding) */
-+      *mms_string_b  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
-+      *mms_string_e  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
-+      *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
-+      return 0;
-+}
-+
-+
-+static int help(const struct iphdr *iph, size_t len,
-+              struct ip_conntrack *ct,
-+              enum ip_conntrack_info ctinfo)
-+{
-+      /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
-+      struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
-+      const char *data = (const char *)tcph + tcph->doff * 4;
-+      unsigned int tcplen = len - iph->ihl * 4;
-+      unsigned int datalen = tcplen - tcph->doff * 4;
-+      int dir = CTINFO2DIR(ctinfo);
-+      struct ip_conntrack_expect expect, *exp = &expect; 
-+      struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
-+      
-+      u_int32_t mms_ip;
-+      u_int16_t mms_proto;
-+      char mms_proto_string[8];
-+      u_int16_t mms_port;
-+      char *mms_string_b, *mms_string_e, *mms_padding_e;
-+           
-+      /* Until there's been traffic both ways, don't look in packets. */
-+      if (ctinfo != IP_CT_ESTABLISHED
-+          && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
-+              DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
-+              return NF_ACCEPT;
-+      }
-+
-+      /* Not whole TCP header? */
-+      if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
-+              DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
-+              return NF_ACCEPT;
-+      }
-+
-+      /* Checksum invalid?  Ignore. */
-+      if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
-+          csum_partial((char *)tcph, tcplen, 0))) {
-+              DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
-+                     tcph, tcplen, NIPQUAD(iph->saddr),
-+                     NIPQUAD(iph->daddr));
-+              return NF_ACCEPT;
-+      }
-+      
-+      /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
-+      if( (MMS_SRV_MSG_OFFSET < datalen) && 
-+          ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
-+              DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n", 
-+                     (u8)*(data+36), (u8)*(data+37), 
-+                     (u8)*(data+38), (u8)*(data+39),
-+                     datalen);
-+              if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
-+                           &mms_string_b, &mms_string_e, &mms_padding_e))
-+                      if(net_ratelimit())
-+                              printk(KERN_WARNING
-+                                     "ip_conntrack_mms: Unable to parse data payload\n");
-+
-+              memset(&expect, 0, sizeof(expect));
-+
-+              sprintf(mms_proto_string, "(%u)", mms_proto);
-+              DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
-+                     mms_proto == IPPROTO_TCP ? "TCP"
-+                     : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
-+                     NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
-+                     NIPQUAD(mms_ip),
-+                     mms_port);
-+              
-+              /* it's possible that the client will just ask the server to tunnel
-+                 the stream over the same TCP session (from port 1755): there's 
-+                 shouldn't be a need to add an expectation in that case, but it
-+                 makes NAT packet mangling so much easier */
-+              LOCK_BH(&ip_mms_lock);
-+
-+              DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
-+              
-+              exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
-+              exp_mms_info->len     = (mms_string_e  - mms_string_b);
-+              exp_mms_info->padding = (mms_padding_e - mms_string_e);
-+              exp_mms_info->port    = mms_port;
-+              
-+              DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
-+                     exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
-+              
-+              exp->tuple = ((struct ip_conntrack_tuple)
-+                            { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
-+                            { mms_ip,
-+                              { (__u16) ntohs(mms_port) },
-+                              mms_proto } }
-+                           );
-+              exp->mask  = ((struct ip_conntrack_tuple)
-+                           { { 0xFFFFFFFF, { 0 } },
-+                             { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
-+              exp->expectfn = NULL;
-+              ip_conntrack_expect_related(ct, &expect);
-+              UNLOCK_BH(&ip_mms_lock);
-+      }
-+
-+      return NF_ACCEPT;
-+}
-+
-+static struct ip_conntrack_helper mms[MAX_PORTS];
-+static char mms_names[MAX_PORTS][10];
-+
-+/* Not __exit: called from init() */
-+static void fini(void)
-+{
-+      int i;
-+      for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
-+              DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
-+                              ports[i]);
-+              ip_conntrack_helper_unregister(&mms[i]);
-+      }
-+}
-+
-+static int __init init(void)
-+{
-+      int i, ret;
-+      char *tmpname;
-+
-+      if (ports[0] == 0)
-+              ports[0] = MMS_PORT;
-+
-+      for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
-+              memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
-+              mms[i].tuple.src.u.tcp.port = htons(ports[i]);
-+              mms[i].tuple.dst.protonum = IPPROTO_TCP;
-+              mms[i].mask.src.u.tcp.port = 0xFFFF;
-+              mms[i].mask.dst.protonum = 0xFFFF;
-+              mms[i].max_expected = 1;
-+              mms[i].timeout = 0;
-+              mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
-+              mms[i].me = THIS_MODULE;
-+              mms[i].help = help;
-+
-+              tmpname = &mms_names[i][0];
-+              if (ports[i] == MMS_PORT)
-+                      sprintf(tmpname, "mms");
-+              else
-+                      sprintf(tmpname, "mms-%d", ports[i]);
-+              mms[i].name = tmpname;
-+
-+              DEBUGP("ip_conntrack_mms: registering helper for port %d\n", 
-+                              ports[i]);
-+              ret = ip_conntrack_helper_register(&mms[i]);
-+
-+              if (ret) {
-+                      fini();
-+                      return ret;
-+              }
-+              ports_c++;
-+      }
-+      return 0;
-+}
-+
-+module_init(init);
-+module_exit(fini);
-diff -urN linux-2.4.32/net/ipv4/netfilter/ip_nat_mms.c linux-2.4.32.new/net/ipv4/netfilter/ip_nat_mms.c
---- linux-2.4.32/net/ipv4/netfilter/ip_nat_mms.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/net/ipv4/netfilter/ip_nat_mms.c   2006-03-01 01:13:32.992148984 +0100
-@@ -0,0 +1,330 @@
-+/* MMS extension for TCP NAT alteration.
-+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
-+ * based on ip_nat_ftp.c and ip_nat_irc.c
-+ *
-+ * ip_nat_mms.c v0.3 2002-09-22
-+ *
-+ *      This program is free software; you can redistribute it and/or
-+ *      modify it under the terms of the GNU General Public License
-+ *      as published by the Free Software Foundation; either version
-+ *      2 of the License, or (at your option) any later version.
-+ *
-+ *      Module load syntax:
-+ *      insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
-+ *
-+ *      Please give the ports of all MMS servers You wish to connect to.
-+ *      If you don't specify ports, the default will be TCP port 1755.
-+ *
-+ *      More info on MMS protocol, firewalls and NAT:
-+ *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
-+ *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
-+ *
-+ *      The SDP project people are reverse-engineering MMS:
-+ *      http://get.to/sdp
-+ */
-+
-+
-+#include <linux/module.h>
-+#include <linux/netfilter_ipv4.h>
-+#include <linux/ip.h>
-+#include <linux/tcp.h>
-+#include <net/tcp.h>
-+#include <linux/netfilter_ipv4/ip_nat.h>
-+#include <linux/netfilter_ipv4/ip_nat_helper.h>
-+#include <linux/netfilter_ipv4/ip_nat_rule.h>
-+#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
-+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
-+
-+#define DEBUGP(format, args...)
-+#define DUMP_BYTES(address, counter)
-+
-+#define MAX_PORTS 8
-+static int ports[MAX_PORTS];
-+static int ports_c = 0;
-+
-+#ifdef MODULE_PARM
-+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
-+#endif
-+
-+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
-+MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
-+MODULE_LICENSE("GPL");
-+
-+DECLARE_LOCK_EXTERN(ip_mms_lock);
-+
-+
-+static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
-+                          struct ip_conntrack *ct,
-+                          struct sk_buff **pskb,
-+                          enum ip_conntrack_info ctinfo,
-+                          struct ip_conntrack_expect *expect)
-+{
-+      u_int32_t newip;
-+      struct ip_conntrack_tuple t;
-+      struct iphdr *iph = (*pskb)->nh.iph;
-+      struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
-+      char *data = (char *)tcph + tcph->doff * 4;
-+      int i, j, k, port;
-+      u_int16_t mms_proto;
-+
-+      u_int32_t *mms_chunkLenLV    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
-+      u_int32_t *mms_chunkLenLM    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
-+      u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
-+
-+      int zero_padding;
-+
-+      char buffer[28];         /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
-+      char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
-+      char proto_string[6];
-+      
-+      MUST_BE_LOCKED(&ip_mms_lock);
-+
-+      /* what was the protocol again ? */
-+      mms_proto = expect->tuple.dst.protonum;
-+      sprintf(proto_string, "%u", mms_proto);
-+      
-+      DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
-+             expect->seq, ct_mms_info->len, ntohl(tcph->seq),
-+             mms_proto == IPPROTO_UDP ? "UDP"
-+             : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
-+      
-+      newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
-+
-+      /* Alter conntrack's expectations. */
-+      t = expect->tuple;
-+      t.dst.ip = newip;
-+      for (port = ct_mms_info->port; port != 0; port++) {
-+              t.dst.u.tcp.port = htons(port);
-+              if (ip_conntrack_change_expect(expect, &t) == 0) {
-+                      DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
-+                      break;
-+              }
-+      }
-+      
-+      if(port == 0)
-+              return 0;
-+
-+      sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
-+              NIPQUAD(newip),
-+              expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
-+              : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
-+              port);
-+      DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
-+      
-+      memset(unicode_buffer, 0, sizeof(char)*75);
-+
-+      for (i=0; i<strlen(buffer); ++i)
-+              *(unicode_buffer+i*2)=*(buffer+i);
-+      
-+      DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
-+      DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
-+      DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
-+      
-+      /* add end of packet to it */
-+      for (j=0; j<ct_mms_info->padding; ++j) {
-+              DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n", 
-+                     i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
-+              *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
-+      }
-+
-+      /* pad with zeroes at the end ? see explanation of weird math below */
-+      zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
-+      for (k=0; k<zero_padding; ++k)
-+              *(unicode_buffer+i*2+j+k)= (char)0;
-+      
-+      DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
-+      DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
-+             *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
-+      
-+      /* explanation, before I forget what I did:
-+         strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
-+         divide by 8 and add 3 to compute the mms_chunkLenLM field,
-+         but note that things may have to be padded with zeroes to align by 8 
-+         bytes, hence we add 7 and divide by 8 to get the correct length */ 
-+      *mms_chunkLenLM    = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
-+      *mms_chunkLenLV    = *mms_chunkLenLM+2;
-+      *mms_messageLength = *mms_chunkLenLV*8;
-+      
-+      DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
-+             *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
-+      
-+      ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
-+                               expect->seq - ntohl(tcph->seq),
-+                               ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
-+                               strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
-+      DUMP_BYTES(unicode_buffer, 60);
-+      
-+      return 1;
-+}
-+
-+static unsigned int
-+mms_nat_expected(struct sk_buff **pskb,
-+                 unsigned int hooknum,
-+                 struct ip_conntrack *ct,
-+                 struct ip_nat_info *info)
-+{
-+      struct ip_nat_multi_range mr;
-+      u_int32_t newdstip, newsrcip, newip;
-+
-+      struct ip_conntrack *master = master_ct(ct);
-+
-+      IP_NF_ASSERT(info);
-+      IP_NF_ASSERT(master);
-+
-+      IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
-+
-+      DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
-+
-+      newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
-+      newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
-+      DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
-+             hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
-+             : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
-+             : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
-+             NIPQUAD(newsrcip), NIPQUAD(newdstip));
-+
-+      if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
-+              newip = newsrcip;
-+      else
-+              newip = newdstip;
-+
-+      DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
-+
-+      mr.rangesize = 1;
-+      /* We don't want to manip the per-protocol, just the IPs. */
-+      mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
-+      mr.range[0].min_ip = mr.range[0].max_ip = newip;
-+
-+      return ip_nat_setup_info(ct, &mr, hooknum);
-+}
-+
-+
-+static unsigned int mms_nat_help(struct ip_conntrack *ct,
-+                       struct ip_conntrack_expect *exp,
-+                       struct ip_nat_info *info,
-+                       enum ip_conntrack_info ctinfo,
-+                       unsigned int hooknum,
-+                       struct sk_buff **pskb)
-+{
-+      struct iphdr *iph = (*pskb)->nh.iph;
-+      struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
-+      unsigned int datalen;
-+      int dir;
-+      struct ip_ct_mms_expect *ct_mms_info;
-+
-+      if (!exp)
-+              DEBUGP("ip_nat_mms: no exp!!");
-+
-+      ct_mms_info = &exp->help.exp_mms_info;
-+      
-+      /* Only mangle things once: original direction in POST_ROUTING
-+         and reply direction on PRE_ROUTING. */
-+      dir = CTINFO2DIR(ctinfo);
-+      if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
-+          ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
-+              DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
-+                     dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
-+                     hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
-+                     : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
-+                     : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
-+              return NF_ACCEPT;
-+      }
-+      DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
-+             dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
-+             hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
-+             : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
-+             : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
-+      
-+      datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
-+      
-+      DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
-+             exp->seq + ct_mms_info->len,
-+             ntohl(tcph->seq),
-+             ntohl(tcph->seq) + datalen);
-+      
-+      LOCK_BH(&ip_mms_lock);
-+      /* Check wether the whole IP/proto/port pattern is carried in the payload */
-+      if (between(exp->seq + ct_mms_info->len,
-+          ntohl(tcph->seq),
-+          ntohl(tcph->seq) + datalen)) {
-+              if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
-+                      UNLOCK_BH(&ip_mms_lock);
-+                      return NF_DROP;
-+              }
-+      } else {
-+              /* Half a match?  This means a partial retransmisison.
-+                 It's a cracker being funky. */
-+              if (net_ratelimit()) {
-+                      printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
-+                             exp->seq, ct_mms_info->len,
-+                             ntohl(tcph->seq),
-+                             ntohl(tcph->seq) + datalen);
-+              }
-+              UNLOCK_BH(&ip_mms_lock);
-+              return NF_DROP;
-+      }
-+      UNLOCK_BH(&ip_mms_lock);
-+      
-+      return NF_ACCEPT;
-+}
-+
-+static struct ip_nat_helper mms[MAX_PORTS];
-+static char mms_names[MAX_PORTS][10];
-+
-+/* Not __exit: called from init() */
-+static void fini(void)
-+{
-+      int i;
-+
-+      for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
-+              DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
-+              ip_nat_helper_unregister(&mms[i]);
-+      }
-+}
-+
-+static int __init init(void)
-+{
-+      int i, ret = 0;
-+      char *tmpname;
-+
-+      if (ports[0] == 0)
-+              ports[0] = MMS_PORT;
-+
-+      for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
-+
-+              memset(&mms[i], 0, sizeof(struct ip_nat_helper));
-+
-+              mms[i].tuple.dst.protonum = IPPROTO_TCP;
-+              mms[i].tuple.src.u.tcp.port = htons(ports[i]);
-+              mms[i].mask.dst.protonum = 0xFFFF;
-+              mms[i].mask.src.u.tcp.port = 0xFFFF;
-+              mms[i].help = mms_nat_help;
-+              mms[i].me = THIS_MODULE;
-+              mms[i].flags = 0;
-+              mms[i].expect = mms_nat_expected;
-+
-+              tmpname = &mms_names[i][0];
-+              if (ports[i] == MMS_PORT)
-+                      sprintf(tmpname, "mms");
-+              else
-+                      sprintf(tmpname, "mms-%d", i);
-+              mms[i].name = tmpname;
-+
-+              DEBUGP("ip_nat_mms: register helper for port %d\n",
-+                              ports[i]);
-+              ret = ip_nat_helper_register(&mms[i]);
-+
-+              if (ret) {
-+                      printk("ip_nat_mms: error registering "
-+                             "helper for port %d\n", ports[i]);
-+                      fini();
-+                      return ret;
-+              }
-+              ports_c++;
-+      }
-+
-+      return ret;
-+}
-+
-+module_init(init);
-+module_exit(fini);
-diff -urN linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack.h
---- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h   2006-03-01 01:12:47.910002512 +0100
-+++ linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack.h       2006-03-01 01:16:16.710260048 +0100
-@@ -73,6 +73,7 @@
- #include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
- #include <linux/netfilter_ipv4/ip_conntrack_h323.h>
- #include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
-+#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
- /* per expectation: application helper private data */
- union ip_conntrack_expect_help {
-@@ -83,6 +84,7 @@
-       struct ip_ct_pptp_expect exp_pptp_info;
-       struct ip_ct_h225_expect exp_h225_info;
-       struct ip_ct_rtsp_expect exp_rtsp_info;
-+      struct ip_ct_mms_expect exp_mms_info;
- #ifdef CONFIG_IP_NF_NAT_NEEDED
-       union {
-@@ -99,6 +101,7 @@
-       struct ip_ct_pptp_master ct_pptp_info;
-       struct ip_ct_h225_master ct_h225_info;
-       struct ip_ct_rtsp_master ct_rtsp_info;
-+      struct ip_ct_mms_master ct_mms_info;
- };
- #ifdef CONFIG_IP_NF_NAT_NEEDED
-diff -urN linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack_mms.h
---- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack_mms.h       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.32.new/include/linux/netfilter_ipv4/ip_conntrack_mms.h   2006-03-01 01:13:32.993148832 +0100
-@@ -0,0 +1,31 @@
-+#ifndef _IP_CONNTRACK_MMS_H
-+#define _IP_CONNTRACK_MMS_H
-+/* MMS tracking. */
-+
-+#ifdef __KERNEL__
-+#include <linux/netfilter_ipv4/lockhelp.h>
-+
-+DECLARE_LOCK_EXTERN(ip_mms_lock);
-+
-+#define MMS_PORT                         1755
-+#define MMS_SRV_MSG_ID                   196610
-+
-+#define MMS_SRV_MSG_OFFSET               36
-+#define MMS_SRV_UNICODE_STRING_OFFSET    60
-+#define MMS_SRV_CHUNKLENLV_OFFSET        16
-+#define MMS_SRV_CHUNKLENLM_OFFSET        32
-+#define MMS_SRV_MESSAGELENGTH_OFFSET     8
-+#endif
-+
-+/* This structure is per expected connection */
-+struct ip_ct_mms_expect {
-+      u_int32_t len;
-+      u_int32_t padding;
-+      u_int16_t port;
-+};
-+
-+/* This structure exists only once per master */
-+struct ip_ct_mms_master {
-+};
-+
-+#endif /* _IP_CONNTRACK_MMS_H */