diff --git a/arch/sim/Kconfig b/arch/sim/Kconfig index cf6de378d4..57894999fe 100644 --- a/arch/sim/Kconfig +++ b/arch/sim/Kconfig @@ -117,15 +117,35 @@ config SIM_NETDEV select ARCH_HAVE_NETDEV_STATISTICS select SCHED_LPWORK select SIM_WALLTIME + ---help--- + Build in support for a simulated network device. + +if SIM_NETDEV + +choice + prompt "Simulated Network Device Type" + default SIM_NETDEV_TAP + +config SIM_NETDEV_TAP + bool "Simulated Network Device with TAP/WPCAP" ---help--- Build in support for a simulated network device using a TAP device on Linux or WPCAP on Windows. +config SIM_NETDEV_VPNKIT + bool "Simulated Network Device with VPNKit" + ---help--- + Build in support for a simulated network device using VPNKit. + +endchoice + +endif + if HOST_LINUX choice prompt "Simulation Network Type" default SIM_NET_HOST_ROUTE - depends on SIM_NETDEV + depends on SIM_NETDEV_TAP config SIM_NET_HOST_ROUTE bool "Use local host route" diff --git a/arch/sim/src/Makefile b/arch/sim/src/Makefile index 69781b01b8..b6a5ae64f9 100644 --- a/arch/sim/src/Makefile +++ b/arch/sim/src/Makefile @@ -157,7 +157,7 @@ ifeq ($(CONFIG_ARCH_ROMGETC),y) CSRCS += up_romgetc.c endif -ifeq ($(CONFIG_SIM_NETDEV),y) +ifeq ($(CONFIG_SIM_NETDEV_TAP),y) CSRCS += up_netdriver.c HOSTCFLAGS += -DNETDEV_BUFSIZE=$(CONFIG_NET_ETH_PKTSIZE) ifneq ($(HOSTOS),Cygwin) @@ -173,7 +173,12 @@ else # HOSTOS != Cygwin HOSTSRCS += up_wpcap.c DRVLIB = /lib/w32api/libws2_32.a /lib/w32api/libiphlpapi.a endif # HOSTOS != Cygwin -endif # CONFIG_SIM_NETDEV +else ifeq ($(CONFIG_SIM_NETDEV_VPNKIT),y) + CSRCS += up_netdriver.c + HOSTSRCS += up_vpnkit.c + VPATH += :sim/vpnkit + HOSTSRCS += protocol.c negotiate.c +endif ifeq ($(CONFIG_RPTUN),y) CSRCS += up_rptun.c diff --git a/arch/sim/src/sim/up_internal.h b/arch/sim/src/sim/up_internal.h index b2ff25bb03..d12a3137c0 100644 --- a/arch/sim/src/sim/up_internal.h +++ b/arch/sim/src/sim/up_internal.h @@ -314,7 +314,7 @@ FAR struct ioexpander_dev_s *sim_ioexpander_initialize(void); /* up_tapdev.c **************************************************************/ -#if defined(CONFIG_SIM_NETDEV) && !defined(__CYGWIN__) +#if defined(CONFIG_SIM_NETDEV_TAP) && !defined(__CYGWIN__) void tapdev_init(void); int tapdev_avail(void); unsigned int tapdev_read(unsigned char *buf, unsigned int buflen); @@ -332,7 +332,7 @@ void tapdev_ifdown(void); /* up_wpcap.c ***************************************************************/ -#if defined(CONFIG_SIM_NETDEV) && defined(__CYGWIN__) +#if defined(CONFIG_SIM_NETDEV_TAP) && defined(__CYGWIN__) void wpcap_init(void); unsigned int wpcap_read(unsigned char *buf, unsigned int buflen); void wpcap_send(unsigned char *buf, unsigned int buflen); @@ -345,6 +345,24 @@ void wpcap_send(unsigned char *buf, unsigned int buflen); # define netdev_ifdown() {} #endif +/* up_vpnkit.c **************************************************************/ + +#if defined(CONFIG_SIM_NETDEV_VPNKIT) +void vpnkit_init(void); +int vpnkit_avail(void); +unsigned int vpnkit_read(unsigned char *buf, unsigned int buflen); +void vpnkit_send(unsigned char *buf, unsigned int buflen); +void vpnkit_ifup(in_addr_t ifaddr); +void vpnkit_ifdown(void); + +# define netdev_init() vpnkit_init() +# define netdev_avail() vpnkit_avail() +# define netdev_read(buf,buflen) vpnkit_read(buf,buflen) +# define netdev_send(buf,buflen) vpnkit_send(buf,buflen) +# define netdev_ifup(ifaddr) vpnkit_ifup(ifaddr) +# define netdev_ifdown() vpnkit_ifdown() +#endif + /* up_netdriver.c ***********************************************************/ #ifdef CONFIG_SIM_NETDEV diff --git a/arch/sim/src/sim/up_vpnkit.c b/arch/sim/src/sim/up_vpnkit.c new file mode 100644 index 0000000000..170c713c9d --- /dev/null +++ b/arch/sim/src/sim/up_vpnkit.c @@ -0,0 +1,259 @@ +/**************************************************************************** + * arch/sim/src/sim/up_vpnkit.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/* XXX broken api: mixing nuttx and host in_addr_t */ + +#include + +#include +#include +#include +#include + +#include "vpnkit/protocol.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ERROR(fmt, ...) \ + fprintf(stderr, "up_vpnkit: " fmt "\r\n", ##__VA_ARGS__) +#define INFO(fmt, ...) \ + fprintf(stderr, "up_vpnkit: " fmt "\r\n", ##__VA_ARGS__) +#define DEBUG(fmt, ...) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char *g_vpnkit_socket_path = "/tmp/vpnkit-nuttx"; /* XXX config */ +static struct vif_info g_vifinfo; +static int g_vpnkit_fd = -1; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +int negotiate(int fd, struct vif_info *vif); +void netdriver_setmacaddr(unsigned char *macaddr); + +static void vpnkit_connect() +{ + struct sockaddr_un sun; + int fd; + + if (g_vpnkit_fd != -1) + { + return; + } + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + { + ERROR("failed to create a socket"); + return; + } + + memset(&sun, 0, sizeof(sun)); + sun.sun_family = AF_UNIX; + strncpy(sun.sun_path, g_vpnkit_socket_path, sizeof(sun.sun_path) - 1); + + if (connect(fd, (const struct sockaddr *)&sun, sizeof(sun)) == -1) + { + ERROR("failed to connect to the vpnkit socket %s", + g_vpnkit_socket_path); + close(fd); + return; + } + + if (negotiate(fd, &g_vifinfo)) + { + ERROR("failed to negotiate with vpnkit"); + close(fd); + return; + } + + INFO("Successfully negotiated with vpnkit"); + g_vpnkit_fd = fd; +} + +static void vpnkit_disconnect() +{ + if (g_vpnkit_fd == -1) + { + return; + } + + INFO("disconnecting from vpnkit"); + close(g_vpnkit_fd); + g_vpnkit_fd = -1; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: vpnkit_init + * + ****************************************************************************/ + +void vpnkit_init(void) +{ + vpnkit_connect(); + netdriver_setmacaddr(g_vifinfo.mac); +} + +/**************************************************************************** + * Name: vpnkit_avail + * + ****************************************************************************/ + +int vpnkit_avail(void) +{ + struct pollfd pfd; + int ret; + + vpnkit_connect(); + memset(&pfd, 0, sizeof(pfd)); + pfd.fd = g_vpnkit_fd; + pfd.events = POLLIN; + ret = poll(&pfd, 1, 0); + if (ret == -1) + { + ERROR("poll failed on vpnkit socket"); + vpnkit_disconnect(); + return 0; + } + else if (ret != 0) + { + DEBUG("vpnkit_avail is returning 1"); + } + + return ret != 0; +} + +/**************************************************************************** + * Name: vpnkit_read + * + ****************************************************************************/ + +unsigned int vpnkit_read(unsigned char *buf, unsigned int buflen) +{ + uint8_t header[2]; /* 16-bit payload length in little endian */ + size_t packet_len; + ssize_t ret; + DEBUG("vpnkit_read called"); + + vpnkit_connect(); + ret = really_read(g_vpnkit_fd, header, sizeof(header)); + if (ret == -1) + { + ERROR("failed to read packet header"); + vpnkit_disconnect(); + return 0; + } + + packet_len = (header[1] << 8) | header[0]; + if (packet_len > buflen) + { + INFO("packet larger (%zu) than buffer size (%u)", packet_len, buflen); + + /* XXX it's better to drop this particular packet it. */ + + vpnkit_disconnect(); + return 0; + } + + ret = really_read(g_vpnkit_fd, buf, packet_len); + if (ret == -1) + { + ERROR("failed to read packet"); + vpnkit_disconnect(); + return 0; + } + + DEBUG("a packet received (size %zu)", packet_len); + return packet_len; +} + +/**************************************************************************** + * Name: vpnkit_send + * + ****************************************************************************/ + +void vpnkit_send(unsigned char *buf, unsigned int buflen) +{ + uint8_t header[2]; /* 16-bit payload length in little endian */ + ssize_t ret; + + DEBUG("vpnkit_send called"); + vpnkit_connect(); + header[0] = buflen & 0xff; + header[1] = (buflen >> 8) & 0xff; + ret = really_write(g_vpnkit_fd, header, sizeof(header)); + if (ret == -1) + { + ERROR("failed to write packet header"); + vpnkit_disconnect(); + return; + } + + ret = really_write(g_vpnkit_fd, buf, buflen); + if (ret == -1) + { + ERROR("failed to write packet payload"); + vpnkit_disconnect(); + return; + } + + DEBUG("a packet sent (size %u)", buflen); +} + +/**************************************************************************** + * Name: vpnkit_ifup + * + ****************************************************************************/ + +void vpnkit_ifup(in_addr_t ifaddr) +{ + DEBUG("vpnkit_ifup called"); +} + +/**************************************************************************** + * Name: vpnkit_ifdown + * + ****************************************************************************/ + +void vpnkit_ifdown(void) +{ + DEBUG("vpnkit_ifdown called"); +}