diff options
| author | Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa> | 2013-09-20 04:13:53 -0400 |
|---|---|---|
| committer | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2013-09-30 15:33:28 -0400 |
| commit | ea53ac5b630e813aec20c7cdcfe511daca70dee4 (patch) | |
| tree | c9263e919fb0352932b25f1b7ad56794476cc8c4 | |
| parent | d9628bbeca888fd1f9a9c57864dd90b7d25954e0 (diff) | |
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: Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
| -rw-r--r-- | net/netfilter/ipset/Kconfig | 9 | ||||
| -rw-r--r-- | net/netfilter/ipset/Makefile | 1 | ||||
| -rw-r--r-- | net/netfilter/ipset/ip_set_hash_gen.h | 58 | ||||
| -rw-r--r-- | net/netfilter/ipset/ip_set_hash_netnet.c | 482 |
4 files changed, 541 insertions, 9 deletions
diff --git a/net/netfilter/ipset/Kconfig b/net/netfilter/ipset/Kconfig index fd2c14b6c51b..9119f658a69b 100644 --- a/net/netfilter/ipset/Kconfig +++ b/net/netfilter/ipset/Kconfig | |||
| @@ -99,6 +99,15 @@ config IP_SET_HASH_NET | |||
| 99 | 99 | ||
| 100 | To compile it as a module, choose M here. If unsure, say N. | 100 | To compile it as a module, choose M here. If unsure, say N. |
| 101 | 101 | ||
| 102 | config IP_SET_HASH_NETNET | ||
| 103 | tristate "hash:net,net set support" | ||
| 104 | depends on IP_SET | ||
| 105 | help | ||
| 106 | This option adds the hash:net,net set type support, by which | ||
| 107 | one can store IPv4/IPv6 network address/prefix pairs in a set. | ||
| 108 | |||
| 109 | To compile it as a module, choose M here. If unsure, say N. | ||
| 110 | |||
| 102 | config IP_SET_HASH_NETPORT | 111 | config IP_SET_HASH_NETPORT |
| 103 | tristate "hash:net,port set support" | 112 | tristate "hash:net,port set support" |
| 104 | depends on IP_SET | 113 | depends on IP_SET |
diff --git a/net/netfilter/ipset/Makefile b/net/netfilter/ipset/Makefile index 6e965ecd5444..43eef7a19e3c 100644 --- a/net/netfilter/ipset/Makefile +++ b/net/netfilter/ipset/Makefile | |||
| @@ -20,6 +20,7 @@ obj-$(CONFIG_IP_SET_HASH_IPPORTNET) += ip_set_hash_ipportnet.o | |||
| 20 | obj-$(CONFIG_IP_SET_HASH_NET) += ip_set_hash_net.o | 20 | obj-$(CONFIG_IP_SET_HASH_NET) += ip_set_hash_net.o |
| 21 | obj-$(CONFIG_IP_SET_HASH_NETPORT) += ip_set_hash_netport.o | 21 | obj-$(CONFIG_IP_SET_HASH_NETPORT) += ip_set_hash_netport.o |
| 22 | obj-$(CONFIG_IP_SET_HASH_NETIFACE) += ip_set_hash_netiface.o | 22 | obj-$(CONFIG_IP_SET_HASH_NETIFACE) += ip_set_hash_netiface.o |
| 23 | obj-$(CONFIG_IP_SET_HASH_NETNET) += ip_set_hash_netnet.o | ||
| 23 | 24 | ||
| 24 | # list types | 25 | # list types |
| 25 | obj-$(CONFIG_IP_SET_LIST_SET) += ip_set_list_set.o | 26 | obj-$(CONFIG_IP_SET_LIST_SET) += ip_set_list_set.o |
diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h index 3c26e5b946f5..6bd2eef4f5d0 100644 --- a/net/netfilter/ipset/ip_set_hash_gen.h +++ b/net/netfilter/ipset/ip_set_hash_gen.h | |||
| @@ -142,11 +142,16 @@ hbucket_elem_add(struct hbucket *n, u8 ahash_max, size_t dsize) | |||
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | #ifdef IP_SET_HASH_WITH_NETS | 144 | #ifdef IP_SET_HASH_WITH_NETS |
| 145 | #if IPSET_NET_COUNT > 1 | ||
| 146 | #define __CIDR(cidr, i) (cidr[i]) | ||
| 147 | #else | ||
| 148 | #define __CIDR(cidr, i) (cidr) | ||
| 149 | #endif | ||
| 145 | #ifdef IP_SET_HASH_WITH_NETS_PACKED | 150 | #ifdef IP_SET_HASH_WITH_NETS_PACKED |
| 146 | /* When cidr is packed with nomatch, cidr - 1 is stored in the entry */ | 151 | /* When cidr is packed with nomatch, cidr - 1 is stored in the entry */ |
| 147 | #define CIDR(cidr) (cidr + 1) | 152 | #define CIDR(cidr, i) (__CIDR(cidr, i) + 1) |
| 148 | #else | 153 | #else |
| 149 | #define CIDR(cidr) (cidr) | 154 | #define CIDR(cidr, i) (__CIDR(cidr, i)) |
| 150 | #endif | 155 | #endif |
| 151 | 156 | ||
| 152 | #define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128) | 157 | #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 | #define mtype_do_data_match(d) 1 | 215 | #define mtype_do_data_match(d) 1 |
| 211 | #endif | 216 | #endif |
| 212 | #define mtype_data_set_flags IPSET_TOKEN(MTYPE, _data_set_flags) | 217 | #define mtype_data_set_flags IPSET_TOKEN(MTYPE, _data_set_flags) |
| 218 | #define mtype_data_reset_elem IPSET_TOKEN(MTYPE, _data_reset_elem) | ||
| 213 | #define mtype_data_reset_flags IPSET_TOKEN(MTYPE, _data_reset_flags) | 219 | #define mtype_data_reset_flags IPSET_TOKEN(MTYPE, _data_reset_flags) |
| 214 | #define mtype_data_netmask IPSET_TOKEN(MTYPE, _data_netmask) | 220 | #define mtype_data_netmask IPSET_TOKEN(MTYPE, _data_netmask) |
| 215 | #define mtype_data_list IPSET_TOKEN(MTYPE, _data_list) | 221 | #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 | struct mtype_elem *data; | 467 | struct mtype_elem *data; |
| 462 | u32 i; | 468 | u32 i; |
| 463 | int j; | 469 | int j; |
| 470 | #ifdef IP_SET_HASH_WITH_NETS | ||
| 471 | u8 k; | ||
| 472 | #endif | ||
| 464 | 473 | ||
| 465 | rcu_read_lock_bh(); | 474 | rcu_read_lock_bh(); |
| 466 | t = rcu_dereference_bh(h->table); | 475 | 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 | if (ip_set_timeout_expired(ext_timeout(data, set))) { | 480 | if (ip_set_timeout_expired(ext_timeout(data, set))) { |
| 472 | pr_debug("expired %u/%u\n", i, j); | 481 | pr_debug("expired %u/%u\n", i, j); |
| 473 | #ifdef IP_SET_HASH_WITH_NETS | 482 | #ifdef IP_SET_HASH_WITH_NETS |
| 474 | mtype_del_cidr(h, CIDR(data->cidr), | 483 | for (k = 0; k < IPSET_NET_COUNT; k++) |
| 475 | nets_length, 0); | 484 | mtype_del_cidr(h, CIDR(data->cidr, k), |
| 485 | nets_length, k); | ||
| 476 | #endif | 486 | #endif |
| 477 | ip_set_ext_destroy(set, data); | 487 | ip_set_ext_destroy(set, data); |
| 478 | if (j != n->pos - 1) | 488 | if (j != n->pos - 1) |
| @@ -658,8 +668,12 @@ reuse_slot: | |||
| 658 | /* Fill out reused slot */ | 668 | /* Fill out reused slot */ |
| 659 | data = ahash_data(n, j, set->dsize); | 669 | data = ahash_data(n, j, set->dsize); |
| 660 | #ifdef IP_SET_HASH_WITH_NETS | 670 | #ifdef IP_SET_HASH_WITH_NETS |
| 661 | mtype_del_cidr(h, CIDR(data->cidr), NLEN(set->family), 0); | 671 | for (i = 0; i < IPSET_NET_COUNT; i++) { |
| 662 | mtype_add_cidr(h, CIDR(d->cidr), NLEN(set->family), 0); | 672 | mtype_del_cidr(h, CIDR(data->cidr, i), |
| 673 | NLEN(set->family), i); | ||
| 674 | mtype_add_cidr(h, CIDR(d->cidr, i), | ||
| 675 | NLEN(set->family), i); | ||
| 676 | } | ||
| 663 | #endif | 677 | #endif |
| 664 | ip_set_ext_destroy(set, data); | 678 | ip_set_ext_destroy(set, data); |
| 665 | } else { | 679 | } else { |
| @@ -673,7 +687,9 @@ reuse_slot: | |||
| 673 | } | 687 | } |
| 674 | data = ahash_data(n, n->pos++, set->dsize); | 688 | data = ahash_data(n, n->pos++, set->dsize); |
| 675 | #ifdef IP_SET_HASH_WITH_NETS | 689 | #ifdef IP_SET_HASH_WITH_NETS |
| 676 | mtype_add_cidr(h, CIDR(d->cidr), NLEN(set->family), 0); | 690 | for (i = 0; i < IPSET_NET_COUNT; i++) |
| 691 | mtype_add_cidr(h, CIDR(d->cidr, i), NLEN(set->family), | ||
| 692 | i); | ||
| 677 | #endif | 693 | #endif |
| 678 | h->elements++; | 694 | h->elements++; |
| 679 | } | 695 | } |
| @@ -704,6 +720,9 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, | |||
| 704 | struct mtype_elem *data; | 720 | struct mtype_elem *data; |
| 705 | struct hbucket *n; | 721 | struct hbucket *n; |
| 706 | int i, ret = -IPSET_ERR_EXIST; | 722 | int i, ret = -IPSET_ERR_EXIST; |
| 723 | #ifdef IP_SET_HASH_WITH_NETS | ||
| 724 | u8 j; | ||
| 725 | #endif | ||
| 707 | u32 key, multi = 0; | 726 | u32 key, multi = 0; |
| 708 | 727 | ||
| 709 | rcu_read_lock_bh(); | 728 | rcu_read_lock_bh(); |
| @@ -725,7 +744,9 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, | |||
| 725 | n->pos--; | 744 | n->pos--; |
| 726 | h->elements--; | 745 | h->elements--; |
| 727 | #ifdef IP_SET_HASH_WITH_NETS | 746 | #ifdef IP_SET_HASH_WITH_NETS |
| 728 | mtype_del_cidr(h, CIDR(d->cidr), NLEN(set->family), 0); | 747 | for (j = 0; j < IPSET_NET_COUNT; j++) |
| 748 | mtype_del_cidr(h, CIDR(d->cidr, j), NLEN(set->family), | ||
| 749 | j); | ||
| 729 | #endif | 750 | #endif |
| 730 | ip_set_ext_destroy(set, data); | 751 | ip_set_ext_destroy(set, data); |
| 731 | if (n->pos + AHASH_INIT_SIZE < n->size) { | 752 | if (n->pos + AHASH_INIT_SIZE < n->size) { |
| @@ -772,13 +793,26 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d, | |||
| 772 | struct htable *t = rcu_dereference_bh(h->table); | 793 | struct htable *t = rcu_dereference_bh(h->table); |
| 773 | struct hbucket *n; | 794 | struct hbucket *n; |
| 774 | struct mtype_elem *data; | 795 | struct mtype_elem *data; |
| 796 | #if IPSET_NET_COUNT == 2 | ||
| 797 | struct mtype_elem orig = *d; | ||
| 798 | int i, j = 0, k; | ||
| 799 | #else | ||
| 775 | int i, j = 0; | 800 | int i, j = 0; |
| 801 | #endif | ||
| 776 | u32 key, multi = 0; | 802 | u32 key, multi = 0; |
| 777 | u8 nets_length = NLEN(set->family); | 803 | u8 nets_length = NLEN(set->family); |
| 778 | 804 | ||
| 779 | pr_debug("test by nets\n"); | 805 | pr_debug("test by nets\n"); |
| 780 | for (; j < nets_length && h->nets[j].nets[0] && !multi; j++) { | 806 | for (; j < nets_length && h->nets[j].nets[0] && !multi; j++) { |
| 807 | #if IPSET_NET_COUNT == 2 | ||
| 808 | mtype_data_reset_elem(d, &orig); | ||
| 809 | mtype_data_netmask(d, h->nets[j].cidr[0], false); | ||
| 810 | for (k = 0; k < nets_length && h->nets[k].nets[1] && !multi; | ||
| 811 | k++) { | ||
| 812 | mtype_data_netmask(d, h->nets[k].cidr[1], true); | ||
| 813 | #else | ||
