mirror of https://github.com/toelke/lwip-ftpd.git
Philipp Toelke
4 years ago
10 changed files with 501 additions and 2 deletions
@ -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 |
@ -0,0 +1 @@ |
|||
#pragma pack(push,1) |
@ -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 */ |
|||
|
@ -0,0 +1 @@ |
|||
#pragma pack(pop) |
@ -0,0 +1,4 @@ |
|||
#ifndef LWIP_ARCH_SYS_ARCH_H |
|||
#define LWIP_ARCH_SYS_ARCH_H |
|||
|
|||
#endif /* LWIP_ARCH_SYS_ARCH_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 |
|||
|
@ -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 |
|||
} |
@ -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) |
@ -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…
Reference in new issue