[PATCH] errata patch to ip_conntrack/nat_irc

Daniel Stone daniel@dustpuppy.ods.org
Sun, 09 Jul 2000 20:11:41 +1000


Here's the new diff with two quick kernel-related patches:
* if you compiled it as a module, it wouldn't compile, ip_conntrack_ftp would
* it didn't have a Configure.help entry
* this will make it correct form and get Harald more points ;)

Be well,
d

--
Daniel Stone
Kernel Hacker (or at least has aspirations to be)
daniel@dustpuppy.ods.org
http://dustpuppy.ods.org

diff -Nru linux-2.4.0-test2/include/linux/netfilter_ipv4/ip_conntrack.h linux-laforge/include/linux/netfilter_ipv4/ip_conntrack.h
--- linux-2.4.0-test2/include/linux/netfilter_ipv4/ip_conntrack.h	Sat Jun 24 06:33:41 2000
+++ linux-laforge/include/linux/netfilter_ipv4/ip_conntrack.h	Fri Jul  7 17:47:04 2000
@@ -84,6 +84,13 @@
 #endif
 #endif
 
+#if defined(CONFIG_IP_NF_IRC) || defined(CONFIG_IP_NF_IRC_MODULE)
+#include <linux/netfilter_ipv4/ip_conntrack_irc.h>
+#ifdef CONFIG_IP_NF_NAT_NEEDED
+#include <linux/netfilter_ipv4/ip_nat_irc.h>
+#endif
+#endif
+
 struct ip_conntrack
 {
 	/* Usage count in here is 1 for destruct timer, 1 per skb,
@@ -123,6 +130,9 @@
 #if defined(CONFIG_IP_NF_FTP) || defined(CONFIG_IP_NF_FTP_MODULE)
 		struct ip_ct_ftp ct_ftp_info;
 #endif
+#if defined(CONFIG_IP_NF_IRC) || defined(CONFIG_IP_NF_IRC_MODULE)
+		struct ip_ct_irc ct_irc_info;
+#endif
 	} help;
 
 #ifdef CONFIG_IP_NF_NAT_NEEDED
@@ -131,6 +141,9 @@
 		union {
 #if defined(CONFIG_IP_NF_FTP) || defined(CONFIG_IP_NF_FTP_MODULE)
 			struct ip_nat_ftp_info ftp_info[IP_CT_DIR_MAX];
+#endif
+#if defined(CONFIG_IP_NF_IRC) || defined(CONFIG_IP_NF_IRC_MODULE)
+			struct ip_nat_irc_info irc_info;
 #endif
 		} help;
 #if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
diff -Nru linux-2.4.0-test2/include/linux/netfilter_ipv4/ip_conntrack_irc.h linux-laforge/include/linux/netfilter_ipv4/ip_conntrack_irc.h
--- linux-2.4.0-test2/include/linux/netfilter_ipv4/ip_conntrack_irc.h	Thu Jan  1 01:00:00 1970
+++ linux-laforge/include/linux/netfilter_ipv4/ip_conntrack_irc.h	Fri Jul  7 17:41:21 2000
@@ -0,0 +1,65 @@
+/* IRC extension for IP connection tracking.
+ * (C) 2000 by Harald Welte <laforge@sunbeam.franken.de>
+ * based on RR's ip_conntrack_ftp.h
+ *
+ * $Id: ip_conntrack_irc.h,v 1.1 2000/06/20 10:19:07 laforge Exp laforge $
+ *
+ *      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.
+ *
+ *
+ */
+#ifndef _IP_CONNTRACK_IRC_H
+#define _IP_CONNTRACK_IRC_H
+
+#ifndef __KERNEL__
+#error Only in kernel.
+#endif
+
+#include <linux/netfilter_ipv4/lockhelp.h>
+
+
+struct dccproto {
+	char* match;
+	int matchlen;
+};
+
+/* Protects irc part of conntracks */
+DECLARE_LOCK_EXTERN(ip_irc_lock);
+
+#if 0
+
+enum ip_ct_ftp_type
+{
+	/* PORT command from client */
+	IP_CT_FTP_PORT = IP_CT_DIR_ORIGINAL,
+	/* PASV response from server */
+	IP_CT_FTP_PASV = IP_CT_DIR_REPLY
+};
+
+#endif
+
+/* We record seq number and length of ftp ip/port text here: all in
+   host order. */
+struct ip_ct_irc
+{
+	/* This tells NAT that this is an IRC connection */
+	int is_irc;
+	/* sequence number where address part of DCC command begins */
+	u_int32_t seq;
+	/* 0 means not found yet */
+	u_int32_t len;
+	/* Port that was to be used */
+	u_int16_t port;
+#if 0
+	/* Next valid seq position for cmd matching after newline */
+	u_int32_t seq_aft_nl[IP_CT_DIR_MAX];
+	/* 0 means seq_match_aft_nl not set */
+	int seq_aft_nl_set[IP_CT_DIR_MAX];
+#endif
+
+};
+
+#endif /* _IP_CONNTRACK_IRC_H */
diff -Nru linux-2.4.0-test2/include/linux/netfilter_ipv4/ip_nat_irc.h linux-laforge/include/linux/netfilter_ipv4/ip_nat_irc.h
--- linux-2.4.0-test2/include/linux/netfilter_ipv4/ip_nat_irc.h	Thu Jan  1 01:00:00 1970
+++ linux-laforge/include/linux/netfilter_ipv4/ip_nat_irc.h	Sat Jul  8 17:57:51 2000
@@ -0,0 +1,34 @@
+#ifndef _IP_NAT_IRC_H
+#define _IP_NAT_IRC_H
+/* IRC extension for TCP NAT alteration.
+ * (C) 2000 by Harald Welte <laforge@sunbeam.franken.de>
+ * based on RR's ip_nat_ftp.h
+ *
+ * $Id: ip_nat_irc.h,v 1.1 2000/06/20 10:22:04 laforge Exp laforge $
+ *
+ *      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.
+ *
+ *
+ */
+
+
+#ifndef __KERNEL__
+#error Only in kernel.
+#endif
+
+/* Protects ftp part of conntracks */
+DECLARE_LOCK_EXTERN(ip_irc_lock);
+
+/* We keep track of where the last SYN correction was, and the SYN
+   offsets before and after that correction.  Two of these (indexed by
+   direction). */
+struct ip_nat_irc_info
+{
+	u_int32_t syn_correction_pos;                              
+	int32_t syn_offset_before, syn_offset_after; 
+};
+
+#endif /* _IP_NAT_IRC_H */
diff -Nru linux-2.4.0-test2/net/ipv4/netfilter/Config.in linux-laforge/net/ipv4/netfilter/Config.in
--- linux-2.4.0-test2/net/ipv4/netfilter/Config.in	Mon Mar 27 20:35:56 2000
+++ linux-laforge/net/ipv4/netfilter/Config.in	Sat Jul  8 17:19:46 2000
@@ -7,6 +7,7 @@
 tristate 'Connection tracking (required for masq/NAT)' CONFIG_IP_NF_CONNTRACK
 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
 fi
 
 if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_NETLINK" = "y" ]; then
diff -Nru linux-2.4.0-test2/net/ipv4/netfilter/Makefile linux-laforge/net/ipv4/netfilter/Makefile
--- linux-2.4.0-test2/net/ipv4/netfilter/Makefile	Mon Mar 27 20:35:56 2000
+++ linux-laforge/net/ipv4/netfilter/Makefile	Sat Jul  8 17:20:45 2000
@@ -37,6 +37,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_IP_NF_IRC),y)
+O_OBJS += ip_conntrack_irc.o
+else 
+  ifeq ($(CONFIG_IP_NF_IRC),m)
+  MX_OBJS += ip_conntrack_irc.o
+  endif
+endif
+
 ifeq ($(CONFIG_IP_NF_IPTABLES),y)
 O_OBJS += ip_tables.o
 else
diff -Nru linux-2.4.0-test2/net/ipv4/netfilter/ip_conntrack_core.c linux-laforge/net/ipv4/netfilter/ip_conntrack_core.c
--- linux-2.4.0-test2/net/ipv4/netfilter/ip_conntrack_core.c	Tue Jun 20 23:32:27 2000
+++ linux-laforge/net/ipv4/netfilter/ip_conntrack_core.c	Sat Jul  8 17:06:40 2000
@@ -419,7 +419,7 @@
 static int expect_cmp(const struct ip_conntrack_expect *i,
 		      const struct ip_conntrack_tuple *tuple)
 {
-	return (tuple->src.ip == i->tuple.src.ip
+	return ((tuple->src.ip == i->tuple.src.ip || i->tuple.src.ip == 0)
 		&& tuple->dst.ip == i->tuple.dst.ip
 		&& tuple->dst.u.all == i->tuple.dst.u.all
 		&& tuple->dst.protonum == i->tuple.dst.protonum);
diff -Nru linux-2.4.0-test2/net/ipv4/netfilter/ip_conntrack_irc.c linux-laforge/net/ipv4/netfilter/ip_conntrack_irc.c
--- linux-2.4.0-test2/net/ipv4/netfilter/ip_conntrack_irc.c	Thu Jan  1 01:00:00 1970
+++ linux-laforge/net/ipv4/netfilter/ip_conntrack_irc.c	Sat Jul  8 17:36:54 2000
@@ -0,0 +1,244 @@
+/* IRC extension for IP connection tracking. 
+ * (C) 2000 by Harald Welte <laforge@sunbeam.franken.de>
+ * based on RR's ip_conntrack_ftp.c	
+ *
+ * ip_conntrack_irc.c,v 1.3 2000/07/08 15:36:33 laforge Exp
+ *
+ *      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.
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/ip.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_irc.h>
+
+#define MAX_PORTS 8
+static int ports[MAX_PORTS] = { 0, };
+static short ports_n[MAX_PORTS] = { 0, };
+static int ports_n_c = 0;
+
+#ifdef MODULE_PARM
+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
+#endif
+
+#define NUM_DCCPROTO 	5
+struct dccproto dccprotos[NUM_DCCPROTO] = {
+	{ "SEND ", 5 },
+	{ "CHAT ", 5 },
+	{ "MOVE ", 5 },
+	{ "TSEND ", 6 },
+	{ "SCHAT ", 6 }
+};
+#define MAXMATCHLEN	6
+
+DECLARE_LOCK(ip_irc_lock);
+struct module *ip_conntrack_irc = THIS_MODULE;
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+#define IP_PARTS_NATIVE(n)			\
+(unsigned int)((n)>>24)&0xFF,			\
+(unsigned int)((n)>>16)&0xFF,			\
+(unsigned int)((n)>>8)&0xFF,			\
+(unsigned int)((n)&0xFF)
+
+#define IP_PARTS(n) IP_PARTS_NATIVE(ntohl(n))
+
+int parse_dcc(char* data, char* data_end, u_int32_t* ip, u_int16_t* port, char** ad_beg_p, char** ad_end_p)
+/* tries to get the ip_addr and port out of a dcc command
+   return value: -1 on failure, 0 on success 
+	data		pointer to first byte of DCC command data
+	data_end	pointer to last byte of dcc command data
+	ip		returns parsed ip of dcc command
+	port		returns parsed port of dcc command
+	ad_beg_p	returns pointer to first byte of addr data
+	ad_end_p	returns pointer to last byte of addr data */
+{
+
+	/* at least 12: "AAAAAAAA P\1\n" */
+	while (*data++ != ' ')
+		if ( data > data_end - 12 )
+			return -1;
+
+	*ad_beg_p = data;
+	*ip = simple_strtoul(data, &data, 10);
+	
+	/* skip blanks between ip and port */
+	while (*data ==' ') 	
+		data++;
+
+
+	*port = simple_strtoul(data, &data, 10);
+	*ad_end_p = data;
+
+	return 0;
+}
+
+
+/* FIXME: This should be in userspace.  Later. */
+static int help(const struct iphdr *iph, size_t len,
+		struct ip_conntrack *ct,
+		enum ip_conntrack_info ctinfo)
+{
+	/* tcplen not negative guarenteed by ip_conntrack_tcp.c */
+	struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
+	const char *data = (const char *)tcph + tcph->doff * 4;
+	const char *_data = data;
+	char* data_limit;
+	u_int32_t tcplen = len - iph->ihl * 4;
+	u_int32_t datalen = tcplen - tcph->doff * 4;
+	int dir = CTINFO2DIR(ctinfo);
+	struct ip_conntrack_tuple t;
+	
+	u_int32_t dcc_ip;
+	u_int16_t dcc_port;
+	int i;
+	char *addr_beg_p, *addr_end_p;
+
+	struct ip_ct_irc *info = &ct->help.ct_irc_info;
+
+	/* Can't track connections formed before we registered */
+	if (!info)
+		return NF_ACCEPT;
+
+	/* If packet is coming from IRC server */
+	if (dir == IP_CT_DIR_REPLY)
+		return NF_ACCEPT;
+
+	/* 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("irc: Conntrackinfo = %u\n", ctinfo);
+		return NF_ACCEPT;
+	}
+
+	/* Not whole TCP header? */
+	if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
+		DEBUGP("irc: tcplen = %u\n", (unsigned)tcplen);
+		return NF_ACCEPT;
+	}
+
+	/* 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("irc_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
+		       tcph, tcplen, IP_PARTS(iph->saddr),
+		       IP_PARTS(iph->daddr));
+		return NF_ACCEPT;
+	}
+
+	data_limit = data + datalen;
+	while (data < (data_limit - ( 22 + MAXMATCHLEN )))
+	{
+		if (memcmp(data, "\1DCC ", 5))
+		{
+			data++;
+			continue;
+		}
+		
+		data += 5;
+
+		DEBUGP("ip_conntrack_irc_help: DCC found in connection %u.%u.%u.%u:%u %u.%u.%u.%u:%u\n", IP_PARTS(iph->saddr), tcph->source, IP_PARTS(iph->daddr), tcph->dest);
+		for (i = 0; i <= NUM_DCCPROTO; i++)
+		{
+			if (memcmp(data, dccprotos[i].match, dccprotos[i].matchlen) == 0)
+			{
+				DEBUGP("ip_conntrack_irc_help: DCC %s detected\n", dccprotos[i].match);
+				data += dccprotos[i].matchlen;
+				if (!parse_dcc(data, data_limit, &dcc_ip, &dcc_port, &addr_beg_p, &addr_end_p)) 
+				{
+					DEBUGP("ip_conntrack_irc_help: DCC request with bound addr %u.%u.%u.%u:%u found\n", IP_PARTS_NATIVE(dcc_ip), dcc_port);
+
+					LOCK_BH(&ip_irc_lock);
+
+					/* save position of address in dcc string, neccessary for NAT */
+					info->is_irc = 1;
+					info->seq = tcph->seq + (addr_beg_p - _data);
+					info->len = (addr_end_p - addr_beg_p);
+					info->port = dcc_port;
+					DEBUGP("ip_conntrack_irc_help: wrote info: seq=%u (ofs=%u), len=%d\n", info->seq, (addr_end_p - _data), info->len);
+
+					memset(&t, 0, sizeof(t));
+					t.src.ip = 0;
+					t.src.u.tcp.port = 0;
+					t.dst.ip = htonl(dcc_ip);
+					t.dst.u.tcp.port = htons(dcc_port);
+					t.dst.protonum = IPPROTO_TCP;
+
+					DEBUGP("ip_conntrack_irc_help: expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n", IP_PARTS(t.src.ip), ntohs(t.src.u.tcp.port), IP_PARTS(t.dst.ip), ntohs(t.dst.u.tcp.port));
+					ip_conntrack_expect_related(ct, &t);
+					UNLOCK_BH(&ip_irc_lock);
+
+					return NF_ACCEPT;
+				}
+			}
+		}
+	}
+	return NF_ACCEPT;
+}
+
+/* Returns TRUE if it wants to help this connection (tuple is the
+   tuple of REPLY packets from server). */
+static int irc_will_help(const struct ip_conntrack_tuple *rtuple)
+{
+	if (rtuple->dst.protonum == IPPROTO_TCP)
+	{
+		int i;
+
+		for (i = 0; i < ports_n_c; i++)
+		{
+			if (rtuple->src.u.tcp.port == ports_n[i])
+				return 1;
+		}
+	}
+	return 0;
+}
+
+static struct ip_conntrack_helper irc = { { NULL, NULL },
+					  irc_will_help,
+					  help };
+
+static int __init init(void)
+{
+	int i;
+
+	/* If no port given, default to standard irc port */
+	if (ports[0] == 0)
+		ports[0] = 6667;
+
+	for (i = 0; i < MAX_PORTS; i++)
+	{
+		if (ports[i])
+		{
+			DEBUGP("ip_conntrack_irc: port #%d: %d\n", i, ports[i]);
+			ports_n[i] = htons(ports[i]);
+			ports_n_c++;
+		}
+	}
+
+	return ip_conntrack_helper_register(&irc);
+}
+
+static void __exit fini(void)
+{
+	DEBUGP("ip_conntrack_irc: unregistering\n");
+	ip_conntrack_helper_unregister(&irc);
+}
+
+module_init(init);
+module_exit(fini);
diff -urN --exclude DocBook --exclude config --exclude System.map --exclude version.h --exclude irc.h --exclude *.rej --exclude *.orig --exclude *~ --exclude *.bak --exclude *.o --exclude=.* --exclude=*.a --exclude=bzImage --exclude=autoconf.h --exclude=patch-* --exclude *.s --exclude *.S --exclude compile.h --exclude IPV4_MODULES linux-virgin/Documentation/Configure.help linux-hacked/Documentation/Configure.help
--- linux-virgin/Documentation/Configure.help	Tue Jun 27 12:39:26 2000
+++ linux-laforge/Documentation/Configure.help	Tue Jun 27 12:39:49 2000
@@ -1820,6 +1820,21 @@
   If you want to compile it as a module, say M here and read
   Documentation/modules.txt.  If unsure, say `Y'.
 
+IRC Send/Chat support
+CONFIG_IP_NF_IRC
+  There is a commonly-used extension to IRC called
+  Direct Client-to-Client Protocol (DCC). This enabled users to send
+  files to each other, and also chat to each other without the need
+  of a server. DCC Sending is used anywhere you send files over IRC,
+  and DCC Chat is most commonly used by Eggdrop bots. If you are
+  using NAT, this extension will enable you to send files and initiate
+  chats. Note that you can still get files and have others initiate
+  chats without this extension, and that everything else in IRC will
+  work fine.
+
+  If you want to compile it as a module, say 'M' here and read
+  Documentation/modules.txt.  If unsure, say 'Y'.
+
 IP: user space queueing via NETLINK (EXPERIMENTAL)
 CONFIG_IP_NF_QUEUE
   Netfilter has the ability to queue packets to user space: the