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__ */