summaryrefslogtreecommitdiff
path: root/src/lib/libc/net/res_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/net/res_debug.c')
-rw-r--r--src/lib/libc/net/res_debug.c1561
1 files changed, 1561 insertions, 0 deletions
diff --git a/src/lib/libc/net/res_debug.c b/src/lib/libc/net/res_debug.c
new file mode 100644
index 0000000000..8f66c7d009
--- /dev/null
+++ b/src/lib/libc/net/res_debug.c
@@ -0,0 +1,1561 @@
1/* $OpenBSD: res_debug.c,v 1.17 2003/06/02 20:18:36 millert Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1990, 1993
5 * -
6 * Copyright (c) 1985, 1990, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 * -
33 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34 *
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * SOFTWARE.
50 * -
51 * Portions Copyright (c) 1995 by International Business Machines, Inc.
52 *
53 * International Business Machines, Inc. (hereinafter called IBM) grants
54 * permission under its copyrights to use, copy, modify, and distribute this
55 * Software with or without fee, provided that the above copyright notice and
56 * all paragraphs of this notice appear in all copies, and that the name of IBM
57 * not be used in connection with the marketing of any product incorporating
58 * the Software or modifications thereof, without specific, written prior
59 * permission.
60 *
61 * To the extent it has a right to do so, IBM grants an immunity from suit
62 * under its patents, if any, for the use, sale or manufacture of products to
63 * the extent that such products are used for performing Domain Name System
64 * dynamic updates in TCP/IP networks by means of the Software. No immunity is
65 * granted for any product per se or for any other function of any product.
66 *
67 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
68 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
69 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
70 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
71 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
72 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
73 * --Copyright--
74 */
75
76#if defined(LIBC_SCCS) && !defined(lint)
77#if 0
78static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
79static char rcsid[] = "$From: res_debug.c,v 8.19 1996/11/26 10:11:23 vixie Exp $";
80#else
81static char rcsid[] = "$OpenBSD: res_debug.c,v 1.17 2003/06/02 20:18:36 millert Exp $";
82#endif
83#endif /* LIBC_SCCS and not lint */
84
85#include <sys/param.h>
86#include <sys/types.h>
87#include <sys/socket.h>
88#include <netinet/in.h>
89#include <arpa/inet.h>
90#include <arpa/nameser.h>
91
92#include <ctype.h>
93#include <netdb.h>
94#include <resolv.h>
95#include <stdio.h>
96#include <time.h>
97
98#include <stdlib.h>
99#include <string.h>
100
101#include "thread_private.h"
102
103extern const char *_res_opcodes[];
104extern const char *_res_resultcodes[];
105
106static const char *loc_ntoal(const u_char *binary, char *ascii, int ascii_len);
107
108/* XXX: we should use getservbyport() instead. */
109static const char *
110dewks(wks)
111 int wks;
112{
113 static char nbuf[20];
114
115 switch (wks) {
116 case 5: return "rje";
117 case 7: return "echo";
118 case 9: return "discard";
119 case 11: return "systat";
120 case 13: return "daytime";
121 case 15: return "netstat";
122 case 17: return "qotd";
123 case 19: return "chargen";
124 case 20: return "ftp-data";
125 case 21: return "ftp";
126 case 23: return "telnet";
127 case 25: return "smtp";
128 case 37: return "time";
129 case 39: return "rlp";
130 case 42: return "name";
131 case 43: return "whois";
132 case 53: return "domain";
133 case 57: return "apts";
134 case 59: return "apfs";
135 case 67: return "bootps";
136 case 68: return "bootpc";
137 case 69: return "tftp";
138 case 77: return "rje";
139 case 79: return "finger";
140 case 87: return "link";
141 case 95: return "supdup";
142 case 100: return "newacct";
143 case 101: return "hostnames";
144 case 102: return "iso-tsap";
145 case 103: return "x400";
146 case 104: return "x400-snd";
147 case 105: return "csnet-ns";
148 case 109: return "pop-2";
149 case 111: return "sunrpc";
150 case 113: return "auth";
151 case 115: return "sftp";
152 case 117: return "uucp-path";
153 case 119: return "nntp";
154 case 121: return "erpc";
155 case 123: return "ntp";
156 case 133: return "statsrv";
157 case 136: return "profile";
158 case 144: return "NeWS";
159 case 161: return "snmp";
160 case 162: return "snmp-trap";
161 case 170: return "print-srv";
162 default:
163 (void) snprintf(nbuf, sizeof nbuf, "%d", wks);
164 return (nbuf);
165 }
166}
167
168/* XXX: we should use getprotobynumber() instead. */
169static const char *
170deproto(protonum)
171 int protonum;
172{
173 static char nbuf[20];
174
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:
189 (void) snprintf(nbuf, sizeof nbuf, "%d", protonum);
190 return (nbuf);
191 }
192}
193
194static const u_char *
195do_rrset(msg, len, cp, cnt, pflag, file, hs)
196 int cnt, pflag, len;
197 const u_char *cp, *msg;
198 const char *hs;
199 FILE *file;
200{
201 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
202 int n;
203 int sflag;
204
205 /*
206 * Print answer records.
207 */
208 sflag = (_resp->pfcode & pflag);
209 if ((n = ntohs(cnt))) {
210 if ((!_resp->pfcode) ||
211 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
212 fprintf(file, "%s", hs);
213 while (--n >= 0) {
214 if ((!_resp->pfcode) || sflag) {
215 cp = p_rr(cp, msg, file);
216 } else {
217 unsigned int dlen;
218 cp += __dn_skipname(cp, cp + MAXCDNAME);
219 cp += INT16SZ;
220 cp += INT16SZ;
221 cp += INT32SZ;
222 dlen = _getshort((u_char*)cp);
223 cp += INT16SZ;
224 cp += dlen;
225 }
226 if ((cp - msg) > len)
227 return (NULL);
228 }
229 if ((!_resp->pfcode) ||
230 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
231 putc('\n', file);
232 }
233 return (cp);
234}
235
236void
237__p_query(msg)
238 const u_char *msg;
239{
240 __fp_query(msg, stdout);
241}
242
243/*
244 * Print the current options.
245 * This is intended to be primarily a debugging routine.
246 */
247void
248__fp_resstat(statp, file)
249 struct __res_state *statp;
250 FILE *file;
251{
252 register u_long mask;
253
254 fprintf(file, ";; res options:");
255 if (!statp)
256 statp = &_res;
257 for (mask = 1; mask != 0; mask <<= 1)
258 if (statp->options & mask)
259 fprintf(file, " %s", p_option(mask));
260 putc('\n', file);
261}
262
263/*
264 * Print the contents of a query.
265 * This is intended to be primarily a debugging routine.
266 */
267void
268__fp_nquery(msg, len, file)
269 const u_char *msg;
270 int len;
271 FILE *file;
272{
273 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
274 register const u_char *cp, *endMark;
275 register const HEADER *hp;
276 register int n;
277
278 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
279 return;
280
281#define TruncTest(x) if (x > endMark) goto trunc
282#define ErrorTest(x) if (x == NULL) goto error
283
284 /*
285 * Print header fields.
286 */
287 hp = (HEADER *)msg;
288 cp = msg + HFIXEDSZ;
289 endMark = msg + len;
290 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX) || hp->rcode) {
291 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %u",
292 _res_opcodes[hp->opcode],
293 _res_resultcodes[hp->rcode],
294 ntohs(hp->id));
295 putc('\n', file);
296 }
297 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX))
298 putc(';', file);
299 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEAD2)) {
300 fprintf(file, "; flags:");
301 if (hp->qr)
302 fprintf(file, " qr");
303 if (hp->aa)
304 fprintf(file, " aa");
305 if (hp->tc)
306 fprintf(file, " tc");
307 if (hp->rd)
308 fprintf(file, " rd");
309 if (hp->ra)
310 fprintf(file, " ra");
311 if (hp->unused)
312 fprintf(file, " UNUSED-BIT-ON");
313 if (hp->ad)
314 fprintf(file, " ad");
315 if (hp->cd)
316 fprintf(file, " cd");
317 }
318 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEAD1)) {
319 fprintf(file, "; Ques: %u", ntohs(hp->qdcount));
320 fprintf(file, ", Ans: %u", ntohs(hp->ancount));
321 fprintf(file, ", Auth: %u", ntohs(hp->nscount));
322 fprintf(file, ", Addit: %u", ntohs(hp->arcount));
323 }
324 if ((!_resp->pfcode) || (_resp->pfcode &
325 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
326 putc('\n',file);
327 }
328 /*
329 * Print question records.
330 */
331 if ((n = ntohs(hp->qdcount))) {
332 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
333 fprintf(file, ";; QUESTIONS:\n");
334 while (--n >= 0) {
335 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
336 fprintf(file, ";;\t");
337 TruncTest(cp);
338 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
339 cp = p_cdnname(cp, msg, len, file);
340 else {
341 int n;
342 char name[MAXDNAME];
343
344 if ((n = dn_expand(msg, msg+len, cp, name,
345 sizeof name)) < 0)
346 cp = NULL;
347 else
348 cp += n;
349 }
350 ErrorTest(cp);
351 TruncTest(cp);
352 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
353 fprintf(file, ", type = %s",
354 __p_type(_getshort((u_char*)cp)));
355 cp += INT16SZ;
356 TruncTest(cp);
357 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
358 fprintf(file, ", class = %s\n",
359 __p_class(_getshort((u_char*)cp)));
360 cp += INT16SZ;
361 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
362 putc('\n', file);
363 }
364 }
365 /*
366 * Print authoritative answer records
367 */
368 TruncTest(cp);
369 cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
370 ";; ANSWERS:\n");
371 ErrorTest(cp);
372
373 /*
374 * print name server records
375 */
376 TruncTest(cp);
377 cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
378 ";; AUTHORITY RECORDS:\n");
379 ErrorTest(cp);
380
381 TruncTest(cp);
382 /*
383 * print additional records
384 */
385 cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
386 ";; ADDITIONAL RECORDS:\n");
387 ErrorTest(cp);
388 return;
389 trunc:
390 fprintf(file, "\n;; ...truncated\n");
391 return;
392 error:
393 fprintf(file, "\n;; ...malformed\n");
394}
395
396void
397__fp_query(msg, file)
398 const u_char *msg;
399 FILE *file;
400{
401 fp_nquery(msg, PACKETSZ, file);
402}
403
404const u_char *
405__p_cdnname(cp, msg, len, file)
406 const u_char *cp, *msg;
407 int len;
408 FILE *file;
409{
410 char name[MAXDNAME];
411 int n;
412
413 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
414 return (NULL);
415 if (name[0] == '\0')
416 putc('.', file);
417 else
418 fputs(name, file);
419 return (cp + n);
420}
421
422const u_char *
423__p_cdname(cp, msg, file)
424 const u_char *cp, *msg;
425 FILE *file;
426{
427 return (p_cdnname(cp, msg, PACKETSZ, file));
428}
429
430
431/* Return a fully-qualified domain name from a compressed name (with
432 length supplied). */
433
434const u_char *
435__p_fqnname(cp, msg, msglen, name, namelen)
436 const u_char *cp, *msg;
437 int msglen;
438 char *name;
439 int namelen;
440{
441 int n, newlen;
442
443 if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
444 return (NULL);
445 newlen = strlen(name);
446 if (newlen == 0 || name[newlen - 1] != '.') {
447 if (newlen + 1 >= namelen) /* Lack space for final dot */
448 return (NULL);
449 else
450 strlcpy(name + newlen, ".", namelen - newlen);
451 }
452 return (cp + n);
453}
454
455/* XXX: the rest of these functions need to become length-limited, too. (vix)
456 */
457
458const u_char *
459__p_fqname(cp, msg, file)
460 const u_char *cp, *msg;
461 FILE *file;
462{
463 char name[MAXDNAME];
464 const u_char *n;
465
466 n = __p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
467 if (n == NULL)
468 return (NULL);
469 fputs(name, file);
470 return (n);
471}
472
473/*
474 * Print resource record fields in human readable form.
475 */
476const u_char *
477__p_rr(cp, msg, file)
478 const u_char *cp, *msg;
479 FILE *file;
480{
481 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
482 int type, class, dlen, n, c;
483 struct in_addr inaddr;
484 const u_char *cp1, *cp2;
485 u_int32_t tmpttl, t;
486 int lcnt;
487 u_int16_t keyflags;
488 char rrname[MAXDNAME]; /* The fqdn of this RR */
489 char base64_key[MAX_KEY_BASE64];
490
491 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
492 h_errno = NETDB_INTERNAL;
493 return (NULL);
494 }
495 cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname);
496 if (!cp)
497 return (NULL); /* compression error */
498 fputs(rrname, file);
499
500 type = _getshort((u_char*)cp);
501 cp += INT16SZ;
502 class = _getshort((u_char*)cp);
503 cp += INT16SZ;
504 tmpttl = _getlong((u_char*)cp);
505 cp += INT32SZ;
506 dlen = _getshort((u_char*)cp);
507 cp += INT16SZ;
508 cp1 = cp;
509 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_TTLID))
510 fprintf(file, "\t%lu", (u_long)tmpttl);
511 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_CLASS))
512 fprintf(file, "\t%s", __p_class(class));
513 fprintf(file, "\t%s", __p_type(type));
514 /*
515 * Print type specific data, if appropriate
516 */
517 switch (type) {
518 case T_A:
519 switch (class) {
520 case C_IN:
521 case C_HS:
522 bcopy(cp, (char *)&inaddr, INADDRSZ);
523 if (dlen == 4) {
524 fprintf(file, "\t%s", inet_ntoa(inaddr));
525 cp += dlen;
526 } else if (dlen == 7) {
527 char *address;
528 u_char protocol;
529 in_port_t port;
530
531 address = inet_ntoa(inaddr);
532 cp += INADDRSZ;
533 protocol = *(u_char*)cp;
534 cp += sizeof (u_char);
535 port = _getshort((u_char*)cp);
536 cp += INT16SZ;
537 fprintf(file, "\t%s\t; proto %u, port %u",
538 address, protocol, port);
539 }
540 break;
541 default:
542 cp += dlen;
543 }
544 break;
545 case T_CNAME:
546 case T_MB:
547 case T_MG:
548 case T_MR:
549 case T_NS:
550 case T_PTR:
551 putc('\t', file);
552 if ((cp = p_fqname(cp, msg, file)) == NULL)
553 return (NULL);
554 break;
555
556 case T_HINFO:
557 case T_ISDN:
558 cp2 = cp + dlen;
559 (void) fputs("\t\"", file);
560 if ((n = (unsigned char) *cp++) != 0) {
561 for (c = n; c > 0 && cp < cp2; c--) {
562 if (strchr("\n\"\\", *cp))
563 (void) putc('\\', file);
564 (void) putc(*cp++, file);
565 }
566 }
567 putc('"', file);
568 if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
569 (void) fputs ("\t\"", file);
570 for (c = n; c > 0 && cp < cp2; c--) {
571 if (strchr("\n\"\\", *cp))
572 (void) putc('\\', file);
573 (void) putc(*cp++, file);
574 }
575 putc('"', file);
576 } else if (type == T_HINFO) {
577 (void) fputs("\"?\"", file);
578 fprintf(file, "\n;; *** Warning *** OS-type missing");
579 }
580 break;
581
582 case T_SOA:
583 putc('\t', file);
584 if ((cp = p_fqname(cp, msg, file)) == NULL)
585 return (NULL);
586 putc(' ', file);
587 if ((cp = p_fqname(cp, msg, file)) == NULL)
588 return (NULL);
589 fputs(" (\n", file);
590 t = _getlong((u_char*)cp); cp += INT32SZ;
591 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
592 t = _getlong((u_char*)cp); cp += INT32SZ;
593 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
594 (u_long)t, __p_time(t));
595 t = _getlong((u_char*)cp); cp += INT32SZ;
596 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
597 (u_long)t, __p_time(t));
598 t = _getlong((u_char*)cp); cp += INT32SZ;
599 fprintf(file, "\t\t\t%lu\t; expire (%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; minimum (%s)",
603 (u_long)t, __p_time(t));
604 break;
605
606 case T_MX:
607 case T_AFSDB:
608 case T_RT:
609 fprintf(file, "\t%u ", _getshort((u_char*)cp));
610 cp += INT16SZ;
611 if ((cp = p_fqname(cp, msg, file)) == NULL)
612 return (NULL);
613 break;
614
615 case T_PX:
616 fprintf(file, "\t%u ", _getshort((u_char*)cp));
617 cp += INT16SZ;
618 if ((cp = p_fqname(cp, msg, file)) == NULL)
619 return (NULL);
620 putc(' ', file);
621 if ((cp = p_fqname(cp, msg, file)) == NULL)
622 return (NULL);
623 break;
624
625 case T_X25:
626 cp2 = cp + dlen;
627 (void) fputs("\t\"", file);
628 if ((n = (unsigned char) *cp++) != 0) {
629 for (c = n; c > 0 && cp < cp2; c--) {
630 if (strchr("\n\"\\", *cp))
631 (void) putc('\\', file);
632 (void) putc(*cp++, file);
633 }
634 }
635 putc('"', file);
636 break;
637
638 case T_TXT:
639 (void) putc('\t', file);
640 cp2 = cp1 + dlen;
641 while (cp < cp2) {
642 putc('"', file);
643 if ((n = (unsigned char) *cp++)) {
644 for (c = n; c > 0 && cp < cp2; c--) {
645 if (strchr("\n\"\\", *cp))
646 (void) putc('\\', file);
647 (void) putc(*cp++, file);
648 }
649 }
650 putc('"', file);
651 if (cp < cp2)
652 putc(' ', file);
653 }
654 break;
655
656 case T_NSAP:
657 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
658 cp += dlen;
659 break;
660
661 case T_AAAA: {
662 char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
663
664 fprintf(file, "\t%s", inet_ntop(AF_INET6, cp, t, sizeof t));
665 cp += dlen;
666 break;
667 }
668
669 case T_LOC: {
670 char t[255];
671
672 fprintf(file, "\t%s", loc_ntoal(cp, t, sizeof t));
673 cp += dlen;
674 break;
675 }
676
677 case T_NAPTR: {
678 u_int order, preference;
679
680 order = _getshort(cp); cp += INT16SZ;
681 preference = _getshort(cp); cp += INT16SZ;
682 fprintf(file, "\t%u %u ",order, preference);
683 /* Flags */
684 n = *cp++;
685 fprintf(file,"\"%.*s\" ", (int)n, cp);
686 cp += n;
687 /* Service */
688 n = *cp++;
689 fprintf(file,"\"%.*s\" ", (int)n, cp);
690 cp += n;
691 /* Regexp */
692 n = *cp++;
693 fprintf(file,"\"%.*s\" ", (int)n, cp);
694 cp += n;
695 if ((cp = p_fqname(cp, msg, file)) == NULL)
696 return (NULL);
697 break;
698 }
699
700 case T_SRV: {
701 u_int priority, weight, port;
702
703 priority = _getshort(cp); cp += INT16SZ;
704 weight = _getshort(cp); cp += INT16SZ;
705 port = _getshort(cp); cp += INT16SZ;
706 fprintf(file, "\t%u %u %u ", priority, weight, port);
707 if ((cp = p_fqname(cp, msg, file)) == NULL)
708 return (NULL);
709 break;
710 }
711
712 case T_MINFO:
713 case T_RP:
714 putc('\t', file);
715 if ((cp = p_fqname(cp, msg, file)) == NULL)
716 return (NULL);
717 putc(' ', file);
718 if ((cp = p_fqname(cp, msg, file)) == NULL)
719 return (NULL);
720 break;
721
722 case T_UINFO:
723 putc('\t', file);
724 fputs((char *)cp, file);
725 cp += dlen;
726 break;
727
728 case T_UID:
729 case T_GID:
730 if (dlen == 4) {
731 fprintf(file, "\t%u", _getlong((u_char*)cp));
732 cp += INT32SZ;
733 }
734 break;
735
736 case T_WKS:
737 if (dlen < INT32SZ + 1)
738 break;
739 bcopy(cp, (char *)&inaddr, INADDRSZ);
740 cp += INT32SZ;
741 fprintf(file, "\t%s %s ( ",
742 inet_ntoa(inaddr),
743 deproto((int) *cp));
744 cp += sizeof (u_char);
745 n = 0;
746 lcnt = 0;
747 while (cp < cp1 + dlen) {
748 c = *cp++;
749 do {
750 if (c & 0200) {
751 if (lcnt == 0) {
752 fputs("\n\t\t\t", file);
753 lcnt = 5;
754 }
755 fputs(dewks(n), file);
756 putc(' ', file);
757 lcnt--;
758 }
759 c <<= 1;
760 } while (++n & 07);
761 }
762 putc(')', file);
763 break;
764
765 case T_KEY:
766 putc('\t', file);
767 keyflags = _getshort(cp);
768 cp += 2;
769 fprintf(file,"0x%04x", keyflags ); /* flags */
770 fprintf(file," %u", *cp++); /* protocol */
771 fprintf(file," %u (", *cp++); /* algorithm */
772
773 n = b64_ntop(cp, (cp1 + dlen) - cp,
774 base64_key, sizeof base64_key);
775 for (c = 0; c < n; ++c) {
776 if (0 == (c & 0x3F))
777 fprintf(file, "\n\t");
778 putc(base64_key[c], file); /* public key data */
779 }
780
781 fprintf(file, " )");
782 if (n < 0)
783 fprintf(file, "\t; BAD BASE64");
784 fflush(file);
785 cp = cp1 + dlen;
786 break;
787
788 case T_SIG:
789 type = _getshort((u_char*)cp);
790 cp += INT16SZ;
791 fprintf(file, " %s", p_type(type));
792 fprintf(file, "\t%u", *cp++); /* algorithm */
793 /* Check label value and print error if wrong. */
794 n = *cp++;
795 c = dn_count_labels (rrname);
796 if (n != c)
797 fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t",
798 n, c);
799 /* orig ttl */
800 n = _getlong((u_char*)cp);
801 if (n != tmpttl)
802 fprintf(file, " %u", n);
803 cp += INT32SZ;
804 /* sig expire */
805 fprintf(file, " (\n\t%s",
806 __p_secstodate(_getlong((u_char*)cp)));
807 cp += INT32SZ;
808 /* time signed */
809 fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp)));
810 cp += INT32SZ;
811 /* sig footprint */
812 fprintf(file," %u ", _getshort((u_char*)cp));
813 cp += INT16SZ;
814 /* signer's name */
815 cp = p_fqname(cp, msg, file);
816 n = b64_ntop(cp, (cp1 + dlen) - cp,
817 base64_key, sizeof base64_key);
818 for (c = 0; c < n; c++) {
819 if (0 == (c & 0x3F))
820 fprintf (file, "\n\t");
821 putc(base64_key[c], file); /* signature */
822 }
823 /* Clean up... */
824 fprintf(file, " )");
825 if (n < 0)
826 fprintf(file, "\t; BAD BASE64");
827 fflush(file);
828 cp = cp1+dlen;
829 break;
830
831#ifdef ALLOW_T_UNSPEC
832 case T_UNSPEC:
833 {
834 int NumBytes = 8;
835 u_char *DataPtr;
836 int i;
837
838 if (dlen < NumBytes) NumBytes = dlen;
839 fprintf(file, "\tFirst %d bytes of hex data:",
840 NumBytes);
841 for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
842 fprintf(file, " %x", *DataPtr);
843 cp += dlen;
844 }
845 break;
846#endif /* ALLOW_T_UNSPEC */
847
848 default:
849 fprintf(file, "\t?%d?", type);
850 cp += dlen;
851 }
852#if 0
853 fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
854#else
855 putc('\n', file);
856#endif
857 if (cp - cp1 != dlen) {
858 fprintf(file, ";; packet size error (found %ld, dlen was %d)\n",
859 (long)(cp - cp1), dlen);
860 cp = NULL;
861 }
862 return (cp);
863}
864
865/*
866 * Names of RR classes and qclasses. Classes and qclasses are the same, except
867 * that C_ANY is a qclass but not a class. (You can ask for records of class
868 * C_ANY, but you can't have any records of that class in the database.)
869 */
870const struct res_sym __p_class_syms[] = {
871 {C_IN, "IN"},
872 {C_CHAOS, "CHAOS"},
873 {C_HS, "HS"},
874 {C_HS, "HESIOD"},
875 {C_ANY, "ANY"},
876 {C_IN, (char *)0}
877};
878
879/*
880 * Names of RR types and qtypes. Types and qtypes are the same, except
881 * that T_ANY is a qtype but not a type. (You can ask for records of type
882 * T_ANY, but you can't have any records of that type in the database.)
883 */
884const struct res_sym __p_type_syms[] = {
885 {T_A, "A", "address"},
886 {T_NS, "NS", "name server"},
887 {T_MD, "MD", "mail destination (deprecated)"},
888 {T_MF, "MF", "mail forwarder (deprecated)"},
889 {T_CNAME, "CNAME", "canonical name"},
890 {T_SOA, "SOA", "start of authority"},
891 {T_MB, "MB", "mailbox"},
892 {T_MG, "MG", "mail group member"},
893 {T_MR, "MR", "mail rename"},
894 {T_NULL, "NULL", "null"},
895 {T_WKS, "WKS", "well-known service (deprecated)"},
896 {T_PTR, "PTR", "domain name pointer"},
897 {T_HINFO, "HINFO", "host information"},
898 {T_MINFO, "MINFO", "mailbox information"},
899 {T_MX, "MX", "mail exchanger"},
900 {T_TXT, "TXT", "text"},
901 {T_RP, "RP", "responsible person"},
902 {T_AFSDB, "AFSDB", "DCE or AFS server"},
903 {T_X25, "X25", "X25 address"},
904 {T_ISDN, "ISDN", "ISDN address"},
905 {T_RT, "RT", "router"},
906 {T_NSAP, "NSAP", "nsap address"},
907 {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"},
908 {T_SIG, "SIG", "signature"},
909 {T_KEY, "KEY", "key"},
910 {T_PX, "PX", "mapping information"},
911 {T_GPOS, "GPOS", "geographical position (withdrawn)"},
912 {T_AAAA, "AAAA", "IPv6 address"},
913 {T_LOC, "LOC", "location"},
914 {T_NXT, "NXT", "next valid name (unimplemented)"},
915 {T_EID, "EID", "endpoint identifier (unimplemented)"},
916 {T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"},
917 {T_SRV, "SRV", "server selection"},
918 {T_ATMA, "ATMA", "ATM address (unimplemented)"},
919 {T_IXFR, "IXFR", "incremental zone transfer"},
920 {T_AXFR, "AXFR", "zone transfer"},
921 {T_MAILB, "MAILB", "mailbox-related data (deprecated)"},
922 {T_MAILA, "MAILA", "mail agent (deprecated)"},
923 {T_UINFO, "UINFO", "user information (nonstandard)"},
924 {T_UID, "UID", "user ID (nonstandard)"},
925 {T_GID, "GID", "group ID (nonstandard)"},
926 {T_NAPTR, "NAPTR", "URN Naming Authority"},
927#ifdef ALLOW_T_UNSPEC
928 {T_UNSPEC, "UNSPEC", "unspecified data (nonstandard)"},
929#endif /* ALLOW_T_UNSPEC */
930 {T_ANY, "ANY", "\"any\""},
931 {0, NULL, NULL}
932};
933
934int
935__sym_ston(syms, name, success)
936 const struct res_sym *syms;
937 char *name;
938 int *success;
939{
940 for (; syms->name != 0; syms++) {
941 if (strcasecmp (name, syms->name) == 0) {
942 if (success)
943 *success = 1;
944 return (syms->number);
945 }
946 }
947 if (success)
948 *success = 0;
949 return (syms->number); /* The default value. */
950}
951
952const char *
953__sym_ntos(syms, number, success)
954 const struct res_sym *syms;
955 int number;
956 int *success;
957{
958 static char unname[20];
959
960 for (; syms->name != 0; syms++) {
961 if (number == syms->number) {
962 if (success)
963 *success = 1;
964 return (syms->name);
965 }
966 }
967
968 snprintf(unname, sizeof unname, "%d", number);
969 if (success)
970 *success = 0;
971 return (unname);
972}
973
974
975const char *
976__sym_ntop(syms, number, success)
977 const struct res_sym *syms;
978 int number;
979 int *success;
980{
981 static char unname[20];
982
983 for (; syms->name != 0; syms++) {
984 if (number == syms->number) {
985 if (success)
986 *success = 1;
987 return (syms->humanname);
988 }
989 }
990 snprintf(unname, sizeof unname, "%d", number);
991 if (success)
992 *success = 0;
993 return (unname);
994}
995
996/*
997 * Return a string for the type
998 */
999const char *
1000__p_type(type)
1001 int type;
1002{
1003 return (__sym_ntos (__p_type_syms, type, (int *)0));
1004}
1005
1006/*
1007 * Return a mnemonic for class
1008 */
1009const char *
1010__p_class(class)
1011 int class;
1012{
1013 return (__sym_ntos (__p_class_syms, class, (int *)0));
1014}
1015
1016/*
1017 * Return a mnemonic for an option
1018 */
1019const char *
1020__p_option(option)
1021 u_long option;
1022{
1023 static char nbuf[40];
1024
1025 switch (option) {
1026 case RES_INIT: return "init";
1027 case RES_DEBUG: return "debug";
1028 case RES_AAONLY: return "aaonly(unimpl)";
1029 case RES_USEVC: return "usevc";
1030 case RES_PRIMARY: return "primry(unimpl)";
1031 case RES_IGNTC: return "igntc";
1032 case RES_RECURSE: return "recurs";
1033 case RES_DEFNAMES: return "defnam";
1034 case RES_STAYOPEN: return "styopn";
1035 case RES_DNSRCH: return "dnsrch";
1036 case RES_INSECURE1: return "insecure1";
1037 case RES_INSECURE2: return "insecure2";
1038 case RES_USE_INET6: return "inet6";
1039 case RES_USE_EDNS0: return "edns0";
1040 default:
1041 snprintf(nbuf, sizeof nbuf, "?0x%lx?", (u_long)option);
1042 return (nbuf);
1043 }
1044}
1045
1046/*
1047 * Return a mnemonic for a time to live
1048 */
1049const char *
1050p_time(value)
1051 u_int32_t value;
1052{
1053 static char nbuf[40];
1054 char *ebuf;
1055 int secs, mins, hours, days;
1056 register char *p;
1057 int tmp;
1058
1059 if (value == 0) {
1060 strlcpy(nbuf, "0 secs", sizeof nbuf);
1061 return (nbuf);
1062 }
1063
1064 secs = value % 60;
1065 value /= 60;
1066 mins = value % 60;
1067 value /= 60;
1068 hours = value % 24;
1069 value /= 24;
1070 days = value;
1071 value = 0;
1072
1073#define PLURALIZE(x) x, (x == 1) ? "" : "s"
1074 p = nbuf;
1075 ebuf = nbuf + sizeof(nbuf);
1076 if (days) {
1077 if ((tmp = snprintf(p, ebuf - p, "%d day%s",
1078 PLURALIZE(days))) >= ebuf - nbuf || tmp < 0)
1079 goto full;
1080 p += tmp;
1081 }
1082 if (hours) {
1083 if (days)
1084 *p++ = ' ';
1085 if (p >= ebuf)
1086 goto full;
1087 if ((tmp = snprintf(p, ebuf - p, "%d hour%s",
1088 PLURALIZE(hours))) >= ebuf - nbuf || tmp < 0)
1089 goto full;
1090 p += tmp;
1091 }
1092 if (mins) {
1093 if (days || hours)
1094 *p++ = ' ';
1095 if (p >= ebuf)
1096 goto full;
1097 if ((tmp = snprintf(p, ebuf - p, "%d min%s",
1098 PLURALIZE(mins))) >= ebuf - nbuf || tmp < 0)
1099 goto full;
1100 p += tmp;
1101 }
1102 if (secs || ! (days || hours || mins)) {
1103 if (days || hours || mins)
1104 *p++ = ' ';
1105 if (p >= ebuf)
1106 goto full;
1107 if ((tmp = snprintf(p, ebuf - p, "%d sec%s",
1108 PLURALIZE(secs))) >= ebuf - nbuf || tmp < 0)
1109 goto full;
1110 }
1111 return (nbuf);
1112full:
1113 p = nbuf + sizeof(nbuf) - 4;
1114 *p++ = '.';
1115 *p++ = '.';
1116 *p++ = '.';
1117 *p++ = '\0';
1118 return (nbuf);
1119}
1120
1121/*
1122 * routines to convert between on-the-wire RR format and zone file format.
1123 * Does not contain conversion to/from decimal degrees; divide or multiply
1124 * by 60*60*1000 for that.
1125 */
1126
1127static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
1128 1000000,10000000,100000000,1000000000};
1129
1130/* takes an XeY precision/size value, returns a string representation. */
1131static const char *
1132precsize_ntoa(prec)
1133 u_int8_t prec;
1134{
1135 static char retbuf[sizeof "90000000.00"];
1136 unsigned long val;
1137 int mantissa, exponent;
1138
1139 mantissa = (int)((prec >> 4) & 0x0f) % 10;
1140 exponent = (int)((prec >> 0) & 0x0f) % 10;
1141
1142 val = mantissa * poweroften[exponent];
1143
1144 (void) snprintf(retbuf, sizeof retbuf, "%ld.%.2ld", val/100, val%100);
1145 return (retbuf);
1146}
1147
1148/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
1149static u_int8_t
1150precsize_aton(strptr)
1151 char **strptr;
1152{
1153 unsigned int mval = 0, cmval = 0;
1154 u_int8_t retval = 0;
1155 register char *cp;
1156 register int exponent;
1157 register int mantissa;
1158
1159 cp = *strptr;
1160
1161 while (isdigit(*cp))
1162 mval = mval * 10 + (*cp++ - '0');
1163
1164 if (*cp == '.') { /* centimeters */
1165 cp++;
1166 if (isdigit(*cp)) {
1167 cmval = (*cp++ - '0') * 10;
1168 if (isdigit(*cp)) {
1169 cmval += (*cp++ - '0');
1170 }
1171 }
1172 }
1173 cmval = (mval * 100) + cmval;
1174
1175 for (exponent = 0; exponent < 9; exponent++)
1176 if (cmval < poweroften[exponent+1])
1177 break;
1178
1179 mantissa = cmval / poweroften[exponent];
1180 if (mantissa > 9)
1181 mantissa = 9;
1182
1183 retval = (mantissa << 4) | exponent;
1184
1185 *strptr = cp;
1186
1187 return (retval);
1188}
1189
1190/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
1191static u_int32_t
1192latlon2ul(latlonstrptr,which)
1193 char **latlonstrptr;
1194 int *which;
1195{
1196 register char *cp;
1197 u_int32_t retval;
1198 int deg = 0, min = 0, secs = 0, secsfrac = 0;
1199
1200 cp = *latlonstrptr;
1201
1202 while (isdigit(*cp))
1203 deg = deg * 10 + (*cp++ - '0');
1204
1205 while (isspace(*cp))
1206 cp++;
1207
1208 if (!(isdigit(*cp)))
1209 goto fndhemi;
1210
1211 while (isdigit(*cp))
1212 min = min * 10 + (*cp++ - '0');
1213
1214 while (isspace(*cp))
1215 cp++;
1216
1217 if (!(isdigit(*cp)))
1218 goto fndhemi;
1219
1220 while (isdigit(*cp))
1221 secs = secs * 10 + (*cp++ - '0');
1222
1223 if (*cp == '.') { /* decimal seconds */
1224 cp++;
1225 if (isdigit(*cp)) {
1226 secsfrac = (*cp++ - '0') * 100;
1227 if (isdigit(*cp)) {
1228 secsfrac += (*cp++ - '0') * 10;
1229 if (isdigit(*cp)) {
1230 secsfrac += (*cp++ - '0');
1231 }
1232 }
1233 }
1234 }
1235
1236 while (!isspace(*cp)) /* if any trailing garbage */
1237 cp++;
1238
1239 while (isspace(*cp))
1240 cp++;
1241
1242 fndhemi:
1243 switch (*cp) {
1244 case 'N': case 'n':
1245 case 'E': case 'e':
1246 retval = ((unsigned)1<<31)
1247 + (((((deg * 60) + min) * 60) + secs) * 1000)
1248 + secsfrac;
1249 break;
1250 case 'S': case 's':
1251 case 'W': case 'w':
1252 retval = ((unsigned)1<<31)
1253 - (((((deg * 60) + min) * 60) + secs) * 1000)
1254 - secsfrac;
1255 break;
1256 default:
1257 retval = 0; /* invalid value -- indicates error */
1258 break;
1259 }
1260
1261 switch (*cp) {
1262 case 'N': case 'n':
1263 case 'S': case 's':
1264 *which = 1; /* latitude */
1265 break;
1266 case 'E': case 'e':
1267 case 'W': case 'w':
1268 *which = 2; /* longitude */
1269 break;
1270 default:
1271 *which = 0; /* error */
1272 break;
1273 }
1274
1275 cp++; /* skip the hemisphere */
1276
1277 while (!isspace(*cp)) /* if any trailing garbage */
1278 cp++;
1279
1280 while (isspace(*cp)) /* move to next field */
1281 cp++;
1282
1283 *latlonstrptr = cp;
1284
1285 return (retval);
1286}
1287
1288/* converts a zone file representation in a string to an RDATA on-the-wire
1289 * representation. */
1290int
1291loc_aton(ascii, binary)
1292 const char *ascii;
1293 u_char *binary;
1294{
1295 const char *maxcp;
1296 u_char *bcp;
1297 char *cp;
1298
1299 u_int32_t latit = 0, longit = 0, alt = 0;
1300 u_int32_t lltemp1 = 0, lltemp2 = 0;
1301 int altmeters = 0, altfrac = 0, altsign = 1;
1302 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
1303 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
1304 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
1305 int which1 = 0, which2 = 0;
1306
1307 cp = (char *)ascii;
1308 maxcp = cp + strlen(ascii);
1309
1310 lltemp1 = latlon2ul(&cp, &which1);
1311
1312 lltemp2 = latlon2ul(&cp, &which2);
1313
1314 switch (which1 + which2) {
1315 case 3: /* 1 + 2, the only valid combination */
1316 if ((which1 == 1) && (which2 == 2)) { /* normal case */
1317 latit = lltemp1;
1318 longit = lltemp2;
1319 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
1320 longit = lltemp1;
1321 latit = lltemp2;
1322 } else { /* some kind of brokenness */
1323 return (0);
1324 }
1325 break;
1326 default: /* we didn't get one of each */
1327 return (0);
1328 }
1329
1330 /* altitude */
1331 if (*cp == '-') {
1332 altsign = -1;
1333 cp++;
1334 }
1335
1336 if (*cp == '+')
1337 cp++;
1338
1339 while (isdigit(*cp))
1340 altmeters = altmeters * 10 + (*cp++ - '0');
1341
1342 if (*cp == '.') { /* decimal meters */
1343 cp++;
1344 if (isdigit(*cp)) {
1345 altfrac = (*cp++ - '0') * 10;
1346 if (isdigit(*cp)) {
1347 altfrac += (*cp++ - '0');
1348 }
1349 }
1350 }
1351
1352 alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
1353
1354 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1355 cp++;
1356
1357 while (isspace(*cp) && (cp < maxcp))
1358 cp++;
1359
1360 if (cp >= maxcp)
1361 goto defaults;
1362
1363 siz = precsize_aton(&cp);
1364
1365 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1366 cp++;
1367
1368 while (isspace(*cp) && (cp < maxcp))
1369 cp++;
1370
1371 if (cp >= maxcp)
1372 goto defaults;
1373
1374 hp = precsize_aton(&cp);
1375
1376 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1377 cp++;
1378
1379 while (isspace(*cp) && (cp < maxcp))
1380 cp++;
1381
1382 if (cp >= maxcp)
1383 goto defaults;
1384
1385 vp = precsize_aton(&cp);
1386
1387 defaults:
1388
1389 bcp = binary;
1390 *bcp++ = (u_int8_t) 0; /* version byte */
1391 *bcp++ = siz;
1392 *bcp++ = hp;
1393 *bcp++ = vp;
1394 PUTLONG(latit,bcp);
1395 PUTLONG(longit,bcp);
1396 PUTLONG(alt,bcp);
1397
1398 return (16); /* size of RR in octets */
1399}
1400
1401const char *
1402loc_ntoa(binary, ascii)
1403 const u_char *binary;
1404 char *ascii;
1405{
1406 return loc_ntoal(binary, ascii, 255);
1407}
1408
1409/* takes an on-the-wire LOC RR and formats it in a human readable format. */
1410static const char *
1411loc_ntoal(binary, ascii, ascii_len)
1412 const u_char *binary;
1413 char *ascii;
1414 int ascii_len;
1415{
1416 static char *error = "?";
1417 register const u_char *cp = binary;
1418
1419 int latdeg, latmin, latsec, latsecfrac;
1420 int longdeg, longmin, longsec, longsecfrac;
1421 char northsouth, eastwest;
1422 int altmeters, altfrac, altsign;
1423
1424 const int referencealt = 100000 * 100;
1425
1426 int32_t latval, longval, altval;
1427 u_int32_t templ;
1428 u_int8_t sizeval, hpval, vpval, versionval;
1429
1430 char *sizestr, *hpstr, *vpstr;
1431
1432 versionval = *cp++;
1433
1434 if (versionval) {
1435 snprintf(ascii, ascii_len, "; error: unknown LOC RR version");
1436 return (ascii);
1437 }
1438
1439 sizeval = *cp++;
1440
1441 hpval = *cp++;
1442 vpval = *cp++;
1443
1444 GETLONG(templ, cp);
1445 latval = (templ - ((unsigned)1<<31));
1446
1447 GETLONG(templ, cp);
1448 longval = (templ - ((unsigned)1<<31));
1449
1450 GETLONG(templ, cp);
1451 if (templ < referencealt) { /* below WGS 84 spheroid */
1452 altval = referencealt - templ;
1453 altsign = -1;
1454 } else {
1455 altval = templ - referencealt;
1456 altsign = 1;
1457 }
1458
1459 if (latval < 0) {
1460 northsouth = 'S';
1461 latval = -latval;
1462 } else
1463 northsouth = 'N';
1464
1465 latsecfrac = latval % 1000;
1466 latval = latval / 1000;
1467 latsec = latval % 60;
1468 latval = latval / 60;
1469 latmin = latval % 60;
1470 latval = latval / 60;
1471 latdeg = latval;
1472
1473 if (longval < 0) {
1474 eastwest = 'W';
1475 longval = -longval;
1476 } else
1477 eastwest = 'E';
1478
1479 longsecfrac = longval % 1000;
1480 longval = longval / 1000;
1481 longsec = longval % 60;
1482 longval = longval / 60;
1483 longmin = longval % 60;
1484 longval = longval / 60;
1485 longdeg = longval;
1486
1487 altfrac = altval % 100;
1488 altmeters = (altval / 100) * altsign;
1489
1490 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1491 sizestr = error;
1492 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1493 hpstr = error;
1494 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1495 vpstr = error;
1496
1497 snprintf(ascii, ascii_len,
1498 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1499 latdeg, latmin, latsec, latsecfrac, northsouth,
1500 longdeg, longmin, longsec, longsecfrac, eastwest,
1501 altmeters, altfrac, sizestr, hpstr, vpstr);
1502
1503 if (sizestr != error)
1504 free(sizestr);
1505 if (hpstr != error)
1506 free(hpstr);
1507 if (vpstr != error)
1508 free(vpstr);
1509
1510 return (ascii);
1511}
1512
1513
1514/* Return the number of DNS hierarchy levels in the name. */
1515int
1516__dn_count_labels(name)
1517 char *name;
1518{
1519 int i, len, count;
1520
1521 len = strlen(name);
1522
1523 for(i = 0, count = 0; i < len; i++) {
1524 if (name[i] == '.')
1525 count++;
1526 }
1527
1528 /* don't count initial wildcard */
1529 if (name[0] == '*')
1530 if (count)
1531 count--;
1532
1533 /* don't count the null label for root. */
1534 /* if terminating '.' not found, must adjust */
1535 /* count to include last label */
1536 if (len > 0 && name[len-1] != '.')
1537 count++;
1538 return (count);
1539}
1540
1541
1542/*
1543 * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
1544 * SIG records are required to be printed like this, by the Secure DNS RFC.
1545 */
1546char *
1547__p_secstodate (secs)
1548 unsigned long secs;
1549{
1550 static char output[15]; /* YYYYMMDDHHMMSS and null */
1551 time_t clock = secs;
1552 struct tm *time;
1553
1554 time = gmtime(&clock);
1555 time->tm_year += 1900;
1556 time->tm_mon += 1;
1557 snprintf(output, sizeof output, "%04d%02d%02d%02d%02d%02d",
1558 time->tm_year, time->tm_mon, time->tm_mday,
1559 time->tm_hour, time->tm_min, time->tm_sec);
1560 return (output);
1561}