- struct iphdr *iph = (*pskb)->nh.iph;
- struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
- unsigned int datalen;
- int dir;
- struct ip_ct_irc_expect *ct_irc_info;
-
- 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. */
- dir = CTINFO2DIR(ctinfo);
- if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
- || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
- DEBUGP("nat_irc: Not touching dir %s at hook %s\n",
- dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
- hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
- : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
- : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
- return NF_ACCEPT;
- }
- DEBUGP("got beyond not touching\n");
-
- datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
- LOCK_BH(&ip_irc_lock);
- /* Check whether 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 {
- /* 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);
-
- return NF_ACCEPT;