diff options
Diffstat (limited to 'kernel/ip_set_bitmap_ipmac.c')
-rw-r--r-- | kernel/ip_set_bitmap_ipmac.c | 486 |
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, |