summaryrefslogtreecommitdiffstats
path: root/kernel/ip_set_bitmap_ipmac.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/ip_set_bitmap_ipmac.c')
-rw-r--r--kernel/ip_set_bitmap_ipmac.c486
1 files changed, 302 insertions, 184 deletions
diff --git a/kernel/ip_set_bitmap_ipmac.c b/kernel/ip_set_bitmap_ipmac.c
index 45335dd..d036862 100644
--- a/kernel/ip_set_bitmap_ipmac.c
+++ b/kernel/ip_set_bitmap_ipmac.c
@@ -10,8 +10,10 @@
/* Kernel module implementing an IP set type: the bitmap:ip,mac type */
+#include <linux/netfilter/ip_set_kernel.h>
#include <linux/module.h>
#include <linux/ip.h>
+#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
@@ -19,7 +21,6 @@
#include <linux/spinlock.h>
#include <linux/if_ether.h>
#include <linux/netlink.h>
-#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
#include <net/netlink.h>
@@ -40,119 +41,235 @@ enum {
MAC_UNSET, /* element is set, without MAC */
};
-/* Member element without and with timeout */
+/* Type structure */
+struct bitmap_ipmac {
+ void *members; /* the set members */
+ u32 first_ip; /* host byte order, included in range */
+ u32 last_ip; /* host byte order, included in range */
+ u32 timeout; /* timeout value */
+ struct timer_list gc; /* garbage collector */
+ size_t dsize; /* size of element */
+};
struct ipmac {
+ u32 id; /* id in array */
+ unsigned char *ether; /* ethernet address */
+};
+
+/* Member element without and with timeout */
+
+struct ipmac_elem {
unsigned char ether[ETH_ALEN];
unsigned char match;
};
-struct ipmac_timeout {
+struct ipmac_telem {
unsigned char ether[ETH_ALEN];
unsigned char match;
unsigned long timeout;
};
-struct bitmap_ipmac {
- void *members; /* the set members */
- uint32_t first_ip; /* host byte order, included in range */
- uint32_t last_ip; /* host byte order, included in range */
- uint32_t timeout; /* timeout value */
- struct timer_list gc; /* garbage collector */
- size_t elem_size; /* size of element */
-};
-
static inline void *
-bitmap_ipmac_elem(const struct bitmap_ipmac *map, uint32_t id)
+bitmap_ipmac_elem(const struct bitmap_ipmac *map, u32 id)
{
- return (void *)((char *)map->members + id * map->elem_size);
+ return (void *)((char *)map->members + id * map->dsize);
}
static inline bool
-bitmap_timeout(const struct bitmap_ipmac *map, uint32_t id)
+bitmap_timeout(const struct bitmap_ipmac *map, u32 id)
{
- const struct ipmac_timeout *elem = bitmap_ipmac_elem(map, id);
+ const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id);
return ip_set_timeout_test(elem->timeout);
}
static inline bool
-bitmap_expired(const struct bitmap_ipmac *map, uint32_t id)
+bitmap_expired(const struct bitmap_ipmac *map, u32 id)
{
- const struct ipmac_timeout *elem = bitmap_ipmac_elem(map, id);
+ const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id);
return ip_set_timeout_expired(elem->timeout);
}
static inline int
-bitmap_ipmac_exist(const struct ipmac *elem, bool with_timeout)
+bitmap_ipmac_exist(const struct ipmac_telem *elem)
{
- const struct ipmac_timeout *e = (const struct ipmac_timeout *) elem;
-
return elem->match == MAC_UNSET
|| (elem->match == MAC_FILLED
- && !(with_timeout && ip_set_timeout_expired(e->timeout)));
+ && !ip_set_timeout_expired(elem->timeout));
}
-static inline int
-bitmap_ipmac_test(const struct bitmap_ipmac *map, bool with_timeout,
- uint32_t id, const unsigned char *ether)
+/* Base variant */
+
+static int
+bitmap_ipmac_test(struct ip_set *set, void *value,
+ gfp_t gfp_flags, u32 timeout)
{
- const struct ipmac *elem = bitmap_ipmac_elem(map, id);
+ const struct bitmap_ipmac *map = set->data;
+ const struct ipmac *data = value;
+ const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
switch (elem->match) {
case MAC_UNSET:
/* Trigger kernel to fill out the ethernet address */
return -EAGAIN;
case MAC_FILLED:
- return (ether == NULL
- || memcmp(ether, elem->ether, ETH_ALEN) == 0)
- && (!with_timeout || bitmap_timeout(map, id));
+ return data->ether == NULL
+ || compare_ether_addr(data->ether, elem->ether) == 0;
}
return 0;
}
static int
-bitmap_ipmac_add(struct bitmap_ipmac *map, bool with_timeout,
- uint32_t id, const unsigned char *ether,
- uint32_t timeout)
+bitmap_ipmac_add(struct ip_set *set, void *value,
+ gfp_t gfp_flags, u32 timeout)
{
- struct ipmac *elem = bitmap_ipmac_elem(map, id);
- struct ipmac_timeout *e = (struct ipmac_timeout *) elem;
+ struct bitmap_ipmac *map = set->data;
+ const struct ipmac *data = value;
+ struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
switch (elem->match) {
case MAC_UNSET:
- if (!ether)
+ if (!data->ether)
/* Already added without ethernet address */
return -IPSET_ERR_EXIST;
/* Fill the MAC address and activate the timer */
- memcpy(elem->ether, ether, ETH_ALEN);
+ memcpy(elem->ether, data->ether, ETH_ALEN);
elem->match = MAC_FILLED;
- if (with_timeout) {
- if (timeout == map->timeout)
- /* Timeout was not specified, get stored one */
- timeout = e->timeout;
- e->timeout = ip_set_timeout_set(timeout);
+ break;
+ case MAC_FILLED:
+ return -IPSET_ERR_EXIST;
+ case MAC_EMPTY:
+ if (data->ether) {
+ memcpy(elem->ether, data->ether, ETH_ALEN);
+ elem->match = MAC_FILLED;
+ } else
+ elem->match = MAC_UNSET;
+ }
+
+ return 0;
+}
+
+static int
+bitmap_ipmac_del(struct ip_set *set, void *value,
+ gfp_t gfp_flags, u32 timeout)
+{
+ struct bitmap_ipmac *map = set->data;
+ const struct ipmac *data = value;
+ struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
+
+ if (elem->match == MAC_EMPTY)
+ return -IPSET_ERR_EXIST;
+
+ elem->match = MAC_EMPTY;
+
+ return 0;
+}
+
+static int
+bitmap_ipmac_list(struct ip_set *set,
+ struct sk_buff *skb, struct netlink_callback *cb)
+{
+ const struct bitmap_ipmac *map = set->data;
+ const struct ipmac_elem *elem;
+ struct nlattr *atd, *nested;
+ u32 id, first = cb->args[2];
+ u32 last = map->last_ip - map->first_ip;
+
+ atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
+ if (!atd)
+ return -EFAULT;
+ for (; cb->args[2] <= last; cb->args[2]++) {
+ id = cb->args[2];
+ elem = bitmap_ipmac_elem(map, id);
+ if (elem->match == MAC_EMPTY)
+ continue;
+ nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+ if (!nested) {
+ if (id == first) {
+ nla_nest_cancel(skb, atd);
+ return -EFAULT;
+ } else
+ goto nla_put_failure;
}
+ NLA_PUT_NET32(skb, IPSET_ATTR_IP,
+ htonl(map->first_ip + id));
+ if (elem->match == MAC_FILLED)
+ NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
+ elem->ether);
+ ipset_nest_end(skb, nested);
+ }
+ ipset_nest_end(skb, atd);
+ /* Set listing finished */
+ cb->args[2] = 0;
+
+ return 0;
+
+nla_put_failure:
+ nla_nest_cancel(skb, nested);
+ ipset_nest_end(skb, atd);
+ return 0;
+}
+
+/* Timeout variant */
+
+static int
+bitmap_ipmac_ttest(struct ip_set *set, void *value,
+ gfp_t gfp_flags, u32 timeout)
+{
+ const struct bitmap_ipmac *map = set->data;
+ const struct ipmac *data = value;
+ const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
+
+ switch (elem->match) {
+ case MAC_UNSET:
+ /* Trigger kernel to fill out the ethernet address */
+ return -EAGAIN;
+ case MAC_FILLED:
+ return (data->ether == NULL
+ || compare_ether_addr(data->ether, elem->ether) == 0)
+ && !bitmap_expired(map, data->id);
+ }
+ return 0;
+}
+
+static int
+bitmap_ipmac_tadd(struct ip_set *set, void *value,
+ gfp_t gfp_flags, u32 timeout)
+{
+ struct bitmap_ipmac *map = set->data;
+ const struct ipmac *data = value;
+ struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
+
+ switch (elem->match) {
+ case MAC_UNSET:
+ if (!data->ether)
+ /* Already added without ethernet address */
+ return -IPSET_ERR_EXIST;
+ /* Fill the MAC address and activate the timer */
+ memcpy(elem->ether, data->ether, ETH_ALEN);
+ elem->match = MAC_FILLED;
+ if (timeout == map->timeout)
+ /* Timeout was not specified, get stored one */
+ timeout = elem->timeout;
+ elem->timeout = ip_set_timeout_set(timeout);
break;
case MAC_FILLED:
- if (!(with_timeout && bitmap_expired(map, id)))
+ if (bitmap_expired(map, data->id))
return -IPSET_ERR_EXIST;
/* Fall through */
case MAC_EMPTY:
- if (ether) {
- memcpy(elem->ether, ether, ETH_ALEN);
+ if (data->ether) {
+ memcpy(elem->ether, data->ether, ETH_ALEN);
elem->match = MAC_FILLED;
} else
elem->match = MAC_UNSET;
- if (with_timeout) {
- /* If MAC is unset yet, we store plain timeout
- * because the timer is not activated yet
- * and we can reuse it later when MAC is filled out,
- * possibly by the kernel */
- e->timeout = ether ? ip_set_timeout_set(timeout)
- : timeout;
- }
+ /* If MAC is unset yet, we store plain timeout
+ * because the timer is not activated yet
+ * and we can reuse it later when MAC is filled out,
+ * possibly by the kernel */
+ elem->timeout = data->ether ? ip_set_timeout_set(timeout)
+ : timeout;
break;
}
@@ -160,13 +277,14 @@ bitmap_ipmac_add(struct bitmap_ipmac *map, bool with_timeout,
}
static int
-bitmap_ipmac_del(struct bitmap_ipmac *map, bool with_timeout,
- uint32_t id)
+bitmap_ipmac_tdel(struct ip_set *set, void *value,
+ gfp_t gfp_flags, u32 timeout)
{
- struct ipmac *elem = bitmap_ipmac_elem(map, id);
+ struct bitmap_ipmac *map = set->data;
+ const struct ipmac *data = value;
+ struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
- if (elem->match == MAC_EMPTY
- || (with_timeout && bitmap_expired(map, id)))
+ if (elem->match == MAC_EMPTY || bitmap_expired(map, data->id))
return -IPSET_ERR_EXIST;
elem->match = MAC_EMPTY;
@@ -175,38 +293,74 @@ bitmap_ipmac_del(struct bitmap_ipmac *map, bool with_timeout,
}
static int
+bitmap_ipmac_tlist(struct ip_set *set,
+ struct sk_buff *skb, struct netlink_callback *cb)
+{
+ const struct bitmap_ipmac *map = set->data;
+ const struct ipmac_telem *elem;
+ struct nlattr *atd, *nested;
+ u32 id, first = cb->args[2];
+ u32 timeout, last = map->last_ip - map->first_ip;
+
+ atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
+ if (!atd)
+ return -EFAULT;
+ for (; cb->args[2] <= last; cb->args[2]++) {
+ id = cb->args[2];
+ elem = bitmap_ipmac_elem(map, id);
+ if (!bitmap_ipmac_exist(elem))
+ continue;
+ nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+ if (!nested) {
+ if (id == first) {
+ nla_nest_cancel(skb, atd);
+ return -EFAULT;
+ } else
+ goto nla_put_failure;
+ }
+ NLA_PUT_NET32(skb, IPSET_ATTR_IP,
+ htonl(map->first_ip + id));
+ if (elem->match == MAC_FILLED)
+ NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
+ elem->ether);
+ timeout = elem->match == MAC_UNSET ? elem->timeout
+ : ip_set_timeout_get(elem->timeout);
+ NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout));
+ ipset_nest_end(skb, nested);
+ }
+ ipset_nest_end(skb, atd);
+ /* Set listing finished */
+ cb->args[2] = 0;
+
+ return 0;
+
+nla_put_failure:
+ nla_nest_cancel(skb, nested);
+ ipset_nest_end(skb, atd);
+ return 0;
+}
+
+static int
bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
- enum ipset_adt adt, uint8_t pf, const uint8_t *flags)
+ enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
{
struct bitmap_ipmac *map = set->data;
- uint32_t ip = ntohl(ip4addr(skb, flags));
- bool with_timeout = set->flags & IP_SET_FLAG_TIMEOUT;
-
- if (pf != AF_INET)
- return -EINVAL;
+ ipset_adtfn adtfn = set->variant->adt[adt];
+ struct ipmac data;
- if (ip < map->first_ip || ip > map->last_ip)
+ data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
+ if (data.id < map->first_ip || data.id > map->last_ip)
return -IPSET_ERR_BITMAP_RANGE;
+ /* Backward compatibility: we don't check the second flag */
if (skb_mac_header(skb) < skb->head
|| (skb_mac_header(skb) + ETH_HLEN) > skb->data)
return -EINVAL;
- ip -= map->first_ip;
-
- switch (adt) {
- case IPSET_TEST:
- return bitmap_ipmac_test(map, with_timeout,
- ip, eth_hdr(skb)->h_source);
- case IPSET_ADD:
- return bitmap_ipmac_add(map, with_timeout,
- ip, eth_hdr(skb)->h_source,
- map->timeout);
- case IPSET_DEL:
- return bitmap_ipmac_del(map, with_timeout, ip);
- default:
- return -EINVAL;
- }
+ data.id -= map->first_ip;
+ data.ether = eth_hdr(skb)->h_source;
+
+ return adtfn(set, &data, GFP_ATOMIC, map->timeout);
}
static const struct nla_policy
@@ -218,14 +372,14 @@ bitmap_ipmac_adt_policy[IPSET_ATTR_ADT_MAX + 1] __read_mostly = {
static int
bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *head, int len,
- enum ipset_adt adt, uint32_t *lineno, uint32_t flags)
+ enum ipset_adt adt, u32 *lineno, u32 flags)
{
struct bitmap_ipmac *map = set->data;
struct nlattr *tb[IPSET_ATTR_ADT_MAX];
+ ipset_adtfn adtfn = set->variant->adt[adt];
bool eexist = flags & IPSET_FLAG_EXIST;
- bool with_timeout = set->flags & IP_SET_FLAG_TIMEOUT;
- uint32_t ip, timeout = map->timeout;
- unsigned char *ether = NULL;
+ struct ipmac data;
+ u32 timeout = map->timeout;
int ret = 0;
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
@@ -233,35 +387,31 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *head, int len,
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_IP])
- ip = ip_set_get_h32(tb[IPSET_ATTR_IP]);
+ data.id = ip_set_get_h32(tb[IPSET_ATTR_IP]);
else
return -IPSET_ERR_PROTOCOL;
- if (ip < map->first_ip || ip > map->last_ip)
+ if (data.id < map->first_ip || data.id > map->last_ip)
return -IPSET_ERR_BITMAP_RANGE;
if (tb[IPSET_ATTR_ETHER])
- ether = nla_data(tb[IPSET_ATTR_ETHER]);
+ data.ether = nla_data(tb[IPSET_ATTR_ETHER]);
+ else
+ data.ether = NULL;
if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout)
+ if (!with_timeout(map->timeout))
return -IPSET_ERR_TIMEOUT;
- timeout = ip_set_get_h32(tb[IPSET_ATTR_TIMEOUT]);
+ timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
- ip -= map->first_ip;
-
- if (adt == IPSET_TEST)
- return bitmap_ipmac_test(map, with_timeout, ip, ether);
+ data.id -= map->first_ip;
- ret = adt == IPSET_ADD ? bitmap_ipmac_add(map, with_timeout,
- ip, ether, timeout)
- : bitmap_ipmac_del(map, with_timeout, ip);
+ ret = adtfn(set, &data, GFP_KERNEL, timeout);
if (ret && !(ret == -IPSET_ERR_EXIST && eexist)) {
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
- return ret;
}
return ret;
}
@@ -271,10 +421,8 @@ bitmap_ipmac_destroy(struct ip_set *set)
{
struct bitmap_ipmac *map = set->data;
- /* gc might be running: del_timer_sync can't be used */
- if (set->flags & IP_SET_FLAG_TIMEOUT)
- while (!del_timer(&map->gc))
- msleep(IPSET_DESTROY_TIMER_SLEEP);
+ if (with_timeout(map->timeout))
+ del_timer_sync(&map->gc);
ip_set_free(map->members, set->flags);
kfree(map);
@@ -288,7 +436,7 @@ bitmap_ipmac_flush(struct ip_set *set)
struct bitmap_ipmac *map = set->data;
memset(map->members, 0,
- (map->last_ip - map->first_ip + 1) * map->elem_size);
+ (map->last_ip - map->first_ip + 1) * map->dsize);
}
static int
@@ -296,28 +444,18 @@ bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb)
{
const struct bitmap_ipmac *map = set->data;
struct nlattr *nested;
- const struct ipmac *elem;
- uint32_t id, elements = 0, last = map->last_ip - map->first_ip;
- bool with_timeout = set->flags & IP_SET_FLAG_TIMEOUT;
-
- for (id = 0; id <= last; id++) {
- elem = bitmap_ipmac_elem(map, id);
- if (bitmap_ipmac_exist(elem, with_timeout))
- elements++;
- }
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
if (!nested)
goto nla_put_failure;
NLA_PUT_NET32(skb, IPSET_ATTR_IP, htonl(map->first_ip));
NLA_PUT_NET32(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
- NLA_PUT_NET32(skb, IPSET_ATTR_ELEMENTS, htonl(elements));
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
htonl(atomic_read(&set->ref) - 1));
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
- htonl((map->last_ip - map->first_ip + 1)
- * map->elem_size));
- if (with_timeout)
+ htonl(sizeof(*map)
+ + (map->last_ip - map->first_ip + 1) * map->dsize));
+ if (with_timeout(map->timeout))
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
ipset_nest_end(skb, nested);
@@ -326,77 +464,54 @@ nla_put_failure:
return -EFAULT;
}
-static int
-bitmap_ipmac_list(struct ip_set *set,
- struct sk_buff *skb, struct netlink_callback *cb)
+static bool
+bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
{
- const struct bitmap_ipmac *map = set->data;
- const struct ipmac *elem;
- struct nlattr *atd, *nested;
- uint32_t id, first = cb->args[2];
- uint32_t last = map->last_ip - map->first_ip;
- bool with_timeout = set->flags & IP_SET_FLAG_TIMEOUT;
-
- atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
- if (!atd)
- return -EFAULT;
- for (; cb->args[2] <= last; cb->args[2]++) {
- id = cb->args[2];
- elem = bitmap_ipmac_elem(map, id);
- if (!bitmap_ipmac_exist(elem, with_timeout))
- continue;
- nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
- if (!nested) {
- if (id == first) {
- nla_nest_cancel(skb, atd);
- return -EFAULT;
- } else
- goto nla_put_failure;
- }
- NLA_PUT_NET32(skb, IPSET_ATTR_IP,
- htonl(map->first_ip + id));
- if (elem->match == MAC_FILLED)
- NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
- elem->ether);
- if (with_timeout) {
- const struct ipmac_timeout *e =
- (const struct ipmac_timeout *)elem;
- uint32_t timeout = e->match == MAC_UNSET ? e->timeout
- : ip_set_timeout_get(e->timeout);
+ struct bitmap_ipmac *x = a->data;
+ struct bitmap_ipmac *y = b->data;
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
- htonl(timeout));
- }
- ipset_nest_end(skb, nested);
- }
- ipset_nest_end(skb, atd);
- /* Set listing finished */
- cb->args[2] = 0;
-
- return 0;
-
-nla_put_failure:
- nla_nest_cancel(skb, nested);
- ipset_nest_end(skb, atd);
- return 0;
+ return x->first_ip == y->first_ip
+ && x->last_ip == y->last_ip
+ && x->timeout == y->timeout;
}
const struct ip_set_type_variant bitmap_ipmac __read_mostly = {
.kadt = bitmap_ipmac_kadt,
.uadt = bitmap_ipmac_uadt,
+ .adt = {
+ [IPSET_ADD] = bitmap_ipmac_add,
+ [IPSET_DEL] = bitmap_ipmac_del,
+ [IPSET_TEST] = bitmap_ipmac_test,
+ },
.destroy = bitmap_ipmac_destroy,
.flush = bitmap_ipmac_flush,
.head = bitmap_ipmac_head,
.list = bitmap_ipmac_list,
+ .same_set = bitmap_ipmac_same_set,
+};
+
+const struct ip_set_type_variant bitmap_tipmac __read_mostly = {
+ .kadt = bitmap_ipmac_kadt,
+ .uadt = bitmap_ipmac_uadt,
+ .adt = {
+ [IPSET_ADD] = bitmap_ipmac_tadd,
+ [IPSET_DEL] = bitmap_ipmac_tdel,
+ [IPSET_TEST] = bitmap_ipmac_ttest,
+ },
+ .destroy = bitmap_ipmac_destroy,
+ .flush = bitmap_ipmac_flush,
+ .head = bitmap_ipmac_head,
+ .list = bitmap_ipmac_tlist,
+ .same_set = bitmap_ipmac_same_set,
};
static void
-bitmap_ipmac_timeout_gc(unsigned long ul_set)
+bitmap_ipmac_gc(unsigned long ul_set)
{
struct ip_set *set = (struct ip_set *) ul_set;
struct bitmap_ipmac *map = set->data;
- struct ipmac_timeout *elem;
- uint32_t id, last = map->last_ip - map->first_ip;
+ struct ipmac_telem *elem;
+ u32 id, last = map->last_ip - map->first_ip;
/* We run parallel with other readers (test element)
* but adding/deleting new entries is locked out */
@@ -414,13 +529,13 @@ bitmap_ipmac_timeout_gc(unsigned long ul_set)
}
static inline void
-bitmap_ipmac_timeout_gc_init(struct ip_set *set)
+bitmap_ipmac_gc_init(struct ip_set *set)
{
struct bitmap_ipmac *map = set->data;
init_timer(&map->gc);
map->gc.data = (unsigned long) set;
- map->gc.function = bitmap_ipmac_timeout_gc;
+ map->gc.function = bitmap_ipmac_gc;
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
add_timer(&map->gc);
}
@@ -436,14 +551,15 @@ bitmap_ipmac_create_policy[IPSET_ATTR_CREATE_MAX+1] __read_mostly = {
static bool
init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
- uint32_t first_ip, uint32_t last_ip)
+ u32 first_ip, u32 last_ip)
{
- map->members = ip_set_alloc((last_ip - first_ip + 1) * map->elem_size,
+ map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize,
GFP_KERNEL, &set->flags);
if (!map->members)
return false;
map->first_ip = first_ip;
map->last_ip = last_ip;
+ map->timeout = IPSET_NO_TIMEOUT;
set->data = map;
set->family = AF_INET;
@@ -453,10 +569,10 @@ init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
static int
bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len,
- uint32_t flags)
+ u32 flags)
{
struct nlattr *tb[IPSET_ATTR_CREATE_MAX];
- uint32_t first_ip, last_ip, elements;
+ u32 first_ip, last_ip, elements;
struct bitmap_ipmac *map;
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
@@ -471,13 +587,13 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len,
if (tb[IPSET_ATTR_IP_TO]) {
last_ip = ip_set_get_h32(tb[IPSET_ATTR_IP_TO]);
if (first_ip > last_ip) {
- uint32_t tmp = first_ip;
+ u32 tmp = first_ip;
first_ip = last_ip;
last_ip = tmp;
}
} else if (tb[IPSET_ATTR_CIDR]) {
- uint8_t cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
+ u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
if (cidr >= 32)
return -IPSET_ERR_INVALID_CIDR;
@@ -490,31 +606,32 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len,
if (elements > IPSET_BITMAP_MAX_RANGE + 1)
return -IPSET_ERR_BITMAP_RANGE_SIZE;
- set->variant = &bitmap_ipmac;
-
map = kzalloc(sizeof(*map), GFP_KERNEL);
if (!map)
return -ENOMEM;
if (tb[IPSET_ATTR_TIMEOUT]) {
- map->elem_size = sizeof(struct ipmac_timeout);
+ map->dsize = sizeof(struct ipmac_telem);
if (!init_map_ipmac(set, map, first_ip, last_ip)) {
kfree(map);
return -ENOMEM;
}
- map->timeout = ip_set_get_h32(tb[IPSET_ATTR_TIMEOUT]);
- set->flags |= IP_SET_FLAG_TIMEOUT;
+ map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
- bitmap_ipmac_timeout_gc_init(set);
+ set->variant = &bitmap_tipmac;
+
+ bitmap_ipmac_gc_init(set);
} else {
- map->elem_size = sizeof(struct ipmac);
+ map->dsize = sizeof(struct ipmac_elem);
if (!init_map_ipmac(set, map, first_ip, last_ip)) {
kfree(map);
return -ENOMEM;
}
+ set->variant = &bitmap_ipmac;
+
}
return 0;
}
@@ -522,7 +639,8 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len,
struct ip_set_type bitmap_ipmac_type = {
.name = "bitmap:ip,mac",
.protocol = IPSET_PROTOCOL,
- .features = IPSET_TYPE_IP,
+ .features = IPSET_TYPE_IP | IPSET_TYPE_MAC,
+ .dimension = IPSET_DIM_TWO,
.family = AF_INET,
.revision = 0,
.create = bitmap_ipmac_create,