Client for LaCie U-Boot NetConsole
A feature of Seagate Personal Cloud NAS (and other U-Boot devices) is
you can connect to a network console, which is activated on power-up
by a magic packet. The tool to do this is clunc
, available from
lacie-nas.org.
My recent attempts to use this failed, so it was time to search the
Internet and read the source. Investigation determined the problem was
an incompatibility with the default version of netcat
on Debian buster.
In the short term, I solved the problem by checking out tag 1.1
, and
using update-alternatives
to set nc
to be nc.traditional
.
My Itch
The existing implementation uses a shell script for orchestration,
a C executable to trigger the netconsole, and invokes netcat
for the
communication.
I wondered if I could -implement it as a Python script, removing the need
for compilation and dependency on the details of the way netcat
works.
The aim was to produce a drop-in compatible script, without the need for additional libraries.
How Does it Work?
A side effect of re-implementing clunc
is I had to understand how
it works.
It first checks to see if the device netconsole is already active,
by sending ^C
to the netconsole UDP port 6666. If it is active,
then the response <INTERRUPT>
is received, and the script switches to
bi-directional communication.
To activate the netconsole, every ½ second the script sends out a LUMP packet (UDP broadcast to port 4446). The packet contains the IP address for the device to use (pick a suitable one for your network).
As the device starts up, the receipt of the LUMP packet causes the normal boot to stop, and connect the netconsole with the sending IP address.
The script will receive a response on UDP port 6666, which is the start of bi-directional communication with the device.
I found out that the reason I was seeing my command repeated back to me was the input was being echoed locally, and also by the device. Disabling local echo, and not buffering the input means the echoed key-presses are from the device.
I also found that sending input too rapidly, or while the device was busy sending responses would result in dropped input. This was especially true when reading from a file.
To combat this, the input is line buffered when reading from a file. Before the next line is sent, there has to be no output for the inactivity timeout (the 1 second default works well).
LUMP Packet
The building block of the packet format is a tag and value:
- Tag (null padded ascii) - 4 bytes
- Length N (network order) - 4 bytes
- Value - N bytes
A field value inside the packet is the combination of a type tag, and a value. There are two types used:
- “IP@” - IPv4 address represented as 4 byte integer
- “MAC@” - 6 byte ethernet address (padded to 8 bytes with leading nulls)
A field in the packet has the field tag, and the field value as described above. The fields used in the packet are:
- “IPS” - The IP address for the device to use
- “MACD” - The destination MAC address (or 00:00:00:00:00:00 if not specified)
- “MACS” - The source MAC address? Always 00:00:00:00:00:00
The entire packet has the tag “LUMP” and the value is the concatenation of the 3 fields.
New Implementation
I am pleased with the result, and feel I’ve successfully scratched my own itch.
In addition to being used interactively, I found reading commands from files works well. I am able to run the entire script to launch the Debian installer without error.
My implementation is available from the “py-clunc” repository, with direct download link from the releases page.