From fb1b7d8ed03cf12258d307d197092d09f1e22559 Mon Sep 17 00:00:00 2001 From: Laine Stump Date: Wed, 22 Jul 2009 16:07:26 +0200 Subject: [PATCH] Update modified mac address in place in virGetInterface * src/datatypes.c: handle the nasty case where an interface mac address change, while it's already in use --- src/datatypes.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/datatypes.c b/src/datatypes.c index 5f90aad34d..0e3628abd7 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -535,7 +535,38 @@ virGetInterface(virConnectPtr conn, const char *name, const char *mac) { ret = (virInterfacePtr) virHashLookup(conn->interfaces, name); - if ((ret == NULL) || STRCASENEQ(ret->mac, mac)) { + if (ret != NULL) { + if (STRCASENEQ(ret->mac, mac)) { + /* + * If the mac address has changed, try to modify it in + * place, which will only work if the new mac is the + * same length as, or shorter than, the old mac. + */ + size_t newmaclen = strlen(mac); + size_t oldmaclen = strlen(ret->mac); + if (newmaclen <= oldmaclen) { + strcpy(ret->mac, mac); + } else { + /* + * If it's longer, we're kind of screwed, because we + * can't add a new hashtable entry (it would clash + * with the existing entry of same name), and we can't + * free/re-alloc the existing entry's mac, as some + * other thread may already be using the existing mac + * pointer. Fortunately, this should never happen, + * since the length of the mac address for any + * interface is determined by the type of the + * interface, and that is unlikely to change. + */ + virMutexUnlock(&conn->lock); + virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, +_("Failed to change interface mac address from %s to %s due to differing lengths."), + ret->mac, mac); + ret = NULL; + goto error; + } + } + } else { if (VIR_ALLOC(ret) < 0) { virReportOOMError(conn); goto error;