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