(root)/
glibc-2.38/
resolv/
res_debug.c
       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
     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
     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
     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  }
     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  }
     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 *
     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  }
     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 *
     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  }
     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
     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 *
     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  }
     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 *
     559  p_type(int type) {
     560  	return (sym_ntos(__p_type_syms, type, (int *)0));
     561  }
     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 *
     586  p_class(int class) {
     587  	return (sym_ntos(__p_class_syms, class, (int *)0));
     588  }
     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  }
     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 *
     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 *
     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
     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
     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
     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 *
     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  }
    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  }
    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