1 /*
2 * Copyright (c) 1985,1989 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 static char sccsid[] = "@(#)debug.c 5.26 (Berkeley) 3/21/91";
36 #endif /* not lint */
37
38 /*
39 *******************************************************************************
40 *
41 * debug.c --
42 *
43 * Routines to print out packets received from a name server query.
44 *
45 * Modified version of 4.3BSD BIND res_debug.c 5.30 6/27/90
46 *
47 *******************************************************************************
48 */
49
50 #include <sys/param.h>
51 #include <netinet/in.h>
52 #include <arpa/nameser.h>
53 #include <arpa/inet.h>
54 #include <resolv.h>
55 #include <netdb.h>
56 #include <stdio.h>
57 #include "res.h"
58
59 extern char ctime();
60
61 /*
62 * Imported from res_debug.c
63 */
64 extern char *_res_resultcodes[];
65 extern char *_res_opcodes[];
66
67 /*
68 * Used to highlight the start of a record when printing it.
69 */
70 #define INDENT " -> "
71
72
73
74 /*
75 * Print the contents of a query.
76 * This is intended to be primarily a debugging routine.
77 */
78
Print_query(msg,eom,printHeader)79 Print_query(msg, eom, printHeader)
80 char *msg, *eom;
81 int printHeader;
82 {
83 Fprint_query(msg, eom, printHeader,stdout);
84 }
85
Fprint_query(msg,eom,printHeader,file)86 Fprint_query(msg, eom, printHeader,file)
87 char *msg, *eom;
88 int printHeader;
89 FILE *file;
90 {
91 register char *cp;
92 register HEADER *hp;
93 register int n;
94 short class;
95 short type;
96
97 /*
98 * Print header fields.
99 */
100 hp = (HEADER *)msg;
101 cp = msg + sizeof(HEADER);
102 if (printHeader || (_res.options & RES_DEBUG2)) {
103 fprintf(file," HEADER:\n");
104 fprintf(file,"\topcode = %s", _res_opcodes[hp->opcode]);
105 fprintf(file,", id = %d", ntohs(hp->id));
106 fprintf(file,", rcode = %s\n", _res_resultcodes[hp->rcode]);
107 fprintf(file,"\theader flags: ");
108 if (hp->qr) {
109 fprintf(file," response");
110 } else {
111 fprintf(file," query");
112 }
113 if (hp->aa)
114 fprintf(file,", auth. answer");
115 if (hp->tc)
116 fprintf(file,", truncation");
117 if (hp->rd)
118 fprintf(file,", want recursion");
119 if (hp->ra)
120 fprintf(file,", recursion avail.");
121 if (hp->pr)
122 fprintf(file,", primary");
123 fprintf(file,"\n\tquestions = %d", ntohs(hp->qdcount));
124 fprintf(file,", answers = %d", ntohs(hp->ancount));
125 fprintf(file,", authority records = %d", ntohs(hp->nscount));
126 fprintf(file,", additional = %d\n\n", ntohs(hp->arcount));
127 }
128
129 /*
130 * Print question records.
131 */
132 if (n = ntohs(hp->qdcount)) {
133 fprintf(file," QUESTIONS:\n");
134 while (--n >= 0) {
135 fprintf(file,"\t");
136 cp = Print_cdname(cp, msg, eom, file);
137 if (cp == NULL)
138 return;
139 type = _getshort(cp);
140 cp += sizeof(u_short);
141 class = _getshort(cp);
142 cp += sizeof(u_short);
143 fprintf(file,", type = %s", p_type(type));
144 fprintf(file,", class = %s\n", p_class(class));
145 }
146 }
147 /*
148 * Print authoritative answer records
149 */
150 if (n = ntohs(hp->ancount)) {
151 fprintf(file," ANSWERS:\n");
152 while (--n >= 0) {
153 fprintf(file, INDENT);
154 cp = Print_rr(cp, msg, eom, file);
155 if (cp == NULL)
156 return;
157 }
158 }
159 /*
160 * print name server records
161 */
162 if (n = ntohs(hp->nscount)) {
163 fprintf(file," AUTHORITY RECORDS:\n");
164 while (--n >= 0) {
165 fprintf(file, INDENT);
166 cp = Print_rr(cp, msg, eom, file);
167 if (cp == NULL)
168 return;
169 }
170 }
171 /*
172 * print additional records
173 */
174 if (n = ntohs(hp->arcount)) {
175 fprintf(file," ADDITIONAL RECORDS:\n");
176 while (--n >= 0) {
177 fprintf(file, INDENT);
178 cp = Print_rr(cp, msg, eom, file);
179 if (cp == NULL)
180 return;
181 }
182 }
183 fprintf(file,"\n------------\n");
184 }
185
186
187 char *
Print_cdname_sub(cp,msg,eom,file,format)188 Print_cdname_sub(cp, msg, eom, file, format)
189 u_char *cp, *msg, *eom;
190 FILE *file;
191 int format;
192 {
193 int n;
194 u_char name[MAXDNAME];
195 extern char *strcpy();
196
197 if ((n = dn_expand(msg, eom, cp, name, sizeof(name))) < 0)
198 return (NULL);
199 if (name[0] == '\0') {
200 (void) strcpy(name, "(root)");
201 }
202 if (format) {
203 fprintf(file, "%-30s", name);
204 } else {
205 fputs((char *)name, file);
206 }
207 return ((char *)cp + n);
208 }
209
210 char *
Print_cdname(cp,msg,eom,file)211 Print_cdname(cp, msg, eom, file)
212 char *cp, *msg, *eom;
213 FILE *file;
214 {
215 return(Print_cdname_sub(cp, msg, eom, file, 0));
216 }
217
218 char *
Print_cdname2(cp,msg,eom,file)219 Print_cdname2(cp, msg, eom, file)
220 char *cp, *msg, *eom;
221 FILE *file;
222 {
223 return(Print_cdname_sub(cp, msg, eom, file, 1));
224 }
225
226 /*
227 * Print resource record fields in human readable form.
228 */
229 char *
Print_rr(cp,msg,eom,file)230 Print_rr(cp, msg, eom, file)
231 char *cp, *msg, *eom;
232 FILE *file;
233 {
234 int type, class, dlen, n, c;
235 unsigned long rrttl, ttl;
236 struct in_addr inaddr;
237 char *cp1, *cp2;
238 int debug;
239
240 if ((cp = Print_cdname(cp, msg, eom, file)) == NULL) {
241 fprintf(file, "(name truncated?)\n");
242 return (NULL); /* compression error */
243 }
244
245 type = _getshort(cp);
246 cp += sizeof(u_short);
247 class = _getshort(cp);
248 cp += sizeof(u_short);
249 rrttl = _getlong(cp);
250 cp += sizeof(u_long);
251 dlen = _getshort(cp);
252 cp += sizeof(u_short);
253
254 debug = _res.options & (RES_DEBUG|RES_DEBUG2);
255 if (debug) {
256 if (_res.options & RES_DEBUG2) {
257 fprintf(file,"\n\ttype = %s, class = %s, dlen = %d",
258 p_type(type), p_class(class), dlen);
259 }
260 if (type == T_SOA) {
261 fprintf(file,"\n\tttl = %lu (%s)", rrttl, p_time(rrttl));
262 }
263 (void) putc('\n', file);
264 }
265
266 cp1 = cp;
267
268 /*
269 * Print type specific data, if appropriate
270 */
271 switch (type) {
272 case T_A:
273 switch (class) {
274 case C_IN:
275 case C_HS:
276 bcopy(cp, (char *)&inaddr, sizeof(inaddr));
277 if (dlen == 4) {
278 fprintf(file,"\tinternet address = %s\n",
279 inet_ntoa(inaddr));
280 cp += dlen;
281 } else if (dlen == 7) {
282 fprintf(file,"\tinternet address = %s",
283 inet_ntoa(inaddr));
284 fprintf(file,", protocol = %d", cp[4]);
285 fprintf(file,", port = %d\n",
286 (cp[5] << 8) + cp[6]);
287 cp += dlen;
288 }
289 break;
290 default:
291 fprintf(file,"\taddress, class = %d, len = %d\n",
292 class, dlen);
293 cp += dlen;
294 }
295 break;
296
297 case T_CNAME:
298 fprintf(file,"\tcanonical name = ");
299 goto doname;
300
301 case T_MG:
302 fprintf(file,"\tmail group member = ");
303 goto doname;
304 case T_MB:
305 fprintf(file,"\tmail box = ");
306 goto doname;
307 case T_MR:
308 fprintf(file,"\tmailbox rename = ");
309 goto doname;
310 case T_MX:
311 fprintf(file,"\tpreference = %u",_getshort(cp));
312 cp += sizeof(u_short);
313 fprintf(file,", mail exchanger = ");
314 goto doname;
315 case T_NS:
316 fprintf(file,"\tnameserver = ");
317 goto doname;
318 case T_PTR:
319 fprintf(file,"\tname = ");
320 doname:
321 cp = Print_cdname(cp, msg, eom, file);
322 (void) putc('\n', file);
323 break;
324
325 case T_HINFO:
326 if (n = *cp++) {
327 fprintf(file,"\tCPU = %.*s", n, cp);
328 cp += n;
329 }
330 if (n = *cp++) {
331 fprintf(file,"\tOS = %.*s\n", n, cp);
332 cp += n;
333 }
334 break;
335
336 case T_SOA:
337 if (!debug)
338 (void) putc('\n', file);
339 fprintf(file,"\torigin = ");
340 cp = Print_cdname(cp, msg, eom, file);
341 fprintf(file,"\n\tmail addr = ");
342 cp = Print_cdname(cp, msg, eom, file);
343 fprintf(file,"\n\tserial = %lu", _getlong(cp));
344 cp += sizeof(u_long);
345 ttl = _getlong(cp);
346 fprintf(file,"\n\trefresh = %lu (%s)", ttl, p_time(ttl));
347 cp += sizeof(u_long);
348 ttl = _getlong(cp);
349 fprintf(file,"\n\tretry = %lu (%s)", ttl, p_time(ttl));
350 cp += sizeof(u_long);
351 ttl = _getlong(cp);
352 fprintf(file,"\n\texpire = %lu (%s)", ttl, p_time(ttl));
353 cp += sizeof(u_long);
354 ttl = _getlong(cp);
355 fprintf(file,
356 "\n\tminimum ttl = %lu (%s)\n", ttl, p_time(ttl));
357 cp += sizeof(u_long);
358 break;
359
360 case T_MINFO:
361 if (!debug)
362 (void) putc('\n', file);
363 fprintf(file,"\trequests = ");
364 cp = Print_cdname(cp, msg, eom, file);
365 fprintf(file,"\n\terrors = ");
366 cp = Print_cdname(cp, msg, eom, file);
367 (void) putc('\n', file);
368 break;
369
370 case T_TXT:
371 (void) fputs("\ttext = \"", file);
372 cp2 = cp1 + dlen;
373 while (cp < cp2) {
374 if (n = (unsigned char) *cp++) {
375 for (c = n; c > 0 && cp < cp2; c--)
376 if (*cp == '\n') {
377 (void) putc('\\', file);
378 (void) putc(*cp++, file);
379 } else
380 (void) putc(*cp++, file);
381 }
382 }
383 (void) fputs("\"\n", file);
384 break;
385
386 case T_UINFO:
387 fprintf(file,"\tuser info = %s\n", cp);
388 cp += dlen;
389 break;
390
391 case T_UID:
392 case T_GID:
393 if (dlen == 4) {
394 fprintf(file,"\t%cid = %lu\n",type == T_UID ? 'u' : 'g',
395 _getlong(cp));
396 cp += sizeof(int);
397 } else {
398 fprintf(file,"\t%cid of length %d?\n",
399 type == T_UID ? 'u' : 'g', dlen);
400 cp += dlen;
401 }
402 break;
403
404 case T_WKS: {
405 struct protoent *protoPtr;
406
407 if (dlen < sizeof(u_long) + 1)
408 break;
409 if (!debug)
410 (void) putc('\n', file);
411 bcopy(cp, (char *)&inaddr, sizeof(inaddr));
412 cp += sizeof(u_long);
413 if ((protoPtr = getprotobynumber(*cp)) != NULL) {
414 fprintf(file,"\tinet address = %s, protocol = %s\n\t",
415 inet_ntoa(inaddr), protoPtr->p_name);
416 } else {
417 fprintf(file,"\tinet address = %s, protocol = %d\n\t",
418 inet_ntoa(inaddr), *cp);
419 }
420 cp++;
421 n = 0;
422 while (cp < cp1 + dlen) {
423 c = *cp++;
424 do {
425 struct servent *s;
426
427 if (c & 0200) {
428 s = getservbyport((int)htons(n),
429 protoPtr ? protoPtr->p_name : NULL);
430 if (s != NULL) {
431 fprintf(file," %s", s->s_name);
432 } else {
433 fprintf(file," #%d", n);
434 }
435 }
436 c <<= 1;
437 } while (++n & 07);
438 }
439 putc('\n',file);
440 }
441 break;
442
443 case T_NULL:
444 fprintf(file, "\tNULL (dlen %d)\n", dlen);
445 cp += dlen;
446 break;
447
448 default:
449 fprintf(file,"\t??? unknown type %d ???\n", type);
450 cp += dlen;
451 }
452 if (_res.options & RES_DEBUG && type != T_SOA) {
453 fprintf(file,"\tttl = %lu (%s)\n", rrttl, p_time(rrttl));
454 }
455 if (cp != cp1 + dlen) {
456 fprintf(file,
457 "\n*** Error: record size incorrect (%d != %d)\n\n",
458 cp - cp1, dlen);
459 cp = NULL;
460 }
461 return (cp);
462 }
463