X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv4%2Fnetfilter%2Fip_conntrack_irc.c;h=33cc7348b6eee161c8c61a1d658070d42a977626;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=d007bc9950cf0a667d8d1413db15d19adc290134;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c index d007bc995..33cc7348b 100644 --- a/net/ipv4/netfilter/ip_conntrack_irc.c +++ b/net/ipv4/netfilter/ip_conntrack_irc.c @@ -43,10 +43,17 @@ static unsigned int dcc_timeout = 300; static char irc_buffer[65536]; static DECLARE_LOCK(irc_buffer_lock); +unsigned int (*ip_nat_irc_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + unsigned int matchoff, + unsigned int matchlen, + struct ip_conntrack_expect *exp); +EXPORT_SYMBOL_GPL(ip_nat_irc_hook); + MODULE_AUTHOR("Harald Welte "); MODULE_DESCRIPTION("IRC (DCC) connection tracking helper"); MODULE_LICENSE("GPL"); -module_param_array(ports, int, ports_c, 0400); +module_param_array(ports, int, &ports_c, 0400); MODULE_PARM_DESC(ports, "port numbers of IRC servers"); module_param(max_dcc_channels, int, 0400); MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session"); @@ -56,8 +63,6 @@ MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels"); static char *dccprotos[] = { "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT " }; #define MINMATCHLEN 5 -struct module *ip_conntrack_irc = THIS_MODULE; - #if 0 #define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s:" format, \ __FILE__, __FUNCTION__ , ## args) @@ -65,8 +70,8 @@ struct module *ip_conntrack_irc = THIS_MODULE; #define DEBUGP(format, args...) #endif -int parse_dcc(char *data, char *data_end, u_int32_t * ip, u_int16_t * port, - char **ad_beg_p, char **ad_end_p) +static 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 @@ -98,7 +103,7 @@ int parse_dcc(char *data, char *data_end, u_int32_t * ip, u_int16_t * port, return 0; } -static int help(struct sk_buff *skb, +static int help(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) { unsigned int dataoff; @@ -106,11 +111,10 @@ static int help(struct sk_buff *skb, char *data, *data_limit, *ib_ptr; int dir = CTINFO2DIR(ctinfo); struct ip_conntrack_expect *exp; - struct ip_ct_irc_expect *exp_irc_info = NULL; - + u32 seq; u_int32_t dcc_ip; u_int16_t dcc_port; - int i; + int i, ret = NF_ACCEPT; char *addr_beg_p, *addr_end_p; DEBUGP("entered\n"); @@ -127,23 +131,23 @@ static int help(struct sk_buff *skb, } /* Not a full tcp header? */ - th = skb_header_pointer(skb, skb->nh.iph->ihl*4, + th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4, sizeof(_tcph), &_tcph); if (th == NULL) return NF_ACCEPT; /* No data? */ - dataoff = skb->nh.iph->ihl*4 + th->doff*4; - if (dataoff >= skb->len) + dataoff = (*pskb)->nh.iph->ihl*4 + th->doff*4; + if (dataoff >= (*pskb)->len) return NF_ACCEPT; LOCK_BH(&irc_buffer_lock); - ib_ptr = skb_header_pointer(skb, dataoff, - skb->len - dataoff, irc_buffer); + ib_ptr = skb_header_pointer(*pskb, dataoff, + (*pskb)->len - dataoff, irc_buffer); BUG_ON(ib_ptr == NULL); data = ib_ptr; - data_limit = ib_ptr + skb->len - dataoff; + data_limit = ib_ptr + (*pskb)->len - dataoff; /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24 * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */ @@ -195,45 +199,46 @@ static int help(struct sk_buff *skb, } exp = ip_conntrack_expect_alloc(); - if (exp == NULL) + if (exp == NULL) { + ret = NF_DROP; goto out; - - exp_irc_info = &exp->help.exp_irc_info; + } /* save position of address in dcc string, * necessary for NAT */ DEBUGP("tcph->seq = %u\n", th->seq); - exp->seq = ntohl(th->seq) + (addr_beg_p - ib_ptr); - 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", - exp->seq, (addr_end_p - _data), exp_irc_info->len); + seq = ntohl(th->seq) + (addr_beg_p - ib_ptr); + /* We refer to the reverse direction ("!dir") + * tuples here, because we're expecting + * something in the other * direction. + * Doesn't matter unless NAT is happening. */ exp->tuple = ((struct ip_conntrack_tuple) { { 0, { 0 } }, - { ct->tuplehash[dir].tuple.src.ip, { .tcp = { htons(dcc_port) } }, + { ct->tuplehash[!dir].tuple.dst.ip, + { .tcp = { htons(dcc_port) } }, IPPROTO_TCP }}); exp->mask = ((struct ip_conntrack_tuple) { { 0, { 0 } }, - { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }}); - + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFF }}); exp->expectfn = NULL; - - DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n", - 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(exp, ct); - + exp->master = ct; + if (ip_nat_irc_hook) + ret = ip_nat_irc_hook(pskb, ctinfo, + addr_beg_p - ib_ptr, + addr_end_p - addr_beg_p, + exp); + else if (ip_conntrack_expect_related(exp) != 0) { + ip_conntrack_expect_free(exp); + ret = NF_DROP; + } goto out; } /* for .. NUM_DCCPROTO */ } /* while data < ... */ out: UNLOCK_BH(&irc_buffer_lock); - return NF_ACCEPT; + return ret; } static struct ip_conntrack_helper irc_helpers[MAX_PORTS]; @@ -265,11 +270,10 @@ static int __init init(void) 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->mask.dst.protonum = 0xFF; hlpr->max_expected = max_dcc_channels; hlpr->timeout = dcc_timeout; - hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT; - hlpr->me = ip_conntrack_irc; + hlpr->me = THIS_MODULE; hlpr->help = help; tmpname = &irc_names[i][0]; @@ -305,7 +309,5 @@ static void fini(void) } } -PROVIDES_CONNTRACK(irc); - module_init(init); module_exit(fini);