From d68838693666ba930ec4143f848c18bff2bfc244 Mon Sep 17 00:00:00 2001 From: Michael Graff Date: Wed, 28 Apr 1999 03:19:58 +0000 Subject: [PATCH] checkpoint --- lib/dns/include/dns/message.h | 9 +- lib/dns/message.c | 326 ++++++++++++++++++++++++++++++++-- 2 files changed, 324 insertions(+), 11 deletions(-) diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index e848d97ef4..606153e227 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -66,6 +66,8 @@ ISC_LANG_BEGINDECLS #define DNS_MESSAGE_OPCODE_SHIFT 11 #define DNS_MESSAGE_RCODE_MASK 0x000fU +#define DNS_MESSAGE_HEADER_LEN 12 /* 6 u_int16_t's */ + /* * Ordering here matters. DNS_SECTION_ANY must be the lowest and negative, * and DNS_SECTION_MAX must be one greater than the last used section. @@ -115,7 +117,12 @@ typedef struct { ISC_LIST(isc_dynbuffer_t) scratchpad; ISC_LIST(dns_msgblock_t) names; ISC_LIST(dns_msgblock_t) rdatas; + ISC_LIST(dns_msgblock_t) rdatasets; ISC_LIST(dns_msgblock_t) rdatalists; + dns_name_t *nextname; + dns_rdata_t *nextrdata; + dns_rdataset_t *nextrdataset; + dns_rdatalist_t *nextrdatalist; } dns_message_t; dns_result_t @@ -175,7 +182,7 @@ dns_message_destroy(dns_message_t **msg); */ dns_result_t -dns_message_parse(dns_message_t *msg, void *buffer, size_t buflen); +dns_message_parse(dns_message_t *msg, isc_buffer_t *source); /* * Parse raw wire data pointed to by "buffer" and bounded by "buflen" as a * DNS message. diff --git a/lib/dns/message.c b/lib/dns/message.c index 58a5ff1980..cbdbaf314e 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -51,7 +51,8 @@ #define SCRATCHPAD_SIZE 768 #define NAME_COUNT 16 #define RDATA_COUNT 32 -#define RDATALIST_COUNT 32 +#define RDATALIST_COUNT 32 /* should match RDATASET_COUNT */ +#define RDATASET_COUNT 32 /* * internal state stuff. @@ -74,7 +75,7 @@ struct dns_msgblock { static inline void msgblock_free(isc_mem_t *, dns_msgblock_t *); #define msgblock_get(block, type) \ - (((type) *)msgblock_internalget(block, sizeof(type))) + ((type *)msgblock_internalget(block, sizeof(type))) static inline void * msgblock_internalget(dns_msgblock_t *, unsigned int); @@ -146,6 +147,174 @@ msgblock_free(isc_mem_t *mctx, dns_msgblock_t *block) isc_mem_put(mctx, block, block->length); } +/* + * Allocate a new dynamic buffer, and attach it to this message as the + * "current" buffer. (which is always the last on the list, for our + * uses) + */ +static inline dns_result_t +newbuffer(dns_message_t *msg) +{ + isc_result_t result; + isc_dynbuffer_t *dynbuf; + + dynbuf = NULL; + result = isc_dynbuffer_allocate(msg->mctx, &dynbuf, SCRATCHPAD_SIZE, + ISC_BUFFERTYPE_BINARY); + if (result != ISC_R_SUCCESS) + return (DNS_R_NOMEMORY); + + ISC_LIST_APPEND(msg->scratchpad, dynbuf, link); + return (DNS_R_SUCCESS); +} + +static inline isc_buffer_t * +currentbuffer(dns_message_t *msg) +{ + isc_dynbuffer_t *dynbuf; + + dynbuf = ISC_LIST_TAIL(msg->scratchpad); + + return (&dynbuf->buffer); +} + +static inline void +releasename(dns_message_t *msg, dns_name_t *name) +{ + msg->nextname = name; +} + +static inline dns_name_t * +newname(dns_message_t *msg) +{ + dns_msgblock_t *msgblock; + dns_name_t *name; + + if (msg->nextname != NULL) { + name = msg->nextname; + msg->nextname = NULL; + return (name); + } + + msgblock = ISC_LIST_HEAD(msg->names); + name = msgblock_get(msgblock, dns_name_t); + if (name == NULL) { + msgblock = msgblock_allocate(msg->mctx, sizeof(dns_name_t), + NAME_COUNT); + if (msgblock == NULL) + return (NULL); + + ISC_LIST_APPEND(msg->names, msgblock, link); + + name = msgblock_get(msgblock, dns_name_t); + } + + return (name); +} + +static inline void +releaserdata(dns_message_t *msg, dns_rdata_t *rdata) +{ + msg->nextrdata = rdata; +} + +static inline dns_rdata_t * +newrdata(dns_message_t *msg) +{ + dns_msgblock_t *msgblock; + dns_rdata_t *rdata; + + if (msg->nextrdata != NULL) { + rdata = msg->nextrdata; + msg->nextrdata = NULL; + return (rdata); + } + + msgblock = ISC_LIST_HEAD(msg->rdatas); + rdata = msgblock_get(msgblock, dns_rdata_t); + if (rdata == NULL) { + msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdata_t), + RDATA_COUNT); + if (msgblock == NULL) + return (NULL); + + ISC_LIST_APPEND(msg->rdatas, msgblock, link); + + rdata = msgblock_get(msgblock, dns_rdata_t); + } + + return (rdata); +} + +static inline void +releaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist) +{ + msg->nextrdatalist = rdatalist; +} + +static inline dns_rdatalist_t * +newrdatalist(dns_message_t *msg) +{ + dns_msgblock_t *msgblock; + dns_rdatalist_t *rdatalist; + + if (msg->nextrdatalist != NULL) { + rdatalist = msg->nextrdatalist; + msg->nextrdatalist = NULL; + return (rdatalist); + } + + msgblock = ISC_LIST_HEAD(msg->rdatalists); + rdatalist = msgblock_get(msgblock, dns_rdatalist_t); + if (rdatalist == NULL) { + msgblock = msgblock_allocate(msg->mctx, + sizeof(dns_rdatalist_t), + RDATALIST_COUNT); + if (msgblock == NULL) + return (NULL); + + ISC_LIST_APPEND(msg->rdatalists, msgblock, link); + + rdatalist = msgblock_get(msgblock, dns_rdatalist_t); + } + + return (rdatalist); +} + +static inline void +releaserdataset(dns_message_t *msg, dns_rdataset_t *rdataset) +{ + msg->nextrdataset = rdataset; +} + +static inline dns_rdataset_t * +newrdataset(dns_message_t *msg) +{ + dns_msgblock_t *msgblock; + dns_rdataset_t *rdataset; + + if (msg->nextrdataset != NULL) { + rdataset = msg->nextrdataset; + msg->nextrdataset = NULL; + return (rdataset); + } + + msgblock = ISC_LIST_HEAD(msg->rdatasets); + rdataset = msgblock_get(msgblock, dns_rdataset_t); + if (rdataset == NULL) { + msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdataset_t), + RDATASET_COUNT); + if (msgblock == NULL) + return (NULL); + + ISC_LIST_APPEND(msg->rdatasets, msgblock, link); + + rdataset = msgblock_get(msgblock, dns_rdataset_t); + } + + return (rdataset); +} + /* * Init elements to default state. Used both when allocating a new element * and when resetting one. @@ -153,6 +322,8 @@ msgblock_free(isc_mem_t *mctx, dns_msgblock_t *block) static inline void msginit(dns_message_t *m) { + unsigned int i; + m->id = 0; m->flags = 0; m->rcode = 0; @@ -162,7 +333,16 @@ msginit(dns_message_t *m) m->ancount = 0; m->aucount = 0; m->adcount = 0; + + for (i = 0 ; i < DNS_SECTION_MAX ; i++) + m->cursors[i] = NULL; + m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */ + + m->nextname = NULL; + m->nextrdata = NULL; + m->nextrdataset = NULL; + m->nextrdatalist = NULL; } /* @@ -241,6 +421,19 @@ msgreset(dns_message_t *msg, isc_boolean_t everything) msgblock = next_msgblock; } + msgblock = ISC_LIST_HEAD(msg->rdatasets); + INSIST(msgblock != NULL); + if (everything == ISC_FALSE) { + msgblock_reset(msgblock, RDATASET_COUNT); + msgblock = ISC_LIST_NEXT(msgblock, link); + } + while (msgblock != NULL) { + next_msgblock = ISC_LIST_NEXT(msgblock, link); + ISC_LIST_UNLINK(msg->rdatasets, msgblock, link); + msgblock_free(msg->mctx, msgblock); + msgblock = next_msgblock; + } + if (msg->from_to_wire == DNS_MESSAGE_INTENT_PARSE) { msgblock = ISC_LIST_HEAD(msg->rdatalists); INSIST(msgblock != NULL); @@ -311,11 +504,17 @@ dns_message_create(isc_mem_t *mctx, dns_message_t **msg, unsigned int intent) goto cleanup3; ISC_LIST_APPEND(m->rdatas, msgblock, link); + msgblock = msgblock_allocate(mctx, sizeof(dns_rdataset_t), + RDATASET_COUNT); + if (msgblock == NULL) + goto cleanup4; + ISC_LIST_APPEND(m->rdatas, msgblock, link); + if (intent == DNS_MESSAGE_INTENT_PARSE) { msgblock = msgblock_allocate(mctx, sizeof(dns_rdatalist_t), RDATALIST_COUNT); if (msgblock == NULL) - goto cleanup4; + goto cleanup5; ISC_LIST_APPEND(m->rdatalists, msgblock, link); } @@ -324,6 +523,9 @@ dns_message_create(isc_mem_t *mctx, dns_message_t **msg, unsigned int intent) /* * Cleanup for error returns. */ + cleanup5: + msgblock = ISC_LIST_HEAD(m->rdatasets); + msgblock_free(mctx, msgblock); cleanup4: msgblock = ISC_LIST_HEAD(m->rdatas); msgblock_free(mctx, msgblock); @@ -362,16 +564,120 @@ dns_message_destroy(dns_message_t **xmsg) isc_mem_put(msg->mctx, msg, sizeof(dns_message_t)); } -dns_result_t -dns_message_parse(dns_message_t *msg, void *buffer, size_t buflen) +static dns_result_t +getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx) +{ + isc_region_t r; + unsigned int count; + dns_name_t *name; + dns_name_t *name2; + dns_rdataset_t *rdataset; + dns_rdatalist_t *rdatalist; + dns_result_t result; + + count = msg->qcount; + + while (count > 0) { + name = newname(msg); + if (name == NULL) + return (DNS_R_NOMEMORY); + + /* + * Parse the name out of this packet. + */ + result = getname(name, source, msg, dctx); + if (result != DNS_R_SUCCESS) + return (result); + + /* + * Run through the section, looking to see if this name + * is already there. If it is found, put back the allocated + * name since we no longer need it, and set our name pointer + * to point to the name we found. + */ + result = findname(); /* XXX stop point */ + + /* + * If it is a new name, append to the section. + */ + + /* + * Get type and class. + */ + + /* + * Search name for the particular type and class. + */ + + /* + * If it was found, this is an error, return FORMERR. + */ + + /* + * Allocate a new rdatalist. + */ + + /* + * Convert rdatalist to rdataset, and attach the latter to + * the name. + */ + } + + return (DNS_R_SUCCESS); +} + +static dns_result_t +getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + dns_section_t section) { - REQUIRE(VALID_MESSAGE(msg)); - REQUIRE(buffer != NULL); - REQUIRE(buflen > 0); /* XXXMLG Should be >= header length... */ + return (DNS_R_UNEXPECTED); +} - /* XXX implement */ - return (ISC_R_NOTIMPLEMENTED); +dns_result_t +dns_message_parse(dns_message_t *msg, isc_buffer_t *source) +{ + isc_region_t r; + dns_decompress_t dctx; + dns_result_t ret; + + REQUIRE(VALID_MESSAGE(msg)); + REQUIRE(source != NULL); + + isc_buffer_remaining(source, &r); + if (r.length >= DNS_MESSAGE_HEADER_LEN) + return (DNS_R_UNEXPECTEDEND); + + msg->id = isc_buffer_getuint16(source); + msg->flags = isc_buffer_getuint16(source); + msg->qcount = isc_buffer_getuint16(source); + msg->ancount = isc_buffer_getuint16(source); + msg->aucount = isc_buffer_getuint16(source); + msg->adcount = isc_buffer_getuint16(source); + + dns_decompress_init(&dctx, -1, ISC_FALSE); + + ret = getquestions(source, msg, &dctx); + if (ret != DNS_R_SUCCESS) + return (ret); + + ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER); + if (ret != DNS_R_SUCCESS) + return (ret); + + ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY); + if (ret != DNS_R_SUCCESS) + return (ret); + + ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL); + if (ret != DNS_R_SUCCESS) + return (ret); + + /* + * XXXMLG Need to check the tsig(s) here... + */ + + return (DNS_R_SUCCESS); } dns_result_t