Update from main archive 960811
[glibc/history.git] / resolv / res_debug.c
blob62cd81cd0fa5d38ff7c2319bb1731a6391de61d6
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 * --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 <sys/types.h>
63 #include <sys/socket.h>
64 #include <netinet/in.h>
65 #include <arpa/inet.h>
66 #include <arpa/nameser.h>
68 #include <stdio.h>
69 #include <ctype.h>
70 #include <netdb.h>
71 #include <resolv.h>
72 #if defined(BSD) && (BSD >= 199103) && defined(AF_INET6)
73 # include <string.h>
74 #else
75 # include "../conf/portability.h"
76 #endif
78 #if defined(USE_OPTIONS_H)
79 # include "../conf/options.h"
80 #endif
82 extern const char *_res_opcodes[];
83 extern const char *_res_resultcodes[];
85 /* XXX: we should use getservbyport() instead. */
86 static const char *
87 dewks(wks)
88 int wks;
90 static char nbuf[20];
92 switch (wks) {
93 case 5: return "rje";
94 case 7: return "echo";
95 case 9: return "discard";
96 case 11: return "systat";
97 case 13: return "daytime";
98 case 15: return "netstat";
99 case 17: return "qotd";
100 case 19: return "chargen";
101 case 20: return "ftp-data";
102 case 21: return "ftp";
103 case 23: return "telnet";
104 case 25: return "smtp";
105 case 37: return "time";
106 case 39: return "rlp";
107 case 42: return "name";
108 case 43: return "whois";
109 case 53: return "domain";
110 case 57: return "apts";
111 case 59: return "apfs";
112 case 67: return "bootps";
113 case 68: return "bootpc";
114 case 69: return "tftp";
115 case 77: return "rje";
116 case 79: return "finger";
117 case 87: return "link";
118 case 95: return "supdup";
119 case 100: return "newacct";
120 case 101: return "hostnames";
121 case 102: return "iso-tsap";
122 case 103: return "x400";
123 case 104: return "x400-snd";
124 case 105: return "csnet-ns";
125 case 109: return "pop-2";
126 case 111: return "sunrpc";
127 case 113: return "auth";
128 case 115: return "sftp";
129 case 117: return "uucp-path";
130 case 119: return "nntp";
131 case 121: return "erpc";
132 case 123: return "ntp";
133 case 133: return "statsrv";
134 case 136: return "profile";
135 case 144: return "NeWS";
136 case 161: return "snmp";
137 case 162: return "snmp-trap";
138 case 170: return "print-srv";
139 default: (void) sprintf(nbuf, "%d", wks); return (nbuf);
143 /* XXX: we should use getprotobynumber() instead. */
144 static const char *
145 deproto(protonum)
146 int protonum;
148 static char nbuf[20];
150 switch (protonum) {
151 case 1: return "icmp";
152 case 2: return "igmp";
153 case 3: return "ggp";
154 case 5: return "st";
155 case 6: return "tcp";
156 case 7: return "ucl";
157 case 8: return "egp";
158 case 9: return "igp";
159 case 11: return "nvp-II";
160 case 12: return "pup";
161 case 16: return "chaos";
162 case 17: return "udp";
163 default: (void) sprintf(nbuf, "%d", protonum); return (nbuf);
167 static const u_char *
168 do_rrset(msg, len, cp, cnt, pflag, file, hs)
169 int cnt, pflag, len;
170 const u_char *cp, *msg;
171 const char *hs;
172 FILE *file;
174 int n;
175 int sflag;
178 * Print answer records.
180 sflag = (_res.pfcode & pflag);
181 if (n = ntohs(cnt)) {
182 if ((!_res.pfcode) ||
183 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
184 fprintf(file, hs);
185 while (--n >= 0) {
186 if ((!_res.pfcode) || sflag) {
187 cp = p_rr(cp, msg, file);
188 } else {
189 unsigned int dlen;
190 cp += __dn_skipname(cp, cp + MAXCDNAME);
191 cp += INT16SZ;
192 cp += INT16SZ;
193 cp += INT32SZ;
194 dlen = _getshort((u_char*)cp);
195 cp += INT16SZ;
196 cp += dlen;
198 if ((cp - msg) > len)
199 return (NULL);
201 if ((!_res.pfcode) ||
202 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
203 putc('\n', file);
205 return (cp);
208 void
209 __p_query(msg)
210 const u_char *msg;
212 __fp_query(msg, stdout);
215 #ifdef ultrix
216 /* ultrix 4.0's packaging has some icky packaging. alias for it here.
217 * there is more junk of this kind over in res_comp.c.
219 void
220 p_query(msg)
221 const u_char *msg;
223 __p_query(msg);
225 #endif
228 * Print the current options.
229 * This is intended to be primarily a debugging routine.
231 void
232 __fp_resstat(statp, file)
233 struct __res_state *statp;
234 FILE *file;
236 register u_long mask;
238 fprintf(file, ";; res options:");
239 if (!statp)
240 statp = &_res;
241 for (mask = 1; mask != 0; mask <<= 1)
242 if (statp->options & mask)
243 fprintf(file, " %s", p_option(mask));
244 putc('\n', file);
248 * Print the contents of a query.
249 * This is intended to be primarily a debugging routine.
251 void
252 __fp_nquery(msg, len, file)
253 const u_char *msg;
254 int len;
255 FILE *file;
257 register const u_char *cp, *endMark;
258 register const HEADER *hp;
259 register int n;
261 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
262 return;
264 #define TruncTest(x) if (x >= endMark) goto trunc
265 #define ErrorTest(x) if (x == NULL) goto error
268 * Print header fields.
270 hp = (HEADER *)msg;
271 cp = msg + HFIXEDSZ;
272 endMark = cp + len;
273 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
274 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
275 _res_opcodes[hp->opcode],
276 _res_resultcodes[hp->rcode],
277 ntohs(hp->id));
278 putc('\n', file);
280 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
281 putc(';', file);
282 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
283 fprintf(file, "; flags:");
284 if (hp->qr)
285 fprintf(file, " qr");
286 if (hp->aa)
287 fprintf(file, " aa");
288 if (hp->tc)
289 fprintf(file, " tc");
290 if (hp->rd)
291 fprintf(file, " rd");
292 if (hp->ra)
293 fprintf(file, " ra");
295 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
296 fprintf(file, "; Ques: %d", ntohs(hp->qdcount));
297 fprintf(file, ", Ans: %d", ntohs(hp->ancount));
298 fprintf(file, ", Auth: %d", ntohs(hp->nscount));
299 fprintf(file, ", Addit: %d", ntohs(hp->arcount));
301 if ((!_res.pfcode) || (_res.pfcode &
302 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
303 putc('\n',file);
306 * Print question records.
308 if (n = ntohs(hp->qdcount)) {
309 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
310 fprintf(file, ";; QUESTIONS:\n");
311 while (--n >= 0) {
312 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
313 fprintf(file, ";;\t");
314 TruncTest(cp);
315 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
316 cp = p_cdnname(cp, msg, len, file);
317 else {
318 int n;
319 char name[MAXDNAME];
321 if ((n = dn_expand(msg, msg+len, cp, name,
322 sizeof name)) < 0)
323 cp = NULL;
324 else
325 cp += n;
327 ErrorTest(cp);
328 TruncTest(cp);
329 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
330 fprintf(file, ", type = %s",
331 __p_type(_getshort((u_char*)cp)));
332 cp += INT16SZ;
333 TruncTest(cp);
334 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
335 fprintf(file, ", class = %s\n",
336 __p_class(_getshort((u_char*)cp)));
337 cp += INT16SZ;
338 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
339 putc('\n', file);
343 * Print authoritative answer records
345 TruncTest(cp);
346 cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
347 ";; ANSWERS:\n");
348 ErrorTest(cp);
351 * print name server records
353 TruncTest(cp);
354 cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
355 ";; AUTHORITY RECORDS:\n");
356 ErrorTest(cp);
358 TruncTest(cp);
360 * print additional records
362 cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
363 ";; ADDITIONAL RECORDS:\n");
364 ErrorTest(cp);
365 return;
366 trunc:
367 fprintf(file, "\n;; ...truncated\n");
368 return;
369 error:
370 fprintf(file, "\n;; ...malformed\n");
373 void
374 __fp_query(msg, file)
375 const u_char *msg;
376 FILE *file;
378 fp_nquery(msg, PACKETSZ, file);
381 const u_char *
382 __p_cdnname(cp, msg, len, file)
383 const u_char *cp, *msg;
384 int len;
385 FILE *file;
387 char name[MAXDNAME];
388 int n;
390 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
391 return (NULL);
392 if (name[0] == '\0')
393 putc('.', file);
394 else
395 fputs(name, file);
396 return (cp + n);
399 const u_char *
400 __p_cdname(cp, msg, file)
401 const u_char *cp, *msg;
402 FILE *file;
404 return (p_cdnname(cp, msg, PACKETSZ, file));
407 /* XXX: the rest of these functions need to become length-limited, too. (vix)
410 const u_char *
411 __p_fqname(cp, msg, file)
412 const u_char *cp, *msg;
413 FILE *file;
415 char name[MAXDNAME];
416 int n;
418 if ((n = dn_expand(msg, cp + MAXCDNAME, cp, name, sizeof name)) < 0)
419 return (NULL);
420 if (name[0] == '\0') {
421 putc('.', file);
422 } else {
423 fputs(name, file);
424 if (name[strlen(name) - 1] != '.')
425 putc('.', file);
427 return (cp + n);
431 * Print resource record fields in human readable form.
433 const u_char *
434 __p_rr(cp, msg, file)
435 const u_char *cp, *msg;
436 FILE *file;
438 int type, class, dlen, n, c;
439 struct in_addr inaddr;
440 const u_char *cp1, *cp2;
441 u_int32_t tmpttl, t;
442 int lcnt;
444 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
445 h_errno = NETDB_INTERNAL;
446 return (NULL);
448 if ((cp = p_fqname(cp, msg, file)) == NULL)
449 return (NULL); /* compression error */
450 type = _getshort((u_char*)cp);
451 cp += INT16SZ;
452 class = _getshort((u_char*)cp);
453 cp += INT16SZ;
454 tmpttl = _getlong((u_char*)cp);
455 cp += INT32SZ;
456 dlen = _getshort((u_char*)cp);
457 cp += INT16SZ;
458 cp1 = cp;
459 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
460 fprintf(file, "\t%lu", (u_long)tmpttl);
461 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS))
462 fprintf(file, "\t%s", __p_class(class));
463 fprintf(file, "\t%s", __p_type(type));
465 * Print type specific data, if appropriate
467 switch (type) {
468 case T_A:
469 switch (class) {
470 case C_IN:
471 case C_HS:
472 bcopy(cp, (char *)&inaddr, INADDRSZ);
473 if (dlen == 4) {
474 fprintf(file, "\t%s", inet_ntoa(inaddr));
475 cp += dlen;
476 } else if (dlen == 7) {
477 char *address;
478 u_char protocol;
479 u_short port;
481 address = inet_ntoa(inaddr);
482 cp += INADDRSZ;
483 protocol = *(u_char*)cp;
484 cp += sizeof(u_char);
485 port = _getshort((u_char*)cp);
486 cp += INT16SZ;
487 fprintf(file, "\t%s\t; proto %d, port %d",
488 address, protocol, port);
490 break;
491 default:
492 cp += dlen;
494 break;
495 case T_CNAME:
496 case T_MB:
497 case T_MG:
498 case T_MR:
499 case T_NS:
500 case T_PTR:
501 putc('\t', file);
502 if ((cp = p_fqname(cp, msg, file)) == NULL)
503 return (NULL);
504 break;
506 case T_HINFO:
507 case T_ISDN:
508 (void) fputs("\t\"", file);
509 cp2 = cp + dlen;
510 if ((n = (unsigned char) *cp++) != 0) {
511 for (c = n; c > 0 && cp < cp2; c--) {
512 if (strchr("\n\"\\", *cp))
513 (void) putc('\\', file);
514 (void) putc(*cp++, file);
516 putc('"', file);
518 if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
519 (void) fputs ("\t\"", file);
520 for (c = n; c > 0 && cp < cp2; c--) {
521 if (strchr("\n\"\\", *cp))
522 (void) putc('\\', file);
523 (void) putc(*cp++, file);
525 putc('"', file);
526 } else if (type == T_HINFO) {
527 (void) fputs("\"?\"", file);
528 fprintf(file, "\n;; *** Warning *** OS-type missing");
530 break;
532 case T_SOA:
533 putc('\t', file);
534 if ((cp = p_fqname(cp, msg, file)) == NULL)
535 return (NULL);
536 putc(' ', file);
537 if ((cp = p_fqname(cp, msg, file)) == NULL)
538 return (NULL);
539 fputs(" (\n", file);
540 t = _getlong((u_char*)cp); cp += INT32SZ;
541 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
542 t = _getlong((u_char*)cp); cp += INT32SZ;
543 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
544 (u_long)t, __p_time(t));
545 t = _getlong((u_char*)cp); cp += INT32SZ;
546 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
547 (u_long)t, __p_time(t));
548 t = _getlong((u_char*)cp); cp += INT32SZ;
549 fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
550 (u_long)t, __p_time(t));
551 t = _getlong((u_char*)cp); cp += INT32SZ;
552 fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
553 (u_long)t, __p_time(t));
554 break;
556 case T_MX:
557 case T_AFSDB:
558 case T_RT:
559 fprintf(file, "\t%d ", _getshort((u_char*)cp));
560 cp += INT16SZ;
561 if ((cp = p_fqname(cp, msg, file)) == NULL)
562 return (NULL);
563 break;
565 case T_PX:
566 fprintf(file, "\t%d ", _getshort((u_char*)cp));
567 cp += INT16SZ;
568 if ((cp = p_fqname(cp, msg, file)) == NULL)
569 return (NULL);
570 putc(' ', file);
571 if ((cp = p_fqname(cp, msg, file)) == NULL)
572 return (NULL);
573 break;
575 case T_TXT:
576 case T_X25:
577 (void) fputs("\t\"", file);
578 cp2 = cp1 + dlen;
579 while (cp < cp2) {
580 if (n = (unsigned char) *cp++) {
581 for (c = n; c > 0 && cp < cp2; c--) {
582 if (strchr("\n\"\\", *cp))
583 (void) putc('\\', file);
584 (void) putc(*cp++, file);
588 putc('"', file);
589 break;
591 case T_NSAP:
592 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
593 cp += dlen;
594 break;
596 case T_AAAA: {
597 char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
599 fprintf(file, "\t%s\n", inet_ntop(AF_INET6, cp, t, sizeof t));
600 cp += dlen;
601 break;
604 case T_LOC: {
605 char t[255];
607 (void) fprintf(file, "\t%s\n", loc_ntoa(cp, t));
608 cp += dlen;
609 break;
612 case T_MINFO:
613 case T_RP:
614 putc('\t', file);
615 if ((cp = p_fqname(cp, msg, file)) == NULL)
616 return (NULL);
617 putc(' ', file);
618 if ((cp = p_fqname(cp, msg, file)) == NULL)
619 return (NULL);
620 break;
622 case T_UINFO:
623 putc('\t', file);
624 fputs((char *)cp, file);
625 cp += dlen;
626 break;
628 case T_UID:
629 case T_GID:
630 if (dlen == 4) {
631 fprintf(file, "\t%u", _getlong((u_char*)cp));
632 cp += INT32SZ;
634 break;
636 case T_WKS:
637 if (dlen < INT32SZ + 1)
638 break;
639 bcopy(cp, (char *)&inaddr, INADDRSZ);
640 cp += INT32SZ;
641 fprintf(file, "\t%s %s ( ",
642 inet_ntoa(inaddr),
643 deproto((int) *cp));
644 cp += sizeof(u_char);
645 n = 0;
646 lcnt = 0;
647 while (cp < cp1 + dlen) {
648 c = *cp++;
649 do {
650 if (c & 0200) {
651 if (lcnt == 0) {
652 fputs("\n\t\t\t", file);
653 lcnt = 5;
655 fputs(dewks(n), file);
656 putc(' ', file);
657 lcnt--;
659 c <<= 1;
660 } while (++n & 07);
662 putc(')', file);
663 break;
665 #ifdef ALLOW_T_UNSPEC
666 case T_UNSPEC:
668 int NumBytes = 8;
669 u_char *DataPtr;
670 int i;
672 if (dlen < NumBytes) NumBytes = dlen;
673 fprintf(file, "\tFirst %d bytes of hex data:",
674 NumBytes);
675 for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
676 fprintf(file, " %x", *DataPtr);
677 cp += dlen;
679 break;
680 #endif /* ALLOW_T_UNSPEC */
682 default:
683 fprintf(file, "\t?%d?", type);
684 cp += dlen;
686 #if 0
687 fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
688 #else
689 putc('\n', file);
690 #endif
691 if (cp - cp1 != dlen) {
692 fprintf(file,
693 ";; packet size error (found %lu, dlen was %d)\n",
694 (unsigned long) (cp - cp1), dlen);
695 cp = NULL;
697 return (cp);
701 * Return a string for the type
703 const char *
704 __p_type(type)
705 int type;
707 static char nbuf[20];
709 switch (type) {
710 case T_A: return "A";
711 case T_NS: return "NS";
712 case T_CNAME: return "CNAME";
713 case T_SOA: return "SOA";
714 case T_MB: return "MB";
715 case T_MG: return "MG";
716 case T_MR: return "MR";
717 case T_NULL: return "NULL";
718 case T_WKS: return "WKS";
719 case T_PTR: return "PTR";
720 case T_HINFO: return "HINFO";
721 case T_MINFO: return "MINFO";
722 case T_MX: return "MX";
723 case T_TXT: return "TXT";
724 case T_RP: return "RP";
725 case T_AFSDB: return "AFSDB";
726 case T_X25: return "X25";
727 case T_ISDN: return "ISDN";
728 case T_RT: return "RT";
729 case T_NSAP: return "NSAP";
730 case T_NSAP_PTR: return "NSAP_PTR";
731 case T_SIG: return "SIG";
732 case T_KEY: return "KEY";
733 case T_PX: return "PX";
734 case T_GPOS: return "GPOS";
735 case T_AAAA: return "AAAA";
736 case T_LOC: return "LOC";
737 case T_AXFR: return "AXFR";
738 case T_MAILB: return "MAILB";
739 case T_MAILA: return "MAILA";
740 case T_ANY: return "ANY";
741 case T_UINFO: return "UINFO";
742 case T_UID: return "UID";
743 case T_GID: return "GID";
744 #ifdef ALLOW_T_UNSPEC
745 case T_UNSPEC: return "UNSPEC";
746 #endif /* ALLOW_T_UNSPEC */
747 default: (void)sprintf(nbuf, "%d", type); return (nbuf);
752 * Return a mnemonic for class
754 const char *
755 __p_class(class)
756 int class;
758 static char nbuf[20];
760 switch (class) {
761 case C_IN: return "IN";
762 case C_HS: return "HS";
763 case C_ANY: return "ANY";
764 default: (void)sprintf(nbuf, "%d", class); return (nbuf);
769 * Return a mnemonic for an option
771 const char *
772 __p_option(option)
773 u_long option;
775 static char nbuf[40];
777 switch (option) {
778 case RES_INIT: return "init";
779 case RES_DEBUG: return "debug";
780 case RES_AAONLY: return "aaonly(unimpl)";
781 case RES_USEVC: return "usevc";
782 case RES_PRIMARY: return "primry(unimpl)";
783 case RES_IGNTC: return "igntc";
784 case RES_RECURSE: return "recurs";
785 case RES_DEFNAMES: return "defnam";
786 case RES_STAYOPEN: return "styopn";
787 case RES_DNSRCH: return "dnsrch";
788 case RES_INSECURE1: return "insecure1";
789 case RES_INSECURE2: return "insecure2";
790 default: sprintf(nbuf, "?0x%lx?", (u_long)option);
791 return (nbuf);
796 * Return a mnemonic for a time to live
798 char *
799 __p_time(value)
800 u_int32_t value;
802 static char nbuf[40];
803 int secs, mins, hours, days;
804 register char *p;
806 if (value == 0) {
807 strcpy(nbuf, "0 secs");
808 return (nbuf);
811 secs = value % 60;
812 value /= 60;
813 mins = value % 60;
814 value /= 60;
815 hours = value % 24;
816 value /= 24;
817 days = value;
818 value = 0;
820 #define PLURALIZE(x) x, (x == 1) ? "" : "s"
821 p = nbuf;
822 if (days) {
823 (void)sprintf(p, "%d day%s", PLURALIZE(days));
824 while (*++p);
826 if (hours) {
827 if (days)
828 *p++ = ' ';
829 (void)sprintf(p, "%d hour%s", PLURALIZE(hours));
830 while (*++p);
832 if (mins) {
833 if (days || hours)
834 *p++ = ' ';
835 (void)sprintf(p, "%d min%s", PLURALIZE(mins));
836 while (*++p);
838 if (secs || ! (days || hours || mins)) {
839 if (days || hours || mins)
840 *p++ = ' ';
841 (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
843 return (nbuf);
847 * routines to convert between on-the-wire RR format and zone file format.
848 * Does not contain conversion to/from decimal degrees; divide or multiply
849 * by 60*60*1000 for that.
852 static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
853 1000000,10000000,100000000,1000000000};
855 /* takes an XeY precision/size value, returns a string representation. */
856 static const char *
857 precsize_ntoa(prec)
858 u_int8_t prec;
860 static char retbuf[sizeof("90000000.00")];
861 unsigned long val;
862 int mantissa, exponent;
864 mantissa = (int)((prec >> 4) & 0x0f) % 10;
865 exponent = (int)((prec >> 0) & 0x0f) % 10;
867 val = mantissa * poweroften[exponent];
869 (void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100);
870 return (retbuf);
873 /* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
874 static u_int8_t
875 precsize_aton(strptr)
876 char **strptr;
878 unsigned int mval = 0, cmval = 0;
879 u_int8_t retval = 0;
880 register char *cp;
881 register int exponent;
882 register int mantissa;
884 cp = *strptr;
886 while (isdigit(*cp))
887 mval = mval * 10 + (*cp++ - '0');
889 if (*cp == '.') { /* centimeters */
890 cp++;
891 if (isdigit(*cp)) {
892 cmval = (*cp++ - '0') * 10;
893 if (isdigit(*cp)) {
894 cmval += (*cp++ - '0');
898 cmval = (mval * 100) + cmval;
900 for (exponent = 0; exponent < 9; exponent++)
901 if (cmval < poweroften[exponent+1])
902 break;
904 mantissa = cmval / poweroften[exponent];
905 if (mantissa > 9)
906 mantissa = 9;
908 retval = (mantissa << 4) | exponent;
910 *strptr = cp;
912 return (retval);
915 /* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
916 static u_int32_t
917 latlon2ul(latlonstrptr,which)
918 char **latlonstrptr;
919 int *which;
921 register char *cp;
922 u_int32_t retval;
923 int deg = 0, min = 0, secs = 0, secsfrac = 0;
925 cp = *latlonstrptr;
927 while (isdigit(*cp))
928 deg = deg * 10 + (*cp++ - '0');
930 while (isspace(*cp))
931 cp++;
933 if (!(isdigit(*cp)))
934 goto fndhemi;
936 while (isdigit(*cp))
937 min = min * 10 + (*cp++ - '0');
939 while (isspace(*cp))
940 cp++;
942 if (!(isdigit(*cp)))
943 goto fndhemi;
945 while (isdigit(*cp))
946 secs = secs * 10 + (*cp++ - '0');
948 if (*cp == '.') { /* decimal seconds */
949 cp++;
950 if (isdigit(*cp)) {
951 secsfrac = (*cp++ - '0') * 100;
952 if (isdigit(*cp)) {
953 secsfrac += (*cp++ - '0') * 10;
954 if (isdigit(*cp)) {
955 secsfrac += (*cp++ - '0');
961 while (!isspace(*cp)) /* if any trailing garbage */
962 cp++;
964 while (isspace(*cp))
965 cp++;
967 fndhemi:
968 switch (*cp) {
969 case 'N': case 'n':
970 case 'E': case 'e':
971 retval = ((unsigned)1<<31)
972 + (((((deg * 60) + min) * 60) + secs) * 1000)
973 + secsfrac;
974 break;
975 case 'S': case 's':
976 case 'W': case 'w':
977 retval = ((unsigned)1<<31)
978 - (((((deg * 60) + min) * 60) + secs) * 1000)
979 - secsfrac;
980 break;
981 default:
982 retval = 0; /* invalid value -- indicates error */
983 break;
986 switch (*cp) {
987 case 'N': case 'n':
988 case 'S': case 's':
989 *which = 1; /* latitude */
990 break;
991 case 'E': case 'e':
992 case 'W': case 'w':
993 *which = 2; /* longitude */
994 break;
995 default:
996 *which = 0; /* error */
997 break;
1000 cp++; /* skip the hemisphere */
1002 while (!isspace(*cp)) /* if any trailing garbage */
1003 cp++;
1005 while (isspace(*cp)) /* move to next field */
1006 cp++;
1008 *latlonstrptr = cp;
1010 return (retval);
1013 /* converts a zone file representation in a string to an RDATA on-the-wire
1014 * representation. */
1016 loc_aton(ascii, binary)
1017 const char *ascii;
1018 u_char *binary;
1020 const char *cp, *maxcp;
1021 u_char *bcp;
1023 u_int32_t latit = 0, longit = 0, alt = 0;
1024 u_int32_t lltemp1 = 0, lltemp2 = 0;
1025 int altmeters = 0, altfrac = 0, altsign = 1;
1026 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
1027 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
1028 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
1029 int which1 = 0, which2 = 0;
1031 cp = ascii;
1032 maxcp = cp + strlen(ascii);
1034 lltemp1 = latlon2ul(&cp, &which1);
1036 lltemp2 = latlon2ul(&cp, &which2);
1038 switch (which1 + which2) {
1039 case 3: /* 1 + 2, the only valid combination */
1040 if ((which1 == 1) && (which2 == 2)) { /* normal case */
1041 latit = lltemp1;
1042 longit = lltemp2;
1043 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
1044 longit = lltemp1;
1045 latit = lltemp2;
1046 } else { /* some kind of brokenness */
1047 return 0;
1049 break;
1050 default: /* we didn't get one of each */
1051 return 0;
1054 /* altitude */
1055 if (*cp == '-') {
1056 altsign = -1;
1057 cp++;
1060 if (*cp == '+')
1061 cp++;
1063 while (isdigit(*cp))
1064 altmeters = altmeters * 10 + (*cp++ - '0');
1066 if (*cp == '.') { /* decimal meters */
1067 cp++;
1068 if (isdigit(*cp)) {
1069 altfrac = (*cp++ - '0') * 10;
1070 if (isdigit(*cp)) {
1071 altfrac += (*cp++ - '0');
1076 alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
1078 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1079 cp++;
1081 while (isspace(*cp) && (cp < maxcp))
1082 cp++;
1084 if (cp >= maxcp)
1085 goto defaults;
1087 siz = precsize_aton(&cp);
1089 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1090 cp++;
1092 while (isspace(*cp) && (cp < maxcp))
1093 cp++;
1095 if (cp >= maxcp)
1096 goto defaults;
1098 hp = precsize_aton(&cp);
1100 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1101 cp++;
1103 while (isspace(*cp) && (cp < maxcp))
1104 cp++;
1106 if (cp >= maxcp)
1107 goto defaults;
1109 vp = precsize_aton(&cp);
1111 defaults:
1113 bcp = binary;
1114 *bcp++ = (u_int8_t) 0; /* version byte */
1115 *bcp++ = siz;
1116 *bcp++ = hp;
1117 *bcp++ = vp;
1118 PUTLONG(latit,bcp);
1119 PUTLONG(longit,bcp);
1120 PUTLONG(alt,bcp);
1122 return (16); /* size of RR in octets */
1125 /* takes an on-the-wire LOC RR and formats it in a human readable format. */
1126 char *
1127 loc_ntoa(binary, ascii)
1128 const u_char *binary;
1129 char *ascii;
1131 static char *error = "?";
1132 register const u_char *cp = binary;
1134 int latdeg, latmin, latsec, latsecfrac;
1135 int longdeg, longmin, longsec, longsecfrac;
1136 char northsouth, eastwest;
1137 int altmeters, altfrac, altsign;
1139 const int referencealt = 100000 * 100;
1141 int32_t latval, longval, altval;
1142 u_int32_t templ;
1143 u_int8_t sizeval, hpval, vpval, versionval;
1145 char *sizestr, *hpstr, *vpstr;
1147 versionval = *cp++;
1149 if (versionval) {
1150 sprintf(ascii, "; error: unknown LOC RR version");
1151 return (ascii);
1154 sizeval = *cp++;
1156 hpval = *cp++;
1157 vpval = *cp++;
1159 GETLONG(templ, cp);
1160 latval = (templ - ((unsigned)1<<31));
1162 GETLONG(templ, cp);
1163 longval = (templ - ((unsigned)1<<31));
1165 GETLONG(templ, cp);
1166 if (templ < referencealt) { /* below WGS 84 spheroid */
1167 altval = referencealt - templ;
1168 altsign = -1;
1169 } else {
1170 altval = templ - referencealt;
1171 altsign = 1;
1174 if (latval < 0) {
1175 northsouth = 'S';
1176 latval = -latval;
1177 } else
1178 northsouth = 'N';
1180 latsecfrac = latval % 1000;
1181 latval = latval / 1000;
1182 latsec = latval % 60;
1183 latval = latval / 60;
1184 latmin = latval % 60;
1185 latval = latval / 60;
1186 latdeg = latval;
1188 if (longval < 0) {
1189 eastwest = 'W';
1190 longval = -longval;
1191 } else
1192 eastwest = 'E';
1194 longsecfrac = longval % 1000;
1195 longval = longval / 1000;
1196 longsec = longval % 60;
1197 longval = longval / 60;
1198 longmin = longval % 60;
1199 longval = longval / 60;
1200 longdeg = longval;
1202 altfrac = altval % 100;
1203 altmeters = (altval / 100) * altsign;
1205 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1206 sizestr = error;
1207 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1208 hpstr = error;
1209 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1210 vpstr = error;
1212 sprintf(ascii,
1213 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1214 latdeg, latmin, latsec, latsecfrac, northsouth,
1215 longdeg, longmin, longsec, longsecfrac, eastwest,
1216 altmeters, altfrac, sizestr, hpstr, vpstr);
1218 if (sizestr != error)
1219 free(sizestr);
1220 if (hpstr != error)
1221 free(hpstr);
1222 if (vpstr != error)
1223 free(vpstr);
1225 return (ascii);