From 21df49cc151b8cd17db866e9d4cf843ef194f316 Mon Sep 17 00:00:00 2001
From: "Sven M. Hallberg" <pesco@khjk.org>
Date: Tue, 15 Jan 2013 01:24:47 +0100
Subject: [PATCH] split out act_header

---
 examples/dns.c | 77 +++++++++++++++++++++++++++++---------------------
 examples/dns.h | 14 ++++-----
 src/pprint.c   |  6 +++-
 3 files changed, 57 insertions(+), 40 deletions(-)

diff --git a/examples/dns.c b/examples/dns.c
index 08e42880..5c59626d 100644
--- a/examples/dns.c
+++ b/examples/dns.c
@@ -2,6 +2,7 @@
 #include <netinet/in.h>
 #include <err.h>
 #include <string.h>
+#include <assert.h>
 #include "../src/hammer.h"
 #include "dns_common.h"
 #include "dns.h"
@@ -27,12 +28,12 @@ bool is_zero(HParseResult *p) {
 bool validate_dns(HParseResult *p) {
   if (TT_SEQUENCE != p->ast->token_type)
     return false;
-  // The header holds the counts as its last 4 elements.
-  HParsedToken **elems = p->ast->seq->elements[0]->seq->elements;
-  size_t qd = elems[8]->uint;
-  size_t an = elems[9]->uint;
-  size_t ns = elems[10]->uint;
-  size_t ar = elems[11]->uint;
+  assert(p->ast->seq->elements[0]->token_type == (HTokenType)TT_dns_header);
+  dns_header_t *header = (dns_header_t *)p->ast->seq->elements[0]->user;
+  size_t qd = header->question_count;
+  size_t an = header->answer_count;
+  size_t ns = header->authority_count;
+  size_t ar = header->additional_count;
   HParsedToken *questions = p->ast->seq->elements[1];
   if (questions->seq->used != qd)
     return false;
@@ -287,34 +288,46 @@ void set_rr(struct dns_rr rr, HCountedArray *rdata) {
   }
 }
 
+const HParsedToken* act_header(const HParseResult *p) {
+  HParsedToken *ret = h_arena_malloc(p->arena, sizeof(HParsedToken));
+  ret->token_type = TT_dns_header;
+  ret->user = h_arena_malloc(p->arena, sizeof(dns_header_t));
+
+  HParsedToken **fields = p->ast->seq->elements;
+  dns_header_t header_ = {
+    .id     = fields[0]->uint,
+    .qr     = fields[1]->uint,
+    .opcode = fields[2]->uint,
+    .aa     = fields[3]->uint,
+    .tc     = fields[4]->uint,
+    .rd     = fields[5]->uint,
+    .ra     = fields[6]->uint,
+    .rcode  = fields[7]->uint,
+    .question_count   = fields[8]->uint,
+    .answer_count     = fields[9]->uint,
+    .authority_count  = fields[10]->uint,
+    .additional_count = fields[11]->uint
+  };
+  *(dns_header_t *)ret->user = header_;
+
+  return ret;
+}
+
 const HParsedToken* act_message(const HParseResult *p) {
   h_pprint(stdout, p->ast, 0, 2);
   HParsedToken *ret = h_arena_malloc(p->arena, sizeof(HParsedToken));
-  ret->token_type = TT_DNS_MESSAGE;
+  ret->token_type = TT_dns_message;
 
   dns_message_t *msg = h_arena_malloc(p->arena, sizeof(dns_message_t));
 
-  HParsedToken *hdr = p->ast->seq->elements[0];
-  struct dns_header header = {
-    .id = hdr->seq->elements[0]->uint,
-    .qr = hdr->seq->elements[1]->uint,
-    .opcode = hdr->seq->elements[2]->uint,
-    .aa = hdr->seq->elements[3]->uint,
-    .tc = hdr->seq->elements[4]->uint,
-    .rd = hdr->seq->elements[5]->uint,
-    .ra = hdr->seq->elements[6]->uint,
-    .rcode = hdr->seq->elements[7]->uint,
-    .question_count = hdr->seq->elements[8]->uint,
-    .answer_count = hdr->seq->elements[9]->uint,
-    .authority_count = hdr->seq->elements[10]->uint,
-    .additional_count = hdr->seq->elements[11]->uint
-  };
-  msg->header = header;
+  assert(p->ast->seq->elements[0]->token_type == (HTokenType)TT_dns_header);
+  dns_header_t *header = (dns_header_t *)p->ast->seq->elements[0]->user;
+  msg->header = *header;
 
   HParsedToken *qs = p->ast->seq->elements[1];
   struct dns_question *questions = h_arena_malloc(p->arena,
-						sizeof(struct dns_question)*(header.question_count));
-  for (size_t i=0; i<header.question_count; ++i) {
+						sizeof(struct dns_question)*(header->question_count));
+  for (size_t i=0; i<header->question_count; ++i) {
     // QNAME is a sequence of labels. In the parser, it's defined as
     // sequence(many1(length_value(...)), ch('\x00'), NULL).
     questions[i].qname = get_qname(qs->seq->elements[i]->seq->elements[0]);
@@ -325,8 +338,8 @@ const HParsedToken* act_message(const HParseResult *p) {
 
   HParsedToken *rrs = p->ast->seq->elements[2];
   struct dns_rr *answers = h_arena_malloc(p->arena,
-					  sizeof(struct dns_rr)*(header.answer_count));
-  for (size_t i=0; i<header.answer_count; ++i) {
+					  sizeof(struct dns_rr)*(header->answer_count));
+  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].class = rrs[i].seq->elements[2]->uint;
@@ -337,8 +350,8 @@ const HParsedToken* act_message(const HParseResult *p) {
   msg->answers = answers;
 
   struct dns_rr *authority = h_arena_malloc(p->arena,
-					  sizeof(struct dns_rr)*(header.authority_count));
-  for (size_t i=0, j=header.answer_count; i<header.authority_count; ++i, ++j) {
+					  sizeof(struct dns_rr)*(header->authority_count));
+  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].class = rrs[j].seq->elements[2]->uint;
@@ -349,8 +362,8 @@ const HParsedToken* act_message(const HParseResult *p) {
   msg->authority = authority;
 
   struct dns_rr *additional = h_arena_malloc(p->arena,
-					     sizeof(struct dns_rr)*(header.additional_count));
-  for (size_t i=0, j=header.answer_count+header.authority_count; i<header.additional_count; ++i, ++j) {
+					     sizeof(struct dns_rr)*(header->additional_count));
+  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].class = rrs[j].seq->elements[2]->uint;
@@ -379,7 +392,7 @@ const HParser* init_parser() {
 
   H_RULE (domain,   init_domain());
   H_ARULE(hdzero,   h_attr_bool(h_bits(3, false), is_zero));
-  H_RULE (header,   h_sequence(h_bits(16, false), // ID
+  H_ARULE(header,   h_sequence(h_bits(16, false), // ID
 			       h_bits(1, false),  // QR
 			       h_bits(4, false),  // opcode
 			       h_bits(1, false),  // AA
diff --git a/examples/dns.h b/examples/dns.h
index a26374e4..6f9fb132 100644
--- a/examples/dns.h
+++ b/examples/dns.h
@@ -1,14 +1,14 @@
 #include "../src/hammer.h"
 
 enum DNSTokenType_ {
-  TT_DNS_MESSAGE = TT_USER,
-  TT_DNS_HEADER,
-  TT_DNS_QNAME,
-  TT_DNS_QUESTION,
-  TT_DNS_RR
+  TT_dns_message = TT_USER,
+  TT_dns_header,
+  TT_dns_qname,
+  TT_dns_question,
+  TT_dns_rr
 };
 
-struct dns_header {
+typedef struct dns_header {
   uint16_t id;
   bool qr, aa, tc, rd, ra;
   char opcode, rcode;
@@ -16,7 +16,7 @@ struct dns_header {
   size_t answer_count;
   size_t authority_count;
   size_t additional_count;
-};
+} dns_header_t;
 
 struct dns_qname {
   size_t qlen;
diff --git a/src/pprint.c b/src/pprint.c
index 1ffe7643..d8b22e2d 100644
--- a/src/pprint.c
+++ b/src/pprint.c
@@ -69,7 +69,11 @@ void h_pprint(FILE* stream, const HParsedToken* tok, int indent, int delta) {
     fprintf(stream, "%*sUSER\n", indent, "");
     break;
   default:
-    assert_message(0, "Should not reach here.");
+    if(tok->token_type > TT_USER) {
+      fprintf(stream, "%*sUSER %d\n", indent, "", tok->token_type-TT_USER);
+    } else {
+      assert_message(0, "Should not reach here.");
+    }
   }
 }
 
-- 
GitLab