Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,15 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential autoconf automake libtool pkg-config
sudo apt-get install -y build-essential autoconf automake libtool pkg-config \
tftpd-hpa tftp-hpa
sudo modprobe tun
# The tftpd-hpa package installs a systemd unit that binds the
# standard TFTP port. The interop test starts its own in.tftpd
# bound to the test tap link, so stop the system instance to
# keep ports / file ownership predictable.
sudo systemctl stop tftpd-hpa || true
sudo systemctl disable tftpd-hpa || true

- name: Clone and build wolfSSL from nightly-snapshot
run: |
Expand Down Expand Up @@ -129,6 +136,28 @@ jobs:
set -euo pipefail
timeout --preserve-status 5m build/test/unit

- name: Build TFTP interop test
run: |
make build/test-tftp-interop

- name: Run TFTP interop test (wolfIP client vs tftpd-hpa, wolfIP server vs tftp-hpa)
timeout-minutes: 3
run: |
set -euo pipefail
timeout --preserve-status 3m sudo ./build/test-tftp-interop all
sudo killall tcpdump || true

- name: Upload TFTP interop diagnostics on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: tftp-interop-diagnostics
path: |
/tmp/wolfip-tftp.pcap
/tmp/wolfip-tftpd-hpa.log
/tmp/wolfip-tftp-client.log
if-no-files-found: ignore

- name: Build ESP unit tests
run: |
make unit-esp
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*.bin
*.swp
*.elf
*.gcov
CMakeCache.txt
CMakeFiles
CMakeScripts
Expand Down
18 changes: 16 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,25 @@ string(TOLOWER "${CMAKE_SYSTEM_NAME}" CMAKE_SYSTEM_NAME_LC)

set(WOLFIP_TAP_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/port/posix/tap_${CMAKE_SYSTEM_NAME_LC}.c")

# Optional TFTP client/server module. Default off to match config.h
# (WOLFIP_ENABLE_TFTP == 0); turn on with -DWOLFIP_ENABLE_TFTP=ON.
option(WOLFIP_ENABLE_TFTP "Build and link the wolfIP TFTP client/server" OFF)
if (WOLFIP_ENABLE_TFTP)
file(GLOB WOLFIP_TFTP_SRCS CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/src/tftp/*.c")
add_compile_definitions(WOLFIP_ENABLE_TFTP=1)
else()
set(WOLFIP_TFTP_SRCS )
endif()

if (NOT EXISTS "${WOLFIP_TAP_SRC}")
message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}")
endif()

set(WOLFIP_SRCS src/wolfip.c ${WOLFIP_TAP_SRC})
set(WOLFIP_SRCS
src/wolfip.c
${WOLFIP_TFTP_SRCS}
${WOLFIP_TAP_SRC})

Comment thread
danielinux marked this conversation as resolved.
set(CERT_SRCS
${CMAKE_BINARY_DIR}/certs/server_cert.c
Expand Down Expand Up @@ -187,7 +201,7 @@ add_executable(test-ttl-expired ${EXCLUDE_TEST_BINARY}
target_compile_definitions(test-ttl-expired PRIVATE -DWOLFIP_MAX_INTERFACES=2 -DWOLFIP_ENABLE_FORWARDING=1)
add_test(NAME ttl-expired COMMAND test-ttl-expired)

if (NOT Check_FOUND)
if (Check_FOUND)
add_executable(unit ${EXCLUDE_TEST_BINARY}
src/test/unit/unit.c
)
Expand Down
78 changes: 72 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,21 @@ endif
TAP_OBJ:=$(NETDEV_OBJ)
TAP_PIE_OBJ:=$(NETDEV_PIE_OBJ)

# Optional TFTP module. Default to off to match config.h
# (WOLFIP_ENABLE_TFTP == 0); set WOLFIP_ENABLE_TFTP=1 on the command
# line to compile and link the TFTP client/server objects.
WOLFIP_ENABLE_TFTP ?= 0
ifeq ($(WOLFIP_ENABLE_TFTP),1)
WOLFIP_TFTP_SRC:=$(wildcard src/tftp/*.c)
WOLFIP_TFTP_OBJ:=$(patsubst src/%.c,build/%.o,$(WOLFIP_TFTP_SRC))
WOLFIP_TFTP_PIE_OBJ:=$(patsubst src/%.c,build/pie/%.o,$(WOLFIP_TFTP_SRC))
CFLAGS+=-DWOLFIP_ENABLE_TFTP=1
else
WOLFIP_TFTP_SRC:=
WOLFIP_TFTP_OBJ:=
WOLFIP_TFTP_PIE_OBJ:=
endif

ifeq ($(UNAME_S),Darwin)
BEGIN_GROUP:=
END_GROUP:=
Expand Down Expand Up @@ -135,12 +150,15 @@ CPPCHECK_FLAGS=--enable=warning,performance,portability,missingInclude \
--error-exitcode=1 --xml --xml-version=2

OBJ=build/wolfip.o \
$(WOLFIP_TFTP_OBJ) \
$(TAP_OBJ)

IPFILTER_OBJ=build/ipfilter/wolfip.o \
$(WOLFIP_TFTP_OBJ) \
$(TAP_OBJ)

ESP_OBJ=build/esp/wolfip.o \
$(WOLFIP_TFTP_OBJ) \
Comment thread
danielinux marked this conversation as resolved.
$(TAP_OBJ)

HAVE_WOLFSSL:=$(shell printf "#include <wolfssl/options.h>\nint main(void){return 0;}\n" | $(CC) $(CFLAGS) -x c - -c -o /dev/null 2>/dev/null && echo 1)
Expand Down Expand Up @@ -185,6 +203,7 @@ libtcpip.a: $(OBJ)

libwolfip.so:CFLAGS+=-fPIC
libwolfip.so: build/pie/port/posix/bsd_socket.o build/pie/wolfip.o \
$(WOLFIP_TFTP_PIE_OBJ) \
$(TAP_PIE_OBJ)
@mkdir -p `dirname $@` || true
@echo "[LD] $@"
Expand Down Expand Up @@ -257,6 +276,39 @@ build/test-dns: $(OBJ) build/test/test_dhcp_dns.o
@echo "[LD] $@"
@$(CC) $(CFLAGS) -o $@ $(BEGIN_GROUP) $(^) $(LDFLAGS) $(END_GROUP)

# Bidirectional TFTP interop test against tftpd-hpa / tftp-hpa.
# Forces WOLFIP_ENABLE_TFTP=1 and uses a single-session server so the
# default UDP socket pool can hold both the listen and the transfer
# socket without raising MAX_UDPSOCKETS.
build/tftp-interop/wolfip.o: src/wolfip.c
@mkdir -p `dirname $@` || true
@echo "[CC] $< (tftp-interop)"
@$(CC) $(CFLAGS) -DWOLFIP_ENABLE_TFTP=1 -c $< -o $@

build/tftp-interop/wolftftp.o: src/tftp/wolftftp.c
@mkdir -p `dirname $@` || true
@echo "[CC] $< (tftp-interop)"
@$(CC) $(CFLAGS) -DWOLFIP_ENABLE_TFTP=1 -DWOLFTFTP_SERVER_MAX_SESSIONS=1 \
-c $< -o $@

build/test/test_tftp_interop.o: src/test/test_tftp_interop.c
@mkdir -p `dirname $@` || true
@echo "[CC] $<"
@$(CC) $(CFLAGS) -DWOLFIP_ENABLE_TFTP=1 -DWOLFTFTP_SERVER_MAX_SESSIONS=1 \
-c $< -o $@

build/test-tftp-interop: build/tftp-interop/wolfip.o \
build/tftp-interop/wolftftp.o $(TAP_OBJ) \
build/test/test_tftp_interop.o
@echo "[LD] $@"
@$(CC) $(CFLAGS) -o $@ $(BEGIN_GROUP) $(^) $(LDFLAGS) $(END_GROUP)

.PHONY: tftp-interop-test
tftp-interop-test: build/test-tftp-interop
@echo "[RUN] $< (requires root, tftpd-hpa and tftp-hpa)"
@sudo -n true >/dev/null 2>&1 || { echo "tftp-interop-test needs to run as root (sudo)"; exit 1; }
@sudo ./build/test-tftp-interop all

build/tcpecho: $(OBJ) build/port/posix/bsd_socket.o build/test/tcp_echo.o
@echo "[LD] $@"
@$(CC) $(CFLAGS) -o $@ $(BEGIN_GROUP) $(^) $(LDFLAGS) $(END_GROUP)
Expand Down Expand Up @@ -321,7 +373,7 @@ build/esp-server: $(ESP_OBJ) build/port/posix/bsd_socket.o build/test/esp_server
@echo "[LD] $@"
@$(CC) $(CFLAGS) $(ESP_CFLAGS) $(LDFLAGS) -o $@ $(BEGIN_GROUP) $(^) -lwolfssl $(END_GROUP)

build/test-wolfssl-forwarding: build/test/test_wolfssl_forwarding.o build/test/wolfip_forwarding.o $(TAP_OBJ) build/port/wolfssl_io.o build/certs/server_key.o build/certs/ca_cert.o build/certs/server_cert.o
build/test-wolfssl-forwarding: build/test/test_wolfssl_forwarding.o build/test/wolfip_forwarding.o $(WOLFIP_TFTP_OBJ) $(TAP_OBJ) build/port/wolfssl_io.o build/certs/server_key.o build/certs/ca_cert.o build/certs/server_cert.o
@echo "[LD] $@"
@$(CC) $(CFLAGS) -o $@ $(BEGIN_GROUP) $(^) $(LDFLAGS) -lwolfssl $(END_GROUP)

Expand All @@ -333,7 +385,7 @@ build/test/wolfip_forwarding.o: src/wolfip.c
@$(CC) $(CFLAGS) -DWOLFIP_MAX_INTERFACES=2 -DWOLFIP_ENABLE_FORWARDING=1 -c $< -o $@

build/test/test_ttl_expired.o: CFLAGS+=-DWOLFIP_MAX_INTERFACES=2 -DWOLFIP_ENABLE_FORWARDING=1
build/test-ttl-expired: build/test/test_ttl_expired.o build/test/wolfip_forwarding.o
build/test-ttl-expired: build/test/test_ttl_expired.o build/test/wolfip_forwarding.o $(WOLFIP_TFTP_OBJ)
@echo "[LD] $@"
@$(CC) $(CFLAGS) -o $@ $(BEGIN_GROUP) $(^) $(LDFLAGS) $(END_GROUP)

Expand Down Expand Up @@ -386,7 +438,8 @@ UNIT_TEST_SRCS:=src/test/unit/unit.c \
src/test/unit/unit_tests_tcp_ack.c \
src/test/unit/unit_tests_tcp_flow.c \
src/test/unit/unit_tests_proto.c \
src/test/unit/unit_tests_multicast.c
src/test/unit/unit_tests_multicast.c \
src/test/unit/unit_tests_tftp.c

unit: build/test/unit

Expand Down Expand Up @@ -486,27 +539,40 @@ $(COV_MCAST_UNIT): $(COV_MCAST_UNIT_O)
cov: unit $(COV_UNIT)
@echo "[RUN] unit (coverage)"
@rm -f $(COV_DIR)/*.gcda
@rm -f $(COV_DIR)/unit-multicast $(COV_DIR)/unit-multicast.o \
$(COV_DIR)/unit-multicast.gcno $(COV_DIR)/unit-multicast.gcda
@$(COV_UNIT)
@echo "[COV] gcovr html"
@mkdir -p build/coverage
@gcovr -r . --exclude "src/test/unit/.*" --html-details -o build/coverage/index.html
@gcovr -r . --exclude "src/test/unit/.*" \
--gcov-ignore-errors=no_working_dir_found \
--merge-mode-functions=merge-use-line-min \
--html-details -o build/coverage/index.html
@$(OPEN_CMD) build/coverage/index.html

autocov: unit $(COV_UNIT)
@echo "[RUN] unit (coverage)"
@rm -f $(COV_DIR)/*.gcda
@rm -f $(COV_DIR)/unit-multicast $(COV_DIR)/unit-multicast.o \
$(COV_DIR)/unit-multicast.gcno $(COV_DIR)/unit-multicast.gcda
@$(COV_UNIT)
@echo "[COV] gcovr html"
@mkdir -p build/coverage
@gcovr -r . --exclude "src/test/unit/.*" --html-details -o build/coverage/index.html
@gcovr -r . --exclude "src/test/unit/.*" \
--gcov-ignore-errors=no_working_dir_found \
--merge-mode-functions=merge-use-line-min \
--html-details -o build/coverage/index.html

autocov-multicast: unit-multicast $(COV_MCAST_UNIT)
@echo "[RUN] unit multicast (coverage)"
@rm -f $(COV_DIR)/*.gcda
@$(COV_MCAST_UNIT)
@echo "[COV] gcovr multicast html"
@mkdir -p build/coverage
@gcovr -r . --exclude "src/test/unit/.*" --html-details -o build/coverage/multicast.html
@gcovr -r . --exclude "src/test/unit/.*" \
--gcov-ignore-errors=no_working_dir_found \
--merge-mode-functions=merge-use-line-min \
--html-details -o build/coverage/multicast.html

# Install dynamic library to re-link linux applications
#
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ configured to forward traffic between multiple network interfaces.
- Multi-interface support
- Optional IPv4-forwarding
- Optional IPv4 UDP multicast with IGMPv3 ASM membership reports
- Reusable allocation-free TFTP module under `src/tftp/`

## Supported socket types

Expand Down Expand Up @@ -53,6 +54,7 @@ wolfIP exposes a BSD-like `socket(2)` API for IPv4 sockets:
| **Application** | DHCP | Client only (DORA) | [RFC 2131](https://datatracker.ietf.org/doc/html/rfc2131) |
| **Application** | DNS | A and PTR record queries (client) | [RFC 1035](https://datatracker.ietf.org/doc/html/rfc1035) |
| **Application** | HTTP/HTTPS | Server with wolfSSL TLS support | [RFC 9110](https://datatracker.ietf.org/doc/html/rfc9110) |
| **Application** | TFTP | Client/server octet-mode transfers with callback-driven storage and verification | [RFC 1350](https://datatracker.ietf.org/doc/html/rfc1350), [RFC 2347](https://datatracker.ietf.org/doc/html/rfc2347), [RFC 2348](https://datatracker.ietf.org/doc/html/rfc2348), [RFC 2349](https://datatracker.ietf.org/doc/html/rfc2349), [RFC 7440](https://datatracker.ietf.org/doc/html/rfc7440) |
| **VPN** | wolfGuard | FIPS-compliant WireGuard (P-256, AES-256-GCM, SHA-256) | [Wolfguard](https://www.github.com/wolfssl/wireguard) |

## wolfGuard (FIPS WireGuard)
Expand Down Expand Up @@ -180,6 +182,14 @@ This port follows the same model as the POSIX wrapper:
- Socket wrappers serialize stack access with a mutex
- Blocking operations wait on callback-driven wakeups (instead of busy polling)

## Source Layout

- `src/wolfip.c`: core TCP/IP stack
- `src/http/`: optional HTTP/HTTPS server pieces
- `src/tftp/`: reusable TFTP module sources, auto-registered by the top-level `Makefile` and `CMakeLists.txt` when present
- `src/port/`: platform and OS adaptation layers
- `src/test/`: integration and unit tests

## Copyright and License

wolfIP is licensed under the GPLv3 license. See the LICENSE file for details.
Expand Down
4 changes: 4 additions & 0 deletions config.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@
#define WOLFIP_ENABLE_HTTP
#endif

#ifndef WOLFIP_ENABLE_TFTP
#define WOLFIP_ENABLE_TFTP 0
#endif

#if WOLFIP_ENABLE_LOOPBACK && WOLFIP_MAX_INTERFACES < 2
#error "WOLFIP_ENABLE_LOOPBACK requires WOLFIP_MAX_INTERFACES > 1"
#endif
Expand Down
16 changes: 16 additions & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,25 @@ wolfIP is a minimal TCP/IP stack designed for resource-constrained embedded syst
- ICMP (RFC 792) - ping replies only
- DHCP (RFC 2131) - client only
- DNS (RFC 1035) - client only
- TFTP (RFC 1350, RFC 2347, RFC 2348, RFC 2349, RFC 7440) via the reusable `src/tftp/` module
- UDP (RFC 768) - unicast, optional IPv4 multicast with `IP_MULTICAST`
- TCP (RFC 793) with options (Timestamps, MSS)

## Build Integration

The top-level build systems register reusable module sources from `src/tftp/`
automatically:

- `Makefile` adds any `src/tftp/*.c` files to the shared library, static library,
and top-level executable link sets.
- `CMakeLists.txt` globs `src/tftp/*.c` with `CONFIGURE_DEPENDS` so the same
sources are compiled into the main `wolfip` and `tcpip` targets.

The TFTP module is callback-driven and allocation-free. Callers provide the UDP
send hook plus open/read/write/close callbacks for storage, and may additionally
provide streaming hash-update and final verification callbacks for firmware
download flows.

## Core Data Structures

### Device Driver Interface
Expand Down
Loading
Loading