230 lines
4.5 KiB
C
230 lines
4.5 KiB
C
/*
|
|
* 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);
|
|
}
|