hjl / source-git / glibc

Forked from source-git/glibc 3 years ago
Clone

Blame resolv/res_debug.c

Packit 6c4009
/*
Packit 6c4009
 * Copyright (c) 1985
Packit 6c4009
 *    The Regents of the University of California.  All rights reserved.
Packit 6c4009
 *
Packit 6c4009
 * Redistribution and use in source and binary forms, with or without
Packit 6c4009
 * modification, are permitted provided that the following conditions
Packit 6c4009
 * are met:
Packit 6c4009
 * 1. Redistributions of source code must retain the above copyright
Packit 6c4009
 *    notice, this list of conditions and the following disclaimer.
Packit 6c4009
 * 2. Redistributions in binary form must reproduce the above copyright
Packit 6c4009
 *    notice, this list of conditions and the following disclaimer in the
Packit 6c4009
 *    documentation and/or other materials provided with the distribution.
Packit 6c4009
 * 4. Neither the name of the University nor the names of its contributors
Packit 6c4009
 *    may be used to endorse or promote products derived from this software
Packit 6c4009
 *    without specific prior written permission.
Packit 6c4009
 *
Packit 6c4009
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
Packit 6c4009
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit 6c4009
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 6c4009
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
Packit 6c4009
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit 6c4009
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Packit 6c4009
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit 6c4009
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit 6c4009
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Packit 6c4009
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Packit 6c4009
 * SUCH DAMAGE.
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
Packit 6c4009
 *
Packit 6c4009
 * Permission to use, copy, modify, and distribute this software for any
Packit 6c4009
 * purpose with or without fee is hereby granted, provided that the above
Packit 6c4009
 * copyright notice and this permission notice appear in all copies, and that
Packit 6c4009
 * the name of Digital Equipment Corporation not be used in advertising or
Packit 6c4009
 * publicity pertaining to distribution of the document or software without
Packit 6c4009
 * specific, written prior permission.
Packit 6c4009
 *
Packit 6c4009
 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
Packit 6c4009
 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
Packit 6c4009
 * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
Packit 6c4009
 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
Packit 6c4009
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
Packit 6c4009
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
Packit 6c4009
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
Packit 6c4009
 * SOFTWARE.
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Portions Copyright (c) 1995 by International Business Machines, Inc.
Packit 6c4009
 *
Packit 6c4009
 * International Business Machines, Inc. (hereinafter called IBM) grants
Packit 6c4009
 * permission under its copyrights to use, copy, modify, and distribute this
Packit 6c4009
 * Software with or without fee, provided that the above copyright notice and
Packit 6c4009
 * all paragraphs of this notice appear in all copies, and that the name of IBM
Packit 6c4009
 * not be used in connection with the marketing of any product incorporating
Packit 6c4009
 * the Software or modifications thereof, without specific, written prior
Packit 6c4009
 * permission.
Packit 6c4009
 *
Packit 6c4009
 * To the extent it has a right to do so, IBM grants an immunity from suit
Packit 6c4009
 * under its patents, if any, for the use, sale or manufacture of products to
Packit 6c4009
 * the extent that such products are used for performing Domain Name System
Packit 6c4009
 * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
Packit 6c4009
 * granted for any product per se or for any other function of any product.
Packit 6c4009
 *
Packit 6c4009
 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
Packit 6c4009
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
Packit 6c4009
 * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
Packit 6c4009
 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
Packit 6c4009
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
Packit 6c4009
 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
Packit 6c4009
 *
Packit 6c4009
 * Permission to use, copy, modify, and distribute this software for any
Packit 6c4009
 * purpose with or without fee is hereby granted, provided that the above
Packit 6c4009
 * copyright notice and this permission notice appear in all copies.
Packit 6c4009
 *
Packit 6c4009
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
Packit 6c4009
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
Packit 6c4009
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
Packit 6c4009
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
Packit 6c4009
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
Packit 6c4009
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
Packit 6c4009
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
Packit 6c4009
 * SOFTWARE.
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
#include <sys/types.h>
Packit 6c4009
#include <sys/param.h>
Packit 6c4009
#include <sys/socket.h>
Packit 6c4009
Packit 6c4009
#include <netinet/in.h>
Packit 6c4009
#include <arpa/inet.h>
Packit 6c4009
#include <arpa/nameser.h>
Packit 6c4009
Packit 6c4009
#include <ctype.h>
Packit 6c4009
#include <errno.h>
Packit 6c4009
#include <math.h>
Packit 6c4009
#include <netdb.h>
Packit 6c4009
#include <resolv/resolv-internal.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <time.h>
Packit 6c4009
#include <shlib-compat.h>
Packit 6c4009
#include <libc-diag.h>
Packit 6c4009
Packit 6c4009
#ifdef SPRINTF_CHAR
Packit 6c4009
# define SPRINTF(x) strlen(sprintf/**/x)
Packit 6c4009
#else
Packit 6c4009
# define SPRINTF(x) sprintf x
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
extern const char *_res_sectioncodes[] attribute_hidden;
Packit 6c4009
Packit 6c4009
/* _res_opcodes was exported by accident as a variable.  */
Packit 6c4009
#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_26)
Packit 6c4009
static const char *res_opcodes[] =
Packit 6c4009
#else
Packit 6c4009
static const char res_opcodes[][9] =
Packit 6c4009
#endif
Packit 6c4009
  {
Packit 6c4009
    "QUERY",
Packit 6c4009
    "IQUERY",
Packit 6c4009
    "CQUERYM",
Packit 6c4009
    "CQUERYU",	/* experimental */
Packit 6c4009
    "NOTIFY",	/* experimental */
Packit 6c4009
    "UPDATE",
Packit 6c4009
    "6",
Packit 6c4009
    "7",
Packit 6c4009
    "8",
Packit 6c4009
    "9",
Packit 6c4009
    "10",
Packit 6c4009
    "11",
Packit 6c4009
    "12",
Packit 6c4009
    "13",
Packit 6c4009
    "ZONEINIT",
Packit 6c4009
    "ZONEREF",
Packit 6c4009
  };
Packit 6c4009
#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_26)
Packit 6c4009
strong_alias (res_opcodes, _res_opcodes)
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
static const char *p_section(int section, int opcode);
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Print the current options.
Packit 6c4009
 */
Packit 6c4009
void
Packit 6c4009
fp_resstat(const res_state statp, FILE *file) {
Packit 6c4009
	u_long mask;
Packit 6c4009
Packit 6c4009
	fprintf(file, ";; res options:");
Packit 6c4009
	for (mask = 1;  mask != 0;  mask <<= 1)
Packit 6c4009
		if (statp->options & mask)
Packit 6c4009
			fprintf(file, " %s", p_option(mask));
Packit 6c4009
	putc('\n', file);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
do_section (int pfcode, ns_msg *handle, ns_sect section, int pflag, FILE *file)
Packit 6c4009
{
Packit 6c4009
	int n, sflag, rrnum;
Packit 6c4009
	static int buflen = 2048;
Packit 6c4009
	char *buf;
Packit 6c4009
	ns_opcode opcode;
Packit 6c4009
	ns_rr rr;
Packit 6c4009
Packit 6c4009
	/*
Packit 6c4009
	 * Print answer records.
Packit 6c4009
	 */
Packit 6c4009
	sflag = (pfcode & pflag);
Packit 6c4009
	if (pfcode && !sflag)
Packit 6c4009
		return;
Packit 6c4009
Packit 6c4009
	buf = malloc(buflen);
Packit 6c4009
	if (buf == NULL) {
Packit 6c4009
		fprintf(file, ";; memory allocation failure\n");
Packit 6c4009
		return;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
	opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode);
Packit 6c4009
	rrnum = 0;
Packit 6c4009
	for (;;) {
Packit 6c4009
		if (ns_parserr(handle, section, rrnum, &rr)) {
Packit 6c4009
			if (errno != ENODEV)
Packit 6c4009
				fprintf(file, ";; ns_parserr: %s\n",
Packit 6c4009
					strerror(errno));
Packit 6c4009
			else if (rrnum > 0 && sflag != 0 &&
Packit 6c4009
				 (pfcode & RES_PRF_HEAD1))
Packit 6c4009
				putc('\n', file);
Packit 6c4009
			goto cleanup;
Packit 6c4009
		}
Packit 6c4009
		if (rrnum == 0 && sflag != 0 && (pfcode & RES_PRF_HEAD1))
Packit 6c4009
			fprintf(file, ";; %s SECTION:\n",
Packit 6c4009
				p_section(section, opcode));
Packit 6c4009
		if (section == ns_s_qd)
Packit 6c4009
			fprintf(file, ";;\t%s, type = %s, class = %s\n",
Packit 6c4009
				ns_rr_name(rr),
Packit 6c4009
				p_type(ns_rr_type(rr)),
Packit 6c4009
				p_class(ns_rr_class(rr)));
Packit 6c4009
		else {
Packit 6c4009
			n = ns_sprintrr(handle, &rr, NULL, NULL,
Packit 6c4009
					buf, buflen);
Packit 6c4009
			if (n < 0) {
Packit 6c4009
				if (errno == ENOSPC) {
Packit 6c4009
					free(buf);
Packit 6c4009
					buf = NULL;
Packit 6c4009
					if (buflen < 131072)
Packit 6c4009
						buf = malloc(buflen += 1024);
Packit 6c4009
					if (buf == NULL) {
Packit 6c4009
						fprintf(file,
Packit 6c4009
					      ";; memory allocation failure\n");
Packit 6c4009
					      return;
Packit 6c4009
					}
Packit 6c4009
					continue;
Packit 6c4009
				}
Packit 6c4009
				fprintf(file, ";; ns_sprintrr: %s\n",
Packit 6c4009
					strerror(errno));
Packit 6c4009
				goto cleanup;
Packit 6c4009
			}
Packit 6c4009
			fputs(buf, file);
Packit 6c4009
			fputc('\n', file);
Packit 6c4009
		}
Packit 6c4009
		rrnum++;
Packit 6c4009
	}
Packit 6c4009
 cleanup:
Packit 6c4009
	free(buf);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Print the contents of a query.
Packit 6c4009
 * This is intended to be primarily a debugging routine.
Packit 6c4009
 */
Packit 6c4009
void
Packit 6c4009
fp_nquery (const unsigned char *msg, int len, FILE *file)
Packit 6c4009
{
Packit 6c4009
	ns_msg handle;
Packit 6c4009
	int qdcount, ancount, nscount, arcount;
Packit 6c4009
	u_int opcode, rcode, id;
Packit 6c4009
Packit 6c4009
	/* There is no need to initialize _res: If _res is not yet
Packit 6c4009
	   initialized, _res.pfcode is zero.  But initialization will
Packit 6c4009
	   leave it at zero, too.  _res.pfcode is an unsigned long,
Packit 6c4009
	   but the code here assumes that the flags fit into an int,
Packit 6c4009
	   so use that.  */
Packit 6c4009
	int pfcode = _res.pfcode;
Packit 6c4009
Packit 6c4009
	if (ns_initparse(msg, len, &handle) < 0) {
Packit 6c4009
		fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
Packit 6c4009
		return;
Packit 6c4009
	}
Packit 6c4009
	opcode = ns_msg_getflag(handle, ns_f_opcode);
Packit 6c4009
	rcode = ns_msg_getflag(handle, ns_f_rcode);
Packit 6c4009
	id = ns_msg_id(handle);
Packit 6c4009
	qdcount = ns_msg_count(handle, ns_s_qd);
Packit 6c4009
	ancount = ns_msg_count(handle, ns_s_an);
Packit 6c4009
	nscount = ns_msg_count(handle, ns_s_ns);
Packit 6c4009
	arcount = ns_msg_count(handle, ns_s_ar);
Packit 6c4009
Packit 6c4009
	/*
Packit 6c4009
	 * Print header fields.
Packit 6c4009
	 */
Packit 6c4009
	if ((!pfcode) || (pfcode & RES_PRF_HEADX) || rcode)
Packit 6c4009
		fprintf(file,
Packit 6c4009
			";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
Packit 6c4009
			res_opcodes[opcode], p_rcode(rcode), id);
Packit 6c4009
	if ((!pfcode) || (pfcode & RES_PRF_HEADX))
Packit 6c4009
		putc(';', file);
Packit 6c4009
	if ((!pfcode) || (pfcode & RES_PRF_HEAD2)) {
Packit 6c4009
		fprintf(file, "; flags:");
Packit 6c4009
		if (ns_msg_getflag(handle, ns_f_qr))
Packit 6c4009
			fprintf(file, " qr");
Packit 6c4009
		if (ns_msg_getflag(handle, ns_f_aa))
Packit 6c4009
			fprintf(file, " aa");
Packit 6c4009
		if (ns_msg_getflag(handle, ns_f_tc))
Packit 6c4009
			fprintf(file, " tc");
Packit 6c4009
		if (ns_msg_getflag(handle, ns_f_rd))
Packit 6c4009
			fprintf(file, " rd");
Packit 6c4009
		if (ns_msg_getflag(handle, ns_f_ra))
Packit 6c4009
			fprintf(file, " ra");
Packit 6c4009
		if (ns_msg_getflag(handle, ns_f_z))
Packit 6c4009
			fprintf(file, " ??");
Packit 6c4009
		if (ns_msg_getflag(handle, ns_f_ad))
Packit 6c4009
			fprintf(file, " ad");
Packit 6c4009
		if (ns_msg_getflag(handle, ns_f_cd))
Packit 6c4009
			fprintf(file, " cd");
Packit 6c4009
	}
Packit 6c4009
	if ((!pfcode) || (pfcode & RES_PRF_HEAD1)) {
Packit 6c4009
		fprintf(file, "; %s: %d",
Packit 6c4009
			p_section(ns_s_qd, opcode), qdcount);
Packit 6c4009
		fprintf(file, ", %s: %d",
Packit 6c4009
			p_section(ns_s_an, opcode), ancount);
Packit 6c4009
		fprintf(file, ", %s: %d",
Packit 6c4009
			p_section(ns_s_ns, opcode), nscount);
Packit 6c4009
		fprintf(file, ", %s: %d",
Packit 6c4009
			p_section(ns_s_ar, opcode), arcount);
Packit 6c4009
	}
Packit 6c4009
	if ((!pfcode) || (pfcode &
Packit 6c4009
		(RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
Packit 6c4009
		putc('\n',file);
Packit 6c4009
	}
Packit 6c4009
	/*
Packit 6c4009
	 * Print the various sections.
Packit 6c4009
	 */
Packit 6c4009
	do_section (pfcode, &handle, ns_s_qd, RES_PRF_QUES, file);
Packit 6c4009
	do_section (pfcode, &handle, ns_s_an, RES_PRF_ANS, file);
Packit 6c4009
	do_section (pfcode, &handle, ns_s_ns, RES_PRF_AUTH, file);
Packit 6c4009
	do_section (pfcode, &handle, ns_s_ar, RES_PRF_ADD, file);
Packit 6c4009
	if (qdcount == 0 && ancount == 0 &&
Packit 6c4009
	    nscount == 0 && arcount == 0)
Packit 6c4009
		putc('\n', file);
Packit 6c4009
}
Packit 6c4009
libresolv_hidden_def (fp_nquery)
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
fp_query (const unsigned char *msg, FILE *file)
Packit 6c4009
{
Packit 6c4009
  fp_nquery (msg, PACKETSZ, file);
Packit 6c4009
}
Packit 6c4009
libresolv_hidden_def (fp_query)
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
p_query (const unsigned char *msg)
Packit 6c4009
{
Packit 6c4009
  fp_query (msg, stdout);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
const u_char *
Packit 6c4009
p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
Packit 6c4009
	char name[MAXDNAME];
Packit 6c4009
	int n;
Packit 6c4009
Packit 6c4009
	if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
Packit 6c4009
		return (NULL);
Packit 6c4009
	if (name[0] == '\0')
Packit 6c4009
		putc('.', file);
Packit 6c4009
	else
Packit 6c4009
		fputs(name, file);
Packit 6c4009
	return (cp + n);
Packit 6c4009
}
Packit 6c4009
libresolv_hidden_def (p_cdnname)
Packit 6c4009
Packit 6c4009
const u_char *
Packit 6c4009
p_cdname(const u_char *cp, const u_char *msg, FILE *file) {
Packit 6c4009
	return (p_cdnname(cp, msg, PACKETSZ, file));
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Return a fully-qualified domain name from a compressed name (with
Packit 6c4009
   length supplied).  */
Packit 6c4009
Packit 6c4009
const u_char *
Packit 6c4009
p_fqnname (const u_char *cp, const u_char *msg, int msglen, char *name,
Packit 6c4009
	   int namelen)
Packit 6c4009
{
Packit 6c4009
	int n, newlen;
Packit 6c4009
Packit 6c4009
	if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
Packit 6c4009
		return (NULL);
Packit 6c4009
	newlen = strlen(name);
Packit 6c4009
	if (newlen == 0 || name[newlen - 1] != '.') {
Packit 6c4009
		if (newlen + 1 >= namelen)	/* Lack space for final dot */
Packit 6c4009
			return (NULL);
Packit 6c4009
		else
Packit 6c4009
			strcpy(name + newlen, ".");
Packit 6c4009
	}
Packit 6c4009
	return (cp + n);
Packit 6c4009
}
Packit 6c4009
libresolv_hidden_def (p_fqnname)
Packit 6c4009
Packit 6c4009
/* XXX:	the rest of these functions need to become length-limited, too. */
Packit 6c4009
Packit 6c4009
const u_char *
Packit 6c4009
p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
Packit 6c4009
	char name[MAXDNAME];
Packit 6c4009
	const u_char *n;
Packit 6c4009
Packit 6c4009
	n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
Packit 6c4009
	if (n == NULL)
Packit 6c4009
		return (NULL);
Packit 6c4009
	fputs(name, file);
Packit 6c4009
	return (n);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Names of RR classes and qclasses.  Classes and qclasses are the same, except
Packit 6c4009
 * that C_ANY is a qclass but not a class.  (You can ask for records of class
Packit 6c4009
 * C_ANY, but you can't have any records of that class in the database.)
Packit 6c4009
 */
Packit 6c4009
extern const struct res_sym __p_class_syms[];
Packit 6c4009
libresolv_hidden_proto (__p_class_syms)
Packit 6c4009
const struct res_sym __p_class_syms[] = {
Packit 6c4009
  {C_IN,    (char *) "IN"},
Packit 6c4009
  {C_CHAOS, (char *) "CHAOS"},
Packit 6c4009
  {C_HS,    (char *) "HS"},
Packit 6c4009
  {C_HS,    (char *) "HESIOD"},
Packit 6c4009
  {C_ANY,   (char *) "ANY"},
Packit 6c4009
  {C_NONE,  (char *) "NONE"},
Packit 6c4009
  {C_IN, NULL, NULL}
Packit 6c4009
};
Packit 6c4009
libresolv_hidden_data_def (__p_class_syms)
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Names of message sections.
Packit 6c4009
 */
Packit 6c4009
const struct res_sym __p_default_section_syms[] attribute_hidden = {
Packit 6c4009
  {ns_s_qd, (char *) "QUERY"},
Packit 6c4009
  {ns_s_an, (char *) "ANSWER"},
Packit 6c4009
  {ns_s_ns, (char *) "AUTHORITY"},
Packit 6c4009
  {ns_s_ar, (char *) "ADDITIONAL"},
Packit 6c4009
  {0, NULL, NULL}
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
const struct res_sym __p_update_section_syms[] attribute_hidden = {
Packit 6c4009
  {S_ZONE,   (char *) "ZONE"},
Packit 6c4009
  {S_PREREQ, (char *) "PREREQUISITE"},
Packit 6c4009
  {S_UPDATE, (char *) "UPDATE"},
Packit 6c4009
  {S_ADDT,   (char *) "ADDITIONAL"},
Packit 6c4009
  {0, NULL, NULL}
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Names of RR types and qtypes.  The list is incomplete because its
Packit 6c4009
 * size is part of the ABI.
Packit 6c4009
 */
Packit 6c4009
extern const struct res_sym __p_type_syms[];
Packit 6c4009
libresolv_hidden_proto (__p_type_syms)
Packit 6c4009
const struct res_sym __p_type_syms[] = {
Packit 6c4009
  {ns_t_a,      (char *) "A",     (char *) "address"},
Packit 6c4009
  {ns_t_ns,     (char *) "NS",    (char *) "name server"},
Packit 6c4009
  {ns_t_md,     (char *) "MD",    (char *) "mail destination (deprecated)"},
Packit 6c4009
  {ns_t_mf,     (char *) "MF",    (char *) "mail forwarder (deprecated)"},
Packit 6c4009
  {ns_t_cname,  (char *) "CNAME", (char *) "canonical name"},
Packit 6c4009
  {ns_t_soa,    (char *) "SOA",   (char *) "start of authority"},
Packit 6c4009
  {ns_t_mb,     (char *) "MB",    (char *) "mailbox"},
Packit 6c4009
  {ns_t_mg,     (char *) "MG",    (char *) "mail group member"},
Packit 6c4009
  {ns_t_mr,     (char *) "MR",    (char *) "mail rename"},
Packit 6c4009
  {ns_t_null,   (char *) "NULL",  (char *) "null"},
Packit 6c4009
  {ns_t_wks,    (char *) "WKS",   (char *) "well-known service (deprecated)"},
Packit 6c4009
  {ns_t_ptr,    (char *) "PTR",   (char *) "domain name pointer"},
Packit 6c4009
  {ns_t_hinfo,  (char *) "HINFO", (char *) "host information"},
Packit 6c4009
  {ns_t_minfo,  (char *) "MINFO", (char *) "mailbox information"},
Packit 6c4009
  {ns_t_mx,     (char *) "MX",    (char *) "mail exchanger"},
Packit 6c4009
  {ns_t_txt,    (char *) "TXT",   (char *) "text"},
Packit 6c4009
  {ns_t_rp,     (char *) "RP",    (char *) "responsible person"},
Packit 6c4009
  {ns_t_afsdb,  (char *) "AFSDB", (char *) "DCE or AFS server"},
Packit 6c4009
  {ns_t_x25,    (char *) "X25",   (char *) "X25 address"},
Packit 6c4009
  {ns_t_isdn,   (char *) "ISDN",  (char *) "ISDN address"},
Packit 6c4009
  {ns_t_rt,     (char *) "RT",    (char *) "router"},
Packit 6c4009
  {ns_t_nsap,   (char *) "NSAP",  (char *) "nsap address"},
Packit 6c4009
  {ns_t_nsap_ptr, (char *) "NSAP_PTR", (char *) "domain name pointer"},
Packit 6c4009
  {ns_t_sig,    (char *) "SIG",   (char *) "signature"},
Packit 6c4009
  {ns_t_key,    (char *) "KEY",   (char *) "key"},
Packit 6c4009
  {ns_t_px,     (char *) "PX",    (char *) "mapping information"},
Packit 6c4009
  {ns_t_gpos,   (char *) "GPOS",
Packit 6c4009
   (char *) "geographical position (withdrawn)"},
Packit 6c4009
  {ns_t_aaaa,   (char *) "AAAA",  (char *) "IPv6 address"},
Packit 6c4009
  {ns_t_loc,    (char *) "LOC",   (char *) "location"},
Packit 6c4009
  {ns_t_nxt,    (char *) "NXT",   (char *) "next valid name (unimplemented)"},
Packit 6c4009
  {ns_t_eid,    (char *) "EID",   (char *) "endpoint identifier (unimplemented)"},
Packit 6c4009
  {ns_t_nimloc, (char *) "NIMLOC", (char *) "NIMROD locator (unimplemented)"},
Packit 6c4009
  {ns_t_srv,    (char *) "SRV",   (char *) "server selection"},
Packit 6c4009
  {ns_t_atma,   (char *) "ATMA",  (char *) "ATM address (unimplemented)"},
Packit 6c4009
  {ns_t_dname,  (char *) "DNAME", (char *) "Non-terminal DNAME (for IPv6)"},
Packit 6c4009
  {ns_t_tsig,   (char *) "TSIG",  (char *) "transaction signature"},
Packit 6c4009
  {ns_t_ixfr,   (char *) "IXFR",  (char *) "incremental zone transfer"},
Packit 6c4009
  {ns_t_axfr,   (char *) "AXFR",  (char *) "zone transfer"},
Packit 6c4009
  {ns_t_mailb,  (char *) "MAILB", (char *) "mailbox-related data (deprecated)"},
Packit 6c4009
  {ns_t_maila,  (char *) "MAILA", (char *) "mail agent (deprecated)"},
Packit 6c4009
  {ns_t_naptr,  (char *) "NAPTR", (char *) "URN Naming Authority"},
Packit 6c4009
  {ns_t_kx,     (char *) "KX",    (char *) "Key Exchange"},
Packit 6c4009
  {ns_t_cert,   (char *) "CERT",  (char *) "Certificate"},
Packit 6c4009
  {ns_t_any,    (char *) "ANY",   (char *) "\"any\""},
Packit 6c4009
  {0, NULL, NULL},		/* Padding to preserve ABI.  */
Packit 6c4009
  {0, NULL, NULL}
Packit 6c4009
};
Packit 6c4009
libresolv_hidden_data_def (__p_type_syms)
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Names of DNS rcodes.
Packit 6c4009
 */
Packit 6c4009
const struct res_sym __p_rcode_syms[] attribute_hidden = {
Packit 6c4009
  {ns_r_noerror,  (char *) "NOERROR",  (char *) "no error"},
Packit 6c4009
  {ns_r_formerr,  (char *) "FORMERR",  (char *) "format error"},
Packit 6c4009
  {ns_r_servfail, (char *) "SERVFAIL", (char *) "server failed"},
Packit 6c4009
  {ns_r_nxdomain, (char *) "NXDOMAIN", (char *) "no such domain name"},
Packit 6c4009
  {ns_r_notimpl,  (char *) "NOTIMP",   (char *) "not implemented"},
Packit 6c4009
  {ns_r_refused,  (char *) "REFUSED",  (char *) "refused"},
Packit 6c4009
  {ns_r_yxdomain, (char *) "YXDOMAIN", (char *) "domain name exists"},
Packit 6c4009
  {ns_r_yxrrset,  (char *) "YXRRSET",  (char *) "rrset exists"},
Packit 6c4009
  {ns_r_nxrrset,  (char *) "NXRRSET",  (char *) "rrset doesn't exist"},
Packit 6c4009
  {ns_r_notauth,  (char *) "NOTAUTH",  (char *) "not authoritative"},
Packit 6c4009
  {ns_r_notzone,  (char *) "NOTZONE",  (char *) "Not in zone"},
Packit 6c4009
  {ns_r_max,      (char *) "",         (char *) ""},
Packit 6c4009
  {ns_r_badsig,   (char *) "BADSIG",   (char *) "bad signature"},
Packit 6c4009
  {ns_r_badkey,   (char *) "BADKEY",   (char *) "bad key"},
Packit 6c4009
  {ns_r_badtime,  (char *) "BADTIME",  (char *) "bad time"},
Packit 6c4009
  {0, NULL, NULL}
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
sym_ston(const struct res_sym *syms, const char *name, int *success) {
Packit 6c4009
	for ((void)NULL; syms->name != 0; syms++) {
Packit 6c4009
		if (strcasecmp (name, syms->name) == 0) {
Packit 6c4009
			if (success)
Packit 6c4009
				*success = 1;
Packit 6c4009
			return (syms->number);
Packit 6c4009
		}
Packit 6c4009
	}
Packit 6c4009
	if (success)
Packit 6c4009
		*success = 0;
Packit 6c4009
	return (syms->number);		/* The default value. */
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
const char *
Packit 6c4009
sym_ntos(const struct res_sym *syms, int number, int *success) {
Packit 6c4009
	static char unname[20];
Packit 6c4009
Packit 6c4009
	for ((void)NULL; syms->name != 0; syms++) {
Packit 6c4009
		if (number == syms->number) {
Packit 6c4009
			if (success)
Packit 6c4009
				*success = 1;
Packit 6c4009
			return (syms->name);
Packit 6c4009
		}
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
	sprintf(unname, "%d", number);		/* XXX nonreentrant */
Packit 6c4009
	if (success)
Packit 6c4009
		*success = 0;
Packit 6c4009
	return (unname);
Packit 6c4009
}
Packit 6c4009
libresolv_hidden_def (sym_ntos)
Packit 6c4009
Packit 6c4009
const char *
Packit 6c4009
sym_ntop(const struct res_sym *syms, int number, int *success) {
Packit 6c4009
	static char unname[20];
Packit 6c4009
Packit 6c4009
	for ((void)NULL; syms->name != 0; syms++) {
Packit 6c4009
		if (number == syms->number) {
Packit 6c4009
			if (success)
Packit 6c4009
				*success = 1;
Packit 6c4009
			return (syms->humanname);
Packit 6c4009
		}
Packit 6c4009
	}
Packit 6c4009
	sprintf(unname, "%d", number);		/* XXX nonreentrant */
Packit 6c4009
	if (success)
Packit 6c4009
		*success = 0;
Packit 6c4009
	return (unname);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Return a string for the type.
Packit 6c4009
 */
Packit 6c4009
const char *
Packit 6c4009
p_type(int type) {
Packit 6c4009
	return (sym_ntos(__p_type_syms, type, (int *)0));
Packit 6c4009
}
Packit 6c4009
libresolv_hidden_def (p_type)
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Return a string for the type.
Packit 6c4009
 */
Packit 6c4009
static const char *
Packit 6c4009
p_section(int section, int opcode) {
Packit 6c4009
	const struct res_sym *symbols;
Packit 6c4009
Packit 6c4009
	switch (opcode) {
Packit 6c4009
	case ns_o_update:
Packit 6c4009
		symbols = __p_update_section_syms;
Packit 6c4009
		break;
Packit 6c4009
	default:
Packit 6c4009
		symbols = __p_default_section_syms;
Packit 6c4009
		break;
Packit 6c4009
	}
Packit 6c4009
	return (sym_ntos(symbols, section, (int *)0));
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Return a mnemonic for class.
Packit 6c4009
 */
Packit 6c4009
const char *
Packit 6c4009
p_class(int class) {
Packit 6c4009
	return (sym_ntos(__p_class_syms, class, (int *)0));
Packit 6c4009
}
Packit 6c4009
libresolv_hidden_def (p_class)
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Return a mnemonic for an option
Packit 6c4009
 */
Packit 6c4009
const char *
Packit 6c4009
p_option(u_long option) {
Packit 6c4009
	static char nbuf[40];
Packit 6c4009
Packit 6c4009
	switch (option) {
Packit 6c4009
	case RES_INIT:		return "init";
Packit 6c4009
	case RES_DEBUG:		return "debug";
Packit 6c4009
	case RES_USEVC:		return "use-vc";
Packit 6c4009
	case RES_IGNTC:		return "igntc";
Packit 6c4009
	case RES_RECURSE:	return "recurs";
Packit 6c4009
	case RES_DEFNAMES:	return "defnam";
Packit 6c4009
	case RES_STAYOPEN:	return "styopn";
Packit 6c4009
	case RES_DNSRCH:	return "dnsrch";
Packit 6c4009
	case RES_INSECURE1:	return "insecure1";
Packit 6c4009
	case RES_INSECURE2:	return "insecure2";
Packit 6c4009
	case RES_NOALIASES:	return "noaliases";
Packit 6c4009
	case DEPRECATED_RES_USE_INET6:	return "inet6";
Packit 6c4009
	case RES_ROTATE:	return "rotate";
Packit 6c4009
	case RES_USE_EDNS0:	return "edns0";
Packit 6c4009
	case RES_SNGLKUP:	return "single-request";
Packit 6c4009
	case RES_SNGLKUPREOP:	return "single-request-reopen";
Packit 6c4009
	case RES_USE_DNSSEC:	return "dnssec";
Packit 6c4009
	case RES_NOTLDQUERY:	return "no-tld-query";
Packit 6c4009
	case RES_NORELOAD:	return "no-reload";
Packit 6c4009
				/* XXX nonreentrant */
Packit 6c4009
	default:		sprintf(nbuf, "?0x%lx?", (u_long)option);
Packit 6c4009
				return (nbuf);
Packit 6c4009
	}
Packit 6c4009
}
Packit 6c4009
libresolv_hidden_def (p_option)
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Return a mnemonic for a time to live.
Packit 6c4009
 */
Packit 6c4009
const char *
Packit 6c4009
p_time(uint32_t value) {
Packit 6c4009
	static char nbuf[40];		/* XXX nonreentrant */
Packit 6c4009
Packit 6c4009
	if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0)
Packit 6c4009
		sprintf(nbuf, "%u", value);
Packit 6c4009
	return (nbuf);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Return a string for the rcode.
Packit 6c4009
 */
Packit 6c4009
const char *
Packit 6c4009
p_rcode(int rcode) {
Packit 6c4009
	return (sym_ntos(__p_rcode_syms, rcode, (int *)0));
Packit 6c4009
}
Packit 6c4009
libresolv_hidden_def (p_rcode)
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * routines to convert between on-the-wire RR format and zone file format.
Packit 6c4009
 * Does not contain conversion to/from decimal degrees; divide or multiply
Packit 6c4009
 * by 60*60*1000 for that.
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
static const unsigned int poweroften[10]=
Packit 6c4009
  { 1, 10, 100, 1000, 10000, 100000,
Packit 6c4009
    1000000,10000000,100000000,1000000000};
Packit 6c4009
Packit 6c4009
/* takes an XeY precision/size value, returns a string representation. */
Packit 6c4009
static const char *
Packit 6c4009
precsize_ntoa (uint8_t prec)
Packit 6c4009
{
Packit 6c4009
	static char retbuf[sizeof "90000000.00"];	/* XXX nonreentrant */
Packit 6c4009
	unsigned long val;
Packit 6c4009
	int mantissa, exponent;
Packit 6c4009
Packit 6c4009
	mantissa = (int)((prec >> 4) & 0x0f) % 10;
Packit 6c4009
	exponent = (int)((prec >> 0) & 0x0f) % 10;
Packit 6c4009
Packit 6c4009
	val = mantissa * poweroften[exponent];
Packit 6c4009
Packit 6c4009
	(void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100);
Packit 6c4009
	return (retbuf);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* converts ascii size/precision X * 10**Y(cm) to 0xXY.  moves pointer. */
Packit 6c4009
static uint8_t
Packit 6c4009
precsize_aton (const char **strptr)
Packit 6c4009
{
Packit 6c4009
	unsigned int mval = 0, cmval = 0;
Packit 6c4009
	uint8_t retval = 0;
Packit 6c4009
	const char *cp;
Packit 6c4009
	int exponent;
Packit 6c4009
	int mantissa;
Packit 6c4009
Packit 6c4009
	cp = *strptr;
Packit 6c4009
Packit 6c4009
	while (isdigit(*cp))
Packit 6c4009
		mval = mval * 10 + (*cp++ - '0');
Packit 6c4009
Packit 6c4009
	if (*cp == '.') {		/* centimeters */
Packit 6c4009
		cp++;
Packit 6c4009
		if (isdigit(*cp)) {
Packit 6c4009
			cmval = (*cp++ - '0') * 10;
Packit 6c4009
			if (isdigit(*cp)) {
Packit 6c4009
				cmval += (*cp++ - '0');
Packit 6c4009
			}
Packit 6c4009
		}
Packit 6c4009
	}
Packit 6c4009
	cmval = (mval * 100) + cmval;
Packit 6c4009
Packit 6c4009
	for (exponent = 0; exponent < 9; exponent++)
Packit 6c4009
		if (cmval < poweroften[exponent+1])
Packit 6c4009
			break;
Packit 6c4009
Packit 6c4009
	mantissa = cmval / poweroften[exponent];
Packit 6c4009
	if (mantissa > 9)
Packit 6c4009
		mantissa = 9;
Packit 6c4009
Packit 6c4009
	retval = (mantissa << 4) | exponent;
Packit 6c4009
Packit 6c4009
	*strptr = cp;
Packit 6c4009
Packit 6c4009
	return (retval);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* converts ascii lat/lon to unsigned encoded 32-bit number.  moves pointer. */
Packit 6c4009
static uint32_t
Packit 6c4009
latlon2ul (const char **latlonstrptr, int *which)
Packit 6c4009
{
Packit 6c4009
	const char *cp;
Packit 6c4009
	uint32_t retval;
Packit 6c4009
	int deg = 0, min = 0, secs = 0, secsfrac = 0;
Packit 6c4009
Packit 6c4009
	cp = *latlonstrptr;
Packit 6c4009
Packit 6c4009
	while (isdigit(*cp))
Packit 6c4009
		deg = deg * 10 + (*cp++ - '0');
Packit 6c4009
Packit 6c4009
	while (isspace(*cp))
Packit 6c4009
		cp++;
Packit 6c4009
Packit 6c4009
	if (!(isdigit(*cp)))
Packit 6c4009
		goto fndhemi;
Packit 6c4009
Packit 6c4009
	while (isdigit(*cp))
Packit 6c4009
		min = min * 10 + (*cp++ - '0');
Packit 6c4009
Packit 6c4009
	while (isspace(*cp))
Packit 6c4009
		cp++;
Packit 6c4009
Packit 6c4009
	if (!(isdigit(*cp)))
Packit 6c4009
		goto fndhemi;
Packit 6c4009
Packit 6c4009
	while (isdigit(*cp))
Packit 6c4009
		secs = secs * 10 + (*cp++ - '0');
Packit 6c4009
Packit 6c4009
	if (*cp == '.') {		/* decimal seconds */
Packit 6c4009
		cp++;
Packit 6c4009
		if (isdigit(*cp)) {
Packit 6c4009
			secsfrac = (*cp++ - '0') * 100;
Packit 6c4009
			if (isdigit(*cp)) {
Packit 6c4009
				secsfrac += (*cp++ - '0') * 10;
Packit 6c4009
				if (isdigit(*cp)) {
Packit 6c4009
					secsfrac += (*cp++ - '0');
Packit 6c4009
				}
Packit 6c4009
			}
Packit 6c4009
		}
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
	while (!isspace(*cp))	/* if any trailing garbage */
Packit 6c4009
		cp++;
Packit 6c4009
Packit 6c4009
	while (isspace(*cp))
Packit 6c4009
		cp++;
Packit 6c4009
Packit 6c4009
 fndhemi:
Packit 6c4009
	switch (*cp) {
Packit 6c4009
	case 'N': case 'n':
Packit 6c4009
	case 'E': case 'e':
Packit 6c4009
		retval = ((unsigned)1<<31)
Packit 6c4009
			+ (((((deg * 60) + min) * 60) + secs) * 1000)
Packit 6c4009
			+ secsfrac;
Packit 6c4009
		break;
Packit 6c4009
	case 'S': case 's':
Packit 6c4009
	case 'W': case 'w':
Packit 6c4009
		retval = ((unsigned)1<<31)
Packit 6c4009
			- (((((deg * 60) + min) * 60) + secs) * 1000)
Packit 6c4009
			- secsfrac;
Packit 6c4009
		break;
Packit 6c4009
	default:
Packit 6c4009
		retval = 0;	/* invalid value -- indicates error */
Packit 6c4009
		break;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
	switch (*cp) {
Packit 6c4009
	case 'N': case 'n':
Packit 6c4009
	case 'S': case 's':
Packit 6c4009
		*which = 1;	/* latitude */
Packit 6c4009
		break;
Packit 6c4009
	case 'E': case 'e':
Packit 6c4009
	case 'W': case 'w':
Packit 6c4009
		*which = 2;	/* longitude */
Packit 6c4009
		break;
Packit 6c4009
	default:
Packit 6c4009
		*which = 0;	/* error */
Packit 6c4009
		break;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
	cp++;			/* skip the hemisphere */
Packit 6c4009
Packit 6c4009
	while (!isspace(*cp))	/* if any trailing garbage */
Packit 6c4009
		cp++;
Packit 6c4009
Packit 6c4009
	while (isspace(*cp))	/* move to next field */
Packit 6c4009
		cp++;
Packit 6c4009
Packit 6c4009
	*latlonstrptr = cp;
Packit 6c4009
Packit 6c4009
	return (retval);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* converts a zone file representation in a string to an RDATA on-the-wire
Packit 6c4009
 * representation. */
Packit 6c4009
int
Packit 6c4009
loc_aton (const char *ascii, u_char *binary)
Packit 6c4009
{
Packit 6c4009
	const char *cp, *maxcp;
Packit 6c4009
	u_char *bcp;
Packit 6c4009
Packit 6c4009
	uint32_t latit = 0, longit = 0, alt = 0;
Packit 6c4009
	uint32_t lltemp1 = 0, lltemp2 = 0;
Packit 6c4009
	int altmeters = 0, altfrac = 0, altsign = 1;
Packit 6c4009
	uint8_t hp = 0x16;	/* default = 1e6 cm = 10000.00m = 10km */
Packit 6c4009
	uint8_t vp = 0x13;	/* default = 1e3 cm = 10.00m */
Packit 6c4009
	uint8_t siz = 0x12;	/* default = 1e2 cm = 1.00m */
Packit 6c4009
	int which1 = 0, which2 = 0;
Packit 6c4009
Packit 6c4009
	cp = ascii;
Packit 6c4009
	maxcp = cp + strlen(ascii);
Packit 6c4009
Packit 6c4009
	lltemp1 = latlon2ul(&cp, &which1);
Packit 6c4009
Packit 6c4009
	lltemp2 = latlon2ul(&cp, &which2);
Packit 6c4009
Packit 6c4009
	switch (which1 + which2) {
Packit 6c4009
	case 3:			/* 1 + 2, the only valid combination */
Packit 6c4009
		if ((which1 == 1) && (which2 == 2)) { /* normal case */
Packit 6c4009
			latit = lltemp1;
Packit 6c4009
			longit = lltemp2;
Packit 6c4009
		} else if ((which1 == 2) && (which2 == 1)) { /* reversed */
Packit 6c4009
			longit = lltemp1;
Packit 6c4009
			latit = lltemp2;
Packit 6c4009
		} else {	/* some kind of brokenness */
Packit 6c4009
			return (0);
Packit 6c4009
		}
Packit 6c4009
		break;
Packit 6c4009
	default:		/* we didn't get one of each */
Packit 6c4009
		return (0);
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
	/* altitude */
Packit 6c4009
	if (*cp == '-') {
Packit 6c4009
		altsign = -1;
Packit 6c4009
		cp++;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
	if (*cp == '+')
Packit 6c4009
		cp++;
Packit 6c4009
Packit 6c4009
	while (isdigit(*cp))
Packit 6c4009
		altmeters = altmeters * 10 + (*cp++ - '0');
Packit 6c4009
Packit 6c4009
	if (*cp == '.') {		/* decimal meters */
Packit 6c4009
		cp++;
Packit 6c4009
		if (isdigit(*cp)) {
Packit 6c4009
			altfrac = (*cp++ - '0') * 10;
Packit 6c4009
			if (isdigit(*cp)) {
Packit 6c4009
				altfrac += (*cp++ - '0');
Packit 6c4009
			}
Packit 6c4009
		}
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
	alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
Packit 6c4009
Packit 6c4009
	while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
Packit 6c4009
		cp++;
Packit 6c4009
Packit 6c4009
	while (isspace(*cp) && (cp < maxcp))
Packit 6c4009
		cp++;
Packit 6c4009
Packit 6c4009
	if (cp >= maxcp)
Packit 6c4009
		goto defaults;
Packit 6c4009
Packit 6c4009
	siz = precsize_aton(&cp;;
Packit 6c4009
Packit 6c4009
	while (!isspace(*cp) && (cp < maxcp))	/* if trailing garbage or m */
Packit 6c4009
		cp++;
Packit 6c4009
Packit 6c4009
	while (isspace(*cp) && (cp < maxcp))
Packit 6c4009
		cp++;
Packit 6c4009
Packit 6c4009
	if (cp >= maxcp)
Packit 6c4009
		goto defaults;
Packit 6c4009
Packit 6c4009
	hp = precsize_aton(&cp;;
Packit 6c4009
Packit 6c4009
	while (!isspace(*cp) && (cp < maxcp))	/* if trailing garbage or m */
Packit 6c4009
		cp++;
Packit 6c4009
Packit 6c4009
	while (isspace(*cp) && (cp < maxcp))
Packit 6c4009
		cp++;
Packit 6c4009
Packit 6c4009
	if (cp >= maxcp)
Packit 6c4009
		goto defaults;
Packit 6c4009
Packit 6c4009
	vp = precsize_aton(&cp;;
Packit 6c4009
Packit 6c4009
 defaults:
Packit 6c4009
Packit 6c4009
	bcp = binary;
Packit 6c4009
	*bcp++ = (uint8_t) 0;	/* version byte */
Packit 6c4009
	*bcp++ = siz;
Packit 6c4009
	*bcp++ = hp;
Packit 6c4009
	*bcp++ = vp;
Packit 6c4009
	PUTLONG(latit,bcp);
Packit 6c4009
	PUTLONG(longit,bcp);
Packit 6c4009
	PUTLONG(alt,bcp);
Packit 6c4009
Packit 6c4009
	return (16);		/* size of RR in octets */
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* takes an on-the-wire LOC RR and formats it in a human readable format. */
Packit 6c4009
const char *
Packit 6c4009
loc_ntoa (const u_char *binary, char *ascii)
Packit 6c4009
{
Packit 6c4009
	static const char error[] = "?";
Packit 6c4009
	static char tmpbuf[sizeof
Packit 6c4009
"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
Packit 6c4009
	const u_char *cp = binary;
Packit 6c4009
Packit 6c4009
	int latdeg, latmin, latsec, latsecfrac;
Packit 6c4009
	int longdeg, longmin, longsec, longsecfrac;
Packit 6c4009
	char northsouth, eastwest;
Packit 6c4009
	int altmeters, altfrac, altsign;
Packit 6c4009
Packit 6c4009
	const uint32_t referencealt = 100000 * 100;
Packit 6c4009
Packit 6c4009
	int32_t latval, longval, altval;
Packit 6c4009
	uint32_t templ;
Packit 6c4009
	uint8_t sizeval, hpval, vpval, versionval;
Packit 6c4009
Packit 6c4009
	char *sizestr, *hpstr, *vpstr;
Packit 6c4009
Packit 6c4009
	versionval = *cp++;
Packit 6c4009
Packit 6c4009
	if (ascii == NULL)
Packit 6c4009
		ascii = tmpbuf;
Packit 6c4009
Packit 6c4009
	if (versionval) {
Packit 6c4009
		(void) sprintf(ascii, "; error: unknown LOC RR version");
Packit 6c4009
		return (ascii);
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
	sizeval = *cp++;
Packit 6c4009
Packit 6c4009
	hpval = *cp++;
Packit 6c4009
	vpval = *cp++;
Packit 6c4009
Packit 6c4009
	GETLONG(templ, cp);
Packit 6c4009
	latval = (templ - ((unsigned)1<<31));
Packit 6c4009
Packit 6c4009
	GETLONG(templ, cp);
Packit 6c4009
	longval = (templ - ((unsigned)1<<31));
Packit 6c4009
Packit 6c4009
	GETLONG(templ, cp);
Packit 6c4009
	if (templ < referencealt) { /* below WGS 84 spheroid */
Packit 6c4009
		altval = referencealt - templ;
Packit 6c4009
		altsign = -1;
Packit 6c4009
	} else {
Packit 6c4009
		altval = templ - referencealt;
Packit 6c4009
		altsign = 1;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
	if (latval < 0) {
Packit 6c4009
		northsouth = 'S';
Packit 6c4009
		latval = -latval;
Packit 6c4009
	} else
Packit 6c4009
		northsouth = 'N';
Packit 6c4009
Packit 6c4009
	latsecfrac = latval % 1000;
Packit 6c4009
	latval = latval / 1000;
Packit 6c4009
	latsec = latval % 60;
Packit 6c4009
	latval = latval / 60;
Packit 6c4009
	latmin = latval % 60;
Packit 6c4009
	latval = latval / 60;
Packit 6c4009
	latdeg = latval;
Packit 6c4009
Packit 6c4009
	if (longval < 0) {
Packit 6c4009
		eastwest = 'W';
Packit 6c4009
		longval = -longval;
Packit 6c4009
	} else
Packit 6c4009
		eastwest = 'E';
Packit 6c4009
Packit 6c4009
	longsecfrac = longval % 1000;
Packit 6c4009
	longval = longval / 1000;
Packit 6c4009
	longsec = longval % 60;
Packit 6c4009
	longval = longval / 60;
Packit 6c4009
	longmin = longval % 60;
Packit 6c4009
	longval = longval / 60;
Packit 6c4009
	longdeg = longval;
Packit 6c4009
Packit 6c4009
	altfrac = altval % 100;
Packit 6c4009
	altmeters = (altval / 100) * altsign;
Packit 6c4009
Packit 6c4009
	if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
Packit 6c4009
		sizestr = (char *) error;
Packit 6c4009
	if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
Packit 6c4009
		hpstr = (char *) error;
Packit 6c4009
	if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
Packit 6c4009
		vpstr = (char *) error;
Packit 6c4009
Packit 6c4009
	sprintf(ascii,
Packit 6c4009
	      "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
Packit 6c4009
		latdeg, latmin, latsec, latsecfrac, northsouth,
Packit 6c4009
		longdeg, longmin, longsec, longsecfrac, eastwest,
Packit 6c4009
		altmeters, altfrac, sizestr, hpstr, vpstr);
Packit 6c4009
Packit 6c4009
	if (sizestr != (char *) error)
Packit 6c4009
		free(sizestr);
Packit 6c4009
	if (hpstr != (char *) error)
Packit 6c4009
		free(hpstr);
Packit 6c4009
	if (vpstr != (char *) error)
Packit 6c4009
		free(vpstr);
Packit 6c4009
Packit 6c4009
	return (ascii);
Packit 6c4009
}
Packit 6c4009
libresolv_hidden_def (loc_ntoa)
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Return the number of DNS hierarchy levels in the name. */
Packit 6c4009
int
Packit 6c4009
dn_count_labels(const char *name) {
Packit 6c4009
	int i, len, count;
Packit 6c4009
Packit 6c4009
	len = strlen(name);
Packit 6c4009
	for (i = 0, count = 0; i < len; i++) {
Packit 6c4009
		/* XXX need to check for \. or use named's nlabels(). */
Packit 6c4009
		if (name[i] == '.')
Packit 6c4009
			count++;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
	/* don't count initial wildcard */
Packit 6c4009
	if (name[0] == '*')
Packit 6c4009
		if (count)
Packit 6c4009
			count--;
Packit 6c4009
Packit 6c4009
	/* don't count the null label for root. */
Packit 6c4009
	/* if terminating '.' not found, must adjust */
Packit 6c4009
	/* count to include last label */
Packit 6c4009
	if (len > 0 && name[len-1] != '.')
Packit 6c4009
		count++;
Packit 6c4009
	return (count);
Packit 6c4009
}
Packit 6c4009
libresolv_hidden_def (__dn_count_labels)
Packit 6c4009
Packit 6c4009
Packit 6c4009
#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_27)
Packit 6c4009
/*
Packit 6c4009
 * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
Packit 6c4009
 * SIG records are required to be printed like this, by the Secure DNS RFC.
Packit 6c4009
 * This is an obsolescent function and does not handle dates outside the
Packit 6c4009
 * signed 32-bit range.
Packit 6c4009
 */
Packit 6c4009
char *
Packit 6c4009
__p_secstodate (u_long secs) {
Packit 6c4009
	/* XXX nonreentrant */
Packit 6c4009
	static char output[15];		/* YYYYMMDDHHMMSS and null */
Packit 6c4009
	time_t clock = secs;
Packit 6c4009
	struct tm *time;
Packit 6c4009
Packit 6c4009
	struct tm timebuf;
Packit 6c4009
	/* The call to __gmtime_r can never produce a year overflowing
Packit 6c4009
	   the range of int, given the check on SECS, but check for a
Packit 6c4009
	   NULL return anyway to avoid a null pointer dereference in
Packit 6c4009
	   case there are any other unspecified errors.  */
Packit 6c4009
	if (secs > 0x7fffffff
Packit 6c4009
	    || (time = __gmtime_r (&clock, &timebuf)) == NULL) {
Packit 6c4009
		strcpy (output, "<overflow>");
Packit 6c4009
		__set_errno (EOVERFLOW);
Packit 6c4009
		return output;
Packit 6c4009
	}
Packit 6c4009
	time->tm_year += 1900;
Packit 6c4009
	time->tm_mon += 1;
Packit 6c4009
	/* The struct tm fields, given the above range check,
Packit 6c4009
	   must have values that mean this sprintf exactly fills the
Packit 6c4009
	   buffer.  But as of GCC 8 of 2017-11-21, GCC cannot tell
Packit 6c4009
	   that, even given range checks on all fields with
Packit 6c4009
	   __builtin_unreachable called for out-of-range values.  */
Packit 6c4009
	DIAG_PUSH_NEEDS_COMMENT;
Packit 6c4009
# if __GNUC_PREREQ (7, 0)
Packit 6c4009
	DIAG_IGNORE_NEEDS_COMMENT (8, "-Wformat-overflow=");
Packit 6c4009
# endif
Packit 6c4009
	sprintf(output, "%04d%02d%02d%02d%02d%02d",
Packit 6c4009
		time->tm_year, time->tm_mon, time->tm_mday,
Packit 6c4009
		time->tm_hour, time->tm_min, time->tm_sec);
Packit 6c4009
	DIAG_POP_NEEDS_COMMENT;
Packit 6c4009
	return (output);
Packit 6c4009
}
Packit 6c4009
compat_symbol (libresolv, __p_secstodate, __p_secstodate, GLIBC_2_0);
Packit 6c4009
#endif