diff --git a/examples/README.txt b/examples/README.txt index a0de89082..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 ^^^^^^^^^^^^^ @@ -694,19 +701,6 @@ examples/json on 2011-10-10 so I presume that the code is stable and there is no risk of maintaining duplicate logic in the NuttX repository. -examples/keypadtest -^^^^^^^^^^^^^^^^^^^ - - This is a generic keypad test example. It is similar to the USB hidkbd - example, but makes no assumptions about the underlying keyboard interface. - It uses the interfaces of include/nuttx/input/keypad.h. - - CONFIG_EXAMPLES_KEYPADTEST - Selects the keypadtest example (only need - if the mconf/Kconfig tool is used. - - CONFIG_EXAMPLES_KEYPAD_DEVNAME - The name of the keypad device that will - be opened in order to perform the keypad test. Default: "/dev/keypad" - examples/lcdrw ^^^^^^^^^^^^^^ diff --git a/examples/keypadtest/.gitignore b/examples/ipforward/.gitignore similarity index 100% rename from examples/keypadtest/.gitignore rename to examples/ipforward/.gitignore 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/keypadtest/Make.defs b/examples/ipforward/Make.defs similarity index 90% rename from examples/keypadtest/Make.defs rename to examples/ipforward/Make.defs index 74d1fdccd..3cfe21de0 100644 --- a/examples/keypadtest/Make.defs +++ b/examples/ipforward/Make.defs @@ -1,8 +1,8 @@ ############################################################################ -# apps/examples/keypadtest/Make.defs +# apps/examples/ipforward/Make.defs # Adds selected applications to apps/ build # -# Copyright (C) 2015 Gregory Nutt. All rights reserved. +# Copyright (C) 2017 Gregory Nutt. All rights reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -34,6 +34,6 @@ # ############################################################################ -ifeq ($(CONFIG_EXAMPLES_KEYPADTEST),y) -CONFIGURED_APPS += examples/keypadtest +ifeq ($(CONFIG_EXAMPLES_IPFORWARD),y) +CONFIGURED_APPS += examples/ipforward endif diff --git a/examples/keypadtest/Makefile b/examples/ipforward/Makefile similarity index 77% rename from examples/keypadtest/Makefile rename to examples/ipforward/Makefile index 8faaf7341..f2450ddba 100644 --- a/examples/keypadtest/Makefile +++ b/examples/ipforward/Makefile @@ -1,7 +1,7 @@ ############################################################################ -# apps/examples/keypadtest/Makefile +# apps/examples/ipforward/Makefile # -# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. +# Copyright (C) 2017 Gregory Nutt. All rights reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -35,19 +35,22 @@ -include $(TOPDIR)/Make.defs -# Keypad Test Example +# 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 = keypadtest_main.c +MAINSRC = ipforward.c -# helloxx built-in application info - -APPNAME = keypadtest -PRIORITY = SCHED_PRIORITY_DEFAULT -STACKSIZE = 2048 - -CONFIG_XYZ_PROGNAME ?= keypadtest$(EXEEXT) -PROGNAME = $(CONFIG_XYZ_PROGNAME) +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..36b484ffe --- /dev/null +++ b/examples/ipforward/ipforward.c @@ -0,0 +1,743 @@ +/**************************************************************************** + * 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 +#include +#include + +#include "netutils/netlib.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MAX_DEVNAME 8 +#define IPFWD_BUFSIZE CONFIG_NET_TUN_MTU +#define NBYTES_PER_LINE 32 +#define IPFWD_NPACKETS 3 + +#ifdef CONFIG_NET_IPv6 +# define IPADDR_TYPE FAR const uint16_t * +# define IP_HDRLEN IPv6_HDRLEN +#else +# define IPADDR_TYPE uint32_t +# define IP_HDRLEN IPv4_HDRLEN +#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; + pthread_t if_receiver; + pthread_t if_sender; +}; + +struct ipfwd_arg_s +{ + int ia_fd; + IPADDR_TYPE ia_srcipaddr; + IPADDR_TYPE ia_destipaddr; + uint8_t ia_buffer[IPFWD_BUFSIZE]; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ +/* Network addresses: + * + * g_tun0_laddr is the address assigned to the tun0 device. g_tun1_laddr + * is the address assigned to tun1 device. Both are loal addresses can the + * target can received addresses on. + * + * g_netmask is the network mask that defines the networks: tun0 is on + * network 0; tun1 is on network 1. + * + * g_tun0_raddr and g_tun1_raddr are addresses that are not local to the + * target, but should instead be forwarded via the correct network device. + * g_tun0_raddr lies on network 0 and g_tun1_raddr lies on network 1 and so + * should be forwarded from network 0 to network1 by the NuttX IP forwarding + * logic. + */ + +#ifdef CONFIG_NET_IPv6 +static const uint16_t g_tun0_laddr[8] = +{ + HTONS(0x7c00), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0), /* Netork 0 */ + HTONS(0x0097), +}; + +static const uint16_t g_tun1_laddr[8] = +{ + HTONS(0x7c00), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0x0001), /* Netork 1 */ + HTONS(0x0139), +}; + +static const uint16_t g_tun0_raddr[8] = +{ + HTONS(0x7c00), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0), /* Netork 0 */ + HTONS(0x0062), +}; + +static const uint16_t g_tun1_raddr[8] = +{ + HTONS(0x7c00), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0), + HTONS(0x0001), /* Netork 1 */ + HTONS(0x0147), +}; + +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_laddr = HTONL(0x0a000097); /* Netork 0 */ +static const uint32_t g_tun1_laddr = HTONL(0x0a000139); /* Netork 1 */ +static const uint32_t g_tun0_raddr = HTONL(0x0a000062); /* Netork 0 */ +static const uint32_t g_tun1_raddr = HTONL(0x0a000147); /* Netork 1 */ +static const uint32_t g_netmask = HTONL(0xffffff00); +#endif + +static const char g_payload[] = "Hi there, TUN receiver!"; +#ifdef CONFIG_NET_IPv4 +static uint16_t g_ipid; +#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: Checksums + ****************************************************************************/ + +static uint16_t chksum(uint16_t sum, FAR const uint8_t *data, uint16_t len) +{ + FAR const uint8_t *dataptr; + FAR const uint8_t *last_byte; + uint16_t t; + + dataptr = data; + last_byte = data + len - 1; + + while (dataptr < last_byte) + { + /* At least two more bytes */ + + t = ((uint16_t)dataptr[0] << 8) + dataptr[1]; + sum += t; + if (sum < t) + { + sum++; /* carry */ + } + + dataptr += 2; + } + + if (dataptr == last_byte) + { + t = (dataptr[0] << 8) + 0; + sum += t; + if (sum < t) + { + sum++; /* carry */ + } + } + + /* Return sum in host byte order. */ + + return sum; +} + +#ifdef CONFIG_NET_IPv4 +static uint16_t ipv4_chksum(FAR const uint8_t *buffer) +{ + uint16_t sum; + + sum = chksum(0, buffer, IPv4_HDRLEN); + return (sum == 0) ? 0xffff : htons(sum); +} +#endif + +uint16_t tcp_chksum(FAR uint8_t *buffer) +{ +#ifdef CONFIG_NET_IPv6 + FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)buffer; + uint16_t upperlen; + uint16_t sum; + + /* The length reported in the IPv6 header is the length of the payload + * that follows the header. + */ + + upperlen = ((uint16_t)ipv6->len[0] << 8) + ipv6->len[1]; + + /* The checksum is calculated starting with a pseudo-header of IPv6 header + * fields according to the IPv6 standard, which consists of the source + * and destination addresses, the packet length and the next header field. + */ + + sum = upperlen + IP_PROTO_TCP; + + /* Sum IP source and destination addresses. */ + + sum = chksum(sum, (FAR uint8_t *)&ipv6->srcipaddr, 2 * sizeof(net_ipv6addr_t)); + + /* Sum IP payload data. */ + + sum = chksum(sum, &buffer[IPv6_HDRLEN], upperlen); + return (sum == 0) ? 0xffff : htons(sum); +#else + FAR struct ipv4_hdr_s *ipv4 = (FAR struct ipv4_hdr_s *)buffer; + uint16_t upperlen; + uint16_t sum; + + /* The length reported in the IPv4 header is the length of both the IPv4 + * header and the payload that follows the header. We need to subtract + * the size of the IPv4 header to get the size of the payload. + */ + + upperlen = (((uint16_t)(ipv4->len[0]) << 8) + ipv4->len[1]) - IPv4_HDRLEN; + + /* First sum pseudo-header. */ + /* IP protocol and length fields. This addition cannot carry. */ + + sum = upperlen + IP_PROTO_TCP; + + /* Sum IP source and destination addresses. */ + + sum = chksum(sum, (FAR uint8_t *)&ipv4->srcipaddr, 2 * sizeof(in_addr_t)); + + /* Sum IP payload data. */ + + sum = chksum(sum, &buffer[IPv4_HDRLEN], upperlen); + return (sum == 0) ? 0xffff : htons(sum); +#endif +} + +/**************************************************************************** + * Name: ipfwd_dumppkt (and friends) + ****************************************************************************/ + +static char lib_nibble(unsigned char nibble) +{ + if (nibble < 10) + { + return '0' + nibble; + } + else + { + return 'a' + nibble - 10; + } +} + +static void ipfwd_dumpbuffer(FAR uint8_t *buffer, size_t buflen) +{ + unsigned int i; + unsigned int j; + unsigned int k; + + for (i = 0; i < buflen; i += NBYTES_PER_LINE) + { + putchar(' '); + putchar(' '); + + /* Generate hex values: 2 * NBYTES_PER_LINE + 1 bytes */ + + for (j = 0; j < NBYTES_PER_LINE; j++) + { + k = i + j; + + if (j == (NBYTES_PER_LINE / 2)) + { + putchar(' '); + } + + if (k < buflen) + { + putchar(lib_nibble((buffer[k] >> 4) & 0xf)); + putchar(lib_nibble(buffer[k] & 0xf)); + } + else + { + putchar(' '); + putchar(' '); + } + } + + putchar('\n'); + } +} + +static void ipfwd_dumppkt(FAR uint8_t *buffer, size_t buflen) +{ + size_t dumpsize; + + if (buflen <= 0) + { + return; + } + + dumpsize = IP_HDRLEN; + if (dumpsize > buflen) + { + dumpsize = buflen; + } + + printf("IP Header:\n"); + ipfwd_dumpbuffer(buffer, dumpsize); + + buffer += dumpsize; + buflen -= dumpsize; + if (buflen <= 0) + { + return; + } + + dumpsize = TCP_HDRLEN; + if (dumpsize > buflen) + { + dumpsize = buflen; + } + + printf("TCP Header:\n"); + ipfwd_dumpbuffer(buffer, dumpsize); + + buffer += dumpsize; + buflen -= dumpsize; + if (buflen <= 0) + { + return; + } + + printf("Payload:\n"); + ipfwd_dumpbuffer(buffer, buflen); +} + +/**************************************************************************** + * Name: ipfwd_receiver + ****************************************************************************/ + +static FAR void *ipfwd_receiver(FAR void *arg) +{ + FAR struct ipfwd_arg_s *fwd = (FAR struct ipfwd_arg_s *)arg; + ssize_t nread; + int errcode; + int i; + + for (i = 0; i < IPFWD_NPACKETS; i++) + { + nread = read(fwd->ia_fd, fwd->ia_buffer, IPFWD_BUFSIZE); + if (nread < 0) + { + errcode = errno; + fprintf(stderr, "ERROR: read() failed: %d\n", errcode); + break; + } + + printf("Received packet %d: size=%lu\n", i+1, (unsigned long)nread); + ipfwd_dumppkt(fwd->ia_buffer, nread); + } + + return NULL; +} + +/**************************************************************************** + * Name: ipfwd_sender + ****************************************************************************/ + +static FAR void *ipfwd_sender(FAR void *arg) +{ + FAR struct ipfwd_arg_s *fwd = (FAR struct ipfwd_arg_s *)arg; +#ifdef CONFIG_NET_IPv6 + FAR struct ipv6_hdr_s *ipv6; +#else + FAR struct ipv4_hdr_s *ipv4; +#endif + FAR struct tcp_hdr_s *tcp; + FAR char *payload; + size_t paysize; + size_t pktlen; + ssize_t nwritten; + int errcode; + int i; + + paysize = sizeof(g_payload); + + for (i = 0; i < IPFWD_NPACKETS; i++) + { +#ifdef CONFIG_NET_IPv6 + ipv6 = (FAR struct ipv6_hdr_s *)fwd->ia_buffer; + + /* Set up the IPv6 header */ + + ipv6->vtc = 0x60; /* Version/traffic class (MS) */ + ipv6->tcf = 0; /* Traffic class (LS)/Flow label (MS) */ + ipv6->flow = 0; /* Flow label (LS) */ + + /* Length excludes the IPv6 header */ + + pktlen = TCP_HDRLEN + paysize; + ipv6->len[0] = (pktlen >> 8); + ipv6->len[1] = (pktlen & 0xff); + + ipv6->proto = IP_PROTO_TCP; /* Next header */ + ipv6->ttl = 255; /* Hop limit */ + + /* Set source and destination address */ + + net_ipv6addr_copy(ipv6->srcipaddr, fwd->ia_srcipaddr); + net_ipv6addr_copy(ipv6->destipaddr, fwd->ia_destipaddr); + + pktlen = IPv6_HDRLEN + TCP_HDRLEN + paysize; + tcp = (FAR struct tcp_hdr_s *)&fwd->ia_buffer[IPv6_HDRLEN]; +#else + ipv4 = (FAR struct ipv4_hdr_s *)fwd->ia_buffer; + + /* Set up the IPv4 header */ + + ipv4->vhl = 0x45; + ipv4->tos = 0; + + pktlen = IPv4_HDRLEN + TCP_HDRLEN + paysize; + ipv4->len[0] = (pktlen >> 8); + ipv4->len[1] = (pktlen & 0xff); + + ++g_ipid; + ipv4->ipid[0] = g_ipid >> 8; + ipv4->ipid[1] = g_ipid & 0xff; + + ipv4->ipoffset[0] = IP_FLAG_DONTFRAG >> 8; + ipv4->ipoffset[1] = IP_FLAG_DONTFRAG & 0xff; + ipv4->ttl = IP_TTL; + ipv4->proto = IP_PROTO_TCP; + + net_ipv4addr_hdrcopy(ipv4->srcipaddr, fwd->ia_srcipaddr); + net_ipv4addr_hdrcopy(ipv4->destipaddr, fwd->ia_srcipaddr); + + /* Calculate IP checksum. */ + + ipv4->ipchksum = 0; + ipv4->ipchksum = ~(ipv4_chksum(fwd->ia_buffer)); + + tcp = (FAR struct tcp_hdr_s *)&fwd->ia_buffer[IPv4_HDRLEN]; +#endif + + /* Set up the TCP header. NOTE: Most of the elements are irrelevant + * in this test. The forwarding is L2 layer only and the L3 header + * content is not used in the forwarding. + */ + + memset(tcp, 0, sizeof(struct tcp_hdr_s)); + + tcp->srcport = HTONS(0x1234); + tcp->destport = HTONS(0xabcd); + tcp->tcpoffset = (TCP_HDRLEN / 4) << 4; + + payload = (FAR char *)tcp + TCP_HDRLEN; + memcpy(payload, g_payload, paysize); + + tcp->tcpchksum = ~tcp_chksum(fwd->ia_buffer); + + printf("Sending packet %d: size=%lu\n", i+1, (unsigned long)pktlen); + ipfwd_dumppkt(fwd->ia_buffer, pktlen); + + nwritten = write(fwd->ia_fd, fwd->ia_buffer, pktlen); + if (nwritten < 0) + { + errcode = errno; + fprintf(stderr, "ERROR: write() failed: %d\n", errcode); + break; + } + + printf(" %lu bytes sent\n", (unsigned long)nwritten); + } + + return NULL; +} + +/**************************************************************************** + * 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; + struct ipfwd_arg_s tun0arg; + struct ipfwd_arg_s tun1arg; + FAR void *value; + 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_laddr, g_netmask); + if (ret < 0) + { + fprintf(stderr, "ERROR: ipfwd_netconfig for tun0 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_tun1, g_tun1_laddr, g_netmask); + if (ret < 0) + { + fprintf(stderr, "ERROR: ipfwd_netconfig tun1 failed: %d\n", ret); + errcode = EXIT_FAILURE; + goto errout_with_tun1; + } + + /* Start receiver thread on tun1 */ + + tun1arg.ia_fd = fwd.if_tun1.it_fd; + tun1arg.ia_srcipaddr = g_tun1_raddr; + tun1arg.ia_destipaddr = g_tun0_raddr; + + ret = pthread_create(&fwd.if_receiver, NULL, ipfwd_receiver, &tun1arg); + if (ret != 0) + { + fprintf(stderr, "ERROR: pthread_create() failed for receiver: %d\n", ret); + errcode = EXIT_FAILURE; + goto errout_with_tun1; + } + + /* Start sender thread on tun0 */ + + tun0arg.ia_fd = fwd.if_tun0.it_fd; + tun0arg.ia_srcipaddr = g_tun0_raddr; + tun0arg.ia_destipaddr = g_tun1_raddr; + + ret = pthread_create(&fwd.if_sender, NULL, ipfwd_sender, &tun0arg); + if (ret != 0) + { + fprintf(stderr, "ERROR: pthread_create() failed for sender: %d\n", ret); + errcode = EXIT_FAILURE; + goto errout_with_receiver; + } + + /* Wait for sender thread to terminate */ + + ret = pthread_join(fwd.if_sender, &value); + if (ret != OK) + { + fprintf(stderr, "ERROR: pthread_join() failed for sender: %d\n", ret); + } + +errout_with_receiver: + /* Wait for receiver thread to terminate */ + + pthread_kill(fwd.if_receiver, 9); + ret = pthread_join(fwd.if_receiver, &value); + if (ret != OK) + { + fprintf(stderr, "ERROR: pthread_join() failed for receiver: %d\n", ret); + } + +errout_with_tun1: + close(fwd.if_tun1.it_fd); +errout_with_tun0: + close(fwd.if_tun0.it_fd); +errout: + return errcode; +} diff --git a/examples/keypadtest/Kconfig b/examples/keypadtest/Kconfig deleted file mode 100644 index 08408ae56..000000000 --- a/examples/keypadtest/Kconfig +++ /dev/null @@ -1,29 +0,0 @@ -# -# For a description of the syntax of this configuration file, -# see the file kconfig-language.txt in the NuttX tools repository. -# - -config EXAMPLES_KEYPADTEST - bool "Keypad test example program" - default n - ---help--- - Enable the Keypad test example programe - -if EXAMPLES_KEYPADTEST - - config EXAMPLES_KEYPAD_DEVNAME - string "Keypad Device Name" - default "/dev/keypad" - ---help--- - The name of the keypad device that will be opened in order to perform - the keypad test. Default: "/dev/keypad" - -config EXAMPLES_KEYPADTEST_ENCODED - bool "Use Keyboard CODEC" - default n - ---help--- - Use the keyboard encoded/decoder to pass control information from - the keypad driver to the keypad test. This is the keyboard CODEC - defined in nuttx/input/kbd_codec.h. - -endif diff --git a/examples/keypadtest/keypadtest_main.c b/examples/keypadtest/keypadtest_main.c deleted file mode 100644 index ea8863755..000000000 --- a/examples/keypadtest/keypadtest_main.c +++ /dev/null @@ -1,259 +0,0 @@ -/**************************************************************************** - * examples/keypadtest/keypadtest_main.c - * - * Copyright (C) 2011 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 Gregory Nutt 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 - -#ifdef CONFIG_EXAMPLES_KEYPADTEST_ENCODED -# include -# include -# include -# include -#endif - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ -/* Configuration ************************************************************/ - -/* Sanity checking */ - -/* Provide some default values for other configuration settings */ - -#ifndef CONFIG_EXAMPLES_KEYPAD_DEVNAME -# define CONFIG_EXAMPLES_KEYPAD_DEVNAME "/dev/keypad" -#endif - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -#ifdef CONFIG_EXAMPLES_KEYPADTEST_ENCODED -struct keypad_instream_s -{ - struct lib_instream_s stream; - FAR char *buffer; - ssize_t nbytes; -}; -#endif - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: keypad_getstream - * - * Description: - * Get one character from the keyboard. - * - ****************************************************************************/ - -#ifdef CONFIG_EXAMPLES_KEYPADTEST_ENCODED -static int keypad_getstream(FAR struct lib_instream_s *this) -{ - FAR struct keypad_instream_s *kbdstream = (FAR struct keypad_instream_s *)this; - - DEBUGASSERT(kbdstream && kbdstream->buffer); - if (kbdstream->nbytes > 0) - { - kbdstream->nbytes--; - kbdstream->stream.nget++; - return (int)*kbdstream->buffer++; - } - - return EOF; -} -#endif - -/**************************************************************************** - * Name: keypad_decode - * - * Description: - * Decode encoded keyboard input - * - ****************************************************************************/ - -#ifdef CONFIG_EXAMPLES_KEYPADTEST_ENCODED -static void keypad_decode(FAR char *buffer, ssize_t nbytes) -{ - struct keypad_instream_s kbdstream; - struct kbd_getstate_s state; - uint8_t ch; - int ret; - - /* Initialize */ - - memset(&state, 0, sizeof(struct kbd_getstate_s)); - kbdstream.stream.get = keypad_getstream; - kbdstream.stream.nget = 0; - kbdstream.buffer = buffer; - kbdstream.nbytes = nbytes; - - /* Loop until all of the bytes have been consumed. We implicitly assume - * that the escaped sequences do not cross buffer boundaries. That - * might be true if the read buffer were small or the data rates high. - */ - - for (;;) - { - /* Decode the next thing from the buffer */ - - ret = kbd_decode((FAR struct lib_instream_s *)&kbdstream, &state, &ch); - if (ret == KBD_ERROR) - { - break; - } - - /* Normal data? Or special key? */ - - switch (ret) - { - case KBD_PRESS: /* Key press event */ - printf("Normal Press: %c [%02x]\n", isprint(ch) ? ch : '.', ch); - break; - - case KBD_RELEASE: /* Key release event */ - printf("Normal Release: %c [%02x]\n", isprint(ch) ? ch : '.', ch); - break; - - case KBD_SPECPRESS: /* Special key press event */ - printf("Special Press: %d\n", ch); - break; - - case KBD_SPECREL: /* Special key release event */ - printf("Special Release: %d\n", ch); - break; - - case KBD_ERROR: /* Error or end-of-file */ - printf("EOF: %d\n", ret); - break; - - default: - printf("Unexpected: %d\n", ret); - break; - } - } - - fflush(stdout); -} -#endif - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: keypadtest_main - ****************************************************************************/ - -#ifdef CONFIG_BUILD_KERNEL -int main(int argc, FAR char *argv[]) -#else -int keypadtest_main(int argc, char *argv[]) -#endif -{ - char buffer[256]; - ssize_t nbytes; - int fd; - int ret; - - /* First, register the keyboard device(s) */ - - printf("keypadtest_main: Register keyboard device\n"); - ret = keypad_kbdinit(); - if (ret != OK) - { - printf("keypadtest_main: Failed to register the KBD class\n"); - fflush(stdout); - return 1; - } - - /* Open the configured keyboard device. */ - - printf("keypadtest_main: Opening device %s\n", CONFIG_EXAMPLES_KEYPAD_DEVNAME); - fd = open(CONFIG_EXAMPLES_KEYPAD_DEVNAME, O_RDONLY); - if (fd < 0) - { - printf("keypadtest_main: open() failed: %d\n", errno); - fflush(stdout); - return 1; - } - - printf("keypadtest_main: Device %s opened\n", CONFIG_EXAMPLES_KEYPAD_DEVNAME); - fflush(stdout); - - /* Loop until there is a read failure */ - - do - { - /* Read a buffer of data */ - - nbytes = read(fd, buffer, 256); - if (nbytes > 0) - { - /* On success, echo the buffer to stdout */ -#ifdef CONFIG_EXAMPLES_KEYPADTEST_ENCODED - keypad_decode(buffer, nbytes); -#else - (void)write(1, buffer, nbytes); -#endif - } - } - while (nbytes >= 0); - - printf("keypadtest_main: Closing device %s: %d\n", CONFIG_EXAMPLES_KEYPAD_DEVNAME, (int)nbytes); - fflush(stdout); - close(fd); - return 0; -} diff --git a/examples/nettest/nettest_initinit.c b/examples/nettest/nettest_netinit.c similarity index 100% rename from examples/nettest/nettest_initinit.c rename to examples/nettest/nettest_netinit.c diff --git a/interpreters/ficl/Makefile b/interpreters/ficl/Makefile index bc3ae7c43..e99f39816 100644 --- a/interpreters/ficl/Makefile +++ b/interpreters/ficl/Makefile @@ -78,7 +78,7 @@ SRC_DEPPATH = --dep-path src VPATH = src:$(FICL_SUBDIR) all: .built -.PHONY: debug context depend clean distclean +.PHONY: debug context depend clean distclean preconfig $(AOBJS): %$(OBJEXT): %.S $(call ASSEMBLE, $<, $@) @@ -113,6 +113,6 @@ distclean: clean $(call DELFILE, Make.dep) $(call DELFILE, .depend) --include Make.dep -.PHONY: preconfig preconfig: + +-include Make.dep diff --git a/nshlib/nsh_command.c b/nshlib/nsh_command.c index cca237151..4f51ca813 100644 --- a/nshlib/nsh_command.c +++ b/nshlib/nsh_command.c @@ -474,7 +474,7 @@ static const struct cmdmap_s g_cmdmap[] = #if defined(CONFIG_NSH_TELNET) && !defined(CONFIG_NSH_DISABLE_TELNETD) #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) - {"telnetd", cmd_telnetd, 2, 2, [ipv4|ipv6] }, + {"telnetd", cmd_telnetd, 2, 2, "[ipv4|ipv6]" }, #else {"telnetd", cmd_telnetd, 1, 1, NULL }, #endif diff --git a/platform/Makefile b/platform/Makefile index 8f562f779..cc85b4833 100644 --- a/platform/Makefile +++ b/platform/Makefile @@ -46,11 +46,11 @@ include $(APPDIR)$(DELIM)Make.defs ifeq ($(DIRLINK),) ifeq ($(CONFIG_WINDOWS_NATIVE),y) -DIRLINK = $(TOPDIR)/tools/link.bat -DIRUNLINK = $(TOPDIR)/tools/unlink.bat +DIRLINK = $(TOPDIR)$(DELIM)tools$(DELIM)link.bat +DIRUNLINK = $(TOPDIR)$(DELIM)tools$(DELIM)unlink.bat else -DIRLINK = $(TOPDIR)/tools/link.sh -DIRUNLINK = $(TOPDIR)/tools/unlink.sh +DIRLINK = $(TOPDIR)$(DELIM)tools$(DELIM)link.sh +DIRUNLINK = $(TOPDIR)$(DELIM)tools$(DELIM)unlink.sh endif endif @@ -82,8 +82,11 @@ CSRCS = -include $(GNUDIR)$(DELIM)Make.defs -include $(PLATFORMDIR)$(DELIM)Make.defs -AOBJS = $(patsubst %.S, bin$(DELIM)%$(OBJEXT), $(ASRCS)) -COBJS = $(patsubst %.c, bin$(DELIM)%$(OBJEXT), $(CSRCS)) +# REVISIT: Backslash causes problems in $(A/COBJS) patsubst +# AOBJS = $(patsubst %.S, bin$(DELIM)%$(OBJEXT), $(ASRCS)) +# COBJS = $(patsubst %.c, bin$(DELIM)%$(OBJEXT), $(CSRCS)) +AOBJS = $(patsubst %.S, bin/%$(OBJEXT), $(ASRCS)) +COBJS = $(patsubst %.c, bin/%$(OBJEXT), $(CSRCS)) SRCS = $(ASRCS) $(CSRCS) OBJS = $(AOBJS) $(COBJS) @@ -104,12 +107,16 @@ all: .built .PHONY: context .depend depend clean distclean ifneq ($(ASRCS),) -$(AOBJS): bin$(DELIM)%$(OBJEXT): %.S +# REVISIT: Backslash causes problems in $(AOBJS) target +# $(AOBJS): bin$(DELIM)%$(OBJEXT): %.S +$(AOBJS): bin/%$(OBJEXT): %.S $(call ASSEMBLE, $<, $@) endif ifneq ($(CSRCS),) -$(COBJS): bin$(DELIM)%$(OBJEXT): %.c +# REVISIT: Backslash causes problems in $(COBJS) target +# $(COBJS): bin$(DELIM)%$(OBJEXT): %.c +$(COBJS): bin/%$(OBJEXT): %.c $(call COMPILE, $<, $@) endif diff --git a/system/dhcpc/Makefile b/system/dhcpc/Makefile index 52e937d6e..25c5bafde 100644 --- a/system/dhcpc/Makefile +++ b/system/dhcpc/Makefile @@ -91,7 +91,7 @@ VPATH = all: .built .PHONY: clean depend distclean -$(OBJS) $(RENEW_MAINOBJ): %$(OBJEXT): %.c +$(RENEW_OBJS) $(RENEW_MAINOBJ): %$(OBJEXT): %.c $(call COMPILE, $<, $@) .built: $(OBJS) diff --git a/tools/mkkconfig.bat b/tools/mkkconfig.bat index e7865cca2..fca5597f7 100755 --- a/tools/mkkconfig.bat +++ b/tools/mkkconfig.bat @@ -76,7 +76,8 @@ REM ) ) REM Get the current directory -SET APPSDIR=%~dp0 +SET APPSDIR=%cd% +SET APPSDIR=%APPSDIR:\=/% Echo # > %kconfig% Echo # For a description of the syntax of this configuration file, >> %kconfig% @@ -87,7 +88,7 @@ Echo # >> %kconfig% Echo[ >> %kconfig% IF %menu% NEQ "" ( - Echo menu "%menu%" >> %kconfig% + Echo menu %menu% >> %kconfig% ) DIR /B /A:D >_tmp_.dat