Browse Source

add docker tester

currently a bit buggy, will work on this
pull/26/head
Philipp Toelke 4 years ago
parent
commit
881fe232d1
  1. 11
      README.md
  2. 31
      test-in-docker/Dockerfile
  3. 1
      test-in-docker/lwip-include/arch/bpstruct.h
  4. 106
      test-in-docker/lwip-include/arch/cc.h
  5. 1
      test-in-docker/lwip-include/arch/epstruct.h
  6. 4
      test-in-docker/lwip-include/arch/sys_arch.h
  7. 31
      test-in-docker/lwip-include/lwipopts.h
  8. 100
      test-in-docker/lwip-include/sys_arch.c
  9. 28
      test-in-docker/src/CMakeLists.txt
  10. 190
      test-in-docker/src/main.c

11
README.md

@ -1,5 +1,4 @@
FTP server for lwip and tinyfatfs # FTP server for lwip and tinyfatfs
=================================
This repository contains the ftp-server for lwip Copyright (c) 2002 Florian This repository contains the ftp-server for lwip Copyright (c) 2002 Florian
Schulze and an API translation layer Copyright (c) 2013 Philipp Tölke. Schulze and an API translation layer Copyright (c) 2013 Philipp Tölke.
@ -18,3 +17,11 @@ The translation-layer
All code in this repository is licensed under a 3-clause BSD license All code in this repository is licensed under a 3-clause BSD license
Patches, comments and pull-requests are welcome. Patches, comments and pull-requests are welcome.
## To build a docker container for testing
```
docker build -f test-in-docker\Dockerfile -t lwip-ftpd-test .
```
It will start lwip running on IP `172.17.0.5`, be sure to change that if it is not your docker network. You can then access ftp by dialing that address. It uses a file called `/app/data` as backing store, you can mount that in, if needed. The tester will `mkfs` when there is no file-system in that file.

31
test-in-docker/Dockerfile

@ -0,0 +1,31 @@
FROM debian:10 AS builder
RUN apt update && apt install -y unzip libpcap-dev build-essential git cmake && rm -rf /var/lib/dpkg/lists/*
WORKDIR /src
RUN git clone https://git.savannah.nongnu.org/git/lwip.git
RUN git clone https://github.com/toelke/lwip-ftpd.git
COPY . lwip-ftpd
ADD http://elm-chan.org/fsw/ff/arc/ff14.zip .
RUN unzip -q ff14.zip -d ff
RUN sed -i -e 's/FF_FS_RPATH[ ]*0/FF_FS_RPATH 2/;s/FF_USE_MKFS[ ]*0/FF_USE_MKFS 1/;' ff/source/ffconf.h
WORKDIR /build
RUN cmake /src/lwip-ftpd/test-in-docker/src && make -j
FROM debian:10 AS runner
RUN apt update && apt install -y libpcap0.8 valgrind && rm -rf /var/lib/dpkg/lists/*
WORKDIR /app
COPY --from=builder /build/lwip-runner .
CMD valgrind /app/lwip-runner

1
test-in-docker/lwip-include/arch/bpstruct.h

@ -0,0 +1 @@
#pragma pack(push,1)

106
test-in-docker/lwip-include/arch/cc.h

@ -0,0 +1,106 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_ARCH_CC_H
#define LWIP_ARCH_CC_H
#include <stdio.h> /* printf, fflush, FILE */
#include <stdlib.h> /* abort */
#include <limits.h>
#include <stdint.h>
#ifdef _MSC_VER
#pragma warning (disable: 4127) /* conditional expression is constant */
#pragma warning (disable: 4996) /* 'strncpy' was declared deprecated */
#pragma warning (disable: 4103) /* structure packing changed by including file */
#pragma warning (disable: 4820) /* 'x' bytes padding added after data member 'y' */
#endif
//#define LWIP_PROVIDE_ERRNO
/* Define platform endianness (might already be defined) */
#ifndef BYTE_ORDER
#define BYTE_ORDER LITTLE_ENDIAN
#endif /* BYTE_ORDER */
/* Define generic types used in lwIP */
typedef uint8_t u8_t;
typedef int8_t s8_t;
typedef uint16_t u16_t;
typedef int16_t s16_t;
typedef uint32_t u32_t;
typedef int32_t s32_t;
typedef size_t mem_ptr_t;
typedef u32_t sys_prot_t;
/* Define (sn)printf formatters for these lwIP types */
#define X8_F "02x"
#define U16_F "hu"
#define U32_F "lu"
#define S32_F "ld"
#define X32_F "lx"
#ifdef __GNUC__
#define S16_F "d"
#define X16_F "uX"
#define SZT_F "u"
#else
#define S16_F "hd"
#define X16_F "hx"
#define SZT_F "lu"
#endif
/* Compiler hints for packing structures */
#define PACK_STRUCT_STRUCT
#define PACK_STRUCT_USE_INCLUDES
/* Plaform specific diagnostic output */
#define LWIP_PLATFORM_DIAG(x) do { printf x; } while(0)
#define LWIP_PLATFORM_ASSERT(x) do { printf("Assertion \"%s\" failed at line %d in %s\n", \
x, __LINE__, __FILE__); fflush(NULL); abort(); } while(0)
#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
printf("Assertion \"%s\" failed at line %d in %s\n", message, __LINE__, __FILE__); \
fflush(NULL);handler;} } while(0)
#ifdef _MSC_VER
/* C runtime functions redefined */
#define snprintf _snprintf
#endif
//u32_t dns_lookup_external_hosts_file(const char *name);
#define LWIP_RAND() ((u32_t)rand())
#endif /* LWIP_ARCH_CC_H */

1
test-in-docker/lwip-include/arch/epstruct.h

@ -0,0 +1 @@
#pragma pack(pop)

4
test-in-docker/lwip-include/arch/sys_arch.h

@ -0,0 +1,4 @@
#ifndef LWIP_ARCH_SYS_ARCH_H
#define LWIP_ARCH_SYS_ARCH_H
#endif /* LWIP_ARCH_SYS_ARCH_H */

31
test-in-docker/lwip-include/lwipopts.h

@ -0,0 +1,31 @@
#define NO_SYS 1
#define SYS_LIGHTWEIGHT_PROT 0
#define MEM_LIBC_MALLOC 1
#define MEMP_MEM_MALLOC 1
#define MEM_USE_POOLS 0
#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 1
#define LWIP_ETHERNET 1
#define LWIP_IPV4 1
#define LWIP_TCP 1
#define LWIP_ARP 1
#define LWIP_ICMP 1
#define IP_FRAG 1
#define LWIP_DEBUG 1
#define FTPD_DEBUG LWIP_DBG_ON
//#define IP4_DEBUG LWIP_DBG_ON
//#define NETIF_DEBUG LWIP_DBG_ON
//#define TCP_DEBUG LWIP_DBG_ON
//#define ETHARP_DEBUG LWIP_DBG_ON
#define PPP_SUPPORT 0
#define LWIP_SOCKET 0
#define LWIP_NETCONN 0
#define LWIP_RAW 0
#define LWIP_COMPAT_SOCKETS 0
#define LWIP_STATS 0
#define LWIP_CHECKSUM_CTRL_PER_NETIF 1

100
test-in-docker/lwip-include/sys_arch.c

@ -0,0 +1,100 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
* Simon Goldschmidt
*
*/
#include <stdlib.h>
#include <lwip/opt.h>
#ifdef _WIN32
#include <windows.h>
LARGE_INTEGER freq, sys_start_time;
static void sys_init_timing(void)
{
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&sys_start_time);
}
static LONGLONG sys_get_ms_longlong(void)
{
LONGLONG ret;
LARGE_INTEGER now;
#if NO_SYS
if (freq.QuadPart == 0) {
sys_init_timing();
}
#endif /* NO_SYS */
QueryPerformanceCounter(&now);
ret = now.QuadPart-sys_start_time.QuadPart;
return (u32_t)(((ret)*1000)/freq.QuadPart);
}
u32_t sys_jiffies(void)
{
return (u32_t)sys_get_ms_longlong();
}
u32_t sys_now(void)
{
return (u32_t)sys_get_ms_longlong();
}
#else
#include <time.h>
u32_t sys_now(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec * 1000L + ts.tv_nsec / 1000000L;
}
u32_t sys_jiffies(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec * 1000000000L + ts.tv_nsec;
}
#endif
void sys_init(void)
{
#ifdef _WIN32
sys_init_timing();
#endif
}

28
test-in-docker/src/CMakeLists.txt

@ -0,0 +1,28 @@
cmake_minimum_required (VERSION 2.8)
project(lwip-runner)
find_path( PCAP_INCLUDE_DIR NAMES pcap/pcap.h pcap.h HINTS "${PCAP_HINTS}/include")
find_library( PCAP_LIBRARY NAMES pcap wpcap HINTS "${PCAP_HINTS}/lib")
find_path(LWIP_DIR src/include/lwip/init.h ${CMAKE_CURRENT_SOURCE_DIR}/../../../lwip)
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/../lwip-include
${PCAP_INCLUDE_DIR}
${LWIP_DIR}/src/include
${CMAKE_CURRENT_SOURCE_DIR}/../../../ff
${CMAKE_CURRENT_SOURCE_DIR}/../..
)
include(${LWIP_DIR}/src/Filelists.cmake)
add_executable(lwip-runner
${CMAKE_CURRENT_SOURCE_DIR}/main.c
${CMAKE_CURRENT_SOURCE_DIR}/../lwip-include/sys_arch.c
${CMAKE_CURRENT_SOURCE_DIR}/../../ftpd.c
${CMAKE_CURRENT_SOURCE_DIR}/../../vfs.c
${CMAKE_CURRENT_SOURCE_DIR}/../../../ff/source/ff.c
)
target_link_libraries(lwip-runner ${PCAP_LIBRARY} lwipcore)

190
test-in-docker/src/main.c

@ -0,0 +1,190 @@
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <fcntl.h>
#include <pcap/pcap.h>
#include <lwip/init.h>
#include <lwip/netif.h>
#include <lwip/ethip6.h>
#include <netif/etharp.h>
#include <lwip/udp.h>
#include <lwip/mld6.h>
#include <lwip/timeouts.h>
#include <ftpd.h>
#include <source/ff.h>
#include <source/diskio.h>
// 4MiB should be enough for everyone
#define DATA_SIZE (4*1024*1024)
int data;
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void *buff) {
if (pdrv != 0) return RES_NOTRDY;
switch(cmd) {
case CTRL_SYNC:
fsync(data);
return RES_OK;
case GET_SECTOR_COUNT:
*((LBA_t*)buff) = DATA_SIZE/512;
return RES_OK;
case GET_BLOCK_SIZE:
*((WORD*)buff) = 512;
return RES_OK;
}
return RES_PARERR;
}
DWORD get_fattime() {
// I am lazy.
return 0;
}
DSTATUS disk_initialize(BYTE pdrv) {
if (pdrv != 0) return STA_NOINIT;
data = open("data.img", O_CREAT | O_RDWR);
printf("disk_initialize: open returns %d\n", data);
return 0;
}
DSTATUS disk_status (BYTE pdrv) {
if (pdrv != 0) return STA_NOINIT;
return 0;
}
DRESULT disk_write(BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
if (pdrv != 0) return RES_NOTRDY;
size_t r = lseek(data, 512*sector, SEEK_SET);
printf("disk_write: lseek returns %d\n", r);
r = write(data, buff, 512 * count);
printf("disk_write(%d): write returns %d\n", count, r);
return RES_OK;
}
DRESULT disk_read(BYTE pdrv, BYTE* buff, LBA_t sector, UINT count) {
if (pdrv != 0) return RES_NOTRDY;
size_t r = lseek(data, 512*sector, SEEK_SET);
printf("disk_read: lseek returns %d\n", r);
r = read(data, buff, 512 * count);
printf("disk_read(%d): read returns %d\n", count, r);
return RES_OK;
}
int dbg_printf(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
int r = vprintf(fmt, args);
va_end(args);
return r;
}
static err_t pcap_output(struct netif* netif, struct pbuf* p) {
pcap_t *pcap = netif->state;
printf("Sending packet with length %d\n", p->tot_len);
int r = pcap_sendpacket(pcap, (uint8_t*)p->payload, p->tot_len);
if (r != 0) {
printf("Error sending packet\n");
printf("Error: %s\n", pcap_geterr(pcap));
return ERR_IF;
}
return ERR_OK;
}
static err_t init_callback(struct netif* netif) {
netif->name[0] = 't';
netif->name[1] = 'p';
netif->linkoutput = pcap_output;
netif->output = etharp_output;
netif->mtu = 1500;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET;
netif_set_link_up(netif);
return ERR_OK;
}
int main(size_t argc, char **argv) {
pcap_t *pcap = pcap_open_live("eth0", 65536, 1, 100, NULL);
char errbuf[PCAP_ERRBUF_SIZE];
int r = pcap_setnonblock(pcap, 1, errbuf);
if (r == PCAP_ERROR) {
printf("pcap_setnonblock returned: %s", errbuf);
return 1;
}
FATFS fs;
unsigned char *buf[4096];
{
FRESULT r = f_mount(&fs, "", 1);
printf("f_mount returns %d\n", r);
if (r == FR_NO_FILESYSTEM) {
r = f_mkfs("", NULL, buf, sizeof buf);
printf("f_mkfs returns %d\n", r);
r = f_mount(&fs, "", 1);
printf("f_mount returns %d\n", r);
}
}
struct netif netif;
memset(&netif, 0, sizeof netif);
netif.hwaddr_len = 6;
memcpy(netif.hwaddr, "\xaa\x00\x00\x00\x00\x01", 6);
ip4_addr_t ip, mask, gw;
IP4_ADDR(&ip, 172,17,0,5);
IP4_ADDR(&mask, 255,255,0,0);
IP4_ADDR(&gw, 172,17,0,1);
netif_add(&netif, &ip, &mask, &gw, pcap, init_callback, ethernet_input);
netif_set_up(&netif);
NETIF_SET_CHECKSUM_CTRL(&netif, 0x00FF);
ftpd_init();
sys_restart_timeouts();
struct pcap_pkthdr *hdr = NULL;
const unsigned char *data = NULL;
while(1) {
sys_check_timeouts();
int r = pcap_next_ex(pcap, &hdr, &data);
switch (r) {
case 0:
// Timeout
continue;
case -1:
printf("Error: %s\n", pcap_geterr(pcap));
continue;
case 1:
break;
default:
printf("Unknown result: %d\n", r);
continue;
}
printf("Packet length: %d / %d\n", hdr->len, hdr->caplen);
struct pbuf *pbuf = pbuf_alloc(PBUF_RAW, hdr->len, PBUF_RAM);
memcpy(pbuf->payload, data, hdr->len);
netif.input(pbuf, &netif);
}
return 0;
}
Loading…
Cancel
Save