Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: ipset: hash:mac type added to ipset

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>

+193 -1
+9
net/netfilter/ipset/Kconfig
··· 99 99 100 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 111 config IP_SET_HASH_NETPORTNET 103 112 tristate "hash:net,port,net set support" 104 113 depends on IP_SET
+1
net/netfilter/ipset/Makefile
··· 18 18 obj-$(CONFIG_IP_SET_HASH_IPPORT) += ip_set_hash_ipport.o 19 19 obj-$(CONFIG_IP_SET_HASH_IPPORTIP) += ip_set_hash_ipportip.o 20 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 22 obj-$(CONFIG_IP_SET_HASH_NET) += ip_set_hash_net.o 22 23 obj-$(CONFIG_IP_SET_HASH_NETPORT) += ip_set_hash_netport.o 23 24 obj-$(CONFIG_IP_SET_HASH_NETIFACE) += ip_set_hash_netiface.o
+10 -1
net/netfilter/ipset/ip_set_hash_gen.h
··· 1054 1054 struct HTYPE *h; 1055 1055 struct htable *t; 1056 1056 1057 + #ifndef IP_SET_PROTO_UNDEF 1057 1058 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) 1058 1059 return -IPSET_ERR_INVALID_FAMILY; 1060 + #endif 1059 1061 1060 1062 #ifdef IP_SET_HASH_WITH_MARKMASK 1061 1063 markmask = 0xffffffff; ··· 1139 1137 rcu_assign_pointer(h->table, t); 1140 1138 1141 1139 set->data = h; 1140 + #ifndef IP_SET_PROTO_UNDEF 1142 1141 if (set->family == NFPROTO_IPV4) { 1142 + #endif 1143 1143 set->variant = &IPSET_TOKEN(HTYPE, 4_variant); 1144 1144 set->dsize = ip_set_elem_len(set, tb, 1145 1145 sizeof(struct IPSET_TOKEN(HTYPE, 4_elem))); 1146 + #ifndef IP_SET_PROTO_UNDEF 1146 1147 } else { 1147 1148 set->variant = &IPSET_TOKEN(HTYPE, 6_variant); 1148 1149 set->dsize = ip_set_elem_len(set, tb, 1149 1150 sizeof(struct IPSET_TOKEN(HTYPE, 6_elem))); 1150 1151 } 1152 + #endif 1151 1153 if (tb[IPSET_ATTR_TIMEOUT]) { 1152 1154 set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 1155 + #ifndef IP_SET_PROTO_UNDEF 1153 1156 if (set->family == NFPROTO_IPV4) 1157 + #endif 1154 1158 IPSET_TOKEN(HTYPE, 4_gc_init)(set, 1155 1159 IPSET_TOKEN(HTYPE, 4_gc)); 1160 + #ifndef IP_SET_PROTO_UNDEF 1156 1161 else 1157 1162 IPSET_TOKEN(HTYPE, 6_gc_init)(set, 1158 1163 IPSET_TOKEN(HTYPE, 6_gc)); 1164 + #endif 1159 1165 } 1160 - 1161 1166 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", 1162 1167 set->name, jhash_size(t->htable_bits), 1163 1168 t->htable_bits, h->maxelem, set->data, t);
+173
net/netfilter/ipset/ip_set_hash_mac.c
··· 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; 86 + 87 + if (skb_mac_header(skb) < skb->head || 88 + (skb_mac_header(skb) + ETH_HLEN) > skb->data) 89 + return -EINVAL; 90 + 91 + memcpy(e.ether, eth_hdr(skb)->h_source, ETH_ALEN); 92 + if (memcmp(e.ether, invalid_ether, ETH_ALEN) == 0) 93 + return -EINVAL; 94 + return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 95 + } 96 + 97 + static int 98 + hash_mac4_uadt(struct ip_set *set, struct nlattr *tb[], 99 + enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 100 + { 101 + ipset_adtfn adtfn = set->variant->adt[adt]; 102 + struct hash_mac4_elem e = { { .foo[0] = 0, .foo[1] = 0 } }; 103 + struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 104 + int ret; 105 + 106 + if (unlikely(!tb[IPSET_ATTR_ETHER] || 107 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 108 + !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 109 + !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) || 110 + !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) || 111 + !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) || 112 + !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE))) 113 + return -IPSET_ERR_PROTOCOL; 114 + 115 + if (tb[IPSET_ATTR_LINENO]) 116 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 117 + 118 + ret = ip_set_get_extensions(set, tb, &ext); 119 + if (ret) 120 + return ret; 121 + memcpy(e.ether, nla_data(tb[IPSET_ATTR_ETHER]), ETH_ALEN); 122 + if (memcmp(e.ether, invalid_ether, ETH_ALEN) == 0) 123 + return -IPSET_ERR_HASH_ELEM; 124 + 125 + return adtfn(set, &e, &ext, &ext, flags); 126 + } 127 + 128 + static struct ip_set_type hash_mac_type __read_mostly = { 129 + .name = "hash:mac", 130 + .protocol = IPSET_PROTOCOL, 131 + .features = IPSET_TYPE_MAC, 132 + .dimension = IPSET_DIM_ONE, 133 + .family = NFPROTO_UNSPEC, 134 + .revision_min = IPSET_TYPE_REV_MIN, 135 + .revision_max = IPSET_TYPE_REV_MAX, 136 + .create = hash_mac_create, 137 + .create_policy = { 138 + [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 139 + [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 140 + [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 141 + [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 142 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 143 + [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 144 + }, 145 + .adt_policy = { 146 + [IPSET_ATTR_ETHER] = { .type = NLA_BINARY, 147 + .len = ETH_ALEN }, 148 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 149 + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 150 + [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 151 + [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 152 + [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 153 + [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 }, 154 + [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 }, 155 + [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 }, 156 + }, 157 + .me = THIS_MODULE, 158 + }; 159 + 160 + static int __init 161 + hash_mac_init(void) 162 + { 163 + return ip_set_type_register(&hash_mac_type); 164 + } 165 + 166 + static void __exit 167 + hash_mac_fini(void) 168 + { 169 + ip_set_type_unregister(&hash_mac_type); 170 + } 171 + 172 + module_init(hash_mac_init); 173 + module_exit(hash_mac_fini);