diary at Telent Netowrks

With a brand new adventure#

Fri, 25 May 2018 13:13:29 +0000

There has been no nixwrt update this week because no nixwrt changes this week. I've done a little bit of refactoring though nothing really worth writing about - mostly I've been treating the last week or two as a nixbreak.

Instead I've been learning some cryptography and some Haskell, by means of trying to write programs that do one, using the other. Specifically, the Cryptopals challenges . Lessons:

Give me docs or give me death, I am undecided which

I have not yet reached the point of "I have type signatures, why do I need docs?". I need docs, preferably with examples. Crypto libraries, I am looking at you specifically here.

In the interests of being vaguely constructive in this criticism, here is what you do to get AES128-ECB decryption with whatever the default crypto that ships with GHC 8.2.2 is.

(Note that, as far as I understand it, there is no reason ever to use ECB mode except in educational examples which will demonstrate to you just how awful a choice it is)

import qualified Crypto.Cipher.AES as AES

decode' keytext payload = let key = AES.initAES keytext in AES.decryptECB key payload

It accepts ByteString arguments. There are probably good ways to get ByteStrings that I haven't found yet, but if you start with an ordinary string you could try

toByteString text = BS.pack (map (\c -> fromIntegral (ord c)) text)

"Yippee, strings!" said Teal

See above. There seem to be an awful lot of incompatible ways to represent "sequences of small integers that map onto ASCII characters" in Haskell. At the moment I'm using arrays of Word8 as my "primary" represnetation and converting to and from other formats when I need to do so to call library functions and stuff.

"Stop, collaborate and listen"

They're not messing about when they say "an appreciation for early-90's MTV hip-hop can't hurt either". A lot of the examples are a bit ... Vanilla?

I have implemented a plausible AES-CBC mode (using ECB as a building block), currently working on challenge 11.

Back to Nix next week

Back up to the start#

Sat, 12 May 2018 23:12:04 +0000

My backup server runs! Since last week I plugged in my actual USB external drive and added a DHCP client, USB support, ext[234]fs and a few more useful busybox apps - cp, chmod, chown, that kind of thing. Now it's running and my home desktop is backing up to it four times a day.

Because the Nix store is world-readable, I didn't want to put passwords in it - so instead I chuck them in files elsewhere and read them at script exection time. To get duplicity running in NixOS I added this stuff to my configuration.nix

 services.cron.systemCronJobs = let script = pkgs.writeScript "run-duplicity" ''
    #!${pkgs.bash}/bin/bash
    export PASSPHRASE=$(cat /var/lib/backupwrt/duplicity) 
    export RSYNC_PASSWORD=$(cat /var/lib/backupwrt/rsync) 
    ${pkgs.duplicity}/bin/duplicity / --include /home --include /etc --include /srv --exclude '**' rsync://backup@snapshto::srv/snapshots/loaclhost
''; in [
      "18 */4 * * * root ${script}"
    ];

This blog entry is super-short because after writing a much longer one I extracted all the interesting bits and turned them into an FAQ document in the Git repo. So go and read that now.

Wrt up#

Tue, 08 May 2018 21:02:54 +0000

Since "last week": I have

What's left for Milestone 0? Nothing really, apart from cleanup. There is a shockingly large amount of "arbitrary" involved in deciding what goes in which nix file, and there really ought to be some kind of principled separation of what/where/how (what the app does, the specifics of the hardware where it runs, and the implementation details), and there are other cleanups to do too. Also need to do something like overlays so that the packages defined in nixwrt override the ones in nixpkgs. Also also need to update it to work with nixpkgs master - or at least with 18.03 without my random patches. Also also also add e2fsutils so we don't have to plug the USB disk in somewhere else just to fsck it.

In other news, if you can read this then you are looking at my new shell host and the DNS for ww.telent.net has updated. Still haven't moved everything off the old one, but this is just one more step (and a large one) along the way.

Let's switch again#

Sun, 29 Apr 2018 13:47:07 +0000

Achieving anything new this week has been rather hampered by (1) my decision to try out XMonad, and then (2) the kids all picked up some kind of vomiting bug. I do not intend you to infer any connection.

(XMonad: dunno yet, haven't really tried using it for long enough. The mouse pointer is impossibly small and I'm going to have to fix that sooner or later, but I only need it for gui apps and all I've really tried using thus far is emacs and rxvt)

But let's see if I can explain why I've been hung up on switches lately. If you've ever wanted to know why your OpenWRT router has network interfaces with names like eth0.1 (no, it's not a misguided decision to do semantic versioning on them) maybe this is for you.

First, you need to know about VLANs. A VLAN is a "virtual LAN": a way to multiplex traffic for multiple independent LANs onto the same cable. In the picture on your right, VLAN 5 connects ports 1 and 3 on switch A with ports 2 and 4 on switch B, and VLAN 6 connects port 2 on A with 3 on B.

The switches do this by "tagging" the packets (frames) according to per-port rules. If alice sends to fred, her frames will be tagged with VLAN ID 5 when they enter switch A, sent (with the tag intact) to switch B, and then untagged again as they are sent out of port 3 to fred. Long story short -

This is super useful, I have no doubt, if you're running an enterprise network and need to keep devices separated without having to run multiple sets of cables to every desk. But how is it relevant to *WRT? Because the hardware you're running it on, despite any impressions you might have had from its inclusion of two or five or eight RJ45 sockets, quite likely only has one ethernet device that Linux can see. This device is connected (internally, inside the SoC) to a builtin switch, which is also connected to all the sockets you can see. So if you want to address them separately - for example, you want to connect your upstream connection to one of them without giving it full access to your LAN and vice versa - you do it with VLAN configuration.

Make the switch

Set the upstream port to tag VLAN 1 and the LAN ports to tag VLAN 2, and the "CPU port" (the one connected to the eth0 device that Linux sees) to allow VLANs 1 and 2 but not to tag/untag either - i.e. it receives tagged packets and particapates in the VLAN as if it were another switch.

We would do this with swconfig but we haven't yet because this turns out to be the default configuration anyway, at least on the MT300A. (I have no idea whether it's hardware or u-boot or the devicetree config that makes it be this way - at some point I dare say I will find out though)

Configure Linux

So we have a switch on the SoC which is sending VLAN tagged frames to the ethernet interface - we need to tell Linux to expect them. (You might say it needs configuring to serve VLAN).

You do this with the ip command found in iproute2

ip link add link eth0 name eth0.1 type vlan id 1 
ip link add link eth0 name eth0.2 type vlan id 2 
ip addr add 192.168.0.251/24 dev eth0.2 
ip link set dev eth0 up

and now for most purposes you can treat eth0.1 and eth0.2 as though you have two network interfaces.

I'd like to close by saying "Simples!" but when I googled that term I learned of the existence of contemporary mereology as a field of philosophical study, and I am not sure anything can ever be simple again.

Null hypothesis#

Tue, 24 Apr 2018 22:39:25 +0000

When I blogged last week I left off at the point that syslogd and ntpd were not writing their pid files into /run.

Having basically no hypothesis[*] as to why this might be, I looked into building gdbserver and I looked into building strace and then I decided to try good old printf debugging first. To do this I wanted a slightly faster development cycle than having to build and tftp an entire image for each change.

Shared folders

It is probably fair to say I had never heard of the Plan 9 Filesystem Protocol (9P for short) before I started messing around wth Nix, but it turns out not only is it a Thing That Replaces NFS, but that it is a Thing which has client support in the Linux kernel and server support in qemu. So now I start qemu with some command rather like

qemu-system-mips  -M malta -m 128 -nographic -kernel malta/kernel.image \
 -virtfs local,path=`pwd`,mount_tag=host0,security_model=passthrough,id=host0 \
 -append 'root=/dev/sr0 console=ttyS0 init=/bin/init' \
 -blockdev driver=file,node-name=squashed,read-only=on,filename=malta/rootfs.image \
 -blockdev driver=raw,node-name=rootfs,file=squashed,read-only=on \
 -device ide-cd,drive=rootfs -nographic

where for the purpose of this blog post the interesting bit is the line starting with virtfs. This exports the current working directory such that inside the qemu VM I can mount it with

mount -t 9p -o trans=virtio,version=9p2000.L host0 /run/mnt

There is one weirdness that I've found, which is that trying to run a binary from from inside /run/mnt fails with Not a socket errors. I don't know why, but if I copy the same binary into /tmp it works fine. Don't ask me, because I don't know.

Anyway, this is all rather lovely because now I can build binaries - such as, for completely random example, a busybox executable with calls to fprintf(stderr, "here %s:%d\n", __FILE__, __LINE__) every four lines - and try them instantly in a running emulator wthout restarting anything. Doing this led me to the discovery that it's trying to open /dev/null as part of daemonising itself, and that that file is somehow mode 0660 instead of 0666. I took a guess (yes, ladies and gentlemen, the "null hypothesis" [*]) that this might make a difference, and turns out I was right. So, fix is to add an mdev.conf entry . It would be interesting to know why it makes a difference, considering that both of the daemons involved run as root, but I haven't really dug into it.

Change my switch up

In other news, after some experimentation with iproute2 and some more reconfiguring the kernel, I believe I might just understand how the builtin switch works and can do networking the Right Way (i.e. treat the WAN and LAN ports separately). But more about that in another thrilling installment.

[*] if you're reading this footnote for the first time, it's not just a lame joke it's foreshadowing an even worse one. See you again in about five paragraphs.