hare

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

commit 3b966e65cac9e761e309308b064361fa2a723f85
parent e348f32284b0e1f55426c206e42c295c5bd2df11
Author: Conrad Hoffmann <ch@bitfehler.net>
Date:   Mon, 10 Jul 2023 15:44:26 +0200

net::dns: add TSIG records and decoding

As defined in https://datatracker.ietf.org/doc/html/rfc2845

Because who doesn't love 48 bit integers?

Signed-off-by: Conrad Hoffmann <ch@bitfehler.net>

Diffstat:
Mnet/dns/decode.ha | 47+++++++++++++++++++++++++++++++++++++++++++++++
Mnet/dns/types.ha | 20+++++++++++++++++++-
2 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/net/dns/decode.ha b/net/dns/decode.ha @@ -74,6 +74,17 @@ fn decode_u32(dec: *decoder) (u32 | format) = { return val; }; +fn decode_u48(dec: *decoder) (u64 | format) = { + if (len(dec.cur) < 6) { + return format; + }; + let buf: [8]u8 = [0...]; + buf[2..] = dec.cur[..6]; + const val = endian::begetu64(buf[..]); + dec.cur = dec.cur[6..]; + return val; +}; + fn decode_header(dec: *decoder, head: *header) (void | format) = { head.id = decode_u16(dec)?; const rawop = decode_u16(dec)?; @@ -209,6 +220,8 @@ fn decode_rdata(dec: *decoder, rtype: rtype, rlen: size) (rdata | format) = { return decode_srv(&sub); case rtype::SSHFP => return decode_sshfp(&sub); + case rtype::TSIG => + return decode_tsig(&sub); case rtype::TXT => return decode_txt(&sub); case => @@ -318,6 +331,40 @@ fn decode_sshfp(dec: *decoder) (rdata | format) = { return r; }; +fn decode_tsig(dec: *decoder) (rdata | format) = { + let success = false; + let r = tsig { + algorithm = decode_name(dec)?, + ... + }; + defer if (!success) free(r.algorithm); + + r.time_signed = decode_u48(dec)?; + r.fudge = decode_u16(dec)?; + r.mac_len = decode_u16(dec)?; + + if (len(dec.cur) < r.mac_len) { + return format; + }; + append(r.mac, dec.cur[..r.mac_len]...); + defer if (!success) free(r.mac); + dec.cur = dec.cur[r.mac_len..]; + + r.orig_id = decode_u16(dec)?; + r.error = decode_u16(dec)?; + r.other_len = decode_u16(dec)?; + + if (len(dec.cur) != r.other_len) { + return format; + }; + if (r.other_len > 0) { + append(r.other_data, dec.cur[..]...); + }; + + success = true; + return r; +}; + fn decode_txt(dec: *decoder) (rdata | format) = { let success = false; let items: txt = []; diff --git a/net/dns/types.ha b/net/dns/types.ha @@ -203,6 +203,19 @@ export type sshfp = struct { fingerprint: []u8, }; +// A TSIG record. +export type tsig = struct { + algorithm: []str, + time_signed: u64, + fudge: u16, + mac_len: u16, + mac: []u8, + orig_id: u16, + error: u16, + other_len: u16, + other_data: []u8, +}; + // A TXT record. export type txt = [][]u8; @@ -210,7 +223,8 @@ export type txt = [][]u8; export type unknown_rdata = []u8; // Tagged union of supported rdata types. -export type rdata = (a | aaaa | caa | cname | mx | ns | ptr | soa | srv | sshfp | txt | unknown_rdata); +export type rdata = (a | aaaa | caa | cname | mx | ns | ptr | soa | srv + | sshfp | tsig | txt | unknown_rdata); // A DNS message, Hare representation. See [[encode]] and [[decode]] for the DNS // representation. @@ -271,6 +285,10 @@ fn rrecord_finish(rr: *rrecord) void = { strings::freeall(sr.target); case let sf: sshfp => free(sf.fingerprint); + case let ts: tsig => + strings::freeall(ts.algorithm); + free(ts.mac); + free(ts.other_data); case let tx: txt => bytes_free(tx: [][]u8); case => void;