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  * 4. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 /*
31  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
32  *
33  * Permission to use, copy, modify, and distribute this software for any
34  * purpose with or without fee is hereby granted, provided that the above
35  * copyright notice and this permission notice appear in all copies, and that
36  * the name of Digital Equipment Corporation not be used in advertising or
37  * publicity pertaining to distribution of the document or software without
38  * specific, written prior permission.
39  *
40  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
41  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
43  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
44  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
45  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
46  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47  * SOFTWARE.
48  */
49 
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  */
74 
75 /*
76  * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
77  *
78  * Permission to use, copy, modify, and distribute this software for any
79  * purpose with or without fee is hereby granted, provided that the above
80  * copyright notice and this permission notice appear in all copies.
81  *
82  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
83  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
84  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
85  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
86  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
87  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
88  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
89  * SOFTWARE.
90  */
91 
92 #include <sys/types.h>
93 #include <sys/param.h>
94 #include <sys/socket.h>
95 
96 #include <netinet/in.h>
97 #include <arpa/inet.h>
98 #include <arpa/nameser.h>
99 
100 #include <ctype.h>
101 #include <errno.h>
102 #include <math.h>
103 #include <netdb.h>
104 #include <resolv/resolv-internal.h>
105 #include <stdio.h>
106 #include <stdlib.h>
107 #include <string.h>
108 #include <time.h>
109 #include <shlib-compat.h>
110 #include <libc-diag.h>
111 
112 #ifdef SPRINTF_CHAR
113 # define SPRINTF(x) strlen(sprintf/**/x)
114 #else
115 # define SPRINTF(x) sprintf x
116 #endif
117 
118 extern const char *_res_sectioncodes[] attribute_hidden;
119 
120 /* _res_opcodes was exported by accident as a variable.  */
121 #if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_26)
122 static const char *res_opcodes[] =
123 #else
124 static const char res_opcodes[][9] =
125 #endif
126   {
127     "QUERY",
128     "IQUERY",
129     "CQUERYM",
130     "CQUERYU",	/* experimental */
131     "NOTIFY",	/* experimental */
132     "UPDATE",
133     "6",
134     "7",
135     "8",
136     "9",
137     "10",
138     "11",
139     "12",
140     "13",
141     "ZONEINIT",
142     "ZONEREF",
143   };
144 #if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_26)
145 strong_alias (res_opcodes, _res_opcodes)
146 #endif
147 
148 static const char *p_section(int section, int opcode);
149 
150 /*
151  * Print the current options.
152  */
153 void
fp_resstat(const res_state statp,FILE * file)154 fp_resstat(const res_state statp, FILE *file) {
155 	u_long mask;
156 
157 	fprintf(file, ";; res options:");
158 	for (mask = 1;  mask != 0;  mask <<= 1)
159 		if (statp->options & mask)
160 			fprintf(file, " %s", p_option(mask));
161 	putc('\n', file);
162 }
163 
164 static void
do_section(int pfcode,ns_msg * handle,ns_sect section,int pflag,FILE * file)165 do_section (int pfcode, ns_msg *handle, ns_sect section, int pflag, FILE *file)
166 {
167 	int n, sflag, rrnum;
168 	static int buflen = 2048;
169 	char *buf;
170 	ns_opcode opcode;
171 	ns_rr rr;
172 
173 	/*
174 	 * Print answer records.
175 	 */
176 	sflag = (pfcode & pflag);
177 	if (pfcode && !sflag)
178 		return;
179 
180 	buf = malloc(buflen);
181 	if (buf == NULL) {
182 		fprintf(file, ";; memory allocation failure\n");
183 		return;
184 	}
185 
186 	opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode);
187 	rrnum = 0;
188 	for (;;) {
189 		if (ns_parserr(handle, section, rrnum, &rr)) {
190 			if (errno != ENODEV)
191 				fprintf(file, ";; ns_parserr: %s\n",
192 					strerror(errno));
193 			else if (rrnum > 0 && sflag != 0 &&
194 				 (pfcode & RES_PRF_HEAD1))
195 				putc('\n', file);
196 			goto cleanup;
197 		}
198 		if (rrnum == 0 && sflag != 0 && (pfcode & RES_PRF_HEAD1))
199 			fprintf(file, ";; %s SECTION:\n",
200 				p_section(section, opcode));
201 		if (section == ns_s_qd)
202 			fprintf(file, ";;\t%s, type = %s, class = %s\n",
203 				ns_rr_name(rr),
204 				p_type(ns_rr_type(rr)),
205 				p_class(ns_rr_class(rr)));
206 		else {
207 			n = ns_sprintrr(handle, &rr, NULL, NULL,
208 					buf, buflen);
209 			if (n < 0) {
210 				if (errno == ENOSPC) {
211 					free(buf);
212 					buf = NULL;
213 					if (buflen < 131072)
214 						buf = malloc(buflen += 1024);
215 					if (buf == NULL) {
216 						fprintf(file,
217 					      ";; memory allocation failure\n");
218 					      return;
219 					}
220 					continue;
221 				}
222 				fprintf(file, ";; ns_sprintrr: %s\n",
223 					strerror(errno));
224 				goto cleanup;
225 			}
226 			fputs(buf, file);
227 			fputc('\n', file);
228 		}
229 		rrnum++;
230 	}
231  cleanup:
232 	free(buf);
233 }
234 
235 /*
236  * Print the contents of a query.
237  * This is intended to be primarily a debugging routine.
238  */
239 void
fp_nquery(const unsigned char * msg,int len,FILE * file)240 fp_nquery (const unsigned char *msg, int len, FILE *file)
241 {
242 	ns_msg handle;
243 	int qdcount, ancount, nscount, arcount;
244 	u_int opcode, rcode, id;
245 
246 	/* There is no need to initialize _res: If _res is not yet
247 	   initialized, _res.pfcode is zero.  But initialization will
248 	   leave it at zero, too.  _res.pfcode is an unsigned long,
249 	   but the code here assumes that the flags fit into an int,
250 	   so use that.  */
251 	int pfcode = _res.pfcode;
252 
253 	if (ns_initparse(msg, len, &handle) < 0) {
254 		fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
255 		return;
256 	}
257 	opcode = ns_msg_getflag(handle, ns_f_opcode);
258 	rcode = ns_msg_getflag(handle, ns_f_rcode);
259 	id = ns_msg_id(handle);
260 	qdcount = ns_msg_count(handle, ns_s_qd);
261 	ancount = ns_msg_count(handle, ns_s_an);
262 	nscount = ns_msg_count(handle, ns_s_ns);
263 	arcount = ns_msg_count(handle, ns_s_ar);
264 
265 	/*
266 	 * Print header fields.
267 	 */
268 	if ((!pfcode) || (pfcode & RES_PRF_HEADX) || rcode)
269 		fprintf(file,
270 			";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
271 			res_opcodes[opcode], p_rcode(rcode), id);
272 	if ((!pfcode) || (pfcode & RES_PRF_HEADX))
273 		putc(';', file);
274 	if ((!pfcode) || (pfcode & RES_PRF_HEAD2)) {
275 		fprintf(file, "; flags:");
276 		if (ns_msg_getflag(handle, ns_f_qr))
277 			fprintf(file, " qr");
278 		if (ns_msg_getflag(handle, ns_f_aa))
279 			fprintf(file, " aa");
280 		if (ns_msg_getflag(handle, ns_f_tc))
281 			fprintf(file, " tc");
282 		if (ns_msg_getflag(handle, ns_f_rd))
283 			fprintf(file, " rd");
284 		if (ns_msg_getflag(handle, ns_f_ra))
285 			fprintf(file, " ra");
286 		if (ns_msg_getflag(handle, ns_f_z))
287 			fprintf(file, " ??");
288 		if (ns_msg_getflag(handle, ns_f_ad))
289 			fprintf(file, " ad");
290 		if (ns_msg_getflag(handle, ns_f_cd))
291 			fprintf(file, " cd");
292 	}
293 	if ((!pfcode) || (pfcode & RES_PRF_HEAD1)) {
294 		fprintf(file, "; %s: %d",
295 			p_section(ns_s_qd, opcode), qdcount);
296 		fprintf(file, ", %s: %d",
297 			p_section(ns_s_an, opcode), ancount);
298 		fprintf(file, ", %s: %d",
299 			p_section(ns_s_ns, opcode), nscount);
300 		fprintf(file, ", %s: %d",
301 			p_section(ns_s_ar, opcode), arcount);
302 	}
303 	if ((!pfcode) || (pfcode &
304 		(RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
305 		putc('\n',file);
306 	}
307 	/*
308 	 * Print the various sections.
309 	 */
310 	do_section (pfcode, &handle, ns_s_qd, RES_PRF_QUES, file);
311 	do_section (pfcode, &handle, ns_s_an, RES_PRF_ANS, file);
312 	do_section (pfcode, &handle, ns_s_ns, RES_PRF_AUTH, file);
313 	do_section (pfcode, &handle, ns_s_ar, RES_PRF_ADD, file);
314 	if (qdcount == 0 && ancount == 0 &&
315 	    nscount == 0 && arcount == 0)
316 		putc('\n', file);
317 }
libresolv_hidden_def(fp_nquery)318 libresolv_hidden_def (fp_nquery)
319 
320 void
321 fp_query (const unsigned char *msg, FILE *file)
322 {
323   fp_nquery (msg, PACKETSZ, file);
324 }
libresolv_hidden_def(fp_query)325 libresolv_hidden_def (fp_query)
326 
327 void
328 p_query (const unsigned char *msg)
329 {
330   fp_query (msg, stdout);
331 }
332 
333 const u_char *
p_cdnname(const u_char * cp,const u_char * msg,int len,FILE * file)334 p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
335 	char name[MAXDNAME];
336 	int n;
337 
338 	if ((n = __libc_dn_expand (msg, msg + len, cp, name, sizeof name)) < 0)
339 		return (NULL);
340 	if (name[0] == '\0')
341 		putc('.', file);
342 	else
343 		fputs(name, file);
344 	return (cp + n);
345 }
libresolv_hidden_def(p_cdnname)346 libresolv_hidden_def (p_cdnname)
347 
348 const u_char *
349 p_cdname(const u_char *cp, const u_char *msg, FILE *file) {
350 	return (p_cdnname(cp, msg, PACKETSZ, file));
351 }
352 
353 /* Return a fully-qualified domain name from a compressed name (with
354    length supplied).  */
355 
356 const u_char *
p_fqnname(const u_char * cp,const u_char * msg,int msglen,char * name,int namelen)357 p_fqnname (const u_char *cp, const u_char *msg, int msglen, char *name,
358 	   int namelen)
359 {
360 	int n, newlen;
361 
362 	if ((n = __libc_dn_expand (msg, cp + msglen, cp, name, namelen)) < 0)
363 		return (NULL);
364 	newlen = strlen(name);
365 	if (newlen == 0 || name[newlen - 1] != '.') {
366 		if (newlen + 1 >= namelen)	/* Lack space for final dot */
367 			return (NULL);
368 		else
369 			strcpy(name + newlen, ".");
370 	}
371 	return (cp + n);
372 }
libresolv_hidden_def(p_fqnname)373 libresolv_hidden_def (p_fqnname)
374 
375 /* XXX:	the rest of these functions need to become length-limited, too. */
376 
377 const u_char *
378 p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
379 	char name[MAXDNAME];
380 	const u_char *n;
381 
382 	n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
383 	if (n == NULL)
384 		return (NULL);
385 	fputs(name, file);
386 	return (n);
387 }
388 
389 /*
390  * Names of RR classes and qclasses.  Classes and qclasses are the same, except
391  * that C_ANY is a qclass but not a class.  (You can ask for records of class
392  * C_ANY, but you can't have any records of that class in the database.)
393  */
394 extern const struct res_sym __p_class_syms[];
395 libresolv_hidden_proto (__p_class_syms)
396 const struct res_sym __p_class_syms[] = {
397   {C_IN,    (char *) "IN"},
398   {C_CHAOS, (char *) "CHAOS"},
399   {C_HS,    (char *) "HS"},
400   {C_HS,    (char *) "HESIOD"},
401   {C_ANY,   (char *) "ANY"},
402   {C_NONE,  (char *) "NONE"},
403   {C_IN, NULL, NULL}
404 };
405 libresolv_hidden_data_def (__p_class_syms)
406 
407 /*
408  * Names of message sections.
409  */
410 const struct res_sym __p_default_section_syms[] attribute_hidden = {
411   {ns_s_qd, (char *) "QUERY"},
412   {ns_s_an, (char *) "ANSWER"},
413   {ns_s_ns, (char *) "AUTHORITY"},
414   {ns_s_ar, (char *) "ADDITIONAL"},
415   {0, NULL, NULL}
416 };
417 
418 const struct res_sym __p_update_section_syms[] attribute_hidden = {
419   {S_ZONE,   (char *) "ZONE"},
420   {S_PREREQ, (char *) "PREREQUISITE"},
421   {S_UPDATE, (char *) "UPDATE"},
422   {S_ADDT,   (char *) "ADDITIONAL"},
423   {0, NULL, NULL}
424 };
425 
426 /*
427  * Names of RR types and qtypes.  The list is incomplete because its
428  * size is part of the ABI.
429  */
430 extern const struct res_sym __p_type_syms[];
431 libresolv_hidden_proto (__p_type_syms)
432 const struct res_sym __p_type_syms[] = {
433   {ns_t_a,      (char *) "A",     (char *) "address"},
434   {ns_t_ns,     (char *) "NS",    (char *) "name server"},
435   {ns_t_md,     (char *) "MD",    (char *) "mail destination (deprecated)"},
436   {ns_t_mf,     (char *) "MF",    (char *) "mail forwarder (deprecated)"},
437   {ns_t_cname,  (char *) "CNAME", (char *) "canonical name"},
438   {ns_t_soa,    (char *) "SOA",   (char *) "start of authority"},
439   {ns_t_mb,     (char *) "MB",    (char *) "mailbox"},
440   {ns_t_mg,     (char *) "MG",    (char *) "mail group member"},
441   {ns_t_mr,     (char *) "MR",    (char *) "mail rename"},
442   {ns_t_null,   (char *) "NULL",  (char *) "null"},
443   {ns_t_wks,    (char *) "WKS",   (char *) "well-known service (deprecated)"},
444   {ns_t_ptr,    (char *) "PTR",   (char *) "domain name pointer"},
445   {ns_t_hinfo,  (char *) "HINFO", (char *) "host information"},
446   {ns_t_minfo,  (char *) "MINFO", (char *) "mailbox information"},
447   {ns_t_mx,     (char *) "MX",    (char *) "mail exchanger"},
448   {ns_t_txt,    (char *) "TXT",   (char *) "text"},
449   {ns_t_rp,     (char *) "RP",    (char *) "responsible person"},
450   {ns_t_afsdb,  (char *) "AFSDB", (char *) "DCE or AFS server"},
451   {ns_t_x25,    (char *) "X25",   (char *) "X25 address"},
452   {ns_t_isdn,   (char *) "ISDN",  (char *) "ISDN address"},
453   {ns_t_rt,     (char *) "RT",    (char *) "router"},
454   {ns_t_nsap,   (char *) "NSAP",  (char *) "nsap address"},
455   {ns_t_nsap_ptr, (char *) "NSAP_PTR", (char *) "domain name pointer"},
456   {ns_t_sig,    (char *) "SIG",   (char *) "signature"},
457   {ns_t_key,    (char *) "KEY",   (char *) "key"},
458   {ns_t_px,     (char *) "PX",    (char *) "mapping information"},
459   {ns_t_gpos,   (char *) "GPOS",
460    (char *) "geographical position (withdrawn)"},
461   {ns_t_aaaa,   (char *) "AAAA",  (char *) "IPv6 address"},
462   {ns_t_loc,    (char *) "LOC",   (char *) "location"},
463   {ns_t_nxt,    (char *) "NXT",   (char *) "next valid name (unimplemented)"},
464   {ns_t_eid,    (char *) "EID",   (char *) "endpoint identifier (unimplemented)"},
465   {ns_t_nimloc, (char *) "NIMLOC", (char *) "NIMROD locator (unimplemented)"},
466   {ns_t_srv,    (char *) "SRV",   (char *) "server selection"},
467   {ns_t_atma,   (char *) "ATMA",  (char *) "ATM address (unimplemented)"},
468   {ns_t_dname,  (char *) "DNAME", (char *) "Non-terminal DNAME (for IPv6)"},
469   {ns_t_tsig,   (char *) "TSIG",  (char *) "transaction signature"},
470   {ns_t_ixfr,   (char *) "IXFR",  (char *) "incremental zone transfer"},
471   {ns_t_axfr,   (char *) "AXFR",  (char *) "zone transfer"},
472   {ns_t_mailb,  (char *) "MAILB", (char *) "mailbox-related data (deprecated)"},
473   {ns_t_maila,  (char *) "MAILA", (char *) "mail agent (deprecated)"},
474   {ns_t_naptr,  (char *) "NAPTR", (char *) "URN Naming Authority"},
475   {ns_t_kx,     (char *) "KX",    (char *) "Key Exchange"},
476   {ns_t_cert,   (char *) "CERT",  (char *) "Certificate"},
477   {ns_t_any,    (char *) "ANY",   (char *) "\"any\""},
478   {0, NULL, NULL},		/* Padding to preserve ABI.  */
479   {0, NULL, NULL}
480 };
481 libresolv_hidden_data_def (__p_type_syms)
482 
483 /*
484  * Names of DNS rcodes.
485  */
486 const struct res_sym __p_rcode_syms[] attribute_hidden = {
487   {ns_r_noerror,  (char *) "NOERROR",  (char *) "no error"},
488   {ns_r_formerr,  (char *) "FORMERR",  (char *) "format error"},
489   {ns_r_servfail, (char *) "SERVFAIL", (char *) "server failed"},
490   {ns_r_nxdomain, (char *) "NXDOMAIN", (char *) "no such domain name"},
491   {ns_r_notimpl,  (char *) "NOTIMP",   (char *) "not implemented"},
492   {ns_r_refused,  (char *) "REFUSED",  (char *) "refused"},
493   {ns_r_yxdomain, (char *) "YXDOMAIN", (char *) "domain name exists"},
494   {ns_r_yxrrset,  (char *) "YXRRSET",  (char *) "rrset exists"},
495   {ns_r_nxrrset,  (char *) "NXRRSET",  (char *) "rrset doesn't exist"},
496   {ns_r_notauth,  (char *) "NOTAUTH",  (char *) "not authoritative"},
497   {ns_r_notzone,  (char *) "NOTZONE",  (char *) "Not in zone"},
498   {ns_r_max,      (char *) "",         (char *) ""},
499   {ns_r_badsig,   (char *) "BADSIG",   (char *) "bad signature"},
500   {ns_r_badkey,   (char *) "BADKEY",   (char *) "bad key"},
501   {ns_r_badtime,  (char *) "BADTIME",  (char *) "bad time"},
502   {0, NULL, NULL}
503 };
504 
505 int
sym_ston(const struct res_sym * syms,const char * name,int * success)506 sym_ston(const struct res_sym *syms, const char *name, int *success) {
507 	for ((void)NULL; syms->name != 0; syms++) {
508 		if (strcasecmp (name, syms->name) == 0) {
509 			if (success)
510 				*success = 1;
511 			return (syms->number);
512 		}
513 	}
514 	if (success)
515 		*success = 0;
516 	return (syms->number);		/* The default value. */
517 }
518 
519 const char *
sym_ntos(const struct res_sym * syms,int number,int * success)520 sym_ntos(const struct res_sym *syms, int number, int *success) {
521 	static char unname[20];
522 
523 	for ((void)NULL; syms->name != 0; syms++) {
524 		if (number == syms->number) {
525 			if (success)
526 				*success = 1;
527 			return (syms->name);
528 		}
529 	}
530 
531 	sprintf(unname, "%d", number);		/* XXX nonreentrant */
532 	if (success)
533 		*success = 0;
534 	return (unname);
535 }
libresolv_hidden_def(sym_ntos)536 libresolv_hidden_def (sym_ntos)
537 
538 const char *
539 sym_ntop(const struct res_sym *syms, int number, int *success) {
540 	static char unname[20];
541 
542 	for ((void)NULL; syms->name != 0; syms++) {
543 		if (number == syms->number) {
544 			if (success)
545 				*success = 1;
546 			return (syms->humanname);
547 		}
548 	}
549 	sprintf(unname, "%d", number);		/* XXX nonreentrant */
550 	if (success)
551 		*success = 0;
552 	return (unname);
553 }
554 
555 /*
556  * Return a string for the type.
557  */
558 const char *
p_type(int type)559 p_type(int type) {
560 	return (sym_ntos(__p_type_syms, type, (int *)0));
561 }
libresolv_hidden_def(p_type)562 libresolv_hidden_def (p_type)
563 
564 /*
565  * Return a string for the type.
566  */
567 static const char *
568 p_section(int section, int opcode) {
569 	const struct res_sym *symbols;
570 
571 	switch (opcode) {
572 	case ns_o_update:
573 		symbols = __p_update_section_syms;
574 		break;
575 	default:
576 		symbols = __p_default_section_syms;
577 		break;
578 	}
579 	return (sym_ntos(symbols, section, (int *)0));
580 }
581 
582 /*
583  * Return a mnemonic for class.
584  */
585 const char *
p_class(int class)586 p_class(int class) {
587 	return (sym_ntos(__p_class_syms, class, (int *)0));
588 }
libresolv_hidden_def(p_class)589 libresolv_hidden_def (p_class)
590 
591 /*
592  * Return a mnemonic for an option
593  */
594 const char *
595 p_option(u_long option) {
596 	static char nbuf[40];
597 
598 	switch (option) {
599 	case RES_INIT:		return "init";
600 	case RES_DEBUG:		return "debug";
601 	case RES_USEVC:		return "use-vc";
602 	case RES_IGNTC:		return "igntc";
603 	case RES_RECURSE:	return "recurs";
604 	case RES_DEFNAMES:	return "defnam";
605 	case RES_STAYOPEN:	return "styopn";
606 	case RES_DNSRCH:	return "dnsrch";
607 	case RES_NOALIASES:	return "noaliases";
608 	case RES_ROTATE:	return "rotate";
609 	case RES_USE_EDNS0:	return "edns0";
610 	case RES_SNGLKUP:	return "single-request";
611 	case RES_SNGLKUPREOP:	return "single-request-reopen";
612 	case RES_USE_DNSSEC:	return "dnssec";
613 	case RES_NOTLDQUERY:	return "no-tld-query";
614 	case RES_NORELOAD:	return "no-reload";
615 	case RES_TRUSTAD:	return "trust-ad";
616 	case RES_NOAAAA:	return "no-aaaa";
617 				/* XXX nonreentrant */
618 	default:		sprintf(nbuf, "?0x%lx?", (u_long)option);
619 				return (nbuf);
620 	}
621 }
libresolv_hidden_def(p_option)622 libresolv_hidden_def (p_option)
623 
624 /*
625  * Return a mnemonic for a time to live.
626  */
627 const char *
628 p_time(uint32_t value) {
629 	static char nbuf[40];		/* XXX nonreentrant */
630 
631 	if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0)
632 		sprintf(nbuf, "%u", value);
633 	return (nbuf);
634 }
635 
636 /*
637  * Return a string for the rcode.
638  */
639 const char *
p_rcode(int rcode)640 p_rcode(int rcode) {
641 	return (sym_ntos(__p_rcode_syms, rcode, (int *)0));
642 }
643 libresolv_hidden_def (p_rcode)
644 
645 /*
646  * routines to convert between on-the-wire RR format and zone file format.
647  * Does not contain conversion to/from decimal degrees; divide or multiply
648  * by 60*60*1000 for that.
649  */
650 
651 static const unsigned int poweroften[10]=
652   { 1, 10, 100, 1000, 10000, 100000,
653     1000000,10000000,100000000,1000000000};
654 
655 /* takes an XeY precision/size value, returns a string representation. */
656 static const char *
precsize_ntoa(uint8_t prec)657 precsize_ntoa (uint8_t prec)
658 {
659 	static char retbuf[sizeof "90000000.00"];	/* XXX nonreentrant */
660 	unsigned long val;
661 	int mantissa, exponent;
662 
663 	mantissa = (int)((prec >> 4) & 0x0f) % 10;
664 	exponent = (int)((prec >> 0) & 0x0f) % 10;
665 
666 	val = mantissa * poweroften[exponent];
667 
668 	(void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100);
669 	return (retbuf);
670 }
671 
672 /* converts ascii size/precision X * 10**Y(cm) to 0xXY.  moves pointer. */
673 static uint8_t
precsize_aton(const char ** strptr)674 precsize_aton (const char **strptr)
675 {
676 	unsigned int mval = 0, cmval = 0;
677 	uint8_t retval = 0;
678 	const char *cp;
679 	int exponent;
680 	int mantissa;
681 
682 	cp = *strptr;
683 
684 	while (isdigit(*cp))
685 		mval = mval * 10 + (*cp++ - '0');
686 
687 	if (*cp == '.') {		/* centimeters */
688 		cp++;
689 		if (isdigit(*cp)) {
690 			cmval = (*cp++ - '0') * 10;
691 			if (isdigit(*cp)) {
692 				cmval += (*cp++ - '0');
693 			}
694 		}
695 	}
696 	cmval = (mval * 100) + cmval;
697 
698 	for (exponent = 0; exponent < 9; exponent++)
699 		if (cmval < poweroften[exponent+1])
700 			break;
701 
702 	mantissa = cmval / poweroften[exponent];
703 	if (mantissa > 9)
704 		mantissa = 9;
705 
706 	retval = (mantissa << 4) | exponent;
707 
708 	*strptr = cp;
709 
710 	return (retval);
711 }
712 
713 /* converts ascii lat/lon to unsigned encoded 32-bit number.  moves pointer. */
714 static uint32_t
latlon2ul(const char ** latlonstrptr,int * which)715 latlon2ul (const char **latlonstrptr, int *which)
716 {
717 	const char *cp;
718 	uint32_t retval;
719 	int deg = 0, min = 0, secs = 0, secsfrac = 0;
720 
721 	cp = *latlonstrptr;
722 
723 	while (isdigit(*cp))
724 		deg = deg * 10 + (*cp++ - '0');
725 
726 	while (isspace(*cp))
727 		cp++;
728 
729 	if (!(isdigit(*cp)))
730 		goto fndhemi;
731 
732 	while (isdigit(*cp))
733 		min = min * 10 + (*cp++ - '0');
734 
735 	while (isspace(*cp))
736 		cp++;
737 
738 	if (!(isdigit(*cp)))
739 		goto fndhemi;
740 
741 	while (isdigit(*cp))
742 		secs = secs * 10 + (*cp++ - '0');
743 
744 	if (*cp == '.') {		/* decimal seconds */
745 		cp++;
746 		if (isdigit(*cp)) {
747 			secsfrac = (*cp++ - '0') * 100;
748 			if (isdigit(*cp)) {
749 				secsfrac += (*cp++ - '0') * 10;
750 				if (isdigit(*cp)) {
751 					secsfrac += (*cp++ - '0');
752 				}
753 			}
754 		}
755 	}
756 
757 	while (!isspace(*cp))	/* if any trailing garbage */
758 		cp++;
759 
760 	while (isspace(*cp))
761 		cp++;
762 
763  fndhemi:
764 	switch (*cp) {
765 	case 'N': case 'n':
766 	case 'E': case 'e':
767 		retval = ((unsigned)1<<31)
768 			+ (((((deg * 60) + min) * 60) + secs) * 1000)
769 			+ secsfrac;
770 		break;
771 	case 'S': case 's':
772 	case 'W': case 'w':
773 		retval = ((unsigned)1<<31)
774 			- (((((deg * 60) + min) * 60) + secs) * 1000)
775 			- secsfrac;
776 		break;
777 	default:
778 		retval = 0;	/* invalid value -- indicates error */
779 		break;
780 	}
781 
782 	switch (*cp) {
783 	case 'N': case 'n':
784 	case 'S': case 's':
785 		*which = 1;	/* latitude */
786 		break;
787 	case 'E': case 'e':
788 	case 'W': case 'w':
789 		*which = 2;	/* longitude */
790 		break;
791 	default:
792 		*which = 0;	/* error */
793 		break;
794 	}
795 
796 	cp++;			/* skip the hemisphere */
797 
798 	while (!isspace(*cp))	/* if any trailing garbage */
799 		cp++;
800 
801 	while (isspace(*cp))	/* move to next field */
802 		cp++;
803 
804 	*latlonstrptr = cp;
805 
806 	return (retval);
807 }
808 
809 /* converts a zone file representation in a string to an RDATA on-the-wire
810  * representation. */
811 int
loc_aton(const char * ascii,u_char * binary)812 loc_aton (const char *ascii, u_char *binary)
813 {
814 	const char *cp, *maxcp;
815 	u_char *bcp;
816 
817 	uint32_t latit = 0, longit = 0, alt = 0;
818 	uint32_t lltemp1 = 0, lltemp2 = 0;
819 	int altmeters = 0, altfrac = 0, altsign = 1;
820 	uint8_t hp = 0x16;	/* default = 1e6 cm = 10000.00m = 10km */
821 	uint8_t vp = 0x13;	/* default = 1e3 cm = 10.00m */
822 	uint8_t siz = 0x12;	/* default = 1e2 cm = 1.00m */
823 	int which1 = 0, which2 = 0;
824 
825 	cp = ascii;
826 	maxcp = cp + strlen(ascii);
827 
828 	lltemp1 = latlon2ul(&cp, &which1);
829 
830 	lltemp2 = latlon2ul(&cp, &which2);
831 
832 	switch (which1 + which2) {
833 	case 3:			/* 1 + 2, the only valid combination */
834 		if ((which1 == 1) && (which2 == 2)) { /* normal case */
835 			latit = lltemp1;
836 			longit = lltemp2;
837 		} else if ((which1 == 2) && (which2 == 1)) { /* reversed */
838 			longit = lltemp1;
839 			latit = lltemp2;
840 		} else {	/* some kind of brokenness */
841 			return (0);
842 		}
843 		break;
844 	default:		/* we didn't get one of each */
845 		return (0);
846 	}
847 
848 	/* altitude */
849 	if (*cp == '-') {
850 		altsign = -1;
851 		cp++;
852 	}
853 
854 	if (*cp == '+')
855 		cp++;
856 
857 	while (isdigit(*cp))
858 		altmeters = altmeters * 10 + (*cp++ - '0');
859 
860 	if (*cp == '.') {		/* decimal meters */
861 		cp++;
862 		if (isdigit(*cp)) {
863 			altfrac = (*cp++ - '0') * 10;
864 			if (isdigit(*cp)) {
865 				altfrac += (*cp++ - '0');
866 			}
867 		}
868 	}
869 
870 	alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
871 
872 	while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
873 		cp++;
874 
875 	while (isspace(*cp) && (cp < maxcp))
876 		cp++;
877 
878 	if (cp >= maxcp)
879 		goto defaults;
880 
881 	siz = precsize_aton(&cp);
882 
883 	while (!isspace(*cp) && (cp < maxcp))	/* if trailing garbage or m */
884 		cp++;
885 
886 	while (isspace(*cp) && (cp < maxcp))
887 		cp++;
888 
889 	if (cp >= maxcp)
890 		goto defaults;
891 
892 	hp = precsize_aton(&cp);
893 
894 	while (!isspace(*cp) && (cp < maxcp))	/* if trailing garbage or m */
895 		cp++;
896 
897 	while (isspace(*cp) && (cp < maxcp))
898 		cp++;
899 
900 	if (cp >= maxcp)
901 		goto defaults;
902 
903 	vp = precsize_aton(&cp);
904 
905  defaults:
906 
907 	bcp = binary;
908 	*bcp++ = (uint8_t) 0;	/* version byte */
909 	*bcp++ = siz;
910 	*bcp++ = hp;
911 	*bcp++ = vp;
912 	PUTLONG(latit,bcp);
913 	PUTLONG(longit,bcp);
914 	PUTLONG(alt,bcp);
915 
916 	return (16);		/* size of RR in octets */
917 }
918 
919 /* takes an on-the-wire LOC RR and formats it in a human readable format. */
920 const char *
loc_ntoa(const u_char * binary,char * ascii)921 loc_ntoa (const u_char *binary, char *ascii)
922 {
923 	static const char error[] = "?";
924 	static char tmpbuf[sizeof
925 "1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
926 	const u_char *cp = binary;
927 
928 	int latdeg, latmin, latsec, latsecfrac;
929 	int longdeg, longmin, longsec, longsecfrac;
930 	char northsouth, eastwest;
931 	int altmeters, altfrac, altsign;
932 
933 	const uint32_t referencealt = 100000 * 100;
934 
935 	int32_t latval, longval, altval;
936 	uint32_t templ;
937 	uint8_t sizeval, hpval, vpval, versionval;
938 
939 	char *sizestr, *hpstr, *vpstr;
940 
941 	versionval = *cp++;
942 
943 	if (ascii == NULL)
944 		ascii = tmpbuf;
945 
946 	if (versionval) {
947 		(void) sprintf(ascii, "; error: unknown LOC RR version");
948 		return (ascii);
949 	}
950 
951 	sizeval = *cp++;
952 
953 	hpval = *cp++;
954 	vpval = *cp++;
955 
956 	GETLONG(templ, cp);
957 	latval = (templ - ((unsigned)1<<31));
958 
959 	GETLONG(templ, cp);
960 	longval = (templ - ((unsigned)1<<31));
961 
962 	GETLONG(templ, cp);
963 	if (templ < referencealt) { /* below WGS 84 spheroid */
964 		altval = referencealt - templ;
965 		altsign = -1;
966 	} else {
967 		altval = templ - referencealt;
968 		altsign = 1;
969 	}
970 
971 	if (latval < 0) {
972 		northsouth = 'S';
973 		latval = -latval;
974 	} else
975 		northsouth = 'N';
976 
977 	latsecfrac = latval % 1000;
978 	latval = latval / 1000;
979 	latsec = latval % 60;
980 	latval = latval / 60;
981 	latmin = latval % 60;
982 	latval = latval / 60;
983 	latdeg = latval;
984 
985 	if (longval < 0) {
986 		eastwest = 'W';
987 		longval = -longval;
988 	} else
989 		eastwest = 'E';
990 
991 	longsecfrac = longval % 1000;
992 	longval = longval / 1000;
993 	longsec = longval % 60;
994 	longval = longval / 60;
995 	longmin = longval % 60;
996 	longval = longval / 60;
997 	longdeg = longval;
998 
999 	altfrac = altval % 100;
1000 	altmeters = (altval / 100) * altsign;
1001 
1002 	if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1003 		sizestr = (char *) error;
1004 	if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1005 		hpstr = (char *) error;
1006 	if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1007 		vpstr = (char *) error;
1008 
1009 	sprintf(ascii,
1010 	      "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1011 		latdeg, latmin, latsec, latsecfrac, northsouth,
1012 		longdeg, longmin, longsec, longsecfrac, eastwest,
1013 		altmeters, altfrac, sizestr, hpstr, vpstr);
1014 
1015 	if (sizestr != (char *) error)
1016 		free(sizestr);
1017 	if (hpstr != (char *) error)
1018 		free(hpstr);
1019 	if (vpstr != (char *) error)
1020 		free(vpstr);
1021 
1022 	return (ascii);
1023 }
libresolv_hidden_def(loc_ntoa)1024 libresolv_hidden_def (loc_ntoa)
1025 
1026 
1027 /* Return the number of DNS hierarchy levels in the name. */
1028 int
1029 dn_count_labels(const char *name) {
1030 	int i, len, count;
1031 
1032 	len = strlen(name);
1033 	for (i = 0, count = 0; i < len; i++) {
1034 		/* XXX need to check for \. or use named's nlabels(). */
1035 		if (name[i] == '.')
1036 			count++;
1037 	}
1038 
1039 	/* don't count initial wildcard */
1040 	if (name[0] == '*')
1041 		if (count)
1042 			count--;
1043 
1044 	/* don't count the null label for root. */
1045 	/* if terminating '.' not found, must adjust */
1046 	/* count to include last label */
1047 	if (len > 0 && name[len-1] != '.')
1048 		count++;
1049 	return (count);
1050 }
libresolv_hidden_def(__dn_count_labels)1051 libresolv_hidden_def (__dn_count_labels)
1052 
1053 
1054 #if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_27)
1055 /*
1056  * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
1057  * SIG records are required to be printed like this, by the Secure DNS RFC.
1058  * This is an obsolescent function and does not handle dates outside the
1059  * signed 32-bit range.
1060  */
1061 char *
1062 __p_secstodate (u_long secs) {
1063 	/* XXX nonreentrant */
1064 	static char output[15];		/* YYYYMMDDHHMMSS and null */
1065 	time_t clock = secs;
1066 	struct tm *time;
1067 
1068 	struct tm timebuf;
1069 	/* The call to __gmtime_r can never produce a year overflowing
1070 	   the range of int, given the check on SECS, but check for a
1071 	   NULL return anyway to avoid a null pointer dereference in
1072 	   case there are any other unspecified errors.  */
1073 	if (secs > 0x7fffffff
1074 	    || (time = __gmtime_r (&clock, &timebuf)) == NULL) {
1075 		strcpy (output, "<overflow>");
1076 		__set_errno (EOVERFLOW);
1077 		return output;
1078 	}
1079 	time->tm_year += 1900;
1080 	time->tm_mon += 1;
1081 	/* The struct tm fields, given the above range check,
1082 	   must have values that mean this sprintf exactly fills the
1083 	   buffer.  But as of GCC 8 of 2017-11-21, GCC cannot tell
1084 	   that, even given range checks on all fields with
1085 	   __builtin_unreachable called for out-of-range values.  */
1086 	DIAG_PUSH_NEEDS_COMMENT;
1087 # if __GNUC_PREREQ (7, 0)
1088 	DIAG_IGNORE_NEEDS_COMMENT (8, "-Wformat-overflow=");
1089 # endif
1090 	sprintf(output, "%04d%02d%02d%02d%02d%02d",
1091 		time->tm_year, time->tm_mon, time->tm_mday,
1092 		time->tm_hour, time->tm_min, time->tm_sec);
1093 	DIAG_POP_NEEDS_COMMENT;
1094 	return (output);
1095 }
1096 compat_symbol (libresolv, __p_secstodate, __p_secstodate, GLIBC_2_0);
1097 #endif
1098