hare

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

types.ha (3672B)


      1 // License: MPL-2.0
      2 // (c) 2021 Drew DeVault <sir@cmpwn.com>
      3 // (c) 2021 Eyal Sawady <ecs@d2evs.net>
      4 // (c) 2021 Jonathan Halmen <slowjo@halmen.xyz>
      5 use net::ip;
      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 	DNSKEY = 48,
     19 };
     20 
     21 // Question type (superset of [[rtype]]).
     22 export type qtype = enum u16 {
     23 	A = 1,
     24 	NS = 2,
     25 	CNAME = 5,
     26 	SOA = 6,
     27 	PTR = 12,
     28 	MX = 15,
     29 	TXT = 16,
     30 	AAAA = 28,
     31 	SRV = 33,
     32 	DNSKEY = 48,
     33 	// ...
     34 	AXFR = 252,
     35 	// *
     36 	ALL = 255,
     37 };
     38 
     39 // Class type (e.g. Internet).
     40 export type class = enum u16 {
     41 	IN = 1,
     42 	CS = 2,
     43 	CH = 3,
     44 	HS = 4,
     45 };
     46 
     47 // Query class (superset of [[class]]).
     48 export type qclass = enum u16 {
     49 	IN = 1,
     50 	CS = 2,
     51 	CH = 3,
     52 	HS = 4,
     53 	// *
     54 	ANY = 255,
     55 };
     56 
     57 // DNS message header.
     58 export type header = struct {
     59 	id: u16,
     60 	op: op,
     61 	// Number of questions
     62 	qdcount: u16,
     63 	// Number of answers
     64 	ancount: u16,
     65 	// Number of name servers
     66 	nscount: u16,
     67 	// Number of additional resources
     68 	arcount: u16,
     69 };
     70 
     71 // Bit indicating if a header precedes a query or response.
     72 export type qr = enum u8 {
     73 	QUERY = 0,
     74 	RESPONSE = 1,
     75 };
     76 
     77 // Operation requested from resolver.
     78 export type opcode = enum u8 {
     79 	QUERY = 0,
     80 	IQUERY = 1,
     81 	STATUS = 2,
     82 };
     83 
     84 // Response code from resolver.
     85 export type rcode = enum u8 {
     86 	NO_ERROR = 0,
     87 	FMT_ERROR = 1,
     88 	SERVER_FAILURE = 2,
     89 	NAME_ERROR = 3,
     90 	NOT_IMPLEMENTED = 4,
     91 	REFUSED = 5,
     92 };
     93 
     94 // Operational information for this message.
     95 export type op = struct {
     96 	// Is this a query or a response?
     97 	qr: qr,
     98 	// Operation code
     99 	opcode: opcode,
    100 	// Authoritative answer bit
    101 	aa: bool,
    102 	// Truncation bit
    103 	tc: bool,
    104 	// Recursion desired bit
    105 	rd: bool,
    106 	// Recursion available bit
    107 	ra: bool,
    108 	// Response code
    109 	rcode: rcode,
    110 };
    111 
    112 // A question section item.
    113 export type question = struct {
    114 	qname: []str,
    115 	qtype: qtype,
    116 	qclass: qclass,
    117 };
    118 
    119 // A resource record item.
    120 export type rrecord = struct {
    121 	name: []str,
    122 	rtype: rtype,
    123 	class: class,
    124 	ttl: u32,
    125 	rdata: rdata,
    126 };
    127 
    128 // An A record.
    129 export type a = ip::addr4;
    130 
    131 // An AAAA record.
    132 export type aaaa = ip::addr6;
    133 
    134 // An MX record.
    135 export type mx = struct {
    136 	priority: u16,
    137 	name: []str,
    138 };
    139 
    140 // A TXT record.
    141 export type txt = [][]u8;
    142 
    143 // The raw rdata field for an [[rrecord]] with an unknown [[rtype]].
    144 export type unknown_rdata = []u8;
    145 
    146 // Tagged union of supported rdata types.
    147 export type rdata = (a | aaaa | mx | txt | unknown_rdata);
    148 
    149 // A DNS message, Hare representation. See [[encode]] and [[decode]] for the DNS
    150 // representation.
    151 export type message = struct {
    152 	header: header,
    153 	questions: []question,
    154 	answers: []rrecord,
    155 	authority: []rrecord,
    156 	additional: []rrecord,
    157 };
    158 
    159 // Frees a [[message]] and the resources associated with it.
    160 export fn message_free(msg: *message) void = {
    161 	for (let i = 0z; i < len(msg.questions); i += 1) {
    162 		strings_free(msg.questions[i].qname);
    163 	};
    164 	free(msg.questions);
    165 
    166 	for (let i = 0z; i < len(msg.answers); i += 1) {
    167 		rrecord_finish(&msg.answers[i]);
    168 	};
    169 	free(msg.answers);
    170 
    171 	for (let i = 0z; i < len(msg.authority); i += 1) {
    172 		rrecord_finish(&msg.authority[i]);
    173 	};
    174 	free(msg.authority);
    175 
    176 	for (let i = 0z; i < len(msg.additional); i += 1) {
    177 		rrecord_finish(&msg.additional[i]);
    178 	};
    179 	free(msg.additional);
    180 
    181 	free(msg);
    182 };
    183 
    184 fn strings_free(in: []str) void = {
    185 	for (let i = 0z; i < len(in); i += 1) {
    186 		free(in[i]);
    187 	};
    188 	free(in);
    189 };
    190 
    191 fn bytes_free(in: [][]u8) void = {
    192 	for (let i = 0z; i < len(in); i += 1) {
    193 		free(in[i]);
    194 	};
    195 	free(in);
    196 };
    197 
    198 fn rrecord_finish(rr: *rrecord) void = {
    199 	strings_free(rr.name);
    200 	match (rr.rdata) {
    201 	case let mx: mx =>
    202 		strings_free(mx.name);
    203 	case let tx: txt =>
    204 		bytes_free(tx: [][]u8);
    205 	case => void;
    206 	};
    207 };