Proof of concept mechanical port of ircnet/ircd to Rust as part of a bit about C being insecure for network services
0

Configure Feed

Select the types of activity you want to include in your feed.

Progress log — P4 (Parser & dispatch)#

See PLAN.md for the phase table and migration model.

  • 2026‑06‑02 — P4 (Parser & dispatch) merged. All of common/parse.c ported into ircd-common/src/parse.rs and parse.o dropped outright (added to PORTED, like list.o/match.o) — no parse_link.o, because every symbol parse.c defined is portable now: the msgtab[] table, all 11 find_* wrappers, parse, getfield, the four stub handlers (m_nop/m_nopriv/m_unreg/m_reg), and the three file‑statics (find_sender/cancel_clients/remove_unknown). Spec: docs/superpowers/specs/2026-06-02-p4-parse-dispatch-design.md; plan: docs/superpowers/plans/2026-06-02-p4-parse-dispatch.md.
    • Refines the hazard table (variadic dispatch): the ~14 sendto_* senders parse.c calls stay C, but Rust calls them through bindgen variadic declarations (sendto_one(to, c"…".as_ptr(), …)) — the exact s_numeric.rs pattern. Calling a C variadic is stable Rust; only defining one is not. So no trampoline is needed on the call side; the senders themselves still vanish in P8.
    • msgtab[] as a Rust #[no_mangle] static mut [Message; 66]: built with a row!/m! macro; handler fn‑pointers reference the still‑C m_* (and the four Rust stubs) and coerce in the static initializer; the mutable count/rcount/bytes/rbytes counters mutate in place exactly as C (read by STATS in still‑C s_serv.o). Config‑resolved for this build: TKLINE on (TKLINE+UNTKLINE rows), USE_SERVICES/KLINE/ENABLE_SIDTRACE off (no SERVSET/KLINE/SIDTRACE rows), MOTD_UNREG off (MOTD unreg slot = m_unreg), IDLE_FROM_MSG on (idle guard = fhandler == m_private), DEBUGMODE off (every Debug(()) omitted). The msgtab L1 test compares cmd/min/max/row‑count, not handler pointers (Rust rows point at m_join, the oracle at cref_m_join).
    • Bug caught by L1: IRCDCONF_DELIMITER is '|' (config.h:500), not ':' — the first getfield draft used ':' and the differential failed immediately. (find_mask/find_name L1 also surfaced that the hash tables are null until inithashtables(); the test now inits both sets.)
    • L1 coverage / L2‑L3 deferrals: L1 zero‑diff vs cref_ on the msgtab[] structure, getfield (delimiter/escape/trailing/empty), find_mask/find_name empty‑hash fallbacks, and parse()'s no‑me/no‑hash/no‑sender paths (IsDead early‑out, empty message, unknown‑command‑from‑non‑person, 3‑digit numeric, and an ENCAP→m_nop dispatch — asserting return code + cptr.flags + ircstp counter deltas). Deferred to L3 (parser fuzz) / L2: the full parse() post‑state differential (dispatch into the still‑C m_*, mutated aClient + handler counters) and hash‑populated find_* — both need the populated‑server fixture.
    • Deliverable: the per‑handler‑file static‑symbol cluster map for P5 (docs/superpowers/specs/2026-06-02-p5-handler-cluster-map.md): clusters + entry points + suggested porting order (s_zip/s_debug → s_auth/s_service → s_user → s_misc → channel.c → s_serv.c).
    • Verification: cargo build warning‑free; the Rust‑driven ircd binary links with parse.o dropped (parse/msgtab/find_*/getfield/m_nop resolve to Rust); full cargo test green (all prior *_diff + parse_diff 4/4 + layout); 0 warnings.