From 3e389402c8cd1e34deba6fd2e2d87bc3c9ee41f1 Mon Sep 17 00:00:00 2001
From: florian <florian@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Date: Mon, 12 Dec 2005 15:59:31 +0000
Subject: [PATCH] Added support for MMS connection tracking

git-svn-id: svn://svn.openwrt.org/openwrt/trunk/openwrt@2640 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 target/linux/linux-2.4/config/brcm            |   2 +
 .../generic/615-netfilter_nat_mms.patch       | 739 ++++++++++++++++++
 target/linux/package/Config.in                |   1 +
 3 files changed, 742 insertions(+)
 create mode 100644 target/linux/linux-2.4/patches/generic/615-netfilter_nat_mms.patch

diff --git a/target/linux/linux-2.4/config/brcm b/target/linux/linux-2.4/config/brcm
index 8bd18cf14..343b14c63 100644
--- a/target/linux/linux-2.4/config/brcm
+++ b/target/linux/linux-2.4/config/brcm
@@ -364,6 +364,7 @@ CONFIG_IP_NF_CT_PROTO_GRE=m
 CONFIG_IP_NF_PPTP=m
 CONFIG_IP_NF_SIP=m
 CONFIG_IP_NF_H323=m
+CONFIG_IP_NF_MMS=m
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=y
 CONFIG_IP_NF_MATCH_LIMIT=m
@@ -414,6 +415,7 @@ CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_NAT_PPTP=m
 CONFIG_IP_NF_NAT_SIP=m
 CONFIG_IP_NF_NAT_H323=m
+CONFIG_IP_NF_NAT_MMS=m
 CONFIG_IP_NF_NAT_PROTO_GRE=m
 CONFIG_IP_NF_NAT_AMANDA=m
 CONFIG_IP_NF_NAT_SNMP_BASIC=m
diff --git a/target/linux/linux-2.4/patches/generic/615-netfilter_nat_mms.patch b/target/linux/linux-2.4/patches/generic/615-netfilter_nat_mms.patch
new file mode 100644
index 000000000..14e070a64
--- /dev/null
+++ b/target/linux/linux-2.4/patches/generic/615-netfilter_nat_mms.patch
@@ -0,0 +1,739 @@
+diff -urN linux-2.4.32/net/ipv4/netfilter/Config.in linux-2.4.32/net/ipv4/netfilter/Config.in
+--- linux-2.4.32/net/ipv4/netfilter/Config.in	2005-12-12 16:29:01.000000000 +0100
++++ linux-2.4.32/net/ipv4/netfilter/Config.in	2005-12-12 16:35:37.000000000 +0100
+@@ -17,6 +17,7 @@
+   dep_tristate '   PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE
+   dep_tristate '  SIP protocol support' CONFIG_IP_NF_SIP $CONFIG_IP_NF_CONNTRACK
+   dep_tristate '  H.323 (netmeeting) support' CONFIG_IP_NF_H323 $CONFIG_IP_NF_CONNTRACK
++  dep_tristate '  MMS protocol support' CONFIG_IP_NF_MMS $CONFIG_IP_NF_CONNTRACK
+ fi
+ 
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+@@ -120,6 +121,13 @@
+ 	  define_tristate CONFIG_IP_NF_NAT_H323 $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_IP_NF_AMANDA" = "m" ]; then
+         define_tristate CONFIG_IP_NF_NAT_AMANDA m
+       else
+diff -urN linux-2.4.32/net/ipv4/netfilter/Makefile linux-2.4.32/net/ipv4/netfilter/Makefile
+--- linux-2.4.32/net/ipv4/netfilter/Makefile	2005-12-12 16:29:01.000000000 +0100
++++ linux-2.4.32/net/ipv4/netfilter/Makefile	2005-12-12 16:36:26.000000000 +0100
+@@ -61,6 +61,10 @@
+ ifdef CONFIG_IP_NF_NAT_H323
+ 	export-objs += ip_conntrack_h323.o
+ endif
++obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
++ifdef CONFIG_IP_NF_NAT_MMS
++	export-objs += ip_conntrack_mms.o
++endif
+ 
+ 
+ # NAT helpers 
+@@ -72,6 +76,7 @@
+ obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
+ obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o
+ obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.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/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/net/ipv4/netfilter/ip_conntrack_mms.c	2005-12-12 16:32:54.000000000 +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/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/net/ipv4/netfilter/ip_nat_mms.c	2005-12-12 16:32:54.000000000 +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/include/linux/netfilter_ipv4/ip_conntrack.h
+--- linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h	2005-12-12 16:29:01.000000000 +0100
++++ linux-2.4.32/include/linux/netfilter_ipv4/ip_conntrack.h	2005-12-12 16:34:09.000000000 +0100
+@@ -73,6 +73,7 @@
+ #include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_sip.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_h323.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_sip_expect exp_sip_info;
+ 	struct ip_ct_h225_expect exp_h225_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_sip_master ct_sip_info;
+ 	struct ip_ct_h225_master ct_h225_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/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/include/linux/netfilter_ipv4/ip_conntrack_mms.h	2005-12-12 16:32:54.000000000 +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 */
diff --git a/target/linux/package/Config.in b/target/linux/package/Config.in
index b58301db9..42acc3dfa 100644
--- a/target/linux/package/Config.in
+++ b/target/linux/package/Config.in
@@ -1,5 +1,6 @@
 source "target/linux/package/alsa/Config.in"
 source "target/linux/package/diag/Config.in"
+source "target/linux/package/eagle-usb/Config.in"
 source "target/linux/package/fuse/Config.in"
 source "target/linux/package/hostap/Config.in"
 source "target/linux/package/madwifi/Config.in"
-- 
2.20.1