diff options
-rw-r--r-- | include/net/netfilter/nf_conntrack.h | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_helper.c | 17 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_tcp.c | 6 |
3 files changed, 16 insertions, 11 deletions
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index a632689b61b4..cbdd6284996d 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h | |||
@@ -258,8 +258,8 @@ static inline bool nf_ct_kill(struct nf_conn *ct) | |||
258 | /* Update TCP window tracking data when NAT mangles the packet */ | 258 | /* Update TCP window tracking data when NAT mangles the packet */ |
259 | extern void nf_conntrack_tcp_update(const struct sk_buff *skb, | 259 | extern void nf_conntrack_tcp_update(const struct sk_buff *skb, |
260 | unsigned int dataoff, | 260 | unsigned int dataoff, |
261 | struct nf_conn *ct, | 261 | struct nf_conn *ct, int dir, |
262 | int dir); | 262 | s16 offset); |
263 | 263 | ||
264 | /* Fake conntrack entry for untracked connections */ | 264 | /* Fake conntrack entry for untracked connections */ |
265 | extern struct nf_conn nf_conntrack_untracked; | 265 | extern struct nf_conn nf_conntrack_untracked; |
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 155c008626c8..09172a65d9b6 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c | |||
@@ -191,7 +191,8 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb, | |||
191 | ct, ctinfo); | 191 | ct, ctinfo); |
192 | /* Tell TCP window tracking about seq change */ | 192 | /* Tell TCP window tracking about seq change */ |
193 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), | 193 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), |
194 | ct, CTINFO2DIR(ctinfo)); | 194 | ct, CTINFO2DIR(ctinfo), |
195 | (int)rep_len - (int)match_len); | ||
195 | 196 | ||
196 | nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); | 197 | nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); |
197 | } | 198 | } |
@@ -377,6 +378,7 @@ nf_nat_seq_adjust(struct sk_buff *skb, | |||
377 | struct tcphdr *tcph; | 378 | struct tcphdr *tcph; |
378 | int dir; | 379 | int dir; |
379 | __be32 newseq, newack; | 380 | __be32 newseq, newack; |
381 | s16 seqoff, ackoff; | ||
380 | struct nf_conn_nat *nat = nfct_nat(ct); | 382 | struct nf_conn_nat *nat = nfct_nat(ct); |
381 | struct nf_nat_seq *this_way, *other_way; | 383 | struct nf_nat_seq *this_way, *other_way; |
382 | 384 | ||
@@ -390,15 +392,18 @@ nf_nat_seq_adjust(struct sk_buff *skb, | |||
390 | 392 | ||
391 | tcph = (void *)skb->data + ip_hdrlen(skb); | 393 | tcph = (void *)skb->data + ip_hdrlen(skb); |
392 | if (after(ntohl(tcph->seq), this_way->correction_pos)) | 394 | if (after(ntohl(tcph->seq), this_way->correction_pos)) |
393 | newseq = htonl(ntohl(tcph->seq) + this_way->offset_after); | 395 | seqoff = this_way->offset_after; |
394 | else | 396 | else |
395 | newseq = htonl(ntohl(tcph->seq) + this_way->offset_before); | 397 | seqoff = this_way->offset_before; |
396 | 398 | ||
397 | if (after(ntohl(tcph->ack_seq) - other_way->offset_before, | 399 | if (after(ntohl(tcph->ack_seq) - other_way->offset_before, |
398 | other_way->correction_pos)) | 400 | other_way->correction_pos)) |
399 | newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_after); | 401 | ackoff = other_way->offset_after; |
400 | else | 402 | else |
401 | newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before); | 403 | ackoff = other_way->offset_before; |
404 | |||
405 | newseq = htonl(ntohl(tcph->seq) + seqoff); | ||
406 | newack = htonl(ntohl(tcph->ack_seq) - ackoff); | ||
402 | 407 | ||
403 | inet_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, 0); | 408 | inet_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, 0); |
404 | inet_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 0); | 409 | inet_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 0); |
@@ -413,7 +418,7 @@ nf_nat_seq_adjust(struct sk_buff *skb, | |||
413 | if (!nf_nat_sack_adjust(skb, tcph, ct, ctinfo)) | 418 | if (!nf_nat_sack_adjust(skb, tcph, ct, ctinfo)) |
414 | return 0; | 419 | return 0; |
415 | 420 | ||
416 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir); | 421 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir, seqoff); |
417 | 422 | ||
418 | return 1; | 423 | return 1; |
419 | } | 424 | } |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 33fc0a443f3d..97a82ba75376 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -720,8 +720,8 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
720 | /* Caller must linearize skb at tcp header. */ | 720 | /* Caller must linearize skb at tcp header. */ |
721 | void nf_conntrack_tcp_update(const struct sk_buff *skb, | 721 | void nf_conntrack_tcp_update(const struct sk_buff *skb, |
722 | unsigned int dataoff, | 722 | unsigned int dataoff, |
723 | struct nf_conn *ct, | 723 | struct nf_conn *ct, int dir, |
724 | int dir) | 724 | s16 offset) |
725 | { | 725 | { |
726 | const struct tcphdr *tcph = (const void *)skb->data + dataoff; | 726 | const struct tcphdr *tcph = (const void *)skb->data + dataoff; |
727 | const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[dir]; | 727 | const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[dir]; |
@@ -734,7 +734,7 @@ void nf_conntrack_tcp_update(const struct sk_buff *skb, | |||
734 | /* | 734 | /* |
735 | * We have to worry for the ack in the reply packet only... | 735 | * We have to worry for the ack in the reply packet only... |
736 | */ | 736 | */ |
737 | if (after(end, ct->proto.tcp.seen[dir].td_end)) | 737 | if (ct->proto.tcp.seen[dir].td_end + offset == end) |
738 | ct->proto.tcp.seen[dir].td_end = end; | 738 | ct->proto.tcp.seen[dir].td_end = end; |
739 | ct->proto.tcp.last_end = end; | 739 | ct->proto.tcp.last_end = end; |
740 | spin_unlock_bh(&ct->lock); | 740 | spin_unlock_bh(&ct->lock); |