diff --git a/examples/Kconfig b/examples/Kconfig index 9b14a5bca..81dd38e79 100644 --- a/examples/Kconfig +++ b/examples/Kconfig @@ -5,6 +5,7 @@ source "$APPSDIR/examples/adc/Kconfig" source "$APPSDIR/examples/bastest/Kconfig" +source "$APPSDIR/examples/bridge/Kconfig" source "$APPSDIR/examples/buttons/Kconfig" source "$APPSDIR/examples/can/Kconfig" source "$APPSDIR/examples/cc3000/Kconfig" diff --git a/examples/Make.defs b/examples/Make.defs index 050eefef5..d22a56b89 100644 --- a/examples/Make.defs +++ b/examples/Make.defs @@ -42,6 +42,10 @@ ifeq ($(CONFIG_EXAMPLES_BASTEST),y) CONFIGURED_APPS += examples/bastest endif +ifeq ($(CONFIG_EXAMPLES_BRIDGE),y) +CONFIGURED_APPS += examples/bridge +endif + ifeq ($(CONFIG_EXAMPLES_BUTTONS),y) CONFIGURED_APPS += examples/buttons endif diff --git a/examples/Makefile b/examples/Makefile index b2e04be81..3beef72a5 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -37,8 +37,8 @@ # Sub-directories -SUBDIRS = adc bastest buttons can cc3000 cpuhog cxxtest dhcpd discover elf -SUBDIRS += flash_test ftpc ftpd hello helloxx hidkbd igmp i2schar json +SUBDIRS = adc bastest bridge buttons can cc3000 cpuhog cxxtest dhcpd discover +SUBDIRS += elf flash_test ftpc ftpd hello helloxx hidkbd igmp i2schar json SUBDIRS += keypadtest lcdrw mm modbus mount mtdpart mtdrwb netpkt nettest SUBDIRS += nrf24l01_term nsh null nx nxterm nxffs nxflat nxhello nximage SUBDIRS += nxlines nxtext ostest pashello pipe poll posix_spawn pwm qencoder @@ -53,7 +53,7 @@ SUBDIRS += usbserial usbterm watchdog webserver wget wgetjson xmlrpc CNTXTDIRS = pwm ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) -CNTXTDIRS += adc can cc3000 cpuhog cxxtest dhcpd discover flash_test ftpd +CNTXTDIRS += adc bridge can cc3000 cpuhog cxxtest dhcpd discover flash_test ftpd CNTXTDIRS += hello helloxx i2schar json keypadtestmodbus lcdrw mtdpart mtdrwb CNTXTDIRS += netpkt nettest nx nxhello nximage nxlines nxtext nrf24l01_term CNTXTDIRS += ostest random relays qencoder serialblasterslcd serialrx diff --git a/examples/README.txt b/examples/README.txt index c9b637439..dbb59adde 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -64,6 +64,47 @@ examples/bastest that will hold the ROMFS file system containing the BASIC files to be tested. Default: "/dev/ram0" +examples/bridge +^^^^^^^^^^^^^^^ + + A simple test of a system with multiple networks. It simply echoes all UDP + packets received on network 1 and network 2 to network 2 and network 1, + respectively. Interface 1 and interface may or may not lie on the same + network. + + CONFIG_EXAMPLES_BRIDGE - Enables the simple UDP bridge test + + There identical configurations for each of the two networks, NETn where n + refers to the network being configured n={1,2}. Let 'm' refer to the + other network. + + CONFIG_EXAMPLES_BRIDGE_NETn_IFNAME - The register name of the network n + device. Must match the previously registered driver name and must + not be the same as other network device name, + CONFIG_EXAMPLES_BRIDGE_NETm_IFNAME + CONFIG_EXAMPLES_BRIDGE_NETn_RECVPORT - Network n listen port number + CONFIG_EXAMPLES_BRIDGE_NETn_SNDPORT - Network 2 send port number + CONFIG_EXAMPLES_BRIDGE_NETn_IOBUFIZE - Size of the network n UDP + send/receive I/O buffer + CONFIG_EXAMPLES_BRIDGE_NETn_STACKSIZE - Network n daemon stacksize + CONFIG_EXAMPLES_BRIDGE_NETn_PRIORITY - Network n daemon task priority + + If used as a NSH add-on, then it is assumed that initialization of both + networks was performed externally prior to the time that this test was + started. Otherwise, the following options are available: + + CONFIG_EXAMPLES_BRIDGE_NETn_NOMAC - Select of the the network n hardware + does not have a built-in MAC address. If selected, the MAC address + provided by CONFIG_EXAMPLES_BRIDGE_NETn_MACADDR will be used to assign + the MAC address to the network n device. + CONFIG_EXAMPLES_BRIDGE_NETn_DHCPC - Use DHCP Client to get the network n + IP address. + CONFIG_EXAMPLES_BRIDGE_NETn_IPADDR -- If CONFIG_EXAMPLES_BRIDGE_NETn_DHCPC + is not selected, then this is the fixed IP address for network n. + CONFIG_EXAMPLES_BRIDGE_NETn_DRIPADDR - Netweork n default router IP + address (Gateway) + CONFIG_EXAMPLES_BRIDGE_NETn_NETMASK - Network n mask. + examples/buttons ^^^^^^^^^^^^^^^^ diff --git a/examples/bridge/.gitignore b/examples/bridge/.gitignore new file mode 100644 index 000000000..fa1ec7579 --- /dev/null +++ b/examples/bridge/.gitignore @@ -0,0 +1,11 @@ +/Make.dep +/.depend +/.built +/*.asm +/*.obj +/*.rel +/*.lst +/*.sym +/*.adb +/*.lib +/*.src diff --git a/examples/bridge/Kconfig b/examples/bridge/Kconfig new file mode 100644 index 000000000..f3ee296be --- /dev/null +++ b/examples/bridge/Kconfig @@ -0,0 +1,170 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_BRIDGE + bool "UDP bridge example" + default n + depends on NET_UDP && NETDEV_MULTINIC && !NET_IPv6 + ---help--- + Simple test of a system with multiple networks. It simply echoes all + UDP packets received on network 1 and network 2 to network 2 and + network 1, respectively. Interface 1 and interface may or may not + lie on the same network. + + If used as a NSH add-on, then it is assumed that initialization of + both networks was performed externally prior to the time that this + test was started. + +if EXAMPLES_BRIDGE + +comment "Network 1 configuration" + +config EXAMPLES_BRIDGE_NET1_IFNAME + string "Device name" + default "eth0" + ---help--- + The register name of the network 1 device. Must match the previously + registered driver name and must not be the same as + EXAMPLES_BRIDGE_NET2_IFNAME + +config EXAMPLES_BRIDGE_NET1_RECVPORT + int "UDP receive port" + default 5471 + ---help--- + Network 1 listen port number + +config EXAMPLES_BRIDGE_NET1_SNDPORT + int "UDP send port" + default 5472 + ---help--- + Network 2 send port number + +config EXAMPLES_BRIDGE_NET1_IOBUFIZE + int "UDP I/O buffer size" + default 1024 + ---help--- + Size of the UDP send/receive I/O buffer + +if !NSH_BUILTIN_APPS + +config EXAMPLES_BRIDGE_NET1_DHCPC + bool "DHCP Client" + default n + select NETUTILS_DHCPC + select NETUTILS_DNSCLIENT + +config EXAMPLES_BRIDGE_NET1_NOMAC + bool "Use Canned MAC Address" + default n + ---help--- + Select if the hardware has no built-in MAC address. + +config EXAMPLES_BRIDGE_NET1_MACADDR + hex "Canned MAC address" + default 0x00e0deadbeef + depends on EXAMPLES_BRIDGE_NET1_NOMAC + ---help--- + If the hardware has no built-in MAC address then the fixed, + software-assigned MAC address MAC address must provided + with this selection. + +config EXAMPLES_BRIDGE_NET1_IPADDR + hex "IP address" + default 0x0a000002 + depends on !EXAMPLES_BRIDGE_NET1_DHCPC + +config EXAMPLES_BRIDGE_NET1_DRIPADDR + hex "Default Router IP address (Gateway)" + default 0x0a000001 + +config EXAMPLES_BRIDGE_NET1_NETMASK + hex "Network Mask" + default 0xffffff00 + +endif # !NSH_BUILTIN_APPS + +config EXAMPLES_BRIDGE_NET1_STACKSIZE + int "Network 1 daemon stacksize" + default 2048 + +config EXAMPLES_BRIDGE_NET1_PRIORITY + int "Network 1 daemon task priority" + default 100 + +comment "Network 2 configuration" + +config EXAMPLES_BRIDGE_NET2_IFNAME + string "Device name" + default "eth1" + ---help--- + The register name of the network 2 device. Must match the previously + registered driver name and must not be the same as + EXAMPLES_BRIDGE_NET2_IFNAME + +config EXAMPLES_BRIDGE_NET2_RECVPORT + int "UDP receive port" + default 5471 + ---help--- + Network 1 listen port number + +config EXAMPLES_BRIDGE_NET2_SNDPORT + int "UDP send port" + default 5472 + ---help--- + Network 2 send port number + +config EXAMPLES_BRIDGE_NET2_IOBUFIZE + int "UDP I/O buffer size" + default 1024 + ---help--- + Size of the UDP send/receive I/O buffer + +if !NSH_BUILTIN_APPS + +config EXAMPLES_BRIDGE_NET2_DHCPC + bool "DHCP Client" + default n + select NETUTILS_DHCPC + select NETUTILS_DNSCLIENT + +config EXAMPLES_BRIDGE_NET2_NOMAC + bool "Use Canned MAC Address" + default n + ---help--- + Select if the hardware has no built-in MAC address. + +config EXAMPLES_BRIDGE_NET2_MACADDR + hex "Canned MAC address" + default 0x00e0f00dface + depends on EXAMPLES_BRIDGE_NET2_NOMAC + ---help--- + If the hardware has no built-in MAC address then the fixed, + software-assigned MAC address MAC address must provided + with this selection. + +config EXAMPLES_BRIDGE_NET2_IPADDR + hex "IP address" + default 0x0a000003 + depends on !EXAMPLES_BRIDGE_NET2_DHCPC + +config EXAMPLES_BRIDGE_NET2_DRIPADDR + hex "Default Router IP address (Gateway)" + default 0x0a000001 + +config EXAMPLES_BRIDGE_NET2_NETMASK + hex "Network Mask" + default 0xffffff00 + +endif # !NSH_BUILTIN_APPS + +config EXAMPLES_BRIDGE_NET2_STACKSIZE + int "Network 2 daemon stacksize" + default 2048 + +config EXAMPLES_BRIDGE_NET2_PRIORITY + int "Network 2 daemon task priority" + default 100 + +endif # EXAMPLES_BRIDGE diff --git a/examples/bridge/Makefile b/examples/bridge/Makefile new file mode 100644 index 000000000..62521e46c --- /dev/null +++ b/examples/bridge/Makefile @@ -0,0 +1,136 @@ +############################################################################ +# apps/examples/bridge/Makefile +# +# Copyright (C) 2014 Gregory Nutt. All rights reserved. +# +# Authors: 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)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# Discover built-in application info + +APPNAME = bridge +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +ASRCS = +CSRCS = +MAINSRC = bridge_main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) +MAINOBJ = $(MAINSRC:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) $(MAINSRC) +OBJS = $(AOBJS) $(COBJS) + +ifneq ($(CONFIG_BUILD_KERNEL),y) + OBJS += $(MAINOBJ) +endif + +ifeq ($(CONFIG_WINDOWS_NATIVE),y) + BIN = ..\..\libapps$(LIBEXT) +else +ifeq ($(WINTOOL),y) + BIN = ..\\..\\libapps$(LIBEXT) +else + BIN = ../../libapps$(LIBEXT) +endif +endif + +ifeq ($(WINTOOL),y) + INSTALL_DIR = "${shell cygpath -w $(BIN_DIR)}" +else + INSTALL_DIR = $(BIN_DIR) +endif + +CONFIG_EXAMPLE_BRIDGE_PROGNAME ?= bridge$(EXEEXT) +PROGNAME = $(CONFIG_EXAMPLE_BRIDGE_PROGNAME) + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS) $(MAINOBJ): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + $(call ARCHIVE, $(BIN), $(OBJS)) + @touch .built + +ifeq ($(CONFIG_BUILD_KERNEL),y) +$(BIN_DIR)$(DELIM)$(PROGNAME): $(OBJS) $(MAINOBJ) + @echo "LD: $(PROGNAME)" + $(Q) $(LD) $(LDELFFLAGS) $(LDLIBPATH) -o $(INSTALL_DIR)$(DELIM)$(PROGNAME) $(ARCHCRT0OBJ) $(MAINOBJ) $(LDLIBS) + $(Q) $(NM) -u $(INSTALL_DIR)$(DELIM)$(PROGNAME) + +install: $(BIN_DIR)$(DELIM)$(PROGNAME) + +else +install: + +endif + +ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) +$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + +context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat +else +context: +endif + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + $(call DELFILE, .built) + $(call CLEAN) + +distclean: clean + $(call DELFILE, Make.dep) + $(call DELFILE, .depend) + +-include Make.dep diff --git a/examples/bridge/bridge_main.c b/examples/bridge/bridge_main.c new file mode 100644 index 000000000..b7062f643 --- /dev/null +++ b/examples/bridge/bridge_main.c @@ -0,0 +1,690 @@ +/**************************************************************************** + * examples/bridge/bridge_main.c + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * + * Authors: 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 + +#if defined(CONFIG_EXAMPLES_BRIDGE_NET1_DHCPC) || \ + defined(CONFIG_EXAMPLES_BRIDGE_NET2_DHCPC) +# include +# include +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define BRIDGE_MAXLINE 64 +#define BRIDGE_POLLTIMEOUT 10000 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static in_addr_t g_net1_ipaddr; +static in_addr_t g_net2_ipaddr; +static uint8_t g_net1_buffer[CONFIG_EXAMPLES_BRIDGE_NET1_IOBUFIZE]; +static uint8_t g_net2_buffer[CONFIG_EXAMPLES_BRIDGE_NET2_IOBUFIZE]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: briget_net1_setup + ****************************************************************************/ + +static int briget_net1_setup(void) +{ + /* If this task is executed as an NSH built-in function, then the + * network has already been configured by NSH's start-up logic. + */ + +#ifndef CONFIG_NSH_BUILTIN_APPS + struct in_addr addr; +#if defined(CONFIG_EXAMPLES_BRIDGE_NET1_DHCPC) || \ + defined(CONFIG_EXAMPLES_BRIDGE_NET1_NOMAC) + uint8_t mac[IFHWADDRLEN]; +#endif +#ifdef CONFIG_EXAMPLES_BRIDGE_NET1_DHCPC + struct dhcpc_state ds; + void *handle; +#endif + +printf("NET1: Configuring %s\n", CONFIG_EXAMPLES_BRIDGE_NET1_IFNAME); + +/* Many embedded network interfaces must have a software assigned MAC */ + +#ifdef CONFIG_EXAMPLES_BRIDGE_NET1_NOMAC + mac[0] = (CONFIG_EXAMPLES_BRIDGE_NET1_MACADDR >> (8 * 5)) & 0xff; + mac[1] = (CONFIG_EXAMPLES_BRIDGE_NET1_MACADDR >> (8 * 4)) & 0xff; + mac[2] = (CONFIG_EXAMPLES_BRIDGE_NET1_MACADDR >> (8 * 3)) & 0xff; + mac[3] = (CONFIG_EXAMPLES_BRIDGE_NET1_MACADDR >> (8 * 2)) & 0xff; + mac[4] = (CONFIG_EXAMPLES_BRIDGE_NET1_MACADDR >> (8 * 1)) & 0xff; + mac[5] = (CONFIG_EXAMPLES_BRIDGE_NET1_MACADDR >> (8 * 0)) & 0xff; + netlib_setmacaddr(CONFIG_EXAMPLES_BRIDGE_NET1_IFNAME, mac); +#endif + + /* Set up our host address */ + +#ifdef CONFIG_EXAMPLES_BRIDGE_NET1_DHCPC + addr.s_addr = 0; +#else + addr.s_addr = HTONL(CONFIG_EXAMPLES_BRIDGE_NET1_IPADDR); +#endif + netlib_sethostaddr(CONFIG_EXAMPLES_BRIDGE_NET1_IFNAME, &addr); + + /* Set up the default router address */ + + addr.s_addr = HTONL(CONFIG_EXAMPLES_BRIDGE_NET1_DRIPADDR); + netlib_setdraddr(CONFIG_EXAMPLES_BRIDGE_NET1_IFNAME, &addr); + + /* Setup the subnet mask */ + + addr.s_addr = HTONL(CONFIG_EXAMPLES_BRIDGE_NET1_NETMASK); + netlib_setnetmask(CONFIG_EXAMPLES_BRIDGE_NET1_IFNAME, &addr); + +#ifdef CONFIG_EXAMPLES_BRIDGE_NET1_DHCPC + /* Set up the resolver */ + + dns_bind(); + + /* Get the MAC address of the NIC */ + + netlib_getmacaddr(CONFIG_EXAMPLES_BRIDGE_NET1_IFNAME, mac); + + /* Set up the DHCPC modules */ + + handle = dhcpc_open(&mac, IFHWADDRLEN); + + /* Get an IP address. Note: there is no logic here for renewing the address in this + * example. The address should be renewed in ds.lease_time/2 seconds. + */ + + if (!handle) + { + fprintf(stderr, "NET1 ERROR: dhcpc_open failed\n"); + return ERROR; + } + + if (dhcpc_request(handle, &ds) != OK) + { + fprintf(stderr, "NET1 ERROR: dhcpc_request failed\n"); + return ERROR; + } + + netlib_sethostaddr(CONFIG_EXAMPLES_BRIDGE_NET1_IFNAME, &ds.ipaddr); + + if (ds.netmask.s_addr != 0) + { + netlib_setnetmask(CONFIG_EXAMPLES_BRIDGE_NET1_IFNAME, &ds.netmask); + } + + if (ds.default_router.s_addr != 0) + { + netlib_setdraddr(CONFIG_EXAMPLES_BRIDGE_NET1_IFNAME, &ds.default_router); + } + + if (ds.dnsaddr.s_addr != 0) + { + dns_setserver(&ds.dnsaddr); + } + + dhcpc_close(handle); + printf("NET1: Assigned IP: %s\n", inet_ntoa(ds.ipaddr)); + + /* Save the IP address in network order */ + + g_net1_ipaddr = ds.ipaddr; + +#else + /* Save the IP address in network order */ + + g_net1_ipaddr = HTONL(CONFIG_EXAMPLES_BRIDGE_NET1_IPADDR); + +#endif /* CONFIG_EXAMPLES_BRIDGE_NET1_DHCPC */ +#endif /* CONFIG_NSH_BUILTIN_APPS */ + + return OK; +} + +/**************************************************************************** + * Name: briget_net2_setup + ****************************************************************************/ + +static int briget_net2_setup(void) +{ + /* If this task is executed as an NSH built-in function, then the + * network has already been configured by NSH's start-up logic. + */ + +#ifndef CONFIG_NSH_BUILTIN_APPS + struct in_addr addr; +#if defined(CONFIG_EXAMPLES_BRIDGE_NET2_DHCPC) || \ + defined(CONFIG_EXAMPLES_BRIDGE_NET2_NOMAC) + uint8_t mac[IFHWADDRLEN]; +#endif +#ifdef CONFIG_EXAMPLES_BRIDGE_NET2_DHCPC + struct dhcpc_state ds; + void *handle; +#endif + +printf("NET2: Configuring %s\n", CONFIG_EXAMPLES_BRIDGE_NET2_IFNAME); + +/* Many embedded network interfaces must have a software assigned MAC */ + +#ifdef CONFIG_EXAMPLES_BRIDGE_NET2_NOMAC + mac[0] = (CONFIG_EXAMPLES_BRIDGE_NET2_MACADDR >> (8 * 5)) & 0xff; + mac[1] = (CONFIG_EXAMPLES_BRIDGE_NET2_MACADDR >> (8 * 4)) & 0xff; + mac[2] = (CONFIG_EXAMPLES_BRIDGE_NET2_MACADDR >> (8 * 3)) & 0xff; + mac[3] = (CONFIG_EXAMPLES_BRIDGE_NET2_MACADDR >> (8 * 2)) & 0xff; + mac[4] = (CONFIG_EXAMPLES_BRIDGE_NET2_MACADDR >> (8 * 1)) & 0xff; + mac[5] = (CONFIG_EXAMPLES_BRIDGE_NET2_MACADDR >> (8 * 0)) & 0xff; + netlib_setmacaddr(CONFIG_EXAMPLES_BRIDGE_NET2_IFNAME, mac); +#endif + + /* Set up our host address */ + +#ifdef CONFIG_EXAMPLES_BRIDGE_NET2_DHCPC + addr.s_addr = 0; +#else + addr.s_addr = HTONL(CONFIG_EXAMPLES_BRIDGE_NET2_IPADDR); +#endif + netlib_sethostaddr(CONFIG_EXAMPLES_BRIDGE_NET2_IFNAME, &addr); + + /* Set up the default router address */ + + addr.s_addr = HTONL(CONFIG_EXAMPLES_BRIDGE_NET2_DRIPADDR); + netlib_setdraddr(CONFIG_EXAMPLES_BRIDGE_NET2_IFNAME, &addr); + + /* Setup the subnet mask */ + + addr.s_addr = HTONL(CONFIG_EXAMPLES_BRIDGE_NET2_NETMASK); + netlib_setnetmask(CONFIG_EXAMPLES_BRIDGE_NET2_IFNAME, &addr); + +#ifdef CONFIG_EXAMPLES_BRIDGE_NET2_DHCPC + /* Set up the resolver */ + + dns_bind(); + + /* Get the MAC address of the NIC */ + + netlib_getmacaddr(CONFIG_EXAMPLES_BRIDGE_NET2_IFNAME, mac); + + /* Set up the DHCPC modules */ + + handle = dhcpc_open(&mac, IFHWADDRLEN); + + /* Get an IP address. Note: there is no logic here for renewing the address in this + * example. The address should be renewed in ds.lease_time/2 seconds. + */ + + if (!handle) + { + fprintf(stderr, "NET2 ERROR: dhcpc_open failed\n"); + return ERROR; + } + + if (dhcpc_request(handle, &ds) != OK) + { + fprintf(stderr, "NET2 ERROR: dhcpc_request failed\n"); + return ERROR; + } + + netlib_sethostaddr(CONFIG_EXAMPLES_BRIDGE_NET2_IFNAME, &ds.ipaddr); + + if (ds.netmask.s_addr != 0) + { + netlib_setnetmask(CONFIG_EXAMPLES_BRIDGE_NET2_IFNAME, &ds.netmask); + } + + if (ds.default_router.s_addr != 0) + { + netlib_setdraddr(CONFIG_EXAMPLES_BRIDGE_NET2_IFNAME, &ds.default_router); + } + + if (ds.dnsaddr.s_addr != 0) + { + dns_setserver(&ds.dnsaddr); + } + + dhcpc_close(handle); + printf("NET1: Assigned IP: %s\n", inet_ntoa(ds.ipaddr)); + + /* Save the IP address in network order */ + + g_net2_ipaddr = ds.ipaddr; + +#else + /* Save the IP address in network order */ + + g_net2_ipaddr = HTONL(CONFIG_EXAMPLES_BRIDGE_NET2_IPADDR); + +#endif /* CONFIG_EXAMPLES_BRIDGE_NET2_DHCPC */ +#endif /* CONFIG_NSH_BUILTIN_APPS */ + + return OK; +} + +/**************************************************************************** + * Name: bridge_net1_worker + ****************************************************************************/ + +static int bridge_net1_worker(int argc, char *argv[]) +{ + struct sockaddr_in recvaddr; + struct sockaddr_in listenaddr; + struct sockaddr_in sendaddr; + socklen_t addrlen; + in_addr_t tmpaddr; + ssize_t nrecvd; + ssize_t nsent; + int optval; + int recvsd; + int sndsd; + + printf("NET1: Worker started. PID=%d\n", getpid()); + + /* Create a UDP receive socket on network 1 */ + + printf("NET1: Create receive socket\n"); + + recvsd = socket(PF_INET, SOCK_DGRAM, 0); + if (recvsd < 0) + { + fprintf(stderr, "NET1 ERROR: Failed to create receive socket: %d\n", errno); + return EXIT_FAILURE; + } + + /* Set socket to reuse address */ + + optval = 1; + if (setsockopt(recvsd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)) < 0) + { + fprintf(stderr, "NET1 ERROR: setsockopt SO_REUSEADDR failure: %d\n", errno); + goto errout_with_recvsd; + } + + /* Bind the socket to a local address */ + + listenaddr.sin_family = AF_INET; + listenaddr.sin_port = HTONS(CONFIG_EXAMPLES_BRIDGE_NET1_RECVPORT); + listenaddr.sin_addr.s_addr = g_net1_ipaddr; + + if (bind(recvsd, (struct sockaddr*)&listenaddr, sizeof(struct sockaddr_in)) < 0) + { + fprintf(stderr, "NET1 ERROR: bind failure: %d\n", errno); + goto errout_with_recvsd; + } + + /* Create a UDP send socket on network 2 */ + + printf("NET1: Create send socket\n"); + + sndsd = socket(PF_INET, SOCK_DGRAM, 0); + if (sndsd < 0) + { + fprintf(stderr, "NET1 ERROR: Failed to create send socket: %d\n", errno); + goto errout_with_recvsd; + } + + /* Set socket to reuse address */ + + optval = 1; + if (setsockopt(sndsd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)) < 0) + { + fprintf(stderr, "NET1 ERROR: setsockopt SO_REUSEADDR failure: %d\n", errno); + goto errout_with_sendsd; + } + + /* Bind the socket to a local address */ + + sendaddr.sin_family = AF_INET; + sendaddr.sin_port = HTONS(CONFIG_EXAMPLES_BRIDGE_NET1_SNDPORT); + sendaddr.sin_addr.s_addr = g_net2_ipaddr; + + if (bind(sndsd, (struct sockaddr*)&sendaddr, sizeof(struct sockaddr_in)) < 0) + { + printf("NET1: bind failure: %d\n", errno); + goto errout_with_sendsd; + } + + /* Then receive and forward UDP packets forever */ + + for (;;) + { + /* Read a packet on network 1 */ + + printf("NET1: Receiving up to %d bytes on network 1\n", + CONFIG_EXAMPLES_BRIDGE_NET1_IOBUFIZE); + + addrlen = sizeof(struct sockaddr_in); + nrecvd = recvfrom(recvsd, g_net1_buffer, CONFIG_EXAMPLES_BRIDGE_NET1_IOBUFIZE, 0, + (FAR struct sockaddr*)&recvaddr, &addrlen); + + tmpaddr = ntohl(recvaddr.sin_addr.s_addr); + printf("NET1: Received %d bytes from %d.%d.%d.%d:%d\n", + nrecvd, + tmpaddr >> 24, (tmpaddr >> 16) & 0xff, + (tmpaddr >> 8) & 0xff, tmpaddr & 0xff, + ntohs(recvaddr.sin_port)); + + /* Check for a receive error or zero bytes received. The negative + * return value indicates a receive error; Zero would mean that the + * other side of the "connection" performed an "orderly" shutdown. + * This should not occur with a UDP socket and so must also be an + * error of some kind. + */ + + if (nrecvd <= 0) + { + if (nrecvd < 0) + { + fprintf(stderr, "NET1 ERROR: recvfrom failed: %d\n", errno); + } + else + { + fprintf(stderr, "NET1 ERROR: recvfrom returned zero\n"); + } + + goto errout_with_sendsd; + } + + /* Send the newly received packet out network 2 */ + + printf("NET1: Sending %d bytes on network 2\n", nrecvd); + nsent = sendto(sndsd, g_net1_buffer, nrecvd, 0, + (struct sockaddr*)&sendaddr, sizeof(struct sockaddr_in)); + + /* Check for send errors */ + + if (nsent < 0) + { + fprintf(stderr, "NET1 ERROR: sendto failed: %d\n", errno); + goto errout_with_sendsd; + } + else if (nsent != nrecvd) + { + fprintf(stderr, "NET1 ERROR: Bad send length: %d Expected: %d\n", + nsent, nrecvd); + goto errout_with_sendsd; + } + } + + close(recvsd); + close(recvsd); + return EXIT_SUCCESS; + +errout_with_sendsd: + close(sndsd); +errout_with_recvsd: + close(recvsd); + return EXIT_FAILURE; +} + +/**************************************************************************** + * Name: bridge_net2_worker + ****************************************************************************/ + +static int bridge_net2_worker(int argc, char *argv[]) +{ + struct sockaddr_in recvaddr; + struct sockaddr_in listenaddr; + struct sockaddr_in sendaddr; + socklen_t addrlen; + in_addr_t tmpaddr; + ssize_t nrecvd; + ssize_t nsent; + int optval; + int recvsd; + int sndsd; + + printf("NET2: Worker started. PID=%d\n", getpid()); + + /* Create a UDP receive socket on network 2 */ + + printf("NET2: Create receive socket\n"); + + recvsd = socket(PF_INET, SOCK_DGRAM, 0); + if (recvsd < 0) + { + fprintf(stderr, "NET2 ERROR: Failed to create receive socket: %d\n", errno); + return EXIT_FAILURE; + } + + /* Set socket to reuse address */ + + optval = 1; + if (setsockopt(recvsd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)) < 0) + { + fprintf(stderr, "NET2 ERROR: setsockopt SO_REUSEADDR failure: %d\n", errno); + goto errout_with_recvsd; + } + + /* Bind the socket to a local address */ + + listenaddr.sin_family = AF_INET; + listenaddr.sin_port = HTONS(CONFIG_EXAMPLES_BRIDGE_NET2_RECVPORT); + listenaddr.sin_addr.s_addr = g_net2_ipaddr; + + if (bind(recvsd, (struct sockaddr*)&listenaddr, sizeof(struct sockaddr_in)) < 0) + { + fprintf(stderr, "NET2 ERROR: bind failure: %d\n", errno); + goto errout_with_recvsd; + } + + /* Create a UDP send socket on network 1 */ + + printf("NET2: Create send socket\n"); + + sndsd = socket(PF_INET, SOCK_DGRAM, 0); + if (sndsd < 0) + { + fprintf(stderr, "NET2 ERROR: Failed to create send socket: %d\n", errno); + goto errout_with_recvsd; + } + + /* Set socket to reuse address */ + + optval = 1; + if (setsockopt(sndsd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)) < 0) + { + fprintf(stderr, "NET2 ERROR: setsockopt SO_REUSEADDR failure: %d\n", errno); + goto errout_with_sendsd; + } + + /* Bind the socket to a local address */ + + sendaddr.sin_family = AF_INET; + sendaddr.sin_port = HTONS(CONFIG_EXAMPLES_BRIDGE_NET2_SNDPORT); + sendaddr.sin_addr.s_addr = g_net1_ipaddr; + + if (bind(sndsd, (struct sockaddr*)&sendaddr, sizeof(struct sockaddr_in)) < 0) + { + printf("NET2: bind failure: %d\n", errno); + goto errout_with_sendsd; + } + + /* Then receive and forward UDP packets forever */ + + for (;;) + { + /* Read a packet on network 2 */ + + printf("NET2: Receiving up to %d bytes on network 2\n", + CONFIG_EXAMPLES_BRIDGE_NET2_IOBUFIZE); + + addrlen = sizeof(struct sockaddr_in); + nrecvd = recvfrom(recvsd, g_net2_buffer, CONFIG_EXAMPLES_BRIDGE_NET2_IOBUFIZE, 0, + (FAR struct sockaddr*)&recvaddr, &addrlen); + + tmpaddr = ntohl(recvaddr.sin_addr.s_addr); + printf("NET2: Received %d bytes from %d.%d.%d.%d:%d\n", + nrecvd, + tmpaddr >> 24, (tmpaddr >> 16) & 0xff, + (tmpaddr >> 8) & 0xff, tmpaddr & 0xff, + ntohs(recvaddr.sin_port)); + + /* Check for a receive error or zero bytes received. The negative + * return value indicates a receive error; Zero would mean that the + * other side of the "connection" performed an "orderly" shutdown. + * This should not occur with a UDP socket and so must also be an + * error of some kind. + */ + + if (nrecvd <= 0) + { + if (nrecvd < 0) + { + fprintf(stderr, "NET2 ERROR: recvfrom failed: %d\n", errno); + } + else + { + fprintf(stderr, "NET2 ERROR: recvfrom returned zero\n"); + } + + goto errout_with_sendsd; + } + + /* Send the newly received packet out network 1 */ + + printf("NET2: Sending %d bytes on network 1\n", nrecvd); + nsent = sendto(sndsd, g_net2_buffer, nrecvd, 0, + (struct sockaddr*)&sendaddr, sizeof(struct sockaddr_in)); + + /* Check for send errors */ + + if (nsent < 0) + { + fprintf(stderr, "NET2 ERROR: sendto failed: %d\n", errno); + goto errout_with_sendsd; + } + else if (nsent != nrecvd) + { + fprintf(stderr, "NET2 ERROR: Bad send length: %d Expected: %d\n", + nsent, nrecvd); + goto errout_with_sendsd; + } + } + + close(recvsd); + close(recvsd); + return EXIT_SUCCESS; + +errout_with_sendsd: + close(sndsd); +errout_with_recvsd: + close(recvsd); + return EXIT_FAILURE; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * bridge_main + ****************************************************************************/ + +#ifdef CONFIG_BUILD_KERNEL +int main(int argc, FAR char *argv[]) +#else +int bridge_main(int argc, char *argv[]) +#endif +{ + pid_t net1_worker; + pid_t net2_worker; + int ret; + + /* Initialize networks */ + + ret = briget_net1_setup(); + if (ret != OK) + { + fprintf(stderr, "ERROR: Failed to setup network 1\n"); + return EXIT_FAILURE; + } + + ret = briget_net2_setup(); + if (ret != OK) + { + fprintf(stderr, "ERROR: Failed to setup network 2\n"); + return EXIT_FAILURE; + } + + /* Start network daemons */ + + printf("Start network 1 worker\n"); + + net1_worker = task_create("NET1 Worker", CONFIG_EXAMPLES_BRIDGE_NET1_PRIORITY, + CONFIG_EXAMPLES_BRIDGE_NET1_STACKSIZE, bridge_net1_worker, + NULL); + if (net1_worker < 0) + { + fprintf(stderr, "ERROR: Failed to start network daemon 1\n"); + return EXIT_FAILURE; + } + + printf("Start network 2 worker\n"); + + net2_worker = task_create("NET2 Worker", CONFIG_EXAMPLES_BRIDGE_NET2_PRIORITY, + CONFIG_EXAMPLES_BRIDGE_NET2_STACKSIZE, bridge_net2_worker, + NULL); + if (net2_worker < 0) + { + fprintf(stderr, "ERROR: Failed to start network daemon 2\n"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} +