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 struct ip_set
*set
; /* attached to this ip_set */
56 unsigned char extensions
[0] /* MAC + data extensions */
57 __aligned(__alignof__(u64
));
60 /* ADT structure for generic function args */
61 struct bitmap_ipmac_adt_elem
{
62 unsigned char ether
[ETH_ALEN
] __aligned(2);
67 struct bitmap_ipmac_elem
{
68 unsigned char ether
[ETH_ALEN
];
70 } __aligned(__alignof__(u64
));
73 ip_to_id(const struct bitmap_ipmac
*m
, u32 ip
)
75 return ip
- m
->first_ip
;
78 #define get_elem(extensions, id, dsize) \
79 (struct bitmap_ipmac_elem *)(extensions + (id) * (dsize))
81 #define get_const_elem(extensions, id, dsize) \
82 (const struct bitmap_ipmac_elem *)(extensions + (id) * (dsize))
84 /* Common functions */
87 bitmap_ipmac_do_test(const struct bitmap_ipmac_adt_elem
*e
,
88 const struct bitmap_ipmac
*map
, size_t dsize
)
90 const struct bitmap_ipmac_elem
*elem
;
92 if (!test_bit(e
->id
, map
->members
))
94 elem
= get_const_elem(map
->extensions
, e
->id
, dsize
);
95 if (e
->add_mac
&& elem
->filled
== MAC_FILLED
)
96 return ether_addr_equal(e
->ether
, elem
->ether
);
97 /* Trigger kernel to fill out the ethernet address */
102 bitmap_ipmac_gc_test(u16 id
, const struct bitmap_ipmac
*map
, size_t dsize
)
104 const struct bitmap_ipmac_elem
*elem
;
106 if (!test_bit(id
, map
->members
))
108 elem
= get_const_elem(map
->extensions
, id
, dsize
);
109 /* Timer not started for the incomplete elements */
110 return elem
->filled
== MAC_FILLED
;
114 bitmap_ipmac_is_filled(const struct bitmap_ipmac_elem
*elem
)
116 return elem
->filled
== MAC_FILLED
;
120 bitmap_ipmac_add_timeout(unsigned long *timeout
,
121 const struct bitmap_ipmac_adt_elem
*e
,
122 const struct ip_set_ext
*ext
, struct ip_set
*set
,
123 struct bitmap_ipmac
*map
, int mode
)
125 u32 t
= ext
->timeout
;
127 if (mode
== IPSET_ADD_START_STORED_TIMEOUT
) {
128 if (t
== set
->timeout
)
129 /* Timeout was not specified, get stored one */
131 ip_set_timeout_set(timeout
, t
);
133 /* If MAC is unset yet, we store plain timeout value
134 * because the timer is not activated yet
135 * and we can reuse it later when MAC is filled out,
136 * possibly by the kernel
139 ip_set_timeout_set(timeout
, t
);
147 bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem
*e
,
148 struct bitmap_ipmac
*map
, u32 flags
, size_t dsize
)
150 struct bitmap_ipmac_elem
*elem
;
152 elem
= get_elem(map
->extensions
, e
->id
, dsize
);
153 if (test_bit(e
->id
, map
->members
)) {
154 if (elem
->filled
== MAC_FILLED
) {
156 (flags
& IPSET_FLAG_EXIST
) &&
157 !ether_addr_equal(e
->ether
, elem
->ether
)) {
158 /* memcpy isn't atomic */
159 clear_bit(e
->id
, map
->members
);
160 smp_mb__after_atomic();
161 ether_addr_copy(elem
->ether
, e
->ether
);
163 return IPSET_ADD_FAILED
;
164 } else if (!e
->add_mac
)
165 /* Already added without ethernet address */
166 return IPSET_ADD_FAILED
;
167 /* Fill the MAC address and trigger the timer activation */
168 clear_bit(e
->id
, map
->members
);
169 smp_mb__after_atomic();
170 ether_addr_copy(elem
->ether
, e
->ether
);
171 elem
->filled
= MAC_FILLED
;
172 return IPSET_ADD_START_STORED_TIMEOUT
;
173 } else if (e
->add_mac
) {
174 /* We can store MAC too */
175 ether_addr_copy(elem
->ether
, e
->ether
);
176 elem
->filled
= MAC_FILLED
;
179 elem
->filled
= MAC_UNSET
;
180 /* MAC is not stored yet, don't start timer */
181 return IPSET_ADD_STORE_PLAIN_TIMEOUT
;
185 bitmap_ipmac_do_del(const struct bitmap_ipmac_adt_elem
*e
,
186 struct bitmap_ipmac
*map
)
188 return !test_and_clear_bit(e
->id
, map
->members
);
192 bitmap_ipmac_do_list(struct sk_buff
*skb
, const struct bitmap_ipmac
*map
,
193 u32 id
, size_t dsize
)
195 const struct bitmap_ipmac_elem
*elem
=
196 get_const_elem(map
->extensions
, id
, dsize
);
198 return nla_put_ipaddr4(skb
, IPSET_ATTR_IP
,
199 htonl(map
->first_ip
+ id
)) ||
200 (elem
->filled
== MAC_FILLED
&&
201 nla_put(skb
, IPSET_ATTR_ETHER
, ETH_ALEN
, elem
->ether
));
205 bitmap_ipmac_do_head(struct sk_buff
*skb
, const struct bitmap_ipmac
*map
)
207 return nla_put_ipaddr4(skb
, IPSET_ATTR_IP
, htonl(map
->first_ip
)) ||
208 nla_put_ipaddr4(skb
, IPSET_ATTR_IP_TO
, htonl(map
->last_ip
));
212 bitmap_ipmac_kadt(struct ip_set
*set
, const struct sk_buff
*skb
,
213 const struct xt_action_param
*par
,
214 enum ipset_adt adt
, struct ip_set_adt_opt
*opt
)
216 struct bitmap_ipmac
*map
= set
->data
;
217 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
218 struct bitmap_ipmac_adt_elem e
= { .id
= 0, .add_mac
= 1 };
219 struct ip_set_ext ext
= IP_SET_INIT_KEXT(skb
, opt
, set
);
222 /* MAC can be src only */
223 if (!(opt
->flags
& IPSET_DIM_TWO_SRC
))
226 ip
= ntohl(ip4addr(skb
, opt
->flags
& IPSET_DIM_ONE_SRC
));
227 if (ip
< map
->first_ip
|| ip
> map
->last_ip
)
228 return -IPSET_ERR_BITMAP_RANGE
;
230 /* Backward compatibility: we don't check the second flag */
231 if (skb_mac_header(skb
) < skb
->head
||
232 (skb_mac_header(skb
) + ETH_HLEN
) > skb
->data
)
235 e
.id
= ip_to_id(map
, ip
);
236 memcpy(e
.ether
, eth_hdr(skb
)->h_source
, ETH_ALEN
);
238 return adtfn(set
, &e
, &ext
, &opt
->ext
, opt
->cmdflags
);
242 bitmap_ipmac_uadt(struct ip_set
*set
, struct nlattr
*tb
[],
243 enum ipset_adt adt
, u32
*lineno
, u32 flags
, bool retried
)
245 const struct bitmap_ipmac
*map
= set
->data
;
246 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
247 struct bitmap_ipmac_adt_elem e
= { .id
= 0 };
248 struct ip_set_ext ext
= IP_SET_INIT_UEXT(set
);
252 if (tb
[IPSET_ATTR_LINENO
])
253 *lineno
= nla_get_u32(tb
[IPSET_ATTR_LINENO
]);
255 if (unlikely(!tb
[IPSET_ATTR_IP
]))
256 return -IPSET_ERR_PROTOCOL
;
258 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP
], &ip
);
262 ret
= ip_set_get_extensions(set
, tb
, &ext
);
266 if (ip
< map
->first_ip
|| ip
> map
->last_ip
)
267 return -IPSET_ERR_BITMAP_RANGE
;
269 e
.id
= ip_to_id(map
, ip
);
270 if (tb
[IPSET_ATTR_ETHER
]) {
271 if (nla_len(tb
[IPSET_ATTR_ETHER
]) != ETH_ALEN
)
272 return -IPSET_ERR_PROTOCOL
;
273 memcpy(e
.ether
, nla_data(tb
[IPSET_ATTR_ETHER
]), ETH_ALEN
);
276 ret
= adtfn(set
, &e
, &ext
, &ext
, flags
);
278 return ip_set_eexist(ret
, flags
) ? 0 : ret
;
282 bitmap_ipmac_same_set(const struct ip_set
*a
, const struct ip_set
*b
)
284 const struct bitmap_ipmac
*x
= a
->data
;
285 const struct bitmap_ipmac
*y
= b
->data
;
287 return x
->first_ip
== y
->first_ip
&&
288 x
->last_ip
== y
->last_ip
&&
289 a
->timeout
== b
->timeout
&&
290 a
->extensions
== b
->extensions
;
295 #include "ip_set_bitmap_gen.h"
297 /* Create bitmap:ip,mac type of sets */
300 init_map_ipmac(struct ip_set
*set
, struct bitmap_ipmac
*map
,
301 u32 first_ip
, u32 last_ip
, u32 elements
)
303 map
->members
= ip_set_alloc(map
->memsize
);
306 map
->first_ip
= first_ip
;
307 map
->last_ip
= last_ip
;
308 map
->elements
= elements
;
309 set
->timeout
= IPSET_NO_TIMEOUT
;
313 set
->family
= NFPROTO_IPV4
;
319 bitmap_ipmac_create(struct net
*net
, struct ip_set
*set
, struct nlattr
*tb
[],
322 u32 first_ip
= 0, last_ip
= 0;
324 struct bitmap_ipmac
*map
;
327 if (unlikely(!tb
[IPSET_ATTR_IP
] ||
328 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
) ||
329 !ip_set_optattr_netorder(tb
, IPSET_ATTR_CADT_FLAGS
)))
330 return -IPSET_ERR_PROTOCOL
;
332 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP
], &first_ip
);
336 if (tb
[IPSET_ATTR_IP_TO
]) {
337 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP_TO
], &last_ip
);
340 if (first_ip
> last_ip
) {
346 } else if (tb
[IPSET_ATTR_CIDR
]) {
347 u8 cidr
= nla_get_u8(tb
[IPSET_ATTR_CIDR
]);
349 if (cidr
>= HOST_MASK
)
350 return -IPSET_ERR_INVALID_CIDR
;
351 ip_set_mask_from_to(first_ip
, last_ip
, cidr
);
353 return -IPSET_ERR_PROTOCOL
;
356 elements
= (u64
)last_ip
- first_ip
+ 1;
358 if (elements
> IPSET_BITMAP_MAX_RANGE
+ 1)
359 return -IPSET_ERR_BITMAP_RANGE_SIZE
;
361 set
->dsize
= ip_set_elem_len(set
, tb
,
362 sizeof(struct bitmap_ipmac_elem
),
363 __alignof__(struct bitmap_ipmac_elem
));
364 map
= ip_set_alloc(sizeof(*map
) + elements
* set
->dsize
);
368 map
->memsize
= bitmap_bytes(0, elements
- 1);
369 set
->variant
= &bitmap_ipmac
;
370 if (!init_map_ipmac(set
, map
, first_ip
, last_ip
, elements
)) {
374 if (tb
[IPSET_ATTR_TIMEOUT
]) {
375 set
->timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
376 bitmap_ipmac_gc_init(set
, bitmap_ipmac_gc
);
381 static struct ip_set_type bitmap_ipmac_type
= {
382 .name
= "bitmap:ip,mac",
383 .protocol
= IPSET_PROTOCOL
,
384 .features
= IPSET_TYPE_IP
| IPSET_TYPE_MAC
,
385 .dimension
= IPSET_DIM_TWO
,
386 .family
= NFPROTO_IPV4
,
387 .revision_min
= IPSET_TYPE_REV_MIN
,
388 .revision_max
= IPSET_TYPE_REV_MAX
,
389 .create
= bitmap_ipmac_create
,
391 [IPSET_ATTR_IP
] = { .type
= NLA_NESTED
},
392 [IPSET_ATTR_IP_TO
] = { .type
= NLA_NESTED
},
393 [IPSET_ATTR_CIDR
] = { .type
= NLA_U8
},
394 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
395 [IPSET_ATTR_CADT_FLAGS
] = { .type
= NLA_U32
},
398 [IPSET_ATTR_IP
] = { .type
= NLA_NESTED
},
399 [IPSET_ATTR_ETHER
] = { .type
= NLA_BINARY
,
401 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
402 [IPSET_ATTR_LINENO
] = { .type
= NLA_U32
},
403 [IPSET_ATTR_BYTES
] = { .type
= NLA_U64
},
404 [IPSET_ATTR_PACKETS
] = { .type
= NLA_U64
},
405 [IPSET_ATTR_COMMENT
] = { .type
= NLA_NUL_STRING
,
406 .len
= IPSET_MAX_COMMENT_SIZE
},
407 [IPSET_ATTR_SKBMARK
] = { .type
= NLA_U64
},
408 [IPSET_ATTR_SKBPRIO
] = { .type
= NLA_U32
},
409 [IPSET_ATTR_SKBQUEUE
] = { .type
= NLA_U16
},
415 bitmap_ipmac_init(void)
417 return ip_set_type_register(&bitmap_ipmac_type
);
421 bitmap_ipmac_fini(void)
424 ip_set_type_unregister(&bitmap_ipmac_type
);
427 module_init(bitmap_ipmac_init
);
428 module_exit(bitmap_ipmac_fini
);