/* * Copyright (c) 2018 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * * Routines setting up the host system. Those are placed in separate file * because there is naming conflicts between host and zephyr network stacks. */ /* Host include files */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __linux #include #endif /* Zephyr include files. Be very careful here and only include minimum * things needed. */ #define LOG_MODULE_NAME eth_posix_adapt #define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL #include LOG_MODULE_REGISTER(LOG_MODULE_NAME); #include #include #if defined(CONFIG_NET_GPTP) #include #endif #include "eth_native_posix_priv.h" /* Note that we cannot create the TUN/TAP device from the setup script * as we need to get a file descriptor to communicate with the interface. */ int eth_iface_create(const char *if_name, bool tun_only) { struct ifreq ifr; int fd, ret = -EINVAL; fd = open(ETH_NATIVE_POSIX_DEV_NAME, O_RDWR); if (fd < 0) { return -errno; } (void)memset(&ifr, 0, sizeof(ifr)); #ifdef __linux ifr.ifr_flags = (tun_only ? IFF_TUN : IFF_TAP) | IFF_NO_PI; strncpy(ifr.ifr_name, if_name, IFNAMSIZ - 1); ret = ioctl(fd, TUNSETIFF, (void *)&ifr); if (ret < 0) { ret = -errno; close(fd); return ret; } #endif return fd; } int eth_iface_remove(int fd) { return close(fd); } static int ssystem(const char *fmt, ...) __attribute__((__format__(__printf__, 1, 2))); static int ssystem(const char *fmt, ...) { char cmd[255]; va_list ap; int ret; va_start(ap, fmt); vsnprintf(cmd, sizeof(cmd), fmt, ap); va_end(ap); posix_print_trace("%s\n", cmd); ret = system(cmd); return -WEXITSTATUS(ret); } int eth_setup_host(const char *if_name) { if (!IS_ENABLED(CONFIG_ETH_NATIVE_POSIX_STARTUP_AUTOMATIC)) { return 0; } /* User might have added -i option to setup script string, so * check that situation in the script itself so that the -i option * we add here is ignored in that case. */ return ssystem("%s -i %s", ETH_NATIVE_POSIX_SETUP_SCRIPT, if_name); } int eth_start_script(const char *if_name) { if (!IS_ENABLED(CONFIG_ETH_NATIVE_POSIX_STARTUP_AUTOMATIC)) { return 0; } if (ETH_NATIVE_POSIX_STARTUP_SCRIPT[0] == '\0') { return 0; } if (ETH_NATIVE_POSIX_STARTUP_SCRIPT_USER[0] == '\0') { return ssystem("%s %s", ETH_NATIVE_POSIX_STARTUP_SCRIPT, if_name); } else { return ssystem("sudo -u %s %s %s", ETH_NATIVE_POSIX_STARTUP_SCRIPT_USER, ETH_NATIVE_POSIX_STARTUP_SCRIPT, if_name); } } int eth_wait_data(int fd) { struct timeval timeout; fd_set rset; int ret; FD_ZERO(&rset); FD_SET(fd, &rset); timeout.tv_sec = 0; timeout.tv_usec = 0; ret = select(fd + 1, &rset, NULL, NULL, &timeout); if (ret < 0 && errno != EINTR) { return -errno; } else if (ret > 0) { if (FD_ISSET(fd, &rset)) { return 0; } } return -EAGAIN; } ssize_t eth_read_data(int fd, void *buf, size_t buf_len) { return read(fd, buf, buf_len); } ssize_t eth_write_data(int fd, void *buf, size_t buf_len) { return write(fd, buf, buf_len); } #if defined(CONFIG_NET_GPTP) int eth_clock_gettime(struct net_ptp_time *time) { struct timespec tp; int ret; ret = clock_gettime(CLOCK_MONOTONIC_RAW, &tp); if (ret < 0) { return -errno; } time->second = tp.tv_sec; time->nanosecond = tp.tv_nsec; return 0; } #endif /* CONFIG_NET_GPTP */ #if defined(CONFIG_NET_PROMISCUOUS_MODE) int eth_promisc_mode(const char *if_name, bool enable) { if (!IS_ENABLED(CONFIG_ETH_NATIVE_POSIX_STARTUP_AUTOMATIC)) { return 0; } return ssystem("ip link set dev %s promisc %s", if_name, enable ? "on" : "off"); } #endif /* CONFIG_NET_PROMISCUOUS_MODE */ /* If we have enabled manual setup, then interface cannot be * taken up or down by the driver as we normally do not have * enough permissions. */ int eth_if_up(const char *if_name) { if (!IS_ENABLED(CONFIG_ETH_NATIVE_POSIX_STARTUP_AUTOMATIC)) { return 0; } return ssystem("ip link set dev %s up", if_name); } int eth_if_down(const char *if_name) { if (!IS_ENABLED(CONFIG_ETH_NATIVE_POSIX_STARTUP_AUTOMATIC)) { return 0; } return ssystem("ip link set dev %s down", if_name); }