nx_email_mx.nx
buildroot/runtime/nx_email_mx.nx
about
nx_email_mx.nx -- EMAIL RUNG R0: MX-record resolution (RFC 5321 §5.1).
module: nishi-core.email.mx
depends: nishi-core.net.dns
capability: CORE_EMAIL
The FIRST email-specific rung above the existing sovereign transport
hardware (nx_socket UDP + nx_dns wire codec). Before sending mail a
client must learn WHICH host accepts mail for a domain: that is the
domain's MX (Mail eXchanger) record set, ordered by preference
(lowest preference value = highest priority, tried first -- RFC 5321
§5.1). nx_dns already encodes the MX qtype (NX_DNS_TYPE_MX=15) and a
generic query builder; what was missing is the ANSWER-side parse for
MX rdata (preference u16 + exchange domain-name, which may use RFC
1035 §4.1.4 compression pointers) plus the preference ordering.
This module is PURE (no syscalls): parse/decode/sort over caller
buffers, architecture-neutral exactly like nx_dns.nx, so the live
UDP composition can live in a later nx_email_mx_io.nx (mirrors the
nx_dns / nx_dns_io split) without dragging a syscall dependency into
the codec. Query building is already covered: call the existing
nx_dns_build_query(name, len, NX_DNS_TYPE_MX, tx_id, out, cap).
license_tier: INDEPENDENT_REDERIVE
genealogy_id: international-research-sources/ietf/rfc_1035 + ietf/rfc_5321
lineage_id: nishi_email_mx_resolution_r0
nx_safety_envelope:
intended_use: "MX rdata parse (preference + exchange name) +
preference ordering. RFC 5321 §5.1 substrate."
sil_target: SIL2 (DNS-spoof picks the attacker's MX)
evidence: [RFC_5321_canonical_basis, sealed_verdict_enum,
txid_spoof_gate, bounded_128_hop_anti_cycle,
compression_pointer_decode, preference_sort]
hazard_register: [bug-tape-MX-spoof-relay-hijack,
bug-tape-compression-pointer-cycle-OOM]
residual_risk: "Authenticity of the MX set needs DNSSEC /
DANE in an upstream consumer (queued R5). This
substrate enforces the txid spoof gate + a
128-hop bound on compression-pointer chase."
dependencies 1 imports · 1 importers
imports: nx_dns.nx
imported by: nx_email_mx_gate.nx
structs
| none |
consts
| 46 | const NX_EMX_OK: i64 = 1 |
| 47 | const NX_EMX_BAD_HEADER: i64 = 2 |
| 48 | const NX_EMX_TXID_MISMATCH: i64 = 3 |
| 49 | const NX_EMX_NOT_RESPONSE: i64 = 4 |
| 50 | const NX_EMX_TRUNCATED: i64 = 5 |
| 51 | const NX_EMX_RCODE_NONZERO: i64 = 6 |
| 52 | const NX_EMX_NO_MX: i64 = 7 |
| 53 | const NX_EMX_BAD_RDATA: i64 = 8 |
| 54 | const NX_EMX_NAMES_FULL: i64 = 9 |
| 55 | const NX_EMX_PTR_LOOP: i64 = 10 |
| 56 | const NX_EMX_BAD_LABEL: i64 = 11 |
| 57 | const NX_EMX_N: i64 = 12 |
| 62 | const NX_EMX_MAX_HOPS: i64 = 128 |
functions
| 64 | func nx_email_mx_verdict_name(v: i64) -> *u8 |
| 79 | func nx_email_mx_verdict_is_valid(v: i64) -> i64 |
| 96 | func emx_decode_name(buf: *u8, n: i64, start: i64, out: *u8, out_cap: i64) -> i64 called by 1: nx_email_mx_parse |
| 189 | func nx_email_mx_parse( |
| 255 | func nx_email_mx_sort(prefs: *i64, ex_off: *i64, count: i64) -> i64 called by 1: main |