Commit 25a76f34 authored by Jozsef Kadlecsik's avatar Jozsef Kadlecsik Committed by Pablo Neira Ayuso

netfilter: ipset: Simplify cidr handling for hash:*net* types

Signed-off-by: default avatarJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 59de79cf
...@@ -147,11 +147,17 @@ hbucket_elem_add(struct hbucket *n, u8 ahash_max, size_t dsize) ...@@ -147,11 +147,17 @@ hbucket_elem_add(struct hbucket *n, u8 ahash_max, size_t dsize)
#else #else
#define __CIDR(cidr, i) (cidr) #define __CIDR(cidr, i) (cidr)
#endif #endif
/* cidr + 1 is stored in net_prefixes to support /0 */
#define SCIDR(cidr, i) (__CIDR(cidr, i) + 1)
#ifdef IP_SET_HASH_WITH_NETS_PACKED #ifdef IP_SET_HASH_WITH_NETS_PACKED
/* When cidr is packed with nomatch, cidr - 1 is stored in the entry */ /* When cidr is packed with nomatch, cidr - 1 is stored in the data entry */
#define CIDR(cidr, i) (__CIDR(cidr, i) + 1) #define GCIDR(cidr, i) (__CIDR(cidr, i) + 1)
#define NCIDR(cidr) (cidr)
#else #else
#define CIDR(cidr, i) (__CIDR(cidr, i)) #define GCIDR(cidr, i) (__CIDR(cidr, i))
#define NCIDR(cidr) (cidr - 1)
#endif #endif
#define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128) #define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128)
...@@ -292,24 +298,22 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n) ...@@ -292,24 +298,22 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n)
int i, j; int i, j;
/* Add in increasing prefix order, so larger cidr first */ /* Add in increasing prefix order, so larger cidr first */
for (i = 0, j = -1; i < nets_length && h->nets[i].nets[n]; i++) { for (i = 0, j = -1; i < nets_length && h->nets[i].cidr[n]; i++) {
if (j != -1) if (j != -1)
continue; continue;
else if (h->nets[i].cidr[n] < cidr) else if (h->nets[i].cidr[n] < cidr)
j = i; j = i;
else if (h->nets[i].cidr[n] == cidr) { else if (h->nets[i].cidr[n] == cidr) {
h->nets[i].nets[n]++; h->nets[cidr - 1].nets[n]++;
return; return;
} }
} }
if (j != -1) { if (j != -1) {
for (; i > j; i--) { for (; i > j; i--)
h->nets[i].cidr[n] = h->nets[i - 1].cidr[n]; h->nets[i].cidr[n] = h->nets[i - 1].cidr[n];
h->nets[i].nets[n] = h->nets[i - 1].nets[n];
}
} }
h->nets[i].cidr[n] = cidr; h->nets[i].cidr[n] = cidr;
h->nets[i].nets[n] = 1; h->nets[cidr - 1].nets[n] = 1;
} }
static void static void
...@@ -320,16 +324,12 @@ mtype_del_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n) ...@@ -320,16 +324,12 @@ mtype_del_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n)
for (i = 0; i < nets_length; i++) { for (i = 0; i < nets_length; i++) {
if (h->nets[i].cidr[n] != cidr) if (h->nets[i].cidr[n] != cidr)
continue; continue;
if (h->nets[i].nets[n] > 1 || i == net_end || h->nets[cidr -1].nets[n]--;
h->nets[i + 1].nets[n] == 0) { if (h->nets[cidr -1].nets[n] > 0)
h->nets[i].nets[n]--;
return; return;
} for (j = i; j < net_end && h->nets[j].cidr[n]; j++)
for (j = i; j < net_end && h->nets[j].nets[n]; j++) {
h->nets[j].cidr[n] = h->nets[j + 1].cidr[n]; h->nets[j].cidr[n] = h->nets[j + 1].cidr[n];
h->nets[j].nets[n] = h->nets[j + 1].nets[n]; h->nets[j].cidr[n] = 0;
}
h->nets[j].nets[n] = 0;
return; return;
} }
} }
...@@ -486,7 +486,7 @@ mtype_expire(struct ip_set *set, struct htype *h, u8 nets_length, size_t dsize) ...@@ -486,7 +486,7 @@ mtype_expire(struct ip_set *set, struct htype *h, u8 nets_length, size_t dsize)
pr_debug("expired %u/%u\n", i, j); pr_debug("expired %u/%u\n", i, j);
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
for (k = 0; k < IPSET_NET_COUNT; k++) for (k = 0; k < IPSET_NET_COUNT; k++)
mtype_del_cidr(h, CIDR(data->cidr, k), mtype_del_cidr(h, SCIDR(data->cidr, k),
nets_length, k); nets_length, k);
#endif #endif
ip_set_ext_destroy(set, data); ip_set_ext_destroy(set, data);
...@@ -680,9 +680,9 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, ...@@ -680,9 +680,9 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
data = ahash_data(n, j, set->dsize); data = ahash_data(n, j, set->dsize);
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
for (i = 0; i < IPSET_NET_COUNT; i++) { for (i = 0; i < IPSET_NET_COUNT; i++) {
mtype_del_cidr(h, CIDR(data->cidr, i), mtype_del_cidr(h, SCIDR(data->cidr, i),
NLEN(set->family), i); NLEN(set->family), i);
mtype_add_cidr(h, CIDR(d->cidr, i), mtype_add_cidr(h, SCIDR(d->cidr, i),
NLEN(set->family), i); NLEN(set->family), i);
} }
#endif #endif
...@@ -699,7 +699,7 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, ...@@ -699,7 +699,7 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
data = ahash_data(n, n->pos++, set->dsize); data = ahash_data(n, n->pos++, set->dsize);
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
for (i = 0; i < IPSET_NET_COUNT; i++) for (i = 0; i < IPSET_NET_COUNT; i++)
mtype_add_cidr(h, CIDR(d->cidr, i), NLEN(set->family), mtype_add_cidr(h, SCIDR(d->cidr, i), NLEN(set->family),
i); i);
#endif #endif
h->elements++; h->elements++;
...@@ -760,7 +760,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, ...@@ -760,7 +760,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
h->elements--; h->elements--;
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
for (j = 0; j < IPSET_NET_COUNT; j++) for (j = 0; j < IPSET_NET_COUNT; j++)
mtype_del_cidr(h, CIDR(d->cidr, j), NLEN(set->family), mtype_del_cidr(h, SCIDR(d->cidr, j), NLEN(set->family),
j); j);
#endif #endif
ip_set_ext_destroy(set, data); ip_set_ext_destroy(set, data);
...@@ -821,15 +821,15 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d, ...@@ -821,15 +821,15 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d,
u8 nets_length = NLEN(set->family); u8 nets_length = NLEN(set->family);
pr_debug("test by nets\n"); pr_debug("test by nets\n");
for (; j < nets_length && h->nets[j].nets[0] && !multi; j++) { for (; j < nets_length && h->nets[j].cidr[0] && !multi; j++) {
#if IPSET_NET_COUNT == 2 #if IPSET_NET_COUNT == 2
mtype_data_reset_elem(d, &orig); mtype_data_reset_elem(d, &orig);
mtype_data_netmask(d, h->nets[j].cidr[0], false); mtype_data_netmask(d, NCIDR(h->nets[j].cidr[0]), false);
for (k = 0; k < nets_length && h->nets[k].nets[1] && !multi; for (k = 0; k < nets_length && h->nets[k].cidr[1] && !multi;
k++) { k++) {
mtype_data_netmask(d, h->nets[k].cidr[1], true); mtype_data_netmask(d, NCIDR(h->nets[k].cidr[1]), true);
#else #else
mtype_data_netmask(d, h->nets[j].cidr[0]); mtype_data_netmask(d, NCIDR(h->nets[j].cidr[0]));
#endif #endif
key = HKEY(d, h->initval, t->htable_bits); key = HKEY(d, h->initval, t->htable_bits);
n = hbucket(t, key); n = hbucket(t, key);
...@@ -877,7 +877,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext, ...@@ -877,7 +877,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
/* If we test an IP address and not a network address, /* If we test an IP address and not a network address,
* try all possible network sizes */ * try all possible network sizes */
for (i = 0; i < IPSET_NET_COUNT; i++) for (i = 0; i < IPSET_NET_COUNT; i++)
if (CIDR(d->cidr, i) != SET_HOST_MASK(set->family)) if (GCIDR(d->cidr, i) != SET_HOST_MASK(set->family))
break; break;
if (i == IPSET_NET_COUNT) { if (i == IPSET_NET_COUNT) {
ret = mtype_test_cidrs(set, d, ext, mext, flags); ret = mtype_test_cidrs(set, d, ext, mext, flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment