aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2011-07-21 06:06:18 -0400
committerPatrick McHardy <kaber@trash.net>2011-07-21 06:06:18 -0400
commit89dc79b787d20e4b6c4077dcee1c5b1be4ab55b8 (patch)
tree24ebd4da0fe7e239e45cbc5a4ec599ee1abba94d /net
parenta6a7b759ba62e62542308e091f7fc9cfac4f978e (diff)
netfilter: ipset: hash:net,iface fixed to handle overlapping nets behind different interfaces
If overlapping networks with different interfaces was added to the set, the type did not handle it properly. Example ipset create test hash:net,iface ipset add test 192.168.0.0/16,eth0 ipset add test 192.168.0.0/24,eth1 Now, if a packet was sent from 192.168.0.0/24,eth0, the type returned a match. In the patch the algorithm is fixed in order to correctly handle overlapping networks. Limitation: the same network cannot be stored with more than 64 different interfaces in a single set. Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/ipset/ip_set_hash_ip.c6
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipport.c6
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportip.c6
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportnet.c6
-rw-r--r--net/netfilter/ipset/ip_set_hash_net.c6
-rw-r--r--net/netfilter/ipset/ip_set_hash_netiface.c40
-rw-r--r--net/netfilter/ipset/ip_set_hash_netport.c6
7 files changed, 56 insertions, 20 deletions
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c
index fa80bb9b9c81..f2d576e6b769 100644
--- a/net/netfilter/ipset/ip_set_hash_ip.c
+++ b/net/netfilter/ipset/ip_set_hash_ip.c
@@ -53,7 +53,8 @@ struct hash_ip4_telem {
53 53
54static inline bool 54static inline bool
55hash_ip4_data_equal(const struct hash_ip4_elem *ip1, 55hash_ip4_data_equal(const struct hash_ip4_elem *ip1,
56 const struct hash_ip4_elem *ip2) 56 const struct hash_ip4_elem *ip2,
57 u32 *multi)
57{ 58{
58 return ip1->ip == ip2->ip; 59 return ip1->ip == ip2->ip;
59} 60}
@@ -225,7 +226,8 @@ struct hash_ip6_telem {
225 226
226static inline bool 227static inline bool
227hash_ip6_data_equal(const struct hash_ip6_elem *ip1, 228hash_ip6_data_equal(const struct hash_ip6_elem *ip1,
228 const struct hash_ip6_elem *ip2) 229 const struct hash_ip6_elem *ip2,
230 u32 *multi)
229{ 231{
230 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0; 232 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0;
231} 233}
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c
index bbf51b67b170..6ee10f5d59bd 100644
--- a/net/netfilter/ipset/ip_set_hash_ipport.c
+++ b/net/netfilter/ipset/ip_set_hash_ipport.c
@@ -60,7 +60,8 @@ struct hash_ipport4_telem {
60 60
61static inline bool 61static inline bool
62hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1, 62hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
63 const struct hash_ipport4_elem *ip2) 63 const struct hash_ipport4_elem *ip2,
64 u32 *multi)
64{ 65{
65 return ip1->ip == ip2->ip && 66 return ip1->ip == ip2->ip &&
66 ip1->port == ip2->port && 67 ip1->port == ip2->port &&
@@ -276,7 +277,8 @@ struct hash_ipport6_telem {
276 277
277static inline bool 278static inline bool
278hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1, 279hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
279 const struct hash_ipport6_elem *ip2) 280 const struct hash_ipport6_elem *ip2,
281 u32 *multi)
280{ 282{
281 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 283 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
282 ip1->port == ip2->port && 284 ip1->port == ip2->port &&
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c
index 96525f529a54..fb90e344e907 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportip.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportip.c
@@ -62,7 +62,8 @@ struct hash_ipportip4_telem {
62 62
63static inline bool 63static inline bool
64hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1, 64hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
65 const struct hash_ipportip4_elem *ip2) 65 const struct hash_ipportip4_elem *ip2,
66 u32 *multi)
66{ 67{
67 return ip1->ip == ip2->ip && 68 return ip1->ip == ip2->ip &&
68 ip1->ip2 == ip2->ip2 && 69 ip1->ip2 == ip2->ip2 &&
@@ -286,7 +287,8 @@ struct hash_ipportip6_telem {
286 287
287static inline bool 288static inline bool
288hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1, 289hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
289 const struct hash_ipportip6_elem *ip2) 290 const struct hash_ipportip6_elem *ip2,
291 u32 *multi)
290{ 292{
291 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 293 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
292 ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 && 294 ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
index d2d6ab89f087..deb3e3dfa5fc 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -62,7 +62,8 @@ struct hash_ipportnet4_telem {
62 62
63static inline bool 63static inline bool
64hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1, 64hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
65 const struct hash_ipportnet4_elem *ip2) 65 const struct hash_ipportnet4_elem *ip2,
66 u32 *multi)
66{ 67{
67 return ip1->ip == ip2->ip && 68 return ip1->ip == ip2->ip &&
68 ip1->ip2 == ip2->ip2 && 69 ip1->ip2 == ip2->ip2 &&
@@ -335,7 +336,8 @@ struct hash_ipportnet6_telem {
335 336
336static inline bool 337static inline bool
337hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1, 338hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
338 const struct hash_ipportnet6_elem *ip2) 339 const struct hash_ipportnet6_elem *ip2,
340 u32 *multi)
339{ 341{
340 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 342 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
341 ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 && 343 ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c
index 2d4b1f48e8c9..60d016541c58 100644
--- a/net/netfilter/ipset/ip_set_hash_net.c
+++ b/net/netfilter/ipset/ip_set_hash_net.c
@@ -58,7 +58,8 @@ struct hash_net4_telem {
58 58
59static inline bool 59static inline bool
60hash_net4_data_equal(const struct hash_net4_elem *ip1, 60hash_net4_data_equal(const struct hash_net4_elem *ip1,
61 const struct hash_net4_elem *ip2) 61 const struct hash_net4_elem *ip2,
62 u32 *multi)
62{ 63{
63 return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr; 64 return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr;
64} 65}
@@ -249,7 +250,8 @@ struct hash_net6_telem {
249 250
250static inline bool 251static inline bool
251hash_net6_data_equal(const struct hash_net6_elem *ip1, 252hash_net6_data_equal(const struct hash_net6_elem *ip1,
252 const struct hash_net6_elem *ip2) 253 const struct hash_net6_elem *ip2,
254 u32 *multi)
253{ 255{
254 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 256 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
255 ip1->cidr == ip2->cidr; 257 ip1->cidr == ip2->cidr;
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
index 3d6c53b6211a..e13095deb50d 100644
--- a/net/netfilter/ipset/ip_set_hash_netiface.c
+++ b/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -99,7 +99,7 @@ iface_test(struct rb_root *root, const char **iface)
99 99
100 while (n) { 100 while (n) {
101 const char *d = iface_data(n); 101 const char *d = iface_data(n);
102 int res = ifname_compare(*iface, d); 102 long res = ifname_compare(*iface, d);
103 103
104 if (res < 0) 104 if (res < 0)
105 n = n->rb_left; 105 n = n->rb_left;
@@ -121,7 +121,7 @@ iface_add(struct rb_root *root, const char **iface)
121 121
122 while (*n) { 122 while (*n) {
123 char *ifname = iface_data(*n); 123 char *ifname = iface_data(*n);
124 int res = ifname_compare(*iface, ifname); 124 long res = ifname_compare(*iface, ifname);
125 125
126 p = *n; 126 p = *n;
127 if (res < 0) 127 if (res < 0)
@@ -159,31 +159,42 @@ hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b);
159 159
160/* The type variant functions: IPv4 */ 160/* The type variant functions: IPv4 */
161 161
162struct hash_netiface4_elem_hashed {
163 __be32 ip;
164 u8 physdev;
165 u8 cidr;
166 u16 padding;
167};
168
169#define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed)
170
162/* Member elements without timeout */ 171/* Member elements without timeout */
163struct hash_netiface4_elem { 172struct hash_netiface4_elem {
164 __be32 ip; 173 __be32 ip;
165 const char *iface;
166 u8 physdev; 174 u8 physdev;
167 u8 cidr; 175 u8 cidr;
168 u16 padding; 176 u16 padding;
177 const char *iface;
169}; 178};
170 179
171/* Member elements with timeout support */ 180/* Member elements with timeout support */
172struct hash_netiface4_telem { 181struct hash_netiface4_telem {
173 __be32 ip; 182 __be32 ip;
174 const char *iface;
175 u8 physdev; 183 u8 physdev;
176 u8 cidr; 184 u8 cidr;
177 u16 padding; 185 u16 padding;
186 const char *iface;
178 unsigned long timeout; 187 unsigned long timeout;
179}; 188};
180 189
181static inline bool 190static inline bool
182hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1, 191hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
183 const struct hash_netiface4_elem *ip2) 192 const struct hash_netiface4_elem *ip2,
193 u32 *multi)
184{ 194{
185 return ip1->ip == ip2->ip && 195 return ip1->ip == ip2->ip &&
186 ip1->cidr == ip2->cidr && 196 ip1->cidr == ip2->cidr &&
197 (++*multi) &&
187 ip1->physdev == ip2->physdev && 198 ip1->physdev == ip2->physdev &&
188 ip1->iface == ip2->iface; 199 ip1->iface == ip2->iface;
189} 200}
@@ -257,6 +268,7 @@ nla_put_failure:
257 268
258#define IP_SET_HASH_WITH_NETS 269#define IP_SET_HASH_WITH_NETS
259#define IP_SET_HASH_WITH_RBTREE 270#define IP_SET_HASH_WITH_RBTREE
271#define IP_SET_HASH_WITH_MULTI
260 272
261#define PF 4 273#define PF 4
262#define HOST_MASK 32 274#define HOST_MASK 32
@@ -424,29 +436,40 @@ hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b)
424 436
425/* The type variant functions: IPv6 */ 437/* The type variant functions: IPv6 */
426 438
439struct hash_netiface6_elem_hashed {
440 union nf_inet_addr ip;
441 u8 physdev;
442 u8 cidr;
443 u16 padding;
444};
445
446#define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed)
447
427struct hash_netiface6_elem { 448struct hash_netiface6_elem {
428 union nf_inet_addr ip; 449 union nf_inet_addr ip;
429 const char *iface;
430 u8 physdev; 450 u8 physdev;
431 u8 cidr; 451 u8 cidr;
432 u16 padding; 452 u16 padding;
453 const char *iface;
433}; 454};
434 455
435struct hash_netiface6_telem { 456struct hash_netiface6_telem {
436 union nf_inet_addr ip; 457 union nf_inet_addr ip;
437 const char *iface;
438 u8 physdev; 458 u8 physdev;
439 u8 cidr; 459 u8 cidr;
440 u16 padding; 460 u16 padding;
461 const char *iface;
441 unsigned long timeout; 462 unsigned long timeout;
442}; 463};
443 464
444static inline bool 465static inline bool
445hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1, 466hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
446 const struct hash_netiface6_elem *ip2) 467 const struct hash_netiface6_elem *ip2,
468 u32 *multi)
447{ 469{
448 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 470 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
449 ip1->cidr == ip2->cidr && 471 ip1->cidr == ip2->cidr &&
472 (++*multi) &&
450 ip1->physdev == ip2->physdev && 473 ip1->physdev == ip2->physdev &&
451 ip1->iface == ip2->iface; 474 ip1->iface == ip2->iface;
452} 475}
@@ -681,6 +704,7 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
681 h->maxelem = maxelem; 704 h->maxelem = maxelem;
682 get_random_bytes(&h->initval, sizeof(h->initval)); 705 get_random_bytes(&h->initval, sizeof(h->initval));
683 h->timeout = IPSET_NO_TIMEOUT; 706 h->timeout = IPSET_NO_TIMEOUT;
707 h->ahash_max = AHASH_MAX_SIZE;
684 708
685 hbits = htable_bits(hashsize); 709 hbits = htable_bits(hashsize);
686 h->table = ip_set_alloc( 710 h->table = ip_set_alloc(
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
index fe203d12f56b..8f9de7207ec9 100644
--- a/net/netfilter/ipset/ip_set_hash_netport.c
+++ b/net/netfilter/ipset/ip_set_hash_netport.c
@@ -59,7 +59,8 @@ struct hash_netport4_telem {
59 59
60static inline bool 60static inline bool
61hash_netport4_data_equal(const struct hash_netport4_elem *ip1, 61hash_netport4_data_equal(const struct hash_netport4_elem *ip1,
62 const struct hash_netport4_elem *ip2) 62 const struct hash_netport4_elem *ip2,
63 u32 *multi)
63{ 64{
64 return ip1->ip == ip2->ip && 65 return ip1->ip == ip2->ip &&
65 ip1->port == ip2->port && 66 ip1->port == ip2->port &&
@@ -300,7 +301,8 @@ struct hash_netport6_telem {
300 301
301static inline bool 302static inline bool
302hash_netport6_data_equal(const struct hash_netport6_elem *ip1, 303hash_netport6_data_equal(const struct hash_netport6_elem *ip1,
303 const struct hash_netport6_elem *ip2) 304 const struct hash_netport6_elem *ip2,
305 u32 *multi)
304{ 306{
305 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 307 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
306 ip1->port == ip2->port && 308 ip1->port == ip2->port &&