|
|
e942243 |
diff -rup libvirt-0.7.1/src/network_driver.c new/src/network_driver.c
|
|
|
e942243 |
--- libvirt-0.7.1/src/network_driver.c 2009-09-15 03:49:04.000000000 -0400
|
|
|
e942243 |
+++ new/src/network_driver.c 2010-06-15 13:33:01.900912000 -0400
|
|
|
e942243 |
@@ -43,6 +43,8 @@
|
|
|
e942243 |
#include <stdio.h>
|
|
|
e942243 |
#include <sys/wait.h>
|
|
|
e942243 |
#include <sys/ioctl.h>
|
|
|
e942243 |
+#include <netinet/in.h>
|
|
|
e942243 |
+#include <arpa/inet.h>
|
|
|
e942243 |
|
|
|
e942243 |
#include "virterror_internal.h"
|
|
|
e942243 |
#include "datatypes.h"
|
|
|
e942243 |
@@ -843,6 +845,102 @@ cleanup:
|
|
|
e942243 |
return ret;
|
|
|
e942243 |
}
|
|
|
e942243 |
|
|
|
e942243 |
+#define PROC_NET_ROUTE "/proc/net/route"
|
|
|
e942243 |
+
|
|
|
e942243 |
+static int networkCheckRouteCollision(virNetworkObjPtr network)
|
|
|
e942243 |
+{
|
|
|
e942243 |
+ int ret = -1, len;
|
|
|
e942243 |
+ char *cur, *buf = NULL;
|
|
|
e942243 |
+ enum {MAX_ROUTE_SIZE = 1024*64};
|
|
|
e942243 |
+ struct in_addr inaddress, innetmask;
|
|
|
e942243 |
+ unsigned int net_dest;
|
|
|
e942243 |
+
|
|
|
e942243 |
+ if (!network->def->ipAddress || !network->def->netmask)
|
|
|
e942243 |
+ return 0;
|
|
|
e942243 |
+
|
|
|
e942243 |
+ if (inet_pton(AF_INET, network->def->ipAddress, &inaddress) <= 0) {
|
|
|
e942243 |
+ networkReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
e942243 |
+ _("cannot parse IP address '%s'"),
|
|
|
e942243 |
+ network->def->ipAddress);
|
|
|
e942243 |
+ goto error;
|
|
|
e942243 |
+ }
|
|
|
e942243 |
+ if (inet_pton(AF_INET, network->def->netmask, &innetmask) <= 0) {
|
|
|
e942243 |
+ networkReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
e942243 |
+ _("cannot parse netmask '%s'"),
|
|
|
e942243 |
+ network->def->netmask);
|
|
|
e942243 |
+ goto error;
|
|
|
e942243 |
+ }
|
|
|
e942243 |
+
|
|
|
e942243 |
+ net_dest = (inaddress.s_addr & innetmask.s_addr);
|
|
|
e942243 |
+
|
|
|
e942243 |
+ /* Read whole routing table into memory */
|
|
|
e942243 |
+ if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0)
|
|
|
e942243 |
+ goto error;
|
|
|
e942243 |
+
|
|
|
e942243 |
+ /* Dropping the last character shouldn't hurt */
|
|
|
e942243 |
+ if (len > 0)
|
|
|
e942243 |
+ buf[len-1] = '\0';
|
|
|
e942243 |
+
|
|
|
e942243 |
+ VIR_DEBUG("%s output:\n%s", PROC_NET_ROUTE, buf);
|
|
|
e942243 |
+
|
|
|
e942243 |
+ if (!STRPREFIX (buf, "Iface"))
|
|
|
e942243 |
+ goto out;
|
|
|
e942243 |
+
|
|
|
e942243 |
+ /* First line is just headings, skip it */
|
|
|
e942243 |
+ cur = strchr(buf, '\n');
|
|
|
e942243 |
+ if (cur)
|
|
|
e942243 |
+ cur++;
|
|
|
e942243 |
+
|
|
|
e942243 |
+ while (cur) {
|
|
|
e942243 |
+ char iface[17], dest[128], mask[128];
|
|
|
e942243 |
+ unsigned int addr_val, mask_val;
|
|
|
e942243 |
+ int num;
|
|
|
e942243 |
+
|
|
|
e942243 |
+ /* NUL-terminate the line, so sscanf doesn't go beyond a newline. */
|
|
|
e942243 |
+ char *nl = strchr(cur, '\n');
|
|
|
e942243 |
+ if (nl) {
|
|
|
e942243 |
+ *nl++ = '\0';
|
|
|
e942243 |
+ }
|
|
|
e942243 |
+
|
|
|
e942243 |
+ num = sscanf(cur, "%16s %127s %*s %*s %*s %*s %*s %127s",
|
|
|
e942243 |
+ iface, dest, mask);
|
|
|
e942243 |
+ cur = nl;
|
|
|
e942243 |
+
|
|
|
e942243 |
+ if (num != 3) {
|
|
|
e942243 |
+ VIR_DEBUG("Failed to parse %s", PROC_NET_ROUTE);
|
|
|
e942243 |
+ continue;
|
|
|
e942243 |
+ }
|
|
|
e942243 |
+
|
|
|
e942243 |
+ if (virStrToLong_ui(dest, NULL, 16, &addr_val) < 0) {
|
|
|
e942243 |
+ VIR_DEBUG("Failed to convert network address %s to uint", dest);
|
|
|
e942243 |
+ continue;
|
|
|
e942243 |
+ }
|
|
|
e942243 |
+
|
|
|
e942243 |
+ if (virStrToLong_ui(mask, NULL, 16, &mask_val) < 0) {
|
|
|
e942243 |
+ VIR_DEBUG("Failed to convert network mask %s to uint", mask);
|
|
|
e942243 |
+ continue;
|
|
|
e942243 |
+ }
|
|
|
e942243 |
+
|
|
|
e942243 |
+ addr_val &= mask_val;
|
|
|
e942243 |
+
|
|
|
e942243 |
+ if ((net_dest == addr_val) &&
|
|
|
e942243 |
+ (innetmask.s_addr == mask_val)) {
|
|
|
e942243 |
+ networkReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
e942243 |
+ _("Network %s/%s is already in use by "
|
|
|
e942243 |
+ "interface %s"),
|
|
|
e942243 |
+ network->def->ipAddress,
|
|
|
e942243 |
+ network->def->netmask, iface);
|
|
|
e942243 |
+ goto error;
|
|
|
e942243 |
+ }
|
|
|
e942243 |
+ }
|
|
|
e942243 |
+
|
|
|
e942243 |
+out:
|
|
|
e942243 |
+ ret = 0;
|
|
|
e942243 |
+error:
|
|
|
e942243 |
+ VIR_FREE(buf);
|
|
|
e942243 |
+ return ret;
|
|
|
e942243 |
+}
|
|
|
e942243 |
+
|
|
|
e942243 |
static int networkStartNetworkDaemon(virConnectPtr conn,
|
|
|
e942243 |
struct network_driver *driver,
|
|
|
e942243 |
virNetworkObjPtr network) {
|
|
|
e942243 |
@@ -854,6 +952,10 @@ static int networkStartNetworkDaemon(vir
|
|
|
e942243 |
return -1;
|
|
|
e942243 |
}
|
|
|
e942243 |
|
|
|
e942243 |
+ /* Check to see if network collides with an existing route */
|
|
|
e942243 |
+ if (networkCheckRouteCollision(network) < 0)
|
|
|
e942243 |
+ return -1;
|
|
|
e942243 |
+
|
|
|
e942243 |
if ((err = brAddBridge(driver->brctl, network->def->bridge))) {
|
|
|
e942243 |
virReportSystemError(conn, err,
|
|
|
e942243 |
_("cannot create bridge '%s'"),
|