]> git.ipfire.org Git - thirdparty/glibc.git/blame - resolv/res_debug.c
initial import
[thirdparty/glibc.git] / resolv / res_debug.c
CommitLineData
28f540f4
RM
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.
22 *
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.
36 *
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.
43 *
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--
54 */
55
56#if defined(LIBC_SCCS) && !defined(lint)
57static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
58static char rcsid[] = "$Id$";
59#endif /* LIBC_SCCS and not lint */
60
61#include <sys/param.h>
62#include <netinet/in.h>
63#include <arpa/inet.h>
64#include <arpa/nameser.h>
65
66#include <stdio.h>
67#include <resolv.h>
68#if defined(BSD) && (BSD >= 199103)
69# include <string.h>
70#else
71# include "../conf/portability.h"
72#endif
73
74#if defined(USE_OPTIONS_H)
75# include "../conf/options.h"
76#endif
77
78const char *_res_opcodes[] = {
79 "QUERY",
80 "IQUERY",
81 "CQUERYM",
82 "CQUERYU", /* experimental */
83 "NOTIFY", /* experimental */
84 "5",
85 "6",
86 "7",
87 "8",
88 "UPDATEA",
89 "UPDATED",
90 "UPDATEDA",
91 "UPDATEM",
92 "UPDATEMA",
93 "ZONEINIT",
94 "ZONEREF",
95};
96
97const char *_res_resultcodes[] = {
98 "NOERROR",
99 "FORMERR",
100 "SERVFAIL",
101 "NXDOMAIN",
102 "NOTIMP",
103 "REFUSED",
104 "6",
105 "7",
106 "8",
107 "9",
108 "10",
109 "11",
110 "12",
111 "13",
112 "14",
113 "NOCHANGE",
114};
115
116static char retbuf[16];
117
118static const char *
119dewks(wks)
120 int wks;
121{
122 switch (wks) {
123 case 5: return "rje";
124 case 7: return "echo";
125 case 9: return "discard";
126 case 11: return "systat";
127 case 13: return "daytime";
128 case 15: return "netstat";
129 case 17: return "qotd";
130 case 19: return "chargen";
131 case 20: return "ftp-data";
132 case 21: return "ftp";
133 case 23: return "telnet";
134 case 25: return "smtp";
135 case 37: return "time";
136 case 39: return "rlp";
137 case 42: return "name";
138 case 43: return "whois";
139 case 53: return "domain";
140 case 57: return "apts";
141 case 59: return "apfs";
142 case 67: return "bootps";
143 case 68: return "bootpc";
144 case 69: return "tftp";
145 case 77: return "rje";
146 case 79: return "finger";
147 case 87: return "link";
148 case 95: return "supdup";
149 case 100: return "newacct";
150 case 101: return "hostnames";
151 case 102: return "iso-tsap";
152 case 103: return "x400";
153 case 104: return "x400-snd";
154 case 105: return "csnet-ns";
155 case 109: return "pop-2";
156 case 111: return "sunrpc";
157 case 113: return "auth";
158 case 115: return "sftp";
159 case 117: return "uucp-path";
160 case 119: return "nntp";
161 case 121: return "erpc";
162 case 123: return "ntp";
163 case 133: return "statsrv";
164 case 136: return "profile";
165 case 144: return "NeWS";
166 case 161: return "snmp";
167 case 162: return "snmp-trap";
168 case 170: return "print-srv";
169 default: (void) sprintf(retbuf, "%d", wks); return (retbuf);
170 }
171}
172
173static const char *
174deproto(protonum)
175 int protonum;
176{
177 switch (protonum) {
178 case 1: return "icmp";
179 case 2: return "igmp";
180 case 3: return "ggp";
181 case 5: return "st";
182 case 6: return "tcp";
183 case 7: return "ucl";
184 case 8: return "egp";
185 case 9: return "igp";
186 case 11: return "nvp-II";
187 case 12: return "pup";
188 case 16: return "chaos";
189 case 17: return "udp";
190 default: (void) sprintf(retbuf, "%d", protonum); return (retbuf);
191 }
192}
193
194static const u_char *
195do_rrset(msg, cp, cnt, pflag, file, hs)
196 int cnt, pflag;
197 const u_char *cp, *msg;
198 const char *hs;
199 FILE *file;
200{
201 int n;
202 int sflag;
203
204 /*
205 * Print answer records.
206 */
207 sflag = (_res.pfcode & pflag);
208 if (n = ntohs(cnt)) {
209 if ((!_res.pfcode) ||
210 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
211 fprintf(file, hs);
212 while (--n >= 0) {
213 if ((!_res.pfcode) || sflag) {
214 cp = p_rr(cp, msg, file);
215 } else {
216 unsigned int dlen;
217 cp += __dn_skipname(cp, cp + MAXCDNAME);
218 cp += INT16SZ;
219 cp += INT16SZ;
220 cp += INT32SZ;
221 dlen = _getshort((u_char*)cp);
222 cp += INT16SZ;
223 cp += dlen;
224 }
225 if ((cp - msg) > PACKETSZ)
226 return (NULL);
227 }
228 if ((!_res.pfcode) ||
229 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
230 putc('\n', file);
231 }
232 return (cp);
233}
234
235void
236__p_query(msg)
237 const u_char *msg;
238{
239 __fp_query(msg, stdout);
240}
241
242#ifdef ultrix
243/* ultrix 4.0's packaging has some icky packaging. alias for it here.
244 * there is more junk of this kind over in res_comp.c.
245 */
246void
247p_query(msg)
248 const u_char *msg;
249{
250 __p_query(msg);
251}
252#endif
253
254/*
255 * Print the current options.
256 * This is intended to be primarily a debugging routine.
257 */
258void
259__fp_resstat(statp, file)
260 struct __res_state *statp;
261 FILE *file;
262{
263 register u_long mask;
264
265 fprintf(file, ";; res options:");
266 if (!statp)
267 statp = &_res;
268 for (mask = 1; mask != 0; mask <<= 1)
269 if (statp->options & mask)
270 fprintf(file, " %s", p_option(mask));
271 putc('\n', file);
272}
273
274/*
275 * Print the contents of a query.
276 * This is intended to be primarily a debugging routine.
277 */
278void
279__fp_nquery(msg, len, file)
280 const u_char *msg;
281 int len;
282 FILE *file;
283{
284 register const u_char *cp, *endMark;
285 register const HEADER *hp;
286 register int n;
287
288#define TruncTest(x) if (x >= endMark) goto trunc
289#define ErrorTest(x) if (x == NULL) goto error
290
291 /*
292 * Print header fields.
293 */
294 hp = (HEADER *)msg;
295 cp = msg + HFIXEDSZ;
296 endMark = cp + len;
297 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
298 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
299 _res_opcodes[hp->opcode],
300 _res_resultcodes[hp->rcode],
301 ntohs(hp->id));
302 putc('\n', file);
303 }
304 putc(';', file);
305 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
306 fprintf(file, "; flags:");
307 if (hp->qr)
308 fprintf(file, " qr");
309 if (hp->aa)
310 fprintf(file, " aa");
311 if (hp->tc)
312 fprintf(file, " tc");
313 if (hp->rd)
314 fprintf(file, " rd");
315 if (hp->ra)
316 fprintf(file, " ra");
317 if (hp->pr)
318 fprintf(file, " pr");
319 }
320 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
321 fprintf(file, "; Ques: %d", ntohs(hp->qdcount));
322 fprintf(file, ", Ans: %d", ntohs(hp->ancount));
323 fprintf(file, ", Auth: %d", ntohs(hp->nscount));
324 fprintf(file, ", Addit: %d", ntohs(hp->arcount));
325 }
326 if ((!_res.pfcode) || (_res.pfcode &
327 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
328 putc('\n',file);
329 }
330 /*
331 * Print question records.
332 */
333 if (n = ntohs(hp->qdcount)) {
334 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
335 fprintf(file, ";; QUESTIONS:\n");
336 while (--n >= 0) {
337 fprintf(file, ";;\t");
338 TruncTest(cp);
339 cp = p_cdname(cp, msg, file);
340 ErrorTest(cp);
341 TruncTest(cp);
342 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
343 fprintf(file, ", type = %s",
344 __p_type(_getshort((u_char*)cp)));
345 cp += INT16SZ;
346 TruncTest(cp);
347 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
348 fprintf(file, ", class = %s\n",
349 __p_class(_getshort((u_char*)cp)));
350 cp += INT16SZ;
351 putc('\n', file);
352 }
353 }
354 /*
355 * Print authoritative answer records
356 */
357 TruncTest(cp);
358 cp = do_rrset(msg, cp, hp->ancount, RES_PRF_ANS, file,
359 ";; ANSWERS:\n");
360 ErrorTest(cp);
361
362 /*
363 * print name server records
364 */
365 TruncTest(cp);
366 cp = do_rrset(msg, cp, hp->nscount, RES_PRF_AUTH, file,
367 ";; AUTHORITY RECORDS:\n");
368 ErrorTest(cp);
369
370 TruncTest(cp);
371 /*
372 * print additional records
373 */
374 cp = do_rrset(msg, cp, hp->arcount, RES_PRF_ADD, file,
375 ";; ADDITIONAL RECORDS:\n");
376 ErrorTest(cp);
377 return;
378 trunc:
379 fprintf(file, "\n;; ...truncated\n");
380 return;
381 error:
382 fprintf(file, "\n;; ...malformed\n");
383}
384
385void
386__fp_query(msg, file)
387 const u_char *msg;
388 FILE *file;
389{
390 fp_nquery(msg, PACKETSZ, file);
391}
392
393const u_char *
394__p_cdnname(cp, msg, len, file)
395 const u_char *cp, *msg;
396 int len;
397 FILE *file;
398{
399 char name[MAXDNAME];
400 int n;
401
402 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
403 return (NULL);
404 if (name[0] == '\0')
405 putc('.', file);
406 else
407 fputs(name, file);
408 return (cp + n);
409}
410
411const u_char *
412__p_cdname(cp, msg, file)
413 const u_char *cp, *msg;
414 FILE *file;
415{
416 return (p_cdnname(cp, msg, PACKETSZ, file));
417}
418
419/* XXX: the rest of these functions need to become length-limited, too. (vix)
420 */
421
422const u_char *
423__p_fqname(cp, msg, file)
424 const u_char *cp, *msg;
425 FILE *file;
426{
427 char name[MAXDNAME];
428 int n, len;
429
430 if ((n = dn_expand(msg, cp + MAXCDNAME, cp, name, sizeof name)) < 0)
431 return (NULL);
432 if (name[0] == '\0') {
433 putc('.', file);
434 } else {
435 fputs(name, file);
436 if (name[strlen(name) - 1] != '.')
437 putc('.', file);
438 }
439 return (cp + n);
440}
441
442/*
443 * Print resource record fields in human readable form.
444 */
445const u_char *
446__p_rr(cp, msg, file)
447 const u_char *cp, *msg;
448 FILE *file;
449{
450 int type, class, dlen, n, c;
451 struct in_addr inaddr;
452 const u_char *cp1, *cp2;
453 u_int32_t tmpttl, t;
454 int lcnt;
455
456 if ((cp = p_fqname(cp, msg, file)) == NULL)
457 return (NULL); /* compression error */
458 type = _getshort((u_char*)cp);
459 cp += INT16SZ;
460 class = _getshort((u_char*)cp);
461 cp += INT16SZ;
462 tmpttl = _getlong((u_char*)cp);
463 cp += INT32SZ;
464 dlen = _getshort((u_char*)cp);
465 cp += INT16SZ;
466 cp1 = cp;
467 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
468 fprintf(file, "\t%lu", tmpttl);
469 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS))
470 fprintf(file, "\t%s", __p_class(class));
471 fprintf(file, "\t%s", __p_type(type));
472 /*
473 * Print type specific data, if appropriate
474 */
475 switch (type) {
476 case T_A:
477 switch (class) {
478 case C_IN:
479 case C_HS:
480 bcopy(cp, (char *)&inaddr, INADDRSZ);
481 if (dlen == 4) {
482 fprintf(file, "\t%s", inet_ntoa(inaddr));
483 cp += dlen;
484 } else if (dlen == 7) {
485 char *address;
486 u_char protocol;
487 u_short port;
488
489 address = inet_ntoa(inaddr);
490 cp += INADDRSZ;
491 protocol = *(u_char*)cp;
492 cp += sizeof(u_char);
493 port = _getshort((u_char*)cp);
494 cp += INT16SZ;
495 fprintf(file, "\t%s\t; proto %d, port %d",
496 address, protocol, port);
497 }
498 break;
499 default:
500 cp += dlen;
501 }
502 break;
503 case T_CNAME:
504 case T_MB:
505 case T_MG:
506 case T_MR:
507 case T_NS:
508 case T_PTR:
509 putc('\t', file);
510 if ((cp = p_fqname(cp, msg, file)) == NULL)
511 return (NULL);
512 break;
513
514 case T_HINFO:
515 case T_ISDN:
516 cp2 = cp + dlen;
517 if (n = *cp++) {
518 fprintf(file, "\t%.*s", n, cp);
519 cp += n;
520 }
521 if ((cp < cp2) && (n = *cp++)) {
522 fprintf(file, "\t%.*s", n, cp);
523 cp += n;
524 } else if (type == T_HINFO)
525 fprintf(file, "\n;; *** Warning *** OS-type missing");
526 break;
527
528 case T_SOA:
529 putc('\t', file);
530 if ((cp = p_fqname(cp, msg, file)) == NULL)
531 return (NULL);
532 putc(' ', file);
533 if ((cp = p_fqname(cp, msg, file)) == NULL)
534 return (NULL);
535 fputs(" (\n", file);
536 t = _getlong((u_char*)cp); cp += INT32SZ;
537 fprintf(file, "\t\t\t%lu\t; serial\n", t);
538 t = _getlong((u_char*)cp); cp += INT32SZ;
539 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n", t, __p_time(t));
540 t = _getlong((u_char*)cp); cp += INT32SZ;
541 fprintf(file, "\t\t\t%lu\t; retry (%s)\n", t, __p_time(t));
542 t = _getlong((u_char*)cp); cp += INT32SZ;
543 fprintf(file, "\t\t\t%lu\t; expire (%s)\n", t, __p_time(t));
544 t = _getlong((u_char*)cp); cp += INT32SZ;
545 fprintf(file, "\t\t\t%lu )\t; minimum (%s)", t, __p_time(t));
546 break;
547
548 case T_MX:
549 case T_AFSDB:
550 case T_RT:
551 fprintf(file, "\t%d ", _getshort((u_char*)cp));
552 cp += INT16SZ;
553 if ((cp = p_fqname(cp, msg, file)) == NULL)
554 return (NULL);
555 break;
556
557 case T_PX:
558 fprintf(file, "\t%d ", _getshort((u_char*)cp));
559 cp += INT16SZ;
560 if ((cp = p_fqname(cp, msg, file)) == NULL)
561 return (NULL);
562 putc(' ', file);
563 if ((cp = p_fqname(cp, msg, file)) == NULL)
564 return (NULL);
565 break;
566
567 case T_TXT:
568 case T_X25:
569 (void) fputs("\t\"", file);
570 cp2 = cp1 + dlen;
571 while (cp < cp2) {
572 if (n = (unsigned char) *cp++) {
573 for (c = n; c > 0 && cp < cp2; c--)
574 if ((*cp == '\n') || (*cp == '"')) {
575 (void) putc('\\', file);
576 (void) putc(*cp++, file);
577 } else
578 (void) putc(*cp++, file);
579 }
580 }
581 putc('"', file);
582 break;
583
584 case T_NSAP:
585 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
586 cp += dlen;
587 break;
588
589 case T_MINFO:
590 case T_RP:
591 putc('\t', file);
592 if ((cp = p_fqname(cp, msg, file)) == NULL)
593 return (NULL);
594 putc(' ', file);
595 if ((cp = p_fqname(cp, msg, file)) == NULL)
596 return (NULL);
597 break;
598
599 case T_UINFO:
600 putc('\t', file);
601 fputs((char *)cp, file);
602 cp += dlen;
603 break;
604
605 case T_UID:
606 case T_GID:
607 if (dlen == 4) {
608 fprintf(file, "\t%u", _getlong((u_char*)cp));
609 cp += INT32SZ;
610 }
611 break;
612
613 case T_WKS:
614 if (dlen < INT32SZ + 1)
615 break;
616 bcopy(cp, (char *)&inaddr, INADDRSZ);
617 cp += INT32SZ;
618 fprintf(file, "\t%s %s ( ",
619 inet_ntoa(inaddr),
620 deproto((int) *cp));
621 cp += sizeof(u_char);
622 n = 0;
623 lcnt = 0;
624 while (cp < cp1 + dlen) {
625 c = *cp++;
626 do {
627 if (c & 0200) {
628 if (lcnt == 0) {
629 fputs("\n\t\t\t", file);
630 lcnt = 5;
631 }
632 fputs(dewks(n), file);
633 putc(' ', file);
634 lcnt--;
635 }
636 c <<= 1;
637 } while (++n & 07);
638 }
639 putc(')', file);
640 break;
641
642#ifdef ALLOW_T_UNSPEC
643 case T_UNSPEC:
644 {
645 int NumBytes = 8;
646 u_char *DataPtr;
647 int i;
648
649 if (dlen < NumBytes) NumBytes = dlen;
650 fprintf(file, "\tFirst %d bytes of hex data:",
651 NumBytes);
652 for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
653 fprintf(file, " %x", *DataPtr);
654 cp += dlen;
655 }
656 break;
657#endif /* ALLOW_T_UNSPEC */
658
659 default:
660 fprintf(file, "\t?%d?", type);
661 cp += dlen;
662 }
663#if 0
664 fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
665#else
666 putc('\n', file);
667#endif
668 if (cp - cp1 != dlen) {
669 fprintf(file, ";; packet size error (found %d, dlen was %d)\n",
670 cp - cp1, dlen);
671 cp = NULL;
672 }
673 return (cp);
674}
675
676static char nbuf[40];
677
678/*
679 * Return a string for the type
680 */
681const char *
682__p_type(type)
683 int type;
684{
685 switch (type) {
686 case T_A: return "A";
687 case T_NS: return "NS";
688 case T_CNAME: return "CNAME";
689 case T_SOA: return "SOA";
690 case T_MB: return "MB";
691 case T_MG: return "MG";
692 case T_MR: return "MR";
693 case T_NULL: return "NULL";
694 case T_WKS: return "WKS";
695 case T_PTR: return "PTR";
696 case T_HINFO: return "HINFO";
697 case T_MINFO: return "MINFO";
698 case T_MX: return "MX";
699 case T_TXT: return "TXT";
700 case T_RP: return "RP";
701 case T_AFSDB: return "AFSDB";
702 case T_X25: return "X25";
703 case T_ISDN: return "ISDN";
704 case T_RT: return "RT";
705 case T_NSAP: return "NSAP";
706 case T_NSAP_PTR: return "NSAP_PTR";
707 case T_SIG: return "SIG";
708 case T_KEY: return "KEY";
709 case T_PX: return "PX";
710 case T_GPOS: return "GPOS";
711 case T_AAAA: return "AAAA";
712 case T_LOC: return "LOC";
713 case T_AXFR: return "AXFR";
714 case T_MAILB: return "MAILB";
715 case T_MAILA: return "MAILA";
716 case T_ANY: return "ANY";
717 case T_UINFO: return "UINFO";
718 case T_UID: return "UID";
719 case T_GID: return "GID";
720#ifdef ALLOW_T_UNSPEC
721 case T_UNSPEC: return "UNSPEC";
722#endif /* ALLOW_T_UNSPEC */
723 default: (void)sprintf(nbuf, "%d", type); return (nbuf);
724 }
725}
726
727/*
728 * Return a mnemonic for class
729 */
730const char *
731__p_class(class)
732 int class;
733{
734 switch (class) {
735 case C_IN: return "IN";
736 case C_HS: return "HS";
737 case C_ANY: return "ANY";
738 default: (void)sprintf(nbuf, "%d", class); return (nbuf);
739 }
740}
741
742/*
743 * Return a mnemonic for an option
744 */
745const char *
746__p_option(option)
747 u_long option;
748{
749 switch (option) {
750 case RES_INIT: return "init";
751 case RES_DEBUG: return "debug";
752 case RES_AAONLY: return "aaonly";
753 case RES_USEVC: return "usevc";
754 case RES_PRIMARY: return "primry";
755 case RES_IGNTC: return "igntc";
756 case RES_RECURSE: return "recurs";
757 case RES_DEFNAMES: return "defnam";
758 case RES_STAYOPEN: return "styopn";
759 case RES_DNSRCH: return "dnsrch";
760 case RES_INSECURE1: return "insecure1";
761 case RES_INSECURE2: return "insecure2";
762 default: sprintf(nbuf, "?0x%x?", option); return (nbuf);
763 }
764}
765
766/*
767 * Return a mnemonic for a time to live
768 */
769char *
770__p_time(value)
771 u_int32_t value;
772{
773 int secs, mins, hours, days;
774 register char *p;
775
776 if (value == 0) {
777 strcpy(nbuf, "0 secs");
778 return (nbuf);
779 }
780
781 secs = value % 60;
782 value /= 60;
783 mins = value % 60;
784 value /= 60;
785 hours = value % 24;
786 value /= 24;
787 days = value;
788 value = 0;
789
790#define PLURALIZE(x) x, (x == 1) ? "" : "s"
791 p = nbuf;
792 if (days) {
793 (void)sprintf(p, "%d day%s", PLURALIZE(days));
794 while (*++p);
795 }
796 if (hours) {
797 if (days)
798 *p++ = ' ';
799 (void)sprintf(p, "%d hour%s", PLURALIZE(hours));
800 while (*++p);
801 }
802 if (mins) {
803 if (days || hours)
804 *p++ = ' ';
805 (void)sprintf(p, "%d min%s", PLURALIZE(mins));
806 while (*++p);
807 }
808 if (secs || ! (days || hours || mins)) {
809 if (days || hours || mins)
810 *p++ = ' ';
811 (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
812 }
813 return (nbuf);
814}