CPC/IP - A TCP/IP stack for Amstrad CPCs
CPC/IP is an implementation of the
PPP, SLIP, IP, ICMP, UDP, TCP, DNS, TFTP, HTTP, ping, finger and telnet
protocols for
Amstrad CPC
computers with an Amstrad, Pace or
CPC Amstrad International serial interface.
The code occupies about 14K,
excluding the serial, filing system and IP buffers.
What's new?
-
2000-10-15 (CPC/IP v0.12)
Improve portability by introducing a
standard I/O API
(use this in the HTTP server
(fixes problem with serving binary files);
note the TFTP server
has not been updated yet).
Extend the Amstrad serial interface device driver
to support polling, parity, more stop bits and not using hardware flow control
(no hardware flow control is now the default for the executable).
Extend the configuration to allow
finer control over the components included in the build.
Add some hints on starting a port.
Tweak head in cpcsutils
to support files bigger than 64K.
-
2000-07-02
Update the Z80 assembler.
-
2000-03-12 (CPC/IP v0.11)
Improve PPP layer: make more robust against
remote rejection, add requesting of DNS server address to use, and
add peer PPP tickle (use Copy to send this, immediately after the
physical link has been established).
Update the Z80 assembler.
-
2000-02-29
I wanted to release something on this cool date, but
unfortunately I was ill. Oh, well...
-
2000-01-23 (CPC/IP v0.10)
Add support for PPP (but SLIP
remains the default for the executable for now).
Add support for 64K machines
(this is now the default for the executable) in
the Amstrad serial interface device driver
and loopback driver.
The telnet client now reports when
the connection has been established (incidentally, you can
now enter a bare CR (i.e. not a CRLF) using Enter).
Note you'll need to recompile ZMAC 1.1.1.2
with MAXIFS on line 55
#defined to 1024, say, if you want to use that to assemble CPC/IP;
I haven't tried assembling CPC/IP with Maxam for quite
a while now!
Also, the config stuff has moved one byte up (in case you're
using a loader to set things like your address and DNS server,
or DNS zone, or hosts.txt) and all the config stuff which used
to be in main.z
is now in config.z.
-
2000-01-01 (CPC/IP v0.09)
Nothing to report. It's not even clear CPC/IP v0.09 ever existed.
Ask ARM about the ARM4 and ARM5
for more details.
-
1999-12-19 (CPC/IP v0.08)
Add resolver and
nameserver lookup client;
default nameserver is 127.0.0.1 (localhost).
Speed up telnet
console output.
Add nameserver address and domain name to
configuration; the nameserver address
can be set with the addr module.
A few miscellaneous little bug fixes.
-
1999-11-28 (CPC/IP v0.07, the birthday release!)
Release tipi, the HTTP/0.9 server.
Improve the TCP layer, so it's at least plausible.
Improve telnet, in particular so it can function
as a console
(with a suitable terminfo).
There's a hosts.txt-like mechanism,
which the clients now use.
Add driver for the CPC Amstrad International serial
interface, courtesy of Tim RIEMANN.
Note the code is now loaded at &3800 with HIMEM at &27ff,
CPC/IP's default IP address is now 192.168.6.128,
Ctrl-[ should be used to abort a telnet connection,
and Ctrl-Esc should be used to quit CPC/IP -- or use the new quit command.
-
1999-10-03
Update the Z80 assembler.
-
1999-09-09 (CPC/IP v0.06)
ping and (basic) telnet
clients added. Loopback support added.
TCP layer still exceedingly rudimentary!
ICMP checksums now fully supported.
The command-line interface has been extended
to support multiple clients.
-
1999-08-08
Release a mode 2 text accelerator.
Tweak the set-up details a bit more.
-
1999-07-18
Release a Z80 assembler.
Improve this document (add more links and more set-up details).
-
1999-07-04
Fix bug in the screen saver:
it wouldn't work with a 464 with a disc interface.
-
1999-06-27 (CPC/IP v0.05)
Release DNS server.
-
1999-06-20
Release CPC screen saver
and Z80 symbolic disassembler.
-
1999-06-06 (CPC/IP v0.04)
Forgot head.c in cpcsutils!
Minor tab-handling bug fixed.
This file added (as documentation) to
the zipped sources.
Serial device driver optimised.
-
1999-05-31 (CPC/IP v0.03)
Very rudimentary TCP layer implemented;
enough for a finger client.
TFTP server now handles AMSDOS errors
and reports them remotely.
Miscellaneous improvements and bug fixes.
A bunch of |BLOW and |SUCK utilities,
cpcsutils, and documents on
AMSDOS and
Amstrad serial interface features.
-
1999-05-03 (CPC/IP v0.02)
UDP layer and
TFTP server (writes only) implemented.
Source exploded into multiple files, and made more modular and documented.
A couple of bug fixes.
This document updated and expanded a bit.
-
1999-04-18 (CPC/IP v0.01)
It's all new.
Compatibility
CPC/IP is compatible with the following Internet protocols,
with the limitations listed further below:
Unsupported features
Some of these limitations make this implementation non-compliant as per
RFC1122 and
RFC1123.
You'll have to decide for yourself how significant the non-compliances are!
-
A proper and documented API. In particular, the TCP
stuff is a pretty monstrous hack with lots of collusions. The TCP layer
doesn't pay any attention to windows, doesn't have
a retransmission timer, doesn't do urgent data and
closes connections in a rather abrupt way!
It needs a complete rewrite...
-
IP fragmentation (the MTU is over 1020 octets, though).
-
All the IP option fields. They are ignored.
-
All the error detection and recovery of TCP. This is a bit of a bummer.
-
Handling all the ICMP messages except for ECHO.
-
TFTP RRQ (so files can't be fetched from CPC/IP).
-
Recursive DNS queries (hey, they're not mandatory!).
DNS on TCP (so zone transfers don't work).
-
telnet commands, apart from the option commands,
and telnet options, apart from echo and suppress-go-ahead.
-
The resolver might give the wrong address
for a hostname (this would occur if a nameserver gave an A RR for
something like another nameserver before it gave the address for
the given hostname)!
Oh, and
CPC/IP doesn't support streaming RealVideo.
Portability
Although CPC/IP officially only supports Amstrad CPCs
with Amstrad serial interfaces, it should work on compatible
systems. The important points are that
-
The serial chip must be Z80-DART-compatible, and be located
at &fadc/fadd. The chip's interrupt line must be connected.
-
The clock generator must be CTC-8253-compatible
and be located at &fbdc/fbdd/fbdf. It must be clocked
at 2 MHz.
Note the Pace serial interface satisfies these requirements,
except that the interrupt line is not connected. It
must therefore be polled. In turn, this means the datarate
should be 4800 bps (though 9600 bps may be achievable if
8E2 or maybe just 8N2 framing is used -- it is in fact only
necessary to use two stop bits on the remote side, so you
might be able to get away with 8N1 on the CPC). You will need to
make appropriate changes in config.z
and rebuild.
A device driver for
the serial interface which appeared in CPC Amstrad International
1992-06/07 is available; you'll need to change a line at the top
of config.z and rebuild to use this
(but note this currently does not support 64K memory configurations).
If you want to use the full 128K, then if your machine isn't
a CPC6128 the important point is that
-
The 128K must be selectable using OUT (&7fxx), &cx.
32K is used for rx/tx buffers and 16K is used for a loopback buffer;
the rest may be used in the future to
hide most of the code out of the main 64K.
Failing all this, though, it shouldn't be very difficult to port the
system-dependent bits to a different system.
How to use
(The following assumes connection to a Linux box, and specifically
to the version of Linux which happens to be on my box at home.
I'm not a Linux guru, so it's unlikely I'll be able to help if
the Linux bits don't work for you or make no sense!
You can also connect straight
to an ISP via a modem (ignoring all the bits about setting up the peer),
as long as, if you're using SLIP, you use addr to set your
IP address everytime if your ISP gives out non-static IP addresses.
Note: the Amstrad serial interface, at least, won't receive
unless Carrier Detect is active, if hardware flow control is being used.
If you can't get your modem to
force it active via a DIP switch, you'll have to type "AT&C0" blind
to do so in software.)
-
Somehow get CPC/IP into your CPC.
Your options are:
-
Get the zipped sources,
unzip them, transfer them onto a CPC disc,
edit config.z to specify your CPC's IP address
unless you're happy with the default 192.168.6.128,
load main.z into Maxam
and assemble it (set HIMEM to &27ff). The sources consist of
config.z,
main.z,
telnet.z,
finger.z,
host.z,
ping.z,
addr.z,
httpd.z,
tftp.z,
dns.z,
resolv.z,
tcp.z,
udp.z,
ip.z,
icmp.z,
slip.z,
ppp.z,
fcstab16.z,
loopback.z,
cs.z,
stdio.z,
serialdd.z/cpcaisio.z,
hosts.z,
cons.z,
printlib.z,
utillib.z,
linklist.z, and
timer.z.
-
Get the executable,
change the third to sixth bytes to specify your CPC's IP address
(or remember to set this at run-time as described below) unless
you're happy with the default 192.168.6.128,
transfer the file into your CPC,
and load it to &3800 (set HIMEM to &27ff using
"MEMORY &27ff").
-
Assemble it all using ZMAC and proceed as
above with the executable.
-
Remember, if you're trying to transfer a binary file to a CPC it
must end up with an AMSDOS header.
Put an AMSDOS header on using something like
"head main.bin -l3800 -fcpcip.bin >cpcip.bin"
(see cpcsutils for head).
You can then transfer the file using
"A$ = "cpcip.bin" : |SUCK, @a$"
on the CPC and "blow cpcip.bin" (from the same package) on the source box,
or tftp (remember to use binary mode!) if you've already managed to get
just about any version of CPC/IP on your Amstrad CPC.
-
Set up the serial port on the peer. You'll need to:
-
Set the serial port to use 8 data bits, no parity, and 1 stop bit.
I think this is normally the default, which is a good thing because
I don't know where or how to change it (though I suspect suitable stty
lines somewhere in /etc/rc.boot/0setserial might do the trick)!
-
Edit /etc/inittab to allow connection via this serial port,
at 9600 bps (or 2400 bps if using the CPC Amstrad International
serial interface) and using hardware flow control, if appropriate.
This is what I've got:
T1:23:respawn:/sbin/getty -L -h ttyS1 9600
-
Use /sbin/init q to cause this file to be reparsed
(only necessary the first time).
-
Launch CPC/IP! "CALL &3800". You should see a login prompt.
Log in using any account, to check the serial link is working OK.
Log out.
-
Set up SLIP or PPP on the peer.
If you want to use PPP, you're probably best off
contacting me for further
details. If you want to have a go on your own, be aware that
(a) the peer needs to support PAP, if it wants to authenticate,
and you need to enter your PAP details in config.z,
(b) there are no timeouts in the current implementation, so it
could all just seize up,
(c) there are no state checks in the current implementation, so it
could all go haywire,
(d) I would dare to suggest there's a bug in pppd version 2.3 patch level 5,
which means you should turn off Van Jacobson compression (using "novj").
For SLIP you'll need to:
-
Create a suitable account using adduser.
-
Make this account use /usr/sbin/sliplogin as its shell.
-
Suitably edit /etc/slip.hosts (use DYNAMIC as the remote address).
-
Suitably edit /etc/slip.tty (to specify your CPC's address).
-
Modify /etc/slip.login to make the MTU 1006 (CPC/IP would support 1023
but this is the Berkeley SLIP limit).
-
Make sure /usr/sbin/sliplogin is setuid (use "chmod u+s" if not)
and the SLIP account has execute permission (fiddle with /etc/group if not).
-
Add your CPC to /etc/hosts using the address you allocated (optional).
Alternatively, you could use slattach and ifconfig (as root), if you
can work out the parameters (it's not particle physics). Here
is a hint:
slattach -L -p slip -s 9600 /dev/ttyS0 &
ifconfig sl0 192.168.4.86 pointopoint 192.168.6.128 up mtu 1006
-
Go back to your CPC. Log in using the SLIP account.
You should now be able to use the stack:
-
You should be able to ping your CPC.
-
You should be able to transfer files to your CPC using TFTP
on the remote machine.
The filename should be AMSDOS-friendly, your disc should have
enough free space, etc. Transferring files from your CPC using TFTP isn't
possible yet, unfortunately.
-
You should be able to fetch files from your CPC using tipi,
the HTTP/0.9 server.
The URL to use is just what you'd expect; something like
http://sugar/index.htm . Note if you're serving non-ASCII
files, they should have AMSDOS headers;
head from cpcsutils may be useful!
-
You should be able to make DNS queries regarding the
bufo-house.org domain. Type things like "host -a cpc [CPC]"
and "host -a bufo-house.org [CPC]", where [CPC] is
your CPC's IP address, on the remote machine.
To use your own choice of DNS information, you can rebuild CPC/IP after
changing dns.z, or you can load a DNS zone
file into memory and place the base address at &380d.
-
To use any of the clients CPC/IP will have to realise/believe a SLIP
connection has been established (shown by the presence of a
command-line prompt ("> ")). One way to do so is to ping
your CPC once. Another is to press Copy.
-
In all the clients you can use textual addresses defined
in hosts.z. By default these are
localhost (127.0.0.1), sugar (192.168.6.128) and
koaks (192.168.4.86).
To use your own choice of hosts, you can rebuild CPC/IP after
changing hosts.z, or you can load a
hosts.txt file into memory and place the base address at &3807.
-
If you want to change your CPC's address (only important for
clients and if you didn't suitably set this in the source/executable
if you don't want to use the default 192.168.6.128)
you can use addr. As for all the clients, you can
get the syntax by entering the command name on its own.
Note the clients may be more permissive regarding syntax than
the syntax help would suggest; you should not rely on any
short-cuts you find working in future versions of CPC/IP!
-
If you want to set the nameserver you can also use addr. The
default nameserver is 127.0.0.1 (localhost, your CPC), which
doesn't serve much! The nameserver should preferably support
recursive queries, because the resolver doesn't!
-
You should be able to finger other machines from your CPC.
Remember by default there's no world-wide nameserver,
so you'll have to type numeric addresses!
You can use Ctrl-C to abort a connection.
-
You should be able to ping other machines from your CPC.
This is one of the only two things you can ("usefully") do without a
serial interface: specify a loopback address such as 127.0.0.1.
Note the numeric parameters in this command should be less
than 256.
You can use Ctrl-C to abort pinging.
-
You can also make nameserver queries using host; this is the other thing
you can do without a serial interface. For a hostname, you can either get
all the numeric addresses corresponding to it,
or all DNS information (using -a), or mail
exchange information (using -m). You can also do reverse lookups
on numeric addresses.
You can use Ctrl-C to abort a lookup.
-
You should be able to telnet to other machines from your
CPC. You can use Ctrl-[ to abort a connection.
Because of limitations in the TCP layer, your telnet
connection may get stuck. Also, don't try telneting from
CPC/IP to CPC/IP on port 80 (HTTP) unless you like network
storms.
Install this terminfo file using "tic cpc.tmi"
(as root),
select it using "export TERM=cpc" or your shell's equivalent,
and you'll have a fully-functional console.
The arrow keys work; Ctrl-Left/Right will do Home/End,
Ctrl-Up/Down will do Page Up/Down, Clr will do Delete, Esc will
do Esc, and Ctrl-Tab will do Insert.
-
There is a resolver which the clients automatically use if the
address given isn't numeric and isn't in
hosts.txt. This will
automatically append the domain name specified in
config.z -- "bufo-house.org"
by default (rebuild to use yours!) -- to addresses without dots.
If you need to make
sure this doesn't happen for any reason, make the address
absolute by putting a dot at the end.
DNS is a bit of a monster, and so the resolver may well go
wrong! If it does, please tell me,
specifying the nameserver you were using and the query you were making
(the address you were trying to resolve).
-
Press Ctrl-Esc to escape from CPC/IP. (If after acquiring a SLIP
link you find you need to use CPC/IP as a terminal again
(e.g. because your link fell over), press Copy.)
Well, wasn't that worth it?!
Other 8-bit TCP/IP stacks
Tangents
What next?
If you like what you see, and would like things to go further,
then please get in touch. If no-one cares, there's not much
point (although it's quite an educational experience implementing
the protocols).
As you will see if you look at the code, it's reasonably
well structured (within the limitations of Maxam), and hooking
in new stuff shouldn't be too difficult. The most interesting
bit will be to work out how to allow things to hook in and then
be called in the background. I've been thinking of schemes
using OS events, but nothing's very firm yet. Currently the
serial device driver is interrupt-driven, but the protocol
stack is essentially polling-driven.
Can you contribute?
-
If you're an Internet guru (or even if you're just keen!)
and would like to contribute to CPC/IP, please get in touch.
-
I don't know very much about the Internet protocols
(just about all I know comes from reading the RFCs), and I
could do with advice (for instance, which IP options and
ICMP messages are, realistically, worth implementing?).
-
Perhaps CPC/IP could become PCW/IP or S128/IP? The most important
point to consider here is that CPC/IP uses both IX and IY.
Please email me
if you're even remotely interested in doing a port.
All you need to get a basic pingable system is to:
-
Copy cs.z, icmp.z, ip.z, main.z, slip.z, printlib.z, utillib.z as is.
-
Copy config.z, changing values as appropriate (making sure you
turn off all the bits you can).
-
Write serialdd.z.
-
Write stdio.z. You don't need the FILE_* or KL_* routines; the other
routines need not be perfect.
-
Perhaps device drivers could be written for other Amstrad serial
interfaces (the only file which should need changing is
serialdd.z) -- see
cpcaisio.z for an example.
-
Perhaps you'd like to write a TFTP client, or an FTP client,
or an IRC client, or a WWW browser, or a POP3 client,
or an SMTP client, or an NNTP client, or an NFS client...
Copyright
Although I ultimately plan to make CPC/IP available Free,
at this stage in its evolution I would like to keep it
under reasonable control.
CPC/IP is Copyright (c) 1999-2000 Mark RISON.
You may not distribute it without my permission (this includes
modified/extended versions).
Try emailing me
for permission -- you should be pleasantly surprised!
Thank you for respecting this.
Mark RISON,
<mrison@hotmail.com>,
2000-10-15
Thanks to Franck ARNAUD for hosting these pages.