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