hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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 };