conf: forbid use of multicast mac addresses

A few times libvirt users manually setting mac addresses have
complained of a networking failure that ends up being due to a multicast
mac address being used for a guest interface. This patch prevents that
by logging an error and failing if a multicast mac address is
encountered in each of the three following cases:

1) domain xml <interface> mac address.
2) network xml bridge mac address.
3) network xml dhcp/host mac address.

There are several other places where a mac address can be input that
aren't controlled in this manner because failure to do so has no
consequences (e.g., if the address will be used to search through
existing interfaces for a match).

The RNG has been updated to add multiMacAddr and uniMacAddr along with
the existing macAddr, and macAddr was switched to uniMacAddr where
appropriate.
This commit is contained in:
Laine Stump
2012-03-19 12:49:17 -04:00
parent 43d635caf3
commit 0007237301
8 changed files with 69 additions and 17 deletions

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -1208,6 +1208,8 @@ virKeycodeValueTranslate;
virMacAddrCompare;
virMacAddrFormat;
virMacAddrGenerate;
virMacAddrIsMulticast;
virMacAddrIsUnicast;
virMacAddrParse;

View File

@@ -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);
}

View File

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