1
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
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 <sys/socket.h> /* AF_ */
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;
48
char setname2[IPSET_MAXNAMELEN];
49
/* CREATE/LIST/SAVE */
58
/* Filled out by kernel */
62
char typename[IPSET_MAXNAMELEN];
68
union nf_inet_addr ip2;
72
char name[IPSET_MAXNAMELEN];
73
char nameref[IPSET_MAXNAMELEN];
79
copy_addr(uint8_t family, union nf_inet_addr *ip, const void *value)
81
if (family == AF_INET)
82
in4cpy(&ip->in, value);
84
in6cpy(&ip->in6, value);
88
* ipset_strlcpy - copy the string from src to dst
89
* @dst: the target string buffer
90
* @src: the source string buffer
91
* @len: the length of bytes to copy, including the terminating null byte.
93
* Copy the string from src to destination, but at most len bytes are
94
* copied. The target is unconditionally terminated by the null byte.
97
ipset_strlcpy(char *dst, const char *src, size_t len)
102
strncpy(dst, src, len);
107
* ipset_data_flags_test - test option bits in the data blob
109
* @flags: the option flags to test
111
* Returns true if the options are already set in the data blob.
114
ipset_data_flags_test(const struct ipset_data *data, uint64_t flags)
117
return !!(data->bits & flags);
121
* ipset_data_flags_set - set option bits in the data blob
123
* @flags: the option flags to set
125
* The function sets the flags in the data blob so that
126
* the corresponding fields are regarded as if filled with proper data.
129
ipset_data_flags_set(struct ipset_data *data, uint64_t flags)
136
* ipset_data_flags_unset - unset option bits in the data blob
138
* @flags: the option flags to unset
140
* The function unsets the flags in the data blob.
141
* This is the quick way to clear specific fields.
144
ipset_data_flags_unset(struct ipset_data *data, uint64_t flags)
147
data->bits &= ~flags;
150
#define flag_type_attr(data, opt, flag) \
152
data->flags |= flag; \
153
opt = IPSET_OPT_FLAGS; \
156
#define cadt_flag_type_attr(data, opt, flag) \
158
data->cadt_flags |= flag; \
159
opt = IPSET_OPT_CADT_FLAGS; \
163
* ipset_data_ignored - test and set ignored bits in the data blob
165
* @flags: the option flag to be ignored
167
* Returns true if the option was not already ignored.
170
ipset_data_ignored(struct ipset_data *data, enum ipset_opt opt)
175
ignored = data->ignored & IPSET_FLAG(opt);
176
data->ignored |= IPSET_FLAG(opt);
182
* ipset_data_set - put data into the data blob
184
* @opt: the option kind of the data
185
* @value: the value of the data
187
* Put a given kind of data into the data blob and mark the
188
* option kind as already set in the blob.
190
* Returns 0 on success or a negative error code.
193
ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
196
assert(opt != IPSET_OPT_NONE);
202
ipset_strlcpy(data->setname, value, IPSET_MAXNAMELEN);
207
case IPSET_OPT_FAMILY:
208
data->family = *(const uint8_t *) value;
209
D("family set to %u", data->family);
213
if (!(data->family == AF_INET || data->family == AF_INET6))
215
copy_addr(data->family, &data->ip, value);
217
case IPSET_OPT_IP_TO:
218
if (!(data->family == AF_INET || data->family == AF_INET6))
220
copy_addr(data->family, &data->ip_to, value);
223
data->cidr = *(const uint8_t *) value;
226
data->port = *(const uint16_t *) value;
228
case IPSET_OPT_PORT_TO:
229
data->port_to = *(const uint16_t *) value;
231
case IPSET_OPT_TIMEOUT:
232
data->timeout = *(const uint32_t *) value;
234
/* Create-specific options */
236
data->create.gc = *(const uint32_t *) value;
238
case IPSET_OPT_HASHSIZE:
239
data->create.hashsize = *(const uint32_t *) value;
241
case IPSET_OPT_MAXELEM:
242
data->create.maxelem = *(const uint32_t *) value;
244
case IPSET_OPT_NETMASK:
245
data->create.netmask = *(const uint8_t *) value;
247
case IPSET_OPT_PROBES:
248
data->create.probes = *(const uint8_t *) value;
250
case IPSET_OPT_RESIZE:
251
data->create.resize = *(const uint8_t *) value;
254
data->create.size = *(const uint32_t *) value;
256
/* Create-specific options, filled out by the kernel */
257
case IPSET_OPT_ELEMENTS:
258
data->create.elements = *(const uint32_t *) value;
260
case IPSET_OPT_REFERENCES:
261
data->create.references = *(const uint32_t *) value;
263
case IPSET_OPT_MEMSIZE:
264
data->create.memsize = *(const uint32_t *) value;
266
/* Create-specific options, type */
267
case IPSET_OPT_TYPENAME:
268
ipset_strlcpy(data->create.typename, value,
271
case IPSET_OPT_REVISION:
272
data->create.revision = *(const uint8_t *) value;
274
case IPSET_OPT_REVISION_MIN:
275
data->create.revision_min = *(const uint8_t *) value;
277
/* ADT-specific options */
278
case IPSET_OPT_ETHER:
279
memcpy(data->adt.ether, value, ETH_ALEN);
282
ipset_strlcpy(data->adt.name, value, IPSET_MAXNAMELEN);
284
case IPSET_OPT_NAMEREF:
285
ipset_strlcpy(data->adt.nameref, value, IPSET_MAXNAMELEN);
288
if (!(data->family == AF_INET || data->family == AF_INET6))
290
copy_addr(data->family, &data->adt.ip2, value);
292
case IPSET_OPT_CIDR2:
293
data->adt.cidr2 = *(const uint8_t *) value;
295
case IPSET_OPT_PROTO:
296
data->adt.proto = *(const uint8_t *) value;
299
case IPSET_OPT_SETNAME2:
300
ipset_strlcpy(data->setname2, value, IPSET_MAXNAMELEN);
303
case IPSET_OPT_EXIST:
304
flag_type_attr(data, opt, IPSET_FLAG_EXIST);
306
case IPSET_OPT_BEFORE:
307
cadt_flag_type_attr(data, opt, IPSET_FLAG_BEFORE);
309
case IPSET_OPT_FLAGS:
310
data->flags = *(const uint32_t *)value;
312
case IPSET_OPT_CADT_FLAGS:
313
data->cadt_flags = *(const uint32_t *)value;
319
ipset_data_flags_set(data, IPSET_FLAG(opt));
324
* ipset_data_get - get data from the data blob
326
* @opt: option kind of the requested data
328
* Returns the pointer to the requested kind of data from the data blob
329
* if it is set. If the option kind is not set or is an unkown type,
333
ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
336
assert(opt != IPSET_OPT_NONE);
338
if (!(opt == IPSET_OPT_TYPENAME || ipset_data_test(data, opt)))
344
return data->setname;
347
case IPSET_OPT_TYPENAME:
348
if (ipset_data_test(data, IPSET_OPT_TYPE))
349
return data->type->name;
350
else if (ipset_data_test(data, IPSET_OPT_TYPENAME))
351
return data->create.typename;
353
case IPSET_OPT_FAMILY:
354
return &data->family;
358
case IPSET_OPT_IP_TO:
364
case IPSET_OPT_PORT_TO:
365
return &data->port_to;
366
case IPSET_OPT_TIMEOUT:
367
return &data->timeout;
368
/* Create-specific options */
370
return &data->create.gc;
371
case IPSET_OPT_HASHSIZE:
372
return &data->create.hashsize;
373
case IPSET_OPT_MAXELEM:
374
return &data->create.maxelem;
375
case IPSET_OPT_NETMASK:
376
return &data->create.netmask;
377
case IPSET_OPT_PROBES:
378
return &data->create.probes;
379
case IPSET_OPT_RESIZE:
380
return &data->create.resize;
382
return &data->create.size;
383
/* Create-specific options, filled out by the kernel */
384
case IPSET_OPT_ELEMENTS:
385
return &data->create.elements;
386
case IPSET_OPT_REFERENCES:
387
return &data->create.references;
388
case IPSET_OPT_MEMSIZE:
389
return &data->create.memsize;
390
/* Create-specific options, TYPE */
391
case IPSET_OPT_REVISION:
392
return &data->create.revision;
393
case IPSET_OPT_REVISION_MIN:
394
return &data->create.revision_min;
395
/* ADT-specific options */
396
case IPSET_OPT_ETHER:
397
return data->adt.ether;
399
return data->adt.name;
400
case IPSET_OPT_NAMEREF:
401
return data->adt.nameref;
403
return &data->adt.ip2;
404
case IPSET_OPT_CIDR2:
405
return &data->adt.cidr2;
406
case IPSET_OPT_PROTO:
407
return &data->adt.proto;
409
case IPSET_OPT_SETNAME2:
410
return data->setname2;
412
case IPSET_OPT_FLAGS:
413
case IPSET_OPT_EXIST:
415
case IPSET_OPT_CADT_FLAGS:
416
case IPSET_OPT_BEFORE:
417
return &data->cadt_flags;
424
* ipset_data_sizeof - calculates the size of the data type
425
* @opt: option kind of the data
426
* @family: INET family
428
* Returns the size required to store the given data type.
431
ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
433
assert(opt != IPSET_OPT_NONE);
437
case IPSET_OPT_IP_TO:
439
return family == AF_INET ? sizeof(uint32_t)
440
: sizeof(struct in6_addr);
442
case IPSET_OPT_PORT_TO:
443
return sizeof(uint16_t);
446
case IPSET_OPT_NAMEREF:
447
return IPSET_MAXNAMELEN;
448
case IPSET_OPT_TIMEOUT:
450
case IPSET_OPT_HASHSIZE:
451
case IPSET_OPT_MAXELEM:
453
case IPSET_OPT_ELEMENTS:
454
case IPSET_OPT_REFERENCES:
455
case IPSET_OPT_MEMSIZE:
456
return sizeof(uint32_t);
458
case IPSET_OPT_CIDR2:
459
case IPSET_OPT_NETMASK:
460
case IPSET_OPT_PROBES:
461
case IPSET_OPT_RESIZE:
462
case IPSET_OPT_PROTO:
463
return sizeof(uint8_t);
464
case IPSET_OPT_ETHER:
466
/* Flags counted once */
467
case IPSET_OPT_BEFORE:
468
return sizeof(uint32_t);
475
* ipset_setname - return the name of the set from the data blob
478
* Return the name of the set from the data blob or NULL if the
482
ipset_data_setname(const struct ipset_data *data)
485
return ipset_data_test(data, IPSET_SETNAME) ? data->setname : NULL;
489
* ipset_family - return the INET family of the set from the data blob
492
* Return the INET family supported by the set from the data blob.
493
* If the family is not set yet, AF_UNSPEC is returned.
496
ipset_data_family(const struct ipset_data *data)
499
return ipset_data_test(data, IPSET_OPT_FAMILY)
500
? data->family : AF_UNSPEC;
504
* ipset_data_cidr - return the value of IPSET_OPT_CIDR
507
* Return the value of IPSET_OPT_CIDR stored in the data blob.
508
* If it is not set, then the returned value corresponds to
509
* the default one according to the family type or zero.
512
ipset_data_cidr(const struct ipset_data *data)
515
return ipset_data_test(data, IPSET_OPT_CIDR) ? data->cidr :
516
data->family == AF_INET ? 32 :
517
data->family == AF_INET6 ? 128 : 0;
521
* ipset_flags - return which fields are set in the data blob
524
* Returns the value of the bit field which elements are set.
527
ipset_data_flags(const struct ipset_data *data)
534
* ipset_data_reset - reset the data blob to unset
537
* Resets the data blob to the unset state for every field.
540
ipset_data_reset(struct ipset_data *data)
543
memset(data, 0, sizeof(*data));
547
* ipset_data_init - create a new data blob
549
* Return the new data blob initialized to empty. In case of
550
* an error, NULL is retured.
553
ipset_data_init(void)
555
return calloc(1, sizeof(struct ipset_data));
559
* ipset_data_fini - release a data blob created by ipset_data_init
561
* Release the data blob created by ipset_data_init previously.
564
ipset_data_fini(struct ipset_data *data)