code wiki / (root) / nx_dns_test.nx

nx_dns_test.nx source

↩ module page · 93 lines · 4772 B

1// nx_dns_test.nx -- KAT + self-consistency for the DNS stub resolver. 2// 3// Vector source: an "example.com" query/response pair derived bits-up 4// from RFC 1035 ยง4.1 wire format. IP 93.184.216.34 is the real public 5// A record for example.com -- usable as a worked example because IANA 6// reserves the example.* TLD for documentation under RFC 2606. 7// 8// expect_exit: 0 9// 10// license_tier: ORIGINAL 11 12import "nx_syscalls.nx" 13import "nx_dns.nx" 14 15func main() -> i64 { 16 // ---- Test A: encode_name("example.com", 11) -> 13 bytes. ---- 17 let name: *u8 = sys_mmap(64) 18 name[0]=101; name[1]=120; name[2]=97; name[3]=109; name[4]=112 19 name[5]=108; name[6]=101 // "example" 20 name[7]=46 // '.' 21 name[8]=99; name[9]=111; name[10]=109 // "com" 22 let qname: *u8 = sys_mmap(64) 23 let n_qname: i64 = nx_dns_encode_name(name, 11, qname, 64) 24 if n_qname != 13 { return 1 } 25 if (qname[0] & 0xff) != 7 { return 2 } 26 if (qname[1] & 0xff) != 101 { return 3 } 27 if (qname[7] & 0xff) != 101 { return 4 } 28 if (qname[8] & 0xff) != 3 { return 5 } 29 if (qname[9] & 0xff) != 99 { return 6 } 30 if (qname[12] & 0xff) != 0 { return 7 } 31 32 // ---- Test B: build_query("example.com", A, tx=0x1234) = 29 bytes. ---- 33 let q: *u8 = sys_mmap(128) 34 let n_q: i64 = nx_dns_build_query(name, 11, NX_DNS_TYPE_A, 0x1234, q, 128) 35 if n_q != 29 { return 10 } 36 if (q[0] & 0xff) != 0x12 { return 11 } 37 if (q[1] & 0xff) != 0x34 { return 12 } 38 if (q[2] & 0xff) != 0x01 { return 13 } // flags hi: RD set 39 if (q[3] & 0xff) != 0x00 { return 14 } 40 if (q[5] & 0xff) != 0x01 { return 15 } // QDCOUNT lo = 1 41 if (q[7] & 0xff) != 0x00 { return 16 } // ANCOUNT lo = 0 42 if (q[12] & 0xff) != 7 { return 17 } // QNAME label-len 7 43 if (q[24] & 0xff) != 0 { return 18 } // root terminator 44 if (q[26] & 0xff) != 1 { return 19 } // QTYPE = A 45 if (q[28] & 0xff) != 1 { return 20 } // QCLASS = IN 46 47 // ---- Test C: parse_response_a with a canned example.com reply. ---- 48 let resp: *u8 = sys_mmap(64) 49 resp[0]=0x12; resp[1]=0x34 // tx_id 50 resp[2]=0x81; resp[3]=0x80 // QR+RD+RA, RCODE=0 51 resp[4]=0; resp[5]=1 // QDCOUNT=1 52 resp[6]=0; resp[7]=1 // ANCOUNT=1 53 resp[8]=0; resp[9]=0 54 resp[10]=0; resp[11]=0 55 resp[12]=7; resp[13]=101; resp[14]=120; resp[15]=97; resp[16]=109 56 resp[17]=112; resp[18]=108; resp[19]=101 // "example" 57 resp[20]=3; resp[21]=99; resp[22]=111; resp[23]=109 // "com" 58 resp[24]=0 // root 59 resp[25]=0; resp[26]=1 // QTYPE=A 60 resp[27]=0; resp[28]=1 // QCLASS=IN 61 resp[29]=0xc0; resp[30]=0x0c // NAME = ptr to off 12 62 resp[31]=0; resp[32]=1 // TYPE=A 63 resp[33]=0; resp[34]=1 // CLASS=IN 64 resp[35]=0; resp[36]=0; resp[37]=0; resp[38]=0x3c // TTL=60 65 resp[39]=0; resp[40]=4 // RDLENGTH=4 66 resp[41]=93; resp[42]=184; resp[43]=216; resp[44]=34 // 93.184.216.34 67 let ip: *u8 = sys_mmap(16) 68 let v: i64 = nx_dns_parse_response_a(resp, 45, 0x1234, ip) 69 if v != NX_DNS_VERDICT_OK { return 30 } 70 if (ip[0] & 0xff) != 93 { return 31 } 71 if (ip[1] & 0xff) != 184 { return 32 } 72 if (ip[2] & 0xff) != 216 { return 33 } 73 if (ip[3] & 0xff) != 34 { return 34 } 74 75 // ---- Test D: tx_id mismatch must be rejected (spoof defense). ---- 76 let v2: i64 = nx_dns_parse_response_a(resp, 45, 0x9999, ip) 77 if v2 != NX_DNS_VERDICT_TXID_MISMATCH { return 40 } 78 79 // ---- Test E: pointer-loop attack terminates with PTR_LOOP verdict. ---- 80 let loop_pkt: *u8 = sys_mmap(16) 81 loop_pkt[0] = 0xc0 82 loop_pkt[1] = 0x00 // ptr at off 0 -> off 0 83 let v3: i64 = nx_dns_skip_name(loop_pkt, 2, 0) 84 if v3 != -NX_DNS_VERDICT_PTR_LOOP { return 50 } 85 86 // ---- Test F: sealed-enum validity gate. ---- 87 if nx_dns_verdict_is_valid(NX_DNS_VERDICT_OK) != 1 { return 60 } 88 if nx_dns_verdict_is_valid(NX_DNS_VERDICT_N) != 0 { return 61 } 89 if nx_dns_verdict_is_valid(0 - 1) != 0 { return 62 } 90 if nx_dns_verdict_is_valid(NX_DNS_VERDICT_NO_A_RECORD) != 1 { return 63 } 91 92 return 0 93}