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