From 67a8399cae344e2261475fb054914385624f19a5 Mon Sep 17 00:00:00 2001 From: SeokYeon Hwang Date: Mon, 4 Jan 2016 19:38:25 +0900 Subject: [PATCH] net: clean-up tap handling logic Tizen emulator specific logic is extracted to independent source file. Tap interface prefix is changed to "tap-tizen". Change-Id: I38e218936003e8bc8de51a4d0b3413872defe4c3 Signed-off-by: SeokYeon Hwang Signed-off-by: Munkyu Im --- net/tap-linux.c | 96 +-------------------------- net/tap.c | 19 ++++-- tizen/src/util/Makefile.objs | 3 + tizen/src/util/tap_helper.c | 153 +++++++++++++++++++++++++++++++++++++++++++ tizen/src/util/tap_helper.h | 34 ++++++++++ 5 files changed, 207 insertions(+), 98 deletions(-) create mode 100644 tizen/src/util/tap_helper.c create mode 100644 tizen/src/util/tap_helper.h diff --git a/net/tap-linux.c b/net/tap-linux.c index 419a245..5bd9d21 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -36,82 +36,6 @@ #define PATH_NET_TUN "/dev/net/tun" -#if defined(CONFIG_MARU) -#include "tizen/src/emul_state.h" - -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) { @@ -119,11 +43,7 @@ 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); @@ -177,20 +97,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, if (ifname[0] != '\0') pstrcpy(ifr.ifr_name, IFNAMSIZ, ifname); - 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 + else pstrcpy(ifr.ifr_name, IFNAMSIZ, "tap%d"); -#endif - } ret = ioctl(fd, TUNSETIFF, (void *) &ifr); if (ret != 0) { if (ifname[0] != '\0') { diff --git a/net/tap.c b/net/tap.c index 6642bc4..3a67a3e 100644 --- a/net/tap.c +++ b/net/tap.c @@ -45,6 +45,9 @@ #include "net/vhost_net.h" #if defined(CONFIG_MARU) #include "tizen/src/emul_state.h" +# if defined(CONFIG_LINUX) +#include "tizen/src/util/tap_helper.h" +# endif #endif typedef struct TAPState { @@ -384,7 +387,7 @@ static TAPState *net_tap_fd_init(NetClientState *peer, return s; } -#if !defined(CONFIG_WIN32) && defined(CONFIG_MARU) +#if defined(CONFIG_MARU) #include #include #include @@ -420,7 +423,7 @@ static void launch_script(const char *setup_script, const char *ifname, int fd, Error **errp) { int pid, status; -#if !defined(CONFIG_WIN32) && defined(CONFIG_MARU) +#if defined(CONFIG_MARU) const char* sudo_path = "/usr/bin/sudo"; char *host_ifname = get_interface_name_from_ip(); fprintf(stdout, "host_ifname: %s\n", host_ifname); @@ -452,7 +455,7 @@ static void launch_script(const char *setup_script, const char *ifname, } } parg = args; -#if !defined(CONFIG_WIN32) && defined(CONFIG_MARU) +#if defined(CONFIG_MARU) *parg++ = (char *)sudo_path; #endif *parg++ = (char *)setup_script; @@ -462,7 +465,7 @@ static void launch_script(const char *setup_script, const char *ifname, } *parg = NULL; -#if !defined(CONFIG_WIN32) && defined(CONFIG_MARU) +#if defined(CONFIG_MARU) execv(sudo_path, args); #else execv(setup_script, args); @@ -912,7 +915,15 @@ int net_init_tap(const NetClientOptions *opts, const char *name, if (tap->has_ifname) { pstrcpy(ifname, sizeof ifname, tap->ifname); } else { +#if defined(CONFIG_LINUX) && defined(CONFIG_MARU) + /* Create tap */ + tap_create(ifname); + if (ifname[0] == '\0') { + return -1; + } +#else ifname[0] = '\0'; +#endif } for (i = 0; i < queues; i++) { diff --git a/tizen/src/util/Makefile.objs b/tizen/src/util/Makefile.objs index b860b56..6c2564f 100644 --- a/tizen/src/util/Makefile.objs +++ b/tizen/src/util/Makefile.objs @@ -16,6 +16,9 @@ obj-$(CONFIG_LINUX) += osutil-linux.o obj-$(CONFIG_WIN32) += osutil-win32.o obj-$(CONFIG_DARWIN) += osutil-darwin.o +# tap helper +obj-$(CONFIG_LINUX) += tap_helper.o + #sdb obj-y += sdb.o diff --git a/tizen/src/util/tap_helper.c b/tizen/src/util/tap_helper.c new file mode 100644 index 0000000..6c142f6 --- /dev/null +++ b/tizen/src/util/tap_helper.c @@ -0,0 +1,153 @@ +/* + * TAP helper + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * MunKyu Im + * SeokYeon Hwang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include +#include +#include + +#include "qemu-common.h" +#include "qemu/error-report.h" + +#include "tap_helper.h" + +#define PATH_NET_TUN "/dev/net/tun" + +#include "util/new_debug_ch.h" +DECLARE_DEBUG_CHANNEL(tap_helper); + +#define START_BASE_PORT 26100 +#define END_BASE_PORT 26200 + +static bool launch_openvpn(bool ismake, const char *ifname) +{ + int pid, status; + const char* args[] = { + "/usr/bin/sudo", + "/usr/sbin/openvpn", + "", + "--dev", + ifname, + NULL + }; + if (ismake) { + LOG_INFO("launch_openvpn make tap: %s\n", ifname); + args[2] = "--mktun"; + } else { + LOG_INFO("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 true; + } + } + + LOG_WARNING("Could not launch openvpn\n"); + return false; +} + +void tap_create(char *ifname) +{ + int fd, ret, i; + struct ifreq ifr; + char dname[128]; + int cause; + + ifname[0] = '\0'; + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + + // clean-up legacy ifnames + for (i = START_BASE_PORT ; i < END_BASE_PORT; i += 10) { + g_snprintf(dname, sizeof(dname), "tap%d", i); + g_strlcpy(ifr.ifr_name, dname, IFNAMSIZ); + + TFR(fd = open(PATH_NET_TUN, O_RDWR)); + if (fd < 0) { + error_report("could not open %s: %m", PATH_NET_TUN); + return; + } + + ret = ioctl(fd, TUNSETIFF, (void *) &ifr); + + close(fd); + + if (ret == 0) { + if (!launch_openvpn(false, dname)) { + LOG_INFO("Failed to remove tap interface [%s]." + "The other emulator may be using this interface.\n", dname); + } + } + } + + // clean-up and find first unused ifname + for (i = 0; i < 10; i++) { + g_snprintf(dname, sizeof(dname), "tap_tizen%d", i); + g_strlcpy(ifr.ifr_name, dname, IFNAMSIZ); + + TFR(fd = open(PATH_NET_TUN, O_RDWR)); + if (fd < 0) { + error_report("could not open %s: %m", PATH_NET_TUN); + return; + } + + ret = ioctl(fd, TUNSETIFF, (void *) &ifr); + cause = errno; + close(fd); + + // ret 0: exist but not used + // ret -1 and cause EPERM: not exist + if (ret == 0 || (ret == -1 && cause == EPERM)) { + if (ret == 0 && !launch_openvpn(false, dname)) { + LOG_INFO("Failed to remove tap interface [%s]." + "The other emulator may be using this interface.\n", dname); + continue; + } + if (ifname[0] == '\0') { + g_strlcpy(ifname, dname, 128); + } + } + } + + // create tap + if (ifname == '\0' || !launch_openvpn(true, ifname)) { + LOG_INFO("Tap interface creattion failed.\n"); + } + + return; +} diff --git a/tizen/src/util/tap_helper.h b/tizen/src/util/tap_helper.h new file mode 100644 index 0000000..a14169e --- /dev/null +++ b/tizen/src/util/tap_helper.h @@ -0,0 +1,34 @@ +/* + * TAP helper + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * MunKyu Im + * SeokYeon Hwang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef __TAP_HELPER_H__ +#define __TAP_HELPER_H__ + +void tap_create(char *); + +#endif //__TAP_HELPER_H__ -- 2.7.4