diff options
author | Ulrich Drepper <drepper@redhat.com> | 1999-12-04 18:05:55 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 1999-12-04 18:05:55 +0000 |
commit | b43b13ac2544b11f35be301d1589b51a8473e32b (patch) | |
tree | 6520da2e17c933ebc29b4572cdcc27410b10a4c4 /resolv | |
parent | 591e1ffbf8db5e059b9bcf3bde6d7758f018a46d (diff) | |
download | glibc-b43b13ac2544b11f35be301d1589b51a8473e32b.zip glibc-b43b13ac2544b11f35be301d1589b51a8473e32b.tar.gz glibc-b43b13ac2544b11f35be301d1589b51a8473e32b.tar.bz2 |
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/Banner | 2 | ||||
-rw-r--r-- | resolv/Makefile | 11 | ||||
-rw-r--r-- | resolv/Versions | 7 | ||||
-rw-r--r-- | resolv/arpa/nameser.h | 670 | ||||
-rw-r--r-- | resolv/arpa/nameser_compat.h | 184 | ||||
-rw-r--r-- | resolv/gethnamaddr.c | 20 | ||||
-rw-r--r-- | resolv/ns_name.c | 636 | ||||
-rw-r--r-- | resolv/ns_netint.c | 52 | ||||
-rw-r--r-- | resolv/ns_parse.c | 194 | ||||
-rw-r--r-- | resolv/ns_print.c | 818 | ||||
-rw-r--r-- | resolv/ns_samedomain.c | 202 | ||||
-rw-r--r-- | resolv/ns_ttl.c | 154 | ||||
-rw-r--r-- | resolv/nsap_addr.c | 34 | ||||
-rw-r--r-- | resolv/nss_dns/dns-host.c | 19 | ||||
-rw-r--r-- | resolv/nss_dns/dns-network.c | 14 | ||||
-rw-r--r-- | resolv/res_comp.c | 792 | ||||
-rw-r--r-- | resolv/res_data.c | 335 | ||||
-rw-r--r-- | resolv/res_debug.c | 1234 | ||||
-rw-r--r-- | resolv/res_debug.h | 34 | ||||
-rw-r--r-- | resolv/res_init.c | 436 | ||||
-rw-r--r-- | resolv/res_libc.c | 98 | ||||
-rw-r--r-- | resolv/res_mkquery.c | 81 | ||||
-rw-r--r-- | resolv/res_query.c | 261 | ||||
-rw-r--r-- | resolv/res_send.c | 759 | ||||
-rw-r--r-- | resolv/resolv.h | 299 |
25 files changed, 4469 insertions, 2877 deletions
diff --git a/resolv/Banner b/resolv/Banner index 5d1fdeb..d05a4e3 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 71a66fe..c8dc54a 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 9bf6a39..3448c92 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 8866d90..6655f3b 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 0000000..f67f5b3 --- /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 7f1b742..5808d92 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 0000000..b75f731 --- /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 0000000..9dcf91c --- /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 0000000..7bbdc41 --- /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 0000000..cce3fb6 --- /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 0000000..bac5a63 --- /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 0000000..6be2b0d --- /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 53a19d5..c1c9a61 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 482cbd3..483e791 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 f81341c..b194852 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 2d90e37..e6f54ce 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 aa3ecbd..a9f5a2a 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 dac878d..2df1c5b 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 0000000..4a0aa99 --- /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 e5520ff..bf6cf7f 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 0000000..14d565d --- /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 8f3e66f..dba2c80 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 80c1034..deebf4c 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 e315383..d3dc2ba 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 58742e9..b101262 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_ */ |