From f50ae72ec3417cae55dd4e085991c01af9fdc5f1 Mon Sep 17 00:00:00 2001 From: Martin Nagy Date: Wed, 11 Feb 2009 20:37:59 +0100 Subject: Initial commit --- bin/tests/wire_test.c | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 bin/tests/wire_test.c (limited to 'bin/tests/wire_test.c') diff --git a/bin/tests/wire_test.c b/bin/tests/wire_test.c new file mode 100644 index 0000000..ee7de98 --- /dev/null +++ b/bin/tests/wire_test.c @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1999-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: wire_test.c,v 1.67 2007/06/19 23:46:59 tbox Exp $ */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include "printmsg.h" + +int parseflags = 0; +isc_mem_t *mctx; +isc_boolean_t printmemstats = ISC_FALSE; +isc_boolean_t dorender = ISC_FALSE; + +static void +process_message(isc_buffer_t *source); + +static inline void +CHECKRESULT(isc_result_t result, const char *msg) { + if (result != ISC_R_SUCCESS) { + printf("%s: %s\n", msg, dns_result_totext(result)); + + exit(1); + } +} + +static int +fromhex(char c) { + if (c >= '0' && c <= '9') + return (c - '0'); + else if (c >= 'a' && c <= 'f') + return (c - 'a' + 10); + else if (c >= 'A' && c <= 'F') + return (c - 'A' + 10); + + printf("bad input format: %02x\n", c); + exit(3); + /* NOTREACHED */ +} + +static void +usage(void) { + fprintf(stderr, "wire_test [-p] [-b] [-s] [-r]\n"); + fprintf(stderr, "\t-p\tPreserve order of the records in messages\n"); + fprintf(stderr, "\t-b\tBest-effort parsing (ignore some errors)\n"); + fprintf(stderr, "\t-s\tPrint memory statistics\n"); + fprintf(stderr, "\t-r\tAfter parsing, re-render the message\n"); + fprintf(stderr, "\t-t\tTCP mode - ignore the first 2 bytes\n"); +} + +int +main(int argc, char *argv[]) { + char *rp, *wp; + unsigned char *bp; + isc_buffer_t source; + size_t len, i; + int n; + FILE *f; + isc_boolean_t need_close = ISC_FALSE; + unsigned char b[64 * 1024]; + char s[4000]; + isc_boolean_t tcp = ISC_FALSE; + int ch; + + mctx = NULL; + RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); + + while ((ch = isc_commandline_parse(argc, argv, "pbsrt")) != -1) { + switch (ch) { + case 'p': + parseflags |= DNS_MESSAGEPARSE_PRESERVEORDER; + break; + case 'b': + parseflags |= DNS_MESSAGEPARSE_BESTEFFORT; + break; + case 's': + printmemstats = ISC_TRUE; + break; + case 'r': + dorender = ISC_TRUE; + break; + case 't': + tcp = ISC_TRUE; + break; + default: + usage(); + exit(1); + } + } + + argc -= isc_commandline_index; + argv += isc_commandline_index; + + if (argc > 1) { + f = fopen(argv[1], "r"); + if (f == NULL) { + printf("fopen failed\n"); + exit(1); + } + need_close = ISC_TRUE; + } else + f = stdin; + + bp = b; + while (fgets(s, sizeof(s), f) != NULL) { + rp = s; + wp = s; + len = 0; + while (*rp != '\0') { + if (*rp == '#') + break; + if (*rp != ' ' && *rp != '\t' && + *rp != '\r' && *rp != '\n') { + *wp++ = *rp; + len++; + } + rp++; + } + if (len == 0U) + break; + if (len % 2 != 0U) { + printf("bad input format: %lu\n", (unsigned long)len); + exit(1); + } + if (len > sizeof(b) * 2) { + printf("input too long\n"); + exit(2); + } + rp = s; + for (i = 0; i < len; i += 2) { + n = fromhex(*rp++); + n *= 16; + n += fromhex(*rp++); + *bp++ = n; + } + } + + if (need_close) + fclose(f); + + if (tcp) { + unsigned char *p = b; + while (p < bp) { + unsigned int len; + + if (p + 2 > bp) { + printf("premature end of packet\n"); + exit(1); + } + len = p[0] << 8 | p[1]; + + if (p + 2 + len > bp) { + printf("premature end of packet\n"); + exit(1); + } + isc_buffer_init(&source, p + 2, len); + isc_buffer_add(&source, len); + process_message(&source); + p += 2 + len; + } + } else { + isc_buffer_init(&source, b, sizeof(b)); + isc_buffer_add(&source, bp - b); + process_message(&source); + } + + if (printmemstats) + isc_mem_stats(mctx, stdout); + isc_mem_destroy(&mctx); + + return (0); +} + +static void +process_message(isc_buffer_t *source) { + dns_message_t *message; + isc_result_t result; + int i; + + message = NULL; + result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &message); + CHECKRESULT(result, "dns_message_create failed"); + + result = dns_message_parse(message, source, parseflags); + if (result == DNS_R_RECOVERABLE) + result = ISC_R_SUCCESS; + CHECKRESULT(result, "dns_message_parse failed"); + + result = printmessage(message); + CHECKRESULT(result, "printmessage() failed"); + + if (printmemstats) + isc_mem_stats(mctx, stdout); + + if (dorender) { + unsigned char b2[64 * 1024]; + isc_buffer_t buffer; + dns_compress_t cctx; + + isc_buffer_init(&buffer, b2, sizeof(b2)); + + /* + * XXXMLG + * Changing this here is a hack, and should not be done in + * reasonable application code, ever. + */ + message->from_to_wire = DNS_MESSAGE_INTENTRENDER; + + for (i = 0; i < DNS_SECTION_MAX; i++) + message->counts[i] = 0; /* Another hack XXX */ + + result = dns_compress_init(&cctx, -1, mctx); + CHECKRESULT(result, "dns_compress_init() failed"); + + result = dns_message_renderbegin(message, &cctx, &buffer); + CHECKRESULT(result, "dns_message_renderbegin() failed"); + + result = dns_message_rendersection(message, + DNS_SECTION_QUESTION, 0); + CHECKRESULT(result, + "dns_message_rendersection(QUESTION) failed"); + + result = dns_message_rendersection(message, + DNS_SECTION_ANSWER, 0); + CHECKRESULT(result, + "dns_message_rendersection(ANSWER) failed"); + + result = dns_message_rendersection(message, + DNS_SECTION_AUTHORITY, 0); + CHECKRESULT(result, + "dns_message_rendersection(AUTHORITY) failed"); + + result = dns_message_rendersection(message, + DNS_SECTION_ADDITIONAL, 0); + CHECKRESULT(result, + "dns_message_rendersection(ADDITIONAL) failed"); + + dns_message_renderend(message); + + dns_compress_invalidate(&cctx); + + message->from_to_wire = DNS_MESSAGE_INTENTPARSE; + dns_message_destroy(&message); + + printf("Message rendered.\n"); + if (printmemstats) + isc_mem_stats(mctx, stdout); + + result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, + &message); + CHECKRESULT(result, "dns_message_create failed"); + + result = dns_message_parse(message, &buffer, parseflags); + CHECKRESULT(result, "dns_message_parse failed"); + + result = printmessage(message); + CHECKRESULT(result, "printmessage() failed"); + } + dns_message_destroy(&message); +} -- cgit