--- zzzz-none-000/linux-2.4.17/net/ipv4/netfilter/ip_nat_irc.c 2001-12-21 17:42:05.000000000 +0000 +++ sangam-fb-322/linux-2.4.17/net/ipv4/netfilter/ip_nat_irc.c 2004-11-24 13:22:08.000000000 +0000 @@ -51,42 +51,29 @@ /* FIXME: Time out? --RR */ -static int +static unsigned int irc_nat_expected(struct sk_buff **pskb, unsigned int hooknum, struct ip_conntrack *ct, - struct ip_nat_info *info, - struct ip_conntrack *master, - struct ip_nat_info *masterinfo, unsigned int *verdict) + struct ip_nat_info *info) { struct ip_nat_multi_range mr; u_int32_t newdstip, newsrcip, newip; - struct ip_ct_irc *ircinfo; + + struct ip_conntrack *master = master_ct(ct); IP_NF_ASSERT(info); IP_NF_ASSERT(master); - IP_NF_ASSERT(masterinfo); IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum)))); DEBUGP("nat_expected: We have a connection!\n"); - /* Master must be an irc connection */ - ircinfo = &master->help.ct_irc_info; - LOCK_BH(&ip_irc_lock); - if (ircinfo->is_irc != IP_CONNTR_IRC) { - UNLOCK_BH(&ip_irc_lock); - DEBUGP("nat_expected: master not irc\n"); - return 0; - } - newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; DEBUGP("nat_expected: DCC cmd. %u.%u.%u.%u->%u.%u.%u.%u\n", NIPQUAD(newsrcip), NIPQUAD(newdstip)); - UNLOCK_BH(&ip_irc_lock); - if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) newip = newsrcip; else @@ -99,31 +86,31 @@ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS; mr.range[0].min_ip = mr.range[0].max_ip = newip; - *verdict = ip_nat_setup_info(ct, &mr, hooknum); - - return 1; + return ip_nat_setup_info(ct, &mr, hooknum); } -static int irc_data_fixup(const struct ip_ct_irc *ct_irc_info, +static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info, struct ip_conntrack *ct, - unsigned int datalen, struct sk_buff **pskb, - enum ip_conntrack_info ctinfo) + enum ip_conntrack_info ctinfo, + struct ip_conntrack_expect *expect) { u_int32_t newip; struct ip_conntrack_tuple t; struct iphdr *iph = (*pskb)->nh.iph; struct tcphdr *tcph = (void *) iph + iph->ihl * 4; int port; - + /* "4294967296 65635 " */ char buffer[18]; MUST_BE_LOCKED(&ip_irc_lock); - DEBUGP("IRC_NAT: info (seq %u + %u) packet(seq %u + %u)\n", - ct_irc_info->seq, ct_irc_info->len, - ntohl(tcph->seq), datalen); + DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n", + expect->seq, ct_irc_info->len, + ntohl(tcph->seq)); + + memset(&t, 0, sizeof(t)); newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; @@ -133,13 +120,11 @@ only set in ip_conntrack_irc, with ip_irc_lock held writable */ - t = ct->expected.tuple; + t = expect->tuple; t.dst.ip = newip; for (port = ct_irc_info->port; port != 0; port++) { t.dst.u.tcp.port = htons(port); - if (ip_conntrack_expect_related(ct, &t, - &ct->expected.mask, - NULL) == 0) { + if (ip_conntrack_change_expect(expect, &t) == 0) { DEBUGP("using port %d", port); break; } @@ -166,26 +151,28 @@ buffer, NIPQUAD(newip), port); return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, - ct_irc_info->seq - ntohl(tcph->seq), + expect->seq - ntohl(tcph->seq), ct_irc_info->len, buffer, strlen(buffer)); } static unsigned int help(struct ip_conntrack *ct, + struct ip_conntrack_expect *exp, struct ip_nat_info *info, enum ip_conntrack_info ctinfo, - unsigned int hooknum, struct sk_buff **pskb) + unsigned int hooknum, + struct sk_buff **pskb) { struct iphdr *iph = (*pskb)->nh.iph; struct tcphdr *tcph = (void *) iph + iph->ihl * 4; unsigned int datalen; int dir; - int score; - struct ip_ct_irc *ct_irc_info = &ct->help.ct_irc_info; + struct ip_ct_irc_expect *ct_irc_info; - /* Delete SACK_OK on initial TCP SYNs. */ - if (tcph->syn && !tcph->ack) - ip_nat_delete_sack(*pskb, tcph); + if (!exp) + DEBUGP("ip_nat_irc: no exp!!"); + + ct_irc_info = &exp->help.exp_irc_info; /* Only mangle things once: original direction in POST_ROUTING and reply direction on PRE_ROUTING. */ @@ -202,55 +189,35 @@ DEBUGP("got beyond not touching\n"); datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4; - score = 0; LOCK_BH(&ip_irc_lock); - if (ct_irc_info->len) { - DEBUGP("got beyond ct_irc_info->len\n"); - - /* If it's in the right range... */ - score += between(ct_irc_info->seq, ntohl(tcph->seq), - ntohl(tcph->seq) + datalen); - score += between(ct_irc_info->seq + ct_irc_info->len, - ntohl(tcph->seq), - ntohl(tcph->seq) + datalen); - if (score == 1) { - /* Half a match? This means a partial retransmisison. - It's a cracker being funky. */ - if (net_ratelimit()) { - printk - ("IRC_NAT: partial packet %u/%u in %u/%u\n", - ct_irc_info->seq, ct_irc_info->len, - ntohl(tcph->seq), - ntohl(tcph->seq) + datalen); - } + /* Check wether the whole IP/address pattern is carried in the payload */ + if (between(exp->seq + ct_irc_info->len, + ntohl(tcph->seq), + ntohl(tcph->seq) + datalen)) { + if (!irc_data_fixup(ct_irc_info, ct, pskb, ctinfo, exp)) { UNLOCK_BH(&ip_irc_lock); return NF_DROP; - } else if (score == 2) { - DEBUGP("IRC_NAT: score=2, calling fixup\n"); - if (!irc_data_fixup(ct_irc_info, ct, datalen, - pskb, ctinfo)) { - UNLOCK_BH(&ip_irc_lock); - return NF_DROP; - } - /* skb may have been reallocated */ - iph = (*pskb)->nh.iph; - tcph = (void *) iph + iph->ihl * 4; } + } else { + /* Half a match? This means a partial retransmisison. + It's a cracker being funky. */ + if (net_ratelimit()) { + printk + ("IRC_NAT: partial packet %u/%u in %u/%u\n", + exp->seq, ct_irc_info->len, + ntohl(tcph->seq), + ntohl(tcph->seq) + datalen); + } + UNLOCK_BH(&ip_irc_lock); + return NF_DROP; } - UNLOCK_BH(&ip_irc_lock); - ip_nat_seq_adjust(*pskb, ct, ctinfo); - return NF_ACCEPT; } static struct ip_nat_helper ip_nat_irc_helpers[MAX_PORTS]; -static char ip_nih_names[MAX_PORTS][6]; - -static struct ip_nat_expect irc_expect - = { {NULL, NULL}, irc_nat_expected }; - +static char irc_names[MAX_PORTS][10]; /* This function is intentionally _NOT_ defined as __exit, because * it is needed by init() */ @@ -262,52 +229,54 @@ DEBUGP("ip_nat_irc: unregistering helper for port %d\n", ports[i]); ip_nat_helper_unregister(&ip_nat_irc_helpers[i]); - } - ip_nat_expect_unregister(&irc_expect); + } } + static int __init init(void) { - int ret; + int ret = 0; int i; struct ip_nat_helper *hlpr; char *tmpname; - ret = ip_nat_expect_register(&irc_expect); - if (ret == 0) { - - if (ports[0] == 0) { - ports[0] = 6667; - } + if (ports[0] == 0) { + ports[0] = IRC_PORT; + } - for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) { - hlpr = &ip_nat_irc_helpers[i]; - memset(hlpr, 0, - sizeof(struct ip_nat_helper)); - - hlpr->tuple.dst.protonum = IPPROTO_TCP; - hlpr->tuple.src.u.tcp.port = htons(ports[i]); - hlpr->mask.src.u.tcp.port = 0xFFFF; - hlpr->mask.dst.protonum = 0xFFFF; - hlpr->help = help; - - tmpname = &ip_nih_names[i][0]; - sprintf(tmpname, "irc%2.2d", i); - - hlpr->name = tmpname; - DEBUGP - ("ip_nat_irc: Trying to register helper for port %d: name %s\n", - ports[i], hlpr->name); - ret = ip_nat_helper_register(hlpr); - - if (ret) { - printk - ("ip_nat_irc: error registering helper for port %d\n", - ports[i]); - fini(); - return 1; - } - ports_c++; + for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) { + hlpr = &ip_nat_irc_helpers[i]; + memset(hlpr, 0, + sizeof(struct ip_nat_helper)); + + hlpr->tuple.dst.protonum = IPPROTO_TCP; + hlpr->tuple.src.u.tcp.port = htons(ports[i]); + hlpr->mask.src.u.tcp.port = 0xFFFF; + hlpr->mask.dst.protonum = 0xFFFF; + hlpr->help = help; + hlpr->flags = 0; + hlpr->me = THIS_MODULE; + hlpr->expect = irc_nat_expected; + + tmpname = &irc_names[i][0]; + if (ports[i] == IRC_PORT) + sprintf(tmpname, "irc"); + else + sprintf(tmpname, "irc-%d", i); + hlpr->name = tmpname; + + DEBUGP + ("ip_nat_irc: Trying to register helper for port %d: name %s\n", + ports[i], hlpr->name); + ret = ip_nat_helper_register(hlpr); + + if (ret) { + printk + ("ip_nat_irc: error registering helper for port %d\n", + ports[i]); + fini(); + return 1; } + ports_c++; } return ret; }