|
@@ -47,24 +47,26 @@ enum {
|
|
|
/* Type structure */
|
|
|
struct bitmap_ipmac {
|
|
|
void *members; /* the set members */
|
|
|
- void *extensions; /* MAC + data extensions */
|
|
|
u32 first_ip; /* host byte order, included in range */
|
|
|
u32 last_ip; /* host byte order, included in range */
|
|
|
u32 elements; /* number of max elements in the set */
|
|
|
size_t memsize; /* members size */
|
|
|
struct timer_list gc; /* garbage collector */
|
|
|
+ unsigned char extensions[0] /* MAC + data extensions */
|
|
|
+ __aligned(__alignof__(u64));
|
|
|
};
|
|
|
|
|
|
/* ADT structure for generic function args */
|
|
|
struct bitmap_ipmac_adt_elem {
|
|
|
+ unsigned char ether[ETH_ALEN] __aligned(2);
|
|
|
u16 id;
|
|
|
- unsigned char *ether;
|
|
|
+ u16 add_mac;
|
|
|
};
|
|
|
|
|
|
struct bitmap_ipmac_elem {
|
|
|
unsigned char ether[ETH_ALEN];
|
|
|
unsigned char filled;
|
|
|
-} __attribute__ ((aligned));
|
|
|
+} __aligned(__alignof__(u64));
|
|
|
|
|
|
static inline u32
|
|
|
ip_to_id(const struct bitmap_ipmac *m, u32 ip)
|
|
@@ -72,11 +74,11 @@ ip_to_id(const struct bitmap_ipmac *m, u32 ip)
|
|
|
return ip - m->first_ip;
|
|
|
}
|
|
|
|
|
|
-static inline struct bitmap_ipmac_elem *
|
|
|
-get_elem(void *extensions, u16 id, size_t dsize)
|
|
|
-{
|
|
|
- return (struct bitmap_ipmac_elem *)(extensions + id * dsize);
|
|
|
-}
|
|
|
+#define get_elem(extensions, id, dsize) \
|
|
|
+ (struct bitmap_ipmac_elem *)(extensions + (id) * (dsize))
|
|
|
+
|
|
|
+#define get_const_elem(extensions, id, dsize) \
|
|
|
+ (const struct bitmap_ipmac_elem *)(extensions + (id) * (dsize))
|
|
|
|
|
|
/* Common functions */
|
|
|
|
|
@@ -88,10 +90,9 @@ bitmap_ipmac_do_test(const struct bitmap_ipmac_adt_elem *e,
|
|
|
|
|
|
if (!test_bit(e->id, map->members))
|
|
|
return 0;
|
|
|
- elem = get_elem(map->extensions, e->id, dsize);
|
|
|
- if (elem->filled == MAC_FILLED)
|
|
|
- return !e->ether ||
|
|
|
- ether_addr_equal(e->ether, elem->ether);
|
|
|
+ elem = get_const_elem(map->extensions, e->id, dsize);
|
|
|
+ if (e->add_mac && elem->filled == MAC_FILLED)
|
|
|
+ return ether_addr_equal(e->ether, elem->ether);
|
|
|
/* Trigger kernel to fill out the ethernet address */
|
|
|
return -EAGAIN;
|
|
|
}
|
|
@@ -103,7 +104,7 @@ bitmap_ipmac_gc_test(u16 id, const struct bitmap_ipmac *map, size_t dsize)
|
|
|
|
|
|
if (!test_bit(id, map->members))
|
|
|
return 0;
|
|
|
- elem = get_elem(map->extensions, id, dsize);
|
|
|
+ elem = get_const_elem(map->extensions, id, dsize);
|
|
|
/* Timer not started for the incomplete elements */
|
|
|
return elem->filled == MAC_FILLED;
|
|
|
}
|
|
@@ -133,7 +134,7 @@ bitmap_ipmac_add_timeout(unsigned long *timeout,
|
|
|
* and we can reuse it later when MAC is filled out,
|
|
|
* possibly by the kernel
|
|
|
*/
|
|
|
- if (e->ether)
|
|
|
+ if (e->add_mac)
|
|
|
ip_set_timeout_set(timeout, t);
|
|
|
else
|
|
|
*timeout = t;
|
|
@@ -150,7 +151,7 @@ bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
|
|
|
elem = get_elem(map->extensions, e->id, dsize);
|
|
|
if (test_bit(e->id, map->members)) {
|
|
|
if (elem->filled == MAC_FILLED) {
|
|
|
- if (e->ether &&
|
|
|
+ if (e->add_mac &&
|
|
|
(flags & IPSET_FLAG_EXIST) &&
|
|
|
!ether_addr_equal(e->ether, elem->ether)) {
|
|
|
/* memcpy isn't atomic */
|
|
@@ -159,7 +160,7 @@ bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
|
|
|
ether_addr_copy(elem->ether, e->ether);
|
|
|
}
|
|
|
return IPSET_ADD_FAILED;
|
|
|
- } else if (!e->ether)
|
|
|
+ } else if (!e->add_mac)
|
|
|
/* Already added without ethernet address */
|
|
|
return IPSET_ADD_FAILED;
|
|
|
/* Fill the MAC address and trigger the timer activation */
|
|
@@ -168,7 +169,7 @@ bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
|
|
|
ether_addr_copy(elem->ether, e->ether);
|
|
|
elem->filled = MAC_FILLED;
|
|
|
return IPSET_ADD_START_STORED_TIMEOUT;
|
|
|
- } else if (e->ether) {
|
|
|
+ } else if (e->add_mac) {
|
|
|
/* We can store MAC too */
|
|
|
ether_addr_copy(elem->ether, e->ether);
|
|
|
elem->filled = MAC_FILLED;
|
|
@@ -191,7 +192,7 @@ bitmap_ipmac_do_list(struct sk_buff *skb, const struct bitmap_ipmac *map,
|
|
|
u32 id, size_t dsize)
|
|
|
{
|
|
|
const struct bitmap_ipmac_elem *elem =
|
|
|
- get_elem(map->extensions, id, dsize);
|
|
|
+ get_const_elem(map->extensions, id, dsize);
|
|
|
|
|
|
return nla_put_ipaddr4(skb, IPSET_ATTR_IP,
|
|
|
htonl(map->first_ip + id)) ||
|
|
@@ -213,7 +214,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
|
|
|
{
|
|
|
struct bitmap_ipmac *map = set->data;
|
|
|
ipset_adtfn adtfn = set->variant->adt[adt];
|
|
|
- struct bitmap_ipmac_adt_elem e = { .id = 0 };
|
|
|
+ struct bitmap_ipmac_adt_elem e = { .id = 0, .add_mac = 1 };
|
|
|
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
|
|
|
u32 ip;
|
|
|
|
|
@@ -231,7 +232,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
|
|
|
return -EINVAL;
|
|
|
|
|
|
e.id = ip_to_id(map, ip);
|
|
|
- e.ether = eth_hdr(skb)->h_source;
|
|
|
+ memcpy(e.ether, eth_hdr(skb)->h_source, ETH_ALEN);
|
|
|
|
|
|
return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
|
|
|
}
|
|
@@ -265,11 +266,10 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
|
|
|
return -IPSET_ERR_BITMAP_RANGE;
|
|
|
|
|
|
e.id = ip_to_id(map, ip);
|
|
|
- if (tb[IPSET_ATTR_ETHER])
|
|
|
- e.ether = nla_data(tb[IPSET_ATTR_ETHER]);
|
|
|
- else
|
|
|
- e.ether = NULL;
|
|
|
-
|
|
|
+ if (tb[IPSET_ATTR_ETHER]) {
|
|
|
+ memcpy(e.ether, nla_data(tb[IPSET_ATTR_ETHER]), ETH_ALEN);
|
|
|
+ e.add_mac = 1;
|
|
|
+ }
|
|
|
ret = adtfn(set, &e, &ext, &ext, flags);
|
|
|
|
|
|
return ip_set_eexist(ret, flags) ? 0 : ret;
|
|
@@ -300,13 +300,6 @@ init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
|
|
|
map->members = ip_set_alloc(map->memsize);
|
|
|
if (!map->members)
|
|
|
return false;
|
|
|
- if (set->dsize) {
|
|
|
- map->extensions = ip_set_alloc(set->dsize * elements);
|
|
|
- if (!map->extensions) {
|
|
|
- kfree(map->members);
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
map->first_ip = first_ip;
|
|
|
map->last_ip = last_ip;
|
|
|
map->elements = elements;
|
|
@@ -361,14 +354,15 @@ bitmap_ipmac_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
|
|
|
if (elements > IPSET_BITMAP_MAX_RANGE + 1)
|
|
|
return -IPSET_ERR_BITMAP_RANGE_SIZE;
|
|
|
|
|
|
- map = kzalloc(sizeof(*map), GFP_KERNEL);
|
|
|
+ set->dsize = ip_set_elem_len(set, tb,
|
|
|
+ sizeof(struct bitmap_ipmac_elem),
|
|
|
+ __alignof__(struct bitmap_ipmac_elem));
|
|
|
+ map = ip_set_alloc(sizeof(*map) + elements * set->dsize);
|
|
|
if (!map)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
map->memsize = bitmap_bytes(0, elements - 1);
|
|
|
set->variant = &bitmap_ipmac;
|
|
|
- set->dsize = ip_set_elem_len(set, tb,
|
|
|
- sizeof(struct bitmap_ipmac_elem));
|
|
|
if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
|
|
|
kfree(map);
|
|
|
return -ENOMEM;
|