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 #include <sys/param.h>
77 #include <sys/types.h>
78 #include <sys/time.h>
79 #include <sys/socket.h>
80 #include <netinet/in.h>
81 #include <arpa/inet.h>
82 #include <arpa/nameser.h>
83
84 #include <ctype.h>
85 #include <stdio.h>
86 #include <time.h>
87
88 #include <stdlib.h>
89 #include <string.h>
90 #include <event.h>
91
92 #include "dnsres.h"
93 #include "dnsres-internal.h"
94 #include "resolv.h"
95
96 /* Signatures */
97 /* Size of a mod or exp in bits */
98 #define MIN_MD5RSA_KEY_PART_BITS 512
99 #define MAX_MD5RSA_KEY_PART_BITS 2552
100 /* Total of binary mod and exp, bytes */
101 #define MAX_MD5RSA_KEY_BYTES ((MAX_MD5RSA_KEY_PART_BITS+7/8)*2+3)
102 /* Max length of text sig block */
103 #define MAX_KEY_BASE64 (((MAX_MD5RSA_KEY_BYTES+2)/3)*4)
104
105 extern const char *dnsres_opcodes[];
106 extern const char *dnsres_resultcodes[];
107
108 static const char *loc_ntoal(const u_char *binary, char *ascii, int ascii_len);
109
110 /* XXX: we should use getservbyport() instead. */
111 static const char *
dewks(wks)112 dewks(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. */
171 static const char *
deproto(protonum)172 deproto(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
196 static const u_char *
do_rrset(struct dnsres * _resp,const u_char * msg,int len,const u_char * cp,int cnt,int pflag,FILE * file,const char * hs)197 do_rrset(struct dnsres *_resp,
198 const u_char *msg, int len,
199 const u_char *cp, int cnt, int pflag, FILE *file, const char *hs)
200 {
201 int n;
202 int sflag;
203
204 /*
205 * Print answer records.
206 */
207 sflag = (_resp->pfcode & pflag);
208 if ((n = ntohs(cnt))) {
209 if ((!_resp->pfcode) ||
210 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
211 fprintf(file, "%s", hs);
212 while (--n >= 0) {
213 if ((!_resp->pfcode) || sflag) {
214 cp = p_rr(_resp, cp, msg, file);
215 } else {
216 unsigned int dlen;
217 cp += __dnsres_dn_skipname(cp, cp + DNSRES_MAXCDNAME);
218 cp += DNSRES_INT16SZ;
219 cp += DNSRES_INT16SZ;
220 cp += DNSRES_INT32SZ;
221 dlen = getshort((u_char*)cp);
222 cp += DNSRES_INT16SZ;
223 cp += dlen;
224 }
225 if ((cp - msg) > len)
226 return (NULL);
227 }
228 if ((!_resp->pfcode) ||
229 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
230 putc('\n', file);
231 }
232 return (cp);
233 }
234
235 void
__dnsres_p_query(struct dnsres * _resp,const u_char * msg)236 __dnsres_p_query(struct dnsres *_resp, const u_char *msg)
237 {
238 __dnsres_fp_query(_resp, msg, stdout);
239 }
240
241 /*
242 * Print the current options.
243 * This is intended to be primarily a debugging routine.
244 */
245 void
__dnsres_fp_resstat(statp,file)246 __dnsres_fp_resstat(statp, file)
247 struct dnsres *statp;
248 FILE *file;
249 {
250 register u_long mask;
251
252 fprintf(file, ";; res options:");
253 for (mask = 1; mask != 0; mask <<= 1)
254 if (statp->options & mask)
255 fprintf(file, " %s", p_option(mask));
256 putc('\n', file);
257 }
258
259 /*
260 * Print the contents of a query.
261 * This is intended to be primarily a debugging routine.
262 */
263 void
__dnsres_fp_nquery(struct dnsres * _resp,const u_char * msg,int len,FILE * file)264 __dnsres_fp_nquery(struct dnsres *_resp,
265 const u_char *msg, int len, FILE *file)
266 {
267 register const u_char *cp, *endMark;
268 register const DNSRES_HEADER *hp;
269 register int n;
270
271 #define TruncTest(x) if (x > endMark) goto trunc
272 #define ErrorTest(x) if (x == NULL) goto error
273
274 /*
275 * Print header fields.
276 */
277 hp = (DNSRES_HEADER *)msg;
278 cp = msg + DNSRES_HFIXEDSZ;
279 endMark = msg + len;
280 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX) || hp->rcode) {
281 fprintf(file, ";; ->>DNSRES_HEADER<<- opcode: %s, status: %s, id: %u",
282 dnsres_opcodes[hp->opcode],
283 dnsres_resultcodes[hp->rcode],
284 ntohs(hp->id));
285 putc('\n', file);
286 }
287 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX))
288 putc(';', file);
289 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEAD2)) {
290 fprintf(file, "; flags:");
291 if (hp->qr)
292 fprintf(file, " qr");
293 if (hp->aa)
294 fprintf(file, " aa");
295 if (hp->tc)
296 fprintf(file, " tc");
297 if (hp->rd)
298 fprintf(file, " rd");
299 if (hp->ra)
300 fprintf(file, " ra");
301 if (hp->unused)
302 fprintf(file, " UNUSED-BIT-ON");
303 if (hp->ad)
304 fprintf(file, " ad");
305 if (hp->cd)
306 fprintf(file, " cd");
307 }
308 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEAD1)) {
309 fprintf(file, "; Ques: %u", ntohs(hp->qdcount));
310 fprintf(file, ", Ans: %u", ntohs(hp->ancount));
311 fprintf(file, ", Auth: %u", ntohs(hp->nscount));
312 fprintf(file, ", Addit: %u", ntohs(hp->arcount));
313 }
314 if ((!_resp->pfcode) || (_resp->pfcode &
315 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
316 putc('\n',file);
317 }
318 /*
319 * Print question records.
320 */
321 if ((n = ntohs(hp->qdcount))) {
322 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
323 fprintf(file, ";; QUESTIONS:\n");
324 while (--n >= 0) {
325 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
326 fprintf(file, ";;\t");
327 TruncTest(cp);
328 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
329 cp = p_cdnname(cp, msg, len, file);
330 else {
331 int n;
332 char name[DNSRES_MAXDNAME];
333
334 if ((n = dn_expand(msg, msg+len, cp, name,
335 sizeof name)) < 0)
336 cp = NULL;
337 else
338 cp += n;
339 }
340 ErrorTest(cp);
341 TruncTest(cp);
342 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
343 fprintf(file, ", type = %s",
344 __dnsres_p_type(getshort((u_char*)cp)));
345 cp += DNSRES_INT16SZ;
346 TruncTest(cp);
347 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
348 fprintf(file, ", class = %s\n",
349 __dnsres_p_class(getshort((u_char*)cp)));
350 cp += DNSRES_INT16SZ;
351 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
352 putc('\n', file);
353 }
354 }
355 /*
356 * Print authoritative answer records
357 */
358 TruncTest(cp);
359 cp = do_rrset(_resp, msg, len, cp, hp->ancount, RES_PRF_ANS, file,
360 ";; ANSWERS:\n");
361 ErrorTest(cp);
362
363 /*
364 * print name server records
365 */
366 TruncTest(cp);
367 cp = do_rrset(_resp, msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
368 ";; AUTHORITY RECORDS:\n");
369 ErrorTest(cp);
370
371 TruncTest(cp);
372 /*
373 * print additional records
374 */
375 cp = do_rrset(_resp, msg, len, cp, hp->arcount, RES_PRF_ADD, file,
376 ";; ADDITIONAL RECORDS:\n");
377 ErrorTest(cp);
378 return;
379 trunc:
380 fprintf(file, "\n;; ...truncated\n");
381 return;
382 error:
383 fprintf(file, "\n;; ...malformed\n");
384 }
385
386 void
__dnsres_fp_query(struct dnsres * _resp,const u_char * msg,FILE * file)387 __dnsres_fp_query(struct dnsres *_resp, const u_char *msg, FILE *file)
388 {
389 fp_nquery(_resp, msg, DNSRES_PACKETSZ, file);
390 }
391
392 const u_char *
__dnsres_p_cdnname(cp,msg,len,file)393 __dnsres_p_cdnname(cp, msg, len, file)
394 const u_char *cp, *msg;
395 int len;
396 FILE *file;
397 {
398 char name[DNSRES_MAXDNAME];
399 int n;
400
401 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
402 return (NULL);
403 if (name[0] == '\0')
404 putc('.', file);
405 else
406 fputs(name, file);
407 return (cp + n);
408 }
409
410 const u_char *
__dnsres_p_cdname(cp,msg,file)411 __dnsres_p_cdname(cp, msg, file)
412 const u_char *cp, *msg;
413 FILE *file;
414 {
415 return (p_cdnname(cp, msg, DNSRES_PACKETSZ, file));
416 }
417
418
419 /* Return a fully-qualified domain name from a compressed name (with
420 length supplied). */
421
422 const u_char *
__dnsres_p_fqnname(cp,msg,msglen,name,namelen)423 __dnsres_p_fqnname(cp, msg, msglen, name, namelen)
424 const u_char *cp, *msg;
425 int msglen;
426 char *name;
427 int namelen;
428 {
429 int n, newlen;
430
431 if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
432 return (NULL);
433 newlen = strlen(name);
434 if (newlen == 0 || name[newlen - 1] != '.') {
435 if (newlen + 1 >= namelen) /* Lack space for final dot */
436 return (NULL);
437 else
438 strlcpy(name + newlen, ".", namelen - newlen);
439 }
440 return (cp + n);
441 }
442
443 /* XXX: the rest of these functions need to become length-limited, too. (vix)
444 */
445
446 const u_char *
__dnsres_p_fqname(cp,msg,file)447 __dnsres_p_fqname(cp, msg, file)
448 const u_char *cp, *msg;
449 FILE *file;
450 {
451 char name[DNSRES_MAXDNAME];
452 const u_char *n;
453
454 n = __dnsres_p_fqnname(cp, msg, DNSRES_MAXCDNAME, name, sizeof name);
455 if (n == NULL)
456 return (NULL);
457 fputs(name, file);
458 return (n);
459 }
460
461 /*
462 * Print resource record fields in human readable form.
463 */
464 const u_char *
__dnsres_p_rr(struct dnsres * _resp,const u_char * cp,const u_char * msg,FILE * file)465 __dnsres_p_rr(struct dnsres *_resp,
466 const u_char *cp, const u_char *msg, FILE *file)
467 {
468 int type, class, dlen, n, c;
469 struct in_addr inaddr;
470 const u_char *cp1, *cp2;
471 u_int32_t tmpttl, t;
472 int lcnt;
473 u_int16_t keyflags;
474 char rrname[DNSRES_MAXDNAME]; /* The fqdn of this RR */
475 char base64_key[MAX_KEY_BASE64];
476
477 cp = __dnsres_p_fqnname(cp, msg, DNSRES_MAXCDNAME, rrname, sizeof rrname);
478 if (!cp)
479 return (NULL); /* compression error */
480 fputs(rrname, file);
481
482 type = getshort((u_char*)cp);
483 cp += DNSRES_INT16SZ;
484 class = getshort((u_char*)cp);
485 cp += DNSRES_INT16SZ;
486 tmpttl = getlong((u_char*)cp);
487 cp += DNSRES_INT32SZ;
488 dlen = getshort((u_char*)cp);
489 cp += DNSRES_INT16SZ;
490 cp1 = cp;
491 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_TTLID))
492 fprintf(file, "\t%lu", (u_long)tmpttl);
493 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_CLASS))
494 fprintf(file, "\t%s", __dnsres_p_class(class));
495 fprintf(file, "\t%s", __dnsres_p_type(type));
496 /*
497 * Print type specific data, if appropriate
498 */
499 switch (type) {
500 case DNSRES_T_A:
501 switch (class) {
502 case DNSRES_C_IN:
503 case DNSRES_C_HS:
504 bcopy(cp, (char *)&inaddr, INADDRSZ);
505 if (dlen == 4) {
506 fprintf(file, "\t%s", inet_ntoa(inaddr));
507 cp += dlen;
508 } else if (dlen == 7) {
509 char *address;
510 u_char protocol;
511 in_port_t port;
512
513 address = inet_ntoa(inaddr);
514 cp += INADDRSZ;
515 protocol = *(u_char*)cp;
516 cp += sizeof (u_char);
517 port = getshort((u_char*)cp);
518 cp += DNSRES_INT16SZ;
519 fprintf(file, "\t%s\t; proto %u, port %u",
520 address, protocol, port);
521 }
522 break;
523 default:
524 cp += dlen;
525 }
526 break;
527 case DNSRES_T_CNAME:
528 case DNSRES_T_MB:
529 case DNSRES_T_MG:
530 case DNSRES_T_MR:
531 case DNSRES_T_NS:
532 case DNSRES_T_PTR:
533 putc('\t', file);
534 if ((cp = p_fqname(cp, msg, file)) == NULL)
535 return (NULL);
536 break;
537
538 case DNSRES_T_HINFO:
539 case DNSRES_T_ISDN:
540 cp2 = cp + dlen;
541 (void) fputs("\t\"", file);
542 if ((n = (unsigned char) *cp++) != 0) {
543 for (c = n; c > 0 && cp < cp2; c--) {
544 if (strchr("\n\"\\", *cp))
545 (void) putc('\\', file);
546 (void) putc(*cp++, file);
547 }
548 }
549 putc('"', file);
550 if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
551 (void) fputs ("\t\"", file);
552 for (c = n; c > 0 && cp < cp2; c--) {
553 if (strchr("\n\"\\", *cp))
554 (void) putc('\\', file);
555 (void) putc(*cp++, file);
556 }
557 putc('"', file);
558 } else if (type == DNSRES_T_HINFO) {
559 (void) fputs("\"?\"", file);
560 fprintf(file, "\n;; *** Warning *** OS-type missing");
561 }
562 break;
563
564 case DNSRES_T_SOA:
565 putc('\t', file);
566 if ((cp = p_fqname(cp, msg, file)) == NULL)
567 return (NULL);
568 putc(' ', file);
569 if ((cp = p_fqname(cp, msg, file)) == NULL)
570 return (NULL);
571 fputs(" (\n", file);
572 t = getlong((u_char*)cp); cp += DNSRES_INT32SZ;
573 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
574 t = getlong((u_char*)cp); cp += DNSRES_INT32SZ;
575 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
576 (u_long)t, __dnsres_p_time(t));
577 t = getlong((u_char*)cp); cp += DNSRES_INT32SZ;
578 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
579 (u_long)t, __dnsres_p_time(t));
580 t = getlong((u_char*)cp); cp += DNSRES_INT32SZ;
581 fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
582 (u_long)t, __dnsres_p_time(t));
583 t = getlong((u_char*)cp); cp += DNSRES_INT32SZ;
584 fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
585 (u_long)t, __dnsres_p_time(t));
586 break;
587
588 case DNSRES_T_MX:
589 case DNSRES_T_AFSDB:
590 case DNSRES_T_RT:
591 fprintf(file, "\t%u ", getshort((u_char*)cp));
592 cp += DNSRES_INT16SZ;
593 if ((cp = p_fqname(cp, msg, file)) == NULL)
594 return (NULL);
595 break;
596
597 case DNSRES_T_PX:
598 fprintf(file, "\t%u ", getshort((u_char*)cp));
599 cp += DNSRES_INT16SZ;
600 if ((cp = p_fqname(cp, msg, file)) == NULL)
601 return (NULL);
602 putc(' ', file);
603 if ((cp = p_fqname(cp, msg, file)) == NULL)
604 return (NULL);
605 break;
606
607 case DNSRES_T_X25:
608 cp2 = cp + dlen;
609 (void) fputs("\t\"", file);
610 if ((n = (unsigned char) *cp++) != 0) {
611 for (c = n; c > 0 && cp < cp2; c--) {
612 if (strchr("\n\"\\", *cp))
613 (void) putc('\\', file);
614 (void) putc(*cp++, file);
615 }
616 }
617 putc('"', file);
618 break;
619
620 case DNSRES_T_TXT:
621 (void) putc('\t', file);
622 cp2 = cp1 + dlen;
623 while (cp < cp2) {
624 putc('"', file);
625 if ((n = (unsigned char) *cp++)) {
626 for (c = n; c > 0 && cp < cp2; c--) {
627 if (strchr("\n\"\\", *cp))
628 (void) putc('\\', file);
629 (void) putc(*cp++, file);
630 }
631 }
632 putc('"', file);
633 if (cp < cp2)
634 putc(' ', file);
635 }
636 break;
637
638 case DNSRES_T_NSAP:
639 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
640 cp += dlen;
641 break;
642
643 case DNSRES_T_AAAA: {
644 char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
645
646 fprintf(file, "\t%s", inet_ntop(AF_INET6, cp, t, sizeof t));
647 cp += dlen;
648 break;
649 }
650
651 case DNSRES_T_LOC: {
652 char t[255];
653
654 fprintf(file, "\t%s", loc_ntoal(cp, t, sizeof t));
655 cp += dlen;
656 break;
657 }
658
659 case DNSRES_T_NAPTR: {
660 u_int order, preference;
661
662 order = getshort(cp); cp += DNSRES_INT16SZ;
663 preference = getshort(cp); cp += DNSRES_INT16SZ;
664 fprintf(file, "\t%u %u ",order, preference);
665 /* Flags */
666 n = *cp++;
667 fprintf(file,"\"%.*s\" ", (int)n, cp);
668 cp += n;
669 /* Service */
670 n = *cp++;
671 fprintf(file,"\"%.*s\" ", (int)n, cp);
672 cp += n;
673 /* Regexp */
674 n = *cp++;
675 fprintf(file,"\"%.*s\" ", (int)n, cp);
676 cp += n;
677 if ((cp = p_fqname(cp, msg, file)) == NULL)
678 return (NULL);
679 break;
680 }
681
682 case DNSRES_T_SRV: {
683 u_int priority, weight, port;
684
685 priority = getshort(cp); cp += DNSRES_INT16SZ;
686 weight = getshort(cp); cp += DNSRES_INT16SZ;
687 port = getshort(cp); cp += DNSRES_INT16SZ;
688 fprintf(file, "\t%u %u %u ", priority, weight, port);
689 if ((cp = p_fqname(cp, msg, file)) == NULL)
690 return (NULL);
691 break;
692 }
693
694 case DNSRES_T_MINFO:
695 case DNSRES_T_RP:
696 putc('\t', file);
697 if ((cp = p_fqname(cp, msg, file)) == NULL)
698 return (NULL);
699 putc(' ', file);
700 if ((cp = p_fqname(cp, msg, file)) == NULL)
701 return (NULL);
702 break;
703 #ifdef DNSRES_T_UINFO
704 case DNSRES_T_UINFO:
705 putc('\t', file);
706 fputs((char *)cp, file);
707 cp += dlen;
708 break;
709
710 case DNSRES_T_UID:
711 case DNSRES_T_GID:
712 if (dlen == 4) {
713 fprintf(file, "\t%u", getlong((u_char*)cp));
714 cp += DNSRES_INT32SZ;
715 }
716 break;
717 #endif
718 case DNSRES_T_WKS:
719 if (dlen < DNSRES_INT32SZ + 1)
720 break;
721 bcopy(cp, (char *)&inaddr, INADDRSZ);
722 cp += DNSRES_INT32SZ;
723 fprintf(file, "\t%s %s ( ",
724 inet_ntoa(inaddr),
725 deproto((int) *cp));
726 cp += sizeof (u_char);
727 n = 0;
728 lcnt = 0;
729 while (cp < cp1 + dlen) {
730 c = *cp++;
731 do {
732 if (c & 0200) {
733 if (lcnt == 0) {
734 fputs("\n\t\t\t", file);
735 lcnt = 5;
736 }
737 fputs(dewks(n), file);
738 putc(' ', file);
739 lcnt--;
740 }
741 c <<= 1;
742 } while (++n & 07);
743 }
744 putc(')', file);
745 break;
746
747 case DNSRES_T_KEY:
748 putc('\t', file);
749 keyflags = getshort(cp);
750 cp += 2;
751 fprintf(file,"0x%04x", keyflags ); /* flags */
752 fprintf(file," %u", *cp++); /* protocol */
753 fprintf(file," %u (", *cp++); /* algorithm */
754
755 n = b64_ntop(cp, (cp1 + dlen) - cp,
756 base64_key, sizeof base64_key);
757 for (c = 0; c < n; ++c) {
758 if (0 == (c & 0x3F))
759 fprintf(file, "\n\t");
760 putc(base64_key[c], file); /* public key data */
761 }
762
763 fprintf(file, " )");
764 if (n < 0)
765 fprintf(file, "\t; BAD BASE64");
766 fflush(file);
767 cp = cp1 + dlen;
768 break;
769
770 case DNSRES_T_SIG:
771 type = getshort((u_char*)cp);
772 cp += DNSRES_INT16SZ;
773 fprintf(file, " %s", p_type(type));
774 fprintf(file, "\t%u", *cp++); /* algorithm */
775 /* Check label value and print error if wrong. */
776 n = *cp++;
777 c = dn_count_labels (rrname);
778 if (n != c)
779 fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t",
780 n, c);
781 /* orig ttl */
782 n = getlong((u_char*)cp);
783 if (n != tmpttl)
784 fprintf(file, " %u", n);
785 cp += DNSRES_INT32SZ;
786 /* sig expire */
787 fprintf(file, " (\n\t%s",
788 __dnsres_p_secstodate(getlong((u_char*)cp)));
789 cp += DNSRES_INT32SZ;
790 /* time signed */
791 fprintf(file, " %s",
792 __dnsres_p_secstodate(getlong((u_char*)cp)));
793 cp += DNSRES_INT32SZ;
794 /* sig footprint */
795 fprintf(file," %u ", getshort((u_char*)cp));
796 cp += DNSRES_INT16SZ;
797 /* signer's name */
798 cp = p_fqname(cp, msg, file);
799 n = b64_ntop(cp, (cp1 + dlen) - cp,
800 base64_key, sizeof base64_key);
801 for (c = 0; c < n; c++) {
802 if (0 == (c & 0x3F))
803 fprintf (file, "\n\t");
804 putc(base64_key[c], file); /* signature */
805 }
806 /* Clean up... */
807 fprintf(file, " )");
808 if (n < 0)
809 fprintf(file, "\t; BAD BASE64");
810 fflush(file);
811 cp = cp1+dlen;
812 break;
813
814 #ifdef ALLOW_T_UNSPEC
815 case DNSRES_T_UNSPEC:
816 {
817 int NumBytes = 8;
818 u_char *DataPtr;
819 int i;
820
821 if (dlen < NumBytes) NumBytes = dlen;
822 fprintf(file, "\tFirst %d bytes of hex data:",
823 NumBytes);
824 for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
825 fprintf(file, " %x", *DataPtr);
826 cp += dlen;
827 }
828 break;
829 #endif /* ALLOW_T_UNSPEC */
830
831 default:
832 fprintf(file, "\t?%d?", type);
833 cp += dlen;
834 }
835 #if 0
836 fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __dnsres_p_time(tmpttl));
837 #else
838 putc('\n', file);
839 #endif
840 if (cp - cp1 != dlen) {
841 fprintf(file,
842 ";; packet size error (found %ld, dlen was %d)\n",
843 (long)(cp - cp1), dlen);
844 cp = NULL;
845 }
846 return (cp);
847 }
848
849 /*
850 * Names of RR classes and qclasses. Classes and qclasses are the same, except
851 * that DNSRES_C_ANY is a qclass but not a class. (You can ask for records of class
852 * DNSRES_C_ANY, but you can't have any records of that class in the database.)
853 */
854 const struct res_sym __dnsres_p_class_syms[] = {
855 {DNSRES_C_IN, "IN"},
856 {DNSRES_C_CHAOS, "CHAOS"},
857 {DNSRES_C_HS, "HS"},
858 {DNSRES_C_HS, "HESIOD"},
859 {DNSRES_C_ANY, "ANY"},
860 {DNSRES_C_IN, (char *)0}
861 };
862
863 /*
864 * Names of RR types and qtypes. Types and qtypes are the same, except
865 * that T_ANY is a qtype but not a type. (You can ask for records of type
866 * T_ANY, but you can't have any records of that type in the database.)
867 */
868 const struct res_sym __dnsres_p_type_syms[] = {
869 {DNSRES_T_A, "A", "address"},
870 {DNSRES_T_NS, "NS", "name server"},
871 {DNSRES_T_MD, "MD", "mail destination (deprecated)"},
872 {DNSRES_T_MF, "MF", "mail forwarder (deprecated)"},
873 {DNSRES_T_CNAME,"CNAME", "canonical name"},
874 {DNSRES_T_SOA, "SOA", "start of authority"},
875 {DNSRES_T_MB, "MB", "mailbox"},
876 {DNSRES_T_MG, "MG", "mail group member"},
877 {DNSRES_T_MR, "MR", "mail rename"},
878 {DNSRES_T_NULL, "NULL", "null"},
879 {DNSRES_T_WKS, "WKS", "well-known service (deprecated)"},
880 {DNSRES_T_PTR, "PTR", "domain name pointer"},
881 {DNSRES_T_HINFO,"HINFO", "host information"},
882 {DNSRES_T_MINFO,"MINFO", "mailbox information"},
883 {DNSRES_T_MX, "MX", "mail exchanger"},
884 {DNSRES_T_TXT, "TXT", "text"},
885 {DNSRES_T_RP, "RP", "responsible person"},
886 {DNSRES_T_AFSDB,"AFSDB", "DCE or AFS server"},
887 {DNSRES_T_X25, "X25", "X25 address"},
888 {DNSRES_T_ISDN, "ISDN", "ISDN address"},
889 {DNSRES_T_RT, "RT", "router"},
890 {DNSRES_T_NSAP, "NSAP", "nsap address"},
891 {DNSRES_T_NSAP_PTR, "NSAP_PTR", "domain name pointer"},
892 {DNSRES_T_SIG, "SIG", "signature"},
893 {DNSRES_T_KEY, "KEY", "key"},
894 {DNSRES_T_PX, "PX", "mapping information"},
895 {DNSRES_T_GPOS, "GPOS", "geographical position (withdrawn)"},
896 {DNSRES_T_AAAA, "AAAA", "IPv6 address"},
897 {DNSRES_T_LOC, "LOC", "location"},
898 {DNSRES_T_NXT, "NXT", "next valid name (unimplemented)"},
899 {DNSRES_T_EID, "EID", "endpoint identifier (unimplemented)"},
900 {DNSRES_T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"},
901 {DNSRES_T_SRV, "SRV", "server selection"},
902 {DNSRES_T_ATMA, "ATMA", "ATM address (unimplemented)"},
903 {DNSRES_T_IXFR, "IXFR", "incremental zone transfer"},
904 {DNSRES_T_AXFR, "AXFR", "zone transfer"},
905 {DNSRES_T_MAILB,"MAILB", "mailbox-related data (deprecated)"},
906 {DNSRES_T_MAILA,"MAILA", "mail agent (deprecated)"},
907 #ifdef DNSRES_T_UINFO
908 {DNSRES_T_UINFO,"UINFO", "user information (nonstandard)"},
909 {DNSRES_T_UID, "UID", "user ID (nonstandard)"},
910 {DNSRES_T_GID, "GID", "group ID (nonstandard)"},
911 #endif
912 {DNSRES_T_NAPTR,"NAPTR", "URN Naming Authority"},
913 #ifdef ALLOW_T_UNSPEC
914 {DNSRES_T_UNSPEC,"UNSPEC", "unspecified data (nonstandard)"},
915 #endif /* ALLOW_T_UNSPEC */
916 {DNSRES_T_ANY, "ANY", "\"any\""},
917 {0, NULL, NULL}
918 };
919
920 int
__dnsres_sym_ston(syms,name,success)921 __dnsres_sym_ston(syms, name, success)
922 const struct res_sym *syms;
923 char *name;
924 int *success;
925 {
926 for (; syms->name != 0; syms++) {
927 if (strcasecmp (name, syms->name) == 0) {
928 if (success)
929 *success = 1;
930 return (syms->number);
931 }
932 }
933 if (success)
934 *success = 0;
935 return (syms->number); /* The default value. */
936 }
937
938 const char *
__dnsres_sym_ntos(syms,number,success)939 __dnsres_sym_ntos(syms, number, success)
940 const struct res_sym *syms;
941 int number;
942 int *success;
943 {
944 static char unname[20];
945
946 for (; syms->name != 0; syms++) {
947 if (number == syms->number) {
948 if (success)
949 *success = 1;
950 return (syms->name);
951 }
952 }
953
954 snprintf(unname, sizeof unname, "%d", number);
955 if (success)
956 *success = 0;
957 return (unname);
958 }
959
960
961 const char *
__dnsres_sym_ntop(syms,number,success)962 __dnsres_sym_ntop(syms, number, success)
963 const struct res_sym *syms;
964 int number;
965 int *success;
966 {
967 static char unname[20];
968
969 for (; syms->name != 0; syms++) {
970 if (number == syms->number) {
971 if (success)
972 *success = 1;
973 return (syms->humanname);
974 }
975 }
976 snprintf(unname, sizeof unname, "%d", number);
977 if (success)
978 *success = 0;
979 return (unname);
980 }
981
982 /*
983 * Return a string for the type
984 */
985 const char *
__dnsres_p_type(type)986 __dnsres_p_type(type)
987 int type;
988 {
989 return (__dnsres_sym_ntos (__dnsres_p_type_syms, type, (int *)0));
990 }
991
992 /*
993 * Return a mnemonic for class
994 */
995 const char *
__dnsres_p_class(class)996 __dnsres_p_class(class)
997 int class;
998 {
999 return (__dnsres_sym_ntos (__dnsres_p_class_syms, class, (int *)0));
1000 }
1001
1002 /*
1003 * Return a mnemonic for an option
1004 */
1005 const char *
__dnsres_p_option(option)1006 __dnsres_p_option(option)
1007 u_long option;
1008 {
1009 static char nbuf[40];
1010
1011 switch (option) {
1012 case RES_INIT: return "init";
1013 case RES_DEBUG: return "debug";
1014 case RES_AAONLY: return "aaonly(unimpl)";
1015 case RES_USEVC: return "usevc";
1016 case RES_PRIMARY: return "primry(unimpl)";
1017 case RES_IGNTC: return "igntc";
1018 case RES_RECURSE: return "recurs";
1019 case RES_DEFNAMES: return "defnam";
1020 case RES_STAYOPEN: return "styopn";
1021 case RES_DNSRCH: return "dnsrch";
1022 case RES_INSECURE1: return "insecure1";
1023 case RES_INSECURE2: return "insecure2";
1024 case RES_USE_INET6: return "inet6";
1025 case RES_USE_EDNS0: return "edns0";
1026 default:
1027 snprintf(nbuf, sizeof nbuf, "?0x%lx?", (u_long)option);
1028 return (nbuf);
1029 }
1030 }
1031
1032 /*
1033 * Return a mnemonic for a time to live
1034 */
1035 const char *
p_time(value)1036 p_time(value)
1037 u_int32_t value;
1038 {
1039 static char nbuf[40];
1040 char *ebuf;
1041 int secs, mins, hours, days;
1042 register char *p;
1043 int tmp;
1044
1045 if (value == 0) {
1046 strlcpy(nbuf, "0 secs", sizeof nbuf);
1047 return (nbuf);
1048 }
1049
1050 secs = value % 60;
1051 value /= 60;
1052 mins = value % 60;
1053 value /= 60;
1054 hours = value % 24;
1055 value /= 24;
1056 days = value;
1057 value = 0;
1058
1059 #define PLURALIZE(x) x, (x == 1) ? "" : "s"
1060 p = nbuf;
1061 ebuf = nbuf + sizeof(nbuf);
1062 if (days) {
1063 if ((tmp = snprintf(p, ebuf - p, "%d day%s",
1064 PLURALIZE(days))) >= ebuf - nbuf || tmp < 0)
1065 goto full;
1066 p += tmp;
1067 }
1068 if (hours) {
1069 if (days)
1070 *p++ = ' ';
1071 if (p >= ebuf)
1072 goto full;
1073 if ((tmp = snprintf(p, ebuf - p, "%d hour%s",
1074 PLURALIZE(hours))) >= ebuf - nbuf || tmp < 0)
1075 goto full;
1076 p += tmp;
1077 }
1078 if (mins) {
1079 if (days || hours)
1080 *p++ = ' ';
1081 if (p >= ebuf)
1082 goto full;
1083 if ((tmp = snprintf(p, ebuf - p, "%d min%s",
1084 PLURALIZE(mins))) >= ebuf - nbuf || tmp < 0)
1085 goto full;
1086 p += tmp;
1087 }
1088 if (secs || ! (days || hours || mins)) {
1089 if (days || hours || mins)
1090 *p++ = ' ';
1091 if (p >= ebuf)
1092 goto full;
1093 if ((tmp = snprintf(p, ebuf - p, "%d sec%s",
1094 PLURALIZE(secs))) >= ebuf - nbuf || tmp < 0)
1095 goto full;
1096 }
1097 return (nbuf);
1098 full:
1099 p = nbuf + sizeof(nbuf) - 4;
1100 *p++ = '.';
1101 *p++ = '.';
1102 *p++ = '.';
1103 *p++ = '\0';
1104 return (nbuf);
1105 }
1106
1107 /*
1108 * routines to convert between on-the-wire RR format and zone file format.
1109 * Does not contain conversion to/from decimal degrees; divide or multiply
1110 * by 60*60*1000 for that.
1111 */
1112
1113 static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
1114 1000000,10000000,100000000,1000000000};
1115
1116 /* takes an XeY precision/size value, returns a string representation. */
1117 static const char *
precsize_ntoa(prec)1118 precsize_ntoa(prec)
1119 u_int8_t prec;
1120 {
1121 static char retbuf[sizeof "90000000.00"];
1122 unsigned long val;
1123 int mantissa, exponent;
1124
1125 mantissa = (int)((prec >> 4) & 0x0f) % 10;
1126 exponent = (int)((prec >> 0) & 0x0f) % 10;
1127
1128 val = mantissa * poweroften[exponent];
1129
1130 (void) snprintf(retbuf, sizeof retbuf, "%ld.%.2ld", val/100, val%100);
1131 return (retbuf);
1132 }
1133
1134 /* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
1135 static u_int8_t
precsize_aton(strptr)1136 precsize_aton(strptr)
1137 char **strptr;
1138 {
1139 unsigned int mval = 0, cmval = 0;
1140 u_int8_t retval = 0;
1141 unsigned char *cp;
1142 int exponent;
1143 int mantissa;
1144
1145 cp = *strptr;
1146
1147 while (isdigit(*cp))
1148 mval = mval * 10 + (*cp++ - '0');
1149
1150 if (*cp == '.') { /* centimeters */
1151 cp++;
1152 if (isdigit(*cp)) {
1153 cmval = (*cp++ - '0') * 10;
1154 if (isdigit(*cp)) {
1155 cmval += (*cp++ - '0');
1156 }
1157 }
1158 }
1159 cmval = (mval * 100) + cmval;
1160
1161 for (exponent = 0; exponent < 9; exponent++)
1162 if (cmval < poweroften[exponent+1])
1163 break;
1164
1165 mantissa = cmval / poweroften[exponent];
1166 if (mantissa > 9)
1167 mantissa = 9;
1168
1169 retval = (mantissa << 4) | exponent;
1170
1171 *strptr = cp;
1172
1173 return (retval);
1174 }
1175
1176 /* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
1177 static u_int32_t
latlon2ul(latlonstrptr,which)1178 latlon2ul(latlonstrptr,which)
1179 char **latlonstrptr;
1180 int *which;
1181 {
1182 unsigned char *cp;
1183 u_int32_t retval;
1184 int deg = 0, min = 0, secs = 0, secsfrac = 0;
1185
1186 cp = *latlonstrptr;
1187
1188 while (isdigit(*cp))
1189 deg = deg * 10 + (*cp++ - '0');
1190
1191 while (isspace(*cp))
1192 cp++;
1193
1194 if (!(isdigit(*cp)))
1195 goto fndhemi;
1196
1197 while (isdigit(*cp))
1198 min = min * 10 + (*cp++ - '0');
1199
1200 while (isspace(*cp))
1201 cp++;
1202
1203 if (!(isdigit(*cp)))
1204 goto fndhemi;
1205
1206 while (isdigit(*cp))
1207 secs = secs * 10 + (*cp++ - '0');
1208
1209 if (*cp == '.') { /* decimal seconds */
1210 cp++;
1211 if (isdigit(*cp)) {
1212 secsfrac = (*cp++ - '0') * 100;
1213 if (isdigit(*cp)) {
1214 secsfrac += (*cp++ - '0') * 10;
1215 if (isdigit(*cp)) {
1216 secsfrac += (*cp++ - '0');
1217 }
1218 }
1219 }
1220 }
1221
1222 while (!isspace(*cp)) /* if any trailing garbage */
1223 cp++;
1224
1225 while (isspace(*cp))
1226 cp++;
1227
1228 fndhemi:
1229 switch (*cp) {
1230 case 'N': case 'n':
1231 case 'E': case 'e':
1232 retval = ((unsigned)1<<31)
1233 + (((((deg * 60) + min) * 60) + secs) * 1000)
1234 + secsfrac;
1235 break;
1236 case 'S': case 's':
1237 case 'W': case 'w':
1238 retval = ((unsigned)1<<31)
1239 - (((((deg * 60) + min) * 60) + secs) * 1000)
1240 - secsfrac;
1241 break;
1242 default:
1243 retval = 0; /* invalid value -- indicates error */
1244 break;
1245 }
1246
1247 switch (*cp) {
1248 case 'N': case 'n':
1249 case 'S': case 's':
1250 *which = 1; /* latitude */
1251 break;
1252 case 'E': case 'e':
1253 case 'W': case 'w':
1254 *which = 2; /* longitude */
1255 break;
1256 default:
1257 *which = 0; /* error */
1258 break;
1259 }
1260
1261 cp++; /* skip the hemisphere */
1262
1263 while (!isspace(*cp)) /* if any trailing garbage */
1264 cp++;
1265
1266 while (isspace(*cp)) /* move to next field */
1267 cp++;
1268
1269 *latlonstrptr = cp;
1270
1271 return (retval);
1272 }
1273
1274 /* converts a zone file representation in a string to an RDATA on-the-wire
1275 * representation. */
1276 int
loc_aton(ascii,binary)1277 loc_aton(ascii, binary)
1278 const char *ascii;
1279 u_char *binary;
1280 {
1281 const unsigned char *maxcp;
1282 u_char *bcp;
1283 unsigned char *cp;
1284
1285 u_int32_t latit = 0, longit = 0, alt = 0;
1286 u_int32_t lltemp1 = 0, lltemp2 = 0;
1287 int altmeters = 0, altfrac = 0, altsign = 1;
1288 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
1289 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
1290 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
1291 int which1 = 0, which2 = 0;
1292
1293 cp = (unsigned char *)ascii;
1294 maxcp = cp + strlen(ascii);
1295
1296 lltemp1 = latlon2ul(&cp, &which1);
1297
1298 lltemp2 = latlon2ul(&cp, &which2);
1299
1300 switch (which1 + which2) {
1301 case 3: /* 1 + 2, the only valid combination */
1302 if ((which1 == 1) && (which2 == 2)) { /* normal case */
1303 latit = lltemp1;
1304 longit = lltemp2;
1305 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
1306 longit = lltemp1;
1307 latit = lltemp2;
1308 } else { /* some kind of brokenness */
1309 return (0);
1310 }
1311 break;
1312 default: /* we didn't get one of each */
1313 return (0);
1314 }
1315
1316 /* altitude */
1317 if (*cp == '-') {
1318 altsign = -1;
1319 cp++;
1320 }
1321
1322 if (*cp == '+')
1323 cp++;
1324
1325 while (isdigit(*cp))
1326 altmeters = altmeters * 10 + (*cp++ - '0');
1327
1328 if (*cp == '.') { /* decimal meters */
1329 cp++;
1330 if (isdigit(*cp)) {
1331 altfrac = (*cp++ - '0') * 10;
1332 if (isdigit(*cp)) {
1333 altfrac += (*cp++ - '0');
1334 }
1335 }
1336 }
1337
1338 alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
1339
1340 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1341 cp++;
1342
1343 while (isspace(*cp) && (cp < maxcp))
1344 cp++;
1345
1346 if (cp >= maxcp)
1347 goto defaults;
1348
1349 siz = precsize_aton(&cp);
1350
1351 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1352 cp++;
1353
1354 while (isspace(*cp) && (cp < maxcp))
1355 cp++;
1356
1357 if (cp >= maxcp)
1358 goto defaults;
1359
1360 hp = precsize_aton(&cp);
1361
1362 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1363 cp++;
1364
1365 while (isspace(*cp) && (cp < maxcp))
1366 cp++;
1367
1368 if (cp >= maxcp)
1369 goto defaults;
1370
1371 vp = precsize_aton(&cp);
1372
1373 defaults:
1374
1375 bcp = binary;
1376 *bcp++ = (u_int8_t) 0; /* version byte */
1377 *bcp++ = siz;
1378 *bcp++ = hp;
1379 *bcp++ = vp;
1380 DNSRES_PUTLONG(latit,bcp);
1381 DNSRES_PUTLONG(longit,bcp);
1382 DNSRES_PUTLONG(alt,bcp);
1383
1384 return (16); /* size of RR in octets */
1385 }
1386
1387 const char *
loc_ntoa(binary,ascii)1388 loc_ntoa(binary, ascii)
1389 const u_char *binary;
1390 char *ascii;
1391 {
1392 return loc_ntoal(binary, ascii, 255);
1393 }
1394
1395 /* takes an on-the-wire LOC RR and formats it in a human readable format. */
1396 static const char *
loc_ntoal(binary,ascii,ascii_len)1397 loc_ntoal(binary, ascii, ascii_len)
1398 const u_char *binary;
1399 char *ascii;
1400 int ascii_len;
1401 {
1402 static char *error = "?";
1403 register const u_char *cp = binary;
1404
1405 int latdeg, latmin, latsec, latsecfrac;
1406 int longdeg, longmin, longsec, longsecfrac;
1407 char northsouth, eastwest;
1408 int altmeters, altfrac, altsign;
1409
1410 const int referencealt = 100000 * 100;
1411
1412 int32_t latval, longval, altval;
1413 u_int32_t templ;
1414 u_int8_t sizeval, hpval, vpval, versionval;
1415
1416 char *sizestr, *hpstr, *vpstr;
1417
1418 versionval = *cp++;
1419
1420 if (versionval) {
1421 snprintf(ascii, ascii_len, "; error: unknown LOC RR version");
1422 return (ascii);
1423 }
1424
1425 sizeval = *cp++;
1426
1427 hpval = *cp++;
1428 vpval = *cp++;
1429
1430 DNSRES_GETLONG(templ, cp);
1431 latval = (templ - ((unsigned)1<<31));
1432
1433 DNSRES_GETLONG(templ, cp);
1434 longval = (templ - ((unsigned)1<<31));
1435
1436 DNSRES_GETLONG(templ, cp);
1437 if (templ < referencealt) { /* below WGS 84 spheroid */
1438 altval = referencealt - templ;
1439 altsign = -1;
1440 } else {
1441 altval = templ - referencealt;
1442 altsign = 1;
1443 }
1444
1445 if (latval < 0) {
1446 northsouth = 'S';
1447 latval = -latval;
1448 } else
1449 northsouth = 'N';
1450
1451 latsecfrac = latval % 1000;
1452 latval = latval / 1000;
1453 latsec = latval % 60;
1454 latval = latval / 60;
1455 latmin = latval % 60;
1456 latval = latval / 60;
1457 latdeg = latval;
1458
1459 if (longval < 0) {
1460 eastwest = 'W';
1461 longval = -longval;
1462 } else
1463 eastwest = 'E';
1464
1465 longsecfrac = longval % 1000;
1466 longval = longval / 1000;
1467 longsec = longval % 60;
1468 longval = longval / 60;
1469 longmin = longval % 60;
1470 longval = longval / 60;
1471 longdeg = longval;
1472
1473 altfrac = altval % 100;
1474 altmeters = (altval / 100) * altsign;
1475
1476 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1477 sizestr = error;
1478 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1479 hpstr = error;
1480 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1481 vpstr = error;
1482
1483 snprintf(ascii, ascii_len,
1484 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1485 latdeg, latmin, latsec, latsecfrac, northsouth,
1486 longdeg, longmin, longsec, longsecfrac, eastwest,
1487 altmeters, altfrac, sizestr, hpstr, vpstr);
1488
1489 if (sizestr != error)
1490 free(sizestr);
1491 if (hpstr != error)
1492 free(hpstr);
1493 if (vpstr != error)
1494 free(vpstr);
1495
1496 return (ascii);
1497 }
1498
1499
1500 /* Return the number of DNS hierarchy levels in the name. */
1501 int
__dnsres_dn_count_labels(name)1502 __dnsres_dn_count_labels(name)
1503 char *name;
1504 {
1505 int i, len, count;
1506
1507 len = strlen(name);
1508
1509 for(i = 0, count = 0; i < len; i++) {
1510 if (name[i] == '.')
1511 count++;
1512 }
1513
1514 /* don't count initial wildcard */
1515 if (name[0] == '*')
1516 if (count)
1517 count--;
1518
1519 /* don't count the null label for root. */
1520 /* if terminating '.' not found, must adjust */
1521 /* count to include last label */
1522 if (len > 0 && name[len-1] != '.')
1523 count++;
1524 return (count);
1525 }
1526
1527
1528 /*
1529 * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
1530 * SIG records are required to be printed like this, by the Secure DNS RFC.
1531 */
1532 char *
__dnsres_p_secstodate(secs)1533 __dnsres_p_secstodate (secs)
1534 unsigned long secs;
1535 {
1536 static char output[15]; /* YYYYMMDDHHMMSS and null */
1537 time_t clock = secs;
1538 struct tm *time;
1539
1540 time = gmtime(&clock);
1541 time->tm_year += 1900;
1542 time->tm_mon += 1;
1543 snprintf(output, sizeof output, "%04d%02d%02d%02d%02d%02d",
1544 time->tm_year, time->tm_mon, time->tm_mday,
1545 time->tm_hour, time->tm_min, time->tm_sec);
1546 return (output);
1547 }
1548