Merge tag 'v2.4.0' into tizen_3.0_qemu_2.4
[sdk/emulator/qemu.git] / net / tap-linux.c
index 394f2a6..cecfee9 100644 (file)
 
 #define PATH_NET_TUN "/dev/net/tun"
 
+#if defined(CONFIG_MARU)
+static int launch_openvpn(bool ismake, const char *ifname)
+{
+    int pid, status;
+    const char* args[] = {
+        "/usr/bin/sudo",
+        "/usr/sbin/openvpn",
+        "--mktun",
+        "--dev",
+        ifname,
+        NULL
+    };
+    if (ismake) {
+        fprintf(stdout, "launch_openvpn make tap: %s\n", ifname);
+    } else {
+        fprintf(stdout, "launch_openvpn remove tap: %s\n", ifname);
+        args[2] = "--rmtun";
+    }
+    /* try to launch network script */
+    pid = fork();
+    if (pid == 0) {
+        execv(args[0], (char**)args);
+        _exit(1);
+    } else if (pid > 0) {
+        while (waitpid(pid, &status, 0) != pid) {
+            /* loop */
+        }
+
+        if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+            return 0;
+        }
+    }
+    fprintf(stderr, "Could not launch openvpn\n");
+    return -1;
+}
+
+static int tap_cleanup(void)
+{
+    int fd, ret;
+    struct ifreq ifr;
+    char dname[100];
+    int port = get_emul_vm_base_port() + 10;
+
+    TFR(fd = open(PATH_NET_TUN, O_RDWR));
+    if (fd < 0) {
+        error_report("could not open %s: %m", PATH_NET_TUN);
+        return -1;
+    }
+    memset(&ifr, 0, sizeof(ifr));
+    ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+
+    for ( ; port < 26200; port += 10) {
+        snprintf(dname, sizeof(dname), "tap%d", port);
+        pstrcpy(ifr.ifr_name, IFNAMSIZ, dname);
+        ret = ioctl(fd, TUNSETIFF, (void *) &ifr);
+        if (ret == 0) {
+            close(fd);
+            if (launch_openvpn(false, dname)) {
+                fprintf(stderr, "Failed to remove %s device. It can be used on the other emulator\n", dname);
+            }
+            TFR(fd = open(PATH_NET_TUN, O_RDWR));
+            if (fd < 0) {
+                error_report("could not open %s: %m", PATH_NET_TUN);
+                return -1;
+            }
+        } else {
+            close(fd);
+        }
+    }
+    return 0;
+}
+
+#endif
+
 int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
              int vnet_hdr_required, int mq_required, Error **errp)
 {
@@ -43,7 +117,11 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
     int fd, ret;
     int len = sizeof(struct virtio_net_hdr);
     unsigned int features;
-
+#if defined(CONFIG_MARU)
+    if (tap_cleanup() < 0) {
+        return -1;
+    }
+#endif
     TFR(fd = open(PATH_NET_TUN, O_RDWR));
     if (fd < 0) {
         error_setg_errno(errp, errno, "could not open %s", PATH_NET_TUN);
@@ -97,8 +175,20 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
 
     if (ifname[0] != '\0')
         pstrcpy(ifr.ifr_name, IFNAMSIZ, ifname);
-    else
+    else {
+#if defined(CONFIG_MARU)
+        /* Create tap */
+        char dname[100];
+        snprintf(dname, sizeof dname, "tap%d", get_emul_vm_base_port());
+        if (launch_openvpn(true, dname)) {
+            close(fd);
+            return -1;
+        }
+        pstrcpy(ifr.ifr_name, IFNAMSIZ, dname);
+#else
         pstrcpy(ifr.ifr_name, IFNAMSIZ, "tap%d");
+#endif
+    }
     ret = ioctl(fd, TUNSETIFF, (void *) &ifr);
     if (ret != 0) {
         if (ifname[0] != '\0') {