diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-11-09 12:51:42 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-11-09 12:51:42 -0500 |
| commit | 1ce55238e2dd46b978b098a85cb3d3ea494e4a93 (patch) | |
| tree | 523254dbb402b1850d693f0c1f1a1db6e865456d /net/netfilter | |
| parent | aa907639f1d9fe0e3274b4f6c1088542f750a539 (diff) | |
| parent | 2606289779cb297320a185db5997729d29b6700b (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (34 commits)
net/fsl_pq_mdio: add module license GPL
can: fix WARN_ON dump in net/core/rtnetlink.c:rtmsg_ifinfo()
can: should not use __dev_get_by_index() without locks
hisax: remove bad udelay call to fix build error on ARM
ipip: Fix handling of DF packets when pmtudisc is OFF
qlge: Set PCIe reset type for EEH to fundamental.
qlge: Fix early exit from mbox cmd complete wait.
ixgbe: fix traffic hangs on Tx with ioatdma loaded
ixgbe: Fix checking TFCS register for TXOFF status when DCB is enabled
ixgbe: Fix gso_max_size for 82599 when DCB is enabled
macsonic: fix crash on PowerBook 520
NET: cassini, fix lock imbalance
ems_usb: Fix byte order issues on big endian machines
be2net: Bug fix to send config commands to hardware after netdev_register
be2net: fix to set proper flow control on resume
netfilter: xt_connlimit: fix regression caused by zero family value
rt2x00: Don't queue ieee80211 work after USB removal
Revert "ipw2200: fix oops on missing firmware"
decnet: netdevice refcount leak
netfilter: nf_nat: fix NAT issue in 2.6.30.4+
...
Diffstat (limited to 'net/netfilter')
| -rw-r--r-- | net/netfilter/nf_conntrack_core.c | 8 | ||||
| -rw-r--r-- | net/netfilter/nf_conntrack_proto_tcp.c | 64 | ||||
| -rw-r--r-- | net/netfilter/xt_connlimit.c | 10 |
3 files changed, 38 insertions, 44 deletions
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index ca6e68dcd8a8..b9168c1864ca 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
| @@ -1351,6 +1351,11 @@ err_stat: | |||
| 1351 | return ret; | 1351 | return ret; |
| 1352 | } | 1352 | } |
| 1353 | 1353 | ||
| 1354 | s16 (*nf_ct_nat_offset)(const struct nf_conn *ct, | ||
| 1355 | enum ip_conntrack_dir dir, | ||
| 1356 | u32 seq); | ||
| 1357 | EXPORT_SYMBOL_GPL(nf_ct_nat_offset); | ||
| 1358 | |||
| 1354 | int nf_conntrack_init(struct net *net) | 1359 | int nf_conntrack_init(struct net *net) |
| 1355 | { | 1360 | { |
| 1356 | int ret; | 1361 | int ret; |
| @@ -1368,6 +1373,9 @@ int nf_conntrack_init(struct net *net) | |||
| 1368 | /* For use by REJECT target */ | 1373 | /* For use by REJECT target */ |
| 1369 | rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach); | 1374 | rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach); |
| 1370 | rcu_assign_pointer(nf_ct_destroy, destroy_conntrack); | 1375 | rcu_assign_pointer(nf_ct_destroy, destroy_conntrack); |
| 1376 | |||
| 1377 | /* Howto get NAT offsets */ | ||
| 1378 | rcu_assign_pointer(nf_ct_nat_offset, NULL); | ||
| 1371 | } | 1379 | } |
| 1372 | return 0; | 1380 | return 0; |
| 1373 | 1381 | ||
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 97a82ba75376..ba2b76937283 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
| @@ -492,6 +492,21 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff, | |||
| 492 | } | 492 | } |
| 493 | } | 493 | } |
| 494 | 494 | ||
| 495 | #ifdef CONFIG_NF_NAT_NEEDED | ||
| 496 | static inline s16 nat_offset(const struct nf_conn *ct, | ||
| 497 | enum ip_conntrack_dir dir, | ||
| 498 | u32 seq) | ||
| 499 | { | ||
| 500 | typeof(nf_ct_nat_offset) get_offset = rcu_dereference(nf_ct_nat_offset); | ||
| 501 | |||
| 502 | return get_offset != NULL ? get_offset(ct, dir, seq) : 0; | ||
| 503 | } | ||
| 504 | #define NAT_OFFSET(pf, ct, dir, seq) \ | ||
| 505 | (pf == NFPROTO_IPV4 ? nat_offset(ct, dir, seq) : 0) | ||
| 506 | #else | ||
| 507 | #define NAT_OFFSET(pf, ct, dir, seq) 0 | ||
| 508 | #endif | ||
| 509 | |||
| 495 | static bool tcp_in_window(const struct nf_conn *ct, | 510 | static bool tcp_in_window(const struct nf_conn *ct, |
| 496 | struct ip_ct_tcp *state, | 511 | struct ip_ct_tcp *state, |
| 497 | enum ip_conntrack_dir dir, | 512 | enum ip_conntrack_dir dir, |
| @@ -506,6 +521,7 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
| 506 | struct ip_ct_tcp_state *receiver = &state->seen[!dir]; | 521 | struct ip_ct_tcp_state *receiver = &state->seen[!dir]; |
| 507 | const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple; | 522 | const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple; |
| 508 | __u32 seq, ack, sack, end, win, swin; | 523 | __u32 seq, ack, sack, end, win, swin; |
| 524 | s16 receiver_offset; | ||
| 509 | bool res; | 525 | bool res; |
| 510 | 526 | ||
| 511 | /* | 527 | /* |
| @@ -519,11 +535,16 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
| 519 | if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM) | 535 | if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM) |
| 520 | tcp_sack(skb, dataoff, tcph, &sack); | 536 | tcp_sack(skb, dataoff, tcph, &sack); |
| 521 | 537 | ||
| 538 | /* Take into account NAT sequence number mangling */ | ||
| 539 | receiver_offset = NAT_OFFSET(pf, ct, !dir, ack - 1); | ||
| 540 | ack -= receiver_offset; | ||
| 541 | sack -= receiver_offset; | ||
| 542 | |||
| 522 | pr_debug("tcp_in_window: START\n"); | 543 | pr_debug("tcp_in_window: START\n"); |
| 523 | pr_debug("tcp_in_window: "); | 544 | pr_debug("tcp_in_window: "); |
| 524 | nf_ct_dump_tuple(tuple); | 545 | nf_ct_dump_tuple(tuple); |
| 525 | pr_debug("seq=%u ack=%u sack=%u win=%u end=%u\n", | 546 | pr_debug("seq=%u ack=%u+(%d) sack=%u+(%d) win=%u end=%u\n", |
| 526 | seq, ack, sack, win, end); | 547 | seq, ack, receiver_offset, sack, receiver_offset, win, end); |
| 527 | pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " | 548 | pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " |
| 528 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", | 549 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", |
| 529 | sender->td_end, sender->td_maxend, sender->td_maxwin, | 550 | sender->td_end, sender->td_maxend, sender->td_maxwin, |
| @@ -613,8 +634,8 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
| 613 | 634 | ||
| 614 | pr_debug("tcp_in_window: "); | 635 | pr_debug("tcp_in_window: "); |
| 615 | nf_ct_dump_tuple(tuple); | 636 | nf_ct_dump_tuple(tuple); |
| 616 | pr_debug("seq=%u ack=%u sack =%u win=%u end=%u\n", | 637 | pr_debug("seq=%u ack=%u+(%d) sack=%u+(%d) win=%u end=%u\n", |
| 617 | seq, ack, sack, win, end); | 638 | seq, ack, receiver_offset, sack, receiver_offset, win, end); |
| 618 | pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " | 639 | pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " |
| 619 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", | 640 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", |
| 620 | sender->td_end, sender->td_maxend, sender->td_maxwin, | 641 | sender->td_end, sender->td_maxend, sender->td_maxwin, |
| @@ -700,7 +721,7 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
| 700 | before(seq, sender->td_maxend + 1) ? | 721 | before(seq, sender->td_maxend + 1) ? |
| 701 | after(end, sender->td_end - receiver->td_maxwin - 1) ? | 722 | after(end, sender->td_end - receiver->td_maxwin - 1) ? |
| 702 | before(sack, receiver->td_end + 1) ? | 723 | before(sack, receiver->td_end + 1) ? |
| 703 | after(ack, receiver->td_end - MAXACKWINDOW(sender)) ? "BUG" | 724 | after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1) ? "BUG" |
| 704 | : "ACK is under the lower bound (possible overly delayed ACK)" | 725 | : "ACK is under the lower bound (possible overly delayed ACK)" |
| 705 | : "ACK is over the upper bound (ACKed data not seen yet)" | 726 | : "ACK is over the upper bound (ACKed data not seen yet)" |
| 706 | : "SEQ is under the lower bound (already ACKed data retransmitted)" | 727 | : "SEQ is under the lower bound (already ACKed data retransmitted)" |
| @@ -715,39 +736,6 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
| 715 | return res; | 736 | return res; |
| 716 | } | 737 | } |
| 717 | 738 | ||
| 718 | #ifdef CONFIG_NF_NAT_NEEDED | ||
| 719 | /* Update sender->td_end after NAT successfully mangled the packet */ | ||
| 720 | /* Caller must linearize skb at tcp header. */ | ||
| 721 | void nf_conntrack_tcp_update(const struct sk_buff *skb, | ||
| 722 | unsigned int dataoff, | ||
| 723 | struct nf_conn *ct, int dir, | ||
| 724 | s16 offset) | ||
| 725 | { | ||
| 726 | const struct tcphdr *tcph = (const void *)skb->data + dataoff; | ||
| 727 | const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[dir]; | ||
| 728 | const struct ip_ct_tcp_state *receiver = &ct->proto.tcp.seen[!dir]; | ||
| 729 | __u32 end; | ||
| 730 | |||
| 731 | end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, dataoff, tcph); | ||
| 732 | |||
| 733 | spin_lock_bh(&ct->lock); | ||
| 734 | /* | ||
| 735 | * We have to worry for the ack in the reply packet only... | ||
| 736 | */ | ||
| 737 | if (ct->proto.tcp.seen[dir].td_end + offset == end) | ||
| 738 | ct->proto.tcp.seen[dir].td_end = end; | ||
| 739 | ct->proto.tcp.last_end = end; | ||
| 740 | spin_unlock_bh(&ct->lock); | ||
| 741 | pr_debug("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i " | ||
| 742 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", | ||
| 743 | sender->td_end, sender->td_maxend, sender->td_maxwin, | ||
| 744 | sender->td_scale, | ||
| 745 | receiver->td_end, receiver->td_maxend, receiver->td_maxwin, | ||
| 746 | receiver->td_scale); | ||
| 747 | } | ||
| 748 | EXPORT_SYMBOL_GPL(nf_conntrack_tcp_update); | ||
| 749 | #endif | ||
| 750 | |||
| 751 | #define TH_FIN 0x01 | 739 | #define TH_FIN 0x01 |
| 752 | #define TH_SYN 0x02 | 740 | #define TH_SYN 0x02 |
| 753 | #define TH_RST 0x04 | 741 | #define TH_RST 0x04 |
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c index 680980954395..38f03f75a636 100644 --- a/net/netfilter/xt_connlimit.c +++ b/net/netfilter/xt_connlimit.c | |||
| @@ -103,7 +103,7 @@ static int count_them(struct xt_connlimit_data *data, | |||
| 103 | const struct nf_conntrack_tuple *tuple, | 103 | const struct nf_conntrack_tuple *tuple, |
| 104 | const union nf_inet_addr *addr, | 104 | const union nf_inet_addr *addr, |
| 105 | const union nf_inet_addr *mask, | 105 | const union nf_inet_addr *mask, |
| 106 | const struct xt_match *match) | 106 | u_int8_t family) |
| 107 | { | 107 | { |
| 108 | const struct nf_conntrack_tuple_hash *found; | 108 | const struct nf_conntrack_tuple_hash *found; |
| 109 | struct xt_connlimit_conn *conn; | 109 | struct xt_connlimit_conn *conn; |
| @@ -113,8 +113,7 @@ static int count_them(struct xt_connlimit_data *data, | |||
| 113 | bool addit = true; | 113 | bool addit = true; |
| 114 | int matches = 0; | 114 | int matches = 0; |
| 115 | 115 | ||
| 116 | 116 | if (family == NFPROTO_IPV6) | |
| 117 | if (match->family == NFPROTO_IPV6) | ||
| 118 | hash = &data->iphash[connlimit_iphash6(addr, mask)]; | 117 | hash = &data->iphash[connlimit_iphash6(addr, mask)]; |
| 119 | else | 118 | else |
| 120 | hash = &data->iphash[connlimit_iphash(addr->ip & mask->ip)]; | 119 | hash = &data->iphash[connlimit_iphash(addr->ip & mask->ip)]; |
| @@ -157,8 +156,7 @@ static int count_them(struct xt_connlimit_data *data, | |||
| 157 | continue; | 156 | continue; |
| 158 | } | 157 | } |
| 159 | 158 | ||
| 160 | if (same_source_net(addr, mask, &conn->tuple.src.u3, | 159 | if (same_source_net(addr, mask, &conn->tuple.src.u3, family)) |
| 161 | match->family)) | ||
| 162 | /* same source network -> be counted! */ | 160 | /* same source network -> be counted! */ |
| 163 | ++matches; | 161 | ++matches; |
| 164 | nf_ct_put(found_ct); | 162 | nf_ct_put(found_ct); |
| @@ -207,7 +205,7 @@ connlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
| 207 | 205 | ||
| 208 | spin_lock_bh(&info->data->lock); | 206 | spin_lock_bh(&info->data->lock); |
| 209 | connections = count_them(info->data, tuple_ptr, &addr, | 207 | connections = count_them(info->data, tuple_ptr, &addr, |
| 210 | &info->mask, par->match); | 208 | &info->mask, par->family); |
| 211 | spin_unlock_bh(&info->data->lock); | 209 | spin_unlock_bh(&info->data->lock); |
| 212 | 210 | ||
| 213 | if (connections < 0) { | 211 | if (connections < 0) { |
