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