]> git.saurik.com Git - apple/libinfo.git/blob - dns.subproj/res_debug.c
Libinfo-221.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 * 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.5 2004/06/11 23:16:00 majka 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/nameser8_compat.h>
88
89 #include <stdio.h>
90 #include <netdb.h>
91 #include <resolv8_compat.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, n, c;
480 long dlen;
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 %ld, dlen was %ld)\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 }