aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2014-09-15 11:36:06 -0400
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2014-09-15 16:20:21 -0400
commit07034aeae152de52c29f032ca995bf9dafbe24e2 (patch)
tree294de1cc19c3e8d0a73e0d7493d6e63146c5e01d
parentaef96193fe7b2791c4a3b19fe75426b929769471 (diff)
netfilter: ipset: hash:mac type added to ipset
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
-rw-r--r--net/netfilter/ipset/Kconfig9
-rw-r--r--net/netfilter/ipset/Makefile1
-rw-r--r--net/netfilter/ipset/ip_set_hash_gen.h11
-rw-r--r--net/netfilter/ipset/ip_set_hash_mac.c173
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
102config 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
102config IP_SET_HASH_NETPORTNET 111config 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
18obj-$(CONFIG_IP_SET_HASH_IPPORT) += ip_set_hash_ipport.o 18obj-$(CONFIG_IP_SET_HASH_IPPORT) += ip_set_hash_ipport.o
19obj-$(CONFIG_IP_SET_HASH_IPPORTIP) += ip_set_hash_ipportip.o 19obj-$(CONFIG_IP_SET_HASH_IPPORTIP) += ip_set_hash_ipportip.o
20obj-$(CONFIG_IP_SET_HASH_IPPORTNET) += ip_set_hash_ipportnet.o 20obj-$(CONFIG_IP_SET_HASH_IPPORTNET) += ip_set_hash_ipportnet.o
21obj-$(CONFIG_IP_SET_HASH_MAC) += ip_set_hash_mac.o
21obj-$(CONFIG_IP_SET_HASH_NET) += ip_set_hash_net.o 22obj-$(CONFIG_IP_SET_HASH_NET) += ip_set_hash_net.o
22obj-$(CONFIG_IP_SET_HASH_NETPORT) += ip_set_hash_netport.o 23obj-$(CONFIG_IP_SET_HASH_NETPORT) += ip_set_hash_netport.o
23obj-$(CONFIG_IP_SET_HASH_NETIFACE) += ip_set_hash_netiface.o 24obj-$(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
25MODULE_LICENSE("GPL");
26MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
27IP_SET_MODULE_DESC("hash:mac", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
28MODULE_ALIAS("ip_set_hash:mac");
29
30/* Type specific function prefix */
31#define HTYPE hash_mac
32
33/* Member elements */
34struct 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
44static inline bool
45hash_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
52static inline bool
53hash_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
58static inline void
59hash_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 */
72static const unsigned char invalid_ether[ETH_ALEN] = { 0 };
73
74static int
75hash_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
97static int
98hash_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
128static 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
160static int __init
161hash_mac_init(void)
162{
163 return ip_set_type_register(&hash_mac_type);
164}
165
166static void __exit
167hash_mac_fini(void)
168{
169 ip_set_type_unregister(&hash_mac_type);
170}
171
172module_init(hash_mac_init);
173module_exit(hash_mac_fini);