Provide BOOTP, TFTP (including SGI boot-tape TPD members) and the BSD rsh/rcmd service that IRIX inst needs. Map exec /bin/sh to mksh or dash and run the shell in a read-only bubblewrap sandbox with an IRIX-compatible dd wrapper. Add protocol tests and a usage guide.
5.6 KiB
IRIX network install server
tools/irix_netinstall.py is a single-file BOOTP + TFTP + rsh server for
booting the SGI PROM and running the IRIX inst network installer.
It is intended for a dedicated install network. rsh is unauthenticated by design.
Requirements
- Linux with Python 3.10 or newer.
mkshordash(the server prefersmksh).bubblewrapfor the read-only shell sandbox (recommended;--sandbox noneruns without it, but then absolute paths can reach the host filesystem).- Root, or the ability to bind UDP 67, UDP 69 and TCP 514.
- No other BOOTP/TFTP/rsh service on those ports.
On Debian/Ubuntu:
sudo apt-get install mksh bubblewrap
Install tree
The server serves an already-extracted IRIX distribution tree. It does not
mount ISO images or unpack tardist files itself. The paths used by the PROM
and inst are relative to --root:
/srv/irix/
6.5.30/
stand/
fx.ARCS
fx.64
sashARCS
sash64
dist/
...
install.cmds
The dist directory is what inst opens as the remote distribution. The
stand directory is what the PROM boots with bootp().
Run it
sudo ./tools/irix_netinstall.py \
--root /srv/irix \
--server-ip 10.0.0.1 \
--client-ip 10.0.0.2 \
--client-mac 08:00:69:07:dc:e0 \
--bootfile /6.5.30/stand/fx.ARCS
Useful options:
| Option | Meaning |
|---|---|
--l2-iface tap-mess-1000-0 |
BOOTP over AF_PACKET for MAME/QEMU taps |
--shell mksh / --shell dash |
force a shell |
--sandbox bwrap / --sandbox none |
force a shell sandbox mode |
--bootp-port, --tftp-port, --rsh-port |
non-default ports (testing) |
--allow-high-ports |
accept rsh clients from non-reserved ports (tests only) |
At the PROM:
setenv netaddr 10.0.0.2
boot -f bootp():/6.5.30/stand/fx.ARCS
For a 64-bit machine use fx.64; for the 32-bit IP22 Indy/Indigo2 use
fx.ARCS.
After partitioning, return to the maintenance menu, choose the software installation option, enter the server address and the distribution path without a trailing slash, for example:
/6.5.30/dist
Then load a command file at Inst>:
admin source 10.0.0.1:/install.cmds
What the services do
BOOTP
Answers RFC 951 requests on UDP 67. The reply carries:
yiaddr=--client-ipsiaddr=--server-ipfile= the file the PROM asked for, or--bootfile- the client's
chaddr, transaction ID and flags echoed
It can answer by MAC (--client-mac) and accepts plain UDP or AF_PACKET
(--l2-iface). The L2 mode exists because some emulated clients send from
0.0.0.0 in a way the host IP stack never receives.
TFTP
Serves RFC 1350 RRQ in octet mode. It opens a new UDP socket per transfer and keeps that socket's source port at or below 32767, because the 5.0 B6 and 5.1.2 B4 PROMs compare the server port as a signed 16-bit value.
It also supports the SGI boot-tape directory format:
bootp():/images/boottape(sash)
The first 512-byte block is checked for magic 0xACED1234 (or the
byte-swapped 0x3412EDAC), the checksum, and the 20-entry directory; only the
requested member's bytes are transferred.
rsh
Serves the BSD rcmd protocol on TCP 514:
- the client must connect from a reserved source port (512-1023);
- the server reads the stderr port, dials back before reading the user and command fields, then answers with a zero byte;
exec /bin/shis accepted and mapped tomksh, falling back todash;- stdout is the primary connection, stderr is the callback connection;
- callback bytes
0x02are forwarded to the shell's process group as SIGINT.
The host's /bin/sh is never changed.
Why mksh/dash, not bash or csh
inst runs exec /bin/sh and streams real POSIX shell lines: dd, cat,
ls, grep, pipes, subshells, trap, $?, and the marker idiom:
echo 'TOKEN\c'
Bash's builtin echo does not interpret \c by default (not even with
--posix), so the marker gets a literal \c and a newline. csh is a different
syntax family entirely and cannot parse the stream.
mksh and dash handle \c correctly. The server prefers mksh because it
is the shell used by the proven IRIX install guides.
The shell is run in a read-only bubblewrap sandbox:
- the install tree is bound at
/irixand each top-level entry is symlinked to/, so absoluteinstpaths such as/6.5.30/distwork; - host
/bin,/usr,/lib,/lib64and/etcare bind-mounted read-only; - a small wrapper directory provides an IRIX-compatible
ddthat acceptsiseek/oseekand refuses writes; egrep/fgrepwrappers map to GNUgrep -E/-F.
With --sandbox none, the shell runs with the install tree as its working
directory but can still reach absolute host paths. Use that only on an
isolated install network.
Tested
Protocol tests run without root on loopback:
cd tools
python3 -m unittest -v test_irix_netinstall
They cover BOOTP, TFTP file and TPD-member transfers, rsh shell sessions, the
\c marker, and dd under both none and bwrap. The server has not yet
been run against a physical Indy, so treat a real install as the acceptance
test.
Prior art
- instigator — Go server with
BOOTP/TFTP/rsh and a constrained POSIX interpreter; the best reference for
the
instshell vocabulary. - irixboot — Vagrant VM using isc-dhcp, tftpd-hpa and rsh-server.
- Remote IRIX 6.5 install from Linux
— the
mksh+in.rshd+bootp+tftpdrecipe.