From: John Crispin Date: Sat, 5 Feb 2011 15:23:08 +0000 (+0000) Subject: * reorder patches X-Git-Tag: reboot~17655 X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=97140cecea8232c16ad45024894c9dff2a00b6a4;p=openwrt%2Fstaging%2Flynxis.git * reorder patches SVN-Revision: 25370 --- diff --git a/package/uboot-lantiq/patches/020-mips-enhancements.patch b/package/uboot-lantiq/patches/020-mips-enhancements.patch new file mode 100644 index 0000000000..d056467704 --- /dev/null +++ b/package/uboot-lantiq/patches/020-mips-enhancements.patch @@ -0,0 +1,124 @@ +--- a/cpu/mips/start.S ++++ b/cpu/mips/start.S +@@ -69,6 +69,9 @@ _start: + #elif defined(CONFIG_PURPLE) + .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */ + .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */ ++#elif defined(CONFIG_SYS_EBU_BOOT) ++ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */ ++ .word 0x00000000 /* phase of the flash */ + #else + RVECENT(romReserved,2) + #endif +@@ -202,7 +205,25 @@ _start: + * 128 * 8 == 1024 == 0x400 + * so this is address R_VEC+0x400 == 0xbfc00400 + */ +-#ifdef CONFIG_PURPLE ++#ifndef CONFIG_PURPLE ++ XVECENT(romExcHandle,0x400); /* bfc00400: Int, CauseIV=1 */ ++ RVECENT(romReserved,129); ++ RVECENT(romReserved,130); ++ RVECENT(romReserved,131); ++ RVECENT(romReserved,132); ++ RVECENT(romReserved,133); ++ RVECENT(romReserved,134); ++ RVECENT(romReserved,135); ++ RVECENT(romReserved,136); ++ RVECENT(romReserved,137); ++ RVECENT(romReserved,138); ++ RVECENT(romReserved,139); ++ RVECENT(romReserved,140); ++ RVECENT(romReserved,141); ++ RVECENT(romReserved,142); ++ RVECENT(romReserved,143); ++ XVECENT(romExcHandle,0x480); /* bfc00480: EJTAG debug exception */ ++#else /* CONFIG_PURPLE */ + /* 0xbfc00400 */ + .word 0xdc870000 + .word 0xfca70000 +@@ -228,6 +249,12 @@ _start: + #endif /* CONFIG_PURPLE */ + .align 4 + reset: ++#ifdef CONFIG_SYS_MIPS_MULTI_CPU ++ mfc0 k0, CP0_EBASE ++ and k0, EBASEF_CPUNUM ++ bne k0, zero, ifx_mips_handler_cpux ++ nop ++#endif + + /* Clear watch registers. + */ +@@ -239,6 +266,16 @@ reset: + + setup_c0_status_reset + ++#if defined(CONFIG_MIPS24KEC) || defined(CONFIG_MIPS34KC) ++ /* CONFIG7 register */ ++ /* Erratum "RPS May Cause Incorrect Instruction Execution" ++ * for 24KEC and 34KC */ ++ mfc0 k0, CP0_CONFIG, 7 ++ li k1, MIPS_CONF7_RPS ++ or k0, k1 ++ mtc0 k0, CP0_CONFIG, 7 ++#endif ++ + /* Init Timer */ + mtc0 zero, CP0_COUNT + mtc0 zero, CP0_COMPARE +@@ -270,9 +307,12 @@ reset: + jalr t9 + nop + ++#ifndef CONFIG_SYS_MIPS_CACHE_OPER_MODE ++#define CONFIG_SYS_MIPS_CACHE_OPER_MODE CONF_CM_CACHABLE_NONCOHERENT ++#endif + /* ... and enable them. + */ +- li t0, CONF_CM_CACHABLE_NONCOHERENT ++ li t0, CONFIG_SYS_MIPS_CACHE_OPER_MODE + mtc0 t0, CP0_CONFIG + #endif /* !CONFIG_SKIP_LOWLEVEL_INIT */ + +@@ -419,3 +459,15 @@ romReserved: + + romExcHandle: + b romExcHandle ++ ++ /* Additional handlers. ++ */ ++#ifdef CONFIG_SYS_MIPS_MULTI_CPU ++/* ++ * Stop Slave CPUs ++ */ ++ifx_mips_handler_cpux: ++ wait; ++ b ifx_mips_handler_cpux; ++ nop; ++#endif +--- a/include/asm-mips/mipsregs.h ++++ b/include/asm-mips/mipsregs.h +@@ -57,6 +57,7 @@ + #define CP0_CAUSE $13 + #define CP0_EPC $14 + #define CP0_PRID $15 ++#define CP0_EBASE $15,1 + #define CP0_CONFIG $16 + #define CP0_LLADDR $17 + #define CP0_WATCHLO $18 +@@ -395,6 +396,14 @@ + #define CAUSEF_BD (_ULCAST_(1) << 31) + + /* ++ * Bits in the coprocessor 0 EBase register ++ */ ++#define EBASEB_CPUNUM 0 ++#define EBASEF_CPUNUM (0x3ff << EBASEB_CPUNUM) ++#define EBASEB_EXPBASE 12 ++#define EBASEF_EXPBASE (0x3ffff << EBASEB_EXPBASE) ++ ++/* + * Bits in the coprocessor 0 config register. + */ + /* Generic bits. */ diff --git a/package/uboot-lantiq/patches/030-cfi-addr-fixup.patch b/package/uboot-lantiq/patches/030-cfi-addr-fixup.patch new file mode 100644 index 0000000000..8f95da1f75 --- /dev/null +++ b/package/uboot-lantiq/patches/030-cfi-addr-fixup.patch @@ -0,0 +1,225 @@ +--- a/drivers/mtd/cfi_flash.c ++++ b/drivers/mtd/cfi_flash.c +@@ -85,6 +85,22 @@ flash_info_t flash_info[CFI_MAX_FLASH_BA + #define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_8BIT + #endif + ++/* ++ * Check if address fixup macros are defined, define defaults otherwise ++ */ ++#ifndef FLASH_FIXUP_ADDR_8 ++#define FLASH_FIXUP_ADDR_8(addr) (addr) ++#endif ++#ifndef FLASH_FIXUP_ADDR_16 ++#define FLASH_FIXUP_ADDR_16(addr) (addr) ++#endif ++#ifndef FLASH_FIXUP_ADDR_32 ++#define FLASH_FIXUP_ADDR_32(addr) (addr) ++#endif ++#ifndef FLASH_FIXUP_ADDR_64 ++#define FLASH_FIXUP_ADDR_64(addr) (addr) ++#endif ++ + static void __flash_write8(u8 value, void *addr) + { + __raw_writeb(value, addr); +@@ -264,9 +280,9 @@ static inline uchar flash_read_uchar (fl + + cp = flash_map (info, 0, offset); + #if defined(__LITTLE_ENDIAN) || defined(CONFIG_SYS_WRITE_SWAPPED_DATA) +- retval = flash_read8(cp); ++ retval = flash_read8(FLASH_FIXUP_ADDR_8(cp)); + #else +- retval = flash_read8(cp + info->portwidth - 1); ++ retval = flash_read8(FLASH_FIXUP_ADDR_8(cp) + info->portwidth - 1); + #endif + flash_unmap (info, 0, offset, cp); + return retval; +@@ -280,7 +296,7 @@ static inline ushort flash_read_word (fl + ushort *addr, retval; + + addr = flash_map (info, 0, offset); +- retval = flash_read16 (addr); ++ retval = flash_read16 (FLASH_FIXUP_ADDR_16(addr)); + flash_unmap (info, 0, offset, addr); + return retval; + } +@@ -305,19 +321,28 @@ static ulong flash_read_long (flash_info + debug ("long addr is at %p info->portwidth = %d\n", addr, + info->portwidth); + for (x = 0; x < 4 * info->portwidth; x++) { +- debug ("addr[%x] = 0x%x\n", x, flash_read8(addr + x)); ++ debug ("addr[%x] = 0x%x\n", x, ++ flash_read8(FLASH_FIXUP_ADDR_32(addr) + x)); + } + #endif + #if defined(__LITTLE_ENDIAN) || defined(CONFIG_SYS_WRITE_SWAPPED_DATA) +- retval = ((flash_read8(addr) << 16) | +- (flash_read8(addr + info->portwidth) << 24) | +- (flash_read8(addr + 2 * info->portwidth)) | +- (flash_read8(addr + 3 * info->portwidth) << 8)); ++ retval = ((flash_read8(FLASH_FIXUP_ADDR_8 ++ (addr) << 16) | ++ (flash_read8(FLASH_FIXUP_ADDR_8 ++ (addr + info->portwidth)) << 24) | ++ (flash_read8(FLASH_FIXUP_ADDR_8 ++ (addr + 2 * info->portwidth))) | ++ (flash_read8(FLASH_FIXUP_ADDR_8 ++ (addr + 3 * info->portwidth)) << 8)); + #else +- retval = ((flash_read8(addr + 2 * info->portwidth - 1) << 24) | +- (flash_read8(addr + info->portwidth - 1) << 16) | +- (flash_read8(addr + 4 * info->portwidth - 1) << 8) | +- (flash_read8(addr + 3 * info->portwidth - 1))); ++ retval = ((flash_read8(FLASH_FIXUP_ADDR_8 ++ (addr + 2 * info->portwidth - 1)) << 24) | ++ (flash_read8(FLASH_FIXUP_ADDR_8 ++ (addr + info->portwidth - 1)) << 16) | ++ (flash_read8(FLASH_FIXUP_ADDR_8 ++ (addr + 4 * info->portwidth - 1)) << 8) | ++ (flash_read8(FLASH_FIXUP_ADDR_8 ++ (addr + 3 * info->portwidth - 1)))); + #endif + flash_unmap(info, sect, offset, addr); + +@@ -338,21 +363,22 @@ void flash_write_cmd (flash_info_t * inf + flash_make_cmd (info, cmd, &cword); + switch (info->portwidth) { + case FLASH_CFI_8BIT: +- debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr, cmd, +- cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH); +- flash_write8(cword.c, addr); ++ debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", ++ FLASH_FIXUP_ADDR_8(addr), cmd, cword.c, ++ info->chipwidth << CFI_FLASH_SHIFT_WIDTH); ++ flash_write8(cword.c, FLASH_FIXUP_ADDR_8(addr)); + break; + case FLASH_CFI_16BIT: +- debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr, +- cmd, cword.w, ++ debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", ++ FLASH_FIXUP_ADDR_16(addr), cmd, cword.w, + info->chipwidth << CFI_FLASH_SHIFT_WIDTH); +- flash_write16(cword.w, addr); ++ flash_write16(cword.w, FLASH_FIXUP_ADDR_16(addr)); + break; + case FLASH_CFI_32BIT: +- debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr, +- cmd, cword.l, ++ debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", ++ FLASH_FIXUP_ADDR_32(addr), cmd, cword.l, + info->chipwidth << CFI_FLASH_SHIFT_WIDTH); +- flash_write32(cword.l, addr); ++ flash_write32(cword.l, FLASH_FIXUP_ADDR_32(addr)); + break; + case FLASH_CFI_64BIT: + #ifdef DEBUG +@@ -362,11 +388,11 @@ void flash_write_cmd (flash_info_t * inf + print_longlong (str, cword.ll); + + debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n", +- addr, cmd, str, ++ FLASH_FIXUP_ADDR_64(addr), cmd, str, + info->chipwidth << CFI_FLASH_SHIFT_WIDTH); + } + #endif +- flash_write64(cword.ll, addr); ++ flash_write64(cword.ll, FLASH_FIXUP_ADDR_64(addr)); + break; + } + +@@ -397,16 +423,19 @@ static int flash_isequal (flash_info_t * + debug ("is= cmd %x(%c) addr %p ", cmd, cmd, addr); + switch (info->portwidth) { + case FLASH_CFI_8BIT: +- debug ("is= %x %x\n", flash_read8(addr), cword.c); +- retval = (flash_read8(addr) == cword.c); ++ debug ("is= %x %x\n", ++ flash_read8(FLASH_FIXUP_ADDR_8(addr)), cword.c); ++ retval = (flash_read8(FLASH_FIXUP_ADDR_8(addr)) == cword.c); + break; + case FLASH_CFI_16BIT: +- debug ("is= %4.4x %4.4x\n", flash_read16(addr), cword.w); +- retval = (flash_read16(addr) == cword.w); ++ debug ("is= %4.4x %4.4x\n", ++ flash_read16(FLASH_FIXUP_ADDR_16(addr)), cword.w); ++ retval = (flash_read16(FLASH_FIXUP_ADDR_16(addr)) == cword.w); + break; + case FLASH_CFI_32BIT: +- debug ("is= %8.8x %8.8lx\n", flash_read32(addr), cword.l); +- retval = (flash_read32(addr) == cword.l); ++ debug ("is= %8.8x %8.8lx\n", ++ flash_read32(FLASH_FIXUP_ADDR_32(addr)), cword.l); ++ retval = (flash_read32(FLASH_FIXUP_ADDR_32(addr)) == cword.l); + break; + case FLASH_CFI_64BIT: + #ifdef DEBUG +@@ -414,12 +443,13 @@ static int flash_isequal (flash_info_t * + char str1[20]; + char str2[20]; + +- print_longlong (str1, flash_read64(addr)); ++ print_longlong (str1, flash_read64(FLASH_FIXUP_ADDR_64 ++ (addr))); + print_longlong (str2, cword.ll); + debug ("is= %s %s\n", str1, str2); + } + #endif +- retval = (flash_read64(addr) == cword.ll); ++ retval = (flash_read64(FLASH_FIXUP_ADDR_64(addr)) == cword.ll); + break; + default: + retval = 0; +@@ -443,16 +473,20 @@ static int flash_isset (flash_info_t * i + flash_make_cmd (info, cmd, &cword); + switch (info->portwidth) { + case FLASH_CFI_8BIT: +- retval = ((flash_read8(addr) & cword.c) == cword.c); ++ retval = ((flash_read8(FLASH_FIXUP_ADDR_8(addr)) ++ & cword.c) == cword.c); + break; + case FLASH_CFI_16BIT: +- retval = ((flash_read16(addr) & cword.w) == cword.w); ++ retval = ((flash_read16(FLASH_FIXUP_ADDR_16(addr)) ++ & cword.w) == cword.w); + break; + case FLASH_CFI_32BIT: +- retval = ((flash_read32(addr) & cword.l) == cword.l); ++ retval = ((flash_read32(FLASH_FIXUP_ADDR_32(addr)) ++ & cword.l) == cword.l); + break; + case FLASH_CFI_64BIT: +- retval = ((flash_read64(addr) & cword.ll) == cword.ll); ++ retval = ((flash_read64(FLASH_FIXUP_ADDR_64(addr)) ++ & cword.ll) == cword.ll); + break; + default: + retval = 0; +@@ -476,17 +510,22 @@ static int flash_toggle (flash_info_t * + flash_make_cmd (info, cmd, &cword); + switch (info->portwidth) { + case FLASH_CFI_8BIT: +- retval = flash_read8(addr) != flash_read8(addr); ++ retval = flash_read8(FLASH_FIXUP_ADDR_8(addr)) != ++ flash_read8(FLASH_FIXUP_ADDR_8(addr)); + break; + case FLASH_CFI_16BIT: +- retval = flash_read16(addr) != flash_read16(addr); ++ retval = flash_read16(FLASH_FIXUP_ADDR_16(addr)) != ++ flash_read16(FLASH_FIXUP_ADDR_16(addr)); + break; + case FLASH_CFI_32BIT: +- retval = flash_read32(addr) != flash_read32(addr); ++ retval = flash_read32(FLASH_FIXUP_ADDR_32(addr)) != ++ flash_read32(FLASH_FIXUP_ADDR_32(addr)); + break; + case FLASH_CFI_64BIT: +- retval = ( (flash_read32( addr ) != flash_read32( addr )) || +- (flash_read32(addr+4) != flash_read32(addr+4)) ); ++ retval = ( (flash_read32(FLASH_FIXUP_ADDR_64( addr )) != ++ flash_read32(FLASH_FIXUP_ADDR_64( addr ))) || ++ (flash_read32(FLASH_FIXUP_ADDR_64(addr+4)) != ++ flash_read32(FLASH_FIXUP_ADDR_64(addr+4))) ); + break; + default: + retval = 0; diff --git a/package/uboot-lantiq/patches/040-compile.patch b/package/uboot-lantiq/patches/040-compile.patch new file mode 100644 index 0000000000..c00230069d --- /dev/null +++ b/package/uboot-lantiq/patches/040-compile.patch @@ -0,0 +1,20 @@ +--- a/common/env_common.c ++++ b/common/env_common.c +@@ -26,6 +26,7 @@ + + #include + #include ++#include + #include + #include + #include +--- a/common/env_embedded.c ++++ b/common/env_embedded.c +@@ -27,6 +27,7 @@ + #define __ASM_STUB_PROCESSOR_H__ /* don't include asm/processor. */ + #include + #undef __ASSEMBLY__ ++#include + #include + + /* diff --git a/package/uboot-lantiq/patches/050-mips-enhancements.patch b/package/uboot-lantiq/patches/050-mips-enhancements.patch deleted file mode 100644 index d056467704..0000000000 --- a/package/uboot-lantiq/patches/050-mips-enhancements.patch +++ /dev/null @@ -1,124 +0,0 @@ ---- a/cpu/mips/start.S -+++ b/cpu/mips/start.S -@@ -69,6 +69,9 @@ _start: - #elif defined(CONFIG_PURPLE) - .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */ - .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */ -+#elif defined(CONFIG_SYS_EBU_BOOT) -+ .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */ -+ .word 0x00000000 /* phase of the flash */ - #else - RVECENT(romReserved,2) - #endif -@@ -202,7 +205,25 @@ _start: - * 128 * 8 == 1024 == 0x400 - * so this is address R_VEC+0x400 == 0xbfc00400 - */ --#ifdef CONFIG_PURPLE -+#ifndef CONFIG_PURPLE -+ XVECENT(romExcHandle,0x400); /* bfc00400: Int, CauseIV=1 */ -+ RVECENT(romReserved,129); -+ RVECENT(romReserved,130); -+ RVECENT(romReserved,131); -+ RVECENT(romReserved,132); -+ RVECENT(romReserved,133); -+ RVECENT(romReserved,134); -+ RVECENT(romReserved,135); -+ RVECENT(romReserved,136); -+ RVECENT(romReserved,137); -+ RVECENT(romReserved,138); -+ RVECENT(romReserved,139); -+ RVECENT(romReserved,140); -+ RVECENT(romReserved,141); -+ RVECENT(romReserved,142); -+ RVECENT(romReserved,143); -+ XVECENT(romExcHandle,0x480); /* bfc00480: EJTAG debug exception */ -+#else /* CONFIG_PURPLE */ - /* 0xbfc00400 */ - .word 0xdc870000 - .word 0xfca70000 -@@ -228,6 +249,12 @@ _start: - #endif /* CONFIG_PURPLE */ - .align 4 - reset: -+#ifdef CONFIG_SYS_MIPS_MULTI_CPU -+ mfc0 k0, CP0_EBASE -+ and k0, EBASEF_CPUNUM -+ bne k0, zero, ifx_mips_handler_cpux -+ nop -+#endif - - /* Clear watch registers. - */ -@@ -239,6 +266,16 @@ reset: - - setup_c0_status_reset - -+#if defined(CONFIG_MIPS24KEC) || defined(CONFIG_MIPS34KC) -+ /* CONFIG7 register */ -+ /* Erratum "RPS May Cause Incorrect Instruction Execution" -+ * for 24KEC and 34KC */ -+ mfc0 k0, CP0_CONFIG, 7 -+ li k1, MIPS_CONF7_RPS -+ or k0, k1 -+ mtc0 k0, CP0_CONFIG, 7 -+#endif -+ - /* Init Timer */ - mtc0 zero, CP0_COUNT - mtc0 zero, CP0_COMPARE -@@ -270,9 +307,12 @@ reset: - jalr t9 - nop - -+#ifndef CONFIG_SYS_MIPS_CACHE_OPER_MODE -+#define CONFIG_SYS_MIPS_CACHE_OPER_MODE CONF_CM_CACHABLE_NONCOHERENT -+#endif - /* ... and enable them. - */ -- li t0, CONF_CM_CACHABLE_NONCOHERENT -+ li t0, CONFIG_SYS_MIPS_CACHE_OPER_MODE - mtc0 t0, CP0_CONFIG - #endif /* !CONFIG_SKIP_LOWLEVEL_INIT */ - -@@ -419,3 +459,15 @@ romReserved: - - romExcHandle: - b romExcHandle -+ -+ /* Additional handlers. -+ */ -+#ifdef CONFIG_SYS_MIPS_MULTI_CPU -+/* -+ * Stop Slave CPUs -+ */ -+ifx_mips_handler_cpux: -+ wait; -+ b ifx_mips_handler_cpux; -+ nop; -+#endif ---- a/include/asm-mips/mipsregs.h -+++ b/include/asm-mips/mipsregs.h -@@ -57,6 +57,7 @@ - #define CP0_CAUSE $13 - #define CP0_EPC $14 - #define CP0_PRID $15 -+#define CP0_EBASE $15,1 - #define CP0_CONFIG $16 - #define CP0_LLADDR $17 - #define CP0_WATCHLO $18 -@@ -395,6 +396,14 @@ - #define CAUSEF_BD (_ULCAST_(1) << 31) - - /* -+ * Bits in the coprocessor 0 EBase register -+ */ -+#define EBASEB_CPUNUM 0 -+#define EBASEF_CPUNUM (0x3ff << EBASEB_CPUNUM) -+#define EBASEB_EXPBASE 12 -+#define EBASEF_EXPBASE (0x3ffff << EBASEB_EXPBASE) -+ -+/* - * Bits in the coprocessor 0 config register. - */ - /* Generic bits. */ diff --git a/package/uboot-lantiq/patches/050-portability.patch b/package/uboot-lantiq/patches/050-portability.patch new file mode 100644 index 0000000000..ae38ad68ea --- /dev/null +++ b/package/uboot-lantiq/patches/050-portability.patch @@ -0,0 +1,31 @@ +--- a/tools/kwbimage.c ++++ b/tools/kwbimage.c +@@ -206,6 +206,28 @@ INVL_DATA: + exit (EXIT_FAILURE); + } + ++#ifndef __GLIBC__ ++static ssize_t ++getline(char **line, size_t *len, FILE *fd) ++{ ++ char *tmp; ++ int tmplen; ++ ++ tmp = fgetln(fd, &tmplen); ++ if (!tmp) ++ return -1; ++ ++ if (!*line || tmplen > *len) { ++ *len = tmplen + 1; ++ *line = realloc(*line, *len); ++ } ++ ++ strncpy(*line, tmp, tmplen); ++ line[tmplen] = 0; ++ return tmplen; ++} ++#endif ++ + /* + * this function sets the kwbimage header by- + * 1. Abstracting input command line arguments data diff --git a/package/uboot-lantiq/patches/062-cfi-addr-fixup.patch b/package/uboot-lantiq/patches/062-cfi-addr-fixup.patch deleted file mode 100644 index 8f95da1f75..0000000000 --- a/package/uboot-lantiq/patches/062-cfi-addr-fixup.patch +++ /dev/null @@ -1,225 +0,0 @@ ---- a/drivers/mtd/cfi_flash.c -+++ b/drivers/mtd/cfi_flash.c -@@ -85,6 +85,22 @@ flash_info_t flash_info[CFI_MAX_FLASH_BA - #define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_8BIT - #endif - -+/* -+ * Check if address fixup macros are defined, define defaults otherwise -+ */ -+#ifndef FLASH_FIXUP_ADDR_8 -+#define FLASH_FIXUP_ADDR_8(addr) (addr) -+#endif -+#ifndef FLASH_FIXUP_ADDR_16 -+#define FLASH_FIXUP_ADDR_16(addr) (addr) -+#endif -+#ifndef FLASH_FIXUP_ADDR_32 -+#define FLASH_FIXUP_ADDR_32(addr) (addr) -+#endif -+#ifndef FLASH_FIXUP_ADDR_64 -+#define FLASH_FIXUP_ADDR_64(addr) (addr) -+#endif -+ - static void __flash_write8(u8 value, void *addr) - { - __raw_writeb(value, addr); -@@ -264,9 +280,9 @@ static inline uchar flash_read_uchar (fl - - cp = flash_map (info, 0, offset); - #if defined(__LITTLE_ENDIAN) || defined(CONFIG_SYS_WRITE_SWAPPED_DATA) -- retval = flash_read8(cp); -+ retval = flash_read8(FLASH_FIXUP_ADDR_8(cp)); - #else -- retval = flash_read8(cp + info->portwidth - 1); -+ retval = flash_read8(FLASH_FIXUP_ADDR_8(cp) + info->portwidth - 1); - #endif - flash_unmap (info, 0, offset, cp); - return retval; -@@ -280,7 +296,7 @@ static inline ushort flash_read_word (fl - ushort *addr, retval; - - addr = flash_map (info, 0, offset); -- retval = flash_read16 (addr); -+ retval = flash_read16 (FLASH_FIXUP_ADDR_16(addr)); - flash_unmap (info, 0, offset, addr); - return retval; - } -@@ -305,19 +321,28 @@ static ulong flash_read_long (flash_info - debug ("long addr is at %p info->portwidth = %d\n", addr, - info->portwidth); - for (x = 0; x < 4 * info->portwidth; x++) { -- debug ("addr[%x] = 0x%x\n", x, flash_read8(addr + x)); -+ debug ("addr[%x] = 0x%x\n", x, -+ flash_read8(FLASH_FIXUP_ADDR_32(addr) + x)); - } - #endif - #if defined(__LITTLE_ENDIAN) || defined(CONFIG_SYS_WRITE_SWAPPED_DATA) -- retval = ((flash_read8(addr) << 16) | -- (flash_read8(addr + info->portwidth) << 24) | -- (flash_read8(addr + 2 * info->portwidth)) | -- (flash_read8(addr + 3 * info->portwidth) << 8)); -+ retval = ((flash_read8(FLASH_FIXUP_ADDR_8 -+ (addr) << 16) | -+ (flash_read8(FLASH_FIXUP_ADDR_8 -+ (addr + info->portwidth)) << 24) | -+ (flash_read8(FLASH_FIXUP_ADDR_8 -+ (addr + 2 * info->portwidth))) | -+ (flash_read8(FLASH_FIXUP_ADDR_8 -+ (addr + 3 * info->portwidth)) << 8)); - #else -- retval = ((flash_read8(addr + 2 * info->portwidth - 1) << 24) | -- (flash_read8(addr + info->portwidth - 1) << 16) | -- (flash_read8(addr + 4 * info->portwidth - 1) << 8) | -- (flash_read8(addr + 3 * info->portwidth - 1))); -+ retval = ((flash_read8(FLASH_FIXUP_ADDR_8 -+ (addr + 2 * info->portwidth - 1)) << 24) | -+ (flash_read8(FLASH_FIXUP_ADDR_8 -+ (addr + info->portwidth - 1)) << 16) | -+ (flash_read8(FLASH_FIXUP_ADDR_8 -+ (addr + 4 * info->portwidth - 1)) << 8) | -+ (flash_read8(FLASH_FIXUP_ADDR_8 -+ (addr + 3 * info->portwidth - 1)))); - #endif - flash_unmap(info, sect, offset, addr); - -@@ -338,21 +363,22 @@ void flash_write_cmd (flash_info_t * inf - flash_make_cmd (info, cmd, &cword); - switch (info->portwidth) { - case FLASH_CFI_8BIT: -- debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr, cmd, -- cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH); -- flash_write8(cword.c, addr); -+ debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", -+ FLASH_FIXUP_ADDR_8(addr), cmd, cword.c, -+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH); -+ flash_write8(cword.c, FLASH_FIXUP_ADDR_8(addr)); - break; - case FLASH_CFI_16BIT: -- debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr, -- cmd, cword.w, -+ debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", -+ FLASH_FIXUP_ADDR_16(addr), cmd, cword.w, - info->chipwidth << CFI_FLASH_SHIFT_WIDTH); -- flash_write16(cword.w, addr); -+ flash_write16(cword.w, FLASH_FIXUP_ADDR_16(addr)); - break; - case FLASH_CFI_32BIT: -- debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr, -- cmd, cword.l, -+ debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", -+ FLASH_FIXUP_ADDR_32(addr), cmd, cword.l, - info->chipwidth << CFI_FLASH_SHIFT_WIDTH); -- flash_write32(cword.l, addr); -+ flash_write32(cword.l, FLASH_FIXUP_ADDR_32(addr)); - break; - case FLASH_CFI_64BIT: - #ifdef DEBUG -@@ -362,11 +388,11 @@ void flash_write_cmd (flash_info_t * inf - print_longlong (str, cword.ll); - - debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n", -- addr, cmd, str, -+ FLASH_FIXUP_ADDR_64(addr), cmd, str, - info->chipwidth << CFI_FLASH_SHIFT_WIDTH); - } - #endif -- flash_write64(cword.ll, addr); -+ flash_write64(cword.ll, FLASH_FIXUP_ADDR_64(addr)); - break; - } - -@@ -397,16 +423,19 @@ static int flash_isequal (flash_info_t * - debug ("is= cmd %x(%c) addr %p ", cmd, cmd, addr); - switch (info->portwidth) { - case FLASH_CFI_8BIT: -- debug ("is= %x %x\n", flash_read8(addr), cword.c); -- retval = (flash_read8(addr) == cword.c); -+ debug ("is= %x %x\n", -+ flash_read8(FLASH_FIXUP_ADDR_8(addr)), cword.c); -+ retval = (flash_read8(FLASH_FIXUP_ADDR_8(addr)) == cword.c); - break; - case FLASH_CFI_16BIT: -- debug ("is= %4.4x %4.4x\n", flash_read16(addr), cword.w); -- retval = (flash_read16(addr) == cword.w); -+ debug ("is= %4.4x %4.4x\n", -+ flash_read16(FLASH_FIXUP_ADDR_16(addr)), cword.w); -+ retval = (flash_read16(FLASH_FIXUP_ADDR_16(addr)) == cword.w); - break; - case FLASH_CFI_32BIT: -- debug ("is= %8.8x %8.8lx\n", flash_read32(addr), cword.l); -- retval = (flash_read32(addr) == cword.l); -+ debug ("is= %8.8x %8.8lx\n", -+ flash_read32(FLASH_FIXUP_ADDR_32(addr)), cword.l); -+ retval = (flash_read32(FLASH_FIXUP_ADDR_32(addr)) == cword.l); - break; - case FLASH_CFI_64BIT: - #ifdef DEBUG -@@ -414,12 +443,13 @@ static int flash_isequal (flash_info_t * - char str1[20]; - char str2[20]; - -- print_longlong (str1, flash_read64(addr)); -+ print_longlong (str1, flash_read64(FLASH_FIXUP_ADDR_64 -+ (addr))); - print_longlong (str2, cword.ll); - debug ("is= %s %s\n", str1, str2); - } - #endif -- retval = (flash_read64(addr) == cword.ll); -+ retval = (flash_read64(FLASH_FIXUP_ADDR_64(addr)) == cword.ll); - break; - default: - retval = 0; -@@ -443,16 +473,20 @@ static int flash_isset (flash_info_t * i - flash_make_cmd (info, cmd, &cword); - switch (info->portwidth) { - case FLASH_CFI_8BIT: -- retval = ((flash_read8(addr) & cword.c) == cword.c); -+ retval = ((flash_read8(FLASH_FIXUP_ADDR_8(addr)) -+ & cword.c) == cword.c); - break; - case FLASH_CFI_16BIT: -- retval = ((flash_read16(addr) & cword.w) == cword.w); -+ retval = ((flash_read16(FLASH_FIXUP_ADDR_16(addr)) -+ & cword.w) == cword.w); - break; - case FLASH_CFI_32BIT: -- retval = ((flash_read32(addr) & cword.l) == cword.l); -+ retval = ((flash_read32(FLASH_FIXUP_ADDR_32(addr)) -+ & cword.l) == cword.l); - break; - case FLASH_CFI_64BIT: -- retval = ((flash_read64(addr) & cword.ll) == cword.ll); -+ retval = ((flash_read64(FLASH_FIXUP_ADDR_64(addr)) -+ & cword.ll) == cword.ll); - break; - default: - retval = 0; -@@ -476,17 +510,22 @@ static int flash_toggle (flash_info_t * - flash_make_cmd (info, cmd, &cword); - switch (info->portwidth) { - case FLASH_CFI_8BIT: -- retval = flash_read8(addr) != flash_read8(addr); -+ retval = flash_read8(FLASH_FIXUP_ADDR_8(addr)) != -+ flash_read8(FLASH_FIXUP_ADDR_8(addr)); - break; - case FLASH_CFI_16BIT: -- retval = flash_read16(addr) != flash_read16(addr); -+ retval = flash_read16(FLASH_FIXUP_ADDR_16(addr)) != -+ flash_read16(FLASH_FIXUP_ADDR_16(addr)); - break; - case FLASH_CFI_32BIT: -- retval = flash_read32(addr) != flash_read32(addr); -+ retval = flash_read32(FLASH_FIXUP_ADDR_32(addr)) != -+ flash_read32(FLASH_FIXUP_ADDR_32(addr)); - break; - case FLASH_CFI_64BIT: -- retval = ( (flash_read32( addr ) != flash_read32( addr )) || -- (flash_read32(addr+4) != flash_read32(addr+4)) ); -+ retval = ( (flash_read32(FLASH_FIXUP_ADDR_64( addr )) != -+ flash_read32(FLASH_FIXUP_ADDR_64( addr ))) || -+ (flash_read32(FLASH_FIXUP_ADDR_64(addr+4)) != -+ flash_read32(FLASH_FIXUP_ADDR_64(addr+4))) ); - break; - default: - retval = 0; diff --git a/package/uboot-lantiq/patches/200-httpd.patch b/package/uboot-lantiq/patches/200-httpd.patch new file mode 100644 index 0000000000..04549fc080 --- /dev/null +++ b/package/uboot-lantiq/patches/200-httpd.patch @@ -0,0 +1,6166 @@ +--- a/common/cmd_net.c ++++ b/common/cmd_net.c +@@ -43,6 +43,18 @@ U_BOOT_CMD( + "[loadAddress] [[hostIPaddr:]bootfilename]" + ); + ++#if defined(CONFIG_CMD_HTTPD) ++int do_httpd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ++{ ++ return NetLoopHttpd(); ++} ++ ++U_BOOT_CMD( ++ httpd, 1, 1, do_httpd, ++ "httpd\t- start webserver", "" ++); ++#endif ++ + int do_tftpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) + { + return netboot_common (TFTP, cmdtp, argc, argv); +--- /dev/null ++++ b/include/httpd.h +@@ -0,0 +1,17 @@ ++#ifndef _UIP_HTTPD_H__ ++#define _UIP_HTTPD_H__ ++ ++void HttpdStart (void); ++void HttpdHandler (void); ++ ++/* board specific implementation */ ++extern int do_http_upgrade(const unsigned char *data, const ulong size); ++ ++#define HTTP_PROGRESS_START 0 ++#define HTTP_PROGRESS_TIMEOUT 1 ++#define HTTP_PROGRESS_UPLOAD_READY 2 ++#define HTTP_PROGRESS_UGRADE_READY 3 ++#define HTTP_PROGRESS_UGRADE_FAILED 4 ++extern int do_http_progress(const int state); ++ ++#endif +--- a/include/net.h ++++ b/include/net.h +@@ -383,7 +383,8 @@ extern int NetTimeOffset; /* offset ti + + /* Initialize the network adapter */ + extern int NetLoop(proto_t); +- ++extern int NetLoopHttpd(void); ++extern void NetSendHttpd(void); + /* Shutdown adapters and cleanup */ + extern void NetStop(void); + +--- a/net/Makefile ++++ b/net/Makefile +@@ -26,6 +26,8 @@ include $(TOPDIR)/config.mk + # CFLAGS += -DDEBUG + + LIB = $(obj)libnet.a ++UIPDIR = uip-0.9 ++$(shell mkdir -p $(obj)$(UIPDIR)) + + COBJS-$(CONFIG_CMD_NET) += bootp.o + COBJS-$(CONFIG_CMD_DNS) += dns.o +@@ -36,6 +40,8 @@ COBJS-$(CONFIG_CMD_NET) += rarp.o + COBJS-$(CONFIG_CMD_SNTP) += sntp.o + COBJS-$(CONFIG_CMD_NET) += tftp.o + ++COBJS-$(CONFIG_CMD_HTTPD) += httpd.o $(UIPDIR)/fs.o $(UIPDIR)/httpd.o $(UIPDIR)/uip_arp.o $(UIPDIR)/uip_arch.o $(UIPDIR)/uip.o ++ + COBJS := $(COBJS-y) + SRCS := $(COBJS:.o=.c) + OBJS := $(addprefix $(obj),$(COBJS)) +--- /dev/null ++++ b/net/httpd.c +@@ -0,0 +1,52 @@ ++/* ++ * Copyright 1994, 1995, 2000 Neil Russell. ++ * (See License) ++ * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de ++ */ ++ ++#include ++#include ++#include ++#include "uip-0.9/uipopt.h" ++#include "uip-0.9/uip.h" ++#include "uip-0.9/uip_arp.h" ++ ++ ++#if defined(CONFIG_CMD_HTTPD) ++ ++#define TIMEOUT 5 ++ ++static int arptimer = 0; ++ ++void ++HttpdHandler (void) ++{ ++ int i; ++ for(i = 0; i < UIP_CONNS; i++) { ++ uip_periodic(i); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ NetSendHttpd(); ++ } ++ } ++ if(++arptimer == 20) { ++ uip_arp_timer(); ++ arptimer = 0; ++ } ++} ++ ++static void ++HttpdTimeout (void) ++{ ++ puts ("T "); ++ NetSetTimeout (TIMEOUT * 1000, HttpdTimeout); ++} ++ ++void ++HttpdStart (void) ++{ ++ uip_init(); ++ httpd_init(); ++} ++ ++#endif +--- a/net/net.c ++++ b/net/net.c +@@ -95,6 +95,19 @@ + #if defined(CONFIG_CMD_DNS) + #include "dns.h" + #endif ++#if defined(CONFIG_CMD_HTTPD) ++#include "httpd.h" ++#include "uip-0.9/uipopt.h" ++#include "uip-0.9/uip.h" ++#include "uip-0.9/uip_arp.h" ++static int https_running = 0; ++int httpd_upload_complete = 0; ++unsigned char *httpd_upload_data = 0; ++extern int upload_running; ++void NetReceiveHttpd(volatile uchar * inpkt, int len); ++void NetSendHttpd(void); ++extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); ++#endif + + DECLARE_GLOBAL_DATA_PTR; + +@@ -1308,6 +1321,13 @@ NetReceive(volatile uchar * inpkt, int l + + debug("packet received\n"); + ++#if defined(CONFIG_CMD_HTTPD) ++ if(https_running) { ++ NetReceiveHttpd(inpkt, len); ++ return; ++ } ++#endif ++ + NetRxPacket = inpkt; + NetRxPacketLen = len; + et = (Ethernet_t *)inpkt; +@@ -1922,3 +1942,162 @@ ushort getenv_VLAN(char *var) + { + return (string_to_VLAN(getenv(var))); + } ++ ++#if defined(CONFIG_CMD_HTTPD) ++ ++void ++NetSendHttpd(void) ++{ ++ volatile uchar *tmpbuf = NetTxPacket; ++ int i; ++ ++ for(i = 0; i < 40 + UIP_LLH_LEN; i++) { ++ tmpbuf[i] = uip_buf[i]; ++ } ++ ++ for(; i < uip_len; i++) { ++ tmpbuf[i] = uip_appdata[i - 40 - UIP_LLH_LEN]; ++ } ++ eth_send(NetTxPacket, uip_len); ++} ++ ++#define BUF ((struct uip_eth_hdr *)&uip_buf[0]) ++ ++void ++NetReceiveHttpd(volatile uchar * inpkt, int len) ++{ ++ memcpy(uip_buf, inpkt, len); ++ uip_len = len; ++ if(BUF->type == htons(UIP_ETHTYPE_IP)) { ++ uip_arp_ipin(); ++ uip_input(); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ NetSendHttpd(); ++ } ++ } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) { ++ uip_arp_arpin(); ++ if(uip_len > 0) { ++ NetSendHttpd(); ++ } ++ } ++} ++ ++int ++NetLoopHttpd(void) ++{ ++ unsigned long long tout = 0; ++ bd_t *bd = gd->bd; ++ unsigned short int ip[2]; ++ ++#ifdef CONFIG_NET_MULTI ++ NetRestarted = 0; ++ NetDevExists = 0; ++#endif ++ ++ /* XXX problem with bss workaround */ ++ NetArpWaitPacketMAC = NULL; ++ NetArpWaitTxPacket = NULL; ++ NetArpWaitPacketIP = 0; ++ NetArpWaitReplyIP = 0; ++ NetArpWaitTxPacket = NULL; ++ NetTxPacket = NULL; ++ NetTryCount = 1; ++ ++ if (!NetTxPacket) { ++ int i; ++ /* ++ * Setup packet buffers, aligned correctly. ++ */ ++ NetTxPacket = &PktBuf[0] + (PKTALIGN - 1); ++ NetTxPacket -= (ulong)NetTxPacket % PKTALIGN; ++ for (i = 0; i < PKTBUFSRX; i++) { ++ NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN; ++ } ++ } ++ ++ if (!NetArpWaitTxPacket) { ++ NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1); ++ NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN; ++ NetArpWaitTxPacketSize = 0; ++ } ++ ++restart: ++ ++ eth_halt(); ++#ifdef CONFIG_NET_MULTI ++ eth_set_current(); ++#endif ++ if (eth_init(bd) < 0) { ++ eth_halt(); ++ return(-1); ++ } ++ ++#ifdef CONFIG_NET_MULTI ++ memcpy (NetOurEther, eth_get_dev()->enetaddr, 6); ++#else ++ eth_getenv_enetaddr("ethaddr", NetOurEther); ++#endif ++ ++ NetCopyIP(&NetOurIP, &bd->bi_ip_addr); ++ NetOurGatewayIP = getenv_IPaddr ("gatewayip"); ++ NetOurSubnetMask= getenv_IPaddr ("netmask"); ++ NetOurVLAN = getenv_VLAN("vlan"); ++ NetOurNativeVLAN = getenv_VLAN("nvlan"); ++ ++ printf("starting httpd server from server %ld.%ld.%ld.%ld\n", ++ (bd->bi_ip_addr & 0xff000000) >> 24, ++ (bd->bi_ip_addr & 0x00ff0000) >> 16, ++ (bd->bi_ip_addr & 0x0000ff00) >> 8, ++ (bd->bi_ip_addr & 0x000000ff)); ++ ++ HttpdStart(); ++ ++ ip[0] = ((bd->bi_ip_addr & 0xffff0000) >> 16); ++ ip[1] = (bd->bi_ip_addr & 0x0000ffff); ++ uip_sethostaddr(ip); ++ ++ do_http_progress(HTTP_PROGRESS_START); ++ ++ https_running = 1; ++ for (;;) { ++ unsigned long long t1; ++ WATCHDOG_RESET(); ++ if(eth_rx() > 0) { ++ HttpdHandler(); ++ } else { ++ t1 = get_ticks(); ++ if(t1 - tout > 1000) { ++ do_http_progress(HTTP_PROGRESS_TIMEOUT); ++ tout = t1; ++ } ++ } ++ if(!httpd_upload_complete) ++ continue; ++ printf("Bytes transferred = %ld (%lx hex)\n", ++ NetBootFileXferSize, ++ NetBootFileXferSize); ++ eth_halt(); ++ do_http_progress(HTTP_PROGRESS_UPLOAD_READY); ++ if(do_http_upgrade(&httpd_upload_data[0], NetBootFileXferSize) == 0) { ++ do_http_progress(HTTP_PROGRESS_UGRADE_READY); ++ udelay(1000 * 10); ++ do_reset (0,0,0,0); ++ return 0; ++ } ++ break; ++ } ++ https_running = 0; ++ NetBootFileXferSize = 0; ++ httpd_upload_complete = 0; ++ upload_running = 0; ++// free(httpd_upload_data); ++ ++ do_http_progress(HTTP_PROGRESS_UGRADE_FAILED); ++ ++ goto restart; ++ ++ return -1; ++} ++ ++#endif +--- /dev/null ++++ b/net/uip-0.9/Makefile +@@ -0,0 +1,54 @@ ++# Copyright (c) 2001, 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. All advertising materials mentioning features or use of this software ++# must display the following acknowledgement: ++# This product includes software developed by Adam Dunkels. ++# 4. 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 uIP TCP/IP stack. ++# ++# $Id: Makefile,v 1.8.2.2 2003/10/04 22:54:17 adam Exp $ ++# ++ ++CC=gcc ++CFLAGS=-Wall -fpack-struct -DDUMP=0 ++ ++all: uip ++ ++uip: uip.o uip_arch.o tapdev.o httpd.o main.o fs.o uip_arp.o ++ $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ ++ ++%.o: %.c ++ $(CC) $(CFLAGS) -c $^ -o $@ ++ ++clean: ++ rm -f *.o *~ *core uip ++ ++ ++ ++ ++ ++ +--- /dev/null ++++ b/net/uip-0.9/fs.c +@@ -0,0 +1,154 @@ ++/** ++ * \addtogroup httpd ++ * @{ ++ */ ++ ++/** ++ * \file ++ * HTTP server read-only file system code. ++ * \author Adam Dunkels ++ * ++ * A simple read-only filesystem. ++ */ ++ ++/* ++ * Copyright (c) 2001, Swedish Institute of Computer Science. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of the Institute nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * This file is part of the lwIP TCP/IP stack. ++ * ++ * Author: Adam Dunkels ++ * ++ * $Id: fs.c,v 1.7.2.3 2003/10/07 13:22:27 adam Exp $ ++ */ ++ ++#include "uip.h" ++#include "httpd.h" ++#include "fs.h" ++#include "fsdata.h" ++ ++#include "fsdata.c" ++ ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++static u16_t count[FS_NUMFILES]; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++ ++/*-----------------------------------------------------------------------------------*/ ++static u8_t ++fs_strcmp(const char *str1, const char *str2) ++{ ++ u8_t i; ++ i = 0; ++ loop: ++ ++ if(str2[i] == 0 || ++ str1[i] == '\r' || ++ str1[i] == '\n') { ++ return 0; ++ } ++ ++ if(str1[i] != str2[i]) { ++ return 1; ++ } ++ ++ ++ ++i; ++ goto loop; ++} ++/*-----------------------------------------------------------------------------------*/ ++int ++fs_open(const char *name, struct fs_file *file) ++{ ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ u16_t i = 0; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++ struct fsdata_file_noconst *f; ++ ++ for(f = (struct fsdata_file_noconst *)FS_ROOT; ++ f != NULL; ++ f = (struct fsdata_file_noconst *)f->next) { ++ ++ if(fs_strcmp(name, f->name) == 0) { ++ file->data = f->data; ++ file->len = f->len; ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ ++count[i]; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++ return 1; ++ } ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ ++i; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++ ++ } ++ return 0; ++} ++/*-----------------------------------------------------------------------------------*/ ++void ++fs_init(void) ++{ ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ u16_t i; ++ for(i = 0; i < FS_NUMFILES; i++) { ++ count[i] = 0; ++ } ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++} ++/*-----------------------------------------------------------------------------------*/ ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++u16_t fs_count ++(char *name) ++{ ++ struct fsdata_file_noconst *f; ++ u16_t i; ++ ++ i = 0; ++ for(f = (struct fsdata_file_noconst *)FS_ROOT; ++ f != NULL; ++ f = (struct fsdata_file_noconst *)f->next) { ++ ++ if(fs_strcmp(name, f->name) == 0) { ++ return count[i]; ++ } ++ ++i; ++ } ++ return 0; ++} ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++/*-----------------------------------------------------------------------------------*/ +--- /dev/null ++++ b/net/uip-0.9/fs.h +@@ -0,0 +1,80 @@ ++/** ++ * \addtogroup httpd ++ * @{ ++ */ ++ ++/** ++ * \file ++ * HTTP server read-only file system header file. ++ * \author Adam Dunkels ++ */ ++ ++/* ++ * Copyright (c) 2001, Swedish Institute of Computer Science. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of the Institute nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * This file is part of the lwIP TCP/IP stack. ++ * ++ * Author: Adam Dunkels ++ * ++ * $Id: fs.h,v 1.6.2.3 2003/10/07 13:22:27 adam Exp $ ++ */ ++#ifndef __FS_H__ ++#define __FS_H__ ++ ++#include "uip.h" ++ ++/** ++ * An open file in the read-only file system. ++ */ ++struct fs_file { ++ char *data; /**< The actual file data. */ ++ int len; /**< The length of the file data. */ ++}; ++ ++/** ++ * Open a file in the read-only file system. ++ * ++ * \param name The name of the file. ++ * ++ * \param file The file pointer, which must be allocated by caller and ++ * will be filled in by the function. ++ */ ++int fs_open(const char *name, struct fs_file *file); ++ ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++u16_t fs_count(char *name); ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++ ++/** ++ * Initialize the read-only file system. ++ */ ++void fs_init(void); ++ ++#endif /* __FS_H__ */ +--- /dev/null ++++ b/net/uip-0.9/fsdata.c +@@ -0,0 +1,199 @@ ++static const char data_flashing_html[] = { ++ /* /flashing.html */ ++ 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, ++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, ++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, ++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, ++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, ++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, ++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, ++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c, 0x62, ++ 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3d, ++ 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, ++ 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x20, 0x68, ++ 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x31, 0x30, 0x30, 0x25, ++ 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, ++ 0x66, 0x66, 0x66, 0x3b, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, ++ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, ++ 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, 0x62, 0x30, 0x33, 0x34, ++ 0x3b, 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, ++ 0x3e, 0x3c, 0x68, 0x31, 0x3e, 0x55, 0x70, 0x67, 0x72, 0x61, ++ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, ++ 0x6d, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f, 0x68, 0x31, ++ 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, ++ 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, ++ 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; ++ ++static const char data_fail_html[] = { ++ /* /fail.html */ ++ 0x2f, 0x66, 0x61, 0x69, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, ++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, ++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, ++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, ++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, ++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, ++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, ++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, ++ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, ++ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, ++ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, ++ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, ++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, ++ 0x3e, 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, ++ 0x9, 0x9, 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73, ++ 0x68, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, ++ 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9, 0x45, ++ 0x52, 0x52, 0x4f, 0x52, 0x20, 0x2d, 0x20, 0x74, 0x68, 0x65, ++ 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x79, 0x6f, 0x75, ++ 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x20, ++ 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, ++ 0x70, 0x61, 0x73, 0x73, 0x20, 0x76, 0x65, 0x72, 0x69, 0x66, ++ 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x50, ++ 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x6d, 0x61, 0x6b, 0x65, ++ 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x75, ++ 0x73, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x66, 0x66, 0x69, ++ 0x63, 0x69, 0x61, 0x6c, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, ++ 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, ++ 0x20, 0x62, 0x79, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, ++ 0x66, 0x6f, 0x6e, 0x6f, 0x73, 0x66, 0x65, 0x72, 0x61, 0x2e, ++ 0x6f, 0x72, 0x67, 0x2f, 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f, ++ 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, ++ 0x3e, 0xa, }; ++ ++static const char data_404_html[] = { ++ /* /404.html */ ++ 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x34, ++ 0x30, 0x34, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, ++ 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0xd, 0xa, 0x53, ++ 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, ++ 0x2f, 0x30, 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, ++ 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, ++ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, ++ 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, ++ 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, ++ 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, ++ 0xd, 0xa, 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, ++ 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, ++ 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, ++ 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, ++ 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, 0x20, ++ 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, ++ 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0x3c, ++ 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x2f, ++ 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d, ++ 0x6c, 0x3e, }; ++ ++static const char data_index_html[] = { ++ /* /index.html */ ++ 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, ++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, ++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, ++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, ++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, ++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, ++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, ++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, ++ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, ++ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, ++ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, ++ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, ++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, ++ 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, ++ 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, ++ 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, ++ 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, ++ 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, ++ 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, ++ 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62, ++ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, ++ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, ++ 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9, ++ 0x3c, 0x68, 0x31, 0x3e, 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, ++ 0x72, 0x61, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, ++ 0x65, 0x20, 0x55, 0x49, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, ++ 0x9, 0x9, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x65, ++ 0x74, 0x68, 0x6f, 0x64, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x74, ++ 0x22, 0x20, 0x65, 0x6e, 0x63, 0x74, 0x79, 0x70, 0x65, 0x3d, ++ 0x22, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, ++ 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x64, 0x61, 0x74, 0x61, ++ 0x22, 0x3e, 0xa, 0x9, 0x9, 0x9, 0x3c, 0x69, 0x6e, 0x70, ++ 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, ++ 0x6c, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x66, 0x69, ++ 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x3e, 0xa, 0x9, 0x9, ++ 0x9, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, ++ 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x3e, ++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e, ++ 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, ++ 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; ++ ++static const char data_flash_html[] = { ++ /* /flash.html */ ++ 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, ++ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, ++ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, ++ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, ++ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, ++ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, ++ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, ++ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, ++ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, ++ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, ++ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, ++ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, ++ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, ++ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, ++ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, ++ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, ++ 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, ++ 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, ++ 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, ++ 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, ++ 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, ++ 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, ++ 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62, ++ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, ++ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, ++ 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9, ++ 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x69, ++ 0x6e, 0x67, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9, ++ 0x54, 0x68, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, ++ 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x72, ++ 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x6c, ++ 0x61, 0x73, 0x68, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, ++ 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x70, ++ 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x2c, 0x20, 0x74, 0x68, ++ 0x65, 0x20, 0x6c, 0x65, 0x64, 0x73, 0x20, 0x77, 0x69, 0x6c, ++ 0x6c, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x6f, ++ 0x20, 0x62, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0xa, 0xa, 0x9, ++ 0x9, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, 0x61, 0x20, 0x73, ++ 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x6c, ++ 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, ++ 0x65, 0x20, 0x62, 0x6f, 0x78, 0x20, 0x77, 0x69, 0x6c, 0x6c, ++ 0x20, 0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0xa, 0x9, 0x3c, ++ 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, ++ 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; ++ ++const struct fsdata_file file_flashing_html[] = {{NULL, data_flashing_html, data_flashing_html + 15, sizeof(data_flashing_html) - 15}}; ++ ++const struct fsdata_file file_fail_html[] = {{file_flashing_html, data_fail_html, data_fail_html + 11, sizeof(data_fail_html) - 11}}; ++ ++const struct fsdata_file file_404_html[] = {{file_fail_html, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}}; ++ ++const struct fsdata_file file_index_html[] = {{file_404_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}}; ++ ++const struct fsdata_file file_flash_html[] = {{file_index_html, data_flash_html, data_flash_html + 12, sizeof(data_flash_html) - 12}}; ++ ++#define FS_ROOT file_flash_html ++ ++#define FS_NUMFILES 5 +\ No newline at end of file +--- /dev/null ++++ b/net/uip-0.9/fsdata.h +@@ -0,0 +1,64 @@ ++/* ++ * Copyright (c) 2001, Swedish Institute of Computer Science. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of the Institute nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * This file is part of the lwIP TCP/IP stack. ++ * ++ * Author: Adam Dunkels ++ * ++ * $Id: fsdata.h,v 1.4.2.1 2003/10/04 22:54:06 adam Exp $ ++ */ ++#ifndef __FSDATA_H__ ++#define __FSDATA_H__ ++ ++#include "uipopt.h" ++ ++struct fsdata_file { ++ const struct fsdata_file *next; ++ const char *name; ++ const char *data; ++ const int len; ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ u16_t count; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++}; ++ ++struct fsdata_file_noconst { ++ struct fsdata_file *next; ++ char *name; ++ char *data; ++ int len; ++#ifdef FS_STATISTICS ++#if FS_STATISTICS == 1 ++ u16_t count; ++#endif /* FS_STATISTICS */ ++#endif /* FS_STATISTICS */ ++}; ++ ++#endif /* __FSDATA_H__ */ +--- /dev/null ++++ b/net/uip-0.9/httpd.c +@@ -0,0 +1,278 @@ ++#include "uip.h" ++#include "httpd.h" ++#include "fs.h" ++#include "fsdata.h" ++#include ++ ++#define HTTP_NONE 0 ++#define HTTP_FILE 1 ++#define HTTP_FIRMWARE 2 ++ ++#define PRINT(x) printf("%s", x) ++#define PRINTLN(x) printf("%s\n", x) ++ ++extern unsigned long do_http_tmp_address(void); ++ ++struct httpd_state *hs; ++ ++extern const struct fsdata_file file_index_html; ++extern const struct fsdata_file file_404_html; ++extern const struct fsdata_file file_flash_html; ++extern int httpd_upload_complete; ++extern unsigned char *httpd_upload_data; ++unsigned char *upload_data; ++extern ulong NetBootFileXferSize; ++int upload_running = 0; ++ ++#define ISO_G 0x47 ++#define ISO_E 0x45 ++#define ISO_T 0x54 ++#define ISO_P 0x50 ++#define ISO_O 0x4f ++#define ISO_S 0x53 ++#define ISO_T 0x54 ++#define ISO_slash 0x2f ++#define ISO_c 0x63 ++#define ISO_g 0x67 ++#define ISO_i 0x69 ++#define ISO_space 0x20 ++#define ISO_nl 0x0a ++#define ISO_cr 0x0d ++#define ISO_a 0x61 ++#define ISO_t 0x74 ++#define ISO_hash 0x23 ++#define ISO_period 0x2e ++ ++static char eol[3] = { 0x0d, 0x0a, 0x00 }; ++static char eol2[5] = { 0x0d, 0x0a, 0x0d, 0x0a, 0x00 }; ++static char boundary[128]; ++static int boundary_len = 0; ++ ++/* we use this so that we can do without the ctype library */ ++#define is_digit(c) ((c) >= '0' && (c) <= '9') ++static int atoi(const char *s) ++{ ++ int i=0; ++ ++ while (is_digit(*s)) ++ i = i*10 + *(s++) - '0'; ++ return i; ++} ++ ++void ++httpd_init(void) ++{ ++ fs_init(); ++ uip_listen(HTONS(80)); ++} ++ ++void ++httpd_appcall(void) ++{ ++ struct fs_file fsfile; ++ u8_t i; ++ switch(uip_conn->lport) { ++ case HTONS(80): ++ hs = (struct httpd_state *)(uip_conn->appstate); ++ if(uip_connected()) ++ { ++ hs->state = HTTP_NONE; ++ hs->count = 0; ++ return; ++ } else if(uip_poll()) ++ { ++ if(hs->count++ >= 1000) { ++ uip_abort(); ++ } ++ return; ++ } else if(uip_newdata() && hs->state == HTTP_NONE) ++ { ++ if(uip_appdata[0] == ISO_G && ++ uip_appdata[1] == ISO_E && ++ uip_appdata[2] == ISO_T && ++ uip_appdata[3] == ISO_space) ++ { ++ hs->state = HTTP_FILE; ++ } ++ if(uip_appdata[0] == ISO_P && ++ uip_appdata[1] == ISO_O && ++ uip_appdata[2] == ISO_S && ++ uip_appdata[3] == ISO_T && ++ uip_appdata[4] == ISO_space) ++ { ++ hs->state = HTTP_FIRMWARE; ++ } ++ if(hs->state == HTTP_NONE) ++ { ++ uip_abort(); ++ return; ++ } ++ if(hs->state == HTTP_FILE) ++ { ++ for(i = 4; i < 40; ++i) ++ { ++ if(uip_appdata[i] == ISO_space || ++ uip_appdata[i] == ISO_cr || ++ uip_appdata[i] == ISO_nl) ++ { ++ uip_appdata[i] = 0; ++ break; ++ } ++ } ++ ++ PRINT("request for file "); ++ PRINTLN(&uip_appdata[4]); ++ if(uip_appdata[4] == ISO_slash && ++ uip_appdata[5] == 0) ++ { ++ fs_open(file_index_html.name, &fsfile); ++ } else { ++ if(!fs_open((const char *)&uip_appdata[4], &fsfile)) ++ { ++ PRINTLN("couldn't open file"); ++ fs_open(file_index_html.name, &fsfile); ++ } ++ } ++ hs->script = 0; ++ hs->state = HTTP_FILE; ++ hs->dataptr = fsfile.data; ++ hs->count = fsfile.len; ++ } ++ if(hs->state == HTTP_FIRMWARE) ++ { ++ unsigned char *start = (unsigned char*)uip_appdata; ++ char *clen = strstr(start, "Content-Length:"); ++ int len = 0; ++ unsigned char *next, *end; ++ unsigned char *boundary_start; ++ int i; ++ uip_appdata[uip_len] = '\0'; ++ if(clen) ++ { ++ clen += sizeof("Content-Length:"); ++ next = strstr(clen, eol); ++ if(next) ++ { ++ len = atoi(clen); ++ next++; ++ printf("expecting %d bytes\n", len); ++ upload_data = httpd_upload_data = (unsigned char *)do_http_tmp_address(); ++ printf("received data will be stored at 0x%08X\n", upload_data); ++ if(!upload_data) ++ { ++ printf("failed to allocate memory\n"); ++ uip_close(); ++ return; ++ } ++ } else { ++ uip_close(); ++ return; ++ } ++ } ++ if(len < 4 * 1024) ++ { ++ uip_close(); ++ return; ++ } ++ boundary_start = strstr(next, "---"); ++ if(!boundary_start) ++ { ++ uip_close(); ++ return; ++ } ++ end = strstr(boundary_start, eol); ++ if(!eol) ++ { ++ uip_close(); ++ return; ++ } ++ boundary_len = end - boundary_start; ++ memcpy(boundary, boundary_start, boundary_len); ++ boundary[boundary_len] = 0; ++ next = strstr(boundary_start, "name=\"firmware\";"); ++ if(!next) ++ { ++ uip_close(); ++ return; ++ } ++ next = strstr(next, eol2); ++ if(!next) ++ { ++ printf("could not find start of data\n"); ++ uip_close(); ++ return; ++ } ++ next += 4; ++ hs->script = 0; ++ hs->state = HTTP_FIRMWARE; ++ hs->upload = uip_len - (next - start); ++ hs->upload_total = len - (int)(next - boundary_start); ++ hs->upload_total -= (strlen(boundary) + 6); ++ //printf("storing %d bytes at %p\n", (int)hs->upload, upload_data); ++ for(i = 0; i < hs->upload; i++) ++ upload_data[i] = next[i]; ++ upload_data += (int)hs->upload; ++ printf("%d / %d\n", (int)hs->upload, hs->upload_total); ++ uip_slen = 0; ++ return; ++ } ++ } ++ ++ if(hs->state == HTTP_FIRMWARE) ++ { ++ if(uip_newdata()) ++ { ++ int i; ++ hs->count = 0; ++ uip_appdata[uip_len] = '\0'; ++ hs->upload += uip_len; ++ //printf("storing %d bytes at %p\n", uip_len, upload_data); ++ printf("%d / %d\n", (int)hs->upload, hs->upload_total); ++ for(i = 0; i < uip_len; i++) ++ upload_data[i] = uip_appdata[i]; ++ upload_data += uip_len; ++ uip_slen = 0; ++ if(hs->upload >= hs->upload_total) ++ { ++ upload_running = 1; ++ NetBootFileXferSize = hs->upload_total; ++ fs_open(file_flash_html.name, &fsfile); ++ hs->script = 0; ++ hs->state = HTTP_FILE; ++ hs->dataptr = fsfile.data; ++ hs->count = fsfile.len; ++ } ++ } ++ } ++ if(hs->state == HTTP_FILE) ++ { ++ if(uip_acked()) ++ { ++ if(hs->count >= uip_conn->len) ++ { ++ hs->count -= uip_conn->len; ++ hs->dataptr += uip_conn->len; ++ } else { ++ hs->count = 0; ++ } ++ if(hs->count == 0) ++ { ++ if(upload_running) ++ { ++ int i; ++ httpd_upload_complete = 1; ++ // for(i = 0; i < hs->upload_total; i++) ++ // printf("%c", httpd_upload_data[i]); ++ } ++ uip_close(); ++ } ++ } ++ uip_send(hs->dataptr, hs->count); ++ } ++ break; ++ ++ default: ++ uip_abort(); ++ break; ++ } ++} +--- /dev/null ++++ b/net/uip-0.9/httpd.h +@@ -0,0 +1,83 @@ ++/** ++ * \addtogroup httpd ++ * @{ ++ */ ++ ++/** ++ * \file ++ * HTTP server header file. ++ * \author Adam Dunkels ++ */ ++ ++/* ++ * Copyright (c) 2001, 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. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: httpd.h,v 1.4.2.3 2003/10/06 22:56:44 adam Exp $ ++ * ++ */ ++ ++#ifndef __HTTPD_H__ ++#define __HTTPD_H__ ++ ++void httpd_init(void); ++void httpd_appcall(void); ++ ++/* UIP_APPCALL: the name of the application function. This function ++ must return void and take no arguments (i.e., C type "void ++ appfunc(void)"). */ ++#ifndef UIP_APPCALL ++#define UIP_APPCALL httpd_appcall ++#endif ++ ++struct httpd_state { ++ u8_t state; ++ u16_t count; ++ char *dataptr; ++ char *script; ++ unsigned int upload; ++ unsigned int upload_total; ++}; ++ ++ ++/* UIP_APPSTATE_SIZE: The size of the application-specific state ++ stored in the uip_conn structure. */ ++#ifndef UIP_APPSTATE_SIZE ++#define UIP_APPSTATE_SIZE (sizeof(struct httpd_state)) ++#endif ++ ++#define FS_STATISTICS 1 ++ ++extern struct httpd_state *hs; ++ ++ ++/* we copy the data to RAM+10MB */ ++#define TMP_DATA 0x8A100000 ++ ++#endif /* __HTTPD_H__ */ +--- /dev/null ++++ b/net/uip-0.9/main.c +@@ -0,0 +1,88 @@ ++/* ++ * Copyright (c) 2001-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. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: main.c,v 1.10.2.1 2003/10/04 22:54:17 adam Exp $ ++ * ++ */ ++ ++ ++#include "uip.h" ++#include "uip_arp.h" ++#include "tapdev.h" ++#include "httpd.h" ++ ++#define BUF ((struct uip_eth_hdr *)&uip_buf[0]) ++ ++#ifndef NULL ++#define NULL (void *)0 ++#endif /* NULL */ ++ ++/*-----------------------------------------------------------------------------------*/ ++int ++main(void) ++{ ++ u8_t i, arptimer; ++ tapdev_init(); ++ uip_init(); ++ httpd_init(); ++ arptimer = 0; ++ while(1) { ++ uip_len = tapdev_read(); ++ if(uip_len == 0) { ++ for(i = 0; i < UIP_CONNS; i++) { ++ uip_periodic(i); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ tapdev_send(); ++ } ++ } ++ ++ if(++arptimer == 20) { ++ uip_arp_timer(); ++ arptimer = 0; ++ } ++ } else { ++ if(BUF->type == htons(UIP_ETHTYPE_IP)) { ++ uip_arp_ipin(); ++ uip_input(); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ tapdev_send(); ++ } ++ } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) { ++ uip_arp_arpin(); ++ if(uip_len > 0) { ++ tapdev_send(); ++ } ++ } ++ } ++ } ++ return 0; ++} +--- /dev/null ++++ b/net/uip-0.9/tapdev.c +@@ -0,0 +1,192 @@ ++/* ++ * Copyright (c) 2001, Swedish Institute of Computer Science. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * 3. Neither the name of the Institute nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * Author: Adam Dunkels ++ * ++ * $Id: tapdev.c,v 1.7.2.1 2003/10/07 13:23:19 adam Exp $ ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef linux ++#include ++#include ++#include ++#define DEVTAP "/dev/net/tun" ++#else /* linux */ ++#define DEVTAP "/dev/tap0" ++#endif /* linux */ ++ ++#include "uip.h" ++ ++static int fd; ++ ++static unsigned long lasttime; ++static struct timezone tz; ++ ++/*-----------------------------------------------------------------------------------*/ ++void ++tapdev_init(void) ++{ ++ char buf[1024]; ++ ++ fd = open(DEVTAP, O_RDWR); ++ if(fd == -1) { ++ perror("tapdev: tapdev_init: open"); ++ exit(1); ++ } ++ ++#ifdef linux ++ { ++ struct ifreq ifr; ++ memset(&ifr, 0, sizeof(ifr)); ++ ifr.ifr_flags = IFF_TAP|IFF_NO_PI; ++ if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) { ++ perror(buf); ++ exit(1); ++ } ++ } ++#endif /* Linux */ ++ ++ snprintf(buf, sizeof(buf), "ifconfig tap0 inet %d.%d.%d.%d", ++ UIP_DRIPADDR0, UIP_DRIPADDR1, UIP_DRIPADDR2, UIP_DRIPADDR3); ++ system(buf); ++ ++ lasttime = 0; ++} ++ ++void dump_mem(int type, int len) ++{ ++#if DUMP == 1 ++ int i; ++ for(i = 0; i < len; i++) ++ printf("%c", uip_buf[i]); ++ if(type) ++ { ++ printf("\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"); ++ printf("\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"); ++ } else { ++ printf("\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02"); ++ printf("\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02"); ++ } ++ fflush(stdout); ++#endif ++} ++ ++/*-----------------------------------------------------------------------------------*/ ++unsigned int ++tapdev_read(void) ++{ ++ fd_set fdset; ++ struct timeval tv, now; ++ int ret; ++ ++ if(lasttime >= 500000) { ++ lasttime = 0; ++ return 0; ++ } ++ ++ tv.tv_sec = 0; ++ tv.tv_usec = 500000 - lasttime; ++ ++ ++ FD_ZERO(&fdset); ++ FD_SET(fd, &fdset); ++ ++ gettimeofday(&now, &tz); ++ ret = select(fd + 1, &fdset, NULL, NULL, &tv); ++ if(ret == 0) { ++ lasttime = 0; ++ return 0; ++ } ++ ret = read(fd, uip_buf, UIP_BUFSIZE); ++ if(ret == -1) { ++ perror("tap_dev: tapdev_read: read"); ++ } ++ gettimeofday(&tv, &tz); ++ lasttime += (tv.tv_sec - now.tv_sec) * 1000000 + (tv.tv_usec - now.tv_usec); ++ dump_mem(0, ret); ++ return ret; ++} ++/*-----------------------------------------------------------------------------------*/ ++void ++tapdev_send(void) ++{ ++ int ret; ++ struct iovec iov[2]; ++ ++#ifdef linux ++ { ++ char tmpbuf[UIP_BUFSIZE]; ++ int i; ++ ++ for(i = 0; i < 40 + UIP_LLH_LEN; i++) { ++ tmpbuf[i] = uip_buf[i]; ++ } ++ ++ for(; i < uip_len; i++) { ++ tmpbuf[i] = uip_appdata[i - 40 - UIP_LLH_LEN]; ++ } ++ ++ ret = write(fd, tmpbuf, uip_len); ++ } ++#else ++ ++ if(uip_len < 40 + UIP_LLH_LEN) { ++ ret = write(fd, uip_buf, uip_len + UIP_LLH_LEN); ++ } else { ++ iov[0].iov_base = uip_buf; ++ iov[0].iov_len = 40 + UIP_LLH_LEN; ++ iov[1].iov_base = (char *)uip_appdata; ++ iov[1].iov_len = uip_len - (40 + UIP_LLH_LEN); ++ ++ ret = writev(fd, iov, 2); ++ } ++#endif ++ dump_mem(1, ret); ++ ++ if(ret == -1) { ++ perror("tap_dev: tapdev_send: writev"); ++ exit(1); ++ } ++} ++/*-----------------------------------------------------------------------------------*/ +--- /dev/null ++++ b/net/uip-0.9/tapdev.h +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (c) 2001, 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. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: tapdev.h,v 1.1.2.1 2003/10/04 22:54:17 adam Exp $ ++ * ++ */ ++ ++#ifndef __TAPDEV_H__ ++#define __TAPDEV_H__ ++ ++void tapdev_init(void); ++unsigned int tapdev_read(void); ++void tapdev_send(void); ++ ++#endif /* __TAPDEV_H__ */ +--- /dev/null ++++ b/net/uip-0.9/uip.c +@@ -0,0 +1,1503 @@ ++/** ++ * \addtogroup uip ++ * @{ ++ */ ++ ++/** ++ * \file ++ * The uIP TCP/IP stack code. ++ * \author Adam Dunkels ++ */ ++ ++/* ++ * Copyright (c) 2001-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. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip.c,v 1.62.2.10 2003/10/07 13:23:01 adam Exp $ ++ * ++ */ ++ ++/* ++This is a small implementation of the IP and TCP protocols (as well as ++some basic ICMP stuff). The implementation couples the IP, TCP and the ++application layers very tightly. To keep the size of the compiled code ++down, this code also features heavy usage of the goto statement. ++ ++The principle is that we have a small buffer, called the uip_buf, in ++which the device driver puts an incoming packet. The TCP/IP stack ++parses the headers in the packet, and calls upon the application. If ++the remote host has sent data to the application, this data is present ++in the uip_buf and the application read the data from there. It is up ++to the application to put this data into a byte stream if needed. The ++application will not be fed with data that is out of sequence. ++ ++If the application whishes to send data to the peer, it should put its ++data into the uip_buf, 40 bytes from the start of the buffer. The ++TCP/IP stack will calculate the checksums, and fill in the necessary ++header fields and finally send the packet back to the peer. ++*/ ++ ++#include "uip.h" ++#include "uipopt.h" ++#include "uip_arch.h" ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Variable definitions. */ ++ ++ ++/* The IP address of this host. If it is defined to be fixed (by setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set here. Otherwise, the address */ ++#if UIP_FIXEDADDR > 0 ++const unsigned short int uip_hostaddr[2] = ++ {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1), ++ HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)}; ++const unsigned short int uip_arp_draddr[2] = ++ {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1), ++ HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)}; ++const unsigned short int uip_arp_netmask[2] = ++ {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1), ++ HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)}; ++#else ++unsigned short int uip_hostaddr[2]; ++unsigned short int uip_arp_draddr[2], uip_arp_netmask[2]; ++#endif /* UIP_FIXEDADDR */ ++ ++u8_t uip_buf[UIP_BUFSIZE+2]; /* The packet buffer that contains ++ incoming packets. */ ++volatile u8_t *uip_appdata; /* The uip_appdata pointer points to ++ application data. */ ++volatile u8_t *uip_sappdata; /* The uip_appdata pointer points to the ++ application data which is to be sent. */ ++#if UIP_URGDATA > 0 ++volatile u8_t *uip_urgdata; /* The uip_urgdata pointer points to ++ urgent data (out-of-band data), if ++ present. */ ++volatile u8_t uip_urglen, uip_surglen; ++#endif /* UIP_URGDATA > 0 */ ++ ++volatile unsigned short int uip_len, uip_slen; ++ /* The uip_len is either 8 or 16 bits, ++ depending on the maximum packet ++ size. */ ++ ++volatile u8_t uip_flags; /* The uip_flags variable is used for ++ communication between the TCP/IP stack ++ and the application program. */ ++struct uip_conn *uip_conn; /* uip_conn always points to the current ++ connection. */ ++ ++struct uip_conn uip_conns[UIP_CONNS]; ++ /* The uip_conns array holds all TCP ++ connections. */ ++unsigned short int uip_listenports[UIP_LISTENPORTS]; ++ /* The uip_listenports list all currently ++ listning ports. */ ++#if UIP_UDP ++struct uip_udp_conn *uip_udp_conn; ++struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; ++#endif /* UIP_UDP */ ++ ++ ++static unsigned short int ipid; /* Ths ipid variable is an increasing ++ number that is used for the IP ID ++ field. */ ++ ++static u8_t iss[4]; /* The iss variable is used for the TCP ++ initial sequence number. */ ++ ++#if UIP_ACTIVE_OPEN ++static unsigned short int lastport; /* Keeps track of the last port used for ++ a new connection. */ ++#endif /* UIP_ACTIVE_OPEN */ ++ ++/* Temporary variables. */ ++volatile u8_t uip_acc32[4]; ++static u8_t c, opt; ++static unsigned short int tmp16; ++ ++/* Structures and definitions. */ ++#define TCP_FIN 0x01 ++#define TCP_SYN 0x02 ++#define TCP_RST 0x04 ++#define TCP_PSH 0x08 ++#define TCP_ACK 0x10 ++#define TCP_URG 0x20 ++#define TCP_CTL 0x3f ++ ++#define ICMP_ECHO_REPLY 0 ++#define ICMP_ECHO 8 ++ ++/* Macros. */ ++#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) ++#define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0]) ++#define ICMPBUF ((uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) ++#define UDPBUF ((uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) ++ ++#if UIP_STATISTICS == 1 ++struct uip_stats uip_stat; ++#define UIP_STAT(s) s ++#else ++#define UIP_STAT(s) ++#endif /* UIP_STATISTICS == 1 */ ++ ++#if UIP_LOGGING == 1 ++extern void puts(const char *s); ++#define UIP_LOG(m) puts(m) ++#else ++#define UIP_LOG(m) ++#endif /* UIP_LOGGING == 1 */ ++ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_init(void) ++{ ++ for(c = 0; c < UIP_LISTENPORTS; ++c) { ++ uip_listenports[c] = 0; ++ } ++ for(c = 0; c < UIP_CONNS; ++c) { ++ uip_conns[c].tcpstateflags = CLOSED; ++ } ++#if UIP_ACTIVE_OPEN ++ lastport = 1024; ++#endif /* UIP_ACTIVE_OPEN */ ++ ++#if UIP_UDP ++ for(c = 0; c < UIP_UDP_CONNS; ++c) { ++ uip_udp_conns[c].lport = 0; ++ } ++#endif /* UIP_UDP */ ++ ++ ++ /* IPv4 initialization. */ ++#if UIP_FIXEDADDR == 0 ++ uip_hostaddr[0] = uip_hostaddr[1] = 0; ++#endif /* UIP_FIXEDADDR */ ++ ++} ++/*-----------------------------------------------------------------------------------*/ ++#if UIP_ACTIVE_OPEN ++struct uip_conn * ++uip_connect(unsigned short int *ripaddr, unsigned short int rport) ++{ ++ register struct uip_conn *conn, *cconn; ++ ++ /* Find an unused local port. */ ++ again: ++ ++lastport; ++ ++ if(lastport >= 32000) { ++ lastport = 4096; ++ } ++ ++ /* Check if this port is already in use, and if so try to find ++ another one. */ ++ for(c = 0; c < UIP_CONNS; ++c) { ++ conn = &uip_conns[c]; ++ if(conn->tcpstateflags != CLOSED && ++ conn->lport == htons(lastport)) { ++ goto again; ++ } ++ } ++ ++ ++ conn = 0; ++ for(c = 0; c < UIP_CONNS; ++c) { ++ cconn = &uip_conns[c]; ++ if(cconn->tcpstateflags == CLOSED) { ++ conn = cconn; ++ break; ++ } ++ if(cconn->tcpstateflags == TIME_WAIT) { ++ if(conn == 0 || ++ cconn->timer > uip_conn->timer) { ++ conn = cconn; ++ } ++ } ++ } ++ ++ if(conn == 0) { ++ return 0; ++ } ++ ++ conn->tcpstateflags = SYN_SENT; ++ ++ conn->snd_nxt[0] = iss[0]; ++ conn->snd_nxt[1] = iss[1]; ++ conn->snd_nxt[2] = iss[2]; ++ conn->snd_nxt[3] = iss[3]; ++ ++ conn->initialmss = conn->mss = UIP_TCP_MSS; ++ ++ conn->len = 1; /* TCP length of the SYN is one. */ ++ conn->nrtx = 0; ++ conn->timer = 1; /* Send the SYN next time around. */ ++ conn->rto = UIP_RTO; ++ conn->sa = 0; ++ conn->sv = 16; ++ conn->lport = htons(lastport); ++ conn->rport = rport; ++ conn->ripaddr[0] = ripaddr[0]; ++ conn->ripaddr[1] = ripaddr[1]; ++ ++ return conn; ++} ++#endif /* UIP_ACTIVE_OPEN */ ++/*-----------------------------------------------------------------------------------*/ ++#if UIP_UDP ++struct uip_udp_conn * ++uip_udp_new(unsigned short int *ripaddr, unsigned short int rport) ++{ ++ register struct uip_udp_conn *conn; ++ ++ /* Find an unused local port. */ ++ again: ++ ++lastport; ++ ++ if(lastport >= 32000) { ++ lastport = 4096; ++ } ++ ++ for(c = 0; c < UIP_UDP_CONNS; ++c) { ++ if(uip_udp_conns[c].lport == lastport) { ++ goto again; ++ } ++ } ++ ++ ++ conn = 0; ++ for(c = 0; c < UIP_UDP_CONNS; ++c) { ++ if(uip_udp_conns[c].lport == 0) { ++ conn = &uip_udp_conns[c]; ++ break; ++ } ++ } ++ ++ if(conn == 0) { ++ return 0; ++ } ++ ++ conn->lport = HTONS(lastport); ++ conn->rport = HTONS(rport); ++ conn->ripaddr[0] = ripaddr[0]; ++ conn->ripaddr[1] = ripaddr[1]; ++ ++ return conn; ++} ++#endif /* UIP_UDP */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_unlisten(unsigned short int port) ++{ ++ for(c = 0; c < UIP_LISTENPORTS; ++c) { ++ if(uip_listenports[c] == port) { ++ uip_listenports[c] = 0; ++ return; ++ } ++ } ++} ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_listen(unsigned short int port) ++{ ++ for(c = 0; c < UIP_LISTENPORTS; ++c) { ++ if(uip_listenports[c] == 0) { ++ uip_listenports[c] = port; ++ return; ++ } ++ } ++} ++/*-----------------------------------------------------------------------------------*/ ++/* XXX: IP fragment reassembly: not well-tested. */ ++ ++#if UIP_REASSEMBLY ++#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN) ++static u8_t uip_reassbuf[UIP_REASS_BUFSIZE]; ++static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; ++static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, ++ 0x0f, 0x07, 0x03, 0x01}; ++static unsigned short int uip_reasslen; ++static u8_t uip_reassflags; ++#define UIP_REASS_FLAG_LASTFRAG 0x01 ++static u8_t uip_reasstmr; ++ ++#define IP_HLEN 20 ++#define IP_MF 0x20 ++ ++static u8_t ++uip_reass(void) ++{ ++ unsigned short int offset, len; ++ unsigned short int i; ++ ++ /* If ip_reasstmr is zero, no packet is present in the buffer, so we ++ write the IP header of the fragment into the reassembly ++ buffer. The timer is updated with the maximum age. */ ++ if(uip_reasstmr == 0) { ++ memcpy(uip_reassbuf, &BUF->vhl, IP_HLEN); ++ uip_reasstmr = UIP_REASS_MAXAGE; ++ uip_reassflags = 0; ++ /* Clear the bitmap. */ ++ memset(uip_reassbitmap, sizeof(uip_reassbitmap), 0); ++ } ++ ++ /* Check if the incoming fragment matches the one currently present ++ in the reasembly buffer. If so, we proceed with copying the ++ fragment into the buffer. */ ++ if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] && ++ BUF->srcipaddr[1] == FBUF->srcipaddr[1] && ++ BUF->destipaddr[0] == FBUF->destipaddr[0] && ++ BUF->destipaddr[1] == FBUF->destipaddr[1] && ++ BUF->ipid[0] == FBUF->ipid[0] && ++ BUF->ipid[1] == FBUF->ipid[1]) { ++ ++ len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4; ++ offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8; ++ ++ /* If the offset or the offset + fragment length overflows the ++ reassembly buffer, we discard the entire packet. */ ++ if(offset > UIP_REASS_BUFSIZE || ++ offset + len > UIP_REASS_BUFSIZE) { ++ uip_reasstmr = 0; ++ goto nullreturn; ++ } ++ ++ /* Copy the fragment into the reassembly buffer, at the right ++ offset. */ ++ memcpy(&uip_reassbuf[IP_HLEN + offset], ++ (char *)BUF + (int)((BUF->vhl & 0x0f) * 4), ++ len); ++ ++ /* Update the bitmap. */ ++ if(offset / (8 * 8) == (offset + len) / (8 * 8)) { ++ /* If the two endpoints are in the same byte, we only update ++ that byte. */ ++ ++ uip_reassbitmap[offset / (8 * 8)] |= ++ bitmap_bits[(offset / 8 ) & 7] & ++ ~bitmap_bits[((offset + len) / 8 ) & 7]; ++ } else { ++ /* If the two endpoints are in different bytes, we update the ++ bytes in the endpoints and fill the stuff inbetween with ++ 0xff. */ ++ uip_reassbitmap[offset / (8 * 8)] |= ++ bitmap_bits[(offset / 8 ) & 7]; ++ for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) { ++ uip_reassbitmap[i] = 0xff; ++ } ++ uip_reassbitmap[(offset + len) / (8 * 8)] |= ++ ~bitmap_bits[((offset + len) / 8 ) & 7]; ++ } ++ ++ /* If this fragment has the More Fragments flag set to zero, we ++ know that this is the last fragment, so we can calculate the ++ size of the entire packet. We also set the ++ IP_REASS_FLAG_LASTFRAG flag to indicate that we have received ++ the final fragment. */ ++ ++ if((BUF->ipoffset[0] & IP_MF) == 0) { ++ uip_reassflags |= UIP_REASS_FLAG_LASTFRAG; ++ uip_reasslen = offset + len; ++ } ++ ++ /* Finally, we check if we have a full packet in the buffer. We do ++ this by checking if we have the last fragment and if all bits ++ in the bitmap are set. */ ++ if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) { ++ /* Check all bytes up to and including all but the last byte in ++ the bitmap. */ ++ for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) { ++ if(uip_reassbitmap[i] != 0xff) { ++ goto nullreturn; ++ } ++ } ++ /* Check the last byte in the bitmap. It should contain just the ++ right amount of bits. */ ++ if(uip_reassbitmap[uip_reasslen / (8 * 8)] != ++ (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) { ++ goto nullreturn; ++ } ++ ++ /* If we have come this far, we have a full packet in the ++ buffer, so we allocate a pbuf and copy the packet into it. We ++ also reset the timer. */ ++ uip_reasstmr = 0; ++ memcpy(BUF, FBUF, uip_reasslen); ++ ++ /* Pretend to be a "normal" (i.e., not fragmented) IP packet ++ from now on. */ ++ BUF->ipoffset[0] = BUF->ipoffset[1] = 0; ++ BUF->len[0] = uip_reasslen >> 8; ++ BUF->len[1] = uip_reasslen & 0xff; ++ BUF->ipchksum = 0; ++ BUF->ipchksum = ~(uip_ipchksum()); ++ ++ return uip_reasslen; ++ } ++ } ++ ++ nullreturn: ++ return 0; ++} ++#endif /* UIP_REASSEMBL */ ++/*-----------------------------------------------------------------------------------*/ ++static void ++uip_add_rcv_nxt(unsigned short int n) ++{ ++ uip_add32(uip_conn->rcv_nxt, n); ++ uip_conn->rcv_nxt[0] = uip_acc32[0]; ++ uip_conn->rcv_nxt[1] = uip_acc32[1]; ++ uip_conn->rcv_nxt[2] = uip_acc32[2]; ++ uip_conn->rcv_nxt[3] = uip_acc32[3]; ++} ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_process(u8_t flag) ++{ ++ register struct uip_conn *uip_connr = uip_conn; ++ ++ uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; ++ ++ ++ /* Check if we were invoked because of the perodic timer fireing. */ ++ if(flag == UIP_TIMER) { ++#if UIP_REASSEMBLY ++ if(uip_reasstmr != 0) { ++ --uip_reasstmr; ++ } ++#endif /* UIP_REASSEMBLY */ ++ /* Increase the initial sequence number. */ ++ if(++iss[3] == 0) { ++ if(++iss[2] == 0) { ++ if(++iss[1] == 0) { ++ ++iss[0]; ++ } ++ } ++ } ++ uip_len = 0; ++ if(uip_connr->tcpstateflags == TIME_WAIT || ++ uip_connr->tcpstateflags == FIN_WAIT_2) { ++ ++(uip_connr->timer); ++ if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) { ++ uip_connr->tcpstateflags = CLOSED; ++ } ++ } else if(uip_connr->tcpstateflags != CLOSED) { ++ /* If the connection has outstanding data, we increase the ++ connection's timer and see if it has reached the RTO value ++ in which case we retransmit. */ ++ if(uip_outstanding(uip_connr)) { ++ if(uip_connr->timer-- == 0) { ++ if(uip_connr->nrtx == UIP_MAXRTX || ++ ((uip_connr->tcpstateflags == SYN_SENT || ++ uip_connr->tcpstateflags == SYN_RCVD) && ++ uip_connr->nrtx == UIP_MAXSYNRTX)) { ++ uip_connr->tcpstateflags = CLOSED; ++ ++ /* We call UIP_APPCALL() with uip_flags set to ++ UIP_TIMEDOUT to inform the application that the ++ connection has timed out. */ ++ uip_flags = UIP_TIMEDOUT; ++ UIP_APPCALL(); ++ ++ /* We also send a reset packet to the remote host. */ ++ BUF->flags = TCP_RST | TCP_ACK; ++ goto tcp_send_nodata; ++ } ++ ++ /* Exponential backoff. */ ++ uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4? ++ 4: ++ uip_connr->nrtx); ++ ++(uip_connr->nrtx); ++ ++ /* Ok, so we need to retransmit. We do this differently ++ depending on which state we are in. In ESTABLISHED, we ++ call upon the application so that it may prepare the ++ data for the retransmit. In SYN_RCVD, we resend the ++ SYNACK that we sent earlier and in LAST_ACK we have to ++ retransmit our FINACK. */ ++ UIP_STAT(++uip_stat.tcp.rexmit); ++ switch(uip_connr->tcpstateflags & TS_MASK) { ++ case SYN_RCVD: ++ /* In the SYN_RCVD state, we should retransmit our ++ SYNACK. */ ++ goto tcp_send_synack; ++ ++#if UIP_ACTIVE_OPEN ++ case SYN_SENT: ++ /* In the SYN_SENT state, we retransmit out SYN. */ ++ BUF->flags = 0; ++ goto tcp_send_syn; ++#endif /* UIP_ACTIVE_OPEN */ ++ ++ case ESTABLISHED: ++ /* In the ESTABLISHED state, we call upon the application ++ to do the actual retransmit after which we jump into ++ the code for sending out the packet (the apprexmit ++ label). */ ++ uip_len = 0; ++ uip_slen = 0; ++ uip_flags = UIP_REXMIT; ++ UIP_APPCALL(); ++ goto apprexmit; ++ ++ case FIN_WAIT_1: ++ case CLOSING: ++ case LAST_ACK: ++ /* In all these states we should retransmit a FINACK. */ ++ goto tcp_send_finack; ++ ++ } ++ } ++ } else if((uip_connr->tcpstateflags & TS_MASK) == ESTABLISHED) { ++ /* If there was no need for a retransmission, we poll the ++ application for new data. */ ++ uip_len = 0; ++ uip_slen = 0; ++ uip_flags = UIP_POLL; ++ UIP_APPCALL(); ++ goto appsend; ++ } ++ } ++ goto drop; ++ } ++#if UIP_UDP ++ if(flag == UIP_UDP_TIMER) { ++ if(uip_udp_conn->lport != 0) { ++ uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; ++ uip_len = uip_slen = 0; ++ uip_flags = UIP_POLL; ++ UIP_UDP_APPCALL(); ++ goto udp_send; ++ } else { ++ goto drop; ++ } ++ } ++#endif ++ ++ /* This is where the input processing starts. */ ++ UIP_STAT(++uip_stat.ip.recv); ++ ++ ++ /* Start of IPv4 input header processing code. */ ++ ++ /* Check validity of the IP header. */ ++ if(BUF->vhl != 0x45) { /* IP version and header length. */ ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_STAT(++uip_stat.ip.vhlerr); ++ UIP_LOG("ip: invalid version or header length."); ++ goto drop; ++ } ++ ++ /* Check the size of the packet. If the size reported to us in ++ uip_len doesn't match the size reported in the IP header, there ++ has been a transmission error and we drop the packet. */ ++ ++ if(BUF->len[0] != (uip_len >> 8)) { /* IP length, high byte. */ ++ uip_len = (uip_len & 0xff) | (BUF->len[0] << 8); ++ } ++ if(BUF->len[1] != (uip_len & 0xff)) { /* IP length, low byte. */ ++ uip_len = (uip_len & 0xff00) | BUF->len[1]; ++ } ++ ++ /* Check the fragment flag. */ ++ if((BUF->ipoffset[0] & 0x3f) != 0 || ++ BUF->ipoffset[1] != 0) { ++#if UIP_REASSEMBLY ++ uip_len = uip_reass(); ++ if(uip_len == 0) { ++ goto drop; ++ } ++#else ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_STAT(++uip_stat.ip.fragerr); ++ UIP_LOG("ip: fragment dropped."); ++ goto drop; ++#endif /* UIP_REASSEMBLY */ ++ } ++ ++ /* If we are configured to use ping IP address configuration and ++ hasn't been assigned an IP address yet, we accept all ICMP ++ packets. */ ++#if UIP_PINGADDRCONF ++ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { ++ if(BUF->proto == UIP_PROTO_ICMP) { ++ UIP_LOG("ip: possible ping config packet received."); ++ goto icmp_input; ++ } else { ++ UIP_LOG("ip: packet dropped since no address assigned."); ++ goto drop; ++ } ++ } ++#endif /* UIP_PINGADDRCONF */ ++ ++ /* Check if the packet is destined for our IP address. */ ++ if(BUF->destipaddr[0] != uip_hostaddr[0]) { ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_LOG("ip: packet not for us."); ++ goto drop; ++ } ++ if(BUF->destipaddr[1] != uip_hostaddr[1]) { ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_LOG("ip: packet not for us."); ++ goto drop; ++ } ++ ++ if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header ++ checksum. */ ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_STAT(++uip_stat.ip.chkerr); ++ UIP_LOG("ip: bad checksum."); ++ goto drop; ++ } ++ ++ if(BUF->proto == UIP_PROTO_TCP) /* Check for TCP packet. If so, jump ++ to the tcp_input label. */ ++ goto tcp_input; ++ ++#if UIP_UDP ++ if(BUF->proto == UIP_PROTO_UDP) ++ goto udp_input; ++#endif /* UIP_UDP */ ++ ++ if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from ++ here. */ ++ UIP_STAT(++uip_stat.ip.drop); ++ UIP_STAT(++uip_stat.ip.protoerr); ++ UIP_LOG("ip: neither tcp nor icmp."); ++ goto drop; ++ } ++ ++ //icmp_input: ++ UIP_STAT(++uip_stat.icmp.recv); ++ ++ /* ICMP echo (i.e., ping) processing. This is simple, we only change ++ the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP ++ checksum before we return the packet. */ ++ if(ICMPBUF->type != ICMP_ECHO) { ++ UIP_STAT(++uip_stat.icmp.drop); ++ UIP_STAT(++uip_stat.icmp.typeerr); ++ UIP_LOG("icmp: not icmp echo."); ++ goto drop; ++ } ++ ++ /* If we are configured to use ping IP address assignment, we use ++ the destination IP address of this ping packet and assign it to ++ ourself. */ ++#if UIP_PINGADDRCONF ++ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { ++ uip_hostaddr[0] = BUF->destipaddr[0]; ++ uip_hostaddr[1] = BUF->destipaddr[1]; ++ } ++#endif /* UIP_PINGADDRCONF */ ++ ++ ICMPBUF->type = ICMP_ECHO_REPLY; ++ ++ if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) { ++ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1; ++ } else { ++ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8); ++ } ++ ++ /* Swap IP addresses. */ ++ tmp16 = BUF->destipaddr[0]; ++ BUF->destipaddr[0] = BUF->srcipaddr[0]; ++ BUF->srcipaddr[0] = tmp16; ++ tmp16 = BUF->destipaddr[1]; ++ BUF->destipaddr[1] = BUF->srcipaddr[1]; ++ BUF->srcipaddr[1] = tmp16; ++ ++ UIP_STAT(++uip_stat.icmp.sent); ++ goto send; ++ ++ /* End of IPv4 input header processing code. */ ++ ++ ++#if UIP_UDP ++ /* UDP input processing. */ ++ udp_input: ++ /* UDP processing is really just a hack. We don't do anything to the ++ UDP/IP headers, but let the UDP application do all the hard ++ work. If the application sets uip_slen, it has a packet to ++ send. */ ++#if UIP_UDP_CHECKSUMS ++ if(uip_udpchksum() != 0xffff) { ++ UIP_STAT(++uip_stat.udp.drop); ++ UIP_STAT(++uip_stat.udp.chkerr); ++ UIP_LOG("udp: bad checksum."); ++ goto drop; ++ } ++#endif /* UIP_UDP_CHECKSUMS */ ++ ++ /* Demultiplex this UDP packet between the UDP "connections". */ ++ for(uip_udp_conn = &uip_udp_conns[0]; ++ uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; ++ ++uip_udp_conn) { ++ if(uip_udp_conn->lport != 0 && ++ UDPBUF->destport == uip_udp_conn->lport && ++ (uip_udp_conn->rport == 0 || ++ UDPBUF->srcport == uip_udp_conn->rport) && ++ BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] && ++ BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) { ++ goto udp_found; ++ } ++ } ++ goto drop; ++ ++ udp_found: ++ uip_len = uip_len - 28; ++ uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; ++ uip_flags = UIP_NEWDATA; ++ uip_slen = 0; ++ UIP_UDP_APPCALL(); ++ udp_send: ++ if(uip_slen == 0) { ++ goto drop; ++ } ++ uip_len = uip_slen + 28; ++ ++ BUF->len[0] = (uip_len >> 8); ++ BUF->len[1] = (uip_len & 0xff); ++ ++ BUF->proto = UIP_PROTO_UDP; ++ ++ UDPBUF->udplen = HTONS(uip_slen + 8); ++ UDPBUF->udpchksum = 0; ++#if UIP_UDP_CHECKSUMS ++ /* Calculate UDP checksum. */ ++ UDPBUF->udpchksum = ~(uip_udpchksum()); ++ if(UDPBUF->udpchksum == 0) { ++ UDPBUF->udpchksum = 0xffff; ++ } ++#endif /* UIP_UDP_CHECKSUMS */ ++ ++ BUF->srcport = uip_udp_conn->lport; ++ BUF->destport = uip_udp_conn->rport; ++ ++ BUF->srcipaddr[0] = uip_hostaddr[0]; ++ BUF->srcipaddr[1] = uip_hostaddr[1]; ++ BUF->destipaddr[0] = uip_udp_conn->ripaddr[0]; ++ BUF->destipaddr[1] = uip_udp_conn->ripaddr[1]; ++ ++ uip_appdata = &uip_buf[UIP_LLH_LEN + 40]; ++ goto ip_send_nolen; ++#endif /* UIP_UDP */ ++ ++ /* TCP input processing. */ ++ tcp_input: ++ UIP_STAT(++uip_stat.tcp.recv); ++ ++ /* Start of TCP input header processing code. */ ++ ++ if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP ++ checksum. */ ++ UIP_STAT(++uip_stat.tcp.drop); ++ UIP_STAT(++uip_stat.tcp.chkerr); ++ UIP_LOG("tcp: bad checksum."); ++ goto drop; ++ } ++ ++ /* Demultiplex this segment. */ ++ /* First check any active connections. */ ++ for(uip_connr = &uip_conns[0]; uip_connr < &uip_conns[UIP_CONNS]; ++uip_connr) { ++ if(uip_connr->tcpstateflags != CLOSED && ++ BUF->destport == uip_connr->lport && ++ BUF->srcport == uip_connr->rport && ++ BUF->srcipaddr[0] == uip_connr->ripaddr[0] && ++ BUF->srcipaddr[1] == uip_connr->ripaddr[1]) { ++ goto found; ++ } ++ } ++ ++ /* If we didn't find and active connection that expected the packet, ++ either this packet is an old duplicate, or this is a SYN packet ++ destined for a connection in LISTEN. If the SYN flag isn't set, ++ it is an old packet and we send a RST. */ ++ if((BUF->flags & TCP_CTL) != TCP_SYN) ++ goto reset; ++ ++ tmp16 = BUF->destport; ++ /* Next, check listening connections. */ ++ for(c = 0; c < UIP_LISTENPORTS; ++c) { ++ if(tmp16 == uip_listenports[c]) ++ goto found_listen; ++ } ++ ++ /* No matching connection found, so we send a RST packet. */ ++ UIP_STAT(++uip_stat.tcp.synrst); ++ reset: ++ ++ /* We do not send resets in response to resets. */ ++ if(BUF->flags & TCP_RST) ++ goto drop; ++ ++ UIP_STAT(++uip_stat.tcp.rst); ++ ++ BUF->flags = TCP_RST | TCP_ACK; ++ uip_len = 40; ++ BUF->tcpoffset = 5 << 4; ++ ++ /* Flip the seqno and ackno fields in the TCP header. */ ++ c = BUF->seqno[3]; ++ BUF->seqno[3] = BUF->ackno[3]; ++ BUF->ackno[3] = c; ++ ++ c = BUF->seqno[2]; ++ BUF->seqno[2] = BUF->ackno[2]; ++ BUF->ackno[2] = c; ++ ++ c = BUF->seqno[1]; ++ BUF->seqno[1] = BUF->ackno[1]; ++ BUF->ackno[1] = c; ++ ++ c = BUF->seqno[0]; ++ BUF->seqno[0] = BUF->ackno[0]; ++ BUF->ackno[0] = c; ++ ++ /* We also have to increase the sequence number we are ++ acknowledging. If the least significant byte overflowed, we need ++ to propagate the carry to the other bytes as well. */ ++ if(++BUF->ackno[3] == 0) { ++ if(++BUF->ackno[2] == 0) { ++ if(++BUF->ackno[1] == 0) { ++ ++BUF->ackno[0]; ++ } ++ } ++ } ++ ++ /* Swap port numbers. */ ++ tmp16 = BUF->srcport; ++ BUF->srcport = BUF->destport; ++ BUF->destport = tmp16; ++ ++ /* Swap IP addresses. */ ++ tmp16 = BUF->destipaddr[0]; ++ BUF->destipaddr[0] = BUF->srcipaddr[0]; ++ BUF->srcipaddr[0] = tmp16; ++ tmp16 = BUF->destipaddr[1]; ++ BUF->destipaddr[1] = BUF->srcipaddr[1]; ++ BUF->srcipaddr[1] = tmp16; ++ ++ ++ /* And send out the RST packet! */ ++ goto tcp_send_noconn; ++ ++ /* This label will be jumped to if we matched the incoming packet ++ with a connection in LISTEN. In that case, we should create a new ++ connection and send a SYNACK in return. */ ++ found_listen: ++ /* First we check if there are any connections avaliable. Unused ++ connections are kept in the same table as used connections, but ++ unused ones have the tcpstate set to CLOSED. Also, connections in ++ TIME_WAIT are kept track of and we'll use the oldest one if no ++ CLOSED connections are found. Thanks to Eddie C. Dost for a very ++ nice algorithm for the TIME_WAIT search. */ ++ uip_connr = 0; ++ for(c = 0; c < UIP_CONNS; ++c) { ++ if(uip_conns[c].tcpstateflags == CLOSED) { ++ uip_connr = &uip_conns[c]; ++ break; ++ } ++ if(uip_conns[c].tcpstateflags == TIME_WAIT) { ++ if(uip_connr == 0 || ++ uip_conns[c].timer > uip_connr->timer) { ++ uip_connr = &uip_conns[c]; ++ } ++ } ++ } ++ ++ if(uip_connr == 0) { ++ /* All connections are used already, we drop packet and hope that ++ the remote end will retransmit the packet at a time when we ++ have more spare connections. */ ++ UIP_STAT(++uip_stat.tcp.syndrop); ++ UIP_LOG("tcp: found no unused connections."); ++ goto drop; ++ } ++ uip_conn = uip_connr; ++ ++ /* Fill in the necessary fields for the new connection. */ ++ uip_connr->rto = uip_connr->timer = UIP_RTO; ++ uip_connr->sa = 0; ++ uip_connr->sv = 4; ++ uip_connr->nrtx = 0; ++ uip_connr->lport = BUF->destport; ++ uip_connr->rport = BUF->srcport; ++ uip_connr->ripaddr[0] = BUF->srcipaddr[0]; ++ uip_connr->ripaddr[1] = BUF->srcipaddr[1]; ++ uip_connr->tcpstateflags = SYN_RCVD; ++ ++ uip_connr->snd_nxt[0] = iss[0]; ++ uip_connr->snd_nxt[1] = iss[1]; ++ uip_connr->snd_nxt[2] = iss[2]; ++ uip_connr->snd_nxt[3] = iss[3]; ++ uip_connr->len = 1; ++ ++ /* rcv_nxt should be the seqno from the incoming packet + 1. */ ++ uip_connr->rcv_nxt[3] = BUF->seqno[3]; ++ uip_connr->rcv_nxt[2] = BUF->seqno[2]; ++ uip_connr->rcv_nxt[1] = BUF->seqno[1]; ++ uip_connr->rcv_nxt[0] = BUF->seqno[0]; ++ uip_add_rcv_nxt(1); ++ ++ /* Parse the TCP MSS option, if present. */ ++ if((BUF->tcpoffset & 0xf0) > 0x50) { ++ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { ++ opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; ++ if(opt == 0x00) { ++ /* End of options. */ ++ break; ++ } else if(opt == 0x01) { ++ ++c; ++ /* NOP option. */ ++ } else if(opt == 0x02 && ++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { ++ /* An MSS option with the right option length. */ ++ tmp16 = ((unsigned short int)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | ++ (unsigned short int)uip_buf[40 + UIP_LLH_LEN + 3 + c]; ++ uip_connr->initialmss = uip_connr->mss = ++ tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; ++ ++ /* And we are done processing options. */ ++ break; ++ } else { ++ /* All other options have a length field, so that we easily ++ can skip past them. */ ++ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { ++ /* If the length field is zero, the options are malformed ++ and we don't process them further. */ ++ break; ++ } ++ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; ++ } ++ } ++ } ++ ++ /* Our response will be a SYNACK. */ ++#if UIP_ACTIVE_OPEN ++ tcp_send_synack: ++ BUF->flags = TCP_ACK; ++ ++ tcp_send_syn: ++ BUF->flags |= TCP_SYN; ++#else /* UIP_ACTIVE_OPEN */ ++ tcp_send_synack: ++ BUF->flags = TCP_SYN | TCP_ACK; ++#endif /* UIP_ACTIVE_OPEN */ ++ ++ /* We send out the TCP Maximum Segment Size option with our ++ SYNACK. */ ++ BUF->optdata[0] = 2; ++ BUF->optdata[1] = 4; ++ BUF->optdata[2] = (UIP_TCP_MSS) / 256; ++ BUF->optdata[3] = (UIP_TCP_MSS) & 255; ++ uip_len = 44; ++ BUF->tcpoffset = 6 << 4; ++ goto tcp_send; ++ ++ /* This label will be jumped to if we found an active connection. */ ++ found: ++ uip_conn = uip_connr; ++ uip_flags = 0; ++ ++ /* We do a very naive form of TCP reset processing; we just accept ++ any RST and kill our connection. We should in fact check if the ++ sequence number of this reset is wihtin our advertised window ++ before we accept the reset. */ ++ if(BUF->flags & TCP_RST) { ++ uip_connr->tcpstateflags = CLOSED; ++ UIP_LOG("tcp: got reset, aborting connection."); ++ uip_flags = UIP_ABORT; ++ UIP_APPCALL(); ++ goto drop; ++ } ++ /* Calculated the length of the data, if the application has sent ++ any data to us. */ ++ c = (BUF->tcpoffset >> 4) << 2; ++ /* uip_len will contain the length of the actual TCP data. This is ++ calculated by subtracing the length of the TCP header (in ++ c) and the length of the IP header (20 bytes). */ ++ uip_len = uip_len - c - 20; ++ ++ /* First, check if the sequence number of the incoming packet is ++ what we're expecting next. If not, we send out an ACK with the ++ correct numbers in. */ ++ if(uip_len > 0 && ++ (BUF->seqno[0] != uip_connr->rcv_nxt[0] || ++ BUF->seqno[1] != uip_connr->rcv_nxt[1] || ++ BUF->seqno[2] != uip_connr->rcv_nxt[2] || ++ BUF->seqno[3] != uip_connr->rcv_nxt[3])) { ++ goto tcp_send_ack; ++ } ++ ++ /* Next, check if the incoming segment acknowledges any outstanding ++ data. If so, we update the sequence number, reset the length of ++ the outstanding data, calculate RTT estimations, and reset the ++ retransmission timer. */ ++ if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) { ++ uip_add32(uip_connr->snd_nxt, uip_connr->len); ++ if(BUF->ackno[0] == uip_acc32[0] && ++ BUF->ackno[1] == uip_acc32[1] && ++ BUF->ackno[2] == uip_acc32[2] && ++ BUF->ackno[3] == uip_acc32[3]) { ++ /* Update sequence number. */ ++ uip_connr->snd_nxt[0] = uip_acc32[0]; ++ uip_connr->snd_nxt[1] = uip_acc32[1]; ++ uip_connr->snd_nxt[2] = uip_acc32[2]; ++ uip_connr->snd_nxt[3] = uip_acc32[3]; ++ ++ ++ /* Do RTT estimation, unless we have done retransmissions. */ ++ if(uip_connr->nrtx == 0) { ++ signed char m; ++ m = uip_connr->rto - uip_connr->timer; ++ /* This is taken directly from VJs original code in his paper */ ++ m = m - (uip_connr->sa >> 3); ++ uip_connr->sa += m; ++ if(m < 0) { ++ m = -m; ++ } ++ m = m - (uip_connr->sv >> 2); ++ uip_connr->sv += m; ++ uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv; ++ ++ } ++ /* Set the acknowledged flag. */ ++ uip_flags = UIP_ACKDATA; ++ /* Reset the retransmission timer. */ ++ uip_connr->timer = uip_connr->rto; ++ } ++ ++ } ++ ++ /* Do different things depending on in what state the connection is. */ ++ switch(uip_connr->tcpstateflags & TS_MASK) { ++ /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not ++ implemented, since we force the application to close when the ++ peer sends a FIN (hence the application goes directly from ++ ESTABLISHED to LAST_ACK). */ ++ case SYN_RCVD: ++ /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and ++ we are waiting for an ACK that acknowledges the data we sent ++ out the last time. Therefore, we want to have the UIP_ACKDATA ++ flag set. If so, we enter the ESTABLISHED state. */ ++ if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = ESTABLISHED; ++ uip_flags = UIP_CONNECTED; ++ uip_connr->len = 0; ++ if(uip_len > 0) { ++ uip_flags |= UIP_NEWDATA; ++ uip_add_rcv_nxt(uip_len); ++ } ++ uip_slen = 0; ++ UIP_APPCALL(); ++ goto appsend; ++ } ++ goto drop; ++#if UIP_ACTIVE_OPEN ++ case SYN_SENT: ++ /* In SYN_SENT, we wait for a SYNACK that is sent in response to ++ our SYN. The rcv_nxt is set to sequence number in the SYNACK ++ plus one, and we send an ACK. We move into the ESTABLISHED ++ state. */ ++ if((uip_flags & UIP_ACKDATA) && ++ BUF->flags == (TCP_SYN | TCP_ACK)) { ++ ++ /* Parse the TCP MSS option, if present. */ ++ if((BUF->tcpoffset & 0xf0) > 0x50) { ++ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { ++ opt = uip_buf[40 + UIP_LLH_LEN + c]; ++ if(opt == 0x00) { ++ /* End of options. */ ++ break; ++ } else if(opt == 0x01) { ++ ++c; ++ /* NOP option. */ ++ } else if(opt == 0x02 && ++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { ++ /* An MSS option with the right option length. */ ++ tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | ++ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; ++ uip_connr->initialmss = ++ uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; ++ ++ /* And we are done processing options. */ ++ break; ++ } else { ++ /* All other options have a length field, so that we easily ++ can skip past them. */ ++ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { ++ /* If the length field is zero, the options are malformed ++ and we don't process them further. */ ++ break; ++ } ++ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; ++ } ++ } ++ } ++ uip_connr->tcpstateflags = ESTABLISHED; ++ uip_connr->rcv_nxt[0] = BUF->seqno[0]; ++ uip_connr->rcv_nxt[1] = BUF->seqno[1]; ++ uip_connr->rcv_nxt[2] = BUF->seqno[2]; ++ uip_connr->rcv_nxt[3] = BUF->seqno[3]; ++ uip_add_rcv_nxt(1); ++ uip_flags = UIP_CONNECTED | UIP_NEWDATA; ++ uip_connr->len = 0; ++ uip_len = 0; ++ uip_slen = 0; ++ UIP_APPCALL(); ++ goto appsend; ++ } ++ goto reset; ++#endif /* UIP_ACTIVE_OPEN */ ++ ++ case ESTABLISHED: ++ /* In the ESTABLISHED state, we call upon the application to feed ++ data into the uip_buf. If the UIP_ACKDATA flag is set, the ++ application should put new data into the buffer, otherwise we are ++ retransmitting an old segment, and the application should put that ++ data into the buffer. ++ ++ If the incoming packet is a FIN, we should close the connection on ++ this side as well, and we send out a FIN and enter the LAST_ACK ++ state. We require that there is no outstanding data; otherwise the ++ sequence numbers will be screwed up. */ ++ ++ if(BUF->flags & TCP_FIN) { ++ if(uip_outstanding(uip_connr)) { ++ goto drop; ++ } ++ uip_add_rcv_nxt(1 + uip_len); ++ uip_flags = UIP_CLOSE; ++ if(uip_len > 0) { ++ uip_flags |= UIP_NEWDATA; ++ } ++ UIP_APPCALL(); ++ uip_connr->len = 1; ++ uip_connr->tcpstateflags = LAST_ACK; ++ uip_connr->nrtx = 0; ++ tcp_send_finack: ++ BUF->flags = TCP_FIN | TCP_ACK; ++ goto tcp_send_nodata; ++ } ++ ++ /* Check the URG flag. If this is set, the segment carries urgent ++ data that we must pass to the application. */ ++ if(BUF->flags & TCP_URG) { ++#if UIP_URGDATA > 0 ++ uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1]; ++ if(uip_urglen > uip_len) { ++ /* There is more urgent data in the next segment to come. */ ++ uip_urglen = uip_len; ++ } ++ uip_add_rcv_nxt(uip_urglen); ++ uip_len -= uip_urglen; ++ uip_urgdata = uip_appdata; ++ uip_appdata += uip_urglen; ++ } else { ++ uip_urglen = 0; ++#endif /* UIP_URGDATA > 0 */ ++ uip_appdata += (BUF->urgp[0] << 8) | BUF->urgp[1]; ++ uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1]; ++ } ++ ++ ++ /* If uip_len > 0 we have TCP data in the packet, and we flag this ++ by setting the UIP_NEWDATA flag and update the sequence number ++ we acknowledge. If the application has stopped the dataflow ++ using uip_stop(), we must not accept any data packets from the ++ remote host. */ ++ if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) { ++ uip_flags |= UIP_NEWDATA; ++ uip_add_rcv_nxt(uip_len); ++ } ++ ++ /* Check if the available buffer space advertised by the other end ++ is smaller than the initial MSS for this connection. If so, we ++ set the current MSS to the window size to ensure that the ++ application does not send more data than the other end can ++ handle. ++ ++ If the remote host advertises a zero window, we set the MSS to ++ the initial MSS so that the application will send an entire MSS ++ of data. This data will not be acknowledged by the receiver, ++ and the application will retransmit it. This is called the ++ "persistent timer" and uses the retransmission mechanim. ++ */ ++ tmp16 = ((unsigned short int)BUF->wnd[0] << 8) + (unsigned short int)BUF->wnd[1]; ++ if(tmp16 > uip_connr->initialmss || ++ tmp16 == 0) { ++ tmp16 = uip_connr->initialmss; ++ } ++ uip_connr->mss = tmp16; ++ ++ /* If this packet constitutes an ACK for outstanding data (flagged ++ by the UIP_ACKDATA flag, we should call the application since it ++ might want to send more data. If the incoming packet had data ++ from the peer (as flagged by the UIP_NEWDATA flag), the ++ application must also be notified. ++ ++ When the application is called, the global variable uip_len ++ contains the length of the incoming data. The application can ++ access the incoming data through the global pointer ++ uip_appdata, which usually points 40 bytes into the uip_buf ++ array. ++ ++ If the application wishes to send any data, this data should be ++ put into the uip_appdata and the length of the data should be ++ put into uip_len. If the application don't have any data to ++ send, uip_len must be set to 0. */ ++ if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) { ++ uip_slen = 0; ++ UIP_APPCALL(); ++ ++ appsend: ++ ++ if(uip_flags & UIP_ABORT) { ++ uip_slen = 0; ++ uip_connr->tcpstateflags = CLOSED; ++ BUF->flags = TCP_RST | TCP_ACK; ++ goto tcp_send_nodata; ++ } ++ ++ if(uip_flags & UIP_CLOSE) { ++ uip_slen = 0; ++ uip_connr->len = 1; ++ uip_connr->tcpstateflags = FIN_WAIT_1; ++ uip_connr->nrtx = 0; ++ BUF->flags = TCP_FIN | TCP_ACK; ++ goto tcp_send_nodata; ++ } ++ ++ /* If uip_slen > 0, the application has data to be sent. */ ++ if(uip_slen > 0) { ++ ++ /* If the connection has acknowledged data, the contents of ++ the ->len variable should be discarded. */ ++ if((uip_flags & UIP_ACKDATA) != 0) { ++ uip_connr->len = 0; ++ } ++ ++ /* If the ->len variable is non-zero the connection has ++ already data in transit and cannot send anymore right ++ now. */ ++ if(uip_connr->len == 0) { ++ ++ /* The application cannot send more than what is allowed by ++ the mss (the minumum of the MSS and the available ++ window). */ ++ if(uip_slen > uip_connr->mss) { ++ uip_slen = uip_connr->mss; ++ } ++ ++ /* Remember how much data we send out now so that we know ++ when everything has been acknowledged. */ ++ uip_connr->len = uip_slen; ++ } else { ++ ++ /* If the application already had unacknowledged data, we ++ make sure that the application does not send (i.e., ++ retransmit) out more than it previously sent out. */ ++ uip_slen = uip_connr->len; ++ } ++ } else { ++ uip_connr->len = 0; ++ } ++ uip_connr->nrtx = 0; ++ apprexmit: ++ uip_appdata = uip_sappdata; ++ ++ /* If the application has data to be sent, or if the incoming ++ packet had new data in it, we must send out a packet. */ ++ if(uip_slen > 0 && uip_connr->len > 0) { ++ /* Add the length of the IP and TCP headers. */ ++ uip_len = uip_connr->len + UIP_TCPIP_HLEN; ++ /* We always set the ACK flag in response packets. */ ++ BUF->flags = TCP_ACK | TCP_PSH; ++ /* Send the packet. */ ++ goto tcp_send_noopts; ++ } ++ /* If there is no data to send, just send out a pure ACK if ++ there is newdata. */ ++ if(uip_flags & UIP_NEWDATA) { ++ uip_len = UIP_TCPIP_HLEN; ++ BUF->flags = TCP_ACK; ++ goto tcp_send_noopts; ++ } ++ } ++ goto drop; ++ case LAST_ACK: ++ /* We can close this connection if the peer has acknowledged our ++ FIN. This is indicated by the UIP_ACKDATA flag. */ ++ if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = CLOSED; ++ uip_flags = UIP_CLOSE; ++ UIP_APPCALL(); ++ } ++ break; ++ ++ case FIN_WAIT_1: ++ /* The application has closed the connection, but the remote host ++ hasn't closed its end yet. Thus we do nothing but wait for a ++ FIN from the other side. */ ++ if(uip_len > 0) { ++ uip_add_rcv_nxt(uip_len); ++ } ++ if(BUF->flags & TCP_FIN) { ++ if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = TIME_WAIT; ++ uip_connr->timer = 0; ++ uip_connr->len = 0; ++ } else { ++ uip_connr->tcpstateflags = CLOSING; ++ } ++ uip_add_rcv_nxt(1); ++ uip_flags = UIP_CLOSE; ++ UIP_APPCALL(); ++ goto tcp_send_ack; ++ } else if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = FIN_WAIT_2; ++ uip_connr->len = 0; ++ goto drop; ++ } ++ if(uip_len > 0) { ++ goto tcp_send_ack; ++ } ++ goto drop; ++ ++ case FIN_WAIT_2: ++ if(uip_len > 0) { ++ uip_add_rcv_nxt(uip_len); ++ } ++ if(BUF->flags & TCP_FIN) { ++ uip_connr->tcpstateflags = TIME_WAIT; ++ uip_connr->timer = 0; ++ uip_add_rcv_nxt(1); ++ uip_flags = UIP_CLOSE; ++ UIP_APPCALL(); ++ goto tcp_send_ack; ++ } ++ if(uip_len > 0) { ++ goto tcp_send_ack; ++ } ++ goto drop; ++ ++ case TIME_WAIT: ++ goto tcp_send_ack; ++ ++ case CLOSING: ++ if(uip_flags & UIP_ACKDATA) { ++ uip_connr->tcpstateflags = TIME_WAIT; ++ uip_connr->timer = 0; ++ } ++ } ++ goto drop; ++ ++ ++ /* We jump here when we are ready to send the packet, and just want ++ to set the appropriate TCP sequence numbers in the TCP header. */ ++ tcp_send_ack: ++ BUF->flags = TCP_ACK; ++ tcp_send_nodata: ++ uip_len = 40; ++ tcp_send_noopts: ++ BUF->tcpoffset = 5 << 4; ++ tcp_send: ++ /* We're done with the input processing. We are now ready to send a ++ reply. Our job is to fill in all the fields of the TCP and IP ++ headers before calculating the checksum and finally send the ++ packet. */ ++ BUF->ackno[0] = uip_connr->rcv_nxt[0]; ++ BUF->ackno[1] = uip_connr->rcv_nxt[1]; ++ BUF->ackno[2] = uip_connr->rcv_nxt[2]; ++ BUF->ackno[3] = uip_connr->rcv_nxt[3]; ++ ++ BUF->seqno[0] = uip_connr->snd_nxt[0]; ++ BUF->seqno[1] = uip_connr->snd_nxt[1]; ++ BUF->seqno[2] = uip_connr->snd_nxt[2]; ++ BUF->seqno[3] = uip_connr->snd_nxt[3]; ++ ++ BUF->proto = UIP_PROTO_TCP; ++ ++ BUF->srcport = uip_connr->lport; ++ BUF->destport = uip_connr->rport; ++ ++ BUF->srcipaddr[0] = uip_hostaddr[0]; ++ BUF->srcipaddr[1] = uip_hostaddr[1]; ++ BUF->destipaddr[0] = uip_connr->ripaddr[0]; ++ BUF->destipaddr[1] = uip_connr->ripaddr[1]; ++ ++ ++ if(uip_connr->tcpstateflags & UIP_STOPPED) { ++ /* If the connection has issued uip_stop(), we advertise a zero ++ window so that the remote host will stop sending data. */ ++ BUF->wnd[0] = BUF->wnd[1] = 0; ++ } else { ++ BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8); ++ BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff); ++ } ++ ++ tcp_send_noconn: ++ ++ BUF->len[0] = (uip_len >> 8); ++ BUF->len[1] = (uip_len & 0xff); ++ ++ /* Calculate TCP checksum. */ ++ BUF->tcpchksum = 0; ++ BUF->tcpchksum = ~(uip_tcpchksum()); ++ ++ //ip_send_nolen: ++ ++ BUF->vhl = 0x45; ++ BUF->tos = 0; ++ BUF->ipoffset[0] = BUF->ipoffset[1] = 0; ++ BUF->ttl = UIP_TTL; ++ ++ipid; ++ BUF->ipid[0] = ipid >> 8; ++ BUF->ipid[1] = ipid & 0xff; ++ ++ /* Calculate IP checksum. */ ++ BUF->ipchksum = 0; ++ BUF->ipchksum = ~(uip_ipchksum()); ++ ++ UIP_STAT(++uip_stat.tcp.sent); ++ send: ++ UIP_STAT(++uip_stat.ip.sent); ++ /* Return and let the caller do the actual transmission. */ ++ return; ++ drop: ++ uip_len = 0; ++ return; ++} ++/*-----------------------------------------------------------------------------------*/ ++/*unsigned short int ++htons(unsigned short int val) ++{ ++ return HTONS(val); ++}*/ ++/*-----------------------------------------------------------------------------------*/ ++/** @} */ +--- /dev/null ++++ b/net/uip-0.9/uip.h +@@ -0,0 +1,1066 @@ ++/** ++ * \addtogroup uip ++ * @{ ++ */ ++ ++/** ++ * \file ++ * Header file for the uIP TCP/IP stack. ++ * \author Adam Dunkels ++ * ++ * The uIP TCP/IP stack header file contains definitions for a number ++ * of C macros that are used by uIP programs as well as internal uIP ++ * structures, TCP/IP header structures and function declarations. ++ * ++ */ ++ ++ ++/* ++ * Copyright (c) 2001-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. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip.h,v 1.36.2.7 2003/10/07 13:47:51 adam Exp $ ++ * ++ */ ++ ++#ifndef __UIP_H__ ++#define __UIP_H__ ++#include ++#include ++#include ++#include ++#include ++ ++ ++#include "uipopt.h" ++ ++/*-----------------------------------------------------------------------------------*/ ++/* First, the functions that should be called from the ++ * system. Initialization, the periodic timer and incoming packets are ++ * handled by the following three functions. ++ */ ++ ++/** ++ * \defgroup uipconffunc uIP configuration functions ++ * @{ ++ * ++ * The uIP configuration functions are used for setting run-time ++ * parameters in uIP such as IP addresses. ++ */ ++ ++/** ++ * Set the IP address of this host. ++ * ++ * The IP address is represented as a 4-byte array where the first ++ * octet of the IP address is put in the first member of the 4-byte ++ * array. ++ * ++ * \param addr A pointer to a 4-byte representation of the IP address. ++ * ++ * \hideinitializer ++ */ ++#define uip_sethostaddr(addr) do { uip_hostaddr[0] = addr[0]; \ ++ uip_hostaddr[1] = addr[1]; } while(0) ++ ++/** ++ * Get the IP address of this host. ++ * ++ * The IP address is represented as a 4-byte array where the first ++ * octet of the IP address is put in the first member of the 4-byte ++ * array. ++ * ++ * \param addr A pointer to a 4-byte array that will be filled in with ++ * the currently configured IP address. ++ * ++ * \hideinitializer ++ */ ++#define uip_gethostaddr(addr) do { addr[0] = uip_hostaddr[0]; \ ++ addr[1] = uip_hostaddr[1]; } while(0) ++ ++/** @} */ ++ ++/** ++ * \defgroup uipinit uIP initialization functions ++ * @{ ++ * ++ * The uIP initialization functions are used for booting uIP. ++ */ ++ ++/** ++ * uIP initialization function. ++ * ++ * This function should be called at boot up to initilize the uIP ++ * TCP/IP stack. ++ */ ++void uip_init(void); ++ ++/** @} */ ++ ++/** ++ * \defgroup uipdevfunc uIP device driver functions ++ * @{ ++ * ++ * These functions are used by a network device driver for interacting ++ * with uIP. ++ */ ++ ++/** ++ * Process an incoming packet. ++ * ++ * This function should be called when the device driver has received ++ * a packet from the network. The packet from the device driver must ++ * be present in the uip_buf buffer, and the length of the packet ++ * should be placed in the uip_len variable. ++ * ++ * When the function returns, there may be an outbound packet placed ++ * in the uip_buf packet buffer. If so, the uip_len variable is set to ++ * the length of the packet. If no packet is to be sent out, the ++ * uip_len variable is set to 0. ++ * ++ * The usual way of calling the function is presented by the source ++ * code below. ++ \code ++ uip_len = devicedriver_poll(); ++ if(uip_len > 0) { ++ uip_input(); ++ if(uip_len > 0) { ++ devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \note If you are writing a uIP device driver that needs ARP ++ * (Address Resolution Protocol), e.g., when running uIP over ++ * Ethernet, you will need to call the uIP ARP code before calling ++ * this function: ++ \code ++ #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) ++ uip_len = ethernet_devicedrver_poll(); ++ if(uip_len > 0) { ++ if(BUF->type == HTONS(UIP_ETHTYPE_IP)) { ++ uip_arp_ipin(); ++ uip_input(); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ ethernet_devicedriver_send(); ++ } ++ } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { ++ uip_arp_arpin(); ++ if(uip_len > 0) { ++ ethernet_devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \hideinitializer ++ */ ++#define uip_input() uip_process(UIP_DATA) ++ ++/** ++ * Periodic processing for a connection identified by its number. ++ * ++ * This function does the necessary periodic processing (timers, ++ * polling) for a uIP TCP conneciton, and should be called when the ++ * periodic uIP timer goes off. It should be called for every ++ * connection, regardless of whether they are open of closed. ++ * ++ * When the function returns, it may have an outbound packet waiting ++ * for service in the uIP packet buffer, and if so the uip_len ++ * variable is set to a value larger than zero. The device driver ++ * should be called to send out the packet. ++ * ++ * The ususal way of calling the function is through a for() loop like ++ * this: ++ \code ++ for(i = 0; i < UIP_CONNS; ++i) { ++ uip_periodic(i); ++ if(uip_len > 0) { ++ devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \note If you are writing a uIP device driver that needs ARP ++ * (Address Resolution Protocol), e.g., when running uIP over ++ * Ethernet, you will need to call the uip_arp_out() function before ++ * calling the device driver: ++ \code ++ for(i = 0; i < UIP_CONNS; ++i) { ++ uip_periodic(i); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ ethernet_devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \param conn The number of the connection which is to be periodically polled. ++ * ++ * \hideinitializer ++ */ ++#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \ ++ uip_process(UIP_TIMER); } while (0) ++ ++/** ++ * Periodic processing for a connection identified by a pointer to its structure. ++ * ++ * Same as uip_periodic() but takes a pointer to the actual uip_conn ++ * struct instead of an integer as its argument. This function can be ++ * used to force periodic processing of a specific connection. ++ * ++ * \param conn A pointer to the uip_conn struct for the connection to ++ * be processed. ++ * ++ * \hideinitializer ++ */ ++#define uip_periodic_conn(conn) do { uip_conn = conn; \ ++ uip_process(UIP_TIMER); } while (0) ++ ++#if UIP_UDP ++/** ++ * Periodic processing for a UDP connection identified by its number. ++ * ++ * This function is essentially the same as uip_prerioic(), but for ++ * UDP connections. It is called in a similar fashion as the ++ * uip_periodic() function: ++ \code ++ for(i = 0; i < UIP_UDP_CONNS; i++) { ++ uip_udp_periodic(i); ++ if(uip_len > 0) { ++ devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \note As for the uip_periodic() function, special care has to be ++ * taken when using uIP together with ARP and Ethernet: ++ \code ++ for(i = 0; i < UIP_UDP_CONNS; i++) { ++ uip_udp_periodic(i); ++ if(uip_len > 0) { ++ uip_arp_out(); ++ ethernet_devicedriver_send(); ++ } ++ } ++ \endcode ++ * ++ * \param conn The number of the UDP connection to be processed. ++ * ++ * \hideinitializer ++ */ ++#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \ ++ uip_process(UIP_UDP_TIMER); } while (0) ++ ++/** ++ * Periodic processing for a UDP connection identified by a pointer to ++ * its structure. ++ * ++ * Same as uip_udp_periodic() but takes a pointer to the actual ++ * uip_conn struct instead of an integer as its argument. This ++ * function can be used to force periodic processing of a specific ++ * connection. ++ * ++ * \param conn A pointer to the uip_udp_conn struct for the connection ++ * to be processed. ++ * ++ * \hideinitializer ++ */ ++#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \ ++ uip_process(UIP_UDP_TIMER); } while (0) ++ ++ ++#endif /* UIP_UDP */ ++ ++/** ++ * The uIP packet buffer. ++ * ++ * The uip_buf array is used to hold incoming and outgoing ++ * packets. The device driver should place incoming data into this ++ * buffer. When sending data, the device driver should read the link ++ * level headers and the TCP/IP headers from this buffer. The size of ++ * the link level headers is configured by the UIP_LLH_LEN define. ++ * ++ * \note The application data need not be placed in this buffer, so ++ * the device driver must read it from the place pointed to by the ++ * uip_appdata pointer as illustrated by the following example: ++ \code ++ void ++ devicedriver_send(void) ++ { ++ hwsend(&uip_buf[0], UIP_LLH_LEN); ++ hwsend(&uip_buf[UIP_LLH_LEN], 40); ++ hwsend(uip_appdata, uip_len - 40 - UIP_LLH_LEN); ++ } ++ \endcode ++ */ ++extern u8_t uip_buf[UIP_BUFSIZE+2]; ++ ++/** @} */ ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Functions that are used by the uIP application program. Opening and ++ * closing connections, sending and receiving data, etc. is all ++ * handled by the functions below. ++*/ ++/** ++ * \defgroup uipappfunc uIP application functions ++ * @{ ++ * ++ * Functions used by an application running of top of uIP. ++ */ ++ ++/** ++ * Start listening to the specified port. ++ * ++ * \note Since this function expects the port number in network byte ++ * order, a conversion using HTONS() or htons() is necessary. ++ * ++ \code ++ uip_listen(HTONS(80)); ++ \endcode ++ * ++ * \param port A 16-bit port number in network byte order. ++ */ ++void uip_listen(u16_t port); ++ ++/** ++ * Stop listening to the specified port. ++ * ++ * \note Since this function expects the port number in network byte ++ * order, a conversion using HTONS() or htons() is necessary. ++ * ++ \code ++ uip_unlisten(HTONS(80)); ++ \endcode ++ * ++ * \param port A 16-bit port number in network byte order. ++ */ ++void uip_unlisten(u16_t port); ++ ++/** ++ * Connect to a remote host using TCP. ++ * ++ * This function is used to start a new connection to the specified ++ * port on the specied host. It allocates a new connection identifier, ++ * sets the connection to the SYN_SENT state and sets the ++ * retransmission timer to 0. This will cause a TCP SYN segment to be ++ * sent out the next time this connection is periodically processed, ++ * which usually is done within 0.5 seconds after the call to ++ * uip_connect(). ++ * ++ * \note This function is avaliable only if support for active open ++ * has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h. ++ * ++ * \note Since this function requires the port number to be in network ++ * byte order, a convertion using HTONS() or htons() is necessary. ++ * ++ \code ++ u16_t ipaddr[2]; ++ ++ uip_ipaddr(ipaddr, 192,168,1,2); ++ uip_connect(ipaddr, HTONS(80)); ++ \endcode ++ * ++ * \param ripaddr A pointer to a 4-byte array representing the IP ++ * address of the remote hot. ++ * ++ * \param port A 16-bit port number in network byte order. ++ * ++ * \return A pointer to the uIP connection identifier for the new connection, ++ * or NULL if no connection could be allocated. ++ * ++ */ ++struct uip_conn *uip_connect(u16_t *ripaddr, u16_t port); ++ ++ ++ ++/** ++ * \internal ++ * ++ * Check if a connection has outstanding (i.e., unacknowledged) data. ++ * ++ * \param conn A pointer to the uip_conn structure for the connection. ++ * ++ * \hideinitializer ++ */ ++#define uip_outstanding(conn) ((conn)->len) ++ ++/** ++ * Send data on the current connection. ++ * ++ * This function is used to send out a single segment of TCP ++ * data. Only applications that have been invoked by uIP for event ++ * processing can send data. ++ * ++ * The amount of data that actually is sent out after a call to this ++ * funcion is determined by the maximum amount of data TCP allows. uIP ++ * will automatically crop the data so that only the appropriate ++ * amount of data is sent. The function uip_mss() can be used to query ++ * uIP for the amount of data that actually will be sent. ++ * ++ * \note This function does not guarantee that the sent data will ++ * arrive at the destination. If the data is lost in the network, the ++ * application will be invoked with the uip_rexmit() event being ++ * set. The application will then have to resend the data using this ++ * function. ++ * ++ * \param data A pointer to the data which is to be sent. ++ * ++ * \param len The maximum amount of data bytes to be sent. ++ * ++ * \hideinitializer ++ */ ++#define uip_send(data, len) do { uip_sappdata = (data); uip_slen = (len);} while(0) ++ ++/** ++ * The length of any incoming data that is currently avaliable (if avaliable) ++ * in the uip_appdata buffer. ++ * ++ * The test function uip_data() must first be used to check if there ++ * is any data available at all. ++ * ++ * \hideinitializer ++ */ ++#define uip_datalen() uip_len ++ ++/** ++ * The length of any out-of-band data (urgent data) that has arrived ++ * on the connection. ++ * ++ * \note The configuration parameter UIP_URGDATA must be set for this ++ * function to be enabled. ++ * ++ * \hideinitializer ++ */ ++#define uip_urgdatalen() uip_urglen ++ ++/** ++ * Close the current connection. ++ * ++ * This function will close the current connection in a nice way. ++ * ++ * \hideinitializer ++ */ ++#define uip_close() (uip_flags = UIP_CLOSE) ++ ++/** ++ * Abort the current connection. ++ * ++ * This function will abort (reset) the current connection, and is ++ * usually used when an error has occured that prevents using the ++ * uip_close() function. ++ * ++ * \hideinitializer ++ */ ++#define uip_abort() (uip_flags = UIP_ABORT) ++ ++/** ++ * Tell the sending host to stop sending data. ++ * ++ * This function will close our receiver's window so that we stop ++ * receiving data for the current connection. ++ * ++ * \hideinitializer ++ */ ++#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED) ++ ++/** ++ * Find out if the current connection has been previously stopped with ++ * uip_stop(). ++ * ++ * \hideinitializer ++ */ ++#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED) ++ ++/** ++ * Restart the current connection, if is has previously been stopped ++ * with uip_stop(). ++ * ++ * This function will open the receiver's window again so that we ++ * start receiving data for the current connection. ++ * ++ * \hideinitializer ++ */ ++#define uip_restart() do { uip_flags |= UIP_NEWDATA; \ ++ uip_conn->tcpstateflags &= ~UIP_STOPPED; \ ++ } while(0) ++ ++ ++/* uIP tests that can be made to determine in what state the current ++ connection is, and what the application function should do. */ ++ ++/** ++ * Is new incoming data available? ++ * ++ * Will reduce to non-zero if there is new data for the application ++ * present at the uip_appdata pointer. The size of the data is ++ * avaliable through the uip_len variable. ++ * ++ * \hideinitializer ++ */ ++#define uip_newdata() (uip_flags & UIP_NEWDATA) ++ ++/** ++ * Has previously sent data been acknowledged? ++ * ++ * Will reduce to non-zero if the previously sent data has been ++ * acknowledged by the remote host. This means that the application ++ * can send new data. ++ * ++ * \hideinitializer ++ */ ++#define uip_acked() (uip_flags & UIP_ACKDATA) ++ ++/** ++ * Has the connection just been connected? ++ * ++ * Reduces to non-zero if the current connection has been connected to ++ * a remote host. This will happen both if the connection has been ++ * actively opened (with uip_connect()) or passively opened (with ++ * uip_listen()). ++ * ++ * \hideinitializer ++ */ ++#define uip_connected() (uip_flags & UIP_CONNECTED) ++ ++/** ++ * Has the connection been closed by the other end? ++ * ++ * Is non-zero if the connection has been closed by the remote ++ * host. The application may then do the necessary clean-ups. ++ * ++ * \hideinitializer ++ */ ++#define uip_closed() (uip_flags & UIP_CLOSE) ++ ++/** ++ * Has the connection been aborted by the other end? ++ * ++ * Non-zero if the current connection has been aborted (reset) by the ++ * remote host. ++ * ++ * \hideinitializer ++ */ ++#define uip_aborted() (uip_flags & UIP_ABORT) ++ ++/** ++ * Has the connection timed out? ++ * ++ * Non-zero if the current connection has been aborted due to too many ++ * retransmissions. ++ * ++ * \hideinitializer ++ */ ++#define uip_timedout() (uip_flags & UIP_TIMEDOUT) ++ ++/** ++ * Do we need to retransmit previously data? ++ * ++ * Reduces to non-zero if the previously sent data has been lost in ++ * the network, and the application should retransmit it. The ++ * application should send the exact same data as it did the last ++ * time, using the uip_send() function. ++ * ++ * \hideinitializer ++ */ ++#define uip_rexmit() (uip_flags & UIP_REXMIT) ++ ++/** ++ * Is the connection being polled by uIP? ++ * ++ * Is non-zero if the reason the application is invoked is that the ++ * current connection has been idle for a while and should be ++ * polled. ++ * ++ * The polling event can be used for sending data without having to ++ * wait for the remote host to send data. ++ * ++ * \hideinitializer ++ */ ++#define uip_poll() (uip_flags & UIP_POLL) ++ ++/** ++ * Get the initial maxium segment size (MSS) of the current ++ * connection. ++ * ++ * \hideinitializer ++ */ ++#define uip_initialmss() (uip_conn->initialmss) ++ ++/** ++ * Get the current maxium segment size that can be sent on the current ++ * connection. ++ * ++ * The current maxiumum segment size that can be sent on the ++ * connection is computed from the receiver's window and the MSS of ++ * the connection (which also is available by calling ++ * uip_initialmss()). ++ * ++ * \hideinitializer ++ */ ++#define uip_mss() (uip_conn->mss) ++ ++/** ++ * Set up a new UDP connection. ++ * ++ * \param ripaddr A pointer to a 4-byte structure representing the IP ++ * address of the remote host. ++ * ++ * \param rport The remote port number in network byte order. ++ * ++ * \return The uip_udp_conn structure for the new connection or NULL ++ * if no connection could be allocated. ++ */ ++struct uip_udp_conn *uip_udp_new(u16_t *ripaddr, u16_t rport); ++ ++/** ++ * Removed a UDP connection. ++ * ++ * \param conn A pointer to the uip_udp_conn structure for the connection. ++ * ++ * \hideinitializer ++ */ ++#define uip_udp_remove(conn) (conn)->lport = 0 ++ ++/** ++ * Send a UDP datagram of length len on the current connection. ++ * ++ * This function can only be called in response to a UDP event (poll ++ * or newdata). The data must be present in the uip_buf buffer, at the ++ * place pointed to by the uip_appdata pointer. ++ * ++ * \param len The length of the data in the uip_buf buffer. ++ * ++ * \hideinitializer ++ */ ++#define uip_udp_send(len) uip_slen = (len) ++ ++/** @} */ ++ ++/* uIP convenience and converting functions. */ ++ ++/** ++ * \defgroup uipconvfunc uIP conversion functions ++ * @{ ++ * ++ * These functions can be used for converting between different data ++ * formats used by uIP. ++ */ ++ ++/** ++ * Pack an IP address into a 4-byte array which is used by uIP to ++ * represent IP addresses. ++ * ++ * Example: ++ \code ++ u16_t ipaddr[2]; ++ ++ uip_ipaddr(&ipaddr, 192,168,1,2); ++ \endcode ++ * ++ * \param addr A pointer to a 4-byte array that will be filled in with ++ * the IP addres. ++ * \param addr0 The first octet of the IP address. ++ * \param addr1 The second octet of the IP address. ++ * \param addr2 The third octet of the IP address. ++ * \param addr3 The forth octet of the IP address. ++ * ++ * \hideinitializer ++ */ ++#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ ++ (addr)[0] = HTONS(((addr0) << 8) | (addr1)); \ ++ (addr)[1] = HTONS(((addr2) << 8) | (addr3)); \ ++ } while(0) ++ ++/** ++ * Convert 16-bit quantity from host byte order to network byte order. ++ * ++ * This macro is primarily used for converting constants from host ++ * byte order to network byte order. For converting variables to ++ * network byte order, use the htons() function instead. ++ * ++ * \hideinitializer ++ */ ++#ifndef HTONS ++# if BYTE_ORDER == BIG_ENDIAN ++# define HTONS(n) (n) ++# else /* BYTE_ORDER == BIG_ENDIAN */ ++# define HTONS(n) ((((u16_t)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8)) ++# endif /* BYTE_ORDER == BIG_ENDIAN */ ++#endif /* HTONS */ ++ ++/** ++ * Convert 16-bit quantity from host byte order to network byte order. ++ * ++ * This function is primarily used for converting variables from host ++ * byte order to network byte order. For converting constants to ++ * network byte order, use the HTONS() macro instead. ++ */ ++#ifndef htons ++u16_t htons(u16_t val); ++#endif /* htons */ ++ ++/** @} */ ++ ++/** ++ * Pointer to the application data in the packet buffer. ++ * ++ * This pointer points to the application data when the application is ++ * called. If the application wishes to send data, the application may ++ * use this space to write the data into before calling uip_send(). ++ */ ++extern volatile u8_t *uip_appdata; ++extern volatile u8_t *uip_sappdata; ++ ++#if UIP_URGDATA > 0 ++/* u8_t *uip_urgdata: ++ * ++ * This pointer points to any urgent data that has been received. Only ++ * present if compiled with support for urgent data (UIP_URGDATA). ++ */ ++extern volatile u8_t *uip_urgdata; ++#endif /* UIP_URGDATA > 0 */ ++ ++ ++/* u[8|16]_t uip_len: ++ * ++ * When the application is called, uip_len contains the length of any ++ * new data that has been received from the remote host. The ++ * application should set this variable to the size of any data that ++ * the application wishes to send. When the network device driver ++ * output function is called, uip_len should contain the length of the ++ * outgoing packet. ++ */ ++extern volatile u16_t uip_len, uip_slen; ++ ++#if UIP_URGDATA > 0 ++extern volatile u8_t uip_urglen, uip_surglen; ++#endif /* UIP_URGDATA > 0 */ ++ ++ ++/** ++ * Representation of a uIP TCP connection. ++ * ++ * The uip_conn structure is used for identifying a connection. All ++ * but one field in the structure are to be considered read-only by an ++ * application. The only exception is the appstate field whos purpose ++ * is to let the application store application-specific state (e.g., ++ * file pointers) for the connection. The size of this field is ++ * configured in the "uipopt.h" header file. ++ */ ++struct uip_conn { ++ u16_t ripaddr[2]; /**< The IP address of the remote host. */ ++ ++ u16_t lport; /**< The local TCP port, in network byte order. */ ++ u16_t rport; /**< The local remote TCP port, in network byte ++ order. */ ++ ++ u8_t rcv_nxt[4]; /**< The sequence number that we expect to ++ receive next. */ ++ u8_t snd_nxt[4]; /**< The sequence number that was last sent by ++ us. */ ++ u16_t len; /**< Length of the data that was previously sent. */ ++ u16_t mss; /**< Current maximum segment size for the ++ connection. */ ++ u16_t initialmss; /**< Initial maximum segment size for the ++ connection. */ ++ u8_t sa; /**< Retransmission time-out calculation state ++ variable. */ ++ u8_t sv; /**< Retransmission time-out calculation state ++ variable. */ ++ u8_t rto; /**< Retransmission time-out. */ ++ u8_t tcpstateflags; /**< TCP state and flags. */ ++ u8_t timer; /**< The retransmission timer. */ ++ u8_t nrtx; /**< The number of retransmissions for the last ++ segment sent. */ ++ ++ /** The application state. */ ++ u8_t appstate[UIP_APPSTATE_SIZE]; ++}; ++ ++ ++/* Pointer to the current connection. */ ++extern struct uip_conn *uip_conn; ++/* The array containing all uIP connections. */ ++extern struct uip_conn uip_conns[UIP_CONNS]; ++/** ++ * \addtogroup uiparch ++ * @{ ++ */ ++ ++/** ++ * 4-byte array used for the 32-bit sequence number calculations. ++ */ ++extern volatile u8_t uip_acc32[4]; ++ ++/** @} */ ++ ++ ++#if UIP_UDP ++/** ++ * Representation of a uIP UDP connection. ++ */ ++struct uip_udp_conn { ++ u16_t ripaddr[2]; /**< The IP address of the remote peer. */ ++ u16_t lport; /**< The local port number in network byte order. */ ++ u16_t rport; /**< The remote port number in network byte order. */ ++}; ++ ++extern struct uip_udp_conn *uip_udp_conn; ++extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; ++#endif /* UIP_UDP */ ++ ++/** ++ * The structure holding the TCP/IP statistics that are gathered if ++ * UIP_STATISTICS is set to 1. ++ * ++ */ ++struct uip_stats { ++ struct { ++ uip_stats_t drop; /**< Number of dropped packets at the IP ++ layer. */ ++ uip_stats_t recv; /**< Number of received packets at the IP ++ layer. */ ++ uip_stats_t sent; /**< Number of sent packets at the IP ++ layer. */ ++ uip_stats_t vhlerr; /**< Number of packets dropped due to wrong ++ IP version or header length. */ ++ uip_stats_t hblenerr; /**< Number of packets dropped due to wrong ++ IP length, high byte. */ ++ uip_stats_t lblenerr; /**< Number of packets dropped due to wrong ++ IP length, low byte. */ ++ uip_stats_t fragerr; /**< Number of packets dropped since they ++ were IP fragments. */ ++ uip_stats_t chkerr; /**< Number of packets dropped due to IP ++ checksum errors. */ ++ uip_stats_t protoerr; /**< Number of packets dropped since they ++ were neither ICMP, UDP nor TCP. */ ++ } ip; /**< IP statistics. */ ++ struct { ++ uip_stats_t drop; /**< Number of dropped ICMP packets. */ ++ uip_stats_t recv; /**< Number of received ICMP packets. */ ++ uip_stats_t sent; /**< Number of sent ICMP packets. */ ++ uip_stats_t typeerr; /**< Number of ICMP packets with a wrong ++ type. */ ++ } icmp; /**< ICMP statistics. */ ++ struct { ++ uip_stats_t drop; /**< Number of dropped TCP segments. */ ++ uip_stats_t recv; /**< Number of recived TCP segments. */ ++ uip_stats_t sent; /**< Number of sent TCP segments. */ ++ uip_stats_t chkerr; /**< Number of TCP segments with a bad ++ checksum. */ ++ uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK ++ number. */ ++ uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */ ++ uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */ ++ uip_stats_t syndrop; /**< Number of dropped SYNs due to too few ++ connections was avaliable. */ ++ uip_stats_t synrst; /**< Number of SYNs for closed ports, ++ triggering a RST. */ ++ } tcp; /**< TCP statistics. */ ++}; ++ ++/** ++ * The uIP TCP/IP statistics. ++ * ++ * This is the variable in which the uIP TCP/IP statistics are gathered. ++ */ ++extern struct uip_stats uip_stat; ++ ++ ++/*-----------------------------------------------------------------------------------*/ ++/* All the stuff below this point is internal to uIP and should not be ++ * used directly by an application or by a device driver. ++ */ ++/*-----------------------------------------------------------------------------------*/ ++/* u8_t uip_flags: ++ * ++ * When the application is called, uip_flags will contain the flags ++ * that are defined in this file. Please read below for more ++ * infomation. ++ */ ++extern volatile u8_t uip_flags; ++ ++/* The following flags may be set in the global variable uip_flags ++ before calling the application callback. The UIP_ACKDATA and ++ UIP_NEWDATA flags may both be set at the same time, whereas the ++ others are mutualy exclusive. Note that these flags should *NOT* be ++ accessed directly, but through the uIP functions/macros. */ ++ ++#define UIP_ACKDATA 1 /* Signifies that the outstanding data was ++ acked and the application should send ++ out new data instead of retransmitting ++ the last data. */ ++#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent ++ us new data. */ ++#define UIP_REXMIT 4 /* Tells the application to retransmit the ++ data that was last sent. */ ++#define UIP_POLL 8 /* Used for polling the application, to ++ check if the application has data that ++ it wants to send. */ ++#define UIP_CLOSE 16 /* The remote host has closed the ++ connection, thus the connection has ++ gone away. Or the application signals ++ that it wants to close the ++ connection. */ ++#define UIP_ABORT 32 /* The remote host has aborted the ++ connection, thus the connection has ++ gone away. Or the application signals ++ that it wants to abort the ++ connection. */ ++#define UIP_CONNECTED 64 /* We have got a connection from a remote ++ host and have set up a new connection ++ for it, or an active connection has ++ been successfully established. */ ++ ++#define UIP_TIMEDOUT 128 /* The connection has been aborted due to ++ too many retransmissions. */ ++ ++ ++/* uip_process(flag): ++ * ++ * The actual uIP function which does all the work. ++ */ ++void uip_process(u8_t flag); ++ ++/* The following flags are passed as an argument to the uip_process() ++ function. They are used to distinguish between the two cases where ++ uip_process() is called. It can be called either because we have ++ incoming data that should be processed, or because the periodic ++ timer has fired. */ ++ ++#define UIP_DATA 1 /* Tells uIP that there is incoming data in ++ the uip_buf buffer. The length of the ++ data is stored in the global variable ++ uip_len. */ ++#define UIP_TIMER 2 /* Tells uIP that the periodic timer has ++ fired. */ ++#if UIP_UDP ++#define UIP_UDP_TIMER 3 ++#endif /* UIP_UDP */ ++ ++/* The TCP states used in the uip_conn->tcpstateflags. */ ++#define CLOSED 0 ++#define SYN_RCVD 1 ++#define SYN_SENT 2 ++#define ESTABLISHED 3 ++#define FIN_WAIT_1 4 ++#define FIN_WAIT_2 5 ++#define CLOSING 6 ++#define TIME_WAIT 7 ++#define LAST_ACK 8 ++#define TS_MASK 15 ++ ++#define UIP_STOPPED 16 ++ ++#define UIP_TCPIP_HLEN 40 ++ ++/* The TCP and IP headers. */ ++typedef struct { ++ /* IP header. */ ++ u8_t vhl, ++ tos, ++ len[2], ++ ipid[2], ++ ipoffset[2], ++ ttl, ++ proto; ++ u16_t ipchksum; ++ u16_t srcipaddr[2], ++ destipaddr[2]; ++ ++ /* TCP header. */ ++ u16_t srcport, ++ destport; ++ u8_t seqno[4], ++ ackno[4], ++ tcpoffset, ++ flags, ++ wnd[2]; ++ u16_t tcpchksum; ++ u8_t urgp[2]; ++ u8_t optdata[4]; ++} uip_tcpip_hdr; ++ ++/* The ICMP and IP headers. */ ++typedef struct { ++ /* IP header. */ ++ u8_t vhl, ++ tos, ++ len[2], ++ ipid[2], ++ ipoffset[2], ++ ttl, ++ proto; ++ u16_t ipchksum; ++ u16_t srcipaddr[2], ++ destipaddr[2]; ++ /* ICMP (echo) header. */ ++ u8_t type, icode; ++ u16_t icmpchksum; ++ u16_t id, seqno; ++} uip_icmpip_hdr; ++ ++ ++/* The UDP and IP headers. */ ++typedef struct { ++ /* IP header. */ ++ u8_t vhl, ++ tos, ++ len[2], ++ ipid[2], ++ ipoffset[2], ++ ttl, ++ proto; ++ u16_t ipchksum; ++ u16_t srcipaddr[2], ++ destipaddr[2]; ++ ++ /* UDP header. */ ++ u16_t srcport, ++ destport; ++ u16_t udplen; ++ u16_t udpchksum; ++} uip_udpip_hdr; ++ ++#define UIP_PROTO_ICMP 1 ++#define UIP_PROTO_TCP 6 ++#define UIP_PROTO_UDP 17 ++ ++#if UIP_FIXEDADDR ++extern const u16_t uip_hostaddr[2]; ++#else /* UIP_FIXEDADDR */ ++extern u16_t uip_hostaddr[2]; ++#endif /* UIP_FIXEDADDR */ ++ ++#endif /* __UIP_H__ */ ++ ++ ++/** @} */ ++ +--- /dev/null ++++ b/net/uip-0.9/uip_arch.c +@@ -0,0 +1,145 @@ ++/* ++ * Copyright (c) 2001, 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. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip_arch.c,v 1.2.2.1 2003/10/04 22:54:17 adam Exp $ ++ * ++ */ ++ ++ ++#include "uip.h" ++#include "uip_arch.h" ++ ++#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) ++#define IP_PROTO_TCP 6 ++ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_add32(u8_t *op32, u16_t op16) ++{ ++ ++ uip_acc32[3] = op32[3] + (op16 & 0xff); ++ uip_acc32[2] = op32[2] + (op16 >> 8); ++ uip_acc32[1] = op32[1]; ++ uip_acc32[0] = op32[0]; ++ ++ if(uip_acc32[2] < (op16 >> 8)) { ++ ++uip_acc32[1]; ++ if(uip_acc32[1] == 0) { ++ ++uip_acc32[0]; ++ } ++ } ++ ++ ++ if(uip_acc32[3] < (op16 & 0xff)) { ++ ++uip_acc32[2]; ++ if(uip_acc32[2] == 0) { ++ ++uip_acc32[1]; ++ if(uip_acc32[1] == 0) { ++ ++uip_acc32[0]; ++ } ++ } ++ } ++} ++/*-----------------------------------------------------------------------------------*/ ++u16_t ++uip_chksum(u16_t *sdata, u16_t len) ++{ ++ u16_t acc; ++ ++ for(acc = 0; len > 1; len -= 2) { ++ acc += *sdata; ++ if(acc < *sdata) { ++ /* Overflow, so we add the carry to acc (i.e., increase by ++ one). */ ++ ++acc; ++ } ++ ++sdata; ++ } ++ ++ /* add up any odd byte */ ++ if(len == 1) { ++ acc += htons(((u16_t)(*(u8_t *)sdata)) << 8); ++ if(acc < htons(((u16_t)(*(u8_t *)sdata)) << 8)) { ++ ++acc; ++ } ++ } ++ ++ return acc; ++} ++/*-----------------------------------------------------------------------------------*/ ++u16_t ++uip_ipchksum(void) ++{ ++ return uip_chksum((u16_t *)&uip_buf[UIP_LLH_LEN], 20); ++} ++/*-----------------------------------------------------------------------------------*/ ++u16_t ++uip_tcpchksum(void) ++{ ++ u16_t hsum, sum; ++ ++ ++ /* Compute the checksum of the TCP header. */ ++ hsum = uip_chksum((u16_t *)&uip_buf[20 + UIP_LLH_LEN], 20); ++ ++ /* Compute the checksum of the data in the TCP packet and add it to ++ the TCP header checksum. */ ++ sum = uip_chksum((u16_t *)uip_appdata, ++ (u16_t)(((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 40))); ++ ++ if((sum += hsum) < hsum) { ++ ++sum; ++ } ++ ++ if((sum += BUF->srcipaddr[0]) < BUF->srcipaddr[0]) { ++ ++sum; ++ } ++ if((sum += BUF->srcipaddr[1]) < BUF->srcipaddr[1]) { ++ ++sum; ++ } ++ if((sum += BUF->destipaddr[0]) < BUF->destipaddr[0]) { ++ ++sum; ++ } ++ if((sum += BUF->destipaddr[1]) < BUF->destipaddr[1]) { ++ ++sum; ++ } ++ if((sum += (u16_t)htons((u16_t)IP_PROTO_TCP)) < (u16_t)htons((u16_t)IP_PROTO_TCP)) { ++ ++sum; ++ } ++ ++ hsum = (u16_t)htons((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 20); ++ ++ if((sum += hsum) < hsum) { ++ ++sum; ++ } ++ ++ return sum; ++} ++/*-----------------------------------------------------------------------------------*/ +--- /dev/null ++++ b/net/uip-0.9/uip_arch.h +@@ -0,0 +1,130 @@ ++/** ++ * \defgroup uiparch Architecture specific uIP functions ++ * @{ ++ * ++ * The functions in the architecture specific module implement the IP ++ * check sum and 32-bit additions. ++ * ++ * The IP checksum calculation is the most computationally expensive ++ * operation in the TCP/IP stack and it therefore pays off to ++ * implement this in efficient assembler. The purpose of the uip-arch ++ * module is to let the checksum functions to be implemented in ++ * architecture specific assembler. ++ * ++ */ ++ ++/** ++ * \file ++ * Declarations of architecture specific functions. ++ * \author Adam Dunkels ++ */ ++ ++/* ++ * Copyright (c) 2001, 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. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip_arch.h,v 1.1.2.2 2003/10/06 15:10:22 adam Exp $ ++ * ++ */ ++ ++#ifndef __UIP_ARCH_H__ ++#define __UIP_ARCH_H__ ++ ++#include "uip.h" ++ ++/** ++ * Carry out a 32-bit addition. ++ * ++ * Because not all architectures for which uIP is intended has native ++ * 32-bit arithmetic, uIP uses an external C function for doing the ++ * required 32-bit additions in the TCP protocol processing. This ++ * function should add the two arguments and place the result in the ++ * global variable uip_acc32. ++ * ++ * \note The 32-bit integer pointed to by the op32 parameter and the ++ * result in the uip_acc32 variable are in network byte order (big ++ * endian). ++ * ++ * \param op32 A pointer to a 4-byte array representing a 32-bit ++ * integer in network byte order (big endian). ++ * ++ * \param op16 A 16-bit integer in host byte order. ++ */ ++void uip_add32(u8_t *op32, u16_t op16); ++ ++/** ++ * Calculate the Internet checksum over a buffer. ++ * ++ * The Internet checksum is the one's complement of the one's ++ * complement sum of all 16-bit words in the buffer. ++ * ++ * See RFC1071. ++ * ++ * \note This function is not called in the current version of uIP, ++ * but future versions might make use of it. ++ * ++ * \param buf A pointer to the buffer over which the checksum is to be ++ * computed. ++ * ++ * \param len The length of the buffer over which the checksum is to ++ * be computed. ++ * ++ * \return The Internet checksum of the buffer. ++ */ ++u16_t uip_chksum(u16_t *buf, u16_t len); ++ ++/** ++ * Calculate the IP header checksum of the packet header in uip_buf. ++ * ++ * The IP header checksum is the Internet checksum of the 20 bytes of ++ * the IP header. ++ * ++ * \return The IP header checksum of the IP header in the uip_buf ++ * buffer. ++ */ ++u16_t uip_ipchksum(void); ++ ++/** ++ * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. ++ * ++ * The TCP checksum is the Internet checksum of data contents of the ++ * TCP segment, and a pseudo-header as defined in RFC793. ++ * ++ * \note The uip_appdata pointer that points to the packet data may ++ * point anywhere in memory, so it is not possible to simply calculate ++ * the Internet checksum of the contents of the uip_buf buffer. ++ * ++ * \return The TCP checksum of the TCP segment in uip_buf and pointed ++ * to by uip_appdata. ++ */ ++u16_t uip_tcpchksum(void); ++ ++/** @} */ ++ ++#endif /* __UIP_ARCH_H__ */ +--- /dev/null ++++ b/net/uip-0.9/uip_arp.c +@@ -0,0 +1,421 @@ ++/** ++ * \addtogroup uip ++ * @{ ++ */ ++ ++/** ++ * \defgroup uiparp uIP Address Resolution Protocol ++ * @{ ++ * ++ * The Address Resolution Protocol ARP is used for mapping between IP ++ * addresses and link level addresses such as the Ethernet MAC ++ * addresses. ARP uses broadcast queries to ask for the link level ++ * address of a known IP address and the host which is configured with ++ * the IP address for which the query was meant, will respond with its ++ * link level address. ++ * ++ * \note This ARP implementation only supports Ethernet. ++ */ ++ ++/** ++ * \file ++ * Implementation of the ARP Address Resolution Protocol. ++ * \author Adam Dunkels ++ * ++ */ ++ ++/* ++ * Copyright (c) 2001-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. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip_arp.c,v 1.7.2.3 2003/10/06 22:42:30 adam Exp $ ++ * ++ */ ++ ++ ++#include "uip_arp.h" ++ ++struct arp_hdr { ++ struct uip_eth_hdr ethhdr; ++ u16_t hwtype; ++ u16_t protocol; ++ u8_t hwlen; ++ u8_t protolen; ++ u16_t opcode; ++ struct uip_eth_addr shwaddr; ++ u16_t sipaddr[2]; ++ struct uip_eth_addr dhwaddr; ++ u16_t dipaddr[2]; ++}; ++ ++struct ethip_hdr { ++ struct uip_eth_hdr ethhdr; ++ /* IP header. */ ++ u8_t vhl, ++ tos, ++ len[2], ++ ipid[2], ++ ipoffset[2], ++ ttl, ++ proto; ++ u16_t ipchksum; ++ u16_t srcipaddr[2], ++ destipaddr[2]; ++}; ++ ++#define ARP_REQUEST 1 ++#define ARP_REPLY 2 ++ ++#define ARP_HWTYPE_ETH 1 ++ ++struct arp_entry { ++ u16_t ipaddr[2]; ++ struct uip_eth_addr ethaddr; ++ u8_t time; ++}; ++ ++struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0, ++ UIP_ETHADDR1, ++ UIP_ETHADDR2, ++ UIP_ETHADDR3, ++ UIP_ETHADDR4, ++ UIP_ETHADDR5}}; ++ ++static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; ++static u16_t ipaddr[2]; ++static u8_t i, c; ++ ++static u8_t arptime; ++static u8_t tmpage; ++ ++#define BUF ((struct arp_hdr *)&uip_buf[0]) ++#define IPBUF ((struct ethip_hdr *)&uip_buf[0]) ++/*-----------------------------------------------------------------------------------*/ ++/** ++ * Initialize the ARP module. ++ * ++ */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_init(void) ++{ ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ memset(arp_table[i].ipaddr, 0, 4); ++ } ++} ++/*-----------------------------------------------------------------------------------*/ ++/** ++ * Periodic ARP processing function. ++ * ++ * This function performs periodic timer processing in the ARP module ++ * and should be called at regular intervals. The recommended interval ++ * is 10 seconds between the calls. ++ * ++ */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_timer(void) ++{ ++ struct arp_entry *tabptr; ++ ++ ++arptime; ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ tabptr = &arp_table[i]; ++ if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 && ++ arptime - tabptr->time >= UIP_ARP_MAXAGE) { ++ memset(tabptr->ipaddr, 0, 4); ++ } ++ } ++ ++} ++/*-----------------------------------------------------------------------------------*/ ++static void ++uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr) ++{ ++ register struct arp_entry *tabptr; ++ /* Walk through the ARP mapping table and try to find an entry to ++ update. If none is found, the IP -> MAC address mapping is ++ inserted in the ARP table. */ ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ ++ tabptr = &arp_table[i]; ++ /* Only check those entries that are actually in use. */ ++ if(tabptr->ipaddr[0] != 0 && ++ tabptr->ipaddr[1] != 0) { ++ ++ /* Check if the source IP address of the incoming packet matches ++ the IP address in this ARP table entry. */ ++ if(ipaddr[0] == tabptr->ipaddr[0] && ++ ipaddr[1] == tabptr->ipaddr[1]) { ++ ++ /* An old entry found, update this and return. */ ++ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); ++ tabptr->time = arptime; ++ ++ return; ++ } ++ } ++ } ++ ++ /* If we get here, no existing ARP table entry was found, so we ++ create one. */ ++ ++ /* First, we try to find an unused entry in the ARP table. */ ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ tabptr = &arp_table[i]; ++ if(tabptr->ipaddr[0] == 0 && ++ tabptr->ipaddr[1] == 0) { ++ break; ++ } ++ } ++ ++ /* If no unused entry is found, we try to find the oldest entry and ++ throw it away. */ ++ if(i == UIP_ARPTAB_SIZE) { ++ tmpage = 0; ++ c = 0; ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ tabptr = &arp_table[i]; ++ if(arptime - tabptr->time > tmpage) { ++ tmpage = arptime - tabptr->time; ++ c = i; ++ } ++ } ++ i = c; ++ } ++ ++ /* Now, i is the ARP table entry which we will fill with the new ++ information. */ ++ memcpy(tabptr->ipaddr, ipaddr, 4); ++ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); ++ tabptr->time = arptime; ++} ++/*-----------------------------------------------------------------------------------*/ ++/** ++ * ARP processing for incoming IP packets ++ * ++ * This function should be called by the device driver when an IP ++ * packet has been received. The function will check if the address is ++ * in the ARP cache, and if so the ARP cache entry will be ++ * refreshed. If no ARP cache entry was found, a new one is created. ++ * ++ * This function expects an IP packet with a prepended Ethernet header ++ * in the uip_buf[] buffer, and the length of the packet in the global ++ * variable uip_len. ++ */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_ipin(void) ++{ ++ uip_len -= sizeof(struct uip_eth_hdr); ++ ++ /* Only insert/update an entry if the source IP address of the ++ incoming IP packet comes from a host on the local network. */ ++ if((IPBUF->srcipaddr[0] & uip_arp_netmask[0]) != ++ (uip_hostaddr[0] & uip_arp_netmask[0])) { ++ return; ++ } ++ if((IPBUF->srcipaddr[1] & uip_arp_netmask[1]) != ++ (uip_hostaddr[1] & uip_arp_netmask[1])) { ++ return; ++ } ++ uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); ++ ++ return; ++} ++/*-----------------------------------------------------------------------------------*/ ++/** ++ * ARP processing for incoming ARP packets. ++ * ++ * This function should be called by the device driver when an ARP ++ * packet has been received. The function will act differently ++ * depending on the ARP packet type: if it is a reply for a request ++ * that we previously sent out, the ARP cache will be filled in with ++ * the values from the ARP reply. If the incoming ARP packet is an ARP ++ * request for our IP address, an ARP reply packet is created and put ++ * into the uip_buf[] buffer. ++ * ++ * When the function returns, the value of the global variable uip_len ++ * indicates whether the device driver should send out a packet or ++ * not. If uip_len is zero, no packet should be sent. If uip_len is ++ * non-zero, it contains the length of the outbound packet that is ++ * present in the uip_buf[] buffer. ++ * ++ * This function expects an ARP packet with a prepended Ethernet ++ * header in the uip_buf[] buffer, and the length of the packet in the ++ * global variable uip_len. ++ */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_arpin(void) ++{ ++ ++ if(uip_len < sizeof(struct arp_hdr)) { ++ uip_len = 0; ++ return; ++ } ++ ++ uip_len = 0; ++ ++ switch(BUF->opcode) { ++ case HTONS(ARP_REQUEST): ++ /* ARP request. If it asked for our address, we send out a ++ reply. */ ++ if(BUF->dipaddr[0] == uip_hostaddr[0] && ++ BUF->dipaddr[1] == uip_hostaddr[1]) { ++ /* The reply opcode is 2. */ ++ BUF->opcode = HTONS(2); ++ ++ memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6); ++ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); ++ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); ++ memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); ++ ++ BUF->dipaddr[0] = BUF->sipaddr[0]; ++ BUF->dipaddr[1] = BUF->sipaddr[1]; ++ BUF->sipaddr[0] = uip_hostaddr[0]; ++ BUF->sipaddr[1] = uip_hostaddr[1]; ++ ++ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); ++ uip_len = sizeof(struct arp_hdr); ++ } ++ break; ++ case HTONS(ARP_REPLY): ++ /* ARP reply. We insert or update the ARP table if it was meant ++ for us. */ ++ if(BUF->dipaddr[0] == uip_hostaddr[0] && ++ BUF->dipaddr[1] == uip_hostaddr[1]) { ++ ++ uip_arp_update(BUF->sipaddr, &BUF->shwaddr); ++ } ++ break; ++ } ++ ++ return; ++} ++/*-----------------------------------------------------------------------------------*/ ++/** ++ * Prepend Ethernet header to an outbound IP packet and see if we need ++ * to send out an ARP request. ++ * ++ * This function should be called before sending out an IP packet. The ++ * function checks the destination IP address of the IP packet to see ++ * what Ethernet MAC address that should be used as a destination MAC ++ * address on the Ethernet. ++ * ++ * If the destination IP address is in the local network (determined ++ * by logical ANDing of netmask and our IP address), the function ++ * checks the ARP cache to see if an entry for the destination IP ++ * address is found. If so, an Ethernet header is prepended and the ++ * function returns. If no ARP cache entry is found for the ++ * destination IP address, the packet in the uip_buf[] is replaced by ++ * an ARP request packet for the IP address. The IP packet is dropped ++ * and it is assumed that they higher level protocols (e.g., TCP) ++ * eventually will retransmit the dropped packet. ++ * ++ * If the destination IP address is not on the local network, the IP ++ * address of the default router is used instead. ++ * ++ * When the function returns, a packet is present in the uip_buf[] ++ * buffer, and the length of the packet is in the global variable ++ * uip_len. ++ */ ++/*-----------------------------------------------------------------------------------*/ ++void ++uip_arp_out(void) ++{ ++ struct arp_entry *tabptr; ++ /* Find the destination IP address in the ARP table and construct ++ the Ethernet header. If the destination IP addres isn't on the ++ local network, we use the default router's IP address instead. ++ ++ If not ARP table entry is found, we overwrite the original IP ++ packet with an ARP request for the IP address. */ ++ ++ /* Check if the destination address is on the local network. */ ++ if((IPBUF->destipaddr[0] & uip_arp_netmask[0]) != ++ (uip_hostaddr[0] & uip_arp_netmask[0]) || ++ (IPBUF->destipaddr[1] & uip_arp_netmask[1]) != ++ (uip_hostaddr[1] & uip_arp_netmask[1])) { ++ /* Destination address was not on the local network, so we need to ++ use the default router's IP address instead of the destination ++ address when determining the MAC address. */ ++ ipaddr[0] = uip_arp_draddr[0]; ++ ipaddr[1] = uip_arp_draddr[1]; ++ } else { ++ /* Else, we use the destination IP address. */ ++ ipaddr[0] = IPBUF->destipaddr[0]; ++ ipaddr[1] = IPBUF->destipaddr[1]; ++ } ++ ++ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { ++ tabptr = &arp_table[i]; ++ if(ipaddr[0] == tabptr->ipaddr[0] && ++ ipaddr[1] == tabptr->ipaddr[1]) ++ break; ++ } ++ ++ if(i == UIP_ARPTAB_SIZE) { ++ /* The destination address was not in our ARP table, so we ++ overwrite the IP packet with an ARP request. */ ++ ++ memset(BUF->ethhdr.dest.addr, 0xff, 6); ++ memset(BUF->dhwaddr.addr, 0x00, 6); ++ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); ++ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); ++ ++ BUF->dipaddr[0] = ipaddr[0]; ++ BUF->dipaddr[1] = ipaddr[1]; ++ BUF->sipaddr[0] = uip_hostaddr[0]; ++ BUF->sipaddr[1] = uip_hostaddr[1]; ++ BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ ++ BUF->hwtype = HTONS(ARP_HWTYPE_ETH); ++ BUF->protocol = HTONS(UIP_ETHTYPE_IP); ++ BUF->hwlen = 6; ++ BUF->protolen = 4; ++ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); ++ ++ uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; ++ ++ uip_len = sizeof(struct arp_hdr); ++ return; ++ } ++ ++ /* Build an ethernet header. */ ++ memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); ++ memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); ++ ++ IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); ++ ++ uip_len += sizeof(struct uip_eth_hdr); ++} ++/*-----------------------------------------------------------------------------------*/ ++ ++/** @} */ ++/** @} */ +--- /dev/null ++++ b/net/uip-0.9/uip_arp.h +@@ -0,0 +1,201 @@ ++/** ++ * \addtogroup uip ++ * @{ ++ */ ++ ++/** ++ * \addtogroup uiparp ++ * @{ ++ */ ++ ++/** ++ * \file ++ * Macros and definitions for the ARP module. ++ * \author Adam Dunkels ++ */ ++ ++ ++/* ++ * Copyright (c) 2001-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. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uip_arp.h,v 1.3.2.2 2003/10/06 15:10:22 adam Exp $ ++ * ++ */ ++ ++#ifndef __UIP_ARP_H__ ++#define __UIP_ARP_H__ ++ ++#include "uip.h" ++ ++ ++/** ++ * Representation of a 48-bit Ethernet address. ++ */ ++struct uip_eth_addr { ++ u8_t addr[6]; ++}; ++ ++extern struct uip_eth_addr uip_ethaddr; ++ ++/** ++ * The Ethernet header. ++ */ ++struct uip_eth_hdr { ++ struct uip_eth_addr dest; ++ struct uip_eth_addr src; ++ u16_t type; ++}; ++ ++#define UIP_ETHTYPE_ARP 0x0806 ++#define UIP_ETHTYPE_IP 0x0800 ++#define UIP_ETHTYPE_IP6 0x86dd ++ ++ ++/* The uip_arp_init() function must be called before any of the other ++ ARP functions. */ ++void uip_arp_init(void); ++ ++/* The uip_arp_ipin() function should be called whenever an IP packet ++ arrives from the Ethernet. This function refreshes the ARP table or ++ inserts a new mapping if none exists. The function assumes that an ++ IP packet with an Ethernet header is present in the uip_buf buffer ++ and that the length of the packet is in the uip_len variable. */ ++void uip_arp_ipin(void); ++ ++/* The uip_arp_arpin() should be called when an ARP packet is received ++ by the Ethernet driver. This function also assumes that the ++ Ethernet frame is present in the uip_buf buffer. When the ++ uip_arp_arpin() function returns, the contents of the uip_buf ++ buffer should be sent out on the Ethernet if the uip_len variable ++ is > 0. */ ++void uip_arp_arpin(void); ++ ++/* The uip_arp_out() function should be called when an IP packet ++ should be sent out on the Ethernet. This function creates an ++ Ethernet header before the IP header in the uip_buf buffer. The ++ Ethernet header will have the correct Ethernet MAC destination ++ address filled in if an ARP table entry for the destination IP ++ address (or the IP address of the default router) is present. If no ++ such table entry is found, the IP packet is overwritten with an ARP ++ request and we rely on TCP to retransmit the packet that was ++ overwritten. In any case, the uip_len variable holds the length of ++ the Ethernet frame that should be transmitted. */ ++void uip_arp_out(void); ++ ++/* The uip_arp_timer() function should be called every ten seconds. It ++ is responsible for flushing old entries in the ARP table. */ ++void uip_arp_timer(void); ++ ++/** @} */ ++ ++/** ++ * \addtogroup uipconffunc ++ * @{ ++ */ ++ ++/** ++ * Set the default router's IP address. ++ * ++ * \param addr A pointer to a 4-byte array containing the IP address ++ * of the default router. ++ * ++ * \hideinitializer ++ */ ++#define uip_setdraddr(addr) do { uip_arp_draddr[0] = addr[0]; \ ++ uip_arp_draddr[1] = addr[1]; } while(0) ++ ++/** ++ * Set the netmask. ++ * ++ * \param addr A pointer to a 4-byte array containing the IP address ++ * of the netmask. ++ * ++ * \hideinitializer ++ */ ++#define uip_setnetmask(addr) do { uip_arp_netmask[0] = addr[0]; \ ++ uip_arp_netmask[1] = addr[1]; } while(0) ++ ++ ++/** ++ * Get the default router's IP address. ++ * ++ * \param addr A pointer to a 4-byte array that will be filled in with ++ * the IP address of the default router. ++ * ++ * \hideinitializer ++ */ ++#define uip_getdraddr(addr) do { addr[0] = uip_arp_draddr[0]; \ ++ addr[1] = uip_arp_draddr[1]; } while(0) ++ ++/** ++ * Get the netmask. ++ * ++ * \param addr A pointer to a 4-byte array that will be filled in with ++ * the value of the netmask. ++ * ++ * \hideinitializer ++ */ ++#define uip_getnetmask(addr) do { addr[0] = uip_arp_netmask[0]; \ ++ addr[1] = uip_arp_netmask[1]; } while(0) ++ ++ ++/** ++ * Specifiy the Ethernet MAC address. ++ * ++ * The ARP code needs to know the MAC address of the Ethernet card in ++ * order to be able to respond to ARP queries and to generate working ++ * Ethernet headers. ++ * ++ * \note This macro only specifies the Ethernet MAC address to the ARP ++ * code. It cannot be used to change the MAC address of the Ethernet ++ * card. ++ * ++ * \param eaddr A pointer to a struct uip_eth_addr containing the ++ * Ethernet MAC address of the Ethernet card. ++ * ++ * \hideinitializer ++ */ ++#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \ ++ uip_ethaddr.addr[1] = eaddr.addr[1];\ ++ uip_ethaddr.addr[2] = eaddr.addr[2];\ ++ uip_ethaddr.addr[3] = eaddr.addr[3];\ ++ uip_ethaddr.addr[4] = eaddr.addr[4];\ ++ uip_ethaddr.addr[5] = eaddr.addr[5];} while(0) ++ ++/** @} */ ++ ++/** ++ * \internal Internal variables that are set using the macros ++ * uip_setdraddr and uip_setnetmask. ++ */ ++extern u16_t uip_arp_draddr[2], uip_arp_netmask[2]; ++#endif /* __UIP_ARP_H__ */ ++ ++ +--- /dev/null ++++ b/net/uip-0.9/uipopt.h +@@ -0,0 +1,557 @@ ++/** ++ * \defgroup uipopt Configuration options for uIP ++ * @{ ++ * ++ * uIP is configured using the per-project configuration file ++ * "uipopt.h". This file contains all compile-time options for uIP and ++ * should be tweaked to match each specific project. The uIP ++ * distribution contains a documented example "uipopt.h" that can be ++ * copied and modified for each project. ++ */ ++ ++/** ++ * \file ++ * Configuration options for uIP. ++ * \author Adam Dunkels ++ * ++ * This file is used for tweaking various configuration options for ++ * uIP. You should make a copy of this file into one of your project's ++ * directories instead of editing this example "uipopt.h" file that ++ * comes with the uIP distribution. ++ */ ++ ++/* ++ * Copyright (c) 2001-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. ++ * ++ * This file is part of the uIP TCP/IP stack. ++ * ++ * $Id: uipopt.h,v 1.16.2.5 2003/10/07 13:22:51 adam Exp $ ++ * ++ */ ++ ++#ifndef __UIPOPT_H__ ++#define __UIPOPT_H__ ++ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipopttypedef uIP type definitions ++ * @{ ++ */ ++ ++/** ++ * The 8-bit unsigned data type. ++ * ++ * This may have to be tweaked for your particular compiler. "unsigned ++ * char" works for most compilers. ++ */ ++typedef unsigned char u8_t; ++ ++/** ++ * The 16-bit unsigned data type. ++ * ++ * This may have to be tweaked for your particular compiler. "unsigned ++ * short" works for most compilers. ++ */ ++typedef unsigned short u16_t; ++ ++/** ++ * The statistics data type. ++ * ++ * This datatype determines how high the statistics counters are able ++ * to count. ++ */ ++typedef unsigned short uip_stats_t; ++ ++/** @} */ ++ ++/*------------------------------------------------------------------------------*/ ++ ++/** ++ * \defgroup uipoptstaticconf Static configuration options ++ * @{ ++ * ++ * These configuration options can be used for setting the IP address ++ * settings statically, but only if UIP_FIXEDADDR is set to 1. The ++ * configuration options for a specific node includes IP address, ++ * netmask and default router as well as the Ethernet address. The ++ * netmask, default router and Ethernet address are appliciable only ++ * if uIP should be run over Ethernet. ++ * ++ * All of these should be changed to suit your project. ++*/ ++ ++/** ++ * Determines if uIP should use a fixed IP address or not. ++ * ++ * If uIP should use a fixed IP address, the settings are set in the ++ * uipopt.h file. If not, the macros uip_sethostaddr(), ++ * uip_setdraddr() and uip_setnetmask() should be used instead. ++ * ++ * \hideinitializer ++ */ ++#define UIP_FIXEDADDR 0 ++ ++/** ++ * Ping IP address asignment. ++ * ++ * uIP uses a "ping" packets for setting its own IP address if this ++ * option is set. If so, uIP will start with an empty IP address and ++ * the destination IP address of the first incoming "ping" (ICMP echo) ++ * packet will be used for setting the hosts IP address. ++ * ++ * \note This works only if UIP_FIXEDADDR is 0. ++ * ++ * \hideinitializer ++ */ ++#define UIP_PINGADDRCONF 0 ++ ++#define UIP_IPADDR0 192 /**< The first octet of the IP address of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_IPADDR1 168 /**< The second octet of the IP address of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_IPADDR2 0 /**< The third octet of the IP address of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_IPADDR3 250 /**< The fourth octet of the IP address of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++ ++#define UIP_NETMASK0 255 /**< The first octet of the netmask of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_NETMASK1 255 /**< The second octet of the netmask of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_NETMASK2 255 /**< The third octet of the netmask of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_NETMASK3 0 /**< The fourth octet of the netmask of ++ this uIP node, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++ ++#define UIP_DRIPADDR0 192 /**< The first octet of the IP address of ++ the default router, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_DRIPADDR1 168 /**< The second octet of the IP address of ++ the default router, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_DRIPADDR2 0 /**< The third octet of the IP address of ++ the default router, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++#define UIP_DRIPADDR3 1 /**< The fourth octet of the IP address of ++ the default router, if UIP_FIXEDADDR is ++ 1. \hideinitializer */ ++ ++/** ++ * Specifies if the uIP ARP module should be compiled with a fixed ++ * Ethernet MAC address or not. ++ * ++ * If this configuration option is 0, the macro uip_setethaddr() can ++ * be used to specify the Ethernet address at run-time. ++ * ++ * \hideinitializer ++ */ ++#define UIP_FIXEDETHADDR 0 ++ ++#define UIP_ETHADDR0 0x00 /**< The first octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++#define UIP_ETHADDR1 0xbd /**< The second octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++#define UIP_ETHADDR2 0x3b /**< The third octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++#define UIP_ETHADDR3 0x33 /**< The fourth octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++#define UIP_ETHADDR4 0x05 /**< The fifth octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++#define UIP_ETHADDR5 0x71 /**< The sixth octet of the Ethernet ++ address if UIP_FIXEDETHADDR is ++ 1. \hideinitializer */ ++ ++/** @} */ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipoptip IP configuration options ++ * @{ ++ * ++ */ ++/** ++ * The IP TTL (time to live) of IP packets sent by uIP. ++ * ++ * This should normally not be changed. ++ */ ++#define UIP_TTL 255 ++ ++/** ++ * Turn on support for IP packet reassembly. ++ * ++ * uIP supports reassembly of fragmented IP packets. This features ++ * requires an additonal amount of RAM to hold the reassembly buffer ++ * and the reassembly code size is approximately 700 bytes. The ++ * reassembly buffer is of the same size as the uip_buf buffer ++ * (configured by UIP_BUFSIZE). ++ * ++ * \note IP packet reassembly is not heavily tested. ++ * ++ * \hideinitializer ++ */ ++#define UIP_REASSEMBLY 0 ++ ++/** ++ * The maximum time an IP fragment should wait in the reassembly ++ * buffer before it is dropped. ++ * ++ */ ++#define UIP_REASS_MAXAGE 40 ++ ++/** @} */ ++ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipoptudp UDP configuration options ++ * @{ ++ * ++ * \note The UDP support in uIP is still not entirely complete; there ++ * is no support for sending or receiving broadcast or multicast ++ * packets, but it works well enough to support a number of vital ++ * applications such as DNS queries, though ++ */ ++ ++/** ++ * Toggles wether UDP support should be compiled in or not. ++ * ++ * \hideinitializer ++ */ ++#define UIP_UDP 0 ++ ++/** ++ * Toggles if UDP checksums should be used or not. ++ * ++ * \note Support for UDP checksums is currently not included in uIP, ++ * so this option has no function. ++ * ++ * \hideinitializer ++ */ ++#define UIP_UDP_CHECKSUMS 0 ++ ++/** ++ * The maximum amount of concurrent UDP connections. ++ * ++ * \hideinitializer ++ */ ++#define UIP_UDP_CONNS 10 ++ ++/** ++ * The name of the function that should be called when UDP datagrams arrive. ++ * ++ * \hideinitializer ++ */ ++#define UIP_UDP_APPCALL udp_appcall ++ ++/** @} */ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipopttcp TCP configuration options ++ * @{ ++ */ ++ ++/** ++ * Determines if support for opening connections from uIP should be ++ * compiled in. ++ * ++ * If the applications that are running on top of uIP for this project ++ * do not need to open outgoing TCP connections, this configration ++ * option can be turned off to reduce the code size of uIP. ++ * ++ * \hideinitializer ++ */ ++#define UIP_ACTIVE_OPEN 1 ++ ++/** ++ * The maximum number of simultaneously open TCP connections. ++ * ++ * Since the TCP connections are statically allocated, turning this ++ * configuration knob down results in less RAM used. Each TCP ++ * connection requires approximatly 30 bytes of memory. ++ * ++ * \hideinitializer ++ */ ++#define UIP_CONNS 10 ++ ++/** ++ * The maximum number of simultaneously listening TCP ports. ++ * ++ * Each listening TCP port requires 2 bytes of memory. ++ * ++ * \hideinitializer ++ */ ++#define UIP_LISTENPORTS 10 ++ ++/** ++ * The size of the advertised receiver's window. ++ * ++ * Should be set low (i.e., to the size of the uip_buf buffer) is the ++ * application is slow to process incoming data, or high (32768 bytes) ++ * if the application processes data quickly. ++ * ++ * \hideinitializer ++ */ ++#define UIP_RECEIVE_WINDOW 32768 ++ ++/** ++ * Determines if support for TCP urgent data notification should be ++ * compiled in. ++ * ++ * Urgent data (out-of-band data) is a rarely used TCP feature that ++ * very seldom would be required. ++ * ++ * \hideinitializer ++ */ ++#define UIP_URGDATA 1 ++ ++/** ++ * The initial retransmission timeout counted in timer pulses. ++ * ++ * This should not be changed. ++ */ ++#define UIP_RTO 3 ++ ++/** ++ * The maximum number of times a segment should be retransmitted ++ * before the connection should be aborted. ++ * ++ * This should not be changed. ++ */ ++#define UIP_MAXRTX 8 ++ ++/** ++ * The maximum number of times a SYN segment should be retransmitted ++ * before a connection request should be deemed to have been ++ * unsuccessful. ++ * ++ * This should not need to be changed. ++ */ ++#define UIP_MAXSYNRTX 3 ++ ++/** ++ * The TCP maximum segment size. ++ * ++ * This is should not be to set to more than UIP_BUFSIZE - UIP_LLH_LEN - 40. ++ */ ++#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - 40) ++ ++/** ++ * How long a connection should stay in the TIME_WAIT state. ++ * ++ * This configiration option has no real implication, and it should be ++ * left untouched. ++ */ ++#define UIP_TIME_WAIT_TIMEOUT 120 ++ ++ ++/** @} */ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipoptarp ARP configuration options ++ * @{ ++ */ ++ ++/** ++ * The size of the ARP table. ++ * ++ * This option should be set to a larger value if this uIP node will ++ * have many connections from the local network. ++ * ++ * \hideinitializer ++ */ ++#define UIP_ARPTAB_SIZE 8 ++ ++/** ++ * The maxium age of ARP table entries measured in 10ths of seconds. ++ * ++ * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD ++ * default). ++ */ ++#define UIP_ARP_MAXAGE 120 ++ ++/** @} */ ++ ++/*------------------------------------------------------------------------------*/ ++ ++/** ++ * \defgroup uipoptgeneral General configuration options ++ * @{ ++ */ ++ ++/** ++ * The size of the uIP packet buffer. ++ * ++ * The uIP packet buffer should not be smaller than 60 bytes, and does ++ * not need to be larger than 1500 bytes. Lower size results in lower ++ * TCP throughput, larger size results in higher TCP throughput. ++ * ++ * \hideinitializer ++ */ ++#define UIP_BUFSIZE 1500 ++ ++ ++/** ++ * Determines if statistics support should be compiled in. ++ * ++ * The statistics is useful for debugging and to show the user. ++ * ++ * \hideinitializer ++ */ ++#define UIP_STATISTICS 1 ++ ++/** ++ * Determines if logging of certain events should be compiled in. ++ * ++ * This is useful mostly for debugging. The function uip_log() ++ * must be implemented to suit the architecture of the project, if ++ * logging is turned on. ++ * ++ * \hideinitializer ++ */ ++#define UIP_LOGGING 0 ++ ++/** ++ * Print out a uIP log message. ++ * ++ * This function must be implemented by the module that uses uIP, and ++ * is called by uIP whenever a log message is generated. ++ */ ++void uip_log(char *msg); ++ ++/** ++ * The link level header length. ++ * ++ * This is the offset into the uip_buf where the IP header can be ++ * found. For Ethernet, this should be set to 14. For SLIP, this ++ * should be set to 0. ++ * ++ * \hideinitializer ++ */ ++#define UIP_LLH_LEN 14 ++ ++ ++/** @} */ ++/*------------------------------------------------------------------------------*/ ++/** ++ * \defgroup uipoptcpu CPU architecture configuration ++ * @{ ++ * ++ * The CPU architecture configuration is where the endianess of the ++ * CPU on which uIP is to be run is specified. Most CPUs today are ++ * little endian, and the most notable exception are the Motorolas ++ * which are big endian. The BYTE_ORDER macro should be changed to ++ * reflect the CPU architecture on which uIP is to be run. ++ */ ++#ifndef LITTLE_ENDIAN ++#define LITTLE_ENDIAN 3412 ++#endif /* LITTLE_ENDIAN */ ++#ifndef BIG_ENDIAN ++#define BIG_ENDIAN 1234 ++#endif /* BIGE_ENDIAN */ ++ ++/** ++ * The byte order of the CPU architecture on which uIP is to be run. ++ * ++ * This option can be either BIG_ENDIAN (Motorola byte order) or ++ * LITTLE_ENDIAN (Intel byte order). ++ * ++ * \hideinitializer ++ */ ++/*#ifndef BYTE_ORDER*/ ++#define BYTE_ORDER BIG_ENDIAN ++/*#endif*/ /* BYTE_ORDER */ ++ ++/** @} */ ++/*------------------------------------------------------------------------------*/ ++ ++/** ++ * \defgroup uipoptapp Appication specific configurations ++ * @{ ++ * ++ * An uIP application is implemented using a single application ++ * function that is called by uIP whenever a TCP/IP event occurs. The ++ * name of this function must be registered with uIP at compile time ++ * using the UIP_APPCALL definition. ++ * ++ * uIP applications can store the application state within the ++ * uip_conn structure by specifying the size of the application ++ * structure with the UIP_APPSTATE_SIZE macro. ++ * ++ * The file containing the definitions must be included in the ++ * uipopt.h file. ++ * ++ * The following example illustrates how this can look. ++ \code ++ ++void httpd_appcall(void); ++#define UIP_APPCALL httpd_appcall ++ ++struct httpd_state { ++ u8_t state; ++ u16_t count; ++ char *dataptr; ++ char *script; ++}; ++#define UIP_APPSTATE_SIZE (sizeof(struct httpd_state)) ++ \endcode ++ */ ++ ++/** ++ * \var #define UIP_APPCALL ++ * ++ * The name of the application function that uIP should call in ++ * response to TCP/IP events. ++ * ++ */ ++ ++/** ++ * \var #define UIP_APPSTATE_SIZE ++ * ++ * The size of the application state that is to be stored in the ++ * uip_conn structure. ++ */ ++/** @} */ ++ ++/* Include the header file for the application program that should be ++ used. If you don't use the example web server, you should change ++ this. */ ++#include "httpd.h" ++ ++ ++#endif /* __UIPOPT_H__ */ +--- a/board/infineon/easy50712/danube.c ++++ b/board/infineon/easy50712/danube.c +@@ -354,7 +354,7 @@ int do_http_upgrade(const unsigned char + } + /* write the image to the flash */ + puts("http ugrade ...\n"); +- sprintf(buf, "era ${kernel_addr} +0x%x; cp.b ${ram_addr} ${kernel_addr} 0x%x", size, size); ++ sprintf(buf, "era ${kernel_addr} +0x%lx; cp.b ${ram_addr} ${kernel_addr} 0x%lx", size, size); + return run_command(buf, 0); + } + +--- a/common/main.c ++++ b/common/main.c +@@ -273,6 +273,10 @@ static __inline__ int abortboot(int boot + + void main_loop (void) + { ++#ifdef CONFIG_CMD_HTTPD ++ int ret; ++#endif ++ + #ifndef CONFIG_SYS_HUSH_PARSER + static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, }; + int len; +@@ -403,12 +407,22 @@ void main_loop (void) + # endif + + # ifndef CONFIG_SYS_HUSH_PARSER +- run_command (s, 0); ++ ret = run_command (s, 0); + # else +- parse_string_outer(s, FLAG_PARSE_SEMICOLON | ++ ret = parse_string_outer(s, FLAG_PARSE_SEMICOLON | + FLAG_EXIT_FROM_LOOP); + # endif + ++# ifdef CONFIG_CMD_HTTPD ++ if (ret != 0) { ++ printf("Failed to execute bootcmd " ++ "(maybe invalid u-boot environment?), " ++ "starting httpd to update firmware...\n"); ++ NetLoopHttpd(); ++ } ++# endif ++ ++ + # ifdef CONFIG_AUTOBOOT_KEYED + disable_ctrlc(prev); /* restore Control C checking */ + # endif +--- a/include/configs/easy50712.h ++++ b/include/configs/easy50712.h +@@ -114,4 +114,7 @@ + + #define CONFIG_CMD_HTTPD /* enable upgrade via HTTPD */ + ++#define CONFIG_IPADDR 192.168.0.119 ++#define CONFIG_ETHADDR 00:01:02:03:04:05 ++ + #endif /* __CONFIG_H */ +--- a/lib_mips/time.c ++++ b/lib_mips/time.c +@@ -29,6 +29,8 @@ static unsigned long timestamp; + /* how many counter cycles in a jiffy */ + #define CYCLES_PER_JIFFY (CONFIG_SYS_MIPS_TIMER_FREQ + CONFIG_SYS_HZ / 2) / CONFIG_SYS_HZ + ++unsigned long ifx_get_cpuclk(void); ++ + /* + * timer without interrupts + */ +--- a/net/httpd.c ++++ b/net/httpd.c +@@ -35,12 +35,14 @@ HttpdHandler (void) + } + } + ++#if 0 + static void + HttpdTimeout (void) + { + puts ("T "); + NetSetTimeout (TIMEOUT * 1000, HttpdTimeout); + } ++#endif + + void + HttpdStart (void) +--- a/net/net.c ++++ b/net/net.c +@@ -1966,7 +1966,7 @@ NetSendHttpd(void) + void + NetReceiveHttpd(volatile uchar * inpkt, int len) + { +- memcpy(uip_buf, inpkt, len); ++ memcpy(uip_buf, (const void *)inpkt, len); + uip_len = len; + if(BUF->type == htons(UIP_ETHTYPE_IP)) { + uip_arp_ipin(); +@@ -1989,6 +1989,7 @@ NetLoopHttpd(void) + unsigned long long tout = 0; + bd_t *bd = gd->bd; + unsigned short int ip[2]; ++ struct uip_eth_addr eaddr; + + #ifdef CONFIG_NET_MULTI + NetRestarted = 0; +@@ -2039,6 +2040,15 @@ restart: + eth_getenv_enetaddr("ethaddr", NetOurEther); + #endif + ++ eaddr.addr[0] = NetOurEther[0]; ++ eaddr.addr[1] = NetOurEther[1]; ++ eaddr.addr[2] = NetOurEther[2]; ++ eaddr.addr[3] = NetOurEther[3]; ++ eaddr.addr[4] = NetOurEther[4]; ++ eaddr.addr[5] = NetOurEther[5]; ++ ++ uip_setethaddr(eaddr); ++ + NetCopyIP(&NetOurIP, &bd->bi_ip_addr); + NetOurGatewayIP = getenv_IPaddr ("gatewayip"); + NetOurSubnetMask= getenv_IPaddr ("netmask"); +@@ -2072,6 +2082,14 @@ restart: + tout = t1; + } + } ++ ++ if (ctrlc()) { ++ eth_halt(); ++ puts ("\nAbort\n"); ++ return (-1); ++ } ++ ++ + if(!httpd_upload_complete) + continue; + printf("Bytes transferred = %ld (%lx hex)\n", +--- a/net/uip-0.9/fsdata.c ++++ b/net/uip-0.9/fsdata.c +@@ -1,199 +1,108 @@ +-static const char data_flashing_html[] = { +- /* /flashing.html */ +- 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, +- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, +- 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, +- 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, +- 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, +- 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, +- 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, +- 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, +- 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, +- 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, +- 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c, 0x62, +- 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3d, +- 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, +- 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x20, 0x68, +- 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x31, 0x30, 0x30, 0x25, +- 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, +- 0x66, 0x66, 0x66, 0x3b, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, +- 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, +- 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, 0x62, 0x30, 0x33, 0x34, +- 0x3b, 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, +- 0x3e, 0x3c, 0x68, 0x31, 0x3e, 0x55, 0x70, 0x67, 0x72, 0x61, +- 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, +- 0x6d, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f, 0x68, 0x31, +- 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, +- 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, +- 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; +- +-static const char data_fail_html[] = { +- /* /fail.html */ +- 0x2f, 0x66, 0x61, 0x69, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, +- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, +- 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, +- 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, +- 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, +- 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, +- 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, +- 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, +- 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, +- 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, +- 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, +- 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, +- 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, +- 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, +- 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, +- 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, +- 0x3e, 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, +- 0x9, 0x9, 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73, +- 0x68, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, +- 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9, 0x45, +- 0x52, 0x52, 0x4f, 0x52, 0x20, 0x2d, 0x20, 0x74, 0x68, 0x65, +- 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x79, 0x6f, 0x75, +- 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x20, +- 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, +- 0x70, 0x61, 0x73, 0x73, 0x20, 0x76, 0x65, 0x72, 0x69, 0x66, +- 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x50, +- 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x6d, 0x61, 0x6b, 0x65, +- 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x75, +- 0x73, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x66, 0x66, 0x69, +- 0x63, 0x69, 0x61, 0x6c, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, +- 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, +- 0x20, 0x62, 0x79, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, +- 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, +- 0x66, 0x6f, 0x6e, 0x6f, 0x73, 0x66, 0x65, 0x72, 0x61, 0x2e, +- 0x6f, 0x72, 0x67, 0x2f, 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f, +- 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, +- 0x3e, 0xa, }; +- +-static const char data_404_html[] = { +- /* /404.html */ +- 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, +- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x34, +- 0x30, 0x34, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, +- 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0xd, 0xa, 0x53, +- 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, +- 0x2f, 0x30, 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, +- 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, +- 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, +- 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, +- 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, +- 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, +- 0xd, 0xa, 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, +- 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, +- 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, +- 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, +- 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, 0x20, +- 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, +- 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0x3c, +- 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x2f, +- 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d, +- 0x6c, 0x3e, }; +- +-static const char data_index_html[] = { +- /* /index.html */ +- 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, +- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, +- 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, +- 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, +- 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, +- 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, +- 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, +- 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, +- 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, +- 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, +- 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, +- 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, +- 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, +- 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, +- 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, +- 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, +- 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, +- 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, +- 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, +- 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, +- 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, +- 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, +- 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62, +- 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, +- 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, +- 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9, +- 0x3c, 0x68, 0x31, 0x3e, 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, +- 0x72, 0x61, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, +- 0x65, 0x20, 0x55, 0x49, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, +- 0x9, 0x9, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x65, +- 0x74, 0x68, 0x6f, 0x64, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x74, +- 0x22, 0x20, 0x65, 0x6e, 0x63, 0x74, 0x79, 0x70, 0x65, 0x3d, +- 0x22, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, +- 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x64, 0x61, 0x74, 0x61, +- 0x22, 0x3e, 0xa, 0x9, 0x9, 0x9, 0x3c, 0x69, 0x6e, 0x70, +- 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, +- 0x6c, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x66, 0x69, +- 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x3e, 0xa, 0x9, 0x9, +- 0x9, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, +- 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x3e, +- 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e, +- 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, +- 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; +- +-static const char data_flash_html[] = { +- /* /flash.html */ +- 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, +- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, +- 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, +- 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, +- 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, +- 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, +- 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, +- 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, +- 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, +- 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, +- 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, +- 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, +- 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, +- 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, +- 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, +- 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, +- 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, +- 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, +- 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, +- 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, +- 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, +- 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, +- 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62, +- 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, +- 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, +- 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9, +- 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x69, +- 0x6e, 0x67, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9, +- 0x54, 0x68, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, +- 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x72, +- 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x6c, +- 0x61, 0x73, 0x68, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, +- 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x70, +- 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x2c, 0x20, 0x74, 0x68, +- 0x65, 0x20, 0x6c, 0x65, 0x64, 0x73, 0x20, 0x77, 0x69, 0x6c, +- 0x6c, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x6f, +- 0x20, 0x62, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0xa, 0xa, 0x9, +- 0x9, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, 0x61, 0x20, 0x73, +- 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x6c, +- 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, +- 0x65, 0x20, 0x62, 0x6f, 0x78, 0x20, 0x77, 0x69, 0x6c, 0x6c, +- 0x20, 0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0xa, 0x9, 0x3c, +- 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, +- 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; +- +-const struct fsdata_file file_flashing_html[] = {{NULL, data_flashing_html, data_flashing_html + 15, sizeof(data_flashing_html) - 15}}; ++static const char data_flashing_html[] = ++"HTTP/1.0 200 OK\n" ++"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n" ++"Content-type: text/html\n" ++"\n" ++"\n" ++"\t\n" ++"\t\t\n" ++"\t\t\tFailsafe UI\n" ++"\t\t\n" ++"\t\n" ++"\t\n" ++"\t\t

Upgrading system...

\n" ++"\t\n" ++"\n"; ++ ++static const char data_fail_html[] = ++"HTTP/1.0 200 OK\n" ++"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n" ++"Content-type: text/html\n" ++"\n" ++"\n" ++"\t\n" ++"\t\t\n" ++"\t\t\tFailsafe UI\n" ++"\t\t\n" ++"\t\n" ++"\t\n" ++"\t\t

Flashing failed

\n" ++"\t\tERROR - the image you uploaded failed to pass verification.
\n" ++"\t\tPlease make sure to use an official update provided by http://lantiq.com/\n" ++"\t\n" ++"\n"; ++ ++static const char data_404_html[] = ++"HTTP/1.0 404 File not found\n" ++"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n" ++"Content-type: text/html\n" ++"\n" ++"\n" ++"\t\n" ++"\t\t\n" ++"\t\t\tFailsafe UI\n" ++"\t\t\n" ++"\t\n" ++"\t\n" ++"\t\t

404 - file not found

\n" ++"\t\n" ++"\n"; ++ ++static const char data_index_html[] = ++"HTTP/1.0 200 OK\n" ++"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n" ++"Content-type: text/html\n" ++"\n" ++"\n" ++"\t\n" ++"\t\t\n" ++"\t\t\tFailsafe UI\n" ++"\t\t\n" ++"\t\n" ++"\t\n" ++"\t\t

Failsafe UI

\n" ++"\t\t
\n" ++"\t\t\t\n" ++"\t\t\t\n" ++"\t\t
\n" ++"\t\n" ++"\n"; ++ ++static const char data_flash_html[] = ++"HTTP/1.0 200 OK\n" ++"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n" ++"Content-type: text/html\n" ++"\n" ++"\n" ++"\t\n" ++"\t\t\n" ++"\t\t\tFailsafe UI\n" ++"\t\t\n" ++"\t\n" ++"\t\n" ++"\t\t

Flashing...

\n" ++"\t\tThe system is now trying to flash. If there is a problem, the LEDs will " ++"start to blink.
\n" ++"\n" ++"\t\tAfter a successful update the box will reboot\n" ++"\t\n" ++"\n"; ++ ++const struct fsdata_file file_flashing_html[] = ++{{NULL, "/flashing.html", data_flashing_html, sizeof(data_flashing_html)}}; ++ ++const struct fsdata_file file_fail_html[] = ++{{file_flashing_html, "/fail.html", data_fail_html, sizeof(data_fail_html)}}; + +-const struct fsdata_file file_fail_html[] = {{file_flashing_html, data_fail_html, data_fail_html + 11, sizeof(data_fail_html) - 11}}; ++const struct fsdata_file file_404_html[] = ++{{file_fail_html, "/404.html", data_404_html, sizeof(data_404_html)}}; + +-const struct fsdata_file file_404_html[] = {{file_fail_html, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}}; ++const struct fsdata_file file_index_html[] = ++{{file_404_html, "/index.html", data_index_html, sizeof(data_index_html)}}; + +-const struct fsdata_file file_index_html[] = {{file_404_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}}; +- +-const struct fsdata_file file_flash_html[] = {{file_index_html, data_flash_html, data_flash_html + 12, sizeof(data_flash_html) - 12}}; ++const struct fsdata_file file_flash_html[] = ++{{file_index_html, "/flash.html", data_flash_html, sizeof(data_flash_html)}}; + + #define FS_ROOT file_flash_html + +-#define FS_NUMFILES 5 +\ No newline at end of file ++#define FS_NUMFILES 5 +--- a/net/uip-0.9/httpd.c ++++ b/net/uip-0.9/httpd.c +@@ -130,7 +130,7 @@ httpd_appcall(void) + if(!fs_open((const char *)&uip_appdata[4], &fsfile)) + { + PRINTLN("couldn't open file"); +- fs_open(file_index_html.name, &fsfile); ++ fs_open(file_404_html.name, &fsfile); + } + } + hs->script = 0; +@@ -141,7 +141,7 @@ httpd_appcall(void) + if(hs->state == HTTP_FIRMWARE) + { + unsigned char *start = (unsigned char*)uip_appdata; +- char *clen = strstr(start, "Content-Length:"); ++ char *clen = strstr((char *)start, "Content-Length:"); + int len = 0; + unsigned char *next, *end; + unsigned char *boundary_start; +@@ -150,14 +150,14 @@ httpd_appcall(void) + if(clen) + { + clen += sizeof("Content-Length:"); +- next = strstr(clen, eol); ++ next = (unsigned char *)strstr(clen, eol); + if(next) + { + len = atoi(clen); + next++; + printf("expecting %d bytes\n", len); + upload_data = httpd_upload_data = (unsigned char *)do_http_tmp_address(); +- printf("received data will be stored at 0x%08X\n", upload_data); ++ printf("received data will be stored at %p\n", upload_data); + if(!upload_data) + { + printf("failed to allocate memory\n"); +@@ -174,14 +174,14 @@ httpd_appcall(void) + uip_close(); + return; + } +- boundary_start = strstr(next, "---"); ++ boundary_start = (unsigned char *)strstr((char *)next, "---"); + if(!boundary_start) + { + uip_close(); + return; + } +- end = strstr(boundary_start, eol); +- if(!eol) ++ end = (unsigned char *)strstr((char *)boundary_start, eol); ++ if(!end) + { + uip_close(); + return; +@@ -189,13 +189,13 @@ httpd_appcall(void) + boundary_len = end - boundary_start; + memcpy(boundary, boundary_start, boundary_len); + boundary[boundary_len] = 0; +- next = strstr(boundary_start, "name=\"firmware\";"); ++ next = (unsigned char *)strstr((char *)boundary_start, "name=\"firmware\";"); + if(!next) + { + uip_close(); + return; + } +- next = strstr(next, eol2); ++ next = (unsigned char *)strstr((char *)next, eol2); + if(!next) + { + printf("could not find start of data\n"); +@@ -259,7 +259,6 @@ httpd_appcall(void) + { + if(upload_running) + { +- int i; + httpd_upload_complete = 1; + // for(i = 0; i < hs->upload_total; i++) + // printf("%c", httpd_upload_data[i]); +@@ -267,7 +266,7 @@ httpd_appcall(void) + uip_close(); + } + } +- uip_send(hs->dataptr, hs->count); ++ uip_send((unsigned char *)hs->dataptr, hs->count); + } + break; + diff --git a/package/uboot-lantiq/patches/200-portability.patch b/package/uboot-lantiq/patches/200-portability.patch deleted file mode 100644 index ae38ad68ea..0000000000 --- a/package/uboot-lantiq/patches/200-portability.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- a/tools/kwbimage.c -+++ b/tools/kwbimage.c -@@ -206,6 +206,28 @@ INVL_DATA: - exit (EXIT_FAILURE); - } - -+#ifndef __GLIBC__ -+static ssize_t -+getline(char **line, size_t *len, FILE *fd) -+{ -+ char *tmp; -+ int tmplen; -+ -+ tmp = fgetln(fd, &tmplen); -+ if (!tmp) -+ return -1; -+ -+ if (!*line || tmplen > *len) { -+ *len = tmplen + 1; -+ *line = realloc(*line, *len); -+ } -+ -+ strncpy(*line, tmp, tmplen); -+ line[tmplen] = 0; -+ return tmplen; -+} -+#endif -+ - /* - * this function sets the kwbimage header by- - * 1. Abstracting input command line arguments data diff --git a/package/uboot-lantiq/patches/210-compile.patch b/package/uboot-lantiq/patches/210-compile.patch deleted file mode 100644 index c00230069d..0000000000 --- a/package/uboot-lantiq/patches/210-compile.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/common/env_common.c -+++ b/common/env_common.c -@@ -26,6 +26,7 @@ - - #include - #include -+#include - #include - #include - #include ---- a/common/env_embedded.c -+++ b/common/env_embedded.c -@@ -27,6 +27,7 @@ - #define __ASM_STUB_PROCESSOR_H__ /* don't include asm/processor. */ - #include - #undef __ASSEMBLY__ -+#include - #include - - /* diff --git a/package/uboot-lantiq/patches/300-arcadyan.patch b/package/uboot-lantiq/patches/300-arcadyan.patch new file mode 100644 index 0000000000..24ee042159 --- /dev/null +++ b/package/uboot-lantiq/patches/300-arcadyan.patch @@ -0,0 +1,93 @@ +--- a/common/Makefile ++++ b/common/Makefile +@@ -127,7 +127,9 @@ + ifdef CONFIG_PCI + COBJS-$(CONFIG_CMD_PCI) += cmd_pci.o + endif ++ifdef CONFIG_CMD_PCMCIA + COBJS-y += cmd_pcmcia.o ++endif + COBJS-$(CONFIG_CMD_PORTIO) += cmd_portio.o + COBJS-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o + COBJS-$(CONFIG_CMD_REISER) += cmd_reiser.o +--- a/drivers/pcmcia/Makefile ++++ b/drivers/pcmcia/Makefile +@@ -28,9 +28,11 @@ + COBJS-$(CONFIG_I82365) += i82365.o + COBJS-$(CONFIG_8xx) += mpc8xx_pcmcia.o + COBJS-$(CONFIG_PXA_PCMCIA) += pxa_pcmcia.o +-COBJS-y += rpx_pcmcia.o ++#COBJS-y += rpx_pcmcia.o ++COBJS-$(CONFIG_RPX_PCMCIA) += rpx_pcmcia.o + COBJS-$(CONFIG_IDE_TI_CARDBUS) += ti_pci1410a.o +-COBJS-y += tqm8xx_pcmcia.o ++#COBJS-y += tqm8xx_pcmcia.o ++COBJS-$(CONFIG_TQM8XX_PCMCIA) += tqm8xx_pcmcia.o + COBJS-$(CONFIG_MARUBUN_PCCARD) += marubun_pcmcia.o + + COBJS := $(COBJS-y) +--- a/drivers/usb/phy/Makefile ++++ b/drivers/usb/phy/Makefile +@@ -23,7 +23,7 @@ + LIB := $(obj)libusb_phy.a + + COBJS-$(CONFIG_TWL4030_USB) += twl4030.o +-COBJS-y := twl4030.o ++#COBJS-y := twl4030.o + + COBJS := $(COBJS-y) + SRCS := $(COBJS:.o=.c) +--- a/Makefile ++++ b/Makefile +@@ -3414,6 +3414,37 @@ + ## MIPS32 ifxcpe + ######################################################################### + ++define arcadyan ++$(1) : unconfig ++ @mkdir -p $(obj)include ++ @mkdir -p $(obj)board/arcadyan/ ++ @[ -z "$$(findstring brnboot,$$@)" ] || \ ++ { echo "TEXT_BASE = 0x80002000" >$(obj)board/arcadyan/config.tmp ; \ ++ echo "#define CONFIG_SYS_RAMBOOT" >>$(obj)include/config.h ; \ ++ echo "#define CONFIG_SYS_BRNBOOT" >>$(obj)include/config.h ; \ ++ $(XECHO) "... with brnboot configuration" ; \ ++ } ++ @[ -z "$$(findstring ramboot,$$@)" ] || \ ++ { echo "TEXT_BASE = 0xA0400000" >$(obj)board/arcadyan/config.tmp ; \ ++ echo "#define CONFIG_SYS_RAMBOOT" >>$(obj)include/config.h ; \ ++ $(XECHO) "... with ramboot configuration" ; \ ++ } ++ @if [ "$$(findstring flash,$$@)" ] ; then \ ++ echo "#define CONFIG_USE_DDR_RAM" >>$(obj)include/config.h ; \ ++ echo "#define CONFIG_USE_DDR_RAM_CFG_psc166" >>$(obj)include/config.h ; \ ++ fi ++ @$(MKCONFIG) -a $$(word 1,$$(subst _, ,$$@)) mips mips arcadyan "" danube ++endef ++ ++$(eval $(call arcadyan, arv4520PW%config)) ++$(eval $(call arcadyan, arv452CPW%config)) ++$(eval $(call arcadyan, arv4525PW%config)) ++$(eval $(call arcadyan, arv4510PW%config)) ++$(eval $(call arcadyan, arv4518PW%config)) ++$(eval $(call arcadyan, arv7518PW%config)) ++$(eval $(call arcadyan, arv752DPW%config)) ++$(eval $(call arcadyan, arv752DPW22%config)) ++ + easy50712%config : unconfig + @mkdir -p $(obj)include + @mkdir -p $(obj)board/infineon/easy50712 +--- a/net/tftp.c ++++ b/net/tftp.c +@@ -11,9 +11,9 @@ + #include "bootp.h" + + #define WELL_KNOWN_PORT 69 /* Well known TFTP port # */ +-#define TIMEOUT 5000UL /* Millisecs to timeout for lost pkt */ ++#define TIMEOUT 10000UL /* Millisecs to timeout for lost pkt */ + #ifndef CONFIG_NET_RETRY_COUNT +-# define TIMEOUT_COUNT 10 /* # of timeouts before giving up */ ++# define TIMEOUT_COUNT 200 /* # of timeouts before giving up */ + #else + # define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT * 2) + #endif diff --git a/package/uboot-lantiq/patches/300-httpd.patch b/package/uboot-lantiq/patches/300-httpd.patch deleted file mode 100644 index 8c4c1ffb6e..0000000000 --- a/package/uboot-lantiq/patches/300-httpd.patch +++ /dev/null @@ -1,9350 +0,0 @@ ---- a/common/cmd_net.c -+++ b/common/cmd_net.c -@@ -43,6 +43,18 @@ U_BOOT_CMD( - "[loadAddress] [[hostIPaddr:]bootfilename]" - ); - -+#if defined(CONFIG_CMD_HTTPD) -+int do_httpd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -+{ -+ return NetLoopHttpd(); -+} -+ -+U_BOOT_CMD( -+ httpd, 1, 1, do_httpd, -+ "httpd\t- start webserver", "" -+); -+#endif -+ - int do_tftpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) - { - return netboot_common (TFTP, cmdtp, argc, argv); ---- /dev/null -+++ b/include/httpd.h -@@ -0,0 +1,17 @@ -+#ifndef _UIP_HTTPD_H__ -+#define _UIP_HTTPD_H__ -+ -+void HttpdStart (void); -+void HttpdHandler (void); -+ -+/* board specific implementation */ -+extern int do_http_upgrade(const unsigned char *data, const ulong size); -+ -+#define HTTP_PROGRESS_START 0 -+#define HTTP_PROGRESS_TIMEOUT 1 -+#define HTTP_PROGRESS_UPLOAD_READY 2 -+#define HTTP_PROGRESS_UGRADE_READY 3 -+#define HTTP_PROGRESS_UGRADE_FAILED 4 -+extern int do_http_progress(const int state); -+ -+#endif ---- a/include/net.h -+++ b/include/net.h -@@ -383,7 +383,8 @@ extern int NetTimeOffset; /* offset ti - - /* Initialize the network adapter */ - extern int NetLoop(proto_t); -- -+extern int NetLoopHttpd(void); -+extern void NetSendHttpd(void); - /* Shutdown adapters and cleanup */ - extern void NetStop(void); - ---- a/net/Makefile -+++ b/net/Makefile -@@ -26,6 +26,10 @@ include $(TOPDIR)/config.mk - # CFLAGS += -DDEBUG - - LIB = $(obj)libnet.a -+UIPDIR = uip-0.9 -+RSADIR = uip-0.9 -+$(shell mkdir -p $(obj)$(UIPDIR)) -+$(shell mkdir -p $(obj)$(RSADIR)) - - COBJS-$(CONFIG_CMD_NET) += bootp.o - COBJS-$(CONFIG_CMD_DNS) += dns.o -@@ -36,6 +40,9 @@ COBJS-$(CONFIG_CMD_NET) += rarp.o - COBJS-$(CONFIG_CMD_SNTP) += sntp.o - COBJS-$(CONFIG_CMD_NET) += tftp.o - -+COBJS-$(CONFIG_CMD_HTTPD) += httpd.o $(UIPDIR)/fs.o $(UIPDIR)/httpd.o $(UIPDIR)/uip_arp.o $(UIPDIR)/uip_arch.o $(UIPDIR)/uip.o -+COBJS-$(CONFIG_CMD_RSA) += $(RSADIR)/bigint.o $(RSADIR)/base64.o $(RSADIR)/rmd160.o $(RSADIR)/rsa.o -+ - COBJS := $(COBJS-y) - SRCS := $(COBJS:.o=.c) - OBJS := $(addprefix $(obj),$(COBJS)) ---- /dev/null -+++ b/net/httpd.c -@@ -0,0 +1,52 @@ -+/* -+ * Copyright 1994, 1995, 2000 Neil Russell. -+ * (See License) -+ * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de -+ */ -+ -+#include -+#include -+#include -+#include "uip-0.9/uipopt.h" -+#include "uip-0.9/uip.h" -+#include "uip-0.9/uip_arp.h" -+ -+ -+#if defined(CONFIG_CMD_HTTPD) -+ -+#define TIMEOUT 5 -+ -+static int arptimer = 0; -+ -+void -+HttpdHandler (void) -+{ -+ int i; -+ for(i = 0; i < UIP_CONNS; i++) { -+ uip_periodic(i); -+ if(uip_len > 0) { -+ uip_arp_out(); -+ NetSendHttpd(); -+ } -+ } -+ if(++arptimer == 20) { -+ uip_arp_timer(); -+ arptimer = 0; -+ } -+} -+ -+static void -+HttpdTimeout (void) -+{ -+ puts ("T "); -+ NetSetTimeout (TIMEOUT * 1000, HttpdTimeout); -+} -+ -+void -+HttpdStart (void) -+{ -+ uip_init(); -+ httpd_init(); -+} -+ -+#endif ---- a/net/net.c -+++ b/net/net.c -@@ -95,6 +95,19 @@ - #if defined(CONFIG_CMD_DNS) - #include "dns.h" - #endif -+#if defined(CONFIG_CMD_HTTPD) -+#include "httpd.h" -+#include "uip-0.9/uipopt.h" -+#include "uip-0.9/uip.h" -+#include "uip-0.9/uip_arp.h" -+static int https_running = 0; -+int httpd_upload_complete = 0; -+unsigned char *httpd_upload_data = 0; -+extern int upload_running; -+void NetReceiveHttpd(volatile uchar * inpkt, int len); -+void NetSendHttpd(void); -+extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); -+#endif - - DECLARE_GLOBAL_DATA_PTR; - -@@ -1308,6 +1321,13 @@ NetReceive(volatile uchar * inpkt, int l - - debug("packet received\n"); - -+#if defined(CONFIG_CMD_HTTPD) -+ if(https_running) { -+ NetReceiveHttpd(inpkt, len); -+ return; -+ } -+#endif -+ - NetRxPacket = inpkt; - NetRxPacketLen = len; - et = (Ethernet_t *)inpkt; -@@ -1922,3 +1942,162 @@ ushort getenv_VLAN(char *var) - { - return (string_to_VLAN(getenv(var))); - } -+ -+#if defined(CONFIG_CMD_HTTPD) -+ -+void -+NetSendHttpd(void) -+{ -+ volatile uchar *tmpbuf = NetTxPacket; -+ int i; -+ -+ for(i = 0; i < 40 + UIP_LLH_LEN; i++) { -+ tmpbuf[i] = uip_buf[i]; -+ } -+ -+ for(; i < uip_len; i++) { -+ tmpbuf[i] = uip_appdata[i - 40 - UIP_LLH_LEN]; -+ } -+ eth_send(NetTxPacket, uip_len); -+} -+ -+#define BUF ((struct uip_eth_hdr *)&uip_buf[0]) -+ -+void -+NetReceiveHttpd(volatile uchar * inpkt, int len) -+{ -+ memcpy(uip_buf, inpkt, len); -+ uip_len = len; -+ if(BUF->type == htons(UIP_ETHTYPE_IP)) { -+ uip_arp_ipin(); -+ uip_input(); -+ if(uip_len > 0) { -+ uip_arp_out(); -+ NetSendHttpd(); -+ } -+ } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) { -+ uip_arp_arpin(); -+ if(uip_len > 0) { -+ NetSendHttpd(); -+ } -+ } -+} -+ -+int -+NetLoopHttpd(void) -+{ -+ unsigned long long tout = 0; -+ bd_t *bd = gd->bd; -+ unsigned short int ip[2]; -+ -+#ifdef CONFIG_NET_MULTI -+ NetRestarted = 0; -+ NetDevExists = 0; -+#endif -+ -+ /* XXX problem with bss workaround */ -+ NetArpWaitPacketMAC = NULL; -+ NetArpWaitTxPacket = NULL; -+ NetArpWaitPacketIP = 0; -+ NetArpWaitReplyIP = 0; -+ NetArpWaitTxPacket = NULL; -+ NetTxPacket = NULL; -+ NetTryCount = 1; -+ -+ if (!NetTxPacket) { -+ int i; -+ /* -+ * Setup packet buffers, aligned correctly. -+ */ -+ NetTxPacket = &PktBuf[0] + (PKTALIGN - 1); -+ NetTxPacket -= (ulong)NetTxPacket % PKTALIGN; -+ for (i = 0; i < PKTBUFSRX; i++) { -+ NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN; -+ } -+ } -+ -+ if (!NetArpWaitTxPacket) { -+ NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1); -+ NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN; -+ NetArpWaitTxPacketSize = 0; -+ } -+ -+restart: -+ -+ eth_halt(); -+#ifdef CONFIG_NET_MULTI -+ eth_set_current(); -+#endif -+ if (eth_init(bd) < 0) { -+ eth_halt(); -+ return(-1); -+ } -+ -+#ifdef CONFIG_NET_MULTI -+ memcpy (NetOurEther, eth_get_dev()->enetaddr, 6); -+#else -+ eth_getenv_enetaddr("ethaddr", NetOurEther); -+#endif -+ -+ NetCopyIP(&NetOurIP, &bd->bi_ip_addr); -+ NetOurGatewayIP = getenv_IPaddr ("gatewayip"); -+ NetOurSubnetMask= getenv_IPaddr ("netmask"); -+ NetOurVLAN = getenv_VLAN("vlan"); -+ NetOurNativeVLAN = getenv_VLAN("nvlan"); -+ -+ printf("starting httpd server from server %ld.%ld.%ld.%ld\n", -+ (bd->bi_ip_addr & 0xff000000) >> 24, -+ (bd->bi_ip_addr & 0x00ff0000) >> 16, -+ (bd->bi_ip_addr & 0x0000ff00) >> 8, -+ (bd->bi_ip_addr & 0x000000ff)); -+ -+ HttpdStart(); -+ -+ ip[0] = ((bd->bi_ip_addr & 0xffff0000) >> 16); -+ ip[1] = (bd->bi_ip_addr & 0x0000ffff); -+ uip_sethostaddr(ip); -+ -+ do_http_progress(HTTP_PROGRESS_START); -+ -+ https_running = 1; -+ for (;;) { -+ unsigned long long t1; -+ WATCHDOG_RESET(); -+ if(eth_rx() > 0) { -+ HttpdHandler(); -+ } else { -+ t1 = get_ticks(); -+ if(t1 - tout > 1000) { -+ do_http_progress(HTTP_PROGRESS_TIMEOUT); -+ tout = t1; -+ } -+ } -+ if(!httpd_upload_complete) -+ continue; -+ printf("Bytes transferred = %ld (%lx hex)\n", -+ NetBootFileXferSize, -+ NetBootFileXferSize); -+ eth_halt(); -+ do_http_progress(HTTP_PROGRESS_UPLOAD_READY); -+ if(do_http_upgrade(&httpd_upload_data[0], NetBootFileXferSize) == 0) { -+ do_http_progress(HTTP_PROGRESS_UGRADE_READY); -+ udelay(1000 * 10); -+ do_reset (0,0,0,0); -+ return 0; -+ } -+ break; -+ } -+ https_running = 0; -+ NetBootFileXferSize = 0; -+ httpd_upload_complete = 0; -+ upload_running = 0; -+// free(httpd_upload_data); -+ -+ do_http_progress(HTTP_PROGRESS_UGRADE_FAILED); -+ -+ goto restart; -+ -+ return -1; -+} -+ -+#endif ---- /dev/null -+++ b/net/rsa/Makefile -@@ -0,0 +1,31 @@ -+# -+# FONRSA & FONSIGN libraries unit testing -+# -+# This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. -+# -+# Execute in this directory -+# -+# Created: 20070422 Pablo Martin Medrano -+# -+# $Id: Makefile 389 2007-06-11 08:29:56Z pablo.martin $ -+# -+# FIXME: Put this in the main Makefile.am -+# -+all: fonsign dump_key -+ -+fonsign: -+ gcc -g sign_openssl.c -D__MAINTEST__ -o fonsign -lssl -+ -+dump_key: -+ gcc -o dump_key dump_key.c -+ ./dump_key > public_key.h -+ -+foncheckrsa: -+ gcc -g bigint.c fonrsa.c rmd160.c foncheckrsa.c base64.c log.c -o foncheckrsa -+ -+#private_fon_rsa_key.pem: -+# openssl genrsa -out private_fon_rsa_key.pem 4096 -+# openssl rsa -in private_fon_rsa_key.pem -pubout -out public_fon_rsa_key.pem -+ -+clean: -+ rm fonsign dump_key ---- /dev/null -+++ b/net/rsa/base64.c -@@ -0,0 +1,137 @@ -+#include "base64.h" -+ -+static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -+/* Note that '=' (padding) is 0 */ -+static const unsigned char fb64[256] = { -+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -+ 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63, -+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, -+ 255, 0, 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,255,255,255,255,255, -+ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255, -+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -+}; -+ -+static int encodeblock( unsigned char *in, char *out, int len ) -+{ -+ char s[3]; -+ int i; -+ -+ for (i = 0; i < len; i++) -+ s[i] = in[i]; -+ for (i = len; i < 3; i++) -+ s[i] = 0; -+ out[0] = (unsigned char)(cb64[(s[0] & 0xfc) >> 2 ]); -+ out[1] = (unsigned char)(cb64[((s[0] & 0x03) << 4) | ((s[1] & 0xf0) >> 4) ]); -+ out[2] = (unsigned char)(cb64[((s[1] & 0x0f) << 2) | ((s[2] & 0xc0) >> 6) ]); -+ out[3] = (unsigned char)(cb64[s[2] & 0x3f ]); -+ switch (len) { -+ case 1: -+ out[3] = '='; -+ case 2: -+ out[2] = '='; -+ break; -+ default: -+ break; -+ } -+ -+ return 4; -+} -+ -+static int decodeblock(char *ins, unsigned char *out, int len) -+{ -+ int i; -+ unsigned char in[4]; -+ int skip = 0; -+ -+ if (len != 4) -+ return -1; -+ for (i = 0; i < len; i++) { -+ if (ins[i] == '=') { -+ in[i] = 0; -+ skip++; -+ } else -+ in[i] = fb64[(int)(ins[i])]; -+ if (in[i] == 255) { -+ return -1; -+ } -+ } -+ out[0] = (unsigned char ) (in[0] << 2 | in[1] >> 4); -+ if (skip == 2) { -+ return 1; -+ } -+ out[1] = (unsigned char )((in[1] & 0x0f) << 4 | in[2] >> 2); -+ if (skip == 1) { -+ return 2; -+ } -+ out[2] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]); -+ -+ return 3; -+} -+ -+int B64_encode(char *source, char *destination, int size_source, int size_destination) -+{ -+ int chunks, reminder, size, d, i, size_expected; -+ char *s; -+ unsigned char *t; -+ -+ chunks = size_source / 3; -+ reminder = size_source % 3; -+ size = 0; -+ size_expected = (chunks * 4) + (reminder?(reminder + 1):0); -+ if (size_destination < ((chunks * 4) + (reminder?4:0))) { -+ return 1; -+ } -+ for (i = 0; i < chunks; i++) { -+ s = source + (i * 3); -+ t = destination + (i * 4); -+ d = encodeblock(s, t, 3); -+ if (d == -1) { -+ return 1; -+ } -+ size += d; -+ } -+ if (reminder) { -+ d = encodeblock(source + (chunks * 3), destination + (chunks * 4), reminder); -+ if (d == -1) { -+ return 1; -+ } -+ size += d; -+ } -+ return size; -+} -+ -+int B64_decode(char *source, char *destination, int size_source, int size_destination) -+{ -+ int chunks, reminder, size, d, i; -+ -+ chunks = size_source / 4; -+ reminder = size_source % 4; -+ size = 0; -+ if (reminder) { -+ return 1; -+ } -+ if (size_destination < ((chunks * 3))) { -+ printf("%d, %d\n", -+ size_destination, ((chunks * 3) + reminder)); -+ return -1; -+ } -+ for (i = 0; i < chunks; i++) { -+ d = decodeblock(source + (i * 4), destination + (i * 3), 4); -+ if (d == -1) { -+ return -1; -+ } -+ size += d; -+ } -+ return size; -+} -+ ---- /dev/null -+++ b/net/rsa/base64.h -@@ -0,0 +1,11 @@ -+#ifndef _BASE64_H_ -+#define _BASE64_H_ -+#ifdef __cplusplus -+extern "C" { -+#endif -+int B64_encode(char *source, char *destination, int size_source, int size_destination); -+int B64_decode(char *source, char *destination, int size_source, int size_destination); -+#ifdef __cplusplus -+} -+#endif -+#endif ---- /dev/null -+++ b/net/rsa/bigint.c -@@ -0,0 +1,906 @@ -+/* -+ * Copyright(C) 2006 -+ * -+ * This library is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU Lesser General Public License as published by -+ * the Free Software Foundation; either version 2.1 of the License, or -+ * (at your option) any later version. -+ * -+ * This library 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 Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public License -+ * along with this library; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+/** -+ * @defgroup bigint_api Big Integer API -+ * @brief The bigint implementation as used by the axTLS project. -+ * -+ * The bigint library is for RSA encryption/decryption as well as signing. -+ * This code tries to minimise use of malloc/free by maintaining a small -+ * cache. A bigint context may maintain state by being made "permanent". -+ * It be be later released with a bi_depermanent() and bi_free() call. -+ * -+ * It supports the following reduction techniques: -+ * - Classical -+ * - Barrett -+ * - Montgomery -+ * -+ * It also implements the following: -+ * - Karatsuba multiplication -+ * - Squaring -+ * - Sliding window exponentiation -+ * - Chinese Remainder Theorem (implemented in rsa.c). -+ * -+ * All the algorithms used are pretty standard, and designed for different -+ * data bus sizes. Negative numbers are not dealt with at all, so a subtraction -+ * may need to be tested for negativity. -+ * -+ * This library steals some ideas from Jef Poskanzer -+ * -+ * and GMP . It gets most of its implementation -+ * detail from "The Handbook of Applied Cryptography" -+ * -+ * @{ -+ */ -+ -+#include "bigint.h" -+#include -+#include "div64.h" -+ -+static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bi, comp i); -+static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom); -+static bigint *alloc(BI_CTX *ctx, int size); -+static bigint *trim(bigint *bi); -+static void more_comps(bigint *bi, int n); -+ -+/** -+ * @brief Start a new bigint context. -+ * @return A bigint context. -+ */ -+BI_CTX *bi_initialize(void) -+{ -+ BI_CTX *ctx = (BI_CTX *)calloc(1, sizeof(BI_CTX)); -+ -+ ctx->active_list = NULL; -+ ctx->active_count = 0; -+ ctx->free_list = NULL; -+ ctx->free_count = 0; -+ ctx->mod_offset = 0; -+ -+ /* the radix */ -+ ctx->bi_radix = alloc(ctx, 2); -+ ctx->bi_radix->comps[0] = 0; -+ ctx->bi_radix->comps[1] = 1; -+ bi_permanent(ctx->bi_radix); -+ -+ return ctx; -+} -+ -+/** -+ * @brief Close the bigint context and free any resources. -+ * -+ * Free up any used memory - a check is done if all objects were not -+ * properly freed. -+ * @param ctx [in] The bigint session context. -+ */ -+void bi_terminate(BI_CTX *ctx) -+{ -+ bigint *p, *pn; -+ -+ bi_depermanent(ctx->bi_radix); -+ bi_free(ctx, ctx->bi_radix); -+ -+ if (ctx->active_count != 0) -+ { -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ return; -+ } -+ -+ for (p = ctx->free_list; p != NULL; p = pn) -+ { -+ pn = p->next; -+ free(p->comps); -+ free(p); -+ } -+ -+ free(ctx); -+} -+ -+/** -+ * @brief Increment the number of references to this object. -+ * It does not do a full copy. -+ * @param bi [in] The bigint to copy. -+ * @return A referent to the same bigint. -+ */ -+bigint *bi_copy(bigint *bi) -+{ -+ check(bi); -+ if (bi->refs != PERMANENT) -+ bi->refs++; -+ return bi; -+} -+ -+/** -+ * @brief Simply make a bigint object "unfreeable" if bi_free() is called on it. -+ * -+ * For this object to be freed, bi_depermanent() must be called. -+ * @param bi [in] The bigint to be made permanent. -+ */ -+void bi_permanent(bigint *bi) -+{ -+ check(bi); -+ if (bi->refs != 1) -+ { -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ return; -+ } -+ -+ bi->refs = PERMANENT; -+} -+ -+/** -+ * @brief Take a permanent object and make it elligible for freedom. -+ * @param bi [in] The bigint to be made back to temporary. -+ */ -+void bi_depermanent(bigint *bi) -+{ -+ check(bi); -+ if (bi->refs != PERMANENT) -+ { -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ return; -+ } -+ -+ bi->refs = 1; -+} -+ -+/** -+ * @brief Free a bigint object so it can be used again. -+ * -+ * The memory itself it not actually freed, just tagged as being available -+ * @param ctx [in] The bigint session context. -+ * @param bi [in] The bigint to be freed. -+ */ -+void bi_free(BI_CTX *ctx, bigint *bi) -+{ -+ check(bi); -+ if (bi->refs == PERMANENT) -+ { -+ return; -+ } -+ -+ if (--bi->refs > 0) -+ { -+ return; -+ } -+ -+ bi->next = ctx->free_list; -+ ctx->free_list = bi; -+ ctx->free_count++; -+ -+ if (--ctx->active_count < 0) -+ { -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ return; -+ } -+} -+ -+/** -+ * @brief Convert an (unsigned) integer into a bigint. -+ * @param ctx [in] The bigint session context. -+ * @param i [in] The (unsigned) integer to be converted. -+ * -+ */ -+bigint *int_to_bi(BI_CTX *ctx, comp i) -+{ -+ bigint *biR = alloc(ctx, 1); -+ biR->comps[0] = i; -+ return biR; -+} -+ -+/** -+ * @brief Do a full copy of the bigint object. -+ * @param ctx [in] The bigint session context. -+ * @param bi [in] The bigint object to be copied. -+ */ -+bigint *bi_clone(BI_CTX *ctx, const bigint *bi) -+{ -+ bigint *biR = alloc(ctx, bi->size); -+ check(bi); -+ memcpy(biR->comps, bi->comps, bi->size*COMP_BYTE_SIZE); -+ return biR; -+} -+ -+/** -+ * @brief Perform an additon operation between two bigints. -+ * @param ctx [in] The bigint session context. -+ * @param bia [in] A bigint. -+ * @param bib [in] Another bigint. -+ * @return The result of the addition. -+ */ -+bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib) -+{ -+ int n; -+ comp carry = 0; -+ comp *pa, *pb; -+ -+ check(bia); -+ check(bib); -+ -+ if (bia->size > bib->size) -+ n = bia->size; -+ else -+ n = bib->size; -+ more_comps(bia, n+1); -+ more_comps(bib, n); -+ pa = bia->comps; -+ pb = bib->comps; -+ -+ do -+ { -+ comp sl, rl, cy1; -+ sl = *pa + *pb++; -+ rl = sl + carry; -+ cy1 = sl < *pa; -+ carry = cy1 | (rl < sl); -+ *pa++ = rl; -+ } while (--n != 0); -+ -+ *pa = carry; /* do overflow */ -+ bi_free(ctx, bib); -+ return trim(bia); -+} -+ -+/** -+ * @brief Perform a subtraction operation between two bigints. -+ * @param ctx [in] The bigint session context. -+ * @param bia [in] A bigint. -+ * @param bib [in] Another bigint. -+ * @param is_negative [out] If defined, indicates that the result was negative. -+ * is_negative may be NULL. -+ * @return The result of the subtraction. The result is always positive. -+ */ -+bigint *bi_subtract(BI_CTX *ctx, -+ bigint *bia, bigint *bib, int *is_negative) -+{ -+ int n = bia->size; -+ comp *pa, *pb, carry = 0; -+ -+ check(bia); -+ check(bib); -+ -+ more_comps(bib, n); -+ pa = bia->comps; -+ pb = bib->comps; -+ -+ do -+ { -+ comp sl, rl, cy1; -+ sl = *pa - *pb++; -+ rl = sl - carry; -+ cy1 = sl > *pa; -+ carry = cy1 | (rl > sl); -+ *pa++ = rl; -+ } while (--n != 0); -+ -+ if (is_negative) /* indicate a negative result */ -+ { -+ *is_negative = carry; -+ } -+ -+ bi_free(ctx, trim(bib)); /* put bib back to the way it was */ -+ return trim(bia); -+} -+ -+/** -+ * Perform a multiply between a bigint an an (unsigned) integer -+ */ -+static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bia, comp b) -+{ -+ int j = 0, n = bia->size; -+ bigint *biR = alloc(ctx, n + 1); -+ comp carry = 0; -+ comp *r = biR->comps; -+ comp *a = bia->comps; -+ -+ check(bia); -+ -+ /* clear things to start with */ -+ memset(r, 0, ((n+1)*COMP_BYTE_SIZE)); -+ -+ do -+ { -+ long_comp tmp = *r + (long_comp)a[j]*b + carry; -+ *r++ = (comp)tmp; /* downsize */ -+ carry = (comp)(tmp >> COMP_BIT_SIZE); -+ } while (++j < n); -+ -+ *r = carry; -+ bi_free(ctx, bia); -+ return trim(biR); -+} -+ -+/** -+ * @brief Does both division and modulo calculations. -+ * -+ * Used extensively when doing classical reduction. -+ * @param ctx [in] The bigint session context. -+ * @param u [in] A bigint which is the numerator. -+ * @param v [in] Either the denominator or the modulus depending on the mode. -+ * @param is_mod [n] Determines if this is a normal division (0) or a reduction -+ * (1). -+ * @return The result of the division/reduction. -+ */ -+bigint *bi_divide(BI_CTX *ctx, bigint *u, bigint *v, int is_mod) -+{ -+ int n = v->size, m = u->size-n; -+ int j = 0, orig_u_size = u->size; -+ uint8_t mod_offset = ctx->mod_offset; -+ comp d; -+ bigint *quotient, *tmp_u; -+ comp q_dash; -+ -+ check(u); -+ check(v); -+ -+ /* if doing reduction and we are < mod, then return mod */ -+ if (is_mod && bi_compare(v, u) > 0) -+ { -+ bi_free(ctx, v); -+ return u; -+ } -+ -+ quotient = alloc(ctx, m+1); -+ tmp_u = alloc(ctx, n+1); -+ v = trim(v); /* make sure we have no leading 0's */ -+ // d = (comp)((long_comp)COMP_RADIX/(V1+1)); -+ long_comp x = COMP_RADIX; do_div(x, V1+1); d = x; -+ -+ /* clear things to start with */ -+ memset(quotient->comps, 0, ((quotient->size)*COMP_BYTE_SIZE)); -+ -+ /* normalise */ -+ if (d > 1) -+ { -+ u = bi_int_multiply(ctx, u, d); -+ -+ if (is_mod) -+ { -+ v = ctx->bi_normalised_mod[mod_offset]; -+ } -+ else -+ { -+ v = bi_int_multiply(ctx, v, d); -+ } -+ } -+ -+ if (orig_u_size == u->size) /* new digit position u0 */ -+ { -+ more_comps(u, orig_u_size + 1); -+ } -+ -+ do -+ { -+ /* get a temporary short version of u */ -+ memcpy(tmp_u->comps, &u->comps[u->size-n-1-j], (n+1)*COMP_BYTE_SIZE); -+ -+ /* calculate q' */ -+ if (U(0) == V1) -+ { -+ q_dash = COMP_RADIX-1; -+ } -+ else -+ { -+ //q_dash = (comp)(((long_comp)U(0)*COMP_RADIX + U(1))/V1); -+ long_comp x = U(0)*COMP_RADIX + U(1); do_div(x, V1); q_dash = x; -+ -+ } -+ -+ if (v->size > 1 && V2) -+ { -+ /* we are implementing the following -+ if (V2*q_dash > (((U(0)*COMP_RADIX + U(1) - -+ q_dash*V1)*COMP_RADIX) + U(2))) ... */ -+ comp inner = (comp)((long_comp)COMP_RADIX*U(0) + U(1) - -+ (long_comp)q_dash*V1); -+ if ((long_comp)V2*q_dash > (long_comp)inner*COMP_RADIX + U(2)) -+ { -+ q_dash--; -+ } -+ } -+ -+ /* multiply and subtract */ -+ if (q_dash) -+ { -+ int is_negative; -+ tmp_u = bi_subtract(ctx, tmp_u, -+ bi_int_multiply(ctx, bi_copy(v), q_dash), &is_negative); -+ more_comps(tmp_u, n+1); -+ -+ Q(j) = q_dash; -+ -+ /* add back */ -+ if (is_negative) -+ { -+ Q(j)--; -+ tmp_u = bi_add(ctx, tmp_u, bi_copy(v)); -+ /* lop off the carry */ -+ tmp_u->size--; -+ v->size--; -+ } -+ } -+ else -+ { -+ Q(j) = 0; -+ } -+ -+ /* copy back to u */ -+ memcpy(&u->comps[u->size-n-1-j], tmp_u->comps, (n+1)*COMP_BYTE_SIZE); -+ } while (++j <= m); -+ -+ bi_free(ctx, tmp_u); -+ bi_free(ctx, v); -+ -+ if (is_mod) /* get the remainder */ -+ { -+ bi_free(ctx, quotient); -+ return bi_int_divide(ctx, trim(u), d); -+ } -+ else /* get the quotient */ -+ { -+ bi_free(ctx, u); -+ return trim(quotient); -+ } -+} -+ -+/** -+ * Perform an integer divide on a bigint. -+ */ -+static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom) -+{ -+ int i = biR->size - 1; -+ long_comp r = 0; -+ -+ check(biR); -+ -+ do -+ { -+ r = (r<comps[i]; -+ //biR->comps[i] = (comp)(r / denom); -+ long_comp x = r; do_div(x, denom); biR->comps[i] = x; -+/* while(r > denom) -+ { -+ r -= denom; -+ }*/ -+ r%=denom; -+ } while (--i != 0); -+ -+ return trim(biR); -+} -+ -+/** -+ * @brief Allow a binary sequence to be imported as a bigint. -+ * @param ctx [in] The bigint session context. -+ * @param data [in] The data to be converted. -+ * @param size [in] The number of bytes of data. -+ * @return A bigint representing this data. -+ */ -+bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int size) -+{ -+ bigint *biR = alloc(ctx, (size+COMP_BYTE_SIZE-1)/COMP_BYTE_SIZE); -+ int i, j = 0, offset = 0; -+ -+ memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE); -+ -+ for (i = size-1; i >= 0; i--) -+ { -+ biR->comps[offset] += data[i] << (j*8); -+ -+ if (++j == COMP_BYTE_SIZE) -+ { -+ j = 0; -+ offset ++; -+ } -+ } -+ -+ return trim(biR); -+} -+ -+/** -+ * @brief Take a bigint and convert it into a byte sequence. -+ * -+ * This is useful after a decrypt operation. -+ * @param ctx [in] The bigint session context. -+ * @param x [in] The bigint to be converted. -+ * @param data [out] The converted data as a byte stream. -+ * @param size [in] The maximum size of the byte stream. Unused bytes will be -+ * zeroed. -+ */ -+void bi_export(BI_CTX *ctx, bigint *x, uint8_t *data, int size) -+{ -+ int i, j, k = size-1; -+ -+ check(x); -+ memset(data, 0, size); /* ensure all leading 0's are cleared */ -+ -+ for (i = 0; i < x->size; i++) -+ { -+ for (j = 0; j < COMP_BYTE_SIZE; j++) -+ { -+ comp mask = 0xff << (j*8); -+ int num = (x->comps[i] & mask) >> (j*8); -+ data[k--] = num; -+ -+ if (k < 0) -+ { -+ break; -+ } -+ } -+ } -+ -+ bi_free(ctx, x); -+} -+ -+/** -+ * @brief Pre-calculate some of the expensive steps in reduction. -+ * -+ * This function should only be called once (normally when a session starts). -+ * When the session is over, bi_free_mod() should be called. bi_mod_power() -+ * relies on this function being called. -+ * @param ctx [in] The bigint session context. -+ * @param bim [in] The bigint modulus that will be used. -+ * @param mod_offset [in] There are three moduluii that can be stored - the -+ * standard modulus, and it's two primes p and q. This offset refers to which -+ * modulus we are referring to. -+ * @see bi_free_mod(), bi_mod_power(). -+ */ -+void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset) -+{ -+ int k = bim->size; -+ comp d; -+// comp d = (comp)((long_comp)COMP_RADIX/(bim->comps[k-1]+1)); -+ long_comp x = COMP_RADIX; do_div(x, bim->comps[k-1]+1); d = x; -+ -+ ctx->bi_mod[mod_offset] = bim; -+ bi_permanent(ctx->bi_mod[mod_offset]); -+ ctx->bi_normalised_mod[mod_offset] = bi_int_multiply(ctx, bim, d); -+ bi_permanent(ctx->bi_normalised_mod[mod_offset]); -+} -+ -+/** -+ * @brief Used when cleaning various bigints at the end of a session. -+ * @param ctx [in] The bigint session context. -+ * @param mod_offset [in] The offset to use. -+ * @see bi_set_mod(). -+ */ -+void bi_free_mod(BI_CTX *ctx, int mod_offset) -+{ -+ bi_depermanent(ctx->bi_mod[mod_offset]); -+ bi_free(ctx, ctx->bi_mod[mod_offset]); -+ bi_depermanent(ctx->bi_normalised_mod[mod_offset]); -+ bi_free(ctx, ctx->bi_normalised_mod[mod_offset]); -+} -+ -+/** -+ * Perform a standard multiplication between two bigints. -+ */ -+static bigint *regular_multiply(BI_CTX *ctx, bigint *bia, bigint *bib) -+{ -+ int i, j, i_plus_j, n = bia->size, t = bib->size; -+ bigint *biR = alloc(ctx, n + t); -+ comp *sr = biR->comps; -+ comp *sa = bia->comps; -+ comp *sb = bib->comps; -+ -+ check(bia); -+ check(bib); -+ -+ /* clear things to start with */ -+ memset(biR->comps, 0, ((n+t)*COMP_BYTE_SIZE)); -+ i = 0; -+ -+ do -+ { -+ comp carry = 0; -+ comp b = *sb++; -+ i_plus_j = i; -+ j = 0; -+ -+ do -+ { -+ long_comp tmp = sr[i_plus_j] + (long_comp)sa[j]*b + carry; -+ sr[i_plus_j++] = (comp)tmp; /* downsize */ -+ carry = (comp)(tmp >> COMP_BIT_SIZE); -+ } while (++j < n); -+ -+ sr[i_plus_j] = carry; -+ } while (++i < t); -+ -+ bi_free(ctx, bia); -+ bi_free(ctx, bib); -+ return trim(biR); -+} -+ -+/** -+ * @brief Perform a multiplication operation between two bigints. -+ * @param ctx [in] The bigint session context. -+ * @param bia [in] A bigint. -+ * @param bib [in] Another bigint. -+ * @return The result of the multiplication. -+ */ -+bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib) -+{ -+ check(bia); -+ check(bib); -+ -+ return regular_multiply(ctx, bia, bib); -+} -+ -+ -+/** -+ * @brief Compare two bigints. -+ * @param bia [in] A bigint. -+ * @param bib [in] Another bigint. -+ * @return -1 if smaller, 1 if larger and 0 if equal. -+ */ -+int bi_compare(bigint *bia, bigint *bib) -+{ -+ int r, i; -+ -+ check(bia); -+ check(bib); -+ -+ if (bia->size > bib->size) -+ r = 1; -+ else if (bia->size < bib->size) -+ r = -1; -+ else -+ { -+ comp *a = bia->comps; -+ comp *b = bib->comps; -+ -+ /* Same number of components. Compare starting from the high end -+ * and working down. */ -+ r = 0; -+ i = bia->size - 1; -+ -+ do -+ { -+ if (a[i] > b[i]) -+ { -+ r = 1; -+ break; -+ } -+ else if (a[i] < b[i]) -+ { -+ r = -1; -+ break; -+ } -+ } while (--i >= 0); -+ } -+ -+ return r; -+} -+ -+/** -+ * Allocate and zero more components. Does not consume bi. -+ */ -+static void more_comps(bigint *bi, int n) -+{ -+ if (n > bi->max_comps) -+ { -+ if ((bi->max_comps * 2) > n) { -+ bi->max_comps = bi->max_comps * 2; -+ } else { -+ bi->max_comps = n; -+ } -+ bi->comps = (comp*)realloc(bi->comps, bi->max_comps * COMP_BYTE_SIZE); -+ } -+ -+ if (n > bi->size) -+ { -+ memset(&bi->comps[bi->size], 0, (n-bi->size)*COMP_BYTE_SIZE); -+ } -+ -+ bi->size = n; -+} -+ -+/* -+ * Make a new empty bigint. It may just use an old one if one is available. -+ * Otherwise get one of the heap. -+ */ -+static bigint *alloc(BI_CTX *ctx, int size) -+{ -+ bigint *biR; -+ -+ /* Can we recycle an old bigint? */ -+ if (ctx->free_list != NULL) -+ { -+ biR = ctx->free_list; -+ ctx->free_list = biR->next; -+ ctx->free_count--; -+ if (biR->refs != 0) -+ { -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); -+ return 0; -+ } -+ -+ more_comps(biR, size); -+ } -+ else -+ { -+ /* No free bigints available - create a new one. */ -+ biR = (bigint *)malloc(sizeof(bigint)); -+ biR->comps = (comp*) malloc(size * COMP_BYTE_SIZE); -+ biR->max_comps = size; /* give some space to spare */ -+ } -+ -+ biR->size = size; -+ biR->refs = 1; -+ biR->next = NULL; -+ ctx->active_count++; -+ return biR; -+} -+ -+/* -+ * Work out the highest '1' bit in an exponent. Used when doing sliding-window -+ * exponentiation. -+ */ -+static int find_max_exp_index(bigint *biexp) -+{ -+ int i = COMP_BIT_SIZE-1; -+ comp shift = COMP_RADIX/2; -+ comp test = biexp->comps[biexp->size-1]; /* assume no leading zeroes */ -+ -+ check(biexp); -+ -+ do -+ { -+ if (test & shift) -+ { -+ return i+(biexp->size-1)*COMP_BIT_SIZE; -+ } -+ -+ shift >>= 1; -+ } while (--i != 0); -+ -+ return -1; /* error - must have been a leading 0 */ -+} -+ -+/* -+ * Is a particular bit is an exponent 1 or 0? Used when doing sliding-window -+ * exponentiation. -+ */ -+static int exp_bit_is_one(bigint *biexp, int offset) -+{ -+ comp test = biexp->comps[offset / COMP_BIT_SIZE]; -+ int num_shifts = offset % COMP_BIT_SIZE; -+ comp shift = 1; -+ int i; -+ -+ check(biexp); -+ -+ for (i = 0; i < num_shifts; i++) -+ { -+ shift <<= 1; -+ } -+ -+ return test & shift; -+} -+ -+/* -+ * Delete any leading 0's (and allow for 0). -+ */ -+static bigint *trim(bigint *bi) -+{ -+ check(bi); -+ -+ while (bi->comps[bi->size-1] == 0 && bi->size > 1) -+ { -+ bi->size--; -+ } -+ -+ return bi; -+} -+ -+/** -+ * @brief Perform a modular exponentiation. -+ * -+ * This function requires bi_set_mod() to have been called previously. This is -+ * one of the optimisations used for performance. -+ * @param ctx [in] The bigint session context. -+ * @param bi [in] The bigint on which to perform the mod power operation. -+ * @param biexp [in] The bigint exponent. -+ * @see bi_set_mod(). -+ */ -+bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp) -+{ -+ int i = find_max_exp_index(biexp), j, window_size = 1; -+ bigint *biR = int_to_bi(ctx, 1); -+ -+ check(bi); -+ check(biexp); -+ -+ ctx->g = (bigint **)malloc(sizeof(bigint *)); -+ ctx->g[0] = bi_clone(ctx, bi); -+ ctx->window = 1; -+ bi_permanent(ctx->g[0]); -+ -+ /* if sliding-window is off, then only one bit will be done at a time and -+ * will reduce to standard left-to-right exponentiation */ -+ do -+ { -+ if (exp_bit_is_one(biexp, i)) -+ { -+ int l = i-window_size+1; -+ int part_exp = 0; -+ -+ if (l < 0) /* LSB of exponent will always be 1 */ -+ { -+ l = 0; -+ } -+ else -+ { -+ while (exp_bit_is_one(biexp, l) == 0) -+ { -+ l++; /* go back up */ -+ } -+ } -+ -+ /* build up the section of the exponent */ -+ for (j = i; j >= l; j--) -+ { -+ biR = bi_residue(ctx, bi_square(ctx, biR)); -+ if (exp_bit_is_one(biexp, j)) -+ part_exp++; -+ -+ if (j != l) -+ part_exp <<= 1; -+ } -+ -+ part_exp = (part_exp-1)/2; /* adjust for array */ -+ biR = bi_residue(ctx, -+ bi_multiply(ctx, biR, ctx->g[part_exp])); -+ i = l-1; -+ } -+ else /* square it */ -+ { -+ biR = bi_residue(ctx, bi_square(ctx, biR)); -+ i--; -+ } -+ } while (i >= 0); -+ -+ /* cleanup */ -+ for (i = 0; i < ctx->window; i++) -+ { -+ bi_depermanent(ctx->g[i]); -+ bi_free(ctx, ctx->g[i]); -+ } -+ -+ free(ctx->g); -+ bi_free(ctx, bi); -+ bi_free(ctx, biexp); -+ return biR; -+} -+ -+/** @} */ ---- /dev/null -+++ b/net/rsa/bigint.h -@@ -0,0 +1,73 @@ -+/* -+ * Copyright(C) 2006 -+ * -+ * This library is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU Lesser General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This library 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 Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public License -+ * along with this library; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Trimmed down from axTLS -+ * -+ * $Id: bigint.h 392 2007-06-25 16:24:51Z pablo.martin $ -+ * -+ */ -+ -+#ifndef BIGINT_HEADER -+#define BIGINT_HEADER -+ -+#define CONFIG_BIGINT_CLASSICAL 1 -+ -+#define SOCKET_READ(A,B,C) read(A,B,C) -+#define SOCKET_WRITE(A,B,C) write(A,B,C) -+#define SOCKET_CLOSE(A) close(A) -+#define TTY_FLUSH() -+ -+#include "bigint_impl.h" -+ -+#ifndef CONFIG_BIGINT_CHECK_ON -+#define check(A) /**< disappears in normal production mode */ -+#endif -+BI_CTX *bi_initialize(void); -+void bi_terminate(BI_CTX *ctx); -+void bi_permanent(bigint *bi); -+void bi_depermanent(bigint *bi); -+void bi_free(BI_CTX *ctx, bigint *bi); -+bigint *bi_copy(bigint *bi); -+bigint *bi_clone(BI_CTX *ctx, const bigint *bi); -+void bi_export(BI_CTX *ctx, bigint *bi, uint8_t *data, int size); -+bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int len); -+bigint *int_to_bi(BI_CTX *ctx, comp i); -+ -+/* the functions that actually do something interesting */ -+bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib); -+bigint *bi_subtract(BI_CTX *ctx, bigint *bia, -+ bigint *bib, int *is_negative); -+bigint *bi_divide(BI_CTX *ctx, bigint *bia, bigint *bim, int is_mod); -+bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib); -+bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp); -+bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp); -+int bi_compare(bigint *bia, bigint *bib); -+void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset); -+void bi_free_mod(BI_CTX *ctx, int mod_offset); -+ -+/** -+ * @def bi_mod -+ * Find the residue of B. bi_set_mod() must be called before hand. -+ */ -+#define bi_mod(A, B) bi_divide(A, B, ctx->bi_mod[ctx->mod_offset], 1) -+ -+#define bi_residue(A, B) bi_mod(A, B) -+ -+#define bi_square(A, B) bi_multiply(A, bi_copy(B), B) -+ -+#endif -+ ---- /dev/null -+++ b/net/rsa/bigint_impl.h -@@ -0,0 +1,109 @@ -+/* -+ * Copyright(C) 2006 -+ * -+ * This library is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU Lesser General Public License as published by -+ * the Free Software Foundation; either version 2.1 of the License, or -+ * (at your option) any later version. -+ * -+ * This library 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 Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public License -+ * along with this library; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef BIGINT_IMPL_HEADER -+#define BIGINT_IMPL_HEADER -+ -+#include -+#include -+ -+/* Maintain a number of precomputed variables when doing reduction */ -+#define BIGINT_M_OFFSET 0 /**< Normal modulo offset. */ -+#ifdef CONFIG_BIGINT_CRT -+#define BIGINT_P_OFFSET 1 /**< p modulo offset. */ -+#define BIGINT_Q_OFFSET 2 /**< q module offset. */ -+#define BIGINT_NUM_MODS 3 /**< The number of modulus constants used. */ -+#else -+#define BIGINT_NUM_MODS 1 -+#endif -+ -+/* Architecture specific functions for big ints */ -+// #ifdef WIN32 -+// #define COMP_RADIX 4294967296i64 -+// #define COMP_BIG_MSB 0x8000000000000000i64 -+// #else -+#define COMP_RADIX 4294967296ULL /**< Max component + 1 */ -+#define COMP_BIG_MSB 0x8000000000000000ULL /**< (Max dbl comp + 1)/ 2 */ -+//#endif -+#define COMP_BIT_SIZE 32 /**< Number of bits in a component. */ -+#define COMP_BYTE_SIZE 4 /**< Number of bytes in a component. */ -+#define COMP_NUM_NIBBLES 8 /**< Used For diagnostics only. */ -+ -+typedef uint32_t comp; /**< A single precision component. */ -+typedef uint64_t long_comp; /**< A double precision component. */ -+typedef int64_t slong_comp; /**< A signed double precision component. */ -+ -+/** -+ * @struct _bigint -+ * @brief A big integer basic object -+ */ -+struct _bigint -+{ -+ struct _bigint* next; /**< The next bigint in the cache. */ -+ short size; /**< The number of components in this bigint. */ -+ short max_comps; /**< The heapsize allocated for this bigint */ -+ int refs; /**< An internal reference count. */ -+ comp* comps; /**< A ptr to the actual component data */ -+}; -+ -+typedef struct _bigint bigint; /**< An alias for _bigint */ -+ -+/** -+ * Maintains the state of the cache, and a number of variables used in -+ * reduction. -+ */ -+typedef struct /**< A big integer "session" context. */ -+{ -+ bigint *active_list; /**< Bigints currently used. */ -+ bigint *free_list; /**< Bigints not used. */ -+ bigint *bi_radix; /**< The radix used. */ -+ bigint *bi_mod[BIGINT_NUM_MODS]; /**< modulus */ -+ -+#if defined(CONFIG_BIGINT_MONTGOMERY) -+ bigint *bi_RR_mod_m[BIGINT_NUM_MODS]; /**< R^2 mod m */ -+ bigint *bi_R_mod_m[BIGINT_NUM_MODS]; /**< R mod m */ -+ comp N0_dash[BIGINT_NUM_MODS]; -+#elif defined(CONFIG_BIGINT_BARRETT) -+ bigint *bi_mu[BIGINT_NUM_MODS]; /**< Storage for mu */ -+#endif -+ bigint *bi_normalised_mod[BIGINT_NUM_MODS]; /**< Normalised mod storage. */ -+ bigint **g; /**< Used by sliding-window. */ -+ int window; /**< The size of the sliding window */ -+ -+ int active_count; /**< Number of active bigints. */ -+ int free_count; /**< Number of free bigints. */ -+ -+#ifdef CONFIG_BIGINT_MONTGOMERY -+ uint8_t use_classical; /**< Use classical reduction. */ -+#endif -+ uint8_t mod_offset; /**< The mod offset we are using */ -+} BI_CTX; -+ -+#if 0 -+#define max(a,b) ((a)>(b)?(a):(b)) /**< Find the maximum of 2 numbers. */ -+#define min(a,b) ((a)<(b)?(a):(b)) /**< Find the minimum of 2 numbers. */ -+#endif -+ -+#define PERMANENT 0x7FFF55AA /**< A magic number for permanents. */ -+ -+#define V1 v->comps[v->size-1] /**< v1 for division */ -+#define V2 v->comps[v->size-2] /**< v2 for division */ -+#define U(j) tmp_u->comps[tmp_u->size-j-1] /**< uj for division */ -+#define Q(j) quotient->comps[quotient->size-j-1] /**< qj for division */ -+ -+#endif ---- /dev/null -+++ b/net/rsa/div64.h -@@ -0,0 +1,113 @@ -+/* -+ * Copyright (C) 2000, 2004 Maciej W. Rozycki -+ * Copyright (C) 2003 Ralf Baechle -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ */ -+#ifndef _ASM_DIV64_H -+#define _ASM_DIV64_H -+ -+#if (_MIPS_SZLONG == 32) -+ -+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -+#define GCC_REG_ACCUM "$0" -+#else -+#define GCC_REG_ACCUM "accum" -+#endif -+ -+ -+//#include -+ -+/* -+ * No traps on overflows for any of these... -+ */ -+ -+#define do_div64_32(res, high, low, base) ({ \ -+ unsigned long __quot, __mod; \ -+ unsigned long __cf, __tmp, __tmp2, __i; \ -+ \ -+ __asm__(".set push\n\t" \ -+ ".set noat\n\t" \ -+ ".set noreorder\n\t" \ -+ "move %2, $0\n\t" \ -+ "move %3, $0\n\t" \ -+ "b 1f\n\t" \ -+ " li %4, 0x21\n" \ -+ "0:\n\t" \ -+ "sll $1, %0, 0x1\n\t" \ -+ "srl %3, %0, 0x1f\n\t" \ -+ "or %0, $1, %5\n\t" \ -+ "sll %1, %1, 0x1\n\t" \ -+ "sll %2, %2, 0x1\n" \ -+ "1:\n\t" \ -+ "bnez %3, 2f\n\t" \ -+ " sltu %5, %0, %z6\n\t" \ -+ "bnez %5, 3f\n" \ -+ "2:\n\t" \ -+ " addiu %4, %4, -1\n\t" \ -+ "subu %0, %0, %z6\n\t" \ -+ "addiu %2, %2, 1\n" \ -+ "3:\n\t" \ -+ "bnez %4, 0b\n\t" \ -+ " srl %5, %1, 0x1f\n\t" \ -+ ".set pop" \ -+ : "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \ -+ "=&r" (__i), "=&r" (__tmp2) \ -+ : "Jr" (base), "0" (high), "1" (low)); \ -+ \ -+ (res) = __quot; \ -+ __mod; }) -+ -+#define do_div(n, base) ({ \ -+ unsigned long long __quot; \ -+ unsigned long __mod; \ -+ unsigned long long __div; \ -+ unsigned long __upper, __low, __high, __base; \ -+ \ -+ __div = (n); \ -+ __base = (base); \ -+ \ -+ __high = __div >> 32; \ -+ __low = __div; \ -+ __upper = __high; \ -+ \ -+ if (__high) \ -+ __asm__("divu $0, %z2, %z3" \ -+ : "=h" (__upper), "=l" (__high) \ -+ : "Jr" (__high), "Jr" (__base) \ -+ : GCC_REG_ACCUM); \ -+ \ -+ __mod = do_div64_32(__low, __upper, __low, __base); \ -+ \ -+ __quot = __high; \ -+ __quot = __quot << 32 | __low; \ -+ (n) = __quot; \ -+ __mod; }) -+#endif /* (_MIPS_SZLONG == 32) */ -+ -+#if (_MIPS_SZLONG == 64) -+ -+/* -+ * Hey, we're already 64-bit, no -+ * need to play games.. -+ */ -+#define do_div(n, base) ({ \ -+ unsigned long __quot; \ -+ unsigned int __mod; \ -+ unsigned long __div; \ -+ unsigned int __base; \ -+ \ -+ __div = (n); \ -+ __base = (base); \ -+ \ -+ __mod = __div % __base; \ -+ __quot = __div / __base; \ -+ \ -+ (n) = __quot; \ -+ __mod; }) -+ -+#endif /* (_MIPS_SZLONG == 64) */ -+ -+#endif /* _ASM_DIV64_H */ ---- /dev/null -+++ b/net/rsa/dump_key.c -@@ -0,0 +1,29 @@ -+#include -+#include -+#include -+#include -+#include -+ -+int main(int argc, char **argv) -+{ -+ FILE *fp = fopen("public_fon_rsa_key_6.pem", "r"); -+ struct stat s; -+ unsigned char *b; -+ int i; -+ if(!fp) -+ return 1; -+ stat("public_fon_rsa_key_6.pem", &s); -+ b = malloc(s.st_size); -+ fread(b, s.st_size, 1, fp); -+ fclose(fp); -+ printf("unsigned char public_key[] = {\n\t"); -+ for(i = 0;i < s.st_size; i++) -+ { -+ printf("0x%02X,", b[i]); -+ if(i%16 == 15) -+ printf("\n\t"); -+ } -+ printf("};\n"); -+// printf("\n%d %d\n", i, s.st_size); -+ return 0; -+} ---- /dev/null -+++ b/net/rsa/foncheckrsa.c -@@ -0,0 +1,79 @@ -+/* -+ * RSA + RIPEMD160 signature verification command -+ * -+ * Copyright (C) 2007 FON Wireless Ltd. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -+ * -+ * Created: 20060728 Pablo Martín Medrano -+ * -+ * $Id: foncheckrsa.c 332 2007-05-02 09:45:54Z pablo.martin $ -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "fonrsa.h" -+ -+int main(int argc, char **argv) -+{ -+ int fd, i; -+ FONRSA_ERROR fonrsa_error; -+ void *handle; -+ -+ if (argc != 4) { -+ fprintf(stderr, " Usage: foncheckrsa [public_key.der] [signature] [file]\n"); -+ fprintf(stderr, " Pablo Martín Medrano \n"); -+ fprintf(stderr, " RIPEMD-160 software written by Antoon Bosselaers,\n"); -+ fprintf(stderr, " available at http://www.esat.kuleuven.be/~cosicart/ps/AB-9601/.\n"); -+ fprintf(stderr, " Uses the axTLS library bigint implementation (libfonrsa)\n"); -+ fprintf(stderr, " http://www.leroc.com.au/axTLS/\n"); -+ return -1; -+ } -+ /* Check the existence of input files */ -+ for (i = 1; i < 4; i++) { -+ if ((fd = open(argv[i], O_RDONLY)) == -1) { -+ fprintf(stderr, "Error: opening \"%s\": %s\n", argv[i], -+ strerror(errno)); -+ fprintf(stderr, "Bailing out..."); -+ exit(-2); -+ } -+ close(fd); -+ } -+ handle = FR_init(argv[1]); -+ if (handle == NULL) { -+ printf("Error loading keys in %s\n", argv[1]); -+ return 1; -+ } -+ fonrsa_error = FR_verify_file(handle, argv[3], argv[2]); -+ FR_end(handle); -+ switch (fonrsa_error) { -+ case FONRSA_OK: -+ printf("Verified OK\n"); -+ return 0; -+ case FONRSA_VERIFICATION_FAILURE: -+ printf("Verification failure\n"); -+ return 1; -+ default: -+ printf("Verification error\n"); -+ return -1; -+ } -+ return -1; -+} -+ ---- /dev/null -+++ b/net/rsa/fonrsa.c -@@ -0,0 +1,584 @@ -+/* -+ * FONSM RSA handling library -+ * -+ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. -+ * -+ * This library is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU Lesser General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This library 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 Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public License -+ * along with this library; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Created: 20070306 Pablo Martin Medrano -+ * -+ * Based on axTLS -+ * -+ * $Id: fonrsa.c 405 2007-09-19 15:26:17Z jesus.pico $ -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "rmd160.h" -+#include "bigint.h" -+#include "fonrsa.h" -+#include "base64.h" -+ -+typedef struct { -+ uint8_t *buffer; -+ size_t size; -+} DER_key; -+ -+typedef struct { -+ bigint *m; /* modulus */ -+ bigint *e; /* public exponent */ -+ int num_octets; -+ BI_CTX *bi_ctx; /* big integer handle */ -+} RSA_parameters; -+ -+typedef struct { -+ DER_key *derkey; -+ RSA_parameters *rsaparms; -+} RSA; -+ -+static uint8_t *CH_load_raw_file(char *filename, size_t *size); -+static DER_key *CH_load_der_key(char *filename); -+static void CH_free_der_key(DER_key *key); -+static int asn1_get_public_key(const uint8_t *buf, int len, RSA_parameters **rsa_parameters); -+void CH_pub_key_new(RSA_parameters **rsa_parameters, const uint8_t *modulus, int mod_len, const uint8_t *pub_exp, int pub_len); -+int CH_decrypt(RSA_parameters *rsa, uint8_t *buffer_in, uint8_t *buffer_out); -+byte *RMDbinary(char *fname); -+int CH_get_rmd160_hash_from_signature(byte *hash, char *signature_file, char *public_key_file); -+static unsigned char *load_file_in_buffer(char *path, int *size); -+static int save_file_from_buffer(char *path, unsigned char *buffer, int size); -+int ExtractPadding(uint8_t* OutputBuffer, uint8_t* InputBuffer, int LengthOfInputBuffer); -+ -+#define RMDsize 160 /* A RIPEMD-160 hash has 160 bits */ -+ -+/* -+ * returns RMD(message in file fname) fname is read as binary data. -+ * non-reentrant -+ */ -+byte *RMDbinary(char *fname) -+{ -+ FILE *mf; /* pointer to file */ -+ byte data[1024]; /* contains current mess. block */ -+ dword nbytes; /* length of this block */ -+ dword MDbuf[RMDsize / 32]; /* contains (A, B, C, D(, E)) */ -+ static byte hashcode[RMDsize / 8]; /* for final hash-value */ -+ dword X[16]; /* current 16-word chunk */ -+ unsigned int i, j; /* counters */ -+ dword length[2]; /* length in bytes of message */ -+ dword offset; /* # of unprocessed bytes at */ -+ /* call of MDfinish */ -+ -+ /* initialize */ -+ if ((mf = fopen(fname, "rb")) == NULL) { -+ fprintf(stderr, "\nRMDbinary: cannot open file \"%s\".\n", -+ fname); -+ exit(1); -+ } -+ MDinit(MDbuf); -+ length[0] = 0; -+ length[1] = 0; -+ while ((nbytes = fread(data, 1, 1024, mf)) != 0) { -+ /* process all complete blocks */ -+ for (i = 0; i < (nbytes >> 6); i++) { -+ for (j = 0; j < 16; j++) -+ X[j] = BYTES_TO_DWORD(data + 64 * i + 4 * j); -+ compress(MDbuf, X); -+ } -+ /* update length[] */ -+ if (length[0] + nbytes < length[0]) -+ length[1]++; /* overflow to msb of length */ -+ length[0] += nbytes; -+ } -+ /* finish: */ -+ offset = length[0] & 0x3C0; /* extract bytes 6 to 10 inclusive */ -+ MDfinish(MDbuf, data + offset, length[0], length[1]); -+ -+ for (i = 0; i < RMDsize / 8; i += 4) { -+ hashcode[i] = MDbuf[i >> 2]; -+ hashcode[i + 1] = (MDbuf[i >> 2] >> 8); -+ hashcode[i + 2] = (MDbuf[i >> 2] >> 16); -+ hashcode[i + 3] = (MDbuf[i >> 2] >> 24); -+ } -+ fclose(mf); -+ -+ return (byte *) hashcode; -+} -+byte *RMDbinary_buffer(char *buffer, int size_buffer) -+{ -+ return NULL; -+} -+ -+/* -+ * Extracts the RMD 160 hash from the signature file -+ */ -+int CH_get_rmd160_hash_from_signature(byte *hash, char *signature_file, char *public_key_file) -+{ -+ RSA_parameters *rsa_parameters; -+ DER_key *derkey; -+ uint8_t *signature; -+ size_t signature_size; -+ uint8_t *decrypted; -+ -+ signature = CH_load_raw_file(signature_file, &signature_size); -+ if ((signature == NULL)||(signature_size != 512)) { -+ fprintf(stderr, "Error: Loading signature key '%s'\n", signature_file); -+ exit(-1); -+ } -+ derkey = CH_load_der_key(public_key_file); -+ if (derkey == NULL) { -+ fprintf(stderr, "Error: opening DER key file '%s'\n", public_key_file); -+ exit(-1); -+ } -+ if ((asn1_get_public_key(derkey->buffer, derkey->size, &rsa_parameters)) != 0) { -+ fprintf(stderr, "Error: Extracting public key from DER file\n"); -+ exit(-1); -+ } -+ CH_free_der_key(derkey); -+ if (rsa_parameters->num_octets != 512) -+ fprintf(stderr, "Error: The RSA public key size is not 4096 bits %d\n", rsa_parameters->num_octets); -+ decrypted = (uint8_t *)malloc(rsa_parameters->num_octets); -+ if (CH_decrypt(rsa_parameters, signature, decrypted)) { -+ fprintf(stderr, "Error: Decrypting signature\n"); -+ exit(-1); -+ } -+ memcpy(hash, decrypted + 492, 20); -+ free(decrypted); -+ free(signature); -+ return 0; -+} -+ -+/* -+ * Decrypts the signature buffer using the rsa public key loaded -+ */ -+int CH_decrypt(RSA_parameters *rsa, uint8_t *buffer_in, uint8_t *buffer_out) -+{ -+ bigint *dat_bi; -+ bigint *decrypted_bi; -+ int byte_size; -+ -+ byte_size = rsa->num_octets; -+ dat_bi = bi_import(rsa->bi_ctx, buffer_in, byte_size); -+ rsa->bi_ctx->mod_offset = BIGINT_M_OFFSET; -+ bi_copy(rsa->m); -+ decrypted_bi = bi_mod_power(rsa->bi_ctx, dat_bi, rsa->e); -+ bi_export(rsa->bi_ctx, decrypted_bi, buffer_out, byte_size); -+ return 0; -+} -+/* -+ * Loads a file in a uint8_t buffer -+ */ -+static uint8_t *CH_load_raw_file(char *filename, size_t *size) -+{ -+ struct stat st; -+ int fd; -+ ssize_t br; -+ uint8_t *ret; -+ -+ if ((stat(filename, &st)) == -1) -+ return NULL; -+ if ((ret = (uint8_t *)malloc(st.st_size)) == NULL) -+ return NULL; -+ fd = open(filename, O_RDONLY); -+ if (fd == -1) { -+ free(ret); -+ return NULL; -+ } -+ br = read(fd, ret, st.st_size); -+ close(fd); -+ if (br != st.st_size) { -+ free(ret); -+ return NULL; -+ } -+ *size = st.st_size; -+ return ret; -+} -+/* -+ * Loads a .der file in a buffer -+ */ -+static DER_key *CH_load_der_key(char *filename) -+{ -+ DER_key *ret; -+ -+ if ((ret = (DER_key *)malloc(sizeof(DER_key))) == NULL) -+ return NULL; -+ if ((ret->buffer = CH_load_raw_file(filename, &(ret->size))) == NULL) { -+ free(ret); -+ return NULL; -+ } -+ return ret; -+} -+/* -+ * CH_load_pem_key -+ */ -+static DER_key *CH_load_pem_key(char *filename) -+{ -+ DER_key *ret; -+ uint8_t *buffer; -+ char *b64,*p,*t; -+ char key[1024]; -+ size_t filesize; -+ int size; -+ -+ if ((ret = (DER_key *)malloc(sizeof(DER_key))) == NULL) -+ return NULL; -+ if ((buffer = CH_load_raw_file(filename, &filesize)) == NULL) { -+ free(ret); -+ return NULL; -+ } -+ p = (char *)buffer; -+ while ((*p != '\n') && (*p != '\0')) -+ p++; -+ if (*p == '\0') { -+ free(ret); -+ return NULL; -+ } -+ p++; -+ b64 = t = p; -+ while((p - b64) <= filesize) { -+ if ((*p == '-')) { -+ break; -+ } else if ((*p != '\n') && (*p != ' ') && (*p != '\t')) { -+ *t = *p; -+ t++; -+ } -+ p++; -+ } -+ *t = '\0'; -+ size = B64_decode(b64, key, strlen(b64), 1024); -+ if (size < 0) { -+ free(buffer); -+ free(ret); -+ return NULL; -+ } -+ free(buffer); -+ ret->buffer = (char *)malloc(size); -+ ret->size = size; -+ memcpy((void *)ret->buffer, (void *)key, size); -+ return ret; -+} -+ -+/* -+ * CH_free_der_key -+ */ -+static void CH_free_der_key(DER_key *key) -+{ -+ free(key->buffer); -+ free(key); -+} -+ -+/* -+ * Get the public key specifics from an ASN.1 encoded file -+ * A function lacking in the exported axTLS API -+ * -+ * This is a really weird hack that only works with RSA public key -+ * files -+ */ -+static int asn1_get_public_key(const uint8_t *buf, int len, RSA_parameters **rsa_parameters) -+{ -+ uint8_t *modulus, *pub_exp; -+ int mod_len, pub_len; -+ -+ pub_len = 3; -+ mod_len = len - 37; -+ if (buf[0] != 0x30) { -+ return -1; -+ } -+ -+ pub_exp = (uint8_t *)malloc(3); -+ modulus = (uint8_t *)malloc(mod_len); -+ memcpy(modulus, buf + 32 , mod_len); -+ memcpy(pub_exp, buf + 34 + mod_len, 3); -+ if (mod_len <= 0 || pub_len <= 0 ) -+ return -1; -+ CH_pub_key_new(rsa_parameters, modulus, mod_len, pub_exp, pub_len); -+ -+ free(modulus); -+ free(pub_exp); -+ return 0; -+} -+ -+/* -+ * Similar to RSA_pub_key_new, rewritten to make this program depend only on bi module -+ */ -+void CH_pub_key_new(RSA_parameters **rsa, const uint8_t *modulus, int mod_len, const uint8_t *pub_exp, int pub_len) -+{ -+ RSA_parameters *rsa_parameters; -+ -+ BI_CTX *bi_ctx = bi_initialize(); -+ *rsa = (RSA_parameters *)calloc(1, sizeof(RSA_parameters)); -+ rsa_parameters = *rsa; -+ rsa_parameters->bi_ctx = bi_ctx; -+ rsa_parameters->num_octets = (mod_len & 0xFFF0); -+ rsa_parameters->m = bi_import(bi_ctx, modulus, mod_len); -+ bi_set_mod(bi_ctx, rsa_parameters->m, BIGINT_M_OFFSET); -+ rsa_parameters->e = bi_import(bi_ctx, pub_exp, pub_len); -+ bi_permanent(rsa_parameters->e); -+} -+ -+static unsigned char *load_file_in_buffer(char *path, int *size) -+{ -+ unsigned char *buffer; -+ struct stat st; -+ int fd; -+ -+ if (stat(path, &st)) -+ return NULL; -+ buffer = (unsigned char *)malloc(st.st_size); -+ if (buffer == NULL) -+ return NULL; -+ if ((fd = open(path, O_RDONLY)) == -1) { -+ free(buffer); -+ return NULL; -+ } -+ if (read(fd, (void *)buffer,st.st_size) != (ssize_t)st.st_size) { -+ free(buffer); -+ close(fd); -+ return NULL; -+ } -+ *size = (int)st.st_size; -+ close(fd); -+ return buffer; -+} -+ -+static int save_file_from_buffer(char *path, unsigned char *buffer, int size) -+{ -+ int fd; -+ -+ if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) == -1) -+ return -1; -+ if (write(fd, buffer, (size_t)size) != ((ssize_t)size)) { -+ close(fd); -+ return -1; -+ } -+ close(fd); -+ return 0; -+} -+ -+/* FR_init */ -+void *FR_init(char *public_key_path) -+{ -+ DER_key *derkey; -+ RSA_parameters *rsa_parameters; -+ char *ending; -+ -+ ending = public_key_path + strlen(public_key_path) - 3; -+ if (!strcmp(ending, "der")) -+ derkey = CH_load_der_key(public_key_path); -+ else if (!strcmp(ending, "pem")) -+ derkey = CH_load_pem_key(public_key_path); -+ else { -+ fprintf(stderr, "Error: unknown key format\n"); -+ exit(-1); -+ } -+ if (derkey == NULL) { -+ fprintf(stderr, "Error: opening key file '%s'\n", public_key_path); -+ exit(-1); -+ } -+ if ((asn1_get_public_key(derkey->buffer, derkey->size, &rsa_parameters)) != 0) { -+ fprintf(stderr, "Error: Extracting public key from file\n"); -+ exit(-1); -+ } -+ CH_free_der_key(derkey); -+ return (void *)rsa_parameters; -+} -+ -+/* FR_end */ -+FONRSA_ERROR FR_end(void *handle) -+{ -+ RSA_parameters *rsa_parameters = (RSA_parameters *)handle; -+ -+ free(rsa_parameters); -+ return FONRSA_OK; -+} -+ -+/* FR_decrypt_buffer */ -+FONRSA_ERROR FR_decrypt_buffer(void *handler, unsigned char *cryptext, int cryptext_size, -+ unsigned char *plaintext, int plaintext_buffer_size, int *plaintext_size) -+{ -+ RSA_parameters *rsaparms = (RSA_parameters *)handler; -+ -+ if (cryptext_size != rsaparms->num_octets) { -+ return FONRSA_SIZE; -+ } -+ if (plaintext_buffer_size < cryptext_size) { -+ return FONRSA_SIZE; -+ } -+ if (CH_decrypt(rsaparms, (uint8_t *)cryptext, (uint8_t *)plaintext)) { -+ return FONRSA_DECRYPT; -+ } -+ *plaintext_size = cryptext_size; -+ return FONRSA_OK; -+} -+ -+FONRSA_ERROR FR_decrypt_buffer_v2(void *handler, unsigned char *cryptext, int cryptext_size, -+ unsigned char *plaintext, int plaintext_buffer_size, int *plaintext_size) -+{ -+ unsigned char* AuxBuffer; -+ int AuxSize; -+ -+ AuxBuffer = (unsigned char*)malloc(cryptext_size); -+ -+ RSA_parameters *rsaparms = (RSA_parameters *)handler; -+ -+ if (cryptext_size != rsaparms->num_octets) { -+ return FONRSA_SIZE; -+ } -+ if (plaintext_buffer_size < cryptext_size) { -+ return FONRSA_SIZE; -+ } -+ if (CH_decrypt(rsaparms, (uint8_t *)cryptext, (uint8_t *)AuxBuffer)) { -+ return FONRSA_DECRYPT; -+ } -+ if ((AuxSize = ExtractPadding((uint8_t*)plaintext, (uint8_t*)AuxBuffer, cryptext_size)) < 0) -+ { -+ printf("Incorrect Padding decrypting buffer"); -+ return FONRSA_DECRYPT; -+ } -+ *plaintext_size = AuxSize; -+ return FONRSA_OK; -+} -+ -+/* -+ * -+ * Implementation of PKCS 1.5 padding, borrowed from -+ * Tom's code (public domain) -+ */ -+ -+/* Standalone FR_verify_file */ -+FONRSA_ERROR FR_verify_file(void *handler, char *file_path, char *signature_file_path) -+{ -+ int j; -+ byte *hashcode; -+ byte hash[20]; -+ uint8_t *decrypted; -+ RSA_parameters *rsa_parameters = (RSA_parameters *)handler; -+ char *signature_buffer; -+ int signature_size; -+ -+ /* Calculates the RIPEMD-160 hash of the file */ -+ hashcode = RMDbinary (file_path); -+ /* Decrypts the signature file using the RSA public key */ -+ signature_buffer = load_file_in_buffer(signature_file_path, &signature_size); -+ if (signature_buffer == NULL) -+ return FONRSA_OPENKEY; -+ -+ if (rsa_parameters->num_octets != signature_size) -+ return FONRSA_SIZE; -+ decrypted = (uint8_t *)malloc(rsa_parameters->num_octets); -+ if (CH_decrypt(rsa_parameters, signature_buffer, decrypted)) { -+ fprintf(stderr, "Error: Decrypting signature\n"); -+ exit(-1); -+ } -+ memcpy(hash, decrypted + 492, 20); -+ free(decrypted); -+ free(signature_buffer); -+ for (j = 0; j < RMDsize/8; j++) { -+ if (hash[j] != hashcode[j]) -+ return FONRSA_VERIFICATION_FAILURE; -+ } -+ return FONRSA_OK; -+} -+ -+/* FR_decrypt_file */ -+FONRSA_ERROR FR_decrypt_file(void *handle, char *crypted_file_path, char *plaintext_file_path) -+{ -+ int size; -+ FONRSA_ERROR ret; -+ char *filebuffer; -+ char crypted[1024]; -+ int crypted_size; -+ -+ if ((filebuffer = load_file_in_buffer(crypted_file_path, &size)) == NULL) { -+ return FONRSA_LOADFILE; -+ } -+ -+ ret = FR_decrypt_buffer(handle, filebuffer, size, crypted, 1024, &crypted_size); -+ if (ret != FONRSA_OK) { -+ free(filebuffer); -+ return ret; -+ } -+ free(filebuffer); -+ -+ if (save_file_from_buffer(plaintext_file_path, crypted, crypted_size)) { -+ printf("Error writing %lu bytes into %s", crypted_size, plaintext_file_path); -+ return FONRSA_SAVEFILE; -+ } -+ return FONRSA_OK; -+} -+ -+int ExtractPadding(uint8_t* OutputBuffer, uint8_t* InputBuffer, int LengthOfInputBuffer) -+{ -+ int i; -+ -+ //First typical checks... -+ if (LengthOfInputBuffer < MINIMUM_PADING_BYTES_PKCS_1_5) -+ { -+ fprintf(stderr, "Error:ExtractPadding: Error, Length of input buffer is too short.\n"); -+ return -1; -+ } -+ else if((InputBuffer[0] != 0) || (InputBuffer[1] > 2)) //Necessary header of Padding... -+ { -+ fprintf(stderr, "Error:ExtractPadding: Error, Padding header is incorrect.\n"); -+ return -1; -+ } -+ for (i=2; i < LengthOfInputBuffer; i++) //Variable size of non-zero padding.... -+ { -+ if (InputBuffer[i] == 0) break; //This is the end of Padding. -+ } -+ //We need to evaluate if there is an existing message... -+ if (i < LengthOfInputBuffer - 2) -+ {//Ok, Padding is extracted... copying the message and finishing... -+ memcpy(OutputBuffer, &(InputBuffer[i + 1]), LengthOfInputBuffer - (i + 1)); -+ return LengthOfInputBuffer - (i + 1); -+ } -+ //If we have reached to this point, then an error has occurred... -+ return -1; -+} -+ -+#ifdef __MAINTEST__ -+int main(int argc, char **argv) -+{ -+ void *handle = NULL; -+ FONRSA_ERROR ret; -+ char *filebuffer = NULL; -+ char crypted[1024]; -+ int size, crypted_size; -+ -+ if (argc != 4) { -+ printf("Usage: %s \n", argv[0]); -+ return 1; -+ } -+ -+ handle = FR_init(argv[1]); -+ if (handle == NULL) { -+ printf("Error loading keys\n"); -+ return 1; -+ } -+ ret = FR_decrypt_file(handle, argv[2], argv[3]); -+ if (ret != FONRSA_OK) { -+ printf("FR_decrypt_file returns %d\n", ret); -+ } -+ FR_end(handle); -+ return (int)ret; -+} -+ -+#endif -+ -+ ---- /dev/null -+++ b/net/rsa/fonrsa.h -@@ -0,0 +1,53 @@ -+/* -+ * FONSM RSA handling library, used by fonsmcd and foncheckrsa -+ * -+ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. -+ * -+ * This library is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU Lesser General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This library 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 Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public License -+ * along with this library; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Created: 20070306 Pablo Martin Medrano -+ * -+ * $Id: fonrsa.h 404 2007-09-17 10:41:31Z jesus.pico $ -+ */ -+#ifndef _FONRSA_H -+#define _FONRSA_H -+ -+#define MINIMUM_PADING_BYTES_PKCS_1_5 3 -+ -+typedef enum { -+ FONRSA_OK = 0, -+ FONRSA_VERIFICATION_FAILURE = 1, -+ FONRSA_OPENKEY = 2, -+ FONRSA_SIZE = 3, -+ FONRSA_LOADFILE = 4, -+ FONRSA_CRYPT = 5, -+ FONRSA_DECRYPT = 6, -+ FONRSA_SAVEFILE = 7, -+ FONRSA_NOSYS = 8, -+ FONRSA_VERIFY = 9 -+} FONRSA_ERROR; -+ -+void *FR_init(char *public_key_path); -+FONRSA_ERROR FR_end(void *handle); -+FONRSA_ERROR FR_decrypt_buffer(void *handler, unsigned char *cryptext, int cryptext_size, -+ unsigned char *plaintext, int plaintext_buffer_size, int *plaintext_size); -+FONRSA_ERROR FR_decrypt_buffer_v2(void *handler, unsigned char *cryptext, int cryptext_size, -+ unsigned char *plaintext, int plaintext_buffer_size, int *plaintext_size); -+FONRSA_ERROR FR_verify_file(void *handler, char *file_path, char *signature_file_path); -+FONRSA_ERROR FR_decrypt_file(void *handler, char *crypted_file_path, char *plaintext_file_path); -+ -+#endif -+ -+ ---- /dev/null -+++ b/net/rsa/log.c -@@ -0,0 +1,138 @@ -+/* -+ * Fonsm log module. Used inside the fonsm backend module and on the client. -+ * -+ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. -+ * -+ * Created: 20070202 Pablo Martin Medrano -+ * -+ * $Id: log.c 392 2007-06-25 16:24:51Z pablo.martin $ -+ */ -+#include -+#include -+#include -+#include -+#include -+#ifndef WIN32 -+#include -+#endif -+#include "log.h" -+ -+#define MAX_SESSION_PREFIX 256 -+ -+typedef struct { -+ char domain[256]; -+ LG_LEVEL watermark; -+ int mode; -+ LG_log_function_pointer function; -+} ST_fslog; -+ -+static ST_fslog fslog; -+static void LG_log_string(LG_LEVEL level, const char *message); -+ -+/*! -+ \brief Starts the log subsystem, redirecting glog() to stderr/syslog depending -+ on mode -+ \retval FSLOG_ERROR : FSLOG_OK if everything goes well -+ \param lg : handle that will be returned -+ \param ident : program identifier, any string -+ \param low_watermark : if the log level is less than this value, it will not be logged -+ \param mode : FSLOG_MODE_SYSLOG (log to syslog) or FSLOG_MODE_STDERR (log to stderr) -+*/ -+FSLOG_ERROR LG_start(const char *domain, LG_LEVEL watermark, int mode, -+ LG_log_function_pointer log_function, int facility) -+{ -+#ifndef WIN32 -+ strncpy(fslog.domain, domain, MAX_LG_DOMAIN); -+ fslog.domain[MAX_LG_DOMAIN - 1] = '\0'; -+ fslog.watermark = watermark; -+ fslog.mode = mode; -+ fslog.function = log_function?log_function:LG_log_string; -+ if (fslog.mode & LG_SYSLOG) -+ openlog(domain, LOG_NDELAY, facility); -+ return FSLOG_OK; -+#else -+ return FSLOG_OK; -+#endif -+} -+ -+/*! -+ \brief Set the low watermark -+ \retval FSLOG_ERROR : FSLOG_OK -+ \param lg : log handle -+ \param low_watermark : new watermark -+*/ -+FSLOG_ERROR LG_set_loglevel(LG_LEVEL watermark) -+{ -+ fslog.watermark = watermark; -+ return FSLOG_OK; -+} -+ -+/*! -+ \brief Ends the log subsystem, unregisteing glog handle -+ \retval FSLOG_ERROR : FSLOG_OK if everything goes well -+ \param handle : log handle to free -+*/ -+FSLOG_ERROR LG_end(void) -+{ -+#ifndef WIN32 -+ if (fslog.mode & LG_SYSLOG) -+ closelog(); -+#endif -+ return FSLOG_OK; -+} -+ -+ -+void LG_log(LG_LEVEL loglevel, const char *message, ...) -+{ -+#ifndef WIN32 -+ va_list ap; -+ char buffer[4096]; -+ int n; -+ -+ va_start(ap, message); -+ n = vsnprintf(buffer, MAX_LOG_STRING, message, ap); -+ va_end(ap); -+ if (n > -1 && n < MAX_LOG_STRING) -+ fslog.function(loglevel, buffer); -+ else -+ fon_critical("%s: Message too big to be logged", __FUNCTION__); -+#else -+ return; -+#endif -+} -+ -+/* Default log function (when mode is LG_SYSLOG or LG_STDERR) */ -+static void LG_log_string(LG_LEVEL level, const char *message) -+{ -+#ifndef WIN32 -+ static struct { -+ int syslog_level; -+ char *log_string; -+ } fonlog_to_syslog[] = { -+ [LG_DEBUG] = {LOG_ERR, "DEBUG"}, -+ [LG_MESSAGE] = {LOG_ERR, "MESSAGE"}, -+ [LG_WARNING] = {LOG_ERR, "WARNING"}, -+ [LG_CRITICAL] = {LOG_ERR, "CRITICAL"}, -+ [LG_ERROR] = {LOG_ERR, "ERROR"} -+ }; -+ -+ if (level < fslog.watermark) -+ return; -+ if (fslog.mode & LG_SYSLOG) { -+ if (level == LG_MESSAGE) { -+ syslog(LOG_INFO, "%s", message); -+ } else { -+ syslog(fonlog_to_syslog[level].syslog_level, "%s: %s", fonlog_to_syslog[level].log_string, message); -+ } -+ } -+ if (fslog.mode & LG_STDERR) { -+ fprintf(stderr, "%s[%d]: %8.8s: %s\n", fslog.domain, -+ getpid(), fonlog_to_syslog[level].log_string, -+ message); -+ } -+#else -+ /* FIXE: todo */ -+ return; -+#endif -+} -+ ---- /dev/null -+++ b/net/rsa/log.h -@@ -0,0 +1,77 @@ -+/* -+ * Fonsm log module. Used inside the fonsm backend module and on the client. -+ * -+ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. -+ * -+ * Created: 20070202 Pablo Martin Medrano -+ * -+ * $Id: log.h 379 2007-05-28 09:17:48Z pablo.martin $ -+ */ -+#ifndef _LOG_H -+#define _LOG_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+typedef enum { -+ FSLOG_OK = 0, -+ FSLOG_UNKNOWN = -1 -+} FSLOG_ERROR; -+ -+ -+typedef void * LG_HANDLE; -+ -+typedef enum { -+ LG_DEBUG = 0, -+ LG_MESSAGE = 1, -+ LG_INFO = 2, -+ LG_WARNING = 3, -+ LG_CRITICAL = 4, -+ LG_ERROR = 5 -+} LG_LEVEL; -+ -+#define LG_SYSLOG 0x01 -+#define LG_STDERR 0x02 -+#define LG_CUSTOM 0x04 -+ -+#define MAX_LG_DOMAIN 256 -+#define MAX_LOG_STRING 4096 -+ -+#ifndef NDEBUG -+#ifndef LOGPRINTF -+#define fon_debug(...) LG_log (LG_DEBUG, __VA_ARGS__) -+#else -+#define fon_debug(...) { printf("DEBUG: "); printf(__VA_ARGS__); printf("\n"); } -+#endif -+#else -+/* fon_debug evaluates to nothing when NDEBUG is defined */ -+#define fon_debug(...) -+#endif -+#ifndef LOGPRINTF -+#define fon_message(...) LG_log (LG_MESSAGE, __VA_ARGS__) -+#define fon_warning(...) LG_log (LG_WARNING, __VA_ARGS__) -+#define fon_critical(...) LG_log (LG_CRITICAL, __VA_ARGS__) -+#define fon_error(...) LG_log (LG_ERROR, __VA_ARGS__) -+#else -+#define fon_message(...) { printf("MESSAGE: "); printf(__VA_ARGS__); printf("\n"); } -+#define fon_warning(...) { printf("WARNING: "); printf(__VA_ARGS__); printf("\n"); } -+#define fon_critical(...) { printf("CRITICAL: "); printf(__VA_ARGS__); printf("\n"); } -+#define fon_error(...) { printf("ERROR: "); printf(__VA_ARGS__); printf("\n"); } -+#endif -+ -+typedef void (*LG_log_function_pointer)(LG_LEVEL level, const char *message); -+ -+FSLOG_ERROR LG_start(const char *domain, LG_LEVEL watermark, int mode, LG_log_function_pointer log_function, int facility); -+FSLOG_ERROR LG_set_loglevel(LG_LEVEL watermark); -+FSLOG_ERROR LG_end(void); -+void LG_log(LG_LEVEL loglevel, const char *message, ...); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif -+ ---- /dev/null -+++ b/net/rsa/public_key.h -@@ -0,0 +1,52 @@ -+unsigned char public_key[] = { -+ 0x2D,0x2D,0x2D,0x2D,0x2D,0x42,0x45,0x47,0x49,0x4E,0x20,0x50,0x55,0x42,0x4C,0x49, -+ 0x43,0x20,0x4B,0x45,0x59,0x2D,0x2D,0x2D,0x2D,0x2D,0x0A,0x4D,0x49,0x49,0x43,0x49, -+ 0x6A,0x41,0x4E,0x42,0x67,0x6B,0x71,0x68,0x6B,0x69,0x47,0x39,0x77,0x30,0x42,0x41, -+ 0x51,0x45,0x46,0x41,0x41,0x4F,0x43,0x41,0x67,0x38,0x41,0x4D,0x49,0x49,0x43,0x43, -+ 0x67,0x4B,0x43,0x41,0x67,0x45,0x41,0x34,0x4C,0x42,0x76,0x59,0x43,0x4B,0x38,0x38, -+ 0x6D,0x75,0x57,0x61,0x73,0x31,0x4F,0x53,0x73,0x71,0x30,0x0A,0x38,0x39,0x38,0x79, -+ 0x76,0x54,0x4B,0x71,0x41,0x6E,0x4F,0x37,0x78,0x2F,0x44,0x53,0x57,0x72,0x46,0x53, -+ 0x30,0x42,0x72,0x47,0x53,0x51,0x31,0x52,0x69,0x44,0x39,0x55,0x62,0x78,0x77,0x6F, -+ 0x64,0x76,0x36,0x65,0x51,0x4B,0x55,0x30,0x67,0x36,0x52,0x6B,0x2F,0x39,0x54,0x70, -+ 0x4C,0x6E,0x4F,0x2F,0x76,0x51,0x4B,0x70,0x69,0x41,0x30,0x30,0x0A,0x2B,0x32,0x59, -+ 0x30,0x74,0x6B,0x4C,0x39,0x73,0x6A,0x37,0x64,0x33,0x57,0x4B,0x47,0x39,0x62,0x6A, -+ 0x64,0x51,0x58,0x2F,0x43,0x49,0x35,0x57,0x46,0x42,0x42,0x64,0x77,0x57,0x73,0x74, -+ 0x4D,0x43,0x38,0x77,0x74,0x4C,0x6A,0x6A,0x45,0x59,0x79,0x43,0x58,0x46,0x32,0x31, -+ 0x30,0x39,0x7A,0x31,0x47,0x54,0x4C,0x73,0x53,0x44,0x34,0x57,0x4F,0x0A,0x45,0x50, -+ 0x6D,0x45,0x37,0x34,0x63,0x6E,0x6F,0x35,0x78,0x53,0x43,0x71,0x71,0x33,0x74,0x54, -+ 0x49,0x6D,0x38,0x50,0x78,0x49,0x77,0x54,0x46,0x6D,0x46,0x6F,0x6D,0x6A,0x76,0x31, -+ 0x4F,0x56,0x50,0x32,0x73,0x42,0x49,0x70,0x35,0x4E,0x2B,0x59,0x6F,0x56,0x61,0x53, -+ 0x58,0x6A,0x47,0x66,0x4E,0x63,0x54,0x36,0x4E,0x6B,0x39,0x76,0x6B,0x56,0x0A,0x57, -+ 0x69,0x67,0x39,0x30,0x71,0x50,0x4E,0x4C,0x58,0x6E,0x39,0x39,0x50,0x78,0x48,0x61, -+ 0x49,0x31,0x36,0x52,0x7A,0x78,0x48,0x4C,0x39,0x54,0x42,0x2B,0x50,0x43,0x33,0x68, -+ 0x33,0x61,0x58,0x33,0x71,0x57,0x30,0x4B,0x4C,0x4A,0x41,0x66,0x6F,0x35,0x70,0x48, -+ 0x6C,0x39,0x79,0x75,0x55,0x70,0x37,0x66,0x46,0x65,0x6A,0x4A,0x2B,0x41,0x58,0x0A, -+ 0x51,0x4F,0x4A,0x62,0x53,0x45,0x67,0x56,0x74,0x76,0x72,0x68,0x44,0x39,0x73,0x55, -+ 0x6D,0x4B,0x30,0x74,0x36,0x63,0x51,0x44,0x65,0x32,0x32,0x4E,0x4E,0x6E,0x77,0x37, -+ 0x43,0x4F,0x4F,0x61,0x59,0x49,0x57,0x55,0x55,0x6A,0x79,0x6A,0x68,0x35,0x50,0x4B, -+ 0x64,0x64,0x45,0x4B,0x5A,0x38,0x68,0x62,0x62,0x47,0x65,0x61,0x5A,0x4A,0x6F,0x76, -+ 0x0A,0x63,0x6F,0x51,0x64,0x55,0x56,0x51,0x6D,0x71,0x44,0x53,0x2B,0x6B,0x63,0x2F, -+ 0x41,0x51,0x6C,0x65,0x55,0x36,0x68,0x51,0x6A,0x63,0x55,0x4C,0x57,0x44,0x6B,0x4E, -+ 0x2F,0x6F,0x4F,0x6C,0x33,0x43,0x53,0x65,0x70,0x67,0x54,0x37,0x6B,0x67,0x73,0x52, -+ 0x63,0x63,0x47,0x74,0x66,0x4B,0x65,0x37,0x77,0x4D,0x70,0x35,0x66,0x59,0x4A,0x2B, -+ 0x41,0x0A,0x43,0x46,0x44,0x41,0x6F,0x4C,0x6E,0x58,0x4E,0x6A,0x4E,0x56,0x6C,0x65, -+ 0x73,0x43,0x6B,0x78,0x74,0x6A,0x62,0x4C,0x62,0x49,0x72,0x66,0x32,0x6E,0x43,0x62, -+ 0x32,0x61,0x4D,0x65,0x64,0x31,0x5A,0x48,0x4E,0x4A,0x51,0x75,0x6F,0x4E,0x58,0x67, -+ 0x72,0x43,0x41,0x44,0x31,0x71,0x2B,0x58,0x6E,0x66,0x77,0x63,0x69,0x6D,0x57,0x50, -+ 0x64,0x51,0x0A,0x44,0x59,0x6A,0x6D,0x65,0x44,0x70,0x35,0x77,0x36,0x41,0x4A,0x33, -+ 0x2F,0x35,0x59,0x39,0x55,0x74,0x78,0x47,0x34,0x72,0x51,0x72,0x61,0x68,0x78,0x53, -+ 0x42,0x77,0x43,0x4B,0x57,0x39,0x4B,0x79,0x53,0x31,0x71,0x53,0x76,0x73,0x37,0x7A, -+ 0x59,0x2F,0x52,0x59,0x37,0x4A,0x66,0x36,0x63,0x56,0x6B,0x54,0x43,0x78,0x69,0x33, -+ 0x7A,0x32,0x53,0x0A,0x50,0x46,0x33,0x51,0x64,0x6B,0x30,0x50,0x44,0x2F,0x73,0x2B, -+ 0x6B,0x77,0x39,0x71,0x4F,0x4E,0x79,0x69,0x33,0x67,0x6E,0x61,0x42,0x46,0x6E,0x54, -+ 0x77,0x48,0x7A,0x59,0x69,0x77,0x34,0x2F,0x77,0x6A,0x46,0x33,0x64,0x47,0x68,0x47, -+ 0x4E,0x6B,0x78,0x36,0x70,0x63,0x4E,0x4F,0x52,0x55,0x46,0x4E,0x65,0x4F,0x7A,0x59, -+ 0x76,0x39,0x6F,0x6A,0x0A,0x51,0x59,0x70,0x73,0x55,0x31,0x33,0x6A,0x6D,0x30,0x33, -+ 0x42,0x6F,0x45,0x2B,0x42,0x31,0x64,0x38,0x50,0x47,0x75,0x57,0x2B,0x49,0x7A,0x2F, -+ 0x41,0x4F,0x44,0x7A,0x6B,0x6F,0x56,0x6B,0x39,0x2B,0x57,0x79,0x49,0x33,0x37,0x50, -+ 0x30,0x53,0x7A,0x47,0x4B,0x72,0x2B,0x53,0x33,0x72,0x72,0x74,0x61,0x50,0x6C,0x41, -+ 0x70,0x71,0x4B,0x48,0x55,0x0A,0x6E,0x64,0x35,0x6C,0x30,0x63,0x76,0x75,0x59,0x66, -+ 0x31,0x4C,0x37,0x45,0x52,0x75,0x49,0x58,0x64,0x47,0x4C,0x6A,0x30,0x43,0x41,0x77, -+ 0x45,0x41,0x41,0x51,0x3D,0x3D,0x0A,0x2D,0x2D,0x2D,0x2D,0x2D,0x45,0x4E,0x44,0x20, -+ 0x50,0x55,0x42,0x4C,0x49,0x43,0x20,0x4B,0x45,0x59,0x2D,0x2D,0x2D,0x2D,0x2D,0x0A, -+ }; ---- /dev/null -+++ b/net/rsa/rmd160.c -@@ -0,0 +1,292 @@ -+/********************************************************************\ -+ * -+ * FILE: rmd160.c -+ * -+ * CONTENTS: A sample C-implementation of the RIPEMD-160 -+ * hash-function. -+ * TARGET: any computer with an ANSI C compiler -+ * -+ * AUTHOR: Antoon Bosselaers, ESAT-COSIC -+ * DATE: 1 March 1996 -+ * VERSION: 1.0 -+ * -+ * Copyright (c) Katholieke Universiteit Leuven -+ * 1996, All Rights Reserved -+ * -+ * Conditions for use of the RIPEMD-160 Software -+ * -+ * The RIPEMD-160 software is freely available for use under the terms and -+ * conditions described hereunder, which shall be deemed to be accepted by -+ * any user of the software and applicable on any use of the software: -+ * -+ * 1. K.U.Leuven Department of Electrical Engineering-ESAT/COSIC shall for -+ * all purposes be considered the owner of the RIPEMD-160 software and of -+ * all copyright, trade secret, patent or other intellectual property -+ * rights therein. -+ * 2. The RIPEMD-160 software is provided on an "as is" basis without -+ * warranty of any sort, express or implied. K.U.Leuven makes no -+ * representation that the use of the software will not infringe any -+ * patent or proprietary right of third parties. User will indemnify -+ * K.U.Leuven and hold K.U.Leuven harmless from any claims or liabilities -+ * which may arise as a result of its use of the software. In no -+ * circumstances K.U.Leuven R&D will be held liable for any deficiency, -+ * fault or other mishappening with regard to the use or performance of -+ * the software. -+ * 3. User agrees to give due credit to K.U.Leuven in scientific publications -+ * or communications in relation with the use of the RIPEMD-160 software -+ * as follows: RIPEMD-160 software written by Antoon Bosselaers, -+ * available at http://www.esat.kuleuven.be/~cosicart/ps/AB-9601/. -+ * -+\********************************************************************/ -+ -+/* header files */ -+#include -+#include "rmd160.h" -+ -+/********************************************************************/ -+ -+void MDinit(dword *MDbuf) -+{ -+ MDbuf[0] = 0x67452301UL; -+ MDbuf[1] = 0xefcdab89UL; -+ MDbuf[2] = 0x98badcfeUL; -+ MDbuf[3] = 0x10325476UL; -+ MDbuf[4] = 0xc3d2e1f0UL; -+ -+ return; -+} -+ -+/********************************************************************/ -+ -+void compress(dword *MDbuf, dword *X) -+{ -+ dword aa = MDbuf[0], bb = MDbuf[1], cc = MDbuf[2], -+ dd = MDbuf[3], ee = MDbuf[4]; -+ dword aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2], -+ ddd = MDbuf[3], eee = MDbuf[4]; -+ -+ /* round 1 */ -+ FF(aa, bb, cc, dd, ee, X[ 0], 11); -+ FF(ee, aa, bb, cc, dd, X[ 1], 14); -+ FF(dd, ee, aa, bb, cc, X[ 2], 15); -+ FF(cc, dd, ee, aa, bb, X[ 3], 12); -+ FF(bb, cc, dd, ee, aa, X[ 4], 5); -+ FF(aa, bb, cc, dd, ee, X[ 5], 8); -+ FF(ee, aa, bb, cc, dd, X[ 6], 7); -+ FF(dd, ee, aa, bb, cc, X[ 7], 9); -+ FF(cc, dd, ee, aa, bb, X[ 8], 11); -+ FF(bb, cc, dd, ee, aa, X[ 9], 13); -+ FF(aa, bb, cc, dd, ee, X[10], 14); -+ FF(ee, aa, bb, cc, dd, X[11], 15); -+ FF(dd, ee, aa, bb, cc, X[12], 6); -+ FF(cc, dd, ee, aa, bb, X[13], 7); -+ FF(bb, cc, dd, ee, aa, X[14], 9); -+ FF(aa, bb, cc, dd, ee, X[15], 8); -+ -+ /* round 2 */ -+ GG(ee, aa, bb, cc, dd, X[ 7], 7); -+ GG(dd, ee, aa, bb, cc, X[ 4], 6); -+ GG(cc, dd, ee, aa, bb, X[13], 8); -+ GG(bb, cc, dd, ee, aa, X[ 1], 13); -+ GG(aa, bb, cc, dd, ee, X[10], 11); -+ GG(ee, aa, bb, cc, dd, X[ 6], 9); -+ GG(dd, ee, aa, bb, cc, X[15], 7); -+ GG(cc, dd, ee, aa, bb, X[ 3], 15); -+ GG(bb, cc, dd, ee, aa, X[12], 7); -+ GG(aa, bb, cc, dd, ee, X[ 0], 12); -+ GG(ee, aa, bb, cc, dd, X[ 9], 15); -+ GG(dd, ee, aa, bb, cc, X[ 5], 9); -+ GG(cc, dd, ee, aa, bb, X[ 2], 11); -+ GG(bb, cc, dd, ee, aa, X[14], 7); -+ GG(aa, bb, cc, dd, ee, X[11], 13); -+ GG(ee, aa, bb, cc, dd, X[ 8], 12); -+ -+ /* round 3 */ -+ HH(dd, ee, aa, bb, cc, X[ 3], 11); -+ HH(cc, dd, ee, aa, bb, X[10], 13); -+ HH(bb, cc, dd, ee, aa, X[14], 6); -+ HH(aa, bb, cc, dd, ee, X[ 4], 7); -+ HH(ee, aa, bb, cc, dd, X[ 9], 14); -+ HH(dd, ee, aa, bb, cc, X[15], 9); -+ HH(cc, dd, ee, aa, bb, X[ 8], 13); -+ HH(bb, cc, dd, ee, aa, X[ 1], 15); -+ HH(aa, bb, cc, dd, ee, X[ 2], 14); -+ HH(ee, aa, bb, cc, dd, X[ 7], 8); -+ HH(dd, ee, aa, bb, cc, X[ 0], 13); -+ HH(cc, dd, ee, aa, bb, X[ 6], 6); -+ HH(bb, cc, dd, ee, aa, X[13], 5); -+ HH(aa, bb, cc, dd, ee, X[11], 12); -+ HH(ee, aa, bb, cc, dd, X[ 5], 7); -+ HH(dd, ee, aa, bb, cc, X[12], 5); -+ -+ /* round 4 */ -+ II(cc, dd, ee, aa, bb, X[ 1], 11); -+ II(bb, cc, dd, ee, aa, X[ 9], 12); -+ II(aa, bb, cc, dd, ee, X[11], 14); -+ II(ee, aa, bb, cc, dd, X[10], 15); -+ II(dd, ee, aa, bb, cc, X[ 0], 14); -+ II(cc, dd, ee, aa, bb, X[ 8], 15); -+ II(bb, cc, dd, ee, aa, X[12], 9); -+ II(aa, bb, cc, dd, ee, X[ 4], 8); -+ II(ee, aa, bb, cc, dd, X[13], 9); -+ II(dd, ee, aa, bb, cc, X[ 3], 14); -+ II(cc, dd, ee, aa, bb, X[ 7], 5); -+ II(bb, cc, dd, ee, aa, X[15], 6); -+ II(aa, bb, cc, dd, ee, X[14], 8); -+ II(ee, aa, bb, cc, dd, X[ 5], 6); -+ II(dd, ee, aa, bb, cc, X[ 6], 5); -+ II(cc, dd, ee, aa, bb, X[ 2], 12); -+ -+ /* round 5 */ -+ JJ(bb, cc, dd, ee, aa, X[ 4], 9); -+ JJ(aa, bb, cc, dd, ee, X[ 0], 15); -+ JJ(ee, aa, bb, cc, dd, X[ 5], 5); -+ JJ(dd, ee, aa, bb, cc, X[ 9], 11); -+ JJ(cc, dd, ee, aa, bb, X[ 7], 6); -+ JJ(bb, cc, dd, ee, aa, X[12], 8); -+ JJ(aa, bb, cc, dd, ee, X[ 2], 13); -+ JJ(ee, aa, bb, cc, dd, X[10], 12); -+ JJ(dd, ee, aa, bb, cc, X[14], 5); -+ JJ(cc, dd, ee, aa, bb, X[ 1], 12); -+ JJ(bb, cc, dd, ee, aa, X[ 3], 13); -+ JJ(aa, bb, cc, dd, ee, X[ 8], 14); -+ JJ(ee, aa, bb, cc, dd, X[11], 11); -+ JJ(dd, ee, aa, bb, cc, X[ 6], 8); -+ JJ(cc, dd, ee, aa, bb, X[15], 5); -+ JJ(bb, cc, dd, ee, aa, X[13], 6); -+ -+ /* parallel round 1 */ -+ JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); -+ JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); -+ JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); -+ JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); -+ JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); -+ JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); -+ JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); -+ JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); -+ JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); -+ JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); -+ JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); -+ JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); -+ JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); -+ JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); -+ JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); -+ JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); -+ -+ /* parallel round 2 */ -+ III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); -+ III(ddd, eee, aaa, bbb, ccc, X[11], 13); -+ III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); -+ III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); -+ III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); -+ III(eee, aaa, bbb, ccc, ddd, X[13], 8); -+ III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); -+ III(ccc, ddd, eee, aaa, bbb, X[10], 11); -+ III(bbb, ccc, ddd, eee, aaa, X[14], 7); -+ III(aaa, bbb, ccc, ddd, eee, X[15], 7); -+ III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); -+ III(ddd, eee, aaa, bbb, ccc, X[12], 7); -+ III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); -+ III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); -+ III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); -+ III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); -+ -+ /* parallel round 3 */ -+ HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); -+ HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); -+ HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); -+ HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); -+ HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); -+ HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); -+ HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); -+ HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); -+ HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); -+ HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); -+ HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); -+ HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); -+ HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); -+ HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); -+ HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); -+ HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); -+ -+ /* parallel round 4 */ -+ GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); -+ GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); -+ GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); -+ GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); -+ GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); -+ GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); -+ GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); -+ GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); -+ GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); -+ GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); -+ GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); -+ GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); -+ GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); -+ GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); -+ GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); -+ GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); -+ -+ /* parallel round 5 */ -+ FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); -+ FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); -+ FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); -+ FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); -+ FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); -+ FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); -+ FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); -+ FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); -+ FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); -+ FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); -+ FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); -+ FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); -+ FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); -+ FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); -+ FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); -+ FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); -+ -+ /* combine results */ -+ ddd += cc + MDbuf[1]; /* final result for MDbuf[0] */ -+ MDbuf[1] = MDbuf[2] + dd + eee; -+ MDbuf[2] = MDbuf[3] + ee + aaa; -+ MDbuf[3] = MDbuf[4] + aa + bbb; -+ MDbuf[4] = MDbuf[0] + bb + ccc; -+ MDbuf[0] = ddd; -+ -+ return; -+} -+ -+/********************************************************************/ -+ -+void MDfinish(dword *MDbuf, byte *strptr, dword lswlen, dword mswlen) -+{ -+ unsigned int i; /* counter */ -+ dword X[16]; /* message words */ -+ -+ memset(X, 0, 16*sizeof(dword)); -+ -+ /* put bytes from strptr into X */ -+ for (i=0; i<(lswlen&63); i++) { -+ /* byte i goes into word X[i div 4] at pos. 8*(i mod 4) */ -+ X[i>>2] ^= (dword) *strptr++ << (8 * (i&3)); -+ } -+ -+ /* append the bit m_n == 1 */ -+ X[(lswlen>>2)&15] ^= (dword)1 << (8*(lswlen&3) + 7); -+ -+ if ((lswlen & 63) > 55) { -+ /* length goes to next block */ -+ compress(MDbuf, X); -+ memset(X, 0, 16*sizeof(dword)); -+ } -+ -+ /* append length in bits*/ -+ X[14] = lswlen << 3; -+ X[15] = (lswlen >> 29) | (mswlen << 3); -+ compress(MDbuf, X); -+ -+ return; -+} -+ -+/************************ end of file rmd160.c **********************/ -+ ---- /dev/null -+++ b/net/rsa/rmd160.h -@@ -0,0 +1,154 @@ -+/********************************************************************\ -+ * -+ * FILE: rmd160.h -+ * -+ * CONTENTS: Header file for a sample C-implementation of the -+ * RIPEMD-160 hash-function. -+ * TARGET: any computer with an ANSI C compiler -+ * -+ * AUTHOR: Antoon Bosselaers, ESAT-COSIC -+ * DATE: 1 March 1996 -+ * VERSION: 1.0 -+ * -+ * Copyright (c) Katholieke Universiteit Leuven -+ * 1996, All Rights Reserved -+ * -+ * Conditions for use of the RIPEMD-160 Software -+ * -+ * The RIPEMD-160 software is freely available for use under the terms and -+ * conditions described hereunder, which shall be deemed to be accepted by -+ * any user of the software and applicable on any use of the software: -+ * -+ * 1. K.U.Leuven Department of Electrical Engineering-ESAT/COSIC shall for -+ * all purposes be considered the owner of the RIPEMD-160 software and of -+ * all copyright, trade secret, patent or other intellectual property -+ * rights therein. -+ * 2. The RIPEMD-160 software is provided on an "as is" basis without -+ * warranty of any sort, express or implied. K.U.Leuven makes no -+ * representation that the use of the software will not infringe any -+ * patent or proprietary right of third parties. User will indemnify -+ * K.U.Leuven and hold K.U.Leuven harmless from any claims or liabilities -+ * which may arise as a result of its use of the software. In no -+ * circumstances K.U.Leuven R&D will be held liable for any deficiency, -+ * fault or other mishappening with regard to the use or performance of -+ * the software. -+ * 3. User agrees to give due credit to K.U.Leuven in scientific publications -+ * or communications in relation with the use of the RIPEMD-160 software -+ * as follows: RIPEMD-160 software written by Antoon Bosselaers, -+ * available at http://www.esat.kuleuven.be/~cosicart/ps/AB-9601/. -+ * -+\********************************************************************/ -+ -+#ifndef RMD160H /* make sure this file is read only once */ -+#define RMD160H -+ -+/********************************************************************/ -+ -+/* typedef 8 and 32 bit types, resp. */ -+/* adapt these, if necessary, -+ for your operating system and compiler */ -+typedef unsigned char byte; -+typedef unsigned long dword; -+ -+ -+/********************************************************************/ -+ -+/* macro definitions */ -+ -+/* collect four bytes into one word: */ -+#define BYTES_TO_DWORD(strptr) \ -+ (((dword) *((strptr)+3) << 24) | \ -+ ((dword) *((strptr)+2) << 16) | \ -+ ((dword) *((strptr)+1) << 8) | \ -+ ((dword) *(strptr))) -+ -+/* ROL(x, n) cyclically rotates x over n bits to the left */ -+/* x must be of an unsigned 32 bits type and 0 <= n < 32. */ -+#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n)))) -+ -+/* the five basic functions F(), G() and H() */ -+#define F(x, y, z) ((x) ^ (y) ^ (z)) -+#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) -+#define H(x, y, z) (((x) | ~(y)) ^ (z)) -+#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) -+#define J(x, y, z) ((x) ^ ((y) | ~(z))) -+ -+/* the ten basic operations FF() through III() */ -+#define FF(a, b, c, d, e, x, s) {\ -+ (a) += F((b), (c), (d)) + (x);\ -+ (a) = ROL((a), (s)) + (e);\ -+ (c) = ROL((c), 10);\ -+ } -+#define GG(a, b, c, d, e, x, s) {\ -+ (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ -+ (a) = ROL((a), (s)) + (e);\ -+ (c) = ROL((c), 10);\ -+ } -+#define HH(a, b, c, d, e, x, s) {\ -+ (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ -+ (a) = ROL((a), (s)) + (e);\ -+ (c) = ROL((c), 10);\ -+ } -+#define II(a, b, c, d, e, x, s) {\ -+ (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ -+ (a) = ROL((a), (s)) + (e);\ -+ (c) = ROL((c), 10);\ -+ } -+#define JJ(a, b, c, d, e, x, s) {\ -+ (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ -+ (a) = ROL((a), (s)) + (e);\ -+ (c) = ROL((c), 10);\ -+ } -+#define FFF(a, b, c, d, e, x, s) {\ -+ (a) += F((b), (c), (d)) + (x);\ -+ (a) = ROL((a), (s)) + (e);\ -+ (c) = ROL((c), 10);\ -+ } -+#define GGG(a, b, c, d, e, x, s) {\ -+ (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ -+ (a) = ROL((a), (s)) + (e);\ -+ (c) = ROL((c), 10);\ -+ } -+#define HHH(a, b, c, d, e, x, s) {\ -+ (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ -+ (a) = ROL((a), (s)) + (e);\ -+ (c) = ROL((c), 10);\ -+ } -+#define III(a, b, c, d, e, x, s) {\ -+ (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ -+ (a) = ROL((a), (s)) + (e);\ -+ (c) = ROL((c), 10);\ -+ } -+#define JJJ(a, b, c, d, e, x, s) {\ -+ (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ -+ (a) = ROL((a), (s)) + (e);\ -+ (c) = ROL((c), 10);\ -+ } -+ -+/********************************************************************/ -+ -+/* function prototypes */ -+ -+void MDinit(dword *MDbuf); -+/* -+ * initializes MDbuffer to "magic constants" -+ */ -+ -+void compress(dword *MDbuf, dword *X); -+/* -+ * the compression function. -+ * transforms MDbuf using message bytes X[0] through X[15] -+ */ -+ -+void MDfinish(dword *MDbuf, byte *strptr, dword lswlen, dword mswlen); -+/* -+ * puts bytes from strptr into X and pad out; appends length -+ * and finally, compresses the last block(s) -+ * note: length in bits == 8 * (lswlen + 2^32 mswlen). -+ * note: there are (lswlen mod 64) bytes left in strptr. -+ */ -+ -+#endif /* RMD160H */ -+ -+/*********************** end of file rmd160.h ***********************/ -+ ---- /dev/null -+++ b/net/rsa/rsa.c -@@ -0,0 +1,303 @@ -+/* -+ * FONSM RSA handling library -+ * -+ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. -+ * -+ * This library is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU Lesser General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This library 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 Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public License -+ * along with this library; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Created: 20070306 Pablo Martin Medrano -+ * -+ * Based on axTLS -+ * -+ * $Id: fonrsa.c 405 2007-09-19 15:26:17Z jesus.pico $ -+ */ -+#include -+#include -+#include "rsa.h" -+#include "rmd160.h" -+#include "bigint.h" -+#include "base64.h" -+ -+#include "public_key.h" -+ -+#define RMDsize 160 /* A RIPEMD-160 hash has 160 bits */ -+ -+typedef struct { -+ uint8_t *buffer; -+ size_t size; -+} DER_key; -+ -+typedef struct { -+ bigint *m; /* modulus */ -+ bigint *e; /* public exponent */ -+ int num_octets; -+ BI_CTX *bi_ctx; /* big integer handle */ -+} RSA_parameters; -+ -+typedef struct { -+ DER_key *derkey; -+ RSA_parameters *rsaparms; -+} RSA; -+ -+static void CH_free_der_key(DER_key *key) -+{ -+ free(key->buffer); -+ free(key); -+} -+ -+int CH_decrypt(RSA_parameters *rsa, uint8_t *buffer_in, uint8_t *buffer_out) -+{ -+ bigint *dat_bi; -+ bigint *decrypted_bi; -+ int byte_size; -+ -+ byte_size = rsa->num_octets; -+ dat_bi = bi_import(rsa->bi_ctx, buffer_in, byte_size); -+ rsa->bi_ctx->mod_offset = BIGINT_M_OFFSET; -+ bi_copy(rsa->m); -+ decrypted_bi = bi_mod_power(rsa->bi_ctx, dat_bi, rsa->e); -+ bi_export(rsa->bi_ctx, decrypted_bi, buffer_out, byte_size); -+ return 0; -+} -+ -+byte *RMDbinary(char *buffer, int len) -+{ -+ byte data[1024]; /* contains current mess. block */ -+ dword nbytes; /* length of this block */ -+ dword MDbuf[RMDsize / 32]; /* contains (A, B, C, D(, E)) */ -+ static byte hashcode[RMDsize / 8]; /* for final hash-value */ -+ dword X[16]; /* current 16-word chunk */ -+ unsigned int i, j; /* counters */ -+ dword length[2]; /* length in bytes of message */ -+ dword offset; /* # of unprocessed bytes at */ -+ /* call of MDfinish */ -+ int total = len; -+ char *tmp = buffer; -+ MDinit(MDbuf); -+ length[0] = 0; -+ length[1] = 0; -+ while ( len) { -+ memcpy(data, tmp, 1024); -+ if(len > 1024) -+ { -+ nbytes = 1024; -+ len -= 1024; -+ tmp += 1024; -+ } else { -+ nbytes = len; -+ len = 0; -+ } -+ /* process all complete blocks */ -+ for (i = 0; i < (nbytes >> 6); i++) { -+ for (j = 0; j < 16; j++) -+ X[j] = BYTES_TO_DWORD(data + 64 * i + 4 * j); -+ compress(MDbuf, X); -+ } -+ /* update length[] */ -+ if (length[0] + nbytes < length[0]) -+ length[1]++; /* overflow to msb of length */ -+ length[0] += nbytes; -+ } -+ /* finish: */ -+ offset = length[0] & 0x3C0; /* extract bytes 6 to 10 inclusive */ -+ MDfinish(MDbuf, data + offset, length[0], length[1]); -+ -+ for (i = 0; i < RMDsize / 8; i += 4) { -+ hashcode[i] = MDbuf[i >> 2]; -+ hashcode[i + 1] = (MDbuf[i >> 2] >> 8); -+ hashcode[i + 2] = (MDbuf[i >> 2] >> 16); -+ hashcode[i + 3] = (MDbuf[i >> 2] >> 24); -+ } -+ -+ return (byte *) hashcode; -+} -+ -+static DER_key *CH_load_pem_key(void) -+{ -+ DER_key *ret; -+ uint8_t *buffer; -+ char *b64,*p,*t; -+ char key[1024]; -+ size_t filesize; -+ int size; -+ -+ if ((ret = (DER_key *)malloc(sizeof(DER_key))) == NULL) -+ return NULL; -+ buffer = public_key; -+ p = (char *)buffer; -+ while ((*p != '\n') && (*p != '\0')) -+ p++; -+ if (*p == '\0') { -+ free(ret); -+ return NULL; -+ } -+ p++; -+ b64 = t = p; -+ while((p - b64) <= filesize) { -+ if ((*p == '-')) { -+ break; -+ } else if ((*p != '\n') && (*p != ' ') && (*p != '\t')) { -+ *t = *p; -+ t++; -+ } -+ p++; -+ } -+ *t = '\0'; -+ size = B64_decode(b64, key, strlen(b64), 1024); -+ if (size < 0) { -+ free(buffer); -+ free(ret); -+ return NULL; -+ } -+ //free(buffer); -+ ret->buffer = (char *)malloc(size); -+ ret->size = size; -+ memcpy((void *)ret->buffer, (void *)key, size); -+ return ret; -+} -+ -+/* -+ * Similar to RSA_pub_key_new, rewritten to make this program depend only on bi module -+ */ -+void CH_pub_key_new(RSA_parameters **rsa, const uint8_t *modulus, int mod_len, const uint8_t *pub_exp, int pub_len) -+{ -+ RSA_parameters *rsa_parameters; -+ -+ BI_CTX *bi_ctx = bi_initialize(); -+ *rsa = (RSA_parameters *)calloc(1, sizeof(RSA_parameters)); -+ rsa_parameters = *rsa; -+ rsa_parameters->bi_ctx = bi_ctx; -+ rsa_parameters->num_octets = (mod_len & 0xFFF0); -+ rsa_parameters->m = bi_import(bi_ctx, modulus, mod_len); -+ bi_set_mod(bi_ctx, rsa_parameters->m, BIGINT_M_OFFSET); -+ rsa_parameters->e = bi_import(bi_ctx, pub_exp, pub_len); -+ bi_permanent(rsa_parameters->e); -+} -+ -+/* -+ * Get the public key specifics from an ASN.1 encoded file -+ * A function lacking in the exported axTLS API -+ * -+ * This is a really weird hack that only works with RSA public key -+ * files -+ */ -+static int asn1_get_public_key(const uint8_t *buf, int len, RSA_parameters **rsa_parameters) -+{ -+ uint8_t *modulus, *pub_exp; -+ int mod_len, pub_len; -+ -+ pub_len = 3; -+ mod_len = len - 37; -+ if (buf[0] != 0x30) { -+ return -1; -+ } -+ -+ pub_exp = (uint8_t *)malloc(3); -+ modulus = (uint8_t *)malloc(mod_len); -+ memcpy(modulus, buf + 32 , mod_len); -+ memcpy(pub_exp, buf + 34 + mod_len, 3); -+ if (mod_len <= 0 || pub_len <= 0 ) -+ return -1; -+ CH_pub_key_new(rsa_parameters, modulus, mod_len, pub_exp, pub_len); -+ -+ free(modulus); -+ free(pub_exp); -+ return 0; -+} -+ -+ -+/* FR_init */ -+void *FR_init(void) -+{ -+ DER_key *derkey; -+ RSA_parameters *rsa_parameters; -+ -+ derkey = CH_load_pem_key(); -+ if ((asn1_get_public_key(derkey->buffer, derkey->size, &rsa_parameters)) != 0) { -+ fprintf(stderr, "Error: Extracting public key from file\n"); -+ return 0; -+ } -+ CH_free_der_key(derkey); -+ return (void *)rsa_parameters; -+} -+ -+FONRSA_ERROR FR_end(void *handle) -+{ -+ RSA_parameters *rsa_parameters = (RSA_parameters *)handle; -+ -+ free(rsa_parameters); -+ return FONRSA_OK; -+} -+ -+/* -+ * -+ * Implementation of PKCS 1.5 padding, borrowed from -+ * Tom's code (public domain) -+ */ -+ -+/* Standalone FR_verify_file */ -+FONRSA_ERROR FR_verify_file(void *handler, char *file_data, int file_len, -+ char *signature_buffer, int signature_size) -+{ -+ int j; -+ byte *hashcode; -+ byte hash[20]; -+ uint8_t *decrypted; -+ RSA_parameters *rsa_parameters = (RSA_parameters *)handler; -+ -+ /* Calculates the RIPEMD-160 hash of the file */ -+ hashcode = RMDbinary (file_data, file_len); -+ -+ if (rsa_parameters->num_octets != signature_size) -+ return FONRSA_SIZE; -+ decrypted = (uint8_t *)malloc(rsa_parameters->num_octets); -+ if (CH_decrypt(rsa_parameters, signature_buffer, decrypted)) { -+ printf("Error: Decrypting signature\n"); -+ return FONRSA_VERIFICATION_FAILURE; -+ } -+ memcpy(hash, decrypted + 492, 20); -+ //free(decrypted); -+ //free(signature_buffer); -+ for (j = 0; j < RMDsize/8; j++) { -+ if (hash[j] != hashcode[j]) -+ return FONRSA_VERIFICATION_FAILURE; -+ } -+ return FONRSA_OK; -+} -+ -+int rsa_check_signature(char *signature, int signature_len, char *buffer, int buffer_len) -+{ -+ FONRSA_ERROR fonrsa_error; -+ void *handle; -+ handle = FR_init(); -+ if (handle == NULL) { -+ printf("Error loading keys\n"); -+ return 1; -+ } -+ fonrsa_error = FR_verify_file(handle, buffer, buffer_len, signature, signature_len); -+ FR_end(handle); -+ switch (fonrsa_error) { -+ case FONRSA_OK: -+ printf("Verified OK\n"); -+ return 0; -+ case FONRSA_VERIFICATION_FAILURE: -+ printf("Verification failure\n"); -+ return 1; -+ default: -+ printf("Verification error\n"); -+ return -1; -+ } -+ -+} ---- /dev/null -+++ b/net/rsa/rsa.h -@@ -0,0 +1,46 @@ -+/* -+ * FONSM RSA handling library, used by fonsmcd and foncheckrsa -+ * -+ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. -+ * -+ * This library is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU Lesser General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This library 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 Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public License -+ * along with this library; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Created: 20070306 Pablo Martin Medrano -+ * -+ * $Id: fonrsa.h 404 2007-09-17 10:41:31Z jesus.pico $ -+ */ -+#ifndef _FONRSA_H -+#define _FONRSA_H -+ -+#define MINIMUM_PADING_BYTES_PKCS_1_5 3 -+ -+typedef enum { -+ FONRSA_OK = 0, -+ FONRSA_VERIFICATION_FAILURE = 1, -+ FONRSA_OPENKEY = 2, -+ FONRSA_SIZE = 3, -+ FONRSA_LOADFILE = 4, -+ FONRSA_CRYPT = 5, -+ FONRSA_DECRYPT = 6, -+ FONRSA_SAVEFILE = 7, -+ FONRSA_NOSYS = 8, -+ FONRSA_VERIFY = 9 -+} FONRSA_ERROR; -+ -+int rsa_check_signature(char *signature, int signature_len, char *buffer, int buffer_len); -+ -+#endif -+ -+ ---- /dev/null -+++ b/net/rsa/sign.h -@@ -0,0 +1,27 @@ -+/* -+ * Signature interface -+ * -+ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. -+ * -+ * Created: 20070417 Pablo Martín Medrano -+ * -+ * $Id: sign.h 389 2007-06-11 08:29:56Z pablo.martin $ -+ */ -+#ifndef __SIGN_H__ -+#define __SIGN_H__ -+#ifdef __cplusplus -+ extern "C" { -+#endif -+ -+void SG_init(void); -+void *SG_start(char *private_key_path, char *public_key_path); -+void SG_stop(void *handle); -+int SG_crypt(void *data, unsigned char *text, int size_text, unsigned char *crypted_text, -+ unsigned int crypted_text_buffer_size, int *crypted_size); -+int SG_crypt_v2(void *data, unsigned char *text, int size_text, unsigned char *crypted_text, -+ unsigned int crypted_text_buffer_size, int *crypted_size); -+#ifdef __cplusplus -+} -+#endif -+#endif /* #ifdef __SIGN_H__ */ -+ ---- /dev/null -+++ b/net/rsa/sign_openssl.c -@@ -0,0 +1,437 @@ -+/* -+ * Signature using OpenSSL -+ * -+ * This file is part of FONUCS. Copyright (C) 2007 FON Wireless Ltd. -+ * -+ * Created: 20070417 Pablo Martín Medrano -+ * -+ * $Id: sign_openssl.c 346 2007-05-10 19:51:38Z pablo.martin $ -+ */ -+/* -+ * -+ * How the RSA public and private key was generated -+ * To check .FON files -+ * openssl genrsa -out private_fon_rsa_key.pem 4096 -+ * openssl rsa -in private_fon_rsa_key.pem -pubout -out public_fon_rsa_key.pem -+ * -+ * How the Status Manager public and private key was generated -+ * openssl genrsa -out private_sm_rsa_key.pem 2048 -+ * openssl rsa -in private_sm_rsa_key.pem -pubout -out public_sm_rsa_key.pem -+ * -+ * How to sign using the RSA private key (This is what fonsign does) -+ * openssl dgst -rmd160 -sign private_fon_rsa_key.pem FILE > SIGNATURE -+ * How to verify using the RSA public key (This is what fonverify + foncheckrsa does) -+ * openssl dgst -rmd160 -verify public_fon_rsa_key.pem -signature SIGNATURE FILE -+ * Convert to DER file (to use it in La Fonera) -+ * openssl rsa -inform PEM -outform DER -pubin -in public_fon_rsa_key.pem -pubout -out public_fon_rsa_key.der -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#ifndef __MAINTEST__ -+#include "log.h" -+#else -+#define fon_warning printf -+#define fon_debug printf -+#define fon_critical printf -+#endif -+#include "sign.h" -+ -+typedef struct { -+ RSA *rsa; -+ int rsa_size; -+ EVP_PKEY *pkey; -+ int pkey_size; -+ RSA *public_rsa; -+ int public_rsa_size; -+ EVP_PKEY *public_pkey; -+ int public_pkey_size; -+} Sign; -+ -+typedef enum { -+ KEY_PUBLIC = 0, -+ KEY_PRIVATE -+} KEY_TYPE; -+ -+static EVP_PKEY *SG_load_key(char *key_path, KEY_TYPE type); -+static unsigned char *load_file_in_buffer(char *path, int *size); -+static int save_file_from_buffer(char *path, char *buffer, int size); -+ -+void SG_init(void) -+{ -+ SSL_load_error_strings(); -+ SSL_library_init(); -+ OpenSSL_add_all_algorithms(); -+ OpenSSL_add_all_ciphers(); -+ OpenSSL_add_all_digests(); -+} -+ -+static unsigned char *load_file_in_buffer(char *path, int *size) -+{ -+ char *buffer; -+ struct stat st; -+ int fd; -+ -+ if (stat(path, &st)) -+ return NULL; -+ buffer = (char *)malloc(st.st_size); -+ if (buffer == NULL) -+ return NULL; -+ if ((fd = open(path, O_RDONLY)) == -1) { -+ free(buffer); -+ return NULL; -+ } -+ if (read(fd,buffer,st.st_size) != (ssize_t)st.st_size) { -+ free(buffer); -+ close(fd); -+ return NULL; -+ } -+ *size = (int)st.st_size; -+ close(fd); -+ return buffer; -+} -+ -+static int save_file_from_buffer(char *path, char *buffer, int size) -+{ -+ int fd; -+ -+ if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) == -1) -+ return -1; -+ if (write(fd, buffer, (size_t)size) != ((ssize_t)size)) { -+ close(fd); -+ return -1; -+ } -+ close(fd); -+ return 0; -+} -+ -+static EVP_PKEY *SG_load_key(char *key_path, KEY_TYPE type) -+{ -+ BIO *key = NULL; -+ EVP_PKEY *pkey; -+ -+ if ((key = BIO_new(BIO_s_file())) == NULL) { -+ //ERR_print_errors(err); -+ fon_warning("%s: Error calling BIO_new()\n", __FUNCTION__); -+ return NULL; -+ } -+ if (BIO_read_filename(key, key_path) <= 0) { -+ fon_warning("%s: Error opening %s\n", __FUNCTION__, key_path); -+ // ERR_print_errors(err); -+ BIO_free(key); -+ } -+ if (type == KEY_PUBLIC) { -+ pkey = PEM_read_bio_PUBKEY(key, NULL, NULL, NULL); -+ } else if (type == KEY_PRIVATE) { -+ pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL); -+ } else { -+ return NULL; -+ } -+ -+ if (pkey == NULL) { -+ fon_warning("%s: Error reading %s\n", __FUNCTION__, key_path); -+ BIO_free(key); -+ return NULL; -+ } -+ BIO_free(key); -+ return pkey; -+} -+ -+void *SG_start(char *private_key_path, char *public_key_path) -+{ -+ Sign *sign; -+ -+ if ((sign = (Sign *)malloc(sizeof(Sign))) == NULL) -+ return NULL; -+ memset(sign, 0, sizeof(Sign)); -+ if (private_key_path != NULL) { -+ if ((sign->pkey = SG_load_key(private_key_path, KEY_PRIVATE)) == NULL) { -+ fon_warning("%s: Error loading %s", __FUNCTION__, private_key_path); -+ return NULL; -+ } -+ } -+ if (public_key_path != NULL) { -+ if ((sign->public_pkey = SG_load_key(public_key_path, KEY_PUBLIC)) == NULL) { -+ fon_warning("%s: Error loading %s", __FUNCTION__, public_key_path); -+ return NULL; -+ } -+ } -+ if (sign->pkey != NULL) { -+ sign->pkey_size = EVP_PKEY_size(sign->pkey); -+ if ((sign->rsa = EVP_PKEY_get1_RSA(sign->pkey)) == NULL) { -+ EVP_PKEY_free(sign->pkey); -+ return NULL; -+ } -+ } -+ if (sign->public_pkey != NULL) { -+ sign->public_pkey_size = EVP_PKEY_size(sign->public_pkey); -+ if ((sign->public_rsa = EVP_PKEY_get1_RSA(sign->public_pkey)) == NULL) { -+ EVP_PKEY_free(sign->pkey); -+ return NULL; -+ } -+ } -+ if (((sign->rsa == NULL) && (private_key_path != NULL)) || -+ ((sign->public_rsa == NULL) && (public_key_path != NULL))) { -+ fon_warning("%s: Error calling EVP_PKEY_get1_RSA()", __FUNCTION__); -+ return NULL; -+ } -+ if (sign->rsa != NULL) { -+ sign->rsa_size = RSA_size(sign->rsa); -+ if (RSA_check_key(sign->rsa) != 1) { -+ fon_warning("%s: RSA key failure", __FUNCTION__); -+ return NULL; -+ } -+ } -+ -+ return (void *)sign; -+} -+ -+void SG_stop(void *handle) -+{ -+ Sign *sign = (Sign *)handle; -+ -+ EVP_PKEY_free(sign->pkey); -+ EVP_PKEY_free(sign->public_pkey); -+ if (sign->rsa != NULL) -+ RSA_free(sign->rsa); -+ if (sign->public_rsa != NULL) -+ RSA_free(sign->public_rsa); -+ free(sign); -+} -+ -+int SG_verify(void *data, unsigned char *text, unsigned int size_text, -+ unsigned char *signature, unsigned int size_signature) -+{ -+ EVP_MD_CTX mdctx; -+ EVP_MD *md; -+ EVP_PKEY *pkey; -+ int ret; -+ Sign *sign = (Sign *)data; -+ -+ md = (EVP_MD *)EVP_ripemd160(); -+ if(!EVP_VerifyInit(&mdctx, md)) -+ return 4; -+ if (!EVP_VerifyUpdate(&mdctx, (const void *)text, (unsigned int)size_text)) { -+ return 5; -+ } -+ ret = EVP_VerifyFinal(&mdctx, (const char *)signature, size_signature, sign->public_pkey); -+ EVP_PKEY_free(pkey); -+ EVP_MD_CTX_cleanup(&mdctx); -+ return ret; -+} -+ -+int SG_sign(void *data, void *text, unsigned int size_text, void *signature_buffer, -+ unsigned int size_signature_buffer, unsigned int *size_signature) -+{ -+ unsigned char *digest[EVP_MAX_MD_SIZE]; -+ EVP_MD_CTX mdctx; -+ EVP_MD *md; -+ int ret; -+ Sign *sign = (Sign *)data; -+ -+ if (size_signature_buffer < sign->pkey_size) -+ return 1; -+ -+ md = (EVP_MD *)EVP_ripemd160(); -+ EVP_SignInit(&mdctx, md); -+ if (!EVP_SignUpdate(&mdctx, (const void *)text, (unsigned int)size_text)) { -+ return 2; -+ } -+ if (!EVP_SignFinal(&mdctx, (unsigned char *)signature_buffer, (unsigned int *)size_signature, sign->pkey)) { -+ return 3; -+ } -+ EVP_MD_CTX_cleanup(&mdctx); -+ -+ return 0; -+} -+ -+/* -+ * It's not advised to crypt using RAW ... unless you have crypted the buffer using AES before. -+ */ -+int SG_crypt(void *data, unsigned char *text, int size_text, -+ unsigned char *crypted_text, unsigned int crypted_text_buffer_size, -+ int *crypted_size) -+{ -+ EVP_MD_CTX mdctx; -+ EVP_MD *md; -+ int retsize; -+ Sign *sign = (Sign *)data; -+ -+ if (crypted_text_buffer_size < sign->pkey_size) { -+ fon_critical("%s: size_signature_buffer [%u] < %u", __FUNCTION__, size_text, sign->pkey_size); -+ return 1; -+ } -+ if (size_text != sign->pkey_size) { -+ fon_critical("%s: size_text [%u] != %u", __FUNCTION__, size_text, sign->pkey_size); -+ return 2; -+ } -+ /* The buffer is pre-padded with random data ... */ -+ fon_debug("%s: About to call RSA_private_encrypt(%d, %x, %x, %x, %d)", -+ __FUNCTION__, size_text, crypted_text, sign->rsa, RSA_NO_PADDING); -+ retsize = RSA_private_encrypt(size_text, text, crypted_text, sign->rsa, RSA_NO_PADDING); -+ if (retsize == -1) { -+ fon_critical("%s: Error calling RSA_private_encrypt(%d, %x, %x, %x, %d)", -+ __FUNCTION__, size_text, crypted_text, sign->rsa, RSA_NO_PADDING); -+ return 1; -+ } -+ *crypted_size = retsize; -+ return 0; -+} -+ -+/* SG_decrypt */ -+int SG_decrypt(void *data, unsigned char *cryptext, int cryptext_size, unsigned char *plaintext, -+ int plaintext_buffer_size, int *plaintext_size) -+{ -+ EVP_MD_CTX mdctx; -+ EVP_MD *md; -+ int retsize; -+ Sign *sign = (Sign *)data; -+ -+ if (plaintext_buffer_size < sign->public_pkey_size) { -+ fon_critical("%s: plaintext_buffer_size [%u] < %u", __FUNCTION__, plaintext_buffer_size, sign->public_pkey_size); -+ return 1; -+ } -+ if (cryptext_size != sign->public_pkey_size) { -+ fon_critical("%s: cryptext_size [%u] != %u", __FUNCTION__, cryptext_size, sign->public_pkey_size); -+ return 2; -+ } -+ retsize = RSA_public_decrypt(cryptext_size, cryptext, plaintext, sign->public_rsa, RSA_NO_PADDING); -+ if (retsize == -1) -+ return 1; -+ *plaintext_size = retsize; -+ return 0; -+} -+ -+#ifdef __MAINTEST__ -+int main(int argc, char **argv) -+{ -+ size_t argv0_size; -+ char *token; -+ -+ argv0_size = strlen(argv[0]); -+ if (argv0_size < 7) { -+ fprintf(stderr, "%s?", argv[0]); -+ return 1; -+ } -+ token = argv[0] + argv0_size - 7; -+ -+ SG_init(); -+ if (!strcmp(token, "fonsign")) { -+ return main_fonsign(argc, argv); -+ } else if (!strcmp(token, "foncryp")) { -+ return main_foncryp(argc, argv); -+ } -+ fprintf(stderr, "%s?", argv[0]); -+ return 1; -+} -+ -+int main_foncryp(int argc, char **argv) -+{ -+ void *handle = NULL; -+ int encrypt = 0; -+ char *filebuffer = NULL; -+ char crypted[1024]; -+ int size, crypted_size, ret; -+ -+ if (argc != 5) { -+ printf("Usage: %s encrypt|decrypt \n", argv[0]); -+ return 1; -+ } -+ if (!strcmp(argv[1], "encrypt")) { -+ printf("Encryption mode\n"); -+ encrypt = 1; -+ } else -+ printf("Decryption mode\n"); -+ if (encrypt) -+ handle = SG_start(argv[2], NULL); -+ else -+ handle = SG_start(NULL, argv[2]); -+ if (handle == NULL) { -+ printf("Error loading keys\n"); -+ return 1; -+ } -+ -+ filebuffer = load_file_in_buffer(argv[3], &size); -+ if (filebuffer == NULL) { -+ printf("Error reading %s\n", argv[3]); -+ SG_stop(handle); -+ return 1; -+ } -+ if (encrypt) -+ ret = SG_crypt(handle, filebuffer, size, crypted, 1024, &crypted_size); -+ else -+ ret = SG_decrypt(handle, filebuffer, size, crypted, 1024, &crypted_size); -+ -+ if (ret) { -+ printf("Error crypting %d bytes\n", size); -+ SG_stop(handle); -+ return 1; -+ } -+ printf("Crypted size %d\n", crypted_size); -+ if (save_file_from_buffer(argv[4], crypted, crypted_size)) { -+ printf("Error saving file\n"); -+ SG_stop(handle); -+ return 1; -+ } -+ -+ SG_stop(handle); -+ return 0; -+} -+ -+int main_fonsign(int argc, char **argv) -+{ -+ void *handle = NULL; -+ char signature_buffer[4096]; -+ char *signature; -+ unsigned int signature_size; -+ struct stat st; -+ char *filebuffer = NULL; -+ int size; -+ int ret = -1; -+ -+ if (argc != 5) { -+ fprintf(stderr, "usage: %s \n", argv[0]); -+ goto end; -+ } -+ handle = SG_start(argv[1], argv[2]); -+ if (handle == NULL) { -+ fprintf(stderr, "Error calling SG_start(%s)\n", argv[1]); -+ goto end; -+ } -+ filebuffer = load_file_in_buffer(argv[3], &size); -+ if (filebuffer == NULL) { -+ fprintf(stderr, "Error reading %s\n", argv[3]); -+ goto end; -+ } -+ if (SG_sign(handle, filebuffer, size, signature_buffer, 4096, &signature_size)) { -+ fprintf(stderr, "Error calling SG_sign()\n"); -+ goto end; -+ } -+ ret = SG_verify(handle, filebuffer, size, signature_buffer, signature_size); -+ if (ret == 0) -+ fprintf(stderr, "signature failure\n"); -+ else if (ret == 1) { -+ fprintf(stderr, "signature ok\n"); -+ ret = 0; -+ } else { -+ fprintf(stderr, "signature error\n"); -+ goto end; -+ } -+ if (save_file_from_buffer(argv[4], signature_buffer, signature_size)) { -+ fprintf(stderr, "Error writing to %s\n", argv[4]); -+ goto end; -+ } -+ ret = 0; -+end: -+ if (filebuffer != NULL) -+ free(filebuffer); -+ if (handle != NULL) -+ SG_stop(handle); -+ return ret; -+} -+#endif -+ ---- /dev/null -+++ b/net/uip-0.9/Makefile -@@ -0,0 +1,54 @@ -+# Copyright (c) 2001, 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. All advertising materials mentioning features or use of this software -+# must display the following acknowledgement: -+# This product includes software developed by Adam Dunkels. -+# 4. 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 uIP TCP/IP stack. -+# -+# $Id: Makefile,v 1.8.2.2 2003/10/04 22:54:17 adam Exp $ -+# -+ -+CC=gcc -+CFLAGS=-Wall -fpack-struct -DDUMP=0 -+ -+all: uip -+ -+uip: uip.o uip_arch.o tapdev.o httpd.o main.o fs.o uip_arp.o -+ $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ -+ -+%.o: %.c -+ $(CC) $(CFLAGS) -c $^ -o $@ -+ -+clean: -+ rm -f *.o *~ *core uip -+ -+ -+ -+ -+ -+ ---- /dev/null -+++ b/net/uip-0.9/fs.c -@@ -0,0 +1,154 @@ -+/** -+ * \addtogroup httpd -+ * @{ -+ */ -+ -+/** -+ * \file -+ * HTTP server read-only file system code. -+ * \author Adam Dunkels -+ * -+ * A simple read-only filesystem. -+ */ -+ -+/* -+ * Copyright (c) 2001, Swedish Institute of Computer Science. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. Neither the name of the Institute nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * This file is part of the lwIP TCP/IP stack. -+ * -+ * Author: Adam Dunkels -+ * -+ * $Id: fs.c,v 1.7.2.3 2003/10/07 13:22:27 adam Exp $ -+ */ -+ -+#include "uip.h" -+#include "httpd.h" -+#include "fs.h" -+#include "fsdata.h" -+ -+#include "fsdata.c" -+ -+#ifdef FS_STATISTICS -+#if FS_STATISTICS == 1 -+static u16_t count[FS_NUMFILES]; -+#endif /* FS_STATISTICS */ -+#endif /* FS_STATISTICS */ -+ -+/*-----------------------------------------------------------------------------------*/ -+static u8_t -+fs_strcmp(const char *str1, const char *str2) -+{ -+ u8_t i; -+ i = 0; -+ loop: -+ -+ if(str2[i] == 0 || -+ str1[i] == '\r' || -+ str1[i] == '\n') { -+ return 0; -+ } -+ -+ if(str1[i] != str2[i]) { -+ return 1; -+ } -+ -+ -+ ++i; -+ goto loop; -+} -+/*-----------------------------------------------------------------------------------*/ -+int -+fs_open(const char *name, struct fs_file *file) -+{ -+#ifdef FS_STATISTICS -+#if FS_STATISTICS == 1 -+ u16_t i = 0; -+#endif /* FS_STATISTICS */ -+#endif /* FS_STATISTICS */ -+ struct fsdata_file_noconst *f; -+ -+ for(f = (struct fsdata_file_noconst *)FS_ROOT; -+ f != NULL; -+ f = (struct fsdata_file_noconst *)f->next) { -+ -+ if(fs_strcmp(name, f->name) == 0) { -+ file->data = f->data; -+ file->len = f->len; -+#ifdef FS_STATISTICS -+#if FS_STATISTICS == 1 -+ ++count[i]; -+#endif /* FS_STATISTICS */ -+#endif /* FS_STATISTICS */ -+ return 1; -+ } -+#ifdef FS_STATISTICS -+#if FS_STATISTICS == 1 -+ ++i; -+#endif /* FS_STATISTICS */ -+#endif /* FS_STATISTICS */ -+ -+ } -+ return 0; -+} -+/*-----------------------------------------------------------------------------------*/ -+void -+fs_init(void) -+{ -+#ifdef FS_STATISTICS -+#if FS_STATISTICS == 1 -+ u16_t i; -+ for(i = 0; i < FS_NUMFILES; i++) { -+ count[i] = 0; -+ } -+#endif /* FS_STATISTICS */ -+#endif /* FS_STATISTICS */ -+} -+/*-----------------------------------------------------------------------------------*/ -+#ifdef FS_STATISTICS -+#if FS_STATISTICS == 1 -+u16_t fs_count -+(char *name) -+{ -+ struct fsdata_file_noconst *f; -+ u16_t i; -+ -+ i = 0; -+ for(f = (struct fsdata_file_noconst *)FS_ROOT; -+ f != NULL; -+ f = (struct fsdata_file_noconst *)f->next) { -+ -+ if(fs_strcmp(name, f->name) == 0) { -+ return count[i]; -+ } -+ ++i; -+ } -+ return 0; -+} -+#endif /* FS_STATISTICS */ -+#endif /* FS_STATISTICS */ -+/*-----------------------------------------------------------------------------------*/ ---- /dev/null -+++ b/net/uip-0.9/fs.h -@@ -0,0 +1,80 @@ -+/** -+ * \addtogroup httpd -+ * @{ -+ */ -+ -+/** -+ * \file -+ * HTTP server read-only file system header file. -+ * \author Adam Dunkels -+ */ -+ -+/* -+ * Copyright (c) 2001, Swedish Institute of Computer Science. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. Neither the name of the Institute nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * This file is part of the lwIP TCP/IP stack. -+ * -+ * Author: Adam Dunkels -+ * -+ * $Id: fs.h,v 1.6.2.3 2003/10/07 13:22:27 adam Exp $ -+ */ -+#ifndef __FS_H__ -+#define __FS_H__ -+ -+#include "uip.h" -+ -+/** -+ * An open file in the read-only file system. -+ */ -+struct fs_file { -+ char *data; /**< The actual file data. */ -+ int len; /**< The length of the file data. */ -+}; -+ -+/** -+ * Open a file in the read-only file system. -+ * -+ * \param name The name of the file. -+ * -+ * \param file The file pointer, which must be allocated by caller and -+ * will be filled in by the function. -+ */ -+int fs_open(const char *name, struct fs_file *file); -+ -+#ifdef FS_STATISTICS -+#if FS_STATISTICS == 1 -+u16_t fs_count(char *name); -+#endif /* FS_STATISTICS */ -+#endif /* FS_STATISTICS */ -+ -+/** -+ * Initialize the read-only file system. -+ */ -+void fs_init(void); -+ -+#endif /* __FS_H__ */ ---- /dev/null -+++ b/net/uip-0.9/fsdata.c -@@ -0,0 +1,199 @@ -+static const char data_flashing_html[] = { -+ /* /flashing.html */ -+ 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, -+ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, -+ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, -+ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, -+ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, -+ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, -+ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, -+ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, -+ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, -+ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, -+ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c, 0x62, -+ 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3d, -+ 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, -+ 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x20, 0x68, -+ 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x31, 0x30, 0x30, 0x25, -+ 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, -+ 0x66, 0x66, 0x66, 0x3b, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, -+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, -+ 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, 0x62, 0x30, 0x33, 0x34, -+ 0x3b, 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, -+ 0x3e, 0x3c, 0x68, 0x31, 0x3e, 0x55, 0x70, 0x67, 0x72, 0x61, -+ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, -+ 0x6d, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f, 0x68, 0x31, -+ 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, -+ 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, -+ 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; -+ -+static const char data_fail_html[] = { -+ /* /fail.html */ -+ 0x2f, 0x66, 0x61, 0x69, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, -+ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, -+ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, -+ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, -+ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, -+ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, -+ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, -+ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, -+ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, -+ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, -+ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, -+ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, -+ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, -+ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, -+ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, -+ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, -+ 0x3e, 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, -+ 0x9, 0x9, 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73, -+ 0x68, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, -+ 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9, 0x45, -+ 0x52, 0x52, 0x4f, 0x52, 0x20, 0x2d, 0x20, 0x74, 0x68, 0x65, -+ 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x79, 0x6f, 0x75, -+ 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x20, -+ 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, -+ 0x70, 0x61, 0x73, 0x73, 0x20, 0x76, 0x65, 0x72, 0x69, 0x66, -+ 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x50, -+ 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x6d, 0x61, 0x6b, 0x65, -+ 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x75, -+ 0x73, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x66, 0x66, 0x69, -+ 0x63, 0x69, 0x61, 0x6c, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, -+ 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, -+ 0x20, 0x62, 0x79, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, -+ 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, -+ 0x66, 0x6f, 0x6e, 0x6f, 0x73, 0x66, 0x65, 0x72, 0x61, 0x2e, -+ 0x6f, 0x72, 0x67, 0x2f, 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f, -+ 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, -+ 0x3e, 0xa, }; -+ -+static const char data_404_html[] = { -+ /* /404.html */ -+ 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, -+ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x34, -+ 0x30, 0x34, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, -+ 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0xd, 0xa, 0x53, -+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, -+ 0x2f, 0x30, 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, -+ 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, -+ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, -+ 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, -+ 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, -+ 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, -+ 0xd, 0xa, 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, -+ 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, -+ 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, -+ 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, -+ 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, 0x20, -+ 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, -+ 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0x3c, -+ 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x2f, -+ 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d, -+ 0x6c, 0x3e, }; -+ -+static const char data_index_html[] = { -+ /* /index.html */ -+ 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, -+ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, -+ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, -+ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, -+ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, -+ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, -+ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, -+ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, -+ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, -+ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, -+ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, -+ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, -+ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, -+ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, -+ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, -+ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, -+ 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, -+ 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, -+ 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, -+ 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, -+ 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, -+ 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, -+ 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62, -+ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, -+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, -+ 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9, -+ 0x3c, 0x68, 0x31, 0x3e, 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, -+ 0x72, 0x61, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, -+ 0x65, 0x20, 0x55, 0x49, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, -+ 0x9, 0x9, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x65, -+ 0x74, 0x68, 0x6f, 0x64, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x74, -+ 0x22, 0x20, 0x65, 0x6e, 0x63, 0x74, 0x79, 0x70, 0x65, 0x3d, -+ 0x22, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, -+ 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x64, 0x61, 0x74, 0x61, -+ 0x22, 0x3e, 0xa, 0x9, 0x9, 0x9, 0x3c, 0x69, 0x6e, 0x70, -+ 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, -+ 0x6c, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x66, 0x69, -+ 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x3e, 0xa, 0x9, 0x9, -+ 0x9, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, -+ 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x3e, -+ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e, -+ 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, -+ 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; -+ -+static const char data_flash_html[] = { -+ /* /flash.html */ -+ 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, -+ 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, -+ 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, -+ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, -+ 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, -+ 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, -+ 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, -+ 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, -+ 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, -+ 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, -+ 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, -+ 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, -+ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, -+ 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, -+ 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, -+ 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, -+ 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, -+ 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, -+ 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, -+ 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, -+ 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, -+ 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, -+ 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62, -+ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, -+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, -+ 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9, -+ 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x69, -+ 0x6e, 0x67, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9, -+ 0x54, 0x68, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, -+ 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x72, -+ 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x6c, -+ 0x61, 0x73, 0x68, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, -+ 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x70, -+ 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x2c, 0x20, 0x74, 0x68, -+ 0x65, 0x20, 0x6c, 0x65, 0x64, 0x73, 0x20, 0x77, 0x69, 0x6c, -+ 0x6c, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x6f, -+ 0x20, 0x62, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0xa, 0xa, 0x9, -+ 0x9, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, 0x61, 0x20, 0x73, -+ 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x6c, -+ 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, -+ 0x65, 0x20, 0x62, 0x6f, 0x78, 0x20, 0x77, 0x69, 0x6c, 0x6c, -+ 0x20, 0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0xa, 0x9, 0x3c, -+ 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, -+ 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; -+ -+const struct fsdata_file file_flashing_html[] = {{NULL, data_flashing_html, data_flashing_html + 15, sizeof(data_flashing_html) - 15}}; -+ -+const struct fsdata_file file_fail_html[] = {{file_flashing_html, data_fail_html, data_fail_html + 11, sizeof(data_fail_html) - 11}}; -+ -+const struct fsdata_file file_404_html[] = {{file_fail_html, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}}; -+ -+const struct fsdata_file file_index_html[] = {{file_404_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}}; -+ -+const struct fsdata_file file_flash_html[] = {{file_index_html, data_flash_html, data_flash_html + 12, sizeof(data_flash_html) - 12}}; -+ -+#define FS_ROOT file_flash_html -+ -+#define FS_NUMFILES 5 -\ No newline at end of file ---- /dev/null -+++ b/net/uip-0.9/fsdata.h -@@ -0,0 +1,64 @@ -+/* -+ * Copyright (c) 2001, Swedish Institute of Computer Science. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. Neither the name of the Institute nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * This file is part of the lwIP TCP/IP stack. -+ * -+ * Author: Adam Dunkels -+ * -+ * $Id: fsdata.h,v 1.4.2.1 2003/10/04 22:54:06 adam Exp $ -+ */ -+#ifndef __FSDATA_H__ -+#define __FSDATA_H__ -+ -+#include "uipopt.h" -+ -+struct fsdata_file { -+ const struct fsdata_file *next; -+ const char *name; -+ const char *data; -+ const int len; -+#ifdef FS_STATISTICS -+#if FS_STATISTICS == 1 -+ u16_t count; -+#endif /* FS_STATISTICS */ -+#endif /* FS_STATISTICS */ -+}; -+ -+struct fsdata_file_noconst { -+ struct fsdata_file *next; -+ char *name; -+ char *data; -+ int len; -+#ifdef FS_STATISTICS -+#if FS_STATISTICS == 1 -+ u16_t count; -+#endif /* FS_STATISTICS */ -+#endif /* FS_STATISTICS */ -+}; -+ -+#endif /* __FSDATA_H__ */ ---- /dev/null -+++ b/net/uip-0.9/httpd.c -@@ -0,0 +1,278 @@ -+#include "uip.h" -+#include "httpd.h" -+#include "fs.h" -+#include "fsdata.h" -+#include -+ -+#define HTTP_NONE 0 -+#define HTTP_FILE 1 -+#define HTTP_FIRMWARE 2 -+ -+#define PRINT(x) printf("%s", x) -+#define PRINTLN(x) printf("%s\n", x) -+ -+extern unsigned long do_http_tmp_address(void); -+ -+struct httpd_state *hs; -+ -+extern const struct fsdata_file file_index_html; -+extern const struct fsdata_file file_404_html; -+extern const struct fsdata_file file_flash_html; -+extern int httpd_upload_complete; -+extern unsigned char *httpd_upload_data; -+unsigned char *upload_data; -+extern ulong NetBootFileXferSize; -+int upload_running = 0; -+ -+#define ISO_G 0x47 -+#define ISO_E 0x45 -+#define ISO_T 0x54 -+#define ISO_P 0x50 -+#define ISO_O 0x4f -+#define ISO_S 0x53 -+#define ISO_T 0x54 -+#define ISO_slash 0x2f -+#define ISO_c 0x63 -+#define ISO_g 0x67 -+#define ISO_i 0x69 -+#define ISO_space 0x20 -+#define ISO_nl 0x0a -+#define ISO_cr 0x0d -+#define ISO_a 0x61 -+#define ISO_t 0x74 -+#define ISO_hash 0x23 -+#define ISO_period 0x2e -+ -+static char eol[3] = { 0x0d, 0x0a, 0x00 }; -+static char eol2[5] = { 0x0d, 0x0a, 0x0d, 0x0a, 0x00 }; -+static char boundary[128]; -+static int boundary_len = 0; -+ -+/* we use this so that we can do without the ctype library */ -+#define is_digit(c) ((c) >= '0' && (c) <= '9') -+static int atoi(const char *s) -+{ -+ int i=0; -+ -+ while (is_digit(*s)) -+ i = i*10 + *(s++) - '0'; -+ return i; -+} -+ -+void -+httpd_init(void) -+{ -+ fs_init(); -+ uip_listen(HTONS(80)); -+} -+ -+void -+httpd_appcall(void) -+{ -+ struct fs_file fsfile; -+ u8_t i; -+ switch(uip_conn->lport) { -+ case HTONS(80): -+ hs = (struct httpd_state *)(uip_conn->appstate); -+ if(uip_connected()) -+ { -+ hs->state = HTTP_NONE; -+ hs->count = 0; -+ return; -+ } else if(uip_poll()) -+ { -+ if(hs->count++ >= 1000) { -+ uip_abort(); -+ } -+ return; -+ } else if(uip_newdata() && hs->state == HTTP_NONE) -+ { -+ if(uip_appdata[0] == ISO_G && -+ uip_appdata[1] == ISO_E && -+ uip_appdata[2] == ISO_T && -+ uip_appdata[3] == ISO_space) -+ { -+ hs->state = HTTP_FILE; -+ } -+ if(uip_appdata[0] == ISO_P && -+ uip_appdata[1] == ISO_O && -+ uip_appdata[2] == ISO_S && -+ uip_appdata[3] == ISO_T && -+ uip_appdata[4] == ISO_space) -+ { -+ hs->state = HTTP_FIRMWARE; -+ } -+ if(hs->state == HTTP_NONE) -+ { -+ uip_abort(); -+ return; -+ } -+ if(hs->state == HTTP_FILE) -+ { -+ for(i = 4; i < 40; ++i) -+ { -+ if(uip_appdata[i] == ISO_space || -+ uip_appdata[i] == ISO_cr || -+ uip_appdata[i] == ISO_nl) -+ { -+ uip_appdata[i] = 0; -+ break; -+ } -+ } -+ -+ PRINT("request for file "); -+ PRINTLN(&uip_appdata[4]); -+ if(uip_appdata[4] == ISO_slash && -+ uip_appdata[5] == 0) -+ { -+ fs_open(file_index_html.name, &fsfile); -+ } else { -+ if(!fs_open((const char *)&uip_appdata[4], &fsfile)) -+ { -+ PRINTLN("couldn't open file"); -+ fs_open(file_index_html.name, &fsfile); -+ } -+ } -+ hs->script = 0; -+ hs->state = HTTP_FILE; -+ hs->dataptr = fsfile.data; -+ hs->count = fsfile.len; -+ } -+ if(hs->state == HTTP_FIRMWARE) -+ { -+ unsigned char *start = (unsigned char*)uip_appdata; -+ char *clen = strstr(start, "Content-Length:"); -+ int len = 0; -+ unsigned char *next, *end; -+ unsigned char *boundary_start; -+ int i; -+ uip_appdata[uip_len] = '\0'; -+ if(clen) -+ { -+ clen += sizeof("Content-Length:"); -+ next = strstr(clen, eol); -+ if(next) -+ { -+ len = atoi(clen); -+ next++; -+ printf("expecting %d bytes\n", len); -+ upload_data = httpd_upload_data = (unsigned char *)do_http_tmp_address(); -+ printf("received data will be stored at 0x%08X\n", upload_data); -+ if(!upload_data) -+ { -+ printf("failed to allocate memory\n"); -+ uip_close(); -+ return; -+ } -+ } else { -+ uip_close(); -+ return; -+ } -+ } -+ if(len < 4 * 1024) -+ { -+ uip_close(); -+ return; -+ } -+ boundary_start = strstr(next, "---"); -+ if(!boundary_start) -+ { -+ uip_close(); -+ return; -+ } -+ end = strstr(boundary_start, eol); -+ if(!eol) -+ { -+ uip_close(); -+ return; -+ } -+ boundary_len = end - boundary_start; -+ memcpy(boundary, boundary_start, boundary_len); -+ boundary[boundary_len] = 0; -+ next = strstr(boundary_start, "name=\"firmware\";"); -+ if(!next) -+ { -+ uip_close(); -+ return; -+ } -+ next = strstr(next, eol2); -+ if(!next) -+ { -+ printf("could not find start of data\n"); -+ uip_close(); -+ return; -+ } -+ next += 4; -+ hs->script = 0; -+ hs->state = HTTP_FIRMWARE; -+ hs->upload = uip_len - (next - start); -+ hs->upload_total = len - (int)(next - boundary_start); -+ hs->upload_total -= (strlen(boundary) + 6); -+ //printf("storing %d bytes at %p\n", (int)hs->upload, upload_data); -+ for(i = 0; i < hs->upload; i++) -+ upload_data[i] = next[i]; -+ upload_data += (int)hs->upload; -+ printf("%d / %d\n", (int)hs->upload, hs->upload_total); -+ uip_slen = 0; -+ return; -+ } -+ } -+ -+ if(hs->state == HTTP_FIRMWARE) -+ { -+ if(uip_newdata()) -+ { -+ int i; -+ hs->count = 0; -+ uip_appdata[uip_len] = '\0'; -+ hs->upload += uip_len; -+ //printf("storing %d bytes at %p\n", uip_len, upload_data); -+ printf("%d / %d\n", (int)hs->upload, hs->upload_total); -+ for(i = 0; i < uip_len; i++) -+ upload_data[i] = uip_appdata[i]; -+ upload_data += uip_len; -+ uip_slen = 0; -+ if(hs->upload >= hs->upload_total) -+ { -+ upload_running = 1; -+ NetBootFileXferSize = hs->upload_total; -+ fs_open(file_flash_html.name, &fsfile); -+ hs->script = 0; -+ hs->state = HTTP_FILE; -+ hs->dataptr = fsfile.data; -+ hs->count = fsfile.len; -+ } -+ } -+ } -+ if(hs->state == HTTP_FILE) -+ { -+ if(uip_acked()) -+ { -+ if(hs->count >= uip_conn->len) -+ { -+ hs->count -= uip_conn->len; -+ hs->dataptr += uip_conn->len; -+ } else { -+ hs->count = 0; -+ } -+ if(hs->count == 0) -+ { -+ if(upload_running) -+ { -+ int i; -+ httpd_upload_complete = 1; -+ // for(i = 0; i < hs->upload_total; i++) -+ // printf("%c", httpd_upload_data[i]); -+ } -+ uip_close(); -+ } -+ } -+ uip_send(hs->dataptr, hs->count); -+ } -+ break; -+ -+ default: -+ uip_abort(); -+ break; -+ } -+} ---- /dev/null -+++ b/net/uip-0.9/httpd.h -@@ -0,0 +1,83 @@ -+/** -+ * \addtogroup httpd -+ * @{ -+ */ -+ -+/** -+ * \file -+ * HTTP server header file. -+ * \author Adam Dunkels -+ */ -+ -+/* -+ * Copyright (c) 2001, 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. -+ * -+ * This file is part of the uIP TCP/IP stack. -+ * -+ * $Id: httpd.h,v 1.4.2.3 2003/10/06 22:56:44 adam Exp $ -+ * -+ */ -+ -+#ifndef __HTTPD_H__ -+#define __HTTPD_H__ -+ -+void httpd_init(void); -+void httpd_appcall(void); -+ -+/* UIP_APPCALL: the name of the application function. This function -+ must return void and take no arguments (i.e., C type "void -+ appfunc(void)"). */ -+#ifndef UIP_APPCALL -+#define UIP_APPCALL httpd_appcall -+#endif -+ -+struct httpd_state { -+ u8_t state; -+ u16_t count; -+ char *dataptr; -+ char *script; -+ unsigned int upload; -+ unsigned int upload_total; -+}; -+ -+ -+/* UIP_APPSTATE_SIZE: The size of the application-specific state -+ stored in the uip_conn structure. */ -+#ifndef UIP_APPSTATE_SIZE -+#define UIP_APPSTATE_SIZE (sizeof(struct httpd_state)) -+#endif -+ -+#define FS_STATISTICS 1 -+ -+extern struct httpd_state *hs; -+ -+ -+/* we copy the data to RAM+10MB */ -+#define TMP_DATA 0x8A100000 -+ -+#endif /* __HTTPD_H__ */ ---- /dev/null -+++ b/net/uip-0.9/main.c -@@ -0,0 +1,88 @@ -+/* -+ * Copyright (c) 2001-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. -+ * -+ * This file is part of the uIP TCP/IP stack. -+ * -+ * $Id: main.c,v 1.10.2.1 2003/10/04 22:54:17 adam Exp $ -+ * -+ */ -+ -+ -+#include "uip.h" -+#include "uip_arp.h" -+#include "tapdev.h" -+#include "httpd.h" -+ -+#define BUF ((struct uip_eth_hdr *)&uip_buf[0]) -+ -+#ifndef NULL -+#define NULL (void *)0 -+#endif /* NULL */ -+ -+/*-----------------------------------------------------------------------------------*/ -+int -+main(void) -+{ -+ u8_t i, arptimer; -+ tapdev_init(); -+ uip_init(); -+ httpd_init(); -+ arptimer = 0; -+ while(1) { -+ uip_len = tapdev_read(); -+ if(uip_len == 0) { -+ for(i = 0; i < UIP_CONNS; i++) { -+ uip_periodic(i); -+ if(uip_len > 0) { -+ uip_arp_out(); -+ tapdev_send(); -+ } -+ } -+ -+ if(++arptimer == 20) { -+ uip_arp_timer(); -+ arptimer = 0; -+ } -+ } else { -+ if(BUF->type == htons(UIP_ETHTYPE_IP)) { -+ uip_arp_ipin(); -+ uip_input(); -+ if(uip_len > 0) { -+ uip_arp_out(); -+ tapdev_send(); -+ } -+ } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) { -+ uip_arp_arpin(); -+ if(uip_len > 0) { -+ tapdev_send(); -+ } -+ } -+ } -+ } -+ return 0; -+} ---- /dev/null -+++ b/net/uip-0.9/tapdev.c -@@ -0,0 +1,192 @@ -+/* -+ * Copyright (c) 2001, Swedish Institute of Computer Science. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * -+ * 3. Neither the name of the Institute nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * Author: Adam Dunkels -+ * -+ * $Id: tapdev.c,v 1.7.2.1 2003/10/07 13:23:19 adam Exp $ -+ */ -+ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef linux -+#include -+#include -+#include -+#define DEVTAP "/dev/net/tun" -+#else /* linux */ -+#define DEVTAP "/dev/tap0" -+#endif /* linux */ -+ -+#include "uip.h" -+ -+static int fd; -+ -+static unsigned long lasttime; -+static struct timezone tz; -+ -+/*-----------------------------------------------------------------------------------*/ -+void -+tapdev_init(void) -+{ -+ char buf[1024]; -+ -+ fd = open(DEVTAP, O_RDWR); -+ if(fd == -1) { -+ perror("tapdev: tapdev_init: open"); -+ exit(1); -+ } -+ -+#ifdef linux -+ { -+ struct ifreq ifr; -+ memset(&ifr, 0, sizeof(ifr)); -+ ifr.ifr_flags = IFF_TAP|IFF_NO_PI; -+ if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) { -+ perror(buf); -+ exit(1); -+ } -+ } -+#endif /* Linux */ -+ -+ snprintf(buf, sizeof(buf), "ifconfig tap0 inet %d.%d.%d.%d", -+ UIP_DRIPADDR0, UIP_DRIPADDR1, UIP_DRIPADDR2, UIP_DRIPADDR3); -+ system(buf); -+ -+ lasttime = 0; -+} -+ -+void dump_mem(int type, int len) -+{ -+#if DUMP == 1 -+ int i; -+ for(i = 0; i < len; i++) -+ printf("%c", uip_buf[i]); -+ if(type) -+ { -+ printf("\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"); -+ printf("\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01"); -+ } else { -+ printf("\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02"); -+ printf("\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02"); -+ } -+ fflush(stdout); -+#endif -+} -+ -+/*-----------------------------------------------------------------------------------*/ -+unsigned int -+tapdev_read(void) -+{ -+ fd_set fdset; -+ struct timeval tv, now; -+ int ret; -+ -+ if(lasttime >= 500000) { -+ lasttime = 0; -+ return 0; -+ } -+ -+ tv.tv_sec = 0; -+ tv.tv_usec = 500000 - lasttime; -+ -+ -+ FD_ZERO(&fdset); -+ FD_SET(fd, &fdset); -+ -+ gettimeofday(&now, &tz); -+ ret = select(fd + 1, &fdset, NULL, NULL, &tv); -+ if(ret == 0) { -+ lasttime = 0; -+ return 0; -+ } -+ ret = read(fd, uip_buf, UIP_BUFSIZE); -+ if(ret == -1) { -+ perror("tap_dev: tapdev_read: read"); -+ } -+ gettimeofday(&tv, &tz); -+ lasttime += (tv.tv_sec - now.tv_sec) * 1000000 + (tv.tv_usec - now.tv_usec); -+ dump_mem(0, ret); -+ return ret; -+} -+/*-----------------------------------------------------------------------------------*/ -+void -+tapdev_send(void) -+{ -+ int ret; -+ struct iovec iov[2]; -+ -+#ifdef linux -+ { -+ char tmpbuf[UIP_BUFSIZE]; -+ int i; -+ -+ for(i = 0; i < 40 + UIP_LLH_LEN; i++) { -+ tmpbuf[i] = uip_buf[i]; -+ } -+ -+ for(; i < uip_len; i++) { -+ tmpbuf[i] = uip_appdata[i - 40 - UIP_LLH_LEN]; -+ } -+ -+ ret = write(fd, tmpbuf, uip_len); -+ } -+#else -+ -+ if(uip_len < 40 + UIP_LLH_LEN) { -+ ret = write(fd, uip_buf, uip_len + UIP_LLH_LEN); -+ } else { -+ iov[0].iov_base = uip_buf; -+ iov[0].iov_len = 40 + UIP_LLH_LEN; -+ iov[1].iov_base = (char *)uip_appdata; -+ iov[1].iov_len = uip_len - (40 + UIP_LLH_LEN); -+ -+ ret = writev(fd, iov, 2); -+ } -+#endif -+ dump_mem(1, ret); -+ -+ if(ret == -1) { -+ perror("tap_dev: tapdev_send: writev"); -+ exit(1); -+ } -+} -+/*-----------------------------------------------------------------------------------*/ ---- /dev/null -+++ b/net/uip-0.9/tapdev.h -@@ -0,0 +1,42 @@ -+/* -+ * Copyright (c) 2001, 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. -+ * -+ * This file is part of the uIP TCP/IP stack. -+ * -+ * $Id: tapdev.h,v 1.1.2.1 2003/10/04 22:54:17 adam Exp $ -+ * -+ */ -+ -+#ifndef __TAPDEV_H__ -+#define __TAPDEV_H__ -+ -+void tapdev_init(void); -+unsigned int tapdev_read(void); -+void tapdev_send(void); -+ -+#endif /* __TAPDEV_H__ */ ---- /dev/null -+++ b/net/uip-0.9/uip.c -@@ -0,0 +1,1503 @@ -+/** -+ * \addtogroup uip -+ * @{ -+ */ -+ -+/** -+ * \file -+ * The uIP TCP/IP stack code. -+ * \author Adam Dunkels -+ */ -+ -+/* -+ * Copyright (c) 2001-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. -+ * -+ * This file is part of the uIP TCP/IP stack. -+ * -+ * $Id: uip.c,v 1.62.2.10 2003/10/07 13:23:01 adam Exp $ -+ * -+ */ -+ -+/* -+This is a small implementation of the IP and TCP protocols (as well as -+some basic ICMP stuff). The implementation couples the IP, TCP and the -+application layers very tightly. To keep the size of the compiled code -+down, this code also features heavy usage of the goto statement. -+ -+The principle is that we have a small buffer, called the uip_buf, in -+which the device driver puts an incoming packet. The TCP/IP stack -+parses the headers in the packet, and calls upon the application. If -+the remote host has sent data to the application, this data is present -+in the uip_buf and the application read the data from there. It is up -+to the application to put this data into a byte stream if needed. The -+application will not be fed with data that is out of sequence. -+ -+If the application whishes to send data to the peer, it should put its -+data into the uip_buf, 40 bytes from the start of the buffer. The -+TCP/IP stack will calculate the checksums, and fill in the necessary -+header fields and finally send the packet back to the peer. -+*/ -+ -+#include "uip.h" -+#include "uipopt.h" -+#include "uip_arch.h" -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Variable definitions. */ -+ -+ -+/* The IP address of this host. If it is defined to be fixed (by setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set here. Otherwise, the address */ -+#if UIP_FIXEDADDR > 0 -+const unsigned short int uip_hostaddr[2] = -+ {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1), -+ HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)}; -+const unsigned short int uip_arp_draddr[2] = -+ {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1), -+ HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)}; -+const unsigned short int uip_arp_netmask[2] = -+ {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1), -+ HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)}; -+#else -+unsigned short int uip_hostaddr[2]; -+unsigned short int uip_arp_draddr[2], uip_arp_netmask[2]; -+#endif /* UIP_FIXEDADDR */ -+ -+u8_t uip_buf[UIP_BUFSIZE+2]; /* The packet buffer that contains -+ incoming packets. */ -+volatile u8_t *uip_appdata; /* The uip_appdata pointer points to -+ application data. */ -+volatile u8_t *uip_sappdata; /* The uip_appdata pointer points to the -+ application data which is to be sent. */ -+#if UIP_URGDATA > 0 -+volatile u8_t *uip_urgdata; /* The uip_urgdata pointer points to -+ urgent data (out-of-band data), if -+ present. */ -+volatile u8_t uip_urglen, uip_surglen; -+#endif /* UIP_URGDATA > 0 */ -+ -+volatile unsigned short int uip_len, uip_slen; -+ /* The uip_len is either 8 or 16 bits, -+ depending on the maximum packet -+ size. */ -+ -+volatile u8_t uip_flags; /* The uip_flags variable is used for -+ communication between the TCP/IP stack -+ and the application program. */ -+struct uip_conn *uip_conn; /* uip_conn always points to the current -+ connection. */ -+ -+struct uip_conn uip_conns[UIP_CONNS]; -+ /* The uip_conns array holds all TCP -+ connections. */ -+unsigned short int uip_listenports[UIP_LISTENPORTS]; -+ /* The uip_listenports list all currently -+ listning ports. */ -+#if UIP_UDP -+struct uip_udp_conn *uip_udp_conn; -+struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; -+#endif /* UIP_UDP */ -+ -+ -+static unsigned short int ipid; /* Ths ipid variable is an increasing -+ number that is used for the IP ID -+ field. */ -+ -+static u8_t iss[4]; /* The iss variable is used for the TCP -+ initial sequence number. */ -+ -+#if UIP_ACTIVE_OPEN -+static unsigned short int lastport; /* Keeps track of the last port used for -+ a new connection. */ -+#endif /* UIP_ACTIVE_OPEN */ -+ -+/* Temporary variables. */ -+volatile u8_t uip_acc32[4]; -+static u8_t c, opt; -+static unsigned short int tmp16; -+ -+/* Structures and definitions. */ -+#define TCP_FIN 0x01 -+#define TCP_SYN 0x02 -+#define TCP_RST 0x04 -+#define TCP_PSH 0x08 -+#define TCP_ACK 0x10 -+#define TCP_URG 0x20 -+#define TCP_CTL 0x3f -+ -+#define ICMP_ECHO_REPLY 0 -+#define ICMP_ECHO 8 -+ -+/* Macros. */ -+#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) -+#define FBUF ((uip_tcpip_hdr *)&uip_reassbuf[0]) -+#define ICMPBUF ((uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) -+#define UDPBUF ((uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) -+ -+#if UIP_STATISTICS == 1 -+struct uip_stats uip_stat; -+#define UIP_STAT(s) s -+#else -+#define UIP_STAT(s) -+#endif /* UIP_STATISTICS == 1 */ -+ -+#if UIP_LOGGING == 1 -+extern void puts(const char *s); -+#define UIP_LOG(m) puts(m) -+#else -+#define UIP_LOG(m) -+#endif /* UIP_LOGGING == 1 */ -+ -+/*-----------------------------------------------------------------------------------*/ -+void -+uip_init(void) -+{ -+ for(c = 0; c < UIP_LISTENPORTS; ++c) { -+ uip_listenports[c] = 0; -+ } -+ for(c = 0; c < UIP_CONNS; ++c) { -+ uip_conns[c].tcpstateflags = CLOSED; -+ } -+#if UIP_ACTIVE_OPEN -+ lastport = 1024; -+#endif /* UIP_ACTIVE_OPEN */ -+ -+#if UIP_UDP -+ for(c = 0; c < UIP_UDP_CONNS; ++c) { -+ uip_udp_conns[c].lport = 0; -+ } -+#endif /* UIP_UDP */ -+ -+ -+ /* IPv4 initialization. */ -+#if UIP_FIXEDADDR == 0 -+ uip_hostaddr[0] = uip_hostaddr[1] = 0; -+#endif /* UIP_FIXEDADDR */ -+ -+} -+/*-----------------------------------------------------------------------------------*/ -+#if UIP_ACTIVE_OPEN -+struct uip_conn * -+uip_connect(unsigned short int *ripaddr, unsigned short int rport) -+{ -+ register struct uip_conn *conn, *cconn; -+ -+ /* Find an unused local port. */ -+ again: -+ ++lastport; -+ -+ if(lastport >= 32000) { -+ lastport = 4096; -+ } -+ -+ /* Check if this port is already in use, and if so try to find -+ another one. */ -+ for(c = 0; c < UIP_CONNS; ++c) { -+ conn = &uip_conns[c]; -+ if(conn->tcpstateflags != CLOSED && -+ conn->lport == htons(lastport)) { -+ goto again; -+ } -+ } -+ -+ -+ conn = 0; -+ for(c = 0; c < UIP_CONNS; ++c) { -+ cconn = &uip_conns[c]; -+ if(cconn->tcpstateflags == CLOSED) { -+ conn = cconn; -+ break; -+ } -+ if(cconn->tcpstateflags == TIME_WAIT) { -+ if(conn == 0 || -+ cconn->timer > uip_conn->timer) { -+ conn = cconn; -+ } -+ } -+ } -+ -+ if(conn == 0) { -+ return 0; -+ } -+ -+ conn->tcpstateflags = SYN_SENT; -+ -+ conn->snd_nxt[0] = iss[0]; -+ conn->snd_nxt[1] = iss[1]; -+ conn->snd_nxt[2] = iss[2]; -+ conn->snd_nxt[3] = iss[3]; -+ -+ conn->initialmss = conn->mss = UIP_TCP_MSS; -+ -+ conn->len = 1; /* TCP length of the SYN is one. */ -+ conn->nrtx = 0; -+ conn->timer = 1; /* Send the SYN next time around. */ -+ conn->rto = UIP_RTO; -+ conn->sa = 0; -+ conn->sv = 16; -+ conn->lport = htons(lastport); -+ conn->rport = rport; -+ conn->ripaddr[0] = ripaddr[0]; -+ conn->ripaddr[1] = ripaddr[1]; -+ -+ return conn; -+} -+#endif /* UIP_ACTIVE_OPEN */ -+/*-----------------------------------------------------------------------------------*/ -+#if UIP_UDP -+struct uip_udp_conn * -+uip_udp_new(unsigned short int *ripaddr, unsigned short int rport) -+{ -+ register struct uip_udp_conn *conn; -+ -+ /* Find an unused local port. */ -+ again: -+ ++lastport; -+ -+ if(lastport >= 32000) { -+ lastport = 4096; -+ } -+ -+ for(c = 0; c < UIP_UDP_CONNS; ++c) { -+ if(uip_udp_conns[c].lport == lastport) { -+ goto again; -+ } -+ } -+ -+ -+ conn = 0; -+ for(c = 0; c < UIP_UDP_CONNS; ++c) { -+ if(uip_udp_conns[c].lport == 0) { -+ conn = &uip_udp_conns[c]; -+ break; -+ } -+ } -+ -+ if(conn == 0) { -+ return 0; -+ } -+ -+ conn->lport = HTONS(lastport); -+ conn->rport = HTONS(rport); -+ conn->ripaddr[0] = ripaddr[0]; -+ conn->ripaddr[1] = ripaddr[1]; -+ -+ return conn; -+} -+#endif /* UIP_UDP */ -+/*-----------------------------------------------------------------------------------*/ -+void -+uip_unlisten(unsigned short int port) -+{ -+ for(c = 0; c < UIP_LISTENPORTS; ++c) { -+ if(uip_listenports[c] == port) { -+ uip_listenports[c] = 0; -+ return; -+ } -+ } -+} -+/*-----------------------------------------------------------------------------------*/ -+void -+uip_listen(unsigned short int port) -+{ -+ for(c = 0; c < UIP_LISTENPORTS; ++c) { -+ if(uip_listenports[c] == 0) { -+ uip_listenports[c] = port; -+ return; -+ } -+ } -+} -+/*-----------------------------------------------------------------------------------*/ -+/* XXX: IP fragment reassembly: not well-tested. */ -+ -+#if UIP_REASSEMBLY -+#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN) -+static u8_t uip_reassbuf[UIP_REASS_BUFSIZE]; -+static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; -+static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, -+ 0x0f, 0x07, 0x03, 0x01}; -+static unsigned short int uip_reasslen; -+static u8_t uip_reassflags; -+#define UIP_REASS_FLAG_LASTFRAG 0x01 -+static u8_t uip_reasstmr; -+ -+#define IP_HLEN 20 -+#define IP_MF 0x20 -+ -+static u8_t -+uip_reass(void) -+{ -+ unsigned short int offset, len; -+ unsigned short int i; -+ -+ /* If ip_reasstmr is zero, no packet is present in the buffer, so we -+ write the IP header of the fragment into the reassembly -+ buffer. The timer is updated with the maximum age. */ -+ if(uip_reasstmr == 0) { -+ memcpy(uip_reassbuf, &BUF->vhl, IP_HLEN); -+ uip_reasstmr = UIP_REASS_MAXAGE; -+ uip_reassflags = 0; -+ /* Clear the bitmap. */ -+ memset(uip_reassbitmap, sizeof(uip_reassbitmap), 0); -+ } -+ -+ /* Check if the incoming fragment matches the one currently present -+ in the reasembly buffer. If so, we proceed with copying the -+ fragment into the buffer. */ -+ if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] && -+ BUF->srcipaddr[1] == FBUF->srcipaddr[1] && -+ BUF->destipaddr[0] == FBUF->destipaddr[0] && -+ BUF->destipaddr[1] == FBUF->destipaddr[1] && -+ BUF->ipid[0] == FBUF->ipid[0] && -+ BUF->ipid[1] == FBUF->ipid[1]) { -+ -+ len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4; -+ offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8; -+ -+ /* If the offset or the offset + fragment length overflows the -+ reassembly buffer, we discard the entire packet. */ -+ if(offset > UIP_REASS_BUFSIZE || -+ offset + len > UIP_REASS_BUFSIZE) { -+ uip_reasstmr = 0; -+ goto nullreturn; -+ } -+ -+ /* Copy the fragment into the reassembly buffer, at the right -+ offset. */ -+ memcpy(&uip_reassbuf[IP_HLEN + offset], -+ (char *)BUF + (int)((BUF->vhl & 0x0f) * 4), -+ len); -+ -+ /* Update the bitmap. */ -+ if(offset / (8 * 8) == (offset + len) / (8 * 8)) { -+ /* If the two endpoints are in the same byte, we only update -+ that byte. */ -+ -+ uip_reassbitmap[offset / (8 * 8)] |= -+ bitmap_bits[(offset / 8 ) & 7] & -+ ~bitmap_bits[((offset + len) / 8 ) & 7]; -+ } else { -+ /* If the two endpoints are in different bytes, we update the -+ bytes in the endpoints and fill the stuff inbetween with -+ 0xff. */ -+ uip_reassbitmap[offset / (8 * 8)] |= -+ bitmap_bits[(offset / 8 ) & 7]; -+ for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) { -+ uip_reassbitmap[i] = 0xff; -+ } -+ uip_reassbitmap[(offset + len) / (8 * 8)] |= -+ ~bitmap_bits[((offset + len) / 8 ) & 7]; -+ } -+ -+ /* If this fragment has the More Fragments flag set to zero, we -+ know that this is the last fragment, so we can calculate the -+ size of the entire packet. We also set the -+ IP_REASS_FLAG_LASTFRAG flag to indicate that we have received -+ the final fragment. */ -+ -+ if((BUF->ipoffset[0] & IP_MF) == 0) { -+ uip_reassflags |= UIP_REASS_FLAG_LASTFRAG; -+ uip_reasslen = offset + len; -+ } -+ -+ /* Finally, we check if we have a full packet in the buffer. We do -+ this by checking if we have the last fragment and if all bits -+ in the bitmap are set. */ -+ if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) { -+ /* Check all bytes up to and including all but the last byte in -+ the bitmap. */ -+ for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) { -+ if(uip_reassbitmap[i] != 0xff) { -+ goto nullreturn; -+ } -+ } -+ /* Check the last byte in the bitmap. It should contain just the -+ right amount of bits. */ -+ if(uip_reassbitmap[uip_reasslen / (8 * 8)] != -+ (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) { -+ goto nullreturn; -+ } -+ -+ /* If we have come this far, we have a full packet in the -+ buffer, so we allocate a pbuf and copy the packet into it. We -+ also reset the timer. */ -+ uip_reasstmr = 0; -+ memcpy(BUF, FBUF, uip_reasslen); -+ -+ /* Pretend to be a "normal" (i.e., not fragmented) IP packet -+ from now on. */ -+ BUF->ipoffset[0] = BUF->ipoffset[1] = 0; -+ BUF->len[0] = uip_reasslen >> 8; -+ BUF->len[1] = uip_reasslen & 0xff; -+ BUF->ipchksum = 0; -+ BUF->ipchksum = ~(uip_ipchksum()); -+ -+ return uip_reasslen; -+ } -+ } -+ -+ nullreturn: -+ return 0; -+} -+#endif /* UIP_REASSEMBL */ -+/*-----------------------------------------------------------------------------------*/ -+static void -+uip_add_rcv_nxt(unsigned short int n) -+{ -+ uip_add32(uip_conn->rcv_nxt, n); -+ uip_conn->rcv_nxt[0] = uip_acc32[0]; -+ uip_conn->rcv_nxt[1] = uip_acc32[1]; -+ uip_conn->rcv_nxt[2] = uip_acc32[2]; -+ uip_conn->rcv_nxt[3] = uip_acc32[3]; -+} -+/*-----------------------------------------------------------------------------------*/ -+void -+uip_process(u8_t flag) -+{ -+ register struct uip_conn *uip_connr = uip_conn; -+ -+ uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; -+ -+ -+ /* Check if we were invoked because of the perodic timer fireing. */ -+ if(flag == UIP_TIMER) { -+#if UIP_REASSEMBLY -+ if(uip_reasstmr != 0) { -+ --uip_reasstmr; -+ } -+#endif /* UIP_REASSEMBLY */ -+ /* Increase the initial sequence number. */ -+ if(++iss[3] == 0) { -+ if(++iss[2] == 0) { -+ if(++iss[1] == 0) { -+ ++iss[0]; -+ } -+ } -+ } -+ uip_len = 0; -+ if(uip_connr->tcpstateflags == TIME_WAIT || -+ uip_connr->tcpstateflags == FIN_WAIT_2) { -+ ++(uip_connr->timer); -+ if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) { -+ uip_connr->tcpstateflags = CLOSED; -+ } -+ } else if(uip_connr->tcpstateflags != CLOSED) { -+ /* If the connection has outstanding data, we increase the -+ connection's timer and see if it has reached the RTO value -+ in which case we retransmit. */ -+ if(uip_outstanding(uip_connr)) { -+ if(uip_connr->timer-- == 0) { -+ if(uip_connr->nrtx == UIP_MAXRTX || -+ ((uip_connr->tcpstateflags == SYN_SENT || -+ uip_connr->tcpstateflags == SYN_RCVD) && -+ uip_connr->nrtx == UIP_MAXSYNRTX)) { -+ uip_connr->tcpstateflags = CLOSED; -+ -+ /* We call UIP_APPCALL() with uip_flags set to -+ UIP_TIMEDOUT to inform the application that the -+ connection has timed out. */ -+ uip_flags = UIP_TIMEDOUT; -+ UIP_APPCALL(); -+ -+ /* We also send a reset packet to the remote host. */ -+ BUF->flags = TCP_RST | TCP_ACK; -+ goto tcp_send_nodata; -+ } -+ -+ /* Exponential backoff. */ -+ uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4? -+ 4: -+ uip_connr->nrtx); -+ ++(uip_connr->nrtx); -+ -+ /* Ok, so we need to retransmit. We do this differently -+ depending on which state we are in. In ESTABLISHED, we -+ call upon the application so that it may prepare the -+ data for the retransmit. In SYN_RCVD, we resend the -+ SYNACK that we sent earlier and in LAST_ACK we have to -+ retransmit our FINACK. */ -+ UIP_STAT(++uip_stat.tcp.rexmit); -+ switch(uip_connr->tcpstateflags & TS_MASK) { -+ case SYN_RCVD: -+ /* In the SYN_RCVD state, we should retransmit our -+ SYNACK. */ -+ goto tcp_send_synack; -+ -+#if UIP_ACTIVE_OPEN -+ case SYN_SENT: -+ /* In the SYN_SENT state, we retransmit out SYN. */ -+ BUF->flags = 0; -+ goto tcp_send_syn; -+#endif /* UIP_ACTIVE_OPEN */ -+ -+ case ESTABLISHED: -+ /* In the ESTABLISHED state, we call upon the application -+ to do the actual retransmit after which we jump into -+ the code for sending out the packet (the apprexmit -+ label). */ -+ uip_len = 0; -+ uip_slen = 0; -+ uip_flags = UIP_REXMIT; -+ UIP_APPCALL(); -+ goto apprexmit; -+ -+ case FIN_WAIT_1: -+ case CLOSING: -+ case LAST_ACK: -+ /* In all these states we should retransmit a FINACK. */ -+ goto tcp_send_finack; -+ -+ } -+ } -+ } else if((uip_connr->tcpstateflags & TS_MASK) == ESTABLISHED) { -+ /* If there was no need for a retransmission, we poll the -+ application for new data. */ -+ uip_len = 0; -+ uip_slen = 0; -+ uip_flags = UIP_POLL; -+ UIP_APPCALL(); -+ goto appsend; -+ } -+ } -+ goto drop; -+ } -+#if UIP_UDP -+ if(flag == UIP_UDP_TIMER) { -+ if(uip_udp_conn->lport != 0) { -+ uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; -+ uip_len = uip_slen = 0; -+ uip_flags = UIP_POLL; -+ UIP_UDP_APPCALL(); -+ goto udp_send; -+ } else { -+ goto drop; -+ } -+ } -+#endif -+ -+ /* This is where the input processing starts. */ -+ UIP_STAT(++uip_stat.ip.recv); -+ -+ -+ /* Start of IPv4 input header processing code. */ -+ -+ /* Check validity of the IP header. */ -+ if(BUF->vhl != 0x45) { /* IP version and header length. */ -+ UIP_STAT(++uip_stat.ip.drop); -+ UIP_STAT(++uip_stat.ip.vhlerr); -+ UIP_LOG("ip: invalid version or header length."); -+ goto drop; -+ } -+ -+ /* Check the size of the packet. If the size reported to us in -+ uip_len doesn't match the size reported in the IP header, there -+ has been a transmission error and we drop the packet. */ -+ -+ if(BUF->len[0] != (uip_len >> 8)) { /* IP length, high byte. */ -+ uip_len = (uip_len & 0xff) | (BUF->len[0] << 8); -+ } -+ if(BUF->len[1] != (uip_len & 0xff)) { /* IP length, low byte. */ -+ uip_len = (uip_len & 0xff00) | BUF->len[1]; -+ } -+ -+ /* Check the fragment flag. */ -+ if((BUF->ipoffset[0] & 0x3f) != 0 || -+ BUF->ipoffset[1] != 0) { -+#if UIP_REASSEMBLY -+ uip_len = uip_reass(); -+ if(uip_len == 0) { -+ goto drop; -+ } -+#else -+ UIP_STAT(++uip_stat.ip.drop); -+ UIP_STAT(++uip_stat.ip.fragerr); -+ UIP_LOG("ip: fragment dropped."); -+ goto drop; -+#endif /* UIP_REASSEMBLY */ -+ } -+ -+ /* If we are configured to use ping IP address configuration and -+ hasn't been assigned an IP address yet, we accept all ICMP -+ packets. */ -+#if UIP_PINGADDRCONF -+ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { -+ if(BUF->proto == UIP_PROTO_ICMP) { -+ UIP_LOG("ip: possible ping config packet received."); -+ goto icmp_input; -+ } else { -+ UIP_LOG("ip: packet dropped since no address assigned."); -+ goto drop; -+ } -+ } -+#endif /* UIP_PINGADDRCONF */ -+ -+ /* Check if the packet is destined for our IP address. */ -+ if(BUF->destipaddr[0] != uip_hostaddr[0]) { -+ UIP_STAT(++uip_stat.ip.drop); -+ UIP_LOG("ip: packet not for us."); -+ goto drop; -+ } -+ if(BUF->destipaddr[1] != uip_hostaddr[1]) { -+ UIP_STAT(++uip_stat.ip.drop); -+ UIP_LOG("ip: packet not for us."); -+ goto drop; -+ } -+ -+ if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header -+ checksum. */ -+ UIP_STAT(++uip_stat.ip.drop); -+ UIP_STAT(++uip_stat.ip.chkerr); -+ UIP_LOG("ip: bad checksum."); -+ goto drop; -+ } -+ -+ if(BUF->proto == UIP_PROTO_TCP) /* Check for TCP packet. If so, jump -+ to the tcp_input label. */ -+ goto tcp_input; -+ -+#if UIP_UDP -+ if(BUF->proto == UIP_PROTO_UDP) -+ goto udp_input; -+#endif /* UIP_UDP */ -+ -+ if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from -+ here. */ -+ UIP_STAT(++uip_stat.ip.drop); -+ UIP_STAT(++uip_stat.ip.protoerr); -+ UIP_LOG("ip: neither tcp nor icmp."); -+ goto drop; -+ } -+ -+ //icmp_input: -+ UIP_STAT(++uip_stat.icmp.recv); -+ -+ /* ICMP echo (i.e., ping) processing. This is simple, we only change -+ the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP -+ checksum before we return the packet. */ -+ if(ICMPBUF->type != ICMP_ECHO) { -+ UIP_STAT(++uip_stat.icmp.drop); -+ UIP_STAT(++uip_stat.icmp.typeerr); -+ UIP_LOG("icmp: not icmp echo."); -+ goto drop; -+ } -+ -+ /* If we are configured to use ping IP address assignment, we use -+ the destination IP address of this ping packet and assign it to -+ ourself. */ -+#if UIP_PINGADDRCONF -+ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { -+ uip_hostaddr[0] = BUF->destipaddr[0]; -+ uip_hostaddr[1] = BUF->destipaddr[1]; -+ } -+#endif /* UIP_PINGADDRCONF */ -+ -+ ICMPBUF->type = ICMP_ECHO_REPLY; -+ -+ if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) { -+ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1; -+ } else { -+ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8); -+ } -+ -+ /* Swap IP addresses. */ -+ tmp16 = BUF->destipaddr[0]; -+ BUF->destipaddr[0] = BUF->srcipaddr[0]; -+ BUF->srcipaddr[0] = tmp16; -+ tmp16 = BUF->destipaddr[1]; -+ BUF->destipaddr[1] = BUF->srcipaddr[1]; -+ BUF->srcipaddr[1] = tmp16; -+ -+ UIP_STAT(++uip_stat.icmp.sent); -+ goto send; -+ -+ /* End of IPv4 input header processing code. */ -+ -+ -+#if UIP_UDP -+ /* UDP input processing. */ -+ udp_input: -+ /* UDP processing is really just a hack. We don't do anything to the -+ UDP/IP headers, but let the UDP application do all the hard -+ work. If the application sets uip_slen, it has a packet to -+ send. */ -+#if UIP_UDP_CHECKSUMS -+ if(uip_udpchksum() != 0xffff) { -+ UIP_STAT(++uip_stat.udp.drop); -+ UIP_STAT(++uip_stat.udp.chkerr); -+ UIP_LOG("udp: bad checksum."); -+ goto drop; -+ } -+#endif /* UIP_UDP_CHECKSUMS */ -+ -+ /* Demultiplex this UDP packet between the UDP "connections". */ -+ for(uip_udp_conn = &uip_udp_conns[0]; -+ uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; -+ ++uip_udp_conn) { -+ if(uip_udp_conn->lport != 0 && -+ UDPBUF->destport == uip_udp_conn->lport && -+ (uip_udp_conn->rport == 0 || -+ UDPBUF->srcport == uip_udp_conn->rport) && -+ BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] && -+ BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) { -+ goto udp_found; -+ } -+ } -+ goto drop; -+ -+ udp_found: -+ uip_len = uip_len - 28; -+ uip_appdata = &uip_buf[UIP_LLH_LEN + 28]; -+ uip_flags = UIP_NEWDATA; -+ uip_slen = 0; -+ UIP_UDP_APPCALL(); -+ udp_send: -+ if(uip_slen == 0) { -+ goto drop; -+ } -+ uip_len = uip_slen + 28; -+ -+ BUF->len[0] = (uip_len >> 8); -+ BUF->len[1] = (uip_len & 0xff); -+ -+ BUF->proto = UIP_PROTO_UDP; -+ -+ UDPBUF->udplen = HTONS(uip_slen + 8); -+ UDPBUF->udpchksum = 0; -+#if UIP_UDP_CHECKSUMS -+ /* Calculate UDP checksum. */ -+ UDPBUF->udpchksum = ~(uip_udpchksum()); -+ if(UDPBUF->udpchksum == 0) { -+ UDPBUF->udpchksum = 0xffff; -+ } -+#endif /* UIP_UDP_CHECKSUMS */ -+ -+ BUF->srcport = uip_udp_conn->lport; -+ BUF->destport = uip_udp_conn->rport; -+ -+ BUF->srcipaddr[0] = uip_hostaddr[0]; -+ BUF->srcipaddr[1] = uip_hostaddr[1]; -+ BUF->destipaddr[0] = uip_udp_conn->ripaddr[0]; -+ BUF->destipaddr[1] = uip_udp_conn->ripaddr[1]; -+ -+ uip_appdata = &uip_buf[UIP_LLH_LEN + 40]; -+ goto ip_send_nolen; -+#endif /* UIP_UDP */ -+ -+ /* TCP input processing. */ -+ tcp_input: -+ UIP_STAT(++uip_stat.tcp.recv); -+ -+ /* Start of TCP input header processing code. */ -+ -+ if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP -+ checksum. */ -+ UIP_STAT(++uip_stat.tcp.drop); -+ UIP_STAT(++uip_stat.tcp.chkerr); -+ UIP_LOG("tcp: bad checksum."); -+ goto drop; -+ } -+ -+ /* Demultiplex this segment. */ -+ /* First check any active connections. */ -+ for(uip_connr = &uip_conns[0]; uip_connr < &uip_conns[UIP_CONNS]; ++uip_connr) { -+ if(uip_connr->tcpstateflags != CLOSED && -+ BUF->destport == uip_connr->lport && -+ BUF->srcport == uip_connr->rport && -+ BUF->srcipaddr[0] == uip_connr->ripaddr[0] && -+ BUF->srcipaddr[1] == uip_connr->ripaddr[1]) { -+ goto found; -+ } -+ } -+ -+ /* If we didn't find and active connection that expected the packet, -+ either this packet is an old duplicate, or this is a SYN packet -+ destined for a connection in LISTEN. If the SYN flag isn't set, -+ it is an old packet and we send a RST. */ -+ if((BUF->flags & TCP_CTL) != TCP_SYN) -+ goto reset; -+ -+ tmp16 = BUF->destport; -+ /* Next, check listening connections. */ -+ for(c = 0; c < UIP_LISTENPORTS; ++c) { -+ if(tmp16 == uip_listenports[c]) -+ goto found_listen; -+ } -+ -+ /* No matching connection found, so we send a RST packet. */ -+ UIP_STAT(++uip_stat.tcp.synrst); -+ reset: -+ -+ /* We do not send resets in response to resets. */ -+ if(BUF->flags & TCP_RST) -+ goto drop; -+ -+ UIP_STAT(++uip_stat.tcp.rst); -+ -+ BUF->flags = TCP_RST | TCP_ACK; -+ uip_len = 40; -+ BUF->tcpoffset = 5 << 4; -+ -+ /* Flip the seqno and ackno fields in the TCP header. */ -+ c = BUF->seqno[3]; -+ BUF->seqno[3] = BUF->ackno[3]; -+ BUF->ackno[3] = c; -+ -+ c = BUF->seqno[2]; -+ BUF->seqno[2] = BUF->ackno[2]; -+ BUF->ackno[2] = c; -+ -+ c = BUF->seqno[1]; -+ BUF->seqno[1] = BUF->ackno[1]; -+ BUF->ackno[1] = c; -+ -+ c = BUF->seqno[0]; -+ BUF->seqno[0] = BUF->ackno[0]; -+ BUF->ackno[0] = c; -+ -+ /* We also have to increase the sequence number we are -+ acknowledging. If the least significant byte overflowed, we need -+ to propagate the carry to the other bytes as well. */ -+ if(++BUF->ackno[3] == 0) { -+ if(++BUF->ackno[2] == 0) { -+ if(++BUF->ackno[1] == 0) { -+ ++BUF->ackno[0]; -+ } -+ } -+ } -+ -+ /* Swap port numbers. */ -+ tmp16 = BUF->srcport; -+ BUF->srcport = BUF->destport; -+ BUF->destport = tmp16; -+ -+ /* Swap IP addresses. */ -+ tmp16 = BUF->destipaddr[0]; -+ BUF->destipaddr[0] = BUF->srcipaddr[0]; -+ BUF->srcipaddr[0] = tmp16; -+ tmp16 = BUF->destipaddr[1]; -+ BUF->destipaddr[1] = BUF->srcipaddr[1]; -+ BUF->srcipaddr[1] = tmp16; -+ -+ -+ /* And send out the RST packet! */ -+ goto tcp_send_noconn; -+ -+ /* This label will be jumped to if we matched the incoming packet -+ with a connection in LISTEN. In that case, we should create a new -+ connection and send a SYNACK in return. */ -+ found_listen: -+ /* First we check if there are any connections avaliable. Unused -+ connections are kept in the same table as used connections, but -+ unused ones have the tcpstate set to CLOSED. Also, connections in -+ TIME_WAIT are kept track of and we'll use the oldest one if no -+ CLOSED connections are found. Thanks to Eddie C. Dost for a very -+ nice algorithm for the TIME_WAIT search. */ -+ uip_connr = 0; -+ for(c = 0; c < UIP_CONNS; ++c) { -+ if(uip_conns[c].tcpstateflags == CLOSED) { -+ uip_connr = &uip_conns[c]; -+ break; -+ } -+ if(uip_conns[c].tcpstateflags == TIME_WAIT) { -+ if(uip_connr == 0 || -+ uip_conns[c].timer > uip_connr->timer) { -+ uip_connr = &uip_conns[c]; -+ } -+ } -+ } -+ -+ if(uip_connr == 0) { -+ /* All connections are used already, we drop packet and hope that -+ the remote end will retransmit the packet at a time when we -+ have more spare connections. */ -+ UIP_STAT(++uip_stat.tcp.syndrop); -+ UIP_LOG("tcp: found no unused connections."); -+ goto drop; -+ } -+ uip_conn = uip_connr; -+ -+ /* Fill in the necessary fields for the new connection. */ -+ uip_connr->rto = uip_connr->timer = UIP_RTO; -+ uip_connr->sa = 0; -+ uip_connr->sv = 4; -+ uip_connr->nrtx = 0; -+ uip_connr->lport = BUF->destport; -+ uip_connr->rport = BUF->srcport; -+ uip_connr->ripaddr[0] = BUF->srcipaddr[0]; -+ uip_connr->ripaddr[1] = BUF->srcipaddr[1]; -+ uip_connr->tcpstateflags = SYN_RCVD; -+ -+ uip_connr->snd_nxt[0] = iss[0]; -+ uip_connr->snd_nxt[1] = iss[1]; -+ uip_connr->snd_nxt[2] = iss[2]; -+ uip_connr->snd_nxt[3] = iss[3]; -+ uip_connr->len = 1; -+ -+ /* rcv_nxt should be the seqno from the incoming packet + 1. */ -+ uip_connr->rcv_nxt[3] = BUF->seqno[3]; -+ uip_connr->rcv_nxt[2] = BUF->seqno[2]; -+ uip_connr->rcv_nxt[1] = BUF->seqno[1]; -+ uip_connr->rcv_nxt[0] = BUF->seqno[0]; -+ uip_add_rcv_nxt(1); -+ -+ /* Parse the TCP MSS option, if present. */ -+ if((BUF->tcpoffset & 0xf0) > 0x50) { -+ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { -+ opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; -+ if(opt == 0x00) { -+ /* End of options. */ -+ break; -+ } else if(opt == 0x01) { -+ ++c; -+ /* NOP option. */ -+ } else if(opt == 0x02 && -+ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { -+ /* An MSS option with the right option length. */ -+ tmp16 = ((unsigned short int)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | -+ (unsigned short int)uip_buf[40 + UIP_LLH_LEN + 3 + c]; -+ uip_connr->initialmss = uip_connr->mss = -+ tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; -+ -+ /* And we are done processing options. */ -+ break; -+ } else { -+ /* All other options have a length field, so that we easily -+ can skip past them. */ -+ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { -+ /* If the length field is zero, the options are malformed -+ and we don't process them further. */ -+ break; -+ } -+ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; -+ } -+ } -+ } -+ -+ /* Our response will be a SYNACK. */ -+#if UIP_ACTIVE_OPEN -+ tcp_send_synack: -+ BUF->flags = TCP_ACK; -+ -+ tcp_send_syn: -+ BUF->flags |= TCP_SYN; -+#else /* UIP_ACTIVE_OPEN */ -+ tcp_send_synack: -+ BUF->flags = TCP_SYN | TCP_ACK; -+#endif /* UIP_ACTIVE_OPEN */ -+ -+ /* We send out the TCP Maximum Segment Size option with our -+ SYNACK. */ -+ BUF->optdata[0] = 2; -+ BUF->optdata[1] = 4; -+ BUF->optdata[2] = (UIP_TCP_MSS) / 256; -+ BUF->optdata[3] = (UIP_TCP_MSS) & 255; -+ uip_len = 44; -+ BUF->tcpoffset = 6 << 4; -+ goto tcp_send; -+ -+ /* This label will be jumped to if we found an active connection. */ -+ found: -+ uip_conn = uip_connr; -+ uip_flags = 0; -+ -+ /* We do a very naive form of TCP reset processing; we just accept -+ any RST and kill our connection. We should in fact check if the -+ sequence number of this reset is wihtin our advertised window -+ before we accept the reset. */ -+ if(BUF->flags & TCP_RST) { -+ uip_connr->tcpstateflags = CLOSED; -+ UIP_LOG("tcp: got reset, aborting connection."); -+ uip_flags = UIP_ABORT; -+ UIP_APPCALL(); -+ goto drop; -+ } -+ /* Calculated the length of the data, if the application has sent -+ any data to us. */ -+ c = (BUF->tcpoffset >> 4) << 2; -+ /* uip_len will contain the length of the actual TCP data. This is -+ calculated by subtracing the length of the TCP header (in -+ c) and the length of the IP header (20 bytes). */ -+ uip_len = uip_len - c - 20; -+ -+ /* First, check if the sequence number of the incoming packet is -+ what we're expecting next. If not, we send out an ACK with the -+ correct numbers in. */ -+ if(uip_len > 0 && -+ (BUF->seqno[0] != uip_connr->rcv_nxt[0] || -+ BUF->seqno[1] != uip_connr->rcv_nxt[1] || -+ BUF->seqno[2] != uip_connr->rcv_nxt[2] || -+ BUF->seqno[3] != uip_connr->rcv_nxt[3])) { -+ goto tcp_send_ack; -+ } -+ -+ /* Next, check if the incoming segment acknowledges any outstanding -+ data. If so, we update the sequence number, reset the length of -+ the outstanding data, calculate RTT estimations, and reset the -+ retransmission timer. */ -+ if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) { -+ uip_add32(uip_connr->snd_nxt, uip_connr->len); -+ if(BUF->ackno[0] == uip_acc32[0] && -+ BUF->ackno[1] == uip_acc32[1] && -+ BUF->ackno[2] == uip_acc32[2] && -+ BUF->ackno[3] == uip_acc32[3]) { -+ /* Update sequence number. */ -+ uip_connr->snd_nxt[0] = uip_acc32[0]; -+ uip_connr->snd_nxt[1] = uip_acc32[1]; -+ uip_connr->snd_nxt[2] = uip_acc32[2]; -+ uip_connr->snd_nxt[3] = uip_acc32[3]; -+ -+ -+ /* Do RTT estimation, unless we have done retransmissions. */ -+ if(uip_connr->nrtx == 0) { -+ signed char m; -+ m = uip_connr->rto - uip_connr->timer; -+ /* This is taken directly from VJs original code in his paper */ -+ m = m - (uip_connr->sa >> 3); -+ uip_connr->sa += m; -+ if(m < 0) { -+ m = -m; -+ } -+ m = m - (uip_connr->sv >> 2); -+ uip_connr->sv += m; -+ uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv; -+ -+ } -+ /* Set the acknowledged flag. */ -+ uip_flags = UIP_ACKDATA; -+ /* Reset the retransmission timer. */ -+ uip_connr->timer = uip_connr->rto; -+ } -+ -+ } -+ -+ /* Do different things depending on in what state the connection is. */ -+ switch(uip_connr->tcpstateflags & TS_MASK) { -+ /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not -+ implemented, since we force the application to close when the -+ peer sends a FIN (hence the application goes directly from -+ ESTABLISHED to LAST_ACK). */ -+ case SYN_RCVD: -+ /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and -+ we are waiting for an ACK that acknowledges the data we sent -+ out the last time. Therefore, we want to have the UIP_ACKDATA -+ flag set. If so, we enter the ESTABLISHED state. */ -+ if(uip_flags & UIP_ACKDATA) { -+ uip_connr->tcpstateflags = ESTABLISHED; -+ uip_flags = UIP_CONNECTED; -+ uip_connr->len = 0; -+ if(uip_len > 0) { -+ uip_flags |= UIP_NEWDATA; -+ uip_add_rcv_nxt(uip_len); -+ } -+ uip_slen = 0; -+ UIP_APPCALL(); -+ goto appsend; -+ } -+ goto drop; -+#if UIP_ACTIVE_OPEN -+ case SYN_SENT: -+ /* In SYN_SENT, we wait for a SYNACK that is sent in response to -+ our SYN. The rcv_nxt is set to sequence number in the SYNACK -+ plus one, and we send an ACK. We move into the ESTABLISHED -+ state. */ -+ if((uip_flags & UIP_ACKDATA) && -+ BUF->flags == (TCP_SYN | TCP_ACK)) { -+ -+ /* Parse the TCP MSS option, if present. */ -+ if((BUF->tcpoffset & 0xf0) > 0x50) { -+ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { -+ opt = uip_buf[40 + UIP_LLH_LEN + c]; -+ if(opt == 0x00) { -+ /* End of options. */ -+ break; -+ } else if(opt == 0x01) { -+ ++c; -+ /* NOP option. */ -+ } else if(opt == 0x02 && -+ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0x04) { -+ /* An MSS option with the right option length. */ -+ tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | -+ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; -+ uip_connr->initialmss = -+ uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; -+ -+ /* And we are done processing options. */ -+ break; -+ } else { -+ /* All other options have a length field, so that we easily -+ can skip past them. */ -+ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { -+ /* If the length field is zero, the options are malformed -+ and we don't process them further. */ -+ break; -+ } -+ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; -+ } -+ } -+ } -+ uip_connr->tcpstateflags = ESTABLISHED; -+ uip_connr->rcv_nxt[0] = BUF->seqno[0]; -+ uip_connr->rcv_nxt[1] = BUF->seqno[1]; -+ uip_connr->rcv_nxt[2] = BUF->seqno[2]; -+ uip_connr->rcv_nxt[3] = BUF->seqno[3]; -+ uip_add_rcv_nxt(1); -+ uip_flags = UIP_CONNECTED | UIP_NEWDATA; -+ uip_connr->len = 0; -+ uip_len = 0; -+ uip_slen = 0; -+ UIP_APPCALL(); -+ goto appsend; -+ } -+ goto reset; -+#endif /* UIP_ACTIVE_OPEN */ -+ -+ case ESTABLISHED: -+ /* In the ESTABLISHED state, we call upon the application to feed -+ data into the uip_buf. If the UIP_ACKDATA flag is set, the -+ application should put new data into the buffer, otherwise we are -+ retransmitting an old segment, and the application should put that -+ data into the buffer. -+ -+ If the incoming packet is a FIN, we should close the connection on -+ this side as well, and we send out a FIN and enter the LAST_ACK -+ state. We require that there is no outstanding data; otherwise the -+ sequence numbers will be screwed up. */ -+ -+ if(BUF->flags & TCP_FIN) { -+ if(uip_outstanding(uip_connr)) { -+ goto drop; -+ } -+ uip_add_rcv_nxt(1 + uip_len); -+ uip_flags = UIP_CLOSE; -+ if(uip_len > 0) { -+ uip_flags |= UIP_NEWDATA; -+ } -+ UIP_APPCALL(); -+ uip_connr->len = 1; -+ uip_connr->tcpstateflags = LAST_ACK; -+ uip_connr->nrtx = 0; -+ tcp_send_finack: -+ BUF->flags = TCP_FIN | TCP_ACK; -+ goto tcp_send_nodata; -+ } -+ -+ /* Check the URG flag. If this is set, the segment carries urgent -+ data that we must pass to the application. */ -+ if(BUF->flags & TCP_URG) { -+#if UIP_URGDATA > 0 -+ uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1]; -+ if(uip_urglen > uip_len) { -+ /* There is more urgent data in the next segment to come. */ -+ uip_urglen = uip_len; -+ } -+ uip_add_rcv_nxt(uip_urglen); -+ uip_len -= uip_urglen; -+ uip_urgdata = uip_appdata; -+ uip_appdata += uip_urglen; -+ } else { -+ uip_urglen = 0; -+#endif /* UIP_URGDATA > 0 */ -+ uip_appdata += (BUF->urgp[0] << 8) | BUF->urgp[1]; -+ uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1]; -+ } -+ -+ -+ /* If uip_len > 0 we have TCP data in the packet, and we flag this -+ by setting the UIP_NEWDATA flag and update the sequence number -+ we acknowledge. If the application has stopped the dataflow -+ using uip_stop(), we must not accept any data packets from the -+ remote host. */ -+ if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) { -+ uip_flags |= UIP_NEWDATA; -+ uip_add_rcv_nxt(uip_len); -+ } -+ -+ /* Check if the available buffer space advertised by the other end -+ is smaller than the initial MSS for this connection. If so, we -+ set the current MSS to the window size to ensure that the -+ application does not send more data than the other end can -+ handle. -+ -+ If the remote host advertises a zero window, we set the MSS to -+ the initial MSS so that the application will send an entire MSS -+ of data. This data will not be acknowledged by the receiver, -+ and the application will retransmit it. This is called the -+ "persistent timer" and uses the retransmission mechanim. -+ */ -+ tmp16 = ((unsigned short int)BUF->wnd[0] << 8) + (unsigned short int)BUF->wnd[1]; -+ if(tmp16 > uip_connr->initialmss || -+ tmp16 == 0) { -+ tmp16 = uip_connr->initialmss; -+ } -+ uip_connr->mss = tmp16; -+ -+ /* If this packet constitutes an ACK for outstanding data (flagged -+ by the UIP_ACKDATA flag, we should call the application since it -+ might want to send more data. If the incoming packet had data -+ from the peer (as flagged by the UIP_NEWDATA flag), the -+ application must also be notified. -+ -+ When the application is called, the global variable uip_len -+ contains the length of the incoming data. The application can -+ access the incoming data through the global pointer -+ uip_appdata, which usually points 40 bytes into the uip_buf -+ array. -+ -+ If the application wishes to send any data, this data should be -+ put into the uip_appdata and the length of the data should be -+ put into uip_len. If the application don't have any data to -+ send, uip_len must be set to 0. */ -+ if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) { -+ uip_slen = 0; -+ UIP_APPCALL(); -+ -+ appsend: -+ -+ if(uip_flags & UIP_ABORT) { -+ uip_slen = 0; -+ uip_connr->tcpstateflags = CLOSED; -+ BUF->flags = TCP_RST | TCP_ACK; -+ goto tcp_send_nodata; -+ } -+ -+ if(uip_flags & UIP_CLOSE) { -+ uip_slen = 0; -+ uip_connr->len = 1; -+ uip_connr->tcpstateflags = FIN_WAIT_1; -+ uip_connr->nrtx = 0; -+ BUF->flags = TCP_FIN | TCP_ACK; -+ goto tcp_send_nodata; -+ } -+ -+ /* If uip_slen > 0, the application has data to be sent. */ -+ if(uip_slen > 0) { -+ -+ /* If the connection has acknowledged data, the contents of -+ the ->len variable should be discarded. */ -+ if((uip_flags & UIP_ACKDATA) != 0) { -+ uip_connr->len = 0; -+ } -+ -+ /* If the ->len variable is non-zero the connection has -+ already data in transit and cannot send anymore right -+ now. */ -+ if(uip_connr->len == 0) { -+ -+ /* The application cannot send more than what is allowed by -+ the mss (the minumum of the MSS and the available -+ window). */ -+ if(uip_slen > uip_connr->mss) { -+ uip_slen = uip_connr->mss; -+ } -+ -+ /* Remember how much data we send out now so that we know -+ when everything has been acknowledged. */ -+ uip_connr->len = uip_slen; -+ } else { -+ -+ /* If the application already had unacknowledged data, we -+ make sure that the application does not send (i.e., -+ retransmit) out more than it previously sent out. */ -+ uip_slen = uip_connr->len; -+ } -+ } else { -+ uip_connr->len = 0; -+ } -+ uip_connr->nrtx = 0; -+ apprexmit: -+ uip_appdata = uip_sappdata; -+ -+ /* If the application has data to be sent, or if the incoming -+ packet had new data in it, we must send out a packet. */ -+ if(uip_slen > 0 && uip_connr->len > 0) { -+ /* Add the length of the IP and TCP headers. */ -+ uip_len = uip_connr->len + UIP_TCPIP_HLEN; -+ /* We always set the ACK flag in response packets. */ -+ BUF->flags = TCP_ACK | TCP_PSH; -+ /* Send the packet. */ -+ goto tcp_send_noopts; -+ } -+ /* If there is no data to send, just send out a pure ACK if -+ there is newdata. */ -+ if(uip_flags & UIP_NEWDATA) { -+ uip_len = UIP_TCPIP_HLEN; -+ BUF->flags = TCP_ACK; -+ goto tcp_send_noopts; -+ } -+ } -+ goto drop; -+ case LAST_ACK: -+ /* We can close this connection if the peer has acknowledged our -+ FIN. This is indicated by the UIP_ACKDATA flag. */ -+ if(uip_flags & UIP_ACKDATA) { -+ uip_connr->tcpstateflags = CLOSED; -+ uip_flags = UIP_CLOSE; -+ UIP_APPCALL(); -+ } -+ break; -+ -+ case FIN_WAIT_1: -+ /* The application has closed the connection, but the remote host -+ hasn't closed its end yet. Thus we do nothing but wait for a -+ FIN from the other side. */ -+ if(uip_len > 0) { -+ uip_add_rcv_nxt(uip_len); -+ } -+ if(BUF->flags & TCP_FIN) { -+ if(uip_flags & UIP_ACKDATA) { -+ uip_connr->tcpstateflags = TIME_WAIT; -+ uip_connr->timer = 0; -+ uip_connr->len = 0; -+ } else { -+ uip_connr->tcpstateflags = CLOSING; -+ } -+ uip_add_rcv_nxt(1); -+ uip_flags = UIP_CLOSE; -+ UIP_APPCALL(); -+ goto tcp_send_ack; -+ } else if(uip_flags & UIP_ACKDATA) { -+ uip_connr->tcpstateflags = FIN_WAIT_2; -+ uip_connr->len = 0; -+ goto drop; -+ } -+ if(uip_len > 0) { -+ goto tcp_send_ack; -+ } -+ goto drop; -+ -+ case FIN_WAIT_2: -+ if(uip_len > 0) { -+ uip_add_rcv_nxt(uip_len); -+ } -+ if(BUF->flags & TCP_FIN) { -+ uip_connr->tcpstateflags = TIME_WAIT; -+ uip_connr->timer = 0; -+ uip_add_rcv_nxt(1); -+ uip_flags = UIP_CLOSE; -+ UIP_APPCALL(); -+ goto tcp_send_ack; -+ } -+ if(uip_len > 0) { -+ goto tcp_send_ack; -+ } -+ goto drop; -+ -+ case TIME_WAIT: -+ goto tcp_send_ack; -+ -+ case CLOSING: -+ if(uip_flags & UIP_ACKDATA) { -+ uip_connr->tcpstateflags = TIME_WAIT; -+ uip_connr->timer = 0; -+ } -+ } -+ goto drop; -+ -+ -+ /* We jump here when we are ready to send the packet, and just want -+ to set the appropriate TCP sequence numbers in the TCP header. */ -+ tcp_send_ack: -+ BUF->flags = TCP_ACK; -+ tcp_send_nodata: -+ uip_len = 40; -+ tcp_send_noopts: -+ BUF->tcpoffset = 5 << 4; -+ tcp_send: -+ /* We're done with the input processing. We are now ready to send a -+ reply. Our job is to fill in all the fields of the TCP and IP -+ headers before calculating the checksum and finally send the -+ packet. */ -+ BUF->ackno[0] = uip_connr->rcv_nxt[0]; -+ BUF->ackno[1] = uip_connr->rcv_nxt[1]; -+ BUF->ackno[2] = uip_connr->rcv_nxt[2]; -+ BUF->ackno[3] = uip_connr->rcv_nxt[3]; -+ -+ BUF->seqno[0] = uip_connr->snd_nxt[0]; -+ BUF->seqno[1] = uip_connr->snd_nxt[1]; -+ BUF->seqno[2] = uip_connr->snd_nxt[2]; -+ BUF->seqno[3] = uip_connr->snd_nxt[3]; -+ -+ BUF->proto = UIP_PROTO_TCP; -+ -+ BUF->srcport = uip_connr->lport; -+ BUF->destport = uip_connr->rport; -+ -+ BUF->srcipaddr[0] = uip_hostaddr[0]; -+ BUF->srcipaddr[1] = uip_hostaddr[1]; -+ BUF->destipaddr[0] = uip_connr->ripaddr[0]; -+ BUF->destipaddr[1] = uip_connr->ripaddr[1]; -+ -+ -+ if(uip_connr->tcpstateflags & UIP_STOPPED) { -+ /* If the connection has issued uip_stop(), we advertise a zero -+ window so that the remote host will stop sending data. */ -+ BUF->wnd[0] = BUF->wnd[1] = 0; -+ } else { -+ BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8); -+ BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff); -+ } -+ -+ tcp_send_noconn: -+ -+ BUF->len[0] = (uip_len >> 8); -+ BUF->len[1] = (uip_len & 0xff); -+ -+ /* Calculate TCP checksum. */ -+ BUF->tcpchksum = 0; -+ BUF->tcpchksum = ~(uip_tcpchksum()); -+ -+ //ip_send_nolen: -+ -+ BUF->vhl = 0x45; -+ BUF->tos = 0; -+ BUF->ipoffset[0] = BUF->ipoffset[1] = 0; -+ BUF->ttl = UIP_TTL; -+ ++ipid; -+ BUF->ipid[0] = ipid >> 8; -+ BUF->ipid[1] = ipid & 0xff; -+ -+ /* Calculate IP checksum. */ -+ BUF->ipchksum = 0; -+ BUF->ipchksum = ~(uip_ipchksum()); -+ -+ UIP_STAT(++uip_stat.tcp.sent); -+ send: -+ UIP_STAT(++uip_stat.ip.sent); -+ /* Return and let the caller do the actual transmission. */ -+ return; -+ drop: -+ uip_len = 0; -+ return; -+} -+/*-----------------------------------------------------------------------------------*/ -+/*unsigned short int -+htons(unsigned short int val) -+{ -+ return HTONS(val); -+}*/ -+/*-----------------------------------------------------------------------------------*/ -+/** @} */ ---- /dev/null -+++ b/net/uip-0.9/uip.h -@@ -0,0 +1,1066 @@ -+/** -+ * \addtogroup uip -+ * @{ -+ */ -+ -+/** -+ * \file -+ * Header file for the uIP TCP/IP stack. -+ * \author Adam Dunkels -+ * -+ * The uIP TCP/IP stack header file contains definitions for a number -+ * of C macros that are used by uIP programs as well as internal uIP -+ * structures, TCP/IP header structures and function declarations. -+ * -+ */ -+ -+ -+/* -+ * Copyright (c) 2001-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. -+ * -+ * This file is part of the uIP TCP/IP stack. -+ * -+ * $Id: uip.h,v 1.36.2.7 2003/10/07 13:47:51 adam Exp $ -+ * -+ */ -+ -+#ifndef __UIP_H__ -+#define __UIP_H__ -+#include -+#include -+#include -+#include -+#include -+ -+ -+#include "uipopt.h" -+ -+/*-----------------------------------------------------------------------------------*/ -+/* First, the functions that should be called from the -+ * system. Initialization, the periodic timer and incoming packets are -+ * handled by the following three functions. -+ */ -+ -+/** -+ * \defgroup uipconffunc uIP configuration functions -+ * @{ -+ * -+ * The uIP configuration functions are used for setting run-time -+ * parameters in uIP such as IP addresses. -+ */ -+ -+/** -+ * Set the IP address of this host. -+ * -+ * The IP address is represented as a 4-byte array where the first -+ * octet of the IP address is put in the first member of the 4-byte -+ * array. -+ * -+ * \param addr A pointer to a 4-byte representation of the IP address. -+ * -+ * \hideinitializer -+ */ -+#define uip_sethostaddr(addr) do { uip_hostaddr[0] = addr[0]; \ -+ uip_hostaddr[1] = addr[1]; } while(0) -+ -+/** -+ * Get the IP address of this host. -+ * -+ * The IP address is represented as a 4-byte array where the first -+ * octet of the IP address is put in the first member of the 4-byte -+ * array. -+ * -+ * \param addr A pointer to a 4-byte array that will be filled in with -+ * the currently configured IP address. -+ * -+ * \hideinitializer -+ */ -+#define uip_gethostaddr(addr) do { addr[0] = uip_hostaddr[0]; \ -+ addr[1] = uip_hostaddr[1]; } while(0) -+ -+/** @} */ -+ -+/** -+ * \defgroup uipinit uIP initialization functions -+ * @{ -+ * -+ * The uIP initialization functions are used for booting uIP. -+ */ -+ -+/** -+ * uIP initialization function. -+ * -+ * This function should be called at boot up to initilize the uIP -+ * TCP/IP stack. -+ */ -+void uip_init(void); -+ -+/** @} */ -+ -+/** -+ * \defgroup uipdevfunc uIP device driver functions -+ * @{ -+ * -+ * These functions are used by a network device driver for interacting -+ * with uIP. -+ */ -+ -+/** -+ * Process an incoming packet. -+ * -+ * This function should be called when the device driver has received -+ * a packet from the network. The packet from the device driver must -+ * be present in the uip_buf buffer, and the length of the packet -+ * should be placed in the uip_len variable. -+ * -+ * When the function returns, there may be an outbound packet placed -+ * in the uip_buf packet buffer. If so, the uip_len variable is set to -+ * the length of the packet. If no packet is to be sent out, the -+ * uip_len variable is set to 0. -+ * -+ * The usual way of calling the function is presented by the source -+ * code below. -+ \code -+ uip_len = devicedriver_poll(); -+ if(uip_len > 0) { -+ uip_input(); -+ if(uip_len > 0) { -+ devicedriver_send(); -+ } -+ } -+ \endcode -+ * -+ * \note If you are writing a uIP device driver that needs ARP -+ * (Address Resolution Protocol), e.g., when running uIP over -+ * Ethernet, you will need to call the uIP ARP code before calling -+ * this function: -+ \code -+ #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) -+ uip_len = ethernet_devicedrver_poll(); -+ if(uip_len > 0) { -+ if(BUF->type == HTONS(UIP_ETHTYPE_IP)) { -+ uip_arp_ipin(); -+ uip_input(); -+ if(uip_len > 0) { -+ uip_arp_out(); -+ ethernet_devicedriver_send(); -+ } -+ } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { -+ uip_arp_arpin(); -+ if(uip_len > 0) { -+ ethernet_devicedriver_send(); -+ } -+ } -+ \endcode -+ * -+ * \hideinitializer -+ */ -+#define uip_input() uip_process(UIP_DATA) -+ -+/** -+ * Periodic processing for a connection identified by its number. -+ * -+ * This function does the necessary periodic processing (timers, -+ * polling) for a uIP TCP conneciton, and should be called when the -+ * periodic uIP timer goes off. It should be called for every -+ * connection, regardless of whether they are open of closed. -+ * -+ * When the function returns, it may have an outbound packet waiting -+ * for service in the uIP packet buffer, and if so the uip_len -+ * variable is set to a value larger than zero. The device driver -+ * should be called to send out the packet. -+ * -+ * The ususal way of calling the function is through a for() loop like -+ * this: -+ \code -+ for(i = 0; i < UIP_CONNS; ++i) { -+ uip_periodic(i); -+ if(uip_len > 0) { -+ devicedriver_send(); -+ } -+ } -+ \endcode -+ * -+ * \note If you are writing a uIP device driver that needs ARP -+ * (Address Resolution Protocol), e.g., when running uIP over -+ * Ethernet, you will need to call the uip_arp_out() function before -+ * calling the device driver: -+ \code -+ for(i = 0; i < UIP_CONNS; ++i) { -+ uip_periodic(i); -+ if(uip_len > 0) { -+ uip_arp_out(); -+ ethernet_devicedriver_send(); -+ } -+ } -+ \endcode -+ * -+ * \param conn The number of the connection which is to be periodically polled. -+ * -+ * \hideinitializer -+ */ -+#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \ -+ uip_process(UIP_TIMER); } while (0) -+ -+/** -+ * Periodic processing for a connection identified by a pointer to its structure. -+ * -+ * Same as uip_periodic() but takes a pointer to the actual uip_conn -+ * struct instead of an integer as its argument. This function can be -+ * used to force periodic processing of a specific connection. -+ * -+ * \param conn A pointer to the uip_conn struct for the connection to -+ * be processed. -+ * -+ * \hideinitializer -+ */ -+#define uip_periodic_conn(conn) do { uip_conn = conn; \ -+ uip_process(UIP_TIMER); } while (0) -+ -+#if UIP_UDP -+/** -+ * Periodic processing for a UDP connection identified by its number. -+ * -+ * This function is essentially the same as uip_prerioic(), but for -+ * UDP connections. It is called in a similar fashion as the -+ * uip_periodic() function: -+ \code -+ for(i = 0; i < UIP_UDP_CONNS; i++) { -+ uip_udp_periodic(i); -+ if(uip_len > 0) { -+ devicedriver_send(); -+ } -+ } -+ \endcode -+ * -+ * \note As for the uip_periodic() function, special care has to be -+ * taken when using uIP together with ARP and Ethernet: -+ \code -+ for(i = 0; i < UIP_UDP_CONNS; i++) { -+ uip_udp_periodic(i); -+ if(uip_len > 0) { -+ uip_arp_out(); -+ ethernet_devicedriver_send(); -+ } -+ } -+ \endcode -+ * -+ * \param conn The number of the UDP connection to be processed. -+ * -+ * \hideinitializer -+ */ -+#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \ -+ uip_process(UIP_UDP_TIMER); } while (0) -+ -+/** -+ * Periodic processing for a UDP connection identified by a pointer to -+ * its structure. -+ * -+ * Same as uip_udp_periodic() but takes a pointer to the actual -+ * uip_conn struct instead of an integer as its argument. This -+ * function can be used to force periodic processing of a specific -+ * connection. -+ * -+ * \param conn A pointer to the uip_udp_conn struct for the connection -+ * to be processed. -+ * -+ * \hideinitializer -+ */ -+#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \ -+ uip_process(UIP_UDP_TIMER); } while (0) -+ -+ -+#endif /* UIP_UDP */ -+ -+/** -+ * The uIP packet buffer. -+ * -+ * The uip_buf array is used to hold incoming and outgoing -+ * packets. The device driver should place incoming data into this -+ * buffer. When sending data, the device driver should read the link -+ * level headers and the TCP/IP headers from this buffer. The size of -+ * the link level headers is configured by the UIP_LLH_LEN define. -+ * -+ * \note The application data need not be placed in this buffer, so -+ * the device driver must read it from the place pointed to by the -+ * uip_appdata pointer as illustrated by the following example: -+ \code -+ void -+ devicedriver_send(void) -+ { -+ hwsend(&uip_buf[0], UIP_LLH_LEN); -+ hwsend(&uip_buf[UIP_LLH_LEN], 40); -+ hwsend(uip_appdata, uip_len - 40 - UIP_LLH_LEN); -+ } -+ \endcode -+ */ -+extern u8_t uip_buf[UIP_BUFSIZE+2]; -+ -+/** @} */ -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Functions that are used by the uIP application program. Opening and -+ * closing connections, sending and receiving data, etc. is all -+ * handled by the functions below. -+*/ -+/** -+ * \defgroup uipappfunc uIP application functions -+ * @{ -+ * -+ * Functions used by an application running of top of uIP. -+ */ -+ -+/** -+ * Start listening to the specified port. -+ * -+ * \note Since this function expects the port number in network byte -+ * order, a conversion using HTONS() or htons() is necessary. -+ * -+ \code -+ uip_listen(HTONS(80)); -+ \endcode -+ * -+ * \param port A 16-bit port number in network byte order. -+ */ -+void uip_listen(u16_t port); -+ -+/** -+ * Stop listening to the specified port. -+ * -+ * \note Since this function expects the port number in network byte -+ * order, a conversion using HTONS() or htons() is necessary. -+ * -+ \code -+ uip_unlisten(HTONS(80)); -+ \endcode -+ * -+ * \param port A 16-bit port number in network byte order. -+ */ -+void uip_unlisten(u16_t port); -+ -+/** -+ * Connect to a remote host using TCP. -+ * -+ * This function is used to start a new connection to the specified -+ * port on the specied host. It allocates a new connection identifier, -+ * sets the connection to the SYN_SENT state and sets the -+ * retransmission timer to 0. This will cause a TCP SYN segment to be -+ * sent out the next time this connection is periodically processed, -+ * which usually is done within 0.5 seconds after the call to -+ * uip_connect(). -+ * -+ * \note This function is avaliable only if support for active open -+ * has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h. -+ * -+ * \note Since this function requires the port number to be in network -+ * byte order, a convertion using HTONS() or htons() is necessary. -+ * -+ \code -+ u16_t ipaddr[2]; -+ -+ uip_ipaddr(ipaddr, 192,168,1,2); -+ uip_connect(ipaddr, HTONS(80)); -+ \endcode -+ * -+ * \param ripaddr A pointer to a 4-byte array representing the IP -+ * address of the remote hot. -+ * -+ * \param port A 16-bit port number in network byte order. -+ * -+ * \return A pointer to the uIP connection identifier for the new connection, -+ * or NULL if no connection could be allocated. -+ * -+ */ -+struct uip_conn *uip_connect(u16_t *ripaddr, u16_t port); -+ -+ -+ -+/** -+ * \internal -+ * -+ * Check if a connection has outstanding (i.e., unacknowledged) data. -+ * -+ * \param conn A pointer to the uip_conn structure for the connection. -+ * -+ * \hideinitializer -+ */ -+#define uip_outstanding(conn) ((conn)->len) -+ -+/** -+ * Send data on the current connection. -+ * -+ * This function is used to send out a single segment of TCP -+ * data. Only applications that have been invoked by uIP for event -+ * processing can send data. -+ * -+ * The amount of data that actually is sent out after a call to this -+ * funcion is determined by the maximum amount of data TCP allows. uIP -+ * will automatically crop the data so that only the appropriate -+ * amount of data is sent. The function uip_mss() can be used to query -+ * uIP for the amount of data that actually will be sent. -+ * -+ * \note This function does not guarantee that the sent data will -+ * arrive at the destination. If the data is lost in the network, the -+ * application will be invoked with the uip_rexmit() event being -+ * set. The application will then have to resend the data using this -+ * function. -+ * -+ * \param data A pointer to the data which is to be sent. -+ * -+ * \param len The maximum amount of data bytes to be sent. -+ * -+ * \hideinitializer -+ */ -+#define uip_send(data, len) do { uip_sappdata = (data); uip_slen = (len);} while(0) -+ -+/** -+ * The length of any incoming data that is currently avaliable (if avaliable) -+ * in the uip_appdata buffer. -+ * -+ * The test function uip_data() must first be used to check if there -+ * is any data available at all. -+ * -+ * \hideinitializer -+ */ -+#define uip_datalen() uip_len -+ -+/** -+ * The length of any out-of-band data (urgent data) that has arrived -+ * on the connection. -+ * -+ * \note The configuration parameter UIP_URGDATA must be set for this -+ * function to be enabled. -+ * -+ * \hideinitializer -+ */ -+#define uip_urgdatalen() uip_urglen -+ -+/** -+ * Close the current connection. -+ * -+ * This function will close the current connection in a nice way. -+ * -+ * \hideinitializer -+ */ -+#define uip_close() (uip_flags = UIP_CLOSE) -+ -+/** -+ * Abort the current connection. -+ * -+ * This function will abort (reset) the current connection, and is -+ * usually used when an error has occured that prevents using the -+ * uip_close() function. -+ * -+ * \hideinitializer -+ */ -+#define uip_abort() (uip_flags = UIP_ABORT) -+ -+/** -+ * Tell the sending host to stop sending data. -+ * -+ * This function will close our receiver's window so that we stop -+ * receiving data for the current connection. -+ * -+ * \hideinitializer -+ */ -+#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED) -+ -+/** -+ * Find out if the current connection has been previously stopped with -+ * uip_stop(). -+ * -+ * \hideinitializer -+ */ -+#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED) -+ -+/** -+ * Restart the current connection, if is has previously been stopped -+ * with uip_stop(). -+ * -+ * This function will open the receiver's window again so that we -+ * start receiving data for the current connection. -+ * -+ * \hideinitializer -+ */ -+#define uip_restart() do { uip_flags |= UIP_NEWDATA; \ -+ uip_conn->tcpstateflags &= ~UIP_STOPPED; \ -+ } while(0) -+ -+ -+/* uIP tests that can be made to determine in what state the current -+ connection is, and what the application function should do. */ -+ -+/** -+ * Is new incoming data available? -+ * -+ * Will reduce to non-zero if there is new data for the application -+ * present at the uip_appdata pointer. The size of the data is -+ * avaliable through the uip_len variable. -+ * -+ * \hideinitializer -+ */ -+#define uip_newdata() (uip_flags & UIP_NEWDATA) -+ -+/** -+ * Has previously sent data been acknowledged? -+ * -+ * Will reduce to non-zero if the previously sent data has been -+ * acknowledged by the remote host. This means that the application -+ * can send new data. -+ * -+ * \hideinitializer -+ */ -+#define uip_acked() (uip_flags & UIP_ACKDATA) -+ -+/** -+ * Has the connection just been connected? -+ * -+ * Reduces to non-zero if the current connection has been connected to -+ * a remote host. This will happen both if the connection has been -+ * actively opened (with uip_connect()) or passively opened (with -+ * uip_listen()). -+ * -+ * \hideinitializer -+ */ -+#define uip_connected() (uip_flags & UIP_CONNECTED) -+ -+/** -+ * Has the connection been closed by the other end? -+ * -+ * Is non-zero if the connection has been closed by the remote -+ * host. The application may then do the necessary clean-ups. -+ * -+ * \hideinitializer -+ */ -+#define uip_closed() (uip_flags & UIP_CLOSE) -+ -+/** -+ * Has the connection been aborted by the other end? -+ * -+ * Non-zero if the current connection has been aborted (reset) by the -+ * remote host. -+ * -+ * \hideinitializer -+ */ -+#define uip_aborted() (uip_flags & UIP_ABORT) -+ -+/** -+ * Has the connection timed out? -+ * -+ * Non-zero if the current connection has been aborted due to too many -+ * retransmissions. -+ * -+ * \hideinitializer -+ */ -+#define uip_timedout() (uip_flags & UIP_TIMEDOUT) -+ -+/** -+ * Do we need to retransmit previously data? -+ * -+ * Reduces to non-zero if the previously sent data has been lost in -+ * the network, and the application should retransmit it. The -+ * application should send the exact same data as it did the last -+ * time, using the uip_send() function. -+ * -+ * \hideinitializer -+ */ -+#define uip_rexmit() (uip_flags & UIP_REXMIT) -+ -+/** -+ * Is the connection being polled by uIP? -+ * -+ * Is non-zero if the reason the application is invoked is that the -+ * current connection has been idle for a while and should be -+ * polled. -+ * -+ * The polling event can be used for sending data without having to -+ * wait for the remote host to send data. -+ * -+ * \hideinitializer -+ */ -+#define uip_poll() (uip_flags & UIP_POLL) -+ -+/** -+ * Get the initial maxium segment size (MSS) of the current -+ * connection. -+ * -+ * \hideinitializer -+ */ -+#define uip_initialmss() (uip_conn->initialmss) -+ -+/** -+ * Get the current maxium segment size that can be sent on the current -+ * connection. -+ * -+ * The current maxiumum segment size that can be sent on the -+ * connection is computed from the receiver's window and the MSS of -+ * the connection (which also is available by calling -+ * uip_initialmss()). -+ * -+ * \hideinitializer -+ */ -+#define uip_mss() (uip_conn->mss) -+ -+/** -+ * Set up a new UDP connection. -+ * -+ * \param ripaddr A pointer to a 4-byte structure representing the IP -+ * address of the remote host. -+ * -+ * \param rport The remote port number in network byte order. -+ * -+ * \return The uip_udp_conn structure for the new connection or NULL -+ * if no connection could be allocated. -+ */ -+struct uip_udp_conn *uip_udp_new(u16_t *ripaddr, u16_t rport); -+ -+/** -+ * Removed a UDP connection. -+ * -+ * \param conn A pointer to the uip_udp_conn structure for the connection. -+ * -+ * \hideinitializer -+ */ -+#define uip_udp_remove(conn) (conn)->lport = 0 -+ -+/** -+ * Send a UDP datagram of length len on the current connection. -+ * -+ * This function can only be called in response to a UDP event (poll -+ * or newdata). The data must be present in the uip_buf buffer, at the -+ * place pointed to by the uip_appdata pointer. -+ * -+ * \param len The length of the data in the uip_buf buffer. -+ * -+ * \hideinitializer -+ */ -+#define uip_udp_send(len) uip_slen = (len) -+ -+/** @} */ -+ -+/* uIP convenience and converting functions. */ -+ -+/** -+ * \defgroup uipconvfunc uIP conversion functions -+ * @{ -+ * -+ * These functions can be used for converting between different data -+ * formats used by uIP. -+ */ -+ -+/** -+ * Pack an IP address into a 4-byte array which is used by uIP to -+ * represent IP addresses. -+ * -+ * Example: -+ \code -+ u16_t ipaddr[2]; -+ -+ uip_ipaddr(&ipaddr, 192,168,1,2); -+ \endcode -+ * -+ * \param addr A pointer to a 4-byte array that will be filled in with -+ * the IP addres. -+ * \param addr0 The first octet of the IP address. -+ * \param addr1 The second octet of the IP address. -+ * \param addr2 The third octet of the IP address. -+ * \param addr3 The forth octet of the IP address. -+ * -+ * \hideinitializer -+ */ -+#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ -+ (addr)[0] = HTONS(((addr0) << 8) | (addr1)); \ -+ (addr)[1] = HTONS(((addr2) << 8) | (addr3)); \ -+ } while(0) -+ -+/** -+ * Convert 16-bit quantity from host byte order to network byte order. -+ * -+ * This macro is primarily used for converting constants from host -+ * byte order to network byte order. For converting variables to -+ * network byte order, use the htons() function instead. -+ * -+ * \hideinitializer -+ */ -+#ifndef HTONS -+# if BYTE_ORDER == BIG_ENDIAN -+# define HTONS(n) (n) -+# else /* BYTE_ORDER == BIG_ENDIAN */ -+# define HTONS(n) ((((u16_t)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8)) -+# endif /* BYTE_ORDER == BIG_ENDIAN */ -+#endif /* HTONS */ -+ -+/** -+ * Convert 16-bit quantity from host byte order to network byte order. -+ * -+ * This function is primarily used for converting variables from host -+ * byte order to network byte order. For converting constants to -+ * network byte order, use the HTONS() macro instead. -+ */ -+#ifndef htons -+u16_t htons(u16_t val); -+#endif /* htons */ -+ -+/** @} */ -+ -+/** -+ * Pointer to the application data in the packet buffer. -+ * -+ * This pointer points to the application data when the application is -+ * called. If the application wishes to send data, the application may -+ * use this space to write the data into before calling uip_send(). -+ */ -+extern volatile u8_t *uip_appdata; -+extern volatile u8_t *uip_sappdata; -+ -+#if UIP_URGDATA > 0 -+/* u8_t *uip_urgdata: -+ * -+ * This pointer points to any urgent data that has been received. Only -+ * present if compiled with support for urgent data (UIP_URGDATA). -+ */ -+extern volatile u8_t *uip_urgdata; -+#endif /* UIP_URGDATA > 0 */ -+ -+ -+/* u[8|16]_t uip_len: -+ * -+ * When the application is called, uip_len contains the length of any -+ * new data that has been received from the remote host. The -+ * application should set this variable to the size of any data that -+ * the application wishes to send. When the network device driver -+ * output function is called, uip_len should contain the length of the -+ * outgoing packet. -+ */ -+extern volatile u16_t uip_len, uip_slen; -+ -+#if UIP_URGDATA > 0 -+extern volatile u8_t uip_urglen, uip_surglen; -+#endif /* UIP_URGDATA > 0 */ -+ -+ -+/** -+ * Representation of a uIP TCP connection. -+ * -+ * The uip_conn structure is used for identifying a connection. All -+ * but one field in the structure are to be considered read-only by an -+ * application. The only exception is the appstate field whos purpose -+ * is to let the application store application-specific state (e.g., -+ * file pointers) for the connection. The size of this field is -+ * configured in the "uipopt.h" header file. -+ */ -+struct uip_conn { -+ u16_t ripaddr[2]; /**< The IP address of the remote host. */ -+ -+ u16_t lport; /**< The local TCP port, in network byte order. */ -+ u16_t rport; /**< The local remote TCP port, in network byte -+ order. */ -+ -+ u8_t rcv_nxt[4]; /**< The sequence number that we expect to -+ receive next. */ -+ u8_t snd_nxt[4]; /**< The sequence number that was last sent by -+ us. */ -+ u16_t len; /**< Length of the data that was previously sent. */ -+ u16_t mss; /**< Current maximum segment size for the -+ connection. */ -+ u16_t initialmss; /**< Initial maximum segment size for the -+ connection. */ -+ u8_t sa; /**< Retransmission time-out calculation state -+ variable. */ -+ u8_t sv; /**< Retransmission time-out calculation state -+ variable. */ -+ u8_t rto; /**< Retransmission time-out. */ -+ u8_t tcpstateflags; /**< TCP state and flags. */ -+ u8_t timer; /**< The retransmission timer. */ -+ u8_t nrtx; /**< The number of retransmissions for the last -+ segment sent. */ -+ -+ /** The application state. */ -+ u8_t appstate[UIP_APPSTATE_SIZE]; -+}; -+ -+ -+/* Pointer to the current connection. */ -+extern struct uip_conn *uip_conn; -+/* The array containing all uIP connections. */ -+extern struct uip_conn uip_conns[UIP_CONNS]; -+/** -+ * \addtogroup uiparch -+ * @{ -+ */ -+ -+/** -+ * 4-byte array used for the 32-bit sequence number calculations. -+ */ -+extern volatile u8_t uip_acc32[4]; -+ -+/** @} */ -+ -+ -+#if UIP_UDP -+/** -+ * Representation of a uIP UDP connection. -+ */ -+struct uip_udp_conn { -+ u16_t ripaddr[2]; /**< The IP address of the remote peer. */ -+ u16_t lport; /**< The local port number in network byte order. */ -+ u16_t rport; /**< The remote port number in network byte order. */ -+}; -+ -+extern struct uip_udp_conn *uip_udp_conn; -+extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; -+#endif /* UIP_UDP */ -+ -+/** -+ * The structure holding the TCP/IP statistics that are gathered if -+ * UIP_STATISTICS is set to 1. -+ * -+ */ -+struct uip_stats { -+ struct { -+ uip_stats_t drop; /**< Number of dropped packets at the IP -+ layer. */ -+ uip_stats_t recv; /**< Number of received packets at the IP -+ layer. */ -+ uip_stats_t sent; /**< Number of sent packets at the IP -+ layer. */ -+ uip_stats_t vhlerr; /**< Number of packets dropped due to wrong -+ IP version or header length. */ -+ uip_stats_t hblenerr; /**< Number of packets dropped due to wrong -+ IP length, high byte. */ -+ uip_stats_t lblenerr; /**< Number of packets dropped due to wrong -+ IP length, low byte. */ -+ uip_stats_t fragerr; /**< Number of packets dropped since they -+ were IP fragments. */ -+ uip_stats_t chkerr; /**< Number of packets dropped due to IP -+ checksum errors. */ -+ uip_stats_t protoerr; /**< Number of packets dropped since they -+ were neither ICMP, UDP nor TCP. */ -+ } ip; /**< IP statistics. */ -+ struct { -+ uip_stats_t drop; /**< Number of dropped ICMP packets. */ -+ uip_stats_t recv; /**< Number of received ICMP packets. */ -+ uip_stats_t sent; /**< Number of sent ICMP packets. */ -+ uip_stats_t typeerr; /**< Number of ICMP packets with a wrong -+ type. */ -+ } icmp; /**< ICMP statistics. */ -+ struct { -+ uip_stats_t drop; /**< Number of dropped TCP segments. */ -+ uip_stats_t recv; /**< Number of recived TCP segments. */ -+ uip_stats_t sent; /**< Number of sent TCP segments. */ -+ uip_stats_t chkerr; /**< Number of TCP segments with a bad -+ checksum. */ -+ uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK -+ number. */ -+ uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */ -+ uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */ -+ uip_stats_t syndrop; /**< Number of dropped SYNs due to too few -+ connections was avaliable. */ -+ uip_stats_t synrst; /**< Number of SYNs for closed ports, -+ triggering a RST. */ -+ } tcp; /**< TCP statistics. */ -+}; -+ -+/** -+ * The uIP TCP/IP statistics. -+ * -+ * This is the variable in which the uIP TCP/IP statistics are gathered. -+ */ -+extern struct uip_stats uip_stat; -+ -+ -+/*-----------------------------------------------------------------------------------*/ -+/* All the stuff below this point is internal to uIP and should not be -+ * used directly by an application or by a device driver. -+ */ -+/*-----------------------------------------------------------------------------------*/ -+/* u8_t uip_flags: -+ * -+ * When the application is called, uip_flags will contain the flags -+ * that are defined in this file. Please read below for more -+ * infomation. -+ */ -+extern volatile u8_t uip_flags; -+ -+/* The following flags may be set in the global variable uip_flags -+ before calling the application callback. The UIP_ACKDATA and -+ UIP_NEWDATA flags may both be set at the same time, whereas the -+ others are mutualy exclusive. Note that these flags should *NOT* be -+ accessed directly, but through the uIP functions/macros. */ -+ -+#define UIP_ACKDATA 1 /* Signifies that the outstanding data was -+ acked and the application should send -+ out new data instead of retransmitting -+ the last data. */ -+#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent -+ us new data. */ -+#define UIP_REXMIT 4 /* Tells the application to retransmit the -+ data that was last sent. */ -+#define UIP_POLL 8 /* Used for polling the application, to -+ check if the application has data that -+ it wants to send. */ -+#define UIP_CLOSE 16 /* The remote host has closed the -+ connection, thus the connection has -+ gone away. Or the application signals -+ that it wants to close the -+ connection. */ -+#define UIP_ABORT 32 /* The remote host has aborted the -+ connection, thus the connection has -+ gone away. Or the application signals -+ that it wants to abort the -+ connection. */ -+#define UIP_CONNECTED 64 /* We have got a connection from a remote -+ host and have set up a new connection -+ for it, or an active connection has -+ been successfully established. */ -+ -+#define UIP_TIMEDOUT 128 /* The connection has been aborted due to -+ too many retransmissions. */ -+ -+ -+/* uip_process(flag): -+ * -+ * The actual uIP function which does all the work. -+ */ -+void uip_process(u8_t flag); -+ -+/* The following flags are passed as an argument to the uip_process() -+ function. They are used to distinguish between the two cases where -+ uip_process() is called. It can be called either because we have -+ incoming data that should be processed, or because the periodic -+ timer has fired. */ -+ -+#define UIP_DATA 1 /* Tells uIP that there is incoming data in -+ the uip_buf buffer. The length of the -+ data is stored in the global variable -+ uip_len. */ -+#define UIP_TIMER 2 /* Tells uIP that the periodic timer has -+ fired. */ -+#if UIP_UDP -+#define UIP_UDP_TIMER 3 -+#endif /* UIP_UDP */ -+ -+/* The TCP states used in the uip_conn->tcpstateflags. */ -+#define CLOSED 0 -+#define SYN_RCVD 1 -+#define SYN_SENT 2 -+#define ESTABLISHED 3 -+#define FIN_WAIT_1 4 -+#define FIN_WAIT_2 5 -+#define CLOSING 6 -+#define TIME_WAIT 7 -+#define LAST_ACK 8 -+#define TS_MASK 15 -+ -+#define UIP_STOPPED 16 -+ -+#define UIP_TCPIP_HLEN 40 -+ -+/* The TCP and IP headers. */ -+typedef struct { -+ /* IP header. */ -+ u8_t vhl, -+ tos, -+ len[2], -+ ipid[2], -+ ipoffset[2], -+ ttl, -+ proto; -+ u16_t ipchksum; -+ u16_t srcipaddr[2], -+ destipaddr[2]; -+ -+ /* TCP header. */ -+ u16_t srcport, -+ destport; -+ u8_t seqno[4], -+ ackno[4], -+ tcpoffset, -+ flags, -+ wnd[2]; -+ u16_t tcpchksum; -+ u8_t urgp[2]; -+ u8_t optdata[4]; -+} uip_tcpip_hdr; -+ -+/* The ICMP and IP headers. */ -+typedef struct { -+ /* IP header. */ -+ u8_t vhl, -+ tos, -+ len[2], -+ ipid[2], -+ ipoffset[2], -+ ttl, -+ proto; -+ u16_t ipchksum; -+ u16_t srcipaddr[2], -+ destipaddr[2]; -+ /* ICMP (echo) header. */ -+ u8_t type, icode; -+ u16_t icmpchksum; -+ u16_t id, seqno; -+} uip_icmpip_hdr; -+ -+ -+/* The UDP and IP headers. */ -+typedef struct { -+ /* IP header. */ -+ u8_t vhl, -+ tos, -+ len[2], -+ ipid[2], -+ ipoffset[2], -+ ttl, -+ proto; -+ u16_t ipchksum; -+ u16_t srcipaddr[2], -+ destipaddr[2]; -+ -+ /* UDP header. */ -+ u16_t srcport, -+ destport; -+ u16_t udplen; -+ u16_t udpchksum; -+} uip_udpip_hdr; -+ -+#define UIP_PROTO_ICMP 1 -+#define UIP_PROTO_TCP 6 -+#define UIP_PROTO_UDP 17 -+ -+#if UIP_FIXEDADDR -+extern const u16_t uip_hostaddr[2]; -+#else /* UIP_FIXEDADDR */ -+extern u16_t uip_hostaddr[2]; -+#endif /* UIP_FIXEDADDR */ -+ -+#endif /* __UIP_H__ */ -+ -+ -+/** @} */ -+ ---- /dev/null -+++ b/net/uip-0.9/uip_arch.c -@@ -0,0 +1,145 @@ -+/* -+ * Copyright (c) 2001, 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. -+ * -+ * This file is part of the uIP TCP/IP stack. -+ * -+ * $Id: uip_arch.c,v 1.2.2.1 2003/10/04 22:54:17 adam Exp $ -+ * -+ */ -+ -+ -+#include "uip.h" -+#include "uip_arch.h" -+ -+#define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) -+#define IP_PROTO_TCP 6 -+ -+/*-----------------------------------------------------------------------------------*/ -+void -+uip_add32(u8_t *op32, u16_t op16) -+{ -+ -+ uip_acc32[3] = op32[3] + (op16 & 0xff); -+ uip_acc32[2] = op32[2] + (op16 >> 8); -+ uip_acc32[1] = op32[1]; -+ uip_acc32[0] = op32[0]; -+ -+ if(uip_acc32[2] < (op16 >> 8)) { -+ ++uip_acc32[1]; -+ if(uip_acc32[1] == 0) { -+ ++uip_acc32[0]; -+ } -+ } -+ -+ -+ if(uip_acc32[3] < (op16 & 0xff)) { -+ ++uip_acc32[2]; -+ if(uip_acc32[2] == 0) { -+ ++uip_acc32[1]; -+ if(uip_acc32[1] == 0) { -+ ++uip_acc32[0]; -+ } -+ } -+ } -+} -+/*-----------------------------------------------------------------------------------*/ -+u16_t -+uip_chksum(u16_t *sdata, u16_t len) -+{ -+ u16_t acc; -+ -+ for(acc = 0; len > 1; len -= 2) { -+ acc += *sdata; -+ if(acc < *sdata) { -+ /* Overflow, so we add the carry to acc (i.e., increase by -+ one). */ -+ ++acc; -+ } -+ ++sdata; -+ } -+ -+ /* add up any odd byte */ -+ if(len == 1) { -+ acc += htons(((u16_t)(*(u8_t *)sdata)) << 8); -+ if(acc < htons(((u16_t)(*(u8_t *)sdata)) << 8)) { -+ ++acc; -+ } -+ } -+ -+ return acc; -+} -+/*-----------------------------------------------------------------------------------*/ -+u16_t -+uip_ipchksum(void) -+{ -+ return uip_chksum((u16_t *)&uip_buf[UIP_LLH_LEN], 20); -+} -+/*-----------------------------------------------------------------------------------*/ -+u16_t -+uip_tcpchksum(void) -+{ -+ u16_t hsum, sum; -+ -+ -+ /* Compute the checksum of the TCP header. */ -+ hsum = uip_chksum((u16_t *)&uip_buf[20 + UIP_LLH_LEN], 20); -+ -+ /* Compute the checksum of the data in the TCP packet and add it to -+ the TCP header checksum. */ -+ sum = uip_chksum((u16_t *)uip_appdata, -+ (u16_t)(((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 40))); -+ -+ if((sum += hsum) < hsum) { -+ ++sum; -+ } -+ -+ if((sum += BUF->srcipaddr[0]) < BUF->srcipaddr[0]) { -+ ++sum; -+ } -+ if((sum += BUF->srcipaddr[1]) < BUF->srcipaddr[1]) { -+ ++sum; -+ } -+ if((sum += BUF->destipaddr[0]) < BUF->destipaddr[0]) { -+ ++sum; -+ } -+ if((sum += BUF->destipaddr[1]) < BUF->destipaddr[1]) { -+ ++sum; -+ } -+ if((sum += (u16_t)htons((u16_t)IP_PROTO_TCP)) < (u16_t)htons((u16_t)IP_PROTO_TCP)) { -+ ++sum; -+ } -+ -+ hsum = (u16_t)htons((((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - 20); -+ -+ if((sum += hsum) < hsum) { -+ ++sum; -+ } -+ -+ return sum; -+} -+/*-----------------------------------------------------------------------------------*/ ---- /dev/null -+++ b/net/uip-0.9/uip_arch.h -@@ -0,0 +1,130 @@ -+/** -+ * \defgroup uiparch Architecture specific uIP functions -+ * @{ -+ * -+ * The functions in the architecture specific module implement the IP -+ * check sum and 32-bit additions. -+ * -+ * The IP checksum calculation is the most computationally expensive -+ * operation in the TCP/IP stack and it therefore pays off to -+ * implement this in efficient assembler. The purpose of the uip-arch -+ * module is to let the checksum functions to be implemented in -+ * architecture specific assembler. -+ * -+ */ -+ -+/** -+ * \file -+ * Declarations of architecture specific functions. -+ * \author Adam Dunkels -+ */ -+ -+/* -+ * Copyright (c) 2001, 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. -+ * -+ * This file is part of the uIP TCP/IP stack. -+ * -+ * $Id: uip_arch.h,v 1.1.2.2 2003/10/06 15:10:22 adam Exp $ -+ * -+ */ -+ -+#ifndef __UIP_ARCH_H__ -+#define __UIP_ARCH_H__ -+ -+#include "uip.h" -+ -+/** -+ * Carry out a 32-bit addition. -+ * -+ * Because not all architectures for which uIP is intended has native -+ * 32-bit arithmetic, uIP uses an external C function for doing the -+ * required 32-bit additions in the TCP protocol processing. This -+ * function should add the two arguments and place the result in the -+ * global variable uip_acc32. -+ * -+ * \note The 32-bit integer pointed to by the op32 parameter and the -+ * result in the uip_acc32 variable are in network byte order (big -+ * endian). -+ * -+ * \param op32 A pointer to a 4-byte array representing a 32-bit -+ * integer in network byte order (big endian). -+ * -+ * \param op16 A 16-bit integer in host byte order. -+ */ -+void uip_add32(u8_t *op32, u16_t op16); -+ -+/** -+ * Calculate the Internet checksum over a buffer. -+ * -+ * The Internet checksum is the one's complement of the one's -+ * complement sum of all 16-bit words in the buffer. -+ * -+ * See RFC1071. -+ * -+ * \note This function is not called in the current version of uIP, -+ * but future versions might make use of it. -+ * -+ * \param buf A pointer to the buffer over which the checksum is to be -+ * computed. -+ * -+ * \param len The length of the buffer over which the checksum is to -+ * be computed. -+ * -+ * \return The Internet checksum of the buffer. -+ */ -+u16_t uip_chksum(u16_t *buf, u16_t len); -+ -+/** -+ * Calculate the IP header checksum of the packet header in uip_buf. -+ * -+ * The IP header checksum is the Internet checksum of the 20 bytes of -+ * the IP header. -+ * -+ * \return The IP header checksum of the IP header in the uip_buf -+ * buffer. -+ */ -+u16_t uip_ipchksum(void); -+ -+/** -+ * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. -+ * -+ * The TCP checksum is the Internet checksum of data contents of the -+ * TCP segment, and a pseudo-header as defined in RFC793. -+ * -+ * \note The uip_appdata pointer that points to the packet data may -+ * point anywhere in memory, so it is not possible to simply calculate -+ * the Internet checksum of the contents of the uip_buf buffer. -+ * -+ * \return The TCP checksum of the TCP segment in uip_buf and pointed -+ * to by uip_appdata. -+ */ -+u16_t uip_tcpchksum(void); -+ -+/** @} */ -+ -+#endif /* __UIP_ARCH_H__ */ ---- /dev/null -+++ b/net/uip-0.9/uip_arp.c -@@ -0,0 +1,421 @@ -+/** -+ * \addtogroup uip -+ * @{ -+ */ -+ -+/** -+ * \defgroup uiparp uIP Address Resolution Protocol -+ * @{ -+ * -+ * The Address Resolution Protocol ARP is used for mapping between IP -+ * addresses and link level addresses such as the Ethernet MAC -+ * addresses. ARP uses broadcast queries to ask for the link level -+ * address of a known IP address and the host which is configured with -+ * the IP address for which the query was meant, will respond with its -+ * link level address. -+ * -+ * \note This ARP implementation only supports Ethernet. -+ */ -+ -+/** -+ * \file -+ * Implementation of the ARP Address Resolution Protocol. -+ * \author Adam Dunkels -+ * -+ */ -+ -+/* -+ * Copyright (c) 2001-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. -+ * -+ * This file is part of the uIP TCP/IP stack. -+ * -+ * $Id: uip_arp.c,v 1.7.2.3 2003/10/06 22:42:30 adam Exp $ -+ * -+ */ -+ -+ -+#include "uip_arp.h" -+ -+struct arp_hdr { -+ struct uip_eth_hdr ethhdr; -+ u16_t hwtype; -+ u16_t protocol; -+ u8_t hwlen; -+ u8_t protolen; -+ u16_t opcode; -+ struct uip_eth_addr shwaddr; -+ u16_t sipaddr[2]; -+ struct uip_eth_addr dhwaddr; -+ u16_t dipaddr[2]; -+}; -+ -+struct ethip_hdr { -+ struct uip_eth_hdr ethhdr; -+ /* IP header. */ -+ u8_t vhl, -+ tos, -+ len[2], -+ ipid[2], -+ ipoffset[2], -+ ttl, -+ proto; -+ u16_t ipchksum; -+ u16_t srcipaddr[2], -+ destipaddr[2]; -+}; -+ -+#define ARP_REQUEST 1 -+#define ARP_REPLY 2 -+ -+#define ARP_HWTYPE_ETH 1 -+ -+struct arp_entry { -+ u16_t ipaddr[2]; -+ struct uip_eth_addr ethaddr; -+ u8_t time; -+}; -+ -+struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0, -+ UIP_ETHADDR1, -+ UIP_ETHADDR2, -+ UIP_ETHADDR3, -+ UIP_ETHADDR4, -+ UIP_ETHADDR5}}; -+ -+static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; -+static u16_t ipaddr[2]; -+static u8_t i, c; -+ -+static u8_t arptime; -+static u8_t tmpage; -+ -+#define BUF ((struct arp_hdr *)&uip_buf[0]) -+#define IPBUF ((struct ethip_hdr *)&uip_buf[0]) -+/*-----------------------------------------------------------------------------------*/ -+/** -+ * Initialize the ARP module. -+ * -+ */ -+/*-----------------------------------------------------------------------------------*/ -+void -+uip_arp_init(void) -+{ -+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { -+ memset(arp_table[i].ipaddr, 0, 4); -+ } -+} -+/*-----------------------------------------------------------------------------------*/ -+/** -+ * Periodic ARP processing function. -+ * -+ * This function performs periodic timer processing in the ARP module -+ * and should be called at regular intervals. The recommended interval -+ * is 10 seconds between the calls. -+ * -+ */ -+/*-----------------------------------------------------------------------------------*/ -+void -+uip_arp_timer(void) -+{ -+ struct arp_entry *tabptr; -+ -+ ++arptime; -+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { -+ tabptr = &arp_table[i]; -+ if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 && -+ arptime - tabptr->time >= UIP_ARP_MAXAGE) { -+ memset(tabptr->ipaddr, 0, 4); -+ } -+ } -+ -+} -+/*-----------------------------------------------------------------------------------*/ -+static void -+uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr) -+{ -+ register struct arp_entry *tabptr; -+ /* Walk through the ARP mapping table and try to find an entry to -+ update. If none is found, the IP -> MAC address mapping is -+ inserted in the ARP table. */ -+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { -+ -+ tabptr = &arp_table[i]; -+ /* Only check those entries that are actually in use. */ -+ if(tabptr->ipaddr[0] != 0 && -+ tabptr->ipaddr[1] != 0) { -+ -+ /* Check if the source IP address of the incoming packet matches -+ the IP address in this ARP table entry. */ -+ if(ipaddr[0] == tabptr->ipaddr[0] && -+ ipaddr[1] == tabptr->ipaddr[1]) { -+ -+ /* An old entry found, update this and return. */ -+ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); -+ tabptr->time = arptime; -+ -+ return; -+ } -+ } -+ } -+ -+ /* If we get here, no existing ARP table entry was found, so we -+ create one. */ -+ -+ /* First, we try to find an unused entry in the ARP table. */ -+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { -+ tabptr = &arp_table[i]; -+ if(tabptr->ipaddr[0] == 0 && -+ tabptr->ipaddr[1] == 0) { -+ break; -+ } -+ } -+ -+ /* If no unused entry is found, we try to find the oldest entry and -+ throw it away. */ -+ if(i == UIP_ARPTAB_SIZE) { -+ tmpage = 0; -+ c = 0; -+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { -+ tabptr = &arp_table[i]; -+ if(arptime - tabptr->time > tmpage) { -+ tmpage = arptime - tabptr->time; -+ c = i; -+ } -+ } -+ i = c; -+ } -+ -+ /* Now, i is the ARP table entry which we will fill with the new -+ information. */ -+ memcpy(tabptr->ipaddr, ipaddr, 4); -+ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); -+ tabptr->time = arptime; -+} -+/*-----------------------------------------------------------------------------------*/ -+/** -+ * ARP processing for incoming IP packets -+ * -+ * This function should be called by the device driver when an IP -+ * packet has been received. The function will check if the address is -+ * in the ARP cache, and if so the ARP cache entry will be -+ * refreshed. If no ARP cache entry was found, a new one is created. -+ * -+ * This function expects an IP packet with a prepended Ethernet header -+ * in the uip_buf[] buffer, and the length of the packet in the global -+ * variable uip_len. -+ */ -+/*-----------------------------------------------------------------------------------*/ -+void -+uip_arp_ipin(void) -+{ -+ uip_len -= sizeof(struct uip_eth_hdr); -+ -+ /* Only insert/update an entry if the source IP address of the -+ incoming IP packet comes from a host on the local network. */ -+ if((IPBUF->srcipaddr[0] & uip_arp_netmask[0]) != -+ (uip_hostaddr[0] & uip_arp_netmask[0])) { -+ return; -+ } -+ if((IPBUF->srcipaddr[1] & uip_arp_netmask[1]) != -+ (uip_hostaddr[1] & uip_arp_netmask[1])) { -+ return; -+ } -+ uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); -+ -+ return; -+} -+/*-----------------------------------------------------------------------------------*/ -+/** -+ * ARP processing for incoming ARP packets. -+ * -+ * This function should be called by the device driver when an ARP -+ * packet has been received. The function will act differently -+ * depending on the ARP packet type: if it is a reply for a request -+ * that we previously sent out, the ARP cache will be filled in with -+ * the values from the ARP reply. If the incoming ARP packet is an ARP -+ * request for our IP address, an ARP reply packet is created and put -+ * into the uip_buf[] buffer. -+ * -+ * When the function returns, the value of the global variable uip_len -+ * indicates whether the device driver should send out a packet or -+ * not. If uip_len is zero, no packet should be sent. If uip_len is -+ * non-zero, it contains the length of the outbound packet that is -+ * present in the uip_buf[] buffer. -+ * -+ * This function expects an ARP packet with a prepended Ethernet -+ * header in the uip_buf[] buffer, and the length of the packet in the -+ * global variable uip_len. -+ */ -+/*-----------------------------------------------------------------------------------*/ -+void -+uip_arp_arpin(void) -+{ -+ -+ if(uip_len < sizeof(struct arp_hdr)) { -+ uip_len = 0; -+ return; -+ } -+ -+ uip_len = 0; -+ -+ switch(BUF->opcode) { -+ case HTONS(ARP_REQUEST): -+ /* ARP request. If it asked for our address, we send out a -+ reply. */ -+ if(BUF->dipaddr[0] == uip_hostaddr[0] && -+ BUF->dipaddr[1] == uip_hostaddr[1]) { -+ /* The reply opcode is 2. */ -+ BUF->opcode = HTONS(2); -+ -+ memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6); -+ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); -+ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); -+ memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); -+ -+ BUF->dipaddr[0] = BUF->sipaddr[0]; -+ BUF->dipaddr[1] = BUF->sipaddr[1]; -+ BUF->sipaddr[0] = uip_hostaddr[0]; -+ BUF->sipaddr[1] = uip_hostaddr[1]; -+ -+ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); -+ uip_len = sizeof(struct arp_hdr); -+ } -+ break; -+ case HTONS(ARP_REPLY): -+ /* ARP reply. We insert or update the ARP table if it was meant -+ for us. */ -+ if(BUF->dipaddr[0] == uip_hostaddr[0] && -+ BUF->dipaddr[1] == uip_hostaddr[1]) { -+ -+ uip_arp_update(BUF->sipaddr, &BUF->shwaddr); -+ } -+ break; -+ } -+ -+ return; -+} -+/*-----------------------------------------------------------------------------------*/ -+/** -+ * Prepend Ethernet header to an outbound IP packet and see if we need -+ * to send out an ARP request. -+ * -+ * This function should be called before sending out an IP packet. The -+ * function checks the destination IP address of the IP packet to see -+ * what Ethernet MAC address that should be used as a destination MAC -+ * address on the Ethernet. -+ * -+ * If the destination IP address is in the local network (determined -+ * by logical ANDing of netmask and our IP address), the function -+ * checks the ARP cache to see if an entry for the destination IP -+ * address is found. If so, an Ethernet header is prepended and the -+ * function returns. If no ARP cache entry is found for the -+ * destination IP address, the packet in the uip_buf[] is replaced by -+ * an ARP request packet for the IP address. The IP packet is dropped -+ * and it is assumed that they higher level protocols (e.g., TCP) -+ * eventually will retransmit the dropped packet. -+ * -+ * If the destination IP address is not on the local network, the IP -+ * address of the default router is used instead. -+ * -+ * When the function returns, a packet is present in the uip_buf[] -+ * buffer, and the length of the packet is in the global variable -+ * uip_len. -+ */ -+/*-----------------------------------------------------------------------------------*/ -+void -+uip_arp_out(void) -+{ -+ struct arp_entry *tabptr; -+ /* Find the destination IP address in the ARP table and construct -+ the Ethernet header. If the destination IP addres isn't on the -+ local network, we use the default router's IP address instead. -+ -+ If not ARP table entry is found, we overwrite the original IP -+ packet with an ARP request for the IP address. */ -+ -+ /* Check if the destination address is on the local network. */ -+ if((IPBUF->destipaddr[0] & uip_arp_netmask[0]) != -+ (uip_hostaddr[0] & uip_arp_netmask[0]) || -+ (IPBUF->destipaddr[1] & uip_arp_netmask[1]) != -+ (uip_hostaddr[1] & uip_arp_netmask[1])) { -+ /* Destination address was not on the local network, so we need to -+ use the default router's IP address instead of the destination -+ address when determining the MAC address. */ -+ ipaddr[0] = uip_arp_draddr[0]; -+ ipaddr[1] = uip_arp_draddr[1]; -+ } else { -+ /* Else, we use the destination IP address. */ -+ ipaddr[0] = IPBUF->destipaddr[0]; -+ ipaddr[1] = IPBUF->destipaddr[1]; -+ } -+ -+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { -+ tabptr = &arp_table[i]; -+ if(ipaddr[0] == tabptr->ipaddr[0] && -+ ipaddr[1] == tabptr->ipaddr[1]) -+ break; -+ } -+ -+ if(i == UIP_ARPTAB_SIZE) { -+ /* The destination address was not in our ARP table, so we -+ overwrite the IP packet with an ARP request. */ -+ -+ memset(BUF->ethhdr.dest.addr, 0xff, 6); -+ memset(BUF->dhwaddr.addr, 0x00, 6); -+ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); -+ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); -+ -+ BUF->dipaddr[0] = ipaddr[0]; -+ BUF->dipaddr[1] = ipaddr[1]; -+ BUF->sipaddr[0] = uip_hostaddr[0]; -+ BUF->sipaddr[1] = uip_hostaddr[1]; -+ BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ -+ BUF->hwtype = HTONS(ARP_HWTYPE_ETH); -+ BUF->protocol = HTONS(UIP_ETHTYPE_IP); -+ BUF->hwlen = 6; -+ BUF->protolen = 4; -+ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); -+ -+ uip_appdata = &uip_buf[40 + UIP_LLH_LEN]; -+ -+ uip_len = sizeof(struct arp_hdr); -+ return; -+ } -+ -+ /* Build an ethernet header. */ -+ memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); -+ memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); -+ -+ IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); -+ -+ uip_len += sizeof(struct uip_eth_hdr); -+} -+/*-----------------------------------------------------------------------------------*/ -+ -+/** @} */ -+/** @} */ ---- /dev/null -+++ b/net/uip-0.9/uip_arp.h -@@ -0,0 +1,201 @@ -+/** -+ * \addtogroup uip -+ * @{ -+ */ -+ -+/** -+ * \addtogroup uiparp -+ * @{ -+ */ -+ -+/** -+ * \file -+ * Macros and definitions for the ARP module. -+ * \author Adam Dunkels -+ */ -+ -+ -+/* -+ * Copyright (c) 2001-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. -+ * -+ * This file is part of the uIP TCP/IP stack. -+ * -+ * $Id: uip_arp.h,v 1.3.2.2 2003/10/06 15:10:22 adam Exp $ -+ * -+ */ -+ -+#ifndef __UIP_ARP_H__ -+#define __UIP_ARP_H__ -+ -+#include "uip.h" -+ -+ -+/** -+ * Representation of a 48-bit Ethernet address. -+ */ -+struct uip_eth_addr { -+ u8_t addr[6]; -+}; -+ -+extern struct uip_eth_addr uip_ethaddr; -+ -+/** -+ * The Ethernet header. -+ */ -+struct uip_eth_hdr { -+ struct uip_eth_addr dest; -+ struct uip_eth_addr src; -+ u16_t type; -+}; -+ -+#define UIP_ETHTYPE_ARP 0x0806 -+#define UIP_ETHTYPE_IP 0x0800 -+#define UIP_ETHTYPE_IP6 0x86dd -+ -+ -+/* The uip_arp_init() function must be called before any of the other -+ ARP functions. */ -+void uip_arp_init(void); -+ -+/* The uip_arp_ipin() function should be called whenever an IP packet -+ arrives from the Ethernet. This function refreshes the ARP table or -+ inserts a new mapping if none exists. The function assumes that an -+ IP packet with an Ethernet header is present in the uip_buf buffer -+ and that the length of the packet is in the uip_len variable. */ -+void uip_arp_ipin(void); -+ -+/* The uip_arp_arpin() should be called when an ARP packet is received -+ by the Ethernet driver. This function also assumes that the -+ Ethernet frame is present in the uip_buf buffer. When the -+ uip_arp_arpin() function returns, the contents of the uip_buf -+ buffer should be sent out on the Ethernet if the uip_len variable -+ is > 0. */ -+void uip_arp_arpin(void); -+ -+/* The uip_arp_out() function should be called when an IP packet -+ should be sent out on the Ethernet. This function creates an -+ Ethernet header before the IP header in the uip_buf buffer. The -+ Ethernet header will have the correct Ethernet MAC destination -+ address filled in if an ARP table entry for the destination IP -+ address (or the IP address of the default router) is present. If no -+ such table entry is found, the IP packet is overwritten with an ARP -+ request and we rely on TCP to retransmit the packet that was -+ overwritten. In any case, the uip_len variable holds the length of -+ the Ethernet frame that should be transmitted. */ -+void uip_arp_out(void); -+ -+/* The uip_arp_timer() function should be called every ten seconds. It -+ is responsible for flushing old entries in the ARP table. */ -+void uip_arp_timer(void); -+ -+/** @} */ -+ -+/** -+ * \addtogroup uipconffunc -+ * @{ -+ */ -+ -+/** -+ * Set the default router's IP address. -+ * -+ * \param addr A pointer to a 4-byte array containing the IP address -+ * of the default router. -+ * -+ * \hideinitializer -+ */ -+#define uip_setdraddr(addr) do { uip_arp_draddr[0] = addr[0]; \ -+ uip_arp_draddr[1] = addr[1]; } while(0) -+ -+/** -+ * Set the netmask. -+ * -+ * \param addr A pointer to a 4-byte array containing the IP address -+ * of the netmask. -+ * -+ * \hideinitializer -+ */ -+#define uip_setnetmask(addr) do { uip_arp_netmask[0] = addr[0]; \ -+ uip_arp_netmask[1] = addr[1]; } while(0) -+ -+ -+/** -+ * Get the default router's IP address. -+ * -+ * \param addr A pointer to a 4-byte array that will be filled in with -+ * the IP address of the default router. -+ * -+ * \hideinitializer -+ */ -+#define uip_getdraddr(addr) do { addr[0] = uip_arp_draddr[0]; \ -+ addr[1] = uip_arp_draddr[1]; } while(0) -+ -+/** -+ * Get the netmask. -+ * -+ * \param addr A pointer to a 4-byte array that will be filled in with -+ * the value of the netmask. -+ * -+ * \hideinitializer -+ */ -+#define uip_getnetmask(addr) do { addr[0] = uip_arp_netmask[0]; \ -+ addr[1] = uip_arp_netmask[1]; } while(0) -+ -+ -+/** -+ * Specifiy the Ethernet MAC address. -+ * -+ * The ARP code needs to know the MAC address of the Ethernet card in -+ * order to be able to respond to ARP queries and to generate working -+ * Ethernet headers. -+ * -+ * \note This macro only specifies the Ethernet MAC address to the ARP -+ * code. It cannot be used to change the MAC address of the Ethernet -+ * card. -+ * -+ * \param eaddr A pointer to a struct uip_eth_addr containing the -+ * Ethernet MAC address of the Ethernet card. -+ * -+ * \hideinitializer -+ */ -+#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \ -+ uip_ethaddr.addr[1] = eaddr.addr[1];\ -+ uip_ethaddr.addr[2] = eaddr.addr[2];\ -+ uip_ethaddr.addr[3] = eaddr.addr[3];\ -+ uip_ethaddr.addr[4] = eaddr.addr[4];\ -+ uip_ethaddr.addr[5] = eaddr.addr[5];} while(0) -+ -+/** @} */ -+ -+/** -+ * \internal Internal variables that are set using the macros -+ * uip_setdraddr and uip_setnetmask. -+ */ -+extern u16_t uip_arp_draddr[2], uip_arp_netmask[2]; -+#endif /* __UIP_ARP_H__ */ -+ -+ ---- /dev/null -+++ b/net/uip-0.9/uipopt.h -@@ -0,0 +1,557 @@ -+/** -+ * \defgroup uipopt Configuration options for uIP -+ * @{ -+ * -+ * uIP is configured using the per-project configuration file -+ * "uipopt.h". This file contains all compile-time options for uIP and -+ * should be tweaked to match each specific project. The uIP -+ * distribution contains a documented example "uipopt.h" that can be -+ * copied and modified for each project. -+ */ -+ -+/** -+ * \file -+ * Configuration options for uIP. -+ * \author Adam Dunkels -+ * -+ * This file is used for tweaking various configuration options for -+ * uIP. You should make a copy of this file into one of your project's -+ * directories instead of editing this example "uipopt.h" file that -+ * comes with the uIP distribution. -+ */ -+ -+/* -+ * Copyright (c) 2001-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. -+ * -+ * This file is part of the uIP TCP/IP stack. -+ * -+ * $Id: uipopt.h,v 1.16.2.5 2003/10/07 13:22:51 adam Exp $ -+ * -+ */ -+ -+#ifndef __UIPOPT_H__ -+#define __UIPOPT_H__ -+ -+/*------------------------------------------------------------------------------*/ -+/** -+ * \defgroup uipopttypedef uIP type definitions -+ * @{ -+ */ -+ -+/** -+ * The 8-bit unsigned data type. -+ * -+ * This may have to be tweaked for your particular compiler. "unsigned -+ * char" works for most compilers. -+ */ -+typedef unsigned char u8_t; -+ -+/** -+ * The 16-bit unsigned data type. -+ * -+ * This may have to be tweaked for your particular compiler. "unsigned -+ * short" works for most compilers. -+ */ -+typedef unsigned short u16_t; -+ -+/** -+ * The statistics data type. -+ * -+ * This datatype determines how high the statistics counters are able -+ * to count. -+ */ -+typedef unsigned short uip_stats_t; -+ -+/** @} */ -+ -+/*------------------------------------------------------------------------------*/ -+ -+/** -+ * \defgroup uipoptstaticconf Static configuration options -+ * @{ -+ * -+ * These configuration options can be used for setting the IP address -+ * settings statically, but only if UIP_FIXEDADDR is set to 1. The -+ * configuration options for a specific node includes IP address, -+ * netmask and default router as well as the Ethernet address. The -+ * netmask, default router and Ethernet address are appliciable only -+ * if uIP should be run over Ethernet. -+ * -+ * All of these should be changed to suit your project. -+*/ -+ -+/** -+ * Determines if uIP should use a fixed IP address or not. -+ * -+ * If uIP should use a fixed IP address, the settings are set in the -+ * uipopt.h file. If not, the macros uip_sethostaddr(), -+ * uip_setdraddr() and uip_setnetmask() should be used instead. -+ * -+ * \hideinitializer -+ */ -+#define UIP_FIXEDADDR 0 -+ -+/** -+ * Ping IP address asignment. -+ * -+ * uIP uses a "ping" packets for setting its own IP address if this -+ * option is set. If so, uIP will start with an empty IP address and -+ * the destination IP address of the first incoming "ping" (ICMP echo) -+ * packet will be used for setting the hosts IP address. -+ * -+ * \note This works only if UIP_FIXEDADDR is 0. -+ * -+ * \hideinitializer -+ */ -+#define UIP_PINGADDRCONF 0 -+ -+#define UIP_IPADDR0 192 /**< The first octet of the IP address of -+ this uIP node, if UIP_FIXEDADDR is -+ 1. \hideinitializer */ -+#define UIP_IPADDR1 168 /**< The second octet of the IP address of -+ this uIP node, if UIP_FIXEDADDR is -+ 1. \hideinitializer */ -+#define UIP_IPADDR2 0 /**< The third octet of the IP address of -+ this uIP node, if UIP_FIXEDADDR is -+ 1. \hideinitializer */ -+#define UIP_IPADDR3 250 /**< The fourth octet of the IP address of -+ this uIP node, if UIP_FIXEDADDR is -+ 1. \hideinitializer */ -+ -+#define UIP_NETMASK0 255 /**< The first octet of the netmask of -+ this uIP node, if UIP_FIXEDADDR is -+ 1. \hideinitializer */ -+#define UIP_NETMASK1 255 /**< The second octet of the netmask of -+ this uIP node, if UIP_FIXEDADDR is -+ 1. \hideinitializer */ -+#define UIP_NETMASK2 255 /**< The third octet of the netmask of -+ this uIP node, if UIP_FIXEDADDR is -+ 1. \hideinitializer */ -+#define UIP_NETMASK3 0 /**< The fourth octet of the netmask of -+ this uIP node, if UIP_FIXEDADDR is -+ 1. \hideinitializer */ -+ -+#define UIP_DRIPADDR0 192 /**< The first octet of the IP address of -+ the default router, if UIP_FIXEDADDR is -+ 1. \hideinitializer */ -+#define UIP_DRIPADDR1 168 /**< The second octet of the IP address of -+ the default router, if UIP_FIXEDADDR is -+ 1. \hideinitializer */ -+#define UIP_DRIPADDR2 0 /**< The third octet of the IP address of -+ the default router, if UIP_FIXEDADDR is -+ 1. \hideinitializer */ -+#define UIP_DRIPADDR3 1 /**< The fourth octet of the IP address of -+ the default router, if UIP_FIXEDADDR is -+ 1. \hideinitializer */ -+ -+/** -+ * Specifies if the uIP ARP module should be compiled with a fixed -+ * Ethernet MAC address or not. -+ * -+ * If this configuration option is 0, the macro uip_setethaddr() can -+ * be used to specify the Ethernet address at run-time. -+ * -+ * \hideinitializer -+ */ -+#define UIP_FIXEDETHADDR 0 -+ -+#define UIP_ETHADDR0 0x00 /**< The first octet of the Ethernet -+ address if UIP_FIXEDETHADDR is -+ 1. \hideinitializer */ -+#define UIP_ETHADDR1 0xbd /**< The second octet of the Ethernet -+ address if UIP_FIXEDETHADDR is -+ 1. \hideinitializer */ -+#define UIP_ETHADDR2 0x3b /**< The third octet of the Ethernet -+ address if UIP_FIXEDETHADDR is -+ 1. \hideinitializer */ -+#define UIP_ETHADDR3 0x33 /**< The fourth octet of the Ethernet -+ address if UIP_FIXEDETHADDR is -+ 1. \hideinitializer */ -+#define UIP_ETHADDR4 0x05 /**< The fifth octet of the Ethernet -+ address if UIP_FIXEDETHADDR is -+ 1. \hideinitializer */ -+#define UIP_ETHADDR5 0x71 /**< The sixth octet of the Ethernet -+ address if UIP_FIXEDETHADDR is -+ 1. \hideinitializer */ -+ -+/** @} */ -+/*------------------------------------------------------------------------------*/ -+/** -+ * \defgroup uipoptip IP configuration options -+ * @{ -+ * -+ */ -+/** -+ * The IP TTL (time to live) of IP packets sent by uIP. -+ * -+ * This should normally not be changed. -+ */ -+#define UIP_TTL 255 -+ -+/** -+ * Turn on support for IP packet reassembly. -+ * -+ * uIP supports reassembly of fragmented IP packets. This features -+ * requires an additonal amount of RAM to hold the reassembly buffer -+ * and the reassembly code size is approximately 700 bytes. The -+ * reassembly buffer is of the same size as the uip_buf buffer -+ * (configured by UIP_BUFSIZE). -+ * -+ * \note IP packet reassembly is not heavily tested. -+ * -+ * \hideinitializer -+ */ -+#define UIP_REASSEMBLY 0 -+ -+/** -+ * The maximum time an IP fragment should wait in the reassembly -+ * buffer before it is dropped. -+ * -+ */ -+#define UIP_REASS_MAXAGE 40 -+ -+/** @} */ -+ -+/*------------------------------------------------------------------------------*/ -+/** -+ * \defgroup uipoptudp UDP configuration options -+ * @{ -+ * -+ * \note The UDP support in uIP is still not entirely complete; there -+ * is no support for sending or receiving broadcast or multicast -+ * packets, but it works well enough to support a number of vital -+ * applications such as DNS queries, though -+ */ -+ -+/** -+ * Toggles wether UDP support should be compiled in or not. -+ * -+ * \hideinitializer -+ */ -+#define UIP_UDP 0 -+ -+/** -+ * Toggles if UDP checksums should be used or not. -+ * -+ * \note Support for UDP checksums is currently not included in uIP, -+ * so this option has no function. -+ * -+ * \hideinitializer -+ */ -+#define UIP_UDP_CHECKSUMS 0 -+ -+/** -+ * The maximum amount of concurrent UDP connections. -+ * -+ * \hideinitializer -+ */ -+#define UIP_UDP_CONNS 10 -+ -+/** -+ * The name of the function that should be called when UDP datagrams arrive. -+ * -+ * \hideinitializer -+ */ -+#define UIP_UDP_APPCALL udp_appcall -+ -+/** @} */ -+/*------------------------------------------------------------------------------*/ -+/** -+ * \defgroup uipopttcp TCP configuration options -+ * @{ -+ */ -+ -+/** -+ * Determines if support for opening connections from uIP should be -+ * compiled in. -+ * -+ * If the applications that are running on top of uIP for this project -+ * do not need to open outgoing TCP connections, this configration -+ * option can be turned off to reduce the code size of uIP. -+ * -+ * \hideinitializer -+ */ -+#define UIP_ACTIVE_OPEN 1 -+ -+/** -+ * The maximum number of simultaneously open TCP connections. -+ * -+ * Since the TCP connections are statically allocated, turning this -+ * configuration knob down results in less RAM used. Each TCP -+ * connection requires approximatly 30 bytes of memory. -+ * -+ * \hideinitializer -+ */ -+#define UIP_CONNS 10 -+ -+/** -+ * The maximum number of simultaneously listening TCP ports. -+ * -+ * Each listening TCP port requires 2 bytes of memory. -+ * -+ * \hideinitializer -+ */ -+#define UIP_LISTENPORTS 10 -+ -+/** -+ * The size of the advertised receiver's window. -+ * -+ * Should be set low (i.e., to the size of the uip_buf buffer) is the -+ * application is slow to process incoming data, or high (32768 bytes) -+ * if the application processes data quickly. -+ * -+ * \hideinitializer -+ */ -+#define UIP_RECEIVE_WINDOW 32768 -+ -+/** -+ * Determines if support for TCP urgent data notification should be -+ * compiled in. -+ * -+ * Urgent data (out-of-band data) is a rarely used TCP feature that -+ * very seldom would be required. -+ * -+ * \hideinitializer -+ */ -+#define UIP_URGDATA 1 -+ -+/** -+ * The initial retransmission timeout counted in timer pulses. -+ * -+ * This should not be changed. -+ */ -+#define UIP_RTO 3 -+ -+/** -+ * The maximum number of times a segment should be retransmitted -+ * before the connection should be aborted. -+ * -+ * This should not be changed. -+ */ -+#define UIP_MAXRTX 8 -+ -+/** -+ * The maximum number of times a SYN segment should be retransmitted -+ * before a connection request should be deemed to have been -+ * unsuccessful. -+ * -+ * This should not need to be changed. -+ */ -+#define UIP_MAXSYNRTX 3 -+ -+/** -+ * The TCP maximum segment size. -+ * -+ * This is should not be to set to more than UIP_BUFSIZE - UIP_LLH_LEN - 40. -+ */ -+#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - 40) -+ -+/** -+ * How long a connection should stay in the TIME_WAIT state. -+ * -+ * This configiration option has no real implication, and it should be -+ * left untouched. -+ */ -+#define UIP_TIME_WAIT_TIMEOUT 120 -+ -+ -+/** @} */ -+/*------------------------------------------------------------------------------*/ -+/** -+ * \defgroup uipoptarp ARP configuration options -+ * @{ -+ */ -+ -+/** -+ * The size of the ARP table. -+ * -+ * This option should be set to a larger value if this uIP node will -+ * have many connections from the local network. -+ * -+ * \hideinitializer -+ */ -+#define UIP_ARPTAB_SIZE 8 -+ -+/** -+ * The maxium age of ARP table entries measured in 10ths of seconds. -+ * -+ * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD -+ * default). -+ */ -+#define UIP_ARP_MAXAGE 120 -+ -+/** @} */ -+ -+/*------------------------------------------------------------------------------*/ -+ -+/** -+ * \defgroup uipoptgeneral General configuration options -+ * @{ -+ */ -+ -+/** -+ * The size of the uIP packet buffer. -+ * -+ * The uIP packet buffer should not be smaller than 60 bytes, and does -+ * not need to be larger than 1500 bytes. Lower size results in lower -+ * TCP throughput, larger size results in higher TCP throughput. -+ * -+ * \hideinitializer -+ */ -+#define UIP_BUFSIZE 1500 -+ -+ -+/** -+ * Determines if statistics support should be compiled in. -+ * -+ * The statistics is useful for debugging and to show the user. -+ * -+ * \hideinitializer -+ */ -+#define UIP_STATISTICS 1 -+ -+/** -+ * Determines if logging of certain events should be compiled in. -+ * -+ * This is useful mostly for debugging. The function uip_log() -+ * must be implemented to suit the architecture of the project, if -+ * logging is turned on. -+ * -+ * \hideinitializer -+ */ -+#define UIP_LOGGING 0 -+ -+/** -+ * Print out a uIP log message. -+ * -+ * This function must be implemented by the module that uses uIP, and -+ * is called by uIP whenever a log message is generated. -+ */ -+void uip_log(char *msg); -+ -+/** -+ * The link level header length. -+ * -+ * This is the offset into the uip_buf where the IP header can be -+ * found. For Ethernet, this should be set to 14. For SLIP, this -+ * should be set to 0. -+ * -+ * \hideinitializer -+ */ -+#define UIP_LLH_LEN 14 -+ -+ -+/** @} */ -+/*------------------------------------------------------------------------------*/ -+/** -+ * \defgroup uipoptcpu CPU architecture configuration -+ * @{ -+ * -+ * The CPU architecture configuration is where the endianess of the -+ * CPU on which uIP is to be run is specified. Most CPUs today are -+ * little endian, and the most notable exception are the Motorolas -+ * which are big endian. The BYTE_ORDER macro should be changed to -+ * reflect the CPU architecture on which uIP is to be run. -+ */ -+#ifndef LITTLE_ENDIAN -+#define LITTLE_ENDIAN 3412 -+#endif /* LITTLE_ENDIAN */ -+#ifndef BIG_ENDIAN -+#define BIG_ENDIAN 1234 -+#endif /* BIGE_ENDIAN */ -+ -+/** -+ * The byte order of the CPU architecture on which uIP is to be run. -+ * -+ * This option can be either BIG_ENDIAN (Motorola byte order) or -+ * LITTLE_ENDIAN (Intel byte order). -+ * -+ * \hideinitializer -+ */ -+/*#ifndef BYTE_ORDER*/ -+#define BYTE_ORDER BIG_ENDIAN -+/*#endif*/ /* BYTE_ORDER */ -+ -+/** @} */ -+/*------------------------------------------------------------------------------*/ -+ -+/** -+ * \defgroup uipoptapp Appication specific configurations -+ * @{ -+ * -+ * An uIP application is implemented using a single application -+ * function that is called by uIP whenever a TCP/IP event occurs. The -+ * name of this function must be registered with uIP at compile time -+ * using the UIP_APPCALL definition. -+ * -+ * uIP applications can store the application state within the -+ * uip_conn structure by specifying the size of the application -+ * structure with the UIP_APPSTATE_SIZE macro. -+ * -+ * The file containing the definitions must be included in the -+ * uipopt.h file. -+ * -+ * The following example illustrates how this can look. -+ \code -+ -+void httpd_appcall(void); -+#define UIP_APPCALL httpd_appcall -+ -+struct httpd_state { -+ u8_t state; -+ u16_t count; -+ char *dataptr; -+ char *script; -+}; -+#define UIP_APPSTATE_SIZE (sizeof(struct httpd_state)) -+ \endcode -+ */ -+ -+/** -+ * \var #define UIP_APPCALL -+ * -+ * The name of the application function that uIP should call in -+ * response to TCP/IP events. -+ * -+ */ -+ -+/** -+ * \var #define UIP_APPSTATE_SIZE -+ * -+ * The size of the application state that is to be stored in the -+ * uip_conn structure. -+ */ -+/** @} */ -+ -+/* Include the header file for the application program that should be -+ used. If you don't use the example web server, you should change -+ this. */ -+#include "httpd.h" -+ -+ -+#endif /* __UIPOPT_H__ */ diff --git a/package/uboot-lantiq/patches/310-fix-httpd.patch b/package/uboot-lantiq/patches/310-fix-httpd.patch deleted file mode 100644 index b27ed5859a..0000000000 --- a/package/uboot-lantiq/patches/310-fix-httpd.patch +++ /dev/null @@ -1,530 +0,0 @@ ---- a/board/infineon/easy50712/danube.c -+++ b/board/infineon/easy50712/danube.c -@@ -354,7 +354,7 @@ int do_http_upgrade(const unsigned char - } - /* write the image to the flash */ - puts("http ugrade ...\n"); -- sprintf(buf, "era ${kernel_addr} +0x%x; cp.b ${ram_addr} ${kernel_addr} 0x%x", size, size); -+ sprintf(buf, "era ${kernel_addr} +0x%lx; cp.b ${ram_addr} ${kernel_addr} 0x%lx", size, size); - return run_command(buf, 0); - } - ---- a/common/main.c -+++ b/common/main.c -@@ -273,6 +273,10 @@ static __inline__ int abortboot(int boot - - void main_loop (void) - { -+#ifdef CONFIG_CMD_HTTPD -+ int ret; -+#endif -+ - #ifndef CONFIG_SYS_HUSH_PARSER - static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, }; - int len; -@@ -403,12 +407,22 @@ void main_loop (void) - # endif - - # ifndef CONFIG_SYS_HUSH_PARSER -- run_command (s, 0); -+ ret = run_command (s, 0); - # else -- parse_string_outer(s, FLAG_PARSE_SEMICOLON | -+ ret = parse_string_outer(s, FLAG_PARSE_SEMICOLON | - FLAG_EXIT_FROM_LOOP); - # endif - -+# ifdef CONFIG_CMD_HTTPD -+ if (ret != 0) { -+ printf("Failed to execute bootcmd " -+ "(maybe invalid u-boot environment?), " -+ "starting httpd to update firmware...\n"); -+ NetLoopHttpd(); -+ } -+# endif -+ -+ - # ifdef CONFIG_AUTOBOOT_KEYED - disable_ctrlc(prev); /* restore Control C checking */ - # endif ---- a/include/configs/easy50712.h -+++ b/include/configs/easy50712.h -@@ -114,4 +114,7 @@ - - #define CONFIG_CMD_HTTPD /* enable upgrade via HTTPD */ - -+#define CONFIG_IPADDR 192.168.0.119 -+#define CONFIG_ETHADDR 00:01:02:03:04:05 -+ - #endif /* __CONFIG_H */ ---- a/lib_mips/time.c -+++ b/lib_mips/time.c -@@ -29,6 +29,8 @@ static unsigned long timestamp; - /* how many counter cycles in a jiffy */ - #define CYCLES_PER_JIFFY (CONFIG_SYS_MIPS_TIMER_FREQ + CONFIG_SYS_HZ / 2) / CONFIG_SYS_HZ - -+unsigned long ifx_get_cpuclk(void); -+ - /* - * timer without interrupts - */ ---- a/net/httpd.c -+++ b/net/httpd.c -@@ -35,12 +35,14 @@ HttpdHandler (void) - } - } - -+#if 0 - static void - HttpdTimeout (void) - { - puts ("T "); - NetSetTimeout (TIMEOUT * 1000, HttpdTimeout); - } -+#endif - - void - HttpdStart (void) ---- a/net/net.c -+++ b/net/net.c -@@ -1966,7 +1966,7 @@ NetSendHttpd(void) - void - NetReceiveHttpd(volatile uchar * inpkt, int len) - { -- memcpy(uip_buf, inpkt, len); -+ memcpy(uip_buf, (const void *)inpkt, len); - uip_len = len; - if(BUF->type == htons(UIP_ETHTYPE_IP)) { - uip_arp_ipin(); -@@ -1989,6 +1989,7 @@ NetLoopHttpd(void) - unsigned long long tout = 0; - bd_t *bd = gd->bd; - unsigned short int ip[2]; -+ struct uip_eth_addr eaddr; - - #ifdef CONFIG_NET_MULTI - NetRestarted = 0; -@@ -2039,6 +2040,15 @@ restart: - eth_getenv_enetaddr("ethaddr", NetOurEther); - #endif - -+ eaddr.addr[0] = NetOurEther[0]; -+ eaddr.addr[1] = NetOurEther[1]; -+ eaddr.addr[2] = NetOurEther[2]; -+ eaddr.addr[3] = NetOurEther[3]; -+ eaddr.addr[4] = NetOurEther[4]; -+ eaddr.addr[5] = NetOurEther[5]; -+ -+ uip_setethaddr(eaddr); -+ - NetCopyIP(&NetOurIP, &bd->bi_ip_addr); - NetOurGatewayIP = getenv_IPaddr ("gatewayip"); - NetOurSubnetMask= getenv_IPaddr ("netmask"); -@@ -2072,6 +2082,14 @@ restart: - tout = t1; - } - } -+ -+ if (ctrlc()) { -+ eth_halt(); -+ puts ("\nAbort\n"); -+ return (-1); -+ } -+ -+ - if(!httpd_upload_complete) - continue; - printf("Bytes transferred = %ld (%lx hex)\n", ---- a/net/uip-0.9/fsdata.c -+++ b/net/uip-0.9/fsdata.c -@@ -1,199 +1,108 @@ --static const char data_flashing_html[] = { -- /* /flashing.html */ -- 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, -- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, -- 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, -- 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, -- 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, -- 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, -- 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, -- 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, -- 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, -- 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, -- 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c, 0x62, -- 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3d, -- 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, -- 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x20, 0x68, -- 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x31, 0x30, 0x30, 0x25, -- 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, -- 0x66, 0x66, 0x66, 0x3b, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, -- 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, -- 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, 0x62, 0x30, 0x33, 0x34, -- 0x3b, 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, -- 0x3e, 0x3c, 0x68, 0x31, 0x3e, 0x55, 0x70, 0x67, 0x72, 0x61, -- 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, -- 0x6d, 0x20, 0x2e, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f, 0x68, 0x31, -- 0x3e, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, -- 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, -- 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; -- --static const char data_fail_html[] = { -- /* /fail.html */ -- 0x2f, 0x66, 0x61, 0x69, 0x6c, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, -- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, -- 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, -- 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, -- 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, -- 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, -- 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, -- 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, -- 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, -- 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, -- 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, -- 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, -- 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, -- 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, -- 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, -- 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, -- 0x3e, 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, -- 0x9, 0x9, 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73, -- 0x68, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, -- 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9, 0x45, -- 0x52, 0x52, 0x4f, 0x52, 0x20, 0x2d, 0x20, 0x74, 0x68, 0x65, -- 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x79, 0x6f, 0x75, -- 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x20, -- 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, -- 0x70, 0x61, 0x73, 0x73, 0x20, 0x76, 0x65, 0x72, 0x69, 0x66, -- 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x50, -- 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x6d, 0x61, 0x6b, 0x65, -- 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x75, -- 0x73, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x66, 0x66, 0x69, -- 0x63, 0x69, 0x61, 0x6c, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, -- 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, -- 0x20, 0x62, 0x79, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, -- 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, -- 0x66, 0x6f, 0x6e, 0x6f, 0x73, 0x66, 0x65, 0x72, 0x61, 0x2e, -- 0x6f, 0x72, 0x67, 0x2f, 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f, -- 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, -- 0x3e, 0xa, }; -- --static const char data_404_html[] = { -- /* /404.html */ -- 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, -- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x34, -- 0x30, 0x34, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, -- 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0xd, 0xa, 0x53, -- 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, -- 0x2f, 0x30, 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, -- 0x3a, 0x2f, 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, -- 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, -- 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, -- 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, -- 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, -- 0xd, 0xa, 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, -- 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, -- 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, -- 0x22, 0x3e, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, -- 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, 0x20, -- 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, -- 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0x3c, -- 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, 0x3c, 0x2f, -- 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d, -- 0x6c, 0x3e, }; -- --static const char data_index_html[] = { -- /* /index.html */ -- 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, -- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, -- 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, -- 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, -- 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, -- 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, -- 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, -- 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, -- 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, -- 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, -- 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, -- 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, -- 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, -- 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, -- 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, -- 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, -- 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, -- 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, -- 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, -- 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, -- 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, -- 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, -- 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62, -- 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, -- 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, -- 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9, -- 0x3c, 0x68, 0x31, 0x3e, 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, -- 0x72, 0x61, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, -- 0x65, 0x20, 0x55, 0x49, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, -- 0x9, 0x9, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x65, -- 0x74, 0x68, 0x6f, 0x64, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x74, -- 0x22, 0x20, 0x65, 0x6e, 0x63, 0x74, 0x79, 0x70, 0x65, 0x3d, -- 0x22, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x61, 0x72, 0x74, -- 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x64, 0x61, 0x74, 0x61, -- 0x22, 0x3e, 0xa, 0x9, 0x9, 0x9, 0x3c, 0x69, 0x6e, 0x70, -- 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, -- 0x6c, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x66, 0x69, -- 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x3e, 0xa, 0x9, 0x9, -- 0x9, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, -- 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x3e, -- 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e, -- 0xa, 0x9, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, -- 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; -- --static const char data_flash_html[] = { -- /* /flash.html */ -- 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, -- 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, -- 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, -- 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x30, -- 0x2e, 0x39, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, -- 0x2f, 0x64, 0x75, 0x6e, 0x6b, 0x65, 0x6c, 0x73, 0x2e, 0x63, -- 0x6f, 0x6d, 0x2f, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, -- 0x70, 0x2f, 0x29, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x74, 0x65, -- 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, -- 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, -- 0xd, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x9, -- 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, -- 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x9, -- 0x4c, 0x61, 0x46, 0x6f, 0x6e, 0x65, 0x72, 0x61, 0x20, 0x46, -- 0x61, 0x69, 0x6c, 0x73, 0x61, 0x66, 0x65, 0x20, 0x55, 0x49, -- 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, -- 0x3e, 0xa, 0x9, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, -- 0xa, 0x9, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x73, 0x74, -- 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, -- 0x6e, 0x3a, 0x20, 0x30, 0x70, 0x74, 0x20, 0x61, 0x75, 0x74, -- 0x6f, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, -- 0x31, 0x30, 0x30, 0x25, 0x3b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, -- 0x72, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x62, -- 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, -- 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, -- 0x62, 0x30, 0x33, 0x34, 0x3b, 0x22, 0x3e, 0xa, 0x9, 0x9, -- 0x3c, 0x68, 0x31, 0x3e, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x69, -- 0x6e, 0x67, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x9, 0x9, -- 0x54, 0x68, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, -- 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x72, -- 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x6c, -- 0x61, 0x73, 0x68, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, -- 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x70, -- 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x2c, 0x20, 0x74, 0x68, -- 0x65, 0x20, 0x6c, 0x65, 0x64, 0x73, 0x20, 0x77, 0x69, 0x6c, -- 0x6c, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x6f, -- 0x20, 0x62, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0xa, 0xa, 0x9, -- 0x9, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, 0x61, 0x20, 0x73, -- 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x6c, -- 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, -- 0x65, 0x20, 0x62, 0x6f, 0x78, 0x20, 0x77, 0x69, 0x6c, 0x6c, -- 0x20, 0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0xa, 0x9, 0x3c, -- 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, -- 0x74, 0x6d, 0x6c, 0x3e, 0xa, }; -- --const struct fsdata_file file_flashing_html[] = {{NULL, data_flashing_html, data_flashing_html + 15, sizeof(data_flashing_html) - 15}}; -+static const char data_flashing_html[] = -+"HTTP/1.0 200 OK\n" -+"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n" -+"Content-type: text/html\n" -+"\n" -+"\n" -+"\t\n" -+"\t\t\n" -+"\t\t\tFailsafe UI\n" -+"\t\t\n" -+"\t\n" -+"\t\n" -+"\t\t

Upgrading system...

\n" -+"\t\n" -+"\n"; -+ -+static const char data_fail_html[] = -+"HTTP/1.0 200 OK\n" -+"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n" -+"Content-type: text/html\n" -+"\n" -+"\n" -+"\t\n" -+"\t\t\n" -+"\t\t\tFailsafe UI\n" -+"\t\t\n" -+"\t\n" -+"\t\n" -+"\t\t

Flashing failed

\n" -+"\t\tERROR - the image you uploaded failed to pass verification.
\n" -+"\t\tPlease make sure to use an official update provided by http://lantiq.com/\n" -+"\t\n" -+"\n"; -+ -+static const char data_404_html[] = -+"HTTP/1.0 404 File not found\n" -+"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n" -+"Content-type: text/html\n" -+"\n" -+"\n" -+"\t\n" -+"\t\t\n" -+"\t\t\tFailsafe UI\n" -+"\t\t\n" -+"\t\n" -+"\t\n" -+"\t\t

404 - file not found

\n" -+"\t\n" -+"\n"; -+ -+static const char data_index_html[] = -+"HTTP/1.0 200 OK\n" -+"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n" -+"Content-type: text/html\n" -+"\n" -+"\n" -+"\t\n" -+"\t\t\n" -+"\t\t\tFailsafe UI\n" -+"\t\t\n" -+"\t\n" -+"\t\n" -+"\t\t

Failsafe UI

\n" -+"\t\t
\n" -+"\t\t\t\n" -+"\t\t\t\n" -+"\t\t
\n" -+"\t\n" -+"\n"; -+ -+static const char data_flash_html[] = -+"HTTP/1.0 200 OK\n" -+"Server: uIP/0.9 (http://dunkels.com/adam/uip/)\n" -+"Content-type: text/html\n" -+"\n" -+"\n" -+"\t\n" -+"\t\t\n" -+"\t\t\tFailsafe UI\n" -+"\t\t\n" -+"\t\n" -+"\t\n" -+"\t\t

Flashing...

\n" -+"\t\tThe system is now trying to flash. If there is a problem, the LEDs will " -+"start to blink.
\n" -+"\n" -+"\t\tAfter a successful update the box will reboot\n" -+"\t\n" -+"\n"; -+ -+const struct fsdata_file file_flashing_html[] = -+{{NULL, "/flashing.html", data_flashing_html, sizeof(data_flashing_html)}}; -+ -+const struct fsdata_file file_fail_html[] = -+{{file_flashing_html, "/fail.html", data_fail_html, sizeof(data_fail_html)}}; - --const struct fsdata_file file_fail_html[] = {{file_flashing_html, data_fail_html, data_fail_html + 11, sizeof(data_fail_html) - 11}}; -+const struct fsdata_file file_404_html[] = -+{{file_fail_html, "/404.html", data_404_html, sizeof(data_404_html)}}; - --const struct fsdata_file file_404_html[] = {{file_fail_html, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}}; -+const struct fsdata_file file_index_html[] = -+{{file_404_html, "/index.html", data_index_html, sizeof(data_index_html)}}; - --const struct fsdata_file file_index_html[] = {{file_404_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}}; -- --const struct fsdata_file file_flash_html[] = {{file_index_html, data_flash_html, data_flash_html + 12, sizeof(data_flash_html) - 12}}; -+const struct fsdata_file file_flash_html[] = -+{{file_index_html, "/flash.html", data_flash_html, sizeof(data_flash_html)}}; - - #define FS_ROOT file_flash_html - --#define FS_NUMFILES 5 -\ No newline at end of file -+#define FS_NUMFILES 5 ---- a/net/uip-0.9/httpd.c -+++ b/net/uip-0.9/httpd.c -@@ -130,7 +130,7 @@ httpd_appcall(void) - if(!fs_open((const char *)&uip_appdata[4], &fsfile)) - { - PRINTLN("couldn't open file"); -- fs_open(file_index_html.name, &fsfile); -+ fs_open(file_404_html.name, &fsfile); - } - } - hs->script = 0; -@@ -141,7 +141,7 @@ httpd_appcall(void) - if(hs->state == HTTP_FIRMWARE) - { - unsigned char *start = (unsigned char*)uip_appdata; -- char *clen = strstr(start, "Content-Length:"); -+ char *clen = strstr((char *)start, "Content-Length:"); - int len = 0; - unsigned char *next, *end; - unsigned char *boundary_start; -@@ -150,14 +150,14 @@ httpd_appcall(void) - if(clen) - { - clen += sizeof("Content-Length:"); -- next = strstr(clen, eol); -+ next = (unsigned char *)strstr(clen, eol); - if(next) - { - len = atoi(clen); - next++; - printf("expecting %d bytes\n", len); - upload_data = httpd_upload_data = (unsigned char *)do_http_tmp_address(); -- printf("received data will be stored at 0x%08X\n", upload_data); -+ printf("received data will be stored at %p\n", upload_data); - if(!upload_data) - { - printf("failed to allocate memory\n"); -@@ -174,14 +174,14 @@ httpd_appcall(void) - uip_close(); - return; - } -- boundary_start = strstr(next, "---"); -+ boundary_start = (unsigned char *)strstr((char *)next, "---"); - if(!boundary_start) - { - uip_close(); - return; - } -- end = strstr(boundary_start, eol); -- if(!eol) -+ end = (unsigned char *)strstr((char *)boundary_start, eol); -+ if(!end) - { - uip_close(); - return; -@@ -189,13 +189,13 @@ httpd_appcall(void) - boundary_len = end - boundary_start; - memcpy(boundary, boundary_start, boundary_len); - boundary[boundary_len] = 0; -- next = strstr(boundary_start, "name=\"firmware\";"); -+ next = (unsigned char *)strstr((char *)boundary_start, "name=\"firmware\";"); - if(!next) - { - uip_close(); - return; - } -- next = strstr(next, eol2); -+ next = (unsigned char *)strstr((char *)next, eol2); - if(!next) - { - printf("could not find start of data\n"); -@@ -259,7 +259,6 @@ httpd_appcall(void) - { - if(upload_running) - { -- int i; - httpd_upload_complete = 1; - // for(i = 0; i < hs->upload_total; i++) - // printf("%c", httpd_upload_data[i]); -@@ -267,7 +266,7 @@ httpd_appcall(void) - uip_close(); - } - } -- uip_send(hs->dataptr, hs->count); -+ uip_send((unsigned char *)hs->dataptr, hs->count); - } - break; - diff --git a/package/uboot-lantiq/patches/500-arcadyan.patch b/package/uboot-lantiq/patches/500-arcadyan.patch deleted file mode 100644 index 24ee042159..0000000000 --- a/package/uboot-lantiq/patches/500-arcadyan.patch +++ /dev/null @@ -1,93 +0,0 @@ ---- a/common/Makefile -+++ b/common/Makefile -@@ -127,7 +127,9 @@ - ifdef CONFIG_PCI - COBJS-$(CONFIG_CMD_PCI) += cmd_pci.o - endif -+ifdef CONFIG_CMD_PCMCIA - COBJS-y += cmd_pcmcia.o -+endif - COBJS-$(CONFIG_CMD_PORTIO) += cmd_portio.o - COBJS-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o - COBJS-$(CONFIG_CMD_REISER) += cmd_reiser.o ---- a/drivers/pcmcia/Makefile -+++ b/drivers/pcmcia/Makefile -@@ -28,9 +28,11 @@ - COBJS-$(CONFIG_I82365) += i82365.o - COBJS-$(CONFIG_8xx) += mpc8xx_pcmcia.o - COBJS-$(CONFIG_PXA_PCMCIA) += pxa_pcmcia.o --COBJS-y += rpx_pcmcia.o -+#COBJS-y += rpx_pcmcia.o -+COBJS-$(CONFIG_RPX_PCMCIA) += rpx_pcmcia.o - COBJS-$(CONFIG_IDE_TI_CARDBUS) += ti_pci1410a.o --COBJS-y += tqm8xx_pcmcia.o -+#COBJS-y += tqm8xx_pcmcia.o -+COBJS-$(CONFIG_TQM8XX_PCMCIA) += tqm8xx_pcmcia.o - COBJS-$(CONFIG_MARUBUN_PCCARD) += marubun_pcmcia.o - - COBJS := $(COBJS-y) ---- a/drivers/usb/phy/Makefile -+++ b/drivers/usb/phy/Makefile -@@ -23,7 +23,7 @@ - LIB := $(obj)libusb_phy.a - - COBJS-$(CONFIG_TWL4030_USB) += twl4030.o --COBJS-y := twl4030.o -+#COBJS-y := twl4030.o - - COBJS := $(COBJS-y) - SRCS := $(COBJS:.o=.c) ---- a/Makefile -+++ b/Makefile -@@ -3414,6 +3414,37 @@ - ## MIPS32 ifxcpe - ######################################################################### - -+define arcadyan -+$(1) : unconfig -+ @mkdir -p $(obj)include -+ @mkdir -p $(obj)board/arcadyan/ -+ @[ -z "$$(findstring brnboot,$$@)" ] || \ -+ { echo "TEXT_BASE = 0x80002000" >$(obj)board/arcadyan/config.tmp ; \ -+ echo "#define CONFIG_SYS_RAMBOOT" >>$(obj)include/config.h ; \ -+ echo "#define CONFIG_SYS_BRNBOOT" >>$(obj)include/config.h ; \ -+ $(XECHO) "... with brnboot configuration" ; \ -+ } -+ @[ -z "$$(findstring ramboot,$$@)" ] || \ -+ { echo "TEXT_BASE = 0xA0400000" >$(obj)board/arcadyan/config.tmp ; \ -+ echo "#define CONFIG_SYS_RAMBOOT" >>$(obj)include/config.h ; \ -+ $(XECHO) "... with ramboot configuration" ; \ -+ } -+ @if [ "$$(findstring flash,$$@)" ] ; then \ -+ echo "#define CONFIG_USE_DDR_RAM" >>$(obj)include/config.h ; \ -+ echo "#define CONFIG_USE_DDR_RAM_CFG_psc166" >>$(obj)include/config.h ; \ -+ fi -+ @$(MKCONFIG) -a $$(word 1,$$(subst _, ,$$@)) mips mips arcadyan "" danube -+endef -+ -+$(eval $(call arcadyan, arv4520PW%config)) -+$(eval $(call arcadyan, arv452CPW%config)) -+$(eval $(call arcadyan, arv4525PW%config)) -+$(eval $(call arcadyan, arv4510PW%config)) -+$(eval $(call arcadyan, arv4518PW%config)) -+$(eval $(call arcadyan, arv7518PW%config)) -+$(eval $(call arcadyan, arv752DPW%config)) -+$(eval $(call arcadyan, arv752DPW22%config)) -+ - easy50712%config : unconfig - @mkdir -p $(obj)include - @mkdir -p $(obj)board/infineon/easy50712 ---- a/net/tftp.c -+++ b/net/tftp.c -@@ -11,9 +11,9 @@ - #include "bootp.h" - - #define WELL_KNOWN_PORT 69 /* Well known TFTP port # */ --#define TIMEOUT 5000UL /* Millisecs to timeout for lost pkt */ -+#define TIMEOUT 10000UL /* Millisecs to timeout for lost pkt */ - #ifndef CONFIG_NET_RETRY_COUNT --# define TIMEOUT_COUNT 10 /* # of timeouts before giving up */ -+# define TIMEOUT_COUNT 200 /* # of timeouts before giving up */ - #else - # define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT * 2) - #endif