Skip to contentSkip to conversation

ip_nat_cuseeme NAT helper

PATCH In review Filip Sneppe (Cronos) 3 participants 3 messages Feb 18, 2003 – Feb 26, 2003

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ip_nat_cuseeme NAT helper

Hi Harald & others,

This implements a NAT helper for the CuSeeMe protocol, both as a patch against 2.4.20 and as a patch-o-matic patch.

Note that it requires Brian J. Murrell's newnat-udp-helper.patch that should be in 2.4.21+ kernels (the 2.4.20 patch has Brian's patch in it).

The module should work in DNAT and SNAT scenarios - I posted an earlier version a couple of months ago, but that code had one bug where one would see his/her own messages, yet others didn't see anything. This version works in all my SNAT/DNAT tests...

Regards,
Filip

patch-o-matic/extra/cuseeme-nat.patch +367 -0
diff -urN netfilter/patch-o-matic/extra/cuseeme-nat.patch netfilter-cuseeme/patch-o-matic/extra/cuseeme-nat.patch
@@ -0,0 +1,367 @@
+diff -urN -X dontdiff linux-2.4.20-orig/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h linux-2.4.20-cuseeme/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h
+--- linux-2.4.20-orig/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.20-cuseeme/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h	2003-02-05 20:58:20.000000000 +0100
+@@ -0,0 +1,70 @@
++#ifndef _IP_CT_CUSEEME
++#define _IP_CT_CUSEEME
++
++#define CUSEEME_PORT 7648
++
++/* These structs come from the 2.2 ip_masq_cuseeme code... */
++
++#pragma pack(1)
++/* CuSeeMe data header */
++struct cu_header {
++	u_int16_t	dest_family;
++	u_int16_t	dest_port;
++	u_int32_t	dest_addr;
++	int16_t		family;
++	u_int16_t	port;
++	u_int32_t	addr;
++	u_int32_t	seq;
++	u_int16_t	msg;
++	u_int16_t	data_type;
++				/* possible values:
++				 * 1	small video
++				 * 2	big video
++				 * 3	audio
++				 * 100	acknowledge connectivity when there
++				 * 	is nothing else to send
++				 * 101	OpenContinue packet
++				 * 104	display a text message and 
++				 * 	disconnect (used by reflector to
++				 * 	kick clients off)
++				 * 105	display a text message (welcome
++				 * 	message from reflector)
++				 * 106	exchanged among reflectors for
++				 * 	reflector interoperation
++				 * 107	carry aux stream data when there is
++				 *	no video to piggy-back on
++				 * 108	obsolete (used in Mac alpha version)
++				 * 109	obsolete (used in Mac alpha version)
++				 * 110	used for data rate control
++				 * 111	used for data rate control
++				 * 256	aux data control messages
++				 * 257	aux data packets
++				 * */
++	u_int16_t	packet_len;
++};
++
++/* Open Continue Header */
++struct oc_header {
++	struct cu_header	cu_head;
++	u_int16_t	client_count; /* Number of client info structs */
++	u_int32_t	seq_no;
++	char		user_name[20];
++	char		stuff[4];     /* Flags, version stuff, etc */
++};
++
++/* Client info structures */
++struct client_info {
++	u_int32_t	address;      /* Client address */
++	char		stuff[8];     /* Flags, pruning bitfield, packet counts, etc */
++};
++#pragma pack()
++
++/* This structure is per expected connection */
++struct ip_ct_cuseeme_expect {
++};
++
++/* This structure exists only once per master */
++struct ip_ct_cuseeme_master {
++};
++
++#endif /* _IP_CT_CUSEEME */
+diff -urN -X dontdiff linux-2.4.20-orig/net/ipv4/netfilter/ip_nat_cuseeme.c linux-2.4.20-cuseeme/net/ipv4/netfilter/ip_nat_cuseeme.c
+--- linux-2.4.20-orig/net/ipv4/netfilter/ip_nat_cuseeme.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.20-cuseeme/net/ipv4/netfilter/ip_nat_cuseeme.c	2003-02-18 00:37:52.000000000 +0100
+@@ -0,0 +1,289 @@
++/* CuSeeMe extension for UDP NAT alteration.
++ * (C) 2002 by Filip Sneppe <[email protected]>
++ * based on ip_masq_cuseeme.c in 2.2 kernels
++ *
++ * ip_nat_cuseeme.c v0.0.7 2003-02-18
++ *
++ *      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_cuseeme.o ports=port1,port2,...port<MAX_PORTS>
++ *
++ *      Please give the ports of the CuSeeMe traffic you want to track.
++ *      If you don't specify ports, the default will be UDP port 7648.
++ *
++ *      CuSeeMe Protocol Documentation:
++ *      http://cu-seeme.net/squeek/tech/contents.html
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/netfilter_ipv4.h>
++#include <linux/ip.h>
++#include <linux/udp.h>
++
++#include <linux/netfilter.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
++#include <linux/netfilter_ipv4/ip_conntrack_cuseeme.h>
++#include <linux/netfilter_ipv4/ip_nat_helper.h>
++#include <linux/netfilter_ipv4/ip_nat_rule.h>
++
++MODULE_AUTHOR("Filip Sneppe <[email protected]>");
++MODULE_DESCRIPTION("Netfilter NAT helper for CuSeeMe");
++MODULE_LICENSE("GPL");
++
++#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");
++MODULE_PARM_DESC(ports, "port numbers of CuSeeMe reflectors");
++#endif
++
++#if 0
++#define DEBUGP printk
++#else
++#define DEBUGP(format, args...)
++#endif
++
++/* process packet from client->reflector, possibly manipulate client IP in payload */
++void cuseeme_mangle_outgoing(struct ip_conntrack *ct,
++                             struct ip_nat_info *info,
++                             enum ip_conntrack_info ctinfo,
++                             struct sk_buff **pskb,
++                             char *data,
++                             unsigned int datalen)
++{
++	char new_port_ip[6];
++	struct cu_header *cu_head=(struct cu_header *)data;
++	
++	DEBUGP("ip_nat_cuseeme: outgoing packet, ID %u, dest_family %u\n", 
++	       ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
++		
++	/* At least check that the data at offset 10 is the client's port and IP address */
++	if ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == cu_head->addr) &&
++	    (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port == cu_head->port)) {
++		DEBUGP("ip_nat_cuseeme: rewrite outgoing client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n", 
++		       NIPQUAD(cu_head->addr),
++		       ntohs(cu_head->port),
++		       NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
++		       ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port));
++		*((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
++		*((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
++		/* at offset 10, replace 6 bytes containing port + IP address */
++		ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
++		                         10, 6, (char *)(new_port_ip), 6);
++	} else 
++		DEBUGP("ip_nat_cuseeme: expected outgoing client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
++		       NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
++		       ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port),
++		       NIPQUAD(cu_head->addr),
++		       ntohs(cu_head->port));
++}
++
++/* process packet from reflector->client, possibly manipulate client IP & reflector IP in payload */
++void cuseeme_mangle_incoming(struct ip_conntrack *ct,
++                             struct ip_nat_info *info,
++                             enum ip_conntrack_info ctinfo,
++                             struct sk_buff **pskb,
++                             char *data,
++                             unsigned int datalen)
++{
++	char new_port_ip[6];
++	struct cu_header *cu_head = (struct cu_header *)data;
++	struct oc_header *oc_head = (struct oc_header *)data; 
++	struct client_info *ci; 
++	int i, off;
++
++	
++	DEBUGP("ip_nat_cuseeme: incoming packet, ID %u, dest_family %u\n", 
++	       ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
++		
++	/* Check if we're really dealing with the client's port + IP address before rewriting */
++	if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == cu_head->dest_addr) &&
++	   (ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port == cu_head->dest_port)) {
++		DEBUGP("ip_nat_cuseeme: rewrite incoming client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 2\n",
++		       NIPQUAD(cu_head->dest_addr),
++		       ntohs(cu_head->dest_port),
++		       NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
++		       ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port));
++		*((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
++		*((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
++		/* at offset 2, replace 6 bytes containing port + IP address */
++		ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
++		                         2, 6, (char *)(new_port_ip), 6);
++	} else 
++		DEBUGP("ip_nat_cuseeme: expected incoming client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
++		       NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
++		       ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port),
++		       NIPQUAD(cu_head->dest_addr),
++		       ntohs(cu_head->dest_port));
++	
++	/* Check if we're really dealing with the server's port + IP address before rewriting. 
++	   In some cases, the IP address == 0.0.0.0 so we don't rewrite anything */
++	if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == cu_head->addr) &&
++	   (ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port == cu_head->port)) {
++		DEBUGP("in_nat_cuseeme: rewrite incoming server %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n",
++		       NIPQUAD(cu_head->addr),
++		       ntohs(cu_head->port),
++		       NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),
++		       ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port));
++		*((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port;
++		*((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
++		/* at offset 10, replace 6 bytes containing port + IP address */
++		ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
++		                         10, 6, (char *)(new_port_ip), 6);
++	} else 
++		/* Sometimes we find 0.0.0.0, sometimes an IP address - the docs say this field
++		   is not that important so we're not logging this unless we're debugging */
++		DEBUGP("ip_nat_cuseeme: no biggie, expected incoming server %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
++		       NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip),
++		       ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port),
++		       NIPQUAD(cu_head->addr),
++		       ntohs(cu_head->port));
++	
++	/* Spin through client_info structs until we find our own */
++	if((ntohs(cu_head->data_type) == 101) && (datalen >= sizeof(struct oc_header))) {
++		DEBUGP("ip_nat_cuseeme: looping through %u client_info structs\n", oc_head->client_count);
++		for(i=0, off=sizeof(struct oc_header);
++		    (i < oc_head->client_count && 
++		    off+sizeof(struct client_info) <= datalen); 
++		    i++) {
++			ci=(struct client_info *)(data+off);
++			DEBUGP("ip_nat_cuseeme: comparing %u.%u.%u.%u with %u.%u.%u.%u at offset %u\n", 
++			       NIPQUAD(ci->address), NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
++			       (unsigned int)((void *)&(ci->address) - (void *)cu_head));
++			if(ci->address == ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) {
++				/* mangle this IP address */
++				DEBUGP("ip_nat_cuseeme: changing %u.%u.%u.%u->%u.%u.%u.%u at offset %u\n",
++				       NIPQUAD(ci->address), 
++				       NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
++				       (unsigned int)((void *)&(ci->address) - (void *)cu_head));
++				ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
++				                         (unsigned int)((void *)&(ci->address) - (void *)cu_head), 4, 
++				                         (char *)(&(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip)), 4);
++				break;
++			} else 
++				off+=sizeof(struct client_info);
++		}
++	} else
++		DEBUGP("ip_nat_cuseeme: data_type %u, datalen %u < sizeof(struct oc_header) %u\n", 
++		       ntohs(cu_head->data_type), datalen, sizeof(struct oc_header));
++}
++
++static unsigned int 
++cuseeme_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 udphdr *udph = (void *)iph + iph->ihl * 4;
++	int dir = CTINFO2DIR(ctinfo);
++	unsigned int datalen = (*pskb)->len - iph->ihl * 4 - sizeof(struct udphdr);
++	char *data = (char *) &udph[1];
++	
++	DEBUGP("ip_nat_cuseeme: cuseeme_nat_help, direction: %s 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" : "???"
++	      );
++	
++	/* Only mangle things once: original direction in POST_ROUTING
++	   and reply direction on PRE_ROUTING. */
++	if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
++	    || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
++		DEBUGP("ip_nat_cuseeme: 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;
++	}
++	
++	if(datalen < sizeof(struct cu_header)) {
++		/* packet too small */
++		if (net_ratelimit())
++			printk("ip_nat_cuseeme: payload too small (%u, should be >= %u)\n", 
++			       datalen, sizeof(struct cu_header));
++		return NF_ACCEPT;
++	}
++
++
++	/* In the debugging output, "outgoing" is from client to server, and
++	   "incoming" is from server to client */
++	if(HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) 
++		cuseeme_mangle_outgoing(ct, info, ctinfo, pskb, data, datalen);
++	else 
++		cuseeme_mangle_incoming(ct, info, ctinfo, pskb, data, datalen);
++
++	return NF_ACCEPT;
++}
++
++static struct ip_nat_helper cuseeme[MAX_PORTS];
++static char cuseeme_names[MAX_PORTS][14];  /* cuseeme-65535 */
++
++static void fini(void)
++{
++	int i;
++	
++	for (i = 0 ; i < ports_c; i++) {
++		DEBUGP("ip_nat_cuseeme: unregistering helper for port %d\n", ports[i]);
++		       ip_nat_helper_unregister(&cuseeme[i]);
++	}
++}
++
++static int __init init(void)
++{
++	int i, ret = 0;
++	char *tmpname;
++
++	if (!ports[0])
++		ports[0] = CUSEEME_PORT;
++		
++	for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
++		memset(&cuseeme[i], 0, sizeof(struct ip_nat_helper));
++
++		cuseeme[i].tuple.dst.protonum = IPPROTO_UDP;
++		cuseeme[i].tuple.dst.u.udp.port = htons(ports[i]);
++		cuseeme[i].mask.dst.protonum = 0xFFFF;
++		cuseeme[i].mask.dst.u.udp.port = 0xFFFF;
++		cuseeme[i].help = cuseeme_nat_help;
++		cuseeme[i].flags = IP_NAT_HELPER_F_STANDALONE + 
++		                   IP_NAT_HELPER_F_ALWAYS; /* dunno if IP_NAT_HELPER_F_ALWAYS
++		                                              is stricly needed... */
++		cuseeme[i].me = THIS_MODULE;
++		cuseeme[i].expect = NULL; /* cuseeme_nat_expected; */
++			
++		tmpname = &cuseeme_names[i][0];
++		if (ports[i] == CUSEEME_PORT)
++			sprintf(tmpname, "cuseeme");
++		else
++			sprintf(tmpname, "cuseeme-%d", ports[i]);
++		cuseeme[i].name = tmpname;
++			
++		DEBUGP("ip_nat_cuseeme: registering helper for port %d: name %s\n",
++		       ports[i], cuseeme[i].name);
++		ret = ip_nat_helper_register(&cuseeme[i]);
++			
++		if (ret) {
++			printk("ip_nat_cuseeme: unable to register helper for port %d\n",
++			       ports[i]);
++			fini();
++			return ret;
++		}
++		ports_c++;
++	}
++	return ret;
++}
++	
++module_init(init);
++module_exit(fini);
patch-o-matic/extra/cuseeme-nat.patch.config.in +2 -0
diff -urN netfilter/patch-o-matic/extra/cuseeme-nat.patch.config.in netfilter-cuseeme/patch-o-matic/extra/cuseeme-nat.patch.config.in
@@ -0,0 +1,2 @@
+  dep_tristate '  IRC protocol support' CONFIG_IP_NF_IRC $CONFIG_IP_NF_CONNTRACK
+  dep_tristate '  CuSeeMe protocol support' CONFIG_IP_NF_CUSEEME $CONFIG_IP_NF_CONNTRACK
patch-o-matic/extra/cuseeme-nat.patch.config.in-2 +8 -0
diff -urN netfilter/patch-o-matic/extra/cuseeme-nat.patch.config.in-2 netfilter-cuseeme/patch-o-matic/extra/cuseeme-nat.patch.config.in-2
@@ -0,0 +1,8 @@
+          define_tristate CONFIG_IP_NF_NAT_IRC $CONFIG_IP_NF_NAT
+        fi
+      fi
+      if [ "$CONFIG_IP_NF_CUSEEME" = "m" ]; then
+        define_tristate CONFIG_IP_NF_NAT_CUSEEME m
+      else
+        if [ "$CONFIG_IP_NF_CUSEEME" = "y" ]; then
+         define_tristate CONFIG_IP_NF_NAT_CUSEEME $CONFIG_IP_NF_NAT
patch-o-matic/extra/cuseeme-nat.patch.configure.help +11 -0
diff -urN netfilter/patch-o-matic/extra/cuseeme-nat.patch.configure.help netfilter-cuseeme/patch-o-matic/extra/cuseeme-nat.patch.configure.help
@@ -0,0 +1,11 @@
+CONFIG_IP_NF_IRC
+CuSeeMe protocol support
+CONFIG_IP_NF_CUSEEME
+  The CuSeeMe conferencing protocol is problematic when used in
+  conjunction with NAT; even though there are no random ports used for
+  extra connections, the messages contain IP addresses inside them.
+  This NAT helper mangles the IP address inside packets so both
+  parties don't get confused.
+
+  If you want to compile it as a module, say M here and read
+  <file:Documentation/modules.txt>.  If unsure, say `Y'.
patch-o-matic/extra/cuseeme-nat.patch.help +21 -0
diff -urN netfilter/patch-o-matic/extra/cuseeme-nat.patch.help netfilter-cuseeme/patch-o-matic/extra/cuseeme-nat.patch.help
@@ -0,0 +1,21 @@
+Author: Filip Sneppe <[email protected]>
+Status: WorksForMe(tm) - lightly tested - needs more success stories
+
+This adds CONFIG_IP_NF_CUSEEME: support for the CuSeeMe messaging 
+protocol. 
+
+Unlike protocols like FTP or IRC, CuSeeMe doesn't open any
+seemingly random ports for data transfers. It does, however, 
+contain IP addresses of clients and server (reflector) inside the
+packet payload, making it impossible to use with NAT
+scenario's.
+
+There is only a NAT module, ip_nat_cuseeme.o, and no 
+connection tracking helper. 
+
+By default, the helper module tracks UDP traffic over port 7648.
+
+This helper has been tested in SNAT and DNAT setups. 
+
+Note that this helper requires Brian J. Murrell's 
+newnat-udp-helper.patch (submitted at 2.4.21-pre3 time)
patch-o-matic/extra/cuseeme-nat.patch.makefile +2 -0
diff -urN netfilter/patch-o-matic/extra/cuseeme-nat.patch.makefile netfilter-cuseeme/patch-o-matic/extra/cuseeme-nat.patch.makefile
@@ -0,0 +1,2 @@
+# NAT helpers 
+obj-$(CONFIG_IP_NF_NAT_CUSEEME) += ip_nat_cuseeme.o
Documentation/Configure.help +11 -0
diff -urN -X dontdiff linux-2.4.20-orig/Documentation/Configure.help linux-2.4.20-cuseeme/Documentation/Configure.help
@@ -2508,6 +2508,17 @@
   If you want to compile it as a module, say M here and read
   <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+CuSeeMe protocol support
+CONFIG_IP_NF_CUSEEME
+  The CuSeeMe conferencing protocol is problematic when used in
+  conjunction with NAT; even though there are no random ports used for
+  extra connections, the messages contain IP addresses inside them.
+  This NAT helper mangles the IP address inside packets so both
+  parties don't get confused.
+
+  If you want to compile it as a module, say M here and read
+  <file:Documentation/modules.txt>.  If unsure, say `Y'.
+
 IRC Send/Chat protocol support
 CONFIG_IP_NF_IRC
   There is a commonly-used extension to IRC called
include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h +70 -0

70 lines not on this page · raw message

include/linux/netfilter_ipv4/ip_nat_helper.h +7 -0
diff -urN -X dontdiff linux-2.4.20-orig/include/linux/netfilter_ipv4/ip_nat_helper.h linux-2.4.20-cuseeme/include/linux/netfilter_ipv4/ip_nat_helper.h
@@ -50,6 +50,13 @@
 				unsigned int match_len,
 				char *rep_buffer,
 				unsigned int rep_len);
+extern int ip_nat_mangle_udp_packet(struct sk_buff **skb,
+				struct ip_conntrack *ct,
+				enum ip_conntrack_info ctinfo,
+				unsigned int match_offset,
+				unsigned int match_len,
+				char *rep_buffer,
+				unsigned int rep_len);
 extern int ip_nat_seq_adjust(struct sk_buff *skb,
 				struct ip_conntrack *ct,
 				enum ip_conntrack_info ctinfo);
net/ipv4/netfilter/Config.in +8 -0
diff -urN -X dontdiff linux-2.4.20-orig/net/ipv4/netfilter/Config.in linux-2.4.20-cuseeme/net/ipv4/netfilter/Config.in
@@ -8,6 +8,7 @@
 if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
   dep_tristate '  FTP protocol support' CONFIG_IP_NF_FTP $CONFIG_IP_NF_CONNTRACK
   dep_tristate '  IRC protocol support' CONFIG_IP_NF_IRC $CONFIG_IP_NF_CONNTRACK
+  dep_tristate '  CuSeeMe protocol support' CONFIG_IP_NF_CUSEEME $CONFIG_IP_NF_CONNTRACK
 fi
 
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
@@ -67,6 +68,13 @@
           define_tristate CONFIG_IP_NF_NAT_IRC $CONFIG_IP_NF_NAT
         fi
       fi
+      if [ "$CONFIG_IP_NF_CUSEEME" = "m" ]; then
+        define_tristate CONFIG_IP_NF_NAT_CUSEEME m
+      else
+        if [ "$CONFIG_IP_NF_CUSEEME" = "y" ]; then
+         define_tristate CONFIG_IP_NF_NAT_CUSEEME $CONFIG_IP_NF_NAT
+        fi
+      fi
       # If they want FTP, set to $CONFIG_IP_NF_NAT (m or y), 
       # or $CONFIG_IP_NF_FTP (m or y), whichever is weaker.  Argh.
       if [ "$CONFIG_IP_NF_FTP" = "m" ]; then
net/ipv4/netfilter/Makefile +1 -0
diff -urN -X dontdiff linux-2.4.20-orig/net/ipv4/netfilter/Makefile linux-2.4.20-cuseeme/net/ipv4/netfilter/Makefile
@@ -45,6 +45,7 @@
 # NAT helpers 
 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
+obj-$(CONFIG_IP_NF_NAT_CUSEEME) += ip_nat_cuseeme.o
 
 # generic IP tables 
 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
net/ipv4/netfilter/ip_nat_cuseeme.c +289 -0

289 lines not on this page · raw message

net/ipv4/netfilter/ip_nat_helper.c +143 -32

226 lines not on this page · raw message

net/ipv4/netfilter/ip_nat_standalone.c +1 -0
diff -urN -X dontdiff linux-2.4.20-orig/net/ipv4/netfilter/ip_nat_standalone.c linux-2.4.20-cuseeme/net/ipv4/netfilter/ip_nat_standalone.c
@@ -358,5 +358,6 @@
 EXPORT_SYMBOL(ip_nat_helper_unregister);
 EXPORT_SYMBOL(ip_nat_cheat_check);
 EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
+EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
 EXPORT_SYMBOL(ip_nat_used_tuple);
 MODULE_LICENSE("GPL");
#1 lore raw
Quoted 9 lines · Filip Sneppe (Cronos)

Hi Harald & others,

This implements a NAT helper for the CuSeeMe protocol, both as a patch against 2.4.20 and as a patch-o-matic patch.

Note that it requires Brian J. Murrell's newnat-udp-helper.patch that should be in 2.4.21+ kernels (the 2.4.20 patch has Brian's patch in it).

Quoted 7 lines

The module should work in DNAT and SNAT scenarios - I posted an earlier version a couple of months ago, but that code had one bug where one would see his/her own messages, yet others didn't see anything. This version works in all my SNAT/DNAT tests...

Regards,
Filip

Hi Filip!

I've just looked at the patch you sent, and found this piece of code:

++ char new_port_ip[6];
...
++ *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;

This will make oopses on all platforms with strict alignment restrictions. Probably most RISC platforms fall into this category, some (like Alpha) have software trap emulation for such cases causing horrible slowdown (a single assignment could take a few thousand CPU cycles).

Generally, you should not access a 32-bit dword at a memory location whose two LSB bits are non-zero.
Please consider reworking your patch to make it portable.

Thanks,
Laszlo

#2 lore raw
In reply to Filip Sneppe (Cronos)
Quoted 4 lines · Filip Sneppe (Cronos)

Hi Harald & others,

This implements a NAT helper for the CuSeeMe protocol, both as a patch against 2.4.20 and as a patch-o-matic patch.

thanks, I have added your patch to patch-o-matic.

But please consider a update based on the comment by Laszlo Valko about strict alignment issues...

Quoted 2 lines

Regards,
Filip

Signature · 5 lines
- Harald Welte <[email protected]>             http://www.netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie