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