Update.
[glibc.git] / resolv / res_debug.c
blobdfb3b4706f98ff3de05ed37b7d525eaf11433a28
1 /*
2 * ++Copyright++ 1985, 1990, 1993
3 * -
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
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 * Portions Copyright (c) 1995 by International Business Machines, Inc.
55 * International Business Machines, Inc. (hereinafter called IBM) grants
56 * permission under its copyrights to use, copy, modify, and distribute this
57 * Software with or without fee, provided that the above copyright notice and
58 * all paragraphs of this notice appear in all copies, and that the name of IBM
59 * not be used in connection with the marketing of any product incorporating
60 * the Software or modifications thereof, without specific, written prior
61 * permission.
63 * To the extent it has a right to do so, IBM grants an immunity from suit
64 * under its patents, if any, for the use, sale or manufacture of products to
65 * the extent that such products are used for performing Domain Name System
66 * dynamic updates in TCP/IP networks by means of the Software. No immunity is
67 * granted for any product per se or for any other function of any product.
69 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
70 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
71 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
72 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
73 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
74 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
75 * --Copyright--
78 #if defined(LIBC_SCCS) && !defined(lint)
79 static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
80 static char rcsid[] = "$Id$";
81 #endif /* LIBC_SCCS and not lint */
83 #include <sys/param.h>
84 #include <sys/types.h>
85 #include <sys/socket.h>
86 #include <netinet/in.h>
87 #include <arpa/inet.h>
88 #include <arpa/nameser.h>
90 #include <ctype.h>
91 #include <netdb.h>
92 #include <resolv.h>
93 #include <stdio.h>
94 #include <time.h>
96 #if defined(BSD) && (BSD >= 199103) && defined(AF_INET6)
97 # include <stdlib.h>
98 # include <string.h>
99 #else
100 # include "../conf/portability.h"
101 #endif
103 #if defined(USE_OPTIONS_H)
104 # include "../conf/options.h"
105 #endif
107 extern const char *_res_opcodes[];
108 extern const char *_res_resultcodes[];
110 /* XXX: we should use getservbyport() instead. */
111 static const char *
112 dewks(wks)
113 int wks;
115 static char nbuf[20];
117 switch (wks) {
118 case 5: return "rje";
119 case 7: return "echo";
120 case 9: return "discard";
121 case 11: return "systat";
122 case 13: return "daytime";
123 case 15: return "netstat";
124 case 17: return "qotd";
125 case 19: return "chargen";
126 case 20: return "ftp-data";
127 case 21: return "ftp";
128 case 23: return "telnet";
129 case 25: return "smtp";
130 case 37: return "time";
131 case 39: return "rlp";
132 case 42: return "name";
133 case 43: return "whois";
134 case 53: return "domain";
135 case 57: return "apts";
136 case 59: return "apfs";
137 case 67: return "bootps";
138 case 68: return "bootpc";
139 case 69: return "tftp";
140 case 77: return "rje";
141 case 79: return "finger";
142 case 87: return "link";
143 case 95: return "supdup";
144 case 100: return "newacct";
145 case 101: return "hostnames";
146 case 102: return "iso-tsap";
147 case 103: return "x400";
148 case 104: return "x400-snd";
149 case 105: return "csnet-ns";
150 case 109: return "pop-2";
151 case 111: return "sunrpc";
152 case 113: return "auth";
153 case 115: return "sftp";
154 case 117: return "uucp-path";
155 case 119: return "nntp";
156 case 121: return "erpc";
157 case 123: return "ntp";
158 case 133: return "statsrv";
159 case 136: return "profile";
160 case 144: return "NeWS";
161 case 161: return "snmp";
162 case 162: return "snmp-trap";
163 case 170: return "print-srv";
164 default: (void) sprintf(nbuf, "%d", wks); return (nbuf);
168 /* XXX: we should use getprotobynumber() instead. */
169 static const char *
170 deproto(protonum)
171 int protonum;
173 static char nbuf[20];
175 switch (protonum) {
176 case 1: return "icmp";
177 case 2: return "igmp";
178 case 3: return "ggp";
179 case 5: return "st";
180 case 6: return "tcp";
181 case 7: return "ucl";
182 case 8: return "egp";
183 case 9: return "igp";
184 case 11: return "nvp-II";
185 case 12: return "pup";
186 case 16: return "chaos";
187 case 17: return "udp";
188 default: (void) sprintf(nbuf, "%d", protonum); return (nbuf);
192 static const u_char *
193 do_rrset(msg, len, cp, cnt, pflag, file, hs)
194 int cnt, pflag, len;
195 const u_char *cp, *msg;
196 const char *hs;
197 FILE *file;
199 int n;
200 int sflag;
203 * Print answer records.
205 sflag = (_res.pfcode & pflag);
206 if (n = ntohs(cnt)) {
207 if ((!_res.pfcode) ||
208 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
209 fprintf(file, hs);
210 while (--n >= 0) {
211 if ((!_res.pfcode) || sflag) {
212 cp = p_rr(cp, msg, file);
213 } else {
214 unsigned int dlen;
215 cp += __dn_skipname(cp, cp + MAXCDNAME);
216 cp += INT16SZ;
217 cp += INT16SZ;
218 cp += INT32SZ;
219 dlen = _getshort((u_char*)cp);
220 cp += INT16SZ;
221 cp += dlen;
223 if ((cp - msg) > len)
224 return (NULL);
226 if ((!_res.pfcode) ||
227 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
228 putc('\n', file);
230 return (cp);
233 void
234 __p_query(msg)
235 const u_char *msg;
237 __fp_query(msg, stdout);
240 #ifdef ultrix
241 /* ultrix 4.0's packaging has some icky packaging. alias for it here.
242 * there is more junk of this kind over in res_comp.c.
244 void
245 p_query(msg)
246 const u_char *msg;
248 __p_query(msg);
250 #endif
253 * Print the current options.
254 * This is intended to be primarily a debugging routine.
256 void
257 __fp_resstat(statp, file)
258 struct __res_state *statp;
259 FILE *file;
261 register u_long mask;
263 fprintf(file, ";; res options:");
264 if (!statp)
265 statp = &_res;
266 for (mask = 1; mask != 0; mask <<= 1)
267 if (statp->options & mask)
268 fprintf(file, " %s", p_option(mask));
269 putc('\n', file);
273 * Print the contents of a query.
274 * This is intended to be primarily a debugging routine.
276 void
277 __fp_nquery(msg, len, file)
278 const u_char *msg;
279 int len;
280 FILE *file;
282 register const u_char *cp, *endMark;
283 register const HEADER *hp;
284 register int n;
286 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
287 return;
289 #define TruncTest(x) if (x >= endMark) goto trunc
290 #define ErrorTest(x) if (x == NULL) goto error
293 * Print header fields.
295 hp = (HEADER *)msg;
296 cp = msg + HFIXEDSZ;
297 endMark = cp + len;
298 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
299 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
300 _res_opcodes[hp->opcode],
301 _res_resultcodes[hp->rcode],
302 ntohs(hp->id));
303 putc('\n', file);
305 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
306 putc(';', file);
307 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
308 fprintf(file, "; flags:");
309 if (hp->qr)
310 fprintf(file, " qr");
311 if (hp->aa)
312 fprintf(file, " aa");
313 if (hp->tc)
314 fprintf(file, " tc");
315 if (hp->rd)
316 fprintf(file, " rd");
317 if (hp->ra)
318 fprintf(file, " ra");
319 if (hp->unused)
320 fprintf(file, " UNUSED-BIT-ON");
321 if (hp->ad)
322 fprintf(file, " ad");
323 if (hp->cd)
324 fprintf(file, " cd");
326 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
327 fprintf(file, "; Ques: %d", ntohs(hp->qdcount));
328 fprintf(file, ", Ans: %d", ntohs(hp->ancount));
329 fprintf(file, ", Auth: %d", ntohs(hp->nscount));
330 fprintf(file, ", Addit: %d", ntohs(hp->arcount));
332 if ((!_res.pfcode) || (_res.pfcode &
333 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
334 putc('\n',file);
337 * Print question records.
339 if (n = ntohs(hp->qdcount)) {
340 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
341 fprintf(file, ";; QUESTIONS:\n");
342 while (--n >= 0) {
343 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
344 fprintf(file, ";;\t");
345 TruncTest(cp);
346 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
347 cp = p_cdnname(cp, msg, len, file);
348 else {
349 int n;
350 char name[MAXDNAME];
352 if ((n = dn_expand(msg, msg+len, cp, name,
353 sizeof name)) < 0)
354 cp = NULL;
355 else
356 cp += n;
358 ErrorTest(cp);
359 TruncTest(cp);
360 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
361 fprintf(file, ", type = %s",
362 __p_type(_getshort((u_char*)cp)));
363 cp += INT16SZ;
364 TruncTest(cp);
365 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
366 fprintf(file, ", class = %s\n",
367 __p_class(_getshort((u_char*)cp)));
368 cp += INT16SZ;
369 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
370 putc('\n', file);
374 * Print authoritative answer records
376 TruncTest(cp);
377 cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
378 ";; ANSWERS:\n");
379 ErrorTest(cp);
382 * print name server records
384 TruncTest(cp);
385 cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
386 ";; AUTHORITY RECORDS:\n");
387 ErrorTest(cp);
389 TruncTest(cp);
391 * print additional records
393 cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
394 ";; ADDITIONAL RECORDS:\n");
395 ErrorTest(cp);
396 return;
397 trunc:
398 fprintf(file, "\n;; ...truncated\n");
399 return;
400 error:
401 fprintf(file, "\n;; ...malformed\n");
404 void
405 __fp_query(msg, file)
406 const u_char *msg;
407 FILE *file;
409 fp_nquery(msg, PACKETSZ, file);
412 const u_char *
413 __p_cdnname(cp, msg, len, file)
414 const u_char *cp, *msg;
415 int len;
416 FILE *file;
418 char name[MAXDNAME];
419 int n;
421 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
422 return (NULL);
423 if (name[0] == '\0')
424 putc('.', file);
425 else
426 fputs(name, file);
427 return (cp + n);
430 const u_char *
431 __p_cdname(cp, msg, file)
432 const u_char *cp, *msg;
433 FILE *file;
435 return (p_cdnname(cp, msg, PACKETSZ, file));
439 /* Return a fully-qualified domain name from a compressed name (with
440 length supplied). */
442 const u_char *
443 __p_fqnname(cp, msg, msglen, name, namelen)
444 const u_char *cp, *msg;
445 int msglen;
446 char *name;
447 int namelen;
449 int n, newlen;
451 if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
452 return (NULL);
453 newlen = strlen (name);
454 if (newlen == 0 || name[newlen - 1] != '.')
455 if (newlen+1 >= namelen) /* Lack space for final dot */
456 return (NULL);
457 else
458 strcpy(name + newlen, ".");
459 return (cp + n);
462 /* XXX: the rest of these functions need to become length-limited, too. (vix)
465 const u_char *
466 __p_fqname(cp, msg, file)
467 const u_char *cp, *msg;
468 FILE *file;
470 char name[MAXDNAME];
471 const u_char *n;
473 n = __p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
474 if (n == NULL)
475 return (NULL);
476 fputs(name, file);
477 return (n);
481 * Print resource record fields in human readable form.
483 const u_char *
484 __p_rr(cp, msg, file)
485 const u_char *cp, *msg;
486 FILE *file;
488 int type, class, dlen, n, c;
489 struct in_addr inaddr;
490 const u_char *cp1, *cp2;
491 u_int32_t tmpttl, t;
492 int lcnt;
493 u_int16_t keyflags;
494 char rrname[MAXDNAME]; /* The fqdn of this RR */
495 char base64_key[MAX_KEY_BASE64];
497 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
498 h_errno = NETDB_INTERNAL;
499 return (NULL);
501 cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname);
502 if (!cp)
503 return (NULL); /* compression error */
504 fputs(rrname, file);
506 type = _getshort((u_char*)cp);
507 cp += INT16SZ;
508 class = _getshort((u_char*)cp);
509 cp += INT16SZ;
510 tmpttl = _getlong((u_char*)cp);
511 cp += INT32SZ;
512 dlen = _getshort((u_char*)cp);
513 cp += INT16SZ;
514 cp1 = cp;
515 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
516 fprintf(file, "\t%lu", (u_long)tmpttl);
517 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS))
518 fprintf(file, "\t%s", __p_class(class));
519 fprintf(file, "\t%s", __p_type(type));
521 * Print type specific data, if appropriate
523 switch (type) {
524 case T_A:
525 switch (class) {
526 case C_IN:
527 case C_HS:
528 bcopy(cp, (char *)&inaddr, INADDRSZ);
529 if (dlen == 4) {
530 fprintf(file, "\t%s", inet_ntoa(inaddr));
531 cp += dlen;
532 } else if (dlen == 7) {
533 char *address;
534 u_char protocol;
535 u_short port;
537 address = inet_ntoa(inaddr);
538 cp += INADDRSZ;
539 protocol = *(u_char*)cp;
540 cp += sizeof (u_char);
541 port = _getshort((u_char*)cp);
542 cp += INT16SZ;
543 fprintf(file, "\t%s\t; proto %d, port %d",
544 address, protocol, port);
546 break;
547 default:
548 cp += dlen;
550 break;
551 case T_CNAME:
552 case T_MB:
553 case T_MG:
554 case T_MR:
555 case T_NS:
556 case T_PTR:
557 putc('\t', file);
558 if ((cp = p_fqname(cp, msg, file)) == NULL)
559 return (NULL);
560 break;
562 case T_HINFO:
563 case T_ISDN:
564 cp2 = cp + dlen;
565 (void) fputs("\t\"", file);
566 if ((n = (unsigned char) *cp++) != 0) {
567 for (c = n; c > 0 && cp < cp2; c--) {
568 if (strchr("\n\"\\", *cp))
569 (void) putc('\\', file);
570 (void) putc(*cp++, file);
573 putc('"', file);
574 if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
575 (void) fputs ("\t\"", file);
576 for (c = n; c > 0 && cp < cp2; c--) {
577 if (strchr("\n\"\\", *cp))
578 (void) putc('\\', file);
579 (void) putc(*cp++, file);
581 putc('"', file);
582 } else if (type == T_HINFO) {
583 (void) fputs("\"?\"", file);
584 fprintf(file, "\n;; *** Warning *** OS-type missing");
586 break;
588 case T_SOA:
589 putc('\t', file);
590 if ((cp = p_fqname(cp, msg, file)) == NULL)
591 return (NULL);
592 putc(' ', file);
593 if ((cp = p_fqname(cp, msg, file)) == NULL)
594 return (NULL);
595 fputs(" (\n", file);
596 t = _getlong((u_char*)cp); cp += INT32SZ;
597 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
598 t = _getlong((u_char*)cp); cp += INT32SZ;
599 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
600 (u_long)t, __p_time(t));
601 t = _getlong((u_char*)cp); cp += INT32SZ;
602 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
603 (u_long)t, __p_time(t));
604 t = _getlong((u_char*)cp); cp += INT32SZ;
605 fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
606 (u_long)t, __p_time(t));
607 t = _getlong((u_char*)cp); cp += INT32SZ;
608 fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
609 (u_long)t, __p_time(t));
610 break;
612 case T_MX:
613 case T_AFSDB:
614 case T_RT:
615 fprintf(file, "\t%d ", _getshort((u_char*)cp));
616 cp += INT16SZ;
617 if ((cp = p_fqname(cp, msg, file)) == NULL)
618 return (NULL);
619 break;
621 case T_PX:
622 fprintf(file, "\t%d ", _getshort((u_char*)cp));
623 cp += INT16SZ;
624 if ((cp = p_fqname(cp, msg, file)) == NULL)
625 return (NULL);
626 putc(' ', file);
627 if ((cp = p_fqname(cp, msg, file)) == NULL)
628 return (NULL);
629 break;
631 case T_X25:
632 cp2 = cp + dlen;
633 (void) fputs("\t\"", file);
634 if ((n = (unsigned char) *cp++) != 0) {
635 for (c = n; c > 0 && cp < cp2; c--) {
636 if (strchr("\n\"\\", *cp))
637 (void) putc('\\', file);
638 (void) putc(*cp++, file);
641 putc('"', file);
642 break;
644 case T_TXT:
645 (void) putc('\t', file);
646 cp2 = cp1 + dlen;
647 while (cp < cp2) {
648 putc('"', file);
649 if (n = (unsigned char) *cp++) {
650 for (c = n; c > 0 && cp < cp2; c--) {
651 if (strchr("\n\"\\", *cp))
652 (void) putc('\\', file);
653 (void) putc(*cp++, file);
656 putc('"', file);
657 if (cp < cp2)
658 putc(' ', file);
660 break;
662 case T_NSAP:
663 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
664 cp += dlen;
665 break;
667 case T_AAAA: {
668 char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
670 fprintf(file, "\t%s\n", inet_ntop(AF_INET6, cp, t, sizeof t));
671 cp += dlen;
672 break;
675 case T_LOC: {
676 char t[255];
678 (void) fprintf(file, "\t%s\n", loc_ntoa(cp, t));
679 cp += dlen;
680 break;
683 case T_MINFO:
684 case T_RP:
685 putc('\t', file);
686 if ((cp = p_fqname(cp, msg, file)) == NULL)
687 return (NULL);
688 putc(' ', file);
689 if ((cp = p_fqname(cp, msg, file)) == NULL)
690 return (NULL);
691 break;
693 case T_UINFO:
694 putc('\t', file);
695 fputs((char *)cp, file);
696 cp += dlen;
697 break;
699 case T_UID:
700 case T_GID:
701 if (dlen == 4) {
702 fprintf(file, "\t%u", _getlong((u_char*)cp));
703 cp += INT32SZ;
705 break;
707 case T_WKS:
708 if (dlen < INT32SZ + 1)
709 break;
710 bcopy(cp, (char *)&inaddr, INADDRSZ);
711 cp += INT32SZ;
712 fprintf(file, "\t%s %s ( ",
713 inet_ntoa(inaddr),
714 deproto((int) *cp));
715 cp += sizeof (u_char);
716 n = 0;
717 lcnt = 0;
718 while (cp < cp1 + dlen) {
719 c = *cp++;
720 do {
721 if (c & 0200) {
722 if (lcnt == 0) {
723 fputs("\n\t\t\t", file);
724 lcnt = 5;
726 fputs(dewks(n), file);
727 putc(' ', file);
728 lcnt--;
730 c <<= 1;
731 } while (++n & 07);
733 putc(')', file);
734 break;
736 case T_KEY:
737 putc('\t', file);
738 keyflags = _getshort(cp);
739 cp += 2;
740 fprintf(file,"0x%04x", keyflags ); /* flags */
741 fprintf(file," %u", *cp++); /* protocol */
742 fprintf(file," %u (", *cp++); /* algorithm */
744 n = b64_ntop(cp, (cp1 + dlen) - cp,
745 base64_key, sizeof base64_key);
746 for (c = 0; c < n; ++c) {
747 if (0 == (c & 0x3F))
748 fprintf(file, "\n\t");
749 putc(base64_key[c], file); /* public key data */
752 fprintf(file, " )");
753 if (n < 0)
754 fprintf(file, "\t; BAD BASE64");
755 fflush(file);
756 cp = cp1 + dlen;
757 break;
759 case T_SIG:
760 type = _getshort((u_char*)cp);
761 cp += INT16SZ;
762 fprintf(file, " %s", p_type(type));
763 fprintf(file, "\t%d", *cp++); /* algorithm */
764 /* Check label value and print error if wrong. */
765 n = *cp++;
766 c = dn_count_labels (rrname);
767 if (n != c)
768 fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t",
769 n, c);
770 /* orig ttl */
771 n = _getlong((u_char*)cp);
772 if (n != tmpttl)
773 fprintf(file, " %u", n);
774 cp += INT32SZ;
775 /* sig expire */
776 fprintf(file, " (\n\t%s",
777 __p_secstodate(_getlong((u_char*)cp)));
778 cp += INT32SZ;
779 /* time signed */
780 fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp)));
781 cp += INT32SZ;
782 /* sig footprint */
783 fprintf(file," %u ", _getshort((u_char*)cp));
784 cp += INT16SZ;
785 /* signer's name */
786 cp = p_fqname(cp, msg, file);
787 n = b64_ntop(cp, (cp1 + dlen) - cp,
788 base64_key, sizeof base64_key);
789 for (c = 0; c < n; c++) {
790 if (0 == (c & 0x3F))
791 fprintf (file, "\n\t");
792 putc(base64_key[c], file); /* signature */
794 /* Clean up... */
795 fprintf(file, " )");
796 if (n < 0)
797 fprintf(file, "\t; BAD BASE64");
798 fflush(file);
799 cp = cp1+dlen;
800 break;
802 #ifdef ALLOW_T_UNSPEC
803 case T_UNSPEC:
805 int NumBytes = 8;
806 u_char *DataPtr;
807 int i;
809 if (dlen < NumBytes) NumBytes = dlen;
810 fprintf(file, "\tFirst %d bytes of hex data:",
811 NumBytes);
812 for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
813 fprintf(file, " %x", *DataPtr);
814 cp += dlen;
816 break;
817 #endif /* ALLOW_T_UNSPEC */
819 default:
820 fprintf(file, "\t?%d?", type);
821 cp += dlen;
823 #if 0
824 fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
825 #else
826 putc('\n', file);
827 #endif
828 if (cp - cp1 != dlen) {
829 fprintf(file,
830 ";; packet size error (found %lu, dlen was %d)\n",
831 (unsigned long) (cp - cp1), dlen);
832 cp = NULL;
834 return (cp);
838 * Names of RR classes and qclasses. Classes and qclasses are the same, except
839 * that C_ANY is a qclass but not a class. (You can ask for records of class
840 * C_ANY, but you can't have any records of that class in the database.)
842 const struct res_sym __p_class_syms[] = {
843 {C_IN, "IN"},
844 {C_CHAOS, "CHAOS"},
845 {C_HS, "HS"},
846 {C_HS, "HESIOD"},
847 {C_ANY, "ANY"},
848 {C_IN, (char *)0}
852 * Names of RR types and qtypes. Types and qtypes are the same, except
853 * that T_ANY is a qtype but not a type. (You can ask for records of type
854 * T_ANY, but you can't have any records of that type in the database.)
856 const struct res_sym __p_type_syms[] = {
857 {T_A, "A", "address"},
858 {T_NS, "NS", "name server"},
859 {T_CNAME, "CNAME", "canonical name"},
860 {T_SOA, "SOA", "start of authority"},
861 {T_MB, "MB", "mailbox"},
862 {T_MG, "MG", "mail group member"},
863 {T_MR, "MR", "mail rename"},
864 {T_NULL, "NULL", "null"},
865 {T_WKS, "WKS", "well-known service"},
866 {T_PTR, "PTR", "domain name pointer"},
867 {T_HINFO, "HINFO", "host information"},
868 {T_MINFO, "MINFO", "mailbox information"},
869 {T_MX, "MX", "mail exchanger"},
870 {T_TXT, "TXT", "text"},
871 {T_RP, "RP", "responsible person"},
872 {T_AFSDB, "AFSDB", "DCE or AFS server"},
873 {T_X25, "X25", "X25 address"},
874 {T_ISDN, "ISDN", "ISDN address"},
875 {T_RT, "RT", "router"},
876 {T_NSAP, "NSAP", "nsap address"},
877 {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"},
878 {T_SIG, "SIG", "signature"},
879 {T_KEY, "KEY", "key"},
880 {T_NXT, "NXT", "next valid name"},
881 {T_PX, "PX", "mapping information"},
882 {T_GPOS, "GPOS", "geographical position"},
883 {T_AAAA, "AAAA", "IPv6 address"},
884 {T_LOC, "LOC", "location"},
885 {T_AXFR, "AXFR", "zone transfer"},
886 {T_MAILB, "MAILB", "mailbox-related data"},
887 {T_MAILA, "MAILA", "mail agent"},
888 {T_UINFO, "UINFO", "user information"},
889 {T_UID, "UID", "user ID"},
890 {T_GID, "GID", "group ID"},
891 #ifdef ALLOW_T_UNSPEC
892 {T_UNSPEC, "UNSPEC", "unspecified data"},
893 #endif /* ALLOW_T_UNSPEC */
894 {T_ANY, "ANY", "\"any\""},
895 {0, (char *)0, (char *)0}
899 __sym_ston(syms, name, success)
900 const struct res_sym *syms;
901 char *name;
902 int *success;
904 #ifdef _LIBC
905 /* Changed to prevent warning. --drepper@gnu */
906 for (; syms->name != 0; syms++) {
907 #else
908 for (NULL; syms->name != 0; syms++) {
909 #endif
910 if (strcasecmp (name, syms->name) == 0) {
911 if (success)
912 *success = 1;
913 return (syms->number);
916 if (success)
917 *success = 0;
918 return (syms->number); /* The default value. */
921 const char *
922 __sym_ntos(syms, number, success)
923 const struct res_sym *syms;
924 int number;
925 int *success;
927 static char unname[20];
929 #ifdef _LIBC
930 /* Changed to prevent warning. --drepper@gnu */
931 for (; syms->name != 0; syms++) {
932 #else
933 for (NULL; syms->name != 0; syms++) {
934 #endif
935 if (number == syms->number) {
936 if (success)
937 *success = 1;
938 return (syms->name);
942 sprintf (unname, "%d", number);
943 if (success)
944 *success = 0;
945 return (unname);
949 const char *
950 __sym_ntop(syms, number, success)
951 const struct res_sym *syms;
952 int number;
953 int *success;
955 static char unname[20];
957 #ifdef _LIBC
958 /* Changed to prevent warning. --drepper@gnu */
959 for (; syms->name != 0; syms++) {
960 #else
961 for (NULL; syms->name != 0; syms++) {
962 #endif
963 if (number == syms->number) {
964 if (success)
965 *success = 1;
966 return (syms->humanname);
969 sprintf(unname, "%d", number);
970 if (success)
971 *success = 0;
972 return (unname);
976 * Return a string for the type
978 const char *
979 __p_type(type)
980 int type;
982 return (__sym_ntos (__p_type_syms, type, (int *)0));
986 * Return a mnemonic for class
988 const char *
989 __p_class(class)
990 int class;
992 return (__sym_ntos (__p_class_syms, class, (int *)0));
996 * Return a mnemonic for an option
998 const char *
999 __p_option(option)
1000 u_long option;
1002 static char nbuf[40];
1004 switch (option) {
1005 case RES_INIT: return "init";
1006 case RES_DEBUG: return "debug";
1007 case RES_AAONLY: return "aaonly(unimpl)";
1008 case RES_USEVC: return "usevc";
1009 case RES_PRIMARY: return "primry(unimpl)";
1010 case RES_IGNTC: return "igntc";
1011 case RES_RECURSE: return "recurs";
1012 case RES_DEFNAMES: return "defnam";
1013 case RES_STAYOPEN: return "styopn";
1014 case RES_DNSRCH: return "dnsrch";
1015 case RES_INSECURE1: return "insecure1";
1016 case RES_INSECURE2: return "insecure2";
1017 default: sprintf(nbuf, "?0x%lx?", (u_long)option);
1018 return (nbuf);
1023 * Return a mnemonic for a time to live
1025 char *
1026 __p_time(value)
1027 u_int32_t value;
1029 static char nbuf[40];
1030 int secs, mins, hours, days;
1031 register char *p;
1033 if (value == 0) {
1034 strcpy(nbuf, "0 secs");
1035 return (nbuf);
1038 secs = value % 60;
1039 value /= 60;
1040 mins = value % 60;
1041 value /= 60;
1042 hours = value % 24;
1043 value /= 24;
1044 days = value;
1045 value = 0;
1047 #define PLURALIZE(x) x, (x == 1) ? "" : "s"
1048 p = nbuf;
1049 if (days) {
1050 (void)sprintf(p, "%d day%s", PLURALIZE(days));
1051 while (*++p);
1053 if (hours) {
1054 if (days)
1055 *p++ = ' ';
1056 (void)sprintf(p, "%d hour%s", PLURALIZE(hours));
1057 while (*++p);
1059 if (mins) {
1060 if (days || hours)
1061 *p++ = ' ';
1062 (void)sprintf(p, "%d min%s", PLURALIZE(mins));
1063 while (*++p);
1065 if (secs || ! (days || hours || mins)) {
1066 if (days || hours || mins)
1067 *p++ = ' ';
1068 (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
1070 return (nbuf);
1074 * routines to convert between on-the-wire RR format and zone file format.
1075 * Does not contain conversion to/from decimal degrees; divide or multiply
1076 * by 60*60*1000 for that.
1079 static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
1080 1000000,10000000,100000000,1000000000};
1082 /* takes an XeY precision/size value, returns a string representation. */
1083 static const char *
1084 precsize_ntoa(prec)
1085 u_int8_t prec;
1087 static char retbuf[sizeof "90000000.00"];
1088 unsigned long val;
1089 int mantissa, exponent;
1091 mantissa = (int)((prec >> 4) & 0x0f) % 10;
1092 exponent = (int)((prec >> 0) & 0x0f) % 10;
1094 val = mantissa * poweroften[exponent];
1096 (void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100);
1097 return (retbuf);
1100 /* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
1101 static u_int8_t
1102 precsize_aton(strptr)
1103 char **strptr;
1105 unsigned int mval = 0, cmval = 0;
1106 u_int8_t retval = 0;
1107 register char *cp;
1108 register int exponent;
1109 register int mantissa;
1111 cp = *strptr;
1113 while (isdigit(*cp))
1114 mval = mval * 10 + (*cp++ - '0');
1116 if (*cp == '.') { /* centimeters */
1117 cp++;
1118 if (isdigit(*cp)) {
1119 cmval = (*cp++ - '0') * 10;
1120 if (isdigit(*cp)) {
1121 cmval += (*cp++ - '0');
1125 cmval = (mval * 100) + cmval;
1127 for (exponent = 0; exponent < 9; exponent++)
1128 if (cmval < poweroften[exponent+1])
1129 break;
1131 mantissa = cmval / poweroften[exponent];
1132 if (mantissa > 9)
1133 mantissa = 9;
1135 retval = (mantissa << 4) | exponent;
1137 *strptr = cp;
1139 return (retval);
1142 /* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
1143 static u_int32_t
1144 latlon2ul(latlonstrptr,which)
1145 char **latlonstrptr;
1146 int *which;
1148 register char *cp;
1149 u_int32_t retval;
1150 int deg = 0, min = 0, secs = 0, secsfrac = 0;
1152 cp = *latlonstrptr;
1154 while (isdigit(*cp))
1155 deg = deg * 10 + (*cp++ - '0');
1157 while (isspace(*cp))
1158 cp++;
1160 if (!(isdigit(*cp)))
1161 goto fndhemi;
1163 while (isdigit(*cp))
1164 min = min * 10 + (*cp++ - '0');
1166 while (isspace(*cp))
1167 cp++;
1169 if (!(isdigit(*cp)))
1170 goto fndhemi;
1172 while (isdigit(*cp))
1173 secs = secs * 10 + (*cp++ - '0');
1175 if (*cp == '.') { /* decimal seconds */
1176 cp++;
1177 if (isdigit(*cp)) {
1178 secsfrac = (*cp++ - '0') * 100;
1179 if (isdigit(*cp)) {
1180 secsfrac += (*cp++ - '0') * 10;
1181 if (isdigit(*cp)) {
1182 secsfrac += (*cp++ - '0');
1188 while (!isspace(*cp)) /* if any trailing garbage */
1189 cp++;
1191 while (isspace(*cp))
1192 cp++;
1194 fndhemi:
1195 switch (*cp) {
1196 case 'N': case 'n':
1197 case 'E': case 'e':
1198 retval = ((unsigned)1<<31)
1199 + (((((deg * 60) + min) * 60) + secs) * 1000)
1200 + secsfrac;
1201 break;
1202 case 'S': case 's':
1203 case 'W': case 'w':
1204 retval = ((unsigned)1<<31)
1205 - (((((deg * 60) + min) * 60) + secs) * 1000)
1206 - secsfrac;
1207 break;
1208 default:
1209 retval = 0; /* invalid value -- indicates error */
1210 break;
1213 switch (*cp) {
1214 case 'N': case 'n':
1215 case 'S': case 's':
1216 *which = 1; /* latitude */
1217 break;
1218 case 'E': case 'e':
1219 case 'W': case 'w':
1220 *which = 2; /* longitude */
1221 break;
1222 default:
1223 *which = 0; /* error */
1224 break;
1227 cp++; /* skip the hemisphere */
1229 while (!isspace(*cp)) /* if any trailing garbage */
1230 cp++;
1232 while (isspace(*cp)) /* move to next field */
1233 cp++;
1235 *latlonstrptr = cp;
1237 return (retval);
1240 /* converts a zone file representation in a string to an RDATA on-the-wire
1241 * representation. */
1243 loc_aton(ascii, binary)
1244 const char *ascii;
1245 u_char *binary;
1247 const char *cp, *maxcp;
1248 u_char *bcp;
1250 u_int32_t latit = 0, longit = 0, alt = 0;
1251 u_int32_t lltemp1 = 0, lltemp2 = 0;
1252 int altmeters = 0, altfrac = 0, altsign = 1;
1253 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
1254 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
1255 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
1256 int which1 = 0, which2 = 0;
1258 cp = ascii;
1259 maxcp = cp + strlen(ascii);
1261 lltemp1 = latlon2ul(&cp, &which1);
1263 lltemp2 = latlon2ul(&cp, &which2);
1265 switch (which1 + which2) {
1266 case 3: /* 1 + 2, the only valid combination */
1267 if ((which1 == 1) && (which2 == 2)) { /* normal case */
1268 latit = lltemp1;
1269 longit = lltemp2;
1270 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
1271 longit = lltemp1;
1272 latit = lltemp2;
1273 } else { /* some kind of brokenness */
1274 return (0);
1276 break;
1277 default: /* we didn't get one of each */
1278 return (0);
1281 /* altitude */
1282 if (*cp == '-') {
1283 altsign = -1;
1284 cp++;
1287 if (*cp == '+')
1288 cp++;
1290 while (isdigit(*cp))
1291 altmeters = altmeters * 10 + (*cp++ - '0');
1293 if (*cp == '.') { /* decimal meters */
1294 cp++;
1295 if (isdigit(*cp)) {
1296 altfrac = (*cp++ - '0') * 10;
1297 if (isdigit(*cp)) {
1298 altfrac += (*cp++ - '0');
1303 alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
1305 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1306 cp++;
1308 while (isspace(*cp) && (cp < maxcp))
1309 cp++;
1311 if (cp >= maxcp)
1312 goto defaults;
1314 siz = precsize_aton(&cp);
1316 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1317 cp++;
1319 while (isspace(*cp) && (cp < maxcp))
1320 cp++;
1322 if (cp >= maxcp)
1323 goto defaults;
1325 hp = precsize_aton(&cp);
1327 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1328 cp++;
1330 while (isspace(*cp) && (cp < maxcp))
1331 cp++;
1333 if (cp >= maxcp)
1334 goto defaults;
1336 vp = precsize_aton(&cp);
1338 defaults:
1340 bcp = binary;
1341 *bcp++ = (u_int8_t) 0; /* version byte */
1342 *bcp++ = siz;
1343 *bcp++ = hp;
1344 *bcp++ = vp;
1345 PUTLONG(latit,bcp);
1346 PUTLONG(longit,bcp);
1347 PUTLONG(alt,bcp);
1349 return (16); /* size of RR in octets */
1352 /* takes an on-the-wire LOC RR and formats it in a human readable format. */
1353 char *
1354 loc_ntoa(binary, ascii)
1355 const u_char *binary;
1356 char *ascii;
1358 static char *error = "?";
1359 register const u_char *cp = binary;
1361 int latdeg, latmin, latsec, latsecfrac;
1362 int longdeg, longmin, longsec, longsecfrac;
1363 char northsouth, eastwest;
1364 int altmeters, altfrac, altsign;
1366 const int referencealt = 100000 * 100;
1368 int32_t latval, longval, altval;
1369 u_int32_t templ;
1370 u_int8_t sizeval, hpval, vpval, versionval;
1372 char *sizestr, *hpstr, *vpstr;
1374 versionval = *cp++;
1376 if (versionval) {
1377 sprintf(ascii, "; error: unknown LOC RR version");
1378 return (ascii);
1381 sizeval = *cp++;
1383 hpval = *cp++;
1384 vpval = *cp++;
1386 GETLONG(templ, cp);
1387 latval = (templ - ((unsigned)1<<31));
1389 GETLONG(templ, cp);
1390 longval = (templ - ((unsigned)1<<31));
1392 GETLONG(templ, cp);
1393 if (templ < referencealt) { /* below WGS 84 spheroid */
1394 altval = referencealt - templ;
1395 altsign = -1;
1396 } else {
1397 altval = templ - referencealt;
1398 altsign = 1;
1401 if (latval < 0) {
1402 northsouth = 'S';
1403 latval = -latval;
1404 } else
1405 northsouth = 'N';
1407 latsecfrac = latval % 1000;
1408 latval = latval / 1000;
1409 latsec = latval % 60;
1410 latval = latval / 60;
1411 latmin = latval % 60;
1412 latval = latval / 60;
1413 latdeg = latval;
1415 if (longval < 0) {
1416 eastwest = 'W';
1417 longval = -longval;
1418 } else
1419 eastwest = 'E';
1421 longsecfrac = longval % 1000;
1422 longval = longval / 1000;
1423 longsec = longval % 60;
1424 longval = longval / 60;
1425 longmin = longval % 60;
1426 longval = longval / 60;
1427 longdeg = longval;
1429 altfrac = altval % 100;
1430 altmeters = (altval / 100) * altsign;
1432 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1433 sizestr = error;
1434 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1435 hpstr = error;
1436 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1437 vpstr = error;
1439 sprintf(ascii,
1440 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1441 latdeg, latmin, latsec, latsecfrac, northsouth,
1442 longdeg, longmin, longsec, longsecfrac, eastwest,
1443 altmeters, altfrac, sizestr, hpstr, vpstr);
1445 if (sizestr != error)
1446 free(sizestr);
1447 if (hpstr != error)
1448 free(hpstr);
1449 if (vpstr != error)
1450 free(vpstr);
1452 return (ascii);
1456 /* Return the number of DNS hierarchy levels in the name. */
1458 __dn_count_labels(name)
1459 char *name;
1461 int i, len, count;
1463 len = strlen(name);
1465 for(i = 0, count = 0; i < len; i++) {
1466 if (name[i] == '.')
1467 count++;
1470 /* don't count initial wildcard */
1471 if (name[0] == '*')
1472 if (count)
1473 count--;
1475 /* don't count the null label for root. */
1476 /* if terminating '.' not found, must adjust */
1477 /* count to include last label */
1478 if (len > 0 && name[len-1] != '.')
1479 count++;
1480 return (count);
1485 * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
1486 * SIG records are required to be printed like this, by the Secure DNS RFC.
1488 char *
1489 __p_secstodate (secs)
1490 unsigned long secs;
1492 static char output[15]; /* YYYYMMDDHHMMSS and null */
1493 time_t clock = secs;
1494 struct tm *time;
1496 time = gmtime(&clock);
1497 time->tm_year += 1900;
1498 time->tm_mon += 1;
1499 sprintf(output, "%04d%02d%02d%02d%02d%02d",
1500 time->tm_year, time->tm_mon, time->tm_mday,
1501 time->tm_hour, time->tm_min, time->tm_sec);
1502 return (output);