Skip to content

About

An IPv4+IPv6 TCP/IP stack for classic AmigaOS, and the networking commands to go with it. Provides bsdsocket.library on top of Eclipse ThreadX NetX Duo, driving the SANA-II cards you already have.

Topics

Resources

Security policy

Stars

23 stars

Watchers

0 watching

Forks

Repository files navigation

CodeQL

AmiNetXDuo

An IPv4+IPv6 TCP/IP stack for classic AmigaOS, with the network commands that go with it. It provides bsdsocket.library, the socket API that Amiga network software already speaks, on top of Eclipse ThreadX NetX Duo. It drives existing SANA-II network cards, and ships three SANA-II drivers.

It gets a DHCP lease, configures itself by SLAAC, answers ARP and neighbour discovery, and pings its gateway. It resolves DNS, moves TCP in both directions, does HTTPS, and accepts incoming connections from other machines. It scores 142 of 142 on the independent bsdsocktest conformance suite. ssh and scp run on it, and so do NFS mounts and ixemul programs.

Why

AmigaOS has never included a TCP/IP stack. Networking has always come from a third-party shared library, and each existing option has a limitation. AmiTCP 3.0b2 is free and dates from 1994. AmiTCP 4.x and Miami are proprietary and effectively unobtainable. Roadshow, the one modern stack, is commercial and closed.

AmiNetXDuo is MIT-licensed, with the exceptions named under Licence. It speaks the same socket API and reads the same configuration files as Roadshow, so existing software and existing habits carry over. It also speaks IPv6: on a network with an IPv6 router, a machine picks up an address without being configured for one.

Requirements

Any 68000 or better, AmigaOS 2.04 (Kickstart 37) or newer, 1 MB of RAM, and a SANA-II network card. One binary serves every 68k: the library picks the code for the processor when it opens, and nothing has to match the machine. The fat stack is the exception and needs a 68020 or better.

The archive carries four stacks. The installer asks which one to put on.

Stack Leaves out RAM while up
Full nothing 442 KB
Minimal IPv6, .local lookups, the packet filter, HTTPS, IPv4 multicast, the ARexx host, TCP: 272 KB
Micro all of that, plus getaddrinfo/getnameinfo, ancillary data, out-of-band TCP and less-used administration calls; carries one interface and no route or address-allocation calls. DHCP, the classic resolver and raw sockets work 243 KB
Fat nothing; the full stack, drivers and commands compiled for speed for a 68020 or better Full + 120 KB

AmiNetXDuo micro running on an emulated 68000 A500 with Kickstart 2.04 and 512 KB chip plus 512 KB trapdoor RAM

The micro stack running on a 1 MB A500: 512 KB chip RAM + 512 KB trapdoor RAM, with a 68000, Kickstart 2.04 (37.175) and Workbench 2.04. This Copperline session uses an emulated A2065 with SLIRP/NAT. The screenshot shows a DHCP lease, successful Internet pings and the available memory with NetMeter open. Installation used the modified Installer bundled with the archive.

Network cards

Any SANA-II driver works. The archive also brings its own:

Driver Cards
anxnet.device A2065, Ariadne, Ariadne II, AmigaNet, LAN Rover, X-Surf, X-Surf 100, X-Surf 500; PCMCIA: NE2000-compatible, D-Link DL10019/DL10022 (DFE-670TXD), 3Com 3C589, Megahertz/3Com LAN+modem
anxgenet.device Raspberry Pi 4/CM4 Ethernet, PiStorm32 with Emu68 1.1 alpha.1 or newer
anxwifipi.device Raspberry Pi 4 Wi-Fi, PiStorm32 with Emu68 (experimental)

The installer finds the card and writes the interface definition; on Emu68 it finds the Pi's Ethernet and Wi-Fi itself. On an Emu68 older than 1.1 alpha.1 it uses Emu68's own genet.device when one is installed; with no other network device found, it stops.

The Wi-Fi driver needs its firmware in DEVS:Firmware. With the Pi Wi-Fi selected, at every installer level:

  • The firmware files DEVS:Firmware lacks are copied there from the archive's Devs/Firmware, with their licences and WHENCE.
  • WirelessManager 1.5 goes into C: (or the installation's own drawer), unless a WirelessManager the installer did not put there already exists.
  • A window asks for the network name and passphrase and writes ENVARC:Sys/Wireless.prefs, unless a Wireless.prefs exists. The passphrase appears as asterisks and is not written to the installation log.
  • S:Network-Startup starts the Wi-Fi only when ENV:Sys/Wireless.prefs exists: WirelessManager first, then the interface, which waits at most 30 seconds for an address. With the Pi's Ethernet as well, both start, and the Ethernet's PRIORITY=10 keeps the default route on the cable; the Wi-Fi then starts in the background, so the boot does not wait for it. The micro stack starts only the Ethernet.
  • Where WirelessManager is already set up on the machine (a copy or a Wireless.prefs the installer did not write, or a mention in S:User-Startup, S:Startup-Sequence or SYS:WBStartup), the lines that would start a second copy are written commented out.
  • S:AmiNetXDuo-WiFi lists the Wi-Fi files the installer created; executing it removes them.

Use the driver or wifipi.device, not both in one boot.

Fast cards get faster TCP receive with every driver: the stack merges consecutive segments before TCP sees them. Driver authors can opt into a few SANA-II extensions for more (Developer/include/aminetxduo/anxs2ext.h).

X-Surf 100: enable flow control on the switch

For an X-Surf 100 using anxnet.device, enable IEEE 802.3x flow control (also called PAUSE) on the switch port the Amiga plugs into. Leave its speed and duplex on Auto; PAUSE needs a negotiated full-duplex link. If the switch offers separate receive and transmit PAUSE settings, enable both. This is a switch setting; there is no flow-control keyword to add to DEVS:NetInterfaces.

The 100 Mbit/s link can deliver bursts faster than the Amiga drains the card's small receive buffer. PAUSE lets the card briefly stop the switch before packets are lost. anxnet.device negotiates this automatically and the stack allows a larger TCP receive window while it is agreed. Without it, networking still works, with a smaller automatic window. Leave RXBUFFER unset; increasing it manually does not add memory to the card.

Add LINKSPEED=10 to the interface file to limit the X-Surf 100 to 10 Mbit/s while still negotiating duplex and PAUSE. Omit it or use LINKSPEED=AUTO for the normal modes. Reboot or remove and re-add the interface after editing it. The option requires an updated anxnet.device; the stack refuses the interface if the driver or card does not support the request.

See the manual, "X-Surf 100 and flow control", for setup checks, overrun counters and guidance for switches without this setting. The measured figures below are examples, not the card's link speed.

Measured on

What the numbers in this file come from, and what CI boots. A card or a machine not in this table is not known to fail; it is not known.

Machine Kickstart Card and driver Measured
A1200 + PiStorm32 Lite, Emu68 1.1 3.1 GENET, anxgenet.device (AmiNetXDuo extension path) 900 in / 580 out Mbit/s
A1200 + PiStorm32 Lite, Emu68 1.1 3.1 3Com 3C589 PCMCIA, anxnet.device 8.3 Mbit/s
A1200 + PiStorm32 Lite, Emu68 1.1 3.1 D-Link DFE-670TXD PCMCIA (DL10019), anxnet.device 9.4 in / 9.1 out Mbit/s at its default 10 Mbit/s link, AmiSpeedTest over a 24 ms path (2026-10-06)
A1200 + PiStorm32 Lite, Emu68 1.1 3.1 Broadcom 43455 Wi-Fi, anxwifipi.device 34-36 in / 52-61 out Mbit/s, 5 GHz at -69 dBm
A3000, 68030/25 3.9 X-Surf 100 (Zorro III), anxnet.device 3.8 in / 3.3-3.7 out Mbit/s
A3000, 68060/50 (TF4060) 3.9 X-Surf 100 (Zorro III), anxnet.device 22.5 in / 11.8 out Mbit/s with flow control on the switch port, 18.9 in / 11.7 out with it off (31fff37c, 2026-10-05)
A3000, 68030/25 3.9 ZZ9000, ZZ9000Net.device 2.2 3.6 in / 3.5-3.7 out Mbit/s
A3000, 68060/50 (TF4060) 3.2 ZZ9000, anxzz9000.device (not in the archive), firmware fork 22.2 in / 13.0 out Mbit/s (iperf, 2026-10-06)
Amiberry, A1200 (68020) 3.1 A2065, anxnet.device 4.8 in / 4.4 out Mbit/s
Amiberry, A3000 (68030) 3.1 X-Surf 100 (Zorro III), anxnet.device 30 in / 31 out Mbit/s
Amiberry, A600 (68000) 2.05 NE2000 PCMCIA and cnet.device boots, DHCP, transfers (CI)
Amiberry, A500+ / A2000 (68000) 2.04, 3.1 A2065, Ariadne II boots, DHCP, transfers (CI)
Amiberry, 68060 3.1 A2065 builds and boots (CI arm)

The separate emulator workflow boots Kickstart 2.04, 2.05 and 3.1 guests on 68000 and 68020 and runs DHCP, TCP and UDP transfers, Online/Offline, the installer and the card-eject path. Release end-to-end testing consumes the exact candidate archive produced by CI rather than rebuilding it. Roadshow and AmiTCP_NG coexist on the same disk, selected at boot (SYS:Stacks).

Installing

Download the .lha from Releases, unpack it, and run Install-AmiNetXDuo. It asks:

Question Default
Which stack: Everything, Minimal, Micro, Fat Micro through 2 MB, Minimal below 8 MB, Everything from 8 MB; Fat under Emu68 from 8 MB
Into the system (LIBS:, C:, DEVS:), or into its own drawer, added last to those assigns; refused if LIBS: already has a bsdsocket.library (Intermediate and Expert) into the system
Where the AmiNetXDuo drawer of documentation and examples goes (Expert, and a new drawer installation) SYS:
Which card; the interface name at Expert the cards found
Answer to <hostname>.local on the network (Expert) yes on a 68020 or newer, no on a 68000 or 68010
DHCP, or a fixed address, netmask and gateway DHCP
The machine's name (Expert) amiga- and the card's last three address octets
Start the network at boot (Intermediate and Expert) no for Micro or machines with 4 MB RAM or less; yes otherwise
Start httpd at boot, exposing mounted volumes with a browser file manager and Shell; the port at Expert no, 80
Set the clock at boot, and from which server (Expert) yes, pool.ntp.org

The configuration follows the layout of Roadshow: DEVS:NetInterfaces/<name> defines an interface, DEVS:Internet/routes, DEVS:Internet/name_resolution and the /etc-style netdb files hold the rest. A definition does not start its interface. S:Network-Startup does, one AddNetInterface line per interface, and S:User-Startup runs that file. An installation from 0.26.x or earlier needs that one line added.

The archive also holds Docs/AmiNetXDuo.guide, the manual; Examples/, a commented copy of every configuration file; and Developer/, the headers that the NDK does not declare and the CPU profiler.

Commands

NetSetup ask the questions for one interface, and write the configuration files
NetPrefs Workbench editor for interface, address, device and tuning settings; preserves comments and unknown keywords
NetMeter small Workbench window: each interface's addresses (click one to copy it) and its receive and send rates
NetSwitch Workbench window listing each interface's state and address; takes the selected interface online or offline
NetWireless Wi-Fi commodity: the link's state and signal as an AppIcon, a Tools menu item and ENV:WiFi; reads the signal only while connected
NetWirelessPrefs Wi-Fi networks in range and joining one; writes WirelessManager's Wireless.prefs with the derived key, not the passphrase
AddNetInterface, RemoveNetInterface start an interface from its file, and take one out of the running network
Online, Offline put a started interface on the wire and take it off
ConfigureNetInterface change the address or MTU of a running interface, renew or release its DHCP lease, turn .local answering on
ShowNetStatus, netstat interface state, addresses, routes, connections, multicast groups, counters
ShowNetServices what else on this network is offering something
ping, host, nslookup reachability, name lookups, and one kind of record from a named server
arp the machines on this network that have answered, IPv4 and IPv6
sntp set the clock from a time server
fetch retrieve an http:// or https:// URL
httpd expose mounted volumes over HTTP and WebDAV, so other machines mount them as one drive. -F adds a browser file manager, -T a Shell, and -C the machine's display
nc connect or listen, TCP and UDP, port ranges, timeouts
iperf measure throughput against an iperf server, or act as one
telnet negotiates the options that a real server requires
ssh, scp Dropbear's clients, public-key authentication, scp in both directions and recursive
NetCapture capture what is on the wire to a .pcap file, filtered by host, port or protocol
NetTrace the same file for a transfer it runs itself, with the throughput number beside it
traceroute, tftp, whois trace the path to a host, and small TFTP and WHOIS clients
CheckNetConfig read the configuration and report what is wrong with it
CheckNetDevice what anxnet.device or anxgenet.device found and why a card was refused
NetDevStats every standard and driver-specific SANA-II counter for one unit
CreateAmiNetXDuoStatusReport versions, settings and counters in one file to attach to a bug report
AddNetRoute, DeleteNetRoute where packets go that are not for this network
GetNetStatus, NetShutdown status for scripts, and a clean shutdown
hostname the name of this machine, and where the name came from

The installer copies all of them into C:; a system installation also places the NetPrefs and NetWirelessPrefs programs and icons in SYS:Prefs, NetMeter and NetSwitch in SYS:Utilities and NetWireless in SYS:Tools/Commodities; a drawer installation places all five in its drawer. C: carries no icons. Every command that resolves a name takes -4 and -6.

Files, a Shell and the display in a web browser

httpd -F serves a file manager at http://<address>/files. It browses the mounted volumes and opens, uploads, creates, renames and deletes files and drawers through the same WebDAV interface that desktop file managers mount. Its CodeMirror editor provides line numbers, undo and redo, search, and Ctrl/Cmd+S saving without leaving the browser. Saves carry the file's ETag, so a copy changed after it was opened is refused instead of overwritten. It detects extensionless Amiga text such as startup-sequence, while keeping binary files as downloads. Nothing is fetched from the Internet; the whole page is about 107 KB compressed. Starting httpd with an explicit drawer, such as httpd Work:Public 8080 -F, keeps the older restricted-share form and exposes only that drawer.

httpd -T serves an AmigaDOS Shell at /shell, beside the volumes that it already shares. httpd -C serves the machine's display at /console, chipset and RTG screens alike. The installer offers to start the volume server, file manager, Shell and display when the machine boots.

On a Zorro III MNT ZZ9000, /console can move both framebuffer readback and delta encoding from the 68k to the card's ARM processor. httpd detects the console-encode service automatically and falls back to its normal 68k path when the service is absent, so there is no setting to maintain. On the 25 MHz A3000 this raised a continuously dragged ZZ9000 Workbench from about 0.5 to about 10 frames per second. The required firmware, a ready-to-flash BOOT.bin, installation instructions and rollback instructions are in the AmiNetXDuo ZZ9000 firmware fork.

A live AmigaDOS Shell in Chrome

A live Amiga Workbench display in Chrome

The Shell is a real console, not a pipe. Ed and More work, and so do the cursor keys and the history. A program that asks how big the window is gets an answer. On an A1200 the prompt appears in 44 ms, and a press of Return shows the output about 23 ms later.

There is no password. Anyone who can reach the port gets the Shell, the display and every mounted volume.

For automation, the host-side remote-control tool turns a Shell command into JSON output with an exit code and timeout, transfers files through WebDAV, and captures or controls the display with PNG feedback.

Finding the machine by name

The Amiga answers to <hostname>.local on the local network, so another machine reaches it by name with no DNS server and no configuration. .local names resolve from the Amiga in the other direction too. This matters most when there is no DHCP server at all: the machine gives itself an address and is still reachable.

The responder is per interface and off until asked for, because it costs time on a slow machine. The installer asks. The setting is MDNS=YES in DEVS:NetInterfaces/<name>, or ConfigureNetInterface <name> MDNS=YES on an interface that is already up. The minimal and micro stacks do not carry it.

ShowNetServices lists the kinds of service that answer on the network; a named kind lists the machines behind it with their addresses and ports; ALL lists every instance of every kind. Printers, NAS boxes, media players and anything that runs Bonjour or Avahi appear without being configured anywhere.

HTTPS and SSH

fetch handles https:// URLs. Certificates are checked against Mozilla's root set. The cryptography is in tls.library, a separate library with its own SDK that also runs on Roadshow, AmiTCP and Miami, and that handles the server side of a handshake and ALPN as well.

A first handshake is the cryptography, not the network: about 4 to 9 seconds on a 68020, a minute or two on a 68000. A second connection to the same site takes under a second, because the session is kept in DEVS:Internet/tlssessions and survives a reboot. The minimal and micro stacks do not install tls.library.

ssh needs no special configuration at the far end and reaches the prompt in about five seconds on an A1200. Keys must be in Dropbear's own format; an OpenSSH key copied straight across is not read. Name the key with -i, and generate it on a PC, which has the entropy and the speed for it. The manual has the exact commands.

Existing software

Software that resolves a name with getaddrinfo() and connects to whatever it returns works over IPv6 without being changed. Software written for IPv4 keeps working over IPv4. A program is IPv4-only when it resolves with gethostbyname(), keeps an address in 32 bits, or reads a dotted quad out of a configuration file; for such a program the change is to resolve with getaddrinfo() and hand the result to connect().

usergroup.library reads an existing AmiTCP 4 passwd and group as they stand. AmiNetXDuo does not claim AmiTCP:; ixemul programs that use the literal AmiTCP:libs/usergroup.library path are satisfied by the already resident library, while an existing AmiTCP assign remains untouched. NFS mounts with ch_nfsc authenticate. The full, minimal and micro profiles carry four, two and one interface respectively, and the first one named to AddNetInterface owns the default route.

In the full profile, the whole of AmiTCP's socket_lib.fd (45 vectors) is implemented. Of Roadshow's 125, 21 answer ENOSYS: the tunables API (ObtainRoadshowData and friends), the IP filter/NAT API (ipf_*) and the kernel-memory API (mbuf_*); SBTC_HAVE_* reports each truthfully, and docs/GAPS.md lists every one with what a program loses. crypt() is a stub: a ported server that authenticates against passwd cannot. A survey scanned 5,907 Aminet archives (docs/aminet-survey); among the strictly attributed binaries it found no caller of any of the 21. Attribution covers 399 of the 559 archives that contain a bsdsocket binary (71%), so that absence is strong evidence, not proof.

Building from source

docs/DEVELOPMENT.md covers the build, its options, the test suites, continuous integration, the measurement method and the CPU profiler.

The project-priority matrix records the current support, compatibility and release-safety priorities separately from the known-defect backlog.

Acknowledgements

Thanks to Rondoval for a detailed external review of the SANA-II extension design. His criticism prompted the move of GRO into the stack, relocation of private commands out of the NSD-reserved range, and replacement of borrowed SANA-II fields with a versioned private extension record.

Licence

AmiNetXDuo is an independent implementation of a published ABI. No implementation code from AmiTCP, AROSTCP, Miami or Roadshow has been used, copied or disassembled. The ABI comes from interface definitions and documentation that exist to be read: Olaf Barthel's freely distributable Roadshow SDK headers and autodocs, the NDK's pragmas/bsdsocket_pragmas.h, and the .fd and .sfd function-descriptor files that AmiTCP and Roadshow publish.

MIT, with these exceptions, each confined to the files it names:

What Licence Where
ThreadX and NetX Duo MIT (Microsoft and the Eclipse ThreadX contributors). Both are maintained forks, pinned by the submodules; docs/UPSTREAMING.md records their divergence and upstreaming plan third_party/threadx, third_party/netxduo
The NE2000 core of anxnet.device BSD-2-Clause, adapted from NetBSD's dp8390 driver src/netdev/dp8390.c, ne2000.c, ed.c, netdev_mcaf.c
ssh and scp Dropbear's MIT-style licence third_party/dropbear, clients/dropbear
The bundled Installer Original Commodore-Amiga and Sylvan Technical Arts copyrights retained; modified Installer 2.17, separate from the stack's MIT licence install/Installer; provenance and original notices in docs/user/Installer-NOTICE.txt
The /files text editor CodeMirror 6 and its support packages, MIT bundled into src/tools/web/files.html; notice in src/tools/web/vendor/codemirror
The CA root set MPL 2.0, Mozilla's, file-scoped DEVS:Internet/certificates, from third_party/cacert
WirelessManager wpa_supplicant's three-clause BSD licence, Copyright (c) 2003-2010 Jouni Malinen and contributors, (c) 2011-2025 Neil Cafferkey. The unmodified binary from Aminet driver/net/prism2v2; its notice ships beside it and is installed as WirelessManager-LICENSE third_party/wirelessmanager
anxwifipi.device MPL 2.0 (Michal Schulz's WiFiPi.device, forked; ISC Broadcom/OpenBSD headers and an Apache-2.0 register header inside it, listed in its NOTICE). File-scoped: its sources are the submodule's and are published there third_party/wifipi, built by src/wifipi/CMakeLists.txt

About

An IPv4+IPv6 TCP/IP stack for classic AmigaOS, and the networking commands to go with it. Provides bsdsocket.library on top of Eclipse ThreadX NetX Duo, driving the SANA-II cards you already have.

Topics

Resources

Security policy

Stars

23 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages