start pulling pack_dns_struct apart

This commit is contained in:
Sven M. Hallberg 2013-01-15 13:54:30 +01:00
parent 21df49cc15
commit acfc903a15
2 changed files with 88 additions and 47 deletions

View file

@ -43,27 +43,6 @@ bool validate_dns(HParseResult *p) {
return true; return true;
} }
struct dns_qname get_qname(const HParsedToken *t) {
// The qname parser parses at least 1 length-value pair, then a NULL.
// So, t->seq->elements[0] is a sequence of at least 1 such pair,
// and t->seq->elements[1] is the null.
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)*labels->seq->used)
};
// i is which label we're on
for (size_t i=0; i<labels->seq->used; ++i) {
ret.labels[i].len = labels->seq->elements[i]->seq->used;
ret.labels[i].label = h_arena_malloc(t->seq->arena, ret.labels[i].len + 1);
// j is which char of the label we're on
for (size_t j=0; j<ret.labels[i].len; ++j)
ret.labels[i].label[j] = labels->seq->elements[i]->seq->elements[j]->uint;
ret.labels[i].label[ret.labels[i].len] = 0;
}
return ret;
}
char* get_domain(const HParsedToken *t) { char* get_domain(const HParsedToken *t) {
switch(t->token_type) { switch(t->token_type) {
case TT_UINT: case TT_UINT:
@ -313,6 +292,43 @@ const HParsedToken* act_header(const HParseResult *p) {
return ret; return ret;
} }
const HParsedToken* act_label(const HParseResult *p) {
HParsedToken *ret = h_arena_malloc(p->arena, sizeof(HParsedToken));
ret->token_type = TT_dns_label;
ret->user = h_arena_malloc(p->arena, sizeof(dns_label_t));
dns_label_t *r = (dns_label_t *)ret->user;
r->len = p->ast->seq->used;
r->label = h_arena_malloc(p->arena, r->len + 1);
for (size_t i=0; i<r->len; ++i)
r->label[i] = p->ast->seq->elements[i]->uint;
r->label[r->len] = 0;
return ret;
}
const HParsedToken* act_question(const HParseResult *p) {
HParsedToken *ret = h_arena_malloc(p->arena, sizeof(HParsedToken));
ret->token_type = TT_dns_question;
ret->user = h_arena_malloc(p->arena, sizeof(dns_question_t));
dns_question_t *q = (dns_question_t *)ret->user;
HParsedToken **fields = p->ast->seq->elements;
// QNAME is a sequence of labels. Pack them into an array.
q->qname.qlen = fields[0]->seq->used;
q->qname.labels = h_arena_malloc(p->arena, sizeof(dns_label_t)*q->qname.qlen);
for(size_t i=0; i<fields[0]->seq->used; i++) {
assert(fields[0]->seq->elements[i]->token_type == (HTokenType)TT_dns_label);
q->qname.labels[i] = *(dns_label_t *)fields[0]->seq->elements[i]->user;
}
q->qtype = fields[1]->uint;
q->qclass = fields[2]->uint;
return ret;
}
const HParsedToken* act_message(const HParseResult *p) { const HParsedToken* act_message(const HParseResult *p) {
h_pprint(stdout, p->ast, 0, 2); h_pprint(stdout, p->ast, 0, 2);
HParsedToken *ret = h_arena_malloc(p->arena, sizeof(HParsedToken)); HParsedToken *ret = h_arena_malloc(p->arena, sizeof(HParsedToken));
@ -328,11 +344,8 @@ const HParsedToken* act_message(const HParseResult *p) {
struct dns_question *questions = h_arena_malloc(p->arena, struct dns_question *questions = h_arena_malloc(p->arena,
sizeof(struct dns_question)*(header->question_count)); sizeof(struct dns_question)*(header->question_count));
for (size_t i=0; i<header->question_count; ++i) { for (size_t i=0; i<header->question_count; ++i) {
// QNAME is a sequence of labels. In the parser, it's defined as assert(qs->seq->elements[i]->token_type == (HTokenType)TT_dns_question);
// sequence(many1(length_value(...)), ch('\x00'), NULL). questions[i] = *(dns_question_t *)qs->seq->elements[i]->user;
questions[i].qname = get_qname(qs->seq->elements[i]->seq->elements[0]);
questions[i].qtype = qs->seq->elements[i]->seq->elements[1]->uint;
questions[i].qclass = qs->seq->elements[i]->seq->elements[2]->uint;
} }
msg->questions = questions; msg->questions = questions;
@ -383,7 +396,32 @@ const HParsedToken *act_ignore(const HParseResult *p)
return NULL; return NULL;
} }
// Helper to build HAction's that pick one index out of a sequence.
const HParsedToken *act_index(int i, const HParseResult *p)
{
if(!p) return NULL;
const HParsedToken *tok = p->ast;
if(!tok || tok->token_type != TT_SEQUENCE)
return NULL;
const HCountedArray *seq = tok->seq;
size_t n = seq->used;
if(i<0 || (size_t)i>=n)
return NULL;
else
return tok->seq->elements[i];
}
const HParsedToken *act_index0(const HParseResult *p)
{
return act_index(0, p);
}
#define act_hdzero act_ignore #define act_hdzero act_ignore
#define act_qname act_index0
const HParser* init_parser() { const HParser* init_parser() {
static const HParser *ret = NULL; static const HParser *ret = NULL;
@ -415,11 +453,11 @@ const HParser* init_parser() {
h_int_range(h_uint16(), 255, 255), h_int_range(h_uint16(), 255, 255),
NULL)); NULL));
H_RULE (len, h_int_range(h_uint8(), 1, 255)); H_RULE (len, h_int_range(h_uint8(), 1, 255));
H_RULE (label, h_length_value(len, h_uint8())); H_ARULE(label, h_length_value(len, h_uint8()));
H_RULE (qname, h_sequence(h_many1(label), H_ARULE(qname, h_sequence(h_many1(label),
h_ch('\x00'), h_ch('\x00'),
NULL)); NULL));
H_RULE (question, h_sequence(qname, qtype, qclass, NULL)); H_ARULE(question, h_sequence(qname, qtype, qclass, NULL));
H_RULE (rdata, h_length_value(h_uint16(), h_uint8())); H_RULE (rdata, h_length_value(h_uint16(), h_uint8()));
H_RULE (rr, h_sequence(domain, // NAME H_RULE (rr, h_sequence(domain, // NAME
type, // TYPE type, // TYPE

View file

@ -3,6 +3,7 @@
enum DNSTokenType_ { enum DNSTokenType_ {
TT_dns_message = TT_USER, TT_dns_message = TT_USER,
TT_dns_header, TT_dns_header,
TT_dns_label,
TT_dns_qname, TT_dns_qname,
TT_dns_question, TT_dns_question,
TT_dns_rr TT_dns_rr
@ -18,21 +19,23 @@ typedef struct dns_header {
size_t additional_count; size_t additional_count;
} dns_header_t; } dns_header_t;
struct dns_qname { typedef struct dns_label {
size_t qlen;
struct {
size_t len; size_t len;
uint8_t *label; uint8_t *label;
} *labels; } dns_label_t;
};
struct dns_question { typedef struct dns_qname {
struct dns_qname qname; size_t qlen;
dns_label_t *labels;
} dns_qname_t;
typedef struct dns_question {
dns_qname_t qname;
uint16_t qtype; uint16_t qtype;
uint16_t qclass; uint16_t qclass;
}; } dns_question_t;
struct dns_rr { typedef struct dns_rr {
char* name; char* name;
uint16_t type; uint16_t type;
uint16_t class; uint16_t class;
@ -81,12 +84,12 @@ struct dns_rr {
uint8_t* bit_map; uint8_t* bit_map;
} wks; } wks;
}; };
}; } dns_rr_t;
typedef struct dns_message { typedef struct dns_message {
struct dns_header header; dns_header_t header;
struct dns_question *questions; dns_question_t *questions;
struct dns_rr *answers; dns_rr_t *answers;
struct dns_rr *authority; dns_rr_t *authority;
struct dns_rr *additional; dns_rr_t *additional;
} dns_message_t; } dns_message_t;