This is "Roadshow" - A new TCP/IP stack for
AmigaOS by Olaf Barthel
1. Introduction
1.1 Christmas 2000
What did you do during those slow days between
Christmas Eve and New Year's Day 2000? I was reading Peter
Bogdanovich's book "This is Orson Welles" and was just about
starting to port a TCP/IP stack to the Amiga. Why that? You
may remember that the AmigaOS 3.5 update had shipped with an
evaluation version of Holger Kruse's "Miami" integrated TCP/IP
stack. A complete TCP/IP stack was to be included with the
AmigaOS 3.9 update in the form of "AmiTCP Genesis". However,
the question of who actually owned "AmiTCP", and whether it
could be included legally with AmigaOS 3.9, led to
complications. At the time I started working on my own little
pet project it was hard to tell whether any of the Amiga
TCP/IP stacks was still commercially available, or was still
supported by its developers. I became curious as to how
difficult it would be to port a TCP/IP stack to the Amiga.
1.2 A short look back at Amiga
networking
The first time I ever heard about TCP/IP
networking for the Amiga was when I chatted with a local Amiga
dealer way back in 1990. There was a new Commodore product for
sale (called "A225"), which promised to be a TCP/IP
implementation for the Amiga, using the Ethernet cards made by
Ameristar (which Commodore adopted as the A2065 Ethernet
card). I later learned that this was Commodore's attempt to
fill an important need: the Ethernet hardware had shipped far
earlier than the TCP/IP software, and there was no adequate
software support to speak of.
This first "official" Amiga TCP/IP stack was a
port of the BSD UNIX networking kernel, plus a set of
utilities and even a file system client for Sun's "Networked
File System". However, the software was literally hard-wired
to the A2065/Ameristar Ethernet hardware. I remember that only
a few applications actually used this hard-wired TCP/IP stack,
among these the game "Robosport" by Maxis, Inc. In that game
several players could compete in a network to blow up each
other's robots. While it did sport a null modem option, you
could actually play it via Ethernet in a local network if you
were using an A2065/Ameristar card.
What the Amiga was lacking at that time was a
standard driver design which could be used to hook up any sort
of networking hardware to networking software, such as a
TCP/IP stack. This driver standard eventually arrived in the
form of a proposal called "SANA" (for "Standard Amiga Network
Architecture"). More specifically, this was release 2 of the
standard, which is now known as SANA-II and was subsequently
revised even further. This proposal was published in 1991, but
it took its time to take root. For example, in 1992 Oxxi, Inc.
published a software package, which would allow for an Amiga
to be integrated into a Novell network. While the Amiga client
software was published after the SANA-II specifications were
made available, it did not support the standard and would use
custom driver software instead.
Among the first products to support the SANA-II
standard was Commodore's own "Envoy" peer-to-peer file and
printer sharing software for Amigas. Still, no TCP/IP stack
was in sight, which would support the SANA-II standard.
Commodore's Amiga networking group, the same people who
created "Envoy", was working on a revised and significantly
enhanced version of the original TCP/IP stack port. This was
to be called "AS225R2" ("S" presumably for "shared library").
The new TCP/IP stack was designed around a central shared
library called "socket.library" which implemented the BSD UNIX
networking API, the de-facto industry standard at that
time.
Unfortunately, Commodore decided to disband the
Amiga networking group, reassigning the engineers to different
projects. This stopped development of both "Envoy" and
"AS225R2" dead in their tracks. Commodore would never be able
to make up its mind whether to polish and publish the
software. This basically left the Amiga without an adequate
TCP/IP solution.
Things changed in 1993 when a student project at
the Helsinki University of Technology produced the first
TCP/IP stack for the Amiga which rivaled the functionality of
the stillborn "AS225R2" product: "AmiTCP" was born. Just like
"AS225R2" it would use the BSD UNIX networking kernel and the
associated utilities. However, the programming interfaces were
notably different. Software had to be specially adapted to
support "AmiTCP". It was definitely not a plug-in replacement
for "AS225R2".
Over the years there was a growing competition
between the "AS225R2" and "AmiTCP" designs. "AS225R2"
reemerged as a commercial product at Interworks, Inc. as
"INet-225" and "AmiTCP" was released as a commercial product
as "AmiTCP 4.0". Some applications supported both the
"AS225R2" and the "AmiTCP" programming interfaces, but as time
went by, more and more software was released to support only
"AmiTCP".
In 1996 two further Amiga TCP/IP stacks became
available for the Amiga: "TermiteTCP" by Oregon Research and
"Miami" by Holger Kruse. Both these TCP/IP stacks were
compatible with "AmiTCP". Especially "Miami" and later
"MiamiDeluxe" cemented the "AmiTCP" programming interface as
the de-facto standard for Amiga TCP/IP networking.
1.3 The present situation
While it has become increasingly important to
connect Amigas to the Internet it has become much more
difficult to do so. Today it's next to impossible to buy a
TCP/IP stack for the Amiga, let alone to buy an Ethernet card
specifically designed for the Amiga. "AmiTCP" is no longer
available for sale, and the author of "Miami" is no longer
accepting registrations for the evaluation versions available
for download.
2. Porting a TCP/IP stack to the Amiga
2.1 Curiouser and Curiouser
I was merely curious how difficult it would be to
port a TCP/IP stack to the Amiga. When I began to investigate
how this could be done, I had a good look at the last freely
available "AmiTCP" release 3.0. Before it was turned into a
commercial product, an early version was released, complete
with source code, under the General Public License (GPL). This
proved to be a good starting point as it explained how the
programming interfaces worked from the "inside". However, I
had to start over from scratch. The networking code "AmiTCP"
is based upon came from the BSD UNIX Net/2 release by way of
the MACH kernel into which it was integrated. In 2000, this
made the code in about ten years old. I thought that one could
do better than that. Also, it would not have been prudent to
adapt code from an implementation covered by the GPL, should I
eventually decide to create a commercial product.
I picked up the final 4.4BSD Unix release and
started to extract the networking code. In the "AmiTCP" design
you find both the central socket I/O functionality and
database access functions (for service names and domain name
resolutions). This had to be pieced together from kernel code
and the shared linker libraries. Isolating the required code
was the first step in porting it.
2.2 Memory and interrupts
The Amiga operating system and your typical Unix
kernel have next to nothing in common. AmigaOS is what you
might call a "microkernel" in which services such as message
passing and signal delivery connect application and operating
system software. In the Unix kernel you have special protocol
for application software to obtain kernel services, such as
invoking networking functions. And inside the kernel,
interrupts (as triggered by hardware and software conditions)
drive the processing of incoming and outgoing data.
In porting a Unix-hosted TCP/IP stack to the Amiga
you have to adapt the networking kernel code to the AmigaOS
architecture. For example, if a data packet arrives from the
network on a Unix system, an interrupt would be triggered,
causing the incoming data to be processed. On the Amiga a
packet would instead arrive in the form of a message in need
of processing.
In the BSD UNIX networking kernel I tried to port
you find that a hierarchy of interrupt levels governs the
processing of incoming and outgoing data. This interrupt level
hierarchy works as an arbitration mechanism: if you switch
into a higher interrupt level, lower level interrupts are
blocked until you switch back to a lower level. This mechanism
separates, for example, reception and transmission of
incoming/outgoing data packets and the processing of the data
they contain. The arbitration feature is similar to the
Forbid/Permit Amiga operating system functions, which are
typically used for arbitration to shared operating system or
Task resources. In fact, "AmiTCP" uses the Forbid/Permit to
emulate the multi-level interrupt hierarchy of the Unix
networking kernel.
Another peculiarity of the BSD UNIX networking
kernel is its memory management system. TCP data can be
fragmented, sent and received out of order, with sections
dropped, duplicated or resent. It must be possible to
reassemble this data into its original form, and this is where
the memory management system helps. It makes it easy to
shuffle and combine fragmented data. However, in order to
manage the fragmented memory efficiently and to be able to
release unused memory at times, a certain side effect of the
Unix kernel memory allocator is employed. This side effect is
in that memory blocks are allocated in "pages" which are
aligned to certain memory addresses. This sort of
functionality does not exist in Amiga operating system design
and must be emulated.
2.3 The smoke test
I worked on the first version of the TCP/IP stack
port for about two weeks. Gradually, it improved in terms of
speed and stability but there were still mysterious crashes I
could not explain. It did work rather robustly for extended
periods of time, and so I decided to take this prototype with
me to the annual MeKa meeting at the University of Karlsruhe,
which was to be held in early January 2001.
Traveling lightly, I only brought my trusty
A3000UX and an A2024 monitor with me -- no graphics card or
VGA monitor. That I could use only the Amiga's built-in
graphics hardware (the custom chip set) proved to be extremely
helpful. While I was testing the TCP/IP stack prototype I
noticed odd bitmap patterns to form on the display, like
crawling ants. Investigating the problem, which I had not seen
before as I was working with my Picasso IV graphics card at
home, I found that the memory management system I had written
for the networking kernel was faulty and ended up trashing
chip memory. It took me a while to fix the problem, but then
something important happened which was the turning point for
this little pet project: overall stability increased markedly
and performance literally went through the roof. Not a week
later my TCP/IP stack port outperformed both "AmiTCP Genesis"
and "MiamiDeluxe" during real life tests in my local network.
It was time to think seriously about turning the TCP/IP stack
into a commercial product.
3. Taking it seriously
3.1 Feature set
Holger Kruse's "MiamiDeluxe" set the standard for
the functionality an Amiga TCP/IP stack has to offer. It had
to support automated network configuration through the Dynamic
Host Configuration Protocol (DHCP), there had to be drivers
for dial-up networking (PPP) and broadband Internet access
(PPPoE), a firewall, IP packet filter and support for network
address translation (NAT), support for local server programs,
an optimized implementation of the secure socket layer
protocol and all of this would have to be accessible through a
graphical user interface.
That's a really tall order. And I believe only
"MiamiDeluxe" could deliver all of it in a single package. The
power comes with a price: "MiamiDeluxe" is a tightly
integrated program, which is 500KBytes in size, plus tools and
drivers.
Since I had other projects on my to-do-list, I
decided to approach the TCP/IP stack on a smaller scale. I
would try to support what was essential to the operation of an
Amiga TCP/IP stack and to use a modular concept. Also, I would
concentrate on the TCP/IP stack core and leave the work of
designing a graphical user interface to the people who would
want to license my work. Since some of the features that were
integral components of "MiamiDeluxe" were already available
separately (e.g. telnet/ssh client, secure socket layer) from
third parties, I decided not to implement them myself.
The features, which came out of the planning
process, are as follows:
- Compatible with the "AmiTCP" 4.0 API
- Amiga-ized configuration utilities rather than the terse
and cryptic Unix legacy tools
- The TCP/IP stack should be implemented by a single
shared library rather
- DHCP configuration for Ethernet devices; Zeroconf
support for address allocation
- Support for Ethernet and PPP drivers.
- Complete SANA-IIR3 support, including DMA access feature
- Berkeley Packet Filter support
- IP packet filter/network address translation (NAT)
- "TCP:" device support
- Enhanced API to allow developers to take greater control
of the TCP/IP stack, including features for monitoring and
packet filtering
- Integration into the AmigaOS installation; configuration
files go into DEVS: subdirectories, no special "Roadshow:"
assignment necessary
- "Simple" configuration: one single shell command can
bring up the entire network; no unnecessarily complex
configuration utilities
- Networking driver configuration concept similar to
"mount files", with drivers getting configured in the
Startup-Sequence
- Enhanced & cleaned up software development kit,
which includes the complete source code of all the
configuration tools and sample programs
- Changes to global configuration files tracked by file
notification; updates are made right after a change is
detected
- Support for local Amiga Internet server programs (inetd
style "Internet superserver")
- Multicast support
- Complete localization of all tools and error messages
- Portable, so that it could be rebuilt for use on the
PowerPC
This is in about the feature set that I started
out with and none of these features are missing in the current
release. I thought that as a developer, the software
development kit and the control you should have over the inner
workings of the TCP/IP stack itself should be most important.
What made Amiga products so useful in the past is that they
allowed developers to build upon the functionality they
offered, creating applications which the original designers
would not even dream of. For example, the enhanced API allows
you write your own personal firewall (if you don't want to use
the built-in firewall).
3.2 Dial-up networking
As work progressed on making the TCP/IP stack more
robust and useful I noticed that there was something missing.
Designed to be modular, the TCP/IP stack did not include a
built-in driver for the PPP dial-up networking protocol. At
that time, there would exist only three PPP drivers for the
Amiga: AmiPPP by Thomas Bickel and two different ppp.device
implementations by Holger Kruse and Emmanuel Lesueur. None of
these three was available for licensing.
There didn't seem to be much of an alternative to
writing my own PPP driver from scratch. This turned out to be
a challenging task, considering that just about everybody else
out there simply adapts or ports the existing Australian
National University PPP daemon. Yet this code was developed
for a Unix host and AmigaOS is not necessarily an adequate
environment for it to work in.
Getting the PPP driver written and tested took me
much of the year 2001. Since I was going to get ADSL for my
new home, work soon also included adapting the PPP driver to
support the PPPoE protocol, which is a method for wrapping PPP
data into Ethernet packets. There are other protocols which
serve the same basic need (e.g. PPPoA, PPTP and L2TP) but
which I found hard to support due to lack of adequate
hardware. Also, the complexity of the protocols, in particular
L2TP, is quite an obstacle.
During development of the PPP driver I found that
the SANA-II specifications did not cater particularly well for
dial-up networking drivers. At the time the standard was
developed dial-up networking was not yet an important
application. The typical network access was through Ethernet
and maybe ArcNet, using a static configuration. The dynamic
address configuration performed by dial-up networking drivers
(PPP or SLIP) was beyond the scope of the original design. And
the existing drivers so far had to resort to rather roundabout
methods for configuring their parameters and communicating
these to the application software (e.g. the TCP/IP stack). For
example, a common practice was to store these parameters in
environment variables, which were then read by a script file.
The script file would use the TCP/IP stack configuration
utilities to translate the contents of the environment
variables into network interface parameters.
Out of this work grew the proposed SANA-II,
release 4 enhancements which both Roadshow and the PPP drivers
support.
Due to how the PPP driver design evolved, it was
comparatively easy to implement support for the PPPoE
protocol. As a bonus, the implementation has very little
overhead compared to other designs. Where some drivers have to
parse and repackage plain PPP frames in PPPoE form, my PPPoE
driver will generate and process PPPoE frames on the fly
without any need for extra conversion.
The PPP and PPPoE drivers are designed to
interface to a wrapper program. That program performs the
dial-in operation and handles the driver configuration,
registering it with the TCP/IP stack.
The basic feature set of the PPP drivers is
comparable to the other available solutions. For example, Van
Jacobson header compression is supported, as is MS-CHAPv1
authentication. Data compression, however, is not covered due
to patent issues and general availability of the feature. Just
like the TCP/IP stack, the drivers are portable so that they
can be rebuilt for the PowerPC.
3.3 Putting it all together
The core package consists of the following
components:
- two shared libraries (bsdsocket.library and
usergroup.library)
- configuration files for routing, name resolution,
Internet services and the inetd-style superserver
- configuration and administration tools for the TCP/IP
stack
- configuration and administration tools for the IP packet
filter and network address translation (NAT)
- two PPP drivers (ppp-serial.device and
ppp-ethernet.device)
- tools which perform the dial-in and authentication
operations necessary to go online with the PPP drivers
This is the basic functionality, which is
available for licensing. For AmigaOS4, further application
software has been written which greatly enhances the basic
dial-in utilities supplied in the core package. Also included
is a preferences editor for managing the various configuration
files the TCP/IP stack builds upon, including the network
interface configuration. Also, the AmigaOS4 version of the
core package has been ported to the PowerPC, with the
libraries and drivers running as "native code" on the
machine.
3.4 How it works
The design of Roadshow is peculiar in that it
attempts to break away from the 'traditional' "AmiTCP" design,
which put all the TCP/IP stack functionality into a single
program, which then constructed the central
"bsdsocket.library" in memory. You actually had to launch a
program to make the TCP/IP stack work, and the TCP/IP stack
was active as long as that program was running. In my
implementation I took a hint from "AS225R2" and put all the
functionality into an actual standard Amiga shared
library.
How do you bring up the network and go online?
It's easy for highly-integrated packages such as "Miami": you
indicate which network interfaces should go online when you
push a button, which routes and domain name system servers
should be used and store this information in a configuration
file. When you start the program, you push a button and the
network goes online. In the traditional Unix approach, you
need to invoke a number of shell commands, which configure the
network interfaces and may in turn invoke other programs,
which handle the IP address negotiation and authentication.
Another program is used to establish the default routing
paths. "AmiTCP" would use this shell command based
approach.
With Roadshow it's a mix of both these techniques.
First you need to tell the TCP/IP stack which network
interfaces there are, and then you can configure them manually
or have them configured automatically. It basically works just
like with the file system mount files in the "DEVS:DOSDrivers"
directory: instead of file system configuration files, you
have interface configuration files, which are scanned during
the Startup-Sequence. For Ethernet drivers, you can have the
interfaces configured right after the have been "mounted". The
interface can use a static address or it can use the built-in
DHCP functionality to allocate an address, find the network's
domain name servers and establish a default route
(alternatively, a local IP address can be assigned through a
Zeroconf protocol). Default routing information and domain
name system servers can be configured in two local
configuration files (if you don't choose to use DHCP
configuration). Since Roadshow uses file notification to track
changes made to these files, you can even reconfigure the
network on the fly later just by changing the files.
All this happens early while the system boots, and
ideally, a single line in your Startup-Sequence will add your
Amiga to the network and make it go online. This is what I'm
using both at home and in my company. I turn the Amiga on,
wait until the Workbench appears, and by that time I'm already
online without having started another program or pushed
another button.
3.5 The firewall
For Roadshow I adapted Darren Reed's "IP filter"
package, which fit in nicely with the existing TCP/IP code.
This is quite a powerful package, as it supports both rule
based filtering, masquerading and network address translation.
The configuration is a bit of a rocky road, but it gets the
job done. You can actually use your Amiga as a firewall or
have it share a single PPP connection to the Internet with
other machines in the same network. In fact, I did just that
with my development system until I upgraded my home network
with an ADSL connection.
Roadshow itself sports built-in functionality,
which allows you to write code, which performs filtering and
rewriting of IP packets. You can use the same entry points as
the built-in IP filter to create your own firewall. Also
supported are hooks for monitoring which applications are
trying to establish outbound connections and for monitoring
inbound connections.
4. The future
Roadshow is my first attempt at porting a TCP/IP
stack and writing PPP drivers. On the whole, this has been a
learning experience, but it also produced something useful: a
platform solution application software can build upon. This
contrasts with the highly integrated TCP/IP packages, such as
"Miami", that have been so popular until very recently which
tried to deliver everything and then some in a single
program.
Truth be told, while the PPP drivers, the DHCP and
the Zeroconf support were written from scratch and very much
represent the current state of development, the TCP/IP stack
does not. I started with a BSD UNIX kernel, which is
significantly newer than the code "AmiTCP" was built upon, but
it is still significantly older than TCP/IP code used in
modern BSD UNIX operating systems, such as OpenBSD, NetBSD or
FreeBSD. This means, for example, that IPv6 is not
supported.
The missing IPv6 support is one of the drawbacks I
hope to resolve by eventually porting a more modern TCP/IP
stack. OpenBSD appears to be a very good choice for this
effort. However, considering that it took me almost two years
to get the initial 4.4BSD-Lite2 networking kernel ported and
polished, don't hold your breath for that task to be finished
or even started any time soon.
In the meantime, I hope that Roadshow will meet
your expectations. A lot of hard work went into making it.
P.S.: Where did the strange name "Roadshow" come
from? It came straight from the book "This is Orson Welles",
in which Welles repeatedly says that he would enjoy going on a
roadshow again.
© Copyright 2003 by Olaf
Barthel |