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
bsdsocktestconformance suite.sshandscprun on it, and so do NFS mounts and ixemul programs.
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.
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 |
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.
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:Firmwarelacks are copied there from the archive'sDevs/Firmware, with their licences andWHENCE. - 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 aWireless.prefsexists. The passphrase appears as asterisks and is not written to the installation log. S:Network-Startupstarts the Wi-Fi only whenENV:Sys/Wireless.prefsexists: 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'sPRIORITY=10keeps 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.prefsthe installer did not write, or a mention inS:User-Startup,S:Startup-SequenceorSYS:WBStartup), the lines that would start a second copy are written commented out. S:AmiNetXDuo-WiFilists 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).
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.
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).
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.
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.
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.
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.
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.
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.
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.
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.
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.
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 |


