From 47a42852e5e952afc11c615cd787c2c78660737d Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 7 Jul 2017 13:07:21 -0600 Subject: [PATCH] apps/examples/ipforward: Add beginning of an IP forwarding example using only TUN devices. --- examples/README.txt | 7 + examples/ipforward/.gitignore | 11 ++ examples/ipforward/Kconfig | 31 ++++ examples/ipforward/Make.defs | 39 +++++ examples/ipforward/Makefile | 56 +++++++ examples/ipforward/ipforward.c | 298 +++++++++++++++++++++++++++++++++ 6 files changed, 442 insertions(+) create mode 100644 examples/ipforward/.gitignore create mode 100644 examples/ipforward/Kconfig create mode 100644 examples/ipforward/Make.defs create mode 100644 examples/ipforward/Makefile create mode 100644 examples/ipforward/ipforward.c diff --git a/examples/README.txt b/examples/README.txt index 00e973be3..3ddeaa8f7 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -681,6 +681,13 @@ examples/i2cchar each time that this test executes. Not available in the kernel build mode. +examples/ipforward +^^^^^^^^^^^^^^^^^^ + + A simple test of IP forwarding using TUN devices. This can be used on any + platform, but was intended for use on the simulation platform because it + performs a test of IP forwarding without the use of hardware. + examples/json ^^^^^^^^^^^^^ diff --git a/examples/ipforward/.gitignore b/examples/ipforward/.gitignore new file mode 100644 index 000000000..fa1ec7579 --- /dev/null +++ b/examples/ipforward/.gitignore @@ -0,0 +1,11 @@ +/Make.dep +/.depend +/.built +/*.asm +/*.obj +/*.rel +/*.lst +/*.sym +/*.adb +/*.lib +/*.src diff --git a/examples/ipforward/Kconfig b/examples/ipforward/Kconfig new file mode 100644 index 000000000..148dac1f2 --- /dev/null +++ b/examples/ipforward/Kconfig @@ -0,0 +1,31 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config EXAMPLES_IPFORWARD + bool "IP forwarding example" + default n + depends on NET_TUN && NET_TCP + ---help--- + Enable the IP forwarding example + +if EXAMPLES_IPFORWARD + +config EXAMPLES_IPFORWARD_PROGNAME + string "IP forwarding rogram name" + default "ipfwd" + depends on BUILD_KERNEL + ---help--- + This is the name of the program that will be use when the NSH ELF + program is installed. + +config EXAMPLES_IPFORWARD_PRIORITY + int "IP forwarding task priority" + default 100 + +config EXAMPLES_IPFORWARD_STACKSIZE + int "IP forwarding stack size" + default 2048 + +endif diff --git a/examples/ipforward/Make.defs b/examples/ipforward/Make.defs new file mode 100644 index 000000000..3cfe21de0 --- /dev/null +++ b/examples/ipforward/Make.defs @@ -0,0 +1,39 @@ +############################################################################ +# apps/examples/ipforward/Make.defs +# Adds selected applications to apps/ build +# +# Copyright (C) 2017 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifeq ($(CONFIG_EXAMPLES_IPFORWARD),y) +CONFIGURED_APPS += examples/ipforward +endif diff --git a/examples/ipforward/Makefile b/examples/ipforward/Makefile new file mode 100644 index 000000000..f2450ddba --- /dev/null +++ b/examples/ipforward/Makefile @@ -0,0 +1,56 @@ +############################################################################ +# apps/examples/ipforward/Makefile +# +# Copyright (C) 2017 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +# Hello, World! built-in application info + +CONFIG_EXAMPLES_IPFORWARD_PRIORITY ?= SCHED_PRIORITY_DEFAULT +CONFIG_EXAMPLES_IPFORWARD_STACKSIZE ?= 2048 + +APPNAME = ipfwd +PRIORITY = $(CONFIG_EXAMPLES_IPFORWARD_PRIORITY) +STACKSIZE = $(CONFIG_EXAMPLES_IPFORWARD_STACKSIZE) + +# Hello, World! Example + +ASRCS = +CSRCS = +MAINSRC = ipforward.c + +CONFIG_EXAMPLES_IPFORWARD_PROGNAME ?= ipfwd$(EXEEXT) +PROGNAME = $(CONFIG_EXAMPLES_IPFORWARD_PROGNAME) + +include $(APPDIR)/Application.mk diff --git a/examples/ipforward/ipforward.c b/examples/ipforward/ipforward.c new file mode 100644 index 000000000..3f6487f72 --- /dev/null +++ b/examples/ipforward/ipforward.c @@ -0,0 +1,298 @@ +/**************************************************************************** + * examplex/ipforward/ipforward.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "netutils/netlib.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MAX_DEVNAME 8 + +#ifdef CONFIG_NET_IPv6 +# define IPADDR_TYPE FAR const uint16_t * +#else +# define IPADDR_TYPE uint32_t +#endif + +/**************************************************************************** + * Name: Private Types + ****************************************************************************/ + +struct ipfwd_tun_s +{ + int it_fd; + char it_devname[MAX_DEVNAME]; +}; + +struct ipfwd_state_s +{ + struct ipfwd_tun_s if_tun0; + struct ipfwd_tun_s if_tun1; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +static const uint16_t g_tun0_ipaddr[8] = +{ + HTONS(0x7c00), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0x0097), +}; + +static const uint16_t g_tun1_ipaddr[8] = +{ + HTONS(0x7c00), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0x0139), +}; + +static const uint16_t g_netmask[8] = +{ + HTONS(0xffff), + HTONS(0xffff), + HTONS(0xffff), + HTONS(0xffff), + HTONS(0xffff), + HTONS(0xffff), + HTONS(0xffff), + HTONS(0), +}; +#else +static const uint32_t g_tun0_ipaddr = HTONL(0x0a000097); +static const uint32_t g_tun1_ipaddr = HTONL(0x0a000039); +static const uint32_t g_netmask = HTONL(0xffffff00); +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ipfwd_tun_configure + ****************************************************************************/ + +static int ipfwd_tun_configure(FAR struct ipfwd_tun_s *tun) +{ + struct ifreq ifr; + int errcode; + int ret; + + tun->it_fd = open("/dev/tun", O_RDWR); + if (tun->it_fd < 0) + { + errcode = errno; + fprintf(stderr, "ERROR: Failed to open /dev/tun: %d\n", errcode); + return -errcode; + } + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TUN; + + ret = ioctl(tun->it_fd, TUNSETIFF, (unsigned long)&ifr); + if (ret < 0) + { + errcode = errno; + fprintf(stderr, "ERROR: ioctl TUNSETIFF failed: %d\n", errcode); + close(tun->it_fd); + return -errcode; + } + + strncpy(tun->it_devname, ifr.ifr_name, MAX_DEVNAME); + printf("Created TUN device: %s\n", tun->it_devname); + return 0; +} + +/**************************************************************************** + * Name: ipfwd_netconfig + ****************************************************************************/ + +static int ipfwd_netconfig(FAR struct ipfwd_tun_s *tun, IPADDR_TYPE ipaddr, + IPADDR_TYPE netmask) +{ + int ret; + +#ifdef CONFIG_NET_IPv6 + + struct in6_addr addr; + + memcpy(addr.s6_addr16, ipaddr, 8 * sizeof(uint16_t)); + ret = netlib_set_ipv6addr(tun->it_devname, &addr); + if (ret < 0) + { + fprintf(stderr, "ERROR: netlib_set_ipv6addr() failed\n", ret); + return ret; + } + + memcpy(addr.s6_addr16, netmask, 8 * sizeof(uint16_t)); + ret = netlib_set_ipv6netmask(tun->it_devname, &addr); + if (ret < 0) + { + fprintf(stderr, "ERROR: netlib_set_ipv6netmask() failed\n", ret); + return ret; + } + +#else /* CONFIG_NET_IPv4 */ + + struct in_addr addr; + + addr.s_addr = ipaddr; + ret = netlib_set_ipv4addr(tun->it_devname, &addr); + if (ret < 0) + { + fprintf(stderr, "ERROR: netlib_set_ipv4addr() failed\n", ret); + return ret; + } + + addr.s_addr = netmask; + ret = netlib_set_ipv4netmask(tun->it_devname, &addr); + if (ret < 0) + { + fprintf(stderr, "ERROR: netlib_set_ipv4netmask() failed\n", ret); + return ret; + } +#endif + + netlib_ifup(tun->it_devname); + return 0; +} + +/**************************************************************************** + * Name: ipfwd_receiver + ****************************************************************************/ + +/**************************************************************************** + * Name: ipfwd_sender + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fstest_main + ****************************************************************************/ + +#ifdef CONFIG_BUILD_KERNEL +int main(int argc, FAR char *argv[]) +#else +int ipfwd_main(int argc, char *argv[]) +#endif +{ + struct ipfwd_state_s fwd; + int errcode = EXIT_SUCCESS; + int ret; + + /* Initialize the first TUN device */ + + ret = ipfwd_tun_configure(&fwd.if_tun0); + if (ret < 0) + { + fprintf(stderr, "ERROR: Failed to create tun0: %d\n", ret); + goto errout; + } + + ret = ipfwd_netconfig(&fwd.if_tun0, g_tun0_ipaddr, g_netmask); + if (ret < 0) + { + fprintf(stderr, "ERROR: ipfwd_netconfig failed: %d\n", ret); + goto errout_with_tun0; + } + + /* Initialize the second TUN device */ + + ret = ipfwd_tun_configure(&fwd.if_tun1); + if (ret < 0) + { + fprintf(stderr, "ERROR: Failed to create tun1: %d\n", ret); + goto errout_with_tun0; + } + + ret = ipfwd_netconfig(&fwd.if_tun0, g_tun0_ipaddr, g_netmask); + if (ret < 0) + { + fprintf(stderr, "ERROR: ipfwd_netconfig failed: %d\n", ret); + errcode = EXIT_FAILURE; + goto errout_with_tun1; + } + + /* Start receiver thread */ + + /* Start sender thread */ + + /* Wait for sender thread to terminate */ + +errout_with_receiver: + /* Wait for receiver thread to terminate */ + +errout_with_tun1: + close(fwd.if_tun1.it_fd); +errout_with_tun0: + close(fwd.if_tun0.it_fd); +errout: + return errcode; +}