From 0c324adaa6d594407074baf25c2ce70a44e88a3c Mon Sep 17 00:00:00 2001
From: "Meredith L. Patterson" <clonearmy@gmail.com>
Date: Sat, 26 May 2012 15:50:39 +0200
Subject: [PATCH] Nearly done with RR parsing, need to write two helpers for
 this.

---
 examples/dns.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++--
 examples/dns.h |   5 +-
 2 files changed, 198 insertions(+), 8 deletions(-)

diff --git a/examples/dns.c b/examples/dns.c
index faf9124..ae43594 100644
--- a/examples/dns.c
+++ b/examples/dns.c
@@ -1,6 +1,7 @@
 #include "../src/hammer.h"
 #include "dns_common.h"
 #include "dns.h"
+#include "rr.h"
 
 #define false 0
 #define true 1
@@ -40,7 +41,7 @@ struct dns_qname get_qname(const HParsedToken *t) {
   const HParsedToken *labels = t->seq->elements[0];
   struct dns_qname ret = {
     .qlen = labels->seq->used,
-    .labels = h_arena_malloc(t->seq->arena, sizeof(ret.labels)*ret.qlen)
+    .labels = h_arena_malloc(t->seq->arena, sizeof(ret.labels)*labels->seq->used)
   };
   // i is which label we're on
   for (size_t i=0; i<labels->seq->used; ++i) {
@@ -60,16 +61,204 @@ char* get_domain(const HParsedToken *t) {
   case TT_SEQUENCE:
     {
       // Sequence of subdomains separated by "."
-      return NULL;
+      // Each subdomain is a label, which can be no more than 63 chars.
+      char *ret = h_arena_malloc(t->seq->arena, 64*t->seq->used);
+      size_t count = 0;
+      for (size_t i=0; i<t->seq->used; ++i) {
+	HParsedToken *tmp = t->seq->elements[i];
+	for (size_t j=0; j<tmp->seq->used; ++j) {
+	  ret[count] = tmp->seq->elements[i]->uint;
+	  ++count;
+	}
+	ret[count] = '.';
+	++count;
+      }
+      ret[count-1] = '\x00';
+      return ret;
     }
   default:
     return NULL;
   }
-
 }
 
 void set_rr(struct dns_rr rr, HCountedArray *rdata) {
+  uint8_t *data = h_arena_malloc(rdata->arena, sizeof(uint8_t)*rdata->used);
+  for (size_t i=0; i<rdata->used; ++i)
+    data[i] = rdata->elements[i]->uint;
 
+  // If the RR doesn't parse, set its type to 0.
+  switch(rr.type) {
+  case 1: // A
+    {
+      const HParseResult *r = h_parse(init_a(), (const uint8_t*)data, rdata->used);
+      if (!r) 
+	rr.type = 0;
+      else 
+	rr.a = r->ast->seq->elements[0]->uint;
+      break;
+    }
+  case 2: // NS
+    {
+      const HParseResult *r = h_parse(init_ns(), (const uint8_t*)data, rdata->used);
+      if (!r)
+	rr.type = 0;
+      else
+	rr.ns = get_domain(r->ast->seq->elements[0]);
+      break;
+    }
+  case 3: // MD
+    {
+      const HParseResult *r = h_parse(init_md(), (const uint8_t*)data, rdata->used);
+      if (!r)
+	rr.type = 0;
+      else
+	rr.md = get_domain(r->ast->seq->elements[0]);
+      break;
+    }
+  case 4: // MF
+    {
+      const HParseResult *r = h_parse(init_mf(), (const uint8_t*)data, rdata->used);
+      if (!r)
+	rr.type = 0;
+      else
+	rr.md = get_domain(r->ast->seq->elements[0]);
+      break;
+    }
+  case 5: // CNAME
+    {
+      const HParseResult *r = h_parse(init_cname(), (const uint8_t*)data, rdata->used);
+      if (!r)
+	rr.type = 0;
+      else
+	rr.cname = get_domain(r->ast->seq->elements[0]);
+      break;
+    }
+  case 6: // SOA
+    {
+      const HParseResult *r = h_parse(init_soa(), (const uint8_t*)data, rdata->used);
+      if (!r)
+	rr.type = 0;
+      else {
+	rr.soa.mname = get_domain(r->ast->seq->elements[0]);
+	rr.soa.rname = get_domain(r->ast->seq->elements[1]);
+	rr.soa.serial = r->ast->seq->elements[2]->uint;
+	rr.soa.refresh = r->ast->seq->elements[3]->uint;
+	rr.soa.retry = r->ast->seq->elements[4]->uint;
+	rr.soa.expire = r->ast->seq->elements[5]->uint;
+	rr.soa.minimum = r->ast->seq->elements[6]->uint;
+      }
+      break;
+    }
+  case 7: // MB
+    {
+      const HParseResult *r = h_parse(init_mb(), (const uint8_t*)data, rdata->used);
+      if (!r)
+	rr.type = 0;
+      else
+	rr.mb = get_domain(r->ast->seq->elements[0]);
+      break;
+    }
+  case 8: // MG
+    {
+      const HParseResult *r = h_parse(init_mg(), (const uint8_t*)data, rdata->used);
+      if (!r)
+	rr.type = 0;
+      else
+	rr.mg = get_domain(r->ast->seq->elements[0]);
+      break;
+    }
+  case 9: // MR
+    {
+      const HParseResult *r = h_parse(init_mr(), (const uint8_t*)data, rdata->used);
+      if (!r)
+	rr.type = 0;
+      else
+	rr.mr = get_domain(r->ast->seq->elements[0]);
+      break;
+    }
+  case 10: // NULL
+    {
+      const HParseResult *r = h_parse(init_null(), (const uint8_t*)data, rdata->used);
+      if (!r)
+	rr.type = 0;
+      else {
+	rr.null = h_arena_malloc(rdata->arena, sizeof(uint8_t)*r->ast->seq->used);
+	for (size_t i=0; i<r->ast->seq->used; ++i)
+	  rr.null[i] = r->ast->seq->elements[i]->uint;
+      }
+      break;
+    }
+  case 11: // WKS
+    {
+      const HParseResult *r = h_parse(init_wks(), (const uint8_t*)data, rdata->used);
+      if (!r)
+	rr.type = 0;
+      else {
+	rr.wks.address = r->ast->seq->elements[0]->uint;
+	rr.wks.protocol = r->ast->seq->elements[1]->uint;
+	rr.wks.len = r->ast->seq->elements[2]->seq->used;
+	rr.wks.bit_map = h_arena_malloc(rdata->arena, sizeof(uint8_t)*r->ast->seq->elements[2]->seq->used);
+	for (size_t i=0; i<rr.wks.len; ++i)
+	  rr.wks.bit_map[i] = r->ast->seq->elements[2]->seq->elements[i]->uint;
+      }
+      break;
+    }
+  case 12: // PTR
+    {
+      const HParseResult *r = h_parse(init_ptr(), (const uint8_t*)data, rdata->used);
+      if (!r)
+	rr.type = 0;
+      else
+	rr.ptr = get_domain(r->ast->seq->elements[0]);
+      break;
+    }
+  case 13: // HINFO
+    {
+      const HParseResult *r = h_parse(init_hinfo(), (const uint8_t*)data, rdata->used);
+      if (!r)
+	rr.type = 0;
+      else {
+	rr.hinfo.cpu = get_cs(r->ast->seq->elements[0]);
+	rr.hinfo.os = get_cs(r->ast->seq->elements[1]);
+      }
+      break;
+    }
+  case 14: // MINFO
+    {
+      const HParseResult *r = h_parse(init_minfo(), (const uint8_t*)data, rdata->used);
+      if (!r)
+	rr.type = 0;
+      else {
+	rr.minfo.rmailbx = get_domain(r->ast->seq->elements[0]);
+	rr.minfo.emailbx = get_domain(r->ast->seq->elements[1]);
+      }
+      break;
+    }
+  case 15: // MX
+    {
+      const HParseResult *r = h_parse(init_mx(), (const uint8_t*)data, rdata->used);
+      if (!r)
+	rr.type = 0;
+      else {
+	rr.mx.preference = r->ast->seq->elements[0]->uint;
+	rr.mx.exchange = get_domain(r->ast->seq->elements[1]);
+      }
+      break;
+    }
+  case 16: // TXT
+    {
+      const HParseResult *r = h_parse(init_txt(), (const uint8_t*)data, rdata->used);
+      if (!r)
+	rr.type = 0;
+      else {
+	rr.txt.count = r->ast->seq->elements[0]->seq->used;
+	rr.txt.txt_data = get_txt(r->ast->seq->elements[0]);
+      }
+      break;
+    }
+  default:
+    break;
+  }
 }
 
 const HParsedToken* pack_dns_struct(const HParseResult *p) {
@@ -113,7 +302,7 @@ const HParsedToken* pack_dns_struct(const HParseResult *p) {
   for (size_t i=0; i<header.answer_count; ++i) {
     answers[i].name = get_domain(rrs[i].seq->elements[0]);
     answers[i].type = rrs[i].seq->elements[1]->uint;
-    answers[i].type = rrs[i].seq->elements[2]->uint;
+    answers[i].class = rrs[i].seq->elements[2]->uint;
     answers[i].ttl = rrs[i].seq->elements[3]->uint;
     answers[i].rdlength = rrs[i].seq->elements[4]->seq->used;
     set_rr(answers[i], rrs[i].seq->elements[4]->seq);	   
@@ -125,7 +314,7 @@ const HParsedToken* pack_dns_struct(const HParseResult *p) {
   for (size_t i=0, j=header.answer_count; i<header.authority_count; ++i, ++j) {
     authority[i].name = get_domain(rrs[j].seq->elements[0]);
     authority[i].type = rrs[j].seq->elements[1]->uint;
-    authority[i].type = rrs[j].seq->elements[2]->uint;
+    authority[i].class = rrs[j].seq->elements[2]->uint;
     authority[i].ttl = rrs[j].seq->elements[3]->uint;
     authority[i].rdlength = rrs[j].seq->elements[4]->seq->used;
     set_rr(authority[i], rrs[j].seq->elements[4]->seq);
@@ -137,7 +326,7 @@ const HParsedToken* pack_dns_struct(const HParseResult *p) {
   for (size_t i=0, j=header.answer_count+header.authority_count; i<header.additional_count; ++i, ++j) {
     additional[i].name = get_domain(rrs[j].seq->elements[0]);
     additional[i].type = rrs[j].seq->elements[1]->uint;
-    additional[i].type = rrs[j].seq->elements[2]->uint;
+    additional[i].class = rrs[j].seq->elements[2]->uint;
     additional[i].ttl = rrs[j].seq->elements[3]->uint;
     additional[i].rdlength = rrs[j].seq->elements[4]->seq->used;
     set_rr(additional[i], rrs[j].seq->elements[4]->seq);
diff --git a/examples/dns.h b/examples/dns.h
index 1d36103..151c46e 100644
--- a/examples/dns.h
+++ b/examples/dns.h
@@ -1,4 +1,5 @@
-typedef int bool;
+#include "../src/hammer.h"
+
 struct dns_header {
   uint16_t id;
   bool qr, aa, tc, rd, ra;
@@ -66,7 +67,7 @@ struct dns_rr {
       uint32_t address;
       uint8_t protocol;
       size_t len;
-      uint8_t** bit_map;
+      uint8_t* bit_map;
     } wks;
   };
 };
-- 
GitLab