summaryrefslogtreecommitdiff
path: root/resolv
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1999-12-04 18:05:55 +0000
committerUlrich Drepper <drepper@redhat.com>1999-12-04 18:05:55 +0000
commitb43b13ac2544b11f35be301d1589b51a8473e32b (patch)
tree6520da2e17c933ebc29b4572cdcc27410b10a4c4 /resolv
parent591e1ffbf8db5e059b9bcf3bde6d7758f018a46d (diff)
Update.
1999-12-03 Andreas Jaeger <aj@suse.de> * nss/getXXbyYY.c: Include <resolv.h> (FUNCTION_NAME): Use res_ninit instead of res_init. * nss/getXXbyYY_r.c [NEED__RES]: Include <resolv.h> for _res declaration and prototypes. Remove extra _res declaration. (INTERNAL): Use thread aware res_ninit function. * inet/gethstbyad_r.c: Include <resolv.h>. * resolv/res_data.c: Update from Bind 8.2.2-P5. Moved res_init to res_libc.c. Disabled unneeded functions. * resolv/res_libc.c: New file. * Versions.def: Add version GLIBC_2.2 for libpthread. Add versions GLIBC_2.1 and GLIBC_2.2 for libresolv. * include/resolv.h: Add internal interfaces. * resolv/Makefile (routines): Add new files. (libresolv-routines): Likewise. (distribute): Likewise. * resolv/gethnamaddr.c: Use thread safe resolver functions. * resolv/nss_dns/dns-host.c: Likewise. * resolv/nss_dns/dns-network.c: Likewise. * resolv/arpa/nameser.h: Update from Bind 8.2.2-P5. * resolv/nsap_addr.c: Likewise. * resolv/res_comp.c: Likewise. * resolv/res_debug.c: Likewise. * resolv/res_init.c: Likewise. * resolv/res_mkquery.c: Likewise. * resolv/res_query.c: Likewise. * resolv/res_send.c: Likewise. * resolv/resolv.h: Likewise. * resolv/Versions: Add __res_state and __res_ninit with version GLIBC_2.2 to libc. Add new interfaces with version GLIBC_2.2 to libresolv. * resolv/Banner: Update. * include/arpa/nameser_compat.h: New file. * resolv/ns_name.c: New file from Bind 8.2.2-P5. * resolv/ns_netint.c: Likewise. * resolv/ns_parse.c: Likewise. * resolv/ns_print.c: Likewise. * resolv/ns_samedomain.c: Likewise. * resolv/ns_ttl.c: Likewise. * resolv/arpa/nameser_compat.h: Likewise. * resolv/res_debug.h: Likewise. Some patches are based on work done by Adam D. Bradley <artdodge@cs.bu.edu>. * sysdeps/unix/sysv/linux/configure.in: Remove check for ldconfig, set always use_ldconfig instead.
Diffstat (limited to 'resolv')
-rw-r--r--resolv/Banner2
-rw-r--r--resolv/Makefile11
-rw-r--r--resolv/Versions7
-rw-r--r--resolv/arpa/nameser.h670
-rw-r--r--resolv/arpa/nameser_compat.h184
-rw-r--r--resolv/gethnamaddr.c20
-rw-r--r--resolv/ns_name.c636
-rw-r--r--resolv/ns_netint.c52
-rw-r--r--resolv/ns_parse.c194
-rw-r--r--resolv/ns_print.c818
-rw-r--r--resolv/ns_samedomain.c202
-rw-r--r--resolv/ns_ttl.c154
-rw-r--r--resolv/nsap_addr.c34
-rw-r--r--resolv/nss_dns/dns-host.c19
-rw-r--r--resolv/nss_dns/dns-network.c14
-rw-r--r--resolv/res_comp.c792
-rw-r--r--resolv/res_data.c335
-rw-r--r--resolv/res_debug.c1234
-rw-r--r--resolv/res_debug.h34
-rw-r--r--resolv/res_init.c436
-rw-r--r--resolv/res_libc.c98
-rw-r--r--resolv/res_mkquery.c81
-rw-r--r--resolv/res_query.c261
-rw-r--r--resolv/res_send.c759
-rw-r--r--resolv/resolv.h299
25 files changed, 4469 insertions, 2877 deletions
diff --git a/resolv/Banner b/resolv/Banner
index 5d1fdeb336..d05a4e3ee7 100644
--- a/resolv/Banner
+++ b/resolv/Banner
@@ -1 +1 @@
-BIND-4.9.7-REL
+BIND-8.2.2-5
diff --git a/resolv/Makefile b/resolv/Makefile
index 71a66fe0f0..c8dc54a80c 100644
--- a/resolv/Makefile
+++ b/resolv/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# Copyright (C) 1994,95,96,97,98,1999 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
@@ -23,9 +23,10 @@ subdir := resolv
headers := resolv.h netdb.h arpa/nameser.h sys/bitypes.h
distribute := ../conf/portability.h mapv4v6addr.h mapv4v6hostent.h \
- Banner res_hconf.h
+ Banner res_hconf.h res_debug.h
-routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init res_hconf
+routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \
+ res_hconf res_libc
tests = tst-aton
@@ -35,7 +36,9 @@ extra-libs := libresolv libnss_dns
extra-libs-others = $(extra-libs)
libresolv-routines := gethnamaddr res_comp res_debug \
res_data res_mkquery res_query res_send \
- inet_net_ntop inet_net_pton inet_neta base64
+ inet_net_ntop inet_net_pton inet_neta base64 \
+ ns_parse ns_name ns_netint ns_ttl ns_print \
+ ns_samedomain
subdir-dirs = nss_dns
vpath %.c nss_dns
diff --git a/resolv/Versions b/resolv/Versions
index 9bf6a39b6a..3448c9281b 100644
--- a/resolv/Versions
+++ b/resolv/Versions
@@ -18,6 +18,10 @@ libc {
# r*
res_init;
}
+ GLIBC_2.2 {
+ # r*
+ __res_state; __res_ninit;
+ }
}
libresolv {
@@ -46,6 +50,9 @@ libresolv {
# Needed in libnss_dns.
__ns_name_unpack; __ns_name_ntop;
}
+ GLIBC_2.2 {
+ __res_nmkquery; __res_nquery; __res_nquerydomain; __res_nsearch;
+ __ns_get16;
}
libnss_dns {
diff --git a/resolv/arpa/nameser.h b/resolv/arpa/nameser.h
index 8866d90897..6655f3b8d2 100644
--- a/resolv/arpa/nameser.h
+++ b/resolv/arpa/nameser.h
@@ -1,9 +1,7 @@
/*
- * ++Copyright++ 1983, 1989, 1993
- * -
* Copyright (c) 1983, 1989, 1993
* The Regents of the University of California. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -15,7 +13,7 @@
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -27,320 +25,524 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- * -
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies, and that
- * the name of Digital Equipment Corporation not be used in advertising or
- * publicity pertaining to distribution of the document or software without
- * specific, written prior permission.
+ * copyright notice and this permission notice appear in all copies.
*
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
- * -
- * Portions Copyright (c) 1995 by International Business Machines, Inc.
- *
- * International Business Machines, Inc. (hereinafter called IBM) grants
- * permission under its copyrights to use, copy, modify, and distribute this
- * Software with or without fee, provided that the above copyright notice and
- * all paragraphs of this notice appear in all copies, and that the name of IBM
- * not be used in connection with the marketing of any product incorporating
- * the Software or modifications thereof, without specific, written prior
- * permission.
- *
- * To the extent it has a right to do so, IBM grants an immunity from suit
- * under its patents, if any, for the use, sale or manufacture of products to
- * the extent that such products are used for performing Domain Name System
- * dynamic updates in TCP/IP networks by means of the Software. No immunity is
- * granted for any product per se or for any other function of any product.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
- * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
- * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
- * --Copyright--
*/
/*
- * @(#)nameser.h 8.1 (Berkeley) 6/2/93
* $Id$
*/
-#ifndef _ARPA_NAMESER_H
-#define _ARPA_NAMESER_H 1
+#ifndef _ARPA_NAMESER_H_
+#define _ARPA_NAMESER_H_
+
+#define BIND_4_COMPAT
#include <features.h>
#include <sys/param.h>
#include <sys/types.h>
/*
- * revision information. this is the release date in YYYYMMDD format.
- * it can change every day so the right thing to do with it is use it
- * in preprocessor commands such as "#if (__BIND > 19931104)". do not
- * compare for equality; rather, use it to determine whether your resolver
- * is new enough to contain a certain feature.
+ * Revision information. This is the release date in YYYYMMDD format.
+ * It can change every day so the right thing to do with it is use it
+ * in preprocessor commands such as "#if (__NAMESER > 19931104)". Do not
+ * compare for equality; rather, use it to determine whether your libbind.a
+ * contains a new enough lib/nameser/ to support the feature you need.
*/
-#define __BIND 19960801 /* interface version stamp */
+#define __NAMESER 19991006 /* New interface version stamp. */
/*
- * Define constants based on rfc883
+ * Define constants based on RFC 883, RFC 1034, RFC 1035
*/
-#define PACKETSZ 512 /* maximum packet size */
-#define MAXDNAME 1025 /* maximum domain name */
-#define MAXCDNAME 255 /* maximum compressed domain name */
-#define MAXLABEL 63 /* maximum length of domain label */
-#define HFIXEDSZ 12 /* #/bytes of fixed data in header */
-#define QFIXEDSZ 4 /* #/bytes of fixed data in query */
-#define RRFIXEDSZ 10 /* #/bytes of fixed data in r record */
-#define INT32SZ 4 /* for systems without 32-bit ints */
-#define INT16SZ 2 /* for systems without 16-bit ints */
-#define INADDRSZ 4 /* IPv4 T_A */
-#define IN6ADDRSZ 16 /* IPv6 T_AAAA */
+#define NS_PACKETSZ 512 /* maximum packet size */
+#define NS_MAXDNAME 1025 /* maximum domain name */
+#define NS_MAXCDNAME 255 /* maximum compressed domain name */
+#define NS_MAXLABEL 63 /* maximum length of domain label */
+#define NS_HFIXEDSZ 12 /* #/bytes of fixed data in header */
+#define NS_QFIXEDSZ 4 /* #/bytes of fixed data in query */
+#define NS_RRFIXEDSZ 10 /* #/bytes of fixed data in r record */
+#define NS_INT32SZ 4 /* #/bytes of data in a u_int32_t */
+#define NS_INT16SZ 2 /* #/bytes of data in a u_int16_t */
+#define NS_INT8SZ 1 /* #/bytes of data in a u_int8_t */
+#define NS_INADDRSZ 4 /* IPv4 T_A */
+#define NS_IN6ADDRSZ 16 /* IPv6 T_AAAA */
+#define NS_CMPRSFLGS 0xc0 /* Flag bits indicating name compression. */
+#define NS_DEFAULTPORT 53 /* For both TCP and UDP. */
/*
- * Internet nameserver port number
+ * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord()
+ * in synch with it.
*/
-#define NAMESERVER_PORT 53
+typedef enum __ns_sect {
+ ns_s_qd = 0, /* Query: Question. */
+ ns_s_zn = 0, /* Update: Zone. */
+ ns_s_an = 1, /* Query: Answer. */
+ ns_s_pr = 1, /* Update: Prerequisites. */
+ ns_s_ns = 2, /* Query: Name servers. */
+ ns_s_ud = 2, /* Update: Update. */
+ ns_s_ar = 3, /* Query|Update: Additional records. */
+ ns_s_max = 4
+} ns_sect;
/*
- * Currently defined opcodes
+ * This is a message handle. It is caller allocated and has no dynamic data.
+ * This structure is intended to be opaque to all but ns_parse.c, thus the
+ * leading _'s on the member names. Use the accessor functions, not the _'s.
*/
-#define QUERY 0x0 /* standard query */
-#define IQUERY 0x1 /* inverse query */
-#define STATUS 0x2 /* nameserver status query */
-/*#define xxx 0x3*/ /* 0x3 reserved */
-#define NS_NOTIFY_OP 0x4 /* notify secondary of SOA change */
+typedef struct __ns_msg {
+ const u_char *_msg, *_eom;
+ u_int16_t _id, _flags, _counts[ns_s_max];
+ const u_char *_sections[ns_s_max];
+ ns_sect _sect;
+ int _rrnum;
+ const u_char *_ptr;
+} ns_msg;
+
+/* Private data structure - do not use from outside library. */
+struct _ns_flagdata { int mask, shift; };
+extern struct _ns_flagdata _ns_flagdata[];
+
+/* Accessor macros - this is part of the public interface. */
+#define ns_msg_getflag(handle, flag) ( \
+ ((handle)._flags & _ns_flagdata[flag].mask) \
+ >> _ns_flagdata[flag].shift \
+ )
+#define ns_msg_id(handle) ((handle)._id + 0)
+#define ns_msg_base(handle) ((handle)._msg + 0)
+#define ns_msg_end(handle) ((handle)._eom + 0)
+#define ns_msg_size(handle) ((handle)._eom - (handle)._msg)
+#define ns_msg_count(handle, section) ((handle)._counts[section] + 0)
+
/*
- * Currently defined response codes
+ * This is a parsed record. It is caller allocated and has no dynamic data.
*/
-#define NOERROR 0 /* no error */
-#define FORMERR 1 /* format error */
-#define SERVFAIL 2 /* server failure */
-#define NXDOMAIN 3 /* non existent domain */
-#define NOTIMP 4 /* not implemented */
-#define REFUSED 5 /* query refused */
+typedef struct __ns_rr {
+ char name[NS_MAXDNAME];
+ u_int16_t type;
+ u_int16_t rr_class;
+ u_int32_t ttl;
+ u_int16_t rdlength;
+ const u_char * rdata;
+} ns_rr;
+
+/* Accessor macros - this is part of the public interface. */
+#define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".")
+#define ns_rr_type(rr) ((ns_type)((rr).type + 0))
+#define ns_rr_class(rr) ((ns_class)((rr).rr_class + 0))
+#define ns_rr_ttl(rr) ((rr).ttl + 0)
+#define ns_rr_rdlen(rr) ((rr).rdlength + 0)
+#define ns_rr_rdata(rr) ((rr).rdata + 0)
/*
- * Type values for resources and queries
+ * These don't have to be in the same order as in the packet flags word,
+ * and they can even overlap in some cases, but they will need to be kept
+ * in synch with ns_parse.c:ns_flagdata[].
*/
-#define T_A 1 /* host address */
-#define T_NS 2 /* authoritative server */
-#define T_MD 3 /* mail destination */
-#define T_MF 4 /* mail forwarder */
-#define T_CNAME 5 /* canonical name */
-#define T_SOA 6 /* start of authority zone */
-#define T_MB 7 /* mailbox domain name */
-#define T_MG 8 /* mail group member */
-#define T_MR 9 /* mail rename name */
-#define T_NULL 10 /* null resource record */
-#define T_WKS 11 /* well known service */
-#define T_PTR 12 /* domain name pointer */
-#define T_HINFO 13 /* host information */
-#define T_MINFO 14 /* mailbox information */
-#define T_MX 15 /* mail routing information */
-#define T_TXT 16 /* text strings */
-#define T_RP 17 /* responsible person */
-#define T_AFSDB 18 /* AFS cell database */
-#define T_X25 19 /* X_25 calling address */
-#define T_ISDN 20 /* ISDN calling address */
-#define T_RT 21 /* router */
-#define T_NSAP 22 /* NSAP address */
-#define T_NSAP_PTR 23 /* reverse NSAP lookup (deprecated) */
-#define T_SIG 24 /* security signature */
-#define T_KEY 25 /* security key */
-#define T_PX 26 /* X.400 mail mapping */
-#define T_GPOS 27 /* geographical position (withdrawn) */
-#define T_AAAA 28 /* IP6 Address */
-#define T_LOC 29 /* Location Information */
-#define T_NXT 30 /* Next Valid Name in Zone */
-#define T_EID 31 /* Endpoint identifier */
-#define T_NIMLOC 32 /* Nimrod locator */
-#define T_SRV 33 /* Server selection */
-#define T_ATMA 34 /* ATM Address */
-#define T_NAPTR 35 /* Naming Authority PoinTeR */
- /* non standard */
-#define T_UINFO 100 /* user (finger) information */
-#define T_UID 101 /* user ID */
-#define T_GID 102 /* group ID */
-#define T_UNSPEC 103 /* Unspecified format (binary data) */
- /* Query type values which do not appear in resource records */
-#define T_IXFR 251 /* incremental zone transfer */
-#define T_AXFR 252 /* transfer zone of authority */
-#define T_MAILB 253 /* transfer mailbox records */
-#define T_MAILA 254 /* transfer mail agent records */
-#define T_ANY 255 /* wildcard match */
+typedef enum __ns_flag {
+ ns_f_qr, /* Question/Response. */
+ ns_f_opcode, /* Operation code. */
+ ns_f_aa, /* Authoritative Answer. */
+ ns_f_tc, /* Truncation occurred. */
+ ns_f_rd, /* Recursion Desired. */
+ ns_f_ra, /* Recursion Available. */
+ ns_f_z, /* MBZ. */
+ ns_f_ad, /* Authentic Data (DNSSEC). */
+ ns_f_cd, /* Checking Disabled (DNSSEC). */
+ ns_f_rcode, /* Response code. */
+ ns_f_max
+} ns_flag;
/*
- * Values for class field
+ * Currently defined opcodes.
*/
-
-#define C_IN 1 /* the arpa internet */
-#define C_CHAOS 3 /* for chaos net (MIT) */
-#define C_HS 4 /* for Hesiod name server (MIT) (XXX) */
- /* Query class values which do not appear in resource records */
-#define C_ANY 255 /* wildcard match */
+typedef enum __ns_opcode {
+ ns_o_query = 0, /* Standard query. */
+ ns_o_iquery = 1, /* Inverse query (deprecated/unsupported). */
+ ns_o_status = 2, /* Name server status query (unsupported). */
+ /* Opcode 3 is undefined/reserved. */
+ ns_o_notify = 4, /* Zone change notification. */
+ ns_o_update = 5, /* Zone update message. */
+ ns_o_max = 6
+} ns_opcode;
/*
- * Flags field of the KEY RR rdata
+ * Currently defined response codes.
*/
-#define KEYFLAG_TYPEMASK 0xC000 /* Mask for "type" bits */
-#define KEYFLAG_TYPE_AUTH_CONF 0x0000 /* Key usable for both */
-#define KEYFLAG_TYPE_CONF_ONLY 0x8000 /* Key usable for confidentiality */
-#define KEYFLAG_TYPE_AUTH_ONLY 0x4000 /* Key usable for authentication */
-#define KEYFLAG_TYPE_NO_KEY 0xC000 /* No key usable for either; no key */
-/* The type bits can also be interpreted independently, as single bits: */
-#define KEYFLAG_NO_AUTH 0x8000 /* Key not usable for authentication */
-#define KEYFLAG_NO_CONF 0x4000 /* Key not usable for confidentiality */
-
-#define KEYFLAG_EXPERIMENTAL 0x2000 /* Security is *mandatory* if bit=0 */
-#define KEYFLAG_RESERVED3 0x1000 /* reserved - must be zero */
-#define KEYFLAG_RESERVED4 0x0800 /* reserved - must be zero */
-#define KEYFLAG_USERACCOUNT 0x0400 /* key is assoc. with a user acct */
-#define KEYFLAG_ENTITY 0x0200 /* key is assoc. with entity eg host */
-#define KEYFLAG_ZONEKEY 0x0100 /* key is zone key for the zone named */
-#define KEYFLAG_IPSEC 0x0080 /* key is for IPSEC use (host or user)*/
-#define KEYFLAG_EMAIL 0x0040 /* key is for email (MIME security) */
-#define KEYFLAG_RESERVED10 0x0020 /* reserved - must be zero */
-#define KEYFLAG_RESERVED11 0x0010 /* reserved - must be zero */
-#define KEYFLAG_SIGNATORYMASK 0x000F /* key can sign DNS RR's of same name */
-
-#define KEYFLAG_RESERVED_BITMASK ( KEYFLAG_RESERVED3 | \
- KEYFLAG_RESERVED4 | \
- KEYFLAG_RESERVED10| KEYFLAG_RESERVED11)
+typedef enum __ns_rcode {
+ ns_r_noerror = 0, /* No error occurred. */
+ ns_r_formerr = 1, /* Format error. */
+ ns_r_servfail = 2, /* Server failure. */
+ ns_r_nxdomain = 3, /* Name error. */
+ ns_r_notimpl = 4, /* Unimplemented. */
+ ns_r_refused = 5, /* Operation refused. */
+ /* these are for BIND_UPDATE */
+ ns_r_yxdomain = 6, /* Name exists */
+ ns_r_yxrrset = 7, /* RRset exists */
+ ns_r_nxrrset = 8, /* RRset does not exist */
+ ns_r_notauth = 9, /* Not authoritative for zone */
+ ns_r_notzone = 10, /* Zone of record different from zone section */
+ ns_r_max = 11,
+ /* The following are TSIG extended errors */
+ ns_r_badsig = 16,
+ ns_r_badkey = 17,
+ ns_r_badtime = 18
+} ns_rcode;
-/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */
-#define ALGORITHM_MD5RSA 1 /* MD5 with RSA */
-#define ALGORITHM_EXPIRE_ONLY 253 /* No alg, no security */
-#define ALGORITHM_PRIVATE_OID 254 /* Key begins with OID indicating alg */
+/* BIND_UPDATE */
+typedef enum __ns_update_operation {
+ ns_uop_delete = 0,
+ ns_uop_add = 1,
+ ns_uop_max = 2
+} ns_update_operation;
-/* Signatures */
- /* Size of a mod or exp in bits */
-#define MIN_MD5RSA_KEY_PART_BITS 512
-#define MAX_MD5RSA_KEY_PART_BITS 2552
- /* Total of binary mod and exp, bytes */
-#define MAX_MD5RSA_KEY_BYTES ((MAX_MD5RSA_KEY_PART_BITS+7/8)*2+3)
- /* Max length of text sig block */
-#define MAX_KEY_BASE64 (((MAX_MD5RSA_KEY_BYTES+2)/3)*4)
+/*
+ * This structure is used for TSIG authenticated messages
+ */
+struct ns_tsig_key {
+ char name[NS_MAXDNAME], alg[NS_MAXDNAME];
+ unsigned char *data;
+ int len;
+};
+typedef struct ns_tsig_key ns_tsig_key;
/*
- * Status return codes for T_UNSPEC conversion routines
+ * This structure is used for TSIG authenticated TCP messages
*/
-#define CONV_SUCCESS 0
-#define CONV_OVERFLOW (-1)
-#define CONV_BADFMT (-2)
-#define CONV_BADCKSUM (-3)
-#define CONV_BADBUFLEN (-4)
+struct ns_tcp_tsig_state {
+ int counter;
+ struct dst_key *key;
+ void *ctx;
+ unsigned char sig[NS_PACKETSZ];
+ int siglen;
+};
+typedef struct ns_tcp_tsig_state ns_tcp_tsig_state;
-/* glibc always has byte order info in <endian.h> */
-#include <endian.h>
+#define NS_TSIG_FUDGE 300
+#define NS_TSIG_TCP_COUNT 100
+#define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT"
-__BEGIN_DECLS
+#define NS_TSIG_ERROR_NO_TSIG -10
+#define NS_TSIG_ERROR_NO_SPACE -11
+#define NS_TSIG_ERROR_FORMERR -12
/*
- * Structure for query header. The order of the fields is machine- and
- * compiler-dependent, depending on the byte/bit order and the layout
- * of bit fields. We use bit fields only in int variables, as this
- * is all ANSI requires. This requires a somewhat confusing rearrangement.
+ * Currently defined type values for resources and queries.
*/
+typedef enum __ns_type {
+ ns_t_invalid = 0, /* Cookie. */
+ ns_t_a = 1, /* Host address. */
+ ns_t_ns = 2, /* Authoritative server. */
+ ns_t_md = 3, /* Mail destination. */
+ ns_t_mf = 4, /* Mail forwarder. */
+ ns_t_cname = 5, /* Canonical name. */
+ ns_t_soa = 6, /* Start of authority zone. */
+ ns_t_mb = 7, /* Mailbox domain name. */
+ ns_t_mg = 8, /* Mail group member. */
+ ns_t_mr = 9, /* Mail rename name. */
+ ns_t_null = 10, /* Null resource record. */
+ ns_t_wks = 11, /* Well known service. */
+ ns_t_ptr = 12, /* Domain name pointer. */
+ ns_t_hinfo = 13, /* Host information. */
+ ns_t_minfo = 14, /* Mailbox information. */
+ ns_t_mx = 15, /* Mail routing information. */
+ ns_t_txt = 16, /* Text strings. */
+ ns_t_rp = 17, /* Responsible person. */
+ ns_t_afsdb = 18, /* AFS cell database. */
+ ns_t_x25 = 19, /* X_25 calling address. */
+ ns_t_isdn = 20, /* ISDN calling address. */
+ ns_t_rt = 21, /* Router. */
+ ns_t_nsap = 22, /* NSAP address. */
+ ns_t_nsap_ptr = 23, /* Reverse NSAP lookup (deprecated). */
+ ns_t_sig = 24, /* Security signature. */
+ ns_t_key = 25, /* Security key. */
+ ns_t_px = 26, /* X.400 mail mapping. */
+ ns_t_gpos = 27, /* Geographical position (withdrawn). */
+ ns_t_aaaa = 28, /* Ip6 Address. */
+ ns_t_loc = 29, /* Location Information. */
+ ns_t_nxt = 30, /* Next domain (security). */
+ ns_t_eid = 31, /* Endpoint identifier. */
+ ns_t_nimloc = 32, /* Nimrod Locator. */
+ ns_t_srv = 33, /* Server Selection. */
+ ns_t_atma = 34, /* ATM Address */
+ ns_t_naptr = 35, /* Naming Authority PoinTeR */
+ ns_t_kx = 36, /* Key Exchange */
+ ns_t_cert = 37, /* Certification record */
+ ns_t_a6 = 38, /* IPv6 address (deprecates AAAA) */
+ ns_t_dname = 39, /* Non-terminal DNAME (for IPv6) */
+ ns_t_sink = 40, /* Kitchen sink (experimentatl) */
+ ns_t_opt = 41, /* EDNS0 option (meta-RR) */
+ ns_t_tsig = 250, /* Transaction signature. */
+ ns_t_ixfr = 251, /* Incremental zone transfer. */
+ ns_t_axfr = 252, /* Transfer zone of authority. */
+ ns_t_mailb = 253, /* Transfer mailbox records. */
+ ns_t_maila = 254, /* Transfer mail agent records. */
+ ns_t_any = 255, /* Wildcard match. */
+ ns_t_zxfr = 256, /* BIND-specific, nonstandard. */
+ ns_t_max = 65536
+} ns_type;
-typedef struct {
- unsigned id :16; /* query identification number */
-#if BYTE_ORDER == BIG_ENDIAN
- /* fields in third byte */
- unsigned qr: 1; /* response flag */
- unsigned opcode: 4; /* purpose of message */
- unsigned aa: 1; /* authoritative answer */
- unsigned tc: 1; /* truncated message */
- unsigned rd: 1; /* recursion desired */
- /* fields in fourth byte */
- unsigned ra: 1; /* recursion available */
- unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
- unsigned ad: 1; /* authentic data from named */
- unsigned cd: 1; /* checking disabled by resolver */
- unsigned rcode :4; /* response code */
-#endif
-#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
- /* fields in third byte */
- unsigned rd :1; /* recursion desired */
- unsigned tc :1; /* truncated message */
- unsigned aa :1; /* authoritative answer */
- unsigned opcode :4; /* purpose of message */
- unsigned qr :1; /* response flag */
- /* fields in fourth byte */
- unsigned rcode :4; /* response code */
- unsigned cd: 1; /* checking disabled by resolver */
- unsigned ad: 1; /* authentic data from named */
- unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
- unsigned ra :1; /* recursion available */
-#endif
- /* remaining bytes */
- unsigned qdcount :16; /* number of question entries */
- unsigned ancount :16; /* number of answer entries */
- unsigned nscount :16; /* number of authority entries */
- unsigned arcount :16; /* number of resource entries */
-} HEADER;
+/* Exclusively a QTYPE? (not also an RTYPE) */
+#define ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \
+ (t) == ns_t_mailb || (t) == ns_t_maila)
+/* Some kind of meta-RR? (not a QTYPE, but also not an RTYPE) */
+#define ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt)
+/* Exclusively an RTYPE? (not also a QTYPE or a meta-RR) */
+#define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t))
+#define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr)
+#define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \
+ (t) == ns_t_zxfr)
/*
- * Defines for handling compressed domain names
+ * Values for class field
*/
-#define INDIR_MASK 0xc0
+typedef enum __ns_class {
+ ns_c_invalid = 0, /* Cookie. */
+ ns_c_in = 1, /* Internet. */
+ ns_c_2 = 2, /* unallocated/unsupported. */
+ ns_c_chaos = 3, /* MIT Chaos-net. */
+ ns_c_hs = 4, /* MIT Hesiod. */
+ /* Query class values which do not appear in resource records */
+ ns_c_none = 254, /* for prereq. sections in update requests */
+ ns_c_any = 255, /* Wildcard match. */
+ ns_c_max = 65536
+} ns_class;
+
+/* DNSSEC constants. */
+
+typedef enum __ns_key_types {
+ ns_kt_rsa = 1, /* key type RSA/MD5 */
+ ns_kt_dh = 2, /* Diffie Hellman */
+ ns_kt_dsa = 3, /* Digital Signature Standard (MANDATORY) */
+ ns_kt_private = 254 /* Private key type starts with OID */
+} ns_key_types;
+
+typedef enum __ns_cert_types {
+ cert_t_pkix = 1, /* PKIX (X.509v3) */
+ cert_t_spki = 2, /* SPKI */
+ cert_t_pgp = 3, /* PGP */
+ cert_t_url = 253, /* URL private type */
+ cert_t_oid = 254 /* OID private type */
+} ns_cert_types;
+
+/* Flags field of the KEY RR rdata. */
+#define NS_KEY_TYPEMASK 0xC000 /* Mask for "type" bits */
+#define NS_KEY_TYPE_AUTH_CONF 0x0000 /* Key usable for both */
+#define NS_KEY_TYPE_CONF_ONLY 0x8000 /* Key usable for confidentiality */
+#define NS_KEY_TYPE_AUTH_ONLY 0x4000 /* Key usable for authentication */
+#define NS_KEY_TYPE_NO_KEY 0xC000 /* No key usable for either; no key */
+/* The type bits can also be interpreted independently, as single bits: */
+#define NS_KEY_NO_AUTH 0x8000 /* Key unusable for authentication */
+#define NS_KEY_NO_CONF 0x4000 /* Key unusable for confidentiality */
+#define NS_KEY_RESERVED2 0x2000 /* Security is *mandatory* if bit=0 */
+#define NS_KEY_EXTENDED_FLAGS 0x1000 /* reserved - must be zero */
+#define NS_KEY_RESERVED4 0x0800 /* reserved - must be zero */
+#define NS_KEY_RESERVED5 0x0400 /* reserved - must be zero */
+#define NS_KEY_NAME_TYPE 0x0300 /* these bits determine the type */
+#define NS_KEY_NAME_USER 0x0000 /* key is assoc. with user */
+#define NS_KEY_NAME_ENTITY 0x0200 /* key is assoc. with entity eg host */
+#define NS_KEY_NAME_ZONE 0x0100 /* key is zone key */
+#define NS_KEY_NAME_RESERVED 0x0300 /* reserved meaning */
+#define NS_KEY_RESERVED8 0x0080 /* reserved - must be zero */
+#define NS_KEY_RESERVED9 0x0040 /* reserved - must be zero */
+#define NS_KEY_RESERVED10 0x0020 /* reserved - must be zero */
+#define NS_KEY_RESERVED11 0x0010 /* reserved - must be zero */
+#define NS_KEY_SIGNATORYMASK 0x000F /* key can sign RR's of same name */
+#define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \
+ NS_KEY_RESERVED4 | \
+ NS_KEY_RESERVED5 | \
+ NS_KEY_RESERVED8 | \
+ NS_KEY_RESERVED9 | \
+ NS_KEY_RESERVED10 | \
+ NS_KEY_RESERVED11 )
+#define NS_KEY_RESERVED_BITMASK2 0xFFFF /* no bits defined here */
+
+/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */
+#define NS_ALG_MD5RSA 1 /* MD5 with RSA */
+#define NS_ALG_DH 2 /* Diffie Hellman KEY */
+#define NS_ALG_DSA 3 /* DSA KEY */
+#define NS_ALG_DSS NS_ALG_DSA
+#define NS_ALG_EXPIRE_ONLY 253 /* No alg, no security */
+#define NS_ALG_PRIVATE_OID 254 /* Key begins with OID giving alg */
+
+/* Protocol values */
+/* value 0 is reserved */
+#define NS_KEY_PROT_TLS 1
+#define NS_KEY_PROT_EMAIL 2
+#define NS_KEY_PROT_DNSSEC 3
+#define NS_KEY_PROT_IPSEC 4
+#define NS_KEY_PROT_ANY 255
-extern u_int16_t _getshort __P((const u_char *));
-extern u_int32_t _getlong __P((const u_char *));
+/* Signatures */
+#define NS_MD5RSA_MIN_BITS 512 /* Size of a mod or exp in bits */
+#define NS_MD5RSA_MAX_BITS 2552
+ /* Total of binary mod and exp */
+#define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3)
+ /* Max length of text sig block */
+#define NS_MD5RSA_MAX_BASE64 (((NS_MD5RSA_MAX_BYTES+2)/3)*4)
+#define NS_MD5RSA_MIN_SIZE ((NS_MD5RSA_MIN_BITS+7)/8)
+#define NS_MD5RSA_MAX_SIZE ((NS_MD5RSA_MAX_BITS+7)/8)
+
+#define NS_DSA_SIG_SIZE 41
+#define NS_DSA_MIN_SIZE 213
+#define NS_DSA_MAX_BYTES 405
+
+/* Offsets into SIG record rdata to find various values */
+#define NS_SIG_TYPE 0 /* Type flags */
+#define NS_SIG_ALG 2 /* Algorithm */
+#define NS_SIG_LABELS 3 /* How many labels in name */
+#define NS_SIG_OTTL 4 /* Original TTL */
+#define NS_SIG_EXPIR 8 /* Expiration time */
+#define NS_SIG_SIGNED 12 /* Signature time */
+#define NS_SIG_FOOT 16 /* Key footprint */
+#define NS_SIG_SIGNER 18 /* Domain name of who signed it */
+
+/* How RR types are represented as bit-flags in NXT records */
+#define NS_NXT_BITS 8
+#define NS_NXT_BIT_SET( n,p) (p[(n)/NS_NXT_BITS] |= (0x80>>((n)%NS_NXT_BITS)))
+#define NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS)))
+#define NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] & (0x80>>((n)%NS_NXT_BITS)))
+#define NS_NXT_MAX 127
/*
* Inline versions of get/put short/long. Pointer is advanced.
- *
- * These macros demonstrate the property of C whereby it can be
- * portable or it can be elegant but rarely both.
*/
-#define GETSHORT(s, cp) { \
+#define NS_GET16(s, cp) do { \
register u_char *t_cp = (u_char *)(cp); \
(s) = ((u_int16_t)t_cp[0] << 8) \
| ((u_int16_t)t_cp[1]) \
; \
- (cp) += INT16SZ; \
-}
+ (cp) += NS_INT16SZ; \
+} while (0)
-#define GETLONG(l, cp) { \
+#define NS_GET32(l, cp) do { \
register u_char *t_cp = (u_char *)(cp); \
(l) = ((u_int32_t)t_cp[0] << 24) \
| ((u_int32_t)t_cp[1] << 16) \
| ((u_int32_t)t_cp[2] << 8) \
| ((u_int32_t)t_cp[3]) \
; \
- (cp) += INT32SZ; \
-}
+ (cp) += NS_INT32SZ; \
+} while (0)
-#define PUTSHORT(s, cp) { \
+#define NS_PUT16(s, cp) do { \
register u_int16_t t_s = (u_int16_t)(s); \
register u_char *t_cp = (u_char *)(cp); \
*t_cp++ = t_s >> 8; \
*t_cp = t_s; \
- (cp) += INT16SZ; \
-}
+ (cp) += NS_INT16SZ; \
+} while (0)
-#define PUTLONG(l, cp) { \
+#define NS_PUT32(l, cp) do { \
register u_int32_t t_l = (u_int32_t)(l); \
register u_char *t_cp = (u_char *)(cp); \
*t_cp++ = t_l >> 24; \
*t_cp++ = t_l >> 16; \
*t_cp++ = t_l >> 8; \
*t_cp = t_l; \
- (cp) += INT32SZ; \
-}
+ (cp) += NS_INT32SZ; \
+} while (0)
+/*
+ * ANSI C identifier hiding for bind's lib/nameser.
+ */
+#define ns_get16 __ns_get16
+#define ns_get32 __ns_get32
+#define ns_put16 __ns_put16
+#define ns_put32 __ns_put32
+#define ns_initparse __ns_initparse
+#define ns_skiprr __ns_skiprr
+#define ns_parserr __ns_parserr
+#define ns_sprintrr __ns_sprintrr
+#define ns_sprintrrf __ns_sprintrrf
+#define ns_format_ttl __ns_format_ttl
+#define ns_parse_ttl __ns_parse_ttl
+#define ns_datetosecs __ns_datetosecs
+#define ns_name_ntol __ns_name_ntol
+#define ns_name_ntop __ns_name_ntop
+#define ns_name_pton __ns_name_pton
+#define ns_name_unpack __ns_name_unpack
+#define ns_name_pack __ns_name_pack
+#define ns_name_compress __ns_name_compress
+#define ns_name_uncompress __ns_name_uncompress
+#define ns_name_skip __ns_name_skip
+#define ns_sign __ns_sign
+#define ns_sign_tcp __ns_sign_tcp
+#define ns_sign_tcp_init __ns_sign_tcp_init
+#define ns_find_tsig __ns_find_tsig
+#define ns_verify __ns_verify
+#define ns_verify_tcp __ns_verify_tcp
+#define ns_verify_tcp_init __ns_verify_tcp_init
+#define ns_samedomain __ns_samedomain
+#define ns_subdomain __ns_subdomain
+#define ns_makecanon __ns_makecanon
+#define ns_samename __ns_samename
+
+__BEGIN_DECLS
+u_int ns_get16 __P((const u_char *));
+u_long ns_get32 __P((const u_char *));
+void ns_put16 __P((u_int, u_char *));
+void ns_put32 __P((u_long, u_char *));
+int ns_initparse __P((const u_char *, int, ns_msg *));
+int ns_skiprr __P((const u_char *, const u_char *, ns_sect, int));
+int ns_parserr __P((ns_msg *, ns_sect, int, ns_rr *));
+int ns_sprintrr __P((const ns_msg *, const ns_rr *,
+ const char *, const char *, char *, size_t));
+int ns_sprintrrf __P((const u_char *, size_t, const char *,
+ ns_class, ns_type, u_long, const u_char *,
+ size_t, const char *, const char *,
+ char *, size_t));
+int ns_format_ttl __P((u_long, char *, size_t));
+int ns_parse_ttl __P((const char *, u_long *));
+u_int32_t ns_datetosecs __P((const char *cp, int *errp));
+int ns_name_ntol __P((const u_char *, u_char *, size_t));
+int ns_name_ntop __P((const u_char *, char *, size_t));
+int ns_name_pton __P((const char *, u_char *, size_t));
+int ns_name_unpack __P((const u_char *, const u_char *,
+ const u_char *, u_char *, size_t));
+int ns_name_pack __P((const u_char *, u_char *, int,
+ const u_char **, const u_char **));
+int ns_name_uncompress __P((const u_char *, const u_char *,
+ const u_char *, char *, size_t));
+int ns_name_compress __P((const char *, u_char *, size_t,
+ const u_char **, const u_char **));
+int ns_name_skip __P((const u_char **, const u_char *));
+int ns_sign __P((u_char *, int *, int, int, void *,
+ const u_char *, int, u_char *, int *, time_t));
+int ns_sign_tcp __P((u_char *, int *, int, int,
+ ns_tcp_tsig_state *, int));
+int ns_sign_tcp_init __P((void *, const u_char *, int,
+ ns_tcp_tsig_state *));
+u_char *ns_find_tsig __P((u_char *, u_char *));
+int ns_verify __P((u_char *, int *, void *,
+ const u_char *, int, u_char *, int *,
+ time_t *, int));
+int ns_verify_tcp __P((u_char *, int *, ns_tcp_tsig_state *, int));
+int ns_verify_tcp_init __P((void *, const u_char *, int,
+ ns_tcp_tsig_state *));
+int ns_samedomain __P((const char *, const char *));
+int ns_subdomain __P((const char *, const char *));
+int ns_makecanon __P((const char *, char *, size_t));
+int ns_samename __P((const char *, const char *));
__END_DECLS
-#endif /* arpa/nameser.h */
+#ifdef BIND_4_COMPAT
+#include <arpa/nameser_compat.h>
+#endif
+
+#endif /* !_ARPA_NAMESER_H_ */
diff --git a/resolv/arpa/nameser_compat.h b/resolv/arpa/nameser_compat.h
new file mode 100644
index 0000000000..f67f5b3a67
--- /dev/null
+++ b/resolv/arpa/nameser_compat.h
@@ -0,0 +1,184 @@
+/* Copyright (c) 1983, 1989
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * from nameser.h 8.1 (Berkeley) 6/2/93
+ * $Id$
+ */
+
+#ifndef _ARPA_NAMESER_COMPAT_
+#define _ARPA_NAMESER_COMPAT_
+
+#define __BIND 19950621 /* (DEAD) interface version stamp. */
+
+/* glibc always has byte order info in <endian.h> */
+#include <endian.h>
+
+/*
+ * Structure for query header. The order of the fields is machine- and
+ * compiler-dependent, depending on the byte/bit order and the layout
+ * of bit fields. We use bit fields only in int variables, as this
+ * is all ANSI requires. This requires a somewhat confusing rearrangement.
+ */
+
+typedef struct {
+ unsigned id :16; /* query identification number */
+#if BYTE_ORDER == BIG_ENDIAN
+ /* fields in third byte */
+ unsigned qr: 1; /* response flag */
+ unsigned opcode: 4; /* purpose of message */
+ unsigned aa: 1; /* authoritive answer */
+ unsigned tc: 1; /* truncated message */
+ unsigned rd: 1; /* recursion desired */
+ /* fields in fourth byte */
+ unsigned ra: 1; /* recursion available */
+ unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
+ unsigned ad: 1; /* authentic data from named */
+ unsigned cd: 1; /* checking disabled by resolver */
+ unsigned rcode :4; /* response code */
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
+ /* fields in third byte */
+ unsigned rd :1; /* recursion desired */
+ unsigned tc :1; /* truncated message */
+ unsigned aa :1; /* authoritive answer */
+ unsigned opcode :4; /* purpose of message */
+ unsigned qr :1; /* response flag */
+ /* fields in fourth byte */
+ unsigned rcode :4; /* response code */
+ unsigned cd: 1; /* checking disabled by resolver */
+ unsigned ad: 1; /* authentic data from named */
+ unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
+ unsigned ra :1; /* recursion available */
+#endif
+ /* remaining bytes */
+ unsigned qdcount :16; /* number of question entries */
+ unsigned ancount :16; /* number of answer entries */
+ unsigned nscount :16; /* number of authority entries */
+ unsigned arcount :16; /* number of resource entries */
+} HEADER;
+
+#define PACKETSZ NS_PACKETSZ
+#define MAXDNAME NS_MAXDNAME
+#define MAXCDNAME NS_MAXCDNAME
+#define MAXLABEL NS_MAXLABEL
+#define HFIXEDSZ NS_HFIXEDSZ
+#define QFIXEDSZ NS_QFIXEDSZ
+#define RRFIXEDSZ NS_RRFIXEDSZ
+#define INT32SZ NS_INT32SZ
+#define INT16SZ NS_INT16SZ
+#define INADDRSZ NS_INADDRSZ
+#define IN6ADDRSZ NS_IN6ADDRSZ
+#define INDIR_MASK NS_CMPRSFLGS
+#define NAMESERVER_PORT NS_DEFAULTPORT
+
+#define S_ZONE ns_s_zn
+#define S_PREREQ ns_s_pr
+#define S_UPDATE ns_s_ud
+#define S_ADDT ns_s_ar
+
+#define QUERY ns_o_query
+#define IQUERY ns_o_iquery
+#define STATUS ns_o_status
+#define NS_NOTIFY_OP ns_o_notify
+#define NS_UPDATE_OP ns_o_update
+
+#define NOERROR ns_r_noerror
+#define FORMERR ns_r_formerr
+#define SERVFAIL ns_r_servfail
+#define NXDOMAIN ns_r_nxdomain
+#define NOTIMP ns_r_notimpl
+#define REFUSED ns_r_refused
+#define YXDOMAIN ns_r_yxdomain
+#define YXRRSET ns_r_yxrrset
+#define NXRRSET ns_r_nxrrset
+#define NOTAUTH ns_r_notauth
+#define NOTZONE ns_r_notzone
+/*#define BADSIG ns_r_badsig*/
+/*#define BADKEY ns_r_badkey*/
+/*#define BADTIME ns_r_badtime*/
+
+
+#define DELETE ns_uop_delete
+#define ADD ns_uop_add
+
+#define T_A ns_t_a
+#define T_NS ns_t_ns
+#define T_MD ns_t_md
+#define T_MF ns_t_mf
+#define T_CNAME ns_t_cname
+#define T_SOA ns_t_soa
+#define T_MB ns_t_mb
+#define T_MG ns_t_mg
+#define T_MR ns_t_mr
+#define T_NULL ns_t_null
+#define T_WKS ns_t_wks
+#define T_PTR ns_t_ptr
+#define T_HINFO ns_t_hinfo
+#define T_MINFO ns_t_minfo
+#define T_MX ns_t_mx
+#define T_TXT ns_t_txt
+#define T_RP ns_t_rp
+#define T_AFSDB ns_t_afsdb
+#define T_X25 ns_t_x25
+#define T_ISDN ns_t_isdn
+#define T_RT ns_t_rt
+#define T_NSAP ns_t_nsap
+#define T_NSAP_PTR ns_t_nsap_ptr
+#define T_SIG ns_t_sig
+#define T_KEY ns_t_key
+#define T_PX ns_t_px
+#define T_GPOS ns_t_gpos
+#define T_AAAA ns_t_aaaa
+#define T_LOC ns_t_loc
+#define T_NXT ns_t_nxt
+#define T_EID ns_t_eid
+#define T_NIMLOC ns_t_nimloc
+#define T_SRV ns_t_srv
+#define T_ATMA ns_t_atma
+#define T_NAPTR ns_t_naptr
+#define T_TSIG ns_t_tsig
+#define T_IXFR ns_t_ixfr
+#define T_AXFR ns_t_axfr
+#define T_MAILB ns_t_mailb
+#define T_MAILA ns_t_maila
+#define T_ANY ns_t_any
+
+#define C_IN ns_c_in
+#define C_CHAOS ns_c_chaos
+#define C_HS ns_c_hs
+/* BIND_UPDATE */
+#define C_NONE ns_c_none
+#define C_ANY ns_c_any
+
+#define GETSHORT NS_GET16
+#define GETLONG NS_GET32
+#define PUTSHORT NS_PUT16
+#define PUTLONG NS_PUT32
+
+#endif /* _ARPA_NAMESER_COMPAT_ */
diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c
index 7f1b742c4d..5808d92d7b 100644
--- a/resolv/gethnamaddr.c
+++ b/resolv/gethnamaddr.c
@@ -259,11 +259,11 @@ getanswer(answer, anslen, qname, qtype)
}
cp += n; /* name */
BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
- type = _getshort(cp);
+ type = ns_get16(cp);
cp += INT16SZ; /* type */
- class = _getshort(cp);
+ class = ns_get16(cp);
cp += INT16SZ + INT32SZ; /* class, TTL */
- n = _getshort(cp);
+ n = ns_get16(cp);
cp += INT16SZ; /* len */
BOUNDS_CHECK(cp, n);
erdata = cp + n;
@@ -491,7 +491,7 @@ gethostbyname(name)
{
struct hostent *hp;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ if ((_res.options & RES_INIT) == 0 && __res_ninit(&_res) == -1) {
__set_h_errno (NETDB_INTERNAL);
return (NULL);
}
@@ -514,7 +514,7 @@ gethostbyname2(name, af)
int n, size, type, len;
extern struct hostent *_gethtbyname2();
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ if ((_res.options & RES_INIT) == 0 && __res_ninit(&_res) == -1) {
__set_h_errno (NETDB_INTERNAL);
return (NULL);
}
@@ -613,8 +613,8 @@ gethostbyname2(name, af)
break;
}
- if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf.buf))) < 0) {
- dprintf("res_search failed (%d)\n", n);
+ if ((n = res_nsearch(&_res, name, C_IN, type, buf.buf, sizeof(buf.buf))) < 0) {
+ dprintf("res_nsearch failed (%d)\n", n);
if (errno == ECONNREFUSED)
return (_gethtbyname2(name, af));
return (NULL);
@@ -643,7 +643,7 @@ gethostbyaddr(addr, len, af)
#endif /*SUNSECURITY*/
extern struct hostent *_gethtbyaddr();
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ if ((_res.options & RES_INIT) == 0 && __res_ninit(&_res) == -1) {
__set_h_errno (NETDB_INTERNAL);
return (NULL);
}
@@ -693,9 +693,9 @@ gethostbyaddr(addr, len, af)
default:
abort();
}
- n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
+ n = res_nquery(&_res, qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
if (n < 0) {
- dprintf("res_query failed (%d)\n", n);
+ dprintf("res_nquery failed (%d)\n", n);
if (errno == ECONNREFUSED)
return (_gethtbyaddr(addr, len, af));
return (NULL);
diff --git a/resolv/ns_name.c b/resolv/ns_name.c
new file mode 100644
index 0000000000..b75f731c44
--- /dev/null
+++ b/resolv/ns_name.c
@@ -0,0 +1,636 @@
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id$";
+#endif
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+#include <ctype.h>
+
+/* Data. */
+
+static const char digits[] = "0123456789";
+
+/* Forward. */
+
+static int special(int);
+static int printable(int);
+static int dn_find(const u_char *, const u_char *,
+ const u_char * const *,
+ const u_char * const *);
+
+/* Public. */
+
+/*
+ * ns_name_ntop(src, dst, dstsiz)
+ * Convert an encoded domain name to printable ascii as per RFC1035.
+ * return:
+ * Number of bytes written to buffer, or -1 (with errno set)
+ * notes:
+ * The root is returned as "."
+ * All other domains are returned in non absolute form
+ */
+int
+ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) {
+ const u_char *cp;
+ char *dn, *eom;
+ u_char c;
+ u_int n;
+
+ cp = src;
+ dn = dst;
+ eom = dst + dstsiz;
+
+ while ((n = *cp++) != 0) {
+ if ((n & NS_CMPRSFLGS) != 0) {
+ /* Some kind of compression pointer. */
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ if (dn != dst) {
+ if (dn >= eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ *dn++ = '.';
+ }
+ if (dn + n >= eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ for ((void)NULL; n > 0; n--) {
+ c = *cp++;
+ if (special(c)) {
+ if (dn + 1 >= eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ *dn++ = '\\';
+ *dn++ = (char)c;
+ } else if (!printable(c)) {
+ if (dn + 3 >= eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ *dn++ = '\\';
+ *dn++ = digits[c / 100];
+ *dn++ = digits[(c % 100) / 10];
+ *dn++ = digits[c % 10];
+ } else {
+ if (dn >= eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ *dn++ = (char)c;
+ }
+ }
+ }
+ if (dn == dst) {
+ if (dn >= eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ *dn++ = '.';
+ }
+ if (dn >= eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ *dn++ = '\0';
+ return (dn - dst);
+}
+
+/*
+ * ns_name_pton(src, dst, dstsiz)
+ * Convert a ascii string into an encoded domain name as per RFC1035.
+ * return:
+ * -1 if it fails
+ * 1 if string was fully qualified
+ * 0 is string was not fully qualified
+ * notes:
+ * Enforces label and domain length limits.
+ */
+
+int
+ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
+ u_char *label, *bp, *eom;
+ int c, n, escaped;
+ char *cp;
+
+ escaped = 0;
+ bp = dst;
+ eom = dst + dstsiz;
+ label = bp++;
+
+ while ((c = *src++) != 0) {
+ if (escaped) {
+ if ((cp = strchr(digits, c)) != NULL) {
+ n = (cp - digits) * 100;
+ if ((c = *src++) == 0 ||
+ (cp = strchr(digits, c)) == NULL) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ n += (cp - digits) * 10;
+ if ((c = *src++) == 0 ||
+ (cp = strchr(digits, c)) == NULL) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ n += (cp - digits);
+ if (n > 255) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ c = n;
+ }
+ escaped = 0;
+ } else if (c == '\\') {
+ escaped = 1;
+ continue;
+ } else if (c == '.') {
+ c = (bp - label - 1);
+ if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ if (label >= eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ *label = c;
+ /* Fully qualified ? */
+ if (*src == '\0') {
+ if (c != 0) {
+ if (bp >= eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ *bp++ = '\0';
+ }
+ if ((bp - dst) > MAXCDNAME) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ return (1);
+ }
+ if (c == 0 || *src == '.') {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ label = bp++;
+ continue;
+ }
+ if (bp >= eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ *bp++ = (u_char)c;
+ }
+ c = (bp - label - 1);
+ if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ if (label >= eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ *label = c;
+ if (c != 0) {
+ if (bp >= eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ *bp++ = 0;
+ }
+ if ((bp - dst) > MAXCDNAME) { /* src too big */
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * ns_name_ntol(src, dst, dstsiz)
+ * Convert a network strings labels into all lowercase.
+ * return:
+ * Number of bytes written to buffer, or -1 (with errno set)
+ * notes:
+ * Enforces label and domain length limits.
+ */
+
+int
+ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) {
+ const u_char *cp;
+ u_char *dn, *eom;
+ u_char c;
+ u_int n;
+
+ cp = src;
+ dn = dst;
+ eom = dst + dstsiz;
+
+ while ((n = *cp++) != 0) {
+ if ((n & NS_CMPRSFLGS) != 0) {
+ /* Some kind of compression pointer. */
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ *dn++ = n;
+ if (dn + n >= eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ for ((void)NULL; n > 0; n--) {
+ c = *cp++;
+ if (isupper(c))
+ *dn++ = tolower(c);
+ else
+ *dn++ = c;
+ }
+ }
+ *dn++ = '\0';
+ return (dn - dst);
+}
+
+/*
+ * ns_name_unpack(msg, eom, src, dst, dstsiz)
+ * Unpack a domain name from a message, source may be compressed.
+ * return:
+ * -1 if it fails, or consumed octets if it succeeds.
+ */
+int
+ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
+ u_char *dst, size_t dstsiz)
+{
+ const u_char *srcp, *dstlim;
+ u_char *dstp;
+ int n, len, checked;
+
+ len = -1;
+ checked = 0;
+ dstp = dst;
+ srcp = src;
+ dstlim = dst + dstsiz;
+ if (srcp < msg || srcp >= eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ /* Fetch next label in domain name. */
+ while ((n = *srcp++) != 0) {
+ /* Check for indirection. */
+ switch (n & NS_CMPRSFLGS) {
+ case 0:
+ /* Limit checks. */
+ if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ checked += n + 1;
+ *dstp++ = n;
+ memcpy(dstp, srcp, n);
+ dstp += n;
+ srcp += n;
+ break;
+
+ case NS_CMPRSFLGS:
+ if (srcp >= eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ if (len < 0)
+ len = srcp - src + 1;
+ srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
+ if (srcp < msg || srcp >= eom) { /* Out of range. */
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ checked += 2;
+ /*
+ * Check for loops in the compressed name;
+ * if we've looked at the whole message,
+ * there must be a loop.
+ */
+ if (checked >= eom - msg) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ break;
+
+ default:
+ __set_errno (EMSGSIZE);
+ return (-1); /* flag error */
+ }
+ }
+ *dstp = '\0';
+ if (len < 0)
+ len = srcp - src;
+ return (len);
+}
+
+/*
+ * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
+ * Pack domain name 'domain' into 'comp_dn'.
+ * return:
+ * Size of the compressed name, or -1.
+ * notes:
+ * 'dnptrs' is an array of pointers to previous compressed names.
+ * dnptrs[0] is a pointer to the beginning of the message. The array
+ * ends with NULL.
+ * 'lastdnptr' is a pointer to the end of the array pointed to
+ * by 'dnptrs'.
+ * Side effects:
+ * The list of pointers in dnptrs is updated for labels inserted into
+ * the message as we compress the name. If 'dnptr' is NULL, we don't
+ * try to compress names. If 'lastdnptr' is NULL, we don't update the
+ * list.
+ */
+int
+ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
+ const u_char **dnptrs, const u_char **lastdnptr)
+{
+ u_char *dstp;
+ const u_char **cpp, **lpp, *eob, *msg;
+ const u_char *srcp;
+ int n, l;
+
+ srcp = src;
+ dstp = dst;
+ eob = dstp + dstsiz;
+ lpp = cpp = NULL;
+ if (dnptrs != NULL) {
+ if ((msg = *dnptrs++) != NULL) {
+ for (cpp = dnptrs; *cpp != NULL; cpp++)
+ (void)NULL;
+ lpp = cpp; /* end of list to search */
+ }
+ } else
+ msg = NULL;
+
+ /* make sure the domain we are about to add is legal */
+ l = 0;
+ do {
+ n = *srcp;
+ if ((n & NS_CMPRSFLGS) != 0) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ l += n + 1;
+ if (l > MAXCDNAME) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ srcp += n + 1;
+ } while (n != 0);
+
+ /* from here on we need to reset compression pointer array on error */
+ srcp = src;
+ do {
+ /* Look to see if we can use pointers. */
+ n = *srcp;
+ if (n != 0 && msg != NULL) {
+ l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
+ (const u_char * const *)lpp);
+ if (l >= 0) {
+ if (dstp + 1 >= eob) {
+ goto cleanup;
+ }
+ *dstp++ = (l >> 8) | NS_CMPRSFLGS;
+ *dstp++ = l % 256;
+ return (dstp - dst);
+ }
+ /* Not found, save it. */
+ if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
+ (dstp - msg) < 0x4000) {
+ *cpp++ = dstp;
+ *cpp = NULL;
+ }
+ }
+ /* copy label to buffer */
+ if (n & NS_CMPRSFLGS) { /* Should not happen. */
+ goto cleanup;
+ }
+ if (dstp + 1 + n >= eob) {
+ goto cleanup;
+ }
+ memcpy(dstp, srcp, n + 1);
+ srcp += n + 1;
+ dstp += n + 1;
+ } while (n != 0);
+
+ if (dstp > eob) {
+cleanup:
+ if (msg != NULL)
+ *lpp = NULL;
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ return (dstp - dst);
+}
+
+/*
+ * ns_name_uncompress(msg, eom, src, dst, dstsiz)
+ * Expand compressed domain name to presentation format.
+ * return:
+ * Number of bytes read out of `src', or -1 (with errno set).
+ * note:
+ * Root domain returns as "." not "".
+ */
+int
+ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
+ char *dst, size_t dstsiz)
+{
+ u_char tmp[NS_MAXCDNAME];
+ int n;
+
+ if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
+ return (-1);
+ if (ns_name_ntop(tmp, dst, dstsiz) == -1)
+ return (-1);
+ return (n);
+}
+
+/*
+ * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
+ * Compress a domain name into wire format, using compression pointers.
+ * return:
+ * Number of bytes consumed in `dst' or -1 (with errno set).
+ * notes:
+ * 'dnptrs' is an array of pointers to previous compressed names.
+ * dnptrs[0] is a pointer to the beginning of the message.
+ * The list ends with NULL. 'lastdnptr' is a pointer to the end of the
+ * array pointed to by 'dnptrs'. Side effect is to update the list of
+ * pointers for labels inserted into the message as we compress the name.
+ * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
+ * is NULL, we don't update the list.
+ */
+int
+ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
+ const u_char **dnptrs, const u_char **lastdnptr)
+{
+ u_char tmp[NS_MAXCDNAME];
+
+ if (ns_name_pton(src, tmp, sizeof tmp) == -1)
+ return (-1);
+ return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
+}
+
+/*
+ * ns_name_skip(ptrptr, eom)
+ * Advance *ptrptr to skip over the compressed name it points at.
+ * return:
+ * 0 on success, -1 (with errno set) on failure.
+ */
+int
+ns_name_skip(const u_char **ptrptr, const u_char *eom) {
+ const u_char *cp;
+ u_int n;
+
+ cp = *ptrptr;
+ while (cp < eom && (n = *cp++) != 0) {
+ /* Check for indirection. */
+ switch (n & NS_CMPRSFLGS) {
+ case 0: /* normal case, n == len */
+ cp += n;
+ continue;
+ case NS_CMPRSFLGS: /* indirection */
+ cp++;
+ break;
+ default: /* illegal type */
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ break;
+ }
+ if (cp > eom) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ *ptrptr = cp;
+ return (0);
+}
+
+/* Private. */
+
+/*
+ * special(ch)
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * is this characted special ("in need of quoting") ?
+ * return:
+ * boolean.
+ */
+static int
+special(int ch) {
+ switch (ch) {
+ case 0x22: /* '"' */
+ case 0x2E: /* '.' */
+ case 0x3B: /* ';' */
+ case 0x5C: /* '\\' */
+ /* Special modifiers in zone files. */
+ case 0x40: /* '@' */
+ case 0x24: /* '$' */
+ return (1);
+ default:
+ return (0);
+ }
+}
+
+/*
+ * printable(ch)
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * is this character visible and not a space when printed ?
+ * return:
+ * boolean.
+ */
+static int
+printable(int ch) {
+ return (ch > 0x20 && ch < 0x7f);
+}
+
+/*
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * convert this character to lower case if it's upper case.
+ */
+static int
+mklower(int ch) {
+ if (ch >= 0x41 && ch <= 0x5A)
+ return (ch + 0x20);
+ return (ch);
+}
+
+/*
+ * dn_find(domain, msg, dnptrs, lastdnptr)
+ * Search for the counted-label name in an array of compressed names.
+ * return:
+ * offset from msg if found, or -1.
+ * notes:
+ * dnptrs is the pointer to the first name on the list,
+ * not the pointer to the start of the message.
+ */
+static int
+dn_find(const u_char *domain, const u_char *msg,
+ const u_char * const *dnptrs,
+ const u_char * const *lastdnptr)
+{
+ const u_char *dn, *cp, *sp;
+ const u_char * const *cpp;
+ u_int n;
+
+ for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
+ dn = domain;
+ sp = cp = *cpp;
+ while ((n = *cp++) != 0) {
+ /*
+ * check for indirection
+ */
+ switch (n & NS_CMPRSFLGS) {
+ case 0: /* normal case, n == len */
+ if (n != *dn++)
+ goto next;
+ for ((void)NULL; n > 0; n--)
+ if (mklower(*dn++) != mklower(*cp++))
+ goto next;
+ /* Is next root for both ? */
+ if (*dn == '\0' && *cp == '\0')
+ return (sp - msg);
+ if (*dn)
+ continue;
+ goto next;
+
+ case NS_CMPRSFLGS: /* indirection */
+ cp = msg + (((n & 0x3f) << 8) | *cp);
+ break;
+
+ default: /* illegal type */
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ }
+ next: ;
+ }
+ __set_errno (ENOENT);
+ return (-1);
+}
diff --git a/resolv/ns_netint.c b/resolv/ns_netint.c
new file mode 100644
index 0000000000..9dcf91cf50
--- /dev/null
+++ b/resolv/ns_netint.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id$";
+#endif
+
+/* Import. */
+
+#include <arpa/nameser.h>
+
+/* Public. */
+
+u_int
+ns_get16(const u_char *src) {
+ u_int dst;
+
+ NS_GET16(dst, src);
+ return (dst);
+}
+
+u_long
+ns_get32(const u_char *src) {
+ u_long dst;
+
+ NS_GET32(dst, src);
+ return (dst);
+}
+
+void
+ns_put16(u_int src, u_char *dst) {
+ NS_PUT16(src, dst);
+}
+
+void
+ns_put32(u_long src, u_char *dst) {
+ NS_PUT32(src, dst);
+}
diff --git a/resolv/ns_parse.c b/resolv/ns_parse.c
new file mode 100644
index 0000000000..7bbdc41cdf
--- /dev/null
+++ b/resolv/ns_parse.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id$";
+#endif
+
+/* Import. */
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+
+/* Forward. */
+
+static void setsection(ns_msg *msg, ns_sect sect);
+
+/* Macros. */
+
+#define RETERR(err) do { __set_errno (err); return (-1); } while (0)
+
+/* Public. */
+
+/* These need to be in the same order as the nres.h:ns_flag enum. */
+struct _ns_flagdata _ns_flagdata[16] = {
+ { 0x8000, 15 }, /* qr. */
+ { 0x7800, 11 }, /* opcode. */
+ { 0x0400, 10 }, /* aa. */
+ { 0x0200, 9 }, /* tc. */
+ { 0x0100, 8 }, /* rd. */
+ { 0x0080, 7 }, /* ra. */
+ { 0x0040, 6 }, /* z. */
+ { 0x0020, 5 }, /* ad. */
+ { 0x0010, 4 }, /* cd. */
+ { 0x000f, 0 }, /* rcode. */
+ { 0x0000, 0 }, /* expansion (1/6). */
+ { 0x0000, 0 }, /* expansion (2/6). */
+ { 0x0000, 0 }, /* expansion (3/6). */
+ { 0x0000, 0 }, /* expansion (4/6). */
+ { 0x0000, 0 }, /* expansion (5/6). */
+ { 0x0000, 0 }, /* expansion (6/6). */
+};
+
+int
+ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) {
+ const u_char *optr = ptr;
+
+ for ((void)NULL; count > 0; count--) {
+ int b, rdlength;
+
+ b = dn_skipname(ptr, eom);
+ if (b < 0)
+ RETERR(EMSGSIZE);
+ ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/;
+ if (section != ns_s_qd) {
+ if (ptr + NS_INT32SZ + NS_INT16SZ > eom)
+ RETERR(EMSGSIZE);
+ ptr += NS_INT32SZ/*TTL*/;
+ NS_GET16(rdlength, ptr);
+ ptr += rdlength/*RData*/;
+ }
+ }
+ if (ptr > eom)
+ RETERR(EMSGSIZE);
+ return (ptr - optr);
+}
+
+int
+ns_initparse(const u_char *msg, int msglen, ns_msg *handle) {
+ const u_char *eom = msg + msglen;
+ int i;
+
+ memset(handle, 0x5e, sizeof *handle);
+ handle->_msg = msg;
+ handle->_eom = eom;
+ if (msg + NS_INT16SZ > eom)
+ RETERR(EMSGSIZE);
+ NS_GET16(handle->_id, msg);
+ if (msg + NS_INT16SZ > eom)
+ RETERR(EMSGSIZE);
+ NS_GET16(handle->_flags, msg);
+ for (i = 0; i < ns_s_max; i++) {
+ if (msg + NS_INT16SZ > eom)
+ RETERR(EMSGSIZE);
+ NS_GET16(handle->_counts[i], msg);
+ }
+ for (i = 0; i < ns_s_max; i++)
+ if (handle->_counts[i] == 0)
+ handle->_sections[i] = NULL;
+ else {
+ int b = ns_skiprr(msg, eom, (ns_sect)i,
+ handle->_counts[i]);
+
+ if (b < 0)
+ return (-1);
+ handle->_sections[i] = msg;
+ msg += b;
+ }
+ if (msg != eom)
+ RETERR(EMSGSIZE);
+ setsection(handle, ns_s_max);
+ return (0);
+}
+
+int
+ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
+ int b;
+
+ /* Make section right. */
+ if (section < 0 || section >= ns_s_max)
+ RETERR(ENODEV);
+ if (section != handle->_sect)
+ setsection(handle, section);
+
+ /* Make rrnum right. */
+ if (rrnum == -1)
+ rrnum = handle->_rrnum;
+ if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
+ RETERR(ENODEV);
+ if (rrnum < handle->_rrnum)
+ setsection(handle, section);
+ if (rrnum > handle->_rrnum) {
+ b = ns_skiprr(handle->_ptr, handle->_eom, section,
+ rrnum - handle->_rrnum);
+
+ if (b < 0)
+ return (-1);
+ handle->_ptr += b;
+ handle->_rrnum = rrnum;
+ }
+
+ /* Do the parse. */
+ b = dn_expand(handle->_msg, handle->_eom,
+ handle->_ptr, rr->name, NS_MAXDNAME);
+ if (b < 0)
+ return (-1);
+ handle->_ptr += b;
+ if (handle->_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
+ RETERR(EMSGSIZE);
+ NS_GET16(rr->type, handle->_ptr);
+ NS_GET16(rr->rr_class, handle->_ptr);
+ if (section == ns_s_qd) {
+ rr->ttl = 0;
+ rr->rdlength = 0;
+ rr->rdata = NULL;
+ } else {
+ if (handle->_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
+ RETERR(EMSGSIZE);
+ NS_GET32(rr->ttl, handle->_ptr);
+ NS_GET16(rr->rdlength, handle->_ptr);
+ if (handle->_ptr + rr->rdlength > handle->_eom)
+ RETERR(EMSGSIZE);
+ rr->rdata = handle->_ptr;
+ handle->_ptr += rr->rdlength;
+ }
+ if (++handle->_rrnum > handle->_counts[(int)section])
+ setsection(handle, (ns_sect)((int)section + 1));
+
+ /* All done. */
+ return (0);
+}
+
+/* Private. */
+
+static void
+setsection(ns_msg *msg, ns_sect sect) {
+ msg->_sect = sect;
+ if (sect == ns_s_max) {
+ msg->_rrnum = -1;
+ msg->_ptr = NULL;
+ } else {
+ msg->_rrnum = 0;
+ msg->_ptr = msg->_sections[(int)sect];
+ }
+}
diff --git a/resolv/ns_print.c b/resolv/ns_print.c
new file mode 100644
index 0000000000..cce3fb611d
--- /dev/null
+++ b/resolv/ns_print.c
@@ -0,0 +1,818 @@
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id$";
+#endif
+
+/* Import. */
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/* Forward. */
+
+static size_t prune_origin(const char *name, const char *origin);
+static int charstr(const u_char *rdata, const u_char *edata,
+ char **buf, size_t *buflen);
+static int addname(const u_char *msg, size_t msglen,
+ const u_char **p, const char *origin,
+ char **buf, size_t *buflen);
+static void addlen(size_t len, char **buf, size_t *buflen);
+static int addstr(const char *src, size_t len,
+ char **buf, size_t *buflen);
+static int addtab(size_t len, size_t target, int spaced,
+ char **buf, size_t *buflen);
+
+/* Proto. */
+#ifndef _LIBC
+u_int16_t dst_s_dns_key_id(const u_char *, const int);
+#endif
+
+/* Macros. */
+
+#define T(x) \
+ do { \
+ if ((x) < 0) \
+ return (-1); \
+ } while (0)
+
+/* Public. */
+
+/*
+ * int
+ * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen)
+ * Convert an RR to presentation format.
+ * return:
+ * Number of characters written to buf, or -1 (check errno).
+ */
+int
+ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
+ const char *name_ctx, const char *origin,
+ char *buf, size_t buflen)
+{
+ int n;
+
+ n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
+ ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
+ ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
+ name_ctx, origin, buf, buflen);
+ return (n);
+}
+
+/*
+ * int
+ * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen,
+ * name_ctx, origin, buf, buflen)
+ * Convert the fields of an RR into presentation format.
+ * return:
+ * Number of characters written to buf, or -1 (check errno).
+ */
+int
+ns_sprintrrf(const u_char *msg, size_t msglen,
+ const char *name, ns_class class, ns_type type,
+ u_long ttl, const u_char *rdata, size_t rdlen,
+ const char *name_ctx, const char *origin,
+ char *buf, size_t buflen)
+{
+ const char *obuf = buf;
+ const u_char *edata = rdata + rdlen;
+ int spaced = 0;
+
+ const char *comment;
+ char tmp[100];
+ int len, x;
+
+ /*
+ * Owner.
+ */
+ if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
+ T(addstr("\t\t\t", 3, &buf, &buflen));
+ } else {
+ len = prune_origin(name, origin);
+ if (len == 0) {
+ T(addstr("@\t\t\t", 4, &buf, &buflen));
+ } else {
+ T(addstr(name, len, &buf, &buflen));
+ /* Origin not used and no trailing dot? */
+ if ((!origin || !origin[0] || name[len] == '\0') &&
+ name[len - 1] != '.') {
+ T(addstr(".", 1, &buf, &buflen));
+ len++;
+ }
+ T(spaced = addtab(len, 24, spaced, &buf, &buflen));
+ }
+ }
+
+ /*
+ * TTL, Class, Type.
+ */
+ T(x = ns_format_ttl(ttl, buf, buflen));
+ addlen(x, &buf, &buflen);
+ len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
+ T(addstr(tmp, len, &buf, &buflen));
+ T(spaced = addtab(x + len, 16, spaced, &buf, &buflen));
+
+ /*
+ * RData.
+ */
+ switch (type) {
+ case ns_t_a:
+ if (rdlen != NS_INADDRSZ)
+ goto formerr;
+ (void) inet_ntop(AF_INET, rdata, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ break;
+
+ case ns_t_cname:
+ case ns_t_mb:
+ case ns_t_mg:
+ case ns_t_mr:
+ case ns_t_ns:
+ case ns_t_ptr:
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+
+ case ns_t_hinfo:
+ case ns_t_isdn:
+ /* First word. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+
+ /* Second word, optional in ISDN records. */
+ if (type == ns_t_isdn && rdata == edata)
+ break;
+
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ break;
+
+ case ns_t_soa: {
+ u_long t;
+
+ /* Server name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Administrator name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" (\n", 3, &buf, &buflen));
+ spaced = 0;
+
+ if ((edata - rdata) != 5*NS_INT32SZ)
+ goto formerr;
+
+ /* Serial number. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ len = SPRINTF((tmp, "%lu", t));
+ T(addstr(tmp, len, &buf, &buflen));
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; serial\n", 9, &buf, &buflen));
+ spaced = 0;
+
+ /* Refresh interval. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; refresh\n", 10, &buf, &buflen));
+ spaced = 0;
+
+ /* Retry interval. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; retry\n", 8, &buf, &buflen));
+ spaced = 0;
+
+ /* Expiry. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; expiry\n", 9, &buf, &buflen));
+ spaced = 0;
+
+ /* Minimum TTL. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(addstr(" )", 2, &buf, &buflen));
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; minimum\n", 10, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_mx:
+ case ns_t_afsdb:
+ case ns_t_rt: {
+ u_int t;
+
+ if (rdlen < NS_INT16SZ)
+ goto formerr;
+
+ /* Priority. */
+ t = ns_get16(rdata);
+ rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", t));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Target. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_px: {
+ u_int t;
+
+ if (rdlen < NS_INT16SZ)
+ goto formerr;
+
+ /* Priority. */
+ t = ns_get16(rdata);
+ rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", t));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Name1. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Name2. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_x25:
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ break;
+
+ case ns_t_txt:
+ while (rdata < edata) {
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ if (rdata < edata)
+ T(addstr(" ", 1, &buf, &buflen));
+ }
+ break;
+
+ case ns_t_nsap: {
+ char t[255*3];
+
+ (void) inet_nsap_ntoa(rdlen, rdata, t);
+ T(addstr(t, strlen(t), &buf, &buflen));
+ break;
+ }
+
+ case ns_t_aaaa:
+ if (rdlen != NS_IN6ADDRSZ)
+ goto formerr;
+ (void) inet_ntop(AF_INET6, rdata, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ break;
+
+ case ns_t_loc: {
+ char t[255];
+
+ /* XXX protocol format checking? */
+ (void) loc_ntoa(rdata, t);
+ T(addstr(t, strlen(t), &buf, &buflen));
+ break;
+ }
+
+ case ns_t_naptr: {
+ u_int order, preference;
+ char t[50];
+
+ if (rdlen < 2*NS_INT16SZ)
+ goto formerr;
+
+ /* Order, Precedence. */
+ order = ns_get16(rdata); rdata += NS_INT16SZ;
+ preference = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((t, "%u %u ", order, preference));
+ T(addstr(t, len, &buf, &buflen));
+
+ /* Flags. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Service. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Regexp. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len < 0)
+ return (-1);
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Server. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+ }
+
+ case ns_t_srv: {
+ u_int priority, weight, port;
+ char t[50];
+
+ if (rdlen < NS_INT16SZ*3)
+ goto formerr;
+
+ /* Priority, Weight, Port. */
+ priority = ns_get16(rdata); rdata += NS_INT16SZ;
+ weight = ns_get16(rdata); rdata += NS_INT16SZ;
+ port = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((t, "%u %u %u ", priority, weight, port));
+ T(addstr(t, len, &buf, &buflen));
+
+ /* Server. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+ }
+
+ case ns_t_minfo:
+ case ns_t_rp:
+ /* Name1. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Name2. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+
+ case ns_t_wks: {
+ int n, lcnt;
+
+ if (rdlen < NS_INT32SZ + 1)
+ goto formerr;
+
+ /* Address. */
+ (void) inet_ntop(AF_INET, rdata, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ rdata += NS_INADDRSZ;
+
+ /* Protocol. */
+ len = SPRINTF((tmp, " %u ( ", *rdata));
+ T(addstr(tmp, len, &buf, &buflen));
+ rdata += NS_INT8SZ;
+
+ /* Bit map. */
+ n = 0;
+ lcnt = 0;
+ while (rdata < edata) {
+ u_int c = *rdata++;
+ do {
+ if (c & 0200) {
+ if (lcnt == 0) {
+ T(addstr("\n\t\t\t\t", 5,
+ &buf, &buflen));
+ lcnt = 10;
+ spaced = 0;
+ }
+ len = SPRINTF((tmp, "%d ", n));
+ T(addstr(tmp, len, &buf, &buflen));
+ lcnt--;
+ }
+ c <<= 1;
+ } while (++n & 07);
+ }
+ T(addstr(")", 1, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_key: {
+#ifndef _LIBC
+ char base64_key[NS_MD5RSA_MAX_BASE64];
+ u_int keyflags, protocol, algorithm, key_id;
+ const char *leader;
+ int n;
+
+ if (rdlen < NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
+ goto formerr;
+
+ /* Key flags, Protocol, Algorithm. */
+ key_id = dst_s_dns_key_id(rdata, edata-rdata);
+ keyflags = ns_get16(rdata); rdata += NS_INT16SZ;
+ protocol = *rdata++;
+ algorithm = *rdata++;
+ len = SPRINTF((tmp, "0x%04x %u %u",
+ keyflags, protocol, algorithm));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Public key data. */
+ len = b64_ntop(rdata, edata - rdata,
+ base64_key, sizeof base64_key);
+ if (len < 0)
+ goto formerr;
+ if (len > 15) {
+ T(addstr(" (", 2, &buf, &buflen));
+ leader = "\n\t\t";
+ spaced = 0;
+ } else
+ leader = " ";
+ for (n = 0; n < len; n += 48) {
+ T(addstr(leader, strlen(leader), &buf, &buflen));
+ T(addstr(base64_key + n, MIN(len - n, 48),
+ &buf, &buflen));
+ }
+ if (len > 15)
+ T(addstr(" )", 2, &buf, &buflen));
+ n = SPRINTF((tmp, " ; key_tag= %u", key_id));
+ T(addstr(tmp, n, &buf, &buflen));
+#endif /* !_LIBC */
+ break;
+ }
+
+ case ns_t_sig: {
+#ifndef _LIBC
+ char base64_key[NS_MD5RSA_MAX_BASE64];
+ u_int type, algorithm, labels, footprint;
+ const char *leader;
+ u_long t;
+ int n;
+
+ if (rdlen < 22)
+ goto formerr;
+
+ /* Type covered, Algorithm, Label count, Original TTL. */
+ type = ns_get16(rdata); rdata += NS_INT16SZ;
+ algorithm = *rdata++;
+ labels = *rdata++;
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s %d %d %lu ",
+ p_type(type), algorithm, labels, t));
+ T(addstr(tmp, len, &buf, &buflen));
+ if (labels > (u_int)dn_count_labels(name))
+ goto formerr;
+
+ /* Signature expiry. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Time signed. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Signature Footprint. */
+ footprint = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", footprint));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Signer's name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ /* Signature. */
+ len = b64_ntop(rdata, edata - rdata,
+ base64_key, sizeof base64_key);
+ if (len > 15) {
+ T(addstr(" (", 2, &buf, &buflen));
+ leader = "\n\t\t";
+ spaced = 0;
+ } else
+ leader = " ";
+ if (len < 0)
+ goto formerr;
+ for (n = 0; n < len; n += 48) {
+ T(addstr(leader, strlen(leader), &buf, &buflen));
+ T(addstr(base64_key + n, MIN(len - n, 48),
+ &buf, &buflen));
+ }
+ if (len > 15)
+ T(addstr(" )", 2, &buf, &buflen));
+#endif /* !_LIBC */
+ break;
+ }
+
+ case ns_t_nxt: {
+ int n, c;
+
+ /* Next domain name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ /* Type bit map. */
+ n = edata - rdata;
+ for (c = 0; c < n*8; c++)
+ if (NS_NXT_BIT_ISSET(c, rdata)) {
+ len = SPRINTF((tmp, " %s", p_type(c)));
+ T(addstr(tmp, len, &buf, &buflen));
+ }
+ break;
+ }
+
+ case ns_t_cert: {
+ u_int c_type, key_tag, alg;
+ int n, siz;
+ char base64_cert[8192], *leader, tmp[40];
+
+ c_type = ns_get16(rdata); rdata += NS_INT16SZ;
+ key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
+ alg = (u_int) *rdata++;
+
+ len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg));
+ T(addstr(tmp, len, &buf, &buflen));
+ siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
+ if (siz > sizeof(base64_cert) * 3/4) {
+ char *str = "record too long to print";
+ T(addstr(str, strlen(str), &buf, &buflen));
+ }
+ else {
+ len = b64_ntop(rdata, edata-rdata, base64_cert, siz);
+
+ if (len < 0)
+ goto formerr;
+ else if (len > 15) {
+ T(addstr(" (", 2, &buf, &buflen));
+ leader = "\n\t\t";
+ spaced = 0;
+ }
+ else
+ leader = " ";
+
+ for (n = 0; n < len; n += 48) {
+ T(addstr(leader, strlen(leader),
+ &buf, &buflen));
+ T(addstr(base64_cert + n, MIN(len - n, 48),
+ &buf, &buflen));
+ }
+ if (len > 15)
+ T(addstr(" )", 2, &buf, &buflen));
+ }
+ break;
+ }
+
+ case ns_t_tsig: {
+ /* BEW - need to complete this */
+ int n;
+
+ T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+ rdata += 8; /* time */
+ n = ns_get16(rdata); rdata += INT16SZ;
+ rdata += n; /* sig */
+ n = ns_get16(rdata); rdata += INT16SZ; /* original id */
+ sprintf(buf, "%d", ns_get16(rdata));
+ rdata += INT16SZ;
+ addlen(strlen(buf), &buf, &buflen);
+ break;
+ }
+
+ default:
+ comment = "unknown RR type";
+ goto hexify;
+ }
+ return (buf - obuf);
+ formerr:
+ comment = "RR format error";
+ hexify: {
+ int n, m;
+ char *p;
+
+ len = SPRINTF((tmp, "\\#(\t\t; %s", comment));
+ T(addstr(tmp, len, &buf, &buflen));
+ while (rdata < edata) {
+ p = tmp;
+ p += SPRINTF((p, "\n\t"));
+ spaced = 0;
+ n = MIN(16, edata - rdata);
+ for (m = 0; m < n; m++)
+ p += SPRINTF((p, "%02x ", rdata[m]));
+ T(addstr(tmp, p - tmp, &buf, &buflen));
+ if (n < 16) {
+ T(addstr(")", 1, &buf, &buflen));
+ T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen));
+ }
+ p = tmp;
+ p += SPRINTF((p, "; "));
+ for (m = 0; m < n; m++)
+ *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
+ ? rdata[m]
+ : '.';
+ T(addstr(tmp, p - tmp, &buf, &buflen));
+ rdata += n;
+ }
+ return (buf - obuf);
+ }
+}
+
+/* Private. */
+
+/*
+ * size_t
+ * prune_origin(name, origin)
+ * Find out if the name is at or under the current origin.
+ * return:
+ * Number of characters in name before start of origin,
+ * or length of name if origin does not match.
+ * notes:
+ * This function should share code with samedomain().
+ */
+static size_t
+prune_origin(const char *name, const char *origin) {
+ const char *oname = name;
+
+ while (*name != '\0') {
+ if (origin != NULL && ns_samename(name, origin) == 1)
+ return (name - oname - (name > oname));
+ while (*name != '\0') {
+ if (*name == '\\') {
+ name++;
+ /* XXX need to handle \nnn form. */
+ if (*name == '\0')
+ break;
+ } else if (*name == '.') {
+ name++;
+ break;
+ }
+ name++;
+ }
+ }
+ return (name - oname);
+}
+
+/*
+ * int
+ * charstr(rdata, edata, buf, buflen)
+ * Format a <character-string> into the presentation buffer.
+ * return:
+ * Number of rdata octets consumed
+ * 0 for protocol format error
+ * -1 for output buffer error
+ * side effects:
+ * buffer is advanced on success.
+ */
+static int
+charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
+ const u_char *odata = rdata;
+ size_t save_buflen = *buflen;
+ char *save_buf = *buf;
+
+ if (addstr("\"", 1, buf, buflen) < 0)
+ goto enospc;
+ if (rdata < edata) {
+ int n = *rdata;
+
+ if (rdata + 1 + n <= edata) {
+ rdata++;
+ while (n-- > 0) {
+ if (strchr("\n\"\\", *rdata) != NULL)
+ if (addstr("\\", 1, buf, buflen) < 0)
+ goto enospc;
+ if (addstr((const char *)rdata, 1,
+ buf, buflen) < 0)
+ goto enospc;
+ rdata++;
+ }
+ }
+ }
+ if (addstr("\"", 1, buf, buflen) < 0)
+ goto enospc;
+ return (rdata - odata);
+ enospc:
+ __set_errno (ENOSPC);
+ *buf = save_buf;
+ *buflen = save_buflen;
+ return (-1);
+}
+
+static int
+addname(const u_char *msg, size_t msglen,
+ const u_char **pp, const char *origin,
+ char **buf, size_t *buflen)
+{
+ size_t newlen, save_buflen = *buflen;
+ char *save_buf = *buf;
+ int n;
+
+ n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen);
+ if (n < 0)
+ goto enospc; /* Guess. */
+ newlen = prune_origin(*buf, origin);
+ if ((origin == NULL || origin[0] == '\0' || (*buf)[newlen] == '\0') &&
+ (newlen == 0 || (*buf)[newlen - 1] != '.')) {
+ /* No trailing dot. */
+ if (newlen + 2 > *buflen)
+ goto enospc; /* No room for ".\0". */
+ (*buf)[newlen++] = '.';
+ (*buf)[newlen] = '\0';
+ }
+ if (newlen == 0) {
+ /* Use "@" instead of name. */
+ if (newlen + 2 > *buflen)
+ goto enospc; /* No room for "@\0". */
+ (*buf)[newlen++] = '@';
+ (*buf)[newlen] = '\0';
+ }
+ *pp += n;
+ addlen(newlen, buf, buflen);
+ **buf = '\0';
+ return (newlen);
+ enospc:
+ __set_errno (ENOSPC);
+ *buf = save_buf;
+ *buflen = save_buflen;
+ return (-1);
+}
+
+static void
+addlen(size_t len, char **buf, size_t *buflen) {
+#if 0
+ INSIST(len <= *buflen);
+#endif
+ *buf += len;
+ *buflen -= len;
+}
+
+static int
+addstr(const char *src, size_t len, char **buf, size_t *buflen) {
+ if (len >= *buflen) {
+ __set_errno (ENOSPC);
+ return (-1);
+ }
+ memcpy(*buf, src, len);
+ addlen(len, buf, buflen);
+ **buf = '\0';
+ return (0);
+}
+
+static int
+addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
+ size_t save_buflen = *buflen;
+ char *save_buf = *buf;
+ int t;
+
+ if (spaced || len >= target - 1) {
+ T(addstr(" ", 2, buf, buflen));
+ spaced = 1;
+ } else {
+ for (t = (target - len - 1) / 8; t >= 0; t--)
+ if (addstr("\t", 1, buf, buflen) < 0) {
+ *buflen = save_buflen;
+ *buf = save_buf;
+ return (-1);
+ }
+ spaced = 0;
+ }
+ return (spaced);
+}
diff --git a/resolv/ns_samedomain.c b/resolv/ns_samedomain.c
new file mode 100644
index 0000000000..bac5a639e7
--- /dev/null
+++ b/resolv/ns_samedomain.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 1995,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id$";
+#endif
+
+#include <sys/types.h>
+#include <arpa/nameser.h>
+#include <errno.h>
+#include <string.h>
+
+/*
+ * int
+ * ns_samedomain(a, b)
+ * Check whether a name belongs to a domain.
+ * Inputs:
+ * a - the domain whose ancestory is being verified
+ * b - the potential ancestor we're checking against
+ * Return:
+ * boolean - is a at or below b?
+ * Notes:
+ * Trailing dots are first removed from name and domain.
+ * Always compare complete subdomains, not only whether the
+ * domain name is the trailing string of the given name.
+ *
+ * "host.foobar.top" lies in "foobar.top" and in "top" and in ""
+ * but NOT in "bar.top"
+ */
+
+int
+ns_samedomain(const char *a, const char *b) {
+ size_t la, lb;
+ int diff, i, escaped;
+ const char *cp;
+
+ la = strlen(a);
+ lb = strlen(b);
+
+ /* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */
+ if (la != 0 && a[la - 1] == '.') {
+ escaped = 0;
+ /* Note this loop doesn't get executed if la==1. */
+ for (i = la - 2; i >= 0; i--)
+ if (a[i] == '\\') {
+ if (escaped)
+ escaped = 0;
+ else
+ escaped = 1;
+ } else
+ break;
+ if (!escaped)
+ la--;
+ }
+
+ /* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */
+ if (lb != 0 && b[lb - 1] == '.') {
+ escaped = 0;
+ /* note this loop doesn't get executed if lb==1 */
+ for (i = lb - 2; i >= 0; i--)
+ if (b[i] == '\\') {
+ if (escaped)
+ escaped = 0;
+ else
+ escaped = 1;
+ } else
+ break;
+ if (!escaped)
+ lb--;
+ }
+
+ /* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */
+ if (lb == 0)
+ return (1);
+
+ /* 'b' longer than 'a' means 'a' can't be in 'b'. */
+ if (lb > la)
+ return (0);
+
+ /* 'a' and 'b' being equal at this point indicates sameness. */
+ if (lb == la)
+ return (strncasecmp(a, b, lb) == 0);
+
+ /* Ok, we know la > lb. */
+
+ diff = la - lb;
+
+ /*
+ * If 'a' is only 1 character longer than 'b', then it can't be
+ * a subdomain of 'b' (because of the need for the '.' label
+ * separator).
+ */
+ if (diff < 2)
+ return (0);
+
+ /*
+ * If the character before the last 'lb' characters of 'b'
+ * isn't '.', then it can't be a match (this lets us avoid
+ * having "foobar.com" match "bar.com").
+ */
+ if (a[diff - 1] != '.')
+ return (0);
+
+ /*
+ * We're not sure about that '.', however. It could be escaped
+ * and thus not a really a label separator.
+ */
+ escaped = 0;
+ for (i = diff - 2; i >= 0; i--)
+ if (a[i] == '\\')
+ if (escaped)
+ escaped = 0;
+ else
+ escaped = 1;
+ else
+ break;
+ if (escaped)
+ return (0);
+
+ /* Now compare aligned trailing substring. */
+ cp = a + diff;
+ return (strncasecmp(cp, b, lb) == 0);
+}
+
+/*
+ * int
+ * ns_subdomain(a, b)
+ * is "a" a subdomain of "b"?
+ */
+int
+ns_subdomain(const char *a, const char *b) {
+ return (ns_samename(a, b) != 1 && ns_samedomain(a, b));
+}
+
+/*
+ * int
+ * ns_makecanon(src, dst, dstsize)
+ * make a canonical copy of domain name "src"
+ * notes:
+ * foo -> foo.
+ * foo. -> foo.
+ * foo.. -> foo.
+ * foo\. -> foo\..
+ * foo\\. -> foo\\.
+ */
+
+int
+ns_makecanon(const char *src, char *dst, size_t dstsize) {
+ size_t n = strlen(src);
+
+ if (n + sizeof "." > dstsize) {
+ __set_errno (EMSGSIZE);
+ return (-1);
+ }
+ strcpy(dst, src);
+ while (n > 0 && dst[n - 1] == '.') /* Ends in "." */
+ if (n > 1 && dst[n - 2] == '\\' && /* Ends in "\." */
+ (n < 2 || dst[n - 3] != '\\')) /* But not "\\." */
+ break;
+ else
+ dst[--n] = '\0';
+ dst[n++] = '.';
+ dst[n] = '\0';
+ return (0);
+}
+
+/*
+ * int
+ * ns_samename(a, b)
+ * determine whether domain name "a" is the same as domain name "b"
+ * return:
+ * -1 on error
+ * 0 if names differ
+ * 1 if names are the same
+ */
+
+int
+ns_samename(const char *a, const char *b) {
+ char ta[NS_MAXDNAME], tb[NS_MAXDNAME];
+
+ if (ns_makecanon(a, ta, sizeof ta) < 0 ||
+ ns_makecanon(b, tb, sizeof tb) < 0)
+ return (-1);
+ if (strcasecmp(ta, tb) == 0)
+ return (1);
+ else
+ return (0);
+}
diff --git a/resolv/ns_ttl.c b/resolv/ns_ttl.c
new file mode 100644
index 0000000000..6be2b0d7a7
--- /dev/null
+++ b/resolv/ns_ttl.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id$";
+#endif
+
+/* Import. */
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/* Forward. */
+
+static int fmt1(int t, char s, char **buf, size_t *buflen);
+
+/* Macros. */
+
+#define T(x) if ((x) < 0) return (-1); else (void)NULL
+
+/* Public. */
+
+int
+ns_format_ttl(u_long src, char *dst, size_t dstlen) {
+ char *odst = dst;
+ int secs, mins, hours, days, weeks, x;
+ char *p;
+
+ secs = src % 60; src /= 60;
+ mins = src % 60; src /= 60;
+ hours = src % 24; src /= 24;
+ days = src % 7; src /= 7;
+ weeks = src; src = 0;
+
+ x = 0;
+ if (weeks) {
+ T(fmt1(weeks, 'W', &dst, &dstlen));
+ x++;
+ }
+ if (days) {
+ T(fmt1(days, 'D', &dst, &dstlen));
+ x++;
+ }
+ if (hours) {
+ T(fmt1(hours, 'H', &dst, &dstlen));
+ x++;
+ }
+ if (mins) {
+ T(fmt1(mins, 'M', &dst, &dstlen));
+ x++;
+ }
+ if (secs || !(weeks || days || hours || mins)) {
+ T(fmt1(secs, 'S', &dst, &dstlen));
+ x++;
+ }
+
+ if (x > 1) {
+ int ch;
+
+ for (p = odst; (ch = *p) != '\0'; p++)
+ if (isascii(ch) && isupper(ch))
+ *p = tolower(ch);
+ }
+
+ return (dst - odst);
+}
+
+int
+ns_parse_ttl(const char *src, u_long *dst) {
+ u_long ttl, tmp;
+ int ch, digits, dirty;
+
+ ttl = 0;
+ tmp = 0;
+ digits = 0;
+ dirty = 0;
+ while ((ch = *src++) != '\0') {
+ if (!isascii(ch) || !isprint(ch))
+ goto einval;
+ if (isdigit(ch)) {
+ tmp *= 10;
+ tmp += (ch - '0');
+ digits++;
+ continue;
+ }
+ if (digits == 0)
+ goto einval;
+ if (islower(ch))
+ ch = toupper(ch);
+ switch (ch) {
+ case 'W': tmp *= 7;
+ case 'D': tmp *= 24;
+ case 'H': tmp *= 60;
+ case 'M': tmp *= 60;
+ case 'S': break;
+ default: goto einval;
+ }
+ ttl += tmp;
+ tmp = 0;
+ digits = 0;
+ dirty = 1;
+ }
+ if (digits > 0) {
+ if (dirty)
+ goto einval;
+ else
+ ttl += tmp;
+ }
+ *dst = ttl;
+ return (0);
+
+ einval:
+ __set_errno (EINVAL);
+ return (-1);
+}
+
+/* Private. */
+
+static int
+fmt1(int t, char s, char **buf, size_t *buflen) {
+ char tmp[50];
+ size_t len;
+
+ len = SPRINTF((tmp, "%d%c", t, s));
+ if (len + 1 > *buflen)
+ return (-1);
+ strcpy(*buf, tmp);
+ *buf += len;
+ *buflen -= len;
+ return (0);
+}
diff --git a/resolv/nsap_addr.c b/resolv/nsap_addr.c
index 53a19d59be..c1c9a61d35 100644
--- a/resolv/nsap_addr.c
+++ b/resolv/nsap_addr.c
@@ -28,31 +28,14 @@ static char rcsid[] = "$Id$";
#include <ctype.h>
#include <resolv.h>
-#include "../conf/portability.h"
-
-#if !defined(isxdigit) /* XXX - could be a function */
-static int
-isxdigit(c)
- register int c;
-{
- return ((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'F'));
-}
-#endif
-
static char
-xtob(c)
- register int c;
-{
+xtob(int c) {
return (c - (((c >= '0') && (c <= '9')) ? '0' : '7'));
}
u_int
-inet_nsap_addr(ascii, binary, maxlen)
- const char *ascii;
- u_char *binary;
- int maxlen;
-{
- register u_char c, nib;
+inet_nsap_addr(const char *ascii, u_char *binary, int maxlen) {
+ u_char c, nib;
u_int len = 0;
while ((c = *ascii++) != '\0' && (int) len < maxlen) {
@@ -63,7 +46,8 @@ inet_nsap_addr(ascii, binary, maxlen)
c = toupper(c);
if (isxdigit(c)) {
nib = xtob(c);
- if ((c = *ascii++)) {
+ c = *ascii++;
+ if (c != '\0') {
c = toupper(c);
if (isxdigit(c)) {
*binary++ = (nib << 4) | xtob(c);
@@ -81,12 +65,8 @@ inet_nsap_addr(ascii, binary, maxlen)
}
char *
-inet_nsap_ntoa(binlen, binary, ascii)
- int binlen;
- register const u_char *binary;
- register char *ascii;
-{
- register int nib;
+inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii) {
+ int nib;
int i;
static char tmpbuf[255*3];
char *start;
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index 482cbd3ab4..483e791801 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -133,6 +133,9 @@ _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
int size, type, n;
const char *cp;
+ if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1)
+ return NSS_STATUS_UNAVAIL;
+
switch (af) {
case AF_INET:
size = INADDRSZ;
@@ -159,7 +162,8 @@ _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
if (strchr (name, '.') == NULL && (cp = __hostalias (name)) != NULL)
name = cp;
- n = res_search (name, C_IN, type, host_buffer.buf, sizeof (host_buffer.buf));
+ n = res_nsearch (&_res, name, C_IN, type, host_buffer.buf,
+ sizeof (host_buffer.buf));
if (n < 0)
{
*h_errnop = h_errno;
@@ -211,6 +215,9 @@ _nss_dns_gethostbyaddr_r (const char *addr, size_t len, int af,
size_t size;
int n, status;
+ if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1)
+ return NSS_STATUS_UNAVAIL;
+
if (af == AF_INET6 && len == IN6ADDRSZ
&& (memcmp (uaddr, mapped, sizeof mapped) == 0
|| (memcmp (uaddr, tunnelled, sizeof tunnelled) == 0
@@ -259,8 +266,8 @@ _nss_dns_gethostbyaddr_r (const char *addr, size_t len, int af,
/* Cannot happen. */
}
- n = res_query (qbuf, C_IN, T_PTR, (u_char *)host_buffer.buf,
- sizeof host_buffer);
+ n = res_nquery (&_res, qbuf, C_IN, T_PTR, (u_char *)host_buffer.buf,
+ sizeof host_buffer);
if (n < 0)
{
*h_errnop = h_errno;
@@ -435,11 +442,11 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
continue;
}
cp += n; /* name */
- type = _getshort (cp);
+ type = ns_get16 (cp);
cp += INT16SZ; /* type */
- class = _getshort (cp);
+ class = ns_get16 (cp);
cp += INT16SZ + INT32SZ; /* class, TTL */
- n = _getshort (cp);
+ n = ns_get16 (cp);
cp += INT16SZ; /* len */
if (class != C_IN)
{
diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
index f81341cb39..b194852197 100644
--- a/resolv/nss_dns/dns-network.c
+++ b/resolv/nss_dns/dns-network.c
@@ -113,9 +113,12 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result,
int anslen;
char *qbuf;
+ if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1)
+ return NSS_STATUS_UNAVAIL;
+
qbuf = strdupa (name);
- anslen = res_search (qbuf, C_IN, T_PTR, (u_char *) &net_buffer,
- sizeof (querybuf));
+ anslen = res_nsearch (&_res, qbuf, C_IN, T_PTR, (u_char *) &net_buffer,
+ sizeof (querybuf));
if (anslen < 0)
{
/* Nothing found. */
@@ -146,6 +149,9 @@ _nss_dns_getnetbyaddr_r (long net, int type, struct netent *result,
if (type != AF_INET)
return NSS_STATUS_UNAVAIL;
+ if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1)
+ return NSS_STATUS_UNAVAIL;
+
net2 = (u_int32_t) net;
for (cnt = 4; net2 != 0; net2 >>= 8)
net_bytes[--cnt] = net2 & 0xff;
@@ -172,8 +178,8 @@ _nss_dns_getnetbyaddr_r (long net, int type, struct netent *result,
break;
}
- anslen = res_query (qbuf, C_IN, T_PTR, (u_char *) &net_buffer,
- sizeof (querybuf));
+ anslen = res_nquery (&_res, qbuf, C_IN, T_PTR, (u_char *) &net_buffer,
+ sizeof (querybuf));
if (anslen < 0)
{
/* Nothing found. */
diff --git a/resolv/res_comp.c b/resolv/res_comp.c
index 2d90e37794..e6f54ce06a 100644
--- a/resolv/res_comp.c
+++ b/resolv/res_comp.c
@@ -1,6 +1,4 @@
/*
- * ++Copyright++ 1985, 1993
- * -
* Copyright (c) 1985, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -45,13 +43,28 @@
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
- * -
- * --Copyright--
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id$";
+static const char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@@ -64,24 +77,9 @@ static char rcsid[] = "$Id$";
#include <resolv.h>
#include <stdio.h>
-#if defined(BSD) && (BSD >= 199103)
-# include <unistd.h>
-# include <string.h>
-#else
-# include "../conf/portability.h"
-#endif
+#include <string.h>
+#include <unistd.h>
-extern int __ns_name_ntop __P((const u_char *, char *, size_t));
-static int ns_name_pton __P((const char *, u_char *, size_t));
-extern int __ns_name_unpack __P((const u_char *, const u_char *,
- const u_char *, u_char *, size_t));
-static int ns_name_pack __P((const u_char *, u_char *, int,
- const u_char **, const u_char **));
-static int ns_name_uncompress __P((const u_char *, const u_char *,
- const u_char *, char *, size_t));
-static int ns_name_compress __P((const char *, u_char *, size_t,
- const u_char **, const u_char **));
-static int ns_name_skip __P((const u_char **, const u_char *));
/*
* Expand compressed domain name 'comp_dn' to full domain name.
@@ -91,12 +89,8 @@ static int ns_name_skip __P((const u_char **, const u_char *));
* Return size of compressed name or -1 if there was an error.
*/
int
-dn_expand(msg, eom, src, dst, dstsiz)
- const u_char *msg;
- const u_char *eom;
- const u_char *src;
- char *dst;
- int dstsiz;
+dn_expand(const u_char *msg, const u_char *eom, const u_char *src,
+ char *dst, int dstsiz)
{
int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz);
@@ -111,12 +105,8 @@ dn_expand(msg, eom, src, dst, dstsiz)
* 'length' is the size of the array pointed to by 'comp_dn'.
*/
int
-dn_comp(src, dst, dstsiz, dnptrs, lastdnptr)
- const char *src;
- u_char *dst;
- int dstsiz;
- u_char **dnptrs;
- u_char **lastdnptr;
+dn_comp(const char *src, u_char *dst, int dstsiz,
+ u_char **dnptrs, u_char **lastdnptr)
{
return (ns_name_compress(src, dst, (size_t)dstsiz,
(const u_char **)dnptrs,
@@ -127,10 +117,7 @@ dn_comp(src, dst, dstsiz, dnptrs, lastdnptr)
* Skip over a compressed domain name. Return the size or -1.
*/
int
-__dn_skipname(ptr, eom)
- const u_char *ptr;
- const u_char *eom;
-{
+dn_skipname(const u_char *ptr, const u_char *eom) {
const u_char *saveptr = ptr;
if (ns_name_skip(&ptr, eom) == -1)
@@ -163,9 +150,7 @@ __dn_skipname(ptr, eom)
#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
int
-res_hnok(dn)
- const char *dn;
-{
+res_hnok(const char *dn) {
int ppch = '\0', pch = PERIOD, ch = *dn++;
while (ch != '\0') {
@@ -193,9 +178,7 @@ res_hnok(dn)
* but must otherwise be as a host name.
*/
int
-res_ownok(dn)
- const char *dn;
-{
+res_ownok(const char *dn) {
if (asterchar(dn[0])) {
if (periodchar(dn[1]))
return (res_hnok(dn+2));
@@ -210,9 +193,7 @@ res_ownok(dn)
* label, but the rest of the name has to look like a host name.
*/
int
-res_mailok(dn)
- const char *dn;
-{
+res_mailok(const char *dn) {
int ch, escaped = 0;
/* "." is a valid missing representation */
@@ -232,7 +213,7 @@ res_mailok(dn)
}
if (periodchar(ch))
return (res_hnok(dn));
- return(0);
+ return (0);
}
/*
@@ -240,9 +221,7 @@ res_mailok(dn)
* recommendations.
*/
int
-res_dnok(dn)
- const char *dn;
-{
+res_dnok(const char *dn) {
int ch;
while ((ch = *dn++) != '\0')
@@ -251,700 +230,19 @@ res_dnok(dn)
return (1);
}
+#ifdef BIND_4_COMPAT
/*
- * Routines to insert/extract short/long's.
+ * This module must export the following externally-visible symbols:
+ * ___putlong
+ * ___putshort
+ * __getlong
+ * __getshort
+ * Note that one _ comes from C and the others come from us.
*/
-
-u_int16_t
-_getshort(msgp)
- register const u_char *msgp;
-{
- register u_int16_t u;
-
- GETSHORT(u, msgp);
- return (u);
-}
-
-#ifdef NeXT
-/*
- * nExt machines have some funky library conventions, which we must maintain.
- */
-u_int16_t
-res_getshort(msgp)
- register const u_char *msgp;
-{
- return (_getshort(msgp));
-}
-#endif
-
-u_int32_t
-_getlong(msgp)
- register const u_char *msgp;
-{
- register u_int32_t u;
-
- GETLONG(u, msgp);
- return (u);
-}
-
-void
-#if defined(__STDC__) || defined(__cplusplus)
-__putshort(register u_int16_t s, register u_char *msgp) /* must match proto */
-#else
-__putshort(s, msgp)
- register u_int16_t s;
- register u_char *msgp;
-#endif
-{
- PUTSHORT(s, msgp);
-}
-
-void
-__putlong(l, msgp)
- register u_int32_t l;
- register u_char *msgp;
-{
- PUTLONG(l, msgp);
-}
-
-/* ++ From BIND 8.1.1. ++ */
-/*
- * Copyright (c) 1996 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-/*"Id: ns_name.c,v 1.1 1997/12/13 02:41:13 vixie Exp vixie"*/
-
-/*#include "port_before.h"*/
-
-/*#include <sys/types.h>*/
-
-/*#include <netinet/in.h>*/
-/*#include <arpa/nameser.h>*/
-
-/*#include <errno.h>*/
-/*#include <resolv.h>*/
-/*#include <string.h>*/
-
-/*#include "port_after.h"*/
-
-#define NS_CMPRSFLGS 0xc0 /* Flag bits indicating name compression. */
-#define NS_MAXCDNAME 255 /* maximum compressed domain name */
-
-/* Data. */
-
-static const char digits[] = "0123456789";
-
-/* Forward. */
-
-static int special(int);
-static int printable(int);
-static int dn_find(const u_char *, const u_char *,
- const u_char * const *,
- const u_char * const *);
-
-/* Public. */
-
-/*
- * ns_name_ntop(src, dst, dstsiz)
- * Convert an encoded domain name to printable ascii as per RFC1035.
- * return:
- * Number of bytes written to buffer, or -1 (with errno set)
- * notes:
- * The root is returned as "."
- * All other domains are returned in non absolute form
- */
-int
-__ns_name_ntop(src, dst, dstsiz)
- const u_char *src;
- char *dst;
- size_t dstsiz;
-{
- const u_char *cp;
- char *dn, *eom;
- u_char c;
- u_int n;
-
- cp = src;
- dn = dst;
- eom = dst + dstsiz;
-
- while ((n = *cp++) != 0) {
- if ((n & NS_CMPRSFLGS) != 0) {
- /* Some kind of compression pointer. */
- __set_errno (EINVAL);
- return (-1);
- }
- if (dn != dst) {
- if (dn >= eom) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- *dn++ = '.';
- }
- if (dn + n >= eom) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- for ((void)NULL; n > 0; n--) {
- c = *cp++;
- if (special(c)) {
- if (dn + 1 >= eom) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- *dn++ = '\\';
- *dn++ = (char)c;
- } else if (!printable(c)) {
- if (dn + 3 >= eom) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- *dn++ = '\\';
- *dn++ = digits[c / 100];
- *dn++ = digits[(c % 100) / 10];
- *dn++ = digits[c % 10];
- } else {
- if (dn >= eom) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- *dn++ = (char)c;
- }
- }
- }
- if (dn == dst) {
- if (dn >= eom) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- *dn++ = '.';
- }
- if (dn >= eom) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- *dn++ = '\0';
- return (dn - dst);
-}
-
-/*
- * ns_name_pton(src, dst, dstsiz)
- * Convert a ascii string into an encoded domain name as per RFC1035.
- * return:
- * -1 if it fails
- * 1 if string was fully qualified
- * 0 is string was not fully qualified
- * notes:
- * Enforces label and domain length limits.
- */
-
-static int
-ns_name_pton(src, dst, dstsiz)
- const char *src;
- u_char *dst;
- size_t dstsiz;
-{
- u_char *label, *bp, *eom;
- int c, n, escaped;
- char *cp;
-
- escaped = 0;
- bp = dst;
- eom = dst + dstsiz;
- label = bp++;
-
- while ((c = *src++) != 0) {
- if (escaped) {
- if ((cp = strchr(digits, c)) != NULL) {
- n = (cp - digits) * 100;
- if ((c = *src++) == 0 ||
- (cp = strchr(digits, c)) == NULL) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- n += (cp - digits) * 10;
- if ((c = *src++) == 0 ||
- (cp = strchr(digits, c)) == NULL) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- n += (cp - digits);
- if (n > 255) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- c = n;
- }
- escaped = 0;
- } else if (c == '\\') {
- escaped = 1;
- continue;
- } else if (c == '.') {
- c = (bp - label - 1);
- if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
- __set_errno (EMSGSIZE);
- return (-1);
- }
- if (label >= eom) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- *label = c;
- /* Fully qualified ? */
- if (*src == '\0') {
- if (c != 0) {
- if (bp >= eom) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- *bp++ = '\0';
- }
- if ((bp - dst) > MAXCDNAME) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- return (1);
- }
- if (c == 0) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- label = bp++;
- continue;
- }
- if (bp >= eom) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- *bp++ = (u_char)c;
- }
- c = (bp - label - 1);
- if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
- __set_errno (EMSGSIZE);
- return (-1);
- }
- if (label >= eom) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- *label = c;
- if (c != 0) {
- if (bp >= eom) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- *bp++ = 0;
- }
- if ((bp - dst) > MAXCDNAME) { /* src too big */
- __set_errno (EMSGSIZE);
- return (-1);
- }
- return (0);
-}
-
-/*
- * ns_name_unpack(msg, eom, src, dst, dstsiz)
- * Unpack a domain name from a message, source may be compressed.
- * return:
- * -1 if it fails, or consumed octets if it succeeds.
- */
-int
-__ns_name_unpack(msg, eom, src, dst, dstsiz)
- const u_char *msg;
- const u_char *eom;
- const u_char *src;
- u_char *dst;
- size_t dstsiz;
-{
- const u_char *srcp, *dstlim;
- u_char *dstp;
-#ifdef _LIBC
- /* We don't want warnings! */
- int n, len, checked;
-#else
- int n, c, len, checked;
-#endif
-
- len = -1;
- checked = 0;
- dstp = dst;
- srcp = src;
- dstlim = dst + dstsiz;
- if (srcp < msg || srcp >= eom) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- /* Fetch next label in domain name. */
- while ((n = *srcp++) != 0) {
- /* Check for indirection. */
- switch (n & NS_CMPRSFLGS) {
- case 0:
- /* Limit checks. */
- if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- checked += n + 1;
- *dstp++ = n;
- memcpy(dstp, srcp, n);
- dstp += n;
- srcp += n;
- break;
-
- case NS_CMPRSFLGS:
- if (srcp >= eom) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- if (len < 0)
- len = srcp - src + 1;
- srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
- if (srcp < msg || srcp >= eom) { /* Out of range. */
- __set_errno (EMSGSIZE);
- return (-1);
- }
- checked += 2;
- /*
- * Check for loops in the compressed name;
- * if we've looked at the whole message,
- * there must be a loop.
- */
- if (checked >= eom - msg) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- break;
-
- default:
- __set_errno (EMSGSIZE);
- return (-1); /* flag error */
- }
- }
- *dstp = '\0';
- if (len < 0)
- len = srcp - src;
- return (len);
-}
-
-/*
- * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
- * Pack domain name 'domain' into 'comp_dn'.
- * return:
- * Size of the compressed name, or -1.
- * notes:
- * 'dnptrs' is an array of pointers to previous compressed names.
- * dnptrs[0] is a pointer to the beginning of the message. The array
- * ends with NULL.
- * 'lastdnptr' is a pointer to the end of the array pointed to
- * by 'dnptrs'.
- * Side effects:
- * The list of pointers in dnptrs is updated for labels inserted into
- * the message as we compress the name. If 'dnptr' is NULL, we don't
- * try to compress names. If 'lastdnptr' is NULL, we don't update the
- * list.
- */
-static int
-ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
- const u_char *src;
- u_char *dst;
- int dstsiz;
- const u_char **dnptrs;
- const u_char **lastdnptr;
-{
- u_char *dstp;
- const u_char **cpp, **lpp, *eob, *msg;
- const u_char *srcp;
- int n, l;
-
- srcp = src;
- dstp = dst;
- eob = dstp + dstsiz;
- lpp = cpp = NULL;
- if (dnptrs != NULL) {
- if ((msg = *dnptrs++) != NULL) {
- for (cpp = dnptrs; *cpp != NULL; cpp++)
- (void)NULL;
- lpp = cpp; /* end of list to search */
- }
- } else
- msg = NULL;
-
- /* make sure the domain we are about to add is legal */
- l = 0;
- do {
- n = *srcp;
- if ((n & NS_CMPRSFLGS) != 0) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- l += n + 1;
- if (l > MAXCDNAME) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- srcp += n + 1;
- } while (n != 0);
-
- srcp = src;
- do {
- /* Look to see if we can use pointers. */
- n = *srcp;
- if (n != 0 && msg != NULL) {
- l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
- (const u_char * const *)lpp);
- if (l >= 0) {
- if (dstp + 1 >= eob) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- *dstp++ = (l >> 8) | NS_CMPRSFLGS;
- *dstp++ = l % 256;
- return (dstp - dst);
- }
- /* Not found, save it. */
- if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
- (dstp - msg) < 0x4000) {
- *cpp++ = dstp;
- *cpp = NULL;
- }
- }
- /* copy label to buffer */
- if (n & NS_CMPRSFLGS) { /* Should not happen. */
- __set_errno (EMSGSIZE);
- return (-1);
- }
- if (dstp + 1 + n >= eob) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- memcpy(dstp, srcp, n + 1);
- srcp += n + 1;
- dstp += n + 1;
- } while (n != 0);
-
- if (dstp > eob) {
- if (msg != NULL)
- *lpp = NULL;
- __set_errno (EMSGSIZE);
- return (-1);
- }
- return (dstp - dst);
-}
-
-/*
- * ns_name_uncompress(msg, eom, src, dst, dstsiz)
- * Expand compressed domain name to presentation format.
- * return:
- * Number of bytes read out of `src', or -1 (with errno set).
- * note:
- * Root domain returns as "." not "".
- */
-static int
-ns_name_uncompress(msg, eom, src, dst, dstsiz)
- const u_char *msg;
- const u_char *eom;
- const u_char *src;
- char *dst;
- size_t dstsiz;
-{
- u_char tmp[NS_MAXCDNAME];
- int n;
-
- if ((n = __ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
- return (-1);
- if (__ns_name_ntop(tmp, dst, dstsiz) == -1)
- return (-1);
- return (n);
-}
-
-/*
- * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
- * Compress a domain name into wire format, using compression pointers.
- * return:
- * Number of bytes consumed in `dst' or -1 (with errno set).
- * notes:
- * 'dnptrs' is an array of pointers to previous compressed names.
- * dnptrs[0] is a pointer to the beginning of the message.
- * The list ends with NULL. 'lastdnptr' is a pointer to the end of the
- * array pointed to by 'dnptrs'. Side effect is to update the list of
- * pointers for labels inserted into the message as we compress the name.
- * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
- * is NULL, we don't update the list.
- */
-static int
-ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
- const char *src;
- u_char *dst;
- size_t dstsiz;
- const u_char **dnptrs;
- const u_char **lastdnptr;
-{
- u_char tmp[NS_MAXCDNAME];
-
- if (ns_name_pton(src, tmp, sizeof tmp) == -1)
- return (-1);
- return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
-}
-
-/*
- * ns_name_skip(ptrptr, eom)
- * Advance *ptrptr to skip over the compressed name it points at.
- * return:
- * 0 on success, -1 (with errno set) on failure.
- */
-static int
-ns_name_skip(ptrptr, eom)
- const u_char **ptrptr;
- const u_char *eom;
-{
- const u_char *cp;
- u_int n;
-
- cp = *ptrptr;
- while (cp < eom && (n = *cp++) != 0) {
- /* Check for indirection. */
- switch (n & NS_CMPRSFLGS) {
- case 0: /* normal case, n == len */
- cp += n;
- continue;
- case NS_CMPRSFLGS: /* indirection */
- cp++;
- break;
- default: /* illegal type */
- __set_errno (EMSGSIZE);
- return (-1);
- }
- break;
- }
- if (cp > eom) {
- __set_errno (EMSGSIZE);
- return (-1);
- }
- *ptrptr = cp;
- return (0);
-}
-
-/* Private. */
-
-/*
- * special(ch)
- * Thinking in noninternationalized USASCII (per the DNS spec),
- * is this characted special ("in need of quoting") ?
- * return:
- * boolean.
- */
-static int
-special(ch)
- int ch;
-{
- switch (ch) {
- case 0x22: /* '"' */
- case 0x2E: /* '.' */
- case 0x3B: /* ';' */
- case 0x5C: /* '\\' */
- /* Special modifiers in zone files. */
- case 0x40: /* '@' */
- case 0x24: /* '$' */
- return (1);
- default:
- return (0);
- }
-}
-
-/*
- * printable(ch)
- * Thinking in noninternationalized USASCII (per the DNS spec),
- * is this character visible and not a space when printed ?
- * return:
- * boolean.
- */
-static int
-printable(ch)
- int ch;
-{
- return (ch > 0x20 && ch < 0x7f);
-}
-
-/*
- * Thinking in noninternationalized USASCII (per the DNS spec),
- * convert this character to lower case if it's upper case.
- */
-static int
-mklower(ch)
- int ch;
-{
- if (ch >= 0x41 && ch <= 0x5A)
- return (ch + 0x20);
- return (ch);
-}
-
-/*
- * dn_find(domain, msg, dnptrs, lastdnptr)
- * Search for the counted-label name in an array of compressed names.
- * return:
- * offset from msg if found, or -1.
- * notes:
- * dnptrs is the pointer to the first name on the list,
- * not the pointer to the start of the message.
- */
-static int
-dn_find(domain, msg, dnptrs, lastdnptr)
- const u_char *domain;
- const u_char *msg;
- const u_char * const *dnptrs;
- const u_char * const *lastdnptr;
-{
- const u_char *dn, *cp, *sp;
- const u_char * const *cpp;
- u_int n;
-
- for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
- dn = domain;
- sp = cp = *cpp;
- while ((n = *cp++) != 0) {
- /*
- * check for indirection
- */
- switch (n & NS_CMPRSFLGS) {
- case 0: /* normal case, n == len */
- if (n != *dn++)
- goto next;
- for ((void)NULL; n > 0; n--)
- if (mklower(*dn++) != mklower(*cp++))
- goto next;
- /* Is next root for both ? */
- if (*dn == '\0' && *cp == '\0')
- return (sp - msg);
- if (*dn)
- continue;
- goto next;
-
- case NS_CMPRSFLGS: /* indirection */
- cp = msg + (((n & 0x3f) << 8) | *cp);
- break;
-
- default: /* illegal type */
- __set_errno (EMSGSIZE);
- return (-1);
- }
- }
- next: ;
- }
- __set_errno (ENOENT);
- return (-1);
-}
-
-/* -- From BIND 8.1.1. -- */
+void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); }
+void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); }
+#ifndef __ultrix__
+u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); }
+u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); }
+#endif /*__ultrix__*/
+#endif /*BIND_4_COMPAT*/
diff --git a/resolv/res_data.c b/resolv/res_data.c
index aa3ecbd77c..a9f5a2ad67 100644
--- a/resolv/res_data.c
+++ b/resolv/res_data.c
@@ -1,76 +1,42 @@
/*
- * ++Copyright++ 1995
- * -
- * Copyright (c) 1995
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * -
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * Copyright (c) 1995-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies, and that
- * the name of Digital Equipment Corporation not be used in advertising or
- * publicity pertaining to distribution of the document or software without
- * specific, written prior permission.
+ * copyright notice and this permission notice appear in all copies.
*
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
- * -
- * --Copyright--
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$Id$";
+static const char rcsid[] = "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/time.h>
+
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
-#include <stdio.h>
#include <ctype.h>
+#include <netdb.h>
#include <resolv.h>
-#if defined(BSD) && (BSD >= 199103)
-# include <unistd.h>
-# include <stdlib.h>
-# include <string.h>
-#else
-# include "../conf/portability.h"
-#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#undef _res
const char *_res_opcodes[] = {
"QUERY",
@@ -78,26 +44,7 @@ const char *_res_opcodes[] = {
"CQUERYM",
"CQUERYU", /* experimental */
"NOTIFY", /* experimental */
- "5",
- "6",
- "7",
- "8",
- "UPDATEA",
- "UPDATED",
- "UPDATEDA",
- "UPDATEM",
- "UPDATEMA",
- "ZONEINIT",
- "ZONEREF",
-};
-
-const char *_res_resultcodes[] = {
- "NOERROR",
- "FORMERR",
- "SERVFAIL",
- "NXDOMAIN",
- "NOTIMP",
- "REFUSED",
+ "UPDATE",
"6",
"7",
"8",
@@ -106,6 +53,252 @@ const char *_res_resultcodes[] = {
"11",
"12",
"13",
- "14",
- "NOCHANGE",
+ "ZONEINIT",
+ "ZONEREF",
+};
+
+#ifdef BIND_UPDATE
+const char *_res_sectioncodes[] = {
+ "ZONE",
+ "PREREQUISITES",
+ "UPDATE",
+ "ADDITIONAL",
};
+#endif
+
+#ifndef __BIND_NOSTATIC
+
+#ifdef _LIBC
+extern struct __res_state _res;
+#else
+/* The declaration has been moved to res_libc.c. */
+struct __res_state _res
+# if defined(__BIND_RES_TEXT)
+ = { RES_TIMEOUT, } /* Motorola, et al. */
+# endif
+ ;
+#endif
+
+/* Proto. */
+
+int res_ourserver_p(const res_state, const struct sockaddr_in *);
+void res_pquery(const res_state, const u_char *, int, FILE *);
+
+#ifndef _LIBC
+/* Moved to res_libc.c since res_init should go into libc.so but the
+ rest of this file not. */
+int
+res_init(void) {
+ extern int __res_vinit(res_state, int);
+
+ /*
+ * These three fields used to be statically initialized. This made
+ * it hard to use this code in a shared library. It is necessary,
+ * now that we're doing dynamic initialization here, that we preserve
+ * the old semantics: if an application modifies one of these three
+ * fields of _res before res_init() is called, res_init() will not
+ * alter them. Of course, if an application is setting them to
+ * _zero_ before calling res_init(), hoping to override what used
+ * to be the static default, we can't detect it and unexpected results
+ * will follow. Zero for any of these fields would make no sense,
+ * so one can safely assume that the applications were already getting
+ * unexpected results.
+ *
+ * _res.options is tricky since some apps were known to diddle the bits
+ * before res_init() was first called. We can't replicate that semantic
+ * with dynamic initialization (they may have turned bits off that are
+ * set in RES_DEFAULT). Our solution is to declare such applications
+ * "broken". They could fool us by setting RES_INIT but none do (yet).
+ */
+ if (!_res.retrans)
+ _res.retrans = RES_TIMEOUT;
+ if (!_res.retry)
+ _res.retry = 4;
+ if (!(_res.options & RES_INIT))
+ _res.options = RES_DEFAULT;
+
+ /*
+ * This one used to initialize implicitly to zero, so unless the app
+ * has set it to something in particular, we can randomize it now.
+ */
+ if (!_res.id)
+ _res.id = res_randomid();
+
+ return (__res_vinit(&_res, 1));
+}
+#endif
+
+void
+p_query(const u_char *msg) {
+ fp_query(msg, stdout);
+}
+
+void
+fp_query(const u_char *msg, FILE *file) {
+ fp_nquery(msg, PACKETSZ, file);
+}
+
+void
+fp_nquery(const u_char *msg, int len, FILE *file) {
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ return;
+
+ res_pquery(&_res, msg, len, file);
+}
+
+int
+res_mkquery(int op, /* opcode of query */
+ const char *dname, /* domain name */
+ int class, int type, /* class and type of query */
+ const u_char *data, /* resource record data */
+ int datalen, /* length of data */
+ const u_char *newrr_in, /* new rr for modify or append */
+ u_char *buf, /* buffer to put query */
+ int buflen) /* size of buffer */
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+ return (res_nmkquery(&_res, op, dname, class, type,
+ data, datalen,
+ newrr_in, buf, buflen));
+}
+
+#ifdef BIND_UPDATE
+int
+res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nmkupdate(&_res, rrecp_in, buf, buflen));
+}
+#endif
+
+int
+res_query(const char *name, /* domain name */
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen) /* size of answer buffer */
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+ return (res_nquery(&_res, name, class, type, answer, anslen));
+}
+
+void
+res_send_setqhook(res_send_qhook hook) {
+ _res.qhook = hook;
+}
+
+void
+res_send_setrhook(res_send_rhook hook) {
+ _res.rhook = hook;
+}
+
+int
+res_isourserver(const struct sockaddr_in *inp) {
+ return (res_ourserver_p(&_res, inp));
+}
+
+int
+res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ /* errno should have been set by res_init() in this case. */
+ return (-1);
+ }
+
+ return (res_nsend(&_res, buf, buflen, ans, anssiz));
+}
+
+#ifndef _LIBC
+int
+res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key,
+ u_char *ans, int anssiz)
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ /* errno should have been set by res_init() in this case. */
+ return (-1);
+ }
+
+ return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz));
+}
+#endif
+
+void
+res_close(void) {
+ res_nclose(&_res);
+}
+
+#ifdef BIND_UPDATE
+int
+res_update(ns_updrec *rrecp_in) {
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nupdate(&_res, rrecp_in, NULL));
+}
+#endif
+
+int
+res_search(const char *name, /* domain name */
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen) /* size of answer */
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nsearch(&_res, name, class, type, answer, anslen));
+}
+
+int
+res_querydomain(const char *name,
+ const char *domain,
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen) /* size of answer */
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nquerydomain(&_res, name, domain,
+ class, type,
+ answer, anslen));
+}
+
+const char *
+hostalias(const char *name) {
+ static char abuf[MAXDNAME];
+
+ return (res_hostalias(&_res, name, abuf, sizeof abuf));
+}
+
+#ifdef ultrix
+int
+local_hostname_length(const char *hostname) {
+ int len_host, len_domain;
+
+ if (!*_res.defdname)
+ res_init();
+ len_host = strlen(hostname);
+ len_domain = strlen(_res.defdname);
+ if (len_host > len_domain &&
+ !strcasecmp(hostname + len_host - len_domain, _res.defdname) &&
+ hostname[len_host - len_domain - 1] == '.')
+ return (len_host - len_domain - 1);
+ return (0);
+}
+#endif /*ultrix*/
+
+#endif
diff --git a/resolv/res_debug.c b/resolv/res_debug.c
index dac878d721..2df1c5bbdc 100644
--- a/resolv/res_debug.c
+++ b/resolv/res_debug.c
@@ -1,7 +1,5 @@
/*
- * ++Copyright++ 1985, 1990, 1993
- * -
- * Copyright (c) 1985, 1990, 1993
+ * Copyright (c) 1985
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,7 +25,9 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- * -
+ */
+
+/*
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
@@ -45,7 +45,9 @@
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
- * -
+ */
+
+/*
* Portions Copyright (c) 1995 by International Business Machines, Inc.
*
* International Business Machines, Inc. (hereinafter called IBM) grants
@@ -68,202 +70,121 @@
* DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
- * --Copyright--
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id$";
+static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id$";
#endif /* LIBC_SCCS and not lint */
-#include <sys/param.h>
#include <sys/types.h>
+#include <sys/param.h>
#include <sys/socket.h>
+
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <ctype.h>
+#include <errno.h>
+#include <math.h>
#include <netdb.h>
#include <resolv.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <time.h>
-#if defined(BSD) && (BSD >= 199103) && defined(AF_INET6)
-# include <stdlib.h>
-# include <string.h>
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
#else
-# include "../conf/portability.h"
-#endif
-
-#if defined(USE_OPTIONS_H)
-# include "../conf/options.h"
+# define SPRINTF(x) sprintf x
#endif
extern const char *_res_opcodes[];
-extern const char *_res_resultcodes[];
+extern const char *_res_sectioncodes[];
-/* XXX: we should use getservbyport() instead. */
-static const char *
-dewks(wks)
- int wks;
-{
- static char nbuf[20];
-
- switch (wks) {
- case 5: return "rje";
- case 7: return "echo";
- case 9: return "discard";
- case 11: return "systat";
- case 13: return "daytime";
- case 15: return "netstat";
- case 17: return "qotd";
- case 19: return "chargen";
- case 20: return "ftp-data";
- case 21: return "ftp";
- case 23: return "telnet";
- case 25: return "smtp";
- case 37: return "time";
- case 39: return "rlp";
- case 42: return "name";
- case 43: return "whois";
- case 53: return "domain";
- case 57: return "apts";
- case 59: return "apfs";
- case 67: return "bootps";
- case 68: return "bootpc";
- case 69: return "tftp";
- case 77: return "rje";
- case 79: return "finger";
- case 87: return "link";
- case 95: return "supdup";
- case 100: return "newacct";
- case 101: return "hostnames";
- case 102: return "iso-tsap";
- case 103: return "x400";
- case 104: return "x400-snd";
- case 105: return "csnet-ns";
- case 109: return "pop-2";
- case 111: return "sunrpc";
- case 113: return "auth";
- case 115: return "sftp";
- case 117: return "uucp-path";
- case 119: return "nntp";
- case 121: return "erpc";
- case 123: return "ntp";
- case 133: return "statsrv";
- case 136: return "profile";
- case 144: return "NeWS";
- case 161: return "snmp";
- case 162: return "snmp-trap";
- case 170: return "print-srv";
- default: (void) sprintf(nbuf, "%d", wks); return (nbuf);
- }
-}
+/*
+ * Print the current options.
+ */
+void
+fp_resstat(const res_state statp, FILE *file) {
+ u_long mask;
-/* XXX: we should use getprotobynumber() instead. */
-static const char *
-deproto(protonum)
- int protonum;
-{
- static char nbuf[20];
-
- switch (protonum) {
- case 1: return "icmp";
- case 2: return "igmp";
- case 3: return "ggp";
- case 5: return "st";
- case 6: return "tcp";
- case 7: return "ucl";
- case 8: return "egp";
- case 9: return "igp";
- case 11: return "nvp-II";
- case 12: return "pup";
- case 16: return "chaos";
- case 17: return "udp";
- default: (void) sprintf(nbuf, "%d", protonum); return (nbuf);
- }
+ fprintf(file, ";; res options:");
+ for (mask = 1; mask != 0; mask <<= 1)
+ if (statp->options & mask)
+ fprintf(file, " %s", p_option(mask));
+ putc('\n', file);
}
-static const u_char *
-do_rrset(msg, len, cp, cnt, pflag, file, hs)
- int cnt, pflag, len;
- const u_char *cp, *msg;
- const char *hs;
- FILE *file;
+static void
+do_section(const res_state statp,
+ ns_msg *handle, ns_sect section,
+ int pflag, FILE *file)
{
- int n;
- int sflag;
+ int n, sflag, rrnum;
+ char buf[2048]; /* XXX need to malloc */
+ ns_opcode opcode;
+ ns_rr rr;
/*
* Print answer records.
*/
- sflag = (_res.pfcode & pflag);
- if ((n = ntohs(cnt))) {
- if ((!_res.pfcode) ||
- ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
- fprintf(file, hs);
- while (--n >= 0) {
- if ((!_res.pfcode) || sflag) {
- cp = p_rr(cp, msg, file);
- } else {
- unsigned int dlen;
- cp += __dn_skipname(cp, cp + MAXCDNAME);
- cp += INT16SZ;
- cp += INT16SZ;
- cp += INT32SZ;
- dlen = _getshort((u_char*)cp);
- cp += INT16SZ;
- cp += dlen;
+ sflag = (statp->pfcode & pflag);
+ if (statp->pfcode && !sflag)
+ return;
+
+ opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode);
+ rrnum = 0;
+ for (;;) {
+ if (ns_parserr(handle, section, rrnum, &rr)) {
+ if (errno != ENODEV)
+ fprintf(file, ";; ns_parserr: %s\n",
+ strerror(errno));
+ else if (rrnum > 0 && sflag != 0 &&
+ (statp->pfcode & RES_PRF_HEAD1))
+ putc('\n', file);
+ return;
+ }
+ if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1))
+ fprintf(file, ";; %s SECTION:\n",
+ p_section(section, opcode));
+ if (section == ns_s_qd)
+ fprintf(file, ";;\t%s, type = %s, class = %s\n",
+ ns_rr_name(rr),
+ p_type(ns_rr_type(rr)),
+ p_class(ns_rr_class(rr)));
+ else {
+ n = ns_sprintrr(handle, &rr, NULL, NULL,
+ buf, sizeof buf);
+ if (n < 0) {
+ fprintf(file, ";; ns_sprintrr: %s\n",
+ strerror(errno));
+ return;
}
- if ((cp - msg) > len)
- return (NULL);
+ fputs(buf, file);
+ fputc('\n', file);
}
- if ((!_res.pfcode) ||
- ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
- putc('\n', file);
+ rrnum++;
}
- return (cp);
-}
-
-void
-__p_query(msg)
- const u_char *msg;
-{
- __fp_query(msg, stdout);
-}
-
-#ifdef ultrix
-#undef p_query
-/* ultrix 4.0's packaging has some icky packaging. alias for it here.
- * there is more junk of this kind over in res_comp.c.
- */
-void
-p_query(msg)
- const u_char *msg;
-{
- __p_query(msg);
-}
-#endif
-
-/*
- * Print the current options.
- * This is intended to be primarily a debugging routine.
- */
-void
-__fp_resstat(statp, file)
- struct __res_state *statp;
- FILE *file;
-{
- register u_long mask;
-
- fprintf(file, ";; res options:");
- if (!statp)
- statp = &_res;
- for (mask = 1; mask != 0; mask <<= 1)
- if (statp->options & mask)
- fprintf(file, " %s", p_option(mask));
- putc('\n', file);
}
/*
@@ -271,147 +192,79 @@ __fp_resstat(statp, file)
* This is intended to be primarily a debugging routine.
*/
void
-__fp_nquery(msg, len, file)
- const u_char *msg;
- int len;
- FILE *file;
-{
- register const u_char *cp, *endMark;
- register const HEADER *hp;
- register int n;
+res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
+ ns_msg handle;
+ int qdcount, ancount, nscount, arcount;
+ u_int opcode, rcode, id;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ if (ns_initparse(msg, len, &handle) < 0) {
+ fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
return;
-
-#define TruncTest(x) if (x > endMark) goto trunc
-#define ErrorTest(x) if (x == NULL) goto error
+ }
+ opcode = ns_msg_getflag(handle, ns_f_opcode);
+ rcode = ns_msg_getflag(handle, ns_f_rcode);
+ id = ns_msg_id(handle);
+ qdcount = ns_msg_count(handle, ns_s_qd);
+ ancount = ns_msg_count(handle, ns_s_an);
+ nscount = ns_msg_count(handle, ns_s_ns);
+ arcount = ns_msg_count(handle, ns_s_ar);
/*
* Print header fields.
*/
- hp = (HEADER *)msg;
- cp = msg + HFIXEDSZ;
- endMark = msg + len;
- if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
- fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
- _res_opcodes[hp->opcode],
- _res_resultcodes[hp->rcode],
- ntohs(hp->id));
- putc('\n', file);
- }
- if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode)
+ fprintf(file,
+ ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
+ _res_opcodes[opcode], p_rcode(rcode), id);
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX))
putc(';', file);
- if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) {
fprintf(file, "; flags:");
- if (hp->qr)
+ if (ns_msg_getflag(handle, ns_f_qr))
fprintf(file, " qr");
- if (hp->aa)
+ if (ns_msg_getflag(handle, ns_f_aa))
fprintf(file, " aa");
- if (hp->tc)
+ if (ns_msg_getflag(handle, ns_f_tc))
fprintf(file, " tc");
- if (hp->rd)
+ if (ns_msg_getflag(handle, ns_f_rd))
fprintf(file, " rd");
- if (hp->ra)
+ if (ns_msg_getflag(handle, ns_f_ra))
fprintf(file, " ra");
- if (hp->unused)
- fprintf(file, " UNUSED-BIT-ON");
- if (hp->ad)
+ if (ns_msg_getflag(handle, ns_f_z))
+ fprintf(file, " ??");
+ if (ns_msg_getflag(handle, ns_f_ad))
fprintf(file, " ad");
- if (hp->cd)
+ if (ns_msg_getflag(handle, ns_f_cd))
fprintf(file, " cd");
}
- if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
- fprintf(file, "; Ques: %d", ntohs(hp->qdcount));
- fprintf(file, ", Ans: %d", ntohs(hp->ancount));
- fprintf(file, ", Auth: %d", ntohs(hp->nscount));
- fprintf(file, ", Addit: %d", ntohs(hp->arcount));
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) {
+ fprintf(file, "; %s: %d",
+ p_section(ns_s_qd, opcode), qdcount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_an, opcode), ancount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_ns, opcode), nscount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_ar, opcode), arcount);
}
- if ((!_res.pfcode) || (_res.pfcode &
+ if ((!statp->pfcode) || (statp->pfcode &
(RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
putc('\n',file);
}
/*
- * Print question records.
+ * Print the various sections.
*/
- if ((n = ntohs(hp->qdcount))) {
- if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
- fprintf(file, ";; QUESTIONS:\n");
- while (--n >= 0) {
- if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
- fprintf(file, ";;\t");
- TruncTest(cp);
- if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
- cp = p_cdnname(cp, msg, len, file);
- else {
- int n;
- char name[MAXDNAME];
-
- if ((n = dn_expand(msg, msg+len, cp, name,
- sizeof name)) < 0)
- cp = NULL;
- else
- cp += n;
- }
- ErrorTest(cp);
- TruncTest(cp);
- if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
- fprintf(file, ", type = %s",
- __p_type(_getshort((u_char*)cp)));
- cp += INT16SZ;
- TruncTest(cp);
- if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
- fprintf(file, ", class = %s\n",
- __p_class(_getshort((u_char*)cp)));
- cp += INT16SZ;
- if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
- putc('\n', file);
- }
- }
- /*
- * Print authoritative answer records
- */
- TruncTest(cp);
- cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
- ";; ANSWERS:\n");
- ErrorTest(cp);
-
- /*
- * print name server records
- */
- TruncTest(cp);
- cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
- ";; AUTHORITY RECORDS:\n");
- ErrorTest(cp);
-
- TruncTest(cp);
- /*
- * print additional records
- */
- cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
- ";; ADDITIONAL RECORDS:\n");
- ErrorTest(cp);
- return;
- trunc:
- fprintf(file, "\n;; ...truncated\n");
- return;
- error:
- fprintf(file, "\n;; ...malformed\n");
-}
-
-void
-__fp_query(msg, file)
- const u_char *msg;
- FILE *file;
-{
- fp_nquery(msg, PACKETSZ, file);
+ do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file);
+ do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file);
+ do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file);
+ do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file);
+ if (qdcount == 0 && ancount == 0 &&
+ nscount == 0 && arcount == 0)
+ putc('\n', file);
}
const u_char *
-__p_cdnname(cp, msg, len, file)
- const u_char *cp, *msg;
- int len;
- FILE *file;
-{
+p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
char name[MAXDNAME];
int n;
@@ -425,19 +278,15 @@ __p_cdnname(cp, msg, len, file)
}
const u_char *
-__p_cdname(cp, msg, file)
- const u_char *cp, *msg;
- FILE *file;
-{
+p_cdname(const u_char *cp, const u_char *msg, FILE *file) {
return (p_cdnname(cp, msg, PACKETSZ, file));
}
-
/* Return a fully-qualified domain name from a compressed name (with
length supplied). */
const u_char *
-__p_fqnname(cp, msg, msglen, name, namelen)
+p_fqnname(cp, msg, msglen, name, namelen)
const u_char *cp, *msg;
int msglen;
char *name;
@@ -447,9 +296,9 @@ __p_fqnname(cp, msg, msglen, name, namelen)
if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
return (NULL);
- newlen = strlen (name);
+ newlen = strlen(name);
if (newlen == 0 || name[newlen - 1] != '.') {
- if (newlen+1 >= namelen) /* Lack space for final dot */
+ if (newlen + 1 >= namelen) /* Lack space for final dot */
return (NULL);
else
strcpy(name + newlen, ".");
@@ -457,18 +306,14 @@ __p_fqnname(cp, msg, msglen, name, namelen)
return (cp + n);
}
-/* XXX: the rest of these functions need to become length-limited, too. (vix)
- */
+/* XXX: the rest of these functions need to become length-limited, too. */
const u_char *
-__p_fqname(cp, msg, file)
- const u_char *cp, *msg;
- FILE *file;
-{
+p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
char name[MAXDNAME];
const u_char *n;
- n = __p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
+ n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
if (n == NULL)
return (NULL);
fputs(name, file);
@@ -476,398 +321,6 @@ __p_fqname(cp, msg, file)
}
/*
- * Print resource record fields in human readable form.
- */
-const u_char *
-__p_rr(cp, msg, file)
- const u_char *cp, *msg;
- FILE *file;
-{
- int type, class, dlen, n, c;
- struct in_addr inaddr;
- const u_char *cp1, *cp2;
- u_int32_t tmpttl, t;
- int lcnt;
- u_int16_t keyflags;
- char rrname[MAXDNAME]; /* The fqdn of this RR */
- char base64_key[MAX_KEY_BASE64];
-
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
- __set_h_errno (NETDB_INTERNAL);
- return (NULL);
- }
- cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname);
- if (!cp)
- return (NULL); /* compression error */
- fputs(rrname, file);
-
- type = _getshort((u_char*)cp);
- cp += INT16SZ;
- class = _getshort((u_char*)cp);
- cp += INT16SZ;
- tmpttl = _getlong((u_char*)cp);
- cp += INT32SZ;
- dlen = _getshort((u_char*)cp);
- cp += INT16SZ;
- cp1 = cp;
- if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
- fprintf(file, "\t%lu", (u_long)tmpttl);
- if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS))
- fprintf(file, "\t%s", __p_class(class));
- fprintf(file, "\t%s", __p_type(type));
- /*
- * Print type specific data, if appropriate
- */
- switch (type) {
- case T_A:
- switch (class) {
- case C_IN:
- case C_HS:
- bcopy(cp, (char *)&inaddr, INADDRSZ);
- if (dlen == 4) {
- fprintf(file, "\t%s", inet_ntoa(inaddr));
- cp += dlen;
- } else if (dlen == 7) {
- char *address;
- u_char protocol;
- u_short port;
-
- address = inet_ntoa(inaddr);
- cp += INADDRSZ;
- protocol = *(u_char*)cp;
- cp += sizeof (u_char);
- port = _getshort((u_char*)cp);
- cp += INT16SZ;
- fprintf(file, "\t%s\t; proto %d, port %d",
- address, protocol, port);
- }
- break;
- default:
- cp += dlen;
- }
- break;
- case T_CNAME:
- case T_MB:
- case T_MG:
- case T_MR:
- case T_NS:
- case T_PTR:
- putc('\t', file);
- if ((cp = p_fqname(cp, msg, file)) == NULL)
- return (NULL);
- break;
-
- case T_HINFO:
- case T_ISDN:
- cp2 = cp + dlen;
- (void) fputs("\t\"", file);
- if ((n = (unsigned char) *cp++) != 0) {
- for (c = n; c > 0 && cp < cp2; c--) {
- if (strchr("\n\"\\", *cp))
- (void) putc('\\', file);
- (void) putc(*cp++, file);
- }
- }
- putc('"', file);
- if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
- (void) fputs ("\t\"", file);
- for (c = n; c > 0 && cp < cp2; c--) {
- if (strchr("\n\"\\", *cp))
- (void) putc('\\', file);
- (void) putc(*cp++, file);
- }
- putc('"', file);
- } else if (type == T_HINFO) {
- (void) fputs("\"?\"", file);
- fprintf(file, "\n;; *** Warning *** OS-type missing");
- }
- break;
-
- case T_SOA:
- putc('\t', file);
- if ((cp = p_fqname(cp, msg, file)) == NULL)
- return (NULL);
- putc(' ', file);
- if ((cp = p_fqname(cp, msg, file)) == NULL)
- return (NULL);
- fputs(" (\n", file);
- t = _getlong((u_char*)cp); cp += INT32SZ;
- fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
- t = _getlong((u_char*)cp); cp += INT32SZ;
- fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
- (u_long)t, __p_time(t));
- t = _getlong((u_char*)cp); cp += INT32SZ;
- fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
- (u_long)t, __p_time(t));
- t = _getlong((u_char*)cp); cp += INT32SZ;
- fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
- (u_long)t, __p_time(t));
- t = _getlong((u_char*)cp); cp += INT32SZ;
- fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
- (u_long)t, __p_time(t));
- break;
-
- case T_MX:
- case T_AFSDB:
- case T_RT:
- fprintf(file, "\t%d ", _getshort((u_char*)cp));
- cp += INT16SZ;
- if ((cp = p_fqname(cp, msg, file)) == NULL)
- return (NULL);
- break;
-
- case T_PX:
- fprintf(file, "\t%d ", _getshort((u_char*)cp));
- cp += INT16SZ;
- if ((cp = p_fqname(cp, msg, file)) == NULL)
- return (NULL);
- putc(' ', file);
- if ((cp = p_fqname(cp, msg, file)) == NULL)
- return (NULL);
- break;
-
- case T_X25:
- cp2 = cp + dlen;
- (void) fputs("\t\"", file);
- if ((n = (unsigned char) *cp++) != 0) {
- for (c = n; c > 0 && cp < cp2; c--) {
- if (strchr("\n\"\\", *cp))
- (void) putc('\\', file);
- (void) putc(*cp++, file);
- }
- }
- putc('"', file);
- break;
-
- case T_TXT:
- (void) putc('\t', file);
- cp2 = cp1 + dlen;
- while (cp < cp2) {
- putc('"', file);
- if ((n = (unsigned char) *cp++)) {
- for (c = n; c > 0 && cp < cp2; c--) {
- if (strchr("\n\"\\", *cp))
- (void) putc('\\', file);
- (void) putc(*cp++, file);
- }
- }
- putc('"', file);
- if (cp < cp2)
- putc(' ', file);
- }
- break;
-
- case T_NSAP:
- (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
- cp += dlen;
- break;
-
- case T_AAAA: {
- char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
-
- fprintf(file, "\t%s", inet_ntop(AF_INET6, cp, t, sizeof t));
- cp += dlen;
- break;
- }
-
- case T_LOC: {
- char t[255];
-
- (void) fprintf(file, "\t%s", loc_ntoa(cp, t));
- cp += dlen;
- break;
- }
-
- case T_NAPTR: {
- u_int order, preference;
-
- order = _getshort(cp); cp += INT16SZ;
- preference = _getshort(cp); cp += INT16SZ;
- fprintf(file, "\t%u %u ",order, preference);
- /* Flags */
- n = *cp++;
- fprintf(file,"\"%.*s\" ", (int)n, cp);
- cp += n;
- /* Service */
- n = *cp++;
- fprintf(file,"\"%.*s\" ", (int)n, cp);
- cp += n;
- /* Regexp */
- n = *cp++;
- fprintf(file,"\"%.*s\" ", (int)n, cp);
- cp += n;
- if ((cp = p_fqname(cp, msg, file)) == NULL)
- return (NULL);
- break;
- }
-
- case T_SRV: {
- u_int priority, weight, port;
-
- priority = _getshort(cp); cp += INT16SZ;
- weight = _getshort(cp); cp += INT16SZ;
- port = _getshort(cp); cp += INT16SZ;
- fprintf(file, "\t%u %u %u ", priority, weight, port);
- if ((cp = p_fqname(cp, msg, file)) == NULL)
- return (NULL);
- break;
- }
-
- case T_MINFO:
- case T_RP:
- putc('\t', file);
- if ((cp = p_fqname(cp, msg, file)) == NULL)
- return (NULL);
- putc(' ', file);
- if ((cp = p_fqname(cp, msg, file)) == NULL)
- return (NULL);
- break;
-
- case T_UINFO:
- putc('\t', file);
- fputs((char *)cp, file);
- cp += dlen;
- break;
-
- case T_UID:
- case T_GID:
- if (dlen == 4) {
- fprintf(file, "\t%u", _getlong((u_char*)cp));
- cp += INT32SZ;
- }
- break;
-
- case T_WKS:
- if (dlen < INT32SZ + 1)
- break;
- bcopy(cp, (char *)&inaddr, INADDRSZ);
- cp += INT32SZ;
- fprintf(file, "\t%s %s ( ",
- inet_ntoa(inaddr),
- deproto((int) *cp));
- cp += sizeof (u_char);
- n = 0;
- lcnt = 0;
- while (cp < cp1 + dlen) {
- c = *cp++;
- do {
- if (c & 0200) {
- if (lcnt == 0) {
- fputs("\n\t\t\t", file);
- lcnt = 5;
- }
- fputs(dewks(n), file);
- putc(' ', file);
- lcnt--;
- }
- c <<= 1;
- } while (++n & 07);
- }
- putc(')', file);
- break;
-
- case T_KEY:
- putc('\t', file);
- keyflags = _getshort(cp);
- cp += 2;
- fprintf(file,"0x%04x", keyflags ); /* flags */
- fprintf(file," %u", *cp++); /* protocol */
- fprintf(file," %u (", *cp++); /* algorithm */
-
- n = b64_ntop(cp, (cp1 + dlen) - cp,
- base64_key, sizeof base64_key);
- for (c = 0; c < n; ++c) {
- if (0 == (c & 0x3F))
- fprintf(file, "\n\t");
- putc(base64_key[c], file); /* public key data */
- }
-
- fprintf(file, " )");
- if (n < 0)
- fprintf(file, "\t; BAD BASE64");
- fflush(file);
- cp = cp1 + dlen;
- break;
-
- case T_SIG:
- type = _getshort((u_char*)cp);
- cp += INT16SZ;
- fprintf(file, " %s", p_type(type));
- fprintf(file, "\t%d", *cp++); /* algorithm */
- /* Check label value and print error if wrong. */
- n = *cp++;
- c = dn_count_labels (rrname);
- if (n != c)
- fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t",
- n, c);
- /* orig ttl */
- n = _getlong((u_char*)cp);
- if ((u_int32_t) n != tmpttl)
- fprintf(file, " %u", n);
- cp += INT32SZ;
- /* sig expire */
- fprintf(file, " (\n\t%s",
- __p_secstodate(_getlong((u_char*)cp)));
- cp += INT32SZ;
- /* time signed */
- fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp)));
- cp += INT32SZ;
- /* sig footprint */
- fprintf(file," %u ", _getshort((u_char*)cp));
- cp += INT16SZ;
- /* signer's name */
- cp = p_fqname(cp, msg, file);
- n = b64_ntop(cp, (cp1 + dlen) - cp,
- base64_key, sizeof base64_key);
- for (c = 0; c < n; c++) {
- if (0 == (c & 0x3F))
- fprintf (file, "\n\t");
- putc(base64_key[c], file); /* signature */
- }
- /* Clean up... */
- fprintf(file, " )");
- if (n < 0)
- fprintf(file, "\t; BAD BASE64");
- fflush(file);
- cp = cp1+dlen;
- break;
-
-#ifdef ALLOW_T_UNSPEC
- case T_UNSPEC:
- {
- int NumBytes = 8;
- u_char *DataPtr;
- int i;
-
- if (dlen < NumBytes) NumBytes = dlen;
- fprintf(file, "\tFirst %d bytes of hex data:",
- NumBytes);
- for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
- fprintf(file, " %x", *DataPtr);
- cp += dlen;
- }
- break;
-#endif /* ALLOW_T_UNSPEC */
-
- default:
- fprintf(file, "\t?%d?", type);
- cp += dlen;
- }
-#if 0
- fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
-#else
- putc('\n', file);
-#endif
- if (cp - cp1 != dlen) {
- fprintf(file,
- ";; packet size error (found %lu, dlen was %d)\n",
- (unsigned long) (cp - cp1), dlen);
- cp = NULL;
- }
- return (cp);
-}
-
-/*
* Names of RR classes and qclasses. Classes and qclasses are the same, except
* that C_ANY is a qclass but not a class. (You can ask for records of class
* C_ANY, but you can't have any records of that class in the database.)
@@ -878,7 +331,45 @@ const struct res_sym __p_class_syms[] = {
{C_HS, "HS"},
{C_HS, "HESIOD"},
{C_ANY, "ANY"},
- {C_IN, (char *)0}
+ {C_NONE, "NONE"},
+ {C_IN, (char *)0}
+};
+
+/*
+ * Names of message sections.
+ */
+const struct res_sym __p_default_section_syms[] = {
+ {ns_s_qd, "QUERY"},
+ {ns_s_an, "ANSWER"},
+ {ns_s_ns, "AUTHORITY"},
+ {ns_s_ar, "ADDITIONAL"},
+ {0, (char *)0}
+};
+
+const struct res_sym __p_update_section_syms[] = {
+ {S_ZONE, "ZONE"},
+ {S_PREREQ, "PREREQUISITE"},
+ {S_UPDATE, "UPDATE"},
+ {S_ADDT, "ADDITIONAL"},
+ {0, (char *)0}
+};
+
+const struct res_sym __p_key_syms[] = {
+ {NS_ALG_MD5RSA, "RSA", "RSA KEY with MD5 hash"},
+ {NS_ALG_DH, "DH", "Diffie Hellman"},
+ {NS_ALG_DSA, "DSA", "Digital Signature Algorithm"},
+ {NS_ALG_EXPIRE_ONLY, "EXPIREONLY", "No algorithm"},
+ {NS_ALG_PRIVATE_OID, "PRIVATE", "Algorithm obtained from OID"},
+ {0, NULL, NULL}
+};
+
+const struct res_sym __p_cert_syms[] = {
+ {cert_t_pkix, "PKIX", "PKIX (X.509v3) Certificate"},
+ {cert_t_spki, "SPKI", "SPKI certificate"},
+ {cert_t_pgp, "PGP", "PGP certificate"},
+ {cert_t_url, "URL", "URL Private"},
+ {cert_t_oid, "OID", "OID Private"},
+ {0, NULL, NULL}
};
/*
@@ -887,67 +378,78 @@ const struct res_sym __p_class_syms[] = {
* T_ANY, but you can't have any records of that type in the database.)
*/
const struct res_sym __p_type_syms[] = {
- {T_A, "A", "address"},
- {T_NS, "NS", "name server"},
- {T_MD, "MD", "mail destination (deprecated)"},
- {T_MF, "MF", "mail forwarder (deprecated)"},
- {T_CNAME, "CNAME", "canonical name"},
- {T_SOA, "SOA", "start of authority"},
- {T_MB, "MB", "mailbox"},
- {T_MG, "MG", "mail group member"},
- {T_MR, "MR", "mail rename"},
- {T_NULL, "NULL", "null"},
- {T_WKS, "WKS", "well-known service (deprecated)"},
- {T_PTR, "PTR", "domain name pointer"},
- {T_HINFO, "HINFO", "host information"},
- {T_MINFO, "MINFO", "mailbox information"},
- {T_MX, "MX", "mail exchanger"},
- {T_TXT, "TXT", "text"},
- {T_RP, "RP", "responsible person"},
- {T_AFSDB, "AFSDB", "DCE or AFS server"},
- {T_X25, "X25", "X25 address"},
- {T_ISDN, "ISDN", "ISDN address"},
- {T_RT, "RT", "router"},
- {T_NSAP, "NSAP", "nsap address"},
- {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"},
- {T_SIG, "SIG", "signature"},
- {T_KEY, "KEY", "key"},
- {T_PX, "PX", "mapping information"},
- {T_GPOS, "GPOS", "geographical position (withdrawn)"},
- {T_AAAA, "AAAA", "IPv6 address"},
- {T_LOC, "LOC", "location"},
- {T_NXT, "NXT", "next valid name (unimplemented)"},
- {T_EID, "EID", "endpoint identifier (unimplemented)"},
- {T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"},
- {T_SRV, "SRV", "server selection"},
- {T_ATMA, "ATMA", "ATM address (unimplemented)"},
- {T_IXFR, "IXFR", "incremental zone transfer"},
- {T_AXFR, "AXFR", "zone transfer"},
- {T_MAILB, "MAILB", "mailbox-related data (deprecated)"},
- {T_MAILA, "MAILA", "mail agent (deprecated)"},
- {T_UINFO, "UINFO", "user information (nonstandard)"},
- {T_UID, "UID", "user ID (nonstandard)"},
- {T_GID, "GID", "group ID (nonstandard)"},
- {T_NAPTR, "NAPTR", "URN Naming Authority"},
-#ifdef ALLOW_T_UNSPEC
- {T_UNSPEC, "UNSPEC", "unspecified data (nonstandard)"},
-#endif /* ALLOW_T_UNSPEC */
- {T_ANY, "ANY", "\"any\""},
- {0, NULL, NULL}
+ {ns_t_a, "A", "address"},
+ {ns_t_ns, "NS", "name server"},
+ {ns_t_md, "MD", "mail destination (deprecated)"},
+ {ns_t_mf, "MF", "mail forwarder (deprecated)"},
+ {ns_t_cname, "CNAME", "canonical name"},
+ {ns_t_soa, "SOA", "start of authority"},
+ {ns_t_mb, "MB", "mailbox"},
+ {ns_t_mg, "MG", "mail group member"},
+ {ns_t_mr, "MR", "mail rename"},
+ {ns_t_null, "NULL", "null"},
+ {ns_t_wks, "WKS", "well-known service (deprecated)"},
+ {ns_t_ptr, "PTR", "domain name pointer"},
+ {ns_t_hinfo, "HINFO", "host information"},
+ {ns_t_minfo, "MINFO", "mailbox information"},
+ {ns_t_mx, "MX", "mail exchanger"},
+ {ns_t_txt, "TXT", "text"},
+ {ns_t_rp, "RP", "responsible person"},
+ {ns_t_afsdb, "AFSDB", "DCE or AFS server"},
+ {ns_t_x25, "X25", "X25 address"},
+ {ns_t_isdn, "ISDN", "ISDN address"},
+ {ns_t_rt, "RT", "router"},
+ {ns_t_nsap, "NSAP", "nsap address"},
+ {ns_t_nsap_ptr, "NSAP_PTR", "domain name pointer"},
+ {ns_t_sig, "SIG", "signature"},
+ {ns_t_key, "KEY", "key"},
+ {ns_t_px, "PX", "mapping information"},
+ {ns_t_gpos, "GPOS", "geographical position (withdrawn)"},
+ {ns_t_aaaa, "AAAA", "IPv6 address"},
+ {ns_t_loc, "LOC", "location"},
+ {ns_t_nxt, "NXT", "next valid name (unimplemented)"},
+ {ns_t_eid, "EID", "endpoint identifier (unimplemented)"},
+ {ns_t_nimloc, "NIMLOC", "NIMROD locator (unimplemented)"},
+ {ns_t_srv, "SRV", "server selection"},
+ {ns_t_atma, "ATMA", "ATM address (unimplemented)"},
+ {ns_t_tsig, "TSIG", "transaction signature"},
+ {ns_t_ixfr, "IXFR", "incremental zone transfer"},
+ {ns_t_axfr, "AXFR", "zone transfer"},
+ {ns_t_zxfr, "ZXFR", "compressed zone transfer"},
+ {ns_t_mailb, "MAILB", "mailbox-related data (deprecated)"},
+ {ns_t_maila, "MAILA", "mail agent (deprecated)"},
+ {ns_t_naptr, "NAPTR", "URN Naming Authority"},
+ {ns_t_kx, "KX", "Key Exchange"},
+ {ns_t_cert, "CERT", "Certificate"},
+ {ns_t_any, "ANY", "\"any\""},
+ {0, NULL, NULL}
+};
+
+/*
+ * Names of DNS rcodes.
+ */
+const struct res_sym __p_rcode_syms[] = {
+ {ns_r_noerror, "NOERROR", "no error"},
+ {ns_r_formerr, "FORMERR", "format error"},
+ {ns_r_servfail, "SERVFAIL", "server failed"},
+ {ns_r_nxdomain, "NXDOMAIN", "no such domain name"},
+ {ns_r_notimpl, "NOTIMP", "not implemented"},
+ {ns_r_refused, "REFUSED", "refused"},
+ {ns_r_yxdomain, "YXDOMAIN", "domain name exists"},
+ {ns_r_yxrrset, "YXRRSET", "rrset exists"},
+ {ns_r_nxrrset, "NXRRSET", "rrset doesn't exist"},
+ {ns_r_notauth, "NOTAUTH", "not authoritative"},
+ {ns_r_notzone, "NOTZONE", "Not in zone"},
+ {ns_r_max, "", ""},
+ {ns_r_badsig, "BADSIG", "bad signature"},
+ {ns_r_badkey, "BADKEY", "bad key"},
+ {ns_r_badtime, "BADTIME", "bad time"},
+ {0, NULL, NULL}
};
int
-__sym_ston(syms, name, success)
- const struct res_sym *syms;
- char *name;
- int *success;
-{
-#ifdef _LIBC
- /* Changed to prevent warning. --drepper@gnu */
- for (; syms->name != 0; syms++) {
-#else
- for (NULL; syms->name != 0; syms++) {
-#endif
+sym_ston(const struct res_sym *syms, const char *name, int *success) {
+ for ((void)NULL; syms->name != 0; syms++) {
if (strcasecmp (name, syms->name) == 0) {
if (success)
*success = 1;
@@ -956,50 +458,41 @@ __sym_ston(syms, name, success)
}
if (success)
*success = 0;
- return (syms->number); /* The default value. */
+ return (syms->number); /* The default value. */
}
const char *
-__sym_ntos(syms, number, success)
- const struct res_sym *syms;
- int number;
- int *success;
-{
+sym_ntos(const struct res_sym *syms, int number, int *success) {
static char unname[20];
#ifdef _LIBC
/* Changed to prevent warning. --drepper@gnu */
for (; syms->name != 0; syms++) {
#else
- for (NULL; syms->name != 0; syms++) {
+ for ((void)NULL; syms->name != 0; syms++) {
#endif
- if (number == syms->number) {
+ if (number == syms->number) {
if (success)
*success = 1;
return (syms->name);
}
}
- sprintf (unname, "%d", number);
+ sprintf(unname, "%d", number); /* XXX nonreentrant */
if (success)
*success = 0;
return (unname);
}
-
const char *
-__sym_ntop(syms, number, success)
- const struct res_sym *syms;
- int number;
- int *success;
-{
+sym_ntop(const struct res_sym *syms, int number, int *success) {
static char unname[20];
#ifdef _LIBC
/* Changed to prevent warning. --drepper@gnu */
for (; syms->name != 0; syms++) {
#else
- for (NULL; syms->name != 0; syms++) {
+ for ((void)NULL; syms->name != 0; syms++) {
#endif
if (number == syms->number) {
if (success)
@@ -1007,39 +500,51 @@ __sym_ntop(syms, number, success)
return (syms->humanname);
}
}
- sprintf(unname, "%d", number);
+ sprintf(unname, "%d", number); /* XXX nonreentrant */
if (success)
*success = 0;
return (unname);
}
/*
- * Return a string for the type
+ * Return a string for the type.
*/
const char *
-__p_type(type)
- int type;
-{
- return (__sym_ntos (__p_type_syms, type, (int *)0));
+p_type(int type) {
+ return (sym_ntos(__p_type_syms, type, (int *)0));
}
/*
- * Return a mnemonic for class
+ * Return a string for the type.
*/
const char *
-__p_class(class)
- int class;
-{
- return (__sym_ntos (__p_class_syms, class, (int *)0));
+p_section(int section, int opcode) {
+ const struct res_sym *symbols;
+
+ switch (opcode) {
+ case ns_o_update:
+ symbols = __p_update_section_syms;
+ break;
+ default:
+ symbols = __p_default_section_syms;
+ break;
+ }
+ return (sym_ntos(symbols, section, (int *)0));
+}
+
+/*
+ * Return a mnemonic for class.
+ */
+const char *
+p_class(int class) {
+ return (sym_ntos(__p_class_syms, class, (int *)0));
}
/*
* Return a mnemonic for an option
*/
const char *
-__p_option(option)
- u_long option;
-{
+p_option(u_long option) {
static char nbuf[40];
switch (option) {
@@ -1055,63 +560,33 @@ __p_option(option)
case RES_DNSRCH: return "dnsrch";
case RES_INSECURE1: return "insecure1";
case RES_INSECURE2: return "insecure2";
+ /* XXX nonreentrant */
default: sprintf(nbuf, "?0x%lx?", (u_long)option);
return (nbuf);
}
}
/*
- * Return a mnemonic for a time to live
+ * Return a mnemonic for a time to live.
*/
const char *
-p_time(value)
- u_int32_t value;
-{
- static char nbuf[60];
- int secs, mins, hours, days;
- register char *p;
+p_time(u_int32_t value) {
+ static char nbuf[40]; /* XXX nonreentrant */
- if (value == 0) {
- strcpy(nbuf, "0 secs");
- return (nbuf);
- }
-
- secs = value % 60;
- value /= 60;
- mins = value % 60;
- value /= 60;
- hours = value % 24;
- value /= 24;
- days = value;
- value = 0;
-
-#define PLURALIZE(x) x, (x == 1) ? "" : "s"
- p = nbuf;
- if (days) {
- (void)sprintf(p, "%d day%s", PLURALIZE(days));
- while (*++p);
- }
- if (hours) {
- if (days)
- *p++ = ' ';
- (void)sprintf(p, "%d hour%s", PLURALIZE(hours));
- while (*++p);
- }
- if (mins) {
- if (days || hours)
- *p++ = ' ';
- (void)sprintf(p, "%d min%s", PLURALIZE(mins));
- while (*++p);
- }
- if (secs || ! (days || hours || mins)) {
- if (days || hours || mins)
- *p++ = ' ';
- (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
- }
+ if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0)
+ sprintf(nbuf, "%u", value);
return (nbuf);
}
/*
+ * Return a string for the rcode.
+ */
+const char *
+p_rcode(int rcode) {
+ return (sym_ntos(__p_rcode_syms, rcode, (int *)0));
+}
+
+/*
* routines to convert between on-the-wire RR format and zone file format.
* Does not contain conversion to/from decimal degrees; divide or multiply
* by 60*60*1000 for that.
@@ -1125,7 +600,7 @@ static const char *
precsize_ntoa(prec)
u_int8_t prec;
{
- static char retbuf[sizeof "90000000.00"];
+ static char retbuf[sizeof "90000000.00"]; /* XXX nonreentrant */
unsigned long val;
int mantissa, exponent;
@@ -1143,47 +618,40 @@ static u_int8_t
precsize_aton(strptr)
char **strptr;
{
+ unsigned int mval = 0, cmval = 0;
u_int8_t retval = 0;
char *cp;
- int exponent = 0;
- int mantissa = 0;
+ int exponent;
+ int mantissa;
cp = *strptr;
- while (isdigit(*cp)) {
- if (mantissa == 0)
- mantissa = *cp - '0';
- else
- exponent++;
- cp++;
- }
- if (*cp == '.') {
+ while (isdigit(*cp))
+ mval = mval * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* centimeters */
cp++;
if (isdigit(*cp)) {
- if (mantissa == 0)
- mantissa = *cp - '0';
- else
- exponent++;
- cp++;
-
+ cmval = (*cp++ - '0') * 10;
if (isdigit(*cp)) {
- if (mantissa == 0)
- mantissa = *cp - '0';
- else
- exponent++;
- cp++;
+ cmval += (*cp++ - '0');
}
- else
- exponent++;
}
}
- else
- exponent += 2;
+ cmval = (mval * 100) + cmval;
+
+ for (exponent = 0; exponent < 9; exponent++)
+ if (cmval < poweroften[exponent+1])
+ break;
+
+ mantissa = cmval / poweroften[exponent];
+ if (mantissa > 9)
+ mantissa = 9;
- if (mantissa == 0)
- exponent = 0;
retval = (mantissa << 4) | exponent;
+
*strptr = cp;
+
return (retval);
}
@@ -1193,7 +661,7 @@ latlon2ul(latlonstrptr,which)
char **latlonstrptr;
int *which;
{
- register char *cp;
+ char *cp;
u_int32_t retval;
int deg = 0, min = 0, secs = 0, secsfrac = 0;
@@ -1331,7 +799,7 @@ loc_aton(ascii, binary)
altsign = -1;
cp++;
}
-
+
if (*cp == '+')
cp++;
@@ -1360,7 +828,7 @@ loc_aton(ascii, binary)
goto defaults;
siz = precsize_aton(&cp);
-
+
while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
cp++;
@@ -1393,7 +861,7 @@ loc_aton(ascii, binary)
PUTLONG(latit,bcp);
PUTLONG(longit,bcp);
PUTLONG(alt,bcp);
-
+
return (16); /* size of RR in octets */
}
@@ -1404,25 +872,30 @@ loc_ntoa(binary, ascii)
char *ascii;
{
static char *error = "?";
- register const u_char *cp = binary;
+ static char tmpbuf[sizeof
+"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
+ const u_char *cp = binary;
int latdeg, latmin, latsec, latsecfrac;
int longdeg, longmin, longsec, longsecfrac;
char northsouth, eastwest;
int altmeters, altfrac, altsign;
- const int referencealt = 100000 * 100;
+ const u_int32_t referencealt = 100000 * 100;
int32_t latval, longval, altval;
u_int32_t templ;
u_int8_t sizeval, hpval, vpval, versionval;
-
+
char *sizestr, *hpstr, *vpstr;
versionval = *cp++;
+ if (ascii == NULL)
+ ascii = tmpbuf;
+
if (versionval) {
- sprintf(ascii, "; error: unknown LOC RR version");
+ (void) sprintf(ascii, "; error: unknown LOC RR version");
return (ascii);
}
@@ -1438,7 +911,7 @@ loc_ntoa(binary, ascii)
longval = (templ - ((unsigned)1<<31));
GETLONG(templ, cp);
- if (templ < (u_int32_t) referencealt) { /* below WGS 84 spheroid */
+ if (templ < referencealt) { /* below WGS 84 spheroid */
altval = referencealt - templ;
altsign = -1;
} else {
@@ -1503,14 +976,12 @@ loc_ntoa(binary, ascii)
/* Return the number of DNS hierarchy levels in the name. */
int
-__dn_count_labels(name)
- char *name;
-{
+dn_count_labels(const char *name) {
int i, len, count;
len = strlen(name);
-
- for(i = 0, count = 0; i < len; i++) {
+ for (i = 0, count = 0; i < len; i++) {
+ /* XXX need to check for \. or use named's nlabels(). */
if (name[i] == '.')
count++;
}
@@ -1529,23 +1000,28 @@ __dn_count_labels(name)
}
-/*
- * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
+/*
+ * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
* SIG records are required to be printed like this, by the Secure DNS RFC.
*/
char *
-__p_secstodate (secs)
- unsigned long secs;
-{
- static char output[15]; /* YYYYMMDDHHMMSS and null */
+p_secstodate (u_long secs) {
+ /* XXX nonreentrant */
+ static char output[15]; /* YYYYMMDDHHMMSS and null */
time_t clock = secs;
- struct tm time;
-
- __gmtime_r(&clock, &time);
- time.tm_year += 1900;
- time.tm_mon += 1;
+ struct tm *time;
+
+#ifdef HAVE_TIME_R
+ struct time timebuf;
+
+ time = gmtime_r(&clock, &timebuf);
+#else
+ time = gmtime(&clock);
+#endif
+ time->tm_year += 1900;
+ time->tm_mon += 1;
sprintf(output, "%04d%02d%02d%02d%02d%02d",
- time.tm_year, time.tm_mon, time.tm_mday,
- time.tm_hour, time.tm_min, time.tm_sec);
+ time->tm_year, time->tm_mon, time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec);
return (output);
}
diff --git a/resolv/res_debug.h b/resolv/res_debug.h
new file mode 100644
index 0000000000..4a0aa99ab4
--- /dev/null
+++ b/resolv/res_debug.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef _RES_DEBUG_H_
+#define _RES_DEBUG_H_
+
+#ifndef DEBUG
+# define Dprint(cond, args) /*empty*/
+# define DprintQ(cond, args, query, size) /*empty*/
+# define Aerror(statp, file, string, error, address) /*empty*/
+# define Perror(statp, file, string, error) /*empty*/
+#else
+# define Dprint(cond, args) if (cond) {fprintf args;} else {}
+# define DprintQ(cond, args, query, size) if (cond) {\
+ fprintf args;\
+ res_pquery(statp, query, size, stdout);\
+ } else {}
+#endif
+
+#endif /* _RES_DEBUG_H_ */
diff --git a/resolv/res_init.c b/resolv/res_init.c
index e5520ff65e..bf6cf7f7b1 100644
--- a/resolv/res_init.c
+++ b/resolv/res_init.c
@@ -1,6 +1,4 @@
/*
- * ++Copyright++ 1985, 1989, 1993
- * -
* Copyright (c) 1985, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -27,7 +25,9 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- * -
+ */
+
+/*
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
@@ -45,68 +45,55 @@
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
- * -
- * --Copyright--
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
-static char rcsid[] = "$Id$";
+static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
+static const char rcsid[] = "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/time.h>
+
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
-#include <stdio.h>
#include <ctype.h>
#include <resolv.h>
-#if defined(BSD) && (BSD >= 199103)
-# include <unistd.h>
-# include <stdlib.h>
-# include <string.h>
-#else
-# include "../conf/portability.h"
-#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
-/*-------------------------------------- info about "sortlist" --------------
- * Marc Majka 1994/04/16
- * Allan Nathanson 1994/10/29 (BIND 4.9.3.x)
- *
- * NetInfo resolver configuration directory support.
- *
- * Allow a NetInfo directory to be created in the hierarchy which
- * contains the same information as the resolver configuration file.
- *
- * - The local domain name is stored as the value of the "domain" property.
- * - The Internet address(es) of the name server(s) are stored as values
- * of the "nameserver" property.
- * - The name server addresses are stored as values of the "nameserver"
- * property.
- * - The search list for host-name lookup is stored as values of the
- * "search" property.
- * - The sortlist comprised of IP address netmask pairs are stored as
- * values of the "sortlist" property. The IP address and optional netmask
- * should be separated by a slash (/) or ampersand (&) character.
- * - Internal resolver variables can be set from the value of the "options"
- * property.
- */
-#if defined(NeXT)
-# include <netinfo/ni.h>
-# define NI_PATH_RESCONF "/locations/resolver"
-# define NI_TIMEOUT 10
-static int netinfo_res_init __P((int *haveenv, int *havesearch));
-#endif
+/* Options. Should all be left alone. */
+#define RESOLVSORT
+#define RFC1535
+#undef DEBUG
-#if defined(USE_OPTIONS_H)
-# include "../conf/options.h"
-#endif
+static void
+res_setoptions (res_state statp, const char *options, const char *source)
+ internal_function;
-static void res_setoptions __P((char *, char *)) internal_function;
#ifdef RESOLVSORT
static const char sort_mask[] = "/&";
@@ -122,12 +109,6 @@ static u_int32_t net_mask __P((struct in_addr));
* Resolver state default settings.
*/
-struct __res_state _res
-# if defined(__BIND_RES_TEXT)
- = { RES_TIMEOUT, } /* Motorola, et al. */
-# endif
- ;
-
/*
* Set up default settings. If the configuration file exist, the values
* there will have precedence. Otherwise, the server address is set to
@@ -138,7 +119,7 @@ struct __res_state _res
* since it was noted that INADDR_ANY actually meant ``the first interface
* you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
* it had to be "up" in order for you to reach your own name server. It
- * was later decided that since the recommended practice is to always
+ * was later decided that since the recommended practice is to always
* install local static routes through 127.0.0.1 for all your network
* interfaces, that we could solve this problem without a code change.
*
@@ -150,12 +131,19 @@ struct __res_state _res
* Return 0 if completes successfully, -1 on error
*/
int
-res_init()
-{
+res_ninit(res_state statp) {
+ extern int __res_vinit(res_state, int);
+
+ return (__res_vinit(statp, 0));
+}
+
+/* This function has to be reachable by res_data.c but not publically. */
+int
+__res_vinit(res_state statp, int preinit) {
register FILE *fp;
register char *cp, **pp;
register int n;
- char buf[MAXDNAME];
+ char buf[BUFSIZ];
int nserv = 0; /* number of nameserver records read from file */
int haveenv = 0;
int havesearch = 0;
@@ -167,54 +155,32 @@ res_init()
int dots;
#endif
- /*
- * These three fields used to be statically initialized. This made
- * it hard to use this code in a shared library. It is necessary,
- * now that we're doing dynamic initialization here, that we preserve
- * the old semantics: if an application modifies one of these three
- * fields of _res before res_init() is called, res_init() will not
- * alter them. Of course, if an application is setting them to
- * _zero_ before calling res_init(), hoping to override what used
- * to be the static default, we can't detect it and unexpected results
- * will follow. Zero for any of these fields would make no sense,
- * so one can safely assume that the applications were already getting
- * unexpected results.
- *
- * _res.options is tricky since some apps were known to diddle the bits
- * before res_init() was first called. We can't replicate that semantic
- * with dynamic initialization (they may have turned bits off that are
- * set in RES_DEFAULT). Our solution is to declare such applications
- * "broken". They could fool us by setting RES_INIT but none do (yet).
- */
- if (!_res.retrans)
- _res.retrans = RES_TIMEOUT;
- if (!_res.retry)
- _res.retry = 4;
- if (!(_res.options & RES_INIT))
- _res.options = RES_DEFAULT;
-
- /*
- * This one used to initialize implicitly to zero, so unless the app
- * has set it to something in particular, we can randomize it now.
- */
- if (!_res.id)
- _res.id = res_randomid();
+ if (!preinit) {
+ statp->retrans = RES_TIMEOUT;
+ statp->retry = RES_DFLRETRY;
+ statp->options = RES_DEFAULT;
+ statp->id = res_randomid();
+ }
#ifdef USELOOPBACK
- _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
- _res.nscount = 1;
+ statp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
#else
- _res.nsaddr.sin_addr.s_addr = INADDR_ANY;
- _res.nscount = 0;
+ statp->nsaddr.sin_addr.s_addr = INADDR_ANY;
#endif
- _res.nsaddr.sin_family = AF_INET;
- _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
- _res.ndots = 1;
- _res.pfcode = 0;
+ statp->nsaddr.sin_family = AF_INET;
+ statp->nsaddr.sin_port = htons(NAMESERVER_PORT);
+ statp->nscount = 1;
+ statp->ndots = 1;
+ statp->pfcode = 0;
+ statp->_sock = -1;
+ statp->_flags = 0;
+ statp->qhook = NULL;
+ statp->rhook = NULL;
/* Allow user to override the local domain definition */
if ((cp = __secure_getenv("LOCALDOMAIN")) != NULL) {
- (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
+ (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
+ statp->defdname[sizeof(statp->defdname) - 1] = '\0';
haveenv++;
/*
@@ -224,10 +190,10 @@ res_init()
* one that they want to use as an individual (even more
* important now that the rfc1535 stuff restricts searches)
*/
- cp = _res.defdname;
- pp = _res.dnsrch;
+ cp = statp->defdname;
+ pp = statp->dnsrch;
*pp++ = cp;
- for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
+ for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
if (*cp == '\n') /* silly backwards compat */
break;
else if (*cp == ' ' || *cp == '\t') {
@@ -251,9 +217,6 @@ res_init()
(line[sizeof(name) - 1] == ' ' || \
line[sizeof(name) - 1] == '\t'))
-#ifdef NeXT
- if (netinfo_res_init(&haveenv, &havesearch) == 0)
-#endif
if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
/* read the config file */
while (fgets_unlocked(buf, sizeof(buf), fp) != NULL) {
@@ -269,8 +232,9 @@ res_init()
cp++;
if ((*cp == '\0') || (*cp == '\n'))
continue;
- strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
- if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
+ strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
+ statp->defdname[sizeof(statp->defdname) - 1] = '\0';
+ if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
*cp = '\0';
havesearch = 0;
continue;
@@ -284,16 +248,18 @@ res_init()
cp++;
if ((*cp == '\0') || (*cp == '\n'))
continue;
- strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
- *__strchrnul (_res.defdname, '\n') = '\0';
+ strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
+ statp->defdname[sizeof(statp->defdname) - 1] = '\0';
+ if ((cp = strchr(statp->defdname, '\n')) != NULL)
+ *cp = '\0';
/*
* Set search list to be blank-separated strings
* on rest of line.
*/
- cp = _res.defdname;
- pp = _res.dnsrch;
+ cp = statp->defdname;
+ pp = statp->dnsrch;
*pp++ = cp;
- for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
+ for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
if (*cp == ' ' || *cp == '\t') {
*cp = 0;
n = 1;
@@ -318,9 +284,9 @@ res_init()
while (*cp == ' ' || *cp == '\t')
cp++;
if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
- _res.nsaddr_list[nserv].sin_addr = a;
- _res.nsaddr_list[nserv].sin_family = AF_INET;
- _res.nsaddr_list[nserv].sin_port =
+ statp->nsaddr_list[nserv].sin_addr = a;
+ statp->nsaddr_list[nserv].sin_family = AF_INET;
+ statp->nsaddr_list[nserv].sin_port =
htons(NAMESERVER_PORT);
nserv++;
}
@@ -343,7 +309,7 @@ res_init()
n = *cp;
*cp = 0;
if (inet_aton(net, &a)) {
- _res.sort_list[nsort].addr = a;
+ statp->sort_list[nsort].addr = a;
if (ISSORTMASK(n)) {
*cp++ = n;
net = cp;
@@ -353,14 +319,14 @@ res_init()
n = *cp;
*cp = 0;
if (inet_aton(net, &a)) {
- _res.sort_list[nsort].mask = a.s_addr;
+ statp->sort_list[nsort].mask = a.s_addr;
} else {
- _res.sort_list[nsort].mask =
- net_mask(_res.sort_list[nsort].addr);
+ statp->sort_list[nsort].mask =
+ net_mask(statp->sort_list[nsort].addr);
}
} else {
- _res.sort_list[nsort].mask =
- net_mask(_res.sort_list[nsort].addr);
+ statp->sort_list[nsort].mask =
+ net_mask(statp->sort_list[nsort].addr);
}
nsort++;
}
@@ -370,35 +336,35 @@ res_init()
}
#endif
if (MATCH(buf, "options")) {
- res_setoptions(buf + sizeof("options") - 1, "conf");
+ res_setoptions(statp, buf + sizeof("options") - 1, "conf");
continue;
}
}
- if (nserv > _res.nscount)
- _res.nscount = nserv;
+ if (nserv > 1)
+ statp->nscount = nserv;
#ifdef RESOLVSORT
- _res.nsort = nsort;
+ statp->nsort = nsort;
#endif
(void) fclose(fp);
}
- if (_res.defdname[0] == 0 &&
- __gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
+ if (statp->defdname[0] == 0 &&
+ __gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
(cp = strchr(buf, '.')) != NULL)
- strcpy(_res.defdname, cp + 1);
+ strcpy(statp->defdname, cp + 1);
/* find components of local domain that might be searched */
if (havesearch == 0) {
- pp = _res.dnsrch;
- *pp++ = _res.defdname;
+ pp = statp->dnsrch;
+ *pp++ = statp->defdname;
*pp = NULL;
#ifndef RFC1535
dots = 0;
- for (cp = _res.defdname; *cp; cp++)
+ for (cp = statp->defdname; *cp; cp++)
dots += (*cp == '.');
- cp = _res.defdname;
- while (pp < _res.dnsrch + MAXDFLSRCH) {
+ cp = statp->defdname;
+ while (pp < statp->dnsrch + MAXDFLSRCH) {
if (dots < LOCALDOMAINPARTS)
break;
cp = __rawmemchr(cp, '.') + 1; /* we know there is one */
@@ -407,32 +373,31 @@ res_init()
}
*pp = NULL;
#ifdef DEBUG
- if (_res.options & RES_DEBUG) {
+ if (statp->options & RES_DEBUG) {
printf(";; res_init()... default dnsrch list:\n");
- for (pp = _res.dnsrch; *pp; pp++)
+ for (pp = statp->dnsrch; *pp; pp++)
printf(";;\t%s\n", *pp);
printf(";;\t..END..\n");
}
-#endif /* DEBUG */
+#endif
#endif /* !RFC1535 */
}
if ((cp = __secure_getenv("RES_OPTIONS")) != NULL)
- res_setoptions(cp, "env");
- _res.options |= RES_INIT;
+ res_setoptions(statp, cp, "env");
+ statp->options |= RES_INIT;
return (0);
}
static void
internal_function
-res_setoptions(options, source)
- char *options, *source;
+res_setoptions(res_state statp, const char *options, const char *source)
{
- char *cp = options;
+ const char *cp = options;
int i;
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
+ if (statp->options & RES_DEBUG)
printf(";; res_setoptions(\"%s\", \"%s\")...\n",
options, source);
#endif
@@ -444,24 +409,41 @@ res_setoptions(options, source)
if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
i = atoi(cp + sizeof("ndots:") - 1);
if (i <= RES_MAXNDOTS)
- _res.ndots = i;
+ statp->ndots = i;
else
- _res.ndots = RES_MAXNDOTS;
+ statp->ndots = RES_MAXNDOTS;
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
- printf(";;\tndots=%d\n", _res.ndots);
+ if (statp->options & RES_DEBUG)
+ printf(";;\tndots=%d\n", statp->ndots);
#endif
+ } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
+ i = atoi(cp + sizeof("timeout:") - 1);
+ if (i <= RES_MAXRETRANS)
+ statp->retrans = i;
+ else
+ statp->retrans = RES_MAXRETRANS;
+ } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
+ i = atoi(cp + sizeof("attempts:") - 1);
+ if (i <= RES_MAXRETRY)
+ statp->retry = i;
+ else
+ statp->retry = RES_MAXRETRY;
} else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
#ifdef DEBUG
- if (!(_res.options & RES_DEBUG)) {
+ if (!(statp->options & RES_DEBUG)) {
printf(";; res_setoptions(\"%s\", \"%s\")..\n",
options, source);
- _res.options |= RES_DEBUG;
+ statp->options |= RES_DEBUG;
}
printf(";;\tdebug\n");
#endif
} else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
- _res.options |= RES_USE_INET6;
+ statp->options |= RES_USE_INET6;
+ } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
+ statp->options |= RES_ROTATE;
+ } else if (!strncmp(cp, "no-check-names",
+ sizeof("no-check-names") - 1)) {
+ statp->options |= RES_NOCHECKNAME;
} else {
/* XXX - print a warning here? */
}
@@ -487,164 +469,8 @@ net_mask(in) /* XXX - should really use system's version of this */
}
#endif
-#ifdef NeXT
-static int
-netinfo_res_init(haveenv, havesearch)
- int *haveenv;
- int *havesearch;
-{
- register int n;
- void *domain, *parent;
- ni_id dir;
- ni_status status;
- ni_namelist nl;
- int nserv = 0;
-#ifdef RESOLVSORT
- int nsort = 0;
-#endif
-
- status = ni_open(NULL, ".", &domain);
- if (status == NI_OK) {
- ni_setreadtimeout(domain, NI_TIMEOUT);
- ni_setabort(domain, 1);
-
- /* climb the NetInfo hierarchy to find a resolver directory */
- while (status == NI_OK) {
- status = ni_pathsearch(domain, &dir, NI_PATH_RESCONF);
- if (status == NI_OK) {
- /* found a resolver directory */
-
- if (*haveenv == 0) {
- /* get the default domain name */
- status = ni_lookupprop(domain, &dir, "domain", &nl);
- if (status == NI_OK && nl.ni_namelist_len > 0) {
- (void)strncpy(_res.defdname,
- nl.ni_namelist_val[0],
- sizeof(_res.defdname) - 1);
- _res.defdname[sizeof(_res.defdname) - 1] = '\0';
- ni_namelist_free(&nl);
- *havesearch = 0;
- }
-
- /* get search list */
- status = ni_lookupprop(domain, &dir, "search", &nl);
- if (status == NI_OK && nl.ni_namelist_len > 0) {
- (void)strncpy(_res.defdname,
- nl.ni_namelist_val[0],
- sizeof(_res.defdname) - 1);
- _res.defdname[sizeof(_res.defdname) - 1] = '\0';
- /* copy */
- for (n = 0;
- n < nl.ni_namelist_len && n < MAXDNSRCH;
- n++) {
- /* duplicate up to MAXDNSRCH servers */
- char *cp = nl.ni_namelist_val[n];
- _res.dnsrch[n] =
- strcpy((char *)malloc(strlen(cp) + 1), cp);
- }
- ni_namelist_free(&nl);
- *havesearch = 1;
- }
- }
-
- /* get list of nameservers */
- status = ni_lookupprop(domain, &dir, "nameserver", &nl);
- if (status == NI_OK && nl.ni_namelist_len > 0) {
- /* copy up to MAXNS servers */
- for (n = 0;
- n < nl.ni_namelist_len && nserv < MAXNS;
- n++) {
- struct in_addr a;
-
- if (inet_aton(nl.ni_namelist_val[n], &a)) {
- _res.nsaddr_list[nserv].sin_addr = a;
- _res.nsaddr_list[nserv].sin_family = AF_INET;
- _res.nsaddr_list[nserv].sin_port =
- htons(NAMESERVER_PORT);
- nserv++;
- }
- }
- ni_namelist_free(&nl);
- }
-
- if (nserv > _res.nscount)
- _res.nscount = nserv;
-
-#ifdef RESOLVSORT
- /* get sort order */
- status = ni_lookupprop(domain, &dir, "sortlist", &nl);
- if (status == NI_OK && nl.ni_namelist_len > 0) {
-
- /* copy up to MAXRESOLVSORT address/netmask pairs */
- for (n = 0;
- n < nl.ni_namelist_len && nsort < MAXRESOLVSORT;
- n++) {
- char ch;
- char *cp;
- const char *sp;
- struct in_addr a;
-
- cp = NULL;
- for (sp = sort_mask; *sp; sp++) {
- char *cp1;
- cp1 = strchr(nl.ni_namelist_val[n], *sp);
- if (cp && cp1)
- cp = (cp < cp1)? cp : cp1;
- else if (cp1)
- cp = cp1;
- }
- if (cp != NULL) {
- ch = *cp;
- *cp = '\0';
- break;
- }
- if (inet_aton(nl.ni_namelist_val[n], &a)) {
- _res.sort_list[nsort].addr = a;
- if (*cp && ISSORTMASK(ch)) {
- *cp++ = ch;
- if (inet_aton(cp, &a)) {
- _res.sort_list[nsort].mask = a.s_addr;
- } else {
- _res.sort_list[nsort].mask =
- net_mask(_res.sort_list[nsort].addr);
- }
- } else {
- _res.sort_list[nsort].mask =
- net_mask(_res.sort_list[nsort].addr);
- }
- nsort++;
- }
- }
- ni_namelist_free(&nl);
- }
-
- _res.nsort = nsort;
-#endif
-
- /* get resolver options */
- status = ni_lookupprop(domain, &dir, "options", &nl);
- if (status == NI_OK && nl.ni_namelist_len > 0) {
- res_setoptions(nl.ni_namelist_val[0], "conf");
- ni_namelist_free(&nl);
- }
-
- ni_free(domain);
- return(1); /* using DNS configuration from NetInfo */
- }
-
- status = ni_open(domain, "..", &parent);
- ni_free(domain);
- if (status == NI_OK)
- domain = parent;
- }
- }
- return(0); /* if not using DNS configuration from NetInfo */
-}
-#endif /* NeXT */
-
u_int
-res_randomid()
-{
+res_randomid(void) {
struct timeval now;
__gettimeofday(&now, NULL);
diff --git a/resolv/res_libc.c b/resolv/res_libc.c
new file mode 100644
index 0000000000..14d565df0d
--- /dev/null
+++ b/resolv/res_libc.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1995-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/* Define some functions that go int libc.so. */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#undef _res
+
+struct __res_state _res;
+
+/* This is the old res_init function. It has been moved from
+ res_data.c to this file since res_init should go into libc.so but
+ the rest of res_data not. */
+
+
+int
+res_init(void) {
+ extern int __res_vinit(res_state, int);
+
+ /*
+ * These three fields used to be statically initialized. This made
+ * it hard to use this code in a shared library. It is necessary,
+ * now that we're doing dynamic initialization here, that we preserve
+ * the old semantics: if an application modifies one of these three
+ * fields of _res before res_init() is called, res_init() will not
+ * alter them. Of course, if an application is setting them to
+ * _zero_ before calling res_init(), hoping to override what used
+ * to be the static default, we can't detect it and unexpected results
+ * will follow. Zero for any of these fields would make no sense,
+ * so one can safely assume that the applications were already getting
+ * unexpected results.
+ *
+ * _res.options is tricky since some apps were known to diddle the bits
+ * before res_init() was first called. We can't replicate that semantic
+ * with dynamic initialization (they may have turned bits off that are
+ * set in RES_DEFAULT). Our solution is to declare such applications
+ * "broken". They could fool us by setting RES_INIT but none do (yet).
+ */
+ if (!_res.retrans)
+ _res.retrans = RES_TIMEOUT;
+ if (!_res.retry)
+ _res.retry = 4;
+ if (!(_res.options & RES_INIT))
+ _res.options = RES_DEFAULT;
+
+ /*
+ * This one used to initialize implicitly to zero, so unless the app
+ * has set it to something in particular, we can randomize it now.
+ */
+ if (!_res.id)
+ _res.id = res_randomid();
+
+ return (__res_vinit(&_res, 1));
+}
+
+/* We need a resolver context - in unthreaded apps, this weak function
+ provides it. */
+
+struct __res_state *
+weak_const_function
+__res_state(void)
+{
+ return &_res;
+}
diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c
index 8f3e66fff9..dba2c80e26 100644
--- a/resolv/res_mkquery.c
+++ b/resolv/res_mkquery.c
@@ -1,6 +1,4 @@
/*
- * ++Copyright++ 1985, 1993
- * -
* Copyright (c) 1985, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -27,7 +25,9 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- * -
+ */
+
+/*
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
@@ -45,72 +45,79 @@
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
- * -
- * --Copyright--
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id$";
+static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
-
-#include <stdio.h>
#include <netdb.h>
#include <resolv.h>
-#if defined(BSD) && (BSD >= 199103)
-# include <string.h>
-#else
-# include "../conf/portability.h"
-#endif
+#include <stdio.h>
+#include <string.h>
-#if defined(USE_OPTIONS_H)
-# include <../conf/options.h>
-#endif
+/* Options. Leave them on. */
+/* #define DEBUG */
+
+extern const char *_res_opcodes[];
/*
* Form all types of queries.
* Returns the size of the result or -1.
*/
int
-res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
- int op; /* opcode of query */
- const char *dname; /* domain name */
- int class, type; /* class and type of query */
- const u_char *data; /* resource record data */
- int datalen; /* length of data */
- const u_char *newrr_in; /* new rr for modify or append */
- u_char *buf; /* buffer to put query */
- int buflen; /* size of buffer */
+res_nmkquery(res_state statp,
+ int op, /* opcode of query */
+ const char *dname, /* domain name */
+ int class, int type, /* class and type of query */
+ const u_char *data, /* resource record data */
+ int datalen, /* length of data */
+ const u_char *newrr_in, /* new rr for modify or append */
+ u_char *buf, /* buffer to put query */
+ int buflen) /* size of buffer */
{
register HEADER *hp;
register u_char *cp;
register int n;
u_char *dnptrs[20], **dpp, **lastdnptr;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
- __set_h_errno (NETDB_INTERNAL);
- return (-1);
- }
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
- printf(";; res_mkquery(%d, %s, %d, %d)\n",
- op, dname, class, type);
+ if (statp->options & RES_DEBUG)
+ printf(";; res_nmkquery(%s, %s, %s, %s)\n",
+ _res_opcodes[op], dname, p_class(class), p_type(type));
#endif
/*
* Initialize header fields.
*/
if ((buf == NULL) || (buflen < HFIXEDSZ))
return (-1);
- bzero(buf, HFIXEDSZ);
+ memset(buf, 0, HFIXEDSZ);
hp = (HEADER *) buf;
- hp->id = htons(++_res.id);
+ hp->id = htons(++statp->id);
hp->opcode = op;
- hp->rd = (_res.options & RES_RECURSE) != 0;
+ hp->rd = (statp->options & RES_RECURSE) != 0;
hp->rcode = NOERROR;
cp = buf + HFIXEDSZ;
buflen -= HFIXEDSZ;
@@ -173,7 +180,7 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
__putshort(datalen, cp);
cp += INT16SZ;
if (datalen) {
- bcopy(data, cp, datalen);
+ memcpy(cp, data, datalen);
cp += datalen;
}
hp->ancount = htons(1);
diff --git a/resolv/res_query.c b/resolv/res_query.c
index 80c10344f9..deebf4c62b 100644
--- a/resolv/res_query.c
+++ b/resolv/res_query.c
@@ -1,6 +1,4 @@
/*
- * ++Copyright++ 1988, 1993
- * -
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -27,7 +25,9 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- * -
+ */
+
+/*
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
@@ -45,13 +45,28 @@
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
- * -
- * --Copyright--
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id$";
+static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id$";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@@ -59,22 +74,16 @@ static char rcsid[] = "$Id$";
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
-
-#include <stdio.h>
-#include <netdb.h>
-#include <resolv.h>
#include <ctype.h>
#include <errno.h>
-#if defined(BSD) && (BSD >= 199306)
-# include <stdlib.h>
-# include <string.h>
-#else
-# include "../conf/portability.h"
-#endif
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
-#if defined(USE_OPTIONS_H)
-# include <../conf/options.h>
-#endif
+/* Options. Leave them on. */
+/* #undef DEBUG */
#if PACKETSZ > 1024
#define MAXPACKET PACKETSZ
@@ -82,82 +91,75 @@ static char rcsid[] = "$Id$";
#define MAXPACKET 1024
#endif
-const char *hostalias __P((const char *));
-
-
/*
* Formulate a normal query, send, and await answer.
* Returned answer is placed in supplied buffer "answer".
* Perform preliminary check of answer, returning success only
* if no error is indicated and the answer count is nonzero.
* Return the size of the response on success, -1 on error.
- * Error number is left in h_errno.
+ * Error number is left in H_ERRNO.
*
* Caller must parse answer and determine whether it answers the question.
*/
int
-res_query(name, class, type, answer, anslen)
- const char *name; /* domain name */
- int class, type; /* class and type of query */
- u_char *answer; /* buffer to put answer */
- int anslen; /* size of answer buffer */
+res_nquery(res_state statp,
+ const char *name, /* domain name */
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen) /* size of answer buffer */
{
u_char buf[MAXPACKET];
- register HEADER *hp = (HEADER *) answer;
+ HEADER *hp = (HEADER *) answer;
int n;
hp->rcode = NOERROR; /* default */
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
- __set_h_errno (NETDB_INTERNAL);
- return (-1);
- }
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
+ if (statp->options & RES_DEBUG)
printf(";; res_query(%s, %d, %d)\n", name, class, type);
#endif
- n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
- buf, sizeof(buf));
+ n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
+ buf, sizeof(buf));
if (n <= 0) {
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
+ if (statp->options & RES_DEBUG)
printf(";; res_query: mkquery failed\n");
#endif
- __set_h_errno (NO_RECOVERY);
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
return (n);
}
- n = res_send(buf, n, answer, anslen);
+ n = res_nsend(statp, buf, n, answer, anslen);
if (n < 0) {
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
+ if (statp->options & RES_DEBUG)
printf(";; res_query: send error\n");
#endif
- __set_h_errno (TRY_AGAIN);
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
return (n);
}
if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
+ if (statp->options & RES_DEBUG)
printf(";; rcode = %d, ancount=%d\n", hp->rcode,
ntohs(hp->ancount));
#endif
switch (hp->rcode) {
case NXDOMAIN:
- __set_h_errno (HOST_NOT_FOUND);
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
break;
case SERVFAIL:
- __set_h_errno (TRY_AGAIN);
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
break;
case NOERROR:
- __set_h_errno (NO_DATA);
+ RES_SET_H_ERRNO(statp, NO_DATA);
break;
case FORMERR:
case NOTIMP:
case REFUSED:
default:
- __set_h_errno (NO_RECOVERY);
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
break;
}
return (-1);
@@ -169,52 +171,43 @@ res_query(name, class, type, answer, anslen)
* Formulate a normal query, send, and retrieve answer in supplied buffer.
* Return the size of the response on success, -1 on error.
* If enabled, implement search rules until answer or unrecoverable failure
- * is detected. Error code, if any, is left in h_errno.
+ * is detected. Error code, if any, is left in H_ERRNO.
*/
int
-res_search(name, class, type, answer, anslen)
- const char *name; /* domain name */
- int class, type; /* class and type of query */
- u_char *answer; /* buffer to put answer */
- int anslen; /* size of answer */
+res_nsearch(res_state statp,
+ const char *name, /* domain name */
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen) /* size of answer */
{
- register const char *cp, * const *domain;
+ const char *cp, * const *domain;
HEADER *hp = (HEADER *) answer;
+ char tmp[NS_MAXDNAME];
u_int dots;
- int trailing_dot, ret, saved_herrno;
- int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
+ int trailing_dot, ret;
+ int got_nodata = 0, got_servfail = 0, root_on_list = 0;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
- __set_h_errno (NETDB_INTERNAL);
- return (-1);
- }
__set_errno (0);
- __set_h_errno (HOST_NOT_FOUND); /* default, if we never query */
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /* True if we never query. */
+
dots = 0;
- for (cp = name; *cp; cp++)
+ for (cp = name; *cp != '\0'; cp++)
dots += (*cp == '.');
trailing_dot = 0;
if (cp > name && *--cp == '.')
trailing_dot++;
- /*
- * if there aren't any dots, it could be a user-level alias
- */
- if (!dots && (cp = __hostalias(name)) != NULL)
- return (res_query(cp, class, type, answer, anslen));
+ /* If there aren't any dots, it could be a user-level alias. */
+ if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL)
+ return (res_nquery(statp, cp, class, type, answer, anslen));
/*
- * If there are dots in the name already, let's just give it a try
- * 'as is'. The threshold can be set with the "ndots" option.
+ * If there are enough dots in the name, do no searching.
+ * (The threshold can be set with the "ndots" option.)
*/
- saved_herrno = -1;
- if (dots >= _res.ndots) {
- ret = res_querydomain(name, NULL, class, type, answer, anslen);
- if (ret > 0)
- return (ret);
- saved_herrno = h_errno;
- tried_as_is++;
- }
+ if (dots >= statp->ndots || trailing_dot)
+ return (res_nquerydomain(statp, name, NULL, class, type,
+ answer, anslen));
/*
* We do at least one level of search if
@@ -222,16 +215,21 @@ res_search(name, class, type, answer, anslen)
* - there is at least one dot, there is no trailing dot,
* and RES_DNSRCH is set.
*/
- if ((!dots && (_res.options & RES_DEFNAMES)) ||
- (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
+ if ((!dots && (statp->options & RES_DEFNAMES) != 0) ||
+ (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0)) {
int done = 0;
- for (domain = (const char * const *)_res.dnsrch;
+ for (domain = (const char * const *)statp->dnsrch;
*domain && !done;
domain++) {
- ret = res_querydomain(name, *domain, class, type,
- answer, anslen);
+ if (domain[0][0] == '\0' ||
+ (domain[0][0] == '.' && domain[0][1] == '\0'))
+ root_on_list++;
+
+ ret = res_nquerydomain(statp, name, *domain,
+ class, type,
+ answer, anslen);
if (ret > 0)
return (ret);
@@ -249,11 +247,11 @@ res_search(name, class, type, answer, anslen)
* fully-qualified.
*/
if (errno == ECONNREFUSED) {
- __set_h_errno (TRY_AGAIN);
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
return (-1);
}
- switch (h_errno) {
+ switch (statp->res_h_errno) {
case NO_DATA:
got_nodata++;
/* FALLTHROUGH */
@@ -275,34 +273,33 @@ res_search(name, class, type, answer, anslen)
/* if we got here for some reason other than DNSRCH,
* we only wanted one iteration of the loop, so stop.
*/
- if (!(_res.options & RES_DNSRCH))
+ if ((statp->options & RES_DNSRCH) == 0)
done++;
}
}
- /* if we have not already tried the name "as is", do that now.
- * note that we do this regardless of how many dots were in the
- * name or whether it ends with a dot.
+ /*
+ * If the name has any dots at all, and "." is not on the search
+ * list, then try an as-is query now.
*/
- if (!tried_as_is) {
- ret = res_querydomain(name, NULL, class, type, answer, anslen);
+ if (statp->ndots) {
+ ret = res_nquerydomain(statp, name, NULL, class, type,
+ answer, anslen);
if (ret > 0)
return (ret);
}
/* if we got here, we didn't satisfy the search.
- * if we did an initial full query, return that query's h_errno
+ * if we did an initial full query, return that query's H_ERRNO
* (note that we wouldn't be here if that query had succeeded).
* else if we ever got a nodata, send that back as the reason.
- * else send back meaningless h_errno, that being the one from
+ * else send back meaningless H_ERRNO, that being the one from
* the last DNSRCH we did.
*/
- if (saved_herrno != -1)
- __set_h_errno (saved_herrno);
- else if (got_nodata)
- __set_h_errno (NO_DATA);
+ if (got_nodata)
+ RES_SET_H_ERRNO(statp, NO_DATA);
else if (got_servfail)
- __set_h_errno (TRY_AGAIN);
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
return (-1);
}
@@ -311,23 +308,20 @@ res_search(name, class, type, answer, anslen)
* removing a trailing dot from name if domain is NULL.
*/
int
-res_querydomain(name, domain, class, type, answer, anslen)
- const char *name, *domain;
- int class, type; /* class and type of query */
- u_char *answer; /* buffer to put answer */
- int anslen; /* size of answer */
+res_nquerydomain(res_state statp,
+ const char *name,
+ const char *domain,
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen) /* size of answer */
{
- char nbuf[MAXDNAME * 2 + 2];
+ char nbuf[MAXDNAME];
const char *longname = nbuf;
- int n;
+ int n, d;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
- __set_h_errno (NETDB_INTERNAL);
- return (-1);
- }
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
- printf(";; res_querydomain(%s, %s, %d, %d)\n",
+ if (statp->options & RES_DEBUG)
+ printf(";; res_nquerydomain(%s, %s, %d, %d)\n",
name, domain?domain:"<Nil>", class, type);
#endif
if (domain == NULL) {
@@ -335,30 +329,36 @@ res_querydomain(name, domain, class, type, answer, anslen)
* Check for trailing '.';
* copy without '.' if present.
*/
- n = strlen(name) - 1;
- if (n != (0 - 1) && name[n] == '.'
- && n < (int) (sizeof(nbuf) - 1)) {
- bcopy(name, nbuf, n);
+ n = strlen(name);
+ if (n >= MAXDNAME) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ n--;
+ if (n >= 0 && name[n] == '.') {
+ strncpy(nbuf, name, n);
nbuf[n] = '\0';
} else
longname = name;
- } else
- sprintf(nbuf, "%.*s.%.*s", MAXDNAME, name, MAXDNAME, domain);
-
- return (res_query(longname, class, type, answer, anslen));
+ } else {
+ n = strlen(name);
+ d = strlen(domain);
+ if (n + d + 1 >= MAXDNAME) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ sprintf(nbuf, "%s.%s", name, domain);
+ }
+ return (res_nquery(statp, longname, class, type, answer, anslen));
}
const char *
-hostalias(name)
- register const char *name;
-{
- register char *cp1, *cp2;
- FILE *fp;
- char *file;
+res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) {
+ char *file, *cp1, *cp2;
char buf[BUFSIZ];
- static char abuf[MAXDNAME];
+ FILE *fp;
- if (_res.options & RES_NOALIASES)
+ if (statp->options & RES_NOALIASES)
return (NULL);
file = __secure_getenv("HOSTALIASES");
if (file == NULL || (fp = fopen(file, "r")) == NULL)
@@ -371,17 +371,18 @@ hostalias(name)
if (!*cp1)
break;
*cp1 = '\0';
- if (!strcasecmp(buf, name)) {
+ if (ns_samename(buf, name) == 1) {
while (isspace(*++cp1))
;
if (!*cp1)
break;
for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
;
- abuf[sizeof(abuf) - 1] = *cp2 = '\0';
- strncpy(abuf, cp1, sizeof(abuf) - 1);
+ *cp2 = '\0';
+ strncpy(dst, cp1, siz - 1);
+ dst[siz - 1] = '\0';
fclose(fp);
- return (abuf);
+ return (dst);
}
}
fclose(fp);
diff --git a/resolv/res_send.c b/resolv/res_send.c
index e315383fa7..d3dc2ba8e1 100644
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -1,6 +1,4 @@
/*
- * ++Copyright++ 1985, 1989, 1993
- * -
* Copyright (c) 1985, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -27,7 +25,9 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- * -
+ */
+
+/*
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
@@ -45,133 +45,165 @@
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
- * -
- * --Copyright--
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
-static char rcsid[] = "$Id$";
+static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id$";
#endif /* LIBC_SCCS and not lint */
- /* change this to "0"
- * if you talk to a lot
- * of multi-homed SunOS
- * ("broken") name servers.
- */
-#define CHECK_SRVR_ADDR 1 /* XXX - should be in options.h */
-
/*
* Send query to name server and wait for reply.
*/
#include <sys/types.h>
#include <sys/param.h>
-#include <sys/poll.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/uio.h>
+
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
-#include <stdio.h>
-#include <netdb.h>
#include <errno.h>
+#include <netdb.h>
#include <resolv.h>
-#if defined(BSD) && (BSD >= 199306)
-# include <stdlib.h>
-# include <string.h>
-# include <unistd.h>
-#else
-# include "../conf/portability.h"
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/poll.h>
+
+/* Options. Leave them on. */
+/* #undef DEBUG */
+#include "res_debug.h"
+
+#ifdef NEED_PSELECT
+static int pselect(int, void *, void *, void *,
+ struct timespec *,
+ const sigset_t *);
#endif
-#include <bits/libc-lock.h>
+#define CHECK_SRVR_ADDR
-/* Lock to protect the connection use. */
-__libc_lock_define_initialized (static, lock)
+/* From bind lib/isc/ev_timers.c: */
+#define BILLION 1000000000
+static struct timespec
+evTimeSpec(struct timeval tv) {
+ struct timespec ts;
-static void res_close_internal (void);
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = tv.tv_usec * 1000;
+ return (ts);
+}
-#if defined(USE_OPTIONS_H)
-# include <../conf/options.h>
-#endif
+static struct timespec
+evConsTime(time_t sec, long nsec) {
+ struct timespec x;
-static int s = -1; /* socket used for communications */
-static int connected = 0; /* is the socket connected */
-static int vc = 0; /* is the socket a virtual circuit? */
+ x.tv_sec = sec;
+ x.tv_nsec = nsec;
+ return (x);
+}
-/* XXX - this should be done in portability.h */
-#if (defined(BSD) && (BSD >= 199103)) || defined(linux)
-# define CAN_RECONNECT 1
-#else
-# define CAN_RECONNECT 0
-#endif
+static struct timespec
+evAddTime(struct timespec addend1, struct timespec addend2) {
+ struct timespec x;
-#ifndef DEBUG
-# define Dprint(cond, args) /*empty*/
-# define DprintQ(cond, args, query, size) /*empty*/
-# define Aerror(file, string, error, address) /*empty*/
-# define Perror(file, string, error) /*empty*/
-#else
-# define Dprint(cond, args) if (cond) {fprintf args;} else {}
-# define DprintQ(cond, args, query, size) if (cond) {\
- fprintf args;\
- __fp_nquery(query, size, stdout);\
- } else {}
+ x.tv_sec = addend1.tv_sec + addend2.tv_sec;
+ x.tv_nsec = addend1.tv_nsec + addend2.tv_nsec;
+ if (x.tv_nsec >= BILLION) {
+ x.tv_sec++;
+ x.tv_nsec -= BILLION;
+ }
+ return (x);
+}
+
+static struct timespec
+evSubTime(struct timespec minuend, struct timespec subtrahend) {
+ struct timespec x;
+
+ x.tv_sec = minuend.tv_sec - subtrahend.tv_sec;
+ if (minuend.tv_nsec >= subtrahend.tv_nsec)
+ x.tv_nsec = minuend.tv_nsec - subtrahend.tv_nsec;
+ else {
+ x.tv_nsec = BILLION - subtrahend.tv_nsec + minuend.tv_nsec;
+ x.tv_sec--;
+ }
+ return (x);
+}
+
+static int
+evCmpTime(struct timespec a, struct timespec b) {
+ long x = a.tv_sec - b.tv_sec;
+
+ if (x == 0L)
+ x = a.tv_nsec - b.tv_nsec;
+ return (x < 0L ? (-1) : x > 0L ? (1) : (0));
+}
+
+static struct timespec
+evNowTime() {
+ struct timeval now;
+
+ if (gettimeofday(&now, NULL) < 0)
+ return (evConsTime(0, 0));
+ return (evTimeSpec(now));
+}
+/* End of code from bind lib/isc/ev_timers.c. */
+
+#ifdef DEBUG
static void
- Aerror(file, string, error, address)
- FILE *file;
- char *string;
- int error;
- struct sockaddr_in address;
+ Aerror(const res_state statp, FILE *file, const char *string, int error,
+ struct sockaddr_in address)
{
int save = errno;
- if (_res.options & RES_DEBUG) {
+ if ((statp->options & RES_DEBUG) != 0) {
+ char tmp[sizeof "255.255.255.255"];
+
fprintf(file, "res_send: %s ([%s].%u): %s\n",
string,
- inet_ntoa(address.sin_addr),
+ inet_ntop(address.sin_family, &address.sin_addr,
+ tmp, sizeof tmp),
ntohs(address.sin_port),
strerror(error));
}
__set_errno (save);
}
static void
- Perror(file, string, error)
- FILE *file;
- char *string;
- int error;
- {
+ Perror(const res_state statp, FILE *file, const char *string, int error) {
int save = errno;
- if (_res.options & RES_DEBUG) {
+ if ((statp->options & RES_DEBUG) != 0)
fprintf(file, "res_send: %s: %s\n",
string, strerror(error));
- }
__set_errno (save);
}
#endif
-static res_send_qhook Qhook = NULL;
-static res_send_rhook Rhook = NULL;
-
-void
-res_send_setqhook(hook)
- res_send_qhook hook;
-{
-
- Qhook = hook;
-}
-
-void
-res_send_setrhook(hook)
- res_send_rhook hook;
-{
-
- Rhook = hook;
-}
+static int cmpsock(struct sockaddr_in *a1, struct sockaddr_in *a2);
+void res_pquery(const res_state, const u_char *, int, FILE *);
/* int
* res_isourserver(ina)
@@ -183,33 +215,28 @@ res_send_setrhook(hook)
* paul vixie, 29may94
*/
int
-res_isourserver(inp)
- const struct sockaddr_in *inp;
-{
+res_ourserver_p(const res_state statp, const struct sockaddr_in *inp) {
struct sockaddr_in ina;
- register int ns, ret;
+ int ns;
ina = *inp;
- ret = 0;
- for (ns = 0; ns < _res.nscount; ns++) {
- register const struct sockaddr_in *srv = &_res.nsaddr_list[ns];
+ for (ns = 0; ns < statp->nscount; ns++) {
+ const struct sockaddr_in *srv = &statp->nsaddr_list[ns];
if (srv->sin_family == ina.sin_family &&
srv->sin_port == ina.sin_port &&
(srv->sin_addr.s_addr == INADDR_ANY ||
- srv->sin_addr.s_addr == ina.sin_addr.s_addr)) {
- ret++;
- break;
- }
+ srv->sin_addr.s_addr == ina.sin_addr.s_addr))
+ return (1);
}
- return (ret);
+ return (0);
}
/* int
* res_nameinquery(name, type, class, buf, eom)
* look for (name,type,class) in the query section of packet (buf,eom)
* requires:
- * buf + HFIXESDZ <= eom
+ * buf + HFIXEDSZ <= eom
* returns:
* -1 : format error
* 0 : not found
@@ -218,17 +245,15 @@ res_isourserver(inp)
* paul vixie, 29may94
*/
int
-res_nameinquery(name, type, class, buf, eom)
- const char *name;
- register int type, class;
- const u_char *buf, *eom;
+res_nameinquery(const char *name, int type, int class,
+ const u_char *buf, const u_char *eom)
{
- register const u_char *cp = buf + HFIXEDSZ;
+ const u_char *cp = buf + HFIXEDSZ;
int qdcount = ntohs(((HEADER*)buf)->qdcount);
while (qdcount-- > 0) {
char tname[MAXDNAME+1];
- register int n, ttype, tclass;
+ int n, ttype, tclass;
n = dn_expand(buf, eom, cp, tname, sizeof tname);
if (n < 0)
@@ -236,11 +261,10 @@ res_nameinquery(name, type, class, buf, eom)
cp += n;
if (cp + 2 * INT16SZ > eom)
return (-1);
- ttype = _getshort(cp); cp += INT16SZ;
- tclass = _getshort(cp); cp += INT16SZ;
- if (ttype == type &&
- tclass == class &&
- strcasecmp(tname, name) == 0)
+ ttype = ns_get16(cp); cp += INT16SZ;
+ tclass = ns_get16(cp); cp += INT16SZ;
+ if (ttype == type && tclass == class &&
+ ns_samename(tname, name) == 1)
return (1);
}
return (0);
@@ -258,21 +282,28 @@ res_nameinquery(name, type, class, buf, eom)
* paul vixie, 29may94
*/
int
-res_queriesmatch(buf1, eom1, buf2, eom2)
- const u_char *buf1, *eom1;
- const u_char *buf2, *eom2;
+res_queriesmatch(const u_char *buf1, const u_char *eom1,
+ const u_char *buf2, const u_char *eom2)
{
- register const u_char *cp = buf1 + HFIXEDSZ;
+ const u_char *cp = buf1 + HFIXEDSZ;
int qdcount = ntohs(((HEADER*)buf1)->qdcount);
if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
return (-1);
+ /*
+ * Only header section present in replies to
+ * dynamic update packets.
+ */
+ if ( (((HEADER *)buf1)->opcode == ns_o_update) &&
+ (((HEADER *)buf2)->opcode == ns_o_update) )
+ return (1);
+
if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
return (0);
while (qdcount-- > 0) {
char tname[MAXDNAME+1];
- register int n, ttype, tclass;
+ int n, ttype, tclass;
n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
if (n < 0)
@@ -280,8 +311,8 @@ res_queriesmatch(buf1, eom1, buf2, eom2)
cp += n;
if (cp + 2 * INT16SZ > eom1)
return (-1);
- ttype = _getshort(cp); cp += INT16SZ;
- tclass = _getshort(cp); cp += INT16SZ;
+ ttype = ns_get16(cp); cp += INT16SZ;
+ tclass = ns_get16(cp); cp += INT16SZ;
if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
return (0);
}
@@ -289,67 +320,69 @@ res_queriesmatch(buf1, eom1, buf2, eom2)
}
int
-res_send(buf, buflen, ans, anssiz)
- const u_char *buf;
- int buflen;
- u_char *ans;
- int anssiz;
+res_nsend(res_state statp,
+ const u_char *buf, int buflen, u_char *ans, int anssiz)
{
HEADER *hp = (HEADER *) buf;
HEADER *anhp = (HEADER *) ans;
- int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
- register int n;
- u_int badns; /* XXX NSMAX can't exceed #/bits in this var */
- int result = -1;
+ int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns, n;
+ u_int badns; /* XXX NSMAX can't exceed #/bits in this variable */
+ static int highestFD = FD_SETSIZE - 1;
- if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
- /* errno should have been set by res_init() in this case. */
- return (-1);
- }
if (anssiz < HFIXEDSZ) {
__set_errno (EINVAL);
return (-1);
}
- DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY),
+ DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
(stdout, ";; res_send()\n"), buf, buflen);
- v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
+ v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
gotsomewhere = 0;
connreset = 0;
terrno = ETIMEDOUT;
badns = 0;
- __libc_lock_lock (lock);
+ /*
+ * Some callers want to even out the load on their resolver list.
+ */
+ if (statp->nscount > 0 && (statp->options & RES_ROTATE) != 0) {
+ struct sockaddr_in ina;
+ int lastns = statp->nscount - 1;
+
+ ina = statp->nsaddr_list[0];
+ for (ns = 0; ns < lastns; ns++)
+ statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
+ statp->nsaddr_list[lastns] = ina;
+ }
/*
* Send request, RETRY times, or until successful
*/
- for (try = 0; try < _res.retry; try++) {
- for (ns = 0; ns < _res.nscount; ns++) {
- struct sockaddr_in *nsap = &_res.nsaddr_list[ns];
- same_ns:
+ for (try = 0; try < statp->retry; try++) {
+ for (ns = 0; ns < statp->nscount; ns++) {
+ struct sockaddr_in *nsap = &statp->nsaddr_list[ns];
+ same_ns:
if (badns & (1 << ns)) {
- res_close_internal();
+ res_nclose(statp);
goto next_ns;
}
- if (Qhook) {
+ if (statp->qhook) {
int done = 0, loops = 0;
do {
res_sendhookact act;
- act = (*Qhook)(&nsap, &buf, &buflen,
- ans, anssiz, &resplen);
+ act = (*statp->qhook)(&nsap, &buf, &buflen,
+ ans, anssiz, &resplen);
switch (act) {
case res_goahead:
done = 1;
break;
case res_nextns:
- res_close_internal();
+ res_nclose(statp);
goto next_ns;
case res_done:
- result = resplen;
- goto and_out;
+ return (resplen);
case res_modified:
/* give the hook another try */
if (++loops < 42) /*doug adams*/
@@ -358,12 +391,12 @@ res_send(buf, buflen, ans, anssiz)
case res_error:
/*FALLTHROUGH*/
default:
- goto and_out;
+ return (-1);
}
} while (!done);
}
- Dprint(_res.options & RES_DEBUG,
+ Dprint(statp->options & RES_DEBUG,
(stdout, ";; Querying server (# %d) address = %s\n",
ns + 1, inet_ntoa(nsap->sin_addr)));
@@ -373,33 +406,53 @@ res_send(buf, buflen, ans, anssiz)
u_short len;
u_char *cp;
- /*
- * Use virtual circuit;
- * at most one attempt per server.
- */
- try = _res.retry;
+ /* Use VC; at most one attempt per server. */
+ try = statp->retry;
truncated = 0;
- if ((s < 0) || (!vc)) {
- if (s >= 0)
- res_close_internal();
- s = socket(PF_INET, SOCK_STREAM, 0);
- if (s < 0) {
+ /* Are we still talking to whom we want to talk to? */
+ if (statp->_sock >= 0 &&
+ (statp->_flags & RES_F_VC) != 0) {
+ struct sockaddr_in peer;
+ int size = sizeof(peer);
+
+ if (getpeername(statp->_sock,
+ (struct sockaddr *)&peer,
+ &size) < 0) {
+ res_nclose(statp);
+ statp->_flags &= ~RES_F_VC;
+ } else if (!cmpsock(&peer, nsap)) {
+ res_nclose(statp);
+ statp->_flags &= ~RES_F_VC;
+ }
+ }
+
+ if (statp->_sock < 0 ||
+ (statp->_flags & RES_F_VC) == 0) {
+ if (statp->_sock >= 0)
+ res_nclose(statp);
+
+ statp->_sock = socket(PF_INET,
+ SOCK_STREAM, 0);
+ if (statp->_sock < 0 ||
+ statp->_sock > highestFD) {
terrno = errno;
- Perror(stderr, "socket(vc)", errno);
- goto and_out;
+ Perror(statp, stderr,
+ "socket(vc)", errno);
+ return (-1);
}
__set_errno (0);
- if (connect(s, (struct sockaddr *)nsap,
- sizeof(struct sockaddr)) < 0) {
+ if (connect(statp->_sock,
+ (struct sockaddr *)nsap,
+ sizeof *nsap) < 0) {
terrno = errno;
- Aerror(stderr, "connect/vc",
+ Aerror(statp, stderr, "connect/vc",
errno, *nsap);
badns |= (1 << ns);
- res_close_internal();
+ res_nclose(statp);
goto next_ns;
}
- vc = 1;
+ statp->_flags |= RES_F_VC;
}
/*
* Send length & message
@@ -409,28 +462,30 @@ res_send(buf, buflen, ans, anssiz)
iov[0].iov_len = INT16SZ;
iov[1].iov_base = (caddr_t)buf;
iov[1].iov_len = buflen;
- if (writev(s, iov, 2) != (INT16SZ + buflen)) {
+ if (writev(statp->_sock, iov, 2) !=
+ (INT16SZ + buflen)) {
terrno = errno;
- Perror(stderr, "write failed", errno);
+ Perror(statp, stderr, "write failed", errno);
badns |= (1 << ns);
- res_close_internal();
+ res_nclose(statp);
goto next_ns;
}
/*
* Receive length & response
*/
-read_len:
+ read_len:
cp = ans;
len = INT16SZ;
- while ((n = read(s, (char *)cp, (int)len)) > 0) {
+ while ((n = read(statp->_sock,
+ (char *)cp, (int)len)) > 0) {
cp += n;
if ((len -= n) <= 0)
break;
}
if (n <= 0) {
terrno = errno;
- Perror(stderr, "read failed", errno);
- res_close_internal();
+ Perror(statp, stderr, "read failed", errno);
+ res_nclose(statp);
/*
* A long running process might get its TCP
* connection reset if the remote server was
@@ -442,15 +497,15 @@ read_len:
*/
if (terrno == ECONNRESET && !connreset) {
connreset = 1;
- res_close_internal();
+ res_nclose(statp);
goto same_ns;
}
- res_close_internal();
+ res_nclose(statp);
goto next_ns;
}
- resplen = _getshort(ans);
+ resplen = ns_get16(ans);
if (resplen > anssiz) {
- Dprint(_res.options & RES_DEBUG,
+ Dprint(statp->options & RES_DEBUG,
(stdout, ";; response truncated\n")
);
truncated = 1;
@@ -461,23 +516,24 @@ read_len:
/*
* Undersized message.
*/
- Dprint(_res.options & RES_DEBUG,
+ Dprint(statp->options & RES_DEBUG,
(stdout, ";; undersized: %d\n", len));
terrno = EMSGSIZE;
badns |= (1 << ns);
- res_close_internal();
+ res_nclose(statp);
goto next_ns;
}
cp = ans;
while (len != 0 &&
- (n = read(s, (char *)cp, (int)len)) > 0) {
+ (n = read(statp->_sock, (char *)cp, (int)len))
+ > 0) {
cp += n;
len -= n;
}
if (n <= 0) {
terrno = errno;
- Perror(stderr, "read(vc)", errno);
- res_close_internal();
+ Perror(statp, stderr, "read(vc)", errno);
+ res_nclose(statp);
goto next_ns;
}
if (truncated) {
@@ -490,10 +546,11 @@ read_len:
while (len != 0) {
char junk[PACKETSZ];
- n = ((size_t) len > sizeof(junk)
+ n = ((size_t)len > sizeof(junk)
? sizeof(junk)
: len);
- if ((n = read(s, junk, n)) > 0)
+ n = read(statp->_sock, junk, n);
+ if (n > 0)
len -= n;
else
break;
@@ -507,8 +564,8 @@ read_len:
* wait for the correct one.
*/
if (hp->id != anhp->id) {
- DprintQ((_res.options & RES_DEBUG) ||
- (_res.pfcode & RES_PRF_REPLY),
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
(stdout, ";; old answer (unexpected):\n"),
ans, (resplen>anssiz)?anssiz:resplen);
goto read_len;
@@ -517,27 +574,34 @@ read_len:
/*
* Use datagrams.
*/
- int timeout;
+ struct timespec start, timeout, finish;
+#ifdef _LIBC
struct pollfd pfd[1];
+ int ptimeout;
+#else
+ fd_set dsmask;
+#endif
struct sockaddr_in from;
- socklen_t fromlen;
- time_t curtime;
- time_t endtime;
-
- if ((s < 0) || vc) {
- if (vc)
- res_close_internal();
- s = socket(PF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
-#if !CAN_RECONNECT
+ int fromlen, seconds;
+
+ if (statp->_sock < 0 ||
+ (statp->_flags & RES_F_VC) != 0) {
+ if ((statp->_flags & RES_F_VC) != 0)
+ res_nclose(statp);
+ statp->_sock = socket(PF_INET, SOCK_DGRAM, 0);
+ if (statp->_sock < 0 ||
+ statp->_sock > highestFD) {
+#ifndef CAN_RECONNECT
bad_dg_sock:
#endif
terrno = errno;
- Perror(stderr, "socket(dg)", errno);
- goto and_out;
+ Perror(statp, stderr,
+ "socket(dg)", errno);
+ return (-1);
}
- connected = 0;
+ statp->_flags &= ~RES_F_CONN;
}
+#ifndef CANNOT_CONNECT_DGRAM
/*
* On a 4.3BSD+ machine (client and server,
* actually), sending to a nameserver datagram
@@ -553,28 +617,29 @@ read_len:
* as we wish to receive answers from the first
* server to respond.
*/
- if (_res.nscount == 1 || (try == 0 && ns == 0)) {
+ if (statp->nscount == 1 || (try == 0 && ns == 0)) {
/*
* Connect only if we are sure we won't
* receive a response from another server.
*/
- if (!connected) {
- if (connect(s, (struct sockaddr *)nsap,
- sizeof(struct sockaddr)
- ) < 0) {
- Aerror(stderr,
+ if ((statp->_flags & RES_F_CONN) == 0) {
+ if (connect(statp->_sock,
+ (struct sockaddr *)nsap,
+ sizeof *nsap) < 0) {
+ Aerror(statp, stderr,
"connect(dg)",
errno, *nsap);
badns |= (1 << ns);
- res_close_internal();
+ res_nclose(statp);
goto next_ns;
}
- connected = 1;
+ statp->_flags |= RES_F_CONN;
}
- if (send(s, (char*)buf, buflen, 0) != buflen) {
- Perror(stderr, "send", errno);
+ if (send(statp->_sock, (char*)buf, buflen, 0)
+ != buflen) {
+ Perror(statp, stderr, "send", errno);
badns |= (1 << ns);
- res_close_internal();
+ res_nclose(statp);
goto next_ns;
}
} else {
@@ -582,90 +647,130 @@ read_len:
* Disconnect if we want to listen
* for responses from more than one server.
*/
- if (connected) {
-#if CAN_RECONNECT
+ if ((statp->_flags & RES_F_CONN) != 0) {
+#ifdef CAN_RECONNECT
struct sockaddr_in no_addr;
no_addr.sin_family = AF_INET;
no_addr.sin_addr.s_addr = INADDR_ANY;
no_addr.sin_port = 0;
- (void) connect(s,
+ (void) connect(statp->_sock,
(struct sockaddr *)
&no_addr,
- sizeof(no_addr));
+ sizeof no_addr);
#else
- int s1 = socket(PF_INET, SOCK_DGRAM,0);
+ struct sockaddr_in local_addr;
+ int len, result, s1;
+
+ len = sizeof(local_addr);
+ s1 = socket(PF_INET, SOCK_DGRAM, 0);
+ result = getsockname(statp->_sock,
+ (struct sockaddr *)&local_addr,
+ &len);
if (s1 < 0)
goto bad_dg_sock;
- (void) dup2(s1, s);
+ (void) dup2(s1, statp->_sock);
(void) close(s1);
- Dprint(_res.options & RES_DEBUG,
+ if (result == 0) {
+ /*
+ * Attempt to rebind to old
+ * port. Note connected socket
+ * has an sin_addr set.
+ */
+ local_addr.sin_addr.s_addr =
+ htonl(0);
+ (void)bind(statp->_sock,
+ (struct sockaddr *)
+ &local_addr, len);
+ }
+ Dprint(statp->options & RES_DEBUG,
(stdout, ";; new DG socket\n"))
-#endif
- connected = 0;
+#endif /* CAN_RECONNECT */
+ statp->_flags &= ~RES_F_CONN;
__set_errno (0);
}
- if (sendto(s, (char*)buf, buflen, 0,
+#endif /* !CANNOT_CONNECT_DGRAM */
+ if (sendto(statp->_sock,
+ (char*)buf, buflen, 0,
(struct sockaddr *)nsap,
- sizeof(struct sockaddr))
+ sizeof *nsap)
!= buflen) {
- Aerror(stderr, "sendto", errno, *nsap);
+ Aerror(statp, stderr, "sendto", errno, *nsap);
badns |= (1 << ns);
- res_close_internal();
+ res_nclose(statp);
goto next_ns;
}
+#ifndef CANNOT_CONNECT_DGRAM
+ }
+#endif /* !CANNOT_CONNECT_DGRAM */
+
+ if (statp->_sock < 0 || statp->_sock > highestFD) {
+ Perror(statp, stderr,
+ "fd out-of-bounds", EMFILE);
+ res_nclose(statp);
+ goto next_ns;
}
/*
* Wait for reply
*/
- curtime = time (NULL);
+ seconds = (statp->retrans << try);
if (try > 0)
- endtime = (_res.retrans << try) / _res.nscount;
- else {
- endtime = _res.retrans;
- if (endtime <= 0)
- endtime = 1;
- }
- endtime += curtime;
- wait:
- timeout = MAX (endtime - curtime, 0) * 1000;
-#if 0
- if (s < 0 || s >= FD_SETSIZE) {
- Perror(stderr, "s out-of-bounds", EMFILE);
- res_close_internal();
+ seconds /= statp->nscount;
+ if (seconds <= 0)
+ seconds = 1;
+
+ start = evNowTime();
+ timeout = evConsTime(seconds, 0);
+ finish = evAddTime(start, timeout);
+ wait:
+#ifdef _LIBC
+ /* Convert struct timespec in milliseconds. */
+ ptimeout = timeout.tv_sec * 1000
+ + timeout.tv_nsec / 1000000;
+
+ pfd[0].fd = statp->_sock;
+ pfd[0].events = POLLIN;
+ n = __poll (pfd, 1, ptimeout);
+#else
+ FD_ZERO(&dsmask);
+ FD_SET(statp->_sock, &dsmask);
+ n = pselect(statp->_sock + 1,
+ &dsmask, NULL, NULL,
+ &timeout, NULL);
+#endif
+ if (n == 0) {
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; timeout\n"));
+ gotsomewhere = 1;
goto next_ns;
}
-#endif
- pfd[0].fd = s;
- pfd[0].events = POLLIN;
- n = __poll(pfd, 1, timeout);
if (n < 0) {
if (errno == EINTR) {
- curtime = time (NULL);
- goto wait;
+ struct timespec now;
+
+ now = evNowTime();
+ if (evCmpTime(finish, now) >= 0) {
+ timeout = evSubTime(finish,
+ now);
+ goto wait;
+ }
}
- Perror(stderr, "poll", errno);
- res_close_internal();
- goto next_ns;
- }
- if (n == 0) {
- /*
- * timeout
- */
- Dprint(_res.options & RES_DEBUG,
- (stdout, ";; timeout\n"));
- gotsomewhere = 1;
- res_close_internal();
+#ifdef _LIBC
+ Perror(statp, stderr, "poll", errno);
+#else
+ Perror(statp, stderr, "select", errno);
+#endif
+ res_nclose(statp);
goto next_ns;
}
__set_errno (0);
fromlen = sizeof(struct sockaddr_in);
- resplen = recvfrom(s, (char*)ans, anssiz, 0,
+ resplen = recvfrom(statp->_sock, (char*)ans, anssiz,0,
(struct sockaddr *)&from, &fromlen);
if (resplen <= 0) {
- Perror(stderr, "recvfrom", errno);
- res_close_internal();
+ Perror(statp, stderr, "recvfrom", errno);
+ res_nclose(statp);
goto next_ns;
}
gotsomewhere = 1;
@@ -673,12 +778,12 @@ read_len:
/*
* Undersized message.
*/
- Dprint(_res.options & RES_DEBUG,
+ Dprint(statp->options & RES_DEBUG,
(stdout, ";; undersized: %d\n",
resplen));
terrno = EMSGSIZE;
badns |= (1 << ns);
- res_close_internal();
+ res_nclose(statp);
goto next_ns;
}
if (hp->id != anhp->id) {
@@ -687,30 +792,28 @@ read_len:
* XXX - potential security hazard could
* be detected here.
*/
- DprintQ((_res.options & RES_DEBUG) ||
- (_res.pfcode & RES_PRF_REPLY),
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
(stdout, ";; old answer:\n"),
ans, (resplen>anssiz)?anssiz:resplen);
- curtime = time (NULL);
goto wait;
}
-#if CHECK_SRVR_ADDR
- if (!(_res.options & RES_INSECURE1) &&
- !res_isourserver(&from)) {
+#ifdef CHECK_SRVR_ADDR
+ if (!(statp->options & RES_INSECURE1) &&
+ !res_ourserver_p(statp, &from)) {
/*
* response from wrong server? ignore it.
* XXX - potential security hazard could
* be detected here.
*/
- DprintQ((_res.options & RES_DEBUG) ||
- (_res.pfcode & RES_PRF_REPLY),
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
(stdout, ";; not our server:\n"),
ans, (resplen>anssiz)?anssiz:resplen);
- curtime = time (NULL);
goto wait;
}
#endif
- if (!(_res.options & RES_INSECURE2) &&
+ if (!(statp->options & RES_INSECURE2) &&
!res_queriesmatch(buf, buf + buflen,
ans, ans + anssiz)) {
/*
@@ -718,43 +821,42 @@ read_len:
* XXX - potential security hazard could
* be detected here.
*/
- DprintQ((_res.options & RES_DEBUG) ||
- (_res.pfcode & RES_PRF_REPLY),
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
(stdout, ";; wrong query name:\n"),
ans, (resplen>anssiz)?anssiz:resplen);
- curtime = time (NULL);
goto wait;
}
if (anhp->rcode == SERVFAIL ||
anhp->rcode == NOTIMP ||
anhp->rcode == REFUSED) {
- DprintQ(_res.options & RES_DEBUG,
+ DprintQ(statp->options & RES_DEBUG,
(stdout, "server rejected query:\n"),
ans, (resplen>anssiz)?anssiz:resplen);
badns |= (1 << ns);
- res_close_internal();
+ res_nclose(statp);
/* don't retry if called from dig */
- if (!_res.pfcode)
+ if (!statp->pfcode)
goto next_ns;
}
- if (!(_res.options & RES_IGNTC) && anhp->tc) {
+ if (!(statp->options & RES_IGNTC) && anhp->tc) {
/*
* get rest of answer;
* use TCP with same server.
*/
- Dprint(_res.options & RES_DEBUG,
+ Dprint(statp->options & RES_DEBUG,
(stdout, ";; truncated answer\n"));
v_circuit = 1;
- res_close_internal();
+ res_nclose(statp);
goto same_ns;
}
} /*if vc/dg*/
- Dprint((_res.options & RES_DEBUG) ||
- ((_res.pfcode & RES_PRF_REPLY) &&
- (_res.pfcode & RES_PRF_HEAD1)),
+ Dprint((statp->options & RES_DEBUG) ||
+ ((statp->pfcode & RES_PRF_REPLY) &&
+ (statp->pfcode & RES_PRF_HEAD1)),
(stdout, ";; got answer:\n"));
- DprintQ((_res.options & RES_DEBUG) ||
- (_res.pfcode & RES_PRF_REPLY),
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
(stdout, ""),
ans, (resplen>anssiz)?anssiz:resplen);
/*
@@ -765,25 +867,25 @@ read_len:
* or if we haven't been asked to keep a socket open,
* close the socket.
*/
- if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) ||
- !(_res.options & RES_STAYOPEN)) {
- res_close_internal();
+ if ((v_circuit && (!(statp->options & RES_USEVC) || ns != 0)) ||
+ !(statp->options & RES_STAYOPEN)) {
+ res_nclose(statp);
}
- if (Rhook) {
+ if (statp->rhook) {
int done = 0, loops = 0;
do {
res_sendhookact act;
- act = (*Rhook)(nsap, buf, buflen,
- ans, anssiz, &resplen);
+ act = (*statp->rhook)(nsap, buf, buflen,
+ ans, anssiz, &resplen);
switch (act) {
case res_goahead:
case res_done:
done = 1;
break;
case res_nextns:
- res_close_internal();
+ res_nclose(statp);
goto next_ns;
case res_modified:
/* give the hook another try */
@@ -793,29 +895,24 @@ read_len:
case res_error:
/*FALLTHROUGH*/
default:
- goto and_out;
+ return (-1);
}
} while (!done);
}
- result = resplen;
- goto and_out;
- next_ns: ;
+ return (resplen);
+ next_ns: ;
} /*foreach ns*/
} /*foreach retry*/
- res_close_internal();
+ res_nclose(statp);
if (!v_circuit) {
if (!gotsomewhere)
- __set_errno (ECONNREFUSED); /* no nameservers found */
+ __set_errno (ECONNREFUSED); /* no nameservers found */
else
- __set_errno (ETIMEDOUT); /* no answer obtained */
+ __set_errno (ETIMEDOUT); /* no answer obtained */
} else
__set_errno (terrno);
-
- and_out:
- __libc_lock_unlock (lock);
-
- return result;
+ return (-1);
}
/*
@@ -825,44 +922,46 @@ read_len:
*
* This routine is not expected to be user visible.
*/
-static void
-res_close_internal()
-{
- if (s >= 0) {
- (void) close(s);
- s = -1;
- connected = 0;
- vc = 0;
+void
+res_nclose(res_state statp) {
+ if (statp->_sock >= 0) {
+ (void) close(statp->_sock);
+ statp->_sock = -1;
+ statp->_flags &= ~(RES_F_VC | RES_F_CONN);
}
}
-void
-res_close ()
-{
- __libc_lock_lock (lock);
- res_close_internal ();
- __libc_lock_unlock (lock);
+/* Private */
+static int
+cmpsock(struct sockaddr_in *a1, struct sockaddr_in *a2) {
+ return ((a1->sin_family == a2->sin_family) &&
+ (a1->sin_port == a2->sin_port) &&
+ (a1->sin_addr.s_addr == a2->sin_addr.s_addr));
}
-#ifdef ultrix
-/* ultrix 4.0 had some icky packaging in its libc.a. alias for it here.
- * there is more gunk of this kind over in res_debug.c.
- */
-
-void
-_res_close()
+#ifdef NEED_PSELECT
+/* XXX needs to move to the porting library. */
+static int
+pselect(int nfds, void *rfds, void *wfds, void *efds,
+ struct timespec *tsp,
+ const sigset_t *sigmask)
{
- res_close();
-}
+ struct timeval tv, *tvp;
+ sigset_t sigs;
+ int n;
-#undef res_send
-int
-res_send(buf, buflen, ans, anssiz)
- const u_char *buf;
- int buflen;
- u_char *ans;
- int anssiz;
-{
- return (__res_send(buf, buflen, ans, anssiz));
+ if (tsp) {
+ tvp = &tv;
+ tv = evTimeVal(*tsp);
+ } else
+ tvp = NULL;
+ if (sigmask)
+ sigprocmask(SIG_SETMASK, sigmask, &sigs);
+ n = select(nfds, rfds, wfds, efds, tvp);
+ if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigs, NULL);
+ if (tsp)
+ *tsp = evTimeSpec(tv);
+ return (n);
}
-#endif /* Ultrix 4.0 hackery */
+#endif
diff --git a/resolv/resolv.h b/resolv/resolv.h
index 58742e90bb..b101262f51 100644
--- a/resolv/resolv.h
+++ b/resolv/resolv.h
@@ -50,6 +50,23 @@
*/
/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
* @(#)resolv.h 8.1 (Berkeley) 6/2/93
* $Id$
*/
@@ -76,7 +93,35 @@
* is new enough to contain a certain feature.
*/
-#define __RES 19960801
+#define __RES 19991006
+
+/*
+ * This used to be defined in res_query.c, now it's in herror.c.
+ * [XXX no it's not. It's in irs/irs_data.c]
+ * It was
+ * never extern'd by any *.h file before it was placed here. For thread
+ * aware programs, the last h_errno value set is stored in res->h_errno.
+ *
+ * XXX: There doesn't seem to be a good reason for exposing RES_SET_H_ERRNO
+ * (and __h_errno_set) to the public via <resolv.h>.
+ * XXX: __h_errno_set is really part of IRS, not part of the resolver.
+ * If somebody wants to build and use a resolver that doesn't use IRS,
+ * what do they do? Perhaps something like
+ * #ifdef WANT_IRS
+ * # define RES_SET_H_ERRNO(r,x) __h_errno_set(r,x)
+ * #else
+ * # define RES_SET_H_ERRNO(r,x) (h_errno = (r)->res_h_errno = (x))
+ * #endif
+ */
+#define RES_SET_H_ERRNO(r,x) \
+ do \
+ { \
+ (r)->res_h_errno = x; \
+ __set_h_errno(x); \
+ } \
+ while (0)
+
+struct __res_state; /* forward */
/*
* Resolver configuration file.
@@ -88,6 +133,29 @@
#define _PATH_RESCONF "/etc/resolv.conf"
#endif
+typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error }
+ res_sendhookact;
+
+typedef res_sendhookact (*res_send_qhook)__P((struct sockaddr_in * const *ns,
+ const u_char **query,
+ int *querylen,
+ u_char *ans,
+ int anssiz,
+ int *resplen));
+
+typedef res_sendhookact (*res_send_rhook)__P((const struct sockaddr_in *ns,
+ const u_char *query,
+ int querylen,
+ u_char *ans,
+ int anssiz,
+ int *resplen));
+
+struct res_sym {
+ int number; /* Identifying number, like T_MX */
+ char * name; /* Its symbolic name, like "MX" */
+ char * humanname; /* Its fun name, like "mail exchanger" */
+};
+
/*
* Global defines and variables for resolver stub.
*/
@@ -99,6 +167,9 @@
#define RES_TIMEOUT 5 /* min. seconds between retries */
#define MAXRESOLVSORT 10 /* number of net to sort on */
#define RES_MAXNDOTS 15 /* should reflect bit field size */
+#define RES_MAXRETRANS 30 /* only for resolv.conf/RES_OPTIONS */
+#define RES_MAXRETRY 5 /* only for resolv.conf/RES_OPTIONS */
+#define RES_DFLRETRY 2 /* Default #/tries. */
struct __res_state {
int retrans; /* retransmission time interval */
@@ -119,9 +190,25 @@ struct __res_state {
struct in_addr addr;
u_int32_t mask;
} sort_list[MAXRESOLVSORT];
- char pad[72]; /* on an i386 this means 512b total */
+ res_send_qhook qhook; /* query hook */
+ res_send_rhook rhook; /* response hook */
+ int res_h_errno; /* last one set for this context */
+ int _sock; /* PRIVATE: for res_send i/o */
+ u_int _flags; /* PRIVATE: see below */
+ char pad[52]; /* On an i386 this means 512b total. */
};
+typedef struct __res_state *res_state;
+
+/*
+ * Resolver flags (used to be discrete per-module statics ints).
+ */
+#define RES_F_VC 0x00000001 /* socket is TCP */
+#define RES_F_CONN 0x00000002 /* socket is connected */
+
+/* res_findzonecut() options */
+#define RES_EXHAUSTIVE 0x00000001 /* always do all queries */
+
/*
* Resolver options (keep these in synch with res_debug.c, please)
*/
@@ -139,6 +226,9 @@ struct __res_state {
#define RES_INSECURE2 0x00000800 /* type 2 security disabled */
#define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */
#define RES_USE_INET6 0x00002000 /* use/map IPv6 in gethostbyname() */
+#define RES_ROTATE 0x00004000 /* rotate ns list after each query */
+#define RES_NOCHECKNAME 0x00008000 /* do not check names for sanity. */
+#define RES_KEEPTSIG 0x00010000 /* do not strip TSIG records */
#define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH)
@@ -146,8 +236,8 @@ struct __res_state {
* Resolver "pfcode" values. Used by dig.
*/
#define RES_PRF_STATS 0x00000001
-/* 0x00000002 */
-#define RES_PRF_CLASS 0x00000004
+#define RES_PRF_UPDATE 0x00000002
+#define RES_PRF_CLASS 0x00000004
#define RES_PRF_CMD 0x00000008
#define RES_PRF_QUES 0x00000010
#define RES_PRF_ANS 0x00000020
@@ -159,133 +249,158 @@ struct __res_state {
#define RES_PRF_HEADX 0x00000800
#define RES_PRF_QUERY 0x00001000
#define RES_PRF_REPLY 0x00002000
-#define RES_PRF_INIT 0x00004000
+#define RES_PRF_INIT 0x00004000
/* 0x00008000 */
-/* hooks are still experimental as of 4.9.2 */
-typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error }
- res_sendhookact;
-
-typedef res_sendhookact (*res_send_qhook) (struct sockaddr_in * const *ns,
- const u_char **query, int *querylen,
- u_char *ans, int anssiz,
- int *resplen);
+/* Things involving an internal (static) resolver context. */
+#if defined _REENTRANT || defined _LIBC_REENTRANT
+extern struct __res_state *__res_state(void);
+#define _res (*__res_state())
+#else
+extern struct __res_state _res;
+#endif
-typedef res_sendhookact (*res_send_rhook) (const struct sockaddr_in *ns,
- const u_char *query, int querylen,
- u_char *ans, int anssiz,
- int *resplen);
+#define fp_nquery __fp_nquery
+#define fp_query __fp_query
+#define hostalias __hostalias
+#define p_query __p_query
+#define res_close __res_close
+#define res_isourserver __res_isourserver
+#define res_querydomain __res_querydomain
+#define res_send __res_send
-struct res_sym {
- int number; /* Identifying number, like T_MX */
- char * name; /* Its symbolic name, like "MX" */
- char * humanname; /* Its fun name, like "mail exchanger" */
-};
+__BEGIN_DECLS
+void fp_nquery __P((const u_char *, int, FILE *));
+void fp_query __P((const u_char *, FILE *));
+const char * hostalias __P((const char *));
+void p_query __P((const u_char *));
+void res_close __P((void));
+int res_init __P((void));
+int res_isourserver __P((const struct sockaddr_in *));
+int res_mkquery __P((int, const char *, int, int, const u_char *,
+ int, const u_char *, u_char *, int));
+int res_query __P((const char *, int, int, u_char *, int));
+int res_querydomain __P((const char *, const char *, int, int,
+ u_char *, int));
+int res_search __P((const char *, int, int, u_char *, int));
+int res_send __P((const u_char *, int, u_char *, int));
+__END_DECLS
-extern struct __res_state _res;
+#if !defined(SHARED_LIBBIND) || defined(_LIBC)
+/*
+ * If libbind is a shared object (well, DLL anyway)
+ * these externs break the linker when resolv.h is
+ * included by a lib client (like named)
+ * Make them go away if a client is including this
+ *
+ */
+extern const struct res_sym __p_key_syms[];
+extern const struct res_sym __p_cert_syms[];
extern const struct res_sym __p_class_syms[];
extern const struct res_sym __p_type_syms[];
+extern const struct res_sym __p_rcode_syms[];
+#endif /* SHARED_LIBBIND */
-/* Private routines shared between libc/net, named, nslookup and others. */
-#define res_hnok __res_hnok
-#define res_ownok __res_ownok
-#define res_mailok __res_mailok
-#define res_dnok __res_dnok
-#define sym_ston __sym_ston
-#define sym_ntos __sym_ntos
-#define sym_ntop __sym_ntop
-#define b64_ntop __b64_ntop
-#define b64_pton __b64_pton
-#define loc_ntoa __loc_ntoa
-#define loc_aton __loc_aton
-#define dn_skipname __dn_skipname
-#define fp_resstat __fp_resstat
-#define fp_query __fp_query
-#define fp_nquery __fp_nquery
-#define hostalias __hostalias
-#define putlong __putlong
-#define putshort __putshort
-#define p_class __p_class
-#define p_time __p_time
-#define p_type __p_type
-#define p_query __p_query
-#define p_cdnname __p_cdnname
-#define p_cdname __p_cdname
-#define p_fqnname __p_fqnname
-#define p_fqname __p_fqname
-#define p_rr __p_rr
-#define p_option __p_option
-#define p_secstodate __p_secstodate
-#define dn_count_labels __dn_count_labels
-#define dn_comp __dn_comp
-#define res_randomid __res_randomid
-#define res_send __res_send
-#define res_isourserver __res_isourserver
-#define res_nameinquery __res_nameinquery
-#define res_queriesmatch __res_queriesmatch
-#define res_close __res_close
-
-#ifdef BIND_RES_POSIX3
-#define dn_expand __dn_expand
-#define res_init __res_init
-#define res_query __res_query
-#define res_search __res_search
-#define res_querydomain __res_querydomain
-#define res_mkquery __res_mkquery
-#endif
-
+#define b64_ntop __b64_ntop
+#define b64_pton __b64_pton
+#define dn_comp __dn_comp
+#define dn_count_labels __dn_count_labels
+#define dn_skipname __dn_skipname
+#define fp_resstat __fp_resstat
+#define loc_aton __loc_aton
+#define loc_ntoa __loc_ntoa
+#define p_cdname __p_cdname
+#define p_cdnname __p_cdnname
+#define p_class __p_class
+#define p_fqname __p_fqname
+#define p_fqnname __p_fqnname
+#define p_option __p_option
+#define p_secstodate __p_secstodate
+#define p_section __p_section
+#define p_time __p_time
+#define p_type __p_type
+#define p_rcode __p_rcode
+#define putlong __putlong
+#define putshort __putshort
+#define res_dnok __res_dnok
+#define res_findzonecut __res_findzonecut
+#define res_hnok __res_hnok
+#define res_hostalias __res_hostalias
+#define res_mailok __res_mailok
+#define res_nameinquery __res_nameinquery
+#define res_nclose __res_nclose
+#define res_ninit __res_ninit
+#define res_nmkquery __res_nmkquery
+#define res_npquery __res_npquery
+#define res_nquery __res_nquery
+#define res_nquerydomain __res_nquerydomain
+#define res_nsearch __res_nsearch
+#define res_nsend __res_nsend
+#define res_nisourserver __res_nisourserver
+#define res_ownok __res_ownok
+#define res_queriesmatch __res_queriesmatch
+#define res_randomid __res_randomid
+#define sym_ntop __sym_ntop
+#define sym_ntos __sym_ntos
+#define sym_ston __sym_ston
__BEGIN_DECLS
int res_hnok (const char *) __THROW;
int res_ownok (const char *) __THROW;
int res_mailok (const char *) __THROW;
int res_dnok (const char *) __THROW;
-int sym_ston (const struct res_sym *, char *, int *) __THROW;
+int sym_ston (const struct res_sym *, const char *, int *) __THROW;
const char * sym_ntos (const struct res_sym *, int, int *) __THROW;
const char * sym_ntop (const struct res_sym *, int, int *) __THROW;
int b64_ntop (u_char const *, size_t, char *, size_t) __THROW;
int b64_pton (char const *, u_char *, size_t) __THROW;
-int loc_aton (const char *, u_char *) __THROW;
-const char * loc_ntoa (const u_char *, char *) __THROW;
+int loc_aton (const char *__ascii, u_char *__binary) __THROW;
+const char * loc_ntoa (const u_char *__binary, char *__ascii) __THROW;
int dn_skipname (const u_char *, const u_char *) __THROW;
-void fp_resstat (struct __res_state *, FILE *) __THROW;
-void fp_query (const u_char *, FILE *) __THROW;
-void fp_nquery (const u_char *, int, FILE *) __THROW;
-const char * hostalias (const char *) __THROW;
void putlong (u_int32_t, u_char *) __THROW;
void putshort (u_int16_t, u_char *) __THROW;
const char * p_class (int) __THROW;
const char * p_time (u_int32_t) __THROW;
const char * p_type (int) __THROW;
-void p_query (const u_char *) __THROW;
+const char * p_rcode (int) __THROW;
const u_char * p_cdnname (const u_char *, const u_char *, int, FILE *)
__THROW;
const u_char * p_cdname (const u_char *, const u_char *, FILE *) __THROW;
const u_char * p_fqnname (const u_char *cp, const u_char *msg,
int, char *, int) __THROW;
const u_char * p_fqname (const u_char *, const u_char *, FILE *) __THROW;
-const u_char * p_rr (const u_char *, const u_char *, FILE *) __THROW;
const char * p_option (u_long option) __THROW;
char * p_secstodate (u_long) __THROW;
-int dn_count_labels (char *) __THROW;
+int dn_count_labels (const char *) __THROW;
int dn_comp (const char *, u_char *, int,
u_char **, u_char **) __THROW;
int dn_expand (const u_char *, const u_char *, const u_char *,
char *, int) __THROW;
-int res_init (void) __THROW;
u_int res_randomid (void) __THROW;
-int res_query (const char *, int, int, u_char *, int) __THROW;
-int res_search (const char *, int, int, u_char *, int) __THROW;
-int res_querydomain (const char *, const char *, int, int,
- u_char *, int) __THROW;
-int res_mkquery (int, const char *, int, int, const u_char *, int,
- const u_char *, u_char *, int) __THROW;
-int res_send (const u_char *, int, u_char *, int) __THROW;
-int res_isourserver (const struct sockaddr_in *) __THROW;
int res_nameinquery (const char *, int, int,
const u_char *, const u_char *) __THROW;
int res_queriesmatch (const u_char *, const u_char *,
const u_char *, const u_char *) __THROW;
-void res_close (void) __THROW;
+const char * p_section (int section, int opcode) __THROW;
+/* Things involving a resolver context. */
+int res_ninit (res_state) __THROW;
+int res_nisourserver (const res_state,
+ const struct sockaddr_in *) __THROW;
+void fp_resstat (const res_state, FILE *) __THROW;
+void res_npquery (const res_state, const u_char *, int, FILE *) __THROW;
+const char * res_hostalias (const res_state, const char *,
+ char *, size_t) __THROW;
+int res_nquery (res_state,
+ const char *, int, int, u_char *, int) __THROW;
+int res_nsearch (res_state, const char *, int,
+ int, u_char *, int) __THROW;
+int res_nquerydomain (res_state,
+ const char *, const char *, int, int,
+ u_char *, int) __THROW;
+int res_nmkquery (res_state,
+ int, const char *, int, int, const u_char *,
+ int, const u_char *, u_char *, int) __THROW;
+int res_nsend (res_state, const u_char *, int, u_char *, int) __THROW;
+void res_nclose (res_state) __THROW;
__END_DECLS
-#endif /* resolv.h */
+#endif /* !_RESOLV_H_ */