static unsigned int ip_nat_adjust(unsigned int hooknum, struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; ct = ip_conntrack_get(*pskb, &ctinfo); if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) { DEBUGP("ip_nat_standalone: adjusting sequence number\n"); if (!ip_nat_seq_adjust(pskb, ct, ctinfo)) return NF_DROP; } return NF_ACCEPT; }
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) { struct iphdr *iph = (*pskb)->nh.iph; struct tcphdr *tcph = (void *)iph + iph->ihl*4; unsigned int datalen; int dir; int score; struct ip_ct_sc_expect *exp_sc_info = &exp->help.exp_sc_info; /* Only mangle things once: original direction in POST_ROUTING and reply direction on PRE_ROUTING. */ dir = CTINFO2DIR(ctinfo); DEBUGP("nat_sc: help()\n"); #if 0 if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_REPLY) || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_ORIGINAL))) { #if 1 DEBUGP("nat_sc: 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" : "???"); #endif return NF_ACCEPT; } #endif datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4; score = 0; LOCK_BH(&ip_sc_lock); if (exp_sc_info->len) { /* If it's in the right range... */ score += between(exp_sc_info->seq, ntohl(tcph->seq), ntohl(tcph->seq) + datalen); score += between(exp_sc_info->seq + exp_sc_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("SC_NAT: partial packet %u/%u in %u/%u\n", exp_sc_info->seq, exp_sc_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen); } UNLOCK_BH(&ip_sc_lock); return NF_DROP; } else if (score == 2) { if (!sc_data_fixup(exp_sc_info, ct, datalen, pskb, ctinfo)) { UNLOCK_BH(&ip_sc_lock); return NF_DROP; } /* skb may have been reallocated */ iph = (*pskb)->nh.iph; tcph = (void *)iph + iph->ihl*4; } } UNLOCK_BH(&ip_sc_lock); DEBUGP("nat_sc: ip_nat_seq_adjust()\n"); ip_nat_seq_adjust(*pskb, ct, ctinfo); return NF_ACCEPT; }