Proof of concept mechanical port of ircnet/ircd to Rust as part of a bit about C being insecure for network services
21 kB
Memory Index#
- leveva caller-id (+g/ACCEPT) — slice 216 charybdis caller-id; CallerId store lives in Registry; +g is local-only (not in SEND_UMODES); two deferred follow-ons (remote-sender S2S gating, +G soft caller-id)
- Blog series — docs/blog/ numbered Xe-voice posts about the port; use the xe-writing-style skill, match existing format, which topics are taken
- Rust migration plan — this ircd C codebase is being strangler-fig ported to Rust; locked decisions + phase order + plan-file path
- leveva prod ShadowNET per-server probe — reach one prod server directly via
<servername>.alrest.xeserv.us:6667(irc.xeserv.us load-balances); how to diagnose cross-server desyncs (LINKS/LUSERS/NAMES, bare-UID = slice-162 identity bug) - Project name: leveva (P10) — the idiomatic-Rust end state ships as "leveva"; rename happens at Phase 10
- ircd migration hazards — verified C-side gotchas (variadics, self-pointers, layout gating, mutable msgtab) that constrain the port
- P0b bindgen constraints — bindgen MUST use -x c + v0.72 or ircd structs go opaque; layout drift-net design (P0b merged)
- P0c L1 harness constraints — ircd-testkit cref* differential harness; link-anchor for integration tests + the cref*-oracle-vs-OBJS split phase 1 must wire (P0c merged)
- P1 leaf-utils port — match.c/dbuf.c/support.c-subset ported to the new ircd-common crate; the CREF/link/support_link.o split mechanism + faithfulness gotchas (P1 merged)
- P2 data-lookup port — patricia/class/whowas/hash/list ported; the m_*-handler partial-port mechanism (whowas_link.o/hash_link.o); verified ENABLE_CIDR_LIMITS-on + MyFree-is-a-macro findings (P2 merged)
- P3 transport-format port — serr replies[]/s_id/s_numeric/send delivery-core ported; sendto* family is irreducibly C trampolines (the keystone variadic finding); send_link.o + replies[]-dumped-from-oracle gotchas (P3 merged)
- P0-L2 golden harness — ircd-golden boots ref-C + Rust ircds, diffs scripted wire output (the P5 gate); clock-pin-to-constant breaks the event loop (use real clock); DNS disabled project-wide via NO_DNS_LOOKUP
- Work on master directly — commit straight to master in this repo; never propose branches/worktrees or ask about branch strategy
- P5 S2S golden harness — ircd-golden Peer/boot_s2s for testing server-reachable handler paths + the determinism findings (sequential UIDs, SID format, standalone-refuses-links)
- Commit one test per commit — each test change gets its own commit explaining why; infra/port fixes committed separately first
- Test fake-lag disabled — golden/L2 tests disable ircd fake-lag via IRCD_TEST_CONFIG (ircd_no_fakelag in s_bsd.c); why scripted multi-command tests need it
- Run only edited tests — don't run the full cargo test suite; run only the test binaries you touched (full suite is slow)
- P5 s2s stats flake — TWO STATS golden tests (golden_s2s_s_serv_stats + golden_s_misc stats_t) fail on clean HEAD via reference-C garbage; not regressions
- s_user_umode_diff broken — FIXED 2026-06-04 (c_char-rot buffers → [0 as c_char; 64]); back in the P5 gate
- support irc_memcmp host-gated — FIXED 2026-06-04: support_diff link-failed (cref_irc_memcmp) because irc_memcmp is gated behind MEMCMP_BROKEN (off on aarch64); gated the L1 case on a have_cref_irc_memcmp cfg
- PLAN.md rows stay thin — never accumulate per-sub-phase detail in PLAN.md table rows; put it in PLAN-P-progress.md + docs/progress-log/
- L1 cref static-symbol limit — static C fns have no cref_ oracle symbol → can't be L1-diffed; also every L1 test needs link_reference_archives()
- P-IAUTH state — P5+P6 done; iauth-rs all 5 modules + handshake differential done; what's left; the relink/fd-0-socketpair differential-gate mechanism + C iauth.conf gotchas
- P7 complete — P7 (I/O core + event loop + glue) DONE 2026-06-07 (P7oo ported c_ircd_main, the last C logic); all C logic now Rust, only data globals + ~25 variadic trampolines remain; next = P8 (delete C + retire oracle)
- P8 COMPLETE — P8 DONE 2026-06-08 (P8u final): workspace is 100% Rust, zero C TUs compiled. Deleted the last C (variadic trampolines P8a–P8m; data globals P8n–P8r; version.c P8t), migrated all 115 L1 diffs to ircd-common insta snapshots (P8s), then P8u dropped ALL C compilation from ircd-sys/build.rs (make/cref_/ctruth.o/libircd_c.a/whole-archive + -lz -lm -lcrypt — none needed) keeping only configure+bindgen-over-headers+install-path-vars, and mothballed the oracle (ircd-testkit/ircd-golden excluded from workspace; ctruth.c/layout.rs deleted). Final differential run green. Gate: cargo test --workspace 698 pass/0 fail/125 binaries, 0 warnings. Next = leveva (P9 RETIRED — see leveva-pivot-p9-retired).
- Roadmap pivot: P9 retired, leveva is the destination — 2026-06-08 in-place cleanup dropped; ircd-common = oracle for greenfield leveva, deleted at parity; reframed P9–P12; next = leveva connection/registration state machine
- P12 COMPLETE — strangler finished — P12 DONE 2026-06-13: mechanical port + oracle + deployment rigging deleted; workspace is now
leveva+leveva-iauthONLY; the migration is finished. No more differential testing — future leveva work is standalone feature work, not migration slices. - ircd-common snapshot tests — the L1 tests are now insta snapshot characterization tests in ircd-common/tests/*_snap.rs (no cref oracle); link_anchor + determinism rules for adding/editing them
- P7 L1 shared-global race — P7 L1 tests touching me/cref_me/local[]/highest_fd must serialize on a mutex (cargo runs #[test]s in parallel)
- SUMMON/utmp not required — summon + utmp_open/read/close in s_bsd.c are config-gated off (ENABLE_SUMMON/USERS_SHOWS_UTMP undef) → not compiled, nothing to port
- Boot-level golden harness — self-contained end-to-end net in ircd-rs/tests/ (boots real ircd, insta-snapshots wire output); the IRCD_TEST_CONFIG seam; replaces the deleted C-oracle ircd-golden
- leveva command/ folder — leveva post-registration handlers are one-per-file in leveva/src/command/; how to add a new client handler slice; S2S handlers get their own modtree (deferred)
- s_conf oline snap flake — ircd-common oline snapshots race under parallel --workspace load; re-run the binary alone, not a regression
- Help files per command — leveva HELP serves embedded leveva/help/.md pages (rust-embed); adding a command requires adding its help page (test-enforced both directions)
- CLOSE not required (leveva) — user ruled CLOSE out of scope for leveva (P11); OperPrivilege::Close stays dormant, don't build it
- leveva S2S port-based routing — leveva routes client/server by the listener's server-only flag, not the handshake; a server must link on a server-only port (deliberate, don't change)
- SERVICE NEVER implemented (leveva) — HARD RULE: never plan/scope/build SERVICE/SQUERY/SERVLIST in leveva; let them fall through to 421; like CLOSE, permanently out of scope
- SET not required (leveva) — user ruled SET (m_set runtime tunables) out of scope for leveva (P11); OperPrivilege::Set stays dormant, don't build it
- leveva S2S + auth complete; parity matrix started — S2S + auth + full client surface done; parity matrix toward P12 UNDERWAY: slice 45 (channel-lifecycle inverses) DONE; next matrix area = ask user (registration / WHO-WHOIS / STATS-completion / burst-netsplit)
- iauth subsumed into leveva — P11 slice 39+: iauth becomes a native async leveva-iauth subcrate (no child process/pipe); hickory-dns for DNS; the sync-feed/async-ident registration seam + username
~rule - leveva prometheus metrics — P11 slice 42: server counters are a prometheus Registry in leveva/src/metrics.rs, per-ServerContext NOT the global default (test isolation, deliberate); STATS m/z read it
- leveva IRCv3 track — P11 slice 48 opened an IRCv3 track: CAP negotiation framework in cap.rs; the framework-vs-behavior scope rule (each behavior cap is its own later slice, added to SUPPORTED); leveva-native = no differential
- leveva message-tags seams — the code map for the message-tags delivery plane (TAGMSG/client-only tag relay/417, slice 58 done); the ClientRecord.caps gate + the thin-follow-on attach pattern
- leveva slice recording + TDD discipline — how to record a P11 slice (plan file + p11.md heredoc append + PLAN.md row bump); write failing test FIRST + always test inverse invariants
- ircd-common native boot + testing plan — ircd-common/src/boot.rs: clap entrypoint (run()) + embedded in-process boot() (Server handle, stop flag) so the oracle daemon links into a test binary natively; c_ircd_main left untouched; the standing leveva testing plan + P11 verdict location
- leveva channel-mode rework (slice 77) — ripped out channel +a/+r, kept +R/auto-reop, repurposed +O from uniqop to oper-only-join (520); don't re-add the dead modes or confuse +O with the NJOIN @@ uniqop decode
- leveva S2S introduce fix + leak audit (slice 86) — post-link UNICK introduction was missing (burst-only) → raw-UID JOIN/PRIVMSG + dropped-from-NAMES; the relay burst-vs-live asymmetry rule; real-RSS leak audit method + finding (no unbounded leak; half-open reap is 180s at default ping-freq)
- leveva native oracle harness (slices 92–102) — in-process ircd-common oracle in leveva-integration for live command-skeleton differentials; the oracle_lock/read_until rules; slices 96–99 closed JOIN 0 / WHOIS 317 / MODE +l / 253; 100–101 lookup+server-info; 102 = S2S burst+netsplit verb-skeleton diff (2nd link-accepting Prot::Off oracle + leveva subprocess + verb_skeleton extractor); THE STANDING RULE: oracle-supports-but-leveva-doesn't = bug, close don't document
- hunt_server proptest hazard — VERSION/TIME/ADMIN/INFO/USERS/MOTD/STATS/LINKS/TRACE 402 on an unknown hunt ; proptests feeding arbitrary args to them must model matches(target,SERVER)→local-else-402 or they fail stochastically (slice 113 fixed five stale ones)
- leveva UTF-8-only parse boundary — UTF-8-only enforced at Message::parse_bytes (the single byte→Message gate), not the framing layer; never add a lossy client byte path (P11 slice 120)
- leveva LINELEN=2048 graphemes — non-tag lines up to 2048 graphemes (not 512 bytes); cap lives in to_wire, framer ceiling = tags+LINELEN*64, chunkers/S2S stay byte-conservative (P11 slice 121)
- leveva S2S notify propagation — the P11 area closing IRCv3 "single-server-local" divergences; AWAY (122)+INVITE (123)+MONITOR-live (124)+REDACT (125)+capability-foundation (126)+REDACT→ENCAP (127)+msgid (130)+server-time (134)+bot/oper (135)+account (156) done; 128/129 went elsewhere; area COMPLETE + late addenda: 177 = METADATA SET/CLEAR propagation (
ENCAP * METADATA, modelled on SU; new s2s/metadata.rs); 178-180 WALLOPS/KILL/metrics; 182 SANICK + 183 SAJOIN/SAPART S2S (SA* oper-override family now S2S-complete —ENCAP * SA*to the home server, its local force machinery's relay propagates) - leveva outgoing auto-connect — P11 slice 128: the try_connections counterpart; pure autoconnect::AutoConnect::due (master + autoconnect + connect-freq cooldown ladder) + main.rs ticker reusing the CONNECT outbound-link plane
- leveva S2S peer caps — S2S capability negotiation (slice 126): the CAPAB-via-ENCAP burst verb + egress tag-filter; how to gate any IRCv3 tag per-peer; bare-unknown-verb-SQUITs-the-oracle lesson (extension verbs MUST ride ENCAP)
- leveva live-join NJOIN — P11 slice 129: live joins propagate as
:<sid> NJOIN(op in member token), NOT:<uid> JOIN(the oracle drops bare server JOIN); inbound handle_njoin is burst-vs-live aware; fixed UIDs-not-nicks + chanop-not-synced interop bug; msgid follow-on now slice 130 - leveva msgid S2S propagation — P11 slice 130: the message-ids
@msgidserver tag is network-stable (introducing server mints, relay carries it through + never re-mints), gated on slice-126 CAPAB egress; see the s2s-notify-propagation memory - leveva netburst joins broadcast to clients — FIX 2026-06-13: handle_njoin now fans JOIN+MODE to local members during the BURST too (newly-added only), not just live — a healed split shows the netjoin flood instead of silent merge
- leveva channel-merge works — split-then-merge of two independent same-name channels preserves both members + op on HEAD; couldn't repro "remote member missing" post-129; two-node port-lock is process-local (use unique ports per test binary)
- leveva LINK_VERSION 021- staleness — recurring pre-existing red: PASS-greeting tests/snapshots go stale vs server::LINK_VERSION (021- prefix); fix as a separate prep commit, git-stash to confirm pre-existing
- leveva S2S handshake diagnostics — read_link_handshake now surfaces a peer's ERROR refusal + EOF/port hints + a 30s idle timeout (was a blind "did not complete"); a connect{} to a client port like 6667 is the classic cause
- leveva TS + link fixes (slices 131-133) — connect-dedup (LinkingSet, no re-dial mid-handshake glare) + server-intro broadcast (announce_linked_peer to siblings); channel-ts/user-ts CAPAB tokens carry timestamps as ENCAP-wrapped unix-NANOSECONDS, oldest wins (deop younger chanops / evict younger nick to its UID); the USERTS-before-UNICK buffering + the cross-task Envelope::ForceNick primitive
- leveva elemental channel modes (slice 158) — leveva-native owner/admin/halfop
~&@%+/qaohv; the rank hierarchy (threshold/min-rank/protection) + MemberStatus-is-a-bitmask shape; creator stays op (no ChanServ) - leveva extbans (slice 164) — charybdis-style
$a/$o/$z/$r/$x/$s/$c/$j/$mextbans in leveva/src/extban/; the framework seam, JOIN + speech-plane enforcement (slice 214 added the PRIVMSG ban mute via CanSend::Banned), LiveChannels ChannelView, add-time validity (172); no+qquiet list (q=owner) - leveva OJOIN official-join — P11 slice 165: InspIRCd-style
+Ymembership mode (sigil!, rank 128); OJOIN grants+Yo, absolute kick-immunity, self-removal-only; extends [[leveva-elemental-channel-modes]] - TS6 reop MUST wipe — HARD RULE: on a CHANTS merge loss the loser's +R reop list is wiped with +b/+e/+I; never defer/exclude reop lists (overrules slice-171's union divergence); fire reop at EOB after winner's +R adopted
- leveva REHASH matrix — what hot-reloads on REHASH (opers/classes/allows/MOTD/admin/connect/listeners/default-user+channel-modes/flood-kill-ahead/auto-connect/connection-accept+split-min/max-penalty/knock-delay+knock-delay-channel); the live-or-ctx ConfStore idiom + how to add a new reloadable block; as of slice 210 NO throttle threshold or options field remains boot-immutable
- leveva S2S TLS links — S2S links run over TLS both directions (inbound server-only TLS listener + outbound
connect{} tlsflag →tls::connect_outbound); accept-any cert, auth by PASS not PKI; theboot_two_configsruntime-config test seam (P11 slice 176) - leveva SASL chunking proptest flake — RESOLVED (slice 181): the bare-
+data chunk colliding with the IRCv3 empty-payload sentinel; unrepresentable by design (don't try to "fix" the chunker) — closed via contract docs + base64-domain fuzz + a precise-boundary proptest - leveva slices 178-180 (WALLOPS/KILL/metrics S2S) — 2026-06-15 ultracode workflow closed three more single-server-local gaps: WALLOPS + KILL S2S propagation (first-class verbs, away.rs model) + S2S server-link traffic metrics; recorded in the s2s-notify-propagation memory's "Slices 178-180" section
- leveva server notices (+s) — slice 184: re-introduced the
+s(FLAGS_SERVNOTICE) umode +snotice::server_noticefan (oper-gated, local-only/excluded-from-SEND_UMODES); wired KILL+REHASH; the inbound-S2S-KILL + SA* notices are documented follow-ons - leveva config ban (K-line) enforcement — slice 191:
config.banswas parsed-but-silently-dead; now enforced at registration viakline::config_ban_match(host + optional gecos/realname), gated bykline_exempt, hot-reloaded by REHASH; why no-resolve/xline-exempt stay deferred by design (leveva is IP-only; gecos'd ban subsumes X-lines) - leveva +r restricted enforcement — slices 193–196: the
+r(IRCnetFLAGS_RESTRICT) connection is enforced (was set-but-cosmetic) — a restricted user can become neither IRC operator (OPER→484) nor channel operator (no creator-op; 194: no third-partyMODE +o, halfop+, voice OK; 195: never auto-reopped by ANY trigger via theenforce_reopchokepoint) and cannot change nick (196: NICK→484, RFC 2812 §3.1.7, family complete);mode::is_restrictedseam - leveva KNOCK (slices 198–200, 209) — leveva-native charybdis-style KNOCK to a +i/+k/+l channel (710/711); shares the JOIN check_join gate; S2S propagation done (199,
ENCAP * KNOCK); per-channel 712 flood throttle done (200,knock_throttle::KnockThrottle, local-path only); per-user throttle done (209,knock_delay300s, secondknock_user_throttlekeyed by UID,cooling/armpeek-then-arm split); family complete; 210 = bothknock_delay/knock_delay_channelare now REHASH-ableoptions { knock-delay / knock-delay-channel }knobs (0 disables) - leveva flood penalty (slices 201–208, COMPLETE) — command-rate flood protection (the IRCnet "fakelag" penalty clock), deferred since the start;
flood::FloodClock(idle-decay, Excess Flood kill), armed by the serve loop NOTSession::new(heartbeat opt-in precedent — synthetic-burst tests don't trip it unless they callenable_flood_protection()); lit up the dead can-flood/no-penalty privileges; 202 = per-command cost table (command_penalty: PONG exempt, WHO/LIST/etc +4, JOIN/KNOCK/INVITE +2); 203 = pre-registration guard (charge the same clock in theRegisteringphase too, after QUIT/before CAP); 204 =options { flood-kill-ahead N }config knob (REHASH-reloadable via ConfStore, parser rejects 0, NO ServerContext field — flood is serve-loop-armed); 208 = the fakelag delay/smoothing half (MAX_PENALTY=10 const; serve loopsleep_until-parks the read arm when the clock is past the threshold, output arms stay live;delay_secs/flood_delay_secs,chargeunchanged) — family now COMPLETE; 210 =MAX_PENALTYis now a REHASH-ableoptions { max-penalty }knob (default 10, 0=aggressive smoothing) — no flood threshold remains a const