commit 4bf2bb19ccf91f3405ea408e84266a3a313717e5
parent 636c6dc3faa5bb93b0f31b2821870ef152af9a7b
Author: Drew DeVault <sir@cmpwn.com>
Date: Mon, 21 Jun 2021 10:40:09 -0400
net::dns: add porcelain decoder API
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
2 files changed, 62 insertions(+), 4 deletions(-)
diff --git a/net/dns/encoding.ha b/net/dns/encoding.ha
@@ -16,9 +16,47 @@ export type decoder = struct {
// Decodes a DNS message, heap allocating the resources necessary to represent
// it in Hare's type system. The caller must use [[message_free]] to free the
// return value. To decode without use of the heap, see [[decoder_init]].
-export fn decode(buf: []u8) *message = {
- abort(); // TODO
- return alloc(message { ... });
+export fn decode(buf: []u8) (*message | format) = {
+ let msg = message { ... };
+ let dec = decoder_init(buf);
+ decode_header(&dec, &msg.header)?;
+
+ for (let i = 0z; i < msg.header.qdcount; i += 1) {
+ let q = question { ... };
+ let names = decode_question(&dec, &q)?;
+
+ for (let i = 0; len(names) != 0; i += 1) {
+ let ns = decode_name(&dec, names)!;
+ names = ns.0;
+ append(q.qname, ns.1);
+ };
+
+ append(msg.questions, q);
+ };
+
+ decode_rrecords(&dec, msg.header.ancount, &msg.answers)?;
+ decode_rrecords(&dec, msg.header.nscount, &msg.authority)?;
+ decode_rrecords(&dec, msg.header.arcount, &msg.additional)?;
+ return alloc(msg);
+};
+
+fn decode_rrecords(
+ dec: *decoder,
+ count: u16,
+ out: *[]rrecord,
+) (void | format) = {
+ for (let i = 0z; i < count; i += 1) {
+ let r = rrecord { ... };
+ let names = decode_rrecord(dec, &r)?;
+
+ for (let i = 0; len(names) != 0; i += 1) {
+ let ns = decode_name(dec, names)!;
+ names = ns.0;
+ append(r.name, ns.1);
+ };
+
+ append(*out, r);
+ };
};
// Initializes a DNS message decoder. All storaged used by the decoder is either
diff --git a/net/dns/types.ha b/net/dns/types.ha
@@ -131,5 +131,25 @@ export type message = struct {
// Frees a [[message]] and the resources associated with it.
export fn message_free(msg: *message) void = {
- abort(); // TODO
+ for (let i = 0z; i < len(msg.questions); i += 1) {
+ free(msg.questions[i].qname);
+ };
+ free(msg.questions);
+
+ for (let i = 0z; i < len(msg.questions); i += 1) {
+ free(msg.answers[i].name);
+ };
+ free(msg.answers);
+
+ for (let i = 0z; i < len(msg.questions); i += 1) {
+ free(msg.answers[i].name);
+ };
+ free(msg.authority);
+
+ for (let i = 0z; i < len(msg.questions); i += 1) {
+ free(msg.answers[i].name);
+ };
+ free(msg.additional);
+
+ free(msg);
};