[libvirt] [PATCH 2/4] FreeBSD: implement virNetDevTapCreate() and virNetDevTapDelete().

Roman Bogorodskiy bogorodskiy at gmail.com
Fri Jan 4 15:00:11 UTC 2013


---
 src/util/virnetdevtap.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 137 insertions(+), 3 deletions(-)

diff --git a/src/util/virnetdevtap.c b/src/util/virnetdevtap.c
index a884de1..426d629 100644
--- a/src/util/virnetdevtap.c
+++ b/src/util/virnetdevtap.c
@@ -103,7 +103,7 @@ virNetDevProbeVnetHdr(int tapfd)
 #endif
 
 
-#ifdef TUNSETIFF
+#if defined(TUNSETIFF)
 /**
  * virNetDevTapCreate:
  * @ifname: the interface name
@@ -230,7 +230,141 @@ cleanup:
     VIR_FORCE_CLOSE(fd);
     return ret;
 }
-#else /* ! TUNSETIFF */
+#elif defined(__FreeBSD__)
+int virNetDevTapCreate(char **ifname,
+                       int *tapfd,
+                       unsigned int flags ATTRIBUTE_UNUSED)
+{
+    int s;
+    struct ifreq ifr;
+    int ret = -1;
+
+    s = socket(AF_LOCAL, SOCK_DGRAM, 0);
+    if (s < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to create socket"));
+        return -1;
+    }
+
+    memset(&ifr, 0, sizeof(ifr));
+
+    if (virStrcpyStatic(ifr.ifr_name, "tap") == NULL) {
+        virReportSystemError(ERANGE,
+                             _("Network interface name '%s' is too long"),
+                             *ifname);
+        goto cleanup;
+
+    }
+
+    if (ioctl(s, SIOCIFCREATE2, &ifr) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to create tap device %s"),
+                             NULLSTR(*ifname));
+        goto cleanup;
+    }
+
+    char *newifname = NULL;
+    if (strstr(*ifname, "%d") == NULL) {
+         newifname = *ifname;
+    } else {
+        int i;
+        for (i = 0; i <= 255; i++) {
+            virBuffer newname = VIR_BUFFER_INITIALIZER;
+            virBufferAsprintf(&newname, *ifname, i);
+
+            if (virBufferError(&newname)) {
+                virBufferFreeAndReset(&newname);
+                virReportOOMError();
+                ret = - 1;
+                goto cleanup;
+            }
+
+            if (virNetDevExists(virBufferCurrentContent(&newname)) == 0) {
+                newifname = strdup(virBufferContentAndReset(&newname));
+                break;
+            }
+        }
+    }
+
+    if (newifname == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to generate new name for interface %s"),
+                       ifr.ifr_name);
+        ret = -1;
+        goto cleanup;
+    }
+
+    if (virNetDevSetName(ifr.ifr_name, newifname) == -1) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to rename interface %s to %s"),
+                       ifr.ifr_name, newifname);
+        ret = -1;
+        goto cleanup;
+    }
+
+    *ifname = newifname;
+
+    if (tapfd) {
+        char *dev_prefix = "/dev/";
+        char *dev_path;
+        int dev_path_len = strlen(dev_prefix) +  strlen(*ifname) + 1;
+
+        if (VIR_ALLOC_N(dev_path, dev_path_len) < 0) {
+            virReportOOMError();
+            ret = -1;
+            goto cleanup;
+        }
+        snprintf(dev_path, dev_path_len, "%s%s", dev_prefix, *ifname);
+
+        *tapfd = open(dev_path, O_RDWR);
+
+        VIR_FREE(dev_path);
+    }
+
+    ret = 0;
+cleanup:
+    if (ret < 0)
+        VIR_FORCE_CLOSE(s);
+
+    return ret;
+}
+
+int virNetDevTapDelete(const char *ifname)
+{
+    int s;
+    struct ifreq ifr;
+    int ret = -1;
+
+    s = socket(AF_LOCAL, SOCK_DGRAM, 0);
+    if (s < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to create socket"));
+        return -1;
+    }
+
+    memset(&ifr, 0, sizeof(ifr));
+
+    if (virStrcpyStatic(ifr.ifr_name, ifname) == NULL) {
+        virReportSystemError(ERANGE,
+                             _("Network interface name '%s' is too long"),
+                             ifname);
+        goto cleanup;
+    }
+
+    if (ioctl(s, SIOCIFDESTROY, &ifr) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to remove tap device %s"),
+                             ifname);
+        goto cleanup;
+    }
+
+    ret = 0;
+cleanup:
+    VIR_FORCE_CLOSE(s);
+    return ret;
+}
+
+#else
 int virNetDevTapCreate(char **ifname ATTRIBUTE_UNUSED,
                        int *tapfd ATTRIBUTE_UNUSED,
                        unsigned int flags ATTRIBUTE_UNUSED)
@@ -245,7 +379,7 @@ int virNetDevTapDelete(const char *ifname ATTRIBUTE_UNUSED)
                          _("Unable to delete TAP devices on this platform"));
     return -1;
 }
-#endif /* ! TUNSETIFF */
+#endif
 
 
 /**
-- 
1.8.0




More information about the libvir-list mailing list