~serge-hallyn/ubuntu/oneiric/libvirt/fix-shutdown

« back to all changes in this revision

Viewing changes to .pc/9027-Make-newfilter-xml-transformations-endian-safe.patch/src/conf/nwfilter_conf.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2010-11-02 16:26:51 UTC
  • mfrom: (1.2.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20101102162651-aq8tnbz58mdf01bf
Tags: 0.8.5-0ubuntu1
* New upstream release.
* Removed a slew of patches which have been
  applied upstream since 0.8.3.
  - 9012-apparmor-extra-tests.patch
  - 9013-apparmor-chardev.patch
  - 9015-Add-ubd-to-the-list-of-disk-prefixes.patch
  - 9016-Close-fd-s-of-persistent-tap-devices.patch
  - 9017-Make-sure-all-command-line-arguments-get-passed-to-U.patch
  - 9018-Make-umlConnectTapDevice-ask-brAddTap-for-a-persiste.patch
  - 9019-uml-fix-logic-bug-in-checking-reply-length.patch
  - 9021-Allow-chardev-of-type-file-for-UML-domains.patch
  - 9022-Rename-qemudShrinkDisks-to-virDomainDiskRemove-and-m.patch
  - 9023-Support-virDomainAttachDevice-and-virDomainDetachDev.patch
  - 9024-Explicitly-pass-uml_dir-argument-to-user-mode-linux.patch
  - 9025-Add-nwfilter-support-to-UML-driver.patch
  - 9026-Rebuild-network-filter-for-UML-guests-on-updates.patch
  - 9027-Make-newfilter-xml-transformations-endian-safe.patch
  - 9028-lp628055.patch
* Updated 9002-better_default_uri_virsh.patch to use vshStrdup,
  as now required in that file.  (use of strdup now causes compilation
  to fail)
* Removed 9008-run-as-root-by-default.patch, which has not been
  applied for awhile now, with no ill effects.
* Simple refresh of:
  - 0001-remove-RHism.diff.patch
  - 0003-allow-libvirt-group-to-access-the-socket.patch
  - 0004-fix-Debian-specific-path-to-hvm-loader.patch
  - 0006-patch-qemuMonitorTextGetMigrationStatus-to-intercept.patch
  - 9000-delayed_iff_up_bridge.patch
  - 9001-dont_clobber_existing_bridges.patch
  - 9003-better-default-arch.patch
  - 9004-libvirtd-group-name.patch
  - 9005-increase-unix-socket-timeout.patch
  - 9006-default-config-test-case.patch
  - 9009-autodetect-nc-params.patch
  - 9010-dont-disable-ipv6.patch
  - 9011-move-ebtables-script.patch
  - 9014-skip-nodeinfotest.patch
  - 9020-lp545795.patch
* Create a patch to include stdint.h so lxc_container.h, which
  #includes linux/fs.h, doesn't trip up on undefined uint64_t.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * nwfilter_conf.c: network filter XML processing
3
 
 *                  (derived from storage_conf.c)
4
 
 *
5
 
 * Copyright (C) 2006-2010 Red Hat, Inc.
6
 
 * Copyright (C) 2006-2008 Daniel P. Berrange
7
 
 *
8
 
 * Copyright (C) 2010 IBM Corporation
9
 
 *
10
 
 * This library is free software; you can redistribute it and/or
11
 
 * modify it under the terms of the GNU Lesser General Public
12
 
 * License as published by the Free Software Foundation; either
13
 
 * version 2.1 of the License, or (at your option) any later version.
14
 
 *
15
 
 * This library is distributed in the hope that it will be useful,
16
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 
 * Lesser General Public License for more details.
19
 
 *
20
 
 * You should have received a copy of the GNU Lesser General Public
21
 
 * License along with this library; if not, write to the Free Software
22
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
23
 
 *
24
 
 * Author: Stefan Berger <stefanb@us.ibm.com>
25
 
 */
26
 
 
27
 
#include <config.h>
28
 
 
29
 
#include <sys/types.h>
30
 
#include <sys/stat.h>
31
 
#include <fcntl.h>
32
 
#include <dirent.h>
33
 
#if HAVE_NET_ETHERNET_H
34
 
# include <net/ethernet.h>
35
 
#endif
36
 
#include <unistd.h>
37
 
 
38
 
#include "internal.h"
39
 
 
40
 
#include "uuid.h"
41
 
#include "memory.h"
42
 
#include "virterror_internal.h"
43
 
#include "datatypes.h"
44
 
#include "nwfilter_params.h"
45
 
#include "nwfilter_conf.h"
46
 
#include "domain_conf.h"
47
 
 
48
 
 
49
 
#define VIR_FROM_THIS VIR_FROM_NWFILTER
50
 
 
51
 
 
52
 
VIR_ENUM_IMPL(virNWFilterRuleAction, VIR_NWFILTER_RULE_ACTION_LAST,
53
 
              "drop",
54
 
              "accept");
55
 
 
56
 
VIR_ENUM_IMPL(virNWFilterJumpTarget, VIR_NWFILTER_RULE_ACTION_LAST,
57
 
              "DROP",
58
 
              "ACCEPT");
59
 
 
60
 
VIR_ENUM_IMPL(virNWFilterRuleDirection, VIR_NWFILTER_RULE_DIRECTION_LAST,
61
 
              "in",
62
 
              "out",
63
 
              "inout");
64
 
 
65
 
VIR_ENUM_IMPL(virNWFilterChainPolicy, VIR_NWFILTER_CHAIN_POLICY_LAST,
66
 
              "ACCEPT",
67
 
              "DROP");
68
 
 
69
 
VIR_ENUM_IMPL(virNWFilterEbtablesTable, VIR_NWFILTER_EBTABLES_TABLE_LAST,
70
 
              "filter",
71
 
              "nat",
72
 
              "broute");
73
 
 
74
 
VIR_ENUM_IMPL(virNWFilterChainSuffix, VIR_NWFILTER_CHAINSUFFIX_LAST,
75
 
              "root",
76
 
              "arp",
77
 
              "rarp",
78
 
              "ipv4",
79
 
              "ipv6");
80
 
 
81
 
VIR_ENUM_IMPL(virNWFilterRuleProtocol, VIR_NWFILTER_RULE_PROTOCOL_LAST,
82
 
              "none",
83
 
              "mac",
84
 
              "arp",
85
 
              "rarp",
86
 
              "ip",
87
 
              "ipv6",
88
 
              "tcp",
89
 
              "icmp",
90
 
              "igmp",
91
 
              "udp",
92
 
              "udplite",
93
 
              "esp",
94
 
              "ah",
95
 
              "sctp",
96
 
              "all",
97
 
              "tcp-ipv6",
98
 
              "icmpv6",
99
 
              "udp-ipv6",
100
 
              "udplite-ipv6",
101
 
              "esp-ipv6",
102
 
              "ah-ipv6",
103
 
              "sctp-ipv6",
104
 
              "all-ipv6");
105
 
 
106
 
 
107
 
/*
108
 
 * a map entry for a simple static int-to-string map
109
 
 */
110
 
struct int_map {
111
 
    int32_t attr;
112
 
    const char *val;
113
 
};
114
 
 
115
 
#define INTMAP_ENTRY(ATT, VAL) { .attr = ATT, .val = VAL }
116
 
#define INTMAP_ENTRY_LAST      { .val = NULL }
117
 
 
118
 
 
119
 
/*
120
 
 * only one filter update allowed
121
 
 */
122
 
static virMutex updateMutex;
123
 
 
124
 
void
125
 
virNWFilterLockFilterUpdates(void) {
126
 
    virMutexLock(&updateMutex);
127
 
}
128
 
 
129
 
void
130
 
virNWFilterUnlockFilterUpdates(void) {
131
 
    virMutexUnlock(&updateMutex);
132
 
}
133
 
 
134
 
 
135
 
 
136
 
/*
137
 
 * attribute names for the rules XML
138
 
 */
139
 
static const char srcmacaddr_str[]   = "srcmacaddr";
140
 
static const char srcmacmask_str[]   = "srcmacmask";
141
 
static const char dstmacaddr_str[]   = "dstmacaddr";
142
 
static const char dstmacmask_str[]   = "dstmacmask";
143
 
static const char arpsrcmacaddr_str[]= "arpsrcmacaddr";
144
 
static const char arpdstmacaddr_str[]= "arpdstmacaddr";
145
 
static const char arpsrcipaddr_str[] = "arpsrcipaddr";
146
 
static const char arpdstipaddr_str[] = "arpdstipaddr";
147
 
static const char srcipaddr_str[]    = "srcipaddr";
148
 
static const char srcipmask_str[]    = "srcipmask";
149
 
static const char dstipaddr_str[]    = "dstipaddr";
150
 
static const char dstipmask_str[]    = "dstipmask";
151
 
static const char srcipfrom_str[]    = "srcipfrom";
152
 
static const char srcipto_str[]      = "srcipto";
153
 
static const char dstipfrom_str[]    = "dstipfrom";
154
 
static const char dstipto_str[]      = "dstipto";
155
 
static const char srcportstart_str[] = "srcportstart";
156
 
static const char srcportend_str[]   = "srcportend";
157
 
static const char dstportstart_str[] = "dstportstart";
158
 
static const char dstportend_str[]   = "dstportend";
159
 
static const char dscp_str[]         = "dscp";
160
 
 
161
 
#define SRCMACADDR    srcmacaddr_str
162
 
#define SRCMACMASK    srcmacmask_str
163
 
#define DSTMACADDR    dstmacaddr_str
164
 
#define DSTMACMASK    dstmacmask_str
165
 
#define ARPSRCMACADDR arpsrcmacaddr_str
166
 
#define ARPDSTMACADDR arpdstmacaddr_str
167
 
#define ARPSRCIPADDR  arpsrcipaddr_str
168
 
#define ARPDSTIPADDR  arpdstipaddr_str
169
 
#define SRCIPADDR     srcipaddr_str
170
 
#define SRCIPMASK     srcipmask_str
171
 
#define DSTIPADDR     dstipaddr_str
172
 
#define DSTIPMASK     dstipmask_str
173
 
#define SRCIPFROM     srcipfrom_str
174
 
#define SRCIPTO       srcipto_str
175
 
#define DSTIPFROM     dstipfrom_str
176
 
#define DSTIPTO       dstipto_str
177
 
#define SRCPORTSTART  srcportstart_str
178
 
#define SRCPORTEND    srcportend_str
179
 
#define DSTPORTSTART  dstportstart_str
180
 
#define DSTPORTEND    dstportend_str
181
 
#define DSCP          dscp_str
182
 
 
183
 
 
184
 
/**
185
 
 * intMapGetByInt:
186
 
 * @intmap: Pointer to int-to-string map
187
 
 * @attr: The attribute to look up
188
 
 * @res: Pointer to string pointer for result
189
 
 *
190
 
 * Returns 1 if value was found with result returned, 0 otherwise.
191
 
 *
192
 
 * lookup a map entry given the integer.
193
 
 */
194
 
static bool
195
 
intMapGetByInt(const struct int_map *intmap, int32_t attr, const char **res)
196
 
{
197
 
    int i = 0;
198
 
    bool found = 0;
199
 
    while (intmap[i].val && !found) {
200
 
        if (intmap[i].attr == attr) {
201
 
            *res = intmap[i].val;
202
 
            found = 1;
203
 
        }
204
 
        i++;
205
 
    }
206
 
    return found;
207
 
}
208
 
 
209
 
 
210
 
/**
211
 
 * intMapGetByString:
212
 
 * @intmap: Pointer to int-to-string map
213
 
 * @str: Pointer to string for which to find the entry
214
 
 * @casecmp : Whether to ignore case when doing string matching
215
 
 * @result: Pointer to int for result
216
 
 *
217
 
 * Returns 0 if no entry was found, 1 otherwise.
218
 
 *
219
 
 * Do a lookup in the map trying to find an integer key using the string
220
 
 * value. Returns 1 if entry was found with result returned, 0 otherwise.
221
 
 */
222
 
static bool
223
 
intMapGetByString(const struct int_map *intmap, const char *str, int casecmp,
224
 
                  int32_t *result)
225
 
{
226
 
    int i = 0;
227
 
    bool found = 0;
228
 
    while (intmap[i].val && !found) {
229
 
        if ( (casecmp && STRCASEEQ(intmap[i].val, str)) ||
230
 
                         STREQ    (intmap[i].val, str)    ) {
231
 
            *result = intmap[i].attr;
232
 
            found = 1;
233
 
        }
234
 
        i++;
235
 
    }
236
 
    return found;
237
 
}
238
 
 
239
 
 
240
 
void
241
 
virNWFilterRuleDefFree(virNWFilterRuleDefPtr def) {
242
 
    int i;
243
 
    if (!def)
244
 
        return;
245
 
 
246
 
    for (i = 0; i < def->nvars; i++)
247
 
        VIR_FREE(def->vars[i]);
248
 
 
249
 
    VIR_FREE(def->vars);
250
 
 
251
 
    VIR_FREE(def);
252
 
}
253
 
 
254
 
 
255
 
static void
256
 
virNWFilterIncludeDefFree(virNWFilterIncludeDefPtr inc) {
257
 
    if (!inc)
258
 
        return;
259
 
    virNWFilterHashTableFree(inc->params);
260
 
    VIR_FREE(inc->filterref);
261
 
    VIR_FREE(inc);
262
 
}
263
 
 
264
 
 
265
 
static void
266
 
virNWFilterEntryFree(virNWFilterEntryPtr entry) {
267
 
    if (!entry)
268
 
        return;
269
 
 
270
 
    virNWFilterRuleDefFree(entry->rule);
271
 
    virNWFilterIncludeDefFree(entry->include);
272
 
    VIR_FREE(entry);
273
 
}
274
 
 
275
 
 
276
 
void
277
 
virNWFilterDefFree(virNWFilterDefPtr def) {
278
 
    int i;
279
 
    if (!def)
280
 
        return;
281
 
 
282
 
    VIR_FREE(def->name);
283
 
 
284
 
    for (i = 0; i < def->nentries; i++)
285
 
        virNWFilterEntryFree(def->filterEntries[i]);
286
 
 
287
 
    VIR_FREE(def->filterEntries);
288
 
 
289
 
    VIR_FREE(def);
290
 
}
291
 
 
292
 
 
293
 
void
294
 
virNWFilterPoolObjFree(virNWFilterPoolObjPtr obj) {
295
 
    if (!obj)
296
 
        return;
297
 
 
298
 
    virNWFilterDefFree(obj->def);
299
 
    virNWFilterDefFree(obj->newDef);
300
 
 
301
 
    VIR_FREE(obj->configFile);
302
 
 
303
 
    virMutexDestroy(&obj->lock);
304
 
 
305
 
    VIR_FREE(obj);
306
 
}
307
 
 
308
 
 
309
 
void
310
 
virNWFilterPoolObjListFree(virNWFilterPoolObjListPtr pools)
311
 
{
312
 
    unsigned int i;
313
 
    for (i = 0 ; i < pools->count ; i++)
314
 
        virNWFilterPoolObjFree(pools->objs[i]);
315
 
    VIR_FREE(pools->objs);
316
 
    pools->count = 0;
317
 
}
318
 
 
319
 
 
320
 
static int
321
 
virNWFilterRuleDefAddVar(virNWFilterRuleDefPtr nwf,
322
 
                         nwItemDesc *item,
323
 
                         const char *var)
324
 
{
325
 
    int i = 0;
326
 
 
327
 
    if (nwf->vars) {
328
 
        for (i = 0; i < nwf->nvars; i++)
329
 
            if (STREQ(nwf->vars[i], var)) {
330
 
                item->var = nwf->vars[i];
331
 
                return 0;
332
 
            }
333
 
    }
334
 
 
335
 
    if (VIR_REALLOC_N(nwf->vars, nwf->nvars+1) < 0) {
336
 
        virReportOOMError();
337
 
        return 1;
338
 
    }
339
 
 
340
 
    nwf->vars[nwf->nvars] = strdup(var);
341
 
 
342
 
    if (!nwf->vars[nwf->nvars]) {
343
 
        virReportOOMError();
344
 
        return 1;
345
 
    }
346
 
 
347
 
    item->var = nwf->vars[nwf->nvars++];
348
 
 
349
 
    return 0;
350
 
}
351
 
 
352
 
 
353
 
void
354
 
virNWFilterPoolObjRemove(virNWFilterPoolObjListPtr pools,
355
 
                         virNWFilterPoolObjPtr pool)
356
 
{
357
 
    unsigned int i;
358
 
 
359
 
    virNWFilterPoolObjUnlock(pool);
360
 
 
361
 
    for (i = 0 ; i < pools->count ; i++) {
362
 
        virNWFilterPoolObjLock(pools->objs[i]);
363
 
        if (pools->objs[i] == pool) {
364
 
            virNWFilterPoolObjUnlock(pools->objs[i]);
365
 
            virNWFilterPoolObjFree(pools->objs[i]);
366
 
 
367
 
            if (i < (pools->count - 1))
368
 
                memmove(pools->objs + i, pools->objs + i + 1,
369
 
                        sizeof(*(pools->objs)) * (pools->count - (i + 1)));
370
 
 
371
 
            if (VIR_REALLOC_N(pools->objs, pools->count - 1) < 0) {
372
 
                ; /* Failure to reduce memory allocation isn't fatal */
373
 
            }
374
 
            pools->count--;
375
 
 
376
 
            break;
377
 
        }
378
 
        virNWFilterPoolObjUnlock(pools->objs[i]);
379
 
    }
380
 
}
381
 
 
382
 
 
383
 
 
384
 
typedef bool (*valueValidator)(enum attrDatatype datatype, void *valptr,
385
 
                               virNWFilterRuleDefPtr nwf);
386
 
typedef bool (*valueFormatter)(virBufferPtr buf,
387
 
                               virNWFilterRuleDefPtr nwf);
388
 
 
389
 
typedef struct _virXMLAttr2Struct virXMLAttr2Struct;
390
 
struct _virXMLAttr2Struct
391
 
{
392
 
    const char *name;           // attribute name
393
 
    enum attrDatatype datatype;
394
 
    int dataIdx;                // offset of the hasXYZ boolean
395
 
    valueValidator validator;   // beyond-standard checkers
396
 
    valueFormatter formatter;   // beyond-standard formatter
397
 
};
398
 
 
399
 
 
400
 
static const struct int_map macProtoMap[] = {
401
 
    INTMAP_ENTRY(ETHERTYPE_ARP   , "arp"),
402
 
    INTMAP_ENTRY(ETHERTYPE_REVARP, "rarp"),
403
 
    INTMAP_ENTRY(ETHERTYPE_IP    , "ipv4"),
404
 
    INTMAP_ENTRY(ETHERTYPE_IPV6  , "ipv6"),
405
 
    INTMAP_ENTRY_LAST
406
 
};
407
 
 
408
 
 
409
 
static bool
410
 
checkMacProtocolID(enum attrDatatype datatype, void *value,
411
 
                   virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED)
412
 
{
413
 
    int32_t res = -1;
414
 
 
415
 
    if (datatype == DATATYPE_STRING) {
416
 
        if (intMapGetByString(macProtoMap, (char *)value, 1, &res) == 0)
417
 
            res = -1;
418
 
        datatype = DATATYPE_UINT16;
419
 
    } else if (datatype == DATATYPE_UINT16 ||
420
 
               datatype == DATATYPE_UINT16_HEX) {
421
 
        res = (uint32_t)*(uint16_t *)value;
422
 
        if (res < 0x600)
423
 
            res = -1;
424
 
    }
425
 
 
426
 
    if (res != -1) {
427
 
        nwf->p.ethHdrFilter.dataProtocolID.u.u16 = res;
428
 
        nwf->p.ethHdrFilter.dataProtocolID.datatype = datatype;
429
 
        return 1;
430
 
    }
431
 
 
432
 
    return 0;
433
 
}
434
 
 
435
 
 
436
 
static bool
437
 
macProtocolIDFormatter(virBufferPtr buf,
438
 
                       virNWFilterRuleDefPtr nwf)
439
 
{
440
 
    const char *str = NULL;
441
 
    bool asHex = true;
442
 
 
443
 
    if (intMapGetByInt(macProtoMap,
444
 
                       nwf->p.ethHdrFilter.dataProtocolID.u.u16,
445
 
                       &str)) {
446
 
        virBufferVSprintf(buf, "%s", str);
447
 
    } else {
448
 
        if (nwf->p.ethHdrFilter.dataProtocolID.datatype == DATATYPE_UINT16)
449
 
            asHex = false;
450
 
        virBufferVSprintf(buf, asHex ? "0x%x" : "%d",
451
 
                          nwf->p.ethHdrFilter.dataProtocolID.u.u16);
452
 
    }
453
 
    return 1;
454
 
}
455
 
 
456
 
 
457
 
/* generic function to check for a valid (ipv4,ipv6, mac) mask
458
 
 * A mask is valid of there is a sequence of 1's followed by a sequence
459
 
 * of 0s or only 1s or only 0s
460
 
 */
461
 
static bool
462
 
checkValidMask(unsigned char *data, int len)
463
 
{
464
 
    uint32_t idx = 0;
465
 
    uint8_t mask = 0x80;
466
 
    int checkones = 1;
467
 
 
468
 
    while ((idx >> 3) < len) {
469
 
        if (checkones) {
470
 
            if (!(data[idx>>3] & mask))
471
 
                checkones = 0;
472
 
        } else {
473
 
            if ((data[idx>>3] & mask))
474
 
                return 0;
475
 
        }
476
 
 
477
 
        idx++;
478
 
        mask >>= 1;
479
 
        if (!mask)
480
 
            mask = 0x80;
481
 
    }
482
 
    return 1;
483
 
}
484
 
 
485
 
 
486
 
static bool
487
 
checkMACMask(enum attrDatatype datatype ATTRIBUTE_UNUSED,
488
 
             void *macMask,
489
 
             virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED)
490
 
{
491
 
    return checkValidMask((unsigned char *)macMask, 6);
492
 
}
493
 
 
494
 
 
495
 
/*
496
 
 * supported arp opcode -- see 'ebtables -h arp' for the naming
497
 
 */
498
 
static const struct int_map arpOpcodeMap[] = {
499
 
    INTMAP_ENTRY(1, "Request"),
500
 
    INTMAP_ENTRY(2, "Reply"),
501
 
    INTMAP_ENTRY(3, "Request_Reverse"),
502
 
    INTMAP_ENTRY(4, "Reply_Reverse"),
503
 
    INTMAP_ENTRY(5, "DRARP_Request"),
504
 
    INTMAP_ENTRY(6, "DRARP_Reply"),
505
 
    INTMAP_ENTRY(7, "DRARP_Error"),
506
 
    INTMAP_ENTRY(8, "InARP_Request"),
507
 
    INTMAP_ENTRY(9, "ARP_NAK"),
508
 
    INTMAP_ENTRY_LAST
509
 
};
510
 
 
511
 
 
512
 
static bool
513
 
arpOpcodeValidator(enum attrDatatype datatype,
514
 
                   void *value,
515
 
                   virNWFilterRuleDefPtr nwf)
516
 
{
517
 
    int32_t res = -1;
518
 
 
519
 
    if (datatype == DATATYPE_STRING) {
520
 
        if (intMapGetByString(arpOpcodeMap, (char *)value, 1, &res) == 0)
521
 
            res = -1;
522
 
        datatype = DATATYPE_UINT16;
523
 
    } else if (datatype == DATATYPE_UINT16 ||
524
 
               datatype == DATATYPE_UINT16_HEX) {
525
 
        res = (uint32_t)*(uint16_t *)value;
526
 
    }
527
 
 
528
 
    if (res != -1) {
529
 
        nwf->p.arpHdrFilter.dataOpcode.u.u16 = res;
530
 
        nwf->p.arpHdrFilter.dataOpcode.datatype = datatype;
531
 
        return 1;
532
 
    }
533
 
    return 0;
534
 
}
535
 
 
536
 
 
537
 
static bool
538
 
arpOpcodeFormatter(virBufferPtr buf,
539
 
                   virNWFilterRuleDefPtr nwf)
540
 
{
541
 
    const char *str = NULL;
542
 
 
543
 
    if (intMapGetByInt(arpOpcodeMap,
544
 
                       nwf->p.arpHdrFilter.dataOpcode.u.u16,
545
 
                       &str)) {
546
 
        virBufferVSprintf(buf, "%s", str);
547
 
    } else {
548
 
        virBufferVSprintf(buf, "%d", nwf->p.arpHdrFilter.dataOpcode.u.u16);
549
 
    }
550
 
    return 1;
551
 
}
552
 
 
553
 
 
554
 
static const struct int_map ipProtoMap[] = {
555
 
    INTMAP_ENTRY(IPPROTO_TCP, "tcp"),
556
 
    INTMAP_ENTRY(IPPROTO_UDP, "udp"),
557
 
#ifdef IPPROTO_UDPLITE
558
 
    INTMAP_ENTRY(IPPROTO_UDPLITE, "udplite"),
559
 
#endif
560
 
    INTMAP_ENTRY(IPPROTO_ESP, "esp"),
561
 
    INTMAP_ENTRY(IPPROTO_AH,  "ah"),
562
 
    INTMAP_ENTRY(IPPROTO_ICMP, "icmp"),
563
 
    INTMAP_ENTRY(IPPROTO_IGMP, "igmp"),
564
 
#ifdef IPPROTO_SCTP
565
 
    INTMAP_ENTRY(IPPROTO_SCTP, "sctp"),
566
 
#endif
567
 
    INTMAP_ENTRY(IPPROTO_ICMPV6, "icmpv6"),
568
 
    INTMAP_ENTRY_LAST
569
 
};
570
 
 
571
 
 
572
 
static bool checkIPProtocolID(enum attrDatatype datatype,
573
 
                              void *value,
574
 
                              virNWFilterRuleDefPtr nwf)
575
 
{
576
 
    int32_t res = -1;
577
 
 
578
 
    if (datatype == DATATYPE_STRING) {
579
 
        if (intMapGetByString(ipProtoMap, (char *)value, 1, &res) == 0)
580
 
            res = -1;
581
 
        datatype = DATATYPE_UINT8_HEX;
582
 
    } else if (datatype == DATATYPE_UINT8 ||
583
 
               datatype == DATATYPE_UINT8_HEX) {
584
 
        res = (uint32_t)*(uint16_t *)value;
585
 
    }
586
 
 
587
 
    if (res != -1) {
588
 
        nwf->p.ipHdrFilter.ipHdr.dataProtocolID.u.u8 = res;
589
 
        nwf->p.ipHdrFilter.ipHdr.dataProtocolID.datatype = datatype;
590
 
        return 1;
591
 
    }
592
 
    return 0;
593
 
}
594
 
 
595
 
 
596
 
static bool
597
 
formatIPProtocolID(virBufferPtr buf,
598
 
                   virNWFilterRuleDefPtr nwf)
599
 
{
600
 
    const char *str = NULL;
601
 
    bool asHex = true;
602
 
 
603
 
    if (intMapGetByInt(ipProtoMap,
604
 
                       nwf->p.ipHdrFilter.ipHdr.dataProtocolID.u.u8,
605
 
                       &str)) {
606
 
        virBufferVSprintf(buf, "%s", str);
607
 
    } else {
608
 
        if (nwf->p.ipHdrFilter.ipHdr.dataProtocolID.datatype == DATATYPE_UINT8)
609
 
            asHex = false;
610
 
        virBufferVSprintf(buf, asHex ? "0x%x" : "%d",
611
 
                          nwf->p.ipHdrFilter.ipHdr.dataProtocolID.u.u8);
612
 
    }
613
 
    return 1;
614
 
}
615
 
 
616
 
 
617
 
static bool
618
 
dscpValidator(enum attrDatatype datatype, void *val,
619
 
              virNWFilterRuleDefPtr nwf)
620
 
{
621
 
    uint8_t dscp = *(uint16_t *)val;
622
 
    if (dscp > 63)
623
 
        return 0;
624
 
 
625
 
    nwf->p.ipHdrFilter.ipHdr.dataDSCP.datatype = datatype;
626
 
 
627
 
    return 1;
628
 
}
629
 
 
630
 
#define COMMON_MAC_PROPS(STRUCT) \
631
 
    {\
632
 
        .name = SRCMACADDR,\
633
 
        .datatype = DATATYPE_MACADDR,\
634
 
        .dataIdx = offsetof(virNWFilterRuleDef,p.STRUCT.ethHdr.dataSrcMACAddr),\
635
 
    },\
636
 
    {\
637
 
        .name = SRCMACMASK,\
638
 
        .datatype = DATATYPE_MACMASK,\
639
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ethHdr.dataSrcMACMask),\
640
 
    },\
641
 
    {\
642
 
        .name = DSTMACADDR,\
643
 
        .datatype = DATATYPE_MACADDR,\
644
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ethHdr.dataDstMACAddr),\
645
 
    },\
646
 
    {\
647
 
        .name = DSTMACMASK,\
648
 
        .datatype = DATATYPE_MACMASK,\
649
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ethHdr.dataDstMACMask),\
650
 
    }
651
 
 
652
 
 
653
 
static const virXMLAttr2Struct macAttributes[] = {
654
 
    COMMON_MAC_PROPS(ethHdrFilter),
655
 
    {
656
 
        .name = "protocolid",
657
 
        .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX | DATATYPE_STRING,
658
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ethHdrFilter.dataProtocolID),
659
 
        .validator= checkMacProtocolID,
660
 
        .formatter= macProtocolIDFormatter,
661
 
    },
662
 
    {
663
 
        .name = NULL,
664
 
    }
665
 
};
666
 
 
667
 
static const virXMLAttr2Struct arpAttributes[] = {
668
 
    COMMON_MAC_PROPS(arpHdrFilter),
669
 
    {
670
 
        .name = "hwtype",
671
 
        .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
672
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataHWType),
673
 
    }, {
674
 
        .name = "protocoltype",
675
 
        .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
676
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataProtocolType),
677
 
    }, {
678
 
        .name = "opcode",
679
 
        .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX | DATATYPE_STRING,
680
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataOpcode),
681
 
        .validator= arpOpcodeValidator,
682
 
        .formatter= arpOpcodeFormatter,
683
 
    }, {
684
 
        .name = ARPSRCMACADDR,
685
 
        .datatype = DATATYPE_MACADDR,
686
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataARPSrcMACAddr),
687
 
    }, {
688
 
        .name = ARPDSTMACADDR,
689
 
        .datatype = DATATYPE_MACADDR,
690
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataARPDstMACAddr),
691
 
    }, {
692
 
        .name = ARPSRCIPADDR,
693
 
        .datatype = DATATYPE_IPADDR,
694
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataARPSrcIPAddr),
695
 
    }, {
696
 
        .name = ARPDSTIPADDR,
697
 
        .datatype = DATATYPE_IPADDR,
698
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataARPDstIPAddr),
699
 
    },
700
 
    {
701
 
        .name = NULL,
702
 
    }
703
 
};
704
 
 
705
 
static const virXMLAttr2Struct ipAttributes[] = {
706
 
    COMMON_MAC_PROPS(ipHdrFilter),
707
 
    {
708
 
        .name = SRCIPADDR,
709
 
        .datatype = DATATYPE_IPADDR,
710
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.ipHdr.dataSrcIPAddr),
711
 
    },
712
 
    {
713
 
        .name = SRCIPMASK,
714
 
        .datatype = DATATYPE_IPMASK,
715
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.ipHdr.dataSrcIPMask),
716
 
    },
717
 
    {
718
 
        .name = DSTIPADDR,
719
 
        .datatype = DATATYPE_IPADDR,
720
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.ipHdr.dataDstIPAddr),
721
 
    },
722
 
    {
723
 
        .name = DSTIPMASK,
724
 
        .datatype = DATATYPE_IPMASK,
725
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.ipHdr.dataDstIPMask),
726
 
    },
727
 
    {
728
 
        .name = "protocol",
729
 
        .datatype = DATATYPE_STRING | DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
730
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.ipHdr.dataProtocolID),
731
 
        .validator= checkIPProtocolID,
732
 
        .formatter= formatIPProtocolID,
733
 
    },
734
 
    {
735
 
        .name = SRCPORTSTART,
736
 
        .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
737
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.portData.dataSrcPortStart),
738
 
    },
739
 
    {
740
 
        .name = SRCPORTEND,
741
 
        .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
742
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.portData.dataSrcPortEnd),
743
 
    },
744
 
    {
745
 
        .name = DSTPORTSTART,
746
 
        .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
747
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.portData.dataDstPortStart),
748
 
    },
749
 
    {
750
 
        .name = DSTPORTEND,
751
 
        .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
752
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.portData.dataDstPortEnd),
753
 
    },
754
 
    {
755
 
        .name = DSCP,
756
 
        .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
757
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.ipHdr.dataDSCP),
758
 
        .validator = dscpValidator,
759
 
    },
760
 
    {
761
 
        .name = NULL,
762
 
    }
763
 
};
764
 
 
765
 
 
766
 
static const virXMLAttr2Struct ipv6Attributes[] = {
767
 
    COMMON_MAC_PROPS(ipv6HdrFilter),
768
 
    {
769
 
        .name = SRCIPADDR,
770
 
        .datatype = DATATYPE_IPV6ADDR,
771
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.ipHdr.dataSrcIPAddr),
772
 
    },
773
 
    {
774
 
        .name = SRCIPMASK,
775
 
        .datatype = DATATYPE_IPV6MASK,
776
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.ipHdr.dataSrcIPMask),
777
 
    },
778
 
    {
779
 
        .name = DSTIPADDR,
780
 
        .datatype = DATATYPE_IPV6ADDR,
781
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.ipHdr.dataDstIPAddr),
782
 
    },
783
 
    {
784
 
        .name = DSTIPMASK,
785
 
        .datatype = DATATYPE_IPV6MASK,
786
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.ipHdr.dataDstIPMask),
787
 
    },
788
 
    {
789
 
        .name = "protocol",
790
 
        .datatype = DATATYPE_STRING | DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
791
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.ipHdr.dataProtocolID),
792
 
        .validator= checkIPProtocolID,
793
 
        .formatter= formatIPProtocolID,
794
 
    },
795
 
    {
796
 
        .name = SRCPORTSTART,
797
 
        .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
798
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.portData.dataSrcPortStart),
799
 
    },
800
 
    {
801
 
        .name = SRCPORTEND,
802
 
        .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
803
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.portData.dataSrcPortEnd),
804
 
    },
805
 
    {
806
 
        .name = DSTPORTSTART,
807
 
        .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
808
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.portData.dataDstPortStart),
809
 
    },
810
 
    {
811
 
        .name = DSTPORTEND,
812
 
        .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
813
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.portData.dataDstPortEnd),
814
 
    },
815
 
    {
816
 
        .name = NULL,
817
 
    }
818
 
};
819
 
 
820
 
 
821
 
#define COMMON_L3_MAC_PROPS(STRUCT) \
822
 
    {\
823
 
        .name = SRCMACADDR,\
824
 
        .datatype = DATATYPE_MACADDR,\
825
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.dataSrcMACAddr),\
826
 
    }
827
 
 
828
 
#define COMMON_IP_PROPS(STRUCT, ADDRTYPE, MASKTYPE) \
829
 
    COMMON_L3_MAC_PROPS(STRUCT),\
830
 
    {\
831
 
        .name = SRCIPADDR,\
832
 
        .datatype = ADDRTYPE,\
833
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPAddr),\
834
 
    },\
835
 
    {\
836
 
        .name = SRCIPMASK,\
837
 
        .datatype = MASKTYPE,\
838
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPMask),\
839
 
    },\
840
 
    {\
841
 
        .name = DSTIPADDR,\
842
 
        .datatype = ADDRTYPE,\
843
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPAddr),\
844
 
    },\
845
 
    {\
846
 
        .name = DSTIPMASK,\
847
 
        .datatype = MASKTYPE,\
848
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPMask),\
849
 
    },\
850
 
    {\
851
 
        .name = SRCIPFROM,\
852
 
        .datatype = ADDRTYPE,\
853
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPFrom),\
854
 
    },\
855
 
    {\
856
 
        .name = SRCIPTO,\
857
 
        .datatype = ADDRTYPE,\
858
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPTo),\
859
 
    },\
860
 
    {\
861
 
        .name = DSTIPFROM,\
862
 
        .datatype = ADDRTYPE,\
863
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPFrom),\
864
 
    },\
865
 
    {\
866
 
        .name = DSTIPTO,\
867
 
        .datatype = DATATYPE_IPADDR,\
868
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPTo),\
869
 
    },\
870
 
    {\
871
 
        .name = DSCP,\
872
 
        .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,\
873
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDSCP),\
874
 
        .validator = dscpValidator,\
875
 
    },\
876
 
    {\
877
 
        .name = "connlimit-above",\
878
 
        .datatype = DATATYPE_UINT16,\
879
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataConnlimitAbove),\
880
 
    }
881
 
 
882
 
#define COMMON_PORT_PROPS(STRUCT) \
883
 
    {\
884
 
        .name = SRCPORTSTART,\
885
 
        .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,\
886
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.portData.dataSrcPortStart),\
887
 
    },\
888
 
    {\
889
 
        .name = SRCPORTEND,\
890
 
        .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,\
891
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.portData.dataSrcPortEnd),\
892
 
    },\
893
 
    {\
894
 
        .name = DSTPORTSTART,\
895
 
        .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,\
896
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.portData.dataDstPortStart),\
897
 
    },\
898
 
    {\
899
 
        .name = DSTPORTEND,\
900
 
        .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,\
901
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.portData.dataDstPortEnd),\
902
 
    }
903
 
 
904
 
static const virXMLAttr2Struct tcpAttributes[] = {
905
 
    COMMON_IP_PROPS(tcpHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
906
 
    COMMON_PORT_PROPS(tcpHdrFilter),
907
 
    {
908
 
        .name = "option",
909
 
        .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
910
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.dataTCPOption),
911
 
    },
912
 
    {
913
 
        .name = NULL,
914
 
    }
915
 
};
916
 
 
917
 
static const virXMLAttr2Struct udpAttributes[] = {
918
 
    COMMON_IP_PROPS(udpHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
919
 
    COMMON_PORT_PROPS(udpHdrFilter),
920
 
    {
921
 
        .name = NULL,
922
 
    }
923
 
};
924
 
 
925
 
static const virXMLAttr2Struct udpliteAttributes[] = {
926
 
    COMMON_IP_PROPS(udpliteHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
927
 
    {
928
 
        .name = NULL,
929
 
    }
930
 
};
931
 
 
932
 
static const virXMLAttr2Struct espAttributes[] = {
933
 
    COMMON_IP_PROPS(espHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
934
 
    {
935
 
        .name = NULL,
936
 
    }
937
 
};
938
 
 
939
 
static const virXMLAttr2Struct ahAttributes[] = {
940
 
    COMMON_IP_PROPS(ahHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
941
 
    {
942
 
        .name = NULL,
943
 
    }
944
 
};
945
 
 
946
 
static const virXMLAttr2Struct sctpAttributes[] = {
947
 
    COMMON_IP_PROPS(sctpHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
948
 
    COMMON_PORT_PROPS(sctpHdrFilter),
949
 
    {
950
 
        .name = NULL,
951
 
    }
952
 
};
953
 
 
954
 
 
955
 
static const virXMLAttr2Struct icmpAttributes[] = {
956
 
    COMMON_IP_PROPS(icmpHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
957
 
    {
958
 
        .name = "type",
959
 
        .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
960
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.dataICMPType),
961
 
    },
962
 
    {
963
 
        .name = "code",
964
 
        .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
965
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.dataICMPCode),
966
 
    },
967
 
    {
968
 
        .name = NULL,
969
 
    }
970
 
};
971
 
 
972
 
 
973
 
static const virXMLAttr2Struct allAttributes[] = {
974
 
    COMMON_IP_PROPS(allHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
975
 
    {
976
 
        .name = NULL,
977
 
    }
978
 
};
979
 
 
980
 
 
981
 
static const virXMLAttr2Struct igmpAttributes[] = {
982
 
    COMMON_IP_PROPS(igmpHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
983
 
    {
984
 
        .name = NULL,
985
 
    }
986
 
};
987
 
 
988
 
 
989
 
static const virXMLAttr2Struct tcpipv6Attributes[] = {
990
 
    COMMON_IP_PROPS(tcpHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK),
991
 
    COMMON_PORT_PROPS(tcpHdrFilter),
992
 
    {
993
 
        .name = "option",
994
 
        .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
995
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.dataTCPOption),
996
 
    },
997
 
    {
998
 
        .name = NULL,
999
 
    }
1000
 
};
1001
 
 
1002
 
static const virXMLAttr2Struct udpipv6Attributes[] = {
1003
 
    COMMON_IP_PROPS(udpHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK),
1004
 
    COMMON_PORT_PROPS(udpHdrFilter),
1005
 
    {
1006
 
        .name = NULL,
1007
 
    }
1008
 
};
1009
 
 
1010
 
 
1011
 
static const virXMLAttr2Struct udpliteipv6Attributes[] = {
1012
 
    COMMON_IP_PROPS(udpliteHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK),
1013
 
    {
1014
 
        .name = NULL,
1015
 
    }
1016
 
};
1017
 
 
1018
 
 
1019
 
static const virXMLAttr2Struct espipv6Attributes[] = {
1020
 
    COMMON_IP_PROPS(espHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK),
1021
 
    {
1022
 
        .name = NULL,
1023
 
    }
1024
 
};
1025
 
 
1026
 
 
1027
 
static const virXMLAttr2Struct ahipv6Attributes[] = {
1028
 
    COMMON_IP_PROPS(ahHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK),
1029
 
    {
1030
 
        .name = NULL,
1031
 
    }
1032
 
};
1033
 
 
1034
 
 
1035
 
static const virXMLAttr2Struct sctpipv6Attributes[] = {
1036
 
    COMMON_IP_PROPS(sctpHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK),
1037
 
    COMMON_PORT_PROPS(sctpHdrFilter),
1038
 
    {
1039
 
        .name = NULL,
1040
 
    }
1041
 
};
1042
 
 
1043
 
 
1044
 
static const virXMLAttr2Struct icmpv6Attributes[] = {
1045
 
    COMMON_IP_PROPS(icmpHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK),
1046
 
    {
1047
 
        .name = "type",
1048
 
        .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
1049
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.dataICMPType),
1050
 
    },
1051
 
    {
1052
 
        .name = "code",
1053
 
        .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
1054
 
        .dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.dataICMPCode),
1055
 
    },
1056
 
    {
1057
 
        .name = NULL,
1058
 
    }
1059
 
};
1060
 
 
1061
 
 
1062
 
static const virXMLAttr2Struct allipv6Attributes[] = {
1063
 
    COMMON_IP_PROPS(allHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK),
1064
 
    {
1065
 
        .name = NULL,
1066
 
    }
1067
 
};
1068
 
 
1069
 
 
1070
 
typedef struct _virAttributes virAttributes;
1071
 
struct _virAttributes {
1072
 
    const char *id;
1073
 
    const virXMLAttr2Struct *att;
1074
 
    enum virNWFilterRuleProtocolType prtclType;
1075
 
};
1076
 
 
1077
 
#define PROTOCOL_ENTRY(ID, ATT, PRTCLTYPE) \
1078
 
    { .id = ID, .att = ATT, .prtclType = PRTCLTYPE }
1079
 
#define PROTOCOL_ENTRY_LAST { .id = NULL }
1080
 
 
1081
 
 
1082
 
static const virAttributes virAttr[] = {
1083
 
    PROTOCOL_ENTRY("arp"    , arpAttributes    , VIR_NWFILTER_RULE_PROTOCOL_ARP),
1084
 
    PROTOCOL_ENTRY("rarp"   , arpAttributes    , VIR_NWFILTER_RULE_PROTOCOL_RARP),
1085
 
    PROTOCOL_ENTRY("mac"    , macAttributes    , VIR_NWFILTER_RULE_PROTOCOL_MAC),
1086
 
    PROTOCOL_ENTRY("ip"     , ipAttributes     , VIR_NWFILTER_RULE_PROTOCOL_IP),
1087
 
    PROTOCOL_ENTRY("ipv6"   , ipv6Attributes   , VIR_NWFILTER_RULE_PROTOCOL_IPV6),
1088
 
    PROTOCOL_ENTRY("tcp"    , tcpAttributes    , VIR_NWFILTER_RULE_PROTOCOL_TCP),
1089
 
    PROTOCOL_ENTRY("udp"    , udpAttributes    , VIR_NWFILTER_RULE_PROTOCOL_UDP),
1090
 
    PROTOCOL_ENTRY("udplite", udpliteAttributes, VIR_NWFILTER_RULE_PROTOCOL_UDPLITE),
1091
 
    PROTOCOL_ENTRY("esp"    , espAttributes    , VIR_NWFILTER_RULE_PROTOCOL_ESP),
1092
 
    PROTOCOL_ENTRY("ah"     , ahAttributes     , VIR_NWFILTER_RULE_PROTOCOL_AH),
1093
 
    PROTOCOL_ENTRY("sctp"   , sctpAttributes   , VIR_NWFILTER_RULE_PROTOCOL_SCTP),
1094
 
    PROTOCOL_ENTRY("icmp"   , icmpAttributes   , VIR_NWFILTER_RULE_PROTOCOL_ICMP),
1095
 
    PROTOCOL_ENTRY("all"    , allAttributes    , VIR_NWFILTER_RULE_PROTOCOL_ALL),
1096
 
    PROTOCOL_ENTRY("igmp"   , igmpAttributes   , VIR_NWFILTER_RULE_PROTOCOL_IGMP),
1097
 
    PROTOCOL_ENTRY("tcp-ipv6"    , tcpipv6Attributes    , VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6),
1098
 
    PROTOCOL_ENTRY("udp-ipv6"    , udpipv6Attributes    , VIR_NWFILTER_RULE_PROTOCOL_UDPoIPV6),
1099
 
    PROTOCOL_ENTRY("udplite-ipv6", udpliteipv6Attributes, VIR_NWFILTER_RULE_PROTOCOL_UDPLITEoIPV6),
1100
 
    PROTOCOL_ENTRY("esp-ipv6"    , espipv6Attributes    , VIR_NWFILTER_RULE_PROTOCOL_ESPoIPV6),
1101
 
    PROTOCOL_ENTRY("ah-ipv6"     , ahipv6Attributes     , VIR_NWFILTER_RULE_PROTOCOL_AHoIPV6),
1102
 
    PROTOCOL_ENTRY("sctp-ipv6"   , sctpipv6Attributes   , VIR_NWFILTER_RULE_PROTOCOL_SCTPoIPV6),
1103
 
    PROTOCOL_ENTRY("icmpv6"      , icmpv6Attributes     , VIR_NWFILTER_RULE_PROTOCOL_ICMPV6),
1104
 
    PROTOCOL_ENTRY("all-ipv6"    , allipv6Attributes    , VIR_NWFILTER_RULE_PROTOCOL_ALLoIPV6),
1105
 
    PROTOCOL_ENTRY_LAST
1106
 
};
1107
 
 
1108
 
 
1109
 
static bool
1110
 
virNWMACAddressParser(const char *input,
1111
 
                      nwMACAddressPtr output)
1112
 
{
1113
 
    if (virParseMacAddr(input, &output->addr[0]) == 0)
1114
 
        return 1;
1115
 
    return 0;
1116
 
}
1117
 
 
1118
 
 
1119
 
static bool
1120
 
virNWIPv4AddressParser(const char *input,
1121
 
                       nwIPAddressPtr output)
1122
 
{
1123
 
    if (virSocketParseIpv4Addr(input, &output->addr) == -1)
1124
 
        return 0;
1125
 
    return 1;
1126
 
}
1127
 
 
1128
 
 
1129
 
static bool
1130
 
virNWIPv6AddressParser(const char *input,
1131
 
                       nwIPAddressPtr output)
1132
 
{
1133
 
    if (virSocketParseIpv6Addr(input, &output->addr) == -1)
1134
 
        return 0;
1135
 
    return 1;
1136
 
}
1137
 
 
1138
 
 
1139
 
static int
1140
 
virNWFilterRuleDetailsParse(xmlNodePtr node,
1141
 
                            virNWFilterRuleDefPtr nwf,
1142
 
                            const virXMLAttr2Struct *att)
1143
 
{
1144
 
    int rc = 0, g_rc = 0;
1145
 
    int idx = 0;
1146
 
    char *prop;
1147
 
    int found = 0;
1148
 
    enum attrDatatype datatype, att_datatypes;
1149
 
    enum virNWFilterEntryItemFlags *flags ,match_flag = 0, flags_set = 0;
1150
 
    nwItemDesc *item;
1151
 
    int int_val;
1152
 
    unsigned int uint_val;
1153
 
    void *data_ptr = NULL, *storage_ptr;
1154
 
    valueValidator validator;
1155
 
    char *match = virXMLPropString(node, "match");
1156
 
    nwIPAddress ipaddr;
1157
 
    int base;
1158
 
 
1159
 
    if (match && STREQ(match, "no"))
1160
 
        match_flag = NWFILTER_ENTRY_ITEM_FLAG_IS_NEG;
1161
 
    VIR_FREE(match);
1162
 
    match = NULL;
1163
 
 
1164
 
    while (att[idx].name != NULL) {
1165
 
        prop = virXMLPropString(node, att[idx].name);
1166
 
 
1167
 
        item = (nwItemDesc *)((char *)nwf + att[idx].dataIdx);
1168
 
        flags = &item->flags;
1169
 
        flags_set = match_flag;
1170
 
 
1171
 
        if (prop) {
1172
 
            found = 0;
1173
 
 
1174
 
            validator = NULL;
1175
 
 
1176
 
            if (STRPREFIX(prop, "$")) {
1177
 
                flags_set |= NWFILTER_ENTRY_ITEM_FLAG_HAS_VAR;
1178
 
                storage_ptr = NULL;
1179
 
 
1180
 
                if (virNWFilterRuleDefAddVar(nwf,
1181
 
                                             item,
1182
 
                                             &prop[1]))
1183
 
                    rc = -1;
1184
 
                found = 1;
1185
 
            }
1186
 
 
1187
 
            datatype = 1;
1188
 
 
1189
 
            att_datatypes = att[idx].datatype;
1190
 
 
1191
 
            while (datatype <= DATATYPE_LAST && found == 0 && rc == 0) {
1192
 
                if ((att_datatypes & datatype)) {
1193
 
 
1194
 
                    att_datatypes ^= datatype;
1195
 
 
1196
 
                    validator = att[idx].validator;
1197
 
 
1198
 
                    base = 10;
1199
 
 
1200
 
                    switch (datatype) {
1201
 
                        case DATATYPE_UINT8_HEX:
1202
 
                            base = 16;
1203
 
                        case DATATYPE_UINT8:
1204
 
                            storage_ptr = &item->u.u8;
1205
 
                            if (virStrToLong_ui(prop, NULL, base, &uint_val) >= 0) {
1206
 
                                if (uint_val <= 0xff) {
1207
 
                                    *(uint8_t *)storage_ptr = uint_val;
1208
 
                                    found = 1;
1209
 
                                    data_ptr = &uint_val;
1210
 
                                } else
1211
 
                                    rc = -1;
1212
 
                            } else
1213
 
                                rc = -1;
1214
 
                        break;
1215
 
 
1216
 
                        case DATATYPE_UINT16_HEX:
1217
 
                            base = 16;
1218
 
                        case DATATYPE_UINT16:
1219
 
                            storage_ptr = &item->u.u16;
1220
 
                            if (virStrToLong_ui(prop, NULL, base, &uint_val) >= 0) {
1221
 
                                if (uint_val <= 0xffff) {
1222
 
                                    *(uint16_t *)storage_ptr = uint_val;
1223
 
                                    found = 1;
1224
 
                                    data_ptr = &uint_val;
1225
 
                                } else
1226
 
                                    rc = -1;
1227
 
                            } else
1228
 
                                rc = -1;
1229
 
                        break;
1230
 
 
1231
 
                        case DATATYPE_IPADDR:
1232
 
                            storage_ptr = &item->u.ipaddr;
1233
 
                            if (!virNWIPv4AddressParser(prop,
1234
 
                                       (nwIPAddressPtr)storage_ptr)) {
1235
 
                                rc = -1;
1236
 
                            }
1237
 
                            found = 1;
1238
 
                        break;
1239
 
 
1240
 
                        case DATATYPE_IPMASK:
1241
 
                            storage_ptr = &item->u.u8;
1242
 
                            if (virStrToLong_ui(prop, NULL, 10, &uint_val) == 0) {
1243
 
                                if (uint_val <= 32) {
1244
 
                                    if (!validator)
1245
 
                                        *(uint8_t *)storage_ptr =
1246
 
                                               (uint8_t)uint_val;
1247
 
                                    found = 1;
1248
 
                                    data_ptr = &uint_val;
1249
 
                                } else
1250
 
                                    rc = -1;
1251
 
                            } else {
1252
 
                                if (virNWIPv4AddressParser(prop, &ipaddr)) {
1253
 
                                    int_val = virSocketGetNumNetmaskBits(
1254
 
                                                     &ipaddr.addr);
1255
 
                                    if (int_val >= 0)
1256
 
                                        *(uint8_t *)storage_ptr = int_val;
1257
 
                                    else
1258
 
                                        rc = -1;
1259
 
                                    found = 1;
1260
 
                                } else
1261
 
                                    rc = -1;
1262
 
                            }
1263
 
                        break;
1264
 
 
1265
 
                        case DATATYPE_MACADDR:
1266
 
                            storage_ptr = &item->u.macaddr;
1267
 
                            if (!virNWMACAddressParser(prop,
1268
 
                                        (nwMACAddressPtr)storage_ptr)) {
1269
 
                                rc = -1;
1270
 
                            }
1271
 
                            found = 1;
1272
 
                        break;
1273
 
 
1274
 
                        case DATATYPE_MACMASK:
1275
 
                            validator = checkMACMask;
1276
 
                            storage_ptr = &item->u.macaddr;
1277
 
                            if (!virNWMACAddressParser(prop,
1278
 
                                        (nwMACAddressPtr)storage_ptr)) {
1279
 
                                rc = -1;
1280
 
                            }
1281
 
                            data_ptr = storage_ptr;
1282
 
                            found = 1;
1283
 
                        break;
1284
 
 
1285
 
                        case DATATYPE_IPV6ADDR:
1286
 
                            storage_ptr = &item->u.ipaddr;
1287
 
                            if (!virNWIPv6AddressParser(prop,
1288
 
                                       (nwIPAddressPtr)storage_ptr)) {
1289
 
                                rc = -1;
1290
 
                            }
1291
 
                            found = 1;
1292
 
                        break;
1293
 
 
1294
 
                        case DATATYPE_IPV6MASK:
1295
 
                            storage_ptr = &item->u.u8;
1296
 
                            if (virStrToLong_ui(prop, NULL, 10, &uint_val) == 0) {
1297
 
                                if (uint_val <= 128) {
1298
 
                                    if (!validator)
1299
 
                                        *(uint8_t *)storage_ptr =
1300
 
                                               (uint8_t)uint_val;
1301
 
                                    found = 1;
1302
 
                                    data_ptr = &uint_val;
1303
 
                                } else
1304
 
                                    rc = -1;
1305
 
                            } else {
1306
 
                                if (virNWIPv6AddressParser(prop, &ipaddr)) {
1307
 
                                    int_val = virSocketGetNumNetmaskBits(
1308
 
                                                  &ipaddr.addr);
1309
 
                                    if (int_val >= 0)
1310
 
                                        *(uint8_t *)storage_ptr = int_val;
1311
 
                                    else
1312
 
                                        rc = -1;
1313
 
                                    found = 1;
1314
 
                                } else
1315
 
                                   rc = -1;
1316
 
                            }
1317
 
                        break;
1318
 
 
1319
 
                        case DATATYPE_STRING:
1320
 
                            if (!validator) {
1321
 
                                // not supported
1322
 
                                rc = -1;
1323
 
                                break;
1324
 
                            }
1325
 
                            data_ptr = prop;
1326
 
                            found = 1;
1327
 
                        break;
1328
 
 
1329
 
                        case DATATYPE_LAST:
1330
 
                        default:
1331
 
                        break;
1332
 
                    }
1333
 
                }
1334
 
 
1335
 
                if (rc != 0 && att_datatypes != 0) {
1336
 
                    rc = 0;
1337
 
                    found = 0;
1338
 
                }
1339
 
 
1340
 
                datatype <<= 1;
1341
 
            } /* while */
1342
 
 
1343
 
            if (found == 1 && rc == 0) {
1344
 
                *flags = NWFILTER_ENTRY_ITEM_FLAG_EXISTS | flags_set;
1345
 
                item->datatype = datatype >> 1;
1346
 
                if (validator) {
1347
 
                    if (!validator(datatype >> 1, data_ptr, nwf)) {
1348
 
                        rc = -1;
1349
 
                        *flags = 0;
1350
 
                    }
1351
 
                }
1352
 
            }
1353
 
 
1354
 
            if (!found || rc) {
1355
 
                virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1356
 
                                       _("%s has illegal value %s"),
1357
 
                                       att[idx].name, prop);
1358
 
                rc = -1;
1359
 
            }
1360
 
            VIR_FREE(prop);
1361
 
        }
1362
 
 
1363
 
        if (rc) {
1364
 
            g_rc = rc;
1365
 
            rc = 0;
1366
 
        }
1367
 
 
1368
 
        idx++;
1369
 
    }
1370
 
 
1371
 
    return g_rc;
1372
 
}
1373
 
 
1374
 
 
1375
 
 
1376
 
 
1377
 
static virNWFilterIncludeDefPtr
1378
 
virNWFilterIncludeParse(xmlNodePtr cur)
1379
 
{
1380
 
    virNWFilterIncludeDefPtr ret;
1381
 
 
1382
 
    if (VIR_ALLOC(ret) < 0) {
1383
 
        virReportOOMError();
1384
 
        return NULL;
1385
 
    }
1386
 
 
1387
 
    ret->filterref = virXMLPropString(cur, "filter");
1388
 
    if (!ret->filterref) {
1389
 
        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1390
 
                               "%s",
1391
 
                               _("rule node requires action attribute"));
1392
 
        goto err_exit;
1393
 
    }
1394
 
 
1395
 
    ret->params = virNWFilterParseParamAttributes(cur);
1396
 
    if (!ret->params)
1397
 
        goto err_exit;
1398
 
 
1399
 
cleanup:
1400
 
    return ret;
1401
 
 
1402
 
err_exit:
1403
 
    virNWFilterIncludeDefFree(ret);
1404
 
    ret = NULL;
1405
 
    goto cleanup;
1406
 
}
1407
 
 
1408
 
 
1409
 
static void
1410
 
virNWFilterRuleDefFixup(virNWFilterRuleDefPtr rule)
1411
 
{
1412
 
#define COPY_NEG_SIGN(A, B) \
1413
 
    (A).flags = ((A).flags & ~NWFILTER_ENTRY_ITEM_FLAG_IS_NEG) | \
1414
 
                ((B).flags &  NWFILTER_ENTRY_ITEM_FLAG_IS_NEG);
1415
 
 
1416
 
    switch (rule->prtclType) {
1417
 
    case VIR_NWFILTER_RULE_PROTOCOL_MAC:
1418
 
        COPY_NEG_SIGN(rule->p.ethHdrFilter.ethHdr.dataSrcMACMask,
1419
 
                      rule->p.ethHdrFilter.ethHdr.dataSrcMACAddr);
1420
 
        COPY_NEG_SIGN(rule->p.ethHdrFilter.ethHdr.dataDstMACMask,
1421
 
                      rule->p.ethHdrFilter.ethHdr.dataDstMACAddr);
1422
 
    break;
1423
 
 
1424
 
    case VIR_NWFILTER_RULE_PROTOCOL_IP:
1425
 
        COPY_NEG_SIGN(rule->p.ipHdrFilter.ipHdr.dataSrcIPMask,
1426
 
                      rule->p.ipHdrFilter.ipHdr.dataSrcIPAddr);
1427
 
        COPY_NEG_SIGN(rule->p.ipHdrFilter.ipHdr.dataDstIPMask,
1428
 
                      rule->p.ipHdrFilter.ipHdr.dataDstIPAddr);
1429
 
    break;
1430
 
 
1431
 
    case VIR_NWFILTER_RULE_PROTOCOL_IPV6:
1432
 
        COPY_NEG_SIGN(rule->p.ipv6HdrFilter.ipHdr.dataSrcIPMask,
1433
 
                      rule->p.ipv6HdrFilter.ipHdr.dataSrcIPAddr);
1434
 
        COPY_NEG_SIGN(rule->p.ipv6HdrFilter.ipHdr.dataDstIPMask,
1435
 
                      rule->p.ipv6HdrFilter.ipHdr.dataDstIPAddr);
1436
 
    break;
1437
 
 
1438
 
    case VIR_NWFILTER_RULE_PROTOCOL_ARP:
1439
 
    case VIR_NWFILTER_RULE_PROTOCOL_RARP:
1440
 
    case VIR_NWFILTER_RULE_PROTOCOL_NONE:
1441
 
    break;
1442
 
 
1443
 
    case VIR_NWFILTER_RULE_PROTOCOL_TCP:
1444
 
    case VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6:
1445
 
        COPY_NEG_SIGN(rule->p.tcpHdrFilter.ipHdr.dataSrcIPMask,
1446
 
                      rule->p.tcpHdrFilter.ipHdr.dataSrcIPAddr);
1447
 
        COPY_NEG_SIGN(rule->p.tcpHdrFilter.ipHdr.dataDstIPMask,
1448
 
                      rule->p.tcpHdrFilter.ipHdr.dataDstIPAddr);
1449
 
        COPY_NEG_SIGN(rule->p.tcpHdrFilter.ipHdr.dataSrcIPTo,
1450
 
                      rule->p.tcpHdrFilter.ipHdr.dataSrcIPFrom);
1451
 
        COPY_NEG_SIGN(rule->p.tcpHdrFilter.ipHdr.dataDstIPTo,
1452
 
                      rule->p.tcpHdrFilter.ipHdr.dataDstIPFrom);
1453
 
        COPY_NEG_SIGN(rule->p.tcpHdrFilter.portData.dataSrcPortEnd,
1454
 
                      rule->p.tcpHdrFilter.portData.dataSrcPortStart);
1455
 
        COPY_NEG_SIGN(rule->p.tcpHdrFilter.portData.dataDstPortStart,
1456
 
                      rule->p.tcpHdrFilter.portData.dataSrcPortStart);
1457
 
        COPY_NEG_SIGN(rule->p.tcpHdrFilter.portData.dataDstPortEnd,
1458
 
                      rule->p.tcpHdrFilter.portData.dataSrcPortStart);
1459
 
    break;
1460
 
 
1461
 
    case VIR_NWFILTER_RULE_PROTOCOL_UDP:
1462
 
    case VIR_NWFILTER_RULE_PROTOCOL_UDPoIPV6:
1463
 
        COPY_NEG_SIGN(rule->p.udpHdrFilter.ipHdr.dataSrcIPMask,
1464
 
                      rule->p.udpHdrFilter.ipHdr.dataSrcIPAddr);
1465
 
        COPY_NEG_SIGN(rule->p.udpHdrFilter.ipHdr.dataDstIPMask,
1466
 
                      rule->p.udpHdrFilter.ipHdr.dataDstIPAddr);
1467
 
        COPY_NEG_SIGN(rule->p.udpHdrFilter.ipHdr.dataSrcIPTo,
1468
 
                      rule->p.udpHdrFilter.ipHdr.dataSrcIPFrom);
1469
 
        COPY_NEG_SIGN(rule->p.udpHdrFilter.ipHdr.dataDstIPTo,
1470
 
                      rule->p.udpHdrFilter.ipHdr.dataDstIPFrom);
1471
 
        COPY_NEG_SIGN(rule->p.udpHdrFilter.portData.dataSrcPortEnd,
1472
 
                      rule->p.udpHdrFilter.portData.dataSrcPortStart);
1473
 
        COPY_NEG_SIGN(rule->p.udpHdrFilter.portData.dataDstPortStart,
1474
 
                      rule->p.udpHdrFilter.portData.dataSrcPortStart);
1475
 
        COPY_NEG_SIGN(rule->p.udpHdrFilter.portData.dataDstPortEnd,
1476
 
                      rule->p.udpHdrFilter.portData.dataSrcPortStart);
1477
 
    break;
1478
 
 
1479
 
    case VIR_NWFILTER_RULE_PROTOCOL_UDPLITE:
1480
 
    case VIR_NWFILTER_RULE_PROTOCOL_UDPLITEoIPV6:
1481
 
        COPY_NEG_SIGN(rule->p.udpliteHdrFilter.ipHdr.dataSrcIPMask,
1482
 
                      rule->p.udpliteHdrFilter.ipHdr.dataSrcIPAddr);
1483
 
        COPY_NEG_SIGN(rule->p.udpliteHdrFilter.ipHdr.dataDstIPMask,
1484
 
                      rule->p.udpliteHdrFilter.ipHdr.dataDstIPAddr);
1485
 
        COPY_NEG_SIGN(rule->p.udpliteHdrFilter.ipHdr.dataSrcIPTo,
1486
 
                      rule->p.udpliteHdrFilter.ipHdr.dataSrcIPFrom);
1487
 
        COPY_NEG_SIGN(rule->p.udpliteHdrFilter.ipHdr.dataDstIPTo,
1488
 
                      rule->p.udpliteHdrFilter.ipHdr.dataDstIPFrom);
1489
 
    break;
1490
 
 
1491
 
    case VIR_NWFILTER_RULE_PROTOCOL_ESP:
1492
 
    case VIR_NWFILTER_RULE_PROTOCOL_ESPoIPV6:
1493
 
        COPY_NEG_SIGN(rule->p.espHdrFilter.ipHdr.dataSrcIPMask,
1494
 
                      rule->p.espHdrFilter.ipHdr.dataSrcIPAddr);
1495
 
        COPY_NEG_SIGN(rule->p.espHdrFilter.ipHdr.dataDstIPMask,
1496
 
                      rule->p.espHdrFilter.ipHdr.dataDstIPAddr);
1497
 
        COPY_NEG_SIGN(rule->p.espHdrFilter.ipHdr.dataSrcIPTo,
1498
 
                      rule->p.espHdrFilter.ipHdr.dataSrcIPFrom);
1499
 
        COPY_NEG_SIGN(rule->p.espHdrFilter.ipHdr.dataDstIPTo,
1500
 
                      rule->p.espHdrFilter.ipHdr.dataDstIPFrom);
1501
 
    break;
1502
 
 
1503
 
    case VIR_NWFILTER_RULE_PROTOCOL_AH:
1504
 
    case VIR_NWFILTER_RULE_PROTOCOL_AHoIPV6:
1505
 
        COPY_NEG_SIGN(rule->p.ahHdrFilter.ipHdr.dataSrcIPMask,
1506
 
                      rule->p.ahHdrFilter.ipHdr.dataSrcIPAddr);
1507
 
        COPY_NEG_SIGN(rule->p.ahHdrFilter.ipHdr.dataDstIPMask,
1508
 
                      rule->p.ahHdrFilter.ipHdr.dataDstIPAddr);
1509
 
        COPY_NEG_SIGN(rule->p.ahHdrFilter.ipHdr.dataSrcIPTo,
1510
 
                      rule->p.ahHdrFilter.ipHdr.dataSrcIPFrom);
1511
 
        COPY_NEG_SIGN(rule->p.ahHdrFilter.ipHdr.dataDstIPTo,
1512
 
                      rule->p.ahHdrFilter.ipHdr.dataDstIPFrom);
1513
 
    break;
1514
 
 
1515
 
    case VIR_NWFILTER_RULE_PROTOCOL_SCTP:
1516
 
    case VIR_NWFILTER_RULE_PROTOCOL_SCTPoIPV6:
1517
 
        COPY_NEG_SIGN(rule->p.sctpHdrFilter.ipHdr.dataSrcIPMask,
1518
 
                      rule->p.sctpHdrFilter.ipHdr.dataSrcIPAddr);
1519
 
        COPY_NEG_SIGN(rule->p.sctpHdrFilter.ipHdr.dataDstIPMask,
1520
 
                      rule->p.sctpHdrFilter.ipHdr.dataDstIPAddr);
1521
 
        COPY_NEG_SIGN(rule->p.sctpHdrFilter.ipHdr.dataSrcIPTo,
1522
 
                      rule->p.sctpHdrFilter.ipHdr.dataSrcIPFrom);
1523
 
        COPY_NEG_SIGN(rule->p.sctpHdrFilter.ipHdr.dataDstIPTo,
1524
 
                      rule->p.sctpHdrFilter.ipHdr.dataDstIPFrom);
1525
 
        COPY_NEG_SIGN(rule->p.sctpHdrFilter.portData.dataSrcPortEnd,
1526
 
                      rule->p.sctpHdrFilter.portData.dataSrcPortStart);
1527
 
        COPY_NEG_SIGN(rule->p.sctpHdrFilter.portData.dataDstPortStart,
1528
 
                      rule->p.sctpHdrFilter.portData.dataSrcPortStart);
1529
 
        COPY_NEG_SIGN(rule->p.sctpHdrFilter.portData.dataDstPortEnd,
1530
 
                      rule->p.sctpHdrFilter.portData.dataSrcPortStart);
1531
 
    break;
1532
 
 
1533
 
    case VIR_NWFILTER_RULE_PROTOCOL_ICMP:
1534
 
    case VIR_NWFILTER_RULE_PROTOCOL_ICMPV6:
1535
 
        COPY_NEG_SIGN(rule->p.icmpHdrFilter.ipHdr.dataSrcIPMask,
1536
 
                      rule->p.icmpHdrFilter.ipHdr.dataSrcIPAddr);
1537
 
        COPY_NEG_SIGN(rule->p.icmpHdrFilter.ipHdr.dataDstIPMask,
1538
 
                      rule->p.icmpHdrFilter.ipHdr.dataDstIPAddr);
1539
 
        COPY_NEG_SIGN(rule->p.icmpHdrFilter.ipHdr.dataSrcIPTo,
1540
 
                      rule->p.icmpHdrFilter.ipHdr.dataSrcIPFrom);
1541
 
        COPY_NEG_SIGN(rule->p.icmpHdrFilter.ipHdr.dataDstIPTo,
1542
 
                      rule->p.icmpHdrFilter.ipHdr.dataDstIPFrom);
1543
 
        COPY_NEG_SIGN(rule->p.icmpHdrFilter.dataICMPCode,
1544
 
                      rule->p.icmpHdrFilter.dataICMPType);
1545
 
    break;
1546
 
 
1547
 
    case VIR_NWFILTER_RULE_PROTOCOL_ALL:
1548
 
    case VIR_NWFILTER_RULE_PROTOCOL_ALLoIPV6:
1549
 
        COPY_NEG_SIGN(rule->p.allHdrFilter.ipHdr.dataSrcIPMask,
1550
 
                      rule->p.allHdrFilter.ipHdr.dataSrcIPAddr);
1551
 
        COPY_NEG_SIGN(rule->p.allHdrFilter.ipHdr.dataDstIPMask,
1552
 
                      rule->p.allHdrFilter.ipHdr.dataDstIPAddr);
1553
 
        COPY_NEG_SIGN(rule->p.allHdrFilter.ipHdr.dataSrcIPTo,
1554
 
                      rule->p.allHdrFilter.ipHdr.dataSrcIPFrom);
1555
 
        COPY_NEG_SIGN(rule->p.allHdrFilter.ipHdr.dataDstIPTo,
1556
 
                      rule->p.allHdrFilter.ipHdr.dataDstIPFrom);
1557
 
    break;
1558
 
 
1559
 
    case VIR_NWFILTER_RULE_PROTOCOL_IGMP:
1560
 
        COPY_NEG_SIGN(rule->p.igmpHdrFilter.ipHdr.dataSrcIPMask,
1561
 
                      rule->p.igmpHdrFilter.ipHdr.dataSrcIPAddr);
1562
 
        COPY_NEG_SIGN(rule->p.igmpHdrFilter.ipHdr.dataDstIPMask,
1563
 
                      rule->p.igmpHdrFilter.ipHdr.dataDstIPAddr);
1564
 
        COPY_NEG_SIGN(rule->p.igmpHdrFilter.ipHdr.dataSrcIPTo,
1565
 
                      rule->p.igmpHdrFilter.ipHdr.dataSrcIPFrom);
1566
 
        COPY_NEG_SIGN(rule->p.igmpHdrFilter.ipHdr.dataDstIPTo,
1567
 
                      rule->p.igmpHdrFilter.ipHdr.dataDstIPFrom);
1568
 
    break;
1569
 
 
1570
 
    case VIR_NWFILTER_RULE_PROTOCOL_LAST:
1571
 
    break;
1572
 
    }
1573
 
#undef COPY_NEG_SIGN
1574
 
}
1575
 
 
1576
 
 
1577
 
static virNWFilterRuleDefPtr
1578
 
virNWFilterRuleParse(xmlNodePtr node)
1579
 
{
1580
 
    char *action;
1581
 
    char *direction;
1582
 
    char *prio;
1583
 
    char *statematch;
1584
 
    int found;
1585
 
    int found_i = 0;
1586
 
    unsigned int priority;
1587
 
 
1588
 
    xmlNodePtr cur;
1589
 
    virNWFilterRuleDefPtr ret;
1590
 
 
1591
 
    if (VIR_ALLOC(ret) < 0) {
1592
 
        virReportOOMError();
1593
 
        return NULL;
1594
 
    }
1595
 
 
1596
 
    action    = virXMLPropString(node, "action");
1597
 
    direction = virXMLPropString(node, "direction");
1598
 
    prio      = virXMLPropString(node, "priority");
1599
 
    statematch= virXMLPropString(node, "statematch");
1600
 
 
1601
 
    if (!action) {
1602
 
        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1603
 
                               "%s",
1604
 
                               _("rule node requires action attribute"));
1605
 
        goto err_exit;
1606
 
    }
1607
 
 
1608
 
    if ((ret->action = virNWFilterRuleActionTypeFromString(action)) < 0) {
1609
 
        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1610
 
                               "%s",
1611
 
                               _("unknown rule action attribute value"));
1612
 
        goto err_exit;
1613
 
    }
1614
 
 
1615
 
    if (!direction) {
1616
 
        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1617
 
                               "%s",
1618
 
                               _("rule node requires direction attribute"));
1619
 
        goto err_exit;
1620
 
    }
1621
 
 
1622
 
    if ((ret->tt = virNWFilterRuleDirectionTypeFromString(direction)) < 0) {
1623
 
        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1624
 
                               "%s",
1625
 
                               _("unknown rule direction attribute value"));
1626
 
        goto err_exit;
1627
 
    }
1628
 
 
1629
 
    ret->priority = MAX_RULE_PRIORITY / 2;
1630
 
 
1631
 
    if (prio) {
1632
 
        if (virStrToLong_ui(prio, NULL, 10, &priority) >= 0) {
1633
 
            if (priority <= MAX_RULE_PRIORITY)
1634
 
                ret->priority = priority;
1635
 
        }
1636
 
    }
1637
 
 
1638
 
    if (statematch &&
1639
 
        (STREQ(statematch, "0") || STRCASEEQ(statematch, "false")))
1640
 
        ret->flags |= RULE_FLAG_NO_STATEMATCH;
1641
 
 
1642
 
    cur = node->children;
1643
 
 
1644
 
    found = 0;
1645
 
 
1646
 
    while (cur != NULL) {
1647
 
        if (cur->type == XML_ELEMENT_NODE) {
1648
 
            int i = 0;
1649
 
            while (1) {
1650
 
                if (found)
1651
 
                    i = found_i;
1652
 
 
1653
 
                if (xmlStrEqual(cur->name, BAD_CAST virAttr[i].id)) {
1654
 
 
1655
 
                    found_i = i;
1656
 
                    found = 1;
1657
 
                    ret->prtclType = virAttr[i].prtclType;
1658
 
 
1659
 
                    if (virNWFilterRuleDetailsParse(cur,
1660
 
                                                    ret,
1661
 
                                                    virAttr[i].att) < 0) {
1662
 
                        /* we ignore malformed rules
1663
 
                           goto err_exit;
1664
 
                        */
1665
 
                    }
1666
 
                    break;
1667
 
                }
1668
 
                if (!found) {
1669
 
                    i++;
1670
 
                    if (!virAttr[i].id)
1671
 
                        break;
1672
 
                } else
1673
 
                   break;
1674
 
            }
1675
 
        }
1676
 
 
1677
 
        cur = cur->next;
1678
 
    }
1679
 
 
1680
 
    virNWFilterRuleDefFixup(ret);
1681
 
 
1682
 
cleanup:
1683
 
    VIR_FREE(prio);
1684
 
    VIR_FREE(action);
1685
 
    VIR_FREE(direction);
1686
 
    VIR_FREE(statematch);
1687
 
 
1688
 
    return ret;
1689
 
 
1690
 
err_exit:
1691
 
    virNWFilterRuleDefFree(ret);
1692
 
    ret = NULL;
1693
 
    goto cleanup;
1694
 
}
1695
 
 
1696
 
 
1697
 
static virNWFilterDefPtr
1698
 
virNWFilterDefParseXML(xmlXPathContextPtr ctxt) {
1699
 
    virNWFilterDefPtr ret;
1700
 
    xmlNodePtr curr = ctxt->node;
1701
 
    char *uuid = NULL;
1702
 
    char *chain = NULL;
1703
 
    virNWFilterEntryPtr entry;
1704
 
 
1705
 
    if (VIR_ALLOC(ret) < 0) {
1706
 
        virReportOOMError();
1707
 
        return NULL;
1708
 
    }
1709
 
 
1710
 
    ret->name = virXPathString("string(./@name)", ctxt);
1711
 
    if (!ret->name) {
1712
 
        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1713
 
                               "%s", _("filter has no name"));
1714
 
        goto cleanup;
1715
 
    }
1716
 
 
1717
 
    ret->chainsuffix = VIR_NWFILTER_CHAINSUFFIX_ROOT;
1718
 
    chain = virXPathString("string(./@chain)", ctxt);
1719
 
    if (chain) {
1720
 
        if ((ret->chainsuffix =
1721
 
             virNWFilterChainSuffixTypeFromString(chain)) < 0) {
1722
 
            virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1723
 
                                   _("unknown chain suffix '%s'"), chain);
1724
 
            goto cleanup;
1725
 
        }
1726
 
    }
1727
 
 
1728
 
    uuid = virXPathString("string(./uuid)", ctxt);
1729
 
    if (uuid == NULL) {
1730
 
        if (virUUIDGenerate(ret->uuid) < 0) {
1731
 
            virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1732
 
                                  "%s", _("unable to generate uuid"));
1733
 
            goto cleanup;
1734
 
        }
1735
 
    } else {
1736
 
        if (virUUIDParse(uuid, ret->uuid) < 0) {
1737
 
            virNWFilterReportError(VIR_ERR_XML_ERROR,
1738
 
                                  "%s", _("malformed uuid element"));
1739
 
            goto cleanup;
1740
 
        }
1741
 
        VIR_FREE(uuid);
1742
 
    }
1743
 
 
1744
 
    curr = curr->children;
1745
 
 
1746
 
    while (curr != NULL) {
1747
 
        if (curr->type == XML_ELEMENT_NODE) {
1748
 
            if (VIR_ALLOC(entry) < 0) {
1749
 
                virReportOOMError();
1750
 
                goto cleanup;
1751
 
            }
1752
 
 
1753
 
            /* ignore malformed rule and include elements */
1754
 
            if (xmlStrEqual(curr->name, BAD_CAST "rule"))
1755
 
                entry->rule = virNWFilterRuleParse(curr);
1756
 
            else if (xmlStrEqual(curr->name, BAD_CAST "filterref"))
1757
 
                entry->include = virNWFilterIncludeParse(curr);
1758
 
 
1759
 
            if (entry->rule || entry->include) {
1760
 
                if (VIR_REALLOC_N(ret->filterEntries, ret->nentries+1) < 0) {
1761
 
                    VIR_FREE(entry);
1762
 
                    virReportOOMError();
1763
 
                    goto cleanup;
1764
 
                }
1765
 
                ret->filterEntries[ret->nentries++] = entry;
1766
 
            } else
1767
 
                VIR_FREE(entry);
1768
 
        }
1769
 
        curr = curr->next;
1770
 
    }
1771
 
 
1772
 
    VIR_FREE(chain);
1773
 
 
1774
 
    return ret;
1775
 
 
1776
 
 cleanup:
1777
 
    virNWFilterDefFree(ret);
1778
 
    VIR_FREE(chain);
1779
 
    VIR_FREE(uuid);
1780
 
    return NULL;
1781
 
}
1782
 
 
1783
 
 
1784
 
/* Called from SAX on parsing errors in the XML. */
1785
 
static void
1786
 
catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
1787
 
{
1788
 
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1789
 
 
1790
 
    if (ctxt) {
1791
 
        virConnectPtr conn = ctxt->_private;
1792
 
 
1793
 
        if (conn &&
1794
 
            conn->err.code == VIR_ERR_NONE &&
1795
 
            ctxt->lastError.level == XML_ERR_FATAL &&
1796
 
            ctxt->lastError.message != NULL) {
1797
 
            virNWFilterReportError(VIR_ERR_XML_DETAIL,
1798
 
                                   _("at line %d: %s"),
1799
 
                                   ctxt->lastError.line,
1800
 
                                   ctxt->lastError.message);
1801
 
        }
1802
 
    }
1803
 
}
1804
 
 
1805
 
 
1806
 
virNWFilterDefPtr
1807
 
virNWFilterDefParseNode(xmlDocPtr xml,
1808
 
                        xmlNodePtr root) {
1809
 
    xmlXPathContextPtr ctxt = NULL;
1810
 
    virNWFilterDefPtr def = NULL;
1811
 
 
1812
 
    if (STRNEQ((const char *)root->name, "filter")) {
1813
 
        virNWFilterReportError(VIR_ERR_XML_ERROR,
1814
 
                               "%s",
1815
 
                               _("unknown root element for nw filter pool"));
1816
 
        goto cleanup;
1817
 
    }
1818
 
 
1819
 
    ctxt = xmlXPathNewContext(xml);
1820
 
    if (ctxt == NULL) {
1821
 
        virReportOOMError();
1822
 
        goto cleanup;
1823
 
    }
1824
 
 
1825
 
    ctxt->node = root;
1826
 
    def = virNWFilterDefParseXML(ctxt);
1827
 
 
1828
 
cleanup:
1829
 
    xmlXPathFreeContext(ctxt);
1830
 
    return def;
1831
 
}
1832
 
 
1833
 
 
1834
 
static virNWFilterDefPtr
1835
 
virNWFilterDefParse(virConnectPtr conn,
1836
 
                    const char *xmlStr,
1837
 
                    const char *filename) {
1838
 
    virNWFilterDefPtr ret = NULL;
1839
 
    xmlParserCtxtPtr pctxt;
1840
 
    xmlDocPtr xml = NULL;
1841
 
    xmlNodePtr node = NULL;
1842
 
 
1843
 
    /* Set up a parser context so we can catch the details of XML errors. */
1844
 
    pctxt = xmlNewParserCtxt ();
1845
 
    if (!pctxt || !pctxt->sax)
1846
 
        goto cleanup;
1847
 
    pctxt->sax->error = catchXMLError;
1848
 
    pctxt->_private = conn;
1849
 
 
1850
 
    if (conn) virResetError (&conn->err);
1851
 
    if (filename) {
1852
 
        xml = xmlCtxtReadFile (pctxt, filename, NULL,
1853
 
                               XML_PARSE_NOENT | XML_PARSE_NONET |
1854
 
                               XML_PARSE_NOWARNING);
1855
 
    } else {
1856
 
        xml = xmlCtxtReadDoc (pctxt, BAD_CAST xmlStr,
1857
 
                              "nwfilter.xml", NULL,
1858
 
                              XML_PARSE_NOENT | XML_PARSE_NONET |
1859
 
                              XML_PARSE_NOWARNING);
1860
 
    }
1861
 
 
1862
 
    if (!xml) {
1863
 
        if (conn && conn->err.code == VIR_ERR_NONE)
1864
 
              virNWFilterReportError(VIR_ERR_XML_ERROR,
1865
 
                                     "%s",_("failed to parse xml document"));
1866
 
        goto cleanup;
1867
 
    }
1868
 
 
1869
 
    node = xmlDocGetRootElement(xml);
1870
 
    if (node == NULL) {
1871
 
        virNWFilterReportError(VIR_ERR_XML_ERROR,
1872
 
                               "%s", _("missing root element"));
1873
 
        goto cleanup;
1874
 
    }
1875
 
 
1876
 
    ret = virNWFilterDefParseNode(xml, node);
1877
 
 
1878
 
    xmlFreeParserCtxt (pctxt);
1879
 
    xmlFreeDoc(xml);
1880
 
 
1881
 
    return ret;
1882
 
 
1883
 
 cleanup:
1884
 
    xmlFreeParserCtxt (pctxt);
1885
 
    xmlFreeDoc(xml);
1886
 
    return NULL;
1887
 
}
1888
 
 
1889
 
 
1890
 
virNWFilterDefPtr
1891
 
virNWFilterDefParseString(virConnectPtr conn,
1892
 
                          const char *xmlStr)
1893
 
{
1894
 
    return virNWFilterDefParse(conn, xmlStr, NULL);
1895
 
}
1896
 
 
1897
 
 
1898
 
virNWFilterDefPtr
1899
 
virNWFilterDefParseFile(virConnectPtr conn,
1900
 
                        const char *filename)
1901
 
{
1902
 
    return virNWFilterDefParse(conn, NULL, filename);
1903
 
}
1904
 
 
1905
 
 
1906
 
virNWFilterPoolObjPtr
1907
 
virNWFilterPoolObjFindByUUID(virNWFilterPoolObjListPtr pools,
1908
 
                             const unsigned char *uuid)
1909
 
{
1910
 
    unsigned int i;
1911
 
 
1912
 
    for (i = 0 ; i < pools->count ; i++) {
1913
 
        virNWFilterPoolObjLock(pools->objs[i]);
1914
 
        if (!memcmp(pools->objs[i]->def->uuid, uuid, VIR_UUID_BUFLEN))
1915
 
            return pools->objs[i];
1916
 
        virNWFilterPoolObjUnlock(pools->objs[i]);
1917
 
    }
1918
 
 
1919
 
    return NULL;
1920
 
}
1921
 
 
1922
 
 
1923
 
virNWFilterPoolObjPtr
1924
 
virNWFilterPoolObjFindByName(virNWFilterPoolObjListPtr pools,
1925
 
                             const char *name)
1926
 
{
1927
 
    unsigned int i;
1928
 
 
1929
 
    for (i = 0 ; i < pools->count ; i++) {
1930
 
        virNWFilterPoolObjLock(pools->objs[i]);
1931
 
        if (STREQ(pools->objs[i]->def->name, name))
1932
 
            return pools->objs[i];
1933
 
        virNWFilterPoolObjUnlock(pools->objs[i]);
1934
 
    }
1935
 
 
1936
 
    return NULL;
1937
 
}
1938
 
 
1939
 
 
1940
 
int virNWFilterSaveXML(const char *configDir,
1941
 
                       virNWFilterDefPtr def,
1942
 
                       const char *xml)
1943
 
{
1944
 
    char *configFile = NULL;
1945
 
    int fd = -1, ret = -1;
1946
 
    size_t towrite;
1947
 
    int err;
1948
 
 
1949
 
    if ((configFile = virNWFilterConfigFile(configDir, def->name)) == NULL)
1950
 
        goto cleanup;
1951
 
 
1952
 
    if ((err = virFileMakePath(configDir))) {
1953
 
        virReportSystemError(err,
1954
 
                             _("cannot create config directory '%s'"),
1955
 
                             configDir);
1956
 
        goto cleanup;
1957
 
    }
1958
 
 
1959
 
    if ((fd = open(configFile,
1960
 
                   O_WRONLY | O_CREAT | O_TRUNC,
1961
 
                   S_IRUSR | S_IWUSR )) < 0) {
1962
 
        virReportSystemError(errno,
1963
 
                             _("cannot create config file '%s'"),
1964
 
                             configFile);
1965
 
        goto cleanup;
1966
 
    }
1967
 
 
1968
 
    towrite = strlen(xml);
1969
 
    if (safewrite(fd, xml, towrite) < 0) {
1970
 
        virReportSystemError(errno,
1971
 
                             _("cannot write config file '%s'"),
1972
 
                             configFile);
1973
 
        goto cleanup;
1974
 
    }
1975
 
 
1976
 
    if (close(fd) < 0) {
1977
 
        virReportSystemError(errno,
1978
 
                             _("cannot save config file '%s'"),
1979
 
                             configFile);
1980
 
        goto cleanup;
1981
 
    }
1982
 
 
1983
 
    ret = 0;
1984
 
 
1985
 
 cleanup:
1986
 
    if (fd != -1)
1987
 
        close(fd);
1988
 
 
1989
 
    VIR_FREE(configFile);
1990
 
 
1991
 
    return ret;
1992
 
}
1993
 
 
1994
 
 
1995
 
int virNWFilterSaveConfig(const char *configDir,
1996
 
                          virNWFilterDefPtr def)
1997
 
{
1998
 
    int ret = -1;
1999
 
    char *xml;
2000
 
 
2001
 
    if (!(xml = virNWFilterDefFormat(def)))
2002
 
        goto cleanup;
2003
 
 
2004
 
    if (virNWFilterSaveXML(configDir, def, xml))
2005
 
        goto cleanup;
2006
 
 
2007
 
    ret = 0;
2008
 
cleanup:
2009
 
    VIR_FREE(xml);
2010
 
    return ret;
2011
 
}
2012
 
 
2013
 
 
2014
 
static int
2015
 
_virNWFilterDefLoopDetect(virConnectPtr conn,
2016
 
                          virNWFilterPoolObjListPtr pools,
2017
 
                          virNWFilterDefPtr def,
2018
 
                          const char *filtername)
2019
 
{
2020
 
    int rc = 0;
2021
 
    int i;
2022
 
    virNWFilterEntryPtr entry;
2023
 
    virNWFilterPoolObjPtr obj;
2024
 
 
2025
 
    if (!def)
2026
 
        return 0;
2027
 
 
2028
 
    for (i = 0; i < def->nentries; i++) {
2029
 
        entry = def->filterEntries[i];
2030
 
        if (entry->include) {
2031
 
 
2032
 
            if (STREQ(filtername, entry->include->filterref)) {
2033
 
                rc = 1;
2034
 
                break;
2035
 
            }
2036
 
 
2037
 
            obj = virNWFilterPoolObjFindByName(pools,
2038
 
                                               entry->include->filterref);
2039
 
            if (obj) {
2040
 
                rc = _virNWFilterDefLoopDetect(conn,
2041
 
                                               pools,
2042
 
                                               obj->def, filtername);
2043
 
 
2044
 
                virNWFilterPoolObjUnlock(obj);
2045
 
                if (rc)
2046
 
                   break;
2047
 
            }
2048
 
        }
2049
 
    }
2050
 
 
2051
 
    return rc;
2052
 
}
2053
 
 
2054
 
 
2055
 
/*
2056
 
 * virNWFilterDefLoopDetect:
2057
 
 * @conn: pointer to virConnect object
2058
 
 * @pools : the pools to search
2059
 
 * @def : the filter definiton that may add a loop and is to be tested
2060
 
 *
2061
 
 * Detect a loop introduced through the filters being able to
2062
 
 * reference each other.
2063
 
 *
2064
 
 * Returns 0 in case no loop was detected, 1 otherwise.
2065
 
 */
2066
 
static int
2067
 
virNWFilterDefLoopDetect(virConnectPtr conn,
2068
 
                         virNWFilterPoolObjListPtr pools,
2069
 
                         virNWFilterDefPtr def)
2070
 
{
2071
 
    return _virNWFilterDefLoopDetect(conn, pools, def, def->name);
2072
 
}
2073
 
 
2074
 
int nCallbackDriver;
2075
 
#define MAX_CALLBACK_DRIVER 10
2076
 
static virNWFilterCallbackDriverPtr callbackDrvArray[MAX_CALLBACK_DRIVER];
2077
 
 
2078
 
void
2079
 
virNWFilterRegisterCallbackDriver(virNWFilterCallbackDriverPtr cbd)
2080
 
{
2081
 
    if (nCallbackDriver < MAX_CALLBACK_DRIVER) {
2082
 
        callbackDrvArray[nCallbackDriver++] = cbd;
2083
 
    }
2084
 
}
2085
 
 
2086
 
 
2087
 
static virHashIterator virNWFilterDomainFWUpdateCB;
2088
 
 
2089
 
 
2090
 
static int
2091
 
virNWFilterTriggerVMFilterRebuild(virConnectPtr conn)
2092
 
{
2093
 
    int i;
2094
 
    int err;
2095
 
    struct domUpdateCBStruct cb = {
2096
 
        .conn = conn,
2097
 
        .err = 0,
2098
 
        .step = STEP_APPLY_NEW,
2099
 
        .skipInterfaces = virHashCreate(0),
2100
 
    };
2101
 
 
2102
 
    if (!cb.skipInterfaces) {
2103
 
        virReportOOMError();
2104
 
        return 1;
2105
 
    }
2106
 
 
2107
 
    for (i = 0; i < nCallbackDriver; i++) {
2108
 
        callbackDrvArray[i]->vmFilterRebuild(conn,
2109
 
                                             virNWFilterDomainFWUpdateCB,
2110
 
                                             &cb);
2111
 
    }
2112
 
 
2113
 
    err = cb.err;
2114
 
 
2115
 
    if (err) {
2116
 
        cb.step = STEP_TEAR_NEW; // rollback
2117
 
        cb.err = 0;
2118
 
 
2119
 
        for (i = 0; i < nCallbackDriver; i++)
2120
 
            callbackDrvArray[i]->vmFilterRebuild(conn,
2121
 
                                                 virNWFilterDomainFWUpdateCB,
2122
 
                                                 &cb);
2123
 
    } else {
2124
 
        cb.step = STEP_TEAR_OLD; // switch over
2125
 
 
2126
 
        for (i = 0; i < nCallbackDriver; i++)
2127
 
            callbackDrvArray[i]->vmFilterRebuild(conn,
2128
 
                                                 virNWFilterDomainFWUpdateCB,
2129
 
                                                 &cb);
2130
 
    }
2131
 
 
2132
 
    virHashFree(cb.skipInterfaces, NULL);
2133
 
 
2134
 
    return err;
2135
 
}
2136
 
 
2137
 
 
2138
 
int
2139
 
virNWFilterTestUnassignDef(virConnectPtr conn,
2140
 
                           virNWFilterPoolObjPtr pool)
2141
 
{
2142
 
    int rc = 0;
2143
 
 
2144
 
    virNWFilterLockFilterUpdates();
2145
 
 
2146
 
    pool->wantRemoved = 1;
2147
 
    // trigger the update on VMs referencing the filter
2148
 
    if (virNWFilterTriggerVMFilterRebuild(conn))
2149
 
        rc = 1;
2150
 
 
2151
 
    pool->wantRemoved = 0;
2152
 
    virNWFilterUnlockFilterUpdates();
2153
 
    return rc;
2154
 
}
2155
 
 
2156
 
 
2157
 
virNWFilterPoolObjPtr
2158
 
virNWFilterPoolObjAssignDef(virConnectPtr conn,
2159
 
                            virNWFilterPoolObjListPtr pools,
2160
 
                            virNWFilterDefPtr def)
2161
 
{
2162
 
    virNWFilterPoolObjPtr pool;
2163
 
 
2164
 
    if (virNWFilterDefLoopDetect(conn, pools, def)) {
2165
 
        virNWFilterReportError(VIR_ERR_INVALID_NWFILTER,
2166
 
                              "%s", _("filter would introduce a loop"));
2167
 
        return NULL;
2168
 
    }
2169
 
 
2170
 
    if ((pool = virNWFilterPoolObjFindByName(pools, def->name))) {
2171
 
        virNWFilterLockFilterUpdates();
2172
 
        pool->newDef = def;
2173
 
        // trigger the update on VMs referencing the filter
2174
 
        if (virNWFilterTriggerVMFilterRebuild(conn)) {
2175
 
            pool->newDef = NULL;
2176
 
            virNWFilterUnlockFilterUpdates();
2177
 
            virNWFilterPoolObjUnlock(pool);
2178
 
            return NULL;
2179
 
        }
2180
 
 
2181
 
        virNWFilterDefFree(pool->def);
2182
 
        pool->def = def;
2183
 
        pool->newDef = NULL;
2184
 
        virNWFilterUnlockFilterUpdates();
2185
 
        return pool;
2186
 
    }
2187
 
 
2188
 
    if (VIR_ALLOC(pool) < 0) {
2189
 
        virReportOOMError();
2190
 
        return NULL;
2191
 
    }
2192
 
 
2193
 
    if (virMutexInitRecursive(&pool->lock) < 0) {
2194
 
        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
2195
 
                              "%s", _("cannot initialize mutex"));
2196
 
        VIR_FREE(pool);
2197
 
        return NULL;
2198
 
    }
2199
 
    virNWFilterPoolObjLock(pool);
2200
 
    pool->active = 0;
2201
 
    pool->def = def;
2202
 
 
2203
 
    if (VIR_REALLOC_N(pools->objs, pools->count+1) < 0) {
2204
 
        pool->def = NULL;
2205
 
        virNWFilterPoolObjUnlock(pool);
2206
 
        virNWFilterPoolObjFree(pool);
2207
 
        virReportOOMError();
2208
 
        return NULL;
2209
 
    }
2210
 
    pools->objs[pools->count++] = pool;
2211
 
 
2212
 
    return pool;
2213
 
}
2214
 
 
2215
 
 
2216
 
static virNWFilterPoolObjPtr
2217
 
virNWFilterPoolObjLoad(virConnectPtr conn,
2218
 
                       virNWFilterPoolObjListPtr pools,
2219
 
                       const char *file,
2220
 
                       const char *path)
2221
 
{
2222
 
    virNWFilterDefPtr def;
2223
 
    virNWFilterPoolObjPtr pool;
2224
 
 
2225
 
    if (!(def = virNWFilterDefParseFile(conn, path))) {
2226
 
        return NULL;
2227
 
    }
2228
 
 
2229
 
    if (!virFileMatchesNameSuffix(file, def->name, ".xml")) {
2230
 
        virNWFilterReportError(VIR_ERR_INVALID_NWFILTER,
2231
 
            _("network filter pool config filename '%s' does not match pool name '%s'"),
2232
 
            path, def->name);
2233
 
        virNWFilterDefFree(def);
2234
 
        return NULL;
2235
 
    }
2236
 
 
2237
 
    if (!(pool = virNWFilterPoolObjAssignDef(conn, pools, def))) {
2238
 
        virNWFilterDefFree(def);
2239
 
        return NULL;
2240
 
    }
2241
 
 
2242
 
    pool->configFile = strdup(path);
2243
 
    if (pool->configFile == NULL) {
2244
 
        virReportOOMError();
2245
 
        virNWFilterDefFree(def);
2246
 
        return NULL;
2247
 
    }
2248
 
 
2249
 
    return pool;
2250
 
}
2251
 
 
2252
 
 
2253
 
int
2254
 
virNWFilterPoolLoadAllConfigs(virConnectPtr conn,
2255
 
                              virNWFilterPoolObjListPtr pools,
2256
 
                              const char *configDir)
2257
 
{
2258
 
    DIR *dir;
2259
 
    struct dirent *entry;
2260
 
 
2261
 
    if (!(dir = opendir(configDir))) {
2262
 
        if (errno == ENOENT) {
2263
 
            return 0;
2264
 
        }
2265
 
        virReportSystemError(errno, _("Failed to open dir '%s'"),
2266
 
                             configDir);
2267
 
        return -1;
2268
 
    }
2269
 
 
2270
 
    while ((entry = readdir(dir))) {
2271
 
        char path[PATH_MAX];
2272
 
        virNWFilterPoolObjPtr pool;
2273
 
 
2274
 
        if (entry->d_name[0] == '.')
2275
 
            continue;
2276
 
 
2277
 
        if (!virFileHasSuffix(entry->d_name, ".xml"))
2278
 
            continue;
2279
 
 
2280
 
        if (virFileBuildPath(configDir, entry->d_name,
2281
 
                             NULL, path, PATH_MAX) < 0) {
2282
 
            virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
2283
 
                                   _("config filename '%s/%s' is too long"),
2284
 
                                   configDir, entry->d_name);
2285
 
            continue;
2286
 
        }
2287
 
 
2288
 
        pool = virNWFilterPoolObjLoad(conn, pools, entry->d_name, path);
2289
 
        if (pool)
2290
 
            virNWFilterPoolObjUnlock(pool);
2291
 
    }
2292
 
 
2293
 
    closedir(dir);
2294
 
 
2295
 
    return 0;
2296
 
}
2297
 
 
2298
 
 
2299
 
int
2300
 
virNWFilterPoolObjSaveDef(virNWFilterDriverStatePtr driver,
2301
 
                          virNWFilterPoolObjPtr pool,
2302
 
                          virNWFilterDefPtr def)
2303
 
{
2304
 
    char *xml;
2305
 
    int fd = -1, ret = -1;
2306
 
    ssize_t towrite;
2307
 
 
2308
 
    if (!pool->configFile) {
2309
 
        int err;
2310
 
        char path[PATH_MAX];
2311
 
 
2312
 
        if ((err = virFileMakePath(driver->configDir))) {
2313
 
            virReportSystemError(err,
2314
 
                                 _("cannot create config directory %s"),
2315
 
                                 driver->configDir);
2316
 
            return -1;
2317
 
        }
2318
 
 
2319
 
        if (virFileBuildPath(driver->configDir, def->name, ".xml",
2320
 
                             path, sizeof(path)) < 0) {
2321
 
            virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
2322
 
                                  "%s", _("cannot construct config file path"));
2323
 
            return -1;
2324
 
        }
2325
 
        if (!(pool->configFile = strdup(path))) {
2326
 
            virReportOOMError();
2327
 
            return -1;
2328
 
        }
2329
 
    }
2330
 
 
2331
 
    if (!(xml = virNWFilterDefFormat(def))) {
2332
 
        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
2333
 
                              "%s", _("failed to generate XML"));
2334
 
        return -1;
2335
 
    }
2336
 
 
2337
 
    if ((fd = open(pool->configFile,
2338
 
                   O_WRONLY | O_CREAT | O_TRUNC,
2339
 
                   S_IRUSR | S_IWUSR )) < 0) {
2340
 
        virReportSystemError(errno,
2341
 
                             _("cannot create config file %s"),
2342
 
                             pool->configFile);
2343
 
        goto cleanup;
2344
 
    }
2345
 
 
2346
 
    towrite = strlen(xml);
2347
 
    if (safewrite(fd, xml, towrite) != towrite) {
2348
 
        virReportSystemError(errno,
2349
 
                             _("cannot write config file %s"),
2350
 
                             pool->configFile);
2351
 
        goto cleanup;
2352
 
    }
2353
 
 
2354
 
    if (close(fd) < 0) {
2355
 
        virReportSystemError(errno,
2356
 
                             _("cannot save config file %s"),
2357
 
                             pool->configFile);
2358
 
        goto cleanup;
2359
 
    }
2360
 
 
2361
 
    ret = 0;
2362
 
 
2363
 
 cleanup:
2364
 
    if (fd != -1)
2365
 
        close(fd);
2366
 
 
2367
 
    VIR_FREE(xml);
2368
 
 
2369
 
    return ret;
2370
 
}
2371
 
 
2372
 
 
2373
 
int
2374
 
virNWFilterPoolObjDeleteDef(virNWFilterPoolObjPtr pool)
2375
 
{
2376
 
    if (!pool->configFile) {
2377
 
        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
2378
 
                               _("no config file for %s"), pool->def->name);
2379
 
        return -1;
2380
 
    }
2381
 
 
2382
 
    if (unlink(pool->configFile) < 0) {
2383
 
        virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
2384
 
                               _("cannot remove config for %s"),
2385
 
                               pool->def->name);
2386
 
        return -1;
2387
 
    }
2388
 
 
2389
 
    return 0;
2390
 
}
2391
 
 
2392
 
 
2393
 
static void
2394
 
virNWIPAddressFormat(virBufferPtr buf, nwIPAddressPtr ipaddr)
2395
 
{
2396
 
    virSocketAddrPtr addr = &ipaddr->addr;
2397
 
    char *output = virSocketFormatAddr(addr);
2398
 
 
2399
 
    if (output) {
2400
 
        virBufferVSprintf(buf, "%s", output);
2401
 
        VIR_FREE(output);
2402
 
    }
2403
 
}
2404
 
 
2405
 
 
2406
 
static void
2407
 
virNWFilterRuleDefDetailsFormat(virBufferPtr buf,
2408
 
                                const char *type,
2409
 
                                const virXMLAttr2Struct *att,
2410
 
                                virNWFilterRuleDefPtr def)
2411
 
{
2412
 
    int i = 0, j;
2413
 
    bool typeShown = 0;
2414
 
    bool neverShown = 1;
2415
 
    bool asHex;
2416
 
    enum match {
2417
 
        MATCH_NONE = 0,
2418
 
        MATCH_YES,
2419
 
        MATCH_NO
2420
 
    } matchShown = MATCH_NONE;
2421
 
    nwItemDesc *item;
2422
 
 
2423
 
    while (att[i].name) {
2424
 
        item = (nwItemDesc *)((char *)def + att[i].dataIdx);
2425
 
        enum virNWFilterEntryItemFlags flags = item->flags;
2426
 
        void *storage_ptr;
2427
 
        if ((flags & NWFILTER_ENTRY_ITEM_FLAG_EXISTS)) {
2428
 
            if (!typeShown) {
2429
 
                virBufferVSprintf(buf, "    <%s", type);
2430
 
                typeShown = 1;
2431
 
                neverShown = 0;
2432
 
            }
2433
 
 
2434
 
            if ((flags & NWFILTER_ENTRY_ITEM_FLAG_IS_NEG)) {
2435
 
                if (matchShown == MATCH_NONE) {
2436
 
                    virBufferAddLit(buf, " match='no'");
2437
 
                    matchShown = MATCH_NO;
2438
 
                } else if (matchShown == MATCH_YES) {
2439
 
                    virBufferAddLit(buf, "/>\n");
2440
 
                    typeShown = 0;
2441
 
                    matchShown = MATCH_NONE;
2442
 
                    continue;
2443
 
                }
2444
 
            } else {
2445
 
                if (matchShown == MATCH_NO) {
2446
 
                    virBufferAddLit(buf, "/>\n");
2447
 
                    typeShown = 0;
2448
 
                    matchShown = MATCH_NONE;
2449
 
                    continue;
2450
 
                }
2451
 
                matchShown = MATCH_YES;
2452
 
            }
2453
 
 
2454
 
            virBufferVSprintf(buf, " %s='",
2455
 
                              att[i].name);
2456
 
            if (att[i].formatter) {
2457
 
               if (!att[i].formatter(buf, def)) {
2458
 
                  virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
2459
 
                                         _("formatter for %s %s reported error"),
2460
 
                                         type,
2461
 
                                         att[i].name);
2462
 
                   goto err_exit;
2463
 
               }
2464
 
            } else if ((flags & NWFILTER_ENTRY_ITEM_FLAG_HAS_VAR)) {
2465
 
                virBufferVSprintf(buf, "$%s", item->var);
2466
 
            } else {
2467
 
               asHex = false;
2468
 
 
2469
 
               switch (item->datatype) {
2470
 
 
2471
 
               case DATATYPE_UINT8_HEX:
2472
 
                   asHex = true;
2473
 
               case DATATYPE_IPMASK:
2474
 
               case DATATYPE_IPV6MASK:
2475
 
                   // display all masks in CIDR format
2476
 
               case DATATYPE_UINT8:
2477
 
                   storage_ptr = &item->u.u8;
2478
 
                   virBufferVSprintf(buf, asHex ? "0x%x" : "%d",
2479
 
                                     *(uint8_t *)storage_ptr);
2480
 
               break;
2481
 
 
2482
 
               case DATATYPE_UINT16_HEX:
2483
 
                   asHex = true;
2484
 
               case DATATYPE_UINT16:
2485
 
                   storage_ptr = &item->u.u16;
2486
 
                   virBufferVSprintf(buf, asHex ? "0x%x" : "%d",
2487
 
                                     *(uint16_t *)storage_ptr);
2488
 
               break;
2489
 
 
2490
 
               case DATATYPE_IPADDR:
2491
 
               case DATATYPE_IPV6ADDR:
2492
 
                   storage_ptr = &item->u.ipaddr;
2493
 
                   virNWIPAddressFormat(buf,
2494
 
                                        (nwIPAddressPtr)storage_ptr);
2495
 
               break;
2496
 
 
2497
 
               case DATATYPE_MACMASK:
2498
 
               case DATATYPE_MACADDR:
2499
 
                   storage_ptr = &item->u.macaddr;
2500
 
                   for (j = 0; j < 6; j++)
2501
 
                       virBufferVSprintf(buf, "%02x%s",
2502
 
                                      ((nwMACAddressPtr)storage_ptr)->addr[j],
2503
 
                                      (j < 5) ? ":" : "");
2504
 
               break;
2505
 
 
2506
 
               case DATATYPE_STRING:
2507
 
               default:
2508
 
                   virBufferVSprintf(buf,
2509
 
                                     "UNSUPPORTED DATATYPE 0x%02x\n",
2510
 
                                     att[i].datatype);
2511
 
               }
2512
 
            }
2513
 
            virBufferAddLit(buf, "'");
2514
 
        }
2515
 
        i++;
2516
 
    }
2517
 
    if (typeShown)
2518
 
       virBufferAddLit(buf, "/>\n");
2519
 
 
2520
 
    if (neverShown)
2521
 
       virBufferVSprintf(buf,
2522
 
                         "    <%s/>\n", type);
2523
 
 
2524
 
err_exit:
2525
 
    return;
2526
 
}
2527
 
 
2528
 
 
2529
 
static char *
2530
 
virNWFilterRuleDefFormat(virNWFilterRuleDefPtr def)
2531
 
{
2532
 
    int i;
2533
 
    virBuffer buf  = VIR_BUFFER_INITIALIZER;
2534
 
    virBuffer buf2 = VIR_BUFFER_INITIALIZER;
2535
 
    char *data;
2536
 
 
2537
 
    virBufferVSprintf(&buf, "  <rule action='%s' direction='%s' priority='%d'",
2538
 
                      virNWFilterRuleActionTypeToString(def->action),
2539
 
                      virNWFilterRuleDirectionTypeToString(def->tt),
2540
 
                      def->priority);
2541
 
 
2542
 
    if ((def->flags & RULE_FLAG_NO_STATEMATCH))
2543
 
        virBufferAddLit(&buf, " statematch='false'");
2544
 
 
2545
 
    i = 0;
2546
 
    while (virAttr[i].id) {
2547
 
        if (virAttr[i].prtclType == def->prtclType) {
2548
 
            virNWFilterRuleDefDetailsFormat(&buf2,
2549
 
                                            virAttr[i].id,
2550
 
                                            virAttr[i].att,
2551
 
                                            def);
2552
 
            break;
2553
 
        }
2554
 
        i++;
2555
 
    }
2556
 
 
2557
 
    if (virBufferError(&buf2))
2558
 
        goto no_memory;
2559
 
 
2560
 
    data = virBufferContentAndReset(&buf2);
2561
 
 
2562
 
    if (data) {
2563
 
        virBufferAddLit(&buf, ">\n");
2564
 
        virBufferVSprintf(&buf, "%s  </rule>\n", data);
2565
 
        VIR_FREE(data);
2566
 
    } else
2567
 
        virBufferAddLit(&buf, "/>\n");
2568
 
 
2569
 
    if (virBufferError(&buf))
2570
 
        goto no_memory;
2571
 
 
2572
 
    return virBufferContentAndReset(&buf);
2573
 
 
2574
 
no_memory:
2575
 
    virReportOOMError();
2576
 
    virBufferFreeAndReset(&buf);
2577
 
    virBufferFreeAndReset(&buf2);
2578
 
 
2579
 
    return NULL;
2580
 
}
2581
 
 
2582
 
 
2583
 
static char *
2584
 
virNWFilterIncludeDefFormat(virNWFilterIncludeDefPtr inc)
2585
 
{
2586
 
    char *attrs;
2587
 
    virBuffer buf = VIR_BUFFER_INITIALIZER;
2588
 
 
2589
 
    virBufferVSprintf(&buf,"  <filterref filter='%s'",
2590
 
                      inc->filterref);
2591
 
 
2592
 
    attrs = virNWFilterFormatParamAttributes(inc->params, "    ");
2593
 
 
2594
 
    if (!attrs || strlen(attrs) <= 1)
2595
 
        virBufferAddLit(&buf, "/>\n");
2596
 
    else
2597
 
        virBufferVSprintf(&buf, ">\n%s  </filterref>\n", attrs);
2598
 
 
2599
 
    if (virBufferError(&buf)) {
2600
 
        virReportOOMError();
2601
 
        virBufferFreeAndReset(&buf);
2602
 
        return NULL;
2603
 
    }
2604
 
 
2605
 
    return virBufferContentAndReset(&buf);
2606
 
}
2607
 
 
2608
 
 
2609
 
static char *
2610
 
virNWFilterEntryFormat(virNWFilterEntryPtr entry)
2611
 
{
2612
 
    if (entry->rule)
2613
 
        return virNWFilterRuleDefFormat(entry->rule);
2614
 
    return virNWFilterIncludeDefFormat(entry->include);
2615
 
}
2616
 
 
2617
 
 
2618
 
char *
2619
 
virNWFilterDefFormat(virNWFilterDefPtr def)
2620
 
{
2621
 
    virBuffer buf = VIR_BUFFER_INITIALIZER;
2622
 
    char uuid[VIR_UUID_STRING_BUFLEN];
2623
 
    int i;
2624
 
    char *xml;
2625
 
 
2626
 
    virBufferVSprintf(&buf, "<filter name='%s' chain='%s'",
2627
 
                      def->name,
2628
 
                      virNWFilterChainSuffixTypeToString(def->chainsuffix));
2629
 
    virBufferAddLit(&buf, ">\n");
2630
 
 
2631
 
    virUUIDFormat(def->uuid, uuid);
2632
 
    virBufferVSprintf(&buf,"  <uuid>%s</uuid>\n", uuid);
2633
 
 
2634
 
    for (i = 0; i < def->nentries; i++) {
2635
 
        xml = virNWFilterEntryFormat(def->filterEntries[i]);
2636
 
        if (!xml)
2637
 
            goto err_exit;
2638
 
        virBufferVSprintf(&buf, "%s", xml);
2639
 
        VIR_FREE(xml);
2640
 
    }
2641
 
 
2642
 
    virBufferAddLit(&buf, "</filter>\n");
2643
 
 
2644
 
    if (virBufferError(&buf))
2645
 
        goto no_memory;
2646
 
 
2647
 
    return virBufferContentAndReset(&buf);
2648
 
 
2649
 
 no_memory:
2650
 
    virReportOOMError();
2651
 
 
2652
 
 err_exit:
2653
 
    virBufferFreeAndReset(&buf);
2654
 
    return NULL;
2655
 
}
2656
 
 
2657
 
 
2658
 
char *virNWFilterConfigFile(const char *dir,
2659
 
                            const char *name)
2660
 
{
2661
 
    char *ret = NULL;
2662
 
 
2663
 
    if (virAsprintf(&ret, "%s/%s.xml", dir, name) < 0) {
2664
 
        virReportOOMError();
2665
 
        return NULL;
2666
 
    }
2667
 
 
2668
 
    return ret;
2669
 
}
2670
 
 
2671
 
 
2672
 
int virNWFilterConfLayerInit(virHashIterator domUpdateCB)
2673
 
{
2674
 
    virNWFilterDomainFWUpdateCB = domUpdateCB;
2675
 
 
2676
 
    if (virMutexInitRecursive(&updateMutex))
2677
 
        return 1;
2678
 
 
2679
 
    return 0;
2680
 
}
2681
 
 
2682
 
 
2683
 
void virNWFilterConfLayerShutdown(void)
2684
 
{
2685
 
    virMutexDestroy(&updateMutex);
2686
 
}
2687
 
 
2688
 
 
2689
 
void virNWFilterPoolObjLock(virNWFilterPoolObjPtr obj)
2690
 
{
2691
 
    virMutexLock(&obj->lock);
2692
 
}
2693
 
 
2694
 
void virNWFilterPoolObjUnlock(virNWFilterPoolObjPtr obj)
2695
 
{
2696
 
    virMutexUnlock(&obj->lock);
2697
 
}