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