DNS, refactored and compiling. Needs struct-building action written still.

This commit is contained in:
Meredith L. Patterson 2012-05-24 18:44:48 +02:00
parent 40be28fb7e
commit 4226d67c26
7 changed files with 354 additions and 69 deletions

View file

@ -10,7 +10,11 @@ include ../common.mk
all: dns all: dns
dns: LDFLAGS:=-L../src -lhammer $(LDFLAGS) dns: LDFLAGS:=-L../src -lhammer $(LDFLAGS)
dns: dns.o dns: dns.o rr.o dns_common.o
$(call hush, "Linking $@") $(CC) -o $@ $^ $(LDFLAGS) $(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

View file

@ -1,4 +1,5 @@
#include "../src/hammer.h" #include "../src/hammer.h"
#include "dns_common.h"
#define false 0 #define false 0
#define true 1 #define true 1
@ -9,15 +10,6 @@ bool is_zero(parse_result_t *p) {
return (0 == p->ast->uint); 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 * Every DNS message should have QDCOUNT entries in the question
* section, and ANCOUNT+NSCOUNT+ARCOUNT resource records. * section, and ANCOUNT+NSCOUNT+ARCOUNT resource records.
@ -40,25 +32,27 @@ bool validate_dns(parse_result_t *p) {
return true; return true;
} }
parser_t* init_parser() { const parser_t* init_parser() {
static parser_t *dns_message = NULL; static parser_t *dns_message = NULL;
if (dns_message) if (dns_message)
return dns_message; return dns_message;
const parser_t *domain = init_domain();
const parser_t *dns_header = sequence(bits(16, false), // ID const parser_t *dns_header = sequence(bits(16, false), // ID
bits(1, false), // QR bits(1, false), // QR
bits(4, false), // opcode bits(4, false), // opcode
bits(1, false), // AA bits(1, false), // AA
bits(1, false), // TC bits(1, false), // TC
bits(1, false), // RD bits(1, false), // RD
bits(1, false), // RA bits(1, false), // RA
ignore(attr_bool(bits(3, false), is_zero)), // Z ignore(attr_bool(bits(3, false), is_zero)), // Z
bits(4, false), // RCODE bits(4, false), // RCODE
uint16(), // QDCOUNT uint16(), // QDCOUNT
uint16(), // ANCOUNT uint16(), // ANCOUNT
uint16(), // NSCOUNT uint16(), // NSCOUNT
uint16(), // ARCOUNT uint16(), // ARCOUNT
NULL); NULL);
const parser_t *type = int_range(uint16(), 1, 16); const parser_t *type = int_range(uint16(), 1, 16);
@ -79,50 +73,12 @@ parser_t* init_parser() {
qtype, // QTYPE qtype, // QTYPE
qclass, // QCLASS qclass, // QCLASS
NULL); NULL);
const parser_t *letter = choice(ch_range('a', 'z'), const parser_t *dns_rr = sequence(domain, // NAME
ch_range('A', 'Z'), type, // TYPE
NULL); class, // CLASS
uint32(), // TTL
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
length_value(uint16(), uint8()), // RDLENGTH+RDATA length_value(uint16(), uint8()), // RDLENGTH+RDATA
NULL); NULL);
@ -136,3 +92,7 @@ parser_t* init_parser() {
return dns_message; return dns_message;
} }
int main(int argc, char** argv) {
return 0;
}

71
examples/dns_common.c Normal file
View file

@ -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;
}

9
examples/dns_common.h Normal file
View file

@ -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

218
examples/rr.c Normal file
View file

@ -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;
}

23
examples/rr.h Normal file
View file

@ -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

View file

@ -21,7 +21,7 @@ counted_array_t *carray_new(arena_t arena) {
void carray_append(counted_array_t *array, void* item) { void carray_append(counted_array_t *array, void* item) {
if (array->used >= array->capacity) { 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++) for (size_t i = 0; i < array->used; i++)
elements[i] = array->elements[i]; elements[i] = array->elements[i];
for (size_t i = array->used; i < array->capacity; i++) for (size_t i = array->used; i < array->capacity; i++)