2
* nwfilter_conf.c: network filter XML processing
3
* (derived from storage_conf.c)
5
* Copyright (C) 2006-2010 Red Hat, Inc.
6
* Copyright (C) 2006-2008 Daniel P. Berrange
8
* Copyright (C) 2010 IBM Corporation
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.
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.
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
24
* Author: Stefan Berger <stefanb@us.ibm.com>
29
#include <sys/types.h>
33
#if HAVE_NET_ETHERNET_H
34
# include <net/ethernet.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"
49
#define VIR_FROM_THIS VIR_FROM_NWFILTER
52
VIR_ENUM_IMPL(virNWFilterRuleAction, VIR_NWFILTER_RULE_ACTION_LAST,
56
VIR_ENUM_IMPL(virNWFilterJumpTarget, VIR_NWFILTER_RULE_ACTION_LAST,
60
VIR_ENUM_IMPL(virNWFilterRuleDirection, VIR_NWFILTER_RULE_DIRECTION_LAST,
65
VIR_ENUM_IMPL(virNWFilterChainPolicy, VIR_NWFILTER_CHAIN_POLICY_LAST,
69
VIR_ENUM_IMPL(virNWFilterEbtablesTable, VIR_NWFILTER_EBTABLES_TABLE_LAST,
74
VIR_ENUM_IMPL(virNWFilterChainSuffix, VIR_NWFILTER_CHAINSUFFIX_LAST,
81
VIR_ENUM_IMPL(virNWFilterRuleProtocol, VIR_NWFILTER_RULE_PROTOCOL_LAST,
108
* a map entry for a simple static int-to-string map
115
#define INTMAP_ENTRY(ATT, VAL) { .attr = ATT, .val = VAL }
116
#define INTMAP_ENTRY_LAST { .val = NULL }
120
* only one filter update allowed
122
static virMutex updateMutex;
125
virNWFilterLockFilterUpdates(void) {
126
virMutexLock(&updateMutex);
130
virNWFilterUnlockFilterUpdates(void) {
131
virMutexUnlock(&updateMutex);
137
* attribute names for the rules XML
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";
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
186
* @intmap: Pointer to int-to-string map
187
* @attr: The attribute to look up
188
* @res: Pointer to string pointer for result
190
* Returns 1 if value was found with result returned, 0 otherwise.
192
* lookup a map entry given the integer.
195
intMapGetByInt(const struct int_map *intmap, int32_t attr, const char **res)
199
while (intmap[i].val && !found) {
200
if (intmap[i].attr == attr) {
201
*res = intmap[i].val;
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
217
* Returns 0 if no entry was found, 1 otherwise.
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.
223
intMapGetByString(const struct int_map *intmap, const char *str, int casecmp,
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;
241
virNWFilterRuleDefFree(virNWFilterRuleDefPtr def) {
246
for (i = 0; i < def->nvars; i++)
247
VIR_FREE(def->vars[i]);
256
virNWFilterIncludeDefFree(virNWFilterIncludeDefPtr inc) {
259
virNWFilterHashTableFree(inc->params);
260
VIR_FREE(inc->filterref);
266
virNWFilterEntryFree(virNWFilterEntryPtr entry) {
270
virNWFilterRuleDefFree(entry->rule);
271
virNWFilterIncludeDefFree(entry->include);
277
virNWFilterDefFree(virNWFilterDefPtr def) {
284
for (i = 0; i < def->nentries; i++)
285
virNWFilterEntryFree(def->filterEntries[i]);
287
VIR_FREE(def->filterEntries);
294
virNWFilterPoolObjFree(virNWFilterPoolObjPtr obj) {
298
virNWFilterDefFree(obj->def);
299
virNWFilterDefFree(obj->newDef);
301
VIR_FREE(obj->configFile);
303
virMutexDestroy(&obj->lock);
310
virNWFilterPoolObjListFree(virNWFilterPoolObjListPtr pools)
313
for (i = 0 ; i < pools->count ; i++)
314
virNWFilterPoolObjFree(pools->objs[i]);
315
VIR_FREE(pools->objs);
321
virNWFilterRuleDefAddVar(virNWFilterRuleDefPtr nwf,
328
for (i = 0; i < nwf->nvars; i++)
329
if (STREQ(nwf->vars[i], var)) {
330
item->var = nwf->vars[i];
335
if (VIR_REALLOC_N(nwf->vars, nwf->nvars+1) < 0) {
340
nwf->vars[nwf->nvars] = strdup(var);
342
if (!nwf->vars[nwf->nvars]) {
347
item->var = nwf->vars[nwf->nvars++];
354
virNWFilterPoolObjRemove(virNWFilterPoolObjListPtr pools,
355
virNWFilterPoolObjPtr pool)
359
virNWFilterPoolObjUnlock(pool);
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]);
367
if (i < (pools->count - 1))
368
memmove(pools->objs + i, pools->objs + i + 1,
369
sizeof(*(pools->objs)) * (pools->count - (i + 1)));
371
if (VIR_REALLOC_N(pools->objs, pools->count - 1) < 0) {
372
; /* Failure to reduce memory allocation isn't fatal */
378
virNWFilterPoolObjUnlock(pools->objs[i]);
384
typedef bool (*valueValidator)(enum attrDatatype datatype, void *valptr,
385
virNWFilterRuleDefPtr nwf);
386
typedef bool (*valueFormatter)(virBufferPtr buf,
387
virNWFilterRuleDefPtr nwf);
389
typedef struct _virXMLAttr2Struct virXMLAttr2Struct;
390
struct _virXMLAttr2Struct
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
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"),
410
checkMacProtocolID(enum attrDatatype datatype, void *value,
411
virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED)
415
if (datatype == DATATYPE_STRING) {
416
if (intMapGetByString(macProtoMap, (char *)value, 1, &res) == 0)
418
datatype = DATATYPE_UINT16;
419
} else if (datatype == DATATYPE_UINT16 ||
420
datatype == DATATYPE_UINT16_HEX) {
421
res = (uint32_t)*(uint16_t *)value;
427
nwf->p.ethHdrFilter.dataProtocolID.u.u16 = res;
428
nwf->p.ethHdrFilter.dataProtocolID.datatype = datatype;
437
macProtocolIDFormatter(virBufferPtr buf,
438
virNWFilterRuleDefPtr nwf)
440
const char *str = NULL;
443
if (intMapGetByInt(macProtoMap,
444
nwf->p.ethHdrFilter.dataProtocolID.u.u16,
446
virBufferVSprintf(buf, "%s", str);
448
if (nwf->p.ethHdrFilter.dataProtocolID.datatype == DATATYPE_UINT16)
450
virBufferVSprintf(buf, asHex ? "0x%x" : "%d",
451
nwf->p.ethHdrFilter.dataProtocolID.u.u16);
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
462
checkValidMask(unsigned char *data, int len)
468
while ((idx >> 3) < len) {
470
if (!(data[idx>>3] & mask))
473
if ((data[idx>>3] & mask))
487
checkMACMask(enum attrDatatype datatype ATTRIBUTE_UNUSED,
489
virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED)
491
return checkValidMask((unsigned char *)macMask, 6);
496
* supported arp opcode -- see 'ebtables -h arp' for the naming
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"),
513
arpOpcodeValidator(enum attrDatatype datatype,
515
virNWFilterRuleDefPtr nwf)
519
if (datatype == DATATYPE_STRING) {
520
if (intMapGetByString(arpOpcodeMap, (char *)value, 1, &res) == 0)
522
datatype = DATATYPE_UINT16;
523
} else if (datatype == DATATYPE_UINT16 ||
524
datatype == DATATYPE_UINT16_HEX) {
525
res = (uint32_t)*(uint16_t *)value;
529
nwf->p.arpHdrFilter.dataOpcode.u.u16 = res;
530
nwf->p.arpHdrFilter.dataOpcode.datatype = datatype;
538
arpOpcodeFormatter(virBufferPtr buf,
539
virNWFilterRuleDefPtr nwf)
541
const char *str = NULL;
543
if (intMapGetByInt(arpOpcodeMap,
544
nwf->p.arpHdrFilter.dataOpcode.u.u16,
546
virBufferVSprintf(buf, "%s", str);
548
virBufferVSprintf(buf, "%d", nwf->p.arpHdrFilter.dataOpcode.u.u16);
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"),
560
INTMAP_ENTRY(IPPROTO_ESP, "esp"),
561
INTMAP_ENTRY(IPPROTO_AH, "ah"),
562
INTMAP_ENTRY(IPPROTO_ICMP, "icmp"),
563
INTMAP_ENTRY(IPPROTO_IGMP, "igmp"),
565
INTMAP_ENTRY(IPPROTO_SCTP, "sctp"),
567
INTMAP_ENTRY(IPPROTO_ICMPV6, "icmpv6"),
572
static bool checkIPProtocolID(enum attrDatatype datatype,
574
virNWFilterRuleDefPtr nwf)
578
if (datatype == DATATYPE_STRING) {
579
if (intMapGetByString(ipProtoMap, (char *)value, 1, &res) == 0)
581
datatype = DATATYPE_UINT8_HEX;
582
} else if (datatype == DATATYPE_UINT8 ||
583
datatype == DATATYPE_UINT8_HEX) {
584
res = (uint32_t)*(uint16_t *)value;
588
nwf->p.ipHdrFilter.ipHdr.dataProtocolID.u.u8 = res;
589
nwf->p.ipHdrFilter.ipHdr.dataProtocolID.datatype = datatype;
597
formatIPProtocolID(virBufferPtr buf,
598
virNWFilterRuleDefPtr nwf)
600
const char *str = NULL;
603
if (intMapGetByInt(ipProtoMap,
604
nwf->p.ipHdrFilter.ipHdr.dataProtocolID.u.u8,
606
virBufferVSprintf(buf, "%s", str);
608
if (nwf->p.ipHdrFilter.ipHdr.dataProtocolID.datatype == DATATYPE_UINT8)
610
virBufferVSprintf(buf, asHex ? "0x%x" : "%d",
611
nwf->p.ipHdrFilter.ipHdr.dataProtocolID.u.u8);
618
dscpValidator(enum attrDatatype datatype, void *val,
619
virNWFilterRuleDefPtr nwf)
621
uint8_t dscp = *(uint16_t *)val;
625
nwf->p.ipHdrFilter.ipHdr.dataDSCP.datatype = datatype;
630
#define COMMON_MAC_PROPS(STRUCT) \
633
.datatype = DATATYPE_MACADDR,\
634
.dataIdx = offsetof(virNWFilterRuleDef,p.STRUCT.ethHdr.dataSrcMACAddr),\
638
.datatype = DATATYPE_MACMASK,\
639
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ethHdr.dataSrcMACMask),\
643
.datatype = DATATYPE_MACADDR,\
644
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ethHdr.dataDstMACAddr),\
648
.datatype = DATATYPE_MACMASK,\
649
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ethHdr.dataDstMACMask),\
653
static const virXMLAttr2Struct macAttributes[] = {
654
COMMON_MAC_PROPS(ethHdrFilter),
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,
667
static const virXMLAttr2Struct arpAttributes[] = {
668
COMMON_MAC_PROPS(arpHdrFilter),
671
.datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
672
.dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataHWType),
674
.name = "protocoltype",
675
.datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
676
.dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataProtocolType),
679
.datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX | DATATYPE_STRING,
680
.dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataOpcode),
681
.validator= arpOpcodeValidator,
682
.formatter= arpOpcodeFormatter,
684
.name = ARPSRCMACADDR,
685
.datatype = DATATYPE_MACADDR,
686
.dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataARPSrcMACAddr),
688
.name = ARPDSTMACADDR,
689
.datatype = DATATYPE_MACADDR,
690
.dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataARPDstMACAddr),
692
.name = ARPSRCIPADDR,
693
.datatype = DATATYPE_IPADDR,
694
.dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataARPSrcIPAddr),
696
.name = ARPDSTIPADDR,
697
.datatype = DATATYPE_IPADDR,
698
.dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataARPDstIPAddr),
705
static const virXMLAttr2Struct ipAttributes[] = {
706
COMMON_MAC_PROPS(ipHdrFilter),
709
.datatype = DATATYPE_IPADDR,
710
.dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.ipHdr.dataSrcIPAddr),
714
.datatype = DATATYPE_IPMASK,
715
.dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.ipHdr.dataSrcIPMask),
719
.datatype = DATATYPE_IPADDR,
720
.dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.ipHdr.dataDstIPAddr),
724
.datatype = DATATYPE_IPMASK,
725
.dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.ipHdr.dataDstIPMask),
729
.datatype = DATATYPE_STRING | DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
730
.dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.ipHdr.dataProtocolID),
731
.validator= checkIPProtocolID,
732
.formatter= formatIPProtocolID,
735
.name = SRCPORTSTART,
736
.datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
737
.dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.portData.dataSrcPortStart),
741
.datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
742
.dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.portData.dataSrcPortEnd),
745
.name = DSTPORTSTART,
746
.datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
747
.dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.portData.dataDstPortStart),
751
.datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
752
.dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.portData.dataDstPortEnd),
756
.datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
757
.dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.ipHdr.dataDSCP),
758
.validator = dscpValidator,
766
static const virXMLAttr2Struct ipv6Attributes[] = {
767
COMMON_MAC_PROPS(ipv6HdrFilter),
770
.datatype = DATATYPE_IPV6ADDR,
771
.dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.ipHdr.dataSrcIPAddr),
775
.datatype = DATATYPE_IPV6MASK,
776
.dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.ipHdr.dataSrcIPMask),
780
.datatype = DATATYPE_IPV6ADDR,
781
.dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.ipHdr.dataDstIPAddr),
785
.datatype = DATATYPE_IPV6MASK,
786
.dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.ipHdr.dataDstIPMask),
790
.datatype = DATATYPE_STRING | DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
791
.dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.ipHdr.dataProtocolID),
792
.validator= checkIPProtocolID,
793
.formatter= formatIPProtocolID,
796
.name = SRCPORTSTART,
797
.datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
798
.dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.portData.dataSrcPortStart),
802
.datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
803
.dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.portData.dataSrcPortEnd),
806
.name = DSTPORTSTART,
807
.datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
808
.dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.portData.dataDstPortStart),
812
.datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
813
.dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.portData.dataDstPortEnd),
821
#define COMMON_L3_MAC_PROPS(STRUCT) \
824
.datatype = DATATYPE_MACADDR,\
825
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.dataSrcMACAddr),\
828
#define COMMON_IP_PROPS(STRUCT, ADDRTYPE, MASKTYPE) \
829
COMMON_L3_MAC_PROPS(STRUCT),\
832
.datatype = ADDRTYPE,\
833
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPAddr),\
837
.datatype = MASKTYPE,\
838
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPMask),\
842
.datatype = ADDRTYPE,\
843
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPAddr),\
847
.datatype = MASKTYPE,\
848
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPMask),\
852
.datatype = ADDRTYPE,\
853
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPFrom),\
857
.datatype = ADDRTYPE,\
858
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPTo),\
862
.datatype = ADDRTYPE,\
863
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPFrom),\
867
.datatype = DATATYPE_IPADDR,\
868
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPTo),\
872
.datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,\
873
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDSCP),\
874
.validator = dscpValidator,\
877
.name = "connlimit-above",\
878
.datatype = DATATYPE_UINT16,\
879
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataConnlimitAbove),\
882
#define COMMON_PORT_PROPS(STRUCT) \
884
.name = SRCPORTSTART,\
885
.datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,\
886
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.portData.dataSrcPortStart),\
890
.datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,\
891
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.portData.dataSrcPortEnd),\
894
.name = DSTPORTSTART,\
895
.datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,\
896
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.portData.dataDstPortStart),\
900
.datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,\
901
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.portData.dataDstPortEnd),\
904
static const virXMLAttr2Struct tcpAttributes[] = {
905
COMMON_IP_PROPS(tcpHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
906
COMMON_PORT_PROPS(tcpHdrFilter),
909
.datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
910
.dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.dataTCPOption),
917
static const virXMLAttr2Struct udpAttributes[] = {
918
COMMON_IP_PROPS(udpHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
919
COMMON_PORT_PROPS(udpHdrFilter),
925
static const virXMLAttr2Struct udpliteAttributes[] = {
926
COMMON_IP_PROPS(udpliteHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
932
static const virXMLAttr2Struct espAttributes[] = {
933
COMMON_IP_PROPS(espHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
939
static const virXMLAttr2Struct ahAttributes[] = {
940
COMMON_IP_PROPS(ahHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
946
static const virXMLAttr2Struct sctpAttributes[] = {
947
COMMON_IP_PROPS(sctpHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
948
COMMON_PORT_PROPS(sctpHdrFilter),
955
static const virXMLAttr2Struct icmpAttributes[] = {
956
COMMON_IP_PROPS(icmpHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
959
.datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
960
.dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.dataICMPType),
964
.datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
965
.dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.dataICMPCode),
973
static const virXMLAttr2Struct allAttributes[] = {
974
COMMON_IP_PROPS(allHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
981
static const virXMLAttr2Struct igmpAttributes[] = {
982
COMMON_IP_PROPS(igmpHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK),
989
static const virXMLAttr2Struct tcpipv6Attributes[] = {
990
COMMON_IP_PROPS(tcpHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK),
991
COMMON_PORT_PROPS(tcpHdrFilter),
994
.datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
995
.dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.dataTCPOption),
1002
static const virXMLAttr2Struct udpipv6Attributes[] = {
1003
COMMON_IP_PROPS(udpHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK),
1004
COMMON_PORT_PROPS(udpHdrFilter),
1011
static const virXMLAttr2Struct udpliteipv6Attributes[] = {
1012
COMMON_IP_PROPS(udpliteHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK),
1019
static const virXMLAttr2Struct espipv6Attributes[] = {
1020
COMMON_IP_PROPS(espHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK),
1027
static const virXMLAttr2Struct ahipv6Attributes[] = {
1028
COMMON_IP_PROPS(ahHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK),
1035
static const virXMLAttr2Struct sctpipv6Attributes[] = {
1036
COMMON_IP_PROPS(sctpHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK),
1037
COMMON_PORT_PROPS(sctpHdrFilter),
1044
static const virXMLAttr2Struct icmpv6Attributes[] = {
1045
COMMON_IP_PROPS(icmpHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK),
1048
.datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
1049
.dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.dataICMPType),
1053
.datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
1054
.dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.dataICMPCode),
1062
static const virXMLAttr2Struct allipv6Attributes[] = {
1063
COMMON_IP_PROPS(allHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK),
1070
typedef struct _virAttributes virAttributes;
1071
struct _virAttributes {
1073
const virXMLAttr2Struct *att;
1074
enum virNWFilterRuleProtocolType prtclType;
1077
#define PROTOCOL_ENTRY(ID, ATT, PRTCLTYPE) \
1078
{ .id = ID, .att = ATT, .prtclType = PRTCLTYPE }
1079
#define PROTOCOL_ENTRY_LAST { .id = NULL }
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),
1110
virNWMACAddressParser(const char *input,
1111
nwMACAddressPtr output)
1113
if (virParseMacAddr(input, &output->addr[0]) == 0)
1120
virNWIPv4AddressParser(const char *input,
1121
nwIPAddressPtr output)
1123
if (virSocketParseIpv4Addr(input, &output->addr) == -1)
1130
virNWIPv6AddressParser(const char *input,
1131
nwIPAddressPtr output)
1133
if (virSocketParseIpv6Addr(input, &output->addr) == -1)
1140
virNWFilterRuleDetailsParse(xmlNodePtr node,
1141
virNWFilterRuleDefPtr nwf,
1142
const virXMLAttr2Struct *att)
1144
int rc = 0, g_rc = 0;
1148
enum attrDatatype datatype, att_datatypes;
1149
enum virNWFilterEntryItemFlags *flags ,match_flag = 0, flags_set = 0;
1152
unsigned int uint_val;
1153
void *data_ptr = NULL, *storage_ptr;
1154
valueValidator validator;
1155
char *match = virXMLPropString(node, "match");
1159
if (match && STREQ(match, "no"))
1160
match_flag = NWFILTER_ENTRY_ITEM_FLAG_IS_NEG;
1164
while (att[idx].name != NULL) {
1165
prop = virXMLPropString(node, att[idx].name);
1167
item = (nwItemDesc *)((char *)nwf + att[idx].dataIdx);
1168
flags = &item->flags;
1169
flags_set = match_flag;
1176
if (STRPREFIX(prop, "$")) {
1177
flags_set |= NWFILTER_ENTRY_ITEM_FLAG_HAS_VAR;
1180
if (virNWFilterRuleDefAddVar(nwf,
1189
att_datatypes = att[idx].datatype;
1191
while (datatype <= DATATYPE_LAST && found == 0 && rc == 0) {
1192
if ((att_datatypes & datatype)) {
1194
att_datatypes ^= datatype;
1196
validator = att[idx].validator;
1201
case DATATYPE_UINT8_HEX:
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;
1209
data_ptr = &uint_val;
1216
case DATATYPE_UINT16_HEX:
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;
1224
data_ptr = &uint_val;
1231
case DATATYPE_IPADDR:
1232
storage_ptr = &item->u.ipaddr;
1233
if (!virNWIPv4AddressParser(prop,
1234
(nwIPAddressPtr)storage_ptr)) {
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) {
1245
*(uint8_t *)storage_ptr =
1248
data_ptr = &uint_val;
1252
if (virNWIPv4AddressParser(prop, &ipaddr)) {
1253
int_val = virSocketGetNumNetmaskBits(
1256
*(uint8_t *)storage_ptr = int_val;
1265
case DATATYPE_MACADDR:
1266
storage_ptr = &item->u.macaddr;
1267
if (!virNWMACAddressParser(prop,
1268
(nwMACAddressPtr)storage_ptr)) {
1274
case DATATYPE_MACMASK:
1275
validator = checkMACMask;
1276
storage_ptr = &item->u.macaddr;
1277
if (!virNWMACAddressParser(prop,
1278
(nwMACAddressPtr)storage_ptr)) {
1281
data_ptr = storage_ptr;
1285
case DATATYPE_IPV6ADDR:
1286
storage_ptr = &item->u.ipaddr;
1287
if (!virNWIPv6AddressParser(prop,
1288
(nwIPAddressPtr)storage_ptr)) {
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) {
1299
*(uint8_t *)storage_ptr =
1302
data_ptr = &uint_val;
1306
if (virNWIPv6AddressParser(prop, &ipaddr)) {
1307
int_val = virSocketGetNumNetmaskBits(
1310
*(uint8_t *)storage_ptr = int_val;
1319
case DATATYPE_STRING:
1335
if (rc != 0 && att_datatypes != 0) {
1343
if (found == 1 && rc == 0) {
1344
*flags = NWFILTER_ENTRY_ITEM_FLAG_EXISTS | flags_set;
1345
item->datatype = datatype >> 1;
1347
if (!validator(datatype >> 1, data_ptr, nwf)) {
1355
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1356
_("%s has illegal value %s"),
1357
att[idx].name, prop);
1377
static virNWFilterIncludeDefPtr
1378
virNWFilterIncludeParse(xmlNodePtr cur)
1380
virNWFilterIncludeDefPtr ret;
1382
if (VIR_ALLOC(ret) < 0) {
1383
virReportOOMError();
1387
ret->filterref = virXMLPropString(cur, "filter");
1388
if (!ret->filterref) {
1389
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1391
_("rule node requires action attribute"));
1395
ret->params = virNWFilterParseParamAttributes(cur);
1403
virNWFilterIncludeDefFree(ret);
1410
virNWFilterRuleDefFixup(virNWFilterRuleDefPtr rule)
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);
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);
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);
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);
1438
case VIR_NWFILTER_RULE_PROTOCOL_ARP:
1439
case VIR_NWFILTER_RULE_PROTOCOL_RARP:
1440
case VIR_NWFILTER_RULE_PROTOCOL_NONE:
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);
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);
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);
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);
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);
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);
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);
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);
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);
1570
case VIR_NWFILTER_RULE_PROTOCOL_LAST:
1573
#undef COPY_NEG_SIGN
1577
static virNWFilterRuleDefPtr
1578
virNWFilterRuleParse(xmlNodePtr node)
1586
unsigned int priority;
1589
virNWFilterRuleDefPtr ret;
1591
if (VIR_ALLOC(ret) < 0) {
1592
virReportOOMError();
1596
action = virXMLPropString(node, "action");
1597
direction = virXMLPropString(node, "direction");
1598
prio = virXMLPropString(node, "priority");
1599
statematch= virXMLPropString(node, "statematch");
1602
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1604
_("rule node requires action attribute"));
1608
if ((ret->action = virNWFilterRuleActionTypeFromString(action)) < 0) {
1609
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1611
_("unknown rule action attribute value"));
1616
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1618
_("rule node requires direction attribute"));
1622
if ((ret->tt = virNWFilterRuleDirectionTypeFromString(direction)) < 0) {
1623
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1625
_("unknown rule direction attribute value"));
1629
ret->priority = MAX_RULE_PRIORITY / 2;
1632
if (virStrToLong_ui(prio, NULL, 10, &priority) >= 0) {
1633
if (priority <= MAX_RULE_PRIORITY)
1634
ret->priority = priority;
1639
(STREQ(statematch, "0") || STRCASEEQ(statematch, "false")))
1640
ret->flags |= RULE_FLAG_NO_STATEMATCH;
1642
cur = node->children;
1646
while (cur != NULL) {
1647
if (cur->type == XML_ELEMENT_NODE) {
1653
if (xmlStrEqual(cur->name, BAD_CAST virAttr[i].id)) {
1657
ret->prtclType = virAttr[i].prtclType;
1659
if (virNWFilterRuleDetailsParse(cur,
1661
virAttr[i].att) < 0) {
1662
/* we ignore malformed rules
1680
virNWFilterRuleDefFixup(ret);
1685
VIR_FREE(direction);
1686
VIR_FREE(statematch);
1691
virNWFilterRuleDefFree(ret);
1697
static virNWFilterDefPtr
1698
virNWFilterDefParseXML(xmlXPathContextPtr ctxt) {
1699
virNWFilterDefPtr ret;
1700
xmlNodePtr curr = ctxt->node;
1703
virNWFilterEntryPtr entry;
1705
if (VIR_ALLOC(ret) < 0) {
1706
virReportOOMError();
1710
ret->name = virXPathString("string(./@name)", ctxt);
1712
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1713
"%s", _("filter has no name"));
1717
ret->chainsuffix = VIR_NWFILTER_CHAINSUFFIX_ROOT;
1718
chain = virXPathString("string(./@chain)", ctxt);
1720
if ((ret->chainsuffix =
1721
virNWFilterChainSuffixTypeFromString(chain)) < 0) {
1722
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1723
_("unknown chain suffix '%s'"), chain);
1728
uuid = virXPathString("string(./uuid)", ctxt);
1730
if (virUUIDGenerate(ret->uuid) < 0) {
1731
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
1732
"%s", _("unable to generate uuid"));
1736
if (virUUIDParse(uuid, ret->uuid) < 0) {
1737
virNWFilterReportError(VIR_ERR_XML_ERROR,
1738
"%s", _("malformed uuid element"));
1744
curr = curr->children;
1746
while (curr != NULL) {
1747
if (curr->type == XML_ELEMENT_NODE) {
1748
if (VIR_ALLOC(entry) < 0) {
1749
virReportOOMError();
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);
1759
if (entry->rule || entry->include) {
1760
if (VIR_REALLOC_N(ret->filterEntries, ret->nentries+1) < 0) {
1762
virReportOOMError();
1765
ret->filterEntries[ret->nentries++] = entry;
1777
virNWFilterDefFree(ret);
1784
/* Called from SAX on parsing errors in the XML. */
1786
catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
1788
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1791
virConnectPtr conn = ctxt->_private;
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);
1807
virNWFilterDefParseNode(xmlDocPtr xml,
1809
xmlXPathContextPtr ctxt = NULL;
1810
virNWFilterDefPtr def = NULL;
1812
if (STRNEQ((const char *)root->name, "filter")) {
1813
virNWFilterReportError(VIR_ERR_XML_ERROR,
1815
_("unknown root element for nw filter pool"));
1819
ctxt = xmlXPathNewContext(xml);
1821
virReportOOMError();
1826
def = virNWFilterDefParseXML(ctxt);
1829
xmlXPathFreeContext(ctxt);
1834
static virNWFilterDefPtr
1835
virNWFilterDefParse(virConnectPtr conn,
1837
const char *filename) {
1838
virNWFilterDefPtr ret = NULL;
1839
xmlParserCtxtPtr pctxt;
1840
xmlDocPtr xml = NULL;
1841
xmlNodePtr node = NULL;
1843
/* Set up a parser context so we can catch the details of XML errors. */
1844
pctxt = xmlNewParserCtxt ();
1845
if (!pctxt || !pctxt->sax)
1847
pctxt->sax->error = catchXMLError;
1848
pctxt->_private = conn;
1850
if (conn) virResetError (&conn->err);
1852
xml = xmlCtxtReadFile (pctxt, filename, NULL,
1853
XML_PARSE_NOENT | XML_PARSE_NONET |
1854
XML_PARSE_NOWARNING);
1856
xml = xmlCtxtReadDoc (pctxt, BAD_CAST xmlStr,
1857
"nwfilter.xml", NULL,
1858
XML_PARSE_NOENT | XML_PARSE_NONET |
1859
XML_PARSE_NOWARNING);
1863
if (conn && conn->err.code == VIR_ERR_NONE)
1864
virNWFilterReportError(VIR_ERR_XML_ERROR,
1865
"%s",_("failed to parse xml document"));
1869
node = xmlDocGetRootElement(xml);
1871
virNWFilterReportError(VIR_ERR_XML_ERROR,
1872
"%s", _("missing root element"));
1876
ret = virNWFilterDefParseNode(xml, node);
1878
xmlFreeParserCtxt (pctxt);
1884
xmlFreeParserCtxt (pctxt);
1891
virNWFilterDefParseString(virConnectPtr conn,
1894
return virNWFilterDefParse(conn, xmlStr, NULL);
1899
virNWFilterDefParseFile(virConnectPtr conn,
1900
const char *filename)
1902
return virNWFilterDefParse(conn, NULL, filename);
1906
virNWFilterPoolObjPtr
1907
virNWFilterPoolObjFindByUUID(virNWFilterPoolObjListPtr pools,
1908
const unsigned char *uuid)
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]);
1923
virNWFilterPoolObjPtr
1924
virNWFilterPoolObjFindByName(virNWFilterPoolObjListPtr pools,
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]);
1940
int virNWFilterSaveXML(const char *configDir,
1941
virNWFilterDefPtr def,
1944
char *configFile = NULL;
1945
int fd = -1, ret = -1;
1949
if ((configFile = virNWFilterConfigFile(configDir, def->name)) == NULL)
1952
if ((err = virFileMakePath(configDir))) {
1953
virReportSystemError(err,
1954
_("cannot create config directory '%s'"),
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'"),
1968
towrite = strlen(xml);
1969
if (safewrite(fd, xml, towrite) < 0) {
1970
virReportSystemError(errno,
1971
_("cannot write config file '%s'"),
1976
if (close(fd) < 0) {
1977
virReportSystemError(errno,
1978
_("cannot save config file '%s'"),
1989
VIR_FREE(configFile);
1995
int virNWFilterSaveConfig(const char *configDir,
1996
virNWFilterDefPtr def)
2001
if (!(xml = virNWFilterDefFormat(def)))
2004
if (virNWFilterSaveXML(configDir, def, xml))
2015
_virNWFilterDefLoopDetect(virConnectPtr conn,
2016
virNWFilterPoolObjListPtr pools,
2017
virNWFilterDefPtr def,
2018
const char *filtername)
2022
virNWFilterEntryPtr entry;
2023
virNWFilterPoolObjPtr obj;
2028
for (i = 0; i < def->nentries; i++) {
2029
entry = def->filterEntries[i];
2030
if (entry->include) {
2032
if (STREQ(filtername, entry->include->filterref)) {
2037
obj = virNWFilterPoolObjFindByName(pools,
2038
entry->include->filterref);
2040
rc = _virNWFilterDefLoopDetect(conn,
2042
obj->def, filtername);
2044
virNWFilterPoolObjUnlock(obj);
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
2061
* Detect a loop introduced through the filters being able to
2062
* reference each other.
2064
* Returns 0 in case no loop was detected, 1 otherwise.
2067
virNWFilterDefLoopDetect(virConnectPtr conn,
2068
virNWFilterPoolObjListPtr pools,
2069
virNWFilterDefPtr def)
2071
return _virNWFilterDefLoopDetect(conn, pools, def, def->name);
2074
int nCallbackDriver;
2075
#define MAX_CALLBACK_DRIVER 10
2076
static virNWFilterCallbackDriverPtr callbackDrvArray[MAX_CALLBACK_DRIVER];
2079
virNWFilterRegisterCallbackDriver(virNWFilterCallbackDriverPtr cbd)
2081
if (nCallbackDriver < MAX_CALLBACK_DRIVER) {
2082
callbackDrvArray[nCallbackDriver++] = cbd;
2087
static virHashIterator virNWFilterDomainFWUpdateCB;
2091
virNWFilterTriggerVMFilterRebuild(virConnectPtr conn)
2095
struct domUpdateCBStruct cb = {
2098
.step = STEP_APPLY_NEW,
2099
.skipInterfaces = virHashCreate(0),
2102
if (!cb.skipInterfaces) {
2103
virReportOOMError();
2107
for (i = 0; i < nCallbackDriver; i++) {
2108
callbackDrvArray[i]->vmFilterRebuild(conn,
2109
virNWFilterDomainFWUpdateCB,
2116
cb.step = STEP_TEAR_NEW; // rollback
2119
for (i = 0; i < nCallbackDriver; i++)
2120
callbackDrvArray[i]->vmFilterRebuild(conn,
2121
virNWFilterDomainFWUpdateCB,
2124
cb.step = STEP_TEAR_OLD; // switch over
2126
for (i = 0; i < nCallbackDriver; i++)
2127
callbackDrvArray[i]->vmFilterRebuild(conn,
2128
virNWFilterDomainFWUpdateCB,
2132
virHashFree(cb.skipInterfaces, NULL);
2139
virNWFilterTestUnassignDef(virConnectPtr conn,
2140
virNWFilterPoolObjPtr pool)
2144
virNWFilterLockFilterUpdates();
2146
pool->wantRemoved = 1;
2147
// trigger the update on VMs referencing the filter
2148
if (virNWFilterTriggerVMFilterRebuild(conn))
2151
pool->wantRemoved = 0;
2152
virNWFilterUnlockFilterUpdates();
2157
virNWFilterPoolObjPtr
2158
virNWFilterPoolObjAssignDef(virConnectPtr conn,
2159
virNWFilterPoolObjListPtr pools,
2160
virNWFilterDefPtr def)
2162
virNWFilterPoolObjPtr pool;
2164
if (virNWFilterDefLoopDetect(conn, pools, def)) {
2165
virNWFilterReportError(VIR_ERR_INVALID_NWFILTER,
2166
"%s", _("filter would introduce a loop"));
2170
if ((pool = virNWFilterPoolObjFindByName(pools, def->name))) {
2171
virNWFilterLockFilterUpdates();
2173
// trigger the update on VMs referencing the filter
2174
if (virNWFilterTriggerVMFilterRebuild(conn)) {
2175
pool->newDef = NULL;
2176
virNWFilterUnlockFilterUpdates();
2177
virNWFilterPoolObjUnlock(pool);
2181
virNWFilterDefFree(pool->def);
2183
pool->newDef = NULL;
2184
virNWFilterUnlockFilterUpdates();
2188
if (VIR_ALLOC(pool) < 0) {
2189
virReportOOMError();
2193
if (virMutexInitRecursive(&pool->lock) < 0) {
2194
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
2195
"%s", _("cannot initialize mutex"));
2199
virNWFilterPoolObjLock(pool);
2203
if (VIR_REALLOC_N(pools->objs, pools->count+1) < 0) {
2205
virNWFilterPoolObjUnlock(pool);
2206
virNWFilterPoolObjFree(pool);
2207
virReportOOMError();
2210
pools->objs[pools->count++] = pool;
2216
static virNWFilterPoolObjPtr
2217
virNWFilterPoolObjLoad(virConnectPtr conn,
2218
virNWFilterPoolObjListPtr pools,
2222
virNWFilterDefPtr def;
2223
virNWFilterPoolObjPtr pool;
2225
if (!(def = virNWFilterDefParseFile(conn, path))) {
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'"),
2233
virNWFilterDefFree(def);
2237
if (!(pool = virNWFilterPoolObjAssignDef(conn, pools, def))) {
2238
virNWFilterDefFree(def);
2242
pool->configFile = strdup(path);
2243
if (pool->configFile == NULL) {
2244
virReportOOMError();
2245
virNWFilterDefFree(def);
2254
virNWFilterPoolLoadAllConfigs(virConnectPtr conn,
2255
virNWFilterPoolObjListPtr pools,
2256
const char *configDir)
2259
struct dirent *entry;
2261
if (!(dir = opendir(configDir))) {
2262
if (errno == ENOENT) {
2265
virReportSystemError(errno, _("Failed to open dir '%s'"),
2270
while ((entry = readdir(dir))) {
2271
char path[PATH_MAX];
2272
virNWFilterPoolObjPtr pool;
2274
if (entry->d_name[0] == '.')
2277
if (!virFileHasSuffix(entry->d_name, ".xml"))
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);
2288
pool = virNWFilterPoolObjLoad(conn, pools, entry->d_name, path);
2290
virNWFilterPoolObjUnlock(pool);
2300
virNWFilterPoolObjSaveDef(virNWFilterDriverStatePtr driver,
2301
virNWFilterPoolObjPtr pool,
2302
virNWFilterDefPtr def)
2305
int fd = -1, ret = -1;
2308
if (!pool->configFile) {
2310
char path[PATH_MAX];
2312
if ((err = virFileMakePath(driver->configDir))) {
2313
virReportSystemError(err,
2314
_("cannot create config directory %s"),
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"));
2325
if (!(pool->configFile = strdup(path))) {
2326
virReportOOMError();
2331
if (!(xml = virNWFilterDefFormat(def))) {
2332
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
2333
"%s", _("failed to generate XML"));
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"),
2346
towrite = strlen(xml);
2347
if (safewrite(fd, xml, towrite) != towrite) {
2348
virReportSystemError(errno,
2349
_("cannot write config file %s"),
2354
if (close(fd) < 0) {
2355
virReportSystemError(errno,
2356
_("cannot save config file %s"),
2374
virNWFilterPoolObjDeleteDef(virNWFilterPoolObjPtr pool)
2376
if (!pool->configFile) {
2377
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
2378
_("no config file for %s"), pool->def->name);
2382
if (unlink(pool->configFile) < 0) {
2383
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
2384
_("cannot remove config for %s"),
2394
virNWIPAddressFormat(virBufferPtr buf, nwIPAddressPtr ipaddr)
2396
virSocketAddrPtr addr = &ipaddr->addr;
2397
char *output = virSocketFormatAddr(addr);
2400
virBufferVSprintf(buf, "%s", output);
2407
virNWFilterRuleDefDetailsFormat(virBufferPtr buf,
2409
const virXMLAttr2Struct *att,
2410
virNWFilterRuleDefPtr def)
2414
bool neverShown = 1;
2420
} matchShown = MATCH_NONE;
2423
while (att[i].name) {
2424
item = (nwItemDesc *)((char *)def + att[i].dataIdx);
2425
enum virNWFilterEntryItemFlags flags = item->flags;
2427
if ((flags & NWFILTER_ENTRY_ITEM_FLAG_EXISTS)) {
2429
virBufferVSprintf(buf, " <%s", type);
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");
2441
matchShown = MATCH_NONE;
2445
if (matchShown == MATCH_NO) {
2446
virBufferAddLit(buf, "/>\n");
2448
matchShown = MATCH_NONE;
2451
matchShown = MATCH_YES;
2454
virBufferVSprintf(buf, " %s='",
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"),
2464
} else if ((flags & NWFILTER_ENTRY_ITEM_FLAG_HAS_VAR)) {
2465
virBufferVSprintf(buf, "$%s", item->var);
2469
switch (item->datatype) {
2471
case DATATYPE_UINT8_HEX:
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);
2482
case DATATYPE_UINT16_HEX:
2484
case DATATYPE_UINT16:
2485
storage_ptr = &item->u.u16;
2486
virBufferVSprintf(buf, asHex ? "0x%x" : "%d",
2487
*(uint16_t *)storage_ptr);
2490
case DATATYPE_IPADDR:
2491
case DATATYPE_IPV6ADDR:
2492
storage_ptr = &item->u.ipaddr;
2493
virNWIPAddressFormat(buf,
2494
(nwIPAddressPtr)storage_ptr);
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) ? ":" : "");
2506
case DATATYPE_STRING:
2508
virBufferVSprintf(buf,
2509
"UNSUPPORTED DATATYPE 0x%02x\n",
2513
virBufferAddLit(buf, "'");
2518
virBufferAddLit(buf, "/>\n");
2521
virBufferVSprintf(buf,
2530
virNWFilterRuleDefFormat(virNWFilterRuleDefPtr def)
2533
virBuffer buf = VIR_BUFFER_INITIALIZER;
2534
virBuffer buf2 = VIR_BUFFER_INITIALIZER;
2537
virBufferVSprintf(&buf, " <rule action='%s' direction='%s' priority='%d'",
2538
virNWFilterRuleActionTypeToString(def->action),
2539
virNWFilterRuleDirectionTypeToString(def->tt),
2542
if ((def->flags & RULE_FLAG_NO_STATEMATCH))
2543
virBufferAddLit(&buf, " statematch='false'");
2546
while (virAttr[i].id) {
2547
if (virAttr[i].prtclType == def->prtclType) {
2548
virNWFilterRuleDefDetailsFormat(&buf2,
2557
if (virBufferError(&buf2))
2560
data = virBufferContentAndReset(&buf2);
2563
virBufferAddLit(&buf, ">\n");
2564
virBufferVSprintf(&buf, "%s </rule>\n", data);
2567
virBufferAddLit(&buf, "/>\n");
2569
if (virBufferError(&buf))
2572
return virBufferContentAndReset(&buf);
2575
virReportOOMError();
2576
virBufferFreeAndReset(&buf);
2577
virBufferFreeAndReset(&buf2);
2584
virNWFilterIncludeDefFormat(virNWFilterIncludeDefPtr inc)
2587
virBuffer buf = VIR_BUFFER_INITIALIZER;
2589
virBufferVSprintf(&buf," <filterref filter='%s'",
2592
attrs = virNWFilterFormatParamAttributes(inc->params, " ");
2594
if (!attrs || strlen(attrs) <= 1)
2595
virBufferAddLit(&buf, "/>\n");
2597
virBufferVSprintf(&buf, ">\n%s </filterref>\n", attrs);
2599
if (virBufferError(&buf)) {
2600
virReportOOMError();
2601
virBufferFreeAndReset(&buf);
2605
return virBufferContentAndReset(&buf);
2610
virNWFilterEntryFormat(virNWFilterEntryPtr entry)
2613
return virNWFilterRuleDefFormat(entry->rule);
2614
return virNWFilterIncludeDefFormat(entry->include);
2619
virNWFilterDefFormat(virNWFilterDefPtr def)
2621
virBuffer buf = VIR_BUFFER_INITIALIZER;
2622
char uuid[VIR_UUID_STRING_BUFLEN];
2626
virBufferVSprintf(&buf, "<filter name='%s' chain='%s'",
2628
virNWFilterChainSuffixTypeToString(def->chainsuffix));
2629
virBufferAddLit(&buf, ">\n");
2631
virUUIDFormat(def->uuid, uuid);
2632
virBufferVSprintf(&buf," <uuid>%s</uuid>\n", uuid);
2634
for (i = 0; i < def->nentries; i++) {
2635
xml = virNWFilterEntryFormat(def->filterEntries[i]);
2638
virBufferVSprintf(&buf, "%s", xml);
2642
virBufferAddLit(&buf, "</filter>\n");
2644
if (virBufferError(&buf))
2647
return virBufferContentAndReset(&buf);
2650
virReportOOMError();
2653
virBufferFreeAndReset(&buf);
2658
char *virNWFilterConfigFile(const char *dir,
2663
if (virAsprintf(&ret, "%s/%s.xml", dir, name) < 0) {
2664
virReportOOMError();
2672
int virNWFilterConfLayerInit(virHashIterator domUpdateCB)
2674
virNWFilterDomainFWUpdateCB = domUpdateCB;
2676
if (virMutexInitRecursive(&updateMutex))
2683
void virNWFilterConfLayerShutdown(void)
2685
virMutexDestroy(&updateMutex);
2689
void virNWFilterPoolObjLock(virNWFilterPoolObjPtr obj)
2691
virMutexLock(&obj->lock);
2694
void virNWFilterPoolObjUnlock(virNWFilterPoolObjPtr obj)
2696
virMutexUnlock(&obj->lock);