</define>
<!-- a 6 byte MAC address in ASCII-hex format, eg "12:34:56:78:9A:BC" -->
+ <!-- The lowest bit of the 1st byte is the "multicast" bit. a -->
+ <!-- uniMacAddr requires that bit to be 0, and a multiMacAddr -->
+ <!-- requires it to be 1. Plain macAddr will accept either. -->
+ <!-- Currently there is no use of multiMacAddr in libvirt, it -->
+ <!-- is included here for documentation/comparison purposes. -->
+ <define name="uniMacAddr">
+ <data type="string">
+ <param name="pattern">[a-fA-F0-9][02468aAcCeE](:[a-fA-F0-9]{2}){5}</param>
+ </data>
+ </define>
+ <define name="multiMacAddr">
+ <data type="string">
+ <param name="pattern">[a-fA-F0-9][13579bBdDfF](:[a-fA-F0-9]{2}){5}</param>
+ </data>
+ </define>
<define name="macAddr">
<data type="string">
- <param name="pattern">([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}</param>
+ <param name="pattern">[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}</param>
</data>
</define>
<optional>
<element name="mac">
<attribute name="address">
- <ref name="macAddr"/>
+ <ref name="uniMacAddr"/>
</attribute>
<empty/>
</element>
<optional>
<element name="mac">
<attribute name="address">
- <ref name="macAddr"/>
+ <ref name="uniMacAddr"/>
</attribute>
<empty/>
</element>
<optional>
<element name="mac">
<attribute name="address">
- <ref name="macAddr"/>
+ <ref name="uniMacAddr"/>
</attribute>
<empty/>
</element>
<!-- <mac> element -->
<optional>
<element name="mac">
- <attribute name="address"><ref name="macAddr"/></attribute>
+ <attribute name="address"><ref name="uniMacAddr"/></attribute>
<empty/>
</element>
</optional>
</zeroOrMore>
<zeroOrMore>
<element name="host">
- <attribute name="mac"><ref name="macAddr"/></attribute>
+ <attribute name="mac"><ref name="uniMacAddr"/></attribute>
<attribute name="name"><text/></attribute>
<attribute name="ip"><ref name="ipv4Addr"/></attribute>
</element>
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);
}
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);
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;
}
virMacAddrCompare;
virMacAddrFormat;
virMacAddrGenerate;
+virMacAddrIsMulticast;
+virMacAddrIsUnicast;
virMacAddrParse;
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);
+}
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__ */