static unsigned int mangle_packet(struct sk_buff *skb, unsigned int protoff, unsigned int dataoff, const char **dptr, unsigned int *datalen, unsigned int matchoff, unsigned int matchlen, const char *buffer, unsigned int buflen) { enum ip_conntrack_info ctinfo; struct nf_conn *ct = nf_ct_get(skb, &ctinfo); struct tcphdr *th; unsigned int baseoff; if (nf_ct_protonum(ct) == IPPROTO_TCP) { th = (struct tcphdr *)(skb->data + protoff); baseoff = protoff + th->doff * 4; matchoff += dataoff - baseoff; if (!__nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, matchoff, matchlen, buffer, buflen, false)) return 0; } else { baseoff = protoff + sizeof(struct udphdr); matchoff += dataoff - baseoff; if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, protoff, matchoff, matchlen, buffer, buflen)) return 0; } /* Reload data pointer and adjust datalen value */ *dptr = skb->data + dataoff; *datalen += buflen - matchlen; return 1; }
/* Generic function for mangling variable-length address changes inside * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX * command in FTP). * * Takes care about all the nasty sequence number changes, checksumming, * skb enlargement, ... * * */ int nf_nat_mangle_tcp_packet(struct sk_buff **skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned int match_offset, unsigned int match_len, const char *rep_buffer, unsigned int rep_len) { return __nf_nat_mangle_tcp_packet(skb, ct, ctinfo, match_offset, match_len, rep_buffer, rep_len, true); }