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