nx_dns_client_probe.nx source
↩ module page · 84 lines · 2764 B
1// nx_dns_client_probe.nx -- substrate-side UDP DNS verifier.
2//
3// Sends a real DNS query to 127.0.0.1:5353 + verifies the answer.
4// Used by bench/nx_dns_serve_loopback.sh as the live verification
5// step for the DNS daemon. Sovereign per cardinal: no dig, no
6// nslookup, no python; substrate talks to substrate.
7//
8// Returns 0 on success (answer matches expected RDATA 192.0.2.42)
9// or a numeric error code per failure mode.
10//
11// expect_exit: 0
12
13import "nx_syscalls_x86_64.nx"
14import "nx_dns.nx"
15const SOCK_MAGIC_5353: i64 = 5353
16
17const SOCK_DGRAM_C: i64 = 2
18
19func bytes_eq(a: *u8, b: *u8, n: i64) -> i64 {
20 var i: i64 = 0
21 while i < n {
22 if a[i] != b[i] { return 0 }
23 i = i + 1
24 }
25 return 1
26}
27
28func main() -> i64 {
29 // Build sockaddr_in 127.0.0.1:5353
30 let addr: *u8 = sys_mmap(16)
31 addr[0] = 2 as u8; addr[1] = 0 as u8
32 addr[2] = 0x14 as u8; addr[3] = 0xe9 as u8 // port SOCK_MAGIC_5353 BE
33 addr[4] = 127 as u8; addr[5] = 0 as u8; addr[6] = 0 as u8; addr[7] = 1 as u8
34 addr[8] = 0 as u8; addr[9] = 0 as u8
35 addr[10] = 0 as u8; addr[11] = 0 as u8
36 addr[12] = 0 as u8; addr[13] = 0 as u8
37 addr[14] = 0 as u8; addr[15] = 0 as u8
38
39 // UDP socket
40 let fd: i64 = sys_socket(2, SOCK_DGRAM_C, 0)
41 if fd < 0 { return 10 }
42
43 // Build query for nishifamily.com
44 let qbuf: *u8 = sys_mmap(128)
45 let qn: i64 = nx_dns_build_query("nishifamily.com" as *u8, 15,
46 NX_DNS_TYPE_A, 0x1234,
47 qbuf, 128)
48 if qn < 0 { sys_close(fd); return 20 }
49
50 // sendto
51 let sent: i64 = sys_sendto(fd, qbuf, qn, addr, 16)
52 if sent < 0 { sys_close(fd); return 30 }
53
54 // recvfrom
55 let rbuf: *u8 = sys_mmap(512)
56 let from_addr: *u8 = sys_mmap(16)
57 let from_alen: *i64 = sys_mmap(8) as *i64
58 from_alen[0] = 16
59 let n_recv: i64 = sys_recvfrom(fd, rbuf, 512, from_addr, from_alen)
60 sys_close(fd)
61 if n_recv < 0 { return 40 }
62 if n_recv < 12 { return 41 }
63
64 // Verify response shape:
65 // tx_id echo (0x1234)
66 if rbuf[0] != 0x12 as u8 { return 50 }
67 if rbuf[1] != 0x34 as u8 { return 51 }
68 // QR=1 + AA=1 + rcode=0 => flags = 0x8400
69 if rbuf[2] != 0x84 as u8 { return 52 }
70 if rbuf[3] != 0x00 as u8 { return 53 }
71 // QDCOUNT = 1
72 if rbuf[5] != 1 as u8 { return 54 }
73 // ANCOUNT = 1
74 if rbuf[7] != 1 as u8 { return 55 }
75
76 // Parse the answer's RDATA (skip header + question + answer header).
77 // Expected RDATA: 192.0.2.42 in the LAST 4 bytes of the packet.
78 if rbuf[n_recv - 4] != 192 as u8 { return 60 }
79 if rbuf[n_recv - 3] != 0 as u8 { return 61 }
80 if rbuf[n_recv - 2] != 2 as u8 { return 62 }
81 if rbuf[n_recv - 1] != 42 as u8 { return 63 }
82
83 return 0
84}