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'"),