The patch below extends the XML parser and generator so that every l3 protocol now can have a state attribute. Signed-off-by: Stefan Berger --- src/conf/nwfilter_conf.c | 166 +++++++++++++++++++++++++++++++++++++++++++---- src/conf/nwfilter_conf.h | 21 +++++ src/libvirt_private.syms | 1 3 files changed, 175 insertions(+), 13 deletions(-) Index: libvirt-acl/src/conf/nwfilter_conf.c =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_conf.c +++ libvirt-acl/src/conf/nwfilter_conf.c @@ -44,6 +44,7 @@ #include "nwfilter_params.h" #include "nwfilter_conf.h" #include "domain_conf.h" +#include "c-ctype.h" #define VIR_FROM_THIS VIR_FROM_NWFILTER @@ -157,6 +158,7 @@ static const char srcportend_str[] = " static const char dstportstart_str[] = "dstportstart"; static const char dstportend_str[] = "dstportend"; static const char dscp_str[] = "dscp"; +static const char state_str[] = "state"; #define SRCMACADDR srcmacaddr_str #define SRCMACMASK srcmacmask_str @@ -179,6 +181,7 @@ static const char dscp_str[] = " #define DSTPORTSTART dstportstart_str #define DSTPORTEND dstportend_str #define DSCP dscp_str +#define STATE state_str /** @@ -414,9 +417,11 @@ union data { }; typedef bool (*valueValidator)(enum attrDatatype datatype, union data *valptr, - virNWFilterRuleDefPtr nwf); + virNWFilterRuleDefPtr nwf, + nwItemDesc *item); typedef bool (*valueFormatter)(virBufferPtr buf, - virNWFilterRuleDefPtr nwf); + virNWFilterRuleDefPtr nwf, + nwItemDesc *item); typedef struct _virXMLAttr2Struct virXMLAttr2Struct; struct _virXMLAttr2Struct @@ -441,7 +446,8 @@ static const struct int_map macProtoMap[ static bool checkMacProtocolID(enum attrDatatype datatype, union data *value, - virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED) + virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED, + nwItemDesc *item ATTRIBUTE_UNUSED) { int32_t res = -1; @@ -468,7 +474,8 @@ checkMacProtocolID(enum attrDatatype dat static bool macProtocolIDFormatter(virBufferPtr buf, - virNWFilterRuleDefPtr nwf) + virNWFilterRuleDefPtr nwf, + nwItemDesc *item ATTRIBUTE_UNUSED) { const char *str = NULL; bool asHex = true; @@ -519,7 +526,8 @@ checkValidMask(unsigned char *data, int static bool checkMACMask(enum attrDatatype datatype ATTRIBUTE_UNUSED, union data *macMask, - virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED) + virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED, + nwItemDesc *item ATTRIBUTE_UNUSED) { return checkValidMask(macMask->uc, 6); } @@ -545,7 +553,8 @@ static const struct int_map arpOpcodeMap static bool arpOpcodeValidator(enum attrDatatype datatype, union data *value, - virNWFilterRuleDefPtr nwf) + virNWFilterRuleDefPtr nwf, + nwItemDesc *item ATTRIBUTE_UNUSED) { int32_t res = -1; @@ -569,7 +578,8 @@ arpOpcodeValidator(enum attrDatatype dat static bool arpOpcodeFormatter(virBufferPtr buf, - virNWFilterRuleDefPtr nwf) + virNWFilterRuleDefPtr nwf, + nwItemDesc *item ATTRIBUTE_UNUSED) { const char *str = NULL; @@ -604,7 +614,8 @@ static const struct int_map ipProtoMap[] static bool checkIPProtocolID(enum attrDatatype datatype, union data *value, - virNWFilterRuleDefPtr nwf) + virNWFilterRuleDefPtr nwf, + nwItemDesc *item ATTRIBUTE_UNUSED) { int32_t res = -1; @@ -628,7 +639,8 @@ static bool checkIPProtocolID(enum attrD static bool formatIPProtocolID(virBufferPtr buf, - virNWFilterRuleDefPtr nwf) + virNWFilterRuleDefPtr nwf, + nwItemDesc *item ATTRIBUTE_UNUSED) { const char *str = NULL; bool asHex = true; @@ -649,7 +661,8 @@ formatIPProtocolID(virBufferPtr buf, static bool dscpValidator(enum attrDatatype datatype, union data *val, - virNWFilterRuleDefPtr nwf) + virNWFilterRuleDefPtr nwf, + nwItemDesc *item ATTRIBUTE_UNUSED) { uint8_t dscp = val->ui; if (dscp > 63) @@ -660,6 +673,128 @@ dscpValidator(enum attrDatatype datatype return 1; } + +static const struct int_map stateMatchMap[] = { + INTMAP_ENTRY(RULE_FLAG_STATE_NEW , "NEW"), + INTMAP_ENTRY(RULE_FLAG_STATE_ESTABLISHED , "ESTABLISHED"), + INTMAP_ENTRY(RULE_FLAG_STATE_RELATED , "RELATED"), + INTMAP_ENTRY(RULE_FLAG_STATE_INVALID , "INVALID"), + INTMAP_ENTRY(RULE_FLAG_STATE_NONE , "NONE"), + INTMAP_ENTRY_LAST, +}; + + +static int +parseStringItems(const struct int_map *int_map, + const char *input, int32_t *flags, char sep) +{ + int rc = 0; + unsigned int i, j; + bool found; + + i = 0; + while (input[i]) { + found = false; + while (c_isspace(input[i]) || input[i] == sep) + i++; + if (!input[i]) + break; + for (j = 0; int_map[j].val; j++) { + if (STRCASEEQLEN(&input[i], int_map[j].val, + strlen(int_map[j].val))) { + *flags |= int_map[j].attr; + i += strlen(int_map[j].val); + found = true; + break; + } + } + if (!found) { + rc = 1; + break; + } + } + return rc; +} + + +static int +printStringItems(virBufferPtr buf, const struct int_map *int_map, + int32_t flags, const char *sep) +{ + unsigned int i, c = 0; + int32_t last_attr = 0; + + for (i = 0; int_map[i].val; i++) { + if (last_attr != int_map[i].attr && + flags & int_map[i].attr) { + if (c >= 1) + virBufferVSprintf(buf, "%s", sep); + virBufferVSprintf(buf, "%s", int_map[i].val); + c++; + } + last_attr = int_map[i].attr; + } + + return 0; +} + + +static int +parseStateMatch(const char *statematch, int32_t *flags) +{ + int rc = parseStringItems(stateMatchMap, statematch, flags, ','); + + if ((*flags & RULE_FLAG_STATE_NONE)) + *flags = RULE_FLAG_STATE_NONE; + + return rc; +} + + +void +virNWFilterPrintStateMatchFlags(virBufferPtr buf, const char *prefix, + int32_t flags, bool disp_none) +{ + if (!disp_none && (flags & RULE_FLAG_STATE_NONE)) + return; + + virBufferVSprintf(buf, "%s", prefix); + + printStringItems(buf, stateMatchMap, flags, ","); +} + + +static bool +stateValidator(enum attrDatatype datatype ATTRIBUTE_UNUSED, union data *val, + virNWFilterRuleDefPtr nwf, + nwItemDesc *item) +{ + char *input = val->c; + int32_t flags = 0; + + if (parseStateMatch(input, &flags)) + return 0; + + item->u.u16 = flags; + nwf->flags |= flags; + + item->datatype = DATATYPE_UINT16; + + return 1; +} + + +static bool +stateFormatter(virBufferPtr buf, + virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED, + nwItemDesc *item) +{ + virNWFilterPrintStateMatchFlags(buf, "", item->u.u16, true); + + return true; +} + + #define COMMON_MAC_PROPS(STRUCT) \ {\ .name = SRCMACADDR,\ @@ -926,6 +1061,13 @@ static const virXMLAttr2Struct ipv6Attri .name = "connlimit-above",\ .datatype = DATATYPE_UINT16,\ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataConnlimitAbove),\ + },\ + {\ + .name = STATE,\ + .datatype = DATATYPE_STRING,\ + .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataState),\ + .validator = stateValidator,\ + .formatter = stateFormatter,\ } #define COMMON_PORT_PROPS(STRUCT) \ @@ -1422,7 +1564,7 @@ virNWFilterRuleDetailsParse(xmlNodePtr n *flags = NWFILTER_ENTRY_ITEM_FLAG_EXISTS | flags_set; item->datatype = datatype >> 1; if (validator) { - if (!validator(datatype >> 1, &data, nwf)) { + if (!validator(datatype >> 1, &data, nwf, item)) { rc = -1; *flags = 0; } @@ -2533,7 +2675,7 @@ virNWFilterRuleDefDetailsFormat(virBuffe virBufferVSprintf(buf, " %s='", att[i].name); if (att[i].formatter) { - if (!att[i].formatter(buf, def)) { + if (!att[i].formatter(buf, def, item)) { virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, _("formatter for %s %s reported error"), type, Index: libvirt-acl/src/conf/nwfilter_conf.h =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_conf.h +++ libvirt-acl/src/conf/nwfilter_conf.h @@ -28,11 +28,14 @@ # include # include +# include # include "internal.h" + # include "util.h" # include "hash.h" # include "xml.h" +# include "buf.h" # include "network.h" /* XXX @@ -179,6 +182,7 @@ struct _ipHdrDataDef { nwItemDesc dataDstIPFrom; nwItemDesc dataDstIPTo; nwItemDesc dataDSCP; + nwItemDesc dataState; nwItemDesc dataConnlimitAbove; nwItemDesc dataComment; }; @@ -353,10 +357,25 @@ enum virNWFilterEbtablesTableType { # define MAX_RULE_PRIORITY 1000 enum virNWFilterRuleFlags { - RULE_FLAG_NO_STATEMATCH = (1 << 0), + RULE_FLAG_NO_STATEMATCH = (1 << 0), + RULE_FLAG_STATE_NEW = (1 << 1), + RULE_FLAG_STATE_ESTABLISHED = (1 << 2), + RULE_FLAG_STATE_RELATED = (1 << 3), + RULE_FLAG_STATE_INVALID = (1 << 4), + RULE_FLAG_STATE_NONE = (1 << 5), }; +# define IPTABLES_STATE_FLAGS \ + (RULE_FLAG_STATE_NEW | \ + RULE_FLAG_STATE_ESTABLISHED | \ + RULE_FLAG_STATE_RELATED | \ + RULE_FLAG_STATE_INVALID | \ + RULE_FLAG_STATE_NONE) + +void virNWFilterPrintStateMatchFlags(virBufferPtr buf, const char *prefix, + int32_t flags, bool disp_none); + typedef struct _virNWFilterRuleDef virNWFilterRuleDef; typedef virNWFilterRuleDef *virNWFilterRuleDefPtr; struct _virNWFilterRuleDef { Index: libvirt-acl/src/libvirt_private.syms =================================================================== --- libvirt-acl.orig/src/libvirt_private.syms +++ libvirt-acl/src/libvirt_private.syms @@ -534,6 +534,7 @@ virNWFilterConfLayerInit; virNWFilterConfLayerShutdown; virNWFilterLockFilterUpdates; virNWFilterUnlockFilterUpdates; +virNWFilterPrintStateMatchFlags; # nwfilter_params.h