Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nf_nat: support mangling a single TCP packet multiple times

nf_nat_mangle_tcp_packet() can currently only handle a single mangling
per window because it only maintains two sequence adjustment positions:
the one before the last adjustment and the one after.

This patch makes sequence number adjustment tracking in
nf_nat_mangle_tcp_packet() optional and allows a helper to manually
update the offsets after the packet has been fully handled.

Signed-off-by: Patrick McHardy <kaber@trash.net>

+48 -23
+25 -7
include/net/netfilter/nf_nat_helper.h
··· 7 7 struct sk_buff; 8 8 9 9 /* These return true or false. */ 10 - extern int nf_nat_mangle_tcp_packet(struct sk_buff *skb, 11 - struct nf_conn *ct, 12 - enum ip_conntrack_info ctinfo, 13 - unsigned int match_offset, 14 - unsigned int match_len, 15 - const char *rep_buffer, 16 - unsigned int rep_len); 10 + extern int __nf_nat_mangle_tcp_packet(struct sk_buff *skb, 11 + struct nf_conn *ct, 12 + enum ip_conntrack_info ctinfo, 13 + unsigned int match_offset, 14 + unsigned int match_len, 15 + const char *rep_buffer, 16 + unsigned int rep_len, bool adjust); 17 + 18 + static inline int nf_nat_mangle_tcp_packet(struct sk_buff *skb, 19 + struct nf_conn *ct, 20 + enum ip_conntrack_info ctinfo, 21 + unsigned int match_offset, 22 + unsigned int match_len, 23 + const char *rep_buffer, 24 + unsigned int rep_len) 25 + { 26 + return __nf_nat_mangle_tcp_packet(skb, ct, ctinfo, 27 + match_offset, match_len, 28 + rep_buffer, rep_len, true); 29 + } 30 + 17 31 extern int nf_nat_mangle_udp_packet(struct sk_buff *skb, 18 32 struct nf_conn *ct, 19 33 enum ip_conntrack_info ctinfo, ··· 35 21 unsigned int match_len, 36 22 const char *rep_buffer, 37 23 unsigned int rep_len); 24 + 25 + extern void nf_nat_set_seq_adjust(struct nf_conn *ct, 26 + enum ip_conntrack_info ctinfo, 27 + __be32 seq, s16 off); 38 28 extern int nf_nat_seq_adjust(struct sk_buff *skb, 39 29 struct nf_conn *ct, 40 30 enum ip_conntrack_info ctinfo);
+23 -16
net/ipv4/netfilter/nf_nat_helper.c
··· 141 141 return 1; 142 142 } 143 143 144 + void nf_nat_set_seq_adjust(struct nf_conn *ct, enum ip_conntrack_info ctinfo, 145 + __be32 seq, s16 off) 146 + { 147 + if (!off) 148 + return; 149 + set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); 150 + adjust_tcp_sequence(ntohl(seq), off, ct, ctinfo); 151 + nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); 152 + } 153 + EXPORT_SYMBOL_GPL(nf_nat_set_seq_adjust); 154 + 144 155 /* Generic function for mangling variable-length address changes inside 145 156 * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX 146 157 * command in FTP). ··· 160 149 * skb enlargement, ... 161 150 * 162 151 * */ 163 - int 164 - nf_nat_mangle_tcp_packet(struct sk_buff *skb, 165 - struct nf_conn *ct, 166 - enum ip_conntrack_info ctinfo, 167 - unsigned int match_offset, 168 - unsigned int match_len, 169 - const char *rep_buffer, 170 - unsigned int rep_len) 152 + int __nf_nat_mangle_tcp_packet(struct sk_buff *skb, 153 + struct nf_conn *ct, 154 + enum ip_conntrack_info ctinfo, 155 + unsigned int match_offset, 156 + unsigned int match_len, 157 + const char *rep_buffer, 158 + unsigned int rep_len, bool adjust) 171 159 { 172 160 struct rtable *rt = skb_rtable(skb); 173 161 struct iphdr *iph; ··· 212 202 inet_proto_csum_replace2(&tcph->check, skb, 213 203 htons(oldlen), htons(datalen), 1); 214 204 215 - if (rep_len != match_len) { 216 - set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); 217 - adjust_tcp_sequence(ntohl(tcph->seq), 218 - (int)rep_len - (int)match_len, 219 - ct, ctinfo); 220 - nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); 221 - } 205 + if (adjust && rep_len != match_len) 206 + nf_nat_set_seq_adjust(ct, ctinfo, tcph->seq, 207 + (int)rep_len - (int)match_len); 208 + 222 209 return 1; 223 210 } 224 - EXPORT_SYMBOL(nf_nat_mangle_tcp_packet); 211 + EXPORT_SYMBOL(__nf_nat_mangle_tcp_packet); 225 212 226 213 /* Generic function for mangling variable-length address changes inside 227 214 * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX