| /* |
| * 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 <stdio.h> |
| #include <stdlib.h> |
| #include <stdarg.h> |
| #include <errno.h> |
| #include <string.h> |
| #include <stdbool.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <sys/ioctl.h> |
| #include <sys/socket.h> |
| #include <sys/select.h> |
| #include <net/if.h> |
| #include <time.h> |
| #include <zephyr/arch/posix/posix_trace.h> |
| |
| #ifdef __linux |
| #include <linux/if_tun.h> |
| #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 <zephyr/logging/log.h> |
| LOG_MODULE_REGISTER(LOG_MODULE_NAME); |
| |
| #include <zephyr/types.h> |
| #include <zephyr/sys_clock.h> |
| |
| #if defined(CONFIG_NET_GPTP) |
| #include <zephyr/net/gptp.h> |
| #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); |
| } |