aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-11-09 12:51:42 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-11-09 12:51:42 -0500
commit1ce55238e2dd46b978b098a85cb3d3ea494e4a93 (patch)
tree523254dbb402b1850d693f0c1f1a1db6e865456d /net/netfilter
parentaa907639f1d9fe0e3274b4f6c1088542f750a539 (diff)
parent2606289779cb297320a185db5997729d29b6700b (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.c8
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c64
-rw-r--r--net/netfilter/xt_connlimit.c10
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
1354s16 (*nf_ct_nat_offset)(const struct nf_conn *ct,
1355 enum ip_conntrack_dir dir,
1356 u32 seq);
1357EXPORT_SYMBOL_GPL(nf_ct_nat_offset);
1358
1354int nf_conntrack_init(struct net *net) 1359int 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
496static 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
495static bool tcp_in_window(const struct nf_conn *ct, 510static 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. */
721void 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}
748EXPORT_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) {