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 REVISION_MIN	0
29#define REVISION_MAX	1	/* Counter support added */
30
31MODULE_LICENSE("GPL");
32MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
33IP_SET_MODULE_DESC("bitmap:ip,mac", REVISION_MIN, REVISION_MAX);
34MODULE_ALIAS("ip_set_bitmap:ip,mac");
35
36#define MTYPE		bitmap_ipmac
37#define IP_SET_BITMAP_STORED_TIMEOUT
38
39enum {
40	MAC_UNSET,		/* element is set, without MAC */
41	MAC_FILLED,		/* element is set with MAC */
42};
43
44/* Type structure */
45struct bitmap_ipmac {
46	void *members;		/* the set members */
47	void *extensions;	/* MAC + data extensions */
48	u32 first_ip;		/* host byte order, included in range */
49	u32 last_ip;		/* host byte order, included in range */
50	u32 elements;		/* number of max elements in the set */
51	u32 timeout;		/* timeout value */
52	struct timer_list gc;	/* garbage collector */
53	size_t memsize;		/* members size */
54	size_t dsize;		/* size of element */
55	size_t offset[IPSET_OFFSET_MAX]; /* Offsets to extensions */
56};
57
58/* ADT structure for generic function args */
59struct bitmap_ipmac_adt_elem {
60	u16 id;
61	unsigned char *ether;
62};
63
64struct bitmap_ipmac_elem {
65	unsigned char ether[ETH_ALEN];
66	unsigned char filled;
67} __attribute__ ((aligned));
68
69static inline u32
70ip_to_id(const struct bitmap_ipmac *m, u32 ip)
71{
72	return ip - m->first_ip;
73}
74
75static inline struct bitmap_ipmac_elem *
76get_elem(void *extensions, u16 id, size_t dsize)
77{
78	return (struct bitmap_ipmac_elem *)(extensions + id * dsize);
79}
80
81/* Common functions */
82
83static inline int
84bitmap_ipmac_do_test(const struct bitmap_ipmac_adt_elem *e,
85		     const struct bitmap_ipmac *map)
86{
87	const struct bitmap_ipmac_elem *elem;
88
89	if (!test_bit(e->id, map->members))
90		return 0;
91	elem = get_elem(map->extensions, e->id, map->dsize);
92	if (elem->filled == MAC_FILLED)
93		return e->ether == NULL ||
94		       ether_addr_equal(e->ether, elem->ether);
95	/* Trigger kernel to fill out the ethernet address */
96	return -EAGAIN;
97}
98
99static inline int
100bitmap_ipmac_gc_test(u16 id, const struct bitmap_ipmac *map)
101{
102	const struct bitmap_ipmac_elem *elem;
103
104	if (!test_bit(id, map->members))
105		return 0;
106	elem = get_elem(map->extensions, id, map->dsize);
107	/* Timer not started for the incomplete elements */
108	return elem->filled == MAC_FILLED;
109}
110
111static inline int
112bitmap_ipmac_is_filled(const struct bitmap_ipmac_elem *elem)
113{
114	return elem->filled == MAC_FILLED;
115}
116
117static inline int
118bitmap_ipmac_add_timeout(unsigned long *timeout,
119			 const struct bitmap_ipmac_adt_elem *e,
120			 const struct ip_set_ext *ext,
121			 struct bitmap_ipmac *map, int mode)
122{
123	u32 t = ext->timeout;
124
125	if (mode == IPSET_ADD_START_STORED_TIMEOUT) {
126		if (t == map->timeout)
127			/* Timeout was not specified, get stored one */
128			t = *timeout;
129		ip_set_timeout_set(timeout, t);
130	} else {
131		/* If MAC is unset yet, we store plain timeout value
132		 * because the timer is not activated yet
133		 * and we can reuse it later when MAC is filled out,
134		 * possibly by the kernel */
135		if (e->ether)
136			ip_set_timeout_set(timeout, t);
137		else
138			*timeout = t;
139	}
140	return 0;
141}
142
143static inline int
144bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
145		    struct bitmap_ipmac *map, u32 flags)
146{
147	struct bitmap_ipmac_elem *elem;
148
149	elem = get_elem(map->extensions, e->id, map->dsize);
150	if (test_and_set_bit(e->id, map->members)) {
151		if (elem->filled == MAC_FILLED) {
152			if (e->ether && (flags & IPSET_FLAG_EXIST))
153				memcpy(elem->ether, e->ether, ETH_ALEN);
154			return IPSET_ADD_FAILED;
155		} else if (!e->ether)
156			/* Already added without ethernet address */
157			return IPSET_ADD_FAILED;
158		/* Fill the MAC address and trigger the timer activation */
159		memcpy(elem->ether, e->ether, ETH_ALEN);
160		elem->filled = MAC_FILLED;
161		return IPSET_ADD_START_STORED_TIMEOUT;
162	} else if (e->ether) {
163		/* We can store MAC too */
164		memcpy(elem->ether, e->ether, ETH_ALEN);
165		elem->filled = MAC_FILLED;
166		return 0;
167	} else {
168		elem->filled = MAC_UNSET;
169		/* MAC is not stored yet, don't start timer */
170		return IPSET_ADD_STORE_PLAIN_TIMEOUT;
171	}
172}
173
174static inline int
175bitmap_ipmac_do_del(const struct bitmap_ipmac_adt_elem *e,
176		    struct bitmap_ipmac *map)
177{
178	return !test_and_clear_bit(e->id, map->members);
179}
180
181static inline unsigned long
182ip_set_timeout_stored(struct bitmap_ipmac *map, u32 id, unsigned long *timeout)
183{
184	const struct bitmap_ipmac_elem *elem =
185		get_elem(map->extensions, id, map->dsize);
186
187	return elem->filled == MAC_FILLED ? ip_set_timeout_get(timeout) :
188					    *timeout;
189}
190
191static inline int
192bitmap_ipmac_do_list(struct sk_buff *skb, const struct bitmap_ipmac *map,
193		     u32 id)
194{
195	const struct bitmap_ipmac_elem *elem =
196		get_elem(map->extensions, id, map->dsize);
197
198	return nla_put_ipaddr4(skb, IPSET_ATTR_IP,
199			       htonl(map->first_ip + id)) ||
200	       (elem->filled == MAC_FILLED &&
201		nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, elem->ether));
202}
203
204static inline int
205bitmap_ipmac_do_head(struct sk_buff *skb, const struct bitmap_ipmac *map)
206{
207	return nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) ||
208	       nla_put_ipaddr4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
209}
210
211static int
212bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
213		  const struct xt_action_param *par,
214		  enum ipset_adt adt, struct ip_set_adt_opt *opt)
215{
216	struct bitmap_ipmac *map = set->data;
217	ipset_adtfn adtfn = set->variant->adt[adt];
218	struct bitmap_ipmac_adt_elem e = {};
219	struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, map);
220	u32 ip;
221
222	/* MAC can be src only */
223	if (!(opt->flags & IPSET_DIM_TWO_SRC))
224		return 0;
225
226	ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
227	if (ip < map->first_ip || ip > map->last_ip)
228		return -IPSET_ERR_BITMAP_RANGE;
229
230	/* Backward compatibility: we don't check the second flag */
231	if (skb_mac_header(skb) < skb->head ||
232	    (skb_mac_header(skb) + ETH_HLEN) > skb->data)
233		return -EINVAL;
234
235	e.id = ip_to_id(map, ip);
236	e.ether = eth_hdr(skb)->h_source;
237
238	return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
239}
240
241static int
242bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
243		  enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
244{
245	const struct bitmap_ipmac *map = set->data;
246	ipset_adtfn adtfn = set->variant->adt[adt];
247	struct bitmap_ipmac_adt_elem e = {};
248	struct ip_set_ext ext = IP_SET_INIT_UEXT(map);
249	u32 ip;
250	int ret = 0;
251
252	if (unlikely(!tb[IPSET_ATTR_IP] ||
253		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
254		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
255		     !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES)))
256		return -IPSET_ERR_PROTOCOL;
257
258	if (tb[IPSET_ATTR_LINENO])
259		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
260
261	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
262	      ip_set_get_extensions(set, tb, &ext);
263	if (ret)
264		return ret;
265
266	if (ip < map->first_ip || ip > map->last_ip)
267		return -IPSET_ERR_BITMAP_RANGE;
268
269	e.id = ip_to_id(map, ip);
270	if (tb[IPSET_ATTR_ETHER])
271		e.ether = nla_data(tb[IPSET_ATTR_ETHER]);
272	else
273		e.ether = NULL;
274
275	ret = adtfn(set, &e, &ext, &ext, flags);
276
277	return ip_set_eexist(ret, flags) ? 0 : ret;
278}
279
280static bool
281bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
282{
283	const struct bitmap_ipmac *x = a->data;
284	const struct bitmap_ipmac *y = b->data;
285
286	return x->first_ip == y->first_ip &&
287	       x->last_ip == y->last_ip &&
288	       x->timeout == y->timeout &&
289	       a->extensions == b->extensions;
290}
291
292/* Plain variant */
293
294/* Timeout variant */
295
296struct bitmap_ipmact_elem {
297	struct {
298		unsigned char ether[ETH_ALEN];
299		unsigned char filled;
300	} __attribute__ ((aligned));
301	unsigned long timeout;
302};
303
304/* Plain variant with counter */
305
306struct bitmap_ipmacc_elem {
307	struct {
308		unsigned char ether[ETH_ALEN];
309		unsigned char filled;
310	} __attribute__ ((aligned));
311	struct ip_set_counter counter;
312};
313
314/* Timeout variant with counter */
315
316struct bitmap_ipmacct_elem {
317	struct {
318		unsigned char ether[ETH_ALEN];
319		unsigned char filled;
320	} __attribute__ ((aligned));
321	unsigned long timeout;
322	struct ip_set_counter counter;
323};
324
325#include "ip_set_bitmap_gen.h"
326
327/* Create bitmap:ip,mac type of sets */
328
329static bool
330init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
331	       u32 first_ip, u32 last_ip, u32 elements)
332{
333	map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize);
334	if (!map->members)
335		return false;
336	if (map->dsize) {
337		map->extensions = ip_set_alloc(map->dsize * elements);
338		if (!map->extensions) {
339			kfree(map->members);
340			return false;
341		}
342	}
343	map->first_ip = first_ip;
344	map->last_ip = last_ip;
345	map->elements = elements;
346	map->timeout = IPSET_NO_TIMEOUT;
347
348	set->data = map;
349	set->family = NFPROTO_IPV4;
350
351	return true;
352}
353
354static int
355bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
356		    u32 flags)
357{
358	u32 first_ip, last_ip, cadt_flags = 0;
359	u64 elements;
360	struct bitmap_ipmac *map;
361	int ret;
362
363	if (unlikely(!tb[IPSET_ATTR_IP] ||
364		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
365		     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
366		return -IPSET_ERR_PROTOCOL;
367
368	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
369	if (ret)
370		return ret;
371
372	if (tb[IPSET_ATTR_IP_TO]) {
373		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
374		if (ret)
375			return ret;
376		if (first_ip > last_ip) {
377			u32 tmp = first_ip;
378
379			first_ip = last_ip;
380			last_ip = tmp;
381		}
382	} else if (tb[IPSET_ATTR_CIDR]) {
383		u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
384
385		if (cidr >= 32)
386			return -IPSET_ERR_INVALID_CIDR;
387		ip_set_mask_from_to(first_ip, last_ip, cidr);
388	} else
389		return -IPSET_ERR_PROTOCOL;
390
391	elements = (u64)last_ip - first_ip + 1;
392
393	if (elements > IPSET_BITMAP_MAX_RANGE + 1)
394		return -IPSET_ERR_BITMAP_RANGE_SIZE;
395
396	map = kzalloc(sizeof(*map), GFP_KERNEL);
397	if (!map)
398		return -ENOMEM;
399
400	map->memsize = bitmap_bytes(0, elements - 1);
401	set->variant = &bitmap_ipmac;
402	if (tb[IPSET_ATTR_CADT_FLAGS])
403		cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
404	if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) {
405		set->extensions |= IPSET_EXT_COUNTER;
406		if (tb[IPSET_ATTR_TIMEOUT]) {
407			map->dsize = sizeof(struct bitmap_ipmacct_elem);
408			map->offset[IPSET_OFFSET_TIMEOUT] =
409				offsetof(struct bitmap_ipmacct_elem, timeout);
410			map->offset[IPSET_OFFSET_COUNTER] =
411				offsetof(struct bitmap_ipmacct_elem, counter);
412
413			if (!init_map_ipmac(set, map, first_ip, last_ip,
414					    elements)) {
415				kfree(map);
416				return -ENOMEM;
417			}
418			map->timeout = ip_set_timeout_uget(
419				tb[IPSET_ATTR_TIMEOUT]);
420			set->extensions |= IPSET_EXT_TIMEOUT;
421			bitmap_ipmac_gc_init(set, bitmap_ipmac_gc);
422		} else {
423			map->dsize = sizeof(struct bitmap_ipmacc_elem);
424			map->offset[IPSET_OFFSET_COUNTER] =
425				offsetof(struct bitmap_ipmacc_elem, counter);
426
427			if (!init_map_ipmac(set, map, first_ip, last_ip,
428					    elements)) {
429				kfree(map);
430				return -ENOMEM;
431			}
432		}
433	} else if (tb[IPSET_ATTR_TIMEOUT]) {
434		map->dsize = sizeof(struct bitmap_ipmact_elem);
435		map->offset[IPSET_OFFSET_TIMEOUT] =
436			offsetof(struct bitmap_ipmact_elem, timeout);
437
438		if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
439			kfree(map);
440			return -ENOMEM;
441		}
442		map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
443		set->extensions |= IPSET_EXT_TIMEOUT;
444		bitmap_ipmac_gc_init(set, bitmap_ipmac_gc);
445	} else {
446		map->dsize = sizeof(struct bitmap_ipmac_elem);
447
448		if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
449			kfree(map);
450			return -ENOMEM;
451		}
452		set->variant = &bitmap_ipmac;
453	}
454	return 0;
455}
456
457static struct ip_set_type bitmap_ipmac_type = {
458	.name		= "bitmap:ip,mac",
459	.protocol	= IPSET_PROTOCOL,
460	.features	= IPSET_TYPE_IP | IPSET_TYPE_MAC,
461	.dimension	= IPSET_DIM_TWO,
462	.family		= NFPROTO_IPV4,
463	.revision_min	= REVISION_MIN,
464	.revision_max	= REVISION_MAX,
465	.create		= bitmap_ipmac_create,
466	.create_policy	= {
467		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
468		[IPSET_ATTR_IP_TO]	= { .type = NLA_NESTED },
469		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
470		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
471		[IPSET_ATTR_CADT_FLAGS]	= { .type = NLA_U32 },
472	},
473	.adt_policy	= {
474		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
475		[IPSET_ATTR_ETHER]	= { .type = NLA_BINARY,
476					    .len  = ETH_ALEN },
477		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
478		[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
479		[IPSET_ATTR_BYTES]	= { .type = NLA_U64 },
480		[IPSET_ATTR_PACKETS]	= { .type = NLA_U64 },
481	},
482	.me		= THIS_MODULE,
483};
484
485static int __init
486bitmap_ipmac_init(void)
487{
488	return ip_set_type_register(&bitmap_ipmac_type);
489}
490
491static void __exit
492bitmap_ipmac_fini(void)
493{
494	ip_set_type_unregister(&bitmap_ipmac_type);
495}
496
497module_init(bitmap_ipmac_init);
498module_exit(bitmap_ipmac_fini);
499