diff -NurpP --minimal linux-2.6.21.a/include/linux/netfilter/nf_conntrack_mms.h linux-2.6.21.b/include/linux/netfilter/nf_conntrack_mms.h --- linux-2.6.21.a/include/linux/netfilter/nf_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.21.b/include/linux/netfilter/nf_conntrack_mms.h 2007-05-30 11:50:55.000000000 +0200 @@ -0,0 +1,34 @@ +#ifndef _IP_CONNTRACK_MMS_H +#define _IP_CONNTRACK_MMS_H +/* MMS tracking. */ + +#ifdef __KERNEL__ + +#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 + +/* This structure is per expected connection */ +struct nf_ct_mms_expect { + u_int32_t offset; + u_int32_t len; + u_int32_t padding; + u_int16_t port; +}; + +/* This structure exists only once per master */ +struct nf_ct_mms_master { +}; + +struct nf_conntrack_expect; +extern unsigned int (*nf_nat_mms_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + const struct nf_ct_mms_expect *exp_mms_info, + struct nf_conntrack_expect *exp); +#endif +#endif /* _IP_CONNTRACK_MMS_H */ diff -NurpP --minimal linux-2.6.21.a/include/net/netfilter/nf_conntrack.h linux-2.6.21.b/include/net/netfilter/nf_conntrack.h --- linux-2.6.21.a/include/net/netfilter/nf_conntrack.h 2007-05-30 11:14:07.000000000 +0200 +++ linux-2.6.21.b/include/net/netfilter/nf_conntrack.h 2007-05-30 11:50:55.000000000 +0200 @@ -46,6 +46,7 @@ union nf_conntrack_expect_proto { #include #include #include +#include /* per conntrack: application helper private data */ union nf_conntrack_help { @@ -54,6 +55,7 @@ union nf_conntrack_help { struct nf_ct_h323_master ct_h323_info; struct nf_ct_sane_master ct_sane_info; struct nf_ct_sip_master ct_sip_info; + struct nf_ct_mms_master ct_mms_info; }; #include diff -NurpP --minimal linux-2.6.21.a/include/net/netfilter/nf_conntrack_mms.h linux-2.6.21.b/include/net/netfilter/nf_conntrack_mms.h --- linux-2.6.21.a/include/net/netfilter/nf_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.21.b/include/net/netfilter/nf_conntrack_mms.h 2007-05-30 11:50:55.000000000 +0200 @@ -0,0 +1,34 @@ +#ifndef _IP_CONNTRACK_MMS_H +#define _IP_CONNTRACK_MMS_H +/* MMS tracking. */ + +#ifdef __KERNEL__ + +#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 + +/* This structure is per expected connection */ +struct nf_ct_mms_expect { + u_int32_t offset; + u_int32_t len; + u_int32_t padding; + u_int16_t port; +}; + +/* This structure exists only once per master */ +struct nf_ct_mms_master { +}; + +struct nf_conntrack_expect; +extern unsigned int (*nf_nat_mms_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + const struct nf_ct_mms_expect *exp_mms_info, + struct nf_conntrack_expect *exp); +#endif +#endif /* _IP_CONNTRACK_MMS_H */ diff -NurpP --minimal linux-2.6.21.a/net/ipv4/netfilter/Kconfig linux-2.6.21.b/net/ipv4/netfilter/Kconfig --- linux-2.6.21.a/net/ipv4/netfilter/Kconfig 2007-05-30 11:44:12.000000000 +0200 +++ linux-2.6.21.b/net/ipv4/netfilter/Kconfig 2007-05-30 11:50:55.000000000 +0200 @@ -543,6 +543,11 @@ config NF_NAT_H323 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT default NF_NAT && NF_CONNTRACK_H323 +config NF_NAT_MMS + tristate + depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT + default NF_NAT && NF_CONNTRACK_MMS + config NF_NAT_SIP tristate depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT @@ -847,5 +852,23 @@ config IP_NF_TARGET_TARPIT hardware or IPs. Any TCP port that you would normally DROP or REJECT can instead become a tarpit. +config IP_NF_NAT_MMS + tristate + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n + default IP_NF_NAT if IP_NF_MMS=y + default m if IP_NF_MMS=m + +config IP_NF_MMS + tristate 'MMS protocol support' + depends on IP_NF_CONNTRACK + help + Tracking MMS (Microsoft Windows Media Services) connections + could be problematic if random ports are used to send the + streaming content. This option allows users to track streaming + connections over random UDP or TCP ports. + + If you want to compile it as a module, say M here and read + . If unsure, say `Y'. + endmenu diff -NurpP --minimal linux-2.6.21.a/net/ipv4/netfilter/Makefile linux-2.6.21.b/net/ipv4/netfilter/Makefile --- linux-2.6.21.a/net/ipv4/netfilter/Makefile 2007-05-30 11:44:12.000000000 +0200 +++ linux-2.6.21.b/net/ipv4/netfilter/Makefile 2007-05-30 11:50:55.000000000 +0200 @@ -0,0 +0,1 @@ +obj-$(CONFIG_NF_NAT_MMS) += nf_nat_mms.o diff -NurpP --minimal linux-2.6.21.a/net/ipv4/netfilter/nf_nat_mms.c linux-2.6.21.b/net/ipv4/netfilter/nf_nat_mms.c --- linux-2.6.21.a/net/ipv4/netfilter/nf_nat_mms.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.21.b/net/ipv4/netfilter/nf_nat_mms.c 2007-05-30 11:50:55.000000000 +0200 @@ -0,0 +1,196 @@ +/* MMS extension for TCP NAT alteration. + * (C) 2002 by Filip Sneppe + * 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 + * + * 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 + * + * 2005-02-13: Harald Welte + * - port to 2.6.x + * - update to work with post 2.6.11 helper API changes + * + * 2007-03-30: Marek Guevara Braun + * - port to nf_conntrack + */ + +/* FIXME: issue with UDP & fragmentation with this URL: + http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx + may be related to out-of-order first packets: + basically the expectation is set up correctly, then the server sends + a first UDP packet which is fragmented plus arrives out-of-order. + the MASQUERADING firewall with ip_nat_mms loaded responds with + an ICMP unreachable back to the server */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#define DEBUGP printk +#define DUMP_BYTES(address, counter) \ +({ \ + int temp_counter; \ + for(temp_counter=0; temp_counter"); +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module"); +MODULE_LICENSE("GPL"); + +static unsigned int mms_data_fixup(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + const struct nf_ct_mms_expect *ct_mms_info, + struct nf_conntrack_expect *expect) +{ + u_int32_t newip; + struct nf_conn *ct = expect->master; + struct iphdr *iph = ip_hdr(*pskb); + 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]; + + /* what was the protocol again ? */ + mms_proto = expect->tuple.dst.protonum; + sprintf(proto_string, "%u", mms_proto); + + DEBUGP("nf_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.u3.ip; + expect->saved_proto.tcp.port = expect->tuple.dst.u.tcp.port; + expect->expectfn = nf_nat_follow_master; + + /* Alter conntrack's expectations. */ + for (port = ct_mms_info->port; port != 0; port++) { + expect->tuple.dst.u.tcp.port = htons(port); + if (nf_ct_expect_related(expect) == 0) { + DEBUGP("nf_nat_mms: mms_data_fixup: using port %d\n", + port); + break; + } + } + + if (port == 0) + return NF_DROP; + + 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("nf_nat_mms: new unicode string=%s\n", buffer); + + memset(unicode_buffer, 0, sizeof(char)*75); + + for (i=0; ipadding, ct_mms_info->len); + DEBUGP("nf_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; jpadding; ++j) { + DEBUGP("nf_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 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("nf_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u" + " messageLength=%u\n", *mms_chunkLenLV, *mms_chunkLenLM, + *mms_messageLength); + + nf_nat_mangle_tcp_packet(*pskb, ct, ctinfo, + ct_mms_info->offset, + 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 NF_ACCEPT; +} + +static void __exit fini(void) +{ + nf_nat_mms_hook = NULL; + synchronize_net(); +} + +static int __init init(void) +{ + BUG_ON(nf_nat_mms_hook); + nf_nat_mms_hook = &mms_data_fixup; + + return 0; +} + +module_init(init); +module_exit(fini); diff -NurpP --minimal linux-2.6.21.a/net/netfilter/Kconfig linux-2.6.21.b/net/netfilter/Kconfig --- linux-2.6.21.a/net/netfilter/Kconfig 2007-05-30 11:13:04.000000000 +0200 +++ linux-2.6.21.b/net/netfilter/Kconfig 2007-05-30 11:50:55.000000000 +0200 @@ -271,6 +271,18 @@ config NF_CONNTRACK_TFTP To compile it as a module, choose M here. If unsure, say N. +config NF_CONNTRACK_MMS + tristate 'MMS protocol support' + depends on NF_CONNTRACK + help + Tracking MMS (Microsoft Windows Media Services) connections + could be problematic if random ports are used to send the + streaming content. This option allows users to track streaming + connections over random UDP or TCP ports. + + If you want to compile it as a module, say M here and read + . If unsure, say `Y'. + config NF_CT_NETLINK tristate 'Connection tracking netlink interface (EXPERIMENTAL)' depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK diff -NurpP --minimal linux-2.6.21.a/net/netfilter/Makefile linux-2.6.21.b/net/netfilter/Makefile --- linux-2.6.21.a/net/netfilter/Makefile 2007-05-30 11:13:04.000000000 +0200 +++ linux-2.6.21.b/net/netfilter/Makefile 2007-05-30 11:50:55.000000000 +0200 @@ -26,6 +26,7 @@ nf_conntrack_h323-objs := nf_conntrack_h obj-$(CONFIG_NF_CONNTRACK_AMANDA) += nf_conntrack_amanda.o obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o obj-$(CONFIG_NF_CONNTRACK_H323) += nf_conntrack_h323.o +obj-$(CONFIG_NF_CONNTRACK_MMS) += nf_conntrack_mms.o obj-$(CONFIG_NF_CONNTRACK_IRC) += nf_conntrack_irc.o obj-$(CONFIG_NF_CONNTRACK_NETBIOS_NS) += nf_conntrack_netbios_ns.o obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_conntrack_pptp.o diff -NurpP --minimal linux-2.6.21.a/net/netfilter/nf_conntrack_mms.c linux-2.6.21.b/net/netfilter/nf_conntrack_mms.c --- linux-2.6.21.a/net/netfilter/nf_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.21.b/net/netfilter/nf_conntrack_mms.c 2007-05-30 11:50:55.000000000 +0200 @@ -0,0 +1,374 @@ +/* MMS extension for IP connection tracking + * (C) 2002 by Filip Sneppe + * 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 nf_conntrack_mms.o ports=port1,port2,...port + * + * 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 + * + * 2005-02-13: Harald Welte + * - port to 2.6.x + * - update to work with post 2.6.11 helper API changes + * + * 2007-03-30: Marek Guevara Braun + * - port to nf_conntrack + */ + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define MAX_PORTS 8 +static int ports[MAX_PORTS]; +static int ports_c; +module_param_array(ports, int, &ports_c, 0400); +MODULE_PARM_DESC(ports, "port numbers of MMS"); + +static char mms_buffer[65536]; +static DEFINE_SPINLOCK(mms_buffer_lock); + +unsigned int (*nf_nat_mms_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + const struct nf_ct_mms_expect *exp_mms_info, + struct nf_conntrack_expect *exp); +EXPORT_SYMBOL(nf_nat_mms_hook); + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +MODULE_AUTHOR("Filip Sneppe "); +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("nf_conntrack_mms: offset 60: %s\n", (const char *)(tempstring)); + + /* IP address ? */ + *mms_ip = asciiiptoi(tempstring+2); + + i=sprintf(getlengthstring, "%pI4", 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; +} + + +/* FIXME: This should be in userspace. Later. */ +static int help(struct sk_buff **pskb, + unsigned int protoff, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo) +{ + int ret = NF_DROP; + struct tcphdr _tcph, *th; + char *data, *mb_ptr; + unsigned int datalen, dataoff; + + + //struct tcphdr *tcph = (void *)iph + iph->ihl * 4; + //unsigned int tcplen = len - iph->ihl * 4; + //unsigned int datalen = tcplen - tcph->doff * 4; + int dir = CTINFO2DIR(ctinfo); + struct nf_conntrack_expect *exp; + struct nf_conntrack_tuple *tuple; + struct nf_ct_mms_expect _emmi, *exp_mms_info = &_emmi; + + u_int32_t mms_ip; + u_int16_t mms_proto; + char mms_proto_string[8]; + u_int16_t mms_port; + __be16 port; + char *mms_string_b, *mms_string_e, *mms_padding_e; + typeof(nf_nat_mms_hook) nf_nat_mms; + + /* 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("nf_conntrack_mms: Conntrackinfo = %u\n", ctinfo); + return NF_ACCEPT; + } + + /* Not whole TCP header? */ + th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph); + if (th == NULL) + return NF_ACCEPT; + + /* No data ? */ + dataoff = protoff + th->doff*4; + if (dataoff >= (*pskb)->len) + return NF_ACCEPT; + + datalen = (*pskb)->len - dataoff; + DEBUGP("nf_conntrack_mms: datalen:%u\n", datalen); + + spin_lock_bh(&mms_buffer_lock); + mb_ptr = skb_header_pointer(*pskb, dataoff, + (*pskb)->len - dataoff, mms_buffer); + BUG_ON(mb_ptr == NULL); + + data = mb_ptr; + +#if 0 + /* Checksum invalid? Ignore. */ + /* FIXME: Source route IP option packets --RR */ + 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; + } +#endif + + /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP + * payload */ + + /* FIXME: There is an issue with only looking at this packet: before + * this packet, the client has already sent a packet to the server with + * the server's hostname according to the client (think of it as the + * "Host: " header in HTTP/1.1). The server will break the connection + * if this doesn't correspond to its own host header. The client can + * also connect to an IP address; if it's the server's IP address, it + * will not break the connection. When doing DNAT on a connection where + * the client uses a server's IP address, the nat module should detect + * this and change this string accordingly to the DNATed address. This + * should probably be done by checking for an IP address, then storing + * it as a member of struct ip_ct_mms_expect and checking for it in + * ip_nat_mms... + */ + if ((MMS_SRV_MSG_OFFSET >= datalen) || + ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) != MMS_SRV_MSG_ID)) + goto out; + + DEBUGP("nf_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()) + /* FIXME: more verbose debugging ? */ + printk(KERN_WARNING + "nf_conntrack_mms: Unable to parse " + "data payload\n"); + + sprintf(mms_proto_string, "(%u)", mms_proto); + DEBUGP("nf_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 + * */ + + DEBUGP("nf_conntrack_mms: tcph->seq = %u\n", tcph->seq); + + exp = nf_ct_expect_alloc(ct); + if (exp == NULL) { + ret = NF_DROP; + goto out; + } + + exp_mms_info->offset = (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("nf_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); + + tuple = &ct->tuplehash[!dir].tuple; + port = htons(mms_port); + nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, tuple->src.l3num, + NULL, &tuple->dst.u3, + IPPROTO_TCP, NULL, &port); + + nf_nat_mms = rcu_dereference(nf_nat_mms_hook); + if (nf_nat_mms && ct->status & IPS_NAT_MASK) + ret = nf_nat_mms(pskb, ctinfo, exp_mms_info, exp); + else if (nf_ct_expect_related(exp) != 0) + ret = NF_DROP; + nf_ct_expect_put(exp); +/* + exp->tuple = ((struct nf_conntrack_tuple) + { { ct->tuplehash[!dir].tuple.src.u3.ip, { 0 } }, + { mms_ip, + { .tcp = { (__u16) ntohs(mms_port) } }, + mms_proto } } + ); + exp->mask = ((struct nf_conntrack_tuple) + { { 0xFFFFFFFF, { 0 } }, + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }}); + exp->expectfn = NULL; + exp->master = ct; + + if (nf_nat_mms_hook) + ret = nf_nat_mms_hook(pskb, ctinfo, exp_mms_info, exp); + else if (nf_conntrack_expect_related(exp) != 0) + ret = NF_DROP; + + nf_conntrack_expect_put(exp); +*/ +out: + spin_unlock_bh(&mms_buffer_lock); + return ret; +} + +static struct nf_conntrack_helper mms[MAX_PORTS]; +static char mms_names[MAX_PORTS][10]; +static const struct nf_conntrack_expect_policy mms_exp_policy = { + .max_expected = 1, + .timeout = 120, +}; + +/* Not __exit: called from init() */ +static void fini(void) +{ + int i; + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { + DEBUGP("nf_conntrack_mms: unregistering helper for port %d\n", + ports[i]); + nf_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 nf_conntrack_helper)); + mms[i].tuple.src.u.tcp.port = htons(ports[i]); + mms[i].tuple.dst.protonum = IPPROTO_TCP; + mms[i].me = THIS_MODULE; + mms[i].expect_policy = &mms_exp_policy; + 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("nf_conntrack_mms: registering helper for port %d\n", + ports[i]); + ret = nf_conntrack_helper_register(&mms[i]); + + if (ret) { + fini(); + return ret; + } + ports_c++; + } + return 0; +} + +module_init(init); +module_exit(fini);