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.
187 lines
5.6 KiB
Markdown
187 lines
5.6 KiB
Markdown
# 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.
|
|
- `mksh` or `dash` (the server prefers `mksh`).
|
|
- `bubblewrap` for the read-only shell sandbox (recommended; `--sandbox none`
|
|
runs 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:
|
|
|
|
```sh
|
|
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
|
|
|
|
```sh
|
|
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-ip`
|
|
- `siaddr` = `--server-ip`
|
|
- `file` = 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/sh` is accepted and mapped to `mksh`, falling back to `dash`;
|
|
- stdout is the primary connection, stderr is the callback connection;
|
|
- callback bytes `0x02` are 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:
|
|
|
|
```sh
|
|
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 `/irix` and each top-level entry is symlinked
|
|
to `/`, so absolute `inst` paths such as `/6.5.30/dist` work;
|
|
- host `/bin`, `/usr`, `/lib`, `/lib64` and `/etc` are bind-mounted read-only;
|
|
- a small wrapper directory provides an IRIX-compatible `dd` that accepts
|
|
`iseek`/`oseek` and refuses writes;
|
|
- `egrep`/`fgrep` wrappers map to GNU `grep -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:
|
|
|
|
```sh
|
|
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](https://github.com/jamesbraid/instigator) — Go server with
|
|
BOOTP/TFTP/rsh and a constrained POSIX interpreter; the best reference for
|
|
the `inst` shell vocabulary.
|
|
- [irixboot](https://github.com/halfmanhalftaco/irixboot) — Vagrant VM using
|
|
isc-dhcp, tftpd-hpa and rsh-server.
|
|
- [Remote IRIX 6.5 install from Linux](http://techpubs.spinlocksolutions.com/irix/remote-irix-6.5-installation-from-linux.html)
|
|
— the `mksh` + `in.rshd` + `bootp` + `tftpd` recipe.
|