The patch below extends the XML parser and generator so that every protocol now can have a comment node. Comments are limited to 256 characters and are tested to only contain printable characters or spaces. Signed-off-by: Stefan Berger --- src/conf/nwfilter_conf.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++ src/conf/nwfilter_conf.h | 10 ++++ 2 files changed, 110 insertions(+), 1 deletion(-) Index: libvirt-acl/src/conf/nwfilter_conf.c =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_conf.c +++ libvirt-acl/src/conf/nwfilter_conf.c @@ -38,6 +38,7 @@ #include "internal.h" #include "uuid.h" +#include "c-ctype.h" #include "memory.h" #include "virterror_internal.h" #include "datatypes.h" @@ -181,6 +182,8 @@ static const char dscp_str[] = " #define DSCP dscp_str +#define MAX_COMMENT_LENGTH 256 + /** * intMapGetByInt: * @intmap: Pointer to int-to-string map @@ -246,7 +249,11 @@ virNWFilterRuleDefFree(virNWFilterRuleDe for (i = 0; i < def->nvars; i++) VIR_FREE(def->vars[i]); + for (i = 0; i < def->nstrings; i++) + VIR_FREE(def->strings[i]); + VIR_FREE(def->vars); + VIR_FREE(def->strings); VIR_FREE(def); } @@ -350,6 +357,28 @@ virNWFilterRuleDefAddVar(virNWFilterRule } +static char * +virNWFilterRuleDefAddString(virNWFilterRuleDefPtr nwf, + const char *string) +{ + if (VIR_REALLOC_N(nwf->strings, nwf->nstrings+1) < 0) { + virReportOOMError(); + return NULL; + } + + nwf->strings[nwf->nstrings] = strdup(string); + + if (!nwf->strings[nwf->nstrings]) { + virReportOOMError(); + return NULL; + } + + nwf->nstrings++; + + return nwf->strings[nwf->nstrings-1]; +} + + void virNWFilterPoolObjRemove(virNWFilterPoolObjListPtr pools, virNWFilterPoolObjPtr pool) @@ -632,6 +661,25 @@ dscpValidator(enum attrDatatype datatype return 1; } + +static bool +commentValidator(enum attrDatatype datatype ATTRIBUTE_UNUSED, union data *val, + virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED) +{ + int i = 0; + char c; + + while ((c = val->c[i++]) != 0) { + if (!c_isgraph(c) && c != ' ') + return 0; + } + + if (i > MAX_COMMENT_LENGTH + 1) + val->c[MAX_COMMENT_LENGTH] = 0; + + return 1; +} + #define COMMON_MAC_PROPS(STRUCT) \ {\ .name = SRCMACADDR,\ @@ -655,6 +703,23 @@ dscpValidator(enum attrDatatype datatype } +#define COMMENT_PROP(STRUCT) \ + {\ + .name = "comment",\ + .datatype = DATATYPE_STRINGCOPY,\ + .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.dataComment),\ + .validator = commentValidator,\ + } + +#define COMMENT_PROP_IPHDR(STRUCT) \ + {\ + .name = "comment",\ + .datatype = DATATYPE_STRINGCOPY,\ + .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataComment),\ + .validator = commentValidator,\ + } + + static const virXMLAttr2Struct macAttributes[] = { COMMON_MAC_PROPS(ethHdrFilter), { @@ -664,6 +729,7 @@ static const virXMLAttr2Struct macAttrib .validator= checkMacProtocolID, .formatter= macProtocolIDFormatter, }, + COMMENT_PROP(ethHdrFilter), { .name = NULL, } @@ -702,6 +768,7 @@ static const virXMLAttr2Struct arpAttrib .datatype = DATATYPE_IPADDR, .dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataARPDstIPAddr), }, + COMMENT_PROP(arpHdrFilter), { .name = NULL, } @@ -762,6 +829,7 @@ static const virXMLAttr2Struct ipAttribu .dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.ipHdr.dataDSCP), .validator = dscpValidator, }, + COMMENT_PROP_IPHDR(ipHdrFilter), { .name = NULL, } @@ -817,6 +885,7 @@ static const virXMLAttr2Struct ipv6Attri .datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX, .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.portData.dataDstPortEnd), }, + COMMENT_PROP_IPHDR(ipv6HdrFilter), { .name = NULL, } @@ -914,6 +983,7 @@ static const virXMLAttr2Struct tcpAttrib .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX, .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.dataTCPOption), }, + COMMENT_PROP_IPHDR(tcpHdrFilter), { .name = NULL, } @@ -922,6 +992,7 @@ static const virXMLAttr2Struct tcpAttrib static const virXMLAttr2Struct udpAttributes[] = { COMMON_IP_PROPS(udpHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK), COMMON_PORT_PROPS(udpHdrFilter), + COMMENT_PROP_IPHDR(udpHdrFilter), { .name = NULL, } @@ -929,6 +1000,7 @@ static const virXMLAttr2Struct udpAttrib static const virXMLAttr2Struct udpliteAttributes[] = { COMMON_IP_PROPS(udpliteHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK), + COMMENT_PROP_IPHDR(udpliteHdrFilter), { .name = NULL, } @@ -936,6 +1008,7 @@ static const virXMLAttr2Struct udpliteAt static const virXMLAttr2Struct espAttributes[] = { COMMON_IP_PROPS(espHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK), + COMMENT_PROP_IPHDR(espHdrFilter), { .name = NULL, } @@ -943,6 +1016,7 @@ static const virXMLAttr2Struct espAttrib static const virXMLAttr2Struct ahAttributes[] = { COMMON_IP_PROPS(ahHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK), + COMMENT_PROP_IPHDR(ahHdrFilter), { .name = NULL, } @@ -951,6 +1025,7 @@ static const virXMLAttr2Struct ahAttribu static const virXMLAttr2Struct sctpAttributes[] = { COMMON_IP_PROPS(sctpHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK), COMMON_PORT_PROPS(sctpHdrFilter), + COMMENT_PROP_IPHDR(sctpHdrFilter), { .name = NULL, } @@ -969,6 +1044,7 @@ static const virXMLAttr2Struct icmpAttri .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX, .dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.dataICMPCode), }, + COMMENT_PROP_IPHDR(icmpHdrFilter), { .name = NULL, } @@ -977,6 +1053,7 @@ static const virXMLAttr2Struct icmpAttri static const virXMLAttr2Struct allAttributes[] = { COMMON_IP_PROPS(allHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK), + COMMENT_PROP_IPHDR(allHdrFilter), { .name = NULL, } @@ -985,6 +1062,7 @@ static const virXMLAttr2Struct allAttrib static const virXMLAttr2Struct igmpAttributes[] = { COMMON_IP_PROPS(igmpHdrFilter, DATATYPE_IPADDR, DATATYPE_IPMASK), + COMMENT_PROP_IPHDR(igmpHdrFilter), { .name = NULL, } @@ -999,6 +1077,7 @@ static const virXMLAttr2Struct tcpipv6At .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX, .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.dataTCPOption), }, + COMMENT_PROP_IPHDR(tcpHdrFilter), { .name = NULL, } @@ -1007,6 +1086,7 @@ static const virXMLAttr2Struct tcpipv6At static const virXMLAttr2Struct udpipv6Attributes[] = { COMMON_IP_PROPS(udpHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK), COMMON_PORT_PROPS(udpHdrFilter), + COMMENT_PROP_IPHDR(udpHdrFilter), { .name = NULL, } @@ -1015,6 +1095,7 @@ static const virXMLAttr2Struct udpipv6At static const virXMLAttr2Struct udpliteipv6Attributes[] = { COMMON_IP_PROPS(udpliteHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK), + COMMENT_PROP_IPHDR(udpliteHdrFilter), { .name = NULL, } @@ -1023,6 +1104,7 @@ static const virXMLAttr2Struct udpliteip static const virXMLAttr2Struct espipv6Attributes[] = { COMMON_IP_PROPS(espHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK), + COMMENT_PROP_IPHDR(espHdrFilter), { .name = NULL, } @@ -1031,6 +1113,7 @@ static const virXMLAttr2Struct espipv6At static const virXMLAttr2Struct ahipv6Attributes[] = { COMMON_IP_PROPS(ahHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK), + COMMENT_PROP_IPHDR(ahHdrFilter), { .name = NULL, } @@ -1040,6 +1123,7 @@ static const virXMLAttr2Struct ahipv6Att static const virXMLAttr2Struct sctpipv6Attributes[] = { COMMON_IP_PROPS(sctpHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK), COMMON_PORT_PROPS(sctpHdrFilter), + COMMENT_PROP_IPHDR(sctpHdrFilter), { .name = NULL, } @@ -1058,6 +1142,7 @@ static const virXMLAttr2Struct icmpv6Att .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX, .dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.dataICMPCode), }, + COMMENT_PROP_IPHDR(icmpHdrFilter), { .name = NULL, } @@ -1066,6 +1151,7 @@ static const virXMLAttr2Struct icmpv6Att static const virXMLAttr2Struct allipv6Attributes[] = { COMMON_IP_PROPS(allHdrFilter, DATATYPE_IPV6ADDR, DATATYPE_IPV6MASK), + COMMENT_PROP_IPHDR(allHdrFilter), { .name = NULL, } @@ -1332,6 +1418,17 @@ virNWFilterRuleDetailsParse(xmlNodePtr n found = 1; break; + case DATATYPE_STRINGCOPY: + if (!validator || + !(item->u.string = + virNWFilterRuleDefAddString(nwf, prop))) { + rc = -1; + break; + } + data.c = item->u.string; + found = 1; + break; + case DATATYPE_LAST: default: break; @@ -2510,6 +2607,10 @@ virNWFilterRuleDefDetailsFormat(virBuffe (j < 5) ? ":" : ""); break; + case DATATYPE_STRINGCOPY: + virBufferEscapeString(buf, "%s", item->u.string); + break; + case DATATYPE_STRING: default: virBufferVSprintf(buf, Index: libvirt-acl/src/conf/nwfilter_conf.h =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_conf.h +++ libvirt-acl/src/conf/nwfilter_conf.h @@ -92,8 +92,9 @@ enum attrDatatype { DATATYPE_STRING = (1 << 8), DATATYPE_IPV6ADDR = (1 << 9), DATATYPE_IPV6MASK = (1 << 10), + DATATYPE_STRINGCOPY = (1 << 11), - DATATYPE_LAST = (1 << 11), + DATATYPE_LAST = (1 << 12), }; @@ -123,6 +124,7 @@ struct _nwItemDesc { uint8_t u8; uint16_t u16; char protocolID[10]; + char *string; } u; }; @@ -142,6 +144,7 @@ typedef ethHdrFilterDef *ethHdrFilterDef struct _ethHdrFilterDef { ethHdrDataDef ethHdr; nwItemDesc dataProtocolID; + nwItemDesc dataComment; }; @@ -156,6 +159,7 @@ struct _arpHdrFilterDef { nwItemDesc dataARPSrcIPAddr; nwItemDesc dataARPDstMACAddr; nwItemDesc dataARPDstIPAddr; + nwItemDesc dataComment; }; @@ -174,6 +178,7 @@ struct _ipHdrDataDef { nwItemDesc dataDstIPTo; nwItemDesc dataDSCP; nwItemDesc dataConnlimitAbove; + nwItemDesc dataComment; }; @@ -376,6 +381,9 @@ struct _virNWFilterRuleDef { int nvars; char **vars; + + int nstrings; + char **strings; };