code wiki / (root) / nx_dns_authoritative_test.nx

nx_dns_authoritative_test.nx source

↩ module page · 235 lines · 8710 B

1// nx_dns_authoritative_test.nx -- smoke for authoritative DNS. 2// 3// Covers: 4// 1. Verdict + RCODE enum gates 5// 2. Zone init + add_a + lookup 6// 3. ASCII name decode from wire format 7// 4. Response build for NOERROR (A record) verifying wire bytes 8// 5. Response build for NXDOMAIN 9// 6. Top-level serve_query end-to-end 10// 11// expect_exit: 0 12// 13// license_tier: ORIGINAL 14 15import "nx_syscalls_x86_64.nx" 16import "nx_dns_authoritative.nx" 17 18func bytes_eq(a: *u8, b: *u8, n: i64) -> i64 { 19 var i: i64 = 0 20 while i < n { 21 if a[i] != b[i] { return 0 } 22 i = i + 1 23 } 24 return 1 25} 26 27func main() -> i64 { 28 // ---- Verdict enum gate ---- 29 if nxda_verdict_is_valid(NXDA_OK) != 1 { return 1 } 30 if nxda_verdict_is_valid(NXDA_PARSE_ERR) != 1 { return 2 } 31 if nxda_verdict_is_valid(NXDA_VERDICT_N) != 0 { return 3 } 32 if nxda_verdict_is_valid(-1) != 0 { return 4 } 33 34 if bytes_eq(nxda_verdict_name(NXDA_BIND_ERR), 35 "BIND_ERR" as *u8, 8) != 1 { return 5 } 36 if bytes_eq(nxda_verdict_name(NXDA_PARSE_ERR), 37 "PARSE_ERR" as *u8, 9) != 1 { return 6 } 38 39 // ---- Zone init + add + lookup ---- 40 let zone_raw: *u8 = sys_mmap(NX_DNS_ZONE_BYTES) 41 let zone: *NxDnsZone = zone_raw as *NxDnsZone 42 let names_buf: *u8 = sys_mmap(1024) 43 let rz: i64 = nx_dns_zone_init(zone, 16, names_buf, 1024) 44 if rz != NXDA_OK { return 10 } 45 46 let r_add: i64 = nx_dns_zone_add_a(zone, 47 "nishifamily.com" as *u8, 15, 48 192, 0, 2, 42) 49 if r_add != NXDA_OK { return 11 } 50 51 let r_add2: i64 = nx_dns_zone_add_a(zone, 52 "audit.nishifamily.com" as *u8, 21, 53 192, 0, 2, 43) 54 if r_add2 != NXDA_OK { return 12 } 55 56 // Lookup hit 57 let idx: i64 = nx_dns_zone_lookup_a(zone, 58 "nishifamily.com" as *u8, 15) 59 if idx != 0 { return 20 } 60 61 let idx2: i64 = nx_dns_zone_lookup_a(zone, 62 "audit.nishifamily.com" as *u8, 21) 63 if idx2 != 1 { return 21 } 64 65 // Lookup miss 66 let idx_miss: i64 = nx_dns_zone_lookup_a(zone, 67 "evil.com" as *u8, 8) 68 if idx_miss != -1 { return 22 } 69 70 // ---- Wire-format name decode ---- 71 // Build a wire-format query for "test.example.com" (16 bytes). 72 // Header (12 zeros) + [4]test[7]example[3]com[0] = 12 + 18 = 30 bytes. 73 let wire: *u8 = sys_mmap(64) 74 var i: i64 = 0 75 while i < 12 { wire[i] = 0 as u8; i = i + 1 } 76 wire[12] = 4 as u8 77 wire[13] = 0x74 as u8 // t 78 wire[14] = 0x65 as u8 // e 79 wire[15] = 0x73 as u8 // s 80 wire[16] = 0x74 as u8 // t 81 wire[17] = 7 as u8 82 wire[18] = 0x65 as u8 // e 83 wire[19] = 0x78 as u8 // x 84 wire[20] = 0x61 as u8 // a 85 wire[21] = 0x6d as u8 // m 86 wire[22] = 0x70 as u8 // p 87 wire[23] = 0x6c as u8 // l 88 wire[24] = 0x65 as u8 // e 89 wire[25] = 3 as u8 90 wire[26] = 0x63 as u8 // c 91 wire[27] = 0x6f as u8 // o 92 wire[28] = 0x6d as u8 // m 93 wire[29] = 0 as u8 94 95 let dec_buf: *u8 = sys_mmap(64) 96 let after: *i64 = sys_mmap(8) as *i64 97 let n_dec: i64 = nx_dns_decode_name_ascii(wire, 30, 12, 98 dec_buf, 64, after) 99 if n_dec != 16 { return 30 } 100 if bytes_eq(dec_buf, "test.example.com" as *u8, 16) != 1 { return 31 } 101 if after[0] != 30 { return 32 } 102 103 // ---- Build response: NOERROR + A record ---- 104 // Build a synthetic query: header(12) + [3]foo[3]com[0] + QTYPE A + CLASS IN. 105 let q: *u8 = sys_mmap(64) 106 // tx_id = 0x1234 107 q[0] = 0x12 as u8; q[1] = 0x34 as u8 108 // flags = 0x0100 (RD) 109 q[2] = 0x01 as u8; q[3] = 0x00 as u8 110 // QDCOUNT 1, ANCOUNT 0, NSCOUNT 0, ARCOUNT 0 111 q[4] = 0 as u8; q[5] = 1 as u8 112 q[6] = 0 as u8; q[7] = 0 as u8 113 q[8] = 0 as u8; q[9] = 0 as u8 114 q[10] = 0 as u8; q[11] = 0 as u8 115 // QNAME = [3]foo[3]com[0] 116 q[12] = 3 as u8 117 q[13] = 0x66 as u8; q[14] = 0x6f as u8; q[15] = 0x6f as u8 // foo 118 q[16] = 3 as u8 119 q[17] = 0x63 as u8; q[18] = 0x6f as u8; q[19] = 0x6d as u8 // com 120 q[20] = 0 as u8 121 // QTYPE = A (1) 122 q[21] = 0 as u8; q[22] = 1 as u8 123 // QCLASS = IN (1) 124 q[23] = 0 as u8; q[24] = 1 as u8 125 126 let resp: *u8 = sys_mmap(128) 127 let ipv4: *u8 = sys_mmap(4) 128 ipv4[0] = 1 as u8; ipv4[1] = 2 as u8; ipv4[2] = 3 as u8; ipv4[3] = 4 as u8 129 130 let n_resp: i64 = nx_dns_build_response(q, 25, 131 NXDA_RCODE_NOERROR, 132 ipv4, 300, 133 resp, 128) 134 // Expected: 12 (header) + 13 (question echo) + 16 (answer) = 41 bytes 135 if n_resp != 41 { return 40 } 136 // tx_id echo 137 if resp[0] != 0x12 as u8 { return 41 } 138 if resp[1] != 0x34 as u8 { return 42 } 139 // QR=1, AA=1, RCODE=0 -> flags = 0x8400 140 if resp[2] != 0x84 as u8 { return 43 } 141 if resp[3] != 0x00 as u8 { return 44 } 142 // QDCOUNT = 1, ANCOUNT = 1 143 if resp[5] != 1 as u8 { return 45 } 144 if resp[7] != 1 as u8 { return 46 } 145 // Answer name pointer (0xC00C points to offset 12 = start of QNAME) 146 if resp[25] != 0xc0 as u8 { return 47 } 147 if resp[26] != 0x0c as u8 { return 48 } 148 // TYPE A 149 if resp[27] != 0 as u8 { return 49 } 150 if resp[28] != 1 as u8 { return 50 } 151 // RDATA = 1.2.3.4 152 if resp[37] != 1 as u8 { return 51 } 153 if resp[38] != 2 as u8 { return 52 } 154 if resp[39] != 3 as u8 { return 53 } 155 if resp[40] != 4 as u8 { return 54 } 156 157 // ---- Build response: NXDOMAIN (no answer) ---- 158 let n_nx: i64 = nx_dns_build_response(q, 25, 159 NXDA_RCODE_NXDOMAIN, 160 0 as *u8, 0, 161 resp, 128) 162 // Expected: 12 + 13 = 25 bytes (no answer section) 163 if n_nx != 25 { return 60 } 164 // Flags: QR=1 AA=1 RCODE=3 -> 0x8403 165 if resp[3] != 0x03 as u8 { return 61 } 166 // ANCOUNT = 0 167 if resp[7] != 0 as u8 { return 62 } 168 169 // ---- End-to-end serve_query ---- 170 // Build a query for "nishifamily.com" (15 bytes ASCII). 171 // wire: [11]nishifamily[3]com[0] = 11+1+3+1+1 = 17 bytes 172 let q2: *u8 = sys_mmap(128) 173 q2[0] = 0xab as u8; q2[1] = 0xcd as u8 174 q2[2] = 0x01 as u8; q2[3] = 0x00 as u8 175 q2[4] = 0 as u8; q2[5] = 1 as u8 176 q2[6] = 0 as u8; q2[7] = 0 as u8 177 q2[8] = 0 as u8; q2[9] = 0 as u8 178 q2[10] = 0 as u8; q2[11] = 0 as u8 179 // QNAME = [11]nishifamily[3]com[0] 180 q2[12] = 11 as u8 181 q2[13] = 0x6e as u8; q2[14] = 0x69 as u8; q2[15] = 0x73 as u8 182 q2[16] = 0x68 as u8; q2[17] = 0x69 as u8; q2[18] = 0x66 as u8 183 q2[19] = 0x61 as u8; q2[20] = 0x6d as u8; q2[21] = 0x69 as u8 184 q2[22] = 0x6c as u8; q2[23] = 0x79 as u8 185 q2[24] = 3 as u8 186 q2[25] = 0x63 as u8; q2[26] = 0x6f as u8; q2[27] = 0x6d as u8 187 q2[28] = 0 as u8 188 // QTYPE A 189 q2[29] = 0 as u8; q2[30] = 1 as u8 190 // QCLASS IN 191 q2[31] = 0 as u8; q2[32] = 1 as u8 192 193 let resp2: *u8 = sys_mmap(256) 194 let n_full: i64 = nx_dns_serve_query(zone, q2, 33, resp2, 256) 195 // Expected: 12 header + 21 question + 16 answer = 49 bytes 196 if n_full != 49 { return 70 } 197 // tx_id echo 198 if resp2[0] != 0xab as u8 { return 71 } 199 if resp2[1] != 0xcd as u8 { return 72 } 200 // RCODE = 0 (NOERROR), AA=1, QR=1 201 if resp2[3] != 0x00 as u8 { return 73 } 202 // ANCOUNT = 1 203 if resp2[7] != 1 as u8 { return 74 } 204 // RDATA = 192.0.2.42 (the zone entry) 205 if resp2[n_full - 4] != 192 as u8 { return 75 } 206 if resp2[n_full - 3] != 0 as u8 { return 76 } 207 if resp2[n_full - 2] != 2 as u8 { return 77 } 208 if resp2[n_full - 1] != 42 as u8 { return 78 } 209 210 // ---- serve_query for out-of-zone -> NXDOMAIN ---- 211 // Build a query for "evil.com" 212 let q3: *u8 = sys_mmap(64) 213 q3[0] = 0xee as u8; q3[1] = 0xff as u8 214 q3[2] = 0x01 as u8; q3[3] = 0x00 as u8 215 q3[4] = 0 as u8; q3[5] = 1 as u8 216 q3[6] = 0 as u8; q3[7] = 0 as u8 217 q3[8] = 0 as u8; q3[9] = 0 as u8 218 q3[10] = 0 as u8; q3[11] = 0 as u8 219 // [4]evil[3]com[0] 220 q3[12] = 4 as u8 221 q3[13] = 0x65 as u8; q3[14] = 0x76 as u8; q3[15] = 0x69 as u8; q3[16] = 0x6c as u8 222 q3[17] = 3 as u8 223 q3[18] = 0x63 as u8; q3[19] = 0x6f as u8; q3[20] = 0x6d as u8 224 q3[21] = 0 as u8 225 q3[22] = 0 as u8; q3[23] = 1 as u8 226 q3[24] = 0 as u8; q3[25] = 1 as u8 227 228 let resp3: *u8 = sys_mmap(128) 229 let n_nx3: i64 = nx_dns_serve_query(zone, q3, 26, resp3, 128) 230 if n_nx3 < 0 { return 80 } 231 // RCODE = 3 (NXDOMAIN) -> resp[3] = 0x03 232 if resp3[3] != 0x03 as u8 { return 81 } 233 234 return 0 235}