diff --git a/docs/schemas/nwfilter.rng b/docs/schemas/nwfilter.rng index e679766323..b9d72760af 100644 --- a/docs/schemas/nwfilter.rng +++ b/docs/schemas/nwfilter.rng @@ -286,10 +286,18 @@ root - arp - rarp - ipv4 - ipv6 + + arp[a-zA-Z0-9_\.:-]{0,9} + + + rarp[a-zA-Z0-9_\.:-]{0,8} + + + ipv4[a-zA-Z0-9_\.:-]{0,8} + + + ipv6[a-zA-Z0-9_\.:-]{0,8} + diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index 4b7c823070..ea9111deeb 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -2007,6 +2007,84 @@ err_exit: goto cleanup; } +static bool +virNWFilterIsValidChainName(const char *chainname) +{ + if (strlen(chainname) > MAX_CHAIN_SUFFIX_SIZE) { + virNWFilterReportError(VIR_ERR_INVALID_ARG, + _("Name of chain is longer than " + "%u characters"), + MAX_CHAIN_SUFFIX_SIZE); + return false; + } + + if (chainname[strspn(chainname, VALID_CHAINNAME)] != 0) { + virNWFilterReportError(VIR_ERR_INVALID_ARG, + _("Chain name contains invalid characters")); + return false; + } + + return true; +} + +/* + * Test whether the name of the chain is supported. + * It current has to have a prefix of either one of the strings found in + * virNWFilterChainSuffixTypeToString(). + */ +static const char * +virNWFilterIsAllowedChain(const char *chainname) +{ + enum virNWFilterChainSuffixType i; + const char *name, *msg; + virBuffer buf = VIR_BUFFER_INITIALIZER; + bool printed = false; + + if (!virNWFilterIsValidChainName(chainname)) + return NULL; + + for (i = 0; i < VIR_NWFILTER_CHAINSUFFIX_LAST; i++) { + name = virNWFilterChainSuffixTypeToString(i); + if (i == VIR_NWFILTER_CHAINSUFFIX_ROOT) { + /* allow 'root' as a complete name but not as a prefix */ + if (STREQ(chainname, name)) + return name; + if (STRPREFIX(chainname, name)) + return NULL; + } + if (STRPREFIX(chainname, name)) + return name; + } + + virBufferAsprintf(&buf, + _("Invalid chain name '%s'. Please use a chain name " + "called '%s' or any of the following prefixes: "), + chainname, + virNWFilterChainSuffixTypeToString( + VIR_NWFILTER_CHAINSUFFIX_ROOT)); + for (i = 0; i < VIR_NWFILTER_CHAINSUFFIX_LAST; i++) { + if (i == VIR_NWFILTER_CHAINSUFFIX_ROOT) + continue; + if (printed) + virBufferAddLit(&buf, ", "); + virBufferAdd(&buf, virNWFilterChainSuffixTypeToString(i), -1); + printed = true; + } + + if (virBufferError(&buf)) { + virReportOOMError(); + virBufferFreeAndReset(&buf); + goto err_exit; + } + + msg = virBufferContentAndReset(&buf); + + virNWFilterReportError(VIR_ERR_INVALID_ARG, "%s", msg); + VIR_FREE(msg); + +err_exit: + return NULL; +} static virNWFilterDefPtr virNWFilterDefParseXML(xmlXPathContextPtr ctxt) { @@ -2017,6 +2095,7 @@ virNWFilterDefParseXML(xmlXPathContextPtr ctxt) { char *chain_pri_s = NULL; virNWFilterEntryPtr entry; int chain_priority; + const char *name_prefix; if (VIR_ALLOC(ret) < 0) { virReportOOMError(); @@ -2052,19 +2131,19 @@ virNWFilterDefParseXML(xmlXPathContextPtr ctxt) { chain = virXPathString("string(./@chain)", ctxt); if (chain) { - if (virNWFilterChainSuffixTypeFromString(chain) < 0) { - virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, - _("unknown chain suffix '%s'"), chain); + name_prefix = virNWFilterIsAllowedChain(chain); + if (name_prefix == NULL) goto cleanup; - } ret->chainsuffix = chain; if (chain_pri_s) { ret->chainPriority = chain_priority; } else { /* assign default priority if none can be found via lookup */ - if (!intMapGetByString(chain_priorities, chain, 0, + if (!name_prefix || + !intMapGetByString(chain_priorities, name_prefix, 0, &ret->chainPriority)) { + /* assign default chain priority */ ret->chainPriority = (NWFILTER_MAX_FILTER_PRIORITY + NWFILTER_MIN_FILTER_PRIORITY) / 2; } diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h index 0ff14d143a..55b2aad35a 100644 --- a/src/conf/nwfilter_conf.h +++ b/src/conf/nwfilter_conf.h @@ -446,6 +446,9 @@ enum virNWFilterChainSuffixType { VIR_NWFILTER_CHAINSUFFIX_LAST, }; +# define VALID_CHAINNAME \ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.:-" + typedef int32_t virNWFilterChainPriority; typedef struct _virNWFilterDef virNWFilterDef;