~ubuntu-branches/ubuntu/trusty/xtables-addons/trusty

« back to all changes in this revision

Viewing changes to extensions/ipset-5/libipset/data.c

  • Committer: Bazaar Package Importer
  • Author(s): Pierre Chifflier
  • Date: 2011-05-09 21:42:42 UTC
  • mfrom: (1.3.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20110509214242-x3qc2okkyupvefoy
Tags: 1.35-1
* Imported Upstream version 1.35
* Update version numbers for DKMS package (Closes: #620662)
* Bump Standards Version to 3.9.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
2
 
 *
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.
6
 
 */
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 */
13
 
 
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 */
19
 
 
20
 
/* Internal data structure to hold 
21
 
 * a) input data entered by the user or
22
 
 * b) data received from kernel
23
 
 *
24
 
 * We always store the data in host order, *except* IP addresses.
25
 
 */
26
 
 
27
 
struct ipset_data {
28
 
        /* Option bits: which fields are set */
29
 
        uint64_t bits;
30
 
        /* Option bits: which options are ignored */
31
 
        uint64_t ignored;
32
 
        /* Setname  */
33
 
        char setname[IPSET_MAXNAMELEN];
34
 
        /* Set type */
35
 
        const struct ipset_type *type;
36
 
        /* Common CADT options */
37
 
        uint8_t cidr;
38
 
        uint8_t family;
39
 
        uint32_t flags;         /* command level flags */
40
 
        uint32_t cadt_flags;    /* data level flags */
41
 
        uint32_t timeout;
42
 
        union nf_inet_addr ip;
43
 
        union nf_inet_addr ip_to;
44
 
        uint16_t port;
45
 
        uint16_t port_to;
46
 
        union {
47
 
                /* RENAME/SWAP */
48
 
                char setname2[IPSET_MAXNAMELEN];
49
 
                /* CREATE/LIST/SAVE */
50
 
                struct {
51
 
                        uint8_t probes;
52
 
                        uint8_t resize;
53
 
                        uint8_t netmask;
54
 
                        uint32_t hashsize;
55
 
                        uint32_t maxelem;
56
 
                        uint32_t gc;
57
 
                        uint32_t size;
58
 
                        /* Filled out by kernel */
59
 
                        uint32_t references;
60
 
                        uint32_t elements;
61
 
                        uint32_t memsize;
62
 
                        char typename[IPSET_MAXNAMELEN];
63
 
                        uint8_t revision_min;
64
 
                        uint8_t revision;
65
 
                } create;
66
 
                /* ADT/LIST/SAVE */
67
 
                struct {
68
 
                        union nf_inet_addr ip2;
69
 
                        uint8_t cidr2;
70
 
                        uint8_t proto;
71
 
                        char ether[ETH_ALEN];
72
 
                        char name[IPSET_MAXNAMELEN];
73
 
                        char nameref[IPSET_MAXNAMELEN];
74
 
                } adt;
75
 
        };
76
 
};
77
 
 
78
 
static void
79
 
copy_addr(uint8_t family, union nf_inet_addr *ip, const void *value)
80
 
{
81
 
        if (family == AF_INET)
82
 
                in4cpy(&ip->in, value);
83
 
        else
84
 
                in6cpy(&ip->in6, value);
85
 
}
86
 
 
87
 
/**
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.
92
 
 *
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.
95
 
 */
96
 
void
97
 
ipset_strlcpy(char *dst, const char *src, size_t len)
98
 
{
99
 
        assert(dst);
100
 
        assert(src);
101
 
 
102
 
        strncpy(dst, src, len);
103
 
        dst[len - 1] = '\0';
104
 
}
105
 
 
106
 
/**
107
 
 * ipset_data_flags_test - test option bits in the data blob
108
 
 * @data: data blob
109
 
 * @flags: the option flags to test
110
 
 *
111
 
 * Returns true if the options are already set in the data blob.
112
 
 */
113
 
bool
114
 
ipset_data_flags_test(const struct ipset_data *data, uint64_t flags)
115
 
{
116
 
        assert(data);
117
 
        return !!(data->bits & flags);
118
 
}
119
 
 
120
 
/**
121
 
 * ipset_data_flags_set - set option bits in the data blob
122
 
 * @data: data blob
123
 
 * @flags: the option flags to set
124
 
 *
125
 
 * The function sets the flags in the data blob so that
126
 
 * the corresponding fields are regarded as if filled with proper data.
127
 
 */
128
 
void
129
 
ipset_data_flags_set(struct ipset_data *data, uint64_t flags)
130
 
{
131
 
        assert(data);
132
 
        data->bits |= flags;
133
 
}
134
 
 
135
 
/**
136
 
 * ipset_data_flags_unset - unset option bits in the data blob
137
 
 * @data: data blob
138
 
 * @flags: the option flags to unset
139
 
 *
140
 
 * The function unsets the flags in the data blob.
141
 
 * This is the quick way to clear specific fields.
142
 
 */
143
 
void
144
 
ipset_data_flags_unset(struct ipset_data *data, uint64_t flags)
145
 
{
146
 
        assert(data);
147
 
        data->bits &= ~flags;
148
 
}
149
 
 
150
 
#define flag_type_attr(data, opt, flag)         \
151
 
do {                                            \
152
 
        data->flags |= flag;                    \
153
 
        opt = IPSET_OPT_FLAGS;                  \
154
 
} while (0)
155
 
 
156
 
#define cadt_flag_type_attr(data, opt, flag)    \
157
 
do {                                            \
158
 
        data->cadt_flags |= flag;               \
159
 
        opt = IPSET_OPT_CADT_FLAGS;             \
160
 
} while (0)
161
 
 
162
 
/**
163
 
 * ipset_data_ignored - test and set ignored bits in the data blob
164
 
 * @data: data blob
165
 
 * @flags: the option flag to be ignored
166
 
 *
167
 
 * Returns true if the option was not already ignored.
168
 
 */
169
 
bool
170
 
ipset_data_ignored(struct ipset_data *data, enum ipset_opt opt)
171
 
{
172
 
        bool ignored;
173
 
        assert(data);
174
 
        
175
 
        ignored = data->ignored & IPSET_FLAG(opt);
176
 
        data->ignored |= IPSET_FLAG(opt);
177
 
 
178
 
        return ignored;
179
 
}
180
 
 
181
 
/**
182
 
 * ipset_data_set - put data into the data blob
183
 
 * @data: data blob
184
 
 * @opt: the option kind of the data
185
 
 * @value: the value of the data
186
 
 *
187
 
 * Put a given kind of data into the data blob and mark the
188
 
 * option kind as already set in the blob.
189
 
 *
190
 
 * Returns 0 on success or a negative error code.
191
 
 */
192
 
int
193
 
ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
194
 
{
195
 
        assert(data);
196
 
        assert(opt != IPSET_OPT_NONE);
197
 
        assert(value);
198
 
 
199
 
        switch (opt) {
200
 
        /* Common ones */
201
 
        case IPSET_SETNAME:
202
 
                ipset_strlcpy(data->setname, value, IPSET_MAXNAMELEN);
203
 
                break;
204
 
        case IPSET_OPT_TYPE:
205
 
                data->type = value;
206
 
                break;
207
 
        case IPSET_OPT_FAMILY:
208
 
                data->family = *(const uint8_t *) value;
209
 
                D("family set to %u", data->family);
210
 
                break;
211
 
        /* CADT options */
212
 
        case IPSET_OPT_IP:
213
 
                if (!(data->family == AF_INET || data->family == AF_INET6))
214
 
                        return -1;
215
 
                copy_addr(data->family, &data->ip, value);
216
 
                break;
217
 
        case IPSET_OPT_IP_TO:
218
 
                if (!(data->family == AF_INET || data->family == AF_INET6))
219
 
                        return -1;
220
 
                copy_addr(data->family, &data->ip_to, value);
221
 
                break;
222
 
        case IPSET_OPT_CIDR:
223
 
                data->cidr = *(const uint8_t *) value;
224
 
                break;
225
 
        case IPSET_OPT_PORT:
226
 
                data->port = *(const uint16_t *) value;
227
 
                break;
228
 
        case IPSET_OPT_PORT_TO:
229
 
                data->port_to = *(const uint16_t *) value;
230
 
                break;
231
 
        case IPSET_OPT_TIMEOUT:
232
 
                data->timeout = *(const uint32_t *) value;
233
 
                break;
234
 
        /* Create-specific options */
235
 
        case IPSET_OPT_GC:
236
 
                data->create.gc = *(const uint32_t *) value;
237
 
                break;
238
 
        case IPSET_OPT_HASHSIZE:
239
 
                data->create.hashsize = *(const uint32_t *) value;
240
 
                break;
241
 
        case IPSET_OPT_MAXELEM:
242
 
                data->create.maxelem = *(const uint32_t *) value;
243
 
                break;
244
 
        case IPSET_OPT_NETMASK:
245
 
                data->create.netmask = *(const uint8_t *) value;
246
 
                break;
247
 
        case IPSET_OPT_PROBES:
248
 
                data->create.probes = *(const uint8_t *) value;
249
 
                break;
250
 
        case IPSET_OPT_RESIZE:
251
 
                data->create.resize = *(const uint8_t *) value;
252
 
                break;
253
 
        case IPSET_OPT_SIZE:
254
 
                data->create.size = *(const uint32_t *) value;
255
 
                break;
256
 
        /* Create-specific options, filled out by the kernel */
257
 
        case IPSET_OPT_ELEMENTS:
258
 
                data->create.elements = *(const uint32_t *) value;
259
 
                break;
260
 
        case IPSET_OPT_REFERENCES:
261
 
                data->create.references = *(const uint32_t *) value;
262
 
                break;
263
 
        case IPSET_OPT_MEMSIZE:
264
 
                data->create.memsize = *(const uint32_t *) value;
265
 
                break;
266
 
        /* Create-specific options, type */
267
 
        case IPSET_OPT_TYPENAME:
268
 
                ipset_strlcpy(data->create.typename, value,
269
 
                              IPSET_MAXNAMELEN);
270
 
                break;
271
 
        case IPSET_OPT_REVISION:
272
 
                data->create.revision = *(const uint8_t *) value;
273
 
                break;
274
 
        case IPSET_OPT_REVISION_MIN:
275
 
                data->create.revision_min = *(const uint8_t *) value;
276
 
                break;
277
 
        /* ADT-specific options */
278
 
        case IPSET_OPT_ETHER:
279
 
                memcpy(data->adt.ether, value, ETH_ALEN);
280
 
                break;
281
 
        case IPSET_OPT_NAME:
282
 
                ipset_strlcpy(data->adt.name, value, IPSET_MAXNAMELEN);
283
 
                break;
284
 
        case IPSET_OPT_NAMEREF:
285
 
                ipset_strlcpy(data->adt.nameref, value, IPSET_MAXNAMELEN);
286
 
                break;
287
 
        case IPSET_OPT_IP2:
288
 
                if (!(data->family == AF_INET || data->family == AF_INET6))
289
 
                        return -1;
290
 
                copy_addr(data->family, &data->adt.ip2, value);
291
 
                break;
292
 
        case IPSET_OPT_CIDR2:
293
 
                data->adt.cidr2 = *(const uint8_t *) value;
294
 
                break;
295
 
        case IPSET_OPT_PROTO:
296
 
                data->adt.proto = *(const uint8_t *) value;
297
 
                break;
298
 
        /* Swap/rename */
299
 
        case IPSET_OPT_SETNAME2:
300
 
                ipset_strlcpy(data->setname2, value, IPSET_MAXNAMELEN);
301
 
                break;
302
 
        /* flags */
303
 
        case IPSET_OPT_EXIST:
304
 
                flag_type_attr(data, opt, IPSET_FLAG_EXIST);
305
 
                break;
306
 
        case IPSET_OPT_BEFORE:
307
 
                cadt_flag_type_attr(data, opt, IPSET_FLAG_BEFORE);
308
 
                break;
309
 
        case IPSET_OPT_FLAGS:
310
 
                data->flags = *(const uint32_t *)value;
311
 
                break;
312
 
        case IPSET_OPT_CADT_FLAGS:
313
 
                data->cadt_flags = *(const uint32_t *)value;
314
 
                break;
315
 
        default:
316
 
                return -1;
317
 
        };
318
 
        
319
 
        ipset_data_flags_set(data, IPSET_FLAG(opt));
320
 
        return 0;
321
 
}
322
 
 
323
 
/**
324
 
 * ipset_data_get - get data from the data blob
325
 
 * @data: data blob
326
 
 * @opt: option kind of the requested data
327
 
 *
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,
330
 
 * NULL is returned.
331
 
 */
332
 
const void *
333
 
ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
334
 
{
335
 
        assert(data);
336
 
        assert(opt != IPSET_OPT_NONE);
337
 
        
338
 
        if (!(opt == IPSET_OPT_TYPENAME || ipset_data_test(data, opt)))
339
 
                return NULL;
340
 
 
341
 
        switch (opt) {
342
 
        /* Common ones */
343
 
        case IPSET_SETNAME:
344
 
                return data->setname;
345
 
        case IPSET_OPT_TYPE:
346
 
                return data->type;
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;
352
 
                return NULL;
353
 
        case IPSET_OPT_FAMILY:
354
 
                return &data->family;
355
 
        /* CADT options */
356
 
        case IPSET_OPT_IP:
357
 
                return &data->ip;
358
 
        case IPSET_OPT_IP_TO:
359
 
                 return &data->ip_to;
360
 
        case IPSET_OPT_CIDR:
361
 
                return &data->cidr;
362
 
        case IPSET_OPT_PORT:
363
 
                return &data->port;
364
 
        case IPSET_OPT_PORT_TO:
365
 
                return &data->port_to;
366
 
        case IPSET_OPT_TIMEOUT:
367
 
                return &data->timeout;
368
 
        /* Create-specific options */
369
 
        case IPSET_OPT_GC:
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;
381
 
        case IPSET_OPT_SIZE:
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;
398
 
        case IPSET_OPT_NAME:
399
 
                return data->adt.name;
400
 
        case IPSET_OPT_NAMEREF:
401
 
                return data->adt.nameref;
402
 
        case IPSET_OPT_IP2:
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;
408
 
        /* Swap/rename */
409
 
        case IPSET_OPT_SETNAME2:
410
 
                return data->setname2;
411
 
        /* flags */
412
 
        case IPSET_OPT_FLAGS:
413
 
        case IPSET_OPT_EXIST:
414
 
                return &data->flags;
415
 
        case IPSET_OPT_CADT_FLAGS:
416
 
        case IPSET_OPT_BEFORE:
417
 
                return &data->cadt_flags;
418
 
        default:
419
 
                return NULL;
420
 
        }
421
 
}
422
 
 
423
 
/**
424
 
 * ipset_data_sizeof - calculates the size of the data type
425
 
 * @opt: option kind of the data
426
 
 * @family: INET family
427
 
 *
428
 
 * Returns the size required to store the given data type.
429
 
 */
430
 
size_t
431
 
ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
432
 
{
433
 
        assert(opt != IPSET_OPT_NONE);
434
 
 
435
 
        switch (opt) {
436
 
        case IPSET_OPT_IP:
437
 
        case IPSET_OPT_IP_TO:
438
 
        case IPSET_OPT_IP2:
439
 
                return family == AF_INET ? sizeof(uint32_t)
440
 
                                         : sizeof(struct in6_addr);
441
 
        case IPSET_OPT_PORT:
442
 
        case IPSET_OPT_PORT_TO:
443
 
                return sizeof(uint16_t);
444
 
        case IPSET_SETNAME:
445
 
        case IPSET_OPT_NAME:
446
 
        case IPSET_OPT_NAMEREF:
447
 
                return IPSET_MAXNAMELEN;
448
 
        case IPSET_OPT_TIMEOUT:
449
 
        case IPSET_OPT_GC:
450
 
        case IPSET_OPT_HASHSIZE:
451
 
        case IPSET_OPT_MAXELEM:
452
 
        case IPSET_OPT_SIZE:
453
 
        case IPSET_OPT_ELEMENTS:
454
 
        case IPSET_OPT_REFERENCES:
455
 
        case IPSET_OPT_MEMSIZE:
456
 
                return sizeof(uint32_t);
457
 
        case IPSET_OPT_CIDR:
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:
465
 
                return ETH_ALEN;
466
 
        /* Flags counted once */
467
 
        case IPSET_OPT_BEFORE:
468
 
                return sizeof(uint32_t);
469
 
        default:
470
 
                return 0;
471
 
        };
472
 
}
473
 
 
474
 
/**
475
 
 * ipset_setname - return the name of the set from the data blob
476
 
 * @data: data blob
477
 
 *
478
 
 * Return the name of the set from the data blob or NULL if the
479
 
 * name not set yet.
480
 
 */
481
 
const char *
482
 
ipset_data_setname(const struct ipset_data *data)
483
 
{
484
 
        assert(data);
485
 
        return ipset_data_test(data, IPSET_SETNAME) ? data->setname : NULL;
486
 
}
487
 
 
488
 
/**
489
 
 * ipset_family - return the INET family of the set from the data blob
490
 
 * @data: data blob
491
 
 *
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.
494
 
 */
495
 
uint8_t
496
 
ipset_data_family(const struct ipset_data *data)
497
 
{
498
 
        assert(data);
499
 
        return ipset_data_test(data, IPSET_OPT_FAMILY)
500
 
                ? data->family : AF_UNSPEC;
501
 
}
502
 
 
503
 
/**
504
 
 * ipset_data_cidr - return the value of IPSET_OPT_CIDR
505
 
 * @data: data blob
506
 
 *
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.
510
 
 */
511
 
uint8_t
512
 
ipset_data_cidr(const struct ipset_data *data)
513
 
{
514
 
        assert(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;
518
 
}
519
 
 
520
 
/**
521
 
 * ipset_flags - return which fields are set in the data blob
522
 
 * @data: data blob
523
 
 *
524
 
 * Returns the value of the bit field which elements are set.
525
 
 */
526
 
uint64_t
527
 
ipset_data_flags(const struct ipset_data *data)
528
 
{
529
 
        assert(data);
530
 
        return data->bits;
531
 
}
532
 
 
533
 
/**
534
 
 * ipset_data_reset - reset the data blob to unset
535
 
 * @data: data blob
536
 
 *
537
 
 * Resets the data blob to the unset state for every field.
538
 
 */
539
 
void
540
 
ipset_data_reset(struct ipset_data *data)
541
 
{
542
 
        assert(data);
543
 
        memset(data, 0, sizeof(*data));
544
 
}
545
 
 
546
 
/**
547
 
 * ipset_data_init - create a new data blob
548
 
 *
549
 
 * Return the new data blob initialized to empty. In case of
550
 
 * an error, NULL is retured.
551
 
 */
552
 
struct ipset_data *
553
 
ipset_data_init(void)
554
 
{
555
 
        return calloc(1, sizeof(struct ipset_data));
556
 
}
557
 
 
558
 
/**
559
 
 * ipset_data_fini - release a data blob created by ipset_data_init
560
 
 *
561
 
 * Release the data blob created by ipset_data_init previously.
562
 
 */
563
 
void
564
 
ipset_data_fini(struct ipset_data *data)
565
 
{
566
 
        assert(data);
567
 
        free(data);
568
 
}