diff options
author | David S. Miller <davem@davemloft.net> | 2009-03-27 01:45:23 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-03-27 01:45:23 -0400 |
commit | 01e6de64d9c8d0e75dca3bb4cf898db73abe00d4 (patch) | |
tree | 925982e6241e5ac47f268bc2c2942ab0f06775cd /net/ipv4 | |
parent | 8f1ead2d1a626ed0c85b3d2c2046a49081d5933f (diff) | |
parent | d271e8bd8c60ce059ee36d836ba063cfc61c3e21 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/netfilter/arp_tables.c | 18 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_tables.c | 27 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 6 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | 63 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 6 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_core.c | 2 |
6 files changed, 58 insertions, 64 deletions
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 84b9c179df51..35c5f6a5cb7c 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -81,19 +81,7 @@ static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, | |||
81 | static unsigned long ifname_compare(const char *_a, const char *_b, const char *_mask) | 81 | static unsigned long ifname_compare(const char *_a, const char *_b, const char *_mask) |
82 | { | 82 | { |
83 | #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | 83 | #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS |
84 | const unsigned long *a = (const unsigned long *)_a; | 84 | unsigned long ret = ifname_compare_aligned(_a, _b, _mask); |
85 | const unsigned long *b = (const unsigned long *)_b; | ||
86 | const unsigned long *mask = (const unsigned long *)_mask; | ||
87 | unsigned long ret; | ||
88 | |||
89 | ret = (a[0] ^ b[0]) & mask[0]; | ||
90 | if (IFNAMSIZ > sizeof(unsigned long)) | ||
91 | ret |= (a[1] ^ b[1]) & mask[1]; | ||
92 | if (IFNAMSIZ > 2 * sizeof(unsigned long)) | ||
93 | ret |= (a[2] ^ b[2]) & mask[2]; | ||
94 | if (IFNAMSIZ > 3 * sizeof(unsigned long)) | ||
95 | ret |= (a[3] ^ b[3]) & mask[3]; | ||
96 | BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); | ||
97 | #else | 85 | #else |
98 | unsigned long ret = 0; | 86 | unsigned long ret = 0; |
99 | const u16 *a = (const u16 *)_a; | 87 | const u16 *a = (const u16 *)_a; |
@@ -404,7 +392,9 @@ static int mark_source_chains(struct xt_table_info *newinfo, | |||
404 | && unconditional(&e->arp)) || visited) { | 392 | && unconditional(&e->arp)) || visited) { |
405 | unsigned int oldpos, size; | 393 | unsigned int oldpos, size; |
406 | 394 | ||
407 | if (t->verdict < -NF_MAX_VERDICT - 1) { | 395 | if ((strcmp(t->target.u.user.name, |
396 | ARPT_STANDARD_TARGET) == 0) && | ||
397 | t->verdict < -NF_MAX_VERDICT - 1) { | ||
408 | duprintf("mark_source_chains: bad " | 398 | duprintf("mark_source_chains: bad " |
409 | "negative verdict (%i)\n", | 399 | "negative verdict (%i)\n", |
410 | t->verdict); | 400 | t->verdict); |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index e5294aec967d..82ee7c9049ff 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -74,25 +74,6 @@ do { \ | |||
74 | 74 | ||
75 | Hence the start of any table is given by get_table() below. */ | 75 | Hence the start of any table is given by get_table() below. */ |
76 | 76 | ||
77 | static unsigned long ifname_compare(const char *_a, const char *_b, | ||
78 | const unsigned char *_mask) | ||
79 | { | ||
80 | const unsigned long *a = (const unsigned long *)_a; | ||
81 | const unsigned long *b = (const unsigned long *)_b; | ||
82 | const unsigned long *mask = (const unsigned long *)_mask; | ||
83 | unsigned long ret; | ||
84 | |||
85 | ret = (a[0] ^ b[0]) & mask[0]; | ||
86 | if (IFNAMSIZ > sizeof(unsigned long)) | ||
87 | ret |= (a[1] ^ b[1]) & mask[1]; | ||
88 | if (IFNAMSIZ > 2 * sizeof(unsigned long)) | ||
89 | ret |= (a[2] ^ b[2]) & mask[2]; | ||
90 | if (IFNAMSIZ > 3 * sizeof(unsigned long)) | ||
91 | ret |= (a[3] ^ b[3]) & mask[3]; | ||
92 | BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); | ||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | /* Returns whether matches rule or not. */ | 77 | /* Returns whether matches rule or not. */ |
97 | /* Performance critical - called for every packet */ | 78 | /* Performance critical - called for every packet */ |
98 | static inline bool | 79 | static inline bool |
@@ -121,7 +102,7 @@ ip_packet_match(const struct iphdr *ip, | |||
121 | return false; | 102 | return false; |
122 | } | 103 | } |
123 | 104 | ||
124 | ret = ifname_compare(indev, ipinfo->iniface, ipinfo->iniface_mask); | 105 | ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask); |
125 | 106 | ||
126 | if (FWINV(ret != 0, IPT_INV_VIA_IN)) { | 107 | if (FWINV(ret != 0, IPT_INV_VIA_IN)) { |
127 | dprintf("VIA in mismatch (%s vs %s).%s\n", | 108 | dprintf("VIA in mismatch (%s vs %s).%s\n", |
@@ -130,7 +111,7 @@ ip_packet_match(const struct iphdr *ip, | |||
130 | return false; | 111 | return false; |
131 | } | 112 | } |
132 | 113 | ||
133 | ret = ifname_compare(outdev, ipinfo->outiface, ipinfo->outiface_mask); | 114 | ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask); |
134 | 115 | ||
135 | if (FWINV(ret != 0, IPT_INV_VIA_OUT)) { | 116 | if (FWINV(ret != 0, IPT_INV_VIA_OUT)) { |
136 | dprintf("VIA out mismatch (%s vs %s).%s\n", | 117 | dprintf("VIA out mismatch (%s vs %s).%s\n", |
@@ -507,7 +488,9 @@ mark_source_chains(struct xt_table_info *newinfo, | |||
507 | && unconditional(&e->ip)) || visited) { | 488 | && unconditional(&e->ip)) || visited) { |
508 | unsigned int oldpos, size; | 489 | unsigned int oldpos, size; |
509 | 490 | ||
510 | if (t->verdict < -NF_MAX_VERDICT - 1) { | 491 | if ((strcmp(t->target.u.user.name, |
492 | IPT_STANDARD_TARGET) == 0) && | ||
493 | t->verdict < -NF_MAX_VERDICT - 1) { | ||
511 | duprintf("mark_source_chains: bad " | 494 | duprintf("mark_source_chains: bad " |
512 | "negative verdict (%i)\n", | 495 | "negative verdict (%i)\n", |
513 | t->verdict); | 496 | t->verdict); |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 8b681f24e271..7d2ead7228ac 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -328,6 +328,11 @@ static int ipv4_nlattr_to_tuple(struct nlattr *tb[], | |||
328 | 328 | ||
329 | return 0; | 329 | return 0; |
330 | } | 330 | } |
331 | |||
332 | static int ipv4_nlattr_tuple_size(void) | ||
333 | { | ||
334 | return nla_policy_len(ipv4_nla_policy, CTA_IP_MAX + 1); | ||
335 | } | ||
331 | #endif | 336 | #endif |
332 | 337 | ||
333 | static struct nf_sockopt_ops so_getorigdst = { | 338 | static struct nf_sockopt_ops so_getorigdst = { |
@@ -347,6 +352,7 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = { | |||
347 | .get_l4proto = ipv4_get_l4proto, | 352 | .get_l4proto = ipv4_get_l4proto, |
348 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 353 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
349 | .tuple_to_nlattr = ipv4_tuple_to_nlattr, | 354 | .tuple_to_nlattr = ipv4_tuple_to_nlattr, |
355 | .nlattr_tuple_size = ipv4_nlattr_tuple_size, | ||
350 | .nlattr_to_tuple = ipv4_nlattr_to_tuple, | 356 | .nlattr_to_tuple = ipv4_nlattr_to_tuple, |
351 | .nla_policy = ipv4_nla_policy, | 357 | .nla_policy = ipv4_nla_policy, |
352 | #endif | 358 | #endif |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index 6ba5c557690c..8668a3defda6 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | |||
@@ -25,40 +25,42 @@ struct ct_iter_state { | |||
25 | unsigned int bucket; | 25 | unsigned int bucket; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | static struct hlist_node *ct_get_first(struct seq_file *seq) | 28 | static struct hlist_nulls_node *ct_get_first(struct seq_file *seq) |
29 | { | 29 | { |
30 | struct net *net = seq_file_net(seq); | 30 | struct net *net = seq_file_net(seq); |
31 | struct ct_iter_state *st = seq->private; | 31 | struct ct_iter_state *st = seq->private; |
32 | struct hlist_node *n; | 32 | struct hlist_nulls_node *n; |
33 | 33 | ||
34 | for (st->bucket = 0; | 34 | for (st->bucket = 0; |
35 | st->bucket < nf_conntrack_htable_size; | 35 | st->bucket < nf_conntrack_htable_size; |
36 | st->bucket++) { | 36 | st->bucket++) { |
37 | n = rcu_dereference(net->ct.hash[st->bucket].first); | 37 | n = rcu_dereference(net->ct.hash[st->bucket].first); |
38 | if (n) | 38 | if (!is_a_nulls(n)) |
39 | return n; | 39 | return n; |
40 | } | 40 | } |
41 | return NULL; | 41 | return NULL; |
42 | } | 42 | } |
43 | 43 | ||
44 | static struct hlist_node *ct_get_next(struct seq_file *seq, | 44 | static struct hlist_nulls_node *ct_get_next(struct seq_file *seq, |
45 | struct hlist_node *head) | 45 | struct hlist_nulls_node *head) |
46 | { | 46 | { |
47 | struct net *net = seq_file_net(seq); | 47 | struct net *net = seq_file_net(seq); |
48 | struct ct_iter_state *st = seq->private; | 48 | struct ct_iter_state *st = seq->private; |
49 | 49 | ||
50 | head = rcu_dereference(head->next); | 50 | head = rcu_dereference(head->next); |
51 | while (head == NULL) { | 51 | while (is_a_nulls(head)) { |
52 | if (++st->bucket >= nf_conntrack_htable_size) | 52 | if (likely(get_nulls_value(head) == st->bucket)) { |
53 | return NULL; | 53 | if (++st->bucket >= nf_conntrack_htable_size) |
54 | return NULL; | ||
55 | } | ||
54 | head = rcu_dereference(net->ct.hash[st->bucket].first); | 56 | head = rcu_dereference(net->ct.hash[st->bucket].first); |
55 | } | 57 | } |
56 | return head; | 58 | return head; |
57 | } | 59 | } |
58 | 60 | ||
59 | static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos) | 61 | static struct hlist_nulls_node *ct_get_idx(struct seq_file *seq, loff_t pos) |
60 | { | 62 | { |
61 | struct hlist_node *head = ct_get_first(seq); | 63 | struct hlist_nulls_node *head = ct_get_first(seq); |
62 | 64 | ||
63 | if (head) | 65 | if (head) |
64 | while (pos && (head = ct_get_next(seq, head))) | 66 | while (pos && (head = ct_get_next(seq, head))) |
@@ -87,69 +89,76 @@ static void ct_seq_stop(struct seq_file *s, void *v) | |||
87 | 89 | ||
88 | static int ct_seq_show(struct seq_file *s, void *v) | 90 | static int ct_seq_show(struct seq_file *s, void *v) |
89 | { | 91 | { |
90 | const struct nf_conntrack_tuple_hash *hash = v; | 92 | struct nf_conntrack_tuple_hash *hash = v; |
91 | const struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash); | 93 | struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash); |
92 | const struct nf_conntrack_l3proto *l3proto; | 94 | const struct nf_conntrack_l3proto *l3proto; |
93 | const struct nf_conntrack_l4proto *l4proto; | 95 | const struct nf_conntrack_l4proto *l4proto; |
96 | int ret = 0; | ||
94 | 97 | ||
95 | NF_CT_ASSERT(ct); | 98 | NF_CT_ASSERT(ct); |
99 | if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use))) | ||
100 | return 0; | ||
101 | |||
96 | 102 | ||
97 | /* we only want to print DIR_ORIGINAL */ | 103 | /* we only want to print DIR_ORIGINAL */ |
98 | if (NF_CT_DIRECTION(hash)) | 104 | if (NF_CT_DIRECTION(hash)) |
99 | return 0; | 105 | goto release; |
100 | if (nf_ct_l3num(ct) != AF_INET) | 106 | if (nf_ct_l3num(ct) != AF_INET) |
101 | return 0; | 107 | goto release; |
102 | 108 | ||
103 | l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct)); | 109 | l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct)); |
104 | NF_CT_ASSERT(l3proto); | 110 | NF_CT_ASSERT(l3proto); |
105 | l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); | 111 | l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); |
106 | NF_CT_ASSERT(l4proto); | 112 | NF_CT_ASSERT(l4proto); |
107 | 113 | ||
114 | ret = -ENOSPC; | ||
108 | if (seq_printf(s, "%-8s %u %ld ", | 115 | if (seq_printf(s, "%-8s %u %ld ", |
109 | l4proto->name, nf_ct_protonum(ct), | 116 | l4proto->name, nf_ct_protonum(ct), |
110 | timer_pending(&ct->timeout) | 117 | timer_pending(&ct->timeout) |
111 | ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0) | 118 | ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0) |
112 | return -ENOSPC; | 119 | goto release; |
113 | 120 | ||
114 | if (l4proto->print_conntrack && l4proto->print_conntrack(s, ct)) | 121 | if (l4proto->print_conntrack && l4proto->print_conntrack(s, ct)) |
115 | return -ENOSPC; | 122 | goto release; |
116 | 123 | ||
117 | if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, | 124 | if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, |
118 | l3proto, l4proto)) | 125 | l3proto, l4proto)) |
119 | return -ENOSPC; | 126 | goto release; |
120 | 127 | ||
121 | if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL)) | 128 | if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL)) |
122 | return -ENOSPC; | 129 | goto release; |
123 | 130 | ||
124 | if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) | 131 | if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) |
125 | if (seq_printf(s, "[UNREPLIED] ")) | 132 | if (seq_printf(s, "[UNREPLIED] ")) |
126 | return -ENOSPC; | 133 | goto release; |
127 | 134 | ||
128 | if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, | 135 | if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, |
129 | l3proto, l4proto)) | 136 | l3proto, l4proto)) |
130 | return -ENOSPC; | 137 | goto release; |
131 | 138 | ||
132 | if (seq_print_acct(s, ct, IP_CT_DIR_REPLY)) | 139 | if (seq_print_acct(s, ct, IP_CT_DIR_REPLY)) |
133 | return -ENOSPC; | 140 | goto release; |
134 | 141 | ||
135 | if (test_bit(IPS_ASSURED_BIT, &ct->status)) | 142 | if (test_bit(IPS_ASSURED_BIT, &ct->status)) |
136 | if (seq_printf(s, "[ASSURED] ")) | 143 | if (seq_printf(s, "[ASSURED] ")) |
137 | return -ENOSPC; | 144 | goto release; |
138 | 145 | ||
139 | #ifdef CONFIG_NF_CONNTRACK_MARK | 146 | #ifdef CONFIG_NF_CONNTRACK_MARK |
140 | if (seq_printf(s, "mark=%u ", ct->mark)) | 147 | if (seq_printf(s, "mark=%u ", ct->mark)) |
141 | return -ENOSPC; | 148 | goto release; |
142 | #endif | 149 | #endif |
143 | 150 | ||
144 | #ifdef CONFIG_NF_CONNTRACK_SECMARK | 151 | #ifdef CONFIG_NF_CONNTRACK_SECMARK |
145 | if (seq_printf(s, "secmark=%u ", ct->secmark)) | 152 | if (seq_printf(s, "secmark=%u ", ct->secmark)) |
146 | return -ENOSPC; | 153 | goto release; |
147 | #endif | 154 | #endif |
148 | 155 | ||
149 | if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) | 156 | if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) |
150 | return -ENOSPC; | 157 | goto release; |
151 | 158 | ret = 0; | |
152 | return 0; | 159 | release: |
160 | nf_ct_put(ct); | ||
161 | return ret; | ||
153 | } | 162 | } |
154 | 163 | ||
155 | static const struct seq_operations ct_seq_ops = { | 164 | static const struct seq_operations ct_seq_ops = { |
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 2a8bee26f43d..23b2c2ee869a 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
@@ -262,6 +262,11 @@ static int icmp_nlattr_to_tuple(struct nlattr *tb[], | |||
262 | 262 | ||
263 | return 0; | 263 | return 0; |
264 | } | 264 | } |
265 | |||
266 | static int icmp_nlattr_tuple_size(void) | ||
267 | { | ||
268 | return nla_policy_len(icmp_nla_policy, CTA_PROTO_MAX + 1); | ||
269 | } | ||
265 | #endif | 270 | #endif |
266 | 271 | ||
267 | #ifdef CONFIG_SYSCTL | 272 | #ifdef CONFIG_SYSCTL |
@@ -309,6 +314,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = | |||
309 | .me = NULL, | 314 | .me = NULL, |
310 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 315 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
311 | .tuple_to_nlattr = icmp_tuple_to_nlattr, | 316 | .tuple_to_nlattr = icmp_tuple_to_nlattr, |
317 | .nlattr_tuple_size = icmp_nlattr_tuple_size, | ||
312 | .nlattr_to_tuple = icmp_nlattr_to_tuple, | 318 | .nlattr_to_tuple = icmp_nlattr_to_tuple, |
313 | .nla_policy = icmp_nla_policy, | 319 | .nla_policy = icmp_nla_policy, |
314 | #endif | 320 | #endif |
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index a65cf692359f..fe65187810f0 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c | |||
@@ -679,7 +679,7 @@ nfnetlink_parse_nat_setup(struct nf_conn *ct, | |||
679 | static int __net_init nf_nat_net_init(struct net *net) | 679 | static int __net_init nf_nat_net_init(struct net *net) |
680 | { | 680 | { |
681 | net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size, | 681 | net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size, |
682 | &net->ipv4.nat_vmalloced); | 682 | &net->ipv4.nat_vmalloced, 0); |
683 | if (!net->ipv4.nat_bysource) | 683 | if (!net->ipv4.nat_bysource) |
684 | return -ENOMEM; | 684 | return -ENOMEM; |
685 | return 0; | 685 | return 0; |