diff --git a/Makefile b/Makefile index 7e9239f..4aa8213 100644 --- a/Makefile +++ b/Makefile @@ -116,7 +116,7 @@ LIBZT_INCLUDES+=-Iinclude \ # NS_ Configuration options for userspace network stack ifeq ($(ZT_DEBUG),1) - ZT_FLAGS+=-DZT_TRACE + ZT_DEFS+=-DZT_TRACE CFLAGS+=-Wall -g -pthread STRIP=echo else @@ -125,7 +125,7 @@ else STRIP=strip endif ifeq ($(LIBZT_DEBUG),1) - LIBZT_FLAGS+=-DLIBZT_DEBUG + LIBZT_DEFS+=-DLIBZT_DEBUG endif ifeq ($(NS_DEBUG),1) # specified in stack configuration section @@ -147,8 +147,8 @@ ifeq ($(SDK_JNI), 1) endif CXXFLAGS=$(CFLAGS) -Wno-format -fno-rtti -std=c++11 -ZT_FLAGS+=-DZT_SDK -DZT_SOFTWARE_UPDATE_DEFAULT="\"disable\"" -LIBZT_FLAGS+= +ZT_DEFS+=-DZT_SDK -DZT_SOFTWARE_UPDATE_DEFAULT="\"disable\"" +LIBZT_DEFS+= LIBZT_FILES:=src/VirtualTap.cpp src/libzt.cpp src/Utilities.cpp STATIC_LIB=$(BUILD)/libzt.a @@ -166,22 +166,22 @@ endif ifeq ($(STACK_PICO),1) # picoTCP default protocol versions ifeq ($(NS_DEBUG),1) - STACK_FLAGS+= + STACK_DEFS+= endif ifeq ($(LIBZT_IPV4)$(LIBZT_IPV6),1) ifeq ($(LIBZT_IPV4),1) -STACK_DRIVER_FLAGS+=-DLIBZT_IPV4 -STACK_FLAGS+=IPV4=1 +STACK_DRIVER_DEFS+=-DLIBZT_IPV4 +STACK_DEFS+=IPV4=1 endif ifeq ($(LIBZT_IPV6),1) -STACK_DRIVER_FLAGS+=-DLIBZT_IPV6 -STACK_FLAGS+=IPV6=1 +STACK_DRIVER_DEFS+=-DLIBZT_IPV6 +STACK_DEFS+=IPV6=1 endif else -STACK_DRIVER_FLAGS+=-DLIBZT_IPV4 -DLIBZT_IPV6 -STACK_FLAGS+=IPV6=1 IPV4=1 +STACK_DRIVER_DEFS+=-DLIBZT_IPV4 -DLIBZT_IPV6 +STACK_DEFS+=IPV6=1 IPV4=1 endif -STACK_DRIVER_FLAGS+=-DSTACK_PICO +STACK_DRIVER_DEFS+=-DSTACK_PICO STACK_LIB:=libpicotcp.a STACK_DIR:=ext/picotcp STACK_LIB:=$(STACK_DIR)/build/lib/$(STACK_LIB) @@ -193,23 +193,23 @@ endif ifeq ($(STACK_LWIP),1) # lwIP default protocol versions ifeq ($(NS_DEBUG),1) - STACK_FLAGS+=LWIP_DEBUG=1 + STACK_DEFS+=LWIP_DEBUG=1 endif ifeq ($(LIBZT_IPV4)$(LIBZT_IPV6),1) ifeq ($(LIBZT_IPV4),1) -STACK_DRIVER_FLAGS+=-DLIBZT_IPV4 -DLWIP_IPV4=1 -STACK_FLAGS+=LIBZT_IPV4=1 +STACK_DRIVER_DEFS+=-DLIBZT_IPV4 -DLWIP_IPV4=1 +STACK_DEFS+=LIBZT_IPV4=1 endif ifeq ($(LIBZT_IPV6),1) -STACK_DRIVER_FLAGS+=-DLIBZT_IPV6 -DLWIP_IPV6=1 -STACK_FLAGS+=LIBZT_IPV6=1 +STACK_DRIVER_DEFS+=-DLIBZT_IPV6 -DLWIP_IPV6=1 +STACK_DEFS+=LIBZT_IPV6=1 endif else -STACK_DRIVER_FLAGS+=-DLIBZT_IPV4 -DLWIP_IPV4=1 -STACK_FLAGS+=LIBZT_IPV4=1 +STACK_DRIVER_DEFS+=-DLIBZT_IPV4 -DLWIP_IPV4=1 +STACK_DEFS+=LIBZT_IPV4=1 endif -STACK_DRIVER_FLAGS+=-DLWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS -STACK_DRIVER_FLAGS+=-DSTACK_LWIP +STACK_DRIVER_DEFS+=-DLWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS +STACK_DRIVER_DEFS+=-DSTACK_LWIP STACK_DRIVER_FILES:=src/lwIP.cpp LWIPARCH=$(CONTRIBDIR)/ports/unix LWIPDIR=ext/lwip/src @@ -222,7 +222,7 @@ STACK_INCLUDES+=-Iext/lwip/src/include/lwip \ endif ifeq ($(NO_STACK),1) -STACK_DRIVER_FLAGS+=-DNO_STACK +STACK_DRIVER_DEFS+=-DNO_STACK endif ############################################################################## @@ -231,8 +231,8 @@ endif %.o : %.cpp @mkdir -p $(BUILD) obj - $(CXX) $(CXXFLAGS) $(SANFLAGS) $(STACK_DRIVER_FLAGS) $(ZT_FLAGS) \ - $(ZT_INCLUDES) $(STACK_INCLUDES) $(LIBZT_INCLUDES) -c $^ -o obj/$(@F) + $(CXX) $(CXXFLAGS) $(SANFLAGS) $(STACK_DRIVER_DEFS) $(ZT_DEFS) \ + $(ZT_INCLUDES) $(LIBZT_INCLUDES) -c $^ -o obj/$(@F) %.o : %.c @mkdir -p $(BUILD) obj @@ -242,13 +242,13 @@ picotcp: cd ext/picotcp; make lib ARCH=shared IPV4=1 IPV6=1 lwip: - make -f make-liblwip.mk liblwip.a $(STACK_FLAGS) + make -f make-liblwip.mk liblwip.a $(STACK_DEFS) ifeq ($(STACK_PICO),1) static_lib: picotcp $(ZTO_OBJS) @mkdir -p $(BUILD) obj - $(CXX) $(CXXFLAGS) $(SANFLAGS) $(ZT_FLAGS) $(ZT_INCLUDES) $(LIBZT_FLAGS) \ - $(LIBZT_INCLUDES) $(STACK_INCLUDES) $(STACK_DRIVER_FLAGS) $(LIBZT_FILES) \ + $(CXX) $(CXXFLAGS) $(SANFLAGS) $(ZT_DEFS) $(ZT_INCLUDES) $(LIBZT_DEFS) \ + $(LIBZT_INCLUDES) $(STACK_INCLUDES) $(STACK_DRIVER_DEFS) $(LIBZT_FILES) \ $(STACK_DRIVER_FILES) -c mv *.o obj mv ext/picotcp/build/lib/*.o obj @@ -259,18 +259,23 @@ endif ifeq ($(STACK_LWIP),1) static_lib: lwip $(ZTO_OBJS) @mkdir -p $(BUILD) obj - $(CXX) $(CXXFLAGS) $(SANFLAGS) $(ZT_FLAGS) $(ZT_INCLUDES) $(LIBZT_FLAGS) \ - $(LIBZT_INCLUDES) $(STACK_INCLUDES) $(STACK_DRIVER_FLAGS) $(LIBZT_FILES) \ - $(STACK_DRIVER_FILES) -c + $(CXX) $(CXXFLAGS) -c src/VirtualSocket.cpp $(LIBZT_INCLUDES) + $(CXX) $(CXXFLAGS) -c src/VirtualBindingPair.cpp $(ZT_INCLUDES) $(LIBZT_INCLUDES) + $(CXX) $(CXXFLAGS) -c src/Platform.cpp $(LIBZT_INCLUDES) + $(CXX) $(CXXFLAGS) -c src/libzt.cpp $(ZT_DEFS) $(ZT_INCLUDES) $(STACK_INCLUDES) $(LIBZT_DEFS) $(LIBZT_INCLUDES) $(STACK_DRIVER_DEFS) + $(CXX) $(CXXFLAGS) -c src/Utilities.cpp $(ZT_DEFS) $(ZT_INCLUDES) $(LIBZT_INCLUDES) $(STACK_DRIVER_DEFS) + $(CXX) $(CXXFLAGS) -c src/ZT1Service.cpp $(ZT_DEFS) $(ZT_INCLUDES) $(LIBZT_INCLUDES) $(LIBZT_DEFS) $(STACK_DRIVER_DEFS) + $(CXX) $(CXXFLAGS) -c src/VirtualTap.cpp $(ZT_DEFS) $(ZT_INCLUDES) $(LIBZT_DEFS) $(LIBZT_INCLUDES) $(STACK_DRIVER_DEFS) + $(CXX) $(CXXFLAGS) -c src/lwIP.cpp $(ZT_DEFS) $(ZT_INCLUDES) $(STACK_INCLUDES) $(LIBZT_DEFS) $(LIBZT_INCLUDES) $(STACK_DRIVER_DEFS) mv *.o obj - $(ARTOOL) $(ARFLAGS) -o $(STATIC_LIB) $(STACK_LIB) obj/*.o + $(ARTOOL) $(ARFLAGS) -o $(STATIC_LIB) obj/*.o @date +"Build script finished on %F %T" endif # for layer-2 only (this will omit all userspace network stack code) ifeq ($(NO_STACK),1) static_lib: $(ZTO_OBJS) @mkdir -p $(BUILD) obj - $(CXX) $(CXXFLAGS) $(ZT_FLAGS) $(ZT_INCLUDES) $(LIBZT_FLAGS) $(LIBZT_INCLUDES) $(LIBZT_FILES) -c + $(CXX) $(CXXFLAGS) $(ZT_DEFS) $(ZT_INCLUDES) $(LIBZT_DEFS) $(LIBZT_INCLUDES) $(LIBZT_FILES) -c mv *.o obj $(ARTOOL) $(ARFLAGS) -o $(STATIC_LIB) obj/*.o @date +"Build script finished on %F %T" @@ -318,13 +323,13 @@ tests: selftest nativetest ztproxy ZT_UTILS:=zto/node/Utils.cpp -Izto/node selftest: - $(CXX) $(CXXFLAGS) -D__SELFTEST__ $(STACK_DRIVER_FLAGS) $(LIBZT_FLAGS) \ + $(CXX) $(CXXFLAGS) -D__SELFTEST__ $(STACK_DRIVER_DEFS) $(LIBZT_DEFS) \ $(SANFLAGS) $(LIBZT_INCLUDES) $(ZT_INCLUDES) $(ZT_UTILS) test/selftest.cpp -o \ $(BUILD)/selftest -L$(BUILD) -lzt -lpthread @./check.sh $(BUILD)/selftest @date +"Build script finished on %F %T" nativetest: - $(CXX) $(CXXFLAGS) -D__NATIVETEST__ $(STACK_DRIVER_FLAGS) $(SANFLAGS) \ + $(CXX) $(CXXFLAGS) -D__NATIVETEST__ $(STACK_DRIVER_DEFS) $(SANFLAGS) \ $(LIBZT_INCLUDES) $(ZT_INCLUDES) test/selftest.cpp -o $(BUILD)/nativetest @./check.sh $(BUILD)/nativetest @date +"Build script finished on %F %T" @@ -334,7 +339,7 @@ ztproxy: @./check.sh $(BUILD)/ztproxy @date +"Build script finished on %F %T" intercept: - $(CXX) $(CXXFLAGS) $(SANFLAGS) $(STACK_DRIVER_FLAGS) $(LIBZT_INCLUDES) \ + $(CXX) $(CXXFLAGS) $(SANFLAGS) $(STACK_DRIVER_DEFS) $(LIBZT_INCLUDES) \ $(ZT_INCLUDES) examples/intercept/intercept.cpp -D_GNU_SOURCE \ -shared -o $(BUILD)/intercept.so $< -ldl @./check.sh $(BUILD)/intercept.so diff --git a/ext/lwip-contrib/.gitignore b/ext/lwip-contrib/.gitignore new file mode 100644 index 0000000..64abc74 --- /dev/null +++ b/ext/lwip-contrib/.gitignore @@ -0,0 +1,25 @@ +*.o +*.so +*.a +.depend +/ports/unix/unixsim/simhost +/ports/unix/unixsim/simrouter +/ports/unix/unixsim/simnode +/ports/unix/unixsim/makefsdata +/ports/unix/minimal/echop +/ports/win32/msvc/Debug +/ports/win32/lwipcfg_msvc.h +/ports/win32/msvc/Debug unittests +/ports/win32/msvc/Release +/ports/win32/msvc/Release unittests +/ports/win32/msvc/*.user +/ports/win32/msvc/*.ncb +/ports/win32/msvc/*.cache +/ports/win32/msvc/*.suo +/ports/win32/msvc/ipch +/ports/win32/msvc/*.opensdf +/ports/win32/msvc/*.sdf +/ports/unix/check/lwip_unittests +/ports/win32/mingw/*.exe +/ports/win32/mingw/*.map +/ports/win32/mingw/cov-int diff --git a/ext/lwip-contrib/Filelists.mk b/ext/lwip-contrib/Filelists.mk new file mode 100644 index 0000000..fefe3e8 --- /dev/null +++ b/ext/lwip-contrib/Filelists.mk @@ -0,0 +1,47 @@ +# +# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. +# All rights reserved. +# +# 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. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +# +# This file is part of the lwIP TCP/IP stack. +# +# Author: Adam Dunkels +# + +# CONTRIBAPPFILES: Contrib Applications. +CONTRIBAPPFILES=$(CONTRIBDIR)/apps/httpserver/httpserver-netconn.c \ + $(CONTRIBDIR)/apps/chargen/chargen.c \ + $(CONTRIBDIR)/apps/udpecho/udpecho.c \ + $(CONTRIBDIR)/apps/tcpecho/tcpecho.c \ + $(CONTRIBDIR)/apps/shell/shell.c \ + $(CONTRIBDIR)/apps/udpecho_raw/udpecho_raw.c \ + $(CONTRIBDIR)/apps/tcpecho_raw/tcpecho_raw.c \ + $(CONTRIBDIR)/apps/netio/netio.c \ + $(CONTRIBDIR)/apps/ping/ping.c \ + $(CONTRIBDIR)/apps/snmp_private_mib/lwip_prvmib.c \ + $(CONTRIBDIR)/apps/snmp_v3/snmpv3_dummy.c \ + $(CONTRIBDIR)/apps/socket_examples/socket_examples.c \ + $(CONTRIBDIR)/apps/rtp/rtp.c \ + $(CONTRIBDIR)/addons/tcp_isn/tcp_isn.c \ + $(CONTRIBDIR)/addons/ipv6_static_routing/ip6_route_table.c diff --git a/ext/lwip-contrib/ports/Common.allports.mk b/ext/lwip-contrib/ports/Common.allports.mk new file mode 100644 index 0000000..d3774ba --- /dev/null +++ b/ext/lwip-contrib/ports/Common.allports.mk @@ -0,0 +1,94 @@ +# +# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. +# All rights reserved. +# +# 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. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +# +# This file is part of the lwIP TCP/IP stack. +# +# Author: Adam Dunkels +# + +#CC=gcc +#CC=clang +CCDEP?=$(CC) + +CFLAGS+=-g -Wall -DLWIP_DEBUG -pedantic -Werror \ + -Wparentheses -Wsequence-point -Wswitch-default \ + -Wextra -Wundef -Wshadow -Wpointer-arith -Wcast-qual \ + -Wc++-compat -Wwrite-strings -Wold-style-definition -Wcast-align \ + -Wmissing-prototypes -Wredundant-decls -Wnested-externs \ + -Wunreachable-code -Wuninitialized + +ifeq (,$(findstring clang,$(CC))) +CFLAGS+= -Wlogical-op +# if GCC is newer than 4.8/4.9 you may use: +#CFLAGS:=$(CFLAGS) -fsanitize=address -fstack-protector -fstack-check -fsanitize=undefined -fno-sanitize=alignment +else +# we cannot sanitize alignment on x86-64 targets because clang wants 64 bit alignment +CFLAGS+= -fsanitize=address -fsanitize=undefined -fno-sanitize=alignment -Wdocumentation -Wno-documentation-deprecated-sync +endif + +# not used for now but interesting: +# -Wpacked +# -ansi +# -std=c89 + +CONTRIBDIR?=../../.. +ARFLAGS?=rs + +#Set this to where you have the lwip core module checked out from git +#default assumes it's a dir named lwip at the same level as the contrib module +LWIPDIR?=$(CONTRIBDIR)/../lwip/src + +CFLAGS+=-I. \ + -I$(CONTRIBDIR) \ + -I$(LWIPDIR)/include \ + -I$(LWIPARCH)/include + +# Add include path and link to mbedTLS lib if available +MBEDTLSDIR?=$(CONTRIBDIR)/../mbedtls +ifneq (,$(wildcard $(MBEDTLSDIR)/include/mbedtls/*.h)) +LDFLAGS+=-L$(MBEDTLSDIR)/library -lmbedtls -lmbedcrypto -lmbedx509 +CFLAGS+=-I$(MBEDTLSDIR)/include -Wno-redundant-decls -DLWIP_HAVE_MBEDTLS=1 +endif + +include $(CONTRIBDIR)/Filelists.mk +include $(LWIPDIR)/Filelists.mk + +# LWIPFILES: All the above. +LWIPFILES=$(LWIPNOAPPSFILES) $(ARCHFILES) +LWIPOBJS=$(notdir $(LWIPFILES:.c=.o)) + +LWIPLIBCOMMON=liblwipcommon.a +$(LWIPLIBCOMMON): $(LWIPOBJS) + $(AR) $(ARFLAGS) $(LWIPLIBCOMMON) $? + +APPFILES=$(CONTRIBAPPFILES) $(LWIPAPPFILES) +APPLIB=liblwipapps.a +APPOBJS=$(notdir $(APPFILES:.c=.o)) +$(APPLIB): $(APPOBJS) + $(AR) $(ARFLAGS) $(APPLIB) $? + +%.o: + $(CC) $(CFLAGS) -c $< diff --git a/ext/lwip-contrib/ports/FILES b/ext/lwip-contrib/ports/FILES new file mode 100644 index 0000000..a8db240 --- /dev/null +++ b/ext/lwip-contrib/ports/FILES @@ -0,0 +1,8 @@ +unix/ - Architectural files for testing on unix-like systems + (assuming gcc and pthreads). + - Maintained by Kieran Mansley + +msvc6/ - Architectural files for Microsoft Visual C++ 6.0. + - Maintained by Simon Goldschmidt + +old/ - Ports that are no longer actively maintained diff --git a/ext/lwip-contrib/ports/unix/Common.mk b/ext/lwip-contrib/ports/unix/Common.mk new file mode 100644 index 0000000..ec9c3d4 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/Common.mk @@ -0,0 +1,42 @@ +# +# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. +# All rights reserved. +# +# 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. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +# +# This file is part of the lwIP TCP/IP stack. +# +# Author: Adam Dunkels +# + +# Architecture specific files. +LWIPARCH?=$(CONTRIBDIR)/ports/unix/port +SYSARCH?=$(LWIPARCH)/sys_arch.c +ARCHFILES=$(LWIPARCH)/perf.c $(SYSARCH) $(LWIPARCH)/netif/tapif.c $(LWIPARCH)/netif/tunif.c \ + $(LWIPARCH)/netif/unixif.c $(LWIPARCH)/netif/list.c $(LWIPARCH)/netif/tcpdump.c \ + $(LWIPARCH)/netif/delif.c $(LWIPARCH)/netif/sio.c $(LWIPARCH)/netif/fifo.c + +UNIX_COMMON_MK_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) +include $(UNIX_COMMON_MK_DIR)../Common.allports.mk + +LDFLAGS+=-pthread -lutil -lrt diff --git a/ext/lwip-contrib/ports/unix/README b/ext/lwip-contrib/ports/unix/README new file mode 100644 index 0000000..2e2478a --- /dev/null +++ b/ext/lwip-contrib/ports/unix/README @@ -0,0 +1,52 @@ +This port contains infrastructure and examples for running lwIP on Unix-like +operating systems (Linux, OpenBSD, cygwin). Much of this is targetted towards +testing lwIP applications. + +* port/sys_arch.c, port/perf.c, port/include/arch/: Generic platform porting, + for both states of NO_SYS. (Mapping debugging to printf, providing + sys_now & co from the system time etc.) + +* check: Runs the unit tests shipped with main lwIP on the Unix port. + +* fuzz: Helper application for fuzzing the lwIP stack + +* port/netif, port/include/netif: Various network interface implementations and + their helpers, some explicitly for Unix infrastructure, some generic (but most + useful on an easy to debug system): + + * delif: Network interface that inserts delay before receiving or sending + packages + + * fifo: Helper for sio + + * list: Helper for unixif + + * pcapif: Network interface that replays packages from a PCAP dump file, and + discards packages sent out from it + + * sio: Mapping Unix character devices to lwIP's sio mechanisms + + * tapif: Network interface that is mapped to a tap interface (Unix user + space layer 2 network device). Uses lwIP threads. + + * tcpdump: Utility functions to dump pbufs into a tcpdump formatted log + file + + * tunif: Network interface that is mapped to a tun interface (Unix user + space layer 3 network device). Uses lwIP threads. + + * unixif: Network interface that allows lwIP Unix programs to "meet" at Unix + socket address and exchange traffic over it. + +* lib: Compiling lwIP as a shared library + +* minimal: Standalone example program that runs in NO_SYS=1 mode. + Contains the mintapif network interface implementation, which is similar to + netif/tapif, but runs without threads. + + Runs an echo server and SNMP. + +* unixsim: Standalone example program that runs in NO_SYS=0 mode. Uses + the tapif network interface. + + Runs an HTTP server. diff --git a/ext/lwip-contrib/ports/unix/check/Makefile b/ext/lwip-contrib/ports/unix/check/Makefile new file mode 100644 index 0000000..8ee55fa --- /dev/null +++ b/ext/lwip-contrib/ports/unix/check/Makefile @@ -0,0 +1,62 @@ +# +# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. +# All rights reserved. +# +# 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. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +# +# This file is part of the lwIP TCP/IP stack. +# +# Author: Adam Dunkels +# + +all compile: lwip_unittests +.PHONY: all clean check + +# The include path to sys_arch.h and lwipopts.h must be first, so this must be before Common.mk +CFLAGS=-DLWIP_NOASSERT_ON_ERROR -I/usr/include/check -I$(LWIPDIR)/../test/unit + +# Prevent compiling sys_arch.c of unix port because unit test provide their own port +SYSARCH?= +include ../Common.mk + +LDFLAGS:=-lcheck -lm -lsubunit $(LDFLAGS) + +TESTDIR=$(LWIPDIR)/../test/unit +include $(TESTDIR)/Filelists.mk +TESTOBJS=$(notdir $(TESTFILES:.c=.o)) + +clean: + @rm -f *.o $(LWIPLIBCOMMON) $(APPLIB) lwip_unittests *.s .depend* *.core core + +depend dep: .depend + +include .depend + +.depend: $(LWIPFILES) $(APPFILES) $(TESTFILES) + $(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend + +lwip_unittests: .depend $(TESTOBJS) $(LWIPLIBCOMMON) $(APPLIB) + $(CC) $(CFLAGS) -o lwip_unittests $(TESTOBJS) -Wl,--start-group $(LWIPLIBCOMMON) $(APPLIB) $(LDFLAGS) -Wl,--end-group + +check: lwip_unittests + @./lwip_unittests diff --git a/ext/lwip-contrib/ports/unix/check/README b/ext/lwip-contrib/ports/unix/check/README new file mode 100644 index 0000000..421ae3b --- /dev/null +++ b/ext/lwip-contrib/ports/unix/check/README @@ -0,0 +1,8 @@ + +Helper files to run lwIP unit tests on unix-like systems. + +1. Install the check library, through a package manager or from http://check.sourceforge.net/ +2. Put the lwip code in a directory called 'lwip' in the same directory as lwip-contrib is +3. Run `make check` +4. Make sure all tests pass + diff --git a/ext/lwip-contrib/ports/unix/check/config.h b/ext/lwip-contrib/ports/unix/check/config.h new file mode 100644 index 0000000..0d84b36 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/check/config.h @@ -0,0 +1,2 @@ +/* Enable this to simplify debugging */ +/* #define LWIP_UNITTESTS_NOFORK */ diff --git a/ext/lwip/test/fuzz/Makefile b/ext/lwip-contrib/ports/unix/lib/Makefile old mode 100755 new mode 100644 similarity index 80% rename from ext/lwip/test/fuzz/Makefile rename to ext/lwip-contrib/ports/unix/lib/Makefile index f1b8b22..a07b8f2 --- a/ext/lwip/test/fuzz/Makefile +++ b/ext/lwip-contrib/ports/unix/lib/Makefile @@ -1,53 +1,52 @@ -# -# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. -# All rights reserved. -# -# 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. The name of the author may not be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -# -# This file is part of the lwIP TCP/IP stack. -# -# Author: Adam Dunkels -# - -all compile: lwip_fuzz -.PHONY: all clean - -CC=afl-gcc -LDFLAGS=-lm -CFLAGS=-O0 - -CONTRIBDIR=../../../lwip-contrib -include $(CONTRIBDIR)/ports/unix/Common.mk - -clean: - rm -f *.o $(LWIPLIBCOMMON) lwip_fuzz *.s .depend* *.core core - -depend dep: .depend - -include .depend - -.depend: fuzz.c $(LWIPFILES) $(APPFILES) - $(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend - -lwip_fuzz: .depend $(LWIPLIBCOMMON) fuzz.o - $(CC) $(CFLAGS) -o lwip_fuzz fuzz.o $(LWIPLIBCOMMON) $(LDFLAGS) +# +# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. +# All rights reserved. +# +# 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. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +# +# This file is part of the lwIP TCP/IP stack. +# +# Author: Adam Dunkels +# + +UNIXLIB=liblwip.a + +all: $(UNIXLIB) +.PHONY: all + +include ../Common.mk + +CFLAGS+=-fPIC + +clean: + rm -f *.o $(LWIPLIBCOMMON) *.s .depend* *.core core + +depend dep: .depend + +include .depend + +$(UNIXLIB): $(LWIPLIBCOMMON) unixlib.o + $(CC) -g -nostartfiles -shared -o $@ $^ + +.depend: unixlib.c $(LWIPFILES) + $(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend diff --git a/ext/lwip-contrib/ports/unix/lib/README b/ext/lwip-contrib/ports/unix/lib/README new file mode 100644 index 0000000..cd6cc7b --- /dev/null +++ b/ext/lwip-contrib/ports/unix/lib/README @@ -0,0 +1,31 @@ +This directory contains an example of how to compile lwIP as a self +initialising shared library on Linux. + +Some brief instructions: + +* Compile the code: + + > make clean all + + This should produce liblwip4unixlib.so. This is the shared library. + +* Link an application against the shared library + + If you're using gcc you can do this by including -llwip4unixlib in +your link command. + +* Run your application + + Ensure that LD_LIBRARY_PATH includes the directory that contains +liblwip4unixlib.so (ie. this directory) + + + +If you are unsure about shared libraries and libraries on linux in +general, you might find this HOWTO useful: + + + + + +Kieran Mansley, October 2002. \ No newline at end of file diff --git a/ext/lwip-contrib/ports/unix/lib/lwipopts.h b/ext/lwip-contrib/ports/unix/lib/lwipopts.h new file mode 100644 index 0000000..7675261 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/lib/lwipopts.h @@ -0,0 +1,419 @@ +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_LWIPOPTS_H +#define LWIP_LWIPOPTS_H + +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you dont like! + */ +#include "lwipopts.h" +#include "lwip/debug.h" + +/* + ----------------------------------------------- + ---------- Platform specific locking ---------- + ----------------------------------------------- +*/ + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#define SYS_LIGHTWEIGHT_PROT 0 + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ +#define NO_SYS 0 + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#define MEM_ALIGNMENT 1U + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#define MEM_SIZE 1600 + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#define MEMP_NUM_PBUF 16 + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#define MEMP_NUM_RAW_PCB 4 + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#define MEMP_NUM_UDP_PCB 4 + +/** + * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_PCB 4 + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_PCB_LISTEN 4 + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_SEG 16 + +/** + * MEMP_NUM_REASSDATA: the number of simultaneously IP packets queued for + * reassembly (whole packets, not fragments!) + */ +#define MEMP_NUM_REASSDATA 1 + +/** + * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#define MEMP_NUM_ARP_QUEUE 2 + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. + * (requires NO_SYS==0) + */ +#define MEMP_NUM_SYS_TIMEOUT 3 + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#define MEMP_NUM_NETBUF 2 + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#define MEMP_NUM_NETCONN 4 + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#define MEMP_NUM_TCPIP_MSG_API 8 + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#define MEMP_NUM_TCPIP_MSG_INPKT 8 + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#define PBUF_POOL_SIZE 8 + +/* + --------------------------------- + ---------- ARP options ---------- + --------------------------------- +*/ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#define LWIP_ARP 1 + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#define IP_FORWARD 0 + +/** + * IP_OPTIONS: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#define IP_OPTIONS_ALLOWED 1 + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#define IP_REASSEMBLY 1 + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#define IP_FRAG 1 + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#define IP_REASS_MAXAGE 3 + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#define IP_REASS_MAX_PBUFS 4 + +/** + * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP + * fragmentation. Otherwise pbufs are allocated and reference the original + * packet data to be fragmented. +*/ +#define IP_FRAG_USES_STATIC_BUF 0 + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#define IP_DEFAULT_TTL 255 + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#define LWIP_ICMP 1 + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#define LWIP_RAW 1 + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#define LWIP_DHCP 0 + + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#define LWIP_AUTOIP 0 + +/* + ---------------------------------- + ---------- SNMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP + * transport. + */ +#define LWIP_SNMP 0 + +/* + ---------------------------------- + ---------- IGMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#define LWIP_IGMP 0 + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#define LWIP_DNS 0 + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#define LWIP_UDP 1 + +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#define LWIP_TCP 1 + +#define LWIP_LISTEN_BACKLOG 0 + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#define PBUF_LINK_HLEN 16 + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accomodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. +* + */ +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c + */ +#define LWIP_HAVE_LOOPIF 0 + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#define LWIP_NETCONN 1 + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#define LWIP_SOCKET 1 + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#define LWIP_STATS 0 +/* + --------------------------------- + ---------- PPP options ---------- + --------------------------------- +*/ +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#define PPP_SUPPORT 0 + + +/* Misc */ + +#endif /* LWIP_LWIPOPTS_H */ diff --git a/ext/lwip-contrib/ports/unix/lib/unixlib.c b/ext/lwip-contrib/ports/unix/lib/unixlib.c new file mode 100644 index 0000000..a3d7e7f --- /dev/null +++ b/ext/lwip-contrib/ports/unix/lib/unixlib.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Author: Kieran Mansley + * + * $Id: unixlib.c,v 1.10 2010/02/17 16:52:30 goldsimon Exp $ + */ + +/*-----------------------------------------------------------------------------------*/ +/* unixlib.c + * + * The initialisation functions for a shared library + * + * You may need to configure this file to your own needs - it is only an example + * of how lwIP can be used as a self initialising shared library. + * + * In particular, you should change the gateway, ipaddr, and netmask to be the values + * you would like the stack to use. + */ +/*-----------------------------------------------------------------------------------*/ +#include "lwip/init.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/pbuf.h" +#include "lwip/tcp.h" +#include "lwip/tcpip.h" +#include "lwip/netif.h" +#include "lwip/stats.h" +#include "lwip/sockets.h" + +#include "netif/tapif.h" + +struct netif netif; + +void _init(void); +void _fini(void); + +static void +tcpip_init_done(void *arg) +{ + ip_addr_t ipaddr, netmask, gateway; + sys_sem_t *sem; + sem = (sys_sem_t *)arg; + + /* + CHANGE THESE to suit your own network configuration: + */ + IP4_ADDR(&gateway, 192,168,1,1); + IP4_ADDR(&ipaddr, 192,168,1,2); + IP4_ADDR(&netmask, 255,255,255,0); + + netif_set_default(netif_add(&netif, &ipaddr, &netmask, &gateway, NULL, tapif_init, + tcpip_input)); + netif_set_up(&netif); +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(&netif, 1); +#endif + sys_sem_signal(sem); +} + +void _init(void){ + sys_sem_t sem; + + if(sys_sem_new(&sem, 0) != ERR_OK) { + LWIP_ASSERT("failed to create semaphore", 0); + } + tcpip_init(tcpip_init_done, &sem); + sys_sem_wait(&sem); + sys_sem_free(&sem); +} + +void _fini(void){ +} diff --git a/ext/lwip-contrib/ports/unix/minimal/Makefile b/ext/lwip-contrib/ports/unix/minimal/Makefile new file mode 100644 index 0000000..7385fb1 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/minimal/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. +# All rights reserved. +# +# 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. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +# +# This file is part of the lwIP TCP/IP stack. +# +# Author: Adam Dunkels +# + +all ipv4 compile: echop +.PHONY: all + +include ../Common.mk + +clean: + rm -f *.o $(LWIPLIBCOMMON) $(APPLIB) echop .depend* *.core core + +depend dep: .depend + +include .depend + +.depend: main.c $(LWIPFILES) $(APPFILES) + $(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend + +echop: .depend $(LWIPLIBCOMMON) $(APPLIB) main.o $(APPFILES) + $(CC) $(CFLAGS) -o echop main.o -Wl,--start-group $(APPLIB) $(LWIPLIBCOMMON) -Wl,--end-group $(LDFLAGS) diff --git a/ext/lwip-contrib/ports/unix/minimal/README b/ext/lwip-contrib/ports/unix/minimal/README new file mode 100644 index 0000000..81d7d47 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/minimal/README @@ -0,0 +1,12 @@ +This is an example of a very minimal lwIP project. It runs in a single +thread and runs a single example application - an echo server. The +echo application is implemented using the raw API. Additionally this +raw API example hosts the SNMPv1 agent for development purposes. + +In order to run the demo without root priviledges, you can create a +preconfigured tap device in advance and then run the application with the +interface passed in via an environment variable: + +$ sudo ip tuntap add dev tap0 mode tap user YOUR-USER-NAME +$ sudo ip a a dev tap0 192.168.0.1/24 +$ PRECONFIGURED_TAPIF=tap0 ./echop diff --git a/ext/lwip-contrib/ports/unix/minimal/lwipopts.h b/ext/lwip-contrib/ports/unix/minimal/lwipopts.h new file mode 100644 index 0000000..3388839 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/minimal/lwipopts.h @@ -0,0 +1,440 @@ +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_LWIPOPTS_H +#define LWIP_LWIPOPTS_H + +/* + ----------------------------------------------- + ---------- Platform specific locking ---------- + ----------------------------------------------- +*/ + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ +#define NO_SYS 1 + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#define SYS_LIGHTWEIGHT_PROT 0 + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#define MEM_ALIGNMENT 1U + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#define MEM_SIZE 16000 + + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#define MEMP_NUM_PBUF 30 + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#define MEMP_NUM_RAW_PCB 4 + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#define MEMP_NUM_UDP_PCB 4 + +/** + * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_PCB 2 + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_PCB_LISTEN 8 + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_SEG 16 + +/** + * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#define MEMP_NUM_ARP_QUEUE 2 + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simultaneously active timeouts. + * The default number of timeouts is calculated here for all enabled modules. + * The formula expects settings to be either '0' or '1'. + * + * To this default value, 1 was added for the snmp_increment timer. + */ +#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)) + 1 + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#define MEMP_NUM_NETBUF 0 + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#define MEMP_NUM_NETCONN 0 + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#define MEMP_NUM_TCPIP_MSG_API 0 + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#define MEMP_NUM_TCPIP_MSG_INPKT 0 + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#define PBUF_POOL_SIZE 32 + +/* + --------------------------------- + ---------- ARP options ---------- + --------------------------------- +*/ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#define LWIP_ARP 1 + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#define IP_FORWARD 0 + +/** + * IP_OPTIONS: Defines the behavior for IP options. + * IP_OPTIONS==0_ALLOWED: All packets with IP options are dropped. + * IP_OPTIONS==1_ALLOWED: IP options are allowed (but not parsed). + */ +#define IP_OPTIONS_ALLOWED 1 + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#define IP_REASSEMBLY 1 + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#define IP_FRAG 1 + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#define IP_REASS_MAXAGE 3 + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#define IP_REASS_MAX_PBUFS 10 + +/** + * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP + * fragmentation. Otherwise pbufs are allocated and reference the original + * packet data to be fragmented. + */ +#define IP_FRAG_USES_STATIC_BUF 0 + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#define IP_DEFAULT_TTL 255 + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#define LWIP_ICMP 1 + +/** + * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. + */ +#define ICMP_TTL (IP_DEFAULT_TTL) + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#define LWIP_RAW 0 + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#define LWIP_DHCP 0 + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#define LWIP_AUTOIP 0 + +/* + ---------------------------------- + ---------- SNMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP + * transport. + */ +#define LWIP_SNMP 1 +#define LWIP_MIB2_CALLBACKS 0 +#define MIB2_STATS 1 + +/* + ---------------------------------- + ---------- IGMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#define LWIP_IGMP 0 + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#define LWIP_DNS 0 + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#define LWIP_UDP 1 + +/** + * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) + */ +#define LWIP_UDPLITE 0 + +/** + * UDP_TTL: Default Time-To-Live value. + */ +#define UDP_TTL (IP_DEFAULT_TTL) + +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#define LWIP_TCP 1 + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#define PBUF_LINK_HLEN 16 + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c + */ +#define LWIP_HAVE_LOOPIF 0 + + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#define LWIP_NETCONN 0 + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#define LWIP_SOCKET 0 + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#define LWIP_STATS 1 + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ + +#define TAPIF_DEBUG LWIP_DBG_ON +#define TUNIF_DEBUG LWIP_DBG_OFF +#define UNIXIF_DEBUG LWIP_DBG_OFF +#define DELIF_DEBUG LWIP_DBG_OFF +#define SIO_FIFO_DEBUG LWIP_DBG_OFF +#define TCPDUMP_DEBUG LWIP_DBG_ON +#define API_LIB_DEBUG LWIP_DBG_ON +#define API_MSG_DEBUG LWIP_DBG_ON +#define TCPIP_DEBUG LWIP_DBG_ON +#define NETIF_DEBUG LWIP_DBG_ON +#define SOCKETS_DEBUG LWIP_DBG_ON +#define DEMO_DEBUG LWIP_DBG_ON +#define IP_DEBUG LWIP_DBG_ON +#define IP_REASS_DEBUG LWIP_DBG_ON +#define RAW_DEBUG LWIP_DBG_ON +#define ICMP_DEBUG LWIP_DBG_ON +#define UDP_DEBUG LWIP_DBG_ON +#define TCP_DEBUG LWIP_DBG_ON +#define TCP_INPUT_DEBUG LWIP_DBG_ON +#define TCP_OUTPUT_DEBUG LWIP_DBG_ON +#define TCP_RTO_DEBUG LWIP_DBG_ON +#define TCP_CWND_DEBUG LWIP_DBG_ON +#define TCP_WND_DEBUG LWIP_DBG_ON +#define TCP_FR_DEBUG LWIP_DBG_ON +#define TCP_QLEN_DEBUG LWIP_DBG_ON +#define TCP_RST_DEBUG LWIP_DBG_ON + +extern unsigned char debug_flags; +#define LWIP_DBG_TYPES_ON debug_flags + +#endif /* LWIP_LWIPOPTS_H */ diff --git a/ext/lwip-contrib/ports/unix/minimal/main.c b/ext/lwip-contrib/ports/unix/minimal/main.c new file mode 100644 index 0000000..9d80759 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/minimal/main.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * RT timer modifications by Christiaan Simons + */ + +#include +#include +#include + +#include "lwip/init.h" + +#include "lwip/debug.h" + +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/sys.h" +#include "lwip/timeouts.h" + +#include "lwip/stats.h" + +#include "lwip/ip.h" +#include "lwip/ip4_frag.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "netif/tapif.h" +#include "netif/etharp.h" + +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_mib2.h" + +#include "apps/snmp_private_mib/private_mib.h" +#include "apps/udpecho_raw/udpecho_raw.h" +#include "apps/tcpecho_raw/tcpecho_raw.h" + +/* (manual) host IP configuration */ +static ip4_addr_t ipaddr, netmask, gw; + +#if LWIP_SNMP +/* SNMP trap destination cmd option */ +static unsigned char trap_flag; +static ip_addr_t trap_addr; + +static const struct snmp_mib *mibs[] = { + &mib2, + &mib_private +}; +#endif + +/* nonstatic debug cmd option, exported in lwipopts.h */ +unsigned char debug_flags; + +#if LWIP_SNMP +/* enable == 1, disable == 2 */ +u8_t snmpauthentraps_set = 2; +#endif + +static struct option longopts[] = { + /* turn on debugging output (if build with LWIP_DEBUG) */ + {"debug", no_argument, NULL, 'd'}, + /* help */ + {"help", no_argument, NULL, 'h'}, + /* gateway address */ + {"gateway", required_argument, NULL, 'g'}, + /* ip address */ + {"ipaddr", required_argument, NULL, 'i'}, + /* netmask */ + {"netmask", required_argument, NULL, 'm'}, + /* ping destination */ + {"trap_destination", required_argument, NULL, 't'}, + /* new command line options go here! */ + {NULL, 0, NULL, 0} +}; +#define NUM_OPTS ((sizeof(longopts) / sizeof(struct option)) - 1) + +static void +usage(void) +{ + unsigned char i; + + printf("options:\n"); + for (i = 0; i < NUM_OPTS; i++) { + printf("-%c --%s\n",longopts[i].val, longopts[i].name); + } +} + +int +main(int argc, char **argv) +{ + struct netif netif; + int ch; + char ip_str[16] = {0}, nm_str[16] = {0}, gw_str[16] = {0}; + + /* startup defaults (may be overridden by one or more opts) */ + IP4_ADDR(&gw, 192,168,0,1); + IP4_ADDR(&ipaddr, 192,168,0,2); + IP4_ADDR(&netmask, 255,255,255,0); + +#if LWIP_SNMP + trap_flag = 0; +#endif + /* use debug flags defined by debug.h */ + debug_flags = LWIP_DBG_OFF; + + while ((ch = getopt_long(argc, argv, "dhg:i:m:t:", longopts, NULL)) != -1) { + switch (ch) { + case 'd': + debug_flags |= (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT); + break; + case 'h': + usage(); + exit(0); + break; + case 'g': + ip4addr_aton(optarg, &gw); + break; + case 'i': + ip4addr_aton(optarg, &ipaddr); + break; + case 'm': + ip4addr_aton(optarg, &netmask); + break; + case 't': +#if LWIP_SNMP + trap_flag = !0; + /* @todo: remove this authentraps tweak + when we have proper SET & non-volatile mem */ + snmpauthentraps_set = 1; + ipaddr_aton(optarg, &trap_addr); + strncpy(ip_str, ipaddr_ntoa(&trap_addr),sizeof(ip_str)); + printf("SNMP trap destination %s\n", ip_str); +#endif + break; + default: + usage(); + break; + } + } + argc -= optind; + argv += optind; + + strncpy(ip_str, ip4addr_ntoa(&ipaddr), sizeof(ip_str)); + strncpy(nm_str, ip4addr_ntoa(&netmask), sizeof(nm_str)); + strncpy(gw_str, ip4addr_ntoa(&gw), sizeof(gw_str)); + printf("Host at %s mask %s gateway %s\n", ip_str, nm_str, gw_str); + + +#ifdef PERF + perf_init("/tmp/minimal.perf"); +#endif /* PERF */ + + lwip_init(); + + printf("TCP/IP initialized.\n"); + + netif_add(&netif, &ipaddr, &netmask, &gw, NULL, tapif_init, ethernet_input); + netif_set_default(&netif); + netif_set_up(&netif); +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(&netif, 1); +#endif + +#if LWIP_SNMP + /* initialize our private example MIB */ + lwip_privmib_init(); + + /* snmp_trap_dst_ip_set(0,&trap_addr); */ + /* snmp_trap_dst_enable(0,trap_flag); */ + +#if SNMP_LWIP_MIB2 +#if SNMP_USE_NETCONN + snmp_threadsync_init(&snmp_mib2_lwip_locks, snmp_mib2_lwip_synchronizer); +#endif + snmp_mib2_set_syscontact_readonly((const u8_t*)"root", NULL); + snmp_mib2_set_syslocation_readonly((const u8_t*)"lwIP development PC", NULL); + snmp_mib2_set_sysdescr((const u8_t*)"minimal example", NULL); +#endif /* SNMP_LWIP_MIB2 */ + + /* snmp_set_snmpenableauthentraps(&snmpauthentraps_set); */ + snmp_set_mibs(mibs, LWIP_ARRAYSIZE(mibs)); + snmp_init(); +#endif /* LWIP_SNMP */ + + udpecho_raw_init(); + tcpecho_raw_init(); + + printf("Applications started.\n"); + + + while (1) { + /* poll netif, pass packet to lwIP */ + tapif_select(&netif); + + sys_check_timeouts(); + } + + return 0; +} diff --git a/ext/lwip/test/unit/lwipopts.h b/ext/lwip-contrib/ports/unix/port/include/arch/cc.h old mode 100755 new mode 100644 similarity index 52% rename from ext/lwip/test/unit/lwipopts.h rename to ext/lwip-contrib/ports/unix/port/include/arch/cc.h index 9bd672b..3e77e65 --- a/ext/lwip/test/unit/lwipopts.h +++ b/ext/lwip-contrib/ports/unix/port/include/arch/cc.h @@ -1,65 +1,70 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_LWIPOPTS_H -#define LWIP_HDR_LWIPOPTS_H - -/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ -#define NO_SYS 1 -#define SYS_LIGHTWEIGHT_PROT 0 -#define LWIP_NETCONN 0 -#define LWIP_SOCKET 0 - -/* Enable DHCP to test it, disable UDP checksum to easier inject packets */ -#define LWIP_DHCP 1 - -/* Minimal changes to opt.h required for tcp unit tests: */ -#define MEM_SIZE 16000 -#define TCP_SND_QUEUELEN 40 -#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN -#define TCP_SND_BUF (12 * TCP_MSS) -#define TCP_WND (10 * TCP_MSS) -#define LWIP_WND_SCALE 1 -#define TCP_RCV_SCALE 0 -#define PBUF_POOL_SIZE 400 /* pbuf tests need ~200KByte */ - -/* Enable IGMP and MDNS for MDNS tests */ -#define LWIP_IGMP 1 -#define LWIP_MDNS_RESPONDER 1 -#define LWIP_NUM_NETIF_CLIENT_DATA (LWIP_MDNS_RESPONDER) - -/* Minimal changes to opt.h required for etharp unit tests: */ -#define ETHARP_SUPPORT_STATIC_ENTRIES 1 - -/* MIB2 stats are required to check IPv4 reassembly results */ -#define MIB2_STATS 1 - -#endif /* LWIP_HDR_LWIPOPTS_H */ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_ARCH_CC_H +#define LWIP_ARCH_CC_H + +/* see https://sourceforge.net/p/predef/wiki/OperatingSystems/ */ +#if defined __ANDROID__ +#define LWIP_UNIX_ANDROID +#elif defined __linux__ +#define LWIP_UNIX_LINUX +#elif defined __APPLE__ +#define LWIP_UNIX_MACH +#elif defined __OpenBSD__ +#define LWIP_UNIX_OPENBSD +#elif defined __CYGWIN__ +#define LWIP_UNIX_CYGWIN +#endif + +#define LWIP_TIMEVAL_PRIVATE 0 +#include + +#define LWIP_ERRNO_INCLUDE + +#define LWIP_RAND() ((u32_t)rand()) + +/* different handling for unit test, normally not needed */ +#ifdef LWIP_NOASSERT_ON_ERROR +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ + handler;}} while(0) +#endif + +#if defined(LWIP_UNIX_ANDROID) && defined(FD_SET) +typedef __kernel_fd_set fd_set; +#endif + +struct sio_status_s; +typedef struct sio_status_s sio_status_t; +#define sio_fd_t sio_status_t* +#define __sio_fd_t_defined + +#endif /* LWIP_ARCH_CC_H */ diff --git a/ext/lwip/test/fuzz/lwipopts.h b/ext/lwip-contrib/ports/unix/port/include/arch/perf.h old mode 100755 new mode 100644 similarity index 51% rename from ext/lwip/test/fuzz/lwipopts.h rename to ext/lwip-contrib/ports/unix/port/include/arch/perf.h index 64921ea..326ac9e --- a/ext/lwip/test/fuzz/lwipopts.h +++ b/ext/lwip-contrib/ports/unix/port/include/arch/perf.h @@ -1,68 +1,63 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_LWIPOPTS_H__ -#define LWIP_HDR_LWIPOPTS_H__ - -/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ -#define NO_SYS 1 -#define LWIP_NETCONN 0 -#define LWIP_SOCKET 0 -#define SYS_LIGHTWEIGHT_PROT 0 - -#define LWIP_IPV6 1 -#define IPV6_FRAG_COPYHEADER 1 -#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 0 - -/* Enable DHCP to test it */ -#define LWIP_DHCP 1 - -/* Turn off checksum verification of fuzzed data */ -#define CHECKSUM_CHECK_IP 0 -#define CHECKSUM_CHECK_UDP 0 -#define CHECKSUM_CHECK_TCP 0 -#define CHECKSUM_CHECK_ICMP 0 -#define CHECKSUM_CHECK_ICMP6 0 - -/* Minimal changes to opt.h required for tcp unit tests: */ -#define MEM_SIZE 16000 -#define TCP_SND_QUEUELEN 40 -#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN -#define TCP_SND_BUF (12 * TCP_MSS) -#define TCP_WND (10 * TCP_MSS) -#define LWIP_WND_SCALE 1 -#define TCP_RCV_SCALE 0 -#define PBUF_POOL_SIZE 400 /* pbuf tests need ~200KByte */ - -/* Minimal changes to opt.h required for etharp unit tests: */ -#define ETHARP_SUPPORT_STATIC_ENTRIES 1 - -#endif /* LWIP_HDR_LWIPOPTS_H__ */ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_ARCH_PERF_H +#define LWIP_ARCH_PERF_H + +#include + +#ifdef PERF +#define PERF_START { \ + unsigned long __c1l, __c1h, __c2l, __c2h; \ + __asm__(".byte 0x0f, 0x31" : "=a" (__c1l), "=d" (__c1h)) +#define PERF_STOP(x) __asm__(".byte 0x0f, 0x31" : "=a" (__c2l), "=d" (__c2h)); \ + perf_print(__c1l, __c1h, __c2l, __c2h, x);} + +/*#define PERF_START do { \ + struct tms __perf_start, __perf_end; \ + times(&__perf_start) +#define PERF_STOP(x) times(&__perf_end); \ + perf_print_times(&__perf_start, &__perf_end, x);\ + } while(0)*/ +#else /* PERF */ +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ +#endif /* PERF */ + +void perf_print(unsigned long c1l, unsigned long c1h, + unsigned long c2l, unsigned long c2h, + char *key); + +void perf_print_times(struct tms *start, struct tms *end, char *key); + +void perf_init(char *fname); + +#endif /* LWIP_ARCH_PERF_H */ diff --git a/ext/lwip-contrib/ports/unix/port/include/arch/sys_arch.h b/ext/lwip-contrib/ports/unix/port/include/arch/sys_arch.h new file mode 100644 index 0000000..f11ae33 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/include/arch/sys_arch.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_ARCH_SYS_ARCH_H +#define LWIP_ARCH_SYS_ARCH_H + +#define SYS_MBOX_NULL NULL +#define SYS_SEM_NULL NULL + +typedef u32_t sys_prot_t; + +struct sys_sem; +typedef struct sys_sem * sys_sem_t; +#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL)) +#define sys_sem_valid_val(sem) ((sem) != NULL) +#define sys_sem_set_invalid(sem) do { if((sem) != NULL) { *(sem) = NULL; }}while(0) +#define sys_sem_set_invalid_val(sem) do { (sem) = NULL; }while(0) + +struct sys_mutex; +typedef struct sys_mutex * sys_mutex_t; +#define sys_mutex_valid(mutex) sys_sem_valid(mutex) +#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) + +struct sys_mbox; +typedef struct sys_mbox * sys_mbox_t; +#define sys_mbox_valid(mbox) sys_sem_valid(mbox) +#define sys_mbox_valid_val(mbox) sys_sem_valid_val(mbox) +#define sys_mbox_set_invalid(mbox) sys_sem_set_invalid(mbox) +#define sys_mbox_set_invalid_val(mbox) sys_sem_set_invalid_val(mbox) + +struct sys_thread; +typedef struct sys_thread * sys_thread_t; + +#endif /* LWIP_ARCH_SYS_ARCH_H */ + diff --git a/ext/lwip-contrib/ports/unix/port/include/netif/delif.h b/ext/lwip-contrib/ports/unix/port/include/netif/delif.h new file mode 100644 index 0000000..6672a73 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/include/netif/delif.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_DELIF_H +#define LWIP_DELIF_H + +#include "lwip/netif.h" + +#include "lwip/pbuf.h" + +err_t delif_init(struct netif *netif); +err_t delif_init_thread(struct netif *netif); + +#endif /* LWIP_DELIF_H */ diff --git a/ext/lwip-contrib/ports/unix/port/include/netif/dropif.h b/ext/lwip-contrib/ports/unix/port/include/netif/dropif.h new file mode 100644 index 0000000..a173b5f --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/include/netif/dropif.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_DROPIF_H +#define LWIP_DROPIF_H + +#include "lwip/netif.h" + +#include "lwip/pbuf.h" + +err_t dropif_init(struct netif *netif); + +#endif /* LWIP_DROPIF_H */ diff --git a/ext/lwip-contrib/ports/unix/port/include/netif/fifo.h b/ext/lwip-contrib/ports/unix/port/include/netif/fifo.h new file mode 100644 index 0000000..6c2ad20 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/include/netif/fifo.h @@ -0,0 +1,54 @@ +#ifndef FIFO_H +#define FIFO_H + +#include "lwip/sys.h" + +/** How many bytes in fifo */ +#define FIFOSIZE 2048 + +/** fifo data structure, this one is passed to all fifo functions */ +typedef struct fifo_t { + u8_t data[FIFOSIZE+10]; /* data segment, +10 is a hack probably not needed.. FIXME! */ + int dataslot; /* index to next char to be read */ + int emptyslot; /* index to next empty slot */ + int len; /* len probably not needed, may be calculated from dataslot and emptyslot in conjunction with FIFOSIZE */ + + sys_sem_t sem; /* semaphore protecting simultaneous data manipulation */ + sys_sem_t getSem; /* sepaphore used to signal new data if getWaiting is set */ + u8_t getWaiting; /* flag used to indicate that fifoget is waiting for data. fifoput is suposed to clear */ + /* this flag prior to signaling the getSem semaphore */ +} fifo_t; + + +/** +* Get a character from fifo +* Blocking call. +* @param fifo pointer to fifo data structure +* @return character read from fifo +*/ +u8_t fifoGet(fifo_t * fifo); + +/** +* Get a character from fifo +* Non blocking call. +* @param fifo pointer to fifo data structure +* @return character read from fifo, or < zero if non was available +*/ +s16_t fifoGetNonBlock(fifo_t * fifo); + +/** +* fifoput is called by the signalhandler when new data has arrived (or some other event is indicated) +* fifoput reads directly from the serialport and is thus highly dependent on unix arch at this moment +* @param fifo pointer to fifo data structure +* @param fd unix file descriptor +*/ +void fifoPut(fifo_t * fifo, int fd); + +/** +* fifoinit initiate fifo +* @param fifo pointer to fifo data structure, allocated by the user +*/ +void fifoInit(fifo_t * fifo); + +#endif + diff --git a/ext/lwip-contrib/ports/unix/port/include/netif/list.h b/ext/lwip-contrib/ports/unix/port/include/netif/list.h new file mode 100644 index 0000000..2c4d142 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/include/netif/list.h @@ -0,0 +1,26 @@ + +#ifndef LWIP_LIST_H +#define LWIP_LIST_H + +struct elem; + +struct list { + struct elem *first, *last; + int size, elems; +}; + +struct elem { + struct elem *next; + void *data; +}; + +struct list *list_new(int size); +int list_push(struct list *list, void *data); +void *list_pop(struct list *list); +void *list_first(struct list *list); +int list_elems(struct list *list); +void list_delete(struct list *list); +int list_remove(struct list *list, void *elem); +void list_map(struct list *list, void (* func)(void *arg)); + +#endif diff --git a/ext/lwip/COPYING b/ext/lwip-contrib/ports/unix/port/include/netif/pcapif.h old mode 100755 new mode 100644 similarity index 88% rename from ext/lwip/COPYING rename to ext/lwip-contrib/ports/unix/port/include/netif/pcapif.h index 0d77a67..ef7abd5 --- a/ext/lwip/COPYING +++ b/ext/lwip-contrib/ports/unix/port/include/netif/pcapif.h @@ -1,33 +1,39 @@ -/* - * Copyright (c) 2001, 2002 Swedish Institute of Computer Science. - * All rights reserved. - * - * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - - +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_PCAPIF_H +#define LWIP_PCAPIF_H + +#include "lwip/netif.h" + +err_t pcapif_init(struct netif *netif); + +#endif /* LWIP_PCAPIF_H */ diff --git a/ext/lwip-contrib/ports/unix/port/include/netif/sio.h b/ext/lwip-contrib/ports/unix/port/include/netif/sio.h new file mode 100644 index 0000000..4822b53 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/include/netif/sio.h @@ -0,0 +1,60 @@ +#ifndef SIO_UNIX_H +#define SIO_UNIX_H + +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "netif/fifo.h" +/*#include "netif/pppif.h"*/ + +struct sio_status_s { + int fd; + fifo_t myfifo; +}; + +/* BAUDRATE is defined in sio.c as it is implementation specific */ +/** Baudrates */ +typedef enum sioBaudrates { + SIO_BAUD_9600, + SIO_BAUD_19200, + SIO_BAUD_38400, + SIO_BAUD_57600, + SIO_BAUD_115200 +} sioBaudrates; + +/** +* Poll for a new character from incoming data stream +* @param siostat siostatus struct, contains sio instance data, given by sio_open +* @return char read from input stream, or < 0 if no char was available +*/ +s16_t sio_poll(sio_status_t * siostat); + +/** +* Parse incoming characters until a string str is recieved, blocking call +* @param str zero terminated string to expect +* @param siostat siostatus struct, contains sio instance data, given by sio_open +*/ +void sio_expect_string(u8_t *str, sio_status_t * siostat); + +/** +* Write a char to output data stream +* @param str pointer to a zero terminated string +* @param siostat siostatus struct, contains sio instance data, given by sio_open +*/ +void sio_send_string(u8_t *str, sio_status_t * siostat); + +/** +* Flush outbuffer (send everything in buffer now), useful if some layer below is +* holding on to data, waitng to fill a buffer +* @param siostat siostatus struct, contains sio instance data, given by sio_open +*/ +void sio_flush( sio_status_t * siostat ); + +/** +* Change baudrate of port, may close and reopen port +* @param baud new baudrate +* @param siostat siostatus struct, contains sio instance data, given by sio_open +*/ +void sio_change_baud( sioBaudrates baud, sio_status_t * siostat ); + +#endif + diff --git a/ext/lwip-contrib/ports/unix/port/include/netif/tapif.h b/ext/lwip-contrib/ports/unix/port/include/netif/tapif.h new file mode 100644 index 0000000..7f8b616 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/include/netif/tapif.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_TAPIF_H +#define LWIP_TAPIF_H + +#include "lwip/netif.h" + +err_t tapif_init(struct netif *netif); +#if NO_SYS +int tapif_select(struct netif *netif); +#endif /* NO_SYS */ + +#endif /* LWIP_TAPIF_H */ diff --git a/ext/lwip-contrib/ports/unix/port/include/netif/tcpdump.h b/ext/lwip-contrib/ports/unix/port/include/netif/tcpdump.h new file mode 100644 index 0000000..ecc41d3 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/include/netif/tcpdump.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_NETIF_TCPDUMP_H +#define LWIP_NETIF_TCPDUMP_H + +struct pbuf; +struct netif; + +void tcpdump_init(void); +void tcpdump(struct pbuf *p, struct netif *netif); + +#endif /* LWIP_NETIF_TCPDUMP_H */ diff --git a/ext/lwip-contrib/ports/unix/port/include/netif/tunif.h b/ext/lwip-contrib/ports/unix/port/include/netif/tunif.h new file mode 100644 index 0000000..b425c06 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/include/netif/tunif.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_TUNIF_H +#define LWIP_TUNIF_H + +#include "lwip/netif.h" + +#include "lwip/pbuf.h" + +err_t tunif_init(struct netif *netif); + +#endif /* LWIP_TUNIF_H */ diff --git a/ext/lwip-contrib/ports/unix/port/include/netif/unixif.h b/ext/lwip-contrib/ports/unix/port/include/netif/unixif.h new file mode 100644 index 0000000..10b782b --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/include/netif/unixif.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_UNIXIF_H +#define LWIP_UNIXIF_H + +#include "lwip/netif.h" + +err_t unixif_init_server(struct netif *netif); +err_t unixif_init_client(struct netif *netif); + +#endif /* LWIP_UNIXIF_H */ diff --git a/ext/lwip-contrib/ports/unix/port/netif/delif.c b/ext/lwip-contrib/ports/unix/port/netif/delif.c new file mode 100644 index 0000000..9e35fc1 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/netif/delif.c @@ -0,0 +1,384 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" + +#if !NO_SYS + +#include "lwip/debug.h" + +#include + +#include "lwip/def.h" +#include "netif/delif.h" + +#ifdef LWIP_UNIX_LINUX +#include "netif/tapif.h" +#else /* LWIP_UNIX_LINUX */ +#include "netif/tunif.h" +#endif /* LWIP_UNIX_LINUX */ + +#include "lwip/sys.h" +#include "lwip/timeouts.h" + +#ifndef DELIF_DEBUG +#define DELIF_DEBUG LWIP_DBG_OFF +#endif + +#define DELIF_INPUT_DROPRATE 0.1 +#define DELIF_OUTPUT_DROPRATE 0.1 + +#define DELIF_INPUT_DELAY 500 /* Miliseconds. */ +#define DELIF_OUTPUT_DELAY 500 /* Miliseconds. */ + +#define DELIF_TIMEOUT 10 + +struct delif { + err_t (* input)(struct pbuf *p, struct netif *inp); + struct netif *netif; +}; + +struct delif_pbuf { + struct delif_pbuf *next; + struct pbuf *p; + ip_addr_t ipaddr; + unsigned int time; +}; + +static struct delif_pbuf *input_list = NULL; +static struct delif_pbuf *output_list = NULL; +/*-----------------------------------------------------------------------------------*/ +static void +delif_input_timeout(void *arg) +{ + struct netif *netif; + struct delif *delif; + struct delif_pbuf *dp; + unsigned int timeout, now; + + timeout = DELIF_TIMEOUT; + + netif = (struct netif*)arg; + delif = (struct delif*)netif->state; + + /* Check if there is anything on the input list. */ + dp = input_list; + while (dp != NULL) { + now = sys_now(); + + if (dp->time <= now) { + delif->input(dp->p, netif); + if (dp->next != NULL) { + if (dp->next->time > now) { + timeout = dp->next->time - now; + } else { + timeout = 0; + } + LWIP_DEBUGF(DELIF_DEBUG, ("delif_output_timeout: timeout %u.\n", timeout)); + + } + input_list = dp->next; + free(dp); + dp = input_list; + } else { + dp = dp->next; + } + } + + sys_timeout(timeout, delif_input_timeout, arg); +} +/*-----------------------------------------------------------------------------------*/ +static void +delif_output_timeout(void *arg) +{ + struct netif *netif; + struct delif *delif; + struct delif_pbuf *dp; + unsigned int timeout, now; + + timeout = DELIF_TIMEOUT; + + netif = (struct netif*)arg; + delif = (struct delif*)netif->state; + + /* Check if there is anything on the output list. */ + dp = output_list; + while (dp != NULL) { + now = sys_now(); + if (dp->time <= now) { + LWIP_DEBUGF(DELIF_DEBUG, ("delif_output_timeout: now %u dp->time %u\n", + now, dp->time)); + +#if LWIP_IPV4 + if(!IP_IS_V6_VAL(dp->ipaddr)) { + delif->netif->output(delif->netif, dp->p, ip_2_ip4(&dp->ipaddr)); + } +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 + if(IP_IS_V6_VAL(dp->ipaddr)) { + delif->netif->output_ip6(delif->netif, dp->p, ip_2_ip6(&dp->ipaddr)); + } +#endif /* LWIP_IPV6 */ + + if (dp->next != NULL) { + if (dp->next->time > now) { + timeout = dp->next->time - now; + } else { + timeout = 0; + } + LWIP_DEBUGF(DELIF_DEBUG, ("delif_output_timeout: timeout %u.\n", timeout)); + + } + pbuf_free(dp->p); + + output_list = dp->next; + free(dp); + dp = output_list; + } else { + dp = dp->next; + } + } + + sys_timeout(timeout, delif_output_timeout, arg); +} +/*-----------------------------------------------------------------------------------*/ +static err_t +delif_output(struct netif *netif, struct pbuf *p, const ip_addr_t *ipaddr) +{ + struct delif_pbuf *dp, *np; + char *data; + + LWIP_UNUSED_ARG(netif); + + LWIP_DEBUGF(DELIF_DEBUG, ("delif_output\n")); + +#ifdef DELIF_OUTPUT_DROPRATE + if (((double)rand()/(double)RAND_MAX) < DELIF_OUTPUT_DROPRATE) { + LWIP_DEBUGF(DELIF_DEBUG, ("delif_output: Packet dropped\n")); + return ERR_BUF; + } +#endif /* DELIF_OUTPUT_DROPRATE */ + + LWIP_DEBUGF(DELIF_DEBUG, ("delif_output\n")); + + dp = (struct delif_pbuf*)malloc(sizeof(struct delif_pbuf)); + data = (char*)malloc(p->tot_len); + + pbuf_copy_partial(p, data, p->tot_len, 0); + + dp->p = pbuf_alloc(PBUF_LINK, 0, PBUF_ROM); + dp->p->payload = data; + dp->p->len = p->tot_len; + dp->p->tot_len = p->tot_len; + dp->ipaddr = *ipaddr; + dp->time = sys_now() + DELIF_OUTPUT_DELAY; + dp->next = NULL; + if (output_list == NULL) { + output_list = dp; + } else { + for(np = output_list; np->next != NULL; np = np->next); + np->next = dp; + } + + return ERR_OK; +} + +#if LWIP_IPV4 +static err_t +delif_output4(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr) +{ + ip_addr_t ip; + if (ipaddr != NULL) { + ip_addr_copy_from_ip4(ip, *ipaddr); + } else { + ip = *IP_ADDR_ANY; + } + return delif_output(netif, p, &ip); +} +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 +static err_t +delif_output6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) +{ + ip_addr_t ip; + if (ipaddr != NULL) { + ip_addr_copy_from_ip6(ip, *ipaddr); + } else { + ip = *IP6_ADDR_ANY; + } + return delif_output(netif, p, &ip); +} +#endif /* LWIP_IPV6 */ +/*-----------------------------------------------------------------------------------*/ +static err_t +delif_input(struct pbuf *p, struct netif *inp) +{ + struct delif_pbuf *dp, *np; + + LWIP_UNUSED_ARG(inp); + + LWIP_DEBUGF(DELIF_DEBUG, ("delif_input\n")); +#ifdef DELIF_INPUT_DROPRATE + if (((double)rand()/(double)RAND_MAX) < DELIF_INPUT_DROPRATE) { + LWIP_DEBUGF(DELIF_DEBUG, ("delif_input: Packet dropped\n")); + pbuf_free(p); + return ERR_OK; + } +#endif /* DELIF_INPUT_DROPRATE */ + + dp = (struct delif_pbuf*)malloc(sizeof(struct delif_pbuf)); + dp->p = p; + dp->time = sys_now() + DELIF_INPUT_DELAY; + dp->next = NULL; + + if (input_list == NULL) { + input_list = dp; + } else { + for(np = input_list; np->next != NULL; np = np->next); + np->next = dp; + } + + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +err_t +delif_init(struct netif *netif) +{ + struct delif *del; + + del = (struct delif*)malloc(sizeof(struct delif)); + if (!del) { + return ERR_MEM; + } + netif->state = del; + netif->name[0] = 'd'; + netif->name[1] = 'e'; + +#if LWIP_IPV4 + netif->output = delif_output4; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + netif->output_ip6 = delif_output6; +#endif /* LWIP_IPV6 */ + + del->netif = (struct netif*)malloc(sizeof(struct netif)); + if (!del->netif) { + free(del); + return ERR_MEM; + } + +#ifdef LWIP_UNIX_LINUX + tapif_init(del->netif); +#else /* LWIP_UNIX_LINUX */ + tunif_init(del->netif); +#endif /* LWIP_UNIX_LINUX */ + + del->input = netif->input; + del->netif->input = delif_input; + + sys_timeout(DELIF_TIMEOUT, delif_input_timeout, netif); + sys_timeout(DELIF_TIMEOUT, delif_output_timeout, netif); + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +static void +delif_thread(void *arg) +{ + struct netif *netif = (struct netif*)arg; + struct delif *del; + sys_sem_t sem; + + del = (struct delif*)netif->state; +#ifdef LWIP_UNIX_LINUX + tapif_init(del->netif); +#else /* LWIP_UNIX_LINUX */ + tunif_init(del->netif); +#endif /* LWIP_UNIX_LINUX */ + + sys_timeout(DELIF_TIMEOUT, delif_input_timeout, netif); + sys_timeout(DELIF_TIMEOUT, delif_output_timeout, netif); + + if(sys_sem_new(&sem, 0) != ERR_OK) { + LWIP_ASSERT("Failed to create semaphore", 0); + } + sys_sem_wait(&sem); +} +/*-----------------------------------------------------------------------------------*/ +err_t +delif_init_thread(struct netif *netif) +{ + struct delif *del; + + LWIP_DEBUGF(DELIF_DEBUG, ("delif_init_thread\n")); + + del = (struct delif*)malloc(sizeof(struct delif)); + if (!del) { + return ERR_MEM; + } + + netif->state = del; + netif->name[0] = 'd'; + netif->name[1] = 'e'; + + del->netif = (struct netif*)malloc(sizeof(struct netif)); + if (!del->netif) { + free(del); + return ERR_MEM; + } + +#if LWIP_IPV4 + netif->output = delif_output4; + netif_set_addr(del->netif, netif_ip4_addr(netif), netif_ip4_netmask(netif), netif_ip4_gw(netif)); +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 + { + s8_t i; + netif->output_ip6 = delif_output6; + for(i=0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + netif_ip6_addr_set(del->netif, i, netif_ip6_addr(netif, i)); + } + } +#endif /* LWIP_IPV6 */ + + del->input = netif->input; + del->netif->input = delif_input; + + sys_thread_new("delif_thread", delif_thread, netif, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ + +#endif /* !NO_SYS */ diff --git a/ext/lwip-contrib/ports/unix/port/netif/fifo.c b/ext/lwip-contrib/ports/unix/port/netif/fifo.c new file mode 100644 index 0000000..9fee0bd --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/netif/fifo.c @@ -0,0 +1,139 @@ +/* Author: Magnus Ivarsson */ + +/* ---------------------------------------------- */ +/* --- fifo 4 unix ------------------------------ */ +/* ---------------------------------------------- */ +#include "lwip/err.h" +#include "netif/fifo.h" +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/sys.h" +#include "lwip/arch.h" +#include + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef SIO_FIFO_DEBUG +#define SIO_FIFO_DEBUG LWIP_DBG_OFF +#endif + +u8_t fifoGet(fifo_t * fifo) +{ + u8_t c; + + sys_sem_wait(&fifo->sem); /* enter critical section */ + + if (fifo->dataslot == fifo->emptyslot) + { + fifo->getWaiting = TRUE; /* tell putFifo to signal us when data is available */ + sys_sem_signal(&fifo->sem); /* leave critical section (allow input from serial port..) */ + sys_sem_wait(&fifo->getSem); /* wait 4 data */ + sys_sem_wait(&fifo->sem); /* reenter critical section */ + } + + c = fifo->data[fifo->dataslot++]; + fifo->len--; + + if (fifo->dataslot == FIFOSIZE) + { + fifo->dataslot = 0; + } + sys_sem_signal(&fifo->sem); /* leave critical section */ + return c; +} + + +s16_t fifoGetNonBlock(fifo_t * fifo) +{ + u16_t c; + + sys_sem_wait(&fifo->sem); /* enter critical section */ + + if (fifo->dataslot == fifo->emptyslot) + { + /* empty fifo */ + c = -1; + } + else + { + c = fifo->data[fifo->dataslot++]; + fifo->len--; + + if (fifo->dataslot == FIFOSIZE) + { + fifo->dataslot = 0; + } + } + sys_sem_signal(&fifo->sem); /* leave critical section */ + return c; +} + + +void fifoPut(fifo_t * fifo, int fd) +{ + /* FIXME: mutex around struct data.. */ + int cnt=0; + + sys_sem_wait(&fifo->sem ); /* enter critical */ + + LWIP_DEBUGF( SIO_FIFO_DEBUG,("fifoput: len%d dat%d empt%d --> ", fifo->len, fifo->dataslot, fifo->emptyslot ) ); + + if ( fifo->emptyslot < fifo->dataslot ) + { + cnt = read( fd, &fifo->data[fifo->emptyslot], fifo->dataslot - fifo->emptyslot ); + } + else + { + cnt = read( fd, &fifo->data[fifo->emptyslot], FIFOSIZE-fifo->emptyslot ); + } + fifo->emptyslot += cnt; + fifo->len += cnt; + + LWIP_DEBUGF( SIO_FIFO_DEBUG,("len%d dat%d empt%d\n", fifo->len, fifo->dataslot, fifo->emptyslot ) ); + + if ( fifo->len > FIFOSIZE ) + { + printf( "ERROR: fifo overrun detected len=%d, flushing\n", fifo->len ); + fifo->dataslot = 0; + fifo->emptyslot = 0; + fifo->len = 0; + } + + if ( fifo->emptyslot == FIFOSIZE ) + { + fifo->emptyslot = 0; + LWIP_DEBUGF( SIO_FIFO_DEBUG, ("(WRAP) ") ); + + sys_sem_signal(&fifo->sem ); /* leave critical */ + fifoPut( fifo, fd ); + return; + } + if ( fifo->getWaiting ) + { + fifo->getWaiting = FALSE; + sys_sem_signal(&fifo->getSem ); + } + + sys_sem_signal(&fifo->sem ); /* leave critical */ + return; +} + + +void fifoInit(fifo_t * fifo) +{ + fifo->dataslot = 0; + fifo->emptyslot = 0; + fifo->len = 0; + if(sys_sem_new(&fifo->sem, 1) != ERR_OK) { /* critical section 1=free to enter */ + LWIP_ASSERT("Failed to create semaphore", 0); + } + if(sys_sem_new(&fifo->getSem, 0) != ERR_OK) { /* 0 = no one waiting */ + LWIP_ASSERT("Failed to create semaphore", 0); + } + fifo->getWaiting = FALSE; +} diff --git a/ext/lwip-contrib/ports/unix/port/netif/list.c b/ext/lwip-contrib/ports/unix/port/netif/list.c new file mode 100644 index 0000000..fd61f53 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/netif/list.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + + +#include +#include + + +/*-----------------------------------------------------------------------------------*/ +struct list * +list_new(int size) +{ + struct list *list; + list = (struct list *)malloc(sizeof(struct list)); + list->first = list->last = NULL; + list->size = size; + list->elems = 0; + return list; +} +/*-----------------------------------------------------------------------------------*/ +int +list_push(struct list *list, void *data) +{ + struct elem *elem; + + if (list->elems < list->size) { + elem = (struct elem *)malloc(sizeof(struct elem)); + elem->data = data; + elem->next = NULL; + if (list->last != NULL) { + list->last->next = elem; + } + list->last = elem; + if (list->first == NULL) { + list->first = elem; + } + list->elems++; + return 1; + } + return 0; +} +/*-----------------------------------------------------------------------------------*/ +void * +list_pop(struct list *list) +{ + struct elem *elem; + void *data; + + if (list->elems > 0) { + elem = list->first; + if (elem == list->last) { + list->last = elem->next; + } + list->first = elem->next; + + list->elems--; + + data = elem->data; + free(elem); + + return data; + } + return NULL; +} +/*-----------------------------------------------------------------------------------*/ +void * +list_first(struct list *list) +{ + return list->first; +} +/*-----------------------------------------------------------------------------------*/ +int +list_elems(struct list *list) +{ + return list->elems; +} +/*-----------------------------------------------------------------------------------*/ +void +list_delete(struct list *list) +{ + while (list_pop(list) != NULL); + free(list); +} +/*-----------------------------------------------------------------------------------*/ +int +list_remove(struct list *list, void *elem) +{ + struct elem *e, *p; + + p = NULL; + for(e = list->first; e != NULL; e = e->next) { + if (e->data == elem) { + if (p != NULL) { + p->next = e->next; + } else { + list->first = e->next; + } + if (list->last == e) { + list->last = p; + if (p != NULL) { + p->next = NULL; + } + } + free(e); + list->elems--; + return 1; + } + p = e; + } + return 0; +} +/*-----------------------------------------------------------------------------------*/ +void +list_map(struct list *list, void (* func)(void *arg)) +{ + struct elem *e; + + for(e = list->first; e != NULL; e = e->next) { + func(e->data); + } +} +/*-----------------------------------------------------------------------------------*/ + diff --git a/ext/lwip-contrib/ports/unix/port/netif/pcapif.c b/ext/lwip-contrib/ports/unix/port/netif/pcapif.c new file mode 100644 index 0000000..afd0d08 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/netif/pcapif.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef linux /* Apparently, this doesn't work under Linux. */ + +#include "lwip/debug.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "netif/etharp.h" + +#include "lwip/stats.h" + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "netif/unixif.h" +#include "lwip/sys.h" + +#include "lwip/ip.h" + + +#if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP) +#include "netif/tcpdump.h" +#endif /* LWIP_DEBUG && LWIP_TCPDUMP */ + +struct pcapif { + pcap_t *pd; + sys_sem_t sem; + u8_t pkt[2048]; + u32_t len; + u32_t lasttime; + struct pbuf *p; + struct eth_addr *ethaddr; +}; + +static char errbuf[PCAP_ERRBUF_SIZE]; + +/*-----------------------------------------------------------------------------------*/ +static err_t +pcapif_output(struct netif *netif, struct pbuf *p, + ip_addr_t *ipaddr) +{ + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +static void +timeout(void *arg) +{ + struct netif *netif; + struct pcapif *pcapif; + struct pbuf *p; + struct eth_hdr *ethhdr; + + netif = (struct netif *)arg; + pcapif = netif->state; + ethhdr = (struct eth_hdr *)pcapif->pkt; + + + if (lwip_htons(ethhdr->type) != ETHTYPE_IP || + ip_lookup(pcapif->pkt + 14, netif)) { + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_LINK, pcapif->len, PBUF_POOL); + + if (p != NULL) { + pbuf_take(p, pcapif->pkt, pcapif->len); + +#if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP) + tcpdump(p, netif); +#endif /* LWIP_DEBUG && LWIP_TCPDUMP */ + + ethhdr = p->payload; + switch (lwip_htons(ethhdr->type)) { + /* IP or ARP packet? */ + case ETHTYPE_IP: + case ETHTYPE_ARP: +#if PPPOE_SUPPORT + /* PPPoE packet? */ + case ETHTYPE_PPPOEDISC: + case ETHTYPE_PPPOE: +#endif /* PPPOE_SUPPORT */ + /* full packet send to tcpip_thread to process */ + if (netif->input(p, netif) != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + p = NULL; + } + break; + default: + pbuf_free(p); + break; + } + } + } else { + printf("ip_lookup dropped\n"); + } + + sys_sem_signal(&pcapif->sem); +} +/*-----------------------------------------------------------------------------------*/ +static void +callback(u_char *arg, const struct pcap_pkthdr *hdr, const u_char *pkt) +{ + struct netif *netif; + struct pcapif *pcapif; + u32_t time, lasttime; + + netif = (struct netif *)arg; + pcapif = netif->state; + + pcapif->len = hdr->len; + + bcopy(pkt, pcapif->pkt, hdr->len); + + time = hdr->ts.tv_sec * 1000 + hdr->ts.tv_usec / 1000; + + lasttime = pcapif->lasttime; + pcapif->lasttime = time; + + + if (lasttime == 0) { + sys_timeout(1000, timeout, netif); + } else { + sys_timeout(time - lasttime, timeout, netif); + } +} +/*-----------------------------------------------------------------------------------*/ +static void +pcapif_thread(void *arg) +{ + struct netif *netif; + struct pcapif *pcapif; + netif = arg; + pcapif = netif->state; + + while (1) { + pcap_loop(pcapif->pd, 1, callback, (u_char *)netif); + sys_sem_wait(&pcapif->sem); + if (pcapif->p != NULL) { + netif->input(pcapif->p, netif); + } + } +} +/*-----------------------------------------------------------------------------------*/ +err_t +pcapif_init(struct netif *netif) +{ + struct pcapif *p; + + p = malloc(sizeof(struct pcapif)); + if (p == NULL) + return ERR_MEM; + netif->state = p; + netif->name[0] = 'p'; + netif->name[1] = 'c'; + netif->output = pcapif_output; + + p->pd = pcap_open_offline("pcapdump", errbuf); + if (p->pd == NULL) { + printf("pcapif_init: failed %s\n", errbuf); + return ERR_IF; + } + + if(sys_sem_new(&p->sem, 0) != ERR_OK) { + LWIP_ASSERT("Failed to create semaphore", 0); + } + p->p = NULL; + p->lasttime = 0; + + sys_thread_new("pcapif_thread", pcapif_thread, netif, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +#endif /* linux */ diff --git a/ext/lwip-contrib/ports/unix/port/netif/sio.c b/ext/lwip-contrib/ports/unix/port/netif/sio.c new file mode 100644 index 0000000..686b2cb --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/netif/sio.c @@ -0,0 +1,481 @@ +/* Author: Magnus Ivarsson */ + +/* to get rid of implicit function declarations */ +#define _XOPEN_SOURCE 600 +#define _GNU_SOURCE + +#include "netif/sio.h" +#include "netif/fifo.h" +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/sys.h" +#include "lwip/arch.h" +#include "lwip/sio.h" +#include "netif/ppp/ppp_opts.h" + +/* Following #undefs are here to keep compiler from issuing warnings + about them being double defined. (They are defined in lwip/inet.h + as well as the Unix #includes below.) */ +#undef htonl +#undef ntohl +#undef htons +#undef ntohs +#undef HTONL +#undef NTOHL +#undef HTONS +#undef NTOHS + +#include +#include +#if defined(LWIP_UNIX_OPENBSD) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef LWIP_HAVE_SLIPIF +#define LWIP_HAVE_SLIPIF 0 +#endif + +#if (PPP_SUPPORT || LWIP_HAVE_SLIPIF) && defined(LWIP_UNIX_LINUX) +#include +#endif + +/*#define BAUDRATE B19200 */ +/*#define BAUDRATE B57600 */ +#define BAUDRATE B115200 + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/* for all of you who dont define SIO_DEBUG in debug.h */ +#ifndef SIO_DEBUG +#define SIO_DEBUG 0 +#endif + + +/* typedef struct siostruct_t */ +/* { */ +/* sio_status_t *sio; */ +/* } siostruct_t; */ + +/** array of ((siostruct*)netif->state)->sio structs */ +static sio_status_t statusar[4]; + +#if ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF) +/* --private-functions----------------------------------------------------------------- */ +/** + * Signal handler for ttyXX0 to indicate bytes received + * one per interface is needed since we cannot send a instance number / pointer as callback argument (?) + */ +static void signal_handler_IO_0( int status ) +{ + LWIP_UNUSED_ARG(status); + LWIP_DEBUGF(SIO_DEBUG, ("SigHand: rxSignal channel 0\n")); + fifoPut( &statusar[0].myfifo, statusar[0].fd ); +} + +/** + * Signal handler for ttyXX1 to indicate bytes received + * one per interface is needed since we cannot send a instance number / pointer as callback argument (?) + */ +static void signal_handler_IO_1( int status ) +{ + LWIP_UNUSED_ARG(status); + LWIP_DEBUGF(SIO_DEBUG, ("SigHand: rxSignal channel 1\n")); + fifoPut( &statusar[1].myfifo, statusar[1].fd ); +} +#endif /* ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF) */ + +/** +* Initiation of serial device +* @param device string with the device name and path, eg. "/dev/ttyS0" +* @param devnum device number +* @param siostat status +* @return file handle to serial dev. +*/ +static int sio_init( char * device, int devnum, sio_status_t * siostat ) +{ + struct termios oldtio,newtio; +#if ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF) + struct sigaction saio; /* definition of signal action */ +#endif + int fd; + LWIP_UNUSED_ARG(siostat); + LWIP_UNUSED_ARG(devnum); + + /* open the device to be non-blocking (read will return immediately) */ + fd = open( device, O_RDWR | O_NOCTTY | O_NONBLOCK ); + if ( fd < 0 ) + { + perror( device ); + exit( -1 ); + } + +#if ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF) + /* install the signal handler before making the device asynchronous */ + switch ( devnum ) + { + case 0: + LWIP_DEBUGF( SIO_DEBUG, ("sioinit, signal_handler_IO_0\n") ); + saio.sa_handler = signal_handler_IO_0; + break; + case 1: + LWIP_DEBUGF( SIO_DEBUG, ("sioinit, signal_handler_IO_1\n") ); + saio.sa_handler = signal_handler_IO_1; + break; + default: + LWIP_DEBUGF( SIO_DEBUG,("sioinit, devnum not allowed\n") ); + break; + } + + saio.sa_flags = 0; +#if defined(LWIP_UNIX_LINUX) + saio.sa_restorer = NULL; +#endif /* LWIP_UNIX_LINUX */ + sigaction( SIGIO,&saio,NULL ); + + /* allow the process to receive SIGIO */ + if ( fcntl( fd, F_SETOWN, getpid( ) ) != 0) + { + perror( device ); + exit( -1 ); + } + /* Make the file descriptor asynchronous (the manual page says only + O_APPEND and O_NONBLOCK, will work with F_SETFL...) */ + if ( fcntl( fd, F_SETFL, FASYNC ) != 0) + { + perror( device ); + exit( -1 ); + } +#else + if ( fcntl( fd, F_SETFL, 0 ) != 0) + { + perror( device ); + exit( -1 ); + } + +#endif /* ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF) */ + + tcgetattr( fd,&oldtio ); /* save current port settings */ + /* set new port settings */ + /* see 'man termios' for further settings */ + memset(&newtio, 0, sizeof(newtio)); + newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD | CRTSCTS; + newtio.c_iflag = 0; + newtio.c_oflag = 0; + newtio.c_lflag = 0; /*ECHO; */ + newtio.c_cc[VMIN] = 1; /* Read 1 byte at a time, no timer */ + newtio.c_cc[VTIME] = 0; + + tcsetattr( fd,TCSANOW,&newtio ); + tcflush( fd, TCIOFLUSH ); + + return fd; +} + +/** +* +*/ +static void sio_speed( int fd, int speed ) +{ + struct termios oldtio,newtio; + /* int fd; */ + + LWIP_DEBUGF(SIO_DEBUG, ("sio_speed[%d]: baudcode:%d enter\n", fd, speed)); + + if ( fd < 0 ) + { + LWIP_DEBUGF(SIO_DEBUG, ("sio_speed[%d]: fd ERROR\n", fd)); + exit( -1 ); + } + + tcgetattr( fd,&oldtio ); /* get current port settings */ + + /* set new port settings + * see 'man termios' for further settings */ + memset(&newtio, 0, sizeof(newtio)); + newtio.c_cflag = speed | CS8 | CLOCAL | CREAD; /* | CRTSCTS; */ + newtio.c_iflag = 0; + newtio.c_oflag = 0; + newtio.c_lflag = 0; /*ECHO; */ + newtio.c_cc[VMIN] = 1; /* Read 1 byte at a time, no timer */ + newtio.c_cc[VTIME] = 0; + + tcsetattr( fd,TCSANOW,&newtio ); + tcflush( fd, TCIOFLUSH ); + + LWIP_DEBUGF(SIO_DEBUG, ("sio_speed[%d]: leave\n", fd)); +} + +/* --public-functions----------------------------------------------------------------------------- */ +void sio_send( u8_t c, sio_status_t * siostat ) +{ + /* sio_status_t * siostat = ((siostruct_t*)netif->state)->sio; */ + + if ( write( siostat->fd, &c, 1 ) <= 0 ) + { + LWIP_DEBUGF(SIO_DEBUG, ("sio_send[%d]: write refused\n", siostat->fd)); + } +} + +void sio_send_string( u8_t *str, sio_status_t * siostat ) +{ + /* sio_status_t * siostat = ((siostruct_t*)netif->state)->sio; */ + int len = strlen( (const char *)str ); + + if ( write( siostat->fd, str, len ) <= 0 ) + { + LWIP_DEBUGF(SIO_DEBUG, ("sio_send_string[%d]: write refused\n", siostat->fd)); + } + LWIP_DEBUGF(SIO_DEBUG, ("sio_send_string[%d]: sent: %s\n", siostat->fd, str)); +} + + +void sio_flush( sio_status_t * siostat ) +{ + LWIP_UNUSED_ARG(siostat); + /* not implemented in unix as it is not needed */ + /*sio_status_t * siostat = ((siostruct_t*)netif->state)->sio; */ +} + + +#if ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF) +/*u8_t sio_recv( struct netif * netif )*/ +u8_t sio_recv( sio_status_t * siostat ) +{ + /* sio_status_t * siostat = ((siostruct_t*)netif->state)->sio; */ + return fifoGet( &(siostat->myfifo) ); +} + +s16_t sio_poll(sio_status_t * siostat) +{ + /* sio_status_t * siostat = ((siostruct_t*)netif->state)->sio;*/ + return fifoGetNonBlock( &(siostat->myfifo) ); +} + + +void sio_expect_string( u8_t *str, sio_status_t * siostat ) +{ + /* sio_status_t * siostat = ((siostruct_t*)netif->state)->sio;*/ + u8_t c; + int finger=0; + + LWIP_DEBUGF(SIO_DEBUG, ("sio_expect_string[%d]: %s\n", siostat->fd, str)); + while ( 1 ) + { + c=fifoGet( &(siostat->myfifo) ); + LWIP_DEBUGF(SIO_DEBUG, ("_%c", c)); + if ( c==str[finger] ) + { + finger++; + } else if ( finger > 0 ) + { + /*it might fit in the beginning? */ + if ( str[0] == c ) + { + finger = 1; + } + } + if ( 0 == str[finger] ) + break; /* done, we have a match */ + } + LWIP_DEBUGF(SIO_DEBUG, ("sio_expect_string[%d]: [match]\n", siostat->fd)); +} +#endif /* ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF) */ + +#if (PPP_SUPPORT || LWIP_HAVE_SLIPIF) +u32_t sio_write(sio_status_t * siostat, u8_t *buf, u32_t size) +{ + ssize_t wsz = write( siostat->fd, buf, size ); + return wsz < 0 ? 0 : wsz; +} + +u32_t sio_read(sio_status_t * siostat, u8_t *buf, u32_t size) +{ + ssize_t rsz = read( siostat->fd, buf, size ); + return rsz < 0 ? 0 : rsz; +} + +void sio_read_abort(sio_status_t * siostat) +{ + LWIP_UNUSED_ARG(siostat); + printf("sio_read_abort[%d]: not yet implemented for unix\n", siostat->fd); +} +#endif /* (PPP_SUPPORT || LWIP_HAVE_SLIPIF) */ + +sio_fd_t sio_open(u8_t devnum) +{ + char dev[20]; + + /* would be nice with dynamic memory alloc */ + sio_status_t * siostate = &statusar[ devnum ]; +/* siostruct_t * tmp; */ + + +/* tmp = (siostruct_t*)(netif->state); */ +/* tmp->sio = siostate; */ + +/* tmp = (siostruct_t*)(netif->state); */ + +/* ((sio_status_t*)(tmp->sio))->fd = 0; */ + + LWIP_DEBUGF(SIO_DEBUG, ("sio_open: for devnum %d\n", devnum)); + +#if ! (PPP_SUPPORT || LWIP_HAVE_SLIPIF) + fifoInit( &siostate->myfifo ); +#endif /* ! PPP_SUPPORT */ + + snprintf( dev, sizeof(dev), "/dev/ttyS%d", devnum ); + + if ( (devnum == 1) || (devnum == 0) ) + { + if ( ( siostate->fd = sio_init( dev, devnum, siostate ) ) == 0 ) + { + LWIP_DEBUGF(SIO_DEBUG, ("sio_open: ERROR opening serial device dev=%s\n", dev)); + abort( ); + return NULL; + } + LWIP_DEBUGF(SIO_DEBUG, ("sio_open[%d]: dev=%s open.\n", siostate->fd, dev)); + } +#if PPP_SUPPORT + else if (devnum == 2) { + pid_t childpid; + char name[256]; + childpid = forkpty(&siostate->fd, name, NULL, NULL); + if(childpid < 0) { + perror("forkpty"); + exit (1); + } + if(childpid == 0) { + execl("/usr/sbin/pppd", "pppd", + "ms-dns", "198.168.100.7", + "local", "crtscts", + "debug", +#ifdef LWIP_PPP_CHAP_TEST + "auth", + "require-chap", + "remotename", "lwip", +#else + "noauth", +#endif +#if LWIP_IPV6 + "+ipv6", +#endif + "192.168.1.1:192.168.1.2", + NULL); + perror("execl pppd"); + exit (1); + } else { + LWIP_DEBUGF(SIO_DEBUG, ("sio_open[%d]: spawned pppd pid %d on %s\n", + siostate->fd, childpid, name)); + } + + } +#endif +#if LWIP_HAVE_SLIPIF + else if (devnum == 3) { + pid_t childpid; + /* create PTY pair */ + siostate->fd = posix_openpt(O_RDWR | O_NOCTTY); + if (siostate->fd < 0) { + perror("open pty master"); + exit (1); + } + if (grantpt(siostate->fd) != 0) { + perror("grant pty master"); + exit (1); + } + if (unlockpt(siostate->fd) != 0) { + perror("unlock pty master"); + exit (1); + } + LWIP_DEBUGF(SIO_DEBUG, ("sio_open[%d]: for %s\n", + siostate->fd, ptsname(siostate->fd))); + /* fork for slattach */ + childpid = fork(); + if(childpid < 0) { + perror("fork"); + exit (1); + } + if(childpid == 0) { + /* esteblish SLIP interface on host side connected to PTY slave */ + execl("/sbin/slattach", "slattach", + "-d", "-v", "-L", "-p", "slip", + ptsname(siostate->fd), + NULL); + perror("execl slattach"); + exit (1); + } else { + int ret; + char buf[1024]; + LWIP_DEBUGF(SIO_DEBUG, ("sio_open[%d]: spawned slattach pid %d on %s\n", + siostate->fd, childpid, ptsname(siostate->fd))); + /* wait a moment for slattach startup */ + sleep(1); + /* configure SLIP interface on host side as P2P interface */ + snprintf(buf, sizeof(buf), + "/sbin/ifconfig sl0 mtu %d %s pointopoint %s up", + SLIP_MAX_SIZE, "192.168.2.1", "192.168.2.2"); + LWIP_DEBUGF(SIO_DEBUG, ("sio_open[%d]: system(\"%s\");\n", siostate->fd, buf)); + ret = system(buf); + if (ret < 0) { + perror("ifconfig failed"); + exit(1); + } + } + } +#endif /* LWIP_HAVE_SLIPIF */ + else + { + LWIP_DEBUGF(SIO_DEBUG, ("sio_open: device %s (%d) is not supported\n", dev, devnum)); + return NULL; + } + + return siostate; +} + +/** +* +*/ +void sio_change_baud( sioBaudrates baud, sio_status_t * siostat ) +{ + /* sio_status_t * siostat = ((siostruct_t*)netif->state)->sio;*/ + + LWIP_DEBUGF(SIO_DEBUG, ("sio_change_baud[%d]\n", siostat->fd)); + + switch ( baud ) + { + case SIO_BAUD_9600: + sio_speed( siostat->fd, B9600 ); + break; + case SIO_BAUD_19200: + sio_speed( siostat->fd, B19200 ); + break; + case SIO_BAUD_38400: + sio_speed( siostat->fd, B38400 ); + break; + case SIO_BAUD_57600: + sio_speed( siostat->fd, B57600 ); + break; + case SIO_BAUD_115200: + sio_speed( siostat->fd, B115200 ); + break; + + default: + LWIP_DEBUGF(SIO_DEBUG, ("sio_change_baud[%d]: Unknown baudrate, code:%d\n", + siostat->fd, baud)); + break; + } +} + diff --git a/ext/lwip-contrib/ports/unix/port/netif/tapif.c b/ext/lwip-contrib/ports/unix/port/netif/tapif.c new file mode 100644 index 0000000..f78d07b --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/netif/tapif.c @@ -0,0 +1,424 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lwip/opt.h" + +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/ip.h" +#include "lwip/mem.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/timeouts.h" +#include "netif/etharp.h" +#include "lwip/ethip6.h" + +#if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP) +#include "netif/tcpdump.h" +#endif /* LWIP_DEBUG && LWIP_TCPDUMP */ + +#include "netif/tapif.h" + +#define IFCONFIG_BIN "/sbin/ifconfig " + +#if defined(LWIP_UNIX_LINUX) +#include +#include +#include +/* + * Creating a tap interface requires special privileges. If the interfaces + * is created in advance with `tunctl -u ` it can be opened as a regular + * user. The network must already be configured. If DEVTAP_IF is defined it + * will be opened instead of creating a new tap device. + * + * You can also use PRECONFIGURED_TAPIF environment variable to do so. + */ +#ifndef DEVTAP_DEFAULT_IF +#define DEVTAP_DEFAULT_IF "tap0" +#endif +#ifndef DEVTAP +#define DEVTAP "/dev/net/tun" +#endif +#define NETMASK_ARGS "netmask %d.%d.%d.%d" +#define IFCONFIG_ARGS "tap0 inet %d.%d.%d.%d " NETMASK_ARGS +#elif defined(LWIP_UNIX_OPENBSD) +#define DEVTAP "/dev/tun0" +#define NETMASK_ARGS "netmask %d.%d.%d.%d" +#define IFCONFIG_ARGS "tun0 inet %d.%d.%d.%d " NETMASK_ARGS " link0" +#else /* others */ +#define DEVTAP "/dev/tap0" +#define NETMASK_ARGS "netmask %d.%d.%d.%d" +#define IFCONFIG_ARGS "tap0 inet %d.%d.%d.%d " NETMASK_ARGS +#endif + +/* Define those to better describe your network interface. */ +#define IFNAME0 't' +#define IFNAME1 'p' + +#ifndef TAPIF_DEBUG +#define TAPIF_DEBUG LWIP_DBG_OFF +#endif + +struct tapif { + /* Add whatever per-interface state that is needed here. */ + int fd; +}; + +/* Forward declarations. */ +static void tapif_input(struct netif *netif); +#if !NO_SYS +static void tapif_thread(void *arg); +#endif /* !NO_SYS */ + +/*-----------------------------------------------------------------------------------*/ +static void +low_level_init(struct netif *netif) +{ + struct tapif *tapif; +#if LWIP_IPV4 + int ret; + char buf[1024]; +#endif /* LWIP_IPV4 */ + char *preconfigured_tapif = getenv("PRECONFIGURED_TAPIF"); + + tapif = (struct tapif *)netif->state; + + /* Obtain MAC address from network interface. */ + + /* (We just fake an address...) */ + netif->hwaddr[0] = 0x02; + netif->hwaddr[1] = 0x12; + netif->hwaddr[2] = 0x34; + netif->hwaddr[3] = 0x56; + netif->hwaddr[4] = 0x78; + netif->hwaddr[5] = 0xab; + netif->hwaddr_len = 6; + + /* device capabilities */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP; + + tapif->fd = open(DEVTAP, O_RDWR); + LWIP_DEBUGF(TAPIF_DEBUG, ("tapif_init: fd %d\n", tapif->fd)); + if (tapif->fd == -1) { +#ifdef LWIP_UNIX_LINUX + perror("tapif_init: try running \"modprobe tun\" or rebuilding your kernel with CONFIG_TUN; cannot open "DEVTAP); +#else /* LWIP_UNIX_LINUX */ + perror("tapif_init: cannot open "DEVTAP); +#endif /* LWIP_UNIX_LINUX */ + exit(1); + } + +#ifdef LWIP_UNIX_LINUX + { + struct ifreq ifr; + memset(&ifr, 0, sizeof(ifr)); + + if (preconfigured_tapif) { + strncpy(ifr.ifr_name, preconfigured_tapif, sizeof(ifr.ifr_name)); + } else { + strncpy(ifr.ifr_name, DEVTAP_DEFAULT_IF, sizeof(ifr.ifr_name)); + } + ifr.ifr_name[sizeof(ifr.ifr_name)-1] = 0; /* ensure \0 termination */ + + ifr.ifr_flags = IFF_TAP|IFF_NO_PI; + if (ioctl(tapif->fd, TUNSETIFF, (void *) &ifr) < 0) { + perror("tapif_init: "DEVTAP" ioctl TUNSETIFF"); + exit(1); + } + } +#endif /* LWIP_UNIX_LINUX */ + + netif_set_link_up(netif); + + if (preconfigured_tapif == NULL) { +#if LWIP_IPV4 + snprintf(buf, 1024, IFCONFIG_BIN IFCONFIG_ARGS, + ip4_addr1(netif_ip4_gw(netif)), + ip4_addr2(netif_ip4_gw(netif)), + ip4_addr3(netif_ip4_gw(netif)), + ip4_addr4(netif_ip4_gw(netif)) +#ifdef NETMASK_ARGS + , + ip4_addr1(netif_ip4_netmask(netif)), + ip4_addr2(netif_ip4_netmask(netif)), + ip4_addr3(netif_ip4_netmask(netif)), + ip4_addr4(netif_ip4_netmask(netif)) +#endif /* NETMASK_ARGS */ + ); + + LWIP_DEBUGF(TAPIF_DEBUG, ("tapif_init: system(\"%s\");\n", buf)); + ret = system(buf); + if (ret < 0) { + perror("ifconfig failed"); + exit(1); + } + if (ret != 0) { + printf("ifconfig returned %d\n", ret); + } +#else /* LWIP_IPV4 */ + perror("todo: support IPv6 support for non-preconfigured tapif"); + exit(1); +#endif /* LWIP_IPV4 */ + } + +#if !NO_SYS + sys_thread_new("tapif_thread", tapif_thread, netif, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); +#endif /* !NO_SYS */ +} +/*-----------------------------------------------------------------------------------*/ +/* + * low_level_output(): + * + * Should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + */ +/*-----------------------------------------------------------------------------------*/ + +static err_t +low_level_output(struct netif *netif, struct pbuf *p) +{ + struct tapif *tapif = (struct tapif *)netif->state; + char buf[1514]; + ssize_t written; + +#if 0 + if (((double)rand()/(double)RAND_MAX) < 0.2) { + printf("drop output\n"); + return ERR_OK; + } +#endif + + /* initiate transfer(); */ + pbuf_copy_partial(p, buf, p->tot_len, 0); + + /* signal that packet should be sent(); */ + written = write(tapif->fd, buf, p->tot_len); + if (written < 0) { + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + perror("tapif: write"); + } + else { + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, (u32_t)written); + } + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +/* + * low_level_input(): + * + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + */ +/*-----------------------------------------------------------------------------------*/ +static struct pbuf * +low_level_input(struct netif *netif) +{ + struct pbuf *p; + u16_t len; + ssize_t readlen; + char buf[1514]; + struct tapif *tapif = (struct tapif *)netif->state; + + /* Obtain the size of the packet and put it into the "len" + variable. */ + readlen = read(tapif->fd, buf, sizeof(buf)); + if (readlen < 0) { + perror("read returned -1"); + exit(1); + } + len = (u16_t)readlen; + + MIB2_STATS_NETIF_ADD(netif, ifinoctets, len); + +#if 0 + if (((double)rand()/(double)RAND_MAX) < 0.2) { + printf("drop\n"); + return NULL; + } +#endif + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + if (p != NULL) { + pbuf_take(p, buf, len); + /* acknowledge that packet has been read(); */ + } else { + /* drop packet(); */ + MIB2_STATS_NETIF_INC(netif, ifindiscards); + LWIP_DEBUGF(NETIF_DEBUG, ("tapif_input: could not allocate pbuf\n")); + } + + return p; +} + +/*-----------------------------------------------------------------------------------*/ +/* + * tapif_input(): + * + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. + * + */ +/*-----------------------------------------------------------------------------------*/ +static void +tapif_input(struct netif *netif) +{ + struct pbuf *p = low_level_input(netif); + + if (p == NULL) { +#if LINK_STATS + LINK_STATS_INC(link.recv); +#endif /* LINK_STATS */ + LWIP_DEBUGF(TAPIF_DEBUG, ("tapif_input: low_level_input returned NULL\n")); + return; + } + + if (netif->input(p, netif) != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("tapif_input: netif input error\n")); + pbuf_free(p); + } +} +/*-----------------------------------------------------------------------------------*/ +/* + * tapif_init(): + * + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + */ +/*-----------------------------------------------------------------------------------*/ +err_t +tapif_init(struct netif *netif) +{ + struct tapif *tapif = (struct tapif *)mem_malloc(sizeof(struct tapif)); + + if (tapif == NULL) { + LWIP_DEBUGF(NETIF_DEBUG, ("tapif_init: out of memory for tapif\n")); + return ERR_MEM; + } + netif->state = tapif; + MIB2_INIT_NETIF(netif, snmp_ifType_other, 100000000); + + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; +#if LWIP_IPV4 + netif->output = etharp_output; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif /* LWIP_IPV6 */ + netif->linkoutput = low_level_output; + netif->mtu = 1500; + + low_level_init(netif); + + return ERR_OK; +} + + +/*-----------------------------------------------------------------------------------*/ +#if NO_SYS + +int +tapif_select(struct netif *netif) +{ + fd_set fdset; + int ret; + struct timeval tv; + struct tapif *tapif; + u32_t msecs = sys_timeouts_sleeptime(); + + tapif = (struct tapif *)netif->state; + + tv.tv_sec = msecs / 1000; + tv.tv_usec = (msecs % 1000) * 1000; + + FD_ZERO(&fdset); + FD_SET(tapif->fd, &fdset); + + ret = select(tapif->fd + 1, &fdset, NULL, NULL, &tv); + if (ret > 0) { + tapif_input(netif); + } + return ret; +} + +#else /* NO_SYS */ + +static void +tapif_thread(void *arg) +{ + struct netif *netif; + struct tapif *tapif; + fd_set fdset; + int ret; + + netif = (struct netif *)arg; + tapif = (struct tapif *)netif->state; + + while(1) { + FD_ZERO(&fdset); + FD_SET(tapif->fd, &fdset); + + /* Wait for a packet to arrive. */ + ret = select(tapif->fd + 1, &fdset, NULL, NULL, NULL); + + if(ret == 1) { + /* Handle incoming packet. */ + tapif_input(netif); + } else if(ret == -1) { + perror("tapif_thread: select"); + } + } +} + +#endif /* NO_SYS */ diff --git a/ext/lwip-contrib/ports/unix/port/netif/tcpdump.c b/ext/lwip-contrib/ports/unix/port/netif/tcpdump.c new file mode 100644 index 0000000..34adbd7 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/netif/tcpdump.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include + +#include "lwip/opt.h" + +#if (LWIP_IPV4 || LWIP_IPV6) && LWIP_TCP /* @todo: fix IPv6 */ + +#include /* memcpy */ +#include "netif/tcpdump.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip.h" +#include "lwip/ip4.h" +#include "lwip/ip6.h" +#include "lwip/ip_addr.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/udp.h" +#include "lwip/inet.h" +#include "lwip/inet_chksum.h" + +#ifndef TCPDUMP_DEBUG +#define TCPDUMP_DEBUG LWIP_DBG_OFF +#endif + +static FILE *file = NULL; + +/*-----------------------------------------------------------------------------------*/ +void +tcpdump_init(void) +{ +#define TCPDUMP_FNAME "/tmp/tcpdump" + file = fopen(TCPDUMP_FNAME, "w"); + if (file == NULL) { + perror("tcpdump_init: cannot open \""TCPDUMP_FNAME"\" for writing"); + } + LWIP_DEBUGF(TCPDUMP_DEBUG, ("tcpdump: file %s\n", TCPDUMP_FNAME)); +} +/*-----------------------------------------------------------------------------------*/ +void +tcpdump(struct pbuf *p, struct netif* netif) +{ +#if LWIP_IPV4 + ip_addr_t src, dst; + struct ip_hdr *iphdr; +#if LWIP_UDP + struct udp_hdr *udphdr; +#endif +#if LWIP_TCP + struct tcp_hdr *tcphdr; + char flags[5]; + int i; + int len; + int offset; +#endif + + LWIP_UNUSED_ARG(netif); /* in case IPv6 is disabled */ + + if (file == NULL) { + return; + } + iphdr = (struct ip_hdr *)p->payload; + +#if LWIP_IPV6 + if(IPH_V(iphdr) == 6) { + struct ip6_hdr *ip6hdr = (struct ip6_hdr*)iphdr; + + /* create aligned copies if IPv6 src/dest addr */ + ip6_addr_copy_from_packed(*ip_2_ip6(&src), ip6hdr->src); + ip6_addr_assign_zone(ip_2_ip6(&src), IP6_UNKNOWN, netif); + IP_SET_TYPE_VAL(src, IPADDR_TYPE_V6); + + ip6_addr_copy_from_packed(*ip_2_ip6(&dst), ip6hdr->dest); + ip6_addr_assign_zone(ip_2_ip6(&dst), IP6_UNKNOWN, netif); + IP_SET_TYPE_VAL(dst, IPADDR_TYPE_V6); + + fprintf(file, "%s > %s: (IPv6, unsupported) ", + ip_ntoa(&src), + ip_ntoa(&dst)); + return; /* not supported */ + } +#endif + + if(IPH_V(iphdr) == 4) { + ip_addr_copy_from_ip4(src, iphdr->src); + ip_addr_copy_from_ip4(dst, iphdr->dest); + } + + switch (IPH_PROTO(iphdr)) { +#if LWIP_TCP + case IP_PROTO_TCP: + tcphdr = (struct tcp_hdr *)((char *)iphdr + IPH_HL(iphdr)); + + pbuf_header(p, -IP_HLEN); + if (ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, &src, &dst) != 0) { + LWIP_DEBUGF(TCPDUMP_DEBUG, ("tcpdump: IP checksum failed!\n")); + /* + fprintf(file, "chksum 0x%lx ", tcphdr->chksum); + tcphdr->chksum = 0; + fprintf(file, "should be 0x%lx ", inet_chksum_pseudo(p, (ip_addr_t *)&(iphdr->src), + (ip_addr_t *)&(iphdr->dest), IP_PROTO_TCP, p->tot_len));*/ + fprintf(file, "!chksum "); + } + + i = 0; + if (TCPH_FLAGS(tcphdr) & TCP_SYN) { + flags[i++] = 'S'; + } + if (TCPH_FLAGS(tcphdr) & TCP_PSH) { + flags[i++] = 'P'; + } + if (TCPH_FLAGS(tcphdr) & TCP_FIN) { + flags[i++] = 'F'; + } + if (TCPH_FLAGS(tcphdr) & TCP_RST) { + flags[i++] = 'R'; + } + if (i == 0) { + flags[i++] = '.'; + } + flags[i++] = 0; + + fprintf(file, "%s.%u > %s.%u: ", + ip_ntoa(&src), + lwip_ntohs(tcphdr->src), + ip_ntoa(&dst), + lwip_ntohs(tcphdr->dest)); + offset = TCPH_HDRLEN(tcphdr); + + len = lwip_ntohs(IPH_LEN(iphdr)) - offset * 4 - IP_HLEN; + if (len != 0 || flags[0] != '.') { + fprintf(file, "%s %u:%u(%u) ", flags, lwip_ntohl(tcphdr->seqno), + lwip_ntohl(tcphdr->seqno) + (u32_t)len, len); + } + if (TCPH_FLAGS(tcphdr) & TCP_ACK) { + fprintf(file, "ack %u ", lwip_ntohl(tcphdr->ackno)); + } + fprintf(file, "wnd %u\n", lwip_ntohs(tcphdr->wnd)); + + fflush(file); + + pbuf_header(p, IP_HLEN); + break; +#endif /* LWIP_TCP */ + +#if LWIP_UDP + case IP_PROTO_UDP: + udphdr = (struct udp_hdr *)((char *)iphdr + IPH_HL(iphdr)); + + pbuf_header(p, -IP_HLEN); + if (ip_chksum_pseudo(p, IP_PROTO_UDP, p->tot_len, &src, &dst) != 0) { + LWIP_DEBUGF(TCPDUMP_DEBUG, ("tcpdump: IP checksum failed!\n")); + /* + fprintf(file, "chksum 0x%lx ", tcphdr->chksum); + tcphdr->chksum = 0; + fprintf(file, "should be 0x%lx ", ip_chksum_pseudo(p, &src, &dst, IP_PROTO_TCP, p->tot_len));*/ + fprintf(file, "!chksum "); + } + + fprintf(file, "%s.%u > %s.%u: ", + ip_ntoa(&src), + lwip_ntohs(udphdr->src), + ip_ntoa(&dst), + lwip_ntohs(udphdr->dest)); + fprintf(file, "U "); + len = (int)(lwip_ntohs(IPH_LEN(iphdr)) - sizeof(struct udp_hdr) - IP_HLEN); + fprintf(file, " %d\n", len); + + fflush(file); + + pbuf_header(p, IP_HLEN); + break; +#endif /* LWIP_UDP */ + default: + LWIP_DEBUGF(TCPDUMP_DEBUG, ("unhandled IP protocol: %d\n", (int)IPH_PROTO(iphdr))); + break; + } +#else + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(netif); +#endif +} + +#endif /* LWIP_IPV4 && LWIP_TCP */ + +/*-----------------------------------------------------------------------------------*/ diff --git a/ext/lwip-contrib/ports/unix/port/netif/tunif.c b/ext/lwip-contrib/ports/unix/port/netif/tunif.c new file mode 100644 index 0000000..15fd271 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/netif/tunif.c @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "netif/tunif.h" + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "lwip/debug.h" + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/ip.h" +#include "lwip/mem.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" + +#if LWIP_IPV4 /* @todo: IPv6 */ +#if !NO_SYS + +#define IFNAME0 't' +#define IFNAME1 'n' + +#ifndef TUNIF_DEBUG +#define TUNIF_DEBUG LWIP_DBG_OFF +#endif + +#define IFCONFIG_CALL "/sbin/ifconfig tun0 inet %d.%d.%d.%d %d.%d.%d.%d" + +struct tunif { + /* Add whatever per-interface state that is needed here. */ + int fd; +}; + +/* Forward declarations. */ +static void tunif_input(struct netif *netif); +static err_t tunif_output(struct netif *netif, struct pbuf *p, + const ip4_addr_t *ipaddr); + +static void tunif_thread(void *data); + +/*-----------------------------------------------------------------------------------*/ +static void +low_level_init(struct netif *netif) +{ + struct tunif *tunif; + char buf[sizeof(IFCONFIG_CALL) + 50]; + + tunif = (struct tunif *)netif->state; + + /* Obtain MAC address from network interface. */ + + /* Do whatever else is needed to initialize interface. */ + + tunif->fd = open("/dev/tun0", O_RDWR); + LWIP_DEBUGF(TUNIF_DEBUG, ("tunif_init: fd %d\n", tunif->fd)); + if (tunif->fd == -1) { + perror("tunif_init"); + exit(1); + } + sprintf(buf, IFCONFIG_CALL, + ip4_addr1(netif_ip4_gw(netif)), + ip4_addr2(netif_ip4_gw(netif)), + ip4_addr3(netif_ip4_gw(netif)), + ip4_addr4(netif_ip4_gw(netif)), + ip4_addr1(netif_ip4_addr(netif)), + ip4_addr2(netif_ip4_addr(netif)), + ip4_addr3(netif_ip4_addr(netif)), + ip4_addr4(netif_ip4_addr(netif))); + + LWIP_DEBUGF(TUNIF_DEBUG, ("tunif_init: system(\"%s\");\n", buf)); + if (system(buf) == 0) { + sys_thread_new("tunif_thread", tunif_thread, netif, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); + } +} +/*-----------------------------------------------------------------------------------*/ +/* + * low_level_output(): + * + * Should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + */ +/*-----------------------------------------------------------------------------------*/ + +static err_t +low_level_output(struct tunif *tunif, struct pbuf *p) +{ + char buf[1500]; + int rnd_val; + + /* initiate transfer(); */ + + rnd_val = rand(); + if (((double)rnd_val/(double)RAND_MAX) < 0.4) { + printf("drop\n"); + return ERR_OK; + } + + pbuf_copy_partial(p, buf, p->tot_len, 0); + + /* signal that packet should be sent(); */ + if (write(tunif->fd, buf, p->tot_len) == -1) { + perror("tunif: write"); + } + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +/* + * low_level_input(): + * + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + */ +/*-----------------------------------------------------------------------------------*/ +static struct pbuf * +low_level_input(struct tunif *tunif) +{ + struct pbuf *p; + ssize_t len; + char buf[1500]; + + /* Obtain the size of the packet and put it into the "len" + variable. */ + len = read(tunif->fd, buf, sizeof(buf)); + if((len <= 0) || (len > 0xffff)) { + return NULL; + } + + /* if (((double)rand()/(double)RAND_MAX) < 0.1) { + printf("drop\n"); + return NULL; + }*/ + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_LINK, (u16_t)len, PBUF_POOL); + + if (p != NULL) { + pbuf_take(p, buf, (u16_t)len); + /* acknowledge that packet has been read(); */ + } else { + /* drop packet(); */ + } + + return p; +} +/*-----------------------------------------------------------------------------------*/ +static void +tunif_thread(void *arg) +{ + struct netif *netif; + struct tunif *tunif; + fd_set fdset; + int ret; + + netif = (struct netif *)arg; + tunif = (struct tunif *)netif->state; + + while (1) { + FD_ZERO(&fdset); + FD_SET(tunif->fd, &fdset); + + /* Wait for a packet to arrive. */ + ret = select(tunif->fd + 1, &fdset, NULL, NULL, NULL); + + if (ret == 1) { + /* Handle incoming packet. */ + tunif_input(netif); + } else if (ret == -1) { + perror("tunif_thread: select"); + } + } +} +/*-----------------------------------------------------------------------------------*/ +/* + * tunif_output(): + * + * This function is called by the TCP/IP stack when an IP packet + * should be sent. It calls the function called low_level_output() to + * do the actuall transmission of the packet. + * + */ +/*-----------------------------------------------------------------------------------*/ +static err_t +tunif_output(struct netif *netif, struct pbuf *p, + const ip4_addr_t *ipaddr) +{ + struct tunif *tunif; + LWIP_UNUSED_ARG(ipaddr); + + tunif = (struct tunif *)netif->state; + + return low_level_output(tunif, p); + +} +/*-----------------------------------------------------------------------------------*/ +/* + * tunif_input(): + * + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. + * + */ +/*-----------------------------------------------------------------------------------*/ +static void +tunif_input(struct netif *netif) +{ + struct tunif *tunif; + struct pbuf *p; + + + tunif = (struct tunif *)netif->state; + + p = low_level_input(tunif); + + if (p == NULL) { + LWIP_DEBUGF(TUNIF_DEBUG, ("tunif_input: low_level_input returned NULL\n")); + return; + } + +#if 0 +/* CS: ip_lookup() was removed */ + if (ip_lookup(p->payload, netif)) { +#endif + netif->input(p, netif); +#if 0 + } +#endif +} +/*-----------------------------------------------------------------------------------*/ +/* + * tunif_init(): + * + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + */ +/*-----------------------------------------------------------------------------------*/ +err_t +tunif_init(struct netif *netif) +{ + struct tunif *tunif; + + tunif = (struct tunif *)mem_malloc(sizeof(struct tunif)); + if (!tunif) { + return ERR_MEM; + } + netif->state = tunif; + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + netif->output = tunif_output; + + + low_level_init(netif); + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ + +#endif /* !NO_SYS */ +#endif /* LWIP_IPV4 */ diff --git a/ext/lwip-contrib/ports/unix/port/netif/unixif.c b/ext/lwip-contrib/ports/unix/port/netif/unixif.c new file mode 100644 index 0000000..c945383 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/netif/unixif.c @@ -0,0 +1,500 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/debug.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +/*#include */ +/*#include */ + + +#include "lwip/stats.h" + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "netif/list.h" +#include "netif/unixif.h" +#include "lwip/sys.h" +#include "lwip/timeouts.h" + +#if LWIP_IPV4 /* @todo: IPv6 */ +#if !NO_SYS + +#include "netif/tcpdump.h" + +#define UNIXIF_BPS 512000 +#define UNIXIF_QUEUELEN 6 +/*#define UNIXIF_DROP_FIRST */ + +#ifndef UNIXIF_DEBUG +#define UNIXIF_DEBUG LWIP_DBG_OFF +#endif + +struct unixif_buf { + struct pbuf *p; + unsigned short len, tot_len; + void *payload; +}; + +struct unixif { + int fd; + sys_sem_t sem; + struct list *q; +}; + +static void unixif_thread(void *arg); +static void unixif_thread2(void *arg); + +/*-----------------------------------------------------------------------------------*/ +static int +unix_socket_client(const char *name) +{ + int fd; +#if !defined(LWIP_UNIX_LINUX) && !defined(LWIP_UNIX_CYGWIN) && !defined(__CYGWIN__) + int len; +#endif + struct sockaddr_un unix_addr; + + /* create a Unix domain stream socket */ + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + perror("unixif: unix_socket_client: socket"); + return(-1); + } + + /* fill socket address structure w/our address */ + memset(&unix_addr, 0, sizeof(unix_addr)); + unix_addr.sun_family = AF_UNIX; + snprintf(unix_addr.sun_path, sizeof(unix_addr.sun_path), "%s%05d", "/var/tmp/", getpid()); +#if !defined(LWIP_UNIX_LINUX) && !defined(LWIP_UNIX_CYGWIN) && !defined(__CYGWIN__) + len = sizeof(unix_addr.sun_len) + sizeof(unix_addr.sun_family) + + strlen(unix_addr.sun_path) + 1; + unix_addr.sun_len = len; +#endif /* LWIP_UNIX_LINUX */ + + unlink(unix_addr.sun_path); /* in case it already exists */ + if (bind(fd, (struct sockaddr *) &unix_addr, + sizeof(struct sockaddr_un)) < 0) { + perror("unixif: unix_socket_client: socket"); + return(-1); + } + if (chmod(unix_addr.sun_path, S_IRWXU | S_IRWXO) < 0) { + perror("unixif: unix_socket_client: socket"); + return(-1); + } + + /* fill socket address structure w/server's addr */ + memset(&unix_addr, 0, sizeof(unix_addr)); + unix_addr.sun_family = AF_UNIX; + strncpy(unix_addr.sun_path, name, sizeof(unix_addr.sun_path)); + unix_addr.sun_path[sizeof(unix_addr.sun_path)-1] = 0; /* ensure \0 termination */ +#if !defined(LWIP_UNIX_LINUX) && !defined(LWIP_UNIX_CYGWIN) && !defined(__CYGWIN__) + len = sizeof(unix_addr.sun_len) + sizeof(unix_addr.sun_family) + + strlen(unix_addr.sun_path) + 1; + unix_addr.sun_len = len; +#endif /* LWIP_UNIX_LINUX */ + if (connect(fd, (struct sockaddr *) &unix_addr, + sizeof(struct sockaddr_un)) < 0) { + perror("unixif: unix_socket_client: socket"); + return(-1); + } + return(fd); +} + +/*-----------------------------------------------------------------------------------*/ +static int +unix_socket_server(const char *name) +{ + int fd; +#if !defined(LWIP_UNIX_LINUX) && !defined(LWIP_UNIX_CYGWIN) && !defined(__CYGWIN__) + int len; +#endif + struct sockaddr_un unix_addr; + + /* create a Unix domain stream socket */ + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + perror("unixif: unix_socket_server: socket"); + return(-1); + } + + unlink(name); /* in case it already exists */ + + /* fill in socket address structure */ + memset(&unix_addr, 0, sizeof(unix_addr)); + unix_addr.sun_family = AF_UNIX; + strncpy(unix_addr.sun_path, name, sizeof(unix_addr.sun_path)); + unix_addr.sun_path[sizeof(unix_addr.sun_path)-1] = 0; /* ensure \0 termination */ +#if !defined(LWIP_UNIX_LINUX) && !defined(LWIP_UNIX_CYGWIN) && !defined(__CYGWIN__) + len = sizeof(unix_addr.sun_len) + sizeof(unix_addr.sun_family) + + strlen(unix_addr.sun_path) + 1; + unix_addr.sun_len = len; +#endif /* LWIP_UNIX_LINUX */ + + /* bind the name to the descriptor */ + if (bind(fd, (struct sockaddr *) &unix_addr, + sizeof(struct sockaddr_un)) < 0) { + perror("unixif: unix_socket_server: bind"); + return(-1); + } + + if (chmod(unix_addr.sun_path, S_IRWXU | S_IRWXO) < 0) { + perror("unixif: unix_socket_server: chmod"); + return(-1); + } + + + if (listen(fd, 5) < 0) { /* tell kernel we're a server */ + perror("unixif: unix_socket_server: listen"); + return(-1); + } + + return(fd); +} +/*-----------------------------------------------------------------------------------*/ +static void +unixif_input_handler(void *data) +{ + struct netif *netif; + struct unixif *unixif; + char buf[1532]; + int plen; + ssize_t len; + u16_t len16; + struct pbuf *p; + + netif = (struct netif *)data; + unixif = (struct unixif *)netif->state; + + len = read(unixif->fd, &plen, sizeof(int)); + if (len < 0) { + perror("unixif_irq_handler: read"); + abort(); + } + + LWIP_DEBUGF(UNIXIF_DEBUG, ("unixif_irq_handler: len == %d plen == %d bytes\n", (int)len, plen)); + if (len == sizeof(int)) { + + if (plen < 20 || plen > 1500) { + LWIP_DEBUGF(UNIXIF_DEBUG, ("plen %d!\n", plen)); + return; + } + + len = read(unixif->fd, buf, (size_t)plen); + if (len < 0) { + perror("unixif_irq_handler: read"); + abort(); + } + if (len != plen) { + perror("unixif_irq_handler: read len != plen"); + abort(); + } + LWIP_DEBUGF(UNIXIF_DEBUG, ("unixif_irq_handler: read %d bytes\n", (int)len)); + len16 = (u16_t)len; + p = pbuf_alloc(PBUF_LINK, len16, PBUF_POOL); + + if (p != NULL) { + pbuf_take(p, buf, len16); + LINK_STATS_INC(link.recv); +#if LWIP_IPV4 && LWIP_TCP + tcpdump(p, netif); +#endif + netif->input(p, netif); + } else { + LWIP_DEBUGF(UNIXIF_DEBUG, ("unixif_irq_handler: could not allocate pbuf\n")); + } + + + } +} +/*-----------------------------------------------------------------------------------*/ +static void +unixif_thread(void *arg) +{ + struct netif *netif; + struct unixif *unixif; + + LWIP_DEBUGF(UNIXIF_DEBUG, ("unixif_thread: started.\n")); + + netif = (struct netif *)arg; + unixif = (struct unixif *)netif->state; + + + while (1) { + sys_sem_wait(&unixif->sem); + unixif_input_handler(netif); + } + +} +/*-----------------------------------------------------------------------------------*/ +static void +unixif_thread2(void *arg) +{ + struct netif *netif; + struct unixif *unixif; + fd_set fdset; + + LWIP_DEBUGF(UNIXIF_DEBUG, ("unixif_thread2: started.\n")); + + netif = (struct netif *)arg; + unixif = (struct unixif *)netif->state; + + while (1) { + FD_ZERO(&fdset); + FD_SET(unixif->fd, &fdset); + + if (select(unixif->fd + 1, &fdset, NULL, NULL, NULL) > 0) { + sys_sem_signal(&unixif->sem); + } + } +} +/*-----------------------------------------------------------------------------------*/ +static void unixif_output_timeout(void *arg); + +static err_t +unixif_output(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr) +{ + struct unixif *unixif; + struct unixif_buf *buf; + LWIP_UNUSED_ARG(ipaddr); + + unixif = (struct unixif *)netif->state; + + buf = (struct unixif_buf *)malloc(sizeof(struct unixif_buf)); + buf->p = p; + buf->len = p->len; + buf->tot_len = p->tot_len; + buf->payload = p->payload; + + if (list_elems(unixif->q) == 0) { + pbuf_ref(p); + list_push(unixif->q, buf); + sys_timeout((u32_t)p->tot_len * 8000 / UNIXIF_BPS, unixif_output_timeout, + netif); + + LWIP_DEBUGF(UNIXIF_DEBUG, ("unixif_output: first on list\n")); + + } else { + pbuf_ref(p); + if (list_push(unixif->q, buf) == 0) { +#ifdef UNIXIF_DROP_FIRST + struct unixif_buf *buf2; + + buf2 = list_pop(unixif->q); + pbuf_free(buf2->p); + free(buf2); + list_push(unixif->q, buf); +#else + free(buf); + pbuf_free(p); + + LWIP_DEBUGF(UNIXIF_DEBUG, ("unixif_output: drop\n")); + +#endif /* UNIXIF_DROP_FIRST */ + LINK_STATS_INC(link.drop); + + } else { + LWIP_DEBUGF(UNIXIF_DEBUG, ("unixif_output: on list\n")); + } + + } + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +static void +unixif_output_timeout(void *arg) +{ + struct pbuf *p, *q; + int i, j, len; + unsigned short plen, ptot_len; + struct unixif_buf *buf; + void *payload; + struct netif *netif; + struct unixif *unixif; + char *data; + + netif = (struct netif *)arg; + unixif = (struct unixif *)netif->state; + + LWIP_DEBUGF(UNIXIF_DEBUG, ("unixif_output_timeout\n")); + + /* buf = unixif->q[0]; + unixif->q[0] = unixif->q[1]; + unixif->q[1] = NULL;*/ + buf = (struct unixif_buf *)list_pop(unixif->q); + + p = buf->p; + + plen = p->len; + ptot_len = p->tot_len; + payload = p->payload; + + p->len = buf->len; + p->tot_len = buf->tot_len; + p->payload = buf->payload; + + + if (p->tot_len == 0) { + + LWIP_DEBUGF(UNIXIF_DEBUG, ("p->len!\n")); + abort(); + } + data = (char *)malloc(p->tot_len); + + i = 0; + for(q = p; q != NULL; q = q->next) { + for(j = 0; j < q->len; j++) { + data[i] = ((char *)q->payload)[j]; + i++; + } + } + + LWIP_DEBUGF(UNIXIF_DEBUG, ("unixif_output: sending %d (%d) bytes\n", + p->len, p->tot_len)); + + len = p->tot_len; + if (write(unixif->fd, &len, sizeof(int)) == -1) { + perror("unixif_output: write"); + abort(); + } + + if (write(unixif->fd, data, p->tot_len) == -1) { + perror("unixif_output: write"); + abort(); + } +#if LWIP_IPV4 && LWIP_TCP + tcpdump(p, netif); +#endif + LINK_STATS_INC(link.xmit); + + free(data); + free(buf); + p->len = plen; + p->tot_len = ptot_len; + p->payload = payload; + + pbuf_free(p); + + /* if (unixif->q[0] != NULL) { + sys_timeout(unixif->q[0]->tot_len * 8000 / UNIXIF_BPS, + unixif_output_timeout, netif); + }*/ + if (list_elems(unixif->q) > 0) { + sys_timeout(((struct unixif_buf *)list_first(unixif->q))->tot_len * + 8000U / UNIXIF_BPS, + unixif_output_timeout, netif); + } +} +/*-----------------------------------------------------------------------------------*/ +err_t +unixif_init_server(struct netif *netif) +{ + int fd, fd2; + struct sockaddr_un addr; + socklen_t len; + struct unixif *unixif; + + fd = unix_socket_server("/tmp/unixif"); + + if (fd == -1) { + perror("unixif_server"); + abort(); + } + LWIP_DEBUGF(UNIXIF_DEBUG, ("unixif_server: fd %d\n", fd)); + + unixif = (struct unixif *)malloc(sizeof(struct unixif)); + if (!unixif) { + return ERR_MEM; + } + netif->state = unixif; + netif->name[0] = 'u'; + netif->name[1] = 'n'; + netif->output = unixif_output; + unixif->q = list_new(UNIXIF_QUEUELEN); + + printf("Now run ./simnode.\n"); + len = sizeof(addr); + fd2 = accept(fd, (struct sockaddr *)&addr, &len); + + if (fd2 == -1) { + perror("unixif_accept"); + abort(); + } + + LWIP_DEBUGF(UNIXIF_DEBUG, ("unixif_accept: %d\n", fd2)); + + unixif->fd = fd2; + if(sys_sem_new(&unixif->sem, 0) != ERR_OK) { + LWIP_ASSERT("Failed to create semaphore", 0); + } + sys_thread_new("unixif_thread", unixif_thread, netif, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); + sys_thread_new("unixif_thread2", unixif_thread2, netif, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ +err_t +unixif_init_client(struct netif *netif) +{ + struct unixif *unixif; + unixif = (struct unixif *)malloc(sizeof(struct unixif)); + if (!unixif) { + return ERR_MEM; + } + netif->state = unixif; + netif->name[0] = 'u'; + netif->name[1] = 'n'; + netif->output = unixif_output; + + unixif->fd = unix_socket_client("/tmp/unixif"); + if (unixif->fd == -1) { + perror("unixif_init"); + abort(); + } + unixif->q = list_new(UNIXIF_QUEUELEN); + if(sys_sem_new(&unixif->sem, 0) != ERR_OK) { + LWIP_ASSERT("Failed to create semaphore", 0); + } + sys_thread_new("unixif_thread", unixif_thread, netif, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); + sys_thread_new("unixif_thread2", unixif_thread2, netif, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); + return ERR_OK; +} +/*-----------------------------------------------------------------------------------*/ + +#endif /* !NO_SYS */ +#endif /* LWIP_IPV4 */ diff --git a/ext/lwip-contrib/ports/unix/port/perf.c b/ext/lwip-contrib/ports/unix/port/perf.c new file mode 100644 index 0000000..bed4614 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/perf.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "arch/perf.h" + +#include + +static FILE *f; + +void +perf_print(unsigned long c1l, unsigned long c1h, + unsigned long c2l, unsigned long c2h, + char *key) +{ + unsigned long sub_ms, sub_ls; + + sub_ms = c2h - c1h; + sub_ls = c2l - c1l; + if (c2l < c1l) sub_ms--; + fprintf(f, "%s: %.8lu%.8lu\n", key, sub_ms, sub_ls); + fflush(NULL); +} + +void +perf_print_times(struct tms *start, struct tms *end, char *key) +{ + fprintf(f, "%s: %lu\n", key, end->tms_stime - start->tms_stime); + fflush(NULL); +} + +void +perf_init(char *fname) +{ + f = fopen(fname, "w"); +} + diff --git a/ext/lwip-contrib/ports/unix/port/sys_arch.c b/ext/lwip-contrib/ports/unix/port/sys_arch.c new file mode 100644 index 0000000..c94969b --- /dev/null +++ b/ext/lwip-contrib/ports/unix/port/sys_arch.c @@ -0,0 +1,649 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* + * Wed Apr 17 16:05:29 EDT 2002 (James Roth) + * + * - Fixed an unlikely sys_thread_new() race condition. + * + * - Made current_thread() work with threads which where + * not created with sys_thread_new(). This includes + * the main thread and threads made with pthread_create(). + * + * - Catch overflows where more than SYS_MBOX_SIZE messages + * are waiting to be read. The sys_mbox_post() routine + * will block until there is more room instead of just + * leaking messages. + */ +#include "lwip/debug.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "lwip/def.h" + +#ifdef LWIP_UNIX_MACH +#include +#include +#endif + +#include "lwip/sys.h" +#include "lwip/opt.h" +#include "lwip/stats.h" + +static void +get_monotonic_time(struct timespec *ts) +{ +#ifdef LWIP_UNIX_MACH + /* darwin impl (no CLOCK_MONOTONIC) */ + uint64_t t = mach_absolute_time(); + mach_timebase_info_data_t timebase_info = {0, 0}; + mach_timebase_info(&timebase_info); + uint64_t nano = (t * timebase_info.numer) / (timebase_info.denom); + uint64_t sec = nano/1000000000L; + nano -= sec * 1000000000L; + ts->tv_sec = sec; + ts->tv_nsec = nano; +#else + clock_gettime(CLOCK_MONOTONIC, ts); +#endif +} + +#if !NO_SYS + +static struct sys_thread *threads = NULL; +static pthread_mutex_t threads_mutex = PTHREAD_MUTEX_INITIALIZER; + +struct sys_mbox_msg { + struct sys_mbox_msg *next; + void *msg; +}; + +#define SYS_MBOX_SIZE 128 + +struct sys_mbox { + int first, last; + void *msgs[SYS_MBOX_SIZE]; + struct sys_sem *not_empty; + struct sys_sem *not_full; + struct sys_sem *mutex; + int wait_send; +}; + +struct sys_sem { + unsigned int c; + pthread_condattr_t condattr; + pthread_cond_t cond; + pthread_mutex_t mutex; +}; + +struct sys_mutex { + pthread_mutex_t mutex; +}; + +struct sys_thread { + struct sys_thread *next; + pthread_t pthread; +}; + +#if SYS_LIGHTWEIGHT_PROT +static pthread_mutex_t lwprot_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_t lwprot_thread = (pthread_t)0xDEAD; +static int lwprot_count = 0; +#endif /* SYS_LIGHTWEIGHT_PROT */ + +static struct sys_sem *sys_sem_new_internal(u8_t count); +static void sys_sem_free_internal(struct sys_sem *sem); + +static u32_t cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex, + u32_t timeout); + +/*-----------------------------------------------------------------------------------*/ +/* Threads */ +static struct sys_thread * +introduce_thread(pthread_t id) +{ + struct sys_thread *thread; + + thread = (struct sys_thread *)malloc(sizeof(struct sys_thread)); + + if (thread != NULL) { + pthread_mutex_lock(&threads_mutex); + thread->next = threads; + thread->pthread = id; + threads = thread; + pthread_mutex_unlock(&threads_mutex); + } + + return thread; +} + +sys_thread_t +sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio) +{ + int code; + pthread_t tmp; + struct sys_thread *st = NULL; + LWIP_UNUSED_ARG(name); + LWIP_UNUSED_ARG(stacksize); + LWIP_UNUSED_ARG(prio); + + code = pthread_create(&tmp, + NULL, + (void *(*)(void *)) + function, + arg); + + if (0 == code) { + st = introduce_thread(tmp); + } + + if (NULL == st) { + LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create %d, st = 0x%lx", + code, (unsigned long)st)); + abort(); + } + return st; +} + +/*-----------------------------------------------------------------------------------*/ +/* Mailbox */ +err_t +sys_mbox_new(struct sys_mbox **mb, int size) +{ + struct sys_mbox *mbox; + LWIP_UNUSED_ARG(size); + + mbox = (struct sys_mbox *)malloc(sizeof(struct sys_mbox)); + if (mbox == NULL) { + return ERR_MEM; + } + mbox->first = mbox->last = 0; + mbox->not_empty = sys_sem_new_internal(0); + mbox->not_full = sys_sem_new_internal(0); + mbox->mutex = sys_sem_new_internal(1); + mbox->wait_send = 0; + + SYS_STATS_INC_USED(mbox); + *mb = mbox; + return ERR_OK; +} + +void +sys_mbox_free(struct sys_mbox **mb) +{ + if ((mb != NULL) && (*mb != SYS_MBOX_NULL)) { + struct sys_mbox *mbox = *mb; + SYS_STATS_DEC(mbox.used); + sys_arch_sem_wait(&mbox->mutex, 0); + + sys_sem_free_internal(mbox->not_empty); + sys_sem_free_internal(mbox->not_full); + sys_sem_free_internal(mbox->mutex); + mbox->not_empty = mbox->not_full = mbox->mutex = NULL; + /* LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */ + free(mbox); + } +} + +err_t +sys_mbox_trypost(struct sys_mbox **mb, void *msg) +{ + u8_t first; + struct sys_mbox *mbox; + LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); + mbox = *mb; + + sys_arch_sem_wait(&mbox->mutex, 0); + + LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n", + (void *)mbox, (void *)msg)); + + if ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) { + sys_sem_signal(&mbox->mutex); + return ERR_MEM; + } + + mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg; + + if (mbox->last == mbox->first) { + first = 1; + } else { + first = 0; + } + + mbox->last++; + + if (first) { + sys_sem_signal(&mbox->not_empty); + } + + sys_sem_signal(&mbox->mutex); + + return ERR_OK; +} + +void +sys_mbox_post(struct sys_mbox **mb, void *msg) +{ + u8_t first; + struct sys_mbox *mbox; + LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); + mbox = *mb; + + sys_arch_sem_wait(&mbox->mutex, 0); + + LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mbox, (void *)msg)); + + while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) { + mbox->wait_send++; + sys_sem_signal(&mbox->mutex); + sys_arch_sem_wait(&mbox->not_full, 0); + sys_arch_sem_wait(&mbox->mutex, 0); + mbox->wait_send--; + } + + mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg; + + if (mbox->last == mbox->first) { + first = 1; + } else { + first = 0; + } + + mbox->last++; + + if (first) { + sys_sem_signal(&mbox->not_empty); + } + + sys_sem_signal(&mbox->mutex); +} + +u32_t +sys_arch_mbox_tryfetch(struct sys_mbox **mb, void **msg) +{ + struct sys_mbox *mbox; + LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); + mbox = *mb; + + sys_arch_sem_wait(&mbox->mutex, 0); + + if (mbox->first == mbox->last) { + sys_sem_signal(&mbox->mutex); + return SYS_MBOX_EMPTY; + } + + if (msg != NULL) { + LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p msg %p\n", (void *)mbox, *msg)); + *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE]; + } + else{ + LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mbox)); + } + + mbox->first++; + + if (mbox->wait_send) { + sys_sem_signal(&mbox->not_full); + } + + sys_sem_signal(&mbox->mutex); + + return 0; +} + +u32_t +sys_arch_mbox_fetch(struct sys_mbox **mb, void **msg, u32_t timeout) +{ + u32_t time_needed = 0; + struct sys_mbox *mbox; + LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); + mbox = *mb; + + /* The mutex lock is quick so we don't bother with the timeout + stuff here. */ + sys_arch_sem_wait(&mbox->mutex, 0); + + while (mbox->first == mbox->last) { + sys_sem_signal(&mbox->mutex); + + /* We block while waiting for a mail to arrive in the mailbox. We + must be prepared to timeout. */ + if (timeout != 0) { + time_needed = sys_arch_sem_wait(&mbox->not_empty, timeout); + + if (time_needed == SYS_ARCH_TIMEOUT) { + return SYS_ARCH_TIMEOUT; + } + } else { + sys_arch_sem_wait(&mbox->not_empty, 0); + } + + sys_arch_sem_wait(&mbox->mutex, 0); + } + + if (msg != NULL) { + LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", (void *)mbox, *msg)); + *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE]; + } + else{ + LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mbox)); + } + + mbox->first++; + + if (mbox->wait_send) { + sys_sem_signal(&mbox->not_full); + } + + sys_sem_signal(&mbox->mutex); + + return time_needed; +} + +/*-----------------------------------------------------------------------------------*/ +/* Semaphore */ +static struct sys_sem * +sys_sem_new_internal(u8_t count) +{ + struct sys_sem *sem; + + sem = (struct sys_sem *)malloc(sizeof(struct sys_sem)); + if (sem != NULL) { + sem->c = count; + pthread_condattr_init(&(sem->condattr)); +#if !(defined(LWIP_UNIX_MACH) || (defined(LWIP_UNIX_ANDROID) && __ANDROID_API__ < 21)) + pthread_condattr_setclock(&(sem->condattr), CLOCK_MONOTONIC); +#endif + pthread_cond_init(&(sem->cond), &(sem->condattr)); + pthread_mutex_init(&(sem->mutex), NULL); + } + return sem; +} + +err_t +sys_sem_new(struct sys_sem **sem, u8_t count) +{ + SYS_STATS_INC_USED(sem); + *sem = sys_sem_new_internal(count); + if (*sem == NULL) { + return ERR_MEM; + } + return ERR_OK; +} + +static u32_t +cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, u32_t timeout) +{ + struct timespec rtime1, rtime2, ts; + int ret; + + if (timeout == 0) { + pthread_cond_wait(cond, mutex); + return 0; + } + + /* Get a timestamp and add the timeout value. */ + get_monotonic_time(&rtime1); +#if defined(LWIP_UNIX_MACH) || (defined(LWIP_UNIX_ANDROID) && __ANDROID_API__ < 21) + ts.tv_sec = timeout / 1000L; + ts.tv_nsec = (timeout % 1000L) * 1000000L; + ret = pthread_cond_timedwait_relative_np(cond, mutex, &ts); +#else + ts.tv_sec = rtime1.tv_sec + timeout / 1000L; + ts.tv_nsec = rtime1.tv_nsec + (timeout % 1000L) * 1000000L; + if (ts.tv_nsec >= 1000000000L) { + ts.tv_sec++; + ts.tv_nsec -= 1000000000L; + } + + ret = pthread_cond_timedwait(cond, mutex, &ts); +#endif + if (ret == ETIMEDOUT) { + return SYS_ARCH_TIMEOUT; + } + + /* Calculate for how long we waited for the cond. */ + get_monotonic_time(&rtime2); + ts.tv_sec = rtime2.tv_sec - rtime1.tv_sec; + ts.tv_nsec = rtime2.tv_nsec - rtime1.tv_nsec; + if (ts.tv_nsec < 0) { + ts.tv_sec--; + ts.tv_nsec += 1000000000L; + } + return (u32_t)(ts.tv_sec * 1000L + ts.tv_nsec / 1000000L); +} + +u32_t +sys_arch_sem_wait(struct sys_sem **s, u32_t timeout) +{ + u32_t time_needed = 0; + struct sys_sem *sem; + LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL)); + sem = *s; + + pthread_mutex_lock(&(sem->mutex)); + while (sem->c <= 0) { + if (timeout > 0) { + time_needed = cond_wait(&(sem->cond), &(sem->mutex), timeout); + + if (time_needed == SYS_ARCH_TIMEOUT) { + pthread_mutex_unlock(&(sem->mutex)); + return SYS_ARCH_TIMEOUT; + } + /* pthread_mutex_unlock(&(sem->mutex)); + return time_needed; */ + } else { + cond_wait(&(sem->cond), &(sem->mutex), 0); + } + } + sem->c--; + pthread_mutex_unlock(&(sem->mutex)); + return (u32_t)time_needed; +} + +void +sys_sem_signal(struct sys_sem **s) +{ + struct sys_sem *sem; + LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL)); + sem = *s; + + pthread_mutex_lock(&(sem->mutex)); + sem->c++; + + if (sem->c > 1) { + sem->c = 1; + } + + pthread_cond_broadcast(&(sem->cond)); + pthread_mutex_unlock(&(sem->mutex)); +} + +static void +sys_sem_free_internal(struct sys_sem *sem) +{ + pthread_cond_destroy(&(sem->cond)); + pthread_condattr_destroy(&(sem->condattr)); + pthread_mutex_destroy(&(sem->mutex)); + free(sem); +} + +void +sys_sem_free(struct sys_sem **sem) +{ + if ((sem != NULL) && (*sem != SYS_SEM_NULL)) { + SYS_STATS_DEC(sem.used); + sys_sem_free_internal(*sem); + } +} + +/*-----------------------------------------------------------------------------------*/ +/* Mutex */ +/** Create a new mutex + * @param mutex pointer to the mutex to create + * @return a new mutex */ +err_t +sys_mutex_new(struct sys_mutex **mutex) +{ + struct sys_mutex *mtx; + + mtx = (struct sys_mutex *)malloc(sizeof(struct sys_mutex)); + if (mtx != NULL) { + pthread_mutex_init(&(mtx->mutex), NULL); + *mutex = mtx; + return ERR_OK; + } + else { + return ERR_MEM; + } +} + +/** Lock a mutex + * @param mutex the mutex to lock */ +void +sys_mutex_lock(struct sys_mutex **mutex) +{ + pthread_mutex_lock(&((*mutex)->mutex)); +} + +/** Unlock a mutex + * @param mutex the mutex to unlock */ +void +sys_mutex_unlock(struct sys_mutex **mutex) +{ + pthread_mutex_unlock(&((*mutex)->mutex)); +} + +/** Delete a mutex + * @param mutex the mutex to delete */ +void +sys_mutex_free(struct sys_mutex **mutex) +{ + pthread_mutex_destroy(&((*mutex)->mutex)); + free(*mutex); +} + +#endif /* !NO_SYS */ + +/*-----------------------------------------------------------------------------------*/ +/* Time */ +u32_t +sys_now(void) +{ + struct timespec ts; + + get_monotonic_time(&ts); + return (u32_t)(ts.tv_sec * 1000L + ts.tv_nsec / 1000000L); +} + +u32_t +sys_jiffies(void) +{ + struct timespec ts; + + get_monotonic_time(&ts); + return (u32_t)(ts.tv_sec * 1000000000L + ts.tv_nsec); +} + +/*-----------------------------------------------------------------------------------*/ +/* Init */ + +void +sys_init(void) +{ +} + +/*-----------------------------------------------------------------------------------*/ +/* Critical section */ +#if SYS_LIGHTWEIGHT_PROT +/** sys_prot_t sys_arch_protect(void) + +This optional function does a "fast" critical region protection and returns +the previous protection level. This function is only called during very short +critical regions. An embedded system which supports ISR-based drivers might +want to implement this function by disabling interrupts. Task-based systems +might want to implement this by using a mutex or disabling tasking. This +function should support recursive calls from the same task or interrupt. In +other words, sys_arch_protect() could be called while already protected. In +that case the return value indicates that it is already protected. + +sys_arch_protect() is only required if your port is supporting an operating +system. +*/ +sys_prot_t +sys_arch_protect(void) +{ + /* Note that for the UNIX port, we are using a lightweight mutex, and our + * own counter (which is locked by the mutex). The return code is not actually + * used. */ + if (lwprot_thread != pthread_self()) + { + /* We are locking the mutex where it has not been locked before * + * or is being locked by another thread */ + pthread_mutex_lock(&lwprot_mutex); + lwprot_thread = pthread_self(); + lwprot_count = 1; + } + else + /* It is already locked by THIS thread */ + lwprot_count++; + return 0; +} + +/** void sys_arch_unprotect(sys_prot_t pval) + +This optional function does a "fast" set of critical region protection to the +value specified by pval. See the documentation for sys_arch_protect() for +more information. This function is only required if your port is supporting +an operating system. +*/ +void +sys_arch_unprotect(sys_prot_t pval) +{ + LWIP_UNUSED_ARG(pval); + if (lwprot_thread == pthread_self()) + { + if (--lwprot_count == 0) + { + lwprot_thread = (pthread_t) 0xDEAD; + pthread_mutex_unlock(&lwprot_mutex); + } + } +} +#endif /* SYS_LIGHTWEIGHT_PROT */ diff --git a/ext/lwip-contrib/ports/unix/setup-tapif b/ext/lwip-contrib/ports/unix/setup-tapif new file mode 100755 index 0000000..3846e96 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/setup-tapif @@ -0,0 +1,15 @@ +#!/bin/bash + +# Run me using "source setup-tapif" to get exported PRECONFIGURED_TAPIF variable +# Alternatively, add "export PRECONFIGURED_TAPIF=tap0" to ~/.bashrc + +# http://backreference.org/2010/03/26/tuntap-interface-tutorial/ + +# After executing this script, start unixsim/simhost. +# Enter 192.168.0.2 or "http://simhost.local/" (Zeroconf) +# in your webbrowser to see simhost webpage. + +sudo ip tuntap add dev tap0 mode tap user `whoami` +sudo ip link set tap0 up +sudo ip addr add 192.168.0.1/24 dev tap0 +export PRECONFIGURED_TAPIF=tap0 diff --git a/ext/lwip-contrib/ports/unix/unixsim/Makefile b/ext/lwip-contrib/ports/unix/unixsim/Makefile new file mode 100644 index 0000000..20767e9 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/unixsim/Makefile @@ -0,0 +1,59 @@ +# +# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. +# All rights reserved. +# +# 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. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +# +# This file is part of the lwIP TCP/IP stack. +# +# Author: Adam Dunkels +# + +all compile: simhost simrouter simnode makefsdata +.PHONY: all + +include ../Common.mk + +MAKEFSDATAOBJS=$(notdir $(MAKEFSDATAFILES:.c=.o)) + +clean: + rm -f *.o $(LWIPLIBCOMMON) $(APPLIB) simhost simnode simrouter *.s .depend* *.core core + +depend dep: .depend + +include .depend + +.depend: simhost.c simnode.c simrouter.c $(LWIPFILES) $(APPFILES) $(MAKEFSDATAFILES) + $(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend + +simhost: .depend $(LWIPLIBCOMMON) $(APPLIB) simhost.o + $(CC) $(CFLAGS) -o simhost simhost.o -Wl,--start-group $(APPLIB) $(LWIPLIBCOMMON) -Wl,--end-group $(LDFLAGS) + +simrouter: .depend $(LWIPLIBCOMMON) $(APPLIB) simrouter.o + $(CC) $(CFLAGS) -o simrouter simrouter.o -Wl,--start-group $(APPLIB) $(LWIPLIBCOMMON) -Wl,--end-group $(LDFLAGS) + +simnode: .depend $(LWIPLIBCOMMON) $(APPLIB) simnode.o + $(CC) $(CFLAGS) -o simnode simnode.o -Wl,--start-group $(APPLIB) $(LWIPLIBCOMMON) -Wl,--end-group $(LDFLAGS) + +makefsdata: .depend $(MAKEFSDATAOBJS) + $(CC) $(CFLAGS) -o makefsdata $(MAKEFSDATAOBJS) diff --git a/ext/lwip-contrib/ports/unix/unixsim/README b/ext/lwip-contrib/ports/unix/unixsim/README new file mode 100644 index 0000000..949c917 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/unixsim/README @@ -0,0 +1,61 @@ +This directory contains an example of how a project using lwIP might +look. It is also the development platform of lwIP, since it can be run +as a user process under FreeBSD or Linux. There are also a number of +example applications (including a simple web server) in the apps/ +directory. + +Some short instructions on how to build and run lwIP on a FreeBSD or +Linux host. For FreeBSD, the tap interface must be enabled in the +kernel configuration and the kernel must be recompiled. The tap +interface is enabled by adding the line "pseudo-device tap" in the +kernel configuration. See Chapter 9 in the FreeBSD handbook for +instructions on how to build a custom FreeBSD kernel. + +For Linux you might need to create a device node with + + > mknod /dev/net/tun c 10 200 + +* Compile the code. This must be done by using GNU Make. Under + FreeBSD, GNU Make can be found in the ports collection under + /usr/ports/devel/gmake (type "make install distclean" to + install). Under Linux, GNU Make is the default "make". + + > gmake (FreeBSD) + + > make (Linux) + +* The compilation process produces the executable file "simhost". To + run this, you have to be root. + + > su (Type password for the root account) + # ./simhost + +* The lwIP TCP/IP stack is now running with IP address + 192.168.0.2. Some things that you can try: + + To see the packets that are going to and from the lwIP stack, run + tcpdump: + + # tcpdump -l -n -i tap0 + + You can ping lwIP: + + > ping 192.168.0.2 + + For a telnet shell, run: + + > telnet 192.168.0.2 + + Finally, "simhost" also includes a simple web server; the URL is + of course http://192.168.0.2/. + +* Simhost has some extra features that can be + selected with command line options. + + To enable runtime debug output (project must be build with -DLWIP_DEBUG): + + # ./simhost -d + + To ping any host, e.g. the gateway: + + # ./simhost -p 192.168.0.1 diff --git a/ext/lwip-contrib/ports/unix/unixsim/lwip_hooks.h b/ext/lwip-contrib/ports/unix/unixsim/lwip_hooks.h new file mode 100644 index 0000000..194e8b2 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/unixsim/lwip_hooks.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef LWIP_HOOKS_H +#define LWIP_HOOKS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "addons/tcp_isn/tcp_isn.h" + +#define LWIP_HOOK_TCP_ISN lwip_hook_tcp_isn + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HOOKS_H */ + diff --git a/ext/lwip-contrib/ports/unix/unixsim/lwipopts.h b/ext/lwip-contrib/ports/unix/unixsim/lwipopts.h new file mode 100644 index 0000000..1009e85 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/unixsim/lwipopts.h @@ -0,0 +1,374 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_LWIPOPTS_H +#define LWIP_LWIPOPTS_H + +#include "lwip/arch.h" + +#define LWIP_HOOK_FILENAME "lwip_hooks.h" + +#define LWIP_IPV4 1 +#define LWIP_IPV6 1 + +#define LWIP_DBG_MIN_LEVEL 0 +#define LWIP_COMPAT_SOCKETS 1 +#define TAPIF_DEBUG LWIP_DBG_ON +#define TUNIF_DEBUG LWIP_DBG_OFF +#define UNIXIF_DEBUG LWIP_DBG_OFF +#define DELIF_DEBUG LWIP_DBG_OFF +#define SIO_FIFO_DEBUG LWIP_DBG_OFF +#define TCPDUMP_DEBUG LWIP_DBG_ON + +#define SLIP_DEBUG LWIP_DBG_OFF +#define PPP_DEBUG LWIP_DBG_OFF +#define MEM_DEBUG LWIP_DBG_OFF +#define MEMP_DEBUG LWIP_DBG_OFF +#define PBUF_DEBUG LWIP_DBG_OFF +#define API_LIB_DEBUG LWIP_DBG_ON +#define API_MSG_DEBUG LWIP_DBG_ON +#define TCPIP_DEBUG LWIP_DBG_ON +#define NETIF_DEBUG LWIP_DBG_ON +#define SOCKETS_DEBUG LWIP_DBG_ON +#define DEMO_DEBUG LWIP_DBG_ON +#define IP_DEBUG LWIP_DBG_ON +#define IP_REASS_DEBUG LWIP_DBG_ON +#define RAW_DEBUG LWIP_DBG_ON +#define ICMP_DEBUG LWIP_DBG_ON +#define UDP_DEBUG LWIP_DBG_ON +#define TCP_DEBUG LWIP_DBG_ON +#define TCP_INPUT_DEBUG LWIP_DBG_ON +#define TCP_OUTPUT_DEBUG LWIP_DBG_ON +#define TCP_RTO_DEBUG LWIP_DBG_ON +#define TCP_CWND_DEBUG LWIP_DBG_ON +#define TCP_WND_DEBUG LWIP_DBG_ON +#define TCP_FR_DEBUG LWIP_DBG_ON +#define TCP_QLEN_DEBUG LWIP_DBG_ON +#define TCP_RST_DEBUG LWIP_DBG_ON + +extern unsigned char debug_flags; +#define LWIP_DBG_TYPES_ON debug_flags + +#define NO_SYS 0 +#define LWIP_SOCKET (NO_SYS==0) +#define LWIP_NETCONN (NO_SYS==0) +#define SO_REUSE 1 +#define IP_SOF_BROADCAST_RECV 1 +#define IP_SOF_BROADCAST 1 +#define SO_REUSE_RXTOALL 1 +#define LWIP_SO_RCVTIMEO (LWIP_SOCKET) + +/* ---------- Memory options ---------- */ +/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which + lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2 + byte alignment -> define MEM_ALIGNMENT to 2. */ +/* MSVC port: intel processors don't need 4-byte alignment, + but are faster that way! */ +#define MEM_ALIGNMENT 4U + +/* MEM_SIZE: the size of the heap memory. If the application will send +a lot of data that needs to be copied, this should be set high. */ +#define MEM_SIZE 10240 + +/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application + sends a lot of data out of ROM (or other static memory), this + should be set high. */ +#define MEMP_NUM_PBUF 16 +/* MEMP_NUM_RAW_PCB: the number of UDP protocol control blocks. One + per active RAW "connection". */ +#define MEMP_NUM_RAW_PCB 3 +/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + per active UDP "connection". */ +#define MEMP_NUM_UDP_PCB 6 +/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP + connections. */ +#define MEMP_NUM_TCP_PCB 5 +/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP + connections. */ +#define MEMP_NUM_TCP_PCB_LISTEN 8 +/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP + segments. */ +#define MEMP_NUM_TCP_SEG 16 +/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active + timeouts. */ +#define MEMP_NUM_SYS_TIMEOUT 17 + +/* The following four are used only with the sequential API and can be + set to 0 if the application only will use the raw API. */ +/* MEMP_NUM_NETBUF: the number of struct netbufs. */ +#define MEMP_NUM_NETBUF 2 +/* MEMP_NUM_NETCONN: the number of struct netconns. */ +#define MEMP_NUM_NETCONN 10 +/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used + for sequential API communication and incoming packets. Used in + src/api/tcpip.c. */ +#define MEMP_NUM_TCPIP_MSG_API 16 +#define MEMP_NUM_TCPIP_MSG_INPKT 16 + +#define MEMP_OVERFLOW_CHECK 1 + +/* ---------- Pbuf options ---------- */ +/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ +#define PBUF_POOL_SIZE 200 + +/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ +#define PBUF_POOL_BUFSIZE 128 + +/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a + link level header. */ +#define PBUF_LINK_HLEN 16u + +/** SYS_LIGHTWEIGHT_PROT + * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection + * for certain critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#define SYS_LIGHTWEIGHT_PROT 1 + +#define LWIP_TCPIP_TIMEOUT 1 + +/* ---------- TCP options ---------- */ +#define LWIP_TCP 1 +#define LWIP_ALTCP (LWIP_TCP) +#define TCP_TTL 255 + +#ifdef LWIP_HAVE_MBEDTLS +#define LWIP_ALTCP_TLS (LWIP_TCP) +#define LWIP_ALTCP_TLS_MBEDTLS (LWIP_TCP) +#endif + +#define TCP_LISTEN_BACKLOG 1 + +/* Controls if TCP should queue segments that arrive out of + order. Define to 0 if your device is low on memory. */ +#define TCP_QUEUE_OOSEQ 1 + +/* TCP Maximum segment size. */ +#define TCP_MSS 1024 + +/* TCP sender buffer space (bytes). */ +#define TCP_SND_BUF 2048 + +/* TCP sender buffer space (pbufs). This must be at least = 2 * + TCP_SND_BUF/TCP_MSS for things to work. */ +#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF/TCP_MSS) + +/* TCP writable space (bytes). This must be less than or equal + to TCP_SND_BUF. It is the amount of space which must be + available in the tcp snd_buf for select to return writable */ +#define TCP_SNDLOWAT (TCP_SND_BUF/2) + +/* TCP receive window. */ +#define TCP_WND 8096 + +/* Maximum number of retransmissions of data segments. */ +#define TCP_MAXRTX 12 + +/* Maximum number of retransmissions of SYN segments. */ +#define TCP_SYNMAXRTX 4 + +/* ---------- ARP options ---------- */ +#define LWIP_ARP 1 +#define ARP_TABLE_SIZE 10 +#define ARP_QUEUEING 1 + +/* ---------- IP options ---------- */ +/* Define IP_FORWARD to 1 if you wish to have the ability to forward + IP packets across network interfaces. If you are going to run lwIP + on a device with only one network interface, define this to 0. */ +#define IP_FORWARD 1 + + +/* IP reassembly and segmentation.These are orthogonal even + * if they both deal with IP fragments */ +#define IP_REASSEMBLY 1 +#define IP_REASS_MAX_PBUFS 10 +#define MEMP_NUM_REASSDATA 10 +#define IP_FRAG 1 +#define IPV6_FRAG_COPYHEADER 1 +#define LWIP_IPV6_FRAG 1 + +#define LWIP_IGMP (LWIP_IPV4) + +/* ---------- ICMP options ---------- */ +#define ICMP_TTL 255 + +/* ---------- DHCP options ---------- */ +/* Define LWIP_DHCP to 1 if you want DHCP configuration of + interfaces. */ +#define LWIP_DHCP 0 + +#define LWIP_DHCP_GET_NTP_SRV (LWIP_DHCP) + +/* 1 if you want to do an ARP check on the offered address + (recommended if using DHCP). */ +#define DHCP_DOES_ARP_CHECK (LWIP_DHCP) + +/* ---------- AUTOIP options ------- */ +#define LWIP_AUTOIP (LWIP_DHCP) +#define LWIP_DHCP_AUTOIP_COOP (LWIP_DHCP) +#define LWIP_DHCP_AUTOIP_COOP_TRIES 3 + +/* ---------- SNTP options --------- */ +extern void sntp_set_system_time(u32_t sec); +#define SNTP_SET_SYSTEM_TIME(s) sntp_set_system_time(s) + +/* ---------- SNMP options ---------- */ +#define LWIP_SNMP (LWIP_UDP) +#ifdef LWIP_HAVE_MBEDTLS +#define LWIP_SNMP_V3 (LWIP_SNMP) +#endif +#define MIB2_STATS (LWIP_SNMP) +#define SNMP_USE_NETCONN (LWIP_NETCONN) +#define SNMP_USE_RAW (!LWIP_NETCONN) + +/* ---------- DNS options ---------- */ +#define LWIP_DNS 1 + +/* ---------- MDNS options ---------- */ +#define LWIP_MDNS_RESPONDER 1 +#define LWIP_NUM_NETIF_CLIENT_DATA (LWIP_MDNS_RESPONDER) + +/* ---------- UDP options ---------- */ +#define LWIP_UDP 1 +#define UDP_TTL 255 + +/* ---------- RAW options ---------- */ +#define LWIP_RAW 1 +#define RAW_TTL 255 + +/* ---------- Statistics options ---------- */ +/* individual STATS options can be turned off by defining them to 0 + * (e.g #define TCP_STATS 0). All of them are turned off if LWIP_STATS + * is 0 + * */ + +#define LWIP_STATS 1 + +#define LWIP_NETIF_API 1 +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_EXT_STATUS_CALLBACK 1 +#define LWIP_NETIF_HOSTNAME 0 + +/* ---------- SLIP options ---------- */ + +#define LWIP_HAVE_SLIPIF 1 /* Set > 0 for SLIP */ + +/* Maximum packet size that is received by this netif */ +#define SLIP_MAX_SIZE 1500 +#define sio_tryread sio_read + +/* ---------- 6LoWPAN options ---------- */ +#define LWIP_6LOWPAN 1 + +/* ---------- PPP options ---------- */ + +#define PPP_SUPPORT 1 /* Set > 0 for PPP */ +#define MPPE_SUPPORT PPP_SUPPORT +#define PPPOE_SUPPORT PPP_SUPPORT +#define PPPOL2TP_SUPPORT PPP_SUPPORT +#define PPPOS_SUPPORT PPP_SUPPORT + +#if PPP_SUPPORT > 0 + +#define NUM_PPP 1 /* Max PPP sessions. */ + + +/* Select modules to enable. Ideally these would be set in the makefile but + * we're limited by the command line length so you need to modify the settings + * in this file. + */ +#define PAP_SUPPORT 1 /* Set > 0 for PAP. */ +#define CHAP_SUPPORT 1 /* Set > 0 for CHAP. */ +#define MSCHAP_SUPPORT 0 /* Set > 0 for MSCHAP (NOT FUNCTIONAL!) */ +#define CBCP_SUPPORT 0 /* Set > 0 for CBCP (NOT FUNCTIONAL!) */ +#define CCP_SUPPORT 0 /* Set > 0 for CCP (NOT FUNCTIONAL!) */ +#define VJ_SUPPORT 1 /* Set > 0 for VJ header compression. */ +#define MD5_SUPPORT 1 /* Set > 0 for MD5 (see also CHAP) */ + + +/* + * Timeouts. + */ +#define FSM_DEFTIMEOUT 6 /* Timeout time in seconds */ +#define FSM_DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ +#define FSM_DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ +#define FSM_DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ + +#define UPAP_DEFTIMEOUT 6 /* Timeout (seconds) for retransmitting req */ +#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ + +#define CHAP_DEFTIMEOUT 6 /* Timeout time in seconds */ +#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */ + + +/* Interval in seconds between keepalive echo requests, 0 to disable. */ +#if 1 +#define LCP_ECHOINTERVAL 0 +#else +#define LCP_ECHOINTERVAL 10 +#endif + +/* Number of unanswered echo requests before failure. */ +#define LCP_MAXECHOFAILS 3 + +/* Max Xmit idle time (in jiffies) before resend flag char. */ +#define PPP_MAXIDLEFLAG 100 + +/* + * Packet sizes + * + * Note - lcp shouldn't be allowed to negotiate stuff outside these + * limits. See lcp.h in the pppd directory. + * (XXX - these constants should simply be shared by lcp.c instead + * of living in lcp.h) + */ +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#if 0 +#define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN) +#else +#define PPP_MAXMTU 1500 /* Largest MTU we allow */ +#endif +#define PPP_MINMTU 64 +#define PPP_MRU 1500 /* default MRU = max length of info field */ +#define PPP_MAXMRU 1500 /* Largest MRU we allow */ +#define PPP_DEFMRU 296 /* Try for this */ +#define PPP_MINMRU 128 /* No MRUs below this */ + + +#define MAXNAMELEN 256 /* max length of hostname or name for auth */ +#define MAXSECRETLEN 256 /* max length of password or secret */ + +#endif /* PPP_SUPPORT > 0 */ + +#define LWIP_HTTPD_SSI 1 + +#endif /* LWIP_LWIPOPTS_H */ diff --git a/ext/lwip-contrib/ports/unix/unixsim/simhost.c b/ext/lwip-contrib/ports/unix/unixsim/simhost.c new file mode 100644 index 0000000..2c63947 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/unixsim/simhost.c @@ -0,0 +1,670 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include +#include +#include +#include +#include + +#include "lwip/opt.h" + +#include "lwip/init.h" + +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/sys.h" +#include "lwip/timeouts.h" + +#include "lwip/ip_addr.h" + +#include "lwip/dns.h" +#include "lwip/dhcp.h" + +#include "lwip/stats.h" + +#include "lwip/tcp.h" +#include "lwip/inet_chksum.h" + +#include "lwip/tcpip.h" +#include "lwip/sockets.h" + +#include "netif/tapif.h" +#include "netif/tunif.h" + +#include "netif/unixif.h" +#include "netif/dropif.h" +#include "netif/pcapif.h" + +#include "netif/tcpdump.h" + +#ifndef LWIP_HAVE_SLIPIF +#define LWIP_HAVE_SLIPIF 0 +#endif +#if LWIP_HAVE_SLIPIF +#include "netif/slipif.h" +#define SLIP_PTY_TEST 1 +#endif + +#if PPP_SUPPORT +#include "netif/ppp/pppos.h" +#include "lwip/sio.h" +#define PPP_PTY_TEST 1 +#include +#endif + +#include "lwip/ip_addr.h" +#include "arch/perf.h" + +#include "lwip/apps/httpd.h" +#include "apps/udpecho/udpecho.h" +#include "apps/tcpecho/tcpecho.h" +#include "apps/shell/shell.h" +#include "apps/chargen/chargen.h" +#include "apps/netio/netio.h" +#include "apps/ping/ping.h" +#include "lwip/apps/netbiosns.h" +#include "lwip/apps/mdns.h" +#include "lwip/apps/sntp.h" +#include "lwip/apps/snmp.h" +#include "lwip/apps/snmp_mib2.h" +#include "apps/snmp_private_mib/private_mib.h" +#include "lwip/apps/snmpv3.h" +#include "apps/snmp_v3/snmpv3_dummy.h" +#include "lwip/apps/snmp_snmpv2_framework.h" +#include "lwip/apps/snmp_snmpv2_usm.h" +#include "lwip/apps/tftp_server.h" +#include "addons/tcp_isn/tcp_isn.h" + +#if LWIP_RAW +#include "lwip/icmp.h" +#include "lwip/raw.h" +#endif + +#if LWIP_SNMP +static const struct snmp_mib *mibs[] = { + &mib2, + &mib_private +#if LWIP_SNMP_V3 + , &snmpframeworkmib + , &snmpusmmib +#endif +}; +#endif /* LWIP_SNMP */ + +#if LWIP_IPV4 +/* (manual) host IP configuration */ +static ip_addr_t ipaddr, netmask, gw; +#endif /* LWIP_IPV4 */ + +struct netif netif; + +/* ping out destination cmd option */ +static unsigned char ping_flag; +static ip_addr_t ping_addr; + +/* nonstatic debug cmd option, exported in lwipopts.h */ +unsigned char debug_flags; + +/** @todo add options for selecting netif, starting DHCP client etc */ +static struct option longopts[] = { + /* turn on debugging output (if build with LWIP_DEBUG) */ + {"debug", no_argument, NULL, 'd'}, + /* help */ + {"help", no_argument, NULL, 'h'}, +#if LWIP_IPV4 + /* gateway address */ + {"gateway", required_argument, NULL, 'g'}, + /* ip address */ + {"ipaddr", required_argument, NULL, 'i'}, + /* netmask */ + {"netmask", required_argument, NULL, 'm'}, + /* ping destination */ + {"ping", required_argument, NULL, 'p'}, +#endif /* LWIP_IPV4 */ + /* new command line options go here! */ + {NULL, 0, NULL, 0} +}; +#define NUM_OPTS ((sizeof(longopts) / sizeof(struct option)) - 1) + +static void init_netifs(void); + +static void usage(void) +{ + unsigned char i; + + printf("options:\n"); + for (i = 0; i < NUM_OPTS; i++) { + printf("-%c --%s\n",longopts[i].val, longopts[i].name); + } +} + +#if 0 +static void +tcp_debug_timeout(void *data) +{ + LWIP_UNUSED_ARG(data); +#if TCP_DEBUG + tcp_debug_print_pcbs(); +#endif /* TCP_DEBUG */ + sys_timeout(5000, tcp_debug_timeout, NULL); +} +#endif + +void +sntp_set_system_time(u32_t sec) +{ + char buf[32]; + struct tm current_time_val; + time_t current_time = (time_t)sec; + + localtime_r(¤t_time, ¤t_time_val); + + strftime(buf, sizeof(buf), "%d.%m.%Y %H:%M:%S", ¤t_time_val); + printf("SNTP time: %s\n", buf); +} + +#if LWIP_MDNS_RESPONDER +static void +srv_txt(struct mdns_service *service, void *txt_userdata) +{ + err_t res; + LWIP_UNUSED_ARG(txt_userdata); + + res = mdns_resp_add_service_txtitem(service, "path=/", 6); + LWIP_ERROR("mdns add service txt failed\n", (res == ERR_OK), return); +} +#endif + +#if LWIP_UDP + +static void* +tftp_open(const char* fname, const char* mode, u8_t is_write) +{ + LWIP_UNUSED_ARG(mode); + + if (is_write) { + return (void*)fopen(fname, "wb"); + } else { + return (void*)fopen(fname, "rb"); + } +} +static void +tftp_close(void* handle) +{ + fclose((FILE*)handle); +} +static int +tftp_read(void* handle, void* buf, int bytes) +{ + int ret = fread(buf, 1, bytes, (FILE*)handle); + if (ret <= 0) { + return -1; + } + return ret; +} +static int +tftp_write(void* handle, struct pbuf* p) +{ + while (p != NULL) { + if (fwrite(p->payload, 1, p->len, (FILE*)handle) != (size_t)p->len) { + return -1; + } + p = p->next; + } + + return 0; +} + +static const struct tftp_context tftp = { + tftp_open, + tftp_close, + tftp_read, + tftp_write +}; + +#endif /* LWIP_UDP */ + +static void +tcpip_init_done(void *arg) +{ + sys_sem_t *sem; + sem = (sys_sem_t *)arg; + + init_netifs(); + +#if LWIP_IPV4 + netbiosns_set_name("simhost"); + netbiosns_init(); +#endif /* LWIP_IPV4 */ + + sntp_setoperatingmode(SNTP_OPMODE_POLL); +#if LWIP_DHCP + sntp_servermode_dhcp(1); /* get SNTP server via DHCP */ +#else /* LWIP_DHCP */ +#if LWIP_IPV4 + sntp_setserver(0, netif_ip_gw4(&netif)); +#endif /* LWIP_IPV4 */ +#endif /* LWIP_DHCP */ + sntp_init(); + +#if LWIP_SNMP + lwip_privmib_init(); +#if SNMP_LWIP_MIB2 +#if SNMP_USE_NETCONN + snmp_threadsync_init(&snmp_mib2_lwip_locks, snmp_mib2_lwip_synchronizer); +#endif /* SNMP_USE_NETCONN */ + snmp_mib2_set_syscontact_readonly((const u8_t*)"root", NULL); + snmp_mib2_set_syslocation_readonly((const u8_t*)"lwIP development PC", NULL); + snmp_mib2_set_sysdescr((const u8_t*)"simhost", NULL); +#endif /* SNMP_LWIP_MIB2 */ + +#if LWIP_SNMP_V3 + snmpv3_dummy_init(); +#endif + + snmp_set_mibs(mibs, LWIP_ARRAYSIZE(mibs)); + snmp_init(); +#endif /* LWIP_SNMP */ + +#if LWIP_MDNS_RESPONDER + mdns_resp_init(); + mdns_resp_add_netif(&netif, "simhost", 3600); + mdns_resp_add_service(&netif, "myweb", "_http", DNSSD_PROTO_TCP, 80, 3600, srv_txt, NULL); +#endif + +#if LWIP_UDP + tftp_init(&tftp); +#endif /* LWIP_UDP */ + + sys_sem_signal(sem); +} + +/*-----------------------------------------------------------------------------------*/ +/*-----------------------------------------------------------------------------------*/ + +#if LWIP_HAVE_SLIPIF +/* (manual) host IP configuration */ +#if LWIP_IPV4 +static ip_addr_t ipaddr_slip, netmask_slip, gw_slip; +#endif /* LWIP_IPV4 */ +struct netif slipif; +#endif /* LWIP_HAVE_SLIPIF */ + +#if PPP_SUPPORT +sio_fd_t ppp_sio; +ppp_pcb *ppp; +struct netif pppos_netif; + +static void +pppos_rx_thread(void *arg) +{ + u32_t len; + u8_t buffer[128]; + LWIP_UNUSED_ARG(arg); + + /* Please read the "PPPoS input path" chapter in the PPP documentation. */ + while (1) { + len = sio_read(ppp_sio, buffer, sizeof(buffer)); + if (len > 0) { + /* Pass received raw characters from PPPoS to be decoded through lwIP + * TCPIP thread using the TCPIP API. This is thread safe in all cases + * but you should avoid passing data byte after byte. */ + pppos_input_tcpip(ppp, buffer, len); + } + } +} + +static void +ppp_link_status_cb(ppp_pcb *pcb, int err_code, void *ctx) +{ + struct netif *pppif = ppp_netif(pcb); + LWIP_UNUSED_ARG(ctx); + + switch(err_code) { + case PPPERR_NONE: /* No error. */ + { +#if LWIP_DNS + const ip_addr_t *ns; +#endif /* LWIP_DNS */ + fprintf(stderr, "ppp_link_status_cb: PPPERR_NONE\n\r"); +#if LWIP_IPV4 + fprintf(stderr, " our_ip4addr = %s\n\r", ip4addr_ntoa(netif_ip4_addr(pppif))); + fprintf(stderr, " his_ipaddr = %s\n\r", ip4addr_ntoa(netif_ip4_gw(pppif))); + fprintf(stderr, " netmask = %s\n\r", ip4addr_ntoa(netif_ip4_netmask(pppif))); +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + fprintf(stderr, " our_ip6addr = %s\n\r", ip6addr_ntoa(netif_ip6_addr(pppif, 0))); +#endif /* LWIP_IPV6 */ + +#if LWIP_DNS + ns = dns_getserver(0); + fprintf(stderr, " dns1 = %s\n\r", ipaddr_ntoa(ns)); + ns = dns_getserver(1); + fprintf(stderr, " dns2 = %s\n\r", ipaddr_ntoa(ns)); +#endif /* LWIP_DNS */ +#if PPP_IPV6_SUPPORT + fprintf(stderr, " our6_ipaddr = %s\n\r", ip6addr_ntoa(netif_ip6_addr(pppif, 0))); +#endif /* PPP_IPV6_SUPPORT */ + } + break; + + case PPPERR_PARAM: /* Invalid parameter. */ + printf("ppp_link_status_cb: PPPERR_PARAM\n"); + break; + + case PPPERR_OPEN: /* Unable to open PPP session. */ + printf("ppp_link_status_cb: PPPERR_OPEN\n"); + break; + + case PPPERR_DEVICE: /* Invalid I/O device for PPP. */ + printf("ppp_link_status_cb: PPPERR_DEVICE\n"); + break; + + case PPPERR_ALLOC: /* Unable to allocate resources. */ + printf("ppp_link_status_cb: PPPERR_ALLOC\n"); + break; + + case PPPERR_USER: /* User interrupt. */ + printf("ppp_link_status_cb: PPPERR_USER\n"); + break; + + case PPPERR_CONNECT: /* Connection lost. */ + printf("ppp_link_status_cb: PPPERR_CONNECT\n"); + break; + + case PPPERR_AUTHFAIL: /* Failed authentication challenge. */ + printf("ppp_link_status_cb: PPPERR_AUTHFAIL\n"); + break; + + case PPPERR_PROTOCOL: /* Failed to meet protocol. */ + printf("ppp_link_status_cb: PPPERR_PROTOCOL\n"); + break; + + case PPPERR_PEERDEAD: /* Connection timeout. */ + printf("ppp_link_status_cb: PPPERR_PEERDEAD\n"); + break; + + case PPPERR_IDLETIMEOUT: /* Idle Timeout. */ + printf("ppp_link_status_cb: PPPERR_IDLETIMEOUT\n"); + break; + + case PPPERR_CONNECTTIME: /* PPPERR_CONNECTTIME. */ + printf("ppp_link_status_cb: PPPERR_CONNECTTIME\n"); + break; + + case PPPERR_LOOPBACK: /* Connection timeout. */ + printf("ppp_link_status_cb: PPPERR_LOOPBACK\n"); + break; + + default: + printf("ppp_link_status_cb: unknown errCode %d\n", err_code); + break; + } +} + +static u32_t +ppp_output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) +{ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(ctx); + return sio_write(ppp_sio, data, len); +} +#endif + +#if LWIP_NETIF_STATUS_CALLBACK +static void +netif_status_callback(struct netif *nif) +{ + printf("NETIF: %c%c%d is %s\n", nif->name[0], nif->name[1], nif->num, + netif_is_up(nif) ? "UP" : "DOWN"); +#if LWIP_IPV4 + printf("IPV4: Host at %s ", ip4addr_ntoa(netif_ip4_addr(nif))); + printf("mask %s ", ip4addr_ntoa(netif_ip4_netmask(nif))); + printf("gateway %s\n", ip4addr_ntoa(netif_ip4_gw(nif))); +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + printf("IPV6: Host at %s\n", ip6addr_ntoa(netif_ip6_addr(nif, 0))); +#endif /* LWIP_IPV6 */ +#if LWIP_NETIF_HOSTNAME + printf("FQDN: %s\n", netif_get_hostname(nif)); +#endif /* LWIP_NETIF_HOSTNAME */ +} +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +static void +init_netifs(void) +{ +#if LWIP_HAVE_SLIPIF +#if SLIP_PTY_TEST + u8_t siodev_slip = 3; +#else + u8_t siodev_slip = 0; +#endif + +#if LWIP_IPV4 + netif_add(&slipif, ip_2_ip4(&ipaddr_slip), ip_2_ip4(&netmask_slip), ip_2_ip4(&gw_slip), + (void*)&siodev_slip, slipif_init, tcpip_input); +#else /* LWIP_IPV4 */ + netif_add(&slipif, (void*)&siodev_slip, slipif_init, tcpip_input); +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(&slipif, 1); +#endif +#if LWIP_NETIF_STATUS_CALLBACK + netif_set_status_callback(&slipif, netif_status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + netif_set_link_up(&slipif); + netif_set_up(&slipif); +#endif /* LWIP_HAVE_SLIPIF */ + +#if PPP_SUPPORT +#if PPP_PTY_TEST + ppp_sio = sio_open(2); +#else + ppp_sio = sio_open(0); +#endif + if(!ppp_sio) + { + perror("Error opening device: "); + exit(1); + } + + ppp = pppos_create(&pppos_netif, ppp_output_cb, ppp_link_status_cb, NULL); + if (!ppp) + { + printf("Could not create PPP control interface"); + exit(1); + } + +#ifdef LWIP_PPP_CHAP_TEST + ppp_set_auth(ppp, PPPAUTHTYPE_CHAP, "lwip", "mysecret"); +#endif + + ppp_connect(ppp, 0); + +#if LWIP_NETIF_STATUS_CALLBACK + netif_set_status_callback(&pppos_netif, netif_status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#endif /* PPP_SUPPORT */ + +#if LWIP_IPV4 +#if LWIP_DHCP + IP_ADDR4(&gw, 0,0,0,0); + IP_ADDR4(&ipaddr, 0,0,0,0); + IP_ADDR4(&netmask, 0,0,0,0); +#endif /* LWIP_DHCP */ + netif_add(&netif, ip_2_ip4(&ipaddr), ip_2_ip4(&netmask), ip_2_ip4(&gw), NULL, tapif_init, tcpip_input); +#else /* LWIP_IPV4 */ + netif_add(&netif, NULL, tapif_init, tcpip_input); +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(&netif, 1); + netif.ip6_autoconfig_enabled = 1; +#endif +#if LWIP_NETIF_STATUS_CALLBACK + netif_set_status_callback(&netif, netif_status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + netif_set_default(&netif); + netif_set_up(&netif); + +#if LWIP_DHCP + dhcp_start(&netif); +#endif /* LWIP_DHCP */ + +#if 0 + /* Only used for testing purposes: */ + netif_add(&ipaddr, &netmask, &gw, NULL, pcapif_init, tcpip_input); +#endif + +#if LWIP_TCP + netio_init(); +#endif +#if LWIP_TCP && LWIP_NETCONN + tcpecho_init(); + shell_init(); + httpd_init(); +#endif +#if LWIP_UDP && LWIP_NETCONN + udpecho_init(); +#endif +#if LWIP_SOCKET + chargen_init(); +#endif + /* sys_timeout(5000, tcp_debug_timeout, NULL);*/ +} + +/*-----------------------------------------------------------------------------------*/ +static void +main_thread(void *arg) +{ + sys_sem_t sem; + LWIP_UNUSED_ARG(arg); + + lwip_init_tcp_isn(sys_now(), (u8_t*)&netif); + + if(sys_sem_new(&sem, 0) != ERR_OK) { + LWIP_ASSERT("Failed to create semaphore", 0); + } + tcpip_init(tcpip_init_done, &sem); + sys_sem_wait(&sem); + printf("TCP/IP initialized.\n"); + +#if LWIP_SOCKET + if (ping_flag) { + ping_init(&ping_addr); + } +#endif + + printf("Applications started.\n"); + +#ifdef MEM_PERF + mem_perf_init("/tmp/memstats.client"); +#endif /* MEM_PERF */ +#if 0 + stats_display(); +#endif +#if PPP_SUPPORT + /* Block forever. */ + sys_thread_new("pppos_rx_thread", pppos_rx_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); + sys_sem_wait(&sem); +#endif +} +/*-----------------------------------------------------------------------------------*/ +int +main(int argc, char **argv) +{ + int ch; + char ip_str[IPADDR_STRLEN_MAX] = {0}; + + /* startup defaults (may be overridden by one or more opts) */ +#if LWIP_IPV4 + IP_ADDR4(&gw, 192,168, 0,1); + IP_ADDR4(&netmask, 255,255,255,0); + IP_ADDR4(&ipaddr, 192,168, 0,2); +#if LWIP_HAVE_SLIPIF + IP_ADDR4(&gw_slip, 192,168, 2, 1); + IP_ADDR4(&netmask_slip, 255,255,255,255); + IP_ADDR4(&ipaddr_slip, 192,168, 2, 2); +#endif +#endif /* LWIP_IPV4 */ + + ping_flag = 0; + /* use debug flags defined by debug.h */ + debug_flags = LWIP_DBG_OFF; + + while ((ch = getopt_long(argc, argv, "dhg:i:m:p:", longopts, NULL)) != -1) { + switch (ch) { + case 'd': + debug_flags |= (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT); + break; + case 'h': + usage(); + exit(0); + break; +#if LWIP_IPV4 + case 'g': + ipaddr_aton(optarg, &gw); + break; + case 'i': + ipaddr_aton(optarg, &ipaddr); + break; + case 'm': + ipaddr_aton(optarg, &netmask); + break; +#endif /* LWIP_IPV4 */ + case 'p': + ping_flag = !0; + ipaddr_aton(optarg, &ping_addr); + strncpy(ip_str,ipaddr_ntoa(&ping_addr),sizeof(ip_str)); + ip_str[sizeof(ip_str)-1] = 0; /* ensure \0 termination */ + printf("Using %s to ping\n", ip_str); + break; + default: + usage(); + break; + } + } + argc -= optind; + argv += optind; + +#ifdef PERF + perf_init("/tmp/simhost.perf"); +#endif /* PERF */ + + printf("System initialized.\n"); + + sys_thread_new("main_thread", main_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); + pause(); + return 0; +} +/*-----------------------------------------------------------------------------------*/ diff --git a/ext/lwip-contrib/ports/unix/unixsim/simnode.c b/ext/lwip-contrib/ports/unix/unixsim/simnode.c new file mode 100644 index 0000000..29a2031 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/unixsim/simnode.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/debug.h" + +#include + + +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/sys.h" +#include "lwip/tcp.h" +#include "lwip/priv/tcp_priv.h" /* for tcp_debug_print_pcbs() */ +#include "lwip/timeouts.h" + +#include "lwip/stats.h" + + +#include "lwip/tcpip.h" + + +#include "netif/unixif.h" +#include "netif/dropif.h" + +#include "netif/tcpdump.h" + +#include "lwip/ip_addr.h" + +#include "arch/perf.h" + +#include "lwip/apps/httpd.h" +#include "apps/udpecho/udpecho.h" +#include "apps/tcpecho/tcpecho.h" +#include "apps/shell/shell.h" + +#if LWIP_IPV4 /* @todo: IPv6 */ + +/* nonstatic debug cmd option, exported in lwipopts.h */ +unsigned char debug_flags; + +/*-----------------------------------------------------------------------------------*/ +static void +tcp_timeout(void *data) +{ + LWIP_UNUSED_ARG(data); +#if TCP_DEBUG && LWIP_TCP + tcp_debug_print_pcbs(); +#endif /* TCP_DEBUG */ + sys_timeout(5000, tcp_timeout, NULL); +} +/*-----------------------------------------------------------------------------------*/ +struct netif netif_unix; +/*-----------------------------------------------------------------------------------*/ +static void +tcpip_init_done(void *arg) +{ + ip4_addr_t ipaddr, netmask, gw; + sys_sem_t *sem; + sem = (sys_sem_t *)arg; + + IP4_ADDR(&gw, 192,168,1,1); + IP4_ADDR(&ipaddr, 192,168,1,2); + IP4_ADDR(&netmask, 255,255,255,0); + + netif_set_default(netif_add(&netif_unix, &ipaddr, &netmask, &gw, NULL, unixif_init_client, + tcpip_input)); + netif_set_up(&netif_unix); +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(&netif_unix, 1); +#endif + /* netif_set_default(netif_add(&ipaddr, &netmask, &gw, NULL, sioslipif_init1, + tcpip_input)); */ + +#if LWIP_NETCONN + tcpecho_init(); + shell_init(); +#if LWIP_IPV4 && LWIP_TCP + httpd_init(); +#endif + udpecho_init(); +#endif + + printf("Applications started.\n"); + + sys_timeout(5000, tcp_timeout, NULL); + + sys_sem_signal(sem); +} +/*-----------------------------------------------------------------------------------*/ + +static void +main_thread(void *arg) +{ + sys_sem_t sem; + LWIP_UNUSED_ARG(arg); + + if(sys_sem_new(&sem, 0) != ERR_OK) { + LWIP_ASSERT("Failed to create semaphore", 0); + } + tcpip_init(tcpip_init_done, &sem); + sys_sem_wait(&sem); + printf("TCP/IP initialized.\n"); + +#ifdef MEM_PERF + mem_perf_init("/tmp/memstats.client"); +#endif /* MEM_PERF */ + + /* Block forever. */ + sys_sem_wait(&sem); +} +/*-----------------------------------------------------------------------------------*/ +int +main(void) +{ +#ifdef PERF + perf_init("/tmp/client.perf"); +#endif /* PERF */ + +#if LWIP_IPV4 && LWIP_TCP + tcpdump_init(); +#endif + + printf("System initialized.\n"); + + sys_thread_new("main_thread", main_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); + pause(); + return 0; +} + +#else /* LWIP_IPV4 */ + +int +main(int argc, char **argv) +{ + LWIP_UNUSED_ARG(argc); + LWIP_UNUSED_ARG(argv); + + printf("simnode only works with IPv4\n"); + + return 0; +} + +#endif /* LWIP_IPV4 */ + +/* dummy, because SNTP is pulled in via LWIP_DHCP_GET_NTP_SRV */ +void +sntp_set_system_time(u32_t sec) +{ + LWIP_UNUSED_ARG(sec); +} + +/*-----------------------------------------------------------------------------------*/ diff --git a/ext/lwip-contrib/ports/unix/unixsim/simrouter.c b/ext/lwip-contrib/ports/unix/unixsim/simrouter.c new file mode 100644 index 0000000..37b6f34 --- /dev/null +++ b/ext/lwip-contrib/ports/unix/unixsim/simrouter.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/debug.h" + +#include + + +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/sys.h" +#include "lwip/tcp.h" +#include "lwip/priv/tcp_priv.h" /* for tcp_debug_print_pcbs() */ +#include "lwip/timeouts.h" + +#include "lwip/stats.h" + + +#include "lwip/tcpip.h" + +#include "netif/tapif.h" + +#include "netif/unixif.h" +#include "netif/dropif.h" + +#include "netif/tcpdump.h" + + +#include "lwip/ip_addr.h" + +#include "arch/perf.h" + +#include "lwip/apps/httpd.h" +#include "apps/udpecho/udpecho.h" +#include "apps/tcpecho/tcpecho.h" +#include "apps/shell/shell.h" + +#if LWIP_IPV4 /* @todo: IPv6 */ + +/* nonstatic debug cmd option, exported in lwipopts.h */ +unsigned char debug_flags; + +/*-----------------------------------------------------------------------------------*/ +static void +tcp_timeout(void *data) +{ + LWIP_UNUSED_ARG(data); +#if TCP_DEBUG && LWIP_TCP + tcp_debug_print_pcbs(); +#endif /* TCP_DEBUG */ + sys_timeout(5000, tcp_timeout, NULL); +} +/*-----------------------------------------------------------------------------------*/ + +struct netif netif_tap, netif_unix; + +/*-----------------------------------------------------------------------------------*/ +static void +tcpip_init_done(void *arg) +{ + ip4_addr_t ipaddr, netmask, gw; + sys_sem_t *sem; + sem = (sys_sem_t *)arg; + + IP4_ADDR(&gw, 192,168,0,1); + IP4_ADDR(&ipaddr, 192,168,0,2); + IP4_ADDR(&netmask, 255,255,255,0); + + netif_set_default(netif_add(&netif_tap, &ipaddr, &netmask, &gw, NULL, tapif_init, + tcpip_input)); + netif_set_up(&netif_tap); +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(&netif_tap, 1); +#endif + + IP4_ADDR(&gw, 192,168,1,1); + IP4_ADDR(&ipaddr, 192,168,1,1); + IP4_ADDR(&netmask, 255,255,255,0); + netif_set_default(netif_add(&netif_unix, &ipaddr, &netmask, &gw, NULL, unixif_init_server, + tcpip_input)); + netif_set_up(&netif_unix); +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(&netif_unix, 1); +#endif + + if(system("route add 192.168.1.1 192.168.0.2") != 0) { + return; + } + + if(system("route add 192.168.1.2 192.168.0.2") != 0) { + return; + } + + + /*netif_set_default(netif_add(&ipaddr, &netmask, &gw, NULL, sioslipif_init1, + tcpip_input)); */ + +#if LWIP_NETCONN + tcpecho_init(); + shell_init(); +#if LWIP_IPV4 && LWIP_TCP + httpd_init(); +#endif + udpecho_init(); +#endif + + printf("Applications started.\n"); + + sys_timeout(5000, tcp_timeout, NULL); + + sys_sem_signal(sem); +} + + +static void +main_thread(void *arg) +{ + sys_sem_t sem; + LWIP_UNUSED_ARG(arg); + + if(sys_sem_new(&sem, 0) != ERR_OK) { + LWIP_ASSERT("Failed to create semaphore", 0); + } + tcpip_init(tcpip_init_done, &sem); + sys_sem_wait(&sem); + printf("TCP/IP initialized.\n"); + +#ifdef MEM_PERF + mem_perf_init("/tmp/memstats.client"); +#endif /* MEM_PERF */ + /* Block forever. */ + sys_sem_wait(&sem); +} +/*-----------------------------------------------------------------------------------*/ +int +main(void) +{ +#ifdef PERF + perf_init("/tmp/client.perf"); +#endif /* PERF */ + +#if LWIP_IPV4 && LWIP_TCP + tcpdump_init(); +#endif + + printf("System initialized.\n"); + sys_thread_new("main_thread", main_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); + pause(); + return 0; +} + +#else /* LWIP_IPV4 */ + +int +main(int argc, char **argv) +{ + LWIP_UNUSED_ARG(argc); + LWIP_UNUSED_ARG(argv); + + printf("simrouter only works with IPv4\n"); + + return 0; +} + +#endif /* LWIP_IPV4 */ + +/* dummy, because SNTP is pulled in via LWIP_DHCP_GET_NTP_SRV */ +void +sntp_set_system_time(u32_t sec) +{ + LWIP_UNUSED_ARG(sec); +} + +/*-----------------------------------------------------------------------------------*/ diff --git a/ext/lwip-contrib/ports/win32/check/check_stdint.h b/ext/lwip-contrib/ports/win32/check/check_stdint.h new file mode 100644 index 0000000..c2c100d --- /dev/null +++ b/ext/lwip-contrib/ports/win32/check/check_stdint.h @@ -0,0 +1 @@ +/* deliberateliy empty */ diff --git a/ext/lwip-contrib/ports/win32/check/config.h b/ext/lwip-contrib/ports/win32/check/config.h new file mode 100644 index 0000000..69c04f9 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/check/config.h @@ -0,0 +1,30 @@ +/* config.h for check-0.11.0 on win32 under MSVC/MinGW */ + +#ifdef _MSC_VER + +typedef unsigned int pid_t; +typedef unsigned int uint32_t; + +typedef int ssize_t; +#define snprintf _snprintf + +#define HAVE_DECL_STRDUP 1 +#define HAVE_DECL_FILENO 1 +#define HAVE_DECL_PUTENV 1 + +#define _CRT_SECURE_NO_WARNINGS + +/* disable some warnings */ +#pragma warning (disable: 4090) /* const assigned to non-const */ +#pragma warning (disable: 4996) /* fileno is deprecated */ + +#endif /* _ MSC_VER */ + + +#define LWIP_UNITTESTS_NOFORK + +#include + +typedef unsigned int clockid_t; +typedef unsigned int timer_t; +#define STRUCT_TIMESPEC_DEFINITION_MISSING diff --git a/ext/lwip-contrib/ports/win32/check/stdbool.h b/ext/lwip-contrib/ports/win32/check/stdbool.h new file mode 100644 index 0000000..aa4e74c --- /dev/null +++ b/ext/lwip-contrib/ports/win32/check/stdbool.h @@ -0,0 +1,9 @@ +#ifndef MY_STDBOOL_H +#define MY_STDBOOL_H + +typedef int bool; +#define true 1 +#define false 0 +#define __bool_true_false_are_defined 1 + +#endif \ No newline at end of file diff --git a/ext/lwip-contrib/ports/win32/check/sys/time.h b/ext/lwip-contrib/ports/win32/check/sys/time.h new file mode 100644 index 0000000..d71d827 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/check/sys/time.h @@ -0,0 +1,12 @@ +#ifndef LWIP_SYS__TIME_H +#define LWIP_SYS__TIME_H + +#include /* time_t */ + +struct timeval { + time_t tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +int gettimeofday(struct timeval* tp, void* tzp); + +#endif diff --git a/ext/lwip-contrib/ports/win32/check/time.c b/ext/lwip-contrib/ports/win32/check/time.c new file mode 100644 index 0000000..15306fe --- /dev/null +++ b/ext/lwip-contrib/ports/win32/check/time.c @@ -0,0 +1,64 @@ +#include + +#include +#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) + #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 +#else + #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL +#endif + +#include "config.h" + +struct timezone +{ + int tz_minuteswest; /* minutes W of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +int gettimeofday(struct timeval *tv, struct timezone *tz) +{ + FILETIME ft; + unsigned __int64 tmpres = 0; + static int tzflag; + + if (NULL != tv) + { + GetSystemTimeAsFileTime(&ft); + + tmpres |= ft.dwHighDateTime; + tmpres <<= 32; + tmpres |= ft.dwLowDateTime; + + /*converting file time to unix epoch*/ + tmpres -= DELTA_EPOCH_IN_MICROSECS; + tmpres /= 10; /*convert into microseconds*/ + tv->tv_sec = (long)(tmpres / 1000000UL); + tv->tv_usec = (long)(tmpres % 1000000UL); + } + + if (NULL != tz) + { + if (!tzflag) + { + _tzset(); + tzflag++; + } + tz->tz_minuteswest = _timezone / 60; + tz->tz_dsttime = _daylight; + } + + return 0; +} + +struct tm * +localtime_r(const time_t *timer, struct tm *result) +{ + struct tm *local_result; + local_result = localtime (timer); + + if (local_result == NULL || result == NULL) + return NULL; + + memcpy(result, local_result, sizeof (result)); + return result; +} diff --git a/ext/lwip-contrib/ports/win32/check/unistd.h b/ext/lwip-contrib/ports/win32/check/unistd.h new file mode 100644 index 0000000..332e6e1 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/check/unistd.h @@ -0,0 +1,7 @@ +#ifndef LWIP_UNISTD_H +#define LWIP_UNISTD_H + +/* include io.h for read() and write() */ +#include + +#endif diff --git a/ext/lwip-contrib/ports/win32/include/arch/bpstruct.h b/ext/lwip-contrib/ports/win32/include/arch/bpstruct.h new file mode 100644 index 0000000..1d81e3f --- /dev/null +++ b/ext/lwip-contrib/ports/win32/include/arch/bpstruct.h @@ -0,0 +1 @@ +#pragma pack(push,1) diff --git a/ext/lwip-contrib/ports/win32/include/arch/cc.h b/ext/lwip-contrib/ports/win32/include/arch/cc.h new file mode 100644 index 0000000..a1a2a70 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/include/arch/cc.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_ARCH_CC_H +#define LWIP_ARCH_CC_H + +#ifdef _MSC_VER +#pragma warning (disable: 4127) /* conditional expression is constant */ +#pragma warning (disable: 4996) /* 'strncpy' was declared deprecated */ +#pragma warning (disable: 4103) /* structure packing changed by including file */ +#pragma warning (disable: 4820) /* 'x' bytes padding added after data member 'y' */ +#endif + +#define LWIP_PROVIDE_ERRNO + +/* Define platform endianness (might already be defined) */ +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif /* BYTE_ORDER */ + +typedef int sys_prot_t; + +#ifdef _MSC_VER +/* define _INTPTR for Win32 MSVC stdint.h */ +#define _INTPTR 2 + +/* Do not use lwIP default definitions for format strings + * because these do not work with MSVC 2010 compiler (no inttypes.h) + */ +#define LWIP_NO_INTTYPES_H 1 + +/* Define (sn)printf formatters for these lwIP types */ +#define X8_F "02x" +#define U16_F "hu" +#define U32_F "lu" +#define S32_F "ld" +#define X32_F "lx" + +#define S16_F "hd" +#define X16_F "hx" +#define SZT_F "lu" +#endif /* _MSC_VER */ + +/* Compiler hints for packing structures */ +#define PACK_STRUCT_USE_INCLUDES + +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ + printf("Assertion \"%s\" failed at line %d in %s\n", message, __LINE__, __FILE__); \ + fflush(NULL);handler;} } while(0) + +#ifdef _MSC_VER +/* C runtime functions redefined */ +#define snprintf _snprintf +#define strdup _strdup +#endif + +#ifndef LWIP_NORAND +extern unsigned int sys_win_rand(void); +#define LWIP_RAND() (sys_win_rand()) +#endif + +#define PPP_INCLUDE_SETTINGS_HEADER + +#endif /* LWIP_ARCH_CC_H */ diff --git a/ext/lwip-contrib/ports/win32/include/arch/epstruct.h b/ext/lwip-contrib/ports/win32/include/arch/epstruct.h new file mode 100644 index 0000000..65898b5 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/include/arch/epstruct.h @@ -0,0 +1 @@ +#pragma pack(pop) diff --git a/ext/lwip-contrib/ports/win32/include/arch/perf.h b/ext/lwip-contrib/ports/win32/include/arch/perf.h new file mode 100644 index 0000000..4580aab --- /dev/null +++ b/ext/lwip-contrib/ports/win32/include/arch/perf.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * 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 of the Institute 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 INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_PERF_H +#define LWIP_PERF_H + +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ + +#endif /* LWIP_PERF_H */ diff --git a/ext/lwip-contrib/ports/win32/include/arch/sys_arch.h b/ext/lwip-contrib/ports/win32/include/arch/sys_arch.h new file mode 100644 index 0000000..e7c4947 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/include/arch/sys_arch.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_ARCH_SYS_ARCH_H +#define LWIP_ARCH_SYS_ARCH_H + +/* HANDLE is used for sys_sem_t but we won't include windows.h */ +struct _sys_sem { + void *sem; +}; +typedef struct _sys_sem sys_sem_t; +#define sys_sem_valid_val(sema) (((sema).sem != NULL) && ((sema).sem != (void*)-1)) +#define sys_sem_valid(sema) (((sema) != NULL) && sys_sem_valid_val(*(sema))) +#define sys_sem_set_invalid(sema) ((sema)->sem = NULL) + +/* HANDLE is used for sys_mutex_t but we won't include windows.h */ +struct _sys_mut { + void *mut; +}; +typedef struct _sys_mut sys_mutex_t; +#define sys_mutex_valid_val(mutex) (((mutex).mut != NULL) && ((mutex).mut != (void*)-1)) +#define sys_mutex_valid(mutex) (((mutex) != NULL) && sys_mutex_valid_val(*(mutex))) +#define sys_mutex_set_invalid(mutex) ((mutex)->mut = NULL) + +#ifndef MAX_QUEUE_ENTRIES +#define MAX_QUEUE_ENTRIES 100 +#endif +struct lwip_mbox { + void* sem; + void* q_mem[MAX_QUEUE_ENTRIES]; + u32_t head, tail; +}; +typedef struct lwip_mbox sys_mbox_t; +#define SYS_MBOX_NULL NULL +#define sys_mbox_valid_val(mbox) (((mbox).sem != NULL) && ((mbox).sem != (void*)-1)) +#define sys_mbox_valid(mbox) ((mbox != NULL) && sys_mbox_valid_val(*(mbox))) +#define sys_mbox_set_invalid(mbox) ((mbox)->sem = NULL) + +/* DWORD (thread id) is used for sys_thread_t but we won't include windows.h */ +typedef u32_t sys_thread_t; + +sys_sem_t* sys_arch_netconn_sem_get(void); +void sys_arch_netconn_sem_alloc(void); +void sys_arch_netconn_sem_free(void); +#define LWIP_NETCONN_THREAD_SEM_GET() sys_arch_netconn_sem_get() +#define LWIP_NETCONN_THREAD_SEM_ALLOC() sys_arch_netconn_sem_alloc() +#define LWIP_NETCONN_THREAD_SEM_FREE() sys_arch_netconn_sem_free() + +int lwip_win32_keypressed(void); + +#endif /* LWIP_ARCH_SYS_ARCH_H */ + diff --git a/ext/lwip-contrib/ports/win32/include/lwipopts.h b/ext/lwip-contrib/ports/win32/include/lwipopts.h new file mode 100644 index 0000000..7f7fa40 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/include/lwipopts.h @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_LWIPOPTS_H +#define LWIP_LWIPOPTS_H + +#define LWIP_IPV4 1 +#define LWIP_IPV6 1 + +#define NO_SYS 0 +#define LWIP_SOCKET (NO_SYS==0) +#define LWIP_NETCONN (NO_SYS==0) +#define LWIP_NETIF_API (NO_SYS==0) + +#define LWIP_IGMP LWIP_IPV4 +#define LWIP_ICMP LWIP_IPV4 + +#define LWIP_SNMP LWIP_UDP +#define MIB2_STATS LWIP_SNMP +#ifdef LWIP_HAVE_MBEDTLS +#define LWIP_SNMP_V3 (LWIP_SNMP) +#endif + +#define LWIP_DNS LWIP_UDP +#define LWIP_MDNS_RESPONDER LWIP_UDP + +#define LWIP_NUM_NETIF_CLIENT_DATA (LWIP_MDNS_RESPONDER) + +#define LWIP_HAVE_LOOPIF 1 +#define LWIP_NETIF_LOOPBACK 1 +#define LWIP_LOOPBACK_MAX_PBUFS 10 + +#define TCP_LISTEN_BACKLOG 1 + +#define LWIP_COMPAT_SOCKETS 1 +#define LWIP_SO_RCVTIMEO 1 +#define LWIP_SO_RCVBUF 1 + +#define LWIP_TCPIP_CORE_LOCKING 1 + +#define LWIP_NETIF_LINK_CALLBACK 1 +#define LWIP_NETIF_STATUS_CALLBACK 1 + +#ifdef LWIP_DEBUG + +#define LWIP_DBG_MIN_LEVEL 0 +#define PPP_DEBUG LWIP_DBG_OFF +#define MEM_DEBUG LWIP_DBG_OFF +#define MEMP_DEBUG LWIP_DBG_OFF +#define PBUF_DEBUG LWIP_DBG_OFF +#define API_LIB_DEBUG LWIP_DBG_OFF +#define API_MSG_DEBUG LWIP_DBG_OFF +#define TCPIP_DEBUG LWIP_DBG_OFF +#define NETIF_DEBUG LWIP_DBG_OFF +#define SOCKETS_DEBUG LWIP_DBG_OFF +#define DNS_DEBUG LWIP_DBG_OFF +#define AUTOIP_DEBUG LWIP_DBG_OFF +#define DHCP_DEBUG LWIP_DBG_OFF +#define IP_DEBUG LWIP_DBG_OFF +#define IP_REASS_DEBUG LWIP_DBG_OFF +#define ICMP_DEBUG LWIP_DBG_OFF +#define IGMP_DEBUG LWIP_DBG_OFF +#define UDP_DEBUG LWIP_DBG_OFF +#define TCP_DEBUG LWIP_DBG_OFF +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#define TCP_WND_DEBUG LWIP_DBG_OFF +#define TCP_FR_DEBUG LWIP_DBG_OFF +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +#define LWIP_DBG_TYPES_ON (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT) + + +/* ---------- Memory options ---------- */ +/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which + lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2 + byte alignment -> define MEM_ALIGNMENT to 2. */ +/* MSVC port: intel processors don't need 4-byte alignment, + but are faster that way! */ +#define MEM_ALIGNMENT 4U + +/* MEM_SIZE: the size of the heap memory. If the application will send +a lot of data that needs to be copied, this should be set high. */ +#define MEM_SIZE 10240 + +/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application + sends a lot of data out of ROM (or other static memory), this + should be set high. */ +#define MEMP_NUM_PBUF 16 +/* MEMP_NUM_RAW_PCB: the number of UDP protocol control blocks. One + per active RAW "connection". */ +#define MEMP_NUM_RAW_PCB 3 +/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + per active UDP "connection". */ +#define MEMP_NUM_UDP_PCB 4 +/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP + connections. */ +#define MEMP_NUM_TCP_PCB 5 +/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP + connections. */ +#define MEMP_NUM_TCP_PCB_LISTEN 8 +/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP + segments. */ +#define MEMP_NUM_TCP_SEG 16 +/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active + timeouts. */ +#define MEMP_NUM_SYS_TIMEOUT 17 + +/* The following four are used only with the sequential API and can be + set to 0 if the application only will use the raw API. */ +/* MEMP_NUM_NETBUF: the number of struct netbufs. */ +#define MEMP_NUM_NETBUF 2 +/* MEMP_NUM_NETCONN: the number of struct netconns. */ +#define MEMP_NUM_NETCONN 10 +/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used + for sequential API communication and incoming packets. Used in + src/api/tcpip.c. */ +#define MEMP_NUM_TCPIP_MSG_API 16 +#define MEMP_NUM_TCPIP_MSG_INPKT 16 + + +/* ---------- Pbuf options ---------- */ +/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ +#define PBUF_POOL_SIZE 160 + +/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ +#define PBUF_POOL_BUFSIZE 128 + +/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a + link level header. */ +#define PBUF_LINK_HLEN 16 + +/** SYS_LIGHTWEIGHT_PROT + * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection + * for certain critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#define SYS_LIGHTWEIGHT_PROT (NO_SYS==0) + + +/* ---------- TCP options ---------- */ +#define LWIP_TCP 1 +#define TCP_TTL 255 + +#define LWIP_ALTCP (LWIP_TCP) +#ifdef LWIP_HAVE_MBEDTLS +#define LWIP_ALTCP_TLS (LWIP_TCP) +#define LWIP_ALTCP_TLS_MBEDTLS (LWIP_TCP) +#endif + + +/* Controls if TCP should queue segments that arrive out of + order. Define to 0 if your device is low on memory. */ +#define TCP_QUEUE_OOSEQ 1 + +/* TCP Maximum segment size. */ +#define TCP_MSS 1024 + +/* TCP sender buffer space (bytes). */ +#define TCP_SND_BUF 2048 + +/* TCP sender buffer space (pbufs). This must be at least = 2 * + TCP_SND_BUF/TCP_MSS for things to work. */ +#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF/TCP_MSS) + +/* TCP writable space (bytes). This must be less than or equal + to TCP_SND_BUF. It is the amount of space which must be + available in the tcp snd_buf for select to return writable */ +#define TCP_SNDLOWAT (TCP_SND_BUF/2) + +/* TCP receive window. */ +#define TCP_WND 8096 + +/* Maximum number of retransmissions of data segments. */ +#define TCP_MAXRTX 12 + +/* Maximum number of retransmissions of SYN segments. */ +#define TCP_SYNMAXRTX 4 + + +/* ---------- ARP options ---------- */ +#define LWIP_ARP 1 +#define ARP_TABLE_SIZE 10 +#define ARP_QUEUEING 1 + + +/* ---------- IP options ---------- */ +/* Define IP_FORWARD to 1 if you wish to have the ability to forward + IP packets across network interfaces. If you are going to run lwIP + on a device with only one network interface, define this to 0. */ +#define IP_FORWARD 1 + +/* IP reassembly and segmentation.These are orthogonal even + * if they both deal with IP fragments */ +#define IP_REASSEMBLY 1 +#define IP_REASS_MAX_PBUFS 10 +#define MEMP_NUM_REASSDATA 10 +#define IP_FRAG 1 + + +/* ---------- ICMP options ---------- */ +#define ICMP_TTL 255 + + +/* ---------- DHCP options ---------- */ +/* Define LWIP_DHCP to 1 if you want DHCP configuration of + interfaces. */ +#define LWIP_DHCP LWIP_UDP + +/* 1 if you want to do an ARP check on the offered address + (recommended). */ +#define DHCP_DOES_ARP_CHECK (LWIP_DHCP) + + +/* ---------- AUTOIP options ------- */ +#define LWIP_AUTOIP (LWIP_DHCP) +#define LWIP_DHCP_AUTOIP_COOP (LWIP_DHCP && LWIP_AUTOIP) + + +/* ---------- UDP options ---------- */ +#define LWIP_UDP 1 +#define LWIP_UDPLITE LWIP_UDP +#define UDP_TTL 255 + + +/* ---------- RAW options ---------- */ +#define LWIP_RAW 1 + + +/* ---------- Statistics options ---------- */ + +#define LWIP_STATS 1 +#define LWIP_STATS_DISPLAY 1 + +#if LWIP_STATS +#define LINK_STATS 1 +#define IP_STATS 1 +#define ICMP_STATS 1 +#define IGMP_STATS 1 +#define IPFRAG_STATS 1 +#define UDP_STATS 1 +#define TCP_STATS 1 +#define MEM_STATS 1 +#define MEMP_STATS 1 +#define PBUF_STATS 1 +#define SYS_STATS 1 +#endif /* LWIP_STATS */ + + +/* ---------- PPP options ---------- */ + +#define PPP_SUPPORT 1 /* Set > 0 for PPP */ + +#if PPP_SUPPORT + +#define NUM_PPP 1 /* Max PPP sessions. */ + + +/* Select modules to enable. Ideally these would be set in the makefile but + * we're limited by the command line length so you need to modify the settings + * in this file. + */ +#define PPPOE_SUPPORT 1 +#define PPPOS_SUPPORT 1 + +#define PAP_SUPPORT 1 /* Set > 0 for PAP. */ +#define CHAP_SUPPORT 1 /* Set > 0 for CHAP. */ +#define MSCHAP_SUPPORT 0 /* Set > 0 for MSCHAP */ +#define CBCP_SUPPORT 0 /* Set > 0 for CBCP (NOT FUNCTIONAL!) */ +#define CCP_SUPPORT 0 /* Set > 0 for CCP */ +#define VJ_SUPPORT 1 /* Set > 0 for VJ header compression. */ +#define MD5_SUPPORT 1 /* Set > 0 for MD5 (see also CHAP) */ + +#endif /* PPP_SUPPORT */ + +#endif /* LWIP_LWIPOPTS_H */ diff --git a/ext/lwip-contrib/ports/win32/include/ppp_settings.h b/ext/lwip-contrib/ports/win32/include/ppp_settings.h new file mode 100644 index 0000000..7b3ee1a --- /dev/null +++ b/ext/lwip-contrib/ports/win32/include/ppp_settings.h @@ -0,0 +1,6 @@ +#ifdef _MSC_VER +#pragma warning (disable: 4242) /* PPP only: conversion from 'x' to 'y', possible loss of data */ +#pragma warning (disable: 4244) /* PPP only: conversion from 'x' to 'y', possible loss of data (again?) */ +#pragma warning (disable: 4310) /* PPP only: cast truncates constant value */ +#pragma warning (disable: 4706) /* PPP only: assignment within conditional expression */ +#endif /* MSC_VER */ diff --git a/ext/lwip-contrib/ports/win32/lwipcfg_msvc.h.example b/ext/lwip-contrib/ports/win32/lwipcfg_msvc.h.example new file mode 100644 index 0000000..2e48d2d --- /dev/null +++ b/ext/lwip-contrib/ports/win32/lwipcfg_msvc.h.example @@ -0,0 +1,72 @@ +/** + * Additional settings for the win32 port. + * Copy this to lwipcfg_msvc.h and make the config changes you need. + */ + +/* configuration for this port */ +#define PPP_USERNAME "Admin" +#define PPP_PASSWORD "pass" + +/** Define this to the index of the windows network adapter to use */ +#define PACKET_LIB_ADAPTER_NR 1 +/** Define this to the GUID of the windows network adapter to use + * or NOT define this if you want PACKET_LIB_ADAPTER_NR to be used */ +/*#define PACKET_LIB_ADAPTER_GUID "00000000-0000-0000-0000-000000000000"*/ +/*#define PACKET_LIB_GET_ADAPTER_NETADDRESS(addr) IP4_ADDR((addr), 192,168,1,0)*/ +/*#define PACKET_LIB_QUIET*/ + +/* If these 2 are not defined, the corresponding config setting is used */ +/* #define USE_DHCP 0 */ +/* #define USE_AUTOIP 0 */ + +/* #define USE_PCAPIF 1 */ +#define LWIP_PORT_INIT_IPADDR(addr) IP4_ADDR((addr), 192,168,1,200) +#define LWIP_PORT_INIT_GW(addr) IP4_ADDR((addr), 192,168,1,1) +#define LWIP_PORT_INIT_NETMASK(addr) IP4_ADDR((addr), 255,255,255,0) + +/* remember to change this MAC address to suit your needs! + the last octet will be increased by netif->num for each netif */ +#define LWIP_MAC_ADDR_BASE {0x00,0x01,0x02,0x03,0x04,0x05} + +/* #define USE_SLIPIF 0 */ +/* #define SIO_USE_COMPORT 0 */ +#ifdef USE_SLIPIF +#if USE_SLIPIF +#define LWIP_PORT_INIT_SLIP1_IPADDR(addr) IP4_ADDR((addr), 192, 168, 2, 2) +#define LWIP_PORT_INIT_SLIP1_GW(addr) IP4_ADDR((addr), 192, 168, 2, 1) +#define LWIP_PORT_INIT_SLIP1_NETMASK(addr) IP4_ADDR((addr), 255, 255, 255, 0) +#if USE_SLIPIF > 1 +#define LWIP_PORT_INIT_SLIP2_IPADDR(addr) IP4_ADDR((addr), 192, 168, 2, 1) +#define LWIP_PORT_INIT_SLIP2_GW(addr) IP4_ADDR((addr), 0, 0, 0, 0) +#define LWIP_PORT_INIT_SLIP2_NETMASK(addr) IP4_ADDR((addr), 255, 255, 255, 0)*/ +#endif /* USE_SLIPIF > 1 */ +#endif /* USE_SLIPIF */ +#endif /* USE_SLIPIF */ + +/* configuration for applications */ + +#define LWIP_CHARGEN_APP 0 +#define LWIP_DNS_APP 0 +#define LWIP_HTTPD_APP 0 +/* Set this to 1 to use the netconn http server, + * otherwise the raw api server will be used. */ +/*#define LWIP_HTTPD_APP_NETCONN */ +#define LWIP_NETBIOS_APP 0 +#define LWIP_NETIO_APP 0 +#define LWIP_PING_APP 0 +#define LWIP_RTP_APP 0 +#define LWIP_SHELL_APP 0 +#define LWIP_SNTP_APP 0 +#define LWIP_SOCKET_EXAMPLES_APP 0 +#define LWIP_TCPECHO_APP 0 +/* Set this to 1 to use the netconn tcpecho server, + * otherwise the raw api server will be used. */ +/*#define LWIP_TCPECHO_APP_NETCONN */ +#define LWIP_UDPECHO_APP 0 +#define LWIP_LWIPERF_APP 0 + +/*#define USE_DHCP 1*/ +/*#define USE_AUTOIP 1*/ + +/* define this to your custom application-init function */ +/* #define LWIP_APP_INIT my_app_init() */ diff --git a/ext/lwip-contrib/ports/win32/lwippools.h b/ext/lwip-contrib/ports/win32/lwippools.h new file mode 100644 index 0000000..8fc2c92 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/lwippools.h @@ -0,0 +1,20 @@ +/* OPTIONAL: Pools to replace heap allocation + * Optional: Pools can be used instead of the heap for mem_malloc. If + * so, these should be defined here, in increasing order according to + * the pool element size. + * + * LWIP_MALLOC_MEMPOOL(number_elements, element_size) + */ +#if MEM_USE_POOLS +LWIP_MALLOC_MEMPOOL_START +LWIP_MALLOC_MEMPOOL(100, 256) +LWIP_MALLOC_MEMPOOL(50, 512) +LWIP_MALLOC_MEMPOOL(20, 1024) +LWIP_MALLOC_MEMPOOL(20, 1536) +LWIP_MALLOC_MEMPOOL_END +#endif /* MEM_USE_POOLS */ + +/* Optional: Your custom pools can go here if you would like to use + * lwIP's memory pools for anything else. + */ +LWIP_MEMPOOL(SYS_MBOX, 22, 100, "SYS_MBOX") diff --git a/ext/lwip-contrib/ports/win32/mingw/Common.mk b/ext/lwip-contrib/ports/win32/mingw/Common.mk new file mode 100644 index 0000000..5cfd68f --- /dev/null +++ b/ext/lwip-contrib/ports/win32/mingw/Common.mk @@ -0,0 +1,50 @@ +# +# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. +# All rights reserved. +# +# 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. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +# +# This file is part of the lwIP TCP/IP stack. +# +# Author: Adam Dunkels +# + +CC=gcc + +# Architecture specific files. +LWIPARCH?=$(CONTRIBDIR)/ports/win32 +ARCHFILES=$(LWIPARCH)/sys_arch.c $(LWIPARCH)/test.c $(LWIPARCH)/pcapif.c \ + $(LWIPARCH)/pcapif_helper.c $(LWIPARCH)/sio.c + +WIN32_COMMON_MK_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) +include $(WIN32_COMMON_MK_DIR)/../../Common.allports.mk + +PCAPDIR=$(PCAP_DIR)/Include +LDFLAGS+=-L$(PCAP_DIR)/lib -lwpcap -lpacket +# -Wno-format: GCC complains about non-standard 64 bit modifier needed for MSVC runtime +CFLAGS+=-I$(PCAPDIR) -Wno-format + +pcapif.o: + $(CC) $(CFLAGS) -Wno-error -Wno-redundant-decls -c $(<:.o=.c) +pcapif_helper.o: + $(CC) $(CFLAGS) -std=c99 -Wno-redundant-decls -c $(<:.o=.c) diff --git a/ext/lwip-contrib/ports/win32/mingw/Makefile b/ext/lwip-contrib/ports/win32/mingw/Makefile new file mode 100644 index 0000000..541ba48 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/mingw/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. +# All rights reserved. +# +# 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. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +# +# This file is part of the lwIP TCP/IP stack. +# +# Author: Adam Dunkels +# + +all ipv4 compile: test +.PHONY: all + +include Common.mk + +clean: + cmd /c del /q *.o $(LWIPLIBCOMMON) $(APPLIB) test.exe *.s .depend* *.map + +depend dep: .depend + +include .depend + +.depend: $(LWIPFILES) $(APPFILES) + $(CCDEP) $(CFLAGS) -MM $^ > .depend || cmd /c del .depend + +test: .depend $(LWIPLIBCOMMON) $(APPLIB) test.o + $(CC) $(CFLAGS) -o test test.o -Wl,--start-group $(APPLIB) $(LWIPLIBCOMMON) -Wl,--end-group $(LDFLAGS) -Xlinker -Map=test.map diff --git a/ext/lwip-contrib/ports/win32/msvc/libcheck.vcxproj b/ext/lwip-contrib/ports/win32/msvc/libcheck.vcxproj new file mode 100644 index 0000000..24cfed6 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/msvc/libcheck.vcxproj @@ -0,0 +1,100 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {EBB156DC-01BF-47B2-B69C-1A750B6B5F09} + libcheck + + + + StaticLibrary + MultiByte + true + + + StaticLibrary + MultiByte + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + + Disabled + ..\check;..\..\..\..\check\src;%(AdditionalIncludeDirectories) + _LIB;WIN32;_DEBUG;HAVE_CONFIG_H;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + Level3 + EditAndContinue + + + + + MaxSpeed + true + ..\check;..\..\..\..\check\src;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;%(PreprocessorDefinitions) + MultiThreaded + true + Level3 + ProgramDatabase + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ext/lwip-contrib/ports/win32/msvc/libcheck.vcxproj.filters b/ext/lwip-contrib/ports/win32/msvc/libcheck.vcxproj.filters new file mode 100644 index 0000000..9be370e --- /dev/null +++ b/ext/lwip-contrib/ports/win32/msvc/libcheck.vcxproj.filters @@ -0,0 +1,96 @@ + + + + + {05d172f9-8ca6-4d9c-96e4-2b0480a8222f} + + + {eb9ccf88-7e08-4202-bb4f-5a51443fa480} + + + {3f044d95-ab52-45ce-b4ae-27797eb221b2} + + + {abb21abe-51c2-45df-bdc9-8e00ce7fe404} + + + + + Win32 + + + Win32 + + + Win32\sys + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + libcompat + + + + + Win32 + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + src + + + libcompat + + + libcompat + + + \ No newline at end of file diff --git a/ext/lwip-contrib/ports/win32/msvc/lwIP.vcxproj b/ext/lwip-contrib/ports/win32/msvc/lwIP.vcxproj new file mode 100644 index 0000000..5c13a8c --- /dev/null +++ b/ext/lwip-contrib/ports/win32/msvc/lwIP.vcxproj @@ -0,0 +1,552 @@ + + + + + Debug unittests + Win32 + + + Debug + Win32 + + + Release unittests + Win32 + + + Release + Win32 + + + + {2CC276FA-B226-49C9-8F82-7FCD5A228E28} + + + + StaticLibrary + false + MultiByte + + + StaticLibrary + false + MultiByte + + + StaticLibrary + false + MultiByte + + + StaticLibrary + false + MultiByte + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + .\$(Configuration)\ + .\$(Configuration)\$(ProjectName)\ + .\$(Configuration)\unittests\ + .\$(Configuration)\$(ProjectName)\unittests\ + .\$(Configuration)\unittests\ + .\$(Configuration)\$(ProjectName)\unittests\ + + + + MaxSpeed + OnlyExplicitInline + ..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;..\..\..\apps\snmp_private_mib;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreaded + true + $(IntDir)$(ProjectName).pdb + EnableAllWarnings + true + ProgramDatabase + Default + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0407 + + + true + + + + + Disabled + ..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;..\..\..\apps\snmp_private_mib;%(AdditionalIncludeDirectories) + _LIB;WIN32;_DEBUG;LWIP_DEBUG;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + + + $(IntDir)$(ProjectName).pdb + EnableAllWarnings + true + EditAndContinue + Default + true + + + _DEBUG;%(PreprocessorDefinitions) + 0x0407 + + + true + + + + + Disabled + ..\..\..\..\lwip\test\unit;..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;%(AdditionalIncludeDirectories) + LWIP_NORAND;_LIB;WIN32;_DEBUG;LWIP_DEBUG;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + + + $(IntDir)$(ProjectName).pdb + EnableAllWarnings + true + EditAndContinue + Default + true + + + _DEBUG;%(PreprocessorDefinitions) + 0x0407 + + + true + + + + + MaxSpeed + OnlyExplicitInline + ..\..\..\..\lwip\test\unit;..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;%(AdditionalIncludeDirectories) + LWIP_NORAND;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreaded + true + $(IntDir)$(ProjectName).pdb + EnableAllWarnings + true + ProgramDatabase + Default + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0407 + + + true + + + + + true + true + true + true + + + Document + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + Document + true + true + true + true + + + Document + + + Document + true + true + true + true + + + + + + + + + + + + + + + + + + + + true + true + true + true + + + + + + + + + + + + ..\..\..\..\mbedtls\include;..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;..\..\..\apps\snmp_private_mib;%(AdditionalIncludeDirectories) + ..\..\..\..\mbedtls\include;..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;..\..\..\apps\snmp_private_mib;%(AdditionalIncludeDirectories) + ..\..\..\..\mbedtls\include;..\..\..\..\lwip\test\unit;..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;%(AdditionalIncludeDirectories) + ..\..\..\..\mbedtls\include;..\..\..\..\lwip\test\unit;..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;%(AdditionalIncludeDirectories) + + + ..\..\..\..\mbedtls\include;..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;..\..\..\apps\snmp_private_mib;%(AdditionalIncludeDirectories) + ..\..\..\..\mbedtls\include;..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;..\..\..\apps\snmp_private_mib;%(AdditionalIncludeDirectories) + ..\..\..\..\mbedtls\include;..\..\..\..\lwip\test\unit;..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;%(AdditionalIncludeDirectories) + ..\..\..\..\mbedtls\include;..\..\..\..\lwip\test\unit;..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;%(AdditionalIncludeDirectories) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ext/lwip-contrib/ports/win32/msvc/lwIP.vcxproj.filters b/ext/lwip-contrib/ports/win32/msvc/lwIP.vcxproj.filters new file mode 100644 index 0000000..91a503a --- /dev/null +++ b/ext/lwip-contrib/ports/win32/msvc/lwIP.vcxproj.filters @@ -0,0 +1,1002 @@ + + + + + {51757ae3-05ca-4e6a-a745-19c9ffc62278} + + + {e40d58ed-58be-4618-9664-6df29e27f835} + + + {5752fd8f-90c3-4381-8b6a-86c09a2f9859} + + + {48a805a9-e5d2-4eed-b29c-02b57140a03d} + + + {8a8dba58-934c-4292-aa8d-d20e2b801bd4} + + + {20594706-d6e1-4503-bc38-f297892d752a} + + + {1075aec7-b001-47bd-9846-ed635687e26e} + + + {9b7b3b39-f3b0-4915-81d9-d66c3443c348} + + + {75f75ac5-73a4-4458-bc23-eaed529c37e1} + + + {97772339-4210-4a32-82d0-d25269d3e3d6} + + + {06467ead-0683-44db-bc41-6aa5a82490f0} + + + {166a3203-ccc3-4eff-9eaa-1e5648a7fb5b} + + + {6b889738-b59a-450a-b4dd-0d1986bffca1} + + + {c64c0664-acd9-4f2f-8bd7-78250f4b7b4b} + + + {56e8d041-f1e0-4b02-a173-563190c0eb4a} + + + {dc783ea8-63ed-4de6-b576-a87c318a7ad1} + + + {7822191b-1cd0-4ce8-a852-da0474977fc4} + + + {b22a3b7a-d076-44a5-9a16-1e6f49cd5a94} + + + {0109fdbb-3aed-45fa-a308-493988755364} + + + {32a9c4ed-7687-48bb-8b9d-482c2f6c7554} + + + {c6c4a1a7-dab8-4463-b155-07e7303b54e4} + + + {2e87d0f7-38a3-45f8-870d-f8622c20e9d9} + + + {45f6a578-1f4b-4741-9b55-5b5084ecc1d9} + + + {92215272-cad9-4cf0-a2e1-705f6220e2a9} + + + {bdd3995a-aa34-4a4e-891e-a13c5373d618} + + + {d0ce6e8b-4b30-498b-a1bb-aecee958df42} + + + {6db73869-23f6-48ab-8d92-c8e478e55892} + + + {65542a97-c588-47b3-b1f6-ae51645c736e} + + + {ffd283f4-44f0-4be2-83a3-8bd55f29e80f} + + + {d9456888-d299-48ff-8165-ff499e5a0ba3} + + + {5aa786e4-df26-432c-b32c-9c4fac00b951} + + + {8fb42d78-1e77-4208-b457-44f41c4cc901} + + + {81578f11-9d3c-4bc8-a518-6f78f082fe0e} + + + {f8d65087-0cee-46de-8d8c-dca719bf2a4b} + + + {91d8473a-deb5-4943-8b63-b43d86c7fa1c} + + + {15855a74-48c6-473c-b4cb-40ec065698d4} + + + + + + + + + + doc + + + doc + + + doc + + + doc + + + doc + + + doc + + + doc + + + doc\doxygen + + + doc\doxygen + + + doc\doxygen + + + + + src\api + + + src\api + + + src\api + + + src\api + + + src\api + + + src\api + + + src\api + + + src\api + + + src\apps\lwiperf + + + src\apps\netbiosns + + + src\apps\sntp + + + src\core + + + src\core + + + src\core + + + src\core + + + src\core + + + src\core + + + src\core + + + src\core + + + src\core + + + src\core + + + src\core + + + src\core + + + src\core + + + src\core + + + src\core + + + src\core\ipv4 + + + src\core\ipv4 + + + src\core\ipv4 + + + src\core\ipv4 + + + src\core\ipv4 + + + src\core\ipv4 + + + src\core\ipv6 + + + src\core\ipv6 + + + src\core\ipv6 + + + src\core\ipv6 + + + src\core\ipv6 + + + src\core\ipv6 + + + src\core\ipv6 + + + src\core\ipv6 + + + src\core\ipv6 + + + src\netif + + + src\netif + + + src\netif + + + src\netif + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp + + + src\netif\ppp\polarssl + + + src\netif\ppp\polarssl + + + src\netif\ppp\polarssl + + + src\netif\ppp\polarssl + + + src\netif\ppp\polarssl + + + arch + + + arch + + + src\apps\httpd + + + src\apps\httpd + + + src\apps\httpd + + + src\apps\snmp + + + src\apps\snmp + + + src\apps\snmp + + + src\apps\snmp + + + src\apps\snmp + + + src\apps\snmp + + + src\apps\snmp + + + src\apps\snmp + + + src\apps\snmp + + + src\apps\snmp + + + src\apps\snmp + + + src\core + + + src\apps\snmp + + + src\apps\snmp + + + src\apps\snmp + + + src\apps\snmp + + + src\apps\snmp + + + src\apps\snmp + + + src\apps\snmp + + + src\apps\snmp + + + src\netif\ppp + + + src\core\ipv4 + + + src\core\ipv4 + + + src\core + + + src\apps\mdns + + + src\apps\snmp + + + doc + + + src\apps\tftp + + + src\apps\mqtt + + + src\api + + + src\netif + + + src\apps\snmp + + + src\apps\snmp + + + src\core + + + src\core + + + src\apps\altcp_tls + + + src\apps\altcp_tls + + + src\apps\smtp + + + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\netif + + + src\include\netif + + + src\include\netif + + + src\include\netif + + + src\include\netif + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp + + + src\include\netif\ppp\polarssl + + + src\include\netif\ppp\polarssl + + + src\include\netif\ppp\polarssl + + + src\include\netif\ppp\polarssl + + + src\include\netif\ppp\polarssl + + + arch + + + arch + + + arch + + + arch + + + arch + + + arch + + + arch + + + arch + + + src\include\lwip\priv + + + src\include\lwip\priv + + + src\include\lwip\priv + + + src\include\lwip\priv + + + src\include\lwip\priv + + + src\apps\httpd + + + src\apps\httpd + + + src\apps\snmp + + + src\apps\snmp + + + src\apps\snmp + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\apps\snmp + + + src\include\netif\ppp + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip\prot + + + src\include\lwip\prot + + + src\include\lwip\prot + + + src\include\lwip\prot + + + src\include\lwip\prot + + + src\apps\snmp + + + src\include\lwip\prot + + + src\include\lwip\prot + + + src\include\lwip\prot + + + src\include\lwip\prot + + + src\include\lwip\prot + + + src\include\lwip\prot + + + src\include\lwip\prot + + + src\include\lwip\prot + + + src\include\lwip\apps + + + src\include\lwip\prot + + + src\include\lwip\prot + + + doc\doxygen + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip + + + src\include\lwip\priv + + + src\include\lwip\apps + + + src\include\lwip + + + src\include\lwip + + + src\include\lwip\priv + + + src\include\netif + + + src\include\netif + + + src\include\lwip + + + src\include\lwip + + + src\apps\altcp_tls + + + src\apps\altcp_tls + + + src\include\lwip + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\lwip\priv + + + src\include\lwip\apps + + + src\include\lwip\apps + + + src\include\compat\posix\sys + + + src\include\compat\posix + + + src\include\compat\posix\net + + + src\include\compat\posix\arpa + + + src\include\compat\stdc + + + src\include\lwip\prot + + + src\include\lwip\prot + + + + + arch + + + \ No newline at end of file diff --git a/ext/lwip-contrib/ports/win32/msvc/lwIP_Test.sln b/ext/lwip-contrib/ports/win32/msvc/lwIP_Test.sln new file mode 100644 index 0000000..ce59abd --- /dev/null +++ b/ext/lwip-contrib/ports/win32/msvc/lwIP_Test.sln @@ -0,0 +1,37 @@ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C++ Express 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lwIP_Test", "lwIP_Test.vcxproj", "{8CC0CE51-32CF-4585-BFAF-A9343BC5A96D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lwIP pcapif", "lwIP_pcapif.vcxproj", "{6F44E49E-9F21-4144-91EC-53B92AEF62CE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lwIP", "lwIP.vcxproj", "{2CC276FA-B226-49C9-8F82-7FCD5A228E28}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "makefsdata", "makefsdata.vcxproj", "{0BFC0F21-8E84-4E68-A9E1-CE2A09B72F6D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8CC0CE51-32CF-4585-BFAF-A9343BC5A96D}.Debug|Win32.ActiveCfg = Debug|Win32 + {8CC0CE51-32CF-4585-BFAF-A9343BC5A96D}.Debug|Win32.Build.0 = Debug|Win32 + {8CC0CE51-32CF-4585-BFAF-A9343BC5A96D}.Release|Win32.ActiveCfg = Release|Win32 + {8CC0CE51-32CF-4585-BFAF-A9343BC5A96D}.Release|Win32.Build.0 = Release|Win32 + {6F44E49E-9F21-4144-91EC-53B92AEF62CE}.Debug|Win32.ActiveCfg = Debug|Win32 + {6F44E49E-9F21-4144-91EC-53B92AEF62CE}.Debug|Win32.Build.0 = Debug|Win32 + {6F44E49E-9F21-4144-91EC-53B92AEF62CE}.Release|Win32.ActiveCfg = Release|Win32 + {6F44E49E-9F21-4144-91EC-53B92AEF62CE}.Release|Win32.Build.0 = Release|Win32 + {2CC276FA-B226-49C9-8F82-7FCD5A228E28}.Debug|Win32.ActiveCfg = Debug|Win32 + {2CC276FA-B226-49C9-8F82-7FCD5A228E28}.Debug|Win32.Build.0 = Debug|Win32 + {2CC276FA-B226-49C9-8F82-7FCD5A228E28}.Release|Win32.ActiveCfg = Release|Win32 + {2CC276FA-B226-49C9-8F82-7FCD5A228E28}.Release|Win32.Build.0 = Release|Win32 + {0BFC0F21-8E84-4E68-A9E1-CE2A09B72F6D}.Debug|Win32.ActiveCfg = Debug|Win32 + {0BFC0F21-8E84-4E68-A9E1-CE2A09B72F6D}.Debug|Win32.Build.0 = Debug|Win32 + {0BFC0F21-8E84-4E68-A9E1-CE2A09B72F6D}.Release|Win32.ActiveCfg = Release|Win32 + {0BFC0F21-8E84-4E68-A9E1-CE2A09B72F6D}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ext/lwip-contrib/ports/win32/msvc/lwIP_Test.vcxproj b/ext/lwip-contrib/ports/win32/msvc/lwIP_Test.vcxproj new file mode 100644 index 0000000..c5c66ea --- /dev/null +++ b/ext/lwip-contrib/ports/win32/msvc/lwIP_Test.vcxproj @@ -0,0 +1,183 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {8CC0CE51-32CF-4585-BFAF-A9343BC5A96D} + lwIP_test + + + + Application + false + MultiByte + + + Application + false + MultiByte + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + .\$(Configuration)\ + .\$(Configuration)\$(ProjectName)\ + false + true + + + + .\Release/test.tlb + + + + + MaxSpeed + OnlyExplicitInline + ..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;..\..\..;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + $(IntDir)$(TargetName).pch + $(IntDir)$(ProjectName).pdb + EnableAllWarnings + true + Default + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0407 + + + Packet.lib;wpcap.lib;%(AdditionalDependencies) + true + $(PCAP_DIR)\Lib;%(AdditionalLibraryDirectories) + .\Release/test.pdb + Console + false + + + MachineX86 + + + + + .\Debug/test.tlb + + + + + Disabled + ..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;..\..\..;%(AdditionalIncludeDirectories) + _CONSOLE;WIN32;_DEBUG;LWIP_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + + + $(IntDir)$(TargetName).pch + $(IntDir)$(ProjectName).pdb + EnableAllWarnings + true + EditAndContinue + Default + true + + + _DEBUG;%(PreprocessorDefinitions) + 0x0407 + + + Packet.lib;wpcap.lib;%(AdditionalDependencies) + true + $(PCAP_DIR)\Lib;%(AdditionalLibraryDirectories) + true + Console + false + + + MachineX86 + + + + + + + + + + Disabled + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + EnableFastChecks + MaxSpeed + %(AdditionalIncludeDirectories) + %(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {2cc276fa-b226-49c9-8f82-7fcd5a228e28} + false + + + {6f44e49e-9f21-4144-91ec-53b92aef62ce} + false + + + + + + \ No newline at end of file diff --git a/ext/lwip-contrib/ports/win32/msvc/lwIP_Test.vcxproj.filters b/ext/lwip-contrib/ports/win32/msvc/lwIP_Test.vcxproj.filters new file mode 100644 index 0000000..bc0beaf --- /dev/null +++ b/ext/lwip-contrib/ports/win32/msvc/lwIP_Test.vcxproj.filters @@ -0,0 +1,123 @@ + + + + + {e858c3d0-1558-4d47-bc6a-9d4a55ce3d3a} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {0582eefd-a68e-45f8-b93c-f828c4794f30} + + + {ed0627c2-099a-4da8-af0c-142003828f9f} + + + {4ffb2268-6fc6-44d7-8e3b-2a3f68b8d5a3} + + + {93b36161-88b2-448c-9c45-ac6f27b98290} + + + + + Source Files + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\addons\tcp_isn + + + Source Files\addons\ipv6_static_routing + + + Source Files\apps + + + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\apps + + + Source Files\addons\tcp_isn + + + Source Files\addons\ipv6_static_routing + + + Source Files\apps + + + + + Source Files\addons\ipv6_static_routing + + + \ No newline at end of file diff --git a/ext/lwip-contrib/ports/win32/msvc/lwIP_pcapif.vcxproj b/ext/lwip-contrib/ports/win32/msvc/lwIP_pcapif.vcxproj new file mode 100644 index 0000000..4a407d1 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/msvc/lwIP_pcapif.vcxproj @@ -0,0 +1,111 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + lwIP pcapif + {6F44E49E-9F21-4144-91EC-53B92AEF62CE} + lwIP pcapif + + + + StaticLibrary + false + MultiByte + + + StaticLibrary + false + MultiByte + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + .\$(Configuration)\ + .\$(Configuration)\$(ProjectName)\ + + + + Disabled + ..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;.\;$(PCAP_DIR)\Include;%(AdditionalIncludeDirectories) + _LIB;WIN32;_DEBUG;LWIP_DEBUG;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + + + $(IntDir)$(ProjectName).pdb + EnableAllWarnings + true + EditAndContinue + Default + true + + + _DEBUG;%(PreprocessorDefinitions) + 0x0407 + + + + + + MaxSpeed + OnlyExplicitInline + ..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;.\;$(PCAP_DIR)\Include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + $(IntDir)$(TargetName).pch + $(IntDir)$(ProjectName).pdb + EnableAllWarnings + true + Default + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0407 + + + true + + + + + + + + + + + + + {2cc276fa-b226-49c9-8f82-7fcd5a228e28} + false + + + + + + \ No newline at end of file diff --git a/ext/lwip-contrib/ports/win32/msvc/lwIP_pcapif.vcxproj.filters b/ext/lwip-contrib/ports/win32/msvc/lwIP_pcapif.vcxproj.filters new file mode 100644 index 0000000..f933f17 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/msvc/lwIP_pcapif.vcxproj.filters @@ -0,0 +1,28 @@ + + + + + {0d38b8c3-e694-4572-89b8-fc6e825a092d} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {e5ce29d5-319e-4e99-978b-b88e8d6167e4} + + + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/ext/lwip-contrib/ports/win32/msvc/lwIP_unittests.sln b/ext/lwip-contrib/ports/win32/msvc/lwIP_unittests.sln new file mode 100644 index 0000000..2dfefb0 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/msvc/lwIP_unittests.sln @@ -0,0 +1,31 @@ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C++ Express 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lwip_unittests", "lwip_unittests.vcxproj", "{6CCABAA4-F86F-4119-AFF8-43C9A4A234C2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lwIP", "lwIP.vcxproj", "{2CC276FA-B226-49C9-8F82-7FCD5A228E28}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcheck", "libcheck.vcxproj", "{EBB156DC-01BF-47B2-B69C-1A750B6B5F09}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6CCABAA4-F86F-4119-AFF8-43C9A4A234C2}.Debug|Win32.ActiveCfg = Debug|Win32 + {6CCABAA4-F86F-4119-AFF8-43C9A4A234C2}.Debug|Win32.Build.0 = Debug|Win32 + {6CCABAA4-F86F-4119-AFF8-43C9A4A234C2}.Release|Win32.ActiveCfg = Release|Win32 + {6CCABAA4-F86F-4119-AFF8-43C9A4A234C2}.Release|Win32.Build.0 = Release|Win32 + {2CC276FA-B226-49C9-8F82-7FCD5A228E28}.Debug|Win32.ActiveCfg = Debug unittests|Win32 + {2CC276FA-B226-49C9-8F82-7FCD5A228E28}.Debug|Win32.Build.0 = Debug unittests|Win32 + {2CC276FA-B226-49C9-8F82-7FCD5A228E28}.Release|Win32.ActiveCfg = Release unittests|Win32 + {2CC276FA-B226-49C9-8F82-7FCD5A228E28}.Release|Win32.Build.0 = Release unittests|Win32 + {EBB156DC-01BF-47B2-B69C-1A750B6B5F09}.Debug|Win32.ActiveCfg = Debug|Win32 + {EBB156DC-01BF-47B2-B69C-1A750B6B5F09}.Debug|Win32.Build.0 = Debug|Win32 + {EBB156DC-01BF-47B2-B69C-1A750B6B5F09}.Release|Win32.ActiveCfg = Release|Win32 + {EBB156DC-01BF-47B2-B69C-1A750B6B5F09}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ext/lwip-contrib/ports/win32/msvc/lwip_unittests.vcxproj b/ext/lwip-contrib/ports/win32/msvc/lwip_unittests.vcxproj new file mode 100644 index 0000000..5a6a011 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/msvc/lwip_unittests.vcxproj @@ -0,0 +1,131 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {6CCABAA4-F86F-4119-AFF8-43C9A4A234C2} + lwip_unittests + + + + Application + MultiByte + true + + + Application + MultiByte + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + + Disabled + ..\check;..\..\..\..\check\src;..\..\..\..\lwip\test\unit;..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;%(AdditionalIncludeDirectories) + _LIB;WIN32;_DEBUG;LWIP_DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + EnableAllWarnings + EditAndContinue + 4820 + + + true + false + + + MachineX86 + + + + + MaxSpeed + true + ..\check;..\..\..\..\check\src;..\..\..\..\lwip\test\unit;..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;..;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreaded + true + Level4 + ProgramDatabase + + + true + true + true + false + + + MachineX86 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {ebb156dc-01bf-47b2-b69c-1a750b6b5f09} + false + + + {2cc276fa-b226-49c9-8f82-7fcd5a228e28} + false + + + + + + \ No newline at end of file diff --git a/ext/lwip-contrib/ports/win32/msvc/lwip_unittests.vcxproj.filters b/ext/lwip-contrib/ports/win32/msvc/lwip_unittests.vcxproj.filters new file mode 100644 index 0000000..ae8d325 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/msvc/lwip_unittests.vcxproj.filters @@ -0,0 +1,120 @@ + + + + + {e351c538-9f2b-4a01-bf46-3ee8873cbc0f} + + + {5805c4bc-32c1-49cf-a35e-af58757e2d7a} + + + {173ba4ab-b194-4933-8e02-319044c2a8fa} + + + {70c655a7-f40f-4728-b586-33fd9598b355} + + + {a6b60d4e-4b81-44f2-9408-2e45cc769391} + + + {d454902e-ce5b-48ae-a690-e6490bdbbf17} + + + {d9501476-6102-4f14-90bd-35322fbd2fb2} + + + {b04f182c-1910-456d-9388-397dfe82dbc9} + + + {fd48ae04-ec85-478f-a97c-a7c8384a2d94} + + + {fe93fc95-f1af-4a1f-a086-c1771dbf4d79} + + + + + core + + + core + + + tcp + + + tcp + + + tcp + + + udp + + + etharp + + + dhcp + + + + mdns + + + api + + + arch + + + mqtt + + + ip4 + + + + + core + + + core + + + tcp + + + tcp + + + tcp + + + udp + + + etharp + + + dhcp + + + + + mdns + + + api + + + arch + + + mqtt + + + ip4 + + + \ No newline at end of file diff --git a/ext/lwip-contrib/ports/win32/msvc/makefsdata.vcxproj b/ext/lwip-contrib/ports/win32/msvc/makefsdata.vcxproj new file mode 100644 index 0000000..b0d9aa7 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/msvc/makefsdata.vcxproj @@ -0,0 +1,99 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + {0BFC0F21-8E84-4E68-A9E1-CE2A09B72F6D} + makefsdata + Win32Proj + + + + Application + Unicode + true + + + Application + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + + + + Disabled + ..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + true + EditAndContinue + + + true + Console + false + + + MachineX86 + + + + + MaxSpeed + true + ..\..\..\..\lwip\src\include;..\..\..\..\lwip\src\include\ipv4;..\..\..\..\lwip\src\include\ipv6;..\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level4 + true + ProgramDatabase + + + true + Console + true + true + false + + + MachineX86 + + + + + + \ No newline at end of file diff --git a/ext/lwip-contrib/ports/win32/msvc/makefsdata.vcxproj.filters b/ext/lwip-contrib/ports/win32/msvc/makefsdata.vcxproj.filters new file mode 100644 index 0000000..e48a9ad --- /dev/null +++ b/ext/lwip-contrib/ports/win32/msvc/makefsdata.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Quelldateien + + + \ No newline at end of file diff --git a/ext/lwip-contrib/ports/win32/pcapif.c b/ext/lwip-contrib/ports/win32/pcapif.c new file mode 100644 index 0000000..26e58ba --- /dev/null +++ b/ext/lwip-contrib/ports/win32/pcapif.c @@ -0,0 +1,1083 @@ +/** + * pcapif.c - This file is part of lwIP pcapif + * + **************************************************************************** + * + * This file is derived from an example in lwIP with the following license: + * + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * 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 of the Institute 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 INSTITUTE 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 INSTITUTE 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 the port-dependent configuration */ +#include "lwipcfg_msvc.h" + +#include +#include + +#ifdef _MSC_VER +#pragma warning( push, 3 ) +#include "pcap.h" +#pragma warning ( pop ) +#else +/* e.g. mingw */ +#define _MSC_VER 1500 +#include "pcap.h" +#undef _MSC_VER +#endif + +#include "lwip/opt.h" + +#if LWIP_ETHERNET + +#include "pcapif.h" + +#include +#include +#include + +#include "lwip/debug.h" + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/sys.h" +#include "lwip/ip.h" +#include "lwip/snmp.h" +#include "lwip/tcpip.h" +#include "lwip/timeouts.h" +#include "lwip/ethip6.h" + +#include "lwip/etharp.h" + +/* For compatibility with old pcap */ +#ifndef PCAP_OPENFLAG_PROMISCUOUS +#define PCAP_OPENFLAG_PROMISCUOUS 1 +#endif + +/** Set this to 0 to receive all multicast ethernet destination addresses */ +#ifndef PCAPIF_FILTER_GROUP_ADDRESSES +#define PCAPIF_FILTER_GROUP_ADDRESSES 1 +#endif + +/** Set this to 1 to receive all frames (also unicast to other addresses) + * In this mode, filtering out our own tx packets from loopback receiving + * is done via matching rx against recent tx (memcmp). + */ +#ifndef PCAPIF_RECEIVE_PROMISCUOUS +#define PCAPIF_RECEIVE_PROMISCUOUS 0 +#endif + +/* Define those to better describe your network interface. + For now, we use 'e0', 'e1', 'e2' and so on */ +#define IFNAME0 'e' +#define IFNAME1 '0' + +/** index of the network adapter to use for lwIP */ +#ifndef PACKET_LIB_ADAPTER_NR +#define PACKET_LIB_ADAPTER_NR 0 +#endif + +/** If 1, check link state and report it to lwIP. + * If 0, don't check link state (lwIP link state is always UP). + */ +#ifndef PCAPIF_HANDLE_LINKSTATE +#define PCAPIF_HANDLE_LINKSTATE 1 +#endif + +/** If 1, use PBUF_REF for RX (for testing purposes mainly). + * For this, LWIP_SUPPORT_CUSTOM_PBUF must be enabled. + */ +#ifndef PCAPIF_RX_REF +#define PCAPIF_RX_REF 0 +#endif + +/** This can be used when netif->state is used for something else in your + * application (e.g. when wrapping a class around this interface). Just + * make sure this define returns the state pointer set by + * pcapif_low_level_init() (e.g. by using an offset or a callback). + */ +#ifndef PCAPIF_GET_STATE_PTR +#define PCAPIF_GET_STATE_PTR(netif) ((netif)->state) +#endif + +#if PCAPIF_HANDLE_LINKSTATE +#include "pcapif_helper.h" + +/* Define "PHY" delay when "link up" */ +#ifndef PCAPIF_LINKUP_DELAY +#define PCAPIF_LINKUP_DELAY 0 +#endif + +/* Define PCAPIF_RX_LOCK_LWIP and PCAPIF_RX_UNLOCK_LWIP if you need to lock the lwIP core + before/after pbuf_alloc() or netif->input() are called on RX. */ +#ifndef PCAPIF_RX_LOCK_LWIP +#define PCAPIF_RX_LOCK_LWIP() +#endif +#ifndef PCAPIF_RX_UNLOCK_LWIP +#define PCAPIF_RX_UNLOCK_LWIP() +#endif + +#define PCAPIF_LINKCHECK_INTERVAL_MS 500 + +/* link state notification macro */ +#if PCAPIF_LINKUP_DELAY +#define PCAPIF_NOTIFY_LINKSTATE(netif, linkfunc) sys_timeout(PCAPIF_LINKUP_DELAY, (sys_timeout_handler)linkfunc, netif) +#else /* PHY_LINKUP_DELAY */ +#define PCAPIF_NOTIFY_LINKSTATE(netif, linkfunc) linkfunc(netif) +#endif /* PHY_LINKUP_DELAY */ + +#endif /* PCAPIF_HANDLE_LINKSTATE */ + +#define ETH_MIN_FRAME_LEN 60U +#define ETH_MAX_FRAME_LEN 1518U + +#define ADAPTER_NAME_LEN 128 +#define ADAPTER_DESC_LEN 128 + +#if PCAPIF_RECEIVE_PROMISCUOUS +#ifndef PCAPIF_LOOPBACKFILTER_NUM_TX_PACKETS +#define PCAPIF_LOOPBACKFILTER_NUM_TX_PACKETS 128 +#endif +struct pcapipf_pending_packet { + struct pcapipf_pending_packet *next; + u16_t len; + u8_t data[ETH_MAX_FRAME_LEN]; +}; +#endif /* PCAPIF_RECEIVE_PROMISCUOUS */ + +/* Packet Adapter informations */ +struct pcapif_private { + void *input_fn_arg; + pcap_t *adapter; + char name[ADAPTER_NAME_LEN]; + char description[ADAPTER_DESC_LEN]; + int shutdown_called; +#if PCAPIF_RX_USE_THREAD + volatile int rx_run; + volatile int rx_running; +#endif /* PCAPIF_RX_USE_THREAD */ +#if PCAPIF_HANDLE_LINKSTATE + struct pcapifh_linkstate *link_state; + enum pcapifh_link_event last_link_event; +#endif /* PCAPIF_HANDLE_LINKSTATE */ +#if PCAPIF_RECEIVE_PROMISCUOUS + struct pcapipf_pending_packet packets[PCAPIF_LOOPBACKFILTER_NUM_TX_PACKETS]; + struct pcapipf_pending_packet *tx_packets; + struct pcapipf_pending_packet *free_packets; +#endif /* PCAPIF_RECEIVE_PROMISCUOUS */ +}; + +#if PCAPIF_RECEIVE_PROMISCUOUS +static void +pcapif_init_tx_packets(struct pcapif_private *priv) +{ + int i; + priv->tx_packets = NULL; + priv->free_packets = NULL; + for (i = 0; i < PCAPIF_LOOPBACKFILTER_NUM_TX_PACKETS; i++) { + struct pcapipf_pending_packet *pack = &priv->packets[i]; + pack->len = 0; + pack->next = priv->free_packets; + priv->free_packets = pack; + } +} + +static void +pcapif_add_tx_packet(struct pcapif_private *priv, unsigned char *buf, u16_t tot_len) +{ + struct pcapipf_pending_packet *tx; + struct pcapipf_pending_packet *pack; + SYS_ARCH_DECL_PROTECT(lev); + + /* get a free packet (locked) */ + SYS_ARCH_PROTECT(lev); + pack = priv->free_packets; + if ((pack == NULL) && (priv->tx_packets != NULL)) { + /* no free packets, reuse the oldest */ + pack = priv->tx_packets; + priv->tx_packets = pack->next; + } + LWIP_ASSERT("no free packet", pack != NULL); + priv->free_packets = pack->next; + pack->next = NULL; + SYS_ARCH_UNPROTECT(lev); + + /* set up the packet (unlocked) */ + pack->len = tot_len; + memcpy(pack->data, buf, tot_len); + + /* put the packet on the list (locked) */ + SYS_ARCH_PROTECT(lev); + if (priv->tx_packets != NULL) { + for (tx = priv->tx_packets; tx->next != NULL; tx = tx->next); + LWIP_ASSERT("bug", tx != NULL); + tx->next = pack; + } else { + priv->tx_packets = pack; + } + SYS_ARCH_UNPROTECT(lev); +} + +static int +pcapif_compare_packets(struct pcapipf_pending_packet *pack, const void *packet, int packet_len) +{ + if (pack->len == packet_len) { + if (!memcmp(pack->data, packet, packet_len)) { + return 1; + } + } + return 0; +} + +static int +pcaipf_is_tx_packet(struct netif *netif, const void *packet, int packet_len) +{ + struct pcapif_private *priv = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif); + struct pcapipf_pending_packet *iter, *last; + SYS_ARCH_DECL_PROTECT(lev); + + last = priv->tx_packets; + if (last == NULL) { + /* list is empty */ + return 0; + } + /* compare the first packet */ + if (pcapif_compare_packets(last, packet, packet_len)) { + SYS_ARCH_PROTECT(lev); + LWIP_ASSERT("list has changed", last == priv->tx_packets); + priv->tx_packets = last->next; + last->next = priv->free_packets; + priv->free_packets = last; + last->len = 0; + SYS_ARCH_UNPROTECT(lev); + return 1; + } + SYS_ARCH_PROTECT(lev); + for (iter = last->next; iter != NULL; last = iter, iter = iter->next) { + /* unlock while comparing (this works because we have a clean threading separation + of adding and removing items and adding is only done at the end) */ + SYS_ARCH_UNPROTECT(lev); + if (pcapif_compare_packets(iter, packet, packet_len)) { + SYS_ARCH_PROTECT(lev); + LWIP_ASSERT("last != NULL", last != NULL); + last->next = iter->next; + iter->next = priv->free_packets; + priv->free_packets = iter; + last->len = 0; + SYS_ARCH_UNPROTECT(lev); + return 1; + } + SYS_ARCH_PROTECT(lev); + } + SYS_ARCH_UNPROTECT(lev); + return 0; +} +#else /* PCAPIF_RECEIVE_PROMISCUOUS */ +#define pcapif_init_tx_packets(priv) +#define pcapif_add_tx_packet(priv, buf, tot_len) +static int +pcaipf_is_tx_packet(struct netif *netif, const void *packet, int packet_len) +{ + const struct eth_addr *src = (const struct eth_addr *)packet + 1; + if (packet_len >= (ETH_HWADDR_LEN * 2)) { + /* Don't let feedback packets through (limitation in winpcap?) */ + if(!memcmp(src, netif->hwaddr, ETH_HWADDR_LEN)) { + return 1; + } + } + return 0; +} +#endif /* PCAPIF_RECEIVE_PROMISCUOUS */ + +#if PCAPIF_RX_REF +struct pcapif_pbuf_custom +{ + struct pbuf_custom pc; + struct pbuf* p; +}; +#endif /* PCAPIF_RX_REF */ + +/* Forward declarations. */ +static void pcapif_input(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *packet); + +#ifdef PACKET_LIB_GET_ADAPTER_NETADDRESS +/** Get the index of an adapter by its network address + * + * @param netaddr network address of the adapter (e.g. 192.168.1.0) + * @return index of the adapter or negative on error + */ +static int +get_adapter_index_from_addr(struct in_addr *netaddr, char *guid, size_t guid_len) +{ + pcap_if_t *alldevs; + pcap_if_t *d; + char errbuf[PCAP_ERRBUF_SIZE+1]; + int index = 0; + + memset(guid, 0, guid_len); + + /* Retrieve the interfaces list */ + if (pcap_findalldevs(&alldevs, errbuf) == -1) { + printf("Error in pcap_findalldevs: %s\n", errbuf); + return -1; + } + /* Scan the list printing every entry */ + for (d = alldevs; d != NULL; d = d->next, index++) { + pcap_addr_t *a; + for(a = d->addresses; a != NULL; a = a->next) { + if (a->addr->sa_family == AF_INET) { + ULONG a_addr = ((struct sockaddr_in *)a->addr)->sin_addr.s_addr; + ULONG a_netmask = ((struct sockaddr_in *)a->netmask)->sin_addr.s_addr; + ULONG a_netaddr = a_addr & a_netmask; + ULONG addr = (*netaddr).s_addr; + if (a_netaddr == addr) { + int ret = -1; + char name[128]; + char *start, *end; + size_t len = strlen(d->name); + if(len > 127) { + len = 127; + } + MEMCPY(name, d->name, len); + name[len] = 0; + start = strstr(name, "{"); + if (start != NULL) { + end = strstr(start, "}"); + if (end != NULL) { + size_t len = end - start + 1; + MEMCPY(guid, start, len); + ret = index; + } + } + pcap_freealldevs(alldevs); + return ret; + } + } + } + } + printf("Network address not found.\n"); + + pcap_freealldevs(alldevs); + return -1; +} +#endif /* PACKET_LIB_GET_ADAPTER_NETADDRESS */ + +#if defined(PACKET_LIB_GET_ADAPTER_NETADDRESS) || defined(PACKET_LIB_ADAPTER_GUID) +/** Get the index of an adapter by its GUID + * + * @param adapter_guid GUID of the adapter + * @return index of the adapter or negative on error + */ +static int +get_adapter_index(const char* adapter_guid) +{ + pcap_if_t *alldevs; + pcap_if_t *d; + char errbuf[PCAP_ERRBUF_SIZE+1]; + int idx = 0; + + /* Retrieve the interfaces list */ + if (pcap_findalldevs(&alldevs, errbuf) == -1) { + printf("Error in pcap_findalldevs: %s\n", errbuf); + return -1; + } + /* Scan the list and compare name vs. adapter_guid */ + for (d = alldevs; d != NULL; d = d->next, idx++) { + if(strstr(d->name, adapter_guid)) { + pcap_freealldevs(alldevs); + return idx; + } + } + /* not found, dump all adapters */ + printf("%d available adapters:\n", idx); + for (d = alldevs, idx = 0; d != NULL; d = d->next, idx++) { + printf("- %d: %s\n", idx, d->name); + } + pcap_freealldevs(alldevs); + return -1; +} +#endif /* defined(PACKET_LIB_GET_ADAPTER_NETADDRESS) || defined(PACKET_LIB_ADAPTER_GUID) */ + +static pcap_t* +pcapif_open_adapter(const char* adapter_name, char* errbuf) +{ + pcap_t* adapter = pcap_open_live(adapter_name,/* name of the device */ + 65536, /* portion of the packet to capture */ + /* 65536 guarantees that the whole packet will be captured on all the link layers */ + PCAP_OPENFLAG_PROMISCUOUS,/* promiscuous mode */ +#if PCAPIF_RX_USE_THREAD + /*-*/1, /* don't wait at all for lower latency */ +#else + 1, /* wait 1 ms in ethernetif_poll */ +#endif + errbuf); /* error buffer */ + return adapter; +} + +#if !PCAPIF_RX_USE_THREAD +static void +pcap_reopen_adapter(struct pcapif_private *pa) +{ + char errbuf[PCAP_ERRBUF_SIZE+1]; + pcap_if_t *alldevs; + if (pa->adapter != NULL) { + pcap_close(pa->adapter); + pa->adapter = NULL; + } + if (pcap_findalldevs(&alldevs, errbuf) != -1) { + pcap_if_t *d; + for (d = alldevs; d != NULL; d = d->next) { + if (!strcmp(d->name, pa->name)) { + pa->adapter = pcapif_open_adapter(pa->name, errbuf); + if (pa->adapter == NULL) { + printf("failed to reopen pcap adapter after failure: %s\n", errbuf); + } + break; + } + } + pcap_freealldevs(alldevs); + } +} +#endif + +/** + * Open a network adapter and set it up for packet input + * + * @param adapter_num the index of the adapter to use + * @param arg argument to pass to input + * @return an adapter handle on success, NULL on failure + */ +static struct pcapif_private* +pcapif_init_adapter(int adapter_num, void *arg) +{ + int i; + int number_of_adapters; + struct pcapif_private *pa; + char errbuf[PCAP_ERRBUF_SIZE+1]; + + pcap_if_t *alldevs; + pcap_if_t *d; + pcap_if_t *used_adapter = NULL; + + pa = (struct pcapif_private *)malloc(sizeof(struct pcapif_private)); + if (!pa) { + printf("Unable to alloc the adapter!\n"); + return NULL; + } + + memset(pa, 0, sizeof(struct pcapif_private)); + pcapif_init_tx_packets(pa); + pa->input_fn_arg = arg; + + /* Retrieve the interfaces list */ + if (pcap_findalldevs(&alldevs, errbuf) == -1) { + free(pa); + return NULL; /* no adapters found */ + } + /* get number of adapters and adapter pointer */ + for (d = alldevs, number_of_adapters = 0; d != NULL; d = d->next, number_of_adapters++) { + if (number_of_adapters == adapter_num) { + char *desc = d->description; + size_t len; + + len = strlen(d->name); + LWIP_ASSERT("len < ADAPTER_NAME_LEN", len < ADAPTER_NAME_LEN); + strcpy(pa->name, d->name); + + used_adapter = d; + /* format vendor description */ + if (desc != NULL) { + len = strlen(desc); + if (strstr(desc, " ' on local host") != NULL) { + len -= 16; + } + else if (strstr(desc, "' on local host") != NULL) { + len -= 15; + } + if (strstr(desc, "Network adapter '") == desc) { + len -= 17; + desc += 17; + } + len = LWIP_MIN(len, ADAPTER_DESC_LEN-1); + while ((desc[len-1] == ' ') || (desc[len-1] == '\t')) { + /* don't copy trailing whitespace */ + len--; + } + strncpy(pa->description, desc, len); + pa->description[len] = 0; + } else { + strcpy(pa->description, ""); + } + } + } + +#ifndef PCAPIF_LIB_QUIET + /* Scan the list printing every entry */ + for (d = alldevs, i = 0; d != NULL; d = d->next, i++) { + char *desc = d->description; + char descBuf[128]; + size_t len; + const char* devname = d->name; + if (d->name == NULL) { + devname = ""; + } else { + if (strstr(devname, "\\Device\\") == devname) { + /* windows: strip the first part */ + devname += 8; + } + } + printf("%2i: %s\n", i, devname); + if (desc != NULL) { + /* format vendor description */ + len = strlen(desc); + if (strstr(desc, " ' on local host") != NULL) { + len -= 16; + } + else if (strstr(desc, "' on local host") != NULL) { + len -= 15; + } + if (strstr(desc, "Network adapter '") == desc) { + len -= 17; + desc += 17; + } + len = LWIP_MIN(len, 127); + while ((desc[len-1] == ' ') || (desc[len-1] == '\t')) { + /* don't copy trailing whitespace */ + len--; + } + strncpy(descBuf, desc, len); + descBuf[len] = 0; + printf(" Desc: \"%s\"\n", descBuf); + } + } +#endif /* PCAPIF_LIB_QUIET */ + + /* invalid adapter index -> check this after printing the adapters */ + if (adapter_num < 0) { + printf("Invalid adapter_num: %d\n", adapter_num); + free(pa); + pcap_freealldevs(alldevs); + return NULL; + } + /* adapter index out of range */ + if (adapter_num >= number_of_adapters) { + printf("Invalid adapter_num: %d\n", adapter_num); + free(pa); + pcap_freealldevs(alldevs); + return NULL; + } +#ifndef PCAPIF_LIB_QUIET + printf("Using adapter_num: %d\n", adapter_num); +#endif /* PCAPIF_LIB_QUIET */ + /* set up the selected adapter */ + + LWIP_ASSERT("used_adapter != NULL", used_adapter != NULL); + + /* Open the device */ + pa->adapter = pcapif_open_adapter(used_adapter->name, errbuf); + if (pa->adapter == NULL) { + printf("\nUnable to open the adapter. %s is not supported by pcap (\"%s\").\n", used_adapter->name, errbuf); + /* Free the device list */ + pcap_freealldevs(alldevs); + free(pa); + return NULL; + } + printf("Using adapter: \"%s\"\n", pa->description); + pcap_freealldevs(alldevs); + +#if PCAPIF_HANDLE_LINKSTATE + pa->link_state = pcapifh_linkstate_init(pa->name); + pa->last_link_event = PCAPIF_LINKEVENT_UNKNOWN; +#endif /* PCAPIF_HANDLE_LINKSTATE */ + + return pa; +} + +#if PCAPIF_HANDLE_LINKSTATE +static void +pcapif_check_linkstate(void *netif_ptr) +{ + struct netif *netif = (struct netif*)netif_ptr; + struct pcapif_private *pa = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif); + enum pcapifh_link_event le; + + le = pcapifh_linkstate_get(pa->link_state); + + if (pa->last_link_event != le) { + pa->last_link_event = le; + switch (le) { + case PCAPIF_LINKEVENT_UP: { + PCAPIF_NOTIFY_LINKSTATE(netif, netif_set_link_up); + break; + } + case PCAPIF_LINKEVENT_DOWN: { + PCAPIF_NOTIFY_LINKSTATE(netif, netif_set_link_down); + break; + } + case PCAPIF_LINKEVENT_UNKNOWN: /* fall through */ + default: + break; + } + } + sys_timeout(PCAPIF_LINKCHECK_INTERVAL_MS, pcapif_check_linkstate, netif); +} +#endif /* PCAPIF_HANDLE_LINKSTATE */ + + +/** + * Close the adapter (no more packets can be sent or received) + * + * @param netif netif to shutdown + */ +void +pcapif_shutdown(struct netif *netif) +{ + struct pcapif_private *pa = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif); + if (pa) { +#if PCAPIF_RX_USE_THREAD + pa->rx_run = 0; +#endif /* PCAPIF_RX_USE_THREAD */ + if (pa->adapter) { + pcap_breakloop(pa->adapter); + pcap_close(pa->adapter); + } +#if PCAPIF_RX_USE_THREAD + /* wait for rxthread to end */ + while(pa->rx_running); +#endif /* PCAPIF_RX_USE_THREAD */ +#if PCAPIF_HANDLE_LINKSTATE + pcapifh_linkstate_close(pa->link_state); +#endif /* PCAPIF_HANDLE_LINKSTATE */ + free(pa); + } +} + +#if PCAPIF_RX_USE_THREAD +/** RX running in its own thread */ +static void +pcapif_input_thread(void *arg) +{ + struct netif *netif = (struct netif *)arg; + struct pcapif_private *pa = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif); + do + { + struct pcap_pkthdr pkt_header; + const u_char *packet = pcap_next(pa->adapter, &pkt_header); + if(packet != NULL) { + pcapif_input((u_char*)pa, &pkt_header, packet); + } + } while (pa->rx_run); + pa->rx_running = 0; +} +#endif /* PCAPIF_RX_USE_THREAD */ + +/** Low-level initialization: find the correct adapter and initialize it. + */ +static void +pcapif_low_level_init(struct netif *netif) +{ + u8_t my_mac_addr[ETH_HWADDR_LEN] = LWIP_MAC_ADDR_BASE; + int adapter_num = PACKET_LIB_ADAPTER_NR; + struct pcapif_private *pa; +#ifdef PACKET_LIB_GET_ADAPTER_NETADDRESS + ip4_addr_t netaddr; +#define GUID_LEN 128 + char guid[GUID_LEN + 1]; +#endif /* PACKET_LIB_GET_ADAPTER_NETADDRESS */ + + /* If 'state' is != NULL at this point, we assume it is an 'int' giving + the index of the adapter to use (+ 1 because 0==NULL is invalid). + This can be used to instantiate multiple PCAP drivers. */ + if (netif->state != NULL) { + adapter_num = (LWIP_PTR_NUMERIC_CAST(int, netif->state)) - 1; + if (adapter_num < 0) { + printf("ERROR: invalid adapter index \"%d\"!\n", adapter_num); + LWIP_ASSERT("ERROR initializing network adapter!\n", 0); + return; + } + } + +#ifdef PACKET_LIB_GET_ADAPTER_NETADDRESS + memset(&guid, 0, sizeof(guid)); + PACKET_LIB_GET_ADAPTER_NETADDRESS(&netaddr); + if (get_adapter_index_from_addr((struct in_addr *)&netaddr, guid, GUID_LEN) < 0) { + printf("ERROR initializing network adapter, failed to get GUID for network address %s\n", ip4addr_ntoa(&netaddr)); + LWIP_ASSERT("ERROR initializing network adapter, failed to get GUID for network address!", 0); + return; + } + adapter_num = get_adapter_index(guid); + if (adapter_num < 0) { + printf("ERROR finding network adapter with GUID \"%s\"!\n", guid); + LWIP_ASSERT("ERROR finding network adapter with expected GUID!", 0); + return; + } + +#else /* PACKET_LIB_GET_ADAPTER_NETADDRESS */ +#ifdef PACKET_LIB_ADAPTER_GUID + /* get adapter index for guid string */ + adapter_num = get_adapter_index(PACKET_LIB_ADAPTER_GUID); + if (adapter_num < 0) { + printf("ERROR finding network adapter with GUID \"%s\"!\n", PACKET_LIB_ADAPTER_GUID); + LWIP_ASSERT("ERROR initializing network adapter!\n", 0); + return; + } +#endif /* PACKET_LIB_ADAPTER_GUID */ +#endif /* PACKET_LIB_GET_ADAPTER_NETADDRESS */ + + /* Do whatever else is needed to initialize interface. */ + pa = pcapif_init_adapter(adapter_num, netif); + if (pa == NULL) { + printf("ERROR initializing network adapter %d!\n", adapter_num); + LWIP_ASSERT("ERROR initializing network adapter!", 0); + return; + } + netif->state = pa; + + /* change the MAC address to a unique value + so that multiple ethernetifs are supported */ + /* @todo: this does NOT support multiple processes using this adapter! */ + my_mac_addr[ETH_HWADDR_LEN - 1] += netif->num; + /* Copy MAC addr */ + SMEMCPY(&netif->hwaddr, my_mac_addr, ETH_HWADDR_LEN); + + /* get the initial link state of the selected interface */ +#if PCAPIF_HANDLE_LINKSTATE + pa->last_link_event = pcapifh_linkstate_get(pa->link_state); + if (pa->last_link_event == PCAPIF_LINKEVENT_DOWN) { + netif_set_link_down(netif); + } else { + netif_set_link_up(netif); + } + sys_timeout(PCAPIF_LINKCHECK_INTERVAL_MS, pcapif_check_linkstate, netif); +#endif /* PCAPIF_HANDLE_LINKSTATE */ + +#if PCAPIF_RX_USE_THREAD + pa->rx_run = 1; + pa->rx_running = 1; + sys_thread_new("pcapif_rxthread", pcapif_input_thread, netif, 0, 0); +#endif + + LWIP_DEBUGF(NETIF_DEBUG, ("pcapif: eth_addr %02X%02X%02X%02X%02X%02X\n",netif->hwaddr[0],netif->hwaddr[1],netif->hwaddr[2],netif->hwaddr[3],netif->hwaddr[4],netif->hwaddr[5])); +} + +/** low_level_output(): + * Transmit a packet. The packet is contained in the pbuf that is passed to + * the function. This pbuf might be chained. + */ +static err_t +pcapif_low_level_output(struct netif *netif, struct pbuf *p) +{ + struct pbuf *q; + unsigned char buffer[ETH_MAX_FRAME_LEN + ETH_PAD_SIZE]; + unsigned char *buf = buffer; + unsigned char *ptr; + struct eth_hdr *ethhdr; + u16_t tot_len = p->tot_len - ETH_PAD_SIZE; + struct pcapif_private *pa = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif); + +#if defined(LWIP_DEBUG) && LWIP_NETIF_TX_SINGLE_PBUF && !(LWIP_IPV4 && IP_FRAG) && (LWIP_IPV6 && LWIP_IPV6_FRAG) + LWIP_ASSERT("p->next == NULL && p->len == p->tot_len", p->next == NULL && p->len == p->tot_len); +#endif + + /* initiate transfer */ + if ((p->len == p->tot_len) && (p->len >= ETH_MIN_FRAME_LEN + ETH_PAD_SIZE)) { + /* no pbuf chain, don't have to copy -> faster */ + buf = &((unsigned char*)p->payload)[ETH_PAD_SIZE]; + } else { + /* pbuf chain, copy into contiguous buffer */ + if (p->tot_len >= sizeof(buffer)) { + LINK_STATS_INC(link.lenerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + return ERR_BUF; + } + ptr = buffer; + for(q = p; q != NULL; q = q->next) { + /* Send the data from the pbuf to the interface, one pbuf at a + time. The size of the data in each pbuf is kept in the ->len + variable. */ + /* send data from(q->payload, q->len); */ + LWIP_DEBUGF(NETIF_DEBUG, ("netif: send ptr %p q->payload %p q->len %i q->next %p\n", ptr, q->payload, (int)q->len, (void*)q->next)); + if (q == p) { + MEMCPY(ptr, &((char*)q->payload)[ETH_PAD_SIZE], q->len - ETH_PAD_SIZE); + ptr += q->len - ETH_PAD_SIZE; + } else { + MEMCPY(ptr, q->payload, q->len); + ptr += q->len; + } + } + } + + if (tot_len < ETH_MIN_FRAME_LEN) { + /* ensure minimal frame length */ + memset(&buf[tot_len], 0, ETH_MIN_FRAME_LEN - tot_len); + tot_len = ETH_MIN_FRAME_LEN; + } + + /* signal that packet should be sent */ + if (pcap_sendpacket(pa->adapter, buf, tot_len) < 0) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + return ERR_BUF; + } + if (netif_is_link_up(netif)) { + pcapif_add_tx_packet(pa, buf, tot_len); + } + + LINK_STATS_INC(link.xmit); + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, tot_len); + ethhdr = (struct eth_hdr *)p->payload; + if ((ethhdr->dest.addr[0] & 1) != 0) { + /* broadcast or multicast packet*/ + MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); + } else { + /* unicast packet */ + MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); + } + return ERR_OK; +} + +/** low_level_input(): Allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + */ +static struct pbuf * +pcapif_low_level_input(struct netif *netif, const void *packet, int packet_len) +{ + struct pbuf *p, *q; + int start; + int length = packet_len; + const struct eth_addr *dest = (const struct eth_addr*)packet; + int unicast; +#if PCAPIF_FILTER_GROUP_ADDRESSES && !PCAPIF_RECEIVE_PROMISCUOUS + const u8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + const u8_t ipv4mcast[] = {0x01, 0x00, 0x5e}; + const u8_t ipv6mcast[] = {0x33, 0x33}; +#endif /* PCAPIF_FILTER_GROUP_ADDRESSES && !PCAPIF_RECEIVE_PROMISCUOUS */ + + if (pcaipf_is_tx_packet(netif, packet, packet_len)) { + /* don't update counters here! */ + return NULL; + } + + unicast = ((dest->addr[0] & 0x01) == 0); +#if !PCAPIF_RECEIVE_PROMISCUOUS + /* MAC filter: only let my MAC or non-unicast through (pcap receives loopback traffic, too) */ + if (memcmp(dest, &netif->hwaddr, ETH_HWADDR_LEN) && +#if PCAPIF_FILTER_GROUP_ADDRESSES + (memcmp(dest, ipv4mcast, 3) || ((dest->addr[3] & 0x80) != 0)) && + memcmp(dest, ipv6mcast, 2) && + memcmp(dest, bcast, 6) +#else /* PCAPIF_FILTER_GROUP_ADDRESSES */ + unicast +#endif /* PCAPIF_FILTER_GROUP_ADDRESSES */ + ) { + /* don't update counters here! */ + return NULL; + } +#endif /* !PCAPIF_RECEIVE_PROMISCUOUS */ + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, (u16_t)length + ETH_PAD_SIZE, PBUF_POOL); + LWIP_DEBUGF(NETIF_DEBUG, ("netif: recv length %i p->tot_len %i\n", length, (int)p->tot_len)); + + if (p != NULL) { + /* We iterate over the pbuf chain until we have read the entire + packet into the pbuf. */ + start = 0; + for (q = p; q != NULL; q = q->next) { + u16_t copy_len = q->len; + /* Read enough bytes to fill this pbuf in the chain. The + available data in the pbuf is given by the q->len + variable. */ + /* read data into(q->payload, q->len); */ + LWIP_DEBUGF(NETIF_DEBUG, ("netif: recv start %i length %i q->payload %p q->len %i q->next %p\n", start, length, q->payload, (int)q->len, (void*)q->next)); + if (q == p) { +#if ETH_PAD_SIZE + LWIP_ASSERT("q->len >= ETH_PAD_SIZE", q->len >= ETH_PAD_SIZE); + copy_len -= ETH_PAD_SIZE; +#endif /* ETH_PAD_SIZE*/ + MEMCPY(&((char*)q->payload)[ETH_PAD_SIZE], &((const char*)packet)[start], copy_len); + } else { + MEMCPY(q->payload, &((const char*)packet)[start], copy_len); + } + start += copy_len; + length -= copy_len; + if (length <= 0) { + break; + } + } + LINK_STATS_INC(link.recv); + MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len - ETH_PAD_SIZE); + if (unicast) { + MIB2_STATS_NETIF_INC(netif, ifinucastpkts); + } else { + MIB2_STATS_NETIF_INC(netif, ifinnucastpkts); + } + } else { + /* drop packet */ + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + MIB2_STATS_NETIF_INC(netif, ifindiscards); + } + + return p; +} + +#if PCAPIF_RX_REF +static void +pcapif_rx_pbuf_free_custom(struct pbuf *p) +{ + struct pcapif_pbuf_custom* ppc; + LWIP_ASSERT("NULL pointer", p != NULL); + ppc = (struct pcapif_pbuf_custom*)p; + LWIP_ASSERT("NULL pointer", ppc->p != NULL); + pbuf_free(ppc->p); + ppc->p = NULL; + mem_free(p); +} + +static struct pbuf* +pcapif_rx_ref(struct pbuf* p) +{ + struct pcapif_pbuf_custom* ppc; + struct pbuf* q; + + LWIP_ASSERT("NULL pointer", p != NULL); + LWIP_ASSERT("chained pbuf not supported here", p->next == NULL); + + ppc = (struct pcapif_pbuf_custom*)mem_malloc(sizeof(struct pcapif_pbuf_custom)); + LWIP_ASSERT("out of memory for RX", ppc != NULL); + ppc->pc.custom_free_function = pcapif_rx_pbuf_free_custom; + ppc->p = p; + + q = pbuf_alloced_custom(PBUF_RAW, p->tot_len, PBUF_REF, &ppc->pc, p->payload, p->tot_len); + LWIP_ASSERT("pbuf_alloced_custom returned NULL", q != NULL); + return q; +} +#endif /* PCAPIF_RX_REF */ + +/** pcapif_input: This function is called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that should + * handle the actual reception of bytes from the network interface. + */ +static void +pcapif_input(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *packet) +{ + struct pcapif_private *pa = (struct pcapif_private*)user; + int packet_len = pkt_header->caplen; + struct netif *netif = (struct netif *)pa->input_fn_arg; + struct pbuf *p; + + PCAPIF_RX_LOCK_LWIP(); + + /* move received packet into a new pbuf */ + p = pcapif_low_level_input(netif, packet, packet_len); + /* if no packet could be read, silently ignore this */ + if (p != NULL) { +#if PCAPIF_RX_REF + p = pcapif_rx_ref(p); +#endif + /* pass all packets to ethernet_input, which decides what packets it supports */ + if (netif->input(p, netif) != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + } + } + PCAPIF_RX_UNLOCK_LWIP(); +} + +/** + * pcapif_init(): initialization function, pass to netif_add(). + */ +err_t +pcapif_init(struct netif *netif) +{ + static int ethernetif_index; + + int local_index; + SYS_ARCH_DECL_PROTECT(lev); + SYS_ARCH_PROTECT(lev); + local_index = ethernetif_index++; + SYS_ARCH_UNPROTECT(lev); + + netif->name[0] = IFNAME0; + netif->name[1] = (char)(IFNAME1 + local_index); + netif->linkoutput = pcapif_low_level_output; +#if LWIP_IPV4 +#if LWIP_ARP + netif->output = etharp_output; +#else /* LWIP_ARP */ + netif->output = NULL; /* not used for PPPoE */ +#endif /* LWIP_ARP */ +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif /* LWIP_IPV6 */ +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif_set_hostname(netif, "lwip"); +#endif /* LWIP_NETIF_HOSTNAME */ + + netif->mtu = 1500; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP; + netif->hwaddr_len = ETH_HWADDR_LEN; + + NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000); + + /* sets link up or down based on current status */ + pcapif_low_level_init(netif); + + return ERR_OK; +} + +#if !PCAPIF_RX_USE_THREAD +void +pcapif_poll(struct netif *netif) +{ + struct pcapif_private *pa = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif); + + int ret; + do { + if (pa->adapter != NULL) { + ret = pcap_dispatch(pa->adapter, -1, pcapif_input, (u_char*)pa); + } else { + ret = -1; + } + if (ret < 0) { + /* error (e.g. adapter removed or resume from standby), try to reopen the adapter */ + pcap_reopen_adapter(pa); + } + } while (ret > 0); + +} +#endif /* !PCAPIF_RX_USE_THREAD */ + +#endif /* LWIP_ETHERNET */ diff --git a/ext/lwip-contrib/ports/win32/pcapif.h b/ext/lwip-contrib/ports/win32/pcapif.h new file mode 100644 index 0000000..8d67ea4 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/pcapif.h @@ -0,0 +1,32 @@ +#ifndef LWIP_PCAPIF_H +#define LWIP_PCAPIF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lwip/err.h" + +/** Set to 1 to let rx use an own thread (only for NO_SYS==0). + * If set to 0, ethernetif_poll is used to poll for packets. + */ +#ifndef PCAPIF_RX_USE_THREAD +#define PCAPIF_RX_USE_THREAD !NO_SYS +#endif +#if PCAPIF_RX_USE_THREAD && NO_SYS +#error "Can't create a dedicated RX thread with NO_SYS==1" +#endif + +struct netif; + +err_t pcapif_init (struct netif *netif); +void pcapif_shutdown(struct netif *netif); +#if !PCAPIF_RX_USE_THREAD +void pcapif_poll (struct netif *netif); +#endif /* !PCAPIF_RX_USE_THREAD */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_PCAPIF_H */ diff --git a/ext/lwip-contrib/ports/win32/pcapif_helper.c b/ext/lwip-contrib/ports/win32/pcapif_helper.c new file mode 100644 index 0000000..de5147f --- /dev/null +++ b/ext/lwip-contrib/ports/win32/pcapif_helper.c @@ -0,0 +1,105 @@ +/** + * pcapif_helper.c - This file is part of lwIP pcapif and provides helper functions + * for managing the link state. + */ + +#include "pcapif_helper.h" + +#include +#include + +#include "lwip/arch.h" + +#ifdef WIN32 + +#define WIN32_LEAN_AND_MEAN + +#ifdef _MSC_VER +#pragma warning( push, 3 ) +#endif +#include +#include +#include +#ifdef _MSC_VER +#pragma warning ( pop ) +#endif + +struct pcapifh_linkstate { + LPADAPTER lpAdapter; + PPACKET_OID_DATA ppacket_oid_data; +}; + +struct pcapifh_linkstate* pcapifh_linkstate_init(char *adapter_name) +{ + struct pcapifh_linkstate* state = (struct pcapifh_linkstate*)malloc(sizeof(struct pcapifh_linkstate)); + if (state != NULL) { + memset(state, 0, sizeof(struct pcapifh_linkstate)); + state->ppacket_oid_data = (PPACKET_OID_DATA)malloc(sizeof(PACKET_OID_DATA) + sizeof(NDIS_MEDIA_STATE)); + if (state->ppacket_oid_data == NULL) { + free(state); + state = NULL; + } else { + state->lpAdapter = PacketOpenAdapter((char*)adapter_name); + if ((state->lpAdapter == NULL) || (state->lpAdapter->hFile == INVALID_HANDLE_VALUE)) { + /* failed to open adapter */ + free(state); + state = NULL; + } + } + } + return state; +} + +enum pcapifh_link_event pcapifh_linkstate_get(struct pcapifh_linkstate* state) +{ + enum pcapifh_link_event ret = PCAPIF_LINKEVENT_UNKNOWN; + if (state != NULL) { + state->ppacket_oid_data->Oid = OID_GEN_MEDIA_CONNECT_STATUS; + state->ppacket_oid_data->Length = sizeof(NDIS_MEDIA_STATE); + if (PacketRequest(state->lpAdapter, FALSE, state->ppacket_oid_data)) { + NDIS_MEDIA_STATE fNdisMediaState; + fNdisMediaState = (*((PNDIS_MEDIA_STATE)(state->ppacket_oid_data->Data))); + ret = ((fNdisMediaState == NdisMediaStateConnected) ? PCAPIF_LINKEVENT_UP : PCAPIF_LINKEVENT_DOWN); + } + } + return ret; +} + +void pcapifh_linkstate_close(struct pcapifh_linkstate* state) +{ + if (state != NULL) { + if (state->lpAdapter != NULL) { + PacketCloseAdapter(state->lpAdapter); + } + if (state->ppacket_oid_data != NULL) { + free(state->ppacket_oid_data); + } + free(state); + } +} + +#else /* WIN32 */ + +/* @todo: add linux/unix implementation? */ + +struct pcapifh_linkstate { + u8_t empty; +}; + +struct pcapifh_linkstate* pcapifh_linkstate_init(char *adapter_name) +{ + LWIP_UNUSED_ARG(adapter_name); + return NULL; +} + +enum pcapifh_link_event pcapifh_linkstate_get(struct pcapifh_linkstate* state) +{ + LWIP_UNUSED_ARG(state); + return PCAPIF_LINKEVENT_UP; +} +void pcapifh_linkstate_close(struct pcapifh_linkstate* state) +{ + LWIP_UNUSED_ARG(state); +} + +#endif /* WIN32 */ \ No newline at end of file diff --git a/ext/lwip-contrib/ports/win32/pcapif_helper.h b/ext/lwip-contrib/ports/win32/pcapif_helper.h new file mode 100644 index 0000000..da08854 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/pcapif_helper.h @@ -0,0 +1,25 @@ +#ifndef LWIP_PCAPIF_HELPER_H +#define LWIP_PCAPIF_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct pcapifh_linkstate; + +enum pcapifh_link_event { + PCAPIF_LINKEVENT_UNKNOWN, + PCAPIF_LINKEVENT_UP, + PCAPIF_LINKEVENT_DOWN +}; + +struct pcapifh_linkstate* pcapifh_linkstate_init(char *adapter_name); +enum pcapifh_link_event pcapifh_linkstate_get(struct pcapifh_linkstate* state); +void pcapifh_linkstate_close(struct pcapifh_linkstate* state); + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_PCAPIF_HELPER_H */ \ No newline at end of file diff --git a/ext/lwip-contrib/ports/win32/readme.txt b/ext/lwip-contrib/ports/win32/readme.txt new file mode 100644 index 0000000..061d468 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/readme.txt @@ -0,0 +1,24 @@ +lwIP for Win32 + +This is an example port of lwIP for Win32. It uses WinPCAP to send & receive packets. +To compile it, use the MSVC projects in the 'msvc' subdir or the Makefile in the 'mingw' subdir. + +For both compilers: +- the lwIP core repository must be in a folder "lwip" next to the "contrib" folder +- you have to set an environment variable PCAP_DIR pointing to the WinPcap Developer's + Pack (containing 'include' and 'lib') + +You also will have to copy the file 'lwipcfg_msvc.h.example' to +'lwipcfg_msvc.h' and modify to suit your needs (WinPcap adapter number, +IP configuration, applications...). + +Included in the contrib\ports\win32 directory is the network interface driver +using the winpcap library. + +lwIP: http://savannah.nongnu.org/projects/lwip/ +WinPCap: https://www.winpcap.org/devel.htm +Visual C++: http://www.microsoft.com/express/download/ + +To compile the unittests (msvc\lwIP_unittests.sln), download check (tested with v0.11.0) from +https://github.com/libcheck/check/releases/ +and place it in a folder "check" next to the "contrib" folder. diff --git a/ext/lwip-contrib/ports/win32/sio.c b/ext/lwip-contrib/ports/win32/sio.c new file mode 100644 index 0000000..6fed932 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/sio.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#include +#include +#include + +#include +#include + +#ifdef _MSC_VER +#pragma warning (push, 3) +#endif +#include +#ifdef _MSC_VER +#pragma warning (pop) +#endif +#include "lwipcfg_msvc.h" + +/** When 1, use COM ports, when 0, use named pipes (for simulation). */ +#ifndef SIO_USE_COMPORT +#define SIO_USE_COMPORT 1 +#endif + +/** If SIO_USE_COMPORT==1, use COMx, if 0, use a pipe (default) */ +#if SIO_USE_COMPORT +#define SIO_DEVICENAME "\\\\.\\COM" +#else +#define SIO_DEVICENAME "\\\\.\\pipe\\lwip" +#endif + +#if SIO_USE_COMPORT +#ifndef SIO_COMPORT_SPEED +#define SIO_COMPORT_SPEED 115200 +#endif +#ifndef SIO_COMPORT_BYTESIZE +#define SIO_COMPORT_BYTESIZE 8 +#endif +#ifndef SIO_COMPORT_STOPBITS +#define SIO_COMPORT_STOPBITS 0 /* ONESTOPBIT */ +#endif +#ifndef SIO_COMPORT_PARITY +#define SIO_COMPORT_PARITY 0 /* NOPARITY */ +#endif +#endif /* SIO_USE_COMPORT */ + +static int sio_abort = 0; + +/* \\.\pipe\lwip0 */ +/* pppd /dev/ttyS0 logfile mylog debug nocrtscts local noauth noccp ms-dns 212.27.54.252 192.168.0.4:192.168.0.5 + */ + +/** + * SIO_DEBUG: Enable debugging for SIO. + */ +#ifndef SIO_DEBUG +#define SIO_DEBUG LWIP_DBG_OFF +#endif + +#if SIO_USE_COMPORT +/** When using a real COM port, set up the + * serial line settings (baudrate etc.) + */ +static BOOL +sio_setup(HANDLE fd) +{ + COMMTIMEOUTS cto; + DCB dcb; + + /* set up baudrate and other communication settings */ + memset(&dcb, 0, sizeof(dcb)); + /* Obtain the DCB structure for the device */ + if (!GetCommState(fd, &dcb)) { + return FALSE; + } + /* Set the new data */ + dcb.BaudRate = SIO_COMPORT_SPEED; + dcb.ByteSize = SIO_COMPORT_BYTESIZE; + dcb.StopBits = 0; /* ONESTOPBIT */ + dcb.Parity = 0; /* NOPARITY */ + dcb.fParity = 0; /* parity is not used */ + /* do not use flow control */ + /*dcb.fOutxDsrFlow = dcb.fDtrControl = 0; + dcb.fOutxCtsFlow = dcb.fRtsControl = 0; + dcb.fErrorChar = dcb.fNull = 0; + dcb.fInX = dcb.fOutX = 0; + dcb.XonChar = dcb.XoffChar = 0; + dcb.XonLim = dcb.XoffLim = 100;*/ + + /* Set the new DCB structure */ + if (!SetCommState(fd, &dcb)) { + return FALSE; + } + + memset(&cto, 0, sizeof(cto)); + if(!GetCommTimeouts(fd, &cto)) + { + return FALSE; + } + /* change read timeout, leave write timeout as it is */ + cto.ReadIntervalTimeout = 1; + cto.ReadTotalTimeoutMultiplier = 0; + cto.ReadTotalTimeoutConstant = 1; /* 1 ms */ + if(!SetCommTimeouts(fd, &cto)) { + return FALSE; + } + + return TRUE; +} +#endif /* SIO_USE_COMPORT */ + +/** + * Opens a serial device for communication. + * + * @param devnum device number + * @return handle to serial device if successful, NULL otherwise + */ +sio_fd_t sio_open(u8_t devnum) +{ + HANDLE fileHandle = INVALID_HANDLE_VALUE; + CHAR fileName[256]; + LWIP_DEBUGF(SIO_DEBUG, ("sio_open(%lu)\n", (DWORD)devnum)); +#if SIO_USE_COMPORT + _snprintf(fileName, 255, SIO_DEVICENAME"%lu", (DWORD)(devnum)); +#else /* SIO_USE_COMPORT */ + _snprintf(fileName, 255, SIO_DEVICENAME"%lu", (DWORD)(devnum & ~1)); + if ((devnum & 1) == 0) { + fileHandle = CreateNamedPipeA(fileName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_NOWAIT, + PIPE_UNLIMITED_INSTANCES, 102400, 102400, 100, NULL); + } else +#endif /* SIO_USE_COMPORT */ + { + fileHandle = CreateFileA(fileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + } + if (fileHandle != INVALID_HANDLE_VALUE) { + sio_abort = 0; +#if !SIO_USE_COMPORT + if (devnum & 1) { + DWORD mode = PIPE_NOWAIT; + if (!SetNamedPipeHandleState(fileHandle, &mode, NULL, NULL)) { + LWIP_DEBUGF(SIO_DEBUG, ("sio_open(%lu): SetNamedPipeHandleState failed. GetLastError() returns %d\n", + (DWORD)devnum, GetLastError())); + } + } else +#endif /* !SIO_USE_COMPORT */ + { + FlushFileBuffers(fileHandle); + } +#if SIO_USE_COMPORT + if(!sio_setup(fileHandle)) { + CloseHandle(fileHandle); + LWIP_DEBUGF(SIO_DEBUG, ("sio_open(%lu): sio_setup failed. GetLastError() returns %lu\n", + (DWORD)devnum, GetLastError())); + return NULL; + } +#endif /* SIO_USE_COMPORT */ + LWIP_DEBUGF(SIO_DEBUG, ("sio_open: file \"%s\" successfully opened.\n", fileName)); + printf("sio_open: file \"%s\" (%d) successfully opened: 0x%08x\n", fileName, devnum, LWIP_PTR_NUMERIC_CAST(unsigned int, fileHandle)); + return (sio_fd_t)(fileHandle); + } + LWIP_DEBUGF(SIO_DEBUG, ("sio_open(%lu) failed. GetLastError() returns %lu\n", + (DWORD)devnum, GetLastError())); + printf("sio_open(%lu) failed. GetLastError() returns %lu\n", + (DWORD)devnum, GetLastError()); + return NULL; +} + +/** + * Sends a single character to the serial device. + * + * @param c character to send + * @param fd serial device handle + * + * @note This function will block until the character can be sent. + */ +void sio_send(u8_t c, sio_fd_t fd) +{ + DWORD dwNbBytesWritten = 0; + LWIP_DEBUGF(SIO_DEBUG, ("sio_send(%lu)\n", (DWORD)c)); + while ((!WriteFile((HANDLE)(fd), &c, 1, &dwNbBytesWritten, NULL)) || (dwNbBytesWritten < 1)) { + } +} + +/** + * Receives a single character from the serial device. + * + * @param fd serial device handle + * + * @note This function will block until a character is received. + */ +u8_t sio_recv(sio_fd_t fd) +{ + DWORD dwNbBytesReadden = 0; + u8_t byte = 0; + LWIP_DEBUGF(SIO_DEBUG, ("sio_recv()\n")); + while ((sio_abort == 0) && ((!ReadFile((HANDLE)(fd), &byte, 1, &dwNbBytesReadden, NULL)) || (dwNbBytesReadden < 1))); + LWIP_DEBUGF(SIO_DEBUG, ("sio_recv()=%lu\n", (DWORD)byte)); + return byte; +} + +/** + * Reads from the serial device. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received - may be 0 if aborted by sio_read_abort + * + * @note This function will block until data can be received. The blocking + * can be cancelled by calling sio_read_abort(). + */ +u32_t sio_read(sio_fd_t fd, u8_t* data, u32_t len) +{ + BOOL ret; + DWORD dwNbBytesReadden = 0; + LWIP_DEBUGF(SIO_DEBUG, ("sio_read()...\n")); + ret = ReadFile((HANDLE)(fd), data, len, &dwNbBytesReadden, NULL); + LWIP_DEBUGF(SIO_DEBUG, ("sio_read()=%lu bytes -> %d\n", dwNbBytesReadden, ret)); + LWIP_UNUSED_ARG(ret); + return dwNbBytesReadden; +} + +/** + * Tries to read from the serial device. Same as sio_read but returns + * immediately if no data is available and never blocks. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received + */ +u32_t sio_tryread(sio_fd_t fd, u8_t* data, u32_t len) +{ + /* @todo: implement non-blocking read */ + BOOL ret; + DWORD dwNbBytesReadden = 0; + LWIP_DEBUGF(SIO_DEBUG, ("sio_read()...\n")); + ret = ReadFile((HANDLE)(fd), data, len, &dwNbBytesReadden, NULL); + LWIP_DEBUGF(SIO_DEBUG, ("sio_read()=%lu bytes -> %d\n", dwNbBytesReadden, ret)); + LWIP_UNUSED_ARG(ret); + return dwNbBytesReadden; +} + +/** + * Writes to the serial device. + * + * @param fd serial device handle + * @param data pointer to data to send + * @param len length (in bytes) of data to send + * @return number of bytes actually sent + * + * @note This function will block until all data can be sent. + */ +u32_t sio_write(sio_fd_t fd, u8_t* data, u32_t len) +{ + BOOL ret; + DWORD dwNbBytesWritten = 0; + LWIP_DEBUGF(SIO_DEBUG, ("sio_write()...\n")); + ret = WriteFile((HANDLE)(fd), data, len, &dwNbBytesWritten, NULL); + LWIP_DEBUGF(SIO_DEBUG, ("sio_write()=%lu bytes -> %d\n", dwNbBytesWritten, ret)); + LWIP_UNUSED_ARG(ret); + return dwNbBytesWritten; +} + +/** + * Aborts a blocking sio_read() call. + * @todo: This currently ignores fd and aborts all reads + * + * @param fd serial device handle + */ +void sio_read_abort(sio_fd_t fd) +{ + LWIP_UNUSED_ARG(fd); + LWIP_DEBUGF(SIO_DEBUG, ("sio_read_abort() !!!!!...\n")); + sio_abort = 1; + return; +} diff --git a/ext/lwip-contrib/ports/win32/sys_arch.c b/ext/lwip-contrib/ports/win32/sys_arch.c new file mode 100644 index 0000000..97ee665 --- /dev/null +++ b/ext/lwip-contrib/ports/win32/sys_arch.c @@ -0,0 +1,612 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * 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. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include +#include /* sprintf() for task names */ + +#ifdef _MSC_VER +#pragma warning (push, 3) +#endif +#include +#ifdef _MSC_VER +#pragma warning (pop) +#endif +#include + +#include +#include +#include +#include +#include + +/* These functions are used from NO_SYS also, for precise timer triggering */ +LARGE_INTEGER freq, sys_start_time; +#define SYS_INITIALIZED() (freq.QuadPart != 0) + +DWORD netconn_sem_tls_index; + +HCRYPTPROV hcrypt; +u32_t sys_win_rand(void) +{ + u32_t ret; + if (CryptGenRandom(hcrypt, sizeof(ret), (BYTE*)&ret)) { + return ret; + } + LWIP_ASSERT("CryptGenRandom failed", 0); + return 0; +} + +static void sys_win_rand_init(void) +{ + if(!CryptAcquireContext(&hcrypt, NULL, NULL, PROV_RSA_FULL, 0)) { + DWORD err = GetLastError(); + LWIP_PLATFORM_DIAG(("CryptAcquireContext failed with error %d, trying to create NEWKEYSET", (int)err)); + if(!CryptAcquireContext(&hcrypt, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { + err = GetLastError(); + char errbuf[128]; + snprintf(errbuf, sizeof(errbuf), "CryptAcquireContext failed with error %d", (int)err); + LWIP_UNUSED_ARG(err); + LWIP_ASSERT(errbuf, 0); + } + } +} + +static void sys_init_timing(void) +{ + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&sys_start_time); +} + +static LONGLONG sys_get_ms_longlong(void) +{ + LONGLONG ret; + LARGE_INTEGER now; +#if NO_SYS + if (!SYS_INITIALIZED()) { + sys_init(); + LWIP_ASSERT("initialization failed", SYS_INITIALIZED()); + } +#endif /* NO_SYS */ + QueryPerformanceCounter(&now); + ret = now.QuadPart-sys_start_time.QuadPart; + return (u32_t)(((ret)*1000)/freq.QuadPart); +} + +u32_t sys_jiffies(void) +{ + return (u32_t)sys_get_ms_longlong(); +} + +u32_t sys_now(void) +{ + return (u32_t)sys_get_ms_longlong(); +} + +CRITICAL_SECTION critSec; + +static void InitSysArchProtect(void) +{ + InitializeCriticalSection(&critSec); +} + +sys_prot_t sys_arch_protect(void) +{ +#if NO_SYS + if (!SYS_INITIALIZED()) { + sys_init(); + LWIP_ASSERT("initialization failed", SYS_INITIALIZED()); + } +#endif + EnterCriticalSection(&critSec); + return 0; +} + +void sys_arch_unprotect(sys_prot_t pval) +{ + LWIP_UNUSED_ARG(pval); + LeaveCriticalSection(&critSec); +} + +static void msvc_sys_init(void) +{ + sys_win_rand_init(); + sys_init_timing(); + InitSysArchProtect(); + netconn_sem_tls_index = TlsAlloc(); + LWIP_ASSERT("TlsAlloc failed", netconn_sem_tls_index != TLS_OUT_OF_INDEXES); +} + +void sys_init(void) +{ + msvc_sys_init(); +} + +#if !NO_SYS + +struct threadlist { + lwip_thread_fn function; + void *arg; + DWORD id; + struct threadlist *next; +}; + +struct threadlist *lwip_win32_threads = NULL; + +err_t sys_sem_new(sys_sem_t *sem, u8_t count) +{ + HANDLE new_sem = NULL; + + LWIP_ASSERT("sem != NULL", sem != NULL); + + new_sem = CreateSemaphore(0, count, 100000, 0); + LWIP_ASSERT("Error creating semaphore", new_sem != NULL); + if(new_sem != NULL) { + SYS_STATS_INC_USED(sem); +#if LWIP_STATS && SYS_STATS + LWIP_ASSERT("sys_sem_new() counter overflow", lwip_stats.sys.sem.used != 0 ); +#endif /* LWIP_STATS && SYS_STATS*/ + sem->sem = new_sem; + return ERR_OK; + } + + /* failed to allocate memory... */ + SYS_STATS_INC(sem.err); + sem->sem = NULL; + return ERR_MEM; +} + +void sys_sem_free(sys_sem_t *sem) +{ + /* parameter check */ + LWIP_ASSERT("sem != NULL", sem != NULL); + LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL); + LWIP_ASSERT("sem->sem != INVALID_HANDLE_VALUE", sem->sem != INVALID_HANDLE_VALUE); + CloseHandle(sem->sem); + + SYS_STATS_DEC(sem.used); +#if LWIP_STATS && SYS_STATS + LWIP_ASSERT("sys_sem_free() closed more than created", lwip_stats.sys.sem.used != (u16_t)-1); +#endif /* LWIP_STATS && SYS_STATS */ + sem->sem = NULL; +} + +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{ + DWORD ret; + LONGLONG starttime, endtime; + LWIP_ASSERT("sem != NULL", sem != NULL); + LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL); + LWIP_ASSERT("sem->sem != INVALID_HANDLE_VALUE", sem->sem != INVALID_HANDLE_VALUE); + if(!timeout) + { + /* wait infinite */ + starttime = sys_get_ms_longlong(); + ret = WaitForSingleObject(sem->sem, INFINITE); + LWIP_ASSERT("Error waiting for semaphore", ret == WAIT_OBJECT_0); + endtime = sys_get_ms_longlong(); + /* return the time we waited for the sem */ + return (u32_t)(endtime - starttime); + } + else + { + starttime = sys_get_ms_longlong(); + ret = WaitForSingleObject(sem->sem, timeout); + LWIP_ASSERT("Error waiting for semaphore", (ret == WAIT_OBJECT_0) || (ret == WAIT_TIMEOUT)); + if(ret == WAIT_OBJECT_0) + { + endtime = sys_get_ms_longlong(); + /* return the time we waited for the sem */ + return (u32_t)(endtime - starttime); + } + else + { + /* timeout */ + return SYS_ARCH_TIMEOUT; + } + } +} + +void sys_sem_signal(sys_sem_t *sem) +{ + BOOL ret; + LWIP_ASSERT("sem != NULL", sem != NULL); + LWIP_ASSERT("sem->sem != NULL", sem->sem != NULL); + LWIP_ASSERT("sem->sem != INVALID_HANDLE_VALUE", sem->sem != INVALID_HANDLE_VALUE); + ret = ReleaseSemaphore(sem->sem, 1, NULL); + LWIP_ASSERT("Error releasing semaphore", ret != 0); + LWIP_UNUSED_ARG(ret); +} + +err_t sys_mutex_new(sys_mutex_t *mutex) +{ + HANDLE new_mut = NULL; + + LWIP_ASSERT("mutex != NULL", mutex != NULL); + + new_mut = CreateMutex(NULL, FALSE, NULL); + LWIP_ASSERT("Error creating mutex", new_mut != NULL); + if(new_mut != NULL) { + SYS_STATS_INC_USED(mutex); +#if LWIP_STATS && SYS_STATS + LWIP_ASSERT("sys_mutex_new() counter overflow", lwip_stats.sys.mutex.used != 0 ); +#endif /* LWIP_STATS && SYS_STATS*/ + mutex->mut = new_mut; + return ERR_OK; + } + + /* failed to allocate memory... */ + SYS_STATS_INC(mutex.err); + mutex->mut = NULL; + return ERR_MEM; +} + +void sys_mutex_free(sys_mutex_t *mutex) +{ + /* parameter check */ + LWIP_ASSERT("mutex != NULL", mutex != NULL); + LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL); + LWIP_ASSERT("mutex->mut != INVALID_HANDLE_VALUE", mutex->mut != INVALID_HANDLE_VALUE); + CloseHandle(mutex->mut); + + SYS_STATS_DEC(mutex.used); +#if LWIP_STATS && SYS_STATS + LWIP_ASSERT("sys_mutex_free() closed more than created", lwip_stats.sys.mutex.used != (u16_t)-1); +#endif /* LWIP_STATS && SYS_STATS */ + mutex->mut = NULL; +} + +void sys_mutex_lock(sys_mutex_t *mutex) +{ + DWORD ret; + LWIP_ASSERT("mutex != NULL", mutex != NULL); + LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL); + LWIP_ASSERT("mutex->mut != INVALID_HANDLE_VALUE", mutex->mut != INVALID_HANDLE_VALUE); + /* wait infinite */ + ret = WaitForSingleObject(mutex->mut, INFINITE); + LWIP_ASSERT("Error waiting for mutex", ret == WAIT_OBJECT_0); + LWIP_UNUSED_ARG(ret); +} + +void sys_mutex_unlock(sys_mutex_t *mutex) +{ + LWIP_ASSERT("mutex != NULL", mutex != NULL); + LWIP_ASSERT("mutex->mut != NULL", mutex->mut != NULL); + LWIP_ASSERT("mutex->mut != INVALID_HANDLE_VALUE", mutex->mut != INVALID_HANDLE_VALUE); + /* wait infinite */ + if(!ReleaseMutex(mutex->mut)) + { + LWIP_ASSERT("Error releasing mutex", 0); + } +} + + +#ifdef _MSC_VER +const DWORD MS_VC_EXCEPTION=0x406D1388; +#pragma pack(push,8) +typedef struct tagTHREADNAME_INFO +{ + DWORD dwType; /* Must be 0x1000. */ + LPCSTR szName; /* Pointer to name (in user addr space). */ + DWORD dwThreadID; /* Thread ID (-1=caller thread). */ + DWORD dwFlags; /* Reserved for future use, must be zero. */ +} THREADNAME_INFO; +#pragma pack(pop) +static void SetThreadName(DWORD dwThreadID, const char* threadName) +{ + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = threadName; + info.dwThreadID = dwThreadID; + info.dwFlags = 0; + + __try + { + RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info); + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + } +} +#else /* _MSC_VER */ +static void SetThreadName(DWORD dwThreadID, const char* threadName) +{ + LWIP_UNUSED_ARG(dwThreadID); + LWIP_UNUSED_ARG(threadName); +} +#endif /* _MSC_VER */ + +static void sys_thread_function(void* arg) +{ + struct threadlist* t = (struct threadlist*)arg; +#if LWIP_NETCONN_SEM_PER_THREAD + sys_arch_netconn_sem_alloc(); +#endif + t->function(t->arg); +#if LWIP_NETCONN_SEM_PER_THREAD + sys_arch_netconn_sem_free(); +#endif +} + +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio) +{ + struct threadlist *new_thread; + HANDLE h; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_UNUSED_ARG(name); + LWIP_UNUSED_ARG(stacksize); + LWIP_UNUSED_ARG(prio); + + new_thread = (struct threadlist*)malloc(sizeof(struct threadlist)); + LWIP_ASSERT("new_thread != NULL", new_thread != NULL); + if(new_thread != NULL) { + new_thread->function = function; + new_thread->arg = arg; + SYS_ARCH_PROTECT(lev); + new_thread->next = lwip_win32_threads; + lwip_win32_threads = new_thread; + + h = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)sys_thread_function, new_thread, 0, &(new_thread->id)); + LWIP_ASSERT("h != 0", h != 0); + LWIP_ASSERT("h != -1", h != INVALID_HANDLE_VALUE); + LWIP_UNUSED_ARG(h); + SetThreadName(new_thread->id, name); + + SYS_ARCH_UNPROTECT(lev); + return new_thread->id; + } + return 0; +} + +err_t sys_mbox_new(sys_mbox_t *mbox, int size) +{ + LWIP_ASSERT("mbox != NULL", mbox != NULL); + LWIP_UNUSED_ARG(size); + + mbox->sem = CreateSemaphore(0, 0, MAX_QUEUE_ENTRIES, 0); + LWIP_ASSERT("Error creating semaphore", mbox->sem != NULL); + if(mbox->sem == NULL) { + SYS_STATS_INC(mbox.err); + return ERR_MEM; + } + memset(&mbox->q_mem, 0, sizeof(u32_t)*MAX_QUEUE_ENTRIES); + mbox->head = 0; + mbox->tail = 0; + SYS_STATS_INC_USED(mbox); +#if LWIP_STATS && SYS_STATS + LWIP_ASSERT("sys_mbox_new() counter overflow", lwip_stats.sys.mbox.used != 0 ); +#endif /* LWIP_STATS && SYS_STATS */ + return ERR_OK; +} + +void sys_mbox_free(sys_mbox_t *mbox) +{ + /* parameter check */ + LWIP_ASSERT("mbox != NULL", mbox != NULL); + LWIP_ASSERT("mbox->sem != NULL", mbox->sem != NULL); + LWIP_ASSERT("mbox->sem != INVALID_HANDLE_VALUE", mbox->sem != INVALID_HANDLE_VALUE); + + CloseHandle(mbox->sem); + + SYS_STATS_DEC(mbox.used); +#if LWIP_STATS && SYS_STATS + LWIP_ASSERT( "sys_mbox_free() ", lwip_stats.sys.mbox.used!= (u16_t)-1 ); +#endif /* LWIP_STATS && SYS_STATS */ + mbox->sem = NULL; +} + +void sys_mbox_post(sys_mbox_t *q, void *msg) +{ + BOOL ret; + SYS_ARCH_DECL_PROTECT(lev); + + /* parameter check */ + LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL); + LWIP_ASSERT("q->sem != NULL", q->sem != NULL); + LWIP_ASSERT("q->sem != INVALID_HANDLE_VALUE", q->sem != INVALID_HANDLE_VALUE); + + SYS_ARCH_PROTECT(lev); + q->q_mem[q->head] = msg; + (q->head)++; + if (q->head >= MAX_QUEUE_ENTRIES) { + q->head = 0; + } + LWIP_ASSERT("mbox is full!", q->head != q->tail); + ret = ReleaseSemaphore(q->sem, 1, 0); + LWIP_ASSERT("Error releasing sem", ret != 0); + LWIP_UNUSED_ARG(ret); + + SYS_ARCH_UNPROTECT(lev); +} + +err_t sys_mbox_trypost(sys_mbox_t *q, void *msg) +{ + u32_t new_head; + BOOL ret; + SYS_ARCH_DECL_PROTECT(lev); + + /* parameter check */ + LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL); + LWIP_ASSERT("q->sem != NULL", q->sem != NULL); + LWIP_ASSERT("q->sem != INVALID_HANDLE_VALUE", q->sem != INVALID_HANDLE_VALUE); + + SYS_ARCH_PROTECT(lev); + + new_head = q->head + 1; + if (new_head >= MAX_QUEUE_ENTRIES) { + new_head = 0; + } + if (new_head == q->tail) { + SYS_ARCH_UNPROTECT(lev); + return ERR_MEM; + } + + q->q_mem[q->head] = msg; + q->head = new_head; + LWIP_ASSERT("mbox is full!", q->head != q->tail); + ret = ReleaseSemaphore(q->sem, 1, 0); + LWIP_ASSERT("Error releasing sem", ret != 0); + LWIP_UNUSED_ARG(ret); + + SYS_ARCH_UNPROTECT(lev); + return ERR_OK; +} + +u32_t sys_arch_mbox_fetch(sys_mbox_t *q, void **msg, u32_t timeout) +{ + DWORD ret; + LONGLONG starttime, endtime; + SYS_ARCH_DECL_PROTECT(lev); + + /* parameter check */ + LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL); + LWIP_ASSERT("q->sem != NULL", q->sem != NULL); + LWIP_ASSERT("q->sem != INVALID_HANDLE_VALUE", q->sem != INVALID_HANDLE_VALUE); + + if (timeout == 0) { + timeout = INFINITE; + } + starttime = sys_get_ms_longlong(); + if ((ret = WaitForSingleObject(q->sem, timeout)) == WAIT_OBJECT_0) { + SYS_ARCH_PROTECT(lev); + if(msg != NULL) { + *msg = q->q_mem[q->tail]; + } + + (q->tail)++; + if (q->tail >= MAX_QUEUE_ENTRIES) { + q->tail = 0; + } + SYS_ARCH_UNPROTECT(lev); + endtime = sys_get_ms_longlong(); + return (u32_t)(endtime - starttime); + } + else + { + LWIP_ASSERT("Error waiting for sem", ret == WAIT_TIMEOUT); + if(msg != NULL) { + *msg = NULL; + } + + return SYS_ARCH_TIMEOUT; + } +} + +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *q, void **msg) +{ + DWORD ret; + SYS_ARCH_DECL_PROTECT(lev); + + /* parameter check */ + LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL); + LWIP_ASSERT("q->sem != NULL", q->sem != NULL); + LWIP_ASSERT("q->sem != INVALID_HANDLE_VALUE", q->sem != INVALID_HANDLE_VALUE); + + if ((ret = WaitForSingleObject(q->sem, 0)) == WAIT_OBJECT_0) { + SYS_ARCH_PROTECT(lev); + if(msg != NULL) { + *msg = q->q_mem[q->tail]; + } + + (q->tail)++; + if (q->tail >= MAX_QUEUE_ENTRIES) { + q->tail = 0; + } + SYS_ARCH_UNPROTECT(lev); + return 0; + } + else + { + LWIP_ASSERT("Error waiting for sem", ret == WAIT_TIMEOUT); + if(msg != NULL) { + *msg = NULL; + } + + return SYS_ARCH_TIMEOUT; + } +} + +#if LWIP_NETCONN_SEM_PER_THREAD +sys_sem_t* sys_arch_netconn_sem_get(void) +{ + LPVOID tls_data = TlsGetValue(netconn_sem_tls_index); + return (sys_sem_t*)tls_data; +} + +void sys_arch_netconn_sem_alloc(void) +{ + sys_sem_t *sem; + err_t err; + BOOL done; + + sem = (sys_sem_t*)malloc(sizeof(sys_sem_t)); + LWIP_ASSERT("failed to allocate memory for TLS semaphore", sem != NULL); + err = sys_sem_new(sem, 0); + LWIP_ASSERT("failed to initialise TLS semaphore", err == ERR_OK); + done = TlsSetValue(netconn_sem_tls_index, sem); + LWIP_UNUSED_ARG(done); + LWIP_ASSERT("failed to initialise TLS semaphore storage", done == TRUE); +} + +void sys_arch_netconn_sem_free(void) +{ + LPVOID tls_data = TlsGetValue(netconn_sem_tls_index); + if (tls_data != NULL) { + BOOL done; + free(tls_data); + done = TlsSetValue(netconn_sem_tls_index, NULL); + LWIP_UNUSED_ARG(done); + LWIP_ASSERT("failed to de-init TLS semaphore storage", done == TRUE); + } +} +#endif /* LWIP_NETCONN_SEM_PER_THREAD */ + +#endif /* !NO_SYS */ + +/* get keyboard state to terminate the debug app on any kbhit event using win32 API */ +int lwip_win32_keypressed(void) +{ + INPUT_RECORD rec; + DWORD num = 0; + HANDLE h = GetStdHandle(STD_INPUT_HANDLE); + BOOL ret = PeekConsoleInput(h, &rec, 1, &num); + if (ret) { + if(rec.EventType == KEY_EVENT) { + if(rec.Event.KeyEvent.bKeyDown) { + return 1; + } + } + ReadConsoleInput(h, &rec, 1, &num); + } + return 0; +} diff --git a/ext/lwip-contrib/ports/win32/test.c b/ext/lwip-contrib/ports/win32/test.c new file mode 100644 index 0000000..5d0dc9c --- /dev/null +++ b/ext/lwip-contrib/ports/win32/test.c @@ -0,0 +1,788 @@ +/* + * Copyright (c) 2001,2002 Florian Schulze. + * All rights reserved. + * + * 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 of the authors nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. + * + * test.c - This file is part of lwIP test + * + */ + +/* C runtime includes */ +#include +#include +#include +#include + +/* lwIP core includes */ +#include "lwip/opt.h" + +#include "lwip/sys.h" +#include "lwip/timeouts.h" +#include "lwip/debug.h" +#include "lwip/stats.h" +#include "lwip/init.h" +#include "lwip/tcpip.h" +#include "lwip/netif.h" +#include "lwip/api.h" + +#include "lwip/tcp.h" +#include "lwip/udp.h" +#include "lwip/dns.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" + +/* lwIP netif includes */ +#include "lwip/etharp.h" +#include "netif/ethernet.h" + +/* applications includes */ +#include "lwip/apps/lwiperf.h" +#include "lwip/apps/netbiosns.h" +#include "lwip/apps/sntp.h" +#include "lwip/apps/httpd.h" +#include "lwip/apps/mdns.h" +#include "lwip/apps/snmp.h" +#include "apps/httpserver/httpserver-netconn.h" +#include "apps/netio/netio.h" +#include "apps/ping/ping.h" +#include "apps/rtp/rtp.h" +#include "apps/chargen/chargen.h" +#include "apps/shell/shell.h" +#include "apps/tcpecho/tcpecho.h" +#include "apps/udpecho/udpecho.h" +#include "apps/tcpecho_raw/tcpecho_raw.h" +#include "apps/socket_examples/socket_examples.h" +#include "apps/snmp_v3/snmpv3_dummy.h" + +#if NO_SYS +/* ... then we need information about the timer intervals: */ +#include "lwip/ip4_frag.h" +#include "lwip/igmp.h" +#endif /* NO_SYS */ + +#include "netif/ppp/ppp_opts.h" +#if PPP_SUPPORT +/* PPP includes */ +#include "lwip/sio.h" +#include "netif/ppp/pppapi.h" +#include "netif/ppp/pppos.h" +#include "netif/ppp/pppoe.h" +#if !NO_SYS && !LWIP_PPP_API +#error With NO_SYS==0, LWIP_PPP_API==1 is required. +#endif +#endif /* PPP_SUPPORT */ + +/* include the port-dependent configuration */ +#include "lwipcfg_msvc.h" + +/** Define this to 1 to enable a PCAP interface as default interface. */ +#ifndef USE_PCAPIF +#define USE_PCAPIF 1 +#endif + +/** Define this to 1 to enable a PPP interface. */ +#ifndef USE_PPP +#define USE_PPP 0 +#endif + +/** Define this to 1 or 2 to support 1 or 2 SLIP interfaces. */ +#ifndef USE_SLIPIF +#define USE_SLIPIF 0 +#endif + +/** Use an ethernet adapter? Default to enabled if PCAPIF or PPPoE are used. */ +#ifndef USE_ETHERNET +#define USE_ETHERNET (USE_PCAPIF || PPPOE_SUPPORT) +#endif + +/** Use an ethernet adapter for TCP/IP? By default only if PCAPIF is used. */ +#ifndef USE_ETHERNET_TCPIP +#define USE_ETHERNET_TCPIP (USE_PCAPIF) +#endif + +#if USE_ETHERNET +#include "pcapif.h" +#endif /* USE_ETHERNET */ +#if USE_SLIPIF +#include +#endif /* USE_SLIPIF */ + +#ifndef USE_DHCP +#define USE_DHCP LWIP_DHCP +#endif +#ifndef USE_AUTOIP +#define USE_AUTOIP LWIP_AUTOIP +#endif + +/* globales variables for netifs */ +#if USE_ETHERNET +/* THE ethernet interface */ +struct netif netif; +#if LWIP_DHCP +/* dhcp struct for the ethernet netif */ +struct dhcp netif_dhcp; +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP +/* autoip struct for the ethernet netif */ +struct autoip netif_autoip; +#endif /* LWIP_AUTOIP */ +#endif /* USE_ETHERNET */ +#if USE_PPP +/* THE PPP PCB */ +ppp_pcb *ppp; +/* THE PPP interface */ +struct netif ppp_netif; +/* THE PPP descriptor */ +u8_t sio_idx = 0; +sio_fd_t ppp_sio; +#endif /* USE_PPP */ +#if USE_SLIPIF +struct netif slipif1; +#if USE_SLIPIF > 1 +struct netif slipif2; +#endif /* USE_SLIPIF > 1 */ +#endif /* USE_SLIPIF */ + + +#if USE_PPP +static void +pppLinkStatusCallback(ppp_pcb *pcb, int errCode, void *ctx) +{ + struct netif *pppif = ppp_netif(pcb); + LWIP_UNUSED_ARG(ctx); + + switch(errCode) { + case PPPERR_NONE: { /* No error. */ + printf("pppLinkStatusCallback: PPPERR_NONE\n"); +#if LWIP_IPV4 + printf(" our_ipaddr = %s\n", ip4addr_ntoa(netif_ip4_addr(pppif))); + printf(" his_ipaddr = %s\n", ip4addr_ntoa(netif_ip4_gw(pppif))); + printf(" netmask = %s\n", ip4addr_ntoa(netif_ip4_netmask(pppif))); +#endif /* LWIP_IPV4 */ +#if LWIP_DNS + printf(" dns1 = %s\n", ipaddr_ntoa(dns_getserver(0))); + printf(" dns2 = %s\n", ipaddr_ntoa(dns_getserver(1))); +#endif /* LWIP_DNS */ +#if PPP_IPV6_SUPPORT + printf(" our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0))); +#endif /* PPP_IPV6_SUPPORT */ + break; + } + case PPPERR_PARAM: { /* Invalid parameter. */ + printf("pppLinkStatusCallback: PPPERR_PARAM\n"); + break; + } + case PPPERR_OPEN: { /* Unable to open PPP session. */ + printf("pppLinkStatusCallback: PPPERR_OPEN\n"); + break; + } + case PPPERR_DEVICE: { /* Invalid I/O device for PPP. */ + printf("pppLinkStatusCallback: PPPERR_DEVICE\n"); + break; + } + case PPPERR_ALLOC: { /* Unable to allocate resources. */ + printf("pppLinkStatusCallback: PPPERR_ALLOC\n"); + break; + } + case PPPERR_USER: { /* User interrupt. */ + printf("pppLinkStatusCallback: PPPERR_USER\n"); + break; + } + case PPPERR_CONNECT: { /* Connection lost. */ + printf("pppLinkStatusCallback: PPPERR_CONNECT\n"); + break; + } + case PPPERR_AUTHFAIL: { /* Failed authentication challenge. */ + printf("pppLinkStatusCallback: PPPERR_AUTHFAIL\n"); + break; + } + case PPPERR_PROTOCOL: { /* Failed to meet protocol. */ + printf("pppLinkStatusCallback: PPPERR_PROTOCOL\n"); + break; + } + case PPPERR_PEERDEAD: { /* Connection timeout */ + printf("pppLinkStatusCallback: PPPERR_PEERDEAD\n"); + break; + } + case PPPERR_IDLETIMEOUT: { /* Idle Timeout */ + printf("pppLinkStatusCallback: PPPERR_IDLETIMEOUT\n"); + break; + } + case PPPERR_CONNECTTIME: { /* Max connect time reached */ + printf("pppLinkStatusCallback: PPPERR_CONNECTTIME\n"); + break; + } + case PPPERR_LOOPBACK: { /* Loopback detected */ + printf("pppLinkStatusCallback: PPPERR_LOOPBACK\n"); + break; + } + default: { + printf("pppLinkStatusCallback: unknown errCode %d\n", errCode); + break; + } + } +} + +#if PPPOS_SUPPORT +static u32_t +ppp_output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) +{ + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(ctx); + return sio_write(ppp_sio, data, len); +} +#endif /* PPPOS_SUPPORT */ +#endif /* USE_PPP */ + +#if LWIP_NETIF_STATUS_CALLBACK +static void +status_callback(struct netif *state_netif) +{ + if (netif_is_up(state_netif)) { +#if LWIP_IPV4 + printf("status_callback==UP, local interface IP is %s\n", ip4addr_ntoa(netif_ip4_addr(state_netif))); +#else + printf("status_callback==UP\n"); +#endif +#if LWIP_MDNS_RESPONDER + mdns_resp_netif_settings_changed(state_netif); +#endif + } else { + printf("status_callback==DOWN\n"); + } +} +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_LINK_CALLBACK +static void +link_callback(struct netif *state_netif) +{ + if (netif_is_link_up(state_netif)) { + printf("link_callback==UP\n"); + } else { + printf("link_callback==DOWN\n"); + } +} +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +/* This function initializes all network interfaces */ +static void +msvc_netif_init(void) +{ +#if LWIP_IPV4 && USE_ETHERNET + ip4_addr_t ipaddr, netmask, gw; +#endif /* LWIP_IPV4 && USE_ETHERNET */ +#if USE_SLIPIF + u8_t num_slip1 = 0; +#if LWIP_IPV4 + ip4_addr_t ipaddr_slip1, netmask_slip1, gw_slip1; +#endif +#if USE_SLIPIF > 1 + u8_t num_slip2 = 1; +#if LWIP_IPV4 + ip4_addr_t ipaddr_slip2, netmask_slip2, gw_slip2; +#endif +#endif /* USE_SLIPIF > 1 */ +#endif /* USE_SLIPIF */ +#if USE_DHCP || USE_AUTOIP + err_t err; +#endif + +#if USE_PPP + const char *username = NULL, *password = NULL; +#ifdef PPP_USERNAME + username = PPP_USERNAME; +#endif +#ifdef PPP_PASSWORD + password = PPP_PASSWORD; +#endif + printf("ppp_connect: COM%d\n", (int)sio_idx); +#if PPPOS_SUPPORT + ppp_sio = sio_open(sio_idx); + if (ppp_sio == NULL) { + printf("sio_open error\n"); + } else { + ppp = pppos_create(&ppp_netif, ppp_output_cb, pppLinkStatusCallback, NULL); + if (ppp == NULL) { + printf("pppos_create error\n"); + } else { + ppp_set_auth(ppp, PPPAUTHTYPE_ANY, username, password); + ppp_connect(ppp, 0); + } + } +#endif /* PPPOS_SUPPORT */ +#endif /* USE_PPP */ + +#if USE_ETHERNET +#if LWIP_IPV4 +#define NETIF_ADDRS &ipaddr, &netmask, &gw, + ip4_addr_set_zero(&gw); + ip4_addr_set_zero(&ipaddr); + ip4_addr_set_zero(&netmask); +#if USE_ETHERNET_TCPIP +#if USE_DHCP + printf("Starting lwIP, local interface IP is dhcp-enabled\n"); +#elif USE_AUTOIP + printf("Starting lwIP, local interface IP is autoip-enabled\n"); +#else /* USE_DHCP */ + LWIP_PORT_INIT_GW(&gw); + LWIP_PORT_INIT_IPADDR(&ipaddr); + LWIP_PORT_INIT_NETMASK(&netmask); + printf("Starting lwIP, local interface IP is %s\n", ip4addr_ntoa(&ipaddr)); +#endif /* USE_DHCP */ +#endif /* USE_ETHERNET_TCPIP */ +#else /* LWIP_IPV4 */ +#define NETIF_ADDRS + printf("Starting lwIP, IPv4 disable\n"); +#endif /* LWIP_IPV4 */ + +#if NO_SYS + netif_set_default(netif_add(&netif, NETIF_ADDRS NULL, pcapif_init, netif_input)); +#else /* NO_SYS */ + netif_set_default(netif_add(&netif, NETIF_ADDRS NULL, pcapif_init, tcpip_input)); +#endif /* NO_SYS */ +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(&netif, 1); + printf("ip6 linklocal address: "); + ip6_addr_debug_print(0xFFFFFFFF & ~LWIP_DBG_HALT, netif_ip6_addr(&netif, 0)); + printf("\n"); +#endif /* LWIP_IPV6 */ +#if LWIP_NETIF_STATUS_CALLBACK + netif_set_status_callback(&netif, status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + netif_set_link_callback(&netif, link_callback); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if USE_ETHERNET_TCPIP +#if LWIP_AUTOIP + autoip_set_struct(&netif, &netif_autoip); +#endif /* LWIP_AUTOIP */ +#if LWIP_DHCP + dhcp_set_struct(&netif, &netif_dhcp); +#endif /* LWIP_DHCP */ + netif_set_up(&netif); +#if USE_DHCP + err = dhcp_start(&netif); + LWIP_ASSERT("dhcp_start failed", err == ERR_OK); +#elif USE_AUTOIP + err = autoip_start(&netif); + LWIP_ASSERT("autoip_start failed", err == ERR_OK); +#endif /* USE_DHCP */ +#else /* USE_ETHERNET_TCPIP */ + /* Use ethernet for PPPoE only */ + netif.flags &= ~(NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP); /* no ARP */ + netif.flags |= NETIF_FLAG_ETHERNET; /* but pure ethernet */ +#endif /* USE_ETHERNET_TCPIP */ + +#if USE_PPP && PPPOE_SUPPORT + /* start PPPoE after ethernet netif is added! */ + ppp = pppoe_create(&ppp_netif, &netif, NULL, NULL, pppLinkStatusCallback, NULL); + if (ppp == NULL) { + printf("pppos_create error\n"); + } else { + ppp_set_auth(ppp, PPPAUTHTYPE_ANY, username, password); + ppp_connect(ppp, 0); + } +#endif /* USE_PPP && PPPOE_SUPPORT */ + +#endif /* USE_ETHERNET */ +#if USE_SLIPIF +#if LWIP_IPV4 +#define SLIP1_ADDRS &ipaddr_slip1, &netmask_slip1, &gw_slip1, + LWIP_PORT_INIT_SLIP1_IPADDR(&ipaddr_slip1); + LWIP_PORT_INIT_SLIP1_GW(&gw_slip1); + LWIP_PORT_INIT_SLIP1_NETMASK(&netmask_slip1); + printf("Starting lwIP slipif, local interface IP is %s\n", ip4addr_ntoa(&ipaddr_slip1)); +#else +#define SLIP1_ADDRS + printf("Starting lwIP slipif\n"); +#endif +#if defined(SIO_USE_COMPORT) && SIO_USE_COMPORT + num_slip1++; /* COM ports cannot be 0-based */ +#endif + netif_add(&slipif1, SLIP1_ADDRS &num_slip1, slipif_init, ip_input); +#if !USE_ETHERNET + netif_set_default(&slipif1); +#endif /* !USE_ETHERNET */ +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(&slipif1, 1); + printf("SLIP ip6 linklocal address: "); + ip6_addr_debug_print(0xFFFFFFFF & ~LWIP_DBG_HALT, netif_ip6_addr(&slipif1, 0)); + printf("\n"); +#endif /* LWIP_IPV6 */ +#if LWIP_NETIF_STATUS_CALLBACK + netif_set_status_callback(&slipif1, status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + netif_set_link_callback(&slipif1, link_callback); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + netif_set_up(&slipif1); + +#if USE_SLIPIF > 1 +#if LWIP_IPV4 +#define SLIP2_ADDRS &ipaddr_slip2, &netmask_slip2, &gw_slip2, + LWIP_PORT_INIT_SLIP2_IPADDR(&ipaddr_slip2); + LWIP_PORT_INIT_SLIP2_GW(&gw_slip2); + LWIP_PORT_INIT_SLIP2_NETMASK(&netmask_slip2); + printf("Starting lwIP SLIP if #2, local interface IP is %s\n", ip4addr_ntoa(&ipaddr_slip2)); +#else +#define SLIP2_ADDRS + printf("Starting lwIP SLIP if #2\n"); +#endif +#if defined(SIO_USE_COMPORT) && SIO_USE_COMPORT + num_slip2++; /* COM ports cannot be 0-based */ +#endif + netif_add(&slipif2, SLIP2_ADDRS &num_slip2, slipif_init, ip_input); +#if LWIP_IPV6 + netif_create_ip6_linklocal_address(&slipif1, 1); + printf("SLIP2 ip6 linklocal address: "); + ip6_addr_debug_print(0xFFFFFFFF & ~LWIP_DBG_HALT, netif_ip6_addr(&slipif2, 0)); + printf("\n"); +#endif /* LWIP_IPV6 */ +#if LWIP_NETIF_STATUS_CALLBACK + netif_set_status_callback(&slipif2, status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + netif_set_link_callback(&slipif2, link_callback); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + netif_set_up(&slipif2); +#endif /* USE_SLIPIF > 1*/ +#endif /* USE_SLIPIF */ +} + +#if LWIP_DNS_APP && LWIP_DNS +static void +dns_found(const char *name, const ip_addr_t *addr, void *arg) +{ + LWIP_UNUSED_ARG(arg); + printf("%s: %s\n", name, addr ? ipaddr_ntoa(addr) : ""); +} + +static void +dns_dorequest(void *arg) +{ + const char* dnsname = "3com.com"; + ip_addr_t dnsresp; + LWIP_UNUSED_ARG(arg); + + if (dns_gethostbyname(dnsname, &dnsresp, dns_found, 0) == ERR_OK) { + dns_found(dnsname, &dnsresp, 0); + } +} +#endif /* LWIP_DNS_APP && LWIP_DNS */ + +#if LWIP_LWIPERF_APP +static void +lwiperf_report(void *arg, enum lwiperf_report_type report_type, + const ip_addr_t* local_addr, u16_t local_port, const ip_addr_t* remote_addr, u16_t remote_port, + u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec) +{ + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(local_addr); + LWIP_UNUSED_ARG(local_port); + + printf("IPERF report: type=%d, remote: %s:%d, total bytes: %lu, duration in ms: %lu, kbits/s: %lu\n", + (int)report_type, ipaddr_ntoa(remote_addr), (int)remote_port, bytes_transferred, ms_duration, bandwidth_kbitpsec); +} +#endif /* LWIP_LWIPERF_APP */ + +#if LWIP_MDNS_RESPONDER +static void srv_txt(struct mdns_service *service, void *txt_userdata) +{ + err_t res = mdns_resp_add_service_txtitem(service, "path=/", 6); + LWIP_ERROR("mdns add service txt failed\n", (res == ERR_OK), return); + LWIP_UNUSED_ARG(txt_userdata); +} +#endif + +/* This function initializes applications */ +static void +apps_init(void) +{ +#if LWIP_DNS_APP && LWIP_DNS + /* wait until the netif is up (for dhcp, autoip or ppp) */ + sys_timeout(5000, dns_dorequest, NULL); +#endif /* LWIP_DNS_APP && LWIP_DNS */ + +#if LWIP_CHARGEN_APP && LWIP_SOCKET + chargen_init(); +#endif /* LWIP_CHARGEN_APP && LWIP_SOCKET */ + +#if LWIP_PING_APP && LWIP_RAW && LWIP_ICMP + ping_init(&netif.gw); +#endif /* LWIP_PING_APP && LWIP_RAW && LWIP_ICMP */ + +#if LWIP_NETBIOS_APP && LWIP_UDP + netbiosns_init(); +#ifndef NETBIOS_LWIP_NAME +#if LWIP_NETIF_HOSTNAME + netbiosns_set_name(netif_default->hostname); +#else + netbiosns_set_name("NETBIOSLWIPDEV"); +#endif +#endif +#endif /* LWIP_NETBIOS_APP && LWIP_UDP */ + +#if LWIP_HTTPD_APP && LWIP_TCP +#ifdef LWIP_HTTPD_APP_NETCONN + http_server_netconn_init(); +#else /* LWIP_HTTPD_APP_NETCONN */ + httpd_init(); +#endif /* LWIP_HTTPD_APP_NETCONN */ +#endif /* LWIP_HTTPD_APP && LWIP_TCP */ + +#if LWIP_MDNS_RESPONDER + mdns_resp_init(); +#if LWIP_NETIF_HOSTNAME + mdns_resp_add_netif(netif_default, netif_default->hostname, 3600); +#else + mdns_resp_add_netif(netif_default, "lwip", 3600); +#endif + mdns_resp_add_service(netif_default, "lwipweb", "_http", DNSSD_PROTO_TCP, HTTPD_SERVER_PORT, 3600, srv_txt, NULL); +#endif + +#if LWIP_NETIO_APP && LWIP_TCP + netio_init(); +#endif /* LWIP_NETIO_APP && LWIP_TCP */ + +#if LWIP_RTP_APP && LWIP_SOCKET && LWIP_IGMP + rtp_init(); +#endif /* LWIP_RTP_APP && LWIP_SOCKET && LWIP_IGMP */ + +#if LWIP_SNTP_APP + sntp_init(); +#endif /* LWIP_SNTP_APP */ + +#if LWIP_SHELL_APP && LWIP_NETCONN + shell_init(); +#endif /* LWIP_SHELL_APP && LWIP_NETCONN */ +#if LWIP_TCPECHO_APP +#if LWIP_NETCONN && defined(LWIP_TCPECHO_APP_NETCONN) + tcpecho_init(); +#else /* LWIP_NETCONN && defined(LWIP_TCPECHO_APP_NETCONN) */ + tcpecho_raw_init(); +#endif +#endif /* LWIP_TCPECHO_APP && LWIP_NETCONN */ +#if LWIP_UDPECHO_APP && LWIP_NETCONN + udpecho_init(); +#endif /* LWIP_UDPECHO_APP && LWIP_NETCONN */ +#if LWIP_LWIPERF_APP + lwiperf_start_tcp_server_default(lwiperf_report, NULL); +#endif +#if LWIP_SOCKET_EXAMPLES_APP && LWIP_SOCKET + socket_examples_init(); +#endif /* LWIP_SOCKET_EXAMPLES_APP && LWIP_SOCKET */ +#if LWIP_SNMP && LWIP_UDP +#if LWIP_SNMP_V3 + snmpv3_dummy_init(); +#endif + snmp_init(); +#endif /* LWIP_SNMP && LWIP_UDP */ +#ifdef LWIP_APP_INIT + LWIP_APP_INIT(); +#endif +} + +/* This function initializes this lwIP test. When NO_SYS=1, this is done in + * the main_loop context (there is no other one), when NO_SYS=0, this is done + * in the tcpip_thread context */ +static void +test_init(void * arg) +{ /* remove compiler warning */ +#if NO_SYS + LWIP_UNUSED_ARG(arg); +#else /* NO_SYS */ + sys_sem_t *init_sem; + LWIP_ASSERT("arg != NULL", arg != NULL); + init_sem = (sys_sem_t*)arg; +#endif /* NO_SYS */ + + /* init randomizer again (seed per thread) */ + srand((unsigned int)time(0)); + + /* init network interfaces */ + msvc_netif_init(); + + /* init apps */ + apps_init(); + +#if !NO_SYS + sys_sem_signal(init_sem); +#endif /* !NO_SYS */ +} + +/* This is somewhat different to other ports: we have a main loop here: + * a dedicated task that waits for packets to arrive. This would normally be + * done from interrupt context with embedded hardware, but we don't get an + * interrupt in windows for that :-) */ +static void +main_loop(void) +{ +#if !NO_SYS + err_t err; + sys_sem_t init_sem; +#endif /* NO_SYS */ +#if USE_PPP +#if !USE_ETHERNET + int count; + u8_t rxbuf[1024]; +#endif + volatile int callClosePpp = 0; +#endif /* USE_PPP */ + + /* initialize lwIP stack, network interfaces and applications */ +#if NO_SYS + lwip_init(); + test_init(NULL); +#else /* NO_SYS */ + err = sys_sem_new(&init_sem, 0); + LWIP_ASSERT("failed to create init_sem", err == ERR_OK); + LWIP_UNUSED_ARG(err); + tcpip_init(test_init, &init_sem); + /* we have to wait for initialization to finish before + * calling update_adapter()! */ + sys_sem_wait(&init_sem); + sys_sem_free(&init_sem); +#endif /* NO_SYS */ + +#if (LWIP_SOCKET || LWIP_NETCONN) && LWIP_NETCONN_SEM_PER_THREAD + netconn_thread_init(); +#endif + + /* MAIN LOOP for driver update (and timers if NO_SYS) */ + while (!lwip_win32_keypressed()) { +#if NO_SYS + /* handle timers (already done in tcpip.c when NO_SYS=0) */ + sys_check_timeouts(); +#endif /* NO_SYS */ + +#if USE_ETHERNET +#if !PCAPIF_RX_USE_THREAD + /* check for packets and link status*/ + pcapif_poll(&netif); + /* When pcapif_poll comes back, there are not packets, so sleep to + prevent 100% CPU load. Don't do this in an embedded system since it + increases latency! */ + sys_msleep(1); +#else /* !PCAPIF_RX_USE_THREAD */ + sys_msleep(50); +#endif /* !PCAPIF_RX_USE_THREAD */ +#else /* USE_ETHERNET */ + /* try to read characters from serial line and pass them to PPPoS */ + count = sio_read(ppp_sio, (u8_t*)rxbuf, 1024); + if(count > 0) { + pppos_input(ppp, rxbuf, count); + } else { + /* nothing received, give other tasks a chance to run */ + sys_msleep(1); + } + +#endif /* USE_ETHERNET */ +#if USE_SLIPIF + slipif_poll(&slipif1); +#if USE_SLIPIF > 1 + slipif_poll(&slipif2); +#endif /* USE_SLIPIF > 1 */ +#endif /* USE_SLIPIF */ +#if ENABLE_LOOPBACK && !LWIP_NETIF_LOOPBACK_MULTITHREADING + /* check for loopback packets on all netifs */ + netif_poll_all(); +#endif /* ENABLE_LOOPBACK && !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#if USE_PPP + { + int do_hup = 0; + if(do_hup) { + ppp_close(ppp, 1); + do_hup = 0; + } + } + if(callClosePpp && ppp) { + /* make sure to disconnect PPP before stopping the program... */ + callClosePpp = 0; +#if NO_SYS + ppp_close(ppp, 0); +#else + pppapi_close(ppp, 0); +#endif + ppp = NULL; + } +#endif /* USE_PPP */ + } + +#if USE_PPP + if(ppp) { + u32_t started; + printf("Closing PPP connection...\n"); + /* make sure to disconnect PPP before stopping the program... */ +#if NO_SYS + ppp_close(ppp, 0); +#else + pppapi_close(ppp, 0); +#endif + ppp = NULL; + /* Wait for some time to let PPP finish... */ + started = sys_now(); + do + { +#if USE_ETHERNET && !PCAPIF_RX_USE_THREAD + pcapif_poll(&netif); +#else /* USE_ETHERNET && !PCAPIF_RX_USE_THREAD */ + sys_msleep(50); +#endif /* USE_ETHERNET && !PCAPIF_RX_USE_THREAD */ + /* @todo: need a better check here: only wait until PPP is down */ + } while(sys_now() - started < 5000); + } +#endif /* USE_PPP */ +#if (LWIP_SOCKET || LWIP_NETCONN) && LWIP_NETCONN_SEM_PER_THREAD + netconn_thread_cleanup(); +#endif +#if USE_ETHERNET + /* release the pcap library... */ + pcapif_shutdown(&netif); +#endif /* USE_ETHERNET */ +} + +#if USE_PPP && PPPOS_SUPPORT +int main(int argc, char **argv) +#else /* USE_PPP && PPPOS_SUPPORT */ +int main(void) +#endif /* USE_PPP && PPPOS_SUPPORT */ +{ +#if USE_PPP && PPPOS_SUPPORT + if(argc > 1) { + sio_idx = (u8_t)atoi(argv[1]); + } + printf("Using serial port %d for PPP\n", sio_idx); +#endif /* USE_PPP && PPPOS_SUPPORT */ + /* no stdio-buffering, please! */ + setvbuf(stdout, NULL,_IONBF, 0); + + main_loop(); + + return 0; +} diff --git a/ext/lwip/CHANGELOG b/ext/lwip/CHANGELOG deleted file mode 100755 index 3b47ec2..0000000 --- a/ext/lwip/CHANGELOG +++ /dev/null @@ -1,4295 +0,0 @@ -HISTORY - -(git master) - - * [Enter new changes just after this line - do not remove this line] - -(STABLE-2.0.3) - - ++ Bugfixes: - - 2017-09-11: Simon Goldschmidt - * tcp_in.c: fix bug #51937 (leaking tcp_pcbs on passive close with unacked data) - - 2017-08-02: Abroz Bizjak/Simon Goldschmidt - * multiple fixes in IPv4 reassembly (leading to corrupted datagrams received) - - 2017-03-30: Simon Goldschmidt - * dhcp.c: return ERR_VAL instead of asserting on offset-out-of-pbuf - - 2017-03-23: Dirk Ziegelmeier - * dhcp.h: fix bug #50618 (dhcp_remove_struct() macro does not work) - -(STABLE-2.0.2) - - ++ New features: - - 2017-02-10: Dirk Ziegelmeier - * Implement task #14367: Hooks need a better place to be defined: - We now have a #define for a header file name that is #included in every .c - file that provides hooks. - - 2017-02-10: Simon Goldschmidt - * tcp_close does not fail on memory error (instead, FIN is sent from tcp_tmr) - - ++ Bugfixes: - - 2017-03-08 - * tcp: do not keep sending SYNs when getting ACKs - - 2017-03-08: Joel Cunningham - * tcp: Initialize ssthresh to TCP_SND_BUF (bug #50476) - - 2017-03-01: Simon Goldschmidt - * httpd: LWIP_HTTPD_POST_MANUAL_WND: fixed double-free when httpd_post_data_recved - is called nested from httpd_post_receive_data() (bug #50424) - - 2017-02-28: David van Moolenbroek/Simon Goldschmidt - * tcp: fixed bug #50418: LWIP_EVENT_API: fix invalid calbacks for SYN_RCVD pcb - - 2017-02-17: Simon Goldschmidt - * dns: Improved DNS_LOCAL_HOSTLIST interface (bug #50325) - - 2017-02-16: Simon Goldschmidt - * LWIP_NETCONN_FULLDUPLEX: fixed shutdown during write (bug #50274) - - 2017-02-13: Simon Goldschmidt/Dirk Ziegelmeier - * For tiny targtes, LWIP_RAND is optional (fix compile time checks) - - 2017-02-10: Simon Goldschmidt - * tcp: Fixed bug #47485 (tcp_close() should not fail on memory error) by retrying - to send FIN from tcp_fasttmr - - 2017-02-09: Simon Goldschmidt - * sockets: Fixed bug #44032 (LWIP_NETCONN_FULLDUPLEX: select might work on - invalid/reused socket) by not allowing to reallocate a socket that has - "select_waiting != 0" - - 2017-02-09: Simon Goldschmidt - * httpd: Fixed bug #50059 (httpd LWIP_HTTPD_SUPPORT_11_KEEPALIVE vs. - LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED) - - 2017-02-08: Dirk Ziegelmeier - * Rename "IPv6 mapped IPv4 addresses" to their correct name from RFC4191: - "IPv4-mapped IPv6 address" - - 2017-02-08: Luc Revardel - * mld6.c: Fix bug #50220 (mld6_leavegroup does not send ICMP6_TYPE_MLD, even - if last reporter) - - 2017-02-08: David van Moolenbroek - * ip6.c: Patch #9250: fix source substitution in ip6_output_if() - - 2017-02-08: Simon Goldschmidt - * tcp_out.c: Fixed bug #50090 (last_unsent->oversize_left can become wrong value - in tcp_write error path) - - 2017-02-02: Dirk Ziegelmeier - * Fix bug #50206: UDP Netconn bind to IP6_ADDR_ANY fails - - 2017-01-18: Dirk Ziegelmeier - * Fix zero-copy RX, see bug bug #50064. PBUF_REFs were not supported as ARP requests. - - 2017-01-15: Axel Lin, Dirk Ziegelmeier - * minor bug fixes in mqtt - - 2017-01-11: Knut Andre Tidemann - * sockets/netconn: fix broken default ICMPv6 handling of checksums - -(STABLE-2.0.1) - - ++ New features: - - 2016-12-31: Simon Goldschmidt - * tcp.h/.c: added function tcp_listen_with_backlog_and_err() to get the error - reason when listening fails (bug #49861) - - 2016-12-20: Erik Andersen - * Add MQTT client - - 2016-12-14: Jan Breuer: - * opt.h, ndc.h/.c: add support for RDNSS option (as per RFC 6106) - - 2016-12-14: David van Moolenbroek - * opt.h, nd6.c: Added LWIP_HOOK_ND6_GET_GW() - - 2016-12-09: Dirk Ziegelmeier - * ip6_frag.c: Implemented support for LWIP_NETIF_TX_SINGLE_PBUF - - 2016-12-09: Simon Goldschmidt - * dns.c: added one-shot multicast DNS queries - - 2016-11-24: Ambroz Bizjak, David van Moolenbroek - * tcp_out.c: Optimize passing contiguous nocopy buffers to tcp_write (bug #46290) - - 2016-11-16: Dirk Ziegelmeier - * sockets.c: added support for IPv6 mapped IPv4 addresses - - ++ Bugfixes: - - 2016-12-16: Thomas Mueller - * api_lib.c: fixed race condition in return value of netconn_gethostbyname() - (and thus also lwip_gethostbyname/_r() and lwip_getaddrinfo()) - - 2016-12-15: David van Moolenbroek - * opt.h, tcp: added LWIP_HOOK_TCP_ISN() to implement less predictable initial - sequence numbers (see contrib/addons/tcp_isn for an example implementation) - - 2016-12-05: Dirk Ziegelmeier - * fixed compiling with IPv4 disabled (IPv6 only case) - - 2016-11-28: Simon Goldschmidt - * api_lib.c: fixed bug #49725 (send-timeout: netconn_write() can return - ERR_OK without all bytes being written) - - 2016-11-28: Ambroz Bizjak - * tcpi_in.c: fixed bug #49717 (window size in received SYN and SYN-ACK - assumed scaled) - - 2016-11-25: Simon Goldschmidt - * dhcp.c: fixed bug #49676 (Possible endless loop when parsing dhcp options) - - 2016-11-23: Dirk Ziegelmeier - * udp.c: fixed bug #49662: multicast traffic is now only received on a UDP PCB - (and therefore on a UDP socket/netconn) when the PCB is bound to IP_ADDR_ANY - - 2016-11-16: Dirk Ziegelmeier - * *: Fixed dual-stack behaviour, IPv6 mapped IPv4 support in socket API - - 2016-11-14: Joel Cunningham - * tcp_out.c: fixed bug #49533 (start persist timer when unsent seg can't fit - in window) - - 2016-11-16: Roberto Barbieri Carrera - * autoip.c: fixed bug #49610 (sometimes AutoIP fails to reuse the same address) - - 2016-11-11: Dirk Ziegelmeier - * sockets.c: fixed bug #49578 (dropping multicast membership does not work - with LWIP_SOCKET_OFFSET) - -(STABLE-2.0.0) - - ++ New features: - - 2016-07-27: Simon Goldschmidt - * opt.h, timeouts.h/.c: added LWIP_TIMERS_CUSTOM to override the default - implementation of timeouts - - 2016-07-xx: Dirk Ziegelmeier - * Large overhaul of doxygen documentation - - 2016-04-05: Simon Goldschmidt - * timers.h/.c: prepare for overriding current timeout implementation: all - stack-internal caclic timers are avaliable in the lwip_cyclic_timers array - - 2016-03-23: Simon Goldschmidt - * tcp: call accept-callback with ERR_MEM when allocating a pcb fails on - passive open to inform the application about this error - ATTENTION: applications have to handle NULL pcb in accept callback! - - 2016-02-22: Ivan Delamer - * Initial 6LoWPAN support - - 2016-02-XX to 2016-03-XX: Dirk Ziegelmeier - * Cleanup TCPIP thread sync methods in a way that it is possibe to use them - in arbitrary code that needs things to be done in TCPIP thread. Used to - decouple netconn, netif, ppp and 6LoWPAN from LWIP core. - - 2016-02-XX: Dirk Ziegelmeier - * Implement dual-stack support in RAW, UDP and TCP. Add new IP address - type IPADDR_ANY_TYPE for this. Netconn/Socket API: Dual-stack is - automatically supported when an IPv6 netconn/socket is created. - - 2015-12-26: Martin Hentschel and Dirk Ziegelmeier - * Rewrite SNMP agent. SNMPv2c + MIB compiler. - - 2015-11-12: Dirk Ziegelmeier - * Decouple SNMP stack from lwIP core and move stack to apps/ directory. - Breaking change: Users have to call snmp_init() now! - - 2015-11-12: Dirk Ziegelmeier - * Implement possibility to declare private memory pools. This is useful to - decouple some apps from the core (SNMP stack) or make contrib app usage - simpler (httpserver_raw) - - 2015-10-09: Simon Goldschmidt - * started to move "private" header files containing implementation details to - "lwip/priv/" include directory to seperate the API from the implementation. - - 2015-10-07: Simon Goldschmidt - * added sntp client as first "supported" application layer protocol implementation - added 'apps' folder - - 2015-09-30: Dirk Ziegelmeier - * snmp_structs.h, mib_structs.c, mib2.c: snmp: fixed ugly inheritance - implementation by aggregating the "base class" (struct mib_node) in all - derived node classes to get more type-safe code - - 2015-09-23: Simon Goldschmidt - * netif.h/.c, nd6.c: task #13729: Convert netif addresses (IPv4 & IPv6) to - ip_addr_t (so they can be used without conversion/temporary storage) - - 2015-09-08: Dirk Ziegelmeier - * snmp: Separate mib2 counter/table callbacks from snmp agent. This both cleans - up the code and should allow integration of a 3rd party agent/mib2. Simple - counters are kept in MIB2_STATS, tree/table change function prototypes moved to - snmp_mib2.h. - - 2015-09-03: Simon Goldschmidt - * opt.h, dns.h/.c: DNS/IPv6: added support for AAAA records - - 2015-09-01: Simon Goldschmidt - * task #12178: hardware checksum capabilities can be configured per netif - (use NETIF_SET_CHECKSUM_CTRL() in your netif's init function) - - 2015-08-30: Simon Goldschmidt - * PBUF_REF with "custom" pbufs is now supported for RX pbufs (see pcapif in - contrib for an example, LWIP_SUPPORT_CUSTOM_PBUF is required) - - 2015-08-30: Simon Goldschmidt - * support IPv4 source based routing: define LWIP_HOOK_IP4_ROUTE_SRC to point - to a routing function - - 2015-08-05: Simon Goldschmidt - * many files: allow multicast socket options IP_MULTICAST_TTL, IP_MULTICAST_IF - and IP_MULTICAST_LOOP to be used without IGMP - - 2015-04-24: Simon Goldschmidt - * dhcp.h/c, autoip.h/.c: added functions dhcp/autoip_supplied_address() to - check for the source of address assignment (replacement for NETIF_FLAG_DHCP) - - 2015-04-10: Simon Goldschmidt - * many files: task #13480: added LWIP_IPV4 define - IPv4 can be disabled, - leaving an IPv6-only stack - - 2015-04-09: Simon Goldschmidt - * nearly all files: task #12722 (improve IPv4/v6 address handling): renamed - ip_addr_t to ip4_addr_t, renamed ipX_addr_t to ip_addr_t and added IP - version; ip_addr_t is used for all generic IP addresses for the API, - ip(4/6)_addr_t are only used internally or when initializing netifs or when - calling version-related functions - - 2015-03-24: Simon Goldschmidt - * opt.h, ip4_addr.h, ip4.c, ip6.c: loopif is not required for loopback traffic - any more but passed through any netif (ENABLE_LOOPBACK has to be enabled) - - 2015-03-23: Simon Goldschmidt - * opt.h, etharp.c: with ETHARP_TABLE_MATCH_NETIF== 1, duplicate (Auto)-IP - addresses on multiple netifs should now be working correctly (if correctly - addressed by routing, that is) - - 2015-03-23: Simon Goldschmidt - * etharp.c: Stable etharp entries that are about to expire are now refreshed - using unicast to prevent unnecessary broadcast. Only if no answer is received - after 15 seconds, broadcast is used. - - 2015-03-06: Philip Gladstone - * netif.h/.c: patch #8359 (Provide utility function to add an IPv6 address to - an interface) - - 2015-03-05: Simon Goldschmidt - * netif.c, ip4.c, dhcp.c, autoip.c: fixed bug #37068 (netif up/down handling - is unclear): correclty separated administrative status of a netif (up/down) - from 'valid address' status - ATTENTION: netif_set_up() now always has to be called, even when dhcp/autoip - is used! - - 2015-02-26: patch by TabascoEye - * netif.c, udp.h/.c: fixed bug #40753 (re-bind UDP pcbs on change of IP address) - - 2015-02-22: chrysn, Simon Goldschmidt - * *.*: Changed nearly all functions taking 'ip(X)_addr_t' pointer to take - const pointers (changed user callbacks: raw_recv_fn, udp_recv_fn; changed - port callbacks: netif_output_fn, netif_igmp_mac_filter_fn) - - 2015-02-19: Ivan Delamer - * netif.h, dhcp.c: Removed unused netif flag for DHCP. The preferred way to evaluate - if DHCP is active is through netif->dhcp field. - - 2015-02-19: Ivan Delamer - * netif.h, slipif.c, ppp.c: Removed unused netif flag for point to point connections - - 2015-02-18: Simon Goldschmidt - * api_lib.c: fixed bug #37958 "netconn API doesn't handle correctly - connections half-closed by peer" - - 2015-02-18: Simon Goldschmidt - * tcp.c: tcp_alloc() prefers killing CLOSING/LAST_ACK over active connections - (see bug #39565) - - 2015-02-16: Claudius Zingerli, Sergio Caprile - * opt.h, dhcp.h/.c: patch #8361 "Add support for NTP option in DHCP" - - 2015-02-14: Simon Goldschmidt - * opt.h, snmp*: added support for write-access community and dedicated - community for sending traps - - 2015-02-13: Simon Goldschmidt - * opt.h, memp.c: added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when - a memp pool was empty and an item is now available - - 2015-02-13: Simon Goldschmidt - * opt.h, pbuf.h/.c, etharp.c: Added the option PBUF_LINK_ENCAPSULATION_HLEN to - allocate additional header space for TX on netifs requiring additional headers - - 2015-02-12: chrysn - * timers.h/.c: introduce sys_timeouts_sleeptime (returns the time left before - the next timeout is due, for NO_SYS==1) - - 2015-02-11: Nick van Ijzendoorn - * opt.h, sockets.h/c: patch #7702 "Include ability to increase the socket number - with defined offset" - - 2015-02-11: Frederick Baksik - * opt.h, def.h, others: patch #8423 "arch/perf.h" should be made an optional item - - 2015-02-11: Simon Goldschmidt - * api_msg.c, opt.h: started to implement fullduplex sockets/netconns - (note that this is highly unstable yet!) - - 2015-01-17: Simon Goldschmidt - * api: allow enabling socket API without (public) netconn API - netconn API is - still used by sockets, but keeping it private (static) should allow better - compiler optimizations - - 2015-01-16: Simon Goldschmidt - * tcp_in.c: fixed bug #20506 "Initial congestion window is very small" again - by implementing the calculation formula from RFC3390 - - 2014-12-10: Simon Goldschmidt - * api: added option LWIP_NETCONN_SEM_PER_THREAD to use a semaphore per thread - instead of using one per netconn and per select call - - 2014-12-08: Simon Goldschmidt - * ip6.h: fixed bug #43778: IPv6 header version not set on 16-bit platform - (macro IP6H_VTCFL_SET()) - - 2014-12-08: Simon Goldschmidt - * icmp.c, ip4.c, pbuf.c, udp.c, pbuf.h: task #11472 Support PBUF_REF for RX - (IPv6 and IPv4/v6 reassembly might not work yet) - - 2014-11-06: Simon Goldschmidt - * sockets.c/.h, init.c: lwip_socket_init() is not needed any more - -> compatibility define - - 2014-09-16: Simon Goldschmidt - * dns.c, opt.h: reduced ram usage by parsing DNS responses in place - - 2014-09-16: Simon Goldschmidt - * pbuf.h/.c: added pbuf_take_at() and pbuf_put_at() - - 2014-09-15: Simon Goldschmidt - * dns.c: added source port randomization to make the DNS client more robust - (see bug #43144) - - 2013-09-02: Simon Goldschmidt - * arch.h and many other files: added optional macros PACK_STRUCT_FLD_8() and - PACK_STRUCT_FLD_S() to prevent gcc 4 from warning about struct members that - do not need packing - - 2013-08-19: Simon Goldschmidt - * netif.h: bug #42998: made NETIF_MAX_HWADDR_LEN overridable for some special - networks - - 2013-03-17: Simon Goldschmidt (patch by Ghobad Emadi) - * opt.h, etharp.c: Added LWIP_HOOK_ETHARP_GET_GW to implement IPv4 routing with - multiple gateways - - 2013-04-20: Fatih Asici - * opt.h, etharp.h/.c: patch #7993: Added support for transmitting packets - with VLAN headers via hook function LWIP_HOOK_VLAN_SET and to check them - via hook function LWIP_HOOK_VLAN_CHECK - - 2014-02-20: Simon Goldschmidt (based on patch by Artem Pisarenko) - * patch #7885: modification of api modules to support FreeRTOS-MPU - (don't pass stack-pointers to other threads) - - 2014-02-05: Simon Goldschmidt (patch by "xtian" and "alex_ab") - * patch #6537/#7858: TCP window scaling support - - 2014-01-17: Jiri Engelthaler - * icmp, icmp6, opt.h: patch #8027: Completed HW checksuming for IPv4 and - IPv6 ICMP's - - 2012-08-22: Sylvain Rochet - * New PPP stack for lwIP, developed in ppp-new branch. - Based from pppd 2.4.5, released 2009-11-17, with huge changes to match - code size and memory requirements for embedded devices, including: - - Gluing together the previous low-level PPP code in lwIP to pppd 2.4.5, which - is more or less what pppd sys-* files are, so that we get something working - using the unix port. - - Merged some patchs from lwIP Git repository which add interesting features - or fix bugs. - - Merged some patchs from Debian pppd package which add interesting features - or fix bugs. - - Ported PPP timeout handling to the lwIP timers system - - Disabled all the PPP code using filesystem access, replaced in necessary cases - to configuration variables. - - Disabled all the PPP code forking processes. - - Removed IPX support, lwIP does not support IPX. - - Ported and improved random module from the previous PPP port. - - Removed samba TDB (file-driven database) usage, because it needs a filesystem. - - MS-CHAP required a DES implementation, we added the latest PolarSSL DES - implementation which is under a BSD-ish license. - - Also switched to PolarSSL MD4,MD5,SHA1 implementations, which are meant to be - used in embedded devices with reduced memory footprint. - - Removed PPP configuration file parsing support. - - Added macro definition EAP_SUPPORT to make EAP support optional. - - Added macro definition CHAP_SUPPORT to make CHAP support optional. - - Added macro definition MSCHAP_SUPPORT to make MSCHAP support optional. - - Added macro definition PAP_SUPPORT to make PAP support optional. - - Cleared all Linux syscall calls. - - Disabled demand support using a macro, so that it can be ported later. - - Disabled ECP support using a macro, so that it can be ported later. - - Disabled CCP support using a macro, so that it can be ported later. - - Disabled CBCP support using a macro, so that it can be ported later. - - Disabled LQR support using a macro, so that it can be ported later. - - Print packet debug feature optional, through PRINTPKT_SUPPORT - - Removed POSIX signal usage. - - Fully ported PPPoS code from the previous port. - - Fully ported PPPoE code from the previous port. - - Fully ported VJ compression protocol code from the previous port. - - Removed all malloc()/free() use from PPP, replaced by stack usage or PBUF. - - Disabled PPP server support using a macro, so that it can be ported later. - - Switched all PPP debug to lwIP debug system. - - Created PPP Control Block (PPP PCB), removed PPP unit integer everywhere, - removed all global variables everywhere, did everything necessary for - the PPP stack to support more than one PPP session (pppd only support - one session per process). - - Removed the statically allocated output buffer, now using PBUF. - - Improved structure size of all PPP modules, deep analyze of code to reduce - variables size to the bare minimum. Switched all boolean type (char type in - most architecture) to compiler generated bitfields. - - Added PPP IPv6 support, glued lwIP IPv6 support to PPP. - - Now using a persistent netif interface which can then be used in lwIP - functions requiring a netif. - - Now initializing PPP in lwip_init() function. - - Reworked completely the PPP state machine, so that we don't end up in - anymore in inconsistent state, especially with PPPoE. - - Improved the way we handle PPP reconnection after disconnect, cleaning - everything required so that we start the PPP connection again from a - clean state. - - Added PPP holdoff support, allow the lwIP user to wait a little bit before - reconnecting, prevents connection flood, especially when using PPPoL2TP. - - Added PPPoL2TP LAC support (a.k.a. UDP tunnels), adding a VPN client - feature to lwIP, L2TP being a widely used tunnel protocol. - - Switched all used PPP types to lwIP types (u8t, u16t, u32t, ...) - - Added PPP API "sequential" thread-safe API, based from NETIFAPI. - - 2011-07-21: Simon Goldschmidt - * sockets.c, opt.h: (bug #30185): added LWIP_FIONREAD_LINUXMODE that makes - ioctl/FIONREAD return the size of the next pending datagram. - - 2011-05-25: Simon Goldschmidt - * again nearly the whole stack, renamed ip.c to ip4.c, ip_addr.c to ip4_addr.c, - combined ipv4/ipv6 inet_chksum.c, added ip.h, ip_addr.h: Combined IPv4 - and IPv6 code where possible, added defines to access IPv4/IPv6 in non-IP - code so that the code is more readable. - - 2011-05-17: Patch by Ivan Delamer (only checked in by Simon Goldschmidt) - * nearly the whole stack: Finally, we got decent IPv6 support, big thanks to - Ivan! (this is work in progress: we're just post release anyway :-) - - - ++ Bugfixes: - - 2016-08-23: Simon Goldschmidt - * etharp: removed ETHARP_TRUST_IP_MAC since it is insecure and we don't need - it any more after implementing unicast ARP renewal towards arp entry timeout - - 2016-07-20: Simon Goldschmidt - * memp.h/.c: fixed bug #48442 (memp stats don't work for MEMP_MEM_MALLOC) - - 2016-07-21: Simon Goldschmidt (patch by Ambroz Bizjak) - * tcp_in.c, tcp_out.c: fixed bug #48543 (TCP sent callback may prematurely - report sent data when only part of a segment is acked) and don't include - SYN/FIN in snd_buf counter - - 2016-07-19: Simon Goldschmidt - * etharp.c: fixed bug #48477 (ARP input packet might update static entry) - - 2016-07-11: Simon Goldschmidt - * tcp_in.c: fixed bug #48476 (TCP sent callback called wrongly due to picking - up old pcb->acked - - 2016-06-30: Simon Goldschmidt (original patch by Fabian Koch) - * tcp_in.c: fixed bug #48170 (Vulnerable to TCP RST spoofing) - - 2016-05-20: Dirk Ziegelmeier - * sntp.h/.c: Fix return value of sntp_getserver() call to return a pointer - - 2016-04-05: Simon Goldschmidt (patch by Philip Gladstone) - * udp.c: patch #8358: allow more combinations of listening PCB for IPv6 - - 2016-04-05: Simon Goldschmidt - * netconn/socket API: fixed bug# 43739 (Accept not reporting errors about - aborted connections): netconn_accept() returns ERR_ABRT (sockets: ECONNABORTED) - for aborted connections, ERR_CLSD (sockets: EINVAL) if the listening netconn - is closed, which better seems to follow the standard. - - 2016-03-23: Florent Matignon - * dhcp.c: fixed bug #38203: DHCP options are not recorded in all DHCP ack messages - - 2016-03-22: Simon Goldschmidt - * tcp: changed accept handling to be done internally: the application does not - have to call tcp_accepted() any more. Instead, when delaying accept (e.g. sockets - do), call tcp_backlog_delayed()/tcp_backlog_accepted() (fixes bug #46696) - - 2016-03-22: Simon Goldschmidt - * dns.c: ignore dns response parsing errors, only abort resolving for correct - responses or error responses from correct server (bug #47459) - - 2016-03-17: Simon Goldschmidt - * api_msg.c: fixed bug #47448 (netconn/socket leak if RST is received during close) - - 2016-03-17: Joel Cunningham - * api_msg.c: don't fail closing a socket/netconn when failing to allocate the - FIN segment; blocking the calling thread for a while is better than risking - leaking a netconn/socket (see bug #46701) - - 2016-03-16: Joel Cunningham - * tcp_out.c: reset rto timer on fast retransmission - - 2016-03-16: Deomid Ryabkov - * tcp_out.c: fixed bug #46384 Segment size calculation bug with MSS != TCP_MSS - - 2016-03-05: Simon Goldschmidt - * err.h/.c, sockets.c: ERR_IF is not necessarily a fatal error - - 2015-11-19: fix by Kerem Hadimli - * sockets.c: fixed bug #46471: lwip_accept() leaks socket descriptors if new - netconn was already closed because of peer behavior - - 2015-11-12: fix by Valery Ushakov - * tcp_in.c: fixed bug #46365 tcp_accept_null() should call tcp_abort() - - 2015-10-02: Dirk Ziegelmeier/Simon Goldschmidt - * snmp: cleaned up snmp structs API (fixed race conditions from bug #46089, - reduce ram/rom usage of tables): incompatible change for private MIBs - - 2015-09-30: Simon Goldschmidt - * ip4_addr.c: fixed bug #46072: ip4addr_aton() does not check the number range - of all address parts - - 2015-08-28: Simon Goldschmidt - * tcp.c, tcp_in.c: fixed bug #44023: TCP ssthresh value is unclear: ssthresh - is set to the full send window for active open, too, and is updated once - after SYN to ensure the correct send window is used - - 2015-08-28: Simon Goldschmidt - * tcp: fixed bug #45559: Window scaling casts u32_t to u16_t without checks - - 2015-08-26: Simon Goldschmidt - * ip6_frag.h/.c: fixed bug bug #41009: IPv6 reassembly broken on 64-bit platforms: - define IPV6_FRAG_COPYHEADER==1 on these platforms to copy the IPv6 header - instead of referencing it, which gives more room for struct ip6_reass_helper - - 2015-08-25: Simon Goldschmidt - * sockets.c: fixed bug #45827: recvfrom: TCP window is updated with MSG_PEEK - - 2015-08-20: Manoj Kumar - * snmp_msg.h, msg_in.c: fixed bug #43790: Sending octet string of Length >255 - from SNMP agent - - 2015-08-19: Jens Nielsen - * icmp.c, ip4.c, tcp_in.c, udp.c, raw.c: fixed bug #45120: Broadcast & multiple - interfaces handling - - 2015-08-19: Simon Goldschmidt (patch by "Sandra") - * dns.c: fixed bug #45004: dns response without answer might be discarded - - 2015-08-18: Chrysn - * timers.c: patch #8704 fix sys_timeouts_sleeptime function - - 2015-07-01: Erik Ekman - * puf.c: fixed bug #45454 (pbuf_take_at() skips write and returns OK if offset - is at start of pbuf in chain) - - 2015-05-19: Simon Goldschmidt - * dhcp.h/.c: fixed bugs #45140 and #45141 (dhcp was not stopped correctly after - fixing bug #38204) - - 2015-03-21: Simon Goldschmidt (patch by Homyak) - * tcp_in.c: fixed bug #44766 (LWIP_WND_SCALE: tcphdr->wnd was not scaled in - two places) - - 2015-03-21: Simon Goldschmidt - * tcp_impl.h, tcp.c, tcp_in.c: fixed bug #41318 (Bad memory ref in tcp_input() - after tcp_close()) - - 2015-03-21: Simon Goldschmidt - * tcp_in.c: fixed bug #38468 (tcp_sent() not called on half-open connection for - data ACKed with the same ack as FIN) - - 2015-03-21: Simon Goldschmidt (patch by Christoffer Lind) - * dhcp.h/.c: fixed bug #38204 (DHCP lease time not handled correctly) - - 2015-03-20: Simon Goldschmidt - * dhcp.c: fixed bug #38714 (Missing option and client address in DHCPRELEASE message) - - 2015-03-19: Simon Goldschmidt - * api.h, tcpip.h, api_lib.c, api_msg.c: fixed race conditions in assigning - netconn->last_err (fixed bugs #38121 and #37676) - - 2015-03-09: Simon Goldschmidt - * ip4.c: fixed the IPv4 part of bug #43904 (ip_route() must detect linkup status) - - 2015-03-04: Simon Goldschmidt - * nd6.c: fixed bug #43784 (a host should send at least one Router Solicitation) - - 2015-03-04: Valery Ushakov - * ip6.c: fixed bug #41094 (Byte-order bug in IPv6 fragmentation header test) - - 2015-03-04: Zach Smith - * nd6.c: fixed bug #38153 (nd6_input() byte order issues) - - 2015-02-26: Simon Goldschmidt - * netif.c, tcp.h/.c: fixed bug #44378 (TCP connections are not aborted on netif - remove) - - 2015-02-25: Simon Goldschmidt - * ip4.c, etharp.c: fixed bug #40177 (System hangs when dealing with corrupted - packets), implemented task #12357 (Ensure that malicious packets don't - assert-fail): improved some pbuf_header calls to not assert-fail. - - 2015-02-25: patch by Joel Cunningham - * udp.h/.c, sockets.c: fixed bug #43028 (IP_MULTICAST_TTL affects unicast - datagrams) - - 2015-02-25: patch by Greg Renda - * ip4_frag.c: fixed bug #38210 (ip reassembly while remove oldest datagram) - - 2015-02-25: Simon Goldschmidt - * sockets.c: fixed bug #38165 (socket with mulicast): ensure igmp membership - are dropped when socket (not netconn!) is closed. - - 2015-02-25: Simon Goldschmidt - * ip4.h/.c, udp.c: fixed bug #38061 (wrong multicast routing in IPv4) by - adding an optional default netif for multicast routing - - 2015-02-25: Simon Goldschmidt - * netconn API: fixed that netconn_connect still used message passing for - LWIP_TCPIP_CORE_LOCKING==1 - - 2015-02-22: patch by Jens Nielsen - * icmp.c: fixed bug #38803 (Source address in broadcast ping reply) - - 2015-02-22: Simon Goldschmidt - * udp.h, sockets.c: added proper accessor functions for pcb->multicast_ip - (previously used by get/setsockopt only) - - 2015-02-18: Simon Goldschmidt - * sockets.c: Fixed select not reporting received FIN as 'readable' in certain - rare cases (bug #43779: select(), close(), and TCP retransmission error) - - 2015-02-17: Simon Goldschmidt - * err.h, sockets.c, api_msg.c: fixed bug #38853 "connect() use a wrong errno": - return ERR_ALREADY/EALRADY during connect, ERR_ISCONN/EISCONN when already - connected - - 2015-02-17: Simon Goldschmidt - * tcp_impl.h, tcp_out.c, tcp.c, api_msg.c: fixed bug #37614 "Errors from - ipX_output are not processed". Now tcp_output(_segment) checks for the return - value of ipX_output and does not try to send more on error. A netif driver - can call tcp_txnow() (from tcpip_thread!) to try to send again if TX buffers - are available again. - - 2015-02-14: patches by Freddie Chopin - * snmp*: made community writable, fixed some const pointers - - 2015-02-13: Simon Goldschmidt - * msg_in.c: fixed bug #22070 "MIB_OBJECT_WRITE_ONLY not implemented in SNMP" - - 2015-02-12: Simon Goldschmidt - * ip.h, ip4.c, ip6.c: fixed bug #36403 "ip4_input() and ip6_input() always pass - inp to higher layers": now the accepting netif is passed up, but the input - netif is available through ip_current_input_netif() if required. - - 2015-02-11: patch by hichard - * tcpip.c: fixed bug #43094 "The function tcpip_input() forget to handle IPv6" - - 2015-02-10: Simon Goldschmidt - * netconn API: fixed that netconn_close/netconn_delete still used message passing - for LWIP_TCPIP_CORE_LOCKING==1 - - 2015-02-10: Simon Goldschmidt - * netconn/socket api: fixed bug #44225 "closing TCP socket should time out - eventually", implemented task #6930 "Implement SO_LINGER": closing TCP sockets - times out after 20 seconds or after the configured SND_TIMEOUT or depending - on the linger settings. - - 2015-01-27: Simon Goldschmidt - * api_msg.c: fixed that SHUT_RD followed by SHUT_WR was different to SHUT_RDWR, - fixed return value of lwip_netconn_do_close on unconnected netconns - - 2015-01-17: Simon Goldschmidt - * sockets.c: fixed bug #43361 select() crashes with stale FDs - - 2015-01-17: Simon Goldschmidt - * sockets.c/.h, memp_std.h: fixed bug #40788 "lwip_setsockopt_internal() crashes" - by rewriting set/getsockopt functions to combine checks with the actual code - and add more NULL checks; this also fixes that CORE_LOCKING used message - passing for set/getsockopt. - - 2014-12-19: Simon Goldschmidt - * opt.h, dhcp.h/.c: prevent dhcp from starting when netif link is down (only - when LWIP_DHCP_CHECK_LINK_UP==1, which is disabled by default for - compatibility reasons) - - 2014-12-17: Simon Goldschmidt - * tcp_out.c: fixed bug #43840 Checksum error for TCP_CHECKSUM_ON_COPY==1 for - no-copy data with odd length - - 2014-12-10: Simon Goldschmidt - * sockets.c, tcp.c, others: fixed bug #43797 set/getsockopt: SO_SNDTIMEO/SO_RCVTIMEO - take int as option but should take timeval (LWIP_SO_SNDRCVTIMEO_STANDARD==0 can - be used to revert to the old 'winsock' style behaviour) - Fixed implementation of SO_ACCEPTCONN to just look at the pcb state - - 2014-12-09: Simon Goldschmidt - * ip4.c: fixed bug #43596 IGMP queries from 0.0.0.0 are discarded - - 2014-10-21: Simon Goldschmidt (patch by Joel Cunningham and Albert Huitsing) - * sockts.c: fixed bugs #41495 Possible threading issue in select() and #43278 - event_callback() handle context switch when calling sys_sem_signal() - - 2014-10-21: Simon Goldschmidt - * api_msg.c: fixed bug #38219 Assert on TCP netconn_write with sndtimeout set - - 2014-09-16: Kevin Cernekee - * dns.c: patch #8480 Fix handling of dns_seqno wraparound - - 2014-09-16: Simon Goldschmidt - * tcp_out.c: fixed bug #43192 tcp_enqueue_flags() should not check TCP_SND_QUEUELEN - when sending FIN - - 2014-09-03: Simon Goldschmidt - * msg_in.c: fixed bug #39355 SNMP Memory Leak in case of error - - 2014-09-02: Simon Goldschmidt - * err.h/.c, sockets.c, api_msg.c: fixed bug #43110 call getpeername() before - listen() will cause a error - - 2014-09-02: Simon Goldschmidt - * sockets.c: fixed bug #42117 lwip_fcntl does not set errno - - 2014-09-02: Simon Goldschmidt - * tcp.c: fixed bug #42299 tcp_abort() leaves freed pcb on tcp_bound_pcbs list - - 2014-08-20: Simon Goldschmidt - * dns.c: fixed bug #42987 lwIP is vulnerable to DNS cache poisoning due to - non-randomized TXIDs - - 2014-06-03: Simon Goldschmidt - * tcp_impl.h, tcp_in.c: fixed bug #37969 SYN packet dropped as short packet in - tcp_input function - - 2014-05-20: Simon Goldschmidt - * tcp_out.c: fixed bug #37184 tcp_write problem for pcbs in the SYN_SENT state - - 2014-05-19: Simon Goldschmidt - * *.h: Fixed bug #35874 reserved identifier violation (removed leading underscores - from header include guards) - - 2014-04-08: Simon Goldschmidt - * tcp.c: Fixed bug #36167 tcp server crash when client closes (maximum window) - - 2014-04-06: Simon Goldschmidt - * tcp_in.c: Fixed bug #36210 lwIP does not elicit an empty ACK when received - unacceptable ACK - - 2014-04-06: Simon Goldschmidt - * dhcp.c, ip4.c/.h, ip6.c/.h, udp.c/.h, ip.h: Fixed bug #41787 DHCP Discovery - is invalid when an IP is set to thet netif. - - 2014-03-14: Simon Goldschmidt - * tcp_out.c: Fixed bug #36153 TCP Cheksum error if LWIP_CHECKSUM_ON_COPY=1 - - 2014-03-11: Simon Goldschmidt (patch by Mason) - * opt.h, sockets.c: fixed bug #35928 BSD sockets functions must set errno for - POSIX-compliance - - 2014-02-27: Simon Goldschmidt - * dhcp.c: fixed bug #40303 DHCP xid renewed when sending a DHCPREQUEST - - 2014-02-27: Simon Goldschmidt - * raw.c: fixed bug #41680 raw socket can not receive IPv6 packet when - IP_SOF_BROADCAST_RECV==1 - - 2014-02-27: Simon Goldschmidt - * api_msg.c, sockets.c: fixed bug #38404 getpeeraddr returns success on - unconnected/listening TCP sockets - - 2014-02-27: Simon Goldschmidt - * sockets.c: fixed bug #41729 Some socket functions return Exyz instead of -1 - - 2014-02-25: Simon Goldschmidt - * ip4.c: fixed bug #39514 ip_route() may return an IPv6-only interface - - 2014-02-25: Simon Goldschmidt, patch by Fatih Asici - * pbuf.c: fixed bug #39356 Wrong increment in pbuf_memfind() - - 2014-02-25: Simon Goldschmidt - * netif.c/.h, udp.c: fixed bug #39225 udp.c uses netif_matches_ip6_addr() incorrectly; - renamed function netif_matches_ip6_addr() to netif_get_ip6_addr_match() - - 2014-02-25: Simon Goldschmidt - * igmp.c: fixed bug #39145 IGMP membership report for 224.0.0.1 - - 2014-02-22: Simon Goldschmidt (patch by Amir Shalem) - * etharp.c, opt.h: fixed bug #34681 Limit ARP queue length by ARP_QUEUE_LEN (=3) - - 2014-02-22: Simon Goldschmidt (patch by Amir Shalem) - * etharp.h/.c: fixed bug #34682 Limit ARP request flood for unresolved entry - - 2014-02-20: Simon Goldschmidt - * tcp_out.c: fixed bug #39683 Assertion "seg->tcphdr not aligned" failed with - MEM_ALIGNMENT = 8 - - 2014-02-20: Simon Goldschmidt - * sockets.c: fixed bug #39882 No function shall set errno to 0 - - 2014-02-20: Simon Goldschmidt - * mib_structs.c: fixed bug #40050 SNMP problem with MIB arrays > 255 - - 2014-02-20: Simon Goldschmidt - * api.h, sockets.c: fixed bug #41499 netconn::recv_avail can overflow - - 2014-01-08: Stathis Voukelatos - * memp_std.h: patch #7928 Fixed size calculation in MALLOC memory pool - creation macro - - 2014-01-18: Brian Fahs - * tcp_out.c: patch #8237: tcp_rexmit_rto fails to update pcb->unsent_oversize - when necessary - - 2014-01-17: Grant Erickson, Jay Logue, Simon Goldschmidt - * ipv6.c, netif.c: patch #7913 Enable Support for IPv6 Loopback - - 2014-01-16: Stathis Voukelatos - * netif.c: patch #7902 Fixed netif_poll() operation when LWIP_LOOPBACK_MAX_PBUFS > 0 - - 2014-01-14: "Freddie Chopin" - * snmp.h, mib2.c: fixed constness and spelling of sysdescr - - 2014-01-14: Simon Goldschmidt (patch by Thomas Faber) - * tcpip.c: patch #8241: Fix implicit declaration of ip_input with - LWIP_TCPIP_CORE_LOCKING_INPUT disabled - - 2014-01-14: chrysn - * timers.c: patch #8244 make timeouts usable reliably from outside of the - timeout routine - - 2014-01-10: Simon Goldschmidt - * ip_frag.c, ip6_frag.c: fixed bug #41041 Potential use-after-free in IPv6 reassembly - - 2014-01-10: Simon Goldschmidt - * memp.c: fixed bug #41188 Alignment error in memp_init() when MEMP_SEPARATE_POOLS==1 - - 2014-01-10: Simon Goldschmidt - * tcp.c: fixed bug #39898 tcp_fasttmr() possible lock due to infinte queue process loop - - 2013-06-29: Simon Goldschmidt - * inet.h, sockets.h: partially fixed bug #37585: IPv6 compatibility (in socket structs) - - 2013-06-29: Simon Goldschmidt - * inet6.h: bug #37585/task #12600: fixed struct in6_addr.s6_addr to conform to spec - - 2013-04-24: patch by Liam - * api_msg.c: patch #8008 Fix a potential null pointer dereference in assert - - 2013-04-24: Simon Goldschmidt - * igmp.c: fixed possible division by zero - - 2013-04-24: Simon Goldschmidt - * ip6.h, some ipv6 C files: fixed bug #38526 Coverity: Recursive Header Inclusion in ip6.h - - 2013-04-24: Simon Goldschmidt (patch by Emil Ljungdahl): - * netif.c: fixed bug #38586 netif_loop_output() "deadlocks" - - 2013-01-15: Simon Goldschmidt - * ip4.c: fixed bug #37665 ip_canforward operates on address in wrong byte order - - 2013-01-15: Simon Goldschmidt - * pbuf.h: fixed bug #38097 pbuf_free_ooseq() warning - - 2013-01-14: Simon Goldschmidt - * dns.c: fixed bug #37705 Possible memory corruption in DNS query - - 2013-01-11: Simon Goldschmidt - * raw.c: fixed bug #38066 Raw pcbs can alter packet without eating it - - 2012-08-22: Simon Goldschmidt - * memp.c: fixed bug #37166: memp_sanity check loops itself - - 2012-08-13: Simon Goldschmidt - * dhcp.c: fixed bug #36645: Calling dhcp_release before dhcp_start - dereferences NULL - - 2012-08-13: Simon Goldschmidt - * msg_out.c: fixed bug #36840 snmp_send_trap() NULL de-reference if traps - configured but no interfaces available - - 2012-08-13: Simon Goldschmidt - * dns.c: fixed bug #36899 DNS TTL 0 is cached for a long time - - 2012-05-11: Simon Goldschmidt (patch by Marty) - * memp.c: fixed bug #36412: memp.c does not compile when - MEMP_OVERFLOW_CHECK > zero and MEMP_SEPARATE_POOLS == 1 - - 2012-05-03: Simon Goldschmidt (patch by Sylvain Rochet) - * ppp.c: fixed bug #36283 (PPP struct used on header size computation and - not packed) - - 2012-05-03: Simon Goldschmidt (patch by David Empson) - * ppp.c: fixed bug #36388 (PPP: checksum-only in last pbuf leads to pbuf with - zero length) - - 2012-03-25: Simon Goldschmidt - * api_msg.c: Fixed bug #35817: do_connect() invalidly signals op_completed - for UDP/RAW with LWIP_TCPIP_CORE_LOCKING==1 - - 2012-03-25: Simon Goldschmidt - * api_msg.h, api_lib.c, api_msg.c, netifapi.c: fixed bug #35931: Name space - pollution in api_msg.c and netifapi.c - - 2011-08-24: Simon Goldschmidt - * inet6.h: fixed bug #34124 struct in6_addr does not conform to the standard - - - -(STABLE-1.4.1) - - ++ New features: - - 2012-03-25: Simon Goldschmidt (idea by Mason) - * posix/*: added posix-compatibility include files posix/netdb.h and posix/sys/socket.h - which are a simple wrapper to the correct lwIP include files. - - 2012-01-16: Simon Goldschmidt - * opt.h, icmp.c: Added option CHECKSUM_GEN_ICMP - - 2011-12-17: Simon Goldschmidt - * ip.h: implemented API functions to access so_options of IP pcbs (UDP, TCP, RAW) - (fixes bug #35061) - - 2011-09-27: Simon Goldschmidt - * opt.h, tcp.c, tcp_in.c: Implemented limiting data on ooseq queue (task #9989) - (define TCP_OOSEQ_MAX_BYTES / TCP_OOSEQ_MAX_PBUFS in lwipopts.h) - - 2011-09-21: Simon Goldschmidt - * opt.h, api.h, api_lib.c, api_msg.h/.c, sockets.c: Implemented timeout on - send (TCP only, bug #33820) - - 2011-09-21: Simon Goldschmidt - * init.c: Converted runtime-sanity-checks into compile-time checks that can - be disabled (since runtime checks can often not be seen on embedded targets) - - 2011-09-11: Simon Goldschmidt - * ppp.h, ppp_impl.h: splitted ppp.h to an internal and external header file - to get a clear separation of which functions an application or port may use - (task #11281) - - 2011-09-11: Simon Goldschmidt - * opt.h, tcp_impl.h, tcp.c, udp.h/.c: Added a config option to randomize - initial local TCP/UDP ports (so that different port ranges are used after - a reboot; bug #33818; this one added tcp_init/udp_init functions again) - - 2011-09-03: Simon Goldschmidt - * dhcp.c: DHCP uses LWIP_RAND() for xid's (bug #30302) - - 2011-08-24: Simon Goldschmidt - * opt.h, netif.h/.c: added netif remove callback (bug #32397) - - 2011-07-26: Simon Goldschmidt - * etharp.c: ETHARP_SUPPORT_VLAN: add support for an external VLAN filter - function instead of only checking for one VLAN (define ETHARP_VLAN_CHECK_FN) - - 2011-07-21: Simon Goldschmidt (patch by hanhui) - * ip4.c, etharp.c, pbuf.h: bug #33634 ip_forward() have a faulty behaviour: - Added pbuf flags to mark incoming packets as link-layer broadcast/multicast. - Also added code to allow ip_forward() to forward non-broadcast packets to - the input netif (set IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1). - - 2011-06-26: Simon Goldschmidt (patch by Cameron Gutman) - * tcp.c, tcp_out.c: bug #33604: added some more asserts to check that - pcb->state != LISTEN - - 2011-05-14: Simon Goldschmidt (patch by Stéphane Lesage) - * tcpip.c/.h: patch #7449 allow tcpip callback from interrupt with static - memory message - - - ++ Bugfixes: - - 2012-09-26: Simon Goldschmidt - * api_msg.c: fixed bug #37405 'err_tcp()' uses already freed 'netconn' object - - 2012-09-26: patch by Henrik Persson - * dhcp.c: patch #7843 Fix corner case with dhcp timeouts - - 2012-09-26: patch by Henrik Persson - * dhcp.c: patch #7840 Segfault in dhcp_parse_reply if no end marker in dhcp packet - - 2012-08-22: Simon Goldschmidt - * memp.c: fixed bug #37166: memp_sanity check loops itself - - 2012-05-08: Simon Goldschmidt - * tcp_out.c: fixed bug: #36380 unsent_oversize mismatch in 1.4.1RC1 (this was - a debug-check issue only) - - 2012-03-27: Simon Goldschmidt - * vj.c: fixed bug #35756 header length calculation problem in ppp/vj.c - - 2012-03-27: Simon Goldschmidt (patch by Mason) - * tcp_out.c: fixed bug #35945: SYN packet should provide the recv MSS not the - send MSS - - 2012-03-22: Simon Goldschmidt - * ip4.c: fixed bug #35927: missing refragmentaion in ip_forward - - 2012-03-20: Simon Goldschmidt (patch by Mason) - * netdb.c: fixed bug #35907: lwip_gethostbyname_r returns an invalid h_addr_list - - 2012-03-12: Simon Goldschmidt (patch by Bostjan Meglic) - * ppp.c: fixed bug #35809: PPP GetMask(): Compiler warning on big endian, - possible bug on little endian system - - 2012-02-23: Simon Goldschmidt - * etharp.c: fixed bug #35595: Impossible to send broadcast without a gateway - (introduced when fixing bug# 33551) - - 2012-02-16: Simon Goldschmidt - * ppp.c: fixed pbuf leak when PPP session is aborted through pppSigHUP() - (bug #35541: PPP Memory Leak) - - 2012-02-16: Simon Goldschmidt - * etharp.c: fixed bug #35531: Impossible to send multicast without a gateway - (introduced when fixing bug# 33551) - - 2012-02-16: Simon Goldschmidt (patch by Stéphane Lesage) - * msg_in.c, msg_out.c: fixed bug #35536 SNMP: error too big response is malformed - - 2012-02-15: Simon Goldschmidt - * init.c: fixed bug #35537: MEMP_NUM_* sanity checks should be disabled with - MEMP_MEM_MALLOC==1 - - 2012-02-12: Simon Goldschmidt - * tcp.h, tcp_in.c, tcp_out.c: partly fixed bug #25882: TCP hangs on - MSS > pcb->snd_wnd (by not creating segments bigger than half the window) - - 2012-02-11: Simon Goldschmidt - * tcp.c: fixed bug #35435: No pcb state check before adding it to time-wait - queue while closing - - 2012-01-22: Simon Goldschmidt - * tcp.c, tcp_in.c: fixed bug #35305: pcb may be freed too early on shutdown(WR) - - 2012-01-21: Simon Goldschmidt - * tcp.c: fixed bug #34636: FIN_WAIT_2 - Incorrect shutdown of TCP pcb - - 2012-01-20: Simon Goldschmidt - * dhcp.c: fixed bug #35151: DHCP asserts on incoming option lengths - - 2012-01-20: Simon Goldschmidt - * pbuf.c: fixed bug #35291: NULL pointer in pbuf_copy - - 2011-11-25: Simon Goldschmidt - * tcp.h/.c, tcp_impl.h, tcp_in.c: fixed bug #31177: tcp timers can corrupt - tcp_active_pcbs in some cases - - 2011-11-23: Simon Goldschmidt - * sys.c: fixed bug #34884: sys_msleep() body needs to be surrounded with - '#ifndef sys_msleep' - - 2011-11-22: Simon Goldschmidt - * netif.c, etharp.h/.c: fixed bug #34684: Clear the arp table cache when - netif is brought down - - 2011-10-28: Simon Goldschmidt - * tcp_in.c: fixed bug #34638: Dead code in tcp_receive - pcb->dupacks - - 2011-10-23: Simon Goldschmidt - * mem.c: fixed bug #34429: possible memory corruption with - LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT set to 1 - - 2011-10-18: Simon Goldschmidt - * arch.h, netdb.c: fixed bug #34592: lwip_gethostbyname_r uses nonstandard - error value - - 2011-10-18: Simon Goldschmidt - * opt.h: fixed default values of TCP_SNDLOWAT and TCP_SNDQUEUELOWAT for small - windows (bug #34176 select after non-blocking send times out) - - 2011-10-18: Simon Goldschmidt - * tcp_impl.h, tcp_out.c: fixed bug #34587: TCP_BUILD_MSS_OPTION doesn't - consider netif->mtu, causes slow network - - 2011-10-18: Simon Goldschmidt - * sockets.c: fixed bug #34581 missing parentheses in udplite sockets code - - 2011-10-18: Simon Goldschmidt - * sockets.h: fixed bug #34580 fcntl() is missing in LWIP_COMPAT_SOCKETS - - 2011-10-17: Simon Goldschmidt - * api_msg.c: fixed bug #34569: shutdown(SHUT_WR) crashes netconn/socket api - - 2011-10-13: Simon Goldschmidt - * tcp_in.c, tcp_out.c: fixed bug #34517 (persist timer is started although no - zero window is received) by starting the persist timer when a zero window is - received, not when we have more data queued for sending than fits into the - window - - 2011-10-13: Simon Goldschmidt - * def.h, timers.c: fixed bug #34541: LWIP_U32_DIFF is unnecessarily complex - - 2011-10-13: Simon Goldschmidt - * sockets.c, api_lib.c: fixed bug #34540: compiler error when CORE_LOCKING is - used and not all protocols are enabled - - 2011-10-12: Simon Goldschmidt - * pbuf.c: fixed bug #34534: Error in sending fragmented IP if MEM_ALIGNMENT > 4 - - 2011-10-09: Simon Goldschmidt - * tcp_out.c: fixed bug #34426: tcp_zero_window_probe() transmits incorrect - byte value when pcb->unacked != NULL - - 2011-10-09: Simon Goldschmidt - * ip4.c: fixed bug #34447 LWIP_IP_ACCEPT_UDP_PORT(dst_port) wrong - - 2011-09-27: Simon Goldschmidt - * tcp_in.c, tcp_out.c: Reset pcb->unsent_oversize in 2 more places... - - 2011-09-27: Simon Goldschmidt - * tcp_in.c: fixed bug #28288: Data after FIN in oos queue - - 2011-09-27: Simon Goldschmidt - * dhcp.c: fixed bug #34406 dhcp_option_hostname() can overflow the pbuf - - 2011-09-24: Simon Goldschmidt - * mem.h: fixed bug #34377 MEM_SIZE_F is not defined if MEM_LIBC_MALLOC==1 - - 2011-09-23: Simon Goldschmidt - * pbuf.h, tcp.c, tcp_in.c: fixed bug #33871: rejecting TCP_EVENT_RECV() for - the last packet including FIN can lose data - - 2011-09-22: Simon Goldschmidt - * tcp_impl.h: fixed bug #34355: nagle does not take snd_buf/snd_queuelen into - account - - 2011-09-21: Simon Goldschmidt - * opt.h: fixed default value of TCP_SND_BUF to not violate the sanity checks - in init.c - - 2011-09-20: Simon Goldschmidt - * timers.c: fixed bug #34337 (possible NULL pointer in sys_check_timeouts) - - 2011-09-11: Simon Goldschmidt - * tcp_out.c: use pcb->mss instead of TCP_MSS for preallocate mss-sized pbufs - (bug #34019) - - 2011-09-09: Simon Goldschmidt - * udp.c: fixed bug #34072: UDP broadcast is received from wrong UDP pcb if - udp port matches - - 2011-09-03: Simon Goldschmidt - * tcp_in.c: fixed bug #33952 PUSH flag in incoming packet is lost when packet - is aggregated and sent to application - - 2011-09-01: Simon Goldschmidt - * opt.h: fixed bug #31809 LWIP_EVENT_API in opts.h is inconsistent compared - to other options - - 2011-09-01: Simon Goldschmidt - * tcp_in.c: fixed bug #34111 RST for ACK to listening pcb has wrong seqno - - 2011-08-24: Simon Goldschmidt - * api_msg.c, sockets.c: fixed bug #33956 Wrong error returned when calling - accept() on UDP connections - - 2011-08-24: Simon Goldschmidt - * sockets.h: fixed bug #34057 socklen_t should be a typedef - - 2011-08-24: Simon Goldschmidt - * pbuf.c: fixed bug #34112 Odd check in pbuf_alloced_custom (typo) - - 2011-08-24: Simon Goldschmidt - * dhcp.c: fixed bug #34122 dhcp: hostname can overflow - - 2011-08-24: Simon Goldschmidt - * netif.c: fixed bug #34121 netif_add/netif_set_ipaddr fail on NULL ipaddr - - 2011-08-22: Simon Goldschmidt - * tcp_out.c: fixed bug #33962 TF_FIN not always set after FIN is sent. (This - merely prevents nagle from not transmitting fast after closing.) - - 2011-07-22: Simon Goldschmidt - * api_lib.c, api_msg.c, sockets.c, api.h: fixed bug #31084 (socket API returns - always EMSGSIZE on non-blocking sockets if data size > send buffers) -> now - lwip_send() sends as much as possible for non-blocking sockets - - 2011-07-22: Simon Goldschmidt - * pbuf.c/.h, timers.c: freeing ooseq pbufs when the pbuf pool is empty implemented - for NO_SYS==1: when not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() - at regular intervals from main level. - - 2011-07-21: Simon Goldschmidt - * etharp.c: fixed bug #33551 (ARP entries may time out although in use) by - sending an ARP request when an ARP entry is used in the last minute before - it would time out. - - 2011-07-04: Simon Goldschmidt - * sys_arch.txt: Fixed documentation after changing sys arch prototypes for 1.4.0. - - 2011-06-26: Simon Goldschmidt - * tcp.c: fixed bug #31723 (tcp_kill_prio() kills pcbs with the same prio) by - updating its documentation only. - - 2011-06-26: Simon Goldschmidt - * mem.c: fixed bug #33545: With MEM_USE_POOLS==1, mem_malloc can return an - unaligned pointer. - - 2011-06-26: Simon Goldschmidt - * mem.c: fixed bug #33544 "warning in mem.c in lwip 1.4.0 with NO_SYS=1" - - 2011-05-25: Simon Goldschmidt - * tcp.c: fixed bug #33398 (pointless conversion when checking TCP port range) - - - -(STABLE-1.4.0) - - ++ New features: - - 2011-03-27: Simon Goldschmidt - * tcp_impl.h, tcp_in.c, tcp_out.c: Removed 'dataptr' from 'struct tcp_seg' and - calculate it in tcp_zero_window_probe (the only place where it was used). - - 2010-11-21: Simon Goldschmidt - * dhcp.c/.h: Added a function to deallocate the struct dhcp from a netif - (fixes bug #31525). - - 2010-07-12: Simon Goldschmidt (patch by Stephane Lesage) - * ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for - IP_MULTICAST_LOOP at socket- and raw-API level. - - 2010-06-16: Simon Goldschmidt - * ip.c: Added an optional define (LWIP_IP_ACCEPT_UDP_PORT) that can allow - link-layer-addressed UDP traffic to be received while a netif is down (just - like DHCP during configuration) - - 2010-05-22: Simon Goldschmidt - * many many files: bug #27352: removed packing from ip_addr_t, the packed - version is now only used in protocol headers. Added global storage for - current src/dest IP address while in input functions. - - 2010-05-16: Simon Goldschmidt - * def.h: task #10391: Add preprocessor-macros for compile-time htonl - calculation (and use them throughout the stack where applicable) - - 2010-05-16: Simon Goldschmidt - * opt.h, memp_std.h, memp.c, ppp_oe.h/.c: PPPoE now uses its own MEMP pool - instead of the heap (moved struct pppoe_softc from ppp_oe.c to ppp_oe.h) - - 2010-05-16: Simon Goldschmidt - * opt.h, memp_std.h, dns.h/.c: DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses its own - MEMP pool instead of the heap - - 2010-05-13: Simon Goldschmidt - * tcp.c, udp.c: task #6995: Implement SO_REUSEADDR (correctly), added - new option SO_REUSE_RXTOALL to pass received UDP broadcast/multicast - packets to more than one pcb. - - 2010-05-02: Simon Goldschmidt - * netbuf.h/.c, sockets.c, api_msg.c: use checksum-on-copy for sending - UDP data for LWIP_NETIF_TX_SINGLE_PBUF==1 - - 2010-04-30: Simon Goldschmidt - * udp.h/.c, pbuf.h/.c: task #6849: added udp_send(_to/_if) functions that - take a precalculated checksum, added pbuf_fill_chksum() to copy data - into a pbuf and at the same time calculating the checksum for that data - - 2010-04-29: Simon Goldschmidt - * ip_addr.h, etharp.h/.c, autoip.c: Create overridable macros for copying - 2-byte-aligned IP addresses and MAC addresses - - 2010-04-28: Patch by Bill Auerbach - * ip.c: Inline generating IP checksum to save a function call - - 2010-04-14: Simon Goldschmidt - * tcpip.h/.c, timers.c: Added an overridable define to get informed when the - tcpip_thread processes messages or timeouts to implement a watchdog. - - 2010-03-28: Simon Goldschmidt - * ip_frag.c: create a new (contiguous) PBUF_RAM for every outgoing - fragment if LWIP_NETIF_TX_SINGLE_PBUF==1 - - 2010-03-27: Simon Goldschmidt - * etharp.c: Speedup TX by moving code from find_entry to etharp_output/ - etharp_query to prevent unnecessary function calls (inspired by - patch #7135). - - 2010-03-20: Simon Goldschmidt - * opt.h, tcpip.c/.h: Added an option to disable tcpip_(un)timeout code - since the linker cannot do this automatically to save space. - - 2010-03-20: Simon Goldschmidt - * opt.h, etharp.c/.h: Added support for static ARP table entries - - 2010-03-14: Simon Goldschmidt - * tcp_impl.h, tcp_out.c, inet_chksum.h/.c: task #6849: Calculate checksum - when creating TCP segments, not when (re-)transmitting them. - - 2010-03-07: Simon Goldschmidt - * sockets.c: bug #28775 (select/event_callback: only check select_cb_list - on change) plus use SYS_LIGHTWEIGHT_PROT to protect the select code. - This should speed up receiving data on sockets as the select code in - event_callback is only executed when select is waiting. - - 2010-03-06: Simon Goldschmidt - * tcp_out.c: task #7013 (Create option to have all packets delivered to - netif->output in one piece): Always copy to try to create single pbufs - in tcp_write. - - 2010-03-06: Simon Goldschmidt - * api.h, api_lib.c, sockets.c: task #10167 (sockets: speed up TCP recv - by not allocating a netbuf): added function netconn_recv_tcp_pbuf() - for tcp netconns to receive pbufs, not netbufs; use that function - for tcp sockets. - - 2010-03-05: Jakob Ole Stoklundsen / Simon Goldschmidt - * opt.h, tcp.h, tcp_impl.h, tcp.c, tcp_in.c, tcp_out.c: task #7040: - Work on tcp_enqueue: Don't waste memory when chaining segments, - added option TCP_OVERSIZE to prevent creating many small pbufs when - calling tcp_write with many small blocks of data. Instead, pbufs are - allocated larger than needed and the space is used for later calls to - tcp_write. - - 2010-02-21: Simon Goldschmidt - * stats.c/.h: Added const char* name to mem- and memp-stats for easier - debugging. - - 2010-02-21: Simon Goldschmidt - * tcp.h (and usages), added tcp_impl.h: Splitted API and internal - implementation of tcp to make API usage cleare to application programmers - - 2010-02-14: Simon Goldschmidt/Stephane Lesage - * ip_addr.h: Improved some defines working on ip addresses, added faster - macro to copy addresses that cannot be NULL - - 2010-02-13: Simon Goldschmidt - * api.h, api_lib.c, api_msg.c, sockets.c: task #7865 (implement non- - blocking send operation) - - 2010-02-12: Simon Goldschmidt - * sockets.c/.h: Added a minimal version of posix fctl() to have a - standardised way to set O_NONBLOCK for nonblocking sockets. - - 2010-02-12: Simon Goldschmidt - * dhcp.c/.h, autoip.c/.h: task #10139 (Prefer statically allocated - memory): added autoip_set_struct() and dhcp_set_struct() to let autoip - and dhcp work with user-allocated structs instead of callin mem_malloc - - 2010-02-12: Simon Goldschmidt/Jeff Barber - * tcp.c/h: patch #6865 (SO_REUSEADDR for TCP): if pcb.so_options has - SOF_REUSEADDR set, allow binding to endpoint in TIME_WAIT - - 2010-02-12: Simon Goldschmidt - * sys layer: task #10139 (Prefer statically allocated memory): converted - mbox and semaphore functions to take pointers to sys_mbox_t/sys_sem_t; - converted sys_mbox_new/sys_sem_new to take pointers and return err_t; - task #7212: Add Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX - to let sys.h use binary semaphores instead of mutexes - as before) - - 2010-02-09: Simon Goldschmidt (Simon Kallweit) - * timers.c/.h: Added function sys_restart_timeouts() from patch #7085 - (Restart system timeout handling) - - 2010-02-09: Simon Goldschmidt - * netif.c/.h, removed loopif.c/.h: task #10153 (Integrate loopif into - netif.c) - loopif does not have to be created by the port any more, - just define LWIP_HAVE_LOOPIF to 1. - - 2010-02-08: Simon Goldschmidt - * inet.h, ip_addr.c/.h: Added reentrant versions of inet_ntoa/ipaddr_ntoa - inet_ntoa_r/ipaddr_ntoa_r - - 2010-02-08: Simon Goldschmidt - * netif.h: Added netif_s/get_igmp_mac_filter() macros - - 2010-02-05: Simon Goldschmidt - * netif.h: Added function-like macros to get/set the hostname on a netif - - 2010-02-04: Simon Goldschmidt - * nearly every file: Replaced struct ip_addr by typedef ip_addr_t to - make changing the actual implementation behind the typedef easier. - - 2010-02-01: Simon Goldschmidt - * opt.h, memp_std.h, dns.h, netdb.c, memp.c: Let netdb use a memp pool - for allocating memory when getaddrinfo() is called. - - 2010-01-31: Simon Goldschmidt - * dhcp.h, dhcp.c: Reworked the code that parses DHCP options: parse - them once instead of parsing for every option. This also removes - the need for mem_malloc from dhcp_recv and makes it possible to - correctly retrieve the BOOTP file. - - 2010-01-30: simon Goldschmidt - * sockets.c: Use SYS_LIGHTWEIGHT_PROT instead of a semaphore to protect - the sockets array. - - 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) - * api.h, api_msg.c, sockets.c: Added except set support in select - (patch #6860) - - 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) - * api.h, sockets.h, err.h, api_lib.c, api_msg.c, sockets.c, err.c: - Add non-blocking support for connect (partly from patch #6860), - plus many cleanups in socket & netconn API. - - 2010-01-27: Simon Goldschmidt - * opt.h, tcp.h, init.c, api_msg.c: Added TCP_SNDQUEUELOWAT corresponding - to TCP_SNDLOWAT and added tcp_sndqueuelen() - this fixes bug #28605 - - 2010-01-26: Simon Goldschmidt - * snmp: Use memp pools for snmp instead of the heap; added 4 new pools. - - 2010-01-14: Simon Goldschmidt - * ppp.c/.h: Fixed bug #27856: PPP: Set netif link- and status-callback - by adding ppp_set_netif_statuscallback()/ppp_set_netif_linkcallback() - - 2010-01-13: Simon Goldschmidt - * mem.c: The heap now may be moved to user-defined memory by defining - LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address - (patch #6966 and bug #26133) - - 2010-01-10: Simon Goldschmidt (Bill Auerbach) - * opt.h, memp.c: patch #6822 (Add option to place memory pools in - separate arrays) - - 2010-01-10: Simon Goldschmidt - * init.c, igmp.c: patch #6463 (IGMP - Adding Random Delay): added define - LWIP_RAND() for lwip-wide randomization (to be defined in cc.h) - - 2009-12-31: Simon Goldschmidt - * tcpip.c, init.c, memp.c, sys.c, memp_std.h, sys.h, tcpip.h - added timers.c/.h: Separated timer implementation from semaphore/mbox - implementation, moved timer implementation to timers.c/.h, timers are - now only called from tcpip_thread or by explicitly checking them. - (TASK#7235) - - 2009-12-27: Simon Goldschmidt - * opt.h, etharp.h/.c, init.c, tcpip.c: Added an additional option - LWIP_ETHERNET to support ethernet without ARP (necessary for pure PPPoE) - - - ++ Bugfixes: - - 2011-04-20: Simon Goldschmidt - * sys_arch.txt: sys_arch_timeouts() is not needed any more. - - 2011-04-13: Simon Goldschmidt - * tcp.c, udp.c: Fixed bug #33048 (Bad range for IP source port numbers) by - using ports in the IANA private/dynamic range (49152 through 65535). - - 2011-03-29: Simon Goldschmidt, patch by Emil Lhungdahl: - * etharp.h/.c: Fixed broken VLAN support. - - 2011-03-27: Simon Goldschmidt - * tcp.c: Fixed bug #32926 (TCP_RMV(&tcp_bound_pcbs) is called on unbound tcp - pcbs) by checking if the pcb was bound (local_port != 0). - - 2011-03-27: Simon Goldschmidt - * ppp.c: Fixed bug #32280 (ppp: a pbuf is freed twice) - - 2011-03-27: Simon Goldschmidt - * sockets.c: Fixed bug #32906: lwip_connect+lwip_send did not work for udp and - raw pcbs with LWIP_TCPIP_CORE_LOCKING==1. - - 2011-03-27: Simon Goldschmidt - * tcp_out.c: Fixed bug #32820 (Outgoing TCP connections created before route - is present never times out) by starting retransmission timer before checking - route. - - 2011-03-22: Simon Goldschmidt - * ppp.c: Fixed bug #32648 (PPP code crashes when terminating a link) by only - calling sio_read_abort() if the file descriptor is valid. - - 2011-03-14: Simon Goldschmidt - * err.h/.c, sockets.c, api_msg.c: fixed bug #31748 (Calling non-blocking connect - more than once can render a socket useless) since it mainly involves changing - "FATAL" classification of error codes: ERR_USE and ERR_ISCONN just aren't fatal. - - 2011-03-13: Simon Goldschmidt - * sockets.c: fixed bug #32769 (ESHUTDOWN is linux-specific) by fixing - err_to_errno_table (ERR_CLSD: ENOTCONN instead of ESHUTDOWN), ERR_ISCONN: - use EALRADY instead of -1 - - 2011-03-13: Simon Goldschmidt - * api_lib.c: netconn_accept: return ERR_ABRT instead of ERR_CLSD if the - connection has been aborted by err_tcp (since this is not a normal closing - procedure). - - 2011-03-13: Simon Goldschmidt - * tcp.c: tcp_bind: return ERR_VAL instead of ERR_ISCONN when trying to bind - with pcb->state != CLOSED - - 2011-02-17: Simon Goldschmidt - * rawapi.txt: Fixed bug #32561 tcp_poll argument definition out-of-order in - documentation - - 2011-02-17: Simon Goldschmidt - * many files: Added missing U/UL modifiers to fix 16-bit-arch portability. - - 2011-01-24: Simon Goldschmidt - * sockets.c: Fixed bug #31741: lwip_select seems to have threading problems - - 2010-12-02: Simon Goldschmidt - * err.h: Fixed ERR_IS_FATAL so that ERR_WOULDBLOCK is not fatal. - - 2010-11-23: Simon Goldschmidt - * api.h, api_lib.c, api_msg.c, sockets.c: netconn.recv_avail is only used for - LWIP_SO_RCVBUF and ioctl/FIONREAD. - - 2010-11-23: Simon Goldschmidt - * etharp.c: Fixed bug #31720: ARP-queueing: RFC 1122 recommends to queue at - least 1 packet -> ARP_QUEUEING==0 now queues the most recent packet. - - 2010-11-23: Simon Goldschmidt - * tcp_in.c: Fixed bug #30577: tcp_input: don't discard ACK-only packets after - refusing 'refused_data' again. - - 2010-11-22: Simon Goldschmidt - * sockets.c: Fixed bug #31590: getsockopt(... SO_ERROR ...) gives EINPROGRESS - after a successful nonblocking connection. - - 2010-11-22: Simon Goldschmidt - * etharp.c: Fixed bug #31722: IP packets sent with an AutoIP source addr - must be sent link-local - - 2010-11-22: Simon Goldschmidt - * timers.c: patch #7329: tcp_timer_needed prototype was ifdef'ed out for - LWIP_TIMERS==0 - - 2010-11-20: Simon Goldschmidt - * sockets.c: Fixed bug #31170: lwip_setsockopt() does not set socket number - - 2010-11-20: Simon Goldschmidt - * sockets.h: Fixed bug #31304: Changed SHUT_RD, SHUT_WR and SHUT_RDWR to - resemble other stacks. - - 2010-11-20: Simon Goldschmidt - * dns.c: Fixed bug #31535: TCP_SND_QUEUELEN must be at least 2 or else - no-copy TCP writes will never succeed. - - 2010-11-20: Simon Goldschmidt - * dns.c: Fixed bug #31701: Error return value from dns_gethostbyname() does - not match documentation: return ERR_ARG instead of ERR_VAL if not - initialized or wrong argument. - - 2010-10-20: Simon Goldschmidt - * sockets.h: Fixed bug #31385: sizeof(struct sockaddr) is 30 but should be 16 - - 2010-10-05: Simon Goldschmidt - * dhcp.c: Once again fixed #30038: DHCP/AutoIP cooperation failed when - replugging the network cable after an AutoIP address was assigned. - - 2010-08-10: Simon Goldschmidt - * tcp.c: Fixed bug #30728: tcp_new_port() did not check listen pcbs - - 2010-08-03: Simon Goldschmidt - * udp.c, raw.c: Don't chain empty pbufs when sending them (fixes bug #30625) - - 2010-08-01: Simon Goldschmidt (patch by Greg Renda) - * ppp.c: Applied patch #7264 (PPP protocols are rejected incorrectly on big - endian architectures) - - 2010-07-28: Simon Goldschmidt - * api_lib.c, api_msg.c, sockets.c, mib2.c: Fixed compilation with TCP or UDP - disabled. - - 2010-07-27: Simon Goldschmidt - * tcp.c: Fixed bug #30565 (tcp_connect() check bound list): that check did no - harm but never did anything - - 2010-07-21: Simon Goldschmidt - * ip.c: Fixed invalid fix for bug #30402 (CHECKSUM_GEN_IP_INLINE does not - add IP options) - - 2010-07-16: Kieran Mansley - * msg_in.c: Fixed SNMP ASN constant defines to not use ! operator - - 2010-07-10: Simon Goldschmidt - * ip.c: Fixed bug #30402: CHECKSUM_GEN_IP_INLINE does not add IP options - - 2010-06-30: Simon Goldschmidt - * api_msg.c: fixed bug #30300 (shutdown parameter was not initialized in - netconn_delete) - - 2010-06-28: Kieran Mansley - * timers.c remove unportable printing of C function pointers - - 2010-06-24: Simon Goldschmidt - * init.c, timers.c/.h, opt.h, memp_std.h: From patch #7221: added flag - NO_SYS_NO_TIMERS to drop timer support for NO_SYS==1 for easier upgrading - - 2010-06-24: Simon Goldschmidt - * api(_lib).c/.h, api_msg.c/.h, sockets.c/.h: Fixed bug #10088: Correctly - implemented shutdown at socket level. - - 2010-06-21: Simon Goldschmidt - * pbuf.c/.h, ip_frag.c/.h, opt.h, memp_std.h: Fixed bug #29361 (ip_frag has - problems with zero-copy DMA MACs) by adding custom pbufs and implementing - custom pbufs that reference other (original) pbufs. Additionally set - IP_FRAG_USES_STATIC_BUF=0 as default to be on the safe side. - - 2010-06-15: Simon Goldschmidt - * dhcp.c: Fixed bug #29970: DHCP endian issue parsing option responses - - 2010-06-14: Simon Goldschmidt - * autoip.c: Fixed bug #30039: AutoIP does not reuse previous addresses - - 2010-06-12: Simon Goldschmidt - * dhcp.c: Fixed bug #30038: dhcp_network_changed doesn't reset AUTOIP coop - state - - 2010-05-17: Simon Goldschmidt - * netdb.c: Correctly NULL-terminate h_addr_list - - 2010-05-16: Simon Goldschmidt - * def.h/.c: changed the semantics of LWIP_PREFIX_BYTEORDER_FUNCS to prevent - "symbol already defined" i.e. when linking to winsock - - 2010-05-05: Simon Goldschmidt - * def.h, timers.c: Fixed bug #29769 (sys_check_timeouts: sys_now() may - overflow) - - 2010-04-21: Simon Goldschmidt - * api_msg.c: Fixed bug #29617 (sometime cause stall on delete listening - connection) - - 2010-03-28: Luca Ceresoli - * ip_addr.c/.h: patch #7143: Add a few missing const qualifiers - - 2010-03-27: Luca Ceresoli - * mib2.c: patch #7130: remove meaningless const qualifiers - - 2010-03-26: Simon Goldschmidt - * tcp_out.c: Make LWIP_NETIF_TX_SINGLE_PBUF work for TCP, too - - 2010-03-26: Simon Goldschmidt - * various files: Fixed compiling with different options disabled (TCP/UDP), - triggered by bug #29345; don't allocate acceptmbox if LWIP_TCP is disabled - - 2010-03-25: Simon Goldschmidt - * sockets.c: Fixed bug #29332: lwip_select() processes readset incorrectly - - 2010-03-25: Simon Goldschmidt - * tcp_in.c, test_tcp_oos.c: Fixed bug #29080: Correctly handle remote side - overrunning our rcv_wnd in ooseq case. - - 2010-03-22: Simon Goldschmidt - * tcp.c: tcp_listen() did not copy the pcb's prio. - - 2010-03-19: Simon Goldschmidt - * snmp_msg.c: Fixed bug #29256: SNMP Trap address was not correctly set - - 2010-03-14: Simon Goldschmidt - * opt.h, etharp.h: Fixed bug #29148 (Incorrect PBUF_POOL_BUFSIZE for ports - where ETH_PAD_SIZE > 0) by moving definition of ETH_PAD_SIZE to opt.h - and basing PBUF_LINK_HLEN on it. - - 2010-03-08: Simon Goldschmidt - * netif.c, ipv4/ip.c: task #10241 (AutoIP: don't break existing connections - when assiging routable address): when checking incoming packets and - aborting existing connection on address change, filter out link-local - addresses. - - 2010-03-06: Simon Goldschmidt - * sockets.c: Fixed LWIP_NETIF_TX_SINGLE_PBUF for LWIP_TCPIP_CORE_LOCKING - - 2010-03-06: Simon Goldschmidt - * ipv4/ip.c: Don't try to forward link-local addresses - - 2010-03-06: Simon Goldschmidt - * etharp.c: Fixed bug #29087: etharp: don't send packets for LinkLocal- - addresses to gw - - 2010-03-05: Simon Goldschmidt - * dhcp.c: Fixed bug #29072: Correctly set ciaddr based on message-type - and state. - - 2010-03-05: Simon Goldschmidt - * api_msg.c: Correctly set TCP_WRITE_FLAG_MORE when netconn_write is split - into multiple calls to tcp_write. - - 2010-02-21: Simon Goldschmidt - * opt.h, mem.h, dns.c: task #10140: Remove DNS_USES_STATIC_BUF (keep - the implementation of DNS_USES_STATIC_BUF==1) - - 2010-02-20: Simon Goldschmidt - * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Task #10088: Correctly implement - close() vs. shutdown(). Now the application does not get any more - recv callbacks after calling tcp_close(). Added tcp_shutdown(). - - 2010-02-19: Simon Goldschmidt - * mem.c/.h, pbuf.c: Renamed mem_realloc() to mem_trim() to prevent - confusion with realloc() - - 2010-02-15: Simon Goldschmidt/Stephane Lesage - * netif.c/.h: Link status does not depend on LWIP_NETIF_LINK_CALLBACK - (fixes bug #28899) - - 2010-02-14: Simon Goldschmidt - * netif.c: Fixed bug #28877 (Duplicate ARP gratuitous packet with - LWIP_NETIF_LINK_CALLBACK set on) by only sending if both link- and - admin-status of a netif are up - - 2010-02-14: Simon Goldschmidt - * opt.h: Disable ETHARP_TRUST_IP_MAC by default since it slows down packet - reception and is not really necessary - - 2010-02-14: Simon Goldschmidt - * etharp.c/.h: Fixed ARP input processing: only add a new entry if a - request was directed as us (RFC 826, Packet Reception), otherwise - only update existing entries; internalized some functions - - 2010-02-14: Simon Goldschmidt - * netif.h, etharp.c, tcpip.c: Fixed bug #28183 (ARP and TCP/IP cannot be - disabled on netif used for PPPoE) by adding a new netif flag - (NETIF_FLAG_ETHERNET) that tells the stack the device is an ethernet - device but prevents usage of ARP (so that ethernet_input can be used - for PPPoE). - - 2010-02-12: Simon Goldschmidt - * netif.c: netif_set_link_up/down: only do something if the link state - actually changes - - 2010-02-12: Simon Goldschmidt/Stephane Lesage - * api_msg.c: Fixed bug #28865 (Cannot close socket/netconn in non-blocking - connect) - - 2010-02-12: Simon Goldschmidt - * mem.h: Fixed bug #28866 (mem_realloc function defined in mem.h) - - 2010-02-09: Simon Goldschmidt - * api_lib.c, api_msg.c, sockets.c, api.h, api_msg.h: Fixed bug #22110 - (recv() makes receive window update for data that wasn't received by - application) - - 2010-02-09: Simon Goldschmidt/Stephane Lesage - * sockets.c: Fixed bug #28853 (lwip_recvfrom() returns 0 on receive time-out - or any netconn_recv() error) - - 2010-02-09: Simon Goldschmidt - * ppp.c: task #10154 (PPP: Update snmp in/out counters for tx/rx packets) - - 2010-02-09: Simon Goldschmidt - * netif.c: For loopback packets, adjust the stats- and snmp-counters - for the loopback netif. - - 2010-02-08: Simon Goldschmidt - * igmp.c/.h, ip.h: Moved most defines from igmp.h to igmp.c for clarity - since they are not used anywhere else. - - 2010-02-08: Simon Goldschmidt (Stéphane Lesage) - * igmp.c, igmp.h, stats.c, stats.h: Improved IGMP stats - (patch from bug #28798) - - 2010-02-08: Simon Goldschmidt (Stéphane Lesage) - * igmp.c: Fixed bug #28798 (Error in "Max Response Time" processing) and - another bug when LWIP_RAND() returns zero. - - 2010-02-04: Simon Goldschmidt - * nearly every file: Use macros defined in ip_addr.h (some of them new) - to work with IP addresses (preparation for bug #27352 - Change ip_addr - from struct to typedef (u32_t) - and better code). - - 2010-01-31: Simon Goldschmidt - * netif.c: Don't call the link-callback from netif_set_up/down() since - this invalidly retriggers DHCP. - - 2010-01-29: Simon Goldschmidt - * ip_addr.h, inet.h, def.h, inet.c, def.c, more: Cleanly separate the - portability file inet.h and its contents from the stack: moved htonX- - functions to def.h (and the new def.c - they are not ipv4 dependent), - let inet.h depend on ip_addr.h and not the other way round. - This fixes bug #28732. - - 2010-01-28: Kieran Mansley - * tcp.c: Ensure ssthresh >= 2*MSS - - 2010-01-27: Simon Goldschmidt - * tcp.h, tcp.c, tcp_in.c: Fixed bug #27871: Calling tcp_abort() in recv - callback can lead to accessing unallocated memory. As a consequence, - ERR_ABRT means the application has called tcp_abort()! - - 2010-01-25: Simon Goldschmidt - * snmp_structs.h, msg_in.c: Partly fixed bug #22070 (MIB_OBJECT_WRITE_ONLY - not implemented in SNMP): write-only or not-accessible are still - returned by getnext (though not by get) - - 2010-01-24: Simon Goldschmidt - * snmp: Renamed the private mib node from 'private' to 'mib_private' to - not use reserved C/C++ keywords - - 2010-01-23: Simon Goldschmidt - * sockets.c: Fixed bug #28716: select() returns 0 after waiting for less - than 1 ms - - 2010-01-21: Simon Goldschmidt - * tcp.c, api_msg.c: Fixed bug #28651 (tcp_connect: no callbacks called - if tcp_enqueue fails) both in raw- and netconn-API - - 2010-01-19: Simon Goldschmidt - * api_msg.c: Fixed bug #27316: netconn: Possible deadlock in err_tcp - - 2010-01-18: Iordan Neshev/Simon Goldschmidt - * src/netif/ppp: reorganised PPP sourcecode to 2.3.11 including some - bugfix backports from 2.4.x. - - 2010-01-18: Simon Goldschmidt - * mem.c: Fixed bug #28679: mem_realloc calculates mem_stats wrong - - 2010-01-17: Simon Goldschmidt - * api_lib.c, api_msg.c, (api_msg.h, api.h, sockets.c, tcpip.c): - task #10102: "netconn: clean up conn->err threading issues" by adding - error return value to struct api_msg_msg - - 2010-01-17: Simon Goldschmidt - * api.h, api_lib.c, sockets.c: Changed netconn_recv() and netconn_accept() - to return err_t (bugs #27709 and #28087) - - 2010-01-14: Simon Goldschmidt - * ...: Use typedef for function prototypes throughout the stack. - - 2010-01-13: Simon Goldschmidt - * api_msg.h/.c, api_lib.c: Fixed bug #26672 (close connection when receive - window = 0) by correctly draining recvmbox/acceptmbox - - 2010-01-11: Simon Goldschmidt - * pap.c: Fixed bug #13315 (PPP PAP authentication can result in - erroneous callbacks) by copying the code from recent pppd - - 2010-01-10: Simon Goldschmidt - * raw.c: Fixed bug #28506 (raw_bind should filter received packets) - - 2010-01-10: Simon Goldschmidt - * tcp.h/.c: bug #28127 (remove call to tcp_output() from tcp_ack(_now)()) - - 2010-01-08: Simon Goldschmidt - * sockets.c: Fixed bug #28519 (lwip_recvfrom bug with len > 65535) - - 2010-01-08: Simon Goldschmidt - * dns.c: Copy hostname for DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1 since string - passed to dns_local_addhost() might be volatile - - 2010-01-07: Simon Goldschmidt - * timers.c, tcp.h: Call tcp_timer_needed() with NO_SYS==1, too - - 2010-01-06: Simon Goldschmidt - * netdb.h: Fixed bug #28496: missing include guards in netdb.h - - 2009-12-31: Simon Goldschmidt - * many ppp files: Reorganised PPP source code from ucip structure to pppd - structure to easily compare our code against the pppd code (around v2.3.1) - - 2009-12-27: Simon Goldschmidt - * tcp_in.c: Another fix for bug #28241 (ooseq processing) and adapted - unit test - - -(STABLE-1.3.2) - - ++ New features: - - 2009-10-27 Simon Goldschmidt/Stephan Lesage - * netifapi.c/.h: Added netifapi_netif_set_addr() - - 2009-10-07 Simon Goldschmidt/Fabian Koch - * api_msg.c, netbuf.c/.h, opt.h: patch #6888: Patch for UDP Netbufs to - support dest-addr and dest-port (optional: LWIP_NETBUF_RECVINFO) - - 2009-08-26 Simon Goldschmidt/Simon Kallweit - * slipif.c/.h: bug #26397: SLIP polling support - - 2009-08-25 Simon Goldschmidt - * opt.h, etharp.h/.c: task #9033: Support IEEE 802.1q tagged frame (VLAN), - New configuration options ETHARP_SUPPORT_VLAN and ETHARP_VLAN_CHECK. - - 2009-08-25 Simon Goldschmidt - * ip_addr.h, netdb.c: patch #6900: added define ip_ntoa(struct ip_addr*) - - 2009-08-24 Jakob Stoklund Olesen - * autoip.c, dhcp.c, netif.c: patch #6725: Teach AutoIP and DHCP to respond - to netif_set_link_up(). - - 2009-08-23 Simon Goldschmidt - * tcp.h/.c: Added function tcp_debug_state_str() to convert a tcp state - to a human-readable string. - - ++ Bugfixes: - - 2009-12-24: Kieran Mansley - * tcp_in.c Apply patches from Oleg Tyshev to improve OOS processing - (BUG#28241) - - 2009-12-06: Simon Goldschmidt - * ppp.h/.c: Fixed bug #27079 (Yet another leak in PPP): outpacket_buf can - be statically allocated (like in ucip) - - 2009-12-04: Simon Goldschmidt (patch by Ioardan Neshev) - * pap.c: patch #6969: PPP: missing PAP authentication UNTIMEOUT - - 2009-12-03: Simon Goldschmidt - * tcp.h, tcp_in.c, tcp_out.c: Fixed bug #28106: dup ack for fast retransmit - could have non-zero length - - 2009-12-02: Simon Goldschmidt - * tcp_in.c: Fixed bug #27904: TCP sends too many ACKs: delay resetting - tcp_input_pcb until after calling the pcb's callbacks - - 2009-11-29: Simon Goldschmidt - * tcp_in.c: Fixed bug #28054: Two segments with FIN flag on the out-of- - sequence queue, also fixed PBUF_POOL leak in the out-of-sequence code - - 2009-11-29: Simon Goldschmidt - * pbuf.c: Fixed bug #28064: pbuf_alloc(PBUF_POOL) is not thread-safe by - queueing a call into tcpip_thread to free ooseq-bufs if the pool is empty - - 2009-11-26: Simon Goldschmidt - * tcp.h: Fixed bug #28098: Nagle can prevent fast retransmit from sending - segment - - 2009-11-26: Simon Goldschmidt - * tcp.h, sockets.c: Fixed bug #28099: API required to disable Nagle - algorithm at PCB level - - 2009-11-22: Simon Goldschmidt - * tcp_out.c: Fixed bug #27905: FIN isn't combined with data on unsent - - 2009-11-22: Simon Goldschmidt (suggested by Bill Auerbach) - * tcp.c: tcp_alloc: prevent increasing stats.err for MEMP_TCP_PCB when - reusing time-wait pcb - - 2009-11-20: Simon Goldschmidt (patch by Albert Bartel) - * sockets.c: Fixed bug #28062: Data received directly after accepting - does not wake up select - - 2009-11-11: Simon Goldschmidt - * netdb.h: Fixed bug #27994: incorrect define for freeaddrinfo(addrinfo) - - 2009-10-30: Simon Goldschmidt - * opt.h: Increased default value for TCP_MSS to 536, updated default - value for TCP_WND to 4*TCP_MSS to keep delayed ACK working. - - 2009-10-28: Kieran Mansley - * tcp_in.c, tcp_out.c, tcp.h: re-work the fast retransmission code - to follow algorithm from TCP/IP Illustrated - - 2009-10-27: Kieran Mansley - * tcp_in.c: fix BUG#27445: grow cwnd with every duplicate ACK - - 2009-10-25: Simon Goldschmidt - * tcp.h: bug-fix in the TCP_EVENT_RECV macro (has to call tcp_recved if - pcb->recv is NULL to keep rcv_wnd correct) - - 2009-10-25: Simon Goldschmidt - * tcp_in.c: Fixed bug #26251: RST process in TIME_WAIT TCP state - - 2009-10-23: Simon Goldschmidt (David Empson) - * tcp.c: Fixed bug #27783: Silly window avoidance for small window sizes - - 2009-10-21: Simon Goldschmidt - * tcp_in.c: Fixed bug #27215: TCP sent() callback gives leading and - trailing 1 byte len (SYN/FIN) - - 2009-10-21: Simon Goldschmidt - * tcp_out.c: Fixed bug #27315: zero window probe and FIN - - 2009-10-19: Simon Goldschmidt - * dhcp.c/.h: Minor code simplification (don't store received pbuf, change - conditional code to assert where applicable), check pbuf length before - testing for valid reply - - 2009-10-19: Simon Goldschmidt - * dhcp.c: Removed most calls to udp_connect since they aren't necessary - when using udp_sendto_if() - always stay connected to IP_ADDR_ANY. - - 2009-10-16: Simon Goldschmidt - * ip.c: Fixed bug #27390: Source IP check in ip_input() causes it to drop - valid DHCP packets -> allow 0.0.0.0 as source address when LWIP_DHCP is - enabled - - 2009-10-15: Simon Goldschmidt (Oleg Tyshev) - * tcp_in.c: Fixed bug #27329: dupacks by unidirectional data transmit - - 2009-10-15: Simon Goldschmidt - * api_lib.c: Fixed bug #27709: conn->err race condition on netconn_recv() - timeout - - 2009-10-15: Simon Goldschmidt - * autoip.c: Fixed bug #27704: autoip starts with wrong address - LWIP_AUTOIP_CREATE_SEED_ADDR() returned address in host byte order instead - of network byte order - - 2009-10-11 Simon Goldschmidt (Jörg Kesten) - * tcp_out.c: Fixed bug #27504: tcp_enqueue wrongly concatenates segments - which are not consecutive when retransmitting unacked segments - - 2009-10-09 Simon Goldschmidt - * opt.h: Fixed default values of some stats to only be enabled if used - Fixes bug #27338: sys_stats is defined when NO_SYS = 1 - - 2009-08-30 Simon Goldschmidt - * ip.c: Fixed bug bug #27345: "ip_frag() does not use the LWIP_NETIF_LOOPBACK - function" by checking for loopback before calling ip_frag - - 2009-08-25 Simon Goldschmidt - * dhcp.c: fixed invalid dependency to etharp_query if DHCP_DOES_ARP_CHECK==0 - - 2009-08-23 Simon Goldschmidt - * ppp.c: bug #27078: Possible memory leak in pppInit() - - 2009-08-23 Simon Goldschmidt - * netdb.c, dns.c: bug #26657: DNS, if host name is "localhost", result - is error. - - 2009-08-23 Simon Goldschmidt - * opt.h, init.c: bug #26649: TCP fails when TCP_MSS > TCP_SND_BUF - Fixed wrong parenthesis, added check in init.c - - 2009-08-23 Simon Goldschmidt - * ppp.c: bug #27266: wait-state debug message in pppMain occurs every ms - - 2009-08-23 Simon Goldschmidt - * many ppp files: bug #27267: Added include to string.h where needed - - 2009-08-23 Simon Goldschmidt - * tcp.h: patch #6843: tcp.h macro optimization patch (for little endian) - - -(STABLE-1.3.1) - - ++ New features: - - 2009-05-10 Simon Goldschmidt - * opt.h, sockets.c, pbuf.c, netbuf.h, pbuf.h: task #7013: Added option - LWIP_NETIF_TX_SINGLE_PBUF to try to create transmit packets from only - one pbuf to help MACs that don't support scatter-gather DMA. - - 2009-05-09 Simon Goldschmidt - * icmp.h, icmp.c: Shrinked ICMP code, added option to NOT check icoming - ECHO pbuf for size (just use it): LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN - - 2009-05-05 Simon Goldschmidt, Jakob Stoklund Olesen - * ip.h, ip.c: Added ip_current_netif() & ip_current_header() to receive - extended info about the currently received packet. - - 2009-04-27 Simon Goldschmidt - * sys.h: Made SYS_LIGHTWEIGHT_PROT and sys_now() work with NO_SYS=1 - - 2009-04-25 Simon Goldschmidt - * mem.c, opt.h: Added option MEM_USE_POOLS_TRY_BIGGER_POOL to try the next - bigger malloc pool if one is empty (only usable with MEM_USE_POOLS). - - 2009-04-21 Simon Goldschmidt - * dns.c, init.c, dns.h, opt.h: task #7507, patch #6786: DNS supports static - hosts table. New configuration options DNS_LOCAL_HOSTLIST and - DNS_LOCAL_HOSTLIST_IS_DYNAMIC. Also, DNS_LOOKUP_LOCAL_EXTERN() can be defined - as an external function for lookup. - - 2009-04-15 Simon Goldschmidt - * dhcp.c: patch #6763: Global DHCP XID can be redefined to something more unique - - 2009-03-31 Kieran Mansley - * tcp.c, tcp_out.c, tcp_in.c, sys.h, tcp.h, opts.h: add support for - TCP timestamp options, off by default. Rework tcp_enqueue() to - take option flags rather than specified option data - - 2009-02-18 Simon Goldschmidt - * cc.h: Added printf formatter for size_t: SZT_F - - 2009-02-16 Simon Goldschmidt (patch by Rishi Khan) - * icmp.c, opt.h: patch #6539: (configurable) response to broadcast- and multicast - pings - - 2009-02-12 Simon Goldschmidt - * init.h: Added LWIP_VERSION to get the current version of the stack - - 2009-02-11 Simon Goldschmidt (suggested by Gottfried Spitaler) - * opt.h, memp.h/.c: added MEMP_MEM_MALLOC to use mem_malloc/mem_free instead - of the pool allocator (can save code size with MEM_LIBC_MALLOC if libc-malloc - is otherwise used) - - 2009-01-28 Jonathan Larmour (suggested by Bill Bauerbach) - * ipv4/inet_chksum.c, ipv4/lwip/inet_chksum.h: inet_chksum_pseudo_partial() - is only used by UDPLITE at present, so conditionalise it. - - 2008-12-03 Simon Goldschmidt (base on patch from Luca Ceresoli) - * autoip.c: checked in (slightly modified) patch #6683: Customizable AUTOIP - "seed" address. This should reduce AUTOIP conflicts if - LWIP_AUTOIP_CREATE_SEED_ADDR is overridden. - - 2008-10-02 Jonathan Larmour and Rishi Khan - * sockets.c (lwip_accept): Return EWOULDBLOCK if would block on non-blocking - socket. - - 2008-06-30 Simon Goldschmidt - * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from - interrupt context isn't safe: LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT allows - mem_free to run between mem_malloc iterations. Added illegal counter for - mem stats. - - 2008-06-27 Simon Goldschmidt - * stats.h/.c, some other files: patch #6483: stats module improvement: - Added defines to display each module's statistic individually, added stats - defines for MEM, MEMP and SYS modules, removed (unused) rexmit counter. - - 2008-06-17 Simon Goldschmidt - * err.h: patch #6459: Made err_t overridable to use a more efficient type - (define LWIP_ERR_T in cc.h) - - 2008-06-17 Simon Goldschmidt - * slipif.c: patch #6480: Added a configuration option for slipif for symmetry - to loopif - - 2008-06-17 Simon Goldschmidt (patch by Luca Ceresoli) - * netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly - modified version of patch # 6370: Moved loopif code to netif.c so that - loopback traffic is supported on all netifs (all local IPs). - Added option to limit loopback packets for each netifs. - - - ++ Bugfixes: - 2009-08-12 Kieran Mansley - * tcp_in.c, tcp.c: Fix bug #27209: handle trimming of segments when - out of window or out of order properly - - 2009-08-12 Kieran Mansley - * tcp_in.c: Fix bug #27199: use snd_wl2 instead of snd_wl1 - - 2009-07-28 Simon Goldschmidt - * mem.h: Fixed bug #27105: "realloc() cannot replace mem_realloc()"s - - 2009-07-27 Kieran Mansley - * api.h api_msg.h netdb.h sockets.h: add missing #include directives - - 2009-07-09 Kieran Mansley - * api_msg.c, sockets.c, api.h: BUG23240 use signed counters for - recv_avail and don't increment counters until message successfully - sent to mbox - - 2009-06-25 Kieran Mansley - * api_msg.c api.h: BUG26722: initialise netconn write variables - in netconn_alloc - - 2009-06-25 Kieran Mansley - * tcp.h: BUG26879: set ret value in TCP_EVENT macros when function is not set - - 2009-06-25 Kieran Mansley - * tcp.c, tcp_in.c, tcp_out.c, tcp.h: BUG26301 and BUG26267: correct - simultaneous close behaviour, and make snd_nxt have the same meaning - as in the RFCs. - - 2009-05-12 Simon Goldschmidt - * etharp.h, etharp.c, netif.c: fixed bug #26507: "Gratuitous ARP depends on - arp_table / uses etharp_query" by adding etharp_gratuitous() - - 2009-05-12 Simon Goldschmidt - * ip.h, ip.c, igmp.c: bug #26487: Added ip_output_if_opt that can add IP options - to the IP header (used by igmp_ip_output_if) - - 2009-05-06 Simon Goldschmidt - * inet_chksum.c: On little endian architectures, use LWIP_PLATFORM_HTONS (if - defined) for SWAP_BYTES_IN_WORD to speed up checksumming. - - 2009-05-05 Simon Goldschmidt - * sockets.c: bug #26405: Prematurely released semaphore causes lwip_select() - to crash - - 2009-05-04 Simon Goldschmidt - * init.c: snmp was not initialized in lwip_init() - - 2009-05-04 Frédéric Bernon - * dhcp.c, netbios.c: Changes if IP_SOF_BROADCAST is enabled. - - 2009-05-03 Simon Goldschmidt - * tcp.h: bug #26349: Nagle algorithm doesn't send although segment is full - (and unsent->next == NULL) - - 2009-05-02 Simon Goldschmidt - * tcpip.h, tcpip.c: fixed tcpip_untimeout (does not need the time, broken after - 1.3.0 in CVS only) - fixes compilation of ppp_oe.c - - 2009-05-02 Simon Goldschmidt - * msg_in.c: fixed bug #25636: SNMPSET value is ignored for integer fields - - 2009-05-01 Simon Goldschmidt - * pap.c: bug #21680: PPP upap_rauthnak() drops legal NAK packets - - 2009-05-01 Simon Goldschmidt - * ppp.c: bug #24228: Memory corruption with PPP and DHCP - - 2009-04-29 Frédéric Bernon - * raw.c, udp.c, init.c, opt.h, ip.h, sockets.h: bug #26309: Implement the - SO(F)_BROADCAST filter for all API layers. Avoid the unindented reception - of broadcast packets even when this option wasn't set. Port maintainers - which want to enable this filter have to set IP_SOF_BROADCAST=1 in opt.h. - If you want this option also filter broadcast on recv operations, you also - have to set IP_SOF_BROADCAST_RECV=1 in opt.h. - - 2009-04-28 Simon Goldschmidt, Jakob Stoklund Olesen - * dhcp.c: patch #6721, bugs #25575, #25576: Some small fixes to DHCP and - DHCP/AUTOIP cooperation - - 2009-04-25 Simon Goldschmidt, Oleg Tyshev - * tcp_out.c: bug #24212: Deadlocked tcp_retransmit due to exceeded pcb->cwnd - Fixed by sorting the unsent and unacked queues (segments are inserted at the - right place in tcp_output and tcp_rexmit). - - 2009-04-25 Simon Goldschmidt - * memp.c, mem.c, memp.h, mem_std.h: bug #26213 "Problem with memory allocation - when debugging": memp_sizes contained the wrong sizes (including sanity - regions); memp pools for MEM_USE_POOLS were too small - - 2009-04-24 Simon Goldschmidt, Frédéric Bernon - * inet.c: patch #6765: Fix a small problem with the last changes (incorrect - behavior, with with ip address string not ended by a '\0', a space or a - end of line) - - 2009-04-19 Simon Goldschmidt - * rawapi.txt: Fixed bug #26069: Corrected documentation: if tcp_connect fails, - pcb->err is called, not pcb->connected (with an error code). - - 2009-04-19 Simon Goldschmidt - * tcp_out.c: Fixed bug #26236: "TCP options (timestamp) don't work with - no-copy-tcpwrite": deallocate option data, only concat segments with same flags - - 2009-04-19 Simon Goldschmidt - * tcp_out.c: Fixed bug #25094: "Zero-length pbuf" (options are now allocated - in the header pbuf, not the data pbuf) - - 2009-04-18 Simon Goldschmidt - * api_msg.c: fixed bug #25695: Segmentation fault in do_writemore() - - 2009-04-15 Simon Goldschmidt - * sockets.c: tried to fix bug #23559: lwip_recvfrom problem with tcp - - 2009-04-15 Simon Goldschmidt - * dhcp.c: task #9192: mem_free of dhcp->options_in and dhcp->msg_in - - 2009-04-15 Simon Goldschmidt - * ip.c, ip6.c, tcp_out.c, ip.h: patch #6808: Add a utility function - ip_hinted_output() (for smaller code mainly) - - 2009-04-15 Simon Goldschmidt - * inet.c: patch #6765: Supporting new line characters in inet_aton() - - 2009-04-15 Simon Goldschmidt - * dhcp.c: patch #6764: DHCP rebind and renew did not send hostnam option; - Converted constant OPTION_MAX_MSG_SIZE to netif->mtu, check if netif->mtu - is big enough in dhcp_start - - 2009-04-15 Simon Goldschmidt - * netbuf.c: bug #26027: netbuf_chain resulted in pbuf memory leak - - 2009-04-15 Simon Goldschmidt - * sockets.c, ppp.c: bug #25763: corrected 4 occurrences of SMEMCPY to MEMCPY - - 2009-04-15 Simon Goldschmidt - * sockets.c: bug #26121: set_errno can be overridden - - 2009-04-09 Kieran Mansley (patch from Luca Ceresoli ) - * init.c, opt.h: Patch#6774 TCP_QUEUE_OOSEQ breaks compilation when - LWIP_TCP==0 - - 2009-04-09 Kieran Mansley (patch from Roy Lee ) - * tcp.h: Patch#6802 Add do-while-clauses to those function like - macros in tcp.h - - 2009-03-31 Kieran Mansley - * tcp.c, tcp_in.c, tcp_out.c, tcp.h, opt.h: Rework the way window - updates are calculated and sent (BUG20515) - - * tcp_in.c: cope with SYN packets received during established states, - and retransmission of initial SYN. - - * tcp_out.c: set push bit correctly when tcp segments are merged - - 2009-03-27 Kieran Mansley - * tcp_out.c set window correctly on probes (correcting change made - yesterday) - - 2009-03-26 Kieran Mansley - * tcp.c, tcp_in.c, tcp.h: add tcp_abandon() to cope with dropping - connections where no reset required (bug #25622) - - * tcp_out.c: set TCP_ACK flag on keepalive and zero window probes - (bug #20779) - - 2009-02-18 Simon Goldschmidt (Jonathan Larmour and Bill Auerbach) - * ip_frag.c: patch #6528: the buffer used for IP_FRAG_USES_STATIC_BUF could be - too small depending on MEM_ALIGNMENT - - 2009-02-16 Simon Goldschmidt - * sockets.h/.c, api_*.h/.c: fixed arguments of socket functions to match the standard; - converted size argument of netconn_write to 'size_t' - - 2009-02-16 Simon Goldschmidt - * tcp.h, tcp.c: fixed bug #24440: TCP connection close problem on 64-bit host - by moving accept callback function pointer to TCP_PCB_COMMON - - 2009-02-12 Simon Goldschmidt - * dhcp.c: fixed bug #25345 (DHCPDECLINE is sent with "Maximum message size" - option) - - 2009-02-11 Simon Goldschmidt - * dhcp.c: fixed bug #24480 (releasing old udp_pdb and pbuf in dhcp_start) - - 2009-02-11 Simon Goldschmidt - * opt.h, api_msg.c: added configurable default valud for netconn->recv_bufsize: - RECV_BUFSIZE_DEFAULT (fixes bug #23726: pbuf pool exhaustion on slow recv()) - - 2009-02-10 Simon Goldschmidt - * tcp.c: fixed bug #25467: Listen backlog is not reset on timeout in SYN_RCVD: - Accepts_pending is decrease on a corresponding listen pcb when a connection - in state SYN_RCVD is close. - - 2009-01-28 Jonathan Larmour - * pbuf.c: reclaim pbufs from TCP out-of-sequence segments if we run - out of pool pbufs. - - 2008-12-19 Simon Goldschmidt - * many files: patch #6699: fixed some warnings on platform where sizeof(int) == 2 - - 2008-12-10 Tamas Somogyi, Frédéric Bernon - * sockets.c: fixed bug #25051: lwip_recvfrom problem with udp: fromaddr and - port uses deleted netbuf. - - 2008-10-18 Simon Goldschmidt - * tcp_in.c: fixed bug ##24596: Vulnerability on faulty TCP options length - in tcp_parseopt - - 2008-10-15 Simon Goldschmidt - * ip_frag.c: fixed bug #24517: IP reassembly crashes on unaligned IP headers - by packing the struct ip_reass_helper. - - 2008-10-03 David Woodhouse, Jonathan Larmour - * etharp.c (etharp_arp_input): Fix type aliasing problem copying ip address. - - 2008-10-02 Jonathan Larmour - * dns.c: Hard-code structure sizes, to avoid issues on some compilers where - padding is included. - - 2008-09-30 Jonathan Larmour - * sockets.c (lwip_accept): check addr isn't NULL. If it's valid, do an - assertion check that addrlen isn't NULL. - - 2008-09-30 Jonathan Larmour - * tcp.c: Fix bug #24227, wrong error message in tcp_bind. - - 2008-08-26 Simon Goldschmidt - * inet.h, ip_addr.h: fixed bug #24132: Cross-dependency between ip_addr.h and - inet.h -> moved declaration of struct in_addr from ip_addr.h to inet.h - - 2008-08-14 Simon Goldschmidt - * api_msg.c: fixed bug #23847: do_close_internal references freed memory (when - tcp_close returns != ERR_OK) - - 2008-07-08 Frédéric Bernon - * stats.h: Fix some build bugs introduced with patch #6483 (missing some parameters - in macros, mainly if MEM_STATS=0 and MEMP_STATS=0). - - 2008-06-24 Jonathan Larmour - * tcp_in.c: Fix for bug #23693 as suggested by Art R. Ensure cseg is unused - if tcp_seg_copy fails. - - 2008-06-17 Simon Goldschmidt - * inet_chksum.c: Checked in some ideas of patch #6460 (loop optimizations) - and created defines for swapping bytes and folding u32 to u16. - - 2008-05-30 Kieran Mansley - * tcp_in.c Remove redundant "if" statement, and use real rcv_wnd - rather than rcv_ann_wnd when deciding if packets are in-window. - Contributed by - - 2008-05-30 Kieran Mansley - * mem.h: Fix BUG#23254. Change macro definition of mem_* to allow - passing as function pointers when MEM_LIBC_MALLOC is defined. - - 2008-05-09 Jonathan Larmour - * err.h, err.c, sockets.c: Fix bug #23119: Reorder timeout error code to - stop it being treated as a fatal error. - - 2008-04-15 Simon Goldschmidt - * dhcp.c: fixed bug #22804: dhcp_stop doesn't clear NETIF_FLAG_DHCP - (flag now cleared) - - 2008-03-27 Simon Goldschmidt - * mem.c, tcpip.c, tcpip.h, opt.h: fixed bug #21433 (Calling mem_free/pbuf_free - from interrupt context isn't safe): set LWIP_USE_HEAP_FROM_INTERRUPT to 1 - in lwipopts.h or use pbuf_free_callback(p)/mem_free_callback(m) to free pbufs - or heap memory from interrupt context - - 2008-03-26 Simon Goldschmidt - * tcp_in.c, tcp.c: fixed bug #22249: division by zero could occur if a remote - host sent a zero mss as TCP option. - - -(STABLE-1.3.0) - - ++ New features: - - 2008-03-10 Jonathan Larmour - * inet_chksum.c: Allow choice of one of the sample algorithms to be - made from lwipopts.h. Fix comment on how to override LWIP_CHKSUM. - - 2008-01-22 Frédéric Bernon - * tcp.c, tcp_in.c, tcp.h, opt.h: Rename LWIP_CALCULATE_EFF_SEND_MSS in - TCP_CALCULATE_EFF_SEND_MSS to have coherent TCP options names. - - 2008-01-14 Frédéric Bernon - * rawapi.txt, api_msg.c, tcp.c, tcp_in.c, tcp.h: changes for task #7675 "Enable - to refuse data on a TCP_EVENT_RECV call". Important, behavior changes for the - tcp_recv callback (see rawapi.txt). - - 2008-01-14 Frédéric Bernon, Marc Chaland - * ip.c: Integrate patch #6369" ip_input : checking before realloc". - - 2008-01-12 Frédéric Bernon - * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field - netconn::sem per netconn::op_completed like suggested for the task #7490 - "Add return value to sys_mbox_post". - - 2008-01-12 Frédéric Bernon - * api_msg.c, opt.h: replace DEFAULT_RECVMBOX_SIZE per DEFAULT_TCP_RECVMBOX_SIZE, - DEFAULT_UDP_RECVMBOX_SIZE and DEFAULT_RAW_RECVMBOX_SIZE (to optimize queues - sizes), like suggested for the task #7490 "Add return value to sys_mbox_post". - - 2008-01-10 Frédéric Bernon - * tcpip.h, tcpip.c: add tcpip_callback_with_block function for the task #7490 - "Add return value to sys_mbox_post". tcpip_callback is always defined as - "blocking" ("block" parameter = 1). - - 2008-01-10 Frédéric Bernon - * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field - netconn::mbox (sys_mbox_t) per netconn::sem (sys_sem_t) for the task #7490 - "Add return value to sys_mbox_post". - - 2008-01-05 Frédéric Bernon - * sys_arch.txt, api.h, api_lib.c, api_msg.h, api_msg.c, tcpip.c, sys.h, opt.h: - Introduce changes for task #7490 "Add return value to sys_mbox_post" with some - modifications in the sys_mbox api: sys_mbox_new take a "size" parameters which - indicate the number of pointers query by the mailbox. There is three defines - in opt.h to indicate sizes for tcpip::mbox, netconn::recvmbox, and for the - netconn::acceptmbox. Port maintainers, you can decide to just add this new - parameter in your implementation, but to ignore it to keep the previous behavior. - The new sys_mbox_trypost function return a value to know if the mailbox is - full or if the message is posted. Take a look to sys_arch.txt for more details. - This new function is used in tcpip_input (so, can be called in an interrupt - context since the function is not blocking), and in recv_udp and recv_raw. - - 2008-01-04 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour - * rawapi.txt, api.h, api_lib.c, api_msg.h, api_msg.c, sockets.c, tcp.h, tcp.c, - tcp_in.c, init.c, opt.h: rename backlog options with TCP_ prefix, limit the - "backlog" parameter in an u8_t, 0 is interpreted as "smallest queue", add - documentation in the rawapi.txt file. - - 2007-12-31 Kieran Mansley (based on patch from Per-Henrik Lundbolm) - * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Add TCP persist timer - - 2007-12-31 Frédéric Bernon, Luca Ceresoli - * autoip.c, etharp.c: ip_addr.h: Integrate patch #6348: "Broadcast ARP packets - in autoip". The change in etharp_raw could be removed, since all calls to - etharp_raw use ethbroadcast for the "ethdst_addr" parameter. But it could be - wrong in the future. - - 2007-12-30 Frédéric Bernon, Tom Evans - * ip.c: Fix bug #21846 "LwIP doesn't appear to perform any IP Source Address - Filtering" reported by Tom Evans. - - 2007-12-21 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour - * tcp.h, opt.h, api.h, api_msg.h, tcp.c, tcp_in.c, api_lib.c, api_msg.c, - sockets.c, init.c: task #7252: Implement TCP listen backlog: Warning: raw API - applications have to call 'tcp_accepted(pcb)' in their accept callback to - keep accepting new connections. - - 2007-12-13 Frédéric Bernon - * api_msg.c, err.h, err.c, sockets.c, dns.c, dns.h: replace "enum dns_result" - by err_t type. Add a new err_t code "ERR_INPROGRESS". - - 2007-12-12 Frédéric Bernon - * dns.h, dns.c, opt.h: move DNS options to the "right" place. Most visibles - are the one which have ram usage. - - 2007-12-05 Frédéric Bernon - * netdb.c: add a LWIP_DNS_API_HOSTENT_STORAGE option to decide to use a static - set of variables (=0) or a local one (=1). In this last case, your port should - provide a function "struct hostent* sys_thread_hostent( struct hostent* h)" - which have to do a copy of "h" and return a pointer ont the "per-thread" copy. - - 2007-12-03 Simon Goldschmidt - * ip.c: ip_input: check if a packet is for inp first before checking all other - netifs on netif_list (speeds up packet receiving in most cases) - - 2007-11-30 Simon Goldschmidt - * udp.c, raw.c: task #7497: Sort lists (pcb, netif, ...) for faster access - UDP: move a (connected) pcb selected for input to the front of the list of - pcbs so that it is found faster next time. Same for RAW pcbs that have eaten - a packet. - - 2007-11-28 Simon Goldschmidt - * etharp.c, stats.c, stats.h, opt.h: Introduced ETHARP_STATS - - 2007-11-25 Simon Goldschmidt - * dhcp.c: dhcp_unfold_reply() uses pbuf_copy_partial instead of its own copy - algorithm. - - 2007-11-24 Simon Goldschmidt - * netdb.h, netdb.c, sockets.h/.c: Moved lwip_gethostbyname from sockets.c - to the new file netdb.c; included lwip_getaddrinfo. - - 2007-11-21 Simon Goldschmidt - * tcp.h, opt.h, tcp.c, tcp_in.c: implemented calculating the effective send-mss - based on the MTU of the netif used to send. Enabled by default. Disable by - setting LWIP_CALCULATE_EFF_SEND_MSS to 0. This fixes bug #21492. - - 2007-11-19 Frédéric Bernon - * api_msg.c, dns.h, dns.c: Implement DNS_DOES_NAME_CHECK option (check if name - received match the name query), implement DNS_USES_STATIC_BUF (the place where - copy dns payload to parse the response), return an error if there is no place - for a new query, and fix some minor problems. - - 2007-11-16 Simon Goldschmidt - * new files: ipv4/inet.c, ipv4/inet_chksum.c, ipv6/inet6.c - removed files: core/inet.c, core/inet6.c - Moved inet files into ipv4/ipv6 directory; splitted inet.c/inet.h into - inet and chksum part; changed includes in all lwIP files as appropriate - - 2007-11-16 Simon Goldschmidt - * api.h, api_msg.h, api_lib.c, api_msg.c, socket.h, socket.c: Added sequential - dns resolver function for netconn api (netconn_gethostbyname) and socket api - (gethostbyname/gethostbyname_r). - - 2007-11-15 Jim Pettinato, Frédéric Bernon - * opt.h, init.c, tcpip.c, dhcp.c, dns.h, dns.c: add DNS client for simple name - requests with RAW api interface. Initialization is done in lwip_init() with - build time options. DNS timer is added in tcpip_thread context. DHCP can set - DNS server ip addresses when options are received. You need to set LWIP_DNS=1 - in your lwipopts.h file (LWIP_DNS=0 in opt.h). DNS_DEBUG can be set to get - some traces with LWIP_DEBUGF. Sanity check have been added. There is a "todo" - list with points to improve. - - 2007-11-06 Simon Goldschmidt - * opt.h, mib2.c: Patch #6215: added ifAdminStatus write support (if explicitly - enabled by defining SNMP_SAFE_REQUESTS to 0); added code to check link status - for ifOperStatus if LWIP_NETIF_LINK_CALLBACK is defined. - - 2007-11-06 Simon Goldschmidt - * api.h, api_msg.h and dependent files: Task #7410: Removed the need to include - core header files in api.h (ip/tcp/udp/raw.h) to hide the internal - implementation from netconn api applications. - - 2007-11-03 Frédéric Bernon - * api.h, api_lib.c, api_msg.c, sockets.c, opt.h: add SO_RCVBUF option for UDP & - RAW netconn. You need to set LWIP_SO_RCVBUF=1 in your lwipopts.h (it's disabled - by default). Netconn API users can use the netconn_recv_bufsize macro to access - it. This is a first release which have to be improve for TCP. Note it used the - netconn::recv_avail which need to be more "thread-safe" (note there is already - the problem for FIONREAD with lwip_ioctl/ioctlsocket). - - 2007-11-01 Frédéric Bernon, Marc Chaland - * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, tcp.h, tcp_out.c: - Integrate "patch #6250 : MSG_MORE flag for send". MSG_MORE is used at socket api - layer, NETCONN_MORE at netconn api layer, and TCP_WRITE_FLAG_MORE at raw api - layer. This option enable to delayed TCP PUSH flag on multiple "write" calls. - Note that previous "copy" parameter for "write" APIs is now called "apiflags". - - 2007-10-24 Frédéric Bernon - * api.h, api_lib.c, api_msg.c: Add macro API_EVENT in the same spirit than - TCP_EVENT_xxx macros to get a code more readable. It could also help to remove - some code (like we have talk in "patch #5919 : Create compile switch to remove - select code"), but it could be done later. - - 2007-10-08 Simon Goldschmidt - * many files: Changed initialization: many init functions are not needed any - more since we now rely on the compiler initializing global and static - variables to zero! - - 2007-10-06 Simon Goldschmidt - * ip_frag.c, memp.c, mib2.c, ip_frag.h, memp_std.h, opt.h: Changed IP_REASSEMBLY - to enqueue the received pbufs so that multiple packets can be reassembled - simultaneously and no static reassembly buffer is needed. - - 2007-10-05 Simon Goldschmidt - * tcpip.c, etharp.h, etharp.c: moved ethernet_input from tcpip.c to etharp.c so - all netifs (or ports) can use it. - - 2007-10-05 Frédéric Bernon - * netifapi.h, netifapi.c: add function netifapi_netif_set_default. Change the - common function to reduce a little bit the footprint (for all functions using - only the "netif" parameter). - - 2007-10-03 Frédéric Bernon - * netifapi.h, netifapi.c: add functions netifapi_netif_set_up, netifapi_netif_set_down, - netifapi_autoip_start and netifapi_autoip_stop. Use a common function to reduce - a little bit the footprint (for all functions using only the "netif" parameter). - - 2007-09-15 Frédéric Bernon - * udp.h, udp.c, sockets.c: Changes for "#20503 IGMP Improvement". Add IP_MULTICAST_IF - option in socket API, and a new field "multicast_ip" in "struct udp_pcb" (for - netconn and raw API users), only if LWIP_IGMP=1. Add getsockopt processing for - IP_MULTICAST_TTL and IP_MULTICAST_IF. - - 2007-09-10 Frédéric Bernon - * snmp.h, mib2.c: enable to remove SNMP timer (which consumne several cycles - even when it's not necessary). snmp_agent.txt tell to call snmp_inc_sysuptime() - each 10ms (but, it's intrusive if you use sys_timeout feature). Now, you can - decide to call snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but - call to a lower frequency). Or, you can decide to not call snmp_inc_sysuptime() - or snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro. - This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside - snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only - when it's queried (any direct call to "sysuptime" is changed by a call to - snmp_get_sysuptime). - - 2007-09-09 Frédéric Bernon, Bill Florac - * igmp.h, igmp.c, netif.h, netif.c, ip.c: To enable to have interfaces with IGMP, - and others without it, there is a new NETIF_FLAG_IGMP flag to set in netif->flags - if you want IGMP on an interface. igmp_stop() is now called inside netif_remove(). - igmp_report_groups() is now called inside netif_set_link_up() (need to have - LWIP_NETIF_LINK_CALLBACK=1) to resend reports once the link is up (avoid to wait - the next query message to receive the matching multicast streams). - - 2007-09-08 Frédéric Bernon - * sockets.c, ip.h, api.h, tcp.h: declare a "struct ip_pcb" which only contains - IP_PCB. Add in the netconn's "pcb" union a "struct ip_pcb *ip;" (no size change). - Use this new field to access to common pcb fields (ttl, tos, so_options, etc...). - Enable to access to these fields with LWIP_TCP=0. - - 2007-09-05 Frédéric Bernon - * udp.c, ipv4/icmp.c, ipv4/ip.c, ipv6/icmp.c, ipv6/ip6.c, ipv4/icmp.h, - ipv6/icmp.h, opt.h: Integrate "task #7272 : LWIP_ICMP option". The new option - LWIP_ICMP enable/disable ICMP module inside the IP stack (enable per default). - Be careful, disabling ICMP make your product non-compliant to RFC1122, but - help to reduce footprint, and to reduce "visibility" on the Internet. - - 2007-09-05 Frédéric Bernon, Bill Florac - * opt.h, sys.h, tcpip.c, slipif.c, ppp.c, sys_arch.txt: Change parameters list - for sys_thread_new (see "task #7252 : Create sys_thread_new_ex()"). Two new - parameters have to be provided: a task name, and a task stack size. For this - one, since it's platform dependant, you could define the best one for you in - your lwipopts.h. For port maintainers, you can just add these new parameters - in your sys_arch.c file, and but it's not mandatory, use them in your OS - specific functions. - - 2007-09-05 Frédéric Bernon - * inet.c, autoip.c, msg_in.c, msg_out.c, init.c: Move some build time checkings - inside init.c for task #7142 "Sanity check user-configurable values". - - 2007-09-04 Frédéric Bernon, Bill Florac - * igmp.h, igmp.c, memp_std.h, memp.c, init.c, opt.h: Replace mem_malloc call by - memp_malloc, and use a new MEMP_NUM_IGMP_GROUP option (see opt.h to define the - value). It will avoid potential fragmentation problems, use a counter to know - how many times a group is used on an netif, and free it when all applications - leave it. MEMP_NUM_IGMP_GROUP got 8 as default value (and init.c got a sanity - check if LWIP_IGMP!=0). - - 2007-09-03 Frédéric Bernon - * igmp.h, igmp.c, sockets.c, api_msg.c: Changes for "#20503 IGMP Improvement". - Initialize igmp_mac_filter to NULL in netif_add (this field should be set in - the netif's "init" function). Use the "imr_interface" field (for socket layer) - and/or the "interface" field (for netconn layer), for join/leave operations. - The igmp_join/leavegroup first parameter change from a netif to an ipaddr. - This field could be a netif's ipaddr, or "any" (same meaning than ip_addr_isany). - - 2007-08-30 Frédéric Bernon - * Add netbuf.h, netbuf.c, Change api.h, api_lib.c: #7249 "Split netbuf functions - from api/api_lib". Now netbuf API is independant of netconn, and can be used - with other API (application based on raw API, or future "socket2" API). Ports - maintainers just have to add src/api/netbuf.c in their makefile/projects. - - 2007-08-30 Frédéric Bernon, Jonathan Larmour - * init.c: Add first version of lwip_sanity_check for task #7142 "Sanity check - user-configurable values". - - 2007-08-29 Frédéric Bernon - * igmp.h, igmp.c, tcpip.c, init.c, netif.c: change igmp_init and add igmp_start. - igmp_start is call inside netif_add. Now, igmp initialization is in the same - spirit than the others modules. Modify some IGMP debug traces. - - 2007-08-29 Frédéric Bernon - * Add init.h, init.c, Change opt.h, tcpip.c: Task #7213 "Add a lwip_init function" - Add lwip_init function to regroup all modules initializations, and to provide - a place to add code for task #7142 "Sanity check user-configurable values". - Ports maintainers should remove direct initializations calls from their code, - and add init.c in their makefiles. Note that lwip_init() function is called - inside tcpip_init, but can also be used by raw api users since all calls are - disabled when matching options are disabled. Also note that their is new options - in opt.h, you should configure in your lwipopts.h (they are enabled per default). - - 2007-08-26 Marc Boucher - * api_msg.c: do_close_internal(): Reset the callbacks and arg (conn) to NULL - since they can under certain circumstances be called with an invalid conn - pointer after the connection has been closed (and conn has been freed). - - 2007-08-25 Frédéric Bernon (Artem Migaev's Patch) - * netif.h, netif.c: Integrate "patch #6163 : Function to check if link layer is up". - Add a netif_is_link_up() function if LWIP_NETIF_LINK_CALLBACK option is set. - - 2007-08-22 Frédéric Bernon - * netif.h, netif.c, opt.h: Rename LWIP_NETIF_CALLBACK in LWIP_NETIF_STATUS_CALLBACK - to be coherent with new LWIP_NETIF_LINK_CALLBACK option before next release. - - 2007-08-22 Frédéric Bernon - * tcpip.h, tcpip.c, ethernetif.c, opt.h: remove options ETHARP_TCPIP_INPUT & - ETHARP_TCPIP_ETHINPUT, now, only "ethinput" code is supported, even if the - name is tcpip_input (we keep the name of 1.2.0 function). - - 2007-08-17 Jared Grubb - * memp_std.h, memp.h, memp.c, mem.c, stats.c: (Task #7136) Centralize mempool - settings into new memp_std.h and optional user file lwippools.h. This adds - more dynamic mempools, and allows the user to create an arbitrary number of - mempools for mem_malloc. - - 2007-08-16 Marc Boucher - * api_msg.c: Initialize newconn->state to NETCONN_NONE in accept_function; - otherwise it was left to NETCONN_CLOSE and sent_tcp() could prematurely - close the connection. - - 2007-08-16 Marc Boucher - * sockets.c: lwip_accept(): check netconn_peer() error return. - - 2007-08-16 Marc Boucher - * mem.c, mem.h: Added mem_calloc(). - - 2007-08-16 Marc Boucher - * tcpip.c, tcpip.h memp.c, memp.h: Added distinct memp (MEMP_TCPIP_MSG_INPKT) - for input packets to prevent floods from consuming all of MEMP_TCPIP_MSG - and starving other message types. - Renamed MEMP_TCPIP_MSG to MEMP_TCPIP_MSG_API - - 2007-08-16 Marc Boucher - * pbuf.c, pbuf.h, etharp.c, tcp_in.c, sockets.c: Split pbuf flags in pbuf - type and flgs (later renamed to flags). - Use enum pbuf_flag as pbuf_type. Renumber PBUF_FLAG_*. - Improved lwip_recvfrom(). TCP push now propagated. - - 2007-08-16 Marc Boucher - * ethernetif.c, contrib/ports/various: ethbroadcast now a shared global - provided by etharp. - - 2007-08-16 Marc Boucher - * ppp_oe.c ppp_oe.h, auth.c chap.c fsm.c lcp.c ppp.c ppp.h, - etharp.c ethernetif.c, etharp.h, opt.h tcpip.h, tcpip.c: - Added PPPoE support and various PPP improvements. - - 2007-07-25 Simon Goldschmidt - * api_lib.c, ip_frag.c, pbuf.c, api.h, pbuf.h: Introduced pbuf_copy_partial, - making netbuf_copy_partial use this function. - - 2007-07-25 Simon Goldschmidt - * tcp_in.c: Fix bug #20506: Slow start / initial congestion window starts with - 2 * mss (instead of 1 * mss previously) to comply with some newer RFCs and - other stacks. - - 2007-07-13 Jared Grubb (integrated by Frédéric Bernon) - * opt.h, netif.h, netif.c, ethernetif.c: Add new configuration option to add - a link callback in the netif struct, and functions to handle it. Be carefull - for port maintainers to add the NETIF_FLAG_LINK_UP flag (like in ethernetif.c) - if you want to be sure to be compatible with future changes... - - 2007-06-30 Frédéric Bernon - * sockets.h, sockets.c: Implement MSG_PEEK flag for recv/recvfrom functions. - - 2007-06-21 Simon Goldschmidt - * etharp.h, etharp.c: Combined etharp_request with etharp_raw for both - LWIP_AUTOIP =0 and =1 to remove redundant code. - - 2007-06-21 Simon Goldschmidt - * mem.c, memp.c, mem.h, memp.h, opt.h: task #6863: Introduced the option - MEM_USE_POOLS to use 4 pools with different sized elements instead of a - heap. This both prevents memory fragmentation and gives a higher speed - at the cost of more memory consumption. Turned off by default. - - 2007-06-21 Simon Goldschmidt - * api_lib.c, api_msg.c, api.h, api_msg.h: Converted the length argument of - netconn_write (and therefore also api_msg_msg.msg.w.len) from u16_t into - int to be able to send a bigger buffer than 64K with one time (mainly - used from lwip_send). - - 2007-06-21 Simon Goldschmidt - * tcp.h, api_msg.c: Moved the nagle algorithm from netconn_write/do_write - into a define (tcp_output_nagle) in tcp.h to provide it to raw api users, too. - - 2007-06-21 Simon Goldschmidt - * api.h, api_lib.c, api_msg.c: Fixed bug #20021: Moved sendbuf-processing in - netconn_write from api_lib.c to api_msg.c to also prevent multiple context- - changes on low memory or empty send-buffer. - - 2007-06-18 Simon Goldschmidt - * etharp.c, etharp.h: Changed etharp to use a defined hardware address length - of 6 to avoid loading netif->hwaddr_len every time (since this file is only - used for ethernet and struct eth_addr already had a defined length of 6). - - 2007-06-17 Simon Goldschmidt - * sockets.c, sockets.h: Implemented socket options SO_NO_CHECK for UDP sockets - to disable UDP checksum generation on transmit. - - 2007-06-13 Frédéric Bernon, Simon Goldschmidt - * debug.h, api_msg.c: change LWIP_ERROR to use it to check errors like invalid - pointers or parameters, and let the possibility to redefined it in cc.h. Use - this macro to check "conn" parameter in api_msg.c functions. - - 2007-06-11 Simon Goldschmidt - * sockets.c, sockets.h: Added UDP lite support for sockets - - 2007-06-10 Simon Goldschmidt - * udp.h, opt.h, api_msg.c, ip.c, udp.c: Included switch LWIP_UDPLITE (enabled - by default) to switch off UDP-Lite support if not needed (reduces udp.c code - size) - - 2007-06-09 Dominik Spies (integrated by Frédéric Bernon) - * autoip.h, autoip.c, dhcp.h, dhcp.c, netif.h, netif.c, etharp.h, etharp.c, opt.h: - AutoIP implementation available for IPv4, with new options LWIP_AUTOIP and - LWIP_DHCP_AUTOIP_COOP if you want to cooperate with DHCP. Some tips to adapt - (see TODO mark in the source code). - - 2007-06-09 Simon Goldschmidt - * etharp.h, etharp.c, ethernetif.c: Modified order of parameters for - etharp_output() to match netif->output so etharp_output() can be used - directly as netif->output to save one function call. - - 2007-06-08 Simon Goldschmidt - * netif.h, ethernetif.c, slipif.c, loopif.c: Added define - NETIF_INIT_SNMP(netif, type, speed) to initialize per-netif snmp variables, - added initialization of those to ethernetif, slipif and loopif. - - 2007-05-18 Simon Goldschmidt - * opt.h, ip_frag.c, ip_frag.h, ip.c: Added option IP_FRAG_USES_STATIC_BUF - (defaulting to off for now) that can be set to 0 to send fragmented - packets by passing PBUF_REFs down the stack. - - 2007-05-23 Frédéric Bernon - * api_lib.c: Implement SO_RCVTIMEO for accept and recv on TCP - connections, such present in patch #5959. - - 2007-05-23 Frédéric Bernon - * api.h, api_lib.c, api_msg.c, sockets.c: group the different NETCONN_UDPxxx - code in only one part... - - 2007-05-18 Simon Goldschmidt - * opt.h, memp.h, memp.c: Added option MEMP_OVERFLOW_CHECK to check for memp - elements to overflow. This is achieved by adding some bytes before and after - each pool element (increasing their size, of course), filling them with a - prominent value and checking them on freeing the element. - Set it to 2 to also check every element in every pool each time memp_malloc() - or memp_free() is called (slower but more helpful). - - 2007-05-10 Simon Goldschmidt - * opt.h, memp.h, memp.c, pbuf.c (see task #6831): use a new memp pool for - PBUF_POOL pbufs instead of the old pool implementation in pbuf.c to reduce - code size. - - 2007-05-11 Frédéric Bernon - * sockets.c, api_lib.c, api_msg.h, api_msg.c, netifapi.h, netifapi.c, tcpip.c: - Include a function pointer instead of a table index in the message to reduce - footprint. Disable some part of lwip_send and lwip_sendto if some options are - not set (LWIP_TCP, LWIP_UDP, LWIP_RAW). - - 2007-05-10 Simon Goldschmidt - * *.h (except netif/ppp/*.h): Included patch #5448: include '#ifdef __cplusplus - \ extern "C" {' in all header files. Now you can write your application using - the lwIP stack in C++ and simply #include the core files. Note I have left - out the netif/ppp/*h header files for now, since I don't know which files are - included by applications and which are for internal use only. - - 2007-05-09 Simon Goldschmidt - * opt.h, *.c/*.h: Included patch #5920: Create define to override C-library - memcpy. 2 Defines are created: MEMCPY() for normal memcpy, SMEMCPY() for - situations where some compilers might inline the copy and save a function - call. Also replaced all calls to memcpy() with calls to (S)MEMCPY(). - - 2007-05-08 Simon Goldschmidt - * mem.h: If MEM_LIBC_MALLOC==1, allow the defines (e.g. mem_malloc() -> malloc()) - to be overriden in case the C-library malloc implementation is not protected - against concurrent access. - - 2007-05-04 Simon Goldschmidt (Atte Kojo) - * etharp.c: Introduced fast one-entry-cache to speed up ARP lookup when sending - multiple packets to the same host. - - 2007-05-04 Frédéric Bernon, Jonathan Larmour - * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible - to corrupt remote addr/port connection state". Reduce problems "not enought memory" with - netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between - sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function. - Warning, if you directly access to "fromaddr" & "fromport" field from netbuf struct, - these fields are now renamed "addr" & "port". - - 2007-04-11 Jonathan Larmour - * sys.h, api_lib.c: Provide new sys_mbox_tryfetch function. Require ports to provide new - sys_arch_mbox_tryfetch function to get a message if one is there, otherwise return - with SYS_MBOX_EMPTY. sys_arch_mbox_tryfetch can be implemented as a function-like macro - by the port in sys_arch.h if desired. - - 2007-04-06 Frédéric Bernon, Simon Goldschmidt - * opt.h, tcpip.h, tcpip.c, netifapi.h, netifapi.c: New configuration option LWIP_NETIF_API - allow to use thread-safe functions to add/remove netif in list, and to start/stop dhcp - clients, using new functions from netifapi.h. Disable as default (no port change to do). - - 2007-04-05 Frédéric Bernon - * sockets.c: remplace ENOBUFS errors on alloc_socket by ENFILE to be more BSD compliant. - - 2007-04-04 Simon Goldschmidt - * arch.h, api_msg.c, dhcp.c, msg_in.c, sockets.c: Introduced #define LWIP_UNUSED_ARG(x) - use this for and architecture-independent form to tell the compiler you intentionally - are not using this variable. Can be overriden in cc.h. - - 2007-03-28 Frédéric Bernon - * opt.h, netif.h, dhcp.h, dhcp.c: New configuration option LWIP_NETIF_HOSTNAME allow to - define a hostname in netif struct (this is just a pointer, so, you can use a hardcoded - string, point on one of your's ethernetif field, or alloc a string you will free yourself). - It will be used by DHCP to register a client hostname, but can also be use when you call - snmp_set_sysname. - - 2007-03-28 Frédéric Bernon - * netif.h, netif.c: A new NETIF_FLAG_ETHARP flag is defined in netif.h, to allow to - initialize a network interface's flag with. It tell this interface is an ethernet - device, and we can use ARP with it to do a "gratuitous ARP" (RFC 3220 "IP Mobility - Support for IPv4" section 4.6) when interface is "up" with netif_set_up(). - - 2007-03-26 Frédéric Bernon, Jonathan Larmour - * opt.h, tcpip.c: New configuration option LWIP_ARP allow to disable ARP init at build - time if you only use PPP or SLIP. The default is enable. Note we don't have to call - etharp_init in your port's initilization sequence if you use tcpip.c, because this call - is done in tcpip_init function. - - 2007-03-22 Frédéric Bernon - * stats.h, stats.c, msg_in.c: Stats counters can be change to u32_t if necessary with the - new option LWIP_STATS_LARGE. If you need this option, define LWIP_STATS_LARGE to 1 in - your lwipopts.h. More, unused counters are not defined in the stats structs, and not - display by stats_display(). Note that some options (SYS_STATS and RAW_STATS) are defined - but never used. Fix msg_in.c with the correct #if test for a stat display. - - 2007-03-21 Kieran Mansley - * netif.c, netif.h: Apply patch#4197 with some changes (originator: rireland@hmgsl.com). - Provides callback on netif up/down state change. - - 2007-03-11 Frédéric Bernon, Mace Gael, Steve Reynolds - * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, igmp.h, igmp.c, - ip.c, netif.h, tcpip.c, opt.h: - New configuration option LWIP_IGMP to enable IGMP processing. Based on only one - filter per all network interfaces. Declare a new function in netif to enable to - control the MAC filter (to reduce lwIP traffic processing). - - 2007-03-11 Frédéric Bernon - * tcp.h, tcp.c, sockets.c, tcp_out.c, tcp_in.c, opt.h: Keepalive values can - be configured at run time with LWIP_TCP_KEEPALIVE, but don't change this - unless you know what you're doing (default are RFC1122 compliant). Note - that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set in seconds. - - 2007-03-08 Frédéric Bernon - * tcp.h: Keepalive values can be configured at compile time, but don't change - this unless you know what you're doing (default are RFC1122 compliant). - - 2007-03-08 Frédéric Bernon - * sockets.c, api.h, api_lib.c, tcpip.c, sys.h, sys.c, err.c, opt.h: - Implement LWIP_SO_RCVTIMEO configuration option to enable/disable SO_RCVTIMEO - on UDP sockets/netconn. - - 2007-03-08 Simon Goldschmidt - * snmp_msg.h, msg_in.c: SNMP UDP ports can be configured at compile time. - - 2007-03-06 Frédéric Bernon - * api.h, api_lib.c, sockets.h, sockets.c, tcpip.c, sys.h, sys.c, err.h: - Implement SO_RCVTIMEO on UDP sockets/netconn. - - 2007-02-28 Kieran Mansley (based on patch from Simon Goldschmidt) - * api_lib.c, tcpip.c, memp.c, memp.h: make API msg structs allocated - on the stack and remove the API msg type from memp - - 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) - * sockets.h, sockets.c: Move socket initialization to new - lwip_socket_init() function. - NOTE: this changes the API with ports. Ports will have to be - updated to call lwip_socket_init() now. - - 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) - * api_lib.c: Use memcpy in netbuf_copy_partial. - - - ++ Bug fixes: - - 2008-03-17 Frédéric Bernon, Ed Kerekes - * igmp.h, igmp.c: Fix bug #22613 "IGMP iphdr problem" (could have - some problems to fill the IP header on some targets, use now the - ip.h macros to do it). - - 2008-03-13 Frédéric Bernon - * sockets.c: Fix bug #22435 "lwip_recvfrom with TCP break;". Using - (lwip_)recvfrom with valid "from" and "fromlen" parameters, on a - TCP connection caused a crash. Note that using (lwip_)recvfrom - like this is a bit slow and that using (lwip)getpeername is the - good lwip way to do it (so, using recv is faster on tcp sockets). - - 2008-03-12 Frédéric Bernon, Jonathan Larmour - * api_msg.c, contrib/apps/ping.c: Fix bug #22530 "api_msg.c's - recv_raw() does not consume data", and the ping sample (with - LWIP_SOCKET=1, the code did the wrong supposition that lwip_recvfrom - returned the IP payload, without the IP header). - - 2008-03-04 Jonathan Larmour - * mem.c, stats.c, mem.h: apply patch #6414 to avoid compiler errors - and/or warnings on some systems where mem_size_t and size_t differ. - * pbuf.c, ppp.c: Fix warnings on some systems with mem_malloc. - - 2008-03-04 Kieran Mansley (contributions by others) - * Numerous small compiler error/warning fixes from contributions to - mailing list after 1.3.0 release candidate made. - - 2008-01-25 Cui hengbin (integrated by Frédéric Bernon) - * dns.c: Fix bug #22108 "DNS problem" caused by unaligned structures. - - 2008-01-15 Kieran Mansley - * tcp_out.c: BUG20511. Modify persist timer to start when we are - prevented from sending by a small send window, not just a zero - send window. - - 2008-01-09 Jonathan Larmour - * opt.h, ip.c: Rename IP_OPTIONS define to IP_OPTIONS_ALLOWED to avoid - conflict with Linux system headers. - - 2008-01-06 Jonathan Larmour - * dhcp.c: fix bug #19927: "DHCP NACK problem" by clearing any existing set IP - address entirely on receiving a DHCPNAK, and restarting discovery. - - 2007-12-21 Simon Goldschmidt - * sys.h, api_lib.c, api_msg.c, sockets.c: fix bug #21698: "netconn->recv_avail - is not protected" by using new macros for interlocked access to modify/test - netconn->recv_avail. - - 2007-12-20 Kieran Mansley (based on patch from Oleg Tyshev) - * tcp_in.c: fix bug# 21535 (nrtx not reset correctly in SYN_SENT state) - - 2007-12-20 Kieran Mansley (based on patch from Per-Henrik Lundbolm) - * tcp.c, tcp_in.c, tcp_out.c, tcp.h: fix bug #20199 (better handling - of silly window avoidance and prevent lwIP from shrinking the window) - - 2007-12-04 Simon Goldschmidt - * tcp.c, tcp_in.c: fix bug #21699 (segment leak in ooseq processing when last - data packet was lost): add assert that all segment lists are empty in - tcp_pcb_remove before setting pcb to CLOSED state; don't directly set CLOSED - state from LAST_ACK in tcp_process - - 2007-12-02 Simon Goldschmidt - * sockets.h: fix bug #21654: exclude definition of struct timeval from #ifndef FD_SET - If including for system-struct timeval, LWIP_TIMEVAL_PRIVATE now - has to be set to 0 in lwipopts.h - - 2007-12-02 Simon Goldschmidt - * api_msg.c, api_lib.c: fix bug #21656 (recvmbox problem in netconn API): always - allocate a recvmbox in netconn_new_with_proto_and_callback. For a tcp-listen - netconn, this recvmbox is later freed and a new mbox is allocated for acceptmbox. - This is a fix for thread-safety and allocates all items needed for a netconn - when the netconn is created. - - 2007-11-30 Simon Goldschmidt - * udp.c: first attempt to fix bug #21655 (DHCP doesn't work reliably with multiple - netifs): if LWIP_DHCP is enabled, UDP packets to DHCP_CLIENT_PORT are passed - to netif->dhcp->pcb only (if that exists) and not to any other pcb for the same - port (only solution to let UDP pcbs 'bind' to a netif instead of an IP address) - - 2007-11-27 Simon Goldschmidt - * ip.c: fixed bug #21643 (udp_send/raw_send don't fail if netif is down) by - letting ip_route only use netifs that are up. - - 2007-11-27 Simon Goldschmidt - * err.h, api_lib.c, api_msg.c, sockets.c: Changed error handling: ERR_MEM, ERR_BUF - and ERR_RTE are seen as non-fatal, all other errors are fatal. netconns and - sockets block most operations once they have seen a fatal error. - - 2007-11-27 Simon Goldschmidt - * udp.h, udp.c, dhcp.c: Implemented new function udp_sendto_if which takes the - netif to send as an argument (to be able to send on netifs that are down). - - 2007-11-26 Simon Goldschmidt - * tcp_in.c: Fixed bug #21582: pcb->acked accounting can be wrong when ACKs - arrive out-of-order - - 2007-11-21 Simon Goldschmidt - * tcp.h, tcp_out.c, api_msg.c: Fixed bug #20287: tcp_output_nagle sends too early - Fixed the nagle algorithm; nagle now also works for all raw API applications - and has to be explicitly disabled with 'tcp_pcb->flags |= TF_NODELAY' - - 2007-11-12 Frédéric Bernon - * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fixed bug #20900. Now, most - of the netconn_peer and netconn_addr processing is done inside tcpip_thread - context in do_getaddr. - - 2007-11-10 Simon Goldschmidt - * etharp.c: Fixed bug: assert fired when MEMP_ARP_QUEUE was empty (which can - happen any time). Now the packet simply isn't enqueued when out of memory. - - 2007-11-01 Simon Goldschmidt - * tcp.c, tcp_in.c: Fixed bug #21494: The send mss (pcb->mss) is set to 536 (or - TCP_MSS if that is smaller) as long as no MSS option is received from the - remote host. - - 2007-11-01 Simon Goldschmidt - * tcp.h, tcp.c, tcp_in.c: Fixed bug #21491: The MSS option sent (with SYN) - is now based on TCP_MSS instead of pcb->mss (on passive open now effectively - sending our configured TCP_MSS instead of the one received). - - 2007-11-01 Simon Goldschmidt - * tcp_in.c: Fixed bug #21181: On active open, the initial congestion window was - calculated based on the configured TCP_MSS, not on the MSS option received - with SYN+ACK. - - 2007-10-09 Simon Goldschmidt - * udp.c, inet.c, inet.h: Fixed UDPLite: send: Checksum was always generated too - short and also was generated wrong if checksum coverage != tot_len; - receive: checksum was calculated wrong if checksum coverage != tot_len - - 2007-10-08 Simon Goldschmidt - * mem.c: lfree was not updated in mem_realloc! - - 2007-10-07 Frédéric Bernon - * sockets.c, api.h, api_lib.c: First step to fix "bug #20900 : Potential - crash error problem with netconn_peer & netconn_addr". VERY IMPORTANT: - this change cause an API breakage for netconn_addr, since a parameter - type change. Any compiler should cause an error without any changes in - yours netconn_peer calls (so, it can't be a "silent change"). It also - reduce a little bit the footprint for socket layer (lwip_getpeername & - lwip_getsockname use now a common lwip_getaddrname function since - netconn_peer & netconn_addr have the same parameters). - - 2007-09-20 Simon Goldschmidt - * tcp.c: Fixed bug #21080 (tcp_bind without check pcbs in TIME_WAIT state) - by checking tcp_tw_pcbs also - - 2007-09-19 Simon Goldschmidt - * icmp.c: Fixed bug #21107 (didn't reset IP TTL in ICMP echo replies) - - 2007-09-15 Mike Kleshov - * mem.c: Fixed bug #21077 (inaccuracy in calculation of lwip_stat.mem.used) - - 2007-09-06 Frédéric Bernon - * several-files: replace some #include "arch/cc.h" by "lwip/arch.h", or simply remove - it as long as "lwip/opt.h" is included before (this one include "lwip/debug.h" which - already include "lwip/arch.h"). Like that, default defines are provided by "lwip/arch.h" - if they are not defined in cc.h, in the same spirit than "lwip/opt.h" for lwipopts.h. - - 2007-08-30 Frédéric Bernon - * igmp.h, igmp.c: Some changes to remove some redundant code, add some traces, - and fix some coding style. - - 2007-08-28 Frédéric Bernon - * tcpip.c: Fix TCPIP_MSG_INPKT processing: now, tcpip_input can be used for any - kind of packets. These packets are considered like Ethernet packets (payload - pointing to ethhdr) if the netif got the NETIF_FLAG_ETHARP flag. Else, packets - are considered like IP packets (payload pointing to iphdr). - - 2007-08-27 Frédéric Bernon - * api.h, api_lib.c, api_msg.c: First fix for "bug #20900 : Potential crash error - problem with netconn_peer & netconn_addr". Introduce NETCONN_LISTEN netconn_state - and remove obsolete ones (NETCONN_RECV & NETCONN_ACCEPT). - - 2007-08-24 Kieran Mansley - * inet.c Modify (acc >> 16) test to ((acc >> 16) != 0) to help buggy - compiler (Paradigm C++) - - 2007-08-09 Frédéric Bernon, Bill Florac - * stats.h, stats.c, igmp.h, igmp.c, opt.h: Fix for bug #20503 : IGMP Improvement. - Introduce IGMP_STATS to centralize statistics management. - - 2007-08-09 Frédéric Bernon, Bill Florac - * udp.c: Fix for bug #20503 : IGMP Improvement. Enable to receive a multicast - packet on a udp pcb binded on an netif's IP address, and not on "any". - - 2007-08-09 Frédéric Bernon, Bill Florac - * igmp.h, igmp.c, ip.c: Fix minor changes from bug #20503 : IGMP Improvement. - This is mainly on using lookup/lookfor, and some coding styles... - - 2007-07-26 Frédéric Bernon (and "thedoctor") - * igmp.c: Fix bug #20595 to accept IGMPv3 "Query" messages. - - 2007-07-25 Simon Goldschmidt - * api_msg.c, tcp.c: Another fix for bug #20021: by not returning an error if - tcp_output fails in tcp_close, the code in do_close_internal gets simpler - (tcp_output is called again later from tcp timers). - - 2007-07-25 Simon Goldschmidt - * ip_frag.c: Fixed bug #20429: use the new pbuf_copy_partial instead of the old - copy_from_pbuf, which illegally modified the given pbuf. - - 2007-07-25 Simon Goldschmidt - * tcp_out.c: tcp_enqueue: pcb->snd_queuelen didn't work for chaine PBUF_RAMs: - changed snd_queuelen++ to snd_queuelen += pbuf_clen(p). - - 2007-07-24 Simon Goldschmidt - * api_msg.c, tcp.c: Fix bug #20480: Check the pcb passed to tcp_listen() for the - correct state (must be CLOSED). - - 2007-07-13 Thomas Taranowski (commited by Jared Grubb) - * memp.c: Fix bug #20478: memp_malloc returned NULL+MEMP_SIZE on failed - allocation. It now returns NULL. - - 2007-07-13 Frédéric Bernon - * api_msg.c: Fix bug #20318: api_msg "recv" callbacks don't call pbuf_free in - all error cases. - - 2007-07-13 Frédéric Bernon - * api_msg.c: Fix bug #20315: possible memory leak problem if tcp_listen failed, - because current code doesn't follow rawapi.txt documentation. - - 2007-07-13 Kieran Mansley - * src/core/tcp_in.c Apply patch#5741 from Oleg Tyshev to fix bug in - out of sequence processing of received packets - - 2007-07-03 Simon Goldschmidt - * nearly-all-files: Added assertions where PBUF_RAM pbufs are used and an - assumption is made that this pbuf is in one piece (i.e. not chained). These - assumptions clash with the possibility of converting to fully pool-based - pbuf implementations, where PBUF_RAM pbufs might be chained. - - 2007-07-03 Simon Goldschmidt - * api.h, api_lib.c, api_msg.c: Final fix for bug #20021 and some other problems - when closing tcp netconns: removed conn->sem, less context switches when - closing, both netconn_close and netconn_delete should safely close tcp - connections. - - 2007-07-02 Simon Goldschmidt - * ipv4/ip.h, ipv6/ip.h, opt.h, netif.h, etharp.h, ipv4/ip.c, netif.c, raw.c, - tcp_out.c, udp.c, etharp.c: Added option LWIP_NETIF_HWADDRHINT (default=off) - to cache ARP table indices with each pcb instead of single-entry cache for - the complete stack. - - 2007-07-02 Simon Goldschmidt - * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Added some ASSERTS and casts to prevent - warnings when assigning to smaller types. - - 2007-06-28 Simon Goldschmidt - * tcp_out.c: Added check to prevent tcp_pcb->snd_queuelen from overflowing. - - 2007-06-28 Simon Goldschmidt - * tcp.h: Fixed bug #20287: Fixed nagle algorithm (sending was done too early if - a segment contained chained pbufs) - - 2007-06-28 Frédéric Bernon - * autoip.c: replace most of rand() calls by a macro LWIP_AUTOIP_RAND which compute - a "pseudo-random" value based on netif's MAC and some autoip fields. It's always - possible to define this macro in your own lwipopts.h to always use C library's - rand(). Note that autoip_create_rand_addr doesn't use this macro. - - 2007-06-28 Frédéric Bernon - * netifapi.h, netifapi.c, tcpip.h, tcpip.c: Update code to handle the option - LWIP_TCPIP_CORE_LOCKING, and do some changes to be coherent with last modifications - in api_lib/api_msg (use pointers and not type with table, etc...) - - 2007-06-26 Simon Goldschmidt - * udp.h: Fixed bug #20259: struct udp_hdr was lacking the packin defines. - - 2007-06-25 Simon Goldschmidt - * udp.c: Fixed bug #20253: icmp_dest_unreach was called with a wrong p->payload - for udp packets with no matching pcb. - - 2007-06-25 Simon Goldschmidt - * udp.c: Fixed bug #20220: UDP PCB search in udp_input(): a non-local match - could get udp input packets if the remote side matched. - - 2007-06-13 Simon Goldschmidt - * netif.c: Fixed bug #20180 (TCP pcbs listening on IP_ADDR_ANY could get - changed in netif_set_ipaddr if previous netif->ip_addr.addr was 0. - - 2007-06-13 Simon Goldschmidt - * api_msg.c: pcb_new sets conn->err if protocol is not implemented - -> netconn_new_..() does not allocate a new connection for unsupported - protocols. - - 2007-06-13 Frédéric Bernon, Simon Goldschmidt - * api_lib.c: change return expression in netconn_addr and netconn_peer, because - conn->err was reset to ERR_OK without any reasons (and error was lost)... - - 2007-06-13 Frédéric Bernon, Matthias Weisser - * opt.h, mem.h, mem.c, memp.c, pbuf.c, ip_frag.c, vj.c: Fix bug #20162. Rename - MEM_ALIGN in LWIP_MEM_ALIGN and MEM_ALIGN_SIZE in LWIP_MEM_ALIGN_SIZE to avoid - some macro names collision with some OS macros. - - 2007-06-11 Simon Goldschmidt - * udp.c: UDP Lite: corrected the use of chksum_len (based on RFC3828: if it's 0, - create checksum over the complete packet. On RX, if it's < 8 (and not 0), - discard the packet. Also removed the duplicate 'udphdr->chksum = 0' for both - UDP & UDP Lite. - - 2007-06-11 Srinivas Gollakota & Oleg Tyshev - * tcp_out.c: Fix for bug #20075 : "A problem with keep-alive timer and TCP flags" - where TCP flags wasn't initialized in tcp_keepalive. - - 2007-06-03 Simon Goldschmidt - * udp.c: udp_input(): Input pbuf was not freed if pcb had no recv function - registered, p->payload was modified without modifying p->len if sending - icmp_dest_unreach() (had no negative effect but was definitively wrong). - - 2007-06-03 Simon Goldschmidt - * icmp.c: Corrected bug #19937: For responding to an icmp echo request, icmp - re-used the input pbuf even if that didn't have enough space to include the - link headers. Now the space is tested and a new pbuf is allocated for the - echo response packet if the echo request pbuf isn't big enough. - - 2007-06-01 Simon Goldschmidt - * sockets.c: Checked in patch #5914: Moved sockopt processing into tcpip_thread. - - 2007-05-23 Frédéric Bernon - * api_lib.c, sockets.c: Fixed bug #5958 for netconn_listen (acceptmbox only - allocated by do_listen if success) and netconn_accept errors handling. In - most of api_lib functions, we replace some errors checkings like "if (conn==NULL)" - by ASSERT, except for netconn_delete. - - 2007-05-23 Frédéric Bernon - * api_lib.c: Fixed bug #5957 "Safe-thread problem inside netconn_recv" to return - an error code if it's impossible to fetch a pbuf on a TCP connection (and not - directly close the recvmbox). - - 2007-05-22 Simon Goldschmidt - * tcp.c: Fixed bug #1895 (tcp_bind not correct) by introducing a list of - bound but unconnected (and non-listening) tcp_pcbs. - - 2007-05-22 Frédéric Bernon - * sys.h, sys.c, api_lib.c, tcpip.c: remove sys_mbox_fetch_timeout() (was only - used for LWIP_SO_RCVTIMEO option) and use sys_arch_mbox_fetch() instead of - sys_mbox_fetch() in api files. Now, users SHOULD NOT use internal lwIP features - like "sys_timeout" in their application threads. - - 2007-05-22 Frédéric Bernon - * api.h, api_lib.c, api_msg.h, api_msg.c: change the struct api_msg_msg to see - which parameters are used by which do_xxx function, and to avoid "misusing" - parameters (patch #5938). - - 2007-05-22 Simon Goldschmidt - * api_lib.c, api_msg.c, raw.c, api.h, api_msg.h, raw.h: Included patch #5938: - changed raw_pcb.protocol from u16_t to u8_t since for IPv4 and IPv6, proto - is only 8 bits wide. This affects the api, as there, the protocol was - u16_t, too. - - 2007-05-18 Simon Goldschmidt - * memp.c: addition to patch #5913: smaller pointer was returned but - memp_memory was the same size -> did not save memory. - - 2007-05-16 Simon Goldschmidt - * loopif.c, slipif.c: Fix bug #19729: free pbuf if netif->input() returns - != ERR_OK. - - 2007-05-16 Simon Goldschmidt - * api_msg.c, udp.c: If a udp_pcb has a local_ip set, check if it is the same - as the one of the netif used for sending to prevent sending from old - addresses after a netif address gets changed (partly fixes bug #3168). - - 2007-05-16 Frédéric Bernon - * tcpip.c, igmp.h, igmp.c: Fixed bug "#19800 : IGMP: igmp_tick() will not work - with NO_SYS=1". Note that igmp_init is always in tcpip_thread (and not in - tcpip_init) because we have to be sure that network interfaces are already - added (mac filter is updated only in igmp_init for the moment). - - 2007-05-16 Simon Goldschmidt - * mem.c, memp.c: Removed semaphores from memp, changed sys_sem_wait calls - into sys_arch_sem_wait calls to prevent timers from running while waiting - for the heap. This fixes bug #19167. - - 2007-05-13 Simon Goldschmidt - * tcp.h, sockets.h, sockets.c: Fixed bug from patch #5865 by moving the defines - for socket options (lwip_set/-getsockopt) used with level IPPROTO_TCP from - tcp.h to sockets.h. - - 2007-05-07 Simon Goldschmidt - * mem.c: Another attempt to fix bug #17922. - - 2007-05-04 Simon Goldschmidt - * pbuf.c, pbuf.h, etharp.c: Further update to ARP queueing: Changed pbuf_copy() - implementation so that it can be reused (don't allocate the target - pbuf inside pbuf_copy()). - - 2007-05-04 Simon Goldschmidt - * memp.c: checked in patch #5913: in memp_malloc() we can return memp as mem - to save a little RAM (next pointer of memp is not used while not in pool). - - 2007-05-03 "maq" - * sockets.c: Fix ioctl FIONREAD when some data remains from last recv. - (patch #3574). - - 2007-04-23 Simon Goldschmidt - * loopif.c, loopif.h, opt.h, src/netif/FILES: fix bug #2595: "loopif results - in NULL reference for incoming TCP packets". Loopif has to be configured - (using LWIP_LOOPIF_MULTITHREADING) to directly call netif->input() - (multithreading environments, e.g. netif->input() = tcpip_input()) or - putting packets on a list that is fed to the stack by calling loopif_poll() - (single-thread / NO_SYS / polling environment where e.g. - netif->input() = ip_input). - - 2007-04-17 Jonathan Larmour - * pbuf.c: Use s32_t in pbuf_realloc(), as an s16_t can't reliably hold - the difference between two u16_t's. - * sockets.h: FD_SETSIZE needs to match number of sockets, which is - MEMP_NUM_NETCONN in sockets.c right now. - - 2007-04-12 Jonathan Larmour - * icmp.c: Reset IP header TTL in ICMP ECHO responses (bug #19580). - - 2007-04-12 Kieran Mansley - * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Modify way the retransmission - timer is reset to fix bug#19434, with help from Oleg Tyshev. - - 2007-04-11 Simon Goldschmidt - * etharp.c, pbuf.c, pbuf.h: 3rd fix for bug #11400 (arp-queuing): More pbufs than - previously thought need to be copied (everything but PBUF_ROM!). Cleaned up - pbuf.c: removed functions no needed any more (by etharp). - - 2007-04-11 Kieran Mansley - * inet.c, ip_addr.h, sockets.h, sys.h, tcp.h: Apply patch #5745: Fix - "Constant is long" warnings with 16bit compilers. Contributed by - avatar@mmlab.cse.yzu.edu.tw - - 2007-04-05 Frédéric Bernon, Jonathan Larmour - * api_msg.c: Fix bug #16830: "err_tcp() posts to connection mailbox when no pend on - the mailbox is active". Now, the post is only done during a connect, and do_send, - do_write and do_join_leave_group don't do anything if a previous error was signaled. - - 2007-04-03 Frédéric Bernon - * ip.c: Don't set the IP_DF ("Don't fragment") flag in the IP header in IP output - packets. See patch #5834. - - 2007-03-30 Frédéric Bernon - * api_msg.c: add a "pcb_new" helper function to avoid redundant code, and to add - missing pcb allocations checking (in do_bind, and for each raw_new). Fix style. - - 2007-03-30 Frédéric Bernon - * most of files: prefix all debug.h define with "LWIP_" to avoid any conflict with - others environment defines (these were too "generic"). - - 2007-03-28 Frédéric Bernon - * api.h, api_lib.c, sockets.c: netbuf_ref doesn't check its internal pbuf_alloc call - result and can cause a crash. lwip_send now check netbuf_ref result. - - 2007-03-28 Simon Goldschmidt - * sockets.c Remove "#include " from sockets.c to avoid multiple - definition of macros (in errno.h and lwip/arch.h) if LWIP_PROVIDE_ERRNO is - defined. This is the way it should have been already (looking at - doc/sys_arch.txt) - - 2007-03-28 Kieran Mansley - * opt.h Change default PBUF_POOL_BUFSIZE (again) to accomodate default MSS + - IP and TCP headers *and* physical link headers - - 2007-03-26 Frédéric Bernon (based on patch from Dmitry Potapov) - * api_lib.c: patch for netconn_write(), fixes a possible race condition which cause - to send some garbage. It is not a definitive solution, but the patch does solve - the problem for most cases. - - 2007-03-22 Frédéric Bernon - * api_msg.h, api_msg.c: Remove obsolete API_MSG_ACCEPT and do_accept (never used). - - 2007-03-22 Frédéric Bernon - * api_lib.c: somes resources couldn't be freed if there was errors during - netconn_new_with_proto_and_callback. - - 2007-03-22 Frédéric Bernon - * ethernetif.c: update netif->input calls to check return value. In older ports, - it's a good idea to upgrade them, even if before, there could be another problem - (access to an uninitialized mailbox). - - 2007-03-21 Simon Goldschmidt - * sockets.c: fixed bug #5067 (essentialy a signed/unsigned warning fixed - by casting to unsigned). - - 2007-03-21 Frédéric Bernon - * api_lib.c, api_msg.c, tcpip.c: integrate sys_mbox_fetch(conn->mbox, NULL) calls from - api_lib.c to tcpip.c's tcpip_apimsg(). Now, use a local variable and not a - dynamic one from memp to send tcpip_msg to tcpip_thread in a synchrone call. - Free tcpip_msg from tcpip_apimsg is not done in tcpip_thread. This give a - faster and more reliable communication between api_lib and tcpip. - - 2007-03-21 Frédéric Bernon - * opt.h: Add LWIP_NETIF_CALLBACK (to avoid compiler warning) and set it to 0. - - 2007-03-21 Frédéric Bernon - * api_msg.c, igmp.c, igmp.h: Fix C++ style comments - - 2007-03-21 Kieran Mansley - * opt.h Change default PBUF_POOL_BUFSIZE to accomodate default MSS + - IP and TCP headers - - 2007-03-21 Kieran Mansley - * Fix all uses of pbuf_header to check the return value. In some - cases just assert if it fails as I'm not sure how to fix them, but - this is no worse than before when they would carry on regardless - of the failure. - - 2007-03-21 Kieran Mansley - * sockets.c, igmp.c, igmp.h, memp.h: Fix C++ style comments and - comment out missing header include in icmp.c - - 2007-03-20 Frédéric Bernon - * memp.h, stats.c: Fix stats_display function where memp_names table wasn't - synchronized with memp.h. - - 2007-03-20 Frédéric Bernon - * tcpip.c: Initialize tcpip's mbox, and verify if initialized in tcpip_input, - tcpip_ethinput, tcpip_callback, tcpip_apimsg, to fix a init problem with - network interfaces. Also fix a compiler warning. - - 2007-03-20 Kieran Mansley - * udp.c: Only try and use pbuf_header() to make space for headers if - not a ROM or REF pbuf. - - 2007-03-19 Frédéric Bernon - * api_msg.h, api_msg.c, tcpip.h, tcpip.c: Add return types to tcpip_apimsg() - and api_msg_post(). - - 2007-03-19 Frédéric Bernon - * Remove unimplemented "memp_realloc" function from memp.h. - - 2007-03-11 Simon Goldschmidt - * pbuf.c: checked in patch #5796: pbuf_alloc: len field claculation caused - memory corruption. - - 2007-03-11 Simon Goldschmidt (based on patch from Dmitry Potapov) - * api_lib.c, sockets.c, api.h, api_msg.h, sockets.h: Fixed bug #19251 - (missing `const' qualifier in socket functions), to get more compatible to - standard POSIX sockets. - - 2007-03-11 Frédéric Bernon (based on patch from Dmitry Potapov) - * sockets.c: Add asserts inside bind, connect and sendto to check input - parameters. Remove excessive set_errno() calls after get_socket(), because - errno is set inside of get_socket(). Move last sock_set_errno() inside - lwip_close. - - 2007-03-09 Simon Goldschmidt - * memp.c: Fixed bug #11400: New etharp queueing introduced bug: memp_memory - was allocated too small. - - 2007-03-06 Simon Goldschmidt - * tcpip.c: Initialize dhcp timers in tcpip_thread (if LWIP_DHCP) to protect - the stack from concurrent access. - - 2007-03-06 Frédéric Bernon, Dmitry Potapov - * tcpip.c, ip_frag.c, ethernetif.c: Fix some build problems, and a redundancy - call to "lwip_stats.link.recv++;" in low_level_input() & ethernetif_input(). - - 2007-03-06 Simon Goldschmidt - * ip_frag.c, ip_frag.h: Reduce code size: don't include code in those files - if IP_FRAG == 0 and IP_REASSEMBLY == 0 - - 2007-03-06 Frédéric Bernon, Simon Goldschmidt - * opt.h, ip_frag.h, tcpip.h, tcpip.c, ethernetif.c: add new configuration - option named ETHARP_TCPIP_ETHINPUT, which enable the new tcpip_ethinput. - Allow to do ARP processing for incoming packets inside tcpip_thread - (protecting ARP layer against concurrent access). You can also disable - old code using tcp_input with new define ETHARP_TCPIP_INPUT set to 0. - Older ports have to use tcpip_ethinput. - - 2007-03-06 Simon Goldschmidt (based on patch from Dmitry Potapov) - * err.h, err.c: fixed compiler warning "initialization dircards qualifiers - from pointer target type" - - 2007-03-05 Frédéric Bernon - * opt.h, sockets.h: add new configuration options (LWIP_POSIX_SOCKETS_IO_NAMES, - ETHARP_TRUST_IP_MAC, review SO_REUSE) - - 2007-03-04 Frédéric Bernon - * api_msg.c: Remove some compiler warnings : parameter "pcb" was never - referenced. - - 2007-03-04 Frédéric Bernon - * api_lib.c: Fix "[patch #5764] api_lib.c cleanup: after patch #5687" (from - Dmitry Potapov). - The api_msg struct stay on the stack (not moved to netconn struct). - - 2007-03-04 Simon Goldschmidt (based on patch from Dmitry Potapov) - * pbuf.c: Fix BUG#19168 - pbuf_free can cause deadlock (if - SYS_LIGHTWEIGHT_PROT=1 & freeing PBUF_RAM when mem_sem is not available) - Also fixed cast warning in pbuf_alloc() - - 2007-03-04 Simon Goldschmidt - * etharp.c, etharp.h, memp.c, memp.h, opt.h: Fix BUG#11400 - don't corrupt - existing pbuf chain when enqueuing multiple pbufs to a pending ARP request - - 2007-03-03 Frédéric Bernon - * udp.c: remove obsolete line "static struct udp_pcb *pcb_cache = NULL;" - It is static, and never used in udp.c except udp_init(). - - 2007-03-02 Simon Goldschmidt - * tcpip.c: Moved call to ip_init(), udp_init() and tcp_init() from - tcpip_thread() to tcpip_init(). This way, raw API connections can be - initialized before tcpip_thread is running (e.g. before OS is started) - - 2007-03-02 Frédéric Bernon - * rawapi.txt: Fix documentation mismatch with etharp.h about etharp_tmr's call - interval. - - 2007-02-28 Kieran Mansley - * pbuf.c: Fix BUG#17645 - ensure pbuf payload pointer is not moved - outside the region of the pbuf by pbuf_header() - - 2007-02-28 Kieran Mansley - * sockets.c: Fix BUG#19161 - ensure milliseconds timeout is non-zero - when supplied timeout is also non-zero - -(STABLE-1.2.0) - - 2006-12-05 Leon Woestenberg - * CHANGELOG: Mention STABLE-1.2.0 release. - - ++ New features: - - 2006-12-01 Christiaan Simons - * mem.h, opt.h: Added MEM_LIBC_MALLOC option. - Note this is a workaround. Currently I have no other options left. - - 2006-10-26 Christiaan Simons (accepted patch by Jonathan Larmour) - * ipv4/ip_frag.c: rename MAX_MTU to IP_FRAG_MAX_MTU and move define - to include/lwip/opt.h. - * ipv4/lwip/ip_frag.h: Remove unused IP_REASS_INTERVAL. - Move IP_REASS_MAXAGE and IP_REASS_BUFSIZE to include/lwip/opt.h. - * opt.h: Add above new options. - - 2006-08-18 Christiaan Simons - * tcp_{in,out}.c: added SNMP counters. - * ipv4/ip.c: added SNMP counters. - * ipv4/ip_frag.c: added SNMP counters. - - 2006-08-08 Christiaan Simons - * etharp.{c,h}: added etharp_find_addr() to read - (stable) ethernet/IP address pair from ARP table - - 2006-07-14 Christiaan Simons - * mib_structs.c: added - * include/lwip/snmp_structs.h: added - * netif.{c,h}, netif/ethernetif.c: added SNMP statistics to netif struct - - 2006-07-06 Christiaan Simons - * snmp/asn1_{enc,dec}.c added - * snmp/mib2.c added - * snmp/msg_{in,out}.c added - * include/lwip/snmp_asn1.h added - * include/lwip/snmp_msg.h added - * doc/snmp_agent.txt added - - 2006-03-29 Christiaan Simons - * inet.c, inet.h: Added platform byteswap support. - Added LWIP_PLATFORM_BYTESWAP define (defaults to 0) and - optional LWIP_PLATFORM_HTONS(), LWIP_PLATFORM_HTONL() macros. - - ++ Bug fixes: - - 2006-11-30 Christiaan Simons - * dhcp.c: Fixed false triggers of request_timeout. - - 2006-11-28 Christiaan Simons - * netif.c: In netif_add() fixed missing clear of ip_addr, netmask, gw and flags. - - 2006-10-11 Christiaan Simons - * api_lib.c etharp.c, ip.c, memp.c, stats.c, sys.{c,h} tcp.h: - Partially accepted patch #5449 for ANSI C compatibility / build fixes. - * ipv4/lwip/ip.h ipv6/lwip/ip.h: Corrected UDP-Lite protocol - identifier from 170 to 136 (bug #17574). - - 2006-10-10 Christiaan Simons - * api_msg.c: Fixed Nagle algorithm as reported by Bob Grice. - - 2006-08-17 Christiaan Simons - * udp.c: Fixed bug #17200, added check for broadcast - destinations for PCBs bound to a unicast address. - - 2006-08-07 Christiaan Simons - * api_msg.c: Flushing TCP output in do_close() (bug #15926). - - 2006-06-27 Christiaan Simons - * api_msg.c: Applied patch for cold case (bug #11135). - In accept_function() ensure newconn->callback is always initialized. - - 2006-06-15 Christiaan Simons - * mem.h: added MEM_SIZE_F alias to fix an ancient cold case (bug #1748), - facilitate printing of mem_size_t and u16_t statistics. - - 2006-06-14 Christiaan Simons - * api_msg.c: Applied patch #5146 to handle allocation failures - in accept() by Kevin Lawson. - - 2006-05-26 Christiaan Simons - * api_lib.c: Removed conn->sem creation and destruction - from netconn_write() and added sys_sem_new to netconn_new_*. - -(STABLE-1_1_1) - - 2006-03-03 Christiaan Simons - * ipv4/ip_frag.c: Added bound-checking assertions on ip_reassbitmap - access and added pbuf_alloc() return value checks. - - 2006-01-01 Leon Woestenberg - * tcp_{in,out}.c, tcp_out.c: Removed 'even sndbuf' fix in TCP, which is - now handled by the checksum routine properly. - - 2006-02-27 Leon Woestenberg - * pbuf.c: Fix alignment; pbuf_init() would not work unless - pbuf_pool_memory[] was properly aligned. (Patch by Curt McDowell.) - - 2005-12-20 Leon Woestenberg - * tcp.c: Remove PCBs which stay in LAST_ACK state too long. Patch - submitted by Mitrani Hiroshi. - - 2005-12-15 Christiaan Simons - * inet.c: Disabled the added summing routine to preserve code space. - - 2005-12-14 Leon Woestenberg - * tcp_in.c: Duplicate FIN ACK race condition fix by Kelvin Lawson. - Added Curt McDowell's optimized checksumming routine for future - inclusion. Need to create test case for unaliged, aligned, odd, - even length combination of cases on various endianess machines. - - 2005-12-09 Christiaan Simons - * inet.c: Rewrote standard checksum routine in proper portable C. - - 2005-11-25 Christiaan Simons - * udp.c tcp.c: Removed SO_REUSE hack. Should reside in socket code only. - * *.c: introduced cc.h LWIP_DEBUG formatters matching the u16_t, s16_t, - u32_t, s32_t typedefs. This solves most debug word-length assumes. - - 2005-07-17 Leon Woestenberg - * inet.c: Fixed unaligned 16-bit access in the standard checksum - routine by Peter Jolasson. - * slipif.c: Fixed implementation assumption of single-pbuf datagrams. - - 2005-02-04 Leon Woestenberg - * tcp_out.c: Fixed uninitialized 'queue' referenced in memerr branch. - * tcp_{out|in}.c: Applied patch fixing unaligned access. - - 2005-01-04 Leon Woestenberg - * pbuf.c: Fixed missing semicolon after LWIP_DEBUG statement. - - 2005-01-03 Leon Woestenberg - * udp.c: UDP pcb->recv() was called even when it was NULL. - -(STABLE-1_1_0) - - 2004-12-28 Leon Woestenberg - * etharp.*: Disabled multiple packets on the ARP queue. - This clashes with TCP queueing. - - 2004-11-28 Leon Woestenberg - * etharp.*: Fixed race condition from ARP request to ARP timeout. - Halved the ARP period, doubled the period counts. - ETHARP_MAX_PENDING now should be at least 2. This prevents - the counter from reaching 0 right away (which would allow - too little time for ARP responses to be received). - - 2004-11-25 Leon Woestenberg - * dhcp.c: Decline messages were not multicast but unicast. - * etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD. - Do not try hard to insert arbitrary packet's source address, - etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD. - etharp_query() now always DOES call ETHARP_TRY_HARD so that users - querying an address will see it appear in the cache (DHCP could - suffer from this when a server invalidly gave an in-use address.) - * ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are - comparing network addresses (identifiers), not the network masks - themselves. - * ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given - IP address actually belongs to the network of the given interface. - - 2004-11-24 Kieran Mansley - * tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state. - -(STABLE-1_1_0-RC1) - - 2004-10-16 Kieran Mansley - * tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately, - even if one is already pending, if the rcv_wnd is above a threshold - (currently TCP_WND/2). This avoids waiting for a timer to expire to send a - delayed ACK in order to open the window if the stack is only receiving data. - - 2004-09-12 Kieran Mansley - * tcp*.*: Retransmit time-out handling improvement by Sam Jansen. - - 2004-08-20 Tony Mountifield - * etharp.c: Make sure the first pbuf queued on an ARP entry - is properly ref counted. - - 2004-07-27 Tony Mountifield - * debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler - warnings about comparison. - * pbuf.c: Stopped compiler complaining of empty if statement - when LWIP_DEBUGF() empty. Closed an unclosed comment. - * tcp.c: Stopped compiler complaining of empty if statement - when LWIP_DEBUGF() empty. - * ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons(). - * inet.c: Added a couple of casts to quiet the compiler. - No need to test isascii(c) before isdigit(c) or isxdigit(c). - - 2004-07-22 Tony Mountifield - * inet.c: Made data types consistent in inet_ntoa(). - Added casts for return values of checksum routines, to pacify compiler. - * ip_frag.c, tcp_out.c, sockets.c, pbuf.c - Small corrections to some debugging statements, to pacify compiler. - - 2004-07-21 Tony Mountifield - * etharp.c: Removed spurious semicolon and added missing end-of-comment. - * ethernetif.c Updated low_level_output() to match prototype for - netif->linkoutput and changed low_level_input() similarly for consistency. - * api_msg.c: Changed recv_raw() from int to u8_t, to match prototype - of raw_recv() in raw.h and so avoid compiler error. - * sockets.c: Added trivial (int) cast to keep compiler happier. - * ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros. - -(STABLE-1_0_0) - - ++ Changes: - - 2004-07-05 Leon Woestenberg - * sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure - your cc.h file defines this either 1 or 0. If non-defined, - defaults to 1. - * .c: Added and includes where used. - * etharp.c: Made some array indices unsigned. - - 2004-06-27 Leon Woestenberg - * netif.*: Added netif_set_up()/down(). - * dhcp.c: Changes to restart program flow. - - 2004-05-07 Leon Woestenberg - * etharp.c: In find_entry(), instead of a list traversal per candidate, do a - single-pass lookup for different candidates. Should exploit locality. - - 2004-04-29 Leon Woestenberg - * tcp*.c: Cleaned up source comment documentation for Doxygen processing. - * opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC. - * etharp.c: update_arp_entry() only adds new ARP entries when adviced to by - the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option. - - ++ Bug fixes: - - 2004-04-27 Leon Woestenberg - * etharp.c: Applied patch of bug #8708 by Toni Mountifield with a solution - suggested by Timmy Brolin. Fix for 32-bit processors that cannot access - non-aligned 32-bit words, such as soms 32-bit TCP/IP header fields. Fix - is to prefix the 14-bit Ethernet headers with two padding bytes. - - 2004-04-23 Leon Woestenberg - * ip_addr.c: Fix in the ip_addr_isbroadcast() check. - * etharp.c: Fixed the case where the packet that initiates the ARP request - is not queued, and gets lost. Fixed the case where the packets destination - address is already known; we now always queue the packet and perform an ARP - request. - -(STABLE-0_7_0) - - ++ Bug fixes: - - * Fixed TCP bug for SYN_SENT to ESTABLISHED state transition. - * Fixed TCP bug in dequeueing of FIN from out of order segment queue. - * Fixed two possible NULL references in rare cases. - -(STABLE-0_6_6) - - ++ Bug fixes: - - * Fixed DHCP which did not include the IP address in DECLINE messages. - - ++ Changes: - - * etharp.c has been hauled over a bit. - -(STABLE-0_6_5) - - ++ Bug fixes: - - * Fixed TCP bug induced by bad window resizing with unidirectional TCP traffic. - * Packets sent from ARP queue had invalid source hardware address. - - ++ Changes: - - * Pass-by ARP requests do now update the cache. - - ++ New features: - - * No longer dependent on ctype.h. - * New socket options. - * Raw IP pcb support. - -(STABLE-0_6_4) - - ++ Bug fixes: - - * Some debug formatters and casts fixed. - * Numereous fixes in PPP. - - ++ Changes: - - * DEBUGF now is LWIP_DEBUGF - * pbuf_dechain() has been re-enabled. - * Mentioned the changed use of CVS branches in README. - -(STABLE-0_6_3) - - ++ Bug fixes: - - * Fixed pool pbuf memory leak in pbuf_alloc(). - Occured if not enough PBUF_POOL pbufs for a packet pbuf chain. - Reported by Savin Zlobec. - - * PBUF_POOL chains had their tot_len field not set for non-first - pbufs. Fixed in pbuf_alloc(). - - ++ New features: - - * Added PPP stack contributed by Marc Boucher - - ++ Changes: - - * Now drops short packets for ICMP/UDP/TCP protocols. More robust. - - * ARP queueuing now queues the latest packet instead of the first. - This is the RFC recommended behaviour, but can be overridden in - lwipopts.h. - -(0.6.2) - - ++ Bugfixes: - - * TCP has been fixed to deal with the new use of the pbuf->ref - counter. - - * DHCP dhcp_inform() crash bug fixed. - - ++ Changes: - - * Removed pbuf_pool_free_cache and pbuf_pool_alloc_cache. Also removed - pbuf_refresh(). This has sped up pbuf pool operations considerably. - Implemented by David Haas. - -(0.6.1) - - ++ New features: - - * The packet buffer implementation has been enhanced to support - zero-copy and copy-on-demand for packet buffers which have their - payloads in application-managed memory. - Implemented by David Haas. - - Use PBUF_REF to make a pbuf refer to RAM. lwIP will use zero-copy - if an outgoing packet can be directly sent on the link, or perform - a copy-on-demand when necessary. - - The application can safely assume the packet is sent, and the RAM - is available to the application directly after calling udp_send() - or similar function. - - ++ Bugfixes: - - * ARP_QUEUEING should now correctly work for all cases, including - PBUF_REF. - Implemented by Leon Woestenberg. - - ++ Changes: - - * IP_ADDR_ANY is no longer a NULL pointer. Instead, it is a pointer - to a '0.0.0.0' IP address. - - * The packet buffer implementation is changed. The pbuf->ref counter - meaning has changed, and several pbuf functions have been - adapted accordingly. - - * netif drivers have to be changed to set the hardware address length field - that must be initialized correctly by the driver (hint: 6 for Ethernet MAC). - See the contrib/ports/c16x cs8900 driver as a driver example. - - * netif's have a dhcp field that must be initialized to NULL by the driver. - See the contrib/ports/c16x cs8900 driver as a driver example. - -(0.5.x) This file has been unmaintained up to 0.6.1. All changes are - logged in CVS but have not been explained here. - -(0.5.3) Changes since version 0.5.2 - - ++ Bugfixes: - - * memp_malloc(MEMP_API_MSG) could fail with multiple application - threads because it wasn't protected by semaphores. - - ++ Other changes: - - * struct ip_addr now packed. - - * The name of the time variable in arp.c has been changed to ctime - to avoid conflicts with the time() function. - -(0.5.2) Changes since version 0.5.1 - - ++ New features: - - * A new TCP function, tcp_tmr(), now handles both TCP timers. - - ++ Bugfixes: - - * A bug in tcp_parseopt() could cause the stack to hang because of a - malformed TCP option. - - * The address of new connections in the accept() function in the BSD - socket library was not handled correctly. - - * pbuf_dechain() did not update the ->tot_len field of the tail. - - * Aborted TCP connections were not handled correctly in all - situations. - - ++ Other changes: - - * All protocol header structs are now packed. - - * The ->len field in the tcp_seg structure now counts the actual - amount of data, and does not add one for SYN and FIN segments. - -(0.5.1) Changes since version 0.5.0 - - ++ New features: - - * Possible to run as a user process under Linux. - - * Preliminary support for cross platform packed structs. - - * ARP timer now implemented. - - ++ Bugfixes: - - * TCP output queue length was badly initialized when opening - connections. - - * TCP delayed ACKs were not sent correctly. - - * Explicit initialization of BSS segment variables. - - * read() in BSD socket library could drop data. - - * Problems with memory alignment. - - * Situations when all TCP buffers were used could lead to - starvation. - - * TCP MSS option wasn't parsed correctly. - - * Problems with UDP checksum calculation. - - * IP multicast address tests had endianess problems. - - * ARP requests had wrong destination hardware address. - - ++ Other changes: - - * struct eth_addr changed from u16_t[3] array to u8_t[6]. - - * A ->linkoutput() member was added to struct netif. - - * TCP and UDP ->dest_* struct members where changed to ->remote_*. - - * ntoh* macros are now null definitions for big endian CPUs. - -(0.5.0) Changes since version 0.4.2 - - ++ New features: - - * Redesigned operating system emulation layer to make porting easier. - - * Better control over TCP output buffers. - - * Documenation added. - - ++ Bugfixes: - - * Locking issues in buffer management. - - * Bugfixes in the sequential API. - - * IP forwarding could cause memory leakage. This has been fixed. - - ++ Other changes: - - * Directory structure somewhat changed; the core/ tree has been - collapsed. - -(0.4.2) Changes since version 0.4.1 - - ++ New features: - - * Experimental ARP implementation added. - - * Skeleton Ethernet driver added. - - * Experimental BSD socket API library added. - - ++ Bugfixes: - - * In very intense situations, memory leakage could occur. This has - been fixed. - - ++ Other changes: - - * Variables named "data" and "code" have been renamed in order to - avoid name conflicts in certain compilers. - - * Variable++ have in appliciable cases been translated to ++variable - since some compilers generate better code in the latter case. - -(0.4.1) Changes since version 0.4 - - ++ New features: - - * TCP: Connection attempts time out earlier than data - transmissions. Nagle algorithm implemented. Push flag set on the - last segment in a burst. - - * UDP: experimental support for UDP-Lite extensions. - - ++ Bugfixes: - - * TCP: out of order segments were in some cases handled incorrectly, - and this has now been fixed. Delayed acknowledgements was broken - in 0.4, has now been fixed. Binding to an address that is in use - now results in an error. Reset connections sometimes hung an - application; this has been fixed. - - * Checksum calculation sometimes failed for chained pbufs with odd - lengths. This has been fixed. - - * API: a lot of bug fixes in the API. The UDP API has been improved - and tested. Error reporting and handling has been - improved. Logical flaws and race conditions for incoming TCP - connections has been found and removed. - - * Memory manager: alignment issues. Reallocating memory sometimes - failed, this has been fixed. - - * Generic library: bcopy was flawed and has been fixed. - - ++ Other changes: - - * API: all datatypes has been changed from generic ones such as - ints, to specified ones such as u16_t. Functions that return - errors now have the correct type (err_t). - - * General: A lot of code cleaned up and debugging code removed. Many - portability issues have been fixed. - - * The license was changed; the advertising clause was removed. - - * C64 port added. - - * Thanks: Huge thanks go to Dagan Galarneau, Horst Garnetzke, Petri - Kosunen, Mikael Caleres, and Frits Wilmink for reporting and - fixing bugs! - -(0.4) Changes since version 0.3.1 - - * Memory management has been radically changed; instead of - allocating memory from a shared heap, memory for objects that are - rapidly allocated and deallocated is now kept in pools. Allocation - and deallocation from those memory pools is very fast. The shared - heap is still present but is used less frequently. - - * The memory, memory pool, and packet buffer subsystems now support - 4-, 2-, or 1-byte alignment. - - * "Out of memory" situations are handled in a more robust way. - - * Stack usage has been reduced. - - * Easier configuration of lwIP parameters such as memory usage, - TTLs, statistics gathering, etc. All configuration parameters are - now kept in a single header file "lwipopts.h". - - * The directory structure has been changed slightly so that all - architecture specific files are kept under the src/arch - hierarchy. - - * Error propagation has been improved, both in the protocol modules - and in the API. - - * The code for the RTXC architecture has been implemented, tested - and put to use. - - * Bugs have been found and corrected in the TCP, UDP, IP, API, and - the Internet checksum modules. - - * Bugs related to porting between a 32-bit and a 16-bit architecture - have been found and corrected. - - * The license has been changed slightly to conform more with the - original BSD license, including the advertisement clause. - -(0.3.1) Changes since version 0.3 - - * Fix of a fatal bug in the buffer management. Pbufs with allocated - RAM never returned the RAM when the pbuf was deallocated. - - * TCP congestion control, window updates and retransmissions did not - work correctly. This has now been fixed. - - * Bugfixes in the API. - -(0.3) Changes since version 0.2 - - * New and improved directory structure. All include files are now - kept in a dedicated include/ directory. - - * The API now has proper error handling. A new function, - netconn_err(), now returns an error code for the connection in - case of errors. - - * Improvements in the memory management subsystem. The system now - keeps a pointer to the lowest free memory block. A new function, - mem_malloc2() tries to allocate memory once, and if it fails tries - to free some memory and retry the allocation. - - * Much testing has been done with limited memory - configurations. lwIP now does a better job when overloaded. - - * Some bugfixes and improvements to the buffer (pbuf) subsystem. - - * Many bugfixes in the TCP code: - - - Fixed a bug in tcp_close(). - - - The TCP receive window was incorrectly closed when out of - sequence segments was received. This has been fixed. - - - Connections are now timed-out of the FIN-WAIT-2 state. - - - The initial congestion window could in some cases be too - large. This has been fixed. - - - The retransmission queue could in some cases be screwed up. This - has been fixed. - - - TCP RST flag now handled correctly. - - - Out of sequence data was in some cases never delivered to the - application. This has been fixed. - - - Retransmitted segments now contain the correct acknowledgment - number and advertised window. - - - TCP retransmission timeout backoffs are not correctly computed - (ala BSD). After a number of retransmissions, TCP now gives up - the connection. - - * TCP connections now are kept on three lists, one for active - connections, one for listening connections, and one for - connections that are in TIME-WAIT. This greatly speeds up the fast - timeout processing for sending delayed ACKs. - - * TCP now provides proper feedback to the application when a - connection has been successfully set up. - - * More comments have been added to the code. The code has also been - somewhat cleaned up. - -(0.2) Initial public release. diff --git a/ext/lwip/FILES b/ext/lwip/FILES deleted file mode 100755 index e67e086..0000000 --- a/ext/lwip/FILES +++ /dev/null @@ -1,5 +0,0 @@ -src/ - The source code for the lwIP TCP/IP stack. -doc/ - The documentation for lwIP. -test/ - Some code to test whether the sources do what they should. - -See also the FILES file in each subdirectory. diff --git a/ext/lwip/README b/ext/lwip/README deleted file mode 100755 index dba5c47..0000000 --- a/ext/lwip/README +++ /dev/null @@ -1,100 +0,0 @@ -INTRODUCTION - -lwIP is a small independent implementation of the TCP/IP protocol -suite that has been developed by Adam Dunkels at the Computer and -Networks Architectures (CNA) lab at the Swedish Institute of Computer -Science (SICS). - -The focus of the lwIP TCP/IP implementation is to reduce the RAM usage -while still having a full scale TCP. This making lwIP suitable for use -in embedded systems with tens of kilobytes of free RAM and room for -around 40 kilobytes of code ROM. - - -FEATURES - - * IP (Internet Protocol, IPv4 and IPv6) including packet forwarding over - multiple network interfaces - * ICMP (Internet Control Message Protocol) for network maintenance and debugging - * IGMP (Internet Group Management Protocol) for multicast traffic management - * MLD (Multicast listener discovery for IPv6). Aims to be compliant with - RFC 2710. No support for MLDv2 - * ND (Neighbor discovery and stateless address autoconfiguration for IPv6). - Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 - (Address autoconfiguration) - * UDP (User Datagram Protocol) including experimental UDP-lite extensions - * TCP (Transmission Control Protocol) with congestion control, RTT estimation - and fast recovery/fast retransmit - * raw/native API for enhanced performance - * Optional Berkeley-like socket API - * DNS (Domain names resolver) - - -APPLICATIONS - - * HTTP server with SSI and CGI - * SNMPv2c agent with MIB compiler (Simple Network Management Protocol) - * SNTP (Simple network time protocol) - * NetBIOS name service responder - * MDNS (Multicast DNS) responder - * iPerf server implementation - - -LICENSE - -lwIP is freely available under a BSD license. - - -DEVELOPMENT - -lwIP has grown into an excellent TCP/IP stack for embedded devices, -and developers using the stack often submit bug fixes, improvements, -and additions to the stack to further increase its usefulness. - -Development of lwIP is hosted on Savannah, a central point for -software development, maintenance and distribution. Everyone can -help improve lwIP by use of Savannah's interface, Git and the -mailing list. A core team of developers will commit changes to the -Git source tree. - -The lwIP TCP/IP stack is maintained in the 'lwip' Git module and -contributions (such as platform ports) are in the 'contrib' Git module. - -See doc/savannah.txt for details on Git server access for users and -developers. - -The current Git trees are web-browsable: - http://git.savannah.gnu.org/cgit/lwip.git - http://git.savannah.gnu.org/cgit/lwip/lwip-contrib.git - -Submit patches and bugs via the lwIP project page: - http://savannah.nongnu.org/projects/lwip/ - -Continuous integration builds (GCC, clang): - https://travis-ci.org/yarrick/lwip-merged - - -DOCUMENTATION - -Self documentation of the source code is regularly extracted from the current -Git sources and is available from this web page: - http://www.nongnu.org/lwip/ - -There is now a constantly growing wiki about lwIP at - http://lwip.wikia.com/wiki/LwIP_Wiki - -Also, there are mailing lists you can subscribe at - http://savannah.nongnu.org/mail/?group=lwip -plus searchable archives: - http://lists.nongnu.org/archive/html/lwip-users/ - http://lists.nongnu.org/archive/html/lwip-devel/ - -lwIP was originally written by Adam Dunkels: - http://dunkels.com/adam/ - -Reading Adam's papers, the files in docs/, browsing the source code -documentation and browsing the mailing list archives is a good way to -become familiar with the design of lwIP. - -Adam Dunkels -Leon Woestenberg diff --git a/ext/lwip/UPGRADING b/ext/lwip/UPGRADING deleted file mode 100755 index 89267ae..0000000 --- a/ext/lwip/UPGRADING +++ /dev/null @@ -1,243 +0,0 @@ -This file lists major changes between release versions that require -ports or applications to be changed. Use it to update a port or an -application written for an older version of lwIP to correctly work -with newer versions. - - -(git master) - - * [Enter new changes just after this line - do not remove this line] - -(2.0.2) - - ++ Application changes: - - * slipif: The way to pass serial port number has changed. netif->num is not - supported any more, netif->state is interpreted as an u8_t port number now - (it's not a POINTER to an u8_t any more!) - -(2.0.1) - - ++ Application changes: - - * UDP does NOT receive multicast traffic from ALL netifs on an UDP PCB bound to a specific - netif any more. Users need to bind to IP_ADDR_ANY to receive multicast traffic and compare - ip_current_netif() to the desired netif for every packet. - See bug #49662 for an explanation. - -(2.0.0) - - ++ Application changes: - - * Changed netif "up" flag handling to be an administrative flag (as opposed to the previous meaning of - "ip4-address-valid", a netif will now not be used for transmission if not up) -> even a DHCP netif - has to be set "up" before starting the DHCP client - * Added IPv6 support (dual-stack or IPv4/IPv6 only) - * Changed ip_addr_t to be a union in dual-stack mode (use ip4_addr_t where referring to IPv4 only). - * Major rewrite of SNMP (added MIB parser that creates code stubs for custom MIBs); - supports SNMPv2c (experimental v3 support) - * Moved some core applications from contrib repository to src/apps (and include/lwip/apps) - - +++ Raw API: - * Changed TCP listen backlog: removed tcp_accepted(), added the function pair tcp_backlog_delayed()/ - tcp_backlog_accepted() to explicitly delay backlog handling on a connection pcb - - +++ Socket API: - * Added an implementation for posix sendmsg() - * Added LWIP_FIONREAD_LINUXMODE that makes ioctl/FIONREAD return the size of the next pending datagram - - ++ Port changes - - +++ new files: - * MANY new and moved files! - * Added src/Filelists.mk for use in Makefile projects - * Continued moving stack-internal parts from abc.h to abc_priv.h in sub-folder "priv" - to let abc.h only contain the actual application programmer's API - - +++ sys layer: - * Made LWIP_TCPIP_CORE_LOCKING==1 the default as it usually performs better than - the traditional message passing (although with LWIP_COMPAT_MUTEX you are still - open to priority inversion, so this is not recommended any more) - * Added LWIP_NETCONN_SEM_PER_THREAD to use one "op_completed" semaphore per thread - instead of using one per netconn (these semaphores are used even with core locking - enabled as some longer lasting functions like big writes still need to delay) - * Added generalized abstraction for itoa(), strnicmp(), stricmp() and strnstr() - in def.h (to be overridden in cc.h) instead of config - options for netbiosns, httpd, dns, etc. ... - * New abstraction for hton* and ntoh* functions in def.h. - To override them, use the following in cc.h: - #define lwip_htons(x) - #define lwip_htonl(x) - - +++ new options: - * TODO - - +++ new pools: - * Added LWIP_MEMPOOL_* (declare/init/alloc/free) to declare private memp pools - that share memp.c code but do not have to be made global via lwippools.h - * Added pools for IPv6, MPU_COMPATIBLE, dns-api, netif-api, etc. - * added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when a memp pool was empty and an item - is now available - - * Signature of LWIP_HOOK_VLAN_SET macro was changed - - * LWIP_DECLARE_MEMORY_ALIGNED() may be used to declare aligned memory buffers (mem/memp) - or to move buffers to dedicated memory using compiler attributes - - * Standard C headers are used to define sized types and printf formatters - (disable by setting LWIP_NO_STDINT_H=1 or LWIP_NO_INTTYPES_H=1 if your compiler - does not support these) - - - ++ Major bugfixes/improvements - - * Added IPv6 support (dual-stack or IPv4/IPv6 only) - * Major rewrite of PPP (incl. keep-up with apache pppd) - see doc/ppp.txt for an upgrading how-to - * Major rewrite of SNMP (incl. MIB parser) - * Fixed timing issues that might have lead to losing a DHCP lease - * Made rx processing path more robust against crafted errors - * TCP window scaling support - * modification of api modules to support FreeRTOS-MPU (don't pass stack-pointers to other threads) - * made DNS client more robust - * support PBUF_REF for RX packets - * LWIP_NETCONN_FULLDUPLEX allows netconn/sockets to be used for reading/writing from separate - threads each (needs LWIP_NETCONN_SEM_PER_THREAD) - * Moved and reordered stats (mainly memp/mib2) - -(1.4.0) - - ++ Application changes: - - * Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for - compatibility to old applications, but will be removed in the future). - - * Renamed mem_realloc() to mem_trim() to prevent confusion with realloc() - - +++ Raw API: - * Changed the semantics of tcp_close() (since it was rather a - shutdown before): Now the application does *NOT* get any calls to the recv - callback (aside from NULL/closed) after calling tcp_close() - - * When calling tcp_abort() from a raw API TCP callback function, - make sure you return ERR_ABRT to prevent accessing unallocated memory. - (ERR_ABRT now means the applicaiton has called tcp_abort!) - - +++ Netconn API: - * Changed netconn_receive() and netconn_accept() to return - err_t, not a pointer to new data/netconn. - - +++ Socket API: - * LWIP_SO_RCVTIMEO: when accept() or recv() time out, they - now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT. - - * Added a minimal version of posix fctl() to have a - standardised way to set O_NONBLOCK for nonblocking sockets. - - +++ all APIs: - * correctly implemented SO(F)_REUSEADDR - - ++ Port changes - - +++ new files: - - * Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h: - - * Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains - the actual application programmer's API - - * Separated timer implementation from sys.h/.c, moved to timers.h/.c; - Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you - still want to use your own timer implementation for NO_SYS==0 (as before). - - +++ sys layer: - - * Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/ - sys_sem_t; - - * Converted sys_mbox_new/sys_sem_new to take pointers and return err_t; - - * Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use - binary semaphores instead of mutexes - as before) - - +++ new options: - - * Don't waste memory when chaining segments, added option TCP_OVERSIZE to - prevent creating many small pbufs when calling tcp_write with many small - blocks of data. Instead, pbufs are allocated larger than needed and the - space is used for later calls to tcp_write. - - * Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs - in tcp_write/udp_send. - - * Added an additional option LWIP_ETHERNET to support ethernet without ARP - (necessary for pure PPPoE) - - * Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may - be used to place these pools into user-defined memory by using external - declaration. - - * Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT - - +++ new pools: - - * Netdb uses a memp pool for allocating memory when getaddrinfo() is called, - so MEMP_NUM_NETDB has to be set accordingly. - - * DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so - MEMP_NUM_LOCALHOSTLIST has to be set accordingly. - - * Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have - to be set accordingly. - - * PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES - has to be set accordingly - - * Integrated loopif into netif.c - loopif does not have to be created by the - port any more, just define LWIP_HAVE_LOOPIF to 1. - - * Added define LWIP_RAND() for lwip-wide randomization (needs to be defined - in cc.h, e.g. used by igmp) - - * Added printf-formatter X8_F to printf u8_t as hex - - * The heap now may be moved to user-defined memory by defining - LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address - - * added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work - with user-allocated structs instead of calling mem_malloc - - * Added const char* name to mem- and memp-stats for easier debugging. - - * Calculate the TCP/UDP checksum while copying to only fetch data once: - Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum - - * Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to - more than one pcb. - - * Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned - off any more, if this is set to 0, only one packet (the most recent one) is - queued (like demanded by RFC 1122). - - - ++ Major bugfixes/improvements - - * Implemented tcp_shutdown() to only shut down one end of a connection - * Implemented shutdown() at socket- and netconn-level - * Added errorset support to select() + improved select speed overhead - * Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x) - * Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1 - * Use macros defined in ip_addr.h to work with IP addresses - * Implemented many nonblocking socket/netconn functions - * Fixed ARP input processing: only add a new entry if a request was directed as us - * mem_realloc() to mem_trim() to prevent confusion with realloc() - * Some improvements for AutoIP (don't route/forward link-local addresses, don't break - existing connections when assigning a routable address) - * Correctly handle remote side overrunning our rcv_wnd in ooseq case - * Removed packing from ip_addr_t, the packed version is now only used in protocol headers - * Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0 - * Added support for static ARP table entries - -(STABLE-1.3.2) - - * initial version of this file diff --git a/ext/lwip/doc/FILES b/ext/lwip/doc/FILES deleted file mode 100755 index 5bbc29f..0000000 --- a/ext/lwip/doc/FILES +++ /dev/null @@ -1,9 +0,0 @@ -doxygen/ - Configuration files and scripts to create the lwIP doxygen source - documentation (found at http://www.nongnu.org/lwip/) - -savannah.txt - How to obtain the current development source code. -contrib.txt - How to contribute to lwIP as a developer. -rawapi.txt - The documentation for the core API of lwIP. - Also provides an overview about the other APIs and multithreading. -sys_arch.txt - The documentation for a system abstraction layer of lwIP. -ppp.txt - Documentation of the PPP interface for lwIP. diff --git a/ext/lwip/doc/NO_SYS_SampleCode.c b/ext/lwip/doc/NO_SYS_SampleCode.c deleted file mode 100755 index fcc22c5..0000000 --- a/ext/lwip/doc/NO_SYS_SampleCode.c +++ /dev/null @@ -1,122 +0,0 @@ -void -eth_mac_irq() -{ - /* Service MAC IRQ here */ - - /* Allocate pbuf from pool (avoid using heap in interrupts) */ - struct pbuf* p = pbuf_alloc(PBUF_RAW, eth_data_count, PBUF_POOL); - - if(p != NULL) { - /* Copy ethernet frame into pbuf */ - pbuf_take(p, eth_data, eth_data_count); - - /* Put in a queue which is processed in main loop */ - if(!queue_try_put(&queue, p)) { - /* queue is full -> packet loss */ - pbuf_free(p); - } - } -} - -static err_t -netif_output(struct netif *netif, struct pbuf *p) -{ - LINK_STATS_INC(link.xmit); - - /* Update SNMP stats (only if you use SNMP) */ - MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len); - int unicast = ((p->payload[0] & 0x01) == 0); - if (unicast) { - MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); - } else { - MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); - } - - lock_interrupts(); - pbuf_copy_partial(p, mac_send_buffer, p->tot_len, 0); - /* Start MAC transmit here */ - unlock_interrupts(); - - return ERR_OK; -} - -static void -netif_status_callback(struct netif *netif) -{ - printf("netif status changed %s\n", ip4addr_ntoa(netif_ip4_addr(netif))); -} - -static err_t -netif_init(struct netif *netif) -{ - netif->linkoutput = netif_output; - netif->output = etharp_output; - netif->output_ip6 = ethip6_output; - netif->mtu = ETHERNET_MTU; - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6; - MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, 100000000); - - SMEMCPY(netif->hwaddr, your_mac_address_goes_here, sizeof(netif->hwaddr)); - netif->hwaddr_len = sizeof(netif->hwaddr); - - return ERR_OK; -} - -void -main(void) -{ - struct netif netif; - - lwip_init(); - - netif_add(&netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY, NULL, netif_init, netif_input); - netif.name[0] = 'e'; - netif.name[1] = '0'; - netif_create_ip6_linklocal_address(&netif, 1); - netif.ip6_autoconfig_enabled = 1; - netif_set_status_callback(&netif, netif_status_callback); - netif_set_default(&netif); - netif_set_up(&netif); - - /* Start DHCP and HTTPD */ - dhcp_start(&netif ); - httpd_init(); - - while(1) { - /* Check link state, e.g. via MDIO communication with PHY */ - if(link_state_changed()) { - if(link_is_up()) { - netif_set_link_up(&netif); - } else { - netif_set_link_down(&netif); - } - } - - /* Check for received frames, feed them to lwIP */ - lock_interrupts(); - struct pbuf* p = queue_try_get(&queue); - unlock_interrupts(); - - if(p != NULL) { - LINK_STATS_INC(link.recv); - - /* Update SNMP stats (only if you use SNMP) */ - MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); - int unicast = ((p->payload[0] & 0x01) == 0); - if (unicast) { - MIB2_STATS_NETIF_INC(netif, ifinucastpkts); - } else { - MIB2_STATS_NETIF_INC(netif, ifinnucastpkts); - } - - if(netif.input(p, &netif) != ERR_OK) { - pbuf_free(p); - } - } - - /* Cyclic lwIP timers check */ - sys_check_timeouts(); - - /* your application goes here */ - } -} diff --git a/ext/lwip/doc/contrib.txt b/ext/lwip/doc/contrib.txt deleted file mode 100755 index a824fe3..0000000 --- a/ext/lwip/doc/contrib.txt +++ /dev/null @@ -1,58 +0,0 @@ -1 Introduction - -This document describes some guidelines for people participating -in lwIP development. - -2 How to contribute to lwIP - -Here is a short list of suggestions to anybody working with lwIP and -trying to contribute bug reports, fixes, enhancements, platform ports etc. -First of all as you may already know lwIP is a volunteer project so feedback -to fixes or questions might often come late. Hopefully the bug and patch tracking -features of Savannah help us not lose users' input. - -2.1 Source code style: - -1. do not use tabs. -2. indentation is two spaces per level (i.e. per tab). -3. end debug messages with a trailing newline (\n). -4. one space between keyword and opening bracket. -5. no space between function and opening bracket. -6. one space and no newline before opening curly braces of a block. -7. closing curly brace on a single line. -8. spaces surrounding assignment and comparisons. -9. don't initialize static and/or global variables to zero, the compiler takes care of that. -10. use current source code style as further reference. - -2.2 Source code documentation style: - -1. JavaDoc compliant and Doxygen compatible. -2. Function documentation above functions in .c files, not .h files. - (This forces you to synchronize documentation and implementation.) -3. Use current documentation style as further reference. - -2.3 Bug reports and patches: - -1. Make sure you are reporting bugs or send patches against the latest - sources. (From the latest release and/or the current Git sources.) -2. If you think you found a bug make sure it's not already filed in the - bugtracker at Savannah. -3. If you have a fix put the patch on Savannah. If it is a patch that affects - both core and arch specific stuff please separate them so that the core can - be applied separately while leaving the other patch 'open'. The preferred way - is to NOT touch archs you can't test and let maintainers take care of them. - This is a good way to see if they are used at all - the same goes for unix - netifs except tapif. -4. Do not file a bug and post a fix to it to the patch area. Either a bug report - or a patch will be enough. - If you correct an existing bug then attach the patch to the bug rather than creating a new entry in the patch area. -5. Patches should be specific to a single change or to related changes. Do not mix bugfixes with spelling and other - trivial fixes unless the bugfix is trivial too. Do not reorganize code and rename identifiers in the same patch you - change behaviour if not necessary. A patch is easier to read and understand if it's to the point and short than - if it's not to the point and long :) so the chances for it to be applied are greater. - -2.4 Platform porters: - -1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and - you think it could benefit others[1] you might want discuss this on the mailing list. You - can also ask for Git access to submit and maintain your port in the contrib Git module. diff --git a/ext/lwip/doc/doxygen/generate.bat b/ext/lwip/doc/doxygen/generate.bat deleted file mode 100755 index 4eab18c..0000000 --- a/ext/lwip/doc/doxygen/generate.bat +++ /dev/null @@ -1 +0,0 @@ -doxygen lwip.Doxyfile diff --git a/ext/lwip/doc/doxygen/generate.sh b/ext/lwip/doc/doxygen/generate.sh deleted file mode 100755 index c8fd619..0000000 --- a/ext/lwip/doc/doxygen/generate.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -doxygen lwip.Doxyfile diff --git a/ext/lwip/doc/doxygen/main_page.h b/ext/lwip/doc/doxygen/main_page.h deleted file mode 100755 index eb7183f..0000000 --- a/ext/lwip/doc/doxygen/main_page.h +++ /dev/null @@ -1,132 +0,0 @@ -/** - * @defgroup lwip lwIP - * - * @defgroup infrastructure Infrastructure - * - * @defgroup callbackstyle_api Callback-style APIs - * Non thread-safe APIs, callback style for maximum performance and minimum - * memory footprint. - * - * @defgroup sequential_api Sequential-style APIs - * Sequential-style APIs, blocking functions. More overhead, but can be called - * from any thread except TCPIP thread. - * - * @defgroup addons Addons - * - * @defgroup apps Applications - */ - -/** - * @mainpage Overview - * @verbinclude "README" - */ - -/** - * @page upgrading Upgrading - * @verbinclude "UPGRADING" - */ - -/** - * @page changelog Changelog - * @verbinclude "CHANGELOG" - */ - -/** - * @page contrib How to contribute to lwIP - * @verbinclude "contrib.txt" - */ - -/** - * @page pitfalls Common pitfalls - * - * Multiple Execution Contexts in lwIP code - * ======================================== - * - * The most common source of lwIP problems is to have multiple execution contexts - * inside the lwIP code. - * - * lwIP can be used in two basic modes: @ref lwip_nosys (no OS/RTOS - * running on target system) or @ref lwip_os (there is an OS running - * on the target system). - * - * Mainloop Mode - * ------------- - * In mainloop mode, only @ref callbackstyle_api can be used. - * The user has two possibilities to ensure there is only one - * exection context at a time in lwIP: - * - * 1) Deliver RX ethernet packets directly in interrupt context to lwIP - * by calling netif->input directly in interrupt. This implies all lwIP - * callback functions are called in IRQ context, which may cause further - * problems in application code: IRQ is blocked for a long time, multiple - * execution contexts in application code etc. When the application wants - * to call lwIP, it only needs to disable interrupts during the call. - * If timers are involved, even more locking code is needed to lock out - * timer IRQ and ethernet IRQ from each other, assuming these may be nested. - * - * 2) Run lwIP in a mainloop. There is example code here: @ref lwip_nosys. - * lwIP is _ONLY_ called from mainloop callstacks here. The ethernet IRQ - * has to put received telegrams into a queue which is polled in the - * mainloop. Ensure lwIP is _NEVER_ called from an interrupt, e.g. - * some SPI IRQ wants to forward data to udp_send() or tcp_write()! - * - * OS Mode - * ------- - * In OS mode, @ref callbackstyle_api AND @ref sequential_api can be used. - * @ref sequential_api are designed to be called from threads other than - * the TCPIP thread, so there is nothing to consider here. - * But @ref callbackstyle_api functions must _ONLY_ be called from - * TCPIP thread. It is a common error to call these from other threads - * or from IRQ contexts. ​Ethernet RX needs to deliver incoming packets - * in the correct way by sending a message to TCPIP thread, this is - * implemented in tcpip_input().​​ - * Again, ensure lwIP is _NEVER_ called from an interrupt, e.g. - * some SPI IRQ wants to forward data to udp_send() or tcp_write()! - * - * 1) tcpip_callback() can be used get called back from TCPIP thread, - * it is safe to call any @ref callbackstyle_api from there. - * - * 2) Use @ref LWIP_TCPIP_CORE_LOCKING. All @ref callbackstyle_api - * functions can be called when lwIP core lock is aquired, see - * @ref LOCK_TCPIP_CORE() and @ref UNLOCK_TCPIP_CORE(). - * These macros cannot be used in an interrupt context! - * Note the OS must correctly handle priority inversion for this. - */ - -/** - * @page bugs Reporting bugs - * Please report bugs in the lwIP bug tracker at savannah.\n - * BEFORE submitting, please check if the bug has already been reported!\n - * https://savannah.nongnu.org/bugs/?group=lwip - */ - -/** - * @defgroup lwip_nosys Mainloop mode ("NO_SYS") - * @ingroup lwip - * Use this mode if you do not run an OS on your system. \#define NO_SYS to 1. - * Feed incoming packets to netif->input(pbuf, netif) function from mainloop, - * *not* *from* *interrupt* *context*. You can allocate a @ref pbuf in interrupt - * context and put them into a queue which is processed from mainloop.\n - * Call sys_check_timeouts() periodically in the mainloop.\n - * Porting: implement all functions in @ref sys_time, @ref sys_prot and - * @ref compiler_abstraction.\n - * You can only use @ref callbackstyle_api in this mode.\n - * Sample code:\n - * @include NO_SYS_SampleCode.c - */ - -/** - * @defgroup lwip_os OS mode (TCPIP thread) - * @ingroup lwip - * Use this mode if you run an OS on your system. It is recommended to - * use an RTOS that correctly handles priority inversion and - * to use @ref LWIP_TCPIP_CORE_LOCKING.\n - * Porting: implement all functions in @ref sys_layer.\n - * You can use @ref callbackstyle_api together with @ref tcpip_callback, - * and all @ref sequential_api. - */ - -/** - * @page raw_api lwIP API - * @verbinclude "rawapi.txt" - */ diff --git a/ext/lwip/doc/doxygen/output/index.html b/ext/lwip/doc/doxygen/output/index.html deleted file mode 100755 index 7e4caee..0000000 --- a/ext/lwip/doc/doxygen/output/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - Redirection - - - - index.html - - diff --git a/ext/lwip/doc/mdns.txt b/ext/lwip/doc/mdns.txt deleted file mode 100755 index f208528..0000000 --- a/ext/lwip/doc/mdns.txt +++ /dev/null @@ -1,113 +0,0 @@ -Multicast DNS for lwIP - -Author: Erik Ekman - - -Note! The MDNS responder does not have all features required by the standards. -See notes in src/apps/mdns/mdns.c for what is left. It is however usable in normal -cases - but watch out if many devices on the same network try to use the same -host/service instance names. - - -How to enable: -============== - -MDNS support does not depend on DNS. -MDNS supports using IPv4 only, v6 only, or v4+v6. - -To enable MDNS responder, set - LWIP_MDNS_RESPONDER = 1 -in lwipopts.h and add src/apps/mdns/mdns.c to your list of files to build. - -The max number of services supported per netif is defined by MDNS_MAX_SERVICES, -default is 1. - -Increase MEMP_NUM_UDP_PCB by 1. MDNS needs one PCB. -Increase LWIP_NUM_NETIF_CLIENT_DATA by 1 (MDNS needs one entry on netif). - -MDNS with IPv4 requires LWIP_IGMP = 1, and preferably LWIP_AUTOIP = 1. -MDNS with IPv6 requires LWIP_IPV6_MLD = 1, and that a link-local address is -generated. - -The MDNS code puts its structs on the stack where suitable to reduce dynamic -memory allocation. It may use up to 1kB of stack. - -MDNS needs a strncasecmp() implementation. If you have one, define -LWIP_MDNS_STRNCASECMP to it. Otherwise the code will provide an implementation -for you. - - -How to use: -=========== - -Call mdns_resp_init() during system initialization. -This opens UDP sockets on port 5353 for IPv4 and IPv6. - - -To start responding on a netif, run - mdns_resp_add_netif(struct netif *netif, char *hostname, u32_t dns_ttl) - -The hostname will be copied. If this returns successfully, the netif will join -the multicast groups and any MDNS/legacy DNS requests sent unicast or multicast -to port 5353 will be handled: -- .local type A, AAAA or ANY returns relevant IP addresses -- Reverse lookups (PTR in-addr.arpa, ip6.arpa) of netif addresses - returns .local -Answers will use the supplied TTL (in seconds) -MDNS allows UTF-8 names, but it is recommended to stay within ASCII, -since the default case-insensitive comparison assumes this. - -It is recommended to call this function after an IPv4 address has been set, -since there is currently no check if the v4 address is valid. - -Call mdns_resp_netif_settings_changed() every time the IP address -on the netif has changed. - -To stop responding on a netif, run - mdns_resp_remove_netif(struct netif *netif) - - -Adding services: -================ - -The netif first needs to be registered. Then run - mdns_resp_add_service(struct netif *netif, char *name, char *service, - u16_t proto, u16_t port, u32_t dns_ttl, - service_get_txt_fn_t txt_fn, void *txt_userdata); - -The name and service pointers will be copied. Name refers to the name of the -service instance, and service is the type of service, like _http -proto can be DNSSD_PROTO_UDP or DNSSD_PROTO_TCP which represent _udp and _tcp. -If this call returns successfully, the following queries will be answered: -- _services._dns-sd._udp.local type PTR returns ..local -- ..local type PTR returns ...local -- ...local type SRV returns hostname and port of service -- ...local type TXT builds text strings by calling txt_fn - with the supplied userdata. The callback adds strings to the reply by calling - mdns_resp_add_service_txtitem(struct mdns_service *service, char *txt, - int txt_len). Example callback method: - - static void srv_txt(struct mdns_service *service, void *txt_userdata) - { - res = mdns_resp_add_service_txtitem(service, "path=/", 6); - LWIP_ERROR("mdns add service txt failed\n", (res == ERR_OK), return); - } - - Since a hostname struct is used for TXT storage each single item can be max - 63 bytes long, and the total max length (including length bytes for each - item) is 255 bytes. - -If your device runs a webserver on port 80, an example call might be: - - mdns_resp_add_service(netif, "myweb", "_http" - DNSSD_PROTO_TCP, 80, 3600, srv_txt, NULL); - -which will publish myweb._http._tcp.local for any hosts looking for web servers, -and point them to .local:80 - -Relevant information will be sent as additional records to reduce number of -requests required from a client. - -Removing services is currently not supported. Services are removed when the -netif is removed. - diff --git a/ext/lwip/doc/mqtt_client.txt b/ext/lwip/doc/mqtt_client.txt deleted file mode 100755 index a63dbd9..0000000 --- a/ext/lwip/doc/mqtt_client.txt +++ /dev/null @@ -1,162 +0,0 @@ -MQTT client for lwIP - -Author: Erik Andersson - -Details of the MQTT protocol can be found at: -http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html - ------------------------------------------------------------------ -1. Initial steps, reserve memory and make connection to server: - -1.1: Provide storage - -Static allocation: - mqtt_client_t static_client; - example_do_connect(&static_client); - -Dynamic allocation: - mqtt_client_t *client = mqtt_client_new(); - if(client != NULL) { - example_do_connect(&client); - } - -1.2: Establish Connection with server - -void example_do_connect(mqtt_client_t *client) -{ - struct mqtt_connect_client_info_t ci; - err_t err; - - /* Setup an empty client info structure */ - memset(&ci, 0, sizeof(ci)); - - /* Minimal amount of information required is client identifier, so set it here */ - ci.client_id = "lwip_test"; - - /* Initiate client and connect to server, if this fails immediately an error code is returned - otherwise mqtt_connection_cb will be called with connection result after attempting - to establish a connection with the server. - For now MQTT version 3.1.1 is always used */ - - err = mqtt_client_connect(client, ip_addr, MQTT_PORT, mqtt_connection_cb, 0, &ci); - - /* For now just print the result code if something goes wrong - if(err != ERR_OK) { - printf("mqtt_connect return %d\n", err); - } -} - -Connection to server can also be probed by calling mqtt_client_is_connected(client) - ------------------------------------------------------------------ -2. Implementing the connection status callback - - -static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status) -{ - err_t err; - if(status == MQTT_CONNECT_ACCEPTED) { - printf("mqtt_connection_cb: Successfully connected\n"); - - /* Setup callback for incoming publish requests */ - mqtt_set_inpub_callback(client, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, arg); - - /* Subscribe to a topic named "subtopic" with QoS level 1, call mqtt_sub_request_cb with result */ - err = mqtt_subscribe(client, "subtopic", 1, mqtt_sub_request_cb, arg); - - if(err != ERR_OK) { - printf("mqtt_subscribe return: %d\n", err); - } - } else { - printf("mqtt_connection_cb: Disconnected, reason: %d\n", status); - - /* Its more nice to be connected, so try to reconnect */ - example_do_connect(client); - } -} - -static void mqtt_sub_request_cb(void *arg, err_t result) -{ - /* Just print the result code here for simplicity, - normal behaviour would be to take some action if subscribe fails like - notifying user, retry subscribe or disconnect from server */ - printf("Subscribe result: %d\n", result); -} - ------------------------------------------------------------------ -3. Implementing callbacks for incoming publish and data - -/* The idea is to demultiplex topic and create some reference to be used in data callbacks - Example here uses a global variable, better would be to use a member in arg - If RAM and CPU budget allows it, the easiest implementation might be to just take a copy of - the topic string and use it in mqtt_incoming_data_cb -*/ -static int inpub_id; -static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len) -{ - printf("Incoming publish at topic %s with total length %u\n", topic, (unsigned int)tot_len); - - /* Decode topic string into a user defined reference */ - if(strcmp(topic, "print_payload") == 0) { - inpub_id = 0; - } else if(topic[0] == 'A') { - /* All topics starting with 'A' might be handled at the same way */ - inpub_id = 1; - } else { - /* For all other topics */ - inpub_id = 2; - } -} - -static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags) -{ - printf("Incoming publish payload with length %d, flags %u\n", len, (unsigned int)flags); - - if(flags & MQTT_DATA_FLAG_LAST) { - /* Last fragment of payload received (or whole part if payload fits receive buffer - See MQTT_VAR_HEADER_BUFFER_LEN) */ - - /* Call function or do action depending on reference, in this case inpub_id */ - if(inpub_id == 0) { - /* Don't trust the publisher, check zero termination */ - if(data[len-1] == 0) { - printf("mqtt_incoming_data_cb: %s\n", (const char *)data); - } - } else if(inpub_id == 1) { - /* Call an 'A' function... */ - } else { - printf("mqtt_incoming_data_cb: Ignoring payload...\n"); - } - } else { - /* Handle fragmented payload, store in buffer, write to file or whatever */ - } -} - ------------------------------------------------------------------ -4. Using outgoing publish - - -void example_publish(mqtt_client_t *client, void *arg) -{ - const char *pub_payload= "PubSubHubLubJub"; - err_t err; - u8_t qos = 2; /* 0 1 or 2, see MQTT specification */ - u8_t retain = 0; /* No don't retain such crappy payload... */ - err = mqtt_publish(client, "pub_topic", pub_payload, strlen(pub_payload), qos, retain, mqtt_pub_request_cb, arg); - if(err != ERR_OK) { - printf("Publish err: %d\n", err); - } -} - -/* Called when publish is complete either with sucess or failure */ -static void mqtt_pub_request_cb(void *arg, err_t result) -{ - if(result != ERR_OK) { - printf("Publish result: %d\n", result); - } -} - ------------------------------------------------------------------ -5. Disconnecting - -Simply call mqtt_disconnect(client) diff --git a/ext/lwip/doc/ppp.txt b/ext/lwip/doc/ppp.txt deleted file mode 100755 index 17048e0..0000000 --- a/ext/lwip/doc/ppp.txt +++ /dev/null @@ -1,529 +0,0 @@ -PPP interface for lwIP - -Author: Sylvain Rochet - -Table of Contents: - -1 - Supported PPP protocols and features -2 - Raw API PPP example for all protocols -3 - PPPoS input path (raw API, IRQ safe API, TCPIP API) -4 - Thread safe PPP API (PPPAPI) -5 - Notify phase callback (PPP_NOTIFY_PHASE) -6 - Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x - - - -1 Supported PPP protocols and features -====================================== - -Supported Low level protocols: -* PPP over serial using HDLC-like framing, such as wired dialup modems - or mobile telecommunications GPRS/EDGE/UMTS/HSPA+/LTE modems -* PPP over Ethernet, such as xDSL modems -* PPP over L2TP (Layer 2 Tunneling Protocol) LAC (L2TP Access Concentrator), - IP tunnel over UDP, such as VPN access - -Supported auth protocols: -* PAP, Password Authentication Protocol -* CHAP, Challenge-Handshake Authentication Protocol, also known as CHAP-MD5 -* MSCHAPv1, Microsoft version of CHAP, version 1 -* MSCHAPv2, Microsoft version of CHAP, version 2 -* EAP, Extensible Authentication Protocol - -Supported address protocols: -* IPCP, IP Control Protocol, IPv4 addresses negotiation -* IP6CP, IPv6 Control Protocol, IPv6 link-local addresses negotiation - -Supported encryption protocols: -* MPPE, Microsoft Point-to-Point Encryption - -Supported compression or miscellaneous protocols, for serial links only: -* PFC, Protocol Field Compression -* ACFC, Address-and-Control-Field-Compression -* ACCM, Asynchronous-Control-Character-Map -* VJ, Van Jacobson TCP/IP Header Compression - - - -2 Raw API PPP example for all protocols -======================================= - -As usual, raw API for lwIP means the lightweight API which *MUST* only be used -for NO_SYS=1 systems or called inside lwIP core thread for NO_SYS=0 systems. - -/* - * Globals - * ======= - */ - -/* The PPP control block */ -ppp_pcb *ppp; - -/* The PPP IP interface */ -struct netif ppp_netif; - - -/* - * PPP status callback - * =================== - * - * PPP status callback is called on PPP status change (up, down, …) from lwIP - * core thread - */ - -/* PPP status callback example */ -static void status_cb(ppp_pcb *pcb, int err_code, void *ctx) { - struct netif *pppif = ppp_netif(pcb); - LWIP_UNUSED_ARG(ctx); - - switch(err_code) { - case PPPERR_NONE: { -#if LWIP_DNS - const ip_addr_t *ns; -#endif /* LWIP_DNS */ - printf("status_cb: Connected\n"); -#if PPP_IPV4_SUPPORT - printf(" our_ipaddr = %s\n", ipaddr_ntoa(&pppif->ip_addr)); - printf(" his_ipaddr = %s\n", ipaddr_ntoa(&pppif->gw)); - printf(" netmask = %s\n", ipaddr_ntoa(&pppif->netmask)); -#if LWIP_DNS - ns = dns_getserver(0); - printf(" dns1 = %s\n", ipaddr_ntoa(ns)); - ns = dns_getserver(1); - printf(" dns2 = %s\n", ipaddr_ntoa(ns)); -#endif /* LWIP_DNS */ -#endif /* PPP_IPV4_SUPPORT */ -#if PPP_IPV6_SUPPORT - printf(" our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0))); -#endif /* PPP_IPV6_SUPPORT */ - break; - } - case PPPERR_PARAM: { - printf("status_cb: Invalid parameter\n"); - break; - } - case PPPERR_OPEN: { - printf("status_cb: Unable to open PPP session\n"); - break; - } - case PPPERR_DEVICE: { - printf("status_cb: Invalid I/O device for PPP\n"); - break; - } - case PPPERR_ALLOC: { - printf("status_cb: Unable to allocate resources\n"); - break; - } - case PPPERR_USER: { - printf("status_cb: User interrupt\n"); - break; - } - case PPPERR_CONNECT: { - printf("status_cb: Connection lost\n"); - break; - } - case PPPERR_AUTHFAIL: { - printf("status_cb: Failed authentication challenge\n"); - break; - } - case PPPERR_PROTOCOL: { - printf("status_cb: Failed to meet protocol\n"); - break; - } - case PPPERR_PEERDEAD: { - printf("status_cb: Connection timeout\n"); - break; - } - case PPPERR_IDLETIMEOUT: { - printf("status_cb: Idle Timeout\n"); - break; - } - case PPPERR_CONNECTTIME: { - printf("status_cb: Max connect time reached\n"); - break; - } - case PPPERR_LOOPBACK: { - printf("status_cb: Loopback detected\n"); - break; - } - default: { - printf("status_cb: Unknown error code %d\n", err_code); - break; - } - } - -/* - * This should be in the switch case, this is put outside of the switch - * case for example readability. - */ - - if (err_code == PPPERR_NONE) { - return; - } - - /* ppp_close() was previously called, don't reconnect */ - if (err_code == PPPERR_USER) { - /* ppp_free(); -- can be called here */ - return; - } - - /* - * Try to reconnect in 30 seconds, if you need a modem chatscript you have - * to do a much better signaling here ;-) - */ - ppp_connect(pcb, 30); - /* OR ppp_listen(pcb); */ -} - - -/* - * Creating a new PPPoS session - * ============================ - * - * In lwIP, PPPoS is not PPPoSONET, in lwIP PPPoS is PPPoSerial. - */ - -#include "netif/ppp/pppos.h" - -/* - * PPPoS serial output callback - * - * ppp_pcb, PPP control block - * data, buffer to write to serial port - * len, length of the data buffer - * ctx, optional user-provided callback context pointer - * - * Return value: len if write succeed - */ -static u32_t output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) { - return uart_write(UART, data, len); -} - -/* - * Create a new PPPoS interface - * - * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface - * output_cb, PPPoS serial output callback - * status_cb, PPP status callback, called on PPP status change (up, down, …) - * ctx_cb, optional user-provided callback context pointer - */ -ppp = pppos_create(&ppp_netif, - output_cb, status_cb, ctx_cb); - - -/* - * Creating a new PPPoE session - * ============================ - */ - -#include "netif/ppp/pppoe.h" - -/* - * Create a new PPPoE interface - * - * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface - * ethif, already existing and setup Ethernet interface to use - * service_name, PPPoE service name discriminator (not supported yet) - * concentrator_name, PPPoE concentrator name discriminator (not supported yet) - * status_cb, PPP status callback, called on PPP status change (up, down, …) - * ctx_cb, optional user-provided callback context pointer - */ -ppp = pppoe_create(&ppp_netif, - ðif, - service_name, concentrator_name, - status_cb, ctx_cb); - - -/* - * Creating a new PPPoL2TP session - * =============================== - */ - -#include "netif/ppp/pppol2tp.h" - -/* - * Create a new PPPoL2TP interface - * - * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface - * netif, optional already existing and setup output netif, necessary if you - * want to set this interface as default route to settle the chicken - * and egg problem with VPN links - * ipaddr, IP to connect to - * port, UDP port to connect to (usually 1701) - * secret, L2TP secret to use - * secret_len, size in bytes of the L2TP secret - * status_cb, PPP status callback, called on PPP status change (up, down, …) - * ctx_cb, optional user-provided callback context pointer - */ -ppp = pppol2tp_create(&ppp_netif, - struct netif *netif, ip_addr_t *ipaddr, u16_t port, - u8_t *secret, u8_t secret_len, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb); - - -/* - * Initiate PPP client connection - * ============================== - */ - -/* Set this interface as default route */ -ppp_set_default(ppp); - -/* - * Basic PPP client configuration. Can only be set if PPP session is in the - * dead state (i.e. disconnected). We don't need to provide thread-safe - * equivalents through PPPAPI because those helpers are only changing - * structure members while session is inactive for lwIP core. Configuration - * only need to be done once. - */ - -/* Ask the peer for up to 2 DNS server addresses. */ -ppp_set_usepeerdns(ppp, 1); - -/* Auth configuration, this is pretty self-explanatory */ -ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password"); - -/* - * Initiate PPP negotiation, without waiting (holdoff=0), can only be called - * if PPP session is in the dead state (i.e. disconnected). - */ -u16_t holdoff = 0; -ppp_connect(ppp, holdoff); - - -/* - * Initiate PPP server listener - * ============================ - */ - -/* - * Basic PPP server configuration. Can only be set if PPP session is in the - * dead state (i.e. disconnected). We don't need to provide thread-safe - * equivalents through PPPAPI because those helpers are only changing - * structure members while session is inactive for lwIP core. Configuration - * only need to be done once. - */ -ip4_addr_t addr; - -/* Set our address */ -IP4_ADDR(&addr, 192,168,0,1); -ppp_set_ipcp_ouraddr(ppp, &addr); - -/* Set peer(his) address */ -IP4_ADDR(&addr, 192,168,0,2); -ppp_set_ipcp_hisaddr(ppp, &addr); - -/* Set primary DNS server */ -IP4_ADDR(&addr, 192,168,10,20); -ppp_set_ipcp_dnsaddr(ppp, 0, &addr); - -/* Set secondary DNS server */ -IP4_ADDR(&addr, 192,168,10,21); -ppp_set_ipcp_dnsaddr(ppp, 1, &addr); - -/* Auth configuration, this is pretty self-explanatory */ -ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password"); - -/* Require peer to authenticate */ -ppp_set_auth_required(ppp, 1); - -/* - * Only for PPPoS, the PPP session should be up and waiting for input. - * - * Note: for PPPoS, ppp_connect() and ppp_listen() are actually the same thing. - * The listen call is meant for future support of PPPoE and PPPoL2TP server - * mode, where we will need to negotiate the incoming PPPoE session or L2TP - * session before initiating PPP itself. We need this call because there is - * two passive modes for PPPoS, ppp_set_passive and ppp_set_silent. - */ -ppp_set_silent(pppos, 1); - -/* - * Initiate PPP listener (i.e. wait for an incoming connection), can only - * be called if PPP session is in the dead state (i.e. disconnected). - */ -ppp_listen(ppp); - - -/* - * Closing PPP connection - * ====================== - */ - -/* - * Initiate the end of the PPP session, without carrier lost signal - * (nocarrier=0), meaning a clean shutdown of PPP protocols. - * You can call this function at anytime. - */ -u8_t nocarrier = 0; -ppp_close(ppp, nocarrier); -/* - * Then you must wait your status_cb() to be called, it may takes from a few - * seconds to several tens of seconds depending on the current PPP state. - */ - -/* - * Freeing a PPP connection - * ======================== - */ - -/* - * Free the PPP control block, can only be called if PPP session is in the - * dead state (i.e. disconnected). You need to call ppp_close() before. - */ -ppp_free(ppp); - - - -3 PPPoS input path (raw API, IRQ safe API, TCPIP API) -===================================================== - -Received data on serial port should be sent to lwIP using the pppos_input() -function or the pppos_input_tcpip() function. - -If NO_SYS is 1 and if PPP_INPROC_IRQ_SAFE is 0 (the default), pppos_input() -is not IRQ safe and then *MUST* only be called inside your main loop. - -Whatever the NO_SYS value, if PPP_INPROC_IRQ_SAFE is 1, pppos_input() is IRQ -safe and can be safely called from an interrupt context, using that is going -to reduce your need of buffer if pppos_input() is called byte after byte in -your rx serial interrupt. - -if NO_SYS is 0, the thread safe way outside an interrupt context is to use -the pppos_input_tcpip() function to pass input data to the lwIP core thread -using the TCPIP API. This is thread safe in all cases but you should avoid -passing data byte after byte because it uses heavy locking (mailbox) and it -allocates pbuf, better fill them ! - -if NO_SYS is 0 and if PPP_INPROC_IRQ_SAFE is 1, you may also use pppos_input() -from an RX thread, however pppos_input() is not thread safe by itself. You can -do that *BUT* you should NEVER call pppos_connect(), pppos_listen() and -ppp_free() if pppos_input() can still be running, doing this is NOT thread safe -at all. Using PPP_INPROC_IRQ_SAFE from an RX thread is discouraged unless you -really know what you are doing, your move ;-) - - -/* - * Fonction to call for received data - * - * ppp, PPP control block - * buffer, input buffer - * buffer_len, buffer length in bytes - */ -void pppos_input(ppp, buffer, buffer_len); - -or - -void pppos_input_tcpip(ppp, buffer, buffer_len); - - - -4 Thread safe PPP API (PPPAPI) -============================== - -There is a thread safe API for all corresponding ppp_* functions, you have to -enable LWIP_PPP_API in your lwipopts.h file, then see -include/netif/ppp/pppapi.h, this is actually pretty obvious. - - - -5 Notify phase callback (PPP_NOTIFY_PHASE) -========================================== - -Notify phase callback, enabled using the PPP_NOTIFY_PHASE config option, let -you configure a callback that is called on each PPP internal state change. -This is different from the status callback which only warns you about -up(running) and down(dead) events. - -Notify phase callback can be used, for example, to set a LED pattern depending -on the current phase of the PPP session. Here is a callback example which -tries to mimic what we usually see on xDSL modems while they are negotiating -the link, which should be self-explanatory: - -static void ppp_notify_phase_cb(ppp_pcb *pcb, u8_t phase, void *ctx) { - switch (phase) { - - /* Session is down (either permanently or briefly) */ - case PPP_PHASE_DEAD: - led_set(PPP_LED, LED_OFF); - break; - - /* We are between two sessions */ - case PPP_PHASE_HOLDOFF: - led_set(PPP_LED, LED_SLOW_BLINK); - break; - - /* Session just started */ - case PPP_PHASE_INITIALIZE: - led_set(PPP_LED, LED_FAST_BLINK); - break; - - /* Session is running */ - case PPP_PHASE_RUNNING: - led_set(PPP_LED, LED_ON); - break; - - default: - break; - } -} - - - -6 Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x -=============================================== - -PPP API was fully reworked between 1.4.x and 2.0.x releases. However porting -from previous lwIP version is pretty easy: - -* Previous PPP API used an integer to identify PPP sessions, we are now - using ppp_pcb* control block, therefore all functions changed from "int ppp" - to "ppp_pcb *ppp" - -* struct netif was moved outside the PPP structure, you have to provide a netif - for PPP interface in pppoX_create() functions - -* PPP session are not started automatically after you created them anymore, - you have to call ppp_connect(), this way you can configure the session before - starting it. - -* Previous PPP API used CamelCase, we are now using snake_case. - -* Previous PPP API mixed PPPoS and PPPoE calls, this isn't the case anymore, - PPPoS functions are now prefixed pppos_ and PPPoE functions are now prefixed - pppoe_, common functions are now prefixed ppp_. - -* New PPPERR_ error codes added, check you have all of them in your status - callback function - -* Only the following include files should now be used in user application: - #include "netif/ppp/pppapi.h" - #include "netif/ppp/pppos.h" - #include "netif/ppp/pppoe.h" - #include "netif/ppp/pppol2tp.h" - - Functions from ppp.h can be used, but you don't need to include this header - file as it is already included by above header files. - -* PPP_INPROC_OWNTHREAD was broken by design and was removed, you have to create - your own serial rx thread - -* PPP_INPROC_MULTITHREADED option was misnamed and confusing and was renamed - PPP_INPROC_IRQ_SAFE, please read the "PPPoS input path" documentation above - because you might have been fooled by that - -* If you used tcpip_callback_with_block() on ppp_ functions you may wish to use - the PPPAPI API instead. - -* ppp_sighup and ppp_close functions were merged using an optional argument - "nocarrier" on ppp_close. - -* DNS servers are now only remotely asked if LWIP_DNS is set and if - ppp_set_usepeerdns() is set to true, they are now automatically registered - using the dns_setserver() function so you don't need to do that in the PPP - callback anymore. - -* PPPoS does not use the SIO API anymore, as such it now requires a serial - output callback in place of sio_write - -* PPP_MAXIDLEFLAG is now in ms instead of jiffies diff --git a/ext/lwip/doc/rawapi.txt b/ext/lwip/doc/rawapi.txt deleted file mode 100755 index c3f8878..0000000 --- a/ext/lwip/doc/rawapi.txt +++ /dev/null @@ -1,499 +0,0 @@ -Raw TCP/IP interface for lwIP - -Authors: Adam Dunkels, Leon Woestenberg, Christiaan Simons - -lwIP provides three Application Program's Interfaces (APIs) for programs -to use for communication with the TCP/IP code: -* low-level "core" / "callback" or "raw" API. -* higher-level "sequential" API. -* BSD-style socket API. - -The raw API (sometimes called native API) is an event-driven API designed -to be used without an operating system that implements zero-copy send and -receive. This API is also used by the core stack for interaction between -the various protocols. It is the only API available when running lwIP -without an operating system. - -The sequential API provides a way for ordinary, sequential, programs -to use the lwIP stack. It is quite similar to the BSD socket API. The -model of execution is based on the blocking open-read-write-close -paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP -code and the application program must reside in different execution -contexts (threads). - -The socket API is a compatibility API for existing applications, -currently it is built on top of the sequential API. It is meant to -provide all functions needed to run socket API applications running -on other platforms (e.g. unix / windows etc.). However, due to limitations -in the specification of this API, there might be incompatibilities -that require small modifications of existing programs. - -** Multithreading - -lwIP started targeting single-threaded environments. When adding multi- -threading support, instead of making the core thread-safe, another -approach was chosen: there is one main thread running the lwIP core -(also known as the "tcpip_thread"). When running in a multithreaded -environment, raw API functions MUST only be called from the core thread -since raw API functions are not protected from concurrent access (aside -from pbuf- and memory management functions). Application threads using -the sequential- or socket API communicate with this main thread through -message passing. - - As such, the list of functions that may be called from - other threads or an ISR is very limited! Only functions - from these API header files are thread-safe: - - api.h - - netbuf.h - - netdb.h - - netifapi.h - - pppapi.h - - sockets.h - - sys.h - - Additionaly, memory (de-)allocation functions may be - called from multiple threads (not ISR!) with NO_SYS=0 - since they are protected by SYS_LIGHTWEIGHT_PROT and/or - semaphores. - - Netconn or Socket API functions are thread safe against the - core thread but they are not reentrant at the control block - granularity level. That is, a UDP or TCP control block must - not be shared among multiple threads without proper locking. - - If SYS_LIGHTWEIGHT_PROT is set to 1 and - LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1, - pbuf_free() may also be called from another thread or - an ISR (since only then, mem_free - for PBUF_RAM - may - be called from an ISR: otherwise, the HEAP is only - protected by semaphores). - - -** The remainder of this document discusses the "raw" API. ** - -The raw TCP/IP interface allows the application program to integrate -better with the TCP/IP code. Program execution is event based by -having callback functions being called from within the TCP/IP -code. The TCP/IP code and the application program both run in the same -thread. The sequential API has a much higher overhead and is not very -well suited for small systems since it forces a multithreaded paradigm -on the application. - -The raw TCP/IP interface is not only faster in terms of code execution -time but is also less memory intensive. The drawback is that program -development is somewhat harder and application programs written for -the raw TCP/IP interface are more difficult to understand. Still, this -is the preferred way of writing applications that should be small in -code size and memory usage. - -All APIs can be used simultaneously by different application -programs. In fact, the sequential API is implemented as an application -program using the raw TCP/IP interface. - -Do not confuse the lwIP raw API with raw Ethernet or IP sockets. -The former is a way of interfacing the lwIP network stack (including -TCP and UDP), the later refers to processing raw Ethernet or IP data -instead of TCP connections or UDP packets. - -Raw API applications may never block since all packet processing -(input and output) as well as timer processing (TCP mainly) is done -in a single execution context. - ---- Callbacks - -Program execution is driven by callbacks functions, which are then -invoked by the lwIP core when activity related to that application -occurs. A particular application may register to be notified via a -callback function for events such as incoming data available, outgoing -data sent, error notifications, poll timer expiration, connection -closed, etc. An application can provide a callback function to perform -processing for any or all of these events. Each callback is an ordinary -C function that is called from within the TCP/IP code. Every callback -function is passed the current TCP or UDP connection state as an -argument. Also, in order to be able to keep program specific state, -the callback functions are called with a program specified argument -that is independent of the TCP/IP state. - -The function for setting the application connection state is: - -- void tcp_arg(struct tcp_pcb *pcb, void *arg) - - Specifies the program specific state that should be passed to all - other callback functions. The "pcb" argument is the current TCP - connection control block, and the "arg" argument is the argument - that will be passed to the callbacks. - - ---- TCP connection setup - -The functions used for setting up connections is similar to that of -the sequential API and of the BSD socket API. A new TCP connection -identifier (i.e., a protocol control block - PCB) is created with the -tcp_new() function. This PCB can then be either set to listen for new -incoming connections or be explicitly connected to another host. - -- struct tcp_pcb *tcp_new(void) - - Creates a new connection identifier (PCB). If memory is not - available for creating the new pcb, NULL is returned. - -- err_t tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, - u16_t port) - - Binds the pcb to a local IP address and port number. The IP address - can be specified as IP_ADDR_ANY in order to bind the connection to - all local IP addresses. - - If another connection is bound to the same port, the function will - return ERR_USE, otherwise ERR_OK is returned. - -- struct tcp_pcb *tcp_listen(struct tcp_pcb *pcb) - - Commands a pcb to start listening for incoming connections. When an - incoming connection is accepted, the function specified with the - tcp_accept() function will be called. The pcb will have to be bound - to a local port with the tcp_bind() function. - - The tcp_listen() function returns a new connection identifier, and - the one passed as an argument to the function will be - deallocated. The reason for this behavior is that less memory is - needed for a connection that is listening, so tcp_listen() will - reclaim the memory needed for the original connection and allocate a - new smaller memory block for the listening connection. - - tcp_listen() may return NULL if no memory was available for the - listening connection. If so, the memory associated with the pcb - passed as an argument to tcp_listen() will not be deallocated. - -- struct tcp_pcb *tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) - - Same as tcp_listen, but limits the number of outstanding connections - in the listen queue to the value specified by the backlog argument. - To use it, your need to set TCP_LISTEN_BACKLOG=1 in your lwipopts.h. - -- void tcp_accept(struct tcp_pcb *pcb, - err_t (* accept)(void *arg, struct tcp_pcb *newpcb, - err_t err)) - - Specified the callback function that should be called when a new - connection arrives on a listening connection. - -- err_t tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, - u16_t port, err_t (* connected)(void *arg, - struct tcp_pcb *tpcb, - err_t err)); - - Sets up the pcb to connect to the remote host and sends the - initial SYN segment which opens the connection. - - The tcp_connect() function returns immediately; it does not wait for - the connection to be properly setup. Instead, it will call the - function specified as the fourth argument (the "connected" argument) - when the connection is established. If the connection could not be - properly established, either because the other host refused the - connection or because the other host didn't answer, the "err" - callback function of this pcb (registered with tcp_err, see below) - will be called. - - The tcp_connect() function can return ERR_MEM if no memory is - available for enqueueing the SYN segment. If the SYN indeed was - enqueued successfully, the tcp_connect() function returns ERR_OK. - - ---- Sending TCP data - -TCP data is sent by enqueueing the data with a call to -tcp_write(). When the data is successfully transmitted to the remote -host, the application will be notified with a call to a specified -callback function. - -- err_t tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len, - u8_t apiflags) - - Enqueues the data pointed to by the argument dataptr. The length of - the data is passed as the len parameter. The apiflags can be one or more of: - - TCP_WRITE_FLAG_COPY: indicates whether the new memory should be allocated - for the data to be copied into. If this flag is not given, no new memory - should be allocated and the data should only be referenced by pointer. This - also means that the memory behind dataptr must not change until the data is - ACKed by the remote host - - TCP_WRITE_FLAG_MORE: indicates that more data follows. If this is omitted, - the PSH flag is set in the last segment created by this call to tcp_write. - If this flag is given, the PSH flag is not set. - - The tcp_write() function will fail and return ERR_MEM if the length - of the data exceeds the current send buffer size or if the length of - the queue of outgoing segment is larger than the upper limit defined - in lwipopts.h. The number of bytes available in the output queue can - be retrieved with the tcp_sndbuf() function. - - The proper way to use this function is to call the function with at - most tcp_sndbuf() bytes of data. If the function returns ERR_MEM, - the application should wait until some of the currently enqueued - data has been successfully received by the other host and try again. - -- void tcp_sent(struct tcp_pcb *pcb, - err_t (* sent)(void *arg, struct tcp_pcb *tpcb, - u16_t len)) - - Specifies the callback function that should be called when data has - successfully been received (i.e., acknowledged) by the remote - host. The len argument passed to the callback function gives the - amount bytes that was acknowledged by the last acknowledgment. - - ---- Receiving TCP data - -TCP data reception is callback based - an application specified -callback function is called when new data arrives. When the -application has taken the data, it has to call the tcp_recved() -function to indicate that TCP can advertise increase the receive -window. - -- void tcp_recv(struct tcp_pcb *pcb, - err_t (* recv)(void *arg, struct tcp_pcb *tpcb, - struct pbuf *p, err_t err)) - - Sets the callback function that will be called when new data - arrives. The callback function will be passed a NULL pbuf to - indicate that the remote host has closed the connection. If - there are no errors and the callback function is to return - ERR_OK, then it must free the pbuf. Otherwise, it must not - free the pbuf so that lwIP core code can store it. - -- void tcp_recved(struct tcp_pcb *pcb, u16_t len) - - Must be called when the application has received the data. The len - argument indicates the length of the received data. - - ---- Application polling - -When a connection is idle (i.e., no data is either transmitted or -received), lwIP will repeatedly poll the application by calling a -specified callback function. This can be used either as a watchdog -timer for killing connections that have stayed idle for too long, or -as a method of waiting for memory to become available. For instance, -if a call to tcp_write() has failed because memory wasn't available, -the application may use the polling functionality to call tcp_write() -again when the connection has been idle for a while. - -- void tcp_poll(struct tcp_pcb *pcb, - err_t (* poll)(void *arg, struct tcp_pcb *tpcb), - u8_t interval) - - Specifies the polling interval and the callback function that should - be called to poll the application. The interval is specified in - number of TCP coarse grained timer shots, which typically occurs - twice a second. An interval of 10 means that the application would - be polled every 5 seconds. - - ---- Closing and aborting connections - -- err_t tcp_close(struct tcp_pcb *pcb) - - Closes the connection. The function may return ERR_MEM if no memory - was available for closing the connection. If so, the application - should wait and try again either by using the acknowledgment - callback or the polling functionality. If the close succeeds, the - function returns ERR_OK. - - The pcb is deallocated by the TCP code after a call to tcp_close(). - -- void tcp_abort(struct tcp_pcb *pcb) - - Aborts the connection by sending a RST (reset) segment to the remote - host. The pcb is deallocated. This function never fails. - - ATTENTION: When calling this from one of the TCP callbacks, make - sure you always return ERR_ABRT (and never return ERR_ABRT otherwise - or you will risk accessing deallocated memory or memory leaks! - - -If a connection is aborted because of an error, the application is -alerted of this event by the err callback. Errors that might abort a -connection are when there is a shortage of memory. The callback -function to be called is set using the tcp_err() function. - -- void tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg, - err_t err)) - - The error callback function does not get the pcb passed to it as a - parameter since the pcb may already have been deallocated. - - ---- UDP interface - -The UDP interface is similar to that of TCP, but due to the lower -level of complexity of UDP, the interface is significantly simpler. - -- struct udp_pcb *udp_new(void) - - Creates a new UDP pcb which can be used for UDP communication. The - pcb is not active until it has either been bound to a local address - or connected to a remote address. - -- void udp_remove(struct udp_pcb *pcb) - - Removes and deallocates the pcb. - -- err_t udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, - u16_t port) - - Binds the pcb to a local address. The IP-address argument "ipaddr" - can be IP_ADDR_ANY to indicate that it should listen to any local IP - address. The function currently always return ERR_OK. - -- err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, - u16_t port) - - Sets the remote end of the pcb. This function does not generate any - network traffic, but only set the remote address of the pcb. - -- err_t udp_disconnect(struct udp_pcb *pcb) - - Remove the remote end of the pcb. This function does not generate - any network traffic, but only removes the remote address of the pcb. - -- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p) - - Sends the pbuf p. The pbuf is not deallocated. - -- void udp_recv(struct udp_pcb *pcb, - void (* recv)(void *arg, struct udp_pcb *upcb, - struct pbuf *p, - ip_addr_t *addr, - u16_t port), - void *recv_arg) - - Specifies a callback function that should be called when a UDP - datagram is received. - - ---- System initalization - -A truly complete and generic sequence for initializing the lwIP stack -cannot be given because it depends on additional initializations for -your runtime environment (e.g. timers). - -We can give you some idea on how to proceed when using the raw API. -We assume a configuration using a single Ethernet netif and the -UDP and TCP transport layers, IPv4 and the DHCP client. - -Call these functions in the order of appearance: - -- lwip_init() - - Initialize the lwIP stack and all of its subsystems. - -- netif_add(struct netif *netif, const ip4_addr_t *ipaddr, - const ip4_addr_t *netmask, const ip4_addr_t *gw, - void *state, netif_init_fn init, netif_input_fn input) - - Adds your network interface to the netif_list. Allocate a struct - netif and pass a pointer to this structure as the first argument. - Give pointers to cleared ip_addr structures when using DHCP, - or fill them with sane numbers otherwise. The state pointer may be NULL. - - The init function pointer must point to a initialization function for - your Ethernet netif interface. The following code illustrates its use. - - err_t netif_if_init(struct netif *netif) - { - u8_t i; - - for (i = 0; i < ETHARP_HWADDR_LEN; i++) { - netif->hwaddr[i] = some_eth_addr[i]; - } - init_my_eth_device(); - return ERR_OK; - } - - For Ethernet drivers, the input function pointer must point to the lwIP - function ethernet_input() declared in "netif/etharp.h". Other drivers - must use ip_input() declared in "lwip/ip.h". - -- netif_set_default(struct netif *netif) - - Registers the default network interface. - -- netif_set_link_up(struct netif *netif) - - This is the hardware link state; e.g. whether cable is plugged for wired - Ethernet interface. This function must be called even if you don't know - the current state. Having link up and link down events is optional but - DHCP and IPv6 discover benefit well from those events. - -- netif_set_up(struct netif *netif) - - This is the administrative (= software) state of the netif, when the - netif is fully configured this function must be called. - -- dhcp_start(struct netif *netif) - - Creates a new DHCP client for this interface on the first call. - - You can peek in the netif->dhcp struct for the actual DHCP status. - -- sys_check_timeouts() - - When the system is running, you have to periodically call - sys_check_timeouts() which will handle all timers for all protocols in - the stack; add this to your main loop or equivalent. - - ---- Optimalization hints - -The first thing you want to optimize is the lwip_standard_checksum() -routine from src/core/inet.c. You can override this standard -function with the #define LWIP_CHKSUM . - -There are C examples given in inet.c or you might want to -craft an assembly function for this. RFC1071 is a good -introduction to this subject. - -Other significant improvements can be made by supplying -assembly or inline replacements for htons() and htonl() -if you're using a little-endian architecture. -#define lwip_htons(x) -#define lwip_htonl(x) -If you #define them to htons() and htonl(), you should -#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from -defining hton*/ntoh* compatibility macros. - -Check your network interface driver if it reads at -a higher speed than the maximum wire-speed. If the -hardware isn't serviced frequently and fast enough -buffer overflows are likely to occur. - -E.g. when using the cs8900 driver, call cs8900if_service(ethif) -as frequently as possible. When using an RTOS let the cs8900 interrupt -wake a high priority task that services your driver using a binary -semaphore or event flag. Some drivers might allow additional tuning -to match your application and network. - -For a production release it is recommended to set LWIP_STATS to 0. -Note that speed performance isn't influenced much by simply setting -high values to the memory options. - -For more optimization hints take a look at the lwIP wiki. - ---- Zero-copy MACs - -To achieve zero-copy on transmit, the data passed to the raw API must -remain unchanged until sent. Because the send- (or write-)functions return -when the packets have been enqueued for sending, data must be kept stable -after that, too. - -This implies that PBUF_RAM/PBUF_POOL pbufs passed to raw-API send functions -must *not* be reused by the application unless their ref-count is 1. - -For no-copy pbufs (PBUF_ROM/PBUF_REF), data must be kept unchanged, too, -but the stack/driver will/must copy PBUF_REF'ed data when enqueueing, while -PBUF_ROM-pbufs are just enqueued (as ROM-data is expected to never change). - -Also, data passed to tcp_write without the copy-flag must not be changed! - -Therefore, be careful which type of PBUF you use and if you copy TCP data -or not! diff --git a/ext/lwip/doc/savannah.txt b/ext/lwip/doc/savannah.txt deleted file mode 100755 index ba16511..0000000 --- a/ext/lwip/doc/savannah.txt +++ /dev/null @@ -1,120 +0,0 @@ -Daily Use Guide for using Savannah for lwIP - -Table of Contents: - -1 - Obtaining lwIP from the Git repository -2 - Committers/developers Git access using SSH -3 - Merging a development branch to master branch -4 - How to release lwIP - - - -1 Obtaining lwIP from the Git repository ----------------------------------------- - -To perform an anonymous Git clone of the master branch (this is where -bug fixes and incremental enhancements occur), do this: - git clone git://git.savannah.nongnu.org/lwip.git - -Or, obtain a stable branch (updated with bug fixes only) as follows: - git clone --branch DEVEL-1_4_1 git://git.savannah.nongnu.org/lwip.git - -Or, obtain a specific (fixed) release as follows: - git clone --branch STABLE-1_4_1 git://git.savannah.nongnu.org/lwip.git - - -2 Committers/developers Git access using SSH --------------------------------------------- - -The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption. -As such, Git commits to the server occur through a SSH tunnel for project members. -To create a SSH2 key pair in UNIX-like environments, do this: - ssh-keygen -t dsa - -Under Windows, a recommended SSH client is "PuTTY", freely available with good -documentation and a graphic user interface. Use its key generator. - -Now paste the id_dsa.pub contents into your Savannah account public key list. Wait -a while so that Savannah can update its configuration (This can take minutes). - -Try to login using SSH: - ssh -v your_login@git.sv.gnu.org - -If it tells you: - Linux vcs.savannah.gnu.org 2.6.32-5-xen-686 #1 SMP Wed Jun 17 17:10:03 UTC 2015 i686 - - Interactive shell login is not possible for security reasons. - VCS commands are allowed. - Last login: Tue May 15 23:10:12 2012 from 82.245.102.129 - You tried to execute: - Sorry, you are not allowed to execute that command. - Shared connection to git.sv.gnu.org closed. - -then you could login; Savannah refuses to give you a shell - which is OK, as we -are allowed to use SSH for Git only. Now, you should be able to do this: - git clone your_login@git.sv.gnu.org:/srv/git/lwip.git - -After which you can edit your local files with bug fixes or new features and -commit them. Make sure you know what you are doing when using Git to make -changes on the repository. If in doubt, ask on the lwip-members mailing list. - -(If SSH asks about authenticity of the host, you can check the key -fingerprint against https://savannah.nongnu.org/git/?group=lwip - - -3 - Merging a development branch to master branch -------------------------------------------------- - -Merging is a straightforward process in Git. How to merge all changes in a -development branch since our last merge from main: - -Checkout the master branch: - git checkout master - -Merge the development branch to master: - git merge your-development-branch - -Resolve any conflict. - -Commit the merge result. - git commit -a - -Push your commits: - git push - - -4 How to release lwIP ---------------------- - -First, tag the release using Git: (I use release number 1.4.1 throughout -this example). - git tag -a STABLE-1_4_1 - -Share the tag reference by pushing it to remote: - git push origin STABLE-1_4_1 - -Prepare the release: - cp -r lwip lwip-1.4.1 - rm -rf lwip-1.4.1/.git lwip-1.4.1/.gitattributes - -Archive the current directory using tar, gzip'd, bzip2'd and zip'd. - tar czvf lwip-1.4.1.tar.gz lwip-1.4.1 - tar cjvf lwip-1.4.1.tar.bz2 lwip-1.4.1 - zip -r lwip-1.4.1.zip lwip-1.4.1 - -Now, sign the archives with a detached GPG binary signature as follows: - gpg -b lwip-1.4.1.tar.gz - gpg -b lwip-1.4.1.tar.bz2 - gpg -b lwip-1.4.1.zip - -Upload these files using anonymous FTP: - ncftp ftp://savannah.gnu.org/incoming/savannah/lwip - ncftp> mput *1.4.1.* - -Additionally, you may post a news item on Savannah, like this: - -A new 1.4.1 release is now available here: -http://savannah.nongnu.org/files/?group=lwip&highlight=1.4.1 - -You will have to submit this via the user News interface, then approve -this via the Administrator News interface. diff --git a/ext/lwip/doc/sys_arch.txt b/ext/lwip/doc/sys_arch.txt deleted file mode 100755 index 727604c..0000000 --- a/ext/lwip/doc/sys_arch.txt +++ /dev/null @@ -1,303 +0,0 @@ -sys_arch interface for lwIP - -Author: Adam Dunkels - Simon Goldschmidt - -The operating system emulation layer provides a common interface -between the lwIP code and the underlying operating system kernel. The -general idea is that porting lwIP to new architectures requires only -small changes to a few header files and a new sys_arch -implementation. It is also possible to do a sys_arch implementation -that does not rely on any underlying operating system. - -The sys_arch provides semaphores, mailboxes and mutexes to lwIP. For the full -lwIP functionality, multiple threads support can be implemented in the -sys_arch, but this is not required for the basic lwIP -functionality. Timer scheduling is implemented in lwIP, but can be implemented -by the sys_arch port (LWIP_TIMERS_CUSTOM==1). - -In addition to the source file providing the functionality of sys_arch, -the OS emulation layer must provide several header files defining -macros used throughout lwip. The files required and the macros they -must define are listed below the sys_arch description. - -Semaphores can be either counting or binary - lwIP works with both -kinds. Mailboxes should be implemented as a queue which allows multiple messages -to be posted (implementing as a rendez-vous point where only one message can be -posted at a time can have a highly negative impact on performance). A message -in a mailbox is just a pointer, nothing more. - -Semaphores are represented by the type "sys_sem_t" which is typedef'd -in the sys_arch.h file. Mailboxes are equivalently represented by the -type "sys_mbox_t". Mutexes are represented by the type "sys_mutex_t". -lwIP does not place any restrictions on how these types are represented -internally. - -Since lwIP 1.4.0, semaphore, mutexes and mailbox functions are prototyped in a way that -allows both using pointers or actual OS structures to be used. This way, memory -required for such types can be either allocated in place (globally or on the -stack) or on the heap (allocated internally in the "*_new()" functions). - -The following functions must be implemented by the sys_arch: - -- void sys_init(void) - - Is called to initialize the sys_arch layer. - -- err_t sys_sem_new(sys_sem_t *sem, u8_t count) - - Creates a new semaphore. The semaphore is allocated to the memory that 'sem' - points to (which can be both a pointer or the actual OS structure). - The "count" argument specifies the initial state of the semaphore (which is - either 0 or 1). - If the semaphore has been created, ERR_OK should be returned. Returning any - other error will provide a hint what went wrong, but except for assertions, - no real error handling is implemented. - -- void sys_sem_free(sys_sem_t *sem) - - Deallocates a semaphore. - -- void sys_sem_signal(sys_sem_t *sem) - - Signals a semaphore. - -- u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) - - Blocks the thread while waiting for the semaphore to be - signaled. If the "timeout" argument is non-zero, the thread should - only be blocked for the specified time (measured in - milliseconds). If the "timeout" argument is zero, the thread should be - blocked until the semaphore is signalled. - - If the timeout argument is non-zero, the return value is the number of - milliseconds spent waiting for the semaphore to be signaled. If the - semaphore wasn't signaled within the specified time, the return value is - SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore - (i.e., it was already signaled), the function may return zero. - - Notice that lwIP implements a function with a similar name, - sys_sem_wait(), that uses the sys_arch_sem_wait() function. - -- int sys_sem_valid(sys_sem_t *sem) - - Returns 1 if the semaphore is valid, 0 if it is not valid. - When using pointers, a simple way is to check the pointer for != NULL. - When directly using OS structures, implementing this may be more complex. - This may also be a define, in which case the function is not prototyped. - -- void sys_sem_set_invalid(sys_sem_t *sem) - - Invalidate a semaphore so that sys_sem_valid() returns 0. - ATTENTION: This does NOT mean that the semaphore shall be deallocated: - sys_sem_free() is always called before calling this function! - This may also be a define, in which case the function is not prototyped. - -- void sys_mutex_new(sys_mutex_t *mutex) - - Creates a new mutex. The mutex is allocated to the memory that 'mutex' - points to (which can be both a pointer or the actual OS structure). - If the mutex has been created, ERR_OK should be returned. Returning any - other error will provide a hint what went wrong, but except for assertions, - no real error handling is implemented. - -- void sys_mutex_free(sys_mutex_t *mutex) - - Deallocates a mutex. - -- void sys_mutex_lock(sys_mutex_t *mutex) - - Blocks the thread until the mutex can be grabbed. - -- void sys_mutex_unlock(sys_mutex_t *mutex) - - Releases the mutex previously locked through 'sys_mutex_lock()'. - -- void sys_mutex_valid(sys_mutex_t *mutex) - - Returns 1 if the mutes is valid, 0 if it is not valid. - When using pointers, a simple way is to check the pointer for != NULL. - When directly using OS structures, implementing this may be more complex. - This may also be a define, in which case the function is not prototyped. - -- void sys_mutex_set_invalid(sys_mutex_t *mutex) - - Invalidate a mutex so that sys_mutex_valid() returns 0. - ATTENTION: This does NOT mean that the mutex shall be deallocated: - sys_mutex_free() is always called before calling this function! - This may also be a define, in which case the function is not prototyped. - -- err_t sys_mbox_new(sys_mbox_t *mbox, int size) - - Creates an empty mailbox for maximum "size" elements. Elements stored - in mailboxes are pointers. You have to define macros "_MBOX_SIZE" - in your lwipopts.h, or ignore this parameter in your implementation - and use a default size. - If the mailbox has been created, ERR_OK should be returned. Returning any - other error will provide a hint what went wrong, but except for assertions, - no real error handling is implemented. - -- void sys_mbox_free(sys_mbox_t *mbox) - - Deallocates a mailbox. If there are messages still present in the - mailbox when the mailbox is deallocated, it is an indication of a - programming error in lwIP and the developer should be notified. - -- void sys_mbox_post(sys_mbox_t *mbox, void *msg) - - Posts the "msg" to the mailbox. This function have to block until - the "msg" is really posted. - -- err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) - - Try to post the "msg" to the mailbox. Returns ERR_MEM if this one - is full, else, ERR_OK if the "msg" is posted. - -- u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) - - Blocks the thread until a message arrives in the mailbox, but does - not block the thread longer than "timeout" milliseconds (similar to - the sys_arch_sem_wait() function). If "timeout" is 0, the thread should - be blocked until a message arrives. The "msg" argument is a result - parameter that is set by the function (i.e., by doing "*msg = - ptr"). The "msg" parameter maybe NULL to indicate that the message - should be dropped. - - The return values are the same as for the sys_arch_sem_wait() function: - Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a - timeout. - - Note that a function with a similar name, sys_mbox_fetch(), is - implemented by lwIP. - -- u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) - - This is similar to sys_arch_mbox_fetch, however if a message is not - present in the mailbox, it immediately returns with the code - SYS_MBOX_EMPTY. On success 0 is returned. - - To allow for efficient implementations, this can be defined as a - function-like macro in sys_arch.h instead of a normal function. For - example, a naive implementation could be: - #define sys_arch_mbox_tryfetch(mbox,msg) \ - sys_arch_mbox_fetch(mbox,msg,1) - although this would introduce unnecessary delays. - -- int sys_mbox_valid(sys_mbox_t *mbox) - - Returns 1 if the mailbox is valid, 0 if it is not valid. - When using pointers, a simple way is to check the pointer for != NULL. - When directly using OS structures, implementing this may be more complex. - This may also be a define, in which case the function is not prototyped. - -- void sys_mbox_set_invalid(sys_mbox_t *mbox) - - Invalidate a mailbox so that sys_mbox_valid() returns 0. - ATTENTION: This does NOT mean that the mailbox shall be deallocated: - sys_mbox_free() is always called before calling this function! - This may also be a define, in which case the function is not prototyped. - -If threads are supported by the underlying operating system and if -such functionality is needed in lwIP, the following function will have -to be implemented as well: - -- sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio) - - Starts a new thread named "name" with priority "prio" that will begin its - execution in the function "thread()". The "arg" argument will be passed as an - argument to the thread() function. The stack size to used for this thread is - the "stacksize" parameter. The id of the new thread is returned. Both the id - and the priority are system dependent. - -When lwIP is used from more than one context (e.g. from multiple threads OR from -main-loop and from interrupts), the SYS_LIGHTWEIGHT_PROT protection SHOULD be enabled! - -- sys_prot_t sys_arch_protect(void) - - This optional function does a "fast" critical region protection and returns - the previous protection level. This function is only called during very short - critical regions. An embedded system which supports ISR-based drivers might - want to implement this function by disabling interrupts. Task-based systems - might want to implement this by using a mutex or disabling tasking. This - function should support recursive calls from the same task or interrupt. In - other words, sys_arch_protect() could be called while already protected. In - that case the return value indicates that it is already protected. - - sys_arch_protect() is only required if your port is supporting an operating - system. - -- void sys_arch_unprotect(sys_prot_t pval) - - This optional function does a "fast" set of critical region protection to the - value specified by pval. See the documentation for sys_arch_protect() for - more information. This function is only required if your port is supporting - an operating system. - -For some configurations, you also need: - -- u32_t sys_now(void) - - This optional function returns the current time in milliseconds (don't care - for wraparound, this is only used for time diffs). - Not implementing this function means you cannot use some modules (e.g. TCP - timestamps, internal timeouts for NO_SYS==1). - - -Note: - -Be careful with using mem_malloc() in sys_arch. When malloc() refers to -mem_malloc() you can run into a circular function call problem. In mem.c -mem_init() tries to allcate a semaphore using mem_malloc, which of course -can't be performed when sys_arch uses mem_malloc. - -------------------------------------------------------------------------------- -Additional files required for the "OS support" emulation layer: -------------------------------------------------------------------------------- - -cc.h - Architecture environment, some compiler specific, some - environment specific (probably should move env stuff - to sys_arch.h.) - - Typedefs for the types used by lwip - - u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t - - Compiler hints for packing lwip's structures - - PACK_STRUCT_FIELD(x) - PACK_STRUCT_STRUCT - PACK_STRUCT_BEGIN - PACK_STRUCT_END - - Platform specific diagnostic output - - LWIP_PLATFORM_DIAG(x) - non-fatal, print a message. - LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution. - Portability defines for printf formatters: - U16_F, S16_F, X16_F, U32_F, S32_F, X32_F, SZT_F - - "lightweight" synchronization mechanisms - - SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable. - SYS_ARCH_PROTECT(x) - enter protection mode. - SYS_ARCH_UNPROTECT(x) - leave protection mode. - - If the compiler does not provide memset() this file must include a - definition of it, or include a file which defines it. - - This file must either include a system-local which defines - the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO - to make lwip/arch.h define the codes which are used throughout. - - -perf.h - Architecture specific performance measurement. - Measurement calls made throughout lwip, these can be defined to nothing. - PERF_START - start measuring something. - PERF_STOP(x) - stop measuring something, and record the result. - -sys_arch.h - Tied to sys_arch.c - - Arch dependent types for the following objects: - sys_sem_t, sys_mbox_t, sys_thread_t, - And, optionally: - sys_prot_t - - Defines to set vars of sys_mbox_t and sys_sem_t to NULL. - SYS_MBOX_NULL NULL - SYS_SEM_NULL NULL diff --git a/ext/lwip/src/Filelists.mk b/ext/lwip/src/Filelists.mk index 86366bb..0b323e6 100755 --- a/ext/lwip/src/Filelists.mk +++ b/ext/lwip/src/Filelists.mk @@ -78,8 +78,8 @@ APIFILES=$(LWIPDIR)/api/api_lib.c \ $(LWIPDIR)/api/tcpip.c # NETIFFILES: Files implementing various generic network interface functions -NETIFFILES=$(LWIPDIR)/netif/ethernet.c \ - $(LWIPDIR)/netif/slipif.c +NETIFFILES=$(LWIPDIR)/netif/ethernet.c +#\ $(LWIPDIR)/netif/slipif.c # SIXLOWPAN: 6LoWPAN SIXLOWPAN=$(LWIPDIR)/netif/lowpan6.c \ @@ -122,8 +122,8 @@ LWIPNOAPPSFILES=$(COREFILES) \ $(CORE6FILES) \ $(APIFILES) \ $(NETIFFILES) \ - $(PPPFILES) \ $(SIXLOWPAN) +# $(PPPFILES) # SNMPFILES: SNMPv2c agent SNMPFILES=$(LWIPDIR)/apps/snmp/snmp_asn1.c \ diff --git a/ext/lwip/src/api/err.c b/ext/lwip/src/api/err.c index cc3dabb..6e9ab76 100755 --- a/ext/lwip/src/api/err.c +++ b/ext/lwip/src/api/err.c @@ -40,8 +40,7 @@ #include "lwip/def.h" #include "lwip/sys.h" -#include -//#include "lwip/errno.h" +#include "lwip/errno.h" #if !NO_SYS /** Table to quickly map an lwIP error (err_t) to a socket error diff --git a/ext/lwip/src/core/tcp.c b/ext/lwip/src/core/tcp.c index fb95374..7103a52 100755 --- a/ext/lwip/src/core/tcp.c +++ b/ext/lwip/src/core/tcp.c @@ -1001,7 +1001,7 @@ tcp_slowtmr_start: prev = NULL; pcb = tcp_active_pcbs; if (pcb == NULL) { - LWIP_DEBUGF(TCP_DEBUG_TMR, ("tcp_slowtmr: no active pcbs\n")); + LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); } while (pcb != NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); diff --git a/ext/lwip/src/include/arch/cc.h b/ext/lwip/src/include/arch/cc.h index c1046ba..3e77e65 100644 --- a/ext/lwip/src/include/arch/cc.h +++ b/ext/lwip/src/include/arch/cc.h @@ -29,65 +29,42 @@ * Author: Adam Dunkels * */ -#ifndef __ARCH_CC_H__ -#define __ARCH_CC_H__ +#ifndef LWIP_ARCH_CC_H +#define LWIP_ARCH_CC_H -/* Include some files for defining library routines */ -#include -#include -#include -#include - -#define LWIP_TIMEVAL_PRIVATE 0 - -/* Define platform endianness */ -#ifndef BYTE_ORDER -#define BYTE_ORDER LITTLE_ENDIAN -#endif /* BYTE_ORDER */ - -/* Define generic types used in lwIP */ -typedef unsigned char u8_t; -typedef signed char s8_t; -typedef unsigned short u16_t; -typedef signed short s16_t; -typedef unsigned int u32_t; -typedef signed int s32_t; - -typedef unsigned long mem_ptr_t; - -/* Define (sn)printf formatters for these lwIP types */ -#define X8_F "02x" -#define U16_F "hu" -#define S16_F "hd" -#define X16_F "hx" -#define U32_F "u" -#define S32_F "d" -#define X32_F "x" - -/* If only we could use C99 and get %zu */ -#if defined(__x86_64__) -#define SZT_F "lu" -#else -#define SZT_F "u" +/* see https://sourceforge.net/p/predef/wiki/OperatingSystems/ */ +#if defined __ANDROID__ +#define LWIP_UNIX_ANDROID +#elif defined __linux__ +#define LWIP_UNIX_LINUX +#elif defined __APPLE__ +#define LWIP_UNIX_MACH +#elif defined __OpenBSD__ +#define LWIP_UNIX_OPENBSD +#elif defined __CYGWIN__ +#define LWIP_UNIX_CYGWIN #endif -/* Compiler hints for packing structures */ -#define PACK_STRUCT_FIELD(x) x -#define PACK_STRUCT_STRUCT __attribute__((packed)) -#define PACK_STRUCT_BEGIN -#define PACK_STRUCT_END +#define LWIP_TIMEVAL_PRIVATE 0 +#include -/* prototypes for printf() and abort() */ -#include -#include -/* Plaform specific diagnostic output */ -//#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) -#include "Debug.hpp" -#define LWIP_PLATFORM_DIAG(x) DEBUG_STACK x; - -#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \ - x, __LINE__, __FILE__); fflush(NULL); abort();} while(0) +#define LWIP_ERRNO_INCLUDE #define LWIP_RAND() ((u32_t)rand()) -#endif /* __ARCH_CC_H__ */ +/* different handling for unit test, normally not needed */ +#ifdef LWIP_NOASSERT_ON_ERROR +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ + handler;}} while(0) +#endif + +#if defined(LWIP_UNIX_ANDROID) && defined(FD_SET) +typedef __kernel_fd_set fd_set; +#endif + +struct sio_status_s; +typedef struct sio_status_s sio_status_t; +#define sio_fd_t sio_status_t* +#define __sio_fd_t_defined + +#endif /* LWIP_ARCH_CC_H */ diff --git a/ext/lwip/src/include/arch/perf.h b/ext/lwip/src/include/arch/perf.h index 9fbcf60..326ac9e 100644 --- a/ext/lwip/src/include/arch/perf.h +++ b/ext/lwip/src/include/arch/perf.h @@ -29,8 +29,8 @@ * Author: Adam Dunkels * */ -#ifndef __ARCH_PERF_H__ -#define __ARCH_PERF_H__ +#ifndef LWIP_ARCH_PERF_H +#define LWIP_ARCH_PERF_H #include @@ -60,4 +60,4 @@ void perf_print_times(struct tms *start, struct tms *end, char *key); void perf_init(char *fname); -#endif /* __ARCH_PERF_H__ */ +#endif /* LWIP_ARCH_PERF_H */ diff --git a/ext/lwip/src/include/arch/sys_arch.h b/ext/lwip/src/include/arch/sys_arch.h index 56d20af..f11ae33 100644 --- a/ext/lwip/src/include/arch/sys_arch.h +++ b/ext/lwip/src/include/arch/sys_arch.h @@ -29,10 +29,8 @@ * Author: Adam Dunkels * */ -#ifndef __ARCH_SYS_ARCH_H__ -#define __ARCH_SYS_ARCH_H__ - -#include +#ifndef LWIP_ARCH_SYS_ARCH_H +#define LWIP_ARCH_SYS_ARCH_H #define SYS_MBOX_NULL NULL #define SYS_SEM_NULL NULL @@ -41,19 +39,25 @@ typedef u32_t sys_prot_t; struct sys_sem; typedef struct sys_sem * sys_sem_t; -#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL)) -#define sys_sem_set_invalid(sem) do { if((sem) != NULL) { *(sem) = NULL; }}while(0) +#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL)) +#define sys_sem_valid_val(sem) ((sem) != NULL) +#define sys_sem_set_invalid(sem) do { if((sem) != NULL) { *(sem) = NULL; }}while(0) +#define sys_sem_set_invalid_val(sem) do { (sem) = NULL; }while(0) -/* let sys.h use binary semaphores for mutexes */ -#define LWIP_COMPAT_MUTEX 1 +struct sys_mutex; +typedef struct sys_mutex * sys_mutex_t; +#define sys_mutex_valid(mutex) sys_sem_valid(mutex) +#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) struct sys_mbox; -typedef struct sys_mbox *sys_mbox_t; -#define sys_mbox_valid(mbox) (((mbox) != NULL) && (*(mbox) != NULL)) -#define sys_mbox_set_invalid(mbox) do { if((mbox) != NULL) { *(mbox) = NULL; }}while(0) +typedef struct sys_mbox * sys_mbox_t; +#define sys_mbox_valid(mbox) sys_sem_valid(mbox) +#define sys_mbox_valid_val(mbox) sys_sem_valid_val(mbox) +#define sys_mbox_set_invalid(mbox) sys_sem_set_invalid(mbox) +#define sys_mbox_set_invalid_val(mbox) sys_sem_set_invalid_val(mbox) struct sys_thread; typedef struct sys_thread * sys_thread_t; -#endif /* __ARCH_SYS_ARCH_H__ */ +#endif /* LWIP_ARCH_SYS_ARCH_H */ diff --git a/ext/lwip/src/include/lwip/arch.h b/ext/lwip/src/include/lwip/arch.h index f366ab5..6bb6368 100755 --- a/ext/lwip/src/include/lwip/arch.h +++ b/ext/lwip/src/include/lwip/arch.h @@ -75,8 +75,9 @@ * in turn pull in a lot of standard libary code. In resource-constrained * systems, this should be defined to something less resource-consuming. */ +#include "Debug.hpp" #ifndef LWIP_PLATFORM_DIAG -#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) +#define LWIP_PLATFORM_DIAG(x) DEBUG_STACK x #include #include #endif @@ -136,30 +137,16 @@ typedef uintptr_t mem_ptr_t; /* Define (sn)printf formatters for these lwIP types */ #if !LWIP_NO_INTTYPES_H #include -#ifndef X8_F -#define X8_F "02" PRIx8 -#endif -#ifndef U16_F -#define U16_F PRIu16 -#endif -#ifndef S16_F -#define S16_F PRId16 -#endif -#ifndef X16_F -#define X16_F PRIx16 -#endif -#ifndef U32_F -#define U32_F PRIu32 -#endif -#ifndef S32_F -#define S32_F PRId32 -#endif -#ifndef X32_F -#define X32_F PRIx32 -#endif -#ifndef SZT_F -#define SZT_F PRIuPTR -#endif +#define U8_F "c" +#define S8_F "c" +#define X8_F "x" +#define U16_F "u" +#define S16_F "d" +#define X16_F "x" +#define U32_F "u" +#define S32_F "d" +#define X32_F "x" +#define SZT_F "d" #endif /** Define this to 1 in arch/cc.h of your port if your compiler does not provide diff --git a/ext/lwip/src/include/lwip/fuck_off.h b/ext/lwip/src/include/lwip/errno.h similarity index 97% rename from ext/lwip/src/include/lwip/fuck_off.h rename to ext/lwip/src/include/lwip/errno.h index 2d326cb..47a4ff2 100755 --- a/ext/lwip/src/include/lwip/fuck_off.h +++ b/ext/lwip/src/include/lwip/errno.h @@ -181,7 +181,7 @@ extern int errno; /* Define LWIP_ERRNO_INCLUDE to to include the error defines here */ #ifdef LWIP_ERRNO_INCLUDE -#include LWIP_ERRNO_INCLUDE +//#include #endif /* LWIP_ERRNO_INCLUDE */ #endif /* LWIP_PROVIDE_ERRNO */ diff --git a/ext/lwip/src/include/lwip/sockets.h b/ext/lwip/src/include/lwip/sockets.h index ab33292..1646c12 100755 --- a/ext/lwip/src/include/lwip/sockets.h +++ b/ext/lwip/src/include/lwip/sockets.h @@ -40,13 +40,15 @@ #define LWIP_HDR_SOCKETS_H #include "lwip/opt.h" +#include "lwip/sockets.h" #if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ #include "lwip/ip_addr.h" #include "lwip/err.h" #include "lwip/inet.h" -#include "lwip/errno.h" +//#include "lwip/errno.h" +#include #ifdef __cplusplus extern "C" { @@ -508,42 +510,6 @@ int lwip_fcntl(int s, int cmd, int val); #if LWIP_COMPAT_SOCKETS #if LWIP_COMPAT_SOCKETS != 2 -/** @ingroup socket */ -#define accept(s,addr,addrlen) lwip_accept(s,addr,addrlen) -/** @ingroup socket */ -#define bind(s,name,namelen) lwip_bind(s,name,namelen) -/** @ingroup socket */ -#define shutdown(s,how) lwip_shutdown(s,how) -/** @ingroup socket */ -#define getpeername(s,name,namelen) lwip_getpeername(s,name,namelen) -/** @ingroup socket */ -#define getsockname(s,name,namelen) lwip_getsockname(s,name,namelen) -/** @ingroup socket */ -#define setsockopt(s,level,optname,opval,optlen) lwip_setsockopt(s,level,optname,opval,optlen) -/** @ingroup socket */ -#define getsockopt(s,level,optname,opval,optlen) lwip_getsockopt(s,level,optname,opval,optlen) -/** @ingroup socket */ -#define closesocket(s) lwip_close(s) -/** @ingroup socket */ -#define connect(s,name,namelen) lwip_connect(s,name,namelen) -/** @ingroup socket */ -#define listen(s,backlog) lwip_listen(s,backlog) -/** @ingroup socket */ -#define recv(s,mem,len,flags) lwip_recv(s,mem,len,flags) -/** @ingroup socket */ -#define recvfrom(s,mem,len,flags,from,fromlen) lwip_recvfrom(s,mem,len,flags,from,fromlen) -/** @ingroup socket */ -#define send(s,dataptr,size,flags) lwip_send(s,dataptr,size,flags) -/** @ingroup socket */ -#define sendmsg(s,message,flags) lwip_sendmsg(s,message,flags) -/** @ingroup socket */ -#define sendto(s,dataptr,size,flags,to,tolen) lwip_sendto(s,dataptr,size,flags,to,tolen) -/** @ingroup socket */ -#define socket(domain,type,protocol) lwip_socket(domain,type,protocol) -/** @ingroup socket */ -#define select(maxfdp1,readset,writeset,exceptset,timeout) lwip_select(maxfdp1,readset,writeset,exceptset,timeout) -/** @ingroup socket */ -#define ioctlsocket(s,cmd,argp) lwip_ioctl(s,cmd,argp) #if LWIP_POSIX_SOCKETS_IO_NAMES /** @ingroup socket */ diff --git a/ext/lwip/src/include/lwip/sys.h b/ext/lwip/src/include/lwip/sys.h index 98c38d7..c17204a 100755 --- a/ext/lwip/src/include/lwip/sys.h +++ b/ext/lwip/src/include/lwip/sys.h @@ -42,7 +42,7 @@ #ifdef __cplusplus extern "C" { #endif - + #if NO_SYS /* For a totally minimal and standalone system, we provide null diff --git a/ext/lwip/test/fuzz/README b/ext/lwip/test/fuzz/README deleted file mode 100755 index 2cefdec..0000000 --- a/ext/lwip/test/fuzz/README +++ /dev/null @@ -1,34 +0,0 @@ - -Fuzzing the lwIP stack (afl-fuzz requires linux/unix or similar) - -This directory contains a small app that reads Ethernet frames from stdin and -processes them. It is used together with the 'american fuzzy lop' tool (found -at http://lcamtuf.coredump.cx/afl/) and the sample inputs to test how -unexpected inputs are handled. The afl tool will read the known inputs, and -try to modify them to exercise as many code paths as possible, by instrumenting -the code and keeping track of which code is executed. - -Just running make will produce the test program. - -Then run afl with: - -afl-fuzz -i inputs/ -o output ./lwip_fuzz - -and it should start working. It will probably complain about CPU scheduler, -set AFL_SKIP_CPUFREQ=1 to ignore it. -If it complains about invalid "/proc/sys/kernel/core_pattern" setting, try -executing "sudo bash -c 'echo core > /proc/sys/kernel/core_pattern'". - -The input is split into different subdirectories since they test different -parts of the code, and since you want to run one instance of afl-fuzz on each -core. - -When afl finds a crash or a hang, the input that caused it will be placed in -the output directory. If you have hexdump and text2pcap tools installed, -running output_to_pcap.sh will create pcap files for each input -file to simplify viewing in wireshark. - -The lwipopts.h file needs to have checksum checking off, otherwise almost every -packet will be discarded because of that. The other options can be tuned to -expose different parts of the code. - diff --git a/ext/lwip/test/fuzz/config.h b/ext/lwip/test/fuzz/config.h deleted file mode 100755 index e69de29..0000000 diff --git a/ext/lwip/test/fuzz/fuzz.c b/ext/lwip/test/fuzz/fuzz.c deleted file mode 100755 index 9ef38d0..0000000 --- a/ext/lwip/test/fuzz/fuzz.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Ekman - * - */ - -#include "lwip/init.h" -#include "lwip/netif.h" -#include "netif/etharp.h" -#if LWIP_IPV6 -#include "lwip/ethip6.h" -#include "lwip/nd6.h" -#endif -#include -#include - -/* no-op send function */ -static err_t lwip_tx_func(struct netif *netif, struct pbuf *p) -{ - LWIP_UNUSED_ARG(netif); - LWIP_UNUSED_ARG(p); - return ERR_OK; -} - -static err_t testif_init(struct netif *netif) -{ - netif->name[0] = 'f'; - netif->name[1] = 'z'; - netif->output = etharp_output; - netif->linkoutput = lwip_tx_func; - netif->mtu = 1500; - netif->hwaddr_len = 6; - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; - - netif->hwaddr[0] = 0x00; - netif->hwaddr[1] = 0x23; - netif->hwaddr[2] = 0xC1; - netif->hwaddr[3] = 0xDE; - netif->hwaddr[4] = 0xD0; - netif->hwaddr[5] = 0x0D; - -#if LWIP_IPV6 - netif->output_ip6 = ethip6_output; - netif->ip6_autoconfig_enabled = 1; - netif_create_ip6_linklocal_address(netif, 1); - netif->flags |= NETIF_FLAG_MLD6; -#endif - - return ERR_OK; -} - -static void input_pkt(struct netif *netif, const u8_t *data, size_t len) -{ - struct pbuf *p, *q; - err_t err; - - LWIP_ASSERT("pkt too big", len <= 0xFFFF); - p = pbuf_alloc(PBUF_RAW, (u16_t)len, PBUF_POOL); - LWIP_ASSERT("alloc failed", p); - for(q = p; q != NULL; q = q->next) { - MEMCPY(q->payload, data, q->len); - data += q->len; - } - err = netif->input(p, netif); - if (err != ERR_OK) { - pbuf_free(p); - } -} - -int main(int argc, char** argv) -{ - struct netif net_test; - ip4_addr_t addr; - ip4_addr_t netmask; - ip4_addr_t gw; - u8_t pktbuf[2000]; - size_t len; - - lwip_init(); - - IP4_ADDR(&addr, 172, 30, 115, 84); - IP4_ADDR(&netmask, 255, 255, 255, 0); - IP4_ADDR(&gw, 172, 30, 115, 1); - - netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); - netif_set_up(&net_test); - -#if LWIP_IPV6 - nd6_tmr(); /* tick nd to join multicast groups */ -#endif - - if(argc > 1) { - FILE* f; - const char* filename; - printf("reading input from file... "); - fflush(stdout); - filename = argv[1]; - LWIP_ASSERT("invalid filename", filename != NULL); - f = fopen(filename, "rb"); - LWIP_ASSERT("open failed", f != NULL); - len = fread(pktbuf, 1, sizeof(pktbuf), f); - fclose(f); - printf("testing file: \"%s\"...\r\n", filename); - } else { - len = fread(pktbuf, 1, sizeof(pktbuf), stdin); - } - input_pkt(&net_test, pktbuf, len); - - return 0; -} diff --git a/ext/lwip/test/fuzz/inputs/arp/arp_req.bin b/ext/lwip/test/fuzz/inputs/arp/arp_req.bin deleted file mode 100755 index b317334..0000000 Binary files a/ext/lwip/test/fuzz/inputs/arp/arp_req.bin and /dev/null differ diff --git a/ext/lwip/test/fuzz/inputs/icmp/icmp_ping.bin b/ext/lwip/test/fuzz/inputs/icmp/icmp_ping.bin deleted file mode 100755 index 87e1ea7..0000000 Binary files a/ext/lwip/test/fuzz/inputs/icmp/icmp_ping.bin and /dev/null differ diff --git a/ext/lwip/test/fuzz/inputs/ipv6/neighbor_solicitation.bin b/ext/lwip/test/fuzz/inputs/ipv6/neighbor_solicitation.bin deleted file mode 100755 index d2f921c..0000000 Binary files a/ext/lwip/test/fuzz/inputs/ipv6/neighbor_solicitation.bin and /dev/null differ diff --git a/ext/lwip/test/fuzz/inputs/ipv6/router_adv.bin b/ext/lwip/test/fuzz/inputs/ipv6/router_adv.bin deleted file mode 100755 index 3aa9615..0000000 Binary files a/ext/lwip/test/fuzz/inputs/ipv6/router_adv.bin and /dev/null differ diff --git a/ext/lwip/test/fuzz/inputs/tcp/tcp_syn.bin b/ext/lwip/test/fuzz/inputs/tcp/tcp_syn.bin deleted file mode 100755 index d77f6d2..0000000 Binary files a/ext/lwip/test/fuzz/inputs/tcp/tcp_syn.bin and /dev/null differ diff --git a/ext/lwip/test/fuzz/inputs/udp/udp_port_5000.bin b/ext/lwip/test/fuzz/inputs/udp/udp_port_5000.bin deleted file mode 100755 index d77e267..0000000 Binary files a/ext/lwip/test/fuzz/inputs/udp/udp_port_5000.bin and /dev/null differ diff --git a/ext/lwip/test/fuzz/output_to_pcap.sh b/ext/lwip/test/fuzz/output_to_pcap.sh deleted file mode 100755 index 318218e..0000000 --- a/ext/lwip/test/fuzz/output_to_pcap.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -if [ -z "$1" ] -then - echo "This script will make pcap files from the afl-fuzz crash/hang files" - echo "It needs hexdump and text2pcap" - echo "Please give output directory as argument" - exit 2 -fi - -for i in `ls $1/crashes/id*` -do - PCAPNAME=`echo $i | grep pcap` - if [ -z "$PCAPNAME" ]; then - hexdump -C $i > $1/$$.tmp - text2pcap $1/$$.tmp ${i}.pcap - fi -done -for i in `ls $1/hangs/id*` -do - PCAPNAME=`echo $i | grep pcap` - if [ -z "$PCAPNAME" ]; then - hexdump -C $i > $1/$$.tmp - text2pcap $1/$$.tmp ${i}.pcap - fi -done -rm -f $1/$$.tmp - -echo -echo "Created pcap files:" -ls $1/*/*.pcap diff --git a/ext/lwip/test/unit/core/test_mem.c b/ext/lwip/test/unit/core/test_mem.c deleted file mode 100755 index b102011..0000000 --- a/ext/lwip/test/unit/core/test_mem.c +++ /dev/null @@ -1,121 +0,0 @@ -#include "test_mem.h" - -#include "lwip/mem.h" -#include "lwip/stats.h" - -#if !LWIP_STATS || !MEM_STATS -#error "This tests needs MEM-statistics enabled" -#endif -#if LWIP_DNS -#error "This test needs DNS turned off (as it mallocs on init)" -#endif - -/* Setups/teardown functions */ - -static void -mem_setup(void) -{ -} - -static void -mem_teardown(void) -{ -} - - -/* Test functions */ - -/** Call mem_malloc, mem_free and mem_trim and check stats */ -START_TEST(test_mem_one) -{ -#define SIZE1 16 -#define SIZE1_2 12 -#define SIZE2 16 - void *p1, *p2; - mem_size_t s1, s2; - LWIP_UNUSED_ARG(_i); - - fail_unless(lwip_stats.mem.used == 0); - - p1 = mem_malloc(SIZE1); - fail_unless(p1 != NULL); - fail_unless(lwip_stats.mem.used >= SIZE1); - s1 = lwip_stats.mem.used; - - p2 = mem_malloc(SIZE2); - fail_unless(p2 != NULL); - fail_unless(lwip_stats.mem.used >= SIZE2 + s1); - s2 = lwip_stats.mem.used; - - mem_trim(p1, SIZE1_2); - - mem_free(p2); - fail_unless(lwip_stats.mem.used <= s2 - SIZE2); - - mem_free(p1); - fail_unless(lwip_stats.mem.used == 0); -} -END_TEST - -static void malloc_keep_x(int x, int num, int size, int freestep) -{ - int i; - void* p[16]; - LWIP_ASSERT("invalid size", size >= 0 && size < (mem_size_t)-1); - memset(p, 0, sizeof(p)); - for(i = 0; i < num && i < 16; i++) { - p[i] = mem_malloc((mem_size_t)size); - fail_unless(p[i] != NULL); - } - for(i = 0; i < num && i < 16; i += freestep) { - if (i == x) { - continue; - } - mem_free(p[i]); - p[i] = NULL; - } - for(i = 0; i < num && i < 16; i++) { - if (i == x) { - continue; - } - if (p[i] != NULL) { - mem_free(p[i]); - p[i] = NULL; - } - } - fail_unless(p[x] != NULL); - mem_free(p[x]); -} - -START_TEST(test_mem_random) -{ - const int num = 16; - int x; - int size; - int freestep; - LWIP_UNUSED_ARG(_i); - - fail_unless(lwip_stats.mem.used == 0); - - for (x = 0; x < num; x++) { - for (size = 1; size < 32; size++) { - for (freestep = 1; freestep <= 3; freestep++) { - fail_unless(lwip_stats.mem.used == 0); - malloc_keep_x(x, num, size, freestep); - fail_unless(lwip_stats.mem.used == 0); - } - } - } -} -END_TEST - -/** Create the suite including all tests for this module */ -Suite * -mem_suite(void) -{ - testfunc tests[] = { - TESTFUNC(test_mem_one), - TESTFUNC(test_mem_random) - }; - return create_suite("MEM", tests, sizeof(tests)/sizeof(testfunc), mem_setup, mem_teardown); -} diff --git a/ext/lwip/test/unit/core/test_mem.h b/ext/lwip/test/unit/core/test_mem.h deleted file mode 100755 index 4a02d7d..0000000 --- a/ext/lwip/test/unit/core/test_mem.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_MEM_H -#define LWIP_HDR_TEST_MEM_H - -#include "../lwip_check.h" - -Suite *mem_suite(void); - -#endif diff --git a/ext/lwip/test/unit/core/test_pbuf.c b/ext/lwip/test/unit/core/test_pbuf.c deleted file mode 100755 index c5f4684..0000000 --- a/ext/lwip/test/unit/core/test_pbuf.c +++ /dev/null @@ -1,239 +0,0 @@ -#include "test_pbuf.h" - -#include "lwip/pbuf.h" -#include "lwip/stats.h" - -#if !LWIP_STATS || !MEM_STATS ||!MEMP_STATS -#error "This tests needs MEM- and MEMP-statistics enabled" -#endif -#if LWIP_DNS -#error "This test needs DNS turned off (as it mallocs on init)" -#endif -#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !LWIP_WND_SCALE -#error "This test needs TCP OOSEQ queueing and window scaling enabled" -#endif - -/* Setups/teardown functions */ - -static void -pbuf_setup(void) -{ -} - -static void -pbuf_teardown(void) -{ -} - - -#define TESTBUFSIZE_1 65535 -#define TESTBUFSIZE_2 65530 -#define TESTBUFSIZE_3 50050 -static u8_t testbuf_1[TESTBUFSIZE_1]; -static u8_t testbuf_1a[TESTBUFSIZE_1]; -static u8_t testbuf_2[TESTBUFSIZE_2]; -static u8_t testbuf_2a[TESTBUFSIZE_2]; -static u8_t testbuf_3[TESTBUFSIZE_3]; -static u8_t testbuf_3a[TESTBUFSIZE_3]; - -/* Test functions */ - -/** Call pbuf_copy on a pbuf with zero length */ -START_TEST(test_pbuf_copy_zero_pbuf) -{ - struct pbuf *p1, *p2, *p3; - err_t err; - LWIP_UNUSED_ARG(_i); - - fail_unless(lwip_stats.mem.used == 0); - fail_unless(MEMP_STATS_GET(used, MEMP_PBUF_POOL) == 0); - - p1 = pbuf_alloc(PBUF_RAW, 1024, PBUF_RAM); - fail_unless(p1 != NULL); - fail_unless(p1->ref == 1); - - p2 = pbuf_alloc(PBUF_RAW, 2, PBUF_POOL); - fail_unless(p2 != NULL); - fail_unless(p2->ref == 1); - p2->len = p2->tot_len = 0; - - pbuf_cat(p1, p2); - fail_unless(p1->ref == 1); - fail_unless(p2->ref == 1); - - p3 = pbuf_alloc(PBUF_RAW, p1->tot_len, PBUF_POOL); - err = pbuf_copy(p3, p1); - fail_unless(err == ERR_VAL); - - pbuf_free(p1); - pbuf_free(p3); - fail_unless(lwip_stats.mem.used == 0); - - fail_unless(lwip_stats.mem.used == 0); - fail_unless(MEMP_STATS_GET(used, MEMP_PBUF_POOL) == 0); -} -END_TEST - -START_TEST(test_pbuf_split_64k_on_small_pbufs) -{ - struct pbuf *p, *rest=NULL; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, 1, PBUF_POOL); - pbuf_split_64k(p, &rest); - fail_unless(p->tot_len == 1); - pbuf_free(p); -} -END_TEST - -START_TEST(test_pbuf_queueing_bigger_than_64k) -{ - int i; - err_t err; - struct pbuf *p1, *p2, *p3, *rest2=NULL, *rest3=NULL; - LWIP_UNUSED_ARG(_i); - - for(i = 0; i < TESTBUFSIZE_1; i++) { - testbuf_1[i] = (u8_t)rand(); - } - for(i = 0; i < TESTBUFSIZE_2; i++) { - testbuf_2[i] = (u8_t)rand(); - } - for(i = 0; i < TESTBUFSIZE_3; i++) { - testbuf_3[i] = (u8_t)rand(); - } - - p1 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_1, PBUF_POOL); - fail_unless(p1 != NULL); - p2 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_2, PBUF_POOL); - fail_unless(p2 != NULL); - p3 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_3, PBUF_POOL); - fail_unless(p3 != NULL); - err = pbuf_take(p1, testbuf_1, TESTBUFSIZE_1); - fail_unless(err == ERR_OK); - err = pbuf_take(p2, testbuf_2, TESTBUFSIZE_2); - fail_unless(err == ERR_OK); - err = pbuf_take(p3, testbuf_3, TESTBUFSIZE_3); - fail_unless(err == ERR_OK); - - pbuf_cat(p1, p2); - pbuf_cat(p1, p3); - - pbuf_split_64k(p1, &rest2); - fail_unless(p1->tot_len == TESTBUFSIZE_1); - fail_unless(rest2->tot_len == (u16_t)((TESTBUFSIZE_2+TESTBUFSIZE_3) & 0xFFFF)); - pbuf_split_64k(rest2, &rest3); - fail_unless(rest2->tot_len == TESTBUFSIZE_2); - fail_unless(rest3->tot_len == TESTBUFSIZE_3); - - pbuf_copy_partial(p1, testbuf_1a, TESTBUFSIZE_1, 0); - pbuf_copy_partial(rest2, testbuf_2a, TESTBUFSIZE_2, 0); - pbuf_copy_partial(rest3, testbuf_3a, TESTBUFSIZE_3, 0); - for(i = 0; i < TESTBUFSIZE_1; i++) - fail_unless(testbuf_1[i] == testbuf_1a[i]); - for(i = 0; i < TESTBUFSIZE_2; i++) - fail_unless(testbuf_2[i] == testbuf_2a[i]); - for(i = 0; i < TESTBUFSIZE_3; i++) - fail_unless(testbuf_3[i] == testbuf_3a[i]); - - pbuf_free(p1); - pbuf_free(rest2); - pbuf_free(rest3); -} -END_TEST - -/* Test for bug that writing with pbuf_take_at() did nothing - * and returned ERR_OK when writing at beginning of a pbuf - * in the chain. - */ -START_TEST(test_pbuf_take_at_edge) -{ - err_t res; - u8_t *out; - int i; - u8_t testdata[] = { 0x01, 0x08, 0x82, 0x02 }; - struct pbuf *p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL); - struct pbuf *q = p->next; - LWIP_UNUSED_ARG(_i); - /* alloc big enough to get a chain of pbufs */ - fail_if(p->tot_len == p->len); - memset(p->payload, 0, p->len); - memset(q->payload, 0, q->len); - - /* copy data to the beginning of first pbuf */ - res = pbuf_take_at(p, &testdata, sizeof(testdata), 0); - fail_unless(res == ERR_OK); - - out = (u8_t*)p->payload; - for (i = 0; i < (int)sizeof(testdata); i++) { - fail_unless(out[i] == testdata[i], - "Bad data at pos %d, was %02X, expected %02X", i, out[i], testdata[i]); - } - - /* copy data to the just before end of first pbuf */ - res = pbuf_take_at(p, &testdata, sizeof(testdata), p->len - 1); - fail_unless(res == ERR_OK); - - out = (u8_t*)p->payload; - fail_unless(out[p->len - 1] == testdata[0], - "Bad data at pos %d, was %02X, expected %02X", p->len - 1, out[p->len - 1], testdata[0]); - out = (u8_t*)q->payload; - for (i = 1; i < (int)sizeof(testdata); i++) { - fail_unless(out[i-1] == testdata[i], - "Bad data at pos %d, was %02X, expected %02X", p->len - 1 + i, out[i-1], testdata[i]); - } - - /* copy data to the beginning of second pbuf */ - res = pbuf_take_at(p, &testdata, sizeof(testdata), p->len); - fail_unless(res == ERR_OK); - - out = (u8_t*)p->payload; - for (i = 0; i < (int)sizeof(testdata); i++) { - fail_unless(out[i] == testdata[i], - "Bad data at pos %d, was %02X, expected %02X", p->len+i, out[i], testdata[i]); - } -} -END_TEST - -/* Verify pbuf_put_at()/pbuf_get_at() when using - * offsets equal to beginning of new pbuf in chain - */ -START_TEST(test_pbuf_get_put_at_edge) -{ - u8_t *out; - u8_t testdata = 0x01; - u8_t getdata; - struct pbuf *p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL); - struct pbuf *q = p->next; - LWIP_UNUSED_ARG(_i); - /* alloc big enough to get a chain of pbufs */ - fail_if(p->tot_len == p->len); - memset(p->payload, 0, p->len); - memset(q->payload, 0, q->len); - - /* put byte at the beginning of second pbuf */ - pbuf_put_at(p, p->len, testdata); - - out = (u8_t*)q->payload; - fail_unless(*out == testdata, - "Bad data at pos %d, was %02X, expected %02X", p->len, *out, testdata); - - getdata = pbuf_get_at(p, p->len); - fail_unless(*out == getdata, - "pbuf_get_at() returned bad data at pos %d, was %02X, expected %02X", p->len, getdata, *out); -} -END_TEST - -/** Create the suite including all tests for this module */ -Suite * -pbuf_suite(void) -{ - testfunc tests[] = { - TESTFUNC(test_pbuf_copy_zero_pbuf), - TESTFUNC(test_pbuf_split_64k_on_small_pbufs), - TESTFUNC(test_pbuf_queueing_bigger_than_64k), - TESTFUNC(test_pbuf_take_at_edge), - TESTFUNC(test_pbuf_get_put_at_edge) - }; - return create_suite("PBUF", tests, sizeof(tests)/sizeof(testfunc), pbuf_setup, pbuf_teardown); -} diff --git a/ext/lwip/test/unit/core/test_pbuf.h b/ext/lwip/test/unit/core/test_pbuf.h deleted file mode 100755 index c13083b..0000000 --- a/ext/lwip/test/unit/core/test_pbuf.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_PBUF_H -#define LWIP_HDR_TEST_PBUF_H - -#include "../lwip_check.h" - -Suite *pbuf_suite(void); - -#endif diff --git a/ext/lwip/test/unit/dhcp/test_dhcp.c b/ext/lwip/test/unit/dhcp/test_dhcp.c deleted file mode 100755 index 64803c4..0000000 --- a/ext/lwip/test/unit/dhcp/test_dhcp.c +++ /dev/null @@ -1,1024 +0,0 @@ -#include "test_dhcp.h" - -#include "lwip/netif.h" -#include "lwip/dhcp.h" -#include "lwip/prot/dhcp.h" -#include "lwip/etharp.h" -#include "netif/ethernet.h" - -struct netif net_test; - -static const u8_t broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - -static const u8_t magic_cookie[] = { 0x63, 0x82, 0x53, 0x63 }; - -static u8_t dhcp_offer[] = { - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */ - 0x00, 0x0F, 0xEE, 0x30, 0xAB, 0x22, /* From Remote host */ - 0x08, 0x00, /* Protocol: IP */ - 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */ - 0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */ - - 0x02, /* Type == Boot reply */ - 0x01, 0x06, /* Hw Ethernet, 6 bytes addrlen */ - 0x00, /* 0 hops */ - 0xAA, 0xAA, 0xAA, 0xAA, /* Transaction id, will be overwritten */ - 0x00, 0x00, /* 0 seconds elapsed */ - 0x00, 0x00, /* Flags (unicast) */ - 0x00, 0x00, 0x00, 0x00, /* Client ip */ - 0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */ - 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server ip */ - 0x00, 0x00, 0x00, 0x00, /* relay agent */ - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MAC addr + padding */ - - /* Empty server name and boot file name */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - - 0x63, 0x82, 0x53, 0x63, /* Magic cookie */ - 0x35, 0x01, 0x02, /* Message type: Offer */ - 0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Server identifier (IP) */ - 0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */ - 0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */ - 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Subnet mask */ - 0xff, /* End option */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */ -}; - -static u8_t dhcp_ack[] = { - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */ - 0x00, 0x0f, 0xEE, 0x30, 0xAB, 0x22, /* From remote host */ - 0x08, 0x00, /* Proto IP */ - 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */ - 0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */ - 0x02, /* Bootp reply */ - 0x01, 0x06, /* Hw type Eth, len 6 */ - 0x00, /* 0 hops */ - 0xAA, 0xAA, 0xAA, 0xAA, - 0x00, 0x00, /* 0 seconds elapsed */ - 0x00, 0x00, /* Flags (unicast) */ - 0x00, 0x00, 0x00, 0x00, /* Client IP */ - 0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */ - 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server IP */ - 0x00, 0x00, 0x00, 0x00, /* Relay agent */ - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Macaddr + padding */ - - /* Empty server name and boot file name */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - - 0x63, 0x82, 0x53, 0x63, /* Magic cookie */ - 0x35, 0x01, 0x05, /* Dhcp message type ack */ - 0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server identifier */ - 0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */ - 0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */ - 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Netmask */ - 0xff, /* End marker */ - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */ -}; - -static const u8_t arpreply[] = { - 0x00, 0x23, 0xC1, 0xDE, 0xD0, 0x0D, /* dst mac */ - 0x00, 0x32, 0x44, 0x20, 0x01, 0x02, /* src mac */ - 0x08, 0x06, /* proto arp */ - 0x00, 0x01, /* hw eth */ - 0x08, 0x00, /* proto ip */ - 0x06, /* hw addr len 6 */ - 0x04, /* proto addr len 4 */ - 0x00, 0x02, /* arp reply */ - 0x00, 0x32, 0x44, 0x20, 0x01, 0x02, /* sender mac */ - 0xc3, 0xaa, 0xbd, 0xc8, /* sender ip */ - 0x00, 0x23, 0xC1, 0xDE, 0xD0, 0x0D, /* target mac */ - 0x00, 0x00, 0x00, 0x00, /* target ip */ -}; - -static int txpacket; -static enum tcase { - TEST_LWIP_DHCP, - TEST_LWIP_DHCP_NAK, - TEST_LWIP_DHCP_RELAY, - TEST_LWIP_DHCP_NAK_NO_ENDMARKER, - TEST_LWIP_DHCP_INVALID_OVERLOAD -} tcase; - -static int debug = 0; -static void setdebug(int a) {debug = a;} - -static int tick = 0; -static void tick_lwip(void) -{ - tick++; - if (tick % 5 == 0) { - dhcp_fine_tmr(); - } - if (tick % 600 == 0) { - dhcp_coarse_tmr(); - } -} - -static void send_pkt(struct netif *netif, const u8_t *data, size_t len) -{ - struct pbuf *p, *q; - LWIP_ASSERT("pkt too big", len <= 0xFFFF); - p = pbuf_alloc(PBUF_RAW, (u16_t)len, PBUF_POOL); - - if (debug) { - /* Dump data */ - u32_t i; - printf("RX data (len %d)", p->tot_len); - for (i = 0; i < len; i++) { - printf(" %02X", data[i]); - } - printf("\n"); - } - - fail_unless(p != NULL); - for(q = p; q != NULL; q = q->next) { - memcpy(q->payload, data, q->len); - data += q->len; - } - netif->input(p, netif); -} - -static err_t lwip_tx_func(struct netif *netif, struct pbuf *p); - -static err_t testif_init(struct netif *netif) -{ - netif->name[0] = 'c'; - netif->name[1] = 'h'; - netif->output = etharp_output; - netif->linkoutput = lwip_tx_func; - netif->mtu = 1500; - netif->hwaddr_len = 6; - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; - - netif->hwaddr[0] = 0x00; - netif->hwaddr[1] = 0x23; - netif->hwaddr[2] = 0xC1; - netif->hwaddr[3] = 0xDE; - netif->hwaddr[4] = 0xD0; - netif->hwaddr[5] = 0x0D; - - return ERR_OK; -} - -static void dhcp_setup(void) -{ - txpacket = 0; -} - -static void dhcp_teardown(void) -{ -} - -static void check_pkt(struct pbuf *p, u32_t pos, const u8_t *mem, u32_t len) -{ - u8_t *data; - - fail_if((pos + len) > p->tot_len); - while (pos > p->len && p->next) { - pos -= p->len; - p = p->next; - } - fail_if(p == NULL); - fail_unless(pos + len <= p->len); /* All data we seek within same pbuf */ - - data = (u8_t*)p->payload; - fail_if(memcmp(&data[pos], mem, len), "data at pos %d, len %d in packet %d did not match", pos, len, txpacket); -} - -static void check_pkt_fuzzy(struct pbuf *p, u32_t startpos, const u8_t *mem, u32_t len) -{ - int found; - u32_t i; - u8_t *data; - - fail_if((startpos + len) > p->tot_len); - while (startpos > p->len && p->next) { - startpos -= p->len; - p = p->next; - } - fail_if(p == NULL); - fail_unless(startpos + len <= p->len); /* All data we seek within same pbuf */ - - found = 0; - data = (u8_t*)p->payload; - for (i = startpos; i <= (p->len - len); i++) { - if (memcmp(&data[i], mem, len) == 0) { - found = 1; - break; - } - } - fail_unless(found); -} - -static err_t lwip_tx_func(struct netif *netif, struct pbuf *p) -{ - fail_unless(netif == &net_test); - txpacket++; - - if (debug) { - struct pbuf *pp = p; - /* Dump data */ - printf("TX data (pkt %d, len %d, tick %d)", txpacket, p->tot_len, tick); - do { - int i; - for (i = 0; i < pp->len; i++) { - printf(" %02X", ((u8_t *) pp->payload)[i]); - } - if (pp->next) { - pp = pp->next; - } - } while (pp->next); - printf("\n"); - } - - switch (tcase) { - case TEST_LWIP_DHCP: - switch (txpacket) { - case 1: - case 2: - { - const u8_t ipproto[] = { 0x08, 0x00 }; - const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */ - const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ - check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ - - check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */ - - check_pkt(p, 42, bootp_start, sizeof(bootp_start)); - - check_pkt(p, 53, ipaddrs, sizeof(ipaddrs)); - - check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */ - - check_pkt(p, 278, magic_cookie, sizeof(magic_cookie)); - - /* Check dchp message type, can be at different positions */ - if (txpacket == 1) { - u8_t dhcp_discover_opt[] = { 0x35, 0x01, 0x01 }; - check_pkt_fuzzy(p, 282, dhcp_discover_opt, sizeof(dhcp_discover_opt)); - } else if (txpacket == 2) { - u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 }; - u8_t requested_ipaddr[] = { 0x32, 0x04, 0xc3, 0xaa, 0xbd, 0xc8 }; /* Ask for offered IP */ - - check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt)); - check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr)); - } - break; - } - case 3: - case 4: - case 5: - { - const u8_t arpproto[] = { 0x08, 0x06 }; - - check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ - check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ - - check_pkt(p, 12, arpproto, sizeof(arpproto)); /* eth level proto: ip */ - break; - } - default: - fail(); - break; - } - break; - - case TEST_LWIP_DHCP_NAK: - { - const u8_t ipproto[] = { 0x08, 0x00 }; - const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */ - const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - const u8_t dhcp_nak_opt[] = { 0x35, 0x01, 0x04 }; - const u8_t requested_ipaddr[] = { 0x32, 0x04, 0xc3, 0xaa, 0xbd, 0xc8 }; /* offered IP */ - - fail_unless(txpacket == 4); - check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ - check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ - - check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */ - - check_pkt(p, 42, bootp_start, sizeof(bootp_start)); - - check_pkt(p, 53, ipaddrs, sizeof(ipaddrs)); - - check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */ - - check_pkt(p, 278, magic_cookie, sizeof(magic_cookie)); - - check_pkt_fuzzy(p, 282, dhcp_nak_opt, sizeof(dhcp_nak_opt)); /* NAK the ack */ - - check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr)); - break; - } - - case TEST_LWIP_DHCP_RELAY: - switch (txpacket) { - case 1: - case 2: - { - const u8_t ipproto[] = { 0x08, 0x00 }; - const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */ - const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ - check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ - - check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */ - - check_pkt(p, 42, bootp_start, sizeof(bootp_start)); - - check_pkt(p, 53, ipaddrs, sizeof(ipaddrs)); - - check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */ - - check_pkt(p, 278, magic_cookie, sizeof(magic_cookie)); - - /* Check dchp message type, can be at different positions */ - if (txpacket == 1) { - u8_t dhcp_discover_opt[] = { 0x35, 0x01, 0x01 }; - check_pkt_fuzzy(p, 282, dhcp_discover_opt, sizeof(dhcp_discover_opt)); - } else if (txpacket == 2) { - u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 }; - u8_t requested_ipaddr[] = { 0x32, 0x04, 0x4f, 0x8a, 0x33, 0x05 }; /* Ask for offered IP */ - - check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt)); - check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr)); - } - break; - } - case 3: - case 4: - case 5: - case 6: - { - const u8_t arpproto[] = { 0x08, 0x06 }; - - check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ - check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ - - check_pkt(p, 12, arpproto, sizeof(arpproto)); /* eth level proto: ip */ - break; - } - case 7: - { - const u8_t fake_arp[6] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xab }; - const u8_t ipproto[] = { 0x08, 0x00 }; - const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */ - const u8_t ipaddrs[] = { 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - const u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 }; - - check_pkt(p, 0, fake_arp, 6); /* eth level dest: broadcast */ - check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ - - check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */ - - check_pkt(p, 42, bootp_start, sizeof(bootp_start)); - - check_pkt(p, 53, ipaddrs, sizeof(ipaddrs)); - - check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */ - - check_pkt(p, 278, magic_cookie, sizeof(magic_cookie)); - - /* Check dchp message type, can be at different positions */ - check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt)); - break; - } - default: - fail(); - break; - } - break; - - default: - break; - } - - return ERR_OK; -} - -/* - * Test basic happy flow DHCP session. - * Validate that xid is checked. - */ -START_TEST(test_dhcp) -{ - ip4_addr_t addr; - ip4_addr_t netmask; - ip4_addr_t gw; - int i; - u32_t xid; - LWIP_UNUSED_ARG(_i); - - tcase = TEST_LWIP_DHCP; - setdebug(0); - - IP4_ADDR(&addr, 0, 0, 0, 0); - IP4_ADDR(&netmask, 0, 0, 0, 0); - IP4_ADDR(&gw, 0, 0, 0, 0); - - netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); - netif_set_up(&net_test); - - dhcp_start(&net_test); - - fail_unless(txpacket == 1); /* DHCP discover sent */ - xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ - memcpy(&dhcp_offer[46], &xid, 4); - send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); - - /* IP addresses should be zero */ - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - - fail_unless(txpacket == 1, "TX %d packets, expected 1", txpacket); /* Nothing more sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); - memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */ - send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); - - fail_unless(txpacket == 2, "TX %d packets, expected 2", txpacket); /* DHCP request sent */ - xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ - memcpy(&dhcp_ack[46], &xid, 4); - send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); - - fail_unless(txpacket == 2, "TX %d packets, still expected 2", txpacket); /* No more sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ - memcpy(&dhcp_ack[46], &xid, 4); /* insert transaction id */ - send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); - - for (i = 0; i < 20; i++) { - tick_lwip(); - } - fail_unless(txpacket == 5, "TX %d packets, expected 5", txpacket); /* ARP requests sent */ - - /* Interface up */ - fail_unless(netif_is_up(&net_test)); - - /* Now it should have taken the IP */ - IP4_ADDR(&addr, 195, 170, 189, 200); - IP4_ADDR(&netmask, 255, 255, 255, 0); - IP4_ADDR(&gw, 195, 170, 189, 171); - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - - netif_remove(&net_test); -} -END_TEST - -/* - * Test that IP address is not taken and NAK is sent if someone - * replies to ARP requests for the offered address. - */ -START_TEST(test_dhcp_nak) -{ - ip4_addr_t addr; - ip4_addr_t netmask; - ip4_addr_t gw; - u32_t xid; - LWIP_UNUSED_ARG(_i); - - tcase = TEST_LWIP_DHCP; - setdebug(0); - - IP4_ADDR(&addr, 0, 0, 0, 0); - IP4_ADDR(&netmask, 0, 0, 0, 0); - IP4_ADDR(&gw, 0, 0, 0, 0); - - netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); - netif_set_up(&net_test); - - dhcp_start(&net_test); - - fail_unless(txpacket == 1); /* DHCP discover sent */ - xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ - memcpy(&dhcp_offer[46], &xid, 4); - send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); - - /* IP addresses should be zero */ - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - - fail_unless(txpacket == 1); /* Nothing more sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); - memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */ - send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); - - fail_unless(txpacket == 2); /* DHCP request sent */ - xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ - memcpy(&dhcp_ack[46], &xid, 4); - send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); - - fail_unless(txpacket == 2); /* No more sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ - memcpy(&dhcp_ack[46], &xid, 4); /* insert transaction id */ - send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); - - fail_unless(txpacket == 3); /* ARP request sent */ - - tcase = TEST_LWIP_DHCP_NAK; /* Switch testcase */ - - /* Send arp reply, mark offered IP as taken */ - send_pkt(&net_test, arpreply, sizeof(arpreply)); - - fail_unless(txpacket == 4); /* DHCP nak sent */ - - netif_remove(&net_test); -} -END_TEST - -/* - * Test case based on captured data where - * replies are sent from a different IP than the - * one the client unicasted to. - */ -START_TEST(test_dhcp_relayed) -{ - u8_t relay_offer[] = { - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, - 0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, - 0x08, 0x00, 0x45, 0x00, - 0x01, 0x38, 0xfd, 0x53, 0x00, 0x00, 0x40, 0x11, - 0x78, 0x46, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a, - 0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24, - 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x51, 0x35, - 0xb6, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, - 0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23, - 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, - 0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00, - 0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08, - 0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1, - 0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04, - 0x00, 0x00, 0x54, 0x49, 0x35, 0x01, 0x02, 0x36, - 0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff - }; - - u8_t relay_ack1[] = { - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x22, - 0x93, 0x5a, 0xf7, 0x60, 0x08, 0x00, 0x45, 0x00, - 0x01, 0x38, 0xfd, 0x55, 0x00, 0x00, 0x40, 0x11, - 0x78, 0x44, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a, - 0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24, - 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x51, 0x35, - 0xb6, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, - 0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23, - 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, - 0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00, - 0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08, - 0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1, - 0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04, - 0x00, 0x00, 0x54, 0x49, 0x35, 0x01, 0x05, 0x36, - 0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff - }; - - u8_t relay_ack2[] = { - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, - 0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, - 0x08, 0x00, 0x45, 0x00, - 0x01, 0x38, 0xfa, 0x18, 0x00, 0x00, 0x40, 0x11, - 0x7b, 0x81, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a, - 0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24, - 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x49, 0x8b, - 0x6e, 0xab, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x8a, - 0x33, 0x05, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, - 0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23, - 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, - 0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00, - 0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08, - 0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1, - 0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04, - 0x00, 0x00, 0x54, 0x60, 0x35, 0x01, 0x05, 0x36, - 0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff }; - - const u8_t arp_resp[] = { - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* DEST */ - 0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, /* SRC */ - 0x08, 0x06, /* Type: ARP */ - 0x00, 0x01, /* HW: Ethernet */ - 0x08, 0x00, /* PROTO: IP */ - 0x06, /* HW size */ - 0x04, /* PROTO size */ - 0x00, 0x02, /* OPCODE: Reply */ - - 0x12, 0x34, 0x56, 0x78, 0x9a, 0xab, /* Target MAC */ - 0x4f, 0x8a, 0x32, 0x01, /* Target IP */ - - 0x00, 0x23, 0xc1, 0x00, 0x06, 0x50, /* src mac */ - 0x4f, 0x8a, 0x33, 0x05, /* src ip */ - - /* Padding follows.. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }; - - ip4_addr_t addr; - ip4_addr_t netmask; - ip4_addr_t gw; - int i; - u32_t xid; - LWIP_UNUSED_ARG(_i); - - tcase = TEST_LWIP_DHCP_RELAY; - setdebug(0); - - IP4_ADDR(&addr, 0, 0, 0, 0); - IP4_ADDR(&netmask, 0, 0, 0, 0); - IP4_ADDR(&gw, 0, 0, 0, 0); - - netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); - netif_set_up(&net_test); - - dhcp_start(&net_test); - - fail_unless(txpacket == 1); /* DHCP discover sent */ - - /* IP addresses should be zero */ - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - - fail_unless(txpacket == 1); /* Nothing more sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); - memcpy(&relay_offer[46], &xid, 4); /* insert correct transaction id */ - send_pkt(&net_test, relay_offer, sizeof(relay_offer)); - - /* request sent? */ - fail_unless(txpacket == 2, "txpkt = %d, should be 2", txpacket); - xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ - memcpy(&relay_ack1[46], &xid, 4); /* insert transaction id */ - send_pkt(&net_test, relay_ack1, sizeof(relay_ack1)); - - for (i = 0; i < 25; i++) { - tick_lwip(); - } - fail_unless(txpacket == 5, "txpkt should be 5, is %d", txpacket); /* ARP requests sent */ - - /* Interface up */ - fail_unless(netif_is_up(&net_test)); - - /* Now it should have taken the IP */ - IP4_ADDR(&addr, 79, 138, 51, 5); - IP4_ADDR(&netmask, 255, 255, 254, 0); - IP4_ADDR(&gw, 79, 138, 50, 1); - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - - fail_unless(txpacket == 5, "txpacket = %d", txpacket); - - for (i = 0; i < 108000 - 25; i++) { - tick_lwip(); - } - - fail_unless(netif_is_up(&net_test)); - fail_unless(txpacket == 6, "txpacket = %d", txpacket); - - /* We need to send arp response here.. */ - - send_pkt(&net_test, arp_resp, sizeof(arp_resp)); - - fail_unless(txpacket == 7, "txpacket = %d", txpacket); - fail_unless(netif_is_up(&net_test)); - - xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ - memcpy(&relay_ack2[46], &xid, 4); /* insert transaction id */ - send_pkt(&net_test, relay_ack2, sizeof(relay_ack2)); - - for (i = 0; i < 100000; i++) { - tick_lwip(); - } - - fail_unless(txpacket == 7, "txpacket = %d", txpacket); - - netif_remove(&net_test); - -} -END_TEST - -START_TEST(test_dhcp_nak_no_endmarker) -{ - ip4_addr_t addr; - ip4_addr_t netmask; - ip4_addr_t gw; - - u8_t dhcp_nack_no_endmarker[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x54, 0x75, - 0xd0, 0x26, 0xd0, 0x0d, 0x08, 0x00, 0x45, 0x00, - 0x01, 0x15, 0x38, 0x86, 0x00, 0x00, 0xff, 0x11, - 0xc0, 0xa8, 0xc0, 0xa8, 0x01, 0x01, 0xff, 0xff, - 0xff, 0xff, 0x00, 0x43, 0x00, 0x44, 0x01, 0x01, - 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x7a, 0xcb, - 0xba, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, - 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, - 0x53, 0x63, 0x35, 0x01, 0x06, 0x36, 0x04, 0xc0, - 0xa8, 0x01, 0x01, 0x31, 0xef, 0xad, 0x72, 0x31, - 0x43, 0x4e, 0x44, 0x30, 0x32, 0x35, 0x30, 0x43, - 0x52, 0x47, 0x44, 0x38, 0x35, 0x36, 0x3c, 0x08, - 0x4d, 0x53, 0x46, 0x54, 0x20, 0x35, 0x2e, 0x30, - 0x37, 0x0d, 0x01, 0x0f, 0x03, 0x06, 0x2c, 0x2e, - 0x2f, 0x1f, 0x21, 0x79, 0xf9, 0x2b, 0xfc, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x71, - 0xf3, 0x5b, 0xe2, 0x71, 0x2e, 0x01, 0x08, 0x03, - 0x04, 0xc0, 0xa8, 0x01, 0x01, 0xff, 0xeb, 0x1e, - 0x44, 0xec, 0xeb, 0x1e, 0x30, 0x37, 0x0c, 0x01, - 0x0f, 0x03, 0x06, 0x2c, 0x2e, 0x2f, 0x1f, 0x21, - 0x79, 0xf9, 0x2b, 0xff, 0x25, 0xc0, 0x09, 0xd6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - u32_t xid; - LWIP_UNUSED_ARG(_i); - - tcase = TEST_LWIP_DHCP_NAK_NO_ENDMARKER; - setdebug(0); - - IP4_ADDR(&addr, 0, 0, 0, 0); - IP4_ADDR(&netmask, 0, 0, 0, 0); - IP4_ADDR(&gw, 0, 0, 0, 0); - - netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); - netif_set_up(&net_test); - - dhcp_start(&net_test); - - fail_unless(txpacket == 1); /* DHCP discover sent */ - xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ - memcpy(&dhcp_offer[46], &xid, 4); - send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); - - /* IP addresses should be zero */ - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - - fail_unless(txpacket == 1); /* Nothing more sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); - memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */ - send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); - - fail_unless(netif_dhcp_data(&net_test)->state == DHCP_STATE_REQUESTING); - - fail_unless(txpacket == 2); /* No more sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ - memcpy(&dhcp_nack_no_endmarker[46], &xid, 4); /* insert transaction id */ - send_pkt(&net_test, dhcp_nack_no_endmarker, sizeof(dhcp_nack_no_endmarker)); - - /* NAK should put us in another state for a while, no other way detecting it */ - fail_unless(netif_dhcp_data(&net_test)->state != DHCP_STATE_REQUESTING); - - netif_remove(&net_test); -} -END_TEST - -START_TEST(test_dhcp_invalid_overload) -{ - u8_t dhcp_offer_invalid_overload[] = { - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */ - 0x00, 0x0F, 0xEE, 0x30, 0xAB, 0x22, /* From Remote host */ - 0x08, 0x00, /* Protocol: IP */ - 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */ - 0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */ - - 0x02, /* Type == Boot reply */ - 0x01, 0x06, /* Hw Ethernet, 6 bytes addrlen */ - 0x00, /* 0 hops */ - 0xAA, 0xAA, 0xAA, 0xAA, /* Transaction id, will be overwritten */ - 0x00, 0x00, /* 0 seconds elapsed */ - 0x00, 0x00, /* Flags (unicast) */ - 0x00, 0x00, 0x00, 0x00, /* Client ip */ - 0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */ - 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server ip */ - 0x00, 0x00, 0x00, 0x00, /* relay agent */ - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MAC addr + padding */ - - /* Empty server name */ - 0x34, 0x01, 0x02, 0xff, /* Overload: SNAME + END */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* Empty boot file name */ - 0x34, 0x01, 0x01, 0xff, /* Overload FILE + END */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - 0x63, 0x82, 0x53, 0x63, /* Magic cookie */ - 0x35, 0x01, 0x02, /* Message type: Offer */ - 0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Server identifier (IP) */ - 0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */ - 0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */ - 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Subnet mask */ - 0x34, 0x01, 0x03, /* Overload: FILE + SNAME */ - 0xff, /* End option */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */ - }; - ip4_addr_t addr; - ip4_addr_t netmask; - ip4_addr_t gw; - u32_t xid; - LWIP_UNUSED_ARG(_i); - - tcase = TEST_LWIP_DHCP_INVALID_OVERLOAD; - setdebug(0); - - IP4_ADDR(&addr, 0, 0, 0, 0); - IP4_ADDR(&netmask, 0, 0, 0, 0); - IP4_ADDR(&gw, 0, 0, 0, 0); - - netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); - netif_set_up(&net_test); - - dhcp_start(&net_test); - - fail_unless(txpacket == 1); /* DHCP discover sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); - memcpy(&dhcp_offer_invalid_overload[46], &xid, 4); /* insert correct transaction id */ - dhcp_offer_invalid_overload[311] = 3; - send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload)); - /* IP addresses should be zero */ - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - fail_unless(txpacket == 1); /* Nothing more sent */ - - dhcp_offer_invalid_overload[311] = 2; - send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload)); - /* IP addresses should be zero */ - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - fail_unless(txpacket == 1); /* Nothing more sent */ - - dhcp_offer_invalid_overload[311] = 1; - send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload)); - /* IP addresses should be zero */ - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - fail_unless(txpacket == 1); /* Nothing more sent */ - - dhcp_offer_invalid_overload[311] = 0; - send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer)); - - fail_unless(netif_dhcp_data(&net_test)->state == DHCP_STATE_REQUESTING); - - fail_unless(txpacket == 2); /* No more sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ - - netif_remove(&net_test); -} -END_TEST - -/** Create the suite including all tests for this module */ -Suite * -dhcp_suite(void) -{ - testfunc tests[] = { - TESTFUNC(test_dhcp), - TESTFUNC(test_dhcp_nak), - TESTFUNC(test_dhcp_relayed), - TESTFUNC(test_dhcp_nak_no_endmarker), - TESTFUNC(test_dhcp_invalid_overload) - }; - return create_suite("DHCP", tests, sizeof(tests)/sizeof(testfunc), dhcp_setup, dhcp_teardown); -} diff --git a/ext/lwip/test/unit/dhcp/test_dhcp.h b/ext/lwip/test/unit/dhcp/test_dhcp.h deleted file mode 100755 index aed8fc1..0000000 --- a/ext/lwip/test/unit/dhcp/test_dhcp.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_DHCP_H -#define LWIP_HDR_TEST_DHCP_H - -#include "../lwip_check.h" - -Suite* dhcp_suite(void); - -#endif diff --git a/ext/lwip/test/unit/etharp/test_etharp.c b/ext/lwip/test/unit/etharp/test_etharp.c deleted file mode 100755 index f2edc72..0000000 --- a/ext/lwip/test/unit/etharp/test_etharp.c +++ /dev/null @@ -1,269 +0,0 @@ -#include "test_etharp.h" - -#include "lwip/udp.h" -#include "lwip/etharp.h" -#include "netif/ethernet.h" -#include "lwip/stats.h" - -#if !LWIP_STATS || !UDP_STATS || !MEMP_STATS || !ETHARP_STATS -#error "This tests needs UDP-, MEMP- and ETHARP-statistics enabled" -#endif -#if !ETHARP_SUPPORT_STATIC_ENTRIES -#error "This test needs ETHARP_SUPPORT_STATIC_ENTRIES enabled" -#endif - -static struct netif test_netif; -static ip4_addr_t test_ipaddr, test_netmask, test_gw; -struct eth_addr test_ethaddr = {{1,1,1,1,1,1}}; -struct eth_addr test_ethaddr2 = {{1,1,1,1,1,2}}; -struct eth_addr test_ethaddr3 = {{1,1,1,1,1,3}}; -struct eth_addr test_ethaddr4 = {{1,1,1,1,1,4}}; -static int linkoutput_ctr; - -/* Helper functions */ -static void -etharp_remove_all(void) -{ - int i; - /* call etharp_tmr often enough to have all entries cleaned */ - for(i = 0; i < 0xff; i++) { - etharp_tmr(); - } -} - -static err_t -default_netif_linkoutput(struct netif *netif, struct pbuf *p) -{ - fail_unless(netif == &test_netif); - fail_unless(p != NULL); - linkoutput_ctr++; - return ERR_OK; -} - -static err_t -default_netif_init(struct netif *netif) -{ - fail_unless(netif != NULL); - netif->linkoutput = default_netif_linkoutput; - netif->output = etharp_output; - netif->mtu = 1500; - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; - netif->hwaddr_len = ETHARP_HWADDR_LEN; - return ERR_OK; -} - -static void -default_netif_add(void) -{ - IP4_ADDR(&test_gw, 192,168,0,1); - IP4_ADDR(&test_ipaddr, 192,168,0,1); - IP4_ADDR(&test_netmask, 255,255,0,0); - - fail_unless(netif_default == NULL); - netif_set_default(netif_add(&test_netif, &test_ipaddr, &test_netmask, - &test_gw, NULL, default_netif_init, NULL)); - netif_set_up(&test_netif); -} - -static void -default_netif_remove(void) -{ - fail_unless(netif_default == &test_netif); - netif_remove(&test_netif); -} - -static void -create_arp_response(ip4_addr_t *adr) -{ - int k; - struct eth_hdr *ethhdr; - struct etharp_hdr *etharphdr; - struct pbuf *p = pbuf_alloc(PBUF_RAW, sizeof(struct eth_hdr) + sizeof(struct etharp_hdr), PBUF_RAM); - if(p == NULL) { - FAIL_RET(); - } - ethhdr = (struct eth_hdr*)p->payload; - etharphdr = (struct etharp_hdr*)(ethhdr + 1); - - ethhdr->dest = test_ethaddr; - ethhdr->src = test_ethaddr2; - ethhdr->type = htons(ETHTYPE_ARP); - - etharphdr->hwtype = htons(/*HWTYPE_ETHERNET*/ 1); - etharphdr->proto = htons(ETHTYPE_IP); - etharphdr->hwlen = ETHARP_HWADDR_LEN; - etharphdr->protolen = sizeof(ip4_addr_t); - etharphdr->opcode = htons(ARP_REPLY); - - SMEMCPY(ðarphdr->sipaddr, adr, sizeof(ip4_addr_t)); - SMEMCPY(ðarphdr->dipaddr, &test_ipaddr, sizeof(ip4_addr_t)); - - k = 6; - while(k > 0) { - k--; - /* Write the ARP MAC-Addresses */ - etharphdr->shwaddr.addr[k] = test_ethaddr2.addr[k]; - etharphdr->dhwaddr.addr[k] = test_ethaddr.addr[k]; - /* Write the Ethernet MAC-Addresses */ - ethhdr->dest.addr[k] = test_ethaddr.addr[k]; - ethhdr->src.addr[k] = test_ethaddr2.addr[k]; - } - - ethernet_input(p, &test_netif); -} - -/* Setups/teardown functions */ - -static void -etharp_setup(void) -{ - etharp_remove_all(); - default_netif_add(); -} - -static void -etharp_teardown(void) -{ - etharp_remove_all(); - default_netif_remove(); -} - - -/* Test functions */ - -START_TEST(test_etharp_table) -{ -#if ETHARP_SUPPORT_STATIC_ENTRIES - err_t err; -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - s8_t idx; - const ip4_addr_t *unused_ipaddr; - struct eth_addr *unused_ethaddr; - struct udp_pcb* pcb; - LWIP_UNUSED_ARG(_i); - - if (netif_default != &test_netif) { - fail("This test needs a default netif"); - } - - linkoutput_ctr = 0; - - pcb = udp_new(); - fail_unless(pcb != NULL); - if (pcb != NULL) { - ip4_addr_t adrs[ARP_TABLE_SIZE + 2]; - int i; - for(i = 0; i < ARP_TABLE_SIZE + 2; i++) { - IP4_ADDR(&adrs[i], 192,168,0,i+2); - } - /* fill ARP-table with dynamic entries */ - for(i = 0; i < ARP_TABLE_SIZE; i++) { - struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 10, PBUF_RAM); - fail_unless(p != NULL); - if (p != NULL) { - err_t err2; - ip_addr_t dst; - ip_addr_copy_from_ip4(dst, adrs[i]); - err2 = udp_sendto(pcb, p, &dst, 123); - fail_unless(err2 == ERR_OK); - /* etharp request sent? */ - fail_unless(linkoutput_ctr == (2*i) + 1); - pbuf_free(p); - - /* create an ARP response */ - create_arp_response(&adrs[i]); - /* queued UDP packet sent? */ - fail_unless(linkoutput_ctr == (2*i) + 2); - - idx = etharp_find_addr(NULL, &adrs[i], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == i); - etharp_tmr(); - } - } - linkoutput_ctr = 0; -#if ETHARP_SUPPORT_STATIC_ENTRIES - /* create one static entry */ - err = etharp_add_static_entry(&adrs[ARP_TABLE_SIZE], &test_ethaddr3); - fail_unless(err == ERR_OK); - idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == 0); - fail_unless(linkoutput_ctr == 0); -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - - linkoutput_ctr = 0; - /* fill ARP-table with dynamic entries */ - for(i = 0; i < ARP_TABLE_SIZE; i++) { - struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 10, PBUF_RAM); - fail_unless(p != NULL); - if (p != NULL) { - err_t err2; - ip_addr_t dst; - ip_addr_copy_from_ip4(dst, adrs[i]); - err2 = udp_sendto(pcb, p, &dst, 123); - fail_unless(err2 == ERR_OK); - /* etharp request sent? */ - fail_unless(linkoutput_ctr == (2*i) + 1); - pbuf_free(p); - - /* create an ARP response */ - create_arp_response(&adrs[i]); - /* queued UDP packet sent? */ - fail_unless(linkoutput_ctr == (2*i) + 2); - - idx = etharp_find_addr(NULL, &adrs[i], &unused_ethaddr, &unused_ipaddr); - if (i < ARP_TABLE_SIZE - 1) { - fail_unless(idx == i+1); - } else { - /* the last entry must not overwrite the static entry! */ - fail_unless(idx == 1); - } - etharp_tmr(); - } - } -#if ETHARP_SUPPORT_STATIC_ENTRIES - /* create a second static entry */ - err = etharp_add_static_entry(&adrs[ARP_TABLE_SIZE+1], &test_ethaddr4); - fail_unless(err == ERR_OK); - idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == 0); - idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == 2); - /* and remove it again */ - err = etharp_remove_static_entry(&adrs[ARP_TABLE_SIZE+1]); - fail_unless(err == ERR_OK); - idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == 0); - idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == -1); -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - - /* check that static entries don't time out */ - etharp_remove_all(); - idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == 0); - -#if ETHARP_SUPPORT_STATIC_ENTRIES - /* remove the first static entry */ - err = etharp_remove_static_entry(&adrs[ARP_TABLE_SIZE]); - fail_unless(err == ERR_OK); - idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == -1); - idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == -1); -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - - udp_remove(pcb); - } -} -END_TEST - - -/** Create the suite including all tests for this module */ -Suite * -etharp_suite(void) -{ - testfunc tests[] = { - TESTFUNC(test_etharp_table) - }; - return create_suite("ETHARP", tests, sizeof(tests)/sizeof(testfunc), etharp_setup, etharp_teardown); -} diff --git a/ext/lwip/test/unit/etharp/test_etharp.h b/ext/lwip/test/unit/etharp/test_etharp.h deleted file mode 100755 index df343da..0000000 --- a/ext/lwip/test/unit/etharp/test_etharp.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_ETHARP_H -#define LWIP_HDR_TEST_ETHARP_H - -#include "../lwip_check.h" - -Suite* etharp_suite(void); - -#endif diff --git a/ext/lwip/test/unit/ip4/test_ip4.c b/ext/lwip/test/unit/ip4/test_ip4.c deleted file mode 100755 index 383acf3..0000000 --- a/ext/lwip/test/unit/ip4/test_ip4.c +++ /dev/null @@ -1,154 +0,0 @@ -#include "test_ip4.h" - -#include "lwip/ip4.h" -#include "lwip/inet_chksum.h" -#include "lwip/stats.h" -#include "lwip/prot/ip.h" -#include "lwip/prot/ip4.h" - -#if !LWIP_IPV4 || !IP_REASSEMBLY || !MIB2_STATS || !IPFRAG_STATS -#error "This tests needs LWIP_IPV4, IP_REASSEMBLY; MIB2- and IPFRAG-statistics enabled" -#endif - -/* Helper functions */ -static void -create_ip4_input_fragment(u16_t ip_id, u16_t start, u16_t len, int last) -{ - struct pbuf *p; - struct netif *input_netif = netif_list; /* just use any netif */ - fail_unless((start & 7) == 0); - fail_unless(((len & 7) == 0) || last); - fail_unless(input_netif != NULL); - - p = pbuf_alloc(PBUF_RAW, len + sizeof(struct ip_hdr), PBUF_RAM); - fail_unless(p != NULL); - if (p != NULL) { - err_t err; - struct ip_hdr *iphdr = (struct ip_hdr *)p->payload; - IPH_VHL_SET(iphdr, 4, sizeof(struct ip_hdr) / 4); - IPH_TOS_SET(iphdr, 0); - IPH_LEN_SET(iphdr, lwip_htons(p->tot_len)); - IPH_ID_SET(iphdr, lwip_htons(ip_id)); - if (last) { - IPH_OFFSET_SET(iphdr, lwip_htons(start / 8)); - } else { - IPH_OFFSET_SET(iphdr, lwip_htons((start / 8) | IP_MF)); - } - IPH_TTL_SET(iphdr, 5); - IPH_PROTO_SET(iphdr, IP_PROTO_UDP); - IPH_CHKSUM_SET(iphdr, 0); - ip4_addr_copy(iphdr->src, *netif_ip4_addr(input_netif)); - iphdr->src.addr = lwip_htonl(lwip_htonl(iphdr->src.addr) + 1); - ip4_addr_copy(iphdr->dest, *netif_ip4_addr(input_netif)); - IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, sizeof(struct ip_hdr))); - - err = ip4_input(p, input_netif); - if (err != ERR_OK) { - pbuf_free(p); - } - fail_unless(err == ERR_OK); - } -} - -/* Setups/teardown functions */ - -static void -ip4_setup(void) -{ -} - -static void -ip4_teardown(void) -{ - if (netif_list->loop_first != NULL) { - pbuf_free(netif_list->loop_first); - netif_list->loop_first = NULL; - } - netif_list->loop_last = NULL; -} - - -/* Test functions */ - -START_TEST(test_ip4_reass) -{ - const u16_t ip_id = 128; - LWIP_UNUSED_ARG(_i); - - memset(&lwip_stats.mib2, 0, sizeof(lwip_stats.mib2)); - - create_ip4_input_fragment(ip_id, 8*200, 200, 1); - fail_unless(lwip_stats.ip_frag.recv == 1); - fail_unless(lwip_stats.ip_frag.err == 0); - fail_unless(lwip_stats.ip_frag.memerr == 0); - fail_unless(lwip_stats.ip_frag.drop == 0); - fail_unless(lwip_stats.mib2.ipreasmoks == 0); - - create_ip4_input_fragment(ip_id, 0*200, 200, 0); - fail_unless(lwip_stats.ip_frag.recv == 2); - fail_unless(lwip_stats.ip_frag.err == 0); - fail_unless(lwip_stats.ip_frag.memerr == 0); - fail_unless(lwip_stats.ip_frag.drop == 0); - fail_unless(lwip_stats.mib2.ipreasmoks == 0); - - create_ip4_input_fragment(ip_id, 1*200, 200, 0); - fail_unless(lwip_stats.ip_frag.recv == 3); - fail_unless(lwip_stats.ip_frag.err == 0); - fail_unless(lwip_stats.ip_frag.memerr == 0); - fail_unless(lwip_stats.ip_frag.drop == 0); - fail_unless(lwip_stats.mib2.ipreasmoks == 0); - - create_ip4_input_fragment(ip_id, 2*200, 200, 0); - fail_unless(lwip_stats.ip_frag.recv == 4); - fail_unless(lwip_stats.ip_frag.err == 0); - fail_unless(lwip_stats.ip_frag.memerr == 0); - fail_unless(lwip_stats.ip_frag.drop == 0); - fail_unless(lwip_stats.mib2.ipreasmoks == 0); - - create_ip4_input_fragment(ip_id, 3*200, 200, 0); - fail_unless(lwip_stats.ip_frag.recv == 5); - fail_unless(lwip_stats.ip_frag.err == 0); - fail_unless(lwip_stats.ip_frag.memerr == 0); - fail_unless(lwip_stats.ip_frag.drop == 0); - fail_unless(lwip_stats.mib2.ipreasmoks == 0); - - create_ip4_input_fragment(ip_id, 4*200, 200, 0); - fail_unless(lwip_stats.ip_frag.recv == 6); - fail_unless(lwip_stats.ip_frag.err == 0); - fail_unless(lwip_stats.ip_frag.memerr == 0); - fail_unless(lwip_stats.ip_frag.drop == 0); - fail_unless(lwip_stats.mib2.ipreasmoks == 0); - - create_ip4_input_fragment(ip_id, 7*200, 200, 0); - fail_unless(lwip_stats.ip_frag.recv == 7); - fail_unless(lwip_stats.ip_frag.err == 0); - fail_unless(lwip_stats.ip_frag.memerr == 0); - fail_unless(lwip_stats.ip_frag.drop == 0); - fail_unless(lwip_stats.mib2.ipreasmoks == 0); - - create_ip4_input_fragment(ip_id, 6*200, 200, 0); - fail_unless(lwip_stats.ip_frag.recv == 8); - fail_unless(lwip_stats.ip_frag.err == 0); - fail_unless(lwip_stats.ip_frag.memerr == 0); - fail_unless(lwip_stats.ip_frag.drop == 0); - fail_unless(lwip_stats.mib2.ipreasmoks == 0); - - create_ip4_input_fragment(ip_id, 5*200, 200, 0); - fail_unless(lwip_stats.ip_frag.recv == 9); - fail_unless(lwip_stats.ip_frag.err == 0); - fail_unless(lwip_stats.ip_frag.memerr == 0); - fail_unless(lwip_stats.ip_frag.drop == 0); - fail_unless(lwip_stats.mib2.ipreasmoks == 1); -} -END_TEST - - -/** Create the suite including all tests for this module */ -Suite * -ip4_suite(void) -{ - testfunc tests[] = { - TESTFUNC(test_ip4_reass), - }; - return create_suite("IPv4", tests, sizeof(tests)/sizeof(testfunc), ip4_setup, ip4_teardown); -} diff --git a/ext/lwip/test/unit/ip4/test_ip4.h b/ext/lwip/test/unit/ip4/test_ip4.h deleted file mode 100755 index 71922b3..0000000 --- a/ext/lwip/test/unit/ip4/test_ip4.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_IP4_H -#define LWIP_HDR_TEST_IP4_H - -#include "../lwip_check.h" - -Suite* ip4_suite(void); - -#endif diff --git a/ext/lwip/test/unit/lwip_check.h b/ext/lwip/test/unit/lwip_check.h deleted file mode 100755 index 78876ef..0000000 --- a/ext/lwip/test/unit/lwip_check.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef LWIP_HDR_LWIP_CHECK_H -#define LWIP_HDR_LWIP_CHECK_H - -/* Common header file for lwIP unit tests using the check framework */ - -#include -#include -#include - -#define FAIL_RET() do { fail(); return; } while(0) -#define EXPECT(x) fail_unless(x) -#define EXPECT_RET(x) do { fail_unless(x); if(!(x)) { return; }} while(0) -#define EXPECT_RETX(x, y) do { fail_unless(x); if(!(x)) { return y; }} while(0) -#define EXPECT_RETNULL(x) EXPECT_RETX(x, NULL) - -typedef struct { - TFun func; - const char *name; -} testfunc; - -#define TESTFUNC(x) {(x), "" # x "" } - -/* Modified function from check.h, supplying function name */ -#define tcase_add_named_test(tc,tf) \ - _tcase_add_test((tc),(tf).func,(tf).name,0, 0, 0, 1) - -/** typedef for a function returning a test suite */ -typedef Suite* (suite_getter_fn)(void); - -/** Create a test suite */ -Suite* create_suite(const char* name, testfunc *tests, size_t num_tests, SFun setup, SFun teardown); - -#ifdef LWIP_UNITTESTS_LIB -int lwip_unittests_run(void) -#endif - -#endif /* LWIP_HDR_LWIP_CHECK_H */ diff --git a/ext/lwip/test/unit/lwip_unittests.c b/ext/lwip/test/unit/lwip_unittests.c deleted file mode 100755 index 5563015..0000000 --- a/ext/lwip/test/unit/lwip_unittests.c +++ /dev/null @@ -1,72 +0,0 @@ -#include "lwip_check.h" - -#include "ip4/test_ip4.h" -#include "udp/test_udp.h" -#include "tcp/test_tcp.h" -#include "tcp/test_tcp_oos.h" -#include "core/test_mem.h" -#include "core/test_pbuf.h" -#include "etharp/test_etharp.h" -#include "dhcp/test_dhcp.h" -#include "mdns/test_mdns.h" - -#include "lwip/init.h" - -Suite* create_suite(const char* name, testfunc *tests, size_t num_tests, SFun setup, SFun teardown) -{ - size_t i; - Suite *s = suite_create(name); - - for(i = 0; i < num_tests; i++) { - TCase *tc_core = tcase_create(name); - if ((setup != NULL) || (teardown != NULL)) { - tcase_add_checked_fixture(tc_core, setup, teardown); - } - tcase_add_named_test(tc_core, tests[i]); - suite_add_tcase(s, tc_core); - } - return s; -} - -#ifdef LWIP_UNITTESTS_LIB -int lwip_unittests_run(void) -#else -int main(void) -#endif -{ - int number_failed; - SRunner *sr; - size_t i; - suite_getter_fn* suites[] = { - ip4_suite, - udp_suite, - tcp_suite, - tcp_oos_suite, - mem_suite, - pbuf_suite, - etharp_suite, - dhcp_suite, - mdns_suite - }; - size_t num = sizeof(suites)/sizeof(void*); - LWIP_ASSERT("No suites defined", num > 0); - - lwip_init(); - - sr = srunner_create((suites[0])()); - for(i = 1; i < num; i++) { - srunner_add_suite(sr, ((suite_getter_fn*)suites[i])()); - } - -#ifdef LWIP_UNITTESTS_NOFORK - srunner_set_fork_status(sr, CK_NOFORK); -#endif -#ifdef LWIP_UNITTESTS_FORK - srunner_set_fork_status(sr, CK_FORK); -#endif - - srunner_run_all(sr, CK_NORMAL); - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/ext/lwip/test/unit/mdns/test_mdns.c b/ext/lwip/test/unit/mdns/test_mdns.c deleted file mode 100755 index 900b9dd..0000000 --- a/ext/lwip/test/unit/mdns/test_mdns.c +++ /dev/null @@ -1,915 +0,0 @@ -/* - * Copyright (c) 2015 Verisure Innovation AB - * All rights reserved. - * - * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Ekman - * - */ - -#include "test_mdns.h" - -#include "lwip/pbuf.h" -#include "lwip/apps/mdns.h" -#include "lwip/apps/mdns_priv.h" - -START_TEST(readname_basic) -{ - static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0, &domain); - pbuf_free(p); - fail_unless(offset == sizeof(data)); - fail_unless(domain.length == sizeof(data)); - fail_if(memcmp(&domain.name, data, sizeof(data))); -} -END_TEST - -START_TEST(readname_anydata) -{ - static const u8_t data[] = { 0x05, 0x00, 0xFF, 0x08, 0xc0, 0x0f, 0x04, 0x7f, 0x80, 0x82, 0x88, 0x00 }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0, &domain); - pbuf_free(p); - fail_unless(offset == sizeof(data)); - fail_unless(domain.length == sizeof(data)); - fail_if(memcmp(&domain.name, data, sizeof(data))); -} -END_TEST - -START_TEST(readname_short_buf) -{ - static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a' }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0, &domain); - pbuf_free(p); - fail_unless(offset == MDNS_READNAME_ERROR); -} -END_TEST - -START_TEST(readname_long_label) -{ - static const u8_t data[] = { - 0x05, 'm', 'u', 'l', 't', 'i', - 0x52, 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', - 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', - 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', - 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', - 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', - 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0, &domain); - pbuf_free(p); - fail_unless(offset == MDNS_READNAME_ERROR); -} -END_TEST - -START_TEST(readname_overflow) -{ - static const u8_t data[] = { - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0, &domain); - pbuf_free(p); - fail_unless(offset == MDNS_READNAME_ERROR); -} -END_TEST - -START_TEST(readname_jump_earlier) -{ - static const u8_t data[] = { - /* Some padding needed, not supported to jump to bytes containing dns header */ - /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 10 */ 0x0f, 0x0e, 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xab, - /* 20 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x0c - }; - static const u8_t fullname[] = { - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 20, &domain); - pbuf_free(p); - fail_unless(offset == sizeof(data)); - fail_unless(domain.length == sizeof(fullname)); - - fail_if(memcmp(&domain.name, fullname, sizeof(fullname))); -} -END_TEST - -START_TEST(readname_jump_earlier_jump) -{ - static const u8_t data[] = { - /* Some padding needed, not supported to jump to bytes containing dns header */ - /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x0a, 0xf2, - /* 0x10 */ 0x04, 'c', 'a', 's', 't', 0x00, 0xc0, 0x10, - /* 0x18 */ 0x05, 'm', 'u', 'l', 't', 'i', 0xc0, 0x16 - }; - static const u8_t fullname[] = { - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0x18, &domain); - pbuf_free(p); - fail_unless(offset == sizeof(data)); - fail_unless(domain.length == sizeof(fullname)); - - fail_if(memcmp(&domain.name, fullname, sizeof(fullname))); -} -END_TEST - -START_TEST(readname_jump_maxdepth) -{ - static const u8_t data[] = { - /* Some padding needed, not supported to jump to bytes containing dns header */ - /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x0a, 0xf2, - /* 0x10 */ 0x04, 'n', 'a', 'm', 'e', 0xc0, 0x27, 0x03, - /* 0x18 */ 0x03, 'd', 'n', 's', 0xc0, 0x10, 0xc0, 0x10, - /* 0x20 */ 0x04, 'd', 'e', 'e', 'p', 0xc0, 0x18, 0x00, - /* 0x28 */ 0x04, 'c', 'a', 's', 't', 0xc0, 0x20, 0xb0, - /* 0x30 */ 0x05, 'm', 'u', 'l', 't', 'i', 0xc0, 0x28 - }; - static const u8_t fullname[] = { - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x04, 'd', 'e', 'e', 'p', 0x03, 'd', 'n', 's', - 0x04, 'n', 'a', 'm', 'e', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0x30, &domain); - pbuf_free(p); - fail_unless(offset == sizeof(data)); - fail_unless(domain.length == sizeof(fullname)); - - fail_if(memcmp(&domain.name, fullname, sizeof(fullname))); -} -END_TEST - -START_TEST(readname_jump_later) -{ - static const u8_t data[] = { - /* 0x00 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x10, 0x00, 0x01, 0x40, - /* 0x10 */ 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xab - }; - static const u8_t fullname[] = { - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0, &domain); - pbuf_free(p); - fail_unless(offset == 13); - fail_unless(domain.length == sizeof(fullname)); - - fail_if(memcmp(&domain.name, fullname, sizeof(fullname))); -} -END_TEST - -START_TEST(readname_half_jump) -{ - static const u8_t data[] = { - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0, &domain); - pbuf_free(p); - fail_unless(offset == MDNS_READNAME_ERROR); -} -END_TEST - -START_TEST(readname_jump_toolong) -{ - static const u8_t data[] = { - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc2, 0x10, 0x00, 0x01, 0x40 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0, &domain); - pbuf_free(p); - fail_unless(offset == MDNS_READNAME_ERROR); -} -END_TEST - -START_TEST(readname_jump_loop_label) -{ - static const u8_t data[] = { - /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 10 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x10 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 10, &domain); - pbuf_free(p); - fail_unless(offset == MDNS_READNAME_ERROR); -} -END_TEST - -START_TEST(readname_jump_loop_jump) -{ - static const u8_t data[] = { - /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 10 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x15 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 10, &domain); - pbuf_free(p); - fail_unless(offset == MDNS_READNAME_ERROR); -} -END_TEST - -START_TEST(add_label_basic) -{ - static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 }; - struct mdns_domain domain; - err_t res; - LWIP_UNUSED_ARG(_i); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "cast", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - fail_unless(domain.length == sizeof(data)); - fail_if(memcmp(&domain.name, data, sizeof(data))); -} -END_TEST - -START_TEST(add_label_long_label) -{ - static const char *toolong = "abcdefghijklmnopqrstuvwxyz0123456789-abcdefghijklmnopqrstuvwxyz0123456789-abcdefghijklmnopqrstuvwxyz0123456789-"; - struct mdns_domain domain; - err_t res; - LWIP_UNUSED_ARG(_i); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, toolong, (u8_t)strlen(toolong)); - fail_unless(res == ERR_VAL); -} -END_TEST - -START_TEST(add_label_full) -{ - static const char *label = "0123456789abcdef0123456789abcdef"; - struct mdns_domain domain; - err_t res; - LWIP_UNUSED_ARG(_i); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 33); - res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 66); - res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 99); - res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 132); - res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 165); - res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 198); - res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 231); - res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); - fail_unless(res == ERR_VAL); - fail_unless(domain.length == 231); - res = mdns_domain_add_label(&domain, label, 25); - fail_unless(res == ERR_VAL); - fail_unless(domain.length == 231); - res = mdns_domain_add_label(&domain, label, 24); - fail_unless(res == ERR_VAL); - fail_unless(domain.length == 231); - res = mdns_domain_add_label(&domain, label, 23); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 255); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 256); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_VAL); - fail_unless(domain.length == 256); -} -END_TEST - -START_TEST(domain_eq_basic) -{ - static const u8_t data[] = { - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 - }; - struct mdns_domain domain1, domain2; - err_t res; - LWIP_UNUSED_ARG(_i); - - memset(&domain1, 0, sizeof(domain1)); - res = mdns_domain_add_label(&domain1, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, "cast", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, NULL, 0); - fail_unless(res == ERR_OK); - fail_unless(domain1.length == sizeof(data)); - - memset(&domain2, 0, sizeof(domain2)); - res = mdns_domain_add_label(&domain2, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, "cast", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, NULL, 0); - fail_unless(res == ERR_OK); - - fail_unless(mdns_domain_eq(&domain1, &domain2)); -} -END_TEST - -START_TEST(domain_eq_diff) -{ - struct mdns_domain domain1, domain2; - err_t res; - LWIP_UNUSED_ARG(_i); - - memset(&domain1, 0, sizeof(domain1)); - res = mdns_domain_add_label(&domain1, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, "base", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, NULL, 0); - fail_unless(res == ERR_OK); - - memset(&domain2, 0, sizeof(domain2)); - res = mdns_domain_add_label(&domain2, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, "cast", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, NULL, 0); - fail_unless(res == ERR_OK); - - fail_if(mdns_domain_eq(&domain1, &domain2)); -} -END_TEST - -START_TEST(domain_eq_case) -{ - struct mdns_domain domain1, domain2; - err_t res; - LWIP_UNUSED_ARG(_i); - - memset(&domain1, 0, sizeof(domain1)); - res = mdns_domain_add_label(&domain1, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, "cast", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, NULL, 0); - fail_unless(res == ERR_OK); - - memset(&domain2, 0, sizeof(domain2)); - res = mdns_domain_add_label(&domain2, "MulTI", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, "casT", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, NULL, 0); - fail_unless(res == ERR_OK); - - fail_unless(mdns_domain_eq(&domain1, &domain2)); -} -END_TEST - -START_TEST(domain_eq_anydata) -{ - static const u8_t data1[] = { 0x05, 0xcc, 0xdc, 0x00, 0xa0 }; - static const u8_t data2[] = { 0x7f, 0x8c, 0x01, 0xff, 0xcf }; - struct mdns_domain domain1, domain2; - err_t res; - LWIP_UNUSED_ARG(_i); - - memset(&domain1, 0, sizeof(domain1)); - res = mdns_domain_add_label(&domain1, (const char*)data1, sizeof(data1)); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, "cast", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, (const char*)data2, sizeof(data2)); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, NULL, 0); - fail_unless(res == ERR_OK); - - memset(&domain2, 0, sizeof(domain2)); - res = mdns_domain_add_label(&domain2, (const char*)data1, sizeof(data1)); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, "casT", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, (const char*)data2, sizeof(data2)); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, NULL, 0); - fail_unless(res == ERR_OK); - - fail_unless(mdns_domain_eq(&domain1, &domain2)); -} -END_TEST - -START_TEST(domain_eq_length) -{ - struct mdns_domain domain1, domain2; - err_t res; - LWIP_UNUSED_ARG(_i); - - memset(&domain1, 0, sizeof(domain1)); - memset(domain1.name, 0xAA, sizeof(MDNS_DOMAIN_MAXLEN)); - res = mdns_domain_add_label(&domain1, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, "cast", 4); - fail_unless(res == ERR_OK); - - memset(&domain2, 0, sizeof(domain2)); - memset(domain2.name, 0xBB, sizeof(MDNS_DOMAIN_MAXLEN)); - res = mdns_domain_add_label(&domain2, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, "cast", 4); - fail_unless(res == ERR_OK); - - fail_unless(mdns_domain_eq(&domain1, &domain2)); -} -END_TEST - -START_TEST(compress_full_match) -{ - static const u8_t data[] = { - 0x00, 0x00, - 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - u16_t length; - err_t res; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "foobar", 6); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "local", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - - offset = 2; - length = mdns_compress_domain(p, &offset, &domain); - /* Write 0 bytes, then a jump to addr 2 */ - fail_unless(length == 0); - fail_unless(offset == 2); - - pbuf_free(p); -} -END_TEST - -START_TEST(compress_full_match_subset) -{ - static const u8_t data[] = { - 0x00, 0x00, - 0x02, 'g', 'o', 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - u16_t length; - err_t res; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "foobar", 6); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "local", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - - offset = 2; - length = mdns_compress_domain(p, &offset, &domain); - /* Write 0 bytes, then a jump to addr 5 */ - fail_unless(length == 0); - fail_unless(offset == 5); - - pbuf_free(p); -} -END_TEST - -START_TEST(compress_full_match_jump) -{ - static const u8_t data[] = { - /* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - /* 0x10 */ 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xc0, 0x00, 0x02, 0x00, - /* 0x20 */ 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0xc0, 0x15 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - u16_t length; - err_t res; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "foobar", 6); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "local", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - - offset = 0x20; - length = mdns_compress_domain(p, &offset, &domain); - /* Write 0 bytes, then a jump to addr 0x20 */ - fail_unless(length == 0); - fail_unless(offset == 0x20); - - pbuf_free(p); -} -END_TEST - -START_TEST(compress_no_match) -{ - static const u8_t data[] = { - 0x00, 0x00, - 0x04, 'l', 'w', 'i', 'p', 0x05, 'w', 'i', 'k', 'i', 'a', 0x03, 'c', 'o', 'm', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - u16_t length; - err_t res; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "foobar", 6); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "local", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - - offset = 2; - length = mdns_compress_domain(p, &offset, &domain); - /* Write all bytes, no jump */ - fail_unless(length == domain.length); - - pbuf_free(p); -} -END_TEST - -START_TEST(compress_2nd_label) -{ - static const u8_t data[] = { - 0x00, 0x00, - 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - u16_t length; - err_t res; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "lwip", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "local", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - - offset = 2; - length = mdns_compress_domain(p, &offset, &domain); - /* Write 5 bytes, then a jump to addr 9 */ - fail_unless(length == 5); - fail_unless(offset == 9); - - pbuf_free(p); -} -END_TEST - -START_TEST(compress_2nd_label_short) -{ - static const u8_t data[] = { - 0x00, 0x00, - 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - u16_t length; - err_t res; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "foobar", 6); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "local", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - - offset = 2; - length = mdns_compress_domain(p, &offset, &domain); - /* Write 5 bytes, then a jump to addr 7 */ - fail_unless(length == 7); - fail_unless(offset == 7); - - pbuf_free(p); -} -END_TEST - -START_TEST(compress_jump_to_jump) -{ - static const u8_t data[] = { - /* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - /* 0x10 */ 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xc0, 0x00, 0x02, 0x00, - /* 0x20 */ 0x07, 'b', 'a', 'n', 'a', 'n', 'a', 's', 0xc0, 0x15 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - u16_t length; - err_t res; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "foobar", 6); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "local", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - - offset = 0x20; - length = mdns_compress_domain(p, &offset, &domain); - /* Dont compress if jump would be to a jump */ - fail_unless(length == domain.length); - - offset = 0x10; - length = mdns_compress_domain(p, &offset, &domain); - /* Write 7 bytes, then a jump to addr 0x15 */ - fail_unless(length == 7); - fail_unless(offset == 0x15); - - pbuf_free(p); -} -END_TEST - -START_TEST(compress_long_match) -{ - static const u8_t data[] = { - 0x00, 0x00, - 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x03, 'c', 'o', 'm', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - u16_t length; - err_t res; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "foobar", 6); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "local", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - - offset = 2; - length = mdns_compress_domain(p, &offset, &domain); - fail_unless(length == domain.length); - - pbuf_free(p); -} -END_TEST - -Suite* mdns_suite(void) -{ - testfunc tests[] = { - TESTFUNC(readname_basic), - TESTFUNC(readname_anydata), - TESTFUNC(readname_short_buf), - TESTFUNC(readname_long_label), - TESTFUNC(readname_overflow), - TESTFUNC(readname_jump_earlier), - TESTFUNC(readname_jump_earlier_jump), - TESTFUNC(readname_jump_maxdepth), - TESTFUNC(readname_jump_later), - TESTFUNC(readname_half_jump), - TESTFUNC(readname_jump_toolong), - TESTFUNC(readname_jump_loop_label), - TESTFUNC(readname_jump_loop_jump), - - TESTFUNC(add_label_basic), - TESTFUNC(add_label_long_label), - TESTFUNC(add_label_full), - - TESTFUNC(domain_eq_basic), - TESTFUNC(domain_eq_diff), - TESTFUNC(domain_eq_case), - TESTFUNC(domain_eq_anydata), - TESTFUNC(domain_eq_length), - - TESTFUNC(compress_full_match), - TESTFUNC(compress_full_match_subset), - TESTFUNC(compress_full_match_jump), - TESTFUNC(compress_no_match), - TESTFUNC(compress_2nd_label), - TESTFUNC(compress_2nd_label_short), - TESTFUNC(compress_jump_to_jump), - TESTFUNC(compress_long_match), - }; - return create_suite("MDNS", tests, sizeof(tests)/sizeof(testfunc), NULL, NULL); -} diff --git a/ext/lwip/test/unit/mdns/test_mdns.h b/ext/lwip/test/unit/mdns/test_mdns.h deleted file mode 100755 index 758c279..0000000 --- a/ext/lwip/test/unit/mdns/test_mdns.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_MDNS_H__ -#define LWIP_HDR_TEST_MDNS_H__ - -#include "../lwip_check.h" - -Suite* mdns_suite(void); - -#endif diff --git a/ext/lwip/test/unit/tcp/tcp_helper.c b/ext/lwip/test/unit/tcp/tcp_helper.c deleted file mode 100755 index 7a0e818..0000000 --- a/ext/lwip/test/unit/tcp/tcp_helper.c +++ /dev/null @@ -1,314 +0,0 @@ -#include "tcp_helper.h" - -#include "lwip/priv/tcp_priv.h" -#include "lwip/stats.h" -#include "lwip/pbuf.h" -#include "lwip/inet_chksum.h" -#include "lwip/ip_addr.h" - -#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS -#error "This tests needs TCP- and MEMP-statistics enabled" -#endif - -/** Remove all pcbs on the given list. */ -static void -tcp_remove(struct tcp_pcb* pcb_list) -{ - struct tcp_pcb *pcb = pcb_list; - struct tcp_pcb *pcb2; - - while(pcb != NULL) { - pcb2 = pcb; - pcb = pcb->next; - tcp_abort(pcb2); - } -} - -/** Remove all pcbs on listen-, active- and time-wait-list (bound- isn't exported). */ -void -tcp_remove_all(void) -{ - tcp_remove(tcp_listen_pcbs.pcbs); - tcp_remove(tcp_active_pcbs); - tcp_remove(tcp_tw_pcbs); - fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); - fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB_LISTEN) == 0); - fail_unless(MEMP_STATS_GET(used, MEMP_TCP_SEG) == 0); - fail_unless(MEMP_STATS_GET(used, MEMP_PBUF_POOL) == 0); -} - -/** Create a TCP segment usable for passing to tcp_input */ -static struct pbuf* -tcp_create_segment_wnd(ip_addr_t* src_ip, ip_addr_t* dst_ip, - u16_t src_port, u16_t dst_port, void* data, size_t data_len, - u32_t seqno, u32_t ackno, u8_t headerflags, u16_t wnd) -{ - struct pbuf *p, *q; - struct ip_hdr* iphdr; - struct tcp_hdr* tcphdr; - u16_t pbuf_len = (u16_t)(sizeof(struct ip_hdr) + sizeof(struct tcp_hdr) + data_len); - LWIP_ASSERT("data_len too big", data_len <= 0xFFFF); - - p = pbuf_alloc(PBUF_RAW, pbuf_len, PBUF_POOL); - EXPECT_RETNULL(p != NULL); - /* first pbuf must be big enough to hold the headers */ - EXPECT_RETNULL(p->len >= (sizeof(struct ip_hdr) + sizeof(struct tcp_hdr))); - if (data_len > 0) { - /* first pbuf must be big enough to hold at least 1 data byte, too */ - EXPECT_RETNULL(p->len > (sizeof(struct ip_hdr) + sizeof(struct tcp_hdr))); - } - - for(q = p; q != NULL; q = q->next) { - memset(q->payload, 0, q->len); - } - - iphdr = (struct ip_hdr*)p->payload; - /* fill IP header */ - iphdr->dest.addr = ip_2_ip4(dst_ip)->addr; - iphdr->src.addr = ip_2_ip4(src_ip)->addr; - IPH_VHL_SET(iphdr, 4, IP_HLEN / 4); - IPH_TOS_SET(iphdr, 0); - IPH_LEN_SET(iphdr, htons(p->tot_len)); - IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); - - /* let p point to TCP header */ - pbuf_header(p, -(s16_t)sizeof(struct ip_hdr)); - - tcphdr = (struct tcp_hdr*)p->payload; - tcphdr->src = htons(src_port); - tcphdr->dest = htons(dst_port); - tcphdr->seqno = htonl(seqno); - tcphdr->ackno = htonl(ackno); - TCPH_HDRLEN_SET(tcphdr, sizeof(struct tcp_hdr)/4); - TCPH_FLAGS_SET(tcphdr, headerflags); - tcphdr->wnd = htons(wnd); - - if (data_len > 0) { - /* let p point to TCP data */ - pbuf_header(p, -(s16_t)sizeof(struct tcp_hdr)); - /* copy data */ - pbuf_take(p, data, (u16_t)data_len); - /* let p point to TCP header again */ - pbuf_header(p, sizeof(struct tcp_hdr)); - } - - /* calculate checksum */ - - tcphdr->chksum = ip_chksum_pseudo(p, - IP_PROTO_TCP, p->tot_len, src_ip, dst_ip); - - pbuf_header(p, sizeof(struct ip_hdr)); - - return p; -} - -/** Create a TCP segment usable for passing to tcp_input */ -struct pbuf* -tcp_create_segment(ip_addr_t* src_ip, ip_addr_t* dst_ip, - u16_t src_port, u16_t dst_port, void* data, size_t data_len, - u32_t seqno, u32_t ackno, u8_t headerflags) -{ - return tcp_create_segment_wnd(src_ip, dst_ip, src_port, dst_port, data, - data_len, seqno, ackno, headerflags, TCP_WND); -} - -/** Create a TCP segment usable for passing to tcp_input - * - IP-addresses, ports, seqno and ackno are taken from pcb - * - seqno and ackno can be altered with an offset - */ -struct pbuf* -tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len, u32_t seqno_offset, - u32_t ackno_offset, u8_t headerflags) -{ - return tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port, - data, data_len, pcb->rcv_nxt + seqno_offset, pcb->lastack + ackno_offset, headerflags); -} - -/** Create a TCP segment usable for passing to tcp_input - * - IP-addresses, ports, seqno and ackno are taken from pcb - * - seqno and ackno can be altered with an offset - * - TCP window can be adjusted - */ -struct pbuf* tcp_create_rx_segment_wnd(struct tcp_pcb* pcb, void* data, size_t data_len, - u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags, u16_t wnd) -{ - return tcp_create_segment_wnd(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port, - data, data_len, pcb->rcv_nxt + seqno_offset, pcb->lastack + ackno_offset, headerflags, wnd); -} - -/** Safely bring a tcp_pcb into the requested state */ -void -tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, ip_addr_t* local_ip, - ip_addr_t* remote_ip, u16_t local_port, u16_t remote_port) -{ - u32_t iss; - - /* @todo: are these all states? */ - /* @todo: remove from previous list */ - pcb->state = state; - - iss = tcp_next_iss(pcb); - pcb->snd_wl2 = iss; - pcb->snd_nxt = iss; - pcb->lastack = iss; - pcb->snd_lbb = iss; - - if (state == ESTABLISHED) { - TCP_REG(&tcp_active_pcbs, pcb); - ip_addr_copy(pcb->local_ip, *local_ip); - pcb->local_port = local_port; - ip_addr_copy(pcb->remote_ip, *remote_ip); - pcb->remote_port = remote_port; - } else if(state == LISTEN) { - TCP_REG(&tcp_listen_pcbs.pcbs, pcb); - ip_addr_copy(pcb->local_ip, *local_ip); - pcb->local_port = local_port; - } else if(state == TIME_WAIT) { - TCP_REG(&tcp_tw_pcbs, pcb); - ip_addr_copy(pcb->local_ip, *local_ip); - pcb->local_port = local_port; - ip_addr_copy(pcb->remote_ip, *remote_ip); - pcb->remote_port = remote_port; - } else { - fail(); - } -} - -void -test_tcp_counters_err(void* arg, err_t err) -{ - struct test_tcp_counters* counters = (struct test_tcp_counters*)arg; - EXPECT_RET(arg != NULL); - counters->err_calls++; - counters->last_err = err; -} - -static void -test_tcp_counters_check_rxdata(struct test_tcp_counters* counters, struct pbuf* p) -{ - struct pbuf* q; - u32_t i, received; - if(counters->expected_data == NULL) { - /* no data to compare */ - return; - } - EXPECT_RET(counters->recved_bytes + p->tot_len <= counters->expected_data_len); - received = counters->recved_bytes; - for(q = p; q != NULL; q = q->next) { - char *data = (char*)q->payload; - for(i = 0; i < q->len; i++) { - EXPECT_RET(data[i] == counters->expected_data[received]); - received++; - } - } - EXPECT(received == counters->recved_bytes + p->tot_len); -} - -err_t -test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err) -{ - struct test_tcp_counters* counters = (struct test_tcp_counters*)arg; - EXPECT_RETX(arg != NULL, ERR_OK); - EXPECT_RETX(pcb != NULL, ERR_OK); - EXPECT_RETX(err == ERR_OK, ERR_OK); - - if (p != NULL) { - if (counters->close_calls == 0) { - counters->recv_calls++; - test_tcp_counters_check_rxdata(counters, p); - counters->recved_bytes += p->tot_len; - } else { - counters->recv_calls_after_close++; - counters->recved_bytes_after_close += p->tot_len; - } - pbuf_free(p); - } else { - counters->close_calls++; - } - EXPECT(counters->recv_calls_after_close == 0 && counters->recved_bytes_after_close == 0); - return ERR_OK; -} - -/** Allocate a pcb and set up the test_tcp_counters_* callbacks */ -struct tcp_pcb* -test_tcp_new_counters_pcb(struct test_tcp_counters* counters) -{ - struct tcp_pcb* pcb = tcp_new(); - if (pcb != NULL) { - /* set up args and callbacks */ - tcp_arg(pcb, counters); - tcp_recv(pcb, test_tcp_counters_recv); - tcp_err(pcb, test_tcp_counters_err); - pcb->snd_wnd = TCP_WND; - pcb->snd_wnd_max = TCP_WND; - } - return pcb; -} - -/** Calls tcp_input() after adjusting current_iphdr_dest */ -void test_tcp_input(struct pbuf *p, struct netif *inp) -{ - struct ip_hdr *iphdr = (struct ip_hdr*)p->payload; - /* these lines are a hack, don't use them as an example :-) */ - ip_addr_copy_from_ip4(*ip_current_dest_addr(), iphdr->dest); - ip_addr_copy_from_ip4(*ip_current_src_addr(), iphdr->src); - ip_current_netif() = inp; - ip_data.current_ip4_header = iphdr; - - /* since adding IPv6, p->payload must point to tcp header, not ip header */ - pbuf_header(p, -(s16_t)sizeof(struct ip_hdr)); - - tcp_input(p, inp); - - ip_addr_set_zero(ip_current_dest_addr()); - ip_addr_set_zero(ip_current_src_addr()); - ip_current_netif() = NULL; - ip_data.current_ip4_header = NULL; -} - -static err_t test_tcp_netif_output(struct netif *netif, struct pbuf *p, - const ip4_addr_t *ipaddr) -{ - struct test_tcp_txcounters *txcounters = (struct test_tcp_txcounters*)netif->state; - LWIP_UNUSED_ARG(ipaddr); - if (txcounters != NULL) - { - txcounters->num_tx_calls++; - txcounters->num_tx_bytes += p->tot_len; - if (txcounters->copy_tx_packets) { - struct pbuf *p_copy = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); - err_t err; - EXPECT(p_copy != NULL); - err = pbuf_copy(p_copy, p); - EXPECT(err == ERR_OK); - if (txcounters->tx_packets == NULL) { - txcounters->tx_packets = p_copy; - } else { - pbuf_cat(txcounters->tx_packets, p_copy); - } - } - } - return ERR_OK; -} - -void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcounters, - ip_addr_t *ip_addr, ip_addr_t *netmask) -{ - struct netif *n; - memset(netif, 0, sizeof(struct netif)); - if (txcounters != NULL) { - memset(txcounters, 0, sizeof(struct test_tcp_txcounters)); - netif->state = txcounters; - } - netif->output = test_tcp_netif_output; - netif->flags |= NETIF_FLAG_UP | NETIF_FLAG_LINK_UP; - ip_addr_copy_from_ip4(netif->netmask, *ip_2_ip4(netmask)); - ip_addr_copy_from_ip4(netif->ip_addr, *ip_2_ip4(ip_addr)); - for (n = netif_list; n != NULL; n = n->next) { - if (n == netif) { - return; - } - } - netif->next = NULL; - netif_list = netif; -} diff --git a/ext/lwip/test/unit/tcp/tcp_helper.h b/ext/lwip/test/unit/tcp/tcp_helper.h deleted file mode 100755 index ea8fc72..0000000 --- a/ext/lwip/test/unit/tcp/tcp_helper.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef LWIP_HDR_TCP_HELPER_H -#define LWIP_HDR_TCP_HELPER_H - -#include "../lwip_check.h" -#include "lwip/arch.h" -#include "lwip/tcp.h" -#include "lwip/netif.h" - -/* counters used for test_tcp_counters_* callback functions */ -struct test_tcp_counters { - u32_t recv_calls; - u32_t recved_bytes; - u32_t recv_calls_after_close; - u32_t recved_bytes_after_close; - u32_t close_calls; - u32_t err_calls; - err_t last_err; - char* expected_data; - u32_t expected_data_len; -}; - -struct test_tcp_txcounters { - u32_t num_tx_calls; - u32_t num_tx_bytes; - u8_t copy_tx_packets; - struct pbuf *tx_packets; -}; - -/* Helper functions */ -void tcp_remove_all(void); - -struct pbuf* tcp_create_segment(ip_addr_t* src_ip, ip_addr_t* dst_ip, - u16_t src_port, u16_t dst_port, void* data, size_t data_len, - u32_t seqno, u32_t ackno, u8_t headerflags); -struct pbuf* tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len, - u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags); -struct pbuf* tcp_create_rx_segment_wnd(struct tcp_pcb* pcb, void* data, size_t data_len, - u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags, u16_t wnd); -void tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, ip_addr_t* local_ip, - ip_addr_t* remote_ip, u16_t local_port, u16_t remote_port); -void test_tcp_counters_err(void* arg, err_t err); -err_t test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err); - -struct tcp_pcb* test_tcp_new_counters_pcb(struct test_tcp_counters* counters); - -void test_tcp_input(struct pbuf *p, struct netif *inp); - -void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcounters, - ip_addr_t *ip_addr, ip_addr_t *netmask); - - -#endif diff --git a/ext/lwip/test/unit/tcp/test_tcp.c b/ext/lwip/test/unit/tcp/test_tcp.c deleted file mode 100755 index 25063aa..0000000 --- a/ext/lwip/test/unit/tcp/test_tcp.c +++ /dev/null @@ -1,744 +0,0 @@ -#include "test_tcp.h" - -#include "lwip/priv/tcp_priv.h" -#include "lwip/stats.h" -#include "tcp_helper.h" -#include "lwip/inet_chksum.h" - -#ifdef _MSC_VER -#pragma warning(disable: 4307) /* we explicitly wrap around TCP seqnos */ -#endif - -#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS -#error "This tests needs TCP- and MEMP-statistics enabled" -#endif -#if TCP_SND_BUF <= TCP_WND -#error "This tests needs TCP_SND_BUF to be > TCP_WND" -#endif - -static u8_t test_tcp_timer; - -/* our own version of tcp_tmr so we can reset fast/slow timer state */ -static void -test_tcp_tmr(void) -{ - tcp_fasttmr(); - if (++test_tcp_timer & 1) { - tcp_slowtmr(); - } -} - -/* Setups/teardown functions */ - -static void -tcp_setup(void) -{ - /* reset iss to default (6510) */ - tcp_ticks = 0; - tcp_ticks = 0 - (tcp_next_iss(NULL) - 6510); - tcp_next_iss(NULL); - tcp_ticks = 0; - - test_tcp_timer = 0; - tcp_remove_all(); -} - -static void -tcp_teardown(void) -{ - netif_list = NULL; - netif_default = NULL; - tcp_remove_all(); -} - - -/* Test functions */ - -/** Call tcp_new() and tcp_abort() and test memp stats */ -START_TEST(test_tcp_new_abort) -{ - struct tcp_pcb* pcb; - LWIP_UNUSED_ARG(_i); - - fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); - - pcb = tcp_new(); - fail_unless(pcb != NULL); - if (pcb != NULL) { - fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); - } -} -END_TEST - -/** Create an ESTABLISHED pcb and check if receive callback is called */ -START_TEST(test_tcp_recv_inseq) -{ - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf* p; - char data[] = {1, 2, 3, 4}; - ip_addr_t remote_ip, local_ip, netmask; - u16_t data_len; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - struct test_tcp_txcounters txcounters; - LWIP_UNUSED_ARG(_i); - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); - data_len = sizeof(data); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = data_len; - counters.expected_data = data; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - - /* create a segment */ - p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0); - EXPECT(p != NULL); - if (p != NULL) { - /* pass the segment to tcp_input */ - test_tcp_input(p, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 1); - EXPECT(counters.recved_bytes == data_len); - EXPECT(counters.err_calls == 0); - } - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} -END_TEST - -/** Check that we handle malformed tcp headers, and discard the pbuf(s) */ -START_TEST(test_tcp_malformed_header) -{ - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf* p; - char data[] = {1, 2, 3, 4}; - ip_addr_t remote_ip, local_ip, netmask; - u16_t data_len, chksum; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - struct test_tcp_txcounters txcounters; - struct tcp_hdr *hdr; - LWIP_UNUSED_ARG(_i); - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); - data_len = sizeof(data); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = data_len; - counters.expected_data = data; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - - /* create a segment */ - p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0); - - pbuf_header(p, -(s16_t)sizeof(struct ip_hdr)); - - hdr = (struct tcp_hdr *)p->payload; - TCPH_HDRLEN_FLAGS_SET(hdr, 15, 0x3d1); - - hdr->chksum = 0; - - chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, - &remote_ip, &local_ip); - - hdr->chksum = chksum; - - pbuf_header(p, sizeof(struct ip_hdr)); - - EXPECT(p != NULL); - EXPECT(p->next == NULL); - if (p != NULL) { - /* pass the segment to tcp_input */ - test_tcp_input(p, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - } - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} -END_TEST - - -/** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data. - * At the end, send more data. */ -START_TEST(test_tcp_fast_retx_recover) -{ - struct netif netif; - struct test_tcp_txcounters txcounters; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf* p; - char data1[] = { 1, 2, 3, 4}; - char data2[] = { 5, 6, 7, 8}; - char data3[] = { 9, 10, 11, 12}; - char data4[] = {13, 14, 15, 16}; - char data5[] = {17, 18, 19, 20}; - char data6[TCP_MSS] = {21, 22, 23, 24}; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - err_t err; - LWIP_UNUSED_ARG(_i); - - /* initialize local vars */ - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); - memset(&counters, 0, sizeof(counters)); - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->mss = TCP_MSS; - /* disable initial congestion window (we don't send a SYN here...) */ - pcb->cwnd = pcb->snd_wnd; - - /* send data1 */ - err = tcp_write(pcb, data1, sizeof(data1), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - EXPECT_RET(txcounters.num_tx_calls == 1); - EXPECT_RET(txcounters.num_tx_bytes == sizeof(data1) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr)); - memset(&txcounters, 0, sizeof(txcounters)); - /* "recv" ACK for data1 */ - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 4, TCP_ACK); - EXPECT_RET(p != NULL); - test_tcp_input(p, &netif); - EXPECT_RET(txcounters.num_tx_calls == 0); - EXPECT_RET(pcb->unacked == NULL); - /* send data2 */ - err = tcp_write(pcb, data2, sizeof(data2), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - EXPECT_RET(txcounters.num_tx_calls == 1); - EXPECT_RET(txcounters.num_tx_bytes == sizeof(data2) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr)); - memset(&txcounters, 0, sizeof(txcounters)); - /* duplicate ACK for data1 (data2 is lost) */ - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); - EXPECT_RET(p != NULL); - test_tcp_input(p, &netif); - EXPECT_RET(txcounters.num_tx_calls == 0); - EXPECT_RET(pcb->dupacks == 1); - /* send data3 */ - err = tcp_write(pcb, data3, sizeof(data3), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - /* nagle enabled, no tx calls */ - EXPECT_RET(txcounters.num_tx_calls == 0); - EXPECT_RET(txcounters.num_tx_bytes == 0); - memset(&txcounters, 0, sizeof(txcounters)); - /* 2nd duplicate ACK for data1 (data2 and data3 are lost) */ - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); - EXPECT_RET(p != NULL); - test_tcp_input(p, &netif); - EXPECT_RET(txcounters.num_tx_calls == 0); - EXPECT_RET(pcb->dupacks == 2); - /* queue data4, don't send it (unsent-oversize is != 0) */ - err = tcp_write(pcb, data4, sizeof(data4), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - /* 3nd duplicate ACK for data1 (data2 and data3 are lost) -> fast retransmission */ - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); - EXPECT_RET(p != NULL); - test_tcp_input(p, &netif); - /*EXPECT_RET(txcounters.num_tx_calls == 1);*/ - EXPECT_RET(pcb->dupacks == 3); - memset(&txcounters, 0, sizeof(txcounters)); - /* @todo: check expected data?*/ - - /* send data5, not output yet */ - err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - /*err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK);*/ - EXPECT_RET(txcounters.num_tx_calls == 0); - EXPECT_RET(txcounters.num_tx_bytes == 0); - memset(&txcounters, 0, sizeof(txcounters)); - { - int i = 0; - do - { - err = tcp_write(pcb, data6, TCP_MSS, TCP_WRITE_FLAG_COPY); - i++; - }while(err == ERR_OK); - EXPECT_RET(err != ERR_OK); - } - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - /*EXPECT_RET(txcounters.num_tx_calls == 0); - EXPECT_RET(txcounters.num_tx_bytes == 0);*/ - memset(&txcounters, 0, sizeof(txcounters)); - - /* send even more data */ - err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - /* ...and even more data */ - err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - /* ...and even more data */ - err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - /* ...and even more data */ - err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - - /* send ACKs for data2 and data3 */ - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 12, TCP_ACK); - EXPECT_RET(p != NULL); - test_tcp_input(p, &netif); - /*EXPECT_RET(txcounters.num_tx_calls == 0);*/ - - /* ...and even more data */ - err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - /* ...and even more data */ - err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - -#if 0 - /* create expected segment */ - p1 = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0); - EXPECT_RET(p != NULL); - if (p != NULL) { - /* pass the segment to tcp_input */ - test_tcp_input(p, &netif); - /* check if counters are as expected */ - EXPECT_RET(counters.close_calls == 0); - EXPECT_RET(counters.recv_calls == 1); - EXPECT_RET(counters.recved_bytes == data_len); - EXPECT_RET(counters.err_calls == 0); - } -#endif - /* make sure the pcb is freed */ - EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} -END_TEST - -static u8_t tx_data[TCP_WND*2]; - -static void -check_seqnos(struct tcp_seg *segs, int num_expected, u32_t *seqnos_expected) -{ - struct tcp_seg *s = segs; - int i; - for (i = 0; i < num_expected; i++, s = s->next) { - EXPECT_RET(s != NULL); - EXPECT(s->tcphdr->seqno == htonl(seqnos_expected[i])); - } - EXPECT(s == NULL); -} - -/** Send data with sequence numbers that wrap around the u32_t range. - * Then, provoke fast retransmission by duplicate ACKs and check that all - * segment lists are still properly sorted. */ -START_TEST(test_tcp_fast_rexmit_wraparound) -{ - struct netif netif; - struct test_tcp_txcounters txcounters; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf* p; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - err_t err; -#define SEQNO1 (0xFFFFFF00 - TCP_MSS) -#define ISS 6510 - u16_t i, sent_total = 0; - u32_t seqnos[] = { - SEQNO1, - SEQNO1 + (1 * TCP_MSS), - SEQNO1 + (2 * TCP_MSS), - SEQNO1 + (3 * TCP_MSS), - SEQNO1 + (4 * TCP_MSS), - SEQNO1 + (5 * TCP_MSS)}; - LWIP_UNUSED_ARG(_i); - - for (i = 0; i < sizeof(tx_data); i++) { - tx_data[i] = (u8_t)i; - } - - /* initialize local vars */ - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); - memset(&counters, 0, sizeof(counters)); - - /* create and initialize the pcb */ - tcp_ticks = SEQNO1 - ISS; - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->mss = TCP_MSS; - /* disable initial congestion window (we don't send a SYN here...) */ - pcb->cwnd = 2*TCP_MSS; - /* start in congestion advoidance */ - pcb->ssthresh = pcb->cwnd; - - /* send 6 mss-sized segments */ - for (i = 0; i < 6; i++) { - err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - sent_total += TCP_MSS; - } - check_seqnos(pcb->unsent, 6, seqnos); - EXPECT(pcb->unacked == NULL); - err = tcp_output(pcb); - EXPECT(txcounters.num_tx_calls == 2); - EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U)); - memset(&txcounters, 0, sizeof(txcounters)); - - check_seqnos(pcb->unacked, 2, seqnos); - check_seqnos(pcb->unsent, 4, &seqnos[2]); - - /* ACK the first segment */ - p = tcp_create_rx_segment(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK); - test_tcp_input(p, &netif); - /* ensure this didn't trigger a retransmission. Only one - segment should be transmitted because cwnd opened up by - TCP_MSS and a fraction since we are in congestion avoidance */ - EXPECT(txcounters.num_tx_calls == 1); - EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U); - memset(&txcounters, 0, sizeof(txcounters)); - check_seqnos(pcb->unacked, 2, &seqnos[1]); - check_seqnos(pcb->unsent, 3, &seqnos[3]); - - /* 3 dupacks */ - EXPECT(pcb->dupacks == 0); - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); - test_tcp_input(p, &netif); - EXPECT(txcounters.num_tx_calls == 0); - EXPECT(pcb->dupacks == 1); - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); - test_tcp_input(p, &netif); - EXPECT(txcounters.num_tx_calls == 0); - EXPECT(pcb->dupacks == 2); - /* 3rd dupack -> fast rexmit */ - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); - test_tcp_input(p, &netif); - EXPECT(pcb->dupacks == 3); - EXPECT(txcounters.num_tx_calls == 4); - memset(&txcounters, 0, sizeof(txcounters)); - EXPECT(pcb->unsent == NULL); - check_seqnos(pcb->unacked, 5, &seqnos[1]); - - /* make sure the pcb is freed */ - EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} -END_TEST - -/** Send data with sequence numbers that wrap around the u32_t range. - * Then, provoke RTO retransmission and check that all - * segment lists are still properly sorted. */ -START_TEST(test_tcp_rto_rexmit_wraparound) -{ - struct netif netif; - struct test_tcp_txcounters txcounters; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - err_t err; -#define SEQNO1 (0xFFFFFF00 - TCP_MSS) -#define ISS 6510 - u16_t i, sent_total = 0; - u32_t seqnos[] = { - SEQNO1, - SEQNO1 + (1 * TCP_MSS), - SEQNO1 + (2 * TCP_MSS), - SEQNO1 + (3 * TCP_MSS), - SEQNO1 + (4 * TCP_MSS), - SEQNO1 + (5 * TCP_MSS)}; - LWIP_UNUSED_ARG(_i); - - for (i = 0; i < sizeof(tx_data); i++) { - tx_data[i] = (u8_t)i; - } - - /* initialize local vars */ - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); - memset(&counters, 0, sizeof(counters)); - - /* create and initialize the pcb */ - tcp_ticks = 0; - tcp_ticks = 0 - tcp_next_iss(NULL); - tcp_ticks = SEQNO1 - tcp_next_iss(NULL); - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->mss = TCP_MSS; - /* disable initial congestion window (we don't send a SYN here...) */ - pcb->cwnd = 2*TCP_MSS; - - /* send 6 mss-sized segments */ - for (i = 0; i < 6; i++) { - err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - sent_total += TCP_MSS; - } - check_seqnos(pcb->unsent, 6, seqnos); - EXPECT(pcb->unacked == NULL); - err = tcp_output(pcb); - EXPECT(txcounters.num_tx_calls == 2); - EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U)); - memset(&txcounters, 0, sizeof(txcounters)); - - check_seqnos(pcb->unacked, 2, seqnos); - check_seqnos(pcb->unsent, 4, &seqnos[2]); - - /* call the tcp timer some times */ - for (i = 0; i < 10; i++) { - test_tcp_tmr(); - EXPECT(txcounters.num_tx_calls == 0); - } - /* 11th call to tcp_tmr: RTO rexmit fires */ - test_tcp_tmr(); - EXPECT(txcounters.num_tx_calls == 1); - check_seqnos(pcb->unacked, 1, seqnos); - check_seqnos(pcb->unsent, 5, &seqnos[1]); - - /* fake greater cwnd */ - pcb->cwnd = pcb->snd_wnd; - /* send more data */ - err = tcp_output(pcb); - EXPECT(err == ERR_OK); - /* check queues are sorted */ - EXPECT(pcb->unsent == NULL); - check_seqnos(pcb->unacked, 6, seqnos); - - /* make sure the pcb is freed */ - EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} -END_TEST - -/** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data. - * At the end, send more data. */ -static void test_tcp_tx_full_window_lost(u8_t zero_window_probe_from_unsent) -{ - struct netif netif; - struct test_tcp_txcounters txcounters; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf *p; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - err_t err; - u16_t sent_total, i; - u8_t expected = 0xFE; - - for (i = 0; i < sizeof(tx_data); i++) { - u8_t d = (u8_t)i; - if (d == 0xFE) { - d = 0xF0; - } - tx_data[i] = d; - } - if (zero_window_probe_from_unsent) { - tx_data[TCP_WND] = expected; - } else { - tx_data[0] = expected; - } - - /* initialize local vars */ - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); - memset(&counters, 0, sizeof(counters)); - memset(&txcounters, 0, sizeof(txcounters)); - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->mss = TCP_MSS; - /* disable initial congestion window (we don't send a SYN here...) */ - pcb->cwnd = pcb->snd_wnd; - - /* send a full window (minus 1 packets) of TCP data in MSS-sized chunks */ - sent_total = 0; - if ((TCP_WND - TCP_MSS) % TCP_MSS != 0) { - u16_t initial_data_len = (TCP_WND - TCP_MSS) % TCP_MSS; - err = tcp_write(pcb, &tx_data[sent_total], initial_data_len, TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - EXPECT(txcounters.num_tx_calls == 1); - EXPECT(txcounters.num_tx_bytes == initial_data_len + 40U); - memset(&txcounters, 0, sizeof(txcounters)); - sent_total += initial_data_len; - } - for (; sent_total < (TCP_WND - TCP_MSS); sent_total += TCP_MSS) { - err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - EXPECT(txcounters.num_tx_calls == 1); - EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U); - memset(&txcounters, 0, sizeof(txcounters)); - } - EXPECT(sent_total == (TCP_WND - TCP_MSS)); - - /* now ACK the packet before the first */ - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); - test_tcp_input(p, &netif); - /* ensure this didn't trigger a retransmission */ - EXPECT(txcounters.num_tx_calls == 0); - EXPECT(txcounters.num_tx_bytes == 0); - - EXPECT(pcb->persist_backoff == 0); - /* send the last packet, now a complete window has been sent */ - err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); - sent_total += TCP_MSS; - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - EXPECT(txcounters.num_tx_calls == 1); - EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U); - memset(&txcounters, 0, sizeof(txcounters)); - EXPECT(pcb->persist_backoff == 0); - - if (zero_window_probe_from_unsent) { - /* ACK all data but close the TX window */ - p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, TCP_WND, TCP_ACK, 0); - test_tcp_input(p, &netif); - /* ensure this didn't trigger any transmission */ - EXPECT(txcounters.num_tx_calls == 0); - EXPECT(txcounters.num_tx_bytes == 0); - EXPECT(pcb->persist_backoff == 1); - } - - /* send one byte more (out of window) -> persist timer starts */ - err = tcp_write(pcb, &tx_data[sent_total], 1, TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - EXPECT(txcounters.num_tx_calls == 0); - EXPECT(txcounters.num_tx_bytes == 0); - memset(&txcounters, 0, sizeof(txcounters)); - if (!zero_window_probe_from_unsent) { - /* no persist timer unless a zero window announcement has been received */ - EXPECT(pcb->persist_backoff == 0); - } else { - EXPECT(pcb->persist_backoff == 1); - - /* call tcp_timer some more times to let persist timer count up */ - for (i = 0; i < 4; i++) { - test_tcp_tmr(); - EXPECT(txcounters.num_tx_calls == 0); - EXPECT(txcounters.num_tx_bytes == 0); - } - - /* this should trigger the zero-window-probe */ - txcounters.copy_tx_packets = 1; - test_tcp_tmr(); - txcounters.copy_tx_packets = 0; - EXPECT(txcounters.num_tx_calls == 1); - EXPECT(txcounters.num_tx_bytes == 1 + 40U); - EXPECT(txcounters.tx_packets != NULL); - if (txcounters.tx_packets != NULL) { - u8_t sent; - u16_t ret; - ret = pbuf_copy_partial(txcounters.tx_packets, &sent, 1, 40U); - EXPECT(ret == 1); - EXPECT(sent == expected); - } - if (txcounters.tx_packets != NULL) { - pbuf_free(txcounters.tx_packets); - txcounters.tx_packets = NULL; - } - } - - /* make sure the pcb is freed */ - EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} - -START_TEST(test_tcp_tx_full_window_lost_from_unsent) -{ - LWIP_UNUSED_ARG(_i); - test_tcp_tx_full_window_lost(1); -} -END_TEST - -START_TEST(test_tcp_tx_full_window_lost_from_unacked) -{ - LWIP_UNUSED_ARG(_i); - test_tcp_tx_full_window_lost(0); -} -END_TEST - -/** Create the suite including all tests for this module */ -Suite * -tcp_suite(void) -{ - testfunc tests[] = { - TESTFUNC(test_tcp_new_abort), - TESTFUNC(test_tcp_recv_inseq), - TESTFUNC(test_tcp_malformed_header), - TESTFUNC(test_tcp_fast_retx_recover), - TESTFUNC(test_tcp_fast_rexmit_wraparound), - TESTFUNC(test_tcp_rto_rexmit_wraparound), - TESTFUNC(test_tcp_tx_full_window_lost_from_unacked), - TESTFUNC(test_tcp_tx_full_window_lost_from_unsent) - }; - return create_suite("TCP", tests, sizeof(tests)/sizeof(testfunc), tcp_setup, tcp_teardown); -} diff --git a/ext/lwip/test/unit/tcp/test_tcp.h b/ext/lwip/test/unit/tcp/test_tcp.h deleted file mode 100755 index 4258999..0000000 --- a/ext/lwip/test/unit/tcp/test_tcp.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_TCP_H -#define LWIP_HDR_TEST_TCP_H - -#include "../lwip_check.h" - -Suite *tcp_suite(void); - -#endif diff --git a/ext/lwip/test/unit/tcp/test_tcp_oos.c b/ext/lwip/test/unit/tcp/test_tcp_oos.c deleted file mode 100755 index e85ecc9..0000000 --- a/ext/lwip/test/unit/tcp/test_tcp_oos.c +++ /dev/null @@ -1,1049 +0,0 @@ -#include "test_tcp_oos.h" - -#include "lwip/priv/tcp_priv.h" -#include "lwip/stats.h" -#include "tcp_helper.h" - -#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS -#error "This tests needs TCP- and MEMP-statistics enabled" -#endif -#if !TCP_QUEUE_OOSEQ -#error "This tests needs TCP_QUEUE_OOSEQ enabled" -#endif - -/** CHECK_SEGMENTS_ON_OOSEQ: - * 1: check count, seqno and len of segments on pcb->ooseq (strict) - * 0: only check that bytes are received in correct order (less strict) */ -#define CHECK_SEGMENTS_ON_OOSEQ 1 - -#if CHECK_SEGMENTS_ON_OOSEQ -#define EXPECT_OOSEQ(x) EXPECT(x) -#else -#define EXPECT_OOSEQ(x) -#endif - -/* helper functions */ - -/** Get the numbers of segments on the ooseq list */ -static int tcp_oos_count(struct tcp_pcb* pcb) -{ - int num = 0; - struct tcp_seg* seg = pcb->ooseq; - while(seg != NULL) { - num++; - seg = seg->next; - } - return num; -} - -#if TCP_OOSEQ_MAX_PBUFS && (TCP_OOSEQ_MAX_PBUFS < ((TCP_WND / TCP_MSS) + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) -/** Get the numbers of pbufs on the ooseq list */ -static int tcp_oos_pbuf_count(struct tcp_pcb* pcb) -{ - int num = 0; - struct tcp_seg* seg = pcb->ooseq; - while(seg != NULL) { - num += pbuf_clen(seg->p); - seg = seg->next; - } - return num; -} -#endif - -/** Get the seqno of a segment (by index) on the ooseq list - * - * @param pcb the pcb to check for ooseq segments - * @param seg_index index of the segment on the ooseq list - * @return seqno of the segment - */ -static u32_t -tcp_oos_seg_seqno(struct tcp_pcb* pcb, int seg_index) -{ - int num = 0; - struct tcp_seg* seg = pcb->ooseq; - - /* then check the actual segment */ - while(seg != NULL) { - if(num == seg_index) { - return seg->tcphdr->seqno; - } - num++; - seg = seg->next; - } - fail(); - return 0; -} - -/** Get the tcplen (datalen + SYN/FIN) of a segment (by index) on the ooseq list - * - * @param pcb the pcb to check for ooseq segments - * @param seg_index index of the segment on the ooseq list - * @return tcplen of the segment - */ -static int -tcp_oos_seg_tcplen(struct tcp_pcb* pcb, int seg_index) -{ - int num = 0; - struct tcp_seg* seg = pcb->ooseq; - - /* then check the actual segment */ - while(seg != NULL) { - if(num == seg_index) { - return TCP_TCPLEN(seg); - } - num++; - seg = seg->next; - } - fail(); - return -1; -} - -/** Get the tcplen (datalen + SYN/FIN) of all segments on the ooseq list - * - * @param pcb the pcb to check for ooseq segments - * @return tcplen of all segment - */ -static int -tcp_oos_tcplen(struct tcp_pcb* pcb) -{ - int len = 0; - struct tcp_seg* seg = pcb->ooseq; - - /* then check the actual segment */ - while(seg != NULL) { - len += TCP_TCPLEN(seg); - seg = seg->next; - } - return len; -} - -/* Setup/teardown functions */ - -static void -tcp_oos_setup(void) -{ - tcp_remove_all(); -} - -static void -tcp_oos_teardown(void) -{ - tcp_remove_all(); - netif_list = NULL; - netif_default = NULL; -} - - - -/* Test functions */ - -/** create multiple segments and pass them to tcp_input in a wrong - * order to see if ooseq-caching works correctly - * FIN is received in out-of-sequence segments only */ -START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ) -{ - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf *p_8_9, *p_4_8, *p_4_10, *p_2_14, *p_fin, *pinseq; - char data[] = { - 1, 2, 3, 4, - 5, 6, 7, 8, - 9, 10, 11, 12, - 13, 14, 15, 16}; - ip_addr_t remote_ip, local_ip, netmask; - u16_t data_len; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - LWIP_UNUSED_ARG(_i); - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); - data_len = sizeof(data); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = data_len; - counters.expected_data = data; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - - /* create segments */ - /* pinseq is sent as last segment! */ - pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK); - /* p1: 8 bytes before FIN */ - /* seqno: 8..16 */ - p_8_9 = tcp_create_rx_segment(pcb, &data[8], 8, 8, 0, TCP_ACK|TCP_FIN); - /* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */ - /* seqno: 4..11 */ - p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK); - /* p3: same as p2 but 2 bytes longer */ - /* seqno: 4..13 */ - p_4_10 = tcp_create_rx_segment(pcb, &data[4], 10, 4, 0, TCP_ACK); - /* p4: 14 bytes before FIN, includes data from p1 and p2, plus partly from pinseq */ - /* seqno: 2..15 */ - p_2_14 = tcp_create_rx_segment(pcb, &data[2], 14, 2, 0, TCP_ACK); - /* FIN, seqno 16 */ - p_fin = tcp_create_rx_segment(pcb, NULL, 0,16, 0, TCP_ACK|TCP_FIN); - EXPECT(pinseq != NULL); - EXPECT(p_8_9 != NULL); - EXPECT(p_4_8 != NULL); - EXPECT(p_4_10 != NULL); - EXPECT(p_2_14 != NULL); - EXPECT(p_fin != NULL); - if ((pinseq != NULL) && (p_8_9 != NULL) && (p_4_8 != NULL) && (p_4_10 != NULL) && (p_2_14 != NULL) && (p_fin != NULL)) { - /* pass the segment to tcp_input */ - test_tcp_input(p_8_9, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 8); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 9); /* includes FIN */ - - /* pass the segment to tcp_input */ - test_tcp_input(p_4_8, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */ - - /* pass the segment to tcp_input */ - test_tcp_input(p_4_10, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* ooseq queue: unchanged */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */ - - /* pass the segment to tcp_input */ - test_tcp_input(p_2_14, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */ - - /* pass the segment to tcp_input */ - test_tcp_input(p_fin, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* ooseq queue: unchanged */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */ - - /* pass the segment to tcp_input */ - test_tcp_input(pinseq, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 1); - EXPECT(counters.recv_calls == 1); - EXPECT(counters.recved_bytes == data_len); - EXPECT(counters.err_calls == 0); - EXPECT(pcb->ooseq == NULL); - } - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} -END_TEST - - -/** create multiple segments and pass them to tcp_input in a wrong - * order to see if ooseq-caching works correctly - * FIN is received IN-SEQUENCE at the end */ -START_TEST(test_tcp_recv_ooseq_FIN_INSEQ) -{ - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf *p_1_2, *p_4_8, *p_3_11, *p_2_12, *p_15_1, *p_15_1a, *pinseq, *pinseqFIN; - char data[] = { - 1, 2, 3, 4, - 5, 6, 7, 8, - 9, 10, 11, 12, - 13, 14, 15, 16}; - ip_addr_t remote_ip, local_ip, netmask; - u16_t data_len; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - LWIP_UNUSED_ARG(_i); - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); - data_len = sizeof(data); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = data_len; - counters.expected_data = data; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - - /* create segments */ - /* p1: 7 bytes - 2 before FIN */ - /* seqno: 1..2 */ - p_1_2 = tcp_create_rx_segment(pcb, &data[1], 2, 1, 0, TCP_ACK); - /* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */ - /* seqno: 4..11 */ - p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK); - /* p3: same as p2 but 2 bytes longer and one byte more at the front */ - /* seqno: 3..13 */ - p_3_11 = tcp_create_rx_segment(pcb, &data[3], 11, 3, 0, TCP_ACK); - /* p4: 13 bytes - 2 before FIN - should be ignored as contained in p1 and p3 */ - /* seqno: 2..13 */ - p_2_12 = tcp_create_rx_segment(pcb, &data[2], 12, 2, 0, TCP_ACK); - /* pinseq is the first segment that is held back to create ooseq! */ - /* seqno: 0..3 */ - pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK); - /* p5: last byte before FIN */ - /* seqno: 15 */ - p_15_1 = tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK); - /* p6: same as p5, should be ignored */ - p_15_1a= tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK); - /* pinseqFIN: last 2 bytes plus FIN */ - /* only segment containing seqno 14 and FIN */ - pinseqFIN = tcp_create_rx_segment(pcb, &data[14], 2, 14, 0, TCP_ACK|TCP_FIN); - EXPECT(pinseq != NULL); - EXPECT(p_1_2 != NULL); - EXPECT(p_4_8 != NULL); - EXPECT(p_3_11 != NULL); - EXPECT(p_2_12 != NULL); - EXPECT(p_15_1 != NULL); - EXPECT(p_15_1a != NULL); - EXPECT(pinseqFIN != NULL); - if ((pinseq != NULL) && (p_1_2 != NULL) && (p_4_8 != NULL) && (p_3_11 != NULL) && (p_2_12 != NULL) - && (p_15_1 != NULL) && (p_15_1a != NULL) && (pinseqFIN != NULL)) { - /* pass the segment to tcp_input */ - test_tcp_input(p_1_2, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2); - - /* pass the segment to tcp_input */ - test_tcp_input(p_4_8, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 4); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 8); - - /* pass the segment to tcp_input */ - test_tcp_input(p_3_11, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2); - /* p_3_11 has removed p_4_8 from ooseq */ - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 3); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 11); - - /* pass the segment to tcp_input */ - test_tcp_input(p_2_12, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 2); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 12); - - /* pass the segment to tcp_input */ - test_tcp_input(pinseq, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 1); - EXPECT(counters.recved_bytes == 14); - EXPECT(counters.err_calls == 0); - EXPECT(pcb->ooseq == NULL); - - /* pass the segment to tcp_input */ - test_tcp_input(p_15_1, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 1); - EXPECT(counters.recved_bytes == 14); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1); - - /* pass the segment to tcp_input */ - test_tcp_input(p_15_1a, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 1); - EXPECT(counters.recved_bytes == 14); - EXPECT(counters.err_calls == 0); - /* check ooseq queue: unchanged */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1); - - /* pass the segment to tcp_input */ - test_tcp_input(pinseqFIN, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 1); - EXPECT(counters.recv_calls == 2); - EXPECT(counters.recved_bytes == data_len); - EXPECT(counters.err_calls == 0); - EXPECT(pcb->ooseq == NULL); - } - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} -END_TEST - -static char data_full_wnd[TCP_WND + TCP_MSS]; - -/** create multiple segments and pass them to tcp_input with the first segment missing - * to simulate overruning the rxwin with ooseq queueing enabled */ -START_TEST(test_tcp_recv_ooseq_overrun_rxwin) -{ -#if !TCP_OOSEQ_MAX_BYTES && !TCP_OOSEQ_MAX_PBUFS - int i, k; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf *pinseq, *p_ovr; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - int datalen = 0; - int datalen2; - - for(i = 0; i < (int)sizeof(data_full_wnd); i++) { - data_full_wnd[i] = (char)i; - } - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = TCP_WND; - counters.expected_data = data_full_wnd; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->rcv_nxt = 0x8000; - - /* create segments */ - /* pinseq is sent as last segment! */ - pinseq = tcp_create_rx_segment(pcb, &data_full_wnd[0], TCP_MSS, 0, 0, TCP_ACK); - - for(i = TCP_MSS, k = 0; i < TCP_WND; i += TCP_MSS, k++) { - int count, expected_datalen; - struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], - TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK); - EXPECT_RET(p != NULL); - /* pass the segment to tcp_input */ - test_tcp_input(p, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - count = tcp_oos_count(pcb); - EXPECT_OOSEQ(count == k+1); - datalen = tcp_oos_tcplen(pcb); - if (i + TCP_MSS < TCP_WND) { - expected_datalen = (k+1)*TCP_MSS; - } else { - expected_datalen = TCP_WND - TCP_MSS; - } - if (datalen != expected_datalen) { - EXPECT_OOSEQ(datalen == expected_datalen); - } - } - - /* pass in one more segment, cleary overrunning the rxwin */ - p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK); - EXPECT_RET(p_ovr != NULL); - /* pass the segment to tcp_input */ - test_tcp_input(p_ovr, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == k); - datalen2 = tcp_oos_tcplen(pcb); - EXPECT_OOSEQ(datalen == datalen2); - - /* now pass inseq */ - test_tcp_input(pinseq, &netif); - EXPECT(pcb->ooseq == NULL); - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -#endif /* !TCP_OOSEQ_MAX_BYTES && !TCP_OOSEQ_MAX_PBUFS */ - LWIP_UNUSED_ARG(_i); -} -END_TEST - -/** similar to above test, except seqno starts near the max rxwin */ -START_TEST(test_tcp_recv_ooseq_overrun_rxwin_edge) -{ -#if !TCP_OOSEQ_MAX_BYTES && !TCP_OOSEQ_MAX_PBUFS - int i, k; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf *pinseq, *p_ovr; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - int datalen = 0; - int datalen2; - - for(i = 0; i < (int)sizeof(data_full_wnd); i++) { - data_full_wnd[i] = (char)i; - } - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = TCP_WND; - counters.expected_data = data_full_wnd; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->rcv_nxt = 0xffffffff - (TCP_WND / 2); - - /* create segments */ - /* pinseq is sent as last segment! */ - pinseq = tcp_create_rx_segment(pcb, &data_full_wnd[0], TCP_MSS, 0, 0, TCP_ACK); - - for(i = TCP_MSS, k = 0; i < TCP_WND; i += TCP_MSS, k++) { - int count, expected_datalen; - struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], - TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK); - EXPECT_RET(p != NULL); - /* pass the segment to tcp_input */ - test_tcp_input(p, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - count = tcp_oos_count(pcb); - EXPECT_OOSEQ(count == k+1); - datalen = tcp_oos_tcplen(pcb); - if (i + TCP_MSS < TCP_WND) { - expected_datalen = (k+1)*TCP_MSS; - } else { - expected_datalen = TCP_WND - TCP_MSS; - } - if (datalen != expected_datalen) { - EXPECT_OOSEQ(datalen == expected_datalen); - } - } - - /* pass in one more segment, cleary overrunning the rxwin */ - p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK); - EXPECT_RET(p_ovr != NULL); - /* pass the segment to tcp_input */ - test_tcp_input(p_ovr, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == k); - datalen2 = tcp_oos_tcplen(pcb); - EXPECT_OOSEQ(datalen == datalen2); - - /* now pass inseq */ - test_tcp_input(pinseq, &netif); - EXPECT(pcb->ooseq == NULL); - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -#endif /* !TCP_OOSEQ_MAX_BYTES && !TCP_OOSEQ_MAX_PBUFS */ - LWIP_UNUSED_ARG(_i); -} -END_TEST - -START_TEST(test_tcp_recv_ooseq_max_bytes) -{ -#if TCP_OOSEQ_MAX_BYTES && (TCP_OOSEQ_MAX_BYTES < (TCP_WND + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) - int i, k; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf *p_ovr; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - int datalen = 0; - int datalen2; - - for(i = 0; i < sizeof(data_full_wnd); i++) { - data_full_wnd[i] = (char)i; - } - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = TCP_WND; - counters.expected_data = data_full_wnd; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->rcv_nxt = 0x8000; - - /* don't 'recv' the first segment (1 byte) so that all other segments will be ooseq */ - - /* create segments and 'recv' them */ - for(k = 1, i = 1; k < TCP_OOSEQ_MAX_BYTES; k += TCP_MSS, i++) { - int count; - struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[k], - TCP_MSS, k, 0, TCP_ACK); - EXPECT_RET(p != NULL); - EXPECT_RET(p->next == NULL); - /* pass the segment to tcp_input */ - test_tcp_input(p, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - count = tcp_oos_pbuf_count(pcb); - EXPECT_OOSEQ(count == i); - datalen = tcp_oos_tcplen(pcb); - EXPECT_OOSEQ(datalen == (i * TCP_MSS)); - } - - /* pass in one more segment, overrunning the limit */ - p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[k+1], 1, k+1, 0, TCP_ACK); - EXPECT_RET(p_ovr != NULL); - /* pass the segment to tcp_input */ - test_tcp_input(p_ovr, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue (ensure the new segment was not accepted) */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == (i-1)); - datalen2 = tcp_oos_tcplen(pcb); - EXPECT_OOSEQ(datalen2 == ((i-1) * TCP_MSS)); - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -#endif /* TCP_OOSEQ_MAX_BYTES && (TCP_OOSEQ_MAX_BYTES < (TCP_WND + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) */ - LWIP_UNUSED_ARG(_i); -} -END_TEST - -START_TEST(test_tcp_recv_ooseq_max_pbufs) -{ -#if TCP_OOSEQ_MAX_PBUFS && (TCP_OOSEQ_MAX_PBUFS < ((TCP_WND / TCP_MSS) + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) - int i; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf *p_ovr; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - int datalen = 0; - int datalen2; - - for(i = 0; i < sizeof(data_full_wnd); i++) { - data_full_wnd[i] = (char)i; - } - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = TCP_WND; - counters.expected_data = data_full_wnd; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->rcv_nxt = 0x8000; - - /* don't 'recv' the first segment (1 byte) so that all other segments will be ooseq */ - - /* create segments and 'recv' them */ - for(i = 1; i <= TCP_OOSEQ_MAX_PBUFS; i++) { - int count; - struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[i], - 1, i, 0, TCP_ACK); - EXPECT_RET(p != NULL); - EXPECT_RET(p->next == NULL); - /* pass the segment to tcp_input */ - test_tcp_input(p, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - count = tcp_oos_pbuf_count(pcb); - EXPECT_OOSEQ(count == i); - datalen = tcp_oos_tcplen(pcb); - EXPECT_OOSEQ(datalen == i); - } - - /* pass in one more segment, overrunning the limit */ - p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[i+1], 1, i+1, 0, TCP_ACK); - EXPECT_RET(p_ovr != NULL); - /* pass the segment to tcp_input */ - test_tcp_input(p_ovr, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue (ensure the new segment was not accepted) */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == (i-1)); - datalen2 = tcp_oos_tcplen(pcb); - EXPECT_OOSEQ(datalen2 == (i-1)); - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -#endif /* TCP_OOSEQ_MAX_PBUFS && (TCP_OOSEQ_MAX_BYTES < (TCP_WND + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) */ - LWIP_UNUSED_ARG(_i); -} -END_TEST - -static void -check_rx_counters(struct tcp_pcb *pcb, struct test_tcp_counters *counters, u32_t exp_close_calls, u32_t exp_rx_calls, - u32_t exp_rx_bytes, u32_t exp_err_calls, int exp_oos_count, int exp_oos_len) -{ - int oos_len; - EXPECT(counters->close_calls == exp_close_calls); - EXPECT(counters->recv_calls == exp_rx_calls); - EXPECT(counters->recved_bytes == exp_rx_bytes); - EXPECT(counters->err_calls == exp_err_calls); - /* check that pbuf is queued in ooseq */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == exp_oos_count); - oos_len = tcp_oos_tcplen(pcb); - EXPECT_OOSEQ(exp_oos_len == oos_len); -} - -/* this test uses 4 packets: - * - data (len=TCP_MSS) - * - FIN - * - data after FIN (len=1) (invalid) - * - 2nd FIN (invalid) - * - * the parameter 'delay_packet' is a bitmask that choses which on these packets is ooseq - */ -static void test_tcp_recv_ooseq_double_FINs(int delay_packet) -{ - int i, k; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf *p_normal_fin, *p_data_after_fin, *p, *p_2nd_fin_ooseq; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - u32_t exp_rx_calls = 0, exp_rx_bytes = 0, exp_close_calls = 0, exp_oos_pbufs = 0, exp_oos_tcplen = 0; - int first_dropped = 0xff; - - for(i = 0; i < (int)sizeof(data_full_wnd); i++) { - data_full_wnd[i] = (char)i; - } - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = TCP_WND; - counters.expected_data = data_full_wnd; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->rcv_nxt = 0x8000; - - /* create segments */ - p = tcp_create_rx_segment(pcb, &data_full_wnd[0], TCP_MSS, 0, 0, TCP_ACK); - p_normal_fin = tcp_create_rx_segment(pcb, NULL, 0, TCP_MSS, 0, TCP_ACK|TCP_FIN); - k = 1; - p_data_after_fin = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS+1], k, TCP_MSS+1, 0, TCP_ACK); - p_2nd_fin_ooseq = tcp_create_rx_segment(pcb, NULL, 0, TCP_MSS+1+k, 0, TCP_ACK|TCP_FIN); - - if(delay_packet & 1) { - /* drop normal data */ - first_dropped = 1; - } else { - /* send normal data */ - test_tcp_input(p, &netif); - exp_rx_calls++; - exp_rx_bytes += TCP_MSS; - } - /* check if counters are as expected */ - check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); - - if(delay_packet & 2) { - /* drop FIN */ - if(first_dropped > 2) { - first_dropped = 2; - } - } else { - /* send FIN */ - test_tcp_input(p_normal_fin, &netif); - if (first_dropped < 2) { - /* already dropped packets, this one is ooseq */ - exp_oos_pbufs++; - exp_oos_tcplen++; - } else { - /* inseq */ - exp_close_calls++; - } - } - /* check if counters are as expected */ - check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); - - if(delay_packet & 4) { - /* drop data-after-FIN */ - if(first_dropped > 3) { - first_dropped = 3; - } - } else { - /* send data-after-FIN */ - test_tcp_input(p_data_after_fin, &netif); - if (first_dropped < 3) { - /* already dropped packets, this one is ooseq */ - if (delay_packet & 2) { - /* correct FIN was ooseq */ - exp_oos_pbufs++; - exp_oos_tcplen += k; - } - } else { - /* inseq: no change */ - } - } - /* check if counters are as expected */ - check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); - - if(delay_packet & 8) { - /* drop 2nd-FIN */ - if(first_dropped > 4) { - first_dropped = 4; - } - } else { - /* send 2nd-FIN */ - test_tcp_input(p_2nd_fin_ooseq, &netif); - if (first_dropped < 3) { - /* already dropped packets, this one is ooseq */ - if (delay_packet & 2) { - /* correct FIN was ooseq */ - exp_oos_pbufs++; - exp_oos_tcplen++; - } - } else { - /* inseq: no change */ - } - } - /* check if counters are as expected */ - check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); - - if(delay_packet & 1) { - /* dropped normal data before */ - test_tcp_input(p, &netif); - exp_rx_calls++; - exp_rx_bytes += TCP_MSS; - if((delay_packet & 2) == 0) { - /* normal FIN was NOT delayed */ - exp_close_calls++; - exp_oos_pbufs = exp_oos_tcplen = 0; - } - } - /* check if counters are as expected */ - check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); - - if(delay_packet & 2) { - /* dropped normal FIN before */ - test_tcp_input(p_normal_fin, &netif); - exp_close_calls++; - exp_oos_pbufs = exp_oos_tcplen = 0; - } - /* check if counters are as expected */ - check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); - - if(delay_packet & 4) { - /* dropped data-after-FIN before */ - test_tcp_input(p_data_after_fin, &netif); - } - /* check if counters are as expected */ - check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); - - if(delay_packet & 8) { - /* dropped 2nd-FIN before */ - test_tcp_input(p_2nd_fin_ooseq, &netif); - } - /* check if counters are as expected */ - check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); - - /* check that ooseq data has been dumped */ - EXPECT(pcb->ooseq == NULL); - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} - -/** create multiple segments and pass them to tcp_input with the first segment missing - * to simulate overruning the rxwin with ooseq queueing enabled */ -#define FIN_TEST(name, num) \ - START_TEST(name) \ - { \ - LWIP_UNUSED_ARG(_i); \ - test_tcp_recv_ooseq_double_FINs(num); \ - } \ - END_TEST -FIN_TEST(test_tcp_recv_ooseq_double_FIN_0, 0) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_1, 1) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_2, 2) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_3, 3) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_4, 4) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_5, 5) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_6, 6) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_7, 7) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_8, 8) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_9, 9) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_10, 10) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_11, 11) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_12, 12) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_13, 13) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_14, 14) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_15, 15) - - -/** Create the suite including all tests for this module */ -Suite * -tcp_oos_suite(void) -{ - testfunc tests[] = { - TESTFUNC(test_tcp_recv_ooseq_FIN_OOSEQ), - TESTFUNC(test_tcp_recv_ooseq_FIN_INSEQ), - TESTFUNC(test_tcp_recv_ooseq_overrun_rxwin), - TESTFUNC(test_tcp_recv_ooseq_overrun_rxwin_edge), - TESTFUNC(test_tcp_recv_ooseq_max_bytes), - TESTFUNC(test_tcp_recv_ooseq_max_pbufs), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_0), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_1), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_2), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_3), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_4), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_5), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_6), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_7), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_8), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_9), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_10), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_11), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_12), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_13), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_14), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_15) - }; - return create_suite("TCP_OOS", tests, sizeof(tests)/sizeof(testfunc), tcp_oos_setup, tcp_oos_teardown); -} diff --git a/ext/lwip/test/unit/tcp/test_tcp_oos.h b/ext/lwip/test/unit/tcp/test_tcp_oos.h deleted file mode 100755 index 8b2e648..0000000 --- a/ext/lwip/test/unit/tcp/test_tcp_oos.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_TCP_OOS_H -#define LWIP_HDR_TEST_TCP_OOS_H - -#include "../lwip_check.h" - -Suite *tcp_oos_suite(void); - -#endif diff --git a/ext/lwip/test/unit/udp/test_udp.c b/ext/lwip/test/unit/udp/test_udp.c deleted file mode 100755 index 93ab922..0000000 --- a/ext/lwip/test/unit/udp/test_udp.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "test_udp.h" - -#include "lwip/udp.h" -#include "lwip/stats.h" - -#if !LWIP_STATS || !UDP_STATS || !MEMP_STATS -#error "This tests needs UDP- and MEMP-statistics enabled" -#endif - -/* Helper functions */ -static void -udp_remove_all(void) -{ - struct udp_pcb *pcb = udp_pcbs; - struct udp_pcb *pcb2; - - while(pcb != NULL) { - pcb2 = pcb; - pcb = pcb->next; - udp_remove(pcb2); - } - fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0); -} - -/* Setups/teardown functions */ - -static void -udp_setup(void) -{ - udp_remove_all(); -} - -static void -udp_teardown(void) -{ - udp_remove_all(); -} - - -/* Test functions */ - -START_TEST(test_udp_new_remove) -{ - struct udp_pcb* pcb; - LWIP_UNUSED_ARG(_i); - - fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0); - - pcb = udp_new(); - fail_unless(pcb != NULL); - if (pcb != NULL) { - fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 1); - udp_remove(pcb); - fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0); - } -} -END_TEST - - -/** Create the suite including all tests for this module */ -Suite * -udp_suite(void) -{ - testfunc tests[] = { - TESTFUNC(test_udp_new_remove), - }; - return create_suite("UDP", tests, sizeof(tests)/sizeof(testfunc), udp_setup, udp_teardown); -} diff --git a/ext/lwip/test/unit/udp/test_udp.h b/ext/lwip/test/unit/udp/test_udp.h deleted file mode 100755 index 02b7da5..0000000 --- a/ext/lwip/test/unit/udp/test_udp.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_UDP_H -#define LWIP_HDR_TEST_UDP_H - -#include "../lwip_check.h" - -Suite* udp_suite(void); - -#endif diff --git a/ext/picotcp/modules/pico_dns_client.h b/ext/picotcp/modules/pico_dns_client.h index dea234c..da3f313 100644 --- a/ext/picotcp/modules/pico_dns_client.h +++ b/ext/picotcp/modules/pico_dns_client.h @@ -37,9 +37,6 @@ #define PICO_DNS_RR_A_RDLENGTH 4 #define PICO_DNS_RR_AAAA_RDLENGTH 16 -#ifdef __cplusplus -extern "C" { -#endif int pico_dns_client_init(void); /* flag is PICO_DNS_NS_DEL or PICO_DNS_NS_ADD */ int pico_dns_client_nameserver(struct pico_ip4 *ns, uint8_t flag); @@ -49,8 +46,5 @@ int pico_dns_client_getname(const char *ip, void (*callback)(char *url, void *ar int pico_dns_client_getaddr6(const char *url, void (*callback)(char *, void *), void *arg); int pico_dns_client_getname6(const char *url, void (*callback)(char *, void *), void *arg); #endif -#ifdef __cplusplus -} -#endif #endif /* _INCLUDE_PICO_DNS_CLIENT */ diff --git a/include/Debug.hpp b/include/Debug.hpp index 2940811..b47562c 100644 --- a/include/Debug.hpp +++ b/include/Debug.hpp @@ -24,16 +24,28 @@ * of your own application. */ +/** + * @file + * + * Debug macros + */ + +#ifndef LIBZT_DEBUG_HPP +#define LIBZT_DEBUG_HPP + #include #include #include #include +#include + +#include "Platform.h" #define ZT_MSG_ERROR true // Errors #define ZT_MSG_INFO true // Information which is generally useful to any developer #define ZT_MSG_TEST true // For use in selftest #define ZT_MSG_TRANSFER true // RX/TX specific statements -#define ZT_MSG_EXTRA false // If nothing in your world makes sense +#define ZT_MSG_EXTRA true // If nothing in your world makes sense #define ZT_COLOR true @@ -74,7 +86,7 @@ extern unsigned int gettid(); // defined in libzt.cpp #ifdef __linux__ #define ZT_THREAD_ID syscall(SYS_gettid) #elif __APPLE__ - #define ZT_THREAD_ID (long)gettid() + #define ZT_THREAD_ID (long)0//(long)gettid() #endif #if defined(__JNI_LIB__) @@ -87,10 +99,10 @@ extern unsigned int gettid(); // defined in libzt.cpp // Network stack debugging #if defined(__ANDROID__) - #define DEBUG_STACK(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ + #define DEBUG_STACK(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ "STACK[%ld]: %17s:%5d:%20s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) #else - #define DEBUG_STACK(fmt, args...) fprintf(stderr, ZT_YEL "STACK[%ld]: %17s:%5d:%25s: " fmt \ + #define DEBUG_STACK(fmt, args...) fprintf(stderr, ZT_YEL "STACK[%ld]: %17s:%5d:%25s: " fmt \ ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) #endif @@ -99,10 +111,10 @@ extern unsigned int gettid(); // defined in libzt.cpp // #if ZT_MSG_TEST == true #if defined(__ANDROID__) - #define DEBUG_TEST(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ + #define DEBUG_TEST(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ "TEST : %17s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) #else - #define DEBUG_TEST(fmt, args...) fprintf(stderr, ZT_CYN "TEST [%ld]: %17s:%5d:%25s: " fmt \ + #define DEBUG_TEST(fmt, args...) fprintf(stderr, ZT_CYN "TEST [%ld]: %17s:%5d:%25s: " fmt \ "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) #endif #else @@ -112,10 +124,10 @@ extern unsigned int gettid(); // defined in libzt.cpp // #if ZT_MSG_ERROR == true #if defined(__ANDROID__) - #define DEBUG_ERROR(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ + #define DEBUG_ERROR(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ "ERROR: %17s:%5d:%20s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) #else - #define DEBUG_ERROR(fmt, args...) fprintf(stderr, ZT_RED \ + #define DEBUG_ERROR(fmt, args...) fprintf(stderr, ZT_RED \ "ERROR[%ld]: %17s:%5d:%25s: " fmt "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) #endif #else @@ -125,10 +137,10 @@ extern unsigned int gettid(); // defined in libzt.cpp // #if ZT_MSG_INFO == true #if defined(__ANDROID__) - #define DEBUG_INFO(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ + #define DEBUG_INFO(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ "INFO : %17s:%5d:%20s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) #else - #define DEBUG_INFO(fmt, args...) fprintf(stderr, \ + #define DEBUG_INFO(fmt, args...) fprintf(stderr, \ "INFO [%ld]: %17s:%5d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) #endif #else @@ -141,7 +153,7 @@ extern unsigned int gettid(); // defined in libzt.cpp #define DEBUG_TRANS(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ "TRANS: %17s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) #else - #define DEBUG_TRANS(fmt, args...) fprintf(stderr, ZT_GRN "TRANS[%ld]: %17s:%5d:%25s: " fmt \ + #define DEBUG_TRANS(fmt, args...) fprintf(stderr, ZT_GRN "TRANS[%ld]: %17s:%5d:%25s: " fmt \ "\n" ZT_RESET, ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) #endif #else @@ -154,7 +166,7 @@ extern unsigned int gettid(); // defined in libzt.cpp #define DEBUG_EXTRA(fmt, args...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, ZT_LOG_TAG, \ "EXTRA: %17s:%5d:%25s: " fmt "\n", ZT_FILENAME, __LINE__, __FUNCTION__, ##args)) #else - #define DEBUG_EXTRA(fmt, args...) fprintf(stderr, \ + #define DEBUG_EXTRA(fmt, args...) fprintf(stderr, \ "EXTRA[%ld]: %17s:%5d:%25s: " fmt "\n", ZT_THREAD_ID, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) #endif #else @@ -170,3 +182,5 @@ extern unsigned int gettid(); // defined in libzt.cpp #define DEBUG_TRANS(fmt, args...) #define DEBUG_EXTRA(fmt, args...) #endif + +#endif // LIBZT_DEBUG_HPP \ No newline at end of file diff --git a/include/Defs.h b/include/Defs.h new file mode 100644 index 0000000..974644c --- /dev/null +++ b/include/Defs.h @@ -0,0 +1,347 @@ + /* + * ZeroTier SDK - Network Virtualization Everywhere + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +/** + * @file + * + * Application-facing, partially-POSIX-compliant socket API + */ + +#ifndef LIBZT_DEFINES_H +#define LIBZT_DEFINES_H + +#define ZT_MAX_MTU 10000 + +/** + * How fast service states are re-checked (in milliseconds) + */ +#define ZTO_WRAPPER_CHECK_INTERVAL 50 + +/** + * + */ +#define ZTO_ID_LEN 16 + +typedef uint32_t socklen_t; + +/****************************************************************************/ +/* For SOCK_RAW support, it will initially be modeled after linux's API, so */ +/* below are the various things we need to define in order to make this API */ +/* work on other platforms. Mayber later down the road we will customize */ +/* this for each different platform. Maybe. */ +/****************************************************************************/ + +#if !defined(__linux__) +#define SIOCGIFINDEX 101 +#define SIOCGIFHWADDR 102 + +// Normally defined in linux/if_packet.h, defined here so we can offer a linux-like +// raw socket API on non-linux platforms +struct sockaddr_ll { + unsigned short sll_family; /* Always AF_PACKET */ + unsigned short sll_protocol; /* Physical layer protocol */ + int sll_ifindex; /* Interface number */ + unsigned short sll_hatype; /* ARP hardware type */ + unsigned char sll_pkttype; /* Packet type */ + unsigned char sll_halen; /* Length of address */ + unsigned char sll_addr[8]; /* Physical layer address */ +}; + +#endif + +// Provide missing optnames for setsockopt() implementations +#ifdef _WIN32 + #ifdef _WIN64 + #else + #endif +#elif __APPLE__ +#define IP_BIND_ADDRESS_NO_PORT 201 +#define IP_FREEBIND 202 +#define IP_MTU 203 +#define IP_MTU_DISCOVER 204 +#define IP_MULTICAST_ALL 205 +#define IP_NODEFRAG 206 +#define IP_RECVORIGDSTADDR 207 +#define IP_ROUTER_ALERT 208 +#define IP_TRANSPARENT 209 +#define TCP_INFO 210 +#define SO_STYLE 100 +#define TCP_CORK 101 +#define TCP_DEFER_ACCEPT 102 +#define TCP_KEEPIDLE 103 +#define TCP_LINGER2 104 +#define TCP_QUICKACK 105 +#define TCP_SYNCNT 106 +#define TCP_WINDOW_CLAMP 107 +#define UDP_CORK 108 +#elif __linux__ +#define SO_STYLE 100 +#define UDP_CORK 101 +#define IP_BIND_ADDRESS_NO_PORT 201 +#define IP_NODEFRAG 206 +#elif __unix__ +#elif defined(_POSIX_VERSION) +#else +# error "Unknown platform" +#endif + +/****************************************************************************/ +/* Legend */ +/****************************************************************************/ + +/* + NSLWIP network_stack_lwip + NSPICO network_stack_pico + NSRXBF network_stack_pico guarded frame buffer RX + ZTVIRT zt_virtual_wire + APPFDS app_fd + VSRXBF app_fd TX buf + VSTXBF app_fd RX buf +*/ + +/****************************************************************************/ +/* lwIP */ +/****************************************************************************/ + +// For LWIP configuration see: include/lwipopts.h + +#if defined(STACK_LWIP) + +typedef signed char err_t; + +/* + Specifies the polling interval and the callback function that should + be called to poll the application. The interval is specified in + number of TCP coarse grained timer shots, which typically occurs + twice a second. An interval of 10 means that the application would + be polled every 5 seconds. + */ +#define LWIP_APPLICATION_POLL_FREQ 2 + +/** + * + */ +#define LWIP_TCP_TIMER_INTERVAL 25 + +/** + * How often we check VirtualSocket statuses (in ms) + */ +#define LWIP_STATUS_TMR_INTERVAL 500 + +// #define LWIP_CHKSUM , See: RFC1071 for inspiration +#endif + +/****************************************************************************/ +/* picoTCP */ +/****************************************************************************/ + +#if defined(STACK_PICO) +#endif + +/****************************************************************************/ +/* Defines */ +/****************************************************************************/ + +/** + * + */ +#define ZT_MAX_SOCKETS 1024 + +/** + * + */ +#define ZT_SDK_MTU ZT_MAX_MTU + +/** + * + */ +#define ZT_LEN_SZ 4 + +/** + * + */ +#define ZT_ADDR_SZ 128 + +/** + * + */ +#define ZT_SOCKET_MSG_BUF_SZ ZT_SDK_MTU + ZT_LEN_SZ + ZT_ADDR_SZ + +/** + * + */ +#define ZT_PHY_POLL_INTERVAL 5 // ms + +/** + * + */ +#define ZT_ACCEPT_RECHECK_DELAY 100 // ms (for blocking zts_accept() calls) + +/** + * + */ +#define ZT_CONNECT_RECHECK_DELAY 100 // ms (for blocking zts_connect() calls) + +/** + * + */ +#define ZT_API_CHECK_INTERVAL 100 // ms + +/** + * + */ +#define MAX_PICO_FRAME_RX_BUF_SZ ZT_MAX_MTU * 128 + +/** + * + */ +#define ZT_TCP_TX_BUF_SZ 1024 * 1024 * 128 + +/** + * + */ +#define ZT_TCP_RX_BUF_SZ 1024 * 1024 * 128 + +/** + * + */ +#define ZT_UDP_TX_BUF_SZ ZT_MAX_MTU + +/** + * + */ +#define ZT_UDP_RX_BUF_SZ ZT_MAX_MTU * 10 + +// Send and Receive buffer sizes for the network stack +// By default picoTCP sets them to 16834, this is good for embedded-scale +// stuff but you might want to consider higher values for desktop and mobile +// applications. + +/** + * + */ +#define ZT_STACK_TCP_SOCKET_TX_SZ ZT_TCP_TX_BUF_SZ + +/** + * + */ +#define ZT_STACK_TCP_SOCKET_RX_SZ ZT_TCP_RX_BUF_SZ + +// Maximum size we're allowed to read or write from a stack socket +// This is put in place because picoTCP seems to fail at higher values. +// If you use another stack you can probably bump this up a bit. + +/** + * + */ +#define ZT_STACK_SOCKET_WR_MAX 4096 + +/** + * + */ +#define ZT_STACK_SOCKET_RD_MAX 4096*4 + +/** + * + */ +#define ZT_CORE_VERSION_MAJOR 1 +#define ZT_CORE_VERSION_MINOR 2 +#define ZT_CORE_VERSION_REVISION 5 + +/** + * + */ +#define ZT_LIB_VERSION_MAJOR 1 +#define ZT_LIB_VERSION_MINOR 1 +#define ZT_LIB_VERSION_REVISION 4 + +/** + * + */ +#define ZT_ID_LEN 16 + +/** + * + */ +#define ZT_VER_STR_LEN 6 + +/** + * + */ +#define ZT_HOME_PATH_MAX_LEN 128 + +/** + * + */ +#define ZT_MAC_ADDRSTRLEN 18 + +/** + * + */ +#define ZT_ERR_OK 0 + +/** + * + */ +#define ZT_ERR_GENERAL_FAILURE -88 + +// Since extra time is required to send a mesage via a socket through the +// stack and ZT service, calling a zts_close() immediately after a "successful" +// zts_write() might cause data loss, for this reason, sockets will SO_LINGER for +// a short period of time by default as a precaution. + +/** + * + */ +#define ZT_SOCK_BEHAVIOR_LINGER true + +/** + * + */ +#define ZT_SOCK_BEHAVIOR_LINGER_TIME 3 // s + +/** + * Wait time for socket closure if data is still present in the write queue + */ +#define ZT_SDK_CLTIME 60 + +// After closing a pico_socket, other threads might still try to use the +// VirtualSocket object for remaining data I/O, as a safety measure we will wait to +// delete this VirtualSocket object until the socket has been closed for some arbitrary +// amount of time and it is safe to assume any clients interacting with this +// socket have read some sort of error code from the API. + +/** + * Interval for performing cleanup tasks on Tap/Stack objects (in seconds) + */ +#define ZT_HOUSEKEEPING_INTERVAL 10 + +/** + * Whether or not we want libzt to exit on internal failure + */ +#define ZT_EXIT_ON_GENERAL_FAIL false + +#endif // LIBZT_DEFINES_H \ No newline at end of file diff --git a/include/Platform.h b/include/Platform.h new file mode 100644 index 0000000..6c9a408 --- /dev/null +++ b/include/Platform.h @@ -0,0 +1,62 @@ +/* + * ZeroTier SDK - Network Virtualization Everywhere + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +/** + * @file + * + * Platform-specific implementations of common functions + */ + +#ifndef LIBZT_PLATFORM_H +#define LIBZT_PLATFORM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief + * + * @usage For internal use only. + * @param + * @return + */ +void handle_general_failure(); + +/** + * @brief + * + * @usage For internal use only. + * @param + * @return + */ +inline unsigned int gettid(); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/include/README.md b/include/README.md index 9e99921..40d8807 100644 --- a/include/README.md +++ b/include/README.md @@ -1,4 +1 @@ -libzt API -====== - -This is the C++ API for libzt. It provides a platform-agnostic interface to the ZeroTier network virtualization service. All other [language bindings](../examples) are written in terms of this. +For applications, see [libzt.h](libzt.h) for POSIX-like socket API. diff --git a/src/Utilities.hpp b/include/Utilities.h similarity index 55% rename from src/Utilities.hpp rename to include/Utilities.h index bf54c6c..8647649 100644 --- a/src/Utilities.hpp +++ b/include/Utilities.h @@ -24,27 +24,58 @@ * of your own application. */ -#ifndef UTILITIES_HPP -#define UTILITIES_HPP +/** + * @file + * + * Misc utilities + */ + +#ifndef LIBZT_UTILITIES_H +#define LIBZT_UTILITIES_H + +#include "InetAddress.hpp" /** - * Returns masked address for subnet comparisons + * @brief Returns masked address for subnet comparisons + * + * @usage For internal use only. + * + * @param + * + * @return */ -//ZeroTier::InetAddress *ztipv6_mask(ZeroTier::InetAddress *addr, unsigned int bits); bool ipv6_in_subnet(ZeroTier::InetAddress *subnet, ZeroTier::InetAddress *addr); /** - * Convert protocol numbers to human-readable strings + * @brief Convert protocol numbers to human-readable strings + * + * @usage For internal use only. + * + * @param + * + * @return */ char *beautify_eth_proto_nums(int proto); /** - * Convert a struct sockaddr to a ZeroTier::InetAddress + * @brief Convert a struct sockaddr to a ZeroTier::InetAddress + * + * @usage For internal use only. + * + * @param + * + * @return */ void sockaddr2inet(int socket_family, const struct sockaddr *addr, ZeroTier::InetAddress *inet); /** - * Convert a raw MAC address byte array into a human-readable string + * @brief Convert a raw MAC address byte array into a human-readable string + * + * @usage For internal use only. + * + * @param + * + * @return */ void mac2str(char *macbuf, int len, unsigned char* addr); @@ -54,47 +85,6 @@ void mac2str(char *macbuf, int len, unsigned char* addr); (ipaddr)->addr[2] = ZeroTier::Utils::hton(((e & 0xffff) << 16) | (f & 0xffff)); \ (ipaddr)->addr[3] = ZeroTier::Utils::hton(((g & 0xffff) << 16) | (h & 0xffff)); } while(0) -/** - * Convert from standard IPV6 address structure to an lwIP native structure - */ -inline void in6_to_ip6(ip6_addr_t *ba, struct sockaddr_in6 *in6) -{ - uint8_t *ip = &(in6->sin6_addr).s6_addr[0]; - IP6_ADDR2(ba, - (((ip[ 0] & 0xffff) << 8) | ((ip[ 1]) & 0xffff)), - (((ip[ 2] & 0xffff) << 8) | ((ip[ 3]) & 0xffff)), - (((ip[ 4] & 0xffff) << 8) | ((ip[ 5]) & 0xffff)), - (((ip[ 6] & 0xffff) << 8) | ((ip[ 7]) & 0xffff)), - (((ip[ 8] & 0xffff) << 8) | ((ip[ 9]) & 0xffff)), - (((ip[10] & 0xffff) << 8) | ((ip[11]) & 0xffff)), - (((ip[12] & 0xffff) << 8) | ((ip[13]) & 0xffff)), - (((ip[14] & 0xffff) << 8) | ((ip[15]) & 0xffff)) - ); -} #endif - -#if defined(STACK_LWIP) && defined(LIBZT_IPV4) - -#include "lwip/ip_addr.h" -#include - -#define ip4_addr1b(ipaddr) (((u8_t*)(ipaddr))[0]) -#define ip4_addr2b(ipaddr) (((u8_t*)(ipaddr))[1]) -#define ip4_addr3b(ipaddr) (((u8_t*)(ipaddr))[2]) -#define ip4_addr4b(ipaddr) (((u8_t*)(ipaddr))[3]) -inline ip_addr_t convert_ip(struct sockaddr_in * addr) -{ - ip_addr_t conn_addr; - struct sockaddr_in *ipv4 = addr; - short a = ip4_addr1b(&(ipv4->sin_addr)); - short b = ip4_addr2b(&(ipv4->sin_addr)); - short c = ip4_addr3b(&(ipv4->sin_addr)); - short d = ip4_addr4b(&(ipv4->sin_addr)); - IP4_ADDR(&conn_addr, a,b,c,d); - return conn_addr; -} - -#endif // STACK_LWIP && LIBZT_IPV4 - #endif // UTILITIES_HPP diff --git a/src/ExampleStackDriver.cpp b/include/VirtualBindingPair.h similarity index 78% rename from src/ExampleStackDriver.cpp rename to include/VirtualBindingPair.h index a8341c2..4836a3e 100644 --- a/src/ExampleStackDriver.cpp +++ b/include/VirtualBindingPair.h @@ -24,14 +24,25 @@ * of your own application. */ +/** + * @file + * + * + */ /* +#ifndef LIBZT_VIRTUALBINDINGPAIR_H +#define LIBZT_VIRTUALBINDINGPAIR_H -This file is only meant for those who wish to replace the currently supported network stacks (lwIP and picoTCP) with -one of their own choosing. If you're looking for information on how to integrate libzt with your application, you -should instead go view the (examples) folder. Now let us get started. +#ifdef __cplusplus +extern "C" { +#endif - TODO +struct VirtualBindingPair; +#ifdef __cplusplus +} +#endif +#endif */ \ No newline at end of file diff --git a/include/VirtualSocket.h b/include/VirtualSocket.h new file mode 100644 index 0000000..df711f3 --- /dev/null +++ b/include/VirtualSocket.h @@ -0,0 +1,51 @@ +/* + * ZeroTier SDK - Network Virtualization Everywhere + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +/** + * @file + * + * Platform-agnostic implementation of a socket-like object + */ + +#ifndef LIBZT_VIRTUALSOCKET_H +#define LIBZT_VIRTUALSOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * An abstraction of a socket that operates between the application-exposed platform-sockets + * and the network stack's representation of a protocol control structure. This object is used by + * the POSIX socket emulation layer and stack drivers. + */ +class VirtualSocket; + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/include/ZT1Service.h b/include/ZT1Service.h new file mode 100644 index 0000000..a005057 --- /dev/null +++ b/include/ZT1Service.h @@ -0,0 +1,346 @@ + /* + * ZeroTier SDK - Network Virtualization Everywhere + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +/** + * @file + * + * ZeroTier One service control wrapper header file + */ + +#include "ZeroTierOne.h" +#include "Defs.h" + +#include + +#ifndef ZT1SERVICE_H +#define ZT1SERVICE_H + +#ifdef __cplusplus +extern "C" { +#endif + +namespace ZeroTier +{ + extern std::vector vtaps; + + class picoTCP; + extern ZeroTier::picoTCP *picostack; + + class lwIP; + extern ZeroTier::lwIP *lwipstack; + + class VirtualTap; + class VirtualSocket; + struct InetAddress; +} + +/** + * @brief Returns a vector of network routes { target, via, metric, etc... } + * + * @usage + * @param nwid + * @return + */ +std::vector *zts_get_network_routes(char *nwid); + +/** + * @brief + * + * @usage For internal use only. + * @param + * @return + */ +int zts_get_device_id_from_file(const char *filepath, char *devID); + +/** + * @brief Starts a ZeroTier service in the background + * + * @usage For internal use only. + * @param + * @return + */ +void *zts_start_service(void *thread_id); + +/** + * @brief + * + * @usage For internal use only. + * @param + * @return + */ +void disableTaps(); + +/** + * @brief + * + * @usage For internal use only. + * @param + * @return + */ +void zts_get_ipv4_address(const char *nwid, char *addrstr, const int addrlen); + +/** + * @brief + * + * @usage For internal use only. + * @param + * @return + */ +void zts_get_ipv6_address(const char *nwid, char *addrstr, const int addrlen); + +/** + * @brief + * + * @usage For internal use only. + * @param + * @return + */ +int zts_has_ipv4_address(const char *nwid); + +/** + * @brief + * + * @usage For internal use only. + * @param + * @return + */ +int zts_has_ipv6_address(const char *nwid); + +/** + * @brief + * + * @usage For internal use only. + * @param + * @return + */ +int zts_has_address(const char *nwid); + +/** + * @brief + * + * @usage + * @param + * @return + */ +void zts_get_6plane_addr(char *addr, const char *nwid, const char *devID); + +/** + * @brief + * + * @usage + * @param + * @return + */ +void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID); + +/** + * @brief + * + * @usage + * @param + * @return + */ +void zts_join(const char * nwid); + +/** + * @brief + * + * @usage For internal use only. + * @param + * @return + */ +void zts_join_soft(const char * filepath, const char * nwid); + +/** + * @brief + * + * @usage + * @param + * @return + */ +void zts_leave(const char * nwid); + +/** + * @brief + * + * @usage For internal use only. + * @param + * @return + */ +void zts_leave_soft(const char * filepath, const char * nwid); + +/** + * @brief + * + * @usage + * @param + * @return + */ +int zts_running(); + +/** + * @brief + * + * @usage + * @param + * @return + */ +void zts_start(const char *path); + +/** + * @brief + * + * @usage + * @param + * @return + */ +void zts_simple_start(const char *path, const char *nwid); + +/** + * @brief + * + * @usage + * @param + * @return + */ +void zts_stop(); + +/** + * @brief + * + * @usage + * @param + * @return + */void zts_get_homepath(char *homePath, int len); + +/** + * @brief + * + * @usage + * @param + * @return + */ +void zts_core_version(char *ver); + +/** + * @brief + * + * @usage + * @param + * @return + */ +void zts_lib_version(char *ver); + +/** + * @brief + * + * @usage + * @param + * @return + */ +int zts_get_device_id(char *devID); + +/** + * @brief + * + * @usage + * @param + * @return + */ +unsigned long zts_get_peer_count(); + +/** + * @brief + * + * @usage + * @param + * @return + */ +int zts_get_peer_address(char *peer, const char *devID); + +/** + * @brief + * + * @usage + * @param + * @return + */ +void zts_enable_http_control_plane(); + +/** + * @brief + * + * @usage + * @param + * @return + */ +void zts_disable_http_control_plane(); + +/** + * @brief Whether we can add a new socket or not. Depends on stack in use + * + * @usage + * @param socket_type + * @return + */ +bool can_provision_new_socket(int socket_type); + +/** + * @brief Returns the number of sockets either already provisioned or waiting to be + * Some network stacks may have a limit on the number of sockets that they can + * safely handle due to timer construction, this is a way to check that we + * haven't passed that limit. Someday if multiple stacks are used simultaneously + * the logic for this function should change accordingly. + * + * @usage + * @param + * @return + */ +int zts_num_active_virt_sockets(); + +/** + * @brief Returns maximum number of sockets allowed by network stack + * + * @usage + * @param socket_type + * @return + */ +int zts_maxsockets(int socket_type); + +/** + * @brief + * + * @usage + * @param + * @return + */ +int pico_ntimers(); + +#endif // ZT1SERVICE_H + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/include/libzt.h b/include/libzt.h index 0a3a30c..53a4673 100644 --- a/include/libzt.h +++ b/include/libzt.h @@ -1,9 +1,3 @@ -/** - * @file - * - * libzt application-facing POSIX-like socket API - */ - /* * ZeroTier SDK - Network Virtualization Everywhere * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ @@ -30,221 +24,22 @@ * of your own application. */ -#ifndef ZT_LIBZT_H -#define ZT_LIBZT_H +/** + * @file + * + * Application-facing, partially-POSIX-compliant socket API + */ + +#ifndef LIBZT_H +#define LIBZT_H -#include #include -#include #include #include #include -#include "ZeroTierOne.h" - -// See test/selftest.cpp for examples - -/****************************************************************************/ -/* For SOCK_RAW support, it will initially be modeled after linux's API, so */ -/* below are the various things we need to define in order to make this API */ -/* work on other platforms. Mayber later down the road we will customize */ -/* this for each different platform. Maybe. */ -/****************************************************************************/ - -#if !defined(__linux__) -#define SIOCGIFINDEX 101 -#define SIOCGIFHWADDR 102 - -// Normally defined in linux/if_packet.h, defined here so we can offer a linux-like -// raw socket API on non-linux platforms -struct sockaddr_ll { - unsigned short sll_family; /* Always AF_PACKET */ - unsigned short sll_protocol; /* Physical layer protocol */ - int sll_ifindex; /* Interface number */ - unsigned short sll_hatype; /* ARP hardware type */ - unsigned char sll_pkttype; /* Packet type */ - unsigned char sll_halen; /* Length of address */ - unsigned char sll_addr[8]; /* Physical layer address */ -}; - -/* -struct zts_ifreq { - char ifr_name[IFNAMSIZ]; // Interface name - union { - struct sockaddr ifr_addr; - struct sockaddr ifr_dstaddr; - struct sockaddr ifr_broadaddr; - struct sockaddr ifr_netmask; - struct sockaddr ifr_hwaddr; - short ifr_flags; - int ifr_ifindex; - int ifr_metric; - int ifr_mtu; - struct ifmap ifr_map; - char ifr_slave[IFNAMSIZ]; - char ifr_newname[IFNAMSIZ]; - char *ifr_data; - }; -}; -*/ - -#endif - -// Provide missing optnames for setsockopt() implementations -#ifdef _WIN32 - #ifdef _WIN64 - #else - #endif -#elif __APPLE__ -#define IP_BIND_ADDRESS_NO_PORT 201 -#define IP_FREEBIND 202 -#define IP_MTU 203 -#define IP_MTU_DISCOVER 204 -#define IP_MULTICAST_ALL 205 -#define IP_NODEFRAG 206 -#define IP_RECVORIGDSTADDR 207 -#define IP_ROUTER_ALERT 208 -#define IP_TRANSPARENT 209 -#define TCP_INFO 210 -#define SO_STYLE 100 -#define TCP_CORK 101 -#define TCP_DEFER_ACCEPT 102 -#define TCP_KEEPIDLE 103 -#define TCP_LINGER2 104 -#define TCP_QUICKACK 105 -#define TCP_SYNCNT 106 -#define TCP_WINDOW_CLAMP 107 -#define UDP_CORK 108 -#elif __linux__ -#define SO_STYLE 100 -#define UDP_CORK 101 -#define IP_BIND_ADDRESS_NO_PORT 201 -#define IP_NODEFRAG 206 -#elif __unix__ -#elif defined(_POSIX_VERSION) -#else -# error "Unknown platform" -#endif - -/****************************************************************************/ -/* Legend */ -/****************************************************************************/ - -/* - NSLWIP network_stack_lwip - NSPICO network_stack_pico - NSRXBF network_stack_pico guarded frame buffer RX - ZTVIRT zt_virtual_wire - APPFDS app_fd - VSRXBF app_fd TX buf - VSTXBF app_fd RX buf -*/ - -/****************************************************************************/ -/* lwIP */ -/****************************************************************************/ - -// For LWIP configuration see: include/lwipopts.h - -#if defined(STACK_LWIP) -/* - Specifies the polling interval and the callback function that should - be called to poll the application. The interval is specified in - number of TCP coarse grained timer shots, which typically occurs - twice a second. An interval of 10 means that the application would - be polled every 5 seconds. */ -#define LWIP_APPLICATION_POLL_FREQ 2 - -#define LWIP_TCP_TIMER_INTERVAL 25 - -// How often we check VirtualSocket statuses (in ms) -#define LWIP_STATUS_TMR_INTERVAL 500 - -// #define LWIP_CHKSUM , See: RFC1071 for inspiration -#endif - -/****************************************************************************/ -/* picoTCP */ -/****************************************************************************/ - -#if defined(STACK_PICO) -#endif - -/****************************************************************************/ -/* Defines */ -/****************************************************************************/ - -#define ZT_MAX_SOCKETS 1024 -#define ZT_SDK_MTU ZT_MAX_MTU -#define ZT_LEN_SZ 4 -#define ZT_ADDR_SZ 128 -#define ZT_SOCKET_MSG_BUF_SZ ZT_SDK_MTU + ZT_LEN_SZ + ZT_ADDR_SZ - - -#define ZT_PHY_POLL_INTERVAL 2 // ms -#define ZT_ACCEPT_RECHECK_DELAY 100 // ms (for blocking zts_accept() calls) -#define ZT_CONNECT_RECHECK_DELAY 100 // ms (for blocking zts_connect() calls) -#define ZT_API_CHECK_INTERVAL 100 // ms - -#define MAX_PICO_FRAME_RX_BUF_SZ ZT_MAX_MTU * 128 - -#define ZT_TCP_TX_BUF_SZ 1024 * 1024 * 128 -#define ZT_TCP_RX_BUF_SZ 1024 * 1024 * 128 -#define ZT_UDP_TX_BUF_SZ ZT_MAX_MTU -#define ZT_UDP_RX_BUF_SZ ZT_MAX_MTU * 10 - -// Send and Receive buffer sizes for the network stack -// By default picoTCP sets them to 16834, this is good for embedded-scale -// stuff but you might want to consider higher values for desktop and mobile -// applications. -#define ZT_STACK_TCP_SOCKET_TX_SZ ZT_TCP_TX_BUF_SZ -#define ZT_STACK_TCP_SOCKET_RX_SZ ZT_TCP_RX_BUF_SZ - -// Maximum size we're allowed to read or write from a stack socket -// This is put in place because picoTCP seems to fail at higher values. -// If you use another stack you can probably bump this up a bit. -#define ZT_STACK_SOCKET_WR_MAX 4096 -#define ZT_STACK_SOCKET_RD_MAX 4096*4 - -#define ZT_CORE_VERSION_MAJOR 1 -#define ZT_CORE_VERSION_MINOR 2 -#define ZT_CORE_VERSION_REVISION 5 - -#define ZT_LIB_VERSION_MAJOR 1 -#define ZT_LIB_VERSION_MINOR 1 -#define ZT_LIB_VERSION_REVISION 4 - -#define ZT_ID_LEN 16 -#define ZT_VER_STR_LEN 6 -#define ZT_HOME_PATH_MAX_LEN 128 -#define ZT_MAC_ADDRSTRLEN 18 - -#define ZT_ERR_OK 0 -#define ZT_ERR_GENERAL_FAILURE -88 - -// Since extra time is required to send a mesage via a socket through the -// stack and ZT service, calling a zts_close() immediately after a "successful" -// zts_write() might cause data loss, for this reason, sockets will SO_LINGER for -// a short period of time by default as a precaution. - -#define ZT_SOCK_BEHAVIOR_LINGER true -#define ZT_SOCK_BEHAVIOR_LINGER_TIME 3 // s - -// Wait time for socket closure if data is still present in the write queue -#define ZT_SDK_CLTIME 60 - -// After closing a pico_socket, other threads might still try to use the -// VirtualSocket object for remaining data I/O, as a safety measure we will wait to -// delete this VirtualSocket object until the socket has been closed for some arbitrary -// amount of time and it is safe to assume any clients interacting with this -// socket have read some sort of error code from the API. -#define ZT_VirtualSocket_DELETE_WAIT_TIME 30 // s - -// Interval for performing cleanup tasks on Tap/Stack objects -#define ZT_HOUSEKEEPING_INTERVAL 10 // s - -// Whether or not we want libzt to shit its pants -#define ZT_EXIT_ON_GENERAL_FAIL false +#include "Debug.hpp" +#include "Defs.h" /****************************************************************************/ /* Socket API Signatures */ @@ -287,6 +82,12 @@ struct zts_ifreq { extern "C" { #endif +// forward declarations from ZT1Service.h +void zts_simple_start(const char *path, const char *nwid); +int zts_get_device_id(char *devID); + +void init_network_stack(); + /** \brief Start core ZeroTier service (generates cryptographic identity). * * @@ -318,245 +119,227 @@ void zts_start(const char *path); void zts_simple_start(const char *path, const char *nwid); /** - * @brief Stops the ZeroTier core service and disconnects from all virtual networks - * - * @usage Called at the end of your application. This call will block until everything is shut down - * - * @return + * @brief Stops the ZeroTier core service and disconnects from all virtual networks * + * @usage Called at the end of your application. This call will block until everything is shut down + * @return */ void zts_stop(); /** - * @brief Joins a virtual network - * - * @usage Called after zts_start() or zts_simple_start() + * @brief Joins a virtual network * - * @param nwid the 16-digit hexidecimal network identifier - * - * @return + * @usage Called after zts_start() or zts_simple_start() + * @param nwid the 16-digit hexidecimal network identifier + * @return */ void zts_join(const char * nwid); /** - * @brief Joins a network (eventually), this will create the dir and conf file required, don't instruct the core - * to do anything - * - * @usage Candidate for deletion + * @brief Joins a network (eventually), this will create the dir and conf file required, don't instruct the core + * to do anything * - * @param filepath path to the `*.conf` file named after the network - * - * @return + * @usage Candidate for deletion + * @param filepath path to the `*.conf` file named after the network + * @param nwid + * @return */ void zts_join_soft(const char * filepath, const char * nwid); /** - * @brief Leaves a virtual network. - * - * @usage + * @brief Leaves a virtual network. * - * @param nwid - * - * @return - * + * @usage + * @param nwid + * @return */ void zts_leave(const char * nwid); /** - * @brief Leave a network - Only delete the .conf file, this will prevent the service from joining upon next startup - * - * @usage + * @brief Leave a network - Only delete the .conf file, this will prevent the service from joining upon next startup * - * @param filepath - * @param nwid - * - * @return + * @usage + * @param filepath + * @param nwid + * @return */ void zts_leave_soft(const char * filepath, const char * nwid); /** - * @brief Return the home path for this instance of ZeroTier - * - * @usage + * @brief Return the home path for this instance of ZeroTier * - * @param homePath - * @param len - * - * @return + * @usage + * @param homePath + * @param len + * @return */ void zts_get_homepath(char *homePath, const int len); /** - * @brief Copies ZeroTier core version string into `ver` - * - * @usage + * @brief * - * @param ver - * - * @return - * + * @usage Copies ZeroTier core version string into `ver` + * @param ver + * @return */ void zts_core_version(char *ver); /** - * @brief Copies libzt version string into `ver` - * - * @usage + * @brief Copies libzt version string into `ver` * - * @param ver - * - * @return - * - * Provides core libzt service version + * @usage + * @param ver + * @return */ void zts_lib_version(char *ver); /** - * @brief Get device ID (10-digit hex + NULL byte) - * - * @usage + * @brief Get device ID (10-digit hex + NULL byte) * - * @param devID - * - * @return + * @usage + * @param devID + * @return */ int zts_get_device_id(char *devID); /** - * @brief Check whether the service is running - * - * @usage - * @return + * @brief Check whether the service is running + * + * @usage + * @return */ int zts_running(); /** - * @brief Returns whether any IPv6 address has been assigned to the SockTap for this network - * - * @usage This is used as an indicator of readiness for service for the ZeroTier core and stack + * @brief Returns whether any IPv6 address has been assigned to the SockTap for this network * - * @param nwid - * - * @return + * @usage This is used as an indicator of readiness for service for the ZeroTier core and stack + * @param nwid + * @return */ int zts_has_ipv4_address(const char *nwid); /** - * @brief Returns whether any IPv4 address has been assigned to the SockTap for this network - * - * @usage This is used as an indicator of readiness for service for the ZeroTier core and stack + * @brief Returns whether any IPv4 address has been assigned to the SockTap for this network * - * @param nwid - * @return + * @usage This is used as an indicator of readiness for service for the ZeroTier core and stack + * @param nwid + * @return */ int zts_has_ipv6_address(const char *nwid); /** - * @brief Returns whether any address has been assigned to the SockTap for this network - * - * @usage This is used as an indicator of readiness for service for the ZeroTier core and stack + * @brief Returns whether any address has been assigned to the SockTap for this network * - * @param nwid - * @return + * @usage This is used as an indicator of readiness for service for the ZeroTier core and stack + * @param nwid + * @return */ int zts_has_address(const char *nwid); /** - * @brief Get IPV4 Address for this device on a given network - * - * @usage FIXME: Only returns first address found for given protocol and network (should be enough for now) + * @brief Get IPV4 Address for this device on a given network * - * @param nwid - * @param addrstr - * @param addrlen - * - * @return + * @usage FIXME: Only returns first address found for given protocol and network (should be enough for now) + * @param nwid + * @param addrstr + * @param addrlen + * @return */ void zts_get_ipv4_address(const char *nwid, char *addrstr, const int addrlen); /** - * @brief Get IPV6 Address for this device on a given network - * - * @usage FIXME: Only returns first address found for given protocol and network (should be enough for now) + * @brief Get IPV6 Address for this device on a given network * - * @param - * @param - * @param - * - * @return + * @usage FIXME: Only returns first address found for given protocol and network (should be enough for now) + * @param + * @param + * @param + * @param + * @param + * @return */ void zts_get_ipv6_address(const char *nwid, char *addrstr, const int addrlen); /** - * @brief Returns a 6PLANE IPv6 address given a network ID and zerotier ID - * - * @usage + * @brief Returns a 6PLANE IPv6 address given a network ID and zerotier ID * - * @param - * @param - * @param - * - * @return + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ void zts_get_6plane_addr(char *addr, const char *nwid, const char *devID); /** - * @brief Returns an RFC 4193 IPv6 address given a network ID and zerotier ID - * - * @usage + * @brief Returns an RFC 4193 IPv6 address given a network ID and zerotier ID * - * @param - * @param - * @param - * - * @return + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID); /** - * @brief Return the number of peers on this network - * - * @usage + * @brief Return the number of peers on this network * - * @param - * @param - * @param - * - * @return + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ unsigned long zts_get_peer_count(); /** - * @brief Get the IP address of a peer if a direct path is available - * - * @usage + * @brief Get the IP address of a peer if a direct path is available * - * @param peer - * @param devID - * - * @return + * @usage + * @param peer + * @param devID + * @param + * @param + * @param + * @return */ int zts_get_peer_address(char *peer, const char *devID); /** - * @brief Enable HTTP control plane (traditionally used by zerotier-cli) + * @brief Enable HTTP control plane (traditionally used by zerotier-cli) * - Allows one to control the ZeroTier core via HTTP requests * FIXME: Implement - * - * @usage - * - * @return + * + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ void zts_enable_http_control_plane(); /** - * @brief Disable HTTP control plane (traditionally used by zerotier-cli) + * @brief Disable HTTP control plane (traditionally used by zerotier-cli) * - Allows one to control the ZeroTier core via HTTP requests * FIXME: Implement - * - * @usage - * - * @return + * + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ void zts_disable_http_control_plane(); @@ -567,591 +350,347 @@ void zts_disable_http_control_plane(); /****************************************************************************/ /** - * @brief Create a socket - * - * @usage + * @brief Create a socket * - * @param - * @param - * @param - * - * @return + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ int zts_socket(int socket_family, int socket_type, int protocol); /** - * @brief Connect a socket to a remote host - * - * @usage + * @brief Connect a socket to a remote host * - * @param - * @param - * @param - * - * @return + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ int zts_connect(int fd, const struct sockaddr *addr, socklen_t addrlen); /** - * @brief Bind a socket to an interface (VirtualTap) - * - * @usage + * @brief * - * @param - * @param - * @param - * - * @return + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ int zts_bind(int fd, const struct sockaddr *addr, socklen_t addrlen); /** - * @brief Listen for incoming VirtualSockets - * - * @usage + * @brief Listen for incoming VirtualSockets * - * @param - * @param - * @param - * - * @return + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ int zts_listen(int fd, int backlog); /** - * @brief Accept a VirtualSocket - * - * @usage + * @brief Accept a VirtualSocket * - * @param - * @param - * @param - * - * @return + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ int zts_accept(int fd, struct sockaddr *addr, socklen_t *addrlen); /** - * @brief Accept a VirtualSocket - * - * @usage + * @brief Accept a VirtualSocket * - * @param - * @param - * @param - * - * @return + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ #if defined(__linux__) int zts_accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags); #endif /** - * @brief Set socket options - * - * @usage + * @brief Set socket options * - * @param - * @param - * @param - * - * @return + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ int zts_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen); /** - * @brief Get socket options - * - * @usage + * @brief Get socket options * - * @param - * @param - * @param - * - * @return + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ int zts_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen); /** - * @brief Get socket name - * - * @usage + * @brief Get socket name * - * @param - * @param - * @param - * - * @return + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ int zts_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen); /** - * @brief Get a peer name - * - * @usage + * @brief Get a peer name * - * @param - * @param - * @param - * - * @return + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ int zts_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen); /** - * @brief Gets current hostname - * - * @usage + * @brief Gets current hostname * - * @param - * @param - * @param - * - * @return + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ int zts_gethostname(char *name, size_t len); /** - * @brief Sets current hostname - * - * @usage + * @brief Sets current hostname * - * @param - * @param - * @param - * - * @return + * @usage + * @param + * @param + * @param + * @param + * @param + * @return */ int zts_sethostname(const char *name, size_t len); /** - * @brief lose a socket - * - * @usage + * @brief close a socket * - * @param fd - * @param - * @param - * - * @return + * @usage + * @param fd + * @return */ int zts_close(int fd); /** - * @brief waits for one of a set of file descriptors to become ready to perform I/O. - * - * @usage + * @brief waits for one of a set of file descriptors to become ready to perform I/O. * - * @param fds - * @param nfds - * @param timeout - * - * @return + * @usage + * @param fds + * @param nfds + * @param timeout + * @return */ int zts_poll(struct pollfd *fds, nfds_t nfds, int timeout); /** - * @brief monitor multiple file descriptors, waiting until one or more of the file descriptors become "ready" - * - * @usage + * @brief monitor multiple file descriptors, waiting until one or more of the file descriptors become "ready" * - * @param nfds - * @param readfds - * @param writefds - * @param exceptfds - * @param timeout - * - * @return + * @usage + * @param nfds + * @param readfds + * @param writefds + * @param exceptfds + * @param timeout + * @return */ int zts_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); /** - * @brief Issue file control commands on a socket - * - * @usage - * - * @param fd - * @param cmd - * @param flags - * - * @return + * @brief Issue file control commands on a socket * + * @usage + * @param fd + * @param cmd + * @param flags + * @return */ int zts_fcntl(int fd, int cmd, int flags); /** - * @brief Control a device - * - * @usage + * @brief Control a device * - * @param fd - * @param request - * @param argp - * - * @return + * @usage + * @param fd + * @param request + * @param argp + * @return */ int zts_ioctl(int fd, unsigned long request, void *argp); /** - * @brief Send data to remote host - * - * @usage + * @brief Send data to remote host * - * @param fd - * @param buf - * @param len - * @param flags - * - * @return + * @usage + * @param fd + * @param buf + * @param len + * @param flags + * @return */ ssize_t zts_send(int fd, const void *buf, size_t len, int flags); /** - * @brief Send data to remote host - * - * @usage + * @brief Send data to remote host * - * @param fd - * @param buf - * @param len - * @param flags - * @param addr - * @param addrlen - * - * @return + * @usage + * @param fd + * @param buf + * @param len + * @param flags + * @param addr + * @param addrlen + * @return */ ssize_t zts_sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen); /** - * @brief Send message to remote host - * - * @usage + * @brief Send message to remote host * - * @param fd - * @param msg - * @param flags - * - * @return + * @usage + * @param fd + * @param msg + * @param flags + * @return */ ssize_t zts_sendmsg(int fd, const struct msghdr *msg, int flags); /** - * @brief Receive data from remote host - * - * @usage + * @brief Receive data from remote host * - * @param fd - * @param buf - * @param len - * @param flags - * - * @return + * @usage + * @param fd + * @param buf + * @param len + * @param flags + * @param + * @return */ ssize_t zts_recv(int fd, void *buf, size_t len, int flags); /** - * @brief Receive data from remote host - * - * @usage + * @brief Receive data from remote host * - * @param fd - * @param buf - * @param len - * @param flags - * @param addr - * @param addrlen - * - * @return + * @usage + * @param fd + * @param buf + * @param len + * @param flags + * @param addr + * @param addrlen + * @return */ ssize_t zts_recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen); /** - * @brief Receive a message from remote host - * - * @usage + * @brief Receive a message from remote host * - * @param fd - * @param msg - * @param flags - * - * @return + * @usage + * @param fd + * @param msg + * @param flags + * @return */ ssize_t zts_recvmsg(int fd, struct msghdr *msg,int flags); /** - * @brief Read bytes from socket onto buffer - * - * @usage Note, this function isn't strictly necessary, you can use a regular read() - * call as long as the socket file descriptor was created via a zts_socket() call. + * @brief Read bytes from socket onto buffer * - * @param fd - * @param buf - * @param len - * - * @return - * + * @usage + * @param fd + * @param buf + * @param len + * @param + * @param + * @return */ int zts_read(int fd, void *buf, size_t len); /** - * @brief Write bytes from buffer to socket - * - * @usage Note, this function isn't strictly necessary, you can use a regular write() - * call as long as the socket file descriptor was created via a zts_socket() call. + * @brief Write bytes from buffer to socket * - * @param fd - * @param buf - * @param len - * - * @return + * @usage + * @param fd + * @param buf + * @param len + * @param + * @param + * @return */ int zts_write(int fd, const void *buf, size_t len); /** - * @brief Sends a FIN segment - * - * @usage + * @brief * - * @param fd - * @param how - * - * @return + * @usage + * @param fd + * @param how + * @return */ int zts_shutdown(int fd, int how); /** - * @brief Returns a vector of network routes { target, via, metric, etc... } - * - * @usage + * @brief Adds a DNS nameserver for the network stack to use * - * @param nwid - * - * @return - */ -std::vector *zts_get_network_routes(char *nwid); - -/** - * @brief Adds a DNS nameserver for the network stack to use - * - * @usage - * - * @param addr - * - * @return + * @usage + * @param addr + * @return */ int zts_add_dns_nameserver(struct sockaddr *addr); /** - * @brief Removes a DNS nameserver - * - * @usage + * @brief Removes a DNS nameserver * - * @param addr - * - * @return + * @usage + * @param addr + * @return */ int zts_del_dns_nameserver(struct sockaddr *addr); -/****************************************************************************/ -/* SDK Socket API Helper functions/objects --- DONT CALL THESE DIRECTLY */ -/****************************************************************************/ - -namespace ZeroTier -{ - class picoTCP; - extern ZeroTier::picoTCP *picostack; - - class lwIP; - extern ZeroTier::lwIP *lwipstack; - - class VirtualTap; - class VirtualSocket; - struct InetAddress; -} - -/** - * @brief Whether we can add a new socket or not. Depends on stack in use - * - * @usage - * - * @param socket_type - * @param - * @param - * - * @return - */ -bool can_provision_new_socket(int socket_type); - -/** - * @brief Returns the number of sockets either already provisioned or waiting to be - * Some network stacks may have a limit on the number of sockets that they can - * safely handle due to timer construction, this is a way to check that we - * haven't passed that limit. Someday if multiple stacks are used simultaneously - * the logic for this function should change accordingly. - * - * @usage - * - * @return - */ -int zts_num_active_virt_sockets(); - -/** - * @brief Returns maximum number of sockets allowed by network stack - * - * @usage - * - * @param socket_type - * - * @return - */ -int zts_maxsockets(int socket_type); - -int pico_ntimers(); - -/****************************************************************************/ -/* ZeroTier Core helper functions for libzt - DON'T CALL THESE DIRECTLY */ -/****************************************************************************/ - -ZeroTier::VirtualTap *getTapByNWID(uint64_t nwid); -ZeroTier::VirtualTap *getTapByAddr(ZeroTier::InetAddress *addr); -ZeroTier::VirtualTap *getTapByName(char *ifname); -ZeroTier::VirtualTap *getTapByIndex(int index); -ZeroTier::VirtualTap *getAnyTap(); - -/** - * @brief Returns a pointer to a VirtualSocket for a given file descriptor - * - * @usage Don't call this directly from application. For internal use only. - * - * @return - * - */ -ZeroTier::VirtualSocket *get_virt_socket(int fd); - -/** - * @brief Removes a VirtualSocket - * - * @usage Don't call this directly from application. For internal use only. - * - * @param fd - * - * @return - * - */ -int del_virt_socket(int fd); - -/** - * @brief Adds a virtualSocket - * - * @usage Don't call this directly from application. For internal use only. - * - * @param fd - * @param vs - * - * @return - * - */ -int add_unassigned_virt_socket(int fd, ZeroTier::VirtualSocket *vs); - -/** - * @brief Removes unassigned VirtualSocket - * - * @usage Don't call this directly from application. For internal use only. - * - * @param fd - * - * @return - * - */ -int del_unassigned_virt_socket(int fd); - -/** - * @brief Adds an assigned VirtualSocket - * - * @usage Don't call this directly from application. For internal use only. - * - * @param tap - * @param vs - * @param fd - * - * @return - * - */ -int add_assigned_virt_socket(ZeroTier::VirtualTap *tap, ZeroTier::VirtualSocket *vs, int fd); - -/** - * @brief Removes an assigned VirtualSocket - * - * @usage Don't call this directly from application. For internal use only. - * - * @param tap - * @param vs - * @param fd - * - * @return - * - */ -int del_assigned_virt_socket(ZeroTier::VirtualTap *tap, ZeroTier::VirtualSocket *vs, int fd); - -/** - * @brief Gets a pair of associated virtual objects (VirtualSocket bound to a VirtualTap) - * - * @usage Don't call this directly from application. For internal use only. - * - * @param fd - * - * @return - * - */ -std::pair *get_assigned_virtual_pair(int fd); - -/** - * @brief Disables all VirtualTap devices - * - * @usage Don't call this directly from application. For internal use only. - * - * @return - * - */ -void disableTaps(); - -/** - * @brief Reads a 10-digit hexidecimal device ID (aka. nodeId, ztAddress, etc. from file) - * - * @usage Don't call this directly from application. For internal use only. - * - * @param filepath - * @param devID - * - * @return - * - */ -int zts_get_device_id_from_file(const char *filepath, char *devID); - -/** - * @brief Starts an instance of the ZeroTier core service. - * - * @usage Don't call this directly from application. For internal use only. - * - * @param thread_id - * - * @return - * - */ -void *zts_start_service(void *thread_id); - -/** - * @brief Should be called wherever libzt enters a condition where undefined behaviour might occur. - * - * @usage Don't call this directly from application. For internal use only. - * - * @return - * - */ -void handle_general_failure(); - -#include "Debug.hpp" - #ifdef __cplusplus } // extern "C" #endif diff --git a/include/lwIP.hpp b/include/lwIP.hpp new file mode 100644 index 0000000..cdb5bdc --- /dev/null +++ b/include/lwIP.hpp @@ -0,0 +1,73 @@ +/* + * ZeroTier SDK - Network Virtualization Everywhere + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +/** + * @file + * + * lwIP network stack driver + */ + +#ifndef ZT_LWIP_HPP +#define ZT_LWIP_HPP + +#include "MAC.hpp" +#include "InetAddress.hpp" +#include "Defs.h" + +/** + * @brief Initialize network stack semaphores, threads, and timers. + * + * @param + * @return + */ +void lwip_driver_init(); + +/** + * @brief Set up an interface in the network stack for the VirtualTap. + * + * @param + * @return + */ +void lwip_init_interface(void *tapref, const ZeroTier::MAC &mac, const ZeroTier::InetAddress &ip); + +/** + * @brief Called from the stack, outbound ethernet frames from the network stack enter the ZeroTier virtual wire here. + * + * @param + * @return + */ +err_t lwip_eth_tx(struct netif *netif, struct pbuf *p); + +/** + * @brief Packets from the ZeroTier virtual wire enter the stack here. + * + * @param + * @return + */ +void lwip_eth_rx(ZeroTier::VirtualTap *tap, const ZeroTier::MAC &from, const ZeroTier::MAC &to, unsigned int etherType, + const void *data, unsigned int len); + +#endif diff --git a/include/lwipopts.h b/include/lwipopts.h index bc97ac1..504a45e 100644 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -1,9 +1,3 @@ -/** - * @file - * - * lwIP Options Configuration - */ - /* * Copyright (c) 2001-2004 Swedish Institute of Computer Science. * All rights reserved. @@ -35,9 +29,48 @@ * Author: Adam Dunkels * */ + +/** + * @file + * + * lwIP Options Configuration + */ + #ifndef __LWIPOPTS_H__ #define __LWIPOPTS_H__ +/* + * Provides its own errno + */ +#define LWIP_PROVIDE_ERRNO 0 + +/* + * Provides core locking machinery + */ +#define LWIP_TCPIP_CORE_LOCKING 1 + +/* + * Provides a macro to spoof the names of the lwip socket functions + */ +#define LWIP_POSIX_SOCKETS_IO_NAMES 0 + +/* + * + */ +#define LWIP_TIMERS 1 + +/* + * + */ +//#define LWIP_COMPAT_MUTEX 1 +//#define LWIP_COMPAT_MUTEX_ALLOWED 1 + +/* + * Provides network/host byte transformation macros + */ +#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 1 + + /* * Include user defined options first. Anything not defined in these files * will be set to standard values. Override anything you dont like! @@ -56,6 +89,9 @@ // --- DEBUG --- + +#define LWIP_DEBUG 1 + /* flag for LWIP_DEBUGF indicating a tracing message * (to follow program flow) */ @@ -124,8 +160,6 @@ #define DNS_DEBUG LWIP_DBG_OFF -#define LWIP_UDP 1 -#define LWIP_TCP 1 #define LWIP_ETHERNET 1 #define LWIP_CHKSUM_ALGORITHM 2 @@ -187,7 +221,7 @@ happening sooner than they should. * critical regions during buffer allocation, deallocation and memory * allocation and deallocation. */ -#define SYS_LIGHTWEIGHT_PROT 0 +#define SYS_LIGHTWEIGHT_PROT 1 /** * NO_SYS==1: Provides VERY minimal functionality. Otherwise, @@ -195,10 +229,10 @@ happening sooner than they should. */ /* set to 1 so we have no thread behaviour */ -#define NO_SYS 1 +#define NO_SYS 0 /* set to 1 so we can use our own timers */ -#define NO_SYS_NO_TIMERS 1 +#define NO_SYS_NO_TIMERS 0 /*------------------------------------------------------------------------------ @@ -218,7 +252,7 @@ happening sooner than they should. * 4 byte alignment -> #define MEM_ALIGNMENT 4 * 2 byte alignment -> #define MEM_ALIGNMENT 2 */ -#define MEM_ALIGNMENT 1 +#define MEM_ALIGNMENT 4 /** * MEM_SIZE: the size of the heap memory. If the application will send @@ -526,7 +560,7 @@ happening sooner than they should. /** * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) */ -#define LWIP_NETCONN 0 +#define LWIP_NETCONN 1//(NO_SYS==0) /*------------------------------------------------------------------------------ @@ -535,7 +569,8 @@ happening sooner than they should. /** * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) */ -#define LWIP_SOCKET 0 + +#define LWIP_SOCKET 1//(NO_SYS==0) /*------------------------------------------------------------------------------ diff --git a/make-liblwip.mk b/make-liblwip.mk index e79ae4d..cb0dc13 100644 --- a/make-liblwip.mk +++ b/make-liblwip.mk @@ -1,3 +1,5 @@ + + # # Copyright (c) 2001, 2002 Swedish Institute of Computer Science. # All rights reserved. @@ -29,7 +31,7 @@ # Author: Adam Dunkels # -CONTRIBDIR=ext/contrib +CONTRIBDIR=ext/lwip-contrib LWIPARCH=$(CONTRIBDIR)/ports/unix #Set this to where you have the lwip core module checked out from CVS @@ -37,103 +39,44 @@ LWIPARCH=$(CONTRIBDIR)/ports/unix LWIPDIR=ext/lwip/src CCDEP=clang++ - # Automagically pick clang or gcc, with preference for clang # This is only done if we have not overridden these with an environment or CLI variable ifeq ($(origin CCX),default) CCX=$(shell if [ -e /usr/bin/clang++ ]; then echo clang++; else echo g++; fi) endif -CFLAGS=-O3 -g -Wall -fPIC +LWIPINCLUDES:=-I$(LWIPDIR)/include -I$(LWIPARCH) -I$(LWIPDIR) -I. -Iext -Iinclude +CFLAGS=-Wno-format -Wno-deprecated -O3 -g -Wall -fPIC +CFLAGS+=-DLWIP_IPV4 -DLWIP_IPV6=0 -DIPv4 -DLWIP_DEBUG=1 $(LWIPINCLUDES) -CFLAGS:=$(CFLAGS) -I$(LWIPDIR)/include -I$(LWIPARCH)/include -I$(LWIPDIR) -I. -Iext -Iinclude +UNIXLIB=liblwip.a -# COREFILES, CORE4FILES: The minimum set of files needed for lwIP. -COREFILES=$(LWIPDIR)/core/init.c \ - $(LWIPDIR)/core/def.c \ - $(LWIPDIR)/core/dns.c \ - $(LWIPDIR)/core/inet_chksum.c \ - $(LWIPDIR)/core/ip.c \ - $(LWIPDIR)/core/mem.c \ - $(LWIPDIR)/core/memp.c \ - $(LWIPDIR)/core/netif.c \ - $(LWIPDIR)/core/pbuf.c \ - $(LWIPDIR)/core/raw.c \ - $(LWIPDIR)/core/stats.c \ - $(LWIPDIR)/core/sys.c \ - $(LWIPDIR)/core/tcp.c \ - $(LWIPDIR)/core/tcp_in.c \ - $(LWIPDIR)/core/tcp_out.c \ - $(LWIPDIR)/core/timeouts.c \ - $(LWIPDIR)/core/udp.c -CORE4FILES=$(LWIPDIR)/core/ipv4/autoip.c \ - $(LWIPDIR)/core/ipv4/dhcp.c \ - $(LWIPDIR)/core/ipv4/etharp.c \ - $(LWIPDIR)/core/ipv4/icmp.c \ - $(LWIPDIR)/core/ipv4/igmp.c \ - $(LWIPDIR)/core/ipv4/ip4_frag.c \ - $(LWIPDIR)/core/ipv4/ip4.c \ - $(LWIPDIR)/core/ipv4/ip4_addr.c -CORE6FILES=$(LWIPDIR)/core/ipv6/ethip6.c \ - $(LWIPDIR)/core/ipv6/icmp6.c \ - $(LWIPDIR)/core/ipv6/inet6.c \ - $(LWIPDIR)/core/ipv6/ip6.c \ - $(LWIPDIR)/core/ipv6/ip6_addr.c \ - $(LWIPDIR)/core/ipv6/ip6_frag.c \ - $(LWIPDIR)/core/ipv6/mld6.c \ - $(LWIPDIR)/core/ipv6/dhcp6.c \ - $(LWIPDIR)/core/ipv6/nd6.c - # APIFILES: The files which implement the sequential and socket APIs. -APIFILES=$(LWIPDIR)/api/err.c -#$(LWIPDIR)/api/api_lib.c \ - $(LWIPDIR)/api/api_msg.c \ - \ - $(LWIPDIR)/api/netbuf.c \ - $(LWIPDIR)/api/netdb.c \ - $(LWIPDIR)/api/netifapi.c \ - $(LWIPDIR)/api/sockets.c \ - $(LWIPDIR)/api/tcpip.c -# NETIFFILES: Files implementing various generic network interface functions -NETIFFILES=$(LWIPDIR)/netif/ethernet.c -# SIXLOWPAN: 6LoWPAN -SIXLOWPAN=$(LWIPDIR)/netif/lowpan6.c \ -# ARCHFILES: Architecture specific files. -ARCHFILES=$(wildcard $(LWIPARCH)/*.c $(LWIPARCH)tapif.c $(LWIPARCH)/netif/list.c $(LWIPARCH)/netif/tcpdump.c) -# LWIPFILES: All the above. -LWIPFILES=$(COREFILES) $(NETIFFILES) $(ARCHFILES) $(APIFILES) - -ifeq ($(LIBZT_IPV4),1) - LWIPFILES+=$(CORE4FILES) - CFLAGS+=-DLIBZT_IPV4=1 -DLWIP_IPV4 -DLWIP_IPV6=0 -DIPv4 -endif -ifeq ($(LIBZT_IPV6),1) - LWIPFILES+=$(CORE6FILES) - CFLAGS+=-DLIBZT_IPV6=1 -DLWIP_IPV6 -DLWIP_IPV4=0 -DIPv6 -endif -ifeq ($(LWIP_DEBUG),1) - CFLAGS+=-DLWIP_DEBUG=1 -endif - -CFLAGS+=-DLWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS - -LWIPFILESW=$(wildcard $(LWIPFILES)) -LWIPOBJS=$(notdir $(LWIPFILESW:.c=.o)) - -%.o: - $(CXX) $(CFLAGS) -Wno-deprecated -c $(<:.o=.c) -o obj/$@ - -all: +all: $(UNIXLIB) .PHONY: all +include ext/lwip/src/Filelists.mk + +# ARCHFILES: Architecture specific files. +ARCHFILES=$(wildcard $(LWIPARCH)/port/*.c $(LWIPARCH)/*.c $(LWIPARCH)tapif.c $(LWIPARCH)/netif/list.c $(LWIPARCH)/netif/tcpdump.c) + +LWIPNOAPPSFILES+=$(ARCHFILES) +LWIPNOAPPSFILESW=$(wildcard $(LWIPNOAPPSFILES)) +LWIPNOAPPSOBJS=$(notdir $(LWIPNOAPPSFILESW:.c=.o)) + +CCX=clang++ + +%.o: + $(CCX) $(CFLAGS) -c $(<:.o=.c) + clean: - rm -rf .depend - rm -f *.o *.s .depend* *.core core + rm -f *.o $(LWIPNOAPPSOBJS) *.s .depend* *.core core depend dep: .depend + include .depend -liblwip.a: clean $(LWIPOBJS) - #libtool -static -o $@ $^ +$(UNIXLIB): $(LWIPNOAPPSOBJS) + $(CCX) $(CFLAGS) -g -nostartfiles -shared -o $@ $^ -.depend: $(LWIPFILES) - $(CCDEP) $(CFLAGS) -x c -MM $^ > .depend || rm -f .depend \ No newline at end of file +.depend: $(LWIPNOAPPSFILES) + $(CCX) $(CFLAGS) -MM $^ > .depend || rm -f .depend \ No newline at end of file diff --git a/src/Platform.cpp b/src/Platform.cpp new file mode 100644 index 0000000..1146b66 --- /dev/null +++ b/src/Platform.cpp @@ -0,0 +1,68 @@ +/* + * ZeroTier SDK - Network Virtualization Everywhere + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +/** + * @file + * + * Platform-specific implementations of common functions + */ + +#include "Platform.h" +#include +#include + +#ifdef __linux__ +#include +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void handle_general_failure() { +#ifdef ZT_EXIT_ON_GENERAL_FAIL + DEBUG_ERROR("exiting (ZT_EXIT_ON_GENERAL_FAIL==1)"); + exit(-1); +#endif +} + +inline unsigned int gettid() +{ +#ifdef _WIN32 + return GetCurrentThreadId(); +#elif defined(__linux__) + return static_cast(syscall(__NR_gettid)); +#elif defined(__APPLE__) + uint64_t tid64; + pthread_threadid_np(0, &tid64); + return static_cast(tid64); +#endif +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/src/RingBuffer.hpp b/src/RingBuffer.hpp index 3c7d9f0..87e948f 100644 --- a/src/RingBuffer.hpp +++ b/src/RingBuffer.hpp @@ -24,6 +24,12 @@ * of your own application. */ +/** + * @file + * + * Ring buffer implementation for network stack drivers + */ + #ifndef ZT_RINGBUFFER_HPP #define ZT_RINGBUFFER_HPP diff --git a/src/Utilities.cpp b/src/Utilities.cpp index 73a8fc6..b87310d 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -24,6 +24,12 @@ * of your own application. */ +/** + * @file + * + * Misc utilities + */ + #include "InetAddress.hpp" #include "Debug.hpp" @@ -82,26 +88,6 @@ char *beautify_eth_proto_nums(int proto) return (char*)"UNKNOWN"; } -/* -ZeroTier::InetAddress *ztipv6_mask(ZeroTier::InetAddress *addr, unsigned int bits) -{ - ZeroTier::InetAddress r(addr); - switch(r.ss_family) { - case AF_INET: - reinterpret_cast(&r)->sin_addr.s_addr &= ZeroTier::Utils::hton((uint32_t)(0xffffffff << (32 - bits))); - break; - case AF_INET6: { - uint64_t nm[2]; - memcpy(nm,reinterpret_cast(&r)->sin6_addr.s6_addr,16); - nm[0] &= ZeroTier::Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits)))); - nm[1] &= ZeroTier::Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits)))); - memcpy(reinterpret_cast(&r)->sin6_addr.s6_addr,nm,16); - } break; - } - return &r; -} -*/ - bool ipv6_in_subnet(ZeroTier::InetAddress *subnet, ZeroTier::InetAddress *addr) { ZeroTier::InetAddress r(addr); @@ -134,7 +120,6 @@ bool ipv6_in_subnet(ZeroTier::InetAddress *subnet, ZeroTier::InetAddress *addr) return !strcmp(r.toIpString(b0), b.toIpString(b1)); } - void sockaddr2inet(int socket_family, const struct sockaddr *addr, ZeroTier::InetAddress *inet) { char ipstr[INET6_ADDRSTRLEN]; @@ -158,3 +143,24 @@ void mac2str(char *macbuf, int len, unsigned char* addr) snprintf(macbuf, len, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); } + + +/** + * Convert from standard IPV6 address structure to an lwIP native structure + */ +/* +inline void in6_to_ip6(ip6_addr_t *ba, struct sockaddr_in6 *in6) +{ + uint8_t *ip = &(in6->sin6_addr).s6_addr[0]; + IP6_ADDR2(ba, + (((ip[ 0] & 0xffff) << 8) | ((ip[ 1]) & 0xffff)), + (((ip[ 2] & 0xffff) << 8) | ((ip[ 3]) & 0xffff)), + (((ip[ 4] & 0xffff) << 8) | ((ip[ 5]) & 0xffff)), + (((ip[ 6] & 0xffff) << 8) | ((ip[ 7]) & 0xffff)), + (((ip[ 8] & 0xffff) << 8) | ((ip[ 9]) & 0xffff)), + (((ip[10] & 0xffff) << 8) | ((ip[11]) & 0xffff)), + (((ip[12] & 0xffff) << 8) | ((ip[13]) & 0xffff)), + (((ip[14] & 0xffff) << 8) | ((ip[15]) & 0xffff)) + ); +} +*/ \ No newline at end of file diff --git a/src/VirtualBindingPair.cpp b/src/VirtualBindingPair.cpp new file mode 100644 index 0000000..c972ae3 --- /dev/null +++ b/src/VirtualBindingPair.cpp @@ -0,0 +1,51 @@ +/* + * ZeroTier SDK - Network Virtualization Everywhere + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +/** + * @file + * + * + */ + +/* +#include "VirtualSocket.h" +#include "VirtualTap.hpp" + +#ifdef __cplusplus +extern "C" { +#endif + +struct VirtualBindingPair +{ + VirtualTap *tap; + VirtualSocket *vs; + VirtualBindingPair(VirtualTap *_tap, VirtualSocket *_vs) : tap(_tap), vs(_vs) {} +}; + +#ifdef __cplusplus +} +#endif +*/ \ No newline at end of file diff --git a/src/VirtualSocket.cpp b/src/VirtualSocket.cpp new file mode 100644 index 0000000..166473b --- /dev/null +++ b/src/VirtualSocket.cpp @@ -0,0 +1,119 @@ +/* + * ZeroTier SDK - Network Virtualization Everywhere + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +/** + * @file + * + * Platform-agnostic implementation of a socket-like object + */ + +#ifndef ZT_VIRTUALSOCKET_HPP +#define ZT_VIRTUALSOCKET_HPP + +#include +#include + +#include "VirtualSocket.h" +#include "VirtualBindingPair.h" +#include "RingBuffer.hpp" + +#define VS_STATE_INACTIVE 0x000000u // Default value for newly created VirtualSocket +#define VS_STATE_ACTIVE 0x000001u // VirtualSocket is RX'ing or TX'ing without issue +#define VS_STATE_SHOULD_SHUTDOWN 0x000002u // Application, stack driver, or stack marked this VirtualSocket for death +#define VS_STATE_SHUTDOWN 0x000004u // VirtualSocket and underlying protocol control structures will not RX/TX +#define VS_STATE_CLOSED 0x000008u // VirtualSocket and underlying protocol control structures are closed +#define VS_STATE_UNHANDLED_CONNECTED 0x000010u // stack callback has received a connection but we haven't dealt with it +#define VS_STATE_CONNECTED 0x000020u // stack driver has akwnowledged new connection +#define VS_STATE_LISTENING 0x000040u // virtual socket is listening for incoming connections + +#define VS_OPT_TCP_NODELAY 0x000000u // Nagle's algorithm +#define VS_OPT_SO_LINGER 0x000001u // VirtualSocket waits for data transmission before closure +/* +#define VS_RESERVED 0x000002u // +#define VS_RESERVED 0x000004u // +#define VS_RESERVED 0x000008u // +#define VS_RESERVED 0x000010u // +#define VS_RESERVED 0x000020u // +#define VS_RESERVED 0x000040u // +*/ +#define VS_OPT_FD_NONBLOCKING 0x000080u // Whether the VirtualSocket exhibits non-blocking behaviour +/* +#define VS_RESERVED 0x000100u // +#define VS_RESERVED 0x000200u // +#define VS_RESERVED 0x000400u // +#define VS_RESERVED 0x000800u // +#define VS_RESERVED 0x001000u // +#define VS_RESERVED 0x002000u // +#define VS_RESERVED 0x004000u // +#define VS_RESERVED 0x008000u // +#define VS_RESERVED 0x010000u // +#define VS_RESERVED 0x020000u // +#define VS_RESERVED 0x040000u // +#define VS_RESERVED 0x080000u // +#define VS_RESERVED 0x100000u // +#define VS_RESERVED 0x200000u // +#define VS_RESERVED 0x400000u // +#define VS_RESERVED 0x800000u // +*/ + +#define vs_is_nonblocking(vs) (((vs)->optflags & VS_OPT_FD_NONBLOCKING) != 0) + +namespace ZeroTier { + + class VirtualTap; + + class VirtualSocket + { + private: + int _state = VS_STATE_INACTIVE; + public: + + /** + * Sets the VirtualSocket's state value + */ + void apply_state(int state) { + _state &= state; + } + /** + * Sets the VirtualSocket's state value + */ + void set_state(int state) { + _state = state; + } + /** + * Gets the VirtualSocket's state value + */ + int get_state() { + return _state; + } + + VirtualSocket() { + } + ~VirtualSocket() { + } + }; +} +#endif diff --git a/src/VirtualSocket.hpp b/src/VirtualSocket.hpp deleted file mode 100644 index 60e3760..0000000 --- a/src/VirtualSocket.hpp +++ /dev/null @@ -1,236 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -// General connection object used by VirtualTap and network stack drivers - -#ifndef ZT_CONNECTION_HPP -#define ZT_CONNECTION_HPP - -#include -#include - -#if defined(STACK_PICO) -#include "pico_socket.h" -#endif -#if defined(STACK_LWIP) -#include "lwip/tcp.h" -#endif - -#include "Phy.hpp" - -#include "libzt.h" -#include "VirtualTap.hpp" -#include "RingBuffer.hpp" - -#define VS_STATE_INACTIVE 0x000000u // Default value for newly created VirtualSocket -#define VS_STATE_ACTIVE 0x000001u // VirtualSocket is RX'ing or TX'ing without issue -#define VS_STATE_SHOULD_SHUTDOWN 0x000002u // Application, stack driver, or stack marked this VirtualSocket for death -#define VS_STATE_SHUTDOWN 0x000004u // VirtualSocket and underlying protocol control structures will not RX/TX -#define VS_STATE_CLOSED 0x000008u // VirtualSocket and underlying protocol control structures are closed -#define VS_STATE_UNHANDLED_CONNECTED 0x000010u // stack callback has received a connection but we haven't dealt with it -#define VS_STATE_CONNECTED 0x000020u // stack driver has akwnowledged new connection -#define VS_STATE_LISTENING 0x000040u // virtual socket is listening for incoming connections - -#define VS_OPT_TCP_NODELAY 0x000000u // Nagle's algorithm -#define VS_OPT_SO_LINGER 0x000001u // VirtualSocket waits for data transmission before closure -/* -#define VS_RESERVED 0x000002u // -#define VS_RESERVED 0x000004u // -#define VS_RESERVED 0x000008u // -#define VS_RESERVED 0x000010u // -#define VS_RESERVED 0x000020u // -#define VS_RESERVED 0x000040u // -*/ -#define VS_OPT_FD_NONBLOCKING 0x000080u // Whether the VirtualSocket exhibits non-blocking behaviour -/* -#define VS_RESERVED 0x000100u // -#define VS_RESERVED 0x000200u // -#define VS_RESERVED 0x000400u // -#define VS_RESERVED 0x000800u // -#define VS_RESERVED 0x001000u // -#define VS_RESERVED 0x002000u // -#define VS_RESERVED 0x004000u // -#define VS_RESERVED 0x008000u // -#define VS_RESERVED 0x010000u // -#define VS_RESERVED 0x020000u // -#define VS_RESERVED 0x040000u // -#define VS_RESERVED 0x080000u // -#define VS_RESERVED 0x100000u // -#define VS_RESERVED 0x200000u // -#define VS_RESERVED 0x400000u // -#define VS_RESERVED 0x800000u // -*/ - -#define vs_is_nonblocking(vs) (((vs)->optflags & VS_OPT_FD_NONBLOCKING) != 0) - -namespace ZeroTier { - - class VirtualTap; - - /** - * An abstraction of a socket that operates between the application-exposed platform-sockets - * and the network stack's representation of a protocol control structure. This object is used by - * the POSIX socket emulation layer and stack drivers. - */ - class VirtualSocket - { - private: - int _state = VS_STATE_INACTIVE; - public: - RingBuffer *TXbuf; - RingBuffer *RXbuf; - Mutex _tx_m, _rx_m, _op_m; - PhySocket *sock = NULL; - - /** - * Sets the VirtualSocket's state value - */ - void apply_state(int state) { - // states may be set by application or by stack callbacks, thus this must be guarded - _op_m.lock(); - _state &= state; -#if defined (STACK_PICO) - DEBUG_EXTRA("APPLY STATE=%d (state=%d, vs=%p, ps=%p)", _state, state, this, picosock); -#endif -#if defined (STACK_LWIP) - DEBUG_EXTRA("APPLY STATE=%d (state=%d, vs=%p, pcb=%p)", _state, state, this, pcb); -#endif - _op_m.unlock(); - } - /** - * Sets the VirtualSocket's state value - */ - void set_state(int state) { - // states may be set by application or by stack callbacks, thus this must be guarded - _op_m.lock(); - _state = state; -#if defined (STACK_PICO) - DEBUG_EXTRA("SET STATE=%d (state=%d, vs=%p, ps=%p)", _state, state, this, picosock); -#endif -#if defined (STACK_LWIP) - DEBUG_EXTRA("SET STATE=%d (state=%d, vs=%p, pcb=%p)", _state, state, this, pcb); -#endif - _op_m.unlock(); - } - /** - * Gets the VirtualSocket's state value - */ - int get_state() { -#if defined (STACK_PICO) - DEBUG_EXTRA("GET STATE=%d (vs=%p, ps=%p)", _state, this, picosock); -#endif -#if defined (STACK_LWIP) - DEBUG_EXTRA("GET STATE=%d (vs=%p, pcb=%p)", _state, this, pcb); -#endif - return _state; - } -#if defined(STACK_PICO) - struct pico_socket *picosock = NULL; -#endif -#if defined(STACK_LWIP) - int32_t optflags = 0; - int linger; - void *pcb = NULL; // Protocol Control Block - /* - - TCP_WRITE_FLAG_COPY: indicates whether the new memory should be allocated - for the data to be copied into. If this flag is not given, no new memory - should be allocated and the data should only be referenced by pointer. This - also means that the memory behind dataptr must not change until the data is - ACKed by the remote host - - TCP_WRITE_FLAG_MORE: indicates that more data follows. If this is omitted, - the PSH flag is set in the last segment created by this call to tcp_write. - If this flag is given, the PSH flag is not set. - */ - // copy as default, processed via pointer reference if set to 0. See notes in lwip_cb_sent() and lwip_Write() - int8_t copymode = TCP_WRITE_FLAG_COPY; -#endif - - struct sockaddr_storage local_addr; // address we've bound to locally - struct sockaddr_storage peer_addr; // address of connection call to remote host - - int socket_family = 0; - int socket_type = 0; - int protocol = 0; - int app_fd = 0; // used by app for I/O - int sdk_fd = 0; // used by lib for I/O - - std::queue _AcceptedConnections; - VirtualTap *tap = NULL; - - VirtualSocket() { - DEBUG_EXTRA("this=%p",this); - memset(&local_addr, 0, sizeof(sockaddr_storage)); - memset(&peer_addr, 0, sizeof(sockaddr_storage)); - - // ringbuffer used for incoming and outgoing traffic between app, stack, stack drivers, and ZT - TXbuf = new RingBuffer(ZT_TCP_TX_BUF_SZ); - RXbuf = new RingBuffer(ZT_TCP_RX_BUF_SZ); - - // socketpair, I/O channel between app and stack drivers - ZT_PHY_SOCKFD_TYPE fdpair[2]; - if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fdpair) < 0) { - if (errno < 0) { - DEBUG_ERROR("unable to create socketpair, errno=%d", errno); - return; - } - } - sdk_fd = fdpair[0]; - app_fd = fdpair[1]; - - // set to non-blocking since these are used as the primary I/O channel - if (fcntl(sdk_fd, F_SETFL, O_NONBLOCK) < 0) { - DEBUG_ERROR("error while setting virtual socket to NONBLOCKING. exiting", errno); - exit(0); - } - } - ~VirtualSocket() { - DEBUG_EXTRA("this=%p",this); - close(app_fd); - close(sdk_fd); - delete TXbuf; - delete RXbuf; - TXbuf = RXbuf = NULL; -#if defined(STACK_PICO) - picosock->priv = NULL; - picosock = NULL; -#endif -#if defined(STACK_LWIP) - pcb = NULL; -#endif - } - }; - - /** - * A helper object for passing VirtualTap(s) and VirtualSocket(s) through the stack - */ - struct VirtualBindingPair - { - VirtualTap *tap; - VirtualSocket *vs; - VirtualBindingPair(VirtualTap *_tap, VirtualSocket *_vs) : tap(_tap), vs(_vs) {} - }; -} -#endif diff --git a/src/VirtualTap.cpp b/src/VirtualTap.cpp index 0423cf9..09c436a 100644 --- a/src/VirtualTap.cpp +++ b/src/VirtualTap.cpp @@ -24,22 +24,24 @@ * of your own application. */ -#include -#include -#include +/** + * @file + * + * Virtual Ethernet tap device + */ + #include -#include -#include -#include -#include +#include "Phy.hpp" #include "VirtualTap.hpp" + +#include +#include +#include + #include "libzt.h" -#if defined(STACK_PICO) -#include "picoTCP.hpp" -#endif #if defined(STACK_LWIP) #include "lwIP.hpp" #endif @@ -51,15 +53,13 @@ #include #endif -#include "OneService.hpp" +#include "ZT1Service.h" + #include "Utils.hpp" -#include "OSUtils.hpp" +#include "Mutex.hpp" #include "Constants.hpp" -#include "Phy.hpp" - -class VirtualTap; - -extern std::vector vtaps; +#include "InetAddress.hpp" +#include "OneService.hpp" namespace ZeroTier { @@ -92,7 +92,7 @@ namespace ZeroTier { _unixListenSocket((PhySocket *)0), _phy(this,false,true) { - vtaps.push_back((void*)this); + ZeroTier::vtaps.push_back((void*)this); // set virtual tap interface name (full) memset(vtap_full_name, 0, sizeof(vtap_full_name)); @@ -129,40 +129,19 @@ namespace ZeroTier { bool VirtualTap::registerIpWithStack(const InetAddress &ip) { -#if defined(STACK_PICO) - if (picostack) { - picostack->pico_register_address(this, ip); - return true; - } else { - handle_general_failure(); - return false; - } -#endif -#if defined(STACK_LWIP) - if (lwipstack) { - lwipstack->lwip_init_interface(this, ip); - return true; - } else { - handle_general_failure(); - return false; - } -#endif - return false; + DEBUG_EXTRA(); + lwip_driver_init(); + lwip_init_interface((void*)this, this->_mac, ip); + return true; } bool VirtualTap::addIp(const InetAddress &ip) { int err = false; -#if defined(NO_STACK) char ipbuf[INET6_ADDRSTRLEN]; - DEBUG_INFO("addIp (%s)", ip.toString(ipbuf)); - _ips.push_back(ip); - std::sort(_ips.begin(),_ips.end()); - err = true; -#endif -#if defined(STACK_PICO) || defined(STACK_LWIP) - char ipbuf[INET6_ADDRSTRLEN]; - DEBUG_INFO("addIp (%s)", ip.toString(ipbuf)); + DEBUG_EXTRA("addIp (%s)", ip.toString(ipbuf)); + + Mutex::Lock _l(_ips_m); if (registerIpWithStack(ip)) { if (std::find(_ips.begin(),_ips.end(),ip) == _ips.end()) { _ips.push_back(ip); @@ -170,18 +149,17 @@ namespace ZeroTier { } return true; } - err = false; -#endif return err; } bool VirtualTap::removeIp(const InetAddress &ip) { + DEBUG_EXTRA(); Mutex::Lock _l(_ips_m); std::vector::iterator i(std::find(_ips.begin(),_ips.end(),ip)); - if (i == _ips.end()) { - return false; - } + //if (i == _ips.end()) { + // return false; + //} _ips.erase(i); if (ip.isV4()) { // FIXME: De-register from network stacks @@ -201,20 +179,7 @@ namespace ZeroTier { void VirtualTap::put(const MAC &from,const MAC &to,unsigned int etherType, const void *data,unsigned int len) { -#if defined(STACK_PICO) - if (picostack) { - picostack->pico_eth_rx(this,from,to,etherType,data,len); - } else { - handle_general_failure(); - } -#endif -#if defined(STACK_LWIP) - if (lwipstack) { - lwipstack->lwip_eth_rx(this,from,to,etherType,data,len); - } else { - handle_general_failure(); - } -#endif + lwip_eth_rx(this, from, to, etherType, data, len); } std::string VirtualTap::deviceName() const @@ -224,7 +189,6 @@ namespace ZeroTier { std::string VirtualTap::nodeId() const { - // TODO: This is inefficient and awkward, should be replaced with something more elegant if (zt1ServiceRef) { char id[ZT_ID_LEN]; memset(id, 0, sizeof(id)); @@ -238,8 +202,7 @@ namespace ZeroTier { void VirtualTap::setFriendlyName(const char *friendlyName) { - DEBUG_INFO("%s", friendlyName); - // Someday + DEBUG_EXTRA("%s", friendlyName); } void VirtualTap::scanMulticastGroups(std::vector &added, @@ -274,189 +237,64 @@ namespace ZeroTier { void VirtualTap::threadMain() throw() { -#if defined(STACK_PICO) - if (picostack) { - picostack->pico_init_interface(this); - if (should_start_stack) { - // Add link to ipv4_link_add - //ZeroTier::InetAddress localhost; - //localhost.fromString("127.0.0.1"); - //addIp(localhost); // Add a single link to localhost to the picoTCP device (TODO: should be placed elsewhere) - picostack->pico_loop(this); - } - } else { - handle_general_failure(); + DEBUG_EXTRA(); + while (true) { + _phy.poll(ZT_PHY_POLL_INTERVAL); + Housekeeping(); } -#endif -#if defined(STACK_LWIP) - if (lwipstack) - lwipstack->lwip_loop(this); -#endif } void VirtualTap::phyOnUnixClose(PhySocket *sock, void **uptr) { DEBUG_EXTRA(); - /* - int err = 0; - if (sock) { - VirtualSocket *vs = (VirtualSocket*)uptr; - if (vs) { - if (vs->get_state() != VS_STATE_CLOSED && vs->get_state() != VS_STATE_LISTENING) { - DEBUG_EXTRA("vs=%p, vs->get_state()=%d, vs->picosock->state=%d", vs, vs->get_state(), vs->picosock->state); - // doesn't make sense to shut down a listening socket, just close it - if ((err = vs->tap->Shutdown(vs, SHUT_RDWR)) < 0) { - DEBUG_ERROR("error while shutting down socket"); - handle_general_failure(); - return; - } - } - //picostack->pico_Close(vs); - } - } else { - handle_general_failure(); - } - */ } void VirtualTap::phyOnUnixData(PhySocket *sock, void **uptr, void *data, ssize_t len) { DEBUG_EXTRA(); - VirtualSocket *vs = (VirtualSocket*)*uptr; - if (vs == NULL) { - handle_general_failure(); - return; - } - if (len > 0) { - Write(vs, data, len); - } } void VirtualTap::phyOnUnixWritable(PhySocket *sock, void **uptr, bool stack_invoked) { - if (sock) { - Read(sock,uptr,stack_invoked); - } else { - handle_general_failure(); - } + DEBUG_EXTRA(); } - // Adds a route to the virtual tap bool VirtualTap::routeAdd(const InetAddress &addr, const InetAddress &nm, const InetAddress &gw) { -#if defined(NO_STACK) - return false; -#endif -#if defined(STACK_PICO) - if (picostack) { - return picostack->pico_route_add(this, addr, nm, gw, 0); - } else { - handle_general_failure(); - return false; - } -#endif -#if defined(STACK_LWIP) - if (lwipstack) { - // TODO - return true; - } else { - handle_general_failure(); - return false; - } -#endif + DEBUG_EXTRA(); return false; } - // Deletes a route from the virtual tap bool VirtualTap::routeDelete(const InetAddress &addr, const InetAddress &nm) { -#if defined(NO_STACK) - return false; -#endif -#if defined(STACK_PICO) - if (picostack) { - return picostack->pico_route_del(this, addr, nm, 0); - } else { - handle_general_failure(); - return false; - } -#endif -#if defined(STACK_LWIP) - if (lwipstack) { - // TODO - return true; - } else { - handle_general_failure(); - return false; - } -#endif + DEBUG_EXTRA(); return false; } - void VirtualTap::addVirtualSocket(VirtualSocket *vs) + void VirtualTap::addVirtualSocket() { - Mutex::Lock _l(_tcpconns_m); - _VirtualSockets.push_back(vs); + DEBUG_EXTRA(); } - void VirtualTap::removeVirtualSocket(VirtualSocket *vs) + void VirtualTap::removeVirtualSocket() { - Mutex::Lock _l(_tcpconns_m); - for (int i=0; i<_VirtualSockets.size(); i++) { - if (vs == _VirtualSockets[i]) { - _VirtualSockets.erase(_VirtualSockets.begin() + i); - break; - } - } + DEBUG_EXTRA(); } - /****************************************************************************/ /* DNS */ /****************************************************************************/ int VirtualTap::add_DNS_Nameserver(struct sockaddr *addr) { - int err = -1; -#if defined(STACK_PICO) - if (picostack) { - err = picostack->pico_add_dns_nameserver(addr); - } else { - handle_general_failure(); - return -1; - } -#endif -#if defined(STACK_LWIP) - if (lwipstack) { - err = lwipstack->lwip_add_dns_nameserver(addr); - } else { - handle_general_failure(); - return -1; - } -#endif - return err; + DEBUG_EXTRA(); + return -1; } int VirtualTap::del_DNS_Nameserver(struct sockaddr *addr) { - int err = -1; -#if defined(STACK_PICO) - if (picostack) { - err = picostack->pico_del_dns_nameserver(addr); - } else { - handle_general_failure(); - return -1; - } -#endif -#if defined(STACK_LWIP) - if (lwipstack) { - err = lwipstack->lwip_del_dns_nameserver(addr); - } else { - handle_general_failure(); - return -1; - } -#endif - return err; + DEBUG_EXTRA(); + return -1; } /****************************************************************************/ @@ -464,281 +302,66 @@ namespace ZeroTier { /****************************************************************************/ // Connect - int VirtualTap::Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen) + int VirtualTap::Connect(const struct sockaddr *addr, socklen_t addrlen) { - int err = -1; -#if defined(NO_STACK) - return err; -#endif -#if defined(STACK_PICO) - if (picostack) { - Mutex::Lock _l(_tcpconns_m); - err = picostack->pico_Connect(vs, addr, addrlen); - } else { - handle_general_failure(); - return -1; - } -#endif -#if defined(STACK_LWIP) - if (lwipstack) { - err = lwipstack->lwip_Connect(vs, addr, addrlen); - } else { - handle_general_failure(); - return -1; - } -#endif - return err; + DEBUG_EXTRA(); + return -1; } // Bind VirtualSocket to a network stack's interface - int VirtualTap::Bind(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen) + int VirtualTap::Bind(const struct sockaddr *addr, socklen_t addrlen) { -#if defined(NO_STACK) - return -1; -#endif -#if defined(STACK_PICO) - if (picostack) { - Mutex::Lock _l(_tcpconns_m); - return picostack->pico_Bind(vs, addr, addrlen); - } else { - handle_general_failure(); - return -1; - } -#endif -#if defined(STACK_LWIP) - if (lwipstack) { - Mutex::Lock _l(_tcpconns_m); - return lwipstack->lwip_Bind(this, vs, addr, addrlen); - } else { - handle_general_failure(); - return -1; - } -#endif + DEBUG_EXTRA(); return -1; } // Listen for an incoming VirtualSocket - int VirtualTap::Listen(VirtualSocket *vs, int backlog) + int VirtualTap::Listen(int backlog) { - int err = -1; -#if defined(NO_STACK) - return err; -#endif -#if defined(STACK_PICO) - if (picostack) { - Mutex::Lock _l(_tcpconns_m); - return picostack->pico_Listen(vs, backlog); - } else { - handle_general_failure(); - return err; - } -#endif -#if defined(STACK_LWIP) - if (lwipstack) { - Mutex::Lock _l(_tcpconns_m); - err = lwipstack->lwip_Listen(vs, backlog); - } else { - handle_general_failure(); - return err; - } -#endif - return err; + DEBUG_EXTRA(); + return -1; } // Accept a VirtualSocket - VirtualSocket* VirtualTap::Accept(VirtualSocket *vs) + void VirtualTap::Accept() { - VirtualSocket *new_vs = NULL; -#if defined(NO_STACK) - new_vs = NULL; -#endif -#if defined(STACK_PICO) - // TODO: separation of church and state - if (picostack) { - Mutex::Lock _l(_tcpconns_m); - new_vs = picostack->pico_Accept(vs); - } else { - handle_general_failure(); - return NULL; - } -#endif -#if defined(STACK_LWIP) - if (lwipstack) { - Mutex::Lock _l(_tcpconns_m); - new_vs = lwipstack->lwip_Accept(vs); - } else { - handle_general_failure(); - return NULL; - } -#endif - return new_vs; + DEBUG_EXTRA(); } // Read from stack/buffers into the app's socket int VirtualTap::Read(PhySocket *sock,void **uptr,bool stack_invoked) { - int err = -1; -#if defined(NO_STACK) -#endif -#if defined(STACK_PICO) - if (picostack) { - err = picostack->pico_Read(this, sock, (VirtualSocket*)uptr, stack_invoked); - } else { - handle_general_failure(); - return -1; - } -#endif -#if defined(STACK_LWIP) - if (lwipstack) { - err = lwipstack->lwip_Read((VirtualSocket*)*(_phy.getuptr(sock)), stack_invoked); - } else { - handle_general_failure(); - return -1; - } -#endif - return err; + DEBUG_EXTRA(); + return -1; } // Write data from app socket to the virtual wire, either raw over VL2, or via network stack - int VirtualTap::Write(VirtualSocket *vs, void *data, ssize_t len) + int VirtualTap::Write(void *data, ssize_t len) { - DEBUG_EXTRA("vs=%p, fd=%d, data=%p, len=%d", vs, vs->app_fd, data, len); - int err = -1; -#if defined(NO_STACK) -#endif - // VL2, SOCK_RAW, no network stack - if (vs->socket_type == SOCK_RAW) { - struct ether_header *eh = (struct ether_header *) data; - MAC src_mac; - MAC dest_mac; - src_mac.setTo(eh->ether_shost, 6); - dest_mac.setTo(eh->ether_dhost, 6); - _handler(_arg,NULL,_nwid,src_mac,dest_mac, Utils::ntoh((uint16_t)eh->ether_type),0, ((char*)data) + sizeof(struct ether_header),len - sizeof(struct ether_header)); - return len; - } -#if defined(STACK_PICO) - if (picostack) { - err = picostack->pico_Write(vs, data, len); - } else { - handle_general_failure(); - return -1; - } -#endif -#if defined(STACK_LWIP) - if (lwipstack) { - err = lwipstack->lwip_Write(vs, data, len); - } else { - handle_general_failure(); - return -1; - } -#endif - return err; + DEBUG_EXTRA("data=%p, len=%d", data, len); + return -1; } // Send data to a specified host - int VirtualTap::SendTo(VirtualSocket *vs, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen) + int VirtualTap::SendTo(const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen) { - /* FIXME: There is a call to *_Connect for each send, we should probably figure out a better way to do this, - possibly consult the stack for "connection" state */ - // TODO: flags - int err = -1; -#if defined(STACK_PICO) - if (picostack) { - if ((err = picostack->pico_Connect(vs, addr, addrlen)) < 0) { // implicit - errno = ENOTCONN; - return err; - } - if ((err = picostack->pico_Write(vs, (void*)buf, len)) < 0) { - errno = ENOBUFS; // TODO: translate pico err to something more useful - return err; - } - } else { - handle_general_failure(); - return -1; - } -#endif -#if defined(STACK_LWIP) - if (lwipstack) { - if ((err = lwipstack->lwip_Connect(vs, addr, addrlen)) < 0) { // implicit - return err; - } - if ((err = lwipstack->lwip_Write(vs, (void*)buf, len)) < 0) { - return err; - } - } else { - handle_general_failure(); - return -1; - } -#endif - return err; + DEBUG_EXTRA(); + return -1; } // Remove VritualSocket from VirtualTap, and instruct network stacks to dismantle their // respective protocol control structures - int VirtualTap::Close(VirtualSocket *vs) + int VirtualTap::Close() { - int err = 0; - if (vs == NULL) { - DEBUG_ERROR("invalid VirtualSocket"); - handle_general_failure(); - return -1; - } - if (vs->sock) { - DEBUG_EXTRA("calling _phy.close()"); - _phy.close(vs->sock, true); - } - removeVirtualSocket(vs); -#if defined(STACK_PICO) - if (vs->get_state() != VS_STATE_CLOSED && vs->get_state() != VS_STATE_LISTENING) { - DEBUG_EXTRA("vs=%p, vs->get_state()=%d, vs->picosock->state=%d", vs, vs->get_state(), vs->picosock->state); - // doesn't make sense to shut down a listening socket, just close it - if ((err = vs->tap->Shutdown(vs, SHUT_RDWR)) < 0) { - DEBUG_ERROR("error while shutting down socket"); - handle_general_failure(); - return - 1; - } - } - picostack->pico_Close(vs); - removeVirtualSocket(vs); - if (vs->socket_type == SOCK_STREAM) { - while (!(vs->picosock->state & PICO_SOCKET_STATE_CLOSED)) { - nanosleep((const struct timespec[]) {{0, (ZT_ACCEPT_RECHECK_DELAY * 1000000)}}, NULL); - DEBUG_EXTRA("virtual lingering on socket, ps=%p, buf remaining=%d",vs->picosock, vs->TXbuf->count()); - } - } -#endif -#if defined(STACK_LWIP) - if (lwipstack) { - err = lwipstack->lwip_Close(vs); - } else { - handle_general_failure(); - return -1; - } -#endif - return err; + DEBUG_EXTRA(); + return -1; } // Shuts down some aspect of a connection (Read/Write) - int VirtualTap::Shutdown(VirtualSocket *vs, int how) + int VirtualTap::Shutdown(int how) { - int err = 0; -#if defined(STACK_PICO) - if (picostack) { - err = picostack->pico_Shutdown(vs, how); - } else { - handle_general_failure(); - return -1; - } -#endif -#if defined(STACK_LWIP) - if (lwipstack) { - err = lwipstack->lwip_Shutdown(vs, how); - } else { - handle_general_failure(); - return -1; - } -#endif - return err; + DEBUG_EXTRA(); + return -1; } void VirtualTap::Housekeeping() @@ -746,7 +369,7 @@ namespace ZeroTier { Mutex::Lock _l(_tcpconns_m); std::time_t current_ts = std::time(nullptr); if (current_ts > last_housekeeping_ts + ZT_HOUSEKEEPING_INTERVAL) { - // DEBUG_EXTRA(); + DEBUG_EXTRA(); // update managed routes (add/del from network stacks) ZeroTier::OneService *service = ((ZeroTier::OneService *)zt1ServiceRef); if (service) { @@ -800,7 +423,6 @@ namespace ZeroTier { } } } - // TODO: Clean up VirtualSocket objects last_housekeeping_ts = std::time(nullptr); } @@ -819,5 +441,4 @@ namespace ZeroTier { void VirtualTap::phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len) {} void VirtualTap::phyOnTcpWritable(PhySocket *sock,void **uptr) {} -} // namespace ZeroTier - +} // namespace ZeroTier \ No newline at end of file diff --git a/src/VirtualTap.hpp b/src/VirtualTap.hpp index 000caac..bae984b 100644 --- a/src/VirtualTap.hpp +++ b/src/VirtualTap.hpp @@ -24,45 +24,23 @@ * of your own application. */ +/** + * @file + * + * Virtual Ethernet tap device + */ + #ifndef ZT_VIRTUALTAP_HPP #define ZT_VIRTUALTAP_HPP -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include -#include "Constants.hpp" -#include "MulticastGroup.hpp" #include "Mutex.hpp" +#include "MulticastGroup.hpp" #include "InetAddress.hpp" #include "Thread.hpp" #include "Phy.hpp" -#include "libzt.h" -#include "VirtualSocket.hpp" - -#if defined(STACK_PICO) -#include "picoTCP.hpp" -#include "pico_protocol.h" -#include "pico_stack.h" -#include "pico_ipv4.h" -#include "pico_icmp4.h" -#include "pico_dev_tap.h" -#include "pico_protocol.h" -#include "pico_device.h" -#include "pico_ipv6.h" -#endif -#if defined(STACK_LWIP) -#include "lwip/netif.h" -struct netif; -#endif - namespace ZeroTier { /** @@ -175,12 +153,12 @@ namespace ZeroTier { /** * Assign a VirtualSocket to the VirtualTap */ - void addVirtualSocket(VirtualSocket *vs); + void addVirtualSocket(); /** * Remove a VirtualSocket from the VirtualTap */ - void removeVirtualSocket(VirtualSocket *vs); + void removeVirtualSocket(); /****************************************************************************/ /* DNS */ @@ -200,22 +178,6 @@ namespace ZeroTier { /* Vars */ /****************************************************************************/ -#if defined(STACK_PICO) - bool should_start_stack = false; - struct pico_device *picodev = NULL; - - /****************************************************************************/ - /* Guarded RX Frame Buffer for picoTCP */ - /****************************************************************************/ - - unsigned char pico_frame_rxbuf[MAX_PICO_FRAME_RX_BUF_SZ]; - int pico_frame_rxbuf_tot = 0; - Mutex _pico_frame_rxbuf_m; -#endif -#if defined(STACK_LWIP) - netif lwipdev; - netif lwipdev6; -#endif std::vector> routes; void *zt1ServiceRef = NULL; @@ -238,7 +200,7 @@ namespace ZeroTier { PhySocket *_unixListenSocket; Phy _phy; - std::vector _VirtualSockets; + //std::vector _VirtualSockets; Thread _thread; std::string _dev; // path to Unix domain socket @@ -261,22 +223,22 @@ namespace ZeroTier { /** * Connect to a remote host via the userspace stack interface associated with this VirtualTap */ - int Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen); + int Connect( const struct sockaddr *addr, socklen_t addrlen); /** * Bind to the userspace stack interface associated with this VirtualTap */ - int Bind(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen); + int Bind(const struct sockaddr *addr, socklen_t addrlen); /** * Listen for a VirtualSocket */ - int Listen(VirtualSocket *vs, int backlog); + int Listen(int backlog); /** * Accepts an incoming VirtualSocket */ - VirtualSocket* Accept(VirtualSocket *vs); + void Accept(); /** * Move data from RX buffer to application's "socket" @@ -286,22 +248,22 @@ namespace ZeroTier { /** * Move data from application's "socket" into network stack */ - int Write(VirtualSocket *vs, void *data, ssize_t len); + int Write(void *data, ssize_t len); /** * Send data to specified host */ - int SendTo(VirtualSocket *vs, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen); + int SendTo(const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen); /** * Closes a VirtualSocket */ - int Close(VirtualSocket *vs); + int Close(); /** * Shuts down some aspect of a VirtualSocket */ - int Shutdown(VirtualSocket *vs, int how); + int Shutdown(int how); /** * Disposes of previously-closed VirtualSockets diff --git a/src/ZT1Service.cpp b/src/ZT1Service.cpp new file mode 100644 index 0000000..ae5b8ac --- /dev/null +++ b/src/ZT1Service.cpp @@ -0,0 +1,508 @@ +/* + * ZeroTier SDK - Network Virtualization Everywhere + * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +/** + * @file + * + * ZeroTier One service control wrapper + */ + +#include "ZT1Service.h" + +#include "Debug.hpp" + +#include "Phy.hpp" +#include "OneService.hpp" +#include "Utilities.h" +#include "OSUtils.hpp" + +#ifdef __cplusplus +extern "C" { +#endif + +namespace ZeroTier { + std::vector vtaps; + + static ZeroTier::OneService *zt1Service; + + std::string homeDir; // Platform-specific dir we *must* use internally + std::string netDir; // Where network .conf files are to be written + + ZeroTier::Mutex _vtaps_lock; + ZeroTier::Mutex _multiplexer_lock; +} + +/****************************************************************************/ +/* ZeroTier Core helper functions for libzt - DON'T CALL THESE DIRECTLY */ +/****************************************************************************/ + +std::vector *zts_get_network_routes(char *nwid) +{ + uint64_t nwid_int = strtoull(nwid, NULL, 16); + return ZeroTier::zt1Service->getRoutes(nwid_int); +} + +ZeroTier::VirtualTap *getTapByNWID(uint64_t nwid) +{ + ZeroTier::_vtaps_lock.lock(); + ZeroTier::VirtualTap *s, *tap = nullptr; + for (int i=0; i_nwid == nwid) { tap = s; } + } + ZeroTier::_vtaps_lock.unlock(); + return tap; +} + +ZeroTier::VirtualTap *getTapByAddr(ZeroTier::InetAddress *addr) +{ + ZeroTier::_vtaps_lock.lock(); + ZeroTier::VirtualTap *s, *tap = nullptr; + //char ipbuf[64], ipbuf2[64], ipbuf3[64]; + for (int i=0; i_ips.size(); j++) { + if ((s->_ips[j].isV4() && addr->isV4()) || (s->_ips[j].isV6() && addr->isV6())) { + //DEBUG_EXTRA("looking at tap %s, --- for <%s>", s->_dev.c_str(), s->_ips[j].toString(ipbuf), addr->toIpString(ipbuf2)); + if (s->_ips[j].isEqualPrefix(addr) + || s->_ips[j].ipsEqual(addr) + || s->_ips[j].containsAddress(addr) + || (addr->isV6() && ipv6_in_subnet(&s->_ips[j], addr)) + ) + { + //DEBUG_EXTRA("selected tap %s, ", s->_dev.c_str(), s->_ips[j].toString(ipbuf)); + ZeroTier::_vtaps_lock.unlock(); + return s; + } + } + } + // check managed routes + if (tap == NULL) { + std::vector *managed_routes = ZeroTier::zt1Service->getRoutes(s->_nwid); + ZeroTier::InetAddress target, nm, via; + for (int i=0; isize(); i++) { + target = managed_routes->at(i).target; + nm = target.netmask(); + via = managed_routes->at(i).via; + if (target.containsAddress(addr)) { + //DEBUG_EXTRA("chose tap with route ", target.toString(ipbuf), nm.toString(ipbuf2), via.toString(ipbuf3)); + ZeroTier::_vtaps_lock.unlock(); + return s; + } + } + } + } + ZeroTier::_vtaps_lock.unlock(); + return tap; +} + +ZeroTier::VirtualTap *getTapByName(char *ifname) +{ + ZeroTier::_vtaps_lock.lock(); + ZeroTier::VirtualTap *s, *tap = nullptr; + for (int i=0; i_dev.c_str(), ifname) == false) { + tap = s; + } + } + ZeroTier::_vtaps_lock.unlock(); + return tap; +} + +ZeroTier::VirtualTap *getTapByIndex(int index) +{ + ZeroTier::_vtaps_lock.lock(); + ZeroTier::VirtualTap *s, *tap = nullptr; + for (int i=0; iifindex == index) { + tap = s; + } + } + ZeroTier::_vtaps_lock.unlock(); + return tap; +} + +ZeroTier::VirtualTap *getAnyTap() +{ + ZeroTier::_vtaps_lock.lock(); + ZeroTier::VirtualTap *vtap = NULL; + if (ZeroTier::vtaps.size()) { + vtap = (ZeroTier::VirtualTap *)ZeroTier::vtaps[0]; + } + ZeroTier::_vtaps_lock.unlock(); + return vtap; +} + +int zts_get_device_id_from_file(const char *filepath, char *devID) { + std::string fname("identity.public"); + std::string fpath(filepath); + if (ZeroTier::OSUtils::fileExists((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),false)) { + std::string oldid; + ZeroTier::OSUtils::readFile((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),oldid); + memcpy(devID, oldid.c_str(), 10); // first 10 bytes of file + return 0; + } + return -1; +} + +// Starts a ZeroTier service in the background +void *zts_start_service(void *thread_id) +{ + DEBUG_INFO("homeDir=%s", ZeroTier::homeDir.c_str()); + // Where network .conf files will be stored + ZeroTier::netDir = ZeroTier::homeDir + "/networks.d"; + ZeroTier::zt1Service = (ZeroTier::OneService *)0; + // Construct path for network config and supporting service files + if (ZeroTier::homeDir.length()) { + std::vector hpsp(ZeroTier::OSUtils::split(ZeroTier::homeDir.c_str(), ZT_PATH_SEPARATOR_S,"","")); + std::string ptmp; + if (ZeroTier::homeDir[0] == ZT_PATH_SEPARATOR) { + ptmp.push_back(ZT_PATH_SEPARATOR); + } + for (std::vector::iterator pi(hpsp.begin());pi!=hpsp.end();++pi) { + if (ptmp.length() > 0) { + ptmp.push_back(ZT_PATH_SEPARATOR); + } + ptmp.append(*pi); + if ((*pi != ".")&&(*pi != "..")) { + if (ZeroTier::OSUtils::mkdir(ptmp) == false) { + DEBUG_ERROR("home path does not exist, and could not create"); + handle_general_failure(); + perror("error\n"); + } + } + } + } + else { + DEBUG_ERROR("homeDir is empty, could not construct path"); + handle_general_failure(); + return NULL; + } + + // Generate random port for new service instance + unsigned int randp = 0; + ZeroTier::Utils::getSecureRandom(&randp,sizeof(randp)); + // TODO: Better port random range selection + int servicePort = 9000 + (randp % 1000); + for (;;) { + ZeroTier::zt1Service = ZeroTier::OneService::newInstance(ZeroTier::homeDir.c_str(),servicePort); + switch(ZeroTier::zt1Service->run()) { + case ZeroTier::OneService::ONE_STILL_RUNNING: + case ZeroTier::OneService::ONE_NORMAL_TERMINATION: + break; + case ZeroTier::OneService::ONE_UNRECOVERABLE_ERROR: + DEBUG_ERROR("ZTO service port = %d", servicePort); + DEBUG_ERROR("fatal error: %s",ZeroTier::zt1Service->fatalErrorMessage().c_str()); + break; + case ZeroTier::OneService::ONE_IDENTITY_COLLISION: { + delete ZeroTier::zt1Service; + ZeroTier::zt1Service = (ZeroTier::OneService *)0; + std::string oldid; + ZeroTier::OSUtils::readFile((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S + + "identity.secret").c_str(),oldid); + if (oldid.length()) { + ZeroTier::OSUtils::writeFile((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S + + "identity.secret.saved_after_collision").c_str(),oldid); + ZeroTier::OSUtils::rm((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S + + "identity.secret").c_str()); + ZeroTier::OSUtils::rm((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S + + "identity.public").c_str()); + } + } + continue; // restart! + } + break; // terminate loop -- normally we don't keep restarting + } + delete ZeroTier::zt1Service; + ZeroTier::zt1Service = (ZeroTier::OneService *)0; + return NULL; +} + +void disableTaps() +{ + ZeroTier::_vtaps_lock.lock(); + for (int i=0; i_enabled = false; + } + ZeroTier::_vtaps_lock.unlock(); +} + +void zts_get_ipv4_address(const char *nwid, char *addrstr, const int addrlen) +{ + if (ZeroTier::zt1Service) { + uint64_t nwid_int = strtoull(nwid, NULL, 16); + ZeroTier::VirtualTap *tap = getTapByNWID(nwid_int); + if (tap && tap->_ips.size()) { + for (int i=0; i_ips.size(); i++) { + if (tap->_ips[i].isV4()) { + char ipbuf[INET_ADDRSTRLEN]; + std::string addr = tap->_ips[i].toString(ipbuf); + int len = addrlen < addr.length() ? addrlen : addr.length(); + memset(addrstr, 0, len); + memcpy(addrstr, addr.c_str(), len); + return; + } + } + } + } + else + memcpy(addrstr, "\0", 1); +} + +void zts_get_ipv6_address(const char *nwid, char *addrstr, const int addrlen) +{ + if (ZeroTier::zt1Service) { + uint64_t nwid_int = strtoull(nwid, NULL, 16); + ZeroTier::VirtualTap *tap = getTapByNWID(nwid_int); + if (tap && tap->_ips.size()) { + for (int i=0; i_ips.size(); i++) { + if (tap->_ips[i].isV6()) { + char ipbuf[INET6_ADDRSTRLEN]; + std::string addr = tap->_ips[i].toString(ipbuf); + int len = addrlen < addr.length() ? addrlen : addr.length(); + memset(addrstr, 0, len); + memcpy(addrstr, addr.c_str(), len); + return; + } + } + } + } + else + memcpy(addrstr, "\0", 1); +} + +int zts_has_ipv4_address(const char *nwid) +{ + char ipv4_addr[INET_ADDRSTRLEN]; + memset(ipv4_addr, 0, INET_ADDRSTRLEN); + zts_get_ipv4_address(nwid, ipv4_addr, INET_ADDRSTRLEN); + return strcmp(ipv4_addr, "\0"); +} + +int zts_has_ipv6_address(const char *nwid) +{ + char ipv6_addr[INET6_ADDRSTRLEN]; + memset(ipv6_addr, 0, INET6_ADDRSTRLEN); + zts_get_ipv6_address(nwid, ipv6_addr, INET6_ADDRSTRLEN); + return strcmp(ipv6_addr, "\0"); +} + +int zts_has_address(const char *nwid) +{ + return zts_has_ipv4_address(nwid) || zts_has_ipv6_address(nwid); +} + + +void zts_get_6plane_addr(char *addr, const char *nwid, const char *devID) +{ + ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv66plane( + ZeroTier::Utils::hexStrToU64(nwid),ZeroTier::Utils::hexStrToU64(devID)); + char ipbuf[INET6_ADDRSTRLEN]; + memcpy(addr, _6planeAddr.toIpString(ipbuf), 40); +} + +void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID) +{ + ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv6rfc4193( + ZeroTier::Utils::hexStrToU64(nwid),ZeroTier::Utils::hexStrToU64(devID)); + char ipbuf[INET6_ADDRSTRLEN]; + memcpy(addr, _6planeAddr.toIpString(ipbuf), 40); +} + +void zts_join(const char * nwid) { + if (ZeroTier::zt1Service) { + std::string confFile = ZeroTier::zt1Service->givenHomePath() + "/networks.d/" + nwid + ".conf"; + if (ZeroTier::OSUtils::mkdir(ZeroTier::netDir) == false) { + DEBUG_ERROR("unable to create: %s", ZeroTier::netDir.c_str()); + handle_general_failure(); + } + if (ZeroTier::OSUtils::writeFile(confFile.c_str(), "") == false) { + DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str()); + handle_general_failure(); + } + ZeroTier::zt1Service->join(nwid); + } + // provide ZTO service reference to virtual taps + // TODO: This might prove to be unreliable, but it works for now + for (int i=0;izt1ServiceRef=(void*)ZeroTier::zt1Service; + } +} + +void zts_join_soft(const char * filepath, const char * nwid) { + std::string net_dir = std::string(filepath) + "/networks.d/"; + std::string confFile = net_dir + std::string(nwid) + ".conf"; + if (ZeroTier::OSUtils::mkdir(net_dir) == false) { + DEBUG_ERROR("unable to create: %s", net_dir.c_str()); + handle_general_failure(); + } + if (ZeroTier::OSUtils::fileExists(confFile.c_str(), false) == false) { + if (ZeroTier::OSUtils::writeFile(confFile.c_str(), "") == false) { + DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str()); + handle_general_failure(); + } + } +} + +void zts_leave(const char * nwid) { + if (ZeroTier::zt1Service) { + ZeroTier::zt1Service->leave(nwid); + } +} + +void zts_leave_soft(const char * filepath, const char * nwid) { + std::string net_dir = std::string(filepath) + "/networks.d/"; + ZeroTier::OSUtils::rm((net_dir + nwid + ".conf").c_str()); +} + +int zts_running() { + return ZeroTier::zt1Service == NULL ? false : ZeroTier::zt1Service->isRunning(); +} + +void zts_start(const char *path) +{ + if (ZeroTier::zt1Service) { + return; + } + if (path) { + ZeroTier::homeDir = path; + } + pthread_t service_thread; + pthread_create(&service_thread, NULL, zts_start_service, NULL); +} + +void zts_simple_start(const char *path, const char *nwid) +{ + zts_start(path); + while (zts_running() == false) { + DEBUG_EXTRA("waiting for service to start"); + nanosleep((const struct timespec[]) {{0, (ZTO_WRAPPER_CHECK_INTERVAL * 1000000)}}, NULL); + } + while (true) { + DEBUG_EXTRA("trying join"); + try { + zts_join(nwid); + DEBUG_EXTRA("joined"); + break; + } + catch( ... ) { + DEBUG_ERROR("there was a problem joining the virtual network"); + handle_general_failure(); + } + } + DEBUG_EXTRA("waiting for addresss"); + while (zts_has_address(nwid) == false) { + nanosleep((const struct timespec[]) {{0, (ZTO_WRAPPER_CHECK_INTERVAL * 1000000)}}, NULL); + } +} + +void zts_stop() { + if (ZeroTier::zt1Service) { + ZeroTier::zt1Service->terminate(); + disableTaps(); + } +} + +void zts_get_homepath(char *homePath, int len) { + if (ZeroTier::homeDir.length()) { + memset(homePath, 0, len); + int buf_len = len < ZeroTier::homeDir.length() ? len : ZeroTier::homeDir.length(); + memcpy(homePath, ZeroTier::homeDir.c_str(), buf_len); + } +} + +void zts_core_version(char *ver) { + int major, minor, revision; + ZT_version(&major, &minor, &revision); + sprintf(ver, "%d.%d.%d", major, minor, revision); +} + +void zts_lib_version(char *ver) { + //sprintf(ver, "%d.%d.%d", ZT_LIB_VERSION_MAJOR, ZT_LIB_VERSION_MINOR, ZT_LIB_VERSION_REVISION); +} + +int zts_get_device_id(char *devID) { + if (ZeroTier::zt1Service) { + char id[ZTO_ID_LEN]; + sprintf(id, "%lx",ZeroTier::zt1Service->getNode()->address()); + memcpy(devID, id, ZTO_ID_LEN); + return 0; + } + else // Service isn't online, try to read ID from file + { + std::string fname("identity.public"); + std::string fpath(ZeroTier::homeDir); + if (ZeroTier::OSUtils::fileExists((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),false)) { + std::string oldid; + ZeroTier::OSUtils::readFile((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),oldid); + memcpy(devID, oldid.c_str(), ZTO_ID_LEN); // first 10 bytes of file + return 0; + } + } + return -1; +} + +unsigned long zts_get_peer_count() { + if (ZeroTier::zt1Service) { + return ZeroTier::zt1Service->getNode()->peers()->peerCount; + } + else { + return 0; + } +} + +int zts_get_peer_address(char *peer, const char *devID) { + if (ZeroTier::zt1Service) { + ZT_PeerList *pl = ZeroTier::zt1Service->getNode()->peers(); + // uint64_t addr; + for (int i=0; ipeerCount; i++) { + // ZT_Peer *p = &(pl->peers[i]); + // DEBUG_INFO("peer[%d] = %lx", i, p->address); + } + return pl->peerCount; + } + else + return -1; +} + +void zts_enable_http_control_plane() +{ + // TODO +} + +void zts_disable_http_control_plane() +{ + // TODO +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/src/libzt.cpp b/src/libzt.cpp index d2e9928..d1a0245 100644 --- a/src/libzt.cpp +++ b/src/libzt.cpp @@ -24,759 +24,97 @@ * of your own application. */ -/* This file implements the libzt library API, it talks to the network -stack driver and core ZeroTier service to create a socket-like interface -for applications to use. See also: include/libzt.h */ +/** + * @file + * + * Application-facing, partially-POSIX-compliant socket API + */ -#include -#include -#include -#include -#include -#include -#include -#include +#include -#if defined(__APPLE__) -#include -#include -#endif -#if defined(__linux__) -#include -#include -#include -#include -#include -#endif +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include "lwip/ip_addr.h" -#include -#include -#include -#include -#include -#include -#include - -#if defined(STACK_PICO) -#include "pico_stack.h" -#endif -#if defined(STACK_LWIP) -#include "lwIP.hpp" -#endif - -#include "OneService.hpp" -#include "Utils.hpp" -#include "OSUtils.hpp" -#include "InetAddress.hpp" -#include "ZeroTierOne.h" - -#include "Utilities.hpp" -#include "VirtualTap.hpp" #include "libzt.h" - - #ifdef __cplusplus extern "C" { #endif -namespace ZeroTier { +void sys2lwip(int fd, const struct sockaddr *orig, struct sockaddr *modified) { + + /* Inelegant fix for lwIP 'sequential' API address error check (in sockets.c). For some reason + lwIP seems to lose track of the sa_family for the socket internally, when lwip_connect() + is called, it thus receives an AF_UNSPEC socket which fails. Here we use lwIP's own facilities + to get the sa_family ourselves and rebuild the address structure and pass it to lwip_connect(). + I suspect this is due to a struct memory alignment issue. */ - /** - * Reference to core ZeroTier One service - */ - static ZeroTier::OneService *zt1Service; - - std::string homeDir; // Platform-specific dir we *must* use internally - std::string netDir; // Where network .conf files are to be written - -#if defined(STACK_PICO) - /** - * Reference to picoTCP network stack - */ - picoTCP *picostack = NULL; -#endif -#if defined(STACK_LWIP) - /** - * Reference to lwIP network stack - */ - lwIP *lwipstack = NULL; -#endif - - /** - * Set of VirtualSocket objects that have been created but not bound to a VirtualTap interface object yet. - */ - std::map unmap; - - /** - * Map of VirtualSocket objects to their respective VirtualTap objects. These have undergone bind(), or - * connected by use of a route associated with a specific VirtualTap. - */ - std::map*> fdmap; - - /** - * Set of all VirtualTap interface objects that exist. One per virtual network. - */ - std::vector vtaps; - - ZeroTier::Mutex _vtaps_lock; - ZeroTier::Mutex _multiplexer_lock; -} - -/****************************************************************************/ -/* SDK Socket API - Language Bindings are written in terms of these */ -/****************************************************************************/ - -void zts_start(const char *path) -{ - if (ZeroTier::zt1Service) { + struct sockaddr_storage ss; + socklen_t namelen = sizeof(ss); + int err = 0; + if ((err = lwip_getsockname(fd, (struct sockaddr*)&ss, &namelen)) < 0) { + DEBUG_ERROR("error while determining socket family"); return; } -#if defined(STACK_PICO) - if (ZeroTier::picostack) { - return; - } - ZeroTier::picostack = new ZeroTier::picoTCP(); - pico_stack_init(); + + if (ss.ss_family == AF_INET) { +#if defined(__linux__) + struct sockaddr_in *modified_ptr = (struct sockaddr_in *)modified; + struct sockaddr_in *addr4 = (struct sockaddr_in*)orig; + modified_ptr->sin_len = sizeof(struct sockaddr_in); + modified_ptr->sin_family = ss.ss_family; + modified_ptr->sin_port = addr4->sin_port; + modified_ptr->sin_addr.s_addr = addr4->sin_addr.s_addr; +#else + memcpy(modified, orig, sizeof(struct sockaddr_in)); #endif -#if defined(STACK_LWIP) - ZeroTier::lwipstack = new ZeroTier::lwIP(); - lwip_init(); + } + if (ss.ss_family == AF_INET) { +#if defined(__linux__) +#else #endif - if (path) { - ZeroTier::homeDir = path; } - pthread_t service_thread; - pthread_create(&service_thread, NULL, zts_start_service, NULL); } -void zts_simple_start(const char *path, const char *nwid) +int zts_socket(int socket_family, int socket_type, int protocol) { - zts_start(path); - while (zts_running() == false) { - nanosleep((const struct timespec[]) {{0, (ZT_API_CHECK_INTERVAL * 1000000)}}, NULL); - } - while (true) { - try { - zts_join(nwid); - break; - } - catch( ... ) { - DEBUG_ERROR("there was a problem joining the virtual network"); - handle_general_failure(); - } - } - while (zts_has_address(nwid) == false) { - nanosleep((const struct timespec[]) {{0, (ZT_API_CHECK_INTERVAL * 1000000)}}, NULL); - } + DEBUG_EXTRA("family=%d, type=%d, proto=%d", socket_family, socket_type, protocol); + return lwip_socket(socket_family, socket_type, protocol); } -void zts_stop() { - if (ZeroTier::zt1Service) { - ZeroTier::zt1Service->terminate(); - disableTaps(); - } -} - -void zts_join(const char * nwid) { - if (ZeroTier::zt1Service) { - std::string confFile = ZeroTier::zt1Service->givenHomePath() + "/networks.d/" + nwid + ".conf"; - if (ZeroTier::OSUtils::mkdir(ZeroTier::netDir) == false) { - DEBUG_ERROR("unable to create: %s", ZeroTier::netDir.c_str()); - handle_general_failure(); - } - if (ZeroTier::OSUtils::writeFile(confFile.c_str(), "") == false) { - DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str()); - handle_general_failure(); - } - ZeroTier::zt1Service->join(nwid); - } - // provide ZTO service reference to virtual taps - // TODO: This might prove to be unreliable, but it works for now - for (int i=0;izt1ServiceRef=(void*)ZeroTier::zt1Service; - } -} - -void zts_join_soft(const char * filepath, const char * nwid) { - std::string net_dir = std::string(filepath) + "/networks.d/"; - std::string confFile = net_dir + std::string(nwid) + ".conf"; - if (ZeroTier::OSUtils::mkdir(net_dir) == false) { - DEBUG_ERROR("unable to create: %s", net_dir.c_str()); - handle_general_failure(); - } - if (ZeroTier::OSUtils::fileExists(confFile.c_str(), false) == false) { - if (ZeroTier::OSUtils::writeFile(confFile.c_str(), "") == false) { - DEBUG_ERROR("unable to write network conf file: %s", confFile.c_str()); - handle_general_failure(); - } - } -} - -void zts_leave(const char * nwid) { - if (ZeroTier::zt1Service) { - ZeroTier::zt1Service->leave(nwid); - } -} - -void zts_leave_soft(const char * filepath, const char * nwid) { - std::string net_dir = std::string(filepath) + "/networks.d/"; - ZeroTier::OSUtils::rm((net_dir + nwid + ".conf").c_str()); -} - -void zts_get_homepath(char *homePath, int len) { - if (ZeroTier::homeDir.length()) { - memset(homePath, 0, len); - int buf_len = len < ZeroTier::homeDir.length() ? len : ZeroTier::homeDir.length(); - memcpy(homePath, ZeroTier::homeDir.c_str(), buf_len); - } -} - -void zts_core_version(char *ver) { - int major, minor, revision; - ZT_version(&major, &minor, &revision); - sprintf(ver, "%d.%d.%d", major, minor, revision); -} - -void zts_lib_version(char *ver) { - sprintf(ver, "%d.%d.%d", ZT_LIB_VERSION_MAJOR, ZT_LIB_VERSION_MINOR, ZT_LIB_VERSION_REVISION); -} - -int zts_get_device_id(char *devID) { - if (ZeroTier::zt1Service) { - char id[ZT_ID_LEN]; - sprintf(id, "%lx",ZeroTier::zt1Service->getNode()->address()); - memcpy(devID, id, ZT_ID_LEN); - return 0; - } - else // Service isn't online, try to read ID from file - { - std::string fname("identity.public"); - std::string fpath(ZeroTier::homeDir); - if (ZeroTier::OSUtils::fileExists((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),false)) { - std::string oldid; - ZeroTier::OSUtils::readFile((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),oldid); - memcpy(devID, oldid.c_str(), ZT_ID_LEN); // first 10 bytes of file - return 0; - } - } - return -1; -} - -int zts_running() { - return ZeroTier::zt1Service == NULL ? false : ZeroTier::zt1Service->isRunning(); -} - -int zts_has_ipv4_address(const char *nwid) +int zts_connect(int fd, const struct sockaddr *addr, socklen_t addrlen) { - char ipv4_addr[INET_ADDRSTRLEN]; - memset(ipv4_addr, 0, INET_ADDRSTRLEN); - zts_get_ipv4_address(nwid, ipv4_addr, INET_ADDRSTRLEN); - return strcmp(ipv4_addr, "\0"); + DEBUG_EXTRA("fd=%d",fd); + struct sockaddr_storage ss; + sys2lwip(fd, addr, (struct sockaddr*)&ss); + return lwip_connect(fd, (struct sockaddr*)&ss, addrlen); } -int zts_has_ipv6_address(const char *nwid) +int zts_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { - char ipv6_addr[INET6_ADDRSTRLEN]; - memset(ipv6_addr, 0, INET6_ADDRSTRLEN); - zts_get_ipv6_address(nwid, ipv6_addr, INET6_ADDRSTRLEN); - return strcmp(ipv6_addr, "\0"); + DEBUG_EXTRA("fd=%d", fd); + struct sockaddr_storage ss; + sys2lwip(fd, addr, (struct sockaddr*)&ss); + return lwip_bind(fd, (struct sockaddr*)&ss, addrlen); } -int zts_has_address(const char *nwid) +int zts_listen(int fd, int backlog) { - return zts_has_ipv4_address(nwid) || zts_has_ipv6_address(nwid); -} - -void zts_get_ipv4_address(const char *nwid, char *addrstr, const int addrlen) -{ - if (ZeroTier::zt1Service) { - uint64_t nwid_int = strtoull(nwid, NULL, 16); - ZeroTier::VirtualTap *tap = getTapByNWID(nwid_int); - if (tap && tap->_ips.size()) { - for (int i=0; i_ips.size(); i++) { - if (tap->_ips[i].isV4()) { - char ipbuf[INET_ADDRSTRLEN]; - std::string addr = tap->_ips[i].toString(ipbuf); - int len = addrlen < addr.length() ? addrlen : addr.length(); - memset(addrstr, 0, len); - memcpy(addrstr, addr.c_str(), len); - return; - } - } - } - } - else - memcpy(addrstr, "\0", 1); -} - -void zts_get_ipv6_address(const char *nwid, char *addrstr, const int addrlen) -{ - if (ZeroTier::zt1Service) { - uint64_t nwid_int = strtoull(nwid, NULL, 16); - ZeroTier::VirtualTap *tap = getTapByNWID(nwid_int); - if (tap && tap->_ips.size()) { - for (int i=0; i_ips.size(); i++) { - if (tap->_ips[i].isV6()) { - char ipbuf[INET6_ADDRSTRLEN]; - std::string addr = tap->_ips[i].toString(ipbuf); - int len = addrlen < addr.length() ? addrlen : addr.length(); - memset(addrstr, 0, len); - memcpy(addrstr, addr.c_str(), len); - return; - } - } - } - } - else - memcpy(addrstr, "\0", 1); -} - -void zts_get_6plane_addr(char *addr, const char *nwid, const char *devID) -{ - ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv66plane( - ZeroTier::Utils::hexStrToU64(nwid),ZeroTier::Utils::hexStrToU64(devID)); - char ipbuf[INET6_ADDRSTRLEN]; - memcpy(addr, _6planeAddr.toIpString(ipbuf), 40); -} - -void zts_get_rfc4193_addr(char *addr, const char *nwid, const char *devID) -{ - ZeroTier::InetAddress _6planeAddr = ZeroTier::InetAddress::makeIpv6rfc4193( - ZeroTier::Utils::hexStrToU64(nwid),ZeroTier::Utils::hexStrToU64(devID)); - char ipbuf[INET6_ADDRSTRLEN]; - memcpy(addr, _6planeAddr.toIpString(ipbuf), 40); -} - -unsigned long zts_get_peer_count() { - if (ZeroTier::zt1Service) { - return ZeroTier::zt1Service->getNode()->peers()->peerCount; - } - else { - return 0; - } -} - -int zts_get_peer_address(char *peer, const char *devID) { - if (ZeroTier::zt1Service) { - ZT_PeerList *pl = ZeroTier::zt1Service->getNode()->peers(); - // uint64_t addr; - for (int i=0; ipeerCount; i++) { - // ZT_Peer *p = &(pl->peers[i]); - // DEBUG_INFO("peer[%d] = %lx", i, p->address); - } - return pl->peerCount; - } - else - return -1; -} - -void zts_enable_http_control_plane() -{ - // TODO -} - -void zts_disable_http_control_plane() -{ - // TODO -} - -/****************************************************************************/ -/* VirtualTap Multiplexer Functionality */ -/* - This section of the API is used to implement the general socket */ -/* controls. Basically this is designed to handle socket provisioning */ -/* requests when no VirtualTap is yet initialized, and as a way to */ -/* determine which VirtualTap is to be used for a particular connect() or */ -/* bind() call. This enables multi-network support */ -/****************************************************************************/ - -// int socket_family, int socket_type, int protocol -int zts_socket(int socket_family, int socket_type, int protocol) { - DEBUG_EXTRA(); - int err = errno = 0; - if (socket_family < 0 || socket_type < 0 || protocol < 0) { - errno = EINVAL; - return -1; - } - if (ZeroTier::zt1Service == NULL) { - DEBUG_ERROR("cannot create socket, no service running. call zts_start() first."); - errno = EMFILE; // could also be ENFILE - return -1; - } - if (socket_type == SOCK_SEQPACKET) { - DEBUG_ERROR("SOCK_SEQPACKET not yet supported."); - errno = EPROTONOSUPPORT; // seemingly closest match - return -1; - } - if (socket_type == SOCK_RAW) { - // VirtualSocket is only used to associate a socket with a VirtualTap, it has no other implication - ZeroTier::VirtualSocket *vs = new ZeroTier::VirtualSocket(); - vs->socket_family = socket_family; - vs->socket_type = socket_type; - vs->protocol = protocol; - add_unassigned_virt_socket(vs->app_fd, vs); - return vs->app_fd; - } -#if defined(STACK_PICO) - struct pico_socket *p; - err = ZeroTier::picostack->pico_Socket(&p, socket_family, socket_type, protocol); - if (err == false && p) { - ZeroTier::VirtualSocket *vs = new ZeroTier::VirtualSocket(); - vs->socket_family = socket_family; - vs->socket_type = socket_type; - vs->picosock = p; - add_unassigned_virt_socket(vs->app_fd, vs); - err = vs->app_fd; // return one end of the socketpair - } - else { - DEBUG_ERROR("failed to create pico_socket"); - errno = ENOMEM; - err = -1; - } -#endif -#if defined(STACK_LWIP) - // TODO: check for max lwIP timers/sockets - void *pcb; - err = ZeroTier::lwipstack->lwip_Socket(&pcb, socket_family, socket_type, protocol); - if (pcb) { - ZeroTier::VirtualSocket *vs = new ZeroTier::VirtualSocket(); - vs->socket_family = socket_family; - vs->socket_type = socket_type; - vs->pcb = pcb; - add_unassigned_virt_socket(vs->app_fd, vs); - // return one end of the socketpair for the app to use - err = vs->app_fd; - } - else { - DEBUG_ERROR("failed to create lwip pcb"); - errno = ENOMEM; - err = -1; - } -#endif - -//#if defined(DEFAULT_VS_LINGER) - /* - if (socket_type == SOCK_STREAM) { - linger lin; - unsigned int y=sizeof(lin); - lin.l_onoff=1; - lin.l_linger=10; - int fd = err; - if((err = zts_setsockopt(fd, SOL_SOCKET, SO_LINGER, (void*)(&lin), y)) < 0) { - DEBUG_ERROR("error while setting default linger time on socket"); - errno = -1; // TODO - handle_general_failure(); - return -1; - } - err = fd; - } - */ -//#endif - return err; -} - -int zts_connect(int fd, const struct sockaddr *addr, socklen_t addrlen) { - DEBUG_INFO("fd=%d",fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - if (ZeroTier::zt1Service == NULL) { - DEBUG_ERROR("service not started. call zts_start(path) first"); - errno = EBADF; - return -1; - } - ZeroTier::VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid socket, unable to locate VirtualSocket for fd=%d", fd); - errno = EBADF; - return -1; - } - if (addr == NULL) { - DEBUG_ERROR("invalid address for fd=%d", fd); - errno = EINVAL; - return -1; - } - if (addrlen <= 0) { - DEBUG_ERROR("invalid address length for fd=%d", fd); - errno = EINVAL; - return -1; - } - // TODO: Handle bad address lengths, right now this call will still - // succeed with a complete connect despite a bad address length. - - // DEBUG_EXTRA("fd = %d, %s : %d", fd, ipstr, ntohs(port)); - ZeroTier::InetAddress inet; - sockaddr2inet(vs->socket_family, addr, &inet); - ZeroTier::VirtualTap *tap = getTapByAddr(&inet); - if (tap == NULL) { - DEBUG_ERROR("no route to host, could not find appropriate VirtualTap for fd=%d", fd); - errno = ENETUNREACH; - return -1; - } - -#if defined(STACK_PICO) - // pointer to virtual tap we use in callbacks from the stack - vs->picosock->priv = new ZeroTier::VirtualBindingPair(tap, vs); -#endif -#if defined(STACK_LWIP) -#endif - - if ((err = tap->Connect(vs, addr, addrlen)) < 0) { - DEBUG_ERROR("error while connecting socket"); - // errno will be set by tap->Connect - return -1; - } - // assign this VirtualSocket to the tap we decided on - tap->_VirtualSockets.push_back(vs); - vs->tap = tap; - vs->sock = tap->_phy.wrapSocket(vs->sdk_fd, vs); - - // TODO: Consolidate these calls - del_unassigned_virt_socket(fd); - add_assigned_virt_socket(tap, vs, fd); - - // save peer addr, for calls like getpeername - memcpy(&(vs->peer_addr), addr, sizeof(vs->peer_addr)); - - // Below will simulate BLOCKING/NON-BLOCKING behaviour - - // NOTE: pico_socket_connect() will return 0 if no error happens immediately, but that doesn't indicate - // the connection was completed, for that we must wait for a callback from the stack. During that - // callback we will place the VirtualSocket in a VS_STATE_UNHANDLED_CONNECTED state to signal - // to the multiplexer logic that this connection is complete and a success value can be sent to the - // user application - - int f_err, blocking = 1; - if ((f_err = fcntl(fd, F_GETFL, 0)) < 0) { - DEBUG_ERROR("fcntl error, err=%s, errno=%d", f_err, errno); - // errno will be set by fcntl - return -1; - } - blocking = !(f_err & O_NONBLOCK); - if (blocking == false) { - errno = EINPROGRESS; // can't connect immediately - err = -1; - } - if (blocking == true) { - bool complete = false; - while (true) { - // FIXME: locking and unlocking so often might cause significant performance overhead while outgoing VirtualSockets - // are being established (also applies to accept()) - nanosleep((const struct timespec[]) {{0, (ZT_CONNECT_RECHECK_DELAY * 1000000)}}, NULL); - tap->_tcpconns_m.lock(); - for (int i=0; i_VirtualSockets.size(); i++) { -#if defined(STACK_PICO) - DEBUG_EXTRA("checking tap->_VirtualSockets[i]=%p", tap->_VirtualSockets[i]); - if (tap->_VirtualSockets[i]->get_state() == PICO_ERR_ECONNRESET) { - errno = ECONNRESET; - DEBUG_ERROR("ECONNRESET"); - err = -1; - } -#endif -#if defined(STACK_LWIP) -#endif - if (tap->_VirtualSockets[i]->get_state() == VS_STATE_UNHANDLED_CONNECTED) { - tap->_VirtualSockets[i]->set_state(VS_STATE_CONNECTED); - complete = true; - } - } - tap->_tcpconns_m.unlock(); - if (complete) { - break; - } - } - } - return err; -} - -int zts_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - if (ZeroTier::zt1Service == NULL) { - DEBUG_ERROR("service not started. call zts_start(path) first"); - errno = EBADF; - return -1; - } - ZeroTier::VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("no VirtualSocket for fd=%d", fd); - errno = ENOTSOCK; - return -1; - } - // detect local interface binds - ZeroTier::VirtualTap *tap = NULL; - if (vs->socket_family == AF_INET) { - struct sockaddr_in *in4 = (struct sockaddr_in *)addr; - if (in4->sin_addr.s_addr == INADDR_ANY) { - DEBUG_EXTRA("AF_INET, INADDR_ANY, binding to all interfaces"); - // grab first vtap - if (ZeroTier::vtaps.size()) { - tap = (ZeroTier::VirtualTap*)(ZeroTier::vtaps[0]); // pick any vtap - } - } - if (in4->sin_addr.s_addr == 0x7f000001) { - DEBUG_EXTRA("127.0.0.1, will bind to appropriate vtap when connection is inbound"); - if (ZeroTier::vtaps.size()) { - tap = (ZeroTier::VirtualTap*)(ZeroTier::vtaps[0]); // pick any vtap - } - } - } - if (vs->socket_family == AF_INET6) { - struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr; - if (memcmp((void*)&(in6->sin6_addr), (void*)&(in6addr_any), sizeof(in6addr_any)) == 0) { - DEBUG_EXTRA("AF_INET6, in6addr_any, binding to all interfaces"); - if (ZeroTier::vtaps.size()) { - tap = (ZeroTier::VirtualTap*)(ZeroTier::vtaps[0]); // pick any vtap - } - } - } - - ZeroTier::InetAddress inet; - sockaddr2inet(vs->socket_family, addr, &inet); - if (tap == NULL) { - tap = getTapByAddr(&inet); - } - if (tap == NULL) { - DEBUG_ERROR("no matching interface to bind to, could not find appropriate VirtualTap for fd=%d", fd); - errno = ENETUNREACH; - return -1; - } -#if defined(STACK_PICO) - // used in callbacks from network stack - vs->picosock->priv = new ZeroTier::VirtualBindingPair(tap, vs); -#endif - tap->addVirtualSocket(vs); - err = tap->Bind(vs, addr, addrlen); - if (err == 0) { // success - vs->tap = tap; - del_unassigned_virt_socket(fd); - add_assigned_virt_socket(tap, vs, fd); - } - return err; -} - -int zts_listen(int fd, int backlog) { DEBUG_EXTRA("fd=%d", fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - if (ZeroTier::zt1Service == NULL) { - DEBUG_ERROR("service not started. call zts_start(path) first"); - errno = EACCES; - return -1; - } - std::pair *p = get_assigned_virtual_pair(fd); - ZeroTier::_multiplexer_lock.lock(); - if (p == NULL) { - DEBUG_ERROR("unable to locate VirtualSocket pair. did you bind?"); - errno = EDESTADDRREQ; - return -1; - } - ZeroTier::VirtualSocket *vs = p->first; - ZeroTier::VirtualTap *tap = p->second; - if (tap == NULL || vs == NULL) { - DEBUG_ERROR("unable to locate tap interface for file descriptor"); - errno = EBADF; - return -1; - } - backlog = backlog > 128 ? 128 : backlog; // See: /proc/sys/net/core/somaxconn - err = tap->Listen(vs, backlog); - vs->set_state(VS_STATE_LISTENING); - ZeroTier::_multiplexer_lock.unlock(); - return err; + return lwip_listen(fd, backlog); } -int zts_accept(int fd, struct sockaddr *addr, socklen_t *addrlen) { - int err = errno = 0; +int zts_accept(int fd, struct sockaddr *addr, socklen_t *addrlen) +{ DEBUG_EXTRA("fd=%d", fd); - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - if (addr && *addrlen <= 0) { - DEBUG_ERROR("invalid address length given"); - errno = EINVAL; // TODO, not actually a valid error for this function - return -1; - } - if (can_provision_new_socket(SOCK_STREAM) == false) { - DEBUG_ERROR("cannot provision additional socket due to limitation of network stack"); - errno = EMFILE; - return -1; - } - std::pair *p = get_assigned_virtual_pair(fd); - if (p == NULL) { - DEBUG_ERROR("unable to locate VirtualSocket pair (did you zts_bind())?"); - errno = EBADF; - err = -1; - } - else { - ZeroTier::VirtualSocket *vs = p->first; - ZeroTier::VirtualTap *tap = p->second; - // BLOCKING: loop and keep checking until we find a newly accepted VirtualSocket - int f_err, blocking = 1; - if ((f_err = fcntl(fd, F_GETFL, 0)) < 0) { - DEBUG_ERROR("fcntl error, err = %s, errno = %d", f_err, errno); - err = -1; - } - else { - blocking = !(f_err & O_NONBLOCK); - } - ZeroTier::VirtualSocket *accepted_vs; - if (err == false) { - if (blocking == false) { // non-blocking - DEBUG_EXTRA("EWOULDBLOCK, assuming non-blocking mode"); - errno = EWOULDBLOCK; - err = -1; - accepted_vs = tap->Accept(vs); - } - else { // blocking - while (true) { - nanosleep((const struct timespec[]) {{0, (ZT_ACCEPT_RECHECK_DELAY * 1000000)}}, NULL); - accepted_vs = tap->Accept(vs); - if (accepted_vs) - break; // accepted fd = err - } - } - if (accepted_vs) { - add_assigned_virt_socket(tap, accepted_vs, accepted_vs->app_fd); - err = accepted_vs->app_fd; - } - } - if (err > 0) { - if (addr && *addrlen) { - *addrlen = *addrlen < sizeof(accepted_vs->peer_addr) ? *addrlen : sizeof(accepted_vs->peer_addr); - // copy address into provided address buffer and len buffer - memcpy(addr, &(accepted_vs->peer_addr), *addrlen); - } - } - } - return err; + return lwip_accept(fd, addr, addrlen); } #if defined(__linux__) int zts_accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) { - errno = 0; - //DEBUG_INFO("fd=%d", fd); - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - if (flags & SOCK_NONBLOCK) { - fcntl(fd, F_SETFL, O_NONBLOCK); - } - if (flags & SOCK_CLOEXEC) { - fcntl(fd, F_SETFL, FD_CLOEXEC); - } - addrlen = !addr ? 0 : addrlen; + DEBUG_EXTRA("fd=%d", fd); return zts_accept(fd, addr, addrlen); } #endif @@ -784,1324 +122,139 @@ int zts_accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) int zts_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) { DEBUG_EXTRA("fd=%d, level=%d, optname=%d", fd, level, optname); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - ZeroTier::VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid fd=%d", fd); - errno = EBADF; - return -1; - } -#if defined(STACK_PICO) - if (ZeroTier::picostack) { - err = ZeroTier::picostack->pico_setsockopt(vs, level, optname, optval, optlen); - } else { - handle_general_failure(); - // TODO: errno? - err = -1; - } -#endif -#if defined(STACK_LWIP) - if (ZeroTier::lwipstack) { - err = ZeroTier::lwipstack->lwip_setsockopt(vs, level, optname, optval, optlen); - } else { - handle_general_failure(); - // TODO: errno? - err = -1; - } -#endif - return err; + return lwip_setsockopt(fd, level, optname, optval, optlen); } int zts_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen) { DEBUG_EXTRA("fd=%d, level=%d, optname=%d", fd, level, optname); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - ZeroTier::VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid fd=%d", fd); - errno = EBADF; - return -1; - } -#if defined(STACK_PICO) - if (ZeroTier::picostack) { - err = ZeroTier::picostack->pico_getsockopt(vs, level, optname, optval, optlen); - } else { - handle_general_failure(); - // TODO: errno? - err = -1; - } -#endif -#if defined(STACK_LWIP) - if (ZeroTier::lwipstack) { - err = ZeroTier::lwipstack->lwip_getsockopt(vs, level, optname, optval, optlen); - } else { - handle_general_failure(); - // TODO: errno? - err = -1; - } -#endif - return err; + return lwip_getsockopt(fd, level, optname, optval, optlen); } int zts_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen) { - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - // TODO - return err; + DEBUG_EXTRA("fd=%p", fd); + return lwip_getsockname(fd, addr, addrlen); } int zts_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen) { - DEBUG_INFO("fd=%d", fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - ZeroTier::VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - errno = ENOTCONN; - return -1; - } - memcpy(addr, &(vs->peer_addr), sizeof(struct sockaddr_storage)); - return err; + DEBUG_EXTRA("fd=%d", fd); + return lwip_getpeername(fd, addr, addrlen); } int zts_gethostname(char *name, size_t len) { - errno = 0; - return gethostname(name, len); + DEBUG_EXTRA(); + return -1; } int zts_sethostname(const char *name, size_t len) { - errno = 0; - return sethostname(name, len); + DEBUG_EXTRA(); + return -1; } int zts_close(int fd) { DEBUG_EXTRA("fd=%d", fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - if (ZeroTier::zt1Service == NULL) { - DEBUG_ERROR("cannot close socket. service not started. call zts_start(path) first"); - errno = EBADF; - return -1; - } - ZeroTier::VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("no vs found for fd=%d", fd); - handle_general_failure(); - errno = EBADF; - return -1; - } - del_virt_socket(fd); - if (vs->tap) { - vs->tap->Close(vs); - } - delete vs; - vs = NULL; - return err; + return lwip_close(fd); } int zts_poll(struct pollfd *fds, nfds_t nfds, int timeout) { - errno = 0; + DEBUG_EXTRA(); return poll(fds, nfds, timeout); } int zts_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { - errno = 0; + DEBUG_EXTRA(); return select(nfds, readfds, writefds, exceptfds, timeout); } int zts_fcntl(int fd, int cmd, int flags) { - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; + DEBUG_EXTRA("fd=%p, cmd=%d, flags=%d", cmd, flags); + int translated_flags = 0; + if (flags == 2048) { + translated_flags = 1; } - ZeroTier::VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid vs for fd=%d", fd); - errno = EBADF; - return -1; - } - err = fcntl(fd, cmd, flags); - return err; + return lwip_fcntl(fd, cmd, translated_flags); } int zts_ioctl(int fd, unsigned long request, void *argp) { - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - else { -#if defined(__linux__) - if (argp) - { - struct ifreq *ifr = (struct ifreq *)argp; - ZeroTier::VirtualTap *tap = getTapByName(ifr->ifr_name); - if (tap == NULL) { - DEBUG_ERROR("unable to locate tap interface with that name"); - err = -1; - errno = EINVAL; - } - // index of VirtualTap interface - if (request == SIOCGIFINDEX) { - ifr->ifr_ifindex = tap->ifindex; - err = 0; - } - // MAC addres or VirtualTap - if (request == SIOCGIFHWADDR) { - tap->_mac.copyTo(&(ifr->ifr_hwaddr.sa_data), sizeof(ifr->ifr_hwaddr.sa_data)); - err = 0; - } - // IP address of VirtualTap - if (request == SIOCGIFADDR) { - struct sockaddr_in *in4 = (struct sockaddr_in *)&(ifr->ifr_addr); - memcpy(&(in4->sin_addr.s_addr), tap->_ips[0].rawIpData(), sizeof(ifr->ifr_addr)); - err = 0; - } - } - else { - DEBUG_INFO("!argp"); - } -#else - err = ioctl(fd, request, argp); -#endif - } - return err; + DEBUG_EXTRA("fd=%d, req=%d", fd, request); + return lwip_ioctl(fd, request, argp); } ssize_t zts_sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen) { - //DEBUG_TRANS("fd=%d", fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - if (len == 0) { - return 0; - } - if (len > ZT_SOCKET_MSG_BUF_SZ) { - DEBUG_ERROR("msg is too long to be sent atomically (len=%d)", len); - errno = EMSGSIZE; - return -1; - } - if (buf == NULL) { - DEBUG_ERROR("msg buf is null"); - errno = EINVAL; - return -1; - } - ZeroTier::VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("no vs found for fd=%x", fd); - handle_general_failure(); - errno = EBADF; - return -1; - } - ZeroTier::InetAddress iaddr; - ZeroTier::VirtualTap *tap; - - if (vs->socket_type == SOCK_DGRAM) { - if (vs->socket_family == AF_INET) - { - char ipstr[INET_ADDRSTRLEN]; - memset(ipstr, 0, INET_ADDRSTRLEN); - inet_ntop(AF_INET, - (const void *)&((struct sockaddr_in *)addr)->sin_addr.s_addr, ipstr, INET_ADDRSTRLEN); - iaddr.fromString(ipstr); - } - if (vs->socket_family == AF_INET6) - { - char ipstr[INET6_ADDRSTRLEN]; - memset(ipstr, 0, INET6_ADDRSTRLEN); - inet_ntop(AF_INET6, - (const void *)&((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, ipstr, INET6_ADDRSTRLEN); - // TODO: This is a hack, determine a proper way to do this - char addrstr[INET6_ADDRSTRLEN]; - sprintf(addrstr, "%s%s", ipstr, std::string("/40").c_str()); - iaddr.fromString(addrstr); - } - // get tap - tap = getTapByAddr(&iaddr); - if (tap == NULL) { - DEBUG_INFO("SOCK_DGRAM, tap not found"); - errno = EDESTADDRREQ; // TODO: double check this is the best errno to report - return -1; - } - // write - if ((err = tap->SendTo(vs, buf, len, flags, addr, addrlen)) < 0) { - DEBUG_ERROR("error while attempting to sendto"); - errno = EINVAL; // TODO: Not correct, but what else could we use? - } - } - if (vs->socket_type == SOCK_RAW) - { - struct sockaddr_ll *socket_address = (struct sockaddr_ll *)addr; - ZeroTier::VirtualTap *tap = getTapByIndex(socket_address->sll_ifindex); - if (tap) { - DEBUG_INFO("found interface of ifindex=%d", tap->ifindex); - err = tap->Write(vs, (void*)buf, len); - } - else { - DEBUG_ERROR("unable to locate tap of ifindex=%d", socket_address->sll_ifindex); - err = -1; - errno = EINVAL; - } - } - return err; + DEBUG_TRANS("fd=%d, len=%d", fd, len); + struct sockaddr_storage ss; + sys2lwip(fd, addr, (struct sockaddr*)&ss); + return lwip_sendto(fd, buf, len, flags, (struct sockaddr*)&ss, addrlen); } ssize_t zts_send(int fd, const void *buf, size_t len, int flags) { - // DEBUG_TRANS("fd=%d", fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - if (len == 0) { - return 0; - } - if (len > ZT_SOCKET_MSG_BUF_SZ) { - DEBUG_ERROR("msg is too long to be sent atomically (len=%d)", len); - errno = EMSGSIZE; - return -1; - } - ZeroTier::VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid vs for fd=%d", fd); - errno = EBADF; - return -1; - } - if (vs->socket_type != SOCK_STREAM) { - DEBUG_ERROR("the socket is not connection-mode, and no peer address is set for fd=%d", fd); - errno = EDESTADDRREQ; - return -1; - } - if (flags & MSG_DONTROUTE) { - DEBUG_INFO("MSG_DONTROUTE not implemented yet"); - errno = EINVAL; - return -1; - } - if (flags & MSG_DONTWAIT) { - // The stack drivers and stack are inherently non-blocking by design, but we - // still need to modify the unix pipe connecting them to the application: - fcntl(fd, F_SETFL, O_NONBLOCK); - } - if (flags & MSG_EOR) { - DEBUG_INFO("MSG_EOR not implemented yet"); - errno = EINVAL; - return -1; - } - if (flags & MSG_OOB) { - DEBUG_INFO("MSG_OOB not implemented yet"); - errno = EINVAL; - return -1; - } -#if defined(__linux__) - if (flags & MSG_CONFIRM) { - DEBUG_INFO("MSG_CONFIRM not implemented yet"); - errno = EINVAL; - return -1; - } - if (flags & MSG_MORE) { - DEBUG_INFO("MSG_MORE not implemented yet"); - errno = EINVAL; - return -1; - } - if (flags & MSG_NOSIGNAL) { - DEBUG_INFO("MSG_NOSIGNAL not implemented yet"); - errno = EINVAL; - return -1; - } -#endif - - err = write(fd, buf, len); - // restore "per-call" flags - - if (flags & MSG_DONTWAIT) { - int saved_flags = fcntl(fd, F_GETFL); - if (fcntl(fd, F_SETFL, saved_flags & ~O_NONBLOCK) < 0) { // mask out the blocking flag - handle_general_failure(); - return -1; - } - } - return err; + DEBUG_TRANS("fd=%d, len=%d", fd, len); + return lwip_send(fd, buf, len, flags); } -// TODO ssize_t zts_sendmsg(int fd, const struct msghdr *msg, int flags) { DEBUG_TRANS("fd=%d", fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - else { - err = sendmsg(fd, msg, flags); - } - return err; + return lwip_sendmsg(fd, msg, flags); } ssize_t zts_recv(int fd, void *buf, size_t len, int flags) { DEBUG_TRANS("fd=%d", fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - ZeroTier::VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid vs for fd=%d", fd); - errno = EBADF; - return -1; - } - if (vs->socket_type != SOCK_STREAM) { - DEBUG_ERROR("the socket is not connection-mode, and no peer address is set for fd=%d", fd); - errno = EDESTADDRREQ; - return -1; - } - if (vs->get_state() != VS_STATE_CONNECTED) { - DEBUG_ERROR("the socket is not in a connected state, fd=%d", fd); - errno = ENOTCONN; - return -1; - } - if (flags & MSG_DONTWAIT) { - // The stack drivers and stack are inherently non-blocking by design, but we - // still need to modify the unix pipe connecting them to the application: - fcntl(fd, F_SETFL, O_NONBLOCK); - } - if (flags & MSG_OOB) { - DEBUG_INFO("MSG_OOB not implemented yet"); - errno = EINVAL; - return -1; - } - if (flags & MSG_TRUNC) { - DEBUG_INFO("MSG_TRUNC not implemented yet"); - errno = EINVAL; - return -1; - } - if (flags & MSG_WAITALL) { - DEBUG_INFO("MSG_WAITALL not implemented yet"); - errno = EINVAL; - return -1; - } -#if defined(__linux__) - if (flags & MSG_ERRQUEUE) { - DEBUG_INFO("MSG_ERRQUEUE not implemented yet"); - errno = EINVAL; - return -1; - } -#endif - - if (flags & MSG_PEEK) { - // MSG_PEEK doesn't require any special stack-related machinery so we can just - // pass it to a regular recv() call with no issue - err = recv(fd, buf, len, MSG_PEEK); - } - - // restore "per-call" flags - - if (flags & MSG_DONTWAIT) { - int saved_flags = fcntl(fd, F_GETFL); - if (fcntl(fd, F_SETFL, saved_flags & ~O_NONBLOCK) < 0) { // mask out the blocking flag - handle_general_failure(); - return -1; - } - } - return err; + return lwip_recv(fd, buf, len, flags); } ssize_t zts_recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen) { - //DEBUG_TRANS("fd=%d", fd); - int32_t r = 0; - errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - if (len == 0) { - return 0; - } - if (buf == NULL) { - DEBUG_ERROR("buf is null"); - errno = EINVAL; - return -1; - } - char udp_msg_buf[ZT_SOCKET_MSG_BUF_SZ]; - char *msg_ptr = udp_msg_buf; - memset(msg_ptr, 0, sizeof(int32_t)); // zero only len portion - - int32_t udp_msg_len = 0; - - // PEEK at the buffer and see if we can read a length, if not, err out - r = recv(fd, msg_ptr, sizeof(int32_t), MSG_PEEK); - if (r != sizeof(int32_t)) { - errno = EIO; // TODO: test for this - return -1; - } - // read of sizeof(int32_t) for the length of the datagram (including address) - r = read(fd, msg_ptr, sizeof(int32_t)); - // copy to length variable - memcpy(&udp_msg_len, msg_ptr, sizeof(int32_t)); - msg_ptr+=sizeof(int32_t); - - if (udp_msg_len <= 0) { - DEBUG_ERROR("invalid datagram"); - errno = EIO; // TODO: test for this - return -1; - } - // there is a datagram to read, so let's read it - // zero remainder of buffer - memset(msg_ptr, 0, ZT_SOCKET_MSG_BUF_SZ- sizeof(int32_t)); - if ((r = read(fd, msg_ptr, udp_msg_len)) < 0) { - DEBUG_ERROR("invalid datagram"); - errno = EIO; // TODO: test for this - return -1; - } - // get address - if (addr) { - if (*addrlen < sizeof(struct sockaddr_storage)) { - DEBUG_ERROR("invalid address length provided"); - errno = EINVAL; - return -1; - } - *addrlen = sizeof(struct sockaddr_storage); - memcpy(addr, msg_ptr, *addrlen); - } - msg_ptr+=sizeof(struct sockaddr_storage); - // get payload - int32_t payload_sz = udp_msg_len - *addrlen; - int32_t write_sz = len < payload_sz ? len : payload_sz; - memcpy(buf, msg_ptr, write_sz); - return write_sz; + DEBUG_TRANS("fd=%d", fd); + return lwip_recvfrom(fd, buf, len, flags, addr, addrlen); } -// TODO ssize_t zts_recvmsg(int fd, struct msghdr *msg,int flags) { - //DEBUG_TRANS("fd=%d", fd); - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - else { - err = recvmsg(fd, msg, flags); - } - return err; + DEBUG_TRANS("fd=%d", fd); + return -1; } int zts_read(int fd, void *buf, size_t len) { - DEBUG_TRANS("fd=%d", fd); - errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - ZeroTier::VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid vs for fd=%d", fd); - errno = EBADF; - return -1; - } - return read(fd, buf, len); + DEBUG_TRANS("fd=%d, len=%d", fd, len); + return lwip_read(fd, buf, len); } int zts_write(int fd, const void *buf, size_t len) { - DEBUG_TRANS("fd=%d", fd); - errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - ZeroTier::VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid vs for fd=%d", fd); - errno = EBADF; - return -1; - } - return write(fd, buf, len); + DEBUG_TRANS("fd=%d, len=%d", fd, len); + return lwip_write(fd, buf, len); } int zts_shutdown(int fd, int how) { - int err = errno = 0; - if (fd < 0 || fd >= ZT_MAX_SOCKETS) { - errno = EBADF; - return -1; - } - if (how != SHUT_RD && how != SHUT_WR && how != SHUT_RDWR) { - errno = EINVAL; - return -1; - } - ZeroTier::VirtualSocket *vs = get_virt_socket(fd); - if (vs == NULL) { - DEBUG_ERROR("invalid vs for fd=%d", fd); - errno = EBADF; - return -1; - } - if (vs->get_state() != VS_STATE_CONNECTED || vs->socket_type != SOCK_STREAM) { - DEBUG_ERROR("the socket is either not in a connected state, or isn't connection-based, fd=%d", fd); - errno = ENOTCONN; - return -1; - } - if (vs->tap) { - err = vs->tap->Shutdown(vs, how); - } - return err; + DEBUG_EXTRA("fd=%d, how=%d", fd, how); + return lwip_shutdown(fd, how); } int zts_add_dns_nameserver(struct sockaddr *addr) { - ZeroTier::VirtualTap *vtap = getAnyTap(); - if (vtap) { - return vtap->add_DNS_Nameserver(addr); - } - DEBUG_ERROR("unable to locate virtual tap to add DNS nameserver"); + DEBUG_EXTRA(); return -1; } int zts_del_dns_nameserver(struct sockaddr *addr) { - ZeroTier::VirtualTap *vtap = getAnyTap(); - if (vtap) { - return vtap->del_DNS_Nameserver(addr); - } - DEBUG_ERROR("unable to locate virtual tap to remove DNS nameserver"); + DEBUG_EXTRA(); return -1; } -/****************************************************************************/ -/* SDK Socket API (Java Native Interface JNI) */ -/* JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME */ -/****************************************************************************/ - - -#if defined(SDK_JNI) - -namespace ZeroTier { - - #include - - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1start(JNIEnv *env, jobject thisObj, jstring path) { - if (path) { - homeDir = env->GetStringUTFChars(path, NULL); - zts_start(homeDir.c_str()); - } - } - // Shuts down ZeroTier service and SOCKS5 Proxy server - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1stop(JNIEnv *env, jobject thisObj) { - if (ZeroTier::zt1Service) { - zts_stop(); - } - } - - // Returns whether the ZeroTier service is running - JNIEXPORT jboolean JNICALL Java_zerotier_ZeroTier_ztjni_1running( - JNIEnv *env, jobject thisObj) - { - return zts_running(); - } - // Returns path for ZT config/data files - JNIEXPORT jstring JNICALL Java_zerotier_ZeroTier_ztjni_1homepath( - JNIEnv *env, jobject thisObj) - { - // TODO: fix, should copy into given arg - // return (*env).NewStringUTF(zts_get_homepath()); - return (*env).NewStringUTF(""); - } - // Join a network - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1join( - JNIEnv *env, jobject thisObj, jstring nwid) - { - const char *nwidstr; - if (nwid) { - nwidstr = env->GetStringUTFChars(nwid, NULL); - zts_join(nwidstr); - } - } - // Leave a network - JNIEXPORT void JNICALL Java_zerotier_ZeroTier_ztjni_1leave( - JNIEnv *env, jobject thisObj, jstring nwid) - { - const char *nwidstr; - if (nwid) { - nwidstr = env->GetStringUTFChars(nwid, NULL); - zts_leave(nwidstr); - } - } - // FIXME: Re-implemented to make it play nicer with the C-linkage required for Xcode integrations - // Now only returns first assigned address per network. Shouldn't normally be a problem - JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_ztjni_1get_1ipv4_1address( - JNIEnv *env, jobject thisObj, jstring nwid) - { - const char *nwid_str = env->GetStringUTFChars(nwid, NULL); - char address_string[INET_ADDRSTRLEN]; - memset(address_string, 0, INET_ADDRSTRLEN); - zts_get_ipv4_address(nwid_str, address_string, INET_ADDRSTRLEN); - jclass clazz = (*env).FindClass("java/util/ArrayList"); - jobject addresses = (*env).NewObject(clazz, (*env).GetMethodID(clazz, "", "()V")); - jstring _str = (*env).NewStringUTF(address_string); - env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str); - return addresses; - } - - JNIEXPORT jobject JNICALL Java_zerotier_ZeroTier_ztjni_1get_1ipv6_1address( - JNIEnv *env, jobject thisObj, jstring nwid) - { - const char *nwid_str = env->GetStringUTFChars(nwid, NULL); - char address_string[INET6_ADDRSTRLEN]; - memset(address_string, 0, INET6_ADDRSTRLEN); - zts_get_ipv6_address(nwid_str, address_string, INET6_ADDRSTRLEN); - jclass clazz = (*env).FindClass("java/util/ArrayList"); - jobject addresses = (*env).NewObject(clazz, (*env).GetMethodID(clazz, "", "()V")); - jstring _str = (*env).NewStringUTF(address_string); - env->CallBooleanMethod(addresses, env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"), _str); - return addresses; - } - - // Returns the device is in integer form - JNIEXPORT jint Java_zerotier_ZeroTier_ztjni_1get_1device_1id() - { - return zts_get_device_id(NULL); // TODO - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1send(JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, int flags) - { - jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); - char * bufp = (char *)malloc(sizeof(char)*len); - memcpy(bufp, body, len); - (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); - int written_bytes = zts_write(fd, body, len); - return written_bytes; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1sendto( - JNIEnv *env, jobject thisObj, jint fd, jarray buf, jint len, jint flags, jobject ztaddr) - { - struct sockaddr_in addr; - jclass cls = (*env).GetObjectClass( ztaddr); - jfieldID f = (*env).GetFieldID( cls, "port", "I"); - addr.sin_port = htons((*env).GetIntField( ztaddr, f)); - f = (*env).GetFieldID( cls, "_rawAddr", "J"); - addr.sin_addr.s_addr = (*env).GetLongField( ztaddr, f); - addr.sin_family = AF_INET; - //LOGV("zt_sendto(): fd = %d\naddr = %s\nport=%d", fd, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - // TODO: Optimize this - jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); - char * bufp = (char *)malloc(sizeof(char)*len); - memcpy(bufp, body, len); - (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); - // "connect" and send buffer contents - int sent_bytes = zts_sendto(fd, body, len, flags, (struct sockaddr *)&addr, sizeof(addr)); - return sent_bytes; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1recvfrom( - JNIEnv *env, jobject thisObj, jint fd, jbyteArray buf, jint len, jint flags, jobject ztaddr) - { - struct sockaddr_in addr; - jbyte *body = (*env).GetByteArrayElements( buf, 0); - unsigned char buffer[ZT_SDK_MTU]; - int payload_offset = sizeof(int32_t) + sizeof(struct sockaddr_storage); - int rxbytes = zts_recvfrom(fd, &buffer, len, flags, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr_storage)); - if (rxbytes > 0) - memcpy(body, (jbyte*)buffer + payload_offset, rxbytes); - (*env).ReleaseByteArrayElements( buf, body, 0); - // Update fields of Java ZTAddress object - jfieldID fid; - jclass cls = (*env).GetObjectClass( ztaddr); - fid = (*env).GetFieldID( cls, "port", "I"); - (*env).SetIntField( ztaddr, fid, addr.sin_port); - fid = (*env).GetFieldID( cls,"_rawAddr", "J"); - (*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr); - return rxbytes; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1write(JNIEnv *env, jobject thisObj, - jint fd, jarray buf, jint len) - { - jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); - char * bufp = (char *)malloc(sizeof(char)*len); - memcpy(bufp, body, len); - (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); - int written_bytes = zts_write(fd, body, len); - return written_bytes; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1read(JNIEnv *env, jobject thisObj, - jint fd, jarray buf, jint len) - { - jbyte *body = (*env).GetByteArrayElements((_jbyteArray *)buf, 0); - int read_bytes = read(fd, body, len); - (*env).ReleaseByteArrayElements((_jbyteArray *)buf, body, 0); - return read_bytes; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1setsockopt( - JNIEnv *env, jobject thisObj, - jint fd, jint level, jint optname, jint optval, jint optlen) { - return zts_setsockopt(fd, level, optname, (const void*)optval, optlen); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getsockopt(JNIEnv *env, jobject thisObj, - jint fd, jint level, jint optname, jint optval, jint optlen) { - return zts_getsockopt(fd, level, optname, (void*)optval, (socklen_t *)optlen); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1socket(JNIEnv *env, jobject thisObj, - jint family, jint type, jint protocol) { - return zts_socket(family, type, protocol); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1connect(JNIEnv *env, jobject thisObj, - jint fd, jstring addrstr, jint port) { - struct sockaddr_in addr; - const char *str = (*env).GetStringUTFChars( addrstr, 0); - addr.sin_addr.s_addr = inet_addr(str); - addr.sin_family = AF_INET; - addr.sin_port = htons( port ); - (*env).ReleaseStringUTFChars( addrstr, str); - return zts_connect(fd, (struct sockaddr *)&addr, sizeof(addr)); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1bind(JNIEnv *env, jobject thisObj, - jint fd, jstring addrstr, jint port) { - struct sockaddr_in addr; - const char *str = (*env).GetStringUTFChars( addrstr, 0); - DEBUG_INFO("fd=%d, addr=%s, port=%d", fd, str, port); - addr.sin_addr.s_addr = inet_addr(str); - addr.sin_family = AF_INET; - addr.sin_port = htons( port ); - (*env).ReleaseStringUTFChars( addrstr, str); - return zts_bind(fd, (struct sockaddr *)&addr, sizeof(addr)); - } - -#if defined(__linux__) - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1accept4(JNIEnv *env, jobject thisObj, - jint fd, jstring addrstr, jint port, jint flags) { - struct sockaddr_in addr; - char *str; - // = env->GetStringUTFChars(addrstr, NULL); - (*env).ReleaseStringUTFChars( addrstr, str); - addr.sin_addr.s_addr = inet_addr(str); - addr.sin_family = AF_INET; - addr.sin_port = htons( port ); - return zts_accept4(fd, (struct sockaddr *)&addr, sizeof(addr), flags); - } -#endif - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1accept(JNIEnv *env, jobject thisObj, - jint fd, jstring addrstr, jint port) { - struct sockaddr_in addr; - // TODO: Send addr info back to Javaland - addr.sin_addr.s_addr = inet_addr(""); - addr.sin_family = AF_INET; - addr.sin_port = htons( port ); - return zts_accept(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(addr)); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1listen(JNIEnv *env, jobject thisObj, - jint fd, int backlog) { - return zts_listen(fd, backlog); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1close(JNIEnv *env, jobject thisObj, - jint fd) { - return zts_close(fd); - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getsockname(JNIEnv *env, jobject thisObj, - jint fd, jobject ztaddr) { - struct sockaddr_in addr; - int err = zts_getsockname(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr)); - jfieldID fid; - jclass cls = (*env).GetObjectClass(ztaddr); - fid = (*env).GetFieldID( cls, "port", "I"); - (*env).SetIntField( ztaddr, fid, addr.sin_port); - fid = (*env).GetFieldID( cls,"_rawAddr", "J"); - (*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr); - return err; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1getpeername(JNIEnv *env, jobject thisObj, - jint fd, jobject ztaddr) { - struct sockaddr_in addr; - int err = zts_getpeername(fd, (struct sockaddr *)&addr, (socklen_t *)sizeof(struct sockaddr)); - jfieldID fid; - jclass cls = (*env).GetObjectClass( ztaddr); - fid = (*env).GetFieldID( cls, "port", "I"); - (*env).SetIntField( ztaddr, fid, addr.sin_port); - fid = (*env).GetFieldID( cls,"_rawAddr", "J"); - (*env).SetLongField( ztaddr, fid,addr.sin_addr.s_addr); - return err; - } - - JNIEXPORT jint JNICALL Java_zerotier_ZeroTier_ztjni_1fcntl(JNIEnv *env, jobject thisObj, - jint fd, jint cmd, jint flags) { - return zts_fcntl(fd,cmd,flags); - } -} -#endif - -/****************************************************************************/ -/* SDK Socket API Helper functions --- DON'T CALL THESE DIRECTLY */ -/****************************************************************************/ - -bool can_provision_new_socket(int socket_type) -{ - int can = false; -#if defined(STACK_PICO) - return !(pico_ntimers()+1 > PICO_MAX_TIMERS); -#endif -#if defined(STACK_LWIP) - if (socket_type == SOCK_STREAM) { - return !(ZeroTier::lwIP::lwip_num_current_tcp_pcbs()+1 > MEMP_NUM_TCP_PCB); - } - if (socket_type == SOCK_DGRAM) { - return !(ZeroTier::lwIP::lwip_num_current_udp_pcbs()+1 > MEMP_NUM_UDP_PCB); - } - if (socket_type == SOCK_RAW) { - return !(ZeroTier::lwIP::lwip_num_current_raw_pcbs()+1 > MEMP_NUM_RAW_PCB); - } - can = true; -#endif -#if defined(NO_STACK) - // always true since there's no network stack timer/memory limitation - can = true; -#endif - return can; -} - -int zts_num_active_virt_sockets() -{ - ZeroTier::_multiplexer_lock.lock(); - int num = ZeroTier::unmap.size() + ZeroTier::fdmap.size(); - ZeroTier::_multiplexer_lock.unlock(); - return num; -} - -int zts_maxsockets(int socket_type) -{ - int max = 0; -#if defined(STACK_PICO) - // TODO: This is only an approximation - // TODO: distinquish by type - max = PICO_MAX_TIMERS - 10; -#endif -#if defined(STACK_LWIP) - if (socket_type == SOCK_STREAM) { - max = MEMP_NUM_TCP_PCB; - } - if (socket_type == SOCK_DGRAM) { - max = MEMP_NUM_UDP_PCB; - } -#endif -#if defined(NO_STACK) - // arbitrary -#if defined(__linux__) - max = RLIMIT_NOFILE; -#endif -#if defined(__APPLE__) - max = 1024; -#endif -#endif - return max; -} - -/****************************************************************************/ -/* ZeroTier Core helper functions for libzt - DON'T CALL THESE DIRECTLY */ -/****************************************************************************/ - -std::vector *zts_get_network_routes(char *nwid) -{ - uint64_t nwid_int = strtoull(nwid, NULL, 16); - return ZeroTier::zt1Service->getRoutes(nwid_int); -} - -ZeroTier::VirtualTap *getTapByNWID(uint64_t nwid) -{ - ZeroTier::_vtaps_lock.lock(); - ZeroTier::VirtualTap *s, *tap = nullptr; - for (int i=0; i_nwid == nwid) { tap = s; } - } - ZeroTier::_vtaps_lock.unlock(); - return tap; -} - -ZeroTier::VirtualTap *getTapByAddr(ZeroTier::InetAddress *addr) -{ - ZeroTier::_vtaps_lock.lock(); - ZeroTier::VirtualTap *s, *tap = nullptr; - //char ipbuf[64], ipbuf2[64], ipbuf3[64]; - for (int i=0; i_ips.size(); j++) { - if ((s->_ips[j].isV4() && addr->isV4()) || (s->_ips[j].isV6() && addr->isV6())) { - //DEBUG_EXTRA("looking at tap %s, --- for <%s>", s->_dev.c_str(), s->_ips[j].toString(ipbuf), addr->toIpString(ipbuf2)); - if (s->_ips[j].isEqualPrefix(addr) - || s->_ips[j].ipsEqual(addr) - || s->_ips[j].containsAddress(addr) - || (addr->isV6() && ipv6_in_subnet(&s->_ips[j], addr)) - ) - { - //DEBUG_EXTRA("selected tap %s, ", s->_dev.c_str(), s->_ips[j].toString(ipbuf)); - ZeroTier::_vtaps_lock.unlock(); - return s; - } - } - } - // check managed routes - if (tap == NULL) { - std::vector *managed_routes = ZeroTier::zt1Service->getRoutes(s->_nwid); - ZeroTier::InetAddress target, nm, via; - for (int i=0; isize(); i++) { - target = managed_routes->at(i).target; - nm = target.netmask(); - via = managed_routes->at(i).via; - if (target.containsAddress(addr)) { - //DEBUG_EXTRA("chose tap with route ", target.toString(ipbuf), nm.toString(ipbuf2), via.toString(ipbuf3)); - ZeroTier::_vtaps_lock.unlock(); - return s; - } - } - } - } - ZeroTier::_vtaps_lock.unlock(); - return tap; -} - -ZeroTier::VirtualTap *getTapByName(char *ifname) -{ - ZeroTier::_vtaps_lock.lock(); - ZeroTier::VirtualTap *s, *tap = nullptr; - for (int i=0; i_dev.c_str(), ifname) == false) { - tap = s; - } - } - ZeroTier::_vtaps_lock.unlock(); - return tap; -} - -ZeroTier::VirtualTap *getTapByIndex(int index) -{ - ZeroTier::_vtaps_lock.lock(); - ZeroTier::VirtualTap *s, *tap = nullptr; - for (int i=0; iifindex == index) { - tap = s; - } - } - ZeroTier::_vtaps_lock.unlock(); - return tap; -} - -ZeroTier::VirtualTap *getAnyTap() -{ - ZeroTier::_vtaps_lock.lock(); - ZeroTier::VirtualTap *vtap = NULL; - if (ZeroTier::vtaps.size()) { - vtap = (ZeroTier::VirtualTap *)ZeroTier::vtaps[0]; - } - ZeroTier::_vtaps_lock.unlock(); - return vtap; -} - -/****************************************************************************/ -/* VirtualSocket / VirtualTap helper functions - DON'T CALL THESE DIRECTLY */ -/****************************************************************************/ - -ZeroTier::VirtualSocket *get_virt_socket(int fd) -{ - DEBUG_EXTRA("fd=%d", fd); - ZeroTier::_multiplexer_lock.lock(); - // try to locate in unmapped set - ZeroTier::VirtualSocket *vs = ZeroTier::unmap[fd]; - if (vs == NULL) { - // if not, try to find in mapped set (bind to vtap has been performed) - std::pair *p = ZeroTier::fdmap[fd]; - if (p) { - vs = p->first; - } - else { - DEBUG_ERROR("unable to locate virtual socket"); - } - } - ZeroTier::_multiplexer_lock.unlock(); - return vs; -} - -int del_virt_socket(int fd) -{ - DEBUG_EXTRA("fd=%d", fd); - int err = 0; - ZeroTier::_multiplexer_lock.lock(); - try { - std::map::iterator un_iter = ZeroTier::unmap.find(fd); - if (un_iter != ZeroTier::unmap.end()) { - ZeroTier::unmap.erase(un_iter); - } - std::map*>::iterator fd_iter = ZeroTier::fdmap.find(fd); - if (fd_iter != ZeroTier::fdmap.end()) { - ZeroTier::fdmap.erase(fd_iter); - } - } - catch( ... ) { - DEBUG_ERROR("unable to remove virtual socket"); - handle_general_failure(); - err = -1; - } - ZeroTier::_multiplexer_lock.unlock(); - return err; -} - -int add_unassigned_virt_socket(int fd, ZeroTier::VirtualSocket *vs) -{ - DEBUG_EXTRA("fd=%d, vs=%p", fd, vs); - int err = 0; - ZeroTier::_multiplexer_lock.lock(); - try { - std::map::iterator un_iter = ZeroTier::unmap.find(fd); - if (un_iter == ZeroTier::unmap.end()) { - ZeroTier::unmap[fd] = vs; - } - else { - DEBUG_ERROR("fd=%d already contained in map", fd); - handle_general_failure(); - } - } - catch( ... ) { - DEBUG_ERROR("unable to add virtual socket"); - handle_general_failure(); - err = -1; - } - ZeroTier::_multiplexer_lock.unlock(); - return err; -} - -int del_unassigned_virt_socket(int fd) -{ - DEBUG_EXTRA("fd=%d", fd); - int err = 0; - ZeroTier::_multiplexer_lock.lock(); - try { - std::map::iterator un_iter = ZeroTier::unmap.find(fd); - if (un_iter != ZeroTier::unmap.end()) { - ZeroTier::unmap.erase(un_iter); - } - } - catch( ... ) { - DEBUG_ERROR("unable to remove virtual socket"); - handle_general_failure(); - err = -1; - } - ZeroTier::_multiplexer_lock.unlock(); - return err; -} - -int add_assigned_virt_socket(ZeroTier::VirtualTap *tap, ZeroTier::VirtualSocket *vs, int fd) -{ - DEBUG_EXTRA("tap=%p, vs=%p, fd=%d", tap, vs, fd); - int err = 0; - ZeroTier::_multiplexer_lock.lock(); - try { - std::map*>::iterator fd_iter; - fd_iter = ZeroTier::fdmap.find(fd); - if (fd_iter == ZeroTier::fdmap.end()) { - ZeroTier::fdmap[fd] = new std::pair(vs, tap); - } - else { - DEBUG_ERROR("fd=%d already contained in > map", fd); - handle_general_failure(); - } - } - catch( ... ) { - DEBUG_ERROR("unable to add virtual socket"); - handle_general_failure(); - err = -1; - } - ZeroTier::_multiplexer_lock.unlock(); - return err; -} - -int del_assigned_virt_socket(ZeroTier::VirtualTap *tap, ZeroTier::VirtualSocket *vs, int fd) -{ - DEBUG_EXTRA("tap=%p, vs=%p, fd=%d", tap, vs, fd); - int err = 0; - ZeroTier::_multiplexer_lock.lock(); - try { - std::map*>::iterator fd_iter; - fd_iter = ZeroTier::fdmap.find(fd); - if (fd_iter != ZeroTier::fdmap.end()) { - ZeroTier::fdmap.erase(fd_iter); - } - } - catch( ... ) { - DEBUG_ERROR("unable to remove virtual socket"); - handle_general_failure(); - err = -1; - } - ZeroTier::_multiplexer_lock.unlock(); - return err; -} - -std::pair *get_assigned_virtual_pair(int fd) -{ - ZeroTier::_multiplexer_lock.lock(); - std::pair *p = ZeroTier::fdmap[fd]; - ZeroTier::_multiplexer_lock.unlock(); - return p; -} - -void disableTaps() -{ - ZeroTier::_vtaps_lock.lock(); - for (int i=0; i_enabled = false; - } - ZeroTier::_vtaps_lock.unlock(); -} - -int zts_get_device_id_from_file(const char *filepath, char *devID) { - std::string fname("identity.public"); - std::string fpath(filepath); - if (ZeroTier::OSUtils::fileExists((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),false)) { - std::string oldid; - ZeroTier::OSUtils::readFile((fpath + ZT_PATH_SEPARATOR_S + fname).c_str(),oldid); - memcpy(devID, oldid.c_str(), 10); // first 10 bytes of file - return 0; - } - return -1; -} - -// Starts a ZeroTier service in the background -void *zts_start_service(void *thread_id) -{ - DEBUG_INFO("homeDir=%s", ZeroTier::homeDir.c_str()); - // Where network .conf files will be stored - ZeroTier::netDir = ZeroTier::homeDir + "/networks.d"; - ZeroTier::zt1Service = (ZeroTier::OneService *)0; - // Construct path for network config and supporting service files - if (ZeroTier::homeDir.length()) { - std::vector hpsp(ZeroTier::OSUtils::split(ZeroTier::homeDir.c_str(), ZT_PATH_SEPARATOR_S,"","")); - std::string ptmp; - if (ZeroTier::homeDir[0] == ZT_PATH_SEPARATOR) { - ptmp.push_back(ZT_PATH_SEPARATOR); - } - for (std::vector::iterator pi(hpsp.begin());pi!=hpsp.end();++pi) { - if (ptmp.length() > 0) { - ptmp.push_back(ZT_PATH_SEPARATOR); - } - ptmp.append(*pi); - if ((*pi != ".")&&(*pi != "..")) { - if (ZeroTier::OSUtils::mkdir(ptmp) == false) { - DEBUG_ERROR("home path does not exist, and could not create"); - handle_general_failure(); - perror("error\n"); - } - } - } - } - else { - DEBUG_ERROR("homeDir is empty, could not construct path"); - handle_general_failure(); - return NULL; - } - - // Generate random port for new service instance - unsigned int randp = 0; - ZeroTier::Utils::getSecureRandom(&randp,sizeof(randp)); - // TODO: Better port random range selection - int servicePort = 9000 + (randp % 1000); - for (;;) { - ZeroTier::zt1Service = ZeroTier::OneService::newInstance(ZeroTier::homeDir.c_str(),servicePort); - switch(ZeroTier::zt1Service->run()) { - case ZeroTier::OneService::ONE_STILL_RUNNING: - case ZeroTier::OneService::ONE_NORMAL_TERMINATION: - break; - case ZeroTier::OneService::ONE_UNRECOVERABLE_ERROR: - DEBUG_ERROR("ZTO service port = %d", servicePort); - DEBUG_ERROR("fatal error: %s",ZeroTier::zt1Service->fatalErrorMessage().c_str()); - break; - case ZeroTier::OneService::ONE_IDENTITY_COLLISION: { - delete ZeroTier::zt1Service; - ZeroTier::zt1Service = (ZeroTier::OneService *)0; - std::string oldid; - ZeroTier::OSUtils::readFile((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S - + "identity.secret").c_str(),oldid); - if (oldid.length()) { - ZeroTier::OSUtils::writeFile((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S - + "identity.secret.saved_after_collision").c_str(),oldid); - ZeroTier::OSUtils::rm((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S - + "identity.secret").c_str()); - ZeroTier::OSUtils::rm((ZeroTier::homeDir + ZT_PATH_SEPARATOR_S - + "identity.public").c_str()); - } - } - continue; // restart! - } - break; // terminate loop -- normally we don't keep restarting - } - delete ZeroTier::zt1Service; - ZeroTier::zt1Service = (ZeroTier::OneService *)0; - return NULL; -} - -void handle_general_failure() { -#ifdef ZT_EXIT_ON_GENERAL_FAIL - DEBUG_ERROR("exiting (ZT_EXIT_ON_GENERAL_FAIL==1)"); - exit(-1); -#endif -} - -inline unsigned int gettid() -{ -#ifdef _WIN32 - return GetCurrentThreadId(); -#elif defined(__unix__) - return static_cast(::syscall(__NR_gettid)); -#elif defined(__APPLE__) - uint64_t tid64; - pthread_threadid_np(NULL, &tid64); - return static_cast(tid64); -#endif -} - #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/src/lwIP.cpp b/src/lwIP.cpp index 08c8473..2b1ce42 100644 --- a/src/lwIP.cpp +++ b/src/lwIP.cpp @@ -24,36 +24,38 @@ * of your own application. */ -/* +/** + * @file + * + * lwIP network stack driver + */ - lwIP network stack driver +#include "VirtualTap.hpp" -NOTES: - - Calls made in this network stack driver may never block since all packet - processing (input and output) as well as timer processing (TCP mainly) is done - in a single execution context. - -*/ - -#include +#include "ZeroTierOne.h" +#include "MAC.hpp" #include "libzt.h" -#include "VirtualTap.hpp" -#include "Utilities.hpp" -#include "lwIP.hpp" +#include "Utilities.h" +#include "Debug.hpp" #include "netif/ethernet.h" +#include "lwip/netif.h" #include "lwip/etharp.h" +#include "lwip/tcpip.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/sys.h" +#include "lwip/tcp.h" +#include "lwip/priv/tcp_priv.h" /* for tcp_debug_print_pcbs() */ +#include "lwip/timeouts.h" +#include "lwip/stats.h" -#include "priv/tcp_priv.h" +#include "lwIP.hpp" -#if defined(LIBZT_IPV6) -#include "lwip/ethip6.h" -#include "lwip/nd6.h" -#endif +netif lwipdev, lwipdev6; -void nd6_tmr(void); +static bool started = false; err_t tapif_init(struct netif *netif) { @@ -61,6 +63,60 @@ err_t tapif_init(struct netif *netif) return ERR_OK; } +/* +static void tcp_timeout(void *data) +{ + DEBUG_EXTRA(); + LWIP_UNUSED_ARG(data); +#if TCP_DEBUG && LWIP_TCP + // tcp_debug_print_pcbs(); +#endif + sys_timeout(5000, tcp_timeout, NULL); +} +*/ + +// callback for when the TCPIP thread has been successfully started +static void tcpip_init_done(void *arg) +{ + DEBUG_EXTRA(); + sys_sem_t *sem; + sem = (sys_sem_t *)arg; + netif_set_up(&lwipdev); + DEBUG_INFO("Applications started."); + // sys_timeout(5000, tcp_timeout, NULL); + sys_sem_signal(sem); +} + +// main thread which starts the initialization process +static void main_network_stack_thread(void *arg) +{ + DEBUG_EXTRA(); + sys_sem_t sem; + LWIP_UNUSED_ARG(arg); + if (sys_sem_new(&sem, 0) != ERR_OK) { + DEBUG_ERROR("Failed to create semaphore", 0); + } + tcpip_init(tcpip_init_done, &sem); + sys_sem_wait(&sem); + DEBUG_INFO("TCP/IP initialized."); + sys_sem_wait(&sem); +} + +// initialize the lwIP stack +void lwip_driver_init() +{ + DEBUG_EXTRA(); + // TODO: this should be replaced with something thread-safe + if (started == false) { + started=true; + } + else { + return; + } + sys_thread_new("main_network_stack_thread", main_network_stack_thread, + NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); +} + err_t lwip_eth_tx(struct netif *netif, struct pbuf *p) { struct pbuf *q; @@ -102,1710 +158,87 @@ err_t lwip_eth_tx(struct netif *netif, struct pbuf *p) return ERR_OK; } -namespace ZeroTier +void lwip_init_interface(void *tapref, const ZeroTier::MAC &mac, const ZeroTier::InetAddress &ip) { - void lwIP::lwip_init_interface(VirtualTap *tap, const InetAddress &ip) - { - /* NOTE: It is a known issue that when assigned more than one IP address via - Central, this interface will be unable to transmit (including ARP). */ - Mutex::Lock _l(tap->_ips_m); - - if (std::find(tap->_ips.begin(),tap->_ips.end(),ip) == tap->_ips.end()) { - tap->_ips.push_back(ip); - std::sort(tap->_ips.begin(),tap->_ips.end()); - char ipbuf[INET6_ADDRSTRLEN], nmbuf[INET6_ADDRSTRLEN]; -#if defined(LIBZT_IPV4) - if (ip.isV4()) { - static ip_addr_t ipaddr, netmask, gw; - IP4_ADDR(&gw,127,0,0,1); - ipaddr.addr = *((u32_t *)ip.rawIpData()); - netmask.addr = *((u32_t *)ip.netmask().rawIpData()); - netif_add(&(tap->lwipdev),&ipaddr, &netmask, &gw, NULL, tapif_init, ethernet_input); - tap->lwipdev.state = tap; - tap->lwipdev.output = etharp_output; - tap->lwipdev.mtu = tap->_mtu; - tap->lwipdev.name[0] = 'l'; - tap->lwipdev.name[1] = '4'; - tap->lwipdev.linkoutput = lwip_eth_tx; - tap->lwipdev.hwaddr_len = 6; - tap->_mac.copyTo(tap->lwipdev.hwaddr, tap->lwipdev.hwaddr_len); - tap->lwipdev.flags = NETIF_FLAG_BROADCAST - | NETIF_FLAG_ETHARP - | NETIF_FLAG_IGMP - | NETIF_FLAG_LINK_UP - | NETIF_FLAG_UP; - netif_set_default(&(tap->lwipdev)); - netif_set_link_up(&(tap->lwipdev)); - netif_set_up(&(tap->lwipdev)); - char macbuf[ZT_MAC_ADDRSTRLEN]; - mac2str(macbuf, ZT_MAC_ADDRSTRLEN, tap->lwipdev.hwaddr); - DEBUG_INFO("mac=%s, addr=%s, nm=%s", macbuf, ip.toString(ipbuf), ip.netmask().toString(nmbuf)); - } -#endif -#if defined(LIBZT_IPV6) - if (ip.isV6()) { - static ip6_addr_t addr6; - struct sockaddr_in6 in6; - memcpy(in6.sin6_addr.s6_addr,ip.rawIpData(),16); - in6_to_ip6((ip6_addr *)&addr6, &in6); - tap->lwipdev6.mtu = tap->_mtu; - tap->lwipdev6.name[0] = 'l'; - tap->lwipdev6.name[1] = '6'; - - // hwaddr - tap->lwipdev6.hwaddr_len = 6; - tap->_mac.copyTo(tap->lwipdev6.hwaddr, tap->lwipdev6.hwaddr_len); - - // I/O - tap->lwipdev6.linkoutput = lwip_eth_tx; - tap->lwipdev6.output_ip6 = ethip6_output; - netif_add(&(tap->lwipdev6), NULL, tapif_init, ethernet_input); - - //struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx - //netif_add_ip6_address(); - - // linklocal - tap->lwipdev6.ip6_autoconfig_enabled = 1; - netif_create_ip6_linklocal_address(&(tap->lwipdev6), 1); - netif_ip6_addr_set_state(&(tap->lwipdev6), 0, IP6_ADDR_TENTATIVE); - - // manually config addresses - ip6_addr_copy(ip_2_ip6(tap->lwipdev6.ip6_addr[1]), addr6); - netif_ip6_addr_set_state(&(tap->lwipdev6), 1, IP6_ADDR_TENTATIVE); - - netif_set_default(&(tap->lwipdev6)); - netif_set_link_up(&(tap->lwipdev6)); - - // state and flags - tap->lwipdev6.state = tap; - tap->lwipdev6.flags = NETIF_FLAG_LINK_UP - | NETIF_FLAG_UP; - - netif_set_up(&(tap->lwipdev6)); - - char macbuf[ZT_MAC_ADDRSTRLEN]; - mac2str(macbuf, ZT_MAC_ADDRSTRLEN, tap->lwipdev6.hwaddr); - DEBUG_INFO("mac=%s, addr=%s", macbuf, ip.toString(ipbuf)); - } -#endif - } - } - - int lwIP::lwip_num_current_tcp_pcbs() - { - // TODO: These will likely need some sort of locking protection - int count = 0; - struct tcp_pcb *pcb_ptr = tcp_active_pcbs; // PCBs that can RX/TX data - while (pcb_ptr) { - pcb_ptr = pcb_ptr->next; - count++; - } - pcb_ptr = tcp_tw_pcbs; // PCBs in TIME-WAIT state - while (pcb_ptr) { - pcb_ptr = pcb_ptr->next; - count++; - } - /* TODO - pcb_ptr = tcp_listen_pcbs; - while (pcb_ptr) { - pcb_ptr = pcb_ptr->next; - count++; - DEBUG_ERROR("FOUND --- tcp_listen_pcbs PCB COUNT = %d", count); - }*/ - pcb_ptr = tcp_bound_pcbs; // PCBs in a bound state - while (pcb_ptr) { - pcb_ptr = pcb_ptr->next; - count++; - } - return count; - } - - int lwIP::lwip_num_current_udp_pcbs() - { - // TODO: These will likely need some sort of locking protection - int count = 0; - struct udp_pcb *pcb_ptr = udp_pcbs; - while (pcb_ptr) { - pcb_ptr = pcb_ptr->next; - count++; - } - return count; - } - - int lwIP::lwip_num_current_raw_pcbs() - { - // TODO: These will likely need some sort of locking protection - /* - int count = 0; - struct raw_pcb *pcb_ptr = raw_pcbs; - while (pcb_ptr) { - pcb_ptr = pcb_ptr->next; - count++; - DEBUG_ERROR("FOUND --- raw_pcbs PCB COUNT = %d", count); - } - return count; - */ - return 0; - } - - int lwIP::lwip_num_total_pcbs() - { - return lwip_num_current_raw_pcbs() + lwip_num_current_udp_pcbs() + lwip_num_current_tcp_pcbs(); - } - - int lwIP::lwip_add_dns_nameserver(struct sockaddr *addr) - { - return -1; - } - - int lwIP::lwip_del_dns_nameserver(struct sockaddr *addr) - { - return -1; - } - - void lwIP::lwip_loop(VirtualTap *tap) - { - uint64_t prev_tcp_time = 0, prev_discovery_time = 0; - while (tap->_run) - { - uint64_t now = OSUtils::now(); - uint64_t since_tcp = now - prev_tcp_time; - uint64_t since_discovery = now - prev_discovery_time; - uint64_t tcp_remaining = LWIP_TCP_TIMER_INTERVAL; - uint64_t discovery_remaining = 5000; - -#if defined(LIBZT_IPV6) - #define DISCOVERY_INTERVAL 1000 -#elif defined(LIBZT_IPV4) - #define DISCOVERY_INTERVAL ARP_TMR_INTERVAL -#endif - // Main TCP/ETHARP timer section - if (since_tcp >= LWIP_TCP_TIMER_INTERVAL) { - prev_tcp_time = now; - tcp_tmr(); - } - else { - tcp_remaining = LWIP_TCP_TIMER_INTERVAL - since_tcp; - } - if (since_discovery >= DISCOVERY_INTERVAL) { - prev_discovery_time = now; -#if defined(LIBZT_IPV4) - etharp_tmr(); -#endif -#if defined(LIBZT_IPV6) - nd6_tmr(); -#endif - } else { - discovery_remaining = DISCOVERY_INTERVAL - since_discovery; - } - tap->_phy.poll((unsigned long)std::min(tcp_remaining,discovery_remaining)); - tap->Housekeeping(); - } - } - - void lwIP::lwip_eth_rx(VirtualTap *tap, const MAC &from, const MAC &to, unsigned int etherType, - const void *data, unsigned int len) - { - struct pbuf *p,*q; - if (tap->_enabled == false) { - return; - } - struct eth_hdr ethhdr; - from.copyTo(ethhdr.src.addr, 6); - to.copyTo(ethhdr.dest.addr, 6); - ethhdr.type = ZeroTier::Utils::hton((uint16_t)etherType); - - p = pbuf_alloc(PBUF_RAW, len+sizeof(struct eth_hdr), PBUF_POOL); - if (p != NULL) { - const char *dataptr = reinterpret_cast(data); - // First pbuf gets ethernet header at start - q = p; - if (q->len < sizeof(ethhdr)) { - DEBUG_ERROR("dropped packet: first pbuf smaller than ethernet header"); - return; - } - memcpy(q->payload,ðhdr,sizeof(ethhdr)); - memcpy((char*)q->payload + sizeof(ethhdr),dataptr,q->len - sizeof(ethhdr)); - dataptr += q->len - sizeof(ethhdr); - // Remaining pbufs (if any) get rest of data - while ((q = q->next)) { - memcpy(q->payload,dataptr,q->len); - dataptr += q->len; - } - } - else { - DEBUG_ERROR("dropped packet: no pbufs available"); - return; - } - if (ZT_MSG_TRANSFER == true) { - char flagbuf[32]; - memset(&flagbuf, 0, 32); - char macBuf[ZT_MAC_ADDRSTRLEN], nodeBuf[ZT_ID_LEN]; - mac2str(macBuf, ZT_MAC_ADDRSTRLEN, ethhdr.dest.addr); - ZeroTier::MAC mac; - mac.setTo(ethhdr.src.addr, 6); - mac.toAddress(tap->_nwid).toString(nodeBuf); - DEBUG_TRANS("len=%5d dst=%s [%s RX --> %s] proto=0x%04x %s %s", len, macBuf, nodeBuf, tap->nodeId().c_str(), - ZeroTier::Utils::ntoh(ethhdr.type), beautify_eth_proto_nums(ZeroTier::Utils::ntoh(ethhdr.type)), flagbuf); - } - { -#if defined(LIBZT_IPV4) - if (tap->lwipdev.input(p, &(tap->lwipdev)) != ERR_OK) { - DEBUG_ERROR("error while feeding frame into stack interface (ipv4)"); - } -#endif -#if defined(LIBZT_IPV6) - if (tap->lwipdev6.input(p, &(tap->lwipdev6)) != ERR_OK) { - DEBUG_ERROR("error while feeding frame into stack interface (ipv6)"); - } -#endif - } - } - - int lwIP::lwip_Socket(void **pcb, int socket_family, int socket_type, int protocol) - { - if (can_provision_new_socket(socket_type) == false) { - DEBUG_ERROR("unable to create socket due to limitation of network stack, PCBs=%d", lwip_num_total_pcbs()); - errno = ENOMEM; - return -1; - } - if (socket_type == SOCK_STREAM) { - struct tcp_pcb *new_tcp_PCB = tcp_new(); - *pcb = new_tcp_PCB; - tcp_nagle_disable(new_tcp_PCB); - return ERR_OK; - } - if (socket_type == SOCK_DGRAM) { - struct udp_pcb *new_udp_PCB = udp_new(); - *pcb = new_udp_PCB; - return ERR_OK; - } - errno = ENOMEM; - return -1; - } - - int lwIP::lwip_Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen) - { - ip_addr_t ba; - char addrstr[INET6_ADDRSTRLEN]; - int port = 0, err = 0; -#if defined(LIBZT_IPV4) - struct sockaddr_in *in4 = (struct sockaddr_in *)addr; - if (addr->sa_family == AF_INET && vs->socket_type == SOCK_STREAM) { - inet_ntop(AF_INET, &(in4->sin_addr), addrstr, INET_ADDRSTRLEN); - DEBUG_EXTRA("connecting to %s : %d", addrstr, lwip_ntohs(in4->sin_port)); - } - ba = convert_ip(in4); - port = lwip_ntohs(in4->sin_port); -#endif -#if defined(LIBZT_IPV6) - struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&addr; - in6_to_ip6((ip6_addr *)&ba, in6); - if (addr->sa_family == AF_INET6 && vs->socket_type == SOCK_STREAM) { - inet_ntop(AF_INET6, &(in6->sin6_addr), addrstr, INET6_ADDRSTRLEN); - DEBUG_EXTRA("connecting to %s : %d", addrstr, lwip_ntohs(in6->sin6_port)); - } -#endif - if (vs->socket_type == SOCK_DGRAM) { - // generates no network traffic - if ((err = udp_connect((struct udp_pcb*)vs->pcb,(ip_addr_t *)&ba,port)) < 0) { - DEBUG_ERROR("error while connecting to with UDP"); - } - udp_recv((struct udp_pcb*)vs->pcb, lwip_cb_udp_recved, vs); - return ERR_OK; - } - if (vs->socket_type == SOCK_STREAM) { - struct tcp_pcb *tpcb = (struct tcp_pcb*)vs->pcb; - tcp_sent(tpcb, lwip_cb_sent); - tcp_recv(tpcb, lwip_cb_tcp_recved); - tcp_err(tpcb, lwip_cb_err); - tcp_poll(tpcb, lwip_cb_poll, LWIP_APPLICATION_POLL_FREQ); - tcp_arg(tpcb, vs); - if ((err = tcp_connect(tpcb,&ba,port,lwip_cb_connected)) < 0) { - errno = lwip_err_to_errno(err); - // We should only return a value if failure happens immediately - // Otherwise, we still need to wait for a callback from lwIP. - // - This is because an ERR_OK from tcp_connect() only verifies - // that the SYN packet was enqueued onto the stack properly, - // that's it! - DEBUG_ERROR("unable to connect"); - err = -1; - } - } - return err; - } - - int lwIP::lwip_Bind(VirtualTap *tap, VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen) - { - // TODO: Check case for IP_ADDR_ANY - ip_addr_t ba; - char addrstr[INET6_ADDRSTRLEN]; - memset(addrstr, 0, INET6_ADDRSTRLEN); - int port = 0, err = 0; -#if defined(LIBZT_IPV4) - struct sockaddr_in *in4 = (struct sockaddr_in *)addr; - if (addr->sa_family == AF_INET) { - inet_ntop(AF_INET, &(in4->sin_addr), addrstr, INET_ADDRSTRLEN); - DEBUG_EXTRA("binding to %s : %d", addrstr, lwip_ntohs(in4->sin_port)); - } - ba = convert_ip(in4); - port = lwip_ntohs(in4->sin_port); -#endif -#if defined(LIBZT_IPV6) - struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr; - in6_to_ip6((ip6_addr *)&ba, in6); - if (addr->sa_family == AF_INET6) { - inet_ntop(AF_INET6, &(in6->sin6_addr), addrstr, INET6_ADDRSTRLEN); - DEBUG_EXTRA("binding to %s : %d", addrstr, lwip_ntohs(in6->sin6_port)); - } -#endif - if (vs->socket_type == SOCK_DGRAM) { - if ((err = udp_bind((struct udp_pcb*)vs->pcb, (const ip_addr_t *)&ba, port)) < 0) { - errno = lwip_err_to_errno(err); - err = -1; - } - else { - // set callback - udp_recv((struct udp_pcb*)vs->pcb, lwip_cb_udp_recved, vs); - err = ERR_OK; - } - } - else if (vs->socket_type == SOCK_STREAM) { - if ((err = tcp_bind((struct tcp_pcb*)vs->pcb, (const ip_addr_t *)&ba, port)) < 0) { - errno = lwip_err_to_errno(err); - err = -1; - } - else { - err = ERR_OK; - } - } - return err; - } - - int lwIP::lwip_Listen(VirtualSocket *vs, int backlog) - { - int err = 0; - struct tcp_pcb* listeningPCB; -#ifdef TCP_LISTEN_BACKLOG - listeningPCB = tcp_listen_with_backlog((struct tcp_pcb*)vs->pcb, backlog); -#else - listeningPCB = tcp_listen((struct tcp_pcb*)vs->pcb); -#endif - if (listeningPCB) { - vs->pcb = listeningPCB; - // set callback - tcp_accept(listeningPCB, lwip_cb_accept); - tcp_arg(listeningPCB, vs); - err = ERR_OK; - } - else { - errno = ENOMEM; - err = -1; - } - return err; - } - - VirtualSocket* lwIP::lwip_Accept(VirtualSocket *vs) - { - if (vs == NULL) { - DEBUG_ERROR("invalid virtual socket"); - handle_general_failure(); - return NULL; - } - // Retreive first of queued VirtualSockets from parent VirtualSocket - // TODO: check multithreaded behaviour - VirtualSocket *new_vs = NULL; - if (vs->_AcceptedConnections.size()) { - new_vs = vs->_AcceptedConnections.front(); - vs->_AcceptedConnections.pop(); - } - return new_vs; - } - - int lwIP::lwip_Read(VirtualSocket *vs, bool lwip_invoked) - { - DEBUG_EXTRA("vs=%p", vs); - int err = 0; - if (vs == NULL) { - DEBUG_ERROR("no virtual socket"); - return -1; - } - if (lwip_invoked == false) { - DEBUG_INFO("!lwip_invoked"); - vs->tap->_tcpconns_m.lock(); - vs->_rx_m.lock(); - } - if (vs->socket_type == SOCK_STREAM && vs->RXbuf->count()) { - handle_general_failure(); - int wr = std::min((ssize_t)ZT_STACK_TCP_SOCKET_RX_SZ, (ssize_t)vs->RXbuf->count()); - int n = vs->tap->_phy.streamSend(vs->sock, vs->RXbuf->get_buf(), wr); - if (n > 0) { - vs->RXbuf->consume(n); - tcp_recved((struct tcp_pcb*)vs->pcb, n); - DEBUG_TRANS("TCP RX %d bytes", n); - } - } - if (vs->RXbuf->count() == 0) { - vs->tap->_phy.setNotifyWritable(vs->sock, false); // nothing else to send to the app - } - if (lwip_invoked == false) { - vs->tap->_tcpconns_m.unlock(); - vs->_rx_m.unlock(); - } - return err; - } - - int lwIP::lwip_Write(VirtualSocket *vs, void *data, ssize_t len) - { - int err = 0; - if (vs == NULL) { - DEBUG_ERROR("no virtual socket"); - return -1; - } - DEBUG_EXTRA("fd=%d, vs=%p, pcb=%p, pcb->state=%d, len=%d", - vs->app_fd, vs, (struct tcp_pcb*)(vs->pcb), ((struct tcp_pcb*)(vs->pcb))->state, len); - if (vs->socket_type == SOCK_DGRAM) { - // TODO: Packet re-assembly hasn't yet been tested with lwIP so UDP packets are limited to MTU-sized chunks - int udp_trans_len = std::min(len, (ssize_t)ZT_MAX_MTU); - struct pbuf * pb = pbuf_alloc(PBUF_TRANSPORT, udp_trans_len, PBUF_POOL); - if (pb == NULL) { - DEBUG_ERROR("unable to allocate new pbuf of len=%d", udp_trans_len); - return -1; - } - memcpy(pb->payload, data, udp_trans_len); - int err = udp_send((struct udp_pcb*)vs->pcb, pb); - - if (err == ERR_MEM) { - DEBUG_ERROR("error sending packet. out of memory"); - } else if (err == ERR_RTE) { - DEBUG_ERROR("could not find route to destinations address"); - } else if (err != ERR_OK) { - DEBUG_ERROR("error sending packet - %d", err); - } - pbuf_free(pb); - if (err == ERR_OK) { - return udp_trans_len; - } - } - if (vs->socket_type == SOCK_STREAM) { - // How much we are currently allowed to write to the VirtualSocket - ssize_t sndbuf = ((struct tcp_pcb*)vs->pcb)->snd_buf; - if (sndbuf == 0) { - // PCB send buffer is full, turn off readability notifications for the - // corresponding PhySocket until lwip_cb_sent() is called and confirms that there is - // now space on the buffer - DEBUG_ERROR("lwIP stack is full, sndbuf==0"); - //vs->tap->_phy.setNotifyReadable(vs->sock, false); - err = -1; - } - vs->_tx_m.lock(); - int buf_w = vs->TXbuf->write((const unsigned char*)data, len); - if (buf_w != len) { - DEBUG_ERROR("only wrote len=%d but expected to write len=%d to TX buffer", buf_w, len); - handle_general_failure(); - err = ZT_ERR_GENERAL_FAILURE; - } - if (vs->TXbuf->count() <= 0) { - err = -1; // nothing to write - } - if (err == ERR_OK) { - int r = std::min((ssize_t)vs->TXbuf->count(), sndbuf); - // Writes data pulled from the client's socket buffer to LWIP. This merely sends the - // data to LWIP to be enqueued and eventually sent to the network. - if (r > 0) { - err = tcp_write((struct tcp_pcb*)vs->pcb, vs->TXbuf->get_buf(), r, vs->copymode); - tcp_output((struct tcp_pcb*)vs->pcb); - if (err != ERR_OK) { - DEBUG_ERROR("error while writing to lwIP tcp_pcb, err=%d", err); - if (err == ERR_MEM) { - DEBUG_ERROR("lwIP out of memory"); - } - err = -1; - } else { - if (vs->copymode & TCP_WRITE_FLAG_COPY) { - // since we copied the data (allocated pbufs), we can consume the buffer - vs->TXbuf->consume(r); // success - DEBUG_TRANS("len=%5d tx_buf_len=%10d [VSTXBF --> NSLWIP]", err, vs->TXbuf->count()); - } - else { - // since we only processed the data by pointer reference we - // want to preserve it until it has been ACKed by the remote host - // (DO NOTHING) - } - err = ERR_OK; - } - } - } - vs->_tx_m.unlock(); - } - return err; - } - - int lwIP::lwip_Close(VirtualSocket *vs) - { - // requests to close non-LISTEN PCBs are handled lwip_cb_poll() - int err = -1; - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - handle_general_failure(); - return -1; - } - if (vs->socket_type == SOCK_STREAM) { - struct tcp_pcb *tpcb = (struct tcp_pcb*)(vs->pcb); - if (tpcb == NULL) { - DEBUG_ERROR("invalid pcb"); - handle_general_failure(); - return -1; - } - // should be safe to tcp_close() from application thread IF PCB is in LISTENING state (I think) - if (tpcb->state == LISTEN) { - DEBUG_EXTRA("PCB is in LISTEN, calling tcp_close() from application thread."); - tcp_accept(tpcb, NULL); - if ((err = tcp_close(tpcb)) < 0) { - DEBUG_ERROR("error while calling tcp_close, fd=%d, vs=%p, pcb=%p", vs->app_fd, vs, vs->pcb); - errno = lwip_err_to_errno(err); - err = -1; - } - return ERR_OK; - } - // handle junk state values - if (tpcb->state > TIME_WAIT) { - DEBUG_EXTRA("invalid TCP pcb state, already closed, report ERR_OK"); - return ERR_OK; - } - else { - // place a request for the stack to close this VirtualSocket's PCB - vs->set_state(VS_STATE_SHOULD_SHUTDOWN); - // wait for indication of success, this will block if the PCB can't close - while (true) { - sleep(1); - nanosleep((const struct timespec[]) {{0, (ZT_API_CHECK_INTERVAL * 1000000)}}, NULL); - DEBUG_EXTRA("checking closure state... pcb->state=%d", tpcb->state); - if (vs->get_state() == VS_STATE_CLOSED || tpcb->state == CLOSED) { - return ERR_OK; - } - } - } - } - if (vs->socket_type == SOCK_DGRAM) { - // place a request for the stack to close this VirtualSocket's PCB - vs->set_state(VS_STATE_SHOULD_SHUTDOWN); - } - return err; - } - - int lwIP::lwip_Shutdown(VirtualSocket *vs, int how) - { - int err=0, shut_rx=0, shut_tx=0; - if (how == SHUT_RD) { - shut_rx = 1; - } - if (how == SHUT_WR) { - shut_tx = 1; - } - if (how == SHUT_RDWR) { - shut_rx = 1; - shut_tx = 1; - } - if ((err = tcp_shutdown((tcp_pcb*)(vs->pcb), shut_rx, shut_tx) < 0)) { - DEBUG_ERROR("error while shutting down socket, fd=%d", vs->app_fd); - } - return err; - } - - /****************************************************************************/ - /* Callbacks from lwIP stack */ - /****************************************************************************/ - - // write data from processed packets from the stack to the client app - /* - With the raw API, tcp_recv() sets up to receive data via a callback function. Your callback - is delivered chains of pbufs as they become available. You have to manage extracting data - from the pbuf chain, and don't forget to watch out for multiple pbufs in a single callback: - the 'tot_len' field indicates the total length of data in the pbuf chain. You must call - tcp_recved() to tell LWIP when you have processed the received data. As with the netconn API, - you may receive more or less data than you want, and will have to either wait for further - callbacks, or hold onto excess data for later processing. - - http://lwip.wikia.com/wiki/Receiving_data_with_LWIP - */ - err_t lwIP::lwip_cb_tcp_recved(void *arg, struct tcp_pcb *PCB, struct pbuf *p, err_t err) - { - //DEBUG_INFO(); - VirtualSocket *vs = (VirtualSocket *)arg; - int tot = 0; - if (vs == NULL) { - DEBUG_ERROR("no virtual socket"); - handle_general_failure(); - return ERR_OK; - } - struct pbuf* q = p; - if (p == NULL) { - DEBUG_INFO("p=0x0 for pcb=%p, vs->pcb=%p, this indicates a closure. No need to call tcp_close()", PCB, vs->pcb); - vs->set_state(VS_STATE_SHOULD_SHUTDOWN); - return ERR_ABRT; - } - vs->tap->_tcpconns_m.lock(); - vs->_rx_m.lock(); - // cycle through pbufs and write them to the RX buffer - while (p != NULL) { - if (p->len <= 0) { - break; - } - int avail = ZT_TCP_RX_BUF_SZ - vs->RXbuf->count(); - int len = p->len; - if (avail < len) { - DEBUG_ERROR("not enough room (%d bytes) on RX buffer", avail); - } - // place new incoming data on ringbuffer before we try to send it to the app - memcpy(vs->RXbuf->get_buf(), p->payload, len); - vs->RXbuf->produce(len); - p = p->next; - tot += len; - } - if (tot) { - tcp_recved(PCB, tot); - DEBUG_TRANS("len=%5d rx_buf_len=%10d [NSLWIP --> VSRXBF]", tot, vs->RXbuf->count()); - int w, write_attempt_sz = vs->RXbuf->count() < ZT_MAX_MTU ? vs->RXbuf->count() : ZT_MAX_MTU; - if ((w = write(vs->sdk_fd, vs->RXbuf->get_buf(), write_attempt_sz)) < 0) { - DEBUG_ERROR("write(fd=%d)=%d, errno=%d", vs->sdk_fd, w, errno); - } - if (w > 0) { - vs->RXbuf->consume(w); - if (w < write_attempt_sz) { - DEBUG_TRANS("len=%5d rx_buf_len=%10d [VSRXBF --> APPFDS]", w, vs->RXbuf->count()); - DEBUG_EXTRA("intended to write len=%d, only wrote len=%d", write_attempt_sz, w); - } - else { - DEBUG_TRANS("len=%5d rx_buf_len=%10d [VSRXBF --> APPFDS]", w, vs->RXbuf->count()); - } - } - } - else { - DEBUG_EXTRA("warning, wrote 0 bytes"); - } - vs->tap->_tcpconns_m.unlock(); - vs->_rx_m.unlock(); - pbuf_free(q); - return ERR_OK; - } - - // callback from stack to notify driver of the successful acceptance of a connection - err_t lwIP::lwip_cb_accept(void *arg, struct tcp_pcb *newPCB, err_t err) - { - VirtualSocket *vs = (VirtualSocket*)arg; - struct sockaddr_storage ss; -#if defined(LIBZT_IPV4) - struct sockaddr_in *in4 = (struct sockaddr_in *)&ss; - in4->sin_addr.s_addr = newPCB->remote_ip.addr; - in4->sin_port = newPCB->remote_port; -#endif -#if defined(LIBZT_IPV6) - struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&ss; - // TODO: check this - memcpy(&(in6->sin6_addr.s6_addr), &(newPCB->remote_ip), sizeof(int32_t)*4); - in6->sin6_port = newPCB->remote_port; -#endif - VirtualSocket *new_vs = new VirtualSocket(); - new_vs->socket_type = SOCK_STREAM; - new_vs->pcb = newPCB; - new_vs->tap = vs->tap; - new_vs->sock = vs->tap->_phy.wrapSocket(new_vs->sdk_fd, new_vs); - memcpy(&(new_vs->peer_addr), &ss, sizeof(new_vs->peer_addr)); - // add new VirtualSocket object to parent VirtualSocket so that we can find it via lwip_Accept() - vs->_AcceptedConnections.push(new_vs); - // set callbacks - tcp_arg(newPCB, new_vs); - tcp_recv(newPCB, lwip_cb_tcp_recved); - tcp_err(newPCB, lwip_cb_err); - tcp_sent(newPCB, lwip_cb_sent); - tcp_poll(newPCB, lwip_cb_poll, 1); - // let lwIP know that it can queue additional incoming PCBs - tcp_accepted((struct tcp_pcb*)vs->pcb); - return 0; - } - - // copy processed datagram to app socket - void lwIP::lwip_cb_udp_recved(void * arg, struct udp_pcb * upcb, struct pbuf * p, const ip_addr_t * addr, u16_t port) - { - //DEBUG_EXTRA("arg(vs)=%p, pcb=%p, port=%d)", arg, upcb, port); - VirtualSocket *vs = (VirtualSocket *)arg; - if (vs == NULL) { - DEBUG_ERROR("invalid virtual socket"); - return; - } - if (p == NULL) { - DEBUG_ERROR("p == NULL"); - return; - } - struct pbuf* q = p; - struct sockaddr_storage ss; - -#if defined(LIBZT_IPV4) - struct sockaddr_in *in4 = (struct sockaddr_in *)&ss; - in4->sin_addr.s_addr = addr->addr; - in4->sin_port = port; -#endif -#if defined(LIBZT_IPV6) - struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&ss; - memcpy(&(in6->sin6_addr.s6_addr), &(addr->addr), sizeof(int32_t)*4); - in6->sin6_port = port; -#endif - - char udp_payload_buf[ZT_SOCKET_MSG_BUF_SZ]; - memset(udp_payload_buf, 0, sizeof(ZT_SOCKET_MSG_BUF_SZ)); - char *msg_ptr = udp_payload_buf; - int tot_len = 0; - while (p != NULL) { - if (p->len <= 0) { - break; - } - memcpy(msg_ptr, p->payload, p->len); - msg_ptr += p->len; - tot_len += p->len; - p = p->next; - } - if (tot_len > 0) { - int w = 0; - // [sz : addr : payload] - char udp_msg_buf[ZT_SOCKET_MSG_BUF_SZ]; - memset(udp_msg_buf, 0, sizeof(ZT_SOCKET_MSG_BUF_SZ)); - int32_t len = sizeof(struct sockaddr_storage) + tot_len; - int32_t msg_tot_len = sizeof(int32_t) + len; - // len: sockaddr+payload - memcpy(udp_msg_buf, &len, sizeof(int32_t)); - // sockaddr - memcpy(udp_msg_buf + sizeof(int32_t), &ss, sizeof(struct sockaddr_storage)); - // payload - memcpy(udp_msg_buf + sizeof(int32_t) + sizeof(struct sockaddr_storage), &udp_payload_buf, tot_len); - if ((w = write(vs->sdk_fd, udp_msg_buf, msg_tot_len)) < 0) { - DEBUG_ERROR("write(fd=%d)=%d, errno=%d", vs->sdk_fd, w, errno); - } - } - pbuf_free(q); - } - - // callback from stack to notify driver that data was sent - err_t lwIP::lwip_cb_sent(void* arg, struct tcp_pcb *PCB, u16_t len) - { - //DEBUG_EXTRA("pcb=%p", PCB); - VirtualSocket *vs = (VirtualSocket *)arg; - if (vs == NULL) { - DEBUG_ERROR("invalid vs for PCB=%p, len=%d", PCB, len); - } - if ((vs->copymode & TCP_WRITE_FLAG_COPY) == false) { - /* - From lwIP docs: - - To achieve zero-copy on transmit, the data passed to the raw API must - remain unchanged until sent. Because the send- (or write-)functions return - when the packets have been enqueued for sending, data must be kept stable - after that, too. - - This implies that PBUF_RAM/PBUF_POOL pbufs passed to raw-API send functions - must *not* be reused by the application unless their ref-count is 1. - - For no-copy pbufs (PBUF_ROM/PBUF_REF), data must be kept unchanged, too, - but the stack/driver will/must copy PBUF_REF'ed data when enqueueing, while - PBUF_ROM-pbufs are just enqueued (as ROM-data is expected to never change). - - Also, data passed to tcp_write without the copy-flag must not be changed! - - Therefore, be careful which type of PBUF you use and if you copy TCP data - or not! - */ - - // since we decided in lwip_Write() not to consume the buffere data, as it - // was not copied and was only used by pointer reference, we can now consume - // the data on the buffer since we've got an ACK back from the remote host - vs->_tx_m.lock(); - vs->TXbuf->consume(len); - vs->_tx_m.unlock(); - } - return ERR_OK; - } - - err_t lwIP::lwip_cb_connected(void *arg, struct tcp_pcb *PCB, err_t err) - { - DEBUG_EXTRA("pcb=%p", PCB); - VirtualSocket *vs = (VirtualSocket *)arg; - if (vs == NULL) { - DEBUG_ERROR("invalid virtual socket"); - return -1; - } - // add to unhandled connection set for zts_connect to pick up on - vs->tap->_tcpconns_m.lock(); - vs->set_state(VS_STATE_UNHANDLED_CONNECTED); - vs->tap->_VirtualSockets.push_back(vs); - vs->tap->_tcpconns_m.unlock(); - return ERR_OK; - } - - err_t lwIP::lwip_cb_poll(void* arg, struct tcp_pcb *PCB) - { - VirtualSocket *vs = (VirtualSocket *)arg; - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - handle_general_failure(); - return ERR_OK; // TODO: determine appropriate error value, if any - } - if (vs->socket_type == SOCK_DGRAM) { - DEBUG_INFO("fd=%d, vs=%p, pcb=%p", vs->app_fd, vs, PCB, vs->pcb); - } - - // Handle PCB closure requests (set in lwip_Close()) - if (vs->get_state() == VS_STATE_SHOULD_SHUTDOWN) { - DEBUG_EXTRA("closing pcb=%p, fd=%d, vs=%p", PCB, vs->app_fd, vs); - int err = 0; - errno = 0; - if (vs->socket_type == SOCK_DGRAM) { - udp_remove((struct udp_pcb*)vs->pcb); - } - if (vs->socket_type == SOCK_STREAM) { - if (vs->pcb) { - struct tcp_pcb* tpcb = (struct tcp_pcb*)vs->pcb; - if (tpcb->state == CLOSED) { - DEBUG_EXTRA("pcb is in CLOSED state"); - // calling tcp_close() here would be redundant - return 0; - } - //if (tpcb->state == CLOSE_WAIT) { - // DEBUG_EXTRA("pcb is in CLOSE_WAIT state"); - // // calling tcp_close() here would be redundant - //} - if (tpcb->state > TIME_WAIT) { - DEBUG_ERROR("warning, pcb=%p is in an invalid state=%d", vs->pcb, tpcb->state); - handle_general_failure(); - err = -1; - } - // unregister callbacks for this PCB - tcp_arg(tpcb, NULL); - if (tpcb->state == LISTEN) { - tcp_accept(tpcb, NULL); - } - else { - tcp_recv(tpcb, NULL); - tcp_sent(tpcb, NULL); - tcp_poll(tpcb, NULL, 0); - tcp_err(tpcb, NULL); - } - if ((err = tcp_close(tpcb)) < 0) { - DEBUG_ERROR("error while calling tcp_close, fd=%d, vs=%p, pcb=%p", vs->app_fd, vs, vs->pcb); - errno = lwip_err_to_errno(err); - err = -1; - } - else { - vs->set_state(VS_STATE_CLOSED); // success - } - } - } - } - - - // Handle transmission and reception of data - if (vs->socket_type == SOCK_STREAM) { - DEBUG_INFO("fd=%d, vs=%p, PCB=%p, vs->pcb=%p, vs->pcb->state=%d", vs->app_fd, vs, PCB, (struct tcp_pcb*)(vs->pcb), ((struct tcp_pcb*)(vs->pcb))->state); - if (((struct tcp_pcb*)(vs->pcb))->state == CLOSE_WAIT) { - DEBUG_EXTRA("pcb->state=CLOSE_WAIT. do nothing"); - return ERR_OK; - } - if (((struct tcp_pcb*)(vs->pcb))->state == CLOSED) { - DEBUG_EXTRA("pcb->state=CLOSED. do nothing"); - return ERR_OK; - } - // --- Check buffers to see if we need to finish reading/writing anything --- - - // TODO: Make a more generic form of each of these RX/TX blocks that can be shared - // between all polling callbacks and read write methods - - // RX - vs->_rx_m.lock(); - if (vs->RXbuf->count()) { - // this data has already been acknowledged via tcp_recved(), we merely need to - // move it off of the ringbuffer and into the client app - int w, write_attempt_sz = vs->RXbuf->count() < ZT_MAX_MTU ? vs->RXbuf->count() : ZT_MAX_MTU; - if ((w = write(vs->sdk_fd, vs->RXbuf->get_buf(), write_attempt_sz)) < 0) { - DEBUG_ERROR("write(fd=%d)=%d, errno=%d", vs->sdk_fd, w, errno); - } - if (w > 0) { - vs->RXbuf->consume(w); - if (w < write_attempt_sz) { - DEBUG_TRANS("len=%5d rx_buf_len=%10d [VSRXBF --> APPFDS]", w, vs->RXbuf->count()); - DEBUG_EXTRA("intended to write len=%d, only wrote len=%d", write_attempt_sz, w); - } - else { - DEBUG_TRANS("len=%5d rx_buf_len=%10d [VSRXBF --> APPFDS]", w, vs->RXbuf->count()); - } - } - } - vs->_rx_m.unlock(); - // No need to lock the TX buffer since lwip_Write() will lock it for us - // TX - if (vs->TXbuf->count()) { - // we previously attempted to tcp_write(), but something went wrong, this - // is where we retry - lwipstack->lwip_Write(vs, vs->TXbuf->get_buf(), vs->TXbuf->count()); - } - } - return ERR_OK; - } - - int lwIP::lwip_setsockopt(VirtualSocket *vs, int level, int optname, const void *optval, socklen_t optlen) - { - int err = -1; - errno = 0; - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - return -1; - } else { - DEBUG_EXTRA("fd=%d, level=%d, optname=%d", vs->app_fd, level, optname); - } - if (level == SOL_SOCKET) - { - /* Turns on recording of debugging information. This option enables or disables debugging in the underlying - protocol modules. This option takes an int value. This is a Boolean option.*/ - if (optname == SO_DEBUG) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Specifies that the rules used in validating addresses supplied to bind() should allow reuse of local - addresses, if this is supported by the protocol. This option takes an int value. This is a Boolean option.*/ - if (optname == SO_REUSEADDR) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Keeps connections active by enabling the periodic transmission of messages, if this is supported by the - protocol. This option takes an int value. */ - if (optname == SO_KEEPALIVE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Requests that outgoing messages bypass the standard routing facilities. */ - if (optname == SO_DONTROUTE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Lingers on a close() if data is present. */ - if (optname == SO_LINGER) - { - // we do this at the VirtualSocket layer since lwIP's raw API doesn't currently have a way to do this - vs->optflags &= VS_OPT_SO_LINGER; - return 0; - } - /* Permits sending of broadcast messages, if this is supported by the protocol. This option takes an int - value. This is a Boolean option. */ - if (optname == SO_BROADCAST) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Leaves received out-of-band data (data marked urgent) inline. This option takes an int value. This is a - Boolean option. */ - if (optname == SO_OOBINLINE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Sets send buffer size. This option takes an int value. */ - if (optname == SO_SNDBUF) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Sets receive buffer size. This option takes an int value. */ - if (optname == SO_RCVBUF) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* */ - if (optname == SO_STYLE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* */ - if (optname == SO_TYPE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Get error status and clear */ - if (optname == SO_ERROR) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - } - if (level == IPPROTO_IP) - { - if (optname == IP_ADD_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_ADD_SOURCE_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_BIND_ADDRESS_NO_PORT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_BLOCK_SOURCE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_DROP_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_DROP_SOURCE_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_FREEBIND) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_HDRINCL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MSFILTER) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MTU) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MTU_DISCOVER) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_ALL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_IF) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_LOOP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_TTL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_NODEFRAG) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_OPTIONS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_PKTINFO) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVOPTS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVORIGDSTADDR) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVTOS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVTTL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RETOPTS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_ROUTER_ALERT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TOS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TRANSPARENT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TTL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_UNBLOCK_SOURCE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - // TODO - return -1; - } - if (level == IPPROTO_TCP) - { - struct tcp_pcb *pcb = (struct tcp_pcb*)(vs->pcb); - if (pcb == NULL) { - handle_general_failure(); - return -1; - } - /* If set, don't send out partial frames. */ - if (optname == TCP_CORK) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Allow a listener to be awakened only when data arrives on the socket. */ - if (optname == TCP_DEFER_ACCEPT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Used to collect information about this socket. The kernel returns a struct tcp_info as defined in the - file /usr/include/linux/tcp.h.*/ - if (optname == TCP_INFO) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The maximum number of keepalive probes TCP should send before dropping the connection.*/ - if (optname == TCP_KEEPCNT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes, - if the socket option SO_KEEPALIVE has been set on this socket. */ - if (optname == TCP_KEEPIDLE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The time (in seconds) between individual keepalive probes.*/ - if (optname == TCP_KEEPINTVL) { - // TODO - return -1; - } - /* The lifetime of orphaned FIN_WAIT2 state sockets. */ - if (optname == TCP_LINGER2) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The maximum segment size for outgoing TCP packets. */ - if (optname == TCP_MAXSEG) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* If set, disable the Nagle algorithm. */ - if (optname == TCP_NODELAY) { - int enable_nagle = *((const int*)optval); - if (enable_nagle == true) { - tcp_nagle_enable(pcb); - } else { - tcp_nagle_disable(pcb); - } - return 0; - } - /* Enable quickack mode if set or disable quickack mode if cleared. */ - if (optname == TCP_QUICKACK) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Set the number of SYN retransmits that TCP should send before aborting the attempt to connect. It - cannot exceed 255. */ - if (optname == TCP_SYNCNT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Bound the size of the advertised window to this value. The kernel imposes a minimum size of - SOCK_MIN_RCVBUF/2. */ - if (optname == TCP_WINDOW_CLAMP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - } - if (level == IPPROTO_UDP) - { - /*If this option is enabled, then all data output on this socket is accumulated into a single - datagram that is transmitted when the option is disabled. */ - if (optname == UDP_CORK) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - } - return err; - } - - int lwIP::lwip_getsockopt(VirtualSocket *vs, int level, int optname, void *optval, socklen_t *optlen) - { - int err = -1, optval_tmp = 0; - errno = 0; - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - return -1; - } else { - DEBUG_EXTRA("fd=%d, level=%d, optname=%d", vs->app_fd, level, optname); - } - if (level == SOL_SOCKET) - { - /* Turns on recording of debugging information. This option enables or disables debugging in the underlying - protocol modules. This option takes an int value. This is a Boolean option.*/ - if (optname == SO_DEBUG) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Specifies that the rules used in validating addresses supplied to bind() should allow reuse of local - addresses, if this is supported by the protocol. This option takes an int value. This is a Boolean option.*/ - if (optname == SO_REUSEADDR) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Keeps connections active by enabling the periodic transmission of messages, if this is supported by the - protocol. This option takes an int value. */ - if (optname == SO_KEEPALIVE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Requests that outgoing messages bypass the standard routing facilities. */ - if (optname == SO_DONTROUTE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Get SO_LINGER flag value */ - if (optname == SO_LINGER) - { - // we do this at the VirtualSocket layer since lwIP's raw API doesn't currently have a way to do this - optval_tmp = (vs->optflags & VS_OPT_SO_LINGER); - memcpy(optval, &optval_tmp, *optlen); - return 0; - } - /* Permits sending of broadcast messages, if this is supported by the protocol. This option takes an int - value. This is a Boolean option. */ - if (optname == SO_BROADCAST) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Leaves received out-of-band data (data marked urgent) inline. This option takes an int value. This is a - Boolean option. */ - if (optname == SO_OOBINLINE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Sets send buffer size. This option takes an int value. */ - if (optname == SO_SNDBUF) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Sets receive buffer size. This option takes an int value. */ - if (optname == SO_RCVBUF) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* */ - if (optname == SO_STYLE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* */ - if (optname == SO_TYPE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Get error status and clear */ - if (optname == SO_ERROR) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - } - if (level == IPPROTO_IP) - { - if (optname == IP_ADD_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_ADD_SOURCE_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_BIND_ADDRESS_NO_PORT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_BLOCK_SOURCE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_DROP_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_DROP_SOURCE_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_FREEBIND) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_HDRINCL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MSFILTER) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MTU) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MTU_DISCOVER) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_ALL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_IF) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_LOOP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_TTL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_NODEFRAG) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_OPTIONS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_PKTINFO) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVOPTS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVORIGDSTADDR) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVTOS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVTTL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RETOPTS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_ROUTER_ALERT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TOS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TRANSPARENT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TTL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_UNBLOCK_SOURCE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - // TODO - return -1; - } - if (level == IPPROTO_TCP) - { - struct tcp_pcb *pcb = (struct tcp_pcb*)(vs->pcb); - if (pcb == NULL) { - handle_general_failure(); - return -1; - } - /* If set, don't send out partial frames. */ - if (optname == TCP_CORK) { - // TODO - errno = ENOPROTOOPT; - err = -1; - } - /* Allow a listener to be awakened only when data arrives on the socket. */ - if (optname == TCP_DEFER_ACCEPT) { - // TODO - errno = ENOPROTOOPT; - err = -1; - } - /* Used to collect information about this socket. */ - if (optname == TCP_INFO) { - // TODO - errno = ENOPROTOOPT; - err = -1; - } - /* The maximum number of keepalive probes TCP should send before dropping the connection.*/ - if (optname == TCP_KEEPCNT) { - // TODO - errno = ENOPROTOOPT; - err = -1; - } - /* The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes, - if the socket option SO_KEEPALIVE has been set on this socket. */ - if (optname == TCP_KEEPIDLE) { - // TODO - errno = ENOPROTOOPT; - err = -1; - } - /* The time (in seconds) between individual keepalive probes.*/ - if (optname == TCP_KEEPINTVL) { - // TODO - err = -1; - } - /* The lifetime of orphaned FIN_WAIT2 state sockets. */ - if (optname == TCP_LINGER2) { - // TODO - errno = ENOPROTOOPT; - err = -1; - } - /* The maximum segment size for outgoing TCP packets. */ - if (optname == TCP_MAXSEG) { - // TODO - errno = ENOPROTOOPT; - err = -1; - } - /* Get value of Nagle algorithm flag */ - if (optname == TCP_NODELAY) { - optval_tmp = tcp_nagle_disabled(pcb); - memcpy(optval, &optval_tmp, *optlen); - err = 0; - } - /* Enable quickack mode if set or disable quickack mode if cleared. */ - if (optname == TCP_QUICKACK) { - // TODO - errno = ENOPROTOOPT; - err = -1; - } - /* Set the number of SYN retransmits that TCP should send before aborting the attempt to connect. It - cannot exceed 255. */ - if (optname == TCP_SYNCNT) { - // TODO - errno = ENOPROTOOPT; - err = -1; - } - /* Bound the size of the advertised window to this value. The kernel imposes a minimum size of - SOCK_MIN_RCVBUF/2. */ - if (optname == TCP_WINDOW_CLAMP) { - // TODO - errno = ENOPROTOOPT; - err = -1; - } - } - if (level == IPPROTO_UDP) - { - /* If this option is enabled, then all data output on this socket is accumulated into a single - datagram that is transmitted when the option is disabled. */ - if (optname == UDP_CORK) { - // TODO - errno = ENOPROTOOPT; - err = -1; - } - } - return err; - } - - void lwIP::lwip_cb_err(void *arg, err_t err) - { - VirtualSocket *vs = (VirtualSocket *)arg; - if (vs == NULL) { - DEBUG_ERROR("err=%d, invalid virtual socket", err); - errno = -1; - } - if (vs->socket_type == SOCK_STREAM) { - DEBUG_ERROR("vs=%p, pcb=%p, pcb->state=%d, fd=%d, err=%d", vs, vs->pcb, ((struct tcp_pcb*)(vs->pcb))->state, vs->app_fd, err); - } - if (vs->socket_type == SOCK_DGRAM) { - DEBUG_ERROR("vs=%p, pcb=%p, fd=%d, err=%d", vs, vs->pcb, vs->app_fd, err); - } - switch(err) - { - case ERR_MEM: // -1 - DEBUG_ERROR("ERR_MEM->ENOMEM, Out of memory error."); - break; - case ERR_BUF: // -2 - DEBUG_ERROR("ERR_BUF->ENOBUFS, Buffer error."); - break; - case ERR_TIMEOUT: // -3 - DEBUG_ERROR("ERR_TIMEOUT->ETIMEDOUT, Timeout."); - break; - case ERR_RTE: // -4 - DEBUG_ERROR("ERR_RTE->ENETUNREACH, Routing problem."); - break; - case ERR_INPROGRESS: // -5 - DEBUG_ERROR("ERR_INPROGRESS->EINPROGRESS, Operation in progress."); - break; - case ERR_VAL: // -6 - DEBUG_ERROR("ERR_VAL->EINVAL, Illegal value."); - break; - case ERR_WOULDBLOCK: // -7 - DEBUG_ERROR("ERR_WOULDBLOCK->EWOULDBLOCK, Operation would block."); - break; - case ERR_USE: // -8 - DEBUG_ERROR("ERR_USE->EADDRINUSE, Address in use."); - break; - case ERR_ALREADY: // -9 ? - DEBUG_ERROR("ERR_ALREADY->EISCONN, Already connecting."); - break; - case ERR_ISCONN: // -10 - DEBUG_ERROR("ERR_ISCONN->EISCONN, Already connected"); - break; - case ERR_CONN: // -11 ? - DEBUG_ERROR("ERR_CONN->EISCONN, Not connected"); - break; - case ERR_IF: // -12 - DEBUG_ERROR("ERR_IF, Low-level netif error."); - break; - case ERR_ABRT: // -13 - DEBUG_ERROR("ERR_ABRT, Connection aborted."); - break; - case ERR_RST: // -14 - DEBUG_ERROR("ERR_RST, Connection reset."); - break; - case ERR_CLSD: // -15 - DEBUG_ERROR("ERR_CLSD, Connection closed."); - break; - case ERR_ARG: // -16 - DEBUG_ERROR("ERR_ARG, Illegal argument."); - break; - default: - break; - } - errno = lwip_err_to_errno(err); + /* NOTE: It is a known issue that when assigned more than one IP address via + Central, this interface will be unable to transmit (including ARP). */ + char ipbuf[INET6_ADDRSTRLEN], nmbuf[INET6_ADDRSTRLEN]; + if (ip.isV4()) { + static ip_addr_t ipaddr, netmask, gw; + IP4_ADDR(&gw,127,0,0,1); + ipaddr.addr = *((u32_t *)ip.rawIpData()); + netmask.addr = *((u32_t *)ip.netmask().rawIpData()); + netif_add(&(lwipdev),&ipaddr, &netmask, &gw, NULL, tapif_init, tcpip_input); + lwipdev.state = tapref; + lwipdev.output = etharp_output; + lwipdev.mtu = ZT_MAX_MTU; + lwipdev.name[0] = 'l'; + lwipdev.name[1] = '4'; + lwipdev.linkoutput = lwip_eth_tx; + lwipdev.hwaddr_len = 6; + mac.copyTo(lwipdev.hwaddr, lwipdev.hwaddr_len); + lwipdev.flags = NETIF_FLAG_BROADCAST + | NETIF_FLAG_ETHARP + | NETIF_FLAG_IGMP + | NETIF_FLAG_LINK_UP + | NETIF_FLAG_UP; + netif_set_default(&(lwipdev)); + netif_set_link_up(&(lwipdev)); + //netif_set_up(&(lwipdev)); + char macbuf[ZT_MAC_ADDRSTRLEN]; + mac2str(macbuf, ZT_MAC_ADDRSTRLEN, lwipdev.hwaddr); + DEBUG_INFO("mac=%s, addr=%s, nm=%s", macbuf, ip.toString(ipbuf), ip.netmask().toString(nmbuf)); } } + +void lwip_eth_rx(ZeroTier::VirtualTap *tap, const ZeroTier::MAC &from, const ZeroTier::MAC &to, unsigned int etherType, + const void *data, unsigned int len) +{ + struct pbuf *p,*q; + struct eth_hdr ethhdr; + from.copyTo(ethhdr.src.addr, 6); + to.copyTo(ethhdr.dest.addr, 6); + ethhdr.type = ZeroTier::Utils::hton((uint16_t)etherType); + + p = pbuf_alloc(PBUF_RAW, len+sizeof(struct eth_hdr), PBUF_POOL); + if (p != NULL) { + const char *dataptr = reinterpret_cast(data); + // First pbuf gets ethernet header at start + q = p; + if (q->len < sizeof(ethhdr)) { + DEBUG_ERROR("dropped packet: first pbuf smaller than ethernet header"); + return; + } + memcpy(q->payload,ðhdr,sizeof(ethhdr)); + memcpy((char*)q->payload + sizeof(ethhdr),dataptr,q->len - sizeof(ethhdr)); + dataptr += q->len - sizeof(ethhdr); + // Remaining pbufs (if any) get rest of data + while ((q = q->next)) { + memcpy(q->payload,dataptr,q->len); + dataptr += q->len; + } + } + else { + DEBUG_ERROR("dropped packet: no pbufs available"); + return; + } + if (ZT_MSG_TRANSFER == true) { + char flagbuf[32]; + memset(&flagbuf, 0, 32); + char macBuf[ZT_MAC_ADDRSTRLEN], nodeBuf[ZT_ID_LEN]; + mac2str(macBuf, ZT_MAC_ADDRSTRLEN, ethhdr.dest.addr); + ZeroTier::MAC mac; + mac.setTo(ethhdr.src.addr, 6); + mac.toAddress(tap->_nwid).toString(nodeBuf); + DEBUG_TRANS("len=%5d dst=%s [%s RX --> %s] proto=0x%04x %s %s", len, macBuf, nodeBuf, tap->nodeId().c_str(), + ZeroTier::Utils::ntoh(ethhdr.type), beautify_eth_proto_nums(ZeroTier::Utils::ntoh(ethhdr.type)), flagbuf); + } + { +#if defined(LIBZT_IPV4) + if (lwipdev.input(p, &(lwipdev)) != ERR_OK) { + DEBUG_ERROR("error while feeding frame into stack interface (ipv4)"); + } +#endif + } +} + diff --git a/src/lwIP.hpp b/src/lwIP.hpp deleted file mode 100644 index e4be8a4..0000000 --- a/src/lwIP.hpp +++ /dev/null @@ -1,344 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -// lwIP network stack driver - -#ifndef ZT_LWIP_HPP -#define ZT_LWIP_HPP - -#include -#include -#include - -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/init.h" -#include "lwip/udp.h" -#include "lwip/tcp.h" -#include "lwip/priv/tcp_priv.h" - -#include "Mutex.hpp" -#include "OSUtils.hpp" - -#include "libzt.h" -#include "VirtualTap.hpp" - -struct tcp_pcb; -struct netif; - -/** Table to quickly map an lwIP error (err_t) to a socket error - * by using -err as an index */ -static const int lwip_err_to_errno_table[] = { - 0, /* ERR_OK 0 No error, everything OK. */ - ENOMEM, /* ERR_MEM -1 Out of memory error. */ - ENOBUFS, /* ERR_BUF -2 Buffer error. */ - EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */ - EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */ - EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */ - EINVAL, /* ERR_VAL -6 Illegal value. */ - EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */ - EADDRINUSE, /* ERR_USE -8 Address in use. */ - EALREADY, /* ERR_ALREADY -9 Already connecting. */ - EISCONN, /* ERR_ISCONN -10 Conn already established.*/ - ENOTCONN, /* ERR_CONN -11 Not connected. */ - -1, /* ERR_IF -12 Low-level netif error */ - ECONNABORTED, /* ERR_ABRT -13 Connection aborted. */ - ECONNRESET, /* ERR_RST -14 Connection reset. */ - ENOTCONN, /* ERR_CLSD -15 Connection closed. */ - EIO /* ERR_ARG -16 Illegal argument. */ -}; - -#define ERR_TO_ERRNO_TABLE_SIZE LWIP_ARRAYSIZE(lwip_err_to_errno_table) - -#define lwip_err_to_errno(err) \ - ((unsigned)(-(signed)(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \ - lwip_err_to_errno_table[-(signed)(err)] : EIO) - -#if defined(LIBZT_IPV4) - //#define LWIP_NETIF_ADD_SIG struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input - #define LWIP_ETHARP_OUTPUT_SIG struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr -#endif -#if defined(LIBZT_IPV6) -#include "lwip/ip6_addr.h" -#include "ethip6.h" - #define LWIP_NETIF_ADD_SIG struct netif *netif, void *state, netif_init_fn init, netif_input_fn input - #define LWIP_ETHIP6_OUTPUT_SIG struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr - #define LWIP_ETHARP_OUTPUT_SIG struct netif *netif, struct pbuf *q, const ip6_addr_t *ipaddr - #define LWIP_NETIF_IP6_ADDR_SET_STATE_SIG struct netif* netif, s8_t addr_idx, u8_t state - #define LWIP_NETIF_CREATE_IP6_LINKLOCAL_ADDRESS_SIG struct netif *netif, u8_t from_mac_48bit -#endif - -#define LWIP_PBUF_FREE_SIG struct pbuf *p -#define LWIP_PBUF_ALLOC_SIG pbuf_layer layer, u16_t length, pbuf_type type -#define LWIP_HTONS_SIG u16_t x -#define LWIP_NTOHS_SIG u16_t x -#define LWIP_UDP_NEW_SIG void -#define LWIP_UDP_CONNECT_SIG struct udp_pcb * pcb, const ip_addr_t * ipaddr, u16_t port -#define LWIP_UDP_SEND_SIG struct udp_pcb * pcb, struct pbuf * p -#define LWIP_UDP_SENDTO_SIG struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port -#define LWIP_UDP_RECV_SIG struct udp_pcb * pcb, void (* recv)(void * arg, struct udp_pcb * upcb, struct pbuf * p, ip_addr_t * addr, u16_t port), void * recv_arg -#define LWIP_UDP_RECVED_SIG struct udp_pcb * pcb, u16_t len -#define LWIP_UDP_BIND_SIG struct udp_pcb * pcb, const ip_addr_t * ipaddr, u16_t port -#define LWIP_UDP_REMOVE_SIG struct udp_pcb *pcb -#define LWIP_TCP_WRITE_SIG struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags -#define LWIP_TCP_SENT_SIG struct tcp_pcb * pcb, err_t (* sent)(void * arg, struct tcp_pcb * tpcb, u16_t len) -#define LWIP_TCP_NEW_SIG void -#define LWIP_TCP_RECV_SIG struct tcp_pcb * pcb, err_t (* recv)(void * arg, struct tcp_pcb * tpcb, struct pbuf * p, err_t err) -#define LWIP_TCP_RECVED_SIG struct tcp_pcb * pcb, u16_t len -#define LWIP_TCP_CONNECT_SIG struct tcp_pcb * pcb, const ip_addr_t * ipaddr, u16_t port, err_t (* connected)(void * arg, struct tcp_pcb * tpcb, err_t err) -#define LWIP_TCP_RECV_SIG struct tcp_pcb * pcb, err_t (* recv)(void * arg, struct tcp_pcb * tpcb, struct pbuf * p, err_t err) -#define LWIP_TCP_ERR_SIG struct tcp_pcb * pcb, void (* err)(void * arg, err_t err) -#define LWIP_TCP_POLL_SIG struct tcp_pcb * pcb, err_t (* poll)(void * arg, struct tcp_pcb * tpcb), u8_t interval -#define LWIP_TCP_ARG_SIG struct tcp_pcb * pcb, void * arg -#define LWIP_TCP_CLOSE_SIG struct tcp_pcb * pcb -#define LWIP_TCP_ABORT_SIG struct tcp_pcb * pcb -#define LWIP_TCP_OUTPUT_SIG struct tcp_pcb * pcb -#define LWIP_TCP_ACCEPT_SIG struct tcp_pcb * pcb, err_t (* accept)(void * arg, struct tcp_pcb * newpcb, err_t err) -#define LWIP_TCP_LISTEN_SIG struct tcp_pcb * pcb -#define LWIP_TCP_LISTEN_WITH_BACKLOG_SIG struct tcp_pcb * pcb, u8_t backlog -#define LWIP_TCP_BIND_SIG struct tcp_pcb * pcb, const ip_addr_t * ipaddr, u16_t port -#define LWIP_TCP_INPUT_SIG struct pbuf *p, struct netif *inp -#define LWIP_ETHERNET_INPUT_SIG struct pbuf *p, struct netif *netif -#define LWIP_IP_INPUT_SIG struct pbuf *p, struct netif *inp -#define LWIP_NETIF_SET_DEFAULT_SIG struct netif *netif -#define LWIP_NETIF_SET_UP_SIG struct netif *netif -#define LWIP_NETIF_POLL_SIG struct netif *netif -#define NETIF_SET_STATUS_CALLBACK struct netif *netif, netif_status_callback_fn status_callback -#define LWIP_TCP_SHUTDOWN_SIG struct tcp_pcb *pcb, int shut_rx, int shut_tx - -#if defined(LIBZT_IPV4) - extern "C" err_t etharp_output(LWIP_ETHARP_OUTPUT_SIG); -#endif -#if defined(LIBZT_IPV6) - extern "C" void nd6_tmr(void); - //extern "C" void netif_ip6_addr_set_state(LWIP_NETIF_IP6_ADDR_SET_STATE_SIG); - extern "C" void netif_create_ip6_linklocal_address(LWIP_NETIF_CREATE_IP6_LINKLOCAL_ADDRESS_SIG); - extern "C" err_t ethip6_output(LWIP_ETHIP6_OUTPUT_SIG); -#endif - -extern "C" void lwip_init(); -extern "C" err_t ethernet_input(LWIP_ETHERNET_INPUT_SIG); -extern "C" void netif_poll(LWIP_NETIF_POLL_SIG); - -//extern "C" err_t etharp_output(LWIP_ETHARP_OUTPUT_SIG); -//extern "C" err_t ethernet_input(LWIP_ETHERNET_INPUT_SIG); -extern "C" void netif_set_up(LWIP_NETIF_SET_UP_SIG); -extern "C" void netif_set_default(LWIP_NETIF_SET_DEFAULT_SIG); -//extern "C" struct netif *netif_add(LWIP_NETIF_ADD_SIG); -extern "C" err_t tapif_init(struct netif *netif); -//extern "C" err_t low_level_output(struct netif *netif, struct pbuf *p); -extern "C" err_t tcp_write(LWIP_TCP_WRITE_SIG); -extern "C" void tcp_sent(LWIP_TCP_SENT_SIG); -extern "C" struct tcp_pcb *tcp_new(LWIP_TCP_NEW_SIG); -//u16_t tcp_sndbuf(struct tcp_pcb * pcb); -extern "C" err_t tcp_connect(LWIP_TCP_CONNECT_SIG); -extern "C" struct udp_pcb *udp_new(LWIP_UDP_NEW_SIG); -extern "C" err_t udp_connect(LWIP_UDP_CONNECT_SIG); -extern "C" err_t udp_send(LWIP_UDP_SEND_SIG); -extern "C" err_t udp_sendto(LWIP_UDP_SENDTO_SIG); -//extern "C" void udp_recv(LWIP_UDP_RECV_SIG); -extern "C" void udp_recved(LWIP_UDP_RECVED_SIG); -extern "C" err_t udp_bind(LWIP_UDP_BIND_SIG); -extern "C" void udp_remove(LWIP_UDP_REMOVE_SIG); -extern "C" void tcp_recv(LWIP_TCP_RECV_SIG); -extern "C" void tcp_recved(LWIP_TCP_RECVED_SIG); -extern "C" void tcp_err(LWIP_TCP_ERR_SIG); -extern "C" void tcp_poll(LWIP_TCP_POLL_SIG); -extern "C" void tcp_arg(LWIP_TCP_ARG_SIG); -extern "C" err_t tcp_close(LWIP_TCP_CLOSE_SIG); -extern "C" void tcp_abort(LWIP_TCP_ABORT_SIG); -extern "C" err_t tcp_output(LWIP_TCP_OUTPUT_SIG); -extern "C" void tcp_accept(LWIP_TCP_ACCEPT_SIG); -//extern "C" struct tcp_pcb *tcp_listen(LWIP_TCP_LISTEN_SIG); -extern "C" struct tcp_pcb *tcp_listen_with_backlog(LWIP_TCP_LISTEN_WITH_BACKLOG_SIG); -extern "C" err_t tcp_bind(LWIP_TCP_BIND_SIG); -extern "C" void etharp_tmr(void); -extern "C" void tcp_tmr(void); -extern "C" u8_t pbuf_free(LWIP_PBUF_FREE_SIG); -extern "C" struct pbuf *pbuf_alloc(LWIP_PBUF_ALLOC_SIG); -extern "C" u16_t lwip_htons(LWIP_HTONS_SIG); -extern "C" u16_t lwip_ntohs(LWIP_NTOHS_SIG); -extern "C" void tcp_input(LWIP_TCP_INPUT_SIG); -extern "C" err_t ip_input(LWIP_IP_INPUT_SIG); -extern "C" err_t tcp_shutdown(LWIP_TCP_SHUTDOWN_SIG); -//extern "C" void netif_set_status_callback(NETIF_SET_STATUS_CALLBACK); - -namespace ZeroTier { - - class VirtualTap; - class VirtualSocket; - - /** - * lwIP network stack driver class - */ - class lwIP - { - public: - - /** - * Set up an interface in the network stack for the VirtualTap - */ - void lwip_init_interface(VirtualTap *tap, const InetAddress &ip); - - /** - * Returns the number of TCP PCBs currently allocated - */ - static int lwip_num_current_tcp_pcbs(); - - /** - * Returns the number of UDP PCBs currently allocated - */ - static int lwip_num_current_udp_pcbs(); - - /** - * Returns the number of RAW PCBs currently allocated - */ - static int lwip_num_current_raw_pcbs(); - - /** - * Returns the total number of PCBs of any time or state - */ - int lwip_num_total_pcbs(); - - /** - * Registers a DNS nameserver with the network stack - */ - int lwip_add_dns_nameserver(struct sockaddr *addr); - - /** - * Un-registers a DNS nameserver from the network stack - */ - int lwip_del_dns_nameserver(struct sockaddr *addr); - - /** - * Main stack loop - */ - void lwip_loop(VirtualTap *tap); - - /** - * Packets from the ZeroTier virtual wire enter the stack here - */ - void lwip_eth_rx(VirtualTap *tap, const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len); - - /** - * Creates a stack-specific "socket" or "VirtualSocket object" - */ - int lwip_Socket(void **pcb, int socket_family, int socket_type, int protocol); - - /** - * Connect to remote host via userspace network stack interface - Called from VirtualTap - */ - int lwip_Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen); - - /** - * Bind to a userspace network stack interface - Called from VirtualTap - */ - int lwip_Bind(VirtualTap *tap, VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen); - - /** - * Listen for incoming VirtualSockets - Called from VirtualTap - */ - int lwip_Listen(VirtualSocket *vs, int backlog); - - /** - * Accept an incoming VirtualSocket - Called from VirtualTap - */ - VirtualSocket* lwip_Accept(VirtualSocket *vs); - - /** - * Read from RX buffer to application - Called from VirtualTap - */ - int lwip_Read(VirtualSocket *vs, bool lwip_invoked); - - /** - * Write to userspace network stack - Called from VirtualTap - */ - int lwip_Write(VirtualSocket *vs, void *data, ssize_t len); - - /** - * Close a VirtualSocket - Called from VirtualTap - */ - int lwip_Close(VirtualSocket *vs); - - /** - * Shuts down some aspect of a VirtualSocket - Called from VirtualTap - */ - int lwip_Shutdown(VirtualSocket *vs, int how); - - /** - * Sets a property of a socket - */ - static int lwip_setsockopt(VirtualSocket *vs, int level, int optname, const void *optval, socklen_t optlen); - - /** - * Gets a property of a socket - */ - static int lwip_getsockopt(VirtualSocket *vs, int level, int optname, void *optval, socklen_t *optlen); - - // --- Callbacks from network stack --- - - //static void netif_status_callback(struct netif *nif); - - /** - * Callback for handling received UDP packets (already processed by network stack) - */ - static err_t lwip_cb_tcp_recved(void *arg, struct tcp_pcb *PCB, struct pbuf *p, err_t err); - - /** - * Callback for handling accepted connection - */ - static err_t lwip_cb_accept(void *arg, struct tcp_pcb *newPCB, err_t err); - - /** - * Callback for handling received TCP packets (already processed by stack) - */ - static void lwip_cb_udp_recved(void * arg, struct udp_pcb * upcb, struct pbuf * p, const ip_addr_t * addr, u16_t port); - - /** - * Callback for handling errors from within the network stack - */ - static void lwip_cb_err(void *arg, err_t err); - - /** - * Callback for handling periodic background tasks - */ - static err_t lwip_cb_poll(void* arg, struct tcp_pcb *PCB); - - /** - * Callback for handling confirmation of sent packets - */ - static err_t lwip_cb_sent(void *arg, struct tcp_pcb *PCB, u16_t len); - - /** - * Callback for handling successful connections - */ - static err_t lwip_cb_connected(void *arg, struct tcp_pcb *PCB, err_t err); - }; -} - -#endif diff --git a/src/picoTCP.cpp b/src/picoTCP.cpp deleted file mode 100644 index 84b196c..0000000 --- a/src/picoTCP.cpp +++ /dev/null @@ -1,1983 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#include -#include - -#include "pico_eth.h" -#include "pico_stack.h" -#include "pico_ipv4.h" -#include "pico_icmp4.h" -#include "pico_dev_tap.h" -#include "pico_protocol.h" -#include "pico_socket.h" -#include "pico_device.h" -#include "pico_ipv6.h" -#include "pico_tcp.h" -#include "pico_dns_client.h" - -#include "libzt.h" -#include "Utilities.hpp" -#include "VirtualTap.hpp" -#include "picoTCP.hpp" -#include "RingBuffer.hpp" - -#include "Utils.hpp" -#include "OSUtils.hpp" -#include "Mutex.hpp" -#include "Constants.hpp" -#include "Phy.hpp" - -int pico_ipv4_to_string(PICO_IPV4_TO_STRING_SIG); -extern "C" int pico_stack_init(void); -extern "C" void pico_stack_tick(void); -extern "C" int pico_ipv4_link_add(PICO_IPV4_LINK_ADD_SIG); -extern "C" int pico_ipv4_route_add(PICO_IPV4_ROUTE_ADD_SIG); -extern "C" int pico_ipv4_route_del(PICO_IPV4_ROUTE_DEL_SIG); -extern "C" int pico_device_init(PICO_DEVICE_INIT_SIG); -extern "C" int pico_string_to_ipv4(PICO_STRING_TO_IPV4_SIG); -extern "C" int pico_string_to_ipv6(PICO_STRING_TO_IPV6_SIG); -extern "C" int pico_socket_recvfrom(PICO_SOCKET_RECVFROM_SIG); -extern "C" struct pico_socket * pico_socket_open(PICO_SOCKET_OPEN_SIG); -extern "C" int pico_socket_connect(PICO_SOCKET_CONNECT_SIG); -extern "C" int pico_socket_listen(PICO_SOCKET_LISTEN_SIG); -extern "C" int pico_socket_write(PICO_SOCKET_WRITE_SIG); -extern "C" int pico_socket_close(PICO_SOCKET_CLOSE_SIG); -extern "C" struct pico_ipv6_link * pico_ipv6_link_add(PICO_IPV6_LINK_ADD_SIG); -extern "C" int pico_dns_client_nameserver(PICO_DNS_CLIENT_NAMESERVER_SIG); - -/* -int pico_stack_recv(PICO_STACK_RECV_SIG); -int pico_icmp4_ping(PICO_ICMP4_PING_SIG); -int pico_socket_setoption(PICO_SOCKET_SETOPTION_SIG); -uint32_t pico_timer_add(PICO_TIMER_ADD_SIG); -int pico_socket_send(PICO_SOCKET_SEND_SIG); -int pico_socket_sendto(PICO_SOCKET_SENDTO_SIG); -int pico_socket_recv(PICO_SOCKET_RECV_SIG); -int pico_socket_bind(PICO_SOCKET_BIND_SIG); -int pico_socket_read(PICO_SOCKET_READ_SIG); -int pico_socket_shutdown(PICO_SOCKET_SHUTDOWN_SIG); -struct pico_socket * pico_socket_accept(PICO_SOCKET_ACCEPT_SIG); -*/ - -extern std::vector vtaps; - -/* - * Whether our picoTCP device has been initialized - */ -static bool picodev_initialized; - -namespace ZeroTier { - - struct pico_device picodev; - ZeroTier::Mutex _picostack_driver_lock; - - bool picoTCP::pico_init_interface(VirtualTap *tap) - { - bool err = false; - _picostack_driver_lock.lock(); - // give right to vtap to start the stack - // only one stack loop is permitted - if (picodev_initialized == false) { - tap->should_start_stack = true; - picodev.send = pico_eth_tx; // tx - picodev.poll = pico_eth_poll; // calls pico_eth_rx - picodev.mtu = tap->_mtu; - picodev.tap = tap; - uint8_t mac[PICO_SIZE_ETH]; - tap->_mac.copyTo(mac, PICO_SIZE_ETH); - if (pico_device_init(&picodev, tap->vtap_abbr_name, mac) != 0) { - DEBUG_ERROR("dev init failed"); - handle_general_failure(); - err = false; - } - picodev_initialized = true; - err = true; - } - _picostack_driver_lock.unlock(); - return err; - } - - bool picoTCP::pico_register_address(VirtualTap *tap, const InetAddress &ip) - { - _picostack_driver_lock.lock(); - bool err = false; - char ipbuf[INET6_ADDRSTRLEN]; - uint8_t hwaddr[6]; - // register addresses - if (ip.isV4()) { - struct pico_ip4 ipaddr, netmask; - ipaddr.addr = *((uint32_t *)ip.rawIpData()); - netmask.addr = *((uint32_t *)ip.netmask().rawIpData()); - pico_ipv4_link_add(&picodev, ipaddr, netmask); - DEBUG_INFO("addr=%s", ip.toString(ipbuf)); - tap->_mac.copyTo(hwaddr, 6); - char macbuf[ZT_MAC_ADDRSTRLEN]; - mac2str(macbuf, ZT_MAC_ADDRSTRLEN, hwaddr); - DEBUG_INFO("mac=%s", macbuf); - err = true; - } - if (ip.isV6()) { - char ipv6_str[INET6_ADDRSTRLEN], nm_str[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, ip.rawIpData(), ipv6_str, INET6_ADDRSTRLEN); - inet_ntop(AF_INET6, ip.netmask().rawIpData(), nm_str, INET6_ADDRSTRLEN); - struct pico_ip6 ipaddr, netmask; - pico_string_to_ipv6(ipv6_str, ipaddr.addr); - pico_string_to_ipv6(nm_str, netmask.addr); - pico_ipv6_link_add(&picodev, ipaddr, netmask); - DEBUG_INFO("addr=%s", ipv6_str); - tap->_mac.copyTo(hwaddr, 6); - char macbuf[ZT_MAC_ADDRSTRLEN]; - mac2str(macbuf, ZT_MAC_ADDRSTRLEN, hwaddr); - DEBUG_INFO("mac=%s", macbuf); - err = true; - } - _picostack_driver_lock.unlock(); - return err; - } - - // TODO: - // pico_ipv6_route_add - // pico_ipv6_route_del - - bool picoTCP::pico_route_add(VirtualTap *tap, const InetAddress &addr, const InetAddress &nm, const InetAddress &gw, int metric) - { - struct pico_ipv4_link *link = NULL; - struct pico_ip4 address; - address.addr = *((uint32_t *)addr.rawIpData()); - struct pico_ip4 netmask; - netmask.addr = *((uint32_t *)nm.rawIpData()); - struct pico_ip4 gateway; - gateway.addr = *((uint32_t *)gw.rawIpData()); - int err = pico_ipv4_route_add(address, netmask, gateway, metric, link); - if (err) { - DEBUG_ERROR("err=%d, %s", err, beautify_pico_error(pico_err)); - } - return err; - } - - bool picoTCP::pico_route_del(VirtualTap *tap, const InetAddress &addr, const InetAddress &nm, int metric) - { - struct pico_ip4 address; - address.addr = *((uint32_t *)addr.rawIpData()); - struct pico_ip4 netmask; - netmask.addr = *((uint32_t *)nm.rawIpData()); - int err = pico_ipv4_route_del(address, netmask, metric); - if (err) { - DEBUG_ERROR("err=%d, %s", err, beautify_pico_error(pico_err)); - } - return err; - } - - int picoTCP::pico_add_dns_nameserver(struct sockaddr *addr) - { - int err = errno = 0; - // TODO: De-complexify this - struct pico_ip4 ns; - memset(&ns, 0, sizeof (struct pico_ip4)); - struct sockaddr_in *in4 = (struct sockaddr_in*)addr; - char ipv4_str[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, (const void *)&in4->sin_addr.s_addr, ipv4_str, INET_ADDRSTRLEN); - uint32_t ipval = 0; - pico_string_to_ipv4(ipv4_str, &ipval); - ns.addr = ipval; - if ((err = pico_dns_client_nameserver(&ns, PICO_DNS_NS_ADD)) < 0) { - DEBUG_ERROR("error while adding DNS nameserver, err=%d, pico_err=%d, %s", - err, pico_err, beautify_pico_error(pico_err)); - map_pico_err_to_errno(pico_err); - } - return err; - } - - int picoTCP::pico_del_dns_nameserver(struct sockaddr *addr) - { - int err = errno = 0; - // TODO: De-complexify this - struct pico_ip4 ns; - memset(&ns, 0, sizeof (struct pico_ip4)); - struct sockaddr_in *in4 = (struct sockaddr_in*)addr; - char ipv4_str[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, (const void *)&in4->sin_addr.s_addr, ipv4_str, INET_ADDRSTRLEN); - uint32_t ipval = 0; - pico_string_to_ipv4(ipv4_str, &ipval); - ns.addr = ipval; - if ((err = pico_dns_client_nameserver(&ns, PICO_DNS_NS_DEL)) < 0) { - DEBUG_ERROR("error while removing DNS nameserver, err=%d, pico_err=%d, %s", - err, pico_err, beautify_pico_error(pico_err)); - } - return err; - } - - void picoTCP::pico_loop(VirtualTap *tap) - { - while (tap->_run) - { - tap->_phy.poll(ZT_PHY_POLL_INTERVAL); - pico_stack_tick(); - tap->Housekeeping(); - } - } - - // from stack socket to app socket - void picoTCP::pico_cb_tcp_read(ZeroTier::VirtualTap *tap, struct pico_socket *s) - { - VirtualSocket *vs = (VirtualSocket*)(((VirtualBindingPair*)s->priv)->vs); - if (vs == NULL) { - DEBUG_ERROR("s->priv yielded no valid vs"); - handle_general_failure(); - return; - } - Mutex::Lock _l(vs->_rx_m); - if (tap == NULL) { - DEBUG_ERROR("invalid tap"); - handle_general_failure(); - return; - } - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - handle_general_failure(); - return; - } - int r; - uint16_t port = 0; - union { - struct pico_ip4 ip4; - struct pico_ip6 ip6; - } peer; - - do { - int n = 0; - int avail = ZT_TCP_RX_BUF_SZ - vs->RXbuf->count(); - if (avail) { - r = pico_socket_recvfrom(s, vs->RXbuf->get_buf(), ZT_STACK_SOCKET_RD_MAX, - (void *)&peer.ip4.addr, &port); - if (r > 0) - { - vs->RXbuf->produce(r); - n = tap->_phy.streamSend(vs->sock, vs->RXbuf->get_buf(), r); - - if (n>0) - vs->RXbuf->consume(n); - } - if (vs->RXbuf->count() == 0) { - tap->_phy.setNotifyWritable(vs->sock, false); - } - else { - tap->_phy.setNotifyWritable(vs->sock, true); - } - } - else { - //tap->_phy.setNotifyWritable(vs->sock, false); - DEBUG_ERROR("not enough space left on I/O RX buffer for pico_socket(%p)", s); - handle_general_failure(); - } - } - while (r > 0); - } - - // from stack socket to app socket - void picoTCP::pico_cb_udp_read(VirtualTap *tap, struct pico_socket *s) - { - // DEBUG_INFO(); - VirtualSocket *vs = (VirtualSocket*)(((VirtualBindingPair*)s->priv)->vs); - if (vs == NULL) { - DEBUG_ERROR("s->priv yielded no valid vs"); - handle_general_failure(); - return; - } - Mutex::Lock _l(vs->_rx_m); - if (tap == NULL) { - DEBUG_ERROR("invalid tap"); - handle_general_failure(); - return; - } - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - handle_general_failure(); - return; - } - - uint16_t port = 0; - union { - struct pico_ip4 ip4; - struct pico_ip6 ip6; - } peer; - int r = 0, w = 0; - // TODO: Consolidate this - if (vs->socket_family == AF_INET) { - struct sockaddr_in in4; - char udp_payload_buf[ZT_MAX_MTU]; - if ((r = pico_socket_recvfrom(s, udp_payload_buf, ZT_SDK_MTU, (void *)&peer.ip4.addr, &port)) < 0) { - DEBUG_ERROR("err=%d, %s", r, beautify_pico_error(pico_err)); - } - in4.sin_addr.s_addr = peer.ip4.addr; - in4.sin_port = port; - // immediately attempt to write addr and payload to app socket. The idea is that the zts_recvfrom() has - // been called and will pick this up and correctly handle it - char udp_msg_buf[ZT_SOCKET_MSG_BUF_SZ]; // [sz : addr : payload] - int32_t len = sizeof(struct sockaddr_storage) + r; - int32_t tot_len = sizeof(int32_t) + len; - memcpy(udp_msg_buf, &len, sizeof(int32_t)); // len: sockaddr+payload - memcpy(udp_msg_buf + sizeof(int32_t), &in4, sizeof(struct sockaddr_storage)); // sockaddr - memcpy(udp_msg_buf + sizeof(int32_t) + sizeof(struct sockaddr_storage), &udp_payload_buf, r); // payload - if ((w = write(vs->sdk_fd, udp_msg_buf, tot_len)) < 0) { - DEBUG_ERROR("write()=%d, errno=%d", w, errno); - } - } - if (vs->socket_family == AF_INET6) { - struct sockaddr_in6 in6; - char udp_payload_buf[ZT_MAX_MTU]; - if ((r = pico_socket_recvfrom(s, udp_payload_buf, ZT_SDK_MTU, (void *)&peer.ip6.addr, &port)) < 0) { - DEBUG_ERROR("err=%d, %s", r, beautify_pico_error(pico_err)); - } - memcpy(&(in6.sin6_addr.s6_addr), &(peer.ip6.addr), sizeof(peer.ip6.addr)); - in6.sin6_port = port; - // immediately attempt to write addr and payload to app socket. The idea is that the zts_recvfrom() has - // been called and will pick this up and correctly handle it - char udp_msg_buf[ZT_SOCKET_MSG_BUF_SZ]; // [sz : addr : payload] - int32_t len = sizeof(struct sockaddr_storage) + r; - int32_t tot_len = sizeof(int32_t) + len; - memcpy(udp_msg_buf, &len, sizeof(int32_t)); // len: sockaddr+payload - memcpy(udp_msg_buf + sizeof(int32_t), &in6, sizeof(struct sockaddr_storage)); // sockaddr - memcpy(udp_msg_buf + sizeof(int32_t) + sizeof(struct sockaddr_storage), &udp_payload_buf, r); // payload - if ((w = write(vs->sdk_fd, udp_msg_buf, tot_len)) < 0) { - DEBUG_ERROR("write()=%d, errno=%d", w, errno); - } - } - } - - void picoTCP::pico_cb_tcp_write(VirtualTap *tap, struct pico_socket *s) - { - VirtualSocket *vs = (VirtualSocket*)(((VirtualBindingPair*)s->priv)->vs); - if (vs == NULL) { - DEBUG_EXTRA("vs == NULL"); - return; - } - if (vs->picosock != s) { - DEBUG_ERROR("vs->picosock != s, bad callback"); - return; - } - // we will get the vs->TXBuf->get_buf() reference from within pico_Write - picostack->pico_Write(vs, NULL, vs->TXbuf->count()); - } - - void picoTCP::pico_cb_socket_ev(uint16_t ev, struct pico_socket *s) - { - int err = 0; - //DEBUG_EXTRA("s=%p, s->state=%d %s", s, s->state, beautify_pico_state(s->state)); - - // --- handle error events --- - - // PICO_SOCK_EV_FIN - triggered when the socket is closed. No further communication is - // possible from this point on the socket. - if (ev & PICO_SOCK_EV_FIN) { - DEBUG_EXTRA("PICO_SOCK_EV_FIN (socket closed), picosock=%p", s); - //DEBUG_EXTRA("PICO_SOCK_EV_FIN (socket closed), picosock=%p, vs=%p, app_fd=%d, sdk_fd=%d", s, vs, vs->app_fd, vs->sdk_fd); - } - - // PICO_SOCK_EV_ERR - triggered when an error occurs. - if (ev & PICO_SOCK_EV_ERR) { - if (pico_err == PICO_ERR_ECONNRESET) { - DEBUG_ERROR("PICO_ERR_ECONNRESET"); - } - //DEBUG_ERROR("PICO_SOCK_EV_ERR, err=%s, picosock=%p, app_fd=%d, sdk_fd=%d", - // beautify_pico_error(pico_err), s, vs->app_fd, vs->sdk_fd); - } - // PICO_SOCK_EV_CLOSE - triggered when a FIN segment is received (TCP only). This event - // indicates that the oher endpont has closed the VirtualSocket, so the local TCP layer is only - // allowed to send new data until a local shutdown or close is initiated. PicoTCP is able to - // keep the VirtualSocket half-open (only for sending) after the FIN packet has been received, - // allowing new data to be sent in the TCP CLOSE WAIT state. - - VirtualBindingPair *vbp = (VirtualBindingPair*)(s->priv); - if (vbp == NULL) { - DEBUG_ERROR("s->priv yielded no valid vbp"); - handle_general_failure(); - return; - } - VirtualTap *tap = static_cast(vbp->tap); - VirtualSocket *vs = static_cast(vbp->vs); - - if (ev & PICO_SOCK_EV_CLOSE) { - vs->set_state(VS_STATE_CLOSED); - if ((err = pico_socket_shutdown(s, PICO_SHUT_RDWR)) < 0) { - DEBUG_ERROR("error while shutting down socket"); - } - if ((err = pico_socket_close(s)) < 0) { - DEBUG_ERROR("pico_socket_close()=%d, pico_err=%d, %s", err, pico_err, beautify_pico_error(pico_err)); - } - DEBUG_EXTRA("PICO_SOCK_EV_CLOSE (socket closure) err=%d (%s), picosock=%p", pico_err, beautify_pico_error(pico_err), s); - return; - } - - // --- handle non-error events --- - - if (vs == NULL) { - DEBUG_ERROR("invalid VirtualSocket"); - handle_general_failure(); - return; - } - // PICO_SOCK_EV - triggered when VirtualSocket is established (TCP only). This event is - // received either after a successful call to pico socket vsect to indicate that the VirtualSocket - // has been established, or on a listening socket, indicating that a call to pico socket accept - // may now be issued in order to accept the incoming VirtualSocket from a remote host. - if (ev & PICO_SOCK_EV_CONN) { - DEBUG_EXTRA("PICO_SOCK_EV_CONN"); - if (vs->get_state() == VS_STATE_LISTENING) { - uint16_t port; - struct pico_socket *client_psock = nullptr; - struct pico_ip4 orig4; - struct pico_ip6 orig6; - if (vs->socket_family == AF_INET) { // NOTE: p->net->proto_number == PICO_PROTO_IPV4 - client_psock = pico_socket_accept(s, &orig4, &port); - } - if (vs->socket_family == AF_INET6) { // NOTE: p->net->proto_number == PICO_PROTO_IPV4 - client_psock = pico_socket_accept(s, &orig6, &port); - } - if (client_psock == NULL) { - DEBUG_ERROR("pico_socket_accept(): pico_socket=%p, pico_err=%d, %s", s, pico_err, beautify_pico_error(pico_err)); - return; - } - // Create a new VirtualSocket and add it to the queue, - // some time in the future a call to zts_multiplex_accept() will pick up - // this new VirtualSocket, add it to the VirtualSocket list and return its - // VirtualSocket->sock to the application - VirtualSocket *new_vs = new VirtualSocket(); - new_vs->socket_type = SOCK_STREAM; - new_vs->picosock = client_psock; - // TODO: Condense this - if (vs->socket_family == AF_INET) { - char addrstr[INET_ADDRSTRLEN]; - struct sockaddr_storage ss4; - struct sockaddr_in *in4 = (struct sockaddr_in *)&ss4; - in4->sin_addr.s_addr = orig4.addr; - in4->sin_port = Utils::hton(port); - memcpy(&(new_vs->peer_addr), in4, sizeof(new_vs->peer_addr)); - inet_ntop(AF_INET, &(in4->sin_addr), addrstr, INET_ADDRSTRLEN); - DEBUG_EXTRA("accepted connection from: %s : %d", addrstr, port); - ZeroTier::InetAddress inet; - inet.fromString(addrstr); - new_vs->tap = getTapByAddr(&inet); // assign to tap based on incoming address - } - if (vs->socket_family == AF_INET6) { - char addrstr[INET6_ADDRSTRLEN]; - struct sockaddr_in6 in6; - memcpy(&(in6.sin6_addr.s6_addr), &orig6, sizeof(in6.sin6_addr.s6_addr)); - in6.sin6_port = Utils::hton(port); - memcpy(&(new_vs->peer_addr), &in6, sizeof(new_vs->peer_addr)); - inet_ntop(AF_INET6, &(in6.sin6_addr), addrstr, INET6_ADDRSTRLEN); - DEBUG_EXTRA("accepted connection from: %s : %d", addrstr, port); - ZeroTier::InetAddress inet; - inet.fromString(addrstr); - new_vs->tap = getTapByAddr(&inet); // assign to tap based on incoming address - } - if (new_vs->tap == NULL) { - DEBUG_ERROR("no valid VirtualTap could be found"); - handle_general_failure(); - return; - } - // Assign this VirtualSocket to the appropriate VirtualTap - new_vs->picosock->priv = new VirtualBindingPair(new_vs->tap,new_vs); - new_vs->tap->addVirtualSocket(new_vs); - vs->_AcceptedConnections.push(new_vs); - new_vs->sock = new_vs->tap->_phy.wrapSocket(new_vs->sdk_fd, new_vs); - } - if (vs->get_state() != VS_STATE_LISTENING) { - // set state so socket multiplexer logic will pick this up - vs->set_state(VS_STATE_UNHANDLED_CONNECTED); - } - } - // PICO_SOCK_EV_RD - triggered when new data arrives on the socket. A new receive action - // can be taken by the socket owner because this event indicates there is new data to receive. - if (ev & PICO_SOCK_EV_RD) { - if (vs->socket_type==SOCK_STREAM) - pico_cb_tcp_read(tap, s); - if (vs->socket_type==SOCK_DGRAM) - pico_cb_udp_read(tap, s); - } - // PICO_SOCK_EV_WR - triggered when ready to write to the socket. Issuing a write/send call - // will now succeed if the buffer has enough space to allocate new outstanding data - if (ev & PICO_SOCK_EV_WR) { - pico_cb_tcp_write(tap, s); - } - } - - int pico_eth_tx(struct pico_device *dev, void *buf, int len) - { - //DEBUG_TRANS(); - //_picostack_driver_lock.lock(); - VirtualTap *tap = static_cast(dev->tap); - if (tap == NULL) { - DEBUG_ERROR("invalid dev->tap"); - handle_general_failure(); - return ZT_ERR_GENERAL_FAILURE; - } - struct pico_eth_hdr *ethhdr; - ethhdr = (struct pico_eth_hdr *)buf; - MAC src_mac; - MAC dest_mac; - src_mac.setTo(ethhdr->saddr, 6); - dest_mac.setTo(ethhdr->daddr, 6); - if (ZT_MSG_TRANSFER == true) { - char macBuf[ZT_MAC_ADDRSTRLEN], nodeBuf[ZT_ID_LEN]; - mac2str(macBuf, ZT_MAC_ADDRSTRLEN, ethhdr->daddr); - ZeroTier::MAC mac; - mac.setTo(ethhdr->daddr, 6); - mac.toAddress(tap->_nwid).toString(nodeBuf); - - char flagbuf[32]; - memset(&flagbuf, 0, 32); -/* - struct pico_tcp_hdr *hdr; - void * tcp_hdr_ptr; - if (Utils::ntoh(ethhdr->proto) == 0x86dd) { // tcp, ipv6 - tcp_hdr_ptr = ðhdr + PICO_SIZE_ETHHDR + PICO_SIZE_IP4HDR; - } - - if (Utils::ntoh(ethhdr->proto) == 0x0800) // tcp - { - tcp_hdr_ptr = &buf + PICO_SIZE_ETHHDR + PICO_SIZE_IP4HDR; - hdr = (struct pico_tcp_hdr *)tcp_hdr_ptr; - - if (hdr) { - char *flag_ptr = flagbuf; - - if (hdr->flags & PICO_TCP_PSH) { - sprintf(flag_ptr, "PSH "); - flag_ptr+=4; - } - if (hdr->flags & PICO_TCP_SYN) { - sprintf(flag_ptr, "SYN "); - flag_ptr+=4; - } - if (hdr->flags & PICO_TCP_ACK) { - sprintf(flag_ptr, "ACK "); - flag_ptr+=4; - } - if (hdr->flags & PICO_TCP_FIN) { - sprintf(flag_ptr, "FIN "); - flag_ptr+=4; - } - if (hdr->flags & PICO_TCP_RST) { - sprintf(flag_ptr, "RST "); - flag_ptr+=4; - } - } - } -*/ - DEBUG_TRANS("len=%5d dst=%s [%s TX <-- %s] proto=0x%04x %s %s", len, macBuf, nodeBuf, tap->nodeId().c_str(), - Utils::ntoh(ethhdr->proto), beautify_eth_proto_nums(Utils::ntoh(ethhdr->proto)), flagbuf); - } - tap->_handler(tap->_arg,NULL,tap->_nwid,src_mac,dest_mac, - Utils::ntoh((uint16_t)ethhdr->proto), 0, ((char*)buf) - + sizeof(struct pico_eth_hdr),len - sizeof(struct pico_eth_hdr)); - //_picostack_driver_lock.unlock(); - return len; - } - - // receive frames from zerotier virtual wire and copy them to a guarded buffer awaiting placement into network stack - void picoTCP::pico_eth_rx(VirtualTap *tap, const MAC &from,const MAC &to,unsigned int etherType, - const void *data,unsigned int len) - { - //DEBUG_TRANS(); - //_picostack_driver_lock.lock(); - if (tap == NULL) { - DEBUG_ERROR("invalid tap"); - handle_general_failure(); - return; - } - // Since picoTCP only allows the reception of frames from within the polling function, we - // must enqueue each frame into a memory structure shared by both threads. This structure will - Mutex::Lock _l(tap->_pico_frame_rxbuf_m); - // assemble new eth header - struct pico_eth_hdr ethhdr; - from.copyTo(ethhdr.saddr, 6); - to.copyTo(ethhdr.daddr, 6); - ethhdr.proto = Utils::hton((uint16_t)etherType); - int32_t msg_len = len + sizeof(int32_t) + sizeof(struct pico_eth_hdr); - - if (ZT_MSG_TRANSFER == true) { - char macBuf[ZT_MAC_ADDRSTRLEN], nodeBuf[ZT_ID_LEN]; - mac2str(macBuf, sizeof(macBuf), ethhdr.saddr); - ZeroTier::MAC mac; - mac.setTo(ethhdr.saddr, 6); - mac.toAddress(tap->_nwid).toString(nodeBuf); - - char flagbuf[64]; - memset(&flagbuf, 0, 64); -/* - struct pico_tcp_hdr *hdr; - void * tcp_hdr_ptr; - if (etherType == 0x86dd) { // tcp, ipv6 - tcp_hdr_ptr = ðhdr + PICO_SIZE_ETHHDR + PICO_SIZE_IP4HDR; - } - - if (etherType == 0x0800) // tcp, ipv4 - { - tcp_hdr_ptr = ðhdr + PICO_SIZE_ETHHDR + PICO_SIZE_IP4HDR; - hdr = (struct pico_tcp_hdr *)tcp_hdr_ptr; - if (hdr) { - char *flag_ptr = flagbuf; - - if (hdr->flags & PICO_TCP_PSH) { - sprintf(flag_ptr, "PSH "); - flag_ptr+=4; - } - if (hdr->flags & PICO_TCP_SYN) { - sprintf(flag_ptr, "SYN "); - flag_ptr+=4; - } - if (hdr->flags & PICO_TCP_ACK) { - sprintf(flag_ptr, "ACK "); - flag_ptr+=4; - } - if (hdr->flags & PICO_TCP_FIN) { - sprintf(flag_ptr, "FIN "); - flag_ptr+=4; - } - if (hdr->flags & PICO_TCP_RST) { - sprintf(flag_ptr, "RST "); - flag_ptr+=4; - } - } - } -*/ - DEBUG_TRANS("len=%5d src=%s [%s RX --> %s] proto=0x%04x %s %s", len, macBuf, nodeBuf, tap->nodeId().c_str(), - etherType, beautify_eth_proto_nums(etherType), flagbuf); - } - // write virtual ethernet frame to guarded buffer (emptied by pico_eth_poll()) - memcpy(tap->pico_frame_rxbuf + tap->pico_frame_rxbuf_tot, &msg_len, sizeof(int32_t)); // size of frame + meta - memcpy(tap->pico_frame_rxbuf + tap->pico_frame_rxbuf_tot + sizeof(int32_t), ðhdr, sizeof(ethhdr)); // new eth header - memcpy(tap->pico_frame_rxbuf + tap->pico_frame_rxbuf_tot + sizeof(int32_t) + sizeof(ethhdr), data, len); // frame data - tap->pico_frame_rxbuf_tot += msg_len; - //_picostack_driver_lock.unlock(); - } - - // feed frames on the guarded RX buffer (from zerotier virtual wire) into the network stack - int pico_eth_poll(struct pico_device *dev, int loop_score) - { - VirtualTap *tap = static_cast(dev->tap); - if (tap == NULL) { - DEBUG_ERROR("invalid dev->tap"); - handle_general_failure(); - return ZT_ERR_GENERAL_FAILURE; - } - // TODO: Optimize (use Ringbuffer) - Mutex::Lock _l(tap->_pico_frame_rxbuf_m); - unsigned char frame[ZT_SDK_MTU]; - int32_t len, err = 0; - while (tap->pico_frame_rxbuf_tot > 0 && loop_score > 0) { - memset(frame, 0, sizeof(frame)); - len = 0; - // get frame len - memcpy(&len, tap->pico_frame_rxbuf, sizeof(int32_t)); - if (len > sizeof(int32_t)) { // meaning, since we package the len in the msg, we don't want to recv a 0-(sizeof(int32_t)) sized frame - memcpy(frame, tap->pico_frame_rxbuf + sizeof(int32_t), len-(sizeof(int32_t)) ); // get frame data - memmove(tap->pico_frame_rxbuf, tap->pico_frame_rxbuf + len, MAX_PICO_FRAME_RX_BUF_SZ-len); // shift buffer - if ((err = pico_stack_recv(dev, (uint8_t*)frame, (len-sizeof(int32_t)))) < 0) { - if (picostack) { - DEBUG_ERROR("pico_stack_recv(), err=%d, pico_err=%d, %s", err, pico_err, picostack->beautify_pico_error(pico_err)); - } - } - tap->pico_frame_rxbuf_tot-=len; - } - else { - DEBUG_ERROR("invalid frame size (%d)",len); - handle_general_failure(); - } - loop_score--; - } - return loop_score; - } - - int picoTCP::pico_Socket(struct pico_socket **p, int socket_family, int socket_type, int protocol) - { - int err = 0; - if (can_provision_new_socket(socket_type) == false) { - DEBUG_ERROR("cannot create additional socket, see PICO_MAX_TIMERS. current=%d", pico_ntimers()); - errno = EMFILE; - err = -1; - } - else { - int protocol_version = 0; - struct pico_socket *psock; - if (socket_family == AF_INET) { - protocol_version = PICO_PROTO_IPV4; - } - if (socket_family == AF_INET6) { - protocol_version = PICO_PROTO_IPV6; - } - if (socket_type == SOCK_DGRAM) { - psock = pico_socket_open(protocol_version, PICO_PROTO_UDP, &ZeroTier::picoTCP::pico_cb_socket_ev); - if (psock) { - // configure size of UDP SND/RCV buffers - // TODO - } - } - if (socket_type == SOCK_STREAM) { - psock = pico_socket_open(protocol_version, PICO_PROTO_TCP, &ZeroTier::picoTCP::pico_cb_socket_ev); - if (psock) { - // configure size of TCP SND/RCV buffers - int tx_buf_sz = ZT_STACK_TCP_SOCKET_TX_SZ; - int rx_buf_sz = ZT_STACK_TCP_SOCKET_RX_SZ; - int t_err = 0; - if ((t_err = pico_socket_setoption(psock, PICO_SOCKET_OPT_SNDBUF, &tx_buf_sz)) < 0) { - DEBUG_ERROR("unable to set SNDBUF size, err=%d, pico_err=%d, %s", - t_err, pico_err, beautify_pico_error(pico_err)); - } - if ((t_err = pico_socket_setoption(psock, PICO_SOCKET_OPT_RCVBUF, &rx_buf_sz)) < 0) { - DEBUG_ERROR("unable to set RCVBUF size, err=%d, pico_err=%d, %s", - t_err, pico_err, beautify_pico_error(pico_err)); - } - } - } - *p = psock; - } - return err; - } - - int picoTCP::pico_Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen) - { - if (vs == NULL || vs->picosock == NULL) { - DEBUG_ERROR("invalid vs or vs->picosock"); - handle_general_failure(); - return ZT_ERR_GENERAL_FAILURE; - } - int err = 0; - if (vs->socket_family == AF_INET) { - struct pico_ip4 zaddr; - memset(&zaddr, 0, sizeof (struct pico_ip4)); - struct sockaddr_in *in4 = (struct sockaddr_in*)addr; - char ipv4_str[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, (const void *)&in4->sin_addr.s_addr, ipv4_str, INET_ADDRSTRLEN); - uint32_t ipval = 0; - pico_string_to_ipv4(ipv4_str, &ipval); - zaddr.addr = ipval; - if (vs->socket_type == SOCK_STREAM) { // connect is an implicit call for non-connection-based VirtualSockets - DEBUG_EXTRA("connecting to addr=%s port=%d", ipv4_str, Utils::ntoh(in4->sin_port)); - } - err = pico_socket_connect(vs->picosock, &zaddr, in4->sin_port); - } - if (vs->socket_family == AF_INET6) { - struct pico_ip6 zaddr; - struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr; - char ipv6_str[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &(in6->sin6_addr), ipv6_str, INET6_ADDRSTRLEN); - pico_string_to_ipv6(ipv6_str, zaddr.addr); - if (vs->socket_type == SOCK_STREAM) { - DEBUG_EXTRA("connecting to addr=%s port=%d", ipv6_str, Utils::ntoh(in6->sin6_port)); - } - err = pico_socket_connect(vs->picosock, &zaddr, in6->sin6_port); - } - if (err) { - DEBUG_ERROR("error connecting pico_socket=%p, err=%d, pico_err=%d, %s", - vs->picosock, err, pico_err, beautify_pico_error(pico_err)); - return map_pico_err_to_errno(pico_err); - } - memcpy(&(vs->peer_addr), &addr, sizeof(struct sockaddr_storage)); - return err; - } - - int picoTCP::pico_Bind(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen) - { - if (vs == NULL || vs->picosock == NULL) { - DEBUG_ERROR("invalid vs or vs->picosock"); - handle_general_failure(); - return ZT_ERR_GENERAL_FAILURE; - } - int err = 0; - if (vs->socket_family == AF_INET) { - struct pico_ip4 zaddr; - uint32_t tempaddr; - memset(&zaddr, 0, sizeof (struct pico_ip4)); - struct sockaddr_in *in4 = (struct sockaddr_in*)addr; - char ipv4_str[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, (const void *)&in4->sin_addr.s_addr, ipv4_str, INET_ADDRSTRLEN); - pico_string_to_ipv4(ipv4_str, &tempaddr); - zaddr.addr = tempaddr; - DEBUG_EXTRA("binding to addr=%s port=%d", ipv4_str, Utils::ntoh(in4->sin_port)); - err = pico_socket_bind(vs->picosock, &zaddr, (uint16_t *)&(in4->sin_port)); - } - if (vs->socket_family == AF_INET6) { - struct pico_ip6 pip6; - struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr; - char ipv6_str[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &(in6->sin6_addr), ipv6_str, INET6_ADDRSTRLEN); - // TODO: This isn't proper - pico_string_to_ipv6("::", pip6.addr); - DEBUG_EXTRA("binding to addr=%s port=%d", ipv6_str, Utils::ntoh(in6->sin6_port)); - err = pico_socket_bind(vs->picosock, &pip6, (uint16_t *)&(in6->sin6_port)); - } - if (err < 0) { - DEBUG_ERROR("unable to bind pico_socket=%p, err=%d, pico_err=%d, %s", - (vs->picosock), err, pico_err, beautify_pico_error(pico_err)); - return map_pico_err_to_errno(pico_err); - } - return err; - } - - int picoTCP::pico_Listen(VirtualSocket *vs, int backlog) - { - if (vs == NULL || vs->picosock == NULL) { - DEBUG_ERROR("invalid vs or vs->picosock"); - handle_general_failure(); - return ZT_ERR_GENERAL_FAILURE; - } - int err = 0; - if ((err = pico_socket_listen(vs->picosock, backlog)) < 0) { - DEBUG_ERROR("error putting pico_socket=%p into listening state. err=%d, pico_err=%d, %s", - vs->picosock, err, pico_err, beautify_pico_error(pico_err)); - return map_pico_err_to_errno(pico_err); - } - vs->set_state(VS_STATE_LISTENING); - return ZT_ERR_OK; - } - - VirtualSocket* picoTCP::pico_Accept(VirtualSocket *vs) - { - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - handle_general_failure(); - return NULL; - } - // Retreive first of queued VirtualSockets from parent VirtualSocket - VirtualSocket *new_vs = NULL; - if (vs->_AcceptedConnections.size()) { - new_vs = vs->_AcceptedConnections.front(); - vs->_AcceptedConnections.pop(); - } - return new_vs; - } - - int picoTCP::pico_Read(VirtualTap *tap, PhySocket *sock, VirtualSocket* vs, bool stack_invoked) - { - // DEBUG_INFO(); - // Vestigial - return 0; - } - - int picoTCP::pico_Write(VirtualSocket *vs, void *data, ssize_t len) - { - int err = 0; - void *src_buf = NULL; - // TODO: Add RingBuffer overflow checks - DEBUG_EXTRA("vs=%p, fd=%d, data=%p, len=%d", vs, vs->app_fd, data, len); - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - handle_general_failure(); - return ZT_ERR_GENERAL_FAILURE; - } - Mutex::Lock _l(vs->_tx_m); - if (vs->picosock == NULL) { - DEBUG_ERROR("ps == NULL"); - handle_general_failure(); - return -1; - } - if (vs->app_fd <= 0) { - DEBUG_EXTRA("invalid fd"); - handle_general_failure(); - return -1; - } - if (vs->picosock->state & PICO_SOCKET_STATE_CLOSED) { - DEBUG_ERROR("socket is PICO_SOCKET_STATE_CLOSED, this pico_tcp_write() will fail"); - return -1; - } - if (vs == NULL) { - DEBUG_ERROR("invalid VirtualSocket (len=%d)", len); - handle_general_failure(); - return -1; - } - if (vs->socket_type == SOCK_DGRAM) { - if (data == NULL) { - DEBUG_ERROR("data == NULL"); - handle_general_failure(); - return -1; - } - if (len <= 0) { - DEBUG_ERROR("invalid write len=%d for SOCK_DGRAM", len); - handle_general_failure(); - return -1; - } - int r; - if ((r = pico_socket_write(vs->picosock, data, len)) < 0) { - DEBUG_ERROR("unable to write to picosock=%p, err=%d, pico_err=%d, %s", - vs->picosock, r, pico_err, beautify_pico_error(pico_err)); - err = -1; - } - else { - err = r; // successful write - } - if (vs->socket_type == SOCK_DGRAM) { - DEBUG_TRANS("len=%5d buf_len=N/A [APPFDS --> NSPICO] proto=0x%04x (UDP)", r, PICO_PROTO_TCP); - } - } - if (vs->socket_type == SOCK_STREAM) { - if (len > 0 && data != NULL) { - - src_buf = data; // --- Data source: poll loop I/O buffer --- - - // in this case, we've recieved data on the 'data' buffer, add it to TX ringbuffer, then try to handle it from there - int original_txsz = vs->TXbuf->count(); - if (original_txsz + len >= ZT_TCP_TX_BUF_SZ) { - DEBUG_ERROR("txsz=%d, len=%d", original_txsz, len); - DEBUG_ERROR("TX buffer is too small, try increasing ZT_TCP_TX_BUF_SZ in libzt.h"); - handle_general_failure(); - return ZT_ERR_GENERAL_FAILURE; - } - int buf_w = vs->TXbuf->write((const unsigned char*)data, len); - if (buf_w != len) { - // because we checked ZT_TCP_TX_BUF_SZ above, this should not happen - DEBUG_ERROR("wrote only len=%d but expected to write len=%d", buf_w, len); - handle_general_failure(); - return ZT_ERR_GENERAL_FAILURE; - } - } else if (len == 0 && data == NULL) { - DEBUG_EXTRA("len=0 => write request from poll loop or callback"); - - src_buf = vs->TXbuf->get_buf(); // --- Data source: TX ringbuffer --- - - // do nothing, all the data we need is already on the TX ringbuffer - } else if (len < 0) { - DEBUG_ERROR("invalid write len=%d for SOCK_STREAM", len); - } - - int txsz = vs->TXbuf->count(); - int r, max_write_len = std::min(std::min(txsz, ZT_SDK_MTU),ZT_STACK_SOCKET_WR_MAX); - if ((r = pico_socket_write(vs->picosock, src_buf, max_write_len)) < 0) { - DEBUG_ERROR("unable to write to picosock=%p, err=%d, pico_err=%d, %s", - vs->picosock, r, pico_err, beautify_pico_error(pico_err)); - err = -1; - } - else { - err = r; // successful write - } - if (r>0) { - vs->TXbuf->consume(r); - if (vs->socket_type == SOCK_STREAM) { - DEBUG_TRANS("len=%5d buf_len=%13d [VSTXBF --> NSPICO] proto=0x%04x (TCP)", r, vs->TXbuf->count(), PICO_PROTO_TCP); - } - } - } - return err; - } - - int picoTCP::pico_Close(VirtualSocket *vs) - { - DEBUG_EXTRA(); - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - handle_general_failure(); - return ZT_ERR_GENERAL_FAILURE; - } - if (vs->get_state() == VS_STATE_CLOSED) { - DEBUG_EXTRA("socket already in VS_STATE_CLOSED state"); - return 0; - } - if (vs->picosock == NULL) { - DEBUG_EXTRA("ps == NULL"); - return 0; - } - if (vs->picosock->state & PICO_SOCKET_STATE_CLOSED) { - DEBUG_EXTRA("ps already closed, ps=%p", vs->picosock); - return 0; - } - DEBUG_EXTRA("vs=%p, picosock=%p, fd=%d", vs, vs->picosock, vs->app_fd); - if (vs == NULL || vs->picosock == NULL) - return ZT_ERR_GENERAL_FAILURE; - int err = 0; - Mutex::Lock _l(vs->tap->_tcpconns_m); - if ((err = pico_socket_close(vs->picosock)) < 0) { - errno = pico_err; - DEBUG_ERROR("error closing pico_socket, err=%d, pico_err=%d, %s", - err, pico_err, beautify_pico_error(pico_err)); - } - return err; - } - - int picoTCP::pico_Shutdown(VirtualSocket *vs, int how) - { - DEBUG_EXTRA("vs=%p, how=%d", vs, how); - int err = 0, mode = 0; - if (how == SHUT_RD) { - mode = PICO_SHUT_RD; - } - if (how == SHUT_WR) { - mode = PICO_SHUT_WR; - } - if (how == SHUT_RDWR) { - mode = PICO_SHUT_RDWR; - } - if ((err = pico_socket_shutdown(vs->picosock, mode)) < 0) { - DEBUG_ERROR("error while shutting down socket, fd=%d, pico_err=%d, %s", vs->app_fd, pico_err, beautify_pico_error(pico_err)); - } - return err; - } - - int picoTCP::pico_setsockopt(VirtualSocket *vs, int level, int optname, const void *optval, socklen_t optlen) - { - int err = -1; - errno = 0; - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - return -1; - } else { - DEBUG_EXTRA("fd=%d, level=%d, optname=%d", vs->app_fd, level, optname); - } - if (level == SOL_SOCKET) - { - /* Turns on recording of debugging information. This option enables or disables debugging in the underlying - protocol modules. This option takes an int value. This is a Boolean option.*/ - if (optname == SO_DEBUG) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Specifies that the rules used in validating addresses supplied to bind() should allow reuse of local - addresses, if this is supported by the protocol. This option takes an int value. This is a Boolean option.*/ - if (optname == SO_REUSEADDR) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Keeps connections active by enabling the periodic transmission of messages, if this is supported by the - protocol. This option takes an int value. */ - if (optname == SO_KEEPALIVE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Requests that outgoing messages bypass the standard routing facilities. */ - if (optname == SO_DONTROUTE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Lingers on a close() if data is present. */ - if (optname == SO_LINGER) - { - int linger_time_ms = *((const int*)optval); - if ((err = pico_socket_setoption(vs->picosock, PICO_SOCKET_OPT_LINGER, &linger_time_ms)) < 0) { - DEBUG_ERROR("unable to set LINGER, err=%d, pico_err=%d, %s", - err, pico_err, beautify_pico_error(pico_err)); - } - return err; - } - /* Permits sending of broadcast messages, if this is supported by the protocol. This option takes an int - value. This is a Boolean option. */ - if (optname == SO_BROADCAST) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Leaves received out-of-band data (data marked urgent) inline. This option takes an int value. This is a - Boolean option. */ - if (optname == SO_OOBINLINE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Sets send buffer size. This option takes an int value. */ - if (optname == SO_SNDBUF) - { - int no_delay = *((const int*)optval); - if ((err = pico_socket_setoption(vs->picosock, PICO_SOCKET_OPT_SNDBUF, &no_delay) < 0)) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while setting PICO_SOCKET_OPT_SNDBUF"); - errno = EINVAL; - err = -1; - } - } - return err; - } - /* Sets receive buffer size. This option takes an int value. */ - if (optname == SO_RCVBUF) - { - int no_delay = *((const int*)optval); - if ((err = pico_socket_setoption(vs->picosock, PICO_SOCKET_OPT_RCVBUF, &no_delay) < 0)) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while setting PICO_SOCKET_OPT_RCVBUF"); - errno = EINVAL; - err = -1; - } - } - return err; - } - /* */ - if (optname == SO_STYLE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* */ - if (optname == SO_TYPE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Get error status and clear */ - if (optname == SO_ERROR) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - } - if (level == IPPROTO_IP) - { - if (optname == IP_ADD_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_ADD_SOURCE_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_BIND_ADDRESS_NO_PORT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_BLOCK_SOURCE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_DROP_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_DROP_SOURCE_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_FREEBIND) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_HDRINCL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MSFILTER) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MTU) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MTU_DISCOVER) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_ALL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_IF) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_LOOP) { - int loop = *((const int*)optval); - if ((err = pico_socket_setoption(vs->picosock, PICO_IP_MULTICAST_LOOP, &loop) < 0)) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while setting PICO_IP_MULTICAST_TTL"); - errno = EINVAL; - err = -1; - } - } - return err; - } - if (optname == IP_MULTICAST_TTL) { - int ttl = *((const int*)optval); - if ((err = pico_socket_setoption(vs->picosock, PICO_IP_MULTICAST_TTL, &ttl) < 0)) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while setting PICO_IP_MULTICAST_TTL"); - errno = EINVAL; - err = -1; - } - } - return err; - } - if (optname == IP_NODEFRAG) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_OPTIONS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_PKTINFO) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVOPTS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVORIGDSTADDR) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVTOS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVTTL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RETOPTS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_ROUTER_ALERT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TOS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TRANSPARENT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TTL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_UNBLOCK_SOURCE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - // TODO - return -1; - } - if (level == IPPROTO_TCP) - { - struct pico_socket *p = vs->picosock; - if (p == NULL) { - handle_general_failure(); - return -1; - } - /* If set, don't send out partial frames. */ - if (optname == TCP_CORK) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Allow a listener to be awakened only when data arrives on the socket. */ - if (optname == TCP_DEFER_ACCEPT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Used to collect information about this socket. The kernel returns a struct tcp_info as defined in the - file /usr/include/linux/tcp.h.*/ - if (optname == TCP_INFO) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The maximum number of keepalive probes TCP should send before dropping the connection.*/ - if (optname == TCP_KEEPCNT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes, - if the socket option SO_KEEPALIVE has been set on this socket. */ - if (optname == TCP_KEEPIDLE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The time (in seconds) between individual keepalive probes.*/ - if (optname == TCP_KEEPINTVL) { - // TODO - return -1; - } - /* The lifetime of orphaned FIN_WAIT2 state sockets. */ - if (optname == TCP_LINGER2) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The maximum segment size for outgoing TCP packets. */ - if (optname == TCP_MAXSEG) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* If set, disable the Nagle algorithm. */ - if (optname == TCP_NODELAY) { - int no_delay = *((const int*)optval); - if ((err = pico_socket_setoption(vs->picosock, PICO_TCP_NODELAY, &no_delay) < 0)) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while disabling Nagle's algorithm"); - errno = EINVAL; - err = -1; - } - } - return err; - } - /* Enable quickack mode if set or disable quickack mode if cleared. */ - if (optname == TCP_QUICKACK) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Set the number of SYN retransmits that TCP should send before aborting the attempt to connect. It - cannot exceed 255. */ - if (optname == TCP_SYNCNT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Bound the size of the advertised window to this value. The kernel imposes a minimum size of - SOCK_MIN_RCVBUF/2. */ - if (optname == TCP_WINDOW_CLAMP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - } - if (level == IPPROTO_UDP) - { - /*If this option is enabled, then all data output on this socket is accumulated into a single - datagram that is transmitted when the option is disabled. */ - if (optname == UDP_CORK) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - } - return err; - } - - int picoTCP::pico_getsockopt(VirtualSocket *vs, int level, int optname, void *optval, socklen_t *optlen) - { - int err = -1, optval_tmp = 0; - errno = 0; - if (vs == NULL) { - DEBUG_ERROR("invalid vs"); - return -1; - } else { - DEBUG_EXTRA("fd=%d, level=%d, optname=%d", vs->app_fd, level, optname); - } - if (level == SOL_SOCKET) - { - /* Turns on recording of debugging information. This option enables or disables debugging in the underlying - protocol modules. This option takes an int value. This is a Boolean option.*/ - if (optname == SO_DEBUG) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Specifies that the rules used in validating addresses supplied to bind() should allow reuse of local - addresses, if this is supported by the protocol. This option takes an int value. This is a Boolean option.*/ - if (optname == SO_REUSEADDR) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Keeps connections active by enabling the periodic transmission of messages, if this is supported by the - protocol. This option takes an int value. */ - if (optname == SO_KEEPALIVE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Requests that outgoing messages bypass the standard routing facilities. */ - if (optname == SO_DONTROUTE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Lingers on a close() if data is present. */ - if (optname == SO_LINGER) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Permits sending of broadcast messages, if this is supported by the protocol. This option takes an int - value. This is a Boolean option. */ - if (optname == SO_BROADCAST) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Leaves received out-of-band data (data marked urgent) inline. This option takes an int value. This is a - Boolean option. */ - if (optname == SO_OOBINLINE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Sets send buffer size. This option takes an int value. */ - if (optname == SO_SNDBUF) - { - if ((err = pico_socket_getoption(vs->picosock, PICO_SOCKET_OPT_SNDBUF, &optval_tmp)) < 0) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while getting PICO_SOCKET_OPT_SNDBUF"); - errno = ENOPROTOOPT; - err = -1; - } - } - memcpy(optval, &optval_tmp, *optlen); - } - /* Sets receive buffer size. This option takes an int value. */ - if (optname == SO_RCVBUF) - { - if ((err = pico_socket_getoption(vs->picosock, PICO_SOCKET_OPT_SNDBUF, &optval_tmp)) < 0) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while getting PICO_SOCKET_OPT_RCVBUF"); - errno = ENOPROTOOPT; - err = -1; - } - } - memcpy(optval, &optval_tmp, *optlen); - } - /* */ - if (optname == SO_STYLE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* */ - if (optname == SO_TYPE) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Get error status and clear */ - if (optname == SO_ERROR) - { - // TODO - errno = ENOPROTOOPT; - return -1; - } - } - if (level == IPPROTO_IP) - { - if (optname == IP_ADD_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_ADD_SOURCE_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_BIND_ADDRESS_NO_PORT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_BLOCK_SOURCE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_DROP_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_DROP_SOURCE_MEMBERSHIP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_FREEBIND) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_HDRINCL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MSFILTER) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MTU) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MTU_DISCOVER) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_ALL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_IF) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_MULTICAST_LOOP) { - if ((err = pico_socket_getoption(vs->picosock, PICO_IP_MULTICAST_LOOP, &optval_tmp)) < 0) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while getting PICO_IP_MULTICAST_TTL"); - errno = ENOPROTOOPT; - err = -1; - } - } - memcpy(optval, &optval_tmp, *optlen); - } - if (optname == IP_MULTICAST_TTL) { - if ((err = pico_socket_getoption(vs->picosock, PICO_IP_MULTICAST_TTL, &optval_tmp)) < 0) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while getting PICO_IP_MULTICAST_TTL"); - errno = ENOPROTOOPT; - err = -1; - } - } - memcpy(optval, &optval_tmp, *optlen); - } - if (optname == IP_NODEFRAG) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_OPTIONS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_PKTINFO) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVOPTS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVORIGDSTADDR) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVTOS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RECVTTL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_RETOPTS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_ROUTER_ALERT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TOS) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TRANSPARENT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_TTL) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - if (optname == IP_UNBLOCK_SOURCE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - // TODO - return -1; - } - if (level == IPPROTO_TCP) - { - struct pico_socket *p = vs->picosock; - if (p == NULL) { - handle_general_failure(); - return -1; - } - /* If set, don't send out partial frames. */ - if (optname == TCP_CORK) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Allow a listener to be awakened only when data arrives on the socket. */ - if (optname == TCP_DEFER_ACCEPT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Used to collect information about this socket. */ - if (optname == TCP_INFO) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The maximum number of keepalive probes TCP should send before dropping the connection.*/ - if (optname == TCP_KEEPCNT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes, - if the socket option SO_KEEPALIVE has been set on this socket. */ - if (optname == TCP_KEEPIDLE) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The time (in seconds) between individual keepalive probes.*/ - if (optname == TCP_KEEPINTVL) { - // TODO - return -1; - } - /* The lifetime of orphaned FIN_WAIT2 state sockets. */ - if (optname == TCP_LINGER2) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* The maximum segment size for outgoing TCP packets. */ - if (optname == TCP_MAXSEG) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* If set, disable the Nagle algorithm. */ - if (optname == TCP_NODELAY) { - if ((err = pico_socket_getoption(vs->picosock, PICO_TCP_NODELAY, &optval_tmp)) < 0) { - if (err == PICO_ERR_EINVAL) { - DEBUG_ERROR("error while disabling Nagle's algorithm"); - errno = ENOPROTOOPT; - err = -1; - } - } - memcpy(optval, &optval_tmp, *optlen); - return err; - } - /* Enable quickack mode if set or disable quickack mode if cleared. */ - if (optname == TCP_QUICKACK) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Set the number of SYN retransmits that TCP should send before aborting the attempt to connect. It - cannot exceed 255. */ - if (optname == TCP_SYNCNT) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - /* Bound the size of the advertised window to this value. The kernel imposes a minimum size of - SOCK_MIN_RCVBUF/2. */ - if (optname == TCP_WINDOW_CLAMP) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - } - if (level == IPPROTO_UDP) - { - /*If this option is enabled, then all data output on this socket is accumulated into a single - datagram that is transmitted when the option is disabled. */ - if (optname == UDP_CORK) { - // TODO - errno = ENOPROTOOPT; - return -1; - } - } - return err; - } - - int picoTCP::map_pico_err_to_errno(int err) - { - if (err == PICO_ERR_NOERR) { errno = 0; return 0; } // - if (err == PICO_ERR_EPERM) { errno = ENXIO; } - if (err == PICO_ERR_ENOENT) { errno = ENXIO; } - if (err == PICO_ERR_EINTR) { errno = ENXIO; } - if (err == PICO_ERR_EIO) { errno = ENXIO; } - if (err == PICO_ERR_ENXIO) { errno = ENXIO; } // - if (err == PICO_ERR_EAGAIN) { errno = ENXIO; } - if (err == PICO_ERR_ENOMEM) { errno = ENOMEM; } // - if (err == PICO_ERR_EACCESS) { errno = ENXIO; } - if (err == PICO_ERR_EFAULT) { errno = ENXIO; } - if (err == PICO_ERR_EBUSY) { errno = ENXIO; } - if (err == PICO_ERR_EEXIST) { errno = ENXIO; } - if (err == PICO_ERR_EINVAL) { errno = EINVAL; } // - if (err == PICO_ERR_ENONET) { errno = ENXIO; } - if (err == PICO_ERR_EPROTO) { errno = ENXIO; } - if (err == PICO_ERR_ENOPROTOOPT) { errno = ENXIO; } - if (err == PICO_ERR_EPROTONOSUPPORT) { errno = ENXIO; } - if (err == PICO_ERR_EOPNOTSUPP) { errno = ENXIO; } - if (err == PICO_ERR_EADDRINUSE) { errno = ENXIO; } - if (err == PICO_ERR_EADDRNOTAVAIL) { errno = ENXIO; } - if (err == PICO_ERR_ENETDOWN) { errno = ENXIO; } - if (err == PICO_ERR_ENETUNREACH) { errno = ENXIO; } - if (err == PICO_ERR_ECONNRESET) { errno = ENXIO; } - if (err == PICO_ERR_EISCONN) { errno = ENXIO; } - if (err == PICO_ERR_ENOTCONN) { errno = ENXIO; } - if (err == PICO_ERR_ESHUTDOWN) { errno = ENXIO; } - if (err == PICO_ERR_ETIMEDOUT) { errno = ENXIO; } - if (err == PICO_ERR_ECONNREFUSED) { errno = ENXIO; } - if (err == PICO_ERR_EHOSTDOWN) { errno = ENXIO; } - if (err == PICO_ERR_EHOSTUNREACH) { errno = ENXIO; } - return -1; - } - - char *picoTCP::beautify_pico_error(int err) - { - if (err== 0) return (char*)"PICO_ERR_NOERR"; - if (err== 1) return (char*)"PICO_ERR_EPERM"; - if (err== 2) return (char*)"PICO_ERR_ENOENT"; - // ... - if (err== 4) return (char*)"PICO_ERR_EINTR"; - if (err== 5) return (char*)"PICO_ERR_EIO"; - if (err== 6) return (char*)"PICO_ERR_ENXIO (no such device or address)"; - // ... - if (err== 11) return (char*)"PICO_ERR_EAGAIN"; - if (err== 12) return (char*)"PICO_ERR_ENOMEM (not enough space)"; - if (err== 13) return (char*)"PICO_ERR_EACCESS"; - if (err== 14) return (char*)"PICO_ERR_EFAULT"; - // ... - if (err== 16) return (char*)"PICO_ERR_EBUSY"; - if (err== 17) return (char*)"PICO_ERR_EEXIST"; - // ... - if (err== 22) return (char*)"PICO_ERR_EINVAL (invalid argument)"; - // ... - if (err== 64) return (char*)"PICO_ERR_ENONET"; - // ... - if (err== 71) return (char*)"PICO_ERR_EPROTO"; - // ... - if (err== 92) return (char*)"PICO_ERR_ENOPROTOOPT"; - if (err== 93) return (char*)"PICO_ERR_EPROTONOSUPPORT"; - // ... - if (err== 95) return (char*)"PICO_ERR_EOPNOTSUPP"; - if (err== 98) return (char*)"PICO_ERR_EADDRINUSE"; - if (err== 99) return (char*)"PICO_ERR_EADDRNOTAVAIL"; - if (err==100) return (char*)"PICO_ERR_ENETDOWN"; - if (err==101) return (char*)"PICO_ERR_ENETUNREACH"; - // ... - if (err==104) return (char*)"PICO_ERR_ECONNRESET"; - // ... - if (err==106) return (char*)"PICO_ERR_EISCONN"; - if (err==107) return (char*)"PICO_ERR_ENOTCONN"; - if (err==108) return (char*)"PICO_ERR_ESHUTDOWN"; - // ... - if (err==110) return (char*)"PICO_ERR_ETIMEDOUT"; - if (err==111) return (char*)"PICO_ERR_ECONNREFUSED"; - if (err==112) return (char*)"PICO_ERR_EHOSTDOWN"; - if (err==113) return (char*)"PICO_ERR_EHOSTUNREACH"; - return (char*)"UNKNOWN_ERROR"; - } - -/* - -#define PICO_SOCKET_STATE_UNDEFINED 0x0000u -#define PICO_SOCKET_STATE_SHUT_LOCAL 0x0001u -#define PICO_SOCKET_STATE_SHUT_REMOTE 0x0002u -#define PICO_SOCKET_STATE_BOUND 0x0004u -#define PICO_SOCKET_STATE_CONNECTED 0x0008u -#define PICO_SOCKET_STATE_CLOSING 0x0010u -#define PICO_SOCKET_STATE_CLOSED 0x0020u - -# define PICO_SOCKET_STATE_TCP 0xFF00u -# define PICO_SOCKET_STATE_TCP_UNDEF 0x00FFu -# define PICO_SOCKET_STATE_TCP_CLOSED 0x0100u -# define PICO_SOCKET_STATE_TCP_LISTEN 0x0200u -# define PICO_SOCKET_STATE_TCP_SYN_SENT 0x0300u -# define PICO_SOCKET_STATE_TCP_SYN_RECV 0x0400u -# define PICO_SOCKET_STATE_TCP_ESTABLISHED 0x0500u -# define PICO_SOCKET_STATE_TCP_CLOSE_WAIT 0x0600u -# define PICO_SOCKET_STATE_TCP_LAST_ACK 0x0700u -# define PICO_SOCKET_STATE_TCP_FIN_WAIT1 0x0800u -# define PICO_SOCKET_STATE_TCP_FIN_WAIT2 0x0900u -# define PICO_SOCKET_STATE_TCP_CLOSING 0x0a00u -# define PICO_SOCKET_STATE_TCP_TIME_WAIT 0x0b00u -# define PICO_SOCKET_STATE_TCP_ARRAYSIZ 0x0cu - -*/ - char *picoTCP::beautify_pico_state(int state) - { - static char state_str[512]; - char *str_ptr = state_str; - - if (state & PICO_SOCKET_STATE_UNDEFINED) { - sprintf(str_ptr, "UNDEFINED "); - str_ptr += strlen("UNDEFINED "); - } - if (state & PICO_SOCKET_STATE_SHUT_LOCAL) { - sprintf(str_ptr, "SHUT_LOCAL "); - str_ptr += strlen("SHUT_LOCAL "); - } - if (state & PICO_SOCKET_STATE_SHUT_REMOTE) { - sprintf(str_ptr, "SHUT_REMOTE "); - str_ptr += strlen("SHUT_REMOTE "); - } - if (state & PICO_SOCKET_STATE_BOUND) { - sprintf(str_ptr, "BOUND "); - str_ptr += strlen("BOUND "); - } - if (state & PICO_SOCKET_STATE_CONNECTED) { - sprintf(str_ptr, "CONNECTED "); - str_ptr += strlen("CONNECTED "); - } - if (state & PICO_SOCKET_STATE_CLOSING) { - sprintf(str_ptr, "CLOSING "); - str_ptr += strlen("CLOSING "); - } - if (state & PICO_SOCKET_STATE_CLOSED) { - sprintf(str_ptr, "CLOSED "); - str_ptr += strlen("CLOSED "); - } - - - if (state & PICO_SOCKET_STATE_TCP) { - sprintf(str_ptr, "TCP "); - str_ptr += strlen("TCP "); - } - if (state & PICO_SOCKET_STATE_TCP_UNDEF) { - sprintf(str_ptr, "TCP_UNDEF "); - str_ptr += strlen("TCP_UNDEF "); - } - if (state & PICO_SOCKET_STATE_TCP_CLOSED) { - sprintf(str_ptr, "TCP_CLOSED "); - str_ptr += strlen("TCP_CLOSED "); - } - if (state & PICO_SOCKET_STATE_TCP_LISTEN) { - sprintf(str_ptr, "TCP_LISTEN "); - str_ptr += strlen("TCP_LISTEN "); - } - if (state & PICO_SOCKET_STATE_TCP_SYN_SENT) { - sprintf(str_ptr, "TCP_SYN_SENT "); - str_ptr += strlen("TCP_SYN_SENT "); - } - if (state & PICO_SOCKET_STATE_TCP_SYN_RECV) { - sprintf(str_ptr, "TCP_SYN_RECV "); - str_ptr += strlen("TCP_SYN_RECV "); - } - if (state & PICO_SOCKET_STATE_TCP_ESTABLISHED) { - sprintf(str_ptr, "TCP_ESTABLISHED "); - str_ptr += strlen("TCP_ESTABLISHED "); - } - if (state & PICO_SOCKET_STATE_TCP_CLOSE_WAIT) { - sprintf(str_ptr, "TCP_CLOSE_WAIT "); - str_ptr += strlen("TCP_CLOSE_WAIT "); - } - if (state & PICO_SOCKET_STATE_TCP_LAST_ACK) { - sprintf(str_ptr, "TCP_LAST_ACK "); - str_ptr += strlen("TCP_LAST_ACK "); - } - if (state & PICO_SOCKET_STATE_TCP_FIN_WAIT1) { - sprintf(str_ptr, "TCP_FIN_WAIT1 "); - str_ptr += strlen("TCP_FIN_WAIT1 "); - } - if (state & PICO_SOCKET_STATE_TCP_FIN_WAIT2) { - sprintf(str_ptr, "TCP_FIN_WAIT2 "); - str_ptr += strlen("TCP_FIN_WAIT2 "); - } - if (state & PICO_SOCKET_STATE_TCP_CLOSING) { - sprintf(str_ptr, "TCP_CLOSING "); - str_ptr += strlen("TCP_CLOSING "); - } - if (state & PICO_SOCKET_STATE_TCP_TIME_WAIT) { - sprintf(str_ptr, "TCP_TIME_WAIT "); - str_ptr += strlen("TCP_TIME_WAIT "); - } - if (state & PICO_SOCKET_STATE_TCP_ARRAYSIZ) { - sprintf(str_ptr, "TCP_ARRAYSIZ "); - str_ptr += strlen("TCP_ARRAYSIZ "); - } - return (char*)state_str; - } -} diff --git a/src/picoTCP.hpp b/src/picoTCP.hpp deleted file mode 100644 index 3de6eb0..0000000 --- a/src/picoTCP.hpp +++ /dev/null @@ -1,231 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#ifndef ZT_PICOTCP_HPP -#define ZT_PICOTCP_HPP - -#include "pico_eth.h" -#include "pico_stack.h" -#include "pico_ipv4.h" -#include "pico_icmp4.h" -#include "pico_dev_tap.h" -#include "pico_protocol.h" -#include "pico_socket.h" -#include "pico_device.h" -#include "pico_ipv6.h" - -#include "VirtualTap.hpp" - -/****************************************************************************/ -/* PicoTCP API Signatures (See libzt.h for the application-facing API) */ -/****************************************************************************/ - -#define PICO_IPV4_TO_STRING_SIG char *ipbuf, const uint32_t ip -#define PICO_TAP_CREATE_SIG char *name -#define PICO_IPV4_LINK_ADD_SIG struct pico_device *dev, struct pico_ip4 address, struct pico_ip4 netmask -#define PICO_DEVICE_INIT_SIG struct pico_device *dev, const char *name, uint8_t *mac -#define PICO_STACK_RECV_SIG struct pico_device *dev, uint8_t *buffer, uint32_t len -#define PICO_ICMP4_PING_SIG char *dst, int count, int interval, int timeout, int size, void (*cb)(struct pico_icmp4_stats *) -#define PICO_TIMER_ADD_SIG pico_time expire, void (*timer)(pico_time, void *), void *arg -#define PICO_STRING_TO_IPV4_SIG const char *ipstr, uint32_t *ip -#define PICO_STRING_TO_IPV6_SIG const char *ipstr, uint8_t *ip -#define PICO_SOCKET_SETOPTION_SIG struct pico_socket *s, int option, void *value -#define PICO_SOCKET_SEND_SIG struct pico_socket *s, const void *buf, int len -#define PICO_SOCKET_SENDTO_SIG struct pico_socket *s, const void *buf, int len, void *dst, uint16_t remote_port -#define PICO_SOCKET_RECV_SIG struct pico_socket *s, void *buf, int len -#define PICO_SOCKET_RECVFROM_SIG struct pico_socket *s, void *buf, int len, void *orig, uint16_t *remote_port -#define PICO_SOCKET_OPEN_SIG uint16_t net, uint16_t proto, void (*wakeup)(uint16_t ev, struct pico_socket *s) -#define PICO_SOCKET_BIND_SIG struct pico_socket *s, void *local_addr, uint16_t *port -#define PICO_SOCKET_CONNECT_SIG struct pico_socket *s, const void *srv_addr, uint16_t remote_port -#define PICO_SOCKET_LISTEN_SIG struct pico_socket *s, const int backlog -#define PICO_SOCKET_READ_SIG struct pico_socket *s, void *buf, int len -#define PICO_SOCKET_WRITE_SIG struct pico_socket *s, const void *buf, int len -#define PICO_SOCKET_CLOSE_SIG struct pico_socket *s -#define PICO_SOCKET_SHUTDOWN_SIG struct pico_socket *s, int mode -#define PICO_SOCKET_ACCEPT_SIG struct pico_socket *s, void *orig, uint16_t *port -#define PICO_IPV6_LINK_ADD_SIG struct pico_device *dev, struct pico_ip6 address, struct pico_ip6 netmask -#define PICO_IPV4_ROUTE_ADD_SIG struct pico_ip4 address, struct pico_ip4 netmask, struct pico_ip4 gateway, int metric, struct pico_ipv4_link *link -#define PICO_IPV4_ROUTE_DEL_SIG struct pico_ip4 address, struct pico_ip4 netmask, int metric -#define PICO_IPV6_ROUTE_ADD_SIG struct pico_ip6 address, struct pico_ip6 netmask, struct pico_ip6 gateway, int metric, struct pico_ipv6_link *link -#define PICO_IPV6_ROUTE_DEL_SIG struct pico_ip6 address, struct pico_ip6 netmask, struct pico_ip6 gateway, int metric, struct pico_ipv6_link *link -#define PICO_DNS_CLIENT_NAMESERVER_SIG pico_ip4*, unsigned char - -namespace ZeroTier -{ - /** - * Send raw frames from the stack to the ZeroTier virtual wire - */ - int pico_eth_tx(struct pico_device *dev, void *buf, int len); - - /** - * Read raw frames from RX frame buffer into the stack - */ - int pico_eth_poll(struct pico_device *dev, int loop_score); - - class VirtualTap; - class VirtualSocket; - - /** - * picoTCP network stack driver class - */ - class picoTCP - { - public: - - /** - * Set up an interface in the network stack for the VirtualTap - */ - bool pico_init_interface(ZeroTier::VirtualTap *tap); - - /** - * Register an address with the stack - */ - bool pico_register_address(VirtualTap *tap, const InetAddress &ip); - - /** - * Adds a route to the picoTCP device - */ - bool pico_route_add(VirtualTap *tap, const InetAddress &addr, const InetAddress &nm, const InetAddress &gw, int metric); - - /** - * Deletes a route from the picoTCP device - */ - bool pico_route_del(VirtualTap *tap, const InetAddress &addr, const InetAddress &nm, int metric); - - /** - * Registers a DNS nameserver with the network stack - */ - int pico_add_dns_nameserver(struct sockaddr *addr); - - /** - * Un-registers a DNS nameserver from the network stack - */ - int pico_del_dns_nameserver(struct sockaddr *addr); - - /** - * Main stack loop - */ - void pico_loop(VirtualTap *tap); - - /** - * Read bytes from the stack to the RX buffer (prepare to be read by app) - */ - static void pico_cb_tcp_read(VirtualTap *tap, struct pico_socket *s); - - /** - * Read bytes from the stack to the RX buffer (prepare to be read by app) - */ - static void pico_cb_udp_read(VirtualTap *tap, struct pico_socket *s); - - /** - * Write bytes from TX buffer to stack (prepare to be sent to ZT virtual wire) - */ - static void pico_cb_tcp_write(VirtualTap *tap, struct pico_socket *s); - - /** - * Write bytes from TX buffer to stack (prepare to be sent to ZT virtual wire) - */ - static void pico_cb_socket_ev(uint16_t ev, struct pico_socket *s); - - /** - * Packets from the ZeroTier virtual wire enter the stack here - */ - void pico_eth_rx(VirtualTap *tap, const ZeroTier::MAC &from, const ZeroTier::MAC &to, - unsigned int etherType, const void *data, unsigned int len); - - /** - * Creates a stack-specific "socket" or "VirtualSocket object" - */ - int pico_Socket(struct pico_socket **p, int socket_family, int socket_type, int protocol); - - /** - * Connect to remote host via userspace network stack interface - Called from VirtualTap - */ - int pico_Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen); - - /** - * Bind to a userspace network stack interface - Called from VirtualTap - */ - int pico_Bind(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen); - - /** - * Listen for incoming VirtualSockets - Called from VirtualTap - */ - int pico_Listen(VirtualSocket *vs, int backlog); - - /** - * Accept an incoming VirtualSocket - Called from VirtualTap - */ - VirtualSocket* pico_Accept(VirtualSocket *vs); - - /** - * Read from RX buffer to application - Called from VirtualTap - */ - int pico_Read(VirtualTap *tap, ZeroTier::PhySocket *sock, VirtualSocket *vs, bool stack_invoked); - - /** - * Write to userspace network stack - Called from VirtualTap - */ - int pico_Write(VirtualSocket *vs, void *data, ssize_t len); - - /** - * Close a VirtualSocket - Called from VirtualTap - */ - int pico_Close(VirtualSocket *vs); - - /** - * Shuts down some aspect of a VirtualSocket - Called from VirtualTap - */ - int pico_Shutdown(VirtualSocket *vs, int how); - - /** - * Sets a property of a socket - */ - static int pico_setsockopt(VirtualSocket *vs, int level, int optname, const void *optval, socklen_t optlen); - - /** - * Gets a property of a socket - */ - static int pico_getsockopt(VirtualSocket *vs, int level, int optname, void *optval, socklen_t *optlen); - - /** - * Converts a pico_err to its most closely-related errno, and sets errno - */ - static int map_pico_err_to_errno(int err); - - /** - * Converts picoTCP error codes to pretty string - */ - static char *beautify_pico_error(int err); - - /** - * Converts picoTCP socket states into pretty string - */ - static char *beautify_pico_state(int state); - }; -} - -#endif diff --git a/test/selftest.cpp b/test/selftest.cpp index ccbc1fd..8f59418 100644 --- a/test/selftest.cpp +++ b/test/selftest.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include "libzt.h" @@ -1755,10 +1756,10 @@ int slam_api_test() fds[i] = -1; } } - if (zts_num_active_virt_sockets() == 0) - std::cout << "PASSED [slam open and close]" << std::endl; - else - std::cout << "FAILED [slam open and close] - sockets left unclosed" << std::endl; + //if (zts_num_active_virt_sockets() == 0) + // std::cout << "PASSED [slam open and close]" << std::endl; + //else + // std::cout << "FAILED [slam open and close] - sockets left unclosed" << std::endl; } // --- @@ -1827,17 +1828,17 @@ int slam_api_test() } } used_ports.clear(); - if (zts_num_active_virt_sockets() == 0) - std::cout << "PASSED [slam open, bind, listen, accept, close]" << std::endl; - else - std::cout << "FAILED [slam open, bind, listen, accept, close]" << std::endl; + //if (zts_num_active_virt_sockets() == 0) + // std::cout << "PASSED [slam open, bind, listen, accept, close]" << std::endl; + //else + // std::cout << "FAILED [slam open, bind, listen, accept, close]" << std::endl; } // TESTS: // (1) socket() // (2) connect() // (3) close() - int num_times = zts_maxsockets(SOCK_STREAM); + int num_times = 3;//zts_maxsockets(SOCK_STREAM); std::cout << "socket/connect/close - " << num_times << " times" << std::endl; for (int i=0;i<(SLAM_NUMBER*SLAM_REPEAT); i++) { results[i] = 0; } if (true) @@ -1893,15 +1894,15 @@ int slam_api_test() } displayResults(results, num_times); - if (zts_num_active_virt_sockets() == 0) - std::cout << "PASSED [slam open, connect, close]" << std::endl; - else - std::cout << "FAILED [slam open, connect, close]" << std::endl; + //if (zts_num_active_virt_sockets() == 0) + // std::cout << "PASSED [slam open, connect, close]" << std::endl; + //else + // std::cout << "FAILED [slam open, connect, close]" << std::endl; } return 0; } - +/* void get_network_routes(char *nwid) { // Retreive managed routes for a given ZeroTier network @@ -1919,6 +1920,7 @@ void get_network_routes(char *nwid) DEBUG_TEST("", target_str, via_str, routes->at(i).flags); } } +*/ /****************************************************************************/ /* RANDOMIZED API TEST */ @@ -2534,9 +2536,10 @@ for (int i=0; i