commit 07fb96f9ad9c586ec5500929bf4a9967ca1a1107
parent 6f88e34bdcc1db8c1b92b575f10a2069542aa6f3
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 29 Jun 2021 13:34:40 -0400
net::dns: implement TXT rdata decoder
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/net/dns/decode.ha b/net/dns/decode.ha
@@ -41,6 +41,15 @@ fn decoder_init(buf: []u8) decoder = decoder {
...
};
+fn decode_u8(dec: *decoder) (u8 | format) = {
+ if (len(dec.cur) < 1) {
+ return format;
+ };
+ const val = dec.cur[0];
+ dec.cur = dec.cur[1..];
+ return val;
+};
+
fn decode_u16(dec: *decoder) (u16 | format) = {
if (len(dec.cur) < 2) {
return format;
@@ -140,6 +149,7 @@ fn decode_rdata(dec: *decoder, rtype: rtype, rlen: size) (rdata | format) = {
rtype::A => decode_a(dec),
rtype::AAAA => decode_aaaa(dec),
rtype::MX => decode_mx(dec),
+ rtype::TXT => decode_txt(dec),
* => {
let buf = dec.cur[..rlen];
dec.cur = dec.cur[rlen..];
@@ -175,4 +185,19 @@ fn decode_mx(dec: *decoder) (rdata | format) = {
};
};
+fn decode_txt(dec: *decoder) (rdata | format) = {
+ let items: txt = [];
+ for (len(dec.cur) != 0) {
+ const ln = decode_u8(dec)?;
+ if (len(dec.cur) < ln) {
+ return format;
+ };
+ let item: []u8 = [];
+ append(item, dec.cur[..ln]...);
+ dec.cur = dec.cur[ln..];
+ append(items, item);
+ };
+ return items;
+};
+
// TODO: Expand breadth of supported rdata decoders
diff --git a/net/dns/types.ha b/net/dns/types.ha
@@ -133,11 +133,14 @@ export type mx = struct {
name: []str,
};
+// A TXT record.
+export type txt = [][]u8;
+
// The raw rdata field for an [[rrecord]] with an unknown [[rtype]].
export type unknown_rdata = []u8;
// Tagged union of supported rdata types.
-export type rdata = (a | aaaa | mx | unknown_rdata);
+export type rdata = (a | aaaa | mx | txt | unknown_rdata);
// A DNS message, Hare representation. See [[encode]] and [[decode]] for the DNS
// representation.
@@ -181,10 +184,18 @@ fn strings_free(in: []str) void = {
free(in);
};
+fn bytes_free(in: [][]u8) void = {
+ for (let i = 0z; i < len(in); i += 1) {
+ free(in[i]);
+ };
+ free(in);
+};
+
fn rrecord_finish(rr: *rrecord) void = {
strings_free(rr.name);
match (rr.rdata) {
mx: mx => strings_free(mx.name),
+ tx: txt => bytes_free(tx: [][]u8),
* => void,
};
};