Libinfo-173.tar.gz
[apple/libinfo.git] / dns.subproj / res_debug.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * ++Copyright++ 1985, 1990, 1993
27 * -
28 * Copyright (c) 1985, 1990, 1993
29 * The Regents of the University of California. All rights reserved.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58 * -
59 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
60 *
61 * Permission to use, copy, modify, and distribute this software for any
62 * purpose with or without fee is hereby granted, provided that the above
63 * copyright notice and this permission notice appear in all copies, and that
64 * the name of Digital Equipment Corporation not be used in advertising or
65 * publicity pertaining to distribution of the document or software without
66 * specific, written prior permission.
67 *
68 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
69 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
70 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
71 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
72 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
73 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
74 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
75 * SOFTWARE.
76 * -
77 * --Copyright--
78 */
79
80 #if defined(LIBC_SCCS) && !defined(lint)
81 static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
82 static char rcsid[] = "$Id: res_debug.c,v 1.4 2003/02/18 17:29:24 majka Exp $";
83 #endif /* LIBC_SCCS and not lint */
84
85 #include <sys/param.h>
86 #include <netinet/in.h>
87 #include <arpa/inet.h>
88 #include <arpa/nameser8_compat.h>
89
90 #include <stdio.h>
91 #include <netdb.h>
92 #include <resolv8_compat.h>
93 #if defined(BSD) && (BSD >= 199103)
94 # include <string.h>
95 #else
96 # include "portability.h"
97 #endif
98
99 #if defined(USE_OPTIONS_H)
100 # include "options.h"
101 #endif
102
103 const char *_res_opcodes[] = {
104 "QUERY",
105 "IQUERY",
106 "CQUERYM",
107 "CQUERYU", /* experimental */
108 "NOTIFY", /* experimental */
109 "5",
110 "6",
111 "7",
112 "8",
113 "UPDATEA",
114 "UPDATED",
115 "UPDATEDA",
116 "UPDATEM",
117 "UPDATEMA",
118 "ZONEINIT",
119 "ZONEREF",
120 };
121
122 const char *_res_resultcodes[] = {
123 "NOERROR",
124 "FORMERR",
125 "SERVFAIL",
126 "NXDOMAIN",
127 "NOTIMP",
128 "REFUSED",
129 "6",
130 "7",
131 "8",
132 "9",
133 "10",
134 "11",
135 "12",
136 "13",
137 "14",
138 "NOCHANGE",
139 };
140
141 /* XXX: we should use getservbyport() instead. */
142 static const char *
143 dewks(wks)
144 int wks;
145 {
146 static char nbuf[20];
147
148 switch (wks) {
149 case 5: return "rje";
150 case 7: return "echo";
151 case 9: return "discard";
152 case 11: return "systat";
153 case 13: return "daytime";
154 case 15: return "netstat";
155 case 17: return "qotd";
156 case 19: return "chargen";
157 case 20: return "ftp-data";
158 case 21: return "ftp";
159 case 23: return "telnet";
160 case 25: return "smtp";
161 case 37: return "time";
162 case 39: return "rlp";
163 case 42: return "name";
164 case 43: return "whois";
165 case 53: return "domain";
166 case 57: return "apts";
167 case 59: return "apfs";
168 case 67: return "bootps";
169 case 68: return "bootpc";
170 case 69: return "tftp";
171 case 77: return "rje";
172 case 79: return "finger";
173 case 87: return "link";
174 case 95: return "supdup";
175 case 100: return "newacct";
176 case 101: return "hostnames";
177 case 102: return "iso-tsap";
178 case 103: return "x400";
179 case 104: return "x400-snd";
180 case 105: return "csnet-ns";
181 case 109: return "pop-2";
182 case 111: return "sunrpc";
183 case 113: return "auth";
184 case 115: return "sftp";
185 case 117: return "uucp-path";
186 case 119: return "nntp";
187 case 121: return "erpc";
188 case 123: return "ntp";
189 case 133: return "statsrv";
190 case 136: return "profile";
191 case 144: return "NeWS";
192 case 161: return "snmp";
193 case 162: return "snmp-trap";
194 case 170: return "print-srv";
195 default: (void) sprintf(nbuf, "%d", wks); return (nbuf);
196 }
197 }
198
199 /* XXX: we should use getprotobynumber() instead. */
200 static const char *
201 deproto(protonum)
202 int protonum;
203 {
204 static char nbuf[20];
205
206 switch (protonum) {
207 case 1: return "icmp";
208 case 2: return "igmp";
209 case 3: return "ggp";
210 case 5: return "st";
211 case 6: return "tcp";
212 case 7: return "ucl";
213 case 8: return "egp";
214 case 9: return "igp";
215 case 11: return "nvp-II";
216 case 12: return "pup";
217 case 16: return "chaos";
218 case 17: return "udp";
219 default: (void) sprintf(nbuf, "%d", protonum); return (nbuf);
220 }
221 }
222
223 static const u_char *
224 do_rrset(msg, len, cp, cnt, pflag, file, hs)
225 int cnt, pflag, len;
226 const u_char *cp, *msg;
227 const char *hs;
228 FILE *file;
229 {
230 int n;
231 int sflag;
232
233 /*
234 * Print answer records.
235 */
236 sflag = (_res.pfcode & pflag);
237 if ((n = ntohs(cnt))) {
238 if ((!_res.pfcode) ||
239 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
240 fprintf(file, hs);
241 while (--n >= 0) {
242 if ((!_res.pfcode) || sflag) {
243 cp = p_rr(cp, msg, file);
244 } else {
245 unsigned int dlen;
246 cp += __dn_skipname(cp, cp + MAXCDNAME);
247 cp += INT16SZ;
248 cp += INT16SZ;
249 cp += INT32SZ;
250 dlen = _getshort((u_char*)cp);
251 cp += INT16SZ;
252 cp += dlen;
253 }
254 if ((cp - msg) > len)
255 return (NULL);
256 }
257 if ((!_res.pfcode) ||
258 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
259 putc('\n', file);
260 }
261 return (cp);
262 }
263
264 void
265 __p_query(msg)
266 const u_char *msg;
267 {
268 __fp_query(msg, stdout);
269 }
270
271 #ifdef ultrix
272 /* ultrix 4.0's packaging has some icky packaging. alias for it here.
273 * there is more junk of this kind over in res_comp.c.
274 */
275 void
276 p_query(msg)
277 const u_char *msg;
278 {
279 __p_query(msg);
280 }
281 #endif
282
283 /*
284 * Print the current options.
285 * This is intended to be primarily a debugging routine.
286 */
287 void
288 __fp_resstat(statp, file)
289 struct __res_state *statp;
290 FILE *file;
291 {
292 register u_long mask;
293
294 fprintf(file, ";; res options:");
295 if (!statp)
296 statp = &_res;
297 for (mask = 1; mask != 0; mask <<= 1)
298 if (statp->options & mask)
299 fprintf(file, " %s", p_option(mask));
300 putc('\n', file);
301 }
302
303 /*
304 * Print the contents of a query.
305 * This is intended to be primarily a debugging routine.
306 */
307 void
308 __fp_nquery(msg, len, file)
309 const u_char *msg;
310 int len;
311 FILE *file;
312 {
313 register const u_char *cp, *endMark;
314 register const HEADER *hp;
315 register int n;
316
317 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
318 return;
319
320 #define TruncTest(x) if (x >= endMark) goto trunc
321 #define ErrorTest(x) if (x == NULL) goto error
322
323 /*
324 * Print header fields.
325 */
326 hp = (HEADER *)msg;
327 cp = msg + HFIXEDSZ;
328 endMark = cp + len;
329 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
330 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
331 _res_opcodes[hp->opcode],
332 _res_resultcodes[hp->rcode],
333 ntohs(hp->id));
334 putc('\n', file);
335 }
336 putc(';', file);
337 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
338 fprintf(file, "; flags:");
339 if (hp->qr)
340 fprintf(file, " qr");
341 if (hp->aa)
342 fprintf(file, " aa");
343 if (hp->tc)
344 fprintf(file, " tc");
345 if (hp->rd)
346 fprintf(file, " rd");
347 if (hp->ra)
348 fprintf(file, " ra");
349 }
350 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
351 fprintf(file, "; Ques: %d", ntohs(hp->qdcount));
352 fprintf(file, ", Ans: %d", ntohs(hp->ancount));
353 fprintf(file, ", Auth: %d", ntohs(hp->nscount));
354 fprintf(file, ", Addit: %d", ntohs(hp->arcount));
355 }
356 if ((!_res.pfcode) || (_res.pfcode &
357 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
358 putc('\n',file);
359 }
360 /*
361 * Print question records.
362 */
363 if ((n = ntohs(hp->qdcount))) {
364 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
365 fprintf(file, ";; QUESTIONS:\n");
366 while (--n >= 0) {
367 fprintf(file, ";;\t");
368 TruncTest(cp);
369 cp = p_cdnname(cp, msg, len, file);
370 ErrorTest(cp);
371 TruncTest(cp);
372 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
373 fprintf(file, ", type = %s",
374 __p_type(_getshort((u_char*)cp)));
375 cp += INT16SZ;
376 TruncTest(cp);
377 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
378 fprintf(file, ", class = %s\n",
379 __p_class(_getshort((u_char*)cp)));
380 cp += INT16SZ;
381 putc('\n', file);
382 }
383 }
384 /*
385 * Print authoritative answer records
386 */
387 TruncTest(cp);
388 cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
389 ";; ANSWERS:\n");
390 ErrorTest(cp);
391
392 /*
393 * print name server records
394 */
395 TruncTest(cp);
396 cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
397 ";; AUTHORITY RECORDS:\n");
398 ErrorTest(cp);
399
400 TruncTest(cp);
401 /*
402 * print additional records
403 */
404 cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
405 ";; ADDITIONAL RECORDS:\n");
406 ErrorTest(cp);
407 return;
408 trunc:
409 fprintf(file, "\n;; ...truncated\n");
410 return;
411 error:
412 fprintf(file, "\n;; ...malformed\n");
413 }
414
415 void
416 __fp_query(msg, file)
417 const u_char *msg;
418 FILE *file;
419 {
420 fp_nquery(msg, PACKETSZ, file);
421 }
422
423 const u_char *
424 __p_cdnname(cp, msg, len, file)
425 const u_char *cp, *msg;
426 int len;
427 FILE *file;
428 {
429 char name[MAXDNAME];
430 int n;
431
432 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
433 return (NULL);
434 if (name[0] == '\0')
435 putc('.', file);
436 else
437 fputs(name, file);
438 return (cp + n);
439 }
440
441 const u_char *
442 __p_cdname(cp, msg, file)
443 const u_char *cp, *msg;
444 FILE *file;
445 {
446 return (p_cdnname(cp, msg, PACKETSZ, file));
447 }
448
449 /* XXX: the rest of these functions need to become length-limited, too. (vix)
450 */
451
452 const u_char *
453 __p_fqname(cp, msg, file)
454 const u_char *cp, *msg;
455 FILE *file;
456 {
457 char name[MAXDNAME];
458 int n;
459
460 if ((n = dn_expand(msg, cp + MAXCDNAME, cp, name, sizeof name)) < 0)
461 return (NULL);
462 if (name[0] == '\0') {
463 putc('.', file);
464 } else {
465 fputs(name, file);
466 if (name[strlen(name) - 1] != '.')
467 putc('.', file);
468 }
469 return (cp + n);
470 }
471
472 /*
473 * Print resource record fields in human readable form.
474 */
475 const u_char *
476 __p_rr(cp, msg, file)
477 const u_char *cp, *msg;
478 FILE *file;
479 {
480 int type, class, dlen, n, c;
481 struct in_addr inaddr;
482 const u_char *cp1, *cp2;
483 u_int32_t tmpttl, t;
484 int lcnt;
485
486 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
487 h_errno = NETDB_INTERNAL;
488 return (NULL);
489 }
490 if ((cp = p_fqname(cp, msg, file)) == NULL)
491 return (NULL); /* compression error */
492 type = _getshort((u_char*)cp);
493 cp += INT16SZ;
494 class = _getshort((u_char*)cp);
495 cp += INT16SZ;
496 tmpttl = _getlong((u_char*)cp);
497 cp += INT32SZ;
498 dlen = _getshort((u_char*)cp);
499 cp += INT16SZ;
500 cp1 = cp;
501 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
502 fprintf(file, "\t%lu", (u_long)tmpttl);
503 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS))
504 fprintf(file, "\t%s", __p_class(class));
505 fprintf(file, "\t%s", __p_type(type));
506 /*
507 * Print type specific data, if appropriate
508 */
509 switch (type) {
510 case T_A:
511 switch (class) {
512 case C_IN:
513 case C_HS:
514 bcopy(cp, (char *)&inaddr, INADDRSZ);
515 if (dlen == 4) {
516 fprintf(file, "\t%s", inet_ntoa(inaddr));
517 cp += dlen;
518 } else if (dlen == 7) {
519 char *address;
520 u_char protocol;
521 u_short port;
522
523 address = inet_ntoa(inaddr);
524 cp += INADDRSZ;
525 protocol = *(u_char*)cp;
526 cp += sizeof(u_char);
527 port = _getshort((u_char*)cp);
528 cp += INT16SZ;
529 fprintf(file, "\t%s\t; proto %d, port %d",
530 address, protocol, port);
531 }
532 break;
533 default:
534 cp += dlen;
535 }
536 break;
537 case T_CNAME:
538 case T_MB:
539 case T_MG:
540 case T_MR:
541 case T_NS:
542 case T_PTR:
543 putc('\t', file);
544 if ((cp = p_fqname(cp, msg, file)) == NULL)
545 return (NULL);
546 break;
547
548 case T_HINFO:
549 case T_ISDN:
550 cp2 = cp + dlen;
551 if ((n = *cp++)) {
552 fprintf(file, "\t%.*s", n, cp);
553 cp += n;
554 }
555 if ((cp < cp2) && (n = *cp++)) {
556 fprintf(file, "\t%.*s", n, cp);
557 cp += n;
558 } else if (type == T_HINFO)
559 fprintf(file, "\n;; *** Warning *** OS-type missing");
560 break;
561
562 case T_SOA:
563 putc('\t', file);
564 if ((cp = p_fqname(cp, msg, file)) == NULL)
565 return (NULL);
566 putc(' ', file);
567 if ((cp = p_fqname(cp, msg, file)) == NULL)
568 return (NULL);
569 fputs(" (\n", file);
570 t = _getlong((u_char*)cp); cp += INT32SZ;
571 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
572 t = _getlong((u_char*)cp); cp += INT32SZ;
573 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
574 (u_long)t, __p_time(t));
575 t = _getlong((u_char*)cp); cp += INT32SZ;
576 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
577 (u_long)t, __p_time(t));
578 t = _getlong((u_char*)cp); cp += INT32SZ;
579 fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
580 (u_long)t, __p_time(t));
581 t = _getlong((u_char*)cp); cp += INT32SZ;
582 fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
583 (u_long)t, __p_time(t));
584 break;
585
586 case T_MX:
587 case T_AFSDB:
588 case T_RT:
589 fprintf(file, "\t%d ", _getshort((u_char*)cp));
590 cp += INT16SZ;
591 if ((cp = p_fqname(cp, msg, file)) == NULL)
592 return (NULL);
593 break;
594
595 case T_PX:
596 fprintf(file, "\t%d ", _getshort((u_char*)cp));
597 cp += INT16SZ;
598 if ((cp = p_fqname(cp, msg, file)) == NULL)
599 return (NULL);
600 putc(' ', file);
601 if ((cp = p_fqname(cp, msg, file)) == NULL)
602 return (NULL);
603 break;
604
605 case T_TXT:
606 case T_X25:
607 (void) fputs("\t\"", file);
608 cp2 = cp1 + dlen;
609 while (cp < cp2) {
610 if ((n = (unsigned char) *cp++)) {
611 for (c = n; c > 0 && cp < cp2; c--)
612 if ((*cp == '\n') || (*cp == '"')) {
613 (void) putc('\\', file);
614 (void) putc(*cp++, file);
615 } else
616 (void) putc(*cp++, file);
617 }
618 }
619 putc('"', file);
620 break;
621
622 case T_NSAP:
623 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
624 cp += dlen;
625 break;
626
627 case T_MINFO:
628 case T_RP:
629 putc('\t', file);
630 if ((cp = p_fqname(cp, msg, file)) == NULL)
631 return (NULL);
632 putc(' ', file);
633 if ((cp = p_fqname(cp, msg, file)) == NULL)
634 return (NULL);
635 break;
636
637 case T_UINFO:
638 putc('\t', file);
639 fputs((char *)cp, file);
640 cp += dlen;
641 break;
642
643 case T_UID:
644 case T_GID:
645 if (dlen == 4) {
646 fprintf(file, "\t%u", _getlong((u_char*)cp));
647 cp += INT32SZ;
648 }
649 break;
650
651 case T_WKS:
652 if (dlen < INT32SZ + 1)
653 break;
654 bcopy(cp, (char *)&inaddr, INADDRSZ);
655 cp += INT32SZ;
656 fprintf(file, "\t%s %s ( ",
657 inet_ntoa(inaddr),
658 deproto((int) *cp));
659 cp += sizeof(u_char);
660 n = 0;
661 lcnt = 0;
662 while (cp < cp1 + dlen) {
663 c = *cp++;
664 do {
665 if (c & 0200) {
666 if (lcnt == 0) {
667 fputs("\n\t\t\t", file);
668 lcnt = 5;
669 }
670 fputs(dewks(n), file);
671 putc(' ', file);
672 lcnt--;
673 }
674 c <<= 1;
675 } while (++n & 07);
676 }
677 putc(')', file);
678 break;
679
680 #ifdef ALLOW_T_UNSPEC
681 case T_UNSPEC:
682 {
683 int NumBytes = 8;
684 u_char *DataPtr;
685 int i;
686
687 if (dlen < NumBytes) NumBytes = dlen;
688 fprintf(file, "\tFirst %d bytes of hex data:",
689 NumBytes);
690 for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
691 fprintf(file, " %x", *DataPtr);
692 cp += dlen;
693 }
694 break;
695 #endif /* ALLOW_T_UNSPEC */
696
697 default:
698 fprintf(file, "\t?%d?", type);
699 cp += dlen;
700 }
701 #if 0
702 fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
703 #else
704 putc('\n', file);
705 #endif
706 if (cp - cp1 != dlen) {
707 fprintf(file, ";; packet size error (found %d, dlen was %d)\n",
708 cp - cp1, dlen);
709 cp = NULL;
710 }
711 return (cp);
712 }
713
714 /*
715 * Return a string for the type
716 */
717 const char *
718 __p_type(type)
719 int type;
720 {
721 static char nbuf[20];
722
723 switch (type) {
724 case T_A: return "A";
725 case T_NS: return "NS";
726 case T_CNAME: return "CNAME";
727 case T_SOA: return "SOA";
728 case T_MB: return "MB";
729 case T_MG: return "MG";
730 case T_MR: return "MR";
731 case T_NULL: return "NULL";
732 case T_WKS: return "WKS";
733 case T_PTR: return "PTR";
734 case T_HINFO: return "HINFO";
735 case T_MINFO: return "MINFO";
736 case T_MX: return "MX";
737 case T_TXT: return "TXT";
738 case T_RP: return "RP";
739 case T_AFSDB: return "AFSDB";
740 case T_X25: return "X25";
741 case T_ISDN: return "ISDN";
742 case T_RT: return "RT";
743 case T_NSAP: return "NSAP";
744 case T_NSAP_PTR: return "NSAP_PTR";
745 case T_SIG: return "SIG";
746 case T_KEY: return "KEY";
747 case T_PX: return "PX";
748 case T_GPOS: return "GPOS";
749 case T_AAAA: return "AAAA";
750 case T_LOC: return "LOC";
751 case T_AXFR: return "AXFR";
752 case T_MAILB: return "MAILB";
753 case T_MAILA: return "MAILA";
754 case T_ANY: return "ANY";
755 case T_UINFO: return "UINFO";
756 case T_UID: return "UID";
757 case T_GID: return "GID";
758 #ifdef ALLOW_T_UNSPEC
759 case T_UNSPEC: return "UNSPEC";
760 #endif /* ALLOW_T_UNSPEC */
761 default: (void)sprintf(nbuf, "%d", type); return (nbuf);
762 }
763 }
764
765 /*
766 * Return a mnemonic for class
767 */
768 const char *
769 __p_class(class)
770 int class;
771 {
772 static char nbuf[20];
773
774 switch (class) {
775 case C_IN: return "IN";
776 case C_HS: return "HS";
777 case C_ANY: return "ANY";
778 default: (void)sprintf(nbuf, "%d", class); return (nbuf);
779 }
780 }
781
782 /*
783 * Return a mnemonic for an option
784 */
785 const char *
786 __p_option(option)
787 u_long option;
788 {
789 static char nbuf[40];
790
791 switch (option) {
792 case RES_INIT: return "init";
793 case RES_DEBUG: return "debug";
794 case RES_AAONLY: return "aaonly(unimpl)";
795 case RES_USEVC: return "usevc";
796 case RES_PRIMARY: return "primry(unimpl)";
797 case RES_IGNTC: return "igntc";
798 case RES_RECURSE: return "recurs";
799 case RES_DEFNAMES: return "defnam";
800 case RES_STAYOPEN: return "styopn";
801 case RES_DNSRCH: return "dnsrch";
802 case RES_INSECURE1: return "insecure1";
803 case RES_INSECURE2: return "insecure2";
804 default: sprintf(nbuf, "?0x%lx?", (u_long)option);
805 return (nbuf);
806 }
807 }
808
809 /*
810 * Return a mnemonic for a time to live
811 */
812 char *
813 __p_time(value)
814 u_int32_t value;
815 {
816 static char nbuf[40];
817 int secs, mins, hours, days;
818 register char *p;
819
820 if (value == 0) {
821 strcpy(nbuf, "0 secs");
822 return (nbuf);
823 }
824
825 secs = value % 60;
826 value /= 60;
827 mins = value % 60;
828 value /= 60;
829 hours = value % 24;
830 value /= 24;
831 days = value;
832 value = 0;
833
834 #define PLURALIZE(x) x, (x == 1) ? "" : "s"
835 p = nbuf;
836 if (days) {
837 (void)sprintf(p, "%d day%s", PLURALIZE(days));
838 while (*++p);
839 }
840 if (hours) {
841 if (days)
842 *p++ = ' ';
843 (void)sprintf(p, "%d hour%s", PLURALIZE(hours));
844 while (*++p);
845 }
846 if (mins) {
847 if (days || hours)
848 *p++ = ' ';
849 (void)sprintf(p, "%d min%s", PLURALIZE(mins));
850 while (*++p);
851 }
852 if (secs || ! (days || hours || mins)) {
853 if (days || hours || mins)
854 *p++ = ' ';
855 (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
856 }
857 return (nbuf);
858 }