Commit ea53ac5b authored by Oliver Smith's avatar Oliver Smith Committed by Jozsef Kadlecsik

netfilter: ipset: Add hash:net,net module to kernel.

This adds a new set that provides the ability to configure pairs of
subnets. A small amount of additional handling code has been added to
the generic hash header file - this code is conditionally activated by a
preprocessor definition.
Signed-off-by: default avatarOliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>
Signed-off-by: default avatarJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
parent d9628bbe
...@@ -99,6 +99,15 @@ config IP_SET_HASH_NET ...@@ -99,6 +99,15 @@ config IP_SET_HASH_NET
To compile it as a module, choose M here. If unsure, say N. To compile it as a module, choose M here. If unsure, say N.
config IP_SET_HASH_NETNET
tristate "hash:net,net set support"
depends on IP_SET
help
This option adds the hash:net,net set type support, by which
one can store IPv4/IPv6 network address/prefix pairs in a set.
To compile it as a module, choose M here. If unsure, say N.
config IP_SET_HASH_NETPORT config IP_SET_HASH_NETPORT
tristate "hash:net,port set support" tristate "hash:net,port set support"
depends on IP_SET depends on IP_SET
......
...@@ -20,6 +20,7 @@ obj-$(CONFIG_IP_SET_HASH_IPPORTNET) += ip_set_hash_ipportnet.o ...@@ -20,6 +20,7 @@ obj-$(CONFIG_IP_SET_HASH_IPPORTNET) += ip_set_hash_ipportnet.o
obj-$(CONFIG_IP_SET_HASH_NET) += ip_set_hash_net.o obj-$(CONFIG_IP_SET_HASH_NET) += ip_set_hash_net.o
obj-$(CONFIG_IP_SET_HASH_NETPORT) += ip_set_hash_netport.o obj-$(CONFIG_IP_SET_HASH_NETPORT) += ip_set_hash_netport.o
obj-$(CONFIG_IP_SET_HASH_NETIFACE) += ip_set_hash_netiface.o obj-$(CONFIG_IP_SET_HASH_NETIFACE) += ip_set_hash_netiface.o
obj-$(CONFIG_IP_SET_HASH_NETNET) += ip_set_hash_netnet.o
# list types # list types
obj-$(CONFIG_IP_SET_LIST_SET) += ip_set_list_set.o obj-$(CONFIG_IP_SET_LIST_SET) += ip_set_list_set.o
...@@ -142,11 +142,16 @@ hbucket_elem_add(struct hbucket *n, u8 ahash_max, size_t dsize) ...@@ -142,11 +142,16 @@ hbucket_elem_add(struct hbucket *n, u8 ahash_max, size_t dsize)
} }
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
#if IPSET_NET_COUNT > 1
#define __CIDR(cidr, i) (cidr[i])
#else
#define __CIDR(cidr, i) (cidr)
#endif
#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 entry */
#define CIDR(cidr) (cidr + 1) #define CIDR(cidr, i) (__CIDR(cidr, i) + 1)
#else #else
#define CIDR(cidr) (cidr) #define CIDR(cidr, i) (__CIDR(cidr, i))
#endif #endif
#define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128) #define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128)
...@@ -210,6 +215,7 @@ hbucket_elem_add(struct hbucket *n, u8 ahash_max, size_t dsize) ...@@ -210,6 +215,7 @@ hbucket_elem_add(struct hbucket *n, u8 ahash_max, size_t dsize)
#define mtype_do_data_match(d) 1 #define mtype_do_data_match(d) 1
#endif #endif
#define mtype_data_set_flags IPSET_TOKEN(MTYPE, _data_set_flags) #define mtype_data_set_flags IPSET_TOKEN(MTYPE, _data_set_flags)
#define mtype_data_reset_elem IPSET_TOKEN(MTYPE, _data_reset_elem)
#define mtype_data_reset_flags IPSET_TOKEN(MTYPE, _data_reset_flags) #define mtype_data_reset_flags IPSET_TOKEN(MTYPE, _data_reset_flags)
#define mtype_data_netmask IPSET_TOKEN(MTYPE, _data_netmask) #define mtype_data_netmask IPSET_TOKEN(MTYPE, _data_netmask)
#define mtype_data_list IPSET_TOKEN(MTYPE, _data_list) #define mtype_data_list IPSET_TOKEN(MTYPE, _data_list)
...@@ -461,6 +467,9 @@ mtype_expire(struct ip_set *set, struct htype *h, u8 nets_length, size_t dsize) ...@@ -461,6 +467,9 @@ mtype_expire(struct ip_set *set, struct htype *h, u8 nets_length, size_t dsize)
struct mtype_elem *data; struct mtype_elem *data;
u32 i; u32 i;
int j; int j;
#ifdef IP_SET_HASH_WITH_NETS
u8 k;
#endif
rcu_read_lock_bh(); rcu_read_lock_bh();
t = rcu_dereference_bh(h->table); t = rcu_dereference_bh(h->table);
...@@ -471,8 +480,9 @@ mtype_expire(struct ip_set *set, struct htype *h, u8 nets_length, size_t dsize) ...@@ -471,8 +480,9 @@ mtype_expire(struct ip_set *set, struct htype *h, u8 nets_length, size_t dsize)
if (ip_set_timeout_expired(ext_timeout(data, set))) { if (ip_set_timeout_expired(ext_timeout(data, set))) {
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
mtype_del_cidr(h, CIDR(data->cidr), for (k = 0; k < IPSET_NET_COUNT; k++)
nets_length, 0); mtype_del_cidr(h, CIDR(data->cidr, k),
nets_length, k);
#endif #endif
ip_set_ext_destroy(set, data); ip_set_ext_destroy(set, data);
if (j != n->pos - 1) if (j != n->pos - 1)
...@@ -658,8 +668,12 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, ...@@ -658,8 +668,12 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
/* Fill out reused slot */ /* Fill out reused slot */
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
mtype_del_cidr(h, CIDR(data->cidr), NLEN(set->family), 0); for (i = 0; i < IPSET_NET_COUNT; i++) {
mtype_add_cidr(h, CIDR(d->cidr), NLEN(set->family), 0); mtype_del_cidr(h, CIDR(data->cidr, i),
NLEN(set->family), i);
mtype_add_cidr(h, CIDR(d->cidr, i),
NLEN(set->family), i);
}
#endif #endif
ip_set_ext_destroy(set, data); ip_set_ext_destroy(set, data);
} else { } else {
...@@ -673,7 +687,9 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, ...@@ -673,7 +687,9 @@ 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
mtype_add_cidr(h, CIDR(d->cidr), NLEN(set->family), 0); for (i = 0; i < IPSET_NET_COUNT; i++)
mtype_add_cidr(h, CIDR(d->cidr, i), NLEN(set->family),
i);
#endif #endif
h->elements++; h->elements++;
} }
...@@ -704,6 +720,9 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, ...@@ -704,6 +720,9 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
struct mtype_elem *data; struct mtype_elem *data;
struct hbucket *n; struct hbucket *n;
int i, ret = -IPSET_ERR_EXIST; int i, ret = -IPSET_ERR_EXIST;
#ifdef IP_SET_HASH_WITH_NETS
u8 j;
#endif
u32 key, multi = 0; u32 key, multi = 0;
rcu_read_lock_bh(); rcu_read_lock_bh();
...@@ -725,7 +744,9 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, ...@@ -725,7 +744,9 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
n->pos--; n->pos--;
h->elements--; h->elements--;
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
mtype_del_cidr(h, CIDR(d->cidr), NLEN(set->family), 0); for (j = 0; j < IPSET_NET_COUNT; j++)
mtype_del_cidr(h, CIDR(d->cidr, j), NLEN(set->family),
j);
#endif #endif
ip_set_ext_destroy(set, data); ip_set_ext_destroy(set, data);
if (n->pos + AHASH_INIT_SIZE < n->size) { if (n->pos + AHASH_INIT_SIZE < n->size) {
...@@ -772,13 +793,26 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d, ...@@ -772,13 +793,26 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d,
struct htable *t = rcu_dereference_bh(h->table); struct htable *t = rcu_dereference_bh(h->table);
struct hbucket *n; struct hbucket *n;
struct mtype_elem *data; struct mtype_elem *data;
#if IPSET_NET_COUNT == 2
struct mtype_elem orig = *d;
int i, j = 0, k;
#else
int i, j = 0; int i, j = 0;
#endif
u32 key, multi = 0; u32 key, multi = 0;
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].nets[0] && !multi; j++) {
#if IPSET_NET_COUNT == 2
mtype_data_reset_elem(d, &orig);
mtype_data_netmask(d, h->nets[j].cidr[0], false);
for (k = 0; k < nets_length && h->nets[k].nets[1] && !multi;
k++) {
mtype_data_netmask(d, h->nets[k].cidr[1], true);
#else
mtype_data_netmask(d, h->nets[j].cidr[0]); mtype_data_netmask(d, h->nets[j].cidr[0]);
#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);
for (i = 0; i < n->pos; i++) { for (i = 0; i < n->pos; i++) {
...@@ -798,6 +832,9 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d, ...@@ -798,6 +832,9 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d,
return mtype_data_match(data, ext, return mtype_data_match(data, ext,
mext, set, flags); mext, set, flags);
} }
#if IPSET_NET_COUNT == 2
}
#endif
} }
return 0; return 0;
} }
...@@ -821,7 +858,10 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext, ...@@ -821,7 +858,10 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
/* 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 */
if (CIDR(d->cidr) == SET_HOST_MASK(set->family)) { for (i = 0; i < IPSET_NET_COUNT; i++)
if (CIDR(d->cidr, i) != SET_HOST_MASK(set->family))
break;
if (i == IPSET_NET_COUNT) {
ret = mtype_test_cidrs(set, d, ext, mext, flags); ret = mtype_test_cidrs(set, d, ext, mext, flags);
goto out; goto out;
} }
......
This diff is collapsed.
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