diff --git a/Makefile b/Makefile index f452b0a..97f6d45 100644 --- a/Makefile +++ b/Makefile @@ -4,12 +4,131 @@ ifndef PDIR endif -AR = xt-ar -CC = xt-xcc -NM = xt-nm -CPP = xt-cpp -OBJCOPY = xt-objcopy -#MAKE = xt-make +ifeq ($(COMPILE), gcc) + AR = xtensa-lx106-elf-ar + CC = xtensa-lx106-elf-gcc + NM = xtensa-lx106-elf-nm + CPP = xtensa-lx106-elf-cpp + OBJCOPY = xtensa-lx106-elf-objcopy + OBJDUMP = xtensa-lx106-elf-objdump +else + AR = xt-ar + CC = xt-xcc + NM = xt-nm + CPP = xt-cpp + OBJCOPY = xt-objcopy + OBJDUMP = xt-objdump +endif + +BOOT?=none +APP?=0 +SPI_SPEED?=40 +SPI_MODE?=QIO +SPI_SIZE?=512 + +ifeq ($(BOOT), new) + boot = new +else + ifeq ($(BOOT), old) + boot = old + else + boot = none + endif +endif + +ifeq ($(APP), 1) + app = 1 +else + ifeq ($(APP), 2) + app = 2 + else + app = 0 + endif +endif + +ifeq ($(SPI_SPEED), 26.7) + freqdiv = 1 +else + ifeq ($(SPI_SPEED), 20) + freqdiv = 2 + else + ifeq ($(SPI_SPEED), 80) + freqdiv = 15 + else + freqdiv = 0 + endif + endif +endif + + +ifeq ($(SPI_MODE), QOUT) + mode = 1 +else + ifeq ($(SPI_MODE), DIO) + mode = 2 + else + ifeq ($(SPI_MODE), DOUT) + mode = 3 + else + mode = 0 + endif + endif +endif + +# flash larger than 1024KB only use 1024KB to storage user1.bin and user2.bin +ifeq ($(SPI_SIZE), 256) + size = 1 + flash = 256 +else + ifeq ($(SPI_SIZE), 1024) + size = 2 + flash = 1024 + else + ifeq ($(SPI_SIZE), 2048) + size = 3 + flash = 1024 + else + ifeq ($(SPI_SIZE), 4096) + size = 4 + flash = 1024 + else + size = 0 + flash = 512 + endif + endif + endif +endif + +ifeq ($(flash), 512) + ifeq ($(app), 1) + addr = 0x01000 + else + ifeq ($(app), 2) + addr = 0x41000 + endif + endif +else + ifeq ($(flash), 1024) + ifeq ($(app), 1) + addr = 0x01000 + else + ifeq ($(app), 2) + addr = 0x81000 + endif + endif + endif +endif + +LD_FILE = $(LDDIR)/eagle.app.v6.ld + +ifneq ($(boot), none) +ifneq ($(app),0) + LD_FILE = $(LDDIR)/eagle.app.v6.$(boot).$(flash).app$(app).ld + BIN_NAME = user$(app).$(flash).$(boot) +endif +else + app = 0 +endif CSRCS ?= $(wildcard *.c) ASRCs ?= $(wildcard *.s) @@ -82,7 +201,51 @@ endef $(BINODIR)/%.bin: $(IMAGEODIR)/%.out @mkdir -p $(BINODIR) - $(OBJCOPY) -O binary $< $@ + +ifeq ($(APP), 0) + @$(RM) -r ../bin/eagle.S ../bin/eagle.dump + @$(OBJDUMP) -x -s $< > ../bin/eagle.dump + @$(OBJDUMP) -S $< > ../bin/eagle.S +else + @$(RM) -r ../bin/upgrade/$(BIN_NAME).S ../bin/upgrade/$(BIN_NAME).dump + @$(OBJDUMP) -x -s $< > ../bin/upgrade/$(BIN_NAME).dump + @$(OBJDUMP) -S $< > ../bin/upgrade/$(BIN_NAME).S +endif + + @$(OBJCOPY) --only-section .text -O binary $< eagle.app.v6.text.bin + @$(OBJCOPY) --only-section .data -O binary $< eagle.app.v6.data.bin + @$(OBJCOPY) --only-section .rodata -O binary $< eagle.app.v6.rodata.bin + @$(OBJCOPY) --only-section .irom0.text -O binary $< eagle.app.v6.irom0text.bin + + @echo "" + @echo "!!!" + +ifeq ($(app), 0) + @python ../tools/gen_appbin.py $< 0 $(mode) $(freqdiv) $(size) + @mv eagle.app.flash.bin ../bin/eagle.flash.bin + @mv eagle.app.v6.irom0text.bin ../bin/eagle.irom0text.bin + @rm eagle.app.v6.* + @echo "No boot needed." + @echo "Generate eagle.flash.bin and eagle.irom0text.bin successully in folder bin." + @echo "eagle.flash.bin-------->0x00000" + @echo "eagle.irom0text.bin---->0x40000" +else + ifeq ($(boot), new) + @python ../tools/gen_appbin.py $< 2 $(mode) $(freqdiv) $(size) + @echo "Support boot_v1.2 and +" + else + @python ../tools/gen_appbin.py $< 1 $(mode) $(freqdiv) $(size) + @echo "Support boot_v1.1 and +" + endif + + @mv eagle.app.flash.bin ../bin/upgrade/$(BIN_NAME).bin + @rm eagle.app.v6.* + @echo "Generate $(BIN_NAME).bin successully in folder bin/upgrade." + @echo "boot.bin------------>0x00000" + @echo "$(BIN_NAME).bin--->$(addr)" +endif + + @echo "!!!" ############################################################# # Rules base diff --git a/app/Makefile b/app/Makefile index 11be1da..9a1d133 100644 --- a/app/Makefile +++ b/app/Makefile @@ -45,16 +45,6 @@ ifeq ($(FLAVOR),release) TARGET_LDFLAGS += -g -O0 endif -LD_FILE = $(LDDIR)/eagle.app.v6.ld - -ifeq ($(APP), 1) - LD_FILE = $(LDDIR)/eagle.app.v6.app1.ld -endif - -ifeq ($(APP), 2) - LD_FILE = $(LDDIR)/eagle.app.v6.app2.ld -endif - COMPONENTS_eagle.app.v6 = \ user/libuser.a @@ -124,15 +114,6 @@ INCLUDES := $(INCLUDES) -I $(PDIR)include PDIR := ../$(PDIR) sinclude $(PDIR)Makefile -######################################################################### -# -# generate bin file -# - -$(BINODIR)/%.bin: $(IMAGEODIR)/%.out - @mkdir -p $(BINODIR) - $(OBJCOPY) -O binary $< $@ - .PHONY: FORCE FORCE: diff --git a/app/gen_misc.bat b/app/gen_misc.bat index e65b693..216a3c8 100644 --- a/app/gen_misc.bat +++ b/app/gen_misc.bat @@ -1,27 +1,121 @@ @echo off -set BACKPATH=%PATH% -set PATH=%BACKPATH%;%CD%\..\tools -@echo on -del /F ..\bin\eagle.app.v6.flash.bin ..\bin\eagle.app.v6.irom0text.bin ..\bin\eagle.app.v6.dump ..\bin\eagle.app.v6.S +echo Please follow below steps(1-5) to generate specific bin(s): +echo STEP 1: choose boot version(0=boot_v1.1, 1=boot_v1.2+, 2=none) +set input=default +set /p input=enter(0/1/2, default 2): -cd .output\eagle\debug\image +if %input% equ 0 ( + set boot=old +) else ( +if %input% equ 1 ( + set boot=new +) else ( + set boot=none +) +) -xt-objdump -x -s eagle.app.v6.out > ..\..\..\..\..\bin\eagle.app.v6.dump -xt-objdump -S eagle.app.v6.out > ..\..\..\..\..\bin\eagle.app.v6.S +echo boot mode: %boot% +echo. -xt-objcopy --only-section .text -O binary eagle.app.v6.out eagle.app.v6.text.bin -xt-objcopy --only-section .data -O binary eagle.app.v6.out eagle.app.v6.data.bin -xt-objcopy --only-section .rodata -O binary eagle.app.v6.out eagle.app.v6.rodata.bin -xt-objcopy --only-section .irom0.text -O binary eagle.app.v6.out eagle.app.v6.irom0text.bin +echo STEP 2: choose bin generate(0=eagle.flash.bin+eagle.irom0text.bin, 1=user1.bin, 2=user2.bin) +set input=default +set /p input=enter (0/1/2, default 0): -gen_appbin.py eagle.app.v6.out v6 +if %input% equ 1 ( + if %boot% equ none ( + set app=0 + echo choose no boot before + echo generate bin: eagle.flash.bin+eagle.irom0text.bin + ) else ( + set app=1 + echo generate bin: user1.bin + ) +) else ( +if %input% equ 2 ( + if %boot% equ none ( + set app=0 + echo choose no boot before + echo generate bin: eagle.flash.bin+eagle.irom0text.bin + ) else ( + set app=2 + echo generate bin: user2.bin + ) +) else ( + if %boot% neq none ( + set boot=none + echo ignore boot + ) + set app=0 + echo generate bin: eagle.flash.bin+eagle.irom0text.bin +)) -xcopy /y eagle.app.v6.irom0text.bin ..\..\..\..\..\bin\ -xcopy /y eagle.app.v6.flash.bin ..\..\..\..\..\bin\ +echo. -cd ..\..\..\..\ +echo STEP 3: choose spi speed(0=20MHz, 1=26.7MHz, 2=40MHz, 3=80MHz) +set input=default +set /p input=enter (0/1/2/3, default 2): + +if %input% equ 0 ( + set spi_speed=20 +) else ( +if %input% equ 1 ( + set spi_speed=26.7 +) else ( +if %input% equ 3 ( + set spi_speed=80 +) else ( + set spi_speed=40 +))) + +echo spi speed: %spi_speed% MHz +echo. + +echo STEP 4: choose spi mode(0=QIO, 1=QOUT, 2=DIO, 3=DOUT) +set input=default +set /p input=enter (0/1/2/3, default 0): + +if %input% equ 1 ( + set spi_mode=QOUT +) else ( +if %input% equ 2 ( + set spi_mode=DIO +) else ( +if %input% equ 3 ( + set spi_mode=DOUT +) else ( + set spi_mode=QIO +))) + +echo spi mode: %spi_mode% +echo. + +echo STEP 5: choose spi size(0=256KB, 1=512KB, 2=1024KB, 3=2048KB, 4=4096KB) +set input=default +set /p input=enter (0/1/2/3/4, default 1): + +if %input% equ 0 ( + set spi_size=256 +) else ( +if %input% equ 2 ( + set spi_size=1024 +) else ( +if %input% equ 3 ( + set spi_size=2048 +) else ( +if %input% equ 4 ( + set spi_size=4096 +) else ( + set spi_size=512 +)))) + +echo spi size: %spi_size% KB + +touch user/user_main.c + +echo. +echo start... +echo. + +make BOOT=%boot% APP=%app% SPI_SPEED=%spi_speed% SPI_MODE=%spi_mode% SPI_SIZE=%spi_size% -@echo off -set PATH=%BACKPATH% -@echo on diff --git a/app/gen_misc.sh b/app/gen_misc.sh index eeada23..017dad0 100644 --- a/app/gen_misc.sh +++ b/app/gen_misc.sh @@ -1,25 +1,126 @@ -#!/bin/bash -x -make -if [ $? == 0 ];then -rm ../bin/eagle.app.v6.flash.bin ../bin/eagle.app.v6.irom0text.bin ../bin/eagle.app.v6.dump ../bin/eagle.app.v6.S +#!/bin/bash -cd .output/eagle/debug/image +echo "Please follow below steps(1-5) to generate specific bin(s):" +echo "STEP 1: choose boot version(0=boot_v1.1, 1=boot_v1.2+, 2=none)" +echo "enter(0/1/2, default 2):" +read input -xt-objdump -x -s eagle.app.v6.out > ../../../../../bin/eagle.app.v6.dump -xt-objdump -S eagle.app.v6.out > ../../../../../bin/eagle.app.v6.S +if [ -z "$input" ]; then + boot=none +elif [ $input == 0 ]; then + boot=old +elif [ $input == 1 ]; then + boot=new +else + boot=none +fi + +echo "boot mode: $boot" +echo "" + +echo "STEP 2: choose bin generate(0=eagle.flash.bin+eagle.irom0text.bin, 1=user1.bin, 2=user2.bin)" +echo "enter (0/1/2, default 0):" +read input + +if [ -z "$input" ]; then + if [ $boot != none ]; then + boot=none + echo "ignore boot" + fi + app=0 + echo "generate bin: eagle.flash.bin+eagle.irom0text.bin" +elif [ $input == 1 ]; then + if [ $boot == none ]; then + app=0 + echo "choose no boot before" + echo "generate bin: eagle.flash.bin+eagle.irom0text.bin" + else + app=1 + echo "generate bin: user1.bin" + fi +elif [ $input == 2 ]; then + if [ $boot == none ]; then + app=0 + echo "choose no boot before" + echo "generate bin: eagle.flash.bin+eagle.irom0text.bin" + else + app=2 + echo "generate bin: user2.bin" + fi +else + if [ $boot != none ]; then + boot=none + echo "ignore boot" + fi + app=0 + echo "generate bin: eagle.flash.bin+eagle.irom0text.bin" +fi + +echo "" -xt-objcopy --only-section .text -O binary eagle.app.v6.out eagle.app.v6.text.bin -xt-objcopy --only-section .data -O binary eagle.app.v6.out eagle.app.v6.data.bin -xt-objcopy --only-section .rodata -O binary eagle.app.v6.out eagle.app.v6.rodata.bin -xt-objcopy --only-section .irom0.text -O binary eagle.app.v6.out eagle.app.v6.irom0text.bin +echo "STEP 3: choose spi speed(0=20MHz, 1=26.7MHz, 2=40MHz, 3=80MHz)" +echo "enter (0/1/2/3, default 2):" +read input -../../../../../tools/gen_appbin.py eagle.app.v6.out v6 +if [ -z "$input" ]; then + spi_speed=40 +elif [ $input == 0 ]; then + spi_speed=20 +elif [ $input == 1 ]; then + spi_speed=26.7 +elif [ $input == 3 ]; then + spi_speed=80 +else + spi_speed=40 +fi -cp eagle.app.v6.irom0text.bin ../../../../../bin/ -cp eagle.app.v6.flash.bin ../../../../../bin/ +echo "spi speed: $spi_speed MHz" +echo "" -cd ../../../../../ +echo "STEP 4: choose spi mode(0=QIO, 1=QOUT, 2=DIO, 3=DOUT)" +echo "enter (0/1/2/3, default 0):" +read input +if [ -z "$input" ]; then + spi_mode=QIO +elif [ $input == 1 ]; then + spi_mode=QOUT +elif [ $input == 2 ]; then + spi_mode=DIO +elif [ $input == 3 ]; then + spi_mode=DOUT else -echo "make error" + spi_mode=QIO fi + +echo "spi mode: $spi_mode" +echo "" + +echo "STEP 5: choose spi size(0=256KB, 1=512KB, 2=1024KB, 3=2048KB, 4=4096KB)" +echo "enter (0/1/2/3/4, default 1):" +read input + +if [ -z "$input" ]; then + spi_size=512 +elif [ $input == 0 ]; then + spi_size=256 +elif [ $input == 2 ]; then + spi_size=1024 +elif [ $input == 3 ]; then + spi_size=2048 +elif [ $input == 4 ]; then + spi_size=4096 +else + spi_size=512 +fi + +echo "spi size: $spi_size KB" +echo "" + +touch user/user_main.c + +echo "" +echo "start..." +echo "" + +make COMPILE=gcc BOOT=$boot APP=$app SPI_SPEED=$spi_speed SPI_MODE=$spi_mode SPI_SIZE=$spi_size diff --git a/app/gen_misc_plus.bat b/app/gen_misc_plus.bat deleted file mode 100644 index 8022305..0000000 --- a/app/gen_misc_plus.bat +++ /dev/null @@ -1,27 +0,0 @@ -@echo off -set BACKPATH=%PATH% -set PATH=%BACKPATH%;%CD%\..\tools -@echo on - -rm ..\bin\upgrade\%1.bin - -cd .output\eagle\debug\image\ - -xt-objcopy --only-section .text -O binary eagle.app.v6.out eagle.app.v6.text.bin -xt-objcopy --only-section .data -O binary eagle.app.v6.out eagle.app.v6.data.bin -xt-objcopy --only-section .rodata -O binary eagle.app.v6.out eagle.app.v6.rodata.bin -xt-objcopy --only-section .irom0.text -O binary eagle.app.v6.out eagle.app.v6.irom0text.bin - -gen_appbin.py eagle.app.v6.out v6 - -gen_flashbin.py eagle.app.v6.flash.bin eagle.app.v6.irom0text.bin - -cp eagle.app.flash.bin %1.bin - -xcopy /y %1.bin ..\..\..\..\..\bin\upgrade\ - -cd ..\..\..\..\ - -@echo off -set PATH=%BACKPATH% -@echo on \ No newline at end of file diff --git a/app/gen_misc_plus.sh b/app/gen_misc_plus.sh deleted file mode 100644 index dba8a5b..0000000 --- a/app/gen_misc_plus.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -x -make APP=$1 -if [ $? == 0 ];then -rm ../bin/upgrade/user$1.bin - -cd .output/eagle/debug/image/ - -xt-objcopy --only-section .text -O binary eagle.app.v6.out eagle.app.v6.text.bin -xt-objcopy --only-section .data -O binary eagle.app.v6.out eagle.app.v6.data.bin -xt-objcopy --only-section .rodata -O binary eagle.app.v6.out eagle.app.v6.rodata.bin -xt-objcopy --only-section .irom0.text -O binary eagle.app.v6.out eagle.app.v6.irom0text.bin - -../../../../../tools/gen_appbin.py eagle.app.v6.out v6 - -../../../../../tools/gen_flashbin.py eagle.app.v6.flash.bin eagle.app.v6.irom0text.bin - -cp eagle.app.flash.bin user$1.bin -cp user$1.bin ../../../../../bin/upgrade/ - -cd ../../../../../ - -else -echo "make error" -fi \ No newline at end of file diff --git a/app/readme.txt b/app/readme.txt new file mode 100644 index 0000000..3e243ed --- /dev/null +++ b/app/readme.txt @@ -0,0 +1,40 @@ +1ˇ˘compile options + +(1) COMPILE + Possible value: gcc + Default value: + If not set, use xt-xcc by default. + +(2) BOOT + Possible value: none/old/new + none: no need boot + old: use boot_v1.1 + new: use boot_v1.2 + Default value: none + +(3) APP + Possible value: 0/1/2 + 0: original mode, generate eagle.app.v6.flash.bin and eagle.app.v6.irom0text.bin + 1: generate user1 + 2: generate user2 + Default value: 0 + +(3) SPI_SPEED + Possible value: 20/26.7/40/80 + Default value: 40 + +(4) SPI_MODE + Possible value: QIO/QOUT/DIO/DOUT + Default value: QIO + +(4) SPI_SIZE + Possible value: 256/512/1024/2048/4096 + Default value: 512 + +For example: + make COMPILE=gcc BOOT=new APP=1 SPI_SPEED=40 SPI_MODE=QIO SPI_SIZE=512 + +2ˇ˘You can also use gen_misc to make and generate specific bin you needed. + Linux: ./gen_misc.sh + Windows: gen_misc.bat + Follow the tips and steps. \ No newline at end of file diff --git a/app/user/user_main.c b/app/user/user_main.c index 6f46a8b..88de521 100644 --- a/app/user/user_main.c +++ b/app/user/user_main.c @@ -152,10 +152,7 @@ void task3(void *pvParameters) void ICACHE_FLASH_ATTR user_init(void) { - printf("SDK version:%d.%d.%d\n", - SDK_VERSION_MAJOR, - SDK_VERSION_MINOR, - SDK_VERSION_REVISION); + printf("SDK version:%s\n", system_get_sdk_version()); /* need to set opmode before you set config */ wifi_set_opmode(STATIONAP_MODE); diff --git a/bin/boot_v1.3(b3).bin b/bin/boot_v1.3(b3).bin new file mode 100644 index 0000000..c2d7027 Binary files /dev/null and b/bin/boot_v1.3(b3).bin differ diff --git a/bin/esp_init_data_default.bin b/bin/esp_init_data_default.bin new file mode 100644 index 0000000..2936c7b Binary files /dev/null and b/bin/esp_init_data_default.bin differ diff --git a/include/espressif/c_types.h b/include/espressif/c_types.h index 902fb9b..ab788cc 100644 --- a/include/espressif/c_types.h +++ b/include/espressif/c_types.h @@ -74,6 +74,7 @@ typedef enum { #ifdef ICACHE_FLASH #define ICACHE_FLASH_ATTR __attribute__((section(".irom0.text"))) +#define ICACHE_RODATA_ATTR __attribute__((section(".irom.text"))) #else #define ICACHE_FLASH_ATTR #endif /* ICACHE_FLASH */ diff --git a/include/espressif/esp_common.h b/include/espressif/esp_common.h index dfb111e..266166f 100644 --- a/include/espressif/esp_common.h +++ b/include/espressif/esp_common.h @@ -9,15 +9,13 @@ #include "c_types.h" #include "esp_libc.h" #include "esp_misc.h" +#include "esp_wifi.h" #include "esp_softap.h" #include "esp_sta.h" #include "esp_system.h" #include "esp_timer.h" -#include "esp_wifi.h" #include "esp8266/esp8266.h" #include "spi_flash.h" - -#include "version.h" #endif diff --git a/include/espressif/esp_libc.h b/include/espressif/esp_libc.h index 1c2f05c..963fec5 100644 --- a/include/espressif/esp_libc.h +++ b/include/espressif/esp_libc.h @@ -49,4 +49,16 @@ void *realloc(void *p, size_t n); int atoi(const char *s); long atol(const char *s); +/* NOTE: don't use printf_opt in irq handler, for test */ +#define printf_opt(fmt, ...) do { \ + static const char flash_str[] ICACHE_RODATA_ATTR = fmt; \ + printf(flash_str, ##__VA_ARGS__); \ + } while(0) + +/* NOTE: don't use printf_opt in irq handler, for test */ +#define sprintf_opt(out, fmt, ...) do { \ + static const char flash_str[] ICACHE_RODATA_ATTR = fmt; \ + sprintf(out, flash_str, ##__VA_ARGS__); \ + } while(0) + #endif /* __LIBC_H__ */ diff --git a/include/espressif/esp_softap.h b/include/espressif/esp_softap.h index 6330141..4d3a434 100644 --- a/include/espressif/esp_softap.h +++ b/include/espressif/esp_softap.h @@ -6,22 +6,15 @@ #ifndef __ESP_SOFTAP_H__ #define __ESP_SOFTAP_H__ -typedef enum _auth_mode { - AUTH_OPEN = 0, - AUTH_WEP, - AUTH_WPA_PSK, - AUTH_WPA2_PSK, - AUTH_WPA_WPA2_PSK -} AUTH_MODE; - struct softap_config { uint8 ssid[32]; uint8 password[64]; uint8 ssid_len; uint8 channel; - uint8 authmode; + AUTH_MODE authmode; uint8 ssid_hidden; uint8 max_connection; + uint16 beacon_interval; }; bool wifi_softap_get_config(struct softap_config *config); diff --git a/include/espressif/esp_sta.h b/include/espressif/esp_sta.h index b4351b9..06ea288 100644 --- a/include/espressif/esp_sta.h +++ b/include/espressif/esp_sta.h @@ -35,7 +35,7 @@ struct bss_info { uint8 ssid[32]; uint8 channel; sint8 rssi; - uint8 authmode; + AUTH_MODE authmode; uint8 is_hidden; }; diff --git a/include/espressif/esp_system.h b/include/espressif/esp_system.h index cf3f830..7e897d6 100644 --- a/include/espressif/esp_system.h +++ b/include/espressif/esp_system.h @@ -9,21 +9,27 @@ #include "c_types.h" enum rst_reason { - DEFAULT_RST_FLAG = 0, - WDT_RST_FLAG = 1, - EXP_RST_FLAG = 2 + DEFAULT_RST = 0, + WDT_RST = 1, + EXCEPTION_RST = 2, + SOFT_RST = 3 }; struct rst_info{ - uint32 flag; + uint32 reason; uint32 exccause; uint32 epc1; uint32 epc2; uint32 epc3; uint32 excvaddr; uint32 depc; + uint32 rtn_addr; }; +struct rst_info* system_get_rst_info(void); + +const char* system_get_sdk_version(void); + void system_restore(void); void system_restart(void); void system_deep_sleep(uint32 time_in_us); diff --git a/include/espressif/esp_wifi.h b/include/espressif/esp_wifi.h index 70614f2..a959e88 100644 --- a/include/espressif/esp_wifi.h +++ b/include/espressif/esp_wifi.h @@ -14,6 +14,15 @@ enum { MAX_MODE }; +typedef enum _auth_mode { + AUTH_OPEN = 0, + AUTH_WEP, + AUTH_WPA_PSK, + AUTH_WPA2_PSK, + AUTH_WPA_WPA2_PSK, + AUTH_MAX +} AUTH_MODE; + uint8 wifi_get_opmode(void); bool wifi_set_opmode(uint8 opmode); diff --git a/include/espressif/spi_flash.h b/include/espressif/spi_flash.h index 14890e1..0bb2edd 100644 --- a/include/espressif/spi_flash.h +++ b/include/espressif/spi_flash.h @@ -14,6 +14,9 @@ typedef enum { #define SPI_FLASH_SEC_SIZE 4096 +uint32 spi_flash_get_id(void); +SpiFlashOpResult spi_flash_read_status(uint32 *status); +SpiFlashOpResult spi_flash_write_status(uint32 status_value); SpiFlashOpResult spi_flash_erase_sector(uint16 sec); SpiFlashOpResult spi_flash_write(uint32 des_addr, uint32 *src_addr, uint32 size); SpiFlashOpResult spi_flash_read(uint32 src_addr, uint32 *des_addr, uint32 size); diff --git a/include/espressif/version.h b/include/espressif/version.h deleted file mode 100644 index 4d3540f..0000000 --- a/include/espressif/version.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __SDK_VERSION_H__ -#define __SDK_VERSION_H__ - -#define SDK_VERSION_MAJOR 0U -#define SDK_VERSION_MINOR 0U -#define SDK_VERSION_REVISION 5U -#define SDK_VERSION_INTERNAL 0U - -#define SDK_VERSION (SDK_VERSION_MAJOR << 16 | SDK_VERSION_MINOR << 8 | SDK_VERSION_REVISION) - -#endif - diff --git a/include/freertos/FreeRTOSConfig.h b/include/freertos/FreeRTOSConfig.h index 87164f0..5c22444 100644 --- a/include/freertos/FreeRTOSConfig.h +++ b/include/freertos/FreeRTOSConfig.h @@ -82,8 +82,8 @@ #define configUSE_TICK_HOOK 0 #define configCPU_CLOCK_HZ ( ( unsigned long ) 80000000 ) #define configTICK_RATE_HZ ( ( portTickType ) 100 ) -#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 21 ) -#define configMINIMAL_STACK_SIZE ( ( unsigned short )128 ) +#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 15 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short )156 ) //#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) ) #define configMAX_TASK_NAME_LEN ( 16 ) #define configUSE_TRACE_FACILITY 0 diff --git a/include/freertos/portmacro.h b/include/freertos/portmacro.h index 7d9da7f..93f4e1b 100644 --- a/include/freertos/portmacro.h +++ b/include/freertos/portmacro.h @@ -107,7 +107,6 @@ typedef unsigned int INT32U; /* Scheduler utilities. */ extern void PendSV(char req); -extern char ClosedLv1Isr; //#define portYIELD() vPortYield() #define portYIELD() PendSV(1) @@ -116,20 +115,29 @@ extern char ClosedLv1Isr; // if(xSwitchRequired) PendSV(1) #define HDL_MAC_SIG_IN_LV1_ISR() PendSV(2) + +/* Task utilities. */ +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ +{ \ +extern void vTaskSwitchContext( void ); \ + \ + if( xSwitchRequired ) \ + { \ + vTaskSwitchContext(); \ + } \ +} + + /*-----------------------------------------------------------*/ +extern unsigned cpu_sr; /* Critical section management. */ -extern void portDISABLE_INTERRUPTS( void ); -extern void portENABLE_INTERRUPTS( void ); extern void vPortEnterCritical( void ); extern void vPortExitCritical( void ); -extern unsigned cpu_sr; - -/* Don't modify these lines. This port requires OS_CRITICAL_METHOD 3. */ -#define OS_CRITICAL_METHOD 3 - -#if OS_CRITICAL_METHOD == 3 +//DYC_ISR_DBG +void PortDisableInt_NoNest( void ); +void PortEnableInt_NoNest( void ); /* Disable interrupts, saving previous state in cpu_sr */ #define portDISABLE_INTERRUPTS() \ @@ -137,32 +145,14 @@ extern unsigned cpu_sr; /* Restore interrupts to previous level saved in cpu_sr */ #define portENABLE_INTERRUPTS() __asm__ volatile ("wsr %0, ps" :: "a" (cpu_sr) : "memory") -#endif -//DYC_ISR_DBG -void ICACHE_FLASH_ATTR vPortEnterCritical1( void ); -void ICACHE_FLASH_ATTR vPortExitCritical1( void ); -#define portSET_INTERRUPT_MASK_FROM_ISR() vPortEnterCritical1() -#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortExitCritical1() - -//#define portDISABLE_INTERRUPTS() ets_intr_lock() -//#define portENABLE_INTERRUPTS() ets_intr_unlock() - -//#define portDISABLE_INTERRUPTS() -//#define portENABLE_INTERRUPTS() #define portENTER_CRITICAL() vPortEnterCritical() #define portEXIT_CRITICAL() vPortExitCritical() -/* Task utilities. */ -#define portEND_SWITCHING_ISR( xSwitchRequired ) \ -{ \ -extern void vTaskSwitchContext( void ); \ - \ - if( xSwitchRequired ) \ - { \ - vTaskSwitchContext(); \ - } \ -} +// no need to disable/enable lvl1 isr again in ISR +//#define portSET_INTERRUPT_MASK_FROM_ISR() PortDisableInt_NoNest() +//#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) PortEnableInt_NoNest() + /*-----------------------------------------------------------*/ diff --git a/include/lwip/lwip/api.h b/include/lwip/lwip/api.h index a8add39..b5d0a55 100644 --- a/include/lwip/lwip/api.h +++ b/include/lwip/lwip/api.h @@ -80,6 +80,9 @@ extern "C" { #define NETCONN_FLAG_IPV6_V6ONLY 0x20 #endif /* LWIP_IPV6 */ + //***********Code for WIFI_BLOCK from upper************** +#define NETCONN_FLAG_RECV_HOLD 0x80 + /* Helpers to process several netconn_types by the same code */ #define NETCONNTYPE_GROUP(t) ((t)&0xF0) @@ -208,6 +211,8 @@ struct netconn { /** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */ u8_t flags; #if LWIP_TCP + //***********Code for WIFI_BLOCK from upper************** + u32_t recv_holded_buf_Len; /** TCP: when data passed to netconn_write doesn't fit into the send buffer, this temporarily stores how much is already sent. */ size_t write_offset; diff --git a/include/lwip/lwipopts.h b/include/lwip/lwipopts.h index 0da8345..917668e 100644 --- a/include/lwip/lwipopts.h +++ b/include/lwip/lwipopts.h @@ -107,6 +107,34 @@ ---------- IP options ---------- -------------------------------- */ +/** + * 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 0 + +/** + * 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 /* ---------------------------------- @@ -182,7 +210,7 @@ * LWIP_CALLBACK_API==1: The PCB callback function is called directly * for the event. This is the default. */ -#define TCP_MSS 1024 +#define TCP_MSS 1460 /** * TCP_MAXRTX: Maximum number of retransmissions of data segments. @@ -246,7 +274,7 @@ * The priority value itself is platform-dependent, but is passed to * sys_thread_new() when the thread is created. */ -#define TCPIP_THREAD_PRIO (configMAX_PRIORITIES-4) +#define TCPIP_THREAD_PRIO (configMAX_PRIORITIES-5) /** * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages diff --git a/include/udhcp/common.h b/include/udhcp/common.h index 14caa1c..332cf76 100644 --- a/include/udhcp/common.h +++ b/include/udhcp/common.h @@ -388,7 +388,7 @@ void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC; #ifdef UDHCP_DBG #define UDHCP_DEBUG os_printf #else -#define UDHCP_DEBUG +#define UDHCP_DEBUG(...) #endif /*** Other shared functions ***/ diff --git a/ld/eagle.app.v6.app1.ld b/ld/eagle.app.v6.new.1024.app1.ld similarity index 75% rename from ld/eagle.app.v6.app1.ld rename to ld/eagle.app.v6.new.1024.app1.ld index 4b624b1..41514ba 100644 --- a/ld/eagle.app.v6.app1.ld +++ b/ld/eagle.app.v6.new.1024.app1.ld @@ -2,10 +2,10 @@ /* Linker Script for ld -N */ MEMORY { - dport0_0_seg : org = 0x3FF00000, len = 0x10 - dram0_0_seg : org = 0x3FFE8000, len = 0x14000 - iram1_0_seg : org = 0x40100000, len = 0x8000 - irom0_0_seg : org = 0x40211000, len = 0x2B000 + dport0_0_seg : org = 0x3FF00000, len = 0x10 + dram0_0_seg : org = 0x3FFE8000, len = 0x14000 + iram1_0_seg : org = 0x40100000, len = 0x8000 + irom0_0_seg : org = 0x40201010, len = 0x6B000 } PHDRS @@ -20,6 +20,11 @@ PHDRS /* Default entry point: */ ENTRY(call_user_start) +EXTERN(_DebugExceptionVector) +EXTERN(_DoubleExceptionVector) +EXTERN(_KernelExceptionVector) +EXTERN(_NMIExceptionVector) +EXTERN(_UserExceptionVector) PROVIDE(_memmap_vecbase_reset = 0x40000000); /* Various memory-map dependent cache attribute settings: */ _memmap_cacheattr_wb_base = 0x00000110; @@ -121,6 +126,13 @@ SECTIONS _rodata_end = ABSOLUTE(.); } >dram0_0_seg :dram0_0_phdr + .UserExceptionVector.literal : AT(LOADADDR(.rodata) + (ADDR(.UserExceptionVector.literal) - ADDR(.rodata))) ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + .bss ALIGN(8) (NOLOAD) : ALIGN(4) { . = ALIGN (8); @@ -149,6 +161,30 @@ SECTIONS { _stext = .; _text_start = ABSOLUTE(.); + *(.UserEnter.text) + . = ALIGN(16); + *(.DebugExceptionVector.text) + . = ALIGN(16); + *(.NMIExceptionVector.text) + . = ALIGN(16); + *(.KernelExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.UserExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.DoubleExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN (16); *(.entry.text) *(.init.literal) *(.init) diff --git a/ld/eagle.app.v6.new.1024.app2.ld b/ld/eagle.app.v6.new.1024.app2.ld new file mode 100644 index 0000000..b751653 --- /dev/null +++ b/ld/eagle.app.v6.new.1024.app2.ld @@ -0,0 +1,217 @@ +/* This linker script generated from xt-genldscripts.tpp for LSP . */ +/* Linker Script for ld -N */ +MEMORY +{ + dport0_0_seg : org = 0x3FF00000, len = 0x10 + dram0_0_seg : org = 0x3FFE8000, len = 0x14000 + iram1_0_seg : org = 0x40100000, len = 0x8000 + irom0_0_seg : org = 0x40281010, len = 0x6B000 +} + +PHDRS +{ + dport0_0_phdr PT_LOAD; + dram0_0_phdr PT_LOAD; + dram0_0_bss_phdr PT_LOAD; + iram1_0_phdr PT_LOAD; + irom0_0_phdr PT_LOAD; +} + + +/* Default entry point: */ +ENTRY(call_user_start) +EXTERN(_DebugExceptionVector) +EXTERN(_DoubleExceptionVector) +EXTERN(_KernelExceptionVector) +EXTERN(_NMIExceptionVector) +EXTERN(_UserExceptionVector) +PROVIDE(_memmap_vecbase_reset = 0x40000000); +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x00000110; +_memmap_cacheattr_wt_base = 0x00000110; +_memmap_cacheattr_bp_base = 0x00000220; +_memmap_cacheattr_unused_mask = 0xFFFFF00F; +_memmap_cacheattr_wb_trapnull = 0x2222211F; +_memmap_cacheattr_wba_trapnull = 0x2222211F; +_memmap_cacheattr_wbna_trapnull = 0x2222211F; +_memmap_cacheattr_wt_trapnull = 0x2222211F; +_memmap_cacheattr_bp_trapnull = 0x2222222F; +_memmap_cacheattr_wb_strict = 0xFFFFF11F; +_memmap_cacheattr_wt_strict = 0xFFFFF11F; +_memmap_cacheattr_bp_strict = 0xFFFFF22F; +_memmap_cacheattr_wb_allvalid = 0x22222112; +_memmap_cacheattr_wt_allvalid = 0x22222112; +_memmap_cacheattr_bp_allvalid = 0x22222222; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); + +SECTIONS +{ + + .dport0.rodata : ALIGN(4) + { + _dport0_rodata_start = ABSOLUTE(.); + *(.dport0.rodata) + *(.dport.rodata) + _dport0_rodata_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.literal : ALIGN(4) + { + _dport0_literal_start = ABSOLUTE(.); + *(.dport0.literal) + *(.dport.literal) + _dport0_literal_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.data : ALIGN(4) + { + _dport0_data_start = ABSOLUTE(.); + *(.dport0.data) + *(.dport.data) + _dport0_data_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + _data_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + *(.eh_frame) + /* C++ constructor and destructor tables, properly ordered: */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); /* this table MUST be 4-byte aligned */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .UserExceptionVector.literal : AT(LOADADDR(.rodata) + (ADDR(.UserExceptionVector.literal) - ADDR(.rodata))) ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .bss ALIGN(8) (NOLOAD) : ALIGN(4) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + _heap_start = ABSOLUTE(.); +/* _stack_sentry = ALIGN(0x8); */ + } >dram0_0_seg :dram0_0_bss_phdr +/* __stack = 0x3ffc8000; */ + + .text : ALIGN(4) + { + _stext = .; + _text_start = ABSOLUTE(.); + *(.UserEnter.text) + . = ALIGN(16); + *(.DebugExceptionVector.text) + . = ALIGN(16); + *(.NMIExceptionVector.text) + . = ALIGN(16); + *(.KernelExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.UserExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.DoubleExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + } >iram1_0_seg :iram1_0_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >iram1_0_seg :iram1_0_phdr + + .irom0.text : ALIGN(4) + { + _irom0_text_start = ABSOLUTE(.); + *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text) + _irom0_text_end = ABSOLUTE(.); + } >irom0_0_seg :irom0_0_phdr +} + +/* get ROM code address */ +INCLUDE "../ld/eagle.rom.addr.v6.ld" diff --git a/ld/eagle.app.v6.new.512.app1.ld b/ld/eagle.app.v6.new.512.app1.ld new file mode 100644 index 0000000..66e8c7b --- /dev/null +++ b/ld/eagle.app.v6.new.512.app1.ld @@ -0,0 +1,217 @@ +/* This linker script generated from xt-genldscripts.tpp for LSP . */ +/* Linker Script for ld -N */ +MEMORY +{ + dport0_0_seg : org = 0x3FF00000, len = 0x10 + dram0_0_seg : org = 0x3FFE8000, len = 0x14000 + iram1_0_seg : org = 0x40100000, len = 0x8000 + irom0_0_seg : org = 0x40201010, len = 0x2B000 +} + +PHDRS +{ + dport0_0_phdr PT_LOAD; + dram0_0_phdr PT_LOAD; + dram0_0_bss_phdr PT_LOAD; + iram1_0_phdr PT_LOAD; + irom0_0_phdr PT_LOAD; +} + + +/* Default entry point: */ +ENTRY(call_user_start) +EXTERN(_DebugExceptionVector) +EXTERN(_DoubleExceptionVector) +EXTERN(_KernelExceptionVector) +EXTERN(_NMIExceptionVector) +EXTERN(_UserExceptionVector) +PROVIDE(_memmap_vecbase_reset = 0x40000000); +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x00000110; +_memmap_cacheattr_wt_base = 0x00000110; +_memmap_cacheattr_bp_base = 0x00000220; +_memmap_cacheattr_unused_mask = 0xFFFFF00F; +_memmap_cacheattr_wb_trapnull = 0x2222211F; +_memmap_cacheattr_wba_trapnull = 0x2222211F; +_memmap_cacheattr_wbna_trapnull = 0x2222211F; +_memmap_cacheattr_wt_trapnull = 0x2222211F; +_memmap_cacheattr_bp_trapnull = 0x2222222F; +_memmap_cacheattr_wb_strict = 0xFFFFF11F; +_memmap_cacheattr_wt_strict = 0xFFFFF11F; +_memmap_cacheattr_bp_strict = 0xFFFFF22F; +_memmap_cacheattr_wb_allvalid = 0x22222112; +_memmap_cacheattr_wt_allvalid = 0x22222112; +_memmap_cacheattr_bp_allvalid = 0x22222222; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); + +SECTIONS +{ + + .dport0.rodata : ALIGN(4) + { + _dport0_rodata_start = ABSOLUTE(.); + *(.dport0.rodata) + *(.dport.rodata) + _dport0_rodata_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.literal : ALIGN(4) + { + _dport0_literal_start = ABSOLUTE(.); + *(.dport0.literal) + *(.dport.literal) + _dport0_literal_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.data : ALIGN(4) + { + _dport0_data_start = ABSOLUTE(.); + *(.dport0.data) + *(.dport.data) + _dport0_data_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + _data_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + *(.eh_frame) + /* C++ constructor and destructor tables, properly ordered: */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); /* this table MUST be 4-byte aligned */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .UserExceptionVector.literal : AT(LOADADDR(.rodata) + (ADDR(.UserExceptionVector.literal) - ADDR(.rodata))) ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .bss ALIGN(8) (NOLOAD) : ALIGN(4) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + _heap_start = ABSOLUTE(.); +/* _stack_sentry = ALIGN(0x8); */ + } >dram0_0_seg :dram0_0_bss_phdr +/* __stack = 0x3ffc8000; */ + + .text : ALIGN(4) + { + _stext = .; + _text_start = ABSOLUTE(.); + *(.UserEnter.text) + . = ALIGN(16); + *(.DebugExceptionVector.text) + . = ALIGN(16); + *(.NMIExceptionVector.text) + . = ALIGN(16); + *(.KernelExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.UserExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.DoubleExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + } >iram1_0_seg :iram1_0_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >iram1_0_seg :iram1_0_phdr + + .irom0.text : ALIGN(4) + { + _irom0_text_start = ABSOLUTE(.); + *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text) + _irom0_text_end = ABSOLUTE(.); + } >irom0_0_seg :irom0_0_phdr +} + +/* get ROM code address */ +INCLUDE "../ld/eagle.rom.addr.v6.ld" diff --git a/ld/eagle.app.v6.new.512.app2.ld b/ld/eagle.app.v6.new.512.app2.ld new file mode 100644 index 0000000..89773ac --- /dev/null +++ b/ld/eagle.app.v6.new.512.app2.ld @@ -0,0 +1,217 @@ +/* This linker script generated from xt-genldscripts.tpp for LSP . */ +/* Linker Script for ld -N */ +MEMORY +{ + dport0_0_seg : org = 0x3FF00000, len = 0x10 + dram0_0_seg : org = 0x3FFE8000, len = 0x14000 + iram1_0_seg : org = 0x40100000, len = 0x8000 + irom0_0_seg : org = 0x40241010, len = 0x2B000 +} + +PHDRS +{ + dport0_0_phdr PT_LOAD; + dram0_0_phdr PT_LOAD; + dram0_0_bss_phdr PT_LOAD; + iram1_0_phdr PT_LOAD; + irom0_0_phdr PT_LOAD; +} + + +/* Default entry point: */ +ENTRY(call_user_start) +EXTERN(_DebugExceptionVector) +EXTERN(_DoubleExceptionVector) +EXTERN(_KernelExceptionVector) +EXTERN(_NMIExceptionVector) +EXTERN(_UserExceptionVector) +PROVIDE(_memmap_vecbase_reset = 0x40000000); +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x00000110; +_memmap_cacheattr_wt_base = 0x00000110; +_memmap_cacheattr_bp_base = 0x00000220; +_memmap_cacheattr_unused_mask = 0xFFFFF00F; +_memmap_cacheattr_wb_trapnull = 0x2222211F; +_memmap_cacheattr_wba_trapnull = 0x2222211F; +_memmap_cacheattr_wbna_trapnull = 0x2222211F; +_memmap_cacheattr_wt_trapnull = 0x2222211F; +_memmap_cacheattr_bp_trapnull = 0x2222222F; +_memmap_cacheattr_wb_strict = 0xFFFFF11F; +_memmap_cacheattr_wt_strict = 0xFFFFF11F; +_memmap_cacheattr_bp_strict = 0xFFFFF22F; +_memmap_cacheattr_wb_allvalid = 0x22222112; +_memmap_cacheattr_wt_allvalid = 0x22222112; +_memmap_cacheattr_bp_allvalid = 0x22222222; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); + +SECTIONS +{ + + .dport0.rodata : ALIGN(4) + { + _dport0_rodata_start = ABSOLUTE(.); + *(.dport0.rodata) + *(.dport.rodata) + _dport0_rodata_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.literal : ALIGN(4) + { + _dport0_literal_start = ABSOLUTE(.); + *(.dport0.literal) + *(.dport.literal) + _dport0_literal_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.data : ALIGN(4) + { + _dport0_data_start = ABSOLUTE(.); + *(.dport0.data) + *(.dport.data) + _dport0_data_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + _data_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + *(.eh_frame) + /* C++ constructor and destructor tables, properly ordered: */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); /* this table MUST be 4-byte aligned */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .UserExceptionVector.literal : AT(LOADADDR(.rodata) + (ADDR(.UserExceptionVector.literal) - ADDR(.rodata))) ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .bss ALIGN(8) (NOLOAD) : ALIGN(4) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + _heap_start = ABSOLUTE(.); +/* _stack_sentry = ALIGN(0x8); */ + } >dram0_0_seg :dram0_0_bss_phdr +/* __stack = 0x3ffc8000; */ + + .text : ALIGN(4) + { + _stext = .; + _text_start = ABSOLUTE(.); + *(.UserEnter.text) + . = ALIGN(16); + *(.DebugExceptionVector.text) + . = ALIGN(16); + *(.NMIExceptionVector.text) + . = ALIGN(16); + *(.KernelExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.UserExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.DoubleExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + } >iram1_0_seg :iram1_0_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >iram1_0_seg :iram1_0_phdr + + .irom0.text : ALIGN(4) + { + _irom0_text_start = ABSOLUTE(.); + *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text) + _irom0_text_end = ABSOLUTE(.); + } >irom0_0_seg :irom0_0_phdr +} + +/* get ROM code address */ +INCLUDE "../ld/eagle.rom.addr.v6.ld" diff --git a/ld/eagle.app.v6.old.1024.app1.ld b/ld/eagle.app.v6.old.1024.app1.ld new file mode 100644 index 0000000..e17350e --- /dev/null +++ b/ld/eagle.app.v6.old.1024.app1.ld @@ -0,0 +1,217 @@ +/* This linker script generated from xt-genldscripts.tpp for LSP . */ +/* Linker Script for ld -N */ +MEMORY +{ + dport0_0_seg : org = 0x3FF00000, len = 0x10 + dram0_0_seg : org = 0x3FFE8000, len = 0x14000 + iram1_0_seg : org = 0x40100000, len = 0x8000 + irom0_0_seg : org = 0x40211000, len = 0x6B000 +} + +PHDRS +{ + dport0_0_phdr PT_LOAD; + dram0_0_phdr PT_LOAD; + dram0_0_bss_phdr PT_LOAD; + iram1_0_phdr PT_LOAD; + irom0_0_phdr PT_LOAD; +} + + +/* Default entry point: */ +ENTRY(call_user_start) +EXTERN(_DebugExceptionVector) +EXTERN(_DoubleExceptionVector) +EXTERN(_KernelExceptionVector) +EXTERN(_NMIExceptionVector) +EXTERN(_UserExceptionVector) +PROVIDE(_memmap_vecbase_reset = 0x40000000); +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x00000110; +_memmap_cacheattr_wt_base = 0x00000110; +_memmap_cacheattr_bp_base = 0x00000220; +_memmap_cacheattr_unused_mask = 0xFFFFF00F; +_memmap_cacheattr_wb_trapnull = 0x2222211F; +_memmap_cacheattr_wba_trapnull = 0x2222211F; +_memmap_cacheattr_wbna_trapnull = 0x2222211F; +_memmap_cacheattr_wt_trapnull = 0x2222211F; +_memmap_cacheattr_bp_trapnull = 0x2222222F; +_memmap_cacheattr_wb_strict = 0xFFFFF11F; +_memmap_cacheattr_wt_strict = 0xFFFFF11F; +_memmap_cacheattr_bp_strict = 0xFFFFF22F; +_memmap_cacheattr_wb_allvalid = 0x22222112; +_memmap_cacheattr_wt_allvalid = 0x22222112; +_memmap_cacheattr_bp_allvalid = 0x22222222; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); + +SECTIONS +{ + + .dport0.rodata : ALIGN(4) + { + _dport0_rodata_start = ABSOLUTE(.); + *(.dport0.rodata) + *(.dport.rodata) + _dport0_rodata_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.literal : ALIGN(4) + { + _dport0_literal_start = ABSOLUTE(.); + *(.dport0.literal) + *(.dport.literal) + _dport0_literal_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.data : ALIGN(4) + { + _dport0_data_start = ABSOLUTE(.); + *(.dport0.data) + *(.dport.data) + _dport0_data_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + _data_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + *(.eh_frame) + /* C++ constructor and destructor tables, properly ordered: */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); /* this table MUST be 4-byte aligned */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .UserExceptionVector.literal : AT(LOADADDR(.rodata) + (ADDR(.UserExceptionVector.literal) - ADDR(.rodata))) ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .bss ALIGN(8) (NOLOAD) : ALIGN(4) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + _heap_start = ABSOLUTE(.); +/* _stack_sentry = ALIGN(0x8); */ + } >dram0_0_seg :dram0_0_bss_phdr +/* __stack = 0x3ffc8000; */ + + .text : ALIGN(4) + { + _stext = .; + _text_start = ABSOLUTE(.); + *(.UserEnter.text) + . = ALIGN(16); + *(.DebugExceptionVector.text) + . = ALIGN(16); + *(.NMIExceptionVector.text) + . = ALIGN(16); + *(.KernelExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.UserExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.DoubleExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + } >iram1_0_seg :iram1_0_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >iram1_0_seg :iram1_0_phdr + + .irom0.text : ALIGN(4) + { + _irom0_text_start = ABSOLUTE(.); + *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text) + _irom0_text_end = ABSOLUTE(.); + } >irom0_0_seg :irom0_0_phdr +} + +/* get ROM code address */ +INCLUDE "../ld/eagle.rom.addr.v6.ld" diff --git a/ld/eagle.app.v6.old.1024.app2.ld b/ld/eagle.app.v6.old.1024.app2.ld new file mode 100644 index 0000000..80d77cb --- /dev/null +++ b/ld/eagle.app.v6.old.1024.app2.ld @@ -0,0 +1,217 @@ +/* This linker script generated from xt-genldscripts.tpp for LSP . */ +/* Linker Script for ld -N */ +MEMORY +{ + dport0_0_seg : org = 0x3FF00000, len = 0x10 + dram0_0_seg : org = 0x3FFE8000, len = 0x14000 + iram1_0_seg : org = 0x40100000, len = 0x8000 + irom0_0_seg : org = 0x40291000, len = 0x6B000 +} + +PHDRS +{ + dport0_0_phdr PT_LOAD; + dram0_0_phdr PT_LOAD; + dram0_0_bss_phdr PT_LOAD; + iram1_0_phdr PT_LOAD; + irom0_0_phdr PT_LOAD; +} + + +/* Default entry point: */ +ENTRY(call_user_start) +EXTERN(_DebugExceptionVector) +EXTERN(_DoubleExceptionVector) +EXTERN(_KernelExceptionVector) +EXTERN(_NMIExceptionVector) +EXTERN(_UserExceptionVector) +PROVIDE(_memmap_vecbase_reset = 0x40000000); +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x00000110; +_memmap_cacheattr_wt_base = 0x00000110; +_memmap_cacheattr_bp_base = 0x00000220; +_memmap_cacheattr_unused_mask = 0xFFFFF00F; +_memmap_cacheattr_wb_trapnull = 0x2222211F; +_memmap_cacheattr_wba_trapnull = 0x2222211F; +_memmap_cacheattr_wbna_trapnull = 0x2222211F; +_memmap_cacheattr_wt_trapnull = 0x2222211F; +_memmap_cacheattr_bp_trapnull = 0x2222222F; +_memmap_cacheattr_wb_strict = 0xFFFFF11F; +_memmap_cacheattr_wt_strict = 0xFFFFF11F; +_memmap_cacheattr_bp_strict = 0xFFFFF22F; +_memmap_cacheattr_wb_allvalid = 0x22222112; +_memmap_cacheattr_wt_allvalid = 0x22222112; +_memmap_cacheattr_bp_allvalid = 0x22222222; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); + +SECTIONS +{ + + .dport0.rodata : ALIGN(4) + { + _dport0_rodata_start = ABSOLUTE(.); + *(.dport0.rodata) + *(.dport.rodata) + _dport0_rodata_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.literal : ALIGN(4) + { + _dport0_literal_start = ABSOLUTE(.); + *(.dport0.literal) + *(.dport.literal) + _dport0_literal_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.data : ALIGN(4) + { + _dport0_data_start = ABSOLUTE(.); + *(.dport0.data) + *(.dport.data) + _dport0_data_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + _data_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + *(.eh_frame) + /* C++ constructor and destructor tables, properly ordered: */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); /* this table MUST be 4-byte aligned */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .UserExceptionVector.literal : AT(LOADADDR(.rodata) + (ADDR(.UserExceptionVector.literal) - ADDR(.rodata))) ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .bss ALIGN(8) (NOLOAD) : ALIGN(4) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + _heap_start = ABSOLUTE(.); +/* _stack_sentry = ALIGN(0x8); */ + } >dram0_0_seg :dram0_0_bss_phdr +/* __stack = 0x3ffc8000; */ + + .text : ALIGN(4) + { + _stext = .; + _text_start = ABSOLUTE(.); + *(.UserEnter.text) + . = ALIGN(16); + *(.DebugExceptionVector.text) + . = ALIGN(16); + *(.NMIExceptionVector.text) + . = ALIGN(16); + *(.KernelExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.UserExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.DoubleExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + } >iram1_0_seg :iram1_0_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >iram1_0_seg :iram1_0_phdr + + .irom0.text : ALIGN(4) + { + _irom0_text_start = ABSOLUTE(.); + *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text) + _irom0_text_end = ABSOLUTE(.); + } >irom0_0_seg :irom0_0_phdr +} + +/* get ROM code address */ +INCLUDE "../ld/eagle.rom.addr.v6.ld" diff --git a/ld/eagle.app.v6.old.512.app1.ld b/ld/eagle.app.v6.old.512.app1.ld new file mode 100644 index 0000000..7b71083 --- /dev/null +++ b/ld/eagle.app.v6.old.512.app1.ld @@ -0,0 +1,217 @@ +/* This linker script generated from xt-genldscripts.tpp for LSP . */ +/* Linker Script for ld -N */ +MEMORY +{ + dport0_0_seg : org = 0x3FF00000, len = 0x10 + dram0_0_seg : org = 0x3FFE8000, len = 0x14000 + iram1_0_seg : org = 0x40100000, len = 0x8000 + irom0_0_seg : org = 0x40211000, len = 0x2B000 +} + +PHDRS +{ + dport0_0_phdr PT_LOAD; + dram0_0_phdr PT_LOAD; + dram0_0_bss_phdr PT_LOAD; + iram1_0_phdr PT_LOAD; + irom0_0_phdr PT_LOAD; +} + + +/* Default entry point: */ +ENTRY(call_user_start) +EXTERN(_DebugExceptionVector) +EXTERN(_DoubleExceptionVector) +EXTERN(_KernelExceptionVector) +EXTERN(_NMIExceptionVector) +EXTERN(_UserExceptionVector) +PROVIDE(_memmap_vecbase_reset = 0x40000000); +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x00000110; +_memmap_cacheattr_wt_base = 0x00000110; +_memmap_cacheattr_bp_base = 0x00000220; +_memmap_cacheattr_unused_mask = 0xFFFFF00F; +_memmap_cacheattr_wb_trapnull = 0x2222211F; +_memmap_cacheattr_wba_trapnull = 0x2222211F; +_memmap_cacheattr_wbna_trapnull = 0x2222211F; +_memmap_cacheattr_wt_trapnull = 0x2222211F; +_memmap_cacheattr_bp_trapnull = 0x2222222F; +_memmap_cacheattr_wb_strict = 0xFFFFF11F; +_memmap_cacheattr_wt_strict = 0xFFFFF11F; +_memmap_cacheattr_bp_strict = 0xFFFFF22F; +_memmap_cacheattr_wb_allvalid = 0x22222112; +_memmap_cacheattr_wt_allvalid = 0x22222112; +_memmap_cacheattr_bp_allvalid = 0x22222222; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); + +SECTIONS +{ + + .dport0.rodata : ALIGN(4) + { + _dport0_rodata_start = ABSOLUTE(.); + *(.dport0.rodata) + *(.dport.rodata) + _dport0_rodata_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.literal : ALIGN(4) + { + _dport0_literal_start = ABSOLUTE(.); + *(.dport0.literal) + *(.dport.literal) + _dport0_literal_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.data : ALIGN(4) + { + _dport0_data_start = ABSOLUTE(.); + *(.dport0.data) + *(.dport.data) + _dport0_data_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + _data_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + *(.eh_frame) + /* C++ constructor and destructor tables, properly ordered: */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); /* this table MUST be 4-byte aligned */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .UserExceptionVector.literal : AT(LOADADDR(.rodata) + (ADDR(.UserExceptionVector.literal) - ADDR(.rodata))) ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .bss ALIGN(8) (NOLOAD) : ALIGN(4) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + _heap_start = ABSOLUTE(.); +/* _stack_sentry = ALIGN(0x8); */ + } >dram0_0_seg :dram0_0_bss_phdr +/* __stack = 0x3ffc8000; */ + + .text : ALIGN(4) + { + _stext = .; + _text_start = ABSOLUTE(.); + *(.UserEnter.text) + . = ALIGN(16); + *(.DebugExceptionVector.text) + . = ALIGN(16); + *(.NMIExceptionVector.text) + . = ALIGN(16); + *(.KernelExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.UserExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.DoubleExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + } >iram1_0_seg :iram1_0_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >iram1_0_seg :iram1_0_phdr + + .irom0.text : ALIGN(4) + { + _irom0_text_start = ABSOLUTE(.); + *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text) + _irom0_text_end = ABSOLUTE(.); + } >irom0_0_seg :irom0_0_phdr +} + +/* get ROM code address */ +INCLUDE "../ld/eagle.rom.addr.v6.ld" diff --git a/ld/eagle.app.v6.app2.ld b/ld/eagle.app.v6.old.512.app2.ld similarity index 77% rename from ld/eagle.app.v6.app2.ld rename to ld/eagle.app.v6.old.512.app2.ld index 7f45370..33959a4 100644 --- a/ld/eagle.app.v6.app2.ld +++ b/ld/eagle.app.v6.old.512.app2.ld @@ -2,9 +2,9 @@ /* Linker Script for ld -N */ MEMORY { - dport0_0_seg : org = 0x3FF00000, len = 0x10 - dram0_0_seg : org = 0x3FFE8000, len = 0x14000 - iram1_0_seg : org = 0x40100000, len = 0x8000 + dport0_0_seg : org = 0x3FF00000, len = 0x10 + dram0_0_seg : org = 0x3FFE8000, len = 0x14000 + iram1_0_seg : org = 0x40100000, len = 0x8000 irom0_0_seg : org = 0x40251000, len = 0x2B000 } @@ -20,6 +20,11 @@ PHDRS /* Default entry point: */ ENTRY(call_user_start) +EXTERN(_DebugExceptionVector) +EXTERN(_DoubleExceptionVector) +EXTERN(_KernelExceptionVector) +EXTERN(_NMIExceptionVector) +EXTERN(_UserExceptionVector) PROVIDE(_memmap_vecbase_reset = 0x40000000); /* Various memory-map dependent cache attribute settings: */ _memmap_cacheattr_wb_base = 0x00000110; @@ -121,6 +126,13 @@ SECTIONS _rodata_end = ABSOLUTE(.); } >dram0_0_seg :dram0_0_phdr + .UserExceptionVector.literal : AT(LOADADDR(.rodata) + (ADDR(.UserExceptionVector.literal) - ADDR(.rodata))) ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + .bss ALIGN(8) (NOLOAD) : ALIGN(4) { . = ALIGN (8); @@ -149,6 +161,30 @@ SECTIONS { _stext = .; _text_start = ABSOLUTE(.); + *(.UserEnter.text) + . = ALIGN(16); + *(.DebugExceptionVector.text) + . = ALIGN(16); + *(.NMIExceptionVector.text) + . = ALIGN(16); + *(.KernelExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.UserExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.DoubleExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN (16); *(.entry.text) *(.init.literal) *(.init) diff --git a/lib/libfreertos.a b/lib/libfreertos.a index 671b132..d8f8448 100644 Binary files a/lib/libfreertos.a and b/lib/libfreertos.a differ diff --git a/lib/libjson.a b/lib/libjson.a index 854a713..179119d 100644 Binary files a/lib/libjson.a and b/lib/libjson.a differ diff --git a/lib/liblwip.a b/lib/liblwip.a index 4b402eb..0584c42 100644 Binary files a/lib/liblwip.a and b/lib/liblwip.a differ diff --git a/lib/libmain.a b/lib/libmain.a new file mode 100644 index 0000000..60657ec Binary files /dev/null and b/lib/libmain.a differ diff --git a/lib/libnet80211.a b/lib/libnet80211.a new file mode 100644 index 0000000..4a36331 Binary files /dev/null and b/lib/libnet80211.a differ diff --git a/lib/libphy.a b/lib/libphy.a new file mode 100644 index 0000000..e2508e3 Binary files /dev/null and b/lib/libphy.a differ diff --git a/lib/libpp.a b/lib/libpp.a new file mode 100644 index 0000000..2747863 Binary files /dev/null and b/lib/libpp.a differ diff --git a/lib/libssl.a b/lib/libssl.a index 86d230c..77d9dfa 100644 Binary files a/lib/libssl.a and b/lib/libssl.a differ diff --git a/lib/libudhcp.a b/lib/libudhcp.a index f512cb6..d3cd28d 100644 Binary files a/lib/libudhcp.a and b/lib/libudhcp.a differ diff --git a/lib/libwpa.a b/lib/libwpa.a new file mode 100644 index 0000000..a8fa39a Binary files /dev/null and b/lib/libwpa.a differ diff --git a/third_party/freertos/croutine.c b/third_party/freertos/croutine.c index e5a591c..8ee5311 100644 --- a/third_party/freertos/croutine.c +++ b/third_party/freertos/croutine.c @@ -238,12 +238,14 @@ static void prvCheckPendingReadyList( void ) corCRCB *pxUnblockedCRCB; /* The pending ready list can be accessed by an ISR. */ - portDISABLE_INTERRUPTS(); + //portDISABLE_INTERRUPTS(); +PortDisableInt_NoNest(); { pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) ); ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); } - portENABLE_INTERRUPTS(); +// portENABLE_INTERRUPTS(); +PortEnableInt_NoNest(); ( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) ); prvAddCoRoutineToReadyQueue( pxUnblockedCRCB ); @@ -284,7 +286,8 @@ corCRCB *pxCRCB; break; } - portDISABLE_INTERRUPTS(); + //portDISABLE_INTERRUPTS(); +PortDisableInt_NoNest(); { /* The event could have occurred just before this critical section. If this is the case then the generic list item will @@ -299,7 +302,8 @@ corCRCB *pxCRCB; ( void ) uxListRemove( &( pxCRCB->xEventListItem ) ); } } - portENABLE_INTERRUPTS(); +// portENABLE_INTERRUPTS(); +PortEnableInt_NoNest(); prvAddCoRoutineToReadyQueue( pxCRCB ); } diff --git a/third_party/freertos/heap_4.c b/third_party/freertos/heap_4.c index 841db76..51eae94 100644 --- a/third_party/freertos/heap_4.c +++ b/third_party/freertos/heap_4.c @@ -156,7 +156,8 @@ void *pvReturn = NULL; // printf("%s %d %d\n", __func__, xWantedSize, xFreeBytesRemaining); - vTaskSuspendAll(); +// vTaskSuspendAll(); + ETS_INTR_LOCK(); { /* If this is the first call to malloc then the heap will require initialisation to setup the list of free blocks. */ @@ -239,7 +240,8 @@ void *pvReturn = NULL; } } } - xTaskResumeAll(); +// xTaskResumeAll(); + ETS_INTR_UNLOCK(); #if( configUSE_MALLOC_FAILED_HOOK == 1 ) { @@ -287,13 +289,15 @@ xBlockLink *pxLink; allocated. */ pxLink->xBlockSize &= ~xBlockAllocatedBit; - vTaskSuspendAll(); +// vTaskSuspendAll(); + ETS_INTR_LOCK(); { /* Add this block to the list of free blocks. */ xFreeBytesRemaining += pxLink->xBlockSize; prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) ); } - xTaskResumeAll(); +// xTaskResumeAll(); + ETS_INTR_UNLOCK(); } } } diff --git a/third_party/freertos/list.c b/third_party/freertos/list.c index b2dba36..c6b23d0 100644 --- a/third_party/freertos/list.c +++ b/third_party/freertos/list.c @@ -100,7 +100,7 @@ vListInitialiseItem( xListItem * const pxItem ) } /*-----------------------------------------------------------*/ -void ICACHE_FLASH_ATTR +void vListInsertEnd( xList * const pxList, xListItem * const pxNewListItem ) { xListItem * pxIndex; diff --git a/third_party/freertos/port.c b/third_party/freertos/port.c index d9e4b10..fee9337 100644 --- a/third_party/freertos/port.c +++ b/third_party/freertos/port.c @@ -86,8 +86,8 @@ unsigned cpu_sr; variable. */ static unsigned portBASE_TYPE uxCriticalNesting = 0; -void ICACHE_FLASH_ATTR vPortEnterCritical( void ); -void ICACHE_FLASH_ATTR vPortExitCritical( void ); +void vPortEnterCritical( void ); +void vPortExitCritical( void ); /* * See header file for description. */ @@ -123,23 +123,23 @@ pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *p } - - - - void PendSV( char req ) { -char tmp=0; -if(ClosedLv1Isr == 0) -{ - vPortEnterCritical(); - tmp = 1; -} + char tmp=0; +//ETS_INTR_LOCK(); + + if( NMIIrqIsOn == 0 ) + { + vPortEnterCritical(); + //PortDisableInt_NoNest(); + tmp = 1; + } + if(req ==1) { SWReq = 1; } - else + else if(req ==2) HdlMacSig= 1; #if 0 GPIO_REG_WRITE(GPIO_STATUS_W1TS_ADDRESS, 0x40); @@ -188,20 +188,20 @@ void SoftIsrHdl(void) { //if(DbgVal5==1) //printf("GP_%d,",SWReq); + PendSvIsPosted = 0; portBASE_TYPE xHigherPriorityTaskWoken=pdFALSE ; if(HdlMacSig == 1) { - HdlMacSig = 0; xHigherPriorityTaskWoken = MacIsrSigPostDefHdl(); + HdlMacSig = 0; } if( xHigherPriorityTaskWoken || (SWReq==1)) { //if( DbgVal5==1 || DbgVal10==1 ) //printf("_x_s,"); - SWReq = 0; _xt_timer_int1(); + SWReq = 0; } - PendSvIsPosted = 0; } #endif @@ -244,6 +244,7 @@ xPortStartScheduler( void ) // REG_SET_BIT(0x3ff2006c, BIT(4)); /* Restore the context of the first task that is going to run. */ + XT_RTOS_INT_EXIT(); /* Should not get here as the tasks are now running! */ @@ -262,14 +263,13 @@ vPortEndScheduler( void ) /*-----------------------------------------------------------*/ static unsigned int tick_lock=0; -char ClosedLv1Isr = 0; +static char ClosedLv1Isr = 0; -void ICACHE_FLASH_ATTR -vPortEnterCritical( void ) +void vPortEnterCritical( void ) { if(NMIIrqIsOn == 0) { - if( uxCriticalNesting == 0 ) + //if( uxCriticalNesting == 0 ) { if( ClosedLv1Isr !=1 ) { @@ -283,8 +283,7 @@ vPortEnterCritical( void ) } /*-----------------------------------------------------------*/ -void ICACHE_FLASH_ATTR -vPortExitCritical( void ) +void vPortExitCritical( void ) { if(NMIIrqIsOn == 0) { @@ -302,10 +301,11 @@ vPortExitCritical( void ) } } -static unsigned int tick_lock1=0; -void ICACHE_FLASH_ATTR -vPortEnterCritical1( void ) + +void +PortDisableInt_NoNest( void ) { +//os_printf("ERRRRRRR\n"); if(NMIIrqIsOn == 0) { if( ClosedLv1Isr !=1 ) @@ -316,9 +316,10 @@ vPortEnterCritical1( void ) } } -void ICACHE_FLASH_ATTR -vPortExitCritical1( void ) +void +PortEnableInt_NoNest( void ) { +os_printf("ERRRRR\n"); if(NMIIrqIsOn == 0) { if( ClosedLv1Isr ==1 ) diff --git a/third_party/freertos/queue.c b/third_party/freertos/queue.c index 12bc008..649b757 100644 --- a/third_party/freertos/queue.c +++ b/third_party/freertos/queue.c @@ -930,7 +930,7 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; #endif /* configUSE_ALTERNATIVE_API */ /*-----------------------------------------------------------*/ -signed portBASE_TYPE ICACHE_FLASH_ATTR +signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) { signed portBASE_TYPE xReturn; @@ -1201,7 +1201,7 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; } /*-----------------------------------------------------------*/ -signed portBASE_TYPE ICACHE_FLASH_ATTR +signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, const void * const pvBuffer, signed portBASE_TYPE *pxHigherPriorityTaskWoken ) { signed portBASE_TYPE xReturn; @@ -1279,7 +1279,7 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; } /*-----------------------------------------------------------*/ -signed portBASE_TYPE ICACHE_FLASH_ATTR +signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const pvBuffer ) { signed portBASE_TYPE xReturn; @@ -1350,7 +1350,7 @@ unsigned portBASE_TYPE uxReturn; } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ /*-----------------------------------------------------------*/ -unsigned portBASE_TYPE ICACHE_FLASH_ATTR +unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle xQueue ) { unsigned portBASE_TYPE uxReturn; @@ -1414,7 +1414,7 @@ xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ -static void ICACHE_FLASH_ATTR +static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) { if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 ) @@ -1465,7 +1465,7 @@ prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xP } /*-----------------------------------------------------------*/ -static void ICACHE_FLASH_ATTR +static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void * const pvBuffer ) { if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX ) @@ -1602,7 +1602,7 @@ signed portBASE_TYPE xReturn; } /*-----------------------------------------------------------*/ -signed portBASE_TYPE ICACHE_FLASH_ATTR +signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle xQueue ) { signed portBASE_TYPE xReturn; @@ -1643,7 +1643,7 @@ signed portBASE_TYPE xReturn; } /*-----------------------------------------------------------*/ -signed portBASE_TYPE ICACHE_FLASH_ATTR +signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle xQueue ) { signed portBASE_TYPE xReturn; @@ -1675,7 +1675,7 @@ signed portBASE_TYPE xReturn; between the check to see if the queue is full and blocking on the queue. */ //portDISABLE_INTERRUPTS(); -vPortEnterCritical1(); +PortDisableInt_NoNest(); { if( prvIsQueueFull( pxQueue ) != pdFALSE ) { @@ -1687,22 +1687,22 @@ vPortEnterCritical1(); return indicating that we need to block. */ vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) ); //portENABLE_INTERRUPTS(); -vPortExitCritical1(); +PortEnableInt_NoNest(); return errQUEUE_BLOCKED; } else { //portENABLE_INTERRUPTS(); -vPortExitCritical1(); +PortEnableInt_NoNest(); return errQUEUE_FULL; } } } //portENABLE_INTERRUPTS(); -vPortExitCritical1(); +PortEnableInt_NoNest(); //portDISABLE_INTERRUPTS(); -vPortEnterCritical1(); +PortDisableInt_NoNest(); { if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) { @@ -1731,7 +1731,7 @@ vPortEnterCritical1(); } } //portENABLE_INTERRUPTS(); -vPortExitCritical1(); +PortEnableInt_NoNest(); return xReturn; } @@ -1751,7 +1751,7 @@ vPortExitCritical1(); between the check to see if the queue is empty and blocking on the queue. */ //portDISABLE_INTERRUPTS(); -vPortEnterCritical1(); +PortDisableInt_NoNest(); { if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ) { @@ -1763,22 +1763,22 @@ vPortEnterCritical1(); indicating that we need to block. */ vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) ); //portENABLE_INTERRUPTS(); -vPortExitCritical1(); +PortEnableInt_NoNest(); return errQUEUE_BLOCKED; } else { //portENABLE_INTERRUPTS(); -vPortExitCritical1(); +PortEnableInt_NoNest(); return errQUEUE_FULL; } } } //portENABLE_INTERRUPTS(); -vPortExitCritical1(); +PortEnableInt_NoNest(); //portDISABLE_INTERRUPTS(); -vPortEnterCritical1(); +PortDisableInt_NoNest(); { if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) { @@ -1812,7 +1812,7 @@ vPortEnterCritical1(); } } //portENABLE_INTERRUPTS(); -vPortExitCritical1(); +PortEnableInt_NoNest(); return xReturn; } @@ -1822,7 +1822,7 @@ vPortExitCritical1(); #if ( configUSE_CO_ROUTINES == 1 ) - signed portBASE_TYPE ICACHE_FLASH_ATTR + signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) { xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; @@ -1855,7 +1855,7 @@ vPortExitCritical1(); #if ( configUSE_CO_ROUTINES == 1 ) - signed portBASE_TYPE ICACHE_FLASH_ATTR + signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken ) { signed portBASE_TYPE xReturn; @@ -2081,7 +2081,7 @@ vPortExitCritical1(); #if ( configUSE_QUEUE_SETS == 1 ) - xQueueSetMemberHandle ICACHE_FLASH_ATTR + xQueueSetMemberHandle xQueueSelectFromSetFromISR( xQueueSetHandle xQueueSet ) { xQueueSetMemberHandle xReturn = NULL; diff --git a/third_party/freertos/tasks.c b/third_party/freertos/tasks.c index 30ad7cf..808dbaa 100644 --- a/third_party/freertos/tasks.c +++ b/third_party/freertos/tasks.c @@ -101,7 +101,7 @@ privileged Vs unprivileged linkage and placement. */ /* * Defines the size, in words, of the stack allocated to the idle task. */ -#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE +#define tskIDLE_STACK_SIZE 176 //configMINIMAL_STACK_SIZE /* * Task control block. A task control block (TCB) is allocated for each task, @@ -1172,7 +1172,7 @@ tskTCB * pxNewTCB; #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) - portBASE_TYPE ICACHE_FLASH_ATTR + portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume ) { portBASE_TYPE xYieldRequired = pdFALSE; @@ -1270,7 +1270,7 @@ printf("idle_task_hdl : %x\n", xIdleTaskHandle); STEPPING THROUGH HERE USING A DEBUGGER CAN CAUSE BIG PROBLEMS IF THE DEBUGGER ALLOWS INTERRUPTS TO BE PROCESSED. */ //portDISABLE_INTERRUPTS(); -vPortEnterCritical1(); +PortDisableInt_NoNest(); xSchedulerRunning = pdTRUE; xTickCount = ( portTickType ) 0U; @@ -1310,7 +1310,7 @@ vTaskEndScheduler( void ) layer must ensure interrupts enable bit is left in the correct state. */ //portDISABLE_INTERRUPTS(); -vPortEnterCritical1(); +PortDisableInt_NoNest(); xSchedulerRunning = pdFALSE; vPortEndScheduler(); } @@ -1441,7 +1441,7 @@ portTickType xTicks; } /*-----------------------------------------------------------*/ -portTickType ICACHE_FLASH_ATTR +portTickType xTaskGetTickCountFromISR( void ) { portTickType xReturn; @@ -1974,7 +1974,7 @@ portTickType xTimeToWake; #endif /* configUSE_TIMERS */ /*-----------------------------------------------------------*/ -signed portBASE_TYPE ICACHE_FLASH_ATTR +signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) { tskTCB *pxUnblockedTCB; @@ -2734,7 +2734,7 @@ tskTCB *pxNewTCB; #if ( configUSE_MUTEXES == 1 ) - void ICACHE_FLASH_ATTR + void vTaskPriorityDisinherit( xTaskHandle const pxMutexHolder ) { tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; @@ -2769,7 +2769,7 @@ tskTCB *pxNewTCB; vTaskEnterCritical( void ) { //portDISABLE_INTERRUPTS(); -vPortEnterCritical1(); +PortDisableInt_NoNest(); if( xSchedulerRunning != pdFALSE ) { ( pxCurrentTCB->uxCriticalNesting )++; @@ -2793,7 +2793,7 @@ vPortEnterCritical1(); if( pxCurrentTCB->uxCriticalNesting == 0U ) { //portENABLE_INTERRUPTS(); -vPortExitCritical1(); + PortEnableInt_NoNest(); } } } diff --git a/third_party/lwip/FILES b/third_party/lwip/FILES deleted file mode 100644 index 10115a7..0000000 --- a/third_party/lwip/FILES +++ /dev/null @@ -1,13 +0,0 @@ -api/ - The code for the high-level wrapper API. Not needed if - you use the lowel-level call-back/raw API. - -core/ - The core of the TPC/IP stack; protocol implementations, - memory and buffer management, and the low-level raw API. - -include/ - lwIP include files. - -netif/ - Generic network interface device drivers are kept here, - as well as the ARP module. - -For more information on the various subdirectories, check the FILES -file in each directory. diff --git a/third_party/lwip/Makefile b/third_party/lwip/Makefile deleted file mode 100644 index 30db445..0000000 --- a/third_party/lwip/Makefile +++ /dev/null @@ -1,50 +0,0 @@ - -############################################################# -# Required variables for each makefile -# Discard this section from all parent makefiles -# Expected variables (with automatic defaults): -# CSRCS (all "C" files in the dir) -# SUBDIRS (all subdirs with a Makefile) -# GEN_LIBS - list of libs to be generated () -# GEN_IMAGES - list of images to be generated () -# COMPONENTS_xxx - a list of libs/objs in the form -# subdir/lib to be extracted and rolled up into -# a generated lib/image xxx.a () -# -ifndef PDIR -UP_EXTRACT_DIR = .. -GEN_LIBS = liblwip.a -COMPONENTS_liblwip = api/liblwipapi.a \ - arch/liblwiparch.a \ - core/liblwipcore.a \ - core/ipv4/liblwipipv4.a \ - netif/liblwipnetif.a -endif - - -############################################################# -# Configuration i.e. compile options etc. -# Target specific stuff (defines etc.) goes in here! -# Generally values applying to a tree are captured in the -# makefile at its root level - these are then overridden -# for a subtree within the makefile rooted therein -# -#DEFINES += - -############################################################# -# Recursion Magic - Don't touch this!! -# -# Each subtree potentially has an include directory -# corresponding to the common APIs applicable to modules -# rooted at that subtree. Accordingly, the INCLUDE PATH -# of a module can only contain the include directories up -# its parent path, and not its siblings -# -# Required for each makefile to inherit from the parent -# - -INCLUDES := $(INCLUDES) -I $(PDIR)include -INCLUDES += -I ./ -PDIR := ../$(PDIR) -sinclude $(PDIR)Makefile - diff --git a/third_party/lwip/api/Makefile b/third_party/lwip/api/Makefile deleted file mode 100644 index ef34edc..0000000 --- a/third_party/lwip/api/Makefile +++ /dev/null @@ -1,46 +0,0 @@ - -############################################################# -# Required variables for each makefile -# Discard this section from all parent makefiles -# Expected variables (with automatic defaults): -# CSRCS (all "C" files in the dir) -# SUBDIRS (all subdirs with a Makefile) -# GEN_LIBS - list of libs to be generated () -# GEN_IMAGES - list of images to be generated () -# COMPONENTS_xxx - a list of libs/objs in the form -# subdir/lib to be extracted and rolled up into -# a generated lib/image xxx.a () -# -ifndef PDIR - -GEN_LIBS = liblwipapi.a - -endif - - -############################################################# -# Configuration i.e. compile options etc. -# Target specific stuff (defines etc.) goes in here! -# Generally values applying to a tree are captured in the -# makefile at its root level - these are then overridden -# for a subtree within the makefile rooted therein -# -#DEFINES += - -############################################################# -# Recursion Magic - Don't touch this!! -# -# Each subtree potentially has an include directory -# corresponding to the common APIs applicable to modules -# rooted at that subtree. Accordingly, the INCLUDE PATH -# of a module can only contain the include directories up -# its parent path, and not its siblings -# -# Required for each makefile to inherit from the parent -# - -INCLUDES := $(INCLUDES) -I $(PDIR)include -INCLUDES += -I ./ -PDIR := ../$(PDIR) -sinclude $(PDIR)Makefile - diff --git a/third_party/lwip/api/api_lib.c b/third_party/lwip/api/api_lib.c deleted file mode 100644 index 9826cf3..0000000 --- a/third_party/lwip/api/api_lib.c +++ /dev/null @@ -1,788 +0,0 @@ -/** - * @file - * Sequential API External module - * - */ - -/* - * 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 - * - */ - -/* This is the part of the API that is linked with - the application */ - -#include "lwip/opt.h" - -#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/api.h" -#include "lwip/tcpip.h" -#include "lwip/memp.h" - -#include "lwip/ip.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/tcp.h" - -#include - -/** - * Create a new netconn (of a specific type) that has a callback function. - * The corresponding pcb is also created. - * - * @param t the type of 'connection' to create (@see enum netconn_type) - * @param proto the IP protocol for RAW IP pcbs - * @param callback a function to call on status changes (RX available, TX'ed) - * @return a newly allocated struct netconn or - * NULL on memory error - */ -struct netconn* ICACHE_FLASH_ATTR -netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) -{ - struct netconn *conn; - struct api_msg msg; - - conn = netconn_alloc(t, callback); - if (conn != NULL) { - err_t err; - msg.msg.msg.n.proto = proto; - msg.msg.conn = conn; - TCPIP_APIMSG((&msg), lwip_netconn_do_newconn, err); - if (err != ERR_OK) { - LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL); - LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed)); - LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox)); -#if LWIP_TCP - LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox)); -#endif /* LWIP_TCP */ - sys_sem_free(&conn->op_completed); - sys_mbox_free(&conn->recvmbox); - memp_free(MEMP_NETCONN, conn); - return NULL; - } - } - return conn; -} - -/** - * Close a netconn 'connection' and free its resources. - * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate - * after this returns. - * - * @param conn the netconn to delete - * @return ERR_OK if the connection was deleted - */ -err_t ICACHE_FLASH_ATTR -netconn_delete(struct netconn *conn) -{ - struct api_msg msg; - - /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */ - if (conn == NULL) { - return ERR_OK; - } - - msg.function = lwip_netconn_do_delconn; - msg.msg.conn = conn; - tcpip_apimsg(&msg); - - netconn_free(conn); - - /* don't care for return value of lwip_netconn_do_delconn since it only calls void functions */ - - return ERR_OK; -} - -/** - * Get the local or remote IP address and port of a netconn. - * For RAW netconns, this returns the protocol instead of a port! - * - * @param conn the netconn to query - * @param addr a pointer to which to save the IP address - * @param port a pointer to which to save the port (or protocol for RAW) - * @param local 1 to get the local IP address, 0 to get the remote one - * @return ERR_CONN for invalid connections - * ERR_OK if the information was retrieved - */ -err_t ICACHE_FLASH_ATTR -netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local) -{ - struct api_msg msg; - err_t err; - - LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;); - - msg.msg.conn = conn; - msg.msg.msg.ad.ipaddr = ip_2_ipX(addr); - msg.msg.msg.ad.port = port; - msg.msg.msg.ad.local = local; - TCPIP_APIMSG(&msg, lwip_netconn_do_getaddr, err); - - NETCONN_SET_SAFE_ERR(conn, err); - return err; -} - -/** - * Bind a netconn to a specific local IP address and port. - * Binding one netconn twice might not always be checked correctly! - * - * @param conn the netconn to bind - * @param addr the local IP address to bind the netconn to (use IP_ADDR_ANY - * to bind to all addresses) - * @param port the local port to bind the netconn to (not used for RAW) - * @return ERR_OK if bound, any other err_t on failure - */ -err_t ICACHE_FLASH_ATTR -netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port) -{ - struct api_msg msg; - err_t err; - - LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); - - msg.msg.conn = conn; - msg.msg.msg.bc.ipaddr = addr; - msg.msg.msg.bc.port = port; - TCPIP_APIMSG(&msg, lwip_netconn_do_bind, err); - - NETCONN_SET_SAFE_ERR(conn, err); - return err; -} - -/** - * Connect a netconn to a specific remote IP address and port. - * - * @param conn the netconn to connect - * @param addr the remote IP address to connect to - * @param port the remote port to connect to (no used for RAW) - * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise - */ -err_t ICACHE_FLASH_ATTR -netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port) -{ - struct api_msg msg; - err_t err; - - LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;); - - msg.msg.conn = conn; - msg.msg.msg.bc.ipaddr = addr; - msg.msg.msg.bc.port = port; -#if LWIP_TCP -#if (LWIP_UDP || LWIP_RAW) - if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) -#endif /* (LWIP_UDP || LWIP_RAW) */ - { - /* The TCP version waits for the connect to succeed, - so always needs to use message passing. */ - msg.function = lwip_netconn_do_connect; - err = tcpip_apimsg(&msg); - } -#endif /* LWIP_TCP */ -#if (LWIP_UDP || LWIP_RAW) && LWIP_TCP - else -#endif /* (LWIP_UDP || LWIP_RAW) && LWIP_TCP */ -#if (LWIP_UDP || LWIP_RAW) - { - /* UDP and RAW only set flags, so we can use core-locking. */ - TCPIP_APIMSG(&msg, lwip_netconn_do_connect, err); - } -#endif /* (LWIP_UDP || LWIP_RAW) */ - - NETCONN_SET_SAFE_ERR(conn, err); - return err; -} - -/** - * Disconnect a netconn from its current peer (only valid for UDP netconns). - * - * @param conn the netconn to disconnect - * @return TODO: return value is not set here... - */ -err_t ICACHE_FLASH_ATTR -netconn_disconnect(struct netconn *conn) -{ - struct api_msg msg; - err_t err; - - LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;); - - msg.msg.conn = conn; - TCPIP_APIMSG(&msg, lwip_netconn_do_disconnect, err); - - NETCONN_SET_SAFE_ERR(conn, err); - return err; -} - -/** - * Set a TCP netconn into listen mode - * - * @param conn the tcp netconn to set to listen mode - * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1 - * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns - * don't return any error (yet?)) - */ -err_t ICACHE_FLASH_ATTR -netconn_listen_with_backlog(struct netconn *conn, u8_t backlog) -{ -#if LWIP_TCP - struct api_msg msg; - err_t err; - - /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */ - LWIP_UNUSED_ARG(backlog); - - LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;); - - msg.msg.conn = conn; -#if TCP_LISTEN_BACKLOG - msg.msg.msg.lb.backlog = backlog; -#endif /* TCP_LISTEN_BACKLOG */ - TCPIP_APIMSG(&msg, lwip_netconn_do_listen, err); - - NETCONN_SET_SAFE_ERR(conn, err); - return err; -#else /* LWIP_TCP */ - LWIP_UNUSED_ARG(conn); - LWIP_UNUSED_ARG(backlog); - return ERR_ARG; -#endif /* LWIP_TCP */ -} - -/** - * Accept a new connection on a TCP listening netconn. - * - * @param conn the TCP listen netconn - * @param new_conn pointer where the new connection is stored - * @return ERR_OK if a new connection has been received or an error - * code otherwise - */ -err_t ICACHE_FLASH_ATTR -netconn_accept(struct netconn *conn, struct netconn **new_conn) -{ -#if LWIP_TCP - struct netconn *newconn; - err_t err; -#if TCP_LISTEN_BACKLOG - struct api_msg msg; -#endif /* TCP_LISTEN_BACKLOG */ - - LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;); - *new_conn = NULL; - LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_accept: invalid acceptmbox", sys_mbox_valid(&conn->acceptmbox), return ERR_ARG;); - - err = conn->last_err; - if (ERR_IS_FATAL(err)) { - /* don't recv on fatal errors: this might block the application task - waiting on acceptmbox forever! */ - return err; - } - -#if LWIP_SO_RCVTIMEO - if (sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { - NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT); - return ERR_TIMEOUT; - } -#else - sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, 0); -#endif /* LWIP_SO_RCVTIMEO*/ - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); - - if (newconn == NULL) { - /* connection has been aborted */ - NETCONN_SET_SAFE_ERR(conn, ERR_ABRT); - return ERR_ABRT; - } -#if TCP_LISTEN_BACKLOG - /* Let the stack know that we have accepted the connection. */ - msg.msg.conn = conn; - /* don't care for the return value of lwip_netconn_do_recv */ - TCPIP_APIMSG_NOERR(&msg, lwip_netconn_do_recv); -#endif /* TCP_LISTEN_BACKLOG */ - - *new_conn = newconn; - /* don't set conn->last_err: it's only ERR_OK, anyway */ - return ERR_OK; -#else /* LWIP_TCP */ - LWIP_UNUSED_ARG(conn); - LWIP_UNUSED_ARG(new_conn); - return ERR_ARG; -#endif /* LWIP_TCP */ -} - -/** - * Receive data: actual implementation that doesn't care whether pbuf or netbuf - * is received - * - * @param conn the netconn from which to receive data - * @param new_buf pointer where a new pbuf/netbuf is stored when received data - * @return ERR_OK if data has been received, an error code otherwise (timeout, - * memory error or another error) - */ -static err_t ICACHE_FLASH_ATTR -netconn_recv_data(struct netconn *conn, void **new_buf) -{ - void *buf = NULL; - u16_t len; - err_t err; -#if LWIP_TCP - struct api_msg msg; -#endif /* LWIP_TCP */ - - LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); - *new_buf = NULL; - LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); - - err = conn->last_err; - if (ERR_IS_FATAL(err)) { - /* don't recv on fatal errors: this might block the application task - waiting on recvmbox forever! */ - /* @todo: this does not allow us to fetch data that has been put into recvmbox - before the fatal error occurred - is that a problem? */ - return err; - } - -#if LWIP_SO_RCVTIMEO - if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { - NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT); - return ERR_TIMEOUT; - } -#else - sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); -#endif /* LWIP_SO_RCVTIMEO*/ - -#if LWIP_TCP -#if (LWIP_UDP || LWIP_RAW) - if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) -#endif /* (LWIP_UDP || LWIP_RAW) */ - { - if (!netconn_get_noautorecved(conn) || (buf == NULL)) { - /* Let the stack know that we have taken the data. */ - /* TODO: Speedup: Don't block and wait for the answer here - (to prevent multiple thread-switches). */ - msg.msg.conn = conn; - if (buf != NULL) { - msg.msg.msg.r.len = ((struct pbuf *)buf)->tot_len; - } else { - msg.msg.msg.r.len = 1; - } - /* don't care for the return value of lwip_netconn_do_recv */ - TCPIP_APIMSG_NOERR(&msg, lwip_netconn_do_recv); - } - - /* If we are closed, we indicate that we no longer wish to use the socket */ - if (buf == NULL) { - API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); - /* Avoid to lose any previous error code */ - NETCONN_SET_SAFE_ERR(conn, ERR_CLSD); - return ERR_CLSD; - } - len = ((struct pbuf *)buf)->tot_len; - } -#endif /* LWIP_TCP */ -#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) - else -#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ -#if (LWIP_UDP || LWIP_RAW) - { - LWIP_ASSERT("buf != NULL", buf != NULL); - len = netbuf_len((struct netbuf *)buf); - } -#endif /* (LWIP_UDP || LWIP_RAW) */ - -#if LWIP_SO_RCVBUF - SYS_ARCH_DEC(conn->recv_avail, len); -#endif /* LWIP_SO_RCVBUF */ - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVMINUS, len); - - LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len)); - - *new_buf = buf; - /* don't set conn->last_err: it's only ERR_OK, anyway */ - return ERR_OK; -} - -/** - * Receive data (in form of a pbuf) from a TCP netconn - * - * @param conn the netconn from which to receive data - * @param new_buf pointer where a new pbuf is stored when received data - * @return ERR_OK if data has been received, an error code otherwise (timeout, - * memory error or another error) - * ERR_ARG if conn is not a TCP netconn - */ -err_t ICACHE_FLASH_ATTR -netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf) -{ - LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) && - NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;); - - return netconn_recv_data(conn, (void **)new_buf); -} - -/** - * Receive data (in form of a netbuf containing a packet buffer) from a netconn - * - * @param conn the netconn from which to receive data - * @param new_buf pointer where a new netbuf is stored when received data - * @return ERR_OK if data has been received, an error code otherwise (timeout, - * memory error or another error) - */ -err_t ICACHE_FLASH_ATTR -netconn_recv(struct netconn *conn, struct netbuf **new_buf) -{ -#if LWIP_TCP - struct netbuf *buf = NULL; - err_t err; -#endif /* LWIP_TCP */ - - LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); - *new_buf = NULL; - LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); - -#if LWIP_TCP -#if (LWIP_UDP || LWIP_RAW) - if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) -#endif /* (LWIP_UDP || LWIP_RAW) */ - { - struct pbuf *p = NULL; - /* This is not a listening netconn, since recvmbox is set */ - - buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); - if (buf == NULL) { - NETCONN_SET_SAFE_ERR(conn, ERR_MEM); - return ERR_MEM; - } - - err = netconn_recv_data(conn, (void **)&p); - if (err != ERR_OK) { - memp_free(MEMP_NETBUF, buf); - return err; - } - LWIP_ASSERT("p != NULL", p != NULL); - - buf->p = p; - buf->ptr = p; - buf->port = 0; - ipX_addr_set_any(LWIP_IPV6, &buf->addr); - *new_buf = buf; - /* don't set conn->last_err: it's only ERR_OK, anyway */ - return ERR_OK; - } -#endif /* LWIP_TCP */ -#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) - else -#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ - { -#if (LWIP_UDP || LWIP_RAW) - return netconn_recv_data(conn, (void **)new_buf); -#endif /* (LWIP_UDP || LWIP_RAW) */ - } -} - -/** - * TCP: update the receive window: by calling this, the application - * tells the stack that it has processed data and is able to accept - * new data. - * ATTENTION: use with care, this is mainly used for sockets! - * Can only be used when calling netconn_set_noautorecved(conn, 1) before. - * - * @param conn the netconn for which to update the receive window - * @param length amount of data processed (ATTENTION: this must be accurate!) - */ -void ICACHE_FLASH_ATTR -netconn_recved(struct netconn *conn, u32_t length) -{ -#if LWIP_TCP - if ((conn != NULL) && (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && - (netconn_get_noautorecved(conn))) { - struct api_msg msg; - /* Let the stack know that we have taken the data. */ - /* TODO: Speedup: Don't block and wait for the answer here - (to prevent multiple thread-switches). */ - msg.msg.conn = conn; - msg.msg.msg.r.len = length; - /* don't care for the return value of lwip_netconn_do_recv */ - TCPIP_APIMSG_NOERR(&msg, lwip_netconn_do_recv); - } -#else /* LWIP_TCP */ - LWIP_UNUSED_ARG(conn); - LWIP_UNUSED_ARG(length); -#endif /* LWIP_TCP */ -} - -/** - * Send data (in form of a netbuf) to a specific remote IP address and port. - * Only to be used for UDP and RAW netconns (not TCP). - * - * @param conn the netconn over which to send data - * @param buf a netbuf containing the data to send - * @param addr the remote IP address to which to send the data - * @param port the remote port to which to send the data - * @return ERR_OK if data was sent, any other err_t on error - */ -err_t ICACHE_FLASH_ATTR -netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t port) -{ - if (buf != NULL) { - ipX_addr_set_ipaddr(PCB_ISIPV6(conn->pcb.ip), &buf->addr, addr); - buf->port = port; - return netconn_send(conn, buf); - } - return ERR_VAL; -} - -/** - * Send data over a UDP or RAW netconn (that is already connected). - * - * @param conn the UDP or RAW netconn over which to send data - * @param buf a netbuf containing the data to send - * @return ERR_OK if data was sent, any other err_t on error - */ -err_t ICACHE_FLASH_ATTR -netconn_send(struct netconn *conn, struct netbuf *buf) -{ - struct api_msg msg; - err_t err; - - LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;); - - LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len)); - msg.msg.conn = conn; - msg.msg.msg.b = buf; - TCPIP_APIMSG(&msg, lwip_netconn_do_send, err); - - NETCONN_SET_SAFE_ERR(conn, err); - return err; -} - -/** - * Send data over a TCP netconn. - * - * @param conn the TCP netconn over which to send data - * @param dataptr pointer to the application buffer that contains the data to send - * @param size size of the application data to send - * @param apiflags combination of following flags : - * - NETCONN_COPY: data will be copied into memory belonging to the stack - * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent - * - NETCONN_DONTBLOCK: only write the data if all dat can be written at once - * @param bytes_written pointer to a location that receives the number of written bytes - * @return ERR_OK if data was sent, any other err_t on error - */ -err_t ICACHE_FLASH_ATTR -netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, - u8_t apiflags, size_t *bytes_written) -{ - struct api_msg msg; - err_t err; - u8_t dontblock; - - LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_write: invalid conn->type", (NETCONNTYPE_GROUP(conn->type)== NETCONN_TCP), return ERR_VAL;); - if (size == 0) { - return ERR_OK; - } - dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); - if (dontblock && !bytes_written) { - /* This implies netconn_write() cannot be used for non-blocking send, since - it has no way to return the number of bytes written. */ - return ERR_VAL; - } - - /* non-blocking write sends as much */ - msg.msg.conn = conn; - msg.msg.msg.w.dataptr = dataptr; - msg.msg.msg.w.apiflags = apiflags; - msg.msg.msg.w.len = size; -#if LWIP_SO_SNDTIMEO - if (conn->send_timeout != 0) { - /* get the time we started, which is later compared to - sys_now() + conn->send_timeout */ - msg.msg.msg.w.time_started = sys_now(); - } else { - msg.msg.msg.w.time_started = 0; - } -#endif /* LWIP_SO_SNDTIMEO */ - - /* For locking the core: this _can_ be delayed on low memory/low send buffer, - but if it is, this is done inside api_msg.c:do_write(), so we can use the - non-blocking version here. */ - TCPIP_APIMSG(&msg, lwip_netconn_do_write, err); - if ((err == ERR_OK) && (bytes_written != NULL)) { - if (dontblock -#if LWIP_SO_SNDTIMEO - || (conn->send_timeout != 0) -#endif /* LWIP_SO_SNDTIMEO */ - ) { - /* nonblocking write: maybe the data has been sent partly */ - *bytes_written = msg.msg.msg.w.len; - } else { - /* blocking call succeeded: all data has been sent if it */ - *bytes_written = size; - } - } - - NETCONN_SET_SAFE_ERR(conn, err); - return err; -} - -/** - * Close ot shutdown a TCP netconn (doesn't delete it). - * - * @param conn the TCP netconn to close or shutdown - * @param how fully close or only shutdown one side? - * @return ERR_OK if the netconn was closed, any other err_t on error - */ -static err_t ICACHE_FLASH_ATTR -netconn_close_shutdown(struct netconn *conn, u8_t how) -{ - struct api_msg msg; - err_t err; - - LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;); - - msg.function = lwip_netconn_do_close; - msg.msg.conn = conn; - /* shutting down both ends is the same as closing */ - msg.msg.msg.sd.shut = how; - /* because of the LWIP_TCPIP_CORE_LOCKING implementation of lwip_netconn_do_close, - don't use TCPIP_APIMSG here */ - err = tcpip_apimsg(&msg); - - NETCONN_SET_SAFE_ERR(conn, err); - return err; -} - -/** - * Close a TCP netconn (doesn't delete it). - * - * @param conn the TCP netconn to close - * @return ERR_OK if the netconn was closed, any other err_t on error - */ -err_t ICACHE_FLASH_ATTR -netconn_close(struct netconn *conn) -{ - /* shutting down both ends is the same as closing */ - return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR); -} - -/** - * Shut down one or both sides of a TCP netconn (doesn't delete it). - * - * @param conn the TCP netconn to shut down - * @return ERR_OK if the netconn was closed, any other err_t on error - */ -err_t ICACHE_FLASH_ATTR -netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx) -{ - return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0)); -} - -#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) -/** - * Join multicast groups for UDP netconns. - * - * @param conn the UDP netconn for which to change multicast addresses - * @param multiaddr IP address of the multicast group to join or leave - * @param netif_addr the IP address of the network interface on which to send - * the igmp message - * @param join_or_leave flag whether to send a join- or leave-message - * @return ERR_OK if the action was taken, any err_t on error - */ -err_t ICACHE_FLASH_ATTR -netconn_join_leave_group(struct netconn *conn, - ip_addr_t *multiaddr, - ip_addr_t *netif_addr, - enum netconn_igmp join_or_leave) -{ - struct api_msg msg; - err_t err; - - LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;); - - msg.msg.conn = conn; - msg.msg.msg.jl.multiaddr = ip_2_ipX(multiaddr); - msg.msg.msg.jl.netif_addr = ip_2_ipX(netif_addr); - msg.msg.msg.jl.join_or_leave = join_or_leave; - TCPIP_APIMSG(&msg, lwip_netconn_do_join_leave_group, err); - - NETCONN_SET_SAFE_ERR(conn, err); - return err; -} -#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ - -#if LWIP_DNS -/** - * Execute a DNS query, only one IP address is returned - * - * @param name a string representation of the DNS host name to query - * @param addr a preallocated ip_addr_t where to store the resolved IP address - * @return ERR_OK: resolving succeeded - * ERR_MEM: memory error, try again later - * ERR_ARG: dns client not initialized or invalid hostname - * ERR_VAL: dns server response was invalid - */ -err_t ICACHE_FLASH_ATTR -netconn_gethostbyname(const char *name, ip_addr_t *addr) -{ - struct dns_api_msg msg; - err_t err; - sys_sem_t sem; - - LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;); - - err = sys_sem_new(&sem, 0); - if (err != ERR_OK) { - return err; - } - - msg.name = name; - msg.addr = addr; - msg.err = &err; - msg.sem = &sem; - - tcpip_callback(lwip_netconn_do_gethostbyname, &msg); - sys_sem_wait(&sem); - sys_sem_free(&sem); - - return err; -} -#endif /* LWIP_DNS*/ - -#endif /* LWIP_NETCONN */ diff --git a/third_party/lwip/api/api_msg.c b/third_party/lwip/api/api_msg.c deleted file mode 100644 index 6b4d63e..0000000 --- a/third_party/lwip/api/api_msg.c +++ /dev/null @@ -1,1611 +0,0 @@ -/** - * @file - * Sequential API Internal module - * - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" - -#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/api_msg.h" - -#include "lwip/ip.h" -#include "lwip/udp.h" -#include "lwip/tcp.h" -#include "lwip/raw.h" - -#include "lwip/memp.h" -#include "lwip/tcpip.h" -#include "lwip/igmp.h" -#include "lwip/dns.h" -#include "lwip/mld6.h" - -#include - -#define SET_NONBLOCKING_CONNECT(conn, val) do { if(val) { \ - (conn)->flags |= NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \ -} else { \ - (conn)->flags &= ~ NETCONN_FLAG_IN_NONBLOCKING_CONNECT; }} while(0) -#define IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0) - -/* forward declarations */ -#if LWIP_TCP -static err_t lwip_netconn_do_writemore(struct netconn *conn); -static void lwip_netconn_do_close_internal(struct netconn *conn); -#endif - -#if LWIP_RAW -/** - * Receive callback function for RAW netconns. - * Doesn't 'eat' the packet, only references it and sends it to - * conn->recvmbox - * - * @see raw.h (struct raw_pcb.recv) for parameters and return value - */ -static u8_t ICACHE_FLASH_ATTR -recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, - ip_addr_t *addr) -{ - struct pbuf *q; - struct netbuf *buf; - struct netconn *conn; - - LWIP_UNUSED_ARG(addr); - conn = (struct netconn *)arg; - - if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) { -#if LWIP_SO_RCVBUF - int recv_avail; - SYS_ARCH_GET(conn->recv_avail, recv_avail); - if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) { - return 0; - } -#endif /* LWIP_SO_RCVBUF */ - /* copy the whole packet into new pbufs */ - q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); - if(q != NULL) { - if (pbuf_copy(q, p) != ERR_OK) { - pbuf_free(q); - q = NULL; - } - } - - if (q != NULL) { - u16_t len; - buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); - if (buf == NULL) { - pbuf_free(q); - return 0; - } - - buf->p = q; - buf->ptr = q; - ipX_addr_copy(PCB_ISIPV6(pcb), buf->addr, *ipX_current_src_addr()); - buf->port = pcb->protocol; - - len = q->tot_len; - if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { - netbuf_delete(buf); - return 0; - } else { -#if LWIP_SO_RCVBUF - SYS_ARCH_INC(conn->recv_avail, len); -#endif /* LWIP_SO_RCVBUF */ - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); - } - } - } - - return 0; /* do not eat the packet */ -} -#endif /* LWIP_RAW*/ - -#if LWIP_UDP -/** - * Receive callback function for UDP netconns. - * Posts the packet to conn->recvmbox or deletes it on memory error. - * - * @see udp.h (struct udp_pcb.recv) for parameters - */ -static void ICACHE_FLASH_ATTR -recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, - ip_addr_t *addr, u16_t port) -{ - struct netbuf *buf; - struct netconn *conn; - u16_t len; -#if LWIP_SO_RCVBUF - int recv_avail; -#endif /* LWIP_SO_RCVBUF */ - - LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ - LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); - LWIP_ASSERT("recv_udp must have an argument", arg != NULL); - conn = (struct netconn *)arg; - LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); - -#if LWIP_SO_RCVBUF - SYS_ARCH_GET(conn->recv_avail, recv_avail); - if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) || - ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) { -#else /* LWIP_SO_RCVBUF */ - if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) { -#endif /* LWIP_SO_RCVBUF */ - pbuf_free(p); - return; - } - - buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); - if (buf == NULL) { - pbuf_free(p); - return; - } else { - buf->p = p; - buf->ptr = p; - ipX_addr_set_ipaddr(ip_current_is_v6(), &buf->addr, addr); - buf->port = port; -#if LWIP_NETBUF_RECVINFO - { - /* get the UDP header - always in the first pbuf, ensured by udp_input */ - const struct udp_hdr* udphdr = ipX_next_header_ptr(); -#if LWIP_CHECKSUM_ON_COPY - buf->flags = NETBUF_FLAG_DESTADDR; -#endif /* LWIP_CHECKSUM_ON_COPY */ - ipX_addr_set(ip_current_is_v6(), &buf->toaddr, ipX_current_dest_addr()); - buf->toport_chksum = udphdr->dest; - } -#endif /* LWIP_NETBUF_RECVINFO */ - } - - len = p->tot_len; - if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { - netbuf_delete(buf); - return; - } else { -#if LWIP_SO_RCVBUF - SYS_ARCH_INC(conn->recv_avail, len); -#endif /* LWIP_SO_RCVBUF */ - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); - } -} -#endif /* LWIP_UDP */ - -#if LWIP_TCP -/** - * Receive callback function for TCP netconns. - * Posts the packet to conn->recvmbox, but doesn't delete it on errors. - * - * @see tcp.h (struct tcp_pcb.recv) for parameters and return value - */ -static err_t ICACHE_FLASH_ATTR -recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) -{ - struct netconn *conn; - u16_t len; - - LWIP_UNUSED_ARG(pcb); - LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL); - LWIP_ASSERT("recv_tcp must have an argument", arg != NULL); - conn = (struct netconn *)arg; - - if (conn == NULL) { - return ERR_VAL; - } - LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb); - - if (!sys_mbox_valid(&conn->recvmbox)) { - /* recvmbox already deleted */ - if (p != NULL) { - tcp_recved(pcb, p->tot_len); - pbuf_free(p); - } - return ERR_OK; - } - /* Unlike for UDP or RAW pcbs, don't check for available space - using recv_avail since that could break the connection - (data is already ACKed) */ - - /* don't overwrite fatal errors! */ - NETCONN_SET_SAFE_ERR(conn, err); - - if (p != NULL) { - len = p->tot_len; - } else { - len = 0; - } - - if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) { - /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */ - return ERR_MEM; - } else { -#if LWIP_SO_RCVBUF - SYS_ARCH_INC(conn->recv_avail, len); -#endif /* LWIP_SO_RCVBUF */ - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); - } - - return ERR_OK; -} - -/** - * Poll callback function for TCP netconns. - * Wakes up an application thread that waits for a connection to close - * or data to be sent. The application thread then takes the - * appropriate action to go on. - * - * Signals the conn->sem. - * netconn_close waits for conn->sem if closing failed. - * - * @see tcp.h (struct tcp_pcb.poll) for parameters and return value - */ -static err_t ICACHE_FLASH_ATTR -poll_tcp(void *arg, struct tcp_pcb *pcb) -{ - struct netconn *conn = (struct netconn *)arg; - - LWIP_UNUSED_ARG(pcb); - LWIP_ASSERT("conn != NULL", (conn != NULL)); - - if (conn->state == NETCONN_WRITE) { - lwip_netconn_do_writemore(conn); - } else if (conn->state == NETCONN_CLOSE) { - lwip_netconn_do_close_internal(conn); - } - /* @todo: implement connect timeout here? */ - - /* Did a nonblocking write fail before? Then check available write-space. */ - if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) { - /* If the queued byte- or pbuf-count drops below the configured low-water limit, - let select mark this pcb as writable again. */ - if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && - (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { - conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; - API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); - } - } - - return ERR_OK; -} - -/** - * Sent callback function for TCP netconns. - * Signals the conn->sem and calls API_EVENT. - * netconn_write waits for conn->sem if send buffer is low. - * - * @see tcp.h (struct tcp_pcb.sent) for parameters and return value - */ -static err_t ICACHE_FLASH_ATTR -sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) -{ - struct netconn *conn = (struct netconn *)arg; - - LWIP_UNUSED_ARG(pcb); - LWIP_ASSERT("conn != NULL", (conn != NULL)); - - if (conn->state == NETCONN_WRITE) { - lwip_netconn_do_writemore(conn); - } else if (conn->state == NETCONN_CLOSE) { - lwip_netconn_do_close_internal(conn); - } - - if (conn) { - /* If the queued byte- or pbuf-count drops below the configured low-water limit, - let select mark this pcb as writable again. */ - if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && - (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { - conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; - API_EVENT(conn, NETCONN_EVT_SENDPLUS, len); - } - } - - return ERR_OK; -} - -/** - * Error callback function for TCP netconns. - * Signals conn->sem, posts to all conn mboxes and calls API_EVENT. - * The application thread has then to decide what to do. - * - * @see tcp.h (struct tcp_pcb.err) for parameters - */ -static void ICACHE_FLASH_ATTR -err_tcp(void *arg, err_t err) -{ - struct netconn *conn; - enum netconn_state old_state; - SYS_ARCH_DECL_PROTECT(lev); - - conn = (struct netconn *)arg; - LWIP_ASSERT("conn != NULL", (conn != NULL)); - - conn->pcb.tcp = NULL; - - /* no check since this is always fatal! */ - SYS_ARCH_PROTECT(lev); - conn->last_err = err; - SYS_ARCH_UNPROTECT(lev); - - /* reset conn->state now before waking up other threads */ - old_state = conn->state; - conn->state = NETCONN_NONE; - - /* Notify the user layer about a connection error. Used to signal - select. */ - API_EVENT(conn, NETCONN_EVT_ERROR, 0); - /* Try to release selects pending on 'read' or 'write', too. - They will get an error if they actually try to read or write. */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); - API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); - - /* pass NULL-message to recvmbox to wake up pending recv */ - if (sys_mbox_valid(&conn->recvmbox)) { - /* use trypost to prevent deadlock */ - sys_mbox_trypost(&conn->recvmbox, NULL); - } - /* pass NULL-message to acceptmbox to wake up pending accept */ - if (sys_mbox_valid(&conn->acceptmbox)) { - /* use trypost to preven deadlock */ - sys_mbox_trypost(&conn->acceptmbox, NULL); - } - - if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) || - (old_state == NETCONN_CONNECT)) { - /* calling lwip_netconn_do_writemore/lwip_netconn_do_close_internal is not necessary - since the pcb has already been deleted! */ - int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn); - SET_NONBLOCKING_CONNECT(conn, 0); - - if (!was_nonblocking_connect) { - /* set error return code */ - LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); - conn->current_msg->err = err; - conn->current_msg = NULL; - /* wake up the waiting task */ - sys_sem_signal(&conn->op_completed); - } - } else { - LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL); - } -} - -/** - * Setup a tcp_pcb with the correct callback function pointers - * and their arguments. - * - * @param conn the TCP netconn to setup - */ -static void ICACHE_FLASH_ATTR -setup_tcp(struct netconn *conn) -{ - struct tcp_pcb *pcb; - - pcb = conn->pcb.tcp; - tcp_arg(pcb, conn); - tcp_recv(pcb, recv_tcp); - tcp_sent(pcb, sent_tcp); - tcp_poll(pcb, poll_tcp, 4); - tcp_err(pcb, err_tcp); -} - -/** - * Accept callback function for TCP netconns. - * Allocates a new netconn and posts that to conn->acceptmbox. - * - * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value - */ -static err_t ICACHE_FLASH_ATTR -accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) -{ - struct netconn *newconn; - struct netconn *conn = (struct netconn *)arg; - - LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state))); - - if (!sys_mbox_valid(&conn->acceptmbox)) { - LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n")); - return ERR_VAL; - } - - /* We have to set the callback here even though - * the new socket is unknown. conn->socket is marked as -1. */ - newconn = netconn_alloc(conn->type, conn->callback); - if (newconn == NULL) { - return ERR_MEM; - } - newconn->pcb.tcp = newpcb; - setup_tcp(newconn); - /* no protection: when creating the pcb, the netconn is not yet known - to the application thread */ - newconn->last_err = err; - - if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) { - /* When returning != ERR_OK, the pcb is aborted in tcp_process(), - so do nothing here! */ - /* remove all references to this netconn from the pcb */ - struct tcp_pcb* pcb = newconn->pcb.tcp; - tcp_arg(pcb, NULL); - tcp_recv(pcb, NULL); - tcp_sent(pcb, NULL); - tcp_poll(pcb, NULL, 4); - tcp_err(pcb, NULL); - /* remove reference from to the pcb from this netconn */ - newconn->pcb.tcp = NULL; - /* no need to drain since we know the recvmbox is empty. */ - sys_mbox_free(&newconn->recvmbox); - sys_mbox_set_invalid(&newconn->recvmbox); - netconn_free(newconn); - return ERR_MEM; - } else { - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); - } - - return ERR_OK; -} -#endif /* LWIP_TCP */ - -/** - * Create a new pcb of a specific type. - * Called from lwip_netconn_do_newconn(). - * - * @param msg the api_msg_msg describing the connection type - * @return msg->conn->err, but the return value is currently ignored - */ -static void ICACHE_FLASH_ATTR -pcb_new(struct api_msg_msg *msg) -{ - LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL); - - /* Allocate a PCB for this connection */ - switch(NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - msg->conn->pcb.raw = raw_new(msg->msg.n.proto); - if(msg->conn->pcb.raw != NULL) { - raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); - } - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - msg->conn->pcb.udp = udp_new(); - if(msg->conn->pcb.udp != NULL) { -#if LWIP_UDPLITE - if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { - udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); - } -#endif /* LWIP_UDPLITE */ - if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) { - udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); - } - udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); - } - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - msg->conn->pcb.tcp = tcp_new(); - if(msg->conn->pcb.tcp != NULL) { - setup_tcp(msg->conn); - } - break; -#endif /* LWIP_TCP */ - default: - /* Unsupported netconn type, e.g. protocol disabled */ - msg->err = ERR_VAL; - return; - } - if (msg->conn->pcb.ip == NULL) { - msg->err = ERR_MEM; - } -#if LWIP_IPV6 - else { - if (NETCONNTYPE_ISIPV6(msg->conn->type)) { - ip_set_v6(msg->conn->pcb.ip, 1); - } - } -#endif /* LWIP_IPV6 */ -} - -/** - * Create a new pcb of a specific type inside a netconn. - * Called from netconn_new_with_proto_and_callback. - * - * @param msg the api_msg_msg describing the connection type - */ -void ICACHE_FLASH_ATTR -lwip_netconn_do_newconn(struct api_msg_msg *msg) -{ - msg->err = ERR_OK; - if(msg->conn->pcb.tcp == NULL) { - pcb_new(msg); - } - /* Else? This "new" connection already has a PCB allocated. */ - /* Is this an error condition? Should it be deleted? */ - /* We currently just are happy and return. */ - - TCPIP_APIMSG_ACK(msg); -} - -/** - * Create a new netconn (of a specific type) that has a callback function. - * The corresponding pcb is NOT created! - * - * @param t the type of 'connection' to create (@see enum netconn_type) - * @param proto the IP protocol for RAW IP pcbs - * @param callback a function to call on status changes (RX available, TX'ed) - * @return a newly allocated struct netconn or - * NULL on memory error - */ -struct netconn* ICACHE_FLASH_ATTR -netconn_alloc(enum netconn_type t, netconn_callback callback) -{ - struct netconn *conn; - int size; - - conn = (struct netconn *)memp_malloc(MEMP_NETCONN); - if (conn == NULL) { - return NULL; - } - - conn->last_err = ERR_OK; - conn->type = t; - conn->pcb.tcp = NULL; - - /* If all sizes are the same, every compiler should optimize this switch to nothing, */ - switch(NETCONNTYPE_GROUP(t)) { -#if LWIP_RAW - case NETCONN_RAW: - size = DEFAULT_RAW_RECVMBOX_SIZE; - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - size = DEFAULT_UDP_RECVMBOX_SIZE; - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - size = DEFAULT_TCP_RECVMBOX_SIZE; - break; -#endif /* LWIP_TCP */ - default: - LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0); - goto free_and_return; - } - - if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) { - goto free_and_return; - } - if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) { - sys_sem_free(&conn->op_completed); - goto free_and_return; - } - -#if LWIP_TCP - sys_mbox_set_invalid(&conn->acceptmbox); -#endif - conn->state = NETCONN_NONE; -#if LWIP_SOCKET - /* initialize socket to -1 since 0 is a valid socket */ - conn->socket = -1; -#endif /* LWIP_SOCKET */ - conn->callback = callback; -#if LWIP_TCP - conn->current_msg = NULL; - conn->write_offset = 0; -#endif /* LWIP_TCP */ -#if LWIP_SO_SNDTIMEO - conn->send_timeout = 0; -#endif /* LWIP_SO_SNDTIMEO */ -#if LWIP_SO_RCVTIMEO - conn->recv_timeout = 0; -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVBUF - conn->recv_bufsize = RECV_BUFSIZE_DEFAULT; - conn->recv_avail = 0; -#endif /* LWIP_SO_RCVBUF */ - conn->flags = 0; - return conn; -free_and_return: - memp_free(MEMP_NETCONN, conn); - return NULL; -} - -/** - * Delete a netconn and all its resources. - * The pcb is NOT freed (since we might not be in the right thread context do this). - * - * @param conn the netconn to free - */ -void ICACHE_FLASH_ATTR -netconn_free(struct netconn *conn) -{ - LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL); - LWIP_ASSERT("recvmbox must be deallocated before calling this function", - !sys_mbox_valid(&conn->recvmbox)); -#if LWIP_TCP - LWIP_ASSERT("acceptmbox must be deallocated before calling this function", - !sys_mbox_valid(&conn->acceptmbox)); -#endif /* LWIP_TCP */ - - sys_sem_free(&conn->op_completed); - sys_sem_set_invalid(&conn->op_completed); - - memp_free(MEMP_NETCONN, conn); -} - -/** - * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in - * these mboxes - * - * @param conn the netconn to free - * @bytes_drained bytes drained from recvmbox - * @accepts_drained pending connections drained from acceptmbox - */ -static void ICACHE_FLASH_ATTR -netconn_drain(struct netconn *conn) -{ - void *mem; -#if LWIP_TCP - struct pbuf *p; -#endif /* LWIP_TCP */ - - /* This runs in tcpip_thread, so we don't need to lock against rx packets */ - - /* Delete and drain the recvmbox. */ - if (sys_mbox_valid(&conn->recvmbox)) { - while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) { -#if LWIP_TCP - if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) { - if(mem != NULL) { - p = (struct pbuf*)mem; - /* pcb might be set to NULL already by err_tcp() */ - if (conn->pcb.tcp != NULL) { - tcp_recved(conn->pcb.tcp, p->tot_len); - } - pbuf_free(p); - } - } else -#endif /* LWIP_TCP */ - { - netbuf_delete((struct netbuf *)mem); - } - } - sys_mbox_free(&conn->recvmbox); - sys_mbox_set_invalid(&conn->recvmbox); - } - - /* Delete and drain the acceptmbox. */ -#if LWIP_TCP - if (sys_mbox_valid(&conn->acceptmbox)) { - while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) { - struct netconn *newconn = (struct netconn *)mem; - /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ - /* pcb might be set to NULL already by err_tcp() */ - if (conn->pcb.tcp != NULL) { - tcp_accepted(conn->pcb.tcp); - } - /* drain recvmbox */ - netconn_drain(newconn); - if (newconn->pcb.tcp != NULL) { - tcp_abort(newconn->pcb.tcp); - newconn->pcb.tcp = NULL; - } - netconn_free(newconn); - } - sys_mbox_free(&conn->acceptmbox); - sys_mbox_set_invalid(&conn->acceptmbox); - } -#endif /* LWIP_TCP */ -} - -#if LWIP_TCP -/** - * Internal helper function to close a TCP netconn: since this sometimes - * doesn't work at the first attempt, this function is called from multiple - * places. - * - * @param conn the TCP netconn to close - */ -static void ICACHE_FLASH_ATTR -lwip_netconn_do_close_internal(struct netconn *conn) -{ - err_t err; - u8_t shut, shut_rx, shut_tx, close; - - LWIP_ASSERT("invalid conn", (conn != NULL)); - LWIP_ASSERT("this is for tcp netconns only", (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)); - LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE)); - LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL)); - LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); - - shut = conn->current_msg->msg.sd.shut; - shut_rx = shut & NETCONN_SHUT_RD; - shut_tx = shut & NETCONN_SHUT_WR; - /* shutting down both ends is the same as closing */ - close = shut == NETCONN_SHUT_RDWR; - - /* Set back some callback pointers */ - if (close) { - tcp_arg(conn->pcb.tcp, NULL); - } - if (conn->pcb.tcp->state == LISTEN) { - tcp_accept(conn->pcb.tcp, NULL); - } else { - /* some callbacks have to be reset if tcp_close is not successful */ - if (shut_rx) { - tcp_recv(conn->pcb.tcp, NULL); - tcp_accept(conn->pcb.tcp, NULL); - } - if (shut_tx) { - tcp_sent(conn->pcb.tcp, NULL); - } - if (close) { - tcp_poll(conn->pcb.tcp, NULL, 4); - tcp_err(conn->pcb.tcp, NULL); - } - } - /* Try to close the connection */ - if (close) { - err = tcp_close(conn->pcb.tcp); - } else { - err = tcp_shutdown(conn->pcb.tcp, shut_rx, shut_tx); - } - if (err == ERR_OK) { - /* Closing succeeded */ - conn->current_msg->err = ERR_OK; - conn->current_msg = NULL; - conn->state = NETCONN_NONE; - if (close) { - /* Set back some callback pointers as conn is going away */ - conn->pcb.tcp = NULL; - /* Trigger select() in socket layer. Make sure everybody notices activity - on the connection, error first! */ - API_EVENT(conn, NETCONN_EVT_ERROR, 0); - } - if (shut_rx) { - API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); - } - if (shut_tx) { - API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); - } - /* wake up the application task */ - sys_sem_signal(&conn->op_completed); - } else { - /* Closing failed, restore some of the callbacks */ - /* Closing of listen pcb will never fail! */ - LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN)); - tcp_sent(conn->pcb.tcp, sent_tcp); - tcp_poll(conn->pcb.tcp, poll_tcp, 4); - tcp_err(conn->pcb.tcp, err_tcp); - tcp_arg(conn->pcb.tcp, conn); - /* don't restore recv callback: we don't want to receive any more data */ - } - /* If closing didn't succeed, we get called again either - from poll_tcp or from sent_tcp */ -} -#endif /* LWIP_TCP */ - -/** - * Delete the pcb inside a netconn. - * Called from netconn_delete. - * - * @param msg the api_msg_msg pointing to the connection - */ -void ICACHE_FLASH_ATTR -lwip_netconn_do_delconn(struct api_msg_msg *msg) -{ - /* @todo TCP: abort running write/connect? */ - if ((msg->conn->state != NETCONN_NONE) && - (msg->conn->state != NETCONN_LISTEN) && - (msg->conn->state != NETCONN_CONNECT)) { - /* this only happens for TCP netconns */ - LWIP_ASSERT("NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP", - NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP); - msg->err = ERR_INPROGRESS; - } else { - LWIP_ASSERT("blocking connect in progress", - (msg->conn->state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn)); - /* Drain and delete mboxes */ - netconn_drain(msg->conn); - - if (msg->conn->pcb.tcp != NULL) { - - switch (NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - raw_remove(msg->conn->pcb.raw); - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - msg->conn->pcb.udp->recv_arg = NULL; - udp_remove(msg->conn->pcb.udp); - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && - msg->conn->write_offset == 0); - msg->conn->state = NETCONN_CLOSE; - msg->msg.sd.shut = NETCONN_SHUT_RDWR; - msg->conn->current_msg = msg; - lwip_netconn_do_close_internal(msg->conn); - /* API_EVENT is called inside lwip_netconn_do_close_internal, before releasing - the application thread, so we can return at this point! */ - return; -#endif /* LWIP_TCP */ - default: - break; - } - msg->conn->pcb.tcp = NULL; - } - /* tcp netconns don't come here! */ - - /* @todo: this lets select make the socket readable and writable, - which is wrong! errfd instead? */ - API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0); - API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); - } - if (sys_sem_valid(&msg->conn->op_completed)) { - sys_sem_signal(&msg->conn->op_completed); - } -} - -/** - * Bind a pcb contained in a netconn - * Called from netconn_bind. - * - * @param msg the api_msg_msg pointing to the connection and containing - * the IP address and port to bind to - */ -void ICACHE_FLASH_ATTR -lwip_netconn_do_bind(struct api_msg_msg *msg) -{ - if (ERR_IS_FATAL(msg->conn->last_err)) { - msg->err = msg->conn->last_err; - } else { - msg->err = ERR_VAL; - if (msg->conn->pcb.tcp != NULL) { - switch (NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - msg->err = raw_bind(msg->conn->pcb.raw, msg->msg.bc.ipaddr); - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - msg->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port); - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - msg->err = tcp_bind(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port); - break; -#endif /* LWIP_TCP */ - default: - break; - } - } - } - TCPIP_APIMSG_ACK(msg); -} - -#if LWIP_TCP -/** - * TCP callback function if a connection (opened by tcp_connect/lwip_netconn_do_connect) has - * been established (or reset by the remote host). - * - * @see tcp.h (struct tcp_pcb.connected) for parameters and return values - */ -static err_t ICACHE_FLASH_ATTR -lwip_netconn_do_connected(void *arg, struct tcp_pcb *pcb, err_t err) -{ - struct netconn *conn; - int was_blocking; - - LWIP_UNUSED_ARG(pcb); - - conn = (struct netconn *)arg; - - if (conn == NULL) { - return ERR_VAL; - } - - LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT); - LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect", - (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn)); - - if (conn->current_msg != NULL) { - conn->current_msg->err = err; - } - if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && (err == ERR_OK)) { - setup_tcp(conn); - } - was_blocking = !IN_NONBLOCKING_CONNECT(conn); - SET_NONBLOCKING_CONNECT(conn, 0); - conn->current_msg = NULL; - conn->state = NETCONN_NONE; - if (!was_blocking) { - NETCONN_SET_SAFE_ERR(conn, ERR_OK); - } - API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); - - if (was_blocking) { - sys_sem_signal(&conn->op_completed); - } - return ERR_OK; -} -#endif /* LWIP_TCP */ - -/** - * Connect a pcb contained inside a netconn - * Called from netconn_connect. - * - * @param msg the api_msg_msg pointing to the connection and containing - * the IP address and port to connect to - */ -void ICACHE_FLASH_ATTR -lwip_netconn_do_connect(struct api_msg_msg *msg) -{ - if (msg->conn->pcb.tcp == NULL) { - /* This may happen when calling netconn_connect() a second time */ - msg->err = ERR_CLSD; - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { - /* For TCP, netconn_connect() calls tcpip_apimsg(), so signal op_completed here. */ - sys_sem_signal(&msg->conn->op_completed); - return; - } - } else { - switch (NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - msg->err = raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr); - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - msg->err = udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port); - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - /* Prevent connect while doing any other action. */ - if (msg->conn->state != NETCONN_NONE) { - msg->err = ERR_ISCONN; - } else { - setup_tcp(msg->conn); - msg->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, - msg->msg.bc.port, lwip_netconn_do_connected); - if (msg->err == ERR_OK) { - u8_t non_blocking = netconn_is_nonblocking(msg->conn); - msg->conn->state = NETCONN_CONNECT; - SET_NONBLOCKING_CONNECT(msg->conn, non_blocking); - if (non_blocking) { - msg->err = ERR_INPROGRESS; - } else { - msg->conn->current_msg = msg; - /* sys_sem_signal() is called from lwip_netconn_do_connected (or err_tcp()), - * when the connection is established! */ - return; - } - } - } - /* For TCP, netconn_connect() calls tcpip_apimsg(), so signal op_completed here. */ - sys_sem_signal(&msg->conn->op_completed); - return; -#endif /* LWIP_TCP */ - default: - LWIP_ERROR("Invalid netconn type", 0, do{ msg->err = ERR_VAL; }while(0)); - break; - } - } - /* For all other protocols, netconn_connect() calls TCPIP_APIMSG(), - so use TCPIP_APIMSG_ACK() here. */ - TCPIP_APIMSG_ACK(msg); -} - -/** - * Connect a pcb contained inside a netconn - * Only used for UDP netconns. - * Called from netconn_disconnect. - * - * @param msg the api_msg_msg pointing to the connection to disconnect - */ -void ICACHE_FLASH_ATTR -lwip_netconn_do_disconnect(struct api_msg_msg *msg) -{ -#if LWIP_UDP - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { - udp_disconnect(msg->conn->pcb.udp); - msg->err = ERR_OK; - } else -#endif /* LWIP_UDP */ - { - msg->err = ERR_VAL; - } - TCPIP_APIMSG_ACK(msg); -} - -#if LWIP_TCP -/** - * Set a TCP pcb contained in a netconn into listen mode - * Called from netconn_listen. - * - * @param msg the api_msg_msg pointing to the connection - */ -void ICACHE_FLASH_ATTR -lwip_netconn_do_listen(struct api_msg_msg *msg) -{ - if (ERR_IS_FATAL(msg->conn->last_err)) { - msg->err = msg->conn->last_err; - } else { - msg->err = ERR_CONN; - if (msg->conn->pcb.tcp != NULL) { - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { - if (msg->conn->state == NETCONN_NONE) { - struct tcp_pcb* lpcb; -#if LWIP_IPV6 - if ((msg->conn->flags & NETCONN_FLAG_IPV6_V6ONLY) == 0) { -#if TCP_LISTEN_BACKLOG - lpcb = tcp_listen_dual_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog); -#else /* TCP_LISTEN_BACKLOG */ - lpcb = tcp_listen_dual(msg->conn->pcb.tcp); -#endif /* TCP_LISTEN_BACKLOG */ - } else -#endif /* LWIP_IPV6 */ - { -#if TCP_LISTEN_BACKLOG - lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog); -#else /* TCP_LISTEN_BACKLOG */ - lpcb = tcp_listen(msg->conn->pcb.tcp); -#endif /* TCP_LISTEN_BACKLOG */ - } - if (lpcb == NULL) { - /* in this case, the old pcb is still allocated */ - msg->err = ERR_MEM; - } else { - /* delete the recvmbox and allocate the acceptmbox */ - if (sys_mbox_valid(&msg->conn->recvmbox)) { - /** @todo: should we drain the recvmbox here? */ - sys_mbox_free(&msg->conn->recvmbox); - sys_mbox_set_invalid(&msg->conn->recvmbox); - } - msg->err = ERR_OK; - if (!sys_mbox_valid(&msg->conn->acceptmbox)) { - msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE); - } - if (msg->err == ERR_OK) { - msg->conn->state = NETCONN_LISTEN; - msg->conn->pcb.tcp = lpcb; - tcp_arg(msg->conn->pcb.tcp, msg->conn); - tcp_accept(msg->conn->pcb.tcp, accept_function); - } else { - /* since the old pcb is already deallocated, free lpcb now */ - tcp_close(lpcb); - msg->conn->pcb.tcp = NULL; - } - } - } - } else { - msg->err = ERR_ARG; - } - } - } - TCPIP_APIMSG_ACK(msg); -} -#endif /* LWIP_TCP */ - -/** - * Send some data on a RAW or UDP pcb contained in a netconn - * Called from netconn_send - * - * @param msg the api_msg_msg pointing to the connection - */ -void ICACHE_FLASH_ATTR -lwip_netconn_do_send(struct api_msg_msg *msg) -{ - if (ERR_IS_FATAL(msg->conn->last_err)) { - msg->err = msg->conn->last_err; - } else { - msg->err = ERR_CONN; - if (msg->conn->pcb.tcp != NULL) { - switch (NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - if (ipX_addr_isany(PCB_ISIPV6(msg->conn->pcb.ip), &msg->msg.b->addr)) { - msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); - } else { - msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, ipX_2_ip(&msg->msg.b->addr)); - } - break; -#endif -#if LWIP_UDP - case NETCONN_UDP: -#if LWIP_CHECKSUM_ON_COPY - if (ipX_addr_isany(PCB_ISIPV6(msg->conn->pcb.ip), &msg->msg.b->addr)) { - msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p, - msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); - } else { - msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p, - ipX_2_ip(&msg->msg.b->addr), msg->msg.b->port, - msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); - } -#else /* LWIP_CHECKSUM_ON_COPY */ - if (ipX_addr_isany(PCB_ISIPV6(msg->conn->pcb.ip), &msg->msg.b->addr)) { - msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p); - } else { - msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, ipX_2_ip(&msg->msg.b->addr), msg->msg.b->port); - } -#endif /* LWIP_CHECKSUM_ON_COPY */ - break; -#endif /* LWIP_UDP */ - default: - break; - } - } - } - TCPIP_APIMSG_ACK(msg); -} - -#if LWIP_TCP -/** - * Indicate data has been received from a TCP pcb contained in a netconn - * Called from netconn_recv - * - * @param msg the api_msg_msg pointing to the connection - */ -void ICACHE_FLASH_ATTR -lwip_netconn_do_recv(struct api_msg_msg *msg) -{ - msg->err = ERR_OK; - if (msg->conn->pcb.tcp != NULL) { - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { -#if TCP_LISTEN_BACKLOG - if (msg->conn->pcb.tcp->state == LISTEN) { - tcp_accepted(msg->conn->pcb.tcp); - } else -#endif /* TCP_LISTEN_BACKLOG */ - { - u32_t remaining = msg->msg.r.len; - do { - u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining; - tcp_recved(msg->conn->pcb.tcp, recved); - remaining -= recved; - }while(remaining != 0); - } - } - } - TCPIP_APIMSG_ACK(msg); -} - -/** - * See if more data needs to be written from a previous call to netconn_write. - * Called initially from lwip_netconn_do_write. If the first call can't send all data - * (because of low memory or empty send-buffer), this function is called again - * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the - * blocking application thread (waiting in netconn_write) is released. - * - * @param conn netconn (that is currently in state NETCONN_WRITE) to process - * @return ERR_OK - * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished - */ -static err_t ICACHE_FLASH_ATTR -lwip_netconn_do_writemore(struct netconn *conn) -{ - err_t err; - void *dataptr; - u16_t len, available; - u8_t write_finished = 0; - size_t diff; - u8_t dontblock = netconn_is_nonblocking(conn) || - (conn->current_msg->msg.w.apiflags & NETCONN_DONTBLOCK); - u8_t apiflags = conn->current_msg->msg.w.apiflags; - - LWIP_ASSERT("conn != NULL", conn != NULL); - LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE)); - LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); - LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL); - LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len", - conn->write_offset < conn->current_msg->msg.w.len); - -#if LWIP_SO_SNDTIMEO - if ((conn->send_timeout != 0) && - ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) { - write_finished = 1; - if (conn->write_offset == 0) { - /* nothing has been written */ - err = ERR_WOULDBLOCK; - conn->current_msg->msg.w.len = 0; - } else { - /* partial write */ - err = ERR_OK; - conn->current_msg->msg.w.len = conn->write_offset; - } - } else -#endif /* LWIP_SO_SNDTIMEO */ - { - dataptr = (u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset; - diff = conn->current_msg->msg.w.len - conn->write_offset; - if (diff > 0xffffUL) { /* max_u16_t */ - len = 0xffff; -#if LWIP_TCPIP_CORE_LOCKING - conn->flags |= NETCONN_FLAG_WRITE_DELAYED; -#endif - apiflags |= TCP_WRITE_FLAG_MORE; - } else { - len = (u16_t)diff; - } - available = tcp_sndbuf(conn->pcb.tcp); - if (available < len) { - /* don't try to write more than sendbuf */ - len = available; - if (dontblock){ - if (!len) { - err = ERR_WOULDBLOCK; - goto err_mem; - } - } else { -#if LWIP_TCPIP_CORE_LOCKING - conn->flags |= NETCONN_FLAG_WRITE_DELAYED; -#endif - apiflags |= TCP_WRITE_FLAG_MORE; - } - } - LWIP_ASSERT("lwip_netconn_do_writemore: invalid length!", ((conn->write_offset + len) <= conn->current_msg->msg.w.len)); - err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags); - /* if OK or memory error, check available space */ - if ((err == ERR_OK) || (err == ERR_MEM)) { -err_mem: - if (dontblock && (len < conn->current_msg->msg.w.len)) { - /* non-blocking write did not write everything: mark the pcb non-writable - and let poll_tcp check writable space to mark the pcb writable again */ - API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); - conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE; - } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) || - (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) { - /* The queued byte- or pbuf-count exceeds the configured low-water limit, - let select mark this pcb as non-writable. */ - API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); - } - } - - if (err == ERR_OK) { - conn->write_offset += len; - if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) { - /* return sent length */ - conn->current_msg->msg.w.len = conn->write_offset; - /* everything was written */ - write_finished = 1; - conn->write_offset = 0; - } - tcp_output(conn->pcb.tcp); - } else if ((err == ERR_MEM) && !dontblock) { - /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called - we do NOT return to the application thread, since ERR_MEM is - only a temporary error! */ - - /* tcp_write returned ERR_MEM, try tcp_output anyway */ - tcp_output(conn->pcb.tcp); - -#if LWIP_TCPIP_CORE_LOCKING - conn->flags |= NETCONN_FLAG_WRITE_DELAYED; -#endif - } else { - /* On errors != ERR_MEM, we don't try writing any more but return - the error to the application thread. */ - write_finished = 1; - conn->current_msg->msg.w.len = 0; - } - } - if (write_finished) { - /* everything was written: set back connection state - and back to application task */ - conn->current_msg->err = err; - conn->current_msg = NULL; - conn->state = NETCONN_NONE; -#if LWIP_TCPIP_CORE_LOCKING - if ((conn->flags & NETCONN_FLAG_WRITE_DELAYED) != 0) -#endif - { - sys_sem_signal(&conn->op_completed); - } - } -#if LWIP_TCPIP_CORE_LOCKING - else - return ERR_MEM; -#endif - return ERR_OK; -} -#endif /* LWIP_TCP */ - -/** - * Send some data on a TCP pcb contained in a netconn - * Called from netconn_write - * - * @param msg the api_msg_msg pointing to the connection - */ -void ICACHE_FLASH_ATTR -lwip_netconn_do_write(struct api_msg_msg *msg) -{ - if (ERR_IS_FATAL(msg->conn->last_err)) { - msg->err = msg->conn->last_err; - } else { - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { -#if LWIP_TCP - if (msg->conn->state != NETCONN_NONE) { - /* netconn is connecting, closing or in blocking write */ - msg->err = ERR_INPROGRESS; - } else if (msg->conn->pcb.tcp != NULL) { - msg->conn->state = NETCONN_WRITE; - /* set all the variables used by lwip_netconn_do_writemore */ - LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && - msg->conn->write_offset == 0); - LWIP_ASSERT("msg->msg.w.len != 0", msg->msg.w.len != 0); - msg->conn->current_msg = msg; - msg->conn->write_offset = 0; -#if LWIP_TCPIP_CORE_LOCKING - msg->conn->flags &= ~NETCONN_FLAG_WRITE_DELAYED; - if (lwip_netconn_do_writemore(msg->conn) != ERR_OK) { - LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE); - UNLOCK_TCPIP_CORE(); - sys_arch_sem_wait(&msg->conn->op_completed, 0); - LOCK_TCPIP_CORE(); - LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); - } -#else /* LWIP_TCPIP_CORE_LOCKING */ - lwip_netconn_do_writemore(msg->conn); -#endif /* LWIP_TCPIP_CORE_LOCKING */ - /* for both cases: if lwip_netconn_do_writemore was called, don't ACK the APIMSG - since lwip_netconn_do_writemore ACKs it! */ - return; - } else { - msg->err = ERR_CONN; - } -#else /* LWIP_TCP */ - msg->err = ERR_VAL; -#endif /* LWIP_TCP */ -#if (LWIP_UDP || LWIP_RAW) - } else { - msg->err = ERR_VAL; -#endif /* (LWIP_UDP || LWIP_RAW) */ - } - } - TCPIP_APIMSG_ACK(msg); -} - -/** - * Return a connection's local or remote address - * Called from netconn_getaddr - * - * @param msg the api_msg_msg pointing to the connection - */ -void ICACHE_FLASH_ATTR -lwip_netconn_do_getaddr(struct api_msg_msg *msg) -{ - if (msg->conn->pcb.ip != NULL) { - if (msg->msg.ad.local) { - ipX_addr_copy(PCB_ISIPV6(msg->conn->pcb.ip), *(msg->msg.ad.ipaddr), - msg->conn->pcb.ip->local_ip); - } else { - ipX_addr_copy(PCB_ISIPV6(msg->conn->pcb.ip), *(msg->msg.ad.ipaddr), - msg->conn->pcb.ip->remote_ip); - } - msg->err = ERR_OK; - switch (NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - if (msg->msg.ad.local) { - *(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; - } else { - /* return an error as connecting is only a helper for upper layers */ - msg->err = ERR_CONN; - } - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - if (msg->msg.ad.local) { - *(msg->msg.ad.port) = msg->conn->pcb.udp->local_port; - } else { - if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) { - msg->err = ERR_CONN; - } else { - *(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port; - } - } - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - *(msg->msg.ad.port) = (msg->msg.ad.local?msg->conn->pcb.tcp->local_port:msg->conn->pcb.tcp->remote_port); - break; -#endif /* LWIP_TCP */ - default: - LWIP_ASSERT("invalid netconn_type", 0); - break; - } - } else { - msg->err = ERR_CONN; - } - TCPIP_APIMSG_ACK(msg); -} - -/** - * Close a TCP pcb contained in a netconn - * Called from netconn_close - * - * @param msg the api_msg_msg pointing to the connection - */ -void ICACHE_FLASH_ATTR -lwip_netconn_do_close(struct api_msg_msg *msg) -{ -#if LWIP_TCP - /* @todo: abort running write/connect? */ - if ((msg->conn->state != NETCONN_NONE) && (msg->conn->state != NETCONN_LISTEN)) { - /* this only happens for TCP netconns */ - LWIP_ASSERT("NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP", - NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP); - msg->err = ERR_INPROGRESS; - } else if ((msg->conn->pcb.tcp != NULL) && (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP)) { - if ((msg->msg.sd.shut != NETCONN_SHUT_RDWR) && (msg->conn->state == NETCONN_LISTEN)) { - /* LISTEN doesn't support half shutdown */ - msg->err = ERR_CONN; - } else { - if (msg->msg.sd.shut & NETCONN_SHUT_RD) { - /* Drain and delete mboxes */ - netconn_drain(msg->conn); - } - LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && - msg->conn->write_offset == 0); - msg->conn->state = NETCONN_CLOSE; - msg->conn->current_msg = msg; - lwip_netconn_do_close_internal(msg->conn); - /* for tcp netconns, lwip_netconn_do_close_internal ACKs the message */ - return; - } - } else -#endif /* LWIP_TCP */ - { - msg->err = ERR_VAL; - } - sys_sem_signal(&msg->conn->op_completed); -} - -#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) -/** - * Join multicast groups for UDP netconns. - * Called from netconn_join_leave_group - * - * @param msg the api_msg_msg pointing to the connection - */ -void ICACHE_FLASH_ATTR -lwip_netconn_do_join_leave_group(struct api_msg_msg *msg) -{ - if (ERR_IS_FATAL(msg->conn->last_err)) { - msg->err = msg->conn->last_err; - } else { - if (msg->conn->pcb.tcp != NULL) { - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { -#if LWIP_UDP -#if LWIP_IPV6 && LWIP_IPV6_MLD - if (PCB_ISIPV6(msg->conn->pcb.udp)) { - if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { - msg->err = mld6_joingroup(ipX_2_ip6(msg->msg.jl.netif_addr), - ipX_2_ip6(msg->msg.jl.multiaddr)); - } else { - msg->err = mld6_leavegroup(ipX_2_ip6(msg->msg.jl.netif_addr), - ipX_2_ip6(msg->msg.jl.multiaddr)); - } - } - else -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ - { -#if LWIP_IGMP - if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { - msg->err = igmp_joingroup(ipX_2_ip(msg->msg.jl.netif_addr), - ipX_2_ip(msg->msg.jl.multiaddr)); - } else { - msg->err = igmp_leavegroup(ipX_2_ip(msg->msg.jl.netif_addr), - ipX_2_ip(msg->msg.jl.multiaddr)); - } -#endif /* LWIP_IGMP */ - } -#endif /* LWIP_UDP */ -#if (LWIP_TCP || LWIP_RAW) - } else { - msg->err = ERR_VAL; -#endif /* (LWIP_TCP || LWIP_RAW) */ - } - } else { - msg->err = ERR_CONN; - } - } - TCPIP_APIMSG_ACK(msg); -} -#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ - -#if LWIP_DNS -/** - * Callback function that is called when DNS name is resolved - * (or on timeout). A waiting application thread is waked up by - * signaling the semaphore. - */ -static void ICACHE_FLASH_ATTR -lwip_netconn_do_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) -{ - struct dns_api_msg *msg = (struct dns_api_msg*)arg; - - LWIP_ASSERT("DNS response for wrong host name", strcmp(msg->name, name) == 0); - LWIP_UNUSED_ARG(name); - - if (ipaddr == NULL) { - /* timeout or memory error */ - *msg->err = ERR_VAL; - } else { - /* address was resolved */ - *msg->err = ERR_OK; - *msg->addr = *ipaddr; - } - /* wake up the application task waiting in netconn_gethostbyname */ - sys_sem_signal(msg->sem); -} - -/** - * Execute a DNS query - * Called from netconn_gethostbyname - * - * @param arg the dns_api_msg pointing to the query - */ -void ICACHE_FLASH_ATTR -lwip_netconn_do_gethostbyname(void *arg) -{ - struct dns_api_msg *msg = (struct dns_api_msg*)arg; - - *msg->err = dns_gethostbyname(msg->name, msg->addr, lwip_netconn_do_dns_found, msg); - if (*msg->err != ERR_INPROGRESS) { - /* on error or immediate success, wake up the application - * task waiting in netconn_gethostbyname */ - sys_sem_signal(msg->sem); - } -} -#endif /* LWIP_DNS */ - -#endif /* LWIP_NETCONN */ diff --git a/third_party/lwip/api/err.c b/third_party/lwip/api/err.c deleted file mode 100644 index 7c5d94c..0000000 --- a/third_party/lwip/api/err.c +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @file - * Error Management module - * - */ - -/* - * 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 - * - */ - -#include "lwip/err.h" - -#ifdef LWIP_DEBUG - -static const char *err_strerr[] = { - "Ok.", /* ERR_OK 0 */ - "Out of memory error.", /* ERR_MEM -1 */ - "Buffer error.", /* ERR_BUF -2 */ - "Timeout.", /* ERR_TIMEOUT -3 */ - "Routing problem.", /* ERR_RTE -4 */ - "Operation in progress.", /* ERR_INPROGRESS -5 */ - "Illegal value.", /* ERR_VAL -6 */ - "Operation would block.", /* ERR_WOULDBLOCK -7 */ - "Address in use.", /* ERR_USE -8 */ - "Already connected.", /* ERR_ISCONN -9 */ - "Connection aborted.", /* ERR_ABRT -10 */ - "Connection reset.", /* ERR_RST -11 */ - "Connection closed.", /* ERR_CLSD -12 */ - "Not connected.", /* ERR_CONN -13 */ - "Illegal argument.", /* ERR_ARG -14 */ - "Low-level netif error.", /* ERR_IF -15 */ -}; - -/** - * Convert an lwip internal error to a string representation. - * - * @param err an lwip internal err_t - * @return a string representation for err - */ -const char * -lwip_strerr(err_t err) -{ - return err_strerr[-err]; - -} - -#endif /* LWIP_DEBUG */ diff --git a/third_party/lwip/api/netbuf.c b/third_party/lwip/api/netbuf.c deleted file mode 100644 index cbd2fcc..0000000 --- a/third_party/lwip/api/netbuf.c +++ /dev/null @@ -1,245 +0,0 @@ -/** - * @file - * Network buffer management - * - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" - -#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/netbuf.h" -#include "lwip/memp.h" - -#include - -/** - * Create (allocate) and initialize a new netbuf. - * The netbuf doesn't yet contain a packet buffer! - * - * @return a pointer to a new netbuf - * NULL on lack of memory - */ -struct ICACHE_FLASH_ATTR -netbuf *netbuf_new(void) -{ - struct netbuf *buf; - - buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); - if (buf != NULL) { - buf->p = NULL; - buf->ptr = NULL; - ipX_addr_set_any(LWIP_IPV6, &buf->addr); - buf->port = 0; -#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY -#if LWIP_CHECKSUM_ON_COPY - buf->flags = 0; -#endif /* LWIP_CHECKSUM_ON_COPY */ - buf->toport_chksum = 0; -#if LWIP_NETBUF_RECVINFO - ipX_addr_set_any(LWIP_IPV6, &buf->toaddr); -#endif /* LWIP_NETBUF_RECVINFO */ -#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ - return buf; - } else { - return NULL; - } -} - -/** - * Deallocate a netbuf allocated by netbuf_new(). - * - * @param buf pointer to a netbuf allocated by netbuf_new() - */ -void ICACHE_FLASH_ATTR -netbuf_delete(struct netbuf *buf) -{ - if (buf != NULL) { - if (buf->p != NULL) { - pbuf_free(buf->p); - buf->p = buf->ptr = NULL; - } - memp_free(MEMP_NETBUF, buf); - } -} - -/** - * Allocate memory for a packet buffer for a given netbuf. - * - * @param buf the netbuf for which to allocate a packet buffer - * @param size the size of the packet buffer to allocate - * @return pointer to the allocated memory - * NULL if no memory could be allocated - */ -void * ICACHE_FLASH_ATTR -netbuf_alloc(struct netbuf *buf, u16_t size) -{ - LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); - - /* Deallocate any previously allocated memory. */ - if (buf->p != NULL) { - pbuf_free(buf->p); - } - buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); - if (buf->p == NULL) { - return NULL; - } - LWIP_ASSERT("check that first pbuf can hold size", - (buf->p->len >= size)); - buf->ptr = buf->p; - return buf->p->payload; -} - -/** - * Free the packet buffer included in a netbuf - * - * @param buf pointer to the netbuf which contains the packet buffer to free - */ -void ICACHE_FLASH_ATTR -netbuf_free(struct netbuf *buf) -{ - LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); - if (buf->p != NULL) { - pbuf_free(buf->p); - } - buf->p = buf->ptr = NULL; -} - -/** - * Let a netbuf reference existing (non-volatile) data. - * - * @param buf netbuf which should reference the data - * @param dataptr pointer to the data to reference - * @param size size of the data - * @return ERR_OK if data is referenced - * ERR_MEM if data couldn't be referenced due to lack of memory - */ -err_t ICACHE_FLASH_ATTR -netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size) -{ - LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;); - if (buf->p != NULL) { - pbuf_free(buf->p); - } - buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); - if (buf->p == NULL) { - buf->ptr = NULL; - return ERR_MEM; - } - buf->p->payload = (void*)dataptr; - buf->p->len = buf->p->tot_len = size; - buf->ptr = buf->p; - return ERR_OK; -} - -/** - * Chain one netbuf to another (@see pbuf_chain) - * - * @param head the first netbuf - * @param tail netbuf to chain after head, freed by this function, may not be reference after returning - */ -void ICACHE_FLASH_ATTR -netbuf_chain(struct netbuf *head, struct netbuf *tail) -{ - LWIP_ERROR("netbuf_ref: invalid head", (head != NULL), return;); - LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;); - pbuf_cat(head->p, tail->p); - head->ptr = head->p; - memp_free(MEMP_NETBUF, tail); -} - -/** - * Get the data pointer and length of the data inside a netbuf. - * - * @param buf netbuf to get the data from - * @param dataptr pointer to a void pointer where to store the data pointer - * @param len pointer to an u16_t where the length of the data is stored - * @return ERR_OK if the information was retreived, - * ERR_BUF on error. - */ -err_t ICACHE_FLASH_ATTR -netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len) -{ - LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;); - LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;); - LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;); - - if (buf->ptr == NULL) { - return ERR_BUF; - } - *dataptr = buf->ptr->payload; - *len = buf->ptr->len; - return ERR_OK; -} - -/** - * Move the current data pointer of a packet buffer contained in a netbuf - * to the next part. - * The packet buffer itself is not modified. - * - * @param buf the netbuf to modify - * @return -1 if there is no next part - * 1 if moved to the next part but now there is no next part - * 0 if moved to the next part and there are still more parts - */ -s8_t ICACHE_FLASH_ATTR -netbuf_next(struct netbuf *buf) -{ - LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return -1;); - if (buf->ptr->next == NULL) { - return -1; - } - buf->ptr = buf->ptr->next; - if (buf->ptr->next == NULL) { - return 1; - } - return 0; -} - -/** - * Move the current data pointer of a packet buffer contained in a netbuf - * to the beginning of the packet. - * The packet buffer itself is not modified. - * - * @param buf the netbuf to modify - */ -void ICACHE_FLASH_ATTR -netbuf_first(struct netbuf *buf) -{ - LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); - buf->ptr = buf->p; -} - -#endif /* LWIP_NETCONN */ diff --git a/third_party/lwip/api/netdb.c b/third_party/lwip/api/netdb.c deleted file mode 100644 index 324e049..0000000 --- a/third_party/lwip/api/netdb.c +++ /dev/null @@ -1,353 +0,0 @@ -/** - * @file - * API functions for name resolving - * - */ - -/* - * 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 - * - */ - -#include "lwip/netdb.h" - -#if LWIP_DNS && LWIP_SOCKET - -#include "lwip/err.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/ip_addr.h" -#include "lwip/api.h" -#include "lwip/dns.h" - -#include -#include - -/** helper struct for gethostbyname_r to access the char* buffer */ -struct gethostbyname_r_helper { - ip_addr_t *addr_list[2]; - ip_addr_t addr; - char *aliases; -}; - -/** h_errno is exported in netdb.h for access by applications. */ -#if LWIP_DNS_API_DECLARE_H_ERRNO -int h_errno; -#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ - -/** define "hostent" variables storage: 0 if we use a static (but unprotected) - * set of variables for lwip_gethostbyname, 1 if we use a local storage */ -#ifndef LWIP_DNS_API_HOSTENT_STORAGE -#define LWIP_DNS_API_HOSTENT_STORAGE 0 -#endif - -/** define "hostent" variables storage */ -#if LWIP_DNS_API_HOSTENT_STORAGE -#define HOSTENT_STORAGE -#else -#define HOSTENT_STORAGE static -#endif /* LWIP_DNS_API_STATIC_HOSTENT */ - -/** - * Returns an entry containing addresses of address family AF_INET - * for the host with name name. - * Due to dns_gethostbyname limitations, only one address is returned. - * - * @param name the hostname to resolve - * @return an entry containing addresses of address family AF_INET - * for the host with name name - */ -struct hostent* ICACHE_FLASH_ATTR -lwip_gethostbyname(const char *name) -{ - err_t err; - ip_addr_t addr; - - /* buffer variables for lwip_gethostbyname() */ - HOSTENT_STORAGE struct hostent s_hostent; - HOSTENT_STORAGE char *s_aliases; - HOSTENT_STORAGE ip_addr_t s_hostent_addr; - HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2]; - - /* query host IP address */ - err = netconn_gethostbyname(name, &addr); - if (err != ERR_OK) { - LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); - h_errno = HOST_NOT_FOUND; - return NULL; - } - - /* fill hostent */ - s_hostent_addr = addr; - s_phostent_addr[0] = &s_hostent_addr; - s_phostent_addr[1] = NULL; - s_hostent.h_name = (char*)name; - s_hostent.h_aliases = &s_aliases; - s_hostent.h_addrtype = AF_INET; - s_hostent.h_length = sizeof(ip_addr_t); - s_hostent.h_addr_list = (char**)&s_phostent_addr; - -#if DNS_DEBUG - /* dump hostent */ - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name)); - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", s_hostent.h_aliases)); - if (s_hostent.h_aliases != NULL) { - u8_t idx; - for ( idx=0; s_hostent.h_aliases[idx]; idx++) { - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %p\n", idx, s_hostent.h_aliases[idx])); - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %s\n", idx, s_hostent.h_aliases[idx])); - } - } - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype)); - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length)); - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", s_hostent.h_addr_list)); - if (s_hostent.h_addr_list != NULL) { - u8_t idx; - for ( idx=0; s_hostent.h_addr_list[idx]; idx++) { - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx])); - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ip_ntoa((ip_addr_t*)s_hostent.h_addr_list[idx]))); - } - } -#endif /* DNS_DEBUG */ - -#if LWIP_DNS_API_HOSTENT_STORAGE - /* this function should return the "per-thread" hostent after copy from s_hostent */ - return sys_thread_hostent(&s_hostent); -#else - return &s_hostent; -#endif /* LWIP_DNS_API_HOSTENT_STORAGE */ -} - -/** - * Thread-safe variant of lwip_gethostbyname: instead of using a static - * buffer, this function takes buffer and errno pointers as arguments - * and uses these for the result. - * - * @param name the hostname to resolve - * @param ret pre-allocated struct where to store the result - * @param buf pre-allocated buffer where to store additional data - * @param buflen the size of buf - * @param result pointer to a hostent pointer that is set to ret on success - * and set to zero on error - * @param h_errnop pointer to an int where to store errors (instead of modifying - * the global h_errno) - * @return 0 on success, non-zero on error, additional error information - * is stored in *h_errnop instead of h_errno to be thread-safe - */ -int ICACHE_FLASH_ATTR -lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, - size_t buflen, struct hostent **result, int *h_errnop) -{ - err_t err; - struct gethostbyname_r_helper *h; - char *hostname; - size_t namelen; - int lh_errno; - - if (h_errnop == NULL) { - /* ensure h_errnop is never NULL */ - h_errnop = &lh_errno; - } - - if (result == NULL) { - /* not all arguments given */ - *h_errnop = EINVAL; - return -1; - } - /* first thing to do: set *result to nothing */ - *result = NULL; - if ((name == NULL) || (ret == NULL) || (buf == NULL)) { - /* not all arguments given */ - *h_errnop = EINVAL; - return -1; - } - - namelen = strlen(name); - if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) { - /* buf can't hold the data needed + a copy of name */ - *h_errnop = ERANGE; - return -1; - } - - h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf); - hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper); - - /* query host IP address */ - err = netconn_gethostbyname(name, &h->addr); - if (err != ERR_OK) { - LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); - *h_errnop = HOST_NOT_FOUND; - return -1; - } - - /* copy the hostname into buf */ - MEMCPY(hostname, name, namelen); - hostname[namelen] = 0; - - /* fill hostent */ - h->addr_list[0] = &h->addr; - h->addr_list[1] = NULL; - h->aliases = NULL; - ret->h_name = hostname; - ret->h_aliases = &h->aliases; - ret->h_addrtype = AF_INET; - ret->h_length = sizeof(ip_addr_t); - ret->h_addr_list = (char**)&h->addr_list; - - /* set result != NULL */ - *result = ret; - - /* return success */ - return 0; -} - -/** - * Frees one or more addrinfo structures returned by getaddrinfo(), along with - * any additional storage associated with those structures. If the ai_next field - * of the structure is not null, the entire list of structures is freed. - * - * @param ai struct addrinfo to free - */ -void ICACHE_FLASH_ATTR -lwip_freeaddrinfo(struct addrinfo *ai) -{ - struct addrinfo *next; - - while (ai != NULL) { - next = ai->ai_next; - memp_free(MEMP_NETDB, ai); - ai = next; - } -} - -/** - * Translates the name of a service location (for example, a host name) and/or - * a service name and returns a set of socket addresses and associated - * information to be used in creating a socket with which to address the - * specified service. - * Memory for the result is allocated internally and must be freed by calling - * lwip_freeaddrinfo()! - * - * Due to a limitation in dns_gethostbyname, only the first address of a - * host is returned. - * Also, service names are not supported (only port numbers)! - * - * @param nodename descriptive name or address string of the host - * (may be NULL -> local address) - * @param servname port number as string of NULL - * @param hints structure containing input values that set socktype and protocol - * @param res pointer to a pointer where to store the result (set to NULL on failure) - * @return 0 on success, non-zero on failure - */ -int ICACHE_FLASH_ATTR -lwip_getaddrinfo(const char *nodename, const char *servname, - const struct addrinfo *hints, struct addrinfo **res) -{ - err_t err; - ip_addr_t addr; - struct addrinfo *ai; - struct sockaddr_in *sa = NULL; - int port_nr = 0; - size_t total_size; - size_t namelen = 0; - - if (res == NULL) { - return EAI_FAIL; - } - *res = NULL; - if ((nodename == NULL) && (servname == NULL)) { - return EAI_NONAME; - } - - if (servname != NULL) { - /* service name specified: convert to port number - * @todo?: currently, only ASCII integers (port numbers) are supported! */ - port_nr = atoi(servname); - if ((port_nr <= 0) || (port_nr > 0xffff)) { - return EAI_SERVICE; - } - } - - if (nodename != NULL) { - /* service location specified, try to resolve */ - err = netconn_gethostbyname(nodename, &addr); - if (err != ERR_OK) { - return EAI_FAIL; - } - } else { - /* service location specified, use loopback address */ - ip_addr_set_loopback(&addr); - } - - total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_in); - if (nodename != NULL) { - namelen = strlen(nodename); - LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1); - total_size += namelen + 1; - } - /* If this fails, please report to lwip-devel! :-) */ - LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!", - total_size <= NETDB_ELEM_SIZE); - ai = (struct addrinfo *)memp_malloc(MEMP_NETDB); - if (ai == NULL) { - goto memerr; - } - memset(ai, 0, total_size); - sa = (struct sockaddr_in*)((u8_t*)ai + sizeof(struct addrinfo)); - /* set up sockaddr */ - inet_addr_from_ipaddr(&sa->sin_addr, &addr); - sa->sin_family = AF_INET; - sa->sin_len = sizeof(struct sockaddr_in); - sa->sin_port = htons((u16_t)port_nr); - - /* set up addrinfo */ - ai->ai_family = AF_INET; - if (hints != NULL) { - /* copy socktype & protocol from hints if specified */ - ai->ai_socktype = hints->ai_socktype; - ai->ai_protocol = hints->ai_protocol; - } - if (nodename != NULL) { - /* copy nodename to canonname if specified */ - ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); - MEMCPY(ai->ai_canonname, nodename, namelen); - ai->ai_canonname[namelen] = 0; - } - ai->ai_addrlen = sizeof(struct sockaddr_in); - ai->ai_addr = (struct sockaddr*)sa; - - *res = ai; - - return 0; -memerr: - if (ai != NULL) { - memp_free(MEMP_NETDB, ai); - } - return EAI_MEMORY; -} - -#endif /* LWIP_DNS && LWIP_SOCKET */ diff --git a/third_party/lwip/api/netifapi.c b/third_party/lwip/api/netifapi.c deleted file mode 100644 index fc96459..0000000 --- a/third_party/lwip/api/netifapi.c +++ /dev/null @@ -1,160 +0,0 @@ -/** - * @file - * Network Interface Sequential API module - * - */ - -/* - * 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 "lwip/opt.h" - -#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/netifapi.h" -#include "lwip/tcpip.h" - -/** - * Call netif_add() inside the tcpip_thread context. - */ -static void ICACHE_FLASH_ATTR -netifapi_do_netif_add(struct netifapi_msg_msg *msg) -{ - if (!netif_add( msg->netif, - msg->msg.add.ipaddr, - msg->msg.add.netmask, - msg->msg.add.gw, - msg->msg.add.state, - msg->msg.add.init, - msg->msg.add.input)) { - msg->err = ERR_IF; - } else { - msg->err = ERR_OK; - } - TCPIP_NETIFAPI_ACK(msg); -} - -/** - * Call netif_set_addr() inside the tcpip_thread context. - */ -static void ICACHE_FLASH_ATTR -netifapi_do_netif_set_addr(struct netifapi_msg_msg *msg) -{ - netif_set_addr( msg->netif, - msg->msg.add.ipaddr, - msg->msg.add.netmask, - msg->msg.add.gw); - msg->err = ERR_OK; - TCPIP_NETIFAPI_ACK(msg); -} - -/** - * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the - * tcpip_thread context. - */ -static void ICACHE_FLASH_ATTR -netifapi_do_netif_common(struct netifapi_msg_msg *msg) -{ - if (msg->msg.common.errtfunc != NULL) { - msg->err = msg->msg.common.errtfunc(msg->netif); - } else { - msg->err = ERR_OK; - msg->msg.common.voidfunc(msg->netif); - } - TCPIP_NETIFAPI_ACK(msg); -} - -/** - * Call netif_add() in a thread-safe way by running that function inside the - * tcpip_thread context. - * - * @note for params @see netif_add() - */ -err_t ICACHE_FLASH_ATTR -netifapi_netif_add(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) -{ - struct netifapi_msg msg; - msg.function = netifapi_do_netif_add; - msg.msg.netif = netif; - msg.msg.msg.add.ipaddr = ipaddr; - msg.msg.msg.add.netmask = netmask; - msg.msg.msg.add.gw = gw; - msg.msg.msg.add.state = state; - msg.msg.msg.add.init = init; - msg.msg.msg.add.input = input; - TCPIP_NETIFAPI(&msg); - return msg.msg.err; -} - -/** - * Call netif_set_addr() in a thread-safe way by running that function inside the - * tcpip_thread context. - * - * @note for params @see netif_set_addr() - */ -err_t ICACHE_FLASH_ATTR -netifapi_netif_set_addr(struct netif *netif, - ip_addr_t *ipaddr, - ip_addr_t *netmask, - ip_addr_t *gw) -{ - struct netifapi_msg msg; - msg.function = netifapi_do_netif_set_addr; - msg.msg.netif = netif; - msg.msg.msg.add.ipaddr = ipaddr; - msg.msg.msg.add.netmask = netmask; - msg.msg.msg.add.gw = gw; - TCPIP_NETIFAPI(&msg); - return msg.msg.err; -} - -/** - * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe - * way by running that function inside the tcpip_thread context. - * - * @note use only for functions where there is only "netif" parameter. - */ -err_t ICACHE_FLASH_ATTR -netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, - netifapi_errt_fn errtfunc) -{ - struct netifapi_msg msg; - msg.function = netifapi_do_netif_common; - msg.msg.netif = netif; - msg.msg.msg.common.voidfunc = voidfunc; - msg.msg.msg.common.errtfunc = errtfunc; - TCPIP_NETIFAPI(&msg); - return msg.msg.err; -} - -#endif /* LWIP_NETIF_API */ diff --git a/third_party/lwip/api/sockets.c b/third_party/lwip/api/sockets.c deleted file mode 100644 index 5e6d767..0000000 --- a/third_party/lwip/api/sockets.c +++ /dev/null @@ -1,2568 +0,0 @@ -/** - * @file - * Sockets BSD-Like API module - * - */ - -/* - * 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 - * - * Improved by Marc Boucher and David Haas - * - */ - -#include "lwip/opt.h" - -#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/api.h" -#include "lwip/sockets.h" -#include "lwip/sys.h" -#include "lwip/igmp.h" -#include "lwip/inet.h" -#include "lwip/tcp.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/tcpip.h" -#include "lwip/pbuf.h" -#if LWIP_CHECKSUM_ON_COPY -#include "lwip/inet_chksum.h" -#endif - -//#include - -#define IP4ADDR_PORT_TO_SOCKADDR(sin, ipXaddr, port) do { \ - (sin)->sin_len = sizeof(struct sockaddr_in); \ - (sin)->sin_family = AF_INET; \ - (sin)->sin_port = htons((port)); \ - inet_addr_from_ipaddr(&(sin)->sin_addr, ipX_2_ip(ipXaddr)); \ - memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0) -#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipXaddr, port) do { \ - inet_addr_to_ipaddr(ipX_2_ip(ipXaddr), &((sin)->sin_addr)); \ - (port) = ntohs((sin)->sin_port); }while(0) - -#if LWIP_IPV6 -#define IS_SOCK_ADDR_LEN_VALID(namelen) (((namelen) == sizeof(struct sockaddr_in)) || \ - ((namelen) == sizeof(struct sockaddr_in6))) -#define IS_SOCK_ADDR_TYPE_VALID(name) (((name)->sa_family == AF_INET) || \ - ((name)->sa_family == AF_INET6)) -#define SOCK_ADDR_TYPE_MATCH(name, sock) \ - ((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \ - (((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type)))) -#define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipXaddr, port) do { \ - (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ - (sin6)->sin6_family = AF_INET6; \ - (sin6)->sin6_port = htons((port)); \ - (sin6)->sin6_flowinfo = 0; \ - inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipX_2_ip6(ipXaddr)); }while(0) -#define IPXADDR_PORT_TO_SOCKADDR(isipv6, sockaddr, ipXaddr, port) do { \ - if (isipv6) { \ - IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ipXaddr, port); \ - } else { \ - IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ipXaddr, port); \ - } } while(0) -#define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipXaddr, port) do { \ - inet6_addr_to_ip6addr(ipX_2_ip6(ipXaddr), &((sin6)->sin6_addr)); \ - (port) = ntohs((sin6)->sin6_port); }while(0) -#define SOCKADDR_TO_IPXADDR_PORT(isipv6, sockaddr, ipXaddr, port) do { \ - if (isipv6) { \ - SOCKADDR6_TO_IP6ADDR_PORT((struct sockaddr_in6*)(void*)(sockaddr), ipXaddr, port); \ - } else { \ - SOCKADDR4_TO_IP4ADDR_PORT((struct sockaddr_in*)(void*)(sockaddr), ipXaddr, port); \ - } } while(0) -#define DOMAIN_TO_NETCONN_TYPE(domain, type) (((domain) == AF_INET) ? \ - (type) : (enum netconn_type)((type) | NETCONN_TYPE_IPV6)) -#else /* LWIP_IPV6 */ -#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in)) -#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET) -#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 -#define IPXADDR_PORT_TO_SOCKADDR(isipv6, sockaddr, ipXaddr, port) \ - IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ipXaddr, port) -#define SOCKADDR_TO_IPXADDR_PORT(isipv6, sockaddr, ipXaddr, port) \ - SOCKADDR4_TO_IP4ADDR_PORT((struct sockaddr_in*)(void*)(sockaddr), ipXaddr, port) -#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) -#endif /* LWIP_IPV6 */ - -#define IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) (((name)->sa_family == AF_UNSPEC) || \ - IS_SOCK_ADDR_TYPE_VALID(name)) -#define SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock) (((name)->sa_family == AF_UNSPEC) || \ - SOCK_ADDR_TYPE_MATCH(name, sock)) -#define IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % 4) == 0) - - - -#define NUM_SOCKETS MEMP_NUM_NETCONN - -/** Contains all internal pointers and states used for a socket */ -struct lwip_sock { - /** sockets currently are built on netconns, each socket has one netconn */ - struct netconn *conn; - /** data that was left from the previous read */ - void *lastdata; - /** offset in the data that was left from the previous read */ - u16_t lastoffset; - /** number of times data was received, set by event_callback(), - tested by the receive and select functions */ - s16_t rcvevent; - /** number of times data was ACKed (free send buffer), set by event_callback(), - tested by select */ - u16_t sendevent; - /** error happened for this socket, set by event_callback(), tested by select */ - u16_t errevent; - /** last error that occurred on this socket */ - int err; - /** counter of how many threads are waiting for this socket using select */ - int select_waiting; -}; - -/** Description for a task waiting in select */ -struct lwip_select_cb { - /** Pointer to the next waiting task */ - struct lwip_select_cb *next; - /** Pointer to the previous waiting task */ - struct lwip_select_cb *prev; - /** readset passed to select */ - fd_set *readset; - /** writeset passed to select */ - fd_set *writeset; - /** unimplemented: exceptset passed to select */ - fd_set *exceptset; - /** don't signal the same semaphore twice: set to 1 when signalled */ - int sem_signalled; - /** semaphore to wake up a task waiting for select */ - sys_sem_t sem; -}; - -/** This struct is used to pass data to the set/getsockopt_internal - * functions running in tcpip_thread context (only a void* is allowed) */ -struct lwip_setgetsockopt_data { - /** socket struct for which to change options */ - struct lwip_sock *sock; -#ifdef LWIP_DEBUG - /** socket index for which to change options */ - int s; -#endif /* LWIP_DEBUG */ - /** level of the option to process */ - int level; - /** name of the option to process */ - int optname; - /** set: value to set the option to - * get: value of the option is stored here */ - void *optval; - /** size of *optval */ - socklen_t *optlen; - /** if an error occures, it is temporarily stored here */ - err_t err; -}; - -/** A struct sockaddr replacement that has the same alignment as sockaddr_in/ - * sockaddr_in6 if instantiated. - */ -union sockaddr_aligned { - struct sockaddr sa; -#if LWIP_IPV6 - struct sockaddr_in6 sin6; -#endif /* LWIP_IPV6 */ - struct sockaddr_in sin; -}; - - -/** The global array of available sockets */ -static struct lwip_sock sockets[NUM_SOCKETS]; -/** The global list of tasks waiting for select */ -static struct lwip_select_cb *select_cb_list; -/** This counter is increased from lwip_select when the list is chagned - and checked in event_callback to see if it has changed. */ -static volatile int select_cb_ctr; - -/** Table to quickly map an lwIP error (err_t) to a socket error - * by using -err as an index */ -static const int 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_ISCONN -9 Already connected. */ - ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */ - ECONNRESET, /* ERR_RST -11 Connection reset. */ - ENOTCONN, /* ERR_CLSD -12 Connection closed. */ - ENOTCONN, /* ERR_CONN -13 Not connected. */ - EIO, /* ERR_ARG -14 Illegal argument. */ - -1, /* ERR_IF -15 Low-level netif error */ -}; - -#define ERR_TO_ERRNO_TABLE_SIZE \ - (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0])) - -#define err_to_errno(err) \ - ((unsigned)(-(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \ - err_to_errno_table[-(err)] : EIO) - -#ifdef ERRNO -#ifndef set_errno -#define set_errno(err) errno = (err) -#endif -#else /* ERRNO */ -#define set_errno(err) -#endif /* ERRNO */ - -#define sock_set_errno(sk, e) do { \ - sk->err = (e); \ - set_errno(sk->err); \ -} while (0) - -/* Forward delcaration of some functions */ -static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); -static void lwip_getsockopt_internal(void *arg); -static void lwip_setsockopt_internal(void *arg); - -/** - * Initialize this module. This function has to be called before any other - * functions in this module! - */ -void ICACHE_FLASH_ATTR -lwip_socket_init(void) -{ -} - -/** - * Map a externally used socket index to the internal socket representation. - * - * @param s externally used socket index - * @return struct lwip_sock for the socket or NULL if not found - */ -static struct lwip_sock * ICACHE_FLASH_ATTR -get_socket(int s) -{ - struct lwip_sock *sock; - - if ((s < 0) || (s >= NUM_SOCKETS)) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s)); - set_errno(EBADF); - return NULL; - } - - sock = &sockets[s]; - - if (!sock->conn) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s)); - set_errno(EBADF); - return NULL; - } - - return sock; -} - -/** - * Same as get_socket but doesn't set errno - * - * @param s externally used socket index - * @return struct lwip_sock for the socket or NULL if not found - */ -static struct lwip_sock * ICACHE_FLASH_ATTR -tryget_socket(int s) -{ - if ((s < 0) || (s >= NUM_SOCKETS)) { - return NULL; - } - if (!sockets[s].conn) { - return NULL; - } - return &sockets[s]; -} - -/** - * Allocate a new socket for a given netconn. - * - * @param newconn the netconn for which to allocate a socket - * @param accepted 1 if socket has been created by accept(), - * 0 if socket has been created by socket() - * @return the index of the new socket; -1 on error - */ -static int ICACHE_FLASH_ATTR -alloc_socket(struct netconn *newconn, int accepted) -{ - int i; - SYS_ARCH_DECL_PROTECT(lev); - - /* allocate a new socket identifier */ - for (i = 0; i < NUM_SOCKETS; ++i) { - /* Protect socket array */ - SYS_ARCH_PROTECT(lev); - if (!sockets[i].conn) { - sockets[i].conn = newconn; - /* The socket is not yet known to anyone, so no need to protect - after having marked it as used. */ - SYS_ARCH_UNPROTECT(lev); - sockets[i].lastdata = NULL; - sockets[i].lastoffset = 0; - sockets[i].rcvevent = 0; - /* TCP sendbuf is empty, but the socket is not yet writable until connected - * (unless it has been created by accept()). */ - sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1); - sockets[i].errevent = 0; - sockets[i].err = 0; - sockets[i].select_waiting = 0; - return i; - } - SYS_ARCH_UNPROTECT(lev); - } - return -1; -} - -/** Free a socket. The socket's netconn must have been - * delete before! - * - * @param sock the socket to free - * @param is_tcp != 0 for TCP sockets, used to free lastdata - */ -static void ICACHE_FLASH_ATTR -free_socket(struct lwip_sock *sock, int is_tcp) -{ - void *lastdata; - SYS_ARCH_DECL_PROTECT(lev); - - lastdata = sock->lastdata; - sock->lastdata = NULL; - sock->lastoffset = 0; - sock->err = 0; - - /* Protect socket array */ - SYS_ARCH_PROTECT(lev); - sock->conn = NULL; - SYS_ARCH_UNPROTECT(lev); - /* don't use 'sock' after this line, as another task might have allocated it */ - - if (lastdata != NULL) { - if (is_tcp) { - pbuf_free((struct pbuf *)lastdata); - } else { - netbuf_delete((struct netbuf *)lastdata); - } - } -} - -/* Below this, the well-known socket functions are implemented. - * Use google.com or opengroup.org to get a good description :-) - * - * Exceptions are documented! - */ - -int ICACHE_FLASH_ATTR -lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) -{ - struct lwip_sock *sock, *nsock; - struct netconn *newconn; - ipX_addr_t naddr; - u16_t port = 0; - int newsock; - err_t err; - SYS_ARCH_DECL_PROTECT(lev); - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s)); - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s)); - sock_set_errno(sock, EWOULDBLOCK); - return -1; - } - - /* wait for a new connection */ - err = netconn_accept(sock->conn, &newconn); - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err)); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { - sock_set_errno(sock, EOPNOTSUPP); - return EOPNOTSUPP; - } - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - LWIP_ASSERT("newconn != NULL", newconn != NULL); - /* Prevent automatic window updates, we do this on our own! */ - netconn_set_noautorecved(newconn, 1); - - /* Note that POSIX only requires us to check addr is non-NULL. addrlen must - * not be NULL if addr is valid. - */ - if (addr != NULL) { - union sockaddr_aligned tempaddr; - /* get the IP address and port of the remote host */ - err = netconn_peer(newconn, ipX_2_ip(&naddr), &port); - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err)); - netconn_delete(newconn); - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL); - - IPXADDR_PORT_TO_SOCKADDR(NETCONNTYPE_ISIPV6(newconn->type), &tempaddr, &naddr, port); - if (*addrlen > tempaddr.sa.sa_len) { - *addrlen = tempaddr.sa.sa_len; - } - MEMCPY(addr, &tempaddr, *addrlen); - } - - newsock = alloc_socket(newconn, 1); - if (newsock == -1) { - netconn_delete(newconn); - sock_set_errno(sock, ENFILE); - return -1; - } - LWIP_ASSERT("invalid socket index", (newsock >= 0) && (newsock < NUM_SOCKETS)); - LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback); - nsock = &sockets[newsock]; - - /* See event_callback: If data comes in right away after an accept, even - * though the server task might not have created a new socket yet. - * In that case, newconn->socket is counted down (newconn->socket--), - * so nsock->rcvevent is >= 1 here! - */ - SYS_ARCH_PROTECT(lev); - nsock->rcvevent += (s16_t)(-1 - newconn->socket); - newconn->socket = newsock; - SYS_ARCH_UNPROTECT(lev); - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d", s, newsock)); - if (addr != NULL) { - LWIP_DEBUGF(SOCKETS_DEBUG, (" addr=")); - ipX_addr_debug_print(NETCONNTYPE_ISIPV6(newconn->type), SOCKETS_DEBUG, &naddr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port)); - } - - sock_set_errno(sock, 0); - return newsock; -} - -int ICACHE_FLASH_ATTR -lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) -{ - struct lwip_sock *sock; - ipX_addr_t local_addr; - u16_t local_port; - err_t err; - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { - /* sockaddr does not match socket type (IPv4/IPv6) */ - sock_set_errno(sock, err_to_errno(ERR_VAL)); - return -1; - } - - /* check size, familiy and alignment of 'name' */ - LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && - IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)), - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - LWIP_UNUSED_ARG(namelen); - - SOCKADDR_TO_IPXADDR_PORT((name->sa_family == AF_INET6), name, &local_addr, local_port); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); - ipX_addr_debug_print(name->sa_family == AF_INET6, SOCKETS_DEBUG, &local_addr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); - - err = netconn_bind(sock->conn, ipX_2_ip(&local_addr), local_port); - - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s)); - sock_set_errno(sock, 0); - return 0; -} - -int ICACHE_FLASH_ATTR -lwip_close(int s) -{ - struct lwip_sock *sock; - int is_tcp = 0; - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s)); - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if(sock->conn != NULL) { - is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP; - } else { - LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL); - } - - netconn_delete(sock->conn); - - free_socket(sock, is_tcp); - set_errno(0); - return 0; -} - -int ICACHE_FLASH_ATTR -lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) -{ - struct lwip_sock *sock; - err_t err; - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) { - /* sockaddr does not match socket type (IPv4/IPv6) */ - sock_set_errno(sock, err_to_errno(ERR_VAL)); - return -1; - } - - /* check size, familiy and alignment of 'name' */ - LWIP_ERROR("lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) && - IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name), - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - LWIP_UNUSED_ARG(namelen); - if (name->sa_family == AF_UNSPEC) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s)); - err = netconn_disconnect(sock->conn); - } else { - ipX_addr_t remote_addr; - u16_t remote_port; - SOCKADDR_TO_IPXADDR_PORT((name->sa_family == AF_INET6), name, &remote_addr, remote_port); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s)); - ipX_addr_debug_print(name->sa_family == AF_INET6, SOCKETS_DEBUG, &remote_addr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port)); - - err = netconn_connect(sock->conn, ipX_2_ip(&remote_addr), remote_port); - } - - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err)); - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s)); - sock_set_errno(sock, 0); - return 0; -} - -/** - * Set a socket into listen mode. - * The socket may not have been used for another connection previously. - * - * @param s the socket to set to listening mode - * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1) - * @return 0 on success, non-zero on failure - */ -int ICACHE_FLASH_ATTR -lwip_listen(int s, int backlog) -{ - struct lwip_sock *sock; - err_t err; - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog)); - - sock = get_socket(s); - if (!sock) { - return -1; - } - - /* limit the "backlog" parameter to fit in an u8_t */ - backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff); - - err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog); - - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err)); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { - sock_set_errno(sock, EOPNOTSUPP); - return EOPNOTSUPP; - } - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - - sock_set_errno(sock, 0); - return 0; -} - -int ICACHE_FLASH_ATTR -lwip_recvfrom(int s, void *mem, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen) -{ - struct lwip_sock *sock; - void *buf = NULL; - struct pbuf *p; - u16_t buflen, copylen; - int off = 0; - u8_t done = 0; - err_t err; - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags)); - sock = get_socket(s); - if (!sock) { - return -1; - } - - do { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata)); - /* Check if there is data left from the last recv operation. */ - if (sock->lastdata) { - buf = sock->lastdata; - } else { - /* If this is non-blocking call, then check first */ - if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) && - (sock->rcvevent <= 0)) { - if (off > 0) { - /* update receive window */ - netconn_recved(sock->conn, (u32_t)off); - /* already received data, return that */ - sock_set_errno(sock, 0); - return off; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); - sock_set_errno(sock, EWOULDBLOCK); - return -1; - } - - /* No data was left from the previous operation, so we try to get - some from the network. */ - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { - err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf); - } else { - err = netconn_recv(sock->conn, (struct netbuf **)&buf); - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n", - err, buf)); - - if (err != ERR_OK) { - if (off > 0) { - /* update receive window */ - netconn_recved(sock->conn, (u32_t)off); - /* already received data, return that */ - sock_set_errno(sock, 0); - return off; - } - /* We should really do some error checking here. */ - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n", - s, lwip_strerr(err))); - sock_set_errno(sock, err_to_errno(err)); - if (err == ERR_CLSD) { - return 0; - } else { - return -1; - } - } - LWIP_ASSERT("buf != NULL", buf != NULL); - sock->lastdata = buf; - } - - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { - p = (struct pbuf *)buf; - } else { - p = ((struct netbuf *)buf)->p; - } - buflen = p->tot_len; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n", - buflen, len, off, sock->lastoffset)); - - buflen -= sock->lastoffset; - - if (len > buflen) { - copylen = buflen; - } else { - copylen = (u16_t)len; - } - - /* copy the contents of the received buffer into - the supplied memory pointer mem */ - pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset); - - off += copylen; - - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { - LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen); - len -= copylen; - if ( (len <= 0) || - (p->flags & PBUF_FLAG_PUSH) || - (sock->rcvevent <= 0) || - ((flags & MSG_PEEK)!=0)) { - done = 1; - } - } else { - done = 1; - } - - /* Check to see from where the data was.*/ - if (done) { -//#if !SOCKETS_DEBUG - if (from && fromlen) -//#endif /* !SOCKETS_DEBUG */ - { - u16_t port; - ipX_addr_t tmpaddr; - ipX_addr_t *fromaddr; - union sockaddr_aligned saddr; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { - fromaddr = &tmpaddr; - /* @todo: this does not work for IPv6, yet */ - netconn_getaddr(sock->conn, ipX_2_ip(fromaddr), &port, 0); - } else { - port = netbuf_fromport((struct netbuf *)buf); - fromaddr = netbuf_fromaddr_ipX((struct netbuf *)buf); - } - IPXADDR_PORT_TO_SOCKADDR(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), - &saddr, fromaddr, port); - ipX_addr_debug_print(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), - SOCKETS_DEBUG, fromaddr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off)); -//#if SOCKETS_DEBUG - if (from && fromlen) -//#endif /* SOCKETS_DEBUG */ - { - if (*fromlen > saddr.sa.sa_len) { - *fromlen = saddr.sa.sa_len; - } - MEMCPY(from, &saddr, *fromlen); - } else { - /*fix the code for setting the UDP PROTO's remote infomation by liuh at 2014.8.27*/ - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_UDP){ - sock->conn->pcb.udp->remote_ip.addr = fromaddr->addr; - sock->conn->pcb.udp->remote_port = port; - } - } - } - } - - /* If we don't peek the incoming message... */ - if ((flags & MSG_PEEK) == 0) { - /* If this is a TCP socket, check if there is data left in the - buffer. If so, it should be saved in the sock structure for next - time around. */ - if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) { - sock->lastdata = buf; - sock->lastoffset += copylen; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf)); - } else { - sock->lastdata = NULL; - sock->lastoffset = 0; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf)); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { - pbuf_free((struct pbuf *)buf); - } else { - netbuf_delete((struct netbuf *)buf); - } - } - } - } while (!done); - - if ((off > 0) && (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP)) { - /* update receive window */ - netconn_recved(sock->conn, (u32_t)off); - } - sock_set_errno(sock, 0); - return off; -} - -int ICACHE_FLASH_ATTR -lwip_read(int s, void *mem, size_t len) -{ - return lwip_recvfrom(s, mem, len, 0, NULL, NULL); -} - -int ICACHE_FLASH_ATTR -lwip_recv(int s, void *mem, size_t len, int flags) -{ - return lwip_recvfrom(s, mem, len, flags, NULL, NULL); -} - -int ICACHE_FLASH_ATTR -lwip_send(int s, const void *data, size_t size, int flags) -{ - struct lwip_sock *sock; - err_t err; - u8_t write_flags; - size_t written; - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n", - s, data, size, flags)); - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { -#if (LWIP_UDP || LWIP_RAW) - return lwip_sendto(s, data, size, flags, NULL, 0); -#else /* (LWIP_UDP || LWIP_RAW) */ - sock_set_errno(sock, err_to_errno(ERR_ARG)); - return -1; -#endif /* (LWIP_UDP || LWIP_RAW) */ - } - - write_flags = NETCONN_COPY | - ((flags & MSG_MORE) ? NETCONN_MORE : 0) | - ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); - written = 0; - err = netconn_write_partly(sock->conn, data, size, write_flags, &written); - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d written=%"SZT_F"\n", s, err, written)); - sock_set_errno(sock, err_to_errno(err)); - return (err == ERR_OK ? (int)written : -1); -} - -int ICACHE_FLASH_ATTR -lwip_sendto(int s, const void *data, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen) -{ - struct lwip_sock *sock; - err_t err; - u16_t short_size; - u16_t remote_port; -#if !LWIP_TCPIP_CORE_LOCKING - struct netbuf buf; -#endif - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { -#if LWIP_TCP - return lwip_send(s, data, size, flags); -#else /* LWIP_TCP */ - LWIP_UNUSED_ARG(flags); - sock_set_errno(sock, err_to_errno(ERR_ARG)); - return -1; -#endif /* LWIP_TCP */ - } - - if ((to != NULL) && !SOCK_ADDR_TYPE_MATCH(to, sock)) { - /* sockaddr does not match socket type (IPv4/IPv6) */ - sock_set_errno(sock, err_to_errno(ERR_VAL)); - return -1; - } - - /* @todo: split into multiple sendto's? */ - LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff); - short_size = (u16_t)size; - LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || - (IS_SOCK_ADDR_LEN_VALID(tolen) && - IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))), - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - LWIP_UNUSED_ARG(tolen); - -#if LWIP_TCPIP_CORE_LOCKING - /* Special speedup for fast UDP/RAW sending: call the raw API directly - instead of using the netconn functions. */ - { - struct pbuf* p; - ipX_addr_t *remote_addr; - ipX_addr_t remote_addr_tmp; - -#if LWIP_NETIF_TX_SINGLE_PBUF - p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_RAM); - if (p != NULL) { -#if LWIP_CHECKSUM_ON_COPY - u16_t chksum = 0; - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { - chksum = LWIP_CHKSUM_COPY(p->payload, data, short_size); - } else -#endif /* LWIP_CHECKSUM_ON_COPY */ - MEMCPY(p->payload, data, size); -#else /* LWIP_NETIF_TX_SINGLE_PBUF */ - p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_REF); - if (p != NULL) { - p->payload = (void*)data; -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - - if (to != NULL) { - SOCKADDR_TO_IPXADDR_PORT(to->sa_family == AF_INET6, - to, &remote_addr_tmp, remote_port); - remote_addr = &remote_addr_tmp; - } else { - remote_addr = &sock->conn->pcb.ip->remote_ip; -#if LWIP_UDP - if (NETCONNTYPE_GROUP(sock->conn->type) == NETCONN_UDP) { - remote_port = sock->conn->pcb.udp->remote_port; - } else -#endif /* LWIP_UDP */ - { - remote_port = 0; - } - } - - LOCK_TCPIP_CORE(); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_RAW) { -#if LWIP_RAW - err = sock->conn->last_err = raw_sendto(sock->conn->pcb.raw, p, ipX_2_ip(remote_addr)); -#else /* LWIP_RAW */ - err = ERR_ARG; -#endif /* LWIP_RAW */ - } -#if LWIP_UDP && LWIP_RAW - else -#endif /* LWIP_UDP && LWIP_RAW */ - { -#if LWIP_UDP -#if LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF - err = sock->conn->last_err = udp_sendto_chksum(sock->conn->pcb.udp, p, - ipX_2_ip(remote_addr), remote_port, 1, chksum); -#else /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */ - err = sock->conn->last_err = udp_sendto(sock->conn->pcb.udp, p, - ipX_2_ip(remote_addr), remote_port); -#endif /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */ -#else /* LWIP_UDP */ - err = ERR_ARG; -#endif /* LWIP_UDP */ - } - UNLOCK_TCPIP_CORE(); - - pbuf_free(p); - } else { - err = ERR_MEM; - } - } -#else /* LWIP_TCPIP_CORE_LOCKING */ - /* initialize a buffer */ - buf.p = buf.ptr = NULL; -#if LWIP_CHECKSUM_ON_COPY - buf.flags = 0; -#endif /* LWIP_CHECKSUM_ON_COPY */ - if (to) { - SOCKADDR_TO_IPXADDR_PORT((to->sa_family) == AF_INET6, to, &buf.addr, remote_port); - } else { - /*fix the code for getting the UDP proto's remote information by liuh at 2014.8.27*/ -// ipX_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_UDP){ - buf.addr.addr = sock->conn->pcb.udp->remote_ip.addr; - remote_port = sock->conn->pcb.udp->remote_port; - } else { - remote_port = 0; - ipX_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr); - } - } - netbuf_fromport(&buf) = remote_port; - - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=", - s, data, short_size, flags)); - ipX_addr_debug_print(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), - SOCKETS_DEBUG, &buf.addr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); - - /* make the buffer point to the data that should be sent */ -#if LWIP_NETIF_TX_SINGLE_PBUF - /* Allocate a new netbuf and copy the data into it. */ - if (netbuf_alloc(&buf, short_size) == NULL) { - err = ERR_MEM; - } else { -#if LWIP_CHECKSUM_ON_COPY - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { - u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); - netbuf_set_chksum(&buf, chksum); - err = ERR_OK; - } else -#endif /* LWIP_CHECKSUM_ON_COPY */ - { - err = netbuf_take(&buf, data, short_size); - } - } -#else /* LWIP_NETIF_TX_SINGLE_PBUF */ - err = netbuf_ref(&buf, data, short_size); -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - if (err == ERR_OK) { - /* send the data */ - err = netconn_send(sock->conn, &buf); - } - - /* deallocated the buffer */ - netbuf_free(&buf); -#endif /* LWIP_TCPIP_CORE_LOCKING */ - sock_set_errno(sock, err_to_errno(err)); - return (err == ERR_OK ? short_size : -1); -} - -int ICACHE_FLASH_ATTR -lwip_socket(int domain, int type, int protocol) -{ - struct netconn *conn; - int i; - -#if !LWIP_IPV6 - LWIP_UNUSED_ARG(domain); /* @todo: check this */ -#endif /* LWIP_IPV6 */ - - /* create a netconn */ - switch (type) { - case SOCK_RAW: - conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), - (u8_t)protocol, event_callback); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", - domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); - break; - case SOCK_DGRAM: - conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, - ((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP)) , - event_callback); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", - domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); - break; - case SOCK_STREAM: - conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_TCP), event_callback); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", - domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); - if (conn != NULL) { - /* Prevent automatic window updates, we do this on our own! */ - netconn_set_noautorecved(conn, 1); - } - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", - domain, type, protocol)); - set_errno(EINVAL); - return -1; - } - - if (!conn) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n")); - set_errno(ENOBUFS); - return -1; - } - - i = alloc_socket(conn, 0); - - if (i == -1) { - netconn_delete(conn); - set_errno(ENFILE); - return -1; - } - conn->socket = i; - LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); - set_errno(0); - return i; -} - -int ICACHE_FLASH_ATTR -lwip_write(int s, const void *data, size_t size) -{ - return lwip_send(s, data, size, 0); -} - -/** - * Go through the readset and writeset lists and see which socket of the sockets - * set in the sets has events. On return, readset, writeset and exceptset have - * the sockets enabled that had events. - * - * exceptset is not used for now!!! - * - * @param maxfdp1 the highest socket index in the sets - * @param readset_in: set of sockets to check for read events - * @param writeset_in: set of sockets to check for write events - * @param exceptset_in: set of sockets to check for error events - * @param readset_out: set of sockets that had read events - * @param writeset_out: set of sockets that had write events - * @param exceptset_out: set os sockets that had error events - * @return number of sockets that had events (read/write/exception) (>= 0) - */ -static int ICACHE_FLASH_ATTR -lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in, - fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out) -{ - int i, nready = 0; - fd_set lreadset, lwriteset, lexceptset; - struct lwip_sock *sock; - SYS_ARCH_DECL_PROTECT(lev); - - FD_ZERO(&lreadset); - FD_ZERO(&lwriteset); - FD_ZERO(&lexceptset); - - /* Go through each socket in each list to count number of sockets which - currently match */ - for(i = 0; i < maxfdp1; i++) { - void* lastdata = NULL; - s16_t rcvevent = 0; - u16_t sendevent = 0; - u16_t errevent = 0; - /* First get the socket's status (protected)... */ - SYS_ARCH_PROTECT(lev); - sock = tryget_socket(i); - if (sock != NULL) { - lastdata = sock->lastdata; - rcvevent = sock->rcvevent; - sendevent = sock->sendevent; - errevent = sock->errevent; - } - SYS_ARCH_UNPROTECT(lev); - /* ... then examine it: */ - /* See if netconn of this socket is ready for read */ - if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) { - FD_SET(i, &lreadset); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); - nready++; - } - /* See if netconn of this socket is ready for write */ - if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) { - FD_SET(i, &lwriteset); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i)); - nready++; - } - /* See if netconn of this socket had an error */ - if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) { - FD_SET(i, &lexceptset); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i)); - nready++; - } - } - /* copy local sets to the ones provided as arguments */ - *readset_out = lreadset; - *writeset_out = lwriteset; - *exceptset_out = lexceptset; - - LWIP_ASSERT("nready >= 0", nready >= 0); - return nready; -} - -/** - * Processing exceptset is not yet implemented. - */ -int ICACHE_FLASH_ATTR -lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, - struct timeval *timeout) -{ - u32_t waitres = 0; - int nready; - fd_set lreadset, lwriteset, lexceptset; - u32_t msectimeout; - struct lwip_select_cb select_cb; - err_t err; - int i; - SYS_ARCH_DECL_PROTECT(lev); - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n", - maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, - timeout ? (s32_t)timeout->tv_sec : (s32_t)-1, - timeout ? (s32_t)timeout->tv_usec : (s32_t)-1)); - - /* Go through each socket in each list to count number of sockets which - currently match */ - nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); - - /* If we don't have any current events, then suspend if we are supposed to */ - if (!nready) { - if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); - /* This is OK as the local fdsets are empty and nready is zero, - or we would have returned earlier. */ - goto return_copy_fdsets; - } - - /* None ready: add our semaphore to list: - We don't actually need any dynamic memory. Our entry on the - list is only valid while we are in this function, so it's ok - to use local variables. */ - - select_cb.next = NULL; - select_cb.prev = NULL; - select_cb.readset = readset; - select_cb.writeset = writeset; - select_cb.exceptset = exceptset; - select_cb.sem_signalled = 0; - err = sys_sem_new(&select_cb.sem, 0); - if (err != ERR_OK) { - /* failed to create semaphore */ - set_errno(ENOMEM); - return -1; - } - - /* Protect the select_cb_list */ - SYS_ARCH_PROTECT(lev); - - /* Put this select_cb on top of list */ - select_cb.next = select_cb_list; - if (select_cb_list != NULL) { - select_cb_list->prev = &select_cb; - } - select_cb_list = &select_cb; - /* Increasing this counter tells even_callback that the list has changed. */ - select_cb_ctr++; - - /* Now we can safely unprotect */ - SYS_ARCH_UNPROTECT(lev); - - /* Increase select_waiting for each socket we are interested in */ - for(i = 0; i < maxfdp1; i++) { - if ((readset && FD_ISSET(i, readset)) || - (writeset && FD_ISSET(i, writeset)) || - (exceptset && FD_ISSET(i, exceptset))) { - struct lwip_sock *sock = tryget_socket(i); - LWIP_ASSERT("sock != NULL", sock != NULL); - SYS_ARCH_PROTECT(lev); - sock->select_waiting++; - LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); - SYS_ARCH_UNPROTECT(lev); - } - } - - /* Call lwip_selscan again: there could have been events between - the last scan (whithout us on the list) and putting us on the list! */ - nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); - if (!nready) { - /* Still none ready, just wait to be woken */ - if (timeout == 0) { - /* Wait forever */ - msectimeout = 0; - } else { - msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000)); - if (msectimeout == 0) { - /* Wait 1ms at least (0 means wait forever) */ - msectimeout = 1; - } - } - - waitres = sys_arch_sem_wait(&select_cb.sem, msectimeout); - } - /* Increase select_waiting for each socket we are interested in */ - for(i = 0; i < maxfdp1; i++) { - if ((readset && FD_ISSET(i, readset)) || - (writeset && FD_ISSET(i, writeset)) || - (exceptset && FD_ISSET(i, exceptset))) { - struct lwip_sock *sock = tryget_socket(i); - LWIP_ASSERT("sock != NULL", sock != NULL); - SYS_ARCH_PROTECT(lev); - sock->select_waiting--; - LWIP_ASSERT("sock->select_waiting >= 0", sock->select_waiting >= 0); - SYS_ARCH_UNPROTECT(lev); - } - } - /* Take us off the list */ - SYS_ARCH_PROTECT(lev); - if (select_cb.next != NULL) { - select_cb.next->prev = select_cb.prev; - } - if (select_cb_list == &select_cb) { - LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL); - select_cb_list = select_cb.next; - } else { - LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL); - select_cb.prev->next = select_cb.next; - } - /* Increasing this counter tells even_callback that the list has changed. */ - select_cb_ctr++; - SYS_ARCH_UNPROTECT(lev); - - sys_sem_free(&select_cb.sem); - if (waitres == SYS_ARCH_TIMEOUT) { - /* Timeout */ - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); - /* This is OK as the local fdsets are empty and nready is zero, - or we would have returned earlier. */ - goto return_copy_fdsets; - } - - /* See what's set */ - nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); - } - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); -return_copy_fdsets: - set_errno(0); - if (readset) { - *readset = lreadset; - } - if (writeset) { - *writeset = lwriteset; - } - if (exceptset) { - *exceptset = lexceptset; - } - return nready; -} - -/** - * Callback registered in the netconn layer for each socket-netconn. - * Processes recvevent (data available) and wakes up tasks waiting for select. - */ -static void ICACHE_FLASH_ATTR -event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) -{ - int s; - struct lwip_sock *sock; - struct lwip_select_cb *scb; - int last_select_cb_ctr; - SYS_ARCH_DECL_PROTECT(lev); - - LWIP_UNUSED_ARG(len); - - /* Get socket */ - if (conn) { - s = conn->socket; - if (s < 0) { - /* Data comes in right away after an accept, even though - * the server task might not have created a new socket yet. - * Just count down (or up) if that's the case and we - * will use the data later. Note that only receive events - * can happen before the new socket is set up. */ - SYS_ARCH_PROTECT(lev); - if (conn->socket < 0) { - if (evt == NETCONN_EVT_RCVPLUS) { - conn->socket--; - } - SYS_ARCH_UNPROTECT(lev); - return; - } - s = conn->socket; - SYS_ARCH_UNPROTECT(lev); - } - - sock = get_socket(s); - if (!sock) { - return; - } - } else { - return; - } - - SYS_ARCH_PROTECT(lev); - /* Set event as required */ - switch (evt) { - case NETCONN_EVT_RCVPLUS: - sock->rcvevent++; - break; - case NETCONN_EVT_RCVMINUS: - sock->rcvevent--; - break; - case NETCONN_EVT_SENDPLUS: - sock->sendevent = 1; - break; - case NETCONN_EVT_SENDMINUS: - sock->sendevent = 0; - break; - case NETCONN_EVT_ERROR: - sock->errevent = 1; - break; - default: - LWIP_ASSERT("unknown event", 0); - break; - } - - if (sock->select_waiting == 0) { - /* noone is waiting for this socket, no need to check select_cb_list */ - SYS_ARCH_UNPROTECT(lev); - return; - } - - /* Now decide if anyone is waiting for this socket */ - /* NOTE: This code goes through the select_cb_list list multiple times - ONLY IF a select was actually waiting. We go through the list the number - of waiting select calls + 1. This list is expected to be small. */ - - /* At this point, SYS_ARCH is still protected! */ -again: - for (scb = select_cb_list; scb != NULL; scb = scb->next) { - if (scb->sem_signalled == 0) { - /* semaphore not signalled yet */ - int do_signal = 0; - /* Test this select call for our socket */ - if (sock->rcvevent > 0) { - if (scb->readset && FD_ISSET(s, scb->readset)) { - do_signal = 1; - } - } - if (sock->sendevent != 0) { - if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) { - do_signal = 1; - } - } - if (sock->errevent != 0) { - if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) { - do_signal = 1; - } - } - if (do_signal) { - scb->sem_signalled = 1; - /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might - lead to the select thread taking itself off the list, invalidagin the semaphore. */ - sys_sem_signal(&scb->sem); - } - } - /* unlock interrupts with each step */ - last_select_cb_ctr = select_cb_ctr; - SYS_ARCH_UNPROTECT(lev); - /* this makes sure interrupt protection time is short */ - SYS_ARCH_PROTECT(lev); - if (last_select_cb_ctr != select_cb_ctr) { - /* someone has changed select_cb_list, restart at the beginning */ - goto again; - } - } - SYS_ARCH_UNPROTECT(lev); -} - -/** - * Unimplemented: Close one end of a full-duplex connection. - * Currently, the full connection is closed. - */ -int ICACHE_FLASH_ATTR -lwip_shutdown(int s, int how) -{ - struct lwip_sock *sock; - err_t err; - u8_t shut_rx = 0, shut_tx = 0; - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (sock->conn != NULL) { - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { - sock_set_errno(sock, EOPNOTSUPP); - return EOPNOTSUPP; - } - } else { - sock_set_errno(sock, ENOTCONN); - return ENOTCONN; - } - - if (how == SHUT_RD) { - shut_rx = 1; - } else if (how == SHUT_WR) { - shut_tx = 1; - } else if(how == SHUT_RDWR) { - shut_rx = 1; - shut_tx = 1; - } else { - sock_set_errno(sock, EINVAL); - return EINVAL; - } - err = netconn_shutdown(sock->conn, shut_rx, shut_tx); - - sock_set_errno(sock, err_to_errno(err)); - return (err == ERR_OK ? 0 : -1); -} - -static int ICACHE_FLASH_ATTR -lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) -{ - struct lwip_sock *sock; - union sockaddr_aligned saddr; - ipX_addr_t naddr; - u16_t port; - - sock = get_socket(s); - if (!sock) { - return -1; - } - - /* get the IP address and port */ - /* @todo: this does not work for IPv6, yet */ - netconn_getaddr(sock->conn, ipX_2_ip(&naddr), &port, local); - IPXADDR_PORT_TO_SOCKADDR(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), - &saddr, &naddr, port); - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s)); - ipX_addr_debug_print(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), - SOCKETS_DEBUG, &naddr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port)); - - if (*namelen > saddr.sa.sa_len) { - *namelen = saddr.sa.sa_len; - } - MEMCPY(name, &saddr, *namelen); - - sock_set_errno(sock, 0); - return 0; -} - -int ICACHE_FLASH_ATTR -lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen) -{ - return lwip_getaddrname(s, name, namelen, 0); -} - -int ICACHE_FLASH_ATTR -lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen) -{ - return lwip_getaddrname(s, name, namelen, 1); -} - -int ICACHE_FLASH_ATTR -lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) -{ - err_t err = ERR_OK; - struct lwip_sock *sock = get_socket(s); - struct lwip_setgetsockopt_data data; - - if (!sock) { - return -1; - } - - if ((NULL == optval) || (NULL == optlen)) { - sock_set_errno(sock, EFAULT); - return -1; - } - - /* Do length and type checks for the various options first, to keep it readable. */ - switch (level) { - -/* Level: SOL_SOCKET */ - case SOL_SOCKET: - switch (optname) { - - case SO_ACCEPTCONN: - case SO_BROADCAST: - /* UNIMPL case SO_DEBUG: */ - /* UNIMPL case SO_DONTROUTE: */ - case SO_ERROR: - case SO_KEEPALIVE: - /* UNIMPL case SO_CONTIMEO: */ -#if LWIP_SO_SNDTIMEO - case SO_SNDTIMEO: -#endif /* LWIP_SO_SNDTIMEO */ -#if LWIP_SO_RCVTIMEO - case SO_RCVTIMEO: -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVBUF - case SO_RCVBUF: -#endif /* LWIP_SO_RCVBUF */ - /* UNIMPL case SO_OOBINLINE: */ - /* UNIMPL case SO_SNDBUF: */ - /* UNIMPL case SO_RCVLOWAT: */ - /* UNIMPL case SO_SNDLOWAT: */ -#if SO_REUSE - case SO_REUSEADDR: - case SO_REUSEPORT: -#endif /* SO_REUSE */ - case SO_TYPE: - /* UNIMPL case SO_USELOOPBACK: */ - if (*optlen < sizeof(int)) { - err = EINVAL; - } - break; - - case SO_NO_CHECK: - if (*optlen < sizeof(int)) { - err = EINVAL; - } -#if LWIP_UDP - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP || - ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) { - /* this flag is only available for UDP, not for UDP lite */ - err = EAFNOSUPPORT; - } -#endif /* LWIP_UDP */ - break; - - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - } /* switch (optname) */ - break; - -/* Level: IPPROTO_IP */ - case IPPROTO_IP: - switch (optname) { - /* UNIMPL case IP_HDRINCL: */ - /* UNIMPL case IP_RCVDSTADDR: */ - /* UNIMPL case IP_RCVIF: */ - case IP_TTL: - case IP_TOS: - if (*optlen < sizeof(int)) { - err = EINVAL; - } - break; -#if LWIP_IGMP - case IP_MULTICAST_TTL: - if (*optlen < sizeof(u8_t)) { - err = EINVAL; - } - break; - case IP_MULTICAST_IF: - if (*optlen < sizeof(struct in_addr)) { - err = EINVAL; - } - break; - case IP_MULTICAST_LOOP: - if (*optlen < sizeof(u8_t)) { - err = EINVAL; - } - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { - err = EAFNOSUPPORT; - } - break; -#endif /* LWIP_IGMP */ - - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - } /* switch (optname) */ - break; - -#if LWIP_TCP -/* Level: IPPROTO_TCP */ - case IPPROTO_TCP: - if (*optlen < sizeof(int)) { - err = EINVAL; - break; - } - - /* If this is no TCP socket, ignore any options. */ - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) - return 0; - - switch (optname) { - case TCP_NODELAY: - case TCP_KEEPALIVE: -#if LWIP_TCP_KEEPALIVE - case TCP_KEEPIDLE: - case TCP_KEEPINTVL: - case TCP_KEEPCNT: -#endif /* LWIP_TCP_KEEPALIVE */ - break; - - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - } /* switch (optname) */ - break; -#endif /* LWIP_TCP */ - -#if LWIP_IPV6 -/* Level: IPPROTO_IPV6 */ - case IPPROTO_IPV6: - switch (optname) { - case IPV6_V6ONLY: - if (*optlen < sizeof(int)) { - err = EINVAL; - } - /* @todo: this does not work for datagram sockets, yet */ - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) - return 0; - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - } /* switch (optname) */ - break; -#endif /* LWIP_IPV6 */ - -#if LWIP_UDP && LWIP_UDPLITE -/* Level: IPPROTO_UDPLITE */ - case IPPROTO_UDPLITE: - if (*optlen < sizeof(int)) { - err = EINVAL; - break; - } - - /* If this is no UDP lite socket, ignore any options. */ - if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { - return 0; - } - - switch (optname) { - case UDPLITE_SEND_CSCOV: - case UDPLITE_RECV_CSCOV: - break; - - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - } /* switch (optname) */ - break; -#endif /* LWIP_UDP && LWIP_UDPLITE*/ -/* UNDEFINED LEVEL */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", - s, level, optname)); - err = ENOPROTOOPT; - } /* switch */ - - - if (err != ERR_OK) { - sock_set_errno(sock, err); - return -1; - } - - /* Now do the actual option processing */ - data.sock = sock; -#ifdef LWIP_DEBUG - data.s = s; -#endif /* LWIP_DEBUG */ - data.level = level; - data.optname = optname; - data.optval = optval; - data.optlen = optlen; - data.err = err; - tcpip_callback(lwip_getsockopt_internal, &data); - sys_arch_sem_wait(&sock->conn->op_completed, 0); - /* maybe lwip_getsockopt_internal has changed err */ - err = data.err; - - sock_set_errno(sock, err); - return err ? -1 : 0; -} - -static void ICACHE_FLASH_ATTR -lwip_getsockopt_internal(void *arg) -{ - struct lwip_sock *sock; -#ifdef LWIP_DEBUG - int s; -#endif /* LWIP_DEBUG */ - int level, optname; - void *optval; - struct lwip_setgetsockopt_data *data; - - LWIP_ASSERT("arg != NULL", arg != NULL); - - data = (struct lwip_setgetsockopt_data*)arg; - sock = data->sock; -#ifdef LWIP_DEBUG - s = data->s; -#endif /* LWIP_DEBUG */ - level = data->level; - optname = data->optname; - optval = data->optval; - - switch (level) { - -/* Level: SOL_SOCKET */ - case SOL_SOCKET: - switch (optname) { - - /* The option flags */ - case SO_ACCEPTCONN: - case SO_BROADCAST: - /* UNIMPL case SO_DEBUG: */ - /* UNIMPL case SO_DONTROUTE: */ - case SO_KEEPALIVE: - /* UNIMPL case SO_OOBINCLUDE: */ -#if SO_REUSE - case SO_REUSEADDR: - case SO_REUSEPORT: -#endif /* SO_REUSE */ - /*case SO_USELOOPBACK: UNIMPL */ - *(int*)optval = ip_get_option(sock->conn->pcb.ip, optname); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", - s, optname, (*(int*)optval?"on":"off"))); - break; - - case SO_TYPE: - switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) { - case NETCONN_RAW: - *(int*)optval = SOCK_RAW; - break; - case NETCONN_TCP: - *(int*)optval = SOCK_STREAM; - break; - case NETCONN_UDP: - *(int*)optval = SOCK_DGRAM; - break; - default: /* unrecognized socket type */ - *(int*)optval = netconn_type(sock->conn); - LWIP_DEBUGF(SOCKETS_DEBUG, - ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", - s, *(int *)optval)); - } /* switch (netconn_type(sock->conn)) */ - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", - s, *(int *)optval)); - break; - - case SO_ERROR: - /* only overwrite ERR_OK or tempoary errors */ - if ((sock->err == 0) || (sock->err == EINPROGRESS)) { - sock_set_errno(sock, err_to_errno(sock->conn->last_err)); - } - *(int *)optval = sock->err; - sock->err = 0; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", - s, *(int *)optval)); - break; - -#if LWIP_SO_SNDTIMEO - case SO_SNDTIMEO: - *(int *)optval = netconn_get_sendtimeout(sock->conn); - break; -#endif /* LWIP_SO_SNDTIMEO */ -#if LWIP_SO_RCVTIMEO - case SO_RCVTIMEO: - *(int *)optval = netconn_get_recvtimeout(sock->conn); - break; -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVBUF - case SO_RCVBUF: - *(int *)optval = netconn_get_recvbufsize(sock->conn); - break; -#endif /* LWIP_SO_RCVBUF */ -#if LWIP_UDP - case SO_NO_CHECK: - *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0; - break; -#endif /* LWIP_UDP*/ - default: - LWIP_ASSERT("unhandled optname", 0); - break; - } /* switch (optname) */ - break; - -/* Level: IPPROTO_IP */ - case IPPROTO_IP: - switch (optname) { - case IP_TTL: - *(int*)optval = sock->conn->pcb.ip->ttl; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", - s, *(int *)optval)); - break; - case IP_TOS: - *(int*)optval = sock->conn->pcb.ip->tos; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", - s, *(int *)optval)); - break; -#if LWIP_IGMP - case IP_MULTICAST_TTL: - *(u8_t*)optval = sock->conn->pcb.ip->ttl; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", - s, *(int *)optval)); - break; - case IP_MULTICAST_IF: - inet_addr_from_ipaddr((struct in_addr*)optval, &sock->conn->pcb.udp->multicast_ip); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n", - s, *(u32_t *)optval)); - break; - case IP_MULTICAST_LOOP: - if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) { - *(u8_t*)optval = 1; - } else { - *(u8_t*)optval = 0; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n", - s, *(int *)optval)); - break; -#endif /* LWIP_IGMP */ - default: - LWIP_ASSERT("unhandled optname", 0); - break; - } /* switch (optname) */ - break; - -#if LWIP_TCP -/* Level: IPPROTO_TCP */ - case IPPROTO_TCP: - switch (optname) { - case TCP_NODELAY: - *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", - s, (*(int*)optval)?"on":"off") ); - break; - case TCP_KEEPALIVE: - *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", - s, *(int *)optval)); - break; - -#if LWIP_TCP_KEEPALIVE - case TCP_KEEPIDLE: - *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n", - s, *(int *)optval)); - break; - case TCP_KEEPINTVL: - *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n", - s, *(int *)optval)); - break; - case TCP_KEEPCNT: - *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n", - s, *(int *)optval)); - break; -#endif /* LWIP_TCP_KEEPALIVE */ - default: - LWIP_ASSERT("unhandled optname", 0); - break; - } /* switch (optname) */ - break; -#endif /* LWIP_TCP */ - -#if LWIP_IPV6 -/* Level: IPPROTO_IPV6 */ - case IPPROTO_IPV6: - switch (optname) { - case IPV6_V6ONLY: - *(int*)optval = ((sock->conn->flags & NETCONN_FLAG_IPV6_V6ONLY) ? 1 : 0); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n", - s, *(int *)optval)); - break; - default: - LWIP_ASSERT("unhandled optname", 0); - break; - } /* switch (optname) */ - break; -#endif /* LWIP_IPV6 */ - -#if LWIP_UDP && LWIP_UDPLITE - /* Level: IPPROTO_UDPLITE */ - case IPPROTO_UDPLITE: - switch (optname) { - case UDPLITE_SEND_CSCOV: - *(int*)optval = sock->conn->pcb.udp->chksum_len_tx; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n", - s, (*(int*)optval)) ); - break; - case UDPLITE_RECV_CSCOV: - *(int*)optval = sock->conn->pcb.udp->chksum_len_rx; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n", - s, (*(int*)optval)) ); - break; - default: - LWIP_ASSERT("unhandled optname", 0); - break; - } /* switch (optname) */ - break; -#endif /* LWIP_UDP */ - default: - LWIP_ASSERT("unhandled level", 0); - break; - } /* switch (level) */ - sys_sem_signal(&sock->conn->op_completed); -} - -int ICACHE_FLASH_ATTR -lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) -{ - struct lwip_sock *sock = get_socket(s); - err_t err = ERR_OK; - struct lwip_setgetsockopt_data data; - - if (!sock) { - return -1; - } - - if (NULL == optval) { - sock_set_errno(sock, EFAULT); - return -1; - } - - /* Do length and type checks for the various options first, to keep it readable. */ - switch (level) { - -/* Level: SOL_SOCKET */ - case SOL_SOCKET: - switch (optname) { - - case SO_BROADCAST: - /* UNIMPL case SO_DEBUG: */ - /* UNIMPL case SO_DONTROUTE: */ - case SO_KEEPALIVE: - /* UNIMPL case case SO_CONTIMEO: */ -#if LWIP_SO_SNDTIMEO - case SO_SNDTIMEO: -#endif /* LWIP_SO_SNDTIMEO */ -#if LWIP_SO_RCVTIMEO - case SO_RCVTIMEO: -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVBUF - case SO_RCVBUF: -#endif /* LWIP_SO_RCVBUF */ - /* UNIMPL case SO_OOBINLINE: */ - /* UNIMPL case SO_SNDBUF: */ - /* UNIMPL case SO_RCVLOWAT: */ - /* UNIMPL case SO_SNDLOWAT: */ -#if SO_REUSE - case SO_REUSEADDR: - case SO_REUSEPORT: -#endif /* SO_REUSE */ - /* UNIMPL case SO_USELOOPBACK: */ - if (optlen < sizeof(int)) { - err = EINVAL; - } - break; - case SO_NO_CHECK: - if (optlen < sizeof(int)) { - err = EINVAL; - } -#if LWIP_UDP - if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) || - ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) { - /* this flag is only available for UDP, not for UDP lite */ - err = EAFNOSUPPORT; - } -#endif /* LWIP_UDP */ - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - } /* switch (optname) */ - break; - -/* Level: IPPROTO_IP */ - case IPPROTO_IP: - switch (optname) { - /* UNIMPL case IP_HDRINCL: */ - /* UNIMPL case IP_RCVDSTADDR: */ - /* UNIMPL case IP_RCVIF: */ - case IP_TTL: - case IP_TOS: - if (optlen < sizeof(int)) { - err = EINVAL; - } - break; -#if LWIP_IGMP - case IP_MULTICAST_TTL: - if (optlen < sizeof(u8_t)) { - err = EINVAL; - } - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { - err = EAFNOSUPPORT; - } - break; - case IP_MULTICAST_IF: - if (optlen < sizeof(struct in_addr)) { - err = EINVAL; - } - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { - err = EAFNOSUPPORT; - } - break; - case IP_MULTICAST_LOOP: - if (optlen < sizeof(u8_t)) { - err = EINVAL; - } - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { - err = EAFNOSUPPORT; - } - break; - case IP_ADD_MEMBERSHIP: - case IP_DROP_MEMBERSHIP: - if (optlen < sizeof(struct ip_mreq)) { - err = EINVAL; - } - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { - err = EAFNOSUPPORT; - } - break; -#endif /* LWIP_IGMP */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - } /* switch (optname) */ - break; - -#if LWIP_TCP -/* Level: IPPROTO_TCP */ - case IPPROTO_TCP: - if (optlen < sizeof(int)) { - err = EINVAL; - break; - } - - /* If this is no TCP socket, ignore any options. */ - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) - return 0; - - switch (optname) { - case TCP_NODELAY: - case TCP_KEEPALIVE: -#if LWIP_TCP_KEEPALIVE - case TCP_KEEPIDLE: - case TCP_KEEPINTVL: - case TCP_KEEPCNT: -#endif /* LWIP_TCP_KEEPALIVE */ - break; - - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - } /* switch (optname) */ - break; -#endif /* LWIP_TCP */ - -#if LWIP_IPV6 -/* Level: IPPROTO_IPV6 */ - case IPPROTO_IPV6: - switch (optname) { - case IPV6_V6ONLY: - if (optlen < sizeof(int)) { - err = EINVAL; - } - - /* @todo: this does not work for datagram sockets, yet */ - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) - return 0; - - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - } /* switch (optname) */ - break; -#endif /* LWIP_IPV6 */ - -#if LWIP_UDP && LWIP_UDPLITE -/* Level: IPPROTO_UDPLITE */ - case IPPROTO_UDPLITE: - if (optlen < sizeof(int)) { - err = EINVAL; - break; - } - - /* If this is no UDP lite socket, ignore any options. */ - if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) - return 0; - - switch (optname) { - case UDPLITE_SEND_CSCOV: - case UDPLITE_RECV_CSCOV: - break; - - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - } /* switch (optname) */ - break; -#endif /* LWIP_UDP && LWIP_UDPLITE */ -/* UNDEFINED LEVEL */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", - s, level, optname)); - err = ENOPROTOOPT; - } /* switch (level) */ - - - if (err != ERR_OK) { - sock_set_errno(sock, err); - return -1; - } - - - /* Now do the actual option processing */ - data.sock = sock; -#ifdef LWIP_DEBUG - data.s = s; -#endif /* LWIP_DEBUG */ - data.level = level; - data.optname = optname; - data.optval = (void*)optval; - data.optlen = &optlen; - data.err = err; - tcpip_callback(lwip_setsockopt_internal, &data); - sys_arch_sem_wait(&sock->conn->op_completed, 0); - /* maybe lwip_setsockopt_internal has changed err */ - err = data.err; - - sock_set_errno(sock, err); - return err ? -1 : 0; -} - -static void ICACHE_FLASH_ATTR -lwip_setsockopt_internal(void *arg) -{ - struct lwip_sock *sock; -#ifdef LWIP_DEBUG - int s; -#endif /* LWIP_DEBUG */ - int level, optname; - const void *optval; - struct lwip_setgetsockopt_data *data; - - LWIP_ASSERT("arg != NULL", arg != NULL); - - data = (struct lwip_setgetsockopt_data*)arg; - sock = data->sock; -#ifdef LWIP_DEBUG - s = data->s; -#endif /* LWIP_DEBUG */ - level = data->level; - optname = data->optname; - optval = data->optval; - - switch (level) { - -/* Level: SOL_SOCKET */ - case SOL_SOCKET: - switch (optname) { - - /* The option flags */ - case SO_BROADCAST: - /* UNIMPL case SO_DEBUG: */ - /* UNIMPL case SO_DONTROUTE: */ - case SO_KEEPALIVE: - /* UNIMPL case SO_OOBINCLUDE: */ -#if SO_REUSE - case SO_REUSEADDR: - case SO_REUSEPORT: -#endif /* SO_REUSE */ - /* UNIMPL case SO_USELOOPBACK: */ - if (*(int*)optval) { - ip_set_option(sock->conn->pcb.ip, optname); - } else { - ip_reset_option(sock->conn->pcb.ip, optname); - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", - s, optname, (*(int*)optval?"on":"off"))); - break; -#if LWIP_SO_SNDTIMEO - case SO_SNDTIMEO: - netconn_set_sendtimeout(sock->conn, (s32_t)*(int*)optval); - break; -#endif /* LWIP_SO_SNDTIMEO */ -#if LWIP_SO_RCVTIMEO - case SO_RCVTIMEO: - netconn_set_recvtimeout(sock->conn, *(int*)optval); - break; -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVBUF - case SO_RCVBUF: - netconn_set_recvbufsize(sock->conn, *(int*)optval); - break; -#endif /* LWIP_SO_RCVBUF */ -#if LWIP_UDP - case SO_NO_CHECK: - if (*(int*)optval) { - udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM); - } else { - udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM); - } - break; -#endif /* LWIP_UDP */ - default: - LWIP_ASSERT("unhandled optname", 0); - break; - } /* switch (optname) */ - break; - -/* Level: IPPROTO_IP */ - case IPPROTO_IP: - switch (optname) { - case IP_TTL: - sock->conn->pcb.ip->ttl = (u8_t)(*(int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n", - s, sock->conn->pcb.ip->ttl)); - break; - case IP_TOS: - sock->conn->pcb.ip->tos = (u8_t)(*(int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n", - s, sock->conn->pcb.ip->tos)); - break; -#if LWIP_IGMP - case IP_MULTICAST_TTL: - sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval); - break; - case IP_MULTICAST_IF: - inet_addr_to_ipaddr(&sock->conn->pcb.udp->multicast_ip, (struct in_addr*)optval); - break; - case IP_MULTICAST_LOOP: - if (*(u8_t*)optval) { - udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP); - } else { - udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP); - } - break; - case IP_ADD_MEMBERSHIP: - case IP_DROP_MEMBERSHIP: - { - /* If this is a TCP or a RAW socket, ignore these options. */ - struct ip_mreq *imr = (struct ip_mreq *)optval; - ip_addr_t if_addr; - ip_addr_t multi_addr; - inet_addr_to_ipaddr(&if_addr, &imr->imr_interface); - inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr); - if(optname == IP_ADD_MEMBERSHIP){ - data->err = igmp_joingroup(&if_addr, &multi_addr); - } else { - data->err = igmp_leavegroup(&if_addr, &multi_addr); - } - if(data->err != ERR_OK) { - data->err = EADDRNOTAVAIL; - } - } - break; -#endif /* LWIP_IGMP */ - default: - LWIP_ASSERT("unhandled optname", 0); - break; - } /* switch (optname) */ - break; - -#if LWIP_TCP -/* Level: IPPROTO_TCP */ - case IPPROTO_TCP: - switch (optname) { - case TCP_NODELAY: - if (*(int*)optval) { - tcp_nagle_disable(sock->conn->pcb.tcp); - } else { - tcp_nagle_enable(sock->conn->pcb.tcp); - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", - s, (*(int *)optval)?"on":"off") ); - break; - case TCP_KEEPALIVE: - sock->conn->pcb.tcp->keep_idle = (u32_t)(*(int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n", - s, sock->conn->pcb.tcp->keep_idle)); - break; - -#if LWIP_TCP_KEEPALIVE - case TCP_KEEPIDLE: - sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n", - s, sock->conn->pcb.tcp->keep_idle)); - break; - case TCP_KEEPINTVL: - sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n", - s, sock->conn->pcb.tcp->keep_intvl)); - break; - case TCP_KEEPCNT: - sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n", - s, sock->conn->pcb.tcp->keep_cnt)); - break; -#endif /* LWIP_TCP_KEEPALIVE */ - default: - LWIP_ASSERT("unhandled optname", 0); - break; - } /* switch (optname) */ - break; -#endif /* LWIP_TCP*/ - -#if LWIP_IPV6 -/* Level: IPPROTO_IPV6 */ - case IPPROTO_IPV6: - switch (optname) { - case IPV6_V6ONLY: - if (*(int*)optval) { - sock->conn->flags |= NETCONN_FLAG_IPV6_V6ONLY; - } else { - sock->conn->flags &= ~NETCONN_FLAG_IPV6_V6ONLY; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n", - s, ((sock->conn->flags & NETCONN_FLAG_IPV6_V6ONLY) ? 1 : 0))); - break; - default: - LWIP_ASSERT("unhandled optname", 0); - break; - } /* switch (optname) */ - break; -#endif /* LWIP_IPV6 */ - -#if LWIP_UDP && LWIP_UDPLITE - /* Level: IPPROTO_UDPLITE */ - case IPPROTO_UDPLITE: - switch (optname) { - case UDPLITE_SEND_CSCOV: - if ((*(int*)optval != 0) && ((*(int*)optval < 8) || (*(int*)optval > 0xffff))) { - /* don't allow illegal values! */ - sock->conn->pcb.udp->chksum_len_tx = 8; - } else { - sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(int*)optval; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n", - s, (*(int*)optval)) ); - break; - case UDPLITE_RECV_CSCOV: - if ((*(int*)optval != 0) && ((*(int*)optval < 8) || (*(int*)optval > 0xffff))) { - /* don't allow illegal values! */ - sock->conn->pcb.udp->chksum_len_rx = 8; - } else { - sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(int*)optval; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n", - s, (*(int*)optval)) ); - break; - default: - LWIP_ASSERT("unhandled optname", 0); - break; - } /* switch (optname) */ - break; -#endif /* LWIP_UDP */ - default: - LWIP_ASSERT("unhandled level", 0); - break; - } /* switch (level) */ - sys_sem_signal(&sock->conn->op_completed); -} - -int ICACHE_FLASH_ATTR -lwip_ioctl(int s, long cmd, void *argp) -{ - struct lwip_sock *sock = get_socket(s); - u8_t val; -#if LWIP_SO_RCVBUF - u16_t buflen = 0; - s16_t recv_avail; -#endif /* LWIP_SO_RCVBUF */ - - if (!sock) { - return -1; - } - - switch (cmd) { -#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE - case FIONREAD: - if (!argp) { - sock_set_errno(sock, EINVAL); - return -1; - } -#if LWIP_FIONREAD_LINUXMODE - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { - struct pbuf *p; - if (sock->lastdata) { - p = ((struct netbuf *)sock->lastdata)->p; - } else { - struct netbuf *rxbuf; - err_t err; - if (sock->rcvevent <= 0) { - *((u16_t*)argp) = 0; - } else { - err = netconn_recv(sock->conn, &rxbuf); - if (err != ERR_OK) { - *((u16_t*)argp) = 0; - } else { - sock->lastdata = rxbuf; - *((u16_t*)argp) = rxbuf->p->tot_len; - } - } - } - return 0; - } -#endif /* LWIP_FIONREAD_LINUXMODE */ - -#if LWIP_SO_RCVBUF - /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ - SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); - if (recv_avail < 0) { - recv_avail = 0; - } - *((u16_t*)argp) = (u16_t)recv_avail; - - /* Check if there is data left from the last recv operation. /maq 041215 */ - if (sock->lastdata) { - struct pbuf *p = (struct pbuf *)sock->lastdata; - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { - p = ((struct netbuf *)p)->p; - } - buflen = p->tot_len; - buflen -= sock->lastoffset; - - *((u16_t*)argp) += buflen; - } - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); - sock_set_errno(sock, 0); - return 0; -#else /* LWIP_SO_RCVBUF */ - break; -#endif /* LWIP_SO_RCVBUF */ -#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ - - case FIONBIO: - val = 0; - if (argp && *(u32_t*)argp) { - val = 1; - } - netconn_set_nonblocking(sock->conn, val); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); - sock_set_errno(sock, 0); - return 0; - - default: - break; - } /* switch (cmd) */ - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); - sock_set_errno(sock, ENOSYS); /* not yet implemented */ - return -1; -} - -/** A minimal implementation of fcntl. - * Currently only the commands F_GETFL and F_SETFL are implemented. - * Only the flag O_NONBLOCK is implemented. - */ -int ICACHE_FLASH_ATTR -lwip_fcntl(int s, int cmd, int val) -{ - struct lwip_sock *sock = get_socket(s); - int ret = -1; - - if (!sock || !sock->conn) { - return -1; - } - - switch (cmd) { - case F_GETFL: - ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0; - break; - case F_SETFL: - if ((val & ~O_NONBLOCK) == 0) { - /* only O_NONBLOCK, all other bits are zero */ - netconn_set_nonblocking(sock->conn, val & O_NONBLOCK); - ret = 0; - } - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val)); - break; - } - return ret; -} - -#endif /* LWIP_SOCKET */ diff --git a/third_party/lwip/api/tcpip.c b/third_party/lwip/api/tcpip.c deleted file mode 100644 index 478f0e9..0000000 --- a/third_party/lwip/api/tcpip.c +++ /dev/null @@ -1,507 +0,0 @@ -/** - * @file - * Sequential API Main thread module - * - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" - -#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/sys.h" -#include "lwip/memp.h" -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/tcpip.h" -#include "lwip/init.h" -#include "netif/etharp.h" -#include "netif/ppp_oe.h" - -/* global variables */ -static tcpip_init_done_fn tcpip_init_done; -static void *tcpip_init_done_arg; -static sys_mbox_t mbox; -sys_thread_t xLwipTaskHandle; - -#if LWIP_TCPIP_CORE_LOCKING -/** The global semaphore to lock the stack. */ -sys_mutex_t lock_tcpip_core; -#endif /* LWIP_TCPIP_CORE_LOCKING */ - - -/** - * The main lwIP thread. This thread has exclusive access to lwIP core functions - * (unless access to them is not locked). Other threads communicate with this - * thread using message boxes. - * - * It also starts all the timers to make sure they are running in the right - * thread context. - * - * @param arg unused argument - */ -static void ICACHE_FLASH_ATTR -tcpip_thread(void *arg) -{ - struct tcpip_msg *msg; - LWIP_UNUSED_ARG(arg); - - if (tcpip_init_done != NULL) { - tcpip_init_done(tcpip_init_done_arg); - } - - LOCK_TCPIP_CORE(); - while (1) { /* MAIN Loop */ - UNLOCK_TCPIP_CORE(); - LWIP_TCPIP_THREAD_ALIVE(); - /* wait for a message, timeouts are processed while waiting */ - sys_timeouts_mbox_fetch(&mbox, (void **)&msg); - LOCK_TCPIP_CORE(); - switch (msg->type) { -#if LWIP_NETCONN - case TCPIP_MSG_API: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); - msg->msg.apimsg->function(&(msg->msg.apimsg->msg)); - break; -#endif /* LWIP_NETCONN */ - -#if !LWIP_TCPIP_CORE_LOCKING_INPUT - case TCPIP_MSG_INPKT: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); -#if LWIP_ETHERNET - if (msg->msg.inp.netif->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { - ethernet_input(msg->msg.inp.p, msg->msg.inp.netif); - } else -#endif /* LWIP_ETHERNET */ -#if LWIP_IPV6 - if ((*((unsigned char *)(msg->msg.inp.p->payload)) & 0xf0) == 0x60) { - ip6_input(msg->msg.inp.p, msg->msg.inp.netif); - } else -#endif /* LWIP_IPV6 */ - { - ip_input(msg->msg.inp.p, msg->msg.inp.netif); - } - memp_free(MEMP_TCPIP_MSG_INPKT, msg); - break; -#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ - -#if LWIP_NETIF_API - case TCPIP_MSG_NETIFAPI: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg)); - msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg)); - break; -#endif /* LWIP_NETIF_API */ - -#if LWIP_TCPIP_TIMEOUT - case TCPIP_MSG_TIMEOUT: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); - sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); - memp_free(MEMP_TCPIP_MSG_API, msg); - break; - case TCPIP_MSG_UNTIMEOUT: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg)); - sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); - memp_free(MEMP_TCPIP_MSG_API, msg); - break; -#endif /* LWIP_TCPIP_TIMEOUT */ - - case TCPIP_MSG_CALLBACK: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); - msg->msg.cb.function(msg->msg.cb.ctx); - memp_free(MEMP_TCPIP_MSG_API, msg); - break; - - case TCPIP_MSG_CALLBACK_STATIC: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg)); - msg->msg.cb.function(msg->msg.cb.ctx); - break; - - default: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type)); - LWIP_ASSERT("tcpip_thread: invalid message", 0); - break; - } - } -} - -/** - * Pass a received packet to tcpip_thread for input processing - * - * @param p the received packet, p->payload pointing to the Ethernet header or - * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or - * NETIF_FLAG_ETHERNET flags) - * @param inp the network interface on which the packet was received - */ -err_t ICACHE_FLASH_ATTR -tcpip_input(struct pbuf *p, struct netif *inp) -{ -#if LWIP_TCPIP_CORE_LOCKING_INPUT - err_t ret; - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_input: PACKET %p/%p\n", (void *)p, (void *)inp)); - LOCK_TCPIP_CORE(); -#if LWIP_ETHERNET - if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { - ret = ethernet_input(p, inp); - } else -#endif /* LWIP_ETHERNET */ - { - ret = ip_input(p, inp); - } - UNLOCK_TCPIP_CORE(); - return ret; -#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */ - struct tcpip_msg *msg; - - if (!sys_mbox_valid(&mbox)) { - return ERR_VAL; - } - msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); - if (msg == NULL) { - return ERR_MEM; - } - - msg->type = TCPIP_MSG_INPKT; - msg->msg.inp.p = p; - msg->msg.inp.netif = inp; - if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { - memp_free(MEMP_TCPIP_MSG_INPKT, msg); - return ERR_MEM; - } - return ERR_OK; -#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ -} - -/** - * Call a specific function in the thread context of - * tcpip_thread for easy access synchronization. - * A function called in that way may access lwIP core code - * without fearing concurrent access. - * - * @param f the function to call - * @param ctx parameter passed to f - * @param block 1 to block until the request is posted, 0 to non-blocking mode - * @return ERR_OK if the function was called, another err_t if not - */ -err_t ICACHE_FLASH_ATTR -tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block) -{ - struct tcpip_msg *msg; - - if (sys_mbox_valid(&mbox)) { - msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); - if (msg == NULL) { - return ERR_MEM; - } - - msg->type = TCPIP_MSG_CALLBACK; - msg->msg.cb.function = function; - msg->msg.cb.ctx = ctx; - if (block) { - sys_mbox_post(&mbox, msg); - } else { - if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { - memp_free(MEMP_TCPIP_MSG_API, msg); - return ERR_MEM; - } - } - return ERR_OK; - } - return ERR_VAL; -} - -#if LWIP_TCPIP_TIMEOUT -/** - * call sys_timeout in tcpip_thread - * - * @param msec time in milliseconds for timeout - * @param h function to be called on timeout - * @param arg argument to pass to timeout function h - * @return ERR_MEM on memory error, ERR_OK otherwise - */ -err_t ICACHE_FLASH_ATTR -tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) -{ - struct tcpip_msg *msg; - - if (sys_mbox_valid(&mbox)) { - msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); - if (msg == NULL) { - return ERR_MEM; - } - - msg->type = TCPIP_MSG_TIMEOUT; - msg->msg.tmo.msecs = msecs; - msg->msg.tmo.h = h; - msg->msg.tmo.arg = arg; - sys_mbox_post(&mbox, msg); - return ERR_OK; - } - return ERR_VAL; -} - -/** - * call sys_untimeout in tcpip_thread - * - * @param msec time in milliseconds for timeout - * @param h function to be called on timeout - * @param arg argument to pass to timeout function h - * @return ERR_MEM on memory error, ERR_OK otherwise - */ -err_t ICACHE_FLASH_ATTR -tcpip_untimeout(sys_timeout_handler h, void *arg) -{ - struct tcpip_msg *msg; - - if (sys_mbox_valid(&mbox)) { - msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); - if (msg == NULL) { - return ERR_MEM; - } - - msg->type = TCPIP_MSG_UNTIMEOUT; - msg->msg.tmo.h = h; - msg->msg.tmo.arg = arg; - sys_mbox_post(&mbox, msg); - return ERR_OK; - } - return ERR_VAL; -} -#endif /* LWIP_TCPIP_TIMEOUT */ - -#if LWIP_NETCONN -/** - * Call the lower part of a netconn_* function - * This function is then running in the thread context - * of tcpip_thread and has exclusive access to lwIP core code. - * - * @param apimsg a struct containing the function to call and its parameters - * @return ERR_OK if the function was called, another err_t if not - */ -static sys_mutex_t ApiMsgMutex = NULL; - -err_t ICACHE_FLASH_ATTR -tcpip_apimsg(struct api_msg *apimsg) -{ - struct tcpip_msg msg; -#ifdef LWIP_DEBUG - /* catch functions that don't set err */ - apimsg->msg.err = ERR_VAL; -#endif - - if (sys_mbox_valid(&mbox)) { - msg.type = TCPIP_MSG_API; - msg.msg.apimsg = apimsg; - -sys_mutex_lock(&ApiMsgMutex); - - sys_mbox_post(&mbox, &msg); - sys_arch_sem_wait(&apimsg->msg.conn->op_completed, 0); - -sys_mutex_unlock(&ApiMsgMutex); - - return apimsg->msg.err; - } - return ERR_VAL; -} - -#endif /* LWIP_NETCONN */ - -#if LWIP_NETIF_API -#if !LWIP_TCPIP_CORE_LOCKING -/** - * Much like tcpip_apimsg, but calls the lower part of a netifapi_* - * function. - * - * @param netifapimsg a struct containing the function to call and its parameters - * @return error code given back by the function that was called - */ -err_t ICACHE_FLASH_ATTR -tcpip_netifapi(struct netifapi_msg* netifapimsg) -{ - struct tcpip_msg msg; - - if (sys_mbox_valid(&mbox)) { - err_t err = sys_sem_new(&netifapimsg->msg.sem, 0); - if (err != ERR_OK) { - netifapimsg->msg.err = err; - return err; - } - - msg.type = TCPIP_MSG_NETIFAPI; - msg.msg.netifapimsg = netifapimsg; - sys_mbox_post(&mbox, &msg); - sys_sem_wait(&netifapimsg->msg.sem); - sys_sem_free(&netifapimsg->msg.sem); - return netifapimsg->msg.err; - } - return ERR_VAL; -} -#else /* !LWIP_TCPIP_CORE_LOCKING */ -/** - * Call the lower part of a netifapi_* function - * This function has exclusive access to lwIP core code by locking it - * before the function is called. - * - * @param netifapimsg a struct containing the function to call and its parameters - * @return ERR_OK (only for compatibility fo tcpip_netifapi()) - */ -err_t ICACHE_FLASH_ATTR -tcpip_netifapi_lock(struct netifapi_msg* netifapimsg) -{ - LOCK_TCPIP_CORE(); - netifapimsg->function(&(netifapimsg->msg)); - UNLOCK_TCPIP_CORE(); - return netifapimsg->msg.err; -} -#endif /* !LWIP_TCPIP_CORE_LOCKING */ -#endif /* LWIP_NETIF_API */ - -/** - * Allocate a structure for a static callback message and initialize it. - * This is intended to be used to send "static" messages from interrupt context. - * - * @param function the function to call - * @param ctx parameter passed to function - * @return a struct pointer to pass to tcpip_trycallback(). - */ -struct tcpip_callback_msg* ICACHE_FLASH_ATTR tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx) -{ - struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); - if (msg == NULL) { - return NULL; - } - msg->type = TCPIP_MSG_CALLBACK_STATIC; - msg->msg.cb.function = function; - msg->msg.cb.ctx = ctx; - return (struct tcpip_callback_msg*)msg; -} - -/** - * Free a callback message allocated by tcpip_callbackmsg_new(). - * - * @param msg the message to free - */ -void ICACHE_FLASH_ATTR tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg) -{ - memp_free(MEMP_TCPIP_MSG_API, msg); -} - -/** - * Try to post a callback-message to the tcpip_thread mbox - * This is intended to be used to send "static" messages from interrupt context. - * - * @param msg pointer to the message to post - * @return sys_mbox_trypost() return code - */ -err_t ICACHE_FLASH_ATTR -tcpip_trycallback(struct tcpip_callback_msg* msg) -{ - if (!sys_mbox_valid(&mbox)) { - return ERR_VAL; - } - return sys_mbox_trypost(&mbox, msg); -} - -/** - * Initialize this module: - * - initialize all sub modules - * - start the tcpip_thread - * - * @param initfunc a function to call when tcpip_thread is running and finished initializing - * @param arg argument to pass to initfunc - */ -void ICACHE_FLASH_ATTR -tcpip_init(tcpip_init_done_fn initfunc, void *arg) -{ - lwip_init(); - - tcpip_init_done = initfunc; - tcpip_init_done_arg = arg; - if(sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) { - LWIP_ASSERT("failed to create tcpip_thread mbox", 0); - } -#if LWIP_TCPIP_CORE_LOCKING - if(sys_mutex_new(&lock_tcpip_core) != ERR_OK) { - LWIP_ASSERT("failed to create lock_tcpip_core", 0); - } -#endif /* LWIP_TCPIP_CORE_LOCKING */ - -sys_mutex_new(&ApiMsgMutex); -if(ApiMsgMutex==NULL) - printf("ApiMsgMutex create fail\n"); -else - printf("ApiMsgMutex created\n"); - - xLwipTaskHandle = sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); -} - -/** - * Simple callback function used with tcpip_callback to free a pbuf - * (pbuf_free has a wrong signature for tcpip_callback) - * - * @param p The pbuf (chain) to be dereferenced. - */ -static void ICACHE_FLASH_ATTR -pbuf_free_int(void *p) -{ - struct pbuf *q = (struct pbuf *)p; - pbuf_free(q); -} - -/** - * A simple wrapper function that allows you to free a pbuf from interrupt context. - * - * @param p The pbuf (chain) to be dereferenced. - * @return ERR_OK if callback could be enqueued, an err_t if not - */ -err_t ICACHE_FLASH_ATTR -pbuf_free_callback(struct pbuf *p) -{ - return tcpip_callback_with_block(pbuf_free_int, p, 0); -} - -/** - * A simple wrapper function that allows you to free heap memory from - * interrupt context. - * - * @param m the heap memory to free - * @return ERR_OK if callback could be enqueued, an err_t if not - */ -err_t ICACHE_FLASH_ATTR -mem_free_callback(void *m) -{ - return tcpip_callback_with_block(mem_free, m, 0); -} - -#endif /* !NO_SYS */ diff --git a/third_party/lwip/arch/Makefile b/third_party/lwip/arch/Makefile deleted file mode 100644 index 5d7af3a..0000000 --- a/third_party/lwip/arch/Makefile +++ /dev/null @@ -1,46 +0,0 @@ - -############################################################# -# Required variables for each makefile -# Discard this section from all parent makefiles -# Expected variables (with automatic defaults): -# CSRCS (all "C" files in the dir) -# SUBDIRS (all subdirs with a Makefile) -# GEN_LIBS - list of libs to be generated () -# GEN_IMAGES - list of images to be generated () -# COMPONENTS_xxx - a list of libs/objs in the form -# subdir/lib to be extracted and rolled up into -# a generated lib/image xxx.a () -# -ifndef PDIR - -GEN_LIBS = liblwiparch.a - -endif - - -############################################################# -# Configuration i.e. compile options etc. -# Target specific stuff (defines etc.) goes in here! -# Generally values applying to a tree are captured in the -# makefile at its root level - these are then overridden -# for a subtree within the makefile rooted therein -# -#DEFINES += - -############################################################# -# Recursion Magic - Don't touch this!! -# -# Each subtree potentially has an include directory -# corresponding to the common APIs applicable to modules -# rooted at that subtree. Accordingly, the INCLUDE PATH -# of a module can only contain the include directories up -# its parent path, and not its siblings -# -# Required for each makefile to inherit from the parent -# - -INCLUDES := $(INCLUDES) -I $(PDIR)include -INCLUDES += -I ./ -PDIR := ../$(PDIR) -sinclude $(PDIR)Makefile - diff --git a/third_party/lwip/arch/sys_arch.c b/third_party/lwip/arch/sys_arch.c deleted file mode 100644 index 0363648..0000000 --- a/third_party/lwip/arch/sys_arch.c +++ /dev/null @@ -1,414 +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: Adam Dunkels - * - */ - -/* lwIP includes. */ - -#include -#include "lwip/debug.h" -#include "lwip/def.h" -#include "lwip/sys.h" -#include "lwip/mem.h" -#include "arch/sys_arch.h" - - -/* Message queue constants. */ -#define archMESG_QUEUE_LENGTH (100)//( 6 ) -#define archPOST_BLOCK_TIME_MS ( ( unsigned portLONG ) 10000 ) - - -struct timeoutlist { - //struct sys_timeouts timeouts; - xTaskHandle pid; -}; - -/* This is the number of threads that can be started with sys_thread_new() */ -#define SYS_THREAD_MAX 4 - -//static struct timeoutlist timeoutlist[SYS_THREAD_MAX]; -//static u16_t nextthread = 0; -int intlevel = 0; - -/*-----------------------------------------------------------------------------------*/ -// Initialize sys arch -void ICACHE_FLASH_ATTR -sys_init(void) -{ -} - -/*-----------------------------------------------------------------------------------*/ -// Creates and returns a new semaphore. The "count" argument specifies -// the initial state of the semaphore. TBD finish and test -err_t ICACHE_FLASH_ATTR -sys_sem_new(sys_sem_t *sem, u8_t count) -{ - err_t xReturn = ERR_MEM; - vSemaphoreCreateBinary(*sem); - - if ((*sem) != NULL) { - if (count == 0) { // Means it can't be taken - xSemaphoreTake(*sem, 1); - } - - xReturn = ERR_OK; - } else { - ; // TBD need assert - } - - return xReturn; -} - - -/*-----------------------------------------------------------------------------------*/ -// Deallocates a semaphore -void ICACHE_FLASH_ATTR -sys_sem_free(sys_sem_t *sem) -{ - //vQueueDelete( sem ); - vSemaphoreDelete(*sem); -} - - -/*-----------------------------------------------------------------------------------*/ -// Signals a semaphore -void ICACHE_FLASH_ATTR -sys_sem_signal(sys_sem_t *sem) -{ - xSemaphoreGive(*sem); -} - - -/*-----------------------------------------------------------------------------------*/ -/* - 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 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. -*/ -u32_t ICACHE_FLASH_ATTR -sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) -{ - portTickType StartTime, EndTime, Elapsed; - unsigned long ulReturn; - - StartTime = xTaskGetTickCount(); - - if (timeout != 0) { - if (xSemaphoreTake(*sem, timeout / portTICK_RATE_MS) == pdTRUE) { - EndTime = xTaskGetTickCount(); - Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; - - if (Elapsed == 0) { - Elapsed = 1; - } - - ulReturn = Elapsed; - } else { - ulReturn = SYS_ARCH_TIMEOUT; - } - } else { // must block without a timeout - while (xSemaphoreTake(*sem, portMAX_DELAY) != pdTRUE); - - EndTime = xTaskGetTickCount(); - Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; - - if (Elapsed == 0) { - Elapsed = 1; - } - - ulReturn = Elapsed; - } - - return ulReturn ; // return time blocked -} - -/*-----------------------------------------------------------------------------------*/ -// Creates an empty mailbox. -err_t ICACHE_FLASH_ATTR -sys_mbox_new(sys_mbox_t *mbox, int size) -{ - err_t xReturn = ERR_MEM; - - *mbox = xQueueCreate(size, sizeof(void *)); - - if (*mbox != NULL) { - xReturn = ERR_OK; - } - - return xReturn; -} - -/*-----------------------------------------------------------------------------------*/ -/* - 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 ICACHE_FLASH_ATTR -sys_mbox_free(sys_mbox_t *mbox) -{ - if (uxQueueMessagesWaiting(*mbox)) { - /* Line for breakpoint. Should never break here! */ -// __asm volatile ( "NOP" ); - } - - vQueueDelete(*mbox); -} - -/*-----------------------------------------------------------------------------------*/ -// Posts the "msg" to the mailbox. -void ICACHE_FLASH_ATTR -sys_mbox_post(sys_mbox_t *mbox, void *msg) -{ - while (xQueueSendToBack(*mbox, &msg, portMAX_DELAY) != pdTRUE); -} - -err_t ICACHE_FLASH_ATTR -sys_mbox_trypost(sys_mbox_t *mbox, void *msg) -{ - err_t xReturn; - - if (xQueueSend(*mbox, &msg, (portTickType)0) == pdPASS) { - xReturn = ERR_OK; - } else { - xReturn = ERR_MEM; - } - - return xReturn; -} - -/*-----------------------------------------------------------------------------------*/ -/* - 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). 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 ICACHE_FLASH_ATTR -sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) -{ - void *dummyptr; - portTickType StartTime, EndTime, Elapsed; - unsigned long ulReturn; - - StartTime = xTaskGetTickCount(); - - if (msg == NULL) { - msg = &dummyptr; - } - - if (timeout != 0) { - if (pdTRUE == xQueueReceive(*mbox, &(*msg), timeout / portTICK_RATE_MS)) { - EndTime = xTaskGetTickCount(); - Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; - - if (Elapsed == 0) { - Elapsed = 1; - } - - ulReturn = Elapsed; - } else { // timed out blocking for message - *msg = NULL; - ulReturn = SYS_ARCH_TIMEOUT; - } - } else { // block forever for a message. - while (pdTRUE != xQueueReceive(*mbox, &(*msg), portMAX_DELAY)); - - EndTime = xTaskGetTickCount(); - Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; - - if (Elapsed == 0) { - Elapsed = 1; - } - - ulReturn = Elapsed; - } - - return ulReturn ; // return time blocked TBD test -} - -u32_t ICACHE_FLASH_ATTR -sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) -{ - void *pvDummy; - unsigned long ulReturn; - - if (msg == NULL) { - msg = &pvDummy; - } - - if (pdTRUE == xQueueReceive(*mbox, &(*msg), 0)) { - ulReturn = ERR_OK; - } else { - ulReturn = SYS_MBOX_EMPTY; - } - - return ulReturn; -} - -/** Create a new mutex - * @param mutex pointer to the mutex to create - * @return a new mutex */ -err_t ICACHE_FLASH_ATTR -sys_mutex_new(sys_mutex_t *pxMutex) -{ - err_t xReturn = ERR_MEM; - - *pxMutex = xSemaphoreCreateMutex(); - - if (*pxMutex != NULL) { - xReturn = ERR_OK; - - } else { - ; - } - - return xReturn; -} - -/** Lock a mutex - * @param mutex the mutex to lock */ -void ICACHE_FLASH_ATTR -sys_mutex_lock(sys_mutex_t *pxMutex) -{ - while (xSemaphoreTake(*pxMutex, portMAX_DELAY) != pdPASS); -} - -/** Unlock a mutex - * @param mutex the mutex to unlock */ -void ICACHE_FLASH_ATTR -sys_mutex_unlock(sys_mutex_t *pxMutex) -{ - xSemaphoreGive(*pxMutex); -} - - -/** Delete a semaphore - * @param mutex the mutex to delete */ -void ICACHE_FLASH_ATTR -sys_mutex_free(sys_mutex_t *pxMutex) -{ - vQueueDelete(*pxMutex); -} - -u32_t ICACHE_FLASH_ATTR -sys_now(void) -{ - return xTaskGetTickCount(); -} - -/*-----------------------------------------------------------------------------------*/ -/*-----------------------------------------------------------------------------------*/ -// TBD -/*-----------------------------------------------------------------------------------*/ -/* - Starts a new thread 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 id of the new thread is returned. Both the id and - the priority are system dependent. -*/ -sys_thread_t ICACHE_FLASH_ATTR -sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio) -{ - xTaskHandle CreatedTask; - portBASE_TYPE result; - - result = xTaskCreate(thread, (signed char *)name, stacksize, arg, prio, &CreatedTask); - - if (result == pdPASS) { - return CreatedTask; - } else { - return NULL; - } -} - -/* - 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 ICACHE_FLASH_ATTR -sys_arch_protect(void) -{ - vPortEnterCritical(); - return (sys_prot_t) 1; -} - -/* - 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 ICACHE_FLASH_ATTR -sys_arch_unprotect(sys_prot_t pval) -{ - (void) pval; - vPortExitCritical(); -} - -/* - * Prints an assertion messages and aborts execution. - */ -void ICACHE_FLASH_ATTR -sys_arch_assert(const char *file, int line) -{ - printf("\nAssertion: %d in %s\n", line, file); - - while(1); -} - diff --git a/third_party/lwip/core/Makefile b/third_party/lwip/core/Makefile deleted file mode 100644 index 9915910..0000000 --- a/third_party/lwip/core/Makefile +++ /dev/null @@ -1,46 +0,0 @@ - -############################################################# -# Required variables for each makefile -# Discard this section from all parent makefiles -# Expected variables (with automatic defaults): -# CSRCS (all "C" files in the dir) -# SUBDIRS (all subdirs with a Makefile) -# GEN_LIBS - list of libs to be generated () -# GEN_IMAGES - list of images to be generated () -# COMPONENTS_xxx - a list of libs/objs in the form -# subdir/lib to be extracted and rolled up into -# a generated lib/image xxx.a () -# -ifndef PDIR - -GEN_LIBS = liblwipcore.a - -endif - - -############################################################# -# Configuration i.e. compile options etc. -# Target specific stuff (defines etc.) goes in here! -# Generally values applying to a tree are captured in the -# makefile at its root level - these are then overridden -# for a subtree within the makefile rooted therein -# -#DEFINES += - -############################################################# -# Recursion Magic - Don't touch this!! -# -# Each subtree potentially has an include directory -# corresponding to the common APIs applicable to modules -# rooted at that subtree. Accordingly, the INCLUDE PATH -# of a module can only contain the include directories up -# its parent path, and not its siblings -# -# Required for each makefile to inherit from the parent -# - -INCLUDES := $(INCLUDES) -I $(PDIR)include -INCLUDES += -I ./ -PDIR := ../$(PDIR) -sinclude $(PDIR)Makefile - diff --git a/third_party/lwip/core/def.c b/third_party/lwip/core/def.c deleted file mode 100644 index 943de19..0000000 --- a/third_party/lwip/core/def.c +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @file - * Common functions used throughout the stack. - * - */ - -/* - * 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: Simon Goldschmidt - * - */ - -#include "lwip/opt.h" -#include "lwip/def.h" - -/** - * These are reference implementations of the byte swapping functions. - * Again with the aim of being simple, correct and fully portable. - * Byte swapping is the second thing you would want to optimize. You will - * need to port it to your architecture and in your cc.h: - * - * #define LWIP_PLATFORM_BYTESWAP 1 - * #define LWIP_PLATFORM_HTONS(x) - * #define LWIP_PLATFORM_HTONL(x) - * - * Note ntohs() and ntohl() are merely references to the htonx counterparts. - */ - -#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) - -/** - * Convert an u16_t from host- to network byte order. - * - * @param n u16_t in host byte order - * @return n in network byte order - */ -u16_t ICACHE_FLASH_ATTR -lwip_htons(u16_t n) -{ - return ((n & 0xff) << 8) | ((n & 0xff00) >> 8); -} - -/** - * Convert an u16_t from network- to host byte order. - * - * @param n u16_t in network byte order - * @return n in host byte order - */ -u16_t ICACHE_FLASH_ATTR -lwip_ntohs(u16_t n) -{ - return lwip_htons(n); -} - -/** - * Convert an u32_t from host- to network byte order. - * - * @param n u32_t in host byte order - * @return n in network byte order - */ -u32_t ICACHE_FLASH_ATTR -lwip_htonl(u32_t n) -{ - return ((n & 0xff) << 24) | - ((n & 0xff00) << 8) | - ((n & 0xff0000UL) >> 8) | - ((n & 0xff000000UL) >> 24); -} - -/** - * Convert an u32_t from network- to host byte order. - * - * @param n u32_t in network byte order - * @return n in host byte order - */ -u32_t ICACHE_FLASH_ATTR -lwip_ntohl(u32_t n) -{ - return lwip_htonl(n); -} - -#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */ diff --git a/third_party/lwip/core/dhcp.c b/third_party/lwip/core/dhcp.c deleted file mode 100644 index 05ceea6..0000000 --- a/third_party/lwip/core/dhcp.c +++ /dev/null @@ -1,1779 +0,0 @@ -/** - * @file - * Dynamic Host Configuration Protocol client - * - */ - -/* - * - * Copyright (c) 2001-2004 Leon Woestenberg - * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. - * 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 a contribution to the lwIP TCP/IP stack. - * The Swedish Institute of Computer Science and Adam Dunkels - * are specifically granted permission to redistribute this - * source code. - * - * Author: Leon Woestenberg - * - * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform - * with RFC 2131 and RFC 2132. - * - * TODO: - * - Support for interfaces other than Ethernet (SLIP, PPP, ...) - * - * Please coordinate changes and requests with Leon Woestenberg - * - * - * Integration with your code: - * - * In lwip/dhcp.h - * #define DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute) - * #define DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer) - * - * Then have your application call dhcp_coarse_tmr() and - * dhcp_fine_tmr() on the defined intervals. - * - * dhcp_start(struct netif *netif); - * starts a DHCP client instance which configures the interface by - * obtaining an IP address lease and maintaining it. - * - * Use dhcp_release(netif) to end the lease and use dhcp_stop(netif) - * to remove the DHCP client. - * - */ - -#include "lwip/opt.h" - -#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/stats.h" -#include "lwip/mem.h" -#include "lwip/udp.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/def.h" -#include "lwip/dhcp.h" -#include "lwip/autoip.h" -#include "lwip/dns.h" -#include "netif/etharp.h" - -#include - -/** DHCP_CREATE_RAND_XID: if this is set to 1, the xid is created using - * LWIP_RAND() (this overrides DHCP_GLOBAL_XID) - */ -#ifndef DHCP_CREATE_RAND_XID -#define DHCP_CREATE_RAND_XID 1 -#endif - -/** Default for DHCP_GLOBAL_XID is 0xABCD0000 - * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g. - * #define DHCP_GLOBAL_XID_HEADER "stdlib.h" - * #define DHCP_GLOBAL_XID rand() - */ -#ifdef DHCP_GLOBAL_XID_HEADER -#include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */ -#endif - -/** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU - * MTU is checked to be big enough in dhcp_start */ -#define DHCP_MAX_MSG_LEN(netif) (netif->mtu) -#define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576 -/** Minimum length for reply before packet is parsed */ -#define DHCP_MIN_REPLY_LEN 44 - -#define REBOOT_TRIES 2 - -/** Option handling: options are parsed in dhcp_parse_reply - * and saved in an array where other functions can load them from. - * This might be moved into the struct dhcp (not necessarily since - * lwIP is single-threaded and the array is only used while in recv - * callback). */ -#define DHCP_OPTION_IDX_OVERLOAD 0 -#define DHCP_OPTION_IDX_MSG_TYPE 1 -#define DHCP_OPTION_IDX_SERVER_ID 2 -#define DHCP_OPTION_IDX_LEASE_TIME 3 -#define DHCP_OPTION_IDX_T1 4 -#define DHCP_OPTION_IDX_T2 5 -#define DHCP_OPTION_IDX_SUBNET_MASK 6 -#define DHCP_OPTION_IDX_ROUTER 7 -#define DHCP_OPTION_IDX_DNS_SERVER 8 -#define DHCP_OPTION_IDX_MAX (DHCP_OPTION_IDX_DNS_SERVER + DNS_MAX_SERVERS) - -/** Holds the decoded option values, only valid while in dhcp_recv. - @todo: move this into struct dhcp? */ -u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX]; -/** Holds a flag which option was received and is contained in dhcp_rx_options_val, - only valid while in dhcp_recv. - @todo: move this into struct dhcp? */ -u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX]; - -#ifdef DHCP_GLOBAL_XID -static u32_t xid; -static u8_t xid_initialised; -#endif /* DHCP_GLOBAL_XID */ - -#define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0) -#define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1) -#define dhcp_clear_option(dhcp, idx) (dhcp_rx_options_given[idx] = 0) -#define dhcp_clear_all_options(dhcp) (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given))) -#define dhcp_get_option_value(dhcp, idx) (dhcp_rx_options_val[idx]) -#define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val)) - - -/* DHCP client state machine functions */ -static err_t dhcp_discover(struct netif *netif); -static err_t dhcp_select(struct netif *netif); -static void dhcp_bind(struct netif *netif); -#if DHCP_DOES_ARP_CHECK -static err_t dhcp_decline(struct netif *netif); -#endif /* DHCP_DOES_ARP_CHECK */ -static err_t dhcp_rebind(struct netif *netif); -static err_t dhcp_reboot(struct netif *netif); -static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state); - -/* receive, unfold, parse and free incoming messages */ -static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port); - -/* set the DHCP timers */ -static void dhcp_timeout(struct netif *netif); -static void dhcp_t1_timeout(struct netif *netif); -static void dhcp_t2_timeout(struct netif *netif); - -/* build outgoing messages */ -/* create a DHCP message, fill in common headers */ -static err_t dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type); -/* free a DHCP request */ -static void dhcp_delete_msg(struct dhcp *dhcp); -/* add a DHCP option (type, then length in bytes) */ -static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len); -/* add option values */ -static void dhcp_option_byte(struct dhcp *dhcp, u8_t value); -static void dhcp_option_short(struct dhcp *dhcp, u16_t value); -static void dhcp_option_long(struct dhcp *dhcp, u32_t value); -#if LWIP_NETIF_HOSTNAME -static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif); -#endif /* LWIP_NETIF_HOSTNAME */ -/* always add the DHCP options trailer to end and pad */ -static void dhcp_option_trailer(struct dhcp *dhcp); - -/** - * Back-off the DHCP client (because of a received NAK response). - * - * Back-off the DHCP client because of a received NAK. Receiving a - * NAK means the client asked for something non-sensible, for - * example when it tries to renew a lease obtained on another network. - * - * We clear any existing set IP address and restart DHCP negotiation - * afresh (as per RFC2131 3.2.3). - * - * @param netif the netif under DHCP control - */ -static void ICACHE_FLASH_ATTR -dhcp_handle_nak(struct netif *netif) -{ - struct dhcp *dhcp = netif->dhcp; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n", - (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); - /* Set the interface down since the address must no longer be used, as per RFC2131 */ - netif_set_down(netif); - /* remove IP address from interface */ - netif_set_ipaddr(netif, IP_ADDR_ANY); - netif_set_gw(netif, IP_ADDR_ANY); - netif_set_netmask(netif, IP_ADDR_ANY); - /* Change to a defined state */ - dhcp_set_state(dhcp, DHCP_BACKING_OFF); - /* We can immediately restart discovery */ - dhcp_discover(netif); -} - -#if DHCP_DOES_ARP_CHECK -/** - * Checks if the offered IP address is already in use. - * - * It does so by sending an ARP request for the offered address and - * entering CHECKING state. If no ARP reply is received within a small - * interval, the address is assumed to be free for use by us. - * - * @param netif the netif under DHCP control - */ -static void ICACHE_FLASH_ATTR -dhcp_check(struct netif *netif) -{ - struct dhcp *dhcp = netif->dhcp; - err_t result; - u16_t msecs; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0], - (s16_t)netif->name[1])); - dhcp_set_state(dhcp, DHCP_CHECKING); - /* create an ARP query for the offered IP address, expecting that no host - responds, as the IP address should not be in use. */ - result = etharp_query(netif, &dhcp->offered_ip_addr, NULL); - if (result != ERR_OK) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n")); - } - dhcp->tries++; - msecs = 500; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs)); -} -#endif /* DHCP_DOES_ARP_CHECK */ - -/** - * Remember the configuration offered by a DHCP server. - * - * @param netif the netif under DHCP control - */ -static void ICACHE_FLASH_ATTR -dhcp_handle_offer(struct netif *netif) -{ - struct dhcp *dhcp = netif->dhcp; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n", - (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); - /* obtain the server address */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) { - ip4_addr_set_u32(&dhcp->server_ip_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID))); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", - ip4_addr_get_u32(&dhcp->server_ip_addr))); - /* remember offered address */ - ip_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", - ip4_addr_get_u32(&dhcp->offered_ip_addr))); - - dhcp_select(netif); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("dhcp_handle_offer(netif=%p) did not get server ID!\n", (void*)netif)); - } -} - -/** - * Select a DHCP server offer out of all offers. - * - * Simply select the first offer received. - * - * @param netif the netif under DHCP control - * @return lwIP specific error (see error.h) - */ -static err_t ICACHE_FLASH_ATTR -dhcp_select(struct netif *netif) -{ - struct dhcp *dhcp = netif->dhcp; - err_t result; - u16_t msecs; - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); - dhcp_set_state(dhcp, DHCP_REQUESTING); - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); - - /* MUST request the offered IP address */ - dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); - dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); - - dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); - dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->server_ip_addr))); - - dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/); - dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK); - dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); - dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); - dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); - -#if LWIP_NETIF_HOSTNAME - dhcp_option_hostname(dhcp, netif); -#endif /* LWIP_NETIF_HOSTNAME */ - - dhcp_option_trailer(dhcp); - /* shrink the pbuf to the actual content length */ - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - /* send broadcast to any DHCP server */ - udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n")); - } - dhcp->tries++; - msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} - -/** - * The DHCP timer that checks for lease renewal/rebind timeouts. - */ -void ICACHE_FLASH_ATTR -dhcp_coarse_tmr() -{ - struct netif *netif = netif_list; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n")); - /* iterate through all network interfaces */ - while (netif != NULL) { - /* only act on DHCP configured interfaces */ - if (netif->dhcp != NULL) { - /* timer is active (non zero), and triggers (zeroes) now? */ - if (netif->dhcp->t2_timeout-- == 1) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n")); - /* this clients' rebind timeout triggered */ - dhcp_t2_timeout(netif); - /* timer is active (non zero), and triggers (zeroes) now */ - } else if (netif->dhcp->t1_timeout-- == 1) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n")); - /* this clients' renewal timeout triggered */ - dhcp_t1_timeout(netif); - } - } - /* proceed to next netif */ - netif = netif->next; - } -} - -/** - * DHCP transaction timeout handling - * - * A DHCP server is expected to respond within a short period of time. - * This timer checks whether an outstanding DHCP request is timed out. - */ -void ICACHE_FLASH_ATTR -dhcp_fine_tmr() -{ - struct netif *netif = netif_list; - /* loop through netif's */ - while (netif != NULL) { - /* only act on DHCP configured interfaces */ - if (netif->dhcp != NULL) { - /* timer is active (non zero), and is about to trigger now */ - if (netif->dhcp->request_timeout > 1) { - netif->dhcp->request_timeout--; - } - else if (netif->dhcp->request_timeout == 1) { - netif->dhcp->request_timeout--; - /* { netif->dhcp->request_timeout == 0 } */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n")); - /* this client's request timeout triggered */ - dhcp_timeout(netif); - } - } - /* proceed to next network interface */ - netif = netif->next; - } -} - -/** - * A DHCP negotiation transaction, or ARP request, has timed out. - * - * The timer that was started with the DHCP or ARP request has - * timed out, indicating no response was received in time. - * - * @param netif the netif under DHCP control - */ -static void ICACHE_FLASH_ATTR -dhcp_timeout(struct netif *netif) -{ - struct dhcp *dhcp = netif->dhcp; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n")); - /* back-off period has passed, or server selection timed out */ - if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n")); - dhcp_discover(netif); - /* receiving the requested lease timed out */ - } else if (dhcp->state == DHCP_REQUESTING) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n")); - if (dhcp->tries <= 5) { - dhcp_select(netif); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n")); - dhcp_release(netif); - dhcp_discover(netif); - } -#if DHCP_DOES_ARP_CHECK - /* received no ARP reply for the offered address (which is good) */ - } else if (dhcp->state == DHCP_CHECKING) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n")); - if (dhcp->tries <= 1) { - dhcp_check(netif); - /* no ARP replies on the offered address, - looks like the IP address is indeed free */ - } else { - /* bind the interface to the offered address */ - dhcp_bind(netif); - } -#endif /* DHCP_DOES_ARP_CHECK */ - } - /* did not get response to renew request? */ - else if (dhcp->state == DHCP_RENEWING) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RENEWING, DHCP request timed out\n")); - /* just retry renewal */ - /* note that the rebind timer will eventually time-out if renew does not work */ - dhcp_renew(netif); - /* did not get response to rebind request? */ - } else if (dhcp->state == DHCP_REBINDING) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REBINDING, DHCP request timed out\n")); - if (dhcp->tries <= 8) { - dhcp_rebind(netif); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): RELEASING, DISCOVERING\n")); - dhcp_release(netif); - dhcp_discover(netif); - } - } else if (dhcp->state == DHCP_REBOOTING) { - if (dhcp->tries < REBOOT_TRIES) { - dhcp_reboot(netif); - } else { - dhcp_discover(netif); - } - } -} - -/** - * The renewal period has timed out. - * - * @param netif the netif under DHCP control - */ -static void ICACHE_FLASH_ATTR -dhcp_t1_timeout(struct netif *netif) -{ - struct dhcp *dhcp = netif->dhcp; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n")); - if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || - (dhcp->state == DHCP_RENEWING)) { - /* just retry to renew - note that the rebind timer (t2) will - * eventually time-out if renew tries fail. */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("dhcp_t1_timeout(): must renew\n")); - /* This slightly different to RFC2131: DHCPREQUEST will be sent from state - DHCP_RENEWING, not DHCP_BOUND */ - dhcp_renew(netif); - } -} - -/** - * The rebind period has timed out. - * - * @param netif the netif under DHCP control - */ -static void ICACHE_FLASH_ATTR -dhcp_t2_timeout(struct netif *netif) -{ - struct dhcp *dhcp = netif->dhcp; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n")); - if ((dhcp->state == DHCP_REQUESTING) || (dhcp->state == DHCP_BOUND) || - (dhcp->state == DHCP_RENEWING)) { - /* just retry to rebind */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("dhcp_t2_timeout(): must rebind\n")); - /* This slightly different to RFC2131: DHCPREQUEST will be sent from state - DHCP_REBINDING, not DHCP_BOUND */ - dhcp_rebind(netif); - } -} - -/** - * Handle a DHCP ACK packet - * - * @param netif the netif under DHCP control - */ -static void ICACHE_FLASH_ATTR -dhcp_handle_ack(struct netif *netif) -{ - struct dhcp *dhcp = netif->dhcp; -#if LWIP_DNS - u8_t n; -#endif /* LWIP_DNS */ - - /* clear options we might not get from the ACK */ - ip_addr_set_zero(&dhcp->offered_sn_mask); - ip_addr_set_zero(&dhcp->offered_gw_addr); -#if LWIP_DHCP_BOOTP_FILE - ip_addr_set_zero(&dhcp->offered_si_addr); -#endif /* LWIP_DHCP_BOOTP_FILE */ - - /* lease time given? */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_LEASE_TIME)) { - /* remember offered lease time */ - dhcp->offered_t0_lease = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_LEASE_TIME); - } - /* renewal period given? */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T1)) { - /* remember given renewal period */ - dhcp->offered_t1_renew = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T1); - } else { - /* calculate safe periods for renewal */ - dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2; - } - - /* renewal period given? */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) { - /* remember given rebind period */ - dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2); - } else { - /* calculate safe periods for rebinding */ - dhcp->offered_t2_rebind = dhcp->offered_t0_lease; - } - - /* (y)our internet address */ - ip_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); - -#if LWIP_DHCP_BOOTP_FILE - /* copy boot server address, - boot file name copied in dhcp_parse_reply if not overloaded */ - ip_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr); -#endif /* LWIP_DHCP_BOOTP_FILE */ - - /* subnet mask given? */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) { - /* remember given subnet mask */ - ip4_addr_set_u32(&dhcp->offered_sn_mask, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK))); - dhcp->subnet_mask_given = 1; - } else { - dhcp->subnet_mask_given = 0; - } - - /* gateway router */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) { - ip4_addr_set_u32(&dhcp->offered_gw_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER))); - } - -#if LWIP_DNS - /* DNS servers */ - for(n = 0; (n < DNS_MAX_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) { - ip_addr_t dns_addr; - ip4_addr_set_u32(&dns_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n))); - dns_setserver(n, &dns_addr); - } -#endif /* LWIP_DNS */ -} - -/** Set a statically allocated struct dhcp to work with. - * Using this prevents dhcp_start to allocate it using mem_malloc. - * - * @param netif the netif for which to set the struct dhcp - * @param dhcp (uninitialised) dhcp struct allocated by the application - */ -void ICACHE_FLASH_ATTR -dhcp_set_struct(struct netif *netif, struct dhcp *dhcp) -{ - LWIP_ASSERT("netif != NULL", netif != NULL); - LWIP_ASSERT("dhcp != NULL", dhcp != NULL); - LWIP_ASSERT("netif already has a struct dhcp set", netif->dhcp == NULL); - - /* clear data structure */ - memset(dhcp, 0, sizeof(struct dhcp)); - /* dhcp_set_state(&dhcp, DHCP_OFF); */ - netif->dhcp = dhcp; -} - -/** Removes a struct dhcp from a netif. - * - * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the - * struct dhcp since the memory is passed back to the heap. - * - * @param netif the netif from which to remove the struct dhcp - */ -void ICACHE_FLASH_ATTR -dhcp_cleanup(struct netif *netif) -{ - LWIP_ASSERT("netif != NULL", netif != NULL); - - if (netif->dhcp != NULL) { - mem_free(netif->dhcp); - netif->dhcp = NULL; - } -} - -/** - * Start DHCP negotiation for a network interface. - * - * If no DHCP client instance was attached to this interface, - * a new client is created first. If a DHCP client instance - * was already present, it restarts negotiation. - * - * @param netif The lwIP network interface - * @return lwIP error code - * - ERR_OK - No error - * - ERR_MEM - Out of memory - */ -err_t ICACHE_FLASH_ATTR -dhcp_start(struct netif *netif) -{ - struct dhcp *dhcp; - err_t result = ERR_OK; - - LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;); - dhcp = netif->dhcp; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); - /* Remove the flag that says this netif is handled by DHCP, - it is set when we succeeded starting. */ - netif->flags &= ~NETIF_FLAG_DHCP; - - /* check hwtype of the netif */ - if ((netif->flags & NETIF_FLAG_ETHARP) == 0) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): No ETHARP netif\n")); - return ERR_ARG; - } - - /* check MTU of the netif */ - if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n")); - return ERR_MEM; - } - - /* no DHCP client attached yet? */ - if (dhcp == NULL) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n")); - dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp)); - if (dhcp == NULL) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n")); - return ERR_MEM; - } - /* store this dhcp client in the netif */ - netif->dhcp = dhcp; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp\n")); - /* already has DHCP client attached */ - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n")); - if (dhcp->pcb != NULL) { - udp_remove(dhcp->pcb); - } - LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL); - LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL ); - } - - /* clear data structure */ - memset(dhcp, 0, sizeof(struct dhcp)); - /* dhcp_set_state(&dhcp, DHCP_OFF); */ - /* allocate UDP PCB */ - dhcp->pcb = udp_new(); - if (dhcp->pcb == NULL) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not obtain pcb\n")); - return ERR_MEM; - } - ip_set_option(dhcp->pcb, SOF_BROADCAST); - /* set up local and remote port for the pcb */ - udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); - udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); - /* set up the recv callback and argument */ - udp_recv(dhcp->pcb, dhcp_recv, netif); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n")); - /* (re)start the DHCP negotiation */ - result = dhcp_discover(netif); - if (result != ERR_OK) { - /* free resources allocated above */ - dhcp_stop(netif); - return ERR_MEM; - } - /* Set the flag that says this netif is handled by DHCP. */ - netif->flags |= NETIF_FLAG_DHCP; - return result; -} - -/** - * Inform a DHCP server of our manual configuration. - * - * This informs DHCP servers of our fixed IP address configuration - * by sending an INFORM message. It does not involve DHCP address - * configuration, it is just here to be nice to the network. - * - * @param netif The lwIP network interface - */ -void ICACHE_FLASH_ATTR -dhcp_inform(struct netif *netif) -{ - struct dhcp dhcp; - err_t result = ERR_OK; - struct udp_pcb *pcb; - - LWIP_ERROR("netif != NULL", (netif != NULL), return;); - - memset(&dhcp, 0, sizeof(struct dhcp)); - dhcp_set_state(&dhcp, DHCP_INFORM); - - if ((netif->dhcp != NULL) && (netif->dhcp->pcb != NULL)) { - /* re-use existing pcb */ - pcb = netif->dhcp->pcb; - } else { - pcb = udp_new(); - if (pcb == NULL) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform(): could not obtain pcb")); - return; - } - dhcp.pcb = pcb; - ip_set_option(dhcp.pcb, SOF_BROADCAST); - udp_bind(dhcp.pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_inform(): created new udp pcb\n")); - } - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, &dhcp, DHCP_INFORM); - if (result == ERR_OK) { - dhcp_option(&dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(&dhcp, DHCP_MAX_MSG_LEN(netif)); - - dhcp_option_trailer(&dhcp); - - pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n")); - udp_sendto_if(pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); - dhcp_delete_msg(&dhcp); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n")); - } - - if (dhcp.pcb != NULL) { - /* otherwise, the existing pcb was used */ - udp_remove(dhcp.pcb); - } -} - -/** Handle a possible change in the network configuration. - * - * This enters the REBOOTING state to verify that the currently bound - * address is still valid. - */ -void ICACHE_FLASH_ATTR -dhcp_network_changed(struct netif *netif) -{ - struct dhcp *dhcp = netif->dhcp; - if (!dhcp) - return; - switch (dhcp->state) { - case DHCP_REBINDING: - case DHCP_RENEWING: - case DHCP_BOUND: - case DHCP_REBOOTING: - netif_set_down(netif); - dhcp->tries = 0; - dhcp_reboot(netif); - break; - case DHCP_OFF: - /* stay off */ - break; - default: - dhcp->tries = 0; -#if LWIP_DHCP_AUTOIP_COOP - if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { - autoip_stop(netif); - dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; - } -#endif /* LWIP_DHCP_AUTOIP_COOP */ - dhcp_discover(netif); - break; - } -} - -#if DHCP_DOES_ARP_CHECK -/** - * Match an ARP reply with the offered IP address. - * - * @param netif the network interface on which the reply was received - * @param addr The IP address we received a reply from - */ -void ICACHE_FLASH_ATTR -dhcp_arp_reply(struct netif *netif, ip_addr_t *addr) -{ - LWIP_ERROR("netif != NULL", (netif != NULL), return;); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n")); - /* is a DHCP client doing an ARP check? */ - if ((netif->dhcp != NULL) && (netif->dhcp->state == DHCP_CHECKING)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", - ip4_addr_get_u32(addr))); - /* did a host respond with the address we - were offered by the DHCP server? */ - if (ip_addr_cmp(addr, &netif->dhcp->offered_ip_addr)) { - /* we will not accept the offered address */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, - ("dhcp_arp_reply(): arp reply matched with offered address, declining\n")); - dhcp_decline(netif); - } - } -} - -/** - * Decline an offered lease. - * - * Tell the DHCP server we do not accept the offered address. - * One reason to decline the lease is when we find out the address - * is already in use by another host (through ARP). - * - * @param netif the netif under DHCP control - */ -static err_t ICACHE_FLASH_ATTR -dhcp_decline(struct netif *netif) -{ - struct dhcp *dhcp = netif->dhcp; - err_t result = ERR_OK; - u16_t msecs; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n")); - dhcp_set_state(dhcp, DHCP_BACKING_OFF); - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); - dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); - - dhcp_option_trailer(dhcp); - /* resize pbuf to reflect true size of options */ - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - /* per section 4.4.4, broadcast DECLINE messages */ - udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("dhcp_decline: could not allocate DHCP request\n")); - } - dhcp->tries++; - msecs = 10*1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} -#endif /* DHCP_DOES_ARP_CHECK */ - - -/** - * Start the DHCP process, discover a DHCP server. - * - * @param netif the netif under DHCP control - */ -static err_t ICACHE_FLASH_ATTR -dhcp_discover(struct netif *netif) -{ - struct dhcp *dhcp = netif->dhcp; - err_t result = ERR_OK; - u16_t msecs; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n")); - ip_addr_set_any(&dhcp->offered_ip_addr); - dhcp_set_state(dhcp, DHCP_SELECTING); - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER); - if (result == ERR_OK) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n")); - - dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); - - dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/); - dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK); - dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); - dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); - dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); - - dhcp_option_trailer(dhcp); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n")); - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n")); - udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); - - dhcp->p_out->type = PBUF_RAM; - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n")); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n")); - } - dhcp->tries++; -#if LWIP_DHCP_AUTOIP_COOP - if(dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) { - dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON; - autoip_start(netif); - } -#endif /* LWIP_DHCP_AUTOIP_COOP */ - msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} - - -/** - * Bind the interface to the offered IP address. - * - * @param netif network interface to bind to the offered address - */ -static void ICACHE_FLASH_ATTR -dhcp_bind(struct netif *netif) -{ - u32_t timeout; - struct dhcp *dhcp; - ip_addr_t sn_mask, gw_addr; - LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;); - dhcp = netif->dhcp; - LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); - - /* temporary DHCP lease? */ - if (dhcp->offered_t1_renew != 0xffffffffUL) { - /* set renewal period timer */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew)); - timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; - if(timeout > 0xffff) { - timeout = 0xffff; - } - dhcp->t1_timeout = (u16_t)timeout; - if (dhcp->t1_timeout == 0) { - dhcp->t1_timeout = 1; - } - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000)); - } - /* set renewal period timer */ - if (dhcp->offered_t2_rebind != 0xffffffffUL) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind)); - timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; - if(timeout > 0xffff) { - timeout = 0xffff; - } - dhcp->t2_timeout = (u16_t)timeout; - if (dhcp->t2_timeout == 0) { - dhcp->t2_timeout = 1; - } - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000)); - } - - /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */ - if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) { - dhcp->t1_timeout = 0; - } - - if (dhcp->subnet_mask_given) { - /* copy offered network mask */ - ip_addr_copy(sn_mask, dhcp->offered_sn_mask); - } else { - /* subnet mask not given, choose a safe subnet mask given the network class */ - u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr); - if (first_octet <= 127) { - ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL)); - } else if (first_octet >= 192) { - ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL)); - } else { - ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL)); - } - } - - ip_addr_copy(gw_addr, dhcp->offered_gw_addr); - /* gateway address not given? */ - if (ip_addr_isany(&gw_addr)) { - /* copy network address */ - ip_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask); - /* use first host address on network as gateway */ - ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL)); - } - -#if LWIP_DHCP_AUTOIP_COOP - if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { - autoip_stop(netif); - dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; - } -#endif /* LWIP_DHCP_AUTOIP_COOP */ - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n", - ip4_addr_get_u32(&dhcp->offered_ip_addr))); - netif_set_ipaddr(netif, &dhcp->offered_ip_addr); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): SN: 0x%08"X32_F"\n", - ip4_addr_get_u32(&sn_mask))); - netif_set_netmask(netif, &sn_mask); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n", - ip4_addr_get_u32(&gw_addr))); - - system_station_got_ip_set(&dhcp->offered_ip_addr, &sn_mask, &gw_addr); - - netif_set_gw(netif, &gw_addr); - /* bring the interface up */ - netif_set_up(netif); - /* netif is now bound to DHCP leased address */ - dhcp_set_state(dhcp, DHCP_BOUND); -} - -/** - * Renew an existing DHCP lease at the involved DHCP server. - * - * @param netif network interface which must renew its lease - */ -err_t ICACHE_FLASH_ATTR -dhcp_renew(struct netif *netif) -{ - struct dhcp *dhcp = netif->dhcp; - err_t result; - u16_t msecs; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n")); - dhcp_set_state(dhcp, DHCP_RENEWING); - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); - -#if 0 - dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); - dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr)); -#endif - -#if 0 - dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); - dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); -#endif - -#if LWIP_NETIF_HOSTNAME - dhcp_option_hostname(dhcp, netif); -#endif /* LWIP_NETIF_HOSTNAME */ - - /* append DHCP message trailer */ - dhcp_option_trailer(dhcp); - - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); - dhcp_delete_msg(dhcp); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n")); - } - dhcp->tries++; - /* back-off on retries, but to a maximum of 20 seconds */ - msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} - -/** - * Rebind with a DHCP server for an existing DHCP lease. - * - * @param netif network interface which must rebind with a DHCP server - */ -static err_t ICACHE_FLASH_ATTR -dhcp_rebind(struct netif *netif) -{ - struct dhcp *dhcp = netif->dhcp; - err_t result; - u16_t msecs; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n")); - dhcp_set_state(dhcp, DHCP_REBINDING); - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); - -#if LWIP_NETIF_HOSTNAME - dhcp_option_hostname(dhcp, netif); -#endif /* LWIP_NETIF_HOSTNAME */ - -#if 0 - dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); - dhcp_option_long(dhcp, ntohl(dhcp->offered_ip_addr.addr)); - - dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); - dhcp_option_long(dhcp, ntohl(dhcp->server_ip_addr.addr)); -#endif - - dhcp_option_trailer(dhcp); - - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - /* broadcast to server */ - udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n")); - } - dhcp->tries++; - msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} - -/** - * Enter REBOOTING state to verify an existing lease - * - * @param netif network interface which must reboot - */ -static err_t ICACHE_FLASH_ATTR -dhcp_reboot(struct netif *netif) -{ - struct dhcp *dhcp = netif->dhcp; - err_t result; - u16_t msecs; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n")); - dhcp_set_state(dhcp, DHCP_REBOOTING); - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(dhcp, 576); - - dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); - dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); - - dhcp_option_trailer(dhcp); - - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - /* broadcast to server */ - udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n")); - } - dhcp->tries++; - msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} - - -/** - * Release a DHCP lease. - * - * @param netif network interface which must release its lease - */ -err_t ICACHE_FLASH_ATTR -dhcp_release(struct netif *netif) -{ - struct dhcp *dhcp = netif->dhcp; - err_t result; - u16_t msecs; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n")); - if (dhcp == NULL) { - return ERR_ARG; - } - - /* idle DHCP client */ - dhcp_set_state(dhcp, DHCP_OFF); - /* clean old DHCP offer */ - ip_addr_set_zero(&dhcp->server_ip_addr); - ip_addr_set_zero(&dhcp->offered_ip_addr); - ip_addr_set_zero(&dhcp->offered_sn_mask); - ip_addr_set_zero(&dhcp->offered_gw_addr); -#if LWIP_DHCP_BOOTP_FILE - ip_addr_set_zero(&dhcp->offered_si_addr); -#endif /* LWIP_DHCP_BOOTP_FILE */ - dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0; - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE); - if (result == ERR_OK) { - dhcp_option_trailer(dhcp); - - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n")); - } - dhcp->tries++; - msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release(): set request timeout %"U16_F" msecs\n", msecs)); - /* bring the interface down */ - netif_set_down(netif); - /* remove IP address from interface */ - netif_set_ipaddr(netif, IP_ADDR_ANY); - netif_set_gw(netif, IP_ADDR_ANY); - netif_set_netmask(netif, IP_ADDR_ANY); - - return result; -} - -/** - * Remove the DHCP client from the interface. - * - * @param netif The network interface to stop DHCP on - */ -void ICACHE_FLASH_ATTR -dhcp_stop(struct netif *netif) -{ - struct dhcp *dhcp; - LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;); - dhcp = netif->dhcp; - /* Remove the flag that says this netif is handled by DHCP. */ - netif->flags &= ~NETIF_FLAG_DHCP; - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n")); - /* netif is DHCP configured? */ - if (dhcp != NULL) { -#if LWIP_DHCP_AUTOIP_COOP - if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { - autoip_stop(netif); - dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; - } -#endif /* LWIP_DHCP_AUTOIP_COOP */ - - if (dhcp->pcb != NULL) { - udp_remove(dhcp->pcb); - dhcp->pcb = NULL; - } - LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); - dhcp_set_state(dhcp, DHCP_OFF); - } -} - -/* - * Set the DHCP state of a DHCP client. - * - * If the state changed, reset the number of tries. - */ -static void ICACHE_FLASH_ATTR -dhcp_set_state(struct dhcp *dhcp, u8_t new_state) -{ - if (new_state != dhcp->state) { - dhcp->state = new_state; - dhcp->tries = 0; - dhcp->request_timeout = 0; - } -} - -/* - * Concatenate an option type and length field to the outgoing - * DHCP message. - * - */ -static void ICACHE_FLASH_ATTR -dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len) -{ - LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN); - dhcp->msg_out->options[dhcp->options_out_len++] = option_type; - dhcp->msg_out->options[dhcp->options_out_len++] = option_len; -} -/* - * Concatenate a single byte to the outgoing DHCP message. - * - */ -static void ICACHE_FLASH_ATTR -dhcp_option_byte(struct dhcp *dhcp, u8_t value) -{ - LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN); - dhcp->msg_out->options[dhcp->options_out_len++] = value; -} - -static void ICACHE_FLASH_ATTR -dhcp_option_short(struct dhcp *dhcp, u16_t value) -{ - LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU); -} - -static void ICACHE_FLASH_ATTR -dhcp_option_long(struct dhcp *dhcp, u32_t value) -{ - LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL)); -} - -#if LWIP_NETIF_HOSTNAME -static void ICACHE_FLASH_ATTR -dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif) -{ - if (netif->hostname != NULL) { - size_t namelen = strlen(netif->hostname); - if (namelen > 0) { - u8_t len; - const char *p = netif->hostname; - /* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME - and 1 byte for trailer) */ - size_t available = DHCP_OPTIONS_LEN - dhcp->options_out_len - 3; - LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available); - len = LWIP_MIN(namelen, available); - dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, len); - while (len--) { - dhcp_option_byte(dhcp, *p++); - } - } - } -} -#endif /* LWIP_NETIF_HOSTNAME */ - -/** - * Extract the DHCP message and the DHCP options. - * - * Extract the DHCP message and the DHCP options, each into a contiguous - * piece of memory. As a DHCP message is variable sized by its options, - * and also allows overriding some fields for options, the easy approach - * is to first unfold the options into a conitguous piece of memory, and - * use that further on. - * - */ -static err_t ICACHE_FLASH_ATTR -dhcp_parse_reply(struct dhcp *dhcp, struct pbuf *p) -{ - u8_t *options; - u16_t offset; - u16_t offset_max; - u16_t options_idx; - u16_t options_idx_max; - struct pbuf *q; - int parse_file_as_options = 0; - int parse_sname_as_options = 0; - - /* clear received options */ - dhcp_clear_all_options(dhcp); - /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */ - if (p->len < DHCP_SNAME_OFS) { - return ERR_BUF; - } - dhcp->msg_in = (struct dhcp_msg *)p->payload; -#if LWIP_DHCP_BOOTP_FILE - /* clear boot file name */ - dhcp->boot_file_name[0] = 0; -#endif /* LWIP_DHCP_BOOTP_FILE */ - - /* parse options */ - - /* start with options field */ - options_idx = DHCP_OPTIONS_OFS; - /* parse options to the end of the received packet */ - options_idx_max = p->tot_len; -again: - q = p; - while((q != NULL) && (options_idx >= q->len)) { - options_idx -= q->len; - options_idx_max -= q->len; - q = q->next; - } - if (q == NULL) { - return ERR_BUF; - } - offset = options_idx; - offset_max = options_idx_max; - options = (u8_t*)q->payload; - /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */ - while((q != NULL) && (options[offset] != DHCP_OPTION_END) && (offset < offset_max)) { - u8_t op = options[offset]; - u8_t len; - u8_t decode_len = 0; - int decode_idx = -1; - u16_t val_offset = offset + 2; - /* len byte might be in the next pbuf */ - if (offset + 1 < q->len) { - len = options[offset + 1]; - } else { - len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0); - } - /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */ - decode_len = len; - switch(op) { - /* case(DHCP_OPTION_END): handled above */ - case(DHCP_OPTION_PAD): - /* special option: no len encoded */ - decode_len = len = 0; - /* will be increased below */ - offset--; - break; - case(DHCP_OPTION_SUBNET_MASK): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_SUBNET_MASK; - break; - case(DHCP_OPTION_ROUTER): - decode_len = 4; /* only copy the first given router */ - LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_ROUTER; - break; - case(DHCP_OPTION_DNS_SERVER): - /* special case: there might be more than one server */ - LWIP_ERROR("len % 4 == 0", len % 4 == 0, return ERR_VAL;); - /* limit number of DNS servers */ - decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS); - LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_DNS_SERVER; - break; - case(DHCP_OPTION_LEASE_TIME): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_LEASE_TIME; - break; - case(DHCP_OPTION_OVERLOAD): - LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_OVERLOAD; - break; - case(DHCP_OPTION_MESSAGE_TYPE): - LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_MSG_TYPE; - break; - case(DHCP_OPTION_SERVER_ID): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_SERVER_ID; - break; - case(DHCP_OPTION_T1): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_T1; - break; - case(DHCP_OPTION_T2): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_T2; - break; - default: - decode_len = 0; - LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", op)); - break; - } - offset += len + 2; - if (decode_len > 0) { - u32_t value = 0; - u16_t copy_len; -decode_next: - LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX); - if (!dhcp_option_given(dhcp, decode_idx)) { - copy_len = LWIP_MIN(decode_len, 4); - pbuf_copy_partial(q, &value, copy_len, val_offset); - if (decode_len > 4) { - /* decode more than one u32_t */ - LWIP_ERROR("decode_len % 4 == 0", decode_len % 4 == 0, return ERR_VAL;); - dhcp_got_option(dhcp, decode_idx); - dhcp_set_option_value(dhcp, decode_idx, htonl(value)); - decode_len -= 4; - val_offset += 4; - decode_idx++; - goto decode_next; - } else if (decode_len == 4) { - value = ntohl(value); - } else { - LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;); - value = ((u8_t*)&value)[0]; - } - dhcp_got_option(dhcp, decode_idx); - dhcp_set_option_value(dhcp, decode_idx, value); - } - } - if (offset >= q->len) { - offset -= q->len; - offset_max -= q->len; - if ((offset < offset_max) && offset_max) { - q = q->next; - LWIP_ASSERT("next pbuf was null", q); - options = (u8_t*)q->payload; - } else { - /* We've run out of bytes, probably no end marker. Don't proceed. */ - break; - } - } - } - /* is this an overloaded message? */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) { - u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD); - dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD); - if (overload == DHCP_OVERLOAD_FILE) { - parse_file_as_options = 1; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n")); - } else if (overload == DHCP_OVERLOAD_SNAME) { - parse_sname_as_options = 1; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n")); - } else if (overload == DHCP_OVERLOAD_SNAME_FILE) { - parse_sname_as_options = 1; - parse_file_as_options = 1; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload)); - } -#if LWIP_DHCP_BOOTP_FILE - if (!parse_file_as_options) { - /* only do this for ACK messages */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) && - (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK)) - /* copy bootp file name, don't care for sname (server hostname) */ - pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS); - /* make sure the string is really NULL-terminated */ - dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0; - } -#endif /* LWIP_DHCP_BOOTP_FILE */ - } - if (parse_file_as_options) { - /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */ - parse_file_as_options = 0; - options_idx = DHCP_FILE_OFS; - options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN; - goto again; - } else if (parse_sname_as_options) { - parse_sname_as_options = 0; - options_idx = DHCP_SNAME_OFS; - options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN; - goto again; - } - return ERR_OK; -} - -/** - * If an incoming DHCP message is in response to us, then trigger the state machine - */ -static void ICACHE_FLASH_ATTR -dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) -{ - struct netif *netif = (struct netif *)arg; - struct dhcp *dhcp = netif->dhcp; - struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload; - u8_t msg_type; - u8_t i; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p, - ip4_addr1_16(addr), ip4_addr2_16(addr), ip4_addr3_16(addr), ip4_addr4_16(addr), port)); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len)); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len)); - /* prevent warnings about unused arguments */ - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(addr); - LWIP_UNUSED_ARG(port); - - LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); - - if (p->len < DHCP_MIN_REPLY_LEN) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n")); - goto free_pbuf_and_return; - } - - if (reply_msg->op != DHCP_BOOTREPLY) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op)); - goto free_pbuf_and_return; - } - /* iterate through hardware address and match against DHCP message */ - for (i = 0; i < netif->hwaddr_len; i++) { - if (netif->hwaddr[i] != reply_msg->chaddr[i]) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n", - (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i])); - goto free_pbuf_and_return; - } - } - /* match transaction ID against what we expected */ - if (ntohl(reply_msg->xid) != dhcp->xid) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid)); - goto free_pbuf_and_return; - } - /* option fields could be unfold? */ - if (dhcp_parse_reply(dhcp, p) != ERR_OK) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("problem unfolding DHCP message - too short on memory?\n")); - goto free_pbuf_and_return; - } - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n")); - /* obtain pointer to DHCP message type */ - if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n")); - goto free_pbuf_and_return; - } - - /* read DHCP message type */ - msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE); - /* message type is DHCP ACK? */ - if (msg_type == DHCP_ACK) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n")); - /* in requesting state? */ - if (dhcp->state == DHCP_REQUESTING) { - dhcp_handle_ack(netif); -#if DHCP_DOES_ARP_CHECK - /* check if the acknowledged lease address is already in use */ - dhcp_check(netif); -#else - /* bind interface to the acknowledged lease address */ - dhcp_bind(netif); -#endif - } - /* already bound to the given lease address? */ - else if ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING)) { - dhcp_bind(netif); - } - } - /* received a DHCP_NAK in appropriate state? */ - else if ((msg_type == DHCP_NAK) && - ((dhcp->state == DHCP_REBOOTING) || (dhcp->state == DHCP_REQUESTING) || - (dhcp->state == DHCP_REBINDING) || (dhcp->state == DHCP_RENEWING ))) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n")); - dhcp_handle_nak(netif); - } - /* received a DHCP_OFFER in DHCP_SELECTING state? */ - else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_SELECTING)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_SELECTING state\n")); - dhcp->request_timeout = 0; - /* remember offered lease */ - dhcp_handle_offer(netif); - } -free_pbuf_and_return: - dhcp->msg_in = NULL; - pbuf_free(p); -} - -/** - * Create a DHCP request, fill in common headers - * - * @param netif the netif under DHCP control - * @param dhcp dhcp control struct - * @param message_type message type of the request - */ -static err_t ICACHE_FLASH_ATTR -dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type) -{ - u16_t i; -#ifndef DHCP_GLOBAL_XID - /** default global transaction identifier starting value (easy to match - * with a packet analyser). We simply increment for each new request. - * Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one - * at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */ -#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) - static u32_t xid; -#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ - static u32_t xid = 0xABCD0000; -#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ -#else - if (!xid_initialised) { - xid = DHCP_GLOBAL_XID; - xid_initialised = !xid_initialised; - } -#endif - LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return ERR_ARG;); - LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return ERR_VAL;); - LWIP_ASSERT("dhcp_create_msg: dhcp->p_out == NULL", dhcp->p_out == NULL); - LWIP_ASSERT("dhcp_create_msg: dhcp->msg_out == NULL", dhcp->msg_out == NULL); - dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM); - if (dhcp->p_out == NULL) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("dhcp_create_msg(): could not allocate pbuf\n")); - return ERR_MEM; - } - LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg", - (dhcp->p_out->len >= sizeof(struct dhcp_msg))); - - /* reuse transaction identifier in retransmissions */ - if (dhcp->tries == 0) { -#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) - xid = LWIP_RAND(); -#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ - xid++; -#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ - } - dhcp->xid = xid; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, - ("transaction id xid(%"X32_F")\n", xid)); - - dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload; - - dhcp->msg_out->op = DHCP_BOOTREQUEST; - /* TODO: make link layer independent */ - dhcp->msg_out->htype = DHCP_HTYPE_ETH; - dhcp->msg_out->hlen = netif->hwaddr_len; - dhcp->msg_out->hops = 0; - dhcp->msg_out->xid = htonl(dhcp->xid); - dhcp->msg_out->secs = 0; - /* we don't need the broadcast flag since we can receive unicast traffic - before being fully configured! */ - dhcp->msg_out->flags = 0; - ip_addr_set_zero(&dhcp->msg_out->ciaddr); - /* set ciaddr to netif->ip_addr based on message_type and state */ - if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) || - ((message_type == DHCP_REQUEST) && /* DHCP_BOUND not used for sending! */ - ((dhcp->state==DHCP_RENEWING) || dhcp->state==DHCP_REBINDING))) { - ip_addr_copy(dhcp->msg_out->ciaddr, netif->ip_addr); - } - ip_addr_set_zero(&dhcp->msg_out->yiaddr); - ip_addr_set_zero(&dhcp->msg_out->siaddr); - ip_addr_set_zero(&dhcp->msg_out->giaddr); - for (i = 0; i < DHCP_CHADDR_LEN; i++) { - /* copy netif hardware address, pad with zeroes */ - dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN) ? netif->hwaddr[i] : 0/* pad byte*/; - } - for (i = 0; i < DHCP_SNAME_LEN; i++) { - dhcp->msg_out->sname[i] = 0; - } - for (i = 0; i < DHCP_FILE_LEN; i++) { - dhcp->msg_out->file[i] = 0; - } - dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE); - dhcp->options_out_len = 0; - /* fill options field with an incrementing array (for debugging purposes) */ - for (i = 0; i < DHCP_OPTIONS_LEN; i++) { - dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */ - } - /* Add option MESSAGE_TYPE */ - dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); - dhcp_option_byte(dhcp, message_type); - return ERR_OK; -} - -/** - * Free previously allocated memory used to send a DHCP request. - * - * @param dhcp the dhcp struct to free the request from - */ -static void ICACHE_FLASH_ATTR -dhcp_delete_msg(struct dhcp *dhcp) -{ - LWIP_ERROR("dhcp_delete_msg: dhcp != NULL", (dhcp != NULL), return;); - LWIP_ASSERT("dhcp_delete_msg: dhcp->p_out != NULL", dhcp->p_out != NULL); - LWIP_ASSERT("dhcp_delete_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL); - if (dhcp->p_out != NULL) { - pbuf_free(dhcp->p_out); - } - dhcp->p_out = NULL; - dhcp->msg_out = NULL; -} - -/** - * Add a DHCP message trailer - * - * Adds the END option to the DHCP message, and if - * necessary, up to three padding bytes. - * - * @param dhcp DHCP state structure - */ -static void ICACHE_FLASH_ATTR -dhcp_option_trailer(struct dhcp *dhcp) -{ - LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;); - LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL); - LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN); - dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END; - /* packet is too small, or not 4 byte aligned? */ - while (((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) && - (dhcp->options_out_len < DHCP_OPTIONS_LEN)) { - /* add a fill/padding byte */ - dhcp->msg_out->options[dhcp->options_out_len++] = 0; - } -} - -#endif /* LWIP_DHCP */ diff --git a/third_party/lwip/core/dns.c b/third_party/lwip/core/dns.c deleted file mode 100644 index 77142e8..0000000 --- a/third_party/lwip/core/dns.c +++ /dev/null @@ -1,988 +0,0 @@ -/** - * @file - * DNS - host name to IP address resolver. - * - */ - -/** - - * This file implements a DNS host name to IP address resolver. - - * Port to lwIP from uIP - * by Jim Pettinato April 2007 - - * uIP version Copyright (c) 2002-2003, Adam Dunkels. - * 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. - * - * - * DNS.C - * - * The lwIP DNS resolver functions are used to lookup a host name and - * map it to a numerical IP address. It maintains a list of resolved - * hostnames that can be queried with the dns_lookup() function. - * New hostnames can be resolved using the dns_query() function. - * - * The lwIP version of the resolver also adds a non-blocking version of - * gethostbyname() that will work with a raw API application. This function - * checks for an IP address string first and converts it if it is valid. - * gethostbyname() then does a dns_lookup() to see if the name is - * already in the table. If so, the IP is returned. If not, a query is - * issued and the function returns with a ERR_INPROGRESS status. The app - * using the dns client must then go into a waiting state. - * - * Once a hostname has been resolved (or found to be non-existent), - * the resolver code calls a specified callback function (which - * must be implemented by the module that uses the resolver). - */ - -/*----------------------------------------------------------------------------- - * RFC 1035 - Domain names - implementation and specification - * RFC 2181 - Clarifications to the DNS Specification - *----------------------------------------------------------------------------*/ - -/** @todo: define good default values (rfc compliance) */ -/** @todo: improve answer parsing, more checkings... */ -/** @todo: check RFC1035 - 7.3. Processing responses */ - -/*----------------------------------------------------------------------------- - * Includes - *----------------------------------------------------------------------------*/ - -#include "lwip/opt.h" - -#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/udp.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/dns.h" - -#include - -/** DNS server IP address */ -#ifndef DNS_SERVER_ADDRESS -#define DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */ -#endif - -/** DNS server port address */ -#ifndef DNS_SERVER_PORT -#define DNS_SERVER_PORT 53 -#endif - -/** DNS maximum number of retries when asking for a name, before "timeout". */ -#ifndef DNS_MAX_RETRIES -#define DNS_MAX_RETRIES 4 -#endif - -/** DNS resource record max. TTL (one week as default) */ -#ifndef DNS_MAX_TTL -#define DNS_MAX_TTL 604800 -#endif - -/* DNS protocol flags */ -#define DNS_FLAG1_RESPONSE 0x80 -#define DNS_FLAG1_OPCODE_STATUS 0x10 -#define DNS_FLAG1_OPCODE_INVERSE 0x08 -#define DNS_FLAG1_OPCODE_STANDARD 0x00 -#define DNS_FLAG1_AUTHORATIVE 0x04 -#define DNS_FLAG1_TRUNC 0x02 -#define DNS_FLAG1_RD 0x01 -#define DNS_FLAG2_RA 0x80 -#define DNS_FLAG2_ERR_MASK 0x0f -#define DNS_FLAG2_ERR_NONE 0x00 -#define DNS_FLAG2_ERR_NAME 0x03 - -/* DNS protocol states */ -#define DNS_STATE_UNUSED 0 -#define DNS_STATE_NEW 1 -#define DNS_STATE_ASKING 2 -#define DNS_STATE_DONE 3 - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/** DNS message header */ -struct dns_hdr { - PACK_STRUCT_FIELD(u16_t id); - PACK_STRUCT_FIELD(u8_t flags1); - PACK_STRUCT_FIELD(u8_t flags2); - PACK_STRUCT_FIELD(u16_t numquestions); - PACK_STRUCT_FIELD(u16_t numanswers); - PACK_STRUCT_FIELD(u16_t numauthrr); - PACK_STRUCT_FIELD(u16_t numextrarr); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif -#define SIZEOF_DNS_HDR 12 - -/** DNS query message structure. - No packing needed: only used locally on the stack. */ -struct dns_query { - /* DNS query record starts with either a domain name or a pointer - to a name already present somewhere in the packet. */ - u16_t type; - u16_t cls; -}; -#define SIZEOF_DNS_QUERY 4 - -/** DNS answer message structure. - No packing needed: only used locally on the stack. */ -struct dns_answer { - /* DNS answer record starts with either a domain name or a pointer - to a name already present somewhere in the packet. */ - u16_t type; - u16_t cls; - u32_t ttl; - u16_t len; -}; -#define SIZEOF_DNS_ANSWER 10 - -/** DNS table entry */ -struct dns_table_entry { - u8_t state; - u8_t numdns; - u8_t tmr; - u8_t retries; - u8_t seqno; - u8_t err; - u32_t ttl; - char name[DNS_MAX_NAME_LENGTH]; - ip_addr_t ipaddr; - /* pointer to callback on DNS query done */ - dns_found_callback found; - void *arg; -}; - -#if DNS_LOCAL_HOSTLIST - -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC -/** Local host-list. For hostnames in this list, no - * external name resolution is performed */ -static struct local_hostlist_entry *local_hostlist_dynamic; -#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - -/** Defining this allows the local_hostlist_static to be placed in a different - * linker section (e.g. FLASH) */ -#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE -#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static -#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */ -/** Defining this allows the local_hostlist_static to be placed in a different - * linker section (e.g. FLASH) */ -#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST -#define DNS_LOCAL_HOSTLIST_STORAGE_POST -#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */ -DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[] - DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT; - -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - -static void dns_init_local(); -#endif /* DNS_LOCAL_HOSTLIST */ - - -/* forward declarations */ -static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port); -static void dns_check_entries(void); - -/*----------------------------------------------------------------------------- - * Globales - *----------------------------------------------------------------------------*/ - -/* DNS variables */ -static struct udp_pcb *dns_pcb; -static u8_t dns_seqno; -static struct dns_table_entry dns_table[DNS_TABLE_SIZE]; -static ip_addr_t dns_servers[DNS_MAX_SERVERS]; -/** Contiguous buffer for processing responses */ -static u8_t dns_payload_buffer[LWIP_MEM_ALIGN_BUFFER(DNS_MSG_SIZE)]; -static u8_t* dns_payload; - -/** - * Initialize the resolver: set up the UDP pcb and configure the default server - * (DNS_SERVER_ADDRESS). - */ -void ICACHE_FLASH_ATTR -dns_init() -{ - ip_addr_t dnsserver; - - dns_payload = (u8_t *)LWIP_MEM_ALIGN(dns_payload_buffer); - - /* initialize default DNS server address */ - DNS_SERVER_ADDRESS(&dnsserver); - - LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n")); - - /* if dns client not yet initialized... */ - if (dns_pcb == NULL) { - dns_pcb = udp_new(); - - if (dns_pcb != NULL) { - /* initialize DNS table not needed (initialized to zero since it is a - * global variable) */ - LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0", - DNS_STATE_UNUSED == 0); - - /* initialize DNS client */ - udp_bind(dns_pcb, IP_ADDR_ANY, 0); - udp_recv(dns_pcb, dns_recv, NULL); - - /* initialize default DNS primary server */ - dns_setserver(0, &dnsserver); - } - } -#if DNS_LOCAL_HOSTLIST - dns_init_local(); -#endif -} - -/** - * Initialize one of the DNS servers. - * - * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS - * @param dnsserver IP address of the DNS server to set - */ -void ICACHE_FLASH_ATTR -dns_setserver(u8_t numdns, ip_addr_t *dnsserver) -{ - if ((numdns < DNS_MAX_SERVERS) && (dns_pcb != NULL) && - (dnsserver != NULL) && !ip_addr_isany(dnsserver)) { - dns_servers[numdns] = (*dnsserver); - } -} - -/** - * Obtain one of the currently configured DNS server. - * - * @param numdns the index of the DNS server - * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS - * server has not been configured. - */ -ip_addr_t ICACHE_FLASH_ATTR -dns_getserver(u8_t numdns) -{ - if (numdns < DNS_MAX_SERVERS) { - return dns_servers[numdns]; - } else { - return *IP_ADDR_ANY; - } -} - -/** - * The DNS resolver client timer - handle retries and timeouts and should - * be called every DNS_TMR_INTERVAL milliseconds (every second by default). - */ -void ICACHE_FLASH_ATTR -dns_tmr(void) -{ - if (dns_pcb != NULL) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n")); - dns_check_entries(); - } -} - -#if DNS_LOCAL_HOSTLIST -static void ICACHE_FLASH_ATTR -dns_init_local() -{ -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) - int i; - struct local_hostlist_entry *entry; - /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */ - struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT; - size_t namelen; - for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) { - struct local_hostlist_entry *init_entry = &local_hostlist_init[i]; - LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL); - namelen = strlen(init_entry->name); - LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); - entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); - LWIP_ASSERT("mem-error in dns_init_local", entry != NULL); - if (entry != NULL) { - entry->name = (char*)entry + sizeof(struct local_hostlist_entry); - MEMCPY((char*)entry->name, init_entry->name, namelen); - ((char*)entry->name)[namelen] = 0; - entry->addr = init_entry->addr; - entry->next = local_hostlist_dynamic; - local_hostlist_dynamic = entry; - } - } -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */ -} - -/** - * Scans the local host-list for a hostname. - * - * @param hostname Hostname to look for in the local host-list - * @return The first IP address for the hostname in the local host-list or - * IPADDR_NONE if not found. - */ -static u32_t ICACHE_FLASH_ATTR -dns_lookup_local(const char *hostname) -{ -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC - struct local_hostlist_entry *entry = local_hostlist_dynamic; - while(entry != NULL) { - if(strcmp(entry->name, hostname) == 0) { - return ip4_addr_get_u32(&entry->addr); - } - entry = entry->next; - } -#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - int i; - for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) { - if(strcmp(local_hostlist_static[i].name, hostname) == 0) { - return ip4_addr_get_u32(&local_hostlist_static[i].addr); - } - } -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - return IPADDR_NONE; -} - -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC -/** Remove all entries from the local host-list for a specific hostname - * and/or IP addess - * - * @param hostname hostname for which entries shall be removed from the local - * host-list - * @param addr address for which entries shall be removed from the local host-list - * @return the number of removed entries - */ -int ICACHE_FLASH_ATTR -dns_local_removehost(const char *hostname, const ip_addr_t *addr) -{ - int removed = 0; - struct local_hostlist_entry *entry = local_hostlist_dynamic; - struct local_hostlist_entry *last_entry = NULL; - while (entry != NULL) { - if (((hostname == NULL) || !strcmp(entry->name, hostname)) && - ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) { - struct local_hostlist_entry *free_entry; - if (last_entry != NULL) { - last_entry->next = entry->next; - } else { - local_hostlist_dynamic = entry->next; - } - free_entry = entry; - entry = entry->next; - memp_free(MEMP_LOCALHOSTLIST, free_entry); - removed++; - } else { - last_entry = entry; - entry = entry->next; - } - } - return removed; -} - -/** - * Add a hostname/IP address pair to the local host-list. - * Duplicates are not checked. - * - * @param hostname hostname of the new entry - * @param addr IP address of the new entry - * @return ERR_OK if succeeded or ERR_MEM on memory error - */ -err_t ICACHE_FLASH_ATTR -dns_local_addhost(const char *hostname, const ip_addr_t *addr) -{ - struct local_hostlist_entry *entry; - size_t namelen; - LWIP_ASSERT("invalid host name (NULL)", hostname != NULL); - namelen = strlen(hostname); - LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); - entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); - if (entry == NULL) { - return ERR_MEM; - } - entry->name = (char*)entry + sizeof(struct local_hostlist_entry); - MEMCPY((char*)entry->name, hostname, namelen); - ((char*)entry->name)[namelen] = 0; - ip_addr_copy(entry->addr, *addr); - entry->next = local_hostlist_dynamic; - local_hostlist_dynamic = entry; - return ERR_OK; -} -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/ -#endif /* DNS_LOCAL_HOSTLIST */ - -/** - * Look up a hostname in the array of known hostnames. - * - * @note This function only looks in the internal array of known - * hostnames, it does not send out a query for the hostname if none - * was found. The function dns_enqueue() can be used to send a query - * for a hostname. - * - * @param name the hostname to look up - * @return the hostname's IP address, as u32_t (instead of ip_addr_t to - * better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname - * was not found in the cached dns_table. - */ -static u32_t ICACHE_FLASH_ATTR -dns_lookup(const char *name) -{ - u8_t i; -#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) - u32_t addr; -#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */ -#if DNS_LOCAL_HOSTLIST - if ((addr = dns_lookup_local(name)) != IPADDR_NONE) { - return addr; - } -#endif /* DNS_LOCAL_HOSTLIST */ -#ifdef DNS_LOOKUP_LOCAL_EXTERN - if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != IPADDR_NONE) { - return addr; - } -#endif /* DNS_LOOKUP_LOCAL_EXTERN */ - - /* Walk through name list, return entry if found. If not, return NULL. */ - for (i = 0; i < DNS_TABLE_SIZE; ++i) { - if ((dns_table[i].state == DNS_STATE_DONE) && - (strcmp(name, dns_table[i].name) == 0)) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name)); - ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr)); - LWIP_DEBUGF(DNS_DEBUG, ("\n")); - return ip4_addr_get_u32(&dns_table[i].ipaddr); - } - } - - return IPADDR_NONE; -} - -#if DNS_DOES_NAME_CHECK -/** - * Compare the "dotted" name "query" with the encoded name "response" - * to make sure an answer from the DNS server matches the current dns_table - * entry (otherwise, answers might arrive late for hostname not on the list - * any more). - * - * @param query hostname (not encoded) from the dns_table - * @param response encoded hostname in the DNS response - * @return 0: names equal; 1: names differ - */ -static u8_t ICACHE_FLASH_ATTR -dns_compare_name(unsigned char *query, unsigned char *response) -{ - unsigned char n; - - do { - n = *response++; - /** @see RFC 1035 - 4.1.4. Message compression */ - if ((n & 0xc0) == 0xc0) { - /* Compressed name */ - break; - } else { - /* Not compressed name */ - while (n > 0) { - if ((*query) != (*response)) { - return 1; - } - ++response; - ++query; - --n; - }; - ++query; - } - } while (*response != 0); - - return 0; -} -#endif /* DNS_DOES_NAME_CHECK */ - -/** - * Walk through a compact encoded DNS name and return the end of the name. - * - * @param query encoded DNS name in the DNS server response - * @return end of the name - */ -static unsigned char * ICACHE_FLASH_ATTR -dns_parse_name(unsigned char *query) -{ - unsigned char n; - - do { - n = *query++; - /** @see RFC 1035 - 4.1.4. Message compression */ - if ((n & 0xc0) == 0xc0) { - /* Compressed name */ - break; - } else { - /* Not compressed name */ - while (n > 0) { - ++query; - --n; - }; - } - } while (*query != 0); - - return query + 1; -} - -/** - * Send a DNS query packet. - * - * @param numdns index of the DNS server in the dns_servers table - * @param name hostname to query - * @param id index of the hostname in dns_table, used as transaction ID in the - * DNS query packet - * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise - */ -static err_t ICACHE_FLASH_ATTR -dns_send(u8_t numdns, const char* name, u8_t id) -{ - err_t err; - struct dns_hdr *hdr; - struct dns_query qry; - struct pbuf *p; - char *query, *nptr; - const char *pHostname; - u8_t n; - - LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n", - (u16_t)(numdns), name)); - LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS); - LWIP_ASSERT("dns server has no IP address set", !ip_addr_isany(&dns_servers[numdns])); - - /* if here, we have either a new query or a retry on a previous query to process */ - p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH + 1 + - SIZEOF_DNS_QUERY, PBUF_RAM); - if (p != NULL) { - u16_t realloc_size; - LWIP_ASSERT("pbuf must be in one piece", p->next == NULL); - /* fill dns header */ - hdr = (struct dns_hdr*)p->payload; - memset(hdr, 0, SIZEOF_DNS_HDR); - hdr->id = htons(id); - hdr->flags1 = DNS_FLAG1_RD; - hdr->numquestions = PP_HTONS(1); - query = (char*)hdr + SIZEOF_DNS_HDR; - pHostname = name; - --pHostname; - - /* convert hostname into suitable query format. */ - do { - ++pHostname; - nptr = query; - ++query; - for(n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { - *query = *pHostname; - ++query; - ++n; - } - *nptr = n; - } while(*pHostname != 0); - *query++='\0'; - - /* fill dns query */ - qry.type = PP_HTONS(DNS_RRTYPE_A); - qry.cls = PP_HTONS(DNS_RRCLASS_IN); - SMEMCPY(query, &qry, SIZEOF_DNS_QUERY); - - /* resize pbuf to the exact dns query */ - realloc_size = (u16_t)((query + SIZEOF_DNS_QUERY) - ((char*)(p->payload))); - LWIP_ASSERT("p->tot_len >= realloc_size", p->tot_len >= realloc_size); - pbuf_realloc(p, realloc_size); - - /* connect to the server for faster receiving */ - udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT); - /* send dns packet */ - err = udp_sendto(dns_pcb, p, &dns_servers[numdns], DNS_SERVER_PORT); - - /* free pbuf */ - pbuf_free(p); - } else { - err = ERR_MEM; - } - - return err; -} - -/** - * dns_check_entry() - see if pEntry has not yet been queried and, if so, sends out a query. - * Check an entry in the dns_table: - * - send out query for new entries - * - retry old pending entries on timeout (also with different servers) - * - remove completed entries from the table if their TTL has expired - * - * @param i index of the dns_table entry to check - */ -static void ICACHE_FLASH_ATTR -dns_check_entry(u8_t i) -{ - err_t err; - struct dns_table_entry *pEntry = &dns_table[i]; - - LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE); - - switch(pEntry->state) { - - case DNS_STATE_NEW: { - /* initialize new entry */ - pEntry->state = DNS_STATE_ASKING; - pEntry->numdns = 0; - pEntry->tmr = 1; - pEntry->retries = 0; - - /* send DNS packet for this entry */ - err = dns_send(pEntry->numdns, pEntry->name, i); - if (err != ERR_OK) { - LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, - ("dns_send returned error: %s\n", lwip_strerr(err))); - } - break; - } - - case DNS_STATE_ASKING: { - if (--pEntry->tmr == 0) { - if (++pEntry->retries == DNS_MAX_RETRIES) { - if ((pEntry->numdns+1numdns+1])) { - /* change of server */ - pEntry->numdns++; - pEntry->tmr = 1; - pEntry->retries = 0; - break; - } else { - LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", pEntry->name)); - /* call specified callback function if provided */ - if (pEntry->found) - (*pEntry->found)(pEntry->name, NULL, pEntry->arg); - /* flush this entry */ - pEntry->state = DNS_STATE_UNUSED; - pEntry->found = NULL; - break; - } - } - - /* wait longer for the next retry */ - pEntry->tmr = pEntry->retries; - - /* send DNS packet for this entry */ - err = dns_send(pEntry->numdns, pEntry->name, i); - if (err != ERR_OK) { - LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, - ("dns_send returned error: %s\n", lwip_strerr(err))); - } - } - break; - } - - case DNS_STATE_DONE: { - /* if the time to live is nul */ - if ((pEntry->ttl == 0) || (--pEntry->ttl == 0)) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name)); - /* flush this entry */ - pEntry->state = DNS_STATE_UNUSED; - pEntry->found = NULL; - } - break; - } - case DNS_STATE_UNUSED: - /* nothing to do */ - break; - default: - LWIP_ASSERT("unknown dns_table entry state:", 0); - break; - } -} - -/** - * Call dns_check_entry for each entry in dns_table - check all entries. - */ -static void ICACHE_FLASH_ATTR -dns_check_entries(void) -{ - u8_t i; - - for (i = 0; i < DNS_TABLE_SIZE; ++i) { - dns_check_entry(i); - } -} - -/** - * Receive input function for DNS response packets arriving for the dns UDP pcb. - * - * @params see udp.h - */ -static void ICACHE_FLASH_ATTR -dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) -{ - u16_t i; - char *pHostname; - struct dns_hdr *hdr; - struct dns_answer ans; - struct dns_table_entry *pEntry; - u16_t nquestions, nanswers; - - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(addr); - LWIP_UNUSED_ARG(port); - - /* is the dns message too big ? */ - if (p->tot_len > DNS_MSG_SIZE) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n")); - /* free pbuf and return */ - goto memerr; - } - - /* is the dns message big enough ? */ - if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n")); - /* free pbuf and return */ - goto memerr; - } - - /* copy dns payload inside static buffer for processing */ - if (pbuf_copy_partial(p, dns_payload, p->tot_len, 0) == p->tot_len) { - /* The ID in the DNS header should be our entry into the name table. */ - hdr = (struct dns_hdr*)dns_payload; - i = htons(hdr->id); - if (i < DNS_TABLE_SIZE) { - pEntry = &dns_table[i]; - if(pEntry->state == DNS_STATE_ASKING) { - /* This entry is now completed. */ - pEntry->state = DNS_STATE_DONE; - pEntry->err = hdr->flags2 & DNS_FLAG2_ERR_MASK; - - /* We only care about the question(s) and the answers. The authrr - and the extrarr are simply discarded. */ - nquestions = htons(hdr->numquestions); - nanswers = htons(hdr->numanswers); - - /* Check for error. If so, call callback to inform. */ - if (((hdr->flags1 & DNS_FLAG1_RESPONSE) == 0) || (pEntry->err != 0) || (nquestions != 1)) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", pEntry->name)); - /* call callback to indicate error, clean up memory and return */ - goto responseerr; - } - -#if DNS_DOES_NAME_CHECK - /* Check if the name in the "question" part match with the name in the entry. */ - if (dns_compare_name((unsigned char *)(pEntry->name), (unsigned char *)dns_payload + SIZEOF_DNS_HDR) != 0) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", pEntry->name)); - /* call callback to indicate error, clean up memory and return */ - goto responseerr; - } -#endif /* DNS_DOES_NAME_CHECK */ - - /* Skip the name in the "question" part */ - pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY; - - while (nanswers > 0) { - /* skip answer resource record's host name */ - pHostname = (char *) dns_parse_name((unsigned char *)pHostname); - - /* Check for IP address type and Internet class. Others are discarded. */ - SMEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER); - if((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) && - (ans.len == PP_HTONS(sizeof(ip_addr_t))) ) { - /* read the answer resource record's TTL, and maximize it if needed */ - pEntry->ttl = ntohl(ans.ttl); - if (pEntry->ttl > DNS_MAX_TTL) { - pEntry->ttl = DNS_MAX_TTL; - } - /* read the IP address after answer resource record's header */ - SMEMCPY(&(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(ip_addr_t)); - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", pEntry->name)); - ip_addr_debug_print(DNS_DEBUG, (&(pEntry->ipaddr))); - LWIP_DEBUGF(DNS_DEBUG, ("\n")); - /* call specified callback function if provided */ - if (pEntry->found) { - (*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg); - } - if (pEntry->ttl == 0) { - /* RFC 883, page 29: "Zero values are - interpreted to mean that the RR can only be used for the - transaction in progress, and should not be cached." - -> flush this entry now */ - goto flushentry; - } - /* deallocate memory and return */ - goto memerr; - } else { - pHostname = pHostname + SIZEOF_DNS_ANSWER + htons(ans.len); - } - --nanswers; - } - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", pEntry->name)); - /* call callback to indicate error, clean up memory and return */ - goto responseerr; - } - } - } - - /* deallocate memory and return */ - goto memerr; - -responseerr: - /* ERROR: call specified callback function with NULL as name to indicate an error */ - if (pEntry->found) { - (*pEntry->found)(pEntry->name, NULL, pEntry->arg); - } -flushentry: - /* flush this entry */ - pEntry->state = DNS_STATE_UNUSED; - pEntry->found = NULL; - -memerr: - /* free pbuf */ - pbuf_free(p); - return; -} - -/** - * Queues a new hostname to resolve and sends out a DNS query for that hostname - * - * @param name the hostname that is to be queried - * @param hostnamelen length of the hostname - * @param found a callback founction to be called on success, failure or timeout - * @param callback_arg argument to pass to the callback function - * @return @return a err_t return code. - */ -static err_t ICACHE_FLASH_ATTR -dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, - void *callback_arg) -{ - u8_t i; - u8_t lseq, lseqi; - struct dns_table_entry *pEntry = NULL; - size_t namelen; - - /* search an unused entry, or the oldest one */ - lseq = lseqi = 0; - for (i = 0; i < DNS_TABLE_SIZE; ++i) { - pEntry = &dns_table[i]; - /* is it an unused entry ? */ - if (pEntry->state == DNS_STATE_UNUSED) - break; - - /* check if this is the oldest completed entry */ - if (pEntry->state == DNS_STATE_DONE) { - if ((dns_seqno - pEntry->seqno) > lseq) { - lseq = dns_seqno - pEntry->seqno; - lseqi = i; - } - } - } - - /* if we don't have found an unused entry, use the oldest completed one */ - if (i == DNS_TABLE_SIZE) { - if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) { - /* no entry can't be used now, table is full */ - LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name)); - return ERR_MEM; - } else { - /* use the oldest completed one */ - i = lseqi; - pEntry = &dns_table[i]; - } - } - - /* use this entry */ - LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i))); - - /* fill the entry */ - pEntry->state = DNS_STATE_NEW; - pEntry->seqno = dns_seqno++; - pEntry->found = found; - pEntry->arg = callback_arg; - namelen = LWIP_MIN(hostnamelen, DNS_MAX_NAME_LENGTH-1); - MEMCPY(pEntry->name, name, namelen); - pEntry->name[namelen] = 0; - - /* force to send query without waiting timer */ - dns_check_entry(i); - - /* dns query is enqueued */ - return ERR_INPROGRESS; -} - -/** - * Resolve a hostname (string) into an IP address. - * NON-BLOCKING callback version for use with raw API!!! - * - * Returns immediately with one of err_t return codes: - * - ERR_OK if hostname is a valid IP address string or the host - * name is already in the local names table. - * - ERR_INPROGRESS enqueue a request to be sent to the DNS server - * for resolution if no errors are present. - * - ERR_ARG: dns client not initialized or invalid hostname - * - * @param hostname the hostname that is to be queried - * @param addr pointer to a ip_addr_t where to store the address if it is already - * cached in the dns_table (only valid if ERR_OK is returned!) - * @param found a callback function to be called on success, failure or timeout (only if - * ERR_INPROGRESS is returned!) - * @param callback_arg argument to pass to the callback function - * @return a err_t return code. - */ -err_t ICACHE_FLASH_ATTR -dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, - void *callback_arg) -{ - u32_t ipaddr; - size_t hostnamelen; - /* not initialized or no valid server yet, or invalid addr pointer - * or invalid hostname or invalid hostname length */ - if ((dns_pcb == NULL) || (addr == NULL) || - (!hostname) || (!hostname[0])) { - return ERR_ARG; - } - hostnamelen = strlen(hostname); - if (hostnamelen >= DNS_MAX_NAME_LENGTH) { - return ERR_ARG; - } - - -#if LWIP_HAVE_LOOPIF - if (strcmp(hostname, "localhost")==0) { - ip_addr_set_loopback(addr); - return ERR_OK; - } -#endif /* LWIP_HAVE_LOOPIF */ - - /* host name already in octet notation? set ip addr and return ERR_OK */ - ipaddr = ipaddr_addr(hostname); - if (ipaddr == IPADDR_NONE) { - /* already have this address cached? */ - ipaddr = dns_lookup(hostname); - } - if (ipaddr != IPADDR_NONE) { - ip4_addr_set_u32(addr, ipaddr); - return ERR_OK; - } - - /* queue query with specified callback */ - return dns_enqueue(hostname, hostnamelen, found, callback_arg); -} - -#endif /* LWIP_DNS */ diff --git a/third_party/lwip/core/inet_chksum.c b/third_party/lwip/core/inet_chksum.c deleted file mode 100644 index c956d6b..0000000 --- a/third_party/lwip/core/inet_chksum.c +++ /dev/null @@ -1,545 +0,0 @@ -/** - * @file - * Incluse internet checksum functions. - * - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" - -#include "lwip/inet_chksum.h" -#include "lwip/def.h" - -#include -#include - -/* These are some reference implementations of the checksum algorithm, with the - * aim of being simple, correct and fully portable. Checksumming is the - * first thing you would want to optimize for your platform. If you create - * your own version, link it in and in your cc.h put: - * - * #define LWIP_CHKSUM - * - * Or you can select from the implementations below by defining - * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3. - */ - -#ifndef LWIP_CHKSUM -# define LWIP_CHKSUM lwip_standard_chksum -# ifndef LWIP_CHKSUM_ALGORITHM -# define LWIP_CHKSUM_ALGORITHM 2 -# endif -u16_t lwip_standard_chksum(void *dataptr, int len); -#endif -/* If none set: */ -#ifndef LWIP_CHKSUM_ALGORITHM -# define LWIP_CHKSUM_ALGORITHM 0 -#endif - -#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */ -/** - * lwip checksum - * - * @param dataptr points to start of data to be summed at any boundary - * @param len length of data to be summed - * @return host order (!) lwip checksum (non-inverted Internet sum) - * - * @note accumulator size limits summable length to 64k - * @note host endianess is irrelevant (p3 RFC1071) - */ -u16_t ICACHE_FLASH_ATTR -lwip_standard_chksum(void *dataptr, u16_t len) -{ - u32_t acc; - u16_t src; - u8_t *octetptr; - - acc = 0; - /* dataptr may be at odd or even addresses */ - octetptr = (u8_t*)dataptr; - while (len > 1) { - /* declare first octet as most significant - thus assume network order, ignoring host order */ - src = (*octetptr) << 8; - octetptr++; - /* declare second octet as least significant */ - src |= (*octetptr); - octetptr++; - acc += src; - len -= 2; - } - if (len > 0) { - /* accumulate remaining octet */ - src = (*octetptr) << 8; - acc += src; - } - /* add deferred carry bits */ - acc = (acc >> 16) + (acc & 0x0000ffffUL); - if ((acc & 0xffff0000UL) != 0) { - acc = (acc >> 16) + (acc & 0x0000ffffUL); - } - /* This maybe a little confusing: reorder sum using htons() - instead of ntohs() since it has a little less call overhead. - The caller must invert bits for Internet sum ! */ - return htons((u16_t)acc); -} -#endif - -#if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */ -/* - * Curt McDowell - * Broadcom Corp. - * csm@broadcom.com - * - * IP checksum two bytes at a time with support for - * unaligned buffer. - * Works for len up to and including 0x20000. - * by Curt McDowell, Broadcom Corp. 12/08/2005 - * - * @param dataptr points to start of data to be summed at any boundary - * @param len length of data to be summed - * @return host order (!) lwip checksum (non-inverted Internet sum) - */ - -u16_t ICACHE_FLASH_ATTR -lwip_standard_chksum(void *dataptr, int len) -{ - u8_t *pb = (u8_t *)dataptr; - u16_t *ps, t = 0; - u32_t sum = 0; - int odd = ((mem_ptr_t)pb & 1); - - /* Get aligned to u16_t */ - if (odd && len > 0) { - ((u8_t *)&t)[1] = *pb++; - len--; - } - - /* Add the bulk of the data */ - ps = (u16_t *)(void *)pb; - while (len > 1) { - sum += *ps++; - len -= 2; - } - - /* Consume left-over byte, if any */ - if (len > 0) { - ((u8_t *)&t)[0] = *(u8_t *)ps; - } - - /* Add end bytes */ - sum += t; - - /* Fold 32-bit sum to 16 bits - calling this twice is propably faster than if statements... */ - sum = FOLD_U32T(sum); - sum = FOLD_U32T(sum); - - /* Swap if alignment was odd */ - if (odd) { - sum = SWAP_BYTES_IN_WORD(sum); - } - - return (u16_t)sum; -} -#endif - -#if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */ -/** - * An optimized checksum routine. Basically, it uses loop-unrolling on - * the checksum loop, treating the head and tail bytes specially, whereas - * the inner loop acts on 8 bytes at a time. - * - * @arg start of buffer to be checksummed. May be an odd byte address. - * @len number of bytes in the buffer to be checksummed. - * @return host order (!) lwip checksum (non-inverted Internet sum) - * - * by Curt McDowell, Broadcom Corp. December 8th, 2005 - */ - -u16_t ICACHE_FLASH_ATTR -lwip_standard_chksum(void *dataptr, int len) -{ - u8_t *pb = (u8_t *)dataptr; - u16_t *ps, t = 0; - u32_t *pl; - u32_t sum = 0, tmp; - /* starts at odd byte address? */ - int odd = ((mem_ptr_t)pb & 1); - - if (odd && len > 0) { - ((u8_t *)&t)[1] = *pb++; - len--; - } - - ps = (u16_t *)pb; - - if (((mem_ptr_t)ps & 3) && len > 1) { - sum += *ps++; - len -= 2; - } - - pl = (u32_t *)ps; - - while (len > 7) { - tmp = sum + *pl++; /* ping */ - if (tmp < sum) { - tmp++; /* add back carry */ - } - - sum = tmp + *pl++; /* pong */ - if (sum < tmp) { - sum++; /* add back carry */ - } - - len -= 8; - } - - /* make room in upper bits */ - sum = FOLD_U32T(sum); - - ps = (u16_t *)pl; - - /* 16-bit aligned word remaining? */ - while (len > 1) { - sum += *ps++; - len -= 2; - } - - /* dangling tail byte remaining? */ - if (len > 0) { /* include odd byte */ - ((u8_t *)&t)[0] = *(u8_t *)ps; - } - - sum += t; /* add end bytes */ - - /* Fold 32-bit sum to 16 bits - calling this twice is propably faster than if statements... */ - sum = FOLD_U32T(sum); - sum = FOLD_U32T(sum); - - if (odd) { - sum = SWAP_BYTES_IN_WORD(sum); - } - - return (u16_t)sum; -} -#endif - -/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ -static u16_t ICACHE_FLASH_ATTR -inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc) -{ - struct pbuf *q; - u8_t swapped = 0; - - /* iterate through all pbuf in chain */ - for(q = p; q != NULL; q = q->next) { - LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", - (void *)q, (void *)q->next)); - acc += LWIP_CHKSUM(q->payload, q->len); - /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ - /* just executing this next line is probably faster that the if statement needed - to check whether we really need to execute it, and does no harm */ - acc = FOLD_U32T(acc); - if (q->len % 2 != 0) { - swapped = 1 - swapped; - acc = SWAP_BYTES_IN_WORD(acc); - } - /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ - } - - if (swapped) { - acc = SWAP_BYTES_IN_WORD(acc); - } - - acc += (u32_t)htons((u16_t)proto); - acc += (u32_t)htons(proto_len); - - /* Fold 32-bit sum to 16 bits - calling this twice is propably faster than if statements... */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); - return (u16_t)~(acc & 0xffffUL); -} - -/* inet_chksum_pseudo: - * - * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. - * IP addresses are expected to be in network byte order. - * - * @param p chain of pbufs over that a checksum should be calculated (ip data part) - * @param src source ip address (used for checksum of pseudo header) - * @param dst destination ip address (used for checksum of pseudo header) - * @param proto ip protocol (used for checksum of pseudo header) - * @param proto_len length of the ip data part (used for checksum of pseudo header) - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t ICACHE_FLASH_ATTR -inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, - ip_addr_t *src, ip_addr_t *dest) -{ - u32_t acc; - u32_t addr; - - addr = ip4_addr_get_u32(src); - acc = (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - addr = ip4_addr_get_u32(dest); - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - /* fold down to 16 bits */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - - return inet_cksum_pseudo_base(p, proto, proto_len, acc); -} -#if LWIP_IPV6 -/** - * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. - * IPv6 addresses are expected to be in network byte order. - * - * @param p chain of pbufs over that a checksum should be calculated (ip data part) - * @param src source ipv6 address (used for checksum of pseudo header) - * @param dst destination ipv6 address (used for checksum of pseudo header) - * @param proto ipv6 protocol/next header (used for checksum of pseudo header) - * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t ICACHE_FLASH_ATTR -ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, - ip6_addr_t *src, ip6_addr_t *dest) -{ - u32_t acc = 0; - u32_t addr; - u8_t addr_part; - - for (addr_part = 0; addr_part < 4; addr_part++) { - addr = src->addr[addr_part]; - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - addr = dest->addr[addr_part]; - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - } - /* fold down to 16 bits */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - - return inet_cksum_pseudo_base(p, proto, proto_len, acc); -} -#endif /* LWIP_IPV6 */ - -/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ -static u16_t ICACHE_FLASH_ATTR -inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len, - u16_t chksum_len, u32_t acc) -{ - struct pbuf *q; - u8_t swapped = 0; - u16_t chklen; - - /* iterate through all pbuf in chain */ - for(q = p; (q != NULL) && (chksum_len > 0); q = q->next) { - LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", - (void *)q, (void *)q->next)); - chklen = q->len; - if (chklen > chksum_len) { - chklen = chksum_len; - } - acc += LWIP_CHKSUM(q->payload, chklen); - chksum_len -= chklen; - LWIP_ASSERT("delete me", chksum_len < 0x7fff); - /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ - /* fold the upper bit down */ - acc = FOLD_U32T(acc); - if (q->len % 2 != 0) { - swapped = 1 - swapped; - acc = SWAP_BYTES_IN_WORD(acc); - } - /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ - } - - if (swapped) { - acc = SWAP_BYTES_IN_WORD(acc); - } - - acc += (u32_t)htons((u16_t)proto); - acc += (u32_t)htons(proto_len); - - /* Fold 32-bit sum to 16 bits - calling this twice is propably faster than if statements... */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); - return (u16_t)~(acc & 0xffffUL); -} - -/* inet_chksum_pseudo_partial: - * - * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain. - * IP addresses are expected to be in network byte order. - * - * @param p chain of pbufs over that a checksum should be calculated (ip data part) - * @param src source ip address (used for checksum of pseudo header) - * @param dst destination ip address (used for checksum of pseudo header) - * @param proto ip protocol (used for checksum of pseudo header) - * @param proto_len length of the ip data part (used for checksum of pseudo header) - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t ICACHE_FLASH_ATTR -inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, - u16_t chksum_len, ip_addr_t *src, ip_addr_t *dest) -{ - u32_t acc; - u32_t addr; - - addr = ip4_addr_get_u32(src); - acc = (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - addr = ip4_addr_get_u32(dest); - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - /* fold down to 16 bits */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - - return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); -} - -#if LWIP_IPV6 -/** - * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. - * IPv6 addresses are expected to be in network byte order. Will only compute for a - * portion of the payload. - * - * @param p chain of pbufs over that a checksum should be calculated (ip data part) - * @param src source ipv6 address (used for checksum of pseudo header) - * @param dst destination ipv6 address (used for checksum of pseudo header) - * @param proto ipv6 protocol/next header (used for checksum of pseudo header) - * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) - * @param chksum_len number of payload bytes used to compute chksum - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t ICACHE_FLASH_ATTR -ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, - u16_t chksum_len, ip6_addr_t *src, ip6_addr_t *dest) -{ - u32_t acc = 0; - u32_t addr; - u8_t addr_part; - - for (addr_part = 0; addr_part < 4; addr_part++) { - addr = src->addr[addr_part]; - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - addr = dest->addr[addr_part]; - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - } - /* fold down to 16 bits */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - - return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); -} -#endif /* LWIP_IPV6 */ - -/* inet_chksum: - * - * Calculates the Internet checksum over a portion of memory. Used primarily for IP - * and ICMP. - * - * @param dataptr start of the buffer to calculate the checksum (no alignment needed) - * @param len length of the buffer to calculate the checksum - * @return checksum (as u16_t) to be saved directly in the protocol header - */ - -u16_t ICACHE_FLASH_ATTR -inet_chksum(void *dataptr, u16_t len) -{ - return ~LWIP_CHKSUM(dataptr, len); -} - -/** - * Calculate a checksum over a chain of pbufs (without pseudo-header, much like - * inet_chksum only pbufs are used). - * - * @param p pbuf chain over that the checksum should be calculated - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t ICACHE_FLASH_ATTR -inet_chksum_pbuf(struct pbuf *p) -{ - u32_t acc; - struct pbuf *q; - u8_t swapped; - - acc = 0; - swapped = 0; - for(q = p; q != NULL; q = q->next) { - acc += LWIP_CHKSUM(q->payload, q->len); - acc = FOLD_U32T(acc); - if (q->len % 2 != 0) { - swapped = 1 - swapped; - acc = SWAP_BYTES_IN_WORD(acc); - } - } - - if (swapped) { - acc = SWAP_BYTES_IN_WORD(acc); - } - return (u16_t)~(acc & 0xffffUL); -} - -/* These are some implementations for LWIP_CHKSUM_COPY, which copies data - * like MEMCPY but generates a checksum at the same time. Since this is a - * performance-sensitive function, you might want to create your own version - * in assembly targeted at your hardware by defining it in lwipopts.h: - * #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len) - */ - -#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */ -/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM. - * For architectures with big caches, data might still be in cache when - * generating the checksum after copying. - */ -u16_t ICACHE_FLASH_ATTR -lwip_chksum_copy(void *dst, const void *src, u16_t len) -{ - MEMCPY(dst, src, len); - return LWIP_CHKSUM(dst, len); -} -#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */ diff --git a/third_party/lwip/core/init.c b/third_party/lwip/core/init.c deleted file mode 100644 index b8b98ed..0000000 --- a/third_party/lwip/core/init.c +++ /dev/null @@ -1,345 +0,0 @@ -/** - * @file - * Modules initialization - * - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" - -#include "lwip/init.h" -#include "lwip/stats.h" -#include "lwip/sys.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/pbuf.h" -#include "lwip/netif.h" -#include "lwip/sockets.h" -#include "lwip/ip.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/tcp_impl.h" -#include "lwip/snmp_msg.h" -#include "lwip/autoip.h" -#include "lwip/igmp.h" -#include "lwip/dns.h" -#include "lwip/timers.h" -#include "netif/etharp.h" -#include "lwip/ip6.h" -#include "lwip/nd6.h" -#include "lwip/mld6.h" -#include "lwip/api.h" - -/* Compile-time sanity checks for configuration errors. - * These can be done independently of LWIP_DEBUG, without penalty. - */ -#ifndef BYTE_ORDER - #error "BYTE_ORDER is not defined, you have to define it in your cc.h" -#endif -#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV) - #error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_UDPLITE) - #error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_SNMP) - #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_DHCP) - #error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_IGMP) - #error "If you want to use IGMP, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_SNMP) - #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_DNS) - #error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif -#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */ -#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0)) - #error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h" -#endif -#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0)) - #error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h" -#endif -#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0)) - #error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h" -#endif -#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0)) - #error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h" -#endif -#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1)) - #error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h" -#endif -#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0)) - #error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h" -#endif -/* There must be sufficient timeouts, taking into account requirements of the subsystems. */ -#if LWIP_TIMERS && (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))) - #error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts" -#endif -#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS)) - #error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!" -#endif -#endif /* !MEMP_MEM_MALLOC */ -#if (LWIP_TCP && (TCP_WND > 0xffff)) - #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h" -#endif -#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff)) - #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h" -#endif -#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2)) - #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work" -#endif -#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) - #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h" -#endif -#if (LWIP_TCP && TCP_LISTEN_BACKLOG && (TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff)) - #error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t" -#endif -#if (LWIP_NETIF_API && (NO_SYS==1)) - #error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h" -#endif -#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1)) - #error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h" -#endif -#if (!LWIP_NETCONN && LWIP_SOCKET) - #error "If you want to use Socket API, you have to define LWIP_NETCONN=1 in your lwipopts.h" -#endif -#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP) - #error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h" -#endif -#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK) - #error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h" -#endif -#if (!LWIP_ARP && LWIP_AUTOIP) - #error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h" -#endif -#if (LWIP_SNMP && (SNMP_CONCURRENT_REQUESTS<=0)) - #error "If you want to use SNMP, you have to define SNMP_CONCURRENT_REQUESTS>=1 in your lwipopts.h" -#endif -#if (LWIP_SNMP && (SNMP_TRAP_DESTINATIONS<=0)) - #error "If you want to use SNMP, you have to define SNMP_TRAP_DESTINATIONS>=1 in your lwipopts.h" -#endif -#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API))) - #error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h" -#endif -#if (MEM_LIBC_MALLOC && MEM_USE_POOLS) - #error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h" -#endif -#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS) - #error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h" -#endif -#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT) - #error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf" -#endif -#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT))) - #error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST" -#endif -#if PPP_SUPPORT && !PPPOS_SUPPORT & !PPPOE_SUPPORT - #error "PPP_SUPPORT needs either PPPOS_SUPPORT or PPPOE_SUPPORT turned on" -#endif -#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT) - #error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT" -#endif -#if (LWIP_IGMP || LWIP_IPV6) && !defined(LWIP_RAND) - #error "When using IGMP or IPv6, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value" -#endif -#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING - #error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too" -#endif -#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE - #error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets" -#endif -#if IP_FRAG && IP_FRAG_USES_STATIC_BUF && LWIP_NETIF_TX_SINGLE_PBUF - #error "LWIP_NETIF_TX_SINGLE_PBUF does not work with IP_FRAG_USES_STATIC_BUF==1 as that creates pbuf queues" -#endif -#if LWIP_NETCONN && LWIP_TCP -#if NETCONN_COPY != TCP_WRITE_FLAG_COPY - #error "NETCONN_COPY != TCP_WRITE_FLAG_COPY" -#endif -#if NETCONN_MORE != TCP_WRITE_FLAG_MORE - #error "NETCONN_MORE != TCP_WRITE_FLAG_MORE" -#endif -#endif /* LWIP_NETCONN && LWIP_TCP */ -#if LWIP_SOCKET -/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */ -#if SO_ACCEPTCONN != SOF_ACCEPTCONN - #error "SO_ACCEPTCONN != SOF_ACCEPTCONN" -#endif -#if SO_REUSEADDR != SOF_REUSEADDR - #error "WARNING: SO_REUSEADDR != SOF_REUSEADDR" -#endif -#if SO_KEEPALIVE != SOF_KEEPALIVE - #error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE" -#endif -#if SO_BROADCAST != SOF_BROADCAST - #error "WARNING: SO_BROADCAST != SOF_BROADCAST" -#endif -#if SO_LINGER != SOF_LINGER - #error "WARNING: SO_LINGER != SOF_LINGER" -#endif -#endif /* LWIP_SOCKET */ - - -/* Compile-time checks for deprecated options. - */ -#ifdef MEMP_NUM_TCPIP_MSG - #error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h." -#endif -#ifdef MEMP_NUM_API_MSG - #error "MEMP_NUM_API_MSG option is deprecated. Remove it from your lwipopts.h." -#endif -#ifdef TCP_REXMIT_DEBUG - #error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h." -#endif -#ifdef RAW_STATS - #error "RAW_STATS option is deprecated. Remove it from your lwipopts.h." -#endif -#ifdef ETHARP_QUEUE_FIRST - #error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h." -#endif -#ifdef ETHARP_ALWAYS_INSERT - #error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h." -#endif - -#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS -#define LWIP_DISABLE_TCP_SANITY_CHECKS 0 -#endif -#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS -#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0 -#endif - -/* MEMP sanity checks */ -#if !LWIP_DISABLE_MEMP_SANITY_CHECKS -#if LWIP_NETCONN -#if MEMP_MEM_MALLOC -#if !MEMP_NUM_NETCONN && LWIP_SOCKET -#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!" -#endif -#else /* MEMP_MEM_MALLOC */ -#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB) -#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error." -#endif -#endif /* MEMP_MEM_MALLOC */ -#endif /* LWIP_NETCONN */ -#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */ - -/* TCP sanity checks */ -#if !LWIP_DISABLE_TCP_SANITY_CHECKS -#if LWIP_TCP -#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN) - #error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if TCP_SND_BUF < (2 * TCP_MSS) - #error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS)) - #error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if TCP_SNDLOWAT >= TCP_SND_BUF - #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN - #error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if !MEMP_MEM_MALLOC && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) - #error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if !MEMP_MEM_MALLOC && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)))) - #error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if TCP_WND < TCP_MSS - #error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#endif /* LWIP_TCP */ -#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */ - -/** - * Perform Sanity check of user-configurable values, and initialize all modules. - */ -void ICACHE_FLASH_ATTR -lwip_init(void) -{ - /* Modules initialization */ - stats_init(); -#if !NO_SYS - sys_init(); -#endif /* !NO_SYS */ - mem_init(); - memp_init(); - pbuf_init(); - netif_init(); -#if LWIP_SOCKET - lwip_socket_init(); -#endif /* LWIP_SOCKET */ - ip_init(); -#if LWIP_ARP - etharp_init(); -#endif /* LWIP_ARP */ -#if LWIP_RAW - raw_init(); -#endif /* LWIP_RAW */ -#if LWIP_UDP - udp_init(); -#endif /* LWIP_UDP */ -#if LWIP_TCP - tcp_init(); -#endif /* LWIP_TCP */ -#if LWIP_SNMP - snmp_init(); -#endif /* LWIP_SNMP */ -#if LWIP_AUTOIP - autoip_init(); -#endif /* LWIP_AUTOIP */ -#if LWIP_IGMP - igmp_init(); -#endif /* LWIP_IGMP */ -#if LWIP_DNS - dns_init(); -#endif /* LWIP_DNS */ -#if LWIP_IPV6 - ip6_init(); - nd6_init(); -#if LWIP_IPV6_MLD - mld6_init(); -#endif /* LWIP_IPV6_MLD */ -#endif /* LWIP_IPV6 */ - -#if LWIP_TIMERS - sys_timeouts_init(); -#endif /* LWIP_TIMERS */ -} diff --git a/third_party/lwip/core/ipv4/Makefile b/third_party/lwip/core/ipv4/Makefile deleted file mode 100644 index 2d818fe..0000000 --- a/third_party/lwip/core/ipv4/Makefile +++ /dev/null @@ -1,46 +0,0 @@ - -############################################################# -# Required variables for each makefile -# Discard this section from all parent makefiles -# Expected variables (with automatic defaults): -# CSRCS (all "C" files in the dir) -# SUBDIRS (all subdirs with a Makefile) -# GEN_LIBS - list of libs to be generated () -# GEN_IMAGES - list of images to be generated () -# COMPONENTS_xxx - a list of libs/objs in the form -# subdir/lib to be extracted and rolled up into -# a generated lib/image xxx.a () -# -ifndef PDIR - -GEN_LIBS = liblwipipv4.a - -endif - - -############################################################# -# Configuration i.e. compile options etc. -# Target specific stuff (defines etc.) goes in here! -# Generally values applying to a tree are captured in the -# makefile at its root level - these are then overridden -# for a subtree within the makefile rooted therein -# -#DEFINES += - -############################################################# -# Recursion Magic - Don't touch this!! -# -# Each subtree potentially has an include directory -# corresponding to the common APIs applicable to modules -# rooted at that subtree. Accordingly, the INCLUDE PATH -# of a module can only contain the include directories up -# its parent path, and not its siblings -# -# Required for each makefile to inherit from the parent -# - -INCLUDES := $(INCLUDES) -I $(PDIR)include -INCLUDES += -I ./ -PDIR := ../$(PDIR) -sinclude $(PDIR)Makefile - diff --git a/third_party/lwip/core/ipv4/autoip.c b/third_party/lwip/core/ipv4/autoip.c deleted file mode 100644 index fd61792..0000000 --- a/third_party/lwip/core/ipv4/autoip.c +++ /dev/null @@ -1,528 +0,0 @@ -/** - * @file - * AutoIP Automatic LinkLocal IP Configuration - * - */ - -/* - * - * Copyright (c) 2007 Dominik Spies - * 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: Dominik Spies - * - * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform - * with RFC 3927. - * - * - * Please coordinate changes and requests with Dominik Spies - * - */ - -/******************************************************************************* - * USAGE: - * - * define LWIP_AUTOIP 1 in your lwipopts.h - * - * If you don't use tcpip.c (so, don't call, you don't call tcpip_init): - * - First, call autoip_init(). - * - call autoip_tmr() all AUTOIP_TMR_INTERVAL msces, - * that should be defined in autoip.h. - * I recommend a value of 100. The value must divide 1000 with a remainder almost 0. - * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 .... - * - * Without DHCP: - * - Call autoip_start() after netif_add(). - * - * With DHCP: - * - define LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h. - * - Configure your DHCP Client. - * - */ - -#include "lwip/opt.h" - -#if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/mem.h" -#include "lwip/udp.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/autoip.h" -#include "netif/etharp.h" - -#include -#include - -/* 169.254.0.0 */ -#define AUTOIP_NET 0xA9FE0000 -/* 169.254.1.0 */ -#define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100) -/* 169.254.254.255 */ -#define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF) - - -/** Pseudo random macro based on netif informations. - * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */ -#ifndef LWIP_AUTOIP_RAND -#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \ - ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \ - ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \ - ((u32_t)((netif->hwaddr[4]) & 0xff))) + \ - (netif->autoip?netif->autoip->tried_llipaddr:0)) -#endif /* LWIP_AUTOIP_RAND */ - -/** - * Macro that generates the initial IP address to be tried by AUTOIP. - * If you want to override this, define it to something else in lwipopts.h. - */ -#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR -#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \ - htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \ - ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8))) -#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */ - -/* static functions */ -static void autoip_handle_arp_conflict(struct netif *netif); - -/* creates a pseudo random LL IP-Address for a network interface */ -static void autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr); - -/* sends an ARP probe */ -static err_t autoip_arp_probe(struct netif *netif); - -/* sends an ARP announce */ -static err_t autoip_arp_announce(struct netif *netif); - -/* configure interface for use with current LL IP-Address */ -static err_t autoip_bind(struct netif *netif); - -/* start sending probes for llipaddr */ -static void autoip_start_probing(struct netif *netif); - - -/** Set a statically allocated struct autoip to work with. - * Using this prevents autoip_start to allocate it using mem_malloc. - * - * @param netif the netif for which to set the struct autoip - * @param dhcp (uninitialised) dhcp struct allocated by the application - */ -void ICACHE_FLASH_ATTR -autoip_set_struct(struct netif *netif, struct autoip *autoip) -{ - LWIP_ASSERT("netif != NULL", netif != NULL); - LWIP_ASSERT("autoip != NULL", autoip != NULL); - LWIP_ASSERT("netif already has a struct autoip set", netif->autoip == NULL); - - /* clear data structure */ - memset(autoip, 0, sizeof(struct autoip)); - /* autoip->state = AUTOIP_STATE_OFF; */ - netif->autoip = autoip; -} - -/** Restart AutoIP client and check the next address (conflict detected) - * - * @param netif The netif under AutoIP control - */ -static void ICACHE_FLASH_ATTR -autoip_restart(struct netif *netif) -{ - netif->autoip->tried_llipaddr++; - autoip_start(netif); -} - -/** - * Handle a IP address conflict after an ARP conflict detection - */ -static void ICACHE_FLASH_ATTR -autoip_handle_arp_conflict(struct netif *netif) -{ - /* Somehow detect if we are defending or retreating */ - unsigned char defend = 1; /* tbd */ - - if (defend) { - if (netif->autoip->lastconflict > 0) { - /* retreat, there was a conflicting ARP in the last - * DEFEND_INTERVAL seconds - */ - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n")); - - /* TODO: close all TCP sessions */ - autoip_restart(netif); - } else { - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n")); - autoip_arp_announce(netif); - netif->autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; - } - } else { - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_handle_arp_conflict(): we do not defend, retreating\n")); - /* TODO: close all TCP sessions */ - autoip_restart(netif); - } -} - -/** - * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255 - * - * @param netif network interface on which create the IP-Address - * @param ipaddr ip address to initialize - */ -static void ICACHE_FLASH_ATTR -autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr) -{ - /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 - * compliant to RFC 3927 Section 2.1 - * We have 254 * 256 possibilities */ - - u32_t addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif)); - addr += netif->autoip->tried_llipaddr; - addr = AUTOIP_NET | (addr & 0xffff); - /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */ - - if (addr < AUTOIP_RANGE_START) { - addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; - } - if (addr > AUTOIP_RANGE_END) { - addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; - } - LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) && - (addr <= AUTOIP_RANGE_END)); - ip4_addr_set_u32(ipaddr, htonl(addr)); - - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - (u16_t)(netif->autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), - ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); -} - -/** - * Sends an ARP probe from a network interface - * - * @param netif network interface used to send the probe - */ -static err_t ICACHE_FLASH_ATTR -autoip_arp_probe(struct netif *netif) -{ - return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, - (struct eth_addr *)netif->hwaddr, IP_ADDR_ANY, ðzero, - &netif->autoip->llipaddr, ARP_REQUEST); -} - -/** - * Sends an ARP announce from a network interface - * - * @param netif network interface used to send the announce - */ -static err_t ICACHE_FLASH_ATTR -autoip_arp_announce(struct netif *netif) -{ - return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, - (struct eth_addr *)netif->hwaddr, &netif->autoip->llipaddr, ðzero, - &netif->autoip->llipaddr, ARP_REQUEST); -} - -/** - * Configure interface for use with current LL IP-Address - * - * @param netif network interface to configure with current LL IP-Address - */ -static err_t ICACHE_FLASH_ATTR -autoip_bind(struct netif *netif) -{ - struct autoip *autoip = netif->autoip; - ip_addr_t sn_mask, gw_addr; - - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, - ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, - ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), - ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); - - IP4_ADDR(&sn_mask, 255, 255, 0, 0); - IP4_ADDR(&gw_addr, 0, 0, 0, 0); - - netif_set_ipaddr(netif, &autoip->llipaddr); - netif_set_netmask(netif, &sn_mask); - netif_set_gw(netif, &gw_addr); - - /* bring the interface up */ - netif_set_up(netif); - - return ERR_OK; -} - -/** - * Start AutoIP client - * - * @param netif network interface on which start the AutoIP client - */ -err_t ICACHE_FLASH_ATTR -autoip_start(struct netif *netif) -{ - struct autoip *autoip = netif->autoip; - err_t result = ERR_OK; - - if (netif_is_up(netif)) { - netif_set_down(netif); - } - - /* Set IP-Address, Netmask and Gateway to 0 to make sure that - * ARP Packets are formed correctly - */ - ip_addr_set_zero(&netif->ip_addr); - ip_addr_set_zero(&netif->netmask); - ip_addr_set_zero(&netif->gw); - - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], - netif->name[1], (u16_t)netif->num)); - if (autoip == NULL) { - /* no AutoIP client attached yet? */ - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, - ("autoip_start(): starting new AUTOIP client\n")); - autoip = (struct autoip *)mem_malloc(sizeof(struct autoip)); - if (autoip == NULL) { - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, - ("autoip_start(): could not allocate autoip\n")); - return ERR_MEM; - } - memset(autoip, 0, sizeof(struct autoip)); - /* store this AutoIP client in the netif */ - netif->autoip = autoip; - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip")); - } else { - autoip->state = AUTOIP_STATE_OFF; - autoip->ttw = 0; - autoip->sent_num = 0; - ip_addr_set_zero(&autoip->llipaddr); - autoip->lastconflict = 0; - } - - autoip_create_addr(netif, &(autoip->llipaddr)); - autoip_start_probing(netif); - - return result; -} - -static void ICACHE_FLASH_ATTR -autoip_start_probing(struct netif *netif) -{ - struct autoip *autoip = netif->autoip; - - autoip->state = AUTOIP_STATE_PROBING; - autoip->sent_num = 0; - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), - ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); - - /* time to wait to first probe, this is randomly - * choosen out of 0 to PROBE_WAIT seconds. - * compliant to RFC 3927 Section 2.2.1 - */ - autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND)); - - /* - * if we tried more then MAX_CONFLICTS we must limit our rate for - * accquiring and probing address - * compliant to RFC 3927 Section 2.2.1 - */ - if (autoip->tried_llipaddr > MAX_CONFLICTS) { - autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND; - } -} - -/** - * Handle a possible change in the network configuration. - * - * If there is an AutoIP address configured, take the interface down - * and begin probing with the same address. - */ -void ICACHE_FLASH_ATTR -autoip_network_changed(struct netif *netif) -{ - if (netif->autoip && netif->autoip->state != AUTOIP_STATE_OFF) { - netif_set_down(netif); - autoip_start_probing(netif); - } -} - -/** - * Stop AutoIP client - * - * @param netif network interface on which stop the AutoIP client - */ -err_t ICACHE_FLASH_ATTR -autoip_stop(struct netif *netif) -{ - netif->autoip->state = AUTOIP_STATE_OFF; - netif_set_down(netif); - return ERR_OK; -} - -/** - * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds - */ -void ICACHE_FLASH_ATTR -autoip_tmr() -{ - struct netif *netif = netif_list; - /* loop through netif's */ - while (netif != NULL) { - /* only act on AutoIP configured interfaces */ - if (netif->autoip != NULL) { - if (netif->autoip->lastconflict > 0) { - netif->autoip->lastconflict--; - } - - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, - ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n", - (u16_t)(netif->autoip->state), netif->autoip->ttw)); - - switch(netif->autoip->state) { - case AUTOIP_STATE_PROBING: - if (netif->autoip->ttw > 0) { - netif->autoip->ttw--; - } else { - if (netif->autoip->sent_num >= PROBE_NUM) { - netif->autoip->state = AUTOIP_STATE_ANNOUNCING; - netif->autoip->sent_num = 0; - netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), - ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); - } else { - autoip_arp_probe(netif); - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, - ("autoip_tmr() PROBING Sent Probe\n")); - netif->autoip->sent_num++; - /* calculate time to wait to next probe */ - netif->autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) % - ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) + - PROBE_MIN * AUTOIP_TICKS_PER_SECOND); - } - } - break; - - case AUTOIP_STATE_ANNOUNCING: - if (netif->autoip->ttw > 0) { - netif->autoip->ttw--; - } else { - if (netif->autoip->sent_num == 0) { - /* We are here the first time, so we waited ANNOUNCE_WAIT seconds - * Now we can bind to an IP address and use it. - * - * autoip_bind calls netif_set_up. This triggers a gratuitous ARP - * which counts as an announcement. - */ - autoip_bind(netif); - } else { - autoip_arp_announce(netif); - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, - ("autoip_tmr() ANNOUNCING Sent Announce\n")); - } - netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; - netif->autoip->sent_num++; - - if (netif->autoip->sent_num >= ANNOUNCE_NUM) { - netif->autoip->state = AUTOIP_STATE_BOUND; - netif->autoip->sent_num = 0; - netif->autoip->ttw = 0; - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr), - ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr))); - } - } - break; - } - } - /* proceed to next network interface */ - netif = netif->next; - } -} - -/** - * Handles every incoming ARP Packet, called by etharp_arp_input. - * - * @param netif network interface to use for autoip processing - * @param hdr Incoming ARP packet - */ -void ICACHE_FLASH_ATTR -autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) -{ - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n")); - if ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) { - /* when ip.src == llipaddr && hw.src != netif->hwaddr - * - * when probing ip.dst == llipaddr && hw.src != netif->hwaddr - * we have a conflict and must solve it - */ - ip_addr_t sipaddr, dipaddr; - struct eth_addr netifaddr; - ETHADDR16_COPY(netifaddr.addr, netif->hwaddr); - - /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without - * structure packing (not using structure copy which breaks strict-aliasing rules). - */ - IPADDR2_COPY(&sipaddr, &hdr->sipaddr); - IPADDR2_COPY(&dipaddr, &hdr->dipaddr); - - if ((netif->autoip->state == AUTOIP_STATE_PROBING) || - ((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) && - (netif->autoip->sent_num == 0))) { - /* RFC 3927 Section 2.2.1: - * from beginning to after ANNOUNCE_WAIT - * seconds we have a conflict if - * ip.src == llipaddr OR - * ip.dst == llipaddr && hw.src != own hwaddr - */ - if ((ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr)) || - (ip_addr_cmp(&dipaddr, &netif->autoip->llipaddr) && - !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) { - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, - ("autoip_arp_reply(): Probe Conflict detected\n")); - autoip_restart(netif); - } - } else { - /* RFC 3927 Section 2.5: - * in any state we have a conflict if - * ip.src == llipaddr && hw.src != own hwaddr - */ - if (ip_addr_cmp(&sipaddr, &netif->autoip->llipaddr) && - !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) { - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, - ("autoip_arp_reply(): Conflicting ARP-Packet detected\n")); - autoip_handle_arp_conflict(netif); - } - } - } -} - -#endif /* LWIP_AUTOIP */ diff --git a/third_party/lwip/core/ipv4/icmp.c b/third_party/lwip/core/ipv4/icmp.c deleted file mode 100644 index b0e6474..0000000 --- a/third_party/lwip/core/ipv4/icmp.c +++ /dev/null @@ -1,338 +0,0 @@ -/** - * @file - * ICMP - Internet Control Message Protocol - * - */ - -/* - * 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 - * - */ - -/* Some ICMP messages should be passed to the transport protocols. This - is not implemented. */ - -#include "lwip/opt.h" - -#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/icmp.h" -#include "lwip/inet_chksum.h" -#include "lwip/ip.h" -#include "lwip/def.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" - -#include - -/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be - * used to modify and send a response packet (and to 1 if this is not the case, - * e.g. when link header is stripped of when receiving) */ -#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN -#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1 -#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ - -/* The amount of data from the original packet to return in a dest-unreachable */ -#define ICMP_DEST_UNREACH_DATASIZE 8 - -static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code); - -/** - * Processes ICMP input packets, called from ip_input(). - * - * Currently only processes icmp echo requests and sends - * out the echo response. - * - * @param p the icmp echo request packet, p->payload pointing to the icmp header - * @param inp the netif on which this packet was received - */ -void ICACHE_FLASH_ATTR -icmp_input(struct pbuf *p, struct netif *inp) -{ - u8_t type; -#ifdef LWIP_DEBUG - u8_t code; -#endif /* LWIP_DEBUG */ - struct icmp_echo_hdr *iecho; - struct ip_hdr *iphdr; - s16_t hlen; - - ICMP_STATS_INC(icmp.recv); - snmp_inc_icmpinmsgs(); - - iphdr = (struct ip_hdr *)ip_current_header(); - hlen = IPH_HL(iphdr) * 4; - if (p->len < sizeof(u16_t)*2) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len)); - goto lenerr; - } - - type = *((u8_t *)p->payload); -#ifdef LWIP_DEBUG - code = *(((u8_t *)p->payload)+1); -#endif /* LWIP_DEBUG */ - switch (type) { - case ICMP_ER: - /* This is OK, echo reply might have been parsed by a raw PCB - (as obviously, an echo request has been sent, too). */ - break; - case ICMP_ECHO: -#if !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING - { - int accepted = 1; -#if !LWIP_MULTICAST_PING - /* multicast destination address? */ - if (ip_addr_ismulticast(ip_current_dest_addr())) { - accepted = 0; - } -#endif /* LWIP_MULTICAST_PING */ -#if !LWIP_BROADCAST_PING - /* broadcast destination address? */ - if (ip_addr_isbroadcast(ip_current_dest_addr(), inp)) { - accepted = 0; - } -#endif /* LWIP_BROADCAST_PING */ - /* broadcast or multicast destination address not acceptd? */ - if (!accepted) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n")); - ICMP_STATS_INC(icmp.err); - pbuf_free(p); - return; - } - } -#endif /* !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */ - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n")); - if (p->tot_len < sizeof(struct icmp_echo_hdr)) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); - goto lenerr; - } - if (inet_chksum_pbuf(p) != 0) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n")); - pbuf_free(p); - ICMP_STATS_INC(icmp.chkerr); - snmp_inc_icmpinerrors(); - return; - } -#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN - if (pbuf_header(p, (PBUF_IP_HLEN + PBUF_LINK_HLEN))) { - /* p is not big enough to contain link headers - * allocate a new one and copy p into it - */ - struct pbuf *r; - /* switch p->payload to ip header */ - if (pbuf_header(p, hlen)) { - LWIP_ASSERT("icmp_input: moving p->payload to ip header failed\n", 0); - goto memerr; - } - /* allocate new packet buffer with space for link headers */ - r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); - if (r == NULL) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n")); - goto memerr; - } - LWIP_ASSERT("check that first pbuf can hold struct the ICMP header", - (r->len >= hlen + sizeof(struct icmp_echo_hdr))); - /* copy the whole packet including ip header */ - if (pbuf_copy(r, p) != ERR_OK) { - LWIP_ASSERT("icmp_input: copying to new pbuf failed\n", 0); - goto memerr; - } - iphdr = (struct ip_hdr *)r->payload; - /* switch r->payload back to icmp header */ - if (pbuf_header(r, -hlen)) { - LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); - goto memerr; - } - /* free the original p */ - pbuf_free(p); - /* we now have an identical copy of p that has room for link headers */ - p = r; - } else { - /* restore p->payload to point to icmp header */ - if (pbuf_header(p, -(s16_t)(PBUF_IP_HLEN + PBUF_LINK_HLEN))) { - LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); - goto memerr; - } - } -#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ - /* At this point, all checks are OK. */ - /* We generate an answer by switching the dest and src ip addresses, - * setting the icmp type to ECHO_RESPONSE and updating the checksum. */ - iecho = (struct icmp_echo_hdr *)p->payload; - ip_addr_copy(iphdr->src, *ip_current_dest_addr()); - ip_addr_copy(iphdr->dest, *ip_current_src_addr()); - ICMPH_TYPE_SET(iecho, ICMP_ER); -#if CHECKSUM_GEN_ICMP - /* adjust the checksum */ - if (iecho->chksum >= PP_HTONS(0xffffU - (ICMP_ECHO << 8))) { - iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1; - } else { - iecho->chksum += PP_HTONS(ICMP_ECHO << 8); - } -#else /* CHECKSUM_GEN_ICMP */ - iecho->chksum = 0; -#endif /* CHECKSUM_GEN_ICMP */ - - /* Set the correct TTL and recalculate the header checksum. */ - IPH_TTL_SET(iphdr, ICMP_TTL); - IPH_CHKSUM_SET(iphdr, 0); -#if CHECKSUM_GEN_IP - IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); -#endif /* CHECKSUM_GEN_IP */ - - ICMP_STATS_INC(icmp.xmit); - /* increase number of messages attempted to send */ - snmp_inc_icmpoutmsgs(); - /* increase number of echo replies attempted to send */ - snmp_inc_icmpoutechoreps(); - - if(pbuf_header(p, hlen)) { - LWIP_ASSERT("Can't move over header in packet", 0); - } else { - err_t ret; - /* send an ICMP packet, src addr is the dest addr of the curren packet */ - ret = ip_output_if(p, ip_current_dest_addr(), IP_HDRINCL, - ICMP_TTL, 0, IP_PROTO_ICMP, inp); - if (ret != ERR_OK) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %c.\n", ret)); - } - } - break; - default: - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", - (s16_t)type, (s16_t)code)); - ICMP_STATS_INC(icmp.proterr); - ICMP_STATS_INC(icmp.drop); - } - pbuf_free(p); - return; -lenerr: - pbuf_free(p); - ICMP_STATS_INC(icmp.lenerr); - snmp_inc_icmpinerrors(); - return; -#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN -memerr: - pbuf_free(p); - ICMP_STATS_INC(icmp.err); - snmp_inc_icmpinerrors(); - return; -#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ -} - -/** - * Send an icmp 'destination unreachable' packet, called from ip_input() if - * the transport layer protocol is unknown and from udp_input() if the local - * port is not bound. - * - * @param p the input packet for which the 'unreachable' should be sent, - * p->payload pointing to the IP header - * @param t type of the 'unreachable' packet - */ -void ICACHE_FLASH_ATTR -icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) -{ - icmp_send_response(p, ICMP_DUR, t); -} - -#if IP_FORWARD || IP_REASSEMBLY -/** - * Send a 'time exceeded' packet, called from ip_forward() if TTL is 0. - * - * @param p the input packet for which the 'time exceeded' should be sent, - * p->payload pointing to the IP header - * @param t type of the 'time exceeded' packet - */ -void ICACHE_FLASH_ATTR -icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) -{ - icmp_send_response(p, ICMP_TE, t); -} - -#endif /* IP_FORWARD || IP_REASSEMBLY */ - -/** - * Send an icmp packet in response to an incoming packet. - * - * @param p the input packet for which the 'unreachable' should be sent, - * p->payload pointing to the IP header - * @param type Type of the ICMP header - * @param code Code of the ICMP header - */ -static void ICACHE_FLASH_ATTR -icmp_send_response(struct pbuf *p, u8_t type, u8_t code) -{ - struct pbuf *q; - struct ip_hdr *iphdr; - /* we can use the echo header here */ - struct icmp_echo_hdr *icmphdr; - ip_addr_t iphdr_src; - - /* ICMP header + IP header + 8 bytes of data */ - q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE, - PBUF_RAM); - if (q == NULL) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n")); - return; - } - LWIP_ASSERT("check that first pbuf can hold icmp message", - (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE))); - - iphdr = (struct ip_hdr *)p->payload; - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from ")); - ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src)); - LWIP_DEBUGF(ICMP_DEBUG, (" to ")); - ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest)); - LWIP_DEBUGF(ICMP_DEBUG, ("\n")); - - icmphdr = (struct icmp_echo_hdr *)q->payload; - icmphdr->type = type; - icmphdr->code = code; - icmphdr->id = 0; - icmphdr->seqno = 0; - - /* copy fields from original packet */ - SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload, - IP_HLEN + ICMP_DEST_UNREACH_DATASIZE); - - /* calculate checksum */ - icmphdr->chksum = 0; - icmphdr->chksum = inet_chksum(icmphdr, q->len); - ICMP_STATS_INC(icmp.xmit); - /* increase number of messages attempted to send */ - snmp_inc_icmpoutmsgs(); - /* increase number of destination unreachable messages attempted to send */ - snmp_inc_icmpouttimeexcds(); - ip_addr_copy(iphdr_src, iphdr->src); - ip_output(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP); - pbuf_free(q); -} - -#endif /* LWIP_ICMP */ diff --git a/third_party/lwip/core/ipv4/igmp.c b/third_party/lwip/core/ipv4/igmp.c deleted file mode 100644 index 223b2df..0000000 --- a/third_party/lwip/core/ipv4/igmp.c +++ /dev/null @@ -1,805 +0,0 @@ -/** - * @file - * IGMP - Internet Group Management Protocol - * - */ - -/* - * Copyright (c) 2002 CITEL Technologies Ltd. - * 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 CITEL Technologies Ltd 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 CITEL TECHNOLOGIES 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 CITEL TECHNOLOGIES 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 a contribution to the lwIP TCP/IP stack. - * The Swedish Institute of Computer Science and Adam Dunkels - * are specifically granted permission to redistribute this - * source code. -*/ - -/*------------------------------------------------------------- -Note 1) -Although the rfc requires V1 AND V2 capability -we will only support v2 since now V1 is very old (August 1989) -V1 can be added if required - -a debug print and statistic have been implemented to -show this up. -------------------------------------------------------------- -------------------------------------------------------------- -Note 2) -A query for a specific group address (as opposed to ALLHOSTS) -has now been implemented as I am unsure if it is required - -a debug print and statistic have been implemented to -show this up. -------------------------------------------------------------- -------------------------------------------------------------- -Note 3) -The router alert rfc 2113 is implemented in outgoing packets -but not checked rigorously incoming -------------------------------------------------------------- -Steve Reynolds -------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------- - * RFC 988 - Host extensions for IP multicasting - V0 - * RFC 1054 - Host extensions for IP multicasting - - * RFC 1112 - Host extensions for IP multicasting - V1 - * RFC 2236 - Internet Group Management Protocol, Version 2 - V2 <- this code is based on this RFC (it's the "de facto" standard) - * RFC 3376 - Internet Group Management Protocol, Version 3 - V3 - * RFC 4604 - Using Internet Group Management Protocol Version 3... - V3+ - * RFC 2113 - IP Router Alert Option - - *----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------- - * Includes - *----------------------------------------------------------------------------*/ - -#include "lwip/opt.h" - -#if LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/igmp.h" -#include "lwip/debug.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/ip.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/icmp.h" -#include "lwip/udp.h" -#include "lwip/tcp.h" -#include "lwip/stats.h" - -#include "string.h" - -/* - * IGMP constants - */ -#define IGMP_TTL 1 -#define IGMP_MINLEN 8 -#define ROUTER_ALERT 0x9404U -#define ROUTER_ALERTLEN 4 - -/* - * IGMP message types, including version number. - */ -#define IGMP_MEMB_QUERY 0x11 /* Membership query */ -#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */ -#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */ -#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */ - -/* Group membership states */ -#define IGMP_GROUP_NON_MEMBER 0 -#define IGMP_GROUP_DELAYING_MEMBER 1 -#define IGMP_GROUP_IDLE_MEMBER 2 - -/** - * IGMP packet format. - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct igmp_msg { - PACK_STRUCT_FIELD(u8_t igmp_msgtype); - PACK_STRUCT_FIELD(u8_t igmp_maxresp); - PACK_STRUCT_FIELD(u16_t igmp_checksum); - PACK_STRUCT_FIELD(ip_addr_p_t igmp_group_address); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - - -static struct igmp_group *igmp_lookup_group(struct netif *ifp, ip_addr_t *addr); -static err_t igmp_remove_group(struct igmp_group *group); -static void igmp_timeout( struct igmp_group *group); -static void igmp_start_timer(struct igmp_group *group, u8_t max_time); -static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp); -static err_t igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif); -static void igmp_send(struct igmp_group *group, u8_t type); - - -static struct igmp_group* igmp_group_list; -static ip_addr_t allsystems; -static ip_addr_t allrouters; - - -/** - * Initialize the IGMP module - */ -void ICACHE_FLASH_ATTR -igmp_init(void) -{ - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_init: initializing\n")); - - IP4_ADDR(&allsystems, 224, 0, 0, 1); - IP4_ADDR(&allrouters, 224, 0, 0, 2); -} - -#ifdef LWIP_DEBUG -/** - * Dump global IGMP groups list - */ -void -igmp_dump_group_list() -{ - struct igmp_group *group = igmp_group_list; - - while (group != NULL) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_dump_group_list: [%"U32_F"] ", (u32_t)(group->group_state))); - ip_addr_debug_print(IGMP_DEBUG, &group->group_address); - LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif)); - group = group->next; - } - LWIP_DEBUGF(IGMP_DEBUG, ("\n")); -} -#else -#define igmp_dump_group_list() -#endif /* LWIP_DEBUG */ - -/** - * Start IGMP processing on interface - * - * @param netif network interface on which start IGMP processing - */ -err_t ICACHE_FLASH_ATTR -igmp_start(struct netif *netif) -{ - struct igmp_group* group; - - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", netif)); - - group = igmp_lookup_group(netif, &allsystems); - - if (group != NULL) { - group->group_state = IGMP_GROUP_IDLE_MEMBER; - group->use++; - - /* Allow the igmp messages at the MAC level */ - if (netif->igmp_mac_filter != NULL) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD ")); - ip_addr_debug_print(IGMP_DEBUG, &allsystems); - LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); - netif->igmp_mac_filter(netif, &allsystems, IGMP_ADD_MAC_FILTER); - } - - return ERR_OK; - } - - return ERR_MEM; -} - -/** - * Stop IGMP processing on interface - * - * @param netif network interface on which stop IGMP processing - */ -err_t ICACHE_FLASH_ATTR -igmp_stop(struct netif *netif) -{ - struct igmp_group *group = igmp_group_list; - struct igmp_group *prev = NULL; - struct igmp_group *next; - - /* look for groups joined on this interface further down the list */ - while (group != NULL) { - next = group->next; - /* is it a group joined on this interface? */ - if (group->netif == netif) { - /* is it the first group of the list? */ - if (group == igmp_group_list) { - igmp_group_list = next; - } - /* is there a "previous" group defined? */ - if (prev != NULL) { - prev->next = next; - } - /* disable the group at the MAC level */ - if (netif->igmp_mac_filter != NULL) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL ")); - ip_addr_debug_print(IGMP_DEBUG, &group->group_address); - LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); - netif->igmp_mac_filter(netif, &(group->group_address), IGMP_DEL_MAC_FILTER); - } - /* free group */ - memp_free(MEMP_IGMP_GROUP, group); - } else { - /* change the "previous" */ - prev = group; - } - /* move to "next" */ - group = next; - } - return ERR_OK; -} - -/** - * Report IGMP memberships for this interface - * - * @param netif network interface on which report IGMP memberships - */ -void ICACHE_FLASH_ATTR -igmp_report_groups(struct netif *netif) -{ - struct igmp_group *group = igmp_group_list; - - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", netif)); - - while (group != NULL) { - if (group->netif == netif) { - igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR); - } - group = group->next; - } -} - -/** - * Search for a group in the global igmp_group_list - * - * @param ifp the network interface for which to look - * @param addr the group ip address to search for - * @return a struct igmp_group* if the group has been found, - * NULL if the group wasn't found. - */ -struct igmp_group * ICACHE_FLASH_ATTR -igmp_lookfor_group(struct netif *ifp, ip_addr_t *addr) -{ - struct igmp_group *group = igmp_group_list; - - while (group != NULL) { - if ((group->netif == ifp) && (ip_addr_cmp(&(group->group_address), addr))) { - return group; - } - group = group->next; - } - - /* to be clearer, we return NULL here instead of - * 'group' (which is also NULL at this point). - */ - return NULL; -} - -/** - * Search for a specific igmp group and create a new one if not found- - * - * @param ifp the network interface for which to look - * @param addr the group ip address to search - * @return a struct igmp_group*, - * NULL on memory error. - */ -struct igmp_group * ICACHE_FLASH_ATTR -igmp_lookup_group(struct netif *ifp, ip_addr_t *addr) -{ - struct igmp_group *group = igmp_group_list; - - /* Search if the group already exists */ - group = igmp_lookfor_group(ifp, addr); - if (group != NULL) { - /* Group already exists. */ - return group; - } - - /* Group doesn't exist yet, create a new one */ - group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP); - if (group != NULL) { - group->netif = ifp; - ip_addr_set(&(group->group_address), addr); - group->timer = 0; /* Not running */ - group->group_state = IGMP_GROUP_NON_MEMBER; - group->last_reporter_flag = 0; - group->use = 0; - group->next = igmp_group_list; - - igmp_group_list = group; - } - - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to "))); - ip_addr_debug_print(IGMP_DEBUG, addr); - LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", ifp)); - - return group; -} - -/** - * Remove a group in the global igmp_group_list - * - * @param group the group to remove from the global igmp_group_list - * @return ERR_OK if group was removed from the list, an err_t otherwise - */ -static err_t ICACHE_FLASH_ATTR -igmp_remove_group(struct igmp_group *group) -{ - err_t err = ERR_OK; - - /* Is it the first group? */ - if (igmp_group_list == group) { - igmp_group_list = group->next; - } else { - /* look for group further down the list */ - struct igmp_group *tmpGroup; - for (tmpGroup = igmp_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) { - if (tmpGroup->next == group) { - tmpGroup->next = group->next; - break; - } - } - /* Group not found in the global igmp_group_list */ - if (tmpGroup == NULL) - err = ERR_ARG; - } - /* free group */ - memp_free(MEMP_IGMP_GROUP, group); - - return err; -} - -/** - * Called from ip_input() if a new IGMP packet is received. - * - * @param p received igmp packet, p->payload pointing to the igmp header - * @param inp network interface on which the packet was received - * @param dest destination ip address of the igmp packet - */ -void ICACHE_FLASH_ATTR -igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest) -{ - struct igmp_msg* igmp; - struct igmp_group* group; - struct igmp_group* groupref; - - IGMP_STATS_INC(igmp.recv); - - /* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */ - if (p->len < IGMP_MINLEN) { - pbuf_free(p); - IGMP_STATS_INC(igmp.lenerr); - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n")); - return; - } - - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from ")); - ip_addr_debug_print(IGMP_DEBUG, &(ip_current_header()->src)); - LWIP_DEBUGF(IGMP_DEBUG, (" to address ")); - ip_addr_debug_print(IGMP_DEBUG, &(ip_current_header()->dest)); - LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", inp)); - - /* Now calculate and check the checksum */ - igmp = (struct igmp_msg *)p->payload; - if (inet_chksum(igmp, p->len)) { - pbuf_free(p); - IGMP_STATS_INC(igmp.chkerr); - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: checksum error\n")); - return; - } - - /* Packet is ok so find an existing group */ - group = igmp_lookfor_group(inp, dest); /* use the destination IP address of incoming packet */ - - /* If group can be found or create... */ - if (!group) { - pbuf_free(p); - IGMP_STATS_INC(igmp.drop); - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n")); - return; - } - - /* NOW ACT ON THE INCOMING MESSAGE TYPE... */ - switch (igmp->igmp_msgtype) { - case IGMP_MEMB_QUERY: { - /* IGMP_MEMB_QUERY to the "all systems" address ? */ - if ((ip_addr_cmp(dest, &allsystems)) && ip_addr_isany(&igmp->igmp_group_address)) { - /* THIS IS THE GENERAL QUERY */ - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); - - if (igmp->igmp_maxresp == 0) { - IGMP_STATS_INC(igmp.rx_v1); - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n")); - igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR; - } else { - IGMP_STATS_INC(igmp.rx_general); - } - - groupref = igmp_group_list; - while (groupref) { - /* Do not send messages on the all systems group address! */ - if ((groupref->netif == inp) && (!(ip_addr_cmp(&(groupref->group_address), &allsystems)))) { - igmp_delaying_member(groupref, igmp->igmp_maxresp); - } - groupref = groupref->next; - } - } else { - /* IGMP_MEMB_QUERY to a specific group ? */ - if (!ip_addr_isany(&igmp->igmp_group_address)) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group ")); - ip_addr_debug_print(IGMP_DEBUG, &igmp->igmp_group_address); - if (ip_addr_cmp(dest, &allsystems)) { - ip_addr_t groupaddr; - LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); - /* we first need to re-look for the group since we used dest last time */ - ip_addr_copy(groupaddr, igmp->igmp_group_address); - group = igmp_lookfor_group(inp, &groupaddr); - } else { - LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); - } - - if (group != NULL) { - IGMP_STATS_INC(igmp.rx_group); - igmp_delaying_member(group, igmp->igmp_maxresp); - } else { - IGMP_STATS_INC(igmp.drop); - } - } else { - IGMP_STATS_INC(igmp.proterr); - } - } - break; - } - case IGMP_V2_MEMB_REPORT: { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n")); - IGMP_STATS_INC(igmp.rx_report); - if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) { - /* This is on a specific group we have already looked up */ - group->timer = 0; /* stopped */ - group->group_state = IGMP_GROUP_IDLE_MEMBER; - group->last_reporter_flag = 0; - } - break; - } - default: { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n", - igmp->igmp_msgtype, group->group_state, &group, group->netif)); - IGMP_STATS_INC(igmp.proterr); - break; - } - } - - pbuf_free(p); - return; -} - -/** - * Join a group on one network interface. - * - * @param ifaddr ip address of the network interface which should join a new group - * @param groupaddr the ip address of the group which to join - * @return ERR_OK if group was joined on the netif(s), an err_t otherwise - */ -err_t ICACHE_FLASH_ATTR -igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr) -{ - err_t err = ERR_VAL; /* no matching interface */ - struct igmp_group *group; - struct netif *netif; - - /* make sure it is multicast address */ - LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;); - LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); - - /* loop through netif's */ - netif = netif_list; - while (netif != NULL) { - /* Should we join this interface ? */ - if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) { - /* find group or create a new one if not found */ - group = igmp_lookup_group(netif, groupaddr); - - if (group != NULL) { - /* This should create a new group, check the state to make sure */ - if (group->group_state != IGMP_GROUP_NON_MEMBER) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to group not in state IGMP_GROUP_NON_MEMBER\n")); - } else { - /* OK - it was new group */ - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to new group: ")); - ip_addr_debug_print(IGMP_DEBUG, groupaddr); - LWIP_DEBUGF(IGMP_DEBUG, ("\n")); - - /* If first use of the group, allow the group at the MAC level */ - if ((group->use==0) && (netif->igmp_mac_filter != NULL)) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: igmp_mac_filter(ADD ")); - ip_addr_debug_print(IGMP_DEBUG, groupaddr); - LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); - netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER); - } - - IGMP_STATS_INC(igmp.tx_join); - igmp_send(group, IGMP_V2_MEMB_REPORT); - - igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR); - - /* Need to work out where this timer comes from */ - group->group_state = IGMP_GROUP_DELAYING_MEMBER; - } - /* Increment group use */ - group->use++; - /* Join on this interface */ - err = ERR_OK; - } else { - /* Return an error even if some network interfaces are joined */ - /** @todo undo any other netif already joined */ - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: Not enought memory to join to group\n")); - return ERR_MEM; - } - } - /* proceed to next network interface */ - netif = netif->next; - } - - return err; -} - -/** - * Leave a group on one network interface. - * - * @param ifaddr ip address of the network interface which should leave a group - * @param groupaddr the ip address of the group which to leave - * @return ERR_OK if group was left on the netif(s), an err_t otherwise - */ -err_t ICACHE_FLASH_ATTR -igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr) -{ - err_t err = ERR_VAL; /* no matching interface */ - struct igmp_group *group; - struct netif *netif; - - /* make sure it is multicast address */ - LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;); - LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); - - /* loop through netif's */ - netif = netif_list; - while (netif != NULL) { - /* Should we leave this interface ? */ - if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) { - /* find group */ - group = igmp_lookfor_group(netif, groupaddr); - - if (group != NULL) { - /* Only send a leave if the flag is set according to the state diagram */ - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: Leaving group: ")); - ip_addr_debug_print(IGMP_DEBUG, groupaddr); - LWIP_DEBUGF(IGMP_DEBUG, ("\n")); - - /* If there is no other use of the group */ - if (group->use <= 1) { - /* If we are the last reporter for this group */ - if (group->last_reporter_flag) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: sending leaving group\n")); - IGMP_STATS_INC(igmp.tx_leave); - igmp_send(group, IGMP_LEAVE_GROUP); - } - - /* Disable the group at the MAC level */ - if (netif->igmp_mac_filter != NULL) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: igmp_mac_filter(DEL ")); - ip_addr_debug_print(IGMP_DEBUG, groupaddr); - LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif)); - netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER); - } - - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: remove group: ")); - ip_addr_debug_print(IGMP_DEBUG, groupaddr); - LWIP_DEBUGF(IGMP_DEBUG, ("\n")); - - /* Free the group */ - igmp_remove_group(group); - } else { - /* Decrement group use */ - group->use--; - } - /* Leave on this interface */ - err = ERR_OK; - } else { - /* It's not a fatal error on "leavegroup" */ - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: not member of group\n")); - } - } - /* proceed to next network interface */ - netif = netif->next; - } - - return err; -} - -/** - * The igmp timer function (both for NO_SYS=1 and =0) - * Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default). - */ -void ICACHE_FLASH_ATTR -igmp_tmr(void) -{ - struct igmp_group *group = igmp_group_list; - - while (group != NULL) { - if (group->timer > 0) { - group->timer--; - if (group->timer == 0) { - igmp_timeout(group); - } - } - group = group->next; - } -} - -/** - * Called if a timeout for one group is reached. - * Sends a report for this group. - * - * @param group an igmp_group for which a timeout is reached - */ -static void ICACHE_FLASH_ATTR -igmp_timeout(struct igmp_group *group) -{ - /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group */ - if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address ")); - ip_addr_debug_print(IGMP_DEBUG, &(group->group_address)); - LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif)); - - IGMP_STATS_INC(igmp.tx_report); - igmp_send(group, IGMP_V2_MEMB_REPORT); - } -} - -/** - * Start a timer for an igmp group - * - * @param group the igmp_group for which to start a timer - * @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with - * every call to igmp_tmr()) - */ -static void ICACHE_FLASH_ATTR -igmp_start_timer(struct igmp_group *group, u8_t max_time) -{ - /* ensure the input value is > 0 */ - if (max_time == 0) { - max_time = 1; - } -#ifdef LWIP_RAND - /* ensure the random value is > 0 */ - group->timer = (LWIP_RAND() % max_time); -#endif /* LWIP_RAND */ -} - -/** - * Delaying membership report for a group if necessary - * - * @param group the igmp_group for which "delaying" membership report - * @param maxresp query delay - */ -static void ICACHE_FLASH_ATTR -igmp_delaying_member(struct igmp_group *group, u8_t maxresp) -{ - if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) || - ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && - ((group->timer == 0) || (maxresp < group->timer)))) { - igmp_start_timer(group, maxresp); - group->group_state = IGMP_GROUP_DELAYING_MEMBER; - } -} - - -/** - * Sends an IP packet on a network interface. This function constructs the IP header - * and calculates the IP header checksum. If the source IP address is NULL, - * the IP address of the outgoing network interface is filled in as source address. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == IP_HDRINCL, p already includes an IP - header and p->payload points to that IP header) - * @param src the source IP address to send from (if src == IP_ADDR_ANY, the - * IP address of the netif used to send is used as source address) - * @param dest the destination IP address to send the packet to - * @param ttl the TTL value to be set in the IP header - * @param proto the PROTOCOL to be set in the IP header - * @param netif the netif on which to send this packet - * @return ERR_OK if the packet was sent OK - * ERR_BUF if p doesn't have enough space for IP/LINK headers - * returns errors returned by netif->output - */ -static err_t ICACHE_FLASH_ATTR -igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif) -{ - /* This is the "router alert" option */ - u16_t ra[2]; - ra[0] = PP_HTONS(ROUTER_ALERT); - ra[1] = 0x0000; /* Router shall examine packet */ - IGMP_STATS_INC(igmp.xmit); - return ip_output_if_opt(p, src, dest, IGMP_TTL, 0, IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN); -} - -/** - * Send an igmp packet to a specific group. - * - * @param group the group to which to send the packet - * @param type the type of igmp packet to send - */ -static void ICACHE_FLASH_ATTR -igmp_send(struct igmp_group *group, u8_t type) -{ - struct pbuf* p = NULL; - struct igmp_msg* igmp = NULL; - ip_addr_t src = *IP_ADDR_ANY; - ip_addr_t* dest = NULL; - - /* IP header + "router alert" option + IGMP header */ - p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM); - - if (p) { - igmp = (struct igmp_msg *)p->payload; - LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg", - (p->len >= sizeof(struct igmp_msg))); - ip_addr_copy(src, group->netif->ip_addr); - - if (type == IGMP_V2_MEMB_REPORT) { - dest = &(group->group_address); - ip_addr_copy(igmp->igmp_group_address, group->group_address); - group->last_reporter_flag = 1; /* Remember we were the last to report */ - } else { - if (type == IGMP_LEAVE_GROUP) { - dest = &allrouters; - ip_addr_copy(igmp->igmp_group_address, group->group_address); - } - } - - if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) { - igmp->igmp_msgtype = type; - igmp->igmp_maxresp = 0; - igmp->igmp_checksum = 0; - igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN); - - igmp_ip_output_if(p, &src, dest, group->netif); - } - - pbuf_free(p); - } else { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n")); - IGMP_STATS_INC(igmp.memerr); - } -} - -#endif /* LWIP_IGMP */ diff --git a/third_party/lwip/core/ipv4/ip4.c b/third_party/lwip/core/ipv4/ip4.c deleted file mode 100644 index 8d3a34d..0000000 --- a/third_party/lwip/core/ipv4/ip4.c +++ /dev/null @@ -1,922 +0,0 @@ -/** - * @file - * This is the IPv4 layer implementation for incoming and outgoing IP traffic. - * - * @see ip_frag.c - * - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" -#include "lwip/ip.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/ip_frag.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/icmp.h" -#include "lwip/igmp.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/tcp_impl.h" -#include "lwip/snmp.h" -#include "lwip/dhcp.h" -#include "lwip/autoip.h" -#include "lwip/stats.h" -#include "arch/perf.h" - -#include - -/** Set this to 0 in the rare case of wanting to call an extra function to - * generate the IP checksum (in contrast to calculating it on-the-fly). */ -#ifndef LWIP_INLINE_IP_CHKSUM -#define LWIP_INLINE_IP_CHKSUM 1 -#endif -#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP -#define CHECKSUM_GEN_IP_INLINE 1 -#else -#define CHECKSUM_GEN_IP_INLINE 0 -#endif - -#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT) -#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1 - -/** Some defines for DHCP to let link-layer-addressed packets through while the - * netif is down. - * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT - * to return 1 if the port is accepted and 0 if the port is not accepted. - */ -#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) -/* accept DHCP client port and custom port */ -#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \ - || (LWIP_IP_ACCEPT_UDP_PORT(port))) -#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ -/* accept custom port only */ -#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(port)) -#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ -/* accept DHCP client port only */ -#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT)) -#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ - -#else /* LWIP_DHCP */ -#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0 -#endif /* LWIP_DHCP */ - -/** Global data for both IPv4 and IPv6 */ -struct ip_globals ip_data; - -/** The IP header ID of the next outgoing IP packet */ -static u16_t ip_id; - -/** - * Finds the appropriate network interface for a given IP address. It - * searches the list of network interfaces linearly. A match is found - * if the masked IP address of the network interface equals the masked - * IP address given to the function. - * - * @param dest the destination IP address for which to find the route - * @return the netif on which to send to reach dest - */ -struct netif * ICACHE_FLASH_ATTR -ip_route(ip_addr_t *dest) -{ - struct netif *netif; - -#ifdef LWIP_HOOK_IP4_ROUTE - netif = LWIP_HOOK_IP4_ROUTE(dest); - if (netif != NULL) { - return netif; - } -#endif - - /* iterate through netifs */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - /* network mask matches? */ - if (netif_is_up(netif)) { - if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) { - /* return netif on which to forward IP packet */ - return netif; - } - if (!ip_addr_isbroadcast(dest, netif) && netif != netif_default) { - return netif; - } - } - } - if ((netif_default == NULL) || (!netif_is_up(netif_default))) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); - IP_STATS_INC(ip.rterr); - snmp_inc_ipoutnoroutes(); - return NULL; - } - /* no matching netif found, use default netif */ - return netif_default; -} - -#if IP_FORWARD -/** - * Determine whether an IP address is in a reserved set of addresses - * that may not be forwarded, or whether datagrams to that destination - * may be forwarded. - * @param p the packet to forward - * @param dest the destination IP address - * @return 1: can forward 0: discard - */ -static int ICACHE_FLASH_ATTR -ip_canforward(struct pbuf *p) -{ - u32_t addr = htonl(ip4_addr_get_u32(ip_current_dest_addr())); - - if (p->flags & PBUF_FLAG_LLBCAST) { - /* don't route link-layer broadcasts */ - return 0; - } - if ((p->flags & PBUF_FLAG_LLMCAST) && !IP_MULTICAST(addr)) { - /* don't route link-layer multicasts unless the destination address is an IP - multicast address */ - return 0; - } - if (IP_EXPERIMENTAL(addr)) { - return 0; - } - if (IP_CLASSA(addr)) { - u32_t net = addr & IP_CLASSA_NET; - if ((net == 0) || (net == ((u32_t)IP_LOOPBACKNET << IP_CLASSA_NSHIFT))) { - /* don't route loopback packets */ - return 0; - } - } - return 1; -} - -/** - * Forwards an IP packet. It finds an appropriate route for the - * packet, decrements the TTL value of the packet, adjusts the - * checksum and outputs the packet on the appropriate interface. - * - * @param p the packet to forward (p->payload points to IP header) - * @param iphdr the IP header of the input packet - * @param inp the netif on which this packet was received - */ -static void ICACHE_FLASH_ATTR -ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) -{ - struct netif *netif; - - PERF_START; - - if (!ip_canforward(p)) { - goto return_noroute; - } - - /* RFC3927 2.7: do not forward link-local addresses */ - if (ip_addr_islinklocal(ip_current_dest_addr())) { - LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(ip_current_dest_addr()), ip4_addr2_16(ip_current_dest_addr()), - ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr()))); - goto return_noroute; - } - - /* Find network interface where to forward this IP packet to. */ - netif = ip_route(ip_current_dest_addr()); - if (netif == NULL) { - LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n", - ip4_addr1_16(ip_current_dest_addr()), ip4_addr2_16(ip_current_dest_addr()), - ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr()))); - /* @todo: send ICMP_DUR_NET? */ - goto return_noroute; - } -#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF - /* Do not forward packets onto the same network interface on which - * they arrived. */ - if (netif == inp) { - LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n")); - goto return_noroute; - } -#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */ - - /* decrement TTL */ - IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1); - /* send ICMP if TTL == 0 */ - if (IPH_TTL(iphdr) == 0) { - snmp_inc_ipinhdrerrors(); -#if LWIP_ICMP - /* Don't send ICMP messages in response to ICMP messages */ - if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) { - icmp_time_exceeded(p, ICMP_TE_TTL); - } -#endif /* LWIP_ICMP */ - return; - } - - /* Incrementally update the IP checksum. */ - if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) { - IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1); - } else { - IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100)); - } - - LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(ip_current_dest_addr()), ip4_addr2_16(ip_current_dest_addr()), - ip4_addr3_16(ip_current_dest_addr()), ip4_addr4_16(ip_current_dest_addr()))); - - IP_STATS_INC(ip.fw); - IP_STATS_INC(ip.xmit); - snmp_inc_ipforwdatagrams(); - - PERF_STOP("ip_forward"); - /* don't fragment if interface has mtu set to 0 [loopif] */ - if (netif->mtu && (p->tot_len > netif->mtu)) { - if ((IPH_OFFSET(iphdr) & PP_NTOHS(IP_DF)) == 0) { -#if IP_FRAG - ip_frag(p, netif, ip_current_dest_addr()); -#else /* IP_FRAG */ - /* @todo: send ICMP Destination Unreacheable code 13 "Communication administratively prohibited"? */ -#endif /* IP_FRAG */ - } else { - /* send ICMP Destination Unreacheable code 4: "Fragmentation Needed and DF Set" */ - icmp_dest_unreach(p, ICMP_DUR_FRAG); - } - return; - } - /* transmit pbuf on chosen interface */ - netif->output(netif, p, ip_current_dest_addr()); - return; -return_noroute: - snmp_inc_ipoutnoroutes(); -} -#endif /* IP_FORWARD */ - -/** - * This function is called by the network interface device driver when - * an IP packet is received. The function does the basic checks of the - * IP header such as packet size being at least larger than the header - * size etc. If the packet was not destined for us, the packet is - * forwarded (using ip_forward). The IP checksum is always checked. - * - * Finally, the packet is sent to the upper layer protocol input function. - * - * @param p the received IP packet (p->payload points to IP header) - * @param inp the netif on which this packet was received - * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't - * processed, but currently always returns ERR_OK) - */ -err_t ICACHE_FLASH_ATTR -ip_input(struct pbuf *p, struct netif *inp) -{ - struct ip_hdr *iphdr; - struct netif *netif; - u16_t iphdr_hlen; - u16_t iphdr_len; -#if IP_ACCEPT_LINK_LAYER_ADDRESSING - int check_ip_src=1; -#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ - - IP_STATS_INC(ip.recv); - snmp_inc_ipinreceives(); - - /* identify the IP header */ - iphdr = (struct ip_hdr *)p->payload; - if (IPH_V(iphdr) != 4) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr))); - ip_debug_print(p); - pbuf_free(p); - IP_STATS_INC(ip.err); - IP_STATS_INC(ip.drop); - snmp_inc_ipinhdrerrors(); - return ERR_OK; - } - -#ifdef LWIP_HOOK_IP4_INPUT - if (LWIP_HOOK_IP4_INPUT(p, inp)) { - /* the packet has been eaten */ - return ERR_OK; - } -#endif - - /* obtain IP header length in number of 32-bit words */ - iphdr_hlen = IPH_HL(iphdr); - /* calculate IP header length in bytes */ - iphdr_hlen *= 4; - /* obtain ip length in bytes */ - iphdr_len = ntohs(IPH_LEN(iphdr)); - - /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ - if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) { - if (iphdr_hlen > p->len) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", - iphdr_hlen, p->len)); - } - if (iphdr_len > p->tot_len) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", - iphdr_len, p->tot_len)); - } - /* free (drop) packet pbufs */ - pbuf_free(p); - IP_STATS_INC(ip.lenerr); - IP_STATS_INC(ip.drop); - snmp_inc_ipindiscards(); - return ERR_OK; - } - - /* verify checksum */ -#if CHECKSUM_CHECK_IP - if (inet_chksum(iphdr, iphdr_hlen) != 0) { - - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen))); - ip_debug_print(p); - pbuf_free(p); - IP_STATS_INC(ip.chkerr); - IP_STATS_INC(ip.drop); - snmp_inc_ipinhdrerrors(); - return ERR_OK; - } -#endif - - /* Trim pbuf. This should have been done at the netif layer, - * but we'll do it anyway just to be sure that its done. */ - pbuf_realloc(p, iphdr_len); - - /* copy IP addresses to aligned ip_addr_t */ - ip_addr_copy(*ipX_2_ip(&ip_data.current_iphdr_dest), iphdr->dest); - ip_addr_copy(*ipX_2_ip(&ip_data.current_iphdr_src), iphdr->src); - - /* match packet against an interface, i.e. is this packet for us? */ -#if LWIP_IGMP - if (ip_addr_ismulticast(ip_current_dest_addr())) { - if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ip_current_dest_addr()))) { - netif = inp; - } else { - netif = NULL; - } - } else -#endif /* LWIP_IGMP */ - { - /* start trying with inp. if that's not acceptable, start walking the - list of configured netifs. - 'first' is used as a boolean to mark whether we started walking the list */ - int first = 1; - netif = inp; - do { - LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n", - ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(&netif->ip_addr), - ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(&netif->netmask), - ip4_addr_get_u32(&netif->ip_addr) & ip4_addr_get_u32(&netif->netmask), - ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(&netif->netmask))); - - /* interface is up and configured? */ - if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) { - /* unicast to this interface address? */ - if (ip_addr_cmp(ip_current_dest_addr(), &(netif->ip_addr)) || - /* or broadcast on this interface network address? */ - ip_addr_isbroadcast(ip_current_dest_addr(), netif)) { - LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n", - netif->name[0], netif->name[1])); - /* break out of for loop */ - break; - } -#if LWIP_AUTOIP - /* connections to link-local addresses must persist after changing - the netif's address (RFC3927 ch. 1.9) */ - if ((netif->autoip != NULL) && - ip_addr_cmp(ip_current_dest_addr(), &(netif->autoip->llipaddr))) { - LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n", - netif->name[0], netif->name[1])); - /* break out of for loop */ - break; - } -#endif /* LWIP_AUTOIP */ - } - if (first) { - first = 0; - netif = netif_list; - } else { - netif = netif->next; - } - if (netif == inp) { - netif = netif->next; - } - } while(netif != NULL); - } - -#if IP_ACCEPT_LINK_LAYER_ADDRESSING - /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed - * using link layer addressing (such as Ethernet MAC) so we must not filter on IP. - * According to RFC 1542 section 3.1.1, referred by RFC 2131). - * - * If you want to accept private broadcast communication while a netif is down, - * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.: - * - * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345)) - */ - if (netif == NULL) { - /* remote port is DHCP server? */ - if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { - struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen); - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n", - ntohs(udphdr->dest))); - if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n")); - netif = inp; - check_ip_src = 0; - } - } - } -#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ - - /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */ -#if IP_ACCEPT_LINK_LAYER_ADDRESSING - /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */ - if (check_ip_src && !ip_addr_isany(ip_current_src_addr())) -#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ - { if ((ip_addr_isbroadcast(ip_current_src_addr(), inp)) || - (ip_addr_ismulticast(ip_current_src_addr()))) { - /* packet source is not valid */ - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n")); - /* free (drop) packet pbufs */ - pbuf_free(p); - IP_STATS_INC(ip.drop); - snmp_inc_ipinaddrerrors(); - snmp_inc_ipindiscards(); - return ERR_OK; - } - } - - /* packet not for us? */ - if (netif == NULL) { - /* packet not for us, route or discard */ - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n")); -#if IP_FORWARD - /* non-broadcast packet? */ - if (!ip_addr_isbroadcast(ip_current_dest_addr(), inp)) { - /* try to forward IP packet on (other) interfaces */ - ip_forward(p, iphdr, inp); - } else -#endif /* IP_FORWARD */ - { - snmp_inc_ipinaddrerrors(); - snmp_inc_ipindiscards(); - } - pbuf_free(p); - return ERR_OK; - } - /* packet consists of multiple fragments? */ - if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) { -#if IP_REASSEMBLY /* packet fragment reassembly code present? */ - LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n", - ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8)); - /* reassemble the packet*/ - p = ip_reass(p); - /* packet not fully reassembled yet? */ - if (p == NULL) { - return ERR_OK; - } - iphdr = (struct ip_hdr *)p->payload; -#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ - pbuf_free(p); - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", - ntohs(IPH_OFFSET(iphdr)))); - IP_STATS_INC(ip.opterr); - IP_STATS_INC(ip.drop); - /* unsupported protocol feature */ - snmp_inc_ipinunknownprotos(); - return ERR_OK; -#endif /* IP_REASSEMBLY */ - } - -#if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */ - -#if LWIP_IGMP - /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */ - if((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) { -#else - if (iphdr_hlen > IP_HLEN) { -#endif /* LWIP_IGMP */ - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n")); - pbuf_free(p); - IP_STATS_INC(ip.opterr); - IP_STATS_INC(ip.drop); - /* unsupported protocol feature */ - snmp_inc_ipinunknownprotos(); - return ERR_OK; - } -#endif /* IP_OPTIONS_ALLOWED == 0 */ - - /* send to upper layers */ - LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n")); - ip_debug_print(p); - LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); - - ip_data.current_netif = inp; - ip_data.current_ip4_header = iphdr; - ip_data.current_ip_header_tot_len = IPH_HL(iphdr) * 4; - -#if LWIP_RAW - /* raw input did not eat the packet? */ - if (raw_input(p, inp) == 0) -#endif /* LWIP_RAW */ - { - pbuf_header(p, -iphdr_hlen); /* Move to payload, no check necessary. */ - - switch (IPH_PROTO(iphdr)) { -#if LWIP_UDP - case IP_PROTO_UDP: -#if LWIP_UDPLITE - case IP_PROTO_UDPLITE: -#endif /* LWIP_UDPLITE */ - snmp_inc_ipindelivers(); - udp_input(p, inp); - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case IP_PROTO_TCP: - snmp_inc_ipindelivers(); - tcp_input(p, inp); - break; -#endif /* LWIP_TCP */ -#if LWIP_ICMP - case IP_PROTO_ICMP: - snmp_inc_ipindelivers(); - icmp_input(p, inp); - break; -#endif /* LWIP_ICMP */ -#if LWIP_IGMP - case IP_PROTO_IGMP: - igmp_input(p, inp, ip_current_dest_addr()); - break; -#endif /* LWIP_IGMP */ - default: -#if LWIP_ICMP - /* send ICMP destination protocol unreachable unless is was a broadcast */ - if (!ip_addr_isbroadcast(ip_current_dest_addr(), inp) && - !ip_addr_ismulticast(ip_current_dest_addr())) { - pbuf_header(p, iphdr_hlen); /* Move to ip header, no check necessary. */ - p->payload = iphdr; - icmp_dest_unreach(p, ICMP_DUR_PROTO); - } -#endif /* LWIP_ICMP */ - pbuf_free(p); - - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr))); - - IP_STATS_INC(ip.proterr); - IP_STATS_INC(ip.drop); - snmp_inc_ipinunknownprotos(); - } - } - - /* @todo: this is not really necessary... */ - ip_data.current_netif = NULL; - ip_data.current_ip4_header = NULL; - ip_data.current_ip_header_tot_len = 0; - ip_addr_set_any(ip_current_src_addr()); - ip_addr_set_any(ip_current_dest_addr()); - - return ERR_OK; -} - -/** - * Sends an IP packet on a network interface. This function constructs - * the IP header and calculates the IP header checksum. If the source - * IP address is NULL, the IP address of the outgoing network - * interface is filled in as source address. - * If the destination IP address is IP_HDRINCL, p is assumed to already - * include an IP header and p->payload points to it instead of the data. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == IP_HDRINCL, p already includes an IP - header and p->payload points to that IP header) - * @param src the source IP address to send from (if src == IP_ADDR_ANY, the - * IP address of the netif used to send is used as source address) - * @param dest the destination IP address to send the packet to - * @param ttl the TTL value to be set in the IP header - * @param tos the TOS value to be set in the IP header - * @param proto the PROTOCOL to be set in the IP header - * @param netif the netif on which to send this packet - * @return ERR_OK if the packet was sent OK - * ERR_BUF if p doesn't have enough space for IP/LINK headers - * returns errors returned by netif->output - * - * @note ip_id: RFC791 "some host may be able to simply use - * unique identifiers independent of destination" - */ -err_t ICACHE_FLASH_ATTR -ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, - u8_t ttl, u8_t tos, - u8_t proto, struct netif *netif) -{ -#if IP_OPTIONS_SEND - return ip_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0); -} - -/** - * Same as ip_output_if() but with the possibility to include IP options: - * - * @ param ip_options pointer to the IP options, copied into the IP header - * @ param optlen length of ip_options - */ -err_t ICACHE_FLASH_ATTR -ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, - u16_t optlen) -{ -#endif /* IP_OPTIONS_SEND */ - struct ip_hdr *iphdr; - ip_addr_t dest_addr; -#if CHECKSUM_GEN_IP_INLINE - u32_t chk_sum = 0; -#endif /* CHECKSUM_GEN_IP_INLINE */ - - /* pbufs passed to IP must have a ref-count of 1 as their payload pointer - gets altered as the packet is passed down the stack */ - LWIP_ASSERT("p->ref == 1", p->ref == 1); - - snmp_inc_ipoutrequests(); - - /* Should the IP header be generated or is it already included in p? */ - if (dest != IP_HDRINCL) { - u16_t ip_hlen = IP_HLEN; -#if IP_OPTIONS_SEND - u16_t optlen_aligned = 0; - if (optlen != 0) { -#if CHECKSUM_GEN_IP_INLINE - int i; -#endif /* CHECKSUM_GEN_IP_INLINE */ - /* round up to a multiple of 4 */ - optlen_aligned = ((optlen + 3) & ~3); - ip_hlen += optlen_aligned; - /* First write in the IP options */ - if (pbuf_header(p, optlen_aligned)) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output_if_opt: not enough room for IP options in pbuf\n")); - IP_STATS_INC(ip.err); - snmp_inc_ipoutdiscards(); - return ERR_BUF; - } - MEMCPY(p->payload, ip_options, optlen); - if (optlen < optlen_aligned) { - /* zero the remaining bytes */ - memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); - } -#if CHECKSUM_GEN_IP_INLINE - for (i = 0; i < optlen_aligned/2; i++) { - chk_sum += ((u16_t*)p->payload)[i]; - } -#endif /* CHECKSUM_GEN_IP_INLINE */ - } -#endif /* IP_OPTIONS_SEND */ - /* generate IP header */ - if (pbuf_header(p, IP_HLEN)) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output: not enough room for IP header in pbuf\n")); - - IP_STATS_INC(ip.err); - snmp_inc_ipoutdiscards(); - return ERR_BUF; - } - - iphdr = (struct ip_hdr *)p->payload; - LWIP_ASSERT("check that first pbuf can hold struct ip_hdr", - (p->len >= sizeof(struct ip_hdr))); - - IPH_TTL_SET(iphdr, ttl); - IPH_PROTO_SET(iphdr, proto); -#if CHECKSUM_GEN_IP_INLINE - chk_sum += LWIP_MAKE_U16(proto, ttl); -#endif /* CHECKSUM_GEN_IP_INLINE */ - - /* dest cannot be NULL here */ - ip_addr_copy(iphdr->dest, *dest); -#if CHECKSUM_GEN_IP_INLINE - chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF; - chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16; -#endif /* CHECKSUM_GEN_IP_INLINE */ - - IPH_VHL_SET(iphdr, 4, ip_hlen / 4); - IPH_TOS_SET(iphdr, tos); -#if CHECKSUM_GEN_IP_INLINE - chk_sum += LWIP_MAKE_U16(tos, iphdr->_v_hl); -#endif /* CHECKSUM_GEN_IP_INLINE */ - IPH_LEN_SET(iphdr, htons(p->tot_len)); -#if CHECKSUM_GEN_IP_INLINE - chk_sum += iphdr->_len; -#endif /* CHECKSUM_GEN_IP_INLINE */ - IPH_OFFSET_SET(iphdr, 0); - IPH_ID_SET(iphdr, htons(ip_id)); -#if CHECKSUM_GEN_IP_INLINE - chk_sum += iphdr->_id; -#endif /* CHECKSUM_GEN_IP_INLINE */ - ++ip_id; - - if (ip_addr_isany(src)) { - ip_addr_copy(iphdr->src, netif->ip_addr); - } else { - /* src cannot be NULL here */ - ip_addr_copy(iphdr->src, *src); - } - -#if CHECKSUM_GEN_IP_INLINE - chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF; - chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16; - chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF); - chk_sum = (chk_sum >> 16) + chk_sum; - chk_sum = ~chk_sum; - iphdr->_chksum = chk_sum; /* network order */ -#else /* CHECKSUM_GEN_IP_INLINE */ - IPH_CHKSUM_SET(iphdr, 0); -#if CHECKSUM_GEN_IP - IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen)); -#endif -#endif /* CHECKSUM_GEN_IP_INLINE */ - } else { - /* IP header already included in p */ - iphdr = (struct ip_hdr *)p->payload; - ip_addr_copy(dest_addr, iphdr->dest); - dest = &dest_addr; - } - - IP_STATS_INC(ip.xmit); - - LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); - ip_debug_print(p); - -#if ENABLE_LOOPBACK - if (ip_addr_cmp(dest, &netif->ip_addr)) { - /* Packet to self, enqueue it for loopback */ - LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); - return netif_loop_output(netif, p, dest); - } -#if LWIP_IGMP - if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) { - netif_loop_output(netif, p, dest); - } -#endif /* LWIP_IGMP */ -#endif /* ENABLE_LOOPBACK */ -#if IP_FRAG - /* don't fragment if interface has mtu set to 0 [loopif] */ - if (netif->mtu && (p->tot_len > netif->mtu)) { - return ip_frag(p, netif, dest); - } -#endif /* IP_FRAG */ - - LWIP_DEBUGF(IP_DEBUG, ("netif->output()")); - return netif->output(netif, p, dest); -} - -/** - * Simple interface to ip_output_if. It finds the outgoing network - * interface and calls upon ip_output_if to do the actual work. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == IP_HDRINCL, p already includes an IP - header and p->payload points to that IP header) - * @param src the source IP address to send from (if src == IP_ADDR_ANY, the - * IP address of the netif used to send is used as source address) - * @param dest the destination IP address to send the packet to - * @param ttl the TTL value to be set in the IP header - * @param tos the TOS value to be set in the IP header - * @param proto the PROTOCOL to be set in the IP header - * - * @return ERR_RTE if no route is found - * see ip_output_if() for more return values - */ -err_t ICACHE_FLASH_ATTR -ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto) -{ - struct netif *netif; - - /* pbufs passed to IP must have a ref-count of 1 as their payload pointer - gets altered as the packet is passed down the stack */ - LWIP_ASSERT("p->ref == 1", p->ref == 1); - - if ((netif = ip_route(dest)) == NULL) { - LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); - IP_STATS_INC(ip.rterr); - return ERR_RTE; - } - - return ip_output_if(p, src, dest, ttl, tos, proto, netif); -} - -#if LWIP_NETIF_HWADDRHINT -/** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint - * before calling ip_output_if. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == IP_HDRINCL, p already includes an IP - header and p->payload points to that IP header) - * @param src the source IP address to send from (if src == IP_ADDR_ANY, the - * IP address of the netif used to send is used as source address) - * @param dest the destination IP address to send the packet to - * @param ttl the TTL value to be set in the IP header - * @param tos the TOS value to be set in the IP header - * @param proto the PROTOCOL to be set in the IP header - * @param addr_hint address hint pointer set to netif->addr_hint before - * calling ip_output_if() - * - * @return ERR_RTE if no route is found - * see ip_output_if() for more return values - */ -err_t ICACHE_FLASH_ATTR -ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) -{ - struct netif *netif; - err_t err; - - /* pbufs passed to IP must have a ref-count of 1 as their payload pointer - gets altered as the packet is passed down the stack */ - LWIP_ASSERT("p->ref == 1", p->ref == 1); - - if ((netif = ip_route(dest)) == NULL) { - LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); - IP_STATS_INC(ip.rterr); - return ERR_RTE; - } - - NETIF_SET_HWADDRHINT(netif, addr_hint); - err = ip_output_if(p, src, dest, ttl, tos, proto, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - - return err; -} -#endif /* LWIP_NETIF_HWADDRHINT*/ - -#if IP_DEBUG -/* Print an IP header by using LWIP_DEBUGF - * @param p an IP packet, p->payload pointing to the IP header - */ -void ICACHE_FLASH_ATTR -ip_debug_print(struct pbuf *p) -{ - struct ip_hdr *iphdr = (struct ip_hdr *)p->payload; - - LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n", - IPH_V(iphdr), - IPH_HL(iphdr), - IPH_TOS(iphdr), - ntohs(IPH_LEN(iphdr)))); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", - ntohs(IPH_ID(iphdr)), - ntohs(IPH_OFFSET(iphdr)) >> 15 & 1, - ntohs(IPH_OFFSET(iphdr)) >> 14 & 1, - ntohs(IPH_OFFSET(iphdr)) >> 13 & 1, - ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", - IPH_TTL(iphdr), - IPH_PROTO(iphdr), - ntohs(IPH_CHKSUM(iphdr)))); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", - ip4_addr1_16(&iphdr->src), - ip4_addr2_16(&iphdr->src), - ip4_addr3_16(&iphdr->src), - ip4_addr4_16(&iphdr->src))); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n", - ip4_addr1_16(&iphdr->dest), - ip4_addr2_16(&iphdr->dest), - ip4_addr3_16(&iphdr->dest), - ip4_addr4_16(&iphdr->dest))); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); -} -#endif /* IP_DEBUG */ diff --git a/third_party/lwip/core/ipv4/ip4_addr.c b/third_party/lwip/core/ipv4/ip4_addr.c deleted file mode 100644 index 64783ee..0000000 --- a/third_party/lwip/core/ipv4/ip4_addr.c +++ /dev/null @@ -1,313 +0,0 @@ -/** - * @file - * This is the IPv4 address tools implementation. - * - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" - -/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ -const ip_addr_t ip_addr_any = { IPADDR_ANY }; -const ip_addr_t ip_addr_broadcast = { IPADDR_BROADCAST }; - -/** - * Determine if an address is a broadcast address on a network interface - * - * @param addr address to be checked - * @param netif the network interface against which the address is checked - * @return returns non-zero if the address is a broadcast address - */ -u8_t ICACHE_FLASH_ATTR -ip4_addr_isbroadcast(u32_t addr, const struct netif *netif) -{ - ip_addr_t ipaddr; - ip4_addr_set_u32(&ipaddr, addr); - - /* all ones (broadcast) or all zeroes (old skool broadcast) */ - if ((~addr == IPADDR_ANY) || - (addr == IPADDR_ANY)) { - return 1; - /* no broadcast support on this network interface? */ - } else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) { - /* the given address cannot be a broadcast address - * nor can we check against any broadcast addresses */ - return 0; - /* address matches network interface address exactly? => no broadcast */ - } else if (addr == ip4_addr_get_u32(&netif->ip_addr)) { - return 0; - /* on the same (sub) network... */ - } else if (ip_addr_netcmp(&ipaddr, &(netif->ip_addr), &(netif->netmask)) - /* ...and host identifier bits are all ones? =>... */ - && ((addr & ~ip4_addr_get_u32(&netif->netmask)) == - (IPADDR_BROADCAST & ~ip4_addr_get_u32(&netif->netmask)))) { - /* => network broadcast address */ - return 1; - } else { - return 0; - } -} - -/** Checks if a netmask is valid (starting with ones, then only zeros) - * - * @param netmask the IPv4 netmask to check (in network byte order!) - * @return 1 if the netmask is valid, 0 if it is not - */ -u8_t ICACHE_FLASH_ATTR -ip4_addr_netmask_valid(u32_t netmask) -{ - u32_t mask; - u32_t nm_hostorder = lwip_htonl(netmask); - - /* first, check for the first zero */ - for (mask = 1UL << 31 ; mask != 0; mask >>= 1) { - if ((nm_hostorder & mask) == 0) { - break; - } - } - /* then check that there is no one */ - for (; mask != 0; mask >>= 1) { - if ((nm_hostorder & mask) != 0) { - /* there is a one after the first zero -> invalid */ - return 0; - } - } - /* no one after the first zero -> valid */ - return 1; -} - -/* Here for now until needed in other places in lwIP */ -#ifndef isprint -#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) -#define isprint(c) in_range(c, 0x20, 0x7f) -#define isdigit(c) in_range(c, '0', '9') -#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) -#define islower(c) in_range(c, 'a', 'z') -#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') -#endif - -/** - * Ascii internet address interpretation routine. - * The value returned is in network order. - * - * @param cp IP address in ascii represenation (e.g. "127.0.0.1") - * @return ip address in network order - */ -u32_t ICACHE_FLASH_ATTR -ipaddr_addr(const char *cp) -{ - ip_addr_t val; - - if (ipaddr_aton(cp, &val)) { - return ip4_addr_get_u32(&val); - } - return (IPADDR_NONE); -} - -/** - * Check whether "cp" is a valid ascii representation - * of an Internet address and convert to a binary address. - * Returns 1 if the address is valid, 0 if not. - * This replaces inet_addr, the return value from which - * cannot distinguish between failure and a local broadcast address. - * - * @param cp IP address in ascii represenation (e.g. "127.0.0.1") - * @param addr pointer to which to save the ip address in network order - * @return 1 if cp could be converted to addr, 0 on failure - */ -int ICACHE_FLASH_ATTR -ipaddr_aton(const char *cp, ip_addr_t *addr) -{ - u32_t val; - u8_t base; - char c; - u32_t parts[4]; - u32_t *pp = parts; - - c = *cp; - for (;;) { - /* - * Collect number up to ``.''. - * Values are specified as for C: - * 0x=hex, 0=octal, 1-9=decimal. - */ - if (!isdigit(c)) - return (0); - val = 0; - base = 10; - if (c == '0') { - c = *++cp; - if (c == 'x' || c == 'X') { - base = 16; - c = *++cp; - } else - base = 8; - } - for (;;) { - if (isdigit(c)) { - val = (val * base) + (int)(c - '0'); - c = *++cp; - } else if (base == 16 && isxdigit(c)) { - val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A')); - c = *++cp; - } else - break; - } - if (c == '.') { - /* - * Internet format: - * a.b.c.d - * a.b.c (with c treated as 16 bits) - * a.b (with b treated as 24 bits) - */ - if (pp >= parts + 3) { - return (0); - } - *pp++ = val; - c = *++cp; - } else - break; - } - /* - * Check for trailing characters. - */ - if (c != '\0' && !isspace(c)) { - return (0); - } - /* - * Concoct the address according to - * the number of parts specified. - */ - switch (pp - parts + 1) { - - case 0: - return (0); /* initial nondigit */ - - case 1: /* a -- 32 bits */ - break; - - case 2: /* a.b -- 8.24 bits */ - if (val > 0xffffffUL) { - return (0); - } - val |= parts[0] << 24; - break; - - case 3: /* a.b.c -- 8.8.16 bits */ - if (val > 0xffff) { - return (0); - } - val |= (parts[0] << 24) | (parts[1] << 16); - break; - - case 4: /* a.b.c.d -- 8.8.8.8 bits */ - if (val > 0xff) { - return (0); - } - val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); - break; - default: - LWIP_ASSERT("unhandled", 0); - break; - } - if (addr) { - ip4_addr_set_u32(addr, htonl(val)); - } - return (1); -} - -/** - * Convert numeric IP address into decimal dotted ASCII representation. - * returns ptr to static buffer; not reentrant! - * - * @param addr ip address in network order to convert - * @return pointer to a global static (!) buffer that holds the ASCII - * represenation of addr - */ -char * ICACHE_FLASH_ATTR -ipaddr_ntoa(const ip_addr_t *addr) -{ - static char str[16]; - return ipaddr_ntoa_r(addr, str, 16); -} - -/** - * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. - * - * @param addr ip address in network order to convert - * @param buf target buffer where the string is stored - * @param buflen length of buf - * @return either pointer to buf which now holds the ASCII - * representation of addr or NULL if buf was too small - */ -char * ICACHE_FLASH_ATTR -ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen) -{ - u32_t s_addr; - char inv[3]; - char *rp; - u8_t *ap; - u8_t rem; - u8_t n; - u8_t i; - int len = 0; - - s_addr = ip4_addr_get_u32(addr); - - rp = buf; - ap = (u8_t *)&s_addr; - for(n = 0; n < 4; n++) { - i = 0; - do { - rem = *ap % (u8_t)10; - *ap /= (u8_t)10; - inv[i++] = '0' + rem; - } while(*ap); - while(i--) { - if (len++ >= buflen) { - return NULL; - } - *rp++ = inv[i]; - } - if (len++ >= buflen) { - return NULL; - } - *rp++ = '.'; - ap++; - } - *--rp = 0; - return buf; -} diff --git a/third_party/lwip/core/ipv4/ip_frag.c b/third_party/lwip/core/ipv4/ip_frag.c deleted file mode 100644 index 8f14b4d..0000000 --- a/third_party/lwip/core/ipv4/ip_frag.c +++ /dev/null @@ -1,863 +0,0 @@ -/** - * @file - * This is the IPv4 packet segmentation and reassembly implementation. - * - */ - -/* - * 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: Jani Monoses - * Simon Goldschmidt - * original reassembly code by Adam Dunkels - * - */ - -#include "lwip/opt.h" -#include "lwip/ip_frag.h" -#include "lwip/def.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/snmp.h" -#include "lwip/stats.h" -#include "lwip/icmp.h" - -#include - -#if IP_REASSEMBLY -/** - * The IP reassembly code currently has the following limitations: - * - IP header options are not supported - * - fragments must not overlap (e.g. due to different routes), - * currently, overlapping or duplicate fragments are thrown away - * if IP_REASS_CHECK_OVERLAP=1 (the default)! - * - * @todo: work with IP header options - */ - -/** Setting this to 0, you can turn off checking the fragments for overlapping - * regions. The code gets a little smaller. Only use this if you know that - * overlapping won't occur on your network! */ -#ifndef IP_REASS_CHECK_OVERLAP -#define IP_REASS_CHECK_OVERLAP 1 -#endif /* IP_REASS_CHECK_OVERLAP */ - -/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is - * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. - * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA - * is set to 1, so one datagram can be reassembled at a time, only. */ -#ifndef IP_REASS_FREE_OLDEST -#define IP_REASS_FREE_OLDEST 1 -#endif /* IP_REASS_FREE_OLDEST */ - -#define IP_REASS_FLAG_LASTFRAG 0x01 - -/** This is a helper struct which holds the starting - * offset and the ending offset of this fragment to - * easily chain the fragments. - * It has the same packing requirements as the IP header, since it replaces - * the IP header in memory in incoming fragments (after copying it) to keep - * track of the various fragments. (-> If the IP header doesn't need packing, - * this struct doesn't need packing, too.) - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip_reass_helper { - PACK_STRUCT_FIELD(struct pbuf *next_pbuf); - PACK_STRUCT_FIELD(u16_t start); - PACK_STRUCT_FIELD(u16_t end); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \ - (ip_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \ - ip_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \ - IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0 - -/* global variables */ -static struct ip_reassdata *reassdatagrams; -static u16_t ip_reass_pbufcount; - -/* function prototypes */ -static void ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); -static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); - -/** - * Reassembly timer base function - * for both NO_SYS == 0 and 1 (!). - * - * Should be called every 1000 msec (defined by IP_TMR_INTERVAL). - */ -void ICACHE_FLASH_ATTR -ip_reass_tmr(void) -{ - struct ip_reassdata *r, *prev = NULL; - - r = reassdatagrams; - while (r != NULL) { - /* Decrement the timer. Once it reaches 0, - * clean up the incomplete fragment assembly */ - if (r->timer > 0) { - r->timer--; - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n",(u16_t)r->timer)); - prev = r; - r = r->next; - } else { - /* reassembly timed out */ - struct ip_reassdata *tmp; - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer timed out\n")); - tmp = r; - /* get the next pointer before freeing */ - r = r->next; - /* free the helper struct and all enqueued pbufs */ - ip_reass_free_complete_datagram(tmp, prev); - } - } -} - -/** - * Free a datagram (struct ip_reassdata) and all its pbufs. - * Updates the total count of enqueued pbufs (ip_reass_pbufcount), - * SNMP counters and sends an ICMP time exceeded packet. - * - * @param ipr datagram to free - * @param prev the previous datagram in the linked list - * @return the number of pbufs freed - */ -static int ICACHE_FLASH_ATTR -ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) -{ - u16_t pbufs_freed = 0; - u8_t clen; - struct pbuf *p; - struct ip_reass_helper *iprh; - - LWIP_ASSERT("prev != ipr", prev != ipr); - if (prev != NULL) { - LWIP_ASSERT("prev->next == ipr", prev->next == ipr); - } - - snmp_inc_ipreasmfails(); -#if LWIP_ICMP - iprh = (struct ip_reass_helper *)ipr->p->payload; - if (iprh->start == 0) { - /* The first fragment was received, send ICMP time exceeded. */ - /* First, de-queue the first pbuf from r->p. */ - p = ipr->p; - ipr->p = iprh->next_pbuf; - /* Then, copy the original header into it. */ - SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN); - icmp_time_exceeded(p, ICMP_TE_FRAG); - clen = pbuf_clen(p); - LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); - pbufs_freed += clen; - pbuf_free(p); - } -#endif /* LWIP_ICMP */ - - /* First, free all received pbufs. The individual pbufs need to be released - separately as they have not yet been chained */ - p = ipr->p; - while (p != NULL) { - struct pbuf *pcur; - iprh = (struct ip_reass_helper *)p->payload; - pcur = p; - /* get the next pointer before freeing */ - p = iprh->next_pbuf; - clen = pbuf_clen(pcur); - LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); - pbufs_freed += clen; - pbuf_free(pcur); - } - /* Then, unchain the struct ip_reassdata from the list and free it. */ - ip_reass_dequeue_datagram(ipr, prev); - LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= pbufs_freed); - ip_reass_pbufcount -= pbufs_freed; - - return pbufs_freed; -} - -#if IP_REASS_FREE_OLDEST -/** - * Free the oldest datagram to make room for enqueueing new fragments. - * The datagram 'fraghdr' belongs to is not freed! - * - * @param fraghdr IP header of the current fragment - * @param pbufs_needed number of pbufs needed to enqueue - * (used for freeing other datagrams if not enough space) - * @return the number of pbufs freed - */ -static int ICACHE_FLASH_ATTR -ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed) -{ - /* @todo Can't we simply remove the last datagram in the - * linked list behind reassdatagrams? - */ - struct ip_reassdata *r, *oldest, *prev; - int pbufs_freed = 0, pbufs_freed_current; - int other_datagrams; - - /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, - * but don't free the datagram that 'fraghdr' belongs to! */ - do { - oldest = NULL; - prev = NULL; - other_datagrams = 0; - r = reassdatagrams; - while (r != NULL) { - if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) { - /* Not the same datagram as fraghdr */ - other_datagrams++; - if (oldest == NULL) { - oldest = r; - } else if (r->timer <= oldest->timer) { - /* older than the previous oldest */ - oldest = r; - } - } - if (r->next != NULL) { - prev = r; - } - r = r->next; - } - if (oldest != NULL) { - pbufs_freed_current = ip_reass_free_complete_datagram(oldest, prev); - pbufs_freed += pbufs_freed_current; - } - } while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1)); - return pbufs_freed; -} -#endif /* IP_REASS_FREE_OLDEST */ - -/** - * Enqueues a new fragment into the fragment queue - * @param fraghdr points to the new fragments IP hdr - * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space) - * @return A pointer to the queue location into which the fragment was enqueued - */ -static struct ip_reassdata* ICACHE_FLASH_ATTR -ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen) -{ - struct ip_reassdata* ipr; - /* No matching previous fragment found, allocate a new reassdata struct */ - ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); - if (ipr == NULL) { -#if IP_REASS_FREE_OLDEST - if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) { - ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); - } - if (ipr == NULL) -#endif /* IP_REASS_FREE_OLDEST */ - { - IPFRAG_STATS_INC(ip_frag.memerr); - LWIP_DEBUGF(IP_REASS_DEBUG,("Failed to alloc reassdata struct\n")); - return NULL; - } - } - memset(ipr, 0, sizeof(struct ip_reassdata)); - ipr->timer = IP_REASS_MAXAGE; - - /* enqueue the new structure to the front of the list */ - ipr->next = reassdatagrams; - reassdatagrams = ipr; - /* copy the ip header for later tests and input */ - /* @todo: no ip options supported? */ - SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN); - return ipr; -} - -/** - * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs. - * @param ipr points to the queue entry to dequeue - */ -static void ICACHE_FLASH_ATTR -ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) -{ - - /* dequeue the reass struct */ - if (reassdatagrams == ipr) { - /* it was the first in the list */ - reassdatagrams = ipr->next; - } else { - /* it wasn't the first, so it must have a valid 'prev' */ - LWIP_ASSERT("sanity check linked list", prev != NULL); - prev->next = ipr->next; - } - - /* now we can free the ip_reass struct */ - memp_free(MEMP_REASSDATA, ipr); -} - -/** - * Chain a new pbuf into the pbuf list that composes the datagram. The pbuf list - * will grow over time as new pbufs are rx. - * Also checks that the datagram passes basic continuity checks (if the last - * fragment was received at least once). - * @param root_p points to the 'root' pbuf for the current datagram being assembled. - * @param new_p points to the pbuf for the current fragment - * @return 0 if invalid, >0 otherwise - */ -static int ICACHE_FLASH_ATTR -ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p) -{ - struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; - struct pbuf *q; - u16_t offset,len; - struct ip_hdr *fraghdr; - int valid = 1; - - /* Extract length and fragment offset from current fragment */ - fraghdr = (struct ip_hdr*)new_p->payload; - len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; - offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; - - /* overwrite the fragment's ip header from the pbuf with our helper struct, - * and setup the embedded helper structure. */ - /* make sure the struct ip_reass_helper fits into the IP header */ - LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN", - sizeof(struct ip_reass_helper) <= IP_HLEN); - iprh = (struct ip_reass_helper*)new_p->payload; - iprh->next_pbuf = NULL; - iprh->start = offset; - iprh->end = offset + len; - - /* Iterate through until we either get to the end of the list (append), - * or we find on with a larger offset (insert). */ - for (q = ipr->p; q != NULL;) { - iprh_tmp = (struct ip_reass_helper*)q->payload; - if (iprh->start < iprh_tmp->start) { - /* the new pbuf should be inserted before this */ - iprh->next_pbuf = q; - if (iprh_prev != NULL) { - /* not the fragment with the lowest offset */ -#if IP_REASS_CHECK_OVERLAP - if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) { - /* fragment overlaps with previous or following, throw away */ - goto freepbuf; - } -#endif /* IP_REASS_CHECK_OVERLAP */ - iprh_prev->next_pbuf = new_p; - } else { - /* fragment with the lowest offset */ - ipr->p = new_p; - } - break; - } else if(iprh->start == iprh_tmp->start) { - /* received the same datagram twice: no need to keep the datagram */ - goto freepbuf; -#if IP_REASS_CHECK_OVERLAP - } else if(iprh->start < iprh_tmp->end) { - /* overlap: no need to keep the new datagram */ - goto freepbuf; -#endif /* IP_REASS_CHECK_OVERLAP */ - } else { - /* Check if the fragments received so far have no wholes. */ - if (iprh_prev != NULL) { - if (iprh_prev->end != iprh_tmp->start) { - /* There is a fragment missing between the current - * and the previous fragment */ - valid = 0; - } - } - } - q = iprh_tmp->next_pbuf; - iprh_prev = iprh_tmp; - } - - /* If q is NULL, then we made it to the end of the list. Determine what to do now */ - if (q == NULL) { - if (iprh_prev != NULL) { - /* this is (for now), the fragment with the highest offset: - * chain it to the last fragment */ -#if IP_REASS_CHECK_OVERLAP - LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); -#endif /* IP_REASS_CHECK_OVERLAP */ - iprh_prev->next_pbuf = new_p; - if (iprh_prev->end != iprh->start) { - valid = 0; - } - } else { -#if IP_REASS_CHECK_OVERLAP - LWIP_ASSERT("no previous fragment, this must be the first fragment!", - ipr->p == NULL); -#endif /* IP_REASS_CHECK_OVERLAP */ - /* this is the first fragment we ever received for this ip datagram */ - ipr->p = new_p; - } - } - - /* At this point, the validation part begins: */ - /* If we already received the last fragment */ - if ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0) { - /* and had no wholes so far */ - if (valid) { - /* then check if the rest of the fragments is here */ - /* Check if the queue starts with the first datagram */ - if (((struct ip_reass_helper*)ipr->p->payload)->start != 0) { - valid = 0; - } else { - /* and check that there are no wholes after this datagram */ - iprh_prev = iprh; - q = iprh->next_pbuf; - while (q != NULL) { - iprh = (struct ip_reass_helper*)q->payload; - if (iprh_prev->end != iprh->start) { - valid = 0; - break; - } - iprh_prev = iprh; - q = iprh->next_pbuf; - } - /* if still valid, all fragments are received - * (because to the MF==0 already arrived */ - if (valid) { - LWIP_ASSERT("sanity check", ipr->p != NULL); - LWIP_ASSERT("sanity check", - ((struct ip_reass_helper*)ipr->p->payload) != iprh); - LWIP_ASSERT("validate_datagram:next_pbuf!=NULL", - iprh->next_pbuf == NULL); - LWIP_ASSERT("validate_datagram:datagram end!=datagram len", - iprh->end == ipr->datagram_len); - } - } - } - /* If valid is 0 here, there are some fragments missing in the middle - * (since MF == 0 has already arrived). Such datagrams simply time out if - * no more fragments are received... */ - return valid; - } - /* If we come here, not all fragments were received, yet! */ - return 0; /* not yet valid! */ -#if IP_REASS_CHECK_OVERLAP -freepbuf: - ip_reass_pbufcount -= pbuf_clen(new_p); - pbuf_free(new_p); - return 0; -#endif /* IP_REASS_CHECK_OVERLAP */ -} - -/** - * Reassembles incoming IP fragments into an IP datagram. - * - * @param p points to a pbuf chain of the fragment - * @return NULL if reassembly is incomplete, ? otherwise - */ -struct pbuf * ICACHE_FLASH_ATTR -ip_reass(struct pbuf *p) -{ - struct pbuf *r; - struct ip_hdr *fraghdr; - struct ip_reassdata *ipr; - struct ip_reass_helper *iprh; - u16_t offset, len; - u8_t clen; - struct ip_reassdata *ipr_prev = NULL; - - IPFRAG_STATS_INC(ip_frag.recv); - snmp_inc_ipreasmreqds(); - - fraghdr = (struct ip_hdr*)p->payload; - - if ((IPH_HL(fraghdr) * 4) != IP_HLEN) { - LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: IP options currently not supported!\n")); - IPFRAG_STATS_INC(ip_frag.err); - goto nullreturn; - } - - offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; - len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; - - /* Check if we are allowed to enqueue more datagrams. */ - clen = pbuf_clen(p); - if ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { -#if IP_REASS_FREE_OLDEST - if (!ip_reass_remove_oldest_datagram(fraghdr, clen) || - ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)) -#endif /* IP_REASS_FREE_OLDEST */ - { - /* No datagram could be freed and still too many pbufs enqueued */ - LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n", - ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS)); - IPFRAG_STATS_INC(ip_frag.memerr); - /* @todo: send ICMP time exceeded here? */ - /* drop this pbuf */ - goto nullreturn; - } - } - - /* Look for the datagram the fragment belongs to in the current datagram queue, - * remembering the previous in the queue for later dequeueing. */ - for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) { - /* Check if the incoming fragment matches the one currently present - in the reassembly buffer. If so, we proceed with copying the - fragment into the buffer. */ - if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) { - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching previous fragment ID=%"X16_F"\n", - ntohs(IPH_ID(fraghdr)))); - IPFRAG_STATS_INC(ip_frag.cachehit); - break; - } - ipr_prev = ipr; - } - - if (ipr == NULL) { - /* Enqueue a new datagram into the datagram queue */ - ipr = ip_reass_enqueue_new_datagram(fraghdr, clen); - /* Bail if unable to enqueue */ - if(ipr == NULL) { - goto nullreturn; - } - } else { - if (((ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && - ((ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { - /* ipr->iphdr is not the header from the first fragment, but fraghdr is - * -> copy fraghdr into ipr->iphdr since we want to have the header - * of the first fragment (for ICMP time exceeded and later, for copying - * all options, if supported)*/ - SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN); - } - } - /* Track the current number of pbufs current 'in-flight', in order to limit - the number of fragments that may be enqueued at any one time */ - ip_reass_pbufcount += clen; - - /* At this point, we have either created a new entry or pointing - * to an existing one */ - - /* check for 'no more fragments', and update queue entry*/ - if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) { - ipr->flags |= IP_REASS_FLAG_LASTFRAG; - ipr->datagram_len = offset + len; - LWIP_DEBUGF(IP_REASS_DEBUG, - ("ip_reass: last fragment seen, total len %"S16_F"\n", - ipr->datagram_len)); - } - /* find the right place to insert this pbuf */ - /* @todo: trim pbufs if fragments are overlapping */ - if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) { - /* the totally last fragment (flag more fragments = 0) was received at least - * once AND all fragments are received */ - ipr->datagram_len += IP_HLEN; - - /* save the second pbuf before copying the header over the pointer */ - r = ((struct ip_reass_helper*)ipr->p->payload)->next_pbuf; - - /* copy the original ip header back to the first pbuf */ - fraghdr = (struct ip_hdr*)(ipr->p->payload); - SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN); - IPH_LEN_SET(fraghdr, htons(ipr->datagram_len)); - IPH_OFFSET_SET(fraghdr, 0); - IPH_CHKSUM_SET(fraghdr, 0); - /* @todo: do we need to set calculate the correct checksum? */ - IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN)); - - p = ipr->p; - - /* chain together the pbufs contained within the reass_data list. */ - while(r != NULL) { - iprh = (struct ip_reass_helper*)r->payload; - - /* hide the ip header for every succeding fragment */ - pbuf_header(r, -IP_HLEN); - pbuf_cat(p, r); - r = iprh->next_pbuf; - } - /* release the sources allocate for the fragment queue entry */ - ip_reass_dequeue_datagram(ipr, ipr_prev); - - /* and adjust the number of pbufs currently queued for reassembly. */ - ip_reass_pbufcount -= pbuf_clen(p); - - /* Return the pbuf chain */ - return p; - } - /* the datagram is not (yet?) reassembled completely */ - LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass_pbufcount: %d out\n", ip_reass_pbufcount)); - return NULL; - -nullreturn: - LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: nullreturn\n")); - IPFRAG_STATS_INC(ip_frag.drop); - pbuf_free(p); - return NULL; -} -#endif /* IP_REASSEMBLY */ - -#if IP_FRAG -#if IP_FRAG_USES_STATIC_BUF -static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)]; -#else /* IP_FRAG_USES_STATIC_BUF */ - -#if !LWIP_NETIF_TX_SINGLE_PBUF -/** Allocate a new struct pbuf_custom_ref */ -static struct pbuf_custom_ref* ICACHE_FLASH_ATTR -ip_frag_alloc_pbuf_custom_ref(void) -{ - return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); -} - -/** Free a struct pbuf_custom_ref */ -static void ICACHE_FLASH_ATTR -ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) -{ - LWIP_ASSERT("p != NULL", p != NULL); - memp_free(MEMP_FRAG_PBUF, p); -} - -/** Free-callback function to free a 'struct pbuf_custom_ref', called by - * pbuf_free. */ -static void ICACHE_FLASH_ATTR -ipfrag_free_pbuf_custom(struct pbuf *p) -{ - struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; - LWIP_ASSERT("pcr != NULL", pcr != NULL); - LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); - if (pcr->original != NULL) { - pbuf_free(pcr->original); - } - ip_frag_free_pbuf_custom_ref(pcr); -} -#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ -#endif /* IP_FRAG_USES_STATIC_BUF */ - -/** - * Fragment an IP datagram if too large for the netif. - * - * Chop the datagram in MTU sized chunks and send them in order - * by using a fixed size static memory buffer (PBUF_REF) or - * point PBUF_REFs into p (depending on IP_FRAG_USES_STATIC_BUF). - * - * @param p ip packet to send - * @param netif the netif on which to send - * @param dest destination ip address to which to send - * - * @return ERR_OK if sent successfully, err_t otherwise - */ -err_t ICACHE_FLASH_ATTR -ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest) -{ - struct pbuf *rambuf; -#if IP_FRAG_USES_STATIC_BUF - struct pbuf *header; -#else -#if !LWIP_NETIF_TX_SINGLE_PBUF - struct pbuf *newpbuf; -#endif - struct ip_hdr *original_iphdr; -#endif - struct ip_hdr *iphdr; - u16_t nfb; - u16_t left, cop; - u16_t mtu = netif->mtu; - u16_t ofo, omf; - u16_t last; - u16_t poff = IP_HLEN; - u16_t tmp; -#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF - u16_t newpbuflen = 0; - u16_t left_to_copy; -#endif - - /* Get a RAM based MTU sized pbuf */ -#if IP_FRAG_USES_STATIC_BUF - /* When using a static buffer, we use a PBUF_REF, which we will - * use to reference the packet (without link header). - * Layer and length is irrelevant. - */ - rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF); - if (rambuf == NULL) { - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc(PBUF_LINK, 0, PBUF_REF) failed\n")); - return ERR_MEM; - } - rambuf->tot_len = rambuf->len = mtu; - rambuf->payload = LWIP_MEM_ALIGN((void *)buf); - - /* Copy the IP header in it */ - iphdr = (struct ip_hdr *)rambuf->payload; - SMEMCPY(iphdr, p->payload, IP_HLEN); -#else /* IP_FRAG_USES_STATIC_BUF */ - original_iphdr = (struct ip_hdr *)p->payload; - iphdr = original_iphdr; -#endif /* IP_FRAG_USES_STATIC_BUF */ - - /* Save original offset */ - tmp = ntohs(IPH_OFFSET(iphdr)); - ofo = tmp & IP_OFFMASK; - omf = tmp & IP_MF; - - left = p->tot_len - IP_HLEN; - - nfb = (mtu - IP_HLEN) / 8; - - while (left) { - last = (left <= mtu - IP_HLEN); - - /* Set new offset and MF flag */ - tmp = omf | (IP_OFFMASK & (ofo)); - if (!last) { - tmp = tmp | IP_MF; - } - - /* Fill this fragment */ - cop = last ? left : nfb * 8; - -#if IP_FRAG_USES_STATIC_BUF - poff += pbuf_copy_partial(p, (u8_t*)iphdr + IP_HLEN, cop, poff); -#else /* IP_FRAG_USES_STATIC_BUF */ -#if LWIP_NETIF_TX_SINGLE_PBUF - rambuf = pbuf_alloc(PBUF_IP, cop, PBUF_RAM); - if (rambuf == NULL) { - return ERR_MEM; - } - LWIP_ASSERT("this needs a pbuf in one piece!", - (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); - poff += pbuf_copy_partial(p, rambuf->payload, cop, poff); - /* make room for the IP header */ - if(pbuf_header(rambuf, IP_HLEN)) { - pbuf_free(rambuf); - return ERR_MEM; - } - /* fill in the IP header */ - SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); - iphdr = rambuf->payload; -#else /* LWIP_NETIF_TX_SINGLE_PBUF */ - /* When not using a static buffer, create a chain of pbufs. - * The first will be a PBUF_RAM holding the link and IP header. - * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, - * but limited to the size of an mtu. - */ - rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM); - if (rambuf == NULL) { - return ERR_MEM; - } - LWIP_ASSERT("this needs a pbuf in one piece!", - (p->len >= (IP_HLEN))); - SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); - iphdr = (struct ip_hdr *)rambuf->payload; - - /* Can just adjust p directly for needed offset. */ - p->payload = (u8_t *)p->payload + poff; - p->len -= poff; - - left_to_copy = cop; - while (left_to_copy) { - struct pbuf_custom_ref *pcr; - newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; - /* Is this pbuf already empty? */ - if (!newpbuflen) { - p = p->next; - continue; - } - pcr = ip_frag_alloc_pbuf_custom_ref(); - if (pcr == NULL) { - pbuf_free(rambuf); - return ERR_MEM; - } - /* Mirror this pbuf, although we might not need all of it. */ - newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); - if (newpbuf == NULL) { - ip_frag_free_pbuf_custom_ref(pcr); - pbuf_free(rambuf); - return ERR_MEM; - } - pbuf_ref(p); - pcr->original = p; - pcr->pc.custom_free_function = ipfrag_free_pbuf_custom; - - /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain - * so that it is removed when pbuf_dechain is later called on rambuf. - */ - pbuf_cat(rambuf, newpbuf); - left_to_copy -= newpbuflen; - if (left_to_copy) { - p = p->next; - } - } - poff = newpbuflen; -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ -#endif /* IP_FRAG_USES_STATIC_BUF */ - - /* Correct header */ - IPH_OFFSET_SET(iphdr, htons(tmp)); - IPH_LEN_SET(iphdr, htons(cop + IP_HLEN)); - IPH_CHKSUM_SET(iphdr, 0); - IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); - -#if IP_FRAG_USES_STATIC_BUF - if (last) { - pbuf_realloc(rambuf, left + IP_HLEN); - } - - /* This part is ugly: we alloc a RAM based pbuf for - * the link level header for each chunk and then - * free it.A PBUF_ROM style pbuf for which pbuf_header - * worked would make things simpler. - */ - header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM); - if (header != NULL) { - pbuf_chain(header, rambuf); - netif->output(netif, header, dest); - IPFRAG_STATS_INC(ip_frag.xmit); - snmp_inc_ipfragcreates(); - pbuf_free(header); - } else { - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc() for header failed\n")); - pbuf_free(rambuf); - return ERR_MEM; - } -#else /* IP_FRAG_USES_STATIC_BUF */ - /* No need for separate header pbuf - we allowed room for it in rambuf - * when allocated. - */ - netif->output(netif, rambuf, dest); - IPFRAG_STATS_INC(ip_frag.xmit); - - /* Unfortunately we can't reuse rambuf - the hardware may still be - * using the buffer. Instead we free it (and the ensuing chain) and - * recreate it next time round the loop. If we're lucky the hardware - * will have already sent the packet, the free will really free, and - * there will be zero memory penalty. - */ - - pbuf_free(rambuf); -#endif /* IP_FRAG_USES_STATIC_BUF */ - left -= cop; - ofo += nfb; - } -#if IP_FRAG_USES_STATIC_BUF - pbuf_free(rambuf); -#endif /* IP_FRAG_USES_STATIC_BUF */ - snmp_inc_ipfragoks(); - return ERR_OK; -} -#endif /* IP_FRAG */ diff --git a/third_party/lwip/core/ipv6/README b/third_party/lwip/core/ipv6/README deleted file mode 100644 index a59caef..0000000 --- a/third_party/lwip/core/ipv6/README +++ /dev/null @@ -1 +0,0 @@ -IPv6 support in lwIP is very experimental. diff --git a/third_party/lwip/core/ipv6/dhcp6.c b/third_party/lwip/core/ipv6/dhcp6.c deleted file mode 100644 index bb0d574..0000000 --- a/third_party/lwip/core/ipv6/dhcp6.c +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @file - * - * DHCPv6. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * 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: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/ip6_addr.h" -#include "lwip/def.h" - - -#endif /* LWIP_IPV6_DHCP6 */ diff --git a/third_party/lwip/core/ipv6/ethip6.c b/third_party/lwip/core/ipv6/ethip6.c deleted file mode 100644 index bde2334..0000000 --- a/third_party/lwip/core/ipv6/ethip6.c +++ /dev/null @@ -1,193 +0,0 @@ -/** - * @file - * - * Ethernet output for IPv6. Uses ND tables for link-layer addressing. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * 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: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 && LWIP_ETHERNET - -#include "lwip/ethip6.h" -#include "lwip/nd6.h" -#include "lwip/pbuf.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/icmp6.h" - -#include - -#define ETHTYPE_IPV6 0x86DD - -/** The ethernet address */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct eth_addr { - PACK_STRUCT_FIELD(u8_t addr[6]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Ethernet header */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct eth_hdr { -#if ETH_PAD_SIZE - PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]); -#endif - PACK_STRUCT_FIELD(struct eth_addr dest); - PACK_STRUCT_FIELD(struct eth_addr src); - PACK_STRUCT_FIELD(u16_t type); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE) - -/** - * Send an IPv6 packet on the network using netif->linkoutput - * The ethernet header is filled in before sending. - * - * @params netif the lwIP network interface on which to send the packet - * @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header - * @params src the source MAC address to be copied into the ethernet header - * @params dst the destination MAC address to be copied into the ethernet header - * @return ERR_OK if the packet was sent, any other err_t on failure - */ -static err_t -ethip6_send(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst) -{ - struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload; - - LWIP_ASSERT("netif->hwaddr_len must be 6 for ethip6!", - (netif->hwaddr_len == 6)); - SMEMCPY(ðhdr->dest, dst, 6); - SMEMCPY(ðhdr->src, src, 6); - ethhdr->type = PP_HTONS(ETHTYPE_IPV6); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("ethip6_send: sending packet %p\n", (void *)p)); - /* send the packet */ - return netif->linkoutput(netif, p); -} - -/** - * Resolve and fill-in Ethernet address header for outgoing IPv6 packet. - * - * For IPv6 multicast, corresponding Ethernet addresses - * are selected and the packet is transmitted on the link. - * - * For unicast addresses, ... - * - * @TODO anycast addresses - * - * @param netif The lwIP network interface which the IP packet will be sent on. - * @param q The pbuf(s) containing the IP packet to be sent. - * @param ip6addr The IP address of the packet destination. - * - * @return - * - ERR_RTE No route to destination (no gateway to external networks), - * or the return type of either etharp_query() or etharp_send_ip(). - */ -err_t -ethip6_output(struct netif *netif, struct pbuf *q, ip6_addr_t *ip6addr) -{ - struct eth_addr dest; - s8_t i; - - /* make room for Ethernet header - should not fail */ - if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { - /* bail out */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("etharp_output: could not allocate room for header.\n")); - return ERR_BUF; - } - - /* multicast destination IP address? */ - if (ip6_addr_ismulticast(ip6addr)) { - /* Hash IP multicast address to MAC address.*/ - dest.addr[0] = 0x33; - dest.addr[1] = 0x33; - dest.addr[2] = ((u8_t *)(&(ip6addr->addr[3])))[0]; - dest.addr[3] = ((u8_t *)(&(ip6addr->addr[3])))[1]; - dest.addr[4] = ((u8_t *)(&(ip6addr->addr[3])))[2]; - dest.addr[5] = ((u8_t *)(&(ip6addr->addr[3])))[3]; - - /* Send out. */ - return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest); - } - - /* We have a unicast destination IP address */ - /* TODO anycast? */ - /* Get next hop record. */ - i = nd6_get_next_hop_entry(ip6addr, netif); - if (i < 0) { - /* failed to get a next hop neighbor record. */ - return ERR_MEM; - } - - /* Now that we have a destination record, send or queue the packet. */ - if (neighbor_cache[i].state == ND6_STALE) { - /* Switch to delay state. */ - neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; - } - /* TODO should we send or queue if PROBE? send for now, to let unicast NS pass. */ - if ((neighbor_cache[i].state == ND6_REACHABLE) || - (neighbor_cache[i].state == ND6_DELAY) || - (neighbor_cache[i].state == ND6_PROBE)) { - - /* Send out. */ - SMEMCPY(dest.addr, neighbor_cache[i].lladdr, 6); - return ethip6_send(netif, q, (struct eth_addr*)(netif->hwaddr), &dest); - } - - /* We should queue packet on this interface. */ - pbuf_header(q, -(s16_t)SIZEOF_ETH_HDR); - return nd6_queue_packet(i, q); -} - -#endif /* LWIP_IPV6 && LWIP_ETHERNET */ diff --git a/third_party/lwip/core/ipv6/icmp6.c b/third_party/lwip/core/ipv6/icmp6.c deleted file mode 100644 index f876804..0000000 --- a/third_party/lwip/core/ipv6/icmp6.c +++ /dev/null @@ -1,338 +0,0 @@ -/** - * @file - * - * IPv6 version of ICMP, as per RFC 4443. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * 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: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/icmp6.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" -#include "lwip/pbuf.h" -#include "lwip/netif.h" -#include "lwip/nd6.h" -#include "lwip/mld6.h" -#include "lwip/ip.h" -#include "lwip/stats.h" - -#include - -#ifndef LWIP_ICMP6_DATASIZE -#define LWIP_ICMP6_DATASIZE 8 -#endif -#if LWIP_ICMP6_DATASIZE == 0 -#define LWIP_ICMP6_DATASIZE 8 -#endif - -/* Forward declarations */ -static void icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type); - - -/** - * Process an input ICMPv6 message. Called by ip6_input. - * - * Will generate a reply for echo requests. Other messages are forwarded - * to nd6_input, or mld6_input. - * - * @param p the mld packet, p->payload pointing to the icmpv6 header - * @param inp the netif on which this packet was received - */ -void -icmp6_input(struct pbuf *p, struct netif *inp) -{ - struct icmp6_hdr *icmp6hdr; - struct pbuf * r; - ip6_addr_t * reply_src; - - ICMP6_STATS_INC(icmp6.recv); - - /* Check that ICMPv6 header fits in payload */ - if (p->len < sizeof(struct icmp6_hdr)) { - /* drop short packets */ - pbuf_free(p); - ICMP6_STATS_INC(icmp6.lenerr); - ICMP6_STATS_INC(icmp6.drop); - return; - } - - icmp6hdr = (struct icmp6_hdr *)p->payload; - -#if LWIP_ICMP6_CHECKSUM_CHECK - if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(), - ip6_current_dest_addr()) != 0) { - /* Checksum failed */ - pbuf_free(p); - ICMP6_STATS_INC(icmp6.chkerr); - ICMP6_STATS_INC(icmp6.drop); - return; - } -#endif /* LWIP_ICMP6_CHECKSUM_CHECK */ - - switch (icmp6hdr->type) { - case ICMP6_TYPE_NA: /* Neighbor advertisement */ - case ICMP6_TYPE_NS: /* Neighbor solicitation */ - case ICMP6_TYPE_RA: /* Router advertisement */ - case ICMP6_TYPE_RD: /* Redirect */ - case ICMP6_TYPE_PTB: /* Packet too big */ - nd6_input(p, inp); - return; - break; - case ICMP6_TYPE_RS: -#if LWIP_IPV6_FORWARD - /* TODO implement router functionality */ -#endif - break; -#if LWIP_IPV6_MLD - case ICMP6_TYPE_MLQ: - case ICMP6_TYPE_MLR: - case ICMP6_TYPE_MLD: - mld6_input(p, inp); - return; - break; -#endif - case ICMP6_TYPE_EREQ: -#if !LWIP_MULTICAST_PING - /* multicast destination address? */ - if (ip6_addr_ismulticast(ip6_current_dest_addr())) { - /* drop */ - pbuf_free(p); - ICMP6_STATS_INC(icmp6.drop); - return; - } -#endif /* LWIP_MULTICAST_PING */ - - /* Allocate reply. */ - r = pbuf_alloc(PBUF_IP, p->tot_len, PBUF_RAM); - if (r == NULL) { - /* drop */ - pbuf_free(p); - ICMP6_STATS_INC(icmp6.memerr); - return; - } - - /* Copy echo request. */ - if (pbuf_copy(r, p) != ERR_OK) { - /* drop */ - pbuf_free(p); - pbuf_free(r); - ICMP6_STATS_INC(icmp6.err); - return; - } - - /* Determine reply source IPv6 address. */ -#if LWIP_MULTICAST_PING - if (ip6_addr_ismulticast(ip6_current_dest_addr())) { - reply_src = ip6_select_source_address(inp, ip6_current_src_addr()); - if (reply_src == NULL) { - /* drop */ - pbuf_free(p); - pbuf_free(r); - ICMP6_STATS_INC(icmp6.rterr); - return; - } - } - else -#endif /* LWIP_MULTICAST_PING */ - { - reply_src = ip6_current_dest_addr(); - } - - /* Set fields in reply. */ - ((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP; - ((struct icmp6_echo_hdr *)(r->payload))->chksum = 0; - ((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r, - IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr()); - - /* Send reply. */ - ICMP6_STATS_INC(icmp6.xmit); - ip6_output_if(r, reply_src, ip6_current_src_addr(), - LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, inp); - pbuf_free(r); - - break; - default: - ICMP6_STATS_INC(icmp6.proterr); - ICMP6_STATS_INC(icmp6.drop); - break; - } - - pbuf_free(p); -} - - -/** - * Send an icmpv6 'destination unreachable' packet. - * - * @param p the input packet for which the 'unreachable' should be sent, - * p->payload pointing to the IPv6 header - * @param c ICMPv6 code for the unreachable type - */ -void -icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c) -{ - icmp6_send_response(p, c, 0, ICMP6_TYPE_DUR); -} - -/** - * Send an icmpv6 'packet too big' packet. - * - * @param p the input packet for which the 'packet too big' should be sent, - * p->payload pointing to the IPv6 header - * @param mtu the maximum mtu that we can accept - */ -void -icmp6_packet_too_big(struct pbuf *p, u32_t mtu) -{ - icmp6_send_response(p, 0, mtu, ICMP6_TYPE_PTB); -} - -/** - * Send an icmpv6 'time exceeded' packet. - * - * @param p the input packet for which the 'unreachable' should be sent, - * p->payload pointing to the IPv6 header - * @param c ICMPv6 code for the time exceeded type - */ -void -icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c) -{ - icmp6_send_response(p, c, 0, ICMP6_TYPE_TE); -} - -/** - * Send an icmpv6 'parameter problem' packet. - * - * @param p the input packet for which the 'param problem' should be sent, - * p->payload pointing to the IP header - * @param c ICMPv6 code for the param problem type - * @param pointer the pointer to the byte where the parameter is found - */ -void -icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer) -{ - icmp6_send_response(p, c, pointer, ICMP6_TYPE_PP); -} - -/** - * Send an ICMPv6 packet in response to an incoming packet. - * - * @param p the input packet for which the response should be sent, - * p->payload pointing to the IPv6 header - * @param code Code of the ICMPv6 header - * @param data Additional 32-bit parameter in the ICMPv6 header - * @param type Type of the ICMPv6 header - */ -static void -icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type) -{ - struct pbuf *q; - struct icmp6_hdr *icmp6hdr; - ip6_addr_t *reply_src, *reply_dest; - ip6_addr_t reply_src_local, reply_dest_local; - struct ip6_hdr *ip6hdr; - struct netif *netif; - - /* ICMPv6 header + IPv6 header + data */ - q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, - PBUF_RAM); - if (q == NULL) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n")); - ICMP6_STATS_INC(icmp6.memerr); - return; - } - LWIP_ASSERT("check that first pbuf can hold icmp 6message", - (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); - - icmp6hdr = (struct icmp6_hdr *)q->payload; - icmp6hdr->type = type; - icmp6hdr->code = code; - icmp6hdr->data = data; - - /* copy fields from original packet */ - SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload, - IP6_HLEN + LWIP_ICMP6_DATASIZE); - - /* Get the destination address and netif for this ICMP message. */ - if ((ip_current_netif() == NULL) || - ((code == ICMP6_TE_FRAG) && (type == ICMP6_TYPE_TE))) { - /* Special case, as ip6_current_xxx is either NULL, or points - * to a different packet than the one that expired. - * We must use the addresses that are stored in the expired packet. */ - ip6hdr = (struct ip6_hdr *)p->payload; - /* copy from packed address to aligned address */ - ip6_addr_copy(reply_dest_local, ip6hdr->src); - ip6_addr_copy(reply_src_local, ip6hdr->dest); - reply_dest = &reply_dest_local; - reply_src = &reply_src_local; - netif = ip6_route(reply_src, reply_dest); - if (netif == NULL) { - /* drop */ - pbuf_free(q); - ICMP6_STATS_INC(icmp6.rterr); - return; - } - } - else { - netif = ip_current_netif(); - reply_dest = ip6_current_src_addr(); - - /* Select an address to use as source. */ - reply_src = ip6_select_source_address(netif, reply_dest); - if (reply_src == NULL) { - /* drop */ - pbuf_free(q); - ICMP6_STATS_INC(icmp6.rterr); - return; - } - } - - /* calculate checksum */ - icmp6hdr->chksum = 0; - icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len, - reply_src, reply_dest); - - ICMP6_STATS_INC(icmp6.xmit); - ip6_output_if(q, reply_src, reply_dest, LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); - pbuf_free(q); -} - -#endif /* LWIP_ICMP6 && LWIP_IPV6 */ diff --git a/third_party/lwip/core/ipv6/inet6.c b/third_party/lwip/core/ipv6/inet6.c deleted file mode 100644 index bd44208..0000000 --- a/third_party/lwip/core/ipv6/inet6.c +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @file - * - * INET v6 addresses. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * 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: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/inet6.h" - -/** @see ip6_addr.c for implementation of functions. */ - -#endif /* LWIP_IPV6 */ diff --git a/third_party/lwip/core/ipv6/ip6.c b/third_party/lwip/core/ipv6/ip6.c deleted file mode 100644 index 4affcfd..0000000 --- a/third_party/lwip/core/ipv6/ip6.c +++ /dev/null @@ -1,1028 +0,0 @@ -/** - * @file - * - * IPv6 layer. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * 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: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - - -#include "lwip/opt.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/netif.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/ip6_frag.h" -#include "lwip/icmp6.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/tcp_impl.h" -#include "lwip/dhcp6.h" -#include "lwip/nd6.h" -#include "lwip/mld6.h" -#include "lwip/debug.h" -#include "lwip/stats.h" - - -/** - * Finds the appropriate network interface for a given IPv6 address. It tries to select - * a netif following a sequence of heuristics: - * 1) if there is only 1 netif, return it - * 2) if the destination is a link-local address, try to match the src address to a netif. - * this is a tricky case because with multiple netifs, link-local addresses only have - * meaning within a particular subnet/link. - * 3) tries to match the destination subnet to a configured address - * 4) tries to find a router - * 5) tries to match the source address to the netif - * 6) returns the default netif, if configured - * - * @param src the source IPv6 address, if known - * @param dest the destination IPv6 address for which to find the route - * @return the netif on which to send to reach dest - */ -struct netif * -ip6_route(struct ip6_addr *src, struct ip6_addr *dest) -{ - struct netif *netif; - s8_t i; - - /* If single netif configuration, fast return. */ - if ((netif_list != NULL) && (netif_list->next == NULL)) { - return netif_list; - } - - /* Special processing for link-local addresses. */ - if (ip6_addr_islinklocal(dest)) { - if (ip6_addr_isany(src)) { - /* Use default netif. */ - return netif_default; - } - - /* Try to find the netif for the source address. */ - for(netif = netif_list; netif != NULL; netif = netif->next) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { - return netif; - } - } - } - - /* netif not found, use default netif */ - return netif_default; - } - - /* See if the destination subnet matches a configured address. */ - for(netif = netif_list; netif != NULL; netif = netif->next) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { - return netif; - } - } - } - - /* Get the netif for a suitable router. */ - i = nd6_select_router(dest, NULL); - if (i >= 0) { - if (default_router_list[i].neighbor_entry != NULL) { - if (default_router_list[i].neighbor_entry->netif != NULL) { - return default_router_list[i].neighbor_entry->netif; - } - } - } - - /* try with the netif that matches the source address. */ - if (!ip6_addr_isany(src)) { - for(netif = netif_list; netif != NULL; netif = netif->next) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { - return netif; - } - } - } - } - - /* no matching netif found, use default netif */ - return netif_default; -} - -/** - * Select the best IPv6 source address for a given destination - * IPv6 address. Loosely follows RFC 3484. "Strong host" behavior - * is assumed. - * - * @param netif the netif on which to send a packet - * @param dest the destination we are trying to reach - * @return the most suitable source address to use, or NULL if no suitable - * source address is found - */ -ip6_addr_t * -ip6_select_source_address(struct netif *netif, ip6_addr_t * dest) -{ - ip6_addr_t * src = NULL; - u8_t i; - - /* If dest is link-local, choose a link-local source. */ - if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_linklocal(dest) || ip6_addr_ismulticast_iflocal(dest)) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_islinklocal(netif_ip6_addr(netif, i))) { - return netif_ip6_addr(netif, i); - } - } - } - - /* Choose a site-local with matching prefix. */ - if (ip6_addr_issitelocal(dest) || ip6_addr_ismulticast_sitelocal(dest)) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_issitelocal(netif_ip6_addr(netif, i)) && - ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { - return netif_ip6_addr(netif, i); - } - } - } - - /* Choose a unique-local with matching prefix. */ - if (ip6_addr_isuniquelocal(dest) || ip6_addr_ismulticast_orglocal(dest)) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)) && - ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { - return netif_ip6_addr(netif, i); - } - } - } - - /* Choose a global with best matching prefix. */ - if (ip6_addr_isglobal(dest) || ip6_addr_ismulticast_global(dest)) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_isglobal(netif_ip6_addr(netif, i))) { - if (src == NULL) { - src = netif_ip6_addr(netif, i); - } - else { - /* Replace src only if we find a prefix match. */ - /* TODO find longest matching prefix. */ - if ((!(ip6_addr_netcmp(src, dest))) && - ip6_addr_netcmp(netif_ip6_addr(netif, i), dest)) { - src = netif_ip6_addr(netif, i); - } - } - } - } - if (src != NULL) { - return src; - } - } - - /* Last resort: see if arbitrary prefix matches. */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { - return netif_ip6_addr(netif, i); - } - } - - return NULL; -} - -#if LWIP_IPV6_FORWARD -/** - * Forwards an IPv6 packet. It finds an appropriate route for the - * packet, decrements the HL value of the packet, and outputs - * the packet on the appropriate interface. - * - * @param p the packet to forward (p->payload points to IP header) - * @param iphdr the IPv6 header of the input packet - * @param inp the netif on which this packet was received - */ -static void -ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp) -{ - struct netif *netif; - - /* do not forward link-local addresses */ - if (ip6_addr_islinklocal(ip6_current_dest_addr())) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n")); - IP6_STATS_INC(ip6.rterr); - IP6_STATS_INC(ip6.drop); - return; - } - - /* Find network interface where to forward this IP packet to. */ - netif = ip6_route(IP6_ADDR_ANY, ip6_current_dest_addr()); - if (netif == NULL) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", - IP6_ADDR_BLOCK1(ip6_current_dest_addr()), - IP6_ADDR_BLOCK2(ip6_current_dest_addr()), - IP6_ADDR_BLOCK3(ip6_current_dest_addr()), - IP6_ADDR_BLOCK4(ip6_current_dest_addr()), - IP6_ADDR_BLOCK5(ip6_current_dest_addr()), - IP6_ADDR_BLOCK6(ip6_current_dest_addr()), - IP6_ADDR_BLOCK7(ip6_current_dest_addr()), - IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); -#if LWIP_ICMP6 - /* Don't send ICMP messages in response to ICMP messages */ - if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { - icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE); - } -#endif /* LWIP_ICMP6 */ - IP6_STATS_INC(ip6.rterr); - IP6_STATS_INC(ip6.drop); - return; - } - /* Do not forward packets onto the same network interface on which - * they arrived. */ - if (netif == inp) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n")); - IP6_STATS_INC(ip6.rterr); - IP6_STATS_INC(ip6.drop); - return; - } - - /* decrement HL */ - IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1); - /* send ICMP6 if HL == 0 */ - if (IP6H_HOPLIM(iphdr) == 0) { -#if LWIP_ICMP6 - /* Don't send ICMP messages in response to ICMP messages */ - if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { - icmp6_time_exceeded(p, ICMP6_TE_HL); - } -#endif /* LWIP_ICMP6 */ - IP6_STATS_INC(ip6.drop); - return; - } - - if (netif->mtu && (p->tot_len > netif->mtu)) { -#if LWIP_ICMP6 - /* Don't send ICMP messages in response to ICMP messages */ - if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { - icmp6_packet_too_big(p, netif->mtu); - } -#endif /* LWIP_ICMP6 */ - IP6_STATS_INC(ip6.drop); - return; - } - - LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: forwarding packet to %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", - IP6_ADDR_BLOCK1(ip6_current_dest_addr()), - IP6_ADDR_BLOCK2(ip6_current_dest_addr()), - IP6_ADDR_BLOCK3(ip6_current_dest_addr()), - IP6_ADDR_BLOCK4(ip6_current_dest_addr()), - IP6_ADDR_BLOCK5(ip6_current_dest_addr()), - IP6_ADDR_BLOCK6(ip6_current_dest_addr()), - IP6_ADDR_BLOCK7(ip6_current_dest_addr()), - IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); - - /* transmit pbuf on chosen interface */ - netif->output_ip6(netif, p, ip6_current_dest_addr()); - IP6_STATS_INC(ip6.fw); - IP6_STATS_INC(ip6.xmit); - return; -} -#endif /* LWIP_IPV6_FORWARD */ - - -/** - * This function is called by the network interface device driver when - * an IPv6 packet is received. The function does the basic checks of the - * IP header such as packet size being at least larger than the header - * size etc. If the packet was not destined for us, the packet is - * forwarded (using ip6_forward). - * - * Finally, the packet is sent to the upper layer protocol input function. - * - * @param p the received IPv6 packet (p->payload points to IPv6 header) - * @param inp the netif on which this packet was received - * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't - * processed, but currently always returns ERR_OK) - */ -err_t -ip6_input(struct pbuf *p, struct netif *inp) -{ - struct ip6_hdr *ip6hdr; - struct netif *netif; - u8_t nexth; - u16_t hlen; /* the current header length */ - u8_t i; -#if 0 /*IP_ACCEPT_LINK_LAYER_ADDRESSING*/ - @todo - int check_ip_src=1; -#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ - - IP6_STATS_INC(ip6.recv); - - /* identify the IP header */ - ip6hdr = (struct ip6_hdr *)p->payload; - if (IP6H_V(ip6hdr) != 6) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n", - IP6H_V(ip6hdr))); - pbuf_free(p); - IP6_STATS_INC(ip6.err); - IP6_STATS_INC(ip6.drop); - return ERR_OK; - } - - /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ - if ((IP6_HLEN > p->len) || ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len)) { - if (IP6_HLEN > p->len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", - IP6_HLEN, p->len)); - } - if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", - IP6H_PLEN(ip6hdr) + IP6_HLEN, p->tot_len)); - } - /* free (drop) packet pbufs */ - pbuf_free(p); - IP6_STATS_INC(ip6.lenerr); - IP6_STATS_INC(ip6.drop); - return ERR_OK; - } - - /* Trim pbuf. This should have been done at the netif layer, - * but we'll do it anyway just to be sure that its done. */ - pbuf_realloc(p, IP6_HLEN + IP6H_PLEN(ip6hdr)); - - /* copy IP addresses to aligned ip6_addr_t */ - ip6_addr_copy(ip_data.current_iphdr_dest.ip6, ip6hdr->dest); - ip6_addr_copy(ip_data.current_iphdr_src.ip6, ip6hdr->src); - - /* current header pointer. */ - ip_data.current_ip6_header = ip6hdr; - - /* In netif, used in case we need to send ICMPv6 packets back. */ - ip_data.current_netif = inp; - - /* match packet against an interface, i.e. is this packet for us? */ - if (ip6_addr_ismulticast(ip6_current_dest_addr())) { - /* Always joined to multicast if-local and link-local all-nodes group. */ - if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) || - ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())) { - netif = inp; - } -#if LWIP_IPV6_MLD - else if (mld6_lookfor_group(inp, ip6_current_dest_addr())) { - netif = inp; - } -#else /* LWIP_IPV6_MLD */ - else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) { - /* Filter solicited node packets when MLD is not enabled - * (for Neighbor discovery). */ - netif = NULL; - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) && - ip6_addr_cmp_solicitednode(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { - netif = inp; - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n", - netif->name[0], netif->name[1])); - break; - } - } - } -#endif /* LWIP_IPV6_MLD */ - else { - netif = NULL; - } - } - else { - /* start trying with inp. if that's not acceptable, start walking the - list of configured netifs. - 'first' is used as a boolean to mark whether we started walking the list */ - int first = 1; - netif = inp; - do { - /* interface is up? */ - if (netif_is_up(netif)) { - /* unicast to this interface address? address configured? */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i))) { - /* exit outer loop */ - goto netif_found; - } - } - } - if (ip6_addr_islinklocal(ip6_current_dest_addr())) { - /* Do not match link-local addresses to other netifs. */ - netif = NULL; - break; - } - if (first) { - first = 0; - netif = netif_list; - } else { - netif = netif->next; - } - if (netif == inp) { - netif = netif->next; - } - } while(netif != NULL); -netif_found: - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n", - netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X')); - } - - /* "::" packet source address? (used in duplicate address detection) */ - if (ip6_addr_isany(ip6_current_src_addr()) && - (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) { - /* packet source is not valid */ - /* free (drop) packet pbufs */ - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n")); - pbuf_free(p); - IP6_STATS_INC(ip6.drop); - goto ip6_input_cleanup; - } - - /* packet not for us? */ - if (netif == NULL) { - /* packet not for us, route or discard */ - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n")); -#if LWIP_IPV6_FORWARD - /* non-multicast packet? */ - if (!ip6_addr_ismulticast(ip6_current_dest_addr())) { - /* try to forward IP packet on (other) interfaces */ - ip6_forward(p, ip6hdr, inp); - } -#endif /* LWIP_IPV6_FORWARD */ - pbuf_free(p); - goto ip6_input_cleanup; - } - - /* current netif pointer. */ - ip_data.current_netif = netif; - - /* Save next header type. */ - nexth = IP6H_NEXTH(ip6hdr); - - /* Init header length. */ - hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; - - /* Move to payload. */ - pbuf_header(p, -IP6_HLEN); - - /* Process known option extension headers, if present. */ - while (nexth != IP6_NEXTH_NONE) - { - switch (nexth) { - case IP6_NEXTH_HOPBYHOP: - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n")); - /* Get next header type. */ - nexth = *((u8_t *)p->payload); - - /* Get the header length. */ - hlen = 8 * (1 + *((u8_t *)p->payload + 1)); - ip_data.current_ip_header_tot_len += hlen; - - /* Skip over this header. */ - if (hlen > p->len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", - hlen, p->len)); - /* free (drop) packet pbufs */ - pbuf_free(p); - IP6_STATS_INC(ip6.lenerr); - IP6_STATS_INC(ip6.drop); - goto ip6_input_cleanup; - } - - pbuf_header(p, -hlen); - break; - case IP6_NEXTH_DESTOPTS: - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n")); - /* Get next header type. */ - nexth = *((u8_t *)p->payload); - - /* Get the header length. */ - hlen = 8 * (1 + *((u8_t *)p->payload + 1)); - ip_data.current_ip_header_tot_len += hlen; - - /* Skip over this header. */ - if (hlen > p->len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", - hlen, p->len)); - /* free (drop) packet pbufs */ - pbuf_free(p); - IP6_STATS_INC(ip6.lenerr); - IP6_STATS_INC(ip6.drop); - goto ip6_input_cleanup; - } - - pbuf_header(p, -hlen); - break; - case IP6_NEXTH_ROUTING: - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n")); - /* Get next header type. */ - nexth = *((u8_t *)p->payload); - - /* Get the header length. */ - hlen = 8 * (1 + *((u8_t *)p->payload + 1)); - ip_data.current_ip_header_tot_len += hlen; - - /* Skip over this header. */ - if (hlen > p->len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", - hlen, p->len)); - /* free (drop) packet pbufs */ - pbuf_free(p); - IP6_STATS_INC(ip6.lenerr); - IP6_STATS_INC(ip6.drop); - goto ip6_input_cleanup; - } - - pbuf_header(p, -hlen); - break; - - case IP6_NEXTH_FRAGMENT: - { - struct ip6_frag_hdr * frag_hdr; - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n")); - - frag_hdr = (struct ip6_frag_hdr *)p->payload; - - /* Get next header type. */ - nexth = frag_hdr->_nexth; - - /* Fragment Header length. */ - hlen = 8; - ip_data.current_ip_header_tot_len += hlen; - - /* Make sure this header fits in current pbuf. */ - if (hlen > p->len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", - hlen, p->len)); - /* free (drop) packet pbufs */ - pbuf_free(p); - IP6_FRAG_STATS_INC(ip6_frag.lenerr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto ip6_input_cleanup; - } - - /* Offset == 0 and more_fragments == 0? */ - if (((frag_hdr->_fragment_offset & IP6_FRAG_OFFSET_MASK) == 0) && - ((frag_hdr->_fragment_offset & IP6_FRAG_MORE_FLAG) == 0)) { - - /* This is a 1-fragment packet, usually a packet that we have - * already reassembled. Skip this header anc continue. */ - pbuf_header(p, -hlen); - } - else { -#if LWIP_IPV6_REASS - - /* reassemble the packet */ - p = ip6_reass(p); - /* packet not fully reassembled yet? */ - if (p == NULL) { - goto ip6_input_cleanup; - } - - /* Returned p point to IPv6 header. - * Update all our variables and pointers and continue. */ - ip6hdr = (struct ip6_hdr *)p->payload; - nexth = IP6H_NEXTH(ip6hdr); - hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; - pbuf_header(p, -IP6_HLEN); - -#else /* LWIP_IPV6_REASS */ - /* free (drop) packet pbufs */ - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n")); - pbuf_free(p); - IP6_STATS_INC(ip6.opterr); - IP6_STATS_INC(ip6.drop); - goto ip6_input_cleanup; -#endif /* LWIP_IPV6_REASS */ - } - break; - } - default: - goto options_done; - break; - } - } -options_done: - - /* p points to IPv6 header again. */ - pbuf_header(p, ip_data.current_ip_header_tot_len); - - /* send to upper layers */ - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n")); - ip6_debug_print(p); - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); - -#if LWIP_RAW - /* raw input did not eat the packet? */ - if (raw_input(p, inp) == 0) -#endif /* LWIP_RAW */ - { - switch (nexth) { - case IP6_NEXTH_NONE: - pbuf_free(p); - break; -#if LWIP_UDP - case IP6_NEXTH_UDP: -#if LWIP_UDPLITE - case IP6_NEXTH_UDPLITE: -#endif /* LWIP_UDPLITE */ - /* Point to payload. */ - pbuf_header(p, -ip_data.current_ip_header_tot_len); - udp_input(p, inp); - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case IP6_NEXTH_TCP: - /* Point to payload. */ - pbuf_header(p, -ip_data.current_ip_header_tot_len); - tcp_input(p, inp); - break; -#endif /* LWIP_TCP */ -#if LWIP_ICMP6 - case IP6_NEXTH_ICMP6: - /* Point to payload. */ - pbuf_header(p, -ip_data.current_ip_header_tot_len); - icmp6_input(p, inp); - break; -#endif /* LWIP_ICMP */ - default: -#if LWIP_ICMP6 - /* send ICMP parameter problem unless it was a multicast or ICMPv6 */ - if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) && - (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) { - icmp6_param_problem(p, ICMP6_PP_HEADER, ip_data.current_ip_header_tot_len - hlen); - } -#endif /* LWIP_ICMP */ - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", IP6H_NEXTH(ip6hdr))); - pbuf_free(p); - IP6_STATS_INC(ip6.proterr); - IP6_STATS_INC(ip6.drop); - break; - } - } - -ip6_input_cleanup: - ip_data.current_netif = NULL; - ip_data.current_ip6_header = NULL; - ip_data.current_ip_header_tot_len = 0; - ip6_addr_set_any(&ip_data.current_iphdr_src.ip6); - ip6_addr_set_any(&ip_data.current_iphdr_dest.ip6); - - return ERR_OK; -} - - -/** - * Sends an IPv6 packet on a network interface. This function constructs - * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is - * used as source (usually during network startup). If the source IPv6 address it - * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network - * interface is filled in as source address. If the destination IPv6 address is - * IP_HDRINCL, p is assumed to already include an IPv6 header and p->payload points - * to it instead of the data. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == IP_HDRINCL, p already includes an - IPv6 header and p->payload points to that IPv6 header) - * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an - * IP address of the netif is selected and used as source address. - * if src == NULL, IP6_ADDR_ANY is used as source) - * @param dest the destination IPv6 address to send the packet to - * @param hl the Hop Limit value to be set in the IPv6 header - * @param tc the Traffic Class value to be set in the IPv6 header - * @param nexth the Next Header to be set in the IPv6 header - * @param netif the netif on which to send this packet - * @return ERR_OK if the packet was sent OK - * ERR_BUF if p doesn't have enough space for IPv6/LINK headers - * returns errors returned by netif->output - */ -err_t -ip6_output_if(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, - u8_t hl, u8_t tc, - u8_t nexth, struct netif *netif) -{ - struct ip6_hdr *ip6hdr; - ip6_addr_t dest_addr; - - /* pbufs passed to IP must have a ref-count of 1 as their payload pointer - gets altered as the packet is passed down the stack */ - LWIP_ASSERT("p->ref == 1", p->ref == 1); - - /* Should the IPv6 header be generated or is it already included in p? */ - if (dest != IP_HDRINCL) { - /* generate IPv6 header */ - if (pbuf_header(p, IP6_HLEN)) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n")); - IP6_STATS_INC(ip6.err); - return ERR_BUF; - } - - ip6hdr = (struct ip6_hdr *)p->payload; - LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr", - (p->len >= sizeof(struct ip6_hdr))); - - IP6H_HOPLIM_SET(ip6hdr, hl); - IP6H_NEXTH_SET(ip6hdr, nexth); - - /* dest cannot be NULL here */ - ip6_addr_copy(ip6hdr->dest, *dest); - - IP6H_VTCFL_SET(ip6hdr, 6, tc, 0); - IP6H_PLEN_SET(ip6hdr, p->tot_len - IP6_HLEN); - - if (src == NULL) { - src = IP6_ADDR_ANY; - } - else if (ip6_addr_isany(src)) { - src = ip6_select_source_address(netif, dest); - if ((src == NULL) || ip6_addr_isany(src)) { - /* No appropriate source address was found for this packet. */ - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n")); - IP6_STATS_INC(ip6.rterr); - return ERR_RTE; - } - } - /* src cannot be NULL here */ - ip6_addr_copy(ip6hdr->src, *src); - - } else { - /* IP header already included in p */ - ip6hdr = (struct ip6_hdr *)p->payload; - ip6_addr_copy(dest_addr, ip6hdr->dest); - dest = &dest_addr; - } - - IP6_STATS_INC(ip6.xmit); - - LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); - ip6_debug_print(p); - -#if ENABLE_LOOPBACK - /* TODO implement loopback for v6 - if (ip6_addr_cmp(dest, netif_ip6_addr(0))) { - return netif_loop_output(netif, p, dest); - }*/ -#endif /* ENABLE_LOOPBACK */ -#if LWIP_IPV6_FRAG - /* don't fragment if interface has mtu set to 0 [loopif] */ - if (netif->mtu && (p->tot_len > nd6_get_destination_mtu(dest, netif))) { - return ip6_frag(p, netif, dest); - } -#endif /* LWIP_IPV6_FRAG */ - - LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()")); - return netif->output_ip6(netif, p, dest); -} - -/** - * Simple interface to ip6_output_if. It finds the outgoing network - * interface and calls upon ip6_output_if to do the actual work. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == IP_HDRINCL, p already includes an - IPv6 header and p->payload points to that IPv6 header) - * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an - * IP address of the netif is selected and used as source address. - * if src == NULL, IP6_ADDR_ANY is used as source) - * @param dest the destination IPv6 address to send the packet to - * @param hl the Hop Limit value to be set in the IPv6 header - * @param tc the Traffic Class value to be set in the IPv6 header - * @param nexth the Next Header to be set in the IPv6 header - * - * @return ERR_RTE if no route is found - * see ip_output_if() for more return values - */ -err_t -ip6_output(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, - u8_t hl, u8_t tc, u8_t nexth) -{ - struct netif *netif; - struct ip6_hdr *ip6hdr; - ip6_addr_t src_addr, dest_addr; - - /* pbufs passed to IPv6 must have a ref-count of 1 as their payload pointer - gets altered as the packet is passed down the stack */ - LWIP_ASSERT("p->ref == 1", p->ref == 1); - - if (dest != IP_HDRINCL) { - netif = ip6_route(src, dest); - } else { - /* IP header included in p, read addresses. */ - ip6hdr = (struct ip6_hdr *)p->payload; - ip6_addr_copy(src_addr, ip6hdr->src); - ip6_addr_copy(dest_addr, ip6hdr->dest); - netif = ip6_route(&src_addr, &dest_addr); - } - - if (netif == NULL) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", - IP6_ADDR_BLOCK1(dest), - IP6_ADDR_BLOCK2(dest), - IP6_ADDR_BLOCK3(dest), - IP6_ADDR_BLOCK4(dest), - IP6_ADDR_BLOCK5(dest), - IP6_ADDR_BLOCK6(dest), - IP6_ADDR_BLOCK7(dest), - IP6_ADDR_BLOCK8(dest))); - IP6_STATS_INC(ip6.rterr); - return ERR_RTE; - } - - return ip6_output_if(p, src, dest, hl, tc, nexth, netif); -} - - -#if LWIP_NETIF_HWADDRHINT -/** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint - * before calling ip6_output_if. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == IP_HDRINCL, p already includes an - IPv6 header and p->payload points to that IPv6 header) - * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an - * IP address of the netif is selected and used as source address. - * if src == NULL, IP6_ADDR_ANY is used as source) - * @param dest the destination IPv6 address to send the packet to - * @param hl the Hop Limit value to be set in the IPv6 header - * @param tc the Traffic Class value to be set in the IPv6 header - * @param nexth the Next Header to be set in the IPv6 header - * @param addr_hint address hint pointer set to netif->addr_hint before - * calling ip_output_if() - * - * @return ERR_RTE if no route is found - * see ip_output_if() for more return values - */ -err_t -ip6_output_hinted(struct pbuf *p, ip6_addr_t *src, ip6_addr_t *dest, - u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint) -{ - struct netif *netif; - struct ip6_hdr *ip6hdr; - ip6_addr_t src_addr, dest_addr; - err_t err; - - /* pbufs passed to IP must have a ref-count of 1 as their payload pointer - gets altered as the packet is passed down the stack */ - LWIP_ASSERT("p->ref == 1", p->ref == 1); - - if (dest != IP_HDRINCL) { - netif = ip6_route(src, dest); - } else { - /* IP header included in p, read addresses. */ - ip6hdr = (struct ip6_hdr *)p->payload; - ip6_addr_copy(src_addr, ip6hdr->src); - ip6_addr_copy(dest_addr, ip6hdr->dest); - netif = ip6_route(&src_addr, &dest_addr); - } - - if (netif == NULL) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", - IP6_ADDR_BLOCK1(dest), - IP6_ADDR_BLOCK2(dest), - IP6_ADDR_BLOCK3(dest), - IP6_ADDR_BLOCK4(dest), - IP6_ADDR_BLOCK5(dest), - IP6_ADDR_BLOCK6(dest), - IP6_ADDR_BLOCK7(dest), - IP6_ADDR_BLOCK8(dest))); - IP6_STATS_INC(ip6.rterr); - return ERR_RTE; - } - - NETIF_SET_HWADDRHINT(netif, addr_hint); - err = ip6_output_if(p, src, dest, hl, tc, nexth, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - - return err; -} -#endif /* LWIP_NETIF_HWADDRHINT*/ - -#if LWIP_IPV6_MLD -/** - * Add a hop-by-hop options header with a router alert option and padding. - * - * Used by MLD when sending a Multicast listener report/done message. - * - * @param p the packet to which we will prepend the options header - * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6) - * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD) - * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise - */ -err_t -ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value) -{ - struct ip6_hbh_hdr * hbh_hdr; - - /* Move pointer to make room for hop-by-hop options header. */ - if (pbuf_header(p, sizeof(struct ip6_hbh_hdr))) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n")); - IP6_STATS_INC(ip6.err); - return ERR_BUF; - } - - hbh_hdr = (struct ip6_hbh_hdr *)p->payload; - - /* Set fields. */ - hbh_hdr->_nexth = nexth; - hbh_hdr->_hlen = 0; - hbh_hdr->_ra_opt_type = IP6_ROUTER_ALERT_OPTION; - hbh_hdr->_ra_opt_dlen = 2; - hbh_hdr->_ra_opt_data = value; - hbh_hdr->_padn_opt_type = IP6_PADN_ALERT_OPTION; - hbh_hdr->_padn_opt_dlen = 0; - - return ERR_OK; -} -#endif /* LWIP_IPV6_MLD */ - -#if IP6_DEBUG -/* Print an IPv6 header by using LWIP_DEBUGF - * @param p an IPv6 packet, p->payload pointing to the IPv6 header - */ -void -ip6_debug_print(struct pbuf *p) -{ - struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; - - LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n")); - LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" | %3"U16_F" | %7"U32_F" | (ver, class, flow)\n", - IP6H_V(ip6hdr), - IP6H_TC(ip6hdr), - IP6H_FL(ip6hdr))); - LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP6_DEBUG, ("| %5"U16_F" | %3"U16_F" | %3"U16_F" | (plen, nexth, hopl)\n", - IP6H_PLEN(ip6hdr), - IP6H_NEXTH(ip6hdr), - IP6H_HOPLIM(ip6hdr))); - LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (src)\n", - IP6_ADDR_BLOCK1(&(ip6hdr->src)), - IP6_ADDR_BLOCK2(&(ip6hdr->src)), - IP6_ADDR_BLOCK3(&(ip6hdr->src)), - IP6_ADDR_BLOCK4(&(ip6hdr->src)))); - LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", - IP6_ADDR_BLOCK5(&(ip6hdr->src)), - IP6_ADDR_BLOCK6(&(ip6hdr->src)), - IP6_ADDR_BLOCK7(&(ip6hdr->src)), - IP6_ADDR_BLOCK8(&(ip6hdr->src)))); - LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (dest)\n", - IP6_ADDR_BLOCK1(&(ip6hdr->dest)), - IP6_ADDR_BLOCK2(&(ip6hdr->dest)), - IP6_ADDR_BLOCK3(&(ip6hdr->dest)), - IP6_ADDR_BLOCK4(&(ip6hdr->dest)))); - LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", - IP6_ADDR_BLOCK5(&(ip6hdr->dest)), - IP6_ADDR_BLOCK6(&(ip6hdr->dest)), - IP6_ADDR_BLOCK7(&(ip6hdr->dest)), - IP6_ADDR_BLOCK8(&(ip6hdr->dest)))); - LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); -} -#endif /* IP6_DEBUG */ - -#endif /* LWIP_IPV6 */ diff --git a/third_party/lwip/core/ipv6/ip6_addr.c b/third_party/lwip/core/ipv6/ip6_addr.c deleted file mode 100644 index c3f523a..0000000 --- a/third_party/lwip/core/ipv6/ip6_addr.c +++ /dev/null @@ -1,251 +0,0 @@ -/** - * @file - * - * IPv6 addresses. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * 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: Ivan Delamer - * - * Functions for handling IPv6 addresses. - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/ip6_addr.h" -#include "lwip/def.h" - -/* used by IP6_ADDR_ANY in ip6_addr.h */ -const ip6_addr_t ip6_addr_any = { { 0ul, 0ul, 0ul, 0ul } }; - -#ifndef isprint -#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) -#define isprint(c) in_range(c, 0x20, 0x7f) -#define isdigit(c) in_range(c, '0', '9') -#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) -#define islower(c) in_range(c, 'a', 'z') -#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') -#define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10) -#endif - -/** - * Check whether "cp" is a valid ascii representation - * of an IPv6 address and convert to a binary address. - * Returns 1 if the address is valid, 0 if not. - * - * @param cp IPv6 address in ascii represenation (e.g. "FF01::1") - * @param addr pointer to which to save the ip address in network order - * @return 1 if cp could be converted to addr, 0 on failure - */ -int -ip6addr_aton(const char *cp, ip6_addr_t *addr) -{ - u32_t addr_index, zero_blocks, current_block_index, current_block_value; - const char * s; - - /* Count the number of colons, to count the number of blocks in a "::" sequence - zero_blocks may be 1 even if there are no :: sequences */ - zero_blocks = 8; - for (s = cp; *s != 0; s++) { - if (*s == ':') - zero_blocks--; - else if (!isxdigit(*s)) - break; - } - - /* parse each block */ - addr_index = 0; - current_block_index = 0; - current_block_value = 0; - for (s = cp; *s != 0; s++) { - if (*s == ':') { - if (addr) { - if (current_block_index & 0x1) { - addr->addr[addr_index++] |= current_block_value; - } - else { - addr->addr[addr_index] = current_block_value << 16; - } - } - current_block_index++; - current_block_value = 0; - if (current_block_index > 7) { - /* address too long! */ - return 0; - } if (s[1] == ':') { - s++; - /* "::" found, set zeros */ - while (zero_blocks-- > 0) { - if (current_block_index & 0x1) { - addr_index++; - } - else { - if (addr) { - addr->addr[addr_index] = 0; - } - } - current_block_index++; - } - } - } else if (isxdigit(*s)) { - /* add current digit */ - current_block_value = (current_block_value << 4) + - (isdigit(*s) ? *s - '0' : - 10 + (islower(*s) ? *s - 'a' : *s - 'A')); - } else { - /* unexpected digit, space? CRLF? */ - break; - } - } - - if (addr) { - if (current_block_index & 0x1) { - addr->addr[addr_index++] |= current_block_value; - } - else { - addr->addr[addr_index] = current_block_value << 16; - } - } - - /* convert to network byte order. */ - if (addr) { - for (addr_index = 0; addr_index < 4; addr_index++) { - addr->addr[addr_index] = htonl(addr->addr[addr_index]); - } - } - - if (current_block_index != 7) { - return 0; - } - - return 1; -} - -/** - * Convert numeric IPv6 address into ASCII representation. - * returns ptr to static buffer; not reentrant! - * - * @param addr ip6 address in network order to convert - * @return pointer to a global static (!) buffer that holds the ASCII - * represenation of addr - */ -char * -ip6addr_ntoa(const ip6_addr_t *addr) -{ - static char str[40]; - return ip6addr_ntoa_r(addr, str, 40); -} - -/** - * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. - * - * @param addr ip6 address in network order to convert - * @param buf target buffer where the string is stored - * @param buflen length of buf - * @return either pointer to buf which now holds the ASCII - * representation of addr or NULL if buf was too small - */ -char * -ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) -{ - u32_t current_block_index, current_block_value; - s32_t zero_flag, i; - - i = 0; - zero_flag = 0; /* used to indicate a zero chain for "::' */ - - for (current_block_index = 0; current_block_index < 8; current_block_index++) { - /* get the current 16-bit block */ - current_block_value = htonl(addr->addr[current_block_index >> 1]); - if ((current_block_index & 0x1) == 0) { - current_block_value = current_block_value >> 16; - } - current_block_value &= 0xffff; - - if (current_block_value == 0) { - /* generate empty block "::" */ - if (!zero_flag) { - if (current_block_index > 0) { - zero_flag = 1; - buf[i++] = ':'; - if (i >= buflen) return NULL; - } - } - } - else { - if (current_block_index > 0) { - buf[i++] = ':'; - if (i >= buflen) return NULL; - } - - if ((current_block_value & 0xf000) == 0) { - zero_flag = 1; - } - else { - buf[i++] = xchar(((current_block_value & 0xf000) >> 12)); - zero_flag = 0; - if (i >= buflen) return NULL; - } - - if (((current_block_value & 0xf00) == 0) && (zero_flag)) { - /* do nothing */ - } - else { - buf[i++] = xchar(((current_block_value & 0xf00) >> 8)); - zero_flag = 0; - if (i >= buflen) return NULL; - } - - if (((current_block_value & 0xf0) == 0) && (zero_flag)) { - /* do nothing */ - } - else { - buf[i++] = xchar(((current_block_value & 0xf0) >> 4)); - zero_flag = 0; - if (i >= buflen) return NULL; - } - - buf[i++] = xchar((current_block_value & 0xf)); - if (i >= buflen) return NULL; - - zero_flag = 0; - } - } - - buf[i] = 0; - - return buf; -} -#endif /* LWIP_IPV6 */ diff --git a/third_party/lwip/core/ipv6/ip6_frag.c b/third_party/lwip/core/ipv6/ip6_frag.c deleted file mode 100644 index b110dd7..0000000 --- a/third_party/lwip/core/ipv6/ip6_frag.c +++ /dev/null @@ -1,698 +0,0 @@ -/** - * @file - * - * IPv6 fragmentation and reassembly. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * 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: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" -#include "lwip/ip6_frag.h" -#include "lwip/ip6.h" -#include "lwip/icmp6.h" -#include "lwip/nd6.h" -#include "lwip/ip.h" - -#include "lwip/pbuf.h" -#include "lwip/memp.h" -#include "lwip/stats.h" - -#include - -#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */ - - -/** Setting this to 0, you can turn off checking the fragments for overlapping - * regions. The code gets a little smaller. Only use this if you know that - * overlapping won't occur on your network! */ -#ifndef IP_REASS_CHECK_OVERLAP -#define IP_REASS_CHECK_OVERLAP 1 -#endif /* IP_REASS_CHECK_OVERLAP */ - -/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is - * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. - * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA - * is set to 1, so one datagram can be reassembled at a time, only. */ -#ifndef IP_REASS_FREE_OLDEST -#define IP_REASS_FREE_OLDEST 1 -#endif /* IP_REASS_FREE_OLDEST */ - -#define IP_REASS_FLAG_LASTFRAG 0x01 - -/** This is a helper struct which holds the starting - * offset and the ending offset of this fragment to - * easily chain the fragments. - * It has the same packing requirements as the IPv6 header, since it replaces - * the Fragment Header in memory in incoming fragments to keep - * track of the various fragments. - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip6_reass_helper { - PACK_STRUCT_FIELD(struct pbuf *next_pbuf); - PACK_STRUCT_FIELD(u16_t start); - PACK_STRUCT_FIELD(u16_t end); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* static variables */ -static struct ip6_reassdata *reassdatagrams; -static u16_t ip6_reass_pbufcount; - -/* Forward declarations. */ -static void ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr); -#if IP_REASS_FREE_OLDEST -static void ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed); -#endif /* IP_REASS_FREE_OLDEST */ - -void -ip6_reass_tmr(void) -{ - struct ip6_reassdata *r, *tmp; - - r = reassdatagrams; - while (r != NULL) { - /* Decrement the timer. Once it reaches 0, - * clean up the incomplete fragment assembly */ - if (r->timer > 0) { - r->timer--; - r = r->next; - } else { - /* reassembly timed out */ - tmp = r; - /* get the next pointer before freeing */ - r = r->next; - /* free the helper struct and all enqueued pbufs */ - ip6_reass_free_complete_datagram(tmp); - } - } -} - -/** - * Free a datagram (struct ip6_reassdata) and all its pbufs. - * Updates the total count of enqueued pbufs (ip6_reass_pbufcount), - * sends an ICMP time exceeded packet. - * - * @param ipr datagram to free - */ -static void -ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr) -{ - struct ip6_reassdata *prev; - u16_t pbufs_freed = 0; - u8_t clen; - struct pbuf *p; - struct ip6_reass_helper *iprh; - -#if LWIP_ICMP6 - iprh = (struct ip6_reass_helper *)ipr->p->payload; - if (iprh->start == 0) { - /* The first fragment was received, send ICMP time exceeded. */ - /* First, de-queue the first pbuf from r->p. */ - p = ipr->p; - ipr->p = iprh->next_pbuf; - /* Then, move back to the original header (we are now pointing to Fragment header). */ - if (pbuf_header(p, (u8_t*)p->payload - (u8_t*)ipr->iphdr)) { - LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed\n", 0); - } - else { - icmp6_time_exceeded(p, ICMP6_TE_FRAG); - } - clen = pbuf_clen(p); - LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); - pbufs_freed += clen; - pbuf_free(p); - } -#endif /* LWIP_ICMP6 */ - - /* First, free all received pbufs. The individual pbufs need to be released - separately as they have not yet been chained */ - p = ipr->p; - while (p != NULL) { - struct pbuf *pcur; - iprh = (struct ip6_reass_helper *)p->payload; - pcur = p; - /* get the next pointer before freeing */ - p = iprh->next_pbuf; - clen = pbuf_clen(pcur); - LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); - pbufs_freed += clen; - pbuf_free(pcur); - } - - /* Then, unchain the struct ip6_reassdata from the list and free it. */ - if (ipr == reassdatagrams) { - reassdatagrams = ipr->next; - } else { - prev = reassdatagrams; - while (prev != NULL) { - if (prev->next == ipr) { - break; - } - prev = prev->next; - } - if (prev != NULL) { - prev->next = ipr->next; - } - } - memp_free(MEMP_IP6_REASSDATA, ipr); - - /* Finally, update number of pbufs in reassembly queue */ - LWIP_ASSERT("ip_reass_pbufcount >= clen", ip6_reass_pbufcount >= pbufs_freed); - ip6_reass_pbufcount -= pbufs_freed; -} - -#if IP_REASS_FREE_OLDEST -/** - * Free the oldest datagram to make room for enqueueing new fragments. - * The datagram ipr is not freed! - * - * @param ipr ip6_reassdata for the current fragment - * @param pbufs_needed number of pbufs needed to enqueue - * (used for freeing other datagrams if not enough space) - */ -static void -ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed) -{ - struct ip6_reassdata *r, *oldest; - - /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, - * but don't free the current datagram! */ - do { - r = oldest = reassdatagrams; - while (r != NULL) { - if (r != ipr) { - if (r->timer <= oldest->timer) { - /* older than the previous oldest */ - oldest = r; - } - } - r = r->next; - } - if (oldest != NULL) { - ip6_reass_free_complete_datagram(oldest); - } - } while (((ip6_reass_pbufcount + pbufs_needed) > IP_REASS_MAX_PBUFS) && (reassdatagrams != NULL)); -} -#endif /* IP_REASS_FREE_OLDEST */ - -/** - * Reassembles incoming IPv6 fragments into an IPv6 datagram. - * - * @param p points to the IPv6 Fragment Header - * @param len the length of the payload (after Fragment Header) - * @return NULL if reassembly is incomplete, pbuf pointing to - * IPv6 Header if reassembly is complete - */ -struct pbuf * -ip6_reass(struct pbuf *p) -{ - struct ip6_reassdata *ipr, *ipr_prev; - struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; - struct ip6_frag_hdr * frag_hdr; - u16_t offset, len; - u8_t clen, valid = 1; - struct pbuf *q; - - IP6_FRAG_STATS_INC(ip6_frag.recv); - - frag_hdr = (struct ip6_frag_hdr *) p->payload; - - clen = pbuf_clen(p); - - offset = ntohs(frag_hdr->_fragment_offset); - - /* Calculate fragment length from IPv6 payload length. - * Adjust for headers before Fragment Header. - * And finally adjust by Fragment Header length. */ - len = ntohs(ip6_current_header()->_plen); - len -= ((u8_t*)p->payload - (u8_t*)ip6_current_header()) - IP6_HLEN; - len -= IP6_FRAG_HLEN; - - /* Look for the datagram the fragment belongs to in the current datagram queue, - * remembering the previous in the queue for later dequeueing. */ - for (ipr = reassdatagrams, ipr_prev = NULL; ipr != NULL; ipr = ipr->next) { - /* Check if the incoming fragment matches the one currently present - in the reassembly buffer. If so, we proceed with copying the - fragment into the buffer. */ - if ((frag_hdr->_identification == ipr->identification) && - ip6_addr_cmp(ip6_current_src_addr(), &(ipr->iphdr->src)) && - ip6_addr_cmp(ip6_current_dest_addr(), &(ipr->iphdr->dest))) { - IP6_FRAG_STATS_INC(ip6_frag.cachehit); - break; - } - ipr_prev = ipr; - } - - if (ipr == NULL) { - /* Enqueue a new datagram into the datagram queue */ - ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA); - if (ipr == NULL) { -#if IP_REASS_FREE_OLDEST - /* Make room and try again. */ - ip6_reass_remove_oldest_datagram(ipr, clen); - ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA); - if (ipr == NULL) -#endif /* IP_REASS_FREE_OLDEST */ - { - IP6_FRAG_STATS_INC(ip6_frag.memerr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; - } - } - - memset(ipr, 0, sizeof(struct ip6_reassdata)); - ipr->timer = IP_REASS_MAXAGE; - - /* enqueue the new structure to the front of the list */ - ipr->next = reassdatagrams; - reassdatagrams = ipr; - - /* Use the current IPv6 header for src/dest address reference. - * Eventually, we will replace it when we get the first fragment - * (it might be this one, in any case, it is done later). */ - ipr->iphdr = (struct ip6_hdr *)ip6_current_header(); - - /* copy the fragmented packet id. */ - ipr->identification = frag_hdr->_identification; - - /* copy the nexth field */ - ipr->nexth = frag_hdr->_nexth; - } - - /* Check if we are allowed to enqueue more datagrams. */ - if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { -#if IP_REASS_FREE_OLDEST - ip6_reass_remove_oldest_datagram(ipr, clen); - if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) -#endif /* IP_REASS_FREE_OLDEST */ - { - /* @todo: send ICMPv6 time exceeded here? */ - /* drop this pbuf */ - IP6_FRAG_STATS_INC(ip6_frag.memerr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; - } - } - - /* Overwrite Fragment Header with our own helper struct. */ - iprh = (struct ip6_reass_helper *)p->payload; - iprh->next_pbuf = NULL; - iprh->start = (offset & IP6_FRAG_OFFSET_MASK); - iprh->end = (offset & IP6_FRAG_OFFSET_MASK) + len; - - /* find the right place to insert this pbuf */ - /* Iterate through until we either get to the end of the list (append), - * or we find on with a larger offset (insert). */ - for (q = ipr->p; q != NULL;) { - iprh_tmp = (struct ip6_reass_helper*)q->payload; - if (iprh->start < iprh_tmp->start) { -#if IP_REASS_CHECK_OVERLAP - if (iprh->end > iprh_tmp->start) { - /* fragment overlaps with following, throw away */ - IP6_FRAG_STATS_INC(ip6_frag.proterr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; - } - if (iprh_prev != NULL) { - if (iprh->start < iprh_prev->end) { - /* fragment overlaps with previous, throw away */ - IP6_FRAG_STATS_INC(ip6_frag.proterr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; - } - } -#endif /* IP_REASS_CHECK_OVERLAP */ - /* the new pbuf should be inserted before this */ - iprh->next_pbuf = q; - if (iprh_prev != NULL) { - /* not the fragment with the lowest offset */ - iprh_prev->next_pbuf = p; - } else { - /* fragment with the lowest offset */ - ipr->p = p; - } - break; - } else if(iprh->start == iprh_tmp->start) { - /* received the same datagram twice: no need to keep the datagram */ - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; -#if IP_REASS_CHECK_OVERLAP - } else if(iprh->start < iprh_tmp->end) { - /* overlap: no need to keep the new datagram */ - IP6_FRAG_STATS_INC(ip6_frag.proterr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; -#endif /* IP_REASS_CHECK_OVERLAP */ - } else { - /* Check if the fragments received so far have no gaps. */ - if (iprh_prev != NULL) { - if (iprh_prev->end != iprh_tmp->start) { - /* There is a fragment missing between the current - * and the previous fragment */ - valid = 0; - } - } - } - q = iprh_tmp->next_pbuf; - iprh_prev = iprh_tmp; - } - - /* If q is NULL, then we made it to the end of the list. Determine what to do now */ - if (q == NULL) { - if (iprh_prev != NULL) { - /* this is (for now), the fragment with the highest offset: - * chain it to the last fragment */ -#if IP_REASS_CHECK_OVERLAP - LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); -#endif /* IP_REASS_CHECK_OVERLAP */ - iprh_prev->next_pbuf = p; - if (iprh_prev->end != iprh->start) { - valid = 0; - } - } else { -#if IP_REASS_CHECK_OVERLAP - LWIP_ASSERT("no previous fragment, this must be the first fragment!", - ipr->p == NULL); -#endif /* IP_REASS_CHECK_OVERLAP */ - /* this is the first fragment we ever received for this ip datagram */ - ipr->p = p; - } - } - - /* Track the current number of pbufs current 'in-flight', in order to limit - the number of fragments that may be enqueued at any one time */ - ip6_reass_pbufcount += clen; - - /* Remember IPv6 header if this is the first fragment. */ - if (iprh->start == 0) { - ipr->iphdr = (struct ip6_hdr *)ip6_current_header(); - } - - /* If this is the last fragment, calculate total packet length. */ - if ((offset & IP6_FRAG_MORE_FLAG) == 0) { - ipr->datagram_len = iprh->end; - } - - /* Additional validity tests: we have received first and last fragment. */ - iprh_tmp = (struct ip6_reass_helper*)ipr->p->payload; - if (iprh_tmp->start != 0) { - valid = 0; - } - if (ipr->datagram_len == 0) { - valid = 0; - } - - /* Final validity test: no gaps between current and last fragment. */ - iprh_prev = iprh; - q = iprh->next_pbuf; - while ((q != NULL) && valid) { - iprh = (struct ip6_reass_helper*)q->payload; - if (iprh_prev->end != iprh->start) { - valid = 0; - break; - } - iprh_prev = iprh; - q = iprh->next_pbuf; - } - - if (valid) { - /* All fragments have been received */ - - /* chain together the pbufs contained within the ip6_reassdata list. */ - iprh = (struct ip6_reass_helper*) ipr->p->payload; - while(iprh != NULL) { - - if (iprh->next_pbuf != NULL) { - /* Save next helper struct (will be hidden in next step). */ - iprh_tmp = (struct ip6_reass_helper*) iprh->next_pbuf->payload; - - /* hide the fragment header for every succeding fragment */ - pbuf_header(iprh->next_pbuf, -IP6_FRAG_HLEN); - pbuf_cat(ipr->p, iprh->next_pbuf); - } - else { - iprh_tmp = NULL; - } - - iprh = iprh_tmp; - } - - /* Adjust datagram length by adding header lengths. */ - ipr->datagram_len += ((u8_t*)ipr->p->payload - (u8_t*)ipr->iphdr) - + IP6_FRAG_HLEN - - IP6_HLEN ; - - /* Set payload length in ip header. */ - ipr->iphdr->_plen = htons(ipr->datagram_len); - - /* Get the furst pbuf. */ - p = ipr->p; - - /* Restore Fragment Header in first pbuf. Mark as "single fragment" - * packet. Restore nexth. */ - frag_hdr = (struct ip6_frag_hdr *) p->payload; - frag_hdr->_nexth = ipr->nexth; - frag_hdr->reserved = 0; - frag_hdr->_fragment_offset = 0; - frag_hdr->_identification = 0; - - /* release the sources allocate for the fragment queue entry */ - if (reassdatagrams == ipr) { - /* it was the first in the list */ - reassdatagrams = ipr->next; - } else { - /* it wasn't the first, so it must have a valid 'prev' */ - LWIP_ASSERT("sanity check linked list", ipr_prev != NULL); - ipr_prev->next = ipr->next; - } - memp_free(MEMP_IP6_REASSDATA, ipr); - - /* adjust the number of pbufs currently queued for reassembly. */ - ip6_reass_pbufcount -= pbuf_clen(p); - - /* Move pbuf back to IPv6 header. */ - if (pbuf_header(p, (u8_t*)p->payload - (u8_t*)ipr->iphdr)) { - LWIP_ASSERT("ip6_reass: moving p->payload to ip6 header failed\n", 0); - pbuf_free(p); - return NULL; - } - - /* Return the pbuf chain */ - return p; - } - /* the datagram is not (yet?) reassembled completely */ - return NULL; - -nullreturn: - pbuf_free(p); - return NULL; -} - -#endif /* LWIP_IPV6 ^^ LWIP_IPV6_REASS */ - -#if LWIP_IPV6 && LWIP_IPV6_FRAG - -/** Allocate a new struct pbuf_custom_ref */ -static struct pbuf_custom_ref* -ip6_frag_alloc_pbuf_custom_ref(void) -{ - return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); -} - -/** Free a struct pbuf_custom_ref */ -static void -ip6_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) -{ - LWIP_ASSERT("p != NULL", p != NULL); - memp_free(MEMP_FRAG_PBUF, p); -} - -/** Free-callback function to free a 'struct pbuf_custom_ref', called by - * pbuf_free. */ -static void -ip6_frag_free_pbuf_custom(struct pbuf *p) -{ - struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; - LWIP_ASSERT("pcr != NULL", pcr != NULL); - LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); - if (pcr->original != NULL) { - pbuf_free(pcr->original); - } - ip6_frag_free_pbuf_custom_ref(pcr); -} - -/** - * Fragment an IPv6 datagram if too large for the netif or path MTU. - * - * Chop the datagram in MTU sized chunks and send them in order - * by pointing PBUF_REFs into p - * - * @param p ipv6 packet to send - * @param netif the netif on which to send - * @param dest destination ipv6 address to which to send - * - * @return ERR_OK if sent successfully, err_t otherwise - */ -err_t -ip6_frag(struct pbuf *p, struct netif *netif, ip6_addr_t *dest) -{ - struct ip6_hdr *original_ip6hdr; - struct ip6_hdr *ip6hdr; - struct ip6_frag_hdr * frag_hdr; - struct pbuf *rambuf; - struct pbuf *newpbuf; - static u32_t identification; - u16_t nfb; - u16_t left, cop; - u16_t mtu; - u16_t fragment_offset = 0; - u16_t last; - u16_t poff = IP6_HLEN; - u16_t newpbuflen = 0; - u16_t left_to_copy; - - identification++; - - original_ip6hdr = (struct ip6_hdr *)p->payload; - - mtu = nd6_get_destination_mtu(dest, netif); - - /* TODO we assume there are no options in the unfragmentable part (IPv6 header). */ - left = p->tot_len - IP6_HLEN; - - nfb = (mtu - (IP6_HLEN + IP6_FRAG_HLEN)) & IP6_FRAG_OFFSET_MASK; - - while (left) { - last = (left <= nfb); - - /* Fill this fragment */ - cop = last ? left : nfb; - - /* When not using a static buffer, create a chain of pbufs. - * The first will be a PBUF_RAM holding the link, IPv6, and Fragment header. - * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, - * but limited to the size of an mtu. - */ - rambuf = pbuf_alloc(PBUF_LINK, IP6_HLEN + IP6_FRAG_HLEN, PBUF_RAM); - if (rambuf == NULL) { - IP6_FRAG_STATS_INC(ip6_frag.memerr); - return ERR_MEM; - } - LWIP_ASSERT("this needs a pbuf in one piece!", - (p->len >= (IP6_HLEN + IP6_FRAG_HLEN))); - SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN); - ip6hdr = (struct ip6_hdr *)rambuf->payload; - frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN); - - /* Can just adjust p directly for needed offset. */ - p->payload = (u8_t *)p->payload + poff; - p->len -= poff; - p->tot_len -= poff; - - left_to_copy = cop; - while (left_to_copy) { - struct pbuf_custom_ref *pcr; - newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; - /* Is this pbuf already empty? */ - if (!newpbuflen) { - p = p->next; - continue; - } - pcr = ip6_frag_alloc_pbuf_custom_ref(); - if (pcr == NULL) { - pbuf_free(rambuf); - IP6_FRAG_STATS_INC(ip6_frag.memerr); - return ERR_MEM; - } - /* Mirror this pbuf, although we might not need all of it. */ - newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); - if (newpbuf == NULL) { - ip6_frag_free_pbuf_custom_ref(pcr); - pbuf_free(rambuf); - IP6_FRAG_STATS_INC(ip6_frag.memerr); - return ERR_MEM; - } - pbuf_ref(p); - pcr->original = p; - pcr->pc.custom_free_function = ip6_frag_free_pbuf_custom; - - /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain - * so that it is removed when pbuf_dechain is later called on rambuf. - */ - pbuf_cat(rambuf, newpbuf); - left_to_copy -= newpbuflen; - if (left_to_copy) { - p = p->next; - } - } - poff = newpbuflen; - - /* Set headers */ - frag_hdr->_nexth = original_ip6hdr->_nexth; - frag_hdr->reserved = 0; - frag_hdr->_fragment_offset = htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG)); - frag_hdr->_identification = htonl(identification); - - IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT); - IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN); - - /* No need for separate header pbuf - we allowed room for it in rambuf - * when allocated. - */ - IP6_FRAG_STATS_INC(ip6_frag.xmit); - netif->output_ip6(netif, rambuf, dest); - - /* Unfortunately we can't reuse rambuf - the hardware may still be - * using the buffer. Instead we free it (and the ensuing chain) and - * recreate it next time round the loop. If we're lucky the hardware - * will have already sent the packet, the free will really free, and - * there will be zero memory penalty. - */ - - pbuf_free(rambuf); - left -= cop; - fragment_offset += cop; - } - return ERR_OK; -} - -#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */ diff --git a/third_party/lwip/core/ipv6/mld6.c b/third_party/lwip/core/ipv6/mld6.c deleted file mode 100644 index ce6e732..0000000 --- a/third_party/lwip/core/ipv6/mld6.c +++ /dev/null @@ -1,581 +0,0 @@ -/** - * @file - * - * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. - * No support for MLDv2. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * 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: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -/* Based on igmp.c implementation of igmp v2 protocol */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 && LWIP_IPV6_MLD /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/mld6.h" -#include "lwip/icmp6.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/ip.h" -#include "lwip/inet_chksum.h" -#include "lwip/pbuf.h" -#include "lwip/netif.h" -#include "lwip/memp.h" -#include "lwip/stats.h" - -#include - - -/* - * MLD constants - */ -#define MLD6_HL 1 -#define MLD6_JOIN_DELAYING_MEMBER_TMR_MS (500) - -#define MLD6_GROUP_NON_MEMBER 0 -#define MLD6_GROUP_DELAYING_MEMBER 1 -#define MLD6_GROUP_IDLE_MEMBER 2 - - -/* The list of joined groups. */ -static struct mld_group* mld_group_list; - - -/* Forward declarations. */ -static struct mld_group * mld6_new_group(struct netif *ifp, ip6_addr_t *addr); -static err_t mld6_free_group(struct mld_group *group); -static void mld6_delayed_report(struct mld_group *group, u16_t maxresp); -static void mld6_send(struct mld_group *group, u8_t type); - - -/** - * Stop MLD processing on interface - * - * @param netif network interface on which stop MLD processing - */ -err_t -mld6_stop(struct netif *netif) -{ - struct mld_group *group = mld_group_list; - struct mld_group *prev = NULL; - struct mld_group *next; - - /* look for groups joined on this interface further down the list */ - while (group != NULL) { - next = group->next; - /* is it a group joined on this interface? */ - if (group->netif == netif) { - /* is it the first group of the list? */ - if (group == mld_group_list) { - mld_group_list = next; - } - /* is there a "previous" group defined? */ - if (prev != NULL) { - prev->next = next; - } - /* disable the group at the MAC level */ - if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, &(group->group_address), MLD6_DEL_MAC_FILTER); - } - /* free group */ - memp_free(MEMP_MLD6_GROUP, group); - } else { - /* change the "previous" */ - prev = group; - } - /* move to "next" */ - group = next; - } - return ERR_OK; -} - -/** - * Report MLD memberships for this interface - * - * @param netif network interface on which report MLD memberships - */ -void -mld6_report_groups(struct netif *netif) -{ - struct mld_group *group = mld_group_list; - - while (group != NULL) { - if (group->netif == netif) { - mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); - } - group = group->next; - } -} - -/** - * Search for a group that is joined on a netif - * - * @param ifp the network interface for which to look - * @param addr the group ipv6 address to search for - * @return a struct mld_group* if the group has been found, - * NULL if the group wasn't found. - */ -struct mld_group * -mld6_lookfor_group(struct netif *ifp, ip6_addr_t *addr) -{ - struct mld_group *group = mld_group_list; - - while (group != NULL) { - if ((group->netif == ifp) && (ip6_addr_cmp(&(group->group_address), addr))) { - return group; - } - group = group->next; - } - - return NULL; -} - - -/** - * create a new group - * - * @param ifp the network interface for which to create - * @param addr the new group ipv6 - * @return a struct mld_group*, - * NULL on memory error. - */ -static struct mld_group * -mld6_new_group(struct netif *ifp, ip6_addr_t *addr) -{ - struct mld_group *group; - - group = (struct mld_group *)memp_malloc(MEMP_MLD6_GROUP); - if (group != NULL) { - group->netif = ifp; - ip6_addr_set(&(group->group_address), addr); - group->timer = 0; /* Not running */ - group->group_state = MLD6_GROUP_IDLE_MEMBER; - group->last_reporter_flag = 0; - group->use = 0; - group->next = mld_group_list; - - mld_group_list = group; - } - - return group; -} - -/** - * Remove a group in the mld_group_list and free - * - * @param group the group to remove - * @return ERR_OK if group was removed from the list, an err_t otherwise - */ -static err_t -mld6_free_group(struct mld_group *group) -{ - err_t err = ERR_OK; - - /* Is it the first group? */ - if (mld_group_list == group) { - mld_group_list = group->next; - } else { - /* look for group further down the list */ - struct mld_group *tmpGroup; - for (tmpGroup = mld_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) { - if (tmpGroup->next == group) { - tmpGroup->next = group->next; - break; - } - } - /* Group not find group */ - if (tmpGroup == NULL) - err = ERR_ARG; - } - /* free group */ - memp_free(MEMP_MLD6_GROUP, group); - - return err; -} - - -/** - * Process an input MLD message. Called by icmp6_input. - * - * @param p the mld packet, p->payload pointing to the icmpv6 header - * @param inp the netif on which this packet was received - */ -void -mld6_input(struct pbuf *p, struct netif *inp) -{ - struct mld_header * mld_hdr; - struct mld_group* group; - - MLD6_STATS_INC(mld6.recv); - - /* Check that mld header fits in packet. */ - if (p->len < sizeof(struct mld_header)) { - /* TODO debug message */ - pbuf_free(p); - MLD6_STATS_INC(mld6.lenerr); - MLD6_STATS_INC(mld6.drop); - return; - } - - mld_hdr = (struct mld_header *)p->payload; - - switch (mld_hdr->type) { - case ICMP6_TYPE_MLQ: /* Multicast listener query. */ - { - /* Is it a general query? */ - if (ip6_addr_isallnodes_linklocal(ip6_current_dest_addr()) && - ip6_addr_isany(&(mld_hdr->multicast_address))) { - MLD6_STATS_INC(mld6.rx_general); - /* Report all groups, except all nodes group, and if-local groups. */ - group = mld_group_list; - while (group != NULL) { - if ((group->netif == inp) && - (!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) && - (!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) { - mld6_delayed_report(group, mld_hdr->max_resp_delay); - } - group = group->next; - } - } - else { - /* Have we joined this group? - * We use IP6 destination address to have a memory aligned copy. - * mld_hdr->multicast_address should be the same. */ - MLD6_STATS_INC(mld6.rx_group); - group = mld6_lookfor_group(inp, ip6_current_dest_addr()); - if (group != NULL) { - /* Schedule a report. */ - mld6_delayed_report(group, mld_hdr->max_resp_delay); - } - } - break; /* ICMP6_TYPE_MLQ */ - } - case ICMP6_TYPE_MLR: /* Multicast listener report. */ - { - /* Have we joined this group? - * We use IP6 destination address to have a memory aligned copy. - * mld_hdr->multicast_address should be the same. */ - MLD6_STATS_INC(mld6.rx_report); - group = mld6_lookfor_group(inp, ip6_current_dest_addr()); - if (group != NULL) { - /* If we are waiting to report, cancel it. */ - if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { - group->timer = 0; /* stopped */ - group->group_state = MLD6_GROUP_IDLE_MEMBER; - group->last_reporter_flag = 0; - } - } - break; /* ICMP6_TYPE_MLR */ - } - case ICMP6_TYPE_MLD: /* Multicast listener done. */ - { - /* Do nothing, router will query us. */ - break; /* ICMP6_TYPE_MLD */ - } - default: - MLD6_STATS_INC(mld6.proterr); - MLD6_STATS_INC(mld6.drop); - break; - } - - pbuf_free(p); -} - -/** - * Join a group on a network interface. - * - * @param srcaddr ipv6 address of the network interface which should - * join a new group. If IP6_ADDR_ANY, join on all netifs - * @param groupaddr the ipv6 address of the group to join - * @return ERR_OK if group was joined on the netif(s), an err_t otherwise - */ -err_t -mld6_joingroup(ip6_addr_t *srcaddr, ip6_addr_t *groupaddr) -{ - err_t err = ERR_VAL; /* no matching interface */ - struct mld_group *group; - struct netif *netif; - u8_t match; - u8_t i; - - /* loop through netif's */ - netif = netif_list; - while (netif != NULL) { - /* Should we join this interface ? */ - match = 0; - if (ip6_addr_isany(srcaddr)) { - match = 1; - } - else { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_cmp(srcaddr, netif_ip6_addr(netif, i))) { - match = 1; - break; - } - } - } - if (match) { - /* find group or create a new one if not found */ - group = mld6_lookfor_group(netif, groupaddr); - - if (group == NULL) { - /* Joining a new group. Create a new group entry. */ - group = mld6_new_group(netif, groupaddr); - if (group == NULL) { - return ERR_MEM; - } - - /* Activate this address on the MAC layer. */ - if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, groupaddr, MLD6_ADD_MAC_FILTER); - } - - /* Report our membership. */ - MLD6_STATS_INC(mld6.tx_report); - mld6_send(group, ICMP6_TYPE_MLR); - mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); - } - - /* Increment group use */ - group->use++; - err = ERR_OK; - } - - /* proceed to next network interface */ - netif = netif->next; - } - - return err; -} - -/** - * Leave a group on a network interface. - * - * @param srcaddr ipv6 address of the network interface which should - * leave the group. If IP6_ISANY, leave on all netifs - * @param groupaddr the ipv6 address of the group to leave - * @return ERR_OK if group was left on the netif(s), an err_t otherwise - */ -err_t -mld6_leavegroup(ip6_addr_t *srcaddr, ip6_addr_t *groupaddr) -{ - err_t err = ERR_VAL; /* no matching interface */ - struct mld_group *group; - struct netif *netif; - u8_t match; - u8_t i; - - /* loop through netif's */ - netif = netif_list; - while (netif != NULL) { - /* Should we leave this interface ? */ - match = 0; - if (ip6_addr_isany(srcaddr)) { - match = 1; - } - else { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_cmp(srcaddr, netif_ip6_addr(netif, i))) { - match = 1; - break; - } - } - } - if (match) { - /* find group */ - group = mld6_lookfor_group(netif, groupaddr); - - if (group != NULL) { - /* Leave if there is no other use of the group */ - if (group->use <= 1) { - /* If we are the last reporter for this group */ - if (group->last_reporter_flag) { - MLD6_STATS_INC(mld6.tx_leave); - mld6_send(group, ICMP6_TYPE_MLD); - } - - /* Disable the group at the MAC level */ - if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, groupaddr, MLD6_DEL_MAC_FILTER); - } - - /* Free the group */ - mld6_free_group(group); - } else { - /* Decrement group use */ - group->use--; - } - /* Leave on this interface */ - err = ERR_OK; - } - } - /* proceed to next network interface */ - netif = netif->next; - } - - return err; -} - - -/** - * Periodic timer for mld processing. Must be called every - * MLD6_TMR_INTERVAL milliseconds (100). - * - * When a delaying member expires, a membership report is sent. - */ -void -mld6_tmr(void) -{ - struct mld_group *group = mld_group_list; - - while (group != NULL) { - if (group->timer > 0) { - group->timer--; - if (group->timer == 0) { - /* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report for this group */ - if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { - MLD6_STATS_INC(mld6.tx_report); - mld6_send(group, ICMP6_TYPE_MLR); - group->group_state = MLD6_GROUP_IDLE_MEMBER; - } - } - } - group = group->next; - } -} - -/** - * Schedule a delayed membership report for a group - * - * @param group the mld_group for which "delaying" membership report - * should be sent - * @param maxresp the max resp delay provided in the query - */ -static void -mld6_delayed_report(struct mld_group *group, u16_t maxresp) -{ - /* Convert maxresp from milliseconds to tmr ticks */ - maxresp = maxresp / MLD6_TMR_INTERVAL; - if (maxresp == 0) { - maxresp = 1; - } - -#ifdef LWIP_RAND - /* Randomize maxresp. (if LWIP_RAND is supported) */ - maxresp = (LWIP_RAND() % (maxresp - 1)) + 1; -#endif /* LWIP_RAND */ - - /* Apply timer value if no report has been scheduled already. */ - if ((group->group_state == MLD6_GROUP_IDLE_MEMBER) || - ((group->group_state == MLD6_GROUP_DELAYING_MEMBER) && - ((group->timer == 0) || (maxresp < group->timer)))) { - group->timer = maxresp; - group->group_state = MLD6_GROUP_DELAYING_MEMBER; - } -} - -/** - * Send a MLD message (report or done). - * - * An IPv6 hop-by-hop options header with a router alert option - * is prepended. - * - * @param group the group to report or quit - * @param type ICMP6_TYPE_MLR (report) or ICMP6_TYPE_MLD (done) - */ -static void -mld6_send(struct mld_group *group, u8_t type) -{ - struct mld_header * mld_hdr; - struct pbuf * p; - ip6_addr_t * src_addr; - - /* Allocate a packet. Size is MLD header + IPv6 Hop-by-hop options header. */ - p = pbuf_alloc(PBUF_IP, sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr), PBUF_RAM); - if ((p == NULL) || (p->len < (sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr)))) { - /* We couldn't allocate a suitable pbuf. drop it. */ - if (p != NULL) { - pbuf_free(p); - } - MLD6_STATS_INC(mld6.memerr); - return; - } - - /* Move to make room for Hop-by-hop options header. */ - if (pbuf_header(p, -IP6_HBH_HLEN)) { - pbuf_free(p); - MLD6_STATS_INC(mld6.lenerr); - return; - } - - /* Select our source address. */ - if (!ip6_addr_isvalid(netif_ip6_addr_state(group->netif, 0))) { - /* This is a special case, when we are performing duplicate address detection. - * We must join the multicast group, but we don't have a valid address yet. */ - src_addr = IP6_ADDR_ANY; - } else { - /* Use link-local address as source address. */ - src_addr = netif_ip6_addr(group->netif, 0); - } - - /* MLD message header pointer. */ - mld_hdr = (struct mld_header *)p->payload; - - /* Set fields. */ - mld_hdr->type = type; - mld_hdr->code = 0; - mld_hdr->chksum = 0; - mld_hdr->max_resp_delay = 0; - mld_hdr->reserved = 0; - ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address)); - - mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, - src_addr, &(group->group_address)); - - /* Add hop-by-hop headers options: router alert with MLD value. */ - ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD); - - /* Send the packet out. */ - MLD6_STATS_INC(mld6.xmit); - ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address), - MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, group->netif); - pbuf_free(p); -} - - - -#endif /* LWIP_IPV6 */ diff --git a/third_party/lwip/core/ipv6/nd6.c b/third_party/lwip/core/ipv6/nd6.c deleted file mode 100644 index d5855fb..0000000 --- a/third_party/lwip/core/ipv6/nd6.c +++ /dev/null @@ -1,1786 +0,0 @@ -/** - * @file - * - * Neighbor discovery and stateless address autoconfiguration for IPv6. - * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 - * (Address autoconfiguration). - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * 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: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/nd6.h" -#include "lwip/pbuf.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/icmp6.h" -#include "lwip/mld6.h" -#include "lwip/ip.h" -#include "lwip/stats.h" - -#include - - -/* Router tables. */ -struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS]; -struct nd6_destination_cache_entry destination_cache[LWIP_ND6_NUM_DESTINATIONS]; -struct nd6_prefix_list_entry prefix_list[LWIP_ND6_NUM_PREFIXES]; -struct nd6_router_list_entry default_router_list[LWIP_ND6_NUM_ROUTERS]; - -/* Default values, can be updated by a RA message. */ -u32_t reachable_time = LWIP_ND6_REACHABLE_TIME; -u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER; /* TODO implement this value in timer */ - -/* Index for cache entries. */ -static u8_t nd6_cached_neighbor_index; -static u8_t nd6_cached_destination_index; - -/* Multicast address holder. */ -static ip6_addr_t multicast_address; - -/* Static buffer to parse RA packet options (size of a prefix option, biggest option) */ -static u8_t nd6_ra_buffer[sizeof(struct prefix_option)]; - -/* Forward declarations. */ -static s8_t nd6_find_neighbor_cache_entry(ip6_addr_t * ip6addr); -static s8_t nd6_new_neighbor_cache_entry(void); -static void nd6_free_neighbor_cache_entry(s8_t i); -static s8_t nd6_find_destination_cache_entry(ip6_addr_t * ip6addr); -static s8_t nd6_new_destination_cache_entry(void); -static s8_t nd6_is_prefix_in_netif(ip6_addr_t * ip6addr, struct netif * netif); -static s8_t nd6_get_router(ip6_addr_t * router_addr, struct netif * netif); -static s8_t nd6_new_router(ip6_addr_t * router_addr, struct netif * netif); -static s8_t nd6_get_onlink_prefix(ip6_addr_t * prefix, struct netif * netif); -static s8_t nd6_new_onlink_prefix(ip6_addr_t * prefix, struct netif * netif); - -#define ND6_SEND_FLAG_MULTICAST_DEST 0x01 -#define ND6_SEND_FLAG_ALLNODES_DEST 0x02 -static void nd6_send_ns(struct netif * netif, ip6_addr_t * target_addr, u8_t flags); -static void nd6_send_na(struct netif * netif, ip6_addr_t * target_addr, u8_t flags); -#if LWIP_IPV6_SEND_ROUTER_SOLICIT -static void nd6_send_rs(struct netif * netif); -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ - -#if LWIP_ND6_QUEUEING -static void nd6_free_q(struct nd6_q_entry *q); -#else /* LWIP_ND6_QUEUEING */ -#define nd6_free_q(q) pbuf_free(q) -#endif /* LWIP_ND6_QUEUEING */ -static void nd6_send_q(s8_t i); - - -/** - * Process an incoming neighbor discovery message - * - * @param p the nd packet, p->payload pointing to the icmpv6 header - * @param inp the netif on which this packet was received - */ -void -nd6_input(struct pbuf *p, struct netif *inp) -{ - u8_t msg_type; - s8_t i; - - ND6_STATS_INC(nd6.recv); - - msg_type = *((u8_t *)p->payload); - switch (msg_type) { - case ICMP6_TYPE_NA: /* Neighbor Advertisement. */ - { - struct na_header * na_hdr; - struct lladdr_option * lladdr_opt; - - /* Check that na header fits in packet. */ - if (p->len < (sizeof(struct na_header))) { - /* TODO debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - na_hdr = (struct na_header *)p->payload; - - /* Unsolicited NA?*/ - if (ip6_addr_ismulticast(ip6_current_dest_addr())) { - /* This is an unsolicited NA. - * link-layer changed? - * part of DAD mechanism? */ - - /* Check that link-layer address option also fits in packet. */ - if (p->len < (sizeof(struct na_header) + sizeof(struct lladdr_option))) { - /* TODO debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); - - /* Override ip6_current_dest_addr() so that we have an aligned copy. */ - ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address)); - -#if LWIP_IPV6_DUP_DETECT_ATTEMPTS - /* If the target address matches this netif, it is a DAD response. */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { - /* We are using a duplicate address. */ - netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); - -#if LWIP_IPV6_MLD - /* Leave solicited node multicast group. */ - ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(inp, i)->addr[3]); - mld6_leavegroup(netif_ip6_addr(inp, i), &multicast_address); -#endif /* LWIP_IPV6_MLD */ - - - - -#if LWIP_IPV6_AUTOCONFIG - /* Check to see if this address was autoconfigured. */ - if (!ip6_addr_islinklocal(ip6_current_dest_addr())) { - i = nd6_get_onlink_prefix(ip6_current_dest_addr(), inp); - if (i >= 0) { - /* Mark this prefix as duplicate, so that we don't use it - * to generate this address again. */ - prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE; - } - } -#endif /* LWIP_IPV6_AUTOCONFIG */ - - pbuf_free(p); - return; - } - } -#endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */ - - /* This is an unsolicited NA, most likely there was a LLADDR change. */ - i = nd6_find_neighbor_cache_entry(ip6_current_dest_addr()); - if (i >= 0) { - if (na_hdr->flags & ND6_FLAG_OVERRIDE) { - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - } - } - } - else { - /* This is a solicited NA. - * neighbor address resolution response? - * neighbor unreachability detection response? */ - - /* Override ip6_current_dest_addr() so that we have an aligned copy. */ - ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address)); - - /* Find the cache entry corresponding to this na. */ - i = nd6_find_neighbor_cache_entry(ip6_current_dest_addr()); - if (i < 0) { - /* We no longer care about this target address. drop it. */ - pbuf_free(p); - return; - } - - /* Update cache entry. */ - neighbor_cache[i].netif = inp; - neighbor_cache[i].counter.reachable_time = reachable_time; - if ((na_hdr->flags & ND6_FLAG_OVERRIDE) || - (neighbor_cache[i].state == ND6_INCOMPLETE)) { - /* Check that link-layer address option also fits in packet. */ - if (p->len < (sizeof(struct na_header) + sizeof(struct lladdr_option))) { - /* TODO debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); - - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - } - neighbor_cache[i].state = ND6_REACHABLE; - - /* Send queued packets, if any. */ - if (neighbor_cache[i].q != NULL) { - nd6_send_q(i); - } - } - - break; /* ICMP6_TYPE_NA */ - } - case ICMP6_TYPE_NS: /* Neighbor solicitation. */ - { - struct ns_header * ns_hdr; - struct lladdr_option * lladdr_opt; - u8_t accepted; - - /* Check that ns header fits in packet. */ - if (p->len < sizeof(struct ns_header)) { - /* TODO debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - ns_hdr = (struct ns_header *)p->payload; - - /* Check if there is a link-layer address provided. Only point to it if in this buffer. */ - lladdr_opt = NULL; - if (p->len >= (sizeof(struct ns_header) + sizeof(struct lladdr_option))) { - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); - } - - /* Check if the target address is configured on the receiving netif. */ - accepted = 0; - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { - if ((ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) || - (ip6_addr_istentative(netif_ip6_addr_state(inp, i)) && - ip6_addr_isany(ip6_current_src_addr()))) && - ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { - accepted = 1; - break; - } - } - - /* NS not for us? */ - if (!accepted) { - pbuf_free(p); - return; - } - - /* Check for ANY address in src (DAD algorithm). */ - if (ip6_addr_isany(ip6_current_src_addr())) { - /* Sender is validating this address. */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { - if (ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { - /* Send a NA back so that the sender does not use this address. */ - nd6_send_na(inp, netif_ip6_addr(inp, i), ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST); - if (ip6_addr_istentative(netif_ip6_addr_state(inp, i))) { - /* We shouldn't use this address either. */ - netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); - } - } - } - } - else { - /* Sender is trying to resolve our address. */ - /* Verify that they included their own link-layer address. */ - if (lladdr_opt == NULL) { - /* Not a valid message. */ - pbuf_free(p); - ND6_STATS_INC(nd6.proterr); - ND6_STATS_INC(nd6.drop); - return; - } - - i = nd6_find_neighbor_cache_entry(ip6_current_src_addr()); - if ( i>= 0) { - /* We already have a record for the solicitor. */ - if (neighbor_cache[i].state == ND6_INCOMPLETE) { - neighbor_cache[i].netif = inp; - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - - /* Delay probe in case we get confirmation of reachability from upper layer (TCP). */ - neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; - } - } - else - { - /* Add their IPv6 address and link-layer address to neighbor cache. - * We will need it at least to send a unicast NA message, but most - * likely we will also be communicating with this node soon. */ - i = nd6_new_neighbor_cache_entry(); - if (i < 0) { - /* We couldn't assign a cache entry for this neighbor. - * we won't be able to reply. drop it. */ - pbuf_free(p); - ND6_STATS_INC(nd6.memerr); - return; - } - neighbor_cache[i].netif = inp; - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr()); - - /* Receiving a message does not prove reachability: only in one direction. - * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ - neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; - } - - /* Override ip6_current_dest_addr() so that we have an aligned copy. */ - ip6_addr_set(ip6_current_dest_addr(), &(ns_hdr->target_address)); - - /* Send back a NA for us. Allocate the reply pbuf. */ - nd6_send_na(inp, ip6_current_dest_addr(), ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE); - } - - break; /* ICMP6_TYPE_NS */ - } - case ICMP6_TYPE_RA: /* Router Advertisement. */ - { - struct ra_header * ra_hdr; - u8_t * buffer; /* Used to copy options. */ - u16_t offset; - - /* Check that RA header fits in packet. */ - if (p->len < sizeof(struct ra_header)) { - /* TODO debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - ra_hdr = (struct ra_header *)p->payload; - - /* If we are sending RS messages, stop. */ -#if LWIP_IPV6_SEND_ROUTER_SOLICIT - inp->rs_count = 0; -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ - - /* Get the matching default router entry. */ - i = nd6_get_router(ip6_current_src_addr(), inp); - if (i < 0) { - /* Create a new router entry. */ - i = nd6_new_router(ip6_current_src_addr(), inp); - } - - if (i < 0) { - /* Could not create a new router entry. */ - pbuf_free(p); - ND6_STATS_INC(nd6.memerr); - return; - } - - /* Re-set invalidation timer. */ - default_router_list[i].invalidation_timer = ra_hdr->router_lifetime; - - /* Re-set default timer values. */ -#if LWIP_ND6_ALLOW_RA_UPDATES - if (ra_hdr->retrans_timer > 0) { - retrans_timer = ra_hdr->retrans_timer; - } - if (ra_hdr->reachable_time > 0) { - reachable_time = ra_hdr->reachable_time; - } -#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ - - /* TODO set default hop limit... */ - /* ra_hdr->current_hop_limit;*/ - - /* Update flags in local entry (incl. preference). */ - default_router_list[i].flags = ra_hdr->flags; - - /* Offset to options. */ - offset = sizeof(struct ra_header); - - /* Process each option. */ - while ((p->tot_len - offset) > 0) { - if (p->len == p->tot_len) { - /* no need to copy from contiguous pbuf */ - buffer = &((u8_t*)p->payload)[offset]; - } else { - buffer = nd6_ra_buffer; - pbuf_copy_partial(p, buffer, sizeof(struct prefix_option), offset); - } - switch (buffer[0]) { - case ND6_OPTION_TYPE_SOURCE_LLADDR: - { - struct lladdr_option * lladdr_opt; - lladdr_opt = (struct lladdr_option *)buffer; - if ((default_router_list[i].neighbor_entry != NULL) && - (default_router_list[i].neighbor_entry->state == ND6_INCOMPLETE)) { - SMEMCPY(default_router_list[i].neighbor_entry->lladdr, lladdr_opt->addr, inp->hwaddr_len); - default_router_list[i].neighbor_entry->state = ND6_REACHABLE; - default_router_list[i].neighbor_entry->counter.reachable_time = reachable_time; - } - break; - } - case ND6_OPTION_TYPE_MTU: - { - struct mtu_option * mtu_opt; - mtu_opt = (struct mtu_option *)buffer; - if (mtu_opt->mtu >= 1280) { -#if LWIP_ND6_ALLOW_RA_UPDATES - inp->mtu = mtu_opt->mtu; -#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ - } - break; - } - case ND6_OPTION_TYPE_PREFIX_INFO: - { - struct prefix_option * prefix_opt; - prefix_opt = (struct prefix_option *)buffer; - - if (prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) { - /* Add to on-link prefix list. */ - - /* Get a memory-aligned copy of the prefix. */ - ip6_addr_set(ip6_current_dest_addr(), &(prefix_opt->prefix)); - - /* find cache entry for this prefix. */ - i = nd6_get_onlink_prefix(ip6_current_dest_addr(), inp); - if (i < 0) { - /* Create a new cache entry. */ - i = nd6_new_onlink_prefix(ip6_current_dest_addr(), inp); - } - if (i >= 0) { - prefix_list[i].invalidation_timer = prefix_opt->valid_lifetime; - -#if LWIP_IPV6_AUTOCONFIG - if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) { - /* Mark prefix as autonomous, so that address autoconfiguration can take place. - * Only OR flag, so that we don't over-write other flags (such as ADDRESS_DUPLICATE)*/ - prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_AUTONOMOUS; - } -#endif /* LWIP_IPV6_AUTOCONFIG */ - } - } - - break; - } - case ND6_OPTION_TYPE_ROUTE_INFO: - { - /* TODO implement preferred routes. - struct route_option * route_opt; - route_opt = (struct route_option *)buffer;*/ - - break; - } - default: - /* Unrecognized option, abort. */ - ND6_STATS_INC(nd6.proterr); - break; - } - offset += 8 * ((u16_t)buffer[1]); - } - - break; /* ICMP6_TYPE_RA */ - } - case ICMP6_TYPE_RD: /* Redirect */ - { - struct redirect_header * redir_hdr; - struct lladdr_option * lladdr_opt; - - /* Check that Redir header fits in packet. */ - if (p->len < sizeof(struct redirect_header)) { - /* TODO debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - redir_hdr = (struct redirect_header *)p->payload; - - lladdr_opt = NULL; - if (p->len >= (sizeof(struct redirect_header) + sizeof(struct lladdr_option))) { - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct redirect_header)); - } - - /* Copy original destination address to current source address, to have an aligned copy. */ - ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->destination_address)); - - /* Find dest address in cache */ - i = nd6_find_destination_cache_entry(ip6_current_src_addr()); - if (i < 0) { - /* Destination not in cache, drop packet. */ - pbuf_free(p); - return; - } - - /* Set the new target address. */ - ip6_addr_set(&(destination_cache[i].next_hop_addr), &(redir_hdr->target_address)); - - /* If Link-layer address of other router is given, try to add to neighbor cache. */ - if (lladdr_opt != NULL) { - if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) { - /* Copy target address to current source address, to have an aligned copy. */ - ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->target_address)); - - i = nd6_find_neighbor_cache_entry(ip6_current_src_addr()); - if (i < 0) { - i = nd6_new_neighbor_cache_entry(); - if (i >= 0) { - neighbor_cache[i].netif = inp; - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr()); - - /* Receiving a message does not prove reachability: only in one direction. - * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ - neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; - } - } - if (i >= 0) { - if (neighbor_cache[i].state == ND6_INCOMPLETE) { - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - /* Receiving a message does not prove reachability: only in one direction. - * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ - neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; - } - } - } - } - break; /* ICMP6_TYPE_RD */ - } - case ICMP6_TYPE_PTB: /* Packet too big */ - { - struct icmp6_hdr *icmp6hdr; /* Packet too big message */ - struct ip6_hdr * ip6hdr; /* IPv6 header of the packet which caused the error */ - - /* Check that ICMPv6 header + IPv6 header fit in payload */ - if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { - /* drop short packets */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - icmp6hdr = (struct icmp6_hdr *)p->payload; - ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); - - /* Copy original destination address to current source address, to have an aligned copy. */ - ip6_addr_set(ip6_current_src_addr(), &(ip6hdr->dest)); - - /* Look for entry in destination cache. */ - i = nd6_find_destination_cache_entry(ip6_current_src_addr()); - if (i < 0) { - /* Destination not in cache, drop packet. */ - pbuf_free(p); - return; - } - - /* Change the Path MTU. */ - destination_cache[i].pmtu = icmp6hdr->data; - - break; /* ICMP6_TYPE_PTB */ - } - - default: - ND6_STATS_INC(nd6.proterr); - ND6_STATS_INC(nd6.drop); - break; /* default */ - } - - pbuf_free(p); -} - - -/** - * Periodic timer for Neighbor discovery functions: - * - * - Update neighbor reachability states - * - Update destination cache entries age - * - Update invalidation timers of default routers and on-link prefixes - * - Perform duplicate address detection (DAD) for our addresses - * - Send router solicitations - */ -void -nd6_tmr(void) -{ - s8_t i, j; - struct netif * netif; - - /* Process neighbor entries. */ - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - switch (neighbor_cache[i].state) { - case ND6_INCOMPLETE: - if (neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) { - /* Retries exceeded. */ - nd6_free_neighbor_cache_entry(i); - } - else { - /* Send a NS for this entry. */ - neighbor_cache[i].counter.probes_sent++; - nd6_send_ns(neighbor_cache[i].netif, &(neighbor_cache[i].next_hop_address), ND6_SEND_FLAG_MULTICAST_DEST); - } - break; - case ND6_REACHABLE: - /* Send queued packets, if any are left. Should have been sent already. */ - if (neighbor_cache[i].q != NULL) { - nd6_send_q(i); - } - if (neighbor_cache[i].counter.reachable_time <= ND6_TMR_INTERVAL) { - /* Change to stale state. */ - neighbor_cache[i].state = ND6_STALE; - neighbor_cache[i].counter.stale_time = 0; - } - else { - neighbor_cache[i].counter.reachable_time -= ND6_TMR_INTERVAL; - } - break; - case ND6_STALE: - neighbor_cache[i].counter.stale_time += ND6_TMR_INTERVAL; - break; - case ND6_DELAY: - if (neighbor_cache[i].counter.delay_time <= ND6_TMR_INTERVAL) { - /* Change to PROBE state. */ - neighbor_cache[i].state = ND6_PROBE; - neighbor_cache[i].counter.probes_sent = 0; - } - else { - neighbor_cache[i].counter.delay_time -= ND6_TMR_INTERVAL; - } - break; - case ND6_PROBE: - if (neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) { - /* Retries exceeded. */ - nd6_free_neighbor_cache_entry(i); - } - else { - /* Send a NS for this entry. */ - neighbor_cache[i].counter.probes_sent++; - nd6_send_ns(neighbor_cache[i].netif, &(neighbor_cache[i].next_hop_address), 0); - } - break; - case ND6_NO_ENTRY: - default: - /* Do nothing. */ - break; - } - } - - /* Process destination entries. */ - for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { - destination_cache[i].age++; - } - - /* Process router entries. */ - for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { - if (default_router_list[i].neighbor_entry != NULL) { - /* Active entry. */ - if (default_router_list[i].invalidation_timer > 0) { - default_router_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; - } - if (default_router_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { - /* Less than 1 second remainig. Clear this entry. */ - default_router_list[i].neighbor_entry->isrouter = 0; - default_router_list[i].neighbor_entry = NULL; - default_router_list[i].invalidation_timer = 0; - default_router_list[i].flags = 0; - } - } - } - - /* Process prefix entries. */ - for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { - if (prefix_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { - prefix_list[i].invalidation_timer = 0; - } - if ((prefix_list[i].invalidation_timer > 0) && - (prefix_list[i].netif != NULL)) { - prefix_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; - -#if LWIP_IPV6_AUTOCONFIG - /* Initiate address autoconfiguration for this prefix, if conditions are met. */ - if (prefix_list[i].netif->ip6_autoconfig_enabled && - (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_AUTONOMOUS) && - !(prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED)) { - /* Try to get an address on this netif that is invalid. - * Skip 0 index (link-local address) */ - for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { - if (netif_ip6_addr_state(prefix_list[i].netif, j) == IP6_ADDRESS_STATE_INVALID) { - /* Generate an address using this prefix and interface ID from link-local address. */ - prefix_list[i].netif->ip6_addr[j].addr[0] = prefix_list[i].prefix.addr[0]; - prefix_list[i].netif->ip6_addr[j].addr[1] = prefix_list[i].prefix.addr[1]; - prefix_list[i].netif->ip6_addr[j].addr[2] = prefix_list[i].netif->ip6_addr[0].addr[2]; - prefix_list[i].netif->ip6_addr[j].addr[3] = prefix_list[i].netif->ip6_addr[0].addr[3]; - - /* Mark it as tentative (DAD will be performed if configured). */ - netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_TENTATIVE); - - /* Mark this prefix with ADDRESS_GENERATED, so that we don't try again. */ - prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED; - - /* Exit loop. */ - break; - } - } - } -#endif /* LWIP_IPV6_AUTOCONFIG */ - } - } - - - /* Process our own addresses, if DAD configured. */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { - if (ip6_addr_istentative(netif->ip6_addr_state[i])) { - if ((netif->ip6_addr_state[i] & 0x07) >= LWIP_IPV6_DUP_DETECT_ATTEMPTS) { - /* No NA received in response. Mark address as valid. */ - netif->ip6_addr_state[i] = IP6_ADDR_PREFERRED; - /* TODO implement preferred and valid lifetimes. */ - } - else if (netif->flags & NETIF_FLAG_UP) { -#if LWIP_IPV6_MLD - if ((netif->ip6_addr_state[i] & 0x07) == 0) { - /* Join solicited node multicast group. */ - ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, i)->addr[3]); - mld6_joingroup(netif_ip6_addr(netif, i), &multicast_address); - } -#endif /* LWIP_IPV6_MLD */ - /* Send a NS for this address. */ - nd6_send_ns(netif, netif_ip6_addr(netif, i), ND6_SEND_FLAG_MULTICAST_DEST); - (netif->ip6_addr_state[i])++; - /* TODO send max 1 NS per tmr call? enable return*/ - /*return;*/ - } - } - } - } - -#if LWIP_IPV6_SEND_ROUTER_SOLICIT - /* Send router solicitation messages, if necessary. */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - if ((netif->rs_count > 0) && (netif->flags & NETIF_FLAG_UP)) { - nd6_send_rs(netif); - netif->rs_count--; - } - } -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ - -} - -/** - * Send a neighbor solicitation message - * - * @param netif the netif on which to send the message - * @param target_addr the IPv6 target address for the ND message - * @param flags one of ND6_SEND_FLAG_* - */ -static void -nd6_send_ns(struct netif * netif, ip6_addr_t * target_addr, u8_t flags) -{ - struct ns_header * ns_hdr; - struct lladdr_option * lladdr_opt; - struct pbuf * p; - ip6_addr_t * src_addr; - - if (ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) { - /* Use link-local address as source address. */ - src_addr = netif_ip6_addr(netif, 0); - } else { - src_addr = IP6_ADDR_ANY; - } - - /* Allocate a packet. */ - p = pbuf_alloc(PBUF_IP, sizeof(struct ns_header) + sizeof(struct lladdr_option), PBUF_RAM); - if ((p == NULL) || (p->len < (sizeof(struct ns_header) + sizeof(struct lladdr_option)))) { - /* We couldn't allocate a suitable pbuf for the ns. drop it. */ - if (p != NULL) { - pbuf_free(p); - } - ND6_STATS_INC(nd6.memerr); - return; - } - - /* Set fields. */ - ns_hdr = (struct ns_header *)p->payload; - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); - - ns_hdr->type = ICMP6_TYPE_NS; - ns_hdr->code = 0; - ns_hdr->chksum = 0; - ns_hdr->reserved = 0; - ip6_addr_set(&(ns_hdr->target_address), target_addr); - - lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; - lladdr_opt->length = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); - SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); - - /* Generate the solicited node address for the target address. */ - if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { - ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); - target_addr = &multicast_address; - } - - ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, - target_addr); - - /* Send the packet out. */ - ND6_STATS_INC(nd6.xmit); - ip6_output_if(p, (src_addr == IP6_ADDR_ANY) ? NULL : src_addr, target_addr, - LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); - pbuf_free(p); -} - -/** - * Send a neighbor advertisement message - * - * @param netif the netif on which to send the message - * @param target_addr the IPv6 target address for the ND message - * @param flags one of ND6_SEND_FLAG_* - */ -static void -nd6_send_na(struct netif * netif, ip6_addr_t * target_addr, u8_t flags) -{ - struct na_header * na_hdr; - struct lladdr_option * lladdr_opt; - struct pbuf * p; - ip6_addr_t * src_addr; - ip6_addr_t * dest_addr; - - /* Use link-local address as source address. */ - /* src_addr = &(netif->ip6_addr[0]); */ - /* Use target address as source address. */ - src_addr = target_addr; - - /* Allocate a packet. */ - p = pbuf_alloc(PBUF_IP, sizeof(struct na_header) + sizeof(struct lladdr_option), PBUF_RAM); - if ((p == NULL) || (p->len < (sizeof(struct na_header) + sizeof(struct lladdr_option)))) { - /* We couldn't allocate a suitable pbuf for the ns. drop it. */ - if (p != NULL) { - pbuf_free(p); - } - ND6_STATS_INC(nd6.memerr); - return; - } - - /* Set fields. */ - na_hdr = (struct na_header *)p->payload; - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); - - na_hdr->type = ICMP6_TYPE_NA; - na_hdr->code = 0; - na_hdr->chksum = 0; - na_hdr->flags = flags & 0xf0; - na_hdr->reserved[0] = 0; - na_hdr->reserved[1] = 0; - na_hdr->reserved[2] = 0; - ip6_addr_set(&(na_hdr->target_address), target_addr); - - lladdr_opt->type = ND6_OPTION_TYPE_TARGET_LLADDR; - lladdr_opt->length = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); - SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); - - /* Generate the solicited node address for the target address. */ - if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { - ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); - dest_addr = &multicast_address; - } - else if (flags & ND6_SEND_FLAG_ALLNODES_DEST) { - ip6_addr_set_allnodes_linklocal(&multicast_address); - dest_addr = &multicast_address; - } - else { - dest_addr = ip6_current_src_addr(); - } - - na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, - dest_addr); - - /* Send the packet out. */ - ND6_STATS_INC(nd6.xmit); - ip6_output_if(p, src_addr, dest_addr, - LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); - pbuf_free(p); -} - -#if LWIP_IPV6_SEND_ROUTER_SOLICIT -/** - * Send a router solicitation message - * - * @param netif the netif on which to send the message - */ -static void -nd6_send_rs(struct netif * netif) -{ - struct rs_header * rs_hdr; - struct lladdr_option * lladdr_opt; - struct pbuf * p; - ip6_addr_t * src_addr; - u16_t packet_len; - - /* Link-local source address, or unspecified address? */ - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { - src_addr = netif_ip6_addr(netif, 0); - } - else { - src_addr = IP6_ADDR_ANY; - } - - /* Generate the all routers target address. */ - ip6_addr_set_allrouters_linklocal(&multicast_address); - - /* Allocate a packet. */ - packet_len = sizeof(struct rs_header); - if (src_addr != IP6_ADDR_ANY) { - packet_len += sizeof(struct lladdr_option); - } - p = pbuf_alloc(PBUF_IP, packet_len, PBUF_RAM); - if ((p == NULL) || (p->len < packet_len)) { - /* We couldn't allocate a suitable pbuf for the ns. drop it. */ - if (p != NULL) { - pbuf_free(p); - } - ND6_STATS_INC(nd6.memerr); - return; - } - - /* Set fields. */ - rs_hdr = (struct rs_header *)p->payload; - - rs_hdr->type = ICMP6_TYPE_RS; - rs_hdr->code = 0; - rs_hdr->chksum = 0; - rs_hdr->reserved = 0; - - if (src_addr != IP6_ADDR_ANY) { - /* Include our hw address. */ - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct rs_header)); - lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; - lladdr_opt->length = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); - SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); - } - - rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, - &multicast_address); - - /* Send the packet out. */ - ND6_STATS_INC(nd6.xmit); - ip6_output_if(p, src_addr, &multicast_address, - LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); - pbuf_free(p); -} -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ - -/** - * Search for a neighbor cache entry - * - * @param ip6addr the IPv6 address of the neighbor - * @return The neighbor cache entry index that matched, -1 if no - * entry is found - */ -static s8_t -nd6_find_neighbor_cache_entry(ip6_addr_t * ip6addr) -{ - s8_t i; - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if (ip6_addr_cmp(ip6addr, &(neighbor_cache[i].next_hop_address))) { - return i; - } - } - return -1; -} - -/** - * Create a new neighbor cache entry. - * - * If no unused entry is found, will try to recycle an old entry - * according to ad-hoc "age" heuristic. - * - * @return The neighbor cache entry index that was created, -1 if no - * entry could be created - */ -static s8_t -nd6_new_neighbor_cache_entry(void) -{ - s8_t i; - s8_t j; - u32_t time; - - - /* First, try to find an empty entry. */ - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if (neighbor_cache[i].state == ND6_NO_ENTRY) { - return i; - } - } - - /* We need to recycle an entry. in general, do not recycle if it is a router. */ - - /* Next, try to find a Stale entry. */ - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ((neighbor_cache[i].state == ND6_STALE) && - (!neighbor_cache[i].isrouter)) { - nd6_free_neighbor_cache_entry(i); - return i; - } - } - - /* Next, try to find a Probe entry. */ - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ((neighbor_cache[i].state == ND6_PROBE) && - (!neighbor_cache[i].isrouter)) { - nd6_free_neighbor_cache_entry(i); - return i; - } - } - - /* Next, try to find a Delayed entry. */ - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ((neighbor_cache[i].state == ND6_DELAY) && - (!neighbor_cache[i].isrouter)) { - nd6_free_neighbor_cache_entry(i); - return i; - } - } - - /* Next, try to find the oldest reachable entry. */ - time = 0xfffffffful; - j = -1; - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ((neighbor_cache[i].state == ND6_REACHABLE) && - (!neighbor_cache[i].isrouter)) { - if (neighbor_cache[i].counter.reachable_time < time) { - j = i; - time = neighbor_cache[i].counter.reachable_time; - } - } - } - if (j >= 0) { - nd6_free_neighbor_cache_entry(j); - return j; - } - - /* Next, find oldest incomplete entry without queued packets. */ - time = 0; - j = -1; - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ( - (neighbor_cache[i].q == NULL) && - (neighbor_cache[i].state == ND6_INCOMPLETE) && - (!neighbor_cache[i].isrouter)) { - if (neighbor_cache[i].counter.probes_sent >= time) { - j = i; - time = neighbor_cache[i].counter.probes_sent; - } - } - } - if (j >= 0) { - nd6_free_neighbor_cache_entry(j); - return j; - } - - /* Next, find oldest incomplete entry with queued packets. */ - time = 0; - j = -1; - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ((neighbor_cache[i].state == ND6_INCOMPLETE) && - (!neighbor_cache[i].isrouter)) { - if (neighbor_cache[i].counter.probes_sent >= time) { - j = i; - time = neighbor_cache[i].counter.probes_sent; - } - } - } - if (j >= 0) { - nd6_free_neighbor_cache_entry(j); - return j; - } - - /* No more entries to try. */ - return -1; -} - -/** - * Will free any resources associated with a neighbor cache - * entry, and will mark it as unused. - * - * @param i the neighbor cache entry index to free - */ -static void -nd6_free_neighbor_cache_entry(s8_t i) -{ - if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { - return; - } - - /* Free any queued packets. */ - if (neighbor_cache[i].q != NULL) { - nd6_free_q(neighbor_cache[i].q); - neighbor_cache[i].q = NULL; - } - - neighbor_cache[i].state = ND6_NO_ENTRY; - neighbor_cache[i].isrouter = 0; - neighbor_cache[i].netif = NULL; - neighbor_cache[i].counter.reachable_time = 0; - ip6_addr_set_zero(&(neighbor_cache[i].next_hop_address)); -} - -/** - * Search for a destination cache entry - * - * @param ip6addr the IPv6 address of the destination - * @return The destination cache entry index that matched, -1 if no - * entry is found - */ -static s8_t -nd6_find_destination_cache_entry(ip6_addr_t * ip6addr) -{ - s8_t i; - for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { - if (ip6_addr_cmp(ip6addr, &(destination_cache[i].destination_addr))) { - return i; - } - } - return -1; -} - -/** - * Create a new destination cache entry. If no unused entry is found, - * will recycle oldest entry. - * - * @return The destination cache entry index that was created, -1 if no - * entry was created - */ -static s8_t -nd6_new_destination_cache_entry(void) -{ - s8_t i, j; - u32_t age; - - /* Find an empty entry. */ - for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { - if (ip6_addr_isany(&(destination_cache[i].destination_addr))) { - return i; - } - } - - /* Find oldest entry. */ - age = 0; - j = LWIP_ND6_NUM_DESTINATIONS - 1; - for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { - if (destination_cache[i].age > age) { - j = i; - } - } - - return j; -} - -/** - * Determine whether an address matches an on-link prefix. - * - * @param ip6addr the IPv6 address to match - * @return 1 if the address is on-link, 0 otherwise - */ -static s8_t -nd6_is_prefix_in_netif(ip6_addr_t * ip6addr, struct netif * netif) -{ - s8_t i; - for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { - if ((prefix_list[i].netif == netif) && - (prefix_list[i].invalidation_timer > 0) && - ip6_addr_netcmp(ip6addr, &(prefix_list[i].prefix))) { - return 1; - } - } - /* Check to see if address prefix matches a (manually?) configured address. */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_netcmp(ip6addr, netif_ip6_addr(netif, i))) { - return 1; - } - } - return 0; -} - -/** - * Select a default router for a destination. - * - * @param ip6addr the destination address - * @param netif the netif for the outgoing packet, if known - * @return the default router entry index, or -1 if no suitable - * router is found - */ -s8_t -nd6_select_router(ip6_addr_t * ip6addr, struct netif * netif) -{ - s8_t i; - /* last_router is used for round-robin router selection (as recommended - * in RFC). This is more robust in case one router is not reachable, - * we are not stuck trying to resolve it. */ - static s8_t last_router; - (void)ip6addr; /* TODO match preferred routes!! (must implement ND6_OPTION_TYPE_ROUTE_INFO) */ - - /* TODO: implement default router preference */ - - /* Look for reachable routers. */ - for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { - if (++last_router >= LWIP_ND6_NUM_ROUTERS) { - last_router = 0; - } - if ((default_router_list[i].neighbor_entry != NULL) && - (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && - (default_router_list[i].invalidation_timer > 0) && - (default_router_list[i].neighbor_entry->state == ND6_REACHABLE)) { - return i; - } - } - - /* Look for router in other reachability states, but still valid according to timer. */ - for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { - if (++last_router >= LWIP_ND6_NUM_ROUTERS) { - last_router = 0; - } - if ((default_router_list[i].neighbor_entry != NULL) && - (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && - (default_router_list[i].invalidation_timer > 0)) { - return i; - } - } - - /* Look for any router for which we have any information at all. */ - for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { - if (++last_router >= LWIP_ND6_NUM_ROUTERS) { - last_router = 0; - } - if (default_router_list[i].neighbor_entry != NULL && - (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1)) { - return i; - } - } - - /* no suitable router found. */ - return -1; -} - -/** - * Find an entry for a default router. - * - * @param router_addr the IPv6 address of the router - * @param netif the netif on which the router is found, if known - * @return the index of the router entry, or -1 if not found - */ -static s8_t -nd6_get_router(ip6_addr_t * router_addr, struct netif * netif) -{ - s8_t i; - - /* Look for router. */ - for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { - if ((default_router_list[i].neighbor_entry != NULL) && - ((netif != NULL) ? netif == default_router_list[i].neighbor_entry->netif : 1) && - ip6_addr_cmp(router_addr, &(default_router_list[i].neighbor_entry->next_hop_address))) { - return i; - } - } - - /* router not found. */ - return -1; -} - -/** - * Create a new entry for a default router. - * - * @param router_addr the IPv6 address of the router - * @param netif the netif on which the router is connected, if known - * @return the index on the router table, or -1 if could not be created - */ -static s8_t -nd6_new_router(ip6_addr_t * router_addr, struct netif * netif) -{ - s8_t router_index; - s8_t neighbor_index; - - /* Do we have a neighbor entry for this router? */ - neighbor_index = nd6_find_neighbor_cache_entry(router_addr); - if (neighbor_index < 0) { - /* Create a neighbor entry for this router. */ - neighbor_index = nd6_new_neighbor_cache_entry(); - if (neighbor_index < 0) { - /* Could not create neighbor entry for this router. */ - return -1; - } - ip6_addr_set(&(neighbor_cache[neighbor_index].next_hop_address), router_addr); - neighbor_cache[neighbor_index].netif = netif; - neighbor_cache[neighbor_index].q = NULL; - neighbor_cache[neighbor_index].state = ND6_INCOMPLETE; - neighbor_cache[neighbor_index].counter.probes_sent = 0; - } - - /* Mark neighbor as router. */ - neighbor_cache[neighbor_index].isrouter = 1; - - /* Look for empty entry. */ - for (router_index = 0; router_index < LWIP_ND6_NUM_ROUTERS; router_index++) { - if (default_router_list[router_index].neighbor_entry == NULL) { - default_router_list[router_index].neighbor_entry = &(neighbor_cache[neighbor_index]); - return router_index; - } - } - - /* Could not create a router entry. */ - - /* Mark neighbor entry as not-router. Entry might be useful as neighbor still. */ - neighbor_cache[neighbor_index].isrouter = 0; - - /* router not found. */ - return -1; -} - -/** - * Find the cached entry for an on-link prefix. - * - * @param prefix the IPv6 prefix that is on-link - * @param netif the netif on which the prefix is on-link - * @return the index on the prefix table, or -1 if not found - */ -static s8_t -nd6_get_onlink_prefix(ip6_addr_t * prefix, struct netif * netif) -{ - s8_t i; - - /* Look for prefix in list. */ - for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { - if ((ip6_addr_netcmp(&(prefix_list[i].prefix), prefix)) && - (prefix_list[i].netif == netif)) { - return i; - } - } - - /* Entry not available. */ - return -1; -} - -/** - * Creates a new entry for an on-link prefix. - * - * @param prefix the IPv6 prefix that is on-link - * @param netif the netif on which the prefix is on-link - * @return the index on the prefix table, or -1 if not created - */ -static s8_t -nd6_new_onlink_prefix(ip6_addr_t * prefix, struct netif * netif) -{ - s8_t i; - - /* Create new entry. */ - for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { - if ((prefix_list[i].netif == NULL) || - (prefix_list[i].invalidation_timer == 0)) { - /* Found empty prefix entry. */ - prefix_list[i].netif = netif; - ip6_addr_set(&(prefix_list[i].prefix), prefix); - prefix_list[i].flags = 0; - return i; - } - } - - /* Entry not available. */ - return -1; -} - -/** - * Determine the next hop for a destination. Will determine if the - * destination is on-link, else a suitable on-link router is selected. - * - * The last entry index is cached for fast entry search. - * - * @param ip6addr the destination address - * @param netif the netif on which the packet will be sent - * @return the neighbor cache entry for the next hop, ERR_RTE if no - * suitable next hop was found, ERR_MEM if no cache entry - * could be created - */ -s8_t -nd6_get_next_hop_entry(ip6_addr_t * ip6addr, struct netif * netif) -{ - s8_t i; - -#if LWIP_NETIF_HWADDRHINT - if (netif->addr_hint != NULL) { - /* per-pcb cached entry was given */ - u8_t addr_hint = *(netif->addr_hint); - if (addr_hint < LWIP_ND6_NUM_DESTINATIONS) { - nd6_cached_destination_index = addr_hint; - } - } -#endif /* LWIP_NETIF_HWADDRHINT */ - - /* Look for ip6addr in destination cache. */ - if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { - /* the cached entry index is the right one! */ - /* do nothing. */ - ND6_STATS_INC(nd6.cachehit); - } else { - /* Search destination cache. */ - i = nd6_find_destination_cache_entry(ip6addr); - if (i >= 0) { - /* found destination entry. make it our new cached index. */ - nd6_cached_destination_index = i; - } - else { - /* Not found. Create a new destination entry. */ - i = nd6_new_destination_cache_entry(); - if (i >= 0) { - /* got new destination entry. make it our new cached index. */ - nd6_cached_destination_index = i; - } else { - /* Could not create a destination cache entry. */ - return ERR_MEM; - } - - /* Copy dest address to destination cache. */ - ip6_addr_set(&(destination_cache[nd6_cached_destination_index].destination_addr), ip6addr); - - /* Now find the next hop. is it a neighbor? */ - if (ip6_addr_islinklocal(ip6addr) || - nd6_is_prefix_in_netif(ip6addr, netif)) { - /* Destination in local link. */ - destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; - ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr); - } - else { - /* We need to select a router. */ - i = nd6_select_router(ip6addr, netif); - if (i < 0) { - /* No router found. */ - ip6_addr_set_any(&(destination_cache[nd6_cached_destination_index].destination_addr)); - return ERR_RTE; - } - destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; /* Start with netif mtu, correct through ICMPv6 if necessary */ - ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, default_router_list[i].neighbor_entry->next_hop_address); - } - } - } - -#if LWIP_NETIF_HWADDRHINT - if (netif->addr_hint != NULL) { - /* per-pcb cached entry was given */ - *(netif->addr_hint) = nd6_cached_destination_index; - } -#endif /* LWIP_NETIF_HWADDRHINT */ - - /* Look in neighbor cache for the next-hop address. */ - if (ip6_addr_cmp(&(destination_cache[nd6_cached_destination_index].next_hop_addr), - &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { - /* Cache hit. */ - /* Do nothing. */ - ND6_STATS_INC(nd6.cachehit); - } else { - i = nd6_find_neighbor_cache_entry(&(destination_cache[nd6_cached_destination_index].next_hop_addr)); - if (i >= 0) { - /* Found a matching record, make it new cached entry. */ - nd6_cached_neighbor_index = i; - } - else { - /* Neighbor not in cache. Make a new entry. */ - i = nd6_new_neighbor_cache_entry(); - if (i >= 0) { - /* got new neighbor entry. make it our new cached index. */ - nd6_cached_neighbor_index = i; - } else { - /* Could not create a neighbor cache entry. */ - return ERR_MEM; - } - - /* Initialize fields. */ - ip6_addr_copy(neighbor_cache[i].next_hop_address, - destination_cache[nd6_cached_destination_index].next_hop_addr); - neighbor_cache[i].isrouter = 0; - neighbor_cache[i].netif = netif; - neighbor_cache[i].state = ND6_INCOMPLETE; - neighbor_cache[i].counter.probes_sent = 0; - } - } - - /* Reset this destination's age. */ - destination_cache[nd6_cached_destination_index].age = 0; - - return nd6_cached_neighbor_index; -} - -/** - * Queue a packet for a neighbor. - * - * @param neighbor_index the index in the neighbor cache table - * @param q packet to be queued - * @return ERR_OK if succeeded, ERR_MEM if out of memory - */ -err_t -nd6_queue_packet(s8_t neighbor_index, struct pbuf * q) -{ - err_t result = ERR_MEM; - struct pbuf *p; - int copy_needed = 0; -#if LWIP_ND6_QUEUEING - struct nd6_q_entry *new_entry, *r; -#endif /* LWIP_ND6_QUEUEING */ - - if ((neighbor_index < 0) || (neighbor_index >= LWIP_ND6_NUM_NEIGHBORS)) { - return ERR_ARG; - } - - /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but - * to copy the whole queue into a new PBUF_RAM (see bug #11400) - * PBUF_ROMs can be left as they are, since ROM must not get changed. */ - p = q; - while (p) { - if(p->type != PBUF_ROM) { - copy_needed = 1; - break; - } - p = p->next; - } - if(copy_needed) { - /* copy the whole packet into new pbufs */ - p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); - while ((p == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { - /* Free oldest packet (as per RFC recommendation) */ -#if LWIP_ND6_QUEUEING - r = neighbor_cache[neighbor_index].q; - neighbor_cache[neighbor_index].q = r->next; - r->next = NULL; - nd6_free_q(r); -#else /* LWIP_ND6_QUEUEING */ - pbuf_free(neighbor_cache[neighbor_index].q); - neighbor_cache[neighbor_index].q = NULL; -#endif /* LWIP_ND6_QUEUEING */ - p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); - } - if(p != NULL) { - if (pbuf_copy(p, q) != ERR_OK) { - pbuf_free(p); - p = NULL; - } - } - } else { - /* referencing the old pbuf is enough */ - p = q; - pbuf_ref(p); - } - /* packet was copied/ref'd? */ - if (p != NULL) { - /* queue packet ... */ -#if LWIP_ND6_QUEUEING - /* allocate a new nd6 queue entry */ - new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); - if ((new_entry == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { - /* Free oldest packet (as per RFC recommendation) */ - r = neighbor_cache[neighbor_index].q; - neighbor_cache[neighbor_index].q = r->next; - r->next = NULL; - nd6_free_q(r); - new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); - } - if (new_entry != NULL) { - new_entry->next = NULL; - new_entry->p = p; - if(neighbor_cache[neighbor_index].q != NULL) { - /* queue was already existent, append the new entry to the end */ - r = neighbor_cache[neighbor_index].q; - while (r->next != NULL) { - r = r->next; - } - r->next = new_entry; - } else { - /* queue did not exist, first item in queue */ - neighbor_cache[neighbor_index].q = new_entry; - } - LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); - result = ERR_OK; - } else { - /* the pool MEMP_ND6_QUEUE is empty */ - pbuf_free(p); - LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)p)); - /* { result == ERR_MEM } through initialization */ - } -#else /* LWIP_ND6_QUEUEING */ - /* Queue a single packet. If an older packet is already queued, free it as per RFC. */ - if (neighbor_cache[neighbor_index].q != NULL) { - pbuf_free(neighbor_cache[neighbor_index].q); - } - neighbor_cache[neighbor_index].q = p; - LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); - result = ERR_OK; -#endif /* LWIP_ND6_QUEUEING */ - } else { - LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)q)); - /* { result == ERR_MEM } through initialization */ - } - - return result; -} - -#if LWIP_ND6_QUEUEING -/** - * Free a complete queue of nd6 q entries - * - * @param q a queue of nd6_q_entry to free - */ -static void -nd6_free_q(struct nd6_q_entry *q) -{ - struct nd6_q_entry *r; - LWIP_ASSERT("q != NULL", q != NULL); - LWIP_ASSERT("q->p != NULL", q->p != NULL); - while (q) { - r = q; - q = q->next; - LWIP_ASSERT("r->p != NULL", (r->p != NULL)); - pbuf_free(r->p); - memp_free(MEMP_ND6_QUEUE, r); - } -} -#endif /* LWIP_ND6_QUEUEING */ - -/** - * Send queued packets for a neighbor - * - * @param i the neighbor to send packets to - */ -static void -nd6_send_q(s8_t i) -{ - struct ip6_hdr *ip6hdr; -#if LWIP_ND6_QUEUEING - struct nd6_q_entry *q; -#endif /* LWIP_ND6_QUEUEING */ - - if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { - return; - } - -#if LWIP_ND6_QUEUEING - while (neighbor_cache[i].q != NULL) { - /* remember first in queue */ - q = neighbor_cache[i].q; - /* pop first item off the queue */ - neighbor_cache[i].q = q->next; - /* Get ipv6 header. */ - ip6hdr = (struct ip6_hdr *)(q->p->payload); - /* Override ip6_current_dest_addr() so that we have an aligned copy. */ - ip6_addr_set(ip6_current_dest_addr(), &(ip6hdr->dest)); - /* send the queued IPv6 packet */ - (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, ip6_current_dest_addr()); - /* free the queued IP packet */ - pbuf_free(q->p); - /* now queue entry can be freed */ - memp_free(MEMP_ND6_QUEUE, q); - } -#else /* LWIP_ND6_QUEUEING */ - if (neighbor_cache[i].q != NULL) { - /* Get ipv6 header. */ - ip6hdr = (struct ip6_hdr *)(neighbor_cache[i].q->payload); - /* Override ip6_current_dest_addr() so that we have an aligned copy. */ - ip6_addr_set(ip6_current_dest_addr(), &(ip6hdr->dest)); - /* send the queued IPv6 packet */ - (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, ip6_current_dest_addr()); - /* free the queued IP packet */ - pbuf_free(neighbor_cache[i].q); - neighbor_cache[i].q = NULL; - } -#endif /* LWIP_ND6_QUEUEING */ -} - - -/** - * Get the Path MTU for a destination. - * - * @param ip6addr the destination address - * @param netif the netif on which the packet will be sent - * @return the Path MTU, if known, or the netif default MTU - */ -u16_t -nd6_get_destination_mtu(ip6_addr_t * ip6addr, struct netif * netif) -{ - s8_t i; - - i = nd6_find_destination_cache_entry(ip6addr); - if (i >= 0) { - if (destination_cache[i].pmtu > 0) { - return destination_cache[i].pmtu; - } - } - - if (netif != NULL) { - return netif->mtu; - } - - return 1280; /* Minimum MTU */ -} - - -#if LWIP_ND6_TCP_REACHABILITY_HINTS -/** - * Provide the Neighbor discovery process with a hint that a - * destination is reachable. Called by tcp_receive when ACKs are - * received or sent (as per RFC). This is useful to avoid sending - * NS messages every 30 seconds. - * - * @param ip6addr the destination address which is know to be reachable - * by an upper layer protocol (TCP) - */ -void -nd6_reachability_hint(ip6_addr_t * ip6addr) -{ - s8_t i; - - /* Find destination in cache. */ - if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { - i = nd6_cached_destination_index; - ND6_STATS_INC(nd6.cachehit); - } - else { - i = nd6_find_destination_cache_entry(ip6addr); - } - if (i < 0) { - return; - } - - /* Find next hop neighbor in cache. */ - if (ip6_addr_cmp(&(destination_cache[i].next_hop_addr), &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { - i = nd6_cached_neighbor_index; - ND6_STATS_INC(nd6.cachehit); - } - else { - i = nd6_find_neighbor_cache_entry(&(destination_cache[i].next_hop_addr)); - } - if (i < 0) { - return; - } - - /* Set reachability state. */ - neighbor_cache[i].state = ND6_REACHABLE; - neighbor_cache[i].counter.reachable_time = reachable_time; -} -#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ - -#endif /* LWIP_IPV6 */ diff --git a/third_party/lwip/core/mem.c b/third_party/lwip/core/mem.c deleted file mode 100644 index 3375255..0000000 --- a/third_party/lwip/core/mem.c +++ /dev/null @@ -1,660 +0,0 @@ -/** - * @file - * Dynamic memory manager - * - * This is a lightweight replacement for the standard C library malloc(). - * - * If you want to use the standard C library malloc() instead, define - * MEM_LIBC_MALLOC to 1 in your lwipopts.h - * - * To let mem_malloc() use pools (prevents fragmentation and is much faster than - * a heap but might waste some memory), define MEM_USE_POOLS to 1, define - * MEM_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list - * of pools like this (more pools can be added between _START and _END): - * - * Define three pools with sizes 256, 512, and 1512 bytes - * LWIP_MALLOC_MEMPOOL_START - * LWIP_MALLOC_MEMPOOL(20, 256) - * LWIP_MALLOC_MEMPOOL(10, 512) - * LWIP_MALLOC_MEMPOOL(5, 1512) - * LWIP_MALLOC_MEMPOOL_END - */ - -/* - * 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 - * Simon Goldschmidt - * - */ - -#include "lwip/opt.h" - -#if !MEM_LIBC_MALLOC /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/sys.h" -#include "lwip/stats.h" -#include "lwip/err.h" - -#include - -#if MEM_USE_POOLS -/* lwIP head implemented with different sized pools */ - -/** - * Allocate memory: determine the smallest pool that is big enough - * to contain an element of 'size' and get an element from that pool. - * - * @param size the size in bytes of the memory needed - * @return a pointer to the allocated memory or NULL if the pool is empty - */ -void * ICACHE_FLASH_ATTR -mem_malloc(mem_size_t size) -{ - void *ret; - struct memp_malloc_helper *element; - memp_t poolnr; - mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); - - for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) { -#if MEM_USE_POOLS_TRY_BIGGER_POOL -again: -#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ - /* is this pool big enough to hold an element of the required size - plus a struct memp_malloc_helper that saves the pool this element came from? */ - if (required_size <= memp_sizes[poolnr]) { - break; - } - } - if (poolnr > MEMP_POOL_LAST) { - LWIP_ASSERT("mem_malloc(): no pool is that big!", 0); - return NULL; - } - element = (struct memp_malloc_helper*)memp_malloc(poolnr); - if (element == NULL) { - /* No need to DEBUGF or ASSERT: This error is already - taken care of in memp.c */ -#if MEM_USE_POOLS_TRY_BIGGER_POOL - /** Try a bigger pool if this one is empty! */ - if (poolnr < MEMP_POOL_LAST) { - poolnr++; - goto again; - } -#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ - return NULL; - } - - /* save the pool number this element came from */ - element->poolnr = poolnr; - /* and return a pointer to the memory directly after the struct memp_malloc_helper */ - ret = (u8_t*)element + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); - - return ret; -} - -/** - * Free memory previously allocated by mem_malloc. Loads the pool number - * and calls memp_free with that pool number to put the element back into - * its pool - * - * @param rmem the memory element to free - */ -void ICACHE_FLASH_ATTR -mem_free(void *rmem) -{ - struct memp_malloc_helper *hmem; - - LWIP_ASSERT("rmem != NULL", (rmem != NULL)); - LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem))); - - /* get the original struct memp_malloc_helper */ - hmem = (struct memp_malloc_helper*)(void*)((u8_t*)rmem - LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))); - - LWIP_ASSERT("hmem != NULL", (hmem != NULL)); - LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem))); - LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX)); - - /* and put it in the pool we saved earlier */ - memp_free(hmem->poolnr, hmem); -} - -#else /* MEM_USE_POOLS */ -/* lwIP replacement for your libc malloc() */ - -/** - * The heap is made up as a list of structs of this type. - * This does not have to be aligned since for getting its size, - * we only use the macro SIZEOF_STRUCT_MEM, which automatically alignes. - */ -struct mem { - /** index (-> ram[next]) of the next struct */ - mem_size_t next; - /** index (-> ram[prev]) of the previous struct */ - mem_size_t prev; - /** 1: this area is used; 0: this area is unused */ - u8_t used; -}; - -/** All allocated blocks will be MIN_SIZE bytes big, at least! - * MIN_SIZE can be overridden to suit your needs. Smaller values save space, - * larger values could prevent too small blocks to fragment the RAM too much. */ -#ifndef MIN_SIZE -#define MIN_SIZE 12 -#endif /* MIN_SIZE */ -/* some alignment macros: we define them here for better source code layout */ -#define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE) -#define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem)) -#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE) - -/** If you want to relocate the heap to external memory, simply define - * LWIP_RAM_HEAP_POINTER as a void-pointer to that location. - * If so, make sure the memory at that location is big enough (see below on - * how that space is calculated). */ -#ifndef LWIP_RAM_HEAP_POINTER -/** the heap. we need one struct mem at the end and some room for alignment */ -u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT]; -#define LWIP_RAM_HEAP_POINTER ram_heap -#endif /* LWIP_RAM_HEAP_POINTER */ - -/** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */ -static u8_t *ram; -/** the last entry, always unused! */ -static struct mem *ram_end; -/** pointer to the lowest free block, this is used for faster search */ -static struct mem *lfree; - -/** concurrent access protection */ -#if !NO_SYS -static sys_mutex_t mem_mutex; -#endif - -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - -static volatile u8_t mem_free_count; - -/* Allow mem_free from other (e.g. interrupt) context */ -#define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free) -#define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free) -#define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free) -#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc) -#define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc) -#define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc) - -#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - -/* Protect the heap only by using a semaphore */ -#define LWIP_MEM_FREE_DECL_PROTECT() -#define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex) -#define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex) -/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */ -#define LWIP_MEM_ALLOC_DECL_PROTECT() -#define LWIP_MEM_ALLOC_PROTECT() -#define LWIP_MEM_ALLOC_UNPROTECT() - -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - - -/** - * "Plug holes" by combining adjacent empty struct mems. - * After this function is through, there should not exist - * one empty struct mem pointing to another empty struct mem. - * - * @param mem this points to a struct mem which just has been freed - * @internal this function is only called by mem_free() and mem_trim() - * - * This assumes access to the heap is protected by the calling function - * already. - */ -static void ICACHE_FLASH_ATTR -plug_holes(struct mem *mem) -{ - struct mem *nmem; - struct mem *pmem; - - LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram); - LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end); - LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0); - - /* plug hole forward */ - LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED); - - nmem = (struct mem *)(void *)&ram[mem->next]; - if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) { - /* if mem->next is unused and not end of ram, combine mem and mem->next */ - if (lfree == nmem) { - lfree = mem; - } - mem->next = nmem->next; - ((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram); - } - - /* plug hole backward */ - pmem = (struct mem *)(void *)&ram[mem->prev]; - if (pmem != mem && pmem->used == 0) { - /* if mem->prev is unused, combine mem and mem->prev */ - if (lfree == mem) { - lfree = pmem; - } - pmem->next = mem->next; - ((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram); - } -} - -/** - * Zero the heap and initialize start, end and lowest-free - */ -void ICACHE_FLASH_ATTR -mem_init(void) -{ - struct mem *mem; - - LWIP_ASSERT("Sanity check alignment", - (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0); - - /* align the heap */ - ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER); - /* initialize the start of the heap */ - mem = (struct mem *)(void *)ram; - mem->next = MEM_SIZE_ALIGNED; - mem->prev = 0; - mem->used = 0; - /* initialize the end of the heap */ - ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED]; - ram_end->used = 1; - ram_end->next = MEM_SIZE_ALIGNED; - ram_end->prev = MEM_SIZE_ALIGNED; - - /* initialize the lowest-free pointer to the start of the heap */ - lfree = (struct mem *)(void *)ram; - - MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED); - - if(sys_mutex_new(&mem_mutex) != ERR_OK) { - LWIP_ASSERT("failed to create mem_mutex", 0); - } -} - -/** - * Put a struct mem back on the heap - * - * @param rmem is the data portion of a struct mem as returned by a previous - * call to mem_malloc() - */ -void ICACHE_FLASH_ATTR -mem_free(void *rmem) -{ - struct mem *mem; - LWIP_MEM_FREE_DECL_PROTECT(); - - if (rmem == NULL) { - LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n")); - return; - } - LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0); - - LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram && - (u8_t *)rmem < (u8_t *)ram_end); - - if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { - SYS_ARCH_DECL_PROTECT(lev); - LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n")); - /* protect mem stats from concurrent access */ - SYS_ARCH_PROTECT(lev); - MEM_STATS_INC(illegal); - SYS_ARCH_UNPROTECT(lev); - return; - } - /* protect the heap from concurrent access */ - LWIP_MEM_FREE_PROTECT(); - /* Get the corresponding struct mem ... */ - mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); - /* ... which has to be in a used state ... */ - LWIP_ASSERT("mem_free: mem->used", mem->used); - /* ... and is now unused. */ - mem->used = 0; - - if (mem < lfree) { - /* the newly freed struct is now the lowest */ - lfree = mem; - } - - MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram))); - - /* finally, see if prev or next are free also */ - plug_holes(mem); -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - mem_free_count = 1; -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - LWIP_MEM_FREE_UNPROTECT(); -} - -/** - * Shrink memory returned by mem_malloc(). - * - * @param rmem pointer to memory allocated by mem_malloc the is to be shrinked - * @param newsize required size after shrinking (needs to be smaller than or - * equal to the previous size) - * @return for compatibility reasons: is always == rmem, at the moment - * or NULL if newsize is > old size, in which case rmem is NOT touched - * or freed! - */ -void * ICACHE_FLASH_ATTR -mem_trim(void *rmem, mem_size_t newsize) -{ - mem_size_t size; - mem_size_t ptr, ptr2; - struct mem *mem, *mem2; - /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */ - LWIP_MEM_FREE_DECL_PROTECT(); - - /* Expand the size of the allocated memory region so that we can - adjust for alignment. */ - newsize = LWIP_MEM_ALIGN_SIZE(newsize); - - if(newsize < MIN_SIZE_ALIGNED) { - /* every data block must be at least MIN_SIZE_ALIGNED long */ - newsize = MIN_SIZE_ALIGNED; - } - - if (newsize > MEM_SIZE_ALIGNED) { - return NULL; - } - - LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram && - (u8_t *)rmem < (u8_t *)ram_end); - - if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { - SYS_ARCH_DECL_PROTECT(lev); - LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n")); - /* protect mem stats from concurrent access */ - SYS_ARCH_PROTECT(lev); - MEM_STATS_INC(illegal); - SYS_ARCH_UNPROTECT(lev); - return rmem; - } - /* Get the corresponding struct mem ... */ - mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); - /* ... and its offset pointer */ - ptr = (mem_size_t)((u8_t *)mem - ram); - - size = mem->next - ptr - SIZEOF_STRUCT_MEM; - LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size); - if (newsize > size) { - /* not supported */ - return NULL; - } - if (newsize == size) { - /* No change in size, simply return */ - return rmem; - } - - /* protect the heap from concurrent access */ - LWIP_MEM_FREE_PROTECT(); - - mem2 = (struct mem *)(void *)&ram[mem->next]; - if(mem2->used == 0) { - /* The next struct is unused, we can simply move it at little */ - mem_size_t next; - /* remember the old next pointer */ - next = mem2->next; - /* create new struct mem which is moved directly after the shrinked mem */ - ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; - if (lfree == mem2) { - lfree = (struct mem *)(void *)&ram[ptr2]; - } - mem2 = (struct mem *)(void *)&ram[ptr2]; - mem2->used = 0; - /* restore the next pointer */ - mem2->next = next; - /* link it back to mem */ - mem2->prev = ptr; - /* link mem to it */ - mem->next = ptr2; - /* last thing to restore linked list: as we have moved mem2, - * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not - * the end of the heap */ - if (mem2->next != MEM_SIZE_ALIGNED) { - ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; - } - MEM_STATS_DEC_USED(used, (size - newsize)); - /* no need to plug holes, we've already done that */ - } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) { - /* Next struct is used but there's room for another struct mem with - * at least MIN_SIZE_ALIGNED of data. - * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem - * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED'). - * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty - * region that couldn't hold data, but when mem->next gets freed, - * the 2 regions would be combined, resulting in more free memory */ - ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; - mem2 = (struct mem *)(void *)&ram[ptr2]; - if (mem2 < lfree) { - lfree = mem2; - } - mem2->used = 0; - mem2->next = mem->next; - mem2->prev = ptr; - mem->next = ptr2; - if (mem2->next != MEM_SIZE_ALIGNED) { - ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; - } - MEM_STATS_DEC_USED(used, (size - newsize)); - /* the original mem->next is used, so no need to plug holes! */ - } - /* else { - next struct mem is used but size between mem and mem2 is not big enough - to create another struct mem - -> don't do anyhting. - -> the remaining space stays unused since it is too small - } */ -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - mem_free_count = 1; -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - LWIP_MEM_FREE_UNPROTECT(); - return rmem; -} - -/** - * Adam's mem_malloc() plus solution for bug #17922 - * Allocate a block of memory with a minimum of 'size' bytes. - * - * @param size is the minimum size of the requested block in bytes. - * @return pointer to allocated memory or NULL if no free memory was found. - * - * Note that the returned value will always be aligned (as defined by MEM_ALIGNMENT). - */ -void * ICACHE_FLASH_ATTR -mem_malloc(mem_size_t size) -{ - mem_size_t ptr, ptr2; - struct mem *mem, *mem2; -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - u8_t local_mem_free_count = 0; -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - LWIP_MEM_ALLOC_DECL_PROTECT(); - - if (size == 0) { - return NULL; - } - - /* Expand the size of the allocated memory region so that we can - adjust for alignment. */ - size = LWIP_MEM_ALIGN_SIZE(size); - - if(size < MIN_SIZE_ALIGNED) { - /* every data block must be at least MIN_SIZE_ALIGNED long */ - size = MIN_SIZE_ALIGNED; - } - - if (size > MEM_SIZE_ALIGNED) { - return NULL; - } - - /* protect the heap from concurrent access */ - sys_mutex_lock(&mem_mutex); - LWIP_MEM_ALLOC_PROTECT(); -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - /* run as long as a mem_free disturbed mem_malloc or mem_trim */ - do { - local_mem_free_count = 0; -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - - /* Scan through the heap searching for a free block that is big enough, - * beginning with the lowest free block. - */ - for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size; - ptr = ((struct mem *)(void *)&ram[ptr])->next) { - mem = (struct mem *)(void *)&ram[ptr]; -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - mem_free_count = 0; - LWIP_MEM_ALLOC_UNPROTECT(); - /* allow mem_free or mem_trim to run */ - LWIP_MEM_ALLOC_PROTECT(); - if (mem_free_count != 0) { - /* If mem_free or mem_trim have run, we have to restart since they - could have altered our current struct mem. */ - local_mem_free_count = 1; - break; - } -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - - if ((!mem->used) && - (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) { - /* mem is not used and at least perfect fit is possible: - * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */ - - if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) { - /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing - * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem') - * -> split large block, create empty remainder, - * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if - * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size, - * struct mem would fit in but no data between mem2 and mem2->next - * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty - * region that couldn't hold data, but when mem->next gets freed, - * the 2 regions would be combined, resulting in more free memory - */ - ptr2 = ptr + SIZEOF_STRUCT_MEM + size; - /* create mem2 struct */ - mem2 = (struct mem *)(void *)&ram[ptr2]; - mem2->used = 0; - mem2->next = mem->next; - mem2->prev = ptr; - /* and insert it between mem and mem->next */ - mem->next = ptr2; - mem->used = 1; - - if (mem2->next != MEM_SIZE_ALIGNED) { - ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; - } - MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM)); - } else { - /* (a mem2 struct does no fit into the user data space of mem and mem->next will always - * be used at this point: if not we have 2 unused structs in a row, plug_holes should have - * take care of this). - * -> near fit or excact fit: do not split, no mem2 creation - * also can't move mem->next directly behind mem, since mem->next - * will always be used at this point! - */ - mem->used = 1; - MEM_STATS_INC_USED(used, mem->next - (mem_size_t)((u8_t *)mem - ram)); - } -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT -mem_malloc_adjust_lfree: -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - if (mem == lfree) { - struct mem *cur = lfree; - /* Find next free block after mem and update lowest free pointer */ - while (cur->used && cur != ram_end) { -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - mem_free_count = 0; - LWIP_MEM_ALLOC_UNPROTECT(); - /* prevent high interrupt latency... */ - LWIP_MEM_ALLOC_PROTECT(); - if (mem_free_count != 0) { - /* If mem_free or mem_trim have run, we have to restart since they - could have altered our current struct mem or lfree. */ - goto mem_malloc_adjust_lfree; - } -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - cur = (struct mem *)(void *)&ram[cur->next]; - } - lfree = cur; - LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used))); - } - LWIP_MEM_ALLOC_UNPROTECT(); - sys_mutex_unlock(&mem_mutex); - LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.", - (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end); - LWIP_ASSERT("mem_malloc: allocated memory properly aligned.", - ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0); - LWIP_ASSERT("mem_malloc: sanity check alignment", - (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0); - - return (u8_t *)mem + SIZEOF_STRUCT_MEM; - } - } -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - /* if we got interrupted by a mem_free, try again */ - } while(local_mem_free_count != 0); -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size)); - MEM_STATS_INC(err); - LWIP_MEM_ALLOC_UNPROTECT(); - sys_mutex_unlock(&mem_mutex); - return NULL; -} - -#endif /* MEM_USE_POOLS */ -/** - * Contiguously allocates enough space for count objects that are size bytes - * of memory each and returns a pointer to the allocated memory. - * - * The allocated memory is filled with bytes of value zero. - * - * @param count number of objects to allocate - * @param size size of the objects to allocate - * @return pointer to allocated memory / NULL pointer if there is an error - */ -void * ICACHE_FLASH_ATTR -mem_calloc(mem_size_t count, mem_size_t size) -{ - void *p; - - /* allocate 'count' objects of size 'size' */ - p = mem_malloc(count * size); - if (p) { - /* zero the memory */ - memset(p, 0, count * size); - } - return p; -} - -#endif /* !MEM_LIBC_MALLOC */ diff --git a/third_party/lwip/core/memp.c b/third_party/lwip/core/memp.c deleted file mode 100644 index 8dc0086..0000000 --- a/third_party/lwip/core/memp.c +++ /dev/null @@ -1,485 +0,0 @@ -/** - * @file - * Dynamic pool memory manager - * - * lwIP has dedicated pools for many structures (netconn, protocol control blocks, - * packet buffers, ...). All these pools are managed here. - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" - -#include "lwip/memp.h" -#include "lwip/pbuf.h" -#include "lwip/udp.h" -#include "lwip/raw.h" -#include "lwip/tcp_impl.h" -#include "lwip/igmp.h" -#include "lwip/api.h" -#include "lwip/api_msg.h" -#include "lwip/tcpip.h" -#include "lwip/sys.h" -#include "lwip/timers.h" -#include "lwip/stats.h" -#include "netif/etharp.h" -#include "lwip/ip_frag.h" -#include "lwip/snmp_structs.h" -#include "lwip/snmp_msg.h" -#include "lwip/dns.h" -#include "netif/ppp_oe.h" -#include "lwip/nd6.h" -#include "lwip/ip6_frag.h" -#include "lwip/mld6.h" - -#include - -#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ - -struct memp { - struct memp *next; -#if MEMP_OVERFLOW_CHECK - const char *file; - int line; -#endif /* MEMP_OVERFLOW_CHECK */ -}; - -#if MEMP_OVERFLOW_CHECK -/* if MEMP_OVERFLOW_CHECK is turned on, we reserve some bytes at the beginning - * and at the end of each element, initialize them as 0xcd and check - * them later. */ -/* If MEMP_OVERFLOW_CHECK is >= 2, on every call to memp_malloc or memp_free, - * every single element in each pool is checked! - * This is VERY SLOW but also very helpful. */ -/* MEMP_SANITY_REGION_BEFORE and MEMP_SANITY_REGION_AFTER can be overridden in - * lwipopts.h to change the amount reserved for checking. */ -#ifndef MEMP_SANITY_REGION_BEFORE -#define MEMP_SANITY_REGION_BEFORE 16 -#endif /* MEMP_SANITY_REGION_BEFORE*/ -#if MEMP_SANITY_REGION_BEFORE > 0 -#define MEMP_SANITY_REGION_BEFORE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_BEFORE) -#else -#define MEMP_SANITY_REGION_BEFORE_ALIGNED 0 -#endif /* MEMP_SANITY_REGION_BEFORE*/ -#ifndef MEMP_SANITY_REGION_AFTER -#define MEMP_SANITY_REGION_AFTER 16 -#endif /* MEMP_SANITY_REGION_AFTER*/ -#if MEMP_SANITY_REGION_AFTER > 0 -#define MEMP_SANITY_REGION_AFTER_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_AFTER) -#else -#define MEMP_SANITY_REGION_AFTER_ALIGNED 0 -#endif /* MEMP_SANITY_REGION_AFTER*/ - -/* MEMP_SIZE: save space for struct memp and for sanity check */ -#define MEMP_SIZE (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED) -#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED) - -#else /* MEMP_OVERFLOW_CHECK */ - -/* No sanity checks - * We don't need to preserve the struct memp while not allocated, so we - * can save a little space and set MEMP_SIZE to 0. - */ -#define MEMP_SIZE 0 -#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) - -#endif /* MEMP_OVERFLOW_CHECK */ - -/** This array holds the first free element of each pool. - * Elements form a linked list. */ -static struct memp *memp_tab[MEMP_MAX]; - -#else /* MEMP_MEM_MALLOC */ - -#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) - -#endif /* MEMP_MEM_MALLOC */ - -/** This array holds the element sizes of each pool. */ -#if !MEM_USE_POOLS && !MEMP_MEM_MALLOC -static -#endif -const u16_t memp_sizes[MEMP_MAX] = { -#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEM_ALIGN_SIZE(size), -#include "lwip/memp_std.h" -}; - -#if !MEMP_MEM_MALLOC /* don't build if not configured for use in lwipopts.h */ - -/** This array holds the number of elements in each pool. */ -static const u16_t memp_num[MEMP_MAX] = { -#define LWIP_MEMPOOL(name,num,size,desc) (num), -#include "lwip/memp_std.h" -}; - -/** This array holds a textual description of each pool. */ -#ifdef LWIP_DEBUG -static const char *memp_desc[MEMP_MAX] = { -#define LWIP_MEMPOOL(name,num,size,desc) (desc), -#include "lwip/memp_std.h" -}; -#endif /* LWIP_DEBUG */ - -#if MEMP_SEPARATE_POOLS - -/** This creates each memory pool. These are named memp_memory_XXX_base (where - * XXX is the name of the pool defined in memp_std.h). - * To relocate a pool, declare it as extern in cc.h. Example for GCC: - * extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_UDP_PCB_base[]; - */ -#define LWIP_MEMPOOL(name,num,size,desc) u8_t memp_memory_ ## name ## _base \ - [((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))]; -#include "lwip/memp_std.h" - -/** This array holds the base of each memory pool. */ -static u8_t *const memp_bases[] = { -#define LWIP_MEMPOOL(name,num,size,desc) memp_memory_ ## name ## _base, -#include "lwip/memp_std.h" -}; - -#else /* MEMP_SEPARATE_POOLS */ - -/** This is the actual memory used by the pools (all pools in one big block). */ -static u8_t memp_memory[MEM_ALIGNMENT - 1 -#define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) ) -#include "lwip/memp_std.h" -]; - -#endif /* MEMP_SEPARATE_POOLS */ - -#if MEMP_SANITY_CHECK -/** - * Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm". - */ -static int ICACHE_FLASH_ATTR -memp_sanity(void) -{ - s16_t i; - struct memp *t, *h; - - for (i = 0; i < MEMP_MAX; i++) { - t = memp_tab[i]; - if(t != NULL) { - for (h = t->next; (t != NULL) && (h != NULL); t = t->next, - h = (((h->next != NULL) && (h->next->next != NULL)) ? h->next->next : NULL)) { - if (t == h) { - return 0; - } - } - } - } - return 1; -} -#endif /* MEMP_SANITY_CHECK*/ -#if MEMP_OVERFLOW_CHECK -#if defined(LWIP_DEBUG) && MEMP_STATS -static const char * memp_overflow_names[] = { -#define LWIP_MEMPOOL(name,num,size,desc) "/"desc, -#include "lwip/memp_std.h" - }; -#endif - -/** - * Check if a memp element was victim of an overflow - * (e.g. the restricted area after it has been altered) - * - * @param p the memp element to check - * @param memp_type the pool p comes from - */ -static void ICACHE_FLASH_ATTR -memp_overflow_check_element_overflow(struct memp *p, u16_t memp_type) -{ - u16_t k; - u8_t *m; -#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 - m = (u8_t*)p + MEMP_SIZE + memp_sizes[memp_type]; - for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) { - if (m[k] != 0xcd) { - char errstr[128] = "detected memp overflow in pool "; - char digit[] = "0"; - if(memp_type >= 10) { - digit[0] = '0' + (memp_type/10); - strcat(errstr, digit); - } - digit[0] = '0' + (memp_type%10); - strcat(errstr, digit); -#if defined(LWIP_DEBUG) && MEMP_STATS - strcat(errstr, memp_overflow_names[memp_type]); -#endif - LWIP_ASSERT(errstr, 0); - } - } -#endif -} - -/** - * Check if a memp element was victim of an underflow - * (e.g. the restricted area before it has been altered) - * - * @param p the memp element to check - * @param memp_type the pool p comes from - */ -static void ICACHE_FLASH_ATTR -memp_overflow_check_element_underflow(struct memp *p, u16_t memp_type) -{ - u16_t k; - u8_t *m; -#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 - m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; - for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) { - if (m[k] != 0xcd) { - char errstr[128] = "detected memp underflow in pool "; - char digit[] = "0"; - if(memp_type >= 10) { - digit[0] = '0' + (memp_type/10); - strcat(errstr, digit); - } - digit[0] = '0' + (memp_type%10); - strcat(errstr, digit); -#if defined(LWIP_DEBUG) && MEMP_STATS - strcat(errstr, memp_overflow_names[memp_type]); -#endif - LWIP_ASSERT(errstr, 0); - } - } -#endif -} - -/** - * Do an overflow check for all elements in every pool. - * - * @see memp_overflow_check_element for a description of the check - */ -static void ICACHE_FLASH_ATTR -memp_overflow_check_all(void) -{ - u16_t i, j; - struct memp *p; - -#if !MEMP_SEPARATE_POOLS - p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); -#endif /* !MEMP_SEPARATE_POOLS */ - for (i = 0; i < MEMP_MAX; ++i) { -#if MEMP_SEPARATE_POOLS - p = (struct memp *)(memp_bases[i]); -#endif /* MEMP_SEPARATE_POOLS */ - for (j = 0; j < memp_num[i]; ++j) { - memp_overflow_check_element_overflow(p, i); - p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); - } - } -#if !MEMP_SEPARATE_POOLS - p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); -#endif /* !MEMP_SEPARATE_POOLS */ - for (i = 0; i < MEMP_MAX; ++i) { -#if MEMP_SEPARATE_POOLS - p = (struct memp *)(memp_bases[i]); -#endif /* MEMP_SEPARATE_POOLS */ - for (j = 0; j < memp_num[i]; ++j) { - memp_overflow_check_element_underflow(p, i); - p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); - } - } -} - -/** - * Initialize the restricted areas of all memp elements in every pool. - */ -static void ICACHE_FLASH_ATTR -memp_overflow_init(void) -{ - u16_t i, j; - struct memp *p; - u8_t *m; - -#if !MEMP_SEPARATE_POOLS - p = (struct memp *)LWIP_MEM_ALIGN(memp_memory); -#endif /* !MEMP_SEPARATE_POOLS */ - for (i = 0; i < MEMP_MAX; ++i) { -#if MEMP_SEPARATE_POOLS - p = (struct memp *)(memp_bases[i]); -#endif /* MEMP_SEPARATE_POOLS */ - for (j = 0; j < memp_num[i]; ++j) { -#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 - m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; - memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); -#endif -#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 - m = (u8_t*)p + MEMP_SIZE + memp_sizes[i]; - memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); -#endif - p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); - } - } -} -#endif /* MEMP_OVERFLOW_CHECK */ - -/** - * Initialize this module. - * - * Carves out memp_memory into linked lists for each pool-type. - */ -void ICACHE_FLASH_ATTR -memp_init(void) -{ - struct memp *memp; - u16_t i, j; - - for (i = 0; i < MEMP_MAX; ++i) { - MEMP_STATS_AVAIL(used, i, 0); - MEMP_STATS_AVAIL(max, i, 0); - MEMP_STATS_AVAIL(err, i, 0); - MEMP_STATS_AVAIL(avail, i, memp_num[i]); - } - -#if !MEMP_SEPARATE_POOLS - memp = (struct memp *)LWIP_MEM_ALIGN(memp_memory); -#endif /* !MEMP_SEPARATE_POOLS */ - /* for every pool: */ - for (i = 0; i < MEMP_MAX; ++i) { - memp_tab[i] = NULL; -#if MEMP_SEPARATE_POOLS - memp = (struct memp*)memp_bases[i]; -#endif /* MEMP_SEPARATE_POOLS */ - /* create a linked list of memp elements */ - for (j = 0; j < memp_num[i]; ++j) { - memp->next = memp_tab[i]; - memp_tab[i] = memp; - memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i] -#if MEMP_OVERFLOW_CHECK - + MEMP_SANITY_REGION_AFTER_ALIGNED -#endif - ); - } - } -#if MEMP_OVERFLOW_CHECK - memp_overflow_init(); - /* check everything a first time to see if it worked */ - memp_overflow_check_all(); -#endif /* MEMP_OVERFLOW_CHECK */ -} - -/** - * Get an element from a specific pool. - * - * @param type the pool to get an element from - * - * the debug version has two more parameters: - * @param file file name calling this function - * @param line number of line where this function is called - * - * @return a pointer to the allocated memory or a NULL pointer on error - */ -void * ICACHE_FLASH_ATTR -#if !MEMP_OVERFLOW_CHECK -memp_malloc(memp_t type) -#else -memp_malloc_fn(memp_t type, const char* file, const int line) -#endif -{ - struct memp *memp; - SYS_ARCH_DECL_PROTECT(old_level); - - LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;); - - SYS_ARCH_PROTECT(old_level); -#if MEMP_OVERFLOW_CHECK >= 2 - memp_overflow_check_all(); -#endif /* MEMP_OVERFLOW_CHECK >= 2 */ - - memp = memp_tab[type]; - - if (memp != NULL) { - memp_tab[type] = memp->next; -#if MEMP_OVERFLOW_CHECK - memp->next = NULL; - memp->file = file; - memp->line = line; -#endif /* MEMP_OVERFLOW_CHECK */ - MEMP_STATS_INC_USED(used, type); - LWIP_ASSERT("memp_malloc: memp properly aligned", - ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); - memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE); - } else { - LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type])); - MEMP_STATS_INC(err, type); - } - - SYS_ARCH_UNPROTECT(old_level); - - return memp; -} - -/** - * Put an element back into its pool. - * - * @param type the pool where to put mem - * @param mem the memp element to free - */ -void ICACHE_FLASH_ATTR -memp_free(memp_t type, void *mem) -{ - struct memp *memp; - SYS_ARCH_DECL_PROTECT(old_level); - - if (mem == NULL) { - return; - } - LWIP_ASSERT("memp_free: mem properly aligned", - ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0); - - memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE); - - SYS_ARCH_PROTECT(old_level); -#if MEMP_OVERFLOW_CHECK -#if MEMP_OVERFLOW_CHECK >= 2 - memp_overflow_check_all(); -#else - memp_overflow_check_element_overflow(memp, type); - memp_overflow_check_element_underflow(memp, type); -#endif /* MEMP_OVERFLOW_CHECK >= 2 */ -#endif /* MEMP_OVERFLOW_CHECK */ - - MEMP_STATS_DEC(used, type); - - memp->next = memp_tab[type]; - memp_tab[type] = memp; - -#if MEMP_SANITY_CHECK - LWIP_ASSERT("memp sanity", memp_sanity()); -#endif /* MEMP_SANITY_CHECK */ - - SYS_ARCH_UNPROTECT(old_level); -} - -#endif /* MEMP_MEM_MALLOC */ diff --git a/third_party/lwip/core/netif.c b/third_party/lwip/core/netif.c deleted file mode 100644 index 239ff90..0000000 --- a/third_party/lwip/core/netif.c +++ /dev/null @@ -1,902 +0,0 @@ -/** - * @file - * lwIP network interface abstraction - * - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" - -#include "lwip/def.h" -#include "lwip/ip_addr.h" -#include "lwip/ip6_addr.h" -#include "lwip/netif.h" -#include "lwip/tcp_impl.h" -#include "lwip/snmp.h" -#include "lwip/igmp.h" -#include "netif/etharp.h" -#include "lwip/stats.h" -#if ENABLE_LOOPBACK -#include "lwip/sys.h" -#if LWIP_NETIF_LOOPBACK_MULTITHREADING -#include "lwip/tcpip.h" -#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ -#endif /* ENABLE_LOOPBACK */ - -#if LWIP_AUTOIP -#include "lwip/autoip.h" -#endif /* LWIP_AUTOIP */ -#if LWIP_DHCP -#include "lwip/dhcp.h" -#endif /* LWIP_DHCP */ -#if LWIP_IPV6_DHCP6 -#include "lwip/dhcp6.h" -#endif /* LWIP_IPV6_DHCP6 */ -#if LWIP_IPV6_MLD -#include "lwip/mld6.h" -#endif /* LWIP_IPV6_MLD */ - -#if LWIP_NETIF_STATUS_CALLBACK -#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) -#else -#define NETIF_STATUS_CALLBACK(n) -#endif /* LWIP_NETIF_STATUS_CALLBACK */ - -#if LWIP_NETIF_LINK_CALLBACK -#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0) -#else -#define NETIF_LINK_CALLBACK(n) -#endif /* LWIP_NETIF_LINK_CALLBACK */ - -struct netif *netif_list; -struct netif *netif_default; - -static u8_t netif_num; - -#if LWIP_IPV6 -static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, ip6_addr_t *ipaddr); -#endif /* LWIP_IPV6 */ - -#if LWIP_HAVE_LOOPIF -static struct netif loop_netif; - -/** - * Initialize a lwip network interface structure for a loopback interface - * - * @param netif the lwip network interface structure for this loopif - * @return ERR_OK if the loopif is initialized - * ERR_MEM if private data couldn't be allocated - */ -static err_t ICACHE_FLASH_ATTR -netif_loopif_init(struct netif *netif) -{ - /* initialize the snmp variables and counters inside the struct netif - * ifSpeed: no assumption can be made! - */ - NETIF_INIT_SNMP(netif, snmp_ifType_softwareLoopback, 0); - - netif->name[0] = 'l'; - netif->name[1] = 'o'; - netif->output = netif_loop_output; - return ERR_OK; -} -#endif /* LWIP_HAVE_LOOPIF */ - -void ICACHE_FLASH_ATTR -netif_init(void) -{ -#if LWIP_HAVE_LOOPIF - ip_addr_t loop_ipaddr, loop_netmask, loop_gw; - IP4_ADDR(&loop_gw, 127,0,0,1); - IP4_ADDR(&loop_ipaddr, 127,0,0,1); - IP4_ADDR(&loop_netmask, 255,0,0,0); - -#if NO_SYS - netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, ip_input); -#else /* NO_SYS */ - netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, tcpip_input); -#endif /* NO_SYS */ - netif_set_up(&loop_netif); - -#endif /* LWIP_HAVE_LOOPIF */ -} - -/** - * Add a network interface to the list of lwIP netifs. - * - * @param netif a pre-allocated netif structure - * @param ipaddr IP address for the new netif - * @param netmask network mask for the new netif - * @param gw default gateway IP address for the new netif - * @param state opaque data passed to the new netif - * @param init callback function that initializes the interface - * @param input callback function that is called to pass - * ingress packets up in the protocol layer stack. - * - * @return netif, or NULL if failed. - */ -struct netif * ICACHE_FLASH_ATTR -netif_add(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) -{ -#if LWIP_IPV6 - u32_t i; -#endif - - LWIP_ASSERT("No init function given", init != NULL); - - /* reset new interface configuration state */ - ip_addr_set_zero(&netif->ip_addr); - ip_addr_set_zero(&netif->netmask); - ip_addr_set_zero(&netif->gw); -#if LWIP_IPV6 - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - ip6_addr_set_zero(&netif->ip6_addr[i]); - netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID); - } - netif->output_ip6 = netif_null_output_ip6; -#endif /* LWIP_IPV6 */ - netif->flags = 0; -#if LWIP_DHCP - /* netif not under DHCP control by default */ - netif->dhcp = NULL; -#endif /* LWIP_DHCP */ -#if LWIP_AUTOIP - /* netif not under AutoIP control by default */ - netif->autoip = NULL; -#endif /* LWIP_AUTOIP */ -#if LWIP_IPV6_AUTOCONFIG - /* IPv6 address autoconfiguration not enabled by default */ - netif->ip6_autoconfig_enabled = 0; -#endif /* LWIP_IPV6_AUTOCONFIG */ -#if LWIP_IPV6_SEND_ROUTER_SOLICIT - netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ -#if LWIP_IPV6_DHCP6 - /* netif not under DHCPv6 control by default */ - netif->dhcp6 = NULL; -#endif /* LWIP_IPV6_DHCP6 */ -#if LWIP_NETIF_STATUS_CALLBACK - netif->status_callback = NULL; -#endif /* LWIP_NETIF_STATUS_CALLBACK */ -#if LWIP_NETIF_LINK_CALLBACK - netif->link_callback = NULL; -#endif /* LWIP_NETIF_LINK_CALLBACK */ -#if LWIP_IGMP - netif->igmp_mac_filter = NULL; -#endif /* LWIP_IGMP */ -#if LWIP_IPV6 && LWIP_IPV6_MLD - netif->mld_mac_filter = NULL; -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ -#if ENABLE_LOOPBACK - netif->loop_first = NULL; - netif->loop_last = NULL; -#endif /* ENABLE_LOOPBACK */ - - /* remember netif specific state information data */ - netif->state = state; - netif->num = netif_num++; - netif->input = input; - NETIF_SET_HWADDRHINT(netif, NULL); -#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS - netif->loop_cnt_current = 0; -#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ - - netif_set_addr(netif, ipaddr, netmask, gw); - - /* call user specified initialization function for netif */ - if (init(netif) != ERR_OK) { - return NULL; - } - - /* add this netif to the list */ - netif->next = netif_list; - netif_list = netif; - snmp_inc_iflist(); - -#if LWIP_IGMP - /* start IGMP processing */ - if (netif->flags & NETIF_FLAG_IGMP) { - igmp_start(netif); - } -#endif /* LWIP_IGMP */ - - LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ", - netif->name[0], netif->name[1])); - ip_addr_debug_print(NETIF_DEBUG, ipaddr); - LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); - ip_addr_debug_print(NETIF_DEBUG, netmask); - LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); - ip_addr_debug_print(NETIF_DEBUG, gw); - LWIP_DEBUGF(NETIF_DEBUG, ("\n")); - return netif; -} - -/** - * Change IP address configuration for a network interface (including netmask - * and default gateway). - * - * @param netif the network interface to change - * @param ipaddr the new IP address - * @param netmask the new netmask - * @param gw the new default gateway - */ -void ICACHE_FLASH_ATTR -netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, - ip_addr_t *gw) -{ - netif_set_ipaddr(netif, ipaddr); - netif_set_netmask(netif, netmask); - netif_set_gw(netif, gw); -} - -/** - * Remove a network interface from the list of lwIP netifs. - * - * @param netif the network interface to remove - */ -void ICACHE_FLASH_ATTR -netif_remove(struct netif *netif) -{ - if (netif == NULL) { - return; - } - -#if LWIP_IGMP - /* stop IGMP processing */ - if (netif->flags & NETIF_FLAG_IGMP) { - igmp_stop(netif); - } -#endif /* LWIP_IGMP */ -#if LWIP_IPV6 && LWIP_IPV6_MLD - /* stop MLD processing */ - mld6_stop(netif); -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ - if (netif_is_up(netif)) { - /* set netif down before removing (call callback function) */ - netif_set_down(netif); - } - - snmp_delete_ipaddridx_tree(netif); - - /* is it the first netif? */ - if (netif_list == netif) { - netif_list = netif->next; - } else { - /* look for netif further down the list */ - struct netif * tmpNetif; - for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) { - if (tmpNetif->next == netif) { - tmpNetif->next = netif->next; - break; - } - } - if (tmpNetif == NULL) - return; /* we didn't find any netif today */ - } - snmp_dec_iflist(); - /* this netif is default? */ - if (netif_default == netif) { - /* reset default netif */ - netif_set_default(NULL); - } -#if LWIP_NETIF_REMOVE_CALLBACK - if (netif->remove_callback) { - netif->remove_callback(netif); - } -#endif /* LWIP_NETIF_REMOVE_CALLBACK */ - LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); -} - -/** - * Find a network interface by searching for its name - * - * @param name the name of the netif (like netif->name) plus concatenated number - * in ascii representation (e.g. 'en0') - */ -struct netif * ICACHE_FLASH_ATTR -netif_find(char *name) -{ - struct netif *netif; - u8_t num; - - if (name == NULL) { - return NULL; - } - - num = name[2] - '0'; - - for(netif = netif_list; netif != NULL; netif = netif->next) { - if (num == netif->num && - name[0] == netif->name[0] && - name[1] == netif->name[1]) { - LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); - return netif; - } - } - LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); - return NULL; -} - -/** - * Change the IP address of a network interface - * - * @param netif the network interface to change - * @param ipaddr the new IP address - * - * @note call netif_set_addr() if you also want to change netmask and - * default gateway - */ -void ICACHE_FLASH_ATTR -netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr) -{ - /* TODO: Handling of obsolete pcbs */ - /* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */ -#if LWIP_TCP - struct tcp_pcb *pcb; - struct tcp_pcb_listen *lpcb; - - /* address is actually being changed? */ - if (ipaddr && (ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) { - /* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */ - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); - pcb = tcp_active_pcbs; - while (pcb != NULL) { - /* PCB bound to current local interface address? */ - if (ip_addr_cmp(ipX_2_ip(&pcb->local_ip), &(netif->ip_addr)) -#if LWIP_AUTOIP - /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ - && !ip_addr_islinklocal(ipX_2_ip(&pcb->local_ip)) -#endif /* LWIP_AUTOIP */ - ) { - /* this connection must be aborted */ - struct tcp_pcb *next = pcb->next; - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); - tcp_abort(pcb); - pcb = next; - } else { - pcb = pcb->next; - } - } - for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { - /* PCB bound to current local interface address? */ - if ((!(ip_addr_isany(ipX_2_ip(&lpcb->local_ip)))) && - (ip_addr_cmp(ipX_2_ip(&lpcb->local_ip), &(netif->ip_addr)))) { - /* The PCB is listening to the old ipaddr and - * is set to listen to the new one instead */ - ip_addr_set(ipX_2_ip(&lpcb->local_ip), ipaddr); - } - } - } -#endif - snmp_delete_ipaddridx_tree(netif); - snmp_delete_iprteidx_tree(0,netif); - /* set new IP address to netif */ - ip_addr_set(&(netif->ip_addr), ipaddr); - snmp_insert_ipaddridx_tree(netif); - snmp_insert_iprteidx_tree(0,netif); - - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - netif->name[0], netif->name[1], - ip4_addr1_16(&netif->ip_addr), - ip4_addr2_16(&netif->ip_addr), - ip4_addr3_16(&netif->ip_addr), - ip4_addr4_16(&netif->ip_addr))); -} - -/** - * Change the default gateway for a network interface - * - * @param netif the network interface to change - * @param gw the new default gateway - * - * @note call netif_set_addr() if you also want to change ip address and netmask - */ -void ICACHE_FLASH_ATTR -netif_set_gw(struct netif *netif, ip_addr_t *gw) -{ - ip_addr_set(&(netif->gw), gw); - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - netif->name[0], netif->name[1], - ip4_addr1_16(&netif->gw), - ip4_addr2_16(&netif->gw), - ip4_addr3_16(&netif->gw), - ip4_addr4_16(&netif->gw))); -} - -/** - * Change the netmask of a network interface - * - * @param netif the network interface to change - * @param netmask the new netmask - * - * @note call netif_set_addr() if you also want to change ip address and - * default gateway - */ -void ICACHE_FLASH_ATTR -netif_set_netmask(struct netif *netif, ip_addr_t *netmask) -{ - snmp_delete_iprteidx_tree(0, netif); - /* set new netmask to netif */ - ip_addr_set(&(netif->netmask), netmask); - snmp_insert_iprteidx_tree(0, netif); - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - netif->name[0], netif->name[1], - ip4_addr1_16(&netif->netmask), - ip4_addr2_16(&netif->netmask), - ip4_addr3_16(&netif->netmask), - ip4_addr4_16(&netif->netmask))); -} - -/** - * Set a network interface as the default network interface - * (used to output all packets for which no specific route is found) - * - * @param netif the default network interface - */ -void ICACHE_FLASH_ATTR -netif_set_default(struct netif *netif) -{ - if (netif == NULL) { - /* remove default route */ - snmp_delete_iprteidx_tree(1, netif); - } else { - /* install default route */ - snmp_insert_iprteidx_tree(1, netif); - } - netif_default = netif; - LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", - netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); -} - -/** - * Bring an interface up, available for processing - * traffic. - * - * @note: Enabling DHCP on a down interface will make it come - * up once configured. - * - * @see dhcp_start() - */ -void ICACHE_FLASH_ATTR -netif_set_up(struct netif *netif) -{ - if (!(netif->flags & NETIF_FLAG_UP)) { - netif->flags |= NETIF_FLAG_UP; - -#if LWIP_SNMP - snmp_get_sysuptime(&netif->ts); -#endif /* LWIP_SNMP */ - - NETIF_STATUS_CALLBACK(netif); - - if (netif->flags & NETIF_FLAG_LINK_UP) { -#if LWIP_ARP - /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ - if (netif->flags & (NETIF_FLAG_ETHARP)) { - etharp_gratuitous(netif); - } -#endif /* LWIP_ARP */ - -#if LWIP_IGMP - /* resend IGMP memberships */ - if (netif->flags & NETIF_FLAG_IGMP) { - igmp_report_groups( netif); - } -#endif /* LWIP_IGMP */ -#if LWIP_IPV6 && LWIP_IPV6_MLD - /* send mld memberships */ - mld6_report_groups( netif); -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ - -#if LWIP_IPV6_SEND_ROUTER_SOLICIT - /* Send Router Solicitation messages. */ - netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ - - } - } -} - -/** - * Bring an interface down, disabling any traffic processing. - * - * @note: Enabling DHCP on a down interface will make it come - * up once configured. - * - * @see dhcp_start() - */ -void ICACHE_FLASH_ATTR -netif_set_down(struct netif *netif) -{ - if (netif->flags & NETIF_FLAG_UP) { - netif->flags &= ~NETIF_FLAG_UP; -#if LWIP_SNMP - snmp_get_sysuptime(&netif->ts); -#endif - -#if LWIP_ARP - if (netif->flags & NETIF_FLAG_ETHARP) { - etharp_cleanup_netif(netif); - } -#endif /* LWIP_ARP */ - NETIF_STATUS_CALLBACK(netif); - } -} - -#if LWIP_NETIF_STATUS_CALLBACK -/** - * Set callback to be called when interface is brought up/down - */ -void ICACHE_FLASH_ATTR -netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) -{ - if (netif) { - netif->status_callback = status_callback; - } -} -#endif /* LWIP_NETIF_STATUS_CALLBACK */ - -#if LWIP_NETIF_REMOVE_CALLBACK -/** - * Set callback to be called when the interface has been removed - */ -void ICACHE_FLASH_ATTR -netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback) -{ - if (netif) { - netif->remove_callback = remove_callback; - } -} -#endif /* LWIP_NETIF_REMOVE_CALLBACK */ - -/** - * Called by a driver when its link goes up - */ -void ICACHE_FLASH_ATTR -netif_set_link_up(struct netif *netif ) -{ - if (!(netif->flags & NETIF_FLAG_LINK_UP)) { - netif->flags |= NETIF_FLAG_LINK_UP; - -#if LWIP_DHCP - if (netif->dhcp) { - dhcp_network_changed(netif); - } -#endif /* LWIP_DHCP */ - -#if LWIP_AUTOIP - if (netif->autoip) { - autoip_network_changed(netif); - } -#endif /* LWIP_AUTOIP */ - - if (netif->flags & NETIF_FLAG_UP) { -#if LWIP_ARP - /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ - if (netif->flags & NETIF_FLAG_ETHARP) { - etharp_gratuitous(netif); - } -#endif /* LWIP_ARP */ - -#if LWIP_IGMP - /* resend IGMP memberships */ - if (netif->flags & NETIF_FLAG_IGMP) { - igmp_report_groups( netif); - } -#endif /* LWIP_IGMP */ -#if LWIP_IPV6 && LWIP_IPV6_MLD - /* send mld memberships */ - mld6_report_groups( netif); -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ - } - NETIF_LINK_CALLBACK(netif); - } -} - -/** - * Called by a driver when its link goes down - */ -void ICACHE_FLASH_ATTR -netif_set_link_down(struct netif *netif ) -{ - if (netif->flags & NETIF_FLAG_LINK_UP) { - netif->flags &= ~NETIF_FLAG_LINK_UP; - NETIF_LINK_CALLBACK(netif); - } -} - -#if LWIP_NETIF_LINK_CALLBACK -/** - * Set callback to be called when link is brought up/down - */ -void ICACHE_FLASH_ATTR -netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) -{ - if (netif) { - netif->link_callback = link_callback; - } -} -#endif /* LWIP_NETIF_LINK_CALLBACK */ - -#if ENABLE_LOOPBACK -/** - * Send an IP packet to be received on the same netif (loopif-like). - * The pbuf is simply copied and handed back to netif->input. - * In multithreaded mode, this is done directly since netif->input must put - * the packet on a queue. - * In callback mode, the packet is put on an internal queue and is fed to - * netif->input by netif_poll(). - * - * @param netif the lwip network interface structure - * @param p the (IP) packet to 'send' - * @param ipaddr the ip address to send the packet to (not used) - * @return ERR_OK if the packet has been sent - * ERR_MEM if the pbuf used to copy the packet couldn't be allocated - */ -err_t ICACHE_FLASH_ATTR -netif_loop_output(struct netif *netif, struct pbuf *p, - ip_addr_t *ipaddr) -{ - struct pbuf *r; - err_t err; - struct pbuf *last; -#if LWIP_LOOPBACK_MAX_PBUFS - u8_t clen = 0; -#endif /* LWIP_LOOPBACK_MAX_PBUFS */ - /* If we have a loopif, SNMP counters are adjusted for it, - * if not they are adjusted for 'netif'. */ -#if LWIP_SNMP -#if LWIP_HAVE_LOOPIF - struct netif *stats_if = &loop_netif; -#else /* LWIP_HAVE_LOOPIF */ - struct netif *stats_if = netif; -#endif /* LWIP_HAVE_LOOPIF */ -#endif /* LWIP_SNMP */ - SYS_ARCH_DECL_PROTECT(lev); - LWIP_UNUSED_ARG(ipaddr); - - /* Allocate a new pbuf */ - r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); - if (r == NULL) { - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - snmp_inc_ifoutdiscards(stats_if); - return ERR_MEM; - } -#if LWIP_LOOPBACK_MAX_PBUFS - clen = pbuf_clen(r); - /* check for overflow or too many pbuf on queue */ - if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || - ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { - pbuf_free(r); - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - snmp_inc_ifoutdiscards(stats_if); - return ERR_MEM; - } - netif->loop_cnt_current += clen; -#endif /* LWIP_LOOPBACK_MAX_PBUFS */ - - /* Copy the whole pbuf queue p into the single pbuf r */ - if ((err = pbuf_copy(r, p)) != ERR_OK) { - pbuf_free(r); - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - snmp_inc_ifoutdiscards(stats_if); - return err; - } - - /* Put the packet on a linked list which gets emptied through calling - netif_poll(). */ - - /* let last point to the last pbuf in chain r */ - for (last = r; last->next != NULL; last = last->next); - - SYS_ARCH_PROTECT(lev); - if (netif->loop_first != NULL) { - LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); - netif->loop_last->next = r; - netif->loop_last = last; - } else { - netif->loop_first = r; - netif->loop_last = last; - } - SYS_ARCH_UNPROTECT(lev); - - LINK_STATS_INC(link.xmit); - snmp_add_ifoutoctets(stats_if, p->tot_len); - snmp_inc_ifoutucastpkts(stats_if); - -#if LWIP_NETIF_LOOPBACK_MULTITHREADING - /* For multithreading environment, schedule a call to netif_poll */ - tcpip_callback_with_block((tcpip_callback_fn)netif_poll, netif, 0); -#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ - - return ERR_OK; -} - -/** - * Call netif_poll() in the main loop of your application. This is to prevent - * reentering non-reentrant functions like tcp_input(). Packets passed to - * netif_loop_output() are put on a list that is passed to netif->input() by - * netif_poll(). - */ -void ICACHE_FLASH_ATTR -netif_poll(struct netif *netif) -{ - struct pbuf *in; - /* If we have a loopif, SNMP counters are adjusted for it, - * if not they are adjusted for 'netif'. */ -#if LWIP_SNMP -#if LWIP_HAVE_LOOPIF - struct netif *stats_if = &loop_netif; -#else /* LWIP_HAVE_LOOPIF */ - struct netif *stats_if = netif; -#endif /* LWIP_HAVE_LOOPIF */ -#endif /* LWIP_SNMP */ - SYS_ARCH_DECL_PROTECT(lev); - - do { - /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ - SYS_ARCH_PROTECT(lev); - in = netif->loop_first; - if (in != NULL) { - struct pbuf *in_end = in; -#if LWIP_LOOPBACK_MAX_PBUFS - u8_t clen = pbuf_clen(in); - /* adjust the number of pbufs on queue */ - LWIP_ASSERT("netif->loop_cnt_current underflow", - ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); - netif->loop_cnt_current -= clen; -#endif /* LWIP_LOOPBACK_MAX_PBUFS */ - while (in_end->len != in_end->tot_len) { - LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); - in_end = in_end->next; - } - /* 'in_end' now points to the last pbuf from 'in' */ - if (in_end == netif->loop_last) { - /* this was the last pbuf in the list */ - netif->loop_first = netif->loop_last = NULL; - } else { - /* pop the pbuf off the list */ - netif->loop_first = in_end->next; - LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); - } - /* De-queue the pbuf from its successors on the 'loop_' list. */ - in_end->next = NULL; - } - SYS_ARCH_UNPROTECT(lev); - - if (in != NULL) { - LINK_STATS_INC(link.recv); - snmp_add_ifinoctets(stats_if, in->tot_len); - snmp_inc_ifinucastpkts(stats_if); - /* loopback packets are always IP packets! */ - if (ip_input(in, netif) != ERR_OK) { - pbuf_free(in); - } - /* Don't reference the packet any more! */ - in = NULL; - } - /* go on while there is a packet on the list */ - } while (netif->loop_first != NULL); -} - -#if !LWIP_NETIF_LOOPBACK_MULTITHREADING -/** - * Calls netif_poll() for every netif on the netif_list. - */ -void ICACHE_FLASH_ATTR -netif_poll_all(void) -{ - struct netif *netif = netif_list; - /* loop through netifs */ - while (netif != NULL) { - netif_poll(netif); - /* proceed to next network interface */ - netif = netif->next; - } -} -#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ -#endif /* ENABLE_LOOPBACK */ - -#if LWIP_IPV6 -s8_t ICACHE_FLASH_ATTR -netif_matches_ip6_addr(struct netif * netif, ip6_addr_t * ip6addr) -{ - s8_t i; - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_cmp(netif_ip6_addr(netif, i), ip6addr)) { - return i; - } - } - return -1; -} - -void ICACHE_FLASH_ATTR -netif_create_ip6_linklocal_address(struct netif * netif, u8_t from_mac_48bit) -{ - u8_t i, addr_index; - - /* Link-local prefix. */ - netif->ip6_addr[0].addr[0] = PP_HTONL(0xfe800000ul); - netif->ip6_addr[0].addr[1] = 0; - - /* Generate interface ID. */ - if (from_mac_48bit) { - /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */ - netif->ip6_addr[0].addr[2] = htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) | - ((u32_t)(netif->hwaddr[1]) << 16) | - ((u32_t)(netif->hwaddr[2]) << 8) | - (0xff)); - netif->ip6_addr[0].addr[3] = htonl((0xfeul << 24) | - ((u32_t)(netif->hwaddr[3]) << 16) | - ((u32_t)(netif->hwaddr[4]) << 8) | - (netif->hwaddr[5])); - } - else { - /* Use hwaddr directly as interface ID. */ - netif->ip6_addr[0].addr[2] = 0; - netif->ip6_addr[0].addr[3] = 0; - - addr_index = 3; - for (i = 0; i < 8; i++) { - if (i == 4) { - addr_index--; - } - netif->ip6_addr[0].addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03)); - } - } - - /* Set address state. */ -#if LWIP_IPV6_DUP_DETECT_ATTEMPTS - /* Will perform duplicate address detection (DAD). */ - netif->ip6_addr_state[0] = IP6_ADDR_TENTATIVE; -#else - /* Consider address valid. */ - netif->ip6_addr_state[0] = IP6_ADDR_PREFERRED; -#endif /* LWIP_IPV6_AUTOCONFIG */ -} - -static err_t ICACHE_FLASH_ATTR -netif_null_output_ip6(struct netif *netif, struct pbuf *p, ip6_addr_t *ipaddr) -{ - (void)netif; - (void)p; - (void)ipaddr; - - return ERR_IF; -} -#endif /* LWIP_IPV6 */ diff --git a/third_party/lwip/core/pbuf.c b/third_party/lwip/core/pbuf.c deleted file mode 100644 index 3d4df2a..0000000 --- a/third_party/lwip/core/pbuf.c +++ /dev/null @@ -1,1235 +0,0 @@ -/** - * @file - * Packet buffer management - * - * Packets are built from the pbuf data structure. It supports dynamic - * memory allocation for packet contents or can reference externally - * managed packet contents both in RAM and ROM. Quick allocation for - * incoming packets is provided through pools with fixed sized pbufs. - * - * A packet may span over multiple pbufs, chained as a singly linked - * list. This is called a "pbuf chain". - * - * Multiple packets may be queued, also using this singly linked list. - * This is called a "packet queue". - * - * So, a packet queue consists of one or more pbuf chains, each of - * which consist of one or more pbufs. CURRENTLY, PACKET QUEUES ARE - * NOT SUPPORTED!!! Use helper structs to queue multiple packets. - * - * The differences between a pbuf chain and a packet queue are very - * precise but subtle. - * - * The last pbuf of a packet has a ->tot_len field that equals the - * ->len field. It can be found by traversing the list. If the last - * pbuf of a packet has a ->next field other than NULL, more packets - * are on the queue. - * - * Therefore, looping through a pbuf of a single packet, has an - * loop end condition (tot_len == p->len), NOT (next == NULL). - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" - -#include "lwip/stats.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/pbuf.h" -#include "lwip/sys.h" -#include "arch/perf.h" -#if LWIP_TCP && TCP_QUEUE_OOSEQ -#include "lwip/tcp_impl.h" -#endif -#if LWIP_CHECKSUM_ON_COPY -#include "lwip/inet_chksum.h" -#endif - -#include - -#ifdef EBUF_LWIP -#include "pp/esf_buf.h" -#else -#define EP_OFFSET 0 -#endif /* ESF_LWIP */ - -#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf)) -/* Since the pool is created in memp, PBUF_POOL_BUFSIZE will be automatically - aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */ -#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - -#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ -#define PBUF_POOL_IS_EMPTY() -#else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ - -#if !NO_SYS -#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL -#include "lwip/tcpip.h" -#define PBUF_POOL_FREE_OOSEQ_QUEUE_CALL() do { \ - if(tcpip_callback_with_block(pbuf_free_ooseq_callback, NULL, 0) != ERR_OK) { \ - SYS_ARCH_PROTECT(old_level); \ - pbuf_free_ooseq_pending = 0; \ - SYS_ARCH_UNPROTECT(old_level); \ - } } while(0) -#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ -#endif /* !NO_SYS */ - -volatile u8_t pbuf_free_ooseq_pending; -#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty() - -/** - * Attempt to reclaim some memory from queued out-of-sequence TCP segments - * if we run out of pool pbufs. It's better to give priority to new packets - * if we're running out. - * - * This must be done in the correct thread context therefore this function - * can only be used with NO_SYS=0 and through tcpip_callback. - */ -#if !NO_SYS -static -#endif /* !NO_SYS */ -void ICACHE_FLASH_ATTR -pbuf_free_ooseq(void) -{ - struct tcp_pcb* pcb; - SYS_ARCH_DECL_PROTECT(old_level); - - SYS_ARCH_PROTECT(old_level); - pbuf_free_ooseq_pending = 0; - SYS_ARCH_UNPROTECT(old_level); - - for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) { - if (NULL != pcb->ooseq) { - /** Free the ooseq pbufs of one PCB only */ - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n")); - tcp_segs_free(pcb->ooseq); - pcb->ooseq = NULL; - return; - } - } -} - -#if !NO_SYS -/** - * Just a callback function for tcpip_timeout() that calls pbuf_free_ooseq(). - */ -static void ICACHE_FLASH_ATTR -pbuf_free_ooseq_callback(void *arg) -{ - LWIP_UNUSED_ARG(arg); - pbuf_free_ooseq(); -} -#endif /* !NO_SYS */ - -/** Queue a call to pbuf_free_ooseq if not already queued. */ -static void ICACHE_FLASH_ATTR -pbuf_pool_is_empty(void) -{ -#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL - SYS_ARCH_DECL_PROTECT(old_level); - SYS_ARCH_PROTECT(old_level); - pbuf_free_ooseq_pending = 1; - SYS_ARCH_UNPROTECT(old_level); -#else /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ - u8_t queued; - SYS_ARCH_DECL_PROTECT(old_level); - SYS_ARCH_PROTECT(old_level); - queued = pbuf_free_ooseq_pending; - pbuf_free_ooseq_pending = 1; - SYS_ARCH_UNPROTECT(old_level); - - if(!queued) { - /* queue a call to pbuf_free_ooseq if not already queued */ - PBUF_POOL_FREE_OOSEQ_QUEUE_CALL(); - } -#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ -} -#endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ - -/** - * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type). - * - * The actual memory allocated for the pbuf is determined by the - * layer at which the pbuf is allocated and the requested size - * (from the size parameter). - * - * @param layer flag to define header size - * @param length size of the pbuf's payload - * @param type this parameter decides how and where the pbuf - * should be allocated as follows: - * - * - PBUF_RAM: buffer memory for pbuf is allocated as one large - * chunk. This includes protocol headers as well. - * - PBUF_ROM: no buffer memory is allocated for the pbuf, even for - * protocol headers. Additional headers must be prepended - * by allocating another pbuf and chain in to the front of - * the ROM pbuf. It is assumed that the memory used is really - * similar to ROM in that it is immutable and will not be - * changed. Memory which is dynamic should generally not - * be attached to PBUF_ROM pbufs. Use PBUF_REF instead. - * - PBUF_REF: no buffer memory is allocated for the pbuf, even for - * protocol headers. It is assumed that the pbuf is only - * being used in a single thread. If the pbuf gets queued, - * then pbuf_take should be called to copy the buffer. - * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from - * the pbuf pool that is allocated during pbuf_init(). - * - * @return the allocated pbuf. If multiple pbufs where allocated, this - * is the first pbuf of a pbuf chain. - */ -struct pbuf * ICACHE_FLASH_ATTR -pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) -{ - struct pbuf *p, *q, *r; - u16_t offset; - s32_t rem_len; /* remaining length */ - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length)); - - /* determine header offset */ - switch (layer) { - case PBUF_TRANSPORT: - /* add room for transport (often TCP) layer header */ - offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN + EP_OFFSET; - break; - case PBUF_IP: - /* add room for IP layer header */ - offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + EP_OFFSET; - break; - case PBUF_LINK: - /* add room for link layer header */ - offset = PBUF_LINK_HLEN; - -#ifdef PBUF_RSV_FOR_WLAN - /* - * 1. LINK_HLEN 14Byte will be remove in WLAN layer - * 2. IEEE80211_HDR_MAX_LEN needs 40 bytes. - * 3. encryption needs exra 4 bytes ahead of actual data payload, and require - * DAddr and SAddr to be 4-byte aligned. - * 4. TRANSPORT and IP are all 20, 4 bytes aligned, nice... - * 5. LCC add 6 bytes more, We don't consider WAPI yet... - * 6. define LWIP_MEM_ALIGN to be 4 Byte aligned, pbuf struct is 16B, Only thing may be - * matter is ether_hdr is not 4B aligned. - * - * So, we need extra (40 + 4 - 14) = 30 and it's happen to be 4-Byte aligned - * - * 1. lwip - * | empty 30B | eth_hdr (14B) | payload ...| - * total: 44B ahead payload - * 2. net80211 - * | max 80211 hdr, 32B | ccmp/tkip iv (8B) | sec rsv(4B) | payload ...| - * total: 40B ahead sec_rsv and 44B ahead payload - * - */ - offset += EP_OFFSET; //remove LINK hdr in wlan -#endif /* PBUF_RSV_FOR_WLAN */ - - break; - case PBUF_RAW: -#ifdef PBUF_RSV_FOR_WLAN - /* - * RAW pbuf suppose - */ - offset = EP_OFFSET; //remove LINK hdr in wlan -#endif /* PBUF_RAW */ - break; - default: - LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0); - return NULL; - } - - switch (type) { - case PBUF_POOL: - /* allocate head of pbuf chain into p */ - p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p)); - if (p == NULL) { - PBUF_POOL_IS_EMPTY(); - return NULL; - } - p->type = type; - p->next = NULL; - - /* make the payload pointer point 'offset' bytes into pbuf data memory */ - p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset))); - LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", - ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); - /* the total length of the pbuf chain is the requested size */ - p->tot_len = length; - /* set the length of the first pbuf in the chain */ - p->len = LWIP_MIN(length, PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)); - LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", - ((u8_t*)p->payload + p->len <= - (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); - LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT", - (PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 ); - /* set reference count (needed here in case we fail) */ - p->ref = 1; - - /* now allocate the tail of the pbuf chain */ - - /* remember first pbuf for linkage in next iteration */ - r = p; - /* remaining length to be allocated */ - rem_len = length - p->len; - /* any remaining pbufs to be allocated? */ - while (rem_len > 0) { - q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); - if (q == NULL) { - PBUF_POOL_IS_EMPTY(); - /* free chain so far allocated */ - pbuf_free(p); - /* bail out unsuccesfully */ - return NULL; - } - q->type = type; - q->flags = 0; - q->next = NULL; - /* make previous pbuf point to this pbuf */ - r->next = q; - /* set total length of this pbuf and next in chain */ - LWIP_ASSERT("rem_len < max_u16_t", rem_len < 0xffff); - q->tot_len = (u16_t)rem_len; - /* this pbuf length is pool size, unless smaller sized tail */ - q->len = LWIP_MIN((u16_t)rem_len, PBUF_POOL_BUFSIZE_ALIGNED); - q->payload = (void *)((u8_t *)q + SIZEOF_STRUCT_PBUF); - LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned", - ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0); - LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", - ((u8_t*)p->payload + p->len <= - (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); - q->ref = 1; - /* calculate remaining length to be allocated */ - rem_len -= q->len; - /* remember this pbuf for linkage in next iteration */ - r = q; - } - /* end of chain */ - /*r->next = NULL;*/ - - break; - case PBUF_RAM: - /* If pbuf is to be allocated in RAM, allocate memory for it. */ - p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length)); - if (p == NULL) { - return NULL; - } - /* Set up internal structure of the pbuf. */ - p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset)); - p->len = p->tot_len = length; - p->next = NULL; - p->type = type; - - LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", - ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); - break; -#ifdef EBUF_LWIP - case PBUF_ESF_RX: -#endif /* ESF_LWIP */ - /* pbuf references existing (non-volatile static constant) ROM payload? */ - case PBUF_ROM: - /* pbuf references existing (externally allocated) RAM payload? */ - case PBUF_REF: - /* only allocate memory for the pbuf structure */ - p = (struct pbuf *)memp_malloc(MEMP_PBUF); - if (p == NULL) { - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", - (type == PBUF_ROM) ? "ROM" : "REF")); - return NULL; - } - /* caller must set this field properly, afterwards */ - p->payload = NULL; - p->len = p->tot_len = length; - p->next = NULL; - p->type = type; - break; - default: - LWIP_ASSERT("pbuf_alloc: erroneous type", 0); - return NULL; - } - /* set reference count */ - p->ref = 1; - /* set flags */ - p->flags = 0; - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p)); - return p; -} - -#if LWIP_SUPPORT_CUSTOM_PBUF -/** Initialize a custom pbuf (already allocated). - * - * @param layer flag to define header size - * @param length size of the pbuf's payload - * @param type type of the pbuf (only used to treat the pbuf accordingly, as - * this function allocates no memory) - * @param p pointer to the custom pbuf to initialize (already allocated) - * @param payload_mem pointer to the buffer that is used for payload and headers, - * must be at least big enough to hold 'length' plus the header size, - * may be NULL if set later. - * ATTENTION: The caller is responsible for correct alignment of this buffer!! - * @param payload_mem_len the size of the 'payload_mem' buffer, must be at least - * big enough to hold 'length' plus the header size - */ -struct pbuf* ICACHE_FLASH_ATTR -pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p, - void *payload_mem, u16_t payload_mem_len) -{ - u16_t offset; - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length)); - - /* determine header offset */ - switch (l) { - case PBUF_TRANSPORT: - /* add room for transport (often TCP) layer header */ - offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; - break; - case PBUF_IP: - /* add room for IP layer header */ - offset = PBUF_LINK_HLEN + PBUF_IP_HLEN; - break; - case PBUF_LINK: - /* add room for link layer header */ - offset = PBUF_LINK_HLEN; - break; - case PBUF_RAW: - offset = 0; - break; - default: - LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0); - return NULL; - } - - if (LWIP_MEM_ALIGN_SIZE(offset) + length > payload_mem_len) { - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloced_custom(length=%"U16_F") buffer too short\n", length)); - return NULL; - } - - p->pbuf.next = NULL; - if (payload_mem != NULL) { - p->pbuf.payload = (u8_t *)payload_mem + LWIP_MEM_ALIGN_SIZE(offset); - } else { - p->pbuf.payload = NULL; - } - p->pbuf.flags = PBUF_FLAG_IS_CUSTOM; - p->pbuf.len = p->pbuf.tot_len = length; - p->pbuf.type = type; - p->pbuf.ref = 1; - return &p->pbuf; -} -#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ - -/** - * Shrink a pbuf chain to a desired length. - * - * @param p pbuf to shrink. - * @param new_len desired new length of pbuf chain - * - * Depending on the desired length, the first few pbufs in a chain might - * be skipped and left unchanged. The new last pbuf in the chain will be - * resized, and any remaining pbufs will be freed. - * - * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted. - * @note May not be called on a packet queue. - * - * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain). - */ -void ICACHE_FLASH_ATTR -pbuf_realloc(struct pbuf *p, u16_t new_len) -{ - struct pbuf *q; - u16_t rem_len; /* remaining length */ - s32_t grow; - - LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL); - LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL || - p->type == PBUF_ROM || - p->type == PBUF_RAM || - p->type == PBUF_REF); - - /* desired length larger than current length? */ - if (new_len >= p->tot_len) { - /* enlarging not yet supported */ - return; - } - - /* the pbuf chain grows by (new_len - p->tot_len) bytes - * (which may be negative in case of shrinking) */ - grow = new_len - p->tot_len; - - /* first, step over any pbufs that should remain in the chain */ - rem_len = new_len; - q = p; - /* should this pbuf be kept? */ - while (rem_len > q->len) { - /* decrease remaining length by pbuf length */ - rem_len -= q->len; - /* decrease total length indicator */ - LWIP_ASSERT("grow < max_u16_t", grow < 0xffff); - q->tot_len += (u16_t)grow; - /* proceed to next pbuf in chain */ - q = q->next; - LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL); - } - /* we have now reached the new last pbuf (in q) */ - /* rem_len == desired length for pbuf q */ - - /* shrink allocated memory for PBUF_RAM */ - /* (other types merely adjust their length fields */ - if ((q->type == PBUF_RAM) && (rem_len != q->len)) { - /* reallocate and adjust the length of the pbuf that will be split */ - q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len); - LWIP_ASSERT("mem_trim returned q == NULL", q != NULL); - } - /* adjust length fields for new last pbuf */ - q->len = rem_len; - q->tot_len = q->len; - - /* any remaining pbufs in chain? */ - if (q->next != NULL) { - /* free remaining pbufs in chain */ - pbuf_free(q->next); - } - /* q is last packet in chain */ - q->next = NULL; - -} - -/** - * Adjusts the payload pointer to hide or reveal headers in the payload. - * - * Adjusts the ->payload pointer so that space for a header - * (dis)appears in the pbuf payload. - * - * The ->payload, ->tot_len and ->len fields are adjusted. - * - * @param p pbuf to change the header size. - * @param header_size_increment Number of bytes to increment header size which - * increases the size of the pbuf. New space is on the front. - * (Using a negative value decreases the header size.) - * If hdr_size_inc is 0, this function does nothing and returns succesful. - * - * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so - * the call will fail. A check is made that the increase in header size does - * not move the payload pointer in front of the start of the buffer. - * @return non-zero on failure, zero on success. - * - */ -u8_t ICACHE_FLASH_ATTR -pbuf_header(struct pbuf *p, s16_t header_size_increment) -{ - u16_t type; - void *payload; - u16_t increment_magnitude; - - LWIP_ASSERT("p != NULL", p != NULL); - if ((header_size_increment == 0) || (p == NULL)) { - return 0; - } - - if (header_size_increment < 0){ - increment_magnitude = -header_size_increment; - /* Check that we aren't going to move off the end of the pbuf */ - LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;); - } else { - increment_magnitude = header_size_increment; -#if 0 - /* Can't assert these as some callers speculatively call - pbuf_header() to see if it's OK. Will return 1 below instead. */ - /* Check that we've got the correct type of pbuf to work with */ - LWIP_ASSERT("p->type == PBUF_RAM || p->type == PBUF_POOL", - p->type == PBUF_RAM || p->type == PBUF_POOL); - /* Check that we aren't going to move off the beginning of the pbuf */ - LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF", - (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF); -#endif - } - - type = p->type; - /* remember current payload pointer */ - payload = p->payload; - - /* pbuf types containing payloads? */ - if (type == PBUF_RAM || type == PBUF_POOL) { - /* set new payload pointer */ - p->payload = (u8_t *)p->payload - header_size_increment; - /* boundary check fails? */ - if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) { - LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("pbuf_header: failed as %p < %p (not enough space for new header size)\n", - (void *)p->payload, (void *)(p + 1))); - /* restore old payload pointer */ - p->payload = payload; - /* bail out unsuccesfully */ - return 1; - } - /* pbuf types refering to external payloads? */ - } else if (type == PBUF_REF || type == PBUF_ROM) { - /* hide a header in the payload? */ - if ((header_size_increment < 0) && (increment_magnitude <= p->len)) { - /* increase payload pointer */ - p->payload = (u8_t *)p->payload - header_size_increment; - } else { - /* cannot expand payload to front (yet!) - * bail out unsuccesfully */ - if (type == PBUF_REF) { - /* increase payload pointer */ - p->payload = (u8_t *)p->payload - header_size_increment; - } else { - return 1; - } - } - } else { - /* Unknown type */ - LWIP_ASSERT("bad pbuf type", 0); - return 1; - } - /* modify pbuf length fields */ - p->len += header_size_increment; - p->tot_len += header_size_increment; - - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n", - (void *)payload, (void *)p->payload, header_size_increment)); - - return 0; -} - -/** - * Dereference a pbuf chain or queue and deallocate any no-longer-used - * pbufs at the head of this chain or queue. - * - * Decrements the pbuf reference count. If it reaches zero, the pbuf is - * deallocated. - * - * For a pbuf chain, this is repeated for each pbuf in the chain, - * up to the first pbuf which has a non-zero reference count after - * decrementing. So, when all reference counts are one, the whole - * chain is free'd. - * - * @param p The pbuf (chain) to be dereferenced. - * - * @return the number of pbufs that were de-allocated - * from the head of the chain. - * - * @note MUST NOT be called on a packet queue (Not verified to work yet). - * @note the reference counter of a pbuf equals the number of pointers - * that refer to the pbuf (or into the pbuf). - * - * @internal examples: - * - * Assuming existing chains a->b->c with the following reference - * counts, calling pbuf_free(a) results in: - * - * 1->2->3 becomes ...1->3 - * 3->3->3 becomes 2->3->3 - * 1->1->2 becomes ......1 - * 2->1->1 becomes 1->1->1 - * 1->1->1 becomes ....... - * - */ -u8_t ICACHE_FLASH_ATTR -pbuf_free(struct pbuf *p) -{ - u16_t type; - struct pbuf *q; - u8_t count; - - if (p == NULL) { - LWIP_ASSERT("p != NULL", p != NULL); - /* if assertions are disabled, proceed with debug output */ - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("pbuf_free(p == NULL) was called.\n")); - return 0; - } - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p)); - - PERF_START; - - LWIP_ASSERT("pbuf_free: sane type", - p->type == PBUF_RAM || p->type == PBUF_ROM || - p->type == PBUF_REF || p->type == PBUF_POOL -#ifdef EBUF_LWIP - || p->type == PBUF_ESF_RX -#endif //EBUF_LWIP - ); - - count = 0; - /* de-allocate all consecutive pbufs from the head of the chain that - * obtain a zero reference count after decrementing*/ - while (p != NULL) { - u16_t ref; - SYS_ARCH_DECL_PROTECT(old_level); - /* Since decrementing ref cannot be guaranteed to be a single machine operation - * we must protect it. We put the new ref into a local variable to prevent - * further protection. */ - SYS_ARCH_PROTECT(old_level); - /* all pbufs in a chain are referenced at least once */ - LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0); - /* decrease reference count (number of pointers to pbuf) */ - ref = --(p->ref); - SYS_ARCH_UNPROTECT(old_level); - /* this pbuf is no longer referenced to? */ - if (ref == 0) { - /* remember next pbuf in chain for next iteration */ - q = p->next; - LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p)); - type = p->type; -#if LWIP_SUPPORT_CUSTOM_PBUF - /* is this a custom pbuf? */ - if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) { - struct pbuf_custom *pc = (struct pbuf_custom*)p; - LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL); - pc->custom_free_function(p); - } else -#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ - { - /* is this a pbuf from the pool? */ - if (type == PBUF_POOL) { - memp_free(MEMP_PBUF_POOL, p); - /* is this a ROM or RAM referencing pbuf? */ - } else if (type == PBUF_ROM || type == PBUF_REF -#ifdef EBUF_LWIP - || type == PBUF_ESF_RX -#endif //EBUF_LWIP - ) { -#ifdef EBUF_LWIP - esf_buf *eb = p->eb; - ppRecycleRxPkt(eb); -#endif //EBUF_LWIP - memp_free(MEMP_PBUF, p); - /* type == PBUF_RAM */ - } else { - mem_free(p); - } - } - count++; - /* proceed to next pbuf */ - p = q; - /* p->ref > 0, this pbuf is still referenced to */ - /* (and so the remaining pbufs in chain as well) */ - } else { - LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref)); - /* stop walking through the chain */ - p = NULL; - } - } - PERF_STOP("pbuf_free"); - /* return number of de-allocated pbufs */ - return count; -} - -/** - * Count number of pbufs in a chain - * - * @param p first pbuf of chain - * @return the number of pbufs in a chain - */ - -u8_t ICACHE_FLASH_ATTR -pbuf_clen(struct pbuf *p) -{ - u8_t len; - - len = 0; - while (p != NULL) { - ++len; - p = p->next; - } - return len; -} - -/** - * Increment the reference count of the pbuf. - * - * @param p pbuf to increase reference counter of - * - */ -void ICACHE_FLASH_ATTR -pbuf_ref(struct pbuf *p) -{ - SYS_ARCH_DECL_PROTECT(old_level); - /* pbuf given? */ - if (p != NULL) { - SYS_ARCH_PROTECT(old_level); - ++(p->ref); - SYS_ARCH_UNPROTECT(old_level); - } -} - -/** - * Concatenate two pbufs (each may be a pbuf chain) and take over - * the caller's reference of the tail pbuf. - * - * @note The caller MAY NOT reference the tail pbuf afterwards. - * Use pbuf_chain() for that purpose. - * - * @see pbuf_chain() - */ - -void ICACHE_FLASH_ATTR -pbuf_cat(struct pbuf *h, struct pbuf *t) -{ - struct pbuf *p; - - LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)", - ((h != NULL) && (t != NULL)), return;); - - /* proceed to last pbuf of chain */ - for (p = h; p->next != NULL; p = p->next) { - /* add total length of second chain to all totals of first chain */ - p->tot_len += t->tot_len; - } - /* { p is last pbuf of first h chain, p->next == NULL } */ - LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len); - LWIP_ASSERT("p->next == NULL", p->next == NULL); - /* add total length of second chain to last pbuf total of first chain */ - p->tot_len += t->tot_len; - /* chain last pbuf of head (p) with first of tail (t) */ - p->next = t; - /* p->next now references t, but the caller will drop its reference to t, - * so netto there is no change to the reference count of t. - */ -} - -/** - * Chain two pbufs (or pbuf chains) together. - * - * The caller MUST call pbuf_free(t) once it has stopped - * using it. Use pbuf_cat() instead if you no longer use t. - * - * @param h head pbuf (chain) - * @param t tail pbuf (chain) - * @note The pbufs MUST belong to the same packet. - * @note MAY NOT be called on a packet queue. - * - * The ->tot_len fields of all pbufs of the head chain are adjusted. - * The ->next field of the last pbuf of the head chain is adjusted. - * The ->ref field of the first pbuf of the tail chain is adjusted. - * - */ -void ICACHE_FLASH_ATTR -pbuf_chain(struct pbuf *h, struct pbuf *t) -{ - pbuf_cat(h, t); - /* t is now referenced by h */ - pbuf_ref(t); - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t)); -} - -/** - * Dechains the first pbuf from its succeeding pbufs in the chain. - * - * Makes p->tot_len field equal to p->len. - * @param p pbuf to dechain - * @return remainder of the pbuf chain, or NULL if it was de-allocated. - * @note May not be called on a packet queue. - */ -struct pbuf * ICACHE_FLASH_ATTR -pbuf_dechain(struct pbuf *p) -{ - struct pbuf *q; - u8_t tail_gone = 1; - /* tail */ - q = p->next; - /* pbuf has successor in chain? */ - if (q != NULL) { - /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ - LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len); - /* enforce invariant if assertion is disabled */ - q->tot_len = p->tot_len - p->len; - /* decouple pbuf from remainder */ - p->next = NULL; - /* total length of pbuf p is its own length only */ - p->tot_len = p->len; - /* q is no longer referenced by p, free it */ - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q)); - tail_gone = pbuf_free(q); - if (tail_gone > 0) { - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, - ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q)); - } - /* return remaining tail or NULL if deallocated */ - } - /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ - LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len); - return ((tail_gone > 0) ? NULL : q); -} - -/** - * - * Create PBUF_RAM copies of pbufs. - * - * Used to queue packets on behalf of the lwIP stack, such as - * ARP based queueing. - * - * @note You MUST explicitly use p = pbuf_take(p); - * - * @note Only one packet is copied, no packet queue! - * - * @param p_to pbuf destination of the copy - * @param p_from pbuf source of the copy - * - * @return ERR_OK if pbuf was copied - * ERR_ARG if one of the pbufs is NULL or p_to is not big - * enough to hold p_from - */ -err_t ICACHE_FLASH_ATTR -pbuf_copy(struct pbuf *p_to, struct pbuf *p_from) -{ - u16_t offset_to=0, offset_from=0, len; - - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n", - (void*)p_to, (void*)p_from)); - - /* is the target big enough to hold the source? */ - LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) && - (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;); - - /* iterate through pbuf chain */ - do - { - /* copy one part of the original chain */ - if ((p_to->len - offset_to) >= (p_from->len - offset_from)) { - /* complete current p_from fits into current p_to */ - len = p_from->len - offset_from; - } else { - /* current p_from does not fit into current p_to */ - len = p_to->len - offset_to; - } - MEMCPY((u8_t*)p_to->payload + offset_to, (u8_t*)p_from->payload + offset_from, len); - offset_to += len; - offset_from += len; - LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len); - LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len); - if (offset_from >= p_from->len) { - /* on to next p_from (if any) */ - offset_from = 0; - p_from = p_from->next; - } - if (offset_to == p_to->len) { - /* on to next p_to (if any) */ - offset_to = 0; - p_to = p_to->next; - LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL) , return ERR_ARG;); - } - - if((p_from != NULL) && (p_from->len == p_from->tot_len)) { - /* don't copy more than one packet! */ - LWIP_ERROR("pbuf_copy() does not allow packet queues!\n", - (p_from->next == NULL), return ERR_VAL;); - } - if((p_to != NULL) && (p_to->len == p_to->tot_len)) { - /* don't copy more than one packet! */ - LWIP_ERROR("pbuf_copy() does not allow packet queues!\n", - (p_to->next == NULL), return ERR_VAL;); - } - } while (p_from); - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n")); - return ERR_OK; -} - -/** - * Copy (part of) the contents of a packet buffer - * to an application supplied buffer. - * - * @param buf the pbuf from which to copy data - * @param dataptr the application supplied buffer - * @param len length of data to copy (dataptr must be big enough). No more - * than buf->tot_len will be copied, irrespective of len - * @param offset offset into the packet buffer from where to begin copying len bytes - * @return the number of bytes copied, or 0 on failure - */ -u16_t ICACHE_FLASH_ATTR -pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset) -{ - struct pbuf *p; - u16_t left; - u16_t buf_copy_len; - u16_t copied_total = 0; - - LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;); - LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;); - - left = 0; - - if((buf == NULL) || (dataptr == NULL)) { - return 0; - } - - /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ - for(p = buf; len != 0 && p != NULL; p = p->next) { - if ((offset != 0) && (offset >= p->len)) { - /* don't copy from this buffer -> on to the next */ - offset -= p->len; - } else { - /* copy from this buffer. maybe only partially. */ - buf_copy_len = p->len - offset; - if (buf_copy_len > len) - buf_copy_len = len; - /* copy the necessary parts of the buffer */ - MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len); - copied_total += buf_copy_len; - left += buf_copy_len; - len -= buf_copy_len; - offset = 0; - } - } - return copied_total; -} - -/** - * Copy application supplied data into a pbuf. - * This function can only be used to copy the equivalent of buf->tot_len data. - * - * @param buf pbuf to fill with data - * @param dataptr application supplied data buffer - * @param len length of the application supplied data buffer - * - * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough - */ -err_t ICACHE_FLASH_ATTR -pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len) -{ - struct pbuf *p; - u16_t buf_copy_len; - u16_t total_copy_len = len; - u16_t copied_total = 0; - - LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return 0;); - LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return 0;); - - if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) { - return ERR_ARG; - } - - /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ - for(p = buf; total_copy_len != 0; p = p->next) { - LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL); - buf_copy_len = total_copy_len; - if (buf_copy_len > p->len) { - /* this pbuf cannot hold all remaining data */ - buf_copy_len = p->len; - } - /* copy the necessary parts of the buffer */ - MEMCPY(p->payload, &((char*)dataptr)[copied_total], buf_copy_len); - total_copy_len -= buf_copy_len; - copied_total += buf_copy_len; - } - LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len); - return ERR_OK; -} - -/** - * Creates a single pbuf out of a queue of pbufs. - * - * @remark: Either the source pbuf 'p' is freed by this function or the original - * pbuf 'p' is returned, therefore the caller has to check the result! - * - * @param p the source pbuf - * @param layer pbuf_layer of the new pbuf - * - * @return a new, single pbuf (p->next is NULL) - * or the old pbuf if allocation fails - */ -struct pbuf* ICACHE_FLASH_ATTR -pbuf_coalesce(struct pbuf *p, pbuf_layer layer) -{ - struct pbuf *q; - err_t err; - if (p->next == NULL) { - return p; - } - q = pbuf_alloc(layer, p->tot_len, PBUF_RAM); - if (q == NULL) { - /* @todo: what do we do now? */ - return p; - } - err = pbuf_copy(q, p); - LWIP_ASSERT("pbuf_copy failed", err == ERR_OK); - pbuf_free(p); - return q; -} - -#if LWIP_CHECKSUM_ON_COPY -/** - * Copies data into a single pbuf (*not* into a pbuf queue!) and updates - * the checksum while copying - * - * @param p the pbuf to copy data into - * @param start_offset offset of p->payload where to copy the data to - * @param dataptr data to copy into the pbuf - * @param len length of data to copy into the pbuf - * @param chksum pointer to the checksum which is updated - * @return ERR_OK if successful, another error if the data does not fit - * within the (first) pbuf (no pbuf queues!) - */ -err_t ICACHE_FLASH_ATTR -pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, - u16_t len, u16_t *chksum) -{ - u32_t acc; - u16_t copy_chksum; - char *dst_ptr; - LWIP_ASSERT("p != NULL", p != NULL); - LWIP_ASSERT("dataptr != NULL", dataptr != NULL); - LWIP_ASSERT("chksum != NULL", chksum != NULL); - LWIP_ASSERT("len != 0", len != 0); - - if ((start_offset >= p->len) || (start_offset + len > p->len)) { - return ERR_ARG; - } - - dst_ptr = ((char*)p->payload) + start_offset; - copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len); - if ((start_offset & 1) != 0) { - copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum); - } - acc = *chksum; - acc += copy_chksum; - *chksum = FOLD_U32T(acc); - return ERR_OK; -} -#endif /* LWIP_CHECKSUM_ON_COPY */ - - /** Get one byte from the specified position in a pbuf - * WARNING: returns zero for offset >= p->tot_len - * - * @param p pbuf to parse - * @param offset offset into p of the byte to return - * @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len - */ -u8_t ICACHE_FLASH_ATTR -pbuf_get_at(struct pbuf* p, u16_t offset) -{ - u16_t copy_from = offset; - struct pbuf* q = p; - - /* get the correct pbuf */ - while ((q != NULL) && (q->len <= copy_from)) { - copy_from -= q->len; - q = q->next; - } - /* return requested data if pbuf is OK */ - if ((q != NULL) && (q->len > copy_from)) { - return ((u8_t*)q->payload)[copy_from]; - } - return 0; -} - -/** Compare pbuf contents at specified offset with memory s2, both of length n - * - * @param p pbuf to compare - * @param offset offset into p at wich to start comparing - * @param s2 buffer to compare - * @param n length of buffer to compare - * @return zero if equal, nonzero otherwise - * (0xffff if p is too short, diffoffset+1 otherwise) - */ -u16_t ICACHE_FLASH_ATTR -pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n) -{ - u16_t start = offset; - struct pbuf* q = p; - - /* get the correct pbuf */ - while ((q != NULL) && (q->len <= start)) { - start -= q->len; - q = q->next; - } - /* return requested data if pbuf is OK */ - if ((q != NULL) && (q->len > start)) { - u16_t i; - for(i = 0; i < n; i++) { - u8_t a = pbuf_get_at(q, start + i); - u8_t b = ((u8_t*)s2)[i]; - if (a != b) { - return i+1; - } - } - return 0; - } - return 0xffff; -} - -/** Find occurrence of mem (with length mem_len) in pbuf p, starting at offset - * start_offset. - * - * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as - * return value 'not found' - * @param mem search for the contents of this buffer - * @param mem_len length of 'mem' - * @param start_offset offset into p at which to start searching - * @return 0xFFFF if substr was not found in p or the index where it was found - */ -u16_t ICACHE_FLASH_ATTR -pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset) -{ - u16_t i; - u16_t max = p->tot_len - mem_len; - if (p->tot_len >= mem_len + start_offset) { - for(i = start_offset; i <= max; ) { - u16_t plus = pbuf_memcmp(p, i, mem, mem_len); - if (plus == 0) { - return i; - } else { - i += plus; - } - } - } - return 0xFFFF; -} - -/** Find occurrence of substr with length substr_len in pbuf p, start at offset - * start_offset - * WARNING: in contrast to strstr(), this one does not stop at the first \0 in - * the pbuf/source string! - * - * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as - * return value 'not found' - * @param substr string to search for in p, maximum length is 0xFFFE - * @return 0xFFFF if substr was not found in p or the index where it was found - */ -u16_t ICACHE_FLASH_ATTR -pbuf_strstr(struct pbuf* p, const char* substr) -{ - size_t substr_len; - if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) { - return 0xFFFF; - } - substr_len = strlen(substr); - if (substr_len >= 0xFFFF) { - return 0xFFFF; - } - return pbuf_memfind(p, substr, (u16_t)substr_len, 0); -} diff --git a/third_party/lwip/core/raw.c b/third_party/lwip/core/raw.c deleted file mode 100644 index 8672ae2..0000000 --- a/third_party/lwip/core/raw.c +++ /dev/null @@ -1,422 +0,0 @@ -/** - * @file - * Implementation of raw protocol PCBs for low-level handling of - * different types of protocols besides (or overriding) those - * already available in lwIP. - * - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" - -#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/memp.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/raw.h" -#include "lwip/stats.h" -#include "arch/perf.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" - -#include - -/** The list of RAW PCBs */ -static struct raw_pcb *raw_pcbs; - -/** - * Determine if in incoming IP packet is covered by a RAW PCB - * and if so, pass it to a user-provided receive callback function. - * - * Given an incoming IP datagram (as a chain of pbufs) this function - * finds a corresponding RAW PCB and calls the corresponding receive - * callback function. - * - * @param p pbuf to be demultiplexed to a RAW PCB. - * @param inp network interface on which the datagram was received. - * @return - 1 if the packet has been eaten by a RAW PCB receive - * callback function. The caller MAY NOT not reference the - * packet any longer, and MAY NOT call pbuf_free(). - * @return - 0 if packet is not eaten (pbuf is still referenced by the - * caller). - * - */ -u8_t ICACHE_FLASH_ATTR -raw_input(struct pbuf *p, struct netif *inp) -{ - struct raw_pcb *pcb, *prev; - struct ip_hdr *iphdr; - s16_t proto; - u8_t eaten = 0; -#if LWIP_IPV6 - struct ip6_hdr *ip6hdr; -#endif /* LWIP_IPV6 */ - - - LWIP_UNUSED_ARG(inp); - - iphdr = (struct ip_hdr *)p->payload; -#if LWIP_IPV6 - if (IPH_V(iphdr) == 6) { - ip6hdr = (struct ip6_hdr *)p->payload; - proto = IP6H_NEXTH(ip6hdr); - } - else -#endif /* LWIP_IPV6 */ - { - proto = IPH_PROTO(iphdr); - } - - prev = NULL; - pcb = raw_pcbs; - /* loop through all raw pcbs until the packet is eaten by one */ - /* this allows multiple pcbs to match against the packet by design */ - while ((eaten == 0) && (pcb != NULL)) { - if ((pcb->protocol == proto) && IP_PCB_IPVER_INPUT_MATCH(pcb) && - (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip) || - ipX_addr_cmp(PCB_ISIPV6(pcb), &(pcb->local_ip), ipX_current_dest_addr()))) { -#if IP_SOF_BROADCAST_RECV - /* broadcast filter? */ - if ((ip_get_option(pcb, SOF_BROADCAST) || !ip_addr_isbroadcast(ip_current_dest_addr(), inp)) -#if LWIP_IPV6 - && !PCB_ISIPV6(pcb) -#endif /* LWIP_IPV6 */ - ) -#endif /* IP_SOF_BROADCAST_RECV */ - { - /* receive callback function available? */ - if (pcb->recv.ip4 != NULL) { -#ifndef LWIP_NOASSERT - void* old_payload = p->payload; -#endif - /* the receive callback function did not eat the packet? */ - eaten = pcb->recv.ip4(pcb->recv_arg, pcb, p, ip_current_src_addr()); - if (eaten != 0) { - /* receive function ate the packet */ - p = NULL; - eaten = 1; - if (prev != NULL) { - /* move the pcb to the front of raw_pcbs so that is - found faster next time */ - prev->next = pcb->next; - pcb->next = raw_pcbs; - raw_pcbs = pcb; - } - } else { - /* sanity-check that the receive callback did not alter the pbuf */ - LWIP_ASSERT("raw pcb recv callback altered pbuf payload pointer without eating packet", - p->payload == old_payload); - } - } - /* no receive callback function was set for this raw PCB */ - } - /* drop the packet */ - } - prev = pcb; - pcb = pcb->next; - } - return eaten; -} - -/** - * Bind a RAW PCB. - * - * @param pcb RAW PCB to be bound with a local address ipaddr. - * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to - * bind to all local interfaces. - * - * @return lwIP error code. - * - ERR_OK. Successful. No error occured. - * - ERR_USE. The specified IP address is already bound to by - * another RAW PCB. - * - * @see raw_disconnect() - */ -err_t ICACHE_FLASH_ATTR -raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr) -{ - ipX_addr_set_ipaddr(PCB_ISIPV6(pcb), &pcb->local_ip, ipaddr); - return ERR_OK; -} - -/** - * Connect an RAW PCB. This function is required by upper layers - * of lwip. Using the raw api you could use raw_sendto() instead - * - * This will associate the RAW PCB with the remote address. - * - * @param pcb RAW PCB to be connected with remote address ipaddr and port. - * @param ipaddr remote IP address to connect with. - * - * @return lwIP error code - * - * @see raw_disconnect() and raw_sendto() - */ -err_t ICACHE_FLASH_ATTR -raw_connect(struct raw_pcb *pcb, ip_addr_t *ipaddr) -{ - ipX_addr_set_ipaddr(PCB_ISIPV6(pcb), &pcb->remote_ip, ipaddr); - return ERR_OK; -} - - -/** - * Set the callback function for received packets that match the - * raw PCB's protocol and binding. - * - * The callback function MUST either - * - eat the packet by calling pbuf_free() and returning non-zero. The - * packet will not be passed to other raw PCBs or other protocol layers. - * - not free the packet, and return zero. The packet will be matched - * against further PCBs and/or forwarded to another protocol layers. - * - * @return non-zero if the packet was free()d, zero if the packet remains - * available for others. - */ -void ICACHE_FLASH_ATTR -raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) -{ - /* remember recv() callback and user data */ - pcb->recv.ip4 = recv; - pcb->recv_arg = recv_arg; -} - -/** - * Send the raw IP packet to the given address. Note that actually you cannot - * modify the IP headers (this is inconsistent with the receive callback where - * you actually get the IP headers), you can only specify the IP payload here. - * It requires some more changes in lwIP. (there will be a raw_send() function - * then.) - * - * @param pcb the raw pcb which to send - * @param p the IP payload to send - * @param ipaddr the destination address of the IP packet - * - */ -err_t ICACHE_FLASH_ATTR -raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr) -{ - err_t err; - struct netif *netif; - ipX_addr_t *src_ip; - struct pbuf *q; /* q will be sent down the stack */ - s16_t header_size; - ipX_addr_t *dst_ip = ip_2_ipX(ipaddr); - - LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n")); - - header_size = ( -#if LWIP_IPV6 - PCB_ISIPV6(pcb) ? IP6_HLEN : -#endif /* LWIP_IPV6 */ - IP_HLEN); - - /* not enough space to add an IP header to first pbuf in given p chain? */ - if (pbuf_header(p, header_size)) { - /* allocate header in new pbuf */ - q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM); - /* new header pbuf could not be allocated? */ - if (q == NULL) { - LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n")); - return ERR_MEM; - } - if (p->tot_len != 0) { - /* chain header q in front of given pbuf p */ - pbuf_chain(q, p); - } - /* { first pbuf q points to header pbuf } */ - LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); - } else { - /* first pbuf q equals given pbuf */ - q = p; - if(pbuf_header(q, -header_size)) { - LWIP_ASSERT("Can't restore header we just removed!", 0); - return ERR_MEM; - } - } - - netif = ipX_route(PCB_ISIPV6(pcb), &pcb->local_ip, dst_ip); - if (netif == NULL) { - LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to ")); - ipX_addr_debug_print(PCB_ISIPV6(pcb), RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, dst_ip); - /* free any temporary header pbuf allocated by pbuf_header() */ - if (q != p) { - pbuf_free(q); - } - return ERR_RTE; - } - -#if IP_SOF_BROADCAST -#if LWIP_IPV6 - /* @todo: why does IPv6 not filter broadcast with SOF_BROADCAST enabled? */ - if (!PCB_ISIPV6(pcb)) -#endif /* LWIP_IPV6 */ - { - /* broadcast filter? */ - if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(ipaddr, netif)) { - LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); - /* free any temporary header pbuf allocated by pbuf_header() */ - if (q != p) { - pbuf_free(q); - } - return ERR_VAL; - } - } -#endif /* IP_SOF_BROADCAST */ - - if (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) { - /* use outgoing network interface IP address as source address */ - src_ip = ipX_netif_get_local_ipX(PCB_ISIPV6(pcb), netif, dst_ip); -#if LWIP_IPV6 - if (src_ip == NULL) { - if (q != p) { - pbuf_free(q); - } - return ERR_RTE; - } -#endif /* LWIP_IPV6 */ - } else { - /* use RAW PCB local IP address as source address */ - src_ip = &pcb->local_ip; - } - - NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint); - err = ipX_output_if(PCB_ISIPV6(pcb), q, ipX_2_ip(src_ip), ipX_2_ip(dst_ip), pcb->ttl, pcb->tos, pcb->protocol, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - - /* did we chain a header earlier? */ - if (q != p) { - /* free the header */ - pbuf_free(q); - } - return err; -} - -/** - * Send the raw IP packet to the address given by raw_connect() - * - * @param pcb the raw pcb which to send - * @param p the IP payload to send - * - */ -err_t ICACHE_FLASH_ATTR -raw_send(struct raw_pcb *pcb, struct pbuf *p) -{ - return raw_sendto(pcb, p, ipX_2_ip(&pcb->remote_ip)); -} - -/** - * Remove an RAW PCB. - * - * @param pcb RAW PCB to be removed. The PCB is removed from the list of - * RAW PCB's and the data structure is freed from memory. - * - * @see raw_new() - */ -void ICACHE_FLASH_ATTR -raw_remove(struct raw_pcb *pcb) -{ - struct raw_pcb *pcb2; - /* pcb to be removed is first in list? */ - if (raw_pcbs == pcb) { - /* make list start at 2nd pcb */ - raw_pcbs = raw_pcbs->next; - /* pcb not 1st in list */ - } else { - for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { - /* find pcb in raw_pcbs list */ - if (pcb2->next != NULL && pcb2->next == pcb) { - /* remove pcb from list */ - pcb2->next = pcb->next; - } - } - } - memp_free(MEMP_RAW_PCB, pcb); -} - -/** - * Create a RAW PCB. - * - * @return The RAW PCB which was created. NULL if the PCB data structure - * could not be allocated. - * - * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) - * - * @see raw_remove() - */ -struct raw_pcb * ICACHE_FLASH_ATTR -raw_new(u8_t proto) -{ - struct raw_pcb *pcb; - - LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n")); - - pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); - /* could allocate RAW PCB? */ - if (pcb != NULL) { - /* initialize PCB to all zeroes */ - memset(pcb, 0, sizeof(struct raw_pcb)); - pcb->protocol = proto; - pcb->ttl = RAW_TTL; - pcb->next = raw_pcbs; - raw_pcbs = pcb; - } - return pcb; -} - -#if LWIP_IPV6 -/** - * Create a RAW PCB for IPv6. - * - * @return The RAW PCB which was created. NULL if the PCB data structure - * could not be allocated. - * - * @param proto the protocol number (next header) of the IPv6 packet payload - * (e.g. IP6_NEXTH_ICMP6) - * - * @see raw_remove() - */ -struct raw_pcb * ICACHE_FLASH_ATTR -raw_new_ip6(u8_t proto) -{ - struct raw_pcb *pcb; - pcb = raw_new(proto); - ip_set_v6(pcb, 1); - return pcb; -} -#endif /* LWIP_IPV6 */ - -#endif /* LWIP_RAW */ diff --git a/third_party/lwip/core/snmp/asn1_dec.c b/third_party/lwip/core/snmp/asn1_dec.c deleted file mode 100644 index ffa536e..0000000 --- a/third_party/lwip/core/snmp/asn1_dec.c +++ /dev/null @@ -1,657 +0,0 @@ -/** - * @file - * Abstract Syntax Notation One (ISO 8824, 8825) decoding - * - * @todo not optimised (yet), favor correctness over speed, favor speed over size - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * 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: Christiaan Simons - */ - -#include "lwip/opt.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/snmp_asn1.h" - -/** - * Retrieves type field from incoming pbuf chain. - * - * @param p points to a pbuf holding an ASN1 coded type field - * @param ofs points to the offset within the pbuf chain of the ASN1 coded type field - * @param type return ASN1 type - * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode - */ -err_t -snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type) -{ - u16_t plen, base; - u8_t *msg_ptr; - - plen = 0; - while (p != NULL) - { - base = plen; - plen += p->len; - if (ofs < plen) - { - msg_ptr = (u8_t*)p->payload; - msg_ptr += ofs - base; - *type = *msg_ptr; - return ERR_OK; - } - p = p->next; - } - /* p == NULL, ofs >= plen */ - return ERR_ARG; -} - -/** - * Decodes length field from incoming pbuf chain into host length. - * - * @param p points to a pbuf holding an ASN1 coded length - * @param ofs points to the offset within the pbuf chain of the ASN1 coded length - * @param octets_used returns number of octets used by the length code - * @param length return host order length, upto 64k - * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode - */ -err_t -snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length) -{ - u16_t plen, base; - u8_t *msg_ptr; - - plen = 0; - while (p != NULL) - { - base = plen; - plen += p->len; - if (ofs < plen) - { - msg_ptr = (u8_t*)p->payload; - msg_ptr += ofs - base; - - if (*msg_ptr < 0x80) - { - /* primitive definite length format */ - *octets_used = 1; - *length = *msg_ptr; - return ERR_OK; - } - else if (*msg_ptr == 0x80) - { - /* constructed indefinite length format, termination with two zero octets */ - u8_t zeros; - u8_t i; - - *length = 0; - zeros = 0; - while (zeros != 2) - { - i = 2; - while (i > 0) - { - i--; - (*length) += 1; - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - if (*msg_ptr == 0) - { - zeros++; - if (zeros == 2) - { - /* stop while (i > 0) */ - i = 0; - } - } - else - { - zeros = 0; - } - } - } - *octets_used = 1; - return ERR_OK; - } - else if (*msg_ptr == 0x81) - { - /* constructed definite length format, one octet */ - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - *length = *msg_ptr; - *octets_used = 2; - return ERR_OK; - } - else if (*msg_ptr == 0x82) - { - u8_t i; - - /* constructed definite length format, two octets */ - i = 2; - while (i > 0) - { - i--; - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - if (i == 0) - { - /* least significant length octet */ - *length |= *msg_ptr; - } - else - { - /* most significant length octet */ - *length = (*msg_ptr) << 8; - } - } - *octets_used = 3; - return ERR_OK; - } - else - { - /* constructed definite length format 3..127 octets, this is too big (>64k) */ - /** @todo: do we need to accept inefficient codings with many leading zero's? */ - *octets_used = 1 + ((*msg_ptr) & 0x7f); - return ERR_ARG; - } - } - p = p->next; - } - - /* p == NULL, ofs >= plen */ - return ERR_ARG; -} - -/** - * Decodes positive integer (counter, gauge, timeticks) into u32_t. - * - * @param p points to a pbuf holding an ASN1 coded integer - * @param ofs points to the offset within the pbuf chain of the ASN1 coded integer - * @param len length of the coded integer field - * @param value return host order integer - * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode - * - * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded - * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value - * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! - */ -err_t -snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value) -{ - u16_t plen, base; - u8_t *msg_ptr; - - plen = 0; - while (p != NULL) - { - base = plen; - plen += p->len; - if (ofs < plen) - { - msg_ptr = (u8_t*)p->payload; - msg_ptr += ofs - base; - if ((len > 0) && (len < 6)) - { - /* start from zero */ - *value = 0; - if (*msg_ptr & 0x80) - { - /* negative, expecting zero sign bit! */ - return ERR_ARG; - } - else - { - /* positive */ - if ((len > 1) && (*msg_ptr == 0)) - { - /* skip leading "sign byte" octet 0x00 */ - len--; - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - } - } - /* OR octets with value */ - while (len > 1) - { - len--; - *value |= *msg_ptr; - *value <<= 8; - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - } - *value |= *msg_ptr; - return ERR_OK; - } - else - { - return ERR_ARG; - } - } - p = p->next; - } - /* p == NULL, ofs >= plen */ - return ERR_ARG; -} - -/** - * Decodes integer into s32_t. - * - * @param p points to a pbuf holding an ASN1 coded integer - * @param ofs points to the offset within the pbuf chain of the ASN1 coded integer - * @param len length of the coded integer field - * @param value return host order integer - * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode - * - * @note ASN coded integers are _always_ signed! - */ -err_t -snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value) -{ - u16_t plen, base; - u8_t *msg_ptr; -#if BYTE_ORDER == LITTLE_ENDIAN - u8_t *lsb_ptr = (u8_t*)value; -#endif -#if BYTE_ORDER == BIG_ENDIAN - u8_t *lsb_ptr = (u8_t*)value + sizeof(s32_t) - 1; -#endif - u8_t sign; - - plen = 0; - while (p != NULL) - { - base = plen; - plen += p->len; - if (ofs < plen) - { - msg_ptr = (u8_t*)p->payload; - msg_ptr += ofs - base; - if ((len > 0) && (len < 5)) - { - if (*msg_ptr & 0x80) - { - /* negative, start from -1 */ - *value = -1; - sign = 1; - } - else - { - /* positive, start from 0 */ - *value = 0; - sign = 0; - } - /* OR/AND octets with value */ - while (len > 1) - { - len--; - if (sign) - { - *lsb_ptr &= *msg_ptr; - *value <<= 8; - *lsb_ptr |= 255; - } - else - { - *lsb_ptr |= *msg_ptr; - *value <<= 8; - } - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - } - if (sign) - { - *lsb_ptr &= *msg_ptr; - } - else - { - *lsb_ptr |= *msg_ptr; - } - return ERR_OK; - } - else - { - return ERR_ARG; - } - } - p = p->next; - } - /* p == NULL, ofs >= plen */ - return ERR_ARG; -} - -/** - * Decodes object identifier from incoming message into array of s32_t. - * - * @param p points to a pbuf holding an ASN1 coded object identifier - * @param ofs points to the offset within the pbuf chain of the ASN1 coded object identifier - * @param len length of the coded object identifier - * @param oid return object identifier struct - * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode - */ -err_t -snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid) -{ - u16_t plen, base; - u8_t *msg_ptr; - s32_t *oid_ptr; - - plen = 0; - while (p != NULL) - { - base = plen; - plen += p->len; - if (ofs < plen) - { - msg_ptr = (u8_t*)p->payload; - msg_ptr += ofs - base; - - oid->len = 0; - oid_ptr = &oid->id[0]; - if (len > 0) - { - /* first compressed octet */ - if (*msg_ptr == 0x2B) - { - /* (most) common case 1.3 (iso.org) */ - *oid_ptr = 1; - oid_ptr++; - *oid_ptr = 3; - oid_ptr++; - } - else if (*msg_ptr < 40) - { - *oid_ptr = 0; - oid_ptr++; - *oid_ptr = *msg_ptr; - oid_ptr++; - } - else if (*msg_ptr < 80) - { - *oid_ptr = 1; - oid_ptr++; - *oid_ptr = (*msg_ptr) - 40; - oid_ptr++; - } - else - { - *oid_ptr = 2; - oid_ptr++; - *oid_ptr = (*msg_ptr) - 80; - oid_ptr++; - } - oid->len = 2; - } - else - { - /* accepting zero length identifiers e.g. for - getnext operation. uncommon but valid */ - return ERR_OK; - } - len--; - if (len > 0) - { - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - } - while ((len > 0) && (oid->len < LWIP_SNMP_OBJ_ID_LEN)) - { - /* sub-identifier uses multiple octets */ - if (*msg_ptr & 0x80) - { - s32_t sub_id = 0; - - while ((*msg_ptr & 0x80) && (len > 1)) - { - len--; - sub_id = (sub_id << 7) + (*msg_ptr & ~0x80); - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - } - if (!(*msg_ptr & 0x80) && (len > 0)) - { - /* last octet sub-identifier */ - len--; - sub_id = (sub_id << 7) + *msg_ptr; - *oid_ptr = sub_id; - } - } - else - { - /* !(*msg_ptr & 0x80) sub-identifier uses single octet */ - len--; - *oid_ptr = *msg_ptr; - } - if (len > 0) - { - /* remaining oid bytes available ... */ - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - } - oid_ptr++; - oid->len++; - } - if (len == 0) - { - /* len == 0, end of oid */ - return ERR_OK; - } - else - { - /* len > 0, oid->len == LWIP_SNMP_OBJ_ID_LEN or malformed encoding */ - return ERR_ARG; - } - - } - p = p->next; - } - /* p == NULL, ofs >= plen */ - return ERR_ARG; -} - -/** - * Decodes (copies) raw data (ip-addresses, octet strings, opaque encoding) - * from incoming message into array. - * - * @param p points to a pbuf holding an ASN1 coded raw data - * @param ofs points to the offset within the pbuf chain of the ASN1 coded raw data - * @param len length of the coded raw data (zero is valid, e.g. empty string!) - * @param raw_len length of the raw return value - * @param raw return raw bytes - * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode - */ -err_t -snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw) -{ - u16_t plen, base; - u8_t *msg_ptr; - - if (len > 0) - { - plen = 0; - while (p != NULL) - { - base = plen; - plen += p->len; - if (ofs < plen) - { - msg_ptr = (u8_t*)p->payload; - msg_ptr += ofs - base; - if (raw_len >= len) - { - while (len > 1) - { - /* copy len - 1 octets */ - len--; - *raw = *msg_ptr; - raw++; - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - } - /* copy last octet */ - *raw = *msg_ptr; - return ERR_OK; - } - else - { - /* raw_len < len, not enough dst space */ - return ERR_ARG; - } - } - p = p->next; - } - /* p == NULL, ofs >= plen */ - return ERR_ARG; - } - else - { - /* len == 0, empty string */ - return ERR_OK; - } -} - -#endif /* LWIP_SNMP */ diff --git a/third_party/lwip/core/snmp/asn1_enc.c b/third_party/lwip/core/snmp/asn1_enc.c deleted file mode 100644 index a6169dc..0000000 --- a/third_party/lwip/core/snmp/asn1_enc.c +++ /dev/null @@ -1,611 +0,0 @@ -/** - * @file - * Abstract Syntax Notation One (ISO 8824, 8825) encoding - * - * @todo not optimised (yet), favor correctness over speed, favor speed over size - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * 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: Christiaan Simons - */ - -#include "lwip/opt.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/snmp_asn1.h" - -/** - * Returns octet count for length. - * - * @param length - * @param octets_needed points to the return value - */ -void -snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed) -{ - if (length < 0x80U) - { - *octets_needed = 1; - } - else if (length < 0x100U) - { - *octets_needed = 2; - } - else - { - *octets_needed = 3; - } -} - -/** - * Returns octet count for an u32_t. - * - * @param value - * @param octets_needed points to the return value - * - * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded - * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value - * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! - */ -void -snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed) -{ - if (value < 0x80UL) - { - *octets_needed = 1; - } - else if (value < 0x8000UL) - { - *octets_needed = 2; - } - else if (value < 0x800000UL) - { - *octets_needed = 3; - } - else if (value < 0x80000000UL) - { - *octets_needed = 4; - } - else - { - *octets_needed = 5; - } -} - -/** - * Returns octet count for an s32_t. - * - * @param value - * @param octets_needed points to the return value - * - * @note ASN coded integers are _always_ signed. - */ -void -snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed) -{ - if (value < 0) - { - value = ~value; - } - if (value < 0x80L) - { - *octets_needed = 1; - } - else if (value < 0x8000L) - { - *octets_needed = 2; - } - else if (value < 0x800000L) - { - *octets_needed = 3; - } - else - { - *octets_needed = 4; - } -} - -/** - * Returns octet count for an object identifier. - * - * @param ident_len object identifier array length - * @param ident points to object identifier array - * @param octets_needed points to the return value - */ -void -snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed) -{ - s32_t sub_id; - u8_t cnt; - - cnt = 0; - if (ident_len > 1) - { - /* compressed prefix in one octet */ - cnt++; - ident_len -= 2; - ident += 2; - } - while(ident_len > 0) - { - ident_len--; - sub_id = *ident; - - sub_id >>= 7; - cnt++; - while(sub_id > 0) - { - sub_id >>= 7; - cnt++; - } - ident++; - } - *octets_needed = cnt; -} - -/** - * Encodes ASN type field into a pbuf chained ASN1 msg. - * - * @param p points to output pbuf to encode value into - * @param ofs points to the offset within the pbuf chain - * @param type input ASN1 type - * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode - */ -err_t -snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type) -{ - u16_t plen, base; - u8_t *msg_ptr; - - plen = 0; - while (p != NULL) - { - base = plen; - plen += p->len; - if (ofs < plen) - { - msg_ptr = (u8_t*)p->payload; - msg_ptr += ofs - base; - *msg_ptr = type; - return ERR_OK; - } - p = p->next; - } - /* p == NULL, ofs >= plen */ - return ERR_ARG; -} - -/** - * Encodes host order length field into a pbuf chained ASN1 msg. - * - * @param p points to output pbuf to encode length into - * @param ofs points to the offset within the pbuf chain - * @param length is the host order length to be encoded - * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode - */ -err_t -snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length) -{ - u16_t plen, base; - u8_t *msg_ptr; - - plen = 0; - while (p != NULL) - { - base = plen; - plen += p->len; - if (ofs < plen) - { - msg_ptr = (u8_t*)p->payload; - msg_ptr += ofs - base; - - if (length < 0x80) - { - *msg_ptr = (u8_t)length; - return ERR_OK; - } - else if (length < 0x100) - { - *msg_ptr = 0x81; - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - *msg_ptr = (u8_t)length; - return ERR_OK; - } - else - { - u8_t i; - - /* length >= 0x100 && length <= 0xFFFF */ - *msg_ptr = 0x82; - i = 2; - while (i > 0) - { - i--; - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - if (i == 0) - { - /* least significant length octet */ - *msg_ptr = (u8_t)length; - } - else - { - /* most significant length octet */ - *msg_ptr = (u8_t)(length >> 8); - } - } - return ERR_OK; - } - } - p = p->next; - } - /* p == NULL, ofs >= plen */ - return ERR_ARG; -} - -/** - * Encodes u32_t (counter, gauge, timeticks) into a pbuf chained ASN1 msg. - * - * @param p points to output pbuf to encode value into - * @param ofs points to the offset within the pbuf chain - * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) - * @param value is the host order u32_t value to be encoded - * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode - * - * @see snmp_asn1_enc_u32t_cnt() - */ -err_t -snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, u32_t value) -{ - u16_t plen, base; - u8_t *msg_ptr; - - plen = 0; - while (p != NULL) - { - base = plen; - plen += p->len; - if (ofs < plen) - { - msg_ptr = (u8_t*)p->payload; - msg_ptr += ofs - base; - - if (octets_needed == 5) - { - /* not enough bits in 'value' add leading 0x00 */ - octets_needed--; - *msg_ptr = 0x00; - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - } - while (octets_needed > 1) - { - octets_needed--; - *msg_ptr = (u8_t)(value >> (octets_needed << 3)); - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - } - /* (only) one least significant octet */ - *msg_ptr = (u8_t)value; - return ERR_OK; - } - p = p->next; - } - /* p == NULL, ofs >= plen */ - return ERR_ARG; -} - -/** - * Encodes s32_t integer into a pbuf chained ASN1 msg. - * - * @param p points to output pbuf to encode value into - * @param ofs points to the offset within the pbuf chain - * @param octets_needed encoding length (from snmp_asn1_enc_s32t_cnt()) - * @param value is the host order s32_t value to be encoded - * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode - * - * @see snmp_asn1_enc_s32t_cnt() - */ -err_t -snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, s32_t value) -{ - u16_t plen, base; - u8_t *msg_ptr; - - plen = 0; - while (p != NULL) - { - base = plen; - plen += p->len; - if (ofs < plen) - { - msg_ptr = (u8_t*)p->payload; - msg_ptr += ofs - base; - - while (octets_needed > 1) - { - octets_needed--; - *msg_ptr = (u8_t)(value >> (octets_needed << 3)); - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - } - /* (only) one least significant octet */ - *msg_ptr = (u8_t)value; - return ERR_OK; - } - p = p->next; - } - /* p == NULL, ofs >= plen */ - return ERR_ARG; -} - -/** - * Encodes object identifier into a pbuf chained ASN1 msg. - * - * @param p points to output pbuf to encode oid into - * @param ofs points to the offset within the pbuf chain - * @param ident_len object identifier array length - * @param ident points to object identifier array - * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode - */ -err_t -snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident) -{ - u16_t plen, base; - u8_t *msg_ptr; - - plen = 0; - while (p != NULL) - { - base = plen; - plen += p->len; - if (ofs < plen) - { - msg_ptr = (u8_t*)p->payload; - msg_ptr += ofs - base; - - if (ident_len > 1) - { - if ((ident[0] == 1) && (ident[1] == 3)) - { - /* compressed (most common) prefix .iso.org */ - *msg_ptr = 0x2b; - } - else - { - /* calculate prefix */ - *msg_ptr = (u8_t)((ident[0] * 40) + ident[1]); - } - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - ident_len -= 2; - ident += 2; - } - else - { -/* @bug: allow empty varbinds for symmetry (we must decode them for getnext), allow partial compression?? */ - /* ident_len <= 1, at least we need zeroDotZero (0.0) (ident_len == 2) */ - return ERR_ARG; - } - while (ident_len > 0) - { - s32_t sub_id; - u8_t shift, tail; - - ident_len--; - sub_id = *ident; - tail = 0; - shift = 28; - while(shift > 0) - { - u8_t code; - - code = (u8_t)(sub_id >> shift); - if ((code != 0) || (tail != 0)) - { - tail = 1; - *msg_ptr = code | 0x80; - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - } - shift -= 7; - } - *msg_ptr = (u8_t)sub_id & 0x7F; - if (ident_len > 0) - { - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - } - /* proceed to next sub-identifier */ - ident++; - } - return ERR_OK; - } - p = p->next; - } - /* p == NULL, ofs >= plen */ - return ERR_ARG; -} - -/** - * Encodes raw data (octet string, opaque) into a pbuf chained ASN1 msg. - * - * @param p points to output pbuf to encode raw data into - * @param ofs points to the offset within the pbuf chain - * @param raw_len raw data length - * @param raw points raw data - * @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode - */ -err_t -snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u16_t raw_len, u8_t *raw) -{ - u16_t plen, base; - u8_t *msg_ptr; - - plen = 0; - while (p != NULL) - { - base = plen; - plen += p->len; - if (ofs < plen) - { - msg_ptr = (u8_t*)p->payload; - msg_ptr += ofs - base; - - while (raw_len > 1) - { - /* copy raw_len - 1 octets */ - raw_len--; - *msg_ptr = *raw; - raw++; - ofs += 1; - if (ofs >= plen) - { - /* next octet in next pbuf */ - p = p->next; - if (p == NULL) { return ERR_ARG; } - msg_ptr = (u8_t*)p->payload; - plen += p->len; - } - else - { - /* next octet in same pbuf */ - msg_ptr++; - } - } - if (raw_len > 0) - { - /* copy last or single octet */ - *msg_ptr = *raw; - } - return ERR_OK; - } - p = p->next; - } - /* p == NULL, ofs >= plen */ - return ERR_ARG; -} - -#endif /* LWIP_SNMP */ diff --git a/third_party/lwip/core/snmp/mib2.c b/third_party/lwip/core/snmp/mib2.c deleted file mode 100644 index 1fa9e68..0000000 --- a/third_party/lwip/core/snmp/mib2.c +++ /dev/null @@ -1,4146 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) objects and functions. - * - * @note the object identifiers for this MIB-2 and private MIB tree - * must be kept in sorted ascending order. This to ensure correct getnext operation. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * 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: Christiaan Simons - */ - -#include "lwip/opt.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/snmp.h" -#include "lwip/netif.h" -#include "lwip/ip.h" -#include "lwip/ip_frag.h" -#include "lwip/mem.h" -#include "lwip/tcp_impl.h" -#include "lwip/udp.h" -#include "lwip/snmp_asn1.h" -#include "lwip/snmp_structs.h" -#include "lwip/sys.h" -#include "netif/etharp.h" - -/** - * IANA assigned enterprise ID for lwIP is 26381 - * @see http://www.iana.org/assignments/enterprise-numbers - * - * @note this enterprise ID is assigned to the lwIP project, - * all object identifiers living under this ID are assigned - * by the lwIP maintainers (contact Christiaan Simons)! - * @note don't change this define, use snmp_set_sysobjid() - * - * If you need to create your own private MIB you'll need - * to apply for your own enterprise ID with IANA: - * http://www.iana.org/numbers.html - */ -#define SNMP_ENTERPRISE_ID 26381 -#define SNMP_SYSOBJID_LEN 7 -#define SNMP_SYSOBJID {1, 3, 6, 1, 4, 1, SNMP_ENTERPRISE_ID} - -#ifndef SNMP_SYSSERVICES -#define SNMP_SYSSERVICES ((1 << 6) | (1 << 3) | ((IP_FORWARD) << 2)) -#endif - -#ifndef SNMP_GET_SYSUPTIME -#define SNMP_GET_SYSUPTIME(sysuptime) (sysuptime = (sys_now() / 10)) -#endif - -static void system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); -static void system_get_value(struct obj_def *od, u16_t len, void *value); -static u8_t system_set_test(struct obj_def *od, u16_t len, void *value); -static void system_set_value(struct obj_def *od, u16_t len, void *value); -static void interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); -static void interfaces_get_value(struct obj_def *od, u16_t len, void *value); -static void ifentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); -static void ifentry_get_value(struct obj_def *od, u16_t len, void *value); -#if !SNMP_SAFE_REQUESTS -static u8_t ifentry_set_test (struct obj_def *od, u16_t len, void *value); -static void ifentry_set_value (struct obj_def *od, u16_t len, void *value); -#endif /* SNMP_SAFE_REQUESTS */ -static void atentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); -static void atentry_get_value(struct obj_def *od, u16_t len, void *value); -static void ip_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); -static void ip_get_value(struct obj_def *od, u16_t len, void *value); -static u8_t ip_set_test(struct obj_def *od, u16_t len, void *value); -static void ip_addrentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); -static void ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value); -static void ip_rteentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); -static void ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value); -static void ip_ntomentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); -static void ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value); -static void icmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); -static void icmp_get_value(struct obj_def *od, u16_t len, void *value); -#if LWIP_TCP -static void tcp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); -static void tcp_get_value(struct obj_def *od, u16_t len, void *value); -#ifdef THIS_SEEMS_UNUSED -static void tcpconnentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); -static void tcpconnentry_get_value(struct obj_def *od, u16_t len, void *value); -#endif -#endif -static void udp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); -static void udp_get_value(struct obj_def *od, u16_t len, void *value); -static void udpentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); -static void udpentry_get_value(struct obj_def *od, u16_t len, void *value); -static void snmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); -static void snmp_get_value(struct obj_def *od, u16_t len, void *value); -static u8_t snmp_set_test(struct obj_def *od, u16_t len, void *value); -static void snmp_set_value(struct obj_def *od, u16_t len, void *value); - - -/* snmp .1.3.6.1.2.1.11 */ -const mib_scalar_node snmp_scalar = { - &snmp_get_object_def, - &snmp_get_value, - &snmp_set_test, - &snmp_set_value, - MIB_NODE_SC, - 0 -}; -const s32_t snmp_ids[28] = { - 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30 -}; -struct mib_node* const snmp_nodes[28] = { - (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, - (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, - (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, - (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, - (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, - (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, - (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, - (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, - (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, - (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, - (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, - (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, - (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar, - (struct mib_node*)&snmp_scalar, (struct mib_node*)&snmp_scalar -}; -const struct mib_array_node snmp = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 28, - snmp_ids, - snmp_nodes -}; - -/* dot3 and EtherLike MIB not planned. (transmission .1.3.6.1.2.1.10) */ -/* historical (some say hysterical). (cmot .1.3.6.1.2.1.9) */ -/* lwIP has no EGP, thus may not implement it. (egp .1.3.6.1.2.1.8) */ - -/* udp .1.3.6.1.2.1.7 */ -/** index root node for udpTable */ -struct mib_list_rootnode udp_root = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_LR, - 0, - NULL, - NULL, - 0 -}; -const s32_t udpentry_ids[2] = { 1, 2 }; -struct mib_node* const udpentry_nodes[2] = { - (struct mib_node*)&udp_root, (struct mib_node*)&udp_root, -}; -const struct mib_array_node udpentry = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 2, - udpentry_ids, - udpentry_nodes -}; - -s32_t udptable_id = 1; -struct mib_node* udptable_node = (struct mib_node*)&udpentry; -struct mib_ram_array_node udptable = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_RA, - 0, - &udptable_id, - &udptable_node -}; - -const mib_scalar_node udp_scalar = { - &udp_get_object_def, - &udp_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_SC, - 0 -}; -const s32_t udp_ids[5] = { 1, 2, 3, 4, 5 }; -struct mib_node* const udp_nodes[5] = { - (struct mib_node*)&udp_scalar, (struct mib_node*)&udp_scalar, - (struct mib_node*)&udp_scalar, (struct mib_node*)&udp_scalar, - (struct mib_node*)&udptable -}; -const struct mib_array_node udp = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 5, - udp_ids, - udp_nodes -}; - -/* tcp .1.3.6.1.2.1.6 */ -#if LWIP_TCP -/* only if the TCP protocol is available may implement this group */ -/** index root node for tcpConnTable */ -struct mib_list_rootnode tcpconntree_root = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_LR, - 0, - NULL, - NULL, - 0 -}; -const s32_t tcpconnentry_ids[5] = { 1, 2, 3, 4, 5 }; -struct mib_node* const tcpconnentry_nodes[5] = { - (struct mib_node*)&tcpconntree_root, (struct mib_node*)&tcpconntree_root, - (struct mib_node*)&tcpconntree_root, (struct mib_node*)&tcpconntree_root, - (struct mib_node*)&tcpconntree_root -}; -const struct mib_array_node tcpconnentry = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 5, - tcpconnentry_ids, - tcpconnentry_nodes -}; - -s32_t tcpconntable_id = 1; -struct mib_node* tcpconntable_node = (struct mib_node*)&tcpconnentry; -struct mib_ram_array_node tcpconntable = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_RA, -/** @todo update maxlength when inserting / deleting from table - 0 when table is empty, 1 when more than one entry */ - 0, - &tcpconntable_id, - &tcpconntable_node -}; - -const mib_scalar_node tcp_scalar = { - &tcp_get_object_def, - &tcp_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_SC, - 0 -}; -const s32_t tcp_ids[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; -struct mib_node* const tcp_nodes[15] = { - (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, - (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, - (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, - (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, - (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, - (struct mib_node*)&tcp_scalar, (struct mib_node*)&tcp_scalar, - (struct mib_node*)&tcpconntable, (struct mib_node*)&tcp_scalar, - (struct mib_node*)&tcp_scalar -}; -const struct mib_array_node tcp = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 15, - tcp_ids, - tcp_nodes -}; -#endif - -/* icmp .1.3.6.1.2.1.5 */ -const mib_scalar_node icmp_scalar = { - &icmp_get_object_def, - &icmp_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_SC, - 0 -}; -const s32_t icmp_ids[26] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 }; -struct mib_node* const icmp_nodes[26] = { - (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, - (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, - (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, - (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, - (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, - (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, - (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, - (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, - (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, - (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, - (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, - (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar, - (struct mib_node*)&icmp_scalar, (struct mib_node*)&icmp_scalar -}; -const struct mib_array_node icmp = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 26, - icmp_ids, - icmp_nodes -}; - -/** index root node for ipNetToMediaTable */ -struct mib_list_rootnode ipntomtree_root = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_LR, - 0, - NULL, - NULL, - 0 -}; -const s32_t ipntomentry_ids[4] = { 1, 2, 3, 4 }; -struct mib_node* const ipntomentry_nodes[4] = { - (struct mib_node*)&ipntomtree_root, (struct mib_node*)&ipntomtree_root, - (struct mib_node*)&ipntomtree_root, (struct mib_node*)&ipntomtree_root -}; -const struct mib_array_node ipntomentry = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 4, - ipntomentry_ids, - ipntomentry_nodes -}; - -s32_t ipntomtable_id = 1; -struct mib_node* ipntomtable_node = (struct mib_node*)&ipntomentry; -struct mib_ram_array_node ipntomtable = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_RA, - 0, - &ipntomtable_id, - &ipntomtable_node -}; - -/** index root node for ipRouteTable */ -struct mib_list_rootnode iprtetree_root = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_LR, - 0, - NULL, - NULL, - 0 -}; -const s32_t iprteentry_ids[13] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }; -struct mib_node* const iprteentry_nodes[13] = { - (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, - (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, - (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, - (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, - (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, - (struct mib_node*)&iprtetree_root, (struct mib_node*)&iprtetree_root, - (struct mib_node*)&iprtetree_root -}; -const struct mib_array_node iprteentry = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 13, - iprteentry_ids, - iprteentry_nodes -}; - -s32_t iprtetable_id = 1; -struct mib_node* iprtetable_node = (struct mib_node*)&iprteentry; -struct mib_ram_array_node iprtetable = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_RA, - 0, - &iprtetable_id, - &iprtetable_node -}; - -/** index root node for ipAddrTable */ -struct mib_list_rootnode ipaddrtree_root = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_LR, - 0, - NULL, - NULL, - 0 -}; -const s32_t ipaddrentry_ids[5] = { 1, 2, 3, 4, 5 }; -struct mib_node* const ipaddrentry_nodes[5] = { - (struct mib_node*)&ipaddrtree_root, - (struct mib_node*)&ipaddrtree_root, - (struct mib_node*)&ipaddrtree_root, - (struct mib_node*)&ipaddrtree_root, - (struct mib_node*)&ipaddrtree_root -}; -const struct mib_array_node ipaddrentry = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 5, - ipaddrentry_ids, - ipaddrentry_nodes -}; - -s32_t ipaddrtable_id = 1; -struct mib_node* ipaddrtable_node = (struct mib_node*)&ipaddrentry; -struct mib_ram_array_node ipaddrtable = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_RA, - 0, - &ipaddrtable_id, - &ipaddrtable_node -}; - -/* ip .1.3.6.1.2.1.4 */ -const mib_scalar_node ip_scalar = { - &ip_get_object_def, - &ip_get_value, - &ip_set_test, - &noleafs_set_value, - MIB_NODE_SC, - 0 -}; -const s32_t ip_ids[23] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 }; -struct mib_node* const ip_nodes[23] = { - (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, - (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, - (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, - (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, - (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, - (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, - (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, - (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, - (struct mib_node*)&ip_scalar, (struct mib_node*)&ip_scalar, - (struct mib_node*)&ip_scalar, (struct mib_node*)&ipaddrtable, - (struct mib_node*)&iprtetable, (struct mib_node*)&ipntomtable, - (struct mib_node*)&ip_scalar -}; -const struct mib_array_node mib2_ip = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 23, - ip_ids, - ip_nodes -}; - -/** index root node for atTable */ -struct mib_list_rootnode arptree_root = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_LR, - 0, - NULL, - NULL, - 0 -}; -const s32_t atentry_ids[3] = { 1, 2, 3 }; -struct mib_node* const atentry_nodes[3] = { - (struct mib_node*)&arptree_root, - (struct mib_node*)&arptree_root, - (struct mib_node*)&arptree_root -}; -const struct mib_array_node atentry = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 3, - atentry_ids, - atentry_nodes -}; - -const s32_t attable_id = 1; -struct mib_node* const attable_node = (struct mib_node*)&atentry; -const struct mib_array_node attable = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 1, - &attable_id, - &attable_node -}; - -/* at .1.3.6.1.2.1.3 */ -s32_t at_id = 1; -struct mib_node* mib2_at_node = (struct mib_node*)&attable; -struct mib_ram_array_node at = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_RA, - 0, - &at_id, - &mib2_at_node -}; - -/** index root node for ifTable */ -struct mib_list_rootnode iflist_root = { - &ifentry_get_object_def, - &ifentry_get_value, -#if SNMP_SAFE_REQUESTS - &noleafs_set_test, - &noleafs_set_value, -#else /* SNMP_SAFE_REQUESTS */ - &ifentry_set_test, - &ifentry_set_value, -#endif /* SNMP_SAFE_REQUESTS */ - MIB_NODE_LR, - 0, - NULL, - NULL, - 0 -}; -const s32_t ifentry_ids[22] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 }; -struct mib_node* const ifentry_nodes[22] = { - (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, - (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, - (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, - (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, - (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, - (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, - (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, - (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, - (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, - (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root, - (struct mib_node*)&iflist_root, (struct mib_node*)&iflist_root -}; -const struct mib_array_node ifentry = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 22, - ifentry_ids, - ifentry_nodes -}; - -s32_t iftable_id = 1; -struct mib_node* iftable_node = (struct mib_node*)&ifentry; -struct mib_ram_array_node iftable = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_RA, - 0, - &iftable_id, - &iftable_node -}; - -/* interfaces .1.3.6.1.2.1.2 */ -const mib_scalar_node interfaces_scalar = { - &interfaces_get_object_def, - &interfaces_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_SC, - 0 -}; -const s32_t interfaces_ids[2] = { 1, 2 }; -struct mib_node* const interfaces_nodes[2] = { - (struct mib_node*)&interfaces_scalar, (struct mib_node*)&iftable -}; -const struct mib_array_node interfaces = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 2, - interfaces_ids, - interfaces_nodes -}; - - -/* 0 1 2 3 4 5 6 */ -/* system .1.3.6.1.2.1.1 */ -const mib_scalar_node sys_tem_scalar = { - &system_get_object_def, - &system_get_value, - &system_set_test, - &system_set_value, - MIB_NODE_SC, - 0 -}; -const s32_t sys_tem_ids[7] = { 1, 2, 3, 4, 5, 6, 7 }; -struct mib_node* const sys_tem_nodes[7] = { - (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar, - (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar, - (struct mib_node*)&sys_tem_scalar, (struct mib_node*)&sys_tem_scalar, - (struct mib_node*)&sys_tem_scalar -}; -/* work around name issue with 'sys_tem', some compiler(s?) seem to reserve 'system' */ -const struct mib_array_node sys_tem = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 7, - sys_tem_ids, - sys_tem_nodes -}; - -/* mib-2 .1.3.6.1.2.1 */ -#if LWIP_TCP -#define MIB2_GROUPS 8 -#else -#define MIB2_GROUPS 7 -#endif -const s32_t mib2_ids[MIB2_GROUPS] = -{ - 1, - 2, - 3, - 4, - 5, -#if LWIP_TCP - 6, -#endif - 7, - 11 -}; -struct mib_node* const mib2_nodes[MIB2_GROUPS] = { - (struct mib_node*)&sys_tem, - (struct mib_node*)&interfaces, - (struct mib_node*)&at, - (struct mib_node*)&mib2_ip, - (struct mib_node*)&icmp, -#if LWIP_TCP - (struct mib_node*)&tcp, -#endif - (struct mib_node*)&udp, - (struct mib_node*)&snmp -}; - -const struct mib_array_node mib2 = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - MIB2_GROUPS, - mib2_ids, - mib2_nodes -}; - -/* mgmt .1.3.6.1.2 */ -const s32_t mgmt_ids[1] = { 1 }; -struct mib_node* const mgmt_nodes[1] = { (struct mib_node*)&mib2 }; -const struct mib_array_node mgmt = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 1, - mgmt_ids, - mgmt_nodes -}; - -/* internet .1.3.6.1 */ -#if SNMP_PRIVATE_MIB -/* When using a private MIB, you have to create a file 'private_mib.h' that contains - * a 'struct mib_array_node mib_private' which contains your MIB. */ -s32_t internet_ids[2] = { 2, 4 }; -struct mib_node* const internet_nodes[2] = { (struct mib_node*)&mgmt, (struct mib_node*)&mib_private }; -const struct mib_array_node internet = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 2, - internet_ids, - internet_nodes -}; -#else -const s32_t internet_ids[1] = { 2 }; -struct mib_node* const internet_nodes[1] = { (struct mib_node*)&mgmt }; -const struct mib_array_node internet = { - &noleafs_get_object_def, - &noleafs_get_value, - &noleafs_set_test, - &noleafs_set_value, - MIB_NODE_AR, - 1, - internet_ids, - internet_nodes -}; -#endif - -/** mib-2.system.sysObjectID */ -static struct snmp_obj_id sysobjid = {SNMP_SYSOBJID_LEN, SNMP_SYSOBJID}; -/** enterprise ID for generic TRAPs, .iso.org.dod.internet.mgmt.mib-2.snmp */ -static struct snmp_obj_id snmpgrp_id = {7,{1,3,6,1,2,1,11}}; -/** mib-2.system.sysServices */ -static const s32_t sysservices = SNMP_SYSSERVICES; - -/** mib-2.system.sysDescr */ -static const u8_t sysdescr_len_default = 4; -static const u8_t sysdescr_default[] = "lwIP"; -static u8_t* sysdescr_len_ptr = (u8_t*)&sysdescr_len_default; -static u8_t* sysdescr_ptr = (u8_t*)&sysdescr_default[0]; -/** mib-2.system.sysContact */ -static const u8_t syscontact_len_default = 0; -static const u8_t syscontact_default[] = ""; -static u8_t* syscontact_len_ptr = (u8_t*)&syscontact_len_default; -static u8_t* syscontact_ptr = (u8_t*)&syscontact_default[0]; -/** mib-2.system.sysName */ -static const u8_t sysname_len_default = 8; -static const u8_t sysname_default[] = "FQDN-unk"; -static u8_t* sysname_len_ptr = (u8_t*)&sysname_len_default; -static u8_t* sysname_ptr = (u8_t*)&sysname_default[0]; -/** mib-2.system.sysLocation */ -static const u8_t syslocation_len_default = 0; -static const u8_t syslocation_default[] = ""; -static u8_t* syslocation_len_ptr = (u8_t*)&syslocation_len_default; -static u8_t* syslocation_ptr = (u8_t*)&syslocation_default[0]; -/** mib-2.snmp.snmpEnableAuthenTraps */ -static const u8_t snmpenableauthentraps_default = 2; /* disabled */ -static u8_t* snmpenableauthentraps_ptr = (u8_t*)&snmpenableauthentraps_default; - -/** mib-2.interfaces.ifTable.ifEntry.ifSpecific (zeroDotZero) */ -static const struct snmp_obj_id ifspecific = {2, {0, 0}}; -/** mib-2.ip.ipRouteTable.ipRouteEntry.ipRouteInfo (zeroDotZero) */ -static const struct snmp_obj_id iprouteinfo = {2, {0, 0}}; - - - -/* mib-2.system counter(s) */ -static u32_t sysuptime = 0; - -/* mib-2.ip counter(s) */ -static u32_t ipinreceives = 0, - ipinhdrerrors = 0, - ipinaddrerrors = 0, - ipforwdatagrams = 0, - ipinunknownprotos = 0, - ipindiscards = 0, - ipindelivers = 0, - ipoutrequests = 0, - ipoutdiscards = 0, - ipoutnoroutes = 0, - ipreasmreqds = 0, - ipreasmoks = 0, - ipreasmfails = 0, - ipfragoks = 0, - ipfragfails = 0, - ipfragcreates = 0, - iproutingdiscards = 0; -/* mib-2.icmp counter(s) */ -static u32_t icmpinmsgs = 0, - icmpinerrors = 0, - icmpindestunreachs = 0, - icmpintimeexcds = 0, - icmpinparmprobs = 0, - icmpinsrcquenchs = 0, - icmpinredirects = 0, - icmpinechos = 0, - icmpinechoreps = 0, - icmpintimestamps = 0, - icmpintimestampreps = 0, - icmpinaddrmasks = 0, - icmpinaddrmaskreps = 0, - icmpoutmsgs = 0, - icmpouterrors = 0, - icmpoutdestunreachs = 0, - icmpouttimeexcds = 0, - icmpoutparmprobs = 0, - icmpoutsrcquenchs = 0, - icmpoutredirects = 0, - icmpoutechos = 0, - icmpoutechoreps = 0, - icmpouttimestamps = 0, - icmpouttimestampreps = 0, - icmpoutaddrmasks = 0, - icmpoutaddrmaskreps = 0; -/* mib-2.tcp counter(s) */ -static u32_t tcpactiveopens = 0, - tcppassiveopens = 0, - tcpattemptfails = 0, - tcpestabresets = 0, - tcpinsegs = 0, - tcpoutsegs = 0, - tcpretranssegs = 0, - tcpinerrs = 0, - tcpoutrsts = 0; -/* mib-2.udp counter(s) */ -static u32_t udpindatagrams = 0, - udpnoports = 0, - udpinerrors = 0, - udpoutdatagrams = 0; -/* mib-2.snmp counter(s) */ -static u32_t snmpinpkts = 0, - snmpoutpkts = 0, - snmpinbadversions = 0, - snmpinbadcommunitynames = 0, - snmpinbadcommunityuses = 0, - snmpinasnparseerrs = 0, - snmpintoobigs = 0, - snmpinnosuchnames = 0, - snmpinbadvalues = 0, - snmpinreadonlys = 0, - snmpingenerrs = 0, - snmpintotalreqvars = 0, - snmpintotalsetvars = 0, - snmpingetrequests = 0, - snmpingetnexts = 0, - snmpinsetrequests = 0, - snmpingetresponses = 0, - snmpintraps = 0, - snmpouttoobigs = 0, - snmpoutnosuchnames = 0, - snmpoutbadvalues = 0, - snmpoutgenerrs = 0, - snmpoutgetrequests = 0, - snmpoutgetnexts = 0, - snmpoutsetrequests = 0, - snmpoutgetresponses = 0, - snmpouttraps = 0; - - - -/* prototypes of the following functions are in lwip/src/include/lwip/snmp.h */ -/** - * Copy octet string. - * - * @param dst points to destination - * @param src points to source - * @param n number of octets to copy. - */ -static void ocstrncpy(u8_t *dst, u8_t *src, u16_t n) -{ - u16_t i = n; - while (i > 0) { - i--; - *dst++ = *src++; - } -} - -/** - * Copy object identifier (s32_t) array. - * - * @param dst points to destination - * @param src points to source - * @param n number of sub identifiers to copy. - */ -void objectidncpy(s32_t *dst, s32_t *src, u8_t n) -{ - u8_t i = n; - while(i > 0) { - i--; - *dst++ = *src++; - } -} - -/** - * Initializes sysDescr pointers. - * - * @param str if non-NULL then copy str pointer - * @param len points to string length, excluding zero terminator - */ -void snmp_set_sysdesr(u8_t *str, u8_t *len) -{ - if (str != NULL) - { - sysdescr_ptr = str; - sysdescr_len_ptr = len; - } -} - -void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid) -{ - *oid = &sysobjid; -} - -/** - * Initializes sysObjectID value. - * - * @param oid points to stuct snmp_obj_id to copy - */ -void snmp_set_sysobjid(struct snmp_obj_id *oid) -{ - sysobjid = *oid; -} - -/** - * Must be called at regular 10 msec interval from a timer interrupt - * or signal handler depending on your runtime environment. - */ -void snmp_inc_sysuptime(void) -{ - sysuptime++; -} - -void snmp_add_sysuptime(u32_t value) -{ - sysuptime+=value; -} - -void snmp_get_sysuptime(u32_t *value) -{ - SNMP_GET_SYSUPTIME(sysuptime); - *value = sysuptime; -} - -/** - * Initializes sysContact pointers, - * e.g. ptrs to non-volatile memory external to lwIP. - * - * @param ocstr if non-NULL then copy str pointer - * @param ocstrlen points to string length, excluding zero terminator - */ -void snmp_set_syscontact(u8_t *ocstr, u8_t *ocstrlen) -{ - if (ocstr != NULL) - { - syscontact_ptr = ocstr; - syscontact_len_ptr = ocstrlen; - } -} - -/** - * Initializes sysName pointers, - * e.g. ptrs to non-volatile memory external to lwIP. - * - * @param ocstr if non-NULL then copy str pointer - * @param ocstrlen points to string length, excluding zero terminator - */ -void snmp_set_sysname(u8_t *ocstr, u8_t *ocstrlen) -{ - if (ocstr != NULL) - { - sysname_ptr = ocstr; - sysname_len_ptr = ocstrlen; - } -} - -/** - * Initializes sysLocation pointers, - * e.g. ptrs to non-volatile memory external to lwIP. - * - * @param ocstr if non-NULL then copy str pointer - * @param ocstrlen points to string length, excluding zero terminator - */ -void snmp_set_syslocation(u8_t *ocstr, u8_t *ocstrlen) -{ - if (ocstr != NULL) - { - syslocation_ptr = ocstr; - syslocation_len_ptr = ocstrlen; - } -} - - -void snmp_add_ifinoctets(struct netif *ni, u32_t value) -{ - ni->ifinoctets += value; -} - -void snmp_inc_ifinucastpkts(struct netif *ni) -{ - (ni->ifinucastpkts)++; -} - -void snmp_inc_ifinnucastpkts(struct netif *ni) -{ - (ni->ifinnucastpkts)++; -} - -void snmp_inc_ifindiscards(struct netif *ni) -{ - (ni->ifindiscards)++; -} - -void snmp_add_ifoutoctets(struct netif *ni, u32_t value) -{ - ni->ifoutoctets += value; -} - -void snmp_inc_ifoutucastpkts(struct netif *ni) -{ - (ni->ifoutucastpkts)++; -} - -void snmp_inc_ifoutnucastpkts(struct netif *ni) -{ - (ni->ifoutnucastpkts)++; -} - -void snmp_inc_ifoutdiscards(struct netif *ni) -{ - (ni->ifoutdiscards)++; -} - -void snmp_inc_iflist(void) -{ - struct mib_list_node *if_node = NULL; - - snmp_mib_node_insert(&iflist_root, iflist_root.count + 1, &if_node); - /* enable getnext traversal on filled table */ - iftable.maxlength = 1; -} - -void snmp_dec_iflist(void) -{ - snmp_mib_node_delete(&iflist_root, iflist_root.tail); - /* disable getnext traversal on empty table */ - if(iflist_root.count == 0) iftable.maxlength = 0; -} - -/** - * Inserts ARP table indexes (.xIfIndex.xNetAddress) - * into arp table index trees (both atTable and ipNetToMediaTable). - */ -void snmp_insert_arpidx_tree(struct netif *ni, ip_addr_t *ip) -{ - struct mib_list_rootnode *at_rn; - struct mib_list_node *at_node; - s32_t arpidx[5]; - u8_t level, tree; - - LWIP_ASSERT("ni != NULL", ni != NULL); - snmp_netiftoifindex(ni, &arpidx[0]); - snmp_iptooid(ip, &arpidx[1]); - - for (tree = 0; tree < 2; tree++) - { - if (tree == 0) - { - at_rn = &arptree_root; - } - else - { - at_rn = &ipntomtree_root; - } - for (level = 0; level < 5; level++) - { - at_node = NULL; - snmp_mib_node_insert(at_rn, arpidx[level], &at_node); - if ((level != 4) && (at_node != NULL)) - { - if (at_node->nptr == NULL) - { - at_rn = snmp_mib_lrn_alloc(); - at_node->nptr = (struct mib_node*)at_rn; - if (at_rn != NULL) - { - if (level == 3) - { - if (tree == 0) - { - at_rn->get_object_def = atentry_get_object_def; - at_rn->get_value = atentry_get_value; - } - else - { - at_rn->get_object_def = ip_ntomentry_get_object_def; - at_rn->get_value = ip_ntomentry_get_value; - } - at_rn->set_test = noleafs_set_test; - at_rn->set_value = noleafs_set_value; - } - } - else - { - /* at_rn == NULL, malloc failure */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_arpidx_tree() insert failed, mem full")); - break; - } - } - else - { - at_rn = (struct mib_list_rootnode*)at_node->nptr; - } - } - } - } - /* enable getnext traversal on filled tables */ - at.maxlength = 1; - ipntomtable.maxlength = 1; -} - -/** - * Removes ARP table indexes (.xIfIndex.xNetAddress) - * from arp table index trees. - */ -void snmp_delete_arpidx_tree(struct netif *ni, ip_addr_t *ip) -{ - struct mib_list_rootnode *at_rn, *next, *del_rn[5]; - struct mib_list_node *at_n, *del_n[5]; - s32_t arpidx[5]; - u8_t fc, tree, level, del_cnt; - - snmp_netiftoifindex(ni, &arpidx[0]); - snmp_iptooid(ip, &arpidx[1]); - - for (tree = 0; tree < 2; tree++) - { - /* mark nodes for deletion */ - if (tree == 0) - { - at_rn = &arptree_root; - } - else - { - at_rn = &ipntomtree_root; - } - level = 0; - del_cnt = 0; - while ((level < 5) && (at_rn != NULL)) - { - fc = snmp_mib_node_find(at_rn, arpidx[level], &at_n); - if (fc == 0) - { - /* arpidx[level] does not exist */ - del_cnt = 0; - at_rn = NULL; - } - else if (fc == 1) - { - del_rn[del_cnt] = at_rn; - del_n[del_cnt] = at_n; - del_cnt++; - at_rn = (struct mib_list_rootnode*)(at_n->nptr); - } - else if (fc == 2) - { - /* reset delete (2 or more childs) */ - del_cnt = 0; - at_rn = (struct mib_list_rootnode*)(at_n->nptr); - } - level++; - } - /* delete marked index nodes */ - while (del_cnt > 0) - { - del_cnt--; - - at_rn = del_rn[del_cnt]; - at_n = del_n[del_cnt]; - - next = snmp_mib_node_delete(at_rn, at_n); - if (next != NULL) - { - LWIP_ASSERT("next_count == 0",next->count == 0); - snmp_mib_lrn_free(next); - } - } - } - /* disable getnext traversal on empty tables */ - if(arptree_root.count == 0) at.maxlength = 0; - if(ipntomtree_root.count == 0) ipntomtable.maxlength = 0; -} - -void snmp_inc_ipinreceives(void) -{ - ipinreceives++; -} - -void snmp_inc_ipinhdrerrors(void) -{ - ipinhdrerrors++; -} - -void snmp_inc_ipinaddrerrors(void) -{ - ipinaddrerrors++; -} - -void snmp_inc_ipforwdatagrams(void) -{ - ipforwdatagrams++; -} - -void snmp_inc_ipinunknownprotos(void) -{ - ipinunknownprotos++; -} - -void snmp_inc_ipindiscards(void) -{ - ipindiscards++; -} - -void snmp_inc_ipindelivers(void) -{ - ipindelivers++; -} - -void snmp_inc_ipoutrequests(void) -{ - ipoutrequests++; -} - -void snmp_inc_ipoutdiscards(void) -{ - ipoutdiscards++; -} - -void snmp_inc_ipoutnoroutes(void) -{ - ipoutnoroutes++; -} - -void snmp_inc_ipreasmreqds(void) -{ - ipreasmreqds++; -} - -void snmp_inc_ipreasmoks(void) -{ - ipreasmoks++; -} - -void snmp_inc_ipreasmfails(void) -{ - ipreasmfails++; -} - -void snmp_inc_ipfragoks(void) -{ - ipfragoks++; -} - -void snmp_inc_ipfragfails(void) -{ - ipfragfails++; -} - -void snmp_inc_ipfragcreates(void) -{ - ipfragcreates++; -} - -void snmp_inc_iproutingdiscards(void) -{ - iproutingdiscards++; -} - -/** - * Inserts ipAddrTable indexes (.ipAdEntAddr) - * into index tree. - */ -void snmp_insert_ipaddridx_tree(struct netif *ni) -{ - struct mib_list_rootnode *ipa_rn; - struct mib_list_node *ipa_node; - s32_t ipaddridx[4]; - u8_t level; - - LWIP_ASSERT("ni != NULL", ni != NULL); - snmp_iptooid(&ni->ip_addr, &ipaddridx[0]); - - level = 0; - ipa_rn = &ipaddrtree_root; - while (level < 4) - { - ipa_node = NULL; - snmp_mib_node_insert(ipa_rn, ipaddridx[level], &ipa_node); - if ((level != 3) && (ipa_node != NULL)) - { - if (ipa_node->nptr == NULL) - { - ipa_rn = snmp_mib_lrn_alloc(); - ipa_node->nptr = (struct mib_node*)ipa_rn; - if (ipa_rn != NULL) - { - if (level == 2) - { - ipa_rn->get_object_def = ip_addrentry_get_object_def; - ipa_rn->get_value = ip_addrentry_get_value; - ipa_rn->set_test = noleafs_set_test; - ipa_rn->set_value = noleafs_set_value; - } - } - else - { - /* ipa_rn == NULL, malloc failure */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_ipaddridx_tree() insert failed, mem full")); - break; - } - } - else - { - ipa_rn = (struct mib_list_rootnode*)ipa_node->nptr; - } - } - level++; - } - /* enable getnext traversal on filled table */ - ipaddrtable.maxlength = 1; -} - -/** - * Removes ipAddrTable indexes (.ipAdEntAddr) - * from index tree. - */ -void snmp_delete_ipaddridx_tree(struct netif *ni) -{ - struct mib_list_rootnode *ipa_rn, *next, *del_rn[4]; - struct mib_list_node *ipa_n, *del_n[4]; - s32_t ipaddridx[4]; - u8_t fc, level, del_cnt; - - LWIP_ASSERT("ni != NULL", ni != NULL); - snmp_iptooid(&ni->ip_addr, &ipaddridx[0]); - - /* mark nodes for deletion */ - level = 0; - del_cnt = 0; - ipa_rn = &ipaddrtree_root; - while ((level < 4) && (ipa_rn != NULL)) - { - fc = snmp_mib_node_find(ipa_rn, ipaddridx[level], &ipa_n); - if (fc == 0) - { - /* ipaddridx[level] does not exist */ - del_cnt = 0; - ipa_rn = NULL; - } - else if (fc == 1) - { - del_rn[del_cnt] = ipa_rn; - del_n[del_cnt] = ipa_n; - del_cnt++; - ipa_rn = (struct mib_list_rootnode*)(ipa_n->nptr); - } - else if (fc == 2) - { - /* reset delete (2 or more childs) */ - del_cnt = 0; - ipa_rn = (struct mib_list_rootnode*)(ipa_n->nptr); - } - level++; - } - /* delete marked index nodes */ - while (del_cnt > 0) - { - del_cnt--; - - ipa_rn = del_rn[del_cnt]; - ipa_n = del_n[del_cnt]; - - next = snmp_mib_node_delete(ipa_rn, ipa_n); - if (next != NULL) - { - LWIP_ASSERT("next_count == 0",next->count == 0); - snmp_mib_lrn_free(next); - } - } - /* disable getnext traversal on empty table */ - if (ipaddrtree_root.count == 0) ipaddrtable.maxlength = 0; -} - -/** - * Inserts ipRouteTable indexes (.ipRouteDest) - * into index tree. - * - * @param dflt non-zero for the default rte, zero for network rte - * @param ni points to network interface for this rte - * - * @todo record sysuptime for _this_ route when it is installed - * (needed for ipRouteAge) in the netif. - */ -void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni) -{ - u8_t insert = 0; - ip_addr_t dst; - - if (dflt != 0) - { - /* the default route 0.0.0.0 */ - ip_addr_set_any(&dst); - insert = 1; - } - else - { - /* route to the network address */ - ip_addr_get_network(&dst, &ni->ip_addr, &ni->netmask); - /* exclude 0.0.0.0 network (reserved for default rte) */ - if (!ip_addr_isany(&dst)) { - insert = 1; - } - } - if (insert) - { - struct mib_list_rootnode *iprte_rn; - struct mib_list_node *iprte_node; - s32_t iprteidx[4]; - u8_t level; - - snmp_iptooid(&dst, &iprteidx[0]); - level = 0; - iprte_rn = &iprtetree_root; - while (level < 4) - { - iprte_node = NULL; - snmp_mib_node_insert(iprte_rn, iprteidx[level], &iprte_node); - if ((level != 3) && (iprte_node != NULL)) - { - if (iprte_node->nptr == NULL) - { - iprte_rn = snmp_mib_lrn_alloc(); - iprte_node->nptr = (struct mib_node*)iprte_rn; - if (iprte_rn != NULL) - { - if (level == 2) - { - iprte_rn->get_object_def = ip_rteentry_get_object_def; - iprte_rn->get_value = ip_rteentry_get_value; - iprte_rn->set_test = noleafs_set_test; - iprte_rn->set_value = noleafs_set_value; - } - } - else - { - /* iprte_rn == NULL, malloc failure */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_iprteidx_tree() insert failed, mem full")); - break; - } - } - else - { - iprte_rn = (struct mib_list_rootnode*)iprte_node->nptr; - } - } - level++; - } - } - /* enable getnext traversal on filled table */ - iprtetable.maxlength = 1; -} - -/** - * Removes ipRouteTable indexes (.ipRouteDest) - * from index tree. - * - * @param dflt non-zero for the default rte, zero for network rte - * @param ni points to network interface for this rte or NULL - * for default route to be removed. - */ -void snmp_delete_iprteidx_tree(u8_t dflt, struct netif *ni) -{ - u8_t del = 0; - ip_addr_t dst; - - if (dflt != 0) - { - /* the default route 0.0.0.0 */ - ip_addr_set_any(&dst); - del = 1; - } - else - { - /* route to the network address */ - ip_addr_get_network(&dst, &ni->ip_addr, &ni->netmask); - /* exclude 0.0.0.0 network (reserved for default rte) */ - if (!ip_addr_isany(&dst)) { - del = 1; - } - } - if (del) - { - struct mib_list_rootnode *iprte_rn, *next, *del_rn[4]; - struct mib_list_node *iprte_n, *del_n[4]; - s32_t iprteidx[4]; - u8_t fc, level, del_cnt; - - snmp_iptooid(&dst, &iprteidx[0]); - /* mark nodes for deletion */ - level = 0; - del_cnt = 0; - iprte_rn = &iprtetree_root; - while ((level < 4) && (iprte_rn != NULL)) - { - fc = snmp_mib_node_find(iprte_rn, iprteidx[level], &iprte_n); - if (fc == 0) - { - /* iprteidx[level] does not exist */ - del_cnt = 0; - iprte_rn = NULL; - } - else if (fc == 1) - { - del_rn[del_cnt] = iprte_rn; - del_n[del_cnt] = iprte_n; - del_cnt++; - iprte_rn = (struct mib_list_rootnode*)(iprte_n->nptr); - } - else if (fc == 2) - { - /* reset delete (2 or more childs) */ - del_cnt = 0; - iprte_rn = (struct mib_list_rootnode*)(iprte_n->nptr); - } - level++; - } - /* delete marked index nodes */ - while (del_cnt > 0) - { - del_cnt--; - - iprte_rn = del_rn[del_cnt]; - iprte_n = del_n[del_cnt]; - - next = snmp_mib_node_delete(iprte_rn, iprte_n); - if (next != NULL) - { - LWIP_ASSERT("next_count == 0",next->count == 0); - snmp_mib_lrn_free(next); - } - } - } - /* disable getnext traversal on empty table */ - if (iprtetree_root.count == 0) iprtetable.maxlength = 0; -} - - -void snmp_inc_icmpinmsgs(void) -{ - icmpinmsgs++; -} - -void snmp_inc_icmpinerrors(void) -{ - icmpinerrors++; -} - -void snmp_inc_icmpindestunreachs(void) -{ - icmpindestunreachs++; -} - -void snmp_inc_icmpintimeexcds(void) -{ - icmpintimeexcds++; -} - -void snmp_inc_icmpinparmprobs(void) -{ - icmpinparmprobs++; -} - -void snmp_inc_icmpinsrcquenchs(void) -{ - icmpinsrcquenchs++; -} - -void snmp_inc_icmpinredirects(void) -{ - icmpinredirects++; -} - -void snmp_inc_icmpinechos(void) -{ - icmpinechos++; -} - -void snmp_inc_icmpinechoreps(void) -{ - icmpinechoreps++; -} - -void snmp_inc_icmpintimestamps(void) -{ - icmpintimestamps++; -} - -void snmp_inc_icmpintimestampreps(void) -{ - icmpintimestampreps++; -} - -void snmp_inc_icmpinaddrmasks(void) -{ - icmpinaddrmasks++; -} - -void snmp_inc_icmpinaddrmaskreps(void) -{ - icmpinaddrmaskreps++; -} - -void snmp_inc_icmpoutmsgs(void) -{ - icmpoutmsgs++; -} - -void snmp_inc_icmpouterrors(void) -{ - icmpouterrors++; -} - -void snmp_inc_icmpoutdestunreachs(void) -{ - icmpoutdestunreachs++; -} - -void snmp_inc_icmpouttimeexcds(void) -{ - icmpouttimeexcds++; -} - -void snmp_inc_icmpoutparmprobs(void) -{ - icmpoutparmprobs++; -} - -void snmp_inc_icmpoutsrcquenchs(void) -{ - icmpoutsrcquenchs++; -} - -void snmp_inc_icmpoutredirects(void) -{ - icmpoutredirects++; -} - -void snmp_inc_icmpoutechos(void) -{ - icmpoutechos++; -} - -void snmp_inc_icmpoutechoreps(void) -{ - icmpoutechoreps++; -} - -void snmp_inc_icmpouttimestamps(void) -{ - icmpouttimestamps++; -} - -void snmp_inc_icmpouttimestampreps(void) -{ - icmpouttimestampreps++; -} - -void snmp_inc_icmpoutaddrmasks(void) -{ - icmpoutaddrmasks++; -} - -void snmp_inc_icmpoutaddrmaskreps(void) -{ - icmpoutaddrmaskreps++; -} - -void snmp_inc_tcpactiveopens(void) -{ - tcpactiveopens++; -} - -void snmp_inc_tcppassiveopens(void) -{ - tcppassiveopens++; -} - -void snmp_inc_tcpattemptfails(void) -{ - tcpattemptfails++; -} - -void snmp_inc_tcpestabresets(void) -{ - tcpestabresets++; -} - -void snmp_inc_tcpinsegs(void) -{ - tcpinsegs++; -} - -void snmp_inc_tcpoutsegs(void) -{ - tcpoutsegs++; -} - -void snmp_inc_tcpretranssegs(void) -{ - tcpretranssegs++; -} - -void snmp_inc_tcpinerrs(void) -{ - tcpinerrs++; -} - -void snmp_inc_tcpoutrsts(void) -{ - tcpoutrsts++; -} - -void snmp_inc_udpindatagrams(void) -{ - udpindatagrams++; -} - -void snmp_inc_udpnoports(void) -{ - udpnoports++; -} - -void snmp_inc_udpinerrors(void) -{ - udpinerrors++; -} - -void snmp_inc_udpoutdatagrams(void) -{ - udpoutdatagrams++; -} - -/** - * Inserts udpTable indexes (.udpLocalAddress.udpLocalPort) - * into index tree. - */ -void snmp_insert_udpidx_tree(struct udp_pcb *pcb) -{ - struct mib_list_rootnode *udp_rn; - struct mib_list_node *udp_node; - s32_t udpidx[5]; - u8_t level; - - LWIP_ASSERT("pcb != NULL", pcb != NULL); - snmp_iptooid(ipX_2_ip(&pcb->local_ip), &udpidx[0]); - udpidx[4] = pcb->local_port; - - udp_rn = &udp_root; - for (level = 0; level < 5; level++) - { - udp_node = NULL; - snmp_mib_node_insert(udp_rn, udpidx[level], &udp_node); - if ((level != 4) && (udp_node != NULL)) - { - if (udp_node->nptr == NULL) - { - udp_rn = snmp_mib_lrn_alloc(); - udp_node->nptr = (struct mib_node*)udp_rn; - if (udp_rn != NULL) - { - if (level == 3) - { - udp_rn->get_object_def = udpentry_get_object_def; - udp_rn->get_value = udpentry_get_value; - udp_rn->set_test = noleafs_set_test; - udp_rn->set_value = noleafs_set_value; - } - } - else - { - /* udp_rn == NULL, malloc failure */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_insert_udpidx_tree() insert failed, mem full")); - break; - } - } - else - { - udp_rn = (struct mib_list_rootnode*)udp_node->nptr; - } - } - } - udptable.maxlength = 1; -} - -/** - * Removes udpTable indexes (.udpLocalAddress.udpLocalPort) - * from index tree. - */ -void snmp_delete_udpidx_tree(struct udp_pcb *pcb) -{ - struct udp_pcb *npcb; - struct mib_list_rootnode *udp_rn, *next, *del_rn[5]; - struct mib_list_node *udp_n, *del_n[5]; - s32_t udpidx[5]; - u8_t bindings, fc, level, del_cnt; - - LWIP_ASSERT("pcb != NULL", pcb != NULL); - snmp_iptooid(ipX_2_ip(&pcb->local_ip), &udpidx[0]); - udpidx[4] = pcb->local_port; - - /* count PCBs for a given binding - (e.g. when reusing ports or for temp output PCBs) */ - bindings = 0; - npcb = udp_pcbs; - while ((npcb != NULL)) - { - if (ipX_addr_cmp(0, &npcb->local_ip, &pcb->local_ip) && - (npcb->local_port == udpidx[4])) - { - bindings++; - } - npcb = npcb->next; - } - if (bindings == 1) - { - /* selectively remove */ - /* mark nodes for deletion */ - level = 0; - del_cnt = 0; - udp_rn = &udp_root; - while ((level < 5) && (udp_rn != NULL)) - { - fc = snmp_mib_node_find(udp_rn, udpidx[level], &udp_n); - if (fc == 0) - { - /* udpidx[level] does not exist */ - del_cnt = 0; - udp_rn = NULL; - } - else if (fc == 1) - { - del_rn[del_cnt] = udp_rn; - del_n[del_cnt] = udp_n; - del_cnt++; - udp_rn = (struct mib_list_rootnode*)(udp_n->nptr); - } - else if (fc == 2) - { - /* reset delete (2 or more childs) */ - del_cnt = 0; - udp_rn = (struct mib_list_rootnode*)(udp_n->nptr); - } - level++; - } - /* delete marked index nodes */ - while (del_cnt > 0) - { - del_cnt--; - - udp_rn = del_rn[del_cnt]; - udp_n = del_n[del_cnt]; - - next = snmp_mib_node_delete(udp_rn, udp_n); - if (next != NULL) - { - LWIP_ASSERT("next_count == 0",next->count == 0); - snmp_mib_lrn_free(next); - } - } - } - /* disable getnext traversal on empty table */ - if (udp_root.count == 0) udptable.maxlength = 0; -} - - -void snmp_inc_snmpinpkts(void) -{ - snmpinpkts++; -} - -void snmp_inc_snmpoutpkts(void) -{ - snmpoutpkts++; -} - -void snmp_inc_snmpinbadversions(void) -{ - snmpinbadversions++; -} - -void snmp_inc_snmpinbadcommunitynames(void) -{ - snmpinbadcommunitynames++; -} - -void snmp_inc_snmpinbadcommunityuses(void) -{ - snmpinbadcommunityuses++; -} - -void snmp_inc_snmpinasnparseerrs(void) -{ - snmpinasnparseerrs++; -} - -void snmp_inc_snmpintoobigs(void) -{ - snmpintoobigs++; -} - -void snmp_inc_snmpinnosuchnames(void) -{ - snmpinnosuchnames++; -} - -void snmp_inc_snmpinbadvalues(void) -{ - snmpinbadvalues++; -} - -void snmp_inc_snmpinreadonlys(void) -{ - snmpinreadonlys++; -} - -void snmp_inc_snmpingenerrs(void) -{ - snmpingenerrs++; -} - -void snmp_add_snmpintotalreqvars(u8_t value) -{ - snmpintotalreqvars += value; -} - -void snmp_add_snmpintotalsetvars(u8_t value) -{ - snmpintotalsetvars += value; -} - -void snmp_inc_snmpingetrequests(void) -{ - snmpingetrequests++; -} - -void snmp_inc_snmpingetnexts(void) -{ - snmpingetnexts++; -} - -void snmp_inc_snmpinsetrequests(void) -{ - snmpinsetrequests++; -} - -void snmp_inc_snmpingetresponses(void) -{ - snmpingetresponses++; -} - -void snmp_inc_snmpintraps(void) -{ - snmpintraps++; -} - -void snmp_inc_snmpouttoobigs(void) -{ - snmpouttoobigs++; -} - -void snmp_inc_snmpoutnosuchnames(void) -{ - snmpoutnosuchnames++; -} - -void snmp_inc_snmpoutbadvalues(void) -{ - snmpoutbadvalues++; -} - -void snmp_inc_snmpoutgenerrs(void) -{ - snmpoutgenerrs++; -} - -void snmp_inc_snmpoutgetrequests(void) -{ - snmpoutgetrequests++; -} - -void snmp_inc_snmpoutgetnexts(void) -{ - snmpoutgetnexts++; -} - -void snmp_inc_snmpoutsetrequests(void) -{ - snmpoutsetrequests++; -} - -void snmp_inc_snmpoutgetresponses(void) -{ - snmpoutgetresponses++; -} - -void snmp_inc_snmpouttraps(void) -{ - snmpouttraps++; -} - -void snmp_get_snmpgrpid_ptr(struct snmp_obj_id **oid) -{ - *oid = &snmpgrp_id; -} - -void snmp_set_snmpenableauthentraps(u8_t *value) -{ - if (value != NULL) - { - snmpenableauthentraps_ptr = value; - } -} - -void snmp_get_snmpenableauthentraps(u8_t *value) -{ - *value = *snmpenableauthentraps_ptr; -} - -void -noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) -{ - LWIP_UNUSED_ARG(ident_len); - LWIP_UNUSED_ARG(ident); - od->instance = MIB_OBJECT_NONE; -} - -void -noleafs_get_value(struct obj_def *od, u16_t len, void *value) -{ - LWIP_UNUSED_ARG(od); - LWIP_UNUSED_ARG(len); - LWIP_UNUSED_ARG(value); -} - -u8_t -noleafs_set_test(struct obj_def *od, u16_t len, void *value) -{ - LWIP_UNUSED_ARG(od); - LWIP_UNUSED_ARG(len); - LWIP_UNUSED_ARG(value); - /* can't set */ - return 0; -} - -void -noleafs_set_value(struct obj_def *od, u16_t len, void *value) -{ - LWIP_UNUSED_ARG(od); - LWIP_UNUSED_ARG(len); - LWIP_UNUSED_ARG(value); -} - - -/** - * Returns systems object definitions. - * - * @param ident_len the address length (2) - * @param ident points to objectname.0 (object id trailer) - * @param od points to object definition. - */ -static void -system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) -{ - u8_t id; - - /* return to object name, adding index depth (1) */ - ident_len += 1; - ident -= 1; - if (ident_len == 2) - { - od->id_inst_len = ident_len; - od->id_inst_ptr = ident; - - LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); - id = (u8_t)ident[0]; - LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def system.%"U16_F".0\n",(u16_t)id)); - switch (id) - { - case 1: /* sysDescr */ - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); - od->v_len = *sysdescr_len_ptr; - break; - case 2: /* sysObjectID */ - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); - od->v_len = sysobjid.len * sizeof(s32_t); - break; - case 3: /* sysUpTime */ - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS); - od->v_len = sizeof(u32_t); - break; - case 4: /* sysContact */ - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_WRITE; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); - od->v_len = *syscontact_len_ptr; - break; - case 5: /* sysName */ - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_WRITE; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); - od->v_len = *sysname_len_ptr; - break; - case 6: /* sysLocation */ - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_WRITE; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); - od->v_len = *syslocation_len_ptr; - break; - case 7: /* sysServices */ - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); - od->v_len = sizeof(s32_t); - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_object_def: no such object\n")); - od->instance = MIB_OBJECT_NONE; - break; - }; - } - else - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_object_def: no scalar\n")); - od->instance = MIB_OBJECT_NONE; - } -} - -/** - * Returns system object value. - * - * @param ident_len the address length (2) - * @param ident points to objectname.0 (object id trailer) - * @param len return value space (in bytes) - * @param value points to (varbind) space to copy value into. - */ -static void -system_get_value(struct obj_def *od, u16_t len, void *value) -{ - u8_t id; - - LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); - id = (u8_t)od->id_inst_ptr[0]; - switch (id) - { - case 1: /* sysDescr */ - ocstrncpy((u8_t*)value, sysdescr_ptr, len); - break; - case 2: /* sysObjectID */ - objectidncpy((s32_t*)value, (s32_t*)sysobjid.id, (u8_t)(len / sizeof(s32_t))); - break; - case 3: /* sysUpTime */ - { - snmp_get_sysuptime((u32_t*)value); - } - break; - case 4: /* sysContact */ - ocstrncpy((u8_t*)value, syscontact_ptr, len); - break; - case 5: /* sysName */ - ocstrncpy((u8_t*)value, sysname_ptr, len); - break; - case 6: /* sysLocation */ - ocstrncpy((u8_t*)value, syslocation_ptr, len); - break; - case 7: /* sysServices */ - { - s32_t *sint_ptr = (s32_t*)value; - *sint_ptr = sysservices; - } - break; - }; -} - -static u8_t -system_set_test(struct obj_def *od, u16_t len, void *value) -{ - u8_t id, set_ok; - - LWIP_UNUSED_ARG(value); - set_ok = 0; - LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); - id = (u8_t)od->id_inst_ptr[0]; - switch (id) - { - case 4: /* sysContact */ - if ((syscontact_ptr != syscontact_default) && - (len <= 255)) - { - set_ok = 1; - } - break; - case 5: /* sysName */ - if ((sysname_ptr != sysname_default) && - (len <= 255)) - { - set_ok = 1; - } - break; - case 6: /* sysLocation */ - if ((syslocation_ptr != syslocation_default) && - (len <= 255)) - { - set_ok = 1; - } - break; - }; - return set_ok; -} - -static void -system_set_value(struct obj_def *od, u16_t len, void *value) -{ - u8_t id; - - LWIP_ASSERT("invalid len", len <= 0xff); - LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); - id = (u8_t)od->id_inst_ptr[0]; - switch (id) - { - case 4: /* sysContact */ - ocstrncpy(syscontact_ptr, (u8_t*)value, len); - *syscontact_len_ptr = (u8_t)len; - break; - case 5: /* sysName */ - ocstrncpy(sysname_ptr, (u8_t*)value, len); - *sysname_len_ptr = (u8_t)len; - break; - case 6: /* sysLocation */ - ocstrncpy(syslocation_ptr, (u8_t*)value, len); - *syslocation_len_ptr = (u8_t)len; - break; - }; -} - -/** - * Returns interfaces.ifnumber object definition. - * - * @param ident_len the address length (2) - * @param ident points to objectname.index - * @param od points to object definition. - */ -static void -interfaces_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) -{ - /* return to object name, adding index depth (1) */ - ident_len += 1; - ident -= 1; - if (ident_len == 2) - { - od->id_inst_len = ident_len; - od->id_inst_ptr = ident; - - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); - od->v_len = sizeof(s32_t); - } - else - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("interfaces_get_object_def: no scalar\n")); - od->instance = MIB_OBJECT_NONE; - } -} - -/** - * Returns interfaces.ifnumber object value. - * - * @param ident_len the address length (2) - * @param ident points to objectname.0 (object id trailer) - * @param len return value space (in bytes) - * @param value points to (varbind) space to copy value into. - */ -static void -interfaces_get_value(struct obj_def *od, u16_t len, void *value) -{ - LWIP_UNUSED_ARG(len); - if (od->id_inst_ptr[0] == 1) - { - s32_t *sint_ptr = (s32_t*)value; - *sint_ptr = iflist_root.count; - } -} - -/** - * Returns ifentry object definitions. - * - * @param ident_len the address length (2) - * @param ident points to objectname.index - * @param od points to object definition. - */ -static void -ifentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) -{ - u8_t id; - - /* return to object name, adding index depth (1) */ - ident_len += 1; - ident -= 1; - if (ident_len == 2) - { - od->id_inst_len = ident_len; - od->id_inst_ptr = ident; - - LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); - id = (u8_t)ident[0]; - LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def ifentry.%"U16_F"\n",(u16_t)id)); - switch (id) - { - case 1: /* ifIndex */ - case 3: /* ifType */ - case 4: /* ifMtu */ - case 8: /* ifOperStatus */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); - od->v_len = sizeof(s32_t); - break; - case 2: /* ifDescr */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); - /** @todo this should be some sort of sizeof(struct netif.name) */ - od->v_len = 2; - break; - case 5: /* ifSpeed */ - case 21: /* ifOutQLen */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE); - od->v_len = sizeof(u32_t); - break; - case 6: /* ifPhysAddress */ - { - struct netif *netif; - - snmp_ifindextonetif(ident[1], &netif); - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); - od->v_len = netif->hwaddr_len; - } - break; - case 7: /* ifAdminStatus */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_WRITE; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); - od->v_len = sizeof(s32_t); - break; - case 9: /* ifLastChange */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS); - od->v_len = sizeof(u32_t); - break; - case 10: /* ifInOctets */ - case 11: /* ifInUcastPkts */ - case 12: /* ifInNUcastPkts */ - case 13: /* ifInDiscarts */ - case 14: /* ifInErrors */ - case 15: /* ifInUnkownProtos */ - case 16: /* ifOutOctets */ - case 17: /* ifOutUcastPkts */ - case 18: /* ifOutNUcastPkts */ - case 19: /* ifOutDiscarts */ - case 20: /* ifOutErrors */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); - od->v_len = sizeof(u32_t); - break; - case 22: /* ifSpecific */ - /** @note returning zeroDotZero (0.0) no media specific MIB support */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); - od->v_len = ifspecific.len * sizeof(s32_t); - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ifentry_get_object_def: no such object\n")); - od->instance = MIB_OBJECT_NONE; - break; - }; - } - else - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ifentry_get_object_def: no scalar\n")); - od->instance = MIB_OBJECT_NONE; - } -} - -/** - * Returns ifentry object value. - * - * @param ident_len the address length (2) - * @param ident points to objectname.0 (object id trailer) - * @param len return value space (in bytes) - * @param value points to (varbind) space to copy value into. - */ -static void -ifentry_get_value(struct obj_def *od, u16_t len, void *value) -{ - struct netif *netif; - u8_t id; - - snmp_ifindextonetif(od->id_inst_ptr[1], &netif); - LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); - id = (u8_t)od->id_inst_ptr[0]; - switch (id) - { - case 1: /* ifIndex */ - { - s32_t *sint_ptr = (s32_t*)value; - *sint_ptr = od->id_inst_ptr[1]; - } - break; - case 2: /* ifDescr */ - ocstrncpy((u8_t*)value, (u8_t*)netif->name, len); - break; - case 3: /* ifType */ - { - s32_t *sint_ptr = (s32_t*)value; - *sint_ptr = netif->link_type; - } - break; - case 4: /* ifMtu */ - { - s32_t *sint_ptr = (s32_t*)value; - *sint_ptr = netif->mtu; - } - break; - case 5: /* ifSpeed */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = netif->link_speed; - } - break; - case 6: /* ifPhysAddress */ - ocstrncpy((u8_t*)value, netif->hwaddr, len); - break; - case 7: /* ifAdminStatus */ - { - s32_t *sint_ptr = (s32_t*)value; - if (netif_is_up(netif)) - { - if (netif_is_link_up(netif)) - { - *sint_ptr = 1; /* up */ - } - else - { - *sint_ptr = 7; /* lowerLayerDown */ - } - } - else - { - *sint_ptr = 2; /* down */ - } - } - break; - case 8: /* ifOperStatus */ - { - s32_t *sint_ptr = (s32_t*)value; - if (netif_is_up(netif)) - { - *sint_ptr = 1; - } - else - { - *sint_ptr = 2; - } - } - break; - case 9: /* ifLastChange */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = netif->ts; - } - break; - case 10: /* ifInOctets */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = netif->ifinoctets; - } - break; - case 11: /* ifInUcastPkts */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = netif->ifinucastpkts; - } - break; - case 12: /* ifInNUcastPkts */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = netif->ifinnucastpkts; - } - break; - case 13: /* ifInDiscarts */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = netif->ifindiscards; - } - break; - case 14: /* ifInErrors */ - case 15: /* ifInUnkownProtos */ - /** @todo add these counters! */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = 0; - } - break; - case 16: /* ifOutOctets */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = netif->ifoutoctets; - } - break; - case 17: /* ifOutUcastPkts */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = netif->ifoutucastpkts; - } - break; - case 18: /* ifOutNUcastPkts */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = netif->ifoutnucastpkts; - } - break; - case 19: /* ifOutDiscarts */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = netif->ifoutdiscards; - } - break; - case 20: /* ifOutErrors */ - /** @todo add this counter! */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = 0; - } - break; - case 21: /* ifOutQLen */ - /** @todo figure out if this must be 0 (no queue) or 1? */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = 0; - } - break; - case 22: /* ifSpecific */ - objectidncpy((s32_t*)value, (s32_t*)ifspecific.id, (u8_t)(len / sizeof(s32_t))); - break; - }; -} - -#if !SNMP_SAFE_REQUESTS -static u8_t -ifentry_set_test(struct obj_def *od, u16_t len, void *value) -{ - struct netif *netif; - u8_t id, set_ok; - LWIP_UNUSED_ARG(len); - - set_ok = 0; - snmp_ifindextonetif(od->id_inst_ptr[1], &netif); - id = (u8_t)od->id_inst_ptr[0]; - switch (id) - { - case 7: /* ifAdminStatus */ - { - s32_t *sint_ptr = (s32_t*)value; - if (*sint_ptr == 1 || *sint_ptr == 2) - set_ok = 1; - } - break; - } - return set_ok; -} - -static void -ifentry_set_value(struct obj_def *od, u16_t len, void *value) -{ - struct netif *netif; - u8_t id; - LWIP_UNUSED_ARG(len); - - snmp_ifindextonetif(od->id_inst_ptr[1], &netif); - id = (u8_t)od->id_inst_ptr[0]; - switch (id) - { - case 7: /* ifAdminStatus */ - { - s32_t *sint_ptr = (s32_t*)value; - if (*sint_ptr == 1) - { - netif_set_up(netif); - } - else if (*sint_ptr == 2) - { - netif_set_down(netif); - } - } - break; - } -} -#endif /* SNMP_SAFE_REQUESTS */ - -/** - * Returns atentry object definitions. - * - * @param ident_len the address length (6) - * @param ident points to objectname.atifindex.atnetaddress - * @param od points to object definition. - */ -static void -atentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) -{ - /* return to object name, adding index depth (5) */ - ident_len += 5; - ident -= 5; - - if (ident_len == 6) - { - od->id_inst_len = ident_len; - od->id_inst_ptr = ident; - - switch (ident[0]) - { - case 1: /* atIfIndex */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_WRITE; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); - od->v_len = sizeof(s32_t); - break; - case 2: /* atPhysAddress */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_WRITE; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); - od->v_len = 6; /** @todo try to use netif::hwaddr_len */ - break; - case 3: /* atNetAddress */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_WRITE; - od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); - od->v_len = 4; - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("atentry_get_object_def: no such object\n")); - od->instance = MIB_OBJECT_NONE; - break; - } - } - else - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("atentry_get_object_def: no scalar\n")); - od->instance = MIB_OBJECT_NONE; - } -} - -static void -atentry_get_value(struct obj_def *od, u16_t len, void *value) -{ -#if LWIP_ARP - u8_t id; - struct eth_addr* ethaddr_ret; - ip_addr_t* ipaddr_ret; -#endif /* LWIP_ARP */ - ip_addr_t ip; - struct netif *netif; - - LWIP_UNUSED_ARG(len); - LWIP_UNUSED_ARG(value);/* if !LWIP_ARP */ - - snmp_ifindextonetif(od->id_inst_ptr[1], &netif); - snmp_oidtoip(&od->id_inst_ptr[2], &ip); - -#if LWIP_ARP /** @todo implement a netif_find_addr */ - if (etharp_find_addr(netif, &ip, ðaddr_ret, &ipaddr_ret) > -1) - { - LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); - id = (u8_t)od->id_inst_ptr[0]; - switch (id) - { - case 1: /* atIfIndex */ - { - s32_t *sint_ptr = (s32_t*)value; - *sint_ptr = od->id_inst_ptr[1]; - } - break; - case 2: /* atPhysAddress */ - { - struct eth_addr *dst = (struct eth_addr*)value; - - *dst = *ethaddr_ret; - } - break; - case 3: /* atNetAddress */ - { - ip_addr_t *dst = (ip_addr_t*)value; - - *dst = *ipaddr_ret; - } - break; - } - } -#endif /* LWIP_ARP */ -} - -static void -ip_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) -{ - u8_t id; - - /* return to object name, adding index depth (1) */ - ident_len += 1; - ident -= 1; - if (ident_len == 2) - { - od->id_inst_len = ident_len; - od->id_inst_ptr = ident; - - LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); - id = (u8_t)ident[0]; - LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def ip.%"U16_F".0\n",(u16_t)id)); - switch (id) - { - case 1: /* ipForwarding */ - case 2: /* ipDefaultTTL */ - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_WRITE; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); - od->v_len = sizeof(s32_t); - break; - case 3: /* ipInReceives */ - case 4: /* ipInHdrErrors */ - case 5: /* ipInAddrErrors */ - case 6: /* ipForwDatagrams */ - case 7: /* ipInUnknownProtos */ - case 8: /* ipInDiscards */ - case 9: /* ipInDelivers */ - case 10: /* ipOutRequests */ - case 11: /* ipOutDiscards */ - case 12: /* ipOutNoRoutes */ - case 14: /* ipReasmReqds */ - case 15: /* ipReasmOKs */ - case 16: /* ipReasmFails */ - case 17: /* ipFragOKs */ - case 18: /* ipFragFails */ - case 19: /* ipFragCreates */ - case 23: /* ipRoutingDiscards */ - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); - od->v_len = sizeof(u32_t); - break; - case 13: /* ipReasmTimeout */ - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); - od->v_len = sizeof(s32_t); - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_object_def: no such object\n")); - od->instance = MIB_OBJECT_NONE; - break; - }; - } - else - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_object_def: no scalar\n")); - od->instance = MIB_OBJECT_NONE; - } -} - -static void -ip_get_value(struct obj_def *od, u16_t len, void *value) -{ - u8_t id; - - LWIP_UNUSED_ARG(len); - LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); - id = (u8_t)od->id_inst_ptr[0]; - switch (id) - { - case 1: /* ipForwarding */ - { - s32_t *sint_ptr = (s32_t*)value; -#if IP_FORWARD - /* forwarding */ - *sint_ptr = 1; -#else - /* not-forwarding */ - *sint_ptr = 2; -#endif - } - break; - case 2: /* ipDefaultTTL */ - { - s32_t *sint_ptr = (s32_t*)value; - *sint_ptr = IP_DEFAULT_TTL; - } - break; - case 3: /* ipInReceives */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = ipinreceives; - } - break; - case 4: /* ipInHdrErrors */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = ipinhdrerrors; - } - break; - case 5: /* ipInAddrErrors */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = ipinaddrerrors; - } - break; - case 6: /* ipForwDatagrams */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = ipforwdatagrams; - } - break; - case 7: /* ipInUnknownProtos */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = ipinunknownprotos; - } - break; - case 8: /* ipInDiscards */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = ipindiscards; - } - break; - case 9: /* ipInDelivers */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = ipindelivers; - } - break; - case 10: /* ipOutRequests */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = ipoutrequests; - } - break; - case 11: /* ipOutDiscards */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = ipoutdiscards; - } - break; - case 12: /* ipOutNoRoutes */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = ipoutnoroutes; - } - break; - case 13: /* ipReasmTimeout */ - { - s32_t *sint_ptr = (s32_t*)value; -#if IP_REASSEMBLY - *sint_ptr = IP_REASS_MAXAGE; -#else - *sint_ptr = 0; -#endif - } - break; - case 14: /* ipReasmReqds */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = ipreasmreqds; - } - break; - case 15: /* ipReasmOKs */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = ipreasmoks; - } - break; - case 16: /* ipReasmFails */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = ipreasmfails; - } - break; - case 17: /* ipFragOKs */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = ipfragoks; - } - break; - case 18: /* ipFragFails */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = ipfragfails; - } - break; - case 19: /* ipFragCreates */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = ipfragcreates; - } - break; - case 23: /* ipRoutingDiscards */ - /** @todo can lwIP discard routes at all?? hardwire this to 0?? */ - { - u32_t *uint_ptr = (u32_t*)value; - *uint_ptr = iproutingdiscards; - } - break; - }; -} - -/** - * Test ip object value before setting. - * - * @param od is the object definition - * @param len return value space (in bytes) - * @param value points to (varbind) space to copy value from. - * - * @note we allow set if the value matches the hardwired value, - * otherwise return badvalue. - */ -static u8_t -ip_set_test(struct obj_def *od, u16_t len, void *value) -{ - u8_t id, set_ok; - s32_t *sint_ptr = (s32_t*)value; - - LWIP_UNUSED_ARG(len); - set_ok = 0; - LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); - id = (u8_t)od->id_inst_ptr[0]; - switch (id) - { - case 1: /* ipForwarding */ -#if IP_FORWARD - /* forwarding */ - if (*sint_ptr == 1) -#else - /* not-forwarding */ - if (*sint_ptr == 2) -#endif - { - set_ok = 1; - } - break; - case 2: /* ipDefaultTTL */ - if (*sint_ptr == IP_DEFAULT_TTL) - { - set_ok = 1; - } - break; - }; - return set_ok; -} - -static void -ip_addrentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) -{ - /* return to object name, adding index depth (4) */ - ident_len += 4; - ident -= 4; - - if (ident_len == 5) - { - u8_t id; - - od->id_inst_len = ident_len; - od->id_inst_ptr = ident; - - LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); - id = (u8_t)ident[0]; - switch (id) - { - case 1: /* ipAdEntAddr */ - case 3: /* ipAdEntNetMask */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); - od->v_len = 4; - break; - case 2: /* ipAdEntIfIndex */ - case 4: /* ipAdEntBcastAddr */ - case 5: /* ipAdEntReasmMaxSize */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); - od->v_len = sizeof(s32_t); - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_addrentry_get_object_def: no such object\n")); - od->instance = MIB_OBJECT_NONE; - break; - } - } - else - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_addrentry_get_object_def: no scalar\n")); - od->instance = MIB_OBJECT_NONE; - } -} - -static void -ip_addrentry_get_value(struct obj_def *od, u16_t len, void *value) -{ - u8_t id; - u16_t ifidx; - ip_addr_t ip; - struct netif *netif = netif_list; - - LWIP_UNUSED_ARG(len); - snmp_oidtoip(&od->id_inst_ptr[1], &ip); - ifidx = 0; - while ((netif != NULL) && !ip_addr_cmp(&ip, &netif->ip_addr)) - { - netif = netif->next; - ifidx++; - } - - if (netif != NULL) - { - LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); - id = (u8_t)od->id_inst_ptr[0]; - switch (id) - { - case 1: /* ipAdEntAddr */ - { - ip_addr_t *dst = (ip_addr_t*)value; - *dst = netif->ip_addr; - } - break; - case 2: /* ipAdEntIfIndex */ - { - s32_t *sint_ptr = (s32_t*)value; - *sint_ptr = ifidx + 1; - } - break; - case 3: /* ipAdEntNetMask */ - { - ip_addr_t *dst = (ip_addr_t*)value; - *dst = netif->netmask; - } - break; - case 4: /* ipAdEntBcastAddr */ - { - s32_t *sint_ptr = (s32_t*)value; - - /* lwIP oddity, there's no broadcast - address in the netif we can rely on */ - *sint_ptr = IPADDR_BROADCAST & 1; - } - break; - case 5: /* ipAdEntReasmMaxSize */ - { - s32_t *sint_ptr = (s32_t*)value; -#if IP_REASSEMBLY - /* @todo The theoretical maximum is IP_REASS_MAX_PBUFS * size of the pbufs, - * but only if receiving one fragmented packet at a time. - * The current solution is to calculate for 2 simultaneous packets... - */ - *sint_ptr = (IP_HLEN + ((IP_REASS_MAX_PBUFS/2) * - (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN - IP_HLEN))); -#else - /** @todo returning MTU would be a bad thing and - returning a wild guess like '576' isn't good either */ - *sint_ptr = 0; -#endif - } - break; - } - } -} - -/** - * @note - * lwIP IP routing is currently using the network addresses in netif_list. - * if no suitable network IP is found in netif_list, the default_netif is used. - */ -static void -ip_rteentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) -{ - u8_t id; - - /* return to object name, adding index depth (4) */ - ident_len += 4; - ident -= 4; - - if (ident_len == 5) - { - od->id_inst_len = ident_len; - od->id_inst_ptr = ident; - - LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); - id = (u8_t)ident[0]; - switch (id) - { - case 1: /* ipRouteDest */ - case 7: /* ipRouteNextHop */ - case 11: /* ipRouteMask */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_WRITE; - od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); - od->v_len = 4; - break; - case 2: /* ipRouteIfIndex */ - case 3: /* ipRouteMetric1 */ - case 4: /* ipRouteMetric2 */ - case 5: /* ipRouteMetric3 */ - case 6: /* ipRouteMetric4 */ - case 8: /* ipRouteType */ - case 10: /* ipRouteAge */ - case 12: /* ipRouteMetric5 */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_WRITE; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); - od->v_len = sizeof(s32_t); - break; - case 9: /* ipRouteProto */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); - od->v_len = sizeof(s32_t); - break; - case 13: /* ipRouteInfo */ - /** @note returning zeroDotZero (0.0) no routing protocol specific MIB */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); - od->v_len = iprouteinfo.len * sizeof(s32_t); - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_rteentry_get_object_def: no such object\n")); - od->instance = MIB_OBJECT_NONE; - break; - } - } - else - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_rteentry_get_object_def: no scalar\n")); - od->instance = MIB_OBJECT_NONE; - } -} - -static void -ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value) -{ - struct netif *netif; - ip_addr_t dest; - s32_t *ident; - u8_t id; - - ident = od->id_inst_ptr; - snmp_oidtoip(&ident[1], &dest); - - if (ip_addr_isany(&dest)) - { - /* ip_route() uses default netif for default route */ - netif = netif_default; - } - else - { - /* not using ip_route(), need exact match! */ - netif = netif_list; - while ((netif != NULL) && - !ip_addr_netcmp(&dest, &(netif->ip_addr), &(netif->netmask)) ) - { - netif = netif->next; - } - } - if (netif != NULL) - { - LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); - id = (u8_t)ident[0]; - switch (id) - { - case 1: /* ipRouteDest */ - { - ip_addr_t *dst = (ip_addr_t*)value; - - if (ip_addr_isany(&dest)) - { - /* default rte has 0.0.0.0 dest */ - ip_addr_set_zero(dst); - } - else - { - /* netifs have netaddress dest */ - ip_addr_get_network(dst, &netif->ip_addr, &netif->netmask); - } - } - break; - case 2: /* ipRouteIfIndex */ - { - s32_t *sint_ptr = (s32_t*)value; - - snmp_netiftoifindex(netif, sint_ptr); - } - break; - case 3: /* ipRouteMetric1 */ - { - s32_t *sint_ptr = (s32_t*)value; - - if (ip_addr_isany(&dest)) - { - /* default rte has metric 1 */ - *sint_ptr = 1; - } - else - { - /* other rtes have metric 0 */ - *sint_ptr = 0; - } - } - break; - case 4: /* ipRouteMetric2 */ - case 5: /* ipRouteMetric3 */ - case 6: /* ipRouteMetric4 */ - case 12: /* ipRouteMetric5 */ - { - s32_t *sint_ptr = (s32_t*)value; - /* not used */ - *sint_ptr = -1; - } - break; - case 7: /* ipRouteNextHop */ - { - ip_addr_t *dst = (ip_addr_t*)value; - - if (ip_addr_isany(&dest)) - { - /* default rte: gateway */ - *dst = netif->gw; - } - else - { - /* other rtes: netif ip_addr */ - *dst = netif->ip_addr; - } - } - break; - case 8: /* ipRouteType */ - { - s32_t *sint_ptr = (s32_t*)value; - - if (ip_addr_isany(&dest)) - { - /* default rte is indirect */ - *sint_ptr = 4; - } - else - { - /* other rtes are direct */ - *sint_ptr = 3; - } - } - break; - case 9: /* ipRouteProto */ - { - s32_t *sint_ptr = (s32_t*)value; - /* locally defined routes */ - *sint_ptr = 2; - } - break; - case 10: /* ipRouteAge */ - { - s32_t *sint_ptr = (s32_t*)value; - /** @todo (sysuptime - timestamp last change) / 100 - @see snmp_insert_iprteidx_tree() */ - *sint_ptr = 0; - } - break; - case 11: /* ipRouteMask */ - { - ip_addr_t *dst = (ip_addr_t*)value; - - if (ip_addr_isany(&dest)) - { - /* default rte use 0.0.0.0 mask */ - ip_addr_set_zero(dst); - } - else - { - /* other rtes use netmask */ - *dst = netif->netmask; - } - } - break; - case 13: /* ipRouteInfo */ - objectidncpy((s32_t*)value, (s32_t*)iprouteinfo.id, (u8_t)(len / sizeof(s32_t))); - break; - } - } -} - -static void -ip_ntomentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) -{ - /* return to object name, adding index depth (5) */ - ident_len += 5; - ident -= 5; - - if (ident_len == 6) - { - u8_t id; - - od->id_inst_len = ident_len; - od->id_inst_ptr = ident; - - LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); - id = (u8_t)ident[0]; - switch (id) - { - case 1: /* ipNetToMediaIfIndex */ - case 4: /* ipNetToMediaType */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_WRITE; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); - od->v_len = sizeof(s32_t); - break; - case 2: /* ipNetToMediaPhysAddress */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_WRITE; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR); - od->v_len = 6; /** @todo try to use netif::hwaddr_len */ - break; - case 3: /* ipNetToMediaNetAddress */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_WRITE; - od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); - od->v_len = 4; - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_ntomentry_get_object_def: no such object\n")); - od->instance = MIB_OBJECT_NONE; - break; - } - } - else - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_ntomentry_get_object_def: no scalar\n")); - od->instance = MIB_OBJECT_NONE; - } -} - -static void -ip_ntomentry_get_value(struct obj_def *od, u16_t len, void *value) -{ -#if LWIP_ARP - u8_t id; - struct eth_addr* ethaddr_ret; - ip_addr_t* ipaddr_ret; -#endif /* LWIP_ARP */ - ip_addr_t ip; - struct netif *netif; - - LWIP_UNUSED_ARG(len); - LWIP_UNUSED_ARG(value);/* if !LWIP_ARP */ - - snmp_ifindextonetif(od->id_inst_ptr[1], &netif); - snmp_oidtoip(&od->id_inst_ptr[2], &ip); - -#if LWIP_ARP /** @todo implement a netif_find_addr */ - if (etharp_find_addr(netif, &ip, ðaddr_ret, &ipaddr_ret) > -1) - { - LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); - id = (u8_t)od->id_inst_ptr[0]; - switch (id) - { - case 1: /* ipNetToMediaIfIndex */ - { - s32_t *sint_ptr = (s32_t*)value; - *sint_ptr = od->id_inst_ptr[1]; - } - break; - case 2: /* ipNetToMediaPhysAddress */ - { - struct eth_addr *dst = (struct eth_addr*)value; - - *dst = *ethaddr_ret; - } - break; - case 3: /* ipNetToMediaNetAddress */ - { - ip_addr_t *dst = (ip_addr_t*)value; - - *dst = *ipaddr_ret; - } - break; - case 4: /* ipNetToMediaType */ - { - s32_t *sint_ptr = (s32_t*)value; - /* dynamic (?) */ - *sint_ptr = 3; - } - break; - } - } -#endif /* LWIP_ARP */ -} - -static void -icmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) -{ - /* return to object name, adding index depth (1) */ - ident_len += 1; - ident -= 1; - if ((ident_len == 2) && - (ident[0] > 0) && (ident[0] < 27)) - { - od->id_inst_len = ident_len; - od->id_inst_ptr = ident; - - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); - od->v_len = sizeof(u32_t); - } - else - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("icmp_get_object_def: no scalar\n")); - od->instance = MIB_OBJECT_NONE; - } -} - -static void -icmp_get_value(struct obj_def *od, u16_t len, void *value) -{ - u32_t *uint_ptr = (u32_t*)value; - u8_t id; - - LWIP_UNUSED_ARG(len); - LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); - id = (u8_t)od->id_inst_ptr[0]; - switch (id) - { - case 1: /* icmpInMsgs */ - *uint_ptr = icmpinmsgs; - break; - case 2: /* icmpInErrors */ - *uint_ptr = icmpinerrors; - break; - case 3: /* icmpInDestUnreachs */ - *uint_ptr = icmpindestunreachs; - break; - case 4: /* icmpInTimeExcds */ - *uint_ptr = icmpintimeexcds; - break; - case 5: /* icmpInParmProbs */ - *uint_ptr = icmpinparmprobs; - break; - case 6: /* icmpInSrcQuenchs */ - *uint_ptr = icmpinsrcquenchs; - break; - case 7: /* icmpInRedirects */ - *uint_ptr = icmpinredirects; - break; - case 8: /* icmpInEchos */ - *uint_ptr = icmpinechos; - break; - case 9: /* icmpInEchoReps */ - *uint_ptr = icmpinechoreps; - break; - case 10: /* icmpInTimestamps */ - *uint_ptr = icmpintimestamps; - break; - case 11: /* icmpInTimestampReps */ - *uint_ptr = icmpintimestampreps; - break; - case 12: /* icmpInAddrMasks */ - *uint_ptr = icmpinaddrmasks; - break; - case 13: /* icmpInAddrMaskReps */ - *uint_ptr = icmpinaddrmaskreps; - break; - case 14: /* icmpOutMsgs */ - *uint_ptr = icmpoutmsgs; - break; - case 15: /* icmpOutErrors */ - *uint_ptr = icmpouterrors; - break; - case 16: /* icmpOutDestUnreachs */ - *uint_ptr = icmpoutdestunreachs; - break; - case 17: /* icmpOutTimeExcds */ - *uint_ptr = icmpouttimeexcds; - break; - case 18: /* icmpOutParmProbs */ - *uint_ptr = icmpoutparmprobs; - break; - case 19: /* icmpOutSrcQuenchs */ - *uint_ptr = icmpoutsrcquenchs; - break; - case 20: /* icmpOutRedirects */ - *uint_ptr = icmpoutredirects; - break; - case 21: /* icmpOutEchos */ - *uint_ptr = icmpoutechos; - break; - case 22: /* icmpOutEchoReps */ - *uint_ptr = icmpoutechoreps; - break; - case 23: /* icmpOutTimestamps */ - *uint_ptr = icmpouttimestamps; - break; - case 24: /* icmpOutTimestampReps */ - *uint_ptr = icmpouttimestampreps; - break; - case 25: /* icmpOutAddrMasks */ - *uint_ptr = icmpoutaddrmasks; - break; - case 26: /* icmpOutAddrMaskReps */ - *uint_ptr = icmpoutaddrmaskreps; - break; - } -} - -#if LWIP_TCP -/** @todo tcp grp */ -static void -tcp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) -{ - u8_t id; - - /* return to object name, adding index depth (1) */ - ident_len += 1; - ident -= 1; - if (ident_len == 2) - { - od->id_inst_len = ident_len; - od->id_inst_ptr = ident; - - LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); - id = (u8_t)ident[0]; - LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def tcp.%"U16_F".0\n",(u16_t)id)); - - switch (id) - { - case 1: /* tcpRtoAlgorithm */ - case 2: /* tcpRtoMin */ - case 3: /* tcpRtoMax */ - case 4: /* tcpMaxConn */ - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); - od->v_len = sizeof(s32_t); - break; - case 5: /* tcpActiveOpens */ - case 6: /* tcpPassiveOpens */ - case 7: /* tcpAttemptFails */ - case 8: /* tcpEstabResets */ - case 10: /* tcpInSegs */ - case 11: /* tcpOutSegs */ - case 12: /* tcpRetransSegs */ - case 14: /* tcpInErrs */ - case 15: /* tcpOutRsts */ - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); - od->v_len = sizeof(u32_t); - break; - case 9: /* tcpCurrEstab */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE); - od->v_len = sizeof(u32_t); - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_object_def: no such object\n")); - od->instance = MIB_OBJECT_NONE; - break; - }; - } - else - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_object_def: no scalar\n")); - od->instance = MIB_OBJECT_NONE; - } -} - -static void -tcp_get_value(struct obj_def *od, u16_t len, void *value) -{ - u32_t *uint_ptr = (u32_t*)value; - s32_t *sint_ptr = (s32_t*)value; - u8_t id; - - LWIP_UNUSED_ARG(len); - LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); - id = (u8_t)od->id_inst_ptr[0]; - switch (id) - { - case 1: /* tcpRtoAlgorithm, vanj(4) */ - *sint_ptr = 4; - break; - case 2: /* tcpRtoMin */ - /* @todo not the actual value, a guess, - needs to be calculated */ - *sint_ptr = 1000; - break; - case 3: /* tcpRtoMax */ - /* @todo not the actual value, a guess, - needs to be calculated */ - *sint_ptr = 60000; - break; - case 4: /* tcpMaxConn */ - *sint_ptr = MEMP_NUM_TCP_PCB; - break; - case 5: /* tcpActiveOpens */ - *uint_ptr = tcpactiveopens; - break; - case 6: /* tcpPassiveOpens */ - *uint_ptr = tcppassiveopens; - break; - case 7: /* tcpAttemptFails */ - *uint_ptr = tcpattemptfails; - break; - case 8: /* tcpEstabResets */ - *uint_ptr = tcpestabresets; - break; - case 9: /* tcpCurrEstab */ - { - u16_t tcpcurrestab = 0; - struct tcp_pcb *pcb = tcp_active_pcbs; - while (pcb != NULL) - { - if ((pcb->state == ESTABLISHED) || - (pcb->state == CLOSE_WAIT)) - { - tcpcurrestab++; - } - pcb = pcb->next; - } - *uint_ptr = tcpcurrestab; - } - break; - case 10: /* tcpInSegs */ - *uint_ptr = tcpinsegs; - break; - case 11: /* tcpOutSegs */ - *uint_ptr = tcpoutsegs; - break; - case 12: /* tcpRetransSegs */ - *uint_ptr = tcpretranssegs; - break; - case 14: /* tcpInErrs */ - *uint_ptr = tcpinerrs; - break; - case 15: /* tcpOutRsts */ - *uint_ptr = tcpoutrsts; - break; - } -} -#ifdef THIS_SEEMS_UNUSED -static void -tcpconnentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) -{ - /* return to object name, adding index depth (10) */ - ident_len += 10; - ident -= 10; - - if (ident_len == 11) - { - u8_t id; - - od->id_inst_len = ident_len; - od->id_inst_ptr = ident; - - id = ident[0]; - LWIP_DEBUGF(SNMP_MIB_DEBUG,("get_object_def tcp.%"U16_F".0\n",(u16_t)id)); - - switch (id) - { - case 1: /* tcpConnState */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_WRITE; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); - od->v_len = sizeof(s32_t); - break; - case 2: /* tcpConnLocalAddress */ - case 4: /* tcpConnRemAddress */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); - od->v_len = 4; - break; - case 3: /* tcpConnLocalPort */ - case 5: /* tcpConnRemPort */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); - od->v_len = sizeof(s32_t); - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcpconnentry_get_object_def: no such object\n")); - od->instance = MIB_OBJECT_NONE; - break; - }; - } - else - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcpconnentry_get_object_def: no such object\n")); - od->instance = MIB_OBJECT_NONE; - } -} - -static void -tcpconnentry_get_value(struct obj_def *od, u16_t len, void *value) -{ - ip_addr_t lip, rip; - u16_t lport, rport; - s32_t *ident; - - ident = od->id_inst_ptr; - snmp_oidtoip(&ident[1], &lip); - lport = ident[5]; - snmp_oidtoip(&ident[6], &rip); - rport = ident[10]; - - /** @todo find matching PCB */ -} -#endif /* if 0 */ -#endif - -static void -udp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) -{ - /* return to object name, adding index depth (1) */ - ident_len += 1; - ident -= 1; - if ((ident_len == 2) && - (ident[0] > 0) && (ident[0] < 6)) - { - od->id_inst_len = ident_len; - od->id_inst_ptr = ident; - - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); - od->v_len = sizeof(u32_t); - } - else - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("udp_get_object_def: no scalar\n")); - od->instance = MIB_OBJECT_NONE; - } -} - -static void -udp_get_value(struct obj_def *od, u16_t len, void *value) -{ - u32_t *uint_ptr = (u32_t*)value; - u8_t id; - - LWIP_UNUSED_ARG(len); - LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); - id = (u8_t)od->id_inst_ptr[0]; - switch (id) - { - case 1: /* udpInDatagrams */ - *uint_ptr = udpindatagrams; - break; - case 2: /* udpNoPorts */ - *uint_ptr = udpnoports; - break; - case 3: /* udpInErrors */ - *uint_ptr = udpinerrors; - break; - case 4: /* udpOutDatagrams */ - *uint_ptr = udpoutdatagrams; - break; - } -} - -static void -udpentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) -{ - /* return to object name, adding index depth (5) */ - ident_len += 5; - ident -= 5; - - if (ident_len == 6) - { - od->id_inst_len = ident_len; - od->id_inst_ptr = ident; - - switch (ident[0]) - { - case 1: /* udpLocalAddress */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR); - od->v_len = 4; - break; - case 2: /* udpLocalPort */ - od->instance = MIB_OBJECT_TAB; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); - od->v_len = sizeof(s32_t); - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("udpentry_get_object_def: no such object\n")); - od->instance = MIB_OBJECT_NONE; - break; - } - } - else - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("udpentry_get_object_def: no scalar\n")); - od->instance = MIB_OBJECT_NONE; - } -} - -static void -udpentry_get_value(struct obj_def *od, u16_t len, void *value) -{ - u8_t id; - struct udp_pcb *pcb; - ipX_addr_t ip; - u16_t port; - - LWIP_UNUSED_ARG(len); - snmp_oidtoip(&od->id_inst_ptr[1], (ip_addr_t*)&ip); - LWIP_ASSERT("invalid port", (od->id_inst_ptr[5] >= 0) && (od->id_inst_ptr[5] <= 0xffff)); - port = (u16_t)od->id_inst_ptr[5]; - - pcb = udp_pcbs; - while ((pcb != NULL) && - !(ipX_addr_cmp(0, &pcb->local_ip, &ip) && - (pcb->local_port == port))) - { - pcb = pcb->next; - } - - if (pcb != NULL) - { - LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); - id = (u8_t)od->id_inst_ptr[0]; - switch (id) - { - case 1: /* udpLocalAddress */ - { - ipX_addr_t *dst = (ipX_addr_t*)value; - ipX_addr_copy(0, *dst, pcb->local_ip); - } - break; - case 2: /* udpLocalPort */ - { - s32_t *sint_ptr = (s32_t*)value; - *sint_ptr = pcb->local_port; - } - break; - } - } -} - -static void -snmp_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) -{ - /* return to object name, adding index depth (1) */ - ident_len += 1; - ident -= 1; - if (ident_len == 2) - { - u8_t id; - - od->id_inst_len = ident_len; - od->id_inst_ptr = ident; - - LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff)); - id = (u8_t)ident[0]; - switch (id) - { - case 1: /* snmpInPkts */ - case 2: /* snmpOutPkts */ - case 3: /* snmpInBadVersions */ - case 4: /* snmpInBadCommunityNames */ - case 5: /* snmpInBadCommunityUses */ - case 6: /* snmpInASNParseErrs */ - case 8: /* snmpInTooBigs */ - case 9: /* snmpInNoSuchNames */ - case 10: /* snmpInBadValues */ - case 11: /* snmpInReadOnlys */ - case 12: /* snmpInGenErrs */ - case 13: /* snmpInTotalReqVars */ - case 14: /* snmpInTotalSetVars */ - case 15: /* snmpInGetRequests */ - case 16: /* snmpInGetNexts */ - case 17: /* snmpInSetRequests */ - case 18: /* snmpInGetResponses */ - case 19: /* snmpInTraps */ - case 20: /* snmpOutTooBigs */ - case 21: /* snmpOutNoSuchNames */ - case 22: /* snmpOutBadValues */ - case 24: /* snmpOutGenErrs */ - case 25: /* snmpOutGetRequests */ - case 26: /* snmpOutGetNexts */ - case 27: /* snmpOutSetRequests */ - case 28: /* snmpOutGetResponses */ - case 29: /* snmpOutTraps */ - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_ONLY; - od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER); - od->v_len = sizeof(u32_t); - break; - case 30: /* snmpEnableAuthenTraps */ - od->instance = MIB_OBJECT_SCALAR; - od->access = MIB_OBJECT_READ_WRITE; - od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG); - od->v_len = sizeof(s32_t); - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_object_def: no such object\n")); - od->instance = MIB_OBJECT_NONE; - break; - }; - } - else - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_object_def: no scalar\n")); - od->instance = MIB_OBJECT_NONE; - } -} - -static void -snmp_get_value(struct obj_def *od, u16_t len, void *value) -{ - u32_t *uint_ptr = (u32_t*)value; - u8_t id; - - LWIP_UNUSED_ARG(len); - LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); - id = (u8_t)od->id_inst_ptr[0]; - switch (id) - { - case 1: /* snmpInPkts */ - *uint_ptr = snmpinpkts; - break; - case 2: /* snmpOutPkts */ - *uint_ptr = snmpoutpkts; - break; - case 3: /* snmpInBadVersions */ - *uint_ptr = snmpinbadversions; - break; - case 4: /* snmpInBadCommunityNames */ - *uint_ptr = snmpinbadcommunitynames; - break; - case 5: /* snmpInBadCommunityUses */ - *uint_ptr = snmpinbadcommunityuses; - break; - case 6: /* snmpInASNParseErrs */ - *uint_ptr = snmpinasnparseerrs; - break; - case 8: /* snmpInTooBigs */ - *uint_ptr = snmpintoobigs; - break; - case 9: /* snmpInNoSuchNames */ - *uint_ptr = snmpinnosuchnames; - break; - case 10: /* snmpInBadValues */ - *uint_ptr = snmpinbadvalues; - break; - case 11: /* snmpInReadOnlys */ - *uint_ptr = snmpinreadonlys; - break; - case 12: /* snmpInGenErrs */ - *uint_ptr = snmpingenerrs; - break; - case 13: /* snmpInTotalReqVars */ - *uint_ptr = snmpintotalreqvars; - break; - case 14: /* snmpInTotalSetVars */ - *uint_ptr = snmpintotalsetvars; - break; - case 15: /* snmpInGetRequests */ - *uint_ptr = snmpingetrequests; - break; - case 16: /* snmpInGetNexts */ - *uint_ptr = snmpingetnexts; - break; - case 17: /* snmpInSetRequests */ - *uint_ptr = snmpinsetrequests; - break; - case 18: /* snmpInGetResponses */ - *uint_ptr = snmpingetresponses; - break; - case 19: /* snmpInTraps */ - *uint_ptr = snmpintraps; - break; - case 20: /* snmpOutTooBigs */ - *uint_ptr = snmpouttoobigs; - break; - case 21: /* snmpOutNoSuchNames */ - *uint_ptr = snmpoutnosuchnames; - break; - case 22: /* snmpOutBadValues */ - *uint_ptr = snmpoutbadvalues; - break; - case 24: /* snmpOutGenErrs */ - *uint_ptr = snmpoutgenerrs; - break; - case 25: /* snmpOutGetRequests */ - *uint_ptr = snmpoutgetrequests; - break; - case 26: /* snmpOutGetNexts */ - *uint_ptr = snmpoutgetnexts; - break; - case 27: /* snmpOutSetRequests */ - *uint_ptr = snmpoutsetrequests; - break; - case 28: /* snmpOutGetResponses */ - *uint_ptr = snmpoutgetresponses; - break; - case 29: /* snmpOutTraps */ - *uint_ptr = snmpouttraps; - break; - case 30: /* snmpEnableAuthenTraps */ - *uint_ptr = *snmpenableauthentraps_ptr; - break; - }; -} - -/** - * Test snmp object value before setting. - * - * @param od is the object definition - * @param len return value space (in bytes) - * @param value points to (varbind) space to copy value from. - */ -static u8_t -snmp_set_test(struct obj_def *od, u16_t len, void *value) -{ - u8_t id, set_ok; - - LWIP_UNUSED_ARG(len); - set_ok = 0; - LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); - id = (u8_t)od->id_inst_ptr[0]; - if (id == 30) - { - /* snmpEnableAuthenTraps */ - s32_t *sint_ptr = (s32_t*)value; - - if (snmpenableauthentraps_ptr != &snmpenableauthentraps_default) - { - /* we should have writable non-volatile mem here */ - if ((*sint_ptr == 1) || (*sint_ptr == 2)) - { - set_ok = 1; - } - } - else - { - /* const or hardwired value */ - if (*sint_ptr == snmpenableauthentraps_default) - { - set_ok = 1; - } - } - } - return set_ok; -} - -static void -snmp_set_value(struct obj_def *od, u16_t len, void *value) -{ - u8_t id; - - LWIP_UNUSED_ARG(len); - LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff)); - id = (u8_t)od->id_inst_ptr[0]; - if (id == 30) - { - /* snmpEnableAuthenTraps */ - /* @todo @fixme: which kind of pointer is 'value'? s32_t or u8_t??? */ - u8_t *ptr = (u8_t*)value; - *snmpenableauthentraps_ptr = *ptr; - } -} - -#endif /* LWIP_SNMP */ diff --git a/third_party/lwip/core/snmp/mib_structs.c b/third_party/lwip/core/snmp/mib_structs.c deleted file mode 100644 index cffbc70..0000000 --- a/third_party/lwip/core/snmp/mib_structs.c +++ /dev/null @@ -1,1174 +0,0 @@ -/** - * @file - * MIB tree access/construction functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * 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: Christiaan Simons - */ - -#include "lwip/opt.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/snmp_structs.h" -#include "lwip/memp.h" -#include "lwip/netif.h" - -/** .iso.org.dod.internet address prefix, @see snmp_iso_*() */ -const s32_t prefix[4] = {1, 3, 6, 1}; - -#define NODE_STACK_SIZE (LWIP_SNMP_OBJ_ID_LEN) -/** node stack entry (old news?) */ -struct nse -{ - /** right child */ - struct mib_node* r_ptr; - /** right child identifier */ - s32_t r_id; - /** right child next level */ - u8_t r_nl; -}; -static u8_t node_stack_cnt; -static struct nse node_stack[NODE_STACK_SIZE]; - -/** - * Pushes nse struct onto stack. - */ -static void -push_node(struct nse* node) -{ - LWIP_ASSERT("node_stack_cnt < NODE_STACK_SIZE",node_stack_cnt < NODE_STACK_SIZE); - LWIP_DEBUGF(SNMP_MIB_DEBUG,("push_node() node=%p id=%"S32_F"\n",(void*)(node->r_ptr),node->r_id)); - if (node_stack_cnt < NODE_STACK_SIZE) - { - node_stack[node_stack_cnt] = *node; - node_stack_cnt++; - } -} - -/** - * Pops nse struct from stack. - */ -static void -pop_node(struct nse* node) -{ - if (node_stack_cnt > 0) - { - node_stack_cnt--; - *node = node_stack[node_stack_cnt]; - } - LWIP_DEBUGF(SNMP_MIB_DEBUG,("pop_node() node=%p id=%"S32_F"\n",(void *)(node->r_ptr),node->r_id)); -} - -/** - * Conversion from ifIndex to lwIP netif - * @param ifindex is a s32_t object sub-identifier - * @param netif points to returned netif struct pointer - */ -void -snmp_ifindextonetif(s32_t ifindex, struct netif **netif) -{ - struct netif *nif = netif_list; - s32_t i, ifidx; - - ifidx = ifindex - 1; - i = 0; - while ((nif != NULL) && (i < ifidx)) - { - nif = nif->next; - i++; - } - *netif = nif; -} - -/** - * Conversion from lwIP netif to ifIndex - * @param netif points to a netif struct - * @param ifidx points to s32_t object sub-identifier - */ -void -snmp_netiftoifindex(struct netif *netif, s32_t *ifidx) -{ - struct netif *nif = netif_list; - u16_t i; - - i = 0; - while ((nif != NULL) && (nif != netif)) - { - nif = nif->next; - i++; - } - *ifidx = i+1; -} - -/** - * Conversion from oid to lwIP ip_addr - * @param ident points to s32_t ident[4] input - * @param ip points to output struct - */ -void -snmp_oidtoip(s32_t *ident, ip_addr_t *ip) -{ - IP4_ADDR(ip, ident[0], ident[1], ident[2], ident[3]); -} - -/** - * Conversion from lwIP ip_addr to oid - * @param ip points to input struct - * @param ident points to s32_t ident[4] output - */ -void -snmp_iptooid(ip_addr_t *ip, s32_t *ident) -{ - ident[0] = ip4_addr1(ip); - ident[1] = ip4_addr2(ip); - ident[2] = ip4_addr3(ip); - ident[3] = ip4_addr4(ip); -} - -struct mib_list_node * -snmp_mib_ln_alloc(s32_t id) -{ - struct mib_list_node *ln; - - ln = (struct mib_list_node *)memp_malloc(MEMP_SNMP_NODE); - if (ln != NULL) - { - ln->prev = NULL; - ln->next = NULL; - ln->objid = id; - ln->nptr = NULL; - } - return ln; -} - -void -snmp_mib_ln_free(struct mib_list_node *ln) -{ - memp_free(MEMP_SNMP_NODE, ln); -} - -struct mib_list_rootnode * -snmp_mib_lrn_alloc(void) -{ - struct mib_list_rootnode *lrn; - - lrn = (struct mib_list_rootnode*)memp_malloc(MEMP_SNMP_ROOTNODE); - if (lrn != NULL) - { - lrn->get_object_def = noleafs_get_object_def; - lrn->get_value = noleafs_get_value; - lrn->set_test = noleafs_set_test; - lrn->set_value = noleafs_set_value; - lrn->node_type = MIB_NODE_LR; - lrn->maxlength = 0; - lrn->head = NULL; - lrn->tail = NULL; - lrn->count = 0; - } - return lrn; -} - -void -snmp_mib_lrn_free(struct mib_list_rootnode *lrn) -{ - memp_free(MEMP_SNMP_ROOTNODE, lrn); -} - -/** - * Inserts node in idx list in a sorted - * (ascending order) fashion and - * allocates the node if needed. - * - * @param rn points to the root node - * @param objid is the object sub identifier - * @param insn points to a pointer to the inserted node - * used for constructing the tree. - * @return -1 if failed, 1 if inserted, 2 if present. - */ -s8_t -snmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **insn) -{ - struct mib_list_node *nn; - s8_t insert; - - LWIP_ASSERT("rn != NULL",rn != NULL); - - /* -1 = malloc failure, 0 = not inserted, 1 = inserted, 2 = was present */ - insert = 0; - if (rn->head == NULL) - { - /* empty list, add first node */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc empty list objid==%"S32_F"\n",objid)); - nn = snmp_mib_ln_alloc(objid); - if (nn != NULL) - { - rn->head = nn; - rn->tail = nn; - *insn = nn; - insert = 1; - } - else - { - insert = -1; - } - } - else - { - struct mib_list_node *n; - /* at least one node is present */ - n = rn->head; - while ((n != NULL) && (insert == 0)) - { - if (n->objid == objid) - { - /* node is already there */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("node already there objid==%"S32_F"\n",objid)); - *insn = n; - insert = 2; - } - else if (n->objid < objid) - { - if (n->next == NULL) - { - /* alloc and insert at the tail */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc ins tail objid==%"S32_F"\n",objid)); - nn = snmp_mib_ln_alloc(objid); - if (nn != NULL) - { - nn->next = NULL; - nn->prev = n; - n->next = nn; - rn->tail = nn; - *insn = nn; - insert = 1; - } - else - { - /* insertion failure */ - insert = -1; - } - } - else - { - /* there's more to explore: traverse list */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("traverse list\n")); - n = n->next; - } - } - else - { - /* n->objid > objid */ - /* alloc and insert between n->prev and n */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("alloc ins n->prev, objid==%"S32_F", n\n",objid)); - nn = snmp_mib_ln_alloc(objid); - if (nn != NULL) - { - if (n->prev == NULL) - { - /* insert at the head */ - nn->next = n; - nn->prev = NULL; - rn->head = nn; - n->prev = nn; - } - else - { - /* insert in the middle */ - nn->next = n; - nn->prev = n->prev; - n->prev->next = nn; - n->prev = nn; - } - *insn = nn; - insert = 1; - } - else - { - /* insertion failure */ - insert = -1; - } - } - } - } - if (insert == 1) - { - rn->count += 1; - } - LWIP_ASSERT("insert != 0",insert != 0); - return insert; -} - -/** - * Finds node in idx list and returns deletion mark. - * - * @param rn points to the root node - * @param objid is the object sub identifier - * @param fn returns pointer to found node - * @return 0 if not found, 1 if deletable, - * 2 can't delete (2 or more children), 3 not a list_node - */ -s8_t -snmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn) -{ - s8_t fc; - struct mib_list_node *n; - - LWIP_ASSERT("rn != NULL",rn != NULL); - n = rn->head; - while ((n != NULL) && (n->objid != objid)) - { - n = n->next; - } - if (n == NULL) - { - fc = 0; - } - else if (n->nptr == NULL) - { - /* leaf, can delete node */ - fc = 1; - } - else - { - struct mib_list_rootnode *r; - - if (n->nptr->node_type == MIB_NODE_LR) - { - r = (struct mib_list_rootnode *)n->nptr; - if (r->count > 1) - { - /* can't delete node */ - fc = 2; - } - else - { - /* count <= 1, can delete node */ - fc = 1; - } - } - else - { - /* other node type */ - fc = 3; - } - } - *fn = n; - return fc; -} - -/** - * Removes node from idx list - * if it has a single child left. - * - * @param rn points to the root node - * @param n points to the node to delete - * @return the nptr to be freed by caller - */ -struct mib_list_rootnode * -snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n) -{ - struct mib_list_rootnode *next; - - LWIP_ASSERT("rn != NULL",rn != NULL); - LWIP_ASSERT("n != NULL",n != NULL); - - /* caller must remove this sub-tree */ - next = (struct mib_list_rootnode*)(n->nptr); - rn->count -= 1; - - if (n == rn->head) - { - rn->head = n->next; - if (n->next != NULL) - { - /* not last node, new list begin */ - n->next->prev = NULL; - } - } - else if (n == rn->tail) - { - rn->tail = n->prev; - if (n->prev != NULL) - { - /* not last node, new list end */ - n->prev->next = NULL; - } - } - else - { - /* node must be in the middle */ - n->prev->next = n->next; - n->next->prev = n->prev; - } - LWIP_DEBUGF(SNMP_MIB_DEBUG,("free list objid==%"S32_F"\n",n->objid)); - snmp_mib_ln_free(n); - if (rn->count == 0) - { - rn->head = NULL; - rn->tail = NULL; - } - return next; -} - - - -/** - * Searches tree for the supplied (scalar?) object identifier. - * - * @param node points to the root of the tree ('.internet') - * @param ident_len the length of the supplied object identifier - * @param ident points to the array of sub identifiers - * @param np points to the found object instance (return) - * @return pointer to the requested parent (!) node if success, NULL otherwise - */ -struct mib_node * -snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np) -{ - u8_t node_type, ext_level; - - ext_level = 0; - LWIP_DEBUGF(SNMP_MIB_DEBUG,("node==%p *ident==%"S32_F"\n",(void*)node,*ident)); - while (node != NULL) - { - node_type = node->node_type; - if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) - { - struct mib_array_node *an; - u16_t i; - - if (ident_len > 0) - { - /* array node (internal ROM or RAM, fixed length) */ - an = (struct mib_array_node *)node; - i = 0; - while ((i < an->maxlength) && (an->objid[i] != *ident)) - { - i++; - } - if (i < an->maxlength) - { - /* found it, if available proceed to child, otherwise inspect leaf */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("an->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,an->objid[i],*ident)); - if (an->nptr[i] == NULL) - { - /* a scalar leaf OR table, - inspect remaining instance number / table index */ - np->ident_len = ident_len; - np->ident = ident; - return (struct mib_node*)an; - } - else - { - /* follow next child pointer */ - ident++; - ident_len--; - node = an->nptr[i]; - } - } - else - { - /* search failed, identifier mismatch (nosuchname) */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed *ident==%"S32_F"\n",*ident)); - return NULL; - } - } - else - { - /* search failed, short object identifier (nosuchname) */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("an search failed, short object identifier\n")); - return NULL; - } - } - else if(node_type == MIB_NODE_LR) - { - struct mib_list_rootnode *lrn; - struct mib_list_node *ln; - - if (ident_len > 0) - { - /* list root node (internal 'RAM', variable length) */ - lrn = (struct mib_list_rootnode *)node; - ln = lrn->head; - /* iterate over list, head to tail */ - while ((ln != NULL) && (ln->objid != *ident)) - { - ln = ln->next; - } - if (ln != NULL) - { - /* found it, proceed to child */; - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F"\n",ln->objid,*ident)); - if (ln->nptr == NULL) - { - np->ident_len = ident_len; - np->ident = ident; - return (struct mib_node*)lrn; - } - else - { - /* follow next child pointer */ - ident_len--; - ident++; - node = ln->nptr; - } - } - else - { - /* search failed */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed *ident==%"S32_F"\n",*ident)); - return NULL; - } - } - else - { - /* search failed, short object identifier (nosuchname) */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln search failed, short object identifier\n")); - return NULL; - } - } - else if(node_type == MIB_NODE_EX) - { - struct mib_external_node *en; - u16_t i, len; - - if (ident_len > 0) - { - /* external node (addressing and access via functions) */ - en = (struct mib_external_node *)node; - - i = 0; - len = en->level_length(en->addr_inf,ext_level); - while ((i < len) && (en->ident_cmp(en->addr_inf,ext_level,i,*ident) != 0)) - { - i++; - } - if (i < len) - { - s32_t debug_id; - - en->get_objid(en->addr_inf,ext_level,i,&debug_id); - LWIP_DEBUGF(SNMP_MIB_DEBUG,("en->objid==%"S32_F" *ident==%"S32_F"\n",debug_id,*ident)); - if ((ext_level + 1) == en->tree_levels) - { - np->ident_len = ident_len; - np->ident = ident; - return (struct mib_node*)en; - } - else - { - /* found it, proceed to child */ - ident_len--; - ident++; - ext_level++; - } - } - else - { - /* search failed */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("en search failed *ident==%"S32_F"\n",*ident)); - return NULL; - } - } - else - { - /* search failed, short object identifier (nosuchname) */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("en search failed, short object identifier\n")); - return NULL; - } - } - else if (node_type == MIB_NODE_SC) - { - mib_scalar_node *sn; - - sn = (mib_scalar_node *)node; - if ((ident_len == 1) && (*ident == 0)) - { - np->ident_len = ident_len; - np->ident = ident; - return (struct mib_node*)sn; - } - else - { - /* search failed, short object identifier (nosuchname) */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed, invalid object identifier length\n")); - return NULL; - } - } - else - { - /* unknown node_type */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed node_type %"U16_F" unkown\n",(u16_t)node_type)); - return NULL; - } - } - /* done, found nothing */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("search failed node==%p\n",(void*)node)); - return NULL; -} - -/** - * Test table for presence of at least one table entry. - */ -static u8_t -empty_table(struct mib_node *node) -{ - u8_t node_type; - u8_t empty = 0; - - if (node != NULL) - { - node_type = node->node_type; - if (node_type == MIB_NODE_LR) - { - struct mib_list_rootnode *lrn; - lrn = (struct mib_list_rootnode *)node; - if ((lrn->count == 0) || (lrn->head == NULL)) - { - empty = 1; - } - } - else if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) - { - struct mib_array_node *an; - an = (struct mib_array_node *)node; - if ((an->maxlength == 0) || (an->nptr == NULL)) - { - empty = 1; - } - } - else if (node_type == MIB_NODE_EX) - { - struct mib_external_node *en; - en = (struct mib_external_node *)node; - if (en->tree_levels == 0) - { - empty = 1; - } - } - } - return empty; -} - -/** - * Tree expansion. - */ -struct mib_node * -snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret) -{ - u8_t node_type, ext_level, climb_tree; - - ext_level = 0; - /* reset node stack */ - node_stack_cnt = 0; - while (node != NULL) - { - climb_tree = 0; - node_type = node->node_type; - if ((node_type == MIB_NODE_AR) || (node_type == MIB_NODE_RA)) - { - struct mib_array_node *an; - u16_t i; - - /* array node (internal ROM or RAM, fixed length) */ - an = (struct mib_array_node *)node; - if (ident_len > 0) - { - i = 0; - while ((i < an->maxlength) && (an->objid[i] < *ident)) - { - i++; - } - if (i < an->maxlength) - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("an->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,an->objid[i],*ident)); - /* add identifier to oidret */ - oidret->id[oidret->len] = an->objid[i]; - (oidret->len)++; - - if (an->nptr[i] == NULL) - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("leaf node\n")); - /* leaf node (e.g. in a fixed size table) */ - if (an->objid[i] > *ident) - { - return (struct mib_node*)an; - } - else if ((i + 1) < an->maxlength) - { - /* an->objid[i] == *ident */ - (oidret->len)--; - oidret->id[oidret->len] = an->objid[i + 1]; - (oidret->len)++; - return (struct mib_node*)an; - } - else - { - /* (i + 1) == an->maxlength */ - (oidret->len)--; - climb_tree = 1; - } - } - else - { - u8_t j; - struct nse cur_node; - - LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n")); - /* non-leaf, store right child ptr and id */ - LWIP_ASSERT("i < 0xff", i < 0xff); - j = (u8_t)i + 1; - while ((j < an->maxlength) && (empty_table(an->nptr[j]))) - { - j++; - } - if (j < an->maxlength) - { - cur_node.r_ptr = an->nptr[j]; - cur_node.r_id = an->objid[j]; - cur_node.r_nl = 0; - } - else - { - cur_node.r_ptr = NULL; - } - push_node(&cur_node); - if (an->objid[i] == *ident) - { - ident_len--; - ident++; - } - else - { - /* an->objid[i] < *ident */ - ident_len = 0; - } - /* follow next child pointer */ - node = an->nptr[i]; - } - } - else - { - /* i == an->maxlength */ - climb_tree = 1; - } - } - else - { - u8_t j; - /* ident_len == 0, complete with leftmost '.thing' */ - j = 0; - while ((j < an->maxlength) && empty_table(an->nptr[j])) - { - j++; - } - if (j < an->maxlength) - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("left an->objid[j]==%"S32_F"\n",an->objid[j])); - oidret->id[oidret->len] = an->objid[j]; - (oidret->len)++; - if (an->nptr[j] == NULL) - { - /* leaf node */ - return (struct mib_node*)an; - } - else - { - /* no leaf, continue */ - node = an->nptr[j]; - } - } - else - { - /* j == an->maxlength */ - climb_tree = 1; - } - } - } - else if(node_type == MIB_NODE_LR) - { - struct mib_list_rootnode *lrn; - struct mib_list_node *ln; - - /* list root node (internal 'RAM', variable length) */ - lrn = (struct mib_list_rootnode *)node; - if (ident_len > 0) - { - ln = lrn->head; - /* iterate over list, head to tail */ - while ((ln != NULL) && (ln->objid < *ident)) - { - ln = ln->next; - } - if (ln != NULL) - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ln->objid==%"S32_F" *ident==%"S32_F"\n",ln->objid,*ident)); - oidret->id[oidret->len] = ln->objid; - (oidret->len)++; - if (ln->nptr == NULL) - { - /* leaf node */ - if (ln->objid > *ident) - { - return (struct mib_node*)lrn; - } - else if (ln->next != NULL) - { - /* ln->objid == *ident */ - (oidret->len)--; - oidret->id[oidret->len] = ln->next->objid; - (oidret->len)++; - return (struct mib_node*)lrn; - } - else - { - /* ln->next == NULL */ - (oidret->len)--; - climb_tree = 1; - } - } - else - { - struct mib_list_node *jn; - struct nse cur_node; - - /* non-leaf, store right child ptr and id */ - jn = ln->next; - while ((jn != NULL) && empty_table(jn->nptr)) - { - jn = jn->next; - } - if (jn != NULL) - { - cur_node.r_ptr = jn->nptr; - cur_node.r_id = jn->objid; - cur_node.r_nl = 0; - } - else - { - cur_node.r_ptr = NULL; - } - push_node(&cur_node); - if (ln->objid == *ident) - { - ident_len--; - ident++; - } - else - { - /* ln->objid < *ident */ - ident_len = 0; - } - /* follow next child pointer */ - node = ln->nptr; - } - - } - else - { - /* ln == NULL */ - climb_tree = 1; - } - } - else - { - struct mib_list_node *jn; - /* ident_len == 0, complete with leftmost '.thing' */ - jn = lrn->head; - while ((jn != NULL) && empty_table(jn->nptr)) - { - jn = jn->next; - } - if (jn != NULL) - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("left jn->objid==%"S32_F"\n",jn->objid)); - oidret->id[oidret->len] = jn->objid; - (oidret->len)++; - if (jn->nptr == NULL) - { - /* leaf node */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("jn->nptr == NULL\n")); - return (struct mib_node*)lrn; - } - else - { - /* no leaf, continue */ - node = jn->nptr; - } - } - else - { - /* jn == NULL */ - climb_tree = 1; - } - } - } - else if(node_type == MIB_NODE_EX) - { - struct mib_external_node *en; - s32_t ex_id; - - /* external node (addressing and access via functions) */ - en = (struct mib_external_node *)node; - if (ident_len > 0) - { - u16_t i, len; - - i = 0; - len = en->level_length(en->addr_inf,ext_level); - while ((i < len) && (en->ident_cmp(en->addr_inf,ext_level,i,*ident) < 0)) - { - i++; - } - if (i < len) - { - /* add identifier to oidret */ - en->get_objid(en->addr_inf,ext_level,i,&ex_id); - LWIP_DEBUGF(SNMP_MIB_DEBUG,("en->objid[%"U16_F"]==%"S32_F" *ident==%"S32_F"\n",i,ex_id,*ident)); - oidret->id[oidret->len] = ex_id; - (oidret->len)++; - - if ((ext_level + 1) == en->tree_levels) - { - LWIP_DEBUGF(SNMP_MIB_DEBUG,("leaf node\n")); - /* leaf node */ - if (ex_id > *ident) - { - return (struct mib_node*)en; - } - else if ((i + 1) < len) - { - /* ex_id == *ident */ - en->get_objid(en->addr_inf,ext_level,i + 1,&ex_id); - (oidret->len)--; - oidret->id[oidret->len] = ex_id; - (oidret->len)++; - return (struct mib_node*)en; - } - else - { - /* (i + 1) == len */ - (oidret->len)--; - climb_tree = 1; - } - } - else - { - u8_t j; - struct nse cur_node; - - LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n")); - /* non-leaf, store right child ptr and id */ - LWIP_ASSERT("i < 0xff", i < 0xff); - j = (u8_t)i + 1; - if (j < len) - { - /* right node is the current external node */ - cur_node.r_ptr = node; - en->get_objid(en->addr_inf,ext_level,j,&cur_node.r_id); - cur_node.r_nl = ext_level + 1; - } - else - { - cur_node.r_ptr = NULL; - } - push_node(&cur_node); - if (en->ident_cmp(en->addr_inf,ext_level,i,*ident) == 0) - { - ident_len--; - ident++; - } - else - { - /* external id < *ident */ - ident_len = 0; - } - /* proceed to child */ - ext_level++; - } - } - else - { - /* i == len (en->level_len()) */ - climb_tree = 1; - } - } - else - { - /* ident_len == 0, complete with leftmost '.thing' */ - en->get_objid(en->addr_inf,ext_level,0,&ex_id); - LWIP_DEBUGF(SNMP_MIB_DEBUG,("left en->objid==%"S32_F"\n",ex_id)); - oidret->id[oidret->len] = ex_id; - (oidret->len)++; - if ((ext_level + 1) == en->tree_levels) - { - /* leaf node */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("(ext_level + 1) == en->tree_levels\n")); - return (struct mib_node*)en; - } - else - { - /* no leaf, proceed to child */ - ext_level++; - } - } - } - else if(node_type == MIB_NODE_SC) - { - mib_scalar_node *sn; - - /* scalar node */ - sn = (mib_scalar_node *)node; - if (ident_len > 0) - { - /* at .0 */ - climb_tree = 1; - } - else - { - /* ident_len == 0, complete object identifier */ - oidret->id[oidret->len] = 0; - (oidret->len)++; - /* leaf node */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("completed scalar leaf\n")); - return (struct mib_node*)sn; - } - } - else - { - /* unknown/unhandled node_type */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed node_type %"U16_F" unkown\n",(u16_t)node_type)); - return NULL; - } - - if (climb_tree) - { - struct nse child; - - /* find right child ptr */ - child.r_ptr = NULL; - child.r_id = 0; - child.r_nl = 0; - while ((node_stack_cnt > 0) && (child.r_ptr == NULL)) - { - pop_node(&child); - /* trim returned oid */ - (oidret->len)--; - } - if (child.r_ptr != NULL) - { - /* incoming ident is useless beyond this point */ - ident_len = 0; - oidret->id[oidret->len] = child.r_id; - oidret->len++; - node = child.r_ptr; - ext_level = child.r_nl; - } - else - { - /* tree ends here ... */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed, tree ends here\n")); - return NULL; - } - } - } - /* done, found nothing */ - LWIP_DEBUGF(SNMP_MIB_DEBUG,("expand failed node==%p\n",(void*)node)); - return NULL; -} - -/** - * Test object identifier for the iso.org.dod.internet prefix. - * - * @param ident_len the length of the supplied object identifier - * @param ident points to the array of sub identifiers - * @return 1 if it matches, 0 otherwise - */ -u8_t -snmp_iso_prefix_tst(u8_t ident_len, s32_t *ident) -{ - if ((ident_len > 3) && - (ident[0] == 1) && (ident[1] == 3) && - (ident[2] == 6) && (ident[3] == 1)) - { - return 1; - } - else - { - return 0; - } -} - -/** - * Expands object identifier to the iso.org.dod.internet - * prefix for use in getnext operation. - * - * @param ident_len the length of the supplied object identifier - * @param ident points to the array of sub identifiers - * @param oidret points to returned expanded object identifier - * @return 1 if it matches, 0 otherwise - * - * @note ident_len 0 is allowed, expanding to the first known object id!! - */ -u8_t -snmp_iso_prefix_expand(u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret) -{ - const s32_t *prefix_ptr; - s32_t *ret_ptr; - u8_t i; - - i = 0; - prefix_ptr = &prefix[0]; - ret_ptr = &oidret->id[0]; - ident_len = ((ident_len < 4)?ident_len:4); - while ((i < ident_len) && ((*ident) <= (*prefix_ptr))) - { - *ret_ptr++ = *prefix_ptr++; - ident++; - i++; - } - if (i == ident_len) - { - /* match, complete missing bits */ - while (i < 4) - { - *ret_ptr++ = *prefix_ptr++; - i++; - } - oidret->len = i; - return 1; - } - else - { - /* i != ident_len */ - return 0; - } -} - -#endif /* LWIP_SNMP */ diff --git a/third_party/lwip/core/snmp/msg_in.c b/third_party/lwip/core/snmp/msg_in.c deleted file mode 100644 index 2dfbdc9..0000000 --- a/third_party/lwip/core/snmp/msg_in.c +++ /dev/null @@ -1,1453 +0,0 @@ -/** - * @file - * SNMP input message processing (RFC1157). - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * 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: Christiaan Simons - */ - -#include "lwip/opt.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/snmp.h" -#include "lwip/snmp_asn1.h" -#include "lwip/snmp_msg.h" -#include "lwip/snmp_structs.h" -#include "lwip/ip_addr.h" -#include "lwip/memp.h" -#include "lwip/udp.h" -#include "lwip/stats.h" - -#include - -/* public (non-static) constants */ -/** SNMP v1 == 0 */ -const s32_t snmp_version = 0; -/** default SNMP community string */ -const char snmp_publiccommunity[7] = "public"; - -/* statically allocated buffers for SNMP_CONCURRENT_REQUESTS */ -struct snmp_msg_pstat msg_input_list[SNMP_CONCURRENT_REQUESTS]; -/* UDP Protocol Control Block */ -struct udp_pcb *snmp1_pcb; - -static void snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port); -static err_t snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat); -static err_t snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat); - - -/** - * Starts SNMP Agent. - * Allocates UDP pcb and binds it to IP_ADDR_ANY port 161. - */ -void -snmp_init(void) -{ - struct snmp_msg_pstat *msg_ps; - u8_t i; - - snmp1_pcb = udp_new(); - if (snmp1_pcb != NULL) - { - udp_recv(snmp1_pcb, snmp_recv, (void *)SNMP_IN_PORT); - udp_bind(snmp1_pcb, IP_ADDR_ANY, SNMP_IN_PORT); - } - msg_ps = &msg_input_list[0]; - for (i=0; istate = SNMP_MSG_EMPTY; - msg_ps->error_index = 0; - msg_ps->error_status = SNMP_ES_NOERROR; - msg_ps++; - } - trap_msg.pcb = snmp1_pcb; - -#ifdef SNMP_PRIVATE_MIB_INIT - /* If defined, this must be a function-like define to initialize the - * private MIB after the stack has been initialized. - * The private MIB can also be initialized in tcpip_callback (or after - * the stack is initialized), this define is only for convenience. */ - SNMP_PRIVATE_MIB_INIT(); -#endif /* SNMP_PRIVATE_MIB_INIT */ - - /* The coldstart trap will only be output - if our outgoing interface is up & configured */ - snmp_coldstart_trap(); -} - -static void -snmp_error_response(struct snmp_msg_pstat *msg_ps, u8_t error) -{ - /* move names back from outvb to invb */ - int v; - struct snmp_varbind *vbi = msg_ps->invb.head; - struct snmp_varbind *vbo = msg_ps->outvb.head; - for (v=0; vvb_idx; v++) { - vbi->ident_len = vbo->ident_len; - vbo->ident_len = 0; - vbi->ident = vbo->ident; - vbo->ident = NULL; - vbi = vbi->next; - vbo = vbo->next; - } - /* free outvb */ - snmp_varbind_list_free(&msg_ps->outvb); - /* we send invb back */ - msg_ps->outvb = msg_ps->invb; - msg_ps->invb.head = NULL; - msg_ps->invb.tail = NULL; - msg_ps->invb.count = 0; - msg_ps->error_status = error; - /* error index must be 0 for error too big */ - msg_ps->error_index = (error != SNMP_ES_TOOBIG) ? (1 + msg_ps->vb_idx) : 0; - snmp_send_response(msg_ps); - snmp_varbind_list_free(&msg_ps->outvb); - msg_ps->state = SNMP_MSG_EMPTY; -} - -static void -snmp_ok_response(struct snmp_msg_pstat *msg_ps) -{ - err_t err_ret; - - err_ret = snmp_send_response(msg_ps); - if (err_ret == ERR_MEM) - { - /* serious memory problem, can't return tooBig */ - } - else - { - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event = %"S32_F"\n",msg_ps->error_status)); - } - /* free varbinds (if available) */ - snmp_varbind_list_free(&msg_ps->invb); - snmp_varbind_list_free(&msg_ps->outvb); - msg_ps->state = SNMP_MSG_EMPTY; -} - -/** - * Service an internal or external event for SNMP GET. - * - * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) - * @param msg_ps points to the assosicated message process state - */ -static void -snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps) -{ - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_get_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state)); - - if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF) - { - struct mib_external_node *en; - struct snmp_name_ptr np; - - /* get_object_def() answer*/ - en = msg_ps->ext_mib_node; - np = msg_ps->ext_name_ptr; - - /* translate answer into a known lifeform */ - en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def); - if ((msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) && - (msg_ps->ext_object_def.access & MIB_ACCESS_READ)) - { - msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE; - en->get_value_q(request_id, &msg_ps->ext_object_def); - } - else - { - en->get_object_def_pc(request_id, np.ident_len, np.ident); - /* search failed, object id points to unknown object (nosuchname) */ - snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); - } - } - else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_VALUE) - { - struct mib_external_node *en; - struct snmp_varbind *vb; - - /* get_value() answer */ - en = msg_ps->ext_mib_node; - - /* allocate output varbind */ - vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND); - if (vb != NULL) - { - vb->next = NULL; - vb->prev = NULL; - - /* move name from invb to outvb */ - vb->ident = msg_ps->vb_ptr->ident; - vb->ident_len = msg_ps->vb_ptr->ident_len; - /* ensure this memory is refereced once only */ - msg_ps->vb_ptr->ident = NULL; - msg_ps->vb_ptr->ident_len = 0; - - vb->value_type = msg_ps->ext_object_def.asn_type; - LWIP_ASSERT("invalid length", msg_ps->ext_object_def.v_len <= 0xff); - vb->value_len = (u8_t)msg_ps->ext_object_def.v_len; - if (vb->value_len > 0) - { - LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE); - vb->value = memp_malloc(MEMP_SNMP_VALUE); - if (vb->value != NULL) - { - en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value); - snmp_varbind_tail_add(&msg_ps->outvb, vb); - /* search again (if vb_idx < msg_ps->invb.count) */ - msg_ps->state = SNMP_MSG_SEARCH_OBJ; - msg_ps->vb_idx += 1; - } - else - { - en->get_value_pc(request_id, &msg_ps->ext_object_def); - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no variable space\n")); - msg_ps->vb_ptr->ident = vb->ident; - msg_ps->vb_ptr->ident_len = vb->ident_len; - memp_free(MEMP_SNMP_VARBIND, vb); - snmp_error_response(msg_ps,SNMP_ES_TOOBIG); - } - } - else - { - /* vb->value_len == 0, empty value (e.g. empty string) */ - en->get_value_a(request_id, &msg_ps->ext_object_def, 0, NULL); - vb->value = NULL; - snmp_varbind_tail_add(&msg_ps->outvb, vb); - /* search again (if vb_idx < msg_ps->invb.count) */ - msg_ps->state = SNMP_MSG_SEARCH_OBJ; - msg_ps->vb_idx += 1; - } - } - else - { - en->get_value_pc(request_id, &msg_ps->ext_object_def); - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no outvb space\n")); - snmp_error_response(msg_ps,SNMP_ES_TOOBIG); - } - } - - while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && - (msg_ps->vb_idx < msg_ps->invb.count)) - { - struct mib_node *mn; - struct snmp_name_ptr np; - - if (msg_ps->vb_idx == 0) - { - msg_ps->vb_ptr = msg_ps->invb.head; - } - else - { - msg_ps->vb_ptr = msg_ps->vb_ptr->next; - } - /** test object identifier for .iso.org.dod.internet prefix */ - if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident)) - { - mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4, - msg_ps->vb_ptr->ident + 4, &np); - if (mn != NULL) - { - if (mn->node_type == MIB_NODE_EX) - { - /* external object */ - struct mib_external_node *en = (struct mib_external_node*)mn; - - msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF; - /* save en && args in msg_ps!! */ - msg_ps->ext_mib_node = en; - msg_ps->ext_name_ptr = np; - - en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident); - } - else - { - /* internal object */ - struct obj_def object_def; - - msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF; - mn->get_object_def(np.ident_len, np.ident, &object_def); - if ((object_def.instance != MIB_OBJECT_NONE) && - (object_def.access & MIB_ACCESS_READ)) - { - mn = mn; - } - else - { - /* search failed, object id points to unknown object (nosuchname) */ - mn = NULL; - } - if (mn != NULL) - { - struct snmp_varbind *vb; - - msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE; - /* allocate output varbind */ - vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND); - if (vb != NULL) - { - vb->next = NULL; - vb->prev = NULL; - - /* move name from invb to outvb */ - vb->ident = msg_ps->vb_ptr->ident; - vb->ident_len = msg_ps->vb_ptr->ident_len; - /* ensure this memory is refereced once only */ - msg_ps->vb_ptr->ident = NULL; - msg_ps->vb_ptr->ident_len = 0; - - vb->value_type = object_def.asn_type; - LWIP_ASSERT("invalid length", object_def.v_len <= 0xff); - vb->value_len = (u8_t)object_def.v_len; - if (vb->value_len > 0) - { - LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", - vb->value_len <= SNMP_MAX_VALUE_SIZE); - vb->value = memp_malloc(MEMP_SNMP_VALUE); - if (vb->value != NULL) - { - mn->get_value(&object_def, vb->value_len, vb->value); - snmp_varbind_tail_add(&msg_ps->outvb, vb); - msg_ps->state = SNMP_MSG_SEARCH_OBJ; - msg_ps->vb_idx += 1; - } - else - { - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate variable space\n")); - msg_ps->vb_ptr->ident = vb->ident; - msg_ps->vb_ptr->ident_len = vb->ident_len; - vb->ident = NULL; - vb->ident_len = 0; - memp_free(MEMP_SNMP_VARBIND, vb); - snmp_error_response(msg_ps,SNMP_ES_TOOBIG); - } - } - else - { - /* vb->value_len == 0, empty value (e.g. empty string) */ - vb->value = NULL; - snmp_varbind_tail_add(&msg_ps->outvb, vb); - msg_ps->state = SNMP_MSG_SEARCH_OBJ; - msg_ps->vb_idx += 1; - } - } - else - { - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate outvb space\n")); - snmp_error_response(msg_ps,SNMP_ES_TOOBIG); - } - } - } - } - } - else - { - mn = NULL; - } - if (mn == NULL) - { - /* mn == NULL, noSuchName */ - snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); - } - } - if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && - (msg_ps->vb_idx == msg_ps->invb.count)) - { - snmp_ok_response(msg_ps); - } -} - -/** - * Service an internal or external event for SNMP GETNEXT. - * - * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) - * @param msg_ps points to the assosicated message process state - */ -static void -snmp_msg_getnext_event(u8_t request_id, struct snmp_msg_pstat *msg_ps) -{ - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_getnext_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state)); - - if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF) - { - struct mib_external_node *en; - - /* get_object_def() answer*/ - en = msg_ps->ext_mib_node; - - /* translate answer into a known lifeform */ - en->get_object_def_a(request_id, 1, &msg_ps->ext_oid.id[msg_ps->ext_oid.len - 1], &msg_ps->ext_object_def); - if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) - { - msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE; - en->get_value_q(request_id, &msg_ps->ext_object_def); - } - else - { - en->get_object_def_pc(request_id, 1, &msg_ps->ext_oid.id[msg_ps->ext_oid.len - 1]); - /* search failed, object id points to unknown object (nosuchname) */ - snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); - } - } - else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_VALUE) - { - struct mib_external_node *en; - struct snmp_varbind *vb; - - /* get_value() answer */ - en = msg_ps->ext_mib_node; - - LWIP_ASSERT("invalid length", msg_ps->ext_object_def.v_len <= 0xff); - vb = snmp_varbind_alloc(&msg_ps->ext_oid, - msg_ps->ext_object_def.asn_type, - (u8_t)msg_ps->ext_object_def.v_len); - if (vb != NULL) - { - en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value); - snmp_varbind_tail_add(&msg_ps->outvb, vb); - msg_ps->state = SNMP_MSG_SEARCH_OBJ; - msg_ps->vb_idx += 1; - } - else - { - en->get_value_pc(request_id, &msg_ps->ext_object_def); - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_getnext_event: couldn't allocate outvb space\n")); - snmp_error_response(msg_ps,SNMP_ES_TOOBIG); - } - } - - while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && - (msg_ps->vb_idx < msg_ps->invb.count)) - { - struct mib_node *mn; - struct snmp_obj_id oid; - - if (msg_ps->vb_idx == 0) - { - msg_ps->vb_ptr = msg_ps->invb.head; - } - else - { - msg_ps->vb_ptr = msg_ps->vb_ptr->next; - } - if (snmp_iso_prefix_expand(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident, &oid)) - { - if (msg_ps->vb_ptr->ident_len > 3) - { - /* can offset ident_len and ident */ - mn = snmp_expand_tree((struct mib_node*)&internet, - msg_ps->vb_ptr->ident_len - 4, - msg_ps->vb_ptr->ident + 4, &oid); - } - else - { - /* can't offset ident_len -4, ident + 4 */ - mn = snmp_expand_tree((struct mib_node*)&internet, 0, NULL, &oid); - } - } - else - { - mn = NULL; - } - if (mn != NULL) - { - if (mn->node_type == MIB_NODE_EX) - { - /* external object */ - struct mib_external_node *en = (struct mib_external_node*)mn; - - msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF; - /* save en && args in msg_ps!! */ - msg_ps->ext_mib_node = en; - msg_ps->ext_oid = oid; - - en->get_object_def_q(en->addr_inf, request_id, 1, &oid.id[oid.len - 1]); - } - else - { - /* internal object */ - struct obj_def object_def; - struct snmp_varbind *vb; - - msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF; - mn->get_object_def(1, &oid.id[oid.len - 1], &object_def); - - LWIP_ASSERT("invalid length", object_def.v_len <= 0xff); - vb = snmp_varbind_alloc(&oid, object_def.asn_type, (u8_t)object_def.v_len); - if (vb != NULL) - { - msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE; - mn->get_value(&object_def, object_def.v_len, vb->value); - snmp_varbind_tail_add(&msg_ps->outvb, vb); - msg_ps->state = SNMP_MSG_SEARCH_OBJ; - msg_ps->vb_idx += 1; - } - else - { - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv couldn't allocate outvb space\n")); - snmp_error_response(msg_ps,SNMP_ES_TOOBIG); - } - } - } - if (mn == NULL) - { - /* mn == NULL, noSuchName */ - snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); - } - } - if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && - (msg_ps->vb_idx == msg_ps->invb.count)) - { - snmp_ok_response(msg_ps); - } -} - -/** - * Service an internal or external event for SNMP SET. - * - * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) - * @param msg_ps points to the assosicated message process state - */ -static void -snmp_msg_set_event(u8_t request_id, struct snmp_msg_pstat *msg_ps) -{ - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_set_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state)); - - if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF) - { - struct mib_external_node *en; - struct snmp_name_ptr np; - - /* get_object_def() answer*/ - en = msg_ps->ext_mib_node; - np = msg_ps->ext_name_ptr; - - /* translate answer into a known lifeform */ - en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def); - if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) - { - msg_ps->state = SNMP_MSG_EXTERNAL_SET_TEST; - en->set_test_q(request_id, &msg_ps->ext_object_def); - } - else - { - en->get_object_def_pc(request_id, np.ident_len, np.ident); - /* search failed, object id points to unknown object (nosuchname) */ - snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); - } - } - else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_TEST) - { - struct mib_external_node *en; - - /* set_test() answer*/ - en = msg_ps->ext_mib_node; - - if (msg_ps->ext_object_def.access & MIB_ACCESS_WRITE) - { - if ((msg_ps->ext_object_def.asn_type == msg_ps->vb_ptr->value_type) && - (en->set_test_a(request_id,&msg_ps->ext_object_def, - msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0)) - { - msg_ps->state = SNMP_MSG_SEARCH_OBJ; - msg_ps->vb_idx += 1; - } - else - { - en->set_test_pc(request_id,&msg_ps->ext_object_def); - /* bad value */ - snmp_error_response(msg_ps,SNMP_ES_BADVALUE); - } - } - else - { - en->set_test_pc(request_id,&msg_ps->ext_object_def); - /* object not available for set */ - snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); - } - } - else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF_S) - { - struct mib_external_node *en; - struct snmp_name_ptr np; - - /* get_object_def() answer*/ - en = msg_ps->ext_mib_node; - np = msg_ps->ext_name_ptr; - - /* translate answer into a known lifeform */ - en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def); - if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) - { - msg_ps->state = SNMP_MSG_EXTERNAL_SET_VALUE; - en->set_value_q(request_id, &msg_ps->ext_object_def, - msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value); - } - else - { - en->get_object_def_pc(request_id, np.ident_len, np.ident); - /* set_value failed, object has disappeared for some odd reason?? */ - snmp_error_response(msg_ps,SNMP_ES_GENERROR); - } - } - else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_VALUE) - { - struct mib_external_node *en; - - /** set_value_a() */ - en = msg_ps->ext_mib_node; - en->set_value_a(request_id, &msg_ps->ext_object_def, - msg_ps->vb_ptr->value_len, msg_ps->vb_ptr->value); - - /** @todo use set_value_pc() if toobig */ - msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE; - msg_ps->vb_idx += 1; - } - - /* test all values before setting */ - while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && - (msg_ps->vb_idx < msg_ps->invb.count)) - { - struct mib_node *mn; - struct snmp_name_ptr np; - - if (msg_ps->vb_idx == 0) - { - msg_ps->vb_ptr = msg_ps->invb.head; - } - else - { - msg_ps->vb_ptr = msg_ps->vb_ptr->next; - } - /** test object identifier for .iso.org.dod.internet prefix */ - if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident)) - { - mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4, - msg_ps->vb_ptr->ident + 4, &np); - if (mn != NULL) - { - if (mn->node_type == MIB_NODE_EX) - { - /* external object */ - struct mib_external_node *en = (struct mib_external_node*)mn; - - msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF; - /* save en && args in msg_ps!! */ - msg_ps->ext_mib_node = en; - msg_ps->ext_name_ptr = np; - - en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident); - } - else - { - /* internal object */ - struct obj_def object_def; - - msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF; - mn->get_object_def(np.ident_len, np.ident, &object_def); - if (object_def.instance != MIB_OBJECT_NONE) - { - mn = mn; - } - else - { - /* search failed, object id points to unknown object (nosuchname) */ - mn = NULL; - } - if (mn != NULL) - { - msg_ps->state = SNMP_MSG_INTERNAL_SET_TEST; - - if (object_def.access & MIB_ACCESS_WRITE) - { - if ((object_def.asn_type == msg_ps->vb_ptr->value_type) && - (mn->set_test(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0)) - { - msg_ps->state = SNMP_MSG_SEARCH_OBJ; - msg_ps->vb_idx += 1; - } - else - { - /* bad value */ - snmp_error_response(msg_ps,SNMP_ES_BADVALUE); - } - } - else - { - /* object not available for set */ - snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); - } - } - } - } - } - else - { - mn = NULL; - } - if (mn == NULL) - { - /* mn == NULL, noSuchName */ - snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME); - } - } - - if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) && - (msg_ps->vb_idx == msg_ps->invb.count)) - { - msg_ps->vb_idx = 0; - msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE; - } - - /* set all values "atomically" (be as "atomic" as possible) */ - while ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) && - (msg_ps->vb_idx < msg_ps->invb.count)) - { - struct mib_node *mn; - struct snmp_name_ptr np; - - if (msg_ps->vb_idx == 0) - { - msg_ps->vb_ptr = msg_ps->invb.head; - } - else - { - msg_ps->vb_ptr = msg_ps->vb_ptr->next; - } - /* skip iso prefix test, was done previously while settesting() */ - mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4, - msg_ps->vb_ptr->ident + 4, &np); - /* check if object is still available - (e.g. external hot-plug thingy present?) */ - if (mn != NULL) - { - if (mn->node_type == MIB_NODE_EX) - { - /* external object */ - struct mib_external_node *en = (struct mib_external_node*)mn; - - msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF_S; - /* save en && args in msg_ps!! */ - msg_ps->ext_mib_node = en; - msg_ps->ext_name_ptr = np; - - en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident); - } - else - { - /* internal object */ - struct obj_def object_def; - - msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF_S; - mn->get_object_def(np.ident_len, np.ident, &object_def); - msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE; - mn->set_value(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value); - msg_ps->vb_idx += 1; - } - } - } - if ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) && - (msg_ps->vb_idx == msg_ps->invb.count)) - { - /* simply echo the input if we can set it - @todo do we need to return the actual value? - e.g. if value is silently modified or behaves sticky? */ - msg_ps->outvb = msg_ps->invb; - msg_ps->invb.head = NULL; - msg_ps->invb.tail = NULL; - msg_ps->invb.count = 0; - snmp_ok_response(msg_ps); - } -} - - -/** - * Handle one internal or external event. - * Called for one async event. (recv external/private answer) - * - * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) - */ -void -snmp_msg_event(u8_t request_id) -{ - struct snmp_msg_pstat *msg_ps; - - if (request_id < SNMP_CONCURRENT_REQUESTS) - { - msg_ps = &msg_input_list[request_id]; - if (msg_ps->rt == SNMP_ASN1_PDU_GET_NEXT_REQ) - { - snmp_msg_getnext_event(request_id, msg_ps); - } - else if (msg_ps->rt == SNMP_ASN1_PDU_GET_REQ) - { - snmp_msg_get_event(request_id, msg_ps); - } - else if(msg_ps->rt == SNMP_ASN1_PDU_SET_REQ) - { - snmp_msg_set_event(request_id, msg_ps); - } - } -} - - -/* lwIP UDP receive callback function */ -static void -snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) -{ - struct snmp_msg_pstat *msg_ps; - u8_t req_idx; - err_t err_ret; - u16_t payload_len = p->tot_len; - u16_t payload_ofs = 0; - u16_t varbind_ofs = 0; - - /* suppress unused argument warning */ - LWIP_UNUSED_ARG(arg); - - /* traverse input message process list, look for SNMP_MSG_EMPTY */ - msg_ps = &msg_input_list[0]; - req_idx = 0; - while ((req_idx < SNMP_CONCURRENT_REQUESTS) && (msg_ps->state != SNMP_MSG_EMPTY)) - { - req_idx++; - msg_ps++; - } - if (req_idx == SNMP_CONCURRENT_REQUESTS) - { - /* exceeding number of concurrent requests */ - pbuf_free(p); - return; - } - - /* accepting request */ - snmp_inc_snmpinpkts(); - /* record used 'protocol control block' */ - msg_ps->pcb = pcb; - /* source address (network order) */ - msg_ps->sip = *addr; - /* source port (host order (lwIP oddity)) */ - msg_ps->sp = port; - - /* check total length, version, community, pdu type */ - err_ret = snmp_pdu_header_check(p, payload_ofs, payload_len, &varbind_ofs, msg_ps); - /* Only accept requests and requests without error (be robust) */ - /* Reject response and trap headers or error requests as input! */ - if ((err_ret != ERR_OK) || - ((msg_ps->rt != SNMP_ASN1_PDU_GET_REQ) && - (msg_ps->rt != SNMP_ASN1_PDU_GET_NEXT_REQ) && - (msg_ps->rt != SNMP_ASN1_PDU_SET_REQ)) || - ((msg_ps->error_status != SNMP_ES_NOERROR) || - (msg_ps->error_index != 0)) ) - { - /* header check failed drop request silently, do not return error! */ - pbuf_free(p); - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_header_check() failed\n")); - return; - } - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv ok, community %s\n", msg_ps->community)); - - /* Builds a list of variable bindings. Copy the varbinds from the pbuf - chain to glue them when these are divided over two or more pbuf's. */ - err_ret = snmp_pdu_dec_varbindlist(p, varbind_ofs, &varbind_ofs, msg_ps); - /* we've decoded the incoming message, release input msg now */ - pbuf_free(p); - if ((err_ret != ERR_OK) || (msg_ps->invb.count == 0)) - { - /* varbind-list decode failed, or varbind list empty. - drop request silently, do not return error! - (errors are only returned for a specific varbind failure) */ - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_dec_varbindlist() failed\n")); - return; - } - - msg_ps->error_status = SNMP_ES_NOERROR; - msg_ps->error_index = 0; - /* find object for each variable binding */ - msg_ps->state = SNMP_MSG_SEARCH_OBJ; - /* first variable binding from list to inspect */ - msg_ps->vb_idx = 0; - - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv varbind cnt=%"U16_F"\n",(u16_t)msg_ps->invb.count)); - - /* handle input event and as much objects as possible in one go */ - snmp_msg_event(req_idx); -} - -/** - * Checks and decodes incoming SNMP message header, logs header errors. - * - * @param p points to pbuf chain of SNMP message (UDP payload) - * @param ofs points to first octet of SNMP message - * @param pdu_len the length of the UDP payload - * @param ofs_ret returns the ofset of the variable bindings - * @param m_stat points to the current message request state return - * @return - * - ERR_OK SNMP header is sane and accepted - * - ERR_ARG SNMP header is either malformed or rejected - */ -static err_t -snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat) -{ - err_t derr; - u16_t len, ofs_base; - u8_t len_octets; - u8_t type; - s32_t version; - - ofs_base = ofs; - snmp_asn1_dec_type(p, ofs, &type); - derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); - if ((derr != ERR_OK) || - (pdu_len != (1 + len_octets + len)) || - (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ))) - { - snmp_inc_snmpinasnparseerrs(); - return ERR_ARG; - } - ofs += (1 + len_octets); - snmp_asn1_dec_type(p, ofs, &type); - derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); - if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) - { - /* can't decode or no integer (version) */ - snmp_inc_snmpinasnparseerrs(); - return ERR_ARG; - } - derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &version); - if (derr != ERR_OK) - { - /* can't decode */ - snmp_inc_snmpinasnparseerrs(); - return ERR_ARG; - } - if (version != 0) - { - /* not version 1 */ - snmp_inc_snmpinbadversions(); - return ERR_ARG; - } - ofs += (1 + len_octets + len); - snmp_asn1_dec_type(p, ofs, &type); - derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); - if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR))) - { - /* can't decode or no octet string (community) */ - snmp_inc_snmpinasnparseerrs(); - return ERR_ARG; - } - derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, SNMP_COMMUNITY_STR_LEN, m_stat->community); - if (derr != ERR_OK) - { - snmp_inc_snmpinasnparseerrs(); - return ERR_ARG; - } - /* add zero terminator */ - len = ((len < (SNMP_COMMUNITY_STR_LEN))?(len):(SNMP_COMMUNITY_STR_LEN)); - m_stat->community[len] = 0; - m_stat->com_strlen = (u8_t)len; - if (strncmp(snmp_publiccommunity, (const char*)m_stat->community, SNMP_COMMUNITY_STR_LEN) != 0) - { - /** @todo: move this if we need to check more names */ - snmp_inc_snmpinbadcommunitynames(); - snmp_authfail_trap(); - return ERR_ARG; - } - ofs += (1 + len_octets + len); - snmp_asn1_dec_type(p, ofs, &type); - derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); - if (derr != ERR_OK) - { - snmp_inc_snmpinasnparseerrs(); - return ERR_ARG; - } - switch(type) - { - case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_REQ): - /* GetRequest PDU */ - snmp_inc_snmpingetrequests(); - derr = ERR_OK; - break; - case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_NEXT_REQ): - /* GetNextRequest PDU */ - snmp_inc_snmpingetnexts(); - derr = ERR_OK; - break; - case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP): - /* GetResponse PDU */ - snmp_inc_snmpingetresponses(); - derr = ERR_ARG; - break; - case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_SET_REQ): - /* SetRequest PDU */ - snmp_inc_snmpinsetrequests(); - derr = ERR_OK; - break; - case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP): - /* Trap PDU */ - snmp_inc_snmpintraps(); - derr = ERR_ARG; - break; - default: - snmp_inc_snmpinasnparseerrs(); - derr = ERR_ARG; - break; - } - if (derr != ERR_OK) - { - /* unsupported input PDU for this agent (no parse error) */ - return ERR_ARG; - } - m_stat->rt = type & 0x1F; - ofs += (1 + len_octets); - if (len != (pdu_len - (ofs - ofs_base))) - { - /* decoded PDU length does not equal actual payload length */ - snmp_inc_snmpinasnparseerrs(); - return ERR_ARG; - } - snmp_asn1_dec_type(p, ofs, &type); - derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); - if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) - { - /* can't decode or no integer (request ID) */ - snmp_inc_snmpinasnparseerrs(); - return ERR_ARG; - } - derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->rid); - if (derr != ERR_OK) - { - /* can't decode */ - snmp_inc_snmpinasnparseerrs(); - return ERR_ARG; - } - ofs += (1 + len_octets + len); - snmp_asn1_dec_type(p, ofs, &type); - derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); - if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) - { - /* can't decode or no integer (error-status) */ - snmp_inc_snmpinasnparseerrs(); - return ERR_ARG; - } - /* must be noError (0) for incoming requests. - log errors for mib-2 completeness and for debug purposes */ - derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->error_status); - if (derr != ERR_OK) - { - /* can't decode */ - snmp_inc_snmpinasnparseerrs(); - return ERR_ARG; - } - switch (m_stat->error_status) - { - case SNMP_ES_TOOBIG: - snmp_inc_snmpintoobigs(); - break; - case SNMP_ES_NOSUCHNAME: - snmp_inc_snmpinnosuchnames(); - break; - case SNMP_ES_BADVALUE: - snmp_inc_snmpinbadvalues(); - break; - case SNMP_ES_READONLY: - snmp_inc_snmpinreadonlys(); - break; - case SNMP_ES_GENERROR: - snmp_inc_snmpingenerrs(); - break; - } - ofs += (1 + len_octets + len); - snmp_asn1_dec_type(p, ofs, &type); - derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); - if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG))) - { - /* can't decode or no integer (error-index) */ - snmp_inc_snmpinasnparseerrs(); - return ERR_ARG; - } - /* must be 0 for incoming requests. - decode anyway to catch bad integers (and dirty tricks) */ - derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->error_index); - if (derr != ERR_OK) - { - /* can't decode */ - snmp_inc_snmpinasnparseerrs(); - return ERR_ARG; - } - ofs += (1 + len_octets + len); - *ofs_ret = ofs; - return ERR_OK; -} - -static err_t -snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat) -{ - err_t derr; - u16_t len, vb_len; - u8_t len_octets; - u8_t type; - - /* variable binding list */ - snmp_asn1_dec_type(p, ofs, &type); - derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &vb_len); - if ((derr != ERR_OK) || - (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ))) - { - snmp_inc_snmpinasnparseerrs(); - return ERR_ARG; - } - ofs += (1 + len_octets); - - /* start with empty list */ - m_stat->invb.count = 0; - m_stat->invb.head = NULL; - m_stat->invb.tail = NULL; - - while (vb_len > 0) - { - struct snmp_obj_id oid, oid_value; - struct snmp_varbind *vb; - - snmp_asn1_dec_type(p, ofs, &type); - derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); - if ((derr != ERR_OK) || - (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)) || - (len == 0) || (len > vb_len)) - { - snmp_inc_snmpinasnparseerrs(); - /* free varbinds (if available) */ - snmp_varbind_list_free(&m_stat->invb); - return ERR_ARG; - } - ofs += (1 + len_octets); - vb_len -= (1 + len_octets); - - snmp_asn1_dec_type(p, ofs, &type); - derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); - if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID))) - { - /* can't decode object name length */ - snmp_inc_snmpinasnparseerrs(); - /* free varbinds (if available) */ - snmp_varbind_list_free(&m_stat->invb); - return ERR_ARG; - } - derr = snmp_asn1_dec_oid(p, ofs + 1 + len_octets, len, &oid); - if (derr != ERR_OK) - { - /* can't decode object name */ - snmp_inc_snmpinasnparseerrs(); - /* free varbinds (if available) */ - snmp_varbind_list_free(&m_stat->invb); - return ERR_ARG; - } - ofs += (1 + len_octets + len); - vb_len -= (1 + len_octets + len); - - snmp_asn1_dec_type(p, ofs, &type); - derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); - if (derr != ERR_OK) - { - /* can't decode object value length */ - snmp_inc_snmpinasnparseerrs(); - /* free varbinds (if available) */ - snmp_varbind_list_free(&m_stat->invb); - return ERR_ARG; - } - - switch (type) - { - case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): - vb = snmp_varbind_alloc(&oid, type, sizeof(s32_t)); - if (vb != NULL) - { - s32_t *vptr = (s32_t*)vb->value; - - derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, vptr); - snmp_varbind_tail_add(&m_stat->invb, vb); - } - else - { - derr = ERR_ARG; - } - break; - case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): - case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): - case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): - vb = snmp_varbind_alloc(&oid, type, sizeof(u32_t)); - if (vb != NULL) - { - u32_t *vptr = (u32_t*)vb->value; - - derr = snmp_asn1_dec_u32t(p, ofs + 1 + len_octets, len, vptr); - snmp_varbind_tail_add(&m_stat->invb, vb); - } - else - { - derr = ERR_ARG; - } - break; - case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): - case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): - LWIP_ASSERT("invalid length", len <= 0xff); - vb = snmp_varbind_alloc(&oid, type, (u8_t)len); - if (vb != NULL) - { - derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, (u8_t*)vb->value); - snmp_varbind_tail_add(&m_stat->invb, vb); - } - else - { - derr = ERR_ARG; - } - break; - case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): - vb = snmp_varbind_alloc(&oid, type, 0); - if (vb != NULL) - { - snmp_varbind_tail_add(&m_stat->invb, vb); - derr = ERR_OK; - } - else - { - derr = ERR_ARG; - } - break; - case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): - derr = snmp_asn1_dec_oid(p, ofs + 1 + len_octets, len, &oid_value); - if (derr == ERR_OK) - { - vb = snmp_varbind_alloc(&oid, type, oid_value.len * sizeof(s32_t)); - if (vb != NULL) - { - u8_t i = oid_value.len; - s32_t *vptr = (s32_t*)vb->value; - - while(i > 0) - { - i--; - vptr[i] = oid_value.id[i]; - } - snmp_varbind_tail_add(&m_stat->invb, vb); - derr = ERR_OK; - } - else - { - derr = ERR_ARG; - } - } - break; - case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): - if (len == 4) - { - /* must be exactly 4 octets! */ - vb = snmp_varbind_alloc(&oid, type, 4); - if (vb != NULL) - { - derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, (u8_t*)vb->value); - snmp_varbind_tail_add(&m_stat->invb, vb); - } - else - { - derr = ERR_ARG; - } - } - else - { - derr = ERR_ARG; - } - break; - default: - derr = ERR_ARG; - break; - } - if (derr != ERR_OK) - { - snmp_inc_snmpinasnparseerrs(); - /* free varbinds (if available) */ - snmp_varbind_list_free(&m_stat->invb); - return ERR_ARG; - } - ofs += (1 + len_octets + len); - vb_len -= (1 + len_octets + len); - } - - if (m_stat->rt == SNMP_ASN1_PDU_SET_REQ) - { - snmp_add_snmpintotalsetvars(m_stat->invb.count); - } - else - { - snmp_add_snmpintotalreqvars(m_stat->invb.count); - } - - *ofs_ret = ofs; - return ERR_OK; -} - -struct snmp_varbind* -snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len) -{ - struct snmp_varbind *vb; - - vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND); - if (vb != NULL) - { - u8_t i; - - vb->next = NULL; - vb->prev = NULL; - i = oid->len; - vb->ident_len = i; - if (i > 0) - { - LWIP_ASSERT("SNMP_MAX_TREE_DEPTH is configured too low", i <= SNMP_MAX_TREE_DEPTH); - /* allocate array of s32_t for our object identifier */ - vb->ident = (s32_t*)memp_malloc(MEMP_SNMP_VALUE); - if (vb->ident == NULL) - { - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate ident value space\n")); - memp_free(MEMP_SNMP_VARBIND, vb); - return NULL; - } - while(i > 0) - { - i--; - vb->ident[i] = oid->id[i]; - } - } - else - { - /* i == 0, pass zero length object identifier */ - vb->ident = NULL; - } - vb->value_type = type; - vb->value_len = len; - if (len > 0) - { - LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE); - /* allocate raw bytes for our object value */ - vb->value = memp_malloc(MEMP_SNMP_VALUE); - if (vb->value == NULL) - { - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate value space\n")); - if (vb->ident != NULL) - { - memp_free(MEMP_SNMP_VALUE, vb->ident); - } - memp_free(MEMP_SNMP_VARBIND, vb); - return NULL; - } - } - else - { - /* ASN1_NUL type, or zero length ASN1_OC_STR */ - vb->value = NULL; - } - } - else - { - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate varbind space\n")); - } - return vb; -} - -void -snmp_varbind_free(struct snmp_varbind *vb) -{ - if (vb->value != NULL ) - { - memp_free(MEMP_SNMP_VALUE, vb->value); - } - if (vb->ident != NULL ) - { - memp_free(MEMP_SNMP_VALUE, vb->ident); - } - memp_free(MEMP_SNMP_VARBIND, vb); -} - -void -snmp_varbind_list_free(struct snmp_varbind_root *root) -{ - struct snmp_varbind *vb, *prev; - - vb = root->tail; - while ( vb != NULL ) - { - prev = vb->prev; - snmp_varbind_free(vb); - vb = prev; - } - root->count = 0; - root->head = NULL; - root->tail = NULL; -} - -void -snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb) -{ - if (root->count == 0) - { - /* add first varbind to list */ - root->head = vb; - root->tail = vb; - } - else - { - /* add nth varbind to list tail */ - root->tail->next = vb; - vb->prev = root->tail; - root->tail = vb; - } - root->count += 1; -} - -struct snmp_varbind* -snmp_varbind_tail_remove(struct snmp_varbind_root *root) -{ - struct snmp_varbind* vb; - - if (root->count > 0) - { - /* remove tail varbind */ - vb = root->tail; - root->tail = vb->prev; - vb->prev->next = NULL; - root->count -= 1; - } - else - { - /* nothing to remove */ - vb = NULL; - } - return vb; -} - -#endif /* LWIP_SNMP */ diff --git a/third_party/lwip/core/snmp/msg_out.c b/third_party/lwip/core/snmp/msg_out.c deleted file mode 100644 index b1dd565..0000000 --- a/third_party/lwip/core/snmp/msg_out.c +++ /dev/null @@ -1,678 +0,0 @@ -/** - * @file - * SNMP output message processing (RFC1157). - * - * Output responses and traps are build in two passes: - * - * Pass 0: iterate over the output message backwards to determine encoding lengths - * Pass 1: the actual forward encoding of internal form into ASN1 - * - * The single-pass encoding method described by Comer & Stevens - * requires extra buffer space and copying for reversal of the packet. - * The buffer requirement can be prohibitively large for big payloads - * (>= 484) therefore we use the two encoding passes. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * 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: Christiaan Simons - */ - -#include "lwip/opt.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/udp.h" -#include "lwip/netif.h" -#include "lwip/snmp.h" -#include "lwip/snmp_asn1.h" -#include "lwip/snmp_msg.h" - -struct snmp_trap_dst -{ - /* destination IP address in network order */ - ip_addr_t dip; - /* set to 0 when disabled, >0 when enabled */ - u8_t enable; -}; -struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS]; - -/** TRAP message structure */ -struct snmp_msg_trap trap_msg; - -static u16_t snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len); -static u16_t snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len); -static u16_t snmp_varbind_list_sum(struct snmp_varbind_root *root); - -static u16_t snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p); -static u16_t snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p); -static u16_t snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs); - -/** - * Sets enable switch for this trap destination. - * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 - * @param enable switch if 0 destination is disabled >0 enabled. - */ -void -snmp_trap_dst_enable(u8_t dst_idx, u8_t enable) -{ - if (dst_idx < SNMP_TRAP_DESTINATIONS) - { - trap_dst[dst_idx].enable = enable; - } -} - -/** - * Sets IPv4 address for this trap destination. - * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 - * @param dst IPv4 address in host order. - */ -void -snmp_trap_dst_ip_set(u8_t dst_idx, ip_addr_t *dst) -{ - if (dst_idx < SNMP_TRAP_DESTINATIONS) - { - ip_addr_set(&trap_dst[dst_idx].dip, dst); - } -} - -/** - * Sends a 'getresponse' message to the request originator. - * - * @param m_stat points to the current message request state source - * @return ERR_OK when success, ERR_MEM if we're out of memory - * - * @note the caller is responsible for filling in outvb in the m_stat - * and provide error-status and index (except for tooBig errors) ... - */ -err_t -snmp_send_response(struct snmp_msg_pstat *m_stat) -{ - struct snmp_varbind_root emptyvb = {NULL, NULL, 0, 0, 0}; - struct pbuf *p; - u16_t tot_len; - err_t err; - - /* pass 0, calculate length fields */ - tot_len = snmp_varbind_list_sum(&m_stat->outvb); - tot_len = snmp_resp_header_sum(m_stat, tot_len); - - /* try allocating pbuf(s) for complete response */ - p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); - if (p == NULL) - { - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() tooBig\n")); - - /* can't construct reply, return error-status tooBig */ - m_stat->error_status = SNMP_ES_TOOBIG; - m_stat->error_index = 0; - /* pass 0, recalculate lengths, for empty varbind-list */ - tot_len = snmp_varbind_list_sum(&emptyvb); - tot_len = snmp_resp_header_sum(m_stat, tot_len); - /* retry allocation once for header and empty varbind-list */ - p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); - } - if (p != NULL) - { - /* first pbuf alloc try or retry alloc success */ - u16_t ofs; - - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() p != NULL\n")); - - /* pass 1, size error, encode packet ino the pbuf(s) */ - ofs = snmp_resp_header_enc(m_stat, p); - snmp_varbind_list_enc(&m_stat->outvb, p, ofs); - - switch (m_stat->error_status) - { - case SNMP_ES_TOOBIG: - snmp_inc_snmpouttoobigs(); - break; - case SNMP_ES_NOSUCHNAME: - snmp_inc_snmpoutnosuchnames(); - break; - case SNMP_ES_BADVALUE: - snmp_inc_snmpoutbadvalues(); - break; - case SNMP_ES_GENERROR: - snmp_inc_snmpoutgenerrs(); - break; - } - snmp_inc_snmpoutgetresponses(); - snmp_inc_snmpoutpkts(); - - /** @todo do we need separate rx and tx pcbs for threaded case? */ - /** connect to the originating source */ - udp_connect(m_stat->pcb, &m_stat->sip, m_stat->sp); - err = udp_send(m_stat->pcb, p); - if (err == ERR_MEM) - { - /** @todo release some memory, retry and return tooBig? tooMuchHassle? */ - err = ERR_MEM; - } - else - { - err = ERR_OK; - } - /** disassociate remote address and port with this pcb */ - udp_disconnect(m_stat->pcb); - - pbuf_free(p); - LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() done\n")); - return err; - } - else - { - /* first pbuf alloc try or retry alloc failed - very low on memory, couldn't return tooBig */ - return ERR_MEM; - } -} - - -/** - * Sends an generic or enterprise specific trap message. - * - * @param generic_trap is the trap code - * @param eoid points to enterprise object identifier - * @param specific_trap used for enterprise traps when generic_trap == 6 - * @return ERR_OK when success, ERR_MEM if we're out of memory - * - * @note the caller is responsible for filling in outvb in the trap_msg - * @note the use of the enterpise identifier field - * is per RFC1215. - * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps - * and .iso.org.dod.internet.private.enterprises.yourenterprise - * (sysObjectID) for specific traps. - */ -err_t -snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap) -{ - struct snmp_trap_dst *td; - struct netif *dst_if; - ip_addr_t dst_ip; - struct pbuf *p; - u16_t i,tot_len; - err_t err = ERR_OK; - - for (i=0, td = &trap_dst[0]; ienable != 0) && !ip_addr_isany(&td->dip)) - { - /* network order trap destination */ - ip_addr_copy(trap_msg.dip, td->dip); - /* lookup current source address for this dst */ - dst_if = ip_route(&td->dip); - if (dst_if != NULL) { - ip_addr_copy(dst_ip, dst_if->ip_addr); - /* @todo: what about IPv6? */ - trap_msg.sip_raw[0] = ip4_addr1(&dst_ip); - trap_msg.sip_raw[1] = ip4_addr2(&dst_ip); - trap_msg.sip_raw[2] = ip4_addr3(&dst_ip); - trap_msg.sip_raw[3] = ip4_addr4(&dst_ip); - trap_msg.gen_trap = generic_trap; - trap_msg.spc_trap = specific_trap; - if (generic_trap == SNMP_GENTRAP_ENTERPRISESPC) - { - /* enterprise-Specific trap */ - trap_msg.enterprise = eoid; - } - else - { - /* generic (MIB-II) trap */ - snmp_get_snmpgrpid_ptr(&trap_msg.enterprise); - } - snmp_get_sysuptime(&trap_msg.ts); - - /* pass 0, calculate length fields */ - tot_len = snmp_varbind_list_sum(&trap_msg.outvb); - tot_len = snmp_trap_header_sum(&trap_msg, tot_len); - - /* allocate pbuf(s) */ - p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); - if (p != NULL) - { - u16_t ofs; - - /* pass 1, encode packet ino the pbuf(s) */ - ofs = snmp_trap_header_enc(&trap_msg, p); - snmp_varbind_list_enc(&trap_msg.outvb, p, ofs); - - snmp_inc_snmpouttraps(); - snmp_inc_snmpoutpkts(); - - /** send to the TRAP destination */ - udp_sendto(trap_msg.pcb, p, &trap_msg.dip, SNMP_TRAP_PORT); - - pbuf_free(p); - } else { - err = ERR_MEM; - } - } else { - /* routing error */ - err = ERR_RTE; - } - } - } - return err; -} - -void -snmp_coldstart_trap(void) -{ - trap_msg.outvb.head = NULL; - trap_msg.outvb.tail = NULL; - trap_msg.outvb.count = 0; - snmp_send_trap(SNMP_GENTRAP_COLDSTART, NULL, 0); -} - -void -snmp_authfail_trap(void) -{ - u8_t enable; - snmp_get_snmpenableauthentraps(&enable); - if (enable == 1) - { - trap_msg.outvb.head = NULL; - trap_msg.outvb.tail = NULL; - trap_msg.outvb.count = 0; - snmp_send_trap(SNMP_GENTRAP_AUTHFAIL, NULL, 0); - } -} - -/** - * Sums response header field lengths from tail to head and - * returns resp_header_lengths for second encoding pass. - * - * @param vb_len varbind-list length - * @param rhl points to returned header lengths - * @return the required lenght for encoding the response header - */ -static u16_t -snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len) -{ - u16_t tot_len; - struct snmp_resp_header_lengths *rhl; - - rhl = &m_stat->rhl; - tot_len = vb_len; - snmp_asn1_enc_s32t_cnt(m_stat->error_index, &rhl->erridxlen); - snmp_asn1_enc_length_cnt(rhl->erridxlen, &rhl->erridxlenlen); - tot_len += 1 + rhl->erridxlenlen + rhl->erridxlen; - - snmp_asn1_enc_s32t_cnt(m_stat->error_status, &rhl->errstatlen); - snmp_asn1_enc_length_cnt(rhl->errstatlen, &rhl->errstatlenlen); - tot_len += 1 + rhl->errstatlenlen + rhl->errstatlen; - - snmp_asn1_enc_s32t_cnt(m_stat->rid, &rhl->ridlen); - snmp_asn1_enc_length_cnt(rhl->ridlen, &rhl->ridlenlen); - tot_len += 1 + rhl->ridlenlen + rhl->ridlen; - - rhl->pdulen = tot_len; - snmp_asn1_enc_length_cnt(rhl->pdulen, &rhl->pdulenlen); - tot_len += 1 + rhl->pdulenlen; - - rhl->comlen = m_stat->com_strlen; - snmp_asn1_enc_length_cnt(rhl->comlen, &rhl->comlenlen); - tot_len += 1 + rhl->comlenlen + rhl->comlen; - - snmp_asn1_enc_s32t_cnt(snmp_version, &rhl->verlen); - snmp_asn1_enc_length_cnt(rhl->verlen, &rhl->verlenlen); - tot_len += 1 + rhl->verlen + rhl->verlenlen; - - rhl->seqlen = tot_len; - snmp_asn1_enc_length_cnt(rhl->seqlen, &rhl->seqlenlen); - tot_len += 1 + rhl->seqlenlen; - - return tot_len; -} - -/** - * Sums trap header field lengths from tail to head and - * returns trap_header_lengths for second encoding pass. - * - * @param vb_len varbind-list length - * @param thl points to returned header lengths - * @return the required lenght for encoding the trap header - */ -static u16_t -snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len) -{ - u16_t tot_len; - struct snmp_trap_header_lengths *thl; - - thl = &m_trap->thl; - tot_len = vb_len; - - snmp_asn1_enc_u32t_cnt(m_trap->ts, &thl->tslen); - snmp_asn1_enc_length_cnt(thl->tslen, &thl->tslenlen); - tot_len += 1 + thl->tslen + thl->tslenlen; - - snmp_asn1_enc_s32t_cnt(m_trap->spc_trap, &thl->strplen); - snmp_asn1_enc_length_cnt(thl->strplen, &thl->strplenlen); - tot_len += 1 + thl->strplen + thl->strplenlen; - - snmp_asn1_enc_s32t_cnt(m_trap->gen_trap, &thl->gtrplen); - snmp_asn1_enc_length_cnt(thl->gtrplen, &thl->gtrplenlen); - tot_len += 1 + thl->gtrplen + thl->gtrplenlen; - - thl->aaddrlen = 4; - snmp_asn1_enc_length_cnt(thl->aaddrlen, &thl->aaddrlenlen); - tot_len += 1 + thl->aaddrlen + thl->aaddrlenlen; - - snmp_asn1_enc_oid_cnt(m_trap->enterprise->len, &m_trap->enterprise->id[0], &thl->eidlen); - snmp_asn1_enc_length_cnt(thl->eidlen, &thl->eidlenlen); - tot_len += 1 + thl->eidlen + thl->eidlenlen; - - thl->pdulen = tot_len; - snmp_asn1_enc_length_cnt(thl->pdulen, &thl->pdulenlen); - tot_len += 1 + thl->pdulenlen; - - thl->comlen = sizeof(snmp_publiccommunity) - 1; - snmp_asn1_enc_length_cnt(thl->comlen, &thl->comlenlen); - tot_len += 1 + thl->comlenlen + thl->comlen; - - snmp_asn1_enc_s32t_cnt(snmp_version, &thl->verlen); - snmp_asn1_enc_length_cnt(thl->verlen, &thl->verlenlen); - tot_len += 1 + thl->verlen + thl->verlenlen; - - thl->seqlen = tot_len; - snmp_asn1_enc_length_cnt(thl->seqlen, &thl->seqlenlen); - tot_len += 1 + thl->seqlenlen; - - return tot_len; -} - -/** - * Sums varbind lengths from tail to head and - * annotates lengths in varbind for second encoding pass. - * - * @param root points to the root of the variable binding list - * @return the required lenght for encoding the variable bindings - */ -static u16_t -snmp_varbind_list_sum(struct snmp_varbind_root *root) -{ - struct snmp_varbind *vb; - u32_t *uint_ptr; - s32_t *sint_ptr; - u16_t tot_len; - - tot_len = 0; - vb = root->tail; - while ( vb != NULL ) - { - /* encoded value lenght depends on type */ - switch (vb->value_type) - { - case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): - sint_ptr = (s32_t*)vb->value; - snmp_asn1_enc_s32t_cnt(*sint_ptr, &vb->vlen); - break; - case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): - case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): - case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): - uint_ptr = (u32_t*)vb->value; - snmp_asn1_enc_u32t_cnt(*uint_ptr, &vb->vlen); - break; - case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): - case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): - case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): - case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): - vb->vlen = vb->value_len; - break; - case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): - sint_ptr = (s32_t*)vb->value; - snmp_asn1_enc_oid_cnt(vb->value_len / sizeof(s32_t), sint_ptr, &vb->vlen); - break; - default: - /* unsupported type */ - vb->vlen = 0; - break; - }; - /* encoding length of value length field */ - snmp_asn1_enc_length_cnt(vb->vlen, &vb->vlenlen); - snmp_asn1_enc_oid_cnt(vb->ident_len, vb->ident, &vb->olen); - snmp_asn1_enc_length_cnt(vb->olen, &vb->olenlen); - - vb->seqlen = 1 + vb->vlenlen + vb->vlen; - vb->seqlen += 1 + vb->olenlen + vb->olen; - snmp_asn1_enc_length_cnt(vb->seqlen, &vb->seqlenlen); - - /* varbind seq */ - tot_len += 1 + vb->seqlenlen + vb->seqlen; - - vb = vb->prev; - } - - /* varbind-list seq */ - root->seqlen = tot_len; - snmp_asn1_enc_length_cnt(root->seqlen, &root->seqlenlen); - tot_len += 1 + root->seqlenlen; - - return tot_len; -} - -/** - * Encodes response header from head to tail. - */ -static u16_t -snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p) -{ - u16_t ofs; - - ofs = 0; - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, m_stat->rhl.seqlen); - ofs += m_stat->rhl.seqlenlen; - - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, m_stat->rhl.verlen); - ofs += m_stat->rhl.verlenlen; - snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.verlen, snmp_version); - ofs += m_stat->rhl.verlen; - - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, m_stat->rhl.comlen); - ofs += m_stat->rhl.comlenlen; - snmp_asn1_enc_raw(p, ofs, m_stat->rhl.comlen, m_stat->community); - ofs += m_stat->rhl.comlen; - - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, m_stat->rhl.pdulen); - ofs += m_stat->rhl.pdulenlen; - - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, m_stat->rhl.ridlen); - ofs += m_stat->rhl.ridlenlen; - snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.ridlen, m_stat->rid); - ofs += m_stat->rhl.ridlen; - - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, m_stat->rhl.errstatlen); - ofs += m_stat->rhl.errstatlenlen; - snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.errstatlen, m_stat->error_status); - ofs += m_stat->rhl.errstatlen; - - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, m_stat->rhl.erridxlen); - ofs += m_stat->rhl.erridxlenlen; - snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.erridxlen, m_stat->error_index); - ofs += m_stat->rhl.erridxlen; - - return ofs; -} - -/** - * Encodes trap header from head to tail. - */ -static u16_t -snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p) -{ - u16_t ofs; - - ofs = 0; - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, m_trap->thl.seqlen); - ofs += m_trap->thl.seqlenlen; - - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, m_trap->thl.verlen); - ofs += m_trap->thl.verlenlen; - snmp_asn1_enc_s32t(p, ofs, m_trap->thl.verlen, snmp_version); - ofs += m_trap->thl.verlen; - - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, m_trap->thl.comlen); - ofs += m_trap->thl.comlenlen; - snmp_asn1_enc_raw(p, ofs, m_trap->thl.comlen, (u8_t *)&snmp_publiccommunity[0]); - ofs += m_trap->thl.comlen; - - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, m_trap->thl.pdulen); - ofs += m_trap->thl.pdulenlen; - - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, m_trap->thl.eidlen); - ofs += m_trap->thl.eidlenlen; - snmp_asn1_enc_oid(p, ofs, m_trap->enterprise->len, &m_trap->enterprise->id[0]); - ofs += m_trap->thl.eidlen; - - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, m_trap->thl.aaddrlen); - ofs += m_trap->thl.aaddrlenlen; - snmp_asn1_enc_raw(p, ofs, m_trap->thl.aaddrlen, &m_trap->sip_raw[0]); - ofs += m_trap->thl.aaddrlen; - - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, m_trap->thl.gtrplen); - ofs += m_trap->thl.gtrplenlen; - snmp_asn1_enc_u32t(p, ofs, m_trap->thl.gtrplen, m_trap->gen_trap); - ofs += m_trap->thl.gtrplen; - - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, m_trap->thl.strplen); - ofs += m_trap->thl.strplenlen; - snmp_asn1_enc_u32t(p, ofs, m_trap->thl.strplen, m_trap->spc_trap); - ofs += m_trap->thl.strplen; - - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, m_trap->thl.tslen); - ofs += m_trap->thl.tslenlen; - snmp_asn1_enc_u32t(p, ofs, m_trap->thl.tslen, m_trap->ts); - ofs += m_trap->thl.tslen; - - return ofs; -} - -/** - * Encodes varbind list from head to tail. - */ -static u16_t -snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs) -{ - struct snmp_varbind *vb; - s32_t *sint_ptr; - u32_t *uint_ptr; - u8_t *raw_ptr; - - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, root->seqlen); - ofs += root->seqlenlen; - - vb = root->head; - while ( vb != NULL ) - { - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, vb->seqlen); - ofs += vb->seqlenlen; - - snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)); - ofs += 1; - snmp_asn1_enc_length(p, ofs, vb->olen); - ofs += vb->olenlen; - snmp_asn1_enc_oid(p, ofs, vb->ident_len, &vb->ident[0]); - ofs += vb->olen; - - snmp_asn1_enc_type(p, ofs, vb->value_type); - ofs += 1; - snmp_asn1_enc_length(p, ofs, vb->vlen); - ofs += vb->vlenlen; - - switch (vb->value_type) - { - case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): - sint_ptr = (s32_t*)vb->value; - snmp_asn1_enc_s32t(p, ofs, vb->vlen, *sint_ptr); - break; - case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): - case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): - case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): - uint_ptr = (u32_t*)vb->value; - snmp_asn1_enc_u32t(p, ofs, vb->vlen, *uint_ptr); - break; - case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): - case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): - case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): - raw_ptr = (u8_t*)vb->value; - snmp_asn1_enc_raw(p, ofs, vb->vlen, raw_ptr); - break; - case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): - break; - case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): - sint_ptr = (s32_t*)vb->value; - snmp_asn1_enc_oid(p, ofs, vb->value_len / sizeof(s32_t), sint_ptr); - break; - default: - /* unsupported type */ - break; - }; - ofs += vb->vlen; - vb = vb->next; - } - return ofs; -} - -#endif /* LWIP_SNMP */ diff --git a/third_party/lwip/core/stats.c b/third_party/lwip/core/stats.c deleted file mode 100644 index cc232f7..0000000 --- a/third_party/lwip/core/stats.c +++ /dev/null @@ -1,182 +0,0 @@ -/** - * @file - * Statistics module - * - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" - -#if LWIP_STATS /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/stats.h" -#include "lwip/mem.h" - -#include - -struct stats_ lwip_stats; - -void ICACHE_FLASH_ATTR -stats_init(void) -{ -#ifdef LWIP_DEBUG -#if MEMP_STATS - const char * memp_names[] = { -#define LWIP_MEMPOOL(name,num,size,desc) desc, -#include "lwip/memp_std.h" - }; - int i; - for (i = 0; i < MEMP_MAX; i++) { - lwip_stats.memp[i].name = memp_names[i]; - } -#endif /* MEMP_STATS */ -#if MEM_STATS - lwip_stats.mem.name = "MEM"; -#endif /* MEM_STATS */ -#endif /* LWIP_DEBUG */ -} - -#if LWIP_STATS_DISPLAY -void ICACHE_FLASH_ATTR -stats_display_proto(struct stats_proto *proto, const char *name) -{ - LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); - LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit)); - LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv)); - LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw)); - LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop)); - LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", proto->chkerr)); - LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", proto->lenerr)); - LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", proto->memerr)); - LWIP_PLATFORM_DIAG(("rterr: %"STAT_COUNTER_F"\n\t", proto->rterr)); - LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", proto->proterr)); - LWIP_PLATFORM_DIAG(("opterr: %"STAT_COUNTER_F"\n\t", proto->opterr)); - LWIP_PLATFORM_DIAG(("err: %"STAT_COUNTER_F"\n\t", proto->err)); - LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit)); -} - -#if IGMP_STATS -void ICACHE_FLASH_ATTR -stats_display_igmp(struct stats_igmp *igmp, const char *name) -{ - LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); - LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit)); - LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv)); - LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop)); - LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", igmp->chkerr)); - LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr)); - LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", igmp->memerr)); - LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", igmp->proterr)); - LWIP_PLATFORM_DIAG(("rx_v1: %"STAT_COUNTER_F"\n\t", igmp->rx_v1)); - LWIP_PLATFORM_DIAG(("rx_group: %"STAT_COUNTER_F"\n\t", igmp->rx_group)); - LWIP_PLATFORM_DIAG(("rx_general: %"STAT_COUNTER_F"\n\t", igmp->rx_general)); - LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report)); - LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join)); - LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave)); - LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n\t", igmp->tx_report)); -} -#endif /* IGMP_STATS */ - -#if MEM_STATS || MEMP_STATS -void ICACHE_FLASH_ATTR -stats_display_mem(struct stats_mem *mem, const char *name) -{ - LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name)); - LWIP_PLATFORM_DIAG(("avail: %"U32_F"\n\t", (u32_t)mem->avail)); - LWIP_PLATFORM_DIAG(("used: %"U32_F"\n\t", (u32_t)mem->used)); - LWIP_PLATFORM_DIAG(("max: %"U32_F"\n\t", (u32_t)mem->max)); - LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err)); -} - -#if MEMP_STATS -void ICACHE_FLASH_ATTR -stats_display_memp(struct stats_mem *mem, int index) -{ - char * memp_names[] = { -#define LWIP_MEMPOOL(name,num,size,desc) desc, -#include "lwip/memp_std.h" - }; - if(index < MEMP_MAX) { - stats_display_mem(mem, memp_names[index]); - } -} -#endif /* MEMP_STATS */ -#endif /* MEM_STATS || MEMP_STATS */ - -#if SYS_STATS -void ICACHE_FLASH_ATTR -stats_display_sys(struct stats_sys *sys) -{ - LWIP_PLATFORM_DIAG(("\nSYS\n\t")); - LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used)); - LWIP_PLATFORM_DIAG(("sem.max: %"U32_F"\n\t", (u32_t)sys->sem.max)); - LWIP_PLATFORM_DIAG(("sem.err: %"U32_F"\n\t", (u32_t)sys->sem.err)); - LWIP_PLATFORM_DIAG(("mutex.used: %"U32_F"\n\t", (u32_t)sys->mutex.used)); - LWIP_PLATFORM_DIAG(("mutex.max: %"U32_F"\n\t", (u32_t)sys->mutex.max)); - LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err)); - LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used)); - LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max)); - LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n\t", (u32_t)sys->mbox.err)); -} -#endif /* SYS_STATS */ - -void ICACHE_FLASH_ATTR -stats_display(void) -{ - s16_t i; - - LINK_STATS_DISPLAY(); - ETHARP_STATS_DISPLAY(); - IPFRAG_STATS_DISPLAY(); - IP6_FRAG_STATS_DISPLAY(); - IP_STATS_DISPLAY(); - ND6_STATS_DISPLAY(); - IP6_STATS_DISPLAY(); - IGMP_STATS_DISPLAY(); - MLD6_STATS_DISPLAY(); - ICMP_STATS_DISPLAY(); - ICMP6_STATS_DISPLAY(); - UDP_STATS_DISPLAY(); - TCP_STATS_DISPLAY(); - MEM_STATS_DISPLAY(); - for (i = 0; i < MEMP_MAX; i++) { - MEMP_STATS_DISPLAY(i); - } - SYS_STATS_DISPLAY(); -} -#endif /* LWIP_STATS_DISPLAY */ - -#endif /* LWIP_STATS */ - diff --git a/third_party/lwip/core/sys.c b/third_party/lwip/core/sys.c deleted file mode 100644 index e3aa6fc..0000000 --- a/third_party/lwip/core/sys.c +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file - * lwIP Operating System abstraction - * - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" - -#include "lwip/sys.h" - -/* Most of the functions defined in sys.h must be implemented in the - * architecture-dependent file sys_arch.c */ - -#if !NO_SYS - -#ifndef sys_msleep -/** - * Sleep for some ms. Timeouts are NOT processed while sleeping. - * - * @param ms number of milliseconds to sleep - */ -void ICACHE_FLASH_ATTR -sys_msleep(u32_t ms) -{ - if (ms > 0) { - sys_sem_t delaysem; - err_t err = sys_sem_new(&delaysem, 0); - if (err == ERR_OK) { - sys_arch_sem_wait(&delaysem, ms); - sys_sem_free(&delaysem); - } - } -} -#endif /* sys_msleep */ - -#endif /* !NO_SYS */ diff --git a/third_party/lwip/core/tcp.c b/third_party/lwip/core/tcp.c deleted file mode 100644 index 9ffba07..0000000 --- a/third_party/lwip/core/tcp.c +++ /dev/null @@ -1,1820 +0,0 @@ -/** - * @file - * Transmission Control Protocol for IP - * - * This file contains common functions for the TCP implementation, such as functinos - * for manipulating the data structures and the TCP timer functions. TCP functions - * related to input and output is found in tcp_in.c and tcp_out.c respectively. - * - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" - -#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/snmp.h" -#include "lwip/tcp.h" -#include "lwip/tcp_impl.h" -#include "lwip/debug.h" -#include "lwip/stats.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/nd6.h" - -#include - -#ifndef TCP_LOCAL_PORT_RANGE_START -/* From http://www.iana.org/assignments/port-numbers: - "The Dynamic and/or Private Ports are those from 49152 through 65535" */ -#define TCP_LOCAL_PORT_RANGE_START 0xc000 -#define TCP_LOCAL_PORT_RANGE_END 0xffff -#define TCP_ENSURE_LOCAL_PORT_RANGE(port) (((port) & ~TCP_LOCAL_PORT_RANGE_START) + TCP_LOCAL_PORT_RANGE_START) -#endif - -#if LWIP_TCP_KEEPALIVE -#define TCP_KEEP_DUR(pcb) ((pcb)->keep_cnt * (pcb)->keep_intvl) -#define TCP_KEEP_INTVL(pcb) ((pcb)->keep_intvl) -#else /* LWIP_TCP_KEEPALIVE */ -#define TCP_KEEP_DUR(pcb) TCP_MAXIDLE -#define TCP_KEEP_INTVL(pcb) TCP_KEEPINTVL_DEFAULT -#endif /* LWIP_TCP_KEEPALIVE */ - -const char * const tcp_state_str[] = { - "CLOSED", - "LISTEN", - "SYN_SENT", - "SYN_RCVD", - "ESTABLISHED", - "FIN_WAIT_1", - "FIN_WAIT_2", - "CLOSE_WAIT", - "CLOSING", - "LAST_ACK", - "TIME_WAIT" -}; - -/* last local TCP port */ -static u16_t tcp_port = TCP_LOCAL_PORT_RANGE_START; - -/* Incremented every coarse grained timer shot (typically every 500 ms). */ -u32_t tcp_ticks; -const u8_t tcp_backoff[13] = - { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7}; - /* Times per slowtmr hits */ -const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; - -/* The TCP PCB lists. */ - -/** List of all TCP PCBs bound but not yet (connected || listening) */ -struct tcp_pcb *tcp_bound_pcbs; -/** List of all TCP PCBs in LISTEN state */ -union tcp_listen_pcbs_t tcp_listen_pcbs; -/** List of all TCP PCBs that are in a state in which - * they accept or send data. */ -struct tcp_pcb *tcp_active_pcbs; -/** List of all TCP PCBs in TIME-WAIT state */ -struct tcp_pcb *tcp_tw_pcbs; - -#define NUM_TCP_PCB_LISTS 4 -#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3 -/** An array with all (non-temporary) PCB lists, mainly used for smaller code size */ -struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, - &tcp_active_pcbs, &tcp_tw_pcbs}; - -/** Only used for temporary storage. */ -struct tcp_pcb *tcp_tmp_pcb; - -u8_t tcp_active_pcbs_changed; - -/** Timer counter to handle calling slow-timer from tcp_tmr() */ -static u8_t tcp_timer; -static u8_t tcp_timer_ctr; -static u16_t tcp_new_port(void); - -/** - * Initialize this module. - */ -void ICACHE_FLASH_ATTR -tcp_init(void) -{ -#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) - tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); -#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ -} - -/** - * Called periodically to dispatch TCP timers. - */ -void ICACHE_FLASH_ATTR -tcp_tmr(void) -{ - /* Call tcp_fasttmr() every 250 ms */ - tcp_fasttmr(); - - if (++tcp_timer & 1) { - /* Call tcp_tmr() every 500 ms, i.e., every other timer - tcp_tmr() is called. */ - tcp_slowtmr(); - } -} - -/** - * Closes the TX side of a connection held by the PCB. - * For tcp_close(), a RST is sent if the application didn't receive all data - * (tcp_recved() not called for all data passed to recv callback). - * - * Listening pcbs are freed and may not be referenced any more. - * Connection pcbs are freed if not yet connected and may not be referenced - * any more. If a connection is established (at least SYN received or in - * a closing state), the connection is closed, and put in a closing state. - * The pcb is then automatically freed in tcp_slowtmr(). It is therefore - * unsafe to reference it. - * - * @param pcb the tcp_pcb to close - * @return ERR_OK if connection has been closed - * another err_t if closing failed and pcb is not freed - */ -static err_t ICACHE_FLASH_ATTR -tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data) -{ - err_t err; - - if (rst_on_unacked_data && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { - if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND)) { - /* Not all data received by application, send RST to tell the remote - side about this. */ - LWIP_ASSERT("pcb->flags & TF_RXCLOSED", pcb->flags & TF_RXCLOSED); - - /* don't call tcp_abort here: we must not deallocate the pcb since - that might not be expected when calling tcp_close */ - tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, - pcb->local_port, pcb->remote_port, PCB_ISIPV6(pcb)); - - tcp_pcb_purge(pcb); - TCP_RMV_ACTIVE(pcb); - if (pcb->state == ESTABLISHED) { - /* move to TIME_WAIT since we close actively */ - pcb->state = TIME_WAIT; - TCP_REG(&tcp_tw_pcbs, pcb); - } else { - /* CLOSE_WAIT: deallocate the pcb since we already sent a RST for it */ - memp_free(MEMP_TCP_PCB, pcb); - } - return ERR_OK; - } - } - - switch (pcb->state) { - case CLOSED: - /* Closing a pcb in the CLOSED state might seem erroneous, - * however, it is in this state once allocated and as yet unused - * and the user needs some way to free it should the need arise. - * Calling tcp_close() with a pcb that has already been closed, (i.e. twice) - * or for a pcb that has been used and then entered the CLOSED state - * is erroneous, but this should never happen as the pcb has in those cases - * been freed, and so any remaining handles are bogus. */ - err = ERR_OK; - if (pcb->local_port != 0) { - TCP_RMV(&tcp_bound_pcbs, pcb); - } - memp_free(MEMP_TCP_PCB, pcb); - pcb = NULL; - break; - case LISTEN: - err = ERR_OK; - tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb); - memp_free(MEMP_TCP_PCB_LISTEN, pcb); - pcb = NULL; - break; - case SYN_SENT: - err = ERR_OK; - TCP_PCB_REMOVE_ACTIVE(pcb); - memp_free(MEMP_TCP_PCB, pcb); - pcb = NULL; - snmp_inc_tcpattemptfails(); - break; - case SYN_RCVD: - err = tcp_send_fin(pcb); - if (err == ERR_OK) { - snmp_inc_tcpattemptfails(); - pcb->state = FIN_WAIT_1; - } - break; - case ESTABLISHED: - err = tcp_send_fin(pcb); - if (err == ERR_OK) { - snmp_inc_tcpestabresets(); - pcb->state = FIN_WAIT_1; - } - break; - case CLOSE_WAIT: - err = tcp_send_fin(pcb); - if (err == ERR_OK) { - snmp_inc_tcpestabresets(); - pcb->state = LAST_ACK; - } - break; - default: - /* Has already been closed, do nothing. */ - err = ERR_OK; - pcb = NULL; - break; - } - - if (pcb != NULL && err == ERR_OK) { - /* To ensure all data has been sent when tcp_close returns, we have - to make sure tcp_output doesn't fail. - Since we don't really have to ensure all data has been sent when tcp_close - returns (unsent data is sent from tcp timer functions, also), we don't care - for the return value of tcp_output for now. */ - /* @todo: When implementing SO_LINGER, this must be changed somehow: - If SOF_LINGER is set, the data should be sent and acked before close returns. - This can only be valid for sequential APIs, not for the raw API. */ - tcp_output(pcb); - } - return err; -} - -/** - * Closes the connection held by the PCB. - * - * Listening pcbs are freed and may not be referenced any more. - * Connection pcbs are freed if not yet connected and may not be referenced - * any more. If a connection is established (at least SYN received or in - * a closing state), the connection is closed, and put in a closing state. - * The pcb is then automatically freed in tcp_slowtmr(). It is therefore - * unsafe to reference it (unless an error is returned). - * - * @param pcb the tcp_pcb to close - * @return ERR_OK if connection has been closed - * another err_t if closing failed and pcb is not freed - */ -err_t ICACHE_FLASH_ATTR -tcp_close(struct tcp_pcb *pcb) -{ -#if TCP_DEBUG - LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in ")); - tcp_debug_print_state(pcb->state); -#endif /* TCP_DEBUG */ - - if (pcb->state != LISTEN) { - /* Set a flag not to receive any more data... */ - pcb->flags |= TF_RXCLOSED; - } - /* ... and close */ - return tcp_close_shutdown(pcb, 1); -} - -/** - * Causes all or part of a full-duplex connection of this PCB to be shut down. - * This doesn't deallocate the PCB unless shutting down both sides! - * Shutting down both sides is the same as calling tcp_close, so if it succeds, - * the PCB should not be referenced any more. - * - * @param pcb PCB to shutdown - * @param shut_rx shut down receive side if this is != 0 - * @param shut_tx shut down send side if this is != 0 - * @return ERR_OK if shutdown succeeded (or the PCB has already been shut down) - * another err_t on error. - */ -err_t ICACHE_FLASH_ATTR -tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx) -{ - if (pcb->state == LISTEN) { - return ERR_CONN; - } - if (shut_rx) { - /* shut down the receive side: set a flag not to receive any more data... */ - pcb->flags |= TF_RXCLOSED; - if (shut_tx) { - /* shutting down the tx AND rx side is the same as closing for the raw API */ - return tcp_close_shutdown(pcb, 1); - } - /* ... and free buffered data */ - if (pcb->refused_data != NULL) { - pbuf_free(pcb->refused_data); - pcb->refused_data = NULL; - } - } - if (shut_tx) { - /* This can't happen twice since if it succeeds, the pcb's state is changed. - Only close in these states as the others directly deallocate the PCB */ - switch (pcb->state) { - case SYN_RCVD: - case ESTABLISHED: - case CLOSE_WAIT: - return tcp_close_shutdown(pcb, shut_rx); - default: - /* Not (yet?) connected, cannot shutdown the TX side as that would bring us - into CLOSED state, where the PCB is deallocated. */ - return ERR_CONN; - } - } - return ERR_OK; -} - -/** - * Abandons a connection and optionally sends a RST to the remote - * host. Deletes the local protocol control block. This is done when - * a connection is killed because of shortage of memory. - * - * @param pcb the tcp_pcb to abort - * @param reset boolean to indicate whether a reset should be sent - */ -void ICACHE_FLASH_ATTR -tcp_abandon(struct tcp_pcb *pcb, int reset) -{ - u32_t seqno, ackno; -#if LWIP_CALLBACK_API - tcp_err_fn errf; -#endif /* LWIP_CALLBACK_API */ - void *errf_arg; - - /* pcb->state LISTEN not allowed here */ - LWIP_ASSERT("don't call tcp_abort/tcp_abandon for listen-pcbs", - pcb->state != LISTEN); - /* Figure out on which TCP PCB list we are, and remove us. If we - are in an active state, call the receive function associated with - the PCB with a NULL argument, and send an RST to the remote end. */ - if (pcb->state == TIME_WAIT) { - tcp_pcb_remove(&tcp_tw_pcbs, pcb); - memp_free(MEMP_TCP_PCB, pcb); - } else { - int send_rst = reset && (pcb->state != CLOSED); - seqno = pcb->snd_nxt; - ackno = pcb->rcv_nxt; -#if LWIP_CALLBACK_API - errf = pcb->errf; -#endif /* LWIP_CALLBACK_API */ - errf_arg = pcb->callback_arg; - TCP_PCB_REMOVE_ACTIVE(pcb); - if (pcb->unacked != NULL) { - tcp_segs_free(pcb->unacked); - } - if (pcb->unsent != NULL) { - tcp_segs_free(pcb->unsent); - } -#if TCP_QUEUE_OOSEQ - if (pcb->ooseq != NULL) { - tcp_segs_free(pcb->ooseq); - } -#endif /* TCP_QUEUE_OOSEQ */ - if (send_rst) { - LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); - tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, pcb->local_port, pcb->remote_port, PCB_ISIPV6(pcb)); - } - memp_free(MEMP_TCP_PCB, pcb); - TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT); - } -} - -/** - * 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! - * - * @param pcb the tcp pcb to abort - */ -void ICACHE_FLASH_ATTR -tcp_abort(struct tcp_pcb *pcb) -{ - tcp_abandon(pcb, 1); -} - -/** - * Binds the connection to a local portnumber and IP address. If the - * IP address is not given (i.e., ipaddr == NULL), the IP address of - * the outgoing network interface is used instead. - * - * @param pcb the tcp_pcb to bind (no check is done whether this pcb is - * already bound!) - * @param ipaddr the local ip address to bind to (use IP_ADDR_ANY to bind - * to any local address - * @param port the local port to bind to - * @return ERR_USE if the port is already in use - * ERR_VAL if bind failed because the PCB is not in a valid state - * ERR_OK if bound - */ -err_t ICACHE_FLASH_ATTR -tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) -{ - int i; - int max_pcb_list = NUM_TCP_PCB_LISTS; - struct tcp_pcb *cpcb; - - LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_VAL); - -#if SO_REUSE - /* Unless the REUSEADDR flag is set, - we have to check the pcbs in TIME-WAIT state, also. - We do not dump TIME_WAIT pcb's; they can still be matched by incoming - packets using both local and remote IP addresses and ports to distinguish. - */ - if (ip_get_option(pcb, SOF_REUSEADDR)) { - max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT; - } -#endif /* SO_REUSE */ - - if (port == 0) { - port = tcp_new_port(); - if (port == 0) { - return ERR_BUF; - } - } - - /* Check if the address already is in use (on all lists) */ - for (i = 0; i < max_pcb_list; i++) { - for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { - if (cpcb->local_port == port) { -#if SO_REUSE - /* Omit checking for the same port if both pcbs have REUSEADDR set. - For SO_REUSEADDR, the duplicate-check for a 5-tuple is done in - tcp_connect. */ - if (!ip_get_option(pcb, SOF_REUSEADDR) || - !ip_get_option(cpcb, SOF_REUSEADDR)) -#endif /* SO_REUSE */ - { - /* @todo: check accept_any_ip_version */ - if (IP_PCB_IPVER_EQ(pcb, cpcb) && - (ipX_addr_isany(PCB_ISIPV6(pcb), &cpcb->local_ip) || - ipX_addr_isany(PCB_ISIPV6(pcb), ip_2_ipX(ipaddr)) || - ipX_addr_cmp(PCB_ISIPV6(pcb), &cpcb->local_ip, ip_2_ipX(ipaddr)))) { - return ERR_USE; - } - } - } - } - } - - if (!ipX_addr_isany(PCB_ISIPV6(pcb), ip_2_ipX(ipaddr))) { - ipX_addr_set(PCB_ISIPV6(pcb), &pcb->local_ip, ip_2_ipX(ipaddr)); - } - pcb->local_port = port; - TCP_REG(&tcp_bound_pcbs, pcb); - LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); - return ERR_OK; -} -#if LWIP_CALLBACK_API -/** - * Default accept callback if no accept callback is specified by the user. - */ -static err_t ICACHE_FLASH_ATTR -tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) -{ - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(err); - - return ERR_ABRT; -} -#endif /* LWIP_CALLBACK_API */ - -/** - * Set the state of the connection to be LISTEN, which means that it - * is able to accept incoming connections. The protocol control block - * is reallocated in order to consume less memory. Setting the - * connection to LISTEN is an irreversible process. - * - * @param pcb the original tcp_pcb - * @param backlog the incoming connections queue limit - * @return tcp_pcb used for listening, consumes less memory. - * - * @note The original tcp_pcb is freed. This function therefore has to be - * called like this: - * tpcb = tcp_listen(tpcb); - */ -struct tcp_pcb * ICACHE_FLASH_ATTR -tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) -{ - struct tcp_pcb_listen *lpcb; - - LWIP_UNUSED_ARG(backlog); - LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL); - - /* already listening? */ - if (pcb->state == LISTEN) { - return pcb; - } -#if SO_REUSE - if (ip_get_option(pcb, SOF_REUSEADDR)) { - /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage - is declared (listen-/connection-pcb), we have to make sure now that - this port is only used once for every local IP. */ - for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { - if ((lpcb->local_port == pcb->local_port) && - IP_PCB_IPVER_EQ(pcb, lpcb)) { - if (ipX_addr_cmp(PCB_ISIPV6(pcb), &lpcb->local_ip, &pcb->local_ip)) { - /* this address/port is already used */ - return NULL; - } - } - } - } -#endif /* SO_REUSE */ - lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN); - if (lpcb == NULL) { - return NULL; - } - lpcb->callback_arg = pcb->callback_arg; - lpcb->local_port = pcb->local_port; - lpcb->state = LISTEN; - lpcb->prio = pcb->prio; - lpcb->so_options = pcb->so_options; - ip_set_option(lpcb, SOF_ACCEPTCONN); - lpcb->ttl = pcb->ttl; - lpcb->tos = pcb->tos; -#if LWIP_IPV6 - PCB_ISIPV6(lpcb) = PCB_ISIPV6(pcb); - lpcb->accept_any_ip_version = 0; -#endif /* LWIP_IPV6 */ - ipX_addr_copy(PCB_ISIPV6(pcb), lpcb->local_ip, pcb->local_ip); - if (pcb->local_port != 0) { - TCP_RMV(&tcp_bound_pcbs, pcb); - } - memp_free(MEMP_TCP_PCB, pcb); -#if LWIP_CALLBACK_API - lpcb->accept = tcp_accept_null; -#endif /* LWIP_CALLBACK_API */ -#if TCP_LISTEN_BACKLOG - lpcb->accepts_pending = 0; - lpcb->backlog = (backlog ? backlog : 1); -#endif /* TCP_LISTEN_BACKLOG */ - TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb); - return (struct tcp_pcb *)lpcb; -} - -#if LWIP_IPV6 -/** - * Same as tcp_listen_with_backlog, but allows to accept IPv4 and IPv6 - * connections, if the pcb's local address is set to ANY. - */ -struct tcp_pcb * ICACHE_FLASH_ATTR -tcp_listen_dual_with_backlog(struct tcp_pcb *pcb, u8_t backlog) -{ - struct tcp_pcb *lpcb; - - lpcb = tcp_listen_with_backlog(pcb, backlog); - if ((lpcb != NULL) && - ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) { - /* The default behavior is to accept connections on either - * IPv4 or IPv6, if not bound. */ - /* @see NETCONN_FLAG_IPV6_V6ONLY for changing this behavior */ - ((struct tcp_pcb_listen*)lpcb)->accept_any_ip_version = 1; - } - return lpcb; -} -#endif /* LWIP_IPV6 */ - -/** - * Update the state that tracks the available window space to advertise. - * - * Returns how much extra window would be advertised if we sent an - * update now. - */ -u32_t ICACHE_FLASH_ATTR -tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb) -{ - u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd; - - if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) { - /* we can advertise more window */ - pcb->rcv_ann_wnd = pcb->rcv_wnd; - return new_right_edge - pcb->rcv_ann_right_edge; - } else { - if (TCP_SEQ_GT(pcb->rcv_nxt, pcb->rcv_ann_right_edge)) { - /* Can happen due to other end sending out of advertised window, - * but within actual available (but not yet advertised) window */ - pcb->rcv_ann_wnd = 0; - } else { - /* keep the right edge of window constant */ - u32_t new_rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt; - LWIP_ASSERT("new_rcv_ann_wnd <= 0xffff", new_rcv_ann_wnd <= 0xffff); - pcb->rcv_ann_wnd = (u16_t)new_rcv_ann_wnd; - } - return 0; - } -} - -/** - * This function should be called by the application when it has - * processed the data. The purpose is to advertise a larger window - * when the data has been processed. - * - * @param pcb the tcp_pcb for which data is read - * @param len the amount of bytes that have been read by the application - */ -void ICACHE_FLASH_ATTR -tcp_recved(struct tcp_pcb *pcb, u16_t len) -{ - int wnd_inflation; - - /* pcb->state LISTEN not allowed here */ - LWIP_ASSERT("don't call tcp_recved for listen-pcbs", - pcb->state != LISTEN); - LWIP_ASSERT("tcp_recved: len would wrap rcv_wnd\n", - len <= 0xffff - pcb->rcv_wnd ); - - pcb->rcv_wnd += len; - if (pcb->rcv_wnd > TCP_WND) { - pcb->rcv_wnd = TCP_WND; - } - - wnd_inflation = tcp_update_rcv_ann_wnd(pcb); - - /* If the change in the right edge of window is significant (default - * watermark is TCP_WND/4), then send an explicit update now. - * Otherwise wait for a packet to be sent in the normal course of - * events (or more window to be available later) */ - if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) { - tcp_ack_now(pcb); - tcp_output(pcb); - } - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: received %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n", - len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd)); -} - -/** - * Allocate a new local TCP port. - * - * @return a new (free) local TCP port number - */ -static u16_t ICACHE_FLASH_ATTR -tcp_new_port(void) -{ - u8_t i; - u16_t n = 0; - struct tcp_pcb *pcb; - -again: - if (tcp_port++ == TCP_LOCAL_PORT_RANGE_END) { - tcp_port = TCP_LOCAL_PORT_RANGE_START; - } - /* Check all PCB lists. */ - for (i = 0; i < NUM_TCP_PCB_LISTS; i++) { - for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) { - if (pcb->local_port == tcp_port) { - if (++n > (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START)) { - return 0; - } - goto again; - } - } - } - return tcp_port; -} - -/** - * Connects to another host. The function given as the "connected" - * argument will be called when the connection has been established. - * - * @param pcb the tcp_pcb used to establish the connection - * @param ipaddr the remote ip address to connect to - * @param port the remote tcp port to connect to - * @param connected callback function to call when connected (or on error) - * @return ERR_VAL if invalid arguments are given - * ERR_OK if connect request has been sent - * other err_t values if connect request couldn't be sent - */ -err_t ICACHE_FLASH_ATTR -tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, - tcp_connected_fn connected) -{ - err_t ret; - u32_t iss; - u16_t old_local_port; - - LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); - if (ipaddr != NULL) { - ipX_addr_set(PCB_ISIPV6(pcb), &pcb->remote_ip, ip_2_ipX(ipaddr)); - } else { - return ERR_VAL; - } - pcb->remote_port = port; - - /* check if we have a route to the remote host */ - if (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) { - /* no local IP address set, yet. */ - struct netif *netif; - ipX_addr_t *local_ip; - ipX_route_get_local_ipX(PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip, netif, local_ip); - if ((netif == NULL) || (local_ip == NULL)) { - /* Don't even try to send a SYN packet if we have no route - since that will fail. */ - return ERR_RTE; - } - /* Use the address as local address of the pcb. */ - ipX_addr_copy(PCB_ISIPV6(pcb), pcb->local_ip, *local_ip); - } - - old_local_port = pcb->local_port; - if (pcb->local_port == 0) { - pcb->local_port = tcp_new_port(); - if (pcb->local_port == 0) { - return ERR_BUF; - } - } -#if SO_REUSE - if (ip_get_option(pcb, SOF_REUSEADDR)) { - /* Since SOF_REUSEADDR allows reusing a local address, we have to make sure - now that the 5-tuple is unique. */ - struct tcp_pcb *cpcb; - int i; - /* Don't check listen- and bound-PCBs, check active- and TIME-WAIT PCBs. */ - for (i = 2; i < NUM_TCP_PCB_LISTS; i++) { - for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { - if ((cpcb->local_port == pcb->local_port) && - (cpcb->remote_port == port) && - IP_PCB_IPVER_EQ(cpcb, pcb) && - ipX_addr_cmp(PCB_ISIPV6(pcb), &cpcb->local_ip, &pcb->local_ip) && - ipX_addr_cmp(PCB_ISIPV6(pcb), &cpcb->remote_ip, ip_2_ipX(ipaddr))) { - /* linux returns EISCONN here, but ERR_USE should be OK for us */ - return ERR_USE; - } - } - } - } -#endif /* SO_REUSE */ - iss = tcp_next_iss(); - pcb->rcv_nxt = 0; - pcb->snd_nxt = iss; - pcb->lastack = iss - 1; - pcb->snd_lbb = iss - 1; - pcb->rcv_wnd = TCP_WND; - pcb->rcv_ann_wnd = TCP_WND; - pcb->rcv_ann_right_edge = pcb->rcv_nxt; - pcb->snd_wnd = TCP_WND; - /* As initial send MSS, we use TCP_MSS but limit it to 536. - The send MSS is updated when an MSS option is received. */ - pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; -#if TCP_CALCULATE_EFF_SEND_MSS - pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip, PCB_ISIPV6(pcb)); -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - pcb->cwnd = 1; - pcb->ssthresh = pcb->mss * 10; -#if LWIP_CALLBACK_API - pcb->connected = connected; -#else /* LWIP_CALLBACK_API */ - LWIP_UNUSED_ARG(connected); -#endif /* LWIP_CALLBACK_API */ - - /* Send a SYN together with the MSS option. */ - ret = tcp_enqueue_flags(pcb, TCP_SYN); - if (ret == ERR_OK) { - /* SYN segment was enqueued, changed the pcbs state now */ - pcb->state = SYN_SENT; - if (old_local_port != 0) { - TCP_RMV(&tcp_bound_pcbs, pcb); - } - TCP_REG_ACTIVE(pcb); - snmp_inc_tcpactiveopens(); - - tcp_output(pcb); - } - return ret; -} - -/** - * Called every 500 ms and implements the retransmission timer and the timer that - * removes PCBs that have been in TIME-WAIT for enough time. It also increments - * various timers such as the inactivity timer in each PCB. - * - * Automatically called from tcp_tmr(). - */ -void ICACHE_FLASH_ATTR -tcp_slowtmr(void) -{ - struct tcp_pcb *pcb, *prev; - u16_t eff_wnd; - u8_t pcb_remove; /* flag if a PCB should be removed */ - u8_t pcb_reset; /* flag if a RST should be sent when removing */ - err_t err; - - err = ERR_OK; - - ++tcp_ticks; - ++tcp_timer_ctr; - -tcp_slowtmr_start: - /* Steps through all of the active PCBs. */ - prev = NULL; - pcb = tcp_active_pcbs; - if (pcb == NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); - } - while (pcb != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); - LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); - LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); - LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); - if (pcb->last_timer == tcp_timer_ctr) { - /* skip this pcb, we have already processed it */ - pcb = pcb->next; - continue; - } - pcb->last_timer = tcp_timer_ctr; - - pcb_remove = 0; - pcb_reset = 0; - - if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) { - ++pcb_remove; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n")); - } - else if (pcb->nrtx == TCP_MAXRTX) { - ++pcb_remove; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n")); - } else { - if (pcb->persist_backoff > 0) { - /* If snd_wnd is zero, use persist timer to send 1 byte probes - * instead of using the standard retransmission mechanism. */ - pcb->persist_cnt++; - if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1]) { - pcb->persist_cnt = 0; - if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) { - pcb->persist_backoff++; - } - tcp_zero_window_probe(pcb); - } - } else { - /* Increase the retransmission timer if it is running */ - if(pcb->rtime >= 0) { - ++pcb->rtime; - } - - if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { - /* Time for a retransmission. */ - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F - " pcb->rto %"S16_F"\n", - pcb->rtime, pcb->rto)); - - /* Double retransmission time-out unless we are trying to - * connect to somebody (i.e., we are in SYN_SENT). */ - if (pcb->state != SYN_SENT) { - pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx]; - } - - /* Reset the retransmission timer. */ - pcb->rtime = 0; - - /* Reduce congestion window and ssthresh. */ - eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd); - pcb->ssthresh = eff_wnd >> 1; - if (pcb->ssthresh < (pcb->mss << 1)) { - pcb->ssthresh = (pcb->mss << 1); - } - pcb->cwnd = pcb->mss; - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F - " ssthresh %"U16_F"\n", - pcb->cwnd, pcb->ssthresh)); - - /* The following needs to be called AFTER cwnd is set to one - mss - STJ */ - tcp_rexmit_rto(pcb); - } - } - } - /* Check if this PCB has stayed too long in FIN-WAIT-2 */ - if (pcb->state == FIN_WAIT_2) { - /* If this PCB is in FIN_WAIT_2 because of SHUT_WR don't let it time out. */ - if (pcb->flags & TF_RXCLOSED) { - /* PCB was fully closed (either through close() or SHUT_RDWR): - normal FIN-WAIT timeout handling. */ - if ((u32_t)(tcp_ticks - pcb->tmr) > - TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) { - ++pcb_remove; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n")); - } - } - } - - /* Check if KEEPALIVE should be sent */ - if(ip_get_option(pcb, SOF_KEEPALIVE) && - ((pcb->state == ESTABLISHED) || - (pcb->state == CLOSE_WAIT))) { - if((u32_t)(tcp_ticks - pcb->tmr) > - (pcb->keep_idle + TCP_KEEP_DUR(pcb)) / TCP_SLOW_INTERVAL) - { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to ")); - ipX_addr_debug_print(PCB_ISIPV6(pcb), TCP_DEBUG, &pcb->remote_ip); - LWIP_DEBUGF(TCP_DEBUG, ("\n")); - - ++pcb_remove; - ++pcb_reset; - } - else if((u32_t)(tcp_ticks - pcb->tmr) > - (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEP_INTVL(pcb)) - / TCP_SLOW_INTERVAL) - { - tcp_keepalive(pcb); - pcb->keep_cnt_sent++; - } - } - - /* If this PCB has queued out of sequence data, but has been - inactive for too long, will drop the data (it will eventually - be retransmitted). */ -#if TCP_QUEUE_OOSEQ - if (pcb->ooseq != NULL && - (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) { - tcp_segs_free(pcb->ooseq); - pcb->ooseq = NULL; - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n")); - } -#endif /* TCP_QUEUE_OOSEQ */ - - /* Check if this PCB has stayed too long in SYN-RCVD */ - if (pcb->state == SYN_RCVD) { - if ((u32_t)(tcp_ticks - pcb->tmr) > - TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { - ++pcb_remove; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n")); - } - } - - /* Check if this PCB has stayed too long in LAST-ACK */ - if (pcb->state == LAST_ACK) { - if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { - ++pcb_remove; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n")); - } - } - - /* If the PCB should be removed, do it. */ - if (pcb_remove) { - struct tcp_pcb *pcb2; - tcp_err_fn err_fn; - void *err_arg; - tcp_pcb_purge(pcb); - /* Remove PCB from tcp_active_pcbs list. */ - if (prev != NULL) { - LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); - prev->next = pcb->next; - } else { - /* This PCB was the first. */ - LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb); - tcp_active_pcbs = pcb->next; - } - - if (pcb_reset) { - tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, - pcb->local_port, pcb->remote_port, PCB_ISIPV6(pcb)); - } - - err_fn = pcb->errf; - err_arg = pcb->callback_arg; - pcb2 = pcb; - pcb = pcb->next; - memp_free(MEMP_TCP_PCB, pcb2); - - tcp_active_pcbs_changed = 0; - TCP_EVENT_ERR(err_fn, err_arg, ERR_ABRT); - if (tcp_active_pcbs_changed) { - goto tcp_slowtmr_start; - } - } else { - /* get the 'next' element now and work with 'prev' below (in case of abort) */ - prev = pcb; - pcb = pcb->next; - - /* We check if we should poll the connection. */ - ++prev->polltmr; - if (prev->polltmr >= prev->pollinterval) { - prev->polltmr = 0; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n")); - tcp_active_pcbs_changed = 0; - TCP_EVENT_POLL(prev, err); - if (tcp_active_pcbs_changed) { - goto tcp_slowtmr_start; - } - /* if err == ERR_ABRT, 'prev' is already deallocated */ - if (err == ERR_OK) { - tcp_output(prev); - } - } - } - } - - - /* Steps through all of the TIME-WAIT PCBs. */ - prev = NULL; - pcb = tcp_tw_pcbs; - while (pcb != NULL) { - LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); - pcb_remove = 0; - - /* Check if this PCB has stayed long enough in TIME-WAIT */ - if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { - ++pcb_remove; - } - - - - /* If the PCB should be removed, do it. */ - if (pcb_remove) { - struct tcp_pcb *pcb2; - tcp_pcb_purge(pcb); - /* Remove PCB from tcp_tw_pcbs list. */ - if (prev != NULL) { - LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs); - prev->next = pcb->next; - } else { - /* This PCB was the first. */ - LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb); - tcp_tw_pcbs = pcb->next; - } - pcb2 = pcb; - pcb = pcb->next; - memp_free(MEMP_TCP_PCB, pcb2); - } else { - prev = pcb; - pcb = pcb->next; - } - } -} - -/** - * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously - * "refused" by upper layer (application) and sends delayed ACKs. - * - * Automatically called from tcp_tmr(). - */ -void ICACHE_FLASH_ATTR -tcp_fasttmr(void) -{ - struct tcp_pcb *pcb; - - ++tcp_timer_ctr; - -tcp_fasttmr_start: - pcb = tcp_active_pcbs; - - while(pcb != NULL) { - if (pcb->last_timer != tcp_timer_ctr) { - struct tcp_pcb *next; - pcb->last_timer = tcp_timer_ctr; - /* send delayed ACKs */ - if (pcb->flags & TF_ACK_DELAY) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n")); - tcp_ack_now(pcb); - tcp_output(pcb); - pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); - } - - next = pcb->next; - - /* If there is data which was previously "refused" by upper layer */ - if (pcb->refused_data != NULL) { - tcp_active_pcbs_changed = 0; - tcp_process_refused_data(pcb); - if (tcp_active_pcbs_changed) { - /* application callback has changed the pcb list: restart the loop */ - goto tcp_fasttmr_start; - } - } - pcb = next; - } - } -} - -/** Pass pcb->refused_data to the recv callback */ -err_t ICACHE_FLASH_ATTR -tcp_process_refused_data(struct tcp_pcb *pcb) -{ - err_t err; - u8_t refused_flags = pcb->refused_data->flags; - /* set pcb->refused_data to NULL in case the callback frees it and then - closes the pcb */ - struct pbuf *refused_data = pcb->refused_data; - pcb->refused_data = NULL; - /* Notify again application with data previously received. */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); - TCP_EVENT_RECV(pcb, refused_data, ERR_OK, err); - if (err == ERR_OK) { - /* did refused_data include a FIN? */ - if (refused_flags & PBUF_FLAG_TCP_FIN) { - /* correct rcv_wnd as the application won't call tcp_recved() - for the FIN's seqno */ - if (pcb->rcv_wnd != TCP_WND) { - pcb->rcv_wnd++; - } - TCP_EVENT_CLOSED(pcb, err); - if (err == ERR_ABRT) { - return ERR_ABRT; - } - } - } else if (err == ERR_ABRT) { - /* if err == ERR_ABRT, 'pcb' is already deallocated */ - /* Drop incoming packets because pcb is "full" (only if the incoming - segment contains data). */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); - return ERR_ABRT; - } else { - /* data is still refused, pbuf is still valid (go on for ACK-only packets) */ - pcb->refused_data = refused_data; - } - return ERR_OK; -} - -/** - * Deallocates a list of TCP segments (tcp_seg structures). - * - * @param seg tcp_seg list of TCP segments to free - */ -void ICACHE_FLASH_ATTR -tcp_segs_free(struct tcp_seg *seg) -{ - while (seg != NULL) { - struct tcp_seg *next = seg->next; - tcp_seg_free(seg); - seg = next; - } -} - -/** - * Frees a TCP segment (tcp_seg structure). - * - * @param seg single tcp_seg to free - */ -void ICACHE_FLASH_ATTR -tcp_seg_free(struct tcp_seg *seg) -{ - if (seg != NULL) { - if (seg->p != NULL) { - pbuf_free(seg->p); -#if TCP_DEBUG - seg->p = NULL; -#endif /* TCP_DEBUG */ - } - memp_free(MEMP_TCP_SEG, seg); - } -} - -/** - * Sets the priority of a connection. - * - * @param pcb the tcp_pcb to manipulate - * @param prio new priority - */ -void ICACHE_FLASH_ATTR -tcp_setprio(struct tcp_pcb *pcb, u8_t prio) -{ - pcb->prio = prio; -} - -#if TCP_QUEUE_OOSEQ -/** - * Returns a copy of the given TCP segment. - * The pbuf and data are not copied, only the pointers - * - * @param seg the old tcp_seg - * @return a copy of seg - */ -struct tcp_seg * ICACHE_FLASH_ATTR -tcp_seg_copy(struct tcp_seg *seg) -{ - struct tcp_seg *cseg; - - cseg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG); - if (cseg == NULL) { - return NULL; - } - SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg)); - pbuf_ref(cseg->p); - return cseg; -} -#endif /* TCP_QUEUE_OOSEQ */ - -#if LWIP_CALLBACK_API -/** - * Default receive callback that is called if the user didn't register - * a recv callback for the pcb. - */ -err_t ICACHE_FLASH_ATTR -tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) -{ - LWIP_UNUSED_ARG(arg); - if (p != NULL) { - tcp_recved(pcb, p->tot_len); - pbuf_free(p); - } else if (err == ERR_OK) { - return tcp_close(pcb); - } - return ERR_OK; -} -#endif /* LWIP_CALLBACK_API */ - -/** - * Kills the oldest active connection that has the same or lower priority than - * 'prio'. - * - * @param prio minimum priority - */ -static void ICACHE_FLASH_ATTR -tcp_kill_prio(u8_t prio) -{ - struct tcp_pcb *pcb, *inactive; - u32_t inactivity; - u8_t mprio; - - - mprio = TCP_PRIO_MAX; - - /* We kill the oldest active connection that has lower priority than prio. */ - inactivity = 0; - inactive = NULL; - for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - if (pcb->prio <= prio && - pcb->prio <= mprio && - (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { - inactivity = tcp_ticks - pcb->tmr; - inactive = pcb; - mprio = pcb->prio; - } - } - if (inactive != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", - (void *)inactive, inactivity)); - tcp_abort(inactive); - } -} - -/** - * Kills the oldest connection that is in TIME_WAIT state. - * Called from tcp_alloc() if no more connections are available. - */ -static void ICACHE_FLASH_ATTR -tcp_kill_timewait(void) -{ - struct tcp_pcb *pcb, *inactive; - u32_t inactivity; - - inactivity = 0; - inactive = NULL; - /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ - for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { - if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { - inactivity = tcp_ticks - pcb->tmr; - inactive = pcb; - } - } - if (inactive != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", - (void *)inactive, inactivity)); - tcp_abort(inactive); - } -} - -/** - * Allocate a new tcp_pcb structure. - * - * @param prio priority for the new pcb - * @return a new tcp_pcb that initially is in state CLOSED - */ -struct tcp_pcb * ICACHE_FLASH_ATTR -tcp_alloc(u8_t prio) -{ - struct tcp_pcb *pcb; - u32_t iss; - - pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); - if (pcb == NULL) { - /* Try killing oldest connection in TIME-WAIT. */ - LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n")); - tcp_kill_timewait(); - /* Try to allocate a tcp_pcb again. */ - pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); - if (pcb == NULL) { - /* Try killing active connections with lower priority than the new one. */ - LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio)); - tcp_kill_prio(prio); - /* Try to allocate a tcp_pcb again. */ - pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); - if (pcb != NULL) { - /* adjust err stats: memp_malloc failed twice before */ - MEMP_STATS_DEC(err, MEMP_TCP_PCB); - } - } - if (pcb != NULL) { - /* adjust err stats: timewait PCB was freed above */ - MEMP_STATS_DEC(err, MEMP_TCP_PCB); - } - } - if (pcb != NULL) { - memset(pcb, 0, sizeof(struct tcp_pcb)); - pcb->prio = prio; - pcb->snd_buf = TCP_SND_BUF; - pcb->snd_queuelen = 0; - pcb->rcv_wnd = TCP_WND; - pcb->rcv_ann_wnd = TCP_WND; - pcb->tos = 0; - pcb->ttl = TCP_TTL; - /* As initial send MSS, we use TCP_MSS but limit it to 536. - The send MSS is updated when an MSS option is received. */ - pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS; - pcb->rto = 3000 / TCP_SLOW_INTERVAL; - pcb->sa = 0; - pcb->sv = 3000 / TCP_SLOW_INTERVAL; - pcb->rtime = -1; - pcb->cwnd = 1; - iss = tcp_next_iss(); - pcb->snd_wl2 = iss; - pcb->snd_nxt = iss; - pcb->lastack = iss; - pcb->snd_lbb = iss; - pcb->tmr = tcp_ticks; - pcb->last_timer = tcp_timer_ctr; - - pcb->polltmr = 0; - -#if LWIP_CALLBACK_API - pcb->recv = tcp_recv_null; -#endif /* LWIP_CALLBACK_API */ - - /* Init KEEPALIVE timer */ - pcb->keep_idle = TCP_KEEPIDLE_DEFAULT; - -#if LWIP_TCP_KEEPALIVE - pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT; - pcb->keep_cnt = TCP_KEEPCNT_DEFAULT; -#endif /* LWIP_TCP_KEEPALIVE */ - - pcb->keep_cnt_sent = 0; - } - return pcb; -} - -/** - * Creates a new TCP protocol control block but doesn't place it on - * any of the TCP PCB lists. - * The pcb is not put on any list until binding using tcp_bind(). - * - * @internal: Maybe there should be a idle TCP PCB list where these - * PCBs are put on. Port reservation using tcp_bind() is implemented but - * allocated pcbs that are not bound can't be killed automatically if wanting - * to allocate a pcb with higher prio (@see tcp_kill_prio()) - * - * @return a new tcp_pcb that initially is in state CLOSED - */ -struct tcp_pcb * ICACHE_FLASH_ATTR -tcp_new(void) -{ - return tcp_alloc(TCP_PRIO_NORMAL); -} - -#if LWIP_IPV6 -/** - * Creates a new TCP-over-IPv6 protocol control block but doesn't - * place it on any of the TCP PCB lists. - * The pcb is not put on any list until binding using tcp_bind(). - * - * @return a new tcp_pcb that initially is in state CLOSED - */ -struct tcp_pcb * ICACHE_FLASH_ATTR -tcp_new_ip6(void) -{ - struct tcp_pcb * pcb; - pcb = tcp_alloc(TCP_PRIO_NORMAL); - ip_set_v6(pcb, 1); - return pcb; -} -#endif /* LWIP_IPV6 */ - -/** - * Used to specify the argument that should be passed callback - * functions. - * - * @param pcb tcp_pcb to set the callback argument - * @param arg void pointer argument to pass to callback functions - */ -void ICACHE_FLASH_ATTR -tcp_arg(struct tcp_pcb *pcb, void *arg) -{ - /* This function is allowed to be called for both listen pcbs and - connection pcbs. */ - pcb->callback_arg = arg; -} -#if LWIP_CALLBACK_API - -/** - * Used to specify the function that should be called when a TCP - * connection receives data. - * - * @param pcb tcp_pcb to set the recv callback - * @param recv callback function to call for this pcb when data is received - */ -void ICACHE_FLASH_ATTR -tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv) -{ - LWIP_ASSERT("invalid socket state for recv callback", pcb->state != LISTEN); - pcb->recv = recv; -} - -/** - * Used to specify the function that should be called when TCP data - * has been successfully delivered to the remote host. - * - * @param pcb tcp_pcb to set the sent callback - * @param sent callback function to call for this pcb when data is successfully sent - */ -void ICACHE_FLASH_ATTR -tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) -{ - LWIP_ASSERT("invalid socket state for sent callback", pcb->state != LISTEN); - pcb->sent = sent; -} - -/** - * Used to specify the function that should be called when a fatal error - * has occured on the connection. - * - * @param pcb tcp_pcb to set the err callback - * @param err callback function to call for this pcb when a fatal error - * has occured on the connection - */ -void ICACHE_FLASH_ATTR -tcp_err(struct tcp_pcb *pcb, tcp_err_fn err) -{ - LWIP_ASSERT("invalid socket state for err callback", pcb->state != LISTEN); - pcb->errf = err; -} - -/** - * Used for specifying the function that should be called when a - * LISTENing connection has been connected to another host. - * - * @param pcb tcp_pcb to set the accept callback - * @param accept callback function to call for this pcb when LISTENing - * connection has been connected to another host - */ -void ICACHE_FLASH_ATTR -tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept) -{ - /* This function is allowed to be called for both listen pcbs and - connection pcbs. */ - pcb->accept = accept; -} -#endif /* LWIP_CALLBACK_API */ - - -/** - * Used to specify the function that should be called periodically - * from TCP. The interval is specified in terms of the TCP coarse - * timer interval, which is called twice a second. - * - */ -void ICACHE_FLASH_ATTR -tcp_poll(struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval) -{ - LWIP_ASSERT("invalid socket state for poll", pcb->state != LISTEN); -#if LWIP_CALLBACK_API - pcb->poll = poll; -#else /* LWIP_CALLBACK_API */ - LWIP_UNUSED_ARG(poll); -#endif /* LWIP_CALLBACK_API */ - pcb->pollinterval = interval; -} - -/** - * Purges a TCP PCB. Removes any buffered data and frees the buffer memory - * (pcb->ooseq, pcb->unsent and pcb->unacked are freed). - * - * @param pcb tcp_pcb to purge. The pcb itself is not deallocated! - */ -void ICACHE_FLASH_ATTR -tcp_pcb_purge(struct tcp_pcb *pcb) -{ - if (pcb->state != CLOSED && - pcb->state != TIME_WAIT && - pcb->state != LISTEN) { - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); - -#if TCP_LISTEN_BACKLOG - if (pcb->state == SYN_RCVD) { - /* Need to find the corresponding listen_pcb and decrease its accepts_pending */ - struct tcp_pcb_listen *lpcb; - LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL", - tcp_listen_pcbs.listen_pcbs != NULL); - for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { - if ((lpcb->local_port == pcb->local_port) && - IP_PCB_IPVER_EQ(pcb, lpcb) && - (ipX_addr_isany(PCB_ISIPV6(lpcb), &lpcb->local_ip) || - ipX_addr_cmp(PCB_ISIPV6(lpcb), &pcb->local_ip, &lpcb->local_ip))) { - /* port and address of the listen pcb match the timed-out pcb */ - LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending", - lpcb->accepts_pending > 0); - lpcb->accepts_pending--; - break; - } - } - } -#endif /* TCP_LISTEN_BACKLOG */ - - - if (pcb->refused_data != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); - pbuf_free(pcb->refused_data); - pcb->refused_data = NULL; - } - if (pcb->unsent != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n")); - } - if (pcb->unacked != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n")); - } -#if TCP_QUEUE_OOSEQ - if (pcb->ooseq != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n")); - } - tcp_segs_free(pcb->ooseq); - pcb->ooseq = NULL; -#endif /* TCP_QUEUE_OOSEQ */ - - /* Stop the retransmission timer as it will expect data on unacked - queue if it fires */ - pcb->rtime = -1; - - tcp_segs_free(pcb->unsent); - tcp_segs_free(pcb->unacked); - pcb->unacked = pcb->unsent = NULL; -#if TCP_OVERSIZE - pcb->unsent_oversize = 0; -#endif /* TCP_OVERSIZE */ - } -} - -/** - * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first. - * - * @param pcblist PCB list to purge. - * @param pcb tcp_pcb to purge. The pcb itself is NOT deallocated! - */ -void ICACHE_FLASH_ATTR -tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) -{ - TCP_RMV(pcblist, pcb); - - tcp_pcb_purge(pcb); - - /* if there is an outstanding delayed ACKs, send it */ - if (pcb->state != TIME_WAIT && - pcb->state != LISTEN && - pcb->flags & TF_ACK_DELAY) { - pcb->flags |= TF_ACK_NOW; - tcp_output(pcb); - } - - if (pcb->state != LISTEN) { - LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL); - LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL); -#if TCP_QUEUE_OOSEQ - LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL); -#endif /* TCP_QUEUE_OOSEQ */ - } - - pcb->state = CLOSED; - - LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane()); -} - -/** - * Calculates a new initial sequence number for new connections. - * - * @return u32_t pseudo random sequence number - */ -u32_t ICACHE_FLASH_ATTR -tcp_next_iss(void) -{ - static u32_t iss = 6510; - - iss += tcp_ticks; /* XXX */ - return iss; -} - -#if TCP_CALCULATE_EFF_SEND_MSS -/** - * Calcluates the effective send mss that can be used for a specific IP address - * by using ip_route to determin the netif used to send to the address and - * calculating the minimum of TCP_MSS and that netif's mtu (if set). - */ -u16_t ICACHE_FLASH_ATTR -tcp_eff_send_mss_impl(u16_t sendmss, ipX_addr_t *dest -#if LWIP_IPV6 - , ipX_addr_t *src, u8_t isipv6 -#endif /* LWIP_IPV6 */ - ) -{ - u16_t mss_s; - struct netif *outif; - s16_t mtu; - - outif = ipX_route(isipv6, src, dest); -#if LWIP_IPV6 - if (isipv6) { - /* First look in destination cache, to see if there is a Path MTU. */ - mtu = nd6_get_destination_mtu(ipX_2_ip6(dest), outif); - } else -#endif /* LWIP_IPV6 */ - { - if (outif == NULL) { - return sendmss; - } - mtu = outif->mtu; - } - - if (mtu != 0) { - mss_s = mtu - IP_HLEN - TCP_HLEN; -#if LWIP_IPV6 - /* for IPv6, substract the difference in header size */ - mss_s -= (IP6_HLEN - IP_HLEN); -#endif /* LWIP_IPV6 */ - /* RFC 1122, chap 4.2.2.6: - * Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize - * We correct for TCP options in tcp_write(), and don't support IP options. - */ - sendmss = LWIP_MIN(sendmss, mss_s); - } - return sendmss; -} -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - -const char* ICACHE_FLASH_ATTR -tcp_debug_state_str(enum tcp_state s) -{ - return tcp_state_str[s]; -} - -#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG -/** - * Print a tcp header for debugging purposes. - * - * @param tcphdr pointer to a struct tcp_hdr - */ -void ICACHE_FLASH_ATTR -tcp_debug_print(struct tcp_hdr *tcphdr) -{ - LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", - ntohs(tcphdr->src), ntohs(tcphdr->dest))); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", - ntohl(tcphdr->seqno))); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", - ntohl(tcphdr->ackno))); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", - TCPH_HDRLEN(tcphdr), - TCPH_FLAGS(tcphdr) >> 5 & 1, - TCPH_FLAGS(tcphdr) >> 4 & 1, - TCPH_FLAGS(tcphdr) >> 3 & 1, - TCPH_FLAGS(tcphdr) >> 2 & 1, - TCPH_FLAGS(tcphdr) >> 1 & 1, - TCPH_FLAGS(tcphdr) & 1, - ntohs(tcphdr->wnd))); - tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); - LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", - ntohs(tcphdr->chksum), ntohs(tcphdr->urgp))); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); -} - -/** - * Print a tcp state for debugging purposes. - * - * @param s enum tcp_state to print - */ -void ICACHE_FLASH_ATTR -tcp_debug_print_state(enum tcp_state s) -{ - LWIP_DEBUGF(TCP_DEBUG, ("State: %s\n", tcp_state_str[s])); -} - -/** - * Print tcp flags for debugging purposes. - * - * @param flags tcp flags, all active flags are printed - */ -void ICACHE_FLASH_ATTR -tcp_debug_print_flags(u8_t flags) -{ - if (flags & TCP_FIN) { - LWIP_DEBUGF(TCP_DEBUG, ("FIN ")); - } - if (flags & TCP_SYN) { - LWIP_DEBUGF(TCP_DEBUG, ("SYN ")); - } - if (flags & TCP_RST) { - LWIP_DEBUGF(TCP_DEBUG, ("RST ")); - } - if (flags & TCP_PSH) { - LWIP_DEBUGF(TCP_DEBUG, ("PSH ")); - } - if (flags & TCP_ACK) { - LWIP_DEBUGF(TCP_DEBUG, ("ACK ")); - } - if (flags & TCP_URG) { - LWIP_DEBUGF(TCP_DEBUG, ("URG ")); - } - if (flags & TCP_ECE) { - LWIP_DEBUGF(TCP_DEBUG, ("ECE ")); - } - if (flags & TCP_CWR) { - LWIP_DEBUGF(TCP_DEBUG, ("CWR ")); - } - LWIP_DEBUGF(TCP_DEBUG, ("\n")); -} - -/** - * Print all tcp_pcbs in every list for debugging purposes. - */ -void ICACHE_FLASH_ATTR -tcp_debug_print_pcbs(void) -{ - struct tcp_pcb *pcb; - LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); - for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", - pcb->local_port, pcb->remote_port, - pcb->snd_nxt, pcb->rcv_nxt)); - tcp_debug_print_state(pcb->state); - } - LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); - for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", - pcb->local_port, pcb->remote_port, - pcb->snd_nxt, pcb->rcv_nxt)); - tcp_debug_print_state(pcb->state); - } - LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); - for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", - pcb->local_port, pcb->remote_port, - pcb->snd_nxt, pcb->rcv_nxt)); - tcp_debug_print_state(pcb->state); - } -} - -/** - * Check state consistency of the tcp_pcb lists. - */ -s16_t ICACHE_FLASH_ATTR -tcp_pcbs_sane(void) -{ - struct tcp_pcb *pcb; - for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED); - LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN); - LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); - } - for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); - } - return 1; -} -#endif /* TCP_DEBUG */ - -#endif /* LWIP_TCP */ diff --git a/third_party/lwip/core/tcp_in.c b/third_party/lwip/core/tcp_in.c deleted file mode 100644 index a255810..0000000 --- a/third_party/lwip/core/tcp_in.c +++ /dev/null @@ -1,1652 +0,0 @@ -/** - * @file - * Transmission Control Protocol, incoming traffic - * - * The input processing functions of the TCP layer. - * - * These functions are generally called in the order (ip_input() ->) - * tcp_input() -> * tcp_process() -> tcp_receive() (-> application). - * - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" - -#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/tcp_impl.h" -#include "lwip/def.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/inet_chksum.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "arch/perf.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" -#if LWIP_ND6_TCP_REACHABILITY_HINTS -#include "lwip/nd6.h" -#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ - -/* These variables are global to all functions involved in the input - processing of TCP segments. They are set by the tcp_input() - function. */ -static struct tcp_seg inseg; -static struct tcp_hdr *tcphdr; -static u32_t seqno, ackno; -static u8_t flags; -static u16_t tcplen; - -static u8_t recv_flags; -static struct pbuf *recv_data; - -struct tcp_pcb *tcp_input_pcb; - -/* Forward declarations. */ -static err_t tcp_process(struct tcp_pcb *pcb); -static void tcp_receive(struct tcp_pcb *pcb); -static void tcp_parseopt(struct tcp_pcb *pcb); - -static err_t tcp_listen_input(struct tcp_pcb_listen *pcb); -static err_t tcp_timewait_input(struct tcp_pcb *pcb); - -/** - * The initial input processing of TCP. It verifies the TCP header, demultiplexes - * the segment between the PCBs and passes it on to tcp_process(), which implements - * the TCP finite state machine. This function is called by the IP layer (in - * ip_input()). - * - * @param p received TCP segment to process (p->payload pointing to the TCP header) - * @param inp network interface on which this segment was received - */ -void ICACHE_FLASH_ATTR -tcp_input(struct pbuf *p, struct netif *inp) -{ - struct tcp_pcb *pcb, *prev; - struct tcp_pcb_listen *lpcb; -#if SO_REUSE - struct tcp_pcb *lpcb_prev = NULL; - struct tcp_pcb_listen *lpcb_any = NULL; -#endif /* SO_REUSE */ - u8_t hdrlen; - err_t err; -#if CHECKSUM_CHECK_TCP - u16_t chksum; -#endif /* CHECKSUM_CHECK_TCP */ - - PERF_START; - - TCP_STATS_INC(tcp.recv); - snmp_inc_tcpinsegs(); - - tcphdr = (struct tcp_hdr *)p->payload; - -#if TCP_INPUT_DEBUG - tcp_debug_print(tcphdr); -#endif - - /* Check that TCP header fits in payload */ - if (p->len < sizeof(struct tcp_hdr)) { - /* drop short packets */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); - TCP_STATS_INC(tcp.lenerr); - goto dropped; - } - - /* Don't even process incoming broadcasts/multicasts. */ - if ((!ip_current_is_v6() && ip_addr_isbroadcast(ip_current_dest_addr(), inp)) || - ipX_addr_ismulticast(ip_current_is_v6(), ipX_current_dest_addr())) { - TCP_STATS_INC(tcp.proterr); - goto dropped; - } - -#if CHECKSUM_CHECK_TCP - /* Verify TCP checksum. */ - chksum = ipX_chksum_pseudo(ip_current_is_v6(), p, IP_PROTO_TCP, p->tot_len, - ipX_current_src_addr(), ipX_current_dest_addr()); - if (chksum != 0) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n", - chksum)); - tcp_debug_print(tcphdr); - TCP_STATS_INC(tcp.chkerr); - goto dropped; - } -#endif /* CHECKSUM_CHECK_TCP */ - - /* Move the payload pointer in the pbuf so that it points to the - TCP data instead of the TCP header. */ - hdrlen = TCPH_HDRLEN(tcphdr); - if(pbuf_header(p, -(hdrlen * 4))){ - /* drop short packets */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n")); - TCP_STATS_INC(tcp.lenerr); - goto dropped; - } - - /* Convert fields in TCP header to host byte order. */ - tcphdr->src = ntohs(tcphdr->src); - tcphdr->dest = ntohs(tcphdr->dest); - seqno = tcphdr->seqno = ntohl(tcphdr->seqno); - ackno = tcphdr->ackno = ntohl(tcphdr->ackno); - tcphdr->wnd = ntohs(tcphdr->wnd); - - flags = TCPH_FLAGS(tcphdr); - tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0); - - /* Demultiplex an incoming segment. First, we check if it is destined - for an active connection. */ - prev = NULL; - - - for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED); - LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); - LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); - if (pcb->remote_port == tcphdr->src && - pcb->local_port == tcphdr->dest && - IP_PCB_IPVER_INPUT_MATCH(pcb) && - ipX_addr_cmp(ip_current_is_v6(), &pcb->remote_ip, ipX_current_src_addr()) && - ipX_addr_cmp(ip_current_is_v6(),&pcb->local_ip, ipX_current_dest_addr())) { - /* Move this PCB to the front of the list so that subsequent - lookups will be faster (we exploit locality in TCP segment - arrivals). */ - LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); - if (prev != NULL) { - prev->next = pcb->next; - pcb->next = tcp_active_pcbs; - tcp_active_pcbs = pcb; - } - LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb); - break; - } - prev = pcb; - } - - if (pcb == NULL) { - /* If it did not go to an active connection, we check the connections - in the TIME-WAIT state. */ - for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); - if (pcb->remote_port == tcphdr->src && - pcb->local_port == tcphdr->dest && - IP_PCB_IPVER_INPUT_MATCH(pcb) && - ipX_addr_cmp(ip_current_is_v6(), &pcb->remote_ip, ipX_current_src_addr()) && - ipX_addr_cmp(ip_current_is_v6(),&pcb->local_ip, ipX_current_dest_addr())) { - /* We don't really care enough to move this PCB to the front - of the list since we are not very likely to receive that - many segments for connections in TIME-WAIT. */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n")); - tcp_timewait_input(pcb); - pbuf_free(p); - return; - } - } - - /* Finally, if we still did not get a match, we check all PCBs that - are LISTENing for incoming connections. */ - prev = NULL; - for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { - if (lpcb->local_port == tcphdr->dest) { -#if LWIP_IPV6 - if (lpcb->accept_any_ip_version) { - /* found an ANY-match */ -#if SO_REUSE - lpcb_any = lpcb; - lpcb_prev = prev; -#else /* SO_REUSE */ - break; -#endif /* SO_REUSE */ - } else -#endif /* LWIP_IPV6 */ - if (IP_PCB_IPVER_INPUT_MATCH(lpcb)) { - if (ipX_addr_cmp(ip_current_is_v6(), &lpcb->local_ip, ipX_current_dest_addr())) { - /* found an exact match */ - break; - } else if (ipX_addr_isany(ip_current_is_v6(), &lpcb->local_ip)) { - /* found an ANY-match */ -#if SO_REUSE - lpcb_any = lpcb; - lpcb_prev = prev; -#else /* SO_REUSE */ - break; - #endif /* SO_REUSE */ - } - } - } - prev = (struct tcp_pcb *)lpcb; - } -#if SO_REUSE - /* first try specific local IP */ - if (lpcb == NULL) { - /* only pass to ANY if no specific local IP has been found */ - lpcb = lpcb_any; - prev = lpcb_prev; - } -#endif /* SO_REUSE */ - if (lpcb != NULL) { - /* Move this PCB to the front of the list so that subsequent - lookups will be faster (we exploit locality in TCP segment - arrivals). */ - if (prev != NULL) { - ((struct tcp_pcb_listen *)prev)->next = lpcb->next; - /* our successor is the remainder of the listening list */ - lpcb->next = tcp_listen_pcbs.listen_pcbs; - /* put this listening pcb at the head of the listening list */ - tcp_listen_pcbs.listen_pcbs = lpcb; - } - - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); - tcp_listen_input(lpcb); - pbuf_free(p); - return; - } - } - -#if TCP_INPUT_DEBUG - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags ")); - tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n")); -#endif /* TCP_INPUT_DEBUG */ - - - if (pcb != NULL) { - /* The incoming segment belongs to a connection. */ -#if TCP_INPUT_DEBUG -#if TCP_DEBUG - tcp_debug_print_state(pcb->state); -#endif /* TCP_DEBUG */ -#endif /* TCP_INPUT_DEBUG */ - - /* Set up a tcp_seg structure. */ - inseg.next = NULL; - inseg.len = p->tot_len; - inseg.p = p; - inseg.tcphdr = tcphdr; - - recv_data = NULL; - recv_flags = 0; - - if (flags & TCP_PSH) { - p->flags |= PBUF_FLAG_PUSH; - } - - /* If there is data which was previously "refused" by upper layer */ - if (pcb->refused_data != NULL) { - if ((tcp_process_refused_data(pcb) == ERR_ABRT) || - ((pcb->refused_data != NULL) && (tcplen > 0))) { - /* pcb has been aborted or refused data is still refused and the new - segment contains data */ - TCP_STATS_INC(tcp.drop); - snmp_inc_tcpinerrs(); - goto aborted; - } - } - tcp_input_pcb = pcb; - err = tcp_process(pcb); - /* A return value of ERR_ABRT means that tcp_abort() was called - and that the pcb has been freed. If so, we don't do anything. */ - if (err != ERR_ABRT) { - if (recv_flags & TF_RESET) { - /* TF_RESET means that the connection was reset by the other - end. We then call the error callback to inform the - application that the connection is dead before we - deallocate the PCB. */ - TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST); - tcp_pcb_remove(&tcp_active_pcbs, pcb); - memp_free(MEMP_TCP_PCB, pcb); - } else if (recv_flags & TF_CLOSED) { - /* The connection has been closed and we will deallocate the - PCB. */ - if (!(pcb->flags & TF_RXCLOSED)) { - /* Connection closed although the application has only shut down the - tx side: call the PCB's err callback and indicate the closure to - ensure the application doesn't continue using the PCB. */ - TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_CLSD); - } - tcp_pcb_remove(&tcp_active_pcbs, pcb); - memp_free(MEMP_TCP_PCB, pcb); - } else { - err = ERR_OK; - /* If the application has registered a "sent" function to be - called when new send buffer space is available, we call it - now. */ - if (pcb->acked > 0) { - TCP_EVENT_SENT(pcb, pcb->acked, err); - if (err == ERR_ABRT) { - goto aborted; - } - } - - if (recv_data != NULL) { - LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL); - if (pcb->flags & TF_RXCLOSED) { - /* received data although already closed -> abort (send RST) to - notify the remote host that not all data has been processed */ - pbuf_free(recv_data); - tcp_abort(pcb); - goto aborted; - } - - /* Notify application that data has been received. */ - TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); - if (err == ERR_ABRT) { - goto aborted; - } - - /* If the upper layer can't receive this data, store it */ - if (err != ERR_OK) { - pcb->refused_data = recv_data; - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n")); - } - } - - /* If a FIN segment was received, we call the callback - function with a NULL buffer to indicate EOF. */ - if (recv_flags & TF_GOT_FIN) { - if (pcb->refused_data != NULL) { - /* Delay this if we have refused data. */ - pcb->refused_data->flags |= PBUF_FLAG_TCP_FIN; - } else { - /* correct rcv_wnd as the application won't call tcp_recved() - for the FIN's seqno */ - if (pcb->rcv_wnd != TCP_WND) { - pcb->rcv_wnd++; - } - TCP_EVENT_CLOSED(pcb, err); - if (err == ERR_ABRT) { - goto aborted; - } - } - } - - tcp_input_pcb = NULL; - /* Try to send something out. */ - tcp_output(pcb); -#if TCP_INPUT_DEBUG -#if TCP_DEBUG - tcp_debug_print_state(pcb->state); -#endif /* TCP_DEBUG */ -#endif /* TCP_INPUT_DEBUG */ - } - } - /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()). - Below this line, 'pcb' may not be dereferenced! */ -aborted: - tcp_input_pcb = NULL; - recv_data = NULL; - - /* give up our reference to inseg.p */ - if (inseg.p != NULL) - { - pbuf_free(inseg.p); - inseg.p = NULL; - } - } else { - - /* If no matching PCB was found, send a TCP RST (reset) to the - sender. */ - LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); - if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { - TCP_STATS_INC(tcp.proterr); - TCP_STATS_INC(tcp.drop); - tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(), - ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6()); - } - pbuf_free(p); - } - - LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane()); - PERF_STOP("tcp_input"); - return; -dropped: - TCP_STATS_INC(tcp.drop); - snmp_inc_tcpinerrs(); - pbuf_free(p); -} - -/** - * Called by tcp_input() when a segment arrives for a listening - * connection (from tcp_input()). - * - * @param pcb the tcp_pcb_listen for which a segment arrived - * @return ERR_OK if the segment was processed - * another err_t on error - * - * @note the return value is not (yet?) used in tcp_input() - * @note the segment which arrived is saved in global variables, therefore only the pcb - * involved is passed as a parameter to this function - */ -static err_t ICACHE_FLASH_ATTR -tcp_listen_input(struct tcp_pcb_listen *pcb) -{ - struct tcp_pcb *npcb; - err_t rc; - - if (flags & TCP_RST) { - /* An incoming RST should be ignored. Return. */ - return ERR_OK; - } - - /* In the LISTEN state, we check for incoming SYN segments, - creates a new PCB, and responds with a SYN|ACK. */ - if (flags & TCP_ACK) { - /* For incoming segments with the ACK flag set, respond with a - RST. */ - LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n")); - tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(), - ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6()); - } else if (flags & TCP_SYN) { - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); -#if TCP_LISTEN_BACKLOG - if (pcb->accepts_pending >= pcb->backlog) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest)); - return ERR_ABRT; - } -#endif /* TCP_LISTEN_BACKLOG */ - npcb = tcp_alloc(pcb->prio); - /* If a new PCB could not be created (probably due to lack of memory), - we don't do anything, but rely on the sender will retransmit the - SYN at a time when we have more memory available. */ - if (npcb == NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); - TCP_STATS_INC(tcp.memerr); - return ERR_MEM; - } -#if TCP_LISTEN_BACKLOG - pcb->accepts_pending++; -#endif /* TCP_LISTEN_BACKLOG */ - /* Set up the new PCB. */ -#if LWIP_IPV6 - PCB_ISIPV6(npcb) = ip_current_is_v6(); -#endif /* LWIP_IPV6 */ - ipX_addr_copy(ip_current_is_v6(), npcb->local_ip, *ipX_current_dest_addr()); - ipX_addr_copy(ip_current_is_v6(), npcb->remote_ip, *ipX_current_src_addr()); - npcb->local_port = pcb->local_port; - npcb->remote_port = tcphdr->src; - npcb->state = SYN_RCVD; - npcb->rcv_nxt = seqno + 1; - npcb->rcv_ann_right_edge = npcb->rcv_nxt; - npcb->snd_wnd = tcphdr->wnd; - npcb->snd_wnd_max = tcphdr->wnd; - npcb->ssthresh = npcb->snd_wnd; - npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ - npcb->callback_arg = pcb->callback_arg; -#if LWIP_CALLBACK_API - npcb->accept = pcb->accept; -#endif /* LWIP_CALLBACK_API */ - /* inherit socket options */ - npcb->so_options = pcb->so_options & SOF_INHERITED; - /* Register the new PCB so that we can begin receiving segments - for it. */ - TCP_REG_ACTIVE(npcb); - - /* Parse any options in the SYN. */ - tcp_parseopt(npcb); -#if TCP_CALCULATE_EFF_SEND_MSS - npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, - &npcb->remote_ip, PCB_ISIPV6(npcb)); -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - - snmp_inc_tcppassiveopens(); - - /* Send a SYN|ACK together with the MSS option. */ - rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK); - if (rc != ERR_OK) { - tcp_abandon(npcb, 0); - return rc; - } - return tcp_output(npcb); - } - return ERR_OK; -} - -/** - * Called by tcp_input() when a segment arrives for a connection in - * TIME_WAIT. - * - * @param pcb the tcp_pcb for which a segment arrived - * - * @note the segment which arrived is saved in global variables, therefore only the pcb - * involved is passed as a parameter to this function - */ -static err_t ICACHE_FLASH_ATTR -tcp_timewait_input(struct tcp_pcb *pcb) -{ - /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */ - /* RFC 793 3.9 Event Processing - Segment Arrives: - * - first check sequence number - we skip that one in TIME_WAIT (always - * acceptable since we only send ACKs) - * - second check the RST bit (... return) */ - if (flags & TCP_RST) { - return ERR_OK; - } - /* - fourth, check the SYN bit, */ - if (flags & TCP_SYN) { - /* If an incoming segment is not acceptable, an acknowledgment - should be sent in reply */ - if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) { - /* If the SYN is in the window it is an error, send a reset */ - tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(), - ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6()); - return ERR_OK; - } - } else if (flags & TCP_FIN) { - /* - eighth, check the FIN bit: Remain in the TIME-WAIT state. - Restart the 2 MSL time-wait timeout.*/ - pcb->tmr = tcp_ticks; - } - - if ((tcplen > 0)) { - /* Acknowledge data, FIN or out-of-window SYN */ - pcb->flags |= TF_ACK_NOW; - return tcp_output(pcb); - } - return ERR_OK; -} - -/** - * Implements the TCP state machine. Called by tcp_input. In some - * states tcp_receive() is called to receive data. The tcp_seg - * argument will be freed by the caller (tcp_input()) unless the - * recv_data pointer in the pcb is set. - * - * @param pcb the tcp_pcb for which a segment arrived - * - * @note the segment which arrived is saved in global variables, therefore only the pcb - * involved is passed as a parameter to this function - */ -static err_t ICACHE_FLASH_ATTR -tcp_process(struct tcp_pcb *pcb) -{ - struct tcp_seg *rseg; - u8_t acceptable = 0; - err_t err; - - err = ERR_OK; - - /* Process incoming RST segments. */ - if (flags & TCP_RST) { - /* First, determine if the reset is acceptable. */ - if (pcb->state == SYN_SENT) { - if (ackno == pcb->snd_nxt) { - acceptable = 1; - } - } else { - if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, - pcb->rcv_nxt+pcb->rcv_wnd)) { - acceptable = 1; - } - } - - if (acceptable) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n")); - LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED); - recv_flags |= TF_RESET; - pcb->flags &= ~TF_ACK_DELAY; - return ERR_RST; - } else { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", - seqno, pcb->rcv_nxt)); - LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", - seqno, pcb->rcv_nxt)); - return ERR_OK; - } - } - - if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { - /* Cope with new connection attempt after remote end crashed */ - tcp_ack_now(pcb); - return ERR_OK; - } - - if ((pcb->flags & TF_RXCLOSED) == 0) { - /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */ - pcb->tmr = tcp_ticks; - } - pcb->keep_cnt_sent = 0; - - tcp_parseopt(pcb); - - /* Do different things depending on the TCP state. */ - switch (pcb->state) { - case SYN_SENT: - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, - pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno))); - /* received SYN ACK with expected sequence number? */ - if ((flags & TCP_ACK) && (flags & TCP_SYN) - && ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) { - pcb->snd_buf++; - pcb->rcv_nxt = seqno + 1; - pcb->rcv_ann_right_edge = pcb->rcv_nxt; - pcb->lastack = ackno; - pcb->snd_wnd = tcphdr->wnd; - pcb->snd_wnd_max = tcphdr->wnd; - pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ - pcb->state = ESTABLISHED; - -#if TCP_CALCULATE_EFF_SEND_MSS - pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip, - PCB_ISIPV6(pcb)); -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - - /* Set ssthresh again after changing pcb->mss (already set in tcp_connect - * but for the default value of pcb->mss) */ - pcb->ssthresh = pcb->mss * 10; - - pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss); - LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); - --pcb->snd_queuelen; - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen)); - rseg = pcb->unacked; - pcb->unacked = rseg->next; - tcp_seg_free(rseg); - - /* If there's nothing left to acknowledge, stop the retransmit - timer, otherwise reset it to start again */ - if(pcb->unacked == NULL) - pcb->rtime = -1; - else { - pcb->rtime = 0; - pcb->nrtx = 0; - } - - /* Call the user specified function to call when sucessfully - * connected. */ - TCP_EVENT_CONNECTED(pcb, ERR_OK, err); - if (err == ERR_ABRT) { - return ERR_ABRT; - } - tcp_ack_now(pcb); - } - /* received ACK? possibly a half-open connection */ - else if (flags & TCP_ACK) { - /* send a RST to bring the other side in a non-synchronized state. */ - tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(), - ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6()); - } - break; - case SYN_RCVD: - if (flags & TCP_ACK) { - /* expected ACK number? */ - if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { - u16_t old_cwnd; - pcb->state = ESTABLISHED; - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); -#if LWIP_CALLBACK_API - LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL); -#endif - /* Call the accept function. */ - TCP_EVENT_ACCEPT(pcb, ERR_OK, err); - if (err != ERR_OK) { - /* If the accept function returns with an error, we abort - * the connection. */ - /* Already aborted? */ - if (err != ERR_ABRT) { - tcp_abort(pcb); - } - return ERR_ABRT; - } - old_cwnd = pcb->cwnd; - /* If there was any data contained within this ACK, - * we'd better pass it on to the application as well. */ - tcp_receive(pcb); - - /* Prevent ACK for SYN to generate a sent event */ - if (pcb->acked != 0) { - pcb->acked--; - } - - pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss); - - if (recv_flags & TF_GOT_FIN) { - tcp_ack_now(pcb); - pcb->state = CLOSE_WAIT; - } - } else { - /* incorrect ACK number, send RST */ - tcp_rst(ackno, seqno + tcplen, ipX_current_dest_addr(), - ipX_current_src_addr(), tcphdr->dest, tcphdr->src, ip_current_is_v6()); - } - } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) { - /* Looks like another copy of the SYN - retransmit our SYN-ACK */ - tcp_rexmit(pcb); - } - break; - case CLOSE_WAIT: - /* FALLTHROUGH */ - case ESTABLISHED: - tcp_receive(pcb); - if (recv_flags & TF_GOT_FIN) { /* passive close */ - tcp_ack_now(pcb); - pcb->state = CLOSE_WAIT; - } - break; - case FIN_WAIT_1: - tcp_receive(pcb); - if (recv_flags & TF_GOT_FIN) { - if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { - LWIP_DEBUGF(TCP_DEBUG, - ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); - tcp_ack_now(pcb); - tcp_pcb_purge(pcb); - TCP_RMV_ACTIVE(pcb); - pcb->state = TIME_WAIT; - TCP_REG(&tcp_tw_pcbs, pcb); - } else { - tcp_ack_now(pcb); - pcb->state = CLOSING; - } - } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) { - pcb->state = FIN_WAIT_2; - } - break; - case FIN_WAIT_2: - tcp_receive(pcb); - if (recv_flags & TF_GOT_FIN) { - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); - tcp_ack_now(pcb); - tcp_pcb_purge(pcb); - TCP_RMV_ACTIVE(pcb); - pcb->state = TIME_WAIT; - TCP_REG(&tcp_tw_pcbs, pcb); - } - break; - case CLOSING: - tcp_receive(pcb); - if (flags & TCP_ACK && ackno == pcb->snd_nxt) { - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); - tcp_pcb_purge(pcb); - TCP_RMV_ACTIVE(pcb); - pcb->state = TIME_WAIT; - TCP_REG(&tcp_tw_pcbs, pcb); - } - break; - case LAST_ACK: - tcp_receive(pcb); - if (flags & TCP_ACK && ackno == pcb->snd_nxt) { - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); - /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ - recv_flags |= TF_CLOSED; - } - break; - default: - break; - } - return ERR_OK; -} - -#if TCP_QUEUE_OOSEQ -/** - * Insert segment into the list (segments covered with new one will be deleted) - * - * Called from tcp_receive() - */ -static void ICACHE_FLASH_ATTR -tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next) -{ - struct tcp_seg *old_seg; - - if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { - /* received segment overlaps all following segments */ - tcp_segs_free(next); - next = NULL; - } - else { - /* delete some following segments - oos queue may have segments with FIN flag */ - while (next && - TCP_SEQ_GEQ((seqno + cseg->len), - (next->tcphdr->seqno + next->len))) { - /* cseg with FIN already processed */ - if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { - TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN); - } - old_seg = next; - next = next->next; - tcp_seg_free(old_seg); - } - if (next && - TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) { - /* We need to trim the incoming segment. */ - cseg->len = (u16_t)(next->tcphdr->seqno - seqno); - pbuf_realloc(cseg->p, cseg->len); - } - } - cseg->next = next; -} -#endif /* TCP_QUEUE_OOSEQ */ - -/** - * Called by tcp_process. Checks if the given segment is an ACK for outstanding - * data, and if so frees the memory of the buffered data. Next, is places the - * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment - * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until - * it has been removed from the buffer. - * - * If the incoming segment constitutes an ACK for a segment that was used for RTT - * estimation, the RTT is estimated here as well. - * - * Called from tcp_process(). - */ -static void ICACHE_FLASH_ATTR -tcp_receive(struct tcp_pcb *pcb) -{ - struct tcp_seg *next; -#if TCP_QUEUE_OOSEQ - struct tcp_seg *prev, *cseg; -#endif /* TCP_QUEUE_OOSEQ */ - struct pbuf *p; - s32_t off; - s16_t m; - u32_t right_wnd_edge; - u16_t new_tot_len; - int found_dupack = 0; -#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS - u32_t ooseq_blen; - u16_t ooseq_qlen; -#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ - - LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED); - - if (flags & TCP_ACK) { - right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2; - - /* Update window. */ - if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || - (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || - (pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) { - pcb->snd_wnd = tcphdr->wnd; - /* keep track of the biggest window announced by the remote host to calculate - the maximum segment size */ - if (pcb->snd_wnd_max < tcphdr->wnd) { - pcb->snd_wnd_max = tcphdr->wnd; - } - pcb->snd_wl1 = seqno; - pcb->snd_wl2 = ackno; - if (pcb->snd_wnd == 0) { - if (pcb->persist_backoff == 0) { - /* start persist timer */ - pcb->persist_cnt = 0; - pcb->persist_backoff = 1; - } - } else if (pcb->persist_backoff > 0) { - /* stop persist timer */ - pcb->persist_backoff = 0; - } - LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd)); -#if TCP_WND_DEBUG - } else { - if (pcb->snd_wnd != tcphdr->wnd) { - LWIP_DEBUGF(TCP_WND_DEBUG, - ("tcp_receive: no window update lastack %"U32_F" ackno %" - U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n", - pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); - } -#endif /* TCP_WND_DEBUG */ - } - - /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a - * duplicate ack if: - * 1) It doesn't ACK new data - * 2) length of received packet is zero (i.e. no payload) - * 3) the advertised window hasn't changed - * 4) There is outstanding unacknowledged data (retransmission timer running) - * 5) The ACK is == biggest ACK sequence number so far seen (snd_una) - * - * If it passes all five, should process as a dupack: - * a) dupacks < 3: do nothing - * b) dupacks == 3: fast retransmit - * c) dupacks > 3: increase cwnd - * - * If it only passes 1-3, should reset dupack counter (and add to - * stats, which we don't do in lwIP) - * - * If it only passes 1, should reset dupack counter - * - */ - - /* Clause 1 */ - if (TCP_SEQ_LEQ(ackno, pcb->lastack)) { - pcb->acked = 0; - /* Clause 2 */ - if (tcplen == 0) { - /* Clause 3 */ - if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){ - /* Clause 4 */ - if (pcb->rtime >= 0) { - /* Clause 5 */ - if (pcb->lastack == ackno) { - found_dupack = 1; - if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) { - ++pcb->dupacks; - } - if (pcb->dupacks > 3) { - /* Inflate the congestion window, but not if it means that - the value overflows. */ - if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { - pcb->cwnd += pcb->mss; - } - } else if (pcb->dupacks == 3) { - /* Do fast retransmit */ - tcp_rexmit_fast(pcb); - } - } - } - } - } - /* If Clause (1) or more is true, but not a duplicate ack, reset - * count of consecutive duplicate acks */ - if (!found_dupack) { - pcb->dupacks = 0; - } - } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){ - /* We come here when the ACK acknowledges new data. */ - - /* Reset the "IN Fast Retransmit" flag, since we are no longer - in fast retransmit. Also reset the congestion window to the - slow start threshold. */ - if (pcb->flags & TF_INFR) { - pcb->flags &= ~TF_INFR; - pcb->cwnd = pcb->ssthresh; - } - - /* Reset the number of retransmissions. */ - pcb->nrtx = 0; - - /* Reset the retransmission time-out. */ - pcb->rto = (pcb->sa >> 3) + pcb->sv; - - /* Update the send buffer space. Diff between the two can never exceed 64K? */ - pcb->acked = (u16_t)(ackno - pcb->lastack); - - pcb->snd_buf += pcb->acked; - - /* Reset the fast retransmit variables. */ - pcb->dupacks = 0; - pcb->lastack = ackno; - - /* Update the congestion control variables (cwnd and - ssthresh). */ - if (pcb->state >= ESTABLISHED) { - if (pcb->cwnd < pcb->ssthresh) { - if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { - pcb->cwnd += pcb->mss; - } - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"U16_F"\n", pcb->cwnd)); - } else { - u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); - if (new_cwnd > pcb->cwnd) { - pcb->cwnd = new_cwnd; - } - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"U16_F"\n", pcb->cwnd)); - } - } - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", - ackno, - pcb->unacked != NULL? - ntohl(pcb->unacked->tcphdr->seqno): 0, - pcb->unacked != NULL? - ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); - - /* Remove segment from the unacknowledged list if the incoming - ACK acknowlegdes them. */ - while (pcb->unacked != NULL && - TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) + - TCP_TCPLEN(pcb->unacked), ackno)) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", - ntohl(pcb->unacked->tcphdr->seqno), - ntohl(pcb->unacked->tcphdr->seqno) + - TCP_TCPLEN(pcb->unacked))); - - next = pcb->unacked; - pcb->unacked = pcb->unacked->next; - - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); - LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); - /* Prevent ACK for FIN to generate a sent event */ - if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { - pcb->acked--; - } - - pcb->snd_queuelen -= pbuf_clen(next->p); - tcp_seg_free(next); - - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen)); - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || - pcb->unsent != NULL); - } - } - - /* If there's nothing left to acknowledge, stop the retransmit - timer, otherwise reset it to start again */ - if(pcb->unacked == NULL) - pcb->rtime = -1; - else - pcb->rtime = 0; - - pcb->polltmr = 0; - -#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS - if (PCB_ISIPV6(pcb)) { - /* Inform neighbor reachability of forward progress. */ - nd6_reachability_hint(ip6_current_src_addr()); - } -#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ - } else { - /* Fix bug bug #21582: out of sequence ACK, didn't really ack anything */ - pcb->acked = 0; - } - - /* We go through the ->unsent list to see if any of the segments - on the list are acknowledged by the ACK. This may seem - strange since an "unsent" segment shouldn't be acked. The - rationale is that lwIP puts all outstanding segments on the - ->unsent list after a retransmission, so these segments may - in fact have been sent once. */ - while (pcb->unsent != NULL && - TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + - TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", - ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) + - TCP_TCPLEN(pcb->unsent))); - - next = pcb->unsent; - pcb->unsent = pcb->unsent->next; -#if TCP_OVERSIZE - if (pcb->unsent == NULL) { - pcb->unsent_oversize = 0; - } -#endif /* TCP_OVERSIZE */ - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); - LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); - /* Prevent ACK for FIN to generate a sent event */ - if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { - pcb->acked--; - } - pcb->snd_queuelen -= pbuf_clen(next->p); - tcp_seg_free(next); - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen)); - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_receive: valid queue length", - pcb->unacked != NULL || pcb->unsent != NULL); - } - } - /* End of ACK for new data processing. */ - - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n", - pcb->rttest, pcb->rtseq, ackno)); - - /* RTT estimation calculations. This is done by checking if the - incoming segment acknowledges the segment we use to take a - round-trip time measurement. */ - if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) { - /* diff between this shouldn't exceed 32K since this are tcp timer ticks - and a round-trip shouldn't be that long... */ - m = (s16_t)(tcp_ticks - pcb->rttest); - - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", - m, m * TCP_SLOW_INTERVAL)); - - /* This is taken directly from VJs original code in his paper */ - m = m - (pcb->sa >> 3); - pcb->sa += m; - if (m < 0) { - m = -m; - } - m = m - (pcb->sv >> 2); - pcb->sv += m; - pcb->rto = (pcb->sa >> 3) + pcb->sv; - - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n", - pcb->rto, pcb->rto * TCP_SLOW_INTERVAL)); - - pcb->rttest = 0; - } - } - - /* If the incoming segment contains data, we must process it - further unless the pcb already received a FIN. - (RFC 793, chapeter 3.9, "SEGMENT ARRIVES" in states CLOSE-WAIT, CLOSING, - LAST-ACK and TIME-WAIT: "Ignore the segment text.") */ - if ((tcplen > 0) && (pcb->state < CLOSE_WAIT)) { - /* This code basically does three things: - - +) If the incoming segment contains data that is the next - in-sequence data, this data is passed to the application. This - might involve trimming the first edge of the data. The rcv_nxt - variable and the advertised window are adjusted. - - +) If the incoming segment has data that is above the next - sequence number expected (->rcv_nxt), the segment is placed on - the ->ooseq queue. This is done by finding the appropriate - place in the ->ooseq queue (which is ordered by sequence - number) and trim the segment in both ends if needed. An - immediate ACK is sent to indicate that we received an - out-of-sequence segment. - - +) Finally, we check if the first segment on the ->ooseq queue - now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If - rcv_nxt > ooseq->seqno, we must trim the first edge of the - segment on ->ooseq before we adjust rcv_nxt. The data in the - segments that are now on sequence are chained onto the - incoming segment so that we only need to call the application - once. - */ - - /* First, we check if we must trim the first edge. We have to do - this if the sequence number of the incoming segment is less - than rcv_nxt, and the sequence number plus the length of the - segment is larger than rcv_nxt. */ - /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ - if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/ - if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)){ - /* Trimming the first edge is done by pushing the payload - pointer in the pbuf downwards. This is somewhat tricky since - we do not want to discard the full contents of the pbuf up to - the new starting point of the data since we have to keep the - TCP header which is present in the first pbuf in the chain. - - What is done is really quite a nasty hack: the first pbuf in - the pbuf chain is pointed to by inseg.p. Since we need to be - able to deallocate the whole pbuf, we cannot change this - inseg.p pointer to point to any of the later pbufs in the - chain. Instead, we point the ->payload pointer in the first - pbuf to data in one of the later pbufs. We also set the - inseg.data pointer to point to the right place. This way, the - ->p pointer will still point to the first pbuf, but the - ->p->payload pointer will point to data in another pbuf. - - After we are done with adjusting the pbuf pointers we must - adjust the ->data pointer in the seg and the segment - length.*/ - - off = pcb->rcv_nxt - seqno; - p = inseg.p; - LWIP_ASSERT("inseg.p != NULL", inseg.p); - LWIP_ASSERT("insane offset!", (off < 0x7fff)); - if (inseg.p->len < off) { - LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off)); - new_tot_len = (u16_t)(inseg.p->tot_len - off); - while (p->len < off) { - off -= p->len; - /* KJM following line changed (with addition of new_tot_len var) - to fix bug #9076 - inseg.p->tot_len -= p->len; */ - p->tot_len = new_tot_len; - p->len = 0; - p = p->next; - } - if(pbuf_header(p, (s16_t)-off)) { - /* Do we need to cope with this failing? Assert for now */ - LWIP_ASSERT("pbuf_header failed", 0); - } - } else { - if(pbuf_header(inseg.p, (s16_t)-off)) { - /* Do we need to cope with this failing? Assert for now */ - LWIP_ASSERT("pbuf_header failed", 0); - } - } - inseg.len -= (u16_t)(pcb->rcv_nxt - seqno); - inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; - } - else { - if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){ - /* the whole segment is < rcv_nxt */ - /* must be a duplicate of a packet that has already been correctly handled */ - - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); - tcp_ack_now(pcb); - } - } - - /* The sequence number must be within the window (above rcv_nxt - and below rcv_nxt + rcv_wnd) in order to be further - processed. */ - if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, - pcb->rcv_nxt + pcb->rcv_wnd - 1)){ - if (pcb->rcv_nxt == seqno) { - /* The incoming segment is the next in sequence. We check if - we have to trim the end of the segment and update rcv_nxt - and pass the data to the application. */ - tcplen = TCP_TCPLEN(&inseg); - - if (tcplen > pcb->rcv_wnd) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, - ("tcp_receive: other end overran receive window" - "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", - seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); - if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { - /* Must remove the FIN from the header as we're trimming - * that byte of sequence-space from the packet */ - TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) &~ TCP_FIN); - } - /* Adjust length of segment to fit in the window. */ - inseg.len = pcb->rcv_wnd; - if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { - inseg.len -= 1; - } - pbuf_realloc(inseg.p, inseg.len); - tcplen = TCP_TCPLEN(&inseg); - LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", - (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); - } -#if TCP_QUEUE_OOSEQ - /* Received in-sequence data, adjust ooseq data if: - - FIN has been received or - - inseq overlaps with ooseq */ - if (pcb->ooseq != NULL) { - if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, - ("tcp_receive: received in-order FIN, binning ooseq queue\n")); - /* Received in-order FIN means anything that was received - * out of order must now have been received in-order, so - * bin the ooseq queue */ - while (pcb->ooseq != NULL) { - struct tcp_seg *old_ooseq = pcb->ooseq; - pcb->ooseq = pcb->ooseq->next; - tcp_seg_free(old_ooseq); - } - } else { - next = pcb->ooseq; - /* Remove all segments on ooseq that are covered by inseg already. - * FIN is copied from ooseq to inseg if present. */ - while (next && - TCP_SEQ_GEQ(seqno + tcplen, - next->tcphdr->seqno + next->len)) { - /* inseg cannot have FIN here (already processed above) */ - if (TCPH_FLAGS(next->tcphdr) & TCP_FIN && - (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) { - TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN); - tcplen = TCP_TCPLEN(&inseg); - } - prev = next; - next = next->next; - tcp_seg_free(prev); - } - /* Now trim right side of inseg if it overlaps with the first - * segment on ooseq */ - if (next && - TCP_SEQ_GT(seqno + tcplen, - next->tcphdr->seqno)) { - /* inseg cannot have FIN here (already processed above) */ - inseg.len = (u16_t)(next->tcphdr->seqno - seqno); - if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { - inseg.len -= 1; - } - pbuf_realloc(inseg.p, inseg.len); - tcplen = TCP_TCPLEN(&inseg); - LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n", - (seqno + tcplen) == next->tcphdr->seqno); - } - pcb->ooseq = next; - } - } -#endif /* TCP_QUEUE_OOSEQ */ - - pcb->rcv_nxt = seqno + tcplen; - - /* Update the receiver's (our) window. */ - LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen); - pcb->rcv_wnd -= tcplen; - - tcp_update_rcv_ann_wnd(pcb); - - /* If there is data in the segment, we make preparations to - pass this up to the application. The ->recv_data variable - is used for holding the pbuf that goes to the - application. The code for reassembling out-of-sequence data - chains its data on this pbuf as well. - - If the segment was a FIN, we set the TF_GOT_FIN flag that will - be used to indicate to the application that the remote side has - closed its end of the connection. */ - if (inseg.p->tot_len > 0) { - recv_data = inseg.p; - /* Since this pbuf now is the responsibility of the - application, we delete our reference to it so that we won't - (mistakingly) deallocate it. */ - inseg.p = NULL; - } - if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); - recv_flags |= TF_GOT_FIN; - } - -#if TCP_QUEUE_OOSEQ - /* We now check if we have segments on the ->ooseq queue that - are now in sequence. */ - while (pcb->ooseq != NULL && - pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { - - cseg = pcb->ooseq; - seqno = pcb->ooseq->tcphdr->seqno; - - pcb->rcv_nxt += TCP_TCPLEN(cseg); - LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n", - pcb->rcv_wnd >= TCP_TCPLEN(cseg)); - pcb->rcv_wnd -= TCP_TCPLEN(cseg); - - tcp_update_rcv_ann_wnd(pcb); - - if (cseg->p->tot_len > 0) { - /* Chain this pbuf onto the pbuf that we will pass to - the application. */ - if (recv_data) { - pbuf_cat(recv_data, cseg->p); - } else { - recv_data = cseg->p; - } - cseg->p = NULL; - } - if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); - recv_flags |= TF_GOT_FIN; - if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */ - pcb->state = CLOSE_WAIT; - } - } - - pcb->ooseq = cseg->next; - tcp_seg_free(cseg); - } -#endif /* TCP_QUEUE_OOSEQ */ - - - /* Acknowledge the segment(s). */ - tcp_ack(pcb); - -#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS - if (PCB_ISIPV6(pcb)) { - /* Inform neighbor reachability of forward progress. */ - nd6_reachability_hint(ip6_current_src_addr()); - } -#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ - - } else { - /* We get here if the incoming segment is out-of-sequence. */ - tcp_send_empty_ack(pcb); -#if TCP_QUEUE_OOSEQ - /* We queue the segment on the ->ooseq queue. */ - if (pcb->ooseq == NULL) { - pcb->ooseq = tcp_seg_copy(&inseg); - } else { - /* If the queue is not empty, we walk through the queue and - try to find a place where the sequence number of the - incoming segment is between the sequence numbers of the - previous and the next segment on the ->ooseq queue. That is - the place where we put the incoming segment. If needed, we - trim the second edges of the previous and the incoming - segment so that it will fit into the sequence. - - If the incoming segment has the same sequence number as a - segment on the ->ooseq queue, we discard the segment that - contains less data. */ - - prev = NULL; - for(next = pcb->ooseq; next != NULL; next = next->next) { - if (seqno == next->tcphdr->seqno) { - /* The sequence number of the incoming segment is the - same as the sequence number of the segment on - ->ooseq. We check the lengths to see which one to - discard. */ - if (inseg.len > next->len) { - /* The incoming segment is larger than the old - segment. We replace some segments with the new - one. */ - cseg = tcp_seg_copy(&inseg); - if (cseg != NULL) { - if (prev != NULL) { - prev->next = cseg; - } else { - pcb->ooseq = cseg; - } - tcp_oos_insert_segment(cseg, next); - } - break; - } else { - /* Either the lenghts are the same or the incoming - segment was smaller than the old one; in either - case, we ditch the incoming segment. */ - break; - } - } else { - if (prev == NULL) { - if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { - /* The sequence number of the incoming segment is lower - than the sequence number of the first segment on the - queue. We put the incoming segment first on the - queue. */ - cseg = tcp_seg_copy(&inseg); - if (cseg != NULL) { - pcb->ooseq = cseg; - tcp_oos_insert_segment(cseg, next); - } - break; - } - } else { - /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && - TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ - if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) { - /* The sequence number of the incoming segment is in - between the sequence numbers of the previous and - the next segment on ->ooseq. We trim trim the previous - segment, delete next segments that included in received segment - and trim received, if needed. */ - cseg = tcp_seg_copy(&inseg); - if (cseg != NULL) { - if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { - /* We need to trim the prev segment. */ - prev->len = (u16_t)(seqno - prev->tcphdr->seqno); - pbuf_realloc(prev->p, prev->len); - } - prev->next = cseg; - tcp_oos_insert_segment(cseg, next); - } - break; - } - } - /* If the "next" segment is the last segment on the - ooseq queue, we add the incoming segment to the end - of the list. */ - if (next->next == NULL && - TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { - if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { - /* segment "next" already contains all data */ - break; - } - next->next = tcp_seg_copy(&inseg); - if (next->next != NULL) { - if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { - /* We need to trim the last segment. */ - next->len = (u16_t)(seqno - next->tcphdr->seqno); - pbuf_realloc(next->p, next->len); - } - /* check if the remote side overruns our receive window */ - if ((u32_t)tcplen + seqno > pcb->rcv_nxt + (u32_t)pcb->rcv_wnd) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, - ("tcp_receive: other end overran receive window" - "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", - seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); - if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) { - /* Must remove the FIN from the header as we're trimming - * that byte of sequence-space from the packet */ - TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) &~ TCP_FIN); - } - /* Adjust length of segment to fit in the window. */ - next->next->len = pcb->rcv_nxt + pcb->rcv_wnd - seqno; - pbuf_realloc(next->next->p, next->next->len); - tcplen = TCP_TCPLEN(next->next); - LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", - (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); - } - } - break; - } - } - prev = next; - } - } -#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS - /* Check that the data on ooseq doesn't exceed one of the limits - and throw away everything above that limit. */ - ooseq_blen = 0; - ooseq_qlen = 0; - prev = NULL; - for(next = pcb->ooseq; next != NULL; prev = next, next = next->next) { - struct pbuf *p = next->p; - ooseq_blen += p->tot_len; - ooseq_qlen += pbuf_clen(p); - if ((ooseq_blen > TCP_OOSEQ_MAX_BYTES) || - (ooseq_qlen > TCP_OOSEQ_MAX_PBUFS)) { - /* too much ooseq data, dump this and everything after it */ - tcp_segs_free(next); - if (prev == NULL) { - /* first ooseq segment is too much, dump the whole queue */ - pcb->ooseq = NULL; - } else { - /* just dump 'next' and everything after it */ - prev->next = NULL; - } - break; - } - } -#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ -#endif /* TCP_QUEUE_OOSEQ */ - } - } else { - /* The incoming segment is not withing the window. */ - tcp_send_empty_ack(pcb); - } - } else { - /* Segments with length 0 is taken care of here. Segments that - fall out of the window are ACKed. */ - /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) || - TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/ - if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){ - tcp_ack_now(pcb); - } - } -} - -/** - * Parses the options contained in the incoming segment. - * - * Called from tcp_listen_input() and tcp_process(). - * Currently, only the MSS option is supported! - * - * @param pcb the tcp_pcb for which a segment arrived - */ -static void ICACHE_FLASH_ATTR -tcp_parseopt(struct tcp_pcb *pcb) -{ - u16_t c, max_c; - u16_t mss; - u8_t *opts, opt; -#if LWIP_TCP_TIMESTAMPS - u32_t tsval; -#endif - - opts = (u8_t *)tcphdr + TCP_HLEN; - - /* Parse the TCP MSS option, if present. */ - if(TCPH_HDRLEN(tcphdr) > 0x5) { - max_c = (TCPH_HDRLEN(tcphdr) - 5) << 2; - for (c = 0; c < max_c; ) { - opt = opts[c]; - switch (opt) { - case 0x00: - /* End of options. */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n")); - return; - case 0x01: - /* NOP option. */ - ++c; - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n")); - break; - case 0x02: - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n")); - if (opts[c + 1] != 0x04 || c + 0x04 > max_c) { - /* Bad length */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); - return; - } - /* An MSS option with the right option length. */ - mss = (opts[c + 2] << 8) | opts[c + 3]; - /* Limit the mss to the configured TCP_MSS and prevent division by zero */ - pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss; - /* Advance to next option */ - c += 0x04; - break; -#if LWIP_TCP_TIMESTAMPS - case 0x08: - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n")); - if (opts[c + 1] != 0x0A || c + 0x0A > max_c) { - /* Bad length */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); - return; - } - /* TCP timestamp option with valid length */ - tsval = (opts[c+2]) | (opts[c+3] << 8) | - (opts[c+4] << 16) | (opts[c+5] << 24); - if (flags & TCP_SYN) { - pcb->ts_recent = ntohl(tsval); - pcb->flags |= TF_TIMESTAMP; - } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) { - pcb->ts_recent = ntohl(tsval); - } - /* Advance to next option */ - c += 0x0A; - break; -#endif - default: - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n")); - if (opts[c + 1] == 0) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); - /* If the length field is zero, the options are malformed - and we don't process them further. */ - return; - } - /* All other options have a length field, so that we easily - can skip past them. */ - c += opts[c + 1]; - } - } - } -} - -#endif /* LWIP_TCP */ diff --git a/third_party/lwip/core/tcp_out.c b/third_party/lwip/core/tcp_out.c deleted file mode 100644 index 4e8c9e1..0000000 --- a/third_party/lwip/core/tcp_out.c +++ /dev/null @@ -1,1499 +0,0 @@ -/** - * @file - * Transmission Control Protocol, outgoing traffic - * - * The output functions of TCP. - * - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" - -#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/tcp_impl.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/inet_chksum.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" -#if LWIP_TCP_TIMESTAMPS -#include "lwip/sys.h" -#endif - -#include - -/* Define some copy-macros for checksum-on-copy so that the code looks - nicer by preventing too many ifdef's. */ -#if TCP_CHECKSUM_ON_COPY -#define TCP_DATA_COPY(dst, src, len, seg) do { \ - tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \ - len, &seg->chksum, &seg->chksum_swapped); \ - seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0) -#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \ - tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped); -#else /* TCP_CHECKSUM_ON_COPY*/ -#define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len) -#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len) -#endif /* TCP_CHECKSUM_ON_COPY*/ - -/** Define this to 1 for an extra check that the output checksum is valid - * (usefule when the checksum is generated by the application, not the stack) */ -#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK -#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0 -#endif - -/* Forward declarations.*/ -static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb); - -/** Allocate a pbuf and create a tcphdr at p->payload, used for output - * functions other than the default tcp_output -> tcp_output_segment - * (e.g. tcp_send_empty_ack, etc.) - * - * @param pcb tcp pcb for which to send a packet (used to initialize tcp_hdr) - * @param optlen length of header-options - * @param datalen length of tcp data to reserve in pbuf - * @param seqno_be seqno in network byte order (big-endian) - * @return pbuf with p->payload being the tcp_hdr - */ -static struct pbuf * ICACHE_FLASH_ATTR -tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen, - u32_t seqno_be /* already in network byte order */) -{ - struct tcp_hdr *tcphdr; - struct pbuf *p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen + datalen, PBUF_RAM); - if (p != NULL) { - LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", - (p->len >= TCP_HLEN + optlen)); - tcphdr = (struct tcp_hdr *)p->payload; - tcphdr->src = htons(pcb->local_port); - tcphdr->dest = htons(pcb->remote_port); - tcphdr->seqno = seqno_be; - tcphdr->ackno = htonl(pcb->rcv_nxt); - TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK); - tcphdr->wnd = htons(pcb->rcv_ann_wnd); - tcphdr->chksum = 0; - tcphdr->urgp = 0; - - /* If we're sending a packet, update the announced right window edge */ - pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; - } - return p; -} - -/** - * Called by tcp_close() to send a segment including FIN flag but not data. - * - * @param pcb the tcp_pcb over which to send a segment - * @return ERR_OK if sent, another err_t otherwise - */ -err_t ICACHE_FLASH_ATTR -tcp_send_fin(struct tcp_pcb *pcb) -{ - /* first, try to add the fin to the last unsent segment */ - if (pcb->unsent != NULL) { - struct tcp_seg *last_unsent; - for (last_unsent = pcb->unsent; last_unsent->next != NULL; - last_unsent = last_unsent->next); - - if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) { - /* no SYN/FIN/RST flag in the header, we can add the FIN flag */ - TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN); - pcb->flags |= TF_FIN; - return ERR_OK; - } - } - /* no data, no length, flags, copy=1, no optdata */ - return tcp_enqueue_flags(pcb, TCP_FIN); -} - -/** - * Create a TCP segment with prefilled header. - * - * Called by tcp_write and tcp_enqueue_flags. - * - * @param pcb Protocol control block for the TCP connection. - * @param p pbuf that is used to hold the TCP header. - * @param flags TCP flags for header. - * @param seqno TCP sequence number of this packet - * @param optflags options to include in TCP header - * @return a new tcp_seg pointing to p, or NULL. - * The TCP header is filled in except ackno and wnd. - * p is freed on failure. - */ -static struct tcp_seg * ICACHE_FLASH_ATTR -tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags) -{ - struct tcp_seg *seg; - u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags); - - if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_create_segment: no memory.\n")); - pbuf_free(p); - return NULL; - } - seg->flags = optflags; - seg->next = NULL; - seg->p = p; - seg->len = p->tot_len - optlen; -#if TCP_OVERSIZE_DBGCHECK - seg->oversize_left = 0; -#endif /* TCP_OVERSIZE_DBGCHECK */ -#if TCP_CHECKSUM_ON_COPY - seg->chksum = 0; - seg->chksum_swapped = 0; - /* check optflags */ - LWIP_ASSERT("invalid optflags passed: TF_SEG_DATA_CHECKSUMMED", - (optflags & TF_SEG_DATA_CHECKSUMMED) == 0); -#endif /* TCP_CHECKSUM_ON_COPY */ - - /* build TCP header */ - if (pbuf_header(p, TCP_HLEN)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_create_segment: no room for TCP header in pbuf.\n")); - TCP_STATS_INC(tcp.err); - tcp_seg_free(seg); - return NULL; - } - seg->tcphdr = (struct tcp_hdr *)seg->p->payload; - seg->tcphdr->src = htons(pcb->local_port); - seg->tcphdr->dest = htons(pcb->remote_port); - seg->tcphdr->seqno = htonl(seqno); - /* ackno is set in tcp_output */ - TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags); - /* wnd and chksum are set in tcp_output */ - seg->tcphdr->urgp = 0; - return seg; -} - -/** - * Allocate a PBUF_RAM pbuf, perhaps with extra space at the end. - * - * This function is like pbuf_alloc(layer, length, PBUF_RAM) except - * there may be extra bytes available at the end. - * - * @param layer flag to define header size. - * @param length size of the pbuf's payload. - * @param max_length maximum usable size of payload+oversize. - * @param oversize pointer to a u16_t that will receive the number of usable tail bytes. - * @param pcb The TCP connection that willo enqueue the pbuf. - * @param apiflags API flags given to tcp_write. - * @param first_seg true when this pbuf will be used in the first enqueued segment. - * @param - */ -#if TCP_OVERSIZE -static struct pbuf * ICACHE_FLASH_ATTR -tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length, - u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags, - u8_t first_seg) -{ - struct pbuf *p; - u16_t alloc = length; - -#if LWIP_NETIF_TX_SINGLE_PBUF - LWIP_UNUSED_ARG(max_length); - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(apiflags); - LWIP_UNUSED_ARG(first_seg); - /* always create MSS-sized pbufs */ - alloc = max_length; -#else /* LWIP_NETIF_TX_SINGLE_PBUF */ - if (length < max_length) { - /* Should we allocate an oversized pbuf, or just the minimum - * length required? If tcp_write is going to be called again - * before this segment is transmitted, we want the oversized - * buffer. If the segment will be transmitted immediately, we can - * save memory by allocating only length. We use a simple - * heuristic based on the following information: - * - * Did the user set TCP_WRITE_FLAG_MORE? - * - * Will the Nagle algorithm defer transmission of this segment? - */ - if ((apiflags & TCP_WRITE_FLAG_MORE) || - (!(pcb->flags & TF_NODELAY) && - (!first_seg || - pcb->unsent != NULL || - pcb->unacked != NULL))) { - alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(length + TCP_OVERSIZE)); - } - } -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - p = pbuf_alloc(layer, alloc, PBUF_RAM); - if (p == NULL) { - return NULL; - } - LWIP_ASSERT("need unchained pbuf", p->next == NULL); - *oversize = p->len - length; - /* trim p->len to the currently used size */ - p->len = p->tot_len = length; - return p; -} -#else /* TCP_OVERSIZE */ -#define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM) -#endif /* TCP_OVERSIZE */ - -#if TCP_CHECKSUM_ON_COPY -/** Add a checksum of newly added data to the segment */ -static void ICACHE_FLASH_ATTR -tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum, - u8_t *seg_chksum_swapped) -{ - u32_t helper; - /* add chksum to old chksum and fold to u16_t */ - helper = chksum + *seg_chksum; - chksum = FOLD_U32T(helper); - if ((len & 1) != 0) { - *seg_chksum_swapped = 1 - *seg_chksum_swapped; - chksum = SWAP_BYTES_IN_WORD(chksum); - } - *seg_chksum = chksum; -} -#endif /* TCP_CHECKSUM_ON_COPY */ - -/** Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen). - * - * @param pcb the tcp pcb to check for - * @param len length of data to send (checked agains snd_buf) - * @return ERR_OK if tcp_write is allowed to proceed, another err_t otherwise - */ -static err_t ICACHE_FLASH_ATTR -tcp_write_checks(struct tcp_pcb *pcb, u16_t len) -{ - /* connection is in invalid state for data transmission? */ - if ((pcb->state != ESTABLISHED) && - (pcb->state != CLOSE_WAIT) && - (pcb->state != SYN_SENT) && - (pcb->state != SYN_RCVD)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n")); - return ERR_CONN; - } else if (len == 0) { - return ERR_OK; - } - - /* fail on too much data */ - if (len > pcb->snd_buf) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", - len, pcb->snd_buf)); - pcb->flags |= TF_NAGLEMEMERR; - return ERR_MEM; - } - - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); - - /* If total number of pbufs on the unsent/unacked queues exceeds the - * configured maximum, return an error */ - /* check for configured max queuelen and possible overflow */ - if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n", - pcb->snd_queuelen, TCP_SND_QUEUELEN)); - TCP_STATS_INC(tcp.memerr); - pcb->flags |= TF_NAGLEMEMERR; - return ERR_MEM; - } - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty", - pcb->unacked != NULL || pcb->unsent != NULL); - } else { - LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty", - pcb->unacked == NULL && pcb->unsent == NULL); - } - return ERR_OK; -} - -/** - * Write data for sending (but does not send it immediately). - * - * It waits in the expectation of more data being sent soon (as - * it can send them more efficiently by combining them together). - * To prompt the system to send data now, call tcp_output() after - * calling tcp_write(). - * - * @param pcb Protocol control block for the TCP connection to enqueue data for. - * @param arg Pointer to the data to be enqueued for sending. - * @param len Data length in bytes - * @param apiflags combination of following flags : - * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack - * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent, - * @return ERR_OK if enqueued, another err_t on error - */ -err_t ICACHE_FLASH_ATTR -tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) -{ - struct pbuf *concat_p = NULL; - struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL; - u16_t pos = 0; /* position in 'arg' data */ - u16_t queuelen; - u8_t optlen = 0; - u8_t optflags = 0; -#if TCP_OVERSIZE - u16_t oversize = 0; - u16_t oversize_used = 0; -#endif /* TCP_OVERSIZE */ -#if TCP_CHECKSUM_ON_COPY - u16_t concat_chksum = 0; - u8_t concat_chksum_swapped = 0; - u16_t concat_chksummed = 0; -#endif /* TCP_CHECKSUM_ON_COPY */ - err_t err; - /* don't allocate segments bigger than half the maximum window we ever received */ - u16_t mss_local = LWIP_MIN(pcb->mss, pcb->snd_wnd_max/2); - -#if LWIP_NETIF_TX_SINGLE_PBUF - /* Always copy to try to create single pbufs for TX */ - apiflags |= TCP_WRITE_FLAG_COPY; -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", - (void *)pcb, arg, len, (u16_t)apiflags)); - LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)", - arg != NULL, return ERR_ARG;); - - err = tcp_write_checks(pcb, len); - if (err != ERR_OK) { - return err; - } - queuelen = pcb->snd_queuelen; - -#if LWIP_TCP_TIMESTAMPS - if ((pcb->flags & TF_TIMESTAMP)) { - optflags = TF_SEG_OPTS_TS; - optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); - } -#endif /* LWIP_TCP_TIMESTAMPS */ - - - /* - * TCP segmentation is done in three phases with increasing complexity: - * - * 1. Copy data directly into an oversized pbuf. - * 2. Chain a new pbuf to the end of pcb->unsent. - * 3. Create new segments. - * - * We may run out of memory at any point. In that case we must - * return ERR_MEM and not change anything in pcb. Therefore, all - * changes are recorded in local variables and committed at the end - * of the function. Some pcb fields are maintained in local copies: - * - * queuelen = pcb->snd_queuelen - * oversize = pcb->unsent_oversize - * - * These variables are set consistently by the phases: - * - * seg points to the last segment tampered with. - * - * pos records progress as data is segmented. - */ - - /* Find the tail of the unsent queue. */ - if (pcb->unsent != NULL) { - u16_t space; - u16_t unsent_optlen; - - /* @todo: this could be sped up by keeping last_unsent in the pcb */ - for (last_unsent = pcb->unsent; last_unsent->next != NULL; - last_unsent = last_unsent->next); - - /* Usable space at the end of the last unsent segment */ - unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags); - space = mss_local - (last_unsent->len + unsent_optlen); - - /* - * Phase 1: Copy data directly into an oversized pbuf. - * - * The number of bytes copied is recorded in the oversize_used - * variable. The actual copying is done at the bottom of the - * function. - */ -#if TCP_OVERSIZE -#if TCP_OVERSIZE_DBGCHECK - /* check that pcb->unsent_oversize matches last_unsent->unsent_oversize */ - LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)", - pcb->unsent_oversize == last_unsent->oversize_left); -#endif /* TCP_OVERSIZE_DBGCHECK */ - oversize = pcb->unsent_oversize; - if (oversize > 0) { - LWIP_ASSERT("inconsistent oversize vs. space", oversize_used <= space); - seg = last_unsent; - oversize_used = oversize < len ? oversize : len; - pos += oversize_used; - oversize -= oversize_used; - space -= oversize_used; - } - /* now we are either finished or oversize is zero */ - LWIP_ASSERT("inconsistend oversize vs. len", (oversize == 0) || (pos == len)); -#endif /* TCP_OVERSIZE */ - - /* - * Phase 2: Chain a new pbuf to the end of pcb->unsent. - * - * We don't extend segments containing SYN/FIN flags or options - * (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at - * the end. - */ - if ((pos < len) && (space > 0) && (last_unsent->len > 0)) { - u16_t seglen = space < len - pos ? space : len - pos; - seg = last_unsent; - - /* Create a pbuf with a copy or reference to seglen bytes. We - * can use PBUF_RAW here since the data appears in the middle of - * a segment. A header will never be prepended. */ - if (apiflags & TCP_WRITE_FLAG_COPY) { - /* Data is copied */ - if ((concat_p = tcp_pbuf_prealloc(PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, - ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", - seglen)); - goto memerr; - } -#if TCP_OVERSIZE_DBGCHECK - last_unsent->oversize_left += oversize; -#endif /* TCP_OVERSIZE_DBGCHECK */ - TCP_DATA_COPY2(concat_p->payload, (u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped); -#if TCP_CHECKSUM_ON_COPY - concat_chksummed += seglen; -#endif /* TCP_CHECKSUM_ON_COPY */ - } else { - /* Data is not copied */ - if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, - ("tcp_write: could not allocate memory for zero-copy pbuf\n")); - goto memerr; - } -#if TCP_CHECKSUM_ON_COPY - /* calculate the checksum of nocopy-data */ - tcp_seg_add_chksum(~inet_chksum((u8_t*)arg + pos, seglen), seglen, - &concat_chksum, &concat_chksum_swapped); - concat_chksummed += seglen; -#endif /* TCP_CHECKSUM_ON_COPY */ - /* reference the non-volatile payload data */ - concat_p->payload = (u8_t*)arg + pos; - } - - pos += seglen; - queuelen += pbuf_clen(concat_p); - } - } else { -#if TCP_OVERSIZE - LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)", - pcb->unsent_oversize == 0); -#endif /* TCP_OVERSIZE */ - } - - /* - * Phase 3: Create new segments. - * - * The new segments are chained together in the local 'queue' - * variable, ready to be appended to pcb->unsent. - */ - while (pos < len) { - struct pbuf *p; - u16_t left = len - pos; - u16_t max_len = mss_local - optlen; - u16_t seglen = left > max_len ? max_len : left; -#if TCP_CHECKSUM_ON_COPY - u16_t chksum = 0; - u8_t chksum_swapped = 0; -#endif /* TCP_CHECKSUM_ON_COPY */ - - if (apiflags & TCP_WRITE_FLAG_COPY) { - /* If copy is set, memory should be allocated and data copied - * into pbuf */ - if ((p = tcp_pbuf_prealloc(PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", seglen)); - goto memerr; - } - LWIP_ASSERT("tcp_write: check that first pbuf can hold the complete seglen", - (p->len >= seglen)); - TCP_DATA_COPY2((char *)p->payload + optlen, (u8_t*)arg + pos, seglen, &chksum, &chksum_swapped); - } else { - /* Copy is not set: First allocate a pbuf for holding the data. - * Since the referenced data is available at least until it is - * sent out on the link (as it has to be ACKed by the remote - * party) we can safely use PBUF_ROM instead of PBUF_REF here. - */ - struct pbuf *p2; -#if TCP_OVERSIZE - LWIP_ASSERT("oversize == 0", oversize == 0); -#endif /* TCP_OVERSIZE */ - if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: could not allocate memory for zero-copy pbuf\n")); - goto memerr; - } -#if TCP_CHECKSUM_ON_COPY - /* calculate the checksum of nocopy-data */ - chksum = ~inet_chksum((u8_t*)arg + pos, seglen); -#endif /* TCP_CHECKSUM_ON_COPY */ - /* reference the non-volatile payload data */ - p2->payload = (u8_t*)arg + pos; - - /* Second, allocate a pbuf for the headers. */ - if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { - /* If allocation fails, we have to deallocate the data pbuf as - * well. */ - pbuf_free(p2); - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: could not allocate memory for header pbuf\n")); - goto memerr; - } - /* Concatenate the headers and data pbufs together. */ - pbuf_cat(p/*header*/, p2/*data*/); - } - - queuelen += pbuf_clen(p); - - /* Now that there are more segments queued, we check again if the - * length of the queue exceeds the configured maximum or - * overflows. */ - if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN)); - pbuf_free(p); - goto memerr; - } - - if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) { - goto memerr; - } -#if TCP_OVERSIZE_DBGCHECK - seg->oversize_left = oversize; -#endif /* TCP_OVERSIZE_DBGCHECK */ -#if TCP_CHECKSUM_ON_COPY - seg->chksum = chksum; - seg->chksum_swapped = chksum_swapped; - seg->flags |= TF_SEG_DATA_CHECKSUMMED; -#endif /* TCP_CHECKSUM_ON_COPY */ - - /* first segment of to-be-queued data? */ - if (queue == NULL) { - queue = seg; - } else { - /* Attach the segment to the end of the queued segments */ - LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL); - prev_seg->next = seg; - } - /* remember last segment of to-be-queued data for next iteration */ - prev_seg = seg; - - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n", - ntohl(seg->tcphdr->seqno), - ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg))); - - pos += seglen; - } - - /* - * All three segmentation phases were successful. We can commit the - * transaction. - */ - - /* - * Phase 1: If data has been added to the preallocated tail of - * last_unsent, we update the length fields of the pbuf chain. - */ -#if TCP_OVERSIZE - if (oversize_used > 0) { - struct pbuf *p; - /* Bump tot_len of whole chain, len of tail */ - for (p = last_unsent->p; p; p = p->next) { - p->tot_len += oversize_used; - if (p->next == NULL) { - TCP_DATA_COPY((char *)p->payload + p->len, arg, oversize_used, last_unsent); - p->len += oversize_used; - } - } - last_unsent->len += oversize_used; -#if TCP_OVERSIZE_DBGCHECK - LWIP_ASSERT("last_unsent->oversize_left >= oversize_used", - last_unsent->oversize_left >= oversize_used); - last_unsent->oversize_left -= oversize_used; -#endif /* TCP_OVERSIZE_DBGCHECK */ - } - pcb->unsent_oversize = oversize; -#endif /* TCP_OVERSIZE */ - - /* - * Phase 2: concat_p can be concatenated onto last_unsent->p - */ - if (concat_p != NULL) { - LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty", - (last_unsent != NULL)); - pbuf_cat(last_unsent->p, concat_p); - last_unsent->len += concat_p->tot_len; -#if TCP_CHECKSUM_ON_COPY - if (concat_chksummed) { - tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum, - &last_unsent->chksum_swapped); - last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED; - } -#endif /* TCP_CHECKSUM_ON_COPY */ - } - - /* - * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that - * is harmless - */ - if (last_unsent == NULL) { - pcb->unsent = queue; - } else { - last_unsent->next = queue; - } - - /* - * Finally update the pcb state. - */ - pcb->snd_lbb += len; - pcb->snd_buf -= len; - pcb->snd_queuelen = queuelen; - - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n", - pcb->snd_queuelen)); - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_write: valid queue length", - pcb->unacked != NULL || pcb->unsent != NULL); - } - - /* Set the PSH flag in the last segment that we enqueued. */ - if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) { - TCPH_SET_FLAG(seg->tcphdr, TCP_PSH); - } - - return ERR_OK; -memerr: - pcb->flags |= TF_NAGLEMEMERR; - TCP_STATS_INC(tcp.memerr); - - if (concat_p != NULL) { - pbuf_free(concat_p); - } - if (queue != NULL) { - tcp_segs_free(queue); - } - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL || - pcb->unsent != NULL); - } - LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen)); - return ERR_MEM; -} - -/** - * Enqueue TCP options for transmission. - * - * Called by tcp_connect(), tcp_listen_input(), and tcp_send_ctrl(). - * - * @param pcb Protocol control block for the TCP connection. - * @param flags TCP header flags to set in the outgoing segment. - * @param optdata pointer to TCP options, or NULL. - * @param optlen length of TCP options in bytes. - */ -err_t ICACHE_FLASH_ATTR -tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags) -{ - struct pbuf *p; - struct tcp_seg *seg; - u8_t optflags = 0; - u8_t optlen = 0; - - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); - - LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)", - (flags & (TCP_SYN | TCP_FIN)) != 0); - - /* check for configured max queuelen and possible overflow */ - if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n", - pcb->snd_queuelen, TCP_SND_QUEUELEN)); - TCP_STATS_INC(tcp.memerr); - pcb->flags |= TF_NAGLEMEMERR; - return ERR_MEM; - } - - if (flags & TCP_SYN) { - optflags = TF_SEG_OPTS_MSS; - } -#if LWIP_TCP_TIMESTAMPS - if ((pcb->flags & TF_TIMESTAMP)) { - optflags |= TF_SEG_OPTS_TS; - } -#endif /* LWIP_TCP_TIMESTAMPS */ - optlen = LWIP_TCP_OPT_LENGTH(optflags); - - /* tcp_enqueue_flags is always called with either SYN or FIN in flags. - * We need one available snd_buf byte to do that. - * This means we can't send FIN while snd_buf==0. A better fix would be to - * not include SYN and FIN sequence numbers in the snd_buf count. */ - if (pcb->snd_buf == 0) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue_flags: no send buffer available\n")); - TCP_STATS_INC(tcp.memerr); - return ERR_MEM; - } - - /* Allocate pbuf with room for TCP header + options */ - if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { - pcb->flags |= TF_NAGLEMEMERR; - TCP_STATS_INC(tcp.memerr); - return ERR_MEM; - } - LWIP_ASSERT("tcp_enqueue_flags: check that first pbuf can hold optlen", - (p->len >= optlen)); - - /* Allocate memory for tcp_seg, and fill in fields. */ - if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) { - pcb->flags |= TF_NAGLEMEMERR; - TCP_STATS_INC(tcp.memerr); - return ERR_MEM; - } - LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0); - LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0); - - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, - ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n", - ntohl(seg->tcphdr->seqno), - ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), - (u16_t)flags)); - - /* Now append seg to pcb->unsent queue */ - if (pcb->unsent == NULL) { - pcb->unsent = seg; - } else { - struct tcp_seg *useg; - for (useg = pcb->unsent; useg->next != NULL; useg = useg->next); - useg->next = seg; - } -#if TCP_OVERSIZE - /* The new unsent tail has no space */ - pcb->unsent_oversize = 0; -#endif /* TCP_OVERSIZE */ - - /* SYN and FIN bump the sequence number */ - if ((flags & TCP_SYN) || (flags & TCP_FIN)) { - pcb->snd_lbb++; - /* optlen does not influence snd_buf */ - pcb->snd_buf--; - } - if (flags & TCP_FIN) { - pcb->flags |= TF_FIN; - } - - /* update number of segments on the queues */ - pcb->snd_queuelen += pbuf_clen(seg->p); - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen)); - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_enqueue_flags: invalid queue length", - pcb->unacked != NULL || pcb->unsent != NULL); - } - - return ERR_OK; -} - -#if LWIP_TCP_TIMESTAMPS -/* Build a timestamp option (12 bytes long) at the specified options pointer) - * - * @param pcb tcp_pcb - * @param opts option pointer where to store the timestamp option - */ -static void ICACHE_FLASH_ATTR -tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts) -{ - /* Pad with two NOP options to make everything nicely aligned */ - opts[0] = PP_HTONL(0x0101080A); - opts[1] = htonl(sys_now()); - opts[2] = htonl(pcb->ts_recent); -} -#endif - -/** Send an ACK without data. - * - * @param pcb Protocol control block for the TCP connection to send the ACK - */ -err_t ICACHE_FLASH_ATTR -tcp_send_empty_ack(struct tcp_pcb *pcb) -{ - struct pbuf *p; - u8_t optlen = 0; -#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP - struct tcp_hdr *tcphdr; -#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ - -#if LWIP_TCP_TIMESTAMPS - if (pcb->flags & TF_TIMESTAMP) { - optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); - } -#endif - - p = tcp_output_alloc_header(pcb, optlen, 0, htonl(pcb->snd_nxt)); - if (p == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n")); - return ERR_BUF; - } -#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP - tcphdr = (struct tcp_hdr *)p->payload; -#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, - ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt)); - /* remove ACK flags from the PCB, as we send an empty ACK now */ - pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); - - /* NB. MSS option is only sent on SYNs, so ignore it here */ -#if LWIP_TCP_TIMESTAMPS - pcb->ts_lastacksent = pcb->rcv_nxt; - - if (pcb->flags & TF_TIMESTAMP) { - tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1)); - } -#endif - -#if CHECKSUM_GEN_TCP - tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), p, IP_PROTO_TCP, p->tot_len, - &pcb->local_ip, &pcb->remote_ip); -#endif -#if LWIP_NETIF_HWADDRHINT - ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, - IP_PROTO_TCP, &pcb->addr_hint); -#else /* LWIP_NETIF_HWADDRHINT*/ - ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, - IP_PROTO_TCP); -#endif /* LWIP_NETIF_HWADDRHINT*/ - pbuf_free(p); - - return ERR_OK; -} - -/** - * Find out what we can send and send it - * - * @param pcb Protocol control block for the TCP connection to send data - * @return ERR_OK if data has been sent or nothing to send - * another err_t on error - */ -err_t ICACHE_FLASH_ATTR -tcp_output(struct tcp_pcb *pcb) -{ - struct tcp_seg *seg, *useg; - u32_t wnd, snd_nxt; -#if TCP_CWND_DEBUG - s16_t i = 0; -#endif /* TCP_CWND_DEBUG */ - - /* pcb->state LISTEN not allowed here */ - LWIP_ASSERT("don't call tcp_output for listen-pcbs", - pcb->state != LISTEN); - - /* First, check if we are invoked by the TCP input processing - code. If so, we do not output anything. Instead, we rely on the - input processing code to call us when input processing is done - with. */ - if (tcp_input_pcb == pcb) { - return ERR_OK; - } - - wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd); - - seg = pcb->unsent; - - /* If the TF_ACK_NOW flag is set and no data will be sent (either - * because the ->unsent queue is empty or because the window does - * not allow it), construct an empty ACK segment and send it. - * - * If data is to be sent, we will just piggyback the ACK (see below). - */ - if (pcb->flags & TF_ACK_NOW && - (seg == NULL || - ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { - return tcp_send_empty_ack(pcb); - } - - /* useg should point to last segment on unacked queue */ - useg = pcb->unacked; - if (useg != NULL) { - for (; useg->next != NULL; useg = useg->next); - } - -#if TCP_OUTPUT_DEBUG - if (seg == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", - (void*)pcb->unsent)); - } -#endif /* TCP_OUTPUT_DEBUG */ -#if TCP_CWND_DEBUG - if (seg == NULL) { - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F - ", cwnd %"U16_F", wnd %"U32_F - ", seg == NULL, ack %"U32_F"\n", - pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack)); - } else { - LWIP_DEBUGF(TCP_CWND_DEBUG, - ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F - ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n", - pcb->snd_wnd, pcb->cwnd, wnd, - ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, - ntohl(seg->tcphdr->seqno), pcb->lastack)); - } -#endif /* TCP_CWND_DEBUG */ - /* data available and window allows it to be sent? */ - while (seg != NULL && - ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { - LWIP_ASSERT("RST not expected here!", - (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0); - /* Stop sending if the nagle algorithm would prevent it - * Don't stop: - * - if tcp_write had a memory error before (prevent delayed ACK timeout) or - * - if FIN was already enqueued for this PCB (SYN is always alone in a segment - - * either seg->next != NULL or pcb->unacked == NULL; - * RST is no sent using tcp_write/tcp_output. - */ - if((tcp_do_output_nagle(pcb) == 0) && - ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){ - break; - } -#if TCP_CWND_DEBUG - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U16_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n", - pcb->snd_wnd, pcb->cwnd, wnd, - ntohl(seg->tcphdr->seqno) + seg->len - - pcb->lastack, - ntohl(seg->tcphdr->seqno), pcb->lastack, i)); - ++i; -#endif /* TCP_CWND_DEBUG */ - - pcb->unsent = seg->next; - - if (pcb->state != SYN_SENT) { - TCPH_SET_FLAG(seg->tcphdr, TCP_ACK); - pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); - } - -#if TCP_OVERSIZE_DBGCHECK - seg->oversize_left = 0; -#endif /* TCP_OVERSIZE_DBGCHECK */ - tcp_output_segment(seg, pcb); - snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); - if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { - pcb->snd_nxt = snd_nxt; - } - /* put segment on unacknowledged list if length > 0 */ - if (TCP_TCPLEN(seg) > 0) { - seg->next = NULL; - /* unacked list is empty? */ - if (pcb->unacked == NULL) { - pcb->unacked = seg; - useg = seg; - /* unacked list is not empty? */ - } else { - /* In the case of fast retransmit, the packet should not go to the tail - * of the unacked queue, but rather somewhere before it. We need to check for - * this case. -STJ Jul 27, 2004 */ - if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))) { - /* add segment to before tail of unacked list, keeping the list sorted */ - struct tcp_seg **cur_seg = &(pcb->unacked); - while (*cur_seg && - TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { - cur_seg = &((*cur_seg)->next ); - } - seg->next = (*cur_seg); - (*cur_seg) = seg; - } else { - /* add segment to tail of unacked list */ - useg->next = seg; - useg = useg->next; - } - } - /* do not queue empty segments on the unacked list */ - } else { - tcp_seg_free(seg); - } - seg = pcb->unsent; - } -#if TCP_OVERSIZE - if (pcb->unsent == NULL) { - /* last unsent has been removed, reset unsent_oversize */ - pcb->unsent_oversize = 0; - } -#endif /* TCP_OVERSIZE */ - - pcb->flags &= ~TF_NAGLEMEMERR; - return ERR_OK; -} - -/** - * Called by tcp_output() to actually send a TCP segment over IP. - * - * @param seg the tcp_seg to send - * @param pcb the tcp_pcb for the TCP connection used to send the segment - */ -static void ICACHE_FLASH_ATTR -tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb) -{ - u16_t len; - u32_t *opts; - - /** @bug Exclude retransmitted segments from this count. */ - snmp_inc_tcpoutsegs(); - - /* The TCP header has already been constructed, but the ackno and - wnd fields remain. */ - seg->tcphdr->ackno = htonl(pcb->rcv_nxt); - - /* advertise our receive window size in this TCP segment */ - seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd); - - pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; - - /* Add any requested options. NB MSS option is only set on SYN - packets, so ignore it here */ - opts = (u32_t *)(void *)(seg->tcphdr + 1); - if (seg->flags & TF_SEG_OPTS_MSS) { - u16_t mss; -#if TCP_CALCULATE_EFF_SEND_MSS - mss = tcp_eff_send_mss(TCP_MSS, &pcb->local_ip, &pcb->remote_ip, PCB_ISIPV6(pcb)); -#else /* TCP_CALCULATE_EFF_SEND_MSS */ - mss = TCP_MSS; -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - *opts = TCP_BUILD_MSS_OPTION(mss); - opts += 1; - } -#if LWIP_TCP_TIMESTAMPS - pcb->ts_lastacksent = pcb->rcv_nxt; - - if (seg->flags & TF_SEG_OPTS_TS) { - tcp_build_timestamp_option(pcb, opts); - opts += 3; - } -#endif - - /* Set retransmission timer running if it is not currently enabled - This must be set before checking the route. */ - if (pcb->rtime == -1) { - pcb->rtime = 0; - } - - /* If we don't have a local IP address, we get one by - calling ip_route(). */ - if (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) { - struct netif *netif; - ipX_addr_t *local_ip; - ipX_route_get_local_ipX(PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip, netif, local_ip); - if ((netif == NULL) || (local_ip == NULL)) { - return; - } - ipX_addr_copy(PCB_ISIPV6(pcb), pcb->local_ip, *local_ip); - } - - if (pcb->rttest == 0) { - pcb->rttest = tcp_ticks; - pcb->rtseq = ntohl(seg->tcphdr->seqno); - - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); - } - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", - htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) + - seg->len)); - - len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload); - - seg->p->len -= len; - seg->p->tot_len -= len; - - seg->p->payload = seg->tcphdr; - - seg->tcphdr->chksum = 0; -#if TCP_CHECKSUM_ON_COPY - { - u32_t acc; -#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK - u16_t chksum_slow = ipX_chksum_pseudo(PCB_ISIPV6(pcb), seg->p, IP_PROTO_TCP, - seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); -#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ - if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) { - LWIP_ASSERT("data included but not checksummed", - seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4)); - } - - /* rebuild TCP header checksum (TCP header changes for retransmissions!) */ - acc = ipX_chksum_pseudo_partial(PCB_ISIPV6(pcb), seg->p, IP_PROTO_TCP, - seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4, &pcb->local_ip, &pcb->remote_ip); - /* add payload checksum */ - if (seg->chksum_swapped) { - seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum); - seg->chksum_swapped = 0; - } - acc += (u16_t)~(seg->chksum); - seg->tcphdr->chksum = FOLD_U32T(acc); -#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK - if (chksum_slow != seg->tcphdr->chksum) { - LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, - ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n", - seg->tcphdr->chksum, chksum_slow)); - seg->tcphdr->chksum = chksum_slow; - } -#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ - } -#else /* TCP_CHECKSUM_ON_COPY */ -#if CHECKSUM_GEN_TCP - seg->tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), seg->p, IP_PROTO_TCP, - seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); -#endif /* CHECKSUM_GEN_TCP */ -#endif /* TCP_CHECKSUM_ON_COPY */ - TCP_STATS_INC(tcp.xmit); - -#if LWIP_NETIF_HWADDRHINT - ipX_output_hinted(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip, - pcb->ttl, pcb->tos, IP_PROTO_TCP, &pcb->addr_hint); -#else /* LWIP_NETIF_HWADDRHINT*/ - ipX_output(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, - pcb->tos, IP_PROTO_TCP); -#endif /* LWIP_NETIF_HWADDRHINT*/ -} - -/** - * Send a TCP RESET packet (empty segment with RST flag set) either to - * abort a connection or to show that there is no matching local connection - * for a received segment. - * - * Called by tcp_abort() (to abort a local connection), tcp_input() (if no - * matching local pcb was found), tcp_listen_input() (if incoming segment - * has ACK flag set) and tcp_process() (received segment in the wrong state) - * - * Since a RST segment is in most cases not sent for an active connection, - * tcp_rst() has a number of arguments that are taken from a tcp_pcb for - * most other segment output functions. - * - * @param seqno the sequence number to use for the outgoing segment - * @param ackno the acknowledge number to use for the outgoing segment - * @param local_ip the local IP address to send the segment from - * @param remote_ip the remote IP address to send the segment to - * @param local_port the local TCP port to send the segment from - * @param remote_port the remote TCP port to send the segment to - */ -void ICACHE_FLASH_ATTR -tcp_rst_impl(u32_t seqno, u32_t ackno, - ipX_addr_t *local_ip, ipX_addr_t *remote_ip, - u16_t local_port, u16_t remote_port -#if LWIP_IPV6 - , u8_t isipv6 -#endif /* LWIP_IPV6 */ - ) -{ - struct pbuf *p; - struct tcp_hdr *tcphdr; - p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); - if (p == NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); - return; - } - LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", - (p->len >= sizeof(struct tcp_hdr))); - - tcphdr = (struct tcp_hdr *)p->payload; - tcphdr->src = htons(local_port); - tcphdr->dest = htons(remote_port); - tcphdr->seqno = htonl(seqno); - tcphdr->ackno = htonl(ackno); - TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK); - tcphdr->wnd = PP_HTONS(TCP_WND); - tcphdr->chksum = 0; - tcphdr->urgp = 0; - - TCP_STATS_INC(tcp.xmit); - snmp_inc_tcpoutrsts(); - -#if CHECKSUM_GEN_TCP - tcphdr->chksum = ipX_chksum_pseudo(isipv6, p, IP_PROTO_TCP, p->tot_len, - local_ip, remote_ip); -#endif - /* Send output with hardcoded TTL/HL since we have no access to the pcb */ - ipX_output(isipv6, p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP); - pbuf_free(p); - LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno)); -} - -/** - * Requeue all unacked segments for retransmission - * - * Called by tcp_slowtmr() for slow retransmission. - * - * @param pcb the tcp_pcb for which to re-enqueue all unacked segments - */ -void ICACHE_FLASH_ATTR -tcp_rexmit_rto(struct tcp_pcb *pcb) -{ - struct tcp_seg *seg; - - if (pcb->unacked == NULL) { - return; - } - - /* Move all unacked segments to the head of the unsent queue */ - for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); - /* concatenate unsent queue after unacked queue */ - seg->next = pcb->unsent; - /* unsent queue is the concatenated queue (of unacked, unsent) */ - pcb->unsent = pcb->unacked; - /* unacked queue is now empty */ - pcb->unacked = NULL; - /* last unsent hasn't changed, no need to reset unsent_oversize */ - - /* increment number of retransmissions */ - ++pcb->nrtx; - - /* Don't take any RTT measurements after retransmitting. */ - pcb->rttest = 0; - - /* Do the actual retransmission */ - tcp_output(pcb); -} - -/** - * Requeue the first unacked segment for retransmission - * - * Called by tcp_receive() for fast retramsmit. - * - * @param pcb the tcp_pcb for which to retransmit the first unacked segment - */ -void ICACHE_FLASH_ATTR -tcp_rexmit(struct tcp_pcb *pcb) -{ - struct tcp_seg *seg; - struct tcp_seg **cur_seg; - - if (pcb->unacked == NULL) { - return; - } - - /* Move the first unacked segment to the unsent queue */ - /* Keep the unsent queue sorted. */ - seg = pcb->unacked; - pcb->unacked = seg->next; - - cur_seg = &(pcb->unsent); - while (*cur_seg && - TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) { - cur_seg = &((*cur_seg)->next ); - } - seg->next = *cur_seg; - *cur_seg = seg; -#if TCP_OVERSIZE - if (seg->next == NULL) { - /* the retransmitted segment is last in unsent, so reset unsent_oversize */ - pcb->unsent_oversize = 0; - } -#endif /* TCP_OVERSIZE */ - - ++pcb->nrtx; - - /* Don't take any rtt measurements after retransmitting. */ - pcb->rttest = 0; - - /* Do the actual retransmission. */ - snmp_inc_tcpretranssegs(); - /* No need to call tcp_output: we are always called from tcp_input() - and thus tcp_output directly returns. */ -} - - -/** - * Handle retransmission after three dupacks received - * - * @param pcb the tcp_pcb for which to retransmit the first unacked segment - */ -void ICACHE_FLASH_ATTR -tcp_rexmit_fast(struct tcp_pcb *pcb) -{ - if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) { - /* This is fast retransmit. Retransmit the first unacked segment. */ - LWIP_DEBUGF(TCP_FR_DEBUG, - ("tcp_receive: dupacks %"U16_F" (%"U32_F - "), fast retransmit %"U32_F"\n", - (u16_t)pcb->dupacks, pcb->lastack, - ntohl(pcb->unacked->tcphdr->seqno))); - tcp_rexmit(pcb); - - /* Set ssthresh to half of the minimum of the current - * cwnd and the advertised window */ - if (pcb->cwnd > pcb->snd_wnd) { - pcb->ssthresh = pcb->snd_wnd / 2; - } else { - pcb->ssthresh = pcb->cwnd / 2; - } - - /* The minimum value for ssthresh should be 2 MSS */ - if (pcb->ssthresh < 2*pcb->mss) { - LWIP_DEBUGF(TCP_FR_DEBUG, - ("tcp_receive: The minimum value for ssthresh %"U16_F - " should be min 2 mss %"U16_F"...\n", - pcb->ssthresh, 2*pcb->mss)); - pcb->ssthresh = 2*pcb->mss; - } - - pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; - pcb->flags |= TF_INFR; - } -} - - -/** - * Send keepalive packets to keep a connection active although - * no data is sent over it. - * - * Called by tcp_slowtmr() - * - * @param pcb the tcp_pcb for which to send a keepalive packet - */ -void ICACHE_FLASH_ATTR -tcp_keepalive(struct tcp_pcb *pcb) -{ - struct pbuf *p; -#if CHECKSUM_GEN_TCP - struct tcp_hdr *tcphdr; -#endif /* CHECKSUM_GEN_TCP */ - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to ")); - ipX_addr_debug_print(PCB_ISIPV6(pcb), TCP_DEBUG, &pcb->remote_ip); - LWIP_DEBUGF(TCP_DEBUG, ("\n")); - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", - tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); - - p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1)); - if(p == NULL) { - LWIP_DEBUGF(TCP_DEBUG, - ("tcp_keepalive: could not allocate memory for pbuf\n")); - return; - } -#if CHECKSUM_GEN_TCP - tcphdr = (struct tcp_hdr *)p->payload; - - tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), p, IP_PROTO_TCP, p->tot_len, - &pcb->local_ip, &pcb->remote_ip); -#endif /* CHECKSUM_GEN_TCP */ - TCP_STATS_INC(tcp.xmit); - - /* Send output to IP */ -#if LWIP_NETIF_HWADDRHINT - ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, - pcb->ttl, 0, IP_PROTO_TCP, &pcb->addr_hint); -#else /* LWIP_NETIF_HWADDRHINT*/ - ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, - 0, IP_PROTO_TCP); -#endif /* LWIP_NETIF_HWADDRHINT*/ - - pbuf_free(p); - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", - pcb->snd_nxt - 1, pcb->rcv_nxt)); -} - - -/** - * Send persist timer zero-window probes to keep a connection active - * when a window update is lost. - * - * Called by tcp_slowtmr() - * - * @param pcb the tcp_pcb for which to send a zero-window probe packet - */ -void ICACHE_FLASH_ATTR -tcp_zero_window_probe(struct tcp_pcb *pcb) -{ - struct pbuf *p; - struct tcp_hdr *tcphdr; - struct tcp_seg *seg; - u16_t len; - u8_t is_fin; - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to ")); - ipX_addr_debug_print(PCB_ISIPV6(pcb), TCP_DEBUG, &pcb->remote_ip); - LWIP_DEBUGF(TCP_DEBUG, ("\n")); - - LWIP_DEBUGF(TCP_DEBUG, - ("tcp_zero_window_probe: tcp_ticks %"U32_F - " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", - tcp_ticks, pcb->tmr, pcb->keep_cnt_sent)); - - seg = pcb->unacked; - - if(seg == NULL) { - seg = pcb->unsent; - } - if(seg == NULL) { - return; - } - - is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0); - /* we want to send one seqno: either FIN or data (no options) */ - len = is_fin ? 0 : 1; - - p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno); - if(p == NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n")); - return; - } - tcphdr = (struct tcp_hdr *)p->payload; - - if (is_fin) { - /* FIN segment, no data */ - TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN); - } else { - /* Data segment, copy in one byte from the head of the unacked queue */ - char *d = ((char *)p->payload + TCP_HLEN); - /* Depending on whether the segment has already been sent (unacked) or not - (unsent), seg->p->payload points to the IP header or TCP header. - Ensure we copy the first TCP data byte: */ - pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len); - } - -#if CHECKSUM_GEN_TCP - tcphdr->chksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), p, IP_PROTO_TCP, p->tot_len, - &pcb->local_ip, &pcb->remote_ip); -#endif - TCP_STATS_INC(tcp.xmit); - - /* Send output to IP */ -#if LWIP_NETIF_HWADDRHINT - ipX_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, - 0, IP_PROTO_TCP, &pcb->addr_hint); -#else /* LWIP_NETIF_HWADDRHINT*/ - ipX_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP); -#endif /* LWIP_NETIF_HWADDRHINT*/ - - pbuf_free(p); - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F - " ackno %"U32_F".\n", - pcb->snd_nxt - 1, pcb->rcv_nxt)); -} -#endif /* LWIP_TCP */ diff --git a/third_party/lwip/core/timers.c b/third_party/lwip/core/timers.c deleted file mode 100644 index 6f751cc..0000000 --- a/third_party/lwip/core/timers.c +++ /dev/null @@ -1,547 +0,0 @@ -/** - * @file - * Stack-internal timers implementation. - * This file includes timer callbacks for stack-internal timers as well as - * functions to set up or stop timers and check for expired timers. - * - */ - -/* - * 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 - * Simon Goldschmidt - * - */ - -#include "lwip/opt.h" - -#include "lwip/timers.h" -#include "lwip/tcp_impl.h" - -#if LWIP_TIMERS - -#include "lwip/def.h" -#include "lwip/memp.h" -#include "lwip/tcpip.h" - -#include "lwip/ip_frag.h" -#include "netif/etharp.h" -#include "lwip/dhcp.h" -#include "lwip/autoip.h" -#include "lwip/igmp.h" -#include "lwip/dns.h" -#include "lwip/nd6.h" -#include "lwip/ip6_frag.h" -#include "lwip/mld6.h" -#include "lwip/sys.h" -#include "lwip/pbuf.h" - -/** The one and only timeout list */ -static struct sys_timeo *next_timeout; -#if NO_SYS -static u32_t timeouts_last_time; -#endif /* NO_SYS */ - -#if LWIP_TCP -/** global variable that shows if the tcp timer is currently scheduled or not */ -static int tcpip_tcp_timer_active; - -/** - * Timer callback function that calls tcp_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void ICACHE_FLASH_ATTR -tcpip_tcp_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - - /* call TCP timer handler */ - tcp_tmr(); - /* timer still needed? */ - if (tcp_active_pcbs || tcp_tw_pcbs) { - /* restart timer */ - sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); - } else { - /* disable timer */ - tcpip_tcp_timer_active = 0; - } -} - -/** - * Called from TCP_REG when registering a new PCB: - * the reason is to have the TCP timer only running when - * there are active (or time-wait) PCBs. - */ -void ICACHE_FLASH_ATTR -tcp_timer_needed(void) -{ - /* timer is off but needed again? */ - if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { - /* enable and start timer */ - tcpip_tcp_timer_active = 1; - sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); - } -} -#endif /* LWIP_TCP */ - -#if IP_REASSEMBLY -/** - * Timer callback function that calls ip_reass_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void ICACHE_FLASH_ATTR -ip_reass_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip_reass_tmr()\n")); - ip_reass_tmr(); - sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); -} -#endif /* IP_REASSEMBLY */ - -#if LWIP_ARP -/** - * Timer callback function that calls etharp_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void ICACHE_FLASH_ATTR -arp_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: etharp_tmr()\n")); - etharp_tmr(); - sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); -} -#endif /* LWIP_ARP */ - -#if LWIP_DHCP -/** - * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void ICACHE_FLASH_ATTR -dhcp_timer_coarse(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_coarse_tmr()\n")); - dhcp_coarse_tmr(); - sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); -} - -/** - * Timer callback function that calls dhcp_fine_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void ICACHE_FLASH_ATTR -dhcp_timer_fine(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_fine_tmr()\n")); - dhcp_fine_tmr(); - sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); -} -#endif /* LWIP_DHCP */ - -#if LWIP_AUTOIP -/** - * Timer callback function that calls autoip_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void ICACHE_FLASH_ATTR -autoip_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: autoip_tmr()\n")); - autoip_tmr(); - sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); -} -#endif /* LWIP_AUTOIP */ - -#if LWIP_IGMP -/** - * Timer callback function that calls igmp_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void ICACHE_FLASH_ATTR -igmp_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: igmp_tmr()\n")); - igmp_tmr(); - sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); -} -#endif /* LWIP_IGMP */ - -#if LWIP_DNS -/** - * Timer callback function that calls dns_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void ICACHE_FLASH_ATTR -dns_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dns_tmr()\n")); - dns_tmr(); - sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); -} -#endif /* LWIP_DNS */ - -#if LWIP_IPV6 -/** - * Timer callback function that calls nd6_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void ICACHE_FLASH_ATTR -nd6_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: nd6_tmr()\n")); - nd6_tmr(); - sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL); -} - -#if LWIP_IPV6_REASS -/** - * Timer callback function that calls ip6_reass_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void ICACHE_FLASH_ATTR -ip6_reass_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip6_reass_tmr()\n")); - ip6_reass_tmr(); - sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL); -} -#endif /* LWIP_IPV6_REASS */ - -#if LWIP_IPV6_MLD -/** - * Timer callback function that calls mld6_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void ICACHE_FLASH_ATTR -mld6_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: mld6_tmr()\n")); - mld6_tmr(); - sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL); -} -#endif /* LWIP_IPV6_MLD */ -#endif /* LWIP_IPV6 */ - -/** Initialize this module */ -void ICACHE_FLASH_ATTR -sys_timeouts_init(void) -{ -#if IP_REASSEMBLY - sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); -#endif /* IP_REASSEMBLY */ -#if LWIP_ARP - sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); -#endif /* LWIP_ARP */ -#if LWIP_DHCP - sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); - sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); -#endif /* LWIP_DHCP */ -#if LWIP_AUTOIP - sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); -#endif /* LWIP_AUTOIP */ -#if LWIP_IGMP - sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); -#endif /* LWIP_IGMP */ -#if LWIP_DNS - sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); -#endif /* LWIP_DNS */ -#if LWIP_IPV6 - sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL); -#if LWIP_IPV6_REASS - sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL); -#endif /* LWIP_IPV6_REASS */ -#if LWIP_IPV6_MLD - sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL); -#endif /* LWIP_IPV6_MLD */ -#endif /* LWIP_IPV6 */ - -#if NO_SYS - /* Initialise timestamp for sys_check_timeouts */ - timeouts_last_time = sys_now(); -#endif -} - -/** - * Create a one-shot timer (aka timeout). Timeouts are processed in the - * following cases: - * - while waiting for a message using sys_timeouts_mbox_fetch() - * - by calling sys_check_timeouts() (NO_SYS==1 only) - * - * @param msecs time in milliseconds after that the timer should expire - * @param handler callback function to call when msecs have elapsed - * @param arg argument to pass to the callback function - */ -#if LWIP_DEBUG_TIMERNAMES -void ICACHE_FLASH_ATTR -sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name) -#else /* LWIP_DEBUG_TIMERNAMES */ -void ICACHE_FLASH_ATTR -sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg) -#endif /* LWIP_DEBUG_TIMERNAMES */ -{ - struct sys_timeo *timeout, *t; - - timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT); - if (timeout == NULL) { - LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL); - return; - } - timeout->next = NULL; - timeout->h = handler; - timeout->arg = arg; - timeout->time = msecs; -#if LWIP_DEBUG_TIMERNAMES - timeout->handler_name = handler_name; - LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n", - (void *)timeout, msecs, handler_name, (void *)arg)); -#endif /* LWIP_DEBUG_TIMERNAMES */ - - if (next_timeout == NULL) { - next_timeout = timeout; - return; - } - - if (next_timeout->time > msecs) { - next_timeout->time -= msecs; - timeout->next = next_timeout; - next_timeout = timeout; - } else { - for(t = next_timeout; t != NULL; t = t->next) { - timeout->time -= t->time; - if (t->next == NULL || t->next->time > timeout->time) { - if (t->next != NULL) { - t->next->time -= timeout->time; - } - timeout->next = t->next; - t->next = timeout; - break; - } - } - } -} - -/** - * Go through timeout list (for this task only) and remove the first matching - * entry, even though the timeout has not triggered yet. - * - * @note This function only works as expected if there is only one timeout - * calling 'handler' in the list of timeouts. - * - * @param handler callback function that would be called by the timeout - * @param arg callback argument that would be passed to handler -*/ -void ICACHE_FLASH_ATTR -sys_untimeout(sys_timeout_handler handler, void *arg) -{ - struct sys_timeo *prev_t, *t; - - if (next_timeout == NULL) { - return; - } - - for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { - if ((t->h == handler) && (t->arg == arg)) { - /* We have a match */ - /* Unlink from previous in list */ - if (prev_t == NULL) { - next_timeout = t->next; - } else { - prev_t->next = t->next; - } - /* If not the last one, add time of this one back to next */ - if (t->next != NULL) { - t->next->time += t->time; - } - memp_free(MEMP_SYS_TIMEOUT, t); - return; - } - } - return; -} - -#if NO_SYS - -/** Handle timeouts for NO_SYS==1 (i.e. without using - * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout - * handler functions when timeouts expire. - * - * Must be called periodically from your main loop. - */ -void ICACHE_FLASH_ATTR -sys_check_timeouts(void) -{ - if (next_timeout) { - struct sys_timeo *tmptimeout; - u32_t diff; - sys_timeout_handler handler; - void *arg; - u8_t had_one; - u32_t now; - - now = sys_now(); - /* this cares for wraparounds */ - diff = now - timeouts_last_time; - do - { -#if PBUF_POOL_FREE_OOSEQ - PBUF_CHECK_FREE_OOSEQ(); -#endif /* PBUF_POOL_FREE_OOSEQ */ - had_one = 0; - tmptimeout = next_timeout; - if (tmptimeout && (tmptimeout->time <= diff)) { - /* timeout has expired */ - had_one = 1; - timeouts_last_time = now; - diff -= tmptimeout->time; - next_timeout = tmptimeout->next; - handler = tmptimeout->h; - arg = tmptimeout->arg; -#if LWIP_DEBUG_TIMERNAMES - if (handler != NULL) { - LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n", - tmptimeout->handler_name, arg)); - } -#endif /* LWIP_DEBUG_TIMERNAMES */ - memp_free(MEMP_SYS_TIMEOUT, tmptimeout); - if (handler != NULL) { - handler(arg); - } - } - /* repeat until all expired timers have been called */ - }while(had_one); - } -} - -/** Set back the timestamp of the last call to sys_check_timeouts() - * This is necessary if sys_check_timeouts() hasn't been called for a long - * time (e.g. while saving energy) to prevent all timer functions of that - * period being called. - */ -void ICACHE_FLASH_ATTR -sys_restart_timeouts(void) -{ - timeouts_last_time = sys_now(); -} - -#else /* NO_SYS */ - -/** - * Wait (forever) for a message to arrive in an mbox. - * While waiting, timeouts are processed. - * - * @param mbox the mbox to fetch the message from - * @param msg the place to store the message - */ -void ICACHE_FLASH_ATTR -sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg) -{ - u32_t time_needed; - struct sys_timeo *tmptimeout; - sys_timeout_handler handler; - void *arg; - - again: - if (!next_timeout) { - time_needed = sys_arch_mbox_fetch(mbox, msg, 0); - } else { - if (next_timeout->time > 0) { - time_needed = sys_arch_mbox_fetch(mbox, msg, next_timeout->time); - } else { - time_needed = SYS_ARCH_TIMEOUT; - } - - if (time_needed == SYS_ARCH_TIMEOUT) { - /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message - could be fetched. We should now call the timeout handler and - deallocate the memory allocated for the timeout. */ - tmptimeout = next_timeout; - next_timeout = tmptimeout->next; - handler = tmptimeout->h; - arg = tmptimeout->arg; -#if LWIP_DEBUG_TIMERNAMES - if (handler != NULL) { - LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n", - tmptimeout->handler_name, arg)); - } -#endif /* LWIP_DEBUG_TIMERNAMES */ - memp_free(MEMP_SYS_TIMEOUT, tmptimeout); - if (handler != NULL) { - /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the - timeout handler function. */ - LOCK_TCPIP_CORE(); - handler(arg); - UNLOCK_TCPIP_CORE(); - } - LWIP_TCPIP_THREAD_ALIVE(); - - /* We try again to fetch a message from the mbox. */ - goto again; - } else { - /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout - occured. The time variable is set to the number of - milliseconds we waited for the message. */ - if (time_needed < next_timeout->time) { - next_timeout->time -= time_needed; - } else { - next_timeout->time = 0; - } - } - } -} - -#endif /* NO_SYS */ - -#else /* LWIP_TIMERS */ -/* Satisfy the TCP code which calls this function */ -void ICACHE_FLASH_ATTR -tcp_timer_needed(void) -{ -} -#endif /* LWIP_TIMERS */ diff --git a/third_party/lwip/core/udp.c b/third_party/lwip/core/udp.c deleted file mode 100644 index 4655c08..0000000 --- a/third_party/lwip/core/udp.c +++ /dev/null @@ -1,1151 +0,0 @@ -/** - * @file - * User Datagram Protocol module - * - */ - -/* - * 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 - * - */ - - -/* udp.c - * - * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828). - * - */ - -/* @todo Check the use of '(struct udp_pcb).chksum_len_rx'! - */ - -#include "lwip/opt.h" - -#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/udp.h" -#include "lwip/def.h" -#include "lwip/memp.h" -#include "lwip/inet_chksum.h" -#include "lwip/ip_addr.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/icmp.h" -#include "lwip/icmp6.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "arch/perf.h" -#include "lwip/dhcp.h" - -#include - -#ifndef UDP_LOCAL_PORT_RANGE_START -/* From http://www.iana.org/assignments/port-numbers: - "The Dynamic and/or Private Ports are those from 49152 through 65535" */ -#define UDP_LOCAL_PORT_RANGE_START 0xc000 -#define UDP_LOCAL_PORT_RANGE_END 0xffff -#define UDP_ENSURE_LOCAL_PORT_RANGE(port) (((port) & ~UDP_LOCAL_PORT_RANGE_START) + UDP_LOCAL_PORT_RANGE_START) -#endif - -/* last local UDP port */ -static u16_t udp_port = UDP_LOCAL_PORT_RANGE_START; - -/* The list of UDP PCBs */ -/* exported in udp.h (was static) */ -struct udp_pcb *udp_pcbs; - -/** - * Initialize this module. - */ -void ICACHE_FLASH_ATTR -udp_init(void) -{ -#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) - udp_port = UDP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); -#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ -} - -/** - * Allocate a new local UDP port. - * - * @return a new (free) local UDP port number - */ -static u16_t ICACHE_FLASH_ATTR -udp_new_port(void) -{ - u16_t n = 0; - struct udp_pcb *pcb; - -again: - if (udp_port++ == UDP_LOCAL_PORT_RANGE_END) { - udp_port = UDP_LOCAL_PORT_RANGE_START; - } - /* Check all PCBs. */ - for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { - if (pcb->local_port == udp_port) { - if (++n > (UDP_LOCAL_PORT_RANGE_END - UDP_LOCAL_PORT_RANGE_START)) { - return 0; - } - goto again; - } - } - return udp_port; -#if 0 - struct udp_pcb *ipcb = udp_pcbs; - while ((ipcb != NULL) && (udp_port != UDP_LOCAL_PORT_RANGE_END)) { - if (ipcb->local_port == udp_port) { - /* port is already used by another udp_pcb */ - udp_port++; - /* restart scanning all udp pcbs */ - ipcb = udp_pcbs; - } else { - /* go on with next udp pcb */ - ipcb = ipcb->next; - } - } - if (ipcb != NULL) { - return 0; - } - return udp_port; -#endif -} - -/** - * Process an incoming UDP datagram. - * - * Given an incoming UDP datagram (as a chain of pbufs) this function - * finds a corresponding UDP PCB and hands over the pbuf to the pcbs - * recv function. If no pcb is found or the datagram is incorrect, the - * pbuf is freed. - * - * @param p pbuf to be demultiplexed to a UDP PCB (p->payload pointing to the UDP header) - * @param inp network interface on which the datagram was received. - * - */ -void ICACHE_FLASH_ATTR -udp_input(struct pbuf *p, struct netif *inp) -{ - struct udp_hdr *udphdr; - struct udp_pcb *pcb, *prev; - struct udp_pcb *uncon_pcb; - u16_t src, dest; - u8_t local_match; - u8_t broadcast; - u8_t for_us; - - PERF_START; - - UDP_STATS_INC(udp.recv); - - /* Check minimum length (UDP header) */ - if (p->len < UDP_HLEN) { - /* drop short packets */ - LWIP_DEBUGF(UDP_DEBUG, - ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len)); - UDP_STATS_INC(udp.lenerr); - UDP_STATS_INC(udp.drop); - snmp_inc_udpinerrors(); - pbuf_free(p); - goto end; - } - - udphdr = (struct udp_hdr *)p->payload; - - /* is broadcast packet ? */ -#if LWIP_IPV6 - broadcast = !ip_current_is_v6() && ip_addr_isbroadcast(ip_current_dest_addr(), inp); -#else /* LWIP_IPV6 */ - broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), inp); -#endif /* LWIP_IPV6 */ - - LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len)); - - /* convert src and dest ports to host byte order */ - src = ntohs(udphdr->src); - dest = ntohs(udphdr->dest); - - udp_debug_print(udphdr); - - /* print the UDP source and destination */ - LWIP_DEBUGF(UDP_DEBUG, ("udp (")); - ipX_addr_debug_print(ip_current_is_v6(), UDP_DEBUG, ipX_current_dest_addr()); - LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", ntohs(udphdr->dest))); - ipX_addr_debug_print(ip_current_is_v6(), UDP_DEBUG, ipX_current_src_addr()); - LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", ntohs(udphdr->src))); - -#if LWIP_DHCP - pcb = NULL; - /* when LWIP_DHCP is active, packets to DHCP_CLIENT_PORT may only be processed by - the dhcp module, no other UDP pcb may use the local UDP port DHCP_CLIENT_PORT */ - if (dest == DHCP_CLIENT_PORT) { - /* all packets for DHCP_CLIENT_PORT not coming from DHCP_SERVER_PORT are dropped! */ - if (src == DHCP_SERVER_PORT) { - if ((inp->dhcp != NULL) && (inp->dhcp->pcb != NULL)) { - /* accept the packe if - (- broadcast or directed to us) -> DHCP is link-layer-addressed, local ip is always ANY! - - inp->dhcp->pcb->remote == ANY or iphdr->src - (no need to check for IPv6 since the dhcp struct always uses IPv4) */ - if (ipX_addr_isany(0, &inp->dhcp->pcb->remote_ip) || - ip_addr_cmp(ipX_2_ip(&(inp->dhcp->pcb->remote_ip)), ip_current_src_addr())) { - pcb = inp->dhcp->pcb; - } - } - } - } else -#endif /* LWIP_DHCP */ - { - prev = NULL; - local_match = 0; - uncon_pcb = NULL; - /* Iterate through the UDP pcb list for a matching pcb. - * 'Perfect match' pcbs (connected to the remote port & ip address) are - * preferred. If no perfect match is found, the first unconnected pcb that - * matches the local port and ip address gets the datagram. */ - for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { - local_match = 0; - /* print the PCB local and remote address */ - LWIP_DEBUGF(UDP_DEBUG, ("pcb (")); - ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG, &pcb->local_ip); - LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", pcb->local_port)); - ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG, &pcb->remote_ip); - LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", pcb->remote_port)); - - /* compare PCB local addr+port to UDP destination addr+port */ - if (pcb->local_port == dest) { - if ( -#if LWIP_IPV6 - ((PCB_ISIPV6(pcb) && (ip_current_is_v6()) && - (ip6_addr_isany(ipX_2_ip6(&pcb->local_ip)) || -#if LWIP_IPV6_MLD - ip6_addr_ismulticast(ip6_current_dest_addr()) || -#endif /* LWIP_IPV6_MLD */ - ip6_addr_cmp(ipX_2_ip6(&pcb->local_ip), ip6_current_dest_addr()))) || - (!PCB_ISIPV6(pcb) && - (ip_current_header() != NULL) && -#else /* LWIP_IPV6 */ - (( -#endif /* LWIP_IPV6 */ - ((!broadcast && ipX_addr_isany(0, &pcb->local_ip)) || - ip_addr_cmp(ipX_2_ip(&pcb->local_ip), ip_current_dest_addr()) || -#if LWIP_IGMP - ip_addr_ismulticast(ip_current_dest_addr()) || -#endif /* LWIP_IGMP */ -#if IP_SOF_BROADCAST_RECV - (broadcast && ip_get_option(pcb, SOF_BROADCAST) && - (ipX_addr_isany(0, &pcb->local_ip) || - ip_addr_netcmp(ipX_2_ip(&pcb->local_ip), ip_current_dest_addr(), &inp->netmask))))))) { -#else /* IP_SOF_BROADCAST_RECV */ - (broadcast && - (ipX_addr_isany(0, &pcb->local_ip) || - ip_addr_netcmp(ipX_2_ip(&pcb->local_ip), ip_current_dest_addr(), &inp->netmask))))))) { -#endif /* IP_SOF_BROADCAST_RECV */ - local_match = 1; - if ((uncon_pcb == NULL) && - ((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) { - /* the first unconnected matching PCB */ - uncon_pcb = pcb; - } - } - } - /* compare PCB remote addr+port to UDP source addr+port */ - if ((local_match != 0) && - (pcb->remote_port == src) && IP_PCB_IPVER_INPUT_MATCH(pcb) && - (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->remote_ip) || - ipX_addr_cmp(PCB_ISIPV6(pcb), &pcb->remote_ip, ipX_current_src_addr()))) { - /* the first fully matching PCB */ - if (prev != NULL) { - /* move the pcb to the front of udp_pcbs so that is - found faster next time */ - prev->next = pcb->next; - pcb->next = udp_pcbs; - udp_pcbs = pcb; - } else { - UDP_STATS_INC(udp.cachehit); - } - break; - } - prev = pcb; - } - /* no fully matching pcb found? then look for an unconnected pcb */ - if (pcb == NULL) { - pcb = uncon_pcb; - } - } - - /* Check checksum if this is a match or if it was directed at us. */ - if (pcb != NULL) { - for_us = 1; - } else { -#if LWIP_IPV6 - if (ip_current_is_v6()) { - for_us = netif_matches_ip6_addr(inp, ip6_current_dest_addr()); - } else -#endif /* LWIP_IPV6 */ - { - for_us = ip_addr_cmp(&inp->ip_addr, ip_current_dest_addr()); - } - } - if (for_us) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n")); -#if CHECKSUM_CHECK_UDP -#if LWIP_UDPLITE - if (ip_current_header_proto() == IP_PROTO_UDPLITE) { - /* Do the UDP Lite checksum */ - u16_t chklen = ntohs(udphdr->len); - if (chklen < sizeof(struct udp_hdr)) { - if (chklen == 0) { - /* For UDP-Lite, checksum length of 0 means checksum - over the complete packet (See RFC 3828 chap. 3.1) */ - chklen = p->tot_len; - } else { - /* At least the UDP-Lite header must be covered by the - checksum! (Again, see RFC 3828 chap. 3.1) */ - goto chkerr; - } - } - if (ipX_chksum_pseudo_partial(ip_current_is_v6(), p, IP_PROTO_UDPLITE, - p->tot_len, chklen, - ipX_current_src_addr(), ipX_current_dest_addr()) != 0) { - goto chkerr; - } - } else -#endif /* LWIP_UDPLITE */ - { - if (udphdr->chksum != 0) { - if (ipX_chksum_pseudo(ip_current_is_v6(), p, IP_PROTO_UDP, p->tot_len, - ipX_current_src_addr(), - ipX_current_dest_addr()) != 0) { - goto chkerr; - } - } - } -#endif /* CHECKSUM_CHECK_UDP */ - if(pbuf_header(p, -UDP_HLEN)) { - /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_header failed\n", 0); - UDP_STATS_INC(udp.drop); - snmp_inc_udpinerrors(); - pbuf_free(p); - goto end; - } - if (pcb != NULL) { - snmp_inc_udpindatagrams(); -#if SO_REUSE && SO_REUSE_RXTOALL - if ((broadcast || -#if LWIP_IPV6 - ip6_addr_ismulticast(ip6_current_dest_addr()) || -#endif /* LWIP_IPV6 */ - ip_addr_ismulticast(ip_current_dest_addr())) && - ip_get_option(pcb, SOF_REUSEADDR)) { - /* pass broadcast- or multicast packets to all multicast pcbs - if SOF_REUSEADDR is set on the first match */ - struct udp_pcb *mpcb; - u8_t p_header_changed = 0; - s16_t hdrs_len = (s16_t)(ip_current_header_tot_len() + UDP_HLEN); - for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) { - if (mpcb != pcb) { - /* compare PCB local addr+port to UDP destination addr+port */ - if ((mpcb->local_port == dest) && -#if LWIP_IPV6 - ((PCB_ISIPV6(mpcb) && - (ip6_addr_ismulticast(ip6_current_dest_addr()) || - ip6_addr_cmp(ipX_2_ip6(&mpcb->local_ip), ip6_current_dest_addr()))) || - (!PCB_ISIPV6(mpcb) && -#else /* LWIP_IPV6 */ - (( -#endif /* LWIP_IPV6 */ - ((!broadcast && ipX_addr_isany(0, &mpcb->local_ip)) || - ip_addr_cmp(ipX_2_ip(&mpcb->local_ip), ip_current_dest_addr()) || -#if LWIP_IGMP - ip_addr_ismulticast(ip_current_dest_addr()) || -#endif /* LWIP_IGMP */ -#if IP_SOF_BROADCAST_RECV - (broadcast && ip_get_option(mpcb, SOF_BROADCAST)))))) { -#else /* IP_SOF_BROADCAST_RECV */ - (broadcast))))) { -#endif /* IP_SOF_BROADCAST_RECV */ - /* pass a copy of the packet to all local matches */ - if (mpcb->recv.ip4 != NULL) { - struct pbuf *q; - /* for that, move payload to IP header again */ - if (p_header_changed == 0) { - pbuf_header(p, hdrs_len); - p_header_changed = 1; - } - q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); - if (q != NULL) { - err_t err = pbuf_copy(q, p); - if (err == ERR_OK) { - /* move payload to UDP data */ - pbuf_header(q, -hdrs_len); -#if LWIP_IPV6 - if (PCB_ISIPV6(mpcb)) { - mpcb->recv.ip6(mpcb->recv_arg, mpcb, q, ip6_current_src_addr(), src); - } - else -#endif /* LWIP_IPV6 */ - { - mpcb->recv.ip4(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src); - } - } - } - } - } - } - } - if (p_header_changed) { - /* and move payload to UDP data again */ - pbuf_header(p, -hdrs_len); - } - } -#endif /* SO_REUSE && SO_REUSE_RXTOALL */ - /* callback */ - if (pcb->recv.ip4 != NULL) { - /* now the recv function is responsible for freeing p */ -#if LWIP_IPV6 - if (PCB_ISIPV6(pcb)) { - pcb->recv.ip6(pcb->recv_arg, pcb, p, ip6_current_src_addr(), src); - } - else -#endif /* LWIP_IPV6 */ - { - pcb->recv.ip4(pcb->recv_arg, pcb, p, ip_current_src_addr(), src); - } - } else { - /* no recv function registered? then we have to free the pbuf! */ - pbuf_free(p); - goto end; - } - } else { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n")); - -#if LWIP_ICMP || LWIP_ICMP6 - /* No match was found, send ICMP destination port unreachable unless - destination address was broadcast/multicast. */ - if (!broadcast && -#if LWIP_IPV6 - !ip6_addr_ismulticast(ip6_current_dest_addr()) && -#endif /* LWIP_IPV6 */ - !ip_addr_ismulticast(ip_current_dest_addr())) { - /* move payload pointer back to ip header */ - pbuf_header(p, ip_current_header_tot_len() + UDP_HLEN); - icmp_port_unreach(ip_current_is_v6(), p); - } -#endif /* LWIP_ICMP || LWIP_ICMP6 */ - UDP_STATS_INC(udp.proterr); - UDP_STATS_INC(udp.drop); - snmp_inc_udpnoports(); - pbuf_free(p); - } - } else { - pbuf_free(p); - } -end: - PERF_STOP("udp_input"); - return; -#if CHECKSUM_CHECK_UDP -chkerr: - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("udp_input: UDP (or UDP Lite) datagram discarded due to failing checksum\n")); - UDP_STATS_INC(udp.chkerr); - UDP_STATS_INC(udp.drop); - snmp_inc_udpinerrors(); - pbuf_free(p); - PERF_STOP("udp_input"); -#endif /* CHECKSUM_CHECK_UDP */ -} - -/** - * Send data using UDP. - * - * @param pcb UDP PCB used to send the data. - * @param p chain of pbuf's to be sent. - * - * The datagram will be sent to the current remote_ip & remote_port - * stored in pcb. If the pcb is not bound to a port, it will - * automatically be bound to a random port. - * - * @return lwIP error code. - * - ERR_OK. Successful. No error occured. - * - ERR_MEM. Out of memory. - * - ERR_RTE. Could not find route to destination address. - * - More errors could be returned by lower protocol layers. - * - * @see udp_disconnect() udp_sendto() - */ -err_t ICACHE_FLASH_ATTR -udp_send(struct udp_pcb *pcb, struct pbuf *p) -{ - /* send to the packet using remote ip and port stored in the pcb */ - return udp_sendto(pcb, p, ipX_2_ip(&pcb->remote_ip), pcb->remote_port); -} - -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP -/** Same as udp_send() but with checksum - */ -err_t ICACHE_FLASH_ATTR -udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, - u8_t have_chksum, u16_t chksum) -{ - /* send to the packet using remote ip and port stored in the pcb */ - return udp_sendto_chksum(pcb, p, ipX_2_ip(&pcb->remote_ip), pcb->remote_port, - have_chksum, chksum); -} -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - -/** - * Send data to a specified address using UDP. - * - * @param pcb UDP PCB used to send the data. - * @param p chain of pbuf's to be sent. - * @param dst_ip Destination IP address. - * @param dst_port Destination UDP port. - * - * dst_ip & dst_port are expected to be in the same byte order as in the pcb. - * - * If the PCB already has a remote address association, it will - * be restored after the data is sent. - * - * @return lwIP error code (@see udp_send for possible error codes) - * - * @see udp_disconnect() udp_send() - */ -err_t ICACHE_FLASH_ATTR -udp_sendto(struct udp_pcb *pcb, struct pbuf *p, - ip_addr_t *dst_ip, u16_t dst_port) -{ -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP - return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0); -} - -/** Same as udp_sendto(), but with checksum */ -err_t ICACHE_FLASH_ATTR -udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, - u16_t dst_port, u8_t have_chksum, u16_t chksum) -{ -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - struct netif *netif; - ipX_addr_t *dst_ip_route = ip_2_ipX(dst_ip); - - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n")); - -#if LWIP_IPV6 || LWIP_IGMP - if (ipX_addr_ismulticast(PCB_ISIPV6(pcb), dst_ip_route)) { - /* For multicast, find a netif based on source address. */ -#if LWIP_IPV6 - if (PCB_ISIPV6(pcb)) { - dst_ip_route = &pcb->local_ip; - } else -#endif /* LWIP_IPV6 */ - { -#if LWIP_IGMP - dst_ip_route = ip_2_ipX(&pcb->multicast_ip); -#endif /* LWIP_IGMP */ - } - } -#endif /* LWIP_IPV6 || LWIP_IGMP */ - - /* find the outgoing network interface for this packet */ - netif = ipX_route(PCB_ISIPV6(pcb), &pcb->local_ip, dst_ip_route); - - /* no outgoing network interface could be found? */ - if (netif == NULL) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to ")); - ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ip_2_ipX(dst_ip)); - LWIP_DEBUGF(UDP_DEBUG, ("\n")); - UDP_STATS_INC(udp.rterr); - return ERR_RTE; - } -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP - return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum); -#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - return udp_sendto_if(pcb, p, dst_ip, dst_port, netif); -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ -} - -/** - * Send data to a specified address using UDP. - * The netif used for sending can be specified. - * - * This function exists mainly for DHCP, to be able to send UDP packets - * on a netif that is still down. - * - * @param pcb UDP PCB used to send the data. - * @param p chain of pbuf's to be sent. - * @param dst_ip Destination IP address. - * @param dst_port Destination UDP port. - * @param netif the netif used for sending. - * - * dst_ip & dst_port are expected to be in the same byte order as in the pcb. - * - * @return lwIP error code (@see udp_send for possible error codes) - * - * @see udp_disconnect() udp_send() - */ -err_t ICACHE_FLASH_ATTR -udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, - ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) -{ -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP - return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0); -} - -/** Same as udp_sendto_if(), but with checksum */ -err_t ICACHE_FLASH_ATTR -udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, - u16_t dst_port, struct netif *netif, u8_t have_chksum, - u16_t chksum) -{ -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - struct udp_hdr *udphdr; - ip_addr_t *src_ip; - err_t err; - struct pbuf *q; /* q will be sent down the stack */ - u8_t ip_proto; - -#if IP_SOF_BROADCAST - /* broadcast filter? */ - if (!ip_get_option(pcb, SOF_BROADCAST) && -#if LWIP_IPV6 - !PCB_ISIPV6(pcb) && -#endif /* LWIP_IPV6 */ - ip_addr_isbroadcast(dst_ip, netif) ) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); - return ERR_VAL; - } -#endif /* IP_SOF_BROADCAST */ - - /* if the PCB is not yet bound to a port, bind it here */ - if (pcb->local_port == 0) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n")); - err = udp_bind(pcb, ipX_2_ip(&pcb->local_ip), pcb->local_port); - if (err != ERR_OK) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n")); - return err; - } - } - - /* not enough space to add an UDP header to first pbuf in given p chain? */ - if (pbuf_header(p, UDP_HLEN)) { - /* allocate header in a separate new pbuf */ - q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM); - /* new header pbuf could not be allocated? */ - if (q == NULL) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n")); - return ERR_MEM; - } - if (p->tot_len != 0) { - /* chain header q in front of given pbuf p (only if p contains data) */ - pbuf_chain(q, p); - } - /* first pbuf q points to header pbuf */ - LWIP_DEBUGF(UDP_DEBUG, - ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); - } else { - /* adding space for header within p succeeded */ - /* first pbuf q equals given pbuf */ - q = p; - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p)); - } - LWIP_ASSERT("check that first pbuf can hold struct udp_hdr", - (q->len >= sizeof(struct udp_hdr))); - /* q now represents the packet to be sent */ - udphdr = (struct udp_hdr *)q->payload; - udphdr->src = htons(pcb->local_port); - udphdr->dest = htons(dst_port); - /* in UDP, 0 checksum means 'no checksum' */ - udphdr->chksum = 0x0000; - - /* Multicast Loop? */ -#if LWIP_IGMP - if (((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) && -#if LWIP_IPV6 - ( -#if LWIP_IPV6_MLD - (PCB_ISIPV6(pcb) && - ip6_addr_ismulticast(ip_2_ip6(dst_ip))) || -#endif /* LWIP_IPV6_MLD */ - (!PCB_ISIPV6(pcb) && -#else /* LWIP_IPV6 */ - (( -#endif /* LWIP_IPV6 */ - ip_addr_ismulticast(dst_ip)))) { - q->flags |= PBUF_FLAG_MCASTLOOP; - } -#endif /* LWIP_IGMP */ - - - /* PCB local address is IP_ANY_ADDR? */ -#if LWIP_IPV6 - if (PCB_ISIPV6(pcb)) { - if (ip6_addr_isany(ipX_2_ip6(&pcb->local_ip))) { - src_ip = ip6_2_ip(ip6_select_source_address(netif, ip_2_ip6(dst_ip))); - if (src_ip == NULL) { - /* No suitable source address was found. */ - if (q != p) { - /* free the header pbuf */ - pbuf_free(q); - /* p is still referenced by the caller, and will live on */ - } - return ERR_RTE; - } - } else { - /* use UDP PCB local IPv6 address as source address, if still valid. */ - if (netif_matches_ip6_addr(netif, ipX_2_ip6(&pcb->local_ip)) < 0) { - /* Address isn't valid anymore. */ - if (q != p) { - /* free the header pbuf */ - pbuf_free(q); - /* p is still referenced by the caller, and will live on */ - } - return ERR_RTE; - } - src_ip = ipX_2_ip(&pcb->local_ip); - } - } - else -#endif /* LWIP_IPV6 */ - if (ip_addr_isany(ipX_2_ip(&pcb->local_ip))) { - /* use outgoing network interface IP address as source address */ - src_ip = &(netif->ip_addr); - } else { - /* check if UDP PCB local IP address is correct - * this could be an old address if netif->ip_addr has changed */ - if (!ip_addr_cmp(ipX_2_ip(&(pcb->local_ip)), &(netif->ip_addr))) { - /* local_ip doesn't match, drop the packet */ - if (q != p) { - /* free the header pbuf */ - pbuf_free(q); - q = NULL; - /* p is still referenced by the caller, and will live on */ - } - return ERR_VAL; - } - /* use UDP PCB local IP address as source address */ - src_ip = ipX_2_ip(&(pcb->local_ip)); - } - - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len)); - -#if LWIP_UDPLITE - /* UDP Lite protocol? */ - if (pcb->flags & UDP_FLAGS_UDPLITE) { - u16_t chklen, chklen_hdr; - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len)); - /* set UDP message length in UDP header */ - chklen_hdr = chklen = pcb->chksum_len_tx; - if ((chklen < sizeof(struct udp_hdr)) || (chklen > q->tot_len)) { - if (chklen != 0) { - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen)); - } - /* For UDP-Lite, checksum length of 0 means checksum - over the complete packet. (See RFC 3828 chap. 3.1) - At least the UDP-Lite header must be covered by the - checksum, therefore, if chksum_len has an illegal - value, we generate the checksum over the complete - packet to be safe. */ - chklen_hdr = 0; - chklen = q->tot_len; - } - udphdr->len = htons(chklen_hdr); - /* calculate checksum */ -#if CHECKSUM_GEN_UDP -#if LWIP_CHECKSUM_ON_COPY - if (have_chksum) { - chklen = UDP_HLEN; - } -#endif /* LWIP_CHECKSUM_ON_COPY */ - udphdr->chksum = ipX_chksum_pseudo_partial(PCB_ISIPV6(pcb), q, IP_PROTO_UDPLITE, - q->tot_len, chklen, ip_2_ipX(src_ip), ip_2_ipX(dst_ip)); -#if LWIP_CHECKSUM_ON_COPY - if (have_chksum) { - u32_t acc; - acc = udphdr->chksum + (u16_t)~(chksum); - udphdr->chksum = FOLD_U32T(acc); - } -#endif /* LWIP_CHECKSUM_ON_COPY */ - - /* chksum zero must become 0xffff, as zero means 'no checksum' */ - if (udphdr->chksum == 0x0000) { - udphdr->chksum = 0xffff; - } -#endif /* CHECKSUM_GEN_UDP */ - - ip_proto = IP_PROTO_UDPLITE; - } else -#endif /* LWIP_UDPLITE */ - { /* UDP */ - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len)); - udphdr->len = htons(q->tot_len); - /* calculate checksum */ -#if CHECKSUM_GEN_UDP - /* Checksum is mandatory over IPv6. */ - if (PCB_ISIPV6(pcb) || (pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) { - u16_t udpchksum; -#if LWIP_CHECKSUM_ON_COPY - if (have_chksum) { - u32_t acc; - udpchksum = ipX_chksum_pseudo_partial(PCB_ISIPV6(pcb), q, IP_PROTO_UDP, - q->tot_len, UDP_HLEN, ip_2_ipX(src_ip), ip_2_ipX(dst_ip)); - acc = udpchksum + (u16_t)~(chksum); - udpchksum = FOLD_U32T(acc); - } else -#endif /* LWIP_CHECKSUM_ON_COPY */ - { - udpchksum = ipX_chksum_pseudo(PCB_ISIPV6(pcb), q, IP_PROTO_UDP, q->tot_len, - ip_2_ipX(src_ip), ip_2_ipX(dst_ip)); - } - - /* chksum zero must become 0xffff, as zero means 'no checksum' */ - if (udpchksum == 0x0000) { - udpchksum = 0xffff; - } - udphdr->chksum = udpchksum; - } -#endif /* CHECKSUM_GEN_UDP */ - ip_proto = IP_PROTO_UDP; - } - - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum)); - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,0x%02"X16_F",)\n", (u16_t)ip_proto)); - /* output to IP */ - NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); - err = ipX_output_if(PCB_ISIPV6(pcb), q, src_ip, dst_ip, pcb->ttl, pcb->tos, ip_proto, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - - /* TODO: must this be increased even if error occured? */ - snmp_inc_udpoutdatagrams(); - - /* did we chain a separate header pbuf earlier? */ - if (q != p) { - /* free the header pbuf */ - pbuf_free(q); - q = NULL; - /* p is still referenced by the caller, and will live on */ - } - - UDP_STATS_INC(udp.xmit); - return err; -} - -/** - * Bind an UDP PCB. - * - * @param pcb UDP PCB to be bound with a local address ipaddr and port. - * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to - * bind to all local interfaces. - * @param port local UDP port to bind with. Use 0 to automatically bind - * to a random port between UDP_LOCAL_PORT_RANGE_START and - * UDP_LOCAL_PORT_RANGE_END. - * - * ipaddr & port are expected to be in the same byte order as in the pcb. - * - * @return lwIP error code. - * - ERR_OK. Successful. No error occured. - * - ERR_USE. The specified ipaddr and port are already bound to by - * another UDP PCB. - * - * @see udp_disconnect() - */ -err_t ICACHE_FLASH_ATTR -udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) -{ - struct udp_pcb *ipcb; - u8_t rebind; - - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = ")); - ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG | LWIP_DBG_TRACE, ip_2_ipX(ipaddr)); - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port)); - - rebind = 0; - /* Check for double bind and rebind of the same pcb */ - for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { - /* is this UDP PCB already on active list? */ - if (pcb == ipcb) { - /* pcb may occur at most once in active list */ - LWIP_ASSERT("rebind == 0", rebind == 0); - /* pcb already in list, just rebind */ - rebind = 1; - } - - /* By default, we don't allow to bind to a port that any other udp - PCB is alread bound to, unless *all* PCBs with that port have tha - REUSEADDR flag set. */ -#if SO_REUSE - else if (!ip_get_option(pcb, SOF_REUSEADDR) && - !ip_get_option(ipcb, SOF_REUSEADDR)) { -#else /* SO_REUSE */ - /* port matches that of PCB in list and REUSEADDR not set -> reject */ - else { -#endif /* SO_REUSE */ - if ((ipcb->local_port == port) && IP_PCB_IPVER_EQ(pcb, ipcb) && - /* IP address matches, or one is IP_ADDR_ANY? */ - (ipX_addr_isany(PCB_ISIPV6(ipcb), &(ipcb->local_ip)) || - ipX_addr_isany(PCB_ISIPV6(ipcb), ip_2_ipX(ipaddr)) || - ipX_addr_cmp(PCB_ISIPV6(ipcb), &(ipcb->local_ip), ip_2_ipX(ipaddr)))) { - /* other PCB already binds to this local IP and port */ - LWIP_DEBUGF(UDP_DEBUG, - ("udp_bind: local port %"U16_F" already bound by another pcb\n", port)); - return ERR_USE; - } - } - } - - ipX_addr_set_ipaddr(PCB_ISIPV6(pcb), &pcb->local_ip, ipaddr); - - /* no port specified? */ - if (port == 0) { - port = udp_new_port(); - if (port == 0) { - /* no more ports available in local range */ - LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n")); - return ERR_USE; - } - } - pcb->local_port = port; - snmp_insert_udpidx_tree(pcb); - /* pcb not active yet? */ - if (rebind == 0) { - /* place the PCB on the active list if not already there */ - pcb->next = udp_pcbs; - udp_pcbs = pcb; - } - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_bind: bound to ")); - ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->local_ip); - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->local_port)); - return ERR_OK; -} - -/** - * Connect an UDP PCB. - * - * This will associate the UDP PCB with the remote address. - * - * @param pcb UDP PCB to be connected with remote address ipaddr and port. - * @param ipaddr remote IP address to connect with. - * @param port remote UDP port to connect with. - * - * @return lwIP error code - * - * ipaddr & port are expected to be in the same byte order as in the pcb. - * - * The udp pcb is bound to a random local port if not already bound. - * - * @see udp_disconnect() - */ -err_t ICACHE_FLASH_ATTR -udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) -{ - struct udp_pcb *ipcb; - - if (pcb->local_port == 0) { - err_t err = udp_bind(pcb, ipX_2_ip(&pcb->local_ip), pcb->local_port); - if (err != ERR_OK) { - return err; - } - } - - ipX_addr_set_ipaddr(PCB_ISIPV6(pcb), &pcb->remote_ip, ipaddr); - pcb->remote_port = port; - pcb->flags |= UDP_FLAGS_CONNECTED; -/** TODO: this functionality belongs in upper layers */ -#ifdef LWIP_UDP_TODO -#if LWIP_IPV6 - if (!PCB_ISIPV6(pcb)) -#endif /* LWIP_IPV6 */ - { - /* Nail down local IP for netconn_addr()/getsockname() */ - if (ip_addr_isany(ipX_2_ip(&pcb->local_ip)) && !ip_addr_isany(ipX_2_ip(&pcb->remote_ip))) { - struct netif *netif; - - if ((netif = ip_route(ipX_2_ip(&pcb->remote_ip))) == NULL) { - LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", - ip4_addr_get_u32(ipX_2_ip(&pcb->remote_ip)))); - UDP_STATS_INC(udp.rterr); - return ERR_RTE; - } - /** TODO: this will bind the udp pcb locally, to the interface which - is used to route output packets to the remote address. However, we - might want to accept incoming packets on any interface! */ - ipX_addr_copy(0, pcb->local_ip, netif->ip_addr); - } else if (ip_addr_isany(ipX_2_ip(&pcb->remote_ip))) { - ipX_addr_set_any(0, &pcb->local_ip); - } - } -#endif - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_connect: connected to ")); - ipX_addr_debug_print(PCB_ISIPV6(pcb), UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - &pcb->remote_ip); - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->remote_port)); - - /* Insert UDP PCB into the list of active UDP PCBs. */ - for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { - if (pcb == ipcb) { - /* already on the list, just return */ - return ERR_OK; - } - } - /* PCB not yet on the list, add PCB now */ - pcb->next = udp_pcbs; - udp_pcbs = pcb; - return ERR_OK; -} - -/** - * Disconnect a UDP PCB - * - * @param pcb the udp pcb to disconnect. - */ -void ICACHE_FLASH_ATTR -udp_disconnect(struct udp_pcb *pcb) -{ - /* reset remote address association */ - ipX_addr_set_any(PCB_ISIPV6(pcb), &pcb->remote_ip); - pcb->remote_port = 0; - /* mark PCB as unconnected */ - pcb->flags &= ~UDP_FLAGS_CONNECTED; -} - -/** - * Set a receive callback for a UDP PCB - * - * This callback will be called when receiving a datagram for the pcb. - * - * @param pcb the pcb for wich to set the recv callback - * @param recv function pointer of the callback function - * @param recv_arg additional argument to pass to the callback function - */ -void ICACHE_FLASH_ATTR -udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg) -{ - /* remember recv() callback and user data */ - pcb->recv.ip4 = recv; - pcb->recv_arg = recv_arg; -} - -/** - * Remove an UDP PCB. - * - * @param pcb UDP PCB to be removed. The PCB is removed from the list of - * UDP PCB's and the data structure is freed from memory. - * - * @see udp_new() - */ -void ICACHE_FLASH_ATTR -udp_remove(struct udp_pcb *pcb) -{ - struct udp_pcb *pcb2; - - snmp_delete_udpidx_tree(pcb); - /* pcb to be removed is first in list? */ - if (udp_pcbs == pcb) { - /* make list start at 2nd pcb */ - udp_pcbs = udp_pcbs->next; - /* pcb not 1st in list */ - } else { - for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { - /* find pcb in udp_pcbs list */ - if (pcb2->next != NULL && pcb2->next == pcb) { - /* remove pcb from list */ - pcb2->next = pcb->next; - } - } - } - memp_free(MEMP_UDP_PCB, pcb); -} - -/** - * Create a UDP PCB. - * - * @return The UDP PCB which was created. NULL if the PCB data structure - * could not be allocated. - * - * @see udp_remove() - */ -struct udp_pcb * ICACHE_FLASH_ATTR -udp_new(void) -{ - struct udp_pcb *pcb; - pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB); - /* could allocate UDP PCB? */ - if (pcb != NULL) { - /* UDP Lite: by initializing to all zeroes, chksum_len is set to 0 - * which means checksum is generated over the whole datagram per default - * (recommended as default by RFC 3828). */ - /* initialize PCB to all zeroes */ - memset(pcb, 0, sizeof(struct udp_pcb)); - pcb->ttl = UDP_TTL; - } - return pcb; -} - -#if LWIP_IPV6 -/** - * Create a UDP PCB for IPv6. - * - * @return The UDP PCB which was created. NULL if the PCB data structure - * could not be allocated. - * - * @see udp_remove() - */ -struct udp_pcb * ICACHE_FLASH_ATTR -udp_new_ip6(void) -{ - struct udp_pcb *pcb; - pcb = udp_new(); - ip_set_v6(pcb, 1); - return pcb; -} -#endif /* LWIP_IPV6 */ - -#if UDP_DEBUG -/** - * Print UDP header information for debug purposes. - * - * @param udphdr pointer to the udp header in memory. - */ -void ICACHE_FLASH_ATTR -udp_debug_print(struct udp_hdr *udphdr) -{ - LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n")); - LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", - ntohs(udphdr->src), ntohs(udphdr->dest))); - LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n", - ntohs(udphdr->len), ntohs(udphdr->chksum))); - LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); -} -#endif /* UDP_DEBUG */ - -#endif /* LWIP_UDP */ diff --git a/third_party/lwip/netif/FILES b/third_party/lwip/netif/FILES deleted file mode 100644 index e28952e..0000000 --- a/third_party/lwip/netif/FILES +++ /dev/null @@ -1,29 +0,0 @@ -This directory contains generic network interface device drivers that -do not contain any hardware or architecture specific code. The files -are: - -etharp.c - Implements the ARP (Address Resolution Protocol) over - Ethernet. The code in this file should be used together with - Ethernet device drivers. Note that this module has been - largely made Ethernet independent so you should be able to - adapt this for other link layers (such as Firewire). - -ethernetif.c - An example of how an Ethernet device driver could look. This - file can be used as a "skeleton" for developing new Ethernet - network device drivers. It uses the etharp.c ARP code. - -loopif.c - A "loopback" network interface driver. It requires configuration - through the define LWIP_LOOPIF_MULTITHREADING (see opt.h). - -slipif.c - A generic implementation of the SLIP (Serial Line IP) - protocol. It requires a sio (serial I/O) module to work. - -ppp/ Point-to-Point Protocol stack - The PPP stack has been ported from ucip (http://ucip.sourceforge.net). - It matches quite well to pppd 2.3.1 (http://ppp.samba.org), although - compared to that, it has some modifications for embedded systems and - the source code has been reordered a bit. \ No newline at end of file diff --git a/third_party/lwip/netif/Makefile b/third_party/lwip/netif/Makefile deleted file mode 100644 index f03613f..0000000 --- a/third_party/lwip/netif/Makefile +++ /dev/null @@ -1,46 +0,0 @@ - -############################################################# -# Required variables for each makefile -# Discard this section from all parent makefiles -# Expected variables (with automatic defaults): -# CSRCS (all "C" files in the dir) -# SUBDIRS (all subdirs with a Makefile) -# GEN_LIBS - list of libs to be generated () -# GEN_IMAGES - list of images to be generated () -# COMPONENTS_xxx - a list of libs/objs in the form -# subdir/lib to be extracted and rolled up into -# a generated lib/image xxx.a () -# -ifndef PDIR - -GEN_LIBS = liblwipnetif.a - -endif - - -############################################################# -# Configuration i.e. compile options etc. -# Target specific stuff (defines etc.) goes in here! -# Generally values applying to a tree are captured in the -# makefile at its root level - these are then overridden -# for a subtree within the makefile rooted therein -# -#DEFINES += - -############################################################# -# Recursion Magic - Don't touch this!! -# -# Each subtree potentially has an include directory -# corresponding to the common APIs applicable to modules -# rooted at that subtree. Accordingly, the INCLUDE PATH -# of a module can only contain the include directories up -# its parent path, and not its siblings -# -# Required for each makefile to inherit from the parent -# - -INCLUDES := $(INCLUDES) -I $(PDIR)include -INCLUDES += -I ./ -PDIR := ../$(PDIR) -sinclude $(PDIR)Makefile - diff --git a/third_party/lwip/netif/etharp.c b/third_party/lwip/netif/etharp.c deleted file mode 100644 index da7ec06..0000000 --- a/third_party/lwip/netif/etharp.c +++ /dev/null @@ -1,1414 +0,0 @@ -/** - * @file - * Address Resolution Protocol module for IP over Ethernet - * - * Functionally, ARP is divided into two parts. The first maps an IP address - * to a physical address when sending a packet, and the second part answers - * requests from other machines for our physical address. - * - * This implementation complies with RFC 826 (Ethernet ARP). It supports - * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6 - * if an interface calls etharp_gratuitous(our_netif) upon address change. - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * Copyright (c) 2003-2004 Leon Woestenberg - * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. - * 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 "lwip/opt.h" - -#if LWIP_ARP || LWIP_ETHERNET - -#include "lwip/ip_addr.h" -#include "lwip/def.h" -#include "lwip/ip.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/dhcp.h" -#include "lwip/autoip.h" -#include "netif/etharp.h" -#include "lwip/ip6.h" - -#if PPPOE_SUPPORT -#include "netif/ppp_oe.h" -#endif /* PPPOE_SUPPORT */ - -#include - -const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; -const struct eth_addr ethzero = {{0,0,0,0,0,0}}; - -/** The 24-bit IANA multicast OUI is 01-00-5e: */ -#define LL_MULTICAST_ADDR_0 0x01 -#define LL_MULTICAST_ADDR_1 0x00 -#define LL_MULTICAST_ADDR_2 0x5e - -#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */ - -/** the time an ARP entry stays valid after its last update, - * for ARP_TMR_INTERVAL = 5000, this is - * (240 * 5) seconds = 20 minutes. - */ -#define ARP_MAXAGE 240 -/** Re-request a used ARP entry 1 minute before it would expire to prevent - * breaking a steadily used connection because the ARP entry timed out. */ -#define ARP_AGE_REREQUEST_USED (ARP_MAXAGE - 12) - -/** the time an ARP entry stays pending after first request, - * for ARP_TMR_INTERVAL = 5000, this is - * (2 * 5) seconds = 10 seconds. - * - * @internal Keep this number at least 2, otherwise it might - * run out instantly if the timeout occurs directly after a request. - */ -#define ARP_MAXPENDING 2 - -#define HWTYPE_ETHERNET 1 - -enum etharp_state { - ETHARP_STATE_EMPTY = 0, - ETHARP_STATE_PENDING, - ETHARP_STATE_STABLE, - ETHARP_STATE_STABLE_REREQUESTING -#if ETHARP_SUPPORT_STATIC_ENTRIES - ,ETHARP_STATE_STATIC -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ -}; - -struct etharp_entry { -#if ARP_QUEUEING - /** Pointer to queue of pending outgoing packets on this ARP entry. */ - struct etharp_q_entry *q; -#else /* ARP_QUEUEING */ - /** Pointer to a single pending outgoing packet on this ARP entry. */ - struct pbuf *q; -#endif /* ARP_QUEUEING */ - ip_addr_t ipaddr; - struct netif *netif; - struct eth_addr ethaddr; - u8_t state; - u8_t ctime; -}; - -static struct etharp_entry arp_table[ARP_TABLE_SIZE]; - -#if !LWIP_NETIF_HWADDRHINT -static u8_t etharp_cached_entry; -#endif /* !LWIP_NETIF_HWADDRHINT */ - -/** Try hard to create a new entry - we want the IP address to appear in - the cache (even if this means removing an active entry or so). */ -#define ETHARP_FLAG_TRY_HARD 1 -#define ETHARP_FLAG_FIND_ONLY 2 -#if ETHARP_SUPPORT_STATIC_ENTRIES -#define ETHARP_FLAG_STATIC_ENTRY 4 -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - -#if LWIP_NETIF_HWADDRHINT -#define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \ - *((netif)->addr_hint) = (hint); -#else /* LWIP_NETIF_HWADDRHINT */ -#define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint)) -#endif /* LWIP_NETIF_HWADDRHINT */ - - -/* Some checks, instead of etharp_init(): */ -#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) - #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h" -#endif - - -#if ARP_QUEUEING -/** - * Free a complete queue of etharp entries - * - * @param q a qeueue of etharp_q_entry's to free - */ -static void ICACHE_FLASH_ATTR -free_etharp_q(struct etharp_q_entry *q) -{ - struct etharp_q_entry *r; - LWIP_ASSERT("q != NULL", q != NULL); - LWIP_ASSERT("q->p != NULL", q->p != NULL); - while (q) { - r = q; - q = q->next; - LWIP_ASSERT("r->p != NULL", (r->p != NULL)); - pbuf_free(r->p); - memp_free(MEMP_ARP_QUEUE, r); - } -} -#else /* ARP_QUEUEING */ - -/** Compatibility define: free the queued pbuf */ -#define free_etharp_q(q) pbuf_free(q) - -#endif /* ARP_QUEUEING */ - -/** Clean up ARP table entries */ -static void ICACHE_FLASH_ATTR -etharp_free_entry(int i) -{ - /* remove from SNMP ARP index tree */ - snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); - /* and empty packet queue */ - if (arp_table[i].q != NULL) { - /* remove all queued packets */ - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_free_entry: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q))); - free_etharp_q(arp_table[i].q); - arp_table[i].q = NULL; - } - /* recycle entry for re-use */ - arp_table[i].state = ETHARP_STATE_EMPTY; -#ifdef LWIP_DEBUG - /* for debugging, clean out the complete entry */ - arp_table[i].ctime = 0; - arp_table[i].netif = NULL; - ip_addr_set_zero(&arp_table[i].ipaddr); - arp_table[i].ethaddr = ethzero; -#endif /* LWIP_DEBUG */ -} - -/** - * Clears expired entries in the ARP table. - * - * This function should be called every ETHARP_TMR_INTERVAL milliseconds (5 seconds), - * in order to expire entries in the ARP table. - */ -void ICACHE_FLASH_ATTR -etharp_tmr(void) -{ - u8_t i; - - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); - /* remove expired entries from the ARP table */ - for (i = 0; i < ARP_TABLE_SIZE; ++i) { - u8_t state = arp_table[i].state; - if (state != ETHARP_STATE_EMPTY -#if ETHARP_SUPPORT_STATIC_ENTRIES - && (state != ETHARP_STATE_STATIC) -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - ) { - arp_table[i].ctime++; - if ((arp_table[i].ctime >= ARP_MAXAGE) || - ((arp_table[i].state == ETHARP_STATE_PENDING) && - (arp_table[i].ctime >= ARP_MAXPENDING))) { - /* pending or stable entry has become old! */ - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", - arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); - /* clean up entries that have just been expired */ - etharp_free_entry(i); - } - else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING) { - /* Reset state to stable, so that the next transmitted packet will - re-send an ARP request. */ - arp_table[i].state = ETHARP_STATE_STABLE; - } -#if ARP_QUEUEING - /* still pending entry? (not expired) */ - if (arp_table[i].state == ETHARP_STATE_PENDING) { - /* resend an ARP query here? */ - } -#endif /* ARP_QUEUEING */ - } - } -} - -/** - * Search the ARP table for a matching or new entry. - * - * If an IP address is given, return a pending or stable ARP entry that matches - * the address. If no match is found, create a new entry with this address set, - * but in state ETHARP_EMPTY. The caller must check and possibly change the - * state of the returned entry. - * - * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY. - * - * In all cases, attempt to create new entries from an empty entry. If no - * empty entries are available and ETHARP_FLAG_TRY_HARD flag is set, recycle - * old entries. Heuristic choose the least important entry for recycling. - * - * @param ipaddr IP address to find in ARP cache, or to add if not found. - * @param flags @see definition of ETHARP_FLAG_* - * @param netif netif related to this address (used for NETIF_HWADDRHINT) - * - * @return The ARP entry index that matched or is created, ERR_MEM if no - * entry is found or could be recycled. - */ -static s8_t ICACHE_FLASH_ATTR -etharp_find_entry(ip_addr_t *ipaddr, u8_t flags) -{ - s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; - s8_t empty = ARP_TABLE_SIZE; - u8_t i = 0, age_pending = 0, age_stable = 0; - /* oldest entry with packets on queue */ - s8_t old_queue = ARP_TABLE_SIZE; - /* its age */ - u8_t age_queue = 0; - - /** - * a) do a search through the cache, remember candidates - * b) select candidate entry - * c) create new entry - */ - - /* a) in a single search sweep, do all of this - * 1) remember the first empty entry (if any) - * 2) remember the oldest stable entry (if any) - * 3) remember the oldest pending entry without queued packets (if any) - * 4) remember the oldest pending entry with queued packets (if any) - * 5) search for a matching IP entry, either pending or stable - * until 5 matches, or all entries are searched for. - */ - - for (i = 0; i < ARP_TABLE_SIZE; ++i) { - u8_t state = arp_table[i].state; - /* no empty entry found yet and now we do find one? */ - if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) { - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %"U16_F"\n", (u16_t)i)); - /* remember first empty entry */ - empty = i; - } else if (state != ETHARP_STATE_EMPTY) { - LWIP_ASSERT("state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE", - state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE); - /* if given, does IP address match IP address in ARP entry? */ - if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %"U16_F"\n", (u16_t)i)); - /* found exact IP address match, simply bail out */ - return i; - } - /* pending entry? */ - if (state == ETHARP_STATE_PENDING) { - /* pending with queued packets? */ - if (arp_table[i].q != NULL) { - if (arp_table[i].ctime >= age_queue) { - old_queue = i; - age_queue = arp_table[i].ctime; - } - } else - /* pending without queued packets? */ - { - if (arp_table[i].ctime >= age_pending) { - old_pending = i; - age_pending = arp_table[i].ctime; - } - } - /* stable entry? */ - } else if (state >= ETHARP_STATE_STABLE) { -#if ETHARP_SUPPORT_STATIC_ENTRIES - /* don't record old_stable for static entries since they never expire */ - if (state < ETHARP_STATE_STATIC) -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - { - /* remember entry with oldest stable entry in oldest, its age in maxtime */ - if (arp_table[i].ctime >= age_stable) { - old_stable = i; - age_stable = arp_table[i].ctime; - } - } - } - } - } - /* { we have no match } => try to create a new entry */ - - /* don't create new entry, only search? */ - if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) || - /* or no empty entry found and not allowed to recycle? */ - ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n")); - return (s8_t)ERR_MEM; - } - - /* b) choose the least destructive entry to recycle: - * 1) empty entry - * 2) oldest stable entry - * 3) oldest pending entry without queued packets - * 4) oldest pending entry with queued packets - * - * { ETHARP_FLAG_TRY_HARD is set at this point } - */ - - /* 1) empty entry available? */ - if (empty < ARP_TABLE_SIZE) { - i = empty; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %"U16_F"\n", (u16_t)i)); - } else { - /* 2) found recyclable stable entry? */ - if (old_stable < ARP_TABLE_SIZE) { - /* recycle oldest stable*/ - i = old_stable; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); - /* no queued packets should exist on stable entries */ - LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); - /* 3) found recyclable pending entry without queued packets? */ - } else if (old_pending < ARP_TABLE_SIZE) { - /* recycle oldest pending */ - i = old_pending; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); - /* 4) found recyclable pending entry with queued packets? */ - } else if (old_queue < ARP_TABLE_SIZE) { - /* recycle oldest pending (queued packets are free in etharp_free_entry) */ - i = old_queue; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); - /* no empty or recyclable entries found */ - } else { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty or recyclable entries found\n")); - return (s8_t)ERR_MEM; - } - - /* { empty or recyclable entry found } */ - LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); - etharp_free_entry(i); - } - - LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); - LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY", - arp_table[i].state == ETHARP_STATE_EMPTY); - - /* IP address given? */ - if (ipaddr != NULL) { - /* set IP address */ - ip_addr_copy(arp_table[i].ipaddr, *ipaddr); - } - arp_table[i].ctime = 0; - return (err_t)i; -} - -/** - * Send an IP packet on the network using netif->linkoutput - * The ethernet header is filled in before sending. - * - * @params netif the lwIP network interface on which to send the packet - * @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header - * @params src the source MAC address to be copied into the ethernet header - * @params dst the destination MAC address to be copied into the ethernet header - * @return ERR_OK if the packet was sent, any other err_t on failure - */ -static err_t ICACHE_FLASH_ATTR -etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst) -{ - struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload; - - LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", - (netif->hwaddr_len == ETHARP_HWADDR_LEN)); - ETHADDR32_COPY(ðhdr->dest, dst); - ETHADDR16_COPY(ðhdr->src, src); - ethhdr->type = PP_HTONS(ETHTYPE_IP); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p)); - /* send the packet */ - return netif->linkoutput(netif, p); -} - -/** - * Update (or insert) a IP/MAC address pair in the ARP cache. - * - * If a pending entry is resolved, any queued packets will be sent - * at this point. - * - * @param netif netif related to this entry (used for NETIF_ADDRHINT) - * @param ipaddr IP address of the inserted ARP entry. - * @param ethaddr Ethernet address of the inserted ARP entry. - * @param flags @see definition of ETHARP_FLAG_* - * - * @return - * - ERR_OK Succesfully updated ARP cache. - * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. - * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. - * - * @see pbuf_free() - */ -static err_t ICACHE_FLASH_ATTR -etharp_update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) -{ - s8_t i; - LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", - ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), - ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], - ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); - /* non-unicast address? */ - if (ip_addr_isany(ipaddr) || - ip_addr_isbroadcast(ipaddr, netif) || - ip_addr_ismulticast(ipaddr)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: will not add non-unicast IP address to ARP cache\n")); - return ERR_ARG; - } - /* find or create ARP entry */ - i = etharp_find_entry(ipaddr, flags); - /* bail out if no entry could be found */ - if (i < 0) { - return (err_t)i; - } - -#if ETHARP_SUPPORT_STATIC_ENTRIES - if (flags & ETHARP_FLAG_STATIC_ENTRY) { - /* record static type */ - arp_table[i].state = ETHARP_STATE_STATIC; - } else -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - { - /* mark it stable */ - arp_table[i].state = ETHARP_STATE_STABLE; - } - - /* record network interface */ - arp_table[i].netif = netif; - /* insert in SNMP ARP index tree */ - snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr); - - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); - /* update address */ - ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); - /* reset time stamp */ - arp_table[i].ctime = 0; - /* this is where we will send out queued packets! */ -#if ARP_QUEUEING - while (arp_table[i].q != NULL) { - struct pbuf *p; - /* remember remainder of queue */ - struct etharp_q_entry *q = arp_table[i].q; - /* pop first item off the queue */ - arp_table[i].q = q->next; - /* get the packet pointer */ - p = q->p; - /* now queue entry can be freed */ - memp_free(MEMP_ARP_QUEUE, q); -#else /* ARP_QUEUEING */ - if (arp_table[i].q != NULL) { - struct pbuf *p = arp_table[i].q; - arp_table[i].q = NULL; -#endif /* ARP_QUEUEING */ - /* send the queued IP packet */ - etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr); - /* free the queued IP packet */ - pbuf_free(p); - } - return ERR_OK; -} - -#if ETHARP_SUPPORT_STATIC_ENTRIES -/** Add a new static entry to the ARP table. If an entry exists for the - * specified IP address, this entry is overwritten. - * If packets are queued for the specified IP address, they are sent out. - * - * @param ipaddr IP address for the new static entry - * @param ethaddr ethernet address for the new static entry - * @return @see return values of etharp_add_static_entry - */ -err_t ICACHE_FLASH_ATTR -etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr) -{ - struct netif *netif; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", - ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), - ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], - ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); - - netif = ip_route(ipaddr); - if (netif == NULL) { - return ERR_RTE; - } - - return etharp_update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY); -} - -/** Remove a static entry from the ARP table previously added with a call to - * etharp_add_static_entry. - * - * @param ipaddr IP address of the static entry to remove - * @return ERR_OK: entry removed - * ERR_MEM: entry wasn't found - * ERR_ARG: entry wasn't a static entry but a dynamic one - */ -err_t ICACHE_FLASH_ATTR -etharp_remove_static_entry(ip_addr_t *ipaddr) -{ - s8_t i; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); - - /* find or create ARP entry */ - i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY); - /* bail out if no entry could be found */ - if (i < 0) { - return (err_t)i; - } - - if (arp_table[i].state != ETHARP_STATE_STATIC) { - /* entry wasn't a static entry, cannot remove it */ - return ERR_ARG; - } - /* entry found, free it */ - etharp_free_entry(i); - return ERR_OK; -} -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - -/** - * Remove all ARP table entries of the specified netif. - * - * @param netif points to a network interface - */ -void ICACHE_FLASH_ATTR -etharp_cleanup_netif(struct netif *netif) -{ - u8_t i; - - for (i = 0; i < ARP_TABLE_SIZE; ++i) { - u8_t state = arp_table[i].state; - if ((state != ETHARP_STATE_EMPTY) && (arp_table[i].netif == netif)) { - etharp_free_entry(i); - } - } -} - -/** - * Finds (stable) ethernet/IP address pair from ARP table - * using interface and IP address index. - * @note the addresses in the ARP table are in network order! - * - * @param netif points to interface index - * @param ipaddr points to the (network order) IP address index - * @param eth_ret points to return pointer - * @param ip_ret points to return pointer - * @return table index if found, -1 otherwise - */ -s8_t ICACHE_FLASH_ATTR -etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr, - struct eth_addr **eth_ret, ip_addr_t **ip_ret) -{ - s8_t i; - - LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL", - eth_ret != NULL && ip_ret != NULL); - - LWIP_UNUSED_ARG(netif); - - i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY); - if((i >= 0) && (arp_table[i].state >= ETHARP_STATE_STABLE)) { - *eth_ret = &arp_table[i].ethaddr; - *ip_ret = &arp_table[i].ipaddr; - return i; - } - return -1; -} - -#if ETHARP_TRUST_IP_MAC -/** - * Updates the ARP table using the given IP packet. - * - * Uses the incoming IP packet's source address to update the - * ARP cache for the local network. The function does not alter - * or free the packet. This function must be called before the - * packet p is passed to the IP layer. - * - * @param netif The lwIP network interface on which the IP packet pbuf arrived. - * @param p The IP packet that arrived on netif. - * - * @return NULL - * - * @see pbuf_free() - */ -static void ICACHE_FLASH_ATTR -etharp_ip_input(struct netif *netif, struct pbuf *p) -{ - struct eth_hdr *ethhdr; - struct ip_hdr *iphdr; - ip_addr_t iphdr_src; - LWIP_ERROR("netif != NULL", (netif != NULL), return;); - - /* Only insert an entry if the source IP address of the - incoming IP packet comes from a host on the local network. */ - ethhdr = (struct eth_hdr *)p->payload; - iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); -#if ETHARP_SUPPORT_VLAN - if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) { - iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); - } -#endif /* ETHARP_SUPPORT_VLAN */ - - ip_addr_copy(iphdr_src, iphdr->src); - - /* source is not on the local network? */ - if (!ip_addr_netcmp(&iphdr_src, &(netif->ip_addr), &(netif->netmask))) { - /* do nothing */ - return; - } - - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n")); - /* update the source IP address in the cache, if present */ - /* @todo We could use ETHARP_FLAG_TRY_HARD if we think we are going to talk - * back soon (for example, if the destination IP address is ours. */ - etharp_update_arp_entry(netif, &iphdr_src, &(ethhdr->src), ETHARP_FLAG_FIND_ONLY); -} -#endif /* ETHARP_TRUST_IP_MAC */ - -/** - * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache - * send out queued IP packets. Updates cache with snooped address pairs. - * - * Should be called for incoming ARP packets. The pbuf in the argument - * is freed by this function. - * - * @param netif The lwIP network interface on which the ARP packet pbuf arrived. - * @param ethaddr Ethernet address of netif. - * @param p The ARP packet that arrived on netif. Is freed by this function. - * - * @return NULL - * - * @see pbuf_free() - */ -static void ICACHE_FLASH_ATTR -etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) -{ - struct etharp_hdr *hdr; - struct eth_hdr *ethhdr; - /* these are aligned properly, whereas the ARP header fields might not be */ - ip_addr_t sipaddr, dipaddr; - u8_t for_us; -#if LWIP_AUTOIP - const u8_t * ethdst_hwaddr; -#endif /* LWIP_AUTOIP */ - - LWIP_ERROR("netif != NULL", (netif != NULL), return;); - - /* drop short ARP packets: we have to check for p->len instead of p->tot_len here - since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */ - if (p->len < SIZEOF_ETHARP_PACKET) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, - (s16_t)SIZEOF_ETHARP_PACKET)); - ETHARP_STATS_INC(etharp.lenerr); - ETHARP_STATS_INC(etharp.drop); - pbuf_free(p); - return; - } - - ethhdr = (struct eth_hdr *)p->payload; - hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); -#if ETHARP_SUPPORT_VLAN - if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) { - hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); - } -#endif /* ETHARP_SUPPORT_VLAN */ - - /* RFC 826 "Packet Reception": */ - if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) || - (hdr->hwlen != ETHARP_HWADDR_LEN) || - (hdr->protolen != sizeof(ip_addr_t)) || - (hdr->proto != PP_HTONS(ETHTYPE_IP))) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n", - hdr->hwtype, hdr->hwlen, hdr->proto, hdr->protolen)); - ETHARP_STATS_INC(etharp.proterr); - ETHARP_STATS_INC(etharp.drop); - pbuf_free(p); - return; - } - ETHARP_STATS_INC(etharp.recv); - -#if LWIP_AUTOIP - /* We have to check if a host already has configured our random - * created link local address and continously check if there is - * a host with this IP-address so we can detect collisions */ - autoip_arp_reply(netif, hdr); -#endif /* LWIP_AUTOIP */ - - /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without - * structure packing (not using structure copy which breaks strict-aliasing rules). */ - IPADDR2_COPY(&sipaddr, &hdr->sipaddr); - IPADDR2_COPY(&dipaddr, &hdr->dipaddr); - - /* this interface is not configured? */ - if (ip_addr_isany(&netif->ip_addr)) { - for_us = 0; - } else { - /* ARP packet directed to us? */ - for_us = (u8_t)ip_addr_cmp(&dipaddr, &(netif->ip_addr)); - } - - /* ARP message directed to us? - -> add IP address in ARP cache; assume requester wants to talk to us, - can result in directly sending the queued packets for this host. - ARP message not directed to us? - -> update the source IP address in the cache, if present */ - etharp_update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), - for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY); - - /* now act on the message itself */ - switch (hdr->opcode) { - /* ARP request? */ - case PP_HTONS(ARP_REQUEST): - /* ARP request. If it asked for our address, we send out a - * reply. In any case, we time-stamp any existing ARP entry, - * and possiby send out an IP packet that was queued on it. */ - - LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP request\n")); - /* ARP request for our address? */ - if (for_us) { - - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n")); - /* Re-use pbuf to send ARP reply. - Since we are re-using an existing pbuf, we can't call etharp_raw since - that would allocate a new pbuf. */ - hdr->opcode = htons(ARP_REPLY); - - IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr); - IPADDR2_COPY(&hdr->sipaddr, &netif->ip_addr); - - LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", - (netif->hwaddr_len == ETHARP_HWADDR_LEN)); -#if LWIP_AUTOIP - /* If we are using Link-Local, all ARP packets that contain a Link-Local - * 'sender IP address' MUST be sent using link-layer broadcast instead of - * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ - ethdst_hwaddr = ip_addr_islinklocal(&netif->ip_addr) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr; -#endif /* LWIP_AUTOIP */ - - ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr); -#if LWIP_AUTOIP - ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr); -#else /* LWIP_AUTOIP */ - ETHADDR16_COPY(ðhdr->dest, &hdr->shwaddr); -#endif /* LWIP_AUTOIP */ - ETHADDR16_COPY(&hdr->shwaddr, ethaddr); - ETHADDR16_COPY(ðhdr->src, ethaddr); - - /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header - are already correct, we tested that before */ - - /* return ARP reply */ - netif->linkoutput(netif, p); - /* we are not configured? */ - } else if (ip_addr_isany(&netif->ip_addr)) { - /* { for_us == 0 and netif->ip_addr.addr == 0 } */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n")); - /* request was not directed to us */ - } else { - /* { for_us == 0 and netif->ip_addr.addr != 0 } */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n")); - } - break; - case PP_HTONS(ARP_REPLY): - /* ARP reply. We already updated the ARP cache earlier. */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n")); -#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) - /* DHCP wants to know about ARP replies from any host with an - * IP address also offered to us by the DHCP server. We do not - * want to take a duplicate IP address on a single network. - * @todo How should we handle redundant (fail-over) interfaces? */ - dhcp_arp_reply(netif, &sipaddr); -#endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */ - break; - default: - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode))); - ETHARP_STATS_INC(etharp.err); - break; - } - /* free ARP packet */ - pbuf_free(p); -} - -/** Just a small helper function that sends a pbuf to an ethernet address - * in the arp_table specified by the index 'arp_idx'. - */ -static err_t ICACHE_FLASH_ATTR -etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx) -{ - LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE", - arp_table[arp_idx].state >= ETHARP_STATE_STABLE); - /* if arp table entry is about to expire: re-request it, - but only if its state is ETHARP_STATE_STABLE to prevent flooding the - network with ARP requests if this address is used frequently. */ - if ((arp_table[arp_idx].state == ETHARP_STATE_STABLE) && - (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED)) { - if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) { - arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING; - } - } - - return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), - &arp_table[arp_idx].ethaddr); -} - -/** - * Resolve and fill-in Ethernet address header for outgoing IP packet. - * - * For IP multicast and broadcast, corresponding Ethernet addresses - * are selected and the packet is transmitted on the link. - * - * For unicast addresses, the packet is submitted to etharp_query(). In - * case the IP address is outside the local network, the IP address of - * the gateway is used. - * - * @param netif The lwIP network interface which the IP packet will be sent on. - * @param q The pbuf(s) containing the IP packet to be sent. - * @param ipaddr The IP address of the packet destination. - * - * @return - * - ERR_RTE No route to destination (no gateway to external networks), - * or the return type of either etharp_query() or etharp_send_ip(). - */ -err_t ICACHE_FLASH_ATTR -etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr) -{ - struct eth_addr *dest; - struct eth_addr mcastaddr; - ip_addr_t *dst_addr = ipaddr; - - LWIP_ASSERT("netif != NULL", netif != NULL); - LWIP_ASSERT("q != NULL", q != NULL); - LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); - - /* make room for Ethernet header - should not fail */ - if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { - /* bail out */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("etharp_output: could not allocate room for header.\n")); - LINK_STATS_INC(link.lenerr); - return ERR_BUF; - } - - /* Determine on destination hardware address. Broadcasts and multicasts - * are special, other IP addresses are looked up in the ARP table. */ - - /* broadcast destination IP address? */ - if (ip_addr_isbroadcast(ipaddr, netif)) { - /* broadcast on Ethernet also */ - dest = (struct eth_addr *)ðbroadcast; - /* multicast destination IP address? */ - } else if (ip_addr_ismulticast(ipaddr)) { - /* Hash IP multicast address to MAC address.*/ - mcastaddr.addr[0] = LL_MULTICAST_ADDR_0; - mcastaddr.addr[1] = LL_MULTICAST_ADDR_1; - mcastaddr.addr[2] = LL_MULTICAST_ADDR_2; - mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f; - mcastaddr.addr[4] = ip4_addr3(ipaddr); - mcastaddr.addr[5] = ip4_addr4(ipaddr); - /* destination Ethernet address is multicast */ - dest = &mcastaddr; - /* unicast destination IP address? */ - } else { - s8_t i; - /* outside local network? if so, this can neither be a global broadcast nor - a subnet broadcast. */ - if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask)) && - !ip_addr_islinklocal(ipaddr)) { -#if LWIP_AUTOIP - struct ip_hdr *iphdr = (struct ip_hdr*)((u8_t*)q->payload + - sizeof(struct eth_hdr)); - /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with - a link-local source address must always be "directly to its destination - on the same physical link. The host MUST NOT send the packet to any - router for forwarding". */ - if (!ip_addr_islinklocal(&iphdr->src)) -#endif /* LWIP_AUTOIP */ - { - /* interface has default gateway? */ - if (!ip_addr_isany(&netif->gw)) { - /* send to hardware address of default gateway IP address */ - dst_addr = &(netif->gw); - /* no default gateway available */ - } else { - /* no route to destination error (default gateway missing) */ - return ERR_RTE; - } - } - } -#if LWIP_NETIF_HWADDRHINT - if (netif->addr_hint != NULL) { - /* per-pcb cached entry was given */ - u8_t etharp_cached_entry = *(netif->addr_hint); - if (etharp_cached_entry < ARP_TABLE_SIZE) { -#endif /* LWIP_NETIF_HWADDRHINT */ - if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) && - (ip_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) { - /* the per-pcb-cached entry is stable and the right one! */ - ETHARP_STATS_INC(etharp.cachehit); - return etharp_output_to_arp_index(netif, q, etharp_cached_entry); - } -#if LWIP_NETIF_HWADDRHINT - } - } -#endif /* LWIP_NETIF_HWADDRHINT */ - - /* find stable entry: do this here since this is a critical path for - throughput and etharp_find_entry() is kind of slow */ - for (i = 0; i < ARP_TABLE_SIZE; i++) { - if ((arp_table[i].state >= ETHARP_STATE_STABLE) && - (ip_addr_cmp(dst_addr, &arp_table[i].ipaddr))) { - /* found an existing, stable entry */ - ETHARP_SET_HINT(netif, i); - return etharp_output_to_arp_index(netif, q, i); - } - } - /* no stable entry found, use the (slower) query function: - queue on destination Ethernet address belonging to ipaddr */ - return etharp_query(netif, dst_addr, q); - } - - /* continuation for multicast/broadcast destinations */ - /* obtain source Ethernet address of the given interface */ - /* send packet directly on the link */ - return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), dest); -} - -/** - * Send an ARP request for the given IP address and/or queue a packet. - * - * If the IP address was not yet in the cache, a pending ARP cache entry - * is added and an ARP request is sent for the given address. The packet - * is queued on this entry. - * - * If the IP address was already pending in the cache, a new ARP request - * is sent for the given address. The packet is queued on this entry. - * - * If the IP address was already stable in the cache, and a packet is - * given, it is directly sent and no ARP request is sent out. - * - * If the IP address was already stable in the cache, and no packet is - * given, an ARP request is sent out. - * - * @param netif The lwIP network interface on which ipaddr - * must be queried for. - * @param ipaddr The IP address to be resolved. - * @param q If non-NULL, a pbuf that must be delivered to the IP address. - * q is not freed by this function. - * - * @note q must only be ONE packet, not a packet queue! - * - * @return - * - ERR_BUF Could not make room for Ethernet header. - * - ERR_MEM Hardware address unknown, and no more ARP entries available - * to query for address or queue the packet. - * - ERR_MEM Could not queue packet due to memory shortage. - * - ERR_RTE No route to destination (no gateway to external networks). - * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. - * - */ -err_t ICACHE_FLASH_ATTR -etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q) -{ - struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr; - err_t result = ERR_MEM; - s8_t i; /* ARP entry index */ - - /* non-unicast address? */ - if (ip_addr_isbroadcast(ipaddr, netif) || - ip_addr_ismulticast(ipaddr) || - ip_addr_isany(ipaddr)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n")); - return ERR_ARG; - } - - /* find entry in ARP cache, ask to create entry if queueing packet */ - i = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD); - - /* could not find or create entry? */ - if (i < 0) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n")); - if (q) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n")); - ETHARP_STATS_INC(etharp.memerr); - } - return (err_t)i; - } - - /* mark a fresh entry as pending (we just sent a request) */ - if (arp_table[i].state == ETHARP_STATE_EMPTY) { - arp_table[i].state = ETHARP_STATE_PENDING; - } - - /* { i is either a STABLE or (new or existing) PENDING entry } */ - LWIP_ASSERT("arp_table[i].state == PENDING or STABLE", - ((arp_table[i].state == ETHARP_STATE_PENDING) || - (arp_table[i].state >= ETHARP_STATE_STABLE))); - - /* do we have a pending entry? or an implicit query request? */ - if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) { - /* try to resolve it; send out ARP request */ - result = etharp_request(netif, ipaddr); - if (result != ERR_OK) { - /* ARP request couldn't be sent */ - /* We don't re-send arp request in etharp_tmr, but we still queue packets, - since this failure could be temporary, and the next packet calling - etharp_query again could lead to sending the queued packets. */ - } - if (q == NULL) { - return result; - } - } - - /* packet given? */ - LWIP_ASSERT("q != NULL", q != NULL); - /* stable entry? */ - if (arp_table[i].state >= ETHARP_STATE_STABLE) { - /* we have a valid IP->Ethernet address mapping */ - ETHARP_SET_HINT(netif, i); - /* send the packet */ - result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr)); - /* pending entry? (either just created or already pending */ - } else if (arp_table[i].state == ETHARP_STATE_PENDING) { - /* entry is still pending, queue the given packet 'q' */ - struct pbuf *p; - int copy_needed = 0; - /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but - * to copy the whole queue into a new PBUF_RAM (see bug #11400) - * PBUF_ROMs can be left as they are, since ROM must not get changed. */ - p = q; - while (p) { - LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0)); - if(p->type != PBUF_ROM) { - copy_needed = 1; - break; - } - p = p->next; - } - if(copy_needed) { - /* copy the whole packet into new pbufs */ - p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); - if(p != NULL) { - if (pbuf_copy(p, q) != ERR_OK) { - pbuf_free(p); - p = NULL; - } - } - } else { - /* referencing the old pbuf is enough */ - p = q; - pbuf_ref(p); - } - /* packet could be taken over? */ - if (p != NULL) { - /* queue packet ... */ -#if ARP_QUEUEING - struct etharp_q_entry *new_entry; - /* allocate a new arp queue entry */ - new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE); - if (new_entry != NULL) { - new_entry->next = 0; - new_entry->p = p; - if(arp_table[i].q != NULL) { - /* queue was already existent, append the new entry to the end */ - struct etharp_q_entry *r; - r = arp_table[i].q; - while (r->next != NULL) { - r = r->next; - } - r->next = new_entry; - } else { - /* queue did not exist, first item in queue */ - arp_table[i].q = new_entry; - } - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); - result = ERR_OK; - } else { - /* the pool MEMP_ARP_QUEUE is empty */ - pbuf_free(p); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); - result = ERR_MEM; - } -#else /* ARP_QUEUEING */ - /* always queue one packet per ARP request only, freeing a previously queued packet */ - if (arp_table[i].q != NULL) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); - pbuf_free(arp_table[i].q); - } - arp_table[i].q = p; - result = ERR_OK; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); -#endif /* ARP_QUEUEING */ - } else { - ETHARP_STATS_INC(etharp.memerr); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); - result = ERR_MEM; - } - } - return result; -} - -/** - * Send a raw ARP packet (opcode and all addresses can be modified) - * - * @param netif the lwip network interface on which to send the ARP packet - * @param ethsrc_addr the source MAC address for the ethernet header - * @param ethdst_addr the destination MAC address for the ethernet header - * @param hwsrc_addr the source MAC address for the ARP protocol header - * @param ipsrc_addr the source IP address for the ARP protocol header - * @param hwdst_addr the destination MAC address for the ARP protocol header - * @param ipdst_addr the destination IP address for the ARP protocol header - * @param opcode the type of the ARP packet - * @return ERR_OK if the ARP packet has been sent - * ERR_MEM if the ARP packet couldn't be allocated - * any other err_t on failure - */ -#if !LWIP_AUTOIP -static -#endif /* LWIP_AUTOIP */ -err_t ICACHE_FLASH_ATTR -etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, - const struct eth_addr *ethdst_addr, - const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr, - const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr, - const u16_t opcode) -{ - struct pbuf *p; - err_t result = ERR_OK; - struct eth_hdr *ethhdr; - struct etharp_hdr *hdr; -#if LWIP_AUTOIP - const u8_t * ethdst_hwaddr; -#endif /* LWIP_AUTOIP */ - - LWIP_ASSERT("netif != NULL", netif != NULL); - - /* allocate a pbuf for the outgoing ARP request packet */ - p = pbuf_alloc(PBUF_RAW, SIZEOF_ETHARP_PACKET, PBUF_RAM); - /* could allocate a pbuf for an ARP request? */ - if (p == NULL) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("etharp_raw: could not allocate pbuf for ARP request.\n")); - ETHARP_STATS_INC(etharp.memerr); - return ERR_MEM; - } - LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr", - (p->len >= SIZEOF_ETHARP_PACKET)); - - ethhdr = (struct eth_hdr *)p->payload; - hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n")); - hdr->opcode = htons(opcode); - - LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", - (netif->hwaddr_len == ETHARP_HWADDR_LEN)); -#if LWIP_AUTOIP - /* If we are using Link-Local, all ARP packets that contain a Link-Local - * 'sender IP address' MUST be sent using link-layer broadcast instead of - * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ - ethdst_hwaddr = ip_addr_islinklocal(ipsrc_addr) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr; -#endif /* LWIP_AUTOIP */ - /* Write the ARP MAC-Addresses */ - ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr); - ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr); - /* Write the Ethernet MAC-Addresses */ -#if LWIP_AUTOIP - ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr); -#else /* LWIP_AUTOIP */ - ETHADDR16_COPY(ðhdr->dest, ethdst_addr); -#endif /* LWIP_AUTOIP */ - ETHADDR16_COPY(ðhdr->src, ethsrc_addr); - /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without - * structure packing. */ - IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr); - IPADDR2_COPY(&hdr->dipaddr, ipdst_addr); - - hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET); - hdr->proto = PP_HTONS(ETHTYPE_IP); - /* set hwlen and protolen */ - hdr->hwlen = ETHARP_HWADDR_LEN; - hdr->protolen = sizeof(ip_addr_t); - - ethhdr->type = PP_HTONS(ETHTYPE_ARP); - /* send ARP query */ - result = netif->linkoutput(netif, p); - ETHARP_STATS_INC(etharp.xmit); - /* free ARP query packet */ - pbuf_free(p); - p = NULL; - /* could not allocate pbuf for ARP request */ - - return result; -} - -/** - * Send an ARP request packet asking for ipaddr. - * - * @param netif the lwip network interface on which to send the request - * @param ipaddr the IP address for which to ask - * @return ERR_OK if the request has been sent - * ERR_MEM if the ARP packet couldn't be allocated - * any other err_t on failure - */ -err_t ICACHE_FLASH_ATTR -etharp_request(struct netif *netif, ip_addr_t *ipaddr) -{ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n")); - return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, - (struct eth_addr *)netif->hwaddr, &netif->ip_addr, ðzero, - ipaddr, ARP_REQUEST); -} -#endif /* LWIP_ARP */ - -/** - * Process received ethernet frames. Using this function instead of directly - * calling ip_input and passing ARP frames through etharp in ethernetif_input, - * the ARP cache is protected from concurrent access. - * - * @param p the recevied packet, p->payload pointing to the ethernet header - * @param netif the network interface on which the packet was received - */ -err_t ICACHE_FLASH_ATTR -ethernet_input(struct pbuf *p, struct netif *netif) -{ - struct eth_hdr* ethhdr; - u16_t type; -#if LWIP_ARP || ETHARP_SUPPORT_VLAN - s16_t ip_hdr_offset = SIZEOF_ETH_HDR; -#endif /* LWIP_ARP || ETHARP_SUPPORT_VLAN */ - - if (p->len <= SIZEOF_ETH_HDR) { - /* a packet with only an ethernet header (or less) is not valid for us */ - ETHARP_STATS_INC(etharp.proterr); - ETHARP_STATS_INC(etharp.drop); - goto free_and_return; - } - - /* points to packet payload, which starts with an Ethernet header */ - ethhdr = (struct eth_hdr *)p->payload; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, - ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n", - (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2], - (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5], - (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2], - (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5], - (unsigned)htons(ethhdr->type))); - - type = ethhdr->type; -#if ETHARP_SUPPORT_VLAN - if (type == PP_HTONS(ETHTYPE_VLAN)) { - struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR); - if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) { - /* a packet with only an ethernet/vlan header (or less) is not valid for us */ - ETHARP_STATS_INC(etharp.proterr); - ETHARP_STATS_INC(etharp.drop); - goto free_and_return; - } -#if defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */ -#ifdef ETHARP_VLAN_CHECK_FN - if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) { -#elif defined(ETHARP_VLAN_CHECK) - if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { -#endif - /* silently ignore this packet: not for our VLAN */ - pbuf_free(p); - return ERR_OK; - } -#endif /* defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */ - type = vlan->tpid; - ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR; - } -#endif /* ETHARP_SUPPORT_VLAN */ - -#if LWIP_ARP_FILTER_NETIF - netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type)); -#endif /* LWIP_ARP_FILTER_NETIF*/ - - if (ethhdr->dest.addr[0] & 1) { - /* this might be a multicast or broadcast packet */ - if (ethhdr->dest.addr[0] == LL_MULTICAST_ADDR_0) { - if ((ethhdr->dest.addr[1] == LL_MULTICAST_ADDR_1) && - (ethhdr->dest.addr[2] == LL_MULTICAST_ADDR_2)) { - /* mark the pbuf as link-layer multicast */ - p->flags |= PBUF_FLAG_LLMCAST; - } - } else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) { - /* mark the pbuf as link-layer broadcast */ - p->flags |= PBUF_FLAG_LLBCAST; - } - } - - switch (type) { -#if LWIP_ARP - /* IP packet? */ - case PP_HTONS(ETHTYPE_IP): - if (!(netif->flags & NETIF_FLAG_ETHARP)) { - goto free_and_return; - } -#if ETHARP_TRUST_IP_MAC - /* update ARP table */ - etharp_ip_input(netif, p); -#endif /* ETHARP_TRUST_IP_MAC */ - /* skip Ethernet header */ - if(pbuf_header(p, -ip_hdr_offset)) { - LWIP_ASSERT("Can't move over header in packet", 0); - goto free_and_return; - } else { - /* pass to IP layer */ - ip_input(p, netif); - } - break; - - case PP_HTONS(ETHTYPE_ARP): - if (!(netif->flags & NETIF_FLAG_ETHARP)) { - goto free_and_return; - } - /* pass p to ARP module */ - etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p); - break; -#endif /* LWIP_ARP */ -#if PPPOE_SUPPORT - case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */ - pppoe_disc_input(netif, p); - break; - - case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */ - pppoe_data_input(netif, p); - break; -#endif /* PPPOE_SUPPORT */ - -#if LWIP_IPV6 - case PP_HTONS(ETHTYPE_IPV6): /* IPv6 */ - /* skip Ethernet header */ - if(pbuf_header(p, -(s16_t)SIZEOF_ETH_HDR)) { - LWIP_ASSERT("Can't move over header in packet", 0); - goto free_and_return; - } else { - /* pass to IPv6 layer */ - ip6_input(p, netif); - } - break; -#endif /* LWIP_IPV6 */ - - default: - ETHARP_STATS_INC(etharp.proterr); - ETHARP_STATS_INC(etharp.drop); - goto free_and_return; - } - - /* This means the pbuf is freed or consumed, - so the caller doesn't have to free it again */ - return ERR_OK; - -free_and_return: - pbuf_free(p); - return ERR_OK; -} -#endif /* LWIP_ARP || LWIP_ETHERNET */ diff --git a/third_party/lwip/netif/ethernetif.c b/third_party/lwip/netif/ethernetif.c deleted file mode 100644 index 5f6d5f8..0000000 --- a/third_party/lwip/netif/ethernetif.c +++ /dev/null @@ -1,220 +0,0 @@ -/** - * @file - * Ethernet Interface Skeleton - * - */ - -/* - * 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 - * - */ - -#include "lwip/opt.h" - -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/ethip6.h" -#include "netif/etharp.h" -#include "netif/ppp_oe.h" - -/* Define those to better describe your network interface. */ -#define IFNAME0 'e' -#define IFNAME1 'n' - -/** - * In this function, the hardware should be initialized. - * Called from ethernetif_init(). - * - * @param netif the already initialized lwip network interface structure - * for this ethernetif - */ -static void ICACHE_FLASH_ATTR -low_level_init(struct netif *netif) -{ - /* set MAC hardware address length */ - netif->hwaddr_len = ETHARP_HWADDR_LEN; - - /* set MAC hardware address */ - - /* maximum transfer unit */ - netif->mtu = 1500; - - /* device capabilities */ - /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; - - /* Do whatever else is needed to initialize interface. */ -} - -/** - * This function 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. - * - * @param netif the lwip network interface structure for this ethernetif - * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) - * @return ERR_OK if the packet could be sent - * an err_t value if the packet couldn't be sent - * - * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to - * strange results. You might consider waiting for space in the DMA queue - * to become availale since the stack doesn't retry to send a packet - * dropped because of memory failure (except for the TCP timers). - */ - -static err_t ICACHE_FLASH_ATTR -low_level_output(struct netif *netif, struct pbuf *p) -{ - struct ethernetif *ethernetif = netif->state; - struct pbuf *q; - -// initiate transfer(); - -#if ETH_PAD_SIZE - pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ -#endif - - struct pbuf *tmp; - 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); - tmp = q->next; - - ieee80211_output_pbuf(netif, q); - q->next = tmp; - } - -// signal that packet should be sent(); - -#if ETH_PAD_SIZE - pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ -#endif - - LINK_STATS_INC(link.xmit); - - return ERR_OK; -} - -/** - * 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. Then the type of the received packet is determined and - * the appropriate input function is called. - * - * @param netif the lwip network interface structure for this ethernetif - */ -void ICACHE_FLASH_ATTR -ethernetif_input(struct netif *netif, struct pbuf *p) -{ - struct ethernetif *ethernetif; - struct eth_hdr *ethhdr; - - ethernetif = netif->state; - - /* points to packet payload, which starts with an Ethernet header */ - ethhdr = p->payload; - - switch (htons(ethhdr->type)) { - /* IP or ARP packet? */ - case ETHTYPE_IP: - case ETHTYPE_IPV6: - 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); - p = NULL; - break; - } -} - -/** - * 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. - * - * This function should be passed as a parameter to netif_add(). - * - * @param netif the lwip network interface structure for this ethernetif - * @return ERR_OK if the loopif is initialized - * ERR_MEM if private data couldn't be allocated - * any other err_t on error - */ -err_t ICACHE_FLASH_ATTR -ethernetif_init(struct netif *netif) -{ - LWIP_ASSERT("netif != NULL", (netif != NULL)); - -#if LWIP_NETIF_HOSTNAME - /* Initialize interface hostname */ - netif->hostname = "lwip"; -#endif /* LWIP_NETIF_HOSTNAME */ - - /* - * Initialize the snmp variables and counters inside the struct netif. - * The last argument should be replaced with your link speed, in units - * of bits per second. - */ - NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); - - netif->name[0] = IFNAME0; - netif->name[1] = IFNAME1; - /* We directly use etharp_output() here to save a function call. - * You can instead declare your own function an call etharp_output() - * from it if you have to do some checks before sending (e.g. if link - * is available...) */ - netif->output = etharp_output; -#if LWIP_IPV6 - netif->output_ip6 = ethip6_output; -#endif /* LWIP_IPV6 */ - netif->linkoutput = low_level_output; - - /* initialize the hardware */ - low_level_init(netif); - - return ERR_OK; -} diff --git a/third_party/lwip/netif/ppp/auth.c b/third_party/lwip/netif/ppp/auth.c deleted file mode 100644 index 0b0885d..0000000 --- a/third_party/lwip/netif/ppp/auth.c +++ /dev/null @@ -1,1334 +0,0 @@ -/***************************************************************************** -* auth.c - Network Authentication and Phase Control program file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* Copyright (c) 1997 by Global Election Systems Inc. All rights reserved. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-12-08 Guy Lancaster , Global Election Systems Inc. -* Ported from public pppd code. -*****************************************************************************/ -/* - * auth.c - PPP authentication and phase control. - * - * Copyright (c) 1993 The Australian National University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the Australian National University. The name of the University - * may not be used to endorse or promote products derived from this - * software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#include "lwip/opt.h" - -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "ppp_impl.h" -#include "pppdebug.h" - -#include "fsm.h" -#include "lcp.h" -#include "pap.h" -#include "chap.h" -#include "auth.h" -#include "ipcp.h" - -#if CBCP_SUPPORT -#include "cbcp.h" -#endif /* CBCP_SUPPORT */ - -#include "lwip/inet.h" - -#include - -#if 0 /* UNUSED */ -/* Bits in scan_authfile return value */ -#define NONWILD_SERVER 1 -#define NONWILD_CLIENT 2 - -#define ISWILD(word) (word[0] == '*' && word[1] == 0) -#endif /* UNUSED */ - -#if PAP_SUPPORT || CHAP_SUPPORT -/* The name by which the peer authenticated itself to us. */ -static char peer_authname[MAXNAMELEN]; -#endif /* PAP_SUPPORT || CHAP_SUPPORT */ - -/* Records which authentication operations haven't completed yet. */ -static int auth_pending[NUM_PPP]; - -/* Set if we have successfully called plogin() */ -static int logged_in; - -/* Set if we have run the /etc/ppp/auth-up script. */ -static int did_authup; /* @todo, we don't need this in lwip*/ - -/* List of addresses which the peer may use. */ -static struct wordlist *addresses[NUM_PPP]; - -#if 0 /* UNUSED */ -/* Wordlist giving addresses which the peer may use - without authenticating itself. */ -static struct wordlist *noauth_addrs; - -/* Extra options to apply, from the secrets file entry for the peer. */ -static struct wordlist *extra_options; -#endif /* UNUSED */ - -/* Number of network protocols which we have opened. */ -static int num_np_open; - -/* Number of network protocols which have come up. */ -static int num_np_up; - -#if PAP_SUPPORT || CHAP_SUPPORT -/* Set if we got the contents of passwd[] from the pap-secrets file. */ -static int passwd_from_file; -#endif /* PAP_SUPPORT || CHAP_SUPPORT */ - -#if 0 /* UNUSED */ -/* Set if we require authentication only because we have a default route. */ -static bool default_auth; - -/* Hook to enable a plugin to control the idle time limit */ -int (*idle_time_hook) __P((struct ppp_idle *)) = NULL; - -/* Hook for a plugin to say whether we can possibly authenticate any peer */ -int (*pap_check_hook) __P((void)) = NULL; - -/* Hook for a plugin to check the PAP user and password */ -int (*pap_auth_hook) __P((char *user, char *passwd, char **msgp, - struct wordlist **paddrs, - struct wordlist **popts)) = NULL; - -/* Hook for a plugin to know about the PAP user logout */ -void (*pap_logout_hook) __P((void)) = NULL; - -/* Hook for a plugin to get the PAP password for authenticating us */ -int (*pap_passwd_hook) __P((char *user, char *passwd)) = NULL; - -/* - * This is used to ensure that we don't start an auth-up/down - * script while one is already running. - */ -enum script_state { - s_down, - s_up -}; - -static enum script_state auth_state = s_down; -static enum script_state auth_script_state = s_down; -static pid_t auth_script_pid = 0; - -/* - * Option variables. - * lwip: some of these are present in the ppp_settings structure - */ -bool uselogin = 0; /* Use /etc/passwd for checking PAP */ -bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */ -bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */ -bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */ -bool usehostname = 0; /* Use hostname for our_name */ -bool auth_required = 0; /* Always require authentication from peer */ -bool allow_any_ip = 0; /* Allow peer to use any IP address */ -bool explicit_remote = 0; /* User specified explicit remote name */ -char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ - -#endif /* UNUSED */ - -/* Bits in auth_pending[] */ -#define PAP_WITHPEER 1 -#define PAP_PEER 2 -#define CHAP_WITHPEER 4 -#define CHAP_PEER 8 - -/* @todo, move this somewhere */ -/* Used for storing a sequence of words. Usually malloced. */ -struct wordlist { - struct wordlist *next; - char word[1]; -}; - - -extern char *crypt (const char *, const char *); - -/* Prototypes for procedures local to this file. */ - -static void network_phase (int); -static void check_idle (void *); -static void connect_time_expired (void *); -#if 0 -static int plogin (char *, char *, char **, int *); -#endif -static void plogout (void); -static int null_login (int); -static int get_pap_passwd (int, char *, char *); -static int have_pap_secret (void); -static int have_chap_secret (char *, char *, u32_t); -static int ip_addr_check (u32_t, struct wordlist *); - -#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */ -static int scan_authfile (FILE *, char *, char *, char *, - struct wordlist **, struct wordlist **, - char *); -static void free_wordlist (struct wordlist *); -static void auth_script (char *); -static void auth_script_done (void *); -static void set_allowed_addrs (int unit, struct wordlist *addrs); -static int some_ip_ok (struct wordlist *); -static int setupapfile (char **); -static int privgroup (char **); -static int set_noauth_addr (char **); -static void check_access (FILE *, char *); -#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ - -#if 0 /* UNUSED */ -/* - * Authentication-related options. - */ -option_t auth_options[] = { - { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap, - "Require PAP authentication from peer", 1, &auth_required }, - { "+pap", o_bool, &lcp_wantoptions[0].neg_upap, - "Require PAP authentication from peer", 1, &auth_required }, - { "refuse-pap", o_bool, &refuse_pap, - "Don't agree to auth to peer with PAP", 1 }, - { "-pap", o_bool, &refuse_pap, - "Don't allow PAP authentication with peer", 1 }, - { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap, - "Require CHAP authentication from peer", 1, &auth_required }, - { "+chap", o_bool, &lcp_wantoptions[0].neg_chap, - "Require CHAP authentication from peer", 1, &auth_required }, - { "refuse-chap", o_bool, &refuse_chap, - "Don't agree to auth to peer with CHAP", 1 }, - { "-chap", o_bool, &refuse_chap, - "Don't allow CHAP authentication with peer", 1 }, - { "name", o_string, our_name, - "Set local name for authentication", - OPT_PRIV|OPT_STATIC, NULL, MAXNAMELEN }, - { "user", o_string, user, - "Set name for auth with peer", OPT_STATIC, NULL, MAXNAMELEN }, - { "usehostname", o_bool, &usehostname, - "Must use hostname for authentication", 1 }, - { "remotename", o_string, remote_name, - "Set remote name for authentication", OPT_STATIC, - &explicit_remote, MAXNAMELEN }, - { "auth", o_bool, &auth_required, - "Require authentication from peer", 1 }, - { "noauth", o_bool, &auth_required, - "Don't require peer to authenticate", OPT_PRIV, &allow_any_ip }, - { "login", o_bool, &uselogin, - "Use system password database for PAP", 1 }, - { "papcrypt", o_bool, &cryptpap, - "PAP passwords are encrypted", 1 }, - { "+ua", o_special, (void *)setupapfile, - "Get PAP user and password from file" }, - { "password", o_string, passwd, - "Password for authenticating us to the peer", OPT_STATIC, - NULL, MAXSECRETLEN }, - { "privgroup", o_special, (void *)privgroup, - "Allow group members to use privileged options", OPT_PRIV }, - { "allow-ip", o_special, (void *)set_noauth_addr, - "Set IP address(es) which can be used without authentication", - OPT_PRIV }, - { NULL } -}; -#endif /* UNUSED */ -#if 0 /* UNUSED */ -/* - * setupapfile - specifies UPAP info for authenticating with peer. - */ -static int -setupapfile(char **argv) -{ - FILE * ufile; - int l; - - lcp_allowoptions[0].neg_upap = 1; - - /* open user info file */ - seteuid(getuid()); - ufile = fopen(*argv, "r"); - seteuid(0); - if (ufile == NULL) { - option_error("unable to open user login data file %s", *argv); - return 0; - } - check_access(ufile, *argv); - - /* get username */ - if (fgets(user, MAXNAMELEN - 1, ufile) == NULL - || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){ - option_error("unable to read user login data file %s", *argv); - return 0; - } - fclose(ufile); - - /* get rid of newlines */ - l = os_strlen(user); - if (l > 0 && user[l-1] == '\n') - user[l-1] = 0; - l = os_strlen(passwd); - if (l > 0 && passwd[l-1] == '\n') - passwd[l-1] = 0; - - return (1); -} -#endif /* UNUSED */ - -#if 0 /* UNUSED */ -/* - * privgroup - allow members of the group to have privileged access. - */ -static int -privgroup(char **argv) -{ - struct group *g; - int i; - - g = getgrnam(*argv); - if (g == 0) { - option_error("group %s is unknown", *argv); - return 0; - } - for (i = 0; i < ngroups; ++i) { - if (groups[i] == g->gr_gid) { - privileged = 1; - break; - } - } - return 1; -} -#endif - -#if 0 /* UNUSED */ -/* - * set_noauth_addr - set address(es) that can be used without authentication. - * Equivalent to specifying an entry like `"" * "" addr' in pap-secrets. - */ -static int -set_noauth_addr(char **argv) -{ - char *addr = *argv; - int l = os_strlen(addr); - struct wordlist *wp; - - wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l + 1); - if (wp == NULL) - novm("allow-ip argument"); - wp->word = (char *) (wp + 1); - wp->next = noauth_addrs; - BCOPY(addr, wp->word, l); - noauth_addrs = wp; - return 1; -} -#endif /* UNUSED */ - -/* - * An Open on LCP has requested a change from Dead to Establish phase. - * Do what's necessary to bring the physical layer up. - */ -void -link_required(int unit) -{ - LWIP_UNUSED_ARG(unit); - - AUTHDEBUG(LOG_INFO, ("link_required: %d\n", unit)); -} - -/* - * LCP has terminated the link; go to the Dead phase and take the - * physical layer down. - */ -void -link_terminated(int unit) -{ - AUTHDEBUG(LOG_INFO, ("link_terminated: %d\n", unit)); - if (lcp_phase[unit] == PHASE_DEAD) { - return; - } - if (logged_in) { - plogout(); - } - lcp_phase[unit] = PHASE_DEAD; - AUTHDEBUG(LOG_NOTICE, ("Connection terminated.\n")); - pppLinkTerminated(unit); -} - -/* - * LCP has gone down; it will either die or try to re-establish. - */ -void -link_down(int unit) -{ - int i; - struct protent *protp; - - AUTHDEBUG(LOG_INFO, ("link_down: %d\n", unit)); - - if (did_authup) { - /* XXX Do link down processing. */ - did_authup = 0; - } - for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { - if (!protp->enabled_flag) { - continue; - } - if (protp->protocol != PPP_LCP && protp->lowerdown != NULL) { - (*protp->lowerdown)(unit); - } - if (protp->protocol < 0xC000 && protp->close != NULL) { - (*protp->close)(unit, "LCP down"); - } - } - num_np_open = 0; /* number of network protocols we have opened */ - num_np_up = 0; /* Number of network protocols which have come up */ - - if (lcp_phase[unit] != PHASE_DEAD) { - lcp_phase[unit] = PHASE_TERMINATE; - } - pppLinkDown(unit); -} - -/* - * The link is established. - * Proceed to the Dead, Authenticate or Network phase as appropriate. - */ -void -link_established(int unit) -{ - int auth; - int i; - struct protent *protp; - lcp_options *wo = &lcp_wantoptions[unit]; - lcp_options *go = &lcp_gotoptions[unit]; -#if PAP_SUPPORT || CHAP_SUPPORT - lcp_options *ho = &lcp_hisoptions[unit]; -#endif /* PAP_SUPPORT || CHAP_SUPPORT */ - - AUTHDEBUG(LOG_INFO, ("link_established: unit %d; Lowering up all protocols...\n", unit)); - /* - * Tell higher-level protocols that LCP is up. - */ - for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { - if (protp->protocol != PPP_LCP && protp->enabled_flag && protp->lowerup != NULL) { - (*protp->lowerup)(unit); - } - } - if (ppp_settings.auth_required && !(go->neg_chap || go->neg_upap)) { - /* - * We wanted the peer to authenticate itself, and it refused: - * treat it as though it authenticated with PAP using a username - * of "" and a password of "". If that's not OK, boot it out. - */ - if (!wo->neg_upap || !null_login(unit)) { - AUTHDEBUG(LOG_WARNING, ("peer refused to authenticate\n")); - lcp_close(unit, "peer refused to authenticate"); - return; - } - } - - lcp_phase[unit] = PHASE_AUTHENTICATE; - auth = 0; -#if CHAP_SUPPORT - if (go->neg_chap) { - ChapAuthPeer(unit, ppp_settings.our_name, go->chap_mdtype); - auth |= CHAP_PEER; - } -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT && CHAP_SUPPORT - else -#endif /* PAP_SUPPORT && CHAP_SUPPORT */ -#if PAP_SUPPORT - if (go->neg_upap) { - upap_authpeer(unit); - auth |= PAP_PEER; - } -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - if (ho->neg_chap) { - ChapAuthWithPeer(unit, ppp_settings.user, ho->chap_mdtype); - auth |= CHAP_WITHPEER; - } -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT && CHAP_SUPPORT - else -#endif /* PAP_SUPPORT && CHAP_SUPPORT */ -#if PAP_SUPPORT - if (ho->neg_upap) { - if (ppp_settings.passwd[0] == 0) { - passwd_from_file = 1; - if (!get_pap_passwd(unit, ppp_settings.user, ppp_settings.passwd)) { - AUTHDEBUG(LOG_ERR, ("No secret found for PAP login\n")); - } - } - upap_authwithpeer(unit, ppp_settings.user, ppp_settings.passwd); - auth |= PAP_WITHPEER; - } -#endif /* PAP_SUPPORT */ - auth_pending[unit] = auth; - - if (!auth) { - network_phase(unit); - } -} - -/* - * Proceed to the network phase. - */ -static void -network_phase(int unit) -{ - int i; - struct protent *protp; - lcp_options *go = &lcp_gotoptions[unit]; - - /* - * If the peer had to authenticate, run the auth-up script now. - */ - if ((go->neg_chap || go->neg_upap) && !did_authup) { - /* XXX Do setup for peer authentication. */ - did_authup = 1; - } - -#if CBCP_SUPPORT - /* - * If we negotiated callback, do it now. - */ - if (go->neg_cbcp) { - lcp_phase[unit] = PHASE_CALLBACK; - (*cbcp_protent.open)(unit); - return; - } -#endif /* CBCP_SUPPORT */ - - lcp_phase[unit] = PHASE_NETWORK; - for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { - if (protp->protocol < 0xC000 && protp->enabled_flag && protp->open != NULL) { - (*protp->open)(unit); - if (protp->protocol != PPP_CCP) { - ++num_np_open; - } - } - } - - if (num_np_open == 0) { - /* nothing to do */ - lcp_close(0, "No network protocols running"); - } -} -/* @todo: add void start_networks(void) here (pppd 2.3.11) */ - -/* - * The peer has failed to authenticate himself using `protocol'. - */ -void -auth_peer_fail(int unit, u16_t protocol) -{ - LWIP_UNUSED_ARG(protocol); - - AUTHDEBUG(LOG_INFO, ("auth_peer_fail: %d proto=%X\n", unit, protocol)); - /* - * Authentication failure: take the link down - */ - lcp_close(unit, "Authentication failed"); -} - - -#if PAP_SUPPORT || CHAP_SUPPORT -/* - * The peer has been successfully authenticated using `protocol'. - */ -void -auth_peer_success(int unit, u16_t protocol, char *name, int namelen) -{ - int pbit; - - AUTHDEBUG(LOG_INFO, ("auth_peer_success: %d proto=%X\n", unit, protocol)); - switch (protocol) { - case PPP_CHAP: - pbit = CHAP_PEER; - break; - case PPP_PAP: - pbit = PAP_PEER; - break; - default: - AUTHDEBUG(LOG_WARNING, ("auth_peer_success: unknown protocol %x\n", protocol)); - return; - } - - /* - * Save the authenticated name of the peer for later. - */ - if (namelen > (int)sizeof(peer_authname) - 1) { - namelen = sizeof(peer_authname) - 1; - } - BCOPY(name, peer_authname, namelen); - peer_authname[namelen] = 0; - - /* - * If there is no more authentication still to be done, - * proceed to the network (or callback) phase. - */ - if ((auth_pending[unit] &= ~pbit) == 0) { - network_phase(unit); - } -} - -/* - * We have failed to authenticate ourselves to the peer using `protocol'. - */ -void -auth_withpeer_fail(int unit, u16_t protocol) -{ - int errCode = PPPERR_AUTHFAIL; - - LWIP_UNUSED_ARG(protocol); - - AUTHDEBUG(LOG_INFO, ("auth_withpeer_fail: %d proto=%X\n", unit, protocol)); - if (passwd_from_file) { - BZERO(ppp_settings.passwd, MAXSECRETLEN); - } - - /* - * We've failed to authenticate ourselves to our peer. - * He'll probably take the link down, and there's not much - * we can do except wait for that. - */ - pppIOCtl(unit, PPPCTLS_ERRCODE, &errCode); - lcp_close(unit, "Failed to authenticate ourselves to peer"); -} - -/* - * We have successfully authenticated ourselves with the peer using `protocol'. - */ -void -auth_withpeer_success(int unit, u16_t protocol) -{ - int pbit; - - AUTHDEBUG(LOG_INFO, ("auth_withpeer_success: %d proto=%X\n", unit, protocol)); - switch (protocol) { - case PPP_CHAP: - pbit = CHAP_WITHPEER; - break; - case PPP_PAP: - if (passwd_from_file) { - BZERO(ppp_settings.passwd, MAXSECRETLEN); - } - pbit = PAP_WITHPEER; - break; - default: - AUTHDEBUG(LOG_WARNING, ("auth_peer_success: unknown protocol %x\n", protocol)); - pbit = 0; - } - - /* - * If there is no more authentication still being done, - * proceed to the network (or callback) phase. - */ - if ((auth_pending[unit] &= ~pbit) == 0) { - network_phase(unit); - } -} -#endif /* PAP_SUPPORT || CHAP_SUPPORT */ - - -/* - * np_up - a network protocol has come up. - */ -void -np_up(int unit, u16_t proto) -{ - LWIP_UNUSED_ARG(unit); - LWIP_UNUSED_ARG(proto); - - AUTHDEBUG(LOG_INFO, ("np_up: %d proto=%X\n", unit, proto)); - if (num_np_up == 0) { - AUTHDEBUG(LOG_INFO, ("np_up: maxconnect=%d idle_time_limit=%d\n",ppp_settings.maxconnect,ppp_settings.idle_time_limit)); - /* - * At this point we consider that the link has come up successfully. - */ - if (ppp_settings.idle_time_limit > 0) { - TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit); - } - - /* - * Set a timeout to close the connection once the maximum - * connect time has expired. - */ - if (ppp_settings.maxconnect > 0) { - TIMEOUT(connect_time_expired, 0, ppp_settings.maxconnect); - } - } - ++num_np_up; -} - -/* - * np_down - a network protocol has gone down. - */ -void -np_down(int unit, u16_t proto) -{ - LWIP_UNUSED_ARG(unit); - LWIP_UNUSED_ARG(proto); - - AUTHDEBUG(LOG_INFO, ("np_down: %d proto=%X\n", unit, proto)); - if (--num_np_up == 0 && ppp_settings.idle_time_limit > 0) { - UNTIMEOUT(check_idle, NULL); - } -} - -/* - * np_finished - a network protocol has finished using the link. - */ -void -np_finished(int unit, u16_t proto) -{ - LWIP_UNUSED_ARG(unit); - LWIP_UNUSED_ARG(proto); - - AUTHDEBUG(LOG_INFO, ("np_finished: %d proto=%X\n", unit, proto)); - if (--num_np_open <= 0) { - /* no further use for the link: shut up shop. */ - lcp_close(0, "No network protocols running"); - } -} - -/* - * check_idle - check whether the link has been idle for long - * enough that we can shut it down. - */ -static void -check_idle(void *arg) -{ - struct ppp_idle idle; - u_short itime; - - LWIP_UNUSED_ARG(arg); - if (!get_idle_time(0, &idle)) { - return; - } - itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle); - if (itime >= ppp_settings.idle_time_limit) { - /* link is idle: shut it down. */ - AUTHDEBUG(LOG_INFO, ("Terminating connection due to lack of activity.\n")); - lcp_close(0, "Link inactive"); - } else { - TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime); - } -} - -/* - * connect_time_expired - log a message and close the connection. - */ -static void -connect_time_expired(void *arg) -{ - LWIP_UNUSED_ARG(arg); - - AUTHDEBUG(LOG_INFO, ("Connect time expired\n")); - lcp_close(0, "Connect time expired"); /* Close connection */ -} - -#if 0 /* UNUSED */ -/* - * auth_check_options - called to check authentication options. - */ -void -auth_check_options(void) -{ - lcp_options *wo = &lcp_wantoptions[0]; - int can_auth; - ipcp_options *ipwo = &ipcp_wantoptions[0]; - u32_t remote; - - /* Default our_name to hostname, and user to our_name */ - if (ppp_settings.our_name[0] == 0 || ppp_settings.usehostname) { - strcpy(ppp_settings.our_name, ppp_settings.hostname); - } - - if (ppp_settings.user[0] == 0) { - strcpy(ppp_settings.user, ppp_settings.our_name); - } - - /* If authentication is required, ask peer for CHAP or PAP. */ - if (ppp_settings.auth_required && !wo->neg_chap && !wo->neg_upap) { - wo->neg_chap = 1; - wo->neg_upap = 1; - } - - /* - * Check whether we have appropriate secrets to use - * to authenticate the peer. - */ - can_auth = wo->neg_upap && have_pap_secret(); - if (!can_auth && wo->neg_chap) { - remote = ipwo->accept_remote? 0: ipwo->hisaddr; - can_auth = have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote); - } - - if (ppp_settings.auth_required && !can_auth) { - ppp_panic("No auth secret"); - } -} -#endif /* UNUSED */ - -/* - * auth_reset - called when LCP is starting negotiations to recheck - * authentication options, i.e. whether we have appropriate secrets - * to use for authenticating ourselves and/or the peer. - */ -void -auth_reset(int unit) -{ - lcp_options *go = &lcp_gotoptions[unit]; - lcp_options *ao = &lcp_allowoptions[0]; - ipcp_options *ipwo = &ipcp_wantoptions[0]; - u32_t remote; - - AUTHDEBUG(LOG_INFO, ("auth_reset: %d\n", unit)); - ao->neg_upap = !ppp_settings.refuse_pap && (ppp_settings.passwd[0] != 0 || get_pap_passwd(unit, NULL, NULL)); - ao->neg_chap = !ppp_settings.refuse_chap && ppp_settings.passwd[0] != 0 /*have_chap_secret(ppp_settings.user, ppp_settings.remote_name, (u32_t)0)*/; - - if (go->neg_upap && !have_pap_secret()) { - go->neg_upap = 0; - } - if (go->neg_chap) { - remote = ipwo->accept_remote? 0: ipwo->hisaddr; - if (!have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote)) { - go->neg_chap = 0; - } - } -} - -#if PAP_SUPPORT -/* - * check_passwd - Check the user name and passwd against the PAP secrets - * file. If requested, also check against the system password database, - * and login the user if OK. - * - * returns: - * UPAP_AUTHNAK: Authentication failed. - * UPAP_AUTHACK: Authentication succeeded. - * In either case, msg points to an appropriate message. - */ -u_char -check_passwd( int unit, char *auser, int userlen, char *apasswd, int passwdlen, char **msg, int *msglen) -{ -#if 1 /* XXX Assume all entries OK. */ - LWIP_UNUSED_ARG(unit); - LWIP_UNUSED_ARG(auser); - LWIP_UNUSED_ARG(userlen); - LWIP_UNUSED_ARG(apasswd); - LWIP_UNUSED_ARG(passwdlen); - LWIP_UNUSED_ARG(msglen); - *msg = (char *) 0; - return UPAP_AUTHACK; /* XXX Assume all entries OK. */ -#else - u_char ret = 0; - struct wordlist *addrs = NULL; - char passwd[256], user[256]; - char secret[MAXWORDLEN]; - static u_short attempts = 0; - - /* - * Make copies of apasswd and auser, then null-terminate them. - */ - BCOPY(apasswd, passwd, passwdlen); - passwd[passwdlen] = '\0'; - BCOPY(auser, user, userlen); - user[userlen] = '\0'; - *msg = (char *) 0; - - /* XXX Validate user name and password. */ - ret = UPAP_AUTHACK; /* XXX Assume all entries OK. */ - - if (ret == UPAP_AUTHNAK) { - if (*msg == (char *) 0) { - *msg = "Login incorrect"; - } - *msglen = os_strlen(*msg); - /* - * Frustrate passwd stealer programs. - * Allow 10 tries, but start backing off after 3 (stolen from login). - * On 10'th, drop the connection. - */ - if (attempts++ >= 10) { - AUTHDEBUG(LOG_WARNING, ("%d LOGIN FAILURES BY %s\n", attempts, user)); - /*ppp_panic("Excess Bad Logins");*/ - } - if (attempts > 3) { - /* @todo: this was sleep(), i.e. seconds, not milliseconds - * I don't think we really need this in lwIP - we would block tcpip_thread! - */ - /*sys_msleep((attempts - 3) * 5);*/ - } - if (addrs != NULL) { - free_wordlist(addrs); - } - } else { - attempts = 0; /* Reset count */ - if (*msg == (char *) 0) { - *msg = "Login ok"; - } - *msglen = os_strlen(*msg); - set_allowed_addrs(unit, addrs); - } - - BZERO(passwd, sizeof(passwd)); - BZERO(secret, sizeof(secret)); - - return ret; -#endif -} -#endif /* PAP_SUPPORT */ - -#if 0 /* UNUSED */ -/* - * This function is needed for PAM. - */ - -#ifdef USE_PAM - -/* lwip does not support PAM*/ - -#endif /* USE_PAM */ - -#endif /* UNUSED */ - - -#if 0 /* UNUSED */ -/* - * plogin - Check the user name and password against the system - * password database, and login the user if OK. - * - * returns: - * UPAP_AUTHNAK: Login failed. - * UPAP_AUTHACK: Login succeeded. - * In either case, msg points to an appropriate message. - */ -static int -plogin(char *user, char *passwd, char **msg, int *msglen) -{ - - LWIP_UNUSED_ARG(user); - LWIP_UNUSED_ARG(passwd); - LWIP_UNUSED_ARG(msg); - LWIP_UNUSED_ARG(msglen); - - - /* The new lines are here align the file when - * compared against the pppd 2.3.11 code */ - - - - - - - - - - - - - - - - - /* XXX Fail until we decide that we want to support logins. */ - return (UPAP_AUTHNAK); -} -#endif - - - -/* - * plogout - Logout the user. - */ -static void -plogout(void) -{ - logged_in = 0; -} - -/* - * null_login - Check if a username of "" and a password of "" are - * acceptable, and iff so, set the list of acceptable IP addresses - * and return 1. - */ -static int -null_login(int unit) -{ - LWIP_UNUSED_ARG(unit); - /* XXX Fail until we decide that we want to support logins. */ - return 0; -} - - -/* - * get_pap_passwd - get a password for authenticating ourselves with - * our peer using PAP. Returns 1 on success, 0 if no suitable password - * could be found. - */ -static int -get_pap_passwd(int unit, char *user, char *passwd) -{ - LWIP_UNUSED_ARG(unit); -/* normally we would reject PAP if no password is provided, - but this causes problems with some providers (like CHT in Taiwan) - who incorrectly request PAP and expect a bogus/empty password, so - always provide a default user/passwd of "none"/"none" - - @todo: This should be configured by the user, instead of being hardcoded here! -*/ - if(user) { - strcpy(user, "none"); - } - if(passwd) { - strcpy(passwd, "none"); - } - return 1; -} - -/* - * have_pap_secret - check whether we have a PAP file with any - * secrets that we could possibly use for authenticating the peer. - */ -static int -have_pap_secret(void) -{ - /* XXX Fail until we set up our passwords. */ - return 0; -} - -/* - * have_chap_secret - check whether we have a CHAP file with a - * secret that we could possibly use for authenticating `client' - * on `server'. Either can be the null string, meaning we don't - * know the identity yet. - */ -static int -have_chap_secret(char *client, char *server, u32_t remote) -{ - LWIP_UNUSED_ARG(client); - LWIP_UNUSED_ARG(server); - LWIP_UNUSED_ARG(remote); - - /* XXX Fail until we set up our passwords. */ - return 0; -} -#if CHAP_SUPPORT - -/* - * get_secret - open the CHAP secret file and return the secret - * for authenticating the given client on the given server. - * (We could be either client or server). - */ -int -get_secret(int unit, char *client, char *server, char *secret, int *secret_len, int save_addrs) -{ -#if 1 - int len; - struct wordlist *addrs; - - LWIP_UNUSED_ARG(unit); - LWIP_UNUSED_ARG(server); - LWIP_UNUSED_ARG(save_addrs); - - addrs = NULL; - - if(!client || !client[0] || os_strcmp(client, ppp_settings.user)) { - return 0; - } - - len = (int)os_strlen(ppp_settings.passwd); - if (len > MAXSECRETLEN) { - AUTHDEBUG(LOG_ERR, ("Secret for %s on %s is too long\n", client, server)); - len = MAXSECRETLEN; - } - - BCOPY(ppp_settings.passwd, secret, len); - *secret_len = len; - - return 1; -#else - int ret = 0, len; - struct wordlist *addrs; - char secbuf[MAXWORDLEN]; - - addrs = NULL; - secbuf[0] = 0; - - /* XXX Find secret. */ - if (ret < 0) { - return 0; - } - - if (save_addrs) { - set_allowed_addrs(unit, addrs); - } - - len = os_strlen(secbuf); - if (len > MAXSECRETLEN) { - AUTHDEBUG(LOG_ERR, ("Secret for %s on %s is too long\n", client, server)); - len = MAXSECRETLEN; - } - - BCOPY(secbuf, secret, len); - BZERO(secbuf, sizeof(secbuf)); - *secret_len = len; - - return 1; -#endif -} -#endif /* CHAP_SUPPORT */ - - -#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */ -/* - * set_allowed_addrs() - set the list of allowed addresses. - */ -static void -set_allowed_addrs(int unit, struct wordlist *addrs) -{ - if (addresses[unit] != NULL) { - free_wordlist(addresses[unit]); - } - addresses[unit] = addrs; - -#if 0 - /* - * If there's only one authorized address we might as well - * ask our peer for that one right away - */ - if (addrs != NULL && addrs->next == NULL) { - char *p = addrs->word; - struct ipcp_options *wo = &ipcp_wantoptions[unit]; - u32_t a; - struct hostent *hp; - - if (wo->hisaddr == 0 && *p != '!' && *p != '-' && strchr(p, '/') == NULL) { - hp = gethostbyname(p); - if (hp != NULL && hp->h_addrtype == AF_INET) { - a = *(u32_t *)hp->h_addr; - } else { - a = inet_addr(p); - } - if (a != (u32_t) -1) { - wo->hisaddr = a; - } - } - } -#endif -} -#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ - -/* - * auth_ip_addr - check whether the peer is authorized to use - * a given IP address. Returns 1 if authorized, 0 otherwise. - */ -int -auth_ip_addr(int unit, u32_t addr) -{ - return ip_addr_check(addr, addresses[unit]); -} - -static int /* @todo: integrate this funtion into auth_ip_addr()*/ -ip_addr_check(u32_t addr, struct wordlist *addrs) -{ - /* don't allow loopback or multicast address */ - if (bad_ip_adrs(addr)) { - return 0; - } - - if (addrs == NULL) { - return !ppp_settings.auth_required; /* no addresses authorized */ - } - - /* XXX All other addresses allowed. */ - return 1; -} - -/* - * bad_ip_adrs - return 1 if the IP address is one we don't want - * to use, such as an address in the loopback net or a multicast address. - * addr is in network byte order. - */ -int -bad_ip_adrs(u32_t addr) -{ - addr = ntohl(addr); - return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET - || IN_MULTICAST(addr) || IN_BADCLASS(addr); -} - -#if 0 /* UNUSED */ /* PAP_SUPPORT || CHAP_SUPPORT */ -/* - * some_ip_ok - check a wordlist to see if it authorizes any - * IP address(es). - */ -static int -some_ip_ok(struct wordlist *addrs) -{ - for (; addrs != 0; addrs = addrs->next) { - if (addrs->word[0] == '-') - break; - if (addrs->word[0] != '!') - return 1; /* some IP address is allowed */ - } - return 0; -} - -/* - * check_access - complain if a secret file has too-liberal permissions. - */ -static void -check_access(FILE *f, char *filename) -{ - struct stat sbuf; - - if (fstat(fileno(f), &sbuf) < 0) { - warn("cannot stat secret file %s: %m", filename); - } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { - warn("Warning - secret file %s has world and/or group access", - filename); - } -} - - -/* - * scan_authfile - Scan an authorization file for a secret suitable - * for authenticating `client' on `server'. The return value is -1 - * if no secret is found, otherwise >= 0. The return value has - * NONWILD_CLIENT set if the secret didn't have "*" for the client, and - * NONWILD_SERVER set if the secret didn't have "*" for the server. - * Any following words on the line up to a "--" (i.e. address authorization - * info) are placed in a wordlist and returned in *addrs. Any - * following words (extra options) are placed in a wordlist and - * returned in *opts. - * We assume secret is NULL or points to MAXWORDLEN bytes of space. - */ -static int -scan_authfile(FILE *f, char *client, char *server, char *secret, struct wordlist **addrs, struct wordlist **opts, char *filename) -{ - /* We do not (currently) need this in lwip */ - return 0; /* dummy */ -} -/* - * free_wordlist - release memory allocated for a wordlist. - */ -static void -free_wordlist(struct wordlist *wp) -{ - struct wordlist *next; - - while (wp != NULL) { - next = wp->next; - free(wp); - wp = next; - } -} - -/* - * auth_script_done - called when the auth-up or auth-down script - * has finished. - */ -static void -auth_script_done(void *arg) -{ - auth_script_pid = 0; - switch (auth_script_state) { - case s_up: - if (auth_state == s_down) { - auth_script_state = s_down; - auth_script(_PATH_AUTHDOWN); - } - break; - case s_down: - if (auth_state == s_up) { - auth_script_state = s_up; - auth_script(_PATH_AUTHUP); - } - break; - } -} - -/* - * auth_script - execute a script with arguments - * interface-name peer-name real-user tty speed - */ -static void -auth_script(char *script) -{ - char strspeed[32]; - struct passwd *pw; - char struid[32]; - char *user_name; - char *argv[8]; - - if ((pw = getpwuid(getuid())) != NULL && pw->pw_name != NULL) - user_name = pw->pw_name; - else { - slprintf(struid, sizeof(struid), "%d", getuid()); - user_name = struid; - } - slprintf(strspeed, sizeof(strspeed), "%d", baud_rate); - - argv[0] = script; - argv[1] = ifname; - argv[2] = peer_authname; - argv[3] = user_name; - argv[4] = devnam; - argv[5] = strspeed; - argv[6] = NULL; - - auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL); -} -#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ -#endif /* PPP_SUPPORT */ diff --git a/third_party/lwip/netif/ppp/auth.h b/third_party/lwip/netif/ppp/auth.h deleted file mode 100644 index 593e17d..0000000 --- a/third_party/lwip/netif/ppp/auth.h +++ /dev/null @@ -1,111 +0,0 @@ -/***************************************************************************** -* auth.h - PPP Authentication and phase control header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1998 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-12-04 Guy Lancaster , Global Election Systems Inc. -* Original derived from BSD pppd.h. -*****************************************************************************/ -/* - * pppd.h - PPP daemon global declarations. - * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -#ifndef AUTH_H -#define AUTH_H - -/*********************** -*** PUBLIC FUNCTIONS *** -***********************/ - -/* we are starting to use the link */ -void link_required (int); - -/* we are finished with the link */ -void link_terminated (int); - -/* the LCP layer has left the Opened state */ -void link_down (int); - -/* the link is up; authenticate now */ -void link_established (int); - -/* a network protocol has come up */ -void np_up (int, u16_t); - -/* a network protocol has gone down */ -void np_down (int, u16_t); - -/* a network protocol no longer needs link */ -void np_finished (int, u16_t); - -/* peer failed to authenticate itself */ -void auth_peer_fail (int, u16_t); - -/* peer successfully authenticated itself */ -void auth_peer_success (int, u16_t, char *, int); - -/* we failed to authenticate ourselves */ -void auth_withpeer_fail (int, u16_t); - -/* we successfully authenticated ourselves */ -void auth_withpeer_success (int, u16_t); - -/* check authentication options supplied */ -void auth_check_options (void); - -/* check what secrets we have */ -void auth_reset (int); - -/* Check peer-supplied username/password */ -u_char check_passwd (int, char *, int, char *, int, char **, int *); - -/* get "secret" for chap */ -int get_secret (int, char *, char *, char *, int *, int); - -/* check if IP address is authorized */ -int auth_ip_addr (int, u32_t); - -/* check if IP address is unreasonable */ -int bad_ip_adrs (u32_t); - -#endif /* AUTH_H */ diff --git a/third_party/lwip/netif/ppp/chap.c b/third_party/lwip/netif/ppp/chap.c deleted file mode 100644 index 464dc4e..0000000 --- a/third_party/lwip/netif/ppp/chap.c +++ /dev/null @@ -1,908 +0,0 @@ -/*** WARNING - THIS HAS NEVER BEEN FINISHED ***/ -/***************************************************************************** -* chap.c - Network Challenge Handshake Authentication Protocol program file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 by Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-12-04 Guy Lancaster , Global Election Systems Inc. -* Original based on BSD chap.c. -*****************************************************************************/ -/* - * chap.c - Challenge Handshake Authentication Protocol. - * - * Copyright (c) 1993 The Australian National University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the Australian National University. The name of the University - * may not be used to endorse or promote products derived from this - * software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Copyright (c) 1991 Gregory M. Christy. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Gregory M. Christy. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#include "lwip/opt.h" - -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "ppp_impl.h" -#include "pppdebug.h" - -#include "magic.h" -#include "randm.h" -#include "auth.h" -#include "md5.h" -#include "chap.h" -#include "chpms.h" - -#include - -#if 0 /* UNUSED */ -/* - * Command-line options. - */ -static option_t chap_option_list[] = { - { "chap-restart", o_int, &chap[0].timeouttime, - "Set timeout for CHAP" }, - { "chap-max-challenge", o_int, &chap[0].max_transmits, - "Set max #xmits for challenge" }, - { "chap-interval", o_int, &chap[0].chal_interval, - "Set interval for rechallenge" }, -#ifdef MSLANMAN - { "ms-lanman", o_bool, &ms_lanman, - "Use LanMan passwd when using MS-CHAP", 1 }, -#endif - { NULL } -}; -#endif /* UNUSED */ - -/* - * Protocol entry points. - */ -static void ChapInit (int); -static void ChapLowerUp (int); -static void ChapLowerDown (int); -static void ChapInput (int, u_char *, int); -static void ChapProtocolReject (int); -#if PPP_ADDITIONAL_CALLBACKS -static int ChapPrintPkt (u_char *, int, void (*) (void *, char *, ...), void *); -#endif - -struct protent chap_protent = { - PPP_CHAP, - ChapInit, - ChapInput, - ChapProtocolReject, - ChapLowerUp, - ChapLowerDown, - NULL, - NULL, -#if PPP_ADDITIONAL_CALLBACKS - ChapPrintPkt, - NULL, -#endif /* PPP_ADDITIONAL_CALLBACKS */ - 1, - "CHAP", -#if PPP_ADDITIONAL_CALLBACKS - NULL, - NULL, - NULL -#endif /* PPP_ADDITIONAL_CALLBACKS */ -}; - -chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */ - -static void ChapChallengeTimeout (void *); -static void ChapResponseTimeout (void *); -static void ChapReceiveChallenge (chap_state *, u_char *, u_char, int); -static void ChapRechallenge (void *); -static void ChapReceiveResponse (chap_state *, u_char *, int, int); -static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len); -static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len); -static void ChapSendStatus (chap_state *, int); -static void ChapSendChallenge (chap_state *); -static void ChapSendResponse (chap_state *); -static void ChapGenChallenge (chap_state *); - -/* - * ChapInit - Initialize a CHAP unit. - */ -static void -ChapInit(int unit) -{ - chap_state *cstate = &chap[unit]; - - BZERO(cstate, sizeof(*cstate)); - cstate->unit = unit; - cstate->clientstate = CHAPCS_INITIAL; - cstate->serverstate = CHAPSS_INITIAL; - cstate->timeouttime = CHAP_DEFTIMEOUT; - cstate->max_transmits = CHAP_DEFTRANSMITS; - /* random number generator is initialized in magic_init */ -} - - -/* - * ChapAuthWithPeer - Authenticate us with our peer (start client). - * - */ -void -ChapAuthWithPeer(int unit, char *our_name, u_char digest) -{ - chap_state *cstate = &chap[unit]; - - cstate->resp_name = our_name; - cstate->resp_type = digest; - - if (cstate->clientstate == CHAPCS_INITIAL || - cstate->clientstate == CHAPCS_PENDING) { - /* lower layer isn't up - wait until later */ - cstate->clientstate = CHAPCS_PENDING; - return; - } - - /* - * We get here as a result of LCP coming up. - * So even if CHAP was open before, we will - * have to re-authenticate ourselves. - */ - cstate->clientstate = CHAPCS_LISTEN; -} - - -/* - * ChapAuthPeer - Authenticate our peer (start server). - */ -void -ChapAuthPeer(int unit, char *our_name, u_char digest) -{ - chap_state *cstate = &chap[unit]; - - cstate->chal_name = our_name; - cstate->chal_type = digest; - - if (cstate->serverstate == CHAPSS_INITIAL || - cstate->serverstate == CHAPSS_PENDING) { - /* lower layer isn't up - wait until later */ - cstate->serverstate = CHAPSS_PENDING; - return; - } - - ChapGenChallenge(cstate); - ChapSendChallenge(cstate); /* crank it up dude! */ - cstate->serverstate = CHAPSS_INITIAL_CHAL; -} - - -/* - * ChapChallengeTimeout - Timeout expired on sending challenge. - */ -static void -ChapChallengeTimeout(void *arg) -{ - chap_state *cstate = (chap_state *) arg; - - /* if we aren't sending challenges, don't worry. then again we */ - /* probably shouldn't be here either */ - if (cstate->serverstate != CHAPSS_INITIAL_CHAL && - cstate->serverstate != CHAPSS_RECHALLENGE) { - return; - } - - if (cstate->chal_transmits >= cstate->max_transmits) { - /* give up on peer */ - CHAPDEBUG(LOG_ERR, ("Peer failed to respond to CHAP challenge\n")); - cstate->serverstate = CHAPSS_BADAUTH; - auth_peer_fail(cstate->unit, PPP_CHAP); - return; - } - - ChapSendChallenge(cstate); /* Re-send challenge */ -} - - -/* - * ChapResponseTimeout - Timeout expired on sending response. - */ -static void -ChapResponseTimeout(void *arg) -{ - chap_state *cstate = (chap_state *) arg; - - /* if we aren't sending a response, don't worry. */ - if (cstate->clientstate != CHAPCS_RESPONSE) { - return; - } - - ChapSendResponse(cstate); /* re-send response */ -} - - -/* - * ChapRechallenge - Time to challenge the peer again. - */ -static void -ChapRechallenge(void *arg) -{ - chap_state *cstate = (chap_state *) arg; - - /* if we aren't sending a response, don't worry. */ - if (cstate->serverstate != CHAPSS_OPEN) { - return; - } - - ChapGenChallenge(cstate); - ChapSendChallenge(cstate); - cstate->serverstate = CHAPSS_RECHALLENGE; -} - - -/* - * ChapLowerUp - The lower layer is up. - * - * Start up if we have pending requests. - */ -static void -ChapLowerUp(int unit) -{ - chap_state *cstate = &chap[unit]; - - if (cstate->clientstate == CHAPCS_INITIAL) { - cstate->clientstate = CHAPCS_CLOSED; - } else if (cstate->clientstate == CHAPCS_PENDING) { - cstate->clientstate = CHAPCS_LISTEN; - } - - if (cstate->serverstate == CHAPSS_INITIAL) { - cstate->serverstate = CHAPSS_CLOSED; - } else if (cstate->serverstate == CHAPSS_PENDING) { - ChapGenChallenge(cstate); - ChapSendChallenge(cstate); - cstate->serverstate = CHAPSS_INITIAL_CHAL; - } -} - - -/* - * ChapLowerDown - The lower layer is down. - * - * Cancel all timeouts. - */ -static void -ChapLowerDown(int unit) -{ - chap_state *cstate = &chap[unit]; - - /* Timeout(s) pending? Cancel if so. */ - if (cstate->serverstate == CHAPSS_INITIAL_CHAL || - cstate->serverstate == CHAPSS_RECHALLENGE) { - UNTIMEOUT(ChapChallengeTimeout, cstate); - } else if (cstate->serverstate == CHAPSS_OPEN - && cstate->chal_interval != 0) { - UNTIMEOUT(ChapRechallenge, cstate); - } - if (cstate->clientstate == CHAPCS_RESPONSE) { - UNTIMEOUT(ChapResponseTimeout, cstate); - } - cstate->clientstate = CHAPCS_INITIAL; - cstate->serverstate = CHAPSS_INITIAL; -} - - -/* - * ChapProtocolReject - Peer doesn't grok CHAP. - */ -static void -ChapProtocolReject(int unit) -{ - chap_state *cstate = &chap[unit]; - - if (cstate->serverstate != CHAPSS_INITIAL && - cstate->serverstate != CHAPSS_CLOSED) { - auth_peer_fail(unit, PPP_CHAP); - } - if (cstate->clientstate != CHAPCS_INITIAL && - cstate->clientstate != CHAPCS_CLOSED) { - auth_withpeer_fail(unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */ - } - ChapLowerDown(unit); /* shutdown chap */ -} - - -/* - * ChapInput - Input CHAP packet. - */ -static void -ChapInput(int unit, u_char *inpacket, int packet_len) -{ - chap_state *cstate = &chap[unit]; - u_char *inp; - u_char code, id; - int len; - - /* - * Parse header (code, id and length). - * If packet too short, drop it. - */ - inp = inpacket; - if (packet_len < CHAP_HEADERLEN) { - CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short header.\n")); - return; - } - GETCHAR(code, inp); - GETCHAR(id, inp); - GETSHORT(len, inp); - if (len < CHAP_HEADERLEN) { - CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd illegal length.\n")); - return; - } - if (len > packet_len) { - CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short packet.\n")); - return; - } - len -= CHAP_HEADERLEN; - - /* - * Action depends on code (as in fact it usually does :-). - */ - switch (code) { - case CHAP_CHALLENGE: - ChapReceiveChallenge(cstate, inp, id, len); - break; - - case CHAP_RESPONSE: - ChapReceiveResponse(cstate, inp, id, len); - break; - - case CHAP_FAILURE: - ChapReceiveFailure(cstate, inp, id, len); - break; - - case CHAP_SUCCESS: - ChapReceiveSuccess(cstate, inp, id, len); - break; - - default: /* Need code reject? */ - CHAPDEBUG(LOG_WARNING, ("Unknown CHAP code (%d) received.\n", code)); - break; - } -} - - -/* - * ChapReceiveChallenge - Receive Challenge and send Response. - */ -static void -ChapReceiveChallenge(chap_state *cstate, u_char *inp, u_char id, int len) -{ - int rchallenge_len; - u_char *rchallenge; - int secret_len; - char secret[MAXSECRETLEN]; - char rhostname[256]; - MD5_CTX mdContext; - u_char hash[MD5_SIGNATURE_SIZE]; - - CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: Rcvd id %d.\n", id)); - if (cstate->clientstate == CHAPCS_CLOSED || - cstate->clientstate == CHAPCS_PENDING) { - CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: in state %d\n", - cstate->clientstate)); - return; - } - - if (len < 2) { - CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n")); - return; - } - - GETCHAR(rchallenge_len, inp); - len -= sizeof (u_char) + rchallenge_len; /* now name field length */ - if (len < 0) { - CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n")); - return; - } - rchallenge = inp; - INCPTR(rchallenge_len, inp); - - if (len >= (int)sizeof(rhostname)) { - len = sizeof(rhostname) - 1; - } - BCOPY(inp, rhostname, len); - rhostname[len] = '\000'; - - CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: received name field '%s'\n", - rhostname)); - - /* Microsoft doesn't send their name back in the PPP packet */ - if (ppp_settings.remote_name[0] != 0 && (ppp_settings.explicit_remote || rhostname[0] == 0)) { - strncpy(rhostname, ppp_settings.remote_name, sizeof(rhostname)); - rhostname[sizeof(rhostname) - 1] = 0; - CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: using '%s' as remote name\n", - rhostname)); - } - - /* get secret for authenticating ourselves with the specified host */ - if (!get_secret(cstate->unit, cstate->resp_name, rhostname, - secret, &secret_len, 0)) { - secret_len = 0; /* assume null secret if can't find one */ - CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating us to %s\n", - rhostname)); - } - - /* cancel response send timeout if necessary */ - if (cstate->clientstate == CHAPCS_RESPONSE) { - UNTIMEOUT(ChapResponseTimeout, cstate); - } - - cstate->resp_id = id; - cstate->resp_transmits = 0; - - /* generate MD based on negotiated type */ - switch (cstate->resp_type) { - - case CHAP_DIGEST_MD5: - MD5Init(&mdContext); - MD5Update(&mdContext, &cstate->resp_id, 1); - MD5Update(&mdContext, (u_char*)secret, secret_len); - MD5Update(&mdContext, rchallenge, rchallenge_len); - MD5Final(hash, &mdContext); - BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE); - cstate->resp_length = MD5_SIGNATURE_SIZE; - break; - -#if MSCHAP_SUPPORT - case CHAP_MICROSOFT: - ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len); - break; -#endif - - default: - CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->resp_type)); - return; - } - - BZERO(secret, sizeof(secret)); - ChapSendResponse(cstate); -} - - -/* - * ChapReceiveResponse - Receive and process response. - */ -static void -ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len) -{ - u_char *remmd, remmd_len; - int secret_len, old_state; - int code; - char rhostname[256]; - MD5_CTX mdContext; - char secret[MAXSECRETLEN]; - u_char hash[MD5_SIGNATURE_SIZE]; - - CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: Rcvd id %d.\n", id)); - - if (cstate->serverstate == CHAPSS_CLOSED || - cstate->serverstate == CHAPSS_PENDING) { - CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: in state %d\n", - cstate->serverstate)); - return; - } - - if (id != cstate->chal_id) { - return; /* doesn't match ID of last challenge */ - } - - /* - * If we have received a duplicate or bogus Response, - * we have to send the same answer (Success/Failure) - * as we did for the first Response we saw. - */ - if (cstate->serverstate == CHAPSS_OPEN) { - ChapSendStatus(cstate, CHAP_SUCCESS); - return; - } - if (cstate->serverstate == CHAPSS_BADAUTH) { - ChapSendStatus(cstate, CHAP_FAILURE); - return; - } - - if (len < 2) { - CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n")); - return; - } - GETCHAR(remmd_len, inp); /* get length of MD */ - remmd = inp; /* get pointer to MD */ - INCPTR(remmd_len, inp); - - len -= sizeof (u_char) + remmd_len; - if (len < 0) { - CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n")); - return; - } - - UNTIMEOUT(ChapChallengeTimeout, cstate); - - if (len >= (int)sizeof(rhostname)) { - len = sizeof(rhostname) - 1; - } - BCOPY(inp, rhostname, len); - rhostname[len] = '\000'; - - CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: received name field: %s\n", - rhostname)); - - /* - * Get secret for authenticating them with us, - * do the hash ourselves, and compare the result. - */ - code = CHAP_FAILURE; - if (!get_secret(cstate->unit, rhostname, cstate->chal_name, - secret, &secret_len, 1)) { - CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating %s\n", - rhostname)); - } else { - /* generate MD based on negotiated type */ - switch (cstate->chal_type) { - - case CHAP_DIGEST_MD5: /* only MD5 is defined for now */ - if (remmd_len != MD5_SIGNATURE_SIZE) { - break; /* it's not even the right length */ - } - MD5Init(&mdContext); - MD5Update(&mdContext, &cstate->chal_id, 1); - MD5Update(&mdContext, (u_char*)secret, secret_len); - MD5Update(&mdContext, cstate->challenge, cstate->chal_len); - MD5Final(hash, &mdContext); - - /* compare local and remote MDs and send the appropriate status */ - if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0) { - code = CHAP_SUCCESS; /* they are the same! */ - } - break; - - default: - CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->chal_type)); - } - } - - BZERO(secret, sizeof(secret)); - ChapSendStatus(cstate, code); - - if (code == CHAP_SUCCESS) { - old_state = cstate->serverstate; - cstate->serverstate = CHAPSS_OPEN; - if (old_state == CHAPSS_INITIAL_CHAL) { - auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len); - } - if (cstate->chal_interval != 0) { - TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval); - } - } else { - CHAPDEBUG(LOG_ERR, ("CHAP peer authentication failed\n")); - cstate->serverstate = CHAPSS_BADAUTH; - auth_peer_fail(cstate->unit, PPP_CHAP); - } -} - -/* - * ChapReceiveSuccess - Receive Success - */ -static void -ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len) -{ - LWIP_UNUSED_ARG(id); - LWIP_UNUSED_ARG(inp); - - CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: Rcvd id %d.\n", id)); - - if (cstate->clientstate == CHAPCS_OPEN) { - /* presumably an answer to a duplicate response */ - return; - } - - if (cstate->clientstate != CHAPCS_RESPONSE) { - /* don't know what this is */ - CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: in state %d\n", - cstate->clientstate)); - return; - } - - UNTIMEOUT(ChapResponseTimeout, cstate); - - /* - * Print message. - */ - if (len > 0) { - PRINTMSG(inp, len); - } - - cstate->clientstate = CHAPCS_OPEN; - - auth_withpeer_success(cstate->unit, PPP_CHAP); -} - - -/* - * ChapReceiveFailure - Receive failure. - */ -static void -ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len) -{ - LWIP_UNUSED_ARG(id); - LWIP_UNUSED_ARG(inp); - - CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: Rcvd id %d.\n", id)); - - if (cstate->clientstate != CHAPCS_RESPONSE) { - /* don't know what this is */ - CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: in state %d\n", - cstate->clientstate)); - return; - } - - UNTIMEOUT(ChapResponseTimeout, cstate); - - /* - * Print message. - */ - if (len > 0) { - PRINTMSG(inp, len); - } - - CHAPDEBUG(LOG_ERR, ("CHAP authentication failed\n")); - auth_withpeer_fail(cstate->unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */ -} - - -/* - * ChapSendChallenge - Send an Authenticate challenge. - */ -static void -ChapSendChallenge(chap_state *cstate) -{ - u_char *outp; - int chal_len, name_len; - int outlen; - - chal_len = cstate->chal_len; - name_len = (int)os_strlen(cstate->chal_name); - outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len; - outp = outpacket_buf[cstate->unit]; - - MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */ - - PUTCHAR(CHAP_CHALLENGE, outp); - PUTCHAR(cstate->chal_id, outp); - PUTSHORT(outlen, outp); - - PUTCHAR(chal_len, outp); /* put length of challenge */ - BCOPY(cstate->challenge, outp, chal_len); - INCPTR(chal_len, outp); - - BCOPY(cstate->chal_name, outp, name_len); /* append hostname */ - - pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN); - - CHAPDEBUG(LOG_INFO, ("ChapSendChallenge: Sent id %d.\n", cstate->chal_id)); - - TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime); - ++cstate->chal_transmits; -} - - -/* - * ChapSendStatus - Send a status response (ack or nak). - */ -static void -ChapSendStatus(chap_state *cstate, int code) -{ - u_char *outp; - int outlen, msglen; - char msg[256]; /* @todo: this can be a char*, no strcpy needed */ - - if (code == CHAP_SUCCESS) { - strcpy(msg, "Welcome!"); - } else { - strcpy(msg, "I don't like you. Go 'way."); - } - msglen = (int)os_strlen(msg); - - outlen = CHAP_HEADERLEN + msglen; - outp = outpacket_buf[cstate->unit]; - - MAKEHEADER(outp, PPP_CHAP); /* paste in a header */ - - PUTCHAR(code, outp); - PUTCHAR(cstate->chal_id, outp); - PUTSHORT(outlen, outp); - BCOPY(msg, outp, msglen); - pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN); - - CHAPDEBUG(LOG_INFO, ("ChapSendStatus: Sent code %d, id %d.\n", code, - cstate->chal_id)); -} - -/* - * ChapGenChallenge is used to generate a pseudo-random challenge string of - * a pseudo-random length between min_len and max_len. The challenge - * string and its length are stored in *cstate, and various other fields of - * *cstate are initialized. - */ - -static void -ChapGenChallenge(chap_state *cstate) -{ - int chal_len; - u_char *ptr = cstate->challenge; - int i; - - /* pick a random challenge length between MIN_CHALLENGE_LENGTH and - MAX_CHALLENGE_LENGTH */ - chal_len = (unsigned) - ((((magic() >> 16) * - (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) >> 16) - + MIN_CHALLENGE_LENGTH); - LWIP_ASSERT("chal_len <= 0xff", chal_len <= 0xffff); - cstate->chal_len = (u_char)chal_len; - cstate->chal_id = ++cstate->id; - cstate->chal_transmits = 0; - - /* generate a random string */ - for (i = 0; i < chal_len; i++ ) { - *ptr++ = (char) (magic() & 0xff); - } -} - -/* - * ChapSendResponse - send a response packet with values as specified - * in *cstate. - */ -/* ARGSUSED */ -static void -ChapSendResponse(chap_state *cstate) -{ - u_char *outp; - int outlen, md_len, name_len; - - md_len = cstate->resp_length; - name_len = (int)os_strlen(cstate->resp_name); - outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len; - outp = outpacket_buf[cstate->unit]; - - MAKEHEADER(outp, PPP_CHAP); - - PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */ - PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */ - PUTSHORT(outlen, outp); /* packet length */ - - PUTCHAR(md_len, outp); /* length of MD */ - BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */ - INCPTR(md_len, outp); - - BCOPY(cstate->resp_name, outp, name_len); /* append our name */ - - /* send the packet */ - pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN); - - cstate->clientstate = CHAPCS_RESPONSE; - TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime); - ++cstate->resp_transmits; -} - -#if PPP_ADDITIONAL_CALLBACKS -static char *ChapCodenames[] = { - "Challenge", "Response", "Success", "Failure" -}; -/* - * ChapPrintPkt - print the contents of a CHAP packet. - */ -static int -ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) -{ - int code, id, len; - int clen, nlen; - u_char x; - - if (plen < CHAP_HEADERLEN) { - return 0; - } - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < CHAP_HEADERLEN || len > plen) { - return 0; - } - - if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *)) { - printer(arg, " %s", ChapCodenames[code-1]); - } else { - printer(arg, " code=0x%x", code); - } - printer(arg, " id=0x%x", id); - len -= CHAP_HEADERLEN; - switch (code) { - case CHAP_CHALLENGE: - case CHAP_RESPONSE: - if (len < 1) { - break; - } - clen = p[0]; - if (len < clen + 1) { - break; - } - ++p; - nlen = len - clen - 1; - printer(arg, " <"); - for (; clen > 0; --clen) { - GETCHAR(x, p); - printer(arg, "%.2x", x); - } - printer(arg, ">, name = %.*Z", nlen, p); - break; - case CHAP_FAILURE: - case CHAP_SUCCESS: - printer(arg, " %.*Z", len, p); - break; - default: - for (clen = len; clen > 0; --clen) { - GETCHAR(x, p); - printer(arg, " %.2x", x); - } - } - - return len + CHAP_HEADERLEN; -} -#endif /* PPP_ADDITIONAL_CALLBACKS */ - -#endif /* CHAP_SUPPORT */ - -#endif /* PPP_SUPPORT */ diff --git a/third_party/lwip/netif/ppp/chap.h b/third_party/lwip/netif/ppp/chap.h deleted file mode 100644 index 9591c95..0000000 --- a/third_party/lwip/netif/ppp/chap.h +++ /dev/null @@ -1,150 +0,0 @@ -/***************************************************************************** -* chap.h - Network Challenge Handshake Authentication Protocol header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1998 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-12-03 Guy Lancaster , Global Election Systems Inc. -* Original built from BSD network code. -******************************************************************************/ -/* - * chap.h - Challenge Handshake Authentication Protocol definitions. - * - * Copyright (c) 1993 The Australian National University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the Australian National University. The name of the University - * may not be used to endorse or promote products derived from this - * software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Copyright (c) 1991 Gregory M. Christy - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the author. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * $Id: chap.h,v 1.6 2010/01/24 13:19:34 goldsimon Exp $ - */ - -#ifndef CHAP_H -#define CHAP_H - -/* Code + ID + length */ -#define CHAP_HEADERLEN 4 - -/* - * CHAP codes. - */ - -#define CHAP_DIGEST_MD5 5 /* use MD5 algorithm */ -#define MD5_SIGNATURE_SIZE 16 /* 16 bytes in a MD5 message digest */ -#define CHAP_MICROSOFT 0x80 /* use Microsoft-compatible alg. */ -#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */ - -#define CHAP_CHALLENGE 1 -#define CHAP_RESPONSE 2 -#define CHAP_SUCCESS 3 -#define CHAP_FAILURE 4 - -/* - * Challenge lengths (for challenges we send) and other limits. - */ -#define MIN_CHALLENGE_LENGTH 32 -#define MAX_CHALLENGE_LENGTH 64 -#define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 or MS-CHAP */ - -/* - * Each interface is described by a chap structure. - */ - -typedef struct chap_state { - int unit; /* Interface unit number */ - int clientstate; /* Client state */ - int serverstate; /* Server state */ - u_char challenge[MAX_CHALLENGE_LENGTH]; /* last challenge string sent */ - u_char chal_len; /* challenge length */ - u_char chal_id; /* ID of last challenge */ - u_char chal_type; /* hash algorithm for challenges */ - u_char id; /* Current id */ - char *chal_name; /* Our name to use with challenge */ - int chal_interval; /* Time until we challenge peer again */ - int timeouttime; /* Timeout time in seconds */ - int max_transmits; /* Maximum # of challenge transmissions */ - int chal_transmits; /* Number of transmissions of challenge */ - int resp_transmits; /* Number of transmissions of response */ - u_char response[MAX_RESPONSE_LENGTH]; /* Response to send */ - u_char resp_length; /* length of response */ - u_char resp_id; /* ID for response messages */ - u_char resp_type; /* hash algorithm for responses */ - char *resp_name; /* Our name to send with response */ -} chap_state; - - -/* - * Client (peer) states. - */ -#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */ -#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */ -#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */ -#define CHAPCS_LISTEN 3 /* Listening for a challenge */ -#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */ -#define CHAPCS_OPEN 5 /* We've received Success */ - -/* - * Server (authenticator) states. - */ -#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */ -#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */ -#define CHAPSS_PENDING 2 /* Auth peer when lower up */ -#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */ -#define CHAPSS_OPEN 4 /* We've sent a Success msg */ -#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */ -#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */ - -extern chap_state chap[]; - -void ChapAuthWithPeer (int, char *, u_char); -void ChapAuthPeer (int, char *, u_char); - -extern struct protent chap_protent; - -#endif /* CHAP_H */ diff --git a/third_party/lwip/netif/ppp/chpms.c b/third_party/lwip/netif/ppp/chpms.c deleted file mode 100644 index d039f05..0000000 --- a/third_party/lwip/netif/ppp/chpms.c +++ /dev/null @@ -1,396 +0,0 @@ -/*** WARNING - THIS CODE HAS NOT BEEN FINISHED! ***/ -/*** The original PPPD code is written in a way to require either the UNIX DES - encryption functions encrypt(3) and setkey(3) or the DES library libdes. - Since both is not included in lwIP, MSCHAP currently does not work! */ -/***************************************************************************** -* chpms.c - Network MicroSoft Challenge Handshake Authentication Protocol program file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* Copyright (c) 1997 by Global Election Systems Inc. All rights reserved. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-12-08 Guy Lancaster , Global Election Systems Inc. -* Original based on BSD chap_ms.c. -*****************************************************************************/ -/* - * chap_ms.c - Microsoft MS-CHAP compatible implementation. - * - * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited. - * http://www.strataware.com/ - * - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Eric Rosenquist. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -/* - * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997 - * - * Implemented LANManager type password response to MS-CHAP challenges. - * Now pppd provides both NT style and LANMan style blocks, and the - * prefered is set by option "ms-lanman". Default is to use NT. - * The hash text (StdText) was taken from Win95 RASAPI32.DLL. - * - * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80 - */ - -#define USE_CRYPT - -#include "lwip/opt.h" - -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "ppp_impl.h" -#include "pppdebug.h" - -#include "md4.h" -#ifndef USE_CRYPT -#include "des.h" -#endif -#include "chap.h" -#include "chpms.h" - -#include - - -/*************************/ -/*** LOCAL DEFINITIONS ***/ -/*************************/ - - -/************************/ -/*** LOCAL DATA TYPES ***/ -/************************/ -typedef struct { - u_char LANManResp[24]; - u_char NTResp[24]; - u_char UseNT; /* If 1, ignore the LANMan response field */ -} MS_ChapResponse; -/* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse), - in case this struct gets padded. */ - - - -/***********************************/ -/*** LOCAL FUNCTION DECLARATIONS ***/ -/***********************************/ - -/* XXX Don't know what to do with these. */ -extern void setkey(const char *); -extern void encrypt(char *, int); - -static void DesEncrypt (u_char *, u_char *, u_char *); -static void MakeKey (u_char *, u_char *); - -#ifdef USE_CRYPT -static void Expand (u_char *, u_char *); -static void Collapse (u_char *, u_char *); -#endif - -static void ChallengeResponse( - u_char *challenge, /* IN 8 octets */ - u_char *pwHash, /* IN 16 octets */ - u_char *response /* OUT 24 octets */ -); -static void ChapMS_NT( - char *rchallenge, - int rchallenge_len, - char *secret, - int secret_len, - MS_ChapResponse *response -); -static u_char Get7Bits( - u_char *input, - int startBit -); - -static void -ChallengeResponse( u_char *challenge, /* IN 8 octets */ - u_char *pwHash, /* IN 16 octets */ - u_char *response /* OUT 24 octets */) -{ - u_char ZPasswordHash[21]; - - BZERO(ZPasswordHash, sizeof(ZPasswordHash)); - BCOPY(pwHash, ZPasswordHash, 16); - -#if 0 - log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG); -#endif - - DesEncrypt(challenge, ZPasswordHash + 0, response + 0); - DesEncrypt(challenge, ZPasswordHash + 7, response + 8); - DesEncrypt(challenge, ZPasswordHash + 14, response + 16); - -#if 0 - log_packet(response, 24, "ChallengeResponse - response", LOG_DEBUG); -#endif -} - - -#ifdef USE_CRYPT -static void -DesEncrypt( u_char *clear, /* IN 8 octets */ - u_char *key, /* IN 7 octets */ - u_char *cipher /* OUT 8 octets */) -{ - u_char des_key[8]; - u_char crypt_key[66]; - u_char des_input[66]; - - MakeKey(key, des_key); - - Expand(des_key, crypt_key); - setkey((char*)crypt_key); - -#if 0 - CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n", - clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7])); -#endif - - Expand(clear, des_input); - encrypt((char*)des_input, 0); - Collapse(des_input, cipher); - -#if 0 - CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n", - cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7])); -#endif -} - -#else /* USE_CRYPT */ - -static void -DesEncrypt( u_char *clear, /* IN 8 octets */ - u_char *key, /* IN 7 octets */ - u_char *cipher /* OUT 8 octets */) -{ - des_cblock des_key; - des_key_schedule key_schedule; - - MakeKey(key, des_key); - - des_set_key(&des_key, key_schedule); - -#if 0 - CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n", - clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7])); -#endif - - des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1); - -#if 0 - CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n", - cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7])); -#endif -} - -#endif /* USE_CRYPT */ - - -static u_char -Get7Bits( u_char *input, int startBit) -{ - register unsigned int word; - - word = (unsigned)input[startBit / 8] << 8; - word |= (unsigned)input[startBit / 8 + 1]; - - word >>= 15 - (startBit % 8 + 7); - - return word & 0xFE; -} - -#ifdef USE_CRYPT - -/* in == 8-byte string (expanded version of the 56-bit key) - * out == 64-byte string where each byte is either 1 or 0 - * Note that the low-order "bit" is always ignored by by setkey() - */ -static void -Expand(u_char *in, u_char *out) -{ - int j, c; - int i; - - for(i = 0; i < 64; in++){ - c = *in; - for(j = 7; j >= 0; j--) { - *out++ = (c >> j) & 01; - } - i += 8; - } -} - -/* The inverse of Expand - */ -static void -Collapse(u_char *in, u_char *out) -{ - int j; - int i; - unsigned int c; - - for (i = 0; i < 64; i += 8, out++) { - c = 0; - for (j = 7; j >= 0; j--, in++) { - c |= *in << j; - } - *out = c & 0xff; - } -} -#endif - -static void -MakeKey( u_char *key, /* IN 56 bit DES key missing parity bits */ - u_char *des_key /* OUT 64 bit DES key with parity bits added */) -{ - des_key[0] = Get7Bits(key, 0); - des_key[1] = Get7Bits(key, 7); - des_key[2] = Get7Bits(key, 14); - des_key[3] = Get7Bits(key, 21); - des_key[4] = Get7Bits(key, 28); - des_key[5] = Get7Bits(key, 35); - des_key[6] = Get7Bits(key, 42); - des_key[7] = Get7Bits(key, 49); - -#ifndef USE_CRYPT - des_set_odd_parity((des_cblock *)des_key); -#endif - -#if 0 - CHAPDEBUG(LOG_INFO, ("MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X\n", - key[0], key[1], key[2], key[3], key[4], key[5], key[6])); - CHAPDEBUG(LOG_INFO, ("MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X\n", - des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7])); -#endif -} - -static void -ChapMS_NT( char *rchallenge, - int rchallenge_len, - char *secret, - int secret_len, - MS_ChapResponse *response) -{ - int i; - MDstruct md4Context; - u_char unicodePassword[MAX_NT_PASSWORD * 2]; - static int low_byte_first = -1; - - LWIP_UNUSED_ARG(rchallenge_len); - - /* Initialize the Unicode version of the secret (== password). */ - /* This implicitly supports 8-bit ISO8859/1 characters. */ - BZERO(unicodePassword, sizeof(unicodePassword)); - for (i = 0; i < secret_len; i++) { - unicodePassword[i * 2] = (u_char)secret[i]; - } - MDbegin(&md4Context); - MDupdate(&md4Context, unicodePassword, secret_len * 2 * 8); /* Unicode is 2 bytes/char, *8 for bit count */ - - if (low_byte_first == -1) { - low_byte_first = (PP_HTONS((unsigned short int)1) != 1); - } - if (low_byte_first == 0) { - /* @todo: arg type - u_long* or u_int* ? */ - MDreverse((unsigned int*)&md4Context); /* sfb 961105 */ - } - - MDupdate(&md4Context, NULL, 0); /* Tell MD4 we're done */ - - ChallengeResponse((u_char*)rchallenge, (u_char*)md4Context.buffer, response->NTResp); -} - -#ifdef MSLANMAN -static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */ - -static void -ChapMS_LANMan( char *rchallenge, - int rchallenge_len, - char *secret, - int secret_len, - MS_ChapResponse *response) -{ - int i; - u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */ - u_char PasswordHash[16]; - - /* LANMan password is case insensitive */ - BZERO(UcasePassword, sizeof(UcasePassword)); - for (i = 0; i < secret_len; i++) { - UcasePassword[i] = (u_char)toupper(secret[i]); - } - DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 ); - DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 ); - ChallengeResponse(rchallenge, PasswordHash, response->LANManResp); -} -#endif - -void -ChapMS( chap_state *cstate, char *rchallenge, int rchallenge_len, char *secret, int secret_len) -{ - MS_ChapResponse response; -#ifdef MSLANMAN - extern int ms_lanman; -#endif - -#if 0 - CHAPDEBUG(LOG_INFO, ("ChapMS: secret is '%.*s'\n", secret_len, secret)); -#endif - BZERO(&response, sizeof(response)); - - /* Calculate both always */ - ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response); - -#ifdef MSLANMAN - ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response); - - /* prefered method is set by option */ - response.UseNT = !ms_lanman; -#else - response.UseNT = 1; -#endif - - BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN); - cstate->resp_length = MS_CHAP_RESPONSE_LEN; -} - -#endif /* MSCHAP_SUPPORT */ - -#endif /* PPP_SUPPORT */ diff --git a/third_party/lwip/netif/ppp/chpms.h b/third_party/lwip/netif/ppp/chpms.h deleted file mode 100644 index f023cce..0000000 --- a/third_party/lwip/netif/ppp/chpms.h +++ /dev/null @@ -1,64 +0,0 @@ -/***************************************************************************** -* chpms.h - Network Microsoft Challenge Handshake Protocol header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1998 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 98-01-30 Guy Lancaster , Global Election Systems Inc. -* Original built from BSD network code. -******************************************************************************/ -/* - * chap.h - Challenge Handshake Authentication Protocol definitions. - * - * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited. - * http://www.strataware.com/ - * - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Eric Rosenquist. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * $Id: chpms.h,v 1.5 2007/12/19 20:47:23 fbernon Exp $ - */ - -#ifndef CHPMS_H -#define CHPMS_H - -#define MAX_NT_PASSWORD 256 /* Maximum number of (Unicode) chars in an NT password */ - -void ChapMS (chap_state *, char *, int, char *, int); - -#endif /* CHPMS_H */ diff --git a/third_party/lwip/netif/ppp/fsm.c b/third_party/lwip/netif/ppp/fsm.c deleted file mode 100644 index 167861d..0000000 --- a/third_party/lwip/netif/ppp/fsm.c +++ /dev/null @@ -1,890 +0,0 @@ -/***************************************************************************** -* fsm.c - Network Control Protocol Finite State Machine program file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 by Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-12-01 Guy Lancaster , Global Election Systems Inc. -* Original based on BSD fsm.c. -*****************************************************************************/ -/* - * fsm.c - {Link, IP} Control Protocol Finite State Machine. - * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -/* - * TODO: - * Randomize fsm id on link/init. - * Deal with variable outgoing MTU. - */ - -#include "lwip/opt.h" - -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "ppp_impl.h" -#include "pppdebug.h" - -#include "fsm.h" - -#include - -#if PPP_DEBUG -static const char *ppperr_strerr[] = { - "LS_INITIAL", /* LS_INITIAL 0 */ - "LS_STARTING", /* LS_STARTING 1 */ - "LS_CLOSED", /* LS_CLOSED 2 */ - "LS_STOPPED", /* LS_STOPPED 3 */ - "LS_CLOSING", /* LS_CLOSING 4 */ - "LS_STOPPING", /* LS_STOPPING 5 */ - "LS_REQSENT", /* LS_REQSENT 6 */ - "LS_ACKRCVD", /* LS_ACKRCVD 7 */ - "LS_ACKSENT", /* LS_ACKSENT 8 */ - "LS_OPENED" /* LS_OPENED 9 */ -}; -#endif /* PPP_DEBUG */ - -static void fsm_timeout (void *); -static void fsm_rconfreq (fsm *, u_char, u_char *, int); -static void fsm_rconfack (fsm *, int, u_char *, int); -static void fsm_rconfnakrej (fsm *, int, int, u_char *, int); -static void fsm_rtermreq (fsm *, int, u_char *, int); -static void fsm_rtermack (fsm *); -static void fsm_rcoderej (fsm *, u_char *, int); -static void fsm_sconfreq (fsm *, int); - -#define PROTO_NAME(f) ((f)->callbacks->proto_name) - -int peer_mru[NUM_PPP]; - - -/* - * fsm_init - Initialize fsm. - * - * Initialize fsm state. - */ -void -fsm_init(fsm *f) -{ - f->state = LS_INITIAL; - f->flags = 0; - f->id = 0; /* XXX Start with random id? */ - f->timeouttime = FSM_DEFTIMEOUT; - f->maxconfreqtransmits = FSM_DEFMAXCONFREQS; - f->maxtermtransmits = FSM_DEFMAXTERMREQS; - f->maxnakloops = FSM_DEFMAXNAKLOOPS; - f->term_reason_len = 0; -} - - -/* - * fsm_lowerup - The lower layer is up. - */ -void -fsm_lowerup(fsm *f) -{ - int oldState = f->state; - - LWIP_UNUSED_ARG(oldState); - - switch( f->state ) { - case LS_INITIAL: - f->state = LS_CLOSED; - break; - - case LS_STARTING: - if( f->flags & OPT_SILENT ) { - f->state = LS_STOPPED; - } else { - /* Send an initial configure-request */ - fsm_sconfreq(f, 0); - f->state = LS_REQSENT; - } - break; - - default: - FSMDEBUG(LOG_INFO, ("%s: Up event in state %d (%s)!\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - } - - FSMDEBUG(LOG_INFO, ("%s: lowerup state %d (%s) -> %d (%s)\n", - PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); -} - - -/* - * fsm_lowerdown - The lower layer is down. - * - * Cancel all timeouts and inform upper layers. - */ -void -fsm_lowerdown(fsm *f) -{ - int oldState = f->state; - - LWIP_UNUSED_ARG(oldState); - - switch( f->state ) { - case LS_CLOSED: - f->state = LS_INITIAL; - break; - - case LS_STOPPED: - f->state = LS_STARTING; - if( f->callbacks->starting ) { - (*f->callbacks->starting)(f); - } - break; - - case LS_CLOSING: - f->state = LS_INITIAL; - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - break; - - case LS_STOPPING: - case LS_REQSENT: - case LS_ACKRCVD: - case LS_ACKSENT: - f->state = LS_STARTING; - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - break; - - case LS_OPENED: - if( f->callbacks->down ) { - (*f->callbacks->down)(f); - } - f->state = LS_STARTING; - break; - - default: - FSMDEBUG(LOG_INFO, ("%s: Down event in state %d (%s)!\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - } - - FSMDEBUG(LOG_INFO, ("%s: lowerdown state %d (%s) -> %d (%s)\n", - PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); -} - - -/* - * fsm_open - Link is allowed to come up. - */ -void -fsm_open(fsm *f) -{ - int oldState = f->state; - - LWIP_UNUSED_ARG(oldState); - - switch( f->state ) { - case LS_INITIAL: - f->state = LS_STARTING; - if( f->callbacks->starting ) { - (*f->callbacks->starting)(f); - } - break; - - case LS_CLOSED: - if( f->flags & OPT_SILENT ) { - f->state = LS_STOPPED; - } else { - /* Send an initial configure-request */ - fsm_sconfreq(f, 0); - f->state = LS_REQSENT; - } - break; - - case LS_CLOSING: - f->state = LS_STOPPING; - /* fall through */ - case LS_STOPPED: - case LS_OPENED: - if( f->flags & OPT_RESTART ) { - fsm_lowerdown(f); - fsm_lowerup(f); - } - break; - } - - FSMDEBUG(LOG_INFO, ("%s: open state %d (%s) -> %d (%s)\n", - PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); -} - -#if 0 /* backport pppd 2.4.4b1; */ -/* - * terminate_layer - Start process of shutting down the FSM - * - * Cancel any timeout running, notify upper layers we're done, and - * send a terminate-request message as configured. - */ -static void -terminate_layer(fsm *f, int nextstate) -{ - /* @todo */ -} -#endif - -/* - * fsm_close - Start closing connection. - * - * Cancel timeouts and either initiate close or possibly go directly to - * the LS_CLOSED state. - */ -void -fsm_close(fsm *f, char *reason) -{ - int oldState = f->state; - - LWIP_UNUSED_ARG(oldState); - - f->term_reason = reason; - f->term_reason_len = (reason == NULL ? 0 : (int)os_strlen(reason)); - switch( f->state ) { - case LS_STARTING: - f->state = LS_INITIAL; - break; - case LS_STOPPED: - f->state = LS_CLOSED; - break; - case LS_STOPPING: - f->state = LS_CLOSING; - break; - - case LS_REQSENT: - case LS_ACKRCVD: - case LS_ACKSENT: - case LS_OPENED: - if( f->state != LS_OPENED ) { - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - } else if( f->callbacks->down ) { - (*f->callbacks->down)(f); /* Inform upper layers we're down */ - } - /* Init restart counter, send Terminate-Request */ - f->retransmits = f->maxtermtransmits; - fsm_sdata(f, TERMREQ, f->reqid = ++f->id, - (u_char *) f->term_reason, f->term_reason_len); - TIMEOUT(fsm_timeout, f, f->timeouttime); - --f->retransmits; - - f->state = LS_CLOSING; - break; - } - - FSMDEBUG(LOG_INFO, ("%s: close reason=%s state %d (%s) -> %d (%s)\n", - PROTO_NAME(f), reason, oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); -} - - -/* - * fsm_timeout - Timeout expired. - */ -static void -fsm_timeout(void *arg) -{ - fsm *f = (fsm *) arg; - - switch (f->state) { - case LS_CLOSING: - case LS_STOPPING: - if( f->retransmits <= 0 ) { - FSMDEBUG(LOG_WARNING, ("%s: timeout sending Terminate-Request state=%d (%s)\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - /* - * We've waited for an ack long enough. Peer probably heard us. - */ - f->state = (f->state == LS_CLOSING)? LS_CLOSED: LS_STOPPED; - if( f->callbacks->finished ) { - (*f->callbacks->finished)(f); - } - } else { - FSMDEBUG(LOG_WARNING, ("%s: timeout resending Terminate-Requests state=%d (%s)\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - /* Send Terminate-Request */ - fsm_sdata(f, TERMREQ, f->reqid = ++f->id, - (u_char *) f->term_reason, f->term_reason_len); - TIMEOUT(fsm_timeout, f, f->timeouttime); - --f->retransmits; - } - break; - - case LS_REQSENT: - case LS_ACKRCVD: - case LS_ACKSENT: - if (f->retransmits <= 0) { - FSMDEBUG(LOG_WARNING, ("%s: timeout sending Config-Requests state=%d (%s)\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - f->state = LS_STOPPED; - if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) { - (*f->callbacks->finished)(f); - } - } else { - FSMDEBUG(LOG_WARNING, ("%s: timeout resending Config-Request state=%d (%s)\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - /* Retransmit the configure-request */ - if (f->callbacks->retransmit) { - (*f->callbacks->retransmit)(f); - } - fsm_sconfreq(f, 1); /* Re-send Configure-Request */ - if( f->state == LS_ACKRCVD ) { - f->state = LS_REQSENT; - } - } - break; - - default: - FSMDEBUG(LOG_INFO, ("%s: UNHANDLED timeout event in state %d (%s)!\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - } -} - - -/* - * fsm_input - Input packet. - */ -void -fsm_input(fsm *f, u_char *inpacket, int l) -{ - u_char *inp = inpacket; - u_char code, id; - int len; - - /* - * Parse header (code, id and length). - * If packet too short, drop it. - */ - if (l < HEADERLEN) { - FSMDEBUG(LOG_WARNING, ("fsm_input(%x): Rcvd short header.\n", - f->protocol)); - return; - } - GETCHAR(code, inp); - GETCHAR(id, inp); - GETSHORT(len, inp); - if (len < HEADERLEN) { - FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd illegal length.\n", - f->protocol)); - return; - } - if (len > l) { - FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd short packet.\n", - f->protocol)); - return; - } - len -= HEADERLEN; /* subtract header length */ - - if( f->state == LS_INITIAL || f->state == LS_STARTING ) { - FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd packet in state %d (%s).\n", - f->protocol, f->state, ppperr_strerr[f->state])); - return; - } - FSMDEBUG(LOG_INFO, ("fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l)); - /* - * Action depends on code. - */ - switch (code) { - case CONFREQ: - fsm_rconfreq(f, id, inp, len); - break; - - case CONFACK: - fsm_rconfack(f, id, inp, len); - break; - - case CONFNAK: - case CONFREJ: - fsm_rconfnakrej(f, code, id, inp, len); - break; - - case TERMREQ: - fsm_rtermreq(f, id, inp, len); - break; - - case TERMACK: - fsm_rtermack(f); - break; - - case CODEREJ: - fsm_rcoderej(f, inp, len); - break; - - default: - FSMDEBUG(LOG_INFO, ("fsm_input(%s): default: \n", PROTO_NAME(f))); - if( !f->callbacks->extcode || - !(*f->callbacks->extcode)(f, code, id, inp, len) ) { - fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN); - } - break; - } -} - - -/* - * fsm_rconfreq - Receive Configure-Request. - */ -static void -fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len) -{ - int code, reject_if_disagree; - - FSMDEBUG(LOG_INFO, ("fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n", - PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); - switch( f->state ) { - case LS_CLOSED: - /* Go away, we're closed */ - fsm_sdata(f, TERMACK, id, NULL, 0); - return; - case LS_CLOSING: - case LS_STOPPING: - return; - - case LS_OPENED: - /* Go down and restart negotiation */ - if( f->callbacks->down ) { - (*f->callbacks->down)(f); /* Inform upper layers */ - } - fsm_sconfreq(f, 0); /* Send initial Configure-Request */ - break; - - case LS_STOPPED: - /* Negotiation started by our peer */ - fsm_sconfreq(f, 0); /* Send initial Configure-Request */ - f->state = LS_REQSENT; - break; - } - - /* - * Pass the requested configuration options - * to protocol-specific code for checking. - */ - if (f->callbacks->reqci) { /* Check CI */ - reject_if_disagree = (f->nakloops >= f->maxnakloops); - code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree); - } else if (len) { - code = CONFREJ; /* Reject all CI */ - } else { - code = CONFACK; - } - - /* send the Ack, Nak or Rej to the peer */ - fsm_sdata(f, (u_char)code, id, inp, len); - - if (code == CONFACK) { - if (f->state == LS_ACKRCVD) { - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - f->state = LS_OPENED; - if (f->callbacks->up) { - (*f->callbacks->up)(f); /* Inform upper layers */ - } - } else { - f->state = LS_ACKSENT; - } - f->nakloops = 0; - } else { - /* we sent CONFACK or CONFREJ */ - if (f->state != LS_ACKRCVD) { - f->state = LS_REQSENT; - } - if( code == CONFNAK ) { - ++f->nakloops; - } - } -} - - -/* - * fsm_rconfack - Receive Configure-Ack. - */ -static void -fsm_rconfack(fsm *f, int id, u_char *inp, int len) -{ - FSMDEBUG(LOG_INFO, ("fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n", - PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); - - if (id != f->reqid || f->seen_ack) { /* Expected id? */ - return; /* Nope, toss... */ - } - if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ) { - /* Ack is bad - ignore it */ - FSMDEBUG(LOG_INFO, ("%s: received bad Ack (length %d)\n", - PROTO_NAME(f), len)); - return; - } - f->seen_ack = 1; - - switch (f->state) { - case LS_CLOSED: - case LS_STOPPED: - fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); - break; - - case LS_REQSENT: - f->state = LS_ACKRCVD; - f->retransmits = f->maxconfreqtransmits; - break; - - case LS_ACKRCVD: - /* Huh? an extra valid Ack? oh well... */ - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - fsm_sconfreq(f, 0); - f->state = LS_REQSENT; - break; - - case LS_ACKSENT: - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - f->state = LS_OPENED; - f->retransmits = f->maxconfreqtransmits; - if (f->callbacks->up) { - (*f->callbacks->up)(f); /* Inform upper layers */ - } - break; - - case LS_OPENED: - /* Go down and restart negotiation */ - if (f->callbacks->down) { - (*f->callbacks->down)(f); /* Inform upper layers */ - } - fsm_sconfreq(f, 0); /* Send initial Configure-Request */ - f->state = LS_REQSENT; - break; - } -} - - -/* - * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. - */ -static void -fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) -{ - int (*proc) (fsm *, u_char *, int); - int ret; - - FSMDEBUG(LOG_INFO, ("fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n", - PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); - - if (id != f->reqid || f->seen_ack) { /* Expected id? */ - return; /* Nope, toss... */ - } - proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci; - if (!proc || !((ret = proc(f, inp, len)))) { - /* Nak/reject is bad - ignore it */ - FSMDEBUG(LOG_INFO, ("%s: received bad %s (length %d)\n", - PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len)); - return; - } - f->seen_ack = 1; - - switch (f->state) { - case LS_CLOSED: - case LS_STOPPED: - fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); - break; - - case LS_REQSENT: - case LS_ACKSENT: - /* They didn't agree to what we wanted - try another request */ - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - if (ret < 0) { - f->state = LS_STOPPED; /* kludge for stopping CCP */ - } else { - fsm_sconfreq(f, 0); /* Send Configure-Request */ - } - break; - - case LS_ACKRCVD: - /* Got a Nak/reject when we had already had an Ack?? oh well... */ - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - fsm_sconfreq(f, 0); - f->state = LS_REQSENT; - break; - - case LS_OPENED: - /* Go down and restart negotiation */ - if (f->callbacks->down) { - (*f->callbacks->down)(f); /* Inform upper layers */ - } - fsm_sconfreq(f, 0); /* Send initial Configure-Request */ - f->state = LS_REQSENT; - break; - } -} - - -/* - * fsm_rtermreq - Receive Terminate-Req. - */ -static void -fsm_rtermreq(fsm *f, int id, u_char *p, int len) -{ - LWIP_UNUSED_ARG(p); - - FSMDEBUG(LOG_INFO, ("fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n", - PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); - - switch (f->state) { - case LS_ACKRCVD: - case LS_ACKSENT: - f->state = LS_REQSENT; /* Start over but keep trying */ - break; - - case LS_OPENED: - if (len > 0) { - FSMDEBUG(LOG_INFO, ("%s terminated by peer (%p)\n", PROTO_NAME(f), p)); - } else { - FSMDEBUG(LOG_INFO, ("%s terminated by peer\n", PROTO_NAME(f))); - } - if (f->callbacks->down) { - (*f->callbacks->down)(f); /* Inform upper layers */ - } - f->retransmits = 0; - f->state = LS_STOPPING; - TIMEOUT(fsm_timeout, f, f->timeouttime); - break; - } - - fsm_sdata(f, TERMACK, (u_char)id, NULL, 0); -} - - -/* - * fsm_rtermack - Receive Terminate-Ack. - */ -static void -fsm_rtermack(fsm *f) -{ - FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): state=%d (%s)\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - - switch (f->state) { - case LS_CLOSING: - UNTIMEOUT(fsm_timeout, f); - f->state = LS_CLOSED; - if( f->callbacks->finished ) { - (*f->callbacks->finished)(f); - } - break; - - case LS_STOPPING: - UNTIMEOUT(fsm_timeout, f); - f->state = LS_STOPPED; - if( f->callbacks->finished ) { - (*f->callbacks->finished)(f); - } - break; - - case LS_ACKRCVD: - f->state = LS_REQSENT; - break; - - case LS_OPENED: - if (f->callbacks->down) { - (*f->callbacks->down)(f); /* Inform upper layers */ - } - fsm_sconfreq(f, 0); - break; - default: - FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): UNHANDLED state=%d (%s)!!!\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - } -} - - -/* - * fsm_rcoderej - Receive an Code-Reject. - */ -static void -fsm_rcoderej(fsm *f, u_char *inp, int len) -{ - u_char code, id; - - FSMDEBUG(LOG_INFO, ("fsm_rcoderej(%s): state=%d (%s)\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - - if (len < HEADERLEN) { - FSMDEBUG(LOG_INFO, ("fsm_rcoderej: Rcvd short Code-Reject packet!\n")); - return; - } - GETCHAR(code, inp); - GETCHAR(id, inp); - FSMDEBUG(LOG_WARNING, ("%s: Rcvd Code-Reject for code %d, id %d\n", - PROTO_NAME(f), code, id)); - - if( f->state == LS_ACKRCVD ) { - f->state = LS_REQSENT; - } -} - - -/* - * fsm_protreject - Peer doesn't speak this protocol. - * - * Treat this as a catastrophic error (RXJ-). - */ -void -fsm_protreject(fsm *f) -{ - switch( f->state ) { - case LS_CLOSING: - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - /* fall through */ - case LS_CLOSED: - f->state = LS_CLOSED; - if( f->callbacks->finished ) { - (*f->callbacks->finished)(f); - } - break; - - case LS_STOPPING: - case LS_REQSENT: - case LS_ACKRCVD: - case LS_ACKSENT: - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - /* fall through */ - case LS_STOPPED: - f->state = LS_STOPPED; - if( f->callbacks->finished ) { - (*f->callbacks->finished)(f); - } - break; - - case LS_OPENED: - if( f->callbacks->down ) { - (*f->callbacks->down)(f); - } - /* Init restart counter, send Terminate-Request */ - f->retransmits = f->maxtermtransmits; - fsm_sdata(f, TERMREQ, f->reqid = ++f->id, - (u_char *) f->term_reason, f->term_reason_len); - TIMEOUT(fsm_timeout, f, f->timeouttime); - --f->retransmits; - - f->state = LS_STOPPING; - break; - - default: - FSMDEBUG(LOG_INFO, ("%s: Protocol-reject event in state %d (%s)!\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - } -} - - -/* - * fsm_sconfreq - Send a Configure-Request. - */ -static void -fsm_sconfreq(fsm *f, int retransmit) -{ - u_char *outp; - int cilen; - - if( f->state != LS_REQSENT && f->state != LS_ACKRCVD && f->state != LS_ACKSENT ) { - /* Not currently negotiating - reset options */ - if( f->callbacks->resetci ) { - (*f->callbacks->resetci)(f); - } - f->nakloops = 0; - } - - if( !retransmit ) { - /* New request - reset retransmission counter, use new ID */ - f->retransmits = f->maxconfreqtransmits; - f->reqid = ++f->id; - } - - f->seen_ack = 0; - - /* - * Make up the request packet - */ - outp = outpacket_buf[f->unit] + PPP_HDRLEN + HEADERLEN; - if( f->callbacks->cilen && f->callbacks->addci ) { - cilen = (*f->callbacks->cilen)(f); - if( cilen > peer_mru[f->unit] - (int)HEADERLEN ) { - cilen = peer_mru[f->unit] - HEADERLEN; - } - if (f->callbacks->addci) { - (*f->callbacks->addci)(f, outp, &cilen); - } - } else { - cilen = 0; - } - - /* send the request to our peer */ - fsm_sdata(f, CONFREQ, f->reqid, outp, cilen); - - /* start the retransmit timer */ - --f->retransmits; - TIMEOUT(fsm_timeout, f, f->timeouttime); - - FSMDEBUG(LOG_INFO, ("%s: sending Configure-Request, id %d\n", - PROTO_NAME(f), f->reqid)); -} - - -/* - * fsm_sdata - Send some data. - * - * Used for all packets sent to our peer by this module. - */ -void -fsm_sdata( fsm *f, u_char code, u_char id, u_char *data, int datalen) -{ - u_char *outp; - int outlen; - - /* Adjust length to be smaller than MTU */ - outp = outpacket_buf[f->unit]; - if (datalen > peer_mru[f->unit] - (int)HEADERLEN) { - datalen = peer_mru[f->unit] - HEADERLEN; - } - if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) { - BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen); - } - outlen = datalen + HEADERLEN; - MAKEHEADER(outp, f->protocol); - PUTCHAR(code, outp); - PUTCHAR(id, outp); - PUTSHORT(outlen, outp); - pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN); - FSMDEBUG(LOG_INFO, ("fsm_sdata(%s): Sent code %d,%d,%d.\n", - PROTO_NAME(f), code, id, outlen)); -} - -#endif /* PPP_SUPPORT */ diff --git a/third_party/lwip/netif/ppp/fsm.h b/third_party/lwip/netif/ppp/fsm.h deleted file mode 100644 index 9bc7832..0000000 --- a/third_party/lwip/netif/ppp/fsm.h +++ /dev/null @@ -1,157 +0,0 @@ -/***************************************************************************** -* fsm.h - Network Control Protocol Finite State Machine header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* Copyright (c) 1997 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-11-05 Guy Lancaster , Global Election Systems Inc. -* Original based on BSD code. -*****************************************************************************/ -/* - * fsm.h - {Link, IP} Control Protocol Finite State Machine definitions. - * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * $Id: fsm.h,v 1.5 2009/12/31 17:08:08 goldsimon Exp $ - */ - -#ifndef FSM_H -#define FSM_H - -/* - * LCP Packet header = Code, id, length. - */ -#define HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short)) - - -/* - * CP (LCP, IPCP, etc.) codes. - */ -#define CONFREQ 1 /* Configuration Request */ -#define CONFACK 2 /* Configuration Ack */ -#define CONFNAK 3 /* Configuration Nak */ -#define CONFREJ 4 /* Configuration Reject */ -#define TERMREQ 5 /* Termination Request */ -#define TERMACK 6 /* Termination Ack */ -#define CODEREJ 7 /* Code Reject */ - - -/* - * Each FSM is described by an fsm structure and fsm callbacks. - */ -typedef struct fsm { - int unit; /* Interface unit number */ - u_short protocol; /* Data Link Layer Protocol field value */ - int state; /* State */ - int flags; /* Contains option bits */ - u_char id; /* Current id */ - u_char reqid; /* Current request id */ - u_char seen_ack; /* Have received valid Ack/Nak/Rej to Req */ - int timeouttime; /* Timeout time in milliseconds */ - int maxconfreqtransmits; /* Maximum Configure-Request transmissions */ - int retransmits; /* Number of retransmissions left */ - int maxtermtransmits; /* Maximum Terminate-Request transmissions */ - int nakloops; /* Number of nak loops since last ack */ - int maxnakloops; /* Maximum number of nak loops tolerated */ - struct fsm_callbacks* callbacks; /* Callback routines */ - char* term_reason; /* Reason for closing protocol */ - int term_reason_len; /* Length of term_reason */ -} fsm; - - -typedef struct fsm_callbacks { - void (*resetci)(fsm*); /* Reset our Configuration Information */ - int (*cilen)(fsm*); /* Length of our Configuration Information */ - void (*addci)(fsm*, u_char*, int*); /* Add our Configuration Information */ - int (*ackci)(fsm*, u_char*, int); /* ACK our Configuration Information */ - int (*nakci)(fsm*, u_char*, int); /* NAK our Configuration Information */ - int (*rejci)(fsm*, u_char*, int); /* Reject our Configuration Information */ - int (*reqci)(fsm*, u_char*, int*, int); /* Request peer's Configuration Information */ - void (*up)(fsm*); /* Called when fsm reaches LS_OPENED state */ - void (*down)(fsm*); /* Called when fsm leaves LS_OPENED state */ - void (*starting)(fsm*); /* Called when we want the lower layer */ - void (*finished)(fsm*); /* Called when we don't want the lower layer */ - void (*protreject)(int); /* Called when Protocol-Reject received */ - void (*retransmit)(fsm*); /* Retransmission is necessary */ - int (*extcode)(fsm*, int, u_char, u_char*, int); /* Called when unknown code received */ - char *proto_name; /* String name for protocol (for messages) */ -} fsm_callbacks; - - -/* - * Link states. - */ -#define LS_INITIAL 0 /* Down, hasn't been opened */ -#define LS_STARTING 1 /* Down, been opened */ -#define LS_CLOSED 2 /* Up, hasn't been opened */ -#define LS_STOPPED 3 /* Open, waiting for down event */ -#define LS_CLOSING 4 /* Terminating the connection, not open */ -#define LS_STOPPING 5 /* Terminating, but open */ -#define LS_REQSENT 6 /* We've sent a Config Request */ -#define LS_ACKRCVD 7 /* We've received a Config Ack */ -#define LS_ACKSENT 8 /* We've sent a Config Ack */ -#define LS_OPENED 9 /* Connection available */ - -/* - * Flags - indicate options controlling FSM operation - */ -#define OPT_PASSIVE 1 /* Don't die if we don't get a response */ -#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */ -#define OPT_SILENT 4 /* Wait for peer to speak first */ - - -/* - * Prototypes - */ -void fsm_init (fsm*); -void fsm_lowerup (fsm*); -void fsm_lowerdown (fsm*); -void fsm_open (fsm*); -void fsm_close (fsm*, char*); -void fsm_input (fsm*, u_char*, int); -void fsm_protreject (fsm*); -void fsm_sdata (fsm*, u_char, u_char, u_char*, int); - - -/* - * Variables - */ -extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */ - -#endif /* FSM_H */ diff --git a/third_party/lwip/netif/ppp/ipcp.c b/third_party/lwip/netif/ppp/ipcp.c deleted file mode 100644 index d9aee84..0000000 --- a/third_party/lwip/netif/ppp/ipcp.c +++ /dev/null @@ -1,1411 +0,0 @@ -/** In contrast to pppd 2.3.1, DNS support has been added, proxy-ARP and - dial-on-demand has been stripped. */ -/***************************************************************************** -* ipcp.c - Network PPP IP Control Protocol program file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 by Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-12-08 Guy Lancaster , Global Election Systems Inc. -* Original. -*****************************************************************************/ -/* - * ipcp.c - PPP IP Control Protocol. - * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#include "lwip/opt.h" - -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "ppp_impl.h" -#include "pppdebug.h" - -#include "auth.h" -#include "fsm.h" -#include "vj.h" -#include "ipcp.h" - -#include "lwip/inet.h" - -#include - -/* #define OLD_CI_ADDRS 1 */ /* Support deprecated address negotiation. */ - -/* global vars */ -ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */ -ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ -ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ -ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ - -/* local vars */ -static int default_route_set[NUM_PPP]; /* Have set up a default route */ -static int cis_received[NUM_PPP]; /* # Conf-Reqs received */ - - -/* - * Callbacks for fsm code. (CI = Configuration Information) - */ -static void ipcp_resetci (fsm *); /* Reset our CI */ -static int ipcp_cilen (fsm *); /* Return length of our CI */ -static void ipcp_addci (fsm *, u_char *, int *); /* Add our CI */ -static int ipcp_ackci (fsm *, u_char *, int); /* Peer ack'd our CI */ -static int ipcp_nakci (fsm *, u_char *, int); /* Peer nak'd our CI */ -static int ipcp_rejci (fsm *, u_char *, int); /* Peer rej'd our CI */ -static int ipcp_reqci (fsm *, u_char *, int *, int); /* Rcv CI */ -static void ipcp_up (fsm *); /* We're UP */ -static void ipcp_down (fsm *); /* We're DOWN */ -#if PPP_ADDITIONAL_CALLBACKS -static void ipcp_script (fsm *, char *); /* Run an up/down script */ -#endif -static void ipcp_finished (fsm *); /* Don't need lower layer */ - - -fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */ - - -static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ - ipcp_resetci, /* Reset our Configuration Information */ - ipcp_cilen, /* Length of our Configuration Information */ - ipcp_addci, /* Add our Configuration Information */ - ipcp_ackci, /* ACK our Configuration Information */ - ipcp_nakci, /* NAK our Configuration Information */ - ipcp_rejci, /* Reject our Configuration Information */ - ipcp_reqci, /* Request peer's Configuration Information */ - ipcp_up, /* Called when fsm reaches LS_OPENED state */ - ipcp_down, /* Called when fsm leaves LS_OPENED state */ - NULL, /* Called when we want the lower layer up */ - ipcp_finished, /* Called when we want the lower layer down */ - NULL, /* Called when Protocol-Reject received */ - NULL, /* Retransmission is necessary */ - NULL, /* Called to handle protocol-specific codes */ - "IPCP" /* String name of protocol */ -}; - -/* - * Protocol entry points from main code. - */ -static void ipcp_init (int); -static void ipcp_open (int); -static void ipcp_close (int, char *); -static void ipcp_lowerup (int); -static void ipcp_lowerdown (int); -static void ipcp_input (int, u_char *, int); -static void ipcp_protrej (int); - - -struct protent ipcp_protent = { - PPP_IPCP, - ipcp_init, - ipcp_input, - ipcp_protrej, - ipcp_lowerup, - ipcp_lowerdown, - ipcp_open, - ipcp_close, -#if PPP_ADDITIONAL_CALLBACKS - ipcp_printpkt, - NULL, -#endif /* PPP_ADDITIONAL_CALLBACKS */ - 1, - "IPCP", -#if PPP_ADDITIONAL_CALLBACKS - ip_check_options, - NULL, - ip_active_pkt -#endif /* PPP_ADDITIONAL_CALLBACKS */ -}; - -static void ipcp_clear_addrs (int); - -/* - * Lengths of configuration options. - */ -#define CILEN_VOID 2 -#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ -#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ -#define CILEN_ADDR 6 /* new-style single address option */ -#define CILEN_ADDRS 10 /* old-style dual address option */ - - -#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ - (x) == CONFNAK ? "NAK" : "REJ") - - -/* - * ipcp_init - Initialize IPCP. - */ -static void -ipcp_init(int unit) -{ - fsm *f = &ipcp_fsm[unit]; - ipcp_options *wo = &ipcp_wantoptions[unit]; - ipcp_options *ao = &ipcp_allowoptions[unit]; - - f->unit = unit; - f->protocol = PPP_IPCP; - f->callbacks = &ipcp_callbacks; - fsm_init(&ipcp_fsm[unit]); - - memset(wo, 0, sizeof(*wo)); - memset(ao, 0, sizeof(*ao)); - - wo->neg_addr = 1; - wo->ouraddr = 0; -#if VJ_SUPPORT - wo->neg_vj = 1; -#else /* VJ_SUPPORT */ - wo->neg_vj = 0; -#endif /* VJ_SUPPORT */ - wo->vj_protocol = IPCP_VJ_COMP; - wo->maxslotindex = MAX_SLOTS - 1; - wo->cflag = 0; - wo->default_route = 1; - - ao->neg_addr = 1; -#if VJ_SUPPORT - ao->neg_vj = 1; -#else /* VJ_SUPPORT */ - ao->neg_vj = 0; -#endif /* VJ_SUPPORT */ - ao->maxslotindex = MAX_SLOTS - 1; - ao->cflag = 1; - ao->default_route = 1; -} - - -/* - * ipcp_open - IPCP is allowed to come up. - */ -static void -ipcp_open(int unit) -{ - fsm_open(&ipcp_fsm[unit]); -} - - -/* - * ipcp_close - Take IPCP down. - */ -static void -ipcp_close(int unit, char *reason) -{ - fsm_close(&ipcp_fsm[unit], reason); -} - - -/* - * ipcp_lowerup - The lower layer is up. - */ -static void -ipcp_lowerup(int unit) -{ - fsm_lowerup(&ipcp_fsm[unit]); -} - - -/* - * ipcp_lowerdown - The lower layer is down. - */ -static void -ipcp_lowerdown(int unit) -{ - fsm_lowerdown(&ipcp_fsm[unit]); -} - - -/* - * ipcp_input - Input IPCP packet. - */ -static void -ipcp_input(int unit, u_char *p, int len) -{ - fsm_input(&ipcp_fsm[unit], p, len); -} - - -/* - * ipcp_protrej - A Protocol-Reject was received for IPCP. - * - * Pretend the lower layer went down, so we shut up. - */ -static void -ipcp_protrej(int unit) -{ - fsm_lowerdown(&ipcp_fsm[unit]); -} - - -/* - * ipcp_resetci - Reset our CI. - */ -static void -ipcp_resetci(fsm *f) -{ - ipcp_options *wo = &ipcp_wantoptions[f->unit]; - - wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr; - if (wo->ouraddr == 0) { - wo->accept_local = 1; - } - if (wo->hisaddr == 0) { - wo->accept_remote = 1; - } - /* Request DNS addresses from the peer */ - wo->req_dns1 = ppp_settings.usepeerdns; - wo->req_dns2 = ppp_settings.usepeerdns; - ipcp_gotoptions[f->unit] = *wo; - cis_received[f->unit] = 0; -} - - -/* - * ipcp_cilen - Return length of our CI. - */ -static int -ipcp_cilen(fsm *f) -{ - ipcp_options *go = &ipcp_gotoptions[f->unit]; - ipcp_options *wo = &ipcp_wantoptions[f->unit]; - ipcp_options *ho = &ipcp_hisoptions[f->unit]; - -#define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) -#define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0) -#define LENCIDNS(neg) (neg ? (CILEN_ADDR) : 0) - - /* - * First see if we want to change our options to the old - * forms because we have received old forms from the peer. - */ - if (wo->neg_addr && !go->neg_addr && !go->old_addrs) { - /* use the old style of address negotiation */ - go->neg_addr = 1; - go->old_addrs = 1; - } - if (wo->neg_vj && !go->neg_vj && !go->old_vj) { - /* try an older style of VJ negotiation */ - if (cis_received[f->unit] == 0) { - /* keep trying the new style until we see some CI from the peer */ - go->neg_vj = 1; - } else { - /* use the old style only if the peer did */ - if (ho->neg_vj && ho->old_vj) { - go->neg_vj = 1; - go->old_vj = 1; - go->vj_protocol = ho->vj_protocol; - } - } - } - - return (LENCIADDR(go->neg_addr, go->old_addrs) + - LENCIVJ(go->neg_vj, go->old_vj) + - LENCIDNS(go->req_dns1) + - LENCIDNS(go->req_dns2)); -} - - -/* - * ipcp_addci - Add our desired CIs to a packet. - */ -static void -ipcp_addci(fsm *f, u_char *ucp, int *lenp) -{ - ipcp_options *go = &ipcp_gotoptions[f->unit]; - int len = *lenp; - -#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ - if (neg) { \ - int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ - if (len >= vjlen) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(vjlen, ucp); \ - PUTSHORT(val, ucp); \ - if (!old) { \ - PUTCHAR(maxslotindex, ucp); \ - PUTCHAR(cflag, ucp); \ - } \ - len -= vjlen; \ - } else { \ - neg = 0; \ - } \ - } - -#define ADDCIADDR(opt, neg, old, val1, val2) \ - if (neg) { \ - int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ - if (len >= addrlen) { \ - u32_t l; \ - PUTCHAR(opt, ucp); \ - PUTCHAR(addrlen, ucp); \ - l = ntohl(val1); \ - PUTLONG(l, ucp); \ - if (old) { \ - l = ntohl(val2); \ - PUTLONG(l, ucp); \ - } \ - len -= addrlen; \ - } else { \ - neg = 0; \ - } \ - } - -#define ADDCIDNS(opt, neg, addr) \ - if (neg) { \ - if (len >= CILEN_ADDR) { \ - u32_t l; \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_ADDR, ucp); \ - l = ntohl(addr); \ - PUTLONG(l, ucp); \ - len -= CILEN_ADDR; \ - } else { \ - neg = 0; \ - } \ - } - - ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, - go->old_addrs, go->ouraddr, go->hisaddr); - - ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, - go->maxslotindex, go->cflag); - - ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); - - ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); - - *lenp -= len; -} - - -/* - * ipcp_ackci - Ack our CIs. - * - * Returns: - * 0 - Ack was bad. - * 1 - Ack was good. - */ -static int -ipcp_ackci(fsm *f, u_char *p, int len) -{ - ipcp_options *go = &ipcp_gotoptions[f->unit]; - u_short cilen, citype, cishort; - u32_t cilong; - u_char cimaxslotindex, cicflag; - - /* - * CIs must be in exactly the same order that we sent... - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ - -#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ - if (neg) { \ - int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ - if ((len -= vjlen) < 0) { \ - goto bad; \ - } \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != vjlen || \ - citype != opt) { \ - goto bad; \ - } \ - GETSHORT(cishort, p); \ - if (cishort != val) { \ - goto bad; \ - } \ - if (!old) { \ - GETCHAR(cimaxslotindex, p); \ - if (cimaxslotindex != maxslotindex) { \ - goto bad; \ - } \ - GETCHAR(cicflag, p); \ - if (cicflag != cflag) { \ - goto bad; \ - } \ - } \ - } - -#define ACKCIADDR(opt, neg, old, val1, val2) \ - if (neg) { \ - int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ - u32_t l; \ - if ((len -= addrlen) < 0) { \ - goto bad; \ - } \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != addrlen || \ - citype != opt) { \ - goto bad; \ - } \ - GETLONG(l, p); \ - cilong = htonl(l); \ - if (val1 != cilong) { \ - goto bad; \ - } \ - if (old) { \ - GETLONG(l, p); \ - cilong = htonl(l); \ - if (val2 != cilong) { \ - goto bad; \ - } \ - } \ - } - -#define ACKCIDNS(opt, neg, addr) \ - if (neg) { \ - u32_t l; \ - if ((len -= CILEN_ADDR) < 0) { \ - goto bad; \ - } \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_ADDR || \ - citype != opt) { \ - goto bad; \ - } \ - GETLONG(l, p); \ - cilong = htonl(l); \ - if (addr != cilong) { \ - goto bad; \ - } \ - } - - ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, - go->old_addrs, go->ouraddr, go->hisaddr); - - ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, - go->maxslotindex, go->cflag); - - ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); - - ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) { - goto bad; - } - return (1); - -bad: - IPCPDEBUG(LOG_INFO, ("ipcp_ackci: received bad Ack!\n")); - return (0); -} - -/* - * ipcp_nakci - Peer has sent a NAK for some of our CIs. - * This should not modify any state if the Nak is bad - * or if IPCP is in the LS_OPENED state. - * - * Returns: - * 0 - Nak was bad. - * 1 - Nak was good. - */ -static int -ipcp_nakci(fsm *f, u_char *p, int len) -{ - ipcp_options *go = &ipcp_gotoptions[f->unit]; - u_char cimaxslotindex, cicflag; - u_char citype, cilen, *next; - u_short cishort; - u32_t ciaddr1, ciaddr2, l, cidnsaddr; - ipcp_options no; /* options we've seen Naks for */ - ipcp_options try; /* options to request next time */ - - BZERO(&no, sizeof(no)); - try = *go; - - /* - * Any Nak'd CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define NAKCIADDR(opt, neg, old, code) \ - if (go->neg && \ - len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \ - p[1] == cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - ciaddr1 = htonl(l); \ - if (old) { \ - GETLONG(l, p); \ - ciaddr2 = htonl(l); \ - no.old_addrs = 1; \ - } else { \ - ciaddr2 = 0; \ - } \ - no.neg = 1; \ - code \ - } - -#define NAKCIVJ(opt, neg, code) \ - if (go->neg && \ - ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ - len >= cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - no.neg = 1; \ - code \ - } - -#define NAKCIDNS(opt, neg, code) \ - if (go->neg && \ - ((cilen = p[1]) == CILEN_ADDR) && \ - len >= cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - cidnsaddr = htonl(l); \ - no.neg = 1; \ - code \ - } - - /* - * Accept the peer's idea of {our,his} address, if different - * from our idea, only if the accept_{local,remote} flag is set. - */ - NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs, - if (go->accept_local && ciaddr1) { /* Do we know our address? */ - try.ouraddr = ciaddr1; - IPCPDEBUG(LOG_INFO, ("local IP address %s\n", - inet_ntoa(ciaddr1))); - } - if (go->accept_remote && ciaddr2) { /* Does he know his? */ - try.hisaddr = ciaddr2; - IPCPDEBUG(LOG_INFO, ("remote IP address %s\n", - inet_ntoa(ciaddr2))); - } - ); - - /* - * Accept the peer's value of maxslotindex provided that it - * is less than what we asked for. Turn off slot-ID compression - * if the peer wants. Send old-style compress-type option if - * the peer wants. - */ - NAKCIVJ(CI_COMPRESSTYPE, neg_vj, - if (cilen == CILEN_VJ) { - GETCHAR(cimaxslotindex, p); - GETCHAR(cicflag, p); - if (cishort == IPCP_VJ_COMP) { - try.old_vj = 0; - if (cimaxslotindex < go->maxslotindex) { - try.maxslotindex = cimaxslotindex; - } - if (!cicflag) { - try.cflag = 0; - } - } else { - try.neg_vj = 0; - } - } else { - if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { - try.old_vj = 1; - try.vj_protocol = cishort; - } else { - try.neg_vj = 0; - } - } - ); - - NAKCIDNS(CI_MS_DNS1, req_dns1, - try.dnsaddr[0] = cidnsaddr; - IPCPDEBUG(LOG_INFO, ("primary DNS address %s\n", inet_ntoa(cidnsaddr))); - ); - - NAKCIDNS(CI_MS_DNS2, req_dns2, - try.dnsaddr[1] = cidnsaddr; - IPCPDEBUG(LOG_INFO, ("secondary DNS address %s\n", inet_ntoa(cidnsaddr))); - ); - - /* - * There may be remaining CIs, if the peer is requesting negotiation - * on an option that we didn't include in our request packet. - * If they want to negotiate about IP addresses, we comply. - * If they want us to ask for compression, we refuse. - */ - while (len > CILEN_VOID) { - GETCHAR(citype, p); - GETCHAR(cilen, p); - if( (len -= cilen) < 0 ) { - goto bad; - } - next = p + cilen - 2; - - switch (citype) { - case CI_COMPRESSTYPE: - if (go->neg_vj || no.neg_vj || - (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) { - goto bad; - } - no.neg_vj = 1; - break; - case CI_ADDRS: - if ((go->neg_addr && go->old_addrs) || no.old_addrs - || cilen != CILEN_ADDRS) { - goto bad; - } - try.neg_addr = 1; - try.old_addrs = 1; - GETLONG(l, p); - ciaddr1 = htonl(l); - if (ciaddr1 && go->accept_local) { - try.ouraddr = ciaddr1; - } - GETLONG(l, p); - ciaddr2 = htonl(l); - if (ciaddr2 && go->accept_remote) { - try.hisaddr = ciaddr2; - } - no.old_addrs = 1; - break; - case CI_ADDR: - if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) { - goto bad; - } - try.old_addrs = 0; - GETLONG(l, p); - ciaddr1 = htonl(l); - if (ciaddr1 && go->accept_local) { - try.ouraddr = ciaddr1; - } - if (try.ouraddr != 0) { - try.neg_addr = 1; - } - no.neg_addr = 1; - break; - } - p = next; - } - - /* If there is still anything left, this packet is bad. */ - if (len != 0) { - goto bad; - } - - /* - * OK, the Nak is good. Now we can update state. - */ - if (f->state != LS_OPENED) { - *go = try; - } - - return 1; - -bad: - IPCPDEBUG(LOG_INFO, ("ipcp_nakci: received bad Nak!\n")); - return 0; -} - - -/* - * ipcp_rejci - Reject some of our CIs. - */ -static int -ipcp_rejci(fsm *f, u_char *p, int len) -{ - ipcp_options *go = &ipcp_gotoptions[f->unit]; - u_char cimaxslotindex, ciflag, cilen; - u_short cishort; - u32_t cilong; - ipcp_options try; /* options to request next time */ - - try = *go; - /* - * Any Rejected CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define REJCIADDR(opt, neg, old, val1, val2) \ - if (go->neg && \ - len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \ - p[1] == cilen && \ - p[0] == opt) { \ - u32_t l; \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - cilong = htonl(l); \ - /* Check rejected value. */ \ - if (cilong != val1) { \ - goto bad; \ - } \ - if (old) { \ - GETLONG(l, p); \ - cilong = htonl(l); \ - /* Check rejected value. */ \ - if (cilong != val2) { \ - goto bad; \ - } \ - } \ - try.neg = 0; \ - } - -#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ - if (go->neg && \ - p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ - len >= p[1] && \ - p[0] == opt) { \ - len -= p[1]; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - /* Check rejected value. */ \ - if (cishort != val) { \ - goto bad; \ - } \ - if (!old) { \ - GETCHAR(cimaxslotindex, p); \ - if (cimaxslotindex != maxslot) { \ - goto bad; \ - } \ - GETCHAR(ciflag, p); \ - if (ciflag != cflag) { \ - goto bad; \ - } \ - } \ - try.neg = 0; \ - } - -#define REJCIDNS(opt, neg, dnsaddr) \ - if (go->neg && \ - ((cilen = p[1]) == CILEN_ADDR) && \ - len >= cilen && \ - p[0] == opt) { \ - u32_t l; \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - cilong = htonl(l); \ - /* Check rejected value. */ \ - if (cilong != dnsaddr) { \ - goto bad; \ - } \ - try.neg = 0; \ - } - - REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, - go->old_addrs, go->ouraddr, go->hisaddr); - - REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, - go->maxslotindex, go->cflag); - - REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); - - REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) { - goto bad; - } - /* - * Now we can update state. - */ - if (f->state != LS_OPENED) { - *go = try; - } - return 1; - -bad: - IPCPDEBUG(LOG_INFO, ("ipcp_rejci: received bad Reject!\n")); - return 0; -} - - -/* - * ipcp_reqci - Check the peer's requested CIs and send appropriate response. - * - * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified - * appropriately. If reject_if_disagree is non-zero, doesn't return - * CONFNAK; returns CONFREJ if it can't return CONFACK. - */ -static int -ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested CIs */,int reject_if_disagree) -{ - ipcp_options *wo = &ipcp_wantoptions[f->unit]; - ipcp_options *ho = &ipcp_hisoptions[f->unit]; - ipcp_options *ao = &ipcp_allowoptions[f->unit]; -#ifdef OLD_CI_ADDRS - ipcp_options *go = &ipcp_gotoptions[f->unit]; -#endif - u_char *cip, *next; /* Pointer to current and next CIs */ - u_short cilen, citype; /* Parsed len, type */ - u_short cishort; /* Parsed short value */ - u32_t tl, ciaddr1; /* Parsed address values */ -#ifdef OLD_CI_ADDRS - u32_t ciaddr2; /* Parsed address values */ -#endif - int rc = CONFACK; /* Final packet return code */ - int orc; /* Individual option return code */ - u_char *p; /* Pointer to next char to parse */ - u_char *ucp = inp; /* Pointer to current output char */ - int l = *len; /* Length left */ - u_char maxslotindex, cflag; - int d; - - cis_received[f->unit] = 1; - - /* - * Reset all his options. - */ - BZERO(ho, sizeof(*ho)); - - /* - * Process all his options. - */ - next = inp; - while (l) { - orc = CONFACK; /* Assume success */ - cip = p = next; /* Remember begining of CI */ - if (l < 2 || /* Not enough data for CI header or */ - p[1] < 2 || /* CI length too small or */ - p[1] > l) { /* CI length too big? */ - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: bad CI length!\n")); - orc = CONFREJ; /* Reject bad CI */ - cilen = (u_short)l;/* Reject till end of packet */ - l = 0; /* Don't loop again */ - goto endswitch; - } - GETCHAR(citype, p); /* Parse CI type */ - GETCHAR(cilen, p); /* Parse CI length */ - l -= cilen; /* Adjust remaining length */ - next += cilen; /* Step to next CI */ - - switch (citype) { /* Check CI type */ -#ifdef OLD_CI_ADDRS /* Need to save space... */ - case CI_ADDRS: - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received ADDRS\n")); - if (!ao->neg_addr || - cilen != CILEN_ADDRS) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - - /* - * If he has no address, or if we both have his address but - * disagree about it, then NAK it with our idea. - * In particular, if we don't know his address, but he does, - * then accept it. - */ - GETLONG(tl, p); /* Parse source address (his) */ - ciaddr1 = htonl(tl); - IPCPDEBUG(LOG_INFO, ("his addr %s\n", inet_ntoa(ciaddr1))); - if (ciaddr1 != wo->hisaddr - && (ciaddr1 == 0 || !wo->accept_remote)) { - orc = CONFNAK; - if (!reject_if_disagree) { - DECPTR(sizeof(u32_t), p); - tl = ntohl(wo->hisaddr); - PUTLONG(tl, p); - } - } else if (ciaddr1 == 0 && wo->hisaddr == 0) { - /* - * If neither we nor he knows his address, reject the option. - */ - orc = CONFREJ; - wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ - break; - } - - /* - * If he doesn't know our address, or if we both have our address - * but disagree about it, then NAK it with our idea. - */ - GETLONG(tl, p); /* Parse desination address (ours) */ - ciaddr2 = htonl(tl); - IPCPDEBUG(LOG_INFO, ("our addr %s\n", inet_ntoa(ciaddr2))); - if (ciaddr2 != wo->ouraddr) { - if (ciaddr2 == 0 || !wo->accept_local) { - orc = CONFNAK; - if (!reject_if_disagree) { - DECPTR(sizeof(u32_t), p); - tl = ntohl(wo->ouraddr); - PUTLONG(tl, p); - } - } else { - go->ouraddr = ciaddr2; /* accept peer's idea */ - } - } - - ho->neg_addr = 1; - ho->old_addrs = 1; - ho->hisaddr = ciaddr1; - ho->ouraddr = ciaddr2; - break; -#endif - - case CI_ADDR: - if (!ao->neg_addr) { - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR not allowed\n")); - orc = CONFREJ; /* Reject CI */ - break; - } else if (cilen != CILEN_ADDR) { /* Check CI length */ - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR bad len\n")); - orc = CONFREJ; /* Reject CI */ - break; - } - - /* - * If he has no address, or if we both have his address but - * disagree about it, then NAK it with our idea. - * In particular, if we don't know his address, but he does, - * then accept it. - */ - GETLONG(tl, p); /* Parse source address (his) */ - ciaddr1 = htonl(tl); - if (ciaddr1 != wo->hisaddr - && (ciaddr1 == 0 || !wo->accept_remote)) { - orc = CONFNAK; - if (!reject_if_disagree) { - DECPTR(sizeof(u32_t), p); - tl = ntohl(wo->hisaddr); - PUTLONG(tl, p); - } - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1))); - } else if (ciaddr1 == 0 && wo->hisaddr == 0) { - /* - * Don't ACK an address of 0.0.0.0 - reject it instead. - */ - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1))); - orc = CONFREJ; - wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ - break; - } - - ho->neg_addr = 1; - ho->hisaddr = ciaddr1; - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1))); - break; - - case CI_MS_DNS1: - case CI_MS_DNS2: - /* Microsoft primary or secondary DNS request */ - d = citype == CI_MS_DNS2; - - /* If we do not have a DNS address then we cannot send it */ - if (ao->dnsaddr[d] == 0 || - cilen != CILEN_ADDR) { /* Check CI length */ - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting DNS%d Request\n", d+1)); - orc = CONFREJ; /* Reject CI */ - break; - } - GETLONG(tl, p); - if (htonl(tl) != ao->dnsaddr[d]) { - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking DNS%d Request %s\n", - d+1, inet_ntoa(tl))); - DECPTR(sizeof(u32_t), p); - tl = ntohl(ao->dnsaddr[d]); - PUTLONG(tl, p); - orc = CONFNAK; - } - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received DNS%d Request\n", d+1)); - break; - - case CI_MS_WINS1: - case CI_MS_WINS2: - /* Microsoft primary or secondary WINS request */ - d = citype == CI_MS_WINS2; - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received WINS%d Request\n", d+1)); - - /* If we do not have a DNS address then we cannot send it */ - if (ao->winsaddr[d] == 0 || - cilen != CILEN_ADDR) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - GETLONG(tl, p); - if (htonl(tl) != ao->winsaddr[d]) { - DECPTR(sizeof(u32_t), p); - tl = ntohl(ao->winsaddr[d]); - PUTLONG(tl, p); - orc = CONFNAK; - } - break; - - case CI_COMPRESSTYPE: - if (!ao->neg_vj) { - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n")); - orc = CONFREJ; - break; - } else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) { - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen)); - orc = CONFREJ; - break; - } - GETSHORT(cishort, p); - - if (!(cishort == IPCP_VJ_COMP || - (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) { - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort)); - orc = CONFREJ; - break; - } - - ho->neg_vj = 1; - ho->vj_protocol = cishort; - if (cilen == CILEN_VJ) { - GETCHAR(maxslotindex, p); - if (maxslotindex > ao->maxslotindex) { - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ max slot %d\n", maxslotindex)); - orc = CONFNAK; - if (!reject_if_disagree) { - DECPTR(1, p); - PUTCHAR(ao->maxslotindex, p); - } - } - GETCHAR(cflag, p); - if (cflag && !ao->cflag) { - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ cflag %d\n", cflag)); - orc = CONFNAK; - if (!reject_if_disagree) { - DECPTR(1, p); - PUTCHAR(wo->cflag, p); - } - } - ho->maxslotindex = maxslotindex; - ho->cflag = cflag; - } else { - ho->old_vj = 1; - ho->maxslotindex = MAX_SLOTS - 1; - ho->cflag = 1; - } - IPCPDEBUG(LOG_INFO, ( - "ipcp_reqci: received COMPRESSTYPE p=%d old=%d maxslot=%d cflag=%d\n", - ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag)); - break; - - default: - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting unknown CI type %d\n", citype)); - orc = CONFREJ; - break; - } - -endswitch: - if (orc == CONFACK && /* Good CI */ - rc != CONFACK) { /* but prior CI wasnt? */ - continue; /* Don't send this one */ - } - - if (orc == CONFNAK) { /* Nak this CI? */ - if (reject_if_disagree) { /* Getting fed up with sending NAKs? */ - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting too many naks\n")); - orc = CONFREJ; /* Get tough if so */ - } else { - if (rc == CONFREJ) { /* Rejecting prior CI? */ - continue; /* Don't send this one */ - } - if (rc == CONFACK) { /* Ack'd all prior CIs? */ - rc = CONFNAK; /* Not anymore... */ - ucp = inp; /* Backup */ - } - } - } - - if (orc == CONFREJ && /* Reject this CI */ - rc != CONFREJ) { /* but no prior ones? */ - rc = CONFREJ; - ucp = inp; /* Backup */ - } - - /* Need to move CI? */ - if (ucp != cip) { - BCOPY(cip, ucp, cilen); /* Move it */ - } - - /* Update output pointer */ - INCPTR(cilen, ucp); - } - - /* - * If we aren't rejecting this packet, and we want to negotiate - * their address, and they didn't send their address, then we - * send a NAK with a CI_ADDR option appended. We assume the - * input buffer is long enough that we can append the extra - * option safely. - */ - if (rc != CONFREJ && !ho->neg_addr && - wo->req_addr && !reject_if_disagree) { - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Requesting peer address\n")); - if (rc == CONFACK) { - rc = CONFNAK; - ucp = inp; /* reset pointer */ - wo->req_addr = 0; /* don't ask again */ - } - PUTCHAR(CI_ADDR, ucp); - PUTCHAR(CILEN_ADDR, ucp); - tl = ntohl(wo->hisaddr); - PUTLONG(tl, ucp); - } - - *len = (int)(ucp - inp); /* Compute output length */ - IPCPDEBUG(LOG_INFO, ("ipcp_reqci: returning Configure-%s\n", CODENAME(rc))); - return (rc); /* Return final code */ -} - - -#if 0 -/* - * ip_check_options - check that any IP-related options are OK, - * and assign appropriate defaults. - */ -static void -ip_check_options(u_long localAddr) -{ - ipcp_options *wo = &ipcp_wantoptions[0]; - - /* - * Load our default IP address but allow the remote host to give us - * a new address. - */ - if (wo->ouraddr == 0 && !ppp_settings.disable_defaultip) { - wo->accept_local = 1; /* don't insist on this default value */ - wo->ouraddr = htonl(localAddr); - } -} -#endif - - -/* - * ipcp_up - IPCP has come UP. - * - * Configure the IP network interface appropriately and bring it up. - */ -static void -ipcp_up(fsm *f) -{ - u32_t mask; - ipcp_options *ho = &ipcp_hisoptions[f->unit]; - ipcp_options *go = &ipcp_gotoptions[f->unit]; - ipcp_options *wo = &ipcp_wantoptions[f->unit]; - - np_up(f->unit, PPP_IP); - IPCPDEBUG(LOG_INFO, ("ipcp: up\n")); - - /* - * We must have a non-zero IP address for both ends of the link. - */ - if (!ho->neg_addr) { - ho->hisaddr = wo->hisaddr; - } - - if (ho->hisaddr == 0) { - IPCPDEBUG(LOG_ERR, ("Could not determine remote IP address\n")); - ipcp_close(f->unit, "Could not determine remote IP address"); - return; - } - if (go->ouraddr == 0) { - IPCPDEBUG(LOG_ERR, ("Could not determine local IP address\n")); - ipcp_close(f->unit, "Could not determine local IP address"); - return; - } - - if (ppp_settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { - /*pppGotDNSAddrs(go->dnsaddr[0], go->dnsaddr[1]);*/ - } - - /* - * Check that the peer is allowed to use the IP address it wants. - */ - if (!auth_ip_addr(f->unit, ho->hisaddr)) { - IPCPDEBUG(LOG_ERR, ("Peer is not authorized to use remote address %s\n", - inet_ntoa(ho->hisaddr))); - ipcp_close(f->unit, "Unauthorized remote IP address"); - return; - } - - /* set tcp compression */ - sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex); - - /* - * Set IP addresses and (if specified) netmask. - */ - mask = GetMask(go->ouraddr); - - if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask, go->dnsaddr[0], go->dnsaddr[1])) { - IPCPDEBUG(LOG_WARNING, ("sifaddr failed\n")); - ipcp_close(f->unit, "Interface configuration failed"); - return; - } - - /* bring the interface up for IP */ - if (!sifup(f->unit)) { - IPCPDEBUG(LOG_WARNING, ("sifup failed\n")); - ipcp_close(f->unit, "Interface configuration failed"); - return; - } - - sifnpmode(f->unit, PPP_IP, NPMODE_PASS); - - /* assign a default route through the interface if required */ - if (ipcp_wantoptions[f->unit].default_route) { - if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) { - default_route_set[f->unit] = 1; - } - } - - IPCPDEBUG(LOG_NOTICE, ("local IP address %s\n", inet_ntoa(go->ouraddr))); - IPCPDEBUG(LOG_NOTICE, ("remote IP address %s\n", inet_ntoa(ho->hisaddr))); - if (go->dnsaddr[0]) { - IPCPDEBUG(LOG_NOTICE, ("primary DNS address %s\n", inet_ntoa(go->dnsaddr[0]))); - } - if (go->dnsaddr[1]) { - IPCPDEBUG(LOG_NOTICE, ("secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1]))); - } -} - - -/* - * ipcp_down - IPCP has gone DOWN. - * - * Take the IP network interface down, clear its addresses - * and delete routes through it. - */ -static void -ipcp_down(fsm *f) -{ - IPCPDEBUG(LOG_INFO, ("ipcp: down\n")); - np_down(f->unit, PPP_IP); - sifvjcomp(f->unit, 0, 0, 0); - - sifdown(f->unit); - ipcp_clear_addrs(f->unit); -} - - -/* - * ipcp_clear_addrs() - clear the interface addresses, routes, etc. - */ -static void -ipcp_clear_addrs(int unit) -{ - u32_t ouraddr, hisaddr; - - ouraddr = ipcp_gotoptions[unit].ouraddr; - hisaddr = ipcp_hisoptions[unit].hisaddr; - if (default_route_set[unit]) { - cifdefaultroute(unit, ouraddr, hisaddr); - default_route_set[unit] = 0; - } - cifaddr(unit, ouraddr, hisaddr); -} - - -/* - * ipcp_finished - possibly shut down the lower layers. - */ -static void -ipcp_finished(fsm *f) -{ - np_finished(f->unit, PPP_IP); -} - -#if PPP_ADDITIONAL_CALLBACKS -static int -ipcp_printpkt(u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) -{ - LWIP_UNUSED_ARG(p); - LWIP_UNUSED_ARG(plen); - LWIP_UNUSED_ARG(printer); - LWIP_UNUSED_ARG(arg); - return 0; -} - -/* - * ip_active_pkt - see if this IP packet is worth bringing the link up for. - * We don't bring the link up for IP fragments or for TCP FIN packets - * with no data. - */ -#define IP_HDRLEN 20 /* bytes */ -#define IP_OFFMASK 0x1fff -#define IPPROTO_TCP 6 -#define TCP_HDRLEN 20 -#define TH_FIN 0x01 - -/* - * We use these macros because the IP header may be at an odd address, - * and some compilers might use word loads to get th_off or ip_hl. - */ - -#define net_short(x) (((x)[0] << 8) + (x)[1]) -#define get_iphl(x) (((unsigned char *)(x))[0] & 0xF) -#define get_ipoff(x) net_short((unsigned char *)(x) + 6) -#define get_ipproto(x) (((unsigned char *)(x))[9]) -#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) -#define get_tcpflags(x) (((unsigned char *)(x))[13]) - -static int -ip_active_pkt(u_char *pkt, int len) -{ - u_char *tcp; - int hlen; - - len -= PPP_HDRLEN; - pkt += PPP_HDRLEN; - if (len < IP_HDRLEN) { - return 0; - } - if ((get_ipoff(pkt) & IP_OFFMASK) != 0) { - return 0; - } - if (get_ipproto(pkt) != IPPROTO_TCP) { - return 1; - } - hlen = get_iphl(pkt) * 4; - if (len < hlen + TCP_HDRLEN) { - return 0; - } - tcp = pkt + hlen; - if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) { - return 0; - } - return 1; -} -#endif /* PPP_ADDITIONAL_CALLBACKS */ - -#endif /* PPP_SUPPORT */ diff --git a/third_party/lwip/netif/ppp/ipcp.h b/third_party/lwip/netif/ppp/ipcp.h deleted file mode 100644 index 9ef748e..0000000 --- a/third_party/lwip/netif/ppp/ipcp.h +++ /dev/null @@ -1,106 +0,0 @@ -/***************************************************************************** -* ipcp.h - PPP IP NCP: Internet Protocol Network Control Protocol header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-12-04 Guy Lancaster , Global Election Systems Inc. -* Original derived from BSD codes. -*****************************************************************************/ -/* - * ipcp.h - IP Control Protocol definitions. - * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * $Id: ipcp.h,v 1.4 2010/01/18 20:49:43 goldsimon Exp $ - */ - -#ifndef IPCP_H -#define IPCP_H - -/* - * Options. - */ -#define CI_ADDRS 1 /* IP Addresses */ -#define CI_COMPRESSTYPE 2 /* Compression Type */ -#define CI_ADDR 3 - -#define CI_MS_DNS1 129 /* Primary DNS value */ -#define CI_MS_WINS1 128 /* Primary WINS value */ -#define CI_MS_DNS2 131 /* Secondary DNS value */ -#define CI_MS_WINS2 130 /* Secondary WINS value */ - -#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */ -#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */ -#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */ - /* maxslot and slot number compression) */ - -#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option */ -#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */ - /* compression option */ - -typedef struct ipcp_options { - u_int neg_addr : 1; /* Negotiate IP Address? */ - u_int old_addrs : 1; /* Use old (IP-Addresses) option? */ - u_int req_addr : 1; /* Ask peer to send IP address? */ - u_int default_route : 1; /* Assign default route through interface? */ - u_int proxy_arp : 1; /* Make proxy ARP entry for peer? */ - u_int neg_vj : 1; /* Van Jacobson Compression? */ - u_int old_vj : 1; /* use old (short) form of VJ option? */ - u_int accept_local : 1; /* accept peer's value for ouraddr */ - u_int accept_remote : 1; /* accept peer's value for hisaddr */ - u_int req_dns1 : 1; /* Ask peer to send primary DNS address? */ - u_int req_dns2 : 1; /* Ask peer to send secondary DNS address? */ - u_short vj_protocol; /* protocol value to use in VJ option */ - u_char maxslotindex; /* VJ slots - 1. */ - u_char cflag; /* VJ slot compression flag. */ - u32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */ - u32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */ - u32_t winsaddr[2]; /* Primary and secondary MS WINS entries */ -} ipcp_options; - -extern fsm ipcp_fsm[]; -extern ipcp_options ipcp_wantoptions[]; -extern ipcp_options ipcp_gotoptions[]; -extern ipcp_options ipcp_allowoptions[]; -extern ipcp_options ipcp_hisoptions[]; - -extern struct protent ipcp_protent; - -#endif /* IPCP_H */ diff --git a/third_party/lwip/netif/ppp/lcp.c b/third_party/lwip/netif/ppp/lcp.c deleted file mode 100644 index b551a04..0000000 --- a/third_party/lwip/netif/ppp/lcp.c +++ /dev/null @@ -1,2066 +0,0 @@ -/***************************************************************************** -* lcp.c - Network Link Control Protocol program file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 by Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-12-01 Guy Lancaster , Global Election Systems Inc. -* Original. -*****************************************************************************/ - -/* - * lcp.c - PPP Link Control Protocol. - * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - - -#include "lwip/opt.h" - -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "ppp_impl.h" -#include "pppdebug.h" - -#include "fsm.h" -#include "chap.h" -#include "magic.h" -#include "auth.h" -#include "lcp.h" - -#include - -#if PPPOE_SUPPORT -#include "netif/ppp_oe.h" -#else -#define PPPOE_MAXMTU PPP_MAXMRU -#endif - -#if 0 /* UNUSED */ -/* - * LCP-related command-line options. - */ -int lcp_echo_interval = 0; /* Interval between LCP echo-requests */ -int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */ -bool lax_recv = 0; /* accept control chars in asyncmap */ - -static int setescape (char **); - -static option_t lcp_option_list[] = { - /* LCP options */ - /* list stripped for simplicity */ - {NULL} -}; -#endif /* UNUSED */ - -/* options */ -LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */ -static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */ -static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */ - -/* global vars */ -static fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/ -lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */ -lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ -lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ -lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ -ext_accm xmit_accm[NUM_PPP]; /* extended transmit ACCM */ - -static u32_t lcp_echos_pending = 0; /* Number of outstanding echo msgs */ -static u32_t lcp_echo_number = 0; /* ID number of next echo frame */ -static u32_t lcp_echo_timer_running = 0; /* TRUE if a timer is running */ - -/* @todo: do we really need such a large buffer? The typical 1500 bytes seem too much. */ -static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */ - -/* - * Callbacks for fsm code. (CI = Configuration Information) - */ -static void lcp_resetci (fsm*); /* Reset our CI */ -static int lcp_cilen (fsm*); /* Return length of our CI */ -static void lcp_addci (fsm*, u_char*, int*); /* Add our CI to pkt */ -static int lcp_ackci (fsm*, u_char*, int); /* Peer ack'd our CI */ -static int lcp_nakci (fsm*, u_char*, int); /* Peer nak'd our CI */ -static int lcp_rejci (fsm*, u_char*, int); /* Peer rej'd our CI */ -static int lcp_reqci (fsm*, u_char*, int*, int); /* Rcv peer CI */ -static void lcp_up (fsm*); /* We're UP */ -static void lcp_down (fsm*); /* We're DOWN */ -static void lcp_starting (fsm*); /* We need lower layer up */ -static void lcp_finished (fsm*); /* We need lower layer down */ -static int lcp_extcode (fsm*, int, u_char, u_char*, int); -static void lcp_rprotrej (fsm*, u_char*, int); - -/* - * routines to send LCP echos to peer - */ - -static void lcp_echo_lowerup (int); -static void lcp_echo_lowerdown (int); -static void LcpEchoTimeout (void*); -static void lcp_received_echo_reply (fsm*, int, u_char*, int); -static void LcpSendEchoRequest (fsm*); -static void LcpLinkFailure (fsm*); -static void LcpEchoCheck (fsm*); - -static fsm_callbacks lcp_callbacks = { /* LCP callback routines */ - lcp_resetci, /* Reset our Configuration Information */ - lcp_cilen, /* Length of our Configuration Information */ - lcp_addci, /* Add our Configuration Information */ - lcp_ackci, /* ACK our Configuration Information */ - lcp_nakci, /* NAK our Configuration Information */ - lcp_rejci, /* Reject our Configuration Information */ - lcp_reqci, /* Request peer's Configuration Information */ - lcp_up, /* Called when fsm reaches LS_OPENED state */ - lcp_down, /* Called when fsm leaves LS_OPENED state */ - lcp_starting, /* Called when we want the lower layer up */ - lcp_finished, /* Called when we want the lower layer down */ - NULL, /* Called when Protocol-Reject received */ - NULL, /* Retransmission is necessary */ - lcp_extcode, /* Called to handle LCP-specific codes */ - "LCP" /* String name of protocol */ -}; - -/* - * Protocol entry points. - * Some of these are called directly. - */ - -static void lcp_input (int, u_char *, int); -static void lcp_protrej (int); - -struct protent lcp_protent = { - PPP_LCP, - lcp_init, - lcp_input, - lcp_protrej, - lcp_lowerup, - lcp_lowerdown, - lcp_open, - lcp_close, -#if PPP_ADDITIONAL_CALLBACKS - lcp_printpkt, - NULL, -#endif /* PPP_ADDITIONAL_CALLBACKS */ - 1, - "LCP", -#if PPP_ADDITIONAL_CALLBACKS - NULL, - NULL, - NULL -#endif /* PPP_ADDITIONAL_CALLBACKS */ -}; - -int lcp_loopbackfail = DEFLOOPBACKFAIL; - -/* - * Length of each type of configuration option (in octets) - */ -#define CILEN_VOID 2 -#define CILEN_CHAR 3 -#define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */ -#define CILEN_CHAP 5 /* CILEN_VOID + sizeof(short) + 1 */ -#define CILEN_LONG 6 /* CILEN_VOID + sizeof(long) */ -#define CILEN_LQR 8 /* CILEN_VOID + sizeof(short) + sizeof(long) */ -#define CILEN_CBCP 3 - -#define CODENAME(x) ((x) == CONFACK ? "ACK" : (x) == CONFNAK ? "NAK" : "REJ") - -#if 0 /* UNUSED */ -/* - * setescape - add chars to the set we escape on transmission. - */ -static int -setescape(argv) - char **argv; -{ - int n, ret; - char *p, *endp; - - p = *argv; - ret = 1; - while (*p) { - n = strtol(p, &endp, 16); - if (p == endp) { - option_error("escape parameter contains invalid hex number '%s'", p); - return 0; - } - p = endp; - if (n < 0 || n == 0x5E || n > 0xFF) { - option_error("can't escape character 0x%x", n); - ret = 0; - } else - xmit_accm[0][n >> 5] |= 1 << (n & 0x1F); - while (*p == ',' || *p == ' ') - ++p; - } - return ret; -} -#endif /* UNUSED */ - -/* - * lcp_init - Initialize LCP. - */ -void -lcp_init(int unit) -{ - fsm *f = &lcp_fsm[unit]; - lcp_options *wo = &lcp_wantoptions[unit]; - lcp_options *ao = &lcp_allowoptions[unit]; - - f->unit = unit; - f->protocol = PPP_LCP; - f->callbacks = &lcp_callbacks; - - fsm_init(f); - - wo->passive = 0; - wo->silent = 0; - wo->restart = 0; /* Set to 1 in kernels or multi-line implementations */ - wo->neg_mru = 1; - wo->mru = PPP_DEFMRU; - wo->neg_asyncmap = 1; - wo->asyncmap = 0x00000000l; /* Assume don't need to escape any ctl chars. */ - wo->neg_chap = 0; /* Set to 1 on server */ - wo->neg_upap = 0; /* Set to 1 on server */ - wo->chap_mdtype = CHAP_DIGEST_MD5; - wo->neg_magicnumber = 1; - wo->neg_pcompression = 1; - wo->neg_accompression = 1; - wo->neg_lqr = 0; /* no LQR implementation yet */ - wo->neg_cbcp = 0; - - ao->neg_mru = 1; - ao->mru = PPP_MAXMRU; - ao->neg_asyncmap = 1; - ao->asyncmap = 0x00000000l; /* Assume don't need to escape any ctl chars. */ - ao->neg_chap = (CHAP_SUPPORT != 0); - ao->chap_mdtype = CHAP_DIGEST_MD5; - ao->neg_upap = (PAP_SUPPORT != 0); - ao->neg_magicnumber = 1; - ao->neg_pcompression = 1; - ao->neg_accompression = 1; - ao->neg_lqr = 0; /* no LQR implementation yet */ - ao->neg_cbcp = (CBCP_SUPPORT != 0); - - /* - * Set transmit escape for the flag and escape characters plus anything - * set for the allowable options. - */ - memset(xmit_accm[unit], 0, sizeof(xmit_accm[0])); - xmit_accm[unit][15] = 0x60; - xmit_accm[unit][0] = (u_char)((ao->asyncmap & 0xFF)); - xmit_accm[unit][1] = (u_char)((ao->asyncmap >> 8) & 0xFF); - xmit_accm[unit][2] = (u_char)((ao->asyncmap >> 16) & 0xFF); - xmit_accm[unit][3] = (u_char)((ao->asyncmap >> 24) & 0xFF); - LCPDEBUG(LOG_INFO, ("lcp_init: xmit_accm=%X %X %X %X\n", - xmit_accm[unit][0], - xmit_accm[unit][1], - xmit_accm[unit][2], - xmit_accm[unit][3])); - - lcp_phase[unit] = PHASE_INITIALIZE; -} - - -/* - * lcp_open - LCP is allowed to come up. - */ -void -lcp_open(int unit) -{ - fsm *f = &lcp_fsm[unit]; - lcp_options *wo = &lcp_wantoptions[unit]; - - f->flags = 0; - if (wo->passive) { - f->flags |= OPT_PASSIVE; - } - if (wo->silent) { - f->flags |= OPT_SILENT; - } - fsm_open(f); - - lcp_phase[unit] = PHASE_ESTABLISH; -} - - -/* - * lcp_close - Take LCP down. - */ -void -lcp_close(int unit, char *reason) -{ - fsm *f = &lcp_fsm[unit]; - - if (lcp_phase[unit] != PHASE_DEAD) { - lcp_phase[unit] = PHASE_TERMINATE; - } - if (f->state == LS_STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) { - /* - * This action is not strictly according to the FSM in RFC1548, - * but it does mean that the program terminates if you do an - * lcp_close() in passive/silent mode when a connection hasn't - * been established. - */ - f->state = LS_CLOSED; - lcp_finished(f); - } else { - fsm_close(f, reason); - } -} - - -/* - * lcp_lowerup - The lower layer is up. - */ -void -lcp_lowerup(int unit) -{ - lcp_options *wo = &lcp_wantoptions[unit]; - - /* - * Don't use A/C or protocol compression on transmission, - * but accept A/C and protocol compressed packets - * if we are going to ask for A/C and protocol compression. - */ - ppp_set_xaccm(unit, &xmit_accm[unit]); - ppp_send_config(unit, PPP_MRU, 0xffffffffl, 0, 0); - ppp_recv_config(unit, PPP_MRU, 0x00000000l, - wo->neg_pcompression, wo->neg_accompression); - peer_mru[unit] = PPP_MRU; - lcp_allowoptions[unit].asyncmap = (u_long)xmit_accm[unit][0] - | ((u_long)xmit_accm[unit][1] << 8) - | ((u_long)xmit_accm[unit][2] << 16) - | ((u_long)xmit_accm[unit][3] << 24); - LCPDEBUG(LOG_INFO, ("lcp_lowerup: asyncmap=%X %X %X %X\n", - xmit_accm[unit][3], - xmit_accm[unit][2], - xmit_accm[unit][1], - xmit_accm[unit][0])); - - fsm_lowerup(&lcp_fsm[unit]); -} - - -/* - * lcp_lowerdown - The lower layer is down. - */ -void -lcp_lowerdown(int unit) -{ - fsm_lowerdown(&lcp_fsm[unit]); -} - - -/* - * lcp_input - Input LCP packet. - */ -static void -lcp_input(int unit, u_char *p, int len) -{ - fsm *f = &lcp_fsm[unit]; - - fsm_input(f, p, len); -} - - -/* - * lcp_extcode - Handle a LCP-specific code. - */ -static int -lcp_extcode(fsm *f, int code, u_char id, u_char *inp, int len) -{ - u_char *magp; - - switch( code ){ - case PROTREJ: - lcp_rprotrej(f, inp, len); - break; - - case ECHOREQ: - if (f->state != LS_OPENED) { - break; - } - LCPDEBUG(LOG_INFO, ("lcp: Echo-Request, Rcvd id %d\n", id)); - magp = inp; - PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp); - fsm_sdata(f, ECHOREP, id, inp, len); - break; - - case ECHOREP: - lcp_received_echo_reply(f, id, inp, len); - break; - - case DISCREQ: - break; - - default: - return 0; - } - return 1; -} - - -/* - * lcp_rprotrej - Receive an Protocol-Reject. - * - * Figure out which protocol is rejected and inform it. - */ -static void -lcp_rprotrej(fsm *f, u_char *inp, int len) -{ - int i; - struct protent *protp; - u_short prot; - - if (len < (int)sizeof (u_short)) { - LCPDEBUG(LOG_INFO, ("lcp_rprotrej: Rcvd short Protocol-Reject packet!\n")); - return; - } - - GETSHORT(prot, inp); - - LCPDEBUG(LOG_INFO, ("lcp_rprotrej: Rcvd Protocol-Reject packet for %x!\n", prot)); - - /* - * Protocol-Reject packets received in any state other than the LCP - * LS_OPENED state SHOULD be silently discarded. - */ - if( f->state != LS_OPENED ) { - LCPDEBUG(LOG_INFO, ("Protocol-Reject discarded: LCP in state %d\n", f->state)); - return; - } - - /* - * Upcall the proper Protocol-Reject routine. - */ - for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { - if (protp->protocol == prot && protp->enabled_flag) { - (*protp->protrej)(f->unit); - return; - } - } - - LCPDEBUG(LOG_WARNING, ("Protocol-Reject for unsupported protocol 0x%x\n", prot)); -} - - -/* - * lcp_protrej - A Protocol-Reject was received. - */ -static void -lcp_protrej(int unit) -{ - LWIP_UNUSED_ARG(unit); - /* - * Can't reject LCP! - */ - LCPDEBUG(LOG_WARNING, ("lcp_protrej: Received Protocol-Reject for LCP!\n")); - fsm_protreject(&lcp_fsm[unit]); -} - - -/* - * lcp_sprotrej - Send a Protocol-Reject for some protocol. - */ -void -lcp_sprotrej(int unit, u_char *p, int len) -{ - /* - * Send back the protocol and the information field of the - * rejected packet. We only get here if LCP is in the LS_OPENED state. - */ - - fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id, p, len); -} - - -/* - * lcp_resetci - Reset our CI. - */ -static void -lcp_resetci(fsm *f) -{ - lcp_wantoptions[f->unit].magicnumber = magic(); - lcp_wantoptions[f->unit].numloops = 0; - lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit]; - peer_mru[f->unit] = PPP_MRU; - auth_reset(f->unit); -} - - -/* - * lcp_cilen - Return length of our CI. - */ -static int -lcp_cilen(fsm *f) -{ - lcp_options *go = &lcp_gotoptions[f->unit]; - -#define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0) -#define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0) -#define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0) -#define LENCILONG(neg) ((neg) ? CILEN_LONG : 0) -#define LENCILQR(neg) ((neg) ? CILEN_LQR: 0) -#define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0) - /* - * NB: we only ask for one of CHAP and UPAP, even if we will - * accept either. - */ - return (LENCISHORT(go->neg_mru && go->mru != PPP_DEFMRU) + - LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) + - LENCICHAP(go->neg_chap) + - LENCISHORT(!go->neg_chap && go->neg_upap) + - LENCILQR(go->neg_lqr) + - LENCICBCP(go->neg_cbcp) + - LENCILONG(go->neg_magicnumber) + - LENCIVOID(go->neg_pcompression) + - LENCIVOID(go->neg_accompression)); -} - - -/* - * lcp_addci - Add our desired CIs to a packet. - */ -static void -lcp_addci(fsm *f, u_char *ucp, int *lenp) -{ - lcp_options *go = &lcp_gotoptions[f->unit]; - u_char *start_ucp = ucp; - -#define ADDCIVOID(opt, neg) \ - if (neg) { \ - LCPDEBUG(LOG_INFO, ("lcp_addci: opt=%d\n", opt)); \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_VOID, ucp); \ - } -#define ADDCISHORT(opt, neg, val) \ - if (neg) { \ - LCPDEBUG(LOG_INFO, ("lcp_addci: INT opt=%d %X\n", opt, val)); \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_SHORT, ucp); \ - PUTSHORT(val, ucp); \ - } -#define ADDCICHAP(opt, neg, val, digest) \ - if (neg) { \ - LCPDEBUG(LOG_INFO, ("lcp_addci: CHAP opt=%d %X\n", opt, val)); \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_CHAP, ucp); \ - PUTSHORT(val, ucp); \ - PUTCHAR(digest, ucp); \ - } -#define ADDCILONG(opt, neg, val) \ - if (neg) { \ - LCPDEBUG(LOG_INFO, ("lcp_addci: L opt=%d %lX\n", opt, val)); \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_LONG, ucp); \ - PUTLONG(val, ucp); \ - } -#define ADDCILQR(opt, neg, val) \ - if (neg) { \ - LCPDEBUG(LOG_INFO, ("lcp_addci: LQR opt=%d %lX\n", opt, val)); \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_LQR, ucp); \ - PUTSHORT(PPP_LQR, ucp); \ - PUTLONG(val, ucp); \ - } -#define ADDCICHAR(opt, neg, val) \ - if (neg) { \ - LCPDEBUG(LOG_INFO, ("lcp_addci: CHAR opt=%d %X '%z'\n", opt, val, val)); \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_CHAR, ucp); \ - PUTCHAR(val, ucp); \ - } - - ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); - ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl, go->asyncmap); - ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype); - ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); - ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); - ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); - ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); - ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression); - ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression); - - if (ucp - start_ucp != *lenp) { - /* this should never happen, because peer_mtu should be 1500 */ - LCPDEBUG(LOG_ERR, ("Bug in lcp_addci: wrong length\n")); - } -} - - -/* - * lcp_ackci - Ack our CIs. - * This should not modify any state if the Ack is bad. - * - * Returns: - * 0 - Ack was bad. - * 1 - Ack was good. - */ -static int -lcp_ackci(fsm *f, u_char *p, int len) -{ - lcp_options *go = &lcp_gotoptions[f->unit]; - u_char cilen, citype, cichar; - u_short cishort; - u32_t cilong; - - /* - * CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define ACKCIVOID(opt, neg) \ - if (neg) { \ - if ((len -= CILEN_VOID) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_VOID || citype != opt) \ - goto bad; \ - } -#define ACKCISHORT(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_SHORT) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_SHORT || citype != opt) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != val) \ - goto bad; \ - } -#define ACKCICHAR(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_CHAR) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_CHAR || citype != opt) \ - goto bad; \ - GETCHAR(cichar, p); \ - if (cichar != val) \ - goto bad; \ - } -#define ACKCICHAP(opt, neg, val, digest) \ - if (neg) { \ - if ((len -= CILEN_CHAP) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_CHAP || citype != opt) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != val) \ - goto bad; \ - GETCHAR(cichar, p); \ - if (cichar != digest) \ - goto bad; \ - } -#define ACKCILONG(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_LONG) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_LONG || citype != opt) \ - goto bad; \ - GETLONG(cilong, p); \ - if (cilong != val) \ - goto bad; \ - } -#define ACKCILQR(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_LQR) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_LQR || citype != opt) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != PPP_LQR) \ - goto bad; \ - GETLONG(cilong, p); \ - if (cilong != val) \ - goto bad; \ - } - - ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); - ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl, go->asyncmap); - ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype); - ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); - ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); - ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); - ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); - ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression); - ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression); - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) { - goto bad; - } - LCPDEBUG(LOG_INFO, ("lcp_acki: Ack\n")); - return (1); -bad: - LCPDEBUG(LOG_WARNING, ("lcp_acki: received bad Ack!\n")); - return (0); -} - - -/* - * lcp_nakci - Peer has sent a NAK for some of our CIs. - * This should not modify any state if the Nak is bad - * or if LCP is in the LS_OPENED state. - * - * Returns: - * 0 - Nak was bad. - * 1 - Nak was good. - */ -static int -lcp_nakci(fsm *f, u_char *p, int len) -{ - lcp_options *go = &lcp_gotoptions[f->unit]; - lcp_options *wo = &lcp_wantoptions[f->unit]; - u_char citype, cichar, *next; - u_short cishort; - u32_t cilong; - lcp_options no; /* options we've seen Naks for */ - lcp_options try; /* options to request next time */ - int looped_back = 0; - int cilen; - - BZERO(&no, sizeof(no)); - try = *go; - - /* - * Any Nak'd CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define NAKCIVOID(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_VOID && \ - p[1] == CILEN_VOID && \ - p[0] == opt) { \ - len -= CILEN_VOID; \ - INCPTR(CILEN_VOID, p); \ - no.neg = 1; \ - code \ - } -#define NAKCICHAP(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_CHAP && \ - p[1] == CILEN_CHAP && \ - p[0] == opt) { \ - len -= CILEN_CHAP; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETCHAR(cichar, p); \ - no.neg = 1; \ - code \ - } -#define NAKCICHAR(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_CHAR && \ - p[1] == CILEN_CHAR && \ - p[0] == opt) { \ - len -= CILEN_CHAR; \ - INCPTR(2, p); \ - GETCHAR(cichar, p); \ - no.neg = 1; \ - code \ - } -#define NAKCISHORT(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_SHORT && \ - p[1] == CILEN_SHORT && \ - p[0] == opt) { \ - len -= CILEN_SHORT; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - no.neg = 1; \ - code \ - } -#define NAKCILONG(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_LONG && \ - p[1] == CILEN_LONG && \ - p[0] == opt) { \ - len -= CILEN_LONG; \ - INCPTR(2, p); \ - GETLONG(cilong, p); \ - no.neg = 1; \ - code \ - } -#define NAKCILQR(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_LQR && \ - p[1] == CILEN_LQR && \ - p[0] == opt) { \ - len -= CILEN_LQR; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETLONG(cilong, p); \ - no.neg = 1; \ - code \ - } - - /* - * We don't care if they want to send us smaller packets than - * we want. Therefore, accept any MRU less than what we asked for, - * but then ignore the new value when setting the MRU in the kernel. - * If they send us a bigger MRU than what we asked, accept it, up to - * the limit of the default MRU we'd get if we didn't negotiate. - */ - if (go->neg_mru && go->mru != PPP_DEFMRU) { - NAKCISHORT(CI_MRU, neg_mru, - if (cishort <= wo->mru || cishort < PPP_DEFMRU) { - try.mru = cishort; - } - ); - } - - /* - * Add any characters they want to our (receive-side) asyncmap. - */ - if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) { - NAKCILONG(CI_ASYNCMAP, neg_asyncmap, - try.asyncmap = go->asyncmap | cilong; - ); - } - - /* - * If they've nak'd our authentication-protocol, check whether - * they are proposing a different protocol, or a different - * hash algorithm for CHAP. - */ - if ((go->neg_chap || go->neg_upap) - && len >= CILEN_SHORT - && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) { - cilen = p[1]; - len -= cilen; - no.neg_chap = go->neg_chap; - no.neg_upap = go->neg_upap; - INCPTR(2, p); - GETSHORT(cishort, p); - if (cishort == PPP_PAP && cilen == CILEN_SHORT) { - /* - * If we were asking for CHAP, they obviously don't want to do it. - * If we weren't asking for CHAP, then we were asking for PAP, - * in which case this Nak is bad. - */ - if (!go->neg_chap) { - goto bad; - } - try.neg_chap = 0; - - } else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) { - GETCHAR(cichar, p); - if (go->neg_chap) { - /* - * We were asking for CHAP/MD5; they must want a different - * algorithm. If they can't do MD5, we'll have to stop - * asking for CHAP. - */ - if (cichar != go->chap_mdtype) { - try.neg_chap = 0; - } - } else { - /* - * Stop asking for PAP if we were asking for it. - */ - try.neg_upap = 0; - } - - } else { - /* - * We don't recognize what they're suggesting. - * Stop asking for what we were asking for. - */ - if (go->neg_chap) { - try.neg_chap = 0; - } else { - try.neg_upap = 0; - } - p += cilen - CILEN_SHORT; - } - } - - /* - * If they can't cope with our link quality protocol, we'll have - * to stop asking for LQR. We haven't got any other protocol. - * If they Nak the reporting period, take their value XXX ? - */ - NAKCILQR(CI_QUALITY, neg_lqr, - if (cishort != PPP_LQR) { - try.neg_lqr = 0; - } else { - try.lqr_period = cilong; - } - ); - - /* - * Only implementing CBCP...not the rest of the callback options - */ - NAKCICHAR(CI_CALLBACK, neg_cbcp, - try.neg_cbcp = 0; - ); - - /* - * Check for a looped-back line. - */ - NAKCILONG(CI_MAGICNUMBER, neg_magicnumber, - try.magicnumber = magic(); - looped_back = 1; - ); - - /* - * Peer shouldn't send Nak for protocol compression or - * address/control compression requests; they should send - * a Reject instead. If they send a Nak, treat it as a Reject. - */ - NAKCIVOID(CI_PCOMPRESSION, neg_pcompression, - try.neg_pcompression = 0; - ); - NAKCIVOID(CI_ACCOMPRESSION, neg_accompression, - try.neg_accompression = 0; - ); - - /* - * There may be remaining CIs, if the peer is requesting negotiation - * on an option that we didn't include in our request packet. - * If we see an option that we requested, or one we've already seen - * in this packet, then this packet is bad. - * If we wanted to respond by starting to negotiate on the requested - * option(s), we could, but we don't, because except for the - * authentication type and quality protocol, if we are not negotiating - * an option, it is because we were told not to. - * For the authentication type, the Nak from the peer means - * `let me authenticate myself with you' which is a bit pointless. - * For the quality protocol, the Nak means `ask me to send you quality - * reports', but if we didn't ask for them, we don't want them. - * An option we don't recognize represents the peer asking to - * negotiate some option we don't support, so ignore it. - */ - while (len > CILEN_VOID) { - GETCHAR(citype, p); - GETCHAR(cilen, p); - if (cilen < CILEN_VOID || (len -= cilen) < 0) { - goto bad; - } - next = p + cilen - 2; - - switch (citype) { - case CI_MRU: - if ((go->neg_mru && go->mru != PPP_DEFMRU) - || no.neg_mru || cilen != CILEN_SHORT) { - goto bad; - } - GETSHORT(cishort, p); - if (cishort < PPP_DEFMRU) { - try.mru = cishort; - } - break; - case CI_ASYNCMAP: - if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFFl) - || no.neg_asyncmap || cilen != CILEN_LONG) { - goto bad; - } - break; - case CI_AUTHTYPE: - if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap) { - goto bad; - } - break; - case CI_MAGICNUMBER: - if (go->neg_magicnumber || no.neg_magicnumber || - cilen != CILEN_LONG) { - goto bad; - } - break; - case CI_PCOMPRESSION: - if (go->neg_pcompression || no.neg_pcompression - || cilen != CILEN_VOID) { - goto bad; - } - break; - case CI_ACCOMPRESSION: - if (go->neg_accompression || no.neg_accompression - || cilen != CILEN_VOID) { - goto bad; - } - break; - case CI_QUALITY: - if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR) { - goto bad; - } - break; - } - p = next; - } - - /* If there is still anything left, this packet is bad. */ - if (len != 0) { - goto bad; - } - - /* - * OK, the Nak is good. Now we can update state. - */ - if (f->state != LS_OPENED) { - if (looped_back) { - if (++try.numloops >= lcp_loopbackfail) { - LCPDEBUG(LOG_NOTICE, ("Serial line is looped back.\n")); - lcp_close(f->unit, "Loopback detected"); - } - } else { - try.numloops = 0; - } - *go = try; - } - - return 1; - -bad: - LCPDEBUG(LOG_WARNING, ("lcp_nakci: received bad Nak!\n")); - return 0; -} - - -/* - * lcp_rejci - Peer has Rejected some of our CIs. - * This should not modify any state if the Reject is bad - * or if LCP is in the LS_OPENED state. - * - * Returns: - * 0 - Reject was bad. - * 1 - Reject was good. - */ -static int -lcp_rejci(fsm *f, u_char *p, int len) -{ - lcp_options *go = &lcp_gotoptions[f->unit]; - u_char cichar; - u_short cishort; - u32_t cilong; - lcp_options try; /* options to request next time */ - - try = *go; - - /* - * Any Rejected CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define REJCIVOID(opt, neg) \ - if (go->neg && \ - len >= CILEN_VOID && \ - p[1] == CILEN_VOID && \ - p[0] == opt) { \ - len -= CILEN_VOID; \ - INCPTR(CILEN_VOID, p); \ - try.neg = 0; \ - LCPDEBUG(LOG_INFO, ("lcp_rejci: void opt %d rejected\n", opt)); \ - } -#define REJCISHORT(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_SHORT && \ - p[1] == CILEN_SHORT && \ - p[0] == opt) { \ - len -= CILEN_SHORT; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - /* Check rejected value. */ \ - if (cishort != val) { \ - goto bad; \ - } \ - try.neg = 0; \ - LCPDEBUG(LOG_INFO, ("lcp_rejci: short opt %d rejected\n", opt)); \ - } -#define REJCICHAP(opt, neg, val, digest) \ - if (go->neg && \ - len >= CILEN_CHAP && \ - p[1] == CILEN_CHAP && \ - p[0] == opt) { \ - len -= CILEN_CHAP; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETCHAR(cichar, p); \ - /* Check rejected value. */ \ - if (cishort != val || cichar != digest) { \ - goto bad; \ - } \ - try.neg = 0; \ - try.neg_upap = 0; \ - LCPDEBUG(LOG_INFO, ("lcp_rejci: chap opt %d rejected\n", opt)); \ - } -#define REJCILONG(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_LONG && \ - p[1] == CILEN_LONG && \ - p[0] == opt) { \ - len -= CILEN_LONG; \ - INCPTR(2, p); \ - GETLONG(cilong, p); \ - /* Check rejected value. */ \ - if (cilong != val) { \ - goto bad; \ - } \ - try.neg = 0; \ - LCPDEBUG(LOG_INFO, ("lcp_rejci: long opt %d rejected\n", opt)); \ - } -#define REJCILQR(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_LQR && \ - p[1] == CILEN_LQR && \ - p[0] == opt) { \ - len -= CILEN_LQR; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETLONG(cilong, p); \ - /* Check rejected value. */ \ - if (cishort != PPP_LQR || cilong != val) { \ - goto bad; \ - } \ - try.neg = 0; \ - LCPDEBUG(LOG_INFO, ("lcp_rejci: LQR opt %d rejected\n", opt)); \ - } -#define REJCICBCP(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_CBCP && \ - p[1] == CILEN_CBCP && \ - p[0] == opt) { \ - len -= CILEN_CBCP; \ - INCPTR(2, p); \ - GETCHAR(cichar, p); \ - /* Check rejected value. */ \ - if (cichar != val) { \ - goto bad; \ - } \ - try.neg = 0; \ - LCPDEBUG(LOG_INFO, ("lcp_rejci: Callback opt %d rejected\n", opt)); \ - } - - REJCISHORT(CI_MRU, neg_mru, go->mru); - REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap); - REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype); - if (!go->neg_chap) { - REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP); - } - REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period); - REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT); - REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber); - REJCIVOID(CI_PCOMPRESSION, neg_pcompression); - REJCIVOID(CI_ACCOMPRESSION, neg_accompression); - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) { - goto bad; - } - /* - * Now we can update state. - */ - if (f->state != LS_OPENED) { - *go = try; - } - return 1; - -bad: - LCPDEBUG(LOG_WARNING, ("lcp_rejci: received bad Reject!\n")); - return 0; -} - - -/* - * lcp_reqci - Check the peer's requested CIs and send appropriate response. - * - * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified - * appropriately. If reject_if_disagree is non-zero, doesn't return - * CONFNAK; returns CONFREJ if it can't return CONFACK. - */ -static int -lcp_reqci(fsm *f, - u_char *inp, /* Requested CIs */ - int *lenp, /* Length of requested CIs */ - int reject_if_disagree) -{ - lcp_options *go = &lcp_gotoptions[f->unit]; - lcp_options *ho = &lcp_hisoptions[f->unit]; - lcp_options *ao = &lcp_allowoptions[f->unit]; - u_char *cip, *next; /* Pointer to current and next CIs */ - int cilen, citype; /* Parsed len, type */ - u_char cichar; /* Parsed char value */ - u_short cishort; /* Parsed short value */ - u32_t cilong; /* Parse long value */ - int rc = CONFACK; /* Final packet return code */ - int orc; /* Individual option return code */ - u_char *p; /* Pointer to next char to parse */ - u_char *rejp; /* Pointer to next char in reject frame */ - u_char *nakp; /* Pointer to next char in Nak frame */ - int l = *lenp; /* Length left */ -#if TRACELCP > 0 - char traceBuf[80]; - size_t traceNdx = 0; -#endif - - /* - * Reset all his options. - */ - BZERO(ho, sizeof(*ho)); - - /* - * Process all his options. - */ - next = inp; - nakp = nak_buffer; - rejp = inp; - while (l) { - orc = CONFACK; /* Assume success */ - cip = p = next; /* Remember begining of CI */ - if (l < 2 || /* Not enough data for CI header or */ - p[1] < 2 || /* CI length too small or */ - p[1] > l) { /* CI length too big? */ - LCPDEBUG(LOG_WARNING, ("lcp_reqci: bad CI length!\n")); - orc = CONFREJ; /* Reject bad CI */ - cilen = l; /* Reject till end of packet */ - l = 0; /* Don't loop again */ - citype = 0; - goto endswitch; - } - GETCHAR(citype, p); /* Parse CI type */ - GETCHAR(cilen, p); /* Parse CI length */ - l -= cilen; /* Adjust remaining length */ - next += cilen; /* Step to next CI */ - - switch (citype) { /* Check CI type */ - case CI_MRU: - if (!ao->neg_mru) { /* Allow option? */ - LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject MRU - not allowed\n")); - orc = CONFREJ; /* Reject CI */ - break; - } else if (cilen != CILEN_SHORT) { /* Check CI length */ - LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject MRU - bad length\n")); - orc = CONFREJ; /* Reject CI */ - break; - } - GETSHORT(cishort, p); /* Parse MRU */ - - /* - * He must be able to receive at least our minimum. - * No need to check a maximum. If he sends a large number, - * we'll just ignore it. - */ - if (cishort < PPP_MINMRU) { - LCPDEBUG(LOG_INFO, ("lcp_reqci: Nak - MRU too small\n")); - orc = CONFNAK; /* Nak CI */ - PUTCHAR(CI_MRU, nakp); - PUTCHAR(CILEN_SHORT, nakp); - PUTSHORT(PPP_MINMRU, nakp); /* Give him a hint */ - break; - } - ho->neg_mru = 1; /* Remember he sent MRU */ - ho->mru = cishort; /* And remember value */ -#if TRACELCP > 0 - snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MRU %d", cishort); - traceNdx = strlen(traceBuf); -#endif - break; - - case CI_ASYNCMAP: - if (!ao->neg_asyncmap) { - LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject ASYNCMAP not allowed\n")); - orc = CONFREJ; - break; - } else if (cilen != CILEN_LONG) { - LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject ASYNCMAP bad length\n")); - orc = CONFREJ; - break; - } - GETLONG(cilong, p); - - /* - * Asyncmap must have set at least the bits - * which are set in lcp_allowoptions[unit].asyncmap. - */ - if ((ao->asyncmap & ~cilong) != 0) { - LCPDEBUG(LOG_INFO, ("lcp_reqci: Nak ASYNCMAP %lX missing %lX\n", - cilong, ao->asyncmap)); - orc = CONFNAK; - PUTCHAR(CI_ASYNCMAP, nakp); - PUTCHAR(CILEN_LONG, nakp); - PUTLONG(ao->asyncmap | cilong, nakp); - break; - } - ho->neg_asyncmap = 1; - ho->asyncmap = cilong; -#if TRACELCP > 0 - snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ASYNCMAP=%lX", cilong); - traceNdx = strlen(traceBuf); -#endif - break; - - case CI_AUTHTYPE: - if (cilen < CILEN_SHORT) { - LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject AUTHTYPE missing arg\n")); - orc = CONFREJ; - break; - } else if (!(ao->neg_upap || ao->neg_chap)) { - /* - * Reject the option if we're not willing to authenticate. - */ - LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject AUTHTYPE not allowed\n")); - orc = CONFREJ; - break; - } - GETSHORT(cishort, p); - - /* - * Authtype must be UPAP or CHAP. - * - * Note: if both ao->neg_upap and ao->neg_chap are set, - * and the peer sends a Configure-Request with two - * authenticate-protocol requests, one for CHAP and one - * for UPAP, then we will reject the second request. - * Whether we end up doing CHAP or UPAP depends then on - * the ordering of the CIs in the peer's Configure-Request. - */ - - if (cishort == PPP_PAP) { - if (ho->neg_chap) { /* we've already accepted CHAP */ - LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE PAP already accepted\n")); - orc = CONFREJ; - break; - } else if (cilen != CILEN_SHORT) { - LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE PAP bad len\n")); - orc = CONFREJ; - break; - } - if (!ao->neg_upap) { /* we don't want to do PAP */ - LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE PAP not allowed\n")); - orc = CONFNAK; /* NAK it and suggest CHAP */ - PUTCHAR(CI_AUTHTYPE, nakp); - PUTCHAR(CILEN_CHAP, nakp); - PUTSHORT(PPP_CHAP, nakp); - PUTCHAR(ao->chap_mdtype, nakp); - break; - } - ho->neg_upap = 1; -#if TRACELCP > 0 - snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PAP (%X)", cishort); - traceNdx = strlen(traceBuf); -#endif - break; - } - if (cishort == PPP_CHAP) { - if (ho->neg_upap) { /* we've already accepted PAP */ - LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE CHAP accepted PAP\n")); - orc = CONFREJ; - break; - } else if (cilen != CILEN_CHAP) { - LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE CHAP bad len\n")); - orc = CONFREJ; - break; - } - if (!ao->neg_chap) { /* we don't want to do CHAP */ - LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE CHAP not allowed\n")); - orc = CONFNAK; /* NAK it and suggest PAP */ - PUTCHAR(CI_AUTHTYPE, nakp); - PUTCHAR(CILEN_SHORT, nakp); - PUTSHORT(PPP_PAP, nakp); - break; - } - GETCHAR(cichar, p); /* get digest type*/ - if (cichar != CHAP_DIGEST_MD5 -#if MSCHAP_SUPPORT - && cichar != CHAP_MICROSOFT -#endif - ) { - LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE CHAP digest=%d\n", (int)cichar)); - orc = CONFNAK; - PUTCHAR(CI_AUTHTYPE, nakp); - PUTCHAR(CILEN_CHAP, nakp); - PUTSHORT(PPP_CHAP, nakp); - PUTCHAR(ao->chap_mdtype, nakp); - break; - } -#if TRACELCP > 0 - snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, (int)cichar); - traceNdx = strlen(traceBuf); -#endif - ho->chap_mdtype = cichar; /* save md type */ - ho->neg_chap = 1; - break; - } - - /* - * We don't recognize the protocol they're asking for. - * Nak it with something we're willing to do. - * (At this point we know ao->neg_upap || ao->neg_chap.) - */ - orc = CONFNAK; - PUTCHAR(CI_AUTHTYPE, nakp); - if (ao->neg_chap) { - LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE %d req CHAP\n", cishort)); - PUTCHAR(CILEN_CHAP, nakp); - PUTSHORT(PPP_CHAP, nakp); - PUTCHAR(ao->chap_mdtype, nakp); - } else { - LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE %d req PAP\n", cishort)); - PUTCHAR(CILEN_SHORT, nakp); - PUTSHORT(PPP_PAP, nakp); - } - break; - - case CI_QUALITY: - GETSHORT(cishort, p); - GETLONG(cilong, p); -#if TRACELCP > 0 - snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " QUALITY (%x %x)", cishort, (unsigned int) cilong); - traceNdx = strlen(traceBuf); -#endif - - if (!ao->neg_lqr || - cilen != CILEN_LQR) { - orc = CONFREJ; - break; - } - - /* - * Check the protocol and the reporting period. - * XXX When should we Nak this, and what with? - */ - if (cishort != PPP_LQR) { - orc = CONFNAK; - PUTCHAR(CI_QUALITY, nakp); - PUTCHAR(CILEN_LQR, nakp); - PUTSHORT(PPP_LQR, nakp); - PUTLONG(ao->lqr_period, nakp); - break; - } - break; - - case CI_MAGICNUMBER: - if (!(ao->neg_magicnumber || go->neg_magicnumber) || - cilen != CILEN_LONG) { - orc = CONFREJ; - break; - } - GETLONG(cilong, p); -#if TRACELCP > 0 - snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " MAGICNUMBER (%lX)", cilong); - traceNdx = strlen(traceBuf); -#endif - - /* - * He must have a different magic number. - */ - if (go->neg_magicnumber && - cilong == go->magicnumber) { - cilong = magic(); /* Don't put magic() inside macro! */ - orc = CONFNAK; - PUTCHAR(CI_MAGICNUMBER, nakp); - PUTCHAR(CILEN_LONG, nakp); - PUTLONG(cilong, nakp); - break; - } - ho->neg_magicnumber = 1; - ho->magicnumber = cilong; - break; - - - case CI_PCOMPRESSION: -#if TRACELCP > 0 - snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " PCOMPRESSION"); - traceNdx = strlen(traceBuf); -#endif - if (!ao->neg_pcompression || - cilen != CILEN_VOID) { - orc = CONFREJ; - break; - } - ho->neg_pcompression = 1; - break; - - case CI_ACCOMPRESSION: -#if TRACELCP > 0 - snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " ACCOMPRESSION"); - traceNdx = strlen(traceBuf); -#endif - if (!ao->neg_accompression || - cilen != CILEN_VOID) { - orc = CONFREJ; - break; - } - ho->neg_accompression = 1; - break; - - case CI_MRRU: -#if TRACELCP > 0 - snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_MRRU"); - traceNdx = strlen(traceBuf); -#endif - orc = CONFREJ; - break; - - case CI_SSNHF: -#if TRACELCP > 0 - snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_SSNHF"); - traceNdx = strlen(traceBuf); -#endif - orc = CONFREJ; - break; - - case CI_EPDISC: -#if TRACELCP > 0 - snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CI_EPDISC"); - traceNdx = strlen(traceBuf); -#endif - orc = CONFREJ; - break; - - default: -#if TRACELCP - snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " unknown %d", citype); - traceNdx = strlen(traceBuf); -#endif - orc = CONFREJ; - break; - } - - endswitch: -#if TRACELCP - if (traceNdx >= 80 - 32) { - LCPDEBUG(LOG_INFO, ("lcp_reqci: rcvd%s\n", traceBuf)); - traceNdx = 0; - } -#endif - if (orc == CONFACK && /* Good CI */ - rc != CONFACK) { /* but prior CI wasnt? */ - continue; /* Don't send this one */ - } - - if (orc == CONFNAK) { /* Nak this CI? */ - if (reject_if_disagree /* Getting fed up with sending NAKs? */ - && citype != CI_MAGICNUMBER) { - orc = CONFREJ; /* Get tough if so */ - } else { - if (rc == CONFREJ) { /* Rejecting prior CI? */ - continue; /* Don't send this one */ - } - rc = CONFNAK; - } - } - if (orc == CONFREJ) { /* Reject this CI */ - rc = CONFREJ; - if (cip != rejp) { /* Need to move rejected CI? */ - BCOPY(cip, rejp, cilen); /* Move it */ - } - INCPTR(cilen, rejp); /* Update output pointer */ - } - } - - /* - * If we wanted to send additional NAKs (for unsent CIs), the - * code would go here. The extra NAKs would go at *nakp. - * At present there are no cases where we want to ask the - * peer to negotiate an option. - */ - - switch (rc) { - case CONFACK: - *lenp = (int)(next - inp); - break; - case CONFNAK: - /* - * Copy the Nak'd options from the nak_buffer to the caller's buffer. - */ - *lenp = (int)(nakp - nak_buffer); - BCOPY(nak_buffer, inp, *lenp); - break; - case CONFREJ: - *lenp = (int)(rejp - inp); - break; - } - -#if TRACELCP > 0 - if (traceNdx > 0) { - LCPDEBUG(LOG_INFO, ("lcp_reqci: %s\n", traceBuf)); - } -#endif - LCPDEBUG(LOG_INFO, ("lcp_reqci: returning CONF%s.\n", CODENAME(rc))); - return (rc); /* Return final code */ -} - - -/* - * lcp_up - LCP has come UP. - */ -static void -lcp_up(fsm *f) -{ - lcp_options *wo = &lcp_wantoptions[f->unit]; - lcp_options *ho = &lcp_hisoptions[f->unit]; - lcp_options *go = &lcp_gotoptions[f->unit]; - lcp_options *ao = &lcp_allowoptions[f->unit]; - - if (!go->neg_magicnumber) { - go->magicnumber = 0; - } - if (!ho->neg_magicnumber) { - ho->magicnumber = 0; - } - - /* - * Set our MTU to the smaller of the MTU we wanted and - * the MRU our peer wanted. If we negotiated an MRU, - * set our MRU to the larger of value we wanted and - * the value we got in the negotiation. - */ - ppp_send_config(f->unit, LWIP_MIN(ao->mru, (ho->neg_mru? ho->mru: PPP_MRU)), - (ho->neg_asyncmap? ho->asyncmap: 0xffffffffl), - ho->neg_pcompression, ho->neg_accompression); - /* - * If the asyncmap hasn't been negotiated, we really should - * set the receive asyncmap to ffffffff, but we set it to 0 - * for backwards contemptibility. - */ - ppp_recv_config(f->unit, (go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_MRU), - (go->neg_asyncmap? go->asyncmap: 0x00000000), - go->neg_pcompression, go->neg_accompression); - - if (ho->neg_mru) { - peer_mru[f->unit] = ho->mru; - } - - lcp_echo_lowerup(f->unit); /* Enable echo messages */ - - link_established(f->unit); /* The link is up; authenticate now */ -} - - -/* - * lcp_down - LCP has gone DOWN. - * - * Alert other protocols. - */ -static void -lcp_down(fsm *f) -{ - lcp_options *go = &lcp_gotoptions[f->unit]; - - lcp_echo_lowerdown(f->unit); - - link_down(f->unit); - - ppp_send_config(f->unit, PPP_MRU, 0xffffffffl, 0, 0); - ppp_recv_config(f->unit, PPP_MRU, - (go->neg_asyncmap? go->asyncmap: 0x00000000), - go->neg_pcompression, go->neg_accompression); - peer_mru[f->unit] = PPP_MRU; -} - - -/* - * lcp_starting - LCP needs the lower layer up. - */ -static void -lcp_starting(fsm *f) -{ - link_required(f->unit); /* lwip: currently does nothing */ -} - - -/* - * lcp_finished - LCP has finished with the lower layer. - */ -static void -lcp_finished(fsm *f) -{ - link_terminated(f->unit); /* we are finished with the link */ -} - - -#if PPP_ADDITIONAL_CALLBACKS -/* - * print_string - print a readable representation of a string using - * printer. - */ -static void -print_string( char *p, int len, void (*printer) (void *, char *, ...), void *arg) -{ - int c; - - printer(arg, "\""); - for (; len > 0; --len) { - c = *p++; - if (' ' <= c && c <= '~') { - if (c == '\\' || c == '"') { - printer(arg, "\\"); - } - printer(arg, "%c", c); - } else { - switch (c) { - case '\n': - printer(arg, "\\n"); - break; - case '\r': - printer(arg, "\\r"); - break; - case '\t': - printer(arg, "\\t"); - break; - default: - printer(arg, "\\%.3o", c); - } - } - } - printer(arg, "\""); -} - - -/* - * lcp_printpkt - print the contents of an LCP packet. - */ -static char *lcp_codenames[] = { - "ConfReq", "ConfAck", "ConfNak", "ConfRej", - "TermReq", "TermAck", "CodeRej", "ProtRej", - "EchoReq", "EchoRep", "DiscReq" -}; - -static int -lcp_printpkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) -{ - int code, id, len, olen; - u_char *pstart, *optend; - u_short cishort; - u32_t cilong; - - if (plen < HEADERLEN) { - return 0; - } - pstart = p; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < HEADERLEN || len > plen) { - return 0; - } - - if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *)) { - printer(arg, " %s", lcp_codenames[code-1]); - } else { - printer(arg, " code=0x%x", code); - } - printer(arg, " id=0x%x", id); - len -= HEADERLEN; - switch (code) { - case CONFREQ: - case CONFACK: - case CONFNAK: - case CONFREJ: - /* print option list */ - while (len >= 2) { - GETCHAR(code, p); - GETCHAR(olen, p); - p -= 2; - if (olen < 2 || olen > len) { - break; - } - printer(arg, " <"); - len -= olen; - optend = p + olen; - switch (code) { - case CI_MRU: - if (olen == CILEN_SHORT) { - p += 2; - GETSHORT(cishort, p); - printer(arg, "mru %d", cishort); - } - break; - case CI_ASYNCMAP: - if (olen == CILEN_LONG) { - p += 2; - GETLONG(cilong, p); - printer(arg, "asyncmap 0x%lx", cilong); - } - break; - case CI_AUTHTYPE: - if (olen >= CILEN_SHORT) { - p += 2; - printer(arg, "auth "); - GETSHORT(cishort, p); - switch (cishort) { - case PPP_PAP: - printer(arg, "pap"); - break; - case PPP_CHAP: - printer(arg, "chap"); - break; - default: - printer(arg, "0x%x", cishort); - } - } - break; - case CI_QUALITY: - if (olen >= CILEN_SHORT) { - p += 2; - printer(arg, "quality "); - GETSHORT(cishort, p); - switch (cishort) { - case PPP_LQR: - printer(arg, "lqr"); - break; - default: - printer(arg, "0x%x", cishort); - } - } - break; - case CI_CALLBACK: - if (olen >= CILEN_CHAR) { - p += 2; - printer(arg, "callback "); - GETSHORT(cishort, p); - switch (cishort) { - case CBCP_OPT: - printer(arg, "CBCP"); - break; - default: - printer(arg, "0x%x", cishort); - } - } - break; - case CI_MAGICNUMBER: - if (olen == CILEN_LONG) { - p += 2; - GETLONG(cilong, p); - printer(arg, "magic 0x%x", cilong); - } - break; - case CI_PCOMPRESSION: - if (olen == CILEN_VOID) { - p += 2; - printer(arg, "pcomp"); - } - break; - case CI_ACCOMPRESSION: - if (olen == CILEN_VOID) { - p += 2; - printer(arg, "accomp"); - } - break; - } - while (p < optend) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - printer(arg, ">"); - } - break; - - case TERMACK: - case TERMREQ: - if (len > 0 && *p >= ' ' && *p < 0x7f) { - printer(arg, " "); - print_string((char*)p, len, printer, arg); - p += len; - len = 0; - } - break; - - case ECHOREQ: - case ECHOREP: - case DISCREQ: - if (len >= 4) { - GETLONG(cilong, p); - printer(arg, " magic=0x%x", cilong); - p += 4; - len -= 4; - } - break; - } - - /* print the rest of the bytes in the packet */ - for (; len > 0; --len) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - - return (int)(p - pstart); -} -#endif /* PPP_ADDITIONAL_CALLBACKS */ - -/* - * Time to shut down the link because there is nothing out there. - */ -static void -LcpLinkFailure (fsm *f) -{ - if (f->state == LS_OPENED) { - LCPDEBUG(LOG_INFO, ("No response to %d echo-requests\n", lcp_echos_pending)); - LCPDEBUG(LOG_NOTICE, ("Serial link appears to be disconnected.\n")); - lcp_close(f->unit, "Peer not responding"); - } -} - -/* - * Timer expired for the LCP echo requests from this process. - */ -static void -LcpEchoCheck (fsm *f) -{ - LcpSendEchoRequest (f); - - /* - * Start the timer for the next interval. - */ - LWIP_ASSERT("lcp_echo_timer_running == 0", lcp_echo_timer_running == 0); - - TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval); - lcp_echo_timer_running = 1; -} - -/* - * LcpEchoTimeout - Timer expired on the LCP echo - */ -static void -LcpEchoTimeout (void *arg) -{ - if (lcp_echo_timer_running != 0) { - lcp_echo_timer_running = 0; - LcpEchoCheck ((fsm *) arg); - } -} - -/* - * LcpEchoReply - LCP has received a reply to the echo - */ -static void -lcp_received_echo_reply (fsm *f, int id, u_char *inp, int len) -{ - u32_t magic; - - LWIP_UNUSED_ARG(id); - - /* Check the magic number - don't count replies from ourselves. */ - if (len < 4) { - LCPDEBUG(LOG_WARNING, ("lcp: received short Echo-Reply, length %d\n", len)); - return; - } - GETLONG(magic, inp); - if (lcp_gotoptions[f->unit].neg_magicnumber && magic == lcp_gotoptions[f->unit].magicnumber) { - LCPDEBUG(LOG_WARNING, ("appear to have received our own echo-reply!\n")); - return; - } - - /* Reset the number of outstanding echo frames */ - lcp_echos_pending = 0; -} - -/* - * LcpSendEchoRequest - Send an echo request frame to the peer - */ -static void -LcpSendEchoRequest (fsm *f) -{ - u32_t lcp_magic; - u_char pkt[4], *pktp; - - /* - * Detect the failure of the peer at this point. - */ - if (lcp_echo_fails != 0) { - if (lcp_echos_pending >= lcp_echo_fails) { - LcpLinkFailure(f); - lcp_echos_pending = 0; - } - } - - /* - * Make and send the echo request frame. - */ - if (f->state == LS_OPENED) { - lcp_magic = lcp_gotoptions[f->unit].magicnumber; - pktp = pkt; - PUTLONG(lcp_magic, pktp); - fsm_sdata(f, ECHOREQ, (u_char)(lcp_echo_number++ & 0xFF), pkt, (int)(pktp - pkt)); - ++lcp_echos_pending; - } -} - -/* - * lcp_echo_lowerup - Start the timer for the LCP frame - */ - -static void -lcp_echo_lowerup (int unit) -{ - fsm *f = &lcp_fsm[unit]; - - /* Clear the parameters for generating echo frames */ - lcp_echos_pending = 0; - lcp_echo_number = 0; - lcp_echo_timer_running = 0; - - /* If a timeout interval is specified then start the timer */ - if (lcp_echo_interval != 0) { - LcpEchoCheck (f); - } -} - -/* - * lcp_echo_lowerdown - Stop the timer for the LCP frame - */ - -static void -lcp_echo_lowerdown (int unit) -{ - fsm *f = &lcp_fsm[unit]; - - if (lcp_echo_timer_running != 0) { - UNTIMEOUT (LcpEchoTimeout, f); - lcp_echo_timer_running = 0; - } -} - -#endif /* PPP_SUPPORT */ diff --git a/third_party/lwip/netif/ppp/lcp.h b/third_party/lwip/netif/ppp/lcp.h deleted file mode 100644 index 49478c8..0000000 --- a/third_party/lwip/netif/ppp/lcp.h +++ /dev/null @@ -1,151 +0,0 @@ -/***************************************************************************** -* lcp.h - Network Link Control Protocol header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-11-05 Guy Lancaster , Global Election Systems Inc. -* Original derived from BSD codes. -*****************************************************************************/ -/* - * lcp.h - Link Control Protocol definitions. - * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * $Id: lcp.h,v 1.4 2010/01/18 20:49:43 goldsimon Exp $ - */ - -#ifndef LCP_H -#define LCP_H -/* - * Options. - */ -#define CI_MRU 1 /* Maximum Receive Unit */ -#define CI_ASYNCMAP 2 /* Async Control Character Map */ -#define CI_AUTHTYPE 3 /* Authentication Type */ -#define CI_QUALITY 4 /* Quality Protocol */ -#define CI_MAGICNUMBER 5 /* Magic Number */ -#define CI_PCOMPRESSION 7 /* Protocol Field Compression */ -#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */ -#define CI_CALLBACK 13 /* callback */ -#define CI_MRRU 17 /* max reconstructed receive unit; multilink */ -#define CI_SSNHF 18 /* short sequence numbers for multilink */ -#define CI_EPDISC 19 /* endpoint discriminator */ - -/* - * LCP-specific packet types (code numbers). - */ -#define PROTREJ 8 /* Protocol Reject */ -#define ECHOREQ 9 /* Echo Request */ -#define ECHOREP 10 /* Echo Reply */ -#define DISCREQ 11 /* Discard Request */ -#define CBCP_OPT 6 /* Use callback control protocol */ - -/* - * The state of options is described by an lcp_options structure. - */ -typedef struct lcp_options { - u_int passive : 1; /* Don't die if we don't get a response */ - u_int silent : 1; /* Wait for the other end to start first */ - u_int restart : 1; /* Restart vs. exit after close */ - u_int neg_mru : 1; /* Negotiate the MRU? */ - u_int neg_asyncmap : 1; /* Negotiate the async map? */ - u_int neg_upap : 1; /* Ask for UPAP authentication? */ - u_int neg_chap : 1; /* Ask for CHAP authentication? */ - u_int neg_magicnumber : 1; /* Ask for magic number? */ - u_int neg_pcompression : 1; /* HDLC Protocol Field Compression? */ - u_int neg_accompression : 1; /* HDLC Address/Control Field Compression? */ - u_int neg_lqr : 1; /* Negotiate use of Link Quality Reports */ - u_int neg_cbcp : 1; /* Negotiate use of CBCP */ -#ifdef PPP_MULTILINK - u_int neg_mrru : 1; /* Negotiate multilink MRRU */ - u_int neg_ssnhf : 1; /* Negotiate short sequence numbers */ - u_int neg_endpoint : 1; /* Negotiate endpoint discriminator */ -#endif - u_short mru; /* Value of MRU */ -#ifdef PPP_MULTILINK - u_short mrru; /* Value of MRRU, and multilink enable */ -#endif - u_char chap_mdtype; /* which MD type (hashing algorithm) */ - u32_t asyncmap; /* Value of async map */ - u32_t magicnumber; - int numloops; /* Number of loops during magic number neg. */ - u32_t lqr_period; /* Reporting period for LQR 1/100ths second */ -#ifdef PPP_MULTILINK - struct epdisc endpoint; /* endpoint discriminator */ -#endif -} lcp_options; - -/* - * Values for phase from BSD pppd.h based on RFC 1661. - */ -typedef enum { - PHASE_DEAD = 0, - PHASE_INITIALIZE, - PHASE_ESTABLISH, - PHASE_AUTHENTICATE, - PHASE_CALLBACK, - PHASE_NETWORK, - PHASE_TERMINATE -} LinkPhase; - - - -extern LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */ -extern lcp_options lcp_wantoptions[]; -extern lcp_options lcp_gotoptions[]; -extern lcp_options lcp_allowoptions[]; -extern lcp_options lcp_hisoptions[]; -extern ext_accm xmit_accm[]; - - -void lcp_init (int); -void lcp_open (int); -void lcp_close (int, char *); -void lcp_lowerup (int); -void lcp_lowerdown(int); -void lcp_sprotrej (int, u_char *, int); /* send protocol reject */ - -extern struct protent lcp_protent; - -/* Default number of times we receive our magic number from the peer - before deciding the link is looped-back. */ -#define DEFLOOPBACKFAIL 10 - -#endif /* LCP_H */ diff --git a/third_party/lwip/netif/ppp/magic.c b/third_party/lwip/netif/ppp/magic.c deleted file mode 100644 index 0c53c83..0000000 --- a/third_party/lwip/netif/ppp/magic.c +++ /dev/null @@ -1,80 +0,0 @@ -/***************************************************************************** -* magic.c - Network Random Number Generator program file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 by Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-12-04 Guy Lancaster , Global Election Systems Inc. -* Original based on BSD magic.c. -*****************************************************************************/ -/* - * magic.c - PPP Magic Number routines. - * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#include "lwip/opt.h" - -#if PPP_SUPPORT - -#include "ppp_impl.h" -#include "randm.h" -#include "magic.h" - - -/* - * magicInit - Initialize the magic number generator. - * - * Since we use another random number generator that has its own - * initialization, we do nothing here. - */ -void magicInit() -{ - return; -} - -/* - * magic - Returns the next magic number. - */ -u32_t magic() -{ - return avRandom(); -} - -#endif /* PPP_SUPPORT */ diff --git a/third_party/lwip/netif/ppp/magic.h b/third_party/lwip/netif/ppp/magic.h deleted file mode 100644 index e308037..0000000 --- a/third_party/lwip/netif/ppp/magic.h +++ /dev/null @@ -1,63 +0,0 @@ -/***************************************************************************** -* magic.h - Network Random Number Generator header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-12-04 Guy Lancaster , Global Election Systems Inc. -* Original derived from BSD codes. -*****************************************************************************/ -/* - * magic.h - PPP Magic Number definitions. - * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * $Id: magic.h,v 1.3 2010/01/18 20:49:43 goldsimon Exp $ - */ - -#ifndef MAGIC_H -#define MAGIC_H - -/* Initialize the magic number generator */ -void magicInit(void); - -/* Returns the next magic number */ -u32_t magic(void); - -#endif /* MAGIC_H */ diff --git a/third_party/lwip/netif/ppp/md5.c b/third_party/lwip/netif/ppp/md5.c deleted file mode 100644 index befbbab..0000000 --- a/third_party/lwip/netif/ppp/md5.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - *********************************************************************** - ** md5.c -- the source code for MD5 routines ** - ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** - ** Created: 2/17/90 RLR ** - ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. ** - *********************************************************************** - */ - -/* - *********************************************************************** - ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** - ** ** - ** License to copy and use this software is granted provided that ** - ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** - ** Digest Algorithm" in all material mentioning or referencing this ** - ** software or this function. ** - ** ** - ** License is also granted to make and use derivative works ** - ** provided that such works are identified as "derived from the RSA ** - ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** - ** material mentioning or referencing the derived work. ** - ** ** - ** RSA Data Security, Inc. makes no representations concerning ** - ** either the merchantability of this software or the suitability ** - ** of this software for any particular purpose. It is provided "as ** - ** is" without express or implied warranty of any kind. ** - ** ** - ** These notices must be retained in any copies of any part of this ** - ** documentation and/or software. ** - *********************************************************************** - */ - -#include "lwip/opt.h" - -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if CHAP_SUPPORT || MD5_SUPPORT - -#include "ppp_impl.h" -#include "pppdebug.h" - -#include "md5.h" - -#include - -/* - *********************************************************************** - ** Message-digest routines: ** - ** To form the message digest for a message M ** - ** (1) Initialize a context buffer mdContext using MD5Init ** - ** (2) Call MD5Update on mdContext and M ** - ** (3) Call MD5Final on mdContext ** - ** The message digest is now in mdContext->digest[0...15] ** - *********************************************************************** - */ - -/* forward declaration */ -static void Transform (u32_t *buf, u32_t *in); - -static unsigned char PADDING[64] = { - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* F, G, H and I are basic MD5 functions */ -#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define I(x, y, z) ((y) ^ ((x) | (~z))) - -/* ROTATE_LEFT rotates x left n bits */ -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) - -/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ -/* Rotation is separate from addition to prevent recomputation */ -#define FF(a, b, c, d, x, s, ac) \ - {(a) += F ((b), (c), (d)) + (x) + (u32_t)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define GG(a, b, c, d, x, s, ac) \ - {(a) += G ((b), (c), (d)) + (x) + (u32_t)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define HH(a, b, c, d, x, s, ac) \ - {(a) += H ((b), (c), (d)) + (x) + (u32_t)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } -#define II(a, b, c, d, x, s, ac) \ - {(a) += I ((b), (c), (d)) + (x) + (u32_t)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ - } - -#ifdef __STDC__ -#define UL(x) x##UL -#else -#ifdef WIN32 -#define UL(x) x##UL -#else -#define UL(x) x -#endif -#endif - -/* The routine MD5Init initializes the message-digest context - mdContext. All fields are set to zero. - */ -void -MD5Init (MD5_CTX *mdContext) -{ - mdContext->i[0] = mdContext->i[1] = (u32_t)0; - - /* Load magic initialization constants. */ - mdContext->buf[0] = (u32_t)0x67452301UL; - mdContext->buf[1] = (u32_t)0xefcdab89UL; - mdContext->buf[2] = (u32_t)0x98badcfeUL; - mdContext->buf[3] = (u32_t)0x10325476UL; -} - -/* The routine MD5Update updates the message-digest context to - account for the presence of each of the characters inBuf[0..inLen-1] - in the message whose digest is being computed. - */ -void -MD5Update(MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen) -{ - u32_t in[16]; - int mdi; - unsigned int i, ii; - -#if 0 - PPPDEBUG(LOG_INFO, ("MD5Update: %u:%.*H\n", inLen, LWIP_MIN(inLen, 20) * 2, inBuf)); - PPPDEBUG(LOG_INFO, ("MD5Update: %u:%s\n", inLen, inBuf)); -#endif - - /* compute number of bytes mod 64 */ - mdi = (int)((mdContext->i[0] >> 3) & 0x3F); - - /* update number of bits */ - if ((mdContext->i[0] + ((u32_t)inLen << 3)) < mdContext->i[0]) { - mdContext->i[1]++; - } - mdContext->i[0] += ((u32_t)inLen << 3); - mdContext->i[1] += ((u32_t)inLen >> 29); - - while (inLen--) { - /* add new character to buffer, increment mdi */ - mdContext->in[mdi++] = *inBuf++; - - /* transform if necessary */ - if (mdi == 0x40) { - for (i = 0, ii = 0; i < 16; i++, ii += 4) { - in[i] = (((u32_t)mdContext->in[ii+3]) << 24) | - (((u32_t)mdContext->in[ii+2]) << 16) | - (((u32_t)mdContext->in[ii+1]) << 8) | - ((u32_t)mdContext->in[ii]); - } - Transform (mdContext->buf, in); - mdi = 0; - } - } -} - -/* The routine MD5Final terminates the message-digest computation and - ends with the desired message digest in mdContext->digest[0...15]. - */ -void -MD5Final (unsigned char hash[], MD5_CTX *mdContext) -{ - u32_t in[16]; - int mdi; - unsigned int i, ii; - unsigned int padLen; - - /* save number of bits */ - in[14] = mdContext->i[0]; - in[15] = mdContext->i[1]; - - /* compute number of bytes mod 64 */ - mdi = (int)((mdContext->i[0] >> 3) & 0x3F); - - /* pad out to 56 mod 64 */ - padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); - MD5Update (mdContext, PADDING, padLen); - - /* append length in bits and transform */ - for (i = 0, ii = 0; i < 14; i++, ii += 4) { - in[i] = (((u32_t)mdContext->in[ii+3]) << 24) | - (((u32_t)mdContext->in[ii+2]) << 16) | - (((u32_t)mdContext->in[ii+1]) << 8) | - ((u32_t)mdContext->in[ii]); - } - Transform (mdContext->buf, in); - - /* store buffer in digest */ - for (i = 0, ii = 0; i < 4; i++, ii += 4) { - mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); - mdContext->digest[ii+1] = - (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); - mdContext->digest[ii+2] = - (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); - mdContext->digest[ii+3] = - (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); - } - SMEMCPY(hash, mdContext->digest, 16); -} - -/* Basic MD5 step. Transforms buf based on in. - */ -static void -Transform (u32_t *buf, u32_t *in) -{ - u32_t a = buf[0], b = buf[1], c = buf[2], d = buf[3]; - - /* Round 1 */ -#define S11 7 -#define S12 12 -#define S13 17 -#define S14 22 - FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */ - FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */ - FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */ - FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */ - FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */ - FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */ - FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */ - FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */ - FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */ - FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */ - FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */ - FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */ - FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */ - FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */ - FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */ - FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */ - - /* Round 2 */ -#define S21 5 -#define S22 9 -#define S23 14 -#define S24 20 - GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */ - GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */ - GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */ - GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */ - GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */ - GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */ - GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */ - GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */ - GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */ - GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */ - GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */ - GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */ - GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */ - GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */ - GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */ - GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */ - - /* Round 3 */ -#define S31 4 -#define S32 11 -#define S33 16 -#define S34 23 - HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */ - HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */ - HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */ - HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */ - HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */ - HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */ - HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */ - HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */ - HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */ - HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */ - HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */ - HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */ - HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */ - HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */ - HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */ - HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */ - - /* Round 4 */ -#define S41 6 -#define S42 10 -#define S43 15 -#define S44 21 - II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */ - II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */ - II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */ - II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */ - II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */ - II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */ - II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */ - II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */ - II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */ - II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */ - II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */ - II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */ - II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */ - II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */ - II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */ - II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */ - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -#endif /* CHAP_SUPPORT || MD5_SUPPORT */ - -#endif /* PPP_SUPPORT */ diff --git a/third_party/lwip/netif/ppp/md5.h b/third_party/lwip/netif/ppp/md5.h deleted file mode 100644 index 0bcb23c..0000000 --- a/third_party/lwip/netif/ppp/md5.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - *********************************************************************** - ** md5.h -- header file for implementation of MD5 ** - ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** - ** Created: 2/17/90 RLR ** - ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** - ** Revised (for MD5): RLR 4/27/91 ** - ** -- G modified to have y&~z instead of y&z ** - ** -- FF, GG, HH modified to add in last register done ** - ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 ** - ** -- distinct additive constant for each step ** - ** -- round 4 added, working mod 7 ** - *********************************************************************** - */ - -/* - *********************************************************************** - ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** - ** ** - ** License to copy and use this software is granted provided that ** - ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** - ** Digest Algorithm" in all material mentioning or referencing this ** - ** software or this function. ** - ** ** - ** License is also granted to make and use derivative works ** - ** provided that such works are identified as "derived from the RSA ** - ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** - ** material mentioning or referencing the derived work. ** - ** ** - ** RSA Data Security, Inc. makes no representations concerning ** - ** either the merchantability of this software or the suitability ** - ** of this software for any particular purpose. It is provided "as ** - ** is" without express or implied warranty of any kind. ** - ** ** - ** These notices must be retained in any copies of any part of this ** - ** documentation and/or software. ** - *********************************************************************** - */ - -#ifndef MD5_H -#define MD5_H - -/* Data structure for MD5 (Message-Digest) computation */ -typedef struct { - u32_t i[2]; /* number of _bits_ handled mod 2^64 */ - u32_t buf[4]; /* scratch buffer */ - unsigned char in[64]; /* input buffer */ - unsigned char digest[16]; /* actual digest after MD5Final call */ -} MD5_CTX; - -void MD5Init ( MD5_CTX *mdContext); -void MD5Update( MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen); -void MD5Final ( unsigned char hash[], MD5_CTX *mdContext); - -#endif /* MD5_H */ diff --git a/third_party/lwip/netif/ppp/pap.c b/third_party/lwip/netif/ppp/pap.c deleted file mode 100644 index 7436544..0000000 --- a/third_party/lwip/netif/ppp/pap.c +++ /dev/null @@ -1,628 +0,0 @@ -/***************************************************************************** -* pap.c - Network Password Authentication Protocol program file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 by Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-12-12 Guy Lancaster , Global Election Systems Inc. -* Original. -*****************************************************************************/ -/* - * upap.c - User/Password Authentication Protocol. - * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#include "lwip/opt.h" - -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "ppp_impl.h" -#include "pppdebug.h" - -#include "auth.h" -#include "pap.h" - -#include - -#if 0 /* UNUSED */ -static bool hide_password = 1; - -/* - * Command-line options. - */ -static option_t pap_option_list[] = { - { "hide-password", o_bool, &hide_password, - "Don't output passwords to log", 1 }, - { "show-password", o_bool, &hide_password, - "Show password string in debug log messages", 0 }, - { "pap-restart", o_int, &upap[0].us_timeouttime, - "Set retransmit timeout for PAP" }, - { "pap-max-authreq", o_int, &upap[0].us_maxtransmits, - "Set max number of transmissions for auth-reqs" }, - { "pap-timeout", o_int, &upap[0].us_reqtimeout, - "Set time limit for peer PAP authentication" }, - { NULL } -}; -#endif - -/* - * Protocol entry points. - */ -static void upap_init (int); -static void upap_lowerup (int); -static void upap_lowerdown (int); -static void upap_input (int, u_char *, int); -static void upap_protrej (int); -#if PPP_ADDITIONAL_CALLBACKS -static int upap_printpkt (u_char *, int, void (*)(void *, char *, ...), void *); -#endif /* PPP_ADDITIONAL_CALLBACKS */ - -struct protent pap_protent = { - PPP_PAP, - upap_init, - upap_input, - upap_protrej, - upap_lowerup, - upap_lowerdown, - NULL, - NULL, -#if PPP_ADDITIONAL_CALLBACKS - upap_printpkt, - NULL, -#endif /* PPP_ADDITIONAL_CALLBACKS */ - 1, - "PAP", -#if PPP_ADDITIONAL_CALLBACKS - NULL, - NULL, - NULL -#endif /* PPP_ADDITIONAL_CALLBACKS */ -}; - -upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */ - -static void upap_timeout (void *); -static void upap_reqtimeout(void *); -static void upap_rauthreq (upap_state *, u_char *, u_char, int); -static void upap_rauthack (upap_state *, u_char *, int, int); -static void upap_rauthnak (upap_state *, u_char *, int, int); -static void upap_sauthreq (upap_state *); -static void upap_sresp (upap_state *, u_char, u_char, char *, int); - - -/* - * upap_init - Initialize a UPAP unit. - */ -static void -upap_init(int unit) -{ - upap_state *u = &upap[unit]; - - UPAPDEBUG(LOG_INFO, ("upap_init: %d\n", unit)); - u->us_unit = unit; - u->us_user = NULL; - u->us_userlen = 0; - u->us_passwd = NULL; - u->us_passwdlen = 0; - u->us_clientstate = UPAPCS_INITIAL; - u->us_serverstate = UPAPSS_INITIAL; - u->us_id = 0; - u->us_timeouttime = UPAP_DEFTIMEOUT; - u->us_maxtransmits = 10; - u->us_reqtimeout = UPAP_DEFREQTIME; -} - -/* - * upap_authwithpeer - Authenticate us with our peer (start client). - * - * Set new state and send authenticate's. - */ -void -upap_authwithpeer(int unit, char *user, char *password) -{ - upap_state *u = &upap[unit]; - - UPAPDEBUG(LOG_INFO, ("upap_authwithpeer: %d user=%s password=%s s=%d\n", - unit, user, password, u->us_clientstate)); - - /* Save the username and password we're given */ - u->us_user = user; - u->us_userlen = (int)os_strlen(user); - u->us_passwd = password; - u->us_passwdlen = (int)os_strlen(password); - - u->us_transmits = 0; - - /* Lower layer up yet? */ - if (u->us_clientstate == UPAPCS_INITIAL || - u->us_clientstate == UPAPCS_PENDING) { - u->us_clientstate = UPAPCS_PENDING; - return; - } - - upap_sauthreq(u); /* Start protocol */ -} - - -/* - * upap_authpeer - Authenticate our peer (start server). - * - * Set new state. - */ -void -upap_authpeer(int unit) -{ - upap_state *u = &upap[unit]; - - /* Lower layer up yet? */ - if (u->us_serverstate == UPAPSS_INITIAL || - u->us_serverstate == UPAPSS_PENDING) { - u->us_serverstate = UPAPSS_PENDING; - return; - } - - u->us_serverstate = UPAPSS_LISTEN; - if (u->us_reqtimeout > 0) { - TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout); - } -} - -/* - * upap_timeout - Retransmission timer for sending auth-reqs expired. - */ -static void -upap_timeout(void *arg) -{ - upap_state *u = (upap_state *) arg; - - UPAPDEBUG(LOG_INFO, ("upap_timeout: %d timeout %d expired s=%d\n", - u->us_unit, u->us_timeouttime, u->us_clientstate)); - - if (u->us_clientstate != UPAPCS_AUTHREQ) { - UPAPDEBUG(LOG_INFO, ("upap_timeout: not in AUTHREQ state!\n")); - return; - } - - if (u->us_transmits >= u->us_maxtransmits) { - /* give up in disgust */ - UPAPDEBUG(LOG_ERR, ("No response to PAP authenticate-requests\n")); - u->us_clientstate = UPAPCS_BADAUTH; - auth_withpeer_fail(u->us_unit, PPP_PAP); - return; - } - - upap_sauthreq(u); /* Send Authenticate-Request and set upap timeout*/ -} - - -/* - * upap_reqtimeout - Give up waiting for the peer to send an auth-req. - */ -static void -upap_reqtimeout(void *arg) -{ - upap_state *u = (upap_state *) arg; - - if (u->us_serverstate != UPAPSS_LISTEN) { - return; /* huh?? */ - } - - auth_peer_fail(u->us_unit, PPP_PAP); - u->us_serverstate = UPAPSS_BADAUTH; -} - - -/* - * upap_lowerup - The lower layer is up. - * - * Start authenticating if pending. - */ -static void -upap_lowerup(int unit) -{ - upap_state *u = &upap[unit]; - - UPAPDEBUG(LOG_INFO, ("upap_lowerup: init %d clientstate s=%d\n", unit, u->us_clientstate)); - - if (u->us_clientstate == UPAPCS_INITIAL) { - u->us_clientstate = UPAPCS_CLOSED; - } else if (u->us_clientstate == UPAPCS_PENDING) { - upap_sauthreq(u); /* send an auth-request */ - /* now client state is UPAPCS__AUTHREQ */ - } - - if (u->us_serverstate == UPAPSS_INITIAL) { - u->us_serverstate = UPAPSS_CLOSED; - } else if (u->us_serverstate == UPAPSS_PENDING) { - u->us_serverstate = UPAPSS_LISTEN; - if (u->us_reqtimeout > 0) { - TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout); - } - } -} - - -/* - * upap_lowerdown - The lower layer is down. - * - * Cancel all timeouts. - */ -static void -upap_lowerdown(int unit) -{ - upap_state *u = &upap[unit]; - - UPAPDEBUG(LOG_INFO, ("upap_lowerdown: %d s=%d\n", unit, u->us_clientstate)); - - if (u->us_clientstate == UPAPCS_AUTHREQ) { /* Timeout pending? */ - UNTIMEOUT(upap_timeout, u); /* Cancel timeout */ - } - if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0) { - UNTIMEOUT(upap_reqtimeout, u); - } - - u->us_clientstate = UPAPCS_INITIAL; - u->us_serverstate = UPAPSS_INITIAL; -} - - -/* - * upap_protrej - Peer doesn't speak this protocol. - * - * This shouldn't happen. In any case, pretend lower layer went down. - */ -static void -upap_protrej(int unit) -{ - upap_state *u = &upap[unit]; - - if (u->us_clientstate == UPAPCS_AUTHREQ) { - UPAPDEBUG(LOG_ERR, ("PAP authentication failed due to protocol-reject\n")); - auth_withpeer_fail(unit, PPP_PAP); - } - if (u->us_serverstate == UPAPSS_LISTEN) { - UPAPDEBUG(LOG_ERR, ("PAP authentication of peer failed (protocol-reject)\n")); - auth_peer_fail(unit, PPP_PAP); - } - upap_lowerdown(unit); -} - - -/* - * upap_input - Input UPAP packet. - */ -static void -upap_input(int unit, u_char *inpacket, int l) -{ - upap_state *u = &upap[unit]; - u_char *inp; - u_char code, id; - int len; - - /* - * Parse header (code, id and length). - * If packet too short, drop it. - */ - inp = inpacket; - if (l < (int)UPAP_HEADERLEN) { - UPAPDEBUG(LOG_INFO, ("pap_input: rcvd short header.\n")); - return; - } - GETCHAR(code, inp); - GETCHAR(id, inp); - GETSHORT(len, inp); - if (len < (int)UPAP_HEADERLEN) { - UPAPDEBUG(LOG_INFO, ("pap_input: rcvd illegal length.\n")); - return; - } - if (len > l) { - UPAPDEBUG(LOG_INFO, ("pap_input: rcvd short packet.\n")); - return; - } - len -= UPAP_HEADERLEN; - - /* - * Action depends on code. - */ - switch (code) { - case UPAP_AUTHREQ: - upap_rauthreq(u, inp, id, len); - break; - - case UPAP_AUTHACK: - upap_rauthack(u, inp, id, len); - break; - - case UPAP_AUTHNAK: - upap_rauthnak(u, inp, id, len); - break; - - default: /* XXX Need code reject */ - UPAPDEBUG(LOG_INFO, ("pap_input: UNHANDLED default: code: %d, id: %d, len: %d.\n", code, id, len)); - break; - } -} - - -/* - * upap_rauth - Receive Authenticate. - */ -static void -upap_rauthreq(upap_state *u, u_char *inp, u_char id, int len) -{ - u_char ruserlen, rpasswdlen; - char *ruser, *rpasswd; - u_char retcode; - char *msg; - int msglen; - - UPAPDEBUG(LOG_INFO, ("pap_rauth: Rcvd id %d.\n", id)); - - if (u->us_serverstate < UPAPSS_LISTEN) { - return; - } - - /* - * If we receive a duplicate authenticate-request, we are - * supposed to return the same status as for the first request. - */ - if (u->us_serverstate == UPAPSS_OPEN) { - upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */ - return; - } - if (u->us_serverstate == UPAPSS_BADAUTH) { - upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */ - return; - } - - /* - * Parse user/passwd. - */ - if (len < (int)sizeof (u_char)) { - UPAPDEBUG(LOG_INFO, ("pap_rauth: rcvd short packet.\n")); - return; - } - GETCHAR(ruserlen, inp); - len -= sizeof (u_char) + ruserlen + sizeof (u_char); - if (len < 0) { - UPAPDEBUG(LOG_INFO, ("pap_rauth: rcvd short packet.\n")); - return; - } - ruser = (char *) inp; - INCPTR(ruserlen, inp); - GETCHAR(rpasswdlen, inp); - if (len < rpasswdlen) { - UPAPDEBUG(LOG_INFO, ("pap_rauth: rcvd short packet.\n")); - return; - } - rpasswd = (char *) inp; - - /* - * Check the username and password given. - */ - retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen); - /* lwip: currently retcode is always UPAP_AUTHACK */ - BZERO(rpasswd, rpasswdlen); - - upap_sresp(u, retcode, id, msg, msglen); - - if (retcode == UPAP_AUTHACK) { - u->us_serverstate = UPAPSS_OPEN; - auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen); - } else { - u->us_serverstate = UPAPSS_BADAUTH; - auth_peer_fail(u->us_unit, PPP_PAP); - } - - if (u->us_reqtimeout > 0) { - UNTIMEOUT(upap_reqtimeout, u); - } -} - - -/* - * upap_rauthack - Receive Authenticate-Ack. - */ -static void -upap_rauthack(upap_state *u, u_char *inp, int id, int len) -{ - u_char msglen; - char *msg; - - LWIP_UNUSED_ARG(id); - - UPAPDEBUG(LOG_INFO, ("pap_rauthack: Rcvd id %d s=%d\n", id, u->us_clientstate)); - - if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */ - UPAPDEBUG(LOG_INFO, ("pap_rauthack: us_clientstate != UPAPCS_AUTHREQ\n")); - return; - } - - /* - * Parse message. - */ - if (len < (int)sizeof (u_char)) { - UPAPDEBUG(LOG_INFO, ("pap_rauthack: ignoring missing msg-length.\n")); - } else { - GETCHAR(msglen, inp); - if (msglen > 0) { - len -= sizeof (u_char); - if (len < msglen) { - UPAPDEBUG(LOG_INFO, ("pap_rauthack: rcvd short packet.\n")); - return; - } - msg = (char *) inp; - PRINTMSG(msg, msglen); - } - } - UNTIMEOUT(upap_timeout, u); /* Cancel timeout */ - u->us_clientstate = UPAPCS_OPEN; - - auth_withpeer_success(u->us_unit, PPP_PAP); -} - - -/* - * upap_rauthnak - Receive Authenticate-Nak. - */ -static void -upap_rauthnak(upap_state *u, u_char *inp, int id, int len) -{ - u_char msglen; - char *msg; - - LWIP_UNUSED_ARG(id); - - UPAPDEBUG(LOG_INFO, ("pap_rauthnak: Rcvd id %d s=%d\n", id, u->us_clientstate)); - - if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */ - return; - } - - /* - * Parse message. - */ - if (len < sizeof (u_char)) { - UPAPDEBUG(LOG_INFO, ("pap_rauthnak: ignoring missing msg-length.\n")); - } else { - GETCHAR(msglen, inp); - if(msglen > 0) { - len -= sizeof (u_char); - if (len < msglen) { - UPAPDEBUG(LOG_INFO, ("pap_rauthnak: rcvd short packet.\n")); - return; - } - msg = (char *) inp; - PRINTMSG(msg, msglen); - } - } - - u->us_clientstate = UPAPCS_BADAUTH; - - UPAPDEBUG(LOG_ERR, ("PAP authentication failed\n")); - auth_withpeer_fail(u->us_unit, PPP_PAP); -} - - -/* - * upap_sauthreq - Send an Authenticate-Request. - */ -static void -upap_sauthreq(upap_state *u) -{ - u_char *outp; - int outlen; - - outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) - + u->us_userlen + u->us_passwdlen; - outp = outpacket_buf[u->us_unit]; - - MAKEHEADER(outp, PPP_PAP); - - PUTCHAR(UPAP_AUTHREQ, outp); - PUTCHAR(++u->us_id, outp); - PUTSHORT(outlen, outp); - PUTCHAR(u->us_userlen, outp); - BCOPY(u->us_user, outp, u->us_userlen); - INCPTR(u->us_userlen, outp); - PUTCHAR(u->us_passwdlen, outp); - BCOPY(u->us_passwd, outp, u->us_passwdlen); - - pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN); - - UPAPDEBUG(LOG_INFO, ("pap_sauth: Sent id %d\n", u->us_id)); - - TIMEOUT(upap_timeout, u, u->us_timeouttime); - ++u->us_transmits; - u->us_clientstate = UPAPCS_AUTHREQ; -} - - -/* - * upap_sresp - Send a response (ack or nak). - */ -static void -upap_sresp(upap_state *u, u_char code, u_char id, char *msg, int msglen) -{ - u_char *outp; - int outlen; - - outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; - outp = outpacket_buf[u->us_unit]; - MAKEHEADER(outp, PPP_PAP); - - PUTCHAR(code, outp); - PUTCHAR(id, outp); - PUTSHORT(outlen, outp); - PUTCHAR(msglen, outp); - BCOPY(msg, outp, msglen); - pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN); - - UPAPDEBUG(LOG_INFO, ("pap_sresp: Sent code %d, id %d s=%d\n", code, id, u->us_clientstate)); -} - -#if PPP_ADDITIONAL_CALLBACKS -static char *upap_codenames[] = { - "AuthReq", "AuthAck", "AuthNak" -}; - -/* - * upap_printpkt - print the contents of a PAP packet. - */ -static int upap_printpkt( - u_char *p, - int plen, - void (*printer) (void *, char *, ...), - void *arg -) -{ - LWIP_UNUSED_ARG(p); - LWIP_UNUSED_ARG(plen); - LWIP_UNUSED_ARG(printer); - LWIP_UNUSED_ARG(arg); - return 0; -} -#endif /* PPP_ADDITIONAL_CALLBACKS */ - -#endif /* PAP_SUPPORT */ - -#endif /* PPP_SUPPORT */ diff --git a/third_party/lwip/netif/ppp/pap.h b/third_party/lwip/netif/ppp/pap.h deleted file mode 100644 index 4d1c424..0000000 --- a/third_party/lwip/netif/ppp/pap.h +++ /dev/null @@ -1,118 +0,0 @@ -/***************************************************************************** -* pap.h - PPP Password Authentication Protocol header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-12-04 Guy Lancaster , Global Election Systems Inc. -* Original derived from BSD codes. -*****************************************************************************/ -/* - * upap.h - User/Password Authentication Protocol definitions. - * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef PAP_H -#define PAP_H - -#if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -/* - * Packet header = Code, id, length. - */ -#define UPAP_HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short)) - - -/* - * UPAP codes. - */ -#define UPAP_AUTHREQ 1 /* Authenticate-Request */ -#define UPAP_AUTHACK 2 /* Authenticate-Ack */ -#define UPAP_AUTHNAK 3 /* Authenticate-Nak */ - -/* - * Each interface is described by upap structure. - */ -typedef struct upap_state { - int us_unit; /* Interface unit number */ - const char *us_user; /* User */ - int us_userlen; /* User length */ - const char *us_passwd; /* Password */ - int us_passwdlen; /* Password length */ - int us_clientstate; /* Client state */ - int us_serverstate; /* Server state */ - u_char us_id; /* Current id */ - int us_timeouttime; /* Timeout (seconds) for auth-req retrans. */ - int us_transmits; /* Number of auth-reqs sent */ - int us_maxtransmits; /* Maximum number of auth-reqs to send */ - int us_reqtimeout; /* Time to wait for auth-req from peer */ -} upap_state; - -/* - * Client states. - */ -#define UPAPCS_INITIAL 0 /* Connection down */ -#define UPAPCS_CLOSED 1 /* Connection up, haven't requested auth */ -#define UPAPCS_PENDING 2 /* Connection down, have requested auth */ -#define UPAPCS_AUTHREQ 3 /* We've sent an Authenticate-Request */ -#define UPAPCS_OPEN 4 /* We've received an Ack */ -#define UPAPCS_BADAUTH 5 /* We've received a Nak */ - -/* - * Server states. - */ -#define UPAPSS_INITIAL 0 /* Connection down */ -#define UPAPSS_CLOSED 1 /* Connection up, haven't requested auth */ -#define UPAPSS_PENDING 2 /* Connection down, have requested auth */ -#define UPAPSS_LISTEN 3 /* Listening for an Authenticate */ -#define UPAPSS_OPEN 4 /* We've sent an Ack */ -#define UPAPSS_BADAUTH 5 /* We've sent a Nak */ - - -extern upap_state upap[]; - -void upap_authwithpeer (int, char *, char *); -void upap_authpeer (int); - -extern struct protent pap_protent; - -#endif /* PAP_SUPPORT */ - -#endif /* PAP_H */ diff --git a/third_party/lwip/netif/ppp/ppp.c b/third_party/lwip/netif/ppp/ppp.c deleted file mode 100644 index ca50a88..0000000 --- a/third_party/lwip/netif/ppp/ppp.c +++ /dev/null @@ -1,2052 +0,0 @@ -/***************************************************************************** -* ppp.c - Network Point to Point Protocol program file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 by Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-11-05 Guy Lancaster , Global Election Systems Inc. -* Original. -*****************************************************************************/ - -/* - * ppp_defs.h - PPP definitions. - * - * if_pppvar.h - private structures and declarations for PPP. - * - * Copyright (c) 1994 The Australian National University. - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, provided that the above copyright - * notice appears in all copies. This software is provided without any - * warranty, express or implied. The Australian National University - * makes no representations about the suitability of this software for - * any purpose. - * - * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY - * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO - * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, - * OR MODIFICATIONS. - */ - -/* - * if_ppp.h - Point-to-Point Protocol definitions. - * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#include "lwip/opt.h" - -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "ppp_impl.h" -#include "lwip/ip.h" /* for ip_input() */ - -#include "pppdebug.h" - -#include "randm.h" -#include "fsm.h" -#if PAP_SUPPORT -#include "pap.h" -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT -#include "chap.h" -#endif /* CHAP_SUPPORT */ -#include "ipcp.h" -#include "lcp.h" -#include "magic.h" -#include "auth.h" -#if VJ_SUPPORT -#include "vj.h" -#endif /* VJ_SUPPORT */ -#if PPPOE_SUPPORT -#include "netif/ppp_oe.h" -#endif /* PPPOE_SUPPORT */ - -#include "lwip/tcpip.h" -#include "lwip/api.h" -#include "lwip/snmp.h" - -#include - -/*************************/ -/*** LOCAL DEFINITIONS ***/ -/*************************/ - -/** PPP_INPROC_MULTITHREADED==1 call pppInput using tcpip_callback(). - * Set this to 0 if pppInProc is called inside tcpip_thread or with NO_SYS==1. - * Default is 1 for NO_SYS==0 (multithreaded) and 0 for NO_SYS==1 (single-threaded). - */ -#ifndef PPP_INPROC_MULTITHREADED -#define PPP_INPROC_MULTITHREADED (NO_SYS==0) -#endif - -/** PPP_INPROC_OWNTHREAD==1: start a dedicated RX thread per PPP session. - * Default is 0: call pppos_input() for received raw characters, charcater - * reception is up to the port */ -#ifndef PPP_INPROC_OWNTHREAD -#define PPP_INPROC_OWNTHREAD PPP_INPROC_MULTITHREADED -#endif - -#if PPP_INPROC_OWNTHREAD && !PPP_INPROC_MULTITHREADED - #error "PPP_INPROC_OWNTHREAD needs PPP_INPROC_MULTITHREADED==1" -#endif - -/* - * The basic PPP frame. - */ -#define PPP_ADDRESS(p) (((u_char *)(p))[0]) -#define PPP_CONTROL(p) (((u_char *)(p))[1]) -#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) - -/* PPP packet parser states. Current state indicates operation yet to be - * completed. */ -typedef enum { - PDIDLE = 0, /* Idle state - waiting. */ - PDSTART, /* Process start flag. */ - PDADDRESS, /* Process address field. */ - PDCONTROL, /* Process control field. */ - PDPROTOCOL1, /* Process protocol field 1. */ - PDPROTOCOL2, /* Process protocol field 2. */ - PDDATA /* Process data byte. */ -} PPPDevStates; - -#define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07]) - -/************************/ -/*** LOCAL DATA TYPES ***/ -/************************/ - -/** RX buffer size: this may be configured smaller! */ -#ifndef PPPOS_RX_BUFSIZE -#define PPPOS_RX_BUFSIZE (PPP_MRU + PPP_HDRLEN) -#endif - -typedef struct PPPControlRx_s { - /** unit number / ppp descriptor */ - int pd; - /** the rx file descriptor */ - sio_fd_t fd; - /** receive buffer - encoded data is stored here */ -#if PPP_INPROC_OWNTHREAD - u_char rxbuf[PPPOS_RX_BUFSIZE]; -#endif /* PPP_INPROC_OWNTHREAD */ - - /* The input packet. */ - struct pbuf *inHead, *inTail; - -#if PPPOS_SUPPORT - u16_t inProtocol; /* The input protocol code. */ - u16_t inFCS; /* Input Frame Check Sequence value. */ -#endif /* PPPOS_SUPPORT */ - PPPDevStates inState; /* The input process state. */ - char inEscaped; /* Escape next character. */ - ext_accm inACCM; /* Async-Ctl-Char-Map for input. */ -} PPPControlRx; - -/* - * PPP interface control block. - */ -typedef struct PPPControl_s { - PPPControlRx rx; - char openFlag; /* True when in use. */ -#if PPPOE_SUPPORT - struct netif *ethif; - struct pppoe_softc *pppoe_sc; -#endif /* PPPOE_SUPPORT */ - int if_up; /* True when the interface is up. */ - int errCode; /* Code indicating why interface is down. */ -#if PPPOS_SUPPORT - sio_fd_t fd; /* File device ID of port. */ -#endif /* PPPOS_SUPPORT */ - u16_t mtu; /* Peer's mru */ - int pcomp; /* Does peer accept protocol compression? */ - int accomp; /* Does peer accept addr/ctl compression? */ - u_long lastXMit; /* Time of last transmission. */ - ext_accm outACCM; /* Async-Ctl-Char-Map for output. */ -#if PPPOS_SUPPORT && VJ_SUPPORT - int vjEnabled; /* Flag indicating VJ compression enabled. */ - struct vjcompress vjComp; /* Van Jacobson compression header. */ -#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ - - struct netif netif; - - struct ppp_addrs addrs; - - void (*linkStatusCB)(void *ctx, int errCode, void *arg); - void *linkStatusCtx; - -} PPPControl; - - -/* - * Ioctl definitions. - */ - -struct npioctl { - int protocol; /* PPP procotol, e.g. PPP_IP */ - enum NPmode mode; -}; - - - -/***********************************/ -/*** LOCAL FUNCTION DECLARATIONS ***/ -/***********************************/ -#if PPPOS_SUPPORT -#if PPP_INPROC_OWNTHREAD -static void pppInputThread(void *arg); -#endif /* PPP_INPROC_OWNTHREAD */ -static void pppDrop(PPPControlRx *pcrx); -static void pppInProc(PPPControlRx *pcrx, u_char *s, int l); -static void pppFreeCurrentInputPacket(PPPControlRx *pcrx); -#endif /* PPPOS_SUPPORT */ - - -/******************************/ -/*** PUBLIC DATA STRUCTURES ***/ -/******************************/ -static PPPControl pppControl[NUM_PPP]; /* The PPP interface control blocks. */ - -/* - * PPP Data Link Layer "protocol" table. - * One entry per supported protocol. - * The last entry must be NULL. - */ -struct protent *ppp_protocols[] = { - &lcp_protent, -#if PAP_SUPPORT - &pap_protent, -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - &chap_protent, -#endif /* CHAP_SUPPORT */ -#if CBCP_SUPPORT - &cbcp_protent, -#endif /* CBCP_SUPPORT */ - &ipcp_protent, -#if CCP_SUPPORT - &ccp_protent, -#endif /* CCP_SUPPORT */ - NULL -}; - - -/* - * Buffers for outgoing packets. This must be accessed only from the appropriate - * PPP task so that it doesn't need to be protected to avoid collisions. - */ -u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN]; - - -/*****************************/ -/*** LOCAL DATA STRUCTURES ***/ -/*****************************/ - -#if PPPOS_SUPPORT -/* - * FCS lookup table as calculated by genfcstab. - * @todo: smaller, slower implementation for lower memory footprint? - */ -static const u_short fcstab[256] = { - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -}; - -/* PPP's Asynchronous-Control-Character-Map. The mask array is used - * to select the specific bit for a character. */ -static u_char pppACCMMask[] = { - 0x01, - 0x02, - 0x04, - 0x08, - 0x10, - 0x20, - 0x40, - 0x80 -}; - -#if PPP_INPROC_OWNTHREAD -/** Wake up the task blocked in reading from serial line (if any) */ -static void -pppRecvWakeup(int pd) -{ - PPPDEBUG(LOG_DEBUG, ("pppRecvWakeup: unit %d\n", pd)); - if (pppControl[pd].openFlag != 0) { - sio_read_abort(pppControl[pd].fd); - } -} -#endif /* PPP_INPROC_OWNTHREAD */ -#endif /* PPPOS_SUPPORT */ - -void -pppLinkTerminated(int pd) -{ - PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d\n", pd)); - -#if PPPOE_SUPPORT - if (pppControl[pd].ethif) { - pppoe_disconnect(pppControl[pd].pppoe_sc); - } else -#endif /* PPPOE_SUPPORT */ - { -#if PPPOS_SUPPORT - PPPControl* pc; -#if PPP_INPROC_OWNTHREAD - pppRecvWakeup(pd); -#endif /* PPP_INPROC_OWNTHREAD */ - pc = &pppControl[pd]; - - PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); - if (pc->linkStatusCB) { - pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL); - } - - pc->openFlag = 0;/**/ -#endif /* PPPOS_SUPPORT */ - } - PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: finished.\n")); -} - -void -pppLinkDown(int pd) -{ - PPPDEBUG(LOG_DEBUG, ("pppLinkDown: unit %d\n", pd)); - -#if PPPOE_SUPPORT - if (pppControl[pd].ethif) { - pppoe_disconnect(pppControl[pd].pppoe_sc); - } else -#endif /* PPPOE_SUPPORT */ - { -#if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD - pppRecvWakeup(pd); -#endif /* PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD*/ - } -} - -/** Initiate LCP open request */ -static void -pppStart(int pd) -{ - PPPDEBUG(LOG_DEBUG, ("pppStart: unit %d\n", pd)); - lcp_lowerup(pd); - lcp_open(pd); /* Start protocol */ - PPPDEBUG(LOG_DEBUG, ("pppStart: finished\n")); -} - -/** LCP close request */ -static void -pppStop(int pd) -{ - PPPDEBUG(LOG_DEBUG, ("pppStop: unit %d\n", pd)); - lcp_close(pd, "User request"); -} - -/** Called when carrier/link is lost */ -static void -pppHup(int pd) -{ - PPPDEBUG(LOG_DEBUG, ("pppHupCB: unit %d\n", pd)); - lcp_lowerdown(pd); - link_terminated(pd); -} - -/***********************************/ -/*** PUBLIC FUNCTION DEFINITIONS ***/ -/***********************************/ -/* Initialize the PPP subsystem. */ - -struct ppp_settings ppp_settings; - -void -pppInit(void) -{ - struct protent *protp; - int i, j; - - memset(&ppp_settings, 0, sizeof(ppp_settings)); - ppp_settings.usepeerdns = 1; - pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL); - - magicInit(); - - for (i = 0; i < NUM_PPP; i++) { - /* Initialize each protocol to the standard option set. */ - for (j = 0; (protp = ppp_protocols[j]) != NULL; ++j) { - (*protp->init)(i); - } - } -} - -void -pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd) -{ - switch(authType) { - case PPPAUTHTYPE_NONE: - default: -#ifdef LWIP_PPP_STRICT_PAP_REJECT - ppp_settings.refuse_pap = 1; -#else /* LWIP_PPP_STRICT_PAP_REJECT */ - /* some providers request pap and accept an empty login/pw */ - ppp_settings.refuse_pap = 0; -#endif /* LWIP_PPP_STRICT_PAP_REJECT */ - ppp_settings.refuse_chap = 1; - break; - - case PPPAUTHTYPE_ANY: - /* Warning: Using PPPAUTHTYPE_ANY might have security consequences. - * RFC 1994 says: - * - * In practice, within or associated with each PPP server, there is a - * database which associates "user" names with authentication - * information ("secrets"). It is not anticipated that a particular - * named user would be authenticated by multiple methods. This would - * make the user vulnerable to attacks which negotiate the least secure - * method from among a set (such as PAP rather than CHAP). If the same - * secret was used, PAP would reveal the secret to be used later with - * CHAP. - * - * Instead, for each user name there should be an indication of exactly - * one method used to authenticate that user name. If a user needs to - * make use of different authentication methods under different - * circumstances, then distinct user names SHOULD be employed, each of - * which identifies exactly one authentication method. - * - */ - ppp_settings.refuse_pap = 0; - ppp_settings.refuse_chap = 0; - break; - - case PPPAUTHTYPE_PAP: - ppp_settings.refuse_pap = 0; - ppp_settings.refuse_chap = 1; - break; - - case PPPAUTHTYPE_CHAP: - ppp_settings.refuse_pap = 1; - ppp_settings.refuse_chap = 0; - break; - } - - if(user) { - strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1); - ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0'; - } else { - ppp_settings.user[0] = '\0'; - } - - if(passwd) { - strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1); - ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0'; - } else { - ppp_settings.passwd[0] = '\0'; - } -} - -#if PPPOS_SUPPORT -/** Open a new PPP connection using the given I/O device. - * This initializes the PPP control block but does not - * attempt to negotiate the LCP session. If this port - * connects to a modem, the modem connection must be - * established before calling this. - * Return a new PPP connection descriptor on success or - * an error code (negative) on failure. - * - * pppOpen() is directly defined to this function. - */ -int -pppOverSerialOpen(sio_fd_t fd, pppLinkStatusCB_fn linkStatusCB, void *linkStatusCtx) -{ - PPPControl *pc; - int pd; - - if (linkStatusCB == NULL) { - /* PPP is single-threaded: without a callback, - * there is no way to know when the link is up. */ - return PPPERR_PARAM; - } - - /* Find a free PPP session descriptor. */ - for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); - - if (pd >= NUM_PPP) { - pd = PPPERR_OPEN; - } else { - pc = &pppControl[pd]; - /* input pbuf left over from last session? */ - pppFreeCurrentInputPacket(&pc->rx); - /* @todo: is this correct or do I overwrite something? */ - memset(pc, 0, sizeof(PPPControl)); - pc->rx.pd = pd; - pc->rx.fd = fd; - - pc->openFlag = 1; - pc->fd = fd; - -#if VJ_SUPPORT - vj_compress_init(&pc->vjComp); -#endif /* VJ_SUPPORT */ - - /* - * Default the in and out accm so that escape and flag characters - * are always escaped. - */ - pc->rx.inACCM[15] = 0x60; /* no need to protect since RX is not running */ - pc->outACCM[15] = 0x60; - - pc->linkStatusCB = linkStatusCB; - pc->linkStatusCtx = linkStatusCtx; - - /* - * Start the connection and handle incoming events (packet or timeout). - */ - PPPDEBUG(LOG_INFO, ("pppOverSerialOpen: unit %d: Connecting\n", pd)); - pppStart(pd); -#if PPP_INPROC_OWNTHREAD - sys_thread_new(PPP_THREAD_NAME, pppInputThread, (void*)&pc->rx, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO); -#endif /* PPP_INPROC_OWNTHREAD */ - } - - return pd; -} -#endif /* PPPOS_SUPPORT */ - -#if PPPOE_SUPPORT -static void pppOverEthernetLinkStatusCB(int pd, int up); - -void -pppOverEthernetClose(int pd) -{ - PPPControl* pc = &pppControl[pd]; - - /* *TJL* There's no lcp_deinit */ - lcp_close(pd, NULL); - - pppoe_destroy(&pc->netif); -} - -int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, - pppLinkStatusCB_fn linkStatusCB, void *linkStatusCtx) -{ - PPPControl *pc; - int pd; - - LWIP_UNUSED_ARG(service_name); - LWIP_UNUSED_ARG(concentrator_name); - - if (linkStatusCB == NULL) { - /* PPP is single-threaded: without a callback, - * there is no way to know when the link is up. */ - return PPPERR_PARAM; - } - - /* Find a free PPP session descriptor. Critical region? */ - for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); - if (pd >= NUM_PPP) { - pd = PPPERR_OPEN; - } else { - pc = &pppControl[pd]; - memset(pc, 0, sizeof(PPPControl)); - pc->openFlag = 1; - pc->ethif = ethif; - - pc->linkStatusCB = linkStatusCB; - pc->linkStatusCtx = linkStatusCtx; - - lcp_wantoptions[pd].mru = PPPOE_MAXMTU; - lcp_wantoptions[pd].neg_asyncmap = 0; - lcp_wantoptions[pd].neg_pcompression = 0; - lcp_wantoptions[pd].neg_accompression = 0; - - lcp_allowoptions[pd].mru = PPPOE_MAXMTU; - lcp_allowoptions[pd].neg_asyncmap = 0; - lcp_allowoptions[pd].neg_pcompression = 0; - lcp_allowoptions[pd].neg_accompression = 0; - - if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) { - pc->openFlag = 0; - return PPPERR_OPEN; - } - - pppoe_connect(pc->pppoe_sc); - } - - return pd; -} -#endif /* PPPOE_SUPPORT */ - - -/* Close a PPP connection and release the descriptor. - * Any outstanding packets in the queues are dropped. - * Return 0 on success, an error code on failure. */ -int -pppClose(int pd) -{ - PPPControl *pc = &pppControl[pd]; - int st = 0; - - PPPDEBUG(LOG_DEBUG, ("pppClose() called\n")); - - /* Disconnect */ -#if PPPOE_SUPPORT - if(pc->ethif) { - PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd)); - pc->errCode = PPPERR_USER; - /* This will leave us at PHASE_DEAD. */ - pppStop(pd); - } else -#endif /* PPPOE_SUPPORT */ - { -#if PPPOS_SUPPORT - PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd)); - pc->errCode = PPPERR_USER; - /* This will leave us at PHASE_DEAD. */ - pppStop(pd); -#if PPP_INPROC_OWNTHREAD - pppRecvWakeup(pd); -#endif /* PPP_INPROC_OWNTHREAD */ -#endif /* PPPOS_SUPPORT */ - } - - return st; -} - -/* This function is called when carrier is lost on the PPP channel. */ -void -pppSigHUP(int pd) -{ - PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd)); - pppHup(pd); -} - -#if PPPOS_SUPPORT -static void -nPut(PPPControl *pc, struct pbuf *nb) -{ - struct pbuf *b; - int c; - - for(b = nb; b != NULL; b = b->next) { - if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) { - PPPDEBUG(LOG_WARNING, - ("PPP nPut: incomplete sio_write(fd:%"SZT_F", len:%d, c: 0x%"X8_F") c = %d\n", (size_t)pc->fd, b->len, c, c)); - LINK_STATS_INC(link.err); - pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */ - snmp_inc_ifoutdiscards(&pc->netif); - pbuf_free(nb); - return; - } - } - - snmp_add_ifoutoctets(&pc->netif, nb->tot_len); - snmp_inc_ifoutucastpkts(&pc->netif); - pbuf_free(nb); - LINK_STATS_INC(link.xmit); -} - -/* - * pppAppend - append given character to end of given pbuf. If outACCM - * is not NULL and the character needs to be escaped, do so. - * If pbuf is full, append another. - * Return the current pbuf. - */ -static struct pbuf * -pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM) -{ - struct pbuf *tb = nb; - - /* Make sure there is room for the character and an escape code. - * Sure we don't quite fill the buffer if the character doesn't - * get escaped but is one character worth complicating this? */ - /* Note: We assume no packet header. */ - if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) { - tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); - if (tb) { - nb->next = tb; - } else { - LINK_STATS_INC(link.memerr); - } - nb = tb; - } - - if (nb) { - if (outACCM && ESCAPE_P(*outACCM, c)) { - *((u_char*)nb->payload + nb->len++) = PPP_ESCAPE; - *((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS; - } else { - *((u_char*)nb->payload + nb->len++) = c; - } - } - - return tb; -} -#endif /* PPPOS_SUPPORT */ - -#if PPPOE_SUPPORT -static err_t -pppifOutputOverEthernet(int pd, struct pbuf *p) -{ - PPPControl *pc = &pppControl[pd]; - struct pbuf *pb; - u_short protocol = PPP_IP; - int i=0; - u16_t tot_len; - - /* @todo: try to use pbuf_header() here! */ - pb = pbuf_alloc(PBUF_LINK, PPPOE_HDRLEN + sizeof(protocol), PBUF_RAM); - if(!pb) { - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.proterr); - snmp_inc_ifoutdiscards(&pc->netif); - return ERR_MEM; - } - - pbuf_header(pb, -(s16_t)PPPOE_HDRLEN); - - pc->lastXMit = sys_jiffies(); - - if (!pc->pcomp || protocol > 0xFF) { - *((u_char*)pb->payload + i++) = (protocol >> 8) & 0xFF; - } - *((u_char*)pb->payload + i) = protocol & 0xFF; - - pbuf_chain(pb, p); - tot_len = pb->tot_len; - - if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { - LINK_STATS_INC(link.err); - snmp_inc_ifoutdiscards(&pc->netif); - return PPPERR_DEVICE; - } - - snmp_add_ifoutoctets(&pc->netif, tot_len); - snmp_inc_ifoutucastpkts(&pc->netif); - LINK_STATS_INC(link.xmit); - return ERR_OK; -} -#endif /* PPPOE_SUPPORT */ - -/* Send a packet on the given connection. */ -static err_t -pppifOutput(struct netif *netif, struct pbuf *pb, ip_addr_t *ipaddr) -{ - int pd = (int)(size_t)netif->state; - PPPControl *pc = &pppControl[pd]; -#if PPPOS_SUPPORT - u_short protocol = PPP_IP; - u_int fcsOut = PPP_INITFCS; - struct pbuf *headMB = NULL, *tailMB = NULL, *p; - u_char c; -#endif /* PPPOS_SUPPORT */ - - LWIP_UNUSED_ARG(ipaddr); - - /* Validate parameters. */ - /* We let any protocol value go through - it can't hurt us - * and the peer will just drop it if it's not accepting it. */ - if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) { - PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad parms prot=%d pb=%p\n", - pd, PPP_IP, pb)); - LINK_STATS_INC(link.opterr); - LINK_STATS_INC(link.drop); - snmp_inc_ifoutdiscards(netif); - return ERR_ARG; - } - - /* Check that the link is up. */ - if (lcp_phase[pd] == PHASE_DEAD) { - PPPDEBUG(LOG_ERR, ("pppifOutput[%d]: link not up\n", pd)); - LINK_STATS_INC(link.rterr); - LINK_STATS_INC(link.drop); - snmp_inc_ifoutdiscards(netif); - return ERR_RTE; - } - -#if PPPOE_SUPPORT - if(pc->ethif) { - return pppifOutputOverEthernet(pd, pb); - } -#endif /* PPPOE_SUPPORT */ - -#if PPPOS_SUPPORT - /* Grab an output buffer. */ - headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); - if (headMB == NULL) { - PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: first alloc fail\n", pd)); - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - snmp_inc_ifoutdiscards(netif); - return ERR_MEM; - } - -#if VJ_SUPPORT - /* - * Attempt Van Jacobson header compression if VJ is configured and - * this is an IP packet. - */ - if (protocol == PPP_IP && pc->vjEnabled) { - switch (vj_compress_tcp(&pc->vjComp, pb)) { - case TYPE_IP: - /* No change... - protocol = PPP_IP_PROTOCOL; */ - break; - case TYPE_COMPRESSED_TCP: - protocol = PPP_VJC_COMP; - break; - case TYPE_UNCOMPRESSED_TCP: - protocol = PPP_VJC_UNCOMP; - break; - default: - PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad IP packet\n", pd)); - LINK_STATS_INC(link.proterr); - LINK_STATS_INC(link.drop); - snmp_inc_ifoutdiscards(netif); - pbuf_free(headMB); - return ERR_VAL; - } - } -#endif /* VJ_SUPPORT */ - - tailMB = headMB; - - /* Build the PPP header. */ - if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) { - tailMB = pppAppend(PPP_FLAG, tailMB, NULL); - } - - pc->lastXMit = sys_jiffies(); - if (!pc->accomp) { - fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS); - tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM); - fcsOut = PPP_FCS(fcsOut, PPP_UI); - tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM); - } - if (!pc->pcomp || protocol > 0xFF) { - c = (protocol >> 8) & 0xFF; - fcsOut = PPP_FCS(fcsOut, c); - tailMB = pppAppend(c, tailMB, &pc->outACCM); - } - c = protocol & 0xFF; - fcsOut = PPP_FCS(fcsOut, c); - tailMB = pppAppend(c, tailMB, &pc->outACCM); - - /* Load packet. */ - for(p = pb; p; p = p->next) { - int n; - u_char *sPtr; - - sPtr = (u_char*)p->payload; - n = p->len; - while (n-- > 0) { - c = *sPtr++; - - /* Update FCS before checking for special characters. */ - fcsOut = PPP_FCS(fcsOut, c); - - /* Copy to output buffer escaping special characters. */ - tailMB = pppAppend(c, tailMB, &pc->outACCM); - } - } - - /* Add FCS and trailing flag. */ - c = ~fcsOut & 0xFF; - tailMB = pppAppend(c, tailMB, &pc->outACCM); - c = (~fcsOut >> 8) & 0xFF; - tailMB = pppAppend(c, tailMB, &pc->outACCM); - tailMB = pppAppend(PPP_FLAG, tailMB, NULL); - - /* If we failed to complete the packet, throw it away. */ - if (!tailMB) { - PPPDEBUG(LOG_WARNING, - ("pppifOutput[%d]: Alloc err - dropping proto=%d\n", - pd, protocol)); - pbuf_free(headMB); - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - snmp_inc_ifoutdiscards(netif); - return ERR_MEM; - } - - /* Send it. */ - PPPDEBUG(LOG_INFO, ("pppifOutput[%d]: proto=0x%"X16_F"\n", pd, protocol)); - - nPut(pc, headMB); -#endif /* PPPOS_SUPPORT */ - - return ERR_OK; -} - -/* Get and set parameters for the given connection. - * Return 0 on success, an error code on failure. */ -int -pppIOCtl(int pd, int cmd, void *arg) -{ - PPPControl *pc = &pppControl[pd]; - int st = 0; - - if (pd < 0 || pd >= NUM_PPP) { - st = PPPERR_PARAM; - } else { - switch(cmd) { - case PPPCTLG_UPSTATUS: /* Get the PPP up status. */ - if (arg) { - *(int *)arg = (int)(pc->if_up); - } else { - st = PPPERR_PARAM; - } - break; - case PPPCTLS_ERRCODE: /* Set the PPP error code. */ - if (arg) { - pc->errCode = *(int *)arg; - } else { - st = PPPERR_PARAM; - } - break; - case PPPCTLG_ERRCODE: /* Get the PPP error code. */ - if (arg) { - *(int *)arg = (int)(pc->errCode); - } else { - st = PPPERR_PARAM; - } - break; -#if PPPOS_SUPPORT - case PPPCTLG_FD: /* Get the fd associated with the ppp */ - if (arg) { - *(sio_fd_t *)arg = pc->fd; - } else { - st = PPPERR_PARAM; - } - break; -#endif /* PPPOS_SUPPORT */ - default: - st = PPPERR_PARAM; - break; - } - } - - return st; -} - -/* - * Return the Maximum Transmission Unit for the given PPP connection. - */ -u_short -pppMTU(int pd) -{ - PPPControl *pc = &pppControl[pd]; - u_short st; - - /* Validate parameters. */ - if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { - st = 0; - } else { - st = pc->mtu; - } - - return st; -} - -#if PPPOE_SUPPORT -int -pppWriteOverEthernet(int pd, const u_char *s, int n) -{ - PPPControl *pc = &pppControl[pd]; - struct pbuf *pb; - - /* skip address & flags */ - s += 2; - n -= 2; - - LWIP_ASSERT("PPPOE_HDRLEN + n <= 0xffff", PPPOE_HDRLEN + n <= 0xffff); - pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HDRLEN + n), PBUF_RAM); - if(!pb) { - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.proterr); - snmp_inc_ifoutdiscards(&pc->netif); - return PPPERR_ALLOC; - } - - pbuf_header(pb, -(s16_t)PPPOE_HDRLEN); - - pc->lastXMit = sys_jiffies(); - - MEMCPY(pb->payload, s, n); - - if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { - LINK_STATS_INC(link.err); - snmp_inc_ifoutdiscards(&pc->netif); - return PPPERR_DEVICE; - } - - snmp_add_ifoutoctets(&pc->netif, (u16_t)n); - snmp_inc_ifoutucastpkts(&pc->netif); - LINK_STATS_INC(link.xmit); - return PPPERR_NONE; -} -#endif /* PPPOE_SUPPORT */ - -/* - * Write n characters to a ppp link. - * RETURN: >= 0 Number of characters written - * -1 Failed to write to device - */ -int -pppWrite(int pd, const u_char *s, int n) -{ - PPPControl *pc = &pppControl[pd]; -#if PPPOS_SUPPORT - u_char c; - u_int fcsOut; - struct pbuf *headMB, *tailMB; -#endif /* PPPOS_SUPPORT */ - -#if PPPOE_SUPPORT - if(pc->ethif) { - return pppWriteOverEthernet(pd, s, n); - } -#endif /* PPPOE_SUPPORT */ - -#if PPPOS_SUPPORT - headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); - if (headMB == NULL) { - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.proterr); - snmp_inc_ifoutdiscards(&pc->netif); - return PPPERR_ALLOC; - } - - tailMB = headMB; - - /* If the link has been idle, we'll send a fresh flag character to - * flush any noise. */ - if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) { - tailMB = pppAppend(PPP_FLAG, tailMB, NULL); - } - pc->lastXMit = sys_jiffies(); - - fcsOut = PPP_INITFCS; - /* Load output buffer. */ - while (n-- > 0) { - c = *s++; - - /* Update FCS before checking for special characters. */ - fcsOut = PPP_FCS(fcsOut, c); - - /* Copy to output buffer escaping special characters. */ - tailMB = pppAppend(c, tailMB, &pc->outACCM); - } - - /* Add FCS and trailing flag. */ - c = ~fcsOut & 0xFF; - tailMB = pppAppend(c, tailMB, &pc->outACCM); - c = (~fcsOut >> 8) & 0xFF; - tailMB = pppAppend(c, tailMB, &pc->outACCM); - tailMB = pppAppend(PPP_FLAG, tailMB, NULL); - - /* If we failed to complete the packet, throw it away. - * Otherwise send it. */ - if (!tailMB) { - PPPDEBUG(LOG_WARNING, - ("pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len)); - /*"pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */ - pbuf_free(headMB); - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.proterr); - snmp_inc_ifoutdiscards(&pc->netif); - return PPPERR_ALLOC; - } - - PPPDEBUG(LOG_INFO, ("pppWrite[%d]: len=%d\n", pd, headMB->len)); - /* "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */ - nPut(pc, headMB); -#endif /* PPPOS_SUPPORT */ - - return PPPERR_NONE; -} - -/* - * ppp_send_config - configure the transmit characteristics of - * the ppp interface. - */ -void -ppp_send_config( int unit, u16_t mtu, u32_t asyncmap, int pcomp, int accomp) -{ - PPPControl *pc = &pppControl[unit]; - int i; - - pc->mtu = mtu; - pc->pcomp = pcomp; - pc->accomp = accomp; - - /* Load the ACCM bits for the 32 control codes. */ - for (i = 0; i < 32/8; i++) { - pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF); - } - PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]: outACCM=%X %X %X %X\n", - unit, - pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3])); -} - - -/* - * ppp_set_xaccm - set the extended transmit ACCM for the interface. - */ -void -ppp_set_xaccm(int unit, ext_accm *accm) -{ - SMEMCPY(pppControl[unit].outACCM, accm, sizeof(ext_accm)); - PPPDEBUG(LOG_INFO, ("ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n", - unit, - pppControl[unit].outACCM[0], - pppControl[unit].outACCM[1], - pppControl[unit].outACCM[2], - pppControl[unit].outACCM[3])); -} - - -/* - * ppp_recv_config - configure the receive-side characteristics of - * the ppp interface. - */ -void -ppp_recv_config( int unit, int mru, u32_t asyncmap, int pcomp, int accomp) -{ - PPPControl *pc = &pppControl[unit]; - int i; - SYS_ARCH_DECL_PROTECT(lev); - - LWIP_UNUSED_ARG(accomp); - LWIP_UNUSED_ARG(pcomp); - LWIP_UNUSED_ARG(mru); - - /* Load the ACCM bits for the 32 control codes. */ - SYS_ARCH_PROTECT(lev); - for (i = 0; i < 32 / 8; i++) { - /* @todo: does this work? ext_accm has been modified from pppd! */ - pc->rx.inACCM[i] = (u_char)(asyncmap >> (i * 8)); - } - SYS_ARCH_UNPROTECT(lev); - PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]: inACCM=%X %X %X %X\n", - unit, - pc->rx.inACCM[0], pc->rx.inACCM[1], pc->rx.inACCM[2], pc->rx.inACCM[3])); -} - -#if 0 -/* - * ccp_test - ask kernel whether a given compression method - * is acceptable for use. Returns 1 if the method and parameters - * are OK, 0 if the method is known but the parameters are not OK - * (e.g. code size should be reduced), or -1 if the method is unknown. - */ -int -ccp_test( int unit, int opt_len, int for_transmit, u_char *opt_ptr) -{ - return 0; /* XXX Currently no compression. */ -} - -/* - * ccp_flags_set - inform kernel about the current state of CCP. - */ -void -ccp_flags_set(int unit, int isopen, int isup) -{ - /* XXX */ -} - -/* - * ccp_fatal_error - returns 1 if decompression was disabled as a - * result of an error detected after decompression of a packet, - * 0 otherwise. This is necessary because of patent nonsense. - */ -int -ccp_fatal_error(int unit) -{ - /* XXX */ - return 0; -} -#endif - -/* - * get_idle_time - return how long the link has been idle. - */ -int -get_idle_time(int u, struct ppp_idle *ip) -{ - /* XXX */ - LWIP_UNUSED_ARG(u); - LWIP_UNUSED_ARG(ip); - - return 0; -} - - -/* - * Return user specified netmask, modified by any mask we might determine - * for address `addr' (in network byte order). - * Here we scan through the system's list of interfaces, looking for - * any non-point-to-point interfaces which might appear to be on the same - * network as `addr'. If we find any, we OR in their netmask to the - * user-specified netmask. - */ -u32_t -GetMask(u32_t addr) -{ - u32_t mask, nmask; - - addr = htonl(addr); - if (IP_CLASSA(addr)) { /* determine network mask for address class */ - nmask = IP_CLASSA_NET; - } else if (IP_CLASSB(addr)) { - nmask = IP_CLASSB_NET; - } else { - nmask = IP_CLASSC_NET; - } - - /* class D nets are disallowed by bad_ip_adrs */ - mask = PP_HTONL(0xffffff00UL) | htonl(nmask); - - /* XXX - * Scan through the system's network interfaces. - * Get each netmask and OR them into our mask. - */ - - return mask; -} - -/* - * sifvjcomp - config tcp header compression - */ -int -sifvjcomp(int pd, int vjcomp, u8_t cidcomp, u8_t maxcid) -{ -#if PPPOS_SUPPORT && VJ_SUPPORT - PPPControl *pc = &pppControl[pd]; - - pc->vjEnabled = vjcomp; - pc->vjComp.compressSlot = cidcomp; - pc->vjComp.maxSlotIndex = maxcid; - PPPDEBUG(LOG_INFO, ("sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n", - vjcomp, cidcomp, maxcid)); -#else /* PPPOS_SUPPORT && VJ_SUPPORT */ - LWIP_UNUSED_ARG(pd); - LWIP_UNUSED_ARG(vjcomp); - LWIP_UNUSED_ARG(cidcomp); - LWIP_UNUSED_ARG(maxcid); -#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ - - return 0; -} - -/* - * pppifNetifInit - netif init callback - */ -static err_t -pppifNetifInit(struct netif *netif) -{ - netif->name[0] = 'p'; - netif->name[1] = 'p'; - netif->output = pppifOutput; - netif->mtu = pppMTU((int)(size_t)netif->state); - netif->flags = NETIF_FLAG_POINTTOPOINT | NETIF_FLAG_LINK_UP; -#if LWIP_NETIF_HOSTNAME - /* @todo: Initialize interface hostname */ - /* netif_set_hostname(netif, "lwip"); */ -#endif /* LWIP_NETIF_HOSTNAME */ - return ERR_OK; -} - - -/* - * sifup - Config the interface up and enable IP packets to pass. - */ -int -sifup(int pd) -{ - PPPControl *pc = &pppControl[pd]; - int st = 1; - - if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { - st = 0; - PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); - } else { - netif_remove(&pc->netif); - if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, - &pc->addrs.his_ipaddr, (void *)(size_t)pd, pppifNetifInit, ip_input)) { - netif_set_up(&pc->netif); - pc->if_up = 1; - pc->errCode = PPPERR_NONE; - - PPPDEBUG(LOG_DEBUG, ("sifup: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); - if (pc->linkStatusCB) { - pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs); - } - } else { - st = 0; - PPPDEBUG(LOG_ERR, ("sifup[%d]: netif_add failed\n", pd)); - } - } - - return st; -} - -/* - * sifnpmode - Set the mode for handling packets for a given NP. - */ -int -sifnpmode(int u, int proto, enum NPmode mode) -{ - LWIP_UNUSED_ARG(u); - LWIP_UNUSED_ARG(proto); - LWIP_UNUSED_ARG(mode); - return 0; -} - -/* - * sifdown - Config the interface down and disable IP. - */ -int -sifdown(int pd) -{ - PPPControl *pc = &pppControl[pd]; - int st = 1; - - if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { - st = 0; - PPPDEBUG(LOG_WARNING, ("sifdown[%d]: bad parms\n", pd)); - } else { - pc->if_up = 0; - /* make sure the netif status callback is called */ - netif_set_down(&pc->netif); - netif_remove(&pc->netif); - PPPDEBUG(LOG_DEBUG, ("sifdown: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); - if (pc->linkStatusCB) { - pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL); - } - } - return st; -} - -/** - * sifaddr - Config the interface IP addresses and netmask. - * @param pd Interface unit ??? - * @param o Our IP address ??? - * @param h His IP address ??? - * @param m IP subnet mask ??? - * @param ns1 Primary DNS - * @param ns2 Secondary DNS - */ -int -sifaddr( int pd, u32_t o, u32_t h, u32_t m, u32_t ns1, u32_t ns2) -{ - PPPControl *pc = &pppControl[pd]; - int st = 1; - - if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { - st = 0; - PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); - } else { - SMEMCPY(&pc->addrs.our_ipaddr, &o, sizeof(o)); - SMEMCPY(&pc->addrs.his_ipaddr, &h, sizeof(h)); - SMEMCPY(&pc->addrs.netmask, &m, sizeof(m)); - SMEMCPY(&pc->addrs.dns1, &ns1, sizeof(ns1)); - SMEMCPY(&pc->addrs.dns2, &ns2, sizeof(ns2)); - } - return st; -} - -/** - * cifaddr - Clear the interface IP addresses, and delete routes - * through the interface if possible. - * @param pd Interface unit ??? - * @param o Our IP address ??? - * @param h IP broadcast address ??? - */ -int -cifaddr( int pd, u32_t o, u32_t h) -{ - PPPControl *pc = &pppControl[pd]; - int st = 1; - - LWIP_UNUSED_ARG(o); - LWIP_UNUSED_ARG(h); - if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { - st = 0; - PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); - } else { - IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0); - IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0); - IP4_ADDR(&pc->addrs.netmask, 255,255,255,0); - IP4_ADDR(&pc->addrs.dns1, 0,0,0,0); - IP4_ADDR(&pc->addrs.dns2, 0,0,0,0); - } - return st; -} - -/* - * sifdefaultroute - assign a default route through the address given. - */ -int -sifdefaultroute(int pd, u32_t l, u32_t g) -{ - PPPControl *pc = &pppControl[pd]; - int st = 1; - - LWIP_UNUSED_ARG(l); - LWIP_UNUSED_ARG(g); - - if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { - st = 0; - PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); - } else { - netif_set_default(&pc->netif); - } - - /* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */ - - return st; -} - -/* - * cifdefaultroute - delete a default route through the address given. - */ -int -cifdefaultroute(int pd, u32_t l, u32_t g) -{ - PPPControl *pc = &pppControl[pd]; - int st = 1; - - LWIP_UNUSED_ARG(l); - LWIP_UNUSED_ARG(g); - - if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { - st = 0; - PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); - } else { - netif_set_default(NULL); - } - - return st; -} - -/**********************************/ -/*** LOCAL FUNCTION DEFINITIONS ***/ -/**********************************/ - -#if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD -/* The main PPP process function. This implements the state machine according - * to section 4 of RFC 1661: The Point-To-Point Protocol. */ -static void -pppInputThread(void *arg) -{ - int count; - PPPControlRx *pcrx = arg; - - while (lcp_phase[pcrx->pd] != PHASE_DEAD) { - count = sio_read(pcrx->fd, pcrx->rxbuf, PPPOS_RX_BUFSIZE); - if(count > 0) { - pppInProc(pcrx, pcrx->rxbuf, count); - } else { - /* nothing received, give other tasks a chance to run */ - sys_msleep(1); - } - } -} -#endif /* PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD */ - -#if PPPOE_SUPPORT - -void -pppOverEthernetInitFailed(int pd) -{ - PPPControl* pc; - - pppHup(pd); - pppStop(pd); - - pc = &pppControl[pd]; - pppoe_destroy(&pc->netif); - pc->openFlag = 0; - - if(pc->linkStatusCB) { - pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL); - } -} - -static void -pppOverEthernetLinkStatusCB(int pd, int up) -{ - if(up) { - PPPDEBUG(LOG_INFO, ("pppOverEthernetLinkStatusCB: unit %d: Connecting\n", pd)); - pppStart(pd); - } else { - pppOverEthernetInitFailed(pd); - } -} -#endif /* PPPOE_SUPPORT */ - -struct pbuf * -pppSingleBuf(struct pbuf *p) -{ - struct pbuf *q, *b; - u_char *pl; - - if(p->tot_len == p->len) { - return p; - } - - q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); - if(!q) { - PPPDEBUG(LOG_ERR, - ("pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len)); - return p; /* live dangerously */ - } - - for(b = p, pl = q->payload; b != NULL; b = b->next) { - MEMCPY(pl, b->payload, b->len); - pl += b->len; - } - - pbuf_free(p); - - return q; -} - -/** Input helper struct, must be packed since it is stored to pbuf->payload, - * which might be unaligned. - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct pppInputHeader { - PACK_STRUCT_FIELD(int unit); - PACK_STRUCT_FIELD(u16_t proto); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* - * Pass the processed input packet to the appropriate handler. - * This function and all handlers run in the context of the tcpip_thread - */ -static void -pppInput(void *arg) -{ - struct pbuf *nb = (struct pbuf *)arg; - u16_t protocol; - int pd; - - pd = ((struct pppInputHeader *)nb->payload)->unit; - protocol = ((struct pppInputHeader *)nb->payload)->proto; - - if(pbuf_header(nb, -(int)sizeof(struct pppInputHeader))) { - LWIP_ASSERT("pbuf_header failed\n", 0); - goto drop; - } - - LINK_STATS_INC(link.recv); - snmp_inc_ifinucastpkts(&pppControl[pd].netif); - snmp_add_ifinoctets(&pppControl[pd].netif, nb->tot_len); - - /* - * Toss all non-LCP packets unless LCP is OPEN. - * Until we get past the authentication phase, toss all packets - * except LCP, LQR and authentication packets. - */ - if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) { - if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) || - (lcp_phase[pd] != PHASE_AUTHENTICATE)) { - PPPDEBUG(LOG_INFO, ("pppInput: discarding proto 0x%"X16_F" in phase %d\n", protocol, lcp_phase[pd])); - goto drop; - } - } - - switch(protocol) { - case PPP_VJC_COMP: /* VJ compressed TCP */ -#if PPPOS_SUPPORT && VJ_SUPPORT - PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len)); - /* - * Clip off the VJ header and prepend the rebuilt TCP/IP header and - * pass the result to IP. - */ - if ((vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) && (pppControl[pd].netif.input)) { - pppControl[pd].netif.input(nb, &pppControl[pd].netif); - return; - } - /* Something's wrong so drop it. */ - PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ compressed\n", pd)); -#else /* PPPOS_SUPPORT && VJ_SUPPORT */ - /* No handler for this protocol so drop the packet. */ - PPPDEBUG(LOG_INFO, ("pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload)); -#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ - break; - - case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ -#if PPPOS_SUPPORT && VJ_SUPPORT - PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len)); - /* - * Process the TCP/IP header for VJ header compression and then pass - * the packet to IP. - */ - if ((vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) && pppControl[pd].netif.input) { - pppControl[pd].netif.input(nb, &pppControl[pd].netif); - return; - } - /* Something's wrong so drop it. */ - PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ uncompressed\n", pd)); -#else /* PPPOS_SUPPORT && VJ_SUPPORT */ - /* No handler for this protocol so drop the packet. */ - PPPDEBUG(LOG_INFO, - ("pppInput[%d]: drop VJ UnComp in %d:.*H\n", - pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload)); -#endif /* PPPOS_SUPPORT && VJ_SUPPORT */ - break; - - case PPP_IP: /* Internet Protocol */ - PPPDEBUG(LOG_INFO, ("pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len)); - if (pppControl[pd].netif.input) { - pppControl[pd].netif.input(nb, &pppControl[pd].netif); - return; - } - break; - - default: { - struct protent *protp; - int i; - - /* - * Upcall the proper protocol input routine. - */ - for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { - if (protp->protocol == protocol && protp->enabled_flag) { - PPPDEBUG(LOG_INFO, ("pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len)); - nb = pppSingleBuf(nb); - (*protp->input)(pd, nb->payload, nb->len); - PPPDEBUG(LOG_DETAIL, ("pppInput[%d]: packet processed\n", pd)); - goto out; - } - } - - /* No handler for this protocol so reject the packet. */ - PPPDEBUG(LOG_INFO, ("pppInput[%d]: rejecting unsupported proto 0x%"X16_F" len=%d\n", pd, protocol, nb->len)); - if (pbuf_header(nb, sizeof(protocol))) { - LWIP_ASSERT("pbuf_header failed\n", 0); - goto drop; - } -#if BYTE_ORDER == LITTLE_ENDIAN - protocol = htons(protocol); -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - SMEMCPY(nb->payload, &protocol, sizeof(protocol)); - lcp_sprotrej(pd, nb->payload, nb->len); - } - break; - } - -drop: - LINK_STATS_INC(link.drop); - snmp_inc_ifindiscards(&pppControl[pd].netif); - -out: - pbuf_free(nb); - return; -} - -#if PPPOS_SUPPORT -/* - * Drop the input packet. - */ -static void -pppFreeCurrentInputPacket(PPPControlRx *pcrx) -{ - if (pcrx->inHead != NULL) { - if (pcrx->inTail && (pcrx->inTail != pcrx->inHead)) { - pbuf_free(pcrx->inTail); - } - pbuf_free(pcrx->inHead); - pcrx->inHead = NULL; - } - pcrx->inTail = NULL; -} - -/* - * Drop the input packet and increase error counters. - */ -static void -pppDrop(PPPControlRx *pcrx) -{ - if (pcrx->inHead != NULL) { -#if 0 - PPPDEBUG(LOG_INFO, ("pppDrop: %d:%.*H\n", pcrx->inHead->len, min(60, pcrx->inHead->len * 2), pcrx->inHead->payload)); -#endif - PPPDEBUG(LOG_INFO, ("pppDrop: pbuf len=%d, addr %p\n", pcrx->inHead->len, (void*)pcrx->inHead)); - } - pppFreeCurrentInputPacket(pcrx); -#if VJ_SUPPORT - vj_uncompress_err(&pppControl[pcrx->pd].vjComp); -#endif /* VJ_SUPPORT */ - - LINK_STATS_INC(link.drop); - snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif); -} - -#if !PPP_INPROC_OWNTHREAD -/** Pass received raw characters to PPPoS to be decoded. This function is - * thread-safe and can be called from a dedicated RX-thread or from a main-loop. - * - * @param pd PPP descriptor index, returned by pppOpen() - * @param data received data - * @param len length of received data - */ -void -pppos_input(int pd, u_char* data, int len) -{ - pppInProc(&pppControl[pd].rx, data, len); -} -#endif - -/** - * Process a received octet string. - */ -static void -pppInProc(PPPControlRx *pcrx, u_char *s, int l) -{ - struct pbuf *nextNBuf; - u_char curChar; - u_char escaped; - SYS_ARCH_DECL_PROTECT(lev); - - PPPDEBUG(LOG_DEBUG, ("pppInProc[%d]: got %d bytes\n", pcrx->pd, l)); - while (l-- > 0) { - curChar = *s++; - - SYS_ARCH_PROTECT(lev); - escaped = ESCAPE_P(pcrx->inACCM, curChar); - SYS_ARCH_UNPROTECT(lev); - /* Handle special characters. */ - if (escaped) { - /* Check for escape sequences. */ - /* XXX Note that this does not handle an escaped 0x5d character which - * would appear as an escape character. Since this is an ASCII ']' - * and there is no reason that I know of to escape it, I won't complicate - * the code to handle this case. GLL */ - if (curChar == PPP_ESCAPE) { - pcrx->inEscaped = 1; - /* Check for the flag character. */ - } else if (curChar == PPP_FLAG) { - /* If this is just an extra flag character, ignore it. */ - if (pcrx->inState <= PDADDRESS) { - /* ignore it */; - /* If we haven't received the packet header, drop what has come in. */ - } else if (pcrx->inState < PDDATA) { - PPPDEBUG(LOG_WARNING, - ("pppInProc[%d]: Dropping incomplete packet %d\n", - pcrx->pd, pcrx->inState)); - LINK_STATS_INC(link.lenerr); - pppDrop(pcrx); - /* If the fcs is invalid, drop the packet. */ - } else if (pcrx->inFCS != PPP_GOODFCS) { - PPPDEBUG(LOG_INFO, - ("pppInProc[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n", - pcrx->pd, pcrx->inFCS, pcrx->inProtocol)); - /* Note: If you get lots of these, check for UART frame errors or try different baud rate */ - LINK_STATS_INC(link.chkerr); - pppDrop(pcrx); - /* Otherwise it's a good packet so pass it on. */ - } else { - struct pbuf *inp; - /* Trim off the checksum. */ - if(pcrx->inTail->len > 2) { - pcrx->inTail->len -= 2; - - pcrx->inTail->tot_len = pcrx->inTail->len; - if (pcrx->inTail != pcrx->inHead) { - pbuf_cat(pcrx->inHead, pcrx->inTail); - } - } else { - pcrx->inTail->tot_len = pcrx->inTail->len; - if (pcrx->inTail != pcrx->inHead) { - pbuf_cat(pcrx->inHead, pcrx->inTail); - } - - pbuf_realloc(pcrx->inHead, pcrx->inHead->tot_len - 2); - } - - /* Dispatch the packet thereby consuming it. */ - inp = pcrx->inHead; - /* Packet consumed, release our references. */ - pcrx->inHead = NULL; - pcrx->inTail = NULL; -#if PPP_INPROC_MULTITHREADED - if(tcpip_callback_with_block(pppInput, inp, 0) != ERR_OK) { - PPPDEBUG(LOG_ERR, ("pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pcrx->pd)); - pbuf_free(inp); - LINK_STATS_INC(link.drop); - snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif); - } -#else /* PPP_INPROC_MULTITHREADED */ - pppInput(inp); -#endif /* PPP_INPROC_MULTITHREADED */ - } - - /* Prepare for a new packet. */ - pcrx->inFCS = PPP_INITFCS; - pcrx->inState = PDADDRESS; - pcrx->inEscaped = 0; - /* Other characters are usually control characters that may have - * been inserted by the physical layer so here we just drop them. */ - } else { - PPPDEBUG(LOG_WARNING, - ("pppInProc[%d]: Dropping ACCM char <%d>\n", pcrx->pd, curChar)); - } - /* Process other characters. */ - } else { - /* Unencode escaped characters. */ - if (pcrx->inEscaped) { - pcrx->inEscaped = 0; - curChar ^= PPP_TRANS; - } - - /* Process character relative to current state. */ - switch(pcrx->inState) { - case PDIDLE: /* Idle state - waiting. */ - /* Drop the character if it's not 0xff - * we would have processed a flag character above. */ - if (curChar != PPP_ALLSTATIONS) { - break; - } - - /* Fall through */ - case PDSTART: /* Process start flag. */ - /* Prepare for a new packet. */ - pcrx->inFCS = PPP_INITFCS; - - /* Fall through */ - case PDADDRESS: /* Process address field. */ - if (curChar == PPP_ALLSTATIONS) { - pcrx->inState = PDCONTROL; - break; - } - /* Else assume compressed address and control fields so - * fall through to get the protocol... */ - case PDCONTROL: /* Process control field. */ - /* If we don't get a valid control code, restart. */ - if (curChar == PPP_UI) { - pcrx->inState = PDPROTOCOL1; - break; - } -#if 0 - else { - PPPDEBUG(LOG_WARNING, - ("pppInProc[%d]: Invalid control <%d>\n", pcrx->pd, curChar)); - pcrx->inState = PDSTART; - } -#endif - case PDPROTOCOL1: /* Process protocol field 1. */ - /* If the lower bit is set, this is the end of the protocol - * field. */ - if (curChar & 1) { - pcrx->inProtocol = curChar; - pcrx->inState = PDDATA; - } else { - pcrx->inProtocol = (u_int)curChar << 8; - pcrx->inState = PDPROTOCOL2; - } - break; - case PDPROTOCOL2: /* Process protocol field 2. */ - pcrx->inProtocol |= curChar; - pcrx->inState = PDDATA; - break; - case PDDATA: /* Process data byte. */ - /* Make space to receive processed data. */ - if (pcrx->inTail == NULL || pcrx->inTail->len == PBUF_POOL_BUFSIZE) { - if (pcrx->inTail != NULL) { - pcrx->inTail->tot_len = pcrx->inTail->len; - if (pcrx->inTail != pcrx->inHead) { - pbuf_cat(pcrx->inHead, pcrx->inTail); - /* give up the inTail reference now */ - pcrx->inTail = NULL; - } - } - /* If we haven't started a packet, we need a packet header. */ - nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); - if (nextNBuf == NULL) { - /* No free buffers. Drop the input packet and let the - * higher layers deal with it. Continue processing - * the received pbuf chain in case a new packet starts. */ - PPPDEBUG(LOG_ERR, ("pppInProc[%d]: NO FREE MBUFS!\n", pcrx->pd)); - LINK_STATS_INC(link.memerr); - pppDrop(pcrx); - pcrx->inState = PDSTART; /* Wait for flag sequence. */ - break; - } - if (pcrx->inHead == NULL) { - struct pppInputHeader *pih = nextNBuf->payload; - - pih->unit = pcrx->pd; - pih->proto = pcrx->inProtocol; - - nextNBuf->len += sizeof(*pih); - - pcrx->inHead = nextNBuf; - } - pcrx->inTail = nextNBuf; - } - /* Load character into buffer. */ - ((u_char*)pcrx->inTail->payload)[pcrx->inTail->len++] = curChar; - break; - } - - /* update the frame check sequence number. */ - pcrx->inFCS = PPP_FCS(pcrx->inFCS, curChar); - } - } /* while (l-- > 0), all bytes processed */ - - avRandomize(); -} -#endif /* PPPOS_SUPPORT */ - -#if PPPOE_SUPPORT -void -pppInProcOverEthernet(int pd, struct pbuf *pb) -{ - struct pppInputHeader *pih; - u16_t inProtocol; - - if(pb->len < sizeof(inProtocol)) { - PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: too small for protocol field\n")); - goto drop; - } - - inProtocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1]; - - /* make room for pppInputHeader - should not fail */ - if (pbuf_header(pb, sizeof(*pih) - sizeof(inProtocol)) != 0) { - PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: could not allocate room for header\n")); - goto drop; - } - - pih = pb->payload; - - pih->unit = pd; - pih->proto = inProtocol; - - /* Dispatch the packet thereby consuming it. */ - pppInput(pb); - return; - -drop: - LINK_STATS_INC(link.drop); - snmp_inc_ifindiscards(&pppControl[pd].netif); - pbuf_free(pb); - return; -} -#endif /* PPPOE_SUPPORT */ - -#if LWIP_NETIF_STATUS_CALLBACK -/** Set the status callback of a PPP's netif - * - * @param pd The PPP descriptor returned by pppOpen() - * @param status_callback pointer to the status callback function - * - * @see netif_set_status_callback - */ -void -ppp_set_netif_statuscallback(int pd, netif_status_callback_fn status_callback) -{ - netif_set_status_callback(&pppControl[pd].netif, status_callback); -} -#endif /* LWIP_NETIF_STATUS_CALLBACK */ - -#if LWIP_NETIF_LINK_CALLBACK -/** Set the link callback of a PPP's netif - * - * @param pd The PPP descriptor returned by pppOpen() - * @param link_callback pointer to the link callback function - * - * @see netif_set_link_callback - */ -void -ppp_set_netif_linkcallback(int pd, netif_status_callback_fn link_callback) -{ - netif_set_link_callback(&pppControl[pd].netif, link_callback); -} -#endif /* LWIP_NETIF_LINK_CALLBACK */ - -#endif /* PPP_SUPPORT */ diff --git a/third_party/lwip/netif/ppp/ppp.h b/third_party/lwip/netif/ppp/ppp.h deleted file mode 100644 index f8ec6c3..0000000 --- a/third_party/lwip/netif/ppp/ppp.h +++ /dev/null @@ -1,201 +0,0 @@ -/***************************************************************************** -* ppp.h - Network Point to Point Protocol header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-11-05 Guy Lancaster , Global Election Systems Inc. -* Original derived from BSD codes. -*****************************************************************************/ - -#ifndef PPP_H -#define PPP_H - -#include "lwip/opt.h" - -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/sio.h" -#include "lwip/stats.h" -#include "lwip/mem.h" -#include "lwip/netif.h" -#include "lwip/sys.h" -#include "lwip/timers.h" - - -#ifndef __u_char_defined - -/* Type definitions for BSD code. */ -typedef unsigned long u_long; -typedef unsigned int u_int; -typedef unsigned short u_short; -typedef unsigned char u_char; - -#endif - - -/************************* -*** PUBLIC DEFINITIONS *** -*************************/ - -/* Error codes. */ -#define PPPERR_NONE 0 /* No error. */ -#define PPPERR_PARAM -1 /* Invalid parameter. */ -#define PPPERR_OPEN -2 /* Unable to open PPP session. */ -#define PPPERR_DEVICE -3 /* Invalid I/O device for PPP. */ -#define PPPERR_ALLOC -4 /* Unable to allocate resources. */ -#define PPPERR_USER -5 /* User interrupt. */ -#define PPPERR_CONNECT -6 /* Connection lost. */ -#define PPPERR_AUTHFAIL -7 /* Failed authentication challenge. */ -#define PPPERR_PROTOCOL -8 /* Failed to meet protocol. */ - -/* - * PPP IOCTL commands. - */ -/* - * Get the up status - 0 for down, non-zero for up. The argument must - * point to an int. - */ -#define PPPCTLG_UPSTATUS 100 /* Get the up status - 0 down else up */ -#define PPPCTLS_ERRCODE 101 /* Set the error code */ -#define PPPCTLG_ERRCODE 102 /* Get the error code */ -#define PPPCTLG_FD 103 /* Get the fd associated with the ppp */ - -/************************ -*** PUBLIC DATA TYPES *** -************************/ - -struct ppp_addrs { - ip_addr_t our_ipaddr, his_ipaddr, netmask, dns1, dns2; -}; - - -/*********************** -*** PUBLIC FUNCTIONS *** -***********************/ - -/* Initialize the PPP subsystem. */ -void pppInit(void); - -/* Warning: Using PPPAUTHTYPE_ANY might have security consequences. - * RFC 1994 says: - * - * In practice, within or associated with each PPP server, there is a - * database which associates "user" names with authentication - * information ("secrets"). It is not anticipated that a particular - * named user would be authenticated by multiple methods. This would - * make the user vulnerable to attacks which negotiate the least secure - * method from among a set (such as PAP rather than CHAP). If the same - * secret was used, PAP would reveal the secret to be used later with - * CHAP. - * - * Instead, for each user name there should be an indication of exactly - * one method used to authenticate that user name. If a user needs to - * make use of different authentication methods under different - * circumstances, then distinct user names SHOULD be employed, each of - * which identifies exactly one authentication method. - * - */ -enum pppAuthType { - PPPAUTHTYPE_NONE, - PPPAUTHTYPE_ANY, - PPPAUTHTYPE_PAP, - PPPAUTHTYPE_CHAP -}; - -void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd); - -/* Link status callback function prototype */ -typedef void (*pppLinkStatusCB_fn)(void *ctx, int errCode, void *arg); - -#if PPPOS_SUPPORT -/* - * Open a new PPP connection using the given serial I/O device. - * This initializes the PPP control block but does not - * attempt to negotiate the LCP session. - * Return a new PPP connection descriptor on success or - * an error code (negative) on failure. - */ -int pppOverSerialOpen(sio_fd_t fd, pppLinkStatusCB_fn linkStatusCB, void *linkStatusCtx); -#endif /* PPPOS_SUPPORT */ - -#if PPPOE_SUPPORT -/* - * Open a new PPP Over Ethernet (PPPOE) connection. - */ -int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, - pppLinkStatusCB_fn linkStatusCB, void *linkStatusCtx); -#endif /* PPPOE_SUPPORT */ - -/* for source code compatibility */ -#define pppOpen(fd,cb,ls) pppOverSerialOpen(fd,cb,ls) - -/* - * Close a PPP connection and release the descriptor. - * Any outstanding packets in the queues are dropped. - * Return 0 on success, an error code on failure. - */ -int pppClose(int pd); - -/* - * Indicate to the PPP process that the line has disconnected. - */ -void pppSigHUP(int pd); - -/* - * Get and set parameters for the given connection. - * Return 0 on success, an error code on failure. - */ -int pppIOCtl(int pd, int cmd, void *arg); - -/* - * Return the Maximum Transmission Unit for the given PPP connection. - */ -u_short pppMTU(int pd); - -#if PPPOS_SUPPORT && !PPP_INPROC_OWNTHREAD -/* - * PPP over Serial: this is the input function to be called for received data. - * If PPP_INPROC_OWNTHREAD==1, a seperate input thread using the blocking - * sio_read() is used, so this is deactivated. - */ -void pppos_input(int pd, u_char* data, int len); -#endif /* PPPOS_SUPPORT && !PPP_INPROC_OWNTHREAD */ - - -#if LWIP_NETIF_STATUS_CALLBACK -/* Set an lwIP-style status-callback for the selected PPP device */ -void ppp_set_netif_statuscallback(int pd, netif_status_callback_fn status_callback); -#endif /* LWIP_NETIF_STATUS_CALLBACK */ -#if LWIP_NETIF_LINK_CALLBACK -/* Set an lwIP-style link-callback for the selected PPP device */ -void ppp_set_netif_linkcallback(int pd, netif_status_callback_fn link_callback); -#endif /* LWIP_NETIF_LINK_CALLBACK */ - -#endif /* PPP_SUPPORT */ - -#endif /* PPP_H */ diff --git a/third_party/lwip/netif/ppp/ppp_impl.h b/third_party/lwip/netif/ppp/ppp_impl.h deleted file mode 100644 index aadfc4e..0000000 --- a/third_party/lwip/netif/ppp/ppp_impl.h +++ /dev/null @@ -1,363 +0,0 @@ -/***************************************************************************** -* ppp.h - Network Point to Point Protocol header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-11-05 Guy Lancaster , Global Election Systems Inc. -* Original derived from BSD codes. -*****************************************************************************/ - -#ifndef PPP_IMPL_H -#define PPP_IMPL_H - -#include "lwip/opt.h" - -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "ppp.h" -#include "lwip/def.h" -#include "lwip/sio.h" -#include "lwip/stats.h" -#include "lwip/mem.h" -#include "lwip/netif.h" -#include "lwip/sys.h" -#include "lwip/timers.h" - -/** Some defines for code we skip compared to the original pppd. - * These are just here to minimise the use of the ugly "#if 0". */ -#define PPP_ADDITIONAL_CALLBACKS 0 - -/** Some error checks to test for unsupported code */ -#if CBCP_SUPPORT -#error "CBCP is not supported in lwIP PPP" -#endif -#if CCP_SUPPORT -#error "CCP is not supported in lwIP PPP" -#endif - -/* - * pppd.h - PPP daemon global declarations. - * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - */ -/* - * ppp_defs.h - PPP definitions. - * - * Copyright (c) 1994 The Australian National University. - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, provided that the above copyright - * notice appears in all copies. This software is provided without any - * warranty, express or implied. The Australian National University - * makes no representations about the suitability of this software for - * any purpose. - * - * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY - * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO - * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, - * OR MODIFICATIONS. - */ - -#define TIMEOUT(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t)*1000, (f), (a)); } while(0) -#define UNTIMEOUT(f, a) sys_untimeout((f), (a)) - - -/* - * Constants and structures defined by the internet system, - * Per RFC 790, September 1981, and numerous additions. - */ - -/* - * The basic PPP frame. - */ -#define PPP_HDRLEN 4 /* octets for standard ppp header */ -#define PPP_FCSLEN 2 /* octets for FCS */ - - -/* - * Significant octet values. - */ -#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ -#define PPP_UI 0x03 /* Unnumbered Information */ -#define PPP_FLAG 0x7e /* Flag Sequence */ -#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */ -#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ - -/* - * Protocol field values. - */ -#define PPP_IP 0x21 /* Internet Protocol */ -#define PPP_AT 0x29 /* AppleTalk Protocol */ -#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ -#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ -#define PPP_COMP 0xfd /* compressed packet */ -#define PPP_IPCP 0x8021 /* IP Control Protocol */ -#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */ -#define PPP_CCP 0x80fd /* Compression Control Protocol */ -#define PPP_LCP 0xc021 /* Link Control Protocol */ -#define PPP_PAP 0xc023 /* Password Authentication Protocol */ -#define PPP_LQR 0xc025 /* Link Quality Report protocol */ -#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ -#define PPP_CBCP 0xc029 /* Callback Control Protocol */ - -/* - * Values for FCS calculations. - */ -#define PPP_INITFCS 0xffff /* Initial FCS value */ -#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ -#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) - -/* - * Extended asyncmap - allows any character to be escaped. - */ -typedef u_char ext_accm[32]; - -/* - * What to do with network protocol (NP) packets. - */ -enum NPmode { - NPMODE_PASS, /* pass the packet through */ - NPMODE_DROP, /* silently drop the packet */ - NPMODE_ERROR, /* return an error */ - NPMODE_QUEUE /* save it up for later. */ -}; - -/* - * Inline versions of get/put char/short/long. - * Pointer is advanced; we assume that both arguments - * are lvalues and will already be in registers. - * cp MUST be u_char *. - */ -#define GETCHAR(c, cp) { \ - (c) = *(cp)++; \ -} -#define PUTCHAR(c, cp) { \ - *(cp)++ = (u_char) (c); \ -} - - -#define GETSHORT(s, cp) { \ - (s) = *(cp); (cp)++; (s) <<= 8; \ - (s) |= *(cp); (cp)++; \ -} -#define PUTSHORT(s, cp) { \ - *(cp)++ = (u_char) ((s) >> 8); \ - *(cp)++ = (u_char) (s & 0xff); \ -} - -#define GETLONG(l, cp) { \ - (l) = *(cp); (cp)++; (l) <<= 8; \ - (l) |= *(cp); (cp)++; (l) <<= 8; \ - (l) |= *(cp); (cp)++; (l) <<= 8; \ - (l) |= *(cp); (cp)++; \ -} -#define PUTLONG(l, cp) { \ - *(cp)++ = (u_char) ((l) >> 24); \ - *(cp)++ = (u_char) ((l) >> 16); \ - *(cp)++ = (u_char) ((l) >> 8); \ - *(cp)++ = (u_char) (l); \ -} - - -#define INCPTR(n, cp) ((cp) += (n)) -#define DECPTR(n, cp) ((cp) -= (n)) - -#define BCMP(s0, s1, l) memcmp((u_char *)(s0), (u_char *)(s1), (l)) -#define BCOPY(s, d, l) MEMCPY((d), (s), (l)) -#define BZERO(s, n) memset(s, 0, n) - -#if PPP_DEBUG -#define PRINTMSG(m, l) { m[l] = '\0'; LWIP_DEBUGF(LOG_INFO, ("Remote message: %s\n", m)); } -#else /* PPP_DEBUG */ -#define PRINTMSG(m, l) -#endif /* PPP_DEBUG */ - -/* - * MAKEHEADER - Add PPP Header fields to a packet. - */ -#define MAKEHEADER(p, t) { \ - PUTCHAR(PPP_ALLSTATIONS, p); \ - PUTCHAR(PPP_UI, p); \ - PUTSHORT(t, p); } - -/************************ -*** PUBLIC DATA TYPES *** -************************/ - -/* - * The following struct gives the addresses of procedures to call - * for a particular protocol. - */ -struct protent { - u_short protocol; /* PPP protocol number */ - /* Initialization procedure */ - void (*init) (int unit); - /* Process a received packet */ - void (*input) (int unit, u_char *pkt, int len); - /* Process a received protocol-reject */ - void (*protrej) (int unit); - /* Lower layer has come up */ - void (*lowerup) (int unit); - /* Lower layer has gone down */ - void (*lowerdown) (int unit); - /* Open the protocol */ - void (*open) (int unit); - /* Close the protocol */ - void (*close) (int unit, char *reason); -#if PPP_ADDITIONAL_CALLBACKS - /* Print a packet in readable form */ - int (*printpkt) (u_char *pkt, int len, - void (*printer) (void *, char *, ...), - void *arg); - /* Process a received data packet */ - void (*datainput) (int unit, u_char *pkt, int len); -#endif /* PPP_ADDITIONAL_CALLBACKS */ - int enabled_flag; /* 0 if protocol is disabled */ - char *name; /* Text name of protocol */ -#if PPP_ADDITIONAL_CALLBACKS - /* Check requested options, assign defaults */ - void (*check_options) (u_long); - /* Configure interface for demand-dial */ - int (*demand_conf) (int unit); - /* Say whether to bring up link for this pkt */ - int (*active_pkt) (u_char *pkt, int len); -#endif /* PPP_ADDITIONAL_CALLBACKS */ -}; - -/* - * The following structure records the time in seconds since - * the last NP packet was sent or received. - */ -struct ppp_idle { - u_short xmit_idle; /* seconds since last NP packet sent */ - u_short recv_idle; /* seconds since last NP packet received */ -}; - -struct ppp_settings { - - u_int disable_defaultip : 1; /* Don't use hostname for default IP addrs */ - u_int auth_required : 1; /* Peer is required to authenticate */ - u_int explicit_remote : 1; /* remote_name specified with remotename opt */ - u_int refuse_pap : 1; /* Don't wanna auth. ourselves with PAP */ - u_int refuse_chap : 1; /* Don't wanna auth. ourselves with CHAP */ - u_int usehostname : 1; /* Use hostname for our_name */ - u_int usepeerdns : 1; /* Ask peer for DNS adds */ - - u_short idle_time_limit; /* Shut down link if idle for this long */ - int maxconnect; /* Maximum connect time (seconds) */ - - char user [MAXNAMELEN + 1]; /* Username for PAP */ - char passwd [MAXSECRETLEN + 1]; /* Password for PAP, secret for CHAP */ - char our_name [MAXNAMELEN + 1]; /* Our name for authentication purposes */ - char remote_name[MAXNAMELEN + 1]; /* Peer's name for authentication */ -}; - -/***************************** -*** PUBLIC DATA STRUCTURES *** -*****************************/ - -/* Buffers for outgoing packets. */ -extern u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN]; - -extern struct ppp_settings ppp_settings; - -extern struct protent *ppp_protocols[]; /* Table of pointers to supported protocols */ - - -/*********************** -*** PUBLIC FUNCTIONS *** -***********************/ - -/* - * Write n characters to a ppp link. - * RETURN: >= 0 Number of characters written, -1 Failed to write to device. - */ -int pppWrite(int pd, const u_char *s, int n); - -void pppInProcOverEthernet(int pd, struct pbuf *pb); - -struct pbuf *pppSingleBuf(struct pbuf *p); - -void pppLinkTerminated(int pd); - -void pppLinkDown(int pd); - -/* Configure i/f transmit parameters */ -void ppp_send_config (int, u16_t, u32_t, int, int); -/* Set extended transmit ACCM */ -void ppp_set_xaccm (int, ext_accm *); -/* Configure i/f receive parameters */ -void ppp_recv_config (int, int, u32_t, int, int); -/* Find out how long link has been idle */ -int get_idle_time (int, struct ppp_idle *); - -/* Configure VJ TCP header compression */ -int sifvjcomp (int, int, u8_t, u8_t); -/* Configure i/f down (for IP) */ -int sifup (int); -/* Set mode for handling packets for proto */ -int sifnpmode (int u, int proto, enum NPmode mode); -/* Configure i/f down (for IP) */ -int sifdown (int); -/* Configure IP addresses for i/f */ -int sifaddr (int, u32_t, u32_t, u32_t, u32_t, u32_t); -/* Reset i/f IP addresses */ -int cifaddr (int, u32_t, u32_t); -/* Create default route through i/f */ -int sifdefaultroute (int, u32_t, u32_t); -/* Delete default route through i/f */ -int cifdefaultroute (int, u32_t, u32_t); - -/* Get appropriate netmask for address */ -u32_t GetMask (u32_t); - -#endif /* PPP_SUPPORT */ - -#endif /* PPP_IMPL_H */ diff --git a/third_party/lwip/netif/ppp/ppp_oe.c b/third_party/lwip/netif/ppp/ppp_oe.c deleted file mode 100644 index 9718bcb..0000000 --- a/third_party/lwip/netif/ppp/ppp_oe.c +++ /dev/null @@ -1,1132 +0,0 @@ -/***************************************************************************** -* ppp_oe.c - PPP Over Ethernet implementation for lwIP. -* -* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 06-01-01 Marc Boucher -* Ported to lwIP. -*****************************************************************************/ - - - -/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ - -/*- - * Copyright (c) 2002 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Martin Husemann . - * - * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 "lwip/opt.h" - -#if PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "netif/ppp_oe.h" - -#include "ppp_impl.h" -#include "pppdebug.h" - -#include "lwip/timers.h" -#include "lwip/memp.h" - -#include -#include - - -/* Add a 16 bit unsigned value to a buffer pointed to by PTR */ -#define PPPOE_ADD_16(PTR, VAL) \ - *(PTR)++ = (u8_t)((VAL) / 256); \ - *(PTR)++ = (u8_t)((VAL) % 256) - -/* Add a complete PPPoE header to the buffer pointed to by PTR */ -#define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \ - *(PTR)++ = PPPOE_VERTYPE; \ - *(PTR)++ = (CODE); \ - PPPOE_ADD_16(PTR, SESS); \ - PPPOE_ADD_16(PTR, LEN) - -#define PPPOE_DISC_TIMEOUT (5*1000) /* base for quick timeout calculation */ -#define PPPOE_SLOW_RETRY (60*1000) /* persistent retry interval */ -#define PPPOE_DISC_MAXPADI 4 /* retry PADI four times (quickly) */ -#define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */ - -#ifdef PPPOE_SERVER -#error "PPPOE_SERVER is not yet supported under lwIP!" -/* from if_spppsubr.c */ -#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ -#endif - -#ifndef PPPOE_ERRORSTRING_LEN -#define PPPOE_ERRORSTRING_LEN 64 -#endif -static char pppoe_error_tmp[PPPOE_ERRORSTRING_LEN]; - - -/* input routines */ -static void pppoe_dispatch_disc_pkt(struct netif *, struct pbuf *); - -/* management routines */ -static int pppoe_do_disconnect(struct pppoe_softc *); -static void pppoe_abort_connect(struct pppoe_softc *); -static void pppoe_clear_softc(struct pppoe_softc *, const char *); - -/* internal timeout handling */ -static void pppoe_timeout(void *); - -/* sending actual protocol controll packets */ -static err_t pppoe_send_padi(struct pppoe_softc *); -static err_t pppoe_send_padr(struct pppoe_softc *); -#ifdef PPPOE_SERVER -static err_t pppoe_send_pado(struct pppoe_softc *); -static err_t pppoe_send_pads(struct pppoe_softc *); -#endif -static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *); - -/* internal helper functions */ -static struct pppoe_softc * pppoe_find_softc_by_session(u_int, struct netif *); -static struct pppoe_softc * pppoe_find_softc_by_hunique(u8_t *, size_t, struct netif *); - -/** linked list of created pppoe interfaces */ -static struct pppoe_softc *pppoe_softc_list; - -err_t -pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr) -{ - struct pppoe_softc *sc; - - sc = (struct pppoe_softc *)memp_malloc(MEMP_PPPOE_IF); - if (sc == NULL) { - *scptr = NULL; - return ERR_MEM; - } - memset(sc, 0, sizeof(struct pppoe_softc)); - - /* changed to real address later */ - MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); - - sc->sc_pd = pd; - sc->sc_linkStatusCB = linkStatusCB; - sc->sc_ethif = ethif; - - /* put the new interface at the head of the list */ - sc->next = pppoe_softc_list; - pppoe_softc_list = sc; - - *scptr = sc; - - return ERR_OK; -} - -err_t -pppoe_destroy(struct netif *ifp) -{ - struct pppoe_softc *sc, *prev = NULL; - - for (sc = pppoe_softc_list; sc != NULL; prev = sc, sc = sc->next) { - if (sc->sc_ethif == ifp) { - break; - } - } - - if(!(sc && (sc->sc_ethif == ifp))) { - return ERR_IF; - } - - sys_untimeout(pppoe_timeout, sc); - if (prev == NULL) { - /* remove sc from the head of the list */ - pppoe_softc_list = sc->next; - } else { - /* remove sc from the list */ - prev->next = sc->next; - } - -#ifdef PPPOE_TODO - if (sc->sc_concentrator_name) { - mem_free(sc->sc_concentrator_name); - } - if (sc->sc_service_name) { - mem_free(sc->sc_service_name); - } -#endif /* PPPOE_TODO */ - memp_free(MEMP_PPPOE_IF, sc); - - return ERR_OK; -} - -/* - * Find the interface handling the specified session. - * Note: O(number of sessions open), this is a client-side only, mean - * and lean implementation, so number of open sessions typically should - * be 1. - */ -static struct pppoe_softc * -pppoe_find_softc_by_session(u_int session, struct netif *rcvif) -{ - struct pppoe_softc *sc; - - if (session == 0) { - return NULL; - } - - for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { - if (sc->sc_state == PPPOE_STATE_SESSION - && sc->sc_session == session) { - if (sc->sc_ethif == rcvif) { - return sc; - } else { - return NULL; - } - } - } - return NULL; -} - -/* Check host unique token passed and return appropriate softc pointer, - * or NULL if token is bogus. */ -static struct pppoe_softc * -pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) -{ - struct pppoe_softc *sc, *t; - - if (pppoe_softc_list == NULL) { - return NULL; - } - - if (len != sizeof sc) { - return NULL; - } - MEMCPY(&t, token, len); - - for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { - if (sc == t) { - break; - } - } - - if (sc == NULL) { - PPPDEBUG(LOG_DEBUG, ("pppoe: alien host unique tag, no session found\n")); - return NULL; - } - - /* should be safe to access *sc now */ - if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) { - printf("%c%c%"U16_F": host unique tag found, but it belongs to a connection in state %d\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_state); - return NULL; - } - if (sc->sc_ethif != rcvif) { - printf("%c%c%"U16_F": wrong interface, not accepting host unique\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); - return NULL; - } - return sc; -} - -static void -pppoe_linkstatus_up(struct pppoe_softc *sc) -{ - sc->sc_linkStatusCB(sc->sc_pd, 1); -} - -/* analyze and handle a single received packet while not in session state */ -static void -pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb) -{ - u16_t tag, len; - u16_t session, plen; - struct pppoe_softc *sc; - const char *err_msg; - char devname[6]; - u8_t *ac_cookie; - u16_t ac_cookie_len; -#ifdef PPPOE_SERVER - u8_t *hunique; - size_t hunique_len; -#endif - struct pppoehdr *ph; - struct pppoetag pt; - int off, err, errortag; - struct eth_hdr *ethhdr; - - pb = pppSingleBuf(pb); - - strcpy(devname, "pppoe"); /* as long as we don't know which instance */ - err_msg = NULL; - errortag = 0; - if (pb->len < sizeof(*ethhdr)) { - goto done; - } - ethhdr = (struct eth_hdr *)pb->payload; - off = sizeof(*ethhdr); - - ac_cookie = NULL; - ac_cookie_len = 0; -#ifdef PPPOE_SERVER - hunique = NULL; - hunique_len = 0; -#endif - session = 0; - if (pb->len - off < PPPOE_HEADERLEN) { - printf("pppoe: packet too short: %d\n", pb->len); - goto done; - } - - ph = (struct pppoehdr *) (ethhdr + 1); - if (ph->vertype != PPPOE_VERTYPE) { - printf("pppoe: unknown version/type packet: 0x%x\n", ph->vertype); - goto done; - } - session = ntohs(ph->session); - plen = ntohs(ph->plen); - off += sizeof(*ph); - - if (plen + off > pb->len) { - printf("pppoe: packet content does not fit: data available = %d, packet size = %u\n", - pb->len - off, plen); - goto done; - } - if(pb->tot_len == pb->len) { - pb->tot_len = pb->len = (u16_t)off + plen; /* ignore trailing garbage */ - } - tag = 0; - len = 0; - sc = NULL; - while (off + sizeof(pt) <= pb->len) { - MEMCPY(&pt, (u8_t*)pb->payload + off, sizeof(pt)); - tag = ntohs(pt.tag); - len = ntohs(pt.len); - if (off + sizeof(pt) + len > pb->len) { - printf("pppoe: tag 0x%x len 0x%x is too long\n", tag, len); - goto done; - } - switch (tag) { - case PPPOE_TAG_EOL: - goto breakbreak; - case PPPOE_TAG_SNAME: - break; /* ignored */ - case PPPOE_TAG_ACNAME: - break; /* ignored */ - case PPPOE_TAG_HUNIQUE: - if (sc != NULL) { - break; - } -#ifdef PPPOE_SERVER - hunique = (u8_t*)pb->payload + off + sizeof(pt); - hunique_len = len; -#endif - sc = pppoe_find_softc_by_hunique((u8_t*)pb->payload + off + sizeof(pt), len, netif); - if (sc != NULL) { - snprintf(devname, sizeof(devname), "%c%c%"U16_F, sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); - } - break; - case PPPOE_TAG_ACCOOKIE: - if (ac_cookie == NULL) { - ac_cookie = (u8_t*)pb->payload + off + sizeof(pt); - ac_cookie_len = len; - } - break; - case PPPOE_TAG_SNAME_ERR: - err_msg = "SERVICE NAME ERROR"; - errortag = 1; - break; - case PPPOE_TAG_ACSYS_ERR: - err_msg = "AC SYSTEM ERROR"; - errortag = 1; - break; - case PPPOE_TAG_GENERIC_ERR: - err_msg = "GENERIC ERROR"; - errortag = 1; - break; - } - if (err_msg) { - if (errortag && len) { - u16_t error_len = LWIP_MIN(len, sizeof(pppoe_error_tmp)-1); - strncpy(pppoe_error_tmp, (char*)pb->payload + off + sizeof(pt), error_len); - pppoe_error_tmp[error_len-1] = '\0'; - printf("%s: %s: %s\n", devname, err_msg, pppoe_error_tmp); - } else { - printf("%s: %s\n", devname, err_msg); - } - if (errortag) { - goto done; - } - } - off += sizeof(pt) + len; - } - -breakbreak:; - switch (ph->code) { - case PPPOE_CODE_PADI: -#ifdef PPPOE_SERVER - /* - * got service name, concentrator name, and/or host unique. - * ignore if we have no interfaces with IFF_PASSIVE|IFF_UP. - */ - if (LIST_EMPTY(&pppoe_softc_list)) { - goto done; - } - LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { - if (!(sc->sc_sppp.pp_if.if_flags & IFF_UP)) { - continue; - } - if (!(sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { - continue; - } - if (sc->sc_state == PPPOE_STATE_INITIAL) { - break; - } - } - if (sc == NULL) { - /* printf("pppoe: free passive interface is not found\n"); */ - goto done; - } - if (hunique) { - if (sc->sc_hunique) { - mem_free(sc->sc_hunique); - } - sc->sc_hunique = mem_malloc(hunique_len); - if (sc->sc_hunique == NULL) { - goto done; - } - sc->sc_hunique_len = hunique_len; - MEMCPY(sc->sc_hunique, hunique, hunique_len); - } - MEMCPY(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest); - sc->sc_state = PPPOE_STATE_PADO_SENT; - pppoe_send_pado(sc); - break; -#endif /* PPPOE_SERVER */ - case PPPOE_CODE_PADR: -#ifdef PPPOE_SERVER - /* - * get sc from ac_cookie if IFF_PASSIVE - */ - if (ac_cookie == NULL) { - /* be quiet if there is not a single pppoe instance */ - printf("pppoe: received PADR but not includes ac_cookie\n"); - goto done; - } - sc = pppoe_find_softc_by_hunique(ac_cookie, ac_cookie_len, netif); - if (sc == NULL) { - /* be quiet if there is not a single pppoe instance */ - if (!LIST_EMPTY(&pppoe_softc_list)) { - printf("pppoe: received PADR but could not find request for it\n"); - } - goto done; - } - if (sc->sc_state != PPPOE_STATE_PADO_SENT) { - printf("%c%c%"U16_F": received unexpected PADR\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); - goto done; - } - if (hunique) { - if (sc->sc_hunique) { - mem_free(sc->sc_hunique); - } - sc->sc_hunique = mem_malloc(hunique_len); - if (sc->sc_hunique == NULL) { - goto done; - } - sc->sc_hunique_len = hunique_len; - MEMCPY(sc->sc_hunique, hunique, hunique_len); - } - pppoe_send_pads(sc); - sc->sc_state = PPPOE_STATE_SESSION; - pppoe_linkstatus_up(sc); /* notify upper layers */ - break; -#else - /* ignore, we are no access concentrator */ - goto done; -#endif /* PPPOE_SERVER */ - case PPPOE_CODE_PADO: - if (sc == NULL) { - /* be quiet if there is not a single pppoe instance */ - if (pppoe_softc_list != NULL) { - printf("pppoe: received PADO but could not find request for it\n"); - } - goto done; - } - if (sc->sc_state != PPPOE_STATE_PADI_SENT) { - printf("%c%c%"U16_F": received unexpected PADO\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); - goto done; - } - if (ac_cookie) { - sc->sc_ac_cookie_len = ac_cookie_len; - MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len); - } - MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr)); - sys_untimeout(pppoe_timeout, sc); - sc->sc_padr_retried = 0; - sc->sc_state = PPPOE_STATE_PADR_SENT; - if ((err = pppoe_send_padr(sc)) != 0) { - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); - } - sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); - break; - case PPPOE_CODE_PADS: - if (sc == NULL) { - goto done; - } - sc->sc_session = session; - sys_untimeout(pppoe_timeout, sc); - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x connected\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, session)); - sc->sc_state = PPPOE_STATE_SESSION; - pppoe_linkstatus_up(sc); /* notify upper layers */ - break; - case PPPOE_CODE_PADT: - if (sc == NULL) { - goto done; - } - pppoe_clear_softc(sc, "received PADT"); - break; - default: - if(sc) { - printf("%c%c%"U16_F": unknown code (0x%"X16_F") session = 0x%"X16_F"\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, - (u16_t)ph->code, session); - } else { - printf("pppoe: unknown code (0x%"X16_F") session = 0x%"X16_F"\n", (u16_t)ph->code, session); - } - break; - } - -done: - pbuf_free(pb); - return; -} - -void -pppoe_disc_input(struct netif *netif, struct pbuf *p) -{ - /* avoid error messages if there is not a single pppoe instance */ - if (pppoe_softc_list != NULL) { - pppoe_dispatch_disc_pkt(netif, p); - } else { - pbuf_free(p); - } -} - -void -pppoe_data_input(struct netif *netif, struct pbuf *pb) -{ - u16_t session, plen; - struct pppoe_softc *sc; - struct pppoehdr *ph; -#ifdef PPPOE_TERM_UNKNOWN_SESSIONS - u8_t shost[ETHER_ADDR_LEN]; -#endif - -#ifdef PPPOE_TERM_UNKNOWN_SESSIONS - MEMCPY(shost, ((struct eth_hdr *)pb->payload)->src.addr, sizeof(shost)); -#endif - if (pbuf_header(pb, -(int)sizeof(struct eth_hdr)) != 0) { - /* bail out */ - PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header failed\n")); - LINK_STATS_INC(link.lenerr); - goto drop; - } - - pb = pppSingleBuf (pb); - - if (pb->len <= PPPOE_HEADERLEN) { - printf("pppoe (data): dropping too short packet: %d bytes\n", pb->len); - goto drop; - } - - if (pb->len < sizeof(*ph)) { - printf("pppoe_data_input: could not get PPPoE header\n"); - goto drop; - } - ph = (struct pppoehdr *)pb->payload; - - if (ph->vertype != PPPOE_VERTYPE) { - printf("pppoe (data): unknown version/type packet: 0x%x\n", ph->vertype); - goto drop; - } - if (ph->code != 0) { - goto drop; - } - - session = ntohs(ph->session); - sc = pppoe_find_softc_by_session(session, netif); - if (sc == NULL) { -#ifdef PPPOE_TERM_UNKNOWN_SESSIONS - printf("pppoe: input for unknown session 0x%x, sending PADT\n", session); - pppoe_send_padt(netif, session, shost); -#endif - goto drop; - } - - plen = ntohs(ph->plen); - - if (pbuf_header(pb, -(int)(PPPOE_HEADERLEN)) != 0) { - /* bail out */ - PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n")); - LINK_STATS_INC(link.lenerr); - goto drop; - } - - PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, - pb->len, plen)); - - if (pb->len < plen) { - goto drop; - } - - pppInProcOverEthernet(sc->sc_pd, pb); - - return; - -drop: - pbuf_free(pb); -} - -static err_t -pppoe_output(struct pppoe_softc *sc, struct pbuf *pb) -{ - struct eth_hdr *ethhdr; - u16_t etype; - err_t res; - - if (!sc->sc_ethif) { - pbuf_free(pb); - return ERR_IF; - } - - ethhdr = (struct eth_hdr *)pb->payload; - etype = sc->sc_state == PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC; - ethhdr->type = htons(etype); - MEMCPY(ethhdr->dest.addr, sc->sc_dest.addr, sizeof(ethhdr->dest.addr)); - MEMCPY(ethhdr->src.addr, ((struct eth_addr *)sc->sc_ethif->hwaddr)->addr, sizeof(ethhdr->src.addr)); - - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F" (%x) state=%d, session=0x%x output -> %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F", len=%d\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype, - sc->sc_state, sc->sc_session, - sc->sc_dest.addr[0], sc->sc_dest.addr[1], sc->sc_dest.addr[2], sc->sc_dest.addr[3], sc->sc_dest.addr[4], sc->sc_dest.addr[5], - pb->tot_len)); - - res = sc->sc_ethif->linkoutput(sc->sc_ethif, pb); - - pbuf_free(pb); - - return res; -} - -static err_t -pppoe_send_padi(struct pppoe_softc *sc) -{ - struct pbuf *pb; - u8_t *p; - int len; -#ifdef PPPOE_TODO - int l1 = 0, l2 = 0; /* XXX: gcc */ -#endif /* PPPOE_TODO */ - - if (sc->sc_state >PPPOE_STATE_PADI_SENT) { - PPPDEBUG(LOG_ERR, ("ERROR: pppoe_send_padi in state %d", sc->sc_state)); - } - - /* calculate length of frame (excluding ethernet header + pppoe header) */ - len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */ -#ifdef PPPOE_TODO - if (sc->sc_service_name != NULL) { - l1 = (int)strlen(sc->sc_service_name); - len += l1; - } - if (sc->sc_concentrator_name != NULL) { - l2 = (int)strlen(sc->sc_concentrator_name); - len += 2 + 2 + l2; - } -#endif /* PPPOE_TODO */ - LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", - sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); - - /* allocate a buffer */ - pb = pbuf_alloc(PBUF_LINK, (u16_t)(sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len), PBUF_RAM); - if (!pb) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - p = (u8_t*)pb->payload + sizeof (struct eth_hdr); - /* fill in pkt */ - PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len); - PPPOE_ADD_16(p, PPPOE_TAG_SNAME); -#ifdef PPPOE_TODO - if (sc->sc_service_name != NULL) { - PPPOE_ADD_16(p, l1); - MEMCPY(p, sc->sc_service_name, l1); - p += l1; - } else -#endif /* PPPOE_TODO */ - { - PPPOE_ADD_16(p, 0); - } -#ifdef PPPOE_TODO - if (sc->sc_concentrator_name != NULL) { - PPPOE_ADD_16(p, PPPOE_TAG_ACNAME); - PPPOE_ADD_16(p, l2); - MEMCPY(p, sc->sc_concentrator_name, l2); - p += l2; - } -#endif /* PPPOE_TODO */ - PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); - PPPOE_ADD_16(p, sizeof(sc)); - MEMCPY(p, &sc, sizeof sc); - - /* send pkt */ - return pppoe_output(sc, pb); -} - -static void -pppoe_timeout(void *arg) -{ - int retry_wait, err; - struct pppoe_softc *sc = (struct pppoe_softc*)arg; - - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - - switch (sc->sc_state) { - case PPPOE_STATE_PADI_SENT: - /* - * We have two basic ways of retrying: - * - Quick retry mode: try a few times in short sequence - * - Slow retry mode: we already had a connection successfully - * established and will try infinitely (without user - * intervention) - * We only enter slow retry mode if IFF_LINK1 (aka autodial) - * is not set. - */ - - /* initialize for quick retry mode */ - retry_wait = PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried); - - sc->sc_padi_retried++; - if (sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) { -#if 0 - if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0) { - /* slow retry mode */ - retry_wait = PPPOE_SLOW_RETRY; - } else -#endif - { - pppoe_abort_connect(sc); - return; - } - } - if ((err = pppoe_send_padi(sc)) != 0) { - sc->sc_padi_retried--; - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); - } - sys_timeout(retry_wait, pppoe_timeout, sc); - break; - - case PPPOE_STATE_PADR_SENT: - sc->sc_padr_retried++; - if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) { - MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); - sc->sc_state = PPPOE_STATE_PADI_SENT; - sc->sc_padr_retried = 0; - if ((err = pppoe_send_padi(sc)) != 0) { - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); - } - sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc); - return; - } - if ((err = pppoe_send_padr(sc)) != 0) { - sc->sc_padr_retried--; - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); - } - sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); - break; - case PPPOE_STATE_CLOSING: - pppoe_do_disconnect(sc); - break; - default: - return; /* all done, work in peace */ - } -} - -/* Start a connection (i.e. initiate discovery phase) */ -int -pppoe_connect(struct pppoe_softc *sc) -{ - int err; - - if (sc->sc_state != PPPOE_STATE_INITIAL) { - return EBUSY; - } - -#ifdef PPPOE_SERVER - /* wait PADI if IFF_PASSIVE */ - if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { - return 0; - } -#endif - /* save state, in case we fail to send PADI */ - sc->sc_state = PPPOE_STATE_PADI_SENT; - sc->sc_padr_retried = 0; - err = pppoe_send_padi(sc); - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); - sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc); - return err; -} - -/* disconnect */ -void -pppoe_disconnect(struct pppoe_softc *sc) -{ - if (sc->sc_state < PPPOE_STATE_SESSION) { - return; - } - /* - * Do not call pppoe_disconnect here, the upper layer state - * machine gets confused by this. We must return from this - * function and defer disconnecting to the timeout handler. - */ - sc->sc_state = PPPOE_STATE_CLOSING; - sys_timeout(20, pppoe_timeout, sc); -} - -static int -pppoe_do_disconnect(struct pppoe_softc *sc) -{ - int err; - - if (sc->sc_state < PPPOE_STATE_SESSION) { - err = EBUSY; - } else { - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - err = pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest); - } - - /* cleanup softc */ - sc->sc_state = PPPOE_STATE_INITIAL; - MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); - sc->sc_ac_cookie_len = 0; -#ifdef PPPOE_SERVER - if (sc->sc_hunique) { - mem_free(sc->sc_hunique); - sc->sc_hunique = NULL; - } - sc->sc_hunique_len = 0; -#endif - sc->sc_session = 0; - - sc->sc_linkStatusCB(sc->sc_pd, 0); /* notify upper layers */ - - return err; -} - -/* Connection attempt aborted */ -static void -pppoe_abort_connect(struct pppoe_softc *sc) -{ - printf("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); - sc->sc_state = PPPOE_STATE_CLOSING; - - sc->sc_linkStatusCB(sc->sc_pd, 0); /* notify upper layers */ - - /* clear connection state */ - MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); - sc->sc_state = PPPOE_STATE_INITIAL; -} - -/* Send a PADR packet */ -static err_t -pppoe_send_padr(struct pppoe_softc *sc) -{ - struct pbuf *pb; - u8_t *p; - size_t len; -#ifdef PPPOE_TODO - size_t l1 = 0; /* XXX: gcc */ -#endif /* PPPOE_TODO */ - - if (sc->sc_state != PPPOE_STATE_PADR_SENT) { - return ERR_CONN; - } - - len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */ -#ifdef PPPOE_TODO - if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ - l1 = strlen(sc->sc_service_name); - len += l1; - } -#endif /* PPPOE_TODO */ - if (sc->sc_ac_cookie_len > 0) { - len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */ - } - LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", - sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); - pb = pbuf_alloc(PBUF_LINK, (u16_t)(sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len), PBUF_RAM); - if (!pb) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - p = (u8_t*)pb->payload + sizeof (struct eth_hdr); - PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len); - PPPOE_ADD_16(p, PPPOE_TAG_SNAME); -#ifdef PPPOE_TODO - if (sc->sc_service_name != NULL) { - PPPOE_ADD_16(p, l1); - MEMCPY(p, sc->sc_service_name, l1); - p += l1; - } else -#endif /* PPPOE_TODO */ - { - PPPOE_ADD_16(p, 0); - } - if (sc->sc_ac_cookie_len > 0) { - PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); - PPPOE_ADD_16(p, sc->sc_ac_cookie_len); - MEMCPY(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len); - p += sc->sc_ac_cookie_len; - } - PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); - PPPOE_ADD_16(p, sizeof(sc)); - MEMCPY(p, &sc, sizeof sc); - - return pppoe_output(sc, pb); -} - -/* send a PADT packet */ -static err_t -pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest) -{ - struct pbuf *pb; - struct eth_hdr *ethhdr; - err_t res; - u8_t *p; - - pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN, PBUF_RAM); - if (!pb) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - ethhdr = (struct eth_hdr *)pb->payload; - ethhdr->type = PP_HTONS(ETHTYPE_PPPOEDISC); - MEMCPY(ethhdr->dest.addr, dest, sizeof(ethhdr->dest.addr)); - MEMCPY(ethhdr->src.addr, ((struct eth_addr *)outgoing_if->hwaddr)->addr, sizeof(ethhdr->src.addr)); - - p = (u8_t*)(ethhdr + 1); - PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, session, 0); - - res = outgoing_if->linkoutput(outgoing_if, pb); - - pbuf_free(pb); - - return res; -} - -#ifdef PPPOE_SERVER -static err_t -pppoe_send_pado(struct pppoe_softc *sc) -{ - struct pbuf *pb; - u8_t *p; - size_t len; - - if (sc->sc_state != PPPOE_STATE_PADO_SENT) { - return ERR_CONN; - } - - /* calc length */ - len = 0; - /* include ac_cookie */ - len += 2 + 2 + sizeof(sc); - /* include hunique */ - len += 2 + 2 + sc->sc_hunique_len; - pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM); - if (!pb) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - p = (u8_t*)pb->payload + sizeof (struct eth_hdr); - PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len); - PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); - PPPOE_ADD_16(p, sizeof(sc)); - MEMCPY(p, &sc, sizeof(sc)); - p += sizeof(sc); - PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); - PPPOE_ADD_16(p, sc->sc_hunique_len); - MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); - return pppoe_output(sc, pb); -} - -static err_t -pppoe_send_pads(struct pppoe_softc *sc) -{ - struct pbuf *pb; - u8_t *p; - size_t len, l1 = 0; /* XXX: gcc */ - - if (sc->sc_state != PPPOE_STATE_PADO_SENT) { - return ERR_CONN; - } - - sc->sc_session = mono_time.tv_sec % 0xff + 1; - /* calc length */ - len = 0; - /* include hunique */ - len += 2 + 2 + 2 + 2 + sc->sc_hunique_len; /* service name, host unique*/ - if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ - l1 = strlen(sc->sc_service_name); - len += l1; - } - pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM); - if (!pb) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - p = (u8_t*)pb->payload + sizeof (struct eth_hdr); - PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len); - PPPOE_ADD_16(p, PPPOE_TAG_SNAME); - if (sc->sc_service_name != NULL) { - PPPOE_ADD_16(p, l1); - MEMCPY(p, sc->sc_service_name, l1); - p += l1; - } else { - PPPOE_ADD_16(p, 0); - } - PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); - PPPOE_ADD_16(p, sc->sc_hunique_len); - MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); - return pppoe_output(sc, pb); -} -#endif - -err_t -pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb) -{ - u8_t *p; - size_t len; - - /* are we ready to process data yet? */ - if (sc->sc_state < PPPOE_STATE_SESSION) { - /*sppp_flush(&sc->sc_sppp.pp_if);*/ - pbuf_free(pb); - return ERR_CONN; - } - - len = pb->tot_len; - - /* make room for Ethernet header - should not fail */ - if (pbuf_header(pb, sizeof(struct eth_hdr) + PPPOE_HEADERLEN) != 0) { - /* bail out */ - PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - LINK_STATS_INC(link.lenerr); - pbuf_free(pb); - return ERR_BUF; - } - - p = (u8_t*)pb->payload + sizeof(struct eth_hdr); - PPPOE_ADD_HEADER(p, 0, sc->sc_session, len); - - return pppoe_output(sc, pb); -} - -#if 0 /*def PFIL_HOOKS*/ -static int -pppoe_ifattach_hook(void *arg, struct pbuf **mp, struct netif *ifp, int dir) -{ - struct pppoe_softc *sc; - int s; - - if (mp != (struct pbuf **)PFIL_IFNET_DETACH) { - return 0; - } - - LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { - if (sc->sc_ethif != ifp) { - continue; - } - if (sc->sc_sppp.pp_if.if_flags & IFF_UP) { - sc->sc_sppp.pp_if.if_flags &= ~(IFF_UP|IFF_RUNNING); - printf("%c%c%"U16_F": ethernet interface detached, going down\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num); - } - sc->sc_ethif = NULL; - pppoe_clear_softc(sc, "ethernet interface detached"); - } - - return 0; -} -#endif - -static void -pppoe_clear_softc(struct pppoe_softc *sc, const char *message) -{ - LWIP_UNUSED_ARG(message); - - /* stop timer */ - sys_untimeout(pppoe_timeout, sc); - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message)); - - /* fix our state */ - sc->sc_state = PPPOE_STATE_INITIAL; - - /* notify upper layers */ - sc->sc_linkStatusCB(sc->sc_pd, 0); - - /* clean up softc */ - MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); - sc->sc_ac_cookie_len = 0; - sc->sc_session = 0; -} - -#endif /* PPPOE_SUPPORT */ - diff --git a/third_party/lwip/netif/ppp/pppdebug.h b/third_party/lwip/netif/ppp/pppdebug.h deleted file mode 100644 index 08ba7b5..0000000 --- a/third_party/lwip/netif/ppp/pppdebug.h +++ /dev/null @@ -1,73 +0,0 @@ -/***************************************************************************** -* pppdebug.h - System debugging utilities. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1998 Global Election Systems Inc. -* portions Copyright (c) 2001 by Cognizant Pty Ltd. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY (please don't use tabs!) -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 98-07-29 Guy Lancaster , Global Election Systems Inc. -* Original. -* -***************************************************************************** -*/ -#ifndef PPPDEBUG_H -#define PPPDEBUG_H - -/* Trace levels. */ -#define LOG_CRITICAL (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) -#define LOG_ERR (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) -#define LOG_NOTICE (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) -#define LOG_WARNING (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) -#define LOG_INFO (PPP_DEBUG) -#define LOG_DETAIL (PPP_DEBUG) -#define LOG_DEBUG (PPP_DEBUG) - - -#define TRACELCP PPP_DEBUG - -#if PPP_DEBUG - -#define AUTHDEBUG(a, b) LWIP_DEBUGF(a, b) -#define IPCPDEBUG(a, b) LWIP_DEBUGF(a, b) -#define UPAPDEBUG(a, b) LWIP_DEBUGF(a, b) -#define LCPDEBUG(a, b) LWIP_DEBUGF(a, b) -#define FSMDEBUG(a, b) LWIP_DEBUGF(a, b) -#define CHAPDEBUG(a, b) LWIP_DEBUGF(a, b) -#define PPPDEBUG(a, b) LWIP_DEBUGF(a, b) - -#else /* PPP_DEBUG */ - -#define AUTHDEBUG(a, b) -#define IPCPDEBUG(a, b) -#define UPAPDEBUG(a, b) -#define LCPDEBUG(a, b) -#define FSMDEBUG(a, b) -#define CHAPDEBUG(a, b) -#define PPPDEBUG(a, b) - -#endif /* PPP_DEBUG */ - -#endif /* PPPDEBUG_H */ diff --git a/third_party/lwip/netif/ppp/randm.c b/third_party/lwip/netif/ppp/randm.c deleted file mode 100644 index 09340f3..0000000 --- a/third_party/lwip/netif/ppp/randm.c +++ /dev/null @@ -1,249 +0,0 @@ -/***************************************************************************** -* randm.c - Random number generator program file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* Copyright (c) 1998 by Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 98-06-03 Guy Lancaster , Global Election Systems Inc. -* Extracted from avos. -*****************************************************************************/ - -#include "lwip/opt.h" - -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "md5.h" -#include "randm.h" - -#include "ppp_impl.h" -#include "pppdebug.h" - -#include - -#if MD5_SUPPORT /* this module depends on MD5 */ -#define RANDPOOLSZ 16 /* Bytes stored in the pool of randomness. */ - -/*****************************/ -/*** LOCAL DATA STRUCTURES ***/ -/*****************************/ -static char randPool[RANDPOOLSZ]; /* Pool of randomness. */ -static long randCount = 0; /* Pseudo-random incrementer */ - - -/***********************************/ -/*** PUBLIC FUNCTION DEFINITIONS ***/ -/***********************************/ -/* - * Initialize the random number generator. - * - * Since this is to be called on power up, we don't have much - * system randomess to work with. Here all we use is the - * real-time clock. We'll accumulate more randomness as soon - * as things start happening. - */ -void -avRandomInit() -{ - avChurnRand(NULL, 0); -} - -/* - * Churn the randomness pool on a random event. Call this early and often - * on random and semi-random system events to build randomness in time for - * usage. For randomly timed events, pass a null pointer and a zero length - * and this will use the system timer and other sources to add randomness. - * If new random data is available, pass a pointer to that and it will be - * included. - * - * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 - */ -void -avChurnRand(char *randData, u32_t randLen) -{ - MD5_CTX md5; - - /* LWIP_DEBUGF(LOG_INFO, ("churnRand: %u@%P\n", randLen, randData)); */ - MD5Init(&md5); - MD5Update(&md5, (u_char *)randPool, sizeof(randPool)); - if (randData) { - MD5Update(&md5, (u_char *)randData, randLen); - } else { - struct { - /* INCLUDE fields for any system sources of randomness */ - char foobar; - } sysData; - - /* Load sysData fields here. */ - MD5Update(&md5, (u_char *)&sysData, sizeof(sysData)); - } - MD5Final((u_char *)randPool, &md5); -/* LWIP_DEBUGF(LOG_INFO, ("churnRand: -> 0\n")); */ -} - -/* - * Use the random pool to generate random data. This degrades to pseudo - * random when used faster than randomness is supplied using churnRand(). - * Note: It's important that there be sufficient randomness in randPool - * before this is called for otherwise the range of the result may be - * narrow enough to make a search feasible. - * - * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 - * - * XXX Why does he not just call churnRand() for each block? Probably - * so that you don't ever publish the seed which could possibly help - * predict future values. - * XXX Why don't we preserve md5 between blocks and just update it with - * randCount each time? Probably there is a weakness but I wish that - * it was documented. - */ -void -avGenRand(char *buf, u32_t bufLen) -{ - MD5_CTX md5; - u_char tmp[16]; - u32_t n; - - while (bufLen > 0) { - n = LWIP_MIN(bufLen, RANDPOOLSZ); - MD5Init(&md5); - MD5Update(&md5, (u_char *)randPool, sizeof(randPool)); - MD5Update(&md5, (u_char *)&randCount, sizeof(randCount)); - MD5Final(tmp, &md5); - randCount++; - MEMCPY(buf, tmp, n); - buf += n; - bufLen -= n; - } -} - -/* - * Return a new random number. - */ -u32_t -avRandom() -{ - u32_t newRand; - - avGenRand((char *)&newRand, sizeof(newRand)); - - return newRand; -} - -#else /* MD5_SUPPORT */ - -/*****************************/ -/*** LOCAL DATA STRUCTURES ***/ -/*****************************/ -static int avRandomized = 0; /* Set when truely randomized. */ -static u32_t avRandomSeed = 0; /* Seed used for random number generation. */ - - -/***********************************/ -/*** PUBLIC FUNCTION DEFINITIONS ***/ -/***********************************/ -/* - * Initialize the random number generator. - * - * Here we attempt to compute a random number seed but even if - * it isn't random, we'll randomize it later. - * - * The current method uses the fields from the real time clock, - * the idle process counter, the millisecond counter, and the - * hardware timer tick counter. When this is invoked - * in startup(), then the idle counter and timer values may - * repeat after each boot and the real time clock may not be - * operational. Thus we call it again on the first random - * event. - */ -void -avRandomInit() -{ -#if 0 - /* Get a pointer into the last 4 bytes of clockBuf. */ - u32_t *lptr1 = (u32_t *)((char *)&clockBuf[3]); - - /* - * Initialize our seed using the real-time clock, the idle - * counter, the millisecond timer, and the hardware timer - * tick counter. The real-time clock and the hardware - * tick counter are the best sources of randomness but - * since the tick counter is only 16 bit (and truncated - * at that), the idle counter and millisecond timer - * (which may be small values) are added to help - * randomize the lower 16 bits of the seed. - */ - readClk(); - avRandomSeed += *(u32_t *)clockBuf + *lptr1 + OSIdleCtr - + ppp_mtime() + ((u32_t)TM1 << 16) + TM1; -#else - avRandomSeed += sys_jiffies(); /* XXX */ -#endif - - /* Initialize the Borland random number generator. */ - srand((unsigned)avRandomSeed); -} - -/* - * Randomize our random seed value. Here we use the fact that - * this function is called at *truely random* times by the polling - * and network functions. Here we only get 16 bits of new random - * value but we use the previous value to randomize the other 16 - * bits. - */ -void -avRandomize(void) -{ - static u32_t last_jiffies; - - if (!avRandomized) { - avRandomized = !0; - avRandomInit(); - /* The initialization function also updates the seed. */ - } else { - /* avRandomSeed += (avRandomSeed << 16) + TM1; */ - avRandomSeed += (sys_jiffies() - last_jiffies); /* XXX */ - } - last_jiffies = sys_jiffies(); -} - -/* - * Return a new random number. - * Here we use the Borland rand() function to supply a pseudo random - * number which we make truely random by combining it with our own - * seed which is randomized by truely random events. - * Thus the numbers will be truely random unless there have been no - * operator or network events in which case it will be pseudo random - * seeded by the real time clock. - */ -u32_t -avRandom() -{ - return ((((u32_t)rand() << 16) + rand()) + avRandomSeed); -} - -#endif /* MD5_SUPPORT */ - -#endif /* PPP_SUPPORT */ diff --git a/third_party/lwip/netif/ppp/randm.h b/third_party/lwip/netif/ppp/randm.h deleted file mode 100644 index 5fb99ef..0000000 --- a/third_party/lwip/netif/ppp/randm.h +++ /dev/null @@ -1,81 +0,0 @@ -/***************************************************************************** -* randm.h - Random number generator header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* Copyright (c) 1998 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE 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 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. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 98-05-29 Guy Lancaster , Global Election Systems Inc. -* Extracted from avos. -*****************************************************************************/ - -#ifndef RANDM_H -#define RANDM_H - -/*********************** -*** PUBLIC FUNCTIONS *** -***********************/ -/* - * Initialize the random number generator. - */ -void avRandomInit(void); - -/* - * Churn the randomness pool on a random event. Call this early and often - * on random and semi-random system events to build randomness in time for - * usage. For randomly timed events, pass a null pointer and a zero length - * and this will use the system timer and other sources to add randomness. - * If new random data is available, pass a pointer to that and it will be - * included. - */ -void avChurnRand(char *randData, u32_t randLen); - -/* - * Randomize our random seed value. To be called for truely random events - * such as user operations and network traffic. - */ -#if MD5_SUPPORT -#define avRandomize() avChurnRand(NULL, 0) -#else /* MD5_SUPPORT */ -void avRandomize(void); -#endif /* MD5_SUPPORT */ - -/* - * Use the random pool to generate random data. This degrades to pseudo - * random when used faster than randomness is supplied using churnRand(). - * Thus it's important to make sure that the results of this are not - * published directly because one could predict the next result to at - * least some degree. Also, it's important to get a good seed before - * the first use. - */ -void avGenRand(char *buf, u32_t bufLen); - -/* - * Return a new random number. - */ -u32_t avRandom(void); - - -#endif /* RANDM_H */ diff --git a/third_party/lwip/netif/ppp/readme.txt b/third_party/lwip/netif/ppp/readme.txt deleted file mode 100644 index 1895dc6..0000000 --- a/third_party/lwip/netif/ppp/readme.txt +++ /dev/null @@ -1,21 +0,0 @@ -About the PPP code: - -The PPP code is not our "own" code - we just copied it from pppd (http://ppp.samba.org/) and adapted it to lwIP. -Unfortunately, not many here know their way around it too well. Back in 2009, we took the effort to see which -version of pppd our code relates to and we're pretty much on 2.3.11 with some bugs from 2.4.x backported. - -Aside from simple code adaptions, there are some files that are different, however: -- chpms.c/.h are named chap_ms.c/.h in the original pppd 2.3.11 sources -- pap.c/.h are named upap.c/.h in the original pppd 2.3.11 sources -- randm.c is a random generator not included in the original pppd -- magic.c does not use the C library's random functions, but uses randm.c instead -- vj.c/.h is an implementation of the Van Jacobson header compression algorithm adapted to lwIP pbufs, - probably copied from one of the vjcompress.c files from pppd. -- ppp.c, ppp.h and ppp_impl.h contain the adaption from pppd to lwIP. This is the "OS"-dependent part like there - is an implementation for linux, xBSD etc. in the pppd sources. -- ppp_oe.c is Marc Boucher's implementation based on NetBSD's if_pppoe.c - -There is of course potential for bugs in it, but when analyzing of reporting bugs, it is strongly encouraged to -compare the code in question to pppd 2.3.11 (our basis) and newer versions (perhaps it's already fixed?) and to -share this knowledge with us when reporting a bug. - diff --git a/third_party/lwip/netif/ppp/vj.c b/third_party/lwip/netif/ppp/vj.c deleted file mode 100644 index 6bed149..0000000 --- a/third_party/lwip/netif/ppp/vj.c +++ /dev/null @@ -1,652 +0,0 @@ -/* - * Routines to compress and uncompess tcp packets (for transmission - * over low speed serial lines. - * - * Copyright (c) 1989 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: - * Initial distribution. - * - * Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au, - * so that the entire packet being decompressed doesn't have - * to be in contiguous memory (just the compressed header). - * - * Modified March 1998 by Guy Lancaster, glanca@gesn.com, - * for a 16 bit processor. - */ - -#include "lwip/opt.h" - -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "ppp_impl.h" -#include "pppdebug.h" - -#include "vj.h" - -#include - -#if VJ_SUPPORT - -#if LINK_STATS -#define INCR(counter) ++comp->stats.counter -#else -#define INCR(counter) -#endif - -void -vj_compress_init(struct vjcompress *comp) -{ - register u_char i; - register struct cstate *tstate = comp->tstate; - -#if MAX_SLOTS == 0 - memset((char *)comp, 0, sizeof(*comp)); -#endif - comp->maxSlotIndex = MAX_SLOTS - 1; - comp->compressSlot = 0; /* Disable slot ID compression by default. */ - for (i = MAX_SLOTS - 1; i > 0; --i) { - tstate[i].cs_id = i; - tstate[i].cs_next = &tstate[i - 1]; - } - tstate[0].cs_next = &tstate[MAX_SLOTS - 1]; - tstate[0].cs_id = 0; - comp->last_cs = &tstate[0]; - comp->last_recv = 255; - comp->last_xmit = 255; - comp->flags = VJF_TOSS; -} - - -/* ENCODE encodes a number that is known to be non-zero. ENCODEZ - * checks for zero (since zero has to be encoded in the long, 3 byte - * form). - */ -#define ENCODE(n) { \ - if ((u_short)(n) >= 256) { \ - *cp++ = 0; \ - cp[1] = (u_char)(n); \ - cp[0] = (u_char)((n) >> 8); \ - cp += 2; \ - } else { \ - *cp++ = (u_char)(n); \ - } \ -} -#define ENCODEZ(n) { \ - if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \ - *cp++ = 0; \ - cp[1] = (u_char)(n); \ - cp[0] = (u_char)((n) >> 8); \ - cp += 2; \ - } else { \ - *cp++ = (u_char)(n); \ - } \ -} - -#define DECODEL(f) { \ - if (*cp == 0) {\ - u32_t tmp = ntohl(f) + ((cp[1] << 8) | cp[2]); \ - (f) = htonl(tmp); \ - cp += 3; \ - } else { \ - u32_t tmp = ntohl(f) + (u32_t)*cp++; \ - (f) = htonl(tmp); \ - } \ -} - -#define DECODES(f) { \ - if (*cp == 0) {\ - u_short tmp = ntohs(f) + (((u_short)cp[1] << 8) | cp[2]); \ - (f) = htons(tmp); \ - cp += 3; \ - } else { \ - u_short tmp = ntohs(f) + (u_short)*cp++; \ - (f) = htons(tmp); \ - } \ -} - -#define DECODEU(f) { \ - if (*cp == 0) {\ - (f) = htons(((u_short)cp[1] << 8) | cp[2]); \ - cp += 3; \ - } else { \ - (f) = htons((u_short)*cp++); \ - } \ -} - -/* - * vj_compress_tcp - Attempt to do Van Jacobson header compression on a - * packet. This assumes that nb and comp are not null and that the first - * buffer of the chain contains a valid IP header. - * Return the VJ type code indicating whether or not the packet was - * compressed. - */ -u_int -vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) -{ - register struct ip_hdr *ip = (struct ip_hdr *)pb->payload; - register struct cstate *cs = comp->last_cs->cs_next; - register u_short hlen = IPH_HL(ip); - register struct tcp_hdr *oth; - register struct tcp_hdr *th; - register u_short deltaS, deltaA; - register u_long deltaL; - register u_int changes = 0; - u_char new_seq[16]; - register u_char *cp = new_seq; - - /* - * Check that the packet is IP proto TCP. - */ - if (IPH_PROTO(ip) != IP_PROTO_TCP) { - return (TYPE_IP); - } - - /* - * Bail if this is an IP fragment or if the TCP packet isn't - * `compressible' (i.e., ACK isn't set or some other control bit is - * set). - */ - if ((IPH_OFFSET(ip) & PP_HTONS(0x3fff)) || pb->tot_len < 40) { - return (TYPE_IP); - } - th = (struct tcp_hdr *)&((long *)ip)[hlen]; - if ((TCPH_FLAGS(th) & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) { - return (TYPE_IP); - } - /* - * Packet is compressible -- we're going to send either a - * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need - * to locate (or create) the connection state. Special case the - * most recently used connection since it's most likely to be used - * again & we don't have to do any reordering if it's used. - */ - INCR(vjs_packets); - if (!ip_addr_cmp(&ip->src, &cs->cs_ip.src) - || !ip_addr_cmp(&ip->dest, &cs->cs_ip.dest) - || *(long *)th != ((long *)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) { - /* - * Wasn't the first -- search for it. - * - * States are kept in a circularly linked list with - * last_cs pointing to the end of the list. The - * list is kept in lru order by moving a state to the - * head of the list whenever it is referenced. Since - * the list is short and, empirically, the connection - * we want is almost always near the front, we locate - * states via linear search. If we don't find a state - * for the datagram, the oldest state is (re-)used. - */ - register struct cstate *lcs; - register struct cstate *lastcs = comp->last_cs; - - do { - lcs = cs; cs = cs->cs_next; - INCR(vjs_searches); - if (ip_addr_cmp(&ip->src, &cs->cs_ip.src) - && ip_addr_cmp(&ip->dest, &cs->cs_ip.dest) - && *(long *)th == ((long *)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) { - goto found; - } - } while (cs != lastcs); - - /* - * Didn't find it -- re-use oldest cstate. Send an - * uncompressed packet that tells the other side what - * connection number we're using for this conversation. - * Note that since the state list is circular, the oldest - * state points to the newest and we only need to set - * last_cs to update the lru linkage. - */ - INCR(vjs_misses); - comp->last_cs = lcs; - hlen += TCPH_HDRLEN(th); - hlen <<= 2; - /* Check that the IP/TCP headers are contained in the first buffer. */ - if (hlen > pb->len) { - return (TYPE_IP); - } - goto uncompressed; - - found: - /* - * Found it -- move to the front on the connection list. - */ - if (cs == lastcs) { - comp->last_cs = lcs; - } else { - lcs->cs_next = cs->cs_next; - cs->cs_next = lastcs->cs_next; - lastcs->cs_next = cs; - } - } - - oth = (struct tcp_hdr *)&((long *)&cs->cs_ip)[hlen]; - deltaS = hlen; - hlen += TCPH_HDRLEN(th); - hlen <<= 2; - /* Check that the IP/TCP headers are contained in the first buffer. */ - if (hlen > pb->len) { - PPPDEBUG(LOG_INFO, ("vj_compress_tcp: header len %d spans buffers\n", hlen)); - return (TYPE_IP); - } - - /* - * Make sure that only what we expect to change changed. The first - * line of the `if' checks the IP protocol version, header length & - * type of service. The 2nd line checks the "Don't fragment" bit. - * The 3rd line checks the time-to-live and protocol (the protocol - * check is unnecessary but costless). The 4th line checks the TCP - * header length. The 5th line checks IP options, if any. The 6th - * line checks TCP options, if any. If any of these things are - * different between the previous & current datagram, we send the - * current datagram `uncompressed'. - */ - if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0] - || ((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3] - || ((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4] - || TCPH_HDRLEN(th) != TCPH_HDRLEN(oth) - || (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) - || (TCPH_HDRLEN(th) > 5 && BCMP(th + 1, oth + 1, (TCPH_HDRLEN(th) - 5) << 2))) { - goto uncompressed; - } - - /* - * Figure out which of the changing fields changed. The - * receiver expects changes in the order: urgent, window, - * ack, seq (the order minimizes the number of temporaries - * needed in this section of code). - */ - if (TCPH_FLAGS(th) & TCP_URG) { - deltaS = ntohs(th->urgp); - ENCODEZ(deltaS); - changes |= NEW_U; - } else if (th->urgp != oth->urgp) { - /* argh! URG not set but urp changed -- a sensible - * implementation should never do this but RFC793 - * doesn't prohibit the change so we have to deal - * with it. */ - goto uncompressed; - } - - if ((deltaS = (u_short)(ntohs(th->wnd) - ntohs(oth->wnd))) != 0) { - ENCODE(deltaS); - changes |= NEW_W; - } - - if ((deltaL = ntohl(th->ackno) - ntohl(oth->ackno)) != 0) { - if (deltaL > 0xffff) { - goto uncompressed; - } - deltaA = (u_short)deltaL; - ENCODE(deltaA); - changes |= NEW_A; - } - - if ((deltaL = ntohl(th->seqno) - ntohl(oth->seqno)) != 0) { - if (deltaL > 0xffff) { - goto uncompressed; - } - deltaS = (u_short)deltaL; - ENCODE(deltaS); - changes |= NEW_S; - } - - switch(changes) { - case 0: - /* - * Nothing changed. If this packet contains data and the - * last one didn't, this is probably a data packet following - * an ack (normal on an interactive connection) and we send - * it compressed. Otherwise it's probably a retransmit, - * retransmitted ack or window probe. Send it uncompressed - * in case the other side missed the compressed version. - */ - if (IPH_LEN(ip) != IPH_LEN(&cs->cs_ip) && - ntohs(IPH_LEN(&cs->cs_ip)) == hlen) { - break; - } - - /* (fall through) */ - - case SPECIAL_I: - case SPECIAL_D: - /* - * actual changes match one of our special case encodings -- - * send packet uncompressed. - */ - goto uncompressed; - - case NEW_S|NEW_A: - if (deltaS == deltaA && deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { - /* special case for echoed terminal traffic */ - changes = SPECIAL_I; - cp = new_seq; - } - break; - - case NEW_S: - if (deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { - /* special case for data xfer */ - changes = SPECIAL_D; - cp = new_seq; - } - break; - } - - deltaS = (u_short)(ntohs(IPH_ID(ip)) - ntohs(IPH_ID(&cs->cs_ip))); - if (deltaS != 1) { - ENCODEZ(deltaS); - changes |= NEW_I; - } - if (TCPH_FLAGS(th) & TCP_PSH) { - changes |= TCP_PUSH_BIT; - } - /* - * Grab the cksum before we overwrite it below. Then update our - * state with this packet's header. - */ - deltaA = ntohs(th->chksum); - BCOPY(ip, &cs->cs_ip, hlen); - - /* - * We want to use the original packet as our compressed packet. - * (cp - new_seq) is the number of bytes we need for compressed - * sequence numbers. In addition we need one byte for the change - * mask, one for the connection id and two for the tcp checksum. - * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how - * many bytes of the original packet to toss so subtract the two to - * get the new packet size. - */ - deltaS = (u_short)(cp - new_seq); - if (!comp->compressSlot || comp->last_xmit != cs->cs_id) { - comp->last_xmit = cs->cs_id; - hlen -= deltaS + 4; - if(pbuf_header(pb, -hlen)){ - /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_header failed\n", 0); - } - cp = (u_char *)pb->payload; - *cp++ = (u_char)(changes | NEW_C); - *cp++ = cs->cs_id; - } else { - hlen -= deltaS + 3; - if(pbuf_header(pb, -hlen)) { - /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_header failed\n", 0); - } - cp = (u_char *)pb->payload; - *cp++ = (u_char)changes; - } - *cp++ = (u_char)(deltaA >> 8); - *cp++ = (u_char)deltaA; - BCOPY(new_seq, cp, deltaS); - INCR(vjs_compressed); - return (TYPE_COMPRESSED_TCP); - - /* - * Update connection state cs & send uncompressed packet (that is, - * a regular ip/tcp packet but with the 'conversation id' we hope - * to use on future compressed packets in the protocol field). - */ -uncompressed: - BCOPY(ip, &cs->cs_ip, hlen); - IPH_PROTO_SET(ip, cs->cs_id); - comp->last_xmit = cs->cs_id; - return (TYPE_UNCOMPRESSED_TCP); -} - -/* - * Called when we may have missed a packet. - */ -void -vj_uncompress_err(struct vjcompress *comp) -{ - comp->flags |= VJF_TOSS; - INCR(vjs_errorin); -} - -/* - * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP. - * Return 0 on success, -1 on failure. - */ -int -vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp) -{ - register u_int hlen; - register struct cstate *cs; - register struct ip_hdr *ip; - - ip = (struct ip_hdr *)nb->payload; - hlen = IPH_HL(ip) << 2; - if (IPH_PROTO(ip) >= MAX_SLOTS - || hlen + sizeof(struct tcp_hdr) > nb->len - || (hlen += TCPH_HDRLEN(((struct tcp_hdr *)&((char *)ip)[hlen])) << 2) - > nb->len - || hlen > MAX_HDR) { - PPPDEBUG(LOG_INFO, ("vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n", - IPH_PROTO(ip), hlen, nb->len)); - comp->flags |= VJF_TOSS; - INCR(vjs_errorin); - return -1; - } - cs = &comp->rstate[comp->last_recv = IPH_PROTO(ip)]; - comp->flags &=~ VJF_TOSS; - IPH_PROTO_SET(ip, IP_PROTO_TCP); - BCOPY(ip, &cs->cs_ip, hlen); - cs->cs_hlen = (u_short)hlen; - INCR(vjs_uncompressedin); - return 0; -} - -/* - * Uncompress a packet of type TYPE_COMPRESSED_TCP. - * The packet is composed of a buffer chain and the first buffer - * must contain an accurate chain length. - * The first buffer must include the entire compressed TCP/IP header. - * This procedure replaces the compressed header with the uncompressed - * header and returns the length of the VJ header. - */ -int -vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) -{ - u_char *cp; - struct tcp_hdr *th; - struct cstate *cs; - u_short *bp; - struct pbuf *n0 = *nb; - u32_t tmp; - u_int vjlen, hlen, changes; - - INCR(vjs_compressedin); - cp = (u_char *)n0->payload; - changes = *cp++; - if (changes & NEW_C) { - /* - * Make sure the state index is in range, then grab the state. - * If we have a good state index, clear the 'discard' flag. - */ - if (*cp >= MAX_SLOTS) { - PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: bad cid=%d\n", *cp)); - goto bad; - } - - comp->flags &=~ VJF_TOSS; - comp->last_recv = *cp++; - } else { - /* - * this packet has an implicit state index. If we've - * had a line error since the last time we got an - * explicit state index, we have to toss the packet. - */ - if (comp->flags & VJF_TOSS) { - PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: tossing\n")); - INCR(vjs_tossed); - return (-1); - } - } - cs = &comp->rstate[comp->last_recv]; - hlen = IPH_HL(&cs->cs_ip) << 2; - th = (struct tcp_hdr *)&((u_char *)&cs->cs_ip)[hlen]; - th->chksum = htons((*cp << 8) | cp[1]); - cp += 2; - if (changes & TCP_PUSH_BIT) { - TCPH_SET_FLAG(th, TCP_PSH); - } else { - TCPH_UNSET_FLAG(th, TCP_PSH); - } - - switch (changes & SPECIALS_MASK) { - case SPECIAL_I: - { - register u32_t i = ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; - /* some compilers can't nest inline assembler.. */ - tmp = ntohl(th->ackno) + i; - th->ackno = htonl(tmp); - tmp = ntohl(th->seqno) + i; - th->seqno = htonl(tmp); - } - break; - - case SPECIAL_D: - /* some compilers can't nest inline assembler.. */ - tmp = ntohl(th->seqno) + ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; - th->seqno = htonl(tmp); - break; - - default: - if (changes & NEW_U) { - TCPH_SET_FLAG(th, TCP_URG); - DECODEU(th->urgp); - } else { - TCPH_UNSET_FLAG(th, TCP_URG); - } - if (changes & NEW_W) { - DECODES(th->wnd); - } - if (changes & NEW_A) { - DECODEL(th->ackno); - } - if (changes & NEW_S) { - DECODEL(th->seqno); - } - break; - } - if (changes & NEW_I) { - DECODES(cs->cs_ip._id); - } else { - IPH_ID_SET(&cs->cs_ip, ntohs(IPH_ID(&cs->cs_ip)) + 1); - IPH_ID_SET(&cs->cs_ip, htons(IPH_ID(&cs->cs_ip))); - } - - /* - * At this point, cp points to the first byte of data in the - * packet. Fill in the IP total length and update the IP - * header checksum. - */ - vjlen = (u_short)(cp - (u_char*)n0->payload); - if (n0->len < vjlen) { - /* - * We must have dropped some characters (crc should detect - * this but the old slip framing won't) - */ - PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: head buffer %d too short %d\n", - n0->len, vjlen)); - goto bad; - } - -#if BYTE_ORDER == LITTLE_ENDIAN - tmp = n0->tot_len - vjlen + cs->cs_hlen; - IPH_LEN_SET(&cs->cs_ip, htons((u_short)tmp)); -#else - IPH_LEN_SET(&cs->cs_ip, htons(n0->tot_len - vjlen + cs->cs_hlen)); -#endif - - /* recompute the ip header checksum */ - bp = (u_short *) &cs->cs_ip; - IPH_CHKSUM_SET(&cs->cs_ip, 0); - for (tmp = 0; hlen > 0; hlen -= 2) { - tmp += *bp++; - } - tmp = (tmp & 0xffff) + (tmp >> 16); - tmp = (tmp & 0xffff) + (tmp >> 16); - IPH_CHKSUM_SET(&cs->cs_ip, (u_short)(~tmp)); - - /* Remove the compressed header and prepend the uncompressed header. */ - if(pbuf_header(n0, -((s16_t)(vjlen)))) { - /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_header failed\n", 0); - goto bad; - } - - if(LWIP_MEM_ALIGN(n0->payload) != n0->payload) { - struct pbuf *np, *q; - u8_t *bufptr; - - np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL); - if(!np) { - PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: realign failed\n")); - goto bad; - } - - if(pbuf_header(np, -cs->cs_hlen)) { - /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_header failed\n", 0); - goto bad; - } - - bufptr = n0->payload; - for(q = np; q != NULL; q = q->next) { - MEMCPY(q->payload, bufptr, q->len); - bufptr += q->len; - } - - if(n0->next) { - pbuf_chain(np, n0->next); - pbuf_dechain(n0); - } - pbuf_free(n0); - n0 = np; - } - - if(pbuf_header(n0, cs->cs_hlen)) { - struct pbuf *np; - - LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE); - np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL); - if(!np) { - PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: prepend failed\n")); - goto bad; - } - pbuf_cat(np, n0); - n0 = np; - } - LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen); - MEMCPY(n0->payload, &cs->cs_ip, cs->cs_hlen); - - *nb = n0; - - return vjlen; - -bad: - comp->flags |= VJF_TOSS; - INCR(vjs_errorin); - return (-1); -} - -#endif /* VJ_SUPPORT */ - -#endif /* PPP_SUPPORT */ diff --git a/third_party/lwip/netif/ppp/vj.h b/third_party/lwip/netif/ppp/vj.h deleted file mode 100644 index 373fd93..0000000 --- a/third_party/lwip/netif/ppp/vj.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Definitions for tcp compression routines. - * - * $Id: vj.h,v 1.7 2010/02/22 17:52:09 goldsimon Exp $ - * - * Copyright (c) 1989 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: - * - Initial distribution. - */ - -#ifndef VJ_H -#define VJ_H - -#include "lwip/ip.h" -#include "lwip/tcp_impl.h" - -#define MAX_SLOTS 16 /* must be > 2 and < 256 */ -#define MAX_HDR 128 - -/* - * Compressed packet format: - * - * The first octet contains the packet type (top 3 bits), TCP - * 'push' bit, and flags that indicate which of the 4 TCP sequence - * numbers have changed (bottom 5 bits). The next octet is a - * conversation number that associates a saved IP/TCP header with - * the compressed packet. The next two octets are the TCP checksum - * from the original datagram. The next 0 to 15 octets are - * sequence number changes, one change per bit set in the header - * (there may be no changes and there are two special cases where - * the receiver implicitly knows what changed -- see below). - * - * There are 5 numbers which can change (they are always inserted - * in the following order): TCP urgent pointer, window, - * acknowlegement, sequence number and IP ID. (The urgent pointer - * is different from the others in that its value is sent, not the - * change in value.) Since typical use of SLIP links is biased - * toward small packets (see comments on MTU/MSS below), changes - * use a variable length coding with one octet for numbers in the - * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the - * range 256 - 65535 or 0. (If the change in sequence number or - * ack is more than 65535, an uncompressed packet is sent.) - */ - -/* - * Packet types (must not conflict with IP protocol version) - * - * The top nibble of the first octet is the packet type. There are - * three possible types: IP (not proto TCP or tcp with one of the - * control flags set); uncompressed TCP (a normal IP/TCP packet but - * with the 8-bit protocol field replaced by an 8-bit connection id -- - * this type of packet syncs the sender & receiver); and compressed - * TCP (described above). - * - * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and - * is logically part of the 4-bit "changes" field that follows. Top - * three bits are actual packet type. For backward compatibility - * and in the interest of conserving bits, numbers are chosen so the - * IP protocol version number (4) which normally appears in this nibble - * means "IP packet". - */ - -/* packet types */ -#define TYPE_IP 0x40 -#define TYPE_UNCOMPRESSED_TCP 0x70 -#define TYPE_COMPRESSED_TCP 0x80 -#define TYPE_ERROR 0x00 - -/* Bits in first octet of compressed packet */ -#define NEW_C 0x40 /* flag bits for what changed in a packet */ -#define NEW_I 0x20 -#define NEW_S 0x08 -#define NEW_A 0x04 -#define NEW_W 0x02 -#define NEW_U 0x01 - -/* reserved, special-case values of above */ -#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */ -#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */ -#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U) - -#define TCP_PUSH_BIT 0x10 - - -/* - * "state" data for each active tcp conversation on the wire. This is - * basically a copy of the entire IP/TCP header from the last packet - * we saw from the conversation together with a small identifier - * the transmit & receive ends of the line use to locate saved header. - */ -struct cstate { - struct cstate *cs_next; /* next most recently used state (xmit only) */ - u_short cs_hlen; /* size of hdr (receive only) */ - u_char cs_id; /* connection # associated with this state */ - u_char cs_filler; - union { - char csu_hdr[MAX_HDR]; - struct ip_hdr csu_ip; /* ip/tcp hdr from most recent packet */ - } vjcs_u; -}; -#define cs_ip vjcs_u.csu_ip -#define cs_hdr vjcs_u.csu_hdr - - -struct vjstat { - unsigned long vjs_packets; /* outbound packets */ - unsigned long vjs_compressed; /* outbound compressed packets */ - unsigned long vjs_searches; /* searches for connection state */ - unsigned long vjs_misses; /* times couldn't find conn. state */ - unsigned long vjs_uncompressedin; /* inbound uncompressed packets */ - unsigned long vjs_compressedin; /* inbound compressed packets */ - unsigned long vjs_errorin; /* inbound unknown type packets */ - unsigned long vjs_tossed; /* inbound packets tossed because of error */ -}; - -/* - * all the state data for one serial line (we need one of these per line). - */ -struct vjcompress { - struct cstate *last_cs; /* most recently used tstate */ - u_char last_recv; /* last rcvd conn. id */ - u_char last_xmit; /* last sent conn. id */ - u_short flags; - u_char maxSlotIndex; - u_char compressSlot; /* Flag indicating OK to compress slot ID. */ -#if LINK_STATS - struct vjstat stats; -#endif - struct cstate tstate[MAX_SLOTS]; /* xmit connection states */ - struct cstate rstate[MAX_SLOTS]; /* receive connection states */ -}; - -/* flag values */ -#define VJF_TOSS 1U /* tossing rcvd frames because of input err */ - -extern void vj_compress_init (struct vjcompress *comp); -extern u_int vj_compress_tcp (struct vjcompress *comp, struct pbuf *pb); -extern void vj_uncompress_err (struct vjcompress *comp); -extern int vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp); -extern int vj_uncompress_tcp (struct pbuf **nb, struct vjcompress *comp); - -#endif /* VJ_H */ diff --git a/third_party/lwip/netif/slipif.c b/third_party/lwip/netif/slipif.c deleted file mode 100644 index a73f6bf..0000000 --- a/third_party/lwip/netif/slipif.c +++ /dev/null @@ -1,546 +0,0 @@ -/** - * @file - * SLIP Interface - * - */ - -/* - * 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. 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 built upon the file: src/arch/rtxc/netif/sioslip.c - * - * Author: Magnus Ivarsson - * Simon Goldschmidt - * - * Usage: This netif can be used in three ways: - * 1) For NO_SYS==0, an RX thread can be used which blocks on sio_read() - * until data is received. - * 2) In your main loop, call slipif_poll() to check for new RX bytes, - * completed packets are fed into netif->input(). - * 3) Call slipif_received_byte[s]() from your serial RX ISR and - * slipif_process_rxqueue() from your main loop. ISR level decodes - * packets and puts completed packets on a queue which is fed into - * the stack from the main loop (needs SYS_LIGHTWEIGHT_PROT for - * pbuf_alloc to work on ISR level!). - * - */ - -/* - * This is an arch independent SLIP netif. The specific serial hooks must be - * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send - */ - -#include "netif/slipif.h" -#include "lwip/opt.h" - -#if LWIP_HAVE_SLIPIF - -#include "lwip/def.h" -#include "lwip/pbuf.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/sio.h" -#include "lwip/sys.h" - -#define SLIP_END 0xC0 /* 0300: start and end of every packet */ -#define SLIP_ESC 0xDB /* 0333: escape start (one byte escaped data follows) */ -#define SLIP_ESC_END 0xDC /* 0334: following escape: original byte is 0xC0 (END) */ -#define SLIP_ESC_ESC 0xDD /* 0335: following escape: original byte is 0xDB (ESC) */ - -/** Maximum packet size that is received by this netif */ -#ifndef SLIP_MAX_SIZE -#define SLIP_MAX_SIZE 1500 -#endif - -/** Define this to the interface speed for SNMP - * (sio_fd is the sio_fd_t returned by sio_open). - * The default value of zero means 'unknown'. - */ -#ifndef SLIP_SIO_SPEED -#define SLIP_SIO_SPEED(sio_fd) 0 -#endif - -enum slipif_recv_state { - SLIP_RECV_NORMAL, - SLIP_RECV_ESCAPE, -}; - -struct slipif_priv { - sio_fd_t sd; - /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */ - struct pbuf *p, *q; - u8_t state; - u16_t i, recved; -#if SLIP_RX_FROM_ISR - struct pbuf *rxpackets; -#endif -}; - -/** - * Send a pbuf doing the necessary SLIP encapsulation - * - * Uses the serial layer's sio_send() - * - * @param netif the lwip network interface structure for this slipif - * @param p the pbuf chaing packet to send - * @return always returns ERR_OK since the serial layer does not provide return values - */ -static err_t ICACHE_FLASH_ATTR -slipif_output(struct netif *netif, struct pbuf *p) -{ - struct slipif_priv *priv; - struct pbuf *q; - u16_t i; - u8_t c; - - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - LWIP_ASSERT("p != NULL", (p != NULL)); - - LWIP_DEBUGF(SLIP_DEBUG, ("slipif_output(%"U16_F"): sending %"U16_F" bytes\n", (u16_t)netif->num, p->tot_len)); - priv = netif->state; - - /* Send pbuf out on the serial I/O device. */ - /* Start with packet delimiter. */ - sio_send(SLIP_END, priv->sd); - - for (q = p; q != NULL; q = q->next) { - for (i = 0; i < q->len; i++) { - c = ((u8_t *)q->payload)[i]; - switch (c) { - case SLIP_END: - /* need to escape this byte (0xC0 -> 0xDB, 0xDC) */ - sio_send(SLIP_ESC, priv->sd); - sio_send(SLIP_ESC_END, priv->sd); - break; - case SLIP_ESC: - /* need to escape this byte (0xDB -> 0xDB, 0xDD) */ - sio_send(SLIP_ESC, priv->sd); - sio_send(SLIP_ESC_ESC, priv->sd); - break; - default: - /* normal byte - no need for escaping */ - sio_send(c, priv->sd); - break; - } - } - } - /* End with packet delimiter. */ - sio_send(SLIP_END, priv->sd); - return ERR_OK; -} - -/** - * Send a pbuf doing the necessary SLIP encapsulation - * - * Uses the serial layer's sio_send() - * - * @param netif the lwip network interface structure for this slipif - * @param p the pbuf chaing packet to send - * @param ipaddr the ip address to send the packet to (not used for slipif) - * @return always returns ERR_OK since the serial layer does not provide return values - */ -static err_t ICACHE_FLASH_ATTR -slipif_output_v4(struct netif *netif, struct pbuf *p, ip_addr_t *ipaddr) -{ - LWIP_UNUSED_ARG(ipaddr); - return slipif_output(netif, p); -} - -#if LWIP_IPV6 -/** - * Send a pbuf doing the necessary SLIP encapsulation - * - * Uses the serial layer's sio_send() - * - * @param netif the lwip network interface structure for this slipif - * @param p the pbuf chaing packet to send - * @param ipaddr the ip address to send the packet to (not used for slipif) - * @return always returns ERR_OK since the serial layer does not provide return values - */ -static err_t ICACHE_FLASH_ATTR -slipif_output_v6(struct netif *netif, struct pbuf *p, ip6_addr_t *ipaddr) -{ - LWIP_UNUSED_ARG(ipaddr); - return slipif_output(netif, p); -} -#endif /* LWIP_IPV6 */ - -/** - * Handle the incoming SLIP stream character by character - * - * @param netif the lwip network interface structure for this slipif - * @param c received character (multiple calls to this function will - * return a complete packet, NULL is returned before - used for polling) - * @return The IP packet when SLIP_END is received - */ -static struct pbuf* ICACHE_FLASH_ATTR -slipif_rxbyte(struct netif *netif, u8_t c) -{ - struct slipif_priv *priv; - struct pbuf *t; - - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - - priv = netif->state; - - switch (priv->state) { - case SLIP_RECV_NORMAL: - switch (c) { - case SLIP_END: - if (priv->recved > 0) { - /* Received whole packet. */ - /* Trim the pbuf to the size of the received packet. */ - pbuf_realloc(priv->q, priv->recved); - - LINK_STATS_INC(link.recv); - - LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet (%"U16_F" bytes)\n", priv->recved)); - t = priv->q; - priv->p = priv->q = NULL; - priv->i = priv->recved = 0; - return t; - } - return NULL; - case SLIP_ESC: - priv->state = SLIP_RECV_ESCAPE; - return NULL; - } /* end switch (c) */ - break; - case SLIP_RECV_ESCAPE: - /* un-escape END or ESC bytes, leave other bytes - (although that would be a protocol error) */ - switch (c) { - case SLIP_ESC_END: - c = SLIP_END; - break; - case SLIP_ESC_ESC: - c = SLIP_ESC; - break; - } - priv->state = SLIP_RECV_NORMAL; - break; - } /* end switch (priv->state) */ - - /* byte received, packet not yet completely received */ - if (priv->p == NULL) { - /* allocate a new pbuf */ - LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); - priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN), PBUF_POOL); - - if (priv->p == NULL) { - LINK_STATS_INC(link.drop); - LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); - /* don't process any further since we got no pbuf to receive to */ - return NULL; - } - - if (priv->q != NULL) { - /* 'chain' the pbuf to the existing chain */ - pbuf_cat(priv->q, priv->p); - } else { - /* p is the first pbuf in the chain */ - priv->q = priv->p; - } - } - - /* this automatically drops bytes if > SLIP_MAX_SIZE */ - if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) { - ((u8_t *)priv->p->payload)[priv->i] = c; - priv->recved++; - priv->i++; - if (priv->i >= priv->p->len) { - /* on to the next pbuf */ - priv->i = 0; - if (priv->p->next != NULL && priv->p->next->len > 0) { - /* p is a chain, on to the next in the chain */ - priv->p = priv->p->next; - } else { - /* p is a single pbuf, set it to NULL so next time a new - * pbuf is allocated */ - priv->p = NULL; - } - } - } - return NULL; -} - -/** Like slipif_rxbyte, but passes completed packets to netif->input - * - * @param netif The lwip network interface structure for this slipif - * @param data received character - */ -static void ICACHE_FLASH_ATTR -slipif_rxbyte_input(struct netif *netif, u8_t c) -{ - struct pbuf *p; - p = slipif_rxbyte(netif, c); - if (p != NULL) { - if (netif->input(p, netif) != ERR_OK) { - pbuf_free(p); - } - } -} - -#if SLIP_USE_RX_THREAD -/** - * The SLIP input thread. - * - * Feed the IP layer with incoming packets - * - * @param nf the lwip network interface structure for this slipif - */ -static void ICACHE_FLASH_ATTR -slipif_loop_thread(void *nf) -{ - u8_t c; - struct netif *netif = (struct netif *)nf; - struct slipif_priv *priv = (struct slipif_priv *)netif->state; - - while (1) { - if (sio_read(priv->sd, &c, 1) > 0) { - slipif_rxbyte_input(netif, c); - } - } -} -#endif /* SLIP_USE_RX_THREAD */ - -/** - * SLIP netif initialization - * - * Call the arch specific sio_open and remember - * the opened device in the state field of the netif. - * - * @param netif the lwip network interface structure for this slipif - * @return ERR_OK if serial line could be opened, - * ERR_MEM if no memory could be allocated, - * ERR_IF is serial line couldn't be opened - * - * @note netif->num must contain the number of the serial port to open - * (0 by default). If netif->state is != NULL, it is interpreted as an - * u8_t pointer pointing to the serial port number instead of netif->num. - * - */ -err_t ICACHE_FLASH_ATTR -slipif_init(struct netif *netif) -{ - struct slipif_priv *priv; - u8_t sio_num; - - LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num)); - - /* Allocate private data */ - priv = (struct slipif_priv *)mem_malloc(sizeof(struct slipif_priv)); - if (!priv) { - return ERR_MEM; - } - - netif->name[0] = 's'; - netif->name[1] = 'l'; - netif->output = slipif_output_v4; -#if LWIP_IPV6 - netif->output_ip6 = slipif_output_v6; -#endif /* LWIP_IPV6 */ - netif->mtu = SLIP_MAX_SIZE; - netif->flags |= NETIF_FLAG_POINTTOPOINT; - - /* netif->state or netif->num contain the port number */ - if (netif->state != NULL) { - sio_num = *(u8_t*)netif->state; - } else { - sio_num = netif->num; - } - /* Try to open the serial port. */ - priv->sd = sio_open(sio_num); - if (!priv->sd) { - /* Opening the serial port failed. */ - mem_free(priv); - return ERR_IF; - } - - /* Initialize private data */ - priv->p = NULL; - priv->q = NULL; - priv->state = SLIP_RECV_NORMAL; - priv->i = 0; - priv->recved = 0; -#if SLIP_RX_FROM_ISR - priv->rxpackets = NULL; -#endif - - netif->state = priv; - - /* initialize the snmp variables and counters inside the struct netif */ - NETIF_INIT_SNMP(netif, snmp_ifType_slip, SLIP_SIO_SPEED(priv->sd)); - -#if SLIP_USE_RX_THREAD - /* Create a thread to poll the serial line. */ - sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif, - SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO); -#endif /* SLIP_USE_RX_THREAD */ - return ERR_OK; -} - -/** - * Polls the serial device and feeds the IP layer with incoming packets. - * - * @param netif The lwip network interface structure for this slipif - */ -void ICACHE_FLASH_ATTR -slipif_poll(struct netif *netif) -{ - u8_t c; - struct slipif_priv *priv; - - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - - priv = (struct slipif_priv *)netif->state; - - while (sio_tryread(priv->sd, &c, 1) > 0) { - slipif_rxbyte_input(netif, c); - } -} - -#if SLIP_RX_FROM_ISR -/** - * Feeds the IP layer with incoming packets that were receive - * - * @param netif The lwip network interface structure for this slipif - */ -void ICACHE_FLASH_ATTR -slipif_process_rxqueue(struct netif *netif) -{ - struct slipif_priv *priv; - SYS_ARCH_DECL_PROTECT(old_level); - - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - - priv = (struct slipif_priv *)netif->state; - - SYS_ARCH_PROTECT(old_level); - while (priv->rxpackets != NULL) { - struct pbuf *p = priv->rxpackets; -#if SLIP_RX_QUEUE - /* dequeue packet */ - struct pbuf *q = p; - while ((q->len != q->tot_len) && (q->next != NULL)) { - q = q->next; - } - priv->rxpackets = q->next; - q->next = NULL; -#else /* SLIP_RX_QUEUE */ - priv->rxpackets = NULL; -#endif /* SLIP_RX_QUEUE */ - SYS_ARCH_UNPROTECT(old_level); - if (netif->input(p, netif) != ERR_OK) { - pbuf_free(p); - } - SYS_ARCH_PROTECT(old_level); - } -} - -/** Like slipif_rxbyte, but queues completed packets. - * - * @param netif The lwip network interface structure for this slipif - * @param data Received serial byte - */ -static void ICACHE_FLASH_ATTR -slipif_rxbyte_enqueue(struct netif *netif, u8_t data) -{ - struct pbuf *p; - struct slipif_priv *priv = (struct slipif_priv *)netif->state; - SYS_ARCH_DECL_PROTECT(old_level); - - p = slipif_rxbyte(netif, data); - if (p != NULL) { - SYS_ARCH_PROTECT(old_level); - if (priv->rxpackets != NULL) { -#if SLIP_RX_QUEUE - /* queue multiple pbufs */ - struct pbuf *q = p; - while(q->next != NULL) { - q = q->next; - } - q->next = p; - } else { -#else /* SLIP_RX_QUEUE */ - pbuf_free(priv->rxpackets); - } - { -#endif /* SLIP_RX_QUEUE */ - priv->rxpackets = p; - } - SYS_ARCH_UNPROTECT(old_level); - } -} - -/** - * Process a received byte, completed packets are put on a queue that is - * fed into IP through slipif_process_rxqueue(). - * - * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. - * - * @param netif The lwip network interface structure for this slipif - * @param data received character - */ -void ICACHE_FLASH_ATTR -slipif_received_byte(struct netif *netif, u8_t data) -{ - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - slipif_rxbyte_enqueue(netif, data); -} - -/** - * Process multiple received byte, completed packets are put on a queue that is - * fed into IP through slipif_process_rxqueue(). - * - * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. - * - * @param netif The lwip network interface structure for this slipif - * @param data received character - * @param len Number of received characters - */ -void ICACHE_FLASH_ATTR -slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len) -{ - u8_t i; - u8_t *rxdata = data; - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - - for (i = 0; i < len; i++, rxdata++) { - slipif_rxbyte_enqueue(netif, *rxdata); - } -} -#endif /* SLIP_RX_FROM_ISR */ - -#endif /* LWIP_HAVE_SLIPIF */ diff --git a/tools/gen_appbin.py b/tools/gen_appbin.py index 66019d1..d562901 100644 --- a/tools/gen_appbin.py +++ b/tools/gen_appbin.py @@ -1,71 +1,245 @@ #!/usr/bin/python # -# Copyright (c) 2010 Espressif System +# File : gen_appbin.py +# This file is part of Espressif's generate bin script. +# Copyright (C) 2013 - 2016, Espressif Systems # -# grab user_start() address and pass it to genflashbin program +# This program is free software: you can redistribute it and/or modify +# it under the terms of version 3 of the GNU General Public License as +# published by the Free Software Foundation. # +# 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 . + +"""This file is part of Espressif's generate bin script. + argv[1] is elf file name + argv[2] is version num""" import string import sys import os import re +import binascii +import struct + + +TEXT_ADDRESS = 0x40100000 +# app_entry = 0 +# data_address = 0x3ffb0000 +# data_end = 0x40000000 +# text_end = 0x40120000 + +CHECKSUM_INIT = 0xEF + +chk_sum = CHECKSUM_INIT +blocks = 0 + +def write_file(file_name,data): + if file_name is None: + print 'file_name cannot be none\n' + sys.exit(0) + + fp = open(file_name,'ab') + + if fp: + fp.seek(0,os.SEEK_END) + fp.write(data) + fp.close() + else: + print '%s write fail\n'%(file_name) + +def combine_bin(file_name,dest_file_name,start_offset_addr,need_chk): + global chk_sum + global blocks + if dest_file_name is None: + print 'dest_file_name cannot be none\n' + sys.exit(0) + + if file_name: + fp = open(file_name,'rb') + if fp: + ########## write text ########## + fp.seek(0,os.SEEK_END) + data_len = fp.tell() + if data_len: + if need_chk: + tmp_len = (data_len + 3) & (~3) + else: + tmp_len = (data_len + 15) & (~15) + data_bin = struct.pack(' eagle.app.sym' + else : + cmd = 'xt-nm -g ' + elf_file + ' > eagle.app.sym' + + os.system(cmd) + + fp = file('./eagle.app.sym') + if fp is None: + print "open sym file error\n" + sys.exit(0) + + lines = fp.readlines() + fp.close() + + entry_addr = None + p = re.compile('(\w*)(\sT\s)(call_user_start)$') + for line in lines: + m = p.search(line) + if m != None: + entry_addr = m.group(1) + # print entry_addr + + if entry_addr is None: + print 'no entry point!!' + sys.exit(0) + + data_start_addr = '0' + p = re.compile('(\w*)(\sA\s)(_data_start)$') + for line in lines: + m = p.search(line) + if m != None: + data_start_addr = m.group(1) + # print data_start_addr + + rodata_start_addr = '0' + p = re.compile('(\w*)(\sA\s)(_rodata_start)$') + for line in lines: + m = p.search(line) + if m != None: + rodata_start_addr = m.group(1) + # print rodata_start_addr + + # write flash bin header + #============================ + # SPI FLASH PARAMS + #------------------- + #flash_mode= + # 0: QIO + # 1: QOUT + # 2: DIO + # 3: DOUT + #------------------- + #flash_clk_div= + # 0 : 80m / 2 + # 1 : 80m / 3 + # 2 : 80m / 4 + # 0xf: 80m / 1 + #------------------- + #flash_size= + # 0 : 512 KB + # 1 : 256 KB + # 2 : 1024 KB + # 3 : 2048 KB + # 4 : 4096 KB + #------------------- + # END OF SPI FLASH PARAMS + #============================ + byte2=int(flash_mode)&0xff + byte3=(((int(flash_size)<<4)| int(flash_clk_div))&0xff) + + if boot_mode == '2': + # write irom bin head + data_bin = struct.pack(' eagle.app.sym' -#print cmd -os.system(cmd) - -fp = file('./eagle.app.sym') -if fp is None: - print "open sym file error\n" - exit - -lines = fp.readlines() - -fp.close() - -entry_addr = None -p = re.compile('(\w*)(\sT\s)(call_user_start)$') -for line in lines: - m = p.search(line) - if m != None: - entry_addr = m.group(1) - #entry_addr = int(entry_addr, 16) - print entry_addr - -if entry_addr is None: - print 'no entry point!!' - exit - -data_start_addr = '0' -p = re.compile('(\w*)(\sA\s)(_data_start)$') -for line in lines: - m = p.search(line) - if m != None: - data_start_addr = m.group(1) - print data_start_addr - -rodata_start_addr = '0' -p = re.compile('(\w*)(\sA\s)(_rodata_start)$') -for line in lines: - m = p.search(line) - if m != None: - rodata_start_addr = m.group(1) - print rodata_start_addr - -cmd = 'genflashbin%s eagle.app.%s.text.bin '%(ver, ver)+entry_addr+' eagle.app.%s.data.bin '%(ver)+ data_start_addr+' eagle.app.%s.rodata.bin '%(ver)+rodata_start_addr - -print cmd -os.system(cmd) - -cmd = 'mv eagle.app.flash.bin eagle.app.%s.flash.bin'%(ver) - -print cmd -os.system(cmd) +if __name__=='__main__': + gen_appbin() diff --git a/tools/gen_flashbin.py b/tools/gen_flashbin.py deleted file mode 100644 index 0f8f92b..0000000 --- a/tools/gen_flashbin.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/python -import os -import sys -import binascii -import string - -if len(sys.argv) != 3: - print 'Usage: gen_flashbin.py 1.bin 2.bin' - sys.exit(0) - -bin1_name = sys.argv[1] -bin2_name = sys.argv[2] - -bin1_file = open(bin1_name, 'rb') -bin2_file = open(bin2_name, 'rb') - -bin1_len = os.path.getsize(bin1_name) - -bin1 = bin1_file.read() -bin2 = bin2_file.read() - -bitlist = ['FF']*(0x10000-bin1_len) -bytes = binascii.a2b_hex(''.join(bitlist)) - -bitout = open('eagle.app.flash.bin', 'wb') -bitout.write(bin1) -bitout.write(bytes) -bitout.write(bin2) -bitout.close() - -bin1_file.close() -bin2_file.close() -