2 * ++Copyright++ 1985, 1990, 1993
4 * Copyright (c) 1985, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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
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 <sys/types.h>
63 #include <sys/socket.h>
64 #include <netinet/in.h>
65 #include <arpa/inet.h>
66 #include <arpa/nameser.h>
71 #if defined(BSD) && (BSD >= 199103) && defined(AF_INET6)
74 # include "../conf/portability.h"
77 #if defined(USE_OPTIONS_H)
78 # include "../conf/options.h"
81 extern const char *_res_opcodes
[];
82 extern const char *_res_resultcodes
[];
84 /* XXX: we should use getservbyport() instead. */
93 case 7: return "echo";
94 case 9: return "discard";
95 case 11: return "systat";
96 case 13: return "daytime";
97 case 15: return "netstat";
98 case 17: return "qotd";
99 case 19: return "chargen";
100 case 20: return "ftp-data";
101 case 21: return "ftp";
102 case 23: return "telnet";
103 case 25: return "smtp";
104 case 37: return "time";
105 case 39: return "rlp";
106 case 42: return "name";
107 case 43: return "whois";
108 case 53: return "domain";
109 case 57: return "apts";
110 case 59: return "apfs";
111 case 67: return "bootps";
112 case 68: return "bootpc";
113 case 69: return "tftp";
114 case 77: return "rje";
115 case 79: return "finger";
116 case 87: return "link";
117 case 95: return "supdup";
118 case 100: return "newacct";
119 case 101: return "hostnames";
120 case 102: return "iso-tsap";
121 case 103: return "x400";
122 case 104: return "x400-snd";
123 case 105: return "csnet-ns";
124 case 109: return "pop-2";
125 case 111: return "sunrpc";
126 case 113: return "auth";
127 case 115: return "sftp";
128 case 117: return "uucp-path";
129 case 119: return "nntp";
130 case 121: return "erpc";
131 case 123: return "ntp";
132 case 133: return "statsrv";
133 case 136: return "profile";
134 case 144: return "NeWS";
135 case 161: return "snmp";
136 case 162: return "snmp-trap";
137 case 170: return "print-srv";
138 default: (void) sprintf(nbuf
, "%d", wks
); return (nbuf
);
142 /* XXX: we should use getprotobynumber() instead. */
147 static char nbuf
[20];
150 case 1: return "icmp";
151 case 2: return "igmp";
152 case 3: return "ggp";
154 case 6: return "tcp";
155 case 7: return "ucl";
156 case 8: return "egp";
157 case 9: return "igp";
158 case 11: return "nvp-II";
159 case 12: return "pup";
160 case 16: return "chaos";
161 case 17: return "udp";
162 default: (void) sprintf(nbuf
, "%d", protonum
); return (nbuf
);
166 static const u_char
*
167 do_rrset(msg
, len
, cp
, cnt
, pflag
, file
, hs
)
169 const u_char
*cp
, *msg
;
177 * Print answer records.
179 sflag
= (_res
.pfcode
& pflag
);
180 if (n
= ntohs(cnt
)) {
181 if ((!_res
.pfcode
) ||
182 ((sflag
) && (_res
.pfcode
& RES_PRF_HEAD1
)))
185 if ((!_res
.pfcode
) || sflag
) {
186 cp
= p_rr(cp
, msg
, file
);
189 cp
+= __dn_skipname(cp
, cp
+ MAXCDNAME
);
193 dlen
= _getshort((u_char
*)cp
);
197 if ((cp
- msg
) > len
)
200 if ((!_res
.pfcode
) ||
201 ((sflag
) && (_res
.pfcode
& RES_PRF_HEAD1
)))
211 __fp_query(msg
, stdout
);
215 /* ultrix 4.0's packaging has some icky packaging. alias for it here.
216 * there is more junk of this kind over in res_comp.c.
227 * Print the current options.
228 * This is intended to be primarily a debugging routine.
231 __fp_resstat(statp
, file
)
232 struct __res_state
*statp
;
235 register u_long mask
;
237 fprintf(file
, ";; res options:");
240 for (mask
= 1; mask
!= 0; mask
<<= 1)
241 if (statp
->options
& mask
)
242 fprintf(file
, " %s", p_option(mask
));
247 * Print the contents of a query.
248 * This is intended to be primarily a debugging routine.
251 __fp_nquery(msg
, len
, file
)
256 register const u_char
*cp
, *endMark
;
257 register const HEADER
*hp
;
260 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1)
263 #define TruncTest(x) if (x >= endMark) goto trunc
264 #define ErrorTest(x) if (x == NULL) goto error
267 * Print header fields.
272 if ((!_res
.pfcode
) || (_res
.pfcode
& RES_PRF_HEADX
) || hp
->rcode
) {
273 fprintf(file
, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
274 _res_opcodes
[hp
->opcode
],
275 _res_resultcodes
[hp
->rcode
],
279 if ((!_res
.pfcode
) || (_res
.pfcode
& RES_PRF_HEADX
))
281 if ((!_res
.pfcode
) || (_res
.pfcode
& RES_PRF_HEAD2
)) {
282 fprintf(file
, "; flags:");
284 fprintf(file
, " qr");
286 fprintf(file
, " aa");
288 fprintf(file
, " tc");
290 fprintf(file
, " rd");
292 fprintf(file
, " ra");
294 if ((!_res
.pfcode
) || (_res
.pfcode
& RES_PRF_HEAD1
)) {
295 fprintf(file
, "; Ques: %d", ntohs(hp
->qdcount
));
296 fprintf(file
, ", Ans: %d", ntohs(hp
->ancount
));
297 fprintf(file
, ", Auth: %d", ntohs(hp
->nscount
));
298 fprintf(file
, ", Addit: %d", ntohs(hp
->arcount
));
300 if ((!_res
.pfcode
) || (_res
.pfcode
&
301 (RES_PRF_HEADX
| RES_PRF_HEAD2
| RES_PRF_HEAD1
))) {
305 * Print question records.
307 if (n
= ntohs(hp
->qdcount
)) {
308 if ((!_res
.pfcode
) || (_res
.pfcode
& RES_PRF_QUES
))
309 fprintf(file
, ";; QUESTIONS:\n");
311 if ((!_res
.pfcode
) || (_res
.pfcode
& RES_PRF_QUES
))
312 fprintf(file
, ";;\t");
314 if ((!_res
.pfcode
) || (_res
.pfcode
& RES_PRF_QUES
))
315 cp
= p_cdnname(cp
, msg
, len
, file
);
320 if ((n
= dn_expand(msg
, msg
+len
, cp
, name
,
328 if ((!_res
.pfcode
) || (_res
.pfcode
& RES_PRF_QUES
))
329 fprintf(file
, ", type = %s",
330 __p_type(_getshort((u_char
*)cp
)));
333 if ((!_res
.pfcode
) || (_res
.pfcode
& RES_PRF_QUES
))
334 fprintf(file
, ", class = %s\n",
335 __p_class(_getshort((u_char
*)cp
)));
337 if ((!_res
.pfcode
) || (_res
.pfcode
& RES_PRF_QUES
))
342 * Print authoritative answer records
345 cp
= do_rrset(msg
, len
, cp
, hp
->ancount
, RES_PRF_ANS
, file
,
350 * print name server records
353 cp
= do_rrset(msg
, len
, cp
, hp
->nscount
, RES_PRF_AUTH
, file
,
354 ";; AUTHORITY RECORDS:\n");
359 * print additional records
361 cp
= do_rrset(msg
, len
, cp
, hp
->arcount
, RES_PRF_ADD
, file
,
362 ";; ADDITIONAL RECORDS:\n");
366 fprintf(file
, "\n;; ...truncated\n");
369 fprintf(file
, "\n;; ...malformed\n");
373 __fp_query(msg
, file
)
377 fp_nquery(msg
, PACKETSZ
, file
);
381 __p_cdnname(cp
, msg
, len
, file
)
382 const u_char
*cp
, *msg
;
389 if ((n
= dn_expand(msg
, msg
+ len
, cp
, name
, sizeof name
)) < 0)
399 __p_cdname(cp
, msg
, file
)
400 const u_char
*cp
, *msg
;
403 return (p_cdnname(cp
, msg
, PACKETSZ
, file
));
406 /* XXX: the rest of these functions need to become length-limited, too. (vix)
410 __p_fqname(cp
, msg
, file
)
411 const u_char
*cp
, *msg
;
417 if ((n
= dn_expand(msg
, cp
+ MAXCDNAME
, cp
, name
, sizeof name
)) < 0)
419 if (name
[0] == '\0') {
423 if (name
[strlen(name
) - 1] != '.')
430 * Print resource record fields in human readable form.
433 __p_rr(cp
, msg
, file
)
434 const u_char
*cp
, *msg
;
437 int type
, class, dlen
, n
, c
;
438 struct in_addr inaddr
;
439 const u_char
*cp1
, *cp2
;
443 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1) {
444 h_errno
= NETDB_INTERNAL
;
447 if ((cp
= p_fqname(cp
, msg
, file
)) == NULL
)
448 return (NULL
); /* compression error */
449 type
= _getshort((u_char
*)cp
);
451 class = _getshort((u_char
*)cp
);
453 tmpttl
= _getlong((u_char
*)cp
);
455 dlen
= _getshort((u_char
*)cp
);
458 if ((!_res
.pfcode
) || (_res
.pfcode
& RES_PRF_TTLID
))
459 fprintf(file
, "\t%lu", (u_long
)tmpttl
);
460 if ((!_res
.pfcode
) || (_res
.pfcode
& RES_PRF_CLASS
))
461 fprintf(file
, "\t%s", __p_class(class));
462 fprintf(file
, "\t%s", __p_type(type
));
464 * Print type specific data, if appropriate
471 bcopy(cp
, (char *)&inaddr
, INADDRSZ
);
473 fprintf(file
, "\t%s", inet_ntoa(inaddr
));
475 } else if (dlen
== 7) {
480 address
= inet_ntoa(inaddr
);
482 protocol
= *(u_char
*)cp
;
483 cp
+= sizeof(u_char
);
484 port
= _getshort((u_char
*)cp
);
486 fprintf(file
, "\t%s\t; proto %d, port %d",
487 address
, protocol
, port
);
501 if ((cp
= p_fqname(cp
, msg
, file
)) == NULL
)
507 (void) fputs("\t\"", file
);
509 if ((n
= (unsigned char) *cp
++) != 0) {
510 for (c
= n
; c
> 0 && cp
< cp2
; c
--) {
511 if (strchr("\n\"\\", *cp
))
512 (void) putc('\\', file
);
513 (void) putc(*cp
++, file
);
517 if (cp
< cp2
&& (n
= (unsigned char) *cp
++) != 0) {
518 (void) fputs ("\t\"", file
);
519 for (c
= n
; c
> 0 && cp
< cp2
; c
--) {
520 if (strchr("\n\"\\", *cp
))
521 (void) putc('\\', file
);
522 (void) putc(*cp
++, file
);
525 } else if (type
== T_HINFO
) {
526 (void) fputs("\"?\"", file
);
527 fprintf(file
, "\n;; *** Warning *** OS-type missing");
533 if ((cp
= p_fqname(cp
, msg
, file
)) == NULL
)
536 if ((cp
= p_fqname(cp
, msg
, file
)) == NULL
)
539 t
= _getlong((u_char
*)cp
); cp
+= INT32SZ
;
540 fprintf(file
, "\t\t\t%lu\t; serial\n", (u_long
)t
);
541 t
= _getlong((u_char
*)cp
); cp
+= INT32SZ
;
542 fprintf(file
, "\t\t\t%lu\t; refresh (%s)\n",
543 (u_long
)t
, __p_time(t
));
544 t
= _getlong((u_char
*)cp
); cp
+= INT32SZ
;
545 fprintf(file
, "\t\t\t%lu\t; retry (%s)\n",
546 (u_long
)t
, __p_time(t
));
547 t
= _getlong((u_char
*)cp
); cp
+= INT32SZ
;
548 fprintf(file
, "\t\t\t%lu\t; expire (%s)\n",
549 (u_long
)t
, __p_time(t
));
550 t
= _getlong((u_char
*)cp
); cp
+= INT32SZ
;
551 fprintf(file
, "\t\t\t%lu )\t; minimum (%s)",
552 (u_long
)t
, __p_time(t
));
558 fprintf(file
, "\t%d ", _getshort((u_char
*)cp
));
560 if ((cp
= p_fqname(cp
, msg
, file
)) == NULL
)
565 fprintf(file
, "\t%d ", _getshort((u_char
*)cp
));
567 if ((cp
= p_fqname(cp
, msg
, file
)) == NULL
)
570 if ((cp
= p_fqname(cp
, msg
, file
)) == NULL
)
576 (void) fputs("\t\"", file
);
579 if (n
= (unsigned char) *cp
++) {
580 for (c
= n
; c
> 0 && cp
< cp2
; c
--) {
581 if (strchr("\n\"\\", *cp
))
582 (void) putc('\\', file
);
583 (void) putc(*cp
++, file
);
591 (void) fprintf(file
, "\t%s", inet_nsap_ntoa(dlen
, cp
, NULL
));
596 char t
[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
598 fprintf(file
, "\t%s\n", inet_ntop(AF_INET6
, cp
, t
, sizeof t
));
605 if ((cp
= p_fqname(cp
, msg
, file
)) == NULL
)
608 if ((cp
= p_fqname(cp
, msg
, file
)) == NULL
)
614 fputs((char *)cp
, file
);
621 fprintf(file
, "\t%u", _getlong((u_char
*)cp
));
627 if (dlen
< INT32SZ
+ 1)
629 bcopy(cp
, (char *)&inaddr
, INADDRSZ
);
631 fprintf(file
, "\t%s %s ( ",
634 cp
+= sizeof(u_char
);
637 while (cp
< cp1
+ dlen
) {
642 fputs("\n\t\t\t", file
);
645 fputs(dewks(n
), file
);
655 #ifdef ALLOW_T_UNSPEC
662 if (dlen
< NumBytes
) NumBytes
= dlen
;
663 fprintf(file
, "\tFirst %d bytes of hex data:",
665 for (i
= 0, DataPtr
= cp
; i
< NumBytes
; i
++, DataPtr
++)
666 fprintf(file
, " %x", *DataPtr
);
670 #endif /* ALLOW_T_UNSPEC */
673 fprintf(file
, "\t?%d?", type
);
677 fprintf(file
, "\t; dlen=%d, ttl %s\n", dlen
, __p_time(tmpttl
));
681 if (cp
- cp1
!= dlen
) {
682 fprintf(file
, ";; packet size error (found %d, dlen was %d)\n",
690 * Return a string for the type
696 static char nbuf
[20];
699 case T_A
: return "A";
700 case T_NS
: return "NS";
701 case T_CNAME
: return "CNAME";
702 case T_SOA
: return "SOA";
703 case T_MB
: return "MB";
704 case T_MG
: return "MG";
705 case T_MR
: return "MR";
706 case T_NULL
: return "NULL";
707 case T_WKS
: return "WKS";
708 case T_PTR
: return "PTR";
709 case T_HINFO
: return "HINFO";
710 case T_MINFO
: return "MINFO";
711 case T_MX
: return "MX";
712 case T_TXT
: return "TXT";
713 case T_RP
: return "RP";
714 case T_AFSDB
: return "AFSDB";
715 case T_X25
: return "X25";
716 case T_ISDN
: return "ISDN";
717 case T_RT
: return "RT";
718 case T_NSAP
: return "NSAP";
719 case T_NSAP_PTR
: return "NSAP_PTR";
720 case T_SIG
: return "SIG";
721 case T_KEY
: return "KEY";
722 case T_PX
: return "PX";
723 case T_GPOS
: return "GPOS";
724 case T_AAAA
: return "AAAA";
725 case T_LOC
: return "LOC";
726 case T_AXFR
: return "AXFR";
727 case T_MAILB
: return "MAILB";
728 case T_MAILA
: return "MAILA";
729 case T_ANY
: return "ANY";
730 case T_UINFO
: return "UINFO";
731 case T_UID
: return "UID";
732 case T_GID
: return "GID";
733 #ifdef ALLOW_T_UNSPEC
734 case T_UNSPEC
: return "UNSPEC";
735 #endif /* ALLOW_T_UNSPEC */
736 default: (void)sprintf(nbuf
, "%d", type
); return (nbuf
);
741 * Return a mnemonic for class
747 static char nbuf
[20];
750 case C_IN
: return "IN";
751 case C_HS
: return "HS";
752 case C_ANY
: return "ANY";
753 default: (void)sprintf(nbuf
, "%d", class); return (nbuf
);
758 * Return a mnemonic for an option
764 static char nbuf
[40];
767 case RES_INIT
: return "init";
768 case RES_DEBUG
: return "debug";
769 case RES_AAONLY
: return "aaonly(unimpl)";
770 case RES_USEVC
: return "usevc";
771 case RES_PRIMARY
: return "primry(unimpl)";
772 case RES_IGNTC
: return "igntc";
773 case RES_RECURSE
: return "recurs";
774 case RES_DEFNAMES
: return "defnam";
775 case RES_STAYOPEN
: return "styopn";
776 case RES_DNSRCH
: return "dnsrch";
777 case RES_INSECURE1
: return "insecure1";
778 case RES_INSECURE2
: return "insecure2";
779 default: sprintf(nbuf
, "?0x%lx?", (u_long
)option
);
785 * Return a mnemonic for a time to live
791 static char nbuf
[40];
792 int secs
, mins
, hours
, days
;
796 strcpy(nbuf
, "0 secs");
809 #define PLURALIZE(x) x, (x == 1) ? "" : "s"
812 (void)sprintf(p
, "%d day%s", PLURALIZE(days
));
818 (void)sprintf(p
, "%d hour%s", PLURALIZE(hours
));
824 (void)sprintf(p
, "%d min%s", PLURALIZE(mins
));
827 if (secs
|| ! (days
|| hours
|| mins
)) {
828 if (days
|| hours
|| mins
)
830 (void)sprintf(p
, "%d sec%s", PLURALIZE(secs
));