1 /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
2 * Patrick Schaaf <bof@bof.de>
3 * Martin Josefsson <gandalf@wlug.westbo.se>
4 * Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 /* Kernel module implementing an IP set type: the bitmap:ip,mac type */
13 #include <linux/module.h>
15 #include <linux/etherdevice.h>
16 #include <linux/skbuff.h>
17 #include <linux/errno.h>
18 #include <linux/if_ether.h>
19 #include <linux/netlink.h>
20 #include <linux/jiffies.h>
21 #include <linux/timer.h>
22 #include <net/netlink.h>
24 #include <linux/netfilter/ipset/pfxlen.h>
25 #include <linux/netfilter/ipset/ip_set.h>
26 #include <linux/netfilter/ipset/ip_set_bitmap.h>
28 #define IPSET_TYPE_REV_MIN 0
29 /* 1 Counter support added */
30 /* 2 Comment support added */
31 #define IPSET_TYPE_REV_MAX 3 /* skbinfo support added */
33 MODULE_LICENSE("GPL");
34 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
35 IP_SET_MODULE_DESC("bitmap:ip,mac", IPSET_TYPE_REV_MIN
, IPSET_TYPE_REV_MAX
);
36 MODULE_ALIAS("ip_set_bitmap:ip,mac");
38 #define MTYPE bitmap_ipmac
40 #define IP_SET_BITMAP_STORED_TIMEOUT
43 MAC_UNSET
, /* element is set, without MAC */
44 MAC_FILLED
, /* element is set with MAC */
49 void *members
; /* the set members */
50 u32 first_ip
; /* host byte order, included in range */
51 u32 last_ip
; /* host byte order, included in range */
52 u32 elements
; /* number of max elements in the set */
53 size_t memsize
; /* members size */
54 struct timer_list gc
; /* garbage collector */
55 unsigned char extensions
[0] /* MAC + data extensions */
56 __aligned(__alignof__(u64
));
59 /* ADT structure for generic function args */
60 struct bitmap_ipmac_adt_elem
{
61 unsigned char ether
[ETH_ALEN
] __aligned(2);
66 struct bitmap_ipmac_elem
{
67 unsigned char ether
[ETH_ALEN
];
69 } __aligned(__alignof__(u64
));
72 ip_to_id(const struct bitmap_ipmac
*m
, u32 ip
)
74 return ip
- m
->first_ip
;
77 #define get_elem(extensions, id, dsize) \
78 (struct bitmap_ipmac_elem *)(extensions + (id) * (dsize))
80 #define get_const_elem(extensions, id, dsize) \
81 (const struct bitmap_ipmac_elem *)(extensions + (id) * (dsize))
83 /* Common functions */
86 bitmap_ipmac_do_test(const struct bitmap_ipmac_adt_elem
*e
,
87 const struct bitmap_ipmac
*map
, size_t dsize
)
89 const struct bitmap_ipmac_elem
*elem
;
91 if (!test_bit(e
->id
, map
->members
))
93 elem
= get_const_elem(map
->extensions
, e
->id
, dsize
);
94 if (e
->add_mac
&& elem
->filled
== MAC_FILLED
)
95 return ether_addr_equal(e
->ether
, elem
->ether
);
96 /* Trigger kernel to fill out the ethernet address */
101 bitmap_ipmac_gc_test(u16 id
, const struct bitmap_ipmac
*map
, size_t dsize
)
103 const struct bitmap_ipmac_elem
*elem
;
105 if (!test_bit(id
, map
->members
))
107 elem
= get_const_elem(map
->extensions
, id
, dsize
);
108 /* Timer not started for the incomplete elements */
109 return elem
->filled
== MAC_FILLED
;
113 bitmap_ipmac_is_filled(const struct bitmap_ipmac_elem
*elem
)
115 return elem
->filled
== MAC_FILLED
;
119 bitmap_ipmac_add_timeout(unsigned long *timeout
,
120 const struct bitmap_ipmac_adt_elem
*e
,
121 const struct ip_set_ext
*ext
, struct ip_set
*set
,
122 struct bitmap_ipmac
*map
, int mode
)
124 u32 t
= ext
->timeout
;
126 if (mode
== IPSET_ADD_START_STORED_TIMEOUT
) {
127 if (t
== set
->timeout
)
128 /* Timeout was not specified, get stored one */
130 ip_set_timeout_set(timeout
, t
);
132 /* If MAC is unset yet, we store plain timeout value
133 * because the timer is not activated yet
134 * and we can reuse it later when MAC is filled out,
135 * possibly by the kernel
138 ip_set_timeout_set(timeout
, t
);
146 bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem
*e
,
147 struct bitmap_ipmac
*map
, u32 flags
, size_t dsize
)
149 struct bitmap_ipmac_elem
*elem
;
151 elem
= get_elem(map
->extensions
, e
->id
, dsize
);
152 if (test_bit(e
->id
, map
->members
)) {
153 if (elem
->filled
== MAC_FILLED
) {
155 (flags
& IPSET_FLAG_EXIST
) &&
156 !ether_addr_equal(e
->ether
, elem
->ether
)) {
157 /* memcpy isn't atomic */
158 clear_bit(e
->id
, map
->members
);
159 smp_mb__after_atomic();
160 ether_addr_copy(elem
->ether
, e
->ether
);
162 return IPSET_ADD_FAILED
;
163 } else if (!e
->add_mac
)
164 /* Already added without ethernet address */
165 return IPSET_ADD_FAILED
;
166 /* Fill the MAC address and trigger the timer activation */
167 clear_bit(e
->id
, map
->members
);
168 smp_mb__after_atomic();
169 ether_addr_copy(elem
->ether
, e
->ether
);
170 elem
->filled
= MAC_FILLED
;
171 return IPSET_ADD_START_STORED_TIMEOUT
;
172 } else if (e
->add_mac
) {
173 /* We can store MAC too */
174 ether_addr_copy(elem
->ether
, e
->ether
);
175 elem
->filled
= MAC_FILLED
;
178 elem
->filled
= MAC_UNSET
;
179 /* MAC is not stored yet, don't start timer */
180 return IPSET_ADD_STORE_PLAIN_TIMEOUT
;
184 bitmap_ipmac_do_del(const struct bitmap_ipmac_adt_elem
*e
,
185 struct bitmap_ipmac
*map
)
187 return !test_and_clear_bit(e
->id
, map
->members
);
191 bitmap_ipmac_do_list(struct sk_buff
*skb
, const struct bitmap_ipmac
*map
,
192 u32 id
, size_t dsize
)
194 const struct bitmap_ipmac_elem
*elem
=
195 get_const_elem(map
->extensions
, id
, dsize
);
197 return nla_put_ipaddr4(skb
, IPSET_ATTR_IP
,
198 htonl(map
->first_ip
+ id
)) ||
199 (elem
->filled
== MAC_FILLED
&&
200 nla_put(skb
, IPSET_ATTR_ETHER
, ETH_ALEN
, elem
->ether
));
204 bitmap_ipmac_do_head(struct sk_buff
*skb
, const struct bitmap_ipmac
*map
)
206 return nla_put_ipaddr4(skb
, IPSET_ATTR_IP
, htonl(map
->first_ip
)) ||
207 nla_put_ipaddr4(skb
, IPSET_ATTR_IP_TO
, htonl(map
->last_ip
));
211 bitmap_ipmac_kadt(struct ip_set
*set
, const struct sk_buff
*skb
,
212 const struct xt_action_param
*par
,
213 enum ipset_adt adt
, struct ip_set_adt_opt
*opt
)
215 struct bitmap_ipmac
*map
= set
->data
;
216 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
217 struct bitmap_ipmac_adt_elem e
= { .id
= 0, .add_mac
= 1 };
218 struct ip_set_ext ext
= IP_SET_INIT_KEXT(skb
, opt
, set
);
221 /* MAC can be src only */
222 if (!(opt
->flags
& IPSET_DIM_TWO_SRC
))
225 ip
= ntohl(ip4addr(skb
, opt
->flags
& IPSET_DIM_ONE_SRC
));
226 if (ip
< map
->first_ip
|| ip
> map
->last_ip
)
227 return -IPSET_ERR_BITMAP_RANGE
;
229 /* Backward compatibility: we don't check the second flag */
230 if (skb_mac_header(skb
) < skb
->head
||
231 (skb_mac_header(skb
) + ETH_HLEN
) > skb
->data
)
234 e
.id
= ip_to_id(map
, ip
);
235 memcpy(e
.ether
, eth_hdr(skb
)->h_source
, ETH_ALEN
);
237 return adtfn(set
, &e
, &ext
, &opt
->ext
, opt
->cmdflags
);
241 bitmap_ipmac_uadt(struct ip_set
*set
, struct nlattr
*tb
[],
242 enum ipset_adt adt
, u32
*lineno
, u32 flags
, bool retried
)
244 const struct bitmap_ipmac
*map
= set
->data
;
245 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
246 struct bitmap_ipmac_adt_elem e
= { .id
= 0 };
247 struct ip_set_ext ext
= IP_SET_INIT_UEXT(set
);
251 if (tb
[IPSET_ATTR_LINENO
])
252 *lineno
= nla_get_u32(tb
[IPSET_ATTR_LINENO
]);
254 if (unlikely(!tb
[IPSET_ATTR_IP
]))
255 return -IPSET_ERR_PROTOCOL
;
257 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP
], &ip
);
261 ret
= ip_set_get_extensions(set
, tb
, &ext
);
265 if (ip
< map
->first_ip
|| ip
> map
->last_ip
)
266 return -IPSET_ERR_BITMAP_RANGE
;
268 e
.id
= ip_to_id(map
, ip
);
269 if (tb
[IPSET_ATTR_ETHER
]) {
270 if (nla_len(tb
[IPSET_ATTR_ETHER
]) != ETH_ALEN
)
271 return -IPSET_ERR_PROTOCOL
;
272 memcpy(e
.ether
, nla_data(tb
[IPSET_ATTR_ETHER
]), ETH_ALEN
);
275 ret
= adtfn(set
, &e
, &ext
, &ext
, flags
);
277 return ip_set_eexist(ret
, flags
) ? 0 : ret
;
281 bitmap_ipmac_same_set(const struct ip_set
*a
, const struct ip_set
*b
)
283 const struct bitmap_ipmac
*x
= a
->data
;
284 const struct bitmap_ipmac
*y
= b
->data
;
286 return x
->first_ip
== y
->first_ip
&&
287 x
->last_ip
== y
->last_ip
&&
288 a
->timeout
== b
->timeout
&&
289 a
->extensions
== b
->extensions
;
294 #include "ip_set_bitmap_gen.h"
296 /* Create bitmap:ip,mac type of sets */
299 init_map_ipmac(struct ip_set
*set
, struct bitmap_ipmac
*map
,
300 u32 first_ip
, u32 last_ip
, u32 elements
)
302 map
->members
= ip_set_alloc(map
->memsize
);
305 map
->first_ip
= first_ip
;
306 map
->last_ip
= last_ip
;
307 map
->elements
= elements
;
308 set
->timeout
= IPSET_NO_TIMEOUT
;
311 set
->family
= NFPROTO_IPV4
;
317 bitmap_ipmac_create(struct net
*net
, struct ip_set
*set
, struct nlattr
*tb
[],
320 u32 first_ip
= 0, last_ip
= 0;
322 struct bitmap_ipmac
*map
;
325 if (unlikely(!tb
[IPSET_ATTR_IP
] ||
326 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
) ||
327 !ip_set_optattr_netorder(tb
, IPSET_ATTR_CADT_FLAGS
)))
328 return -IPSET_ERR_PROTOCOL
;
330 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP
], &first_ip
);
334 if (tb
[IPSET_ATTR_IP_TO
]) {
335 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP_TO
], &last_ip
);
338 if (first_ip
> last_ip
) {
344 } else if (tb
[IPSET_ATTR_CIDR
]) {
345 u8 cidr
= nla_get_u8(tb
[IPSET_ATTR_CIDR
]);
347 if (cidr
>= HOST_MASK
)
348 return -IPSET_ERR_INVALID_CIDR
;
349 ip_set_mask_from_to(first_ip
, last_ip
, cidr
);
351 return -IPSET_ERR_PROTOCOL
;
354 elements
= (u64
)last_ip
- first_ip
+ 1;
356 if (elements
> IPSET_BITMAP_MAX_RANGE
+ 1)
357 return -IPSET_ERR_BITMAP_RANGE_SIZE
;
359 set
->dsize
= ip_set_elem_len(set
, tb
,
360 sizeof(struct bitmap_ipmac_elem
),
361 __alignof__(struct bitmap_ipmac_elem
));
362 map
= ip_set_alloc(sizeof(*map
) + elements
* set
->dsize
);
366 map
->memsize
= bitmap_bytes(0, elements
- 1);
367 set
->variant
= &bitmap_ipmac
;
368 if (!init_map_ipmac(set
, map
, first_ip
, last_ip
, elements
)) {
372 if (tb
[IPSET_ATTR_TIMEOUT
]) {
373 set
->timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
374 bitmap_ipmac_gc_init(set
, bitmap_ipmac_gc
);
379 static struct ip_set_type bitmap_ipmac_type
= {
380 .name
= "bitmap:ip,mac",
381 .protocol
= IPSET_PROTOCOL
,
382 .features
= IPSET_TYPE_IP
| IPSET_TYPE_MAC
,
383 .dimension
= IPSET_DIM_TWO
,
384 .family
= NFPROTO_IPV4
,
385 .revision_min
= IPSET_TYPE_REV_MIN
,
386 .revision_max
= IPSET_TYPE_REV_MAX
,
387 .create
= bitmap_ipmac_create
,
389 [IPSET_ATTR_IP
] = { .type
= NLA_NESTED
},
390 [IPSET_ATTR_IP_TO
] = { .type
= NLA_NESTED
},
391 [IPSET_ATTR_CIDR
] = { .type
= NLA_U8
},
392 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
393 [IPSET_ATTR_CADT_FLAGS
] = { .type
= NLA_U32
},
396 [IPSET_ATTR_IP
] = { .type
= NLA_NESTED
},
397 [IPSET_ATTR_ETHER
] = { .type
= NLA_BINARY
,
399 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
400 [IPSET_ATTR_LINENO
] = { .type
= NLA_U32
},
401 [IPSET_ATTR_BYTES
] = { .type
= NLA_U64
},
402 [IPSET_ATTR_PACKETS
] = { .type
= NLA_U64
},
403 [IPSET_ATTR_COMMENT
] = { .type
= NLA_NUL_STRING
,
404 .len
= IPSET_MAX_COMMENT_SIZE
},
405 [IPSET_ATTR_SKBMARK
] = { .type
= NLA_U64
},
406 [IPSET_ATTR_SKBPRIO
] = { .type
= NLA_U32
},
407 [IPSET_ATTR_SKBQUEUE
] = { .type
= NLA_U16
},
413 bitmap_ipmac_init(void)
415 return ip_set_type_register(&bitmap_ipmac_type
);
419 bitmap_ipmac_fini(void)
422 ip_set_type_unregister(&bitmap_ipmac_type
);
425 module_init(bitmap_ipmac_init
);
426 module_exit(bitmap_ipmac_fini
);