Add XML parser extensions for network filtering

This patch adds XML processing for the network filter schema
and extends the domain XML processing to parse the top level
referenced filter along with potentially provided parameters

Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
Signed-off-by: Gerhard Stenzel <gerhard.stenzel@de.ibm.com>
This commit is contained in:
Stefan Berger 2010-03-25 13:46:07 -04:00 committed by Daniel P. Berrange
parent 929560384d
commit e4e20423ff
8 changed files with 3104 additions and 1 deletions

View File

@ -8,6 +8,8 @@ src/conf/domain_event.c
src/conf/interface_conf.c
src/conf/network_conf.c
src/conf/node_device_conf.c
src/conf/nwfilter_conf.c
src/conf/nwfilter_params.c
src/conf/secret_conf.c
src/conf/storage_conf.c
src/conf/storage_encryption_conf.c

View File

@ -97,9 +97,17 @@ DOMAIN_EVENT_SOURCES = \
conf/domain_event.c conf/domain_event.h
# Network driver generic impl APIs
NETWORK_CONF_SOURCES = \
NETWORK_CONF_SOURCES = \
conf/network_conf.c conf/network_conf.h
# Network filter driver generic impl APIs
NWFILTER_PARAM_CONF_SOURCES = \
conf/nwfilter_params.c conf/nwfilter_conf.h
NWFILTER_CONF_SOURCES = \
$(NWFILTER_PARAM_CONF_SOURCES) \
conf/nwfilter_conf.c conf/nwfilter_conf.h
# Storage driver generic impl APIs
STORAGE_CONF_SOURCES = \
conf/storage_conf.h conf/storage_conf.c
@ -126,6 +134,7 @@ CONF_SOURCES = \
$(DOMAIN_CONF_SOURCES) \
$(DOMAIN_EVENT_SOURCES) \
$(NETWORK_CONF_SOURCES) \
$(NWFILTER_CONF_SOURCES) \
$(NODE_DEVICE_CONF_SOURCES) \
$(STORAGE_CONF_SOURCES) \
$(ENCRYPTION_CONF_SOURCES) \
@ -761,6 +770,7 @@ EXTRA_DIST += \
$(NODE_DEVICE_DRIVER_SOURCES) \
$(NODE_DEVICE_DRIVER_HAL_SOURCES) \
$(NODE_DEVICE_DRIVER_UDEV_SOURCES) \
$(NWFILTER_DRIVER_SOURCES) \
$(SECURITY_DRIVER_SELINUX_SOURCES) \
$(SECURITY_DRIVER_APPARMOR_SOURCES) \
$(SECRET_DRIVER_SOURCES) \
@ -903,6 +913,7 @@ libvirt_lxc_SOURCES = \
$(NODE_INFO_SOURCES) \
$(ENCRYPTION_CONF_SOURCES) \
$(DOMAIN_CONF_SOURCES) \
$(NWFILTER_PARAM_CONF_SOURCES) \
$(CPU_CONF_SOURCES)
libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(COVERAGE_LDCFLAGS) $(CAPNG_LIBS) $(YAJL_LIBS)
libvirt_lxc_LDADD = $(LIBXML_LIBS) $(NUMACTL_LIBS) ../gnulib/lib/libgnu.la

View File

@ -42,6 +42,7 @@
#include "logging.h"
#include "network.h"
#include "macvtap.h"
#include "nwfilter_conf.h"
#define VIR_FROM_THIS VIR_FROM_DOMAIN
@ -461,6 +462,9 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
virDomainDeviceInfoClear(&def->info);
VIR_FREE(def->filter);
virNWFilterHashTableFree(def->filterparams);
VIR_FREE(def);
}
@ -1736,9 +1740,11 @@ virDomainNetDefParseXML(virCapsPtr caps,
char *address = NULL;
char *port = NULL;
char *model = NULL;
char *filter = NULL;
char *internal = NULL;
char *devaddr = NULL;
char *mode = NULL;
virNWFilterHashTablePtr filterparams = NULL;
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
@ -1807,6 +1813,9 @@ virDomainNetDefParseXML(virCapsPtr caps,
script = virXMLPropString(cur, "path");
} else if (xmlStrEqual (cur->name, BAD_CAST "model")) {
model = virXMLPropString(cur, "type");
} else if (xmlStrEqual (cur->name, BAD_CAST "filterref")) {
filter = virXMLPropString(cur, "filter");
filterparams = virNWFilterParseParamAttributes(cur);
} else if ((flags & VIR_DOMAIN_XML_INTERNAL_STATUS) &&
xmlStrEqual(cur->name, BAD_CAST "state")) {
/* Legacy back-compat. Don't add any more attributes here */
@ -1986,6 +1995,22 @@ virDomainNetDefParseXML(virCapsPtr caps,
model = NULL;
}
if (filter != NULL) {
switch (def->type) {
case VIR_DOMAIN_NET_TYPE_ETHERNET:
case VIR_DOMAIN_NET_TYPE_NETWORK:
case VIR_DOMAIN_NET_TYPE_BRIDGE:
case VIR_DOMAIN_NET_TYPE_DIRECT:
def->filter = filter;
filter = NULL;
def->filterparams = filterparams;
filterparams = NULL;
break;
default:
break;
}
}
cleanup:
VIR_FREE(macaddr);
VIR_FREE(network);
@ -1996,10 +2021,12 @@ cleanup:
VIR_FREE(script);
VIR_FREE(bridge);
VIR_FREE(model);
VIR_FREE(filter);
VIR_FREE(type);
VIR_FREE(internal);
VIR_FREE(devaddr);
VIR_FREE(mode);
virNWFilterHashTableFree(filterparams);
return def;
@ -4810,6 +4837,7 @@ virDomainNetDefFormat(virBufferPtr buf,
int flags)
{
const char *type = virDomainNetTypeToString(def->type);
char *attrs;
if (!type) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
@ -4888,6 +4916,17 @@ virDomainNetDefFormat(virBufferPtr buf,
if (def->model)
virBufferEscapeString(buf, " <model type='%s'/>\n",
def->model);
if (def->filter) {
virBufferEscapeString(buf, " <filterref filter='%s'",
def->filter);
attrs = virNWFilterFormatParamAttributes(def->filterparams,
" ");
if (!attrs || strlen(attrs) <= 1)
virBufferAddLit(buf, "/>\n");
else
virBufferVSprintf(buf, ">\n%s </filterref>\n", attrs);
VIR_FREE(attrs);
}
if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0)
return -1;

View File

@ -36,6 +36,8 @@
# include "threads.h"
# include "hash.h"
# include "network.h"
# include "nwfilter_params.h"
# include "nwfilter_conf.h"
/* Private component of virDomainXMLFlags */
typedef enum {
@ -282,6 +284,8 @@ struct _virDomainNetDef {
} data;
char *ifname;
virDomainDeviceInfo info;
char *filter;
virNWFilterHashTablePtr filterparams;
};
enum virDomainChrTargetType {

2211
src/conf/nwfilter_conf.c Normal file

File diff suppressed because it is too large Load Diff

465
src/conf/nwfilter_conf.h Normal file
View File

@ -0,0 +1,465 @@
/*
* nwfilter_conf.h: network filter XML processing
* (derived from storage_conf.h)
*
* Copyright (C) 2006-2010 Red Hat, Inc.
* Copyright (C) 2006-2008 Daniel P. Berrange
*
* Copyright (C) 2010 IBM Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Stefan Berger <stefanb@us.ibm.com>
*/
#ifndef NWFILTER_CONF_H
#define NWFILTER_CONF_H
#include <stdint.h>
#include <stddef.h>
#include "internal.h"
#include "util.h"
#include "hash.h"
#include "xml.h"
/**
* Chain suffix size is:
* max. user define table name length -
* sizeof("FO-") -
* max. interface name size -
* sizeof("-") -
* terminating '0' =
* 32-3-15-1-1 = 12
*/
#define MAX_CHAIN_SUFFIX_SIZE 12
enum virNWFilterEntryItemFlags {
NWFILTER_ENTRY_ITEM_FLAG_EXISTS = 1 << 0,
NWFILTER_ENTRY_ITEM_FLAG_IS_NEG = 1 << 1,
NWFILTER_ENTRY_ITEM_FLAG_HAS_VAR = 1 << 2,
};
#define HAS_ENTRY_ITEM(data) \
(((data)->flags) & NWFILTER_ENTRY_ITEM_FLAG_EXISTS)
#define ENTRY_GET_NEG_SIGN(data) \
((((data)->flags) & NWFILTER_ENTRY_ITEM_FLAG_IS_NEG) ? "!" : "")
// datatypes appearing in rule attributes
enum attrDatatype {
DATATYPE_UINT16 = (1 << 0),
DATATYPE_UINT8 = (1 << 1),
DATATYPE_MACADDR = (1 << 2),
DATATYPE_MACMASK = (1 << 3),
DATATYPE_IPADDR = (1 << 4),
DATATYPE_IPMASK = (1 << 5),
DATATYPE_STRING = (1 << 6),
DATATYPE_LAST = (1 << 7),
};
typedef struct _nwMACAddress nwMACAddress;
typedef nwMACAddress *nwMACAddressPtr;
struct _nwMACAddress {
unsigned char addr[6];
};
typedef struct _nwIPAddress nwIPAddress;
typedef nwIPAddress *nwIPAddressPtr;
struct _nwIPAddress {
int isIPv6;
union {
unsigned char ipv4Addr[4];
/* unsigned char ipv6Addr[16]; future :-) */
} addr;
};
typedef struct _nwItemDesc nwItemDesc;
typedef nwItemDesc *nwItemDescPtr;
struct _nwItemDesc {
enum virNWFilterEntryItemFlags flags;
char *var;
enum attrDatatype datatype;
union {
nwMACAddress macaddr;
nwIPAddress ipaddr;
uint8_t u8;
uint16_t u16;
char protocolID[10];
} u;
};
typedef struct _ethHdrDataDef ethHdrDataDef;
typedef ethHdrDataDef *ethHdrDataDefPtr;
struct _ethHdrDataDef {
nwItemDesc dataSrcMACAddr;
nwItemDesc dataSrcMACMask;
nwItemDesc dataDstMACAddr;
nwItemDesc dataDstMACMask;
};
typedef struct _ethHdrFilterDef ethHdrFilterDef;
typedef ethHdrFilterDef *ethHdrFilterDefPtr;
struct _ethHdrFilterDef {
ethHdrDataDef ethHdr;
nwItemDesc dataProtocolID;
};
typedef struct _arpHdrFilterDef arpHdrFilterDef;
typedef arpHdrFilterDef *arpHdrFilterDefPtr;
struct _arpHdrFilterDef {
ethHdrDataDef ethHdr;
nwItemDesc dataHWType;
nwItemDesc dataProtocolType;
nwItemDesc dataOpcode;
nwItemDesc dataARPSrcMACAddr;
nwItemDesc dataARPSrcIPAddr;
nwItemDesc dataARPDstMACAddr;
nwItemDesc dataARPDstIPAddr;
};
typedef struct _ipHdrDataDef ipHdrDataDef;
typedef ipHdrDataDef *ipHdrDataDefPtr;
struct _ipHdrDataDef {
nwItemDesc dataIPVersion;
nwItemDesc dataSrcIPAddr;
nwItemDesc dataSrcIPMask;
nwItemDesc dataDstIPAddr;
nwItemDesc dataDstIPMask;
nwItemDesc dataProtocolID;
nwItemDesc dataDSCP;
};
typedef struct _portDataDef portDataDef;
typedef portDataDef *portDataDefPtr;
struct _portDataDef {
nwItemDesc dataSrcPortStart;
nwItemDesc dataSrcPortEnd;
nwItemDesc dataDstPortStart;
nwItemDesc dataDstPortEnd;
};
typedef struct _ipHdrFilterDef ipHdrFilterDef;
typedef ipHdrFilterDef *ipHdrFilterDefPtr;
struct _ipHdrFilterDef {
ethHdrDataDef ethHdr;
ipHdrDataDef ipHdr;
portDataDef portData;
};
enum virNWFilterRuleActionType {
VIR_NWFILTER_RULE_ACTION_DROP = 0,
VIR_NWFILTER_RULE_ACTION_ACCEPT,
VIR_NWFILTER_RULE_ACTION_LAST,
};
enum virNWFilterRuleDirectionType {
VIR_NWFILTER_RULE_DIRECTION_IN = 0,
VIR_NWFILTER_RULE_DIRECTION_OUT,
VIR_NWFILTER_RULE_DIRECTION_INOUT,
VIR_NWFILTER_RULE_DIRECTION_LAST,
};
enum virNWFilterChainPolicyType {
VIR_NWFILTER_CHAIN_POLICY_ACCEPT = 0,
VIR_NWFILTER_CHAIN_POLICY_DROP,
VIR_NWFILTER_CHAIN_POLICY_LAST,
};
enum virNWFilterRuleProtocolType {
VIR_NWFILTER_RULE_PROTOCOL_NONE = 0,
VIR_NWFILTER_RULE_PROTOCOL_MAC,
VIR_NWFILTER_RULE_PROTOCOL_ARP,
VIR_NWFILTER_RULE_PROTOCOL_IP,
};
enum virNWFilterEbtablesTableType {
VIR_NWFILTER_EBTABLES_TABLE_FILTER = 0,
VIR_NWFILTER_EBTABLES_TABLE_NAT,
VIR_NWFILTER_EBTABLES_TABLE_BROUTE,
VIR_NWFILTER_EBTABLES_TABLE_LAST,
};
#define MAX_RULE_PRIORITY 1000
typedef struct _virNWFilterRuleDef virNWFilterRuleDef;
typedef virNWFilterRuleDef *virNWFilterRuleDefPtr;
struct _virNWFilterRuleDef {
unsigned int priority;
int action; /*enum virNWFilterRuleActionType*/
int tt; /*enum virNWFilterRuleDirectionType*/
enum virNWFilterRuleProtocolType prtclType;
union {
ethHdrFilterDef ethHdrFilter;
arpHdrFilterDef arpHdrFilter;
ipHdrFilterDef ipHdrFilter;
} p;
int nvars;
char **vars;
};
typedef struct _virNWFilterIncludeDef virNWFilterIncludeDef;
typedef virNWFilterIncludeDef *virNWFilterIncludeDefPtr;
struct _virNWFilterIncludeDef {
char *filterref;
virNWFilterHashTablePtr params;
};
typedef struct _virNWFilterEntry virNWFilterEntry;
typedef virNWFilterEntry *virNWFilterEntryPtr;
struct _virNWFilterEntry {
virNWFilterRuleDef *rule;
virNWFilterIncludeDef *include;
};
enum virNWFilterChainSuffixType {
VIR_NWFILTER_CHAINSUFFIX_ROOT = 0,
VIR_NWFILTER_CHAINSUFFIX_ARP,
VIR_NWFILTER_CHAINSUFFIX_IPv4,
VIR_NWFILTER_CHAINSUFFIX_LAST,
};
typedef struct _virNWFilterDef virNWFilterDef;
typedef virNWFilterDef *virNWFilterDefPtr;
struct _virNWFilterDef {
char *name;
unsigned char uuid[VIR_UUID_BUFLEN];
int chainsuffix; /*enum virNWFilterChainSuffixType */
int nentries;
virNWFilterEntryPtr *filterEntries;
};
typedef struct _virNWFilterPoolObj virNWFilterPoolObj;
typedef virNWFilterPoolObj *virNWFilterPoolObjPtr;
struct _virNWFilterPoolObj {
virMutex lock;
char *configFile;
int active;
int wantRemoved;
virNWFilterDefPtr def;
virNWFilterDefPtr newDef;
};
typedef struct _virNWFilterPoolObjList virNWFilterPoolObjList;
typedef virNWFilterPoolObjList *virNWFilterPoolObjListPtr;
struct _virNWFilterPoolObjList {
unsigned int count;
virNWFilterPoolObjPtr *objs;
};
typedef struct _virNWFilterDriverState virNWFilterDriverState;
typedef virNWFilterDriverState *virNWFilterDriverStatePtr;
struct _virNWFilterDriverState {
virMutex lock;
virNWFilterPoolObjList pools;
char *configDir;
};
typedef struct _virNWFilterTechDriver virNWFilterTechDriver;
typedef virNWFilterTechDriver *virNWFilterTechDriverPtr;
typedef struct _virNWFilterRuleInst virNWFilterRuleInst;
typedef virNWFilterRuleInst *virNWFilterRuleInstPtr;
struct _virNWFilterRuleInst {
int ndata;
void **data;
virNWFilterTechDriverPtr techdriver;
};
enum virDomainNetType;
typedef int (*virNWFilterRuleCreateInstance)(virConnectPtr conn,
enum virDomainNetType nettype,
virNWFilterDefPtr filter,
virNWFilterRuleDefPtr rule,
const char *ifname,
virNWFilterHashTablePtr vars,
virNWFilterRuleInstPtr res);
typedef int (*virNWFilterRuleApplyNewRules)(virConnectPtr conn,
const char *ifname,
int nruleInstances,
void **_inst);
typedef int (*virNWFilterRuleTeardownNewRules)(virConnectPtr conn,
const char *ifname);
typedef int (*virNWFilterRuleTeardownOldRules)(virConnectPtr conn,
const char *ifname);
typedef int (*virNWFilterRuleRemoveRules)(virConnectPtr conn,
const char *ifname,
int nruleInstances,
void **_inst);
typedef int (*virNWFilterRuleAllTeardown)(const char *ifname);
typedef int (*virNWFilterRuleFreeInstanceData)(void * _inst);
typedef int (*virNWFilterRuleDisplayInstanceData)(virConnectPtr conn,
void *_inst);
struct _virNWFilterTechDriver {
const char *name;
virNWFilterRuleCreateInstance createRuleInstance;
virNWFilterRuleApplyNewRules applyNewRules;
virNWFilterRuleTeardownNewRules tearNewRules;
virNWFilterRuleTeardownOldRules tearOldRules;
virNWFilterRuleRemoveRules removeRules;
virNWFilterRuleAllTeardown allTeardown;
virNWFilterRuleFreeInstanceData freeRuleInstance;
virNWFilterRuleDisplayInstanceData displayRuleInstance;
};
void virNWFilterRuleDefFree(virNWFilterRuleDefPtr def);
void virNWFilterDefFree(virNWFilterDefPtr def);
void virNWFilterPoolObjListFree(virNWFilterPoolObjListPtr pools);
void virNWFilterPoolObjRemove(virNWFilterPoolObjListPtr pools,
virNWFilterPoolObjPtr pool);
void virNWFilterPoolObjFree(virNWFilterPoolObjPtr obj);
virNWFilterPoolObjPtr
virNWFilterPoolObjFindByUUID(virNWFilterPoolObjListPtr pools,
const unsigned char *uuid);
virNWFilterPoolObjPtr
virNWFilterPoolObjFindByName(virNWFilterPoolObjListPtr pools,
const char *name);
int virNWFilterPoolObjSaveDef(virConnectPtr conn,
virNWFilterDriverStatePtr driver,
virNWFilterPoolObjPtr pool,
virNWFilterDefPtr def);
int virNWFilterPoolObjDeleteDef(virConnectPtr conn,
virNWFilterPoolObjPtr pool);
virNWFilterPoolObjPtr virNWFilterPoolObjAssignDef(virConnectPtr conn,
virNWFilterPoolObjListPtr pools,
virNWFilterDefPtr def);
int virNWFilterTestUnassignDef(virConnectPtr conn,
virNWFilterPoolObjPtr pool);
virNWFilterDefPtr virNWFilterDefParseNode(virConnectPtr conn,
xmlDocPtr xml,
xmlNodePtr root);
char *virNWFilterDefFormat(virConnectPtr conn,
virNWFilterDefPtr def);
int virNWFilterSaveXML(virConnectPtr conn,
const char *configDir,
virNWFilterDefPtr def,
const char *xml);
int virNWFilterSaveConfig(virConnectPtr conn,
const char *configDir,
virNWFilterDefPtr def);
int virNWFilterPoolLoadAllConfigs(virConnectPtr conn,
virNWFilterPoolObjListPtr pools,
const char *configDir);
char *virNWFilterConfigFile(virConnectPtr conn,
const char *dir,
const char *name);
virNWFilterDefPtr virNWFilterDefParseString(virConnectPtr conn,
const char *xml);
virNWFilterDefPtr virNWFilterDefParseFile(virConnectPtr conn,
const char *filename);
void virNWFilterPoolObjLock(virNWFilterPoolObjPtr obj);
void virNWFilterPoolObjUnlock(virNWFilterPoolObjPtr obj);
int virNWFilterConfLayerInit(void);
void virNWFilterConfLayerShutdown(void);
int virNWFilterParamConfLayerInit(void);
void virNWFilterParamConfLayerShutdown(void);
#define virNWFilterReportError(conn, code, fmt...) \
virReportErrorHelper(conn, VIR_FROM_NWFILTER, code, __FILE__, \
__FUNCTION__, __LINE__, fmt)
typedef int (*virNWFilterRebuild)(virConnectPtr conn,
virHashIterator, void *data);
typedef struct _virNWFilterCallbackDriver virNWFilterCallbackDriver;
typedef virNWFilterCallbackDriver *virNWFilterCallbackDriverPtr;
struct _virNWFilterCallbackDriver {
const char *name;
virNWFilterRebuild vmFilterRebuild;
};
void virNWFilterRegisterCallbackDriver(virNWFilterCallbackDriverPtr);
VIR_ENUM_DECL(virNWFilterRuleAction);
VIR_ENUM_DECL(virNWFilterRuleDirection);
VIR_ENUM_DECL(virNWFilterRuleProtocol);
VIR_ENUM_DECL(virNWFilterJumpTarget);
VIR_ENUM_DECL(virNWFilterChainPolicy);
VIR_ENUM_DECL(virNWFilterEbtablesTable);
VIR_ENUM_DECL(virNWFilterChainSuffix);
#endif /* NWFILTER_CONF_H */

318
src/conf/nwfilter_params.c Normal file
View File

@ -0,0 +1,318 @@
/*
* nwfilter_params.c: parsing and data maintenance of filter parameters
*
* Copyright (C) 2010 IBM Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Stefan Berger <stefanb@us.ibm.com>
*/
#include <config.h>
#include <regex.h>
#include "internal.h"
#include "memory.h"
#include "virterror_internal.h"
#include "datatypes.h"
#include "nwfilter_params.h"
#include "domain_conf.h"
#define VIR_FROM_THIS VIR_FROM_NWFILTER
/*
* regular expressions for parameter names and values
*/
static regex_t regex_nam;
static regex_t regex_val;
static void
hashDealloc(void *payload, const char *name ATTRIBUTE_UNUSED)
{
VIR_FREE(payload);
}
/**
* virNWFilterHashTablePut:
* @table: Pointer to a virNWFilterHashTable
* @name: name of the key to enter
* @val: The value associated with the key
* @freeName: Whether the name must be freed on table destruction
*
* Returns 0 on success, 1 on failure.
*
* Put an entry into the hashmap replacing and freeing an existing entry
* if one existed.
*/
int
virNWFilterHashTablePut(virNWFilterHashTablePtr table,
const char *name,
char *val,
int copyName)
{
if (!virHashLookup(table->hashTable, name)) {
if (copyName) {
name = strdup(name);
if (!name)
return 1;
if (VIR_REALLOC_N(table->names, table->nNames + 1) < 0) {
VIR_FREE(name);
return 1;
}
table->names[table->nNames++] = (char *)name;
}
if (virHashAddEntry(table->hashTable, name, val) != 0) {
if (copyName) {
VIR_FREE(name);
table->nNames--;
}
return 1;
}
} else {
if (virHashUpdateEntry(table->hashTable, name, val, hashDealloc) != 0) {
return 1;
}
}
return 0;
}
/**
* virNWFilterHashTableFree:
* @table: Pointer to virNWFilterHashTable
*
* Free a hashtable de-allocating memory for all its entries.
*
* All hash tables within the NWFilter driver must use this
* function to deallocate and free their content.
*/
void
virNWFilterHashTableFree(virNWFilterHashTablePtr table)
{
int i;
if (!table)
return;
virHashFree(table->hashTable, hashDealloc);
for (i = 0; i < table->nNames; i++)
VIR_FREE(table->names[i]);
VIR_FREE(table->names);
VIR_FREE(table);
}
virNWFilterHashTablePtr
virNWFilterHashTableCreate(int n) {
virNWFilterHashTablePtr ret;
if (VIR_ALLOC(ret) < 0) {
virReportOOMError();
return NULL;
}
ret->hashTable = virHashCreate(n);
if (!ret->hashTable) {
virReportOOMError();
VIR_FREE(ret);
return NULL;
}
return ret;
}
int
virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr ht,
const char *entry)
{
int i;
int rc = virHashRemoveEntry(ht->hashTable, entry, hashDealloc);
if (rc == 0) {
for (i = 0; i < ht->nNames; i++) {
if (STREQ(ht->names[i], entry)) {
VIR_FREE(ht->names[i]);
ht->names[i] = ht->names[--ht->nNames];
ht->names[ht->nNames] = NULL;
break;
}
}
}
return rc;
}
struct addToTableStruct {
virNWFilterHashTablePtr target;
int errOccurred;
virConnectPtr conn;
};
static void
addToTable(void *payload, const char *name, void *data)
{
struct addToTableStruct *atts = (struct addToTableStruct *)data;
char *val;
if (atts->errOccurred)
return;
val = strdup((char *)payload);
if (!val) {
virReportOOMError();
atts->errOccurred = 1;
return;
}
if (virNWFilterHashTablePut(atts->target, name, val, 1) != 0) {
virNWFilterReportError(atts->conn, VIR_ERR_INTERNAL_ERROR,
_("Could not put variable '%s' into hashmap"),
name);
atts->errOccurred = 1;
VIR_FREE(val);
}
}
int
virNWFilterHashTablePutAll(virConnectPtr conn,
virNWFilterHashTablePtr src,
virNWFilterHashTablePtr dest)
{
struct addToTableStruct atts = {
.target = dest,
.errOccurred = 0,
.conn = conn,
};
virHashForEach(src->hashTable, addToTable, &atts);
if (atts.errOccurred)
goto err_exit;
return 0;
err_exit:
return 1;
}
virNWFilterHashTablePtr
virNWFilterParseParamAttributes(xmlNodePtr cur)
{
char *nam, *val;
virNWFilterHashTablePtr table = virNWFilterHashTableCreate(0);
if (!table) {
virReportOOMError();
return NULL;
}
cur = cur->children;
while (cur != NULL) {
if (cur->type == XML_ELEMENT_NODE) {
if (xmlStrEqual(cur->name, BAD_CAST "parameter")) {
nam = virXMLPropString(cur, "name");
val = virXMLPropString(cur, "value");
if (nam != NULL && val != NULL) {
if (regexec(&regex_nam, nam, 0, NULL, 0) != 0)
goto skip_entry;
if (regexec(&regex_val, val, 0, NULL, 0) != 0)
goto skip_entry;
if (virNWFilterHashTablePut(table, nam, val, 1)) {
VIR_FREE(nam);
VIR_FREE(val);
virNWFilterHashTableFree(table);
return NULL;
}
val = NULL;
}
skip_entry:
VIR_FREE(nam);
VIR_FREE(val);
}
}
cur = cur->next;
}
return table;
}
struct formatterParam {
virBufferPtr buf;
const char *indent;
};
static void
_formatParameterAttrs(void *payload, const char *name, void *data)
{
struct formatterParam *fp = (struct formatterParam *)data;
virBufferVSprintf(fp->buf, "%s<parameter name='%s' value='%s'/>\n",
fp->indent,
name,
(char *)payload);
}
char *
virNWFilterFormatParamAttributes(virNWFilterHashTablePtr table,
const char *indent)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
struct formatterParam fp = {
.buf = &buf,
.indent = indent,
};
virHashForEach(table->hashTable, _formatParameterAttrs, &fp);
if (virBufferError(&buf)) {
virReportOOMError();
virBufferFreeAndReset(&buf);
return NULL;
}
return virBufferContentAndReset(&buf);
}
int virNWFilterParamConfLayerInit(void) {
if (regcomp(&regex_nam, "^[a-zA-Z0-9_]+$" ,
REG_NOSUB|REG_EXTENDED) != 0)
return 1;
if (regcomp(&regex_val, "^[a-zA-Z0-9_.:]+$",
REG_NOSUB|REG_EXTENDED) != 0) {
regfree(&regex_nam);
return 1;
}
return 0;
}
void virNWFilterParamConfLayerShutdown(void) {
regfree(&regex_nam);
regfree(&regex_val);
}

View File

@ -0,0 +1,53 @@
/*
* nwfilter_params.h: parsing and data maintenance of filter parameters
*
* Copyright (C) 2010 IBM Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Stefan Berger <stefanb@us.ibm.com>
*/
#ifndef NWFILTER_PARAMS_H
#define NWFILTER_PARAMS_H
#include "hash.h"
typedef struct _virNWFilterHashTable virNWFilterHashTable;
typedef virNWFilterHashTable *virNWFilterHashTablePtr;
struct _virNWFilterHashTable {
virHashTablePtr hashTable;
int nNames;
char **names;
};
virNWFilterHashTablePtr virNWFilterParseParamAttributes(xmlNodePtr cur);
char * virNWFilterFormatParamAttributes(virNWFilterHashTablePtr table,
const char *indent);
virNWFilterHashTablePtr virNWFilterHashTableCreate(int n);
void virNWFilterHashTableFree(virNWFilterHashTablePtr table);
int virNWFilterHashTablePut(virNWFilterHashTablePtr table,
const char *name,
char *val,
int freeName);
int virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr table,
const char *name);
int virNWFilterHashTablePutAll(virConnectPtr conn,
virNWFilterHashTablePtr src,
virNWFilterHashTablePtr dest);
#endif /* NWFILTER_PARAMS_H */