1 /*
2 * Copyright (c) 1985
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Portions copyright (c) 1999, 2000
6 * Intel Corporation.
7 * 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 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 *
23 * This product includes software developed by the University of
24 * California, Berkeley, Intel Corporation, and its contributors.
25 *
26 * 4. Neither the name of University, Intel Corporation, or their respective
27 * contributors may be used to endorse or promote products derived from
28 * this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
31 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
32 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
34 * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 *
42 */
43
44 /*
45 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
46 *
47 * Permission to use, copy, modify, and distribute this software for any
48 * purpose with or without fee is hereby granted, provided that the above
49 * copyright notice and this permission notice appear in all copies, and that
50 * the name of Digital Equipment Corporation not be used in advertising or
51 * publicity pertaining to distribution of the document or software without
52 * specific, written prior permission.
53 *
54 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
55 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
56 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
57 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
58 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
59 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
60 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
61 * SOFTWARE.
62 */
63
64 /*
65 * Portions Copyright (c) 1995 by International Business Machines, Inc.
66 *
67 * International Business Machines, Inc. (hereinafter called IBM) grants
68 * permission under its copyrights to use, copy, modify, and distribute this
69 * Software with or without fee, provided that the above copyright notice and
70 * all paragraphs of this notice appear in all copies, and that the name of IBM
71 * not be used in connection with the marketing of any product incorporating
72 * the Software or modifications thereof, without specific, written prior
73 * permission.
74 *
75 * To the extent it has a right to do so, IBM grants an immunity from suit
76 * under its patents, if any, for the use, sale or manufacture of products to
77 * the extent that such products are used for performing Domain Name System
78 * dynamic updates in TCP/IP networks by means of the Software. No immunity is
79 * granted for any product per se or for any other function of any product.
80 *
81 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
82 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
83 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
84 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
85 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
86 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
87 */
88
89 /*
90 * Portions Copyright (c) 1996 by Internet Software Consortium.
91 *
92 * Permission to use, copy, modify, and distribute this software for any
93 * purpose with or without fee is hereby granted, provided that the above
94 * copyright notice and this permission notice appear in all copies.
95 *
96 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
97 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
98 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
99 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
100 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
101 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
102 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
103 * SOFTWARE.
104 */
105
106 #if defined(LIBC_SCCS) && !defined(lint)
107 static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
108 static char rcsid[] = "$Id: res_debug.c,v 1.1.1.1 2003/11/19 01:51:36 kyu3 Exp $";
109 #endif /* LIBC_SCCS and not lint */
110
111 #include <sys/types.h>
112 #include <sys/param.h>
113 #include <sys/socket.h>
114
115 #include <netinet/in.h>
116 #include <arpa/inet.h>
117 #include <arpa/nameser.h>
118
119 #include <ctype.h>
120 #include <errno.h>
121 #include <math.h>
122 #include <netdb.h>
123 #include <resolv.h>
124 #include <stdio.h>
125 #include <stdlib.h>
126 #include <string.h>
127 #include <time.h>
128
129 #define SPRINTF(x) sprintf x
130
131 extern const char *_res_opcodes[];
132 extern const char *_res_resultcodes[];
133 extern const char *_res_sectioncodes[];
134
135 /*
136 * Print the current options.
137 */
138 void
fp_resstat(struct __res_state * statp,FILE * file)139 fp_resstat(struct __res_state *statp, FILE *file) {
140 u_long mask;
141
142 fprintf(file, ";; res options:");
143 if (!statp)
144 statp = &_res;
145 for (mask = 1; mask != 0; mask <<= 1)
146 if (statp->options & mask)
147 fprintf(file, " %s", p_option(mask));
148 putc('\n', file);
149 }
150
151 static void
do_section(ns_msg * handle,ns_sect section,int pflag,FILE * file)152 do_section(ns_msg *handle, ns_sect section, int pflag, FILE *file) {
153 int n, sflag, rrnum;
154 ns_opcode opcode;
155 ns_rr rr;
156
157 /*
158 * Print answer records.
159 */
160 sflag = (int)(_res.pfcode & pflag);
161 if (_res.pfcode && !sflag)
162 return;
163
164 opcode = ns_msg_getflag(*handle, ns_f_opcode);
165 rrnum = 0;
166 for (;;) {
167 if (ns_parserr(handle, section, rrnum, &rr)) {
168 if (errno != ENODEV)
169 fprintf(file, ";; ns_parserr: %s\n",
170 strerror(errno));
171 else if (rrnum > 0 && sflag != 0 &&
172 (_res.pfcode & RES_PRF_HEAD1))
173 putc('\n', file);
174 return;
175 }
176 if (rrnum == 0 && sflag != 0 && (_res.pfcode & RES_PRF_HEAD1))
177 fprintf(file, ";; %s SECTION:\n",
178 p_section(section, opcode));
179 if (section == ns_s_qd)
180 fprintf(file, ";;\t%s, type = %s, class = %s\n",
181 ns_rr_name(rr),
182 p_type(ns_rr_type(rr)),
183 p_class(ns_rr_class(rr)));
184 else {
185 char *buf;
186 buf = (char*)malloc(2024);
187 if (buf) {
188 n = ns_sprintrr(handle, &rr, NULL, NULL,
189 buf, sizeof buf);
190 if (n < 0) {
191 fprintf(file, ";; ns_sprintrr: %s\n",
192 strerror(errno));
193 free(buf);
194 return;
195 }
196 fputs(buf, file);
197 fputc('\n', file);
198 free(buf);
199 }
200 }
201 rrnum++;
202 }
203 }
204
205 void
p_query(const u_char * msg)206 p_query(const u_char *msg) {
207 fp_query(msg, stdout);
208 }
209
210 void
fp_query(const u_char * msg,FILE * file)211 fp_query(const u_char *msg, FILE *file) {
212 fp_nquery(msg, PACKETSZ, file);
213 }
214
215 /*
216 * Print the contents of a query.
217 * This is intended to be primarily a debugging routine.
218 */
219 void
fp_nquery(const u_char * msg,int len,FILE * file)220 fp_nquery(const u_char *msg, int len, FILE *file) {
221 ns_msg handle;
222 int qdcount, ancount, nscount, arcount;
223 u_int opcode, rcode, id;
224
225 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
226 return;
227
228 if (ns_initparse(msg, len, &handle) < 0) {
229 fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
230 return;
231 }
232 opcode = ns_msg_getflag(handle, ns_f_opcode);
233 rcode = ns_msg_getflag(handle, ns_f_rcode);
234 id = ns_msg_id(handle);
235 qdcount = ns_msg_count(handle, ns_s_qd);
236 ancount = ns_msg_count(handle, ns_s_an);
237 nscount = ns_msg_count(handle, ns_s_ns);
238 arcount = ns_msg_count(handle, ns_s_ar);
239
240 /*
241 * Print header fields.
242 */
243 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || rcode)
244 fprintf(file,
245 ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
246 _res_opcodes[opcode], _res_resultcodes[rcode], (int)id);
247 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
248 putc(';', file);
249 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
250 fprintf(file, "; flags:");
251 if (ns_msg_getflag(handle, ns_f_qr))
252 fprintf(file, " qr");
253 if (ns_msg_getflag(handle, ns_f_aa))
254 fprintf(file, " aa");
255 if (ns_msg_getflag(handle, ns_f_tc))
256 fprintf(file, " tc");
257 if (ns_msg_getflag(handle, ns_f_rd))
258 fprintf(file, " rd");
259 if (ns_msg_getflag(handle, ns_f_ra))
260 fprintf(file, " ra");
261 if (ns_msg_getflag(handle, ns_f_z))
262 fprintf(file, " ??");
263 if (ns_msg_getflag(handle, ns_f_ad))
264 fprintf(file, " ad");
265 if (ns_msg_getflag(handle, ns_f_cd))
266 fprintf(file, " cd");
267 }
268 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
269 fprintf(file, "; %s: %d",
270 p_section(ns_s_qd, (int)opcode), qdcount);
271 fprintf(file, ", %s: %d",
272 p_section(ns_s_an, (int)opcode), ancount);
273 fprintf(file, ", %s: %d",
274 p_section(ns_s_ns, (int)opcode), nscount);
275 fprintf(file, ", %s: %d",
276 p_section(ns_s_ar, (int)opcode), arcount);
277 }
278 if ((!_res.pfcode) || (_res.pfcode &
279 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
280 putc('\n',file);
281 }
282 /*
283 * Print the various sections.
284 */
285 do_section(&handle, ns_s_qd, RES_PRF_QUES, file);
286 do_section(&handle, ns_s_an, RES_PRF_ANS, file);
287 do_section(&handle, ns_s_ns, RES_PRF_AUTH, file);
288 do_section(&handle, ns_s_ar, RES_PRF_ADD, file);
289 if (qdcount == 0 && ancount == 0 &&
290 nscount == 0 && arcount == 0)
291 putc('\n', file);
292 }
293
294 const u_char *
p_cdnname(const u_char * cp,const u_char * msg,int len,FILE * file)295 p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
296 char name[MAXDNAME];
297 int n;
298
299 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
300 return (NULL);
301 if (name[0] == '\0')
302 putc('.', file);
303 else
304 fputs(name, file);
305 return (cp + n);
306 }
307
308 const u_char *
p_cdname(const u_char * cp,const u_char * msg,FILE * file)309 p_cdname(const u_char *cp, const u_char *msg, FILE *file) {
310 return (p_cdnname(cp, msg, PACKETSZ, file));
311 }
312
313 /* Return a fully-qualified domain name from a compressed name (with
314 length supplied). */
315
316 const u_char *
p_fqnname(const u_char * cp,const u_char * msg,int msglen,char * name,int namelen)317 p_fqnname(
318 const u_char *cp,
319 const u_char *msg,
320 int msglen,
321 char *name,
322 int namelen
323 )
324 {
325 int n, newlen;
326
327 if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
328 return (NULL);
329 newlen = (int)strlen(name);
330 if (newlen == 0 || name[newlen - 1] != '.') {
331 if (newlen + 1 >= namelen) /* Lack space for final dot */
332 return (NULL);
333 else
334 strcpy(name + newlen, ".");
335 }
336 return (cp + n);
337 }
338
339 /* XXX: the rest of these functions need to become length-limited, too. */
340
341 const u_char *
p_fqname(const u_char * cp,const u_char * msg,FILE * file)342 p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
343 char name[MAXDNAME];
344 const u_char *n;
345
346 n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
347 if (n == NULL)
348 return (NULL);
349 fputs(name, file);
350 return (n);
351 }
352
353 /*
354 * Names of RR classes and qclasses. Classes and qclasses are the same, except
355 * that C_ANY is a qclass but not a class. (You can ask for records of class
356 * C_ANY, but you can't have any records of that class in the database.)
357 */
358 const struct res_sym __p_class_syms[] = {
359 {C_IN, "IN"},
360 {C_CHAOS, "CHAOS"},
361 {C_HS, "HS"},
362 {C_HS, "HESIOD"},
363 {C_ANY, "ANY"},
364 {C_NONE, "NONE"},
365 {C_IN, (char *)0}
366 };
367
368 /*
369 * Names of message sections.
370 */
371 const struct res_sym __p_default_section_syms[] = {
372 {ns_s_qd, "QUERY"},
373 {ns_s_an, "ANSWER"},
374 {ns_s_ns, "AUTHORITY"},
375 {ns_s_ar, "ADDITIONAL"},
376 {0, (char *)0}
377 };
378
379 const struct res_sym __p_update_section_syms[] = {
380 {S_ZONE, "ZONE"},
381 {S_PREREQ, "PREREQUISITE"},
382 {S_UPDATE, "UPDATE"},
383 {S_ADDT, "ADDITIONAL"},
384 {0, (char *)0}
385 };
386
387 /*
388 * Names of RR types and qtypes. Types and qtypes are the same, except
389 * that T_ANY is a qtype but not a type. (You can ask for records of type
390 * T_ANY, but you can't have any records of that type in the database.)
391 */
392 const struct res_sym __p_type_syms[] = {
393 {T_A, "A", "address"},
394 {T_NS, "NS", "name server"},
395 {T_MD, "MD", "mail destination (deprecated)"},
396 {T_MF, "MF", "mail forwarder (deprecated)"},
397 {T_CNAME, "CNAME", "canonical name"},
398 {T_SOA, "SOA", "start of authority"},
399 {T_MB, "MB", "mailbox"},
400 {T_MG, "MG", "mail group member"},
401 {T_MR, "MR", "mail rename"},
402 {T_NULL, "NULL", "null"},
403 {T_WKS, "WKS", "well-known service (deprecated)"},
404 {T_PTR, "PTR", "domain name pointer"},
405 {T_HINFO, "HINFO", "host information"},
406 {T_MINFO, "MINFO", "mailbox information"},
407 {T_MX, "MX", "mail exchanger"},
408 {T_TXT, "TXT", "text"},
409 {T_RP, "RP", "responsible person"},
410 {T_AFSDB, "AFSDB", "DCE or AFS server"},
411 {T_X25, "X25", "X25 address"},
412 {T_ISDN, "ISDN", "ISDN address"},
413 {T_RT, "RT", "router"},
414 {T_NSAP, "NSAP", "nsap address"},
415 {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"},
416 {T_SIG, "SIG", "signature"},
417 {T_KEY, "KEY", "key"},
418 {T_PX, "PX", "mapping information"},
419 {T_GPOS, "GPOS", "geographical position (withdrawn)"},
420 {T_AAAA, "AAAA", "IPv6 address"},
421 {T_LOC, "LOC", "location"},
422 {T_NXT, "NXT", "next valid name (unimplemented)"},
423 {T_EID, "EID", "endpoint identifier (unimplemented)"},
424 {T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"},
425 {T_SRV, "SRV", "server selection"},
426 {T_ATMA, "ATMA", "ATM address (unimplemented)"},
427 {T_IXFR, "IXFR", "incremental zone transfer"},
428 {T_AXFR, "AXFR", "zone transfer"},
429 {T_MAILB, "MAILB", "mailbox-related data (deprecated)"},
430 {T_MAILA, "MAILA", "mail agent (deprecated)"},
431 {T_NAPTR, "NAPTR", "URN Naming Authority"},
432 {T_ANY, "ANY", "\"any\""},
433 {0, NULL, NULL}
434 };
435
436 int
sym_ston(const struct res_sym * syms,const char * name,int * success)437 sym_ston(const struct res_sym *syms, const char *name, int *success) {
438 for ((void)NULL; syms->name != 0; syms++) {
439 if (strcasecmp (name, syms->name) == 0) {
440 if (success)
441 *success = 1;
442 return (syms->number);
443 }
444 }
445 if (success)
446 *success = 0;
447 return (syms->number); /* The default value. */
448 }
449
450 const char *
sym_ntos(const struct res_sym * syms,int number,int * success)451 sym_ntos(const struct res_sym *syms, int number, int *success) {
452 static char unname[20];
453
454 for ((void)NULL; syms->name != 0; syms++) {
455 if (number == syms->number) {
456 if (success)
457 *success = 1;
458 return (syms->name);
459 }
460 }
461
462 sprintf(unname, "%d", number);
463 if (success)
464 *success = 0;
465 return (unname);
466 }
467
468 const char *
sym_ntop(const struct res_sym * syms,int number,int * success)469 sym_ntop(const struct res_sym *syms, int number, int *success) {
470 static char unname[20];
471
472 for ((void)NULL; syms->name != 0; syms++) {
473 if (number == syms->number) {
474 if (success)
475 *success = 1;
476 return (syms->humanname);
477 }
478 }
479 sprintf(unname, "%d", number);
480 if (success)
481 *success = 0;
482 return (unname);
483 }
484
485 /*
486 * Return a string for the type.
487 */
488 const char *
p_type(int type)489 p_type(int type) {
490 return (sym_ntos(__p_type_syms, type, (int *)0));
491 }
492
493 /*
494 * Return a string for the type.
495 */
496 const char *
p_section(int section,int opcode)497 p_section(int section, int opcode) {
498 const struct res_sym *symbols;
499
500 switch (opcode) {
501 case ns_o_update:
502 symbols = __p_update_section_syms;
503 break;
504 default:
505 symbols = __p_default_section_syms;
506 break;
507 }
508 return (sym_ntos(symbols, section, (int *)0));
509 }
510
511 /*
512 * Return a mnemonic for class.
513 */
514 const char *
p_class(int class)515 p_class(int class) {
516 return (sym_ntos(__p_class_syms, class, (int *)0));
517 }
518
519 /*
520 * Return a mnemonic for an option
521 */
522 const char *
p_option(u_long option)523 p_option(u_long option) {
524 static char nbuf[40];
525
526 switch (option) {
527 case RES_INIT: return "init";
528 case RES_DEBUG: return "debug";
529 case RES_AAONLY: return "aaonly(unimpl)";
530 case RES_USEVC: return "usevc";
531 case RES_PRIMARY: return "primry(unimpl)";
532 case RES_IGNTC: return "igntc";
533 case RES_RECURSE: return "recurs";
534 case RES_DEFNAMES: return "defnam";
535 case RES_STAYOPEN: return "styopn";
536 case RES_DNSRCH: return "dnsrch";
537 case RES_INSECURE1: return "insecure1";
538 case RES_INSECURE2: return "insecure2";
539 default: sprintf(nbuf, "?0x%lx?", (unsigned long)option);
540 return (nbuf);
541 }
542 }
543
544 /*
545 * Return a mnemonic for a time to live.
546 */
547 const char *
p_time(u_int32_t value)548 p_time(u_int32_t value) {
549 static char nbuf[40];
550
551 if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0)
552 sprintf(nbuf, "%u", value);
553 return (nbuf);
554 }
555
556
557 /*
558 * routines to convert between on-the-wire RR format and zone file format.
559 * Does not contain conversion to/from decimal degrees; divide or multiply
560 * by 60*60*1000 for that.
561 */
562
563 static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
564 1000000,10000000,100000000,1000000000};
565
566 /* takes an XeY precision/size value, returns a string representation. */
567 static const char *
precsize_ntoa(u_int8_t prec)568 precsize_ntoa(
569 u_int8_t prec
570 )
571 {
572 static char retbuf[sizeof "90000000.00"];
573 unsigned long val;
574 int mantissa, exponent;
575
576 mantissa = (int)((prec >> 4) & 0x0f) % 10;
577 exponent = (int)((prec >> 0) & 0x0f) % 10;
578
579 val = mantissa * poweroften[exponent];
580
581 (void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100);
582 return (retbuf);
583 }
584
585 /* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
586 static u_int8_t
precsize_aton(char ** strptr)587 precsize_aton(
588 char **strptr
589 )
590 {
591 unsigned int mval = 0, cmval = 0;
592 u_int8_t retval = 0;
593 char *cp;
594 int exponent;
595 int mantissa;
596
597 cp = *strptr;
598
599 while (isdigit(*cp))
600 mval = mval * 10 + (*cp++ - '0');
601
602 if (*cp == '.') { /* centimeters */
603 cp++;
604 if (isdigit(*cp)) {
605 cmval = (*cp++ - '0') * 10;
606 if (isdigit(*cp)) {
607 cmval += (*cp++ - '0');
608 }
609 }
610 }
611 cmval = (mval * 100) + cmval;
612
613 for (exponent = 0; exponent < 9; exponent++)
614 if (cmval < poweroften[exponent+1])
615 break;
616
617 mantissa = cmval / poweroften[exponent];
618 if (mantissa > 9)
619 mantissa = 9;
620
621 retval = (u_int8_t)((mantissa << 4) | exponent);
622
623 *strptr = cp;
624
625 return (retval);
626 }
627
628 /* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
629 static u_int32_t
latlon2ul(char ** latlonstrptr,int * which)630 latlon2ul(
631 char **latlonstrptr,
632 int *which
633 )
634 {
635 char *cp;
636 u_int32_t retval;
637 int deg = 0, min = 0, secs = 0, secsfrac = 0;
638
639 cp = *latlonstrptr;
640
641 while (isdigit(*cp))
642 deg = deg * 10 + (*cp++ - '0');
643
644 while (isspace(*cp))
645 cp++;
646
647 if (!(isdigit(*cp)))
648 goto fndhemi;
649
650 while (isdigit(*cp))
651 min = min * 10 + (*cp++ - '0');
652
653 while (isspace(*cp))
654 cp++;
655
656 if (!(isdigit(*cp)))
657 goto fndhemi;
658
659 while (isdigit(*cp))
660 secs = secs * 10 + (*cp++ - '0');
661
662 if (*cp == '.') { /* decimal seconds */
663 cp++;
664 if (isdigit(*cp)) {
665 secsfrac = (*cp++ - '0') * 100;
666 if (isdigit(*cp)) {
667 secsfrac += (*cp++ - '0') * 10;
668 if (isdigit(*cp)) {
669 secsfrac += (*cp++ - '0');
670 }
671 }
672 }
673 }
674
675 while (!isspace(*cp)) /* if any trailing garbage */
676 cp++;
677
678 while (isspace(*cp))
679 cp++;
680
681 fndhemi:
682 switch (*cp) {
683 case 'N': case 'n':
684 case 'E': case 'e':
685 retval = ((unsigned)1<<31)
686 + (((((deg * 60) + min) * 60) + secs) * 1000)
687 + secsfrac;
688 break;
689 case 'S': case 's':
690 case 'W': case 'w':
691 retval = ((unsigned)1<<31)
692 - (((((deg * 60) + min) * 60) + secs) * 1000)
693 - secsfrac;
694 break;
695 default:
696 retval = 0; /* invalid value -- indicates error */
697 break;
698 }
699
700 switch (*cp) {
701 case 'N': case 'n':
702 case 'S': case 's':
703 *which = 1; /* latitude */
704 break;
705 case 'E': case 'e':
706 case 'W': case 'w':
707 *which = 2; /* longitude */
708 break;
709 default:
710 *which = 0; /* error */
711 break;
712 }
713
714 cp++; /* skip the hemisphere */
715
716 while (!isspace(*cp)) /* if any trailing garbage */
717 cp++;
718
719 while (isspace(*cp)) /* move to next field */
720 cp++;
721
722 *latlonstrptr = cp;
723
724 return (retval);
725 }
726
727 /* converts a zone file representation in a string to an RDATA on-the-wire
728 * representation. */
729 int
loc_aton(const char * ascii,u_char * binary)730 loc_aton(
731 const char *ascii,
732 u_char *binary
733 )
734 {
735 const char *cp, *maxcp;
736 u_char *bcp;
737
738 u_int32_t latit = 0, longit = 0, alt = 0;
739 u_int32_t lltemp1 = 0, lltemp2 = 0;
740 int altmeters = 0, altfrac = 0, altsign = 1;
741 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
742 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
743 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
744 int which1 = 0, which2 = 0;
745
746 cp = ascii;
747 maxcp = cp + strlen(ascii);
748
749 lltemp1 = latlon2ul((char **)&cp, &which1);
750
751 lltemp2 = latlon2ul((char **)&cp, &which2);
752
753 switch (which1 + which2) {
754 case 3: /* 1 + 2, the only valid combination */
755 if ((which1 == 1) && (which2 == 2)) { /* normal case */
756 latit = lltemp1;
757 longit = lltemp2;
758 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
759 longit = lltemp1;
760 latit = lltemp2;
761 } else { /* some kind of brokenness */
762 return (0);
763 }
764 break;
765 default: /* we didn't get one of each */
766 return (0);
767 }
768
769 /* altitude */
770 if (*cp == '-') {
771 altsign = -1;
772 cp++;
773 }
774
775 if (*cp == '+')
776 cp++;
777
778 while (isdigit(*cp))
779 altmeters = altmeters * 10 + (*cp++ - '0');
780
781 if (*cp == '.') { /* decimal meters */
782 cp++;
783 if (isdigit(*cp)) {
784 altfrac = (*cp++ - '0') * 10;
785 if (isdigit(*cp)) {
786 altfrac += (*cp++ - '0');
787 }
788 }
789 }
790
791 alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
792
793 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
794 cp++;
795
796 while (isspace(*cp) && (cp < maxcp))
797 cp++;
798
799 if (cp >= maxcp)
800 goto defaults;
801
802 siz = precsize_aton((char **)&cp);
803
804 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
805 cp++;
806
807 while (isspace(*cp) && (cp < maxcp))
808 cp++;
809
810 if (cp >= maxcp)
811 goto defaults;
812
813 hp = precsize_aton((char **)&cp);
814
815 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
816 cp++;
817
818 while (isspace(*cp) && (cp < maxcp))
819 cp++;
820
821 if (cp >= maxcp)
822 goto defaults;
823
824 vp = precsize_aton((char **)&cp);
825
826 defaults:
827
828 bcp = binary;
829 *bcp++ = (u_int8_t) 0; /* version byte */
830 *bcp++ = siz;
831 *bcp++ = hp;
832 *bcp++ = vp;
833 PUTLONG(latit,bcp);
834 PUTLONG(longit,bcp);
835 PUTLONG(alt,bcp);
836
837 return (16); /* size of RR in octets */
838 }
839
840 /* takes an on-the-wire LOC RR and formats it in a human readable format. */
841 const char *
loc_ntoa(const u_char * binary,char * ascii)842 loc_ntoa(
843 const u_char *binary,
844 char *ascii
845 )
846 {
847 static char *error = "?";
848 const u_char *cp = binary;
849
850 int latdeg, latmin, latsec, latsecfrac;
851 int longdeg, longmin, longsec, longsecfrac;
852 char northsouth, eastwest;
853 int altmeters, altfrac, altsign;
854
855 const u_int32_t referencealt = 100000 * 100;
856
857 int32_t latval, longval, altval;
858 u_int32_t templ;
859 u_int8_t sizeval, hpval, vpval, versionval;
860
861 char *sizestr, *hpstr, *vpstr;
862
863 versionval = *cp++;
864
865 if (versionval) {
866 (void) sprintf(ascii, "; error: unknown LOC RR version");
867 return (ascii);
868 }
869
870 sizeval = *cp++;
871
872 hpval = *cp++;
873 vpval = *cp++;
874
875 GETLONG(templ, cp);
876 latval = (templ - ((unsigned)1<<31));
877
878 GETLONG(templ, cp);
879 longval = (templ - ((unsigned)1<<31));
880
881 GETLONG(templ, cp);
882 if (templ < referencealt) { /* below WGS 84 spheroid */
883 altval = referencealt - templ;
884 altsign = -1;
885 } else {
886 altval = templ - referencealt;
887 altsign = 1;
888 }
889
890 if (latval < 0) {
891 northsouth = 'S';
892 latval = -latval;
893 } else
894 northsouth = 'N';
895
896 latsecfrac = latval % 1000;
897 latval = latval / 1000;
898 latsec = latval % 60;
899 latval = latval / 60;
900 latmin = latval % 60;
901 latval = latval / 60;
902 latdeg = latval;
903
904 if (longval < 0) {
905 eastwest = 'W';
906 longval = -longval;
907 } else
908 eastwest = 'E';
909
910 longsecfrac = longval % 1000;
911 longval = longval / 1000;
912 longsec = longval % 60;
913 longval = longval / 60;
914 longmin = longval % 60;
915 longval = longval / 60;
916 longdeg = longval;
917
918 altfrac = altval % 100;
919 altmeters = (altval / 100) * altsign;
920
921 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
922 sizestr = error;
923 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
924 hpstr = error;
925 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
926 vpstr = error;
927
928 sprintf(ascii,
929 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
930 latdeg, latmin, latsec, latsecfrac, northsouth,
931 longdeg, longmin, longsec, longsecfrac, eastwest,
932 altmeters, altfrac, sizestr, hpstr, vpstr);
933
934 if (sizestr != error)
935 free(sizestr);
936 if (hpstr != error)
937 free(hpstr);
938 if (vpstr != error)
939 free(vpstr);
940
941 return (ascii);
942 }
943
944
945 /* Return the number of DNS hierarchy levels in the name. */
946 int
dn_count_labels(const char * name)947 dn_count_labels(const char *name) {
948 int i, len, count;
949
950 len = (int)strlen(name);
951 for (i = 0, count = 0; i < len; i++) {
952 /* XXX need to check for \. or use named's nlabels(). */
953 if (name[i] == '.')
954 count++;
955 }
956
957 /* don't count initial wildcard */
958 if (name[0] == '*')
959 if (count)
960 count--;
961
962 /* don't count the null label for root. */
963 /* if terminating '.' not found, must adjust */
964 /* count to include last label */
965 if (len > 0 && name[len-1] != '.')
966 count++;
967 return (count);
968 }
969
970
971 /*
972 * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
973 * SIG records are required to be printed like this, by the Secure DNS RFC.
974 */
975 char *
p_secstodate(u_long secs)976 p_secstodate (u_long secs) {
977 static char output[15]; /* YYYYMMDDHHMMSS and null */
978 time_t clock = (time_t)secs;
979 struct tm *time;
980
981 time = gmtime(&clock);
982 time->tm_year += 1900;
983 time->tm_mon += 1;
984 sprintf(output, "%04d%02d%02d%02d%02d%02d",
985 time->tm_year, time->tm_mon, time->tm_mday,
986 time->tm_hour, time->tm_min, time->tm_sec);
987 return (output);
988 }
989