--- zzzz-none-000/linux-2.4.17/net/ipv4/netfilter/ip_conntrack_irc.c 2001-12-21 17:42:05.000000000 +0000 +++ sangam-fb-322/linux-2.4.17/net/ipv4/netfilter/ip_conntrack_irc.c 2004-11-24 13:22:08.000000000 +0000 @@ -11,16 +11,21 @@ ** * Module load syntax: * insmod ip_conntrack_irc.o ports=port1,port2,...port + * max_dcc_channels=n dcc_timeout=secs * * please give the ports of all IRC servers You wish to connect to. - * If You don't specify ports, the default will be port 6667 + * If You don't specify ports, the default will be port 6667. + * With max_dcc_channels you can define the maximum number of not + * yet answered DCC channels per IRC session (default 8). + * With dcc_timeout you can specify how long the system waits for + * an expected DCC channel (default 300 seconds). * */ +#include #include #include #include -#include #include #include @@ -29,7 +34,9 @@ #define MAX_PORTS 8 static int ports[MAX_PORTS]; -static int ports_n_c = 0; +static int ports_c = 0; +static int max_dcc_channels = 8; +static unsigned int dcc_timeout = 300; MODULE_AUTHOR("Harald Welte "); MODULE_DESCRIPTION("IRC (DCC) connection tracking module"); @@ -37,6 +44,10 @@ #ifdef MODULE_PARM MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i"); MODULE_PARM_DESC(ports, "port numbers of IRC servers"); +MODULE_PARM(max_dcc_channels, "i"); +MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session"); +MODULE_PARM(dcc_timeout, "i"); +MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels"); #endif #define NUM_DCCPROTO 5 @@ -100,26 +111,18 @@ 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; + u_int32_t datalen = len - (iph->ihl + tcph->doff) * 4; int dir = CTINFO2DIR(ctinfo); - struct ip_conntrack_tuple t, mask; + struct ip_conntrack_expect expect, *exp = &expect; + struct ip_ct_irc_expect *exp_irc_info = &exp->help.exp_irc_info; 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; - - memset(&mask, 0, sizeof(struct ip_conntrack_tuple)); - mask.dst.u.tcp.port = 0xFFFF; - mask.dst.protonum = 0xFFFF; DEBUGP("entered\n"); - /* 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) @@ -132,22 +135,6 @@ return NF_ACCEPT; } - /* Not whole TCP header? */ - if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) { - DEBUGP("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("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n", - tcph, tcplen, NIPQUAD(iph->saddr), - NIPQUAD(iph->daddr)); - return NF_ACCEPT; - } - data_limit = (char *) data + datalen; while (data < (data_limit - (22 + MAXMATCHLEN))) { if (memcmp(data, "\1DCC ", 5)) { @@ -189,33 +176,37 @@ continue; } + + memset(&expect, 0, sizeof(expect)); LOCK_BH(&ip_irc_lock); /* save position of address in dcc string, * neccessary for NAT */ - info->is_irc = IP_CONNTR_IRC; DEBUGP("tcph->seq = %u\n", tcph->seq); - info->seq = ntohl(tcph->seq) + (addr_beg_p - _data); - info->len = (addr_end_p - addr_beg_p); - info->port = dcc_port; + exp->seq = ntohl(tcph->seq) + (addr_beg_p - _data); + exp_irc_info->len = (addr_end_p - addr_beg_p); + exp_irc_info->port = dcc_port; DEBUGP("wrote info seq=%u (ofs=%u), len=%d\n", - info->seq, (addr_end_p - _data), info->len); + exp->seq, (addr_end_p - _data), exp_irc_info->len); + + exp->tuple = ((struct ip_conntrack_tuple) + { { 0, { 0 } }, + { htonl(dcc_ip), { htons(dcc_port) }, + IPPROTO_TCP }}); + exp->mask = ((struct ip_conntrack_tuple) + { { 0, { 0 } }, + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }}); - 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(info->port); - t.dst.protonum = IPPROTO_TCP; + exp->expectfn = NULL; DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n", - NIPQUAD(t.src.ip), - ntohs(t.src.u.tcp.port), - NIPQUAD(t.dst.ip), - ntohs(t.dst.u.tcp.port)); + NIPQUAD(exp->tuple.src.ip), + ntohs(exp->tuple.src.u.tcp.port), + NIPQUAD(exp->tuple.dst.ip), + ntohs(exp->tuple.dst.u.tcp.port)); - ip_conntrack_expect_related(ct, &t, &mask, NULL); + ip_conntrack_expect_related(ct, &expect); UNLOCK_BH(&ip_irc_lock); return NF_ACCEPT; @@ -226,29 +217,53 @@ } static struct ip_conntrack_helper irc_helpers[MAX_PORTS]; +static char irc_names[MAX_PORTS][10]; static void fini(void); static int __init init(void) { int i, ret; + struct ip_conntrack_helper *hlpr; + char *tmpname; + if (max_dcc_channels < 1) { + printk("ip_conntrack_irc: max_dcc_channels must be a positive integer\n"); + return -EBUSY; + } + if (dcc_timeout < 0) { + printk("ip_conntrack_irc: dcc_timeout must be a positive integer\n"); + return -EBUSY; + } + /* If no port given, default to standard irc port */ if (ports[0] == 0) - ports[0] = 6667; + ports[0] = IRC_PORT; for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { - memset(&irc_helpers[i], 0, + hlpr = &irc_helpers[i]; + memset(hlpr, 0, sizeof(struct ip_conntrack_helper)); - irc_helpers[i].tuple.src.u.tcp.port = htons(ports[i]); - irc_helpers[i].tuple.dst.protonum = IPPROTO_TCP; - irc_helpers[i].mask.src.u.tcp.port = 0xFFFF; - irc_helpers[i].mask.dst.protonum = 0xFFFF; - irc_helpers[i].help = help; + hlpr->tuple.src.u.tcp.port = htons(ports[i]); + hlpr->tuple.dst.protonum = IPPROTO_TCP; + hlpr->mask.src.u.tcp.port = 0xFFFF; + hlpr->mask.dst.protonum = 0xFFFF; + hlpr->max_expected = max_dcc_channels; + hlpr->timeout = dcc_timeout; + hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT; + hlpr->me = ip_conntrack_irc; + hlpr->help = help; + + tmpname = &irc_names[i][0]; + if (ports[i] == IRC_PORT) + sprintf(tmpname, "irc"); + else + sprintf(tmpname, "irc-%d", i); + hlpr->name = tmpname; DEBUGP("port #%d: %d\n", i, ports[i]); - ret = ip_conntrack_helper_register(&irc_helpers[i]); + ret = ip_conntrack_helper_register(hlpr); if (ret) { printk("ip_conntrack_irc: ERROR registering port %d\n", @@ -256,7 +271,7 @@ fini(); return -EBUSY; } - ports_n_c++; + ports_c++; } return 0; } @@ -266,12 +281,16 @@ static void fini(void) { int i; - for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { + for (i = 0; i < ports_c; i++) { DEBUGP("unregistering port %d\n", ports[i]); ip_conntrack_helper_unregister(&irc_helpers[i]); } } +#ifdef CONFIG_IP_NF_NAT_NEEDED +EXPORT_SYMBOL(ip_irc_lock); +#endif + module_init(init); module_exit(fini);