diff options
| author | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2014-09-15 11:36:06 -0400 |
|---|---|---|
| committer | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2014-09-15 16:20:21 -0400 |
| commit | 07034aeae152de52c29f032ca995bf9dafbe24e2 (patch) | |
| tree | 294de1cc19c3e8d0a73e0d7493d6e63146c5e01d | |
| parent | aef96193fe7b2791c4a3b19fe75426b929769471 (diff) | |
netfilter: ipset: hash:mac type added to ipset
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 | 11 | ||||
| -rw-r--r-- | net/netfilter/ipset/ip_set_hash_mac.c | 173 |
4 files changed, 193 insertions, 1 deletions
diff --git a/net/netfilter/ipset/Kconfig b/net/netfilter/ipset/Kconfig index 2f7f5c32c6f9..234a8ec82076 100644 --- a/net/netfilter/ipset/Kconfig +++ b/net/netfilter/ipset/Kconfig | |||
| @@ -99,6 +99,15 @@ config IP_SET_HASH_IPPORTNET | |||
| 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_MAC | ||
| 103 | tristate "hash:mac set support" | ||
| 104 | depends on IP_SET | ||
| 105 | help | ||
| 106 | This option adds the hash:mac set type support, by which | ||
| 107 | one can store MAC (ethernet address) elements in a set. | ||
| 108 | |||
| 109 | To compile it as a module, choose M here. If unsure, say N. | ||
| 110 | |||
| 102 | config IP_SET_HASH_NETPORTNET | 111 | config IP_SET_HASH_NETPORTNET |
| 103 | tristate "hash:net,port,net set support" | 112 | tristate "hash:net,port,net 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 231f10196cb9..3dbd5e958489 100644 --- a/net/netfilter/ipset/Makefile +++ b/net/netfilter/ipset/Makefile | |||
| @@ -18,6 +18,7 @@ obj-$(CONFIG_IP_SET_HASH_IPMARK) += ip_set_hash_ipmark.o | |||
| 18 | obj-$(CONFIG_IP_SET_HASH_IPPORT) += ip_set_hash_ipport.o | 18 | obj-$(CONFIG_IP_SET_HASH_IPPORT) += ip_set_hash_ipport.o |
| 19 | obj-$(CONFIG_IP_SET_HASH_IPPORTIP) += ip_set_hash_ipportip.o | 19 | obj-$(CONFIG_IP_SET_HASH_IPPORTIP) += ip_set_hash_ipportip.o |
| 20 | obj-$(CONFIG_IP_SET_HASH_IPPORTNET) += ip_set_hash_ipportnet.o | 20 | obj-$(CONFIG_IP_SET_HASH_IPPORTNET) += ip_set_hash_ipportnet.o |
| 21 | obj-$(CONFIG_IP_SET_HASH_MAC) += ip_set_hash_mac.o | ||
| 21 | obj-$(CONFIG_IP_SET_HASH_NET) += ip_set_hash_net.o | 22 | obj-$(CONFIG_IP_SET_HASH_NET) += ip_set_hash_net.o |
| 22 | obj-$(CONFIG_IP_SET_HASH_NETPORT) += ip_set_hash_netport.o | 23 | obj-$(CONFIG_IP_SET_HASH_NETPORT) += ip_set_hash_netport.o |
| 23 | obj-$(CONFIG_IP_SET_HASH_NETIFACE) += ip_set_hash_netiface.o | 24 | obj-$(CONFIG_IP_SET_HASH_NETIFACE) += ip_set_hash_netiface.o |
diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h index ac3a268287d9..fee7c64e4dd1 100644 --- a/net/netfilter/ipset/ip_set_hash_gen.h +++ b/net/netfilter/ipset/ip_set_hash_gen.h | |||
| @@ -1054,8 +1054,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, | |||
| 1054 | struct HTYPE *h; | 1054 | struct HTYPE *h; |
| 1055 | struct htable *t; | 1055 | struct htable *t; |
| 1056 | 1056 | ||
| 1057 | #ifndef IP_SET_PROTO_UNDEF | ||
| 1057 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) | 1058 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) |
| 1058 | return -IPSET_ERR_INVALID_FAMILY; | 1059 | return -IPSET_ERR_INVALID_FAMILY; |
| 1060 | #endif | ||
| 1059 | 1061 | ||
| 1060 | #ifdef IP_SET_HASH_WITH_MARKMASK | 1062 | #ifdef IP_SET_HASH_WITH_MARKMASK |
| 1061 | markmask = 0xffffffff; | 1063 | markmask = 0xffffffff; |
| @@ -1137,25 +1139,32 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, | |||
| 1137 | rcu_assign_pointer(h->table, t); | 1139 | rcu_assign_pointer(h->table, t); |
| 1138 | 1140 | ||
| 1139 | set->data = h; | 1141 | set->data = h; |
| 1142 | #ifndef IP_SET_PROTO_UNDEF | ||
| 1140 | if (set->family == NFPROTO_IPV4) { | 1143 | if (set->family == NFPROTO_IPV4) { |
| 1144 | #endif | ||
| 1141 | set->variant = &IPSET_TOKEN(HTYPE, 4_variant); | 1145 | set->variant = &IPSET_TOKEN(HTYPE, 4_variant); |
| 1142 | set->dsize = ip_set_elem_len(set, tb, | 1146 | set->dsize = ip_set_elem_len(set, tb, |
| 1143 | sizeof(struct IPSET_TOKEN(HTYPE, 4_elem))); | 1147 | sizeof(struct IPSET_TOKEN(HTYPE, 4_elem))); |
| 1148 | #ifndef IP_SET_PROTO_UNDEF | ||
| 1144 | } else { | 1149 | } else { |
| 1145 | set->variant = &IPSET_TOKEN(HTYPE, 6_variant); | 1150 | set->variant = &IPSET_TOKEN(HTYPE, 6_variant); |
| 1146 | set->dsize = ip_set_elem_len(set, tb, | 1151 | set->dsize = ip_set_elem_len(set, tb, |
| 1147 | sizeof(struct IPSET_TOKEN(HTYPE, 6_elem))); | 1152 | sizeof(struct IPSET_TOKEN(HTYPE, 6_elem))); |
| 1148 | } | 1153 | } |
| 1154 | #endif | ||
| 1149 | if (tb[IPSET_ATTR_TIMEOUT]) { | 1155 | if (tb[IPSET_ATTR_TIMEOUT]) { |
| 1150 | set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); | 1156 | set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
| 1157 | #ifndef IP_SET_PROTO_UNDEF | ||
| 1151 | if (set->family == NFPROTO_IPV4) | 1158 | if (set->family == NFPROTO_IPV4) |
| 1159 | #endif | ||
| 1152 | IPSET_TOKEN(HTYPE, 4_gc_init)(set, | 1160 | IPSET_TOKEN(HTYPE, 4_gc_init)(set, |
| 1153 | IPSET_TOKEN(HTYPE, 4_gc)); | 1161 | IPSET_TOKEN(HTYPE, 4_gc)); |
| 1162 | #ifndef IP_SET_PROTO_UNDEF | ||
| 1154 | else | 1163 | else |
| 1155 | IPSET_TOKEN(HTYPE, 6_gc_init)(set, | 1164 | IPSET_TOKEN(HTYPE, 6_gc_init)(set, |
| 1156 | IPSET_TOKEN(HTYPE, 6_gc)); | 1165 | IPSET_TOKEN(HTYPE, 6_gc)); |
| 1166 | #endif | ||
| 1157 | } | 1167 | } |
| 1158 | |||
| 1159 | pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", | 1168 | pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", |
| 1160 | set->name, jhash_size(t->htable_bits), | 1169 | set->name, jhash_size(t->htable_bits), |
| 1161 | t->htable_bits, h->maxelem, set->data, t); | 1170 | t->htable_bits, h->maxelem, set->data, t); |
diff --git a/net/netfilter/ipset/ip_set_hash_mac.c b/net/netfilter/ipset/ip_set_hash_mac.c new file mode 100644 index 000000000000..65690b52a4d5 --- /dev/null +++ b/net/netfilter/ipset/ip_set_hash_mac.c | |||
| @@ -0,0 +1,173 @@ | |||
| 1 | /* Copyright (C) 2014 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License version 2 as | ||
| 5 | * published by the Free Software Foundation. | ||
| 6 | */ | ||
| 7 | |||
| 8 | /* Kernel module implementing an IP set type: the hash:mac type */ | ||
| 9 | |||
| 10 | #include <linux/jhash.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/etherdevice.h> | ||
| 13 | #include <linux/skbuff.h> | ||
| 14 | #include <linux/errno.h> | ||
| 15 | #include <linux/if_ether.h> | ||
| 16 | #include <net/netlink.h> | ||
| 17 | |||
| 18 | #include <linux/netfilter.h> | ||
| 19 | #include <linux/netfilter/ipset/ip_set.h> | ||
| 20 | #include <linux/netfilter/ipset/ip_set_hash.h> | ||
| 21 | |||
| 22 | #define IPSET_TYPE_REV_MIN 0 | ||
| 23 | #define IPSET_TYPE_REV_MAX 0 | ||
| 24 | |||
| 25 | MODULE_LICENSE("GPL"); | ||
| 26 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | ||
| 27 | IP_SET_MODULE_DESC("hash:mac", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX); | ||
| 28 | MODULE_ALIAS("ip_set_hash:mac"); | ||
| 29 | |||
| 30 | /* Type specific function prefix */ | ||
| 31 | #define HTYPE hash_mac | ||
| 32 | |||
| 33 | /* Member elements */ | ||
| 34 | struct hash_mac4_elem { | ||
| 35 | /* Zero valued IP addresses cannot be stored */ | ||
| 36 | union { | ||
| 37 | unsigned char ether[ETH_ALEN]; | ||
| 38 | __be32 foo[2]; | ||
| 39 | }; | ||
| 40 | }; | ||
| 41 | |||
| 42 | /* Common functions */ | ||
| 43 | |||
| 44 | static inline bool | ||
| 45 | hash_mac4_data_equal(const struct hash_mac4_elem *e1, | ||
| 46 | const struct hash_mac4_elem *e2, | ||
| 47 | u32 *multi) | ||
| 48 | { | ||
| 49 | return ether_addr_equal(e1->ether, e2->ether); | ||
| 50 | } | ||
| 51 | |||
| 52 | static inline bool | ||
| 53 | hash_mac4_data_list(struct sk_buff *skb, const struct hash_mac4_elem *e) | ||
| 54 | { | ||
| 55 | return nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, e->ether); | ||
| 56 | } | ||
| 57 | |||
| 58 | static inline void | ||
| 59 | hash_mac4_data_next(struct hash_mac4_elem *next, | ||
| 60 | const struct hash_mac4_elem *e) | ||
| 61 | { | ||
| 62 | } | ||
| 63 | |||
| 64 | #define MTYPE hash_mac4 | ||
| 65 | #define PF 4 | ||
| 66 | #define HOST_MASK 32 | ||
| 67 | #define IP_SET_EMIT_CREATE | ||
| 68 | #define IP_SET_PROTO_UNDEF | ||
| 69 | #include "ip_set_hash_gen.h" | ||
| 70 | |||
| 71 | /* Zero valued element is not supported */ | ||
| 72 | static const unsigned char invalid_ether[ETH_ALEN] = { 0 }; | ||
| 73 | |||
| 74 | static int | ||
| 75 | hash_mac4_kadt(struct ip_set *set, const struct sk_buff *skb, | ||
| 76 | const struct xt_action_param *par, | ||
| 77 | enum ipset_adt adt, struct ip_set_adt_opt *opt) | ||
| 78 | { | ||
| 79 | ipset_adtfn adtfn = set->variant->adt[adt]; | ||
| 80 | struct hash_mac4_elem e = { { .foo[0] = 0, .foo[1] = 0 } }; | ||
| 81 | struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); | ||
| 82 | |||
| 83 | /* MAC can be src only */ | ||
| 84 | if (!(opt->flags & IPSET_DIM_ONE_SRC)) | ||
| 85 | return 0; | ||
