Skip to content

Two ways a board with no DNS failed to mention it

A static address came back from every reboot with no resolvers, because the stanza that rebuilds them carried a # the board's ifup read as a comment. And the firmware check said "nothing new" rather than "I could not reach anything", because the updater printed an empty list and exited 0. One reader found both, the day after v2.35.0 shipped, on a board that simply had no DNS. Boards the old stanza was already written to repair themselves.

Firmware v2.36.0, 22 September 2026 — the first image to carry bmcd 2.38.2, BMC-UI 3.35.0. Every item below is the repository's own changelog entry, taken apart; the whole entry is a click away under each one.

New

The demo can be used, not only read, on the one card whose subject is

time passing BMC-UI 3.35.0

Every write in the demo is refused -- a captured board cannot be changed -- and for the address card that made the feature unshowable: apply, a window running, a confirmation that must arrive over the new address, and the old address coming back by itself are a sequence, and a fixture can only hold one frozen frame of it.

The whole entry

The demo now answers validate, PUT, confirm and revert from a state machine it keeps in memory (src/demo/address.ts), so a reader can apply an address, watch the countdown, keep it -- or say nothing and watch the board put the old one back.

The card is unchanged. The interface still keeps no copy of the daemon's rules: the new file is the demo's stand-in for the board, the thing on the other side of the wire, and it exists only under VITE_DEMO=1. Its refusals and warnings are address_document.rs's own words, so what the demo says is what a board would say. Nothing persists; a reload starts again from the captured fixture.

Changed

  • BMC-UI 3.35.0 changes nothing on a board. It teaches the site's demo to run the address flow — apply, the window, confirm, revert — so a reader can try it. Pinned because a release ships the latest of every component, the rule this image has kept since v2.26.0.

Fixed

  • A static address came back from every reboot with no resolvers. The stanza the address card writes carried a # — the tag the DHCP client puts on its own resolv.conf lines, kept so a later lease can replace them — and the board's ifup reads # anywhere on a line as a comment.

    The whole entry

    The hook that rebuilds /etc/resolv.conf (a link into memory on this image, empty at every boot) was cut off, the shell refused it, and ifup br0 failed at every boot after the address was already on the bridge. The board came up reachable, with a clock that could not find its server. The hook now spells the character so it survives; a board the old stanza was already written to is repaired the first time this daemon starts, without waiting for the address to be changed again.

  • A firmware source it could not reach said "nothing new". tpi-selfupdate --list calls die when curl cannot reach the source, and die exits — but on the left of a pipe it exits only its own subshell.

    The whole entry

    The JSON array had already been opened, the loop then read nothing, and the script closed the array and exited 0: a well-formed "releases":[] with the real reason on stderr, which nobody was reading. bmcd took that as "this source offers nothing" and the firmware page said there was no update, on a board that simply had no DNS. Reported alongside the clock, from the same board; reproduced on board B with an empty resolv.conf — four sources, no candidates, no errors.

    Both listing branches now collect into a variable first, where a non-zero exit is visible, and print nothing on stdout unless they succeeded. tests/listing.sh stubs curl and covers it in dash, busybox ash and sh; run against the original script it reports five failures, which is how it was checked. bmcd 2.38.2 is the other half: it reads the exit status before the output, so the next script that fails cheerfully cannot put the page back to lying.

  • A firmware source that could not be reached reported nothing rather than a failure. list_remote read the updater's stdout and ignored how the process ended. bmcd 2.38.2

    The whole entry

    tpi-selfupdate --list printed {"releases":[]} and exited 0 when it could not reach the source, putting the real reason on stderr where nothing read it -- so on a board with no resolver every remote source came back with no candidates and no error, and the firmware page rendered that as "nothing new". Reported from a 2.4 board on 2026-09-22 as "checking github for updated firmware also fails silently", and reproduced on board B: with an empty /etc/resolv.conf, four sources, zero candidates, zero errors, and curl: (6) Could not resolve host on the updater's stderr.

    The exit status is now read before the output. The updater is fixed in firmware v2.36.0 to exit non-zero and print nothing; this is the other half, so the next script that fails cheerfully cannot put the page back to lying. A failure with nothing on stderr now names the exit code instead of saying "no output", which was the only sentence the page had to show.

  • A static address lost its resolvers at every reboot, and ifup br0 failed at every boot. The up hook 2.38.0 wrote into /etc/network/interfaces carried a literal # -- the # br0 tag udhcpc uses on resolv.conf lines -- and ifupdown-ng reads # anywhere on a line as the start of a comment. bmcd 2.38.1

    The whole entry

    The hook was cut off mid-string, /bin/sh refused the unterminated quote, and ifup exited 1 for br0. The address was already on the bridge by then, so the board came up reachable, with an empty /etc/resolv.conf (a symlink into tmpfs, fresh every boot) and a clock that could not resolve its server. Reported from a 2.4 board on 2026-09-22 by the reader whose report shaped 2.38.0; he had found the workaround of writing a regular resolv.conf into the overlay by hand.

    The hook now spells the hash as \043, which busybox printf turns back into #; the file it writes is byte-for-byte what it was meant to be, and udhcpc's filter still recognises the lines as its own. Measured on board B: the old hook fails with "unterminated quoted string", the new one writes the file and ifup exits 0.

    Boards that 2.38.0 already wrote are repaired at the first start of this daemon: a file this daemon wrote that is not what this version renders is rewritten (same document, corrected hook), and a static address whose resolvers are missing from /etc/resolv.conf gets them written then -- bmcd starts after the network does, so this is exactly the moment the failed hook left empty. A file written by hand is never touched.


Every release of the firmware · the roadmap · follow by feed