sim: Add a netdev backed by VPNKit
This commit is contained in:
parent
124c00b661
commit
a5f8b20fcd
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
259
arch/sim/src/sim/up_vpnkit.c
Normal file
259
arch/sim/src/sim/up_vpnkit.c
Normal file
@ -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 <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
/* XXX broken api: mixing nuttx and host in_addr_t */
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <poll.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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");
|
||||
}
|
Loading…
Reference in New Issue
Block a user