From 4226d67c26cc6afac5a944172ae192861b905fdf Mon Sep 17 00:00:00 2001
From: "Meredith L. Patterson" <clonearmy@gmail.com>
Date: Thu, 24 May 2012 18:44:48 +0200
Subject: [PATCH] DNS, refactored and compiling. Needs struct-building action
 written still.

---
 examples/Makefile     |   8 +-
 examples/dns.c        |  92 +++++-------------
 examples/dns_common.c |  71 ++++++++++++++
 examples/dns_common.h |   9 ++
 examples/rr.c         | 218 ++++++++++++++++++++++++++++++++++++++++++
 examples/rr.h         |  23 +++++
 src/datastructures.c  |   2 +-
 7 files changed, 354 insertions(+), 69 deletions(-)
 create mode 100644 examples/dns_common.c
 create mode 100644 examples/dns_common.h
 create mode 100644 examples/rr.c
 create mode 100644 examples/rr.h

diff --git a/examples/Makefile b/examples/Makefile
index 46f30a05..dc4a0f30 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -10,7 +10,11 @@ include ../common.mk
 all: dns
 
 dns: LDFLAGS:=-L../src -lhammer $(LDFLAGS)
-dns: dns.o
+dns: dns.o rr.o dns_common.o
 	$(call hush, "Linking $@") $(CC) -o $@ $^ $(LDFLAGS)
 
-dns.o: ../src/hammer.h
+dns.o: ../src/hammer.h dns_common.h
+
+rr.o: ../src/hammer.h rr.h dns_common.h
+
+dns_common.o: ../src/hammer.h dns_common.h
\ No newline at end of file
diff --git a/examples/dns.c b/examples/dns.c
index ec8f7128..ce1e9ede 100644
--- a/examples/dns.c
+++ b/examples/dns.c
@@ -1,4 +1,5 @@
 #include "../src/hammer.h"
+#include "dns_common.h"
 
 #define false 0
 #define true 1
@@ -9,15 +10,6 @@ bool is_zero(parse_result_t *p) {
   return (0 == p->ast->uint);
 }
 
-/**
- * A label can't be more than 63 characters.
- */
-bool validate_label(parse_result_t *p) {
-  if (TT_SEQUENCE != p->ast->token_type)
-    return false;
-  return (64 > p->ast->seq->used);
-}
-
 /**
  * Every DNS message should have QDCOUNT entries in the question
  * section, and ANCOUNT+NSCOUNT+ARCOUNT resource records.
@@ -40,25 +32,27 @@ bool validate_dns(parse_result_t *p) {
   return true;
 }
 
-parser_t* init_parser() {
+const parser_t* init_parser() {
   static parser_t *dns_message = NULL;
   if (dns_message)
     return dns_message;
 
+  const parser_t *domain = init_domain();
+
   const parser_t *dns_header = sequence(bits(16, false), // ID
-				       bits(1, false),  // QR
-				       bits(4, false),  // opcode
-				       bits(1, false),  // AA
-				       bits(1, false),  // TC
-				       bits(1, false),  // RD
-				       bits(1, false),  // RA
-				       ignore(attr_bool(bits(3, false), is_zero)), // Z
-				       bits(4, false),  // RCODE
-				       uint16(), // QDCOUNT
-				       uint16(), // ANCOUNT
-				       uint16(), // NSCOUNT
-				       uint16(), // ARCOUNT
-				       NULL);
+					bits(1, false),  // QR
+					bits(4, false),  // opcode
+					bits(1, false),  // AA
+					bits(1, false),  // TC
+					bits(1, false),  // RD
+					bits(1, false),  // RA
+					ignore(attr_bool(bits(3, false), is_zero)), // Z
+					bits(4, false),  // RCODE
+					uint16(), // QDCOUNT
+					uint16(), // ANCOUNT
+					uint16(), // NSCOUNT
+					uint16(), // ARCOUNT
+					NULL);
 
   const parser_t *type = int_range(uint16(), 1, 16);
 
@@ -79,50 +73,12 @@ parser_t* init_parser() {
 					  qtype,           // QTYPE
 					  qclass,          // QCLASS
 					  NULL);
+ 
 
-  const parser_t *letter = choice(ch_range('a', 'z'),
-				  ch_range('A', 'Z'),
-				  NULL);
-
-  const parser_t *let_dig = choice(letter,
-				   ch_range('0', '9'),
-				   NULL);
-
-  const parser_t *ldh_str = many1(choice(let_dig,
-					 ch('-'),
-					 NULL));
-
-  const parser_t *label = attr_bool(sequence(letter,
-					     optional(sequence(optional(ldh_str),
-							       let_dig,
-							       NULL)),
-					     NULL),
-				    validate_label);
-
-  /**
-   * You could write it like this ...
-   *   parser_t *indirect_subdomain = indirect();
-   *   const parser_t *subdomain = choice(label,
-   *				          sequence(indirect_subdomain,
-   *					           ch('.'),
-   *					           label,
-   *					           NULL),
-   *				          NULL);
-   *   bind_indirect(indirect_subdomain, subdomain);
-   *
-   * ... but this is easier and equivalent
-   */
-
-  const parser_t *subdomain = sepBy1(label, ch('.'));
-
-  const parser_t *domain = choice(subdomain, 
-				  ch(' '), 
-				  NULL);
-
-  const parser_t *dns_rr = sequence(domain,                         // NAME
-				    uint16(),                       // TYPE
-				    uint16(),                       // CLASS
-				    uint32(),                       // TTL
+  const parser_t *dns_rr = sequence(domain,                          // NAME
+				    type,                            // TYPE
+				    class,                           // CLASS
+				    uint32(),                        // TTL
 				    length_value(uint16(), uint8()), // RDLENGTH+RDATA
 				    NULL);
 
@@ -136,3 +92,7 @@ parser_t* init_parser() {
 
   return dns_message;
 }
+
+int main(int argc, char** argv) {
+  return 0;
+}
diff --git a/examples/dns_common.c b/examples/dns_common.c
new file mode 100644
index 00000000..a07efdff
--- /dev/null
+++ b/examples/dns_common.c
@@ -0,0 +1,71 @@
+#include "../src/hammer.h"
+#include "dns_common.h"
+
+#define false 0
+#define true 1
+
+/**
+ * A label can't be more than 63 characters.
+ */
+bool validate_label(parse_result_t *p) {
+  if (TT_SEQUENCE != p->ast->token_type)
+    return false;
+  return (64 > p->ast->seq->used);
+}
+
+const parser_t* init_domain() {
+  static const parser_t *domain = NULL;
+  if (domain)
+    return domain;
+
+  const parser_t *letter = choice(ch_range('a', 'z'),
+				  ch_range('A', 'Z'),
+				  NULL);
+
+  const parser_t *let_dig = choice(letter,
+				   ch_range('0', '9'),
+				   NULL);
+
+  const parser_t *ldh_str = many1(choice(let_dig,
+					 ch('-'),
+					 NULL));
+
+  const parser_t *label = attr_bool(sequence(letter,
+					     optional(sequence(optional(ldh_str),
+							       let_dig,
+							       NULL)),
+					     NULL),
+				    validate_label);
+
+  /**
+   * You could write it like this ...
+   *   parser_t *indirect_subdomain = indirect();
+   *   const parser_t *subdomain = choice(label,
+   *				          sequence(indirect_subdomain,
+   *					           ch('.'),
+   *					           label,
+   *					           NULL),
+   *				          NULL);
+   *   bind_indirect(indirect_subdomain, subdomain);
+   *
+   * ... but this is easier and equivalent
+   */
+
+  const parser_t *subdomain = sepBy1(label, ch('.'));
+
+  domain = choice(subdomain, 
+		  ch(' '), 
+		  NULL); 
+
+  return domain;
+}
+
+const parser_t* init_character_string() {
+  static const parser_t *cstr = NULL;
+  if (cstr)
+    return cstr;
+
+  cstr = length_value(uint8(), uint8());
+
+  return cstr;
+}
diff --git a/examples/dns_common.h b/examples/dns_common.h
new file mode 100644
index 00000000..311b5bea
--- /dev/null
+++ b/examples/dns_common.h
@@ -0,0 +1,9 @@
+#ifndef HAMMER_DNS_COMMON__H
+#define HAMMER_DNS_COMMON__H
+
+#include "../src/hammer.h"
+
+const parser_t* init_domain();
+const parser_t* init_character_string();
+
+#endif
diff --git a/examples/rr.c b/examples/rr.c
new file mode 100644
index 00000000..e59f7e09
--- /dev/null
+++ b/examples/rr.c
@@ -0,0 +1,218 @@
+#include "../src/hammer.h"
+#include "dns_common.h"
+#include "rr.h"
+
+#define false 0
+#define true 1
+
+const parser_t* init_cname() {
+  static const parser_t *cname = NULL;
+  if (cname)
+    return cname;
+  
+  cname = sequence(init_domain(),
+		   end_p(),
+		   NULL);
+  
+  return cname;
+}
+
+const parser_t* init_hinfo() {
+  static const parser_t *hinfo = NULL;
+  if (hinfo)
+    return hinfo;
+
+  const parser_t* cstr = init_character_string();
+  
+  hinfo = sequence(cstr,
+		   cstr,
+		   end_p(),
+		   NULL);
+
+  return hinfo;
+}
+
+const parser_t* init_mb() {
+  static const parser_t *mb = NULL;
+  if (mb)
+    return mb;
+  
+  mb = sequence(init_domain(),
+		end_p(),
+		NULL);
+
+  return mb;
+}
+
+const parser_t* init_md() {
+  static const parser_t *md = NULL;
+  if (md)
+    return md;
+  
+  md = sequence(init_domain(),
+		end_p,
+		NULL);
+
+  return md;
+}
+
+const parser_t* init_mf() {
+  static const parser_t *mf = NULL;
+  if (mf)
+    return mf;
+  
+  mf = sequence(init_domain(),
+		end_p(),
+		NULL);
+
+  return mf;
+}
+
+const parser_t* init_mg() {
+  static const parser_t *mg = NULL;
+  if (mg)
+    return mg;
+  
+  mg = sequence(init_domain(),
+		end_p(),
+		NULL);
+
+  return mg;
+}
+
+const parser_t* init_minfo() {
+  static const parser_t *minfo = NULL;
+  if (minfo)
+    return minfo;
+
+  const parser_t* domain = init_domain();
+
+  minfo = sequence(domain,
+		   domain,
+		   end_p(),
+		   NULL);
+
+  return minfo;
+}
+
+const parser_t* init_mr() {
+  static const parser_t *mr = NULL;
+  if (mr)
+    return mr;
+  
+  mr = sequence(init_domain(),
+		end_p(),
+		NULL);
+
+  return mr;
+}
+
+const parser_t* init_mx() {
+  static const parser_t *mx = NULL;
+  if (mx)
+    return mx;
+  
+  mx = sequence(uint16(),
+		init_domain(),
+		end_p(),
+		NULL);
+
+  return mx;
+}
+
+bool validate_null(parse_result_t *p) {
+  if (TT_SEQUENCE != p->ast->token_type)
+    return false;
+  return (65536 > p->ast->seq->used);
+}
+
+const parser_t* init_null() {
+  static const parser_t *null_ = NULL;
+  if (null_)
+    return null_;
+
+  null_ = attr_bool(uint8(), validate_null);
+
+  return null_;
+}
+
+const parser_t* init_ns() {
+  static const parser_t *ns = NULL;
+  if (ns)
+    return ns;
+
+  ns = sequence(init_domain(),
+		end_p(),
+		NULL);
+
+  return ns;
+}
+
+const parser_t* init_ptr() {
+  static const parser_t *ptr = NULL;
+  if (ptr)
+    return ptr;
+  
+  ptr = sequence(init_domain(),
+		end_p(),
+		NULL);
+
+  return ptr;
+}
+
+const parser_t* init_soa() {
+  static const parser_t *soa = NULL;
+  if (soa)
+    return soa;
+
+  const parser_t *domain = init_domain();
+
+  soa = sequence(domain,   // MNAME
+		 domain,   // RNAME
+		 uint32(), // SERIAL
+		 uint32(), // REFRESH
+		 uint32(), // RETRY
+		 uint32(), // EXPIRE
+		 end_p(),
+		 NULL);
+
+  return soa;
+}
+
+const parser_t* init_txt() {
+  static const parser_t *txt = NULL;
+  if (txt)
+    return txt;
+
+  txt = sequence(many1(init_character_string()),
+		 end_p(),
+		 NULL);
+
+  return txt;
+}
+
+const parser_t* init_a() {
+  static const parser_t *a = NULL;
+  if (a)
+    return a;
+
+  a = sequence(uint32(),
+	       end_p(),
+	       NULL);
+
+  return a;
+}
+
+const parser_t* init_wks() {
+  static const parser_t *wks = NULL;
+  if (wks)
+    return wks;
+
+  wks = sequence(uint32(),
+		 uint8(),
+		 many(uint8()),
+		 end_p(),
+		 NULL);
+
+  return wks;
+}
diff --git a/examples/rr.h b/examples/rr.h
new file mode 100644
index 00000000..c0673d88
--- /dev/null
+++ b/examples/rr.h
@@ -0,0 +1,23 @@
+#ifndef HAMMER_DNS_RR__H
+#define HAMMER_DNS_RR__H
+
+#include "../src/hammer.h"
+
+const parser_t* init_cname();
+const parser_t* init_hinfo();
+const parser_t* init_mb();
+const parser_t* init_md();
+const parser_t* init_mf();
+const parser_t* init_mg();
+const parser_t* init_minfo();
+const parser_t* init_mr();
+const parser_t* init_mx();
+const parser_t* init_null();
+const parser_t* init_ns();
+const parser_t* init_ptr();
+const parser_t* init_soa();
+const parser_t* init_txt();
+const parser_t* init_a();
+const parser_t* init_wks();
+
+#endif
diff --git a/src/datastructures.c b/src/datastructures.c
index 7954c434..4b348338 100644
--- a/src/datastructures.c
+++ b/src/datastructures.c
@@ -21,7 +21,7 @@ counted_array_t *carray_new(arena_t arena) {
 
 void carray_append(counted_array_t *array, void* item) {
   if (array->used >= array->capacity) {
-    void **elements = arena_malloc(array->arena, (array->capacity *= 2) * sizeof(counted_array_t*));
+    parsed_token_t **elements = arena_malloc(array->arena, (array->capacity *= 2) * sizeof(counted_array_t*));
     for (size_t i = 0; i < array->used; i++)
       elements[i] = array->elements[i];
     for (size_t i = array->used; i < array->capacity; i++)
-- 
GitLab