diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index 7d7911d0a87cedc92ca55235486c648201241476..9dbda4a6cc77d4bd571a1efbb6a8c0eff8264059 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 5b3e5fa548978ca753bdc929413dd9187b20a2e1..f62969193c4f31b63c2a3e7aed7c37d0df0eef7c 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 6e1002f1b57056033bfe3aa3c77d3bc3e95858c9..2ae879ec47b48a5b700db71378a11e3c34da5a32 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 e6d0f4be010c37d7239a6f1ca3d50dfffaa97b1e..d5def1c816711f113d5032921527d11dba5f369e 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 4341f110733410a8fb33e27070e3ef7638d29e05..17dc0d35390d6d02faafbfa61865b5e135fd4706 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 e40c80eed8315f3b4e8780f9051d0aad972c6101..9a718b412f6dd1e9c1e777b1c1efeb3490449e0a 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 70aef56ce14f32172f77f701c0a9d1b29abec2b2..7b403979bd9dcca442591c97d1fdb08847deba5c 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 278f41ee0c48d1c340255e7d12d2d5bc9104a1a9..f8d3e0c53510afc546ae30874c3c041e42476092 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__ */