1 /* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@netfilter.org)
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
7 #include <assert.h> /* assert */
8 #include <arpa/inet.h> /* ntoh* */
9 #include <net/ethernet.h> /* ETH_ALEN */
10 #include <net/if.h> /* IFNAMSIZ */
11 #include <stdlib.h> /* malloc, free */
12 #include <string.h> /* memset */
14 #include <libipset/linux_ip_set.h> /* IPSET_MAXNAMELEN */
15 #include <libipset/debug.h> /* D() */
16 #include <libipset/types.h> /* struct ipset_type */
17 #include <libipset/utils.h> /* inXcpy */
18 #include <libipset/data.h> /* prototypes */
20 /* Internal data structure to hold
21 * a) input data entered by the user or
22 * b) data received from kernel
24 * We always store the data in host order, *except* IP addresses.
28 /* Option bits: which fields are set */
30 /* Option bits: which options are ignored */
33 char setname
[IPSET_MAXNAMELEN
];
35 const struct ipset_type
*type
;
36 /* Common CADT options */
39 uint32_t flags
; /* command level flags */
40 uint32_t cadt_flags
; /* data level flags */
42 union nf_inet_addr ip
;
43 union nf_inet_addr ip_to
;
50 char setname2
[IPSET_MAXNAMELEN
];
51 /* CREATE/LIST/SAVE */
56 union nf_inet_addr bitmask
;
62 /* Filled out by kernel */
66 char typename
[IPSET_MAXNAMELEN
];
72 union nf_inet_addr ip2
;
73 union nf_inet_addr ip2_to
;
77 char name
[IPSET_MAXNAMELEN
];
78 char nameref
[IPSET_MAXNAMELEN
];
82 char comment
[IPSET_MAX_COMMENT_SIZE
+1];
91 copy_addr(uint8_t family
, union nf_inet_addr
*ip
, const void *value
)
93 if (family
== NFPROTO_IPV4
)
94 in4cpy(&ip
->in
, value
);
96 in6cpy(&ip
->in6
, value
);
100 * ipset_strlcpy - copy the string from src to dst
101 * @dst: the target string buffer
102 * @src: the source string buffer
103 * @len: the length of bytes to copy, including the terminating null byte.
105 * Copy the string from src to destination, but at most len bytes are
106 * copied. The target is unconditionally terminated by the null byte.
109 ipset_strlcpy(char *dst
, const char *src
, size_t len
)
114 strncpy(dst
, src
, len
);
119 * ipset_strlcat - concatenate the string from src to the end of dst
120 * @dst: the target string buffer
121 * @src: the source string buffer
122 * @len: the length of bytes to concat, including the terminating null byte.
124 * Cooncatenate the string in src to destination, but at most len bytes are
125 * copied. The target is unconditionally terminated by the null byte.
128 ipset_strlcat(char *dst
, const char *src
, size_t len
)
133 strncat(dst
, src
, len
);
138 * ipset_data_flags_test - test option bits in the data blob
140 * @flags: the option flags to test
142 * Returns true if the options are already set in the data blob.
145 ipset_data_flags_test(const struct ipset_data
*data
, uint64_t flags
)
148 return !!(data
->bits
& flags
);
152 * ipset_data_flags_set - set option bits in the data blob
154 * @flags: the option flags to set
156 * The function sets the flags in the data blob so that
157 * the corresponding fields are regarded as if filled with proper data.
160 ipset_data_flags_set(struct ipset_data
*data
, uint64_t flags
)
167 * ipset_data_flags_unset - unset option bits in the data blob
169 * @flags: the option flags to unset
171 * The function unsets the flags in the data blob.
172 * This is the quick way to clear specific fields.
175 ipset_data_flags_unset(struct ipset_data
*data
, uint64_t flags
)
178 data
->bits
&= ~flags
;
181 #define flag_type_attr(data, opt, flag) \
183 data->flags |= flag; \
184 opt = IPSET_OPT_FLAGS; \
187 #define cadt_flag_type_attr(data, opt, flag) \
189 data->cadt_flags |= flag; \
190 opt = IPSET_OPT_CADT_FLAGS; \
194 * ipset_data_ignored - test and set ignored bits in the data blob
196 * @flags: the option flag to be ignored
198 * Returns true if the option was already ignored.
201 ipset_data_ignored(struct ipset_data
*data
, enum ipset_opt opt
)
206 ignored
= data
->ignored
& IPSET_FLAG(opt
);
207 data
->ignored
|= IPSET_FLAG(opt
);
213 * ipset_data_test_ignored - test ignored bits in the data blob
215 * @flags: the option flag to be tested
217 * Returns true if the option is ignored.
220 ipset_data_test_ignored(struct ipset_data
*data
, enum ipset_opt opt
)
224 return data
->ignored
& IPSET_FLAG(opt
);
228 * ipset_data_set - put data into the data blob
230 * @opt: the option kind of the data
231 * @value: the value of the data
233 * Put a given kind of data into the data blob and mark the
234 * option kind as already set in the blob.
236 * Returns 0 on success or a negative error code.
239 ipset_data_set(struct ipset_data
*data
, enum ipset_opt opt
, const void *value
)
242 assert(opt
!= IPSET_OPT_NONE
);
248 ipset_strlcpy(data
->setname
, value
, IPSET_MAXNAMELEN
);
253 case IPSET_OPT_FAMILY
:
254 data
->family
= *(const uint8_t *) value
;
255 data
->ignored
&= ~IPSET_FLAG(IPSET_OPT_FAMILY
);
256 D("family set to %u", data
->family
);
260 if (!(data
->family
== NFPROTO_IPV4
||
261 data
->family
== NFPROTO_IPV6
))
263 copy_addr(data
->family
, &data
->ip
, value
);
265 case IPSET_OPT_IP_TO
:
266 if (!(data
->family
== NFPROTO_IPV4
||
267 data
->family
== NFPROTO_IPV6
))
269 copy_addr(data
->family
, &data
->ip_to
, value
);
272 data
->cidr
= *(const uint8_t *) value
;
275 data
->mark
= *(const uint32_t *) value
;
278 data
->port
= *(const uint16_t *) value
;
280 case IPSET_OPT_PORT_TO
:
281 data
->port_to
= *(const uint16_t *) value
;
283 case IPSET_OPT_TIMEOUT
:
284 data
->timeout
= *(const uint32_t *) value
;
286 case IPSET_OPT_INDEX
:
287 data
->index
= *(const uint16_t *) value
;
289 /* Create-specific options */
290 case IPSET_OPT_INITVAL
:
291 data
->create
.initval
= *(const uint32_t *) value
;
293 case IPSET_OPT_HASHSIZE
:
294 data
->create
.hashsize
= *(const uint32_t *) value
;
296 case IPSET_OPT_MAXELEM
:
297 data
->create
.maxelem
= *(const uint32_t *) value
;
299 case IPSET_OPT_MARKMASK
:
300 data
->create
.markmask
= *(const uint32_t *) value
;
302 case IPSET_OPT_NETMASK
:
303 data
->create
.netmask
= *(const uint8_t *) value
;
305 case IPSET_OPT_BITMASK
:
306 if (!(data
->family
== NFPROTO_IPV4
||
307 data
->family
== NFPROTO_IPV6
))
309 copy_addr(data
->family
, &data
->create
.bitmask
, value
);
311 case IPSET_OPT_BUCKETSIZE
:
312 data
->create
.bucketsize
= *(const uint8_t *) value
;
314 case IPSET_OPT_RESIZE
:
315 data
->create
.resize
= *(const uint8_t *) value
;
318 data
->create
.size
= *(const uint32_t *) value
;
320 case IPSET_OPT_COUNTERS
:
321 cadt_flag_type_attr(data
, opt
, IPSET_FLAG_WITH_COUNTERS
);
323 case IPSET_OPT_CREATE_COMMENT
:
324 cadt_flag_type_attr(data
, opt
, IPSET_FLAG_WITH_COMMENT
);
326 case IPSET_OPT_FORCEADD
:
327 cadt_flag_type_attr(data
, opt
, IPSET_FLAG_WITH_FORCEADD
);
329 case IPSET_OPT_SKBINFO
:
330 cadt_flag_type_attr(data
, opt
, IPSET_FLAG_WITH_SKBINFO
);
332 /* Create-specific options, filled out by the kernel */
333 case IPSET_OPT_ELEMENTS
:
334 data
->create
.elements
= *(const uint32_t *) value
;
336 case IPSET_OPT_REFERENCES
:
337 data
->create
.references
= *(const uint32_t *) value
;
339 case IPSET_OPT_MEMSIZE
:
340 data
->create
.memsize
= *(const uint32_t *) value
;
342 /* Create-specific options, type */
343 case IPSET_OPT_TYPENAME
:
344 ipset_strlcpy(data
->create
.typename
, value
,
347 case IPSET_OPT_REVISION
:
348 data
->create
.revision
= *(const uint8_t *) value
;
350 case IPSET_OPT_REVISION_MIN
:
351 data
->create
.revision_min
= *(const uint8_t *) value
;
353 /* ADT-specific options */
354 case IPSET_OPT_ETHER
:
355 memcpy(data
->adt
.ether
, value
, ETH_ALEN
);
358 ipset_strlcpy(data
->adt
.name
, value
, IPSET_MAXNAMELEN
);
360 case IPSET_OPT_NAMEREF
:
361 ipset_strlcpy(data
->adt
.nameref
, value
, IPSET_MAXNAMELEN
);
364 if (!(data
->family
== NFPROTO_IPV4
||
365 data
->family
== NFPROTO_IPV6
))
367 copy_addr(data
->family
, &data
->adt
.ip2
, value
);
369 case IPSET_OPT_IP2_TO
:
370 if (!(data
->family
== NFPROTO_IPV4
||
371 data
->family
== NFPROTO_IPV6
))
373 copy_addr(data
->family
, &data
->adt
.ip2_to
, value
);
375 case IPSET_OPT_CIDR2
:
376 data
->adt
.cidr2
= *(const uint8_t *) value
;
378 case IPSET_OPT_PROTO
:
379 data
->adt
.proto
= *(const uint8_t *) value
;
381 case IPSET_OPT_IFACE
:
382 ipset_strlcpy(data
->adt
.iface
, value
, IFNAMSIZ
);
384 case IPSET_OPT_PACKETS
:
385 data
->adt
.packets
= *(const uint64_t *) value
;
387 case IPSET_OPT_BYTES
:
388 data
->adt
.bytes
= *(const uint64_t *) value
;
390 case IPSET_OPT_ADT_COMMENT
:
391 ipset_strlcpy(data
->adt
.comment
, value
,
392 IPSET_MAX_COMMENT_SIZE
+ 1);
394 case IPSET_OPT_SKBMARK
:
395 data
->adt
.skbmark
= *(const uint64_t *) value
;
397 case IPSET_OPT_SKBPRIO
:
398 data
->adt
.skbprio
= *(const uint32_t *) value
;
400 case IPSET_OPT_SKBQUEUE
:
401 data
->adt
.skbqueue
= *(const uint16_t *) value
;
404 case IPSET_OPT_SETNAME2
:
405 ipset_strlcpy(data
->setname2
, value
, IPSET_MAXNAMELEN
);
408 case IPSET_OPT_EXIST
:
409 flag_type_attr(data
, opt
, IPSET_FLAG_EXIST
);
411 case IPSET_OPT_BEFORE
:
412 cadt_flag_type_attr(data
, opt
, IPSET_FLAG_BEFORE
);
414 case IPSET_OPT_PHYSDEV
:
415 cadt_flag_type_attr(data
, opt
, IPSET_FLAG_PHYSDEV
);
417 case IPSET_OPT_NOMATCH
:
418 cadt_flag_type_attr(data
, opt
, IPSET_FLAG_NOMATCH
);
420 case IPSET_OPT_IFACE_WILDCARD
:
421 cadt_flag_type_attr(data
, opt
, IPSET_FLAG_IFACE_WILDCARD
);
423 case IPSET_OPT_FLAGS
:
424 data
->flags
= *(const uint32_t *)value
;
426 case IPSET_OPT_CADT_FLAGS
:
427 data
->cadt_flags
= *(const uint32_t *)value
;
428 if (data
->cadt_flags
& IPSET_FLAG_BEFORE
)
429 ipset_data_flags_set(data
,
430 IPSET_FLAG(IPSET_OPT_BEFORE
));
431 if (data
->cadt_flags
& IPSET_FLAG_PHYSDEV
)
432 ipset_data_flags_set(data
,
433 IPSET_FLAG(IPSET_OPT_PHYSDEV
));
434 if (data
->cadt_flags
& IPSET_FLAG_NOMATCH
)
435 ipset_data_flags_set(data
,
436 IPSET_FLAG(IPSET_OPT_NOMATCH
));
437 if (data
->cadt_flags
& IPSET_FLAG_WITH_COUNTERS
)
438 ipset_data_flags_set(data
,
439 IPSET_FLAG(IPSET_OPT_COUNTERS
));
440 if (data
->cadt_flags
& IPSET_FLAG_WITH_COMMENT
)
441 ipset_data_flags_set(data
,
442 IPSET_FLAG(IPSET_OPT_CREATE_COMMENT
));
443 if (data
->cadt_flags
& IPSET_FLAG_WITH_SKBINFO
)
444 ipset_data_flags_set(data
,
445 IPSET_FLAG(IPSET_OPT_SKBINFO
));
446 if (data
->cadt_flags
& IPSET_FLAG_IFACE_WILDCARD
)
447 ipset_data_flags_set(data
,
448 IPSET_FLAG(IPSET_OPT_IFACE_WILDCARD
));
454 ipset_data_flags_set(data
, IPSET_FLAG(opt
));
459 * ipset_data_get - get data from the data blob
461 * @opt: option kind of the requested data
463 * Returns the pointer to the requested kind of data from the data blob
464 * if it is set. If the option kind is not set or is an unknown type,
468 ipset_data_get(const struct ipset_data
*data
, enum ipset_opt opt
)
471 assert(opt
!= IPSET_OPT_NONE
);
473 if (!(opt
== IPSET_OPT_TYPENAME
|| ipset_data_test(data
, opt
)))
479 return data
->setname
;
482 case IPSET_OPT_TYPENAME
:
483 if (ipset_data_test(data
, IPSET_OPT_TYPE
))
484 return data
->type
->name
;
485 else if (ipset_data_test(data
, IPSET_OPT_TYPENAME
))
486 return data
->create
.typename
;
488 case IPSET_OPT_FAMILY
:
489 return &data
->family
;
493 case IPSET_OPT_IP_TO
:
501 case IPSET_OPT_PORT_TO
:
502 return &data
->port_to
;
503 case IPSET_OPT_TIMEOUT
:
504 return &data
->timeout
;
505 case IPSET_OPT_INDEX
:
507 /* Create-specific options */
508 case IPSET_OPT_INITVAL
:
509 return &data
->create
.initval
;
510 case IPSET_OPT_HASHSIZE
:
511 return &data
->create
.hashsize
;
512 case IPSET_OPT_MAXELEM
:
513 return &data
->create
.maxelem
;
514 case IPSET_OPT_MARKMASK
:
515 return &data
->create
.markmask
;
516 case IPSET_OPT_NETMASK
:
517 return &data
->create
.netmask
;
518 case IPSET_OPT_BITMASK
:
519 return &data
->create
.bitmask
;
520 case IPSET_OPT_BUCKETSIZE
:
521 return &data
->create
.bucketsize
;
522 case IPSET_OPT_RESIZE
:
523 return &data
->create
.resize
;
525 return &data
->create
.size
;
526 /* Create-specific options, filled out by the kernel */
527 case IPSET_OPT_ELEMENTS
:
528 return &data
->create
.elements
;
529 case IPSET_OPT_REFERENCES
:
530 return &data
->create
.references
;
531 case IPSET_OPT_MEMSIZE
:
532 return &data
->create
.memsize
;
533 /* Create-specific options, TYPE */
534 case IPSET_OPT_REVISION
:
535 return &data
->create
.revision
;
536 case IPSET_OPT_REVISION_MIN
:
537 return &data
->create
.revision_min
;
538 /* ADT-specific options */
539 case IPSET_OPT_ETHER
:
540 return data
->adt
.ether
;
542 return data
->adt
.name
;
543 case IPSET_OPT_NAMEREF
:
544 return data
->adt
.nameref
;
546 return &data
->adt
.ip2
;
547 case IPSET_OPT_IP2_TO
:
548 return &data
->adt
.ip2_to
;
549 case IPSET_OPT_CIDR2
:
550 return &data
->adt
.cidr2
;
551 case IPSET_OPT_PROTO
:
552 return &data
->adt
.proto
;
553 case IPSET_OPT_IFACE
:
554 return &data
->adt
.iface
;
555 case IPSET_OPT_PACKETS
:
556 return &data
->adt
.packets
;
557 case IPSET_OPT_BYTES
:
558 return &data
->adt
.bytes
;
559 case IPSET_OPT_ADT_COMMENT
:
560 return &data
->adt
.comment
;
561 case IPSET_OPT_SKBMARK
:
562 return &data
->adt
.skbmark
;
563 case IPSET_OPT_SKBPRIO
:
564 return &data
->adt
.skbprio
;
565 case IPSET_OPT_SKBQUEUE
:
566 return &data
->adt
.skbqueue
;
568 case IPSET_OPT_SETNAME2
:
569 return data
->setname2
;
571 case IPSET_OPT_FLAGS
:
572 case IPSET_OPT_EXIST
:
574 case IPSET_OPT_CADT_FLAGS
:
575 case IPSET_OPT_BEFORE
:
576 case IPSET_OPT_PHYSDEV
:
577 case IPSET_OPT_NOMATCH
:
578 case IPSET_OPT_COUNTERS
:
579 case IPSET_OPT_CREATE_COMMENT
:
580 case IPSET_OPT_FORCEADD
:
581 case IPSET_OPT_SKBINFO
:
582 case IPSET_OPT_IFACE_WILDCARD
:
583 return &data
->cadt_flags
;
590 * ipset_data_sizeof - calculates the size of the data type
591 * @opt: option kind of the data
592 * @family: INET family
594 * Returns the size required to store the given data type.
597 ipset_data_sizeof(enum ipset_opt opt
, uint8_t family
)
599 assert(opt
!= IPSET_OPT_NONE
);
603 case IPSET_OPT_IP_TO
:
605 case IPSET_OPT_IP2_TO
:
606 case IPSET_OPT_BITMASK
:
607 return family
== NFPROTO_IPV4
? sizeof(uint32_t)
608 : sizeof(struct in6_addr
);
610 return sizeof(uint32_t);
612 case IPSET_OPT_PORT_TO
:
613 case IPSET_OPT_SKBQUEUE
:
614 case IPSET_OPT_INDEX
:
615 return sizeof(uint16_t);
618 case IPSET_OPT_NAMEREF
:
619 return IPSET_MAXNAMELEN
;
620 case IPSET_OPT_TIMEOUT
:
621 case IPSET_OPT_INITVAL
:
622 case IPSET_OPT_HASHSIZE
:
623 case IPSET_OPT_MAXELEM
:
624 case IPSET_OPT_MARKMASK
:
626 case IPSET_OPT_ELEMENTS
:
627 case IPSET_OPT_REFERENCES
:
628 case IPSET_OPT_MEMSIZE
:
629 case IPSET_OPT_SKBPRIO
:
630 return sizeof(uint32_t);
631 case IPSET_OPT_PACKETS
:
632 case IPSET_OPT_BYTES
:
633 case IPSET_OPT_SKBMARK
:
634 return sizeof(uint64_t);
636 case IPSET_OPT_CIDR2
:
637 case IPSET_OPT_NETMASK
:
638 case IPSET_OPT_BUCKETSIZE
:
639 case IPSET_OPT_RESIZE
:
640 case IPSET_OPT_PROTO
:
641 return sizeof(uint8_t);
642 case IPSET_OPT_ETHER
:
644 /* Flags doesn't counted once :-( */
645 case IPSET_OPT_BEFORE
:
646 case IPSET_OPT_PHYSDEV
:
647 case IPSET_OPT_NOMATCH
:
648 case IPSET_OPT_COUNTERS
:
649 case IPSET_OPT_FORCEADD
:
650 case IPSET_OPT_IFACE_WILDCARD
:
651 return sizeof(uint32_t);
652 case IPSET_OPT_ADT_COMMENT
:
653 return IPSET_MAX_COMMENT_SIZE
+ 1;
660 * ipset_setname - return the name of the set from the data blob
663 * Return the name of the set from the data blob or NULL if the
667 ipset_data_setname(const struct ipset_data
*data
)
670 return ipset_data_test(data
, IPSET_SETNAME
) ? data
->setname
: NULL
;
674 * ipset_family - return the INET family of the set from the data blob
677 * Return the INET family supported by the set from the data blob.
678 * If the family is not set yet, NFPROTO_UNSPEC is returned.
681 ipset_data_family(const struct ipset_data
*data
)
684 return ipset_data_test(data
, IPSET_OPT_FAMILY
)
685 ? data
->family
: NFPROTO_UNSPEC
;
689 * ipset_data_cidr - return the value of IPSET_OPT_CIDR
692 * Return the value of IPSET_OPT_CIDR stored in the data blob.
693 * If it is not set, then the returned value corresponds to
694 * the default one according to the family type or zero.
697 ipset_data_cidr(const struct ipset_data
*data
)
700 return ipset_data_test(data
, IPSET_OPT_CIDR
) ? data
->cidr
:
701 data
->family
== NFPROTO_IPV4
? 32 :
702 data
->family
== NFPROTO_IPV6
? 128 : 0;
706 * ipset_flags - return which fields are set in the data blob
709 * Returns the value of the bit field which elements are set.
712 ipset_data_flags(const struct ipset_data
*data
)
719 * ipset_data_reset - reset the data blob to unset
722 * Resets the data blob to the unset state for every field.
725 ipset_data_reset(struct ipset_data
*data
)
728 memset(data
, 0, sizeof(*data
));
732 * ipset_data_init - create a new data blob
734 * Return the new data blob initialized to empty. In case of
735 * an error, NULL is retured.
738 ipset_data_init(void)
740 return calloc(1, sizeof(struct ipset_data
));
744 * ipset_data_fini - release a data blob created by ipset_data_init
746 * Release the data blob created by ipset_data_init previously.
749 ipset_data_fini(struct ipset_data
*data
)