]> Pileus Git - ~andy/linux/blob - net/netfilter/ipset/ip_set_bitmap_ipmac.c
Merge tag 'omap-for-v3.13/more-fixes-for-merge-window-take2' of git://git.kernel...
[~andy/linux] / net / netfilter / ipset / ip_set_bitmap_ipmac.c
1 /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
2  *                         Patrick Schaaf <bof@bof.de>
3  *                         Martin Josefsson <gandalf@wlug.westbo.se>
4  * Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10
11 /* Kernel module implementing an IP set type: the bitmap:ip,mac type */
12
13 #include <linux/module.h>
14 #include <linux/ip.h>
15 #include <linux/etherdevice.h>
16 #include <linux/skbuff.h>
17 #include <linux/errno.h>
18 #include <linux/if_ether.h>
19 #include <linux/netlink.h>
20 #include <linux/jiffies.h>
21 #include <linux/timer.h>
22 #include <net/netlink.h>
23
24 #include <linux/netfilter/ipset/pfxlen.h>
25 #include <linux/netfilter/ipset/ip_set.h>
26 #include <linux/netfilter/ipset/ip_set_bitmap.h>
27
28 #define IPSET_TYPE_REV_MIN      0
29 /*                              1          Counter support added */
30 #define IPSET_TYPE_REV_MAX      2       /* Comment support added */
31
32 MODULE_LICENSE("GPL");
33 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
34 IP_SET_MODULE_DESC("bitmap:ip,mac", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
35 MODULE_ALIAS("ip_set_bitmap:ip,mac");
36
37 #define MTYPE           bitmap_ipmac
38 #define IP_SET_BITMAP_STORED_TIMEOUT
39
40 enum {
41         MAC_UNSET,              /* element is set, without MAC */
42         MAC_FILLED,             /* element is set with MAC */
43 };
44
45 /* Type structure */
46 struct bitmap_ipmac {
47         void *members;          /* the set members */
48         void *extensions;       /* MAC + data extensions */
49         u32 first_ip;           /* host byte order, included in range */
50         u32 last_ip;            /* host byte order, included in range */
51         u32 elements;           /* number of max elements in the set */
52         size_t memsize;         /* members size */
53         struct timer_list gc;   /* garbage collector */
54 };
55
56 /* ADT structure for generic function args */
57 struct bitmap_ipmac_adt_elem {
58         u16 id;
59         unsigned char *ether;
60 };
61
62 struct bitmap_ipmac_elem {
63         unsigned char ether[ETH_ALEN];
64         unsigned char filled;
65 } __attribute__ ((aligned));
66
67 static inline u32
68 ip_to_id(const struct bitmap_ipmac *m, u32 ip)
69 {
70         return ip - m->first_ip;
71 }
72
73 static inline struct bitmap_ipmac_elem *
74 get_elem(void *extensions, u16 id, size_t dsize)
75 {
76         return (struct bitmap_ipmac_elem *)(extensions + id * dsize);
77 }
78
79 /* Common functions */
80
81 static inline int
82 bitmap_ipmac_do_test(const struct bitmap_ipmac_adt_elem *e,
83                      const struct bitmap_ipmac *map, size_t dsize)
84 {
85         const struct bitmap_ipmac_elem *elem;
86
87         if (!test_bit(e->id, map->members))
88                 return 0;
89         elem = get_elem(map->extensions, e->id, dsize);
90         if (elem->filled == MAC_FILLED)
91                 return e->ether == NULL ||
92                        ether_addr_equal(e->ether, elem->ether);
93         /* Trigger kernel to fill out the ethernet address */
94         return -EAGAIN;
95 }
96
97 static inline int
98 bitmap_ipmac_gc_test(u16 id, const struct bitmap_ipmac *map, size_t dsize)
99 {
100         const struct bitmap_ipmac_elem *elem;
101
102         if (!test_bit(id, map->members))
103                 return 0;
104         elem = get_elem(map->extensions, id, dsize);
105         /* Timer not started for the incomplete elements */
106         return elem->filled == MAC_FILLED;
107 }
108
109 static inline int
110 bitmap_ipmac_is_filled(const struct bitmap_ipmac_elem *elem)
111 {
112         return elem->filled == MAC_FILLED;
113 }
114
115 static inline int
116 bitmap_ipmac_add_timeout(unsigned long *timeout,
117                          const struct bitmap_ipmac_adt_elem *e,
118                          const struct ip_set_ext *ext, struct ip_set *set,
119                          struct bitmap_ipmac *map, int mode)
120 {
121         u32 t = ext->timeout;
122
123         if (mode == IPSET_ADD_START_STORED_TIMEOUT) {
124                 if (t == set->timeout)
125                         /* Timeout was not specified, get stored one */
126                         t = *timeout;
127                 ip_set_timeout_set(timeout, t);
128         } else {
129                 /* If MAC is unset yet, we store plain timeout value
130                  * because the timer is not activated yet
131                  * and we can reuse it later when MAC is filled out,
132                  * possibly by the kernel */
133                 if (e->ether)
134                         ip_set_timeout_set(timeout, t);
135                 else
136                         *timeout = t;
137         }
138         return 0;
139 }
140
141 static inline int
142 bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
143                     struct bitmap_ipmac *map, u32 flags, size_t dsize)
144 {
145         struct bitmap_ipmac_elem *elem;
146
147         elem = get_elem(map->extensions, e->id, dsize);
148         if (test_and_set_bit(e->id, map->members)) {
149                 if (elem->filled == MAC_FILLED) {
150                         if (e->ether && (flags & IPSET_FLAG_EXIST))
151                                 memcpy(elem->ether, e->ether, ETH_ALEN);
152                         return IPSET_ADD_FAILED;
153                 } else if (!e->ether)
154                         /* Already added without ethernet address */
155                         return IPSET_ADD_FAILED;
156                 /* Fill the MAC address and trigger the timer activation */
157                 memcpy(elem->ether, e->ether, ETH_ALEN);
158                 elem->filled = MAC_FILLED;
159                 return IPSET_ADD_START_STORED_TIMEOUT;
160         } else if (e->ether) {
161                 /* We can store MAC too */
162                 memcpy(elem->ether, e->ether, ETH_ALEN);
163                 elem->filled = MAC_FILLED;
164                 return 0;
165         } else {
166                 elem->filled = MAC_UNSET;
167                 /* MAC is not stored yet, don't start timer */
168                 return IPSET_ADD_STORE_PLAIN_TIMEOUT;
169         }
170 }
171
172 static inline int
173 bitmap_ipmac_do_del(const struct bitmap_ipmac_adt_elem *e,
174                     struct bitmap_ipmac *map)
175 {
176         return !test_and_clear_bit(e->id, map->members);
177 }
178
179 static inline int
180 bitmap_ipmac_do_list(struct sk_buff *skb, const struct bitmap_ipmac *map,
181                      u32 id, size_t dsize)
182 {
183         const struct bitmap_ipmac_elem *elem =
184                 get_elem(map->extensions, id, dsize);
185
186         return nla_put_ipaddr4(skb, IPSET_ATTR_IP,
187                                htonl(map->first_ip + id)) ||
188                (elem->filled == MAC_FILLED &&
189                 nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, elem->ether));
190 }
191
192 static inline int
193 bitmap_ipmac_do_head(struct sk_buff *skb, const struct bitmap_ipmac *map)
194 {
195         return nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) ||
196                nla_put_ipaddr4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
197 }
198
199 static int
200 bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
201                   const struct xt_action_param *par,
202                   enum ipset_adt adt, struct ip_set_adt_opt *opt)
203 {
204         struct bitmap_ipmac *map = set->data;
205         ipset_adtfn adtfn = set->variant->adt[adt];
206         struct bitmap_ipmac_adt_elem e = {};
207         struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
208         u32 ip;
209
210         /* MAC can be src only */
211         if (!(opt->flags & IPSET_DIM_TWO_SRC))
212                 return 0;
213
214         ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
215         if (ip < map->first_ip || ip > map->last_ip)
216                 return -IPSET_ERR_BITMAP_RANGE;
217
218         /* Backward compatibility: we don't check the second flag */
219         if (skb_mac_header(skb) < skb->head ||
220             (skb_mac_header(skb) + ETH_HLEN) > skb->data)
221                 return -EINVAL;
222
223         e.id = ip_to_id(map, ip);
224         e.ether = eth_hdr(skb)->h_source;
225
226         return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
227 }
228
229 static int
230 bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
231                   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
232 {
233         const struct bitmap_ipmac *map = set->data;
234         ipset_adtfn adtfn = set->variant->adt[adt];
235         struct bitmap_ipmac_adt_elem e = {};
236         struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
237         u32 ip = 0;
238         int ret = 0;
239
240         if (unlikely(!tb[IPSET_ATTR_IP] ||
241                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
242                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
243                      !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES)))
244                 return -IPSET_ERR_PROTOCOL;
245
246         if (tb[IPSET_ATTR_LINENO])
247                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
248
249         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
250               ip_set_get_extensions(set, tb, &ext);
251         if (ret)
252                 return ret;
253
254         if (ip < map->first_ip || ip > map->last_ip)
255                 return -IPSET_ERR_BITMAP_RANGE;
256
257         e.id = ip_to_id(map, ip);
258         if (tb[IPSET_ATTR_ETHER])
259                 e.ether = nla_data(tb[IPSET_ATTR_ETHER]);
260         else
261                 e.ether = NULL;
262
263         ret = adtfn(set, &e, &ext, &ext, flags);
264
265         return ip_set_eexist(ret, flags) ? 0 : ret;
266 }
267
268 static bool
269 bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
270 {
271         const struct bitmap_ipmac *x = a->data;
272         const struct bitmap_ipmac *y = b->data;
273
274         return x->first_ip == y->first_ip &&
275                x->last_ip == y->last_ip &&
276                a->timeout == b->timeout &&
277                a->extensions == b->extensions;
278 }
279
280 /* Plain variant */
281
282 #include "ip_set_bitmap_gen.h"
283
284 /* Create bitmap:ip,mac type of sets */
285
286 static bool
287 init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
288                u32 first_ip, u32 last_ip, u32 elements)
289 {
290         map->members = ip_set_alloc(map->memsize);
291         if (!map->members)
292                 return false;
293         if (set->dsize) {
294                 map->extensions = ip_set_alloc(set->dsize * elements);
295                 if (!map->extensions) {
296                         kfree(map->members);
297                         return false;
298                 }
299         }
300         map->first_ip = first_ip;
301         map->last_ip = last_ip;
302         map->elements = elements;
303         set->timeout = IPSET_NO_TIMEOUT;
304
305         set->data = map;
306         set->family = NFPROTO_IPV4;
307
308         return true;
309 }
310
311 static int
312 bitmap_ipmac_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
313                     u32 flags)
314 {
315         u32 first_ip = 0, last_ip = 0;
316         u64 elements;
317         struct bitmap_ipmac *map;
318         int ret;
319
320         if (unlikely(!tb[IPSET_ATTR_IP] ||
321                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
322                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
323                 return -IPSET_ERR_PROTOCOL;
324
325         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
326         if (ret)
327                 return ret;
328
329         if (tb[IPSET_ATTR_IP_TO]) {
330                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
331                 if (ret)
332                         return ret;
333                 if (first_ip > last_ip) {
334                         u32 tmp = first_ip;
335
336                         first_ip = last_ip;
337                         last_ip = tmp;
338                 }
339         } else if (tb[IPSET_ATTR_CIDR]) {
340                 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
341
342                 if (cidr >= 32)
343                         return -IPSET_ERR_INVALID_CIDR;
344                 ip_set_mask_from_to(first_ip, last_ip, cidr);
345         } else
346                 return -IPSET_ERR_PROTOCOL;
347
348         elements = (u64)last_ip - first_ip + 1;
349
350         if (elements > IPSET_BITMAP_MAX_RANGE + 1)
351                 return -IPSET_ERR_BITMAP_RANGE_SIZE;
352
353         map = kzalloc(sizeof(*map), GFP_KERNEL);
354         if (!map)
355                 return -ENOMEM;
356
357         map->memsize = bitmap_bytes(0, elements - 1);
358         set->variant = &bitmap_ipmac;
359         set->dsize = ip_set_elem_len(set, tb,
360                                      sizeof(struct bitmap_ipmac_elem));
361         if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
362                 kfree(map);
363                 return -ENOMEM;
364         }
365         if (tb[IPSET_ATTR_TIMEOUT]) {
366                 set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
367                 bitmap_ipmac_gc_init(set, bitmap_ipmac_gc);
368         }
369         return 0;
370 }
371
372 static struct ip_set_type bitmap_ipmac_type = {
373         .name           = "bitmap:ip,mac",
374         .protocol       = IPSET_PROTOCOL,
375         .features       = IPSET_TYPE_IP | IPSET_TYPE_MAC,
376         .dimension      = IPSET_DIM_TWO,
377         .family         = NFPROTO_IPV4,
378         .revision_min   = IPSET_TYPE_REV_MIN,
379         .revision_max   = IPSET_TYPE_REV_MAX,
380         .create         = bitmap_ipmac_create,
381         .create_policy  = {
382                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
383                 [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
384                 [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
385                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
386                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
387         },
388         .adt_policy     = {
389                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
390                 [IPSET_ATTR_ETHER]      = { .type = NLA_BINARY,
391                                             .len  = ETH_ALEN },
392                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
393                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
394                 [IPSET_ATTR_BYTES]      = { .type = NLA_U64 },
395                 [IPSET_ATTR_PACKETS]    = { .type = NLA_U64 },
396                 [IPSET_ATTR_COMMENT]    = { .type = NLA_NUL_STRING },
397         },
398         .me             = THIS_MODULE,
399 };
400
401 static int __init
402 bitmap_ipmac_init(void)
403 {
404         return ip_set_type_register(&bitmap_ipmac_type);
405 }
406
407 static void __exit
408 bitmap_ipmac_fini(void)
409 {
410         ip_set_type_unregister(&bitmap_ipmac_type);
411 }
412
413 module_init(bitmap_ipmac_init);
414 module_exit(bitmap_ipmac_fini);