Skip to content

Commit 03c8b23

Browse files
author
Jozsef Kadlecsik
committed
netfilter: ipset: Generalize extensions support
Get rid of the structure based extensions and introduce a blob for the extensions. Thus we can support more extension types easily. Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
1 parent ca134ce commit 03c8b23

14 files changed

+118
-749
lines changed

include/linux/netfilter/ipset/ip_set.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,17 @@ enum ip_set_ext_id {
6666
IPSET_EXT_ID_MAX,
6767
};
6868

69+
/* Extension type */
70+
struct ip_set_ext_type {
71+
enum ip_set_extension type;
72+
enum ipset_cadt_flags flag;
73+
/* Size and minimal alignment */
74+
u8 len;
75+
u8 align;
76+
};
77+
78+
extern const struct ip_set_ext_type ip_set_extensions[];
79+
6980
struct ip_set_ext {
7081
u64 packets;
7182
u64 bytes;
@@ -283,6 +294,8 @@ extern void *ip_set_alloc(size_t size);
283294
extern void ip_set_free(void *members);
284295
extern int ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr);
285296
extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr);
297+
extern size_t ip_set_elem_len(struct ip_set *set, struct nlattr *tb[],
298+
size_t len);
286299
extern int ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[],
287300
struct ip_set_ext *ext);
288301

net/netfilter/ipset/ip_set_bitmap_ip.c

Lines changed: 8 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -208,25 +208,6 @@ bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b)
208208
struct bitmap_ip_elem {
209209
};
210210

211-
/* Timeout variant */
212-
213-
struct bitmap_ipt_elem {
214-
unsigned long timeout;
215-
};
216-
217-
/* Plain variant with counter */
218-
219-
struct bitmap_ipc_elem {
220-
struct ip_set_counter counter;
221-
};
222-
223-
/* Timeout variant with counter */
224-
225-
struct bitmap_ipct_elem {
226-
unsigned long timeout;
227-
struct ip_set_counter counter;
228-
};
229-
230211
#include "ip_set_bitmap_gen.h"
231212

232213
/* Create bitmap:ip type of sets */
@@ -263,7 +244,7 @@ static int
263244
bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
264245
{
265246
struct bitmap_ip *map;
266-
u32 first_ip = 0, last_ip = 0, hosts, cadt_flags = 0;
247+
u32 first_ip = 0, last_ip = 0, hosts;
267248
u64 elements;
268249
u8 netmask = 32;
269250
int ret;
@@ -335,61 +316,15 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
335316

336317
map->memsize = bitmap_bytes(0, elements - 1);
337318
set->variant = &bitmap_ip;
338-
if (tb[IPSET_ATTR_CADT_FLAGS])
339-
cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
340-
if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) {
341-
set->extensions |= IPSET_EXT_COUNTER;
342-
if (tb[IPSET_ATTR_TIMEOUT]) {
343-
set->dsize = sizeof(struct bitmap_ipct_elem);
344-
set->offset[IPSET_EXT_ID_TIMEOUT] =
345-
offsetof(struct bitmap_ipct_elem, timeout);
346-
set->offset[IPSET_EXT_ID_COUNTER] =
347-
offsetof(struct bitmap_ipct_elem, counter);
348-
349-
if (!init_map_ip(set, map, first_ip, last_ip,
350-
elements, hosts, netmask)) {
351-
kfree(map);
352-
return -ENOMEM;
353-
}
354-
355-
set->timeout = ip_set_timeout_uget(
356-
tb[IPSET_ATTR_TIMEOUT]);
357-
set->extensions |= IPSET_EXT_TIMEOUT;
358-
359-
bitmap_ip_gc_init(set, bitmap_ip_gc);
360-
} else {
361-
set->dsize = sizeof(struct bitmap_ipc_elem);
362-
set->offset[IPSET_EXT_ID_COUNTER] =
363-
offsetof(struct bitmap_ipc_elem, counter);
364-
365-
if (!init_map_ip(set, map, first_ip, last_ip,
366-
elements, hosts, netmask)) {
367-
kfree(map);
368-
return -ENOMEM;
369-
}
370-
}
371-
} else if (tb[IPSET_ATTR_TIMEOUT]) {
372-
set->dsize = sizeof(struct bitmap_ipt_elem);
373-
set->offset[IPSET_EXT_ID_TIMEOUT] =
374-
offsetof(struct bitmap_ipt_elem, timeout);
375-
376-
if (!init_map_ip(set, map, first_ip, last_ip,
377-
elements, hosts, netmask)) {
378-
kfree(map);
379-
return -ENOMEM;
380-
}
381-
319+
set->dsize = ip_set_elem_len(set, tb, 0);
320+
if (!init_map_ip(set, map, first_ip, last_ip,
321+
elements, hosts, netmask)) {
322+
kfree(map);
323+
return -ENOMEM;
324+
}
325+
if (tb[IPSET_ATTR_TIMEOUT]) {
382326
set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
383-
set->extensions |= IPSET_EXT_TIMEOUT;
384-
385327
bitmap_ip_gc_init(set, bitmap_ip_gc);
386-
} else {
387-
set->dsize = 0;
388-
if (!init_map_ip(set, map, first_ip, last_ip,
389-
elements, hosts, netmask)) {
390-
kfree(map);
391-
return -ENOMEM;
392-
}
393328
}
394329
return 0;
395330
}

net/netfilter/ipset/ip_set_bitmap_ipmac.c

Lines changed: 9 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -289,37 +289,6 @@ bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
289289

290290
/* Plain variant */
291291

292-
/* Timeout variant */
293-
294-
struct bitmap_ipmact_elem {
295-
struct {
296-
unsigned char ether[ETH_ALEN];
297-
unsigned char filled;
298-
} __attribute__ ((aligned));
299-
unsigned long timeout;
300-
};
301-
302-
/* Plain variant with counter */
303-
304-
struct bitmap_ipmacc_elem {
305-
struct {
306-
unsigned char ether[ETH_ALEN];
307-
unsigned char filled;
308-
} __attribute__ ((aligned));
309-
struct ip_set_counter counter;
310-
};
311-
312-
/* Timeout variant with counter */
313-
314-
struct bitmap_ipmacct_elem {
315-
struct {
316-
unsigned char ether[ETH_ALEN];
317-
unsigned char filled;
318-
} __attribute__ ((aligned));
319-
unsigned long timeout;
320-
struct ip_set_counter counter;
321-
};
322-
323292
#include "ip_set_bitmap_gen.h"
324293

325294
/* Create bitmap:ip,mac type of sets */
@@ -328,7 +297,7 @@ static bool
328297
init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
329298
u32 first_ip, u32 last_ip, u32 elements)
330299
{
331-
map->members = ip_set_alloc((last_ip - first_ip + 1) * set->dsize);
300+
map->members = ip_set_alloc(map->memsize);
332301
if (!map->members)
333302
return false;
334303
if (set->dsize) {
@@ -353,7 +322,7 @@ static int
353322
bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
354323
u32 flags)
355324
{
356-
u32 first_ip = 0, last_ip = 0, cadt_flags = 0;
325+
u32 first_ip = 0, last_ip = 0;
357326
u64 elements;
358327
struct bitmap_ipmac *map;
359328
int ret;
@@ -397,57 +366,15 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
397366

398367
map->memsize = bitmap_bytes(0, elements - 1);
399368
set->variant = &bitmap_ipmac;
400-
if (tb[IPSET_ATTR_CADT_FLAGS])
401-
cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
402-
if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) {
403-
set->extensions |= IPSET_EXT_COUNTER;
404-
if (tb[IPSET_ATTR_TIMEOUT]) {
405-
set->dsize = sizeof(struct bitmap_ipmacct_elem);
406-
set->offset[IPSET_EXT_ID_TIMEOUT] =
407-
offsetof(struct bitmap_ipmacct_elem, timeout);
408-
set->offset[IPSET_EXT_ID_COUNTER] =
409-
offsetof(struct bitmap_ipmacct_elem, counter);
410-
411-
if (!init_map_ipmac(set, map, first_ip, last_ip,
412-
elements)) {
413-
kfree(map);
414-
return -ENOMEM;
415-
}
416-
set->timeout = ip_set_timeout_uget(
417-
tb[IPSET_ATTR_TIMEOUT]);
418-
set->extensions |= IPSET_EXT_TIMEOUT;
419-
bitmap_ipmac_gc_init(set, bitmap_ipmac_gc);
420-
} else {
421-
set->dsize = sizeof(struct bitmap_ipmacc_elem);
422-
set->offset[IPSET_EXT_ID_COUNTER] =
423-
offsetof(struct bitmap_ipmacc_elem, counter);
424-
425-
if (!init_map_ipmac(set, map, first_ip, last_ip,
426-
elements)) {
427-
kfree(map);
428-
return -ENOMEM;
429-
}
430-
}
431-
} else if (tb[IPSET_ATTR_TIMEOUT]) {
432-
set->dsize = sizeof(struct bitmap_ipmact_elem);
433-
set->offset[IPSET_EXT_ID_TIMEOUT] =
434-
offsetof(struct bitmap_ipmact_elem, timeout);
435-
436-
if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
437-
kfree(map);
438-
return -ENOMEM;
439-
}
369+
set->dsize = ip_set_elem_len(set, tb,
370+
sizeof(struct bitmap_ipmac_elem));
371+
if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
372+
kfree(map);
373+
return -ENOMEM;
374+
}
375+
if (tb[IPSET_ATTR_TIMEOUT]) {
440376
set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
441-
set->extensions |= IPSET_EXT_TIMEOUT;
442377
bitmap_ipmac_gc_init(set, bitmap_ipmac_gc);
443-
} else {
444-
set->dsize = sizeof(struct bitmap_ipmac_elem);
445-
446-
if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
447-
kfree(map);
448-
return -ENOMEM;
449-
}
450-
set->variant = &bitmap_ipmac;
451378
}
452379
return 0;
453380
}

net/netfilter/ipset/ip_set_bitmap_port.c

Lines changed: 6 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -198,25 +198,6 @@ bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b)
198198
struct bitmap_port_elem {
199199
};
200200

201-
/* Timeout variant */
202-
203-
struct bitmap_portt_elem {
204-
unsigned long timeout;
205-
};
206-
207-
/* Plain variant with counter */
208-
209-
struct bitmap_portc_elem {
210-
struct ip_set_counter counter;
211-
};
212-
213-
/* Timeout variant with counter */
214-
215-
struct bitmap_portct_elem {
216-
unsigned long timeout;
217-
struct ip_set_counter counter;
218-
};
219-
220201
#include "ip_set_bitmap_gen.h"
221202

222203
/* Create bitmap:ip type of sets */
@@ -250,7 +231,6 @@ bitmap_port_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
250231
{
251232
struct bitmap_port *map;
252233
u16 first_port, last_port;
253-
u32 cadt_flags = 0;
254234

255235
if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
256236
!ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) ||
@@ -274,53 +254,14 @@ bitmap_port_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
274254
map->elements = last_port - first_port + 1;
275255
map->memsize = map->elements * sizeof(unsigned long);
276256
set->variant = &bitmap_port;
277-
if (tb[IPSET_ATTR_CADT_FLAGS])
278-
cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
279-
if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) {
280-
set->extensions |= IPSET_EXT_COUNTER;
281-
if (tb[IPSET_ATTR_TIMEOUT]) {
282-
set->dsize = sizeof(struct bitmap_portct_elem);
283-
set->offset[IPSET_EXT_ID_TIMEOUT] =
284-
offsetof(struct bitmap_portct_elem, timeout);
285-
set->offset[IPSET_EXT_ID_COUNTER] =
286-
offsetof(struct bitmap_portct_elem, counter);
287-
if (!init_map_port(set, map, first_port, last_port)) {
288-
kfree(map);
289-
return -ENOMEM;
290-
}
291-
292-
set->timeout =
293-
ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
294-
set->extensions |= IPSET_EXT_TIMEOUT;
295-
bitmap_port_gc_init(set, bitmap_port_gc);
296-
} else {
297-
set->dsize = sizeof(struct bitmap_portc_elem);
298-
set->offset[IPSET_EXT_ID_COUNTER] =
299-
offsetof(struct bitmap_portc_elem, counter);
300-
if (!init_map_port(set, map, first_port, last_port)) {
301-
kfree(map);
302-
return -ENOMEM;
303-
}
304-
}
305-
} else if (tb[IPSET_ATTR_TIMEOUT]) {
306-
set->dsize = sizeof(struct bitmap_portt_elem);
307-
set->offset[IPSET_EXT_ID_TIMEOUT] =
308-
offsetof(struct bitmap_portt_elem, timeout);
309-
if (!init_map_port(set, map, first_port, last_port)) {
310-
kfree(map);
311-
return -ENOMEM;
312-
}
313-
257+
set->dsize = ip_set_elem_len(set, tb, 0);
258+
if (!init_map_port(set, map, first_port, last_port)) {
259+
kfree(map);
260+
return -ENOMEM;
261+
}
262+
if (tb[IPSET_ATTR_TIMEOUT]) {
314263
set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
315-
set->extensions |= IPSET_EXT_TIMEOUT;
316264
bitmap_port_gc_init(set, bitmap_port_gc);
317-
} else {
318-
set->dsize = 0;
319-
if (!init_map_port(set, map, first_port, last_port)) {
320-
kfree(map);
321-
return -ENOMEM;
322-
}
323-
324265
}
325266
return 0;
326267
}

net/netfilter/ipset/ip_set_core.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,52 @@ ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr)
315315
}
316316
EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6);
317317

318+
/* ipset data extension types, in size order */
319+
320+
const struct ip_set_ext_type ip_set_extensions[] = {
321+
[IPSET_EXT_ID_COUNTER] = {
322+
.type = IPSET_EXT_COUNTER,
323+
.flag = IPSET_FLAG_WITH_COUNTERS,
324+
.len = sizeof(struct ip_set_counter),
325+
.align = __alignof__(struct ip_set_counter),
326+
},
327+
[IPSET_EXT_ID_TIMEOUT] = {
328+
.type = IPSET_EXT_TIMEOUT,
329+
.len = sizeof(unsigned long),
330+
.align = __alignof__(unsigned long),
331+
},
332+
};
333+
EXPORT_SYMBOL_GPL(ip_set_extensions);
334+
335+
static inline bool
336+
add_extension(enum ip_set_ext_id id, u32 flags, struct nlattr *tb[])
337+
{
338+
return ip_set_extensions[id].flag ?
339+
(flags & ip_set_extensions[id].flag) :
340+
!!tb[IPSET_ATTR_TIMEOUT];
341+
}
342+
343+
size_t
344+
ip_set_elem_len(struct ip_set *set, struct nlattr *tb[], size_t len)
345+
{
346+
enum ip_set_ext_id id;
347+
size_t offset = 0;
348+
u32 cadt_flags = 0;
349+
350+
if (tb[IPSET_ATTR_CADT_FLAGS])
351+
cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
352+
for (id = 0; id < IPSET_EXT_ID_MAX; id++) {
353+
if (!add_extension(id, cadt_flags, tb))
354+
continue;
355+
offset += ALIGN(len + offset, ip_set_extensions[id].align);
356+
set->offset[id] = offset;
357+
set->extensions |= ip_set_extensions[id].type;
358+
offset += ip_set_extensions[id].len;
359+
}
360+
return len + offset;
361+
}
362+
EXPORT_SYMBOL_GPL(ip_set_elem_len);
363+
318364
int
319365
ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[],
320366
struct ip_set_ext *ext)

0 commit comments

Comments
 (0)