Skip to content

Latest commit

 

History

838 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tolunnet

An open-source TCP/IP stack and bsdsocket.library v4.1 runtime for classic Commodore AmigaOS (68k), built on a pinned, hardened copy of lwIP 2.2.0 running as a dedicated AmigaOS Exec task (NO_SYS=1).


Pre-release — testers wanted

1.2.0-rc5 is a pre-release. tolunnet is a hobby project, written by one person for the pleasure of keeping 40-year-old machines useful. It is verified in an emulator (WinUAE, Workbench 3.0, A1200 and plain 68000 profiles) and by host unit tests, but it has not yet been tried on real hardware, and the Installer / two-disk Gotek path has never run on a real Amiga. That is where you come in.

  • Try it on a PiStorm, an accelerated Amiga, a CF/HD setup or through a Gotek, and tell us what happens — working or not.
  • Follow the checklist in docs/MANUAL-TEST-rc5.md (about 20 minutes) and report back with photos if you can.
  • Report via GitHub Issues: your Amiga model, CPU/accelerator, Kickstart/Workbench version, network card or SANA-II driver, what you did and what you saw. Screenshots of the Setup wizard or the Preferences window are very welcome.
  • Always keep a backup of S:User-Startup and your current TCP/IP stack. The installer writes an undo script (S:tolunnet-undo), and the default Installer mode is pretend (nothing is written until you choose to). The undo never copies a backup over a live S:User-Startup: it leaves the tolunnet block there (harmless once C:tolunnet is gone; remove it by hand) and keeps the pre-install copy as S:User-Startup.tolunnet-old.

A first look

Setup wizard Address page Test & Finish Preferences
Welcome Address Test Preferences

Icons (Setup, Preferences, tolunnet):

All wizard pages in PAL and NTSC are further down in the Setup Wizard section.


Overview & Motivation

Classic AmigaOS has long lacked an actively maintained, production-grade, 100% open-source TCP/IP stack. Roadshow is proprietary commercial software. Miami and Miami Deluxe are discontinued abandonware. AmiTCP's last open-source release dates back to version 3.0b in 1994.

tolunnet bridges this gap: modern, fully documented, rigorously verified, and distributed under the GNU General Public License v3.0 (GPL-3.0-or-later). It provides a drop-in replacement bsdsocket.library for classic 68k Amiga systems (from a bone-stock Amiga 500 up to accelerated Amiga 4000 and PiStorm systems), complete with standard network diagnostic tools, a modern Setup wizard, and Workbench Preferences.

Compatibility Notice: Applications communicate with tolunnet strictly via the standard AmigaOS library interface: OpenLibrary("bsdsocket.library", 4). Calling bsdsocket.library functions from any third-party application (freeware, shareware, or commercial) does not subject that application to the GPL.


Key Architecture & Features

  • bsdsocket.library v4.1 runtime: 139 total LVO slots (-30 … -858; 121 SFD functions + reserved) generated from Roadshow SDK sfd/bsdsocket_lib.sfd via scripts/gen_lvo_table.py; 70 BUILT (vector → IPC → daemon handler, or handled in-library), 51 honest stubs returning exact Roadshow error semantics (ENOSYS, ENXIO, NULL, NO_RECOVERY, FALSE), 0 BROKEN (marshaled without a daemon handler). A vector-by-vector status table (src/lib/lib_compat_table.gen.md) is generated locally by make python-checks.
  • Roadshow 1.8 & AmiTCP V4 API: socket primitives (socket, bind, listen, accept, connect, shutdown, getsockname, getpeername, send/recv/sendmsg/recvmsg), SocketBaseTagList (-294), WaitSelect (timer-driven, SIGIO delivery), IoctlSocket, GetSocketEvents, Dup2Socket, netdb (gethostbyname, getservbyname/byport, getprotobyname/bynumber, getnetbyname/byaddr, getaddrinfo/getnameinfo), inet_* helpers, gethostname, gethostid and vsyslog.
  • Exec message-port IPC: client calls reach the daemon through native PutMsg/WaitPort/ReplyMsg. The fast path reuses one message per library base; a per-call MEMF_PUBLIC message is allocated only in IPC-timeout mode.
  • Universal 68k code (-m68000 -msoft-float): one binary set for 68000 … 68060, no FPU required.
  • 68000 alignment defence: 4-byte memory pool alignment (MEM_ALIGNMENT 4) and ETH_PAD_SIZE 2 keep IP/TCP headers aligned. -Werror=cast-align in the m68k build catches explicit less-aligned casts at build time; make align-check adds a host -Wcast-align=strict pass (files the host cannot parse are re-checked with the cross compiler, and an unchecked file fails the gate) and a lint for (void *) cast hops and typed dereferences of client pointers, which neither compiler sees.
  • SANA-II Rev 7 driver interface: register-convention buffer-management hooks (A0/A1/D0), multiple outstanding reads, S2_ONEVENT link tracking (active only with TX_QUEUE=0; the TX pool turns it off) and an optional pipelined TX request pool (TX_QUEUE; the default 0 is synchronous DoIO). Works with standard Ethernet and wireless SANA-II drivers such as a2065.device, ariadne.device, cnet.device and wifipi.device.
  • PRNG seeding: the lwIP random source is seeded at start-up from GetSysTime (µs resolution) and free Chip/Fast RAM, then from the adapter MAC address once the interface is open.
  • Text configuration: DEVS:tolunnet.config (KEY=VALUE), described under Configuration. ENV:tolunnet.prefs overrides it when newer. Changes take effect after tolunnet RECONFIG or TolunnetControl RECONFIG.
  • usergroup.library: resident library (LIBS:usergroup.library, 39 public LVOs) for user/group identity and credentials (getuid, geteuid, getpwuid, getpwnam, getgrnam, getgroups, crypt, …).
    • It has a built-in in-memory database: users root, amiga, nobody; groups wheel, staff, nobody.
    • The first passwd/group file found in AmiTCP:db/, DEVS:Internet/ or DEVS:tolunnet/ overrides that database.
    • crypt() uses an internal FNV hash, not Unix DES; existing AmiTCP passwd files are not compatible.
    • Partial implementations are listed under Known limitations.
  • AutoIP (RFC 3927): optional link-local 169.254.x.x/16 address fallback with Address Conflict Detection (lwIP DHCP/AutoIP cooperation, about 3–4 s). Off by default; AUTOIP=YES enables it.
  • mDNS responder (RFC 6762): optional Zeroconf responder that answers <hostname>.local on 224.0.0.251:5353 and publishes a _workstation._tcp DNS-SD service (model=Amiga, os=AmigaOS, stack=tolunnet). Off by default; MDNS=YES enables it.
  • Workbench GUI:
    • TolunnetSetup: first-run wizard whose layout is computed from font metrics (TextLength(), tf_YSize). The bench verifies it on 640×200 NTSC and 640×256 PAL. The same code supports RTG screens, but the bench image has no RTG drivers to test them.
    • TolunnetPrefs: GadTools preferences editor with non-blocking daemon Start/Stop, ToolTypes (TOOLPRI, PUBSCREEN) and WBStartup support.

Setup Wizard

The first-run wizard (TolunnetSetup) guides network configuration with automatic hardware detection and responsive layout adaptation across PAL and NTSC screens:

  • Welcome & replacement: detects existing TCP/IP stacks (Roadshow, Miami, AmiTCP) and backs them up cleanly before proceeding. Page 1: Welcome & Stack Replacement
  • Hardware detection: scans installed SANA-II device drivers and configures unit selection. Page 2: Hardware
  • Wireless networks: scans available Wi-Fi networks (SSID, signal strength, security) and stores passphrases. Page 3: Wireless Setup
  • Address mode (DHCP): automated dynamic host configuration and hostname assignment. Page 4: Address (DHCP)
  • Connection test & finish: verifies network operations and saves configuration with User-Startup integration. Page 5: Test & Finish
  • Preferences: TolunnetPrefs edits the same configuration outside the wizard. Preferences
NTSC (640×200) screenshots — same pages on the 68000 bench leg

Page 1: Welcome & Stack Replacement (NTSC) Page 1 "Replace legacy stacks": empty legacy-stack list, the "Replace with tolunnet (recommended)" checkbox, status "Ready." Page 2: Hardware (NTSC) Page 2 "Network hardware": empty "Adapter:" list with Rescan and Test adapter buttons, status "Ready." Page 3: Wireless Setup (NTSC) Page 3 "Wireless network": empty "Networks:" list, Scan APs button, SSID/Passphrase fields with a Show checkbox, status "Ready." Page 4: Address (DHCP, NTSC) Page 4 "IP address": Mode "Automatic (DHCP)", empty DNS 2/MTU fields, host "amiga", status "Ready." — no invented gateway on screen. Page 5: Test & Finish (NTSC) Page 5 "Test & finish": the check rows (Start stack OK, IP address OK 10.0.2.15, Ping gateway OK 10.0.2.2, DNS lookup SKIPPED, HTTP HEAD SKIPPED) and the honest status line "Tests complete - 3 passed, 0 failed, 2 skipped". Preferences (NTSC) TolunnetPrefs over the Workbench: ethernet.device unit 0, DHCP mode, MTU 1500, DNS 1 127.0.0.1 (the bench's resolver), Save/Use/Stop/Setup/Undo/Ping/Cancel buttons.

All 12 screenshots are PAL/NTSC captures from the newest green bench; the -static variants are excluded on purpose: they show the known invented Manual-mode defaults (see Known limitations in STATUS.md). Total size of docs/screenshots/: about 44 KB.


Sample session

Real outputs, copied VERBATIM from the newest green bench log (docs/bench-logs/20261001-035223-v1.2.0-rc4-453-ga5045cb/a1200/conformance.log) (emulated A1200, WinUAE slirp network; addresses are the bench's):

# tc_net_checks_ok: address 1 - address 10.0.2.15
# tc_net_checks_ok: ping 1 - ping 127.0.0.1 replied
# tc_net_checks_ok: dns 1 - resolved tolunbench.test to 10.0.2.55 via 10.0.2.2
# tc_net_checks_ok: tcp 1 - tcp 10.0.2.2:15880 connected
# tc_cmd_arp: gateway ARP resolves here: yes

The conformance log records the checks as one-line results; it carries no raw ifconfig transcript. The GetNetStatus line is the first row above (address 10.0.2.15); the wizard Test page (screenshot above) shows the same values on screen.


Commands

The release archive ships the following programs, in C/ unless noted. The installer (Install_Tolunnet) installs the complete command set, companion tools and libraries to SYS:C/, SYS:Prefs/ and SYS:Libs/.

Command ReadArgs template / purpose
tolunnet Stack daemon and bsdsocket.library provider. START/S,STOP/S,STATUS/S,RECONFIG/S,STATS/S,RAW/S,WATCH/N,DEVICE,UNIT/N,IP,NETMASK,GATEWAY. With no arguments it reads DEVS:tolunnet.config.
TolunnetControl COMMAND/A: START, STOP, RESTART, STATUS, RECONFIG, STATS, VERSION.
TolunnetSetup (SYS:Prefs/) First-run network wizard: hardware detection, DHCP/static setup, connection test.
TolunnetPrefs (SYS:Prefs/) Preferences editor with stack Start/Stop.
TolunnetStatus, ifconfig, netstat One read-only binary that takes no arguments. The name it is started under picks the output: stack status, interface summary, or socket/route summary.
ShowNetStatus INTERFACES/S,ROUTES/S,DNS/S,SOCKETS/S,FULL/S
GetNetStatus ONLINE/S,ADDRESS/S,GATEWAY/S,DNS/S: status query for scripts, answered through the return code.
TolunnetPing, ping HOST/A,COUNT/N,SIZE/N,INTERVAL/N,TTL/N,TIMEOUT/N,QUIET/S,UDP/S: ICMP echo with min/avg/max/mdev.
TolunnetGet, wget, curl URL/A,PORT/N,PATH,TO/K,QUIET/S: HTTP/1.1 client with 301/302/303/307/308 redirects, chunked transfer and Range resume.
route SHOW/S,ADD/S,DEST/K,NETMASK/K,GATEWAY/K,DELETE/S,DEFAULT/S
AddNetRoute, DeleteNetRoute DEST/A,MASK/K,GATEWAY/K and DEST/A,MASK/K (Roadshow-style names).
AddNetInterface FILE (Roadshow-style interface control).
ConfigureNetInterface NAME/M,ADDRESS/K,NETMASK/K,GATEWAY/K,DHCP/K
Online, Offline NAME
CheckNetConfig FILE: syntax check of a tolunnet config file.
NetShutdown FORCE/S: orderly stack shutdown.
arp SHOW/S: shows the ARP cache via SIOCGARP.
hostname HOSTNAME,SAVE/S
nslookup NAME/A,SERVER: forward (A) and reverse (PTR) lookups.
traceroute HOST/A,MAXHOPS/N,QUERIES/N,WAIT/N,NUMERIC/S: UDP probe routing diagnosis with per-hop IP_TTL and ICMP replies.
whois QUERY/A,SERVER (default server whois.iana.org).
telnet HOST/A,PORT/N: raw TCP terminal. Telnet option negotiation (IAC/SB) is filtered out, not negotiated.
nc HOST/A,PORT/N,UDP/S,LISTEN/S,TIMEOUT/N
ftp HOST,PORT/N,USER,PASS,SCRIPT,QUIET/S,PASVANY/S: passive-mode FTP client. The PASV address must match the control connection's peer unless PASVANY is given.
tftp HOST/A,GET/S,PUT/S,FILE/A,LOCAL: RFC 1350, octet mode.
sntp HOST,SET/S,OFFSET/N
iperf CLIENT/K,SERVER/S,PORT/N,SECONDS/N: simple TCP throughput sink/source with its own format, default port 5201. Not wire-compatible with iperf2 or iperf3.
TestSocket Minimal socket smoke test.
usergroup.library (SYS:Libs/) See Key Architecture & Features.

Configuration

DEVS:tolunnet.config holds one KEY=VALUE per line. TolunnetSetup and TolunnetPrefs write it.

Key Meaning
DEVICE, UNIT SANA-II driver and unit
DHCP YES/NO
IP, NETMASK, GATEWAY static addressing (aliases IP_ADDR, MASK, GW)
DNS, DNS2 resolvers (aliases DNS1, NAMESERVER)
HOSTNAME, MTU host name, interface MTU
AUTOIP, MDNS optional link-local fallback and mDNS responder (default NO; enable with AUTOIP=YES, MDNS=YES)
TX_QUEUE TX request pool depth (0 = synchronous, the release default)
LOG, LOGLEVEL, DEBUG, SYSLOG logging
PRIORITY, SELECTORS, STATS, S2EVENTS, DATABASE_ORDER daemon tuning
DNS_PORT, DNS_PENDING, DNS_RETRIES resolver tuning
FONT font for TolunnetSetup (default: the screen font)

Minimal example:

DEVICE=ethernet.device
UNIT=0
DHCP=YES
DNS=1.1.1.1
LOG=NIL:

Verification

AmigaOS has no memory protection, so one unaligned access or use-after-free ends in a Guru Meditation. Every change therefore goes through three layers of testing. STATUS.md has the current results.

1. Host unit tests (make test-host)

Every tests/host/test_*.c program (the Makefile globs them; ci/check_release_consistency.py keeps the list below in sync) is built with the host compiler under AddressSanitizer and UndefinedBehaviorSanitizer (-Werror). They compile against the real project headers, with a mock lwIP/Exec layer underneath:

test_config, test_constants, test_dns_pending, test_errstr, test_fdset, test_http, test_ifreader, test_inet_addr, test_ipc, test_ipc_dispatch, test_log_format, test_lvo_table, test_manifest_match, test_nslookup_parse, test_queues, test_route, test_sbtc, test_slot_table, test_sockaddr, test_sockopt, test_stats, test_usergroup, test_wizard_config, test_wrap.

After the tests, make test-host runs python-checks: the LVO table generators must be up to date, icon formats are validated, and a gate checks the Forbid()/Disable() regions and a lint bans (T *)(void *) hops and typed dereferences of client pointers outside a reviewed waiver list (scripts/check-cast-known.txt).

2. Emulated conformance bench (ci/bench.sh)

A headless WinUAE harness boots a clean Workbench 3.0 hard-disk image on Kickstart 3.1, in two profiles:

  1. a1200: 68EC020, AGA, PAL.
  2. 68000: A600-class 68000, ECS, NTSC, Fast RAM.

Each profile runs twice: with TX_QUEUE=4 (the pipelined TX pool) and with TX_QUEUE=0 (the release default: synchronous DoIO, S2_ONEVENT link tracking on). Every result row names its TX_QUEUE.

Each run does two cycles in the same OS session, without rebooting:

  • Cycle 1:
    • Start the daemon and obtain a DHCP lease.
    • Run the SocketConformance suite: TCP/UDP/raw ICMP, non-blocking WaitSelect, socket events, a call into each of the 139 LVO slots, and every bundled command.
    • Run the third-party bsdsocktest suite, then stop the daemon. Its score gates the run: fewer than 126 passed, more than 2 failed, or no result fails it.
  • Cycle 2: relaunch the daemon, which re-opens the SANA-II device and gets a fresh lease, then repeat the tests.

A run only counts if the tree was clean (dirty: NO). There is no MuForce/Enforcer pass: the tool image is not part of the bench, every run records SKIP, and setting MUFORCE_ADF aborts the run.

3. Session-profile soak (ci/bench.sh soak)

Hobbyist Amigas are used for a few hours at a time, so the soak models many short sessions rather than long uptime. It runs 12 cycles of 10 minutes on the a1200 profile (SOAK_TX_QUEUE, default 4; 0 soaks the release-default TX path):

  • Each cycle pings the slirp gateway 10.0.2.2 (through SANA-II), downloads from the bench HTTP service (ci/netsvc.py), takes an Avail snapshot, then runs TolunnetControl STOP / START. Every command's return code is checked and logged as an ok / not ok line.
  • The run fails on a Guru or freeze, any not ok line, fewer ok lines than planned, fewer than 13 lwIP initialisations, Chip RAM drift, or Fast RAM drift (measured from the pre-session baseline) above the per-cycle budget.

Real hardware

The owner's target machine is an Amiga 500 with a PiStorm and wifipi.device. Real-hardware retests are done by hand on that machine.


Building from Source

Cross-compile with m68k-amigaos-gcc on Linux or WSL:

git clone https://github.com/tolon/tolunnet.git
cd tolunnet

# Binaries, LhA archive and ADF image (version from include/version.h)
make package CROSS=/path/to/m68k-amigaos/bin/m68k-amigaos-

# Host unit tests (ASan/UBSan) + generator/lint checks
make test-host

# Host-gcc strict cast-alignment gate over src/
make align-check

Outputs in build/:

  • build/tolunnet-<version>.lha: the full release, with binaries, icons, installer, README.guide and licences.
  • build/tolunnet-<version>-disk1.adf / -disk2.adf: the Gotek/FlashFloppy two-disk set (FFS, 880 KB each), built from the stripped release tree with the explicit manifest in scripts/adf_manifest.txt. Merging both disks into one drawer reproduces the package tree byte for byte; disk 1 carries Install_From_Floppies to bootstrap the install. The build/release-assets/ folder bundles the LHA, both ADFs and SHA256SUMS.txt.

Installation

Requirements: AmigaOS 3.0+, 68000 or higher, about 1.2 MB free for the unpacked tree.

Gotek / FlashFloppy / HxC (two floppies)

  1. Download tolunnet-<version>-disk1.adf and tolunnet-<version>-disk2.adf from the GitHub release page and put them on the USB stick.
  2. Boot the Amiga, open a shell, put disk 1 in DF0 and run: Execute tolunnet1:Install_From_Floppies Work:tolunnet The script prints tolunnet two-disk install: copying disk 1 ..., then Disk 1 copied. Insert disk 2 (tolunnet2) now - select disk 2 on the Gotek; DOS asks for the tolunnet2 volume itself if it is not mounted. After disk 2 it prints Both disks copied.
  3. The full package is now in Work:tolunnet; start the Installer from there: CD Work:tolunnet then Installer Install_Tolunnet. Add the NORUN switch to skip the automatic Installer start. This script is shell-only: double-clicking it does not work. Full walkthrough: docs/MANUAL-TEST-rc5.md. Emulator-test status: UNTESTED - the real Installer opens requesters (script error / welcome) that a headless bench cannot answer, so its pretend run has never completed in the emulator (see the notes in STATUS.md). Please try it on real hardware and report.

PiStorm / CF / hard disk

  1. Extract tolunnet-<version>.lha to RAM: or any drawer.
  2. Double-click Install_Tolunnet (or run Installer Install_Tolunnet from a shell). The script asks nothing about hardware:
    • It copies the complete command set to SYS:C/, usergroup.library to SYS:Libs/, and the two preference tools (with icons) to SYS:Prefs/.
    • It detects existing TCP/IP stacks (Roadshow, Miami, AmiTCP), backs up what it replaces (an existing usergroup.library included) and emits S:tolunnet-undo. An existing LIBS:bsdsocket.library is parked with Rename as .pre-tolunnet (or .pre-tn-newer when an older park already exists).
    • It writes DEVS:tolunnet.config and adds the config-driven startup block to S:User-Startup, guarded as If EXISTS C:tolunnet … EndIf.
    • S:tolunnet-undo first runs S:tolunnet-undo-stacks (the wizard's changes to other stacks), restores the replaced files and usergroup.library, and renames a parked bsdsocket.library back only when no live one exists. It leaves a live S:User-Startup as it is and renames S:User-Startup.tolunnet-bak to .tolunnet-old; with no live S:User-Startup the backup is renamed back into place.
  3. It then offers to start SYS:Prefs/TolunnetSetup - the wizard asks for the SANA-II device and unit and configures DHCP or a static address (you can refuse and run it later).

Manual

  1. Copy files from the archive:
    • the C/ programs you want, to SYS:C/;
    • Libs/usergroup.library to LIBS:;
    • TolunnetPrefs and TolunnetSetup with their .info files to SYS:Prefs/.
  2. Run TolunnetSetup once, or create DEVS:tolunnet.config by hand (see Configuration).
  3. Start the stack from S:User-Startup:
    Stack 32768
    Run <NIL: >NIL: C:tolunnet
    

Status & Known Limitations

Release state, test results and known limitations are tracked in STATUS.md.


License & Third-Party Credits

  • tolunnet is Copyright (c) 2026 Ismail Ozturk (tolon), licensed under the GNU General Public License v3.0 or later. See LICENSE.
  • lwIP (BSD-3-Clause) and the other third-party material, including the Roadshow SDK headers and the BSD network headers, are listed in THIRD_PARTY_LICENSES.md with their notices.

About

Open Source Amiga Full TCP/IP Stack

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages