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 				/* XXX nonreentrant */
617 	default:		sprintf(nbuf, "?0x%lx?", (u_long)option);
618 				return (nbuf);
619 	}
620 }
libresolv_hidden_def(p_option)621 libresolv_hidden_def (p_option)
622 
623 /*
624  * Return a mnemonic for a time to live.
625  */
626 const char *
627 p_time(uint32_t value) {
628 	static char nbuf[40];		/* XXX nonreentrant */
629 
630 	if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0)
631 		sprintf(nbuf, "%u", value);
632 	return (nbuf);
633 }
634 
635 /*
636  * Return a string for the rcode.
637  */
638 const char *
p_rcode(int rcode)639 p_rcode(int rcode) {
640 	return (sym_ntos(__p_rcode_syms, rcode, (int *)0));
641 }
642 libresolv_hidden_def (p_rcode)
643 
644 /*
645  * routines to convert between on-the-wire RR format and zone file format.
646  * Does not contain conversion to/from decimal degrees; divide or multiply
647  * by 60*60*1000 for that.
648  */
649 
650 static const unsigned int poweroften[10]=
651   { 1, 10, 100, 1000, 10000, 100000,
652     1000000,10000000,100000000,1000000000};
653 
654 /* takes an XeY precision/size value, returns a string representation. */
655 static const char *
precsize_ntoa(uint8_t prec)656 precsize_ntoa (uint8_t prec)
657 {
658 	static char retbuf[sizeof "90000000.00"];	/* XXX nonreentrant */
659 	unsigned long val;
660 	int mantissa, exponent;
661 
662 	mantissa = (int)((prec >> 4) & 0x0f) % 10;
663 	exponent = (int)((prec >> 0) & 0x0f) % 10;
664 
665 	val = mantissa * poweroften[exponent];
666 
667 	(void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100);
668 	return (retbuf);
669 }
670 
671 /* converts ascii size/precision X * 10**Y(cm) to 0xXY.  moves pointer. */
672 static uint8_t
precsize_aton(const char ** strptr)673 precsize_aton (const char **strptr)
674 {
675 	unsigned int mval = 0, cmval = 0;
676 	uint8_t retval = 0;
677 	const char *cp;
678 	int exponent;
679 	int mantissa;
680 
681 	cp = *strptr;
682 
683 	while (isdigit(*cp))
684 		mval = mval * 10 + (*cp++ - '0');
685 
686 	if (*cp == '.') {		/* centimeters */
687 		cp++;
688 		if (isdigit(*cp)) {
689 			cmval = (*cp++ - '0') * 10;
690 			if (isdigit(*cp)) {
691 				cmval += (*cp++ - '0');
692 			}
693 		}
694 	}
695 	cmval = (mval * 100) + cmval;
696 
697 	for (exponent = 0; exponent < 9; exponent++)
698 		if (cmval < poweroften[exponent+1])
699 			break;
700 
701 	mantissa = cmval / poweroften[exponent];
702 	if (mantissa > 9)
703 		mantissa = 9;
704 
705 	retval = (mantissa << 4) | exponent;
706 
707 	*strptr = cp;
708 
709 	return (retval);
710 }
711 
712 /* converts ascii lat/lon to unsigned encoded 32-bit number.  moves pointer. */
713 static uint32_t
latlon2ul(const char ** latlonstrptr,int * which)714 latlon2ul (const char **latlonstrptr, int *which)
715 {
716 	const char *cp;
717 	uint32_t retval;
718 	int deg = 0, min = 0, secs = 0, secsfrac = 0;
719 
720 	cp = *latlonstrptr;
721 
722 	while (isdigit(*cp))
723 		deg = deg * 10 + (*cp++ - '0');
724 
725 	while (isspace(*cp))
726 		cp++;
727 
728 	if (!(isdigit(*cp)))
729 		goto fndhemi;
730 
731 	while (isdigit(*cp))
732 		min = min * 10 + (*cp++ - '0');
733 
734 	while (isspace(*cp))
735 		cp++;
736 
737 	if (!(isdigit(*cp)))
738 		goto fndhemi;
739 
740 	while (isdigit(*cp))
741 		secs = secs * 10 + (*cp++ - '0');
742 
743 	if (*cp == '.') {		/* decimal seconds */
744 		cp++;
745 		if (isdigit(*cp)) {
746 			secsfrac = (*cp++ - '0') * 100;
747 			if (isdigit(*cp)) {
748 				secsfrac += (*cp++ - '0') * 10;
749 				if (isdigit(*cp)) {
750 					secsfrac += (*cp++ - '0');
751 				}
752 			}
753 		}
754 	}
755 
756 	while (!isspace(*cp))	/* if any trailing garbage */
757 		cp++;
758 
759 	while (isspace(*cp))
760 		cp++;
761 
762  fndhemi:
763 	switch (*cp) {
764 	case 'N': case 'n':
765 	case 'E': case 'e':
766 		retval = ((unsigned)1<<31)
767 			+ (((((deg * 60) + min) * 60) + secs) * 1000)
768 			+ secsfrac;
769 		break;
770 	case 'S': case 's':
771 	case 'W': case 'w':
772 		retval = ((unsigned)1<<31)
773 			- (((((deg * 60) + min) * 60) + secs) * 1000)
774 			- secsfrac;
775 		break;
776 	default:
777 		retval = 0;	/* invalid value -- indicates error */
778 		break;
779 	}
780 
781 	switch (*cp) {
782 	case 'N': case 'n':
783 	case 'S': case 's':
784 		*which = 1;	/* latitude */
785 		break;
786 	case 'E': case 'e':
787 	case 'W': case 'w':
788 		*which = 2;	/* longitude */
789 		break;
790 	default:
791 		*which = 0;	/* error */
792 		break;
793 	}
794 
795 	cp++;			/* skip the hemisphere */
796 
797 	while (!isspace(*cp))	/* if any trailing garbage */
798 		cp++;
799 
800 	while (isspace(*cp))	/* move to next field */
801 		cp++;
802 
803 	*latlonstrptr = cp;
804 
805 	return (retval);
806 }
807 
808 /* converts a zone file representation in a string to an RDATA on-the-wire
809  * representation. */
810 int
loc_aton(const char * ascii,u_char * binary)811 loc_aton (const char *ascii, u_char *binary)
812 {
813 	const char *cp, *maxcp;
814 	u_char *bcp;
815 
816 	uint32_t latit = 0, longit = 0, alt = 0;
817 	uint32_t lltemp1 = 0, lltemp2 = 0;
818 	int altmeters = 0, altfrac = 0, altsign = 1;
819 	uint8_t hp = 0x16;	/* default = 1e6 cm = 10000.00m = 10km */
820 	uint8_t vp = 0x13;	/* default = 1e3 cm = 10.00m */
821 	uint8_t siz = 0x12;	/* default = 1e2 cm = 1.00m */
822 	int which1 = 0, which2 = 0;
823 
824 	cp = ascii;
825 	maxcp = cp + strlen(ascii);
826 
827 	lltemp1 = latlon2ul(&cp, &which1);
828 
829 	lltemp2 = latlon2ul(&cp, &which2);
830 
831 	switch (which1 + which2) {
832 	case 3:			/* 1 + 2, the only valid combination */
833 		if ((which1 == 1) && (which2 == 2)) { /* normal case */
834 			latit = lltemp1;
835 			longit = lltemp2;
836 		} else if ((which1 == 2) && (which2 == 1)) { /* reversed */
837 			longit = lltemp1;
838 			latit = lltemp2;
839 		} else {	/* some kind of brokenness */
840 			return (0);
841 		}
842 		break;
843 	default:		/* we didn't get one of each */
844 		return (0);
845 	}
846 
847 	/* altitude */
848 	if (*cp == '-') {
849 		altsign = -1;
850 		cp++;
851 	}
852 
853 	if (*cp == '+')
854 		cp++;
855 
856 	while (isdigit(*cp))
857 		altmeters = altmeters * 10 + (*cp++ - '0');
858 
859 	if (*cp == '.') {		/* decimal meters */
860 		cp++;
861 		if (isdigit(*cp)) {
862 			altfrac = (*cp++ - '0') * 10;
863 			if (isdigit(*cp)) {
864 				altfrac += (*cp++ - '0');
865 			}
866 		}
867 	}
868 
869 	alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
870 
871 	while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
872 		cp++;
873 
874 	while (isspace(*cp) && (cp < maxcp))
875 		cp++;
876 
877 	if (cp >= maxcp)
878 		goto defaults;
879 
880 	siz = precsize_aton(&cp);
881 
882 	while (!isspace(*cp) && (cp < maxcp))	/* if trailing garbage or m */
883 		cp++;
884 
885 	while (isspace(*cp) && (cp < maxcp))
886 		cp++;
887 
888 	if (cp >= maxcp)
889 		goto defaults;
890 
891 	hp = precsize_aton(&cp);
892 
893 	while (!isspace(*cp) && (cp < maxcp))	/* if trailing garbage or m */
894 		cp++;
895 
896 	while (isspace(*cp) && (cp < maxcp))
897 		cp++;
898 
899 	if (cp >= maxcp)
900 		goto defaults;
901 
902 	vp = precsize_aton(&cp);
903 
904  defaults:
905 
906 	bcp = binary;
907 	*bcp++ = (uint8_t) 0;	/* version byte */
908 	*bcp++ = siz;
909 	*bcp++ = hp;
910 	*bcp++ = vp;
911 	PUTLONG(latit,bcp);
912 	PUTLONG(longit,bcp);
913 	PUTLONG(alt,bcp);
914 
915 	return (16);		/* size of RR in octets */
916 }
917 
918 /* takes an on-the-wire LOC RR and formats it in a human readable format. */
919 const char *
loc_ntoa(const u_char * binary,char * ascii)920 loc_ntoa (const u_char *binary, char *ascii)
921 {
922 	static const char error[] = "?";
923 	static char tmpbuf[sizeof
924 "1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
925 	const u_char *cp = binary;
926 
927 	int latdeg, latmin, latsec, latsecfrac;
928 	int longdeg, longmin, longsec, longsecfrac;
929 	char northsouth, eastwest;
930 	int altmeters, altfrac, altsign;
931 
932 	const uint32_t referencealt = 100000 * 100;
933 
934 	int32_t latval, longval, altval;
935 	uint32_t templ;
936 	uint8_t sizeval, hpval, vpval, versionval;
937 
938 	char *sizestr, *hpstr, *vpstr;
939 
940 	versionval = *cp++;
941 
942 	if (ascii == NULL)
943 		ascii = tmpbuf;
944 
945 	if (versionval) {
946 		(void) sprintf(ascii, "; error: unknown LOC RR version");
947 		return (ascii);
948 	}
949 
950 	sizeval = *cp++;
951 
952 	hpval = *cp++;
953 	vpval = *cp++;
954 
955 	GETLONG(templ, cp);
956 	latval = (templ - ((unsigned)1<<31));
957 
958 	GETLONG(templ, cp);
959 	longval = (templ - ((unsigned)1<<31));
960 
961 	GETLONG(templ, cp);
962 	if (templ < referencealt) { /* below WGS 84 spheroid */
963 		altval = referencealt - templ;
964 		altsign = -1;
965 	} else {
966 		altval = templ - referencealt;
967 		altsign = 1;
968 	}
969 
970 	if (latval < 0) {
971 		northsouth = 'S';
972 		latval = -latval;
973 	} else
974 		northsouth = 'N';
975 
976 	latsecfrac = latval % 1000;
977 	latval = latval / 1000;
978 	latsec = latval % 60;
979 	latval = latval / 60;
980 	latmin = latval % 60;
981 	latval = latval / 60;
982 	latdeg = latval;
983 
984 	if (longval < 0) {
985 		eastwest = 'W';
986 		longval = -longval;
987 	} else
988 		eastwest = 'E';
989 
990 	longsecfrac = longval % 1000;
991 	longval = longval / 1000;
992 	longsec = longval % 60;
993 	longval = longval / 60;
994 	longmin = longval % 60;
995 	longval = longval / 60;
996 	longdeg = longval;
997 
998 	altfrac = altval % 100;
999 	altmeters = (altval / 100) * altsign;
1000 
1001 	if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1002 		sizestr = (char *) error;
1003 	if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1004 		hpstr = (char *) error;
1005 	if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1006 		vpstr = (char *) error;
1007 
1008 	sprintf(ascii,
1009 	      "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1010 		latdeg, latmin, latsec, latsecfrac, northsouth,
1011 		longdeg, longmin, longsec, longsecfrac, eastwest,
1012 		altmeters, altfrac, sizestr, hpstr, vpstr);
1013 
1014 	if (sizestr != (char *) error)
1015 		free(sizestr);
1016 	if (hpstr != (char *) error)
1017 		free(hpstr);
1018 	if (vpstr != (char *) error)
1019 		free(vpstr);
1020 
1021 	return (ascii);
1022 }
libresolv_hidden_def(loc_ntoa)1023 libresolv_hidden_def (loc_ntoa)
1024 
1025 
1026 /* Return the number of DNS hierarchy levels in the name. */
1027 int
1028 dn_count_labels(const char *name) {
1029 	int i, len, count;
1030 
1031 	len = strlen(name);
1032 	for (i = 0, count = 0; i < len; i++) {
1033 		/* XXX need to check for \. or use named's nlabels(). */
1034 		if (name[i] == '.')
1035 			count++;
1036 	}
1037 
1038 	/* don't count initial wildcard */
1039 	if (name[0] == '*')
1040 		if (count)
1041 			count--;
1042 
1043 	/* don't count the null label for root. */
1044 	/* if terminating '.' not found, must adjust */
1045 	/* count to include last label */
1046 	if (len > 0 && name[len-1] != '.')
1047 		count++;
1048 	return (count);
1049 }
libresolv_hidden_def(__dn_count_labels)1050 libresolv_hidden_def (__dn_count_labels)
1051 
1052 
1053 #if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_27)
1054 /*
1055  * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
1056  * SIG records are required to be printed like this, by the Secure DNS RFC.
1057  * This is an obsolescent function and does not handle dates outside the
1058  * signed 32-bit range.
1059  */
1060 char *
1061 __p_secstodate (u_long secs) {
1062 	/* XXX nonreentrant */
1063 	static char output[15];		/* YYYYMMDDHHMMSS and null */
1064 	time_t clock = secs;
1065 	struct tm *time;
1066 
1067 	struct tm timebuf;
1068 	/* The call to __gmtime_r can never produce a year overflowing
1069 	   the range of int, given the check on SECS, but check for a
1070 	   NULL return anyway to avoid a null pointer dereference in
1071 	   case there are any other unspecified errors.  */
1072 	if (secs > 0x7fffffff
1073 	    || (time = __gmtime_r (&clock, &timebuf)) == NULL) {
1074 		strcpy (output, "<overflow>");
1075 		__set_errno (EOVERFLOW);
1076 		return output;
1077 	}
1078 	time->tm_year += 1900;
1079 	time->tm_mon += 1;
1080 	/* The struct tm fields, given the above range check,
1081 	   must have values that mean this sprintf exactly fills the
1082 	   buffer.  But as of GCC 8 of 2017-11-21, GCC cannot tell
1083 	   that, even given range checks on all fields with
1084 	   __builtin_unreachable called for out-of-range values.  */
1085 	DIAG_PUSH_NEEDS_COMMENT;
1086 # if __GNUC_PREREQ (7, 0)
1087 	DIAG_IGNORE_NEEDS_COMMENT (8, "-Wformat-overflow=");
1088 # endif
1089 	sprintf(output, "%04d%02d%02d%02d%02d%02d",
1090 		time->tm_year, time->tm_mon, time->tm_mday,
1091 		time->tm_hour, time->tm_min, time->tm_sec);
1092 	DIAG_POP_NEEDS_COMMENT;
1093 	return (output);
1094 }
1095 compat_symbol (libresolv, __p_secstodate, __p_secstodate, GLIBC_2_0);
1096 #endif
1097