1*00b67f09SDavid van Moolenbroek /* $NetBSD: wire_test.c,v 1.6 2014/12/10 04:37:53 christos Exp $ */
2*00b67f09SDavid van Moolenbroek
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek * Copyright (C) 1999-2001 Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek *
7*00b67f09SDavid van Moolenbroek * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek *
11*00b67f09SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek */
19*00b67f09SDavid van Moolenbroek
20*00b67f09SDavid van Moolenbroek /* Id: wire_test.c,v 1.67 2007/06/19 23:46:59 tbox Exp */
21*00b67f09SDavid van Moolenbroek
22*00b67f09SDavid van Moolenbroek #include <config.h>
23*00b67f09SDavid van Moolenbroek
24*00b67f09SDavid van Moolenbroek #include <stdlib.h>
25*00b67f09SDavid van Moolenbroek
26*00b67f09SDavid van Moolenbroek #include <isc/buffer.h>
27*00b67f09SDavid van Moolenbroek #include <isc/commandline.h>
28*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
29*00b67f09SDavid van Moolenbroek #include <isc/string.h>
30*00b67f09SDavid van Moolenbroek #include <isc/util.h>
31*00b67f09SDavid van Moolenbroek
32*00b67f09SDavid van Moolenbroek #include <dns/result.h>
33*00b67f09SDavid van Moolenbroek
34*00b67f09SDavid van Moolenbroek #include "printmsg.h"
35*00b67f09SDavid van Moolenbroek
36*00b67f09SDavid van Moolenbroek int parseflags = 0;
37*00b67f09SDavid van Moolenbroek isc_mem_t *mctx;
38*00b67f09SDavid van Moolenbroek isc_boolean_t printmemstats = ISC_FALSE;
39*00b67f09SDavid van Moolenbroek isc_boolean_t dorender = ISC_FALSE;
40*00b67f09SDavid van Moolenbroek
41*00b67f09SDavid van Moolenbroek static void
42*00b67f09SDavid van Moolenbroek process_message(isc_buffer_t *source);
43*00b67f09SDavid van Moolenbroek
44*00b67f09SDavid van Moolenbroek static inline void
CHECKRESULT(isc_result_t result,const char * msg)45*00b67f09SDavid van Moolenbroek CHECKRESULT(isc_result_t result, const char *msg) {
46*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
47*00b67f09SDavid van Moolenbroek printf("%s: %s\n", msg, dns_result_totext(result));
48*00b67f09SDavid van Moolenbroek
49*00b67f09SDavid van Moolenbroek exit(1);
50*00b67f09SDavid van Moolenbroek }
51*00b67f09SDavid van Moolenbroek }
52*00b67f09SDavid van Moolenbroek
53*00b67f09SDavid van Moolenbroek static int
fromhex(char c)54*00b67f09SDavid van Moolenbroek fromhex(char c) {
55*00b67f09SDavid van Moolenbroek if (c >= '0' && c <= '9')
56*00b67f09SDavid van Moolenbroek return (c - '0');
57*00b67f09SDavid van Moolenbroek else if (c >= 'a' && c <= 'f')
58*00b67f09SDavid van Moolenbroek return (c - 'a' + 10);
59*00b67f09SDavid van Moolenbroek else if (c >= 'A' && c <= 'F')
60*00b67f09SDavid van Moolenbroek return (c - 'A' + 10);
61*00b67f09SDavid van Moolenbroek
62*00b67f09SDavid van Moolenbroek printf("bad input format: %02x\n", c);
63*00b67f09SDavid van Moolenbroek exit(3);
64*00b67f09SDavid van Moolenbroek /* NOTREACHED */
65*00b67f09SDavid van Moolenbroek }
66*00b67f09SDavid van Moolenbroek
67*00b67f09SDavid van Moolenbroek static void
usage(void)68*00b67f09SDavid van Moolenbroek usage(void) {
69*00b67f09SDavid van Moolenbroek fprintf(stderr, "wire_test [-p] [-b] [-s] [-r]\n");
70*00b67f09SDavid van Moolenbroek fprintf(stderr, "\t-p\tPreserve order of the records in messages\n");
71*00b67f09SDavid van Moolenbroek fprintf(stderr, "\t-b\tBest-effort parsing (ignore some errors)\n");
72*00b67f09SDavid van Moolenbroek fprintf(stderr, "\t-s\tPrint memory statistics\n");
73*00b67f09SDavid van Moolenbroek fprintf(stderr, "\t-r\tAfter parsing, re-render the message\n");
74*00b67f09SDavid van Moolenbroek fprintf(stderr, "\t-t\tTCP mode - ignore the first 2 bytes\n");
75*00b67f09SDavid van Moolenbroek }
76*00b67f09SDavid van Moolenbroek
77*00b67f09SDavid van Moolenbroek int
main(int argc,char * argv[])78*00b67f09SDavid van Moolenbroek main(int argc, char *argv[]) {
79*00b67f09SDavid van Moolenbroek char *rp, *wp;
80*00b67f09SDavid van Moolenbroek unsigned char *bp;
81*00b67f09SDavid van Moolenbroek isc_buffer_t source;
82*00b67f09SDavid van Moolenbroek size_t len, i;
83*00b67f09SDavid van Moolenbroek int n;
84*00b67f09SDavid van Moolenbroek FILE *f;
85*00b67f09SDavid van Moolenbroek isc_boolean_t need_close = ISC_FALSE;
86*00b67f09SDavid van Moolenbroek unsigned char b[64 * 1024];
87*00b67f09SDavid van Moolenbroek char s[4000];
88*00b67f09SDavid van Moolenbroek isc_boolean_t tcp = ISC_FALSE;
89*00b67f09SDavid van Moolenbroek int ch;
90*00b67f09SDavid van Moolenbroek
91*00b67f09SDavid van Moolenbroek mctx = NULL;
92*00b67f09SDavid van Moolenbroek RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
93*00b67f09SDavid van Moolenbroek
94*00b67f09SDavid van Moolenbroek while ((ch = isc_commandline_parse(argc, argv, "pbsrt")) != -1) {
95*00b67f09SDavid van Moolenbroek switch (ch) {
96*00b67f09SDavid van Moolenbroek case 'p':
97*00b67f09SDavid van Moolenbroek parseflags |= DNS_MESSAGEPARSE_PRESERVEORDER;
98*00b67f09SDavid van Moolenbroek break;
99*00b67f09SDavid van Moolenbroek case 'b':
100*00b67f09SDavid van Moolenbroek parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
101*00b67f09SDavid van Moolenbroek break;
102*00b67f09SDavid van Moolenbroek case 's':
103*00b67f09SDavid van Moolenbroek printmemstats = ISC_TRUE;
104*00b67f09SDavid van Moolenbroek break;
105*00b67f09SDavid van Moolenbroek case 'r':
106*00b67f09SDavid van Moolenbroek dorender = ISC_TRUE;
107*00b67f09SDavid van Moolenbroek break;
108*00b67f09SDavid van Moolenbroek case 't':
109*00b67f09SDavid van Moolenbroek tcp = ISC_TRUE;
110*00b67f09SDavid van Moolenbroek break;
111*00b67f09SDavid van Moolenbroek default:
112*00b67f09SDavid van Moolenbroek usage();
113*00b67f09SDavid van Moolenbroek exit(1);
114*00b67f09SDavid van Moolenbroek }
115*00b67f09SDavid van Moolenbroek }
116*00b67f09SDavid van Moolenbroek
117*00b67f09SDavid van Moolenbroek argc -= isc_commandline_index;
118*00b67f09SDavid van Moolenbroek argv += isc_commandline_index;
119*00b67f09SDavid van Moolenbroek
120*00b67f09SDavid van Moolenbroek if (argc > 1) {
121*00b67f09SDavid van Moolenbroek f = fopen(argv[1], "r");
122*00b67f09SDavid van Moolenbroek if (f == NULL) {
123*00b67f09SDavid van Moolenbroek printf("fopen failed\n");
124*00b67f09SDavid van Moolenbroek exit(1);
125*00b67f09SDavid van Moolenbroek }
126*00b67f09SDavid van Moolenbroek need_close = ISC_TRUE;
127*00b67f09SDavid van Moolenbroek } else
128*00b67f09SDavid van Moolenbroek f = stdin;
129*00b67f09SDavid van Moolenbroek
130*00b67f09SDavid van Moolenbroek bp = b;
131*00b67f09SDavid van Moolenbroek while (fgets(s, sizeof(s), f) != NULL) {
132*00b67f09SDavid van Moolenbroek rp = s;
133*00b67f09SDavid van Moolenbroek wp = s;
134*00b67f09SDavid van Moolenbroek len = 0;
135*00b67f09SDavid van Moolenbroek while (*rp != '\0') {
136*00b67f09SDavid van Moolenbroek if (*rp == '#')
137*00b67f09SDavid van Moolenbroek break;
138*00b67f09SDavid van Moolenbroek if (*rp != ' ' && *rp != '\t' &&
139*00b67f09SDavid van Moolenbroek *rp != '\r' && *rp != '\n') {
140*00b67f09SDavid van Moolenbroek *wp++ = *rp;
141*00b67f09SDavid van Moolenbroek len++;
142*00b67f09SDavid van Moolenbroek }
143*00b67f09SDavid van Moolenbroek rp++;
144*00b67f09SDavid van Moolenbroek }
145*00b67f09SDavid van Moolenbroek if (len == 0U)
146*00b67f09SDavid van Moolenbroek break;
147*00b67f09SDavid van Moolenbroek if (len % 2 != 0U) {
148*00b67f09SDavid van Moolenbroek printf("bad input format: %lu\n", (unsigned long)len);
149*00b67f09SDavid van Moolenbroek exit(1);
150*00b67f09SDavid van Moolenbroek }
151*00b67f09SDavid van Moolenbroek if (len > sizeof(b) * 2) {
152*00b67f09SDavid van Moolenbroek printf("input too long\n");
153*00b67f09SDavid van Moolenbroek exit(2);
154*00b67f09SDavid van Moolenbroek }
155*00b67f09SDavid van Moolenbroek rp = s;
156*00b67f09SDavid van Moolenbroek for (i = 0; i < len; i += 2) {
157*00b67f09SDavid van Moolenbroek n = fromhex(*rp++);
158*00b67f09SDavid van Moolenbroek n *= 16;
159*00b67f09SDavid van Moolenbroek n += fromhex(*rp++);
160*00b67f09SDavid van Moolenbroek *bp++ = n;
161*00b67f09SDavid van Moolenbroek }
162*00b67f09SDavid van Moolenbroek }
163*00b67f09SDavid van Moolenbroek
164*00b67f09SDavid van Moolenbroek if (need_close)
165*00b67f09SDavid van Moolenbroek fclose(f);
166*00b67f09SDavid van Moolenbroek
167*00b67f09SDavid van Moolenbroek if (tcp) {
168*00b67f09SDavid van Moolenbroek unsigned char *p = b;
169*00b67f09SDavid van Moolenbroek while (p < bp) {
170*00b67f09SDavid van Moolenbroek unsigned int len;
171*00b67f09SDavid van Moolenbroek
172*00b67f09SDavid van Moolenbroek if (p + 2 > bp) {
173*00b67f09SDavid van Moolenbroek printf("premature end of packet\n");
174*00b67f09SDavid van Moolenbroek exit(1);
175*00b67f09SDavid van Moolenbroek }
176*00b67f09SDavid van Moolenbroek len = p[0] << 8 | p[1];
177*00b67f09SDavid van Moolenbroek
178*00b67f09SDavid van Moolenbroek if (p + 2 + len > bp) {
179*00b67f09SDavid van Moolenbroek printf("premature end of packet\n");
180*00b67f09SDavid van Moolenbroek exit(1);
181*00b67f09SDavid van Moolenbroek }
182*00b67f09SDavid van Moolenbroek isc_buffer_init(&source, p + 2, len);
183*00b67f09SDavid van Moolenbroek isc_buffer_add(&source, len);
184*00b67f09SDavid van Moolenbroek process_message(&source);
185*00b67f09SDavid van Moolenbroek p += 2 + len;
186*00b67f09SDavid van Moolenbroek }
187*00b67f09SDavid van Moolenbroek } else {
188*00b67f09SDavid van Moolenbroek isc_buffer_init(&source, b, sizeof(b));
189*00b67f09SDavid van Moolenbroek isc_buffer_add(&source, bp - b);
190*00b67f09SDavid van Moolenbroek process_message(&source);
191*00b67f09SDavid van Moolenbroek }
192*00b67f09SDavid van Moolenbroek
193*00b67f09SDavid van Moolenbroek if (printmemstats)
194*00b67f09SDavid van Moolenbroek isc_mem_stats(mctx, stdout);
195*00b67f09SDavid van Moolenbroek isc_mem_destroy(&mctx);
196*00b67f09SDavid van Moolenbroek
197*00b67f09SDavid van Moolenbroek return (0);
198*00b67f09SDavid van Moolenbroek }
199*00b67f09SDavid van Moolenbroek
200*00b67f09SDavid van Moolenbroek static void
process_message(isc_buffer_t * source)201*00b67f09SDavid van Moolenbroek process_message(isc_buffer_t *source) {
202*00b67f09SDavid van Moolenbroek dns_message_t *message;
203*00b67f09SDavid van Moolenbroek isc_result_t result;
204*00b67f09SDavid van Moolenbroek int i;
205*00b67f09SDavid van Moolenbroek
206*00b67f09SDavid van Moolenbroek message = NULL;
207*00b67f09SDavid van Moolenbroek result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &message);
208*00b67f09SDavid van Moolenbroek CHECKRESULT(result, "dns_message_create failed");
209*00b67f09SDavid van Moolenbroek
210*00b67f09SDavid van Moolenbroek result = dns_message_parse(message, source, parseflags);
211*00b67f09SDavid van Moolenbroek if (result == DNS_R_RECOVERABLE)
212*00b67f09SDavid van Moolenbroek result = ISC_R_SUCCESS;
213*00b67f09SDavid van Moolenbroek CHECKRESULT(result, "dns_message_parse failed");
214*00b67f09SDavid van Moolenbroek
215*00b67f09SDavid van Moolenbroek result = printmessage(message);
216*00b67f09SDavid van Moolenbroek CHECKRESULT(result, "printmessage() failed");
217*00b67f09SDavid van Moolenbroek
218*00b67f09SDavid van Moolenbroek if (printmemstats)
219*00b67f09SDavid van Moolenbroek isc_mem_stats(mctx, stdout);
220*00b67f09SDavid van Moolenbroek
221*00b67f09SDavid van Moolenbroek if (dorender) {
222*00b67f09SDavid van Moolenbroek unsigned char b2[64 * 1024];
223*00b67f09SDavid van Moolenbroek isc_buffer_t buffer;
224*00b67f09SDavid van Moolenbroek dns_compress_t cctx;
225*00b67f09SDavid van Moolenbroek
226*00b67f09SDavid van Moolenbroek isc_buffer_init(&buffer, b2, sizeof(b2));
227*00b67f09SDavid van Moolenbroek
228*00b67f09SDavid van Moolenbroek /*
229*00b67f09SDavid van Moolenbroek * XXXMLG
230*00b67f09SDavid van Moolenbroek * Changing this here is a hack, and should not be done in
231*00b67f09SDavid van Moolenbroek * reasonable application code, ever.
232*00b67f09SDavid van Moolenbroek */
233*00b67f09SDavid van Moolenbroek message->from_to_wire = DNS_MESSAGE_INTENTRENDER;
234*00b67f09SDavid van Moolenbroek
235*00b67f09SDavid van Moolenbroek for (i = 0; i < DNS_SECTION_MAX; i++)
236*00b67f09SDavid van Moolenbroek message->counts[i] = 0; /* Another hack XXX */
237*00b67f09SDavid van Moolenbroek
238*00b67f09SDavid van Moolenbroek result = dns_compress_init(&cctx, -1, mctx);
239*00b67f09SDavid van Moolenbroek CHECKRESULT(result, "dns_compress_init() failed");
240*00b67f09SDavid van Moolenbroek
241*00b67f09SDavid van Moolenbroek result = dns_message_renderbegin(message, &cctx, &buffer);
242*00b67f09SDavid van Moolenbroek CHECKRESULT(result, "dns_message_renderbegin() failed");
243*00b67f09SDavid van Moolenbroek
244*00b67f09SDavid van Moolenbroek result = dns_message_rendersection(message,
245*00b67f09SDavid van Moolenbroek DNS_SECTION_QUESTION, 0);
246*00b67f09SDavid van Moolenbroek CHECKRESULT(result,
247*00b67f09SDavid van Moolenbroek "dns_message_rendersection(QUESTION) failed");
248*00b67f09SDavid van Moolenbroek
249*00b67f09SDavid van Moolenbroek result = dns_message_rendersection(message,
250*00b67f09SDavid van Moolenbroek DNS_SECTION_ANSWER, 0);
251*00b67f09SDavid van Moolenbroek CHECKRESULT(result,
252*00b67f09SDavid van Moolenbroek "dns_message_rendersection(ANSWER) failed");
253*00b67f09SDavid van Moolenbroek
254*00b67f09SDavid van Moolenbroek result = dns_message_rendersection(message,
255*00b67f09SDavid van Moolenbroek DNS_SECTION_AUTHORITY, 0);
256*00b67f09SDavid van Moolenbroek CHECKRESULT(result,
257*00b67f09SDavid van Moolenbroek "dns_message_rendersection(AUTHORITY) failed");
258*00b67f09SDavid van Moolenbroek
259*00b67f09SDavid van Moolenbroek result = dns_message_rendersection(message,
260*00b67f09SDavid van Moolenbroek DNS_SECTION_ADDITIONAL, 0);
261*00b67f09SDavid van Moolenbroek CHECKRESULT(result,
262*00b67f09SDavid van Moolenbroek "dns_message_rendersection(ADDITIONAL) failed");
263*00b67f09SDavid van Moolenbroek
264*00b67f09SDavid van Moolenbroek dns_message_renderend(message);
265*00b67f09SDavid van Moolenbroek
266*00b67f09SDavid van Moolenbroek dns_compress_invalidate(&cctx);
267*00b67f09SDavid van Moolenbroek
268*00b67f09SDavid van Moolenbroek message->from_to_wire = DNS_MESSAGE_INTENTPARSE;
269*00b67f09SDavid van Moolenbroek dns_message_destroy(&message);
270*00b67f09SDavid van Moolenbroek
271*00b67f09SDavid van Moolenbroek printf("Message rendered.\n");
272*00b67f09SDavid van Moolenbroek if (printmemstats)
273*00b67f09SDavid van Moolenbroek isc_mem_stats(mctx, stdout);
274*00b67f09SDavid van Moolenbroek
275*00b67f09SDavid van Moolenbroek result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
276*00b67f09SDavid van Moolenbroek &message);
277*00b67f09SDavid van Moolenbroek CHECKRESULT(result, "dns_message_create failed");
278*00b67f09SDavid van Moolenbroek
279*00b67f09SDavid van Moolenbroek result = dns_message_parse(message, &buffer, parseflags);
280*00b67f09SDavid van Moolenbroek CHECKRESULT(result, "dns_message_parse failed");
281*00b67f09SDavid van Moolenbroek
282*00b67f09SDavid van Moolenbroek result = printmessage(message);
283*00b67f09SDavid van Moolenbroek CHECKRESULT(result, "printmessage() failed");
284*00b67f09SDavid van Moolenbroek }
285*00b67f09SDavid van Moolenbroek dns_message_destroy(&message);
286*00b67f09SDavid van Moolenbroek }
287