int nf_nat_seq_adjust(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo) { struct tcphdr *tcph; int dir; __be32 newseq, newack; s16 seqoff, ackoff; struct nf_conn_nat *nat = nfct_nat(ct); struct nf_nat_seq *this_way, *other_way; dir = CTINFO2DIR(ctinfo); this_way = &nat->seq[dir]; other_way = &nat->seq[!dir]; #ifdef CONFIG_HTC_NETWORK_MODIFY if (IS_ERR(this_way) || (!this_way)) printk(KERN_ERR "[NET] this_way is NULL in %s!\n", __func__); #endif if (!skb_make_writable(skb, ip_hdrlen(skb) + sizeof(*tcph))) return 0; tcph = (void *)skb->data + ip_hdrlen(skb); if (after(ntohl(tcph->seq), this_way->correction_pos)) seqoff = this_way->offset_after; else seqoff = this_way->offset_before; if (after(ntohl(tcph->ack_seq) - other_way->offset_before, other_way->correction_pos)) ackoff = other_way->offset_after; else ackoff = other_way->offset_before; newseq = htonl(ntohl(tcph->seq) + seqoff); newack = htonl(ntohl(tcph->ack_seq) - ackoff); inet_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, 0); inet_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 0); pr_debug("Adjusting sequence number from %u->%u, ack from %u->%u\n", ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), ntohl(newack)); tcph->seq = newseq; tcph->ack_seq = newack; return nf_nat_sack_adjust(skb, tcph, ct, ctinfo); }
/* TCP sequence number adjustment. Returns 1 on success, 0 on failure */ int nf_nat_seq_adjust(struct sk_buff **pskb, struct nf_conn *ct, enum ip_conntrack_info ctinfo) { struct tcphdr *tcph; int dir; __be32 newseq, newack; struct nf_conn_nat *nat = nfct_nat(ct); struct nf_nat_seq *this_way, *other_way; dir = CTINFO2DIR(ctinfo); this_way = &nat->info.seq[dir]; other_way = &nat->info.seq[!dir]; if (!skb_make_writable(pskb, (*pskb)->nh.iph->ihl*4+sizeof(*tcph))) return 0; tcph = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4; if (after(ntohl(tcph->seq), this_way->correction_pos)) newseq = htonl(ntohl(tcph->seq) + this_way->offset_after); else newseq = htonl(ntohl(tcph->seq) + this_way->offset_before); if (after(ntohl(tcph->ack_seq) - other_way->offset_before, other_way->correction_pos)) newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_after); else newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before); nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0); nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0); DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n", ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), ntohl(newack)); tcph->seq = newseq; tcph->ack_seq = newack; if (!nf_nat_sack_adjust(pskb, tcph, ct, ctinfo)) return 0; nf_conntrack_tcp_update(*pskb, (*pskb)->nh.iph->ihl*4, ct, dir); return 1; }