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