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