Proof of concept mechanical port of ircnet/ircd to Rust as part of a bit about C being insecure for network services
4.0 kB
11 lines
1# Progress log — P0 (Scaffold + baseline + harness)
2
3See [PLAN.md](../../PLAN.md) for the phase table and migration model.
4
5- **2026‑06‑02 — P0a/P0b/P0c merged** (scaffold + Rust‑driven baseline; bindgen full ABI + layout drift‑net; L1 differential harness `ircd-testkit` with the `cref_*` symbol‑renamed oracle archive). See `docs/superpowers/plans/2026-06-01-p0{a,b,c}-*.md`.
6- **2026‑06‑02 — P0‑L2 (golden harness) built.** New workspace crate **`ircd-golden`** boots a pristine **reference‑C `ircd`** and the in‑progress **Rust‑driven `ircd`** side‑by‑side, drives a scripted TCP client one action at a time, canonicalizes, and asserts byte‑identical wire output. First scenario — client registration (NICK/USER → welcome banner) — is **byte‑identical** between the two builds (`alice!~alice@127.0.0.1`, 16 lines through `422 MOTD File is missing`). This is the real **P5** gate (command handlers can't be L1‑tested). Spec/plan: `docs/superpowers/plans/2026-06-02-p0-l2-golden-harness.md`.
7 - **Reference‑C runnable binary (new):** the L1 oracle only ever produced *renamed objects*, never a runnable C ircd. `ircd-golden/build.rs` now builds one: recompile **only `ircd.c`** with a native `main` (`cbuild/ircd.o` carries `‑Dmain=c_ircd_main`, so it has none) into `ircd_ref.o` via `make ‑‑eval` (so the per‑object path defines `$(IRCDCONF_PATH)`/… expand identically), then link it with the **pristine base objects** (the plain `.o`, not the `_link.o` partial‑port variants) + `version.o` + `‑lz ‑lm ‑lcrypt`. Built into `OUT_DIR`; path exported via `cargo:rustc‑env`.
8 - **DNS disabled project‑wide (`NO_DNS_LOOKUP`):** `s_bsd.c add_connection`'s async reverse‑PTR lookup (`gethost_byaddr`→`SetDNS`) both embedded a nondeterministic resolved hostname in the banner **and** held registration across event‑loop iterations. Now `‑DNO_DNS_LOOKUP` (added to `EXTRA_CFLAGS` in `ircd‑sys/build.rs`, so cref oracle + link set + Rust binary all share it) makes the lookup a no‑op: `hostp` stays NULL without `SetDNS`, clients register immediately with their **numeric** host (the same end‑state a no‑PTR lookup reaches; handled at the existing `!cptr->hostp` paths). The `USE_IAUTH` cache‑hit block that derefs `hostp->h_aliases` is compiled out under the same flag. Per the user: resolver behaviour is intentionally **not** maintained.
9 - **Keystone finding — DO NOT pin the clock to a constant.** The PLAN's "LD_PRELOAD shim overriding `time()`/`gettimeofday()` to a fixed value" **breaks the server**: a frozen `time()` freezes the global `timeofday` (set every loop at `ircd.c:1250`), so the io_loop's scheduling never advances and the **listen socket is never serviced** — clients are never accepted (confirmed via `strace`: `poll()` only ever watched the resolver fd). The harness uses the **real clock** and relies on the **canonicalizer** to mask the few time‑bearing tokens (`242` uptime, `317` idle/signon, `391` time; `003`/`004` are compile‑time‑stable across both builds). The registration banner embeds no runtime timestamps, so it needs none. (A future advancing‑from‑fixed‑epoch shim could tighten WHOIS‑idle/STATS scenarios.)
10 - **Config path redirect (no root):** `CMDLINE_CONFIG` is `#undef` → `‑f` is dead; both binaries `open("/usr/local/etc/ircd.conf")` (`s_conf.c:1395`). A committed LD_PRELOAD shim (`ircd-golden/csrc/l2shim.c`) intercepts `open`/`open64` and rewrites that one path to `$IRCD_TEST_CONFIG`. Boot flags: `‑t` (foreground) `‑s` (`BOOT_NOIAUTH`). Both bind the same fixture port (16667), so the test runs them **sequentially**, never concurrently.
11 - **Verification:** `cargo test ‑p ircd‑golden` → `registration_banner_matches_reference` PASS; full `cargo test` green (golden + all 12 `*_diff` L1 suites + layout 4/4); `s_bsd.c` is not L1‑tested so the DNS edit breaks no differential; 0 warnings.