types.ha (6044B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use net::ip; 5 use strings; 6 7 // Record type. 8 export type rtype = enum u16 { 9 A = 1, 10 NS = 2, 11 CNAME = 5, 12 SOA = 6, 13 PTR = 12, 14 MX = 15, 15 TXT = 16, 16 AAAA = 28, 17 SRV = 33, 18 OPT = 41, 19 SSHFP = 44, 20 RRSIG = 46, 21 NSEC = 47, 22 DNSKEY = 48, 23 TSIG = 250, 24 CAA = 257, 25 }; 26 27 // Question type (superset of [[rtype]]). 28 export type qtype = enum u16 { 29 A = 1, 30 NS = 2, 31 CNAME = 5, 32 SOA = 6, 33 PTR = 12, 34 MX = 15, 35 TXT = 16, 36 AAAA = 28, 37 SRV = 33, 38 OPT = 41, 39 SSHFP = 44, 40 RRSIG = 46, 41 NSEC = 47, 42 DNSKEY = 48, 43 // ... 44 AXFR = 252, 45 // * 46 ALL = 255, 47 CAA = 257, 48 }; 49 50 // Class type (e.g. Internet). 51 export type class = enum u16 { 52 IN = 1, 53 CS = 2, 54 CH = 3, 55 HS = 4, 56 }; 57 58 // Query class (superset of [[class]]). 59 export type qclass = enum u16 { 60 IN = 1, 61 CS = 2, 62 CH = 3, 63 HS = 4, 64 // * 65 NONE = 254, 66 ANY = 255, 67 }; 68 69 // DNS message header. 70 export type header = struct { 71 id: u16, 72 op: op, 73 // Number of questions 74 qdcount: u16, 75 // Number of answers 76 ancount: u16, 77 // Number of name servers 78 nscount: u16, 79 // Number of additional resources 80 arcount: u16, 81 }; 82 83 // Bit indicating if a header precedes a query or response. 84 export type qr = enum u8 { 85 QUERY = 0, 86 RESPONSE = 1, 87 }; 88 89 // Operation requested from resolver. 90 export type opcode = enum u8 { 91 QUERY = 0, 92 IQUERY = 1, 93 STATUS = 2, 94 UPDATE = 5, 95 }; 96 97 // Response code from resolver. 98 export type rcode = enum u8 { 99 NOERROR = 0, 100 FORMERR = 1, 101 SERVFAIL = 2, 102 NXDOMAIN = 3, 103 NOTIMP = 4, 104 REFUSED = 5, 105 // RFC 2136 UPDATE 106 YXDOMAIN = 6, 107 YXRRSET = 7, 108 NXRRSET = 8, 109 NOTAUTH = 9, 110 NOTZONE = 10, 111 // RFC 2845 TSIG 112 BADSIG = 16, 113 BADKEY = 17, 114 BADTIME = 18, 115 }; 116 117 // Operational information for this message. 118 export type op = struct { 119 // Is this a query or a response? 120 qr: qr, 121 // Operation code 122 opcode: opcode, 123 // Authoritative answer bit 124 aa: bool, 125 // Truncation bit 126 tc: bool, 127 // Recursion desired bit 128 rd: bool, 129 // Recursion available bit 130 ra: bool, 131 // Response code 132 rcode: rcode, 133 }; 134 135 // A question section item. 136 export type question = struct { 137 qname: []str, 138 qtype: qtype, 139 qclass: qclass, 140 }; 141 142 // A resource record item. 143 export type rrecord = struct { 144 name: []str, 145 rtype: rtype, 146 class: class, 147 ttl: u32, 148 rdata: rdata, 149 }; 150 151 // An EDNS (RFC 6891) option, as contained in [[opt]] records. 152 export type edns_opt = struct { 153 code: u16, 154 data: []u8, 155 }; 156 157 // An A record. 158 export type a = ip::addr4; 159 160 // An AAAA record. 161 export type aaaa = ip::addr6; 162 163 // A CAA record. 164 export type caa = struct { 165 flags: u8, 166 tag: str, 167 value: str, 168 }; 169 170 // A CNAME record. 171 export type cname = struct { 172 name: []str, 173 }; 174 175 // A DNSKEY record. 176 export type dnskey = struct { 177 flags: u16, 178 protocol: u8, 179 algorithm: u8, 180 key: []u8, 181 }; 182 183 // An MX record. 184 export type mx = struct { 185 priority: u16, 186 name: []str, 187 }; 188 189 // An NS record. 190 export type ns = struct { 191 name: []str, 192 }; 193 194 // An OPT record (EDNS, RFC 6891). 195 export type opt = struct { 196 options: []edns_opt, 197 }; 198 199 // An NSEC record. 200 export type nsec = struct { 201 next_domain: []str, 202 type_bitmaps: []u8, 203 }; 204 205 // A PTR record. 206 export type ptr = struct { 207 name: []str, 208 }; 209 210 // An RRSIG record. 211 export type rrsig = struct { 212 type_covered: u16, 213 algorithm: u8, 214 labels: u8, 215 orig_ttl: u32, 216 sig_expiration: u32, 217 sig_inception: u32, 218 key_tag: u16, 219 signer_name: []str, 220 signature: []u8, 221 }; 222 223 // An SOA record. 224 export type soa = struct { 225 mname: []str, 226 rname: []str, 227 serial: u32, 228 refresh: u32, 229 retry: u32, 230 expire: u32, 231 }; 232 233 // An SRV record. 234 export type srv = struct { 235 priority: u16, 236 weight: u16, 237 port: u16, 238 target: []str, 239 }; 240 241 // An SSHFP record. 242 export type sshfp = struct { 243 algorithm: u8, 244 fp_type: u8, 245 fingerprint: []u8, 246 }; 247 248 // A TSIG record. 249 export type tsig = struct { 250 algorithm: []str, 251 time_signed: u64, 252 fudge: u16, 253 mac_len: u16, 254 mac: []u8, 255 orig_id: u16, 256 error: u16, 257 other_len: u16, 258 other_data: []u8, 259 }; 260 261 // A TXT record. 262 export type txt = [][]u8; 263 264 // The raw rdata field for an [[rrecord]] with an unknown [[rtype]]. 265 export type unknown_rdata = []u8; 266 267 // Tagged union of supported rdata types. 268 export type rdata = (a | aaaa | caa | cname | dnskey | mx | ns | nsec | opt 269 | ptr | rrsig | soa | srv | sshfp | tsig | txt | unknown_rdata); 270 271 // A DNS message, Hare representation. See [[encode]] and [[decode]] for the DNS 272 // representation. 273 export type message = struct { 274 header: header, 275 questions: []question, 276 answers: []rrecord, 277 authority: []rrecord, 278 additional: []rrecord, 279 }; 280 281 // Frees a [[message]] and the resources associated with it. 282 export fn message_free(msg: *message) void = { 283 for (let i = 0z; i < len(msg.questions); i += 1) { 284 strings::freeall(msg.questions[i].qname); 285 }; 286 free(msg.questions); 287 288 rrecords_free(msg.answers); 289 rrecords_free(msg.authority); 290 rrecords_free(msg.additional); 291 292 free(msg); 293 }; 294 295 fn bytes_free(in: [][]u8) void = { 296 for (let i = 0z; i < len(in); i += 1) { 297 free(in[i]); 298 }; 299 free(in); 300 }; 301 302 fn rrecords_free(rrs: []rrecord) void = { 303 for (let i = 0z; i < len(rrs); i += 1) { 304 rrecord_finish(&rrs[i]); 305 }; 306 free(rrs); 307 }; 308 309 fn rrecord_finish(rr: *rrecord) void = { 310 strings::freeall(rr.name); 311 match (rr.rdata) { 312 case let cn: cname => 313 strings::freeall(cn.name); 314 case let ca: caa => 315 free(ca.tag); 316 free(ca.value); 317 case let dk: dnskey => 318 free(dk.key); 319 case let mx: mx => 320 strings::freeall(mx.name); 321 case let ns: ns => 322 strings::freeall(ns.name); 323 case let opt: opt => 324 for (let i = 0z; i < len(opt.options); i += 1) { 325 free(opt.options[i].data); 326 }; 327 free(opt.options); 328 case let nsec: nsec => 329 strings::freeall(nsec.next_domain); 330 free(nsec.type_bitmaps); 331 case let ptr: ptr => 332 strings::freeall(ptr.name); 333 case let rrsig: rrsig => 334 strings::freeall(rrsig.signer_name); 335 free(rrsig.signature); 336 case let so: soa => 337 strings::freeall(so.mname); 338 strings::freeall(so.rname); 339 case let sr: srv => 340 strings::freeall(sr.target); 341 case let sf: sshfp => 342 free(sf.fingerprint); 343 case let ts: tsig => 344 strings::freeall(ts.algorithm); 345 free(ts.mac); 346 free(ts.other_data); 347 case let tx: txt => 348 bytes_free(tx: [][]u8); 349 case => void; 350 }; 351 };