1diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux.mppc/net/ipv4/netfilter/ip_conntrack_egg.c linux/net/ipv4/netfilter/ip_conntrack_egg.c
2--- linux.mppc/net/ipv4/netfilter/ip_conntrack_egg.c	Thu Jan  1 01:00:00 1970
3+++ linux/net/ipv4/netfilter/ip_conntrack_egg.c	Mon Mar 25 16:32:21 2002
4@@ -0,0 +1,237 @@
5+/* Eggdrop extension for IP connection tracking, Version 0.0.5
6+ * based on ip_conntrack_irc.c	
7+ *
8+ *      This module only supports the share userfile-send command,
9+ *      used by eggdrops to share it's userfile.
10+ *
11+ *      There are no support for NAT at the moment.
12+ *
13+ *      This program is free software; you can redistribute it and/or
14+ *      modify it under the terms of the GNU General Public License
15+ *      as published by the Free Software Foundation; either version
16+ *      2 of the License, or (at your option) any later version.
17+ *
18+ *	Module load syntax:
19+ *	
20+ * 	please give the ports of all Eggdrops You have running
21+ *      on your system, the default port is 3333.
22+ *
23+ *      2001-04-19: Security update. IP addresses are now compared
24+ *                  to prevent unauthorized "related" access.
25+ *
26+ *      2002-03-25: Harald Welte <laforge@gnumonks.org>:
27+ *      	    Port to netfilter 'newnat' API.
28+ */
29+
30+#include <linux/module.h>
31+#include <linux/netfilter.h>
32+#include <linux/ip.h>
33+#include <net/checksum.h>
34+#include <net/tcp.h>
35+
36+#include <linux/netfilter_ipv4/lockhelp.h>
37+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
38+
39+#define MAX_PORTS 8
40+static int ports[MAX_PORTS];
41+static int ports_c = 0;
42+static unsigned int egg_timeout = 300;
43+
44+MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
45+MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
46+MODULE_LICENSE("GPL");
47+#ifdef MODULE_PARM
48+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
49+MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
50+#endif
51+
52+DECLARE_LOCK(ip_egg_lock);
53+struct module *ip_conntrack_egg = THIS_MODULE;
54+
55+#if 0
56+#define DEBUGP printk
57+#else
58+#define DEBUGP(format, args...)
59+#endif
60+
61+int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
62+/* tries to get the ip_addr and port out of a eggdrop command
63+   return value: -1 on failure, 0 on success 
64+   data		pointer to first byte of DCC command data
65+   data_end	pointer to last byte of dcc command data
66+   ip		returns parsed ip of dcc command
67+   port		returns parsed port of dcc command */
68+{
69+	if (data > data_end)
70+		return -1;
71+	
72+	*ip = simple_strtoul(data, &data, 10);
73+
74+	/* skip blanks between ip and port */
75+	while (*data == ' ' && data < data_end)
76+		data++;
77+
78+	*port = simple_strtoul(data, &data, 10);
79+	return 0;
80+}
81+
82+
83+static int help(const struct iphdr *iph, size_t len,
84+		struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
85+{
86+	/* tcplen not negative guarenteed by ip_conntrack_tcp.c */
87+	struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
88+	char *data = (char *) tcph + tcph->doff * 4;
89+	char *data_limit;
90+	u_int32_t tcplen = len - iph->ihl * 4;
91+	u_int32_t datalen = tcplen - tcph->doff * 4;
92+	int dir = CTINFO2DIR(ctinfo);
93+	int bytes_scanned = 0;
94+	struct ip_conntrack_expect exp;
95+
96+	u_int32_t egg_ip;
97+	u_int16_t egg_port;
98+
99+	DEBUGP("entered\n");
100+
101+	/* If packet is coming from IRC server */
102+	if (dir != IP_CT_DIR_REPLY)
103+		return NF_ACCEPT;
104+
105+	/* Until there's been traffic both ways, don't look in packets. */
106+	if (ctinfo != IP_CT_ESTABLISHED
107+	    && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
108+		DEBUGP("Conntrackinfo = %u\n", ctinfo);
109+		return NF_ACCEPT;
110+	}
111+
112+	/* Not whole TCP header? */
113+	if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
114+		DEBUGP("tcplen = %u\n", (unsigned) tcplen);
115+		return NF_ACCEPT;
116+	}
117+
118+	/* Checksum invalid?  Ignore. */
119+	
120+	if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
121+			 csum_partial((char *) tcph, tcplen, 0))) {
122+		DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
123+			tcph, tcplen, NIPQUAD(iph->saddr),
124+			NIPQUAD(iph->daddr));
125+		return NF_ACCEPT;
126+	}
127+
128+	data_limit = (char *) data + datalen;
129+	while (datalen > 5 && bytes_scanned < 128) {
130+		if (memcmp(data, "s us ", 5)) {
131+			data++;
132+			datalen--;
133+			bytes_scanned++;
134+			continue;
135+		}
136+
137+		data += 5;
138+
139+		DEBUGP("Userfile-share found in connection "
140+			"%u.%u.%u.%u -> %u.%u.%u.%u\n",
141+			NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
142+
143+		if (parse_command((char *) data, data_limit, &egg_ip,
144+				  &egg_port)) {
145+			DEBUGP("no data in userfile-share pkt\n");
146+			return NF_ACCEPT;
147+		}
148+
149+		memset(&exp, 0, sizeof(exp));
150+
151+		if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
152+			if (net_ratelimit())
153+				printk("Forged Eggdrop command from "
154+				       "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
155+				       NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
156+				       HIPQUAD(egg_ip), egg_port);
157+			return NF_ACCEPT;
158+		}
159+
160+		exp.tuple.src.ip = iph->daddr;
161+		exp.tuple.src.u.tcp.port = 0;
162+		exp.tuple.dst.ip = htonl(egg_ip);
163+		exp.tuple.dst.u.tcp.port = htons(egg_port);
164+		exp.tuple.dst.protonum = IPPROTO_TCP;
165+
166+		exp.mask.dst.u.tcp.port = 0xffff;
167+		exp.mask.dst.protonum = 0xffff;
168+
169+		DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
170+			NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
171+			NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
172+
173+		ip_conntrack_expect_related(ct, &exp);
174+		break;
175+	}
176+	return NF_ACCEPT;
177+}
178+
179+static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
180+static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
181+
182+static void deregister_helpers(void) {
183+	int i;
184+	
185+	for (i = 0; i < ports_c; i++) {
186+		DEBUGP("unregistering helper for port %d\n", ports[i]);
187+		ip_conntrack_helper_unregister(&egg_helpers[i]);
188+	}
189+}
190+
191+static int __init init(void)
192+{
193+	int i, ret;
194+	char *tmpname;
195+
196+	/* If no port given, default to standard eggdrop port */
197+	if (ports[0] == 0)
198+		ports[0] = 3333;
199+
200+	for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
201+		memset(&egg_helpers[i], 0,
202+		       sizeof(struct ip_conntrack_helper));
203+		egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
204+		egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
205+		egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
206+		egg_helpers[i].mask.dst.protonum = 0xFFFF;
207+		egg_helpers[i].max_expected = 1;
208+		egg_helpers[i].timeout = egg_timeout;
209+		egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
210+		egg_helpers[i].me = THIS_MODULE;
211+		egg_helpers[i].help = help;
212+
213+		tmpname = &egg_names[i][0];
214+		if (ports[i] == 3333)
215+			sprintf(tmpname, "eggdrop");
216+		else
217+			sprintf(tmpname, "eggdrop-%d", ports[i]);
218+		egg_helpers[i].name = tmpname;
219+
220+		DEBUGP("port #%d: %d\n", i, ports[i]);
221+
222+		ret = ip_conntrack_helper_register(&egg_helpers[i]);
223+
224+		if (ret) {
225+			printk("ip_conntrack_egg: ERROR registering helper "
226+				"for port %d\n", ports[i]);
227+			deregister_helpers();
228+			return 1;
229+		}
230+		ports_c++;
231+	}
232+	return 0;
233+}
234+
235+static void __exit fini(void)
236+{
237+	deregister_helpers();
238+}
239+
240+module_init(init);
241+module_exit(fini);
242