diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in index b5e36ce34b733fbddc3034099c7015516d1410f7..ccf84b729d62b11fa40100f22237d2b9afe47132 100644 --- a/bin/named/Makefile.in +++ b/bin/named/Makefile.in @@ -37,7 +37,7 @@ LIBS = ${DEPLIBS} \ TARGETS = named -OBJS = server.o udpclient.o tcpclient.o wire_debug.o wire_test.o\ +OBJS = server.o udpclient.o tcpclient.o wire_test.o \ zone.o configctx.o confparser.o @BIND9_MAKE_RULES@ diff --git a/bin/named/server.c b/bin/named/server.c index f4085c492f8ef04c76fdb09304156d0b4bb68cbb..bd2ef3675b2bf81c32b6b50f9ac837849e567d84 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -55,10 +56,16 @@ isc_mem_t *mctx = NULL; isc_boolean_t want_stats = ISC_FALSE; dns_db_t *db; -/* - * For debugging only... XXX - */ -void dump_packet(unsigned char *buf, u_int len); +static inline isc_boolean_t +CHECKRESULT(dns_result_t result, char *msg) +{ + if ((result) != DNS_R_SUCCESS) { + printf("%s: %s\n", (msg), dns_result_totext(result)); + return (ISC_TRUE); + } + + return (ISC_FALSE); +} static void makename(isc_mem_t *mctx, char *text, dns_name_t *name, dns_name_t *origin) { @@ -86,10 +93,33 @@ makename(isc_mem_t *mctx, char *text, dns_name_t *name, dns_name_t *origin) { } /* - * XXX This will be in a .h file soon... + * This is in bin/tests/wire_test.c, but should be in a debugging library. */ +extern dns_result_t +printmessage(dns_message_t *); + +dns_result_t +resolve_packet(isc_mem_t *mctx, dns_db_t *, dns_message_t *, + dns_message_t **, isc_buffer_t *); + dns_result_t -resolve_packet(dns_db_t *db, isc_buffer_t *source, isc_buffer_t *target); +resolve_packet(isc_mem_t *mctx, dns_db_t *db, dns_message_t *query, + dns_message_t **reply, isc_buffer_t *target) +{ + dns_message_t *message; + dns_result_t result; + + result = dns_message_create(mctx, &message, DNS_MESSAGE_INTENT_RENDER); + CHECKRESULT(result, "dns_message_create failed"); + + message->id = query->id; + message->rcode = + + result = printmessage(message); + CHECKRESULT(result, "printmessage() failed"); + + return (DNS_R_NOSPACE); +} /* * Process the wire format message given in r, and return a new packet to @@ -103,19 +133,12 @@ resolve_packet(dns_db_t *db, isc_buffer_t *source, isc_buffer_t *target); static dns_result_t dispatch(isc_mem_t *mctx, isc_region_t *rxr, unsigned int reslen) { - char t[5000]; + char t[512]; isc_buffer_t source; isc_buffer_t target; dns_result_t result; isc_region_t txr; - - dump_packet(rxr->base, rxr->length); - - /* - * Set up the temporary output buffer. - */ - isc_buffer_init(&target, t + reslen, sizeof(t) - reslen, - ISC_BUFFERTYPE_BINARY); + dns_message_t *message, *reply; /* * Set up the input buffer from the contents of the region passed @@ -125,17 +148,43 @@ dispatch(isc_mem_t *mctx, isc_region_t *rxr, unsigned int reslen) ISC_BUFFERTYPE_BINARY); isc_buffer_add(&source, rxr->length); - result = resolve_packet(db, &source, &target); - if (result != DNS_R_SUCCESS) + result = dns_message_create(mctx, &message, DNS_MESSAGE_INTENT_PARSE); + if (CHECKRESULT(result, "dns_message_create failed")) { + return (result); + } + + result = dns_message_parse(message, &source); + if (CHECKRESULT(result, "dns_message_parsed failed")) { + dns_message_destroy(&message); + return (result); + } + CHECKRESULT(result, "dns_message_parse failed"); + + result = printmessage(message); + if (CHECKRESULT(result, "printmessage failed")) { + dns_message_destroy(&message); return (result); + } + + isc_buffer_init(&target, t, sizeof(t), ISC_BUFFERTYPE_BINARY); + result = resolve_packet(mctx, db, message, &reply, &target); + dns_message_destroy(&message); + if (result != DNS_R_SUCCESS) { + if (reply != NULL) + dns_message_destroy(&reply); + return (result); + } /* * Copy the reply out, adjusting for reslen */ isc_buffer_used(&target, &txr); txr.base = isc_mem_get(mctx, txr.length + reslen); - if (txr.base == NULL) + if (txr.base == NULL) { + dns_message_destroy(&reply); + return (DNS_R_NOMEMORY); + } memcpy(txr.base + reslen, t + reslen, txr.length); rxr->base = txr.base; @@ -144,11 +193,11 @@ dispatch(isc_mem_t *mctx, isc_region_t *rxr, unsigned int reslen) printf("Base == %p, length == %u\n", txr.base, txr.length); fflush(stdout); - dump_packet(rxr->base + reslen, rxr->length - reslen); - if (want_stats) isc_mem_stats(mctx, stdout); + dns_message_destroy(&reply); + return (DNS_R_SUCCESS); } diff --git a/bin/named/wire_debug.c b/bin/named/wire_debug.c index cc7e977bcd6d3743fe14d7b06f029a195c952b96..3a4628a2099753ad6c20c19885dcc42e9b317ee6 100644 --- a/bin/named/wire_debug.c +++ b/bin/named/wire_debug.c @@ -42,61 +42,32 @@ #include #include #include - -#define DNS_FLAG_QR 0x8000U -#define DNS_FLAG_AA 0x0400U -#define DNS_FLAG_TC 0x0200U -#define DNS_FLAG_RD 0x0100U -#define DNS_FLAG_RA 0x0080U - -#define DNS_OPCODE_MASK 0x7000U -#define DNS_OPCODE_SHIFT 11 -#define DNS_RCODE_MASK 0x000FU - -/* - * XXX All of the following is for debugging only, and will eventually - * be in a library or removed when we really answer queries. - */ -typedef struct dns_message { - unsigned int id; - unsigned int flags; - unsigned int qcount; - unsigned int ancount; - unsigned int aucount; - unsigned int adcount; - dns_namelist_t question; - dns_namelist_t answer; - dns_namelist_t authority; - dns_namelist_t additional; -} dns_message_t; +#include void -dump_packet(unsigned char *buf, u_int len); +dump_packet(isc_mem_t *mctx, unsigned char *buf, u_int len); dns_result_t resolve_packet(dns_db_t *db, isc_buffer_t *source, isc_buffer_t *target); -/* - * in wire_test.c - */ -void getmessage(dns_message_t *message, isc_buffer_t *source, - isc_buffer_t *target); dns_result_t printmessage(dns_message_t *message); +#define CHECKRESULT(result, msg) \ +{ \ + if ((result) != DNS_R_SUCCESS) { \ + printf("%s: %s\n", (msg), dns_result_totext(result)); \ + return; \ + } \ +} + void -dump_packet(unsigned char *buf, u_int len) +dump_packet(isc_mem_t *mctx, unsigned char *buf, u_int len) { - extern unsigned int rdcount, rlcount, ncount; - char t[5000]; /* XXX */ - dns_message_t message; + dns_message_t *message; dns_result_t result; - isc_buffer_t source, target; + isc_buffer_t source; unsigned int i; - rdcount = 0; - rlcount = 0; - ncount = 0; - for (i = 0 ; i < len ; /* */ ) { fprintf(stdout, "%02x", buf[i]); if ((++i % 20) == 0) @@ -110,13 +81,17 @@ dump_packet(unsigned char *buf, u_int len) isc_buffer_init(&source, buf, len, ISC_BUFFERTYPE_BINARY); isc_buffer_add(&source, len); - isc_buffer_init(&target, t, sizeof(t), ISC_BUFFERTYPE_BINARY); - getmessage(&message, &source, &target); - result = printmessage(&message); - if (result != DNS_R_SUCCESS) - printf("printmessage() failed: %s\n", - dns_result_totext(result)); + result = dns_message_create(mctx, &message, DNS_MESSAGE_INTENT_PARSE); + CHECKRESULT(result, "dns_message_create failed"); + + result = dns_message_parse(message, &source); + CHECKRESULT(result, "dns_message_parse failed"); + + result = printmessage(message); + CHECKRESULT(result, "printmessage() failed"); + + dns_message_destroy(&message); } static isc_uint16_t @@ -133,13 +108,13 @@ getshort(isc_buffer_t *buffer) { } dns_result_t -resolve_packet(dns_db_t *db, isc_buffer_t *source, isc_buffer_t *target) +resolve_packet(dns_db_t *db, dns_message_t *query, dns_message_t **reply, + isc_buffer_t *target) { dns_decompress_t dctx; dns_compress_t cctx; dns_result_t result; unsigned int count; - dns_message_t message; dns_name_t name; isc_uint16_t qtype; isc_uint16_t qclass; diff --git a/bin/tests/wire_test.c b/bin/tests/wire_test.c index 7cab0139be804a9075b1b88f3660713eb00976d8..bdc2aa84851789092e42125045f1af6fb1b98b77 100644 --- a/bin/tests/wire_test.c +++ b/bin/tests/wire_test.c @@ -39,10 +39,7 @@ #include dns_decompress_t dctx; -unsigned int rdcount, rlcount, ncount; -void getmessage(dns_message_t *message, isc_buffer_t *source, - isc_buffer_t *target); dns_result_t printmessage(dns_message_t *message); static inline void @@ -69,6 +66,7 @@ print_wirename(isc_region_t *name) { } #endif +#ifndef NOMAIN static int fromhex(char c) { if (c >= '0' && c <= '9') @@ -82,6 +80,7 @@ fromhex(char c) { exit(3); /* NOTREACHED */ } +#endif static char *opcodetext[] = { "QUERY", @@ -260,7 +259,6 @@ main(int argc, char *argv[]) { unsigned char b[1000]; char s[1000]; dns_message_t *message; - dns_message_t *message2; dns_result_t result; isc_mem_t *mctx; diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index e2d29f871ca851b1c2be9d357c16b3195b0822ee..58b2bcbef8fdbad7d9db631dfe8b2dd6a5ed5f05 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -110,6 +110,8 @@ typedef struct { unsigned int from_to_wire : 2; unsigned int reserved; + isc_buffer_t *buffer; + isc_mem_t *mctx; ISC_LIST(isc_dynbuffer_t) scratchpad; ISC_LIST(dns_msgblock_t) names; @@ -221,11 +223,35 @@ dns_message_renderbegin(dns_message_t *msg, isc_buffer_t *buffer); * Requires: * * 'msg' be valid. + * + * buffer != NULL. + * + * buffer is empty. */ dns_result_t -dns_message_renderreserve(dns_message_t *msg, isc_buffer_t *buffer, - unsigned int space); +dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer); +/* + * Reset the buffer. This can be used after growing the old buffer + * on a DNS_R_NOSPACE return from most of the render functions. + * + * Requires: + * + * 'msg' be valid. + * + * dns_message_renderbegin() was called. + * + * buffer != NULL. + * + * Returns: + * + * DNS_R_NOSPACE - new buffer is too small + * + * DNS_R_SUCCESS - all is well. + */ + +dns_result_t +dns_message_renderreserve(dns_message_t *msg, unsigned int space); /* * Reserve "space" bytes in the given buffer. * @@ -233,6 +259,8 @@ dns_message_renderreserve(dns_message_t *msg, isc_buffer_t *buffer, * * 'msg' be valid. * + * dns_message_renderbegin() was called. + * * Returns: * * DNS_R_SUCCESS -- all is well. @@ -248,6 +276,8 @@ dns_message_renderrelease(dns_message_t *msg, unsigned int space); * * 'msg' be valid. * + * dns_message_renderbegin() was called. + * * Returns: * * DNS_R_SUCCESS -- all is well. @@ -255,9 +285,8 @@ dns_message_renderrelease(dns_message_t *msg, unsigned int space); */ dns_result_t -dns_message_rendersection(dns_message_t *msg, isc_buffer_t *buffer, - dns_section_t section, unsigned int priority, - unsigned int flags); +dns_message_rendersection(dns_message_t *msg, dns_section_t section, + unsigned int priority, unsigned int flags); /* * Render all names, rdatalists, etc from the given section at the * specified priority or higher. @@ -270,6 +299,8 @@ dns_message_rendersection(dns_message_t *msg, isc_buffer_t *buffer, * 'buffer' be non-NULL and be initialized to point to a valid memory * block. * + * dns_message_renderbegin() was called. + * * Returns: * DNS_R_SUCCESS -- all records were written, and there are * no more records for this section. @@ -280,7 +311,7 @@ dns_message_rendersection(dns_message_t *msg, isc_buffer_t *buffer, */ dns_result_t -dns_message_renderend(dns_message_t *msg, isc_buffer_t *buffer); +dns_message_renderend(dns_message_t *msg); /* * Finish rendering to the buffer. Note that more data can be in the * 'msg' structure. Destroying the structure will free this, or in a multi- @@ -290,6 +321,8 @@ dns_message_renderend(dns_message_t *msg, isc_buffer_t *buffer); * * 'msg' be a valid message. * + * dns_message_renderbegin() was called. + * * Returns: * * DNS_R_SUCCESS -- all is well. diff --git a/lib/dns/message.c b/lib/dns/message.c index 07720a26de063f350c3cde26c829e1da51b60cc0..c55d0927a1f0766f9fda14656e5c68971dd2cfef 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -345,6 +345,8 @@ msginit(dns_message_t *m) m->nextrdata = NULL; m->nextrdataset = NULL; m->nextrdatalist = NULL; + + m->buffer = NULL; } /* @@ -992,17 +994,69 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source) dns_result_t dns_message_renderbegin(dns_message_t *msg, isc_buffer_t *buffer) { + isc_region_t r; + REQUIRE(VALID_MESSAGE(msg)); REQUIRE(buffer != NULL); + REQUIRE(msg->buffer == NULL); - /* XXX implement */ - return (ISC_R_NOTIMPLEMENTED); + /* + * Erase the contents of this buffer. + */ + isc_buffer_clear(buffer); + + /* + * Make certain there is enough for at least the header in this + * buffer. + */ + isc_buffer_available(buffer, &r); + if (r.length < DNS_MESSAGE_HEADER_LEN) + return (DNS_R_NOSPACE); + + /* + * Reserve enough space for the header in this buffer. + */ + isc_buffer_add(buffer, DNS_MESSAGE_HEADER_LEN); + + return (DNS_R_SUCCESS); +} + +dns_result_t +dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) +{ + isc_region_t r, rn; + + REQUIRE(VALID_MESSAGE(msg)); + REQUIRE(buffer != NULL); + REQUIRE(msg->buffer != NULL); + + /* + * ensure that the new buffer is empty, and has enough space to + * hold the current contents. + */ + isc_buffer_clear(buffer); + + isc_buffer_available(buffer, &rn); + isc_buffer_used(msg->buffer, &r); + if (rn.length < r.length) + return (DNS_R_NOSPACE); + + /* + * Copy the contents from the old to the new buffer. + */ + isc_buffer_add(buffer, r.length); + memcpy(rn.base, r.base, r.length); + + msg->buffer = buffer; + + return (DNS_R_SUCCESS); } dns_result_t dns_message_renderrelease(dns_message_t *msg, unsigned int space) { REQUIRE(VALID_MESSAGE(msg)); + REQUIRE(msg->buffer != NULL); if (msg->reserved < space) return (DNS_R_NOSPACE); @@ -1013,13 +1067,12 @@ dns_message_renderrelease(dns_message_t *msg, unsigned int space) } dns_result_t -dns_message_renderreserve(dns_message_t *msg, isc_buffer_t *buffer, - unsigned int space) +dns_message_renderreserve(dns_message_t *msg, unsigned int space) { isc_region_t r; REQUIRE(VALID_MESSAGE(msg)); - REQUIRE(buffer != NULL); + REQUIRE(msg->buffer != NULL); /* * "space" can be positive or negative. If it is negative we are @@ -1027,7 +1080,7 @@ dns_message_renderreserve(dns_message_t *msg, isc_buffer_t *buffer, * requesting more space to be reserved. */ - isc_buffer_available(buffer, &r); + isc_buffer_available(msg->buffer, &r); if (r.length < (space + msg->reserved)) return (DNS_R_NOSPACE); @@ -1037,12 +1090,11 @@ dns_message_renderreserve(dns_message_t *msg, isc_buffer_t *buffer, } dns_result_t -dns_message_rendersection(dns_message_t *msg, isc_buffer_t *buffer, - dns_section_t section, unsigned int priority, - unsigned int flags) +dns_message_rendersection(dns_message_t *msg, dns_section_t section, + unsigned int priority, unsigned int flags) { REQUIRE(VALID_MESSAGE(msg)); - REQUIRE(buffer != NULL); + REQUIRE(msg->buffer != NULL); REQUIRE(VALID_NAMED_SECTION(section)); /* XXX implement */ @@ -1050,10 +1102,12 @@ dns_message_rendersection(dns_message_t *msg, isc_buffer_t *buffer, } dns_result_t -dns_message_renderend(dns_message_t *msg, isc_buffer_t *buffer) +dns_message_renderend(dns_message_t *msg) { REQUIRE(VALID_MESSAGE(msg)); - REQUIRE(buffer != NULL); + REQUIRE(msg->buffer != NULL); + + msg->buffer = NULL; /* forget about this buffer only on success XXX */ /* XXX implement */ return (ISC_R_NOTIMPLEMENTED);