diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index 7d7911d0a8..9dbda4a6cc 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/schemas/basictypes.rng @@ -55,9 +55,24 @@ + + + + + + + + [a-fA-F0-9][02468aAcCeE](:[a-fA-F0-9]{2}){5} + + + + + [a-fA-F0-9][13579bBdDfF](:[a-fA-F0-9]{2}){5} + + - ([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2} + [a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5} diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 5b3e5fa548..f62969193c 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1391,7 +1391,7 @@ - + @@ -1417,7 +1417,7 @@ - + @@ -1498,7 +1498,7 @@ - + diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng index 6e1002f1b5..2ae879ec47 100644 --- a/docs/schemas/network.rng +++ b/docs/schemas/network.rng @@ -57,7 +57,7 @@ - + @@ -218,7 +218,7 @@ - + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index e6d0f4be01..d5def1c816 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4416,11 +4416,17 @@ virDomainNetDefParseXML(virCapsPtr caps, if (macaddr) { if (virMacAddrParse((const char *)macaddr, def->mac) < 0) { - virDomainReportError(VIR_ERR_INTERNAL_ERROR, + virDomainReportError(VIR_ERR_XML_ERROR, _("unable to parse mac address '%s'"), (const char *)macaddr); goto error; } + if (virMacAddrIsMulticast(def->mac)) { + virDomainReportError(VIR_ERR_XML_ERROR, + _("expected unicast mac address, found multicast '%s'"), + (const char *)macaddr); + goto error; + } } else { virCapabilitiesGenerateMac(caps, def->mac); } diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 4341f11073..17dc0d3539 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -419,22 +419,30 @@ virNetworkDHCPRangeDefParseXML(const char *networkName, def->nranges++; } else if (cur->type == XML_ELEMENT_NODE && xmlStrEqual(cur->name, BAD_CAST "host")) { - char *mac, *name, *ip; + char *mac = NULL, *name = NULL, *ip; unsigned char addr[6]; virSocketAddr inaddr; mac = virXMLPropString(cur, "mac"); - if ((mac != NULL) && - (virMacAddrParse(mac, &addr[0]) != 0)) { - virNetworkReportError(VIR_ERR_INTERNAL_ERROR, - _("Cannot parse MAC address '%s' in network '%s'"), - mac, networkName); - VIR_FREE(mac); - return -1; + if (mac != NULL) { + if (virMacAddrParse(mac, &addr[0]) < 0) { + virNetworkReportError(VIR_ERR_XML_ERROR, + _("Cannot parse MAC address '%s' in network '%s'"), + mac, networkName); + VIR_FREE(mac); + return -1; + } + if (virMacAddrIsMulticast(addr)) { + virNetworkReportError(VIR_ERR_XML_ERROR, + _("expected unicast mac address, found multicast '%s' in network '%s'"), + (const char *)mac, networkName); + VIR_FREE(mac); + return -1; + } } name = virXMLPropString(cur, "name"); if ((name != NULL) && (!c_isalpha(name[0]))) { - virNetworkReportError(VIR_ERR_INTERNAL_ERROR, + virNetworkReportError(VIR_ERR_XML_ERROR, _("Cannot use name address '%s' in network '%s'"), name, networkName); VIR_FREE(mac); @@ -991,6 +999,13 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) VIR_FREE(tmp); goto error; } + if (virMacAddrIsMulticast(def->mac)) { + virNetworkReportError(VIR_ERR_XML_ERROR, + _("Invalid multicast bridge mac address '%s' in network '%s'"), + tmp, def->name); + VIR_FREE(tmp); + goto error; + } VIR_FREE(tmp); def->mac_specified = true; } diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e40c80eed8..9a718b412f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1208,6 +1208,8 @@ virKeycodeValueTranslate; virMacAddrCompare; virMacAddrFormat; virMacAddrGenerate; +virMacAddrIsMulticast; +virMacAddrIsUnicast; virMacAddrParse; diff --git a/src/util/virmacaddr.c b/src/util/virmacaddr.c index 70aef56ce1..7b403979bd 100644 --- a/src/util/virmacaddr.c +++ b/src/util/virmacaddr.c @@ -126,3 +126,16 @@ void virMacAddrGenerate(const unsigned char *prefix, addr[4] = virRandomBits(8); addr[5] = virRandomBits(8); } + +/* The low order bit of the first byte is the "multicast" bit. */ +bool +virMacAddrIsMulticast(const unsigned char *addr) +{ + return !!(addr[0] & 1); +} + +bool +virMacAddrIsUnicast(const unsigned char *addr) +{ + return !(addr[0] & 1); +} diff --git a/src/util/virmacaddr.h b/src/util/virmacaddr.h index 278f41ee0c..f8d3e0c535 100644 --- a/src/util/virmacaddr.h +++ b/src/util/virmacaddr.h @@ -37,5 +37,6 @@ void virMacAddrGenerate(const unsigned char *prefix, unsigned char *addr); int virMacAddrParse(const char* str, unsigned char *addr) ATTRIBUTE_RETURN_CHECK; - +bool virMacAddrIsUnicast(const unsigned char *addr); +bool virMacAddrIsMulticast(const unsigned char *addr); #endif /* __VIR_MACADDR_H__ */