Integrate BIND 4.9.5 resolver and associated routines.
authordownsj <downsj@openbsd.org>
Thu, 13 Mar 1997 19:07:19 +0000 (19:07 +0000)
committerdownsj <downsj@openbsd.org>
Thu, 13 Mar 1997 19:07:19 +0000 (19:07 +0000)
Includes the DNS aware getnetby*() routines and IPv6 support.

24 files changed:
lib/libc/net/Makefile.inc
lib/libc/net/base64.c [new file with mode: 0644]
lib/libc/net/gethostbyname.3
lib/libc/net/gethostnamadr.c
lib/libc/net/getnetbyaddr.c
lib/libc/net/getnetbyname.c
lib/libc/net/getnetent.3
lib/libc/net/getnetnamadr.c [new file with mode: 0644]
lib/libc/net/herror.c
lib/libc/net/inet_addr.c
lib/libc/net/inet_net_ntop.c [new file with mode: 0644]
lib/libc/net/inet_net_pton.c [new file with mode: 0644]
lib/libc/net/inet_neta.c [new file with mode: 0644]
lib/libc/net/inet_ntop.c [new file with mode: 0644]
lib/libc/net/inet_pton.c [new file with mode: 0644]
lib/libc/net/nsap_addr.c
lib/libc/net/res_comp.c
lib/libc/net/res_data.c [new file with mode: 0644]
lib/libc/net/res_debug.c
lib/libc/net/res_init.c
lib/libc/net/res_mkquery.c
lib/libc/net/res_query.c
lib/libc/net/res_send.c
lib/libc/shlib_version

index 04831f4..03f7349 100644 (file)
@@ -1,15 +1,16 @@
-#      $OpenBSD: Makefile.inc,v 1.8 1996/09/01 21:25:34 millert Exp $
+#      $OpenBSD: Makefile.inc,v 1.9 1997/03/13 19:07:21 downsj Exp $
 
 # net sources
 .PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/net ${.CURDIR}/net
 
-SRCS+= gethostnamadr.c getnetbyaddr.c getnetbyname.c getnetent.c \
-       getproto.c getprotoent.c getprotoname.c getservbyname.c \
+SRCS+= base64.c gethostnamadr.c getnetbyaddr.c getnetbyname.c getnetent.c \
+       getnetnamadr.c getproto.c getprotoent.c getprotoname.c getservbyname.c \
        getservbyport.c getservent.c herror.c inet_addr.c inet_lnaof.c \
-       inet_makeaddr.c inet_netof.c inet_network.c inet_ntoa.c \
-       ipx_addr.c ipx_ntoa.c \
+       inet_makeaddr.c inet_neta.c inet_netof.c inet_network.c \
+       inet_net_ntop.c inet_net_pton.c inet_ntoa.c inet_ntop.c \
+       inet_pton.c ipx_addr.c ipx_ntoa.c \
        iso_addr.c linkaddr.c ns_addr.c ns_ntoa.c nsap_addr.c rcmd.c recv.c \
-       res_comp.c res_debug.c res_init.c res_mkquery.c res_query.c \
+       res_comp.c res_data.c res_debug.c res_init.c res_mkquery.c res_query.c \
        res_send.c send.c sethostent.c ethers.c rcmdsh.c
 
 # machine-dependent net sources
@@ -28,7 +29,7 @@ MLINKS+=ethers.3 ether_aton.3 ethers.3 ether_hostton.3 ethers.3 ether_line.3 \
        ethers.3 ether_ntoa.3 ethers.3 ether_ntohost.3
 MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \
        gethostbyname.3 sethostent.3 gethostbyname.3 gethostent.3 \
-       gethostbyname.3 herror.3
+       gethostbyname.3 herror.3 gethostbyname.3 gethostbyname2.3
 MLINKS+=getnetent.3 endnetent.3 getnetent.3 getnetbyaddr.3 \
        getnetent.3 getnetbyname.3 getnetent.3 setnetent.3
 MLINKS+=getprotoent.3 endprotoent.3 getprotoent.3 getprotobyname.3 \
diff --git a/lib/libc/net/base64.c b/lib/libc/net/base64.c
new file mode 100644 (file)
index 0000000..59788be
--- /dev/null
@@ -0,0 +1,319 @@
+/*     $OpenBSD: base64.c,v 1.1 1997/03/13 19:07:22 downsj Exp $       */
+
+/*
+ * 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.
+ */
+
+/*
+ * 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.
+ */
+
+#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 <resolv.h>
+#include <stdio.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#define Assert(Cond) if (!(Cond)) abort()
+
+static const char Base64[] =
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+   The following encoding technique is taken from RFC 1521 by Borenstein
+   and Freed.  It is reproduced here in a slightly edited form for
+   convenience.
+
+   A 65-character subset of US-ASCII is used, enabling 6 bits to be
+   represented per printable character. (The extra 65th character, "=",
+   is used to signify a special processing function.)
+
+   The encoding process represents 24-bit groups of input bits as output
+   strings of 4 encoded characters. Proceeding from left to right, a
+   24-bit input group is formed by concatenating 3 8-bit input groups.
+   These 24 bits are then treated as 4 concatenated 6-bit groups, each
+   of which is translated into a single digit in the base64 alphabet.
+
+   Each 6-bit group is used as an index into an array of 64 printable
+   characters. The character referenced by the index is placed in the
+   output string.
+
+                         Table 1: The Base64 Alphabet
+
+      Value Encoding  Value Encoding  Value Encoding  Value Encoding
+          0 A            17 R            34 i            51 z
+          1 B            18 S            35 j            52 0
+          2 C            19 T            36 k            53 1
+          3 D            20 U            37 l            54 2
+          4 E            21 V            38 m            55 3
+          5 F            22 W            39 n            56 4
+          6 G            23 X            40 o            57 5
+          7 H            24 Y            41 p            58 6
+          8 I            25 Z            42 q            59 7
+          9 J            26 a            43 r            60 8
+         10 K            27 b            44 s            61 9
+         11 L            28 c            45 t            62 +
+         12 M            29 d            46 u            63 /
+         13 N            30 e            47 v
+         14 O            31 f            48 w         (pad) =
+         15 P            32 g            49 x
+         16 Q            33 h            50 y
+
+   Special processing is performed if fewer than 24 bits are available
+   at the end of the data being encoded.  A full encoding quantum is
+   always completed at the end of a quantity.  When fewer than 24 input
+   bits are available in an input group, zero bits are added (on the
+   right) to form an integral number of 6-bit groups.  Padding at the
+   end of the data is performed using the '=' character.
+
+   Since all base64 input is an integral number of octets, only the
+         -------------------------------------------------                       
+   following cases can arise:
+   
+       (1) the final quantum of encoding input is an integral
+           multiple of 24 bits; here, the final unit of encoded
+          output will be an integral multiple of 4 characters
+          with no "=" padding,
+       (2) the final quantum of encoding input is exactly 8 bits;
+           here, the final unit of encoded output will be two
+          characters followed by two "=" padding characters, or
+       (3) the final quantum of encoding input is exactly 16 bits;
+           here, the final unit of encoded output will be three
+          characters followed by one "=" padding character.
+   */
+
+int
+b64_ntop(src, srclength, target, targsize)
+       u_char const *src;
+       size_t srclength;
+       char *target;
+       size_t targsize;
+{
+       size_t datalength = 0;
+       u_char input[3];
+       u_char output[4];
+       int i;
+
+       while (2 < srclength) {
+               input[0] = *src++;
+               input[1] = *src++;
+               input[2] = *src++;
+               srclength -= 3;
+
+               output[0] = input[0] >> 2;
+               output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+               output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+               output[3] = input[2] & 0x3f;
+               Assert(output[0] < 64);
+               Assert(output[1] < 64);
+               Assert(output[2] < 64);
+               Assert(output[3] < 64);
+
+               if (datalength + 4 > targsize)
+                       return (-1);
+               target[datalength++] = Base64[output[0]];
+               target[datalength++] = Base64[output[1]];
+               target[datalength++] = Base64[output[2]];
+               target[datalength++] = Base64[output[3]];
+       }
+    
+       /* Now we worry about padding. */
+       if (0 != srclength) {
+               /* Get what's left. */
+               input[0] = input[1] = input[2] = '\0';
+               for (i = 0; i < srclength; i++)
+                       input[i] = *src++;
+       
+               output[0] = input[0] >> 2;
+               output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+               output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+               Assert(output[0] < 64);
+               Assert(output[1] < 64);
+               Assert(output[2] < 64);
+
+               if (datalength + 4 > targsize)
+                       return (-1);
+               target[datalength++] = Base64[output[0]];
+               target[datalength++] = Base64[output[1]];
+               if (srclength == 1)
+                       target[datalength++] = Pad64;
+               else
+                       target[datalength++] = Base64[output[2]];
+               target[datalength++] = Pad64;
+       }
+       if (datalength >= targsize)
+               return (-1);
+       target[datalength] = '\0';      /* Returned value doesn't count \0. */
+       return (datalength);
+}
+
+/* skips all whitespace anywhere.
+   converts characters, four at a time, starting at (or after)
+   src from base - 64 numbers into three 8 bit bytes in the target area.
+   it returns the number of data bytes stored at the target, or -1 on error.
+ */
+
+int
+b64_pton(src, target, targsize)
+       char const *src;
+       u_char *target;
+       size_t targsize;
+{
+       int tarindex, state, ch;
+       char *pos;
+
+       state = 0;
+       tarindex = 0;
+
+       while ((ch = *src++) != '\0') {
+               if (isspace(ch))        /* Skip whitespace anywhere. */
+                       continue;
+
+               if (ch == Pad64)
+                       break;
+
+               pos = strchr(Base64, ch);
+               if (pos == 0)           /* A non-base64 character. */
+                       return (-1);
+
+               switch (state) {
+               case 0:
+                       if (target) {
+                               if (tarindex >= targsize)
+                                       return (-1);
+                               target[tarindex] = (pos - Base64) << 2;
+                       }
+                       state = 1;
+                       break;
+               case 1:
+                       if (target) {
+                               if (tarindex + 1 >= targsize)
+                                       return (-1);
+                               target[tarindex]   |=  (pos - Base64) >> 4;
+                               target[tarindex+1]  = ((pos - Base64) & 0x0f)
+                                                       << 4 ;
+                       }
+                       tarindex++;
+                       state = 2;
+                       break;
+               case 2:
+                       if (target) {
+                               if (tarindex + 1 >= targsize)
+                                       return (-1);
+                               target[tarindex]   |=  (pos - Base64) >> 2;
+                               target[tarindex+1]  = ((pos - Base64) & 0x03)
+                                                       << 6;
+                       }
+                       tarindex++;
+                       state = 3;
+                       break;
+               case 3:
+                       if (target) {
+                               if (tarindex >= targsize)
+                                       return (-1);
+                               target[tarindex] |= (pos - Base64);
+                       }
+                       tarindex++;
+                       state = 0;
+                       break;
+               default:
+                       abort();
+               }
+       }
+
+       /*
+        * We are done decoding Base-64 chars.  Let's see if we ended
+        * on a byte boundary, and/or with erroneous trailing characters.
+        */
+
+       if (ch == Pad64) {              /* We got a pad char. */
+               ch = *src++;            /* Skip it, get next. */
+               switch (state) {
+               case 0:         /* Invalid = in first position */
+               case 1:         /* Invalid = in second position */
+                       return (-1);
+
+               case 2:         /* Valid, means one byte of info */
+                       /* Skip any number of spaces. */
+                       for (NULL; ch != '\0'; ch = *src++)
+                               if (!isspace(ch))
+                                       break;
+                       /* Make sure there is another trailing = sign. */
+                       if (ch != Pad64)
+                               return (-1);
+                       ch = *src++;            /* Skip the = */
+                       /* Fall through to "single trailing =" case. */
+                       /* FALLTHROUGH */
+
+               case 3:         /* Valid, means two bytes of info */
+                       /*
+                        * We know this char is an =.  Is there anything but
+                        * whitespace after it?
+                        */
+                       for (NULL; ch != '\0'; ch = *src++)
+                               if (!isspace(ch))
+                                       return (-1);
+
+                       /*
+                        * Now make sure for cases 2 and 3 that the "extra"
+                        * bits that slopped past the last full byte were
+                        * zeros.  If we don't check them, they become a
+                        * subliminal channel.
+                        */
+                       if (target && target[tarindex] != 0)
+                               return (-1);
+               }
+       } else {
+               /*
+                * We ended by seeing the end of the string.  Make sure we
+                * have no partial bytes lying around.
+                */
+               if (state != 0)
+                       return (-1);
+       }
+
+       return (tarindex);
+}
index 8dfdb88..1394fa3 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: gethostbyname.3,v 1.3 1996/08/19 08:28:38 tholo Exp $
+.\"    $OpenBSD: gethostbyname.3,v 1.4 1997/03/13 19:07:23 downsj Exp $
 .\"
 .\" Copyright (c) 1983, 1987, 1991, 1993
 .\"    The Regents of the University of California.  All rights reserved.
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd April 19, 1994
+.Dd March 13, 1997
 .Dt GETHOSTBYNAME 3
-.Os BSD 4.2
+.Os
 .Sh NAME
 .Nm gethostbyname ,
+.Nm gethostbyname2 ,
 .Nm gethostbyaddr ,
 .Nm gethostent ,
 .Nm sethostent ,
@@ -48,6 +49,8 @@
 .Ft struct hostent *
 .Fn gethostbyname "const char *name"
 .Ft struct hostent *
+.Fn gethostbyname2 "const char *name" "int af"
+.Ft struct hostent *
 .Fn gethostbyaddr "const char *addr" "int len" "int type"
 .Ft struct hostent *
 .Fn gethostent void
@@ -93,8 +96,7 @@ Official name of the host.
 .It Fa h_aliases
 A zero terminated array of alternate names for the host.
 .It Fa h_addrtype
-The type of address being returned; currently always
-.Dv AF_INET .
+The type of address being returned.
 .It Fa h_length
 The length, in bytes, of the address.
 .It Fa h_addr_list
@@ -104,6 +106,7 @@ Host addresses are returned in network byte order.
 The first address in
 .Fa h_addr_list ;
 this is for backward compatibility.
+.El
 .Pp
 When using the nameserver,
 .Fn gethostbyname
@@ -117,6 +120,14 @@ See
 .Xr hostname 7
 for the domain search procedure and the alias file format.
 .Pp
+.Fn Gethostbyname2
+is an advanced form of
+.Fn gethostbyname
+which allows lookups in address families other than
+.Dv AF_INET ,
+for example
+.Dv AF_INET6 .
+.Pp
 The
 .Fn sethostent
 function
@@ -148,7 +159,8 @@ connection.
 .El
 .Sh DIAGNOSTICS
 Error return status from 
-.Fn gethostbyname
+.Fn gethostbyname ,
+.Fn gethostbyname2 ,
 and
 .Fn gethostbyaddr
 is indicated by return of a null pointer.
@@ -198,20 +210,6 @@ for example, a mail-forwarder may be registered for this domain.
 The
 .Fn gethostent
 function
-is defined, and
-.Fn sethostent
-and
-.Fn endhostent
-are redefined,
-when
-.Xr libc 3
-is built to use only the routines to lookup in
-.Pa /etc/hosts
-and not the name server.
-.Pp
-The
-.Fn gethostent
-function
 reads the next line of
 .Pa /etc/hosts ,
 opening the file if necessary.
@@ -225,7 +223,8 @@ If the
 .Fa stayopen
 argument is non-zero,
 the file will not be closed after each call to
-.Fn gethostbyname
+.Fn gethostbyname ,
+.Fn gethostbyname2 ,
 or
 .Fn gethostbyaddr .
 .Pp
@@ -252,4 +251,9 @@ These functions use static data storage;
 if the data is needed for future use, it should be
 copied before any subsequent calls overwrite it.
 Only the Internet
-address format is currently understood.
+address formats are currently understood.
+.Pp
+YP does not support any address families other than 
+.Dv AF_INET
+and uses
+the traditional database format.
index 83e0225..9826b46 100644 (file)
@@ -52,7 +52,7 @@
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.13 1997/01/30 05:56:06 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.14 1997/03/13 19:07:24 downsj Exp $";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
@@ -66,6 +66,7 @@ static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.13 1997/01/30 05:56:06 dera
 #include <ctype.h>
 #include <errno.h>
 #include <string.h>
+#include <syslog.h>
 #ifdef YP
 #include <rpc/rpc.h>
 #include <rpcsvc/yp.h>
@@ -73,6 +74,8 @@ static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.13 1997/01/30 05:56:06 dera
 #include "ypinternal.h"
 #endif
 
+#define MULTI_PTRS_ARE_ALIASES 1       /* XXX - experimental */
+
 #define        MAXALIASES      35
 #define        MAXADDRS        35
 
@@ -85,10 +88,22 @@ static char *__ypdomain;
 static struct hostent host;
 static char *host_aliases[MAXALIASES];
 static char hostbuf[BUFSIZ+1];
-static struct in_addr host_addr;
+static u_char host_addr[16];           /* IPv4 or IPv6 */
 static FILE *hostf = NULL;
 static int stayopen = 0;
 
+static void map_v4v6_address __P((const char *src, char *dst));
+static void map_v4v6_hostent __P((struct hostent *hp, char **bp, int *len));
+
+#ifdef RESOLVSORT
+static void addrsort __P((char **, int));
+#endif
+
+static int hokchar __P((const char *));
+
+static const char AskedForGot[] =
+                         "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
+
 #if PACKETSZ > 1024
 #define        MAXPACKET       PACKETSZ
 #else
@@ -105,15 +120,14 @@ typedef union {
        char ac;
 } align;
 
-static int qcomp __P((struct in_addr **, struct in_addr **));
-static struct hostent *getanswer __P((querybuf *, int, int));
-static int hbadchar __P((char *));
+static struct hostent *getanswer __P((const querybuf *, int, const char *,
+                                     int));
 
 extern int h_errno;
 
 static int
-hbadchar(p)
-       char *p;
+hokchar(p)
+       const char *p;
 {
        char c;
 
@@ -121,7 +135,7 @@ hbadchar(p)
         * Many people do not obey RFC 822 and 1035.  The valid
         * characters are a-z, A-Z, 0-9, '-' and . But the others
         * tested for below can happen, and we must be more permissive
-        * until those idiots clean up their act.
+        * than the resolver until those idiots clean up their act.
         */
        while ((c = *p++)) {
                if (('a' >= c && c <= 'z') ||
@@ -130,28 +144,50 @@ hbadchar(p)
                        continue;
                if (strchr("-_/.[]\\", c) ||
                    (c == '.' && p[1] == '.'))
-                       return 1;
+                       return 0;
        }
-       return 0;
+       return 1;
 }
 
 static struct hostent *
-getanswer(answer, anslen, iquery)
-       querybuf *answer;
+getanswer(answer, anslen, qname, qtype)
+       const querybuf *answer;
        int anslen;
-       int iquery;
+       const char *qname;
+       int qtype;
 {
-       register HEADER *hp;
-       register u_char *cp;
+       register const HEADER *hp;
+       register const u_char *cp;
        register int n;
-       u_char *eom;
-       char *bp, **ap;
+       const u_char *eom;
+       char *bp, **ap, **hap;
        int type, class, buflen, ancount, qdcount;
-       int haveanswer, getclass = C_ANY;
-       char **hap;
-       int good = 1;
+       int haveanswer, had_error;
+       int toobig = 0;
+       char tbuf[MAXDNAME];
+       const char *tname;
+       int (*name_ok) __P((const char *));
 
+       tname = qname;
+       host.h_name = NULL;
        eom = answer->buf + anslen;
+       switch (qtype) {
+       case T_A:
+       case T_AAAA:
+#ifdef USE_RESOLV_NAME_OK
+               name_ok = res_hnok;
+               break;
+#endif
+       case T_PTR:
+#ifdef USE_RESOLV_NAME_OK
+               name_ok = res_dnok;
+#else
+               name_ok = hokchar;
+#endif
+               break;
+       default:
+               return (NULL);  /* XXX should be abort(); */
+       }
        /*
         * find first satisfactory answer
         */
@@ -159,34 +195,29 @@ getanswer(answer, anslen, iquery)
        ancount = ntohs(hp->ancount);
        qdcount = ntohs(hp->qdcount);
        bp = hostbuf;
-       buflen = sizeof(hostbuf);
-       cp = answer->buf + sizeof(HEADER);
-       if (qdcount) {
-               if (iquery) {
-                       if ((n = dn_expand((u_char *)answer->buf,
-                           (u_char *)eom, (u_char *)cp, bp,
-                           buflen)) < 0) {
-                               h_errno = NO_RECOVERY;
-                               return ((struct hostent *) NULL);
-                       }
-                       cp += n + QFIXEDSZ;
-                       host.h_name = bp;
-                       n = strlen(bp);
-                       if (n >= MAXHOSTNAMELEN)
-                               host.h_name[MAXHOSTNAMELEN-1] = '\0';
-                       n++;
-                       bp += n;
-                       buflen -= n;
-               } else
-                       cp += __dn_skipname(cp, eom) + QFIXEDSZ;
-               while (--qdcount > 0)
-                       cp += __dn_skipname(cp, eom) + QFIXEDSZ;
-       } else if (iquery) {
-               if (hp->aa)
-                       h_errno = HOST_NOT_FOUND;
-               else
-                       h_errno = TRY_AGAIN;
-               return ((struct hostent *) NULL);
+       buflen = sizeof hostbuf;
+       cp = answer->buf + HFIXEDSZ;
+       if (qdcount != 1) {
+               h_errno = NO_RECOVERY;
+               return (NULL);
+       }
+       n = dn_expand(answer->buf, eom, cp, bp, buflen);
+       if ((n < 0) || !(*name_ok)(bp)) {
+               h_errno = NO_RECOVERY;
+               return (NULL);
+       }
+       cp += n + QFIXEDSZ;
+       if (qtype == T_A || qtype == T_AAAA) {
+               /* res_send() has already verified that the query name is the
+                * same as the one we sent; this just gets the expanded name
+                * (i.e., with the succeeding search-domain tacked on).
+                */
+               n = strlen(bp) + 1;             /* for the \0 */
+               host.h_name = bp;
+               bp += n;
+               buflen -= n;
+               /* The qname can be abbreviated, but h_name is now absolute. */
+               qname = host.h_name;
        }
        ap = host_aliases;
        *ap = NULL;
@@ -195,124 +226,258 @@ getanswer(answer, anslen, iquery)
        *hap = NULL;
        host.h_addr_list = h_addr_ptrs;
        haveanswer = 0;
-       if (ancount > MAXADDRS)
-               ancount = MAXADDRS;
-       while (--ancount >= 0 && cp < eom) {
-               if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom,
-                   (u_char *)cp, bp, buflen)) < 0)
-                       break;
-               cp += n;
+       had_error = 0;
+       while (ancount-- > 0 && cp < eom && !had_error) {
+               n = dn_expand(answer->buf, eom, cp, bp, buflen);
+               if ((n < 0) || !(*name_ok)(bp)) {
+                       had_error++;
+                       continue;
+               }
+               cp += n;                        /* name */
                type = _getshort(cp);
-               cp += sizeof(u_int16_t);
+               cp += INT16SZ;                  /* type */
                class = _getshort(cp);
-               cp += sizeof(u_int16_t) + sizeof(u_int32_t);
+               cp += INT16SZ + INT32SZ;        /* class, TTL */
                n = _getshort(cp);
-               cp += sizeof(u_int16_t);
-               if (type == T_CNAME) {
+               cp += INT16SZ;                  /* len */
+               if (class != C_IN) {
+                       /* XXX - debug? syslog? */
                        cp += n;
+                       continue;               /* XXX - had_error++ ? */
+               }
+               if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
                        if (ap >= &host_aliases[MAXALIASES-1])
                                continue;
+                       n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
+                       if ((n < 0) || !(*name_ok)(tbuf)) {
+                               had_error++;
+                               continue;
+                       }
+                       cp += n;
+                       /* Store alias. */
                        *ap++ = bp;
-                       n = strlen(bp) + 1;
-                       if (n > MAXHOSTNAMELEN)
-                               bp[MAXHOSTNAMELEN-1] = '\0';
+                       n = strlen(bp) + 1;     /* for the \0 */
+                       bp += n;
+                       buflen -= n;
+                       /* Get canonical name. */
+                       n = strlen(tbuf) + 1;   /* for the \0 */
+                       if (n > buflen) {
+                               had_error++;
+                               continue;
+                       }
+                       strcpy(bp, tbuf);
+                       host.h_name = bp;
                        bp += n;
                        buflen -= n;
                        continue;
                }
-               if (iquery && type == T_PTR) {
-                       if ((n = dn_expand((u_char *)answer->buf,
-                           (u_char *)eom, (u_char *)cp, bp,
-                           buflen)) < 0)
-                               break;
+               if (qtype == T_PTR && type == T_CNAME) {
+                       n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
+                       if ((n < 0) || !res_hnok(tbuf)) {
+                               had_error++;
+                               continue;
+                       }
                        cp += n;
-                       host.h_name = bp;
-                       n = strlen(host.h_name);
-                       if (n >= MAXHOSTNAMELEN)
-                               host.h_name[MAXHOSTNAMELEN-1] = '\0';
-                       goto gotent;
+                       /* Get canonical name. */
+                       n = strlen(tbuf) + 1;   /* for the \0 */
+                       if (n > buflen) {
+                               had_error++;
+                               continue;
+                       }
+                       strcpy(bp, tbuf);
+                       tname = bp;
+                       bp += n;
+                       buflen -= n;
+                       continue;
                }
-               if (iquery || type != T_A)  {
-#ifdef DEBUG
-                       if (_res.options & RES_DEBUG)
-                               printf("unexpected answer type %d, size %d\n",
-                                       type, n);
-#endif
+               if (type != qtype) {
+                       syslog(LOG_NOTICE|LOG_AUTH,
+              "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
+                              qname, p_class(C_IN), p_type(qtype),
+                              p_type(type));
                        cp += n;
-                       continue;
+                       continue;               /* XXX - had_error++ ? */
                }
-
-               if (haveanswer) {
-                       if (n != host.h_length) {
+               switch (type) {
+               case T_PTR:
+                       if (strcasecmp(tname, bp) != 0) {
+                               syslog(LOG_NOTICE|LOG_AUTH,
+                                      AskedForGot, qname, bp);
                                cp += n;
-                               continue;
+                               continue;       /* XXX - had_error++ ? */
                        }
-                       if (class != getclass) {
+                       n = dn_expand(answer->buf, eom, cp, bp, buflen);
+                       if ((n < 0) || !res_hnok(bp)) {
+                               had_error++;
+                               break;
+                       }
+#if MULTI_PTRS_ARE_ALIASES
+                       cp += n;
+                       if (!haveanswer)
+                               host.h_name = bp;
+                       else if (ap < &host_aliases[MAXALIASES-1])
+                               *ap++ = bp;
+                       else
+                               n = -1;
+                       if (n != -1) {
+                               n = strlen(bp) + 1;     /* for the \0 */
+                               bp += n;
+                               buflen -= n;
+                       }
+                       break;
+#else
+                       host.h_name = bp;
+                       if (_res.options & RES_USE_INET6) {
+                               n = strlen(bp) + 1;     /* for the \0 */
+                               bp += n;
+                               buflen -= n;
+                               map_v4v6_hostent(&host, &bp, &buflen);
+                       }
+                       h_errno = NETDB_SUCCESS;
+                       return (&host);
+#endif
+               case T_A:
+               case T_AAAA:
+                       if (strcasecmp(host.h_name, bp) != 0) {
+                               syslog(LOG_NOTICE|LOG_AUTH,
+                                      AskedForGot, host.h_name, bp);
+                               cp += n;
+                               continue;       /* XXX - had_error++ ? */
+                       }
+                       if (n != host.h_length) {
                                cp += n;
                                continue;
                        }
-               } else {
-                       host.h_length = n;
-                       getclass = class;
-                       host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
-                       if (host.h_addrtype == AF_INET)
-                               host.h_length = INADDRSZ;
-                       if (!iquery) {
+                       if (!haveanswer) {
+                               register int nn;
+
                                host.h_name = bp;
-                               bp += strlen(bp) + 1;
-                               if (strlen(host.h_name) >= MAXHOSTNAMELEN)
-                                       host.h_name[MAXHOSTNAMELEN-1] = '\0';
+                               nn = strlen(bp) + 1;    /* for the \0 */
+                               bp += nn;
+                               buflen -= nn;
                        }
-               }
 
-               bp += sizeof(align) - ((u_long)bp % sizeof(align));
+                       bp += sizeof(align) - ((u_long)bp % sizeof(align));
 
-               if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
+                       if (bp + n >= &hostbuf[sizeof hostbuf]) {
+#ifdef DEBUG
+                               if (_res.options & RES_DEBUG)
+                                       printf("size (%d) too big\n", n);
+#endif
+                               had_error++;
+                               continue;
+                       }
+                       if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
+                               if (!toobig++)
 #ifdef DEBUG
-                       if (_res.options & RES_DEBUG)
-                               printf("size (%d) too big\n", n);
+                                       if (_res.options & RES_DEBUG)
+                                               printf("Too many addresses (%d)\n", MAXADDRS);
 #endif
+                               cp += n;
+                               continue;
+                       }
+                       bcopy(cp, *hap++ = bp, n);
+                       bp += n;
+                       buflen -= n;
+                       cp += n;
                        break;
+               default:
+                       abort();
                }
-               bcopy(cp, *hap++ = bp, n);
-               bp +=n;
-               cp += n;
-               haveanswer++;
-       }
-       if (!haveanswer) {
-               h_errno = TRY_AGAIN;
-               return ((struct hostent *) NULL);
-       }
-       *ap = NULL;
-       *hap = NULL;
-       if (_res.nsort) {
-               qsort(host.h_addr_list, haveanswer,
-                   sizeof(struct in_addr),
-                   (int (*)__P((const void *, const void *)))qcomp);
+               if (!had_error)
+                       haveanswer++;
        }
-gotent:
-       if (hbadchar(host.h_name))
-               good = 0;
-       for (ap = host_aliases; good && *ap; ap++)
-               if (hbadchar(*ap))
-                       good = 0;
-       if (good)
+       if (haveanswer) {
+               *ap = NULL;
+               *hap = NULL;
+# if defined(RESOLVSORT)
+               /*
+                * Note: we sort even if host can take only one address
+                * in its return structures - should give it the "best"
+                * address in that case, not some random one
+                */
+               if (_res.nsort && haveanswer > 1 && qtype == T_A)
+                       addrsort(h_addr_ptrs, haveanswer);
+# endif /*RESOLVSORT*/
+               if (!host.h_name) {
+                       n = strlen(qname) + 1;  /* for the \0 */
+                       if (n > buflen)
+                               goto try_again;
+                       strcpy(bp, qname);
+                       host.h_name = bp;
+                       bp += n;
+                       buflen -= n;
+               }
+               if (_res.options & RES_USE_INET6)
+                       map_v4v6_hostent(&host, &bp, &buflen);
+               h_errno = NETDB_SUCCESS;
                return (&host);
-       h_errno = NO_RECOVERY;
-       return ((struct hostent *) NULL);
+       }
+ try_again:
+       h_errno = TRY_AGAIN;
+       return (NULL);
 }
 
 struct hostent *
 gethostbyname(name)
        const char *name;
+{
+       struct hostent *hp;
+       extern struct hostent *_gethtbyname2();
+
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+               return (_gethtbyname2(name, AF_INET));
+
+       if (_res.options & RES_USE_INET6) {
+               hp = gethostbyname2(name, AF_INET6);
+               if (hp)
+                       return (hp);
+       }
+       return (gethostbyname2(name, AF_INET));
+}
+
+struct hostent *
+gethostbyname2(name, af)
+       const char *name;
+       int af;
 {
        querybuf buf;
        register const char *cp;
-       int n, i;
-       extern struct hostent *_gethtbyname(), *_yp_gethtbyname();
+       char *bp;
+       int n, size, type, len, i;
+       extern struct hostent *_gethtbyname2(), *_yp_gethtbyname();
        register struct hostent *hp;
        char lookups[MAXDNSLUS];
 
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+               return (_gethtbyname2(name, af));
+
+       switch (af) {
+       case AF_INET:
+               size = INADDRSZ;
+               type = T_A;
+               break;
+       case AF_INET6:
+               size = IN6ADDRSZ;
+               type = T_AAAA;
+               break;
+       default:
+               h_errno = NETDB_INTERNAL;
+               errno = EAFNOSUPPORT;
+               return (NULL);
+       }
+
+       host.h_addrtype = af;
+       host.h_length = size;
+
+       /*
+        * if there aren't any dots, it could be a user-level alias.
+        * this is also done in res_query() since we are not the only
+        * function that looks up host names.
+        */
+       if (!strchr(name, '.') && (cp = __hostalias(name)))
+               name = cp;
+
        /*
         * disallow names consisting only of digits/dots, unless
         * they end in a dot.
@@ -327,26 +492,58 @@ gethostbyname(name)
                                 * Fake up a hostent as if we'd actually
                                 * done a lookup.
                                 */
-                               if (!inet_aton(name, &host_addr)) {
+                               if (inet_pton(af, name, host_addr) <= 0) {
                                        h_errno = HOST_NOT_FOUND;
-                                       return((struct hostent *) NULL);
+                                       return (NULL);
                                }
-                               host.h_name = (char *)name;
+                               strncpy(hostbuf, name, MAXDNAME);
+                               hostbuf[MAXDNAME] = '\0';
+                               bp = hostbuf + MAXDNAME;
+                               len = sizeof hostbuf - MAXDNAME;
+                               host.h_name = hostbuf;
                                host.h_aliases = host_aliases;
                                host_aliases[0] = NULL;
-                               host.h_addrtype = AF_INET;
-                               host.h_length = sizeof(u_int32_t);
-                               h_addr_ptrs[0] = (char *)&host_addr;
+                               h_addr_ptrs[0] = (char *)host_addr;
                                h_addr_ptrs[1] = NULL;
                                host.h_addr_list = h_addr_ptrs;
+                               if (_res.options & RES_USE_INET6)
+                                       map_v4v6_hostent(&host, &bp, &len);
+                               h_errno = NETDB_SUCCESS;
                                return (&host);
                        }
                        if (!isdigit(*cp) && *cp != '.') 
                                break;
                }
-
-       if ((_res.options & RES_INIT) == 0 && res_init() == -1)
-               return (_gethtbyname(name));
+       if (isxdigit(name[0]) || name[0] == ':')
+               for (cp = name;; ++cp) {
+                       if (!*cp) {
+                               if (*--cp == '.')
+                                       break;
+                               /*
+                                * All-IPv6-legal, no dot at the end.
+                                * Fake up a hostent as if we'd actually
+                                * done a lookup.
+                                */
+                               if (inet_pton(af, name, host_addr) <= 0) {
+                                       h_errno = HOST_NOT_FOUND;
+                                       return (NULL);
+                               }
+                               strncpy(hostbuf, name, MAXDNAME);
+                               hostbuf[MAXDNAME] = '\0';
+                               bp = hostbuf + MAXDNAME;
+                               len = sizeof hostbuf - MAXDNAME;
+                               host.h_name = hostbuf;
+                               host.h_aliases = host_aliases;
+                               host_aliases[0] = NULL;
+                               h_addr_ptrs[0] = (char *)host_addr;
+                               h_addr_ptrs[1] = NULL;
+                               host.h_addr_list = h_addr_ptrs;
+                               h_errno = NETDB_SUCCESS;
+                               return (&host);
+                       }
+                       if (!isxdigit(*cp) && *cp != ':' && *cp != '.') 
+                               break;
+               }
 
        bcopy(_res.lookups, lookups, sizeof lookups);
        if (lookups[0] == '\0')
@@ -357,11 +554,13 @@ gethostbyname(name)
                switch (lookups[i]) {
 #ifdef YP
                case 'y':
-                       hp = _yp_gethtbyname(name);
+                       /* YP only suports AF_INET. */
+                       if (af == AF_INET)
+                               hp = _yp_gethtbyname(name);
                        break;
 #endif
                case 'b':
-                       if ((n = res_search(name, C_IN, T_A, buf.buf,
+                       if ((n = res_search(name, C_IN, type, buf.buf,
                            sizeof(buf))) < 0) {
 #ifdef DEBUG
                                if (_res.options & RES_DEBUG)
@@ -369,10 +568,10 @@ gethostbyname(name)
 #endif
                                break;
                        }
-                       hp = getanswer(&buf, n, 0);
+                       hp = getanswer(&buf, n, name, type);
                        break;
                case 'f':
-                       hp = _gethtbyname(name);
+                       hp = _gethtbyname2(name, af);
                        break;
                }
        }
@@ -380,27 +579,69 @@ gethostbyname(name)
 }
 
 struct hostent *
-gethostbyaddr(addr, len, type)
-       const char *addr;
-       int len, type;
+gethostbyaddr(addr, len, af)
+       const char *addr;       /* XXX should have been def'd as u_char! */
+       int len, af;
 {
-       int n, i;
+       const u_char *uaddr = (const u_char *)addr;
+       static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
+       static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
+       int n, size, i;
        querybuf buf;
        register struct hostent *hp;
-       char qbuf[MAXDNAME];
+       char qbuf[MAXDNAME+1], *qp;
        extern struct hostent *_gethtbyaddr(), *_yp_gethtbyaddr();
        char lookups[MAXDNSLUS];
        
-       if (type != AF_INET)
-               return ((struct hostent *) NULL);
-       (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
-               ((unsigned)addr[3] & 0xff),
-               ((unsigned)addr[2] & 0xff),
-               ((unsigned)addr[1] & 0xff),
-               ((unsigned)addr[0] & 0xff));
-
        if ((_res.options & RES_INIT) == 0 && res_init() == -1)
-               return (_gethtbyaddr(addr, len, type));
+               return (_gethtbyaddr(addr, len, af));
+
+       if (af == AF_INET6 && len == IN6ADDRSZ &&
+           (!bcmp(uaddr, mapped, sizeof mapped) ||
+            !bcmp(uaddr, tunnelled, sizeof tunnelled))) {
+               /* Unmap. */
+               addr += sizeof mapped;
+               uaddr += sizeof mapped;
+               af = AF_INET;
+               len = INADDRSZ;
+       }
+       switch (af) {
+       case AF_INET:
+               size = INADDRSZ;
+               break;
+       case AF_INET6:
+               size = IN6ADDRSZ;
+               break;
+       default:
+               errno = EAFNOSUPPORT;
+               h_errno = NETDB_INTERNAL;
+               return (NULL);
+       }
+       if (size != len) {
+               errno = EINVAL;
+               h_errno = NETDB_INTERNAL;
+               return (NULL);
+       }
+       switch (af) {
+       case AF_INET:
+               (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
+                              (uaddr[3] & 0xff),
+                              (uaddr[2] & 0xff),
+                              (uaddr[1] & 0xff),
+                              (uaddr[0] & 0xff));
+               break;
+       case AF_INET6:
+               qp = qbuf;
+               for (n = IN6ADDRSZ - 1; n >= 0; n--) {
+                       qp += sprintf(qp, "%x.%x.",
+                                      uaddr[n] & 0xf,
+                                      (uaddr[n] >> 4) & 0xf);
+               }
+               strcpy(qp, "ip6.int");
+               break;
+       default:
+               abort();
+       }
 
        bcopy(_res.lookups, lookups, sizeof lookups);
        if (lookups[0] == '\0')
@@ -411,29 +652,38 @@ gethostbyaddr(addr, len, type)
                switch (lookups[i]) {
 #ifdef YP
                case 'y':
-                       hp = _yp_gethtbyaddr(addr);
+                       /* YP only supports AF_INET. */
+                       if (af == AF_INET)
+                               hp = _yp_gethtbyaddr(addr);
                        break;
 #endif
                case 'b':
-                       n = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
+                       n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf,
+                           sizeof buf.buf);
                        if (n < 0) {
 #ifdef DEBUG
                                if (_res.options & RES_DEBUG)
                                        printf("res_query failed\n");
 #endif
-                               break;
+                               return (NULL);
                        }
-                       hp = getanswer(&buf, n, 1);
-                       if (hp == NULL)
-                               break;
-                       hp->h_addrtype = type;
+                       if (!(hp = getanswer(&buf, n, qbuf, T_PTR)))
+                               return (NULL);  /* h_errno was set by getanswer() */
+                       hp->h_addrtype = af;
                        hp->h_length = len;
-                       h_addr_ptrs[0] = (char *)&host_addr;
-                       h_addr_ptrs[1] = (char *)0;
-                       host_addr = *(struct in_addr *)addr;
+                       bcopy(addr, host_addr, len);
+                       h_addr_ptrs[0] = (char *)host_addr;
+                       h_addr_ptrs[1] = NULL;
+                       if (af == AF_INET && (_res.options & RES_USE_INET6)) {
+                               map_v4v6_address((char*)host_addr,
+                                   (char*)host_addr);
+                               hp->h_addrtype = AF_INET6;
+                               hp->h_length = IN6ADDRSZ;
+                       }
+                       h_errno = NETDB_SUCCESS;
                        break;
                case 'f':
-                       hp = _gethtbyaddr(addr, len, type);
+                       hp = _gethtbyaddr(addr, len, af);
                        break;
                }
        }
@@ -465,35 +715,51 @@ _gethtent()
 {
        char *p;
        register char *cp, **q;
+       int af, len;
 
-       if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL)
+       if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
+               h_errno = NETDB_INTERNAL;
                return (NULL);
-again:
-       if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL)
+       }
+ again:
+       if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
+               h_errno = HOST_NOT_FOUND;
                return (NULL);
+       }
        if (*p == '#')
                goto again;
-       cp = strpbrk(p, "#\n");
-       if (cp == NULL)
+       if (!(cp = strpbrk(p, "#\n")))
                goto again;
        *cp = '\0';
-       cp = strpbrk(p, " \t");
-       if (cp == NULL)
+       if (!(cp = strpbrk(p, " \t")))
                goto again;
        *cp++ = '\0';
-       /* THIS STUFF IS INTERNET SPECIFIC */
-       h_addr_ptrs[0] = (char *)&host_addr;
+       if ((_res.options & RES_USE_INET6) &&
+           inet_pton(AF_INET6, p, host_addr) > 0) {
+               af = AF_INET6;
+               len = IN6ADDRSZ;
+       } else if (inet_pton(AF_INET, p, host_addr) > 0) {
+               if (_res.options & RES_USE_INET6) {
+                       map_v4v6_address((char*)host_addr, (char*)host_addr);
+                       af = AF_INET6;
+                       len = IN6ADDRSZ;
+               } else {
+                       af = AF_INET;
+                       len = INADDRSZ;
+               }
+       } else {
+               goto again;
+       }
+       h_addr_ptrs[0] = (char *)host_addr;
        h_addr_ptrs[1] = NULL;
-       (void) inet_aton(p, &host_addr);
        host.h_addr_list = h_addr_ptrs;
-       host.h_length = sizeof(u_int32_t);
-       host.h_addrtype = AF_INET;
+       host.h_length = len;
+       host.h_addrtype = af;
        while (*cp == ' ' || *cp == '\t')
                cp++;
        host.h_name = cp;
        q = host.h_aliases = host_aliases;
-       cp = strpbrk(cp, " \t");
-       if (cp != NULL) 
+       if (cp = strpbrk(cp, " \t"))
                *cp++ = '\0';
        while (cp && *cp) {
                if (*cp == ' ' || *cp == '\t') {
@@ -502,70 +768,73 @@ again:
                }
                if (q < &host_aliases[MAXALIASES - 1])
                        *q++ = cp;
-               cp = strpbrk(cp, " \t");
-               if (cp != NULL)
+               if (cp = strpbrk(cp, " \t"))
                        *cp++ = '\0';
        }
        *q = NULL;
+       if (_res.options & RES_USE_INET6) {
+               char *bp = hostbuf;
+               int buflen = sizeof hostbuf;
+
+               map_v4v6_hostent(&host, &bp, &buflen);
+       }
+       h_errno = NETDB_SUCCESS;
        return (&host);
 }
 
 struct hostent *
 _gethtbyname(name)
        const char *name;
+{
+       extern struct hostent *_gethtbyname2();
+       struct hostent *hp;
+
+       if (_res.options & RES_USE_INET6) {
+               hp = _gethtbyname2(name, AF_INET6);
+               if (hp)
+                       return (hp);
+       }
+       return (_gethtbyname2(name, AF_INET));
+}
+
+struct hostent *
+_gethtbyname2(name, af)
+       const char *name;
+       int af;
 {
        register struct hostent *p;
        register char **cp;
        
        _sethtent(0);
        while (p = _gethtent()) {
+               if (p->h_addrtype != af)
+                       continue;
                if (strcasecmp(p->h_name, name) == 0)
                        break;
                for (cp = p->h_aliases; *cp != 0; cp++)
                        if (strcasecmp(*cp, name) == 0)
                                goto found;
        }
-found:
+ found:
        _endhtent();
-       if (p==NULL)
-               h_errno = HOST_NOT_FOUND;
        return (p);
 }
 
 struct hostent *
-_gethtbyaddr(addr, len, type)
+_gethtbyaddr(addr, len, af)
        const char *addr;
-       int len, type;
+       int len, af;
 {
        register struct hostent *p;
 
        _sethtent(0);
        while (p = _gethtent())
-               if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
+               if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
                        break;
        _endhtent();
-       if (p==NULL)
-               h_errno = HOST_NOT_FOUND;
        return (p);
 }
 
-static int
-qcomp(a1, a2)
-       struct in_addr **a1, **a2;
-{
-       int pos1, pos2;
-
-       for (pos1 = 0; pos1 < _res.nsort; pos1++)
-               if (_res.sort_list[pos1].addr.s_addr ==
-                   ((*a1)->s_addr & _res.sort_list[pos1].mask))
-                       break;
-       for (pos2 = 0; pos2 < _res.nsort; pos2++)
-               if (_res.sort_list[pos2].addr.s_addr ==
-                   ((*a2)->s_addr & _res.sort_list[pos2].mask))
-                       break;
-       return pos1 - pos2;
-}
-
 #ifdef YP
 struct hostent *
 _yphostent(line)
@@ -687,10 +956,104 @@ _yp_gethtbyname(name)
        __ypcurrent = NULL;
        r = yp_match(__ypdomain, "hosts.byname", name,
                strlen(name), &__ypcurrent, &__ypcurrentlen);
-       if (r==0)
+       if (r == 0)
                hp = _yphostent(__ypcurrent);
-       if (hp==NULL)
+       if (hp == NULL)
                h_errno = HOST_NOT_FOUND;
        return (hp);
 }
 #endif
+
+static void
+map_v4v6_address(src, dst)
+       const char *src;
+       char *dst;
+{
+       u_char *p = (u_char *)dst;
+       char tmp[INADDRSZ];
+       int i;
+
+       /* Stash a temporary copy so our caller can update in place. */
+       bcopy(src, tmp, INADDRSZ);
+       /* Mark this ipv6 addr as a mapped ipv4. */
+       for (i = 0; i < 10; i++)
+               *p++ = 0x00;
+       *p++ = 0xff;
+       *p++ = 0xff;
+       /* Retrieve the saved copy and we're done. */
+       bcopy(tmp, (void*)p, INADDRSZ);
+}
+
+static void
+map_v4v6_hostent(hp, bpp, lenp)
+       struct hostent *hp;
+       char **bpp;
+       int *lenp;
+{
+       char **ap;
+
+       if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
+               return;
+       hp->h_addrtype = AF_INET6;
+       hp->h_length = IN6ADDRSZ;
+       for (ap = hp->h_addr_list; *ap; ap++) {
+               int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
+
+               if (*lenp < (i + IN6ADDRSZ)) {
+                       /* Out of memory.  Truncate address list here.  XXX */
+                       *ap = NULL;
+                       return;
+               }
+               *bpp += i;
+               *lenp -= i;
+               map_v4v6_address(*ap, *bpp);
+               *ap = *bpp;
+               *bpp += IN6ADDRSZ;
+               *lenp -= IN6ADDRSZ;
+       }
+}
+
+#ifdef RESOLVSORT
+static void
+addrsort(ap, num)
+       char **ap;
+       int num;
+{
+       int i, j;
+       char **p;
+       short aval[MAXADDRS];
+       int needsort = 0;
+
+       p = ap;
+       for (i = 0; i < num; i++, p++) {
+           for (j = 0 ; (unsigned)j < _res.nsort; j++)
+               if (_res.sort_list[j].addr.s_addr == 
+                   (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
+                       break;
+           aval[i] = j;
+           if (needsort == 0 && i > 0 && j < aval[i-1])
+               needsort = i;
+       }
+       if (!needsort)
+           return;
+
+       while (needsort < num) {
+           for (j = needsort - 1; j >= 0; j--) {
+               if (aval[j] > aval[j+1]) {
+                   char *hp;
+
+                   i = aval[j];
+                   aval[j] = aval[j+1];
+                   aval[j+1] = i;
+
+                   hp = ap[j];
+                   ap[j] = ap[j+1];
+                   ap[j+1] = hp;
+
+               } else
+                   break;
+           }
+           needsort++;
+       }
+}
+#endif
index aabd741..3d2b6e0 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: getnetbyaddr.c,v 1.2 1996/08/19 08:28:42 tholo Exp $";
+static char rcsid[] = "$OpenBSD: getnetbyaddr.c,v 1.3 1997/03/13 19:07:25 downsj Exp $";
 #endif /* LIBC_SCCS and not lint */
 
 #include <netdb.h>
@@ -40,8 +40,8 @@ static char rcsid[] = "$OpenBSD: getnetbyaddr.c,v 1.2 1996/08/19 08:28:42 tholo
 extern int _net_stayopen;
 
 struct netent *
-getnetbyaddr(net, type)
-       register long net;
+_getnetbyaddr(net, type)
+       register unsigned long net;
        register int type;
 {
        register struct netent *p;
index d2a5b86..764c78b 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: getnetbyname.c,v 1.3 1996/08/19 08:28:44 tholo Exp $";
+static char rcsid[] = "$OpenBSD: getnetbyname.c,v 1.4 1997/03/13 19:07:26 downsj Exp $";
 #endif /* LIBC_SCCS and not lint */
 
 #include <netdb.h>
@@ -41,7 +41,7 @@ static char rcsid[] = "$OpenBSD: getnetbyname.c,v 1.3 1996/08/19 08:28:44 tholo
 extern int _net_stayopen;
 
 struct netent *
-getnetbyname(name)
+_getnetbyname(name)
        register const char *name;
 {
        register struct netent *p;
index 9cd54a8..a3aebf4 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: getnetent.3,v 1.2 1996/08/19 08:28:45 tholo Exp $
+.\"    $OpenBSD: getnetent.3,v 1.3 1997/03/13 19:07:26 downsj Exp $
 .\"
 .\" Copyright (c) 1983, 1991, 1993
 .\"    The Regents of the University of California.  All rights reserved.
@@ -31,9 +31,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd June 4, 1993
+.Dd March 13, 1997
 .Dt GETNETENT 3
-.Os BSD 4.2
+.Os
 .Sh NAME
 .Nm getnetent ,
 .Nm getnetbyaddr ,
@@ -48,7 +48,7 @@
 .Ft struct netent *
 .Fn getnetbyname "char *name"
 .Ft struct netent *
-.Fn getnetbyaddr "long net" "int type"
+.Fn getnetbyaddr "unsigned long net" "int type"
 .Fn setnetent "int stayopen"
 .Fn endnetent 
 .Sh DESCRIPTION
@@ -111,11 +111,10 @@ The
 function
 and
 .Fn getnetbyaddr
-sequentially search from the beginning
-of the file until a matching
-net name or
-net address and type is found,
-or until
+search the domain name server if the system is configured to use one.
+If the search fails, or no name server is configured, they sequentially
+search from the beginning of the file until a matching net name or
+net address and type is found, or until
 .Dv EOF
 is encountered.
 Network numbers are supplied in host order.
@@ -129,7 +128,8 @@ Null pointer
 .Dv EOF
 or error.
 .Sh SEE ALSO
-.Xr networks 5
+.Xr networks 5 ,
+.Xr resolver 3
 .Sh HISTORY
 The
 .Fn getnetent ,
@@ -147,5 +147,4 @@ copied before any subsequent calls to these functions overwrite it.
 Only Internet network
 numbers are currently understood.
 Expecting network numbers to fit
-in no more than 32 bits is probably
-naive.
+in no more than 32 bits is naive.
diff --git a/lib/libc/net/getnetnamadr.c b/lib/libc/net/getnetnamadr.c
new file mode 100644 (file)
index 0000000..cc6ccc4
--- /dev/null
@@ -0,0 +1,291 @@
+/*     $OpenBSD: getnetnamadr.c,v 1.1 1997/03/13 19:07:27 downsj Exp $ */
+
+/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
+ *     Dep. Matematica Universidade de Coimbra, Portugal, Europe
+ *
+ * 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.
+ */
+/*
+ * Copyright (c) 1983, 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:
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)getnetbyaddr.c     8.1 (Berkeley) 6/4/93";
+static char sccsid_[] = "from getnetnamadr.c   1.4 (Coimbra) 93/06/03";
+static char rcsid[] = "$From: getnetnamadr.c,v 8.7 1996/08/05 08:31:35 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: getnetnamadr.c,v 1.1 1997/03/13 19:07:27 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#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 <stdio.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+
+extern int h_errno;
+
+struct netent *_getnetbyaddr __P((long net, int type));
+struct netent *_getnetbyname __P((const char *name));
+
+#define BYADDR 0
+#define BYNAME 1
+#define        MAXALIASES      35
+
+#if PACKETSZ > 1024
+#define        MAXPACKET       PACKETSZ
+#else
+#define        MAXPACKET       1024
+#endif
+
+typedef union {
+       HEADER  hdr;
+       u_char  buf[MAXPACKET];
+} querybuf;
+
+typedef union {
+       long    al;
+       char    ac;
+} align;
+
+static struct netent *
+getnetanswer(answer, anslen, net_i)
+       querybuf *answer;
+       int anslen;
+       int net_i;
+{
+
+       register HEADER *hp;
+       register u_char *cp;
+       register int n;
+       u_char *eom;
+       int type, class, buflen, ancount, qdcount, haveanswer, i, nchar;
+       char aux1[30], aux2[30], ans[30], *in, *st, *pauxt, *bp, **ap,
+               *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0;
+static struct netent net_entry;
+static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
+
+       /*
+        * find first satisfactory answer
+        *
+        *      answer --> +------------+  ( MESSAGE )
+        *                 |   Header   |
+        *                 +------------+
+        *                 |  Question  | the question for the name server
+        *                 +------------+
+        *                 |   Answer   | RRs answering the question
+        *                 +------------+
+        *                 | Authority  | RRs pointing toward an authority
+        *                 | Additional | RRs holding additional information
+        *                 +------------+
+        */
+       eom = answer->buf + anslen;
+       hp = &answer->hdr;
+       ancount = ntohs(hp->ancount); /* #/records in the answer section */
+       qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
+       bp = netbuf;
+       buflen = sizeof(netbuf);
+       cp = answer->buf + HFIXEDSZ;
+       if (!qdcount) {
+               if (hp->aa)
+                       h_errno = HOST_NOT_FOUND;
+               else
+                       h_errno = TRY_AGAIN;
+               return (NULL);
+       }
+       while (qdcount-- > 0)
+               cp += __dn_skipname(cp, eom) + QFIXEDSZ;
+       ap = net_aliases;
+       *ap = NULL;
+       net_entry.n_aliases = net_aliases;
+       haveanswer = 0;
+       while (--ancount >= 0 && cp < eom) {
+               n = dn_expand(answer->buf, eom, cp, bp, buflen);
+               if ((n < 0) || !res_dnok(bp))
+                       break;
+               cp += n;
+               ans[0] = '\0';
+               (void)strcpy(&ans[0], bp);
+               GETSHORT(type, cp);
+               GETSHORT(class, cp);
+               cp += INT32SZ;          /* TTL */
+               GETSHORT(n, cp);
+               if (class == C_IN && type == T_PTR) {
+                       n = dn_expand(answer->buf, eom, cp, bp, buflen);
+                       if ((n < 0) || !res_hnok(bp)) {
+                               cp += n;
+                               return (NULL);
+                       }
+                       cp += n; 
+                       *ap++ = bp;
+                       bp += strlen(bp) + 1;
+                       net_entry.n_addrtype =
+                               (class == C_IN) ? AF_INET : AF_UNSPEC;
+                       haveanswer++;
+               }
+       }
+       if (haveanswer) {
+               *ap = NULL;
+               switch (net_i) {
+               case BYADDR:
+                       net_entry.n_name = *net_entry.n_aliases;
+                       net_entry.n_net = 0L;
+                       break;
+               case BYNAME:
+                       in = *net_entry.n_aliases;
+                       net_entry.n_name = &ans[0];
+                       aux2[0] = '\0';
+                       for (i = 0; i < 4; i++) {
+                               for (st = in, nchar = 0;
+                                    *st != '.';
+                                    st++, nchar++)
+                                       ;
+                               if (nchar != 1 || *in != '0' || flag) {
+                                       flag = 1;
+                                       (void)strncpy(paux1,
+                                                     (i==0) ? in : in-1,
+                                                     (i==0) ?nchar : nchar+1);
+                                       paux1[(i==0) ? nchar : nchar+1] = '\0';
+                                       pauxt = paux2;
+                                       paux2 = strcat(paux1, paux2);
+                                       paux1 = pauxt;
+                               }
+                               in = ++st;
+                       }                 
+                       net_entry.n_net = inet_network(paux2);
+                       break;
+               }
+               net_entry.n_aliases++;
+               return (&net_entry);
+       }
+       h_errno = TRY_AGAIN;
+       return (NULL);
+}
+
+struct netent *
+getnetbyaddr(net, net_type)
+       register u_long net;
+       register int net_type;
+{
+       unsigned int netbr[4];
+       int nn, anslen;
+       querybuf buf;
+       char qbuf[MAXDNAME];
+       unsigned long net2;
+       struct netent *net_entry;
+
+       if (net_type != AF_INET)
+               return (_getnetbyaddr(net, net_type));
+
+       for (nn = 4, net2 = net; net2; net2 >>= 8)
+               netbr[--nn] = net2 & 0xff;
+       switch (nn) {
+       case 3:         /* Class A */
+               snprintf(qbuf, sizeof(qbuf), "0.0.0.%u.in-addr.arpa", netbr[3]);
+               break;
+       case 2:         /* Class B */
+               snprintf(qbuf, sizeof(qbuf), "0.0.%u.%u.in-addr.arpa",
+                   netbr[3], netbr[2]);
+               break;
+       case 1:         /* Class C */
+               snprintf(qbuf, sizeof(qbuf), "0.%u.%u.%u.in-addr.arpa",
+                   netbr[3], netbr[2], netbr[1]);
+               break;
+       case 0:         /* Class D - E */
+               snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa",
+                   netbr[3], netbr[2], netbr[1], netbr[0]);
+               break;
+       }
+       anslen = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
+       if (anslen < 0) {
+#ifdef DEBUG
+               if (_res.options & RES_DEBUG)
+                       printf("res_query failed\n");
+#endif
+               if (errno == ECONNREFUSED)
+                       return (_getnetbyaddr(net, net_type));
+               return (NULL);
+       }
+       net_entry = getnetanswer(&buf, anslen, BYADDR);
+       if (net_entry) {
+               unsigned u_net = net;   /* maybe net should be unsigned ? */
+
+               /* Strip trailing zeros */
+               while ((u_net & 0xff) == 0 && u_net != 0)
+                       u_net >>= 8;
+               net_entry->n_net = u_net;
+               return (net_entry);
+       }
+       return (_getnetbyaddr(net, net_type));
+}
+
+struct netent *
+getnetbyname(net)
+       register const char *net;
+{
+       int anslen;
+       querybuf buf;
+       char qbuf[MAXDNAME];
+       struct netent *net_entry;
+
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+               h_errno = NETDB_INTERNAL;
+               return (NULL);
+       }
+       strcpy(&qbuf[0], net);
+       anslen = res_search(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
+       if (anslen < 0) {
+#ifdef DEBUG
+               if (_res.options & RES_DEBUG)
+                       printf("res_query failed\n");
+#endif
+               if (errno == ECONNREFUSED)
+                       return (_getnetbyname(net));
+               return (_getnetbyname(net));
+       }
+       net_entry = getnetanswer(&buf, anslen, BYNAME);
+       if (net_entry)
+               return (net_entry);
+       return (_getnetbyname(net));
+}
index 40da656..737bb11 100644 (file)
@@ -1,7 +1,11 @@
-/*-
+/*     $OpenBSD: herror.c,v 1.4 1997/03/13 19:07:28 downsj Exp $       */
+
+/*
+ * ++Copyright++ 1987, 1993
+ * -
  * Copyright (c) 1987, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
+ *    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:
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
  * 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
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: herror.c,v 1.3 1996/08/19 08:29:02 tholo Exp $";
+#if 0
+static char sccsid[] = "@(#)herror.c   8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: herror.c,v 8.3 1996/08/05 08:31:35 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: herror.c,v 1.4 1997/03/13 19:07:28 downsj Exp $";
+#endif
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/types.h>
+#include <sys/param.h>
 #include <sys/uio.h>
 #include <netdb.h>
 #include <unistd.h>
 #include <string.h>
 
-const char     *h_errlist[] = {
+const char *h_errlist[] = {
        "Resolver Error 0 (no error)",
        "Unknown host",                         /* 1 HOST_NOT_FOUND */
        "Host name lookup failure",             /* 2 TRY_AGAIN */
index 99a6f66..ef8ee49 100644 (file)
@@ -1,7 +1,11 @@
+/*     $OpenBSD: inet_addr.c,v 1.4 1997/03/13 19:07:29 downsj Exp $    */
+
 /*
+ * ++Copyright++ 1983, 1990, 1993
+ * -
  * Copyright (c) 1983, 1990, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
+ *    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:
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
  * 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
  * 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
+ * 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.
+ * 
+ * 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
+ * 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[] = "$OpenBSD: inet_addr.c,v 1.3 1996/08/19 08:29:08 tholo Exp $";
+#if 0
+static char sccsid[] = "@(#)inet_addr.c        8.1 (Berkeley) 6/17/93";
+static char rcsid[] = "$From: inet_addr.c,v 8.5 1996/08/05 08:31:35 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: inet_addr.c,v 1.4 1997/03/13 19:07:29 downsj Exp $";
+#endif
 #endif /* LIBC_SCCS and not lint */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
@@ -73,50 +103,52 @@ inet_aton(cp, addr)
        u_int parts[4];
        register u_int *pp = parts;
 
+       c = *cp;
        for (;;) {
                /*
                 * Collect number up to ``.''.
                 * Values are specified as for C:
-                * 0x=hex, 0=octal, other=decimal.
+                * 0x=hex, 0=octal, isdigit=decimal.
                 */
+               if (!isdigit(c))
+                       return (0);
                val = 0; base = 10;
-               if (*cp == '0') {
-                       if (*++cp == 'x' || *cp == 'X')
-                               base = 16, cp++;
+               if (c == '0') {
+                       c = *++cp;
+                       if (c == 'x' || c == 'X')
+                               base = 16, c = *++cp;
                        else
                                base = 8;
                }
-               while ((c = *cp) != '\0') {
+               for (;;) {
                        if (isascii(c) && isdigit(c)) {
                                val = (val * base) + (c - '0');
-                               cp++;
-                               continue;
-                       }
-                       if (base == 16 && isascii(c) && isxdigit(c)) {
-                               val = (val << 4) + 
+                               c = *++cp;
+                       } else if (base == 16 && isascii(c) && isxdigit(c)) {
+                               val = (val << 4) |
                                        (c + 10 - (islower(c) ? 'a' : 'A'));
-                               cp++;
-                               continue;
-                       }
-                       break;
+                               c = *++cp;
+                       } else
+                               break;
                }
-               if (*cp == '.') {
+               if (c == '.') {
                        /*
                         * Internet format:
                         *      a.b.c.d
-                        *      a.b.c   (with c treated as 16-bits)
+                        *      a.b.c   (with c treated as 16 bits)
                         *      a.b     (with b treated as 24 bits)
                         */
-                       if (pp >= parts + 3 || val > 0xff)
+                       if (pp >= parts + 3)
                                return (0);
-                       *pp++ = val, cp++;
+                       *pp++ = val;
+                       c = *++cp;
                } else
                        break;
        }
        /*
         * Check for trailing characters.
         */
-       if (*cp && (!isascii(*cp) || !isspace(*cp)))
+       if (c != '\0' && (!isascii(c) || !isspace(c)))
                return (0);
        /*
         * Concoct the address according to
diff --git a/lib/libc/net/inet_net_ntop.c b/lib/libc/net/inet_net_ntop.c
new file mode 100644 (file)
index 0000000..943ec44
--- /dev/null
@@ -0,0 +1,139 @@
+/*     $OpenBSD: inet_net_ntop.c,v 1.1 1997/03/13 19:07:30 downsj Exp $        */
+
+/*
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static const char rcsid[] = "$From: inet_net_ntop.c,v 8.2 1996/08/08 06:54:44 vixie Exp $";
+#else
+static const char rcsid[] = "$OpenBSD: inet_net_ntop.c,v 1.1 1997/03/13 19:07:30 downsj Exp $";
+#endif
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+static char *  inet_net_ntop_ipv4 __P((const u_char *src, int bits,
+                                       char *dst, size_t size));
+
+/*
+ * char *
+ * inet_net_ntop(af, src, bits, dst, size)
+ *     convert network number from network to presentation format.
+ *     generates CIDR style result always.
+ * return:
+ *     pointer to dst, or NULL if an error occurred (check errno).
+ * author:
+ *     Paul Vixie (ISC), July 1996
+ */
+char *
+inet_net_ntop(af, src, bits, dst, size)
+       int af;
+       const void *src;
+       int bits;
+       char *dst;
+       size_t size;
+{
+       switch (af) {
+       case AF_INET:
+               return (inet_net_ntop_ipv4(src, bits, dst, size));
+       default:
+               errno = EAFNOSUPPORT;
+               return (NULL);
+       }
+}
+
+/*
+ * static char *
+ * inet_net_ntop_ipv4(src, bits, dst, size)
+ *     convert IPv4 network number from network to presentation format.
+ *     generates CIDR style result always.
+ * return:
+ *     pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ *     network byte order assumed.  this means 192.5.5.240/28 has
+ *     0x11110000 in its fourth octet.
+ * author:
+ *     Paul Vixie (ISC), July 1996
+ */
+static char *
+inet_net_ntop_ipv4(src, bits, dst, size)
+       const u_char *src;
+       int bits;
+       char *dst;
+       size_t size;
+{
+       char *odst = dst;
+       char *t;
+       u_int m;
+       int b;
+
+       if (bits < 0 || bits > 32) {
+               errno = EINVAL;
+               return (NULL);
+       }
+       if (bits == 0) {
+               if (size < sizeof "0")
+                       goto emsgsize;
+               *dst++ = '0';
+               *dst = '\0';
+       }
+
+       /* Format whole octets. */
+       for (b = bits / 8; b > 0; b--) {
+               if (size < sizeof "255.")
+                       goto emsgsize;
+               t = dst;
+               dst += sprintf(dst, "%u", *src++);
+               if (b > 1) {
+                       *dst++ = '.';
+                       *dst = '\0';
+               }
+               size -= (size_t)(dst - t);
+       }
+
+       /* Format partial octet. */
+       b = bits % 8;
+       if (b > 0) {
+               if (size < sizeof ".255")
+                       goto emsgsize;
+               t = dst;
+               if (dst != odst)
+                       *dst++ = '.';
+               m = ((1 << b) - 1) << (8 - b);
+               dst += sprintf(dst, "%u", *src & m);
+               size -= (size_t)(dst - t);
+       }
+
+       /* Format CIDR /width. */
+       if (size < sizeof "/32")
+               goto emsgsize;
+       dst += sprintf(dst, "/%u", bits);
+       return (odst);
+
+ emsgsize:
+       errno = EMSGSIZE;
+       return (NULL);
+}
diff --git a/lib/libc/net/inet_net_pton.c b/lib/libc/net/inet_net_pton.c
new file mode 100644 (file)
index 0000000..b529e83
--- /dev/null
@@ -0,0 +1,207 @@
+/*     $OpenBSD: inet_net_pton.c,v 1.1 1997/03/13 19:07:30 downsj Exp $        */
+
+/*
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static const char rcsid[] = "$From: inet_net_pton.c,v 8.3 1996/11/11 06:36:52 vixie Exp $";
+#else
+static const char rcsid[] = "$OpenBSD: inet_net_pton.c,v 1.1 1997/03/13 19:07:30 downsj Exp $";
+#endif
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+static int     inet_net_pton_ipv4 __P((const char *src, u_char *dst,
+                                       size_t size));
+
+/*
+ * static int
+ * inet_net_pton(af, src, dst, size)
+ *     convert network number from presentation to network format.
+ *     accepts hex octets, hex strings, decimal octets, and /CIDR.
+ *     "size" is in bytes and describes "dst".
+ * return:
+ *     number of bits, either imputed classfully or specified with /CIDR,
+ *     or -1 if some failure occurred (check errno).  ENOENT means it was
+ *     not a valid network specification.
+ * author:
+ *     Paul Vixie (ISC), June 1996
+ */
+int
+inet_net_pton(af, src, dst, size)
+       int af;
+       const char *src;
+       void *dst;
+       size_t size;
+{
+       switch (af) {
+       case AF_INET:
+               return (inet_net_pton_ipv4(src, dst, size));
+       default:
+               errno = EAFNOSUPPORT;
+               return (-1);
+       }
+}
+
+/*
+ * static int
+ * inet_net_pton_ipv4(src, dst, size)
+ *     convert IPv4 network number from presentation to network format.
+ *     accepts hex octets, hex strings, decimal octets, and /CIDR.
+ *     "size" is in bytes and describes "dst".
+ * return:
+ *     number of bits, either imputed classfully or specified with /CIDR,
+ *     or -1 if some failure occurred (check errno).  ENOENT means it was
+ *     not an IPv4 network specification.
+ * note:
+ *     network byte order assumed.  this means 192.5.5.240/28 has
+ *     0x11110000 in its fourth octet.
+ * author:
+ *     Paul Vixie (ISC), June 1996
+ */
+static int
+inet_net_pton_ipv4(src, dst, size)
+       const char *src;
+       u_char *dst;
+       size_t size;
+{
+       static const char
+               xdigits[] = "0123456789abcdef",
+               digits[] = "0123456789";
+       int n, ch, tmp, dirty, bits;
+       const u_char *odst = dst;
+
+       ch = *src++;
+       if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
+           && isascii(src[1]) && isxdigit(src[1])) {
+               /* Hexadecimal: Eat nybble string. */
+               if (size <= 0)
+                       goto emsgsize;
+               *dst = 0, dirty = 0;
+               src++;  /* skip x or X. */
+               while ((ch = *src++) != '\0' &&
+                      isascii(ch) && isxdigit(ch)) {
+                       if (isupper(ch))
+                               ch = tolower(ch);
+                       n = strchr(xdigits, ch) - xdigits;
+                       assert(n >= 0 && n <= 15);
+                       *dst |= n;
+                       if (!dirty++)
+                               *dst <<= 4;
+                       else if (size-- > 0)
+                               *++dst = 0, dirty = 0;
+                       else
+                               goto emsgsize;
+               }
+               if (dirty)
+                       size--;
+       } else if (isascii(ch) && isdigit(ch)) {
+               /* Decimal: eat dotted digit string. */
+               for (;;) {
+                       tmp = 0;
+                       do {
+                               n = strchr(digits, ch) - digits;
+                               assert(n >= 0 && n <= 9);
+                               tmp *= 10;
+                               tmp += n;
+                               if (tmp > 255)
+                                       goto enoent;
+                       } while ((ch = *src++) != '\0' &&
+                                isascii(ch) && isdigit(ch));
+                       if (size-- <= 0)
+                               goto emsgsize;
+                       *dst++ = (u_char) tmp;
+                       if (ch == '\0' || ch == '/')
+                               break;
+                       if (ch != '.')
+                               goto enoent;
+                       ch = *src++;
+                       if (!isascii(ch) || !isdigit(ch))
+                               goto enoent;
+               }
+       } else
+               goto enoent;
+
+       bits = -1;
+       if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
+               /* CIDR width specifier.  Nothing can follow it. */
+               ch = *src++;    /* Skip over the /. */
+               bits = 0;
+               do {
+                       n = strchr(digits, ch) - digits;
+                       assert(n >= 0 && n <= 9);
+                       bits *= 10;
+                       bits += n;
+               } while ((ch = *src++) != '\0' &&
+                        isascii(ch) && isdigit(ch));
+               if (ch != '\0')
+                       goto enoent;
+               if (bits > 32)
+                       goto emsgsize;
+       }
+
+       /* Firey death and destruction unless we prefetched EOS. */
+       if (ch != '\0')
+               goto enoent;
+
+       /* If nothing was written to the destination, we found no address. */
+       if (dst == odst)
+               goto enoent;
+       /* If no CIDR spec was given, infer width from net class. */
+       if (bits == -1) {
+               if (*odst >= 240)       /* Class E */
+                       bits = 32;
+               else if (*odst >= 224)  /* Class D */
+                       bits = 4;
+               else if (*odst >= 192)  /* Class C */
+                       bits = 24;
+               else if (*odst >= 128)  /* Class B */
+                       bits = 16;
+               else                    /* Class A */
+                       bits = 8;
+               /* If imputed mask is narrower than specified octets, widen. */
+               if (bits >= 8 && bits < ((dst - odst) * 8))
+                       bits = (dst - odst) * 8;
+       }
+       /* Extend network to cover the actual mask. */
+       while (bits > ((dst - odst) * 8)) {
+               if (size-- <= 0)
+                       goto emsgsize;
+               *dst++ = '\0';
+       }
+       return (bits);
+
+ enoent:
+       errno = ENOENT;
+       return (-1);
+
+ emsgsize:
+       errno = EMSGSIZE;
+       return (-1);
+}
diff --git a/lib/libc/net/inet_neta.c b/lib/libc/net/inet_neta.c
new file mode 100644 (file)
index 0000000..dffd163
--- /dev/null
@@ -0,0 +1,82 @@
+/*     $OpenBSD: inet_neta.c,v 1.1 1997/03/13 19:07:31 downsj Exp $    */
+
+/*
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static const char rcsid[] = "$Id: inet_neta.c,v 1.1 1997/03/13 19:07:31 downsj Exp $";
+#else
+static const char rcsid[] = "$OpenBSD: inet_neta.c,v 1.1 1997/03/13 19:07:31 downsj Exp $";
+#endif
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+
+/*
+ * char *
+ * inet_neta(src, dst, size)
+ *     format a u_long network number into presentation format.
+ * return:
+ *     pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ *     format of ``src'' is as for inet_network().
+ * author:
+ *     Paul Vixie (ISC), July 1996
+ */
+char *
+inet_neta(src, dst, size)
+       u_long src;
+       char *dst;
+       size_t size;
+{
+       char *odst = dst;
+       char *tp;
+
+       while (src & 0xffffffff) {
+               u_char b = (src & 0xff000000) >> 24;
+
+               src <<= 8;
+               if (b) {
+                       if (size < sizeof "255.")
+                               goto emsgsize;
+                       tp = dst;
+                       dst += sprintf(dst, "%u", b);
+                       if (src != 0L) {
+                               *dst++ = '.';
+                               *dst = '\0';
+                       }
+                       size -= (size_t)(dst - tp);
+               }
+       }
+       if (dst == odst) {
+               if (size < sizeof "0.0.0.0")
+                       goto emsgsize;
+               strcpy(dst, "0.0.0.0");
+       }
+       return (odst);
+
+ emsgsize:
+       errno = EMSGSIZE;
+       return (NULL);
+}
diff --git a/lib/libc/net/inet_ntop.c b/lib/libc/net/inet_ntop.c
new file mode 100644 (file)
index 0000000..64d0d13
--- /dev/null
@@ -0,0 +1,194 @@
+/*     $OpenBSD: inet_ntop.c,v 1.1 1997/03/13 19:07:32 downsj Exp $    */
+
+/* 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char rcsid[] = "$From: inet_ntop.c,v 8.7 1996/08/05 08:41:18 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: inet_ntop.c,v 1.1 1997/03/13 19:07:32 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static const char *inet_ntop4 __P((const u_char *src, char *dst, size_t size));
+static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size));
+
+/* char *
+ * inet_ntop(af, src, dst, size)
+ *     convert a network format address to presentation format.
+ * return:
+ *     pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ *     Paul Vixie, 1996.
+ */
+const char *
+inet_ntop(af, src, dst, size)
+       int af;
+       const void *src;
+       char *dst;
+       size_t size;
+{
+       switch (af) {
+       case AF_INET:
+               return (inet_ntop4(src, dst, size));
+       case AF_INET6:
+               return (inet_ntop6(src, dst, size));
+       default:
+               errno = EAFNOSUPPORT;
+               return (NULL);
+       }
+       /* NOTREACHED */
+}
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ *     format an IPv4 address, more or less like inet_ntoa()
+ * return:
+ *     `dst' (as a const)
+ * notes:
+ *     (1) uses no statics
+ *     (2) takes a u_char* not an in_addr as input
+ * author:
+ *     Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4(src, dst, size)
+       const u_char *src;
+       char *dst;
+       size_t size;
+{
+       static const char fmt[] = "%u.%u.%u.%u";
+       char tmp[sizeof "255.255.255.255"];
+
+       if (sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) > size) {
+               errno = ENOSPC;
+               return (NULL);
+       }
+       strcpy(dst, tmp);
+       return (dst);
+}
+
+/* const char *
+ * inet_ntop6(src, dst, size)
+ *     convert IPv6 binary address into presentation (printable) format
+ * author:
+ *     Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop6(src, dst, size)
+       const u_char *src;
+       char *dst;
+       size_t size;
+{
+       /*
+        * Note that int32_t and int16_t need only be "at least" large enough
+        * to contain a value of the specified size.  On some systems, like
+        * Crays, there is no such thing as an integer variable with 16 bits.
+        * Keep this in mind if you think this function should have been coded
+        * to use pointer overlays.  All the world's not a VAX.
+        */
+       char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+       struct { int base, len; } best, cur;
+       u_int words[IN6ADDRSZ / INT16SZ];
+       int i;
+
+       /*
+        * Preprocess:
+        *      Copy the input (bytewise) array into a wordwise array.
+        *      Find the longest run of 0x00's in src[] for :: shorthanding.
+        */
+       memset(words, '\0', sizeof words);
+       for (i = 0; i < IN6ADDRSZ; i++)
+               words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+       best.base = -1;
+       cur.base = -1;
+       for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+               if (words[i] == 0) {
+                       if (cur.base == -1)
+                               cur.base = i, cur.len = 1;
+                       else
+                               cur.len++;
+               } else {
+                       if (cur.base != -1) {
+                               if (best.base == -1 || cur.len > best.len)
+                                       best = cur;
+                               cur.base = -1;
+                       }
+               }
+       }
+       if (cur.base != -1) {
+               if (best.base == -1 || cur.len > best.len)
+                       best = cur;
+       }
+       if (best.base != -1 && best.len < 2)
+               best.base = -1;
+
+       /*
+        * Format the result.
+        */
+       tp = tmp;
+       for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+               /* Are we inside the best run of 0x00's? */
+               if (best.base != -1 && i >= best.base &&
+                   i < (best.base + best.len)) {
+                       if (i == best.base)
+                               *tp++ = ':';
+                       continue;
+               }
+               /* Are we following an initial run of 0x00s or any real hex? */
+               if (i != 0)
+                       *tp++ = ':';
+               /* Is this address an encapsulated IPv4? */
+               if (i == 6 && best.base == 0 &&
+                   (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
+                       if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
+                               return (NULL);
+                       tp += strlen(tp);
+                       break;
+               }
+               tp += sprintf(tp, "%x", words[i]);
+       }
+       /* Was it a trailing run of 0x00's? */
+       if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
+               *tp++ = ':';
+       *tp++ = '\0';
+
+       /*
+        * Check for overflow, copy, and we're done.
+        */
+       if ((size_t)(tp - tmp) > size) {
+               errno = ENOSPC;
+               return (NULL);
+       }
+       strcpy(dst, tmp);
+       return (dst);
+}
diff --git a/lib/libc/net/inet_pton.c b/lib/libc/net/inet_pton.c
new file mode 100644 (file)
index 0000000..8ffe81e
--- /dev/null
@@ -0,0 +1,220 @@
+/*     $OpenBSD: inet_pton.c,v 1.1 1997/03/13 19:07:33 downsj Exp $    */
+
+/* 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char rcsid[] = "$From: inet_pton.c,v 8.7 1996/08/05 08:31:35 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: inet_pton.c,v 1.1 1997/03/13 19:07:33 downsj Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <string.h>
+#include <errno.h>
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int     inet_pton4 __P((const char *src, u_char *dst));
+static int     inet_pton6 __P((const char *src, u_char *dst));
+
+/* int
+ * inet_pton(af, src, dst)
+ *     convert from presentation format (which usually means ASCII printable)
+ *     to network format (which is usually some kind of binary format).
+ * return:
+ *     1 if the address was valid for the specified address family
+ *     0 if the address wasn't valid (`dst' is untouched in this case)
+ *     -1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ *     Paul Vixie, 1996.
+ */
+int
+inet_pton(af, src, dst)
+       int af;
+       const char *src;
+       void *dst;
+{
+       switch (af) {
+       case AF_INET:
+               return (inet_pton4(src, dst));
+       case AF_INET6:
+               return (inet_pton6(src, dst));
+       default:
+               errno = EAFNOSUPPORT;
+               return (-1);
+       }
+       /* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ *     like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ *     1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ *     does not touch `dst' unless it's returning 1.
+ * author:
+ *     Paul Vixie, 1996.
+ */
+static int
+inet_pton4(src, dst)
+       const char *src;
+       u_char *dst;
+{
+       static const char digits[] = "0123456789";
+       int saw_digit, octets, ch;
+       u_char tmp[INADDRSZ], *tp;
+
+       saw_digit = 0;
+       octets = 0;
+       *(tp = tmp) = 0;
+       while ((ch = *src++) != '\0') {
+               const char *pch;
+
+               if ((pch = strchr(digits, ch)) != NULL) {
+                       u_int new = *tp * 10 + (pch - digits);
+
+                       if (new > 255)
+                               return (0);
+                       *tp = new;
+                       if (! saw_digit) {
+                               if (++octets > 4)
+                                       return (0);
+                               saw_digit = 1;
+                       }
+               } else if (ch == '.' && saw_digit) {
+                       if (octets == 4)
+                               return (0);
+                       *++tp = 0;
+                       saw_digit = 0;
+               } else
+                       return (0);
+       }
+       if (octets < 4)
+               return (0);
+
+       memcpy(dst, tmp, INADDRSZ);
+       return (1);
+}
+
+/* int
+ * inet_pton6(src, dst)
+ *     convert presentation level address to network order binary form.
+ * return:
+ *     1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ *     (1) does not touch `dst' unless it's returning 1.
+ *     (2) :: in a full address is silently ignored.
+ * credit:
+ *     inspired by Mark Andrews.
+ * author:
+ *     Paul Vixie, 1996.
+ */
+static int
+inet_pton6(src, dst)
+       const char *src;
+       u_char *dst;
+{
+       static const char xdigits_l[] = "0123456789abcdef",
+                         xdigits_u[] = "0123456789ABCDEF";
+       u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
+       const char *xdigits, *curtok;
+       int ch, saw_xdigit;
+       u_int val;
+
+       memset((tp = tmp), '\0', IN6ADDRSZ);
+       endp = tp + IN6ADDRSZ;
+       colonp = NULL;
+       /* Leading :: requires some special handling. */
+       if (*src == ':')
+               if (*++src != ':')
+                       return (0);
+       curtok = src;
+       saw_xdigit = 0;
+       val = 0;
+       while ((ch = *src++) != '\0') {
+               const char *pch;
+
+               if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+                       pch = strchr((xdigits = xdigits_u), ch);
+               if (pch != NULL) {
+                       val <<= 4;
+                       val |= (pch - xdigits);
+                       if (val > 0xffff)
+                               return (0);
+                       saw_xdigit = 1;
+                       continue;
+               }
+               if (ch == ':') {
+                       curtok = src;
+                       if (!saw_xdigit) {
+                               if (colonp)
+                                       return (0);
+                               colonp = tp;
+                               continue;
+                       }
+                       if (tp + INT16SZ > endp)
+                               return (0);
+                       *tp++ = (u_char) (val >> 8) & 0xff;
+                       *tp++ = (u_char) val & 0xff;
+                       saw_xdigit = 0;
+                       val = 0;
+                       continue;
+               }
+               if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
+                   inet_pton4(curtok, tp) > 0) {
+                       tp += INADDRSZ;
+                       saw_xdigit = 0;
+                       break;  /* '\0' was seen by inet_pton4(). */
+               }
+               return (0);
+       }
+       if (saw_xdigit) {
+               if (tp + INT16SZ > endp)
+                       return (0);
+               *tp++ = (u_char) (val >> 8) & 0xff;
+               *tp++ = (u_char) val & 0xff;
+       }
+       if (colonp != NULL) {
+               /*
+                * Since some memmove()'s erroneously fail to handle
+                * overlapping regions, we'll do the shift by hand.
+                */
+               const int n = tp - colonp;
+               int i;
+
+               for (i = 1; i <= n; i++) {
+                       endp[- i] = colonp[n - i];
+                       colonp[n - i] = 0;
+               }
+               tp = endp;
+       }
+       if (tp != endp)
+               return (0);
+       memcpy(dst, tmp, IN6ADDRSZ);
+       return (1);
+}
index ce0a60a..e62d952 100644 (file)
@@ -1,40 +1,31 @@
+/*     $OpenBSD: nsap_addr.c,v 1.3 1997/03/13 19:07:34 downsj Exp $    */
+
 /*
- * Copyright (c) 1989, 1993
- *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1996 by Internet Software Consortium.
  *
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 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.
+ * 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.
  *
- * 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.
+ * 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 rcsid[] = "$OpenBSD: nsap_addr.c,v 1.2 1996/08/19 08:29:32 tholo Exp $";
+#if 0
+static char rcsid[] = "$From: nsap_addr.c,v 8.3 1996/08/05 08:31:35 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: nsap_addr.c,v 1.3 1997/03/13 19:07:34 downsj Exp $";
+#endif
 #endif /* LIBC_SCCS and not lint */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -49,12 +40,6 @@ xtob(c)
        return (c - (((c >= '0') && (c <= '9')) ? '0' : '7'));
 }
 
-/* These have to be here for BIND and its utilities (DiG, nslookup, et al)
- * but should not be promulgated since the calling interface is not pretty.
- * (They do, however, implement the RFC standard way of representing ISO NSAPs
- * and as such, are preferred over the more general iso_addr.c routines.
- */
-
 u_int
 inet_nsap_addr(ascii, binary, maxlen)
        const char *ascii;
index f64a81d..2e98003 100644 (file)
@@ -1,7 +1,11 @@
-/*-
+/*     $OpenBSD: res_comp.c,v 1.4 1997/03/13 19:07:35 downsj Exp $     */
+
+/*
+ * ++Copyright++ 1985, 1993
+ * -
  * Copyright (c) 1985, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
+ *    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:
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
  * 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
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: res_comp.c,v 1.3 1996/08/19 08:29:42 tholo Exp $";
+#if 0
+static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: res_comp.c,v 8.11 1996/12/02 09:17:22 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: res_comp.c,v 1.4 1997/03/13 19:07:35 downsj Exp $";
+#endif
 #endif /* LIBC_SCCS and not lint */
 
+#include <sys/types.h>
 #include <sys/param.h>
-#include <arpa/nameser.h>
 #include <netinet/in.h>
-#include <resolv.h>
+#include <arpa/nameser.h>
+
 #include <stdio.h>
+#include <resolv.h>
 #include <ctype.h>
+
 #include <unistd.h>
 #include <string.h>
 
-static int dn_find __P((u_char *, u_char *, u_char **, u_char **));
+static int     dn_find __P((u_char *exp_dn, u_char *msg,
+                            u_char **dnptrs, u_char **lastdnptr));
 
 /*
  * Expand compressed domain name 'comp_dn' to full domain name.
@@ -106,7 +119,7 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length)
                                return (-1);
                        checked += n + 1;
                        while (--n >= 0) {
-                               if ((c = *cp++) == '.' || c == '\\') {
+                               if (((c = *cp++) == '.') || (c == '\\')) {
                                        if (dn + n + 2 >= eom)
                                                return (-1);
                                        *dn++ = '\\';
@@ -138,9 +151,6 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length)
                }
        }
        *dn = '\0';
-       for (dn = exp_dn; (c = *dn) != '\0'; dn++)
-               if (isascii(c) && isspace(c))
-                       return (-1);
        if (len < 0)
                len = cp - comp_dn;
        return (len);
@@ -263,7 +273,7 @@ __dn_skipname(comp_dn, eom)
                break;
        }
        if (cp > eom)
-               return -1;
+               return (-1);
        return (cp - comp_dn);
 }
 
@@ -330,14 +340,122 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)
 }
 
 /*
- * Routines to insert/extract short/long's. Must account for byte
- * order and non-alignment problems. This code at least has the
- * advantage of being portable.
- *
- * used by sendmail.
+ * Verify that a domain name uses an acceptable character set.
  */
 
-u_short
+/*
+ * Note the conspicuous absence of ctype macros in these definitions.  On
+ * non-ASCII hosts, we can't depend on string literals or ctype macros to
+ * tell us anything about network-format data.  The rest of the BIND system
+ * is not careful about this, but for some reason, we're doing it right here.
+ */
+#define PERIOD 0x2e
+#define        hyphenchar(c) ((c) == 0x2d)
+#define bslashchar(c) ((c) == 0x5c)
+#define periodchar(c) ((c) == PERIOD)
+#define asterchar(c) ((c) == 0x2a)
+#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
+                  || ((c) >= 0x61 && (c) <= 0x7a))
+#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
+
+#define borderchar(c) (alphachar(c) || digitchar(c))
+#define middlechar(c) (borderchar(c) || hyphenchar(c))
+#define        domainchar(c) ((c) > 0x20 && (c) < 0x7f)
+
+int
+res_hnok(dn)
+       const char *dn;
+{
+       int ppch = '\0', pch = PERIOD, ch = *dn++;
+
+       while (ch != '\0') {
+               int nch = *dn++;
+
+               if (periodchar(ch)) {
+                       NULL;
+               } else if (periodchar(pch)) {
+                       if (!borderchar(ch))
+                               return (0);
+               } else if (periodchar(nch) || nch == '\0') {
+                       if (!borderchar(ch))
+                               return (0);
+               } else {
+                       if (!middlechar(ch))
+                               return (0);
+               }
+               ppch = pch, pch = ch, ch = nch;
+       }
+       return (1);
+}
+
+/*
+ * hostname-like (A, MX, WKS) owners can have "*" as their first label
+ * but must otherwise be as a host name.
+ */
+int
+res_ownok(dn)
+       const char *dn;
+{
+       if (asterchar(dn[0])) {
+               if (periodchar(dn[1]))
+                       return (res_hnok(dn+2));
+               if (dn[1] == '\0')
+                       return (1);
+       }
+       return (res_hnok(dn));
+}
+
+/*
+ * SOA RNAMEs and RP RNAMEs can have any printable character in their first
+ * label, but the rest of the name has to look like a host name.
+ */
+int
+res_mailok(dn)
+       const char *dn;
+{
+       int ch, escaped = 0;
+
+       /* "." is a valid missing representation */
+       if (*dn == '\0')
+               return(1);
+
+       /* otherwise <label>.<hostname> */
+       while ((ch = *dn++) != '\0') {
+               if (!domainchar(ch))
+                       return (0);
+               if (!escaped && periodchar(ch))
+                       break;
+               if (escaped)
+                       escaped = 0;
+               else if (bslashchar(ch))
+                       escaped = 1;
+       }
+       if (periodchar(ch))
+               return (res_hnok(dn));
+       return(0);
+}
+
+/*
+ * This function is quite liberal, since RFC 1034's character sets are only
+ * recommendations.
+ */
+int
+res_dnok(dn)
+       const char *dn;
+{
+       int ch;
+
+       while ((ch = *dn++) != '\0')
+               if (!domainchar(ch))
+                       return (0);
+       return (1);
+}
+
+/*
+ * Routines to insert/extract short/long's.
+ */
+
+u_int16_t
 _getshort(msgp)
        register const u_char *msgp;
 {
@@ -347,6 +465,18 @@ _getshort(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;
@@ -359,7 +489,7 @@ _getlong(msgp)
 
 void
 #if defined(__STDC__) || defined(__cplusplus)
-__putshort(register u_int16_t s, register u_char *msgp)
+__putshort(register u_int16_t s, register u_char *msgp)        /* must match proto */
 #else
 __putshort(s, msgp)
        register u_int16_t s;
diff --git a/lib/libc/net/res_data.c b/lib/libc/net/res_data.c
new file mode 100644 (file)
index 0000000..b0d19c3
--- /dev/null
@@ -0,0 +1,117 @@
+/*     $OpenBSD: res_data.c,v 1.1 1997/03/13 19:07:36 downsj Exp $     */
+
+/*
+ * ++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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 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.
+ * 
+ * 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.
+ * 
+ * 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
+ * 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)
+#if 0
+static char rcsid[] = "$From: res_data.c,v 8.2 1996/08/05 08:31:35 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: res_data.c,v 1.1 1997/03/13 19:07:36 downsj Exp $";
+#endif
+#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>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+const char *_res_opcodes[] = {
+       "QUERY",
+       "IQUERY",
+       "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",
+       "6",
+       "7",
+       "8",
+       "9",
+       "10",
+       "11",
+       "12",
+       "13",
+       "14",
+       "NOCHANGE",
+};
index ae6c030..7fd6d4a 100644 (file)
@@ -1,7 +1,11 @@
-/*-
+/*     $OpenBSD: res_debug.c,v 1.5 1997/03/13 19:07:37 downsj Exp $    */
+
+/*
+ * ++Copyright++ 1985, 1990, 1993
+ * -
  * Copyright (c) 1985, 1990, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
+ *    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:
  * 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--
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: res_debug.c,v 1.4 1996/09/15 09:31:18 tholo Exp $";
+#if 0
+static char sccsid[] = "@(#)res_debug.c        8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: res_debug.c,v 8.19 1996/11/26 10:11:23 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: res_debug.c,v 1.5 1997/03/13 19:07:37 downsj Exp $";
+#endif
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.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 <time.h>
+
+#include <stdlib.h>
 #include <string.h>
-#include <netdb.h>
 
-void __fp_query();
-
-char *_res_opcodes[] = {
-       "QUERY",
-       "IQUERY",
-       "CQUERYM",
-       "CQUERYU",      /* experimental */
-       "NOTIFY",       /* experimental */
-       "5",
-       "6",
-       "7",
-       "8",
-       "UPDATEA",
-       "UPDATED",
-       "UPDATEDA",
-       "UPDATEM",
-       "UPDATEMA",
-       "ZONEINIT",
-       "ZONEREF",
-};
+extern const char *_res_opcodes[];
+extern const char *_res_resultcodes[];
 
-char *_res_resultcodes[] = {
-       "NOERROR",
-       "FORMERR",
-       "SERVFAIL",
-       "NXDOMAIN",
-       "NOTIMP",
-       "REFUSED",
-       "6",
-       "7",
-       "8",
-       "9",
-       "10",
-       "11",
-       "12",
-       "13",
-       "14",
-       "NOCHANGE",
-};
-
-static char *
+/* XXX: we should use getservbyport() instead. */
+static const char *
 dewks(wks)
        int wks;
 {
@@ -200,7 +202,8 @@ do_rrset(msg, len, cp, cnt, pflag, file, hs)
         */
        sflag = (_res.pfcode & pflag);
        if (n = ntohs(cnt)) {
-               if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
+               if ((!_res.pfcode) ||
+                   ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
                        fprintf(file, hs);
                while (--n >= 0) {
                        if ((!_res.pfcode) || sflag) {
@@ -208,20 +211,21 @@ do_rrset(msg, len, cp, cnt, pflag, file, hs)
                        } else {
                                unsigned int dlen;
                                cp += __dn_skipname(cp, cp + MAXCDNAME);
-                               cp += sizeof(u_int16_t);
-                               cp += sizeof(u_int16_t);
-                               cp += sizeof(u_int32_t);
+                               cp += INT16SZ;
+                               cp += INT16SZ;
+                               cp += INT32SZ;
                                dlen = _getshort((u_char*)cp);
-                               cp += sizeof(u_int16_t);
+                               cp += INT16SZ;
                                cp += dlen;
                        }
                        if ((cp - msg) > len)
                                return (NULL);
                }
-               if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
+               if ((!_res.pfcode) ||
+                   ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
                        putc('\n', file);
        }
-       return(cp);
+       return (cp);
 }
 
 void
@@ -268,7 +272,7 @@ __fp_nquery(msg, len, file)
        if ((_res.options & RES_INIT) == 0 && res_init() == -1)
                return;
 
-#define TruncTest(x) if (x >= endMark) goto trunc
+#define TruncTest(x) if (x > endMark) goto trunc
 #define        ErrorTest(x) if (x == NULL) goto error
 
        /*
@@ -276,9 +280,9 @@ __fp_nquery(msg, len, file)
         */
        hp = (HEADER *)msg;
        cp = msg + HFIXEDSZ;
-       endMark = cp + len;
+       endMark = msg + len;
        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
-               fprintf(file,";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
+               fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
                        _res_opcodes[hp->opcode],
                        _res_resultcodes[hp->rcode],
                        ntohs(hp->id));
@@ -287,22 +291,28 @@ __fp_nquery(msg, len, file)
        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
                putc(';', file);
        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
-               fprintf(file,"; flags:");
+               fprintf(file, "; flags:");
                if (hp->qr)
-                       fprintf(file," qr");
+                       fprintf(file, " qr");
                if (hp->aa)
-                       fprintf(file," aa");
+                       fprintf(file, " aa");
                if (hp->tc)
-                       fprintf(file," tc");
+                       fprintf(file, " tc");
                if (hp->rd)
-                       fprintf(file," rd");
+                       fprintf(file, " rd");
                if (hp->ra)
-                       fprintf(file," ra");
+                       fprintf(file, " ra");
+               if (hp->unused)
+                       fprintf(file, " UNUSED-BIT-ON");
+               if (hp->ad)
+                       fprintf(file, " ad");
+               if (hp->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, "; 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 ((!_res.pfcode) || (_res.pfcode & 
@@ -314,10 +324,10 @@ __fp_nquery(msg, len, file)
         */
        if (n = ntohs(hp->qdcount)) {
                if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
-                       fprintf(file,";; QUESTIONS:\n");
+                       fprintf(file, ";; QUESTIONS:\n");
                while (--n >= 0) {
                        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
-                       fprintf(file,";;\t");
+                               fprintf(file, ";;\t");
                        TruncTest(cp);
                        if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
                                cp = p_cdnname(cp, msg, len, file);
@@ -372,7 +382,7 @@ __fp_nquery(msg, len, file)
        return;
  trunc:
        fprintf(file, "\n;; ...truncated\n");
-               return;
+       return;
  error:
        fprintf(file, "\n;; ...malformed\n");
 }
@@ -411,6 +421,30 @@ __p_cdname(cp, msg, 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)
+       const u_char *cp, *msg;
+       int msglen;
+       char *name;
+       int namelen;
+{
+       int n, newlen;
+
+       if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
+               return (NULL);
+       newlen = strlen (name);
+       if (newlen == 0 || name[newlen - 1] != '.')
+               if (newlen+1 >= namelen)        /* Lack space for final dot */
+                       return (NULL);
+               else
+                       strcpy(name + newlen, ".");
+       return (cp + n);
+}
+
 /* XXX:        the rest of these functions need to become length-limited, too. (vix)
  */
 
@@ -420,18 +454,13 @@ __p_fqname(cp, msg, file)
        FILE *file;
 {
        char name[MAXDNAME];
-       int n;
+       const u_char *n;
 
-       if ((n = dn_expand(msg, cp + MAXCDNAME, cp, name, sizeof name)) < 0)
+       n = __p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
+       if (n == NULL)
                return (NULL);
-       if (name[0] == '\0') {
-               putc('.', file);
-       } else {
-               fputs(name, file);
-               if (name[strlen(name) - 1] != '.')
-                       putc('.', file);
-       }
-       return (cp + n);
+       fputs(name, file);
+       return (n);
 }
 
 /*
@@ -447,21 +476,27 @@ __p_rr(cp, msg, file)
        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) {
                h_errno = NETDB_INTERNAL;
                return (NULL);
        }
-       if ((cp = p_fqname(cp, msg, file)) == NULL)
+       cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname);
+       if (!cp)
                return (NULL);                  /* compression error */
-       type = _getshort(cp);
-       cp += sizeof(u_int16_t);
-       class = _getshort(cp);
-       cp += sizeof(u_int16_t);
-       tmpttl = _getlong(cp);
-       cp += sizeof(u_int32_t);
-       dlen = _getshort(cp);
-       cp += sizeof(u_int16_t);
+       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);
@@ -476,9 +511,9 @@ __p_rr(cp, msg, file)
                switch (class) {
                case C_IN:
                case C_HS:
-                       bcopy(cp, (char *)&inaddr, sizeof(inaddr));
+                       bcopy(cp, (char *)&inaddr, INADDRSZ);
                        if (dlen == 4) {
-                               fprintf(file,"\t%s", inet_ntoa(inaddr));
+                               fprintf(file, "\t%s", inet_ntoa(inaddr));
                                cp += dlen;
                        } else if (dlen == 7) {
                                char *address;
@@ -486,11 +521,11 @@ __p_rr(cp, msg, file)
                                u_short port;
 
                                address = inet_ntoa(inaddr);
-                               cp += sizeof(inaddr);
-                               protocol = *cp;
-                               cp += sizeof(u_char);
-                               port = _getshort(cp);
-                               cp += sizeof(u_int16_t);
+                               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);
                        }
@@ -513,15 +548,27 @@ __p_rr(cp, msg, file)
        case T_HINFO:
        case T_ISDN:
                cp2 = cp + dlen;
-               if (n = *cp++) {
-                       fprintf(file,"\t%.*s", n, cp);
-                       cp += n;
+               (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);
+                       }
                }
-               if ((cp < cp2) && (n = *cp++)) {
-                       fprintf(file,"\t%.*s", n, cp);
-                       cp += n;
-               } else if (type == T_HINFO)
+               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:
@@ -532,18 +579,18 @@ __p_rr(cp, msg, file)
                if ((cp = p_fqname(cp, msg, file)) == NULL)
                        return (NULL);
                fputs(" (\n", file);
-               t = _getlong(cp);  cp += sizeof(u_int32_t);
+               t = _getlong((u_char*)cp);  cp += INT32SZ;
                fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
-               t = _getlong(cp);  cp += sizeof(u_int32_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(cp);  cp += sizeof(u_int32_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(cp);  cp += sizeof(u_int32_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(cp);  cp += sizeof(u_int32_t);
+               t = _getlong((u_char*)cp);  cp += INT32SZ;
                fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
                        (u_long)t, __p_time(t));
                break;
@@ -551,14 +598,14 @@ __p_rr(cp, msg, file)
        case T_MX:
        case T_AFSDB:
        case T_RT:
-               fprintf(file, "\t%d ", _getshort(cp));
+               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(cp));
+               fprintf(file, "\t%d ", _getshort((u_char*)cp));
                cp += INT16SZ;
                if ((cp = p_fqname(cp, msg, file)) == NULL)
                        return (NULL);
@@ -567,28 +614,93 @@ __p_rr(cp, msg, file)
                        return (NULL);
                break;
 
-       case T_TXT:
        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 ((*cp == '\n') || (*cp == '"')) {
-                                           (void) putc('\\', file);
-                                           (void) putc(*cp++, file);
-                                       } else
-                                           (void) putc(*cp++, file);
+                               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);
                }
-               putc('"', file);
-               break;
+               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];
+
+               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);
@@ -601,33 +713,33 @@ __p_rr(cp, msg, file)
 
        case T_UINFO:
                putc('\t', file);
-               fputs((char *) cp, file);
+               fputs((char *)cp, file);
                cp += dlen;
                break;
 
        case T_UID:
        case T_GID:
                if (dlen == 4) {
-                       fprintf(file,"\t%u", _getlong(cp));
-                       cp += sizeof(int32_t);
+                       fprintf(file, "\t%u", _getlong((u_char*)cp));
+                       cp += INT32SZ;
                }
                break;
 
        case T_WKS:
-               if (dlen < sizeof(u_int32_t) + 1)
+               if (dlen < INT32SZ + 1)
                        break;
-               bcopy(cp, (char *)&inaddr, sizeof(inaddr));
-               cp += sizeof(u_int32_t);
+               bcopy(cp, (char *)&inaddr, INADDRSZ);
+               cp += INT32SZ;
                fprintf(file, "\t%s %s ( ",
                        inet_ntoa(inaddr),
                        deproto((int) *cp));
-               cp += sizeof(u_char);
+               cp += sizeof (u_char);
                n = 0;
                lcnt = 0;
                while (cp < cp1 + dlen) {
                        c = *cp++;
                        do {
-                               if (c & 0200) {
+                               if (c & 0200) {
                                        if (lcnt == 0) {
                                                fputs("\n\t\t\t", file);
                                                lcnt = 5;
@@ -636,12 +748,78 @@ __p_rr(cp, msg, file)
                                        putc(' ', file);
                                        lcnt--;
                                }
-                               c <<= 1;
+                               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 (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:
                {
@@ -660,7 +838,7 @@ __p_rr(cp, msg, file)
 #endif /* ALLOW_T_UNSPEC */
 
        default:
-               fprintf(file,"\t?%d?", type);
+               fprintf(file, "\t?%d?", type);
                cp += dlen;
        }
 #if 0
@@ -669,13 +847,144 @@ __p_rr(cp, msg, file)
        putc('\n', file);
 #endif
        if (cp - cp1 != dlen) {
-               fprintf(file,";; packet size error (found %d, dlen was %d)\n",
+               fprintf(file, ";; packet size error (found %d, dlen was %d)\n",
                        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.)
+ */
+const struct res_sym __p_class_syms[] = {
+       {C_IN,          "IN"},
+       {C_CHAOS,       "CHAOS"},
+       {C_HS,          "HS"},
+       {C_HS,          "HESIOD"},
+       {C_ANY,         "ANY"},
+       {C_IN,          (char *)0}
+};
+
+/*
+ * Names of RR types and qtypes.  Types and qtypes are the same, except
+ * that T_ANY is a qtype but not a type.  (You can ask for records of type
+ * 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}
+};
+
+int
+__sym_ston(syms, name, success)
+       const struct res_sym *syms;
+       char *name;
+       int *success;
+{
+       for (NULL; syms->name != 0; syms++) {
+               if (strcasecmp (name, syms->name) == 0) {
+                       if (success)
+                               *success = 1;
+                       return (syms->number);
+               }
+       }
+       if (success)
+               *success = 0;
+       return (syms->number);          /* The default value. */
+}
+
+const char *
+__sym_ntos(syms, number, success)
+       const struct res_sym *syms;
+       int number;
+       int *success;
+{
+       static char unname[20];
+
+       for (NULL; syms->name != 0; syms++) {
+               if (number == syms->number) {
+                       if (success)
+                               *success = 1;
+                       return (syms->name);
+               }
+       }
+
+       sprintf (unname, "%d", number);
+       if (success)
+               *success = 0;
+       return (unname);
+}
+
+
+const char *
+__sym_ntop(syms, number, success)
+       const struct res_sym *syms;
+       int number;
+       int *success;
+{
+       static char unname[20];
+
+       for (NULL; syms->name != 0; syms++) {
+               if (number == syms->number) {
+                       if (success)
+                               *success = 1;
+                       return (syms->humanname);
+               }
+       }
+       sprintf(unname, "%d", number);
+       if (success)
+               *success = 0;
+       return (unname);
+}
+
 /*
  * Return a string for the type
  */
@@ -683,48 +992,7 @@ const char *
 __p_type(type)
        int type;
 {
-       static char nbuf[20];
-
-       switch (type) {
-       case T_A:       return "A";
-       case T_NS:      return "NS";
-       case T_CNAME:   return "CNAME";
-       case T_SOA:     return "SOA";
-       case T_MB:      return "MB";
-       case T_MG:      return "MG";
-       case T_MR:      return "MR";
-       case T_NULL:    return "NULL";
-       case T_WKS:     return "WKS";
-       case T_PTR:     return "PTR";
-       case T_HINFO:   return "HINFO";
-       case T_MINFO:   return "MINFO";
-       case T_MX:      return "MX";
-       case T_TXT:     return "TXT";
-       case T_RP:      return "RP";
-       case T_AFSDB:   return "AFSDB";
-       case T_X25:     return "X25";
-       case T_ISDN:    return "ISDN";
-       case T_RT:      return "RT";
-       case T_NSAP:    return "NSAP";
-       case T_NSAP_PTR: return "NSAP_PTR";
-       case T_SIG:     return "SIG";
-       case T_KEY:     return "KEY";
-       case T_PX:      return "PX";
-       case T_GPOS:    return "GPOS";
-       case T_AAAA:    return "AAAA";
-       case T_LOC:     return "LOC";
-       case T_AXFR:    return "AXFR";
-       case T_MAILB:   return "MAILB";
-       case T_MAILA:   return "MAILA";
-       case T_ANY:     return "ANY";
-       case T_UINFO:   return "UINFO";
-       case T_UID:     return "UID";
-       case T_GID:     return "GID";
-#ifdef ALLOW_T_UNSPEC
-       case T_UNSPEC:  return "UNSPEC";
-#endif /* ALLOW_T_UNSPEC */
-       default:        (void)sprintf(nbuf, "%d", type); return (nbuf);
-       }
+       return (__sym_ntos (__p_type_syms, type, (int *)0));
 }
 
 /*
@@ -734,14 +1002,7 @@ const char *
 __p_class(class)
        int class;
 {
-       static char nbuf[20];
-
-       switch (class) {
-       case C_IN:      return "IN";
-       case C_HS:      return "HS";
-       case C_ANY:     return "ANY";
-       default:        (void)sprintf(nbuf, "%d", class); return (nbuf);
-       }
+       return (__sym_ntos (__p_class_syms, class, (int *)0));
 }
 
 /*
@@ -774,8 +1035,8 @@ __p_option(option)
 /*
  * Return a mnemonic for a time to live
  */
-char *
-__p_time(value)
+const char *
+p_time(value)
        u_int32_t value;
 {
        static char nbuf[40];
@@ -784,7 +1045,7 @@ __p_time(value)
 
        if (value == 0) {
                strcpy(nbuf, "0 secs");
-               return(nbuf);
+               return (nbuf);
        }
 
        secs = value % 60;
@@ -819,5 +1080,437 @@ __p_time(value)
                        *p++ = ' ';
                (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
        }
-       return(nbuf);
+       return (nbuf);
+}
+
+/*
+ * 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.
+ */
+
+static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
+                                     1000000,10000000,100000000,1000000000};
+
+/* takes an XeY precision/size value, returns a string representation. */
+static const char *
+precsize_ntoa(prec)
+       u_int8_t prec;
+{
+       static char retbuf[sizeof "90000000.00"];
+       unsigned long val;
+       int mantissa, exponent;
+
+       mantissa = (int)((prec >> 4) & 0x0f) % 10;
+       exponent = (int)((prec >> 0) & 0x0f) % 10;
+
+       val = mantissa * poweroften[exponent];
+
+       (void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100);
+       return (retbuf);
+}
+
+/* converts ascii size/precision X * 10**Y(cm) to 0xXY.  moves pointer. */
+static u_int8_t
+precsize_aton(strptr)
+       char **strptr;
+{
+       unsigned int mval = 0, cmval = 0;
+       u_int8_t retval = 0;
+       register char *cp;
+       register int exponent;
+       register int mantissa;
+
+       cp = *strptr;
+
+       while (isdigit(*cp))
+               mval = mval * 10 + (*cp++ - '0');
+
+       if (*cp == '.') {               /* centimeters */
+               cp++;
+               if (isdigit(*cp)) {
+                       cmval = (*cp++ - '0') * 10;
+                       if (isdigit(*cp)) {
+                               cmval += (*cp++ - '0');
+                       }
+               }
+       }
+       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;
+
+       retval = (mantissa << 4) | exponent;
+
+       *strptr = cp;
+
+       return (retval);
+}
+
+/* converts ascii lat/lon to unsigned encoded 32-bit number.  moves pointer. */
+static u_int32_t
+latlon2ul(latlonstrptr,which)
+       char **latlonstrptr;
+       int *which;
+{
+       register char *cp;
+       u_int32_t retval;
+       int deg = 0, min = 0, secs = 0, secsfrac = 0;
+
+       cp = *latlonstrptr;
+
+       while (isdigit(*cp))
+               deg = deg * 10 + (*cp++ - '0');
+
+       while (isspace(*cp))
+               cp++;
+
+       if (!(isdigit(*cp)))
+               goto fndhemi;
+
+       while (isdigit(*cp))
+               min = min * 10 + (*cp++ - '0');
+
+       while (isspace(*cp))
+               cp++;
+
+       if (!(isdigit(*cp)))
+               goto fndhemi;
+
+       while (isdigit(*cp))
+               secs = secs * 10 + (*cp++ - '0');
+
+       if (*cp == '.') {               /* decimal seconds */
+               cp++;
+               if (isdigit(*cp)) {
+                       secsfrac = (*cp++ - '0') * 100;
+                       if (isdigit(*cp)) {
+                               secsfrac += (*cp++ - '0') * 10;
+                               if (isdigit(*cp)) {
+                                       secsfrac += (*cp++ - '0');
+                               }
+                       }
+               }
+       }
+
+       while (!isspace(*cp))   /* if any trailing garbage */
+               cp++;
+
+       while (isspace(*cp))
+               cp++;
+
+ fndhemi:
+       switch (*cp) {
+       case 'N': case 'n':
+       case 'E': case 'e':
+               retval = ((unsigned)1<<31)
+                       + (((((deg * 60) + min) * 60) + secs) * 1000)
+                       + secsfrac;
+               break;
+       case 'S': case 's':
+       case 'W': case 'w':
+               retval = ((unsigned)1<<31)
+                       - (((((deg * 60) + min) * 60) + secs) * 1000)
+                       - secsfrac;
+               break;
+       default:
+               retval = 0;     /* invalid value -- indicates error */
+               break;
+       }
+
+       switch (*cp) {
+       case 'N': case 'n':
+       case 'S': case 's':
+               *which = 1;     /* latitude */
+               break;
+       case 'E': case 'e':
+       case 'W': case 'w':
+               *which = 2;     /* longitude */
+               break;
+       default:
+               *which = 0;     /* error */
+               break;
+       }
+
+       cp++;                   /* skip the hemisphere */
+
+       while (!isspace(*cp))   /* if any trailing garbage */
+               cp++;
+
+       while (isspace(*cp))    /* move to next field */
+               cp++;
+
+       *latlonstrptr = cp;
+
+       return (retval);
+}
+
+/* converts a zone file representation in a string to an RDATA on-the-wire
+ * representation. */
+int
+loc_aton(ascii, binary)
+       const char *ascii;
+       u_char *binary;
+{
+       const char *cp, *maxcp;
+       u_char *bcp;
+
+       u_int32_t latit = 0, longit = 0, alt = 0;
+       u_int32_t lltemp1 = 0, lltemp2 = 0;
+       int altmeters = 0, altfrac = 0, altsign = 1;
+       u_int8_t hp = 0x16;     /* default = 1e6 cm = 10000.00m = 10km */
+       u_int8_t vp = 0x13;     /* default = 1e3 cm = 10.00m */
+       u_int8_t siz = 0x12;    /* default = 1e2 cm = 1.00m */
+       int which1 = 0, which2 = 0;
+
+       cp = ascii;
+       maxcp = cp + strlen(ascii);
+
+       lltemp1 = latlon2ul(&cp, &which1);
+
+       lltemp2 = latlon2ul(&cp, &which2);
+
+       switch (which1 + which2) {
+       case 3:                 /* 1 + 2, the only valid combination */
+               if ((which1 == 1) && (which2 == 2)) { /* normal case */
+                       latit = lltemp1;
+                       longit = lltemp2;
+               } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
+                       longit = lltemp1;
+                       latit = lltemp2;
+               } else {        /* some kind of brokenness */
+                       return (0);
+               }
+               break;
+       default:                /* we didn't get one of each */
+               return (0);
+       }
+
+       /* altitude */
+       if (*cp == '-') {
+               altsign = -1;
+               cp++;
+       }
+    
+       if (*cp == '+')
+               cp++;
+
+       while (isdigit(*cp))
+               altmeters = altmeters * 10 + (*cp++ - '0');
+
+       if (*cp == '.') {               /* decimal meters */
+               cp++;
+               if (isdigit(*cp)) {
+                       altfrac = (*cp++ - '0') * 10;
+                       if (isdigit(*cp)) {
+                               altfrac += (*cp++ - '0');
+                       }
+               }
+       }
+
+       alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
+
+       while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
+               cp++;
+
+       while (isspace(*cp) && (cp < maxcp))
+               cp++;
+
+       if (cp >= maxcp)
+               goto defaults;
+
+       siz = precsize_aton(&cp);
+       
+       while (!isspace(*cp) && (cp < maxcp))   /* if trailing garbage or m */
+               cp++;
+
+       while (isspace(*cp) && (cp < maxcp))
+               cp++;
+
+       if (cp >= maxcp)
+               goto defaults;
+
+       hp = precsize_aton(&cp);
+
+       while (!isspace(*cp) && (cp < maxcp))   /* if trailing garbage or m */
+               cp++;
+
+       while (isspace(*cp) && (cp < maxcp))
+               cp++;
+
+       if (cp >= maxcp)
+               goto defaults;
+
+       vp = precsize_aton(&cp);
+
+ defaults:
+
+       bcp = binary;
+       *bcp++ = (u_int8_t) 0;  /* version byte */
+       *bcp++ = siz;
+       *bcp++ = hp;
+       *bcp++ = vp;
+       PUTLONG(latit,bcp);
+       PUTLONG(longit,bcp);
+       PUTLONG(alt,bcp);
+    
+       return (16);            /* size of RR in octets */
+}
+
+/* takes an on-the-wire LOC RR and formats it in a human readable format. */
+const char *
+loc_ntoa(binary, ascii)
+       const u_char *binary;
+       char *ascii;
+{
+       static char *error = "?";
+       register 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;
+
+       int32_t latval, longval, altval;
+       u_int32_t templ;
+       u_int8_t sizeval, hpval, vpval, versionval;
+    
+       char *sizestr, *hpstr, *vpstr;
+
+       versionval = *cp++;
+
+       if (versionval) {
+               sprintf(ascii, "; error: unknown LOC RR version");
+               return (ascii);
+       }
+
+       sizeval = *cp++;
+
+       hpval = *cp++;
+       vpval = *cp++;
+
+       GETLONG(templ, cp);
+       latval = (templ - ((unsigned)1<<31));
+
+       GETLONG(templ, cp);
+       longval = (templ - ((unsigned)1<<31));
+
+       GETLONG(templ, cp);
+       if (templ < referencealt) { /* below WGS 84 spheroid */
+               altval = referencealt - templ;
+               altsign = -1;
+       } else {
+               altval = templ - referencealt;
+               altsign = 1;
+       }
+
+       if (latval < 0) {
+               northsouth = 'S';
+               latval = -latval;
+       } else
+               northsouth = 'N';
+
+       latsecfrac = latval % 1000;
+       latval = latval / 1000;
+       latsec = latval % 60;
+       latval = latval / 60;
+       latmin = latval % 60;
+       latval = latval / 60;
+       latdeg = latval;
+
+       if (longval < 0) {
+               eastwest = 'W';
+               longval = -longval;
+       } else
+               eastwest = 'E';
+
+       longsecfrac = longval % 1000;
+       longval = longval / 1000;
+       longsec = longval % 60;
+       longval = longval / 60;
+       longmin = longval % 60;
+       longval = longval / 60;
+       longdeg = longval;
+
+       altfrac = altval % 100;
+       altmeters = (altval / 100) * altsign;
+
+       if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
+               sizestr = error;
+       if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
+               hpstr = error;
+       if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
+               vpstr = error;
+
+       sprintf(ascii,
+             "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
+               latdeg, latmin, latsec, latsecfrac, northsouth,
+               longdeg, longmin, longsec, longsecfrac, eastwest,
+               altmeters, altfrac, sizestr, hpstr, vpstr);
+
+       if (sizestr != error)
+               free(sizestr);
+       if (hpstr != error)
+               free(hpstr);
+       if (vpstr != error)
+               free(vpstr);
+
+       return (ascii);
+}
+
+
+/* Return the number of DNS hierarchy levels in the name. */
+int
+__dn_count_labels(name)
+       char *name;
+{
+       int i, len, count;
+
+       len = strlen(name);
+
+       for(i = 0, count = 0; i < len; i++) {
+               if (name[i] == '.')
+                       count++;
+       }
+
+       /* don't count initial wildcard */
+       if (name[0] == '*')
+               if (count)
+                       count--;
+
+       /* don't count the null label for root. */
+       /* if terminating '.' not found, must adjust */
+       /* count to include last label */
+       if (len > 0 && name[len-1] != '.')
+               count++;
+       return (count);
+}
+
+
+/* 
+ * 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 */
+       time_t clock = secs;
+       struct tm *time;
+       
+       time = gmtime(&clock);
+       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);
+       return (output);
 }
index 6f4f39e..46b9361 100644 (file)
@@ -1,7 +1,11 @@
-/*-
+/*     $OpenBSD: res_init.c,v 1.11 1997/03/13 19:07:38 downsj Exp $    */
+
+/*
+ * ++Copyright++ 1985, 1989, 1993
+ * -
  * Copyright (c) 1985, 1989, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
+ *    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:
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
  * 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
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: res_init.c,v 1.10 1996/09/22 11:52:07 deraadt Exp $";
+#if 0
+static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
+static char rcsid[] = "$From: res_init.c,v 8.7 1996/09/28 06:51:07 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: res_init.c,v 1.11 1997/03/13 19:07:38 downsj Exp $";
+#endif
 #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>
 #include <unistd.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.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 seperated by a slash (/) or ampersand (&) character.
+ * - Internal resolver variables can be set from the value of the "options"
+ *   property.
+ */
+
 static void res_setoptions __P((char *, char *));
+
+#ifdef RESOLVSORT
+static const char sort_mask[] = "/&";
+#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
 static u_int32_t net_mask __P((struct in_addr));
+#endif
 
 /*
- * Resolver state default settings
+ * Resolver state default settings.
  */
 
-struct __res_state _res = {
-       RES_TIMEOUT,                    /* retransmition time interval */
-       4,                              /* number of times to retransmit */
-       RES_DEFAULT,                    /* options flags */
-       1,                              /* number of name servers */
-};
+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
@@ -105,25 +145,60 @@ int
 res_init()
 {
        register FILE *fp;
-       register char *cp, **pp, *net;
+       register char *cp, **pp;
        register int n;
-       char buf[BUFSIZ], buf2[BUFSIZ];
+       char buf[BUFSIZ];
        int nserv = 0;    /* number of nameserver records read from file */
        int haveenv = 0;
        int havesearch = 0;
+#ifdef RESOLVSORT
        int nsort = 0;
+       char *net;
+#endif
+#ifndef RFC1535
+       int dots;
+#endif
 
-       if (_res.id == 0)
+       /*
+        * 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();
 
-       _res.nsaddr.sin_len = sizeof(struct sockaddr_in);
-       _res.nsaddr.sin_family = AF_INET;
-       _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
 #ifdef USELOOPBACK
        _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
 #else
        _res.nsaddr.sin_addr.s_addr = INADDR_ANY;
 #endif
+       _res.nsaddr.sin_family = AF_INET;
+       _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
        _res.nscount = 1;
        _res.ndots = 1;
        _res.pfcode = 0;
@@ -133,8 +208,6 @@ res_init()
        if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) {
                (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
                _res.defdname[sizeof(_res.defdname) - 1] = '\0';
-               if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
-                       *cp = '\0';
                haveenv++;
 
                /*
@@ -148,7 +221,7 @@ res_init()
                pp = _res.dnsrch;
                *pp++ = cp;
                for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
-                       if (*cp == '\n')        /* silly backwards compat */
+                       if (*cp == '\n')        /* silly backwards compat */
                                break;
                        else if (*cp == ' ' || *cp == '\t') {
                                *cp = 0;
@@ -166,16 +239,21 @@ res_init()
                *pp++ = 0;
        }
 
+#define        MATCH(line, name) \
+       (!strncmp(line, name, sizeof(name) - 1) && \
+       (line[sizeof(name) - 1] == ' ' || \
+        line[sizeof(name) - 1] == '\t'))
+
        if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
            strncpy(_res.lookups, "bf", sizeof _res.lookups);
 
            /* read the config file */
            while (fgets(buf, sizeof(buf), fp) != NULL) {
                /* skip comments */
-               if ((*buf == ';') || (*buf == '#'))
+               if (*buf == ';' || *buf == '#')
                        continue;
                /* read default domain name */
-               if (!strncmp(buf, "domain", sizeof("domain") - 1)) {
+               if (MATCH(buf, "domain")) {
                    if (haveenv)        /* skip if have from environ */
                            continue;
                    cp = buf + sizeof("domain") - 1;
@@ -183,8 +261,7 @@ res_init()
                            cp++;
                    if ((*cp == '\0') || (*cp == '\n'))
                            continue;
-                   (void)strncpy(_res.defdname, cp,
-                                 sizeof(_res.defdname) - 1);
+                   strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
                    _res.defdname[sizeof(_res.defdname) - 1] = '\0';
                    if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
                            *cp = '\0';
@@ -219,7 +296,7 @@ res_init()
                    continue;
                }
                /* set search list */
-               if (!strncmp(buf, "search", sizeof("search") - 1)) {
+               if (MATCH(buf, "search")) {
                    if (haveenv)        /* skip if have from environ */
                            continue;
                    cp = buf + sizeof("search") - 1;
@@ -227,8 +304,7 @@ res_init()
                            cp++;
                    if ((*cp == '\0') || (*cp == '\n'))
                            continue;
-                   (void)strncpy(_res.defdname, cp,
-                                 sizeof(_res.defdname) - 1);
+                   strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
                    _res.defdname[sizeof(_res.defdname) - 1] = '\0';
                    if ((cp = strchr(_res.defdname, '\n')) != NULL)
                            *cp = '\0';
@@ -257,84 +333,110 @@ res_init()
                    continue;
                }
                /* read nameservers to query */
-               if (!strncmp(buf, "nameserver", sizeof("nameserver") - 1) &&
-                  nserv < MAXNS) {
-                  struct in_addr a;
+               if (MATCH(buf, "nameserver") && nserv < MAXNS) {
+                   struct in_addr a;
 
                    cp = buf + sizeof("nameserver") - 1;
                    while (*cp == ' ' || *cp == '\t')
                        cp++;
                    if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
-                       _res.nsaddr_list[nserv].sin_len = sizeof(struct sockaddr_in);
+                       _res.nsaddr_list[nserv].sin_addr = a;
                        _res.nsaddr_list[nserv].sin_family = AF_INET;
                        _res.nsaddr_list[nserv].sin_port =
                                htons(NAMESERVER_PORT);
-                       _res.nsaddr_list[nserv].sin_addr = a;
                        nserv++;
                    }
                    continue;
                }
-               if (!strncmp(buf, "sortlist", sizeof("sortlist") - 1)) {
+#ifdef RESOLVSORT
+               if (MATCH(buf, "sortlist")) {
                    struct in_addr a;
 
                    cp = buf + sizeof("sortlist") - 1;
-                   while (*cp == ' ' || *cp == '\t')
-                       cp++;
-                   while (sscanf(cp,"%[0-9./]s", buf2) && nsort < MAXRESOLVSORT) {
-                       if (net = strchr(buf2, '/'))
-                           *net = '\0';
-                       if (inet_aton(buf2, &a)) {
+                   while (nsort < MAXRESOLVSORT) {
+                       while (*cp == ' ' || *cp == '\t')
+                           cp++;
+                       if (*cp == '\0' || *cp == '\n' || *cp == ';')
+                           break;
+                       net = cp;
+                       while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
+                              isascii(*cp) && !isspace(*cp))
+                               cp++;
+                       n = *cp;
+                       *cp = 0;
+                       if (inet_aton(net, &a)) {
                            _res.sort_list[nsort].addr = a;
-                           if (net && inet_aton(net+1, &a)) {
-                               _res.sort_list[nsort].mask = a.s_addr;
-                           } else {
-                               _res.sort_list[nsort].mask =
+                           if (ISSORTMASK(n)) {
+                               *cp++ = n;
+                               net = cp;
+                               while (*cp && *cp != ';' &&
+                                       isascii(*cp) && !isspace(*cp))
+                                   cp++;
+                               n = *cp;
+                               *cp = 0;
+                               if (inet_aton(net, &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++;
                        }
-                       if (net)
-                               *net = '/';
-                       cp += strlen(buf2);
-                       while (*cp == ' ' || *cp == '\t')
-                           cp++;
+                       *cp = n;
                    }
                    continue;
                }
-               if (!strncmp(buf, "options", sizeof("options") -1)) {
+#endif
+               if (MATCH(buf, "options")) {
                    res_setoptions(buf + sizeof("options") - 1, "conf");
                    continue;
                }
            }
            if (nserv > 1) 
                _res.nscount = nserv;
+#ifdef RESOLVSORT
            _res.nsort = nsort;
+#endif
            (void) fclose(fp);
        }
-       if (_res.defdname[0] == 0) {
-               if (gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
-                  (cp = strchr(buf, '.')))
-                       (void)strcpy(_res.defdname, cp + 1);
-       }
+       if (_res.defdname[0] == 0 &&
+           gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
+           (cp = strchr(buf, '.')) != NULL)
+               strcpy(_res.defdname, cp + 1);
 
        /* find components of local domain that might be searched */
        if (havesearch == 0) {
                pp = _res.dnsrch;
                *pp++ = _res.defdname;
-#ifndef SEARCH_LOCAL_DOMAINS
                *pp = NULL;
-#else
-               for (cp = _res.defdname, n = 0; *cp; cp++)
-                       if (*cp == '.')
-                               n++;
+
+#ifndef RFC1535
+               dots = 0;
+               for (cp = _res.defdname; *cp; cp++)
+                       dots += (*cp == '.');
+
                cp = _res.defdname;
-               for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH;
-                   n--) {
-                       cp = strchr(cp, '.');
-                       *pp++ = ++cp;
+               while (pp < _res.dnsrch + MAXDFLSRCH) {
+                       if (dots < LOCALDOMAINPARTS)
+                               break;
+                       cp = strchr(cp, '.') + 1;    /* we know there is one */
+                       *pp++ = cp;
+                       dots--;
                }
-               *pp++ = 0;
-#endif
+               *pp = NULL;
+#ifdef DEBUG
+               if (_res.options & RES_DEBUG) {
+                       printf(";; res_init()... default dnsrch list:\n");
+                       for (pp = _res.dnsrch; *pp; pp++)
+                               printf(";;\t%s\n", *pp);
+                       printf(";;\t..END..\n");
+               }
+#endif /* DEBUG */
+#endif /* !RFC1535 */
        }
 
        if (issetugid())
@@ -354,28 +456,26 @@ res_setoptions(options, source)
        int i;
 
 #ifdef DEBUG
-       if (_res.options & RES_DEBUG) {
+       if (_res.options & RES_DEBUG)
                printf(";; res_setoptions(\"%s\", \"%s\")...\n",
                       options, source);
-       }
 #endif
        while (*cp) {
                /* skip leading and inner runs of spaces */
                while (*cp == ' ' || *cp == '\t')
                        cp++;
                /* search for and process individual options */
-               if (!strncmp(cp, "ndots:", sizeof("ndots:")-1)) {
+               if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
                        i = atoi(cp + sizeof("ndots:") - 1);
                        if (i <= RES_MAXNDOTS)
                                _res.ndots = i;
                        else
                                _res.ndots = RES_MAXNDOTS;
 #ifdef DEBUG
-                       if (_res.options & RES_DEBUG) {
+                       if (_res.options & RES_DEBUG)
                                printf(";;\tndots=%d\n", _res.ndots);
-                       }
 #endif
-               } else if (!strncmp(cp, "debug", sizeof("debug")-1)) {
+               } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
 #ifdef DEBUG
                        if (!(_res.options & RES_DEBUG)) {
                                printf(";; res_setoptions(\"%s\", \"%s\")..\n",
@@ -384,6 +484,8 @@ res_setoptions(options, source)
                        }
                        printf(";;\tdebug\n");
 #endif
+               } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
+                       _res.options |= RES_USE_INET6;
                } else {
                        /* XXX - print a warning here? */
                }
@@ -393,6 +495,8 @@ res_setoptions(options, source)
        }
 }
 
+#ifdef RESOLVSORT
+/* XXX - should really support CIDR which means explicit masks always. */
 static u_int32_t
 net_mask(in)           /* XXX - should really use system's version of this */
        struct in_addr in;
@@ -401,12 +505,13 @@ net_mask(in)              /* XXX - should really use system's version of this */
 
        if (IN_CLASSA(i))
                return (htonl(IN_CLASSA_NET));
-       if (IN_CLASSB(i))
+       else if (IN_CLASSB(i))
                return (htonl(IN_CLASSB_NET));
        return (htonl(IN_CLASSC_NET));
 }
+#endif
 
-u_int16_t
+u_int
 res_randomid()
 {
        struct timeval now;
index 6fbd6a3..5faba01 100644 (file)
@@ -1,7 +1,11 @@
-/*-
+/*     $OpenBSD: res_mkquery.c,v 1.6 1997/03/13 19:07:39 downsj Exp $  */
+
+/*
+ * ++Copyright++ 1985, 1993
+ * -
  * Copyright (c) 1985, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
+ *    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:
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
  * 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
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: res_mkquery.c,v 1.5 1996/12/14 06:49:39 tholo Exp $";
+#if 0
+static char sccsid[] = "@(#)res_mkquery.c      8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: res_mkquery.c,v 8.5 1996/08/27 08:33:28 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: res_mkquery.c,v 1.6 1997/03/13 19:07:39 downsj Exp $";
+#endif
 #endif /* LIBC_SCCS and not lint */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
-#include <resolv.h>
+
 #include <stdio.h>
+#include <netdb.h>
+#include <resolv.h>
 #include <string.h>
 
 /*
@@ -70,9 +82,9 @@ static char rcsid[] = "$OpenBSD: res_mkquery.c,v 1.5 1996/12/14 06:49:39 tholo E
 int
 res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
        int op;                 /* opcode of query */
-       const char *dname;              /* domain name */
+       const char *dname;      /* domain name */
        int class, type;        /* class and type of query */
-       const u_char *data;             /* resource record data */
+       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 */
@@ -81,11 +93,12 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
        register HEADER *hp;
        register u_char *cp;
        register int n;
-#ifdef ALLOW_UPDATES
-       struct rrec *newrr = (struct rrec *) newrr_in;
-#endif /* ALLOW_UPDATES */
-       u_char *dnptrs[10], **dpp, **lastdnptr;
+       u_char *dnptrs[20], **dpp, **lastdnptr;
 
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+               h_errno = NETDB_INTERNAL;
+               return (-1);
+       }
 #ifdef DEBUG
        if (_res.options & RES_DEBUG)
                printf(";; res_mkquery(%d, %s, %d, %d)\n",
@@ -94,37 +107,36 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
        /*
         * Initialize header fields.
         */
-       if ((buf == NULL) || (buflen < sizeof(HEADER)))
-               return(-1);
-       bzero(buf, sizeof(HEADER));
+       if ((buf == NULL) || (buflen < HFIXEDSZ))
+               return (-1);
+       bzero(buf, HFIXEDSZ);
        hp = (HEADER *) buf;
        hp->id = htons(++_res.id);
        hp->opcode = op;
-       hp->pr = (_res.options & RES_PRIMARY) != 0;
        hp->rd = (_res.options & RES_RECURSE) != 0;
        hp->rcode = NOERROR;
-       cp = buf + sizeof(HEADER);
-       buflen -= sizeof(HEADER);
+       cp = buf + HFIXEDSZ;
+       buflen -= HFIXEDSZ;
        dpp = dnptrs;
        *dpp++ = buf;
        *dpp++ = NULL;
-       lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
+       lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
        /*
         * perform opcode specific processing
         */
        switch (op) {
-       case QUERY:
+       case QUERY:     /*FALLTHROUGH*/
        case NS_NOTIFY_OP:
                if ((buflen -= QFIXEDSZ) < 0)
-                       return(-1);
+                       return (-1);
                if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
                        return (-1);
                cp += n;
                buflen -= n;
                __putshort(type, cp);
-               cp += sizeof(u_int16_t);
+               cp += INT16SZ;
                __putshort(class, cp);
-               cp += sizeof(u_int16_t);
+               cp += INT16SZ;
                hp->qdcount = htons(1);
                if (op == QUERY || data == NULL)
                        break;
@@ -132,18 +144,19 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
                 * Make an additional record for completion domain.
                 */
                buflen -= RRFIXEDSZ;
-               if ((n = dn_comp((const char *)data, cp, buflen, dnptrs, lastdnptr)) < 0)
+               n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr);
+               if (n < 0)
                        return (-1);
                cp += n;
                buflen -= n;
                __putshort(T_NULL, cp);
-               cp += sizeof(u_int16_t);
+               cp += INT16SZ;
                __putshort(class, cp);
-               cp += sizeof(u_int16_t);
+               cp += INT16SZ;
                __putlong(0, cp);
-               cp += sizeof(u_int32_t);
+               cp += INT32SZ;
                __putshort(0, cp);
-               cp += sizeof(u_int16_t);
+               cp += INT16SZ;
                hp->arcount = htons(1);
                break;
 
@@ -155,13 +168,13 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
                        return (-1);
                *cp++ = '\0';   /* no domain name */
                __putshort(type, cp);
-               cp += sizeof(u_int16_t);
+               cp += INT16SZ;
                __putshort(class, cp);
-               cp += sizeof(u_int16_t);
+               cp += INT16SZ;
                __putlong(0, cp);
-               cp += sizeof(u_int32_t);
+               cp += INT32SZ;
                __putshort(datalen, cp);
-               cp += sizeof(u_int16_t);
+               cp += INT16SZ;
                if (datalen) {
                        bcopy(data, cp, datalen);
                        cp += datalen;
@@ -169,64 +182,6 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
                hp->ancount = htons(1);
                break;
 
-#ifdef ALLOW_UPDATES
-       /*
-        * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
-        * (Record to be modified is followed by its replacement in msg.)
-        */
-       case UPDATEM:
-       case UPDATEMA:
-
-       case UPDATED:
-               /*
-                * The res code for UPDATED and UPDATEDA is the same; user
-                * calls them differently: specifies data for UPDATED; server
-                * ignores data if specified for UPDATEDA.
-                */
-       case UPDATEDA:
-               buflen -= RRFIXEDSZ + datalen;
-               if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
-                       return (-1);
-               cp += n;
-               __putshort(type, cp);
-                cp += sizeof(u_int16_t);
-                __putshort(class, cp);
-                cp += sizeof(u_int16_t);
-               __putlong(0, cp);
-               cp += sizeof(u_int32_t);
-               __putshort(datalen, cp);
-                cp += sizeof(u_int16_t);
-               if (datalen) {
-                       bcopy(data, cp, datalen);
-                       cp += datalen;
-               }
-               if ( (op == UPDATED) || (op == UPDATEDA) ) {
-                       hp->ancount = htons(0);
-                       break;
-               }
-               /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
-
-       case UPDATEA:   /* Add new resource record */
-               buflen -= RRFIXEDSZ + datalen;
-               if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
-                       return (-1);
-               cp += n;
-               __putshort(newrr->r_type, cp);
-                cp += sizeof(u_int16_t);
-                __putshort(newrr->r_class, cp);
-                cp += sizeof(u_int16_t);
-               __putlong(0, cp);
-               cp += sizeof(u_int32_t);
-               __putshort(newrr->r_size, cp);
-                cp += sizeof(u_int16_t);
-               if (newrr->r_size) {
-                       bcopy(newrr->r_data, cp, newrr->r_size);
-                       cp += newrr->r_size;
-               }
-               hp->ancount = htons(0);
-               break;
-
-#endif /* ALLOW_UPDATES */
        default:
                return (-1);
        }
index fb2d22c..fcb3954 100644 (file)
@@ -1,7 +1,11 @@
-/*-
+/*     $OpenBSD: res_query.c,v 1.8 1997/03/13 19:07:40 downsj Exp $    */
+
+/*
+ * ++Copyright++ 1988, 1993
+ * -
  * Copyright (c) 1988, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
+ *    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:
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
  * 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
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: res_query.c,v 1.7 1996/08/27 03:32:54 deraadt Exp $";
+#if 0
+static char sccsid[] = "@(#)res_query.c        8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: res_query.c,v 8.9 1996/09/22 00:13:28 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: res_query.c,v 1.8 1997/03/13 19:07:40 downsj Exp $";
+#endif
 #endif /* LIBC_SCCS and not lint */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <arpa/nameser.h>
+
+#include <stdio.h>
 #include <netdb.h>
 #include <resolv.h>
-#include <stdio.h>
 #include <ctype.h>
 #include <errno.h>
 #include <stdlib.h>
@@ -73,7 +84,7 @@ static char rcsid[] = "$OpenBSD: res_query.c,v 1.7 1996/08/27 03:32:54 deraadt E
 #define MAXPACKET      1024
 #endif
 
-char *__hostalias __P((const char *));
+const char *hostalias __P((const char *));
 int h_errno;
 
 /*
@@ -109,7 +120,7 @@ res_query(name, class, type, answer, anslen)
 #endif
 
        n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
-           buf, sizeof(buf));
+                       buf, sizeof(buf));
        if (n <= 0) {
 #ifdef DEBUG
                if (_res.options & RES_DEBUG)
@@ -128,7 +139,6 @@ res_query(name, class, type, answer, anslen)
                return (n);
        }
 
-       hp = (HEADER *) answer;
        if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
 #ifdef DEBUG
                if (_res.options & RES_DEBUG)
@@ -136,21 +146,21 @@ res_query(name, class, type, answer, anslen)
                            ntohs(hp->ancount));
 #endif
                switch (hp->rcode) {
-                       case NXDOMAIN:
-                               h_errno = HOST_NOT_FOUND;
-                               break;
-                       case SERVFAIL:
-                               h_errno = TRY_AGAIN;
-                               break;
-                       case NOERROR:
-                               h_errno = NO_DATA;
-                               break;
-                       case FORMERR:
-                       case NOTIMP:
-                       case REFUSED:
-                       default:
-                               h_errno = NO_RECOVERY;
-                               break;
+               case NXDOMAIN:
+                       h_errno = HOST_NOT_FOUND;
+                       break;
+               case SERVFAIL:
+                       h_errno = TRY_AGAIN;
+                       break;
+               case NOERROR:
+                       h_errno = NO_DATA;
+                       break;
+               case FORMERR:
+               case NOTIMP:
+               case REFUSED:
+               default:
+                       h_errno = NO_RECOVERY;
+                       break;
                }
                return (-1);
        }
@@ -161,9 +171,7 @@ 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 number is left in h_errno.
- * Only useful for queries in the same name hierarchy as the local host
- * (not, for example, for host address-to-name lookups in domain in-addr.arpa).
+ * is detected.  Error code, if any, is left in h_errno.
  */
 int
 res_search(name, class, type, answer, anslen)
@@ -172,7 +180,7 @@ res_search(name, class, type, answer, anslen)
        u_char *answer;         /* buffer to put answer */
        int anslen;             /* size of answer */
 {
-       register char *cp, **domain;
+       register const char *cp, * const *domain;
        HEADER *hp = (HEADER *) answer;
        u_int dots;
        int trailing_dot, ret, saved_herrno;
@@ -182,15 +190,11 @@ res_search(name, class, type, answer, anslen)
                h_errno = NETDB_INTERNAL;
                return (-1);
        }
-
-       got_nodata = 0;
        errno = 0;
        h_errno = HOST_NOT_FOUND;       /* default, if we never query */
        dots = 0;
-       for (cp = (char *)name; *cp; cp++) {
-               if (*cp == '.')
-                       dots++;
-       }
+       for (cp = name; *cp; cp++)
+               dots += (*cp == '.');
        trailing_dot = 0;
        if (cp > name && *--cp == '.')
                trailing_dot++;
@@ -206,7 +210,6 @@ res_search(name, class, type, answer, anslen)
         * 'as is'.  The threshold can be set with the "ndots" option.
         */
        saved_herrno = -1;
-       tried_as_is = 0;
        if (dots >= _res.ndots) {
                ret = res_querydomain(name, NULL, class, type, answer, anslen);
                if (ret > 0)
@@ -223,13 +226,17 @@ res_search(name, class, type, answer, anslen)
         */
        if ((!dots && (_res.options & RES_DEFNAMES)) ||
            (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
-               for (domain = _res.dnsrch; *domain; domain++) {
-                       int done = 0;
+               int done = 0;
+
+               for (domain = (const char * const *)_res.dnsrch;
+                    *domain && !done;
+                    domain++) {
 
                        ret = res_querydomain(name, *domain, class, type,
-                           answer, anslen);
+                                             answer, anslen);
                        if (ret > 0)
                                return (ret);
+
                        /*
                         * If no server present, give up.
                         * If name isn't found in this domain,
@@ -266,20 +273,16 @@ res_search(name, class, type, answer, anslen)
                                /* anything else implies that we're done */
                                done++;
                        }
-                       /*
-                        * if we got here for some reason other than DNSRCH,
+
+                       /* 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))
-                               done++;
-
-                       if (done)
-                               break;
+                               done++;
                }
        }
 
-       /*
-        * if we have not already tried the name "as is", do that now.
+       /* 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.
         */
@@ -287,11 +290,9 @@ res_search(name, class, type, answer, anslen)
                ret = res_querydomain(name, NULL, class, type, answer, anslen);
                if (ret > 0)
                        return (ret);
-               saved_herrno = h_errno;
        }
 
-       /*
-        * if we got here, we didn't satisfy the search.
+       /* if we got here, we didn't satisfy the search.
         * 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.
@@ -318,7 +319,7 @@ res_querydomain(name, domain, class, type, answer, anslen)
        u_char *answer;         /* buffer to put answer */
        int anslen;             /* size of answer */
 {
-       char nbuf[2*MAXDNAME+2];
+       char nbuf[MAXDNAME];
        const char *longname = nbuf;
        int n;
 
@@ -329,7 +330,7 @@ res_querydomain(name, domain, class, type, answer, anslen)
 #ifdef DEBUG
        if (_res.options & RES_DEBUG)
                printf(";; res_querydomain(%s, %s, %d, %d)\n",
-                       name, domain?domain:"<Nil>", class, type);
+                      name, domain?domain:"<Nil>", class, type);
 #endif
        if (domain == NULL) {
                /*
@@ -343,14 +344,13 @@ res_querydomain(name, domain, class, type, answer, anslen)
                } else
                        longname = name;
        } else
-               (void)sprintf(nbuf, "%.*s.%.*s",
-                   MAXDNAME, name, MAXDNAME, domain);
+               sprintf(nbuf, "%.*s.%.*s", MAXDNAME, name, MAXDNAME, domain);
 
        return (res_query(longname, class, type, answer, anslen));
 }
 
-char *
-__hostalias(name)
+const char *
+hostalias(name)
        register const char *name;
 {
        register char *cp1, *cp2;
@@ -379,7 +379,7 @@ __hostalias(name)
                                break;
                        for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
                                ;
-                       (void)strncpy(abuf, cp1, sizeof(abuf) - 1);
+                       strncpy(abuf, cp1, sizeof(abuf) - 1);
                        abuf[sizeof(abuf) - 1] = *cp2 = '\0';
                        fclose(fp);
                        return (abuf);
index 1efd17d..bfc01f9 100644 (file)
@@ -1,4 +1,8 @@
-/*-
+/*     $OpenBSD: res_send.c,v 1.4 1997/03/13 19:07:41 downsj Exp $     */
+
+/*
+ * ++Copyright++ 1985, 1989, 1993
+ * -
  * Copyright (c) 1985, 1989, 1993
  *    The Regents of the University of California.  All rights reserved.
  * 
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: res_send.c,v 1.3 1996/08/19 08:29:49 tholo Exp $";
+#if 0
+static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$From: res_send.c,v 8.12 1996/10/08 04:51:06 vixie Exp $";
+#else
+static char rcsid[] = "$OpenBSD: res_send.c,v 1.4 1997/03/13 19:07:41 downsj Exp $";
+#endif
 #endif /* LIBC_SCCS and not lint */
 
        /* change this to "0"
@@ -66,6 +75,7 @@ static char rcsid[] = "$OpenBSD: res_send.c,v 1.3 1996/08/19 08:29:49 tholo Exp
  * Send query to name server and wait for reply.
  */
 
+#include <sys/types.h>
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/socket.h>
@@ -78,24 +88,24 @@ static char rcsid[] = "$OpenBSD: res_send.c,v 1.3 1996/08/19 08:29:49 tholo Exp
 #include <netdb.h>
 #include <errno.h>
 #include <resolv.h>
-#if defined(BSD) && (BSD >= 199306)
-# include <stdlib.h>
-# include <string.h>
-# include <unistd.h>
-#else
-# include "../conf/portability.h"
-#endif
-
-#if defined(USE_OPTIONS_H)
-# include <../conf/options.h>
-#endif
-
-void _res_close __P((void));
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 
 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 ciruit? */
 
+#ifndef FD_SET
+/* XXX - should be in portability.h */
+#define        NFDBITS         32
+#define        FD_SETSIZE      32
+#define        FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+#define        FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+#define        FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+#define FD_ZERO(p)     bzero((char *)(p), sizeof(*(p)))
+#endif
+
 #define CAN_RECONNECT 1
 
 #ifndef DEBUG
@@ -301,7 +311,7 @@ res_send(buf, buflen, ans, anssiz)
                struct sockaddr_in *nsap = &_res.nsaddr_list[ns];
     same_ns:
                if (badns & (1 << ns)) {
-                       _res_close();
+                       res_close();
                        goto next_ns;
                }
 
@@ -318,7 +328,7 @@ res_send(buf, buflen, ans, anssiz)
                                        done = 1;
                                        break;
                                case res_nextns:
-                                       _res_close();
+                                       res_close();
                                        goto next_ns;
                                case res_done:
                                        return (resplen);
@@ -353,7 +363,7 @@ res_send(buf, buflen, ans, anssiz)
                        truncated = 0;
                        if ((s < 0) || (!vc)) {
                                if (s >= 0)
-                                       _res_close();
+                                       res_close();
 
                                s = socket(PF_INET, SOCK_STREAM, 0);
                                if (s < 0) {
@@ -368,7 +378,7 @@ res_send(buf, buflen, ans, anssiz)
                                        Aerror(stderr, "connect/vc",
                                               errno, *nsap);
                                        badns |= (1 << ns);
-                                       _res_close();
+                                       res_close();
                                        goto next_ns;
                                }
                                vc = 1;
@@ -385,12 +395,13 @@ res_send(buf, buflen, ans, anssiz)
                                terrno = errno;
                                Perror(stderr, "write failed", errno);
                                badns |= (1 << ns);
-                               _res_close();
+                               res_close();
                                goto next_ns;
                        }
                        /*
                         * Receive length & response
                         */
+read_len:
                        cp = ans;
                        len = INT16SZ;
                        while ((n = read(s, (char *)cp, (int)len)) > 0) {
@@ -401,7 +412,7 @@ res_send(buf, buflen, ans, anssiz)
                        if (n <= 0) {
                                terrno = errno;
                                Perror(stderr, "read failed", errno);
-                               _res_close();
+                               res_close();
                                /*
                                 * A long running process might get its TCP
                                 * connection reset if the remote server was
@@ -413,10 +424,10 @@ res_send(buf, buflen, ans, anssiz)
                                 */
                                if (terrno == ECONNRESET && !connreset) {
                                        connreset = 1;
-                                       _res_close();
+                                       res_close();
                                        goto same_ns;
                                }
-                               _res_close();
+                               res_close();
                                goto next_ns;
                        }
                        resplen = _getshort(ans);
@@ -437,7 +448,7 @@ res_send(buf, buflen, ans, anssiz)
                        if (n <= 0) {
                                terrno = errno;
                                Perror(stderr, "read(vc)", errno);
-                               _res_close();
+                               res_close();
                                goto next_ns;
                        }
                        if (truncated) {
@@ -459,6 +470,20 @@ res_send(buf, buflen, ans, anssiz)
                                                break;
                                }
                        }
+                       /*
+                        * The calling applicating has bailed out of
+                        * a previous call and failed to arrange to have
+                        * the circuit closed or the server has got
+                        * itself confused. Anyway drop the packet and
+                        * wait for the correct one.
+                        */
+                       if (hp->id != anhp->id) {
+                               DprintQ((_res.options & RES_DEBUG) ||
+                                       (_res.pfcode & RES_PRF_REPLY),
+                                       (stdout, ";; old answer (unexpected):\n"),
+                                       ans, (resplen>anssiz)?anssiz:resplen);
+                               goto read_len;
+                       }
                } else {
                        /*
                         * Use datagrams.
@@ -470,7 +495,7 @@ res_send(buf, buflen, ans, anssiz)
 
                        if ((s < 0) || vc) {
                                if (vc)
-                                       _res_close();
+                                       res_close();
                                s = socket(PF_INET, SOCK_DGRAM, 0);
                                if (s < 0) {
 #if !CAN_RECONNECT
@@ -510,7 +535,7 @@ res_send(buf, buflen, ans, anssiz)
                                                       "connect(dg)",
                                                       errno, *nsap);
                                                badns |= (1 << ns);
-                                               _res_close();
+                                               res_close();
                                                goto next_ns;
                                        }
                                        connected = 1;
@@ -518,7 +543,7 @@ res_send(buf, buflen, ans, anssiz)
                                if (send(s, (char*)buf, buflen, 0) != buflen) {
                                        Perror(stderr, "send", errno);
                                        badns |= (1 << ns);
-                                       _res_close();
+                                       res_close();
                                        goto next_ns;
                                }
                        } else {
@@ -555,7 +580,7 @@ res_send(buf, buflen, ans, anssiz)
                                    != buflen) {
                                        Aerror(stderr, "sendto", errno, *nsap);
                                        badns |= (1 << ns);
-                                       _res_close();
+                                       res_close();
                                        goto next_ns;
                                }
                        }
@@ -575,8 +600,10 @@ res_send(buf, buflen, ans, anssiz)
                        n = select(s+1, &dsmask, (fd_set *)NULL,
                                   (fd_set *)NULL, &timeout);
                        if (n < 0) {
+                               if (errno == EINTR)
+                                       goto wait;
                                Perror(stderr, "select", errno);
-                               _res_close();
+                               res_close();
                                goto next_ns;
                        }
                        if (n == 0) {
@@ -586,7 +613,7 @@ res_send(buf, buflen, ans, anssiz)
                                Dprint(_res.options & RES_DEBUG,
                                       (stdout, ";; timeout\n"));
                                gotsomewhere = 1;
-                               _res_close();
+                               res_close();
                                goto next_ns;
                        }
                        errno = 0;
@@ -595,7 +622,7 @@ res_send(buf, buflen, ans, anssiz)
                                           (struct sockaddr *)&from, &fromlen);
                        if (resplen <= 0) {
                                Perror(stderr, "recvfrom", errno);
-                               _res_close();
+                               res_close();
                                goto next_ns;
                        }
                        gotsomewhere = 1;
@@ -608,7 +635,7 @@ res_send(buf, buflen, ans, anssiz)
                                DprintQ((_res.options & RES_DEBUG) ||
                                        (_res.pfcode & RES_PRF_REPLY),
                                        (stdout, ";; old answer:\n"),
-                                       ans, resplen);
+                                       ans, (resplen>anssiz)?anssiz:resplen);
                                goto wait;
                        }
 #if CHECK_SRVR_ADDR
@@ -622,7 +649,7 @@ res_send(buf, buflen, ans, anssiz)
                                DprintQ((_res.options & RES_DEBUG) ||
                                        (_res.pfcode & RES_PRF_REPLY),
                                        (stdout, ";; not our server:\n"),
-                                       ans, resplen);
+                                       ans, (resplen>anssiz)?anssiz:resplen);
                                goto wait;
                        }
 #endif
@@ -637,7 +664,7 @@ res_send(buf, buflen, ans, anssiz)
                                DprintQ((_res.options & RES_DEBUG) ||
                                        (_res.pfcode & RES_PRF_REPLY),
                                        (stdout, ";; wrong query name:\n"),
-                                       ans, resplen);
+                                       ans, (resplen>anssiz)?anssiz:resplen);
                                goto wait;
                        }
                        if (anhp->rcode == SERVFAIL ||
@@ -645,9 +672,9 @@ res_send(buf, buflen, ans, anssiz)
                            anhp->rcode == REFUSED) {
                                DprintQ(_res.options & RES_DEBUG,
                                        (stdout, "server rejected query:\n"),
-                                       ans, resplen);
+                                       ans, (resplen>anssiz)?anssiz:resplen);
                                badns |= (1 << ns);
-                               _res_close();
+                               res_close();
                                /* don't retry if called from dig */
                                if (!_res.pfcode)
                                        goto next_ns;
@@ -660,7 +687,7 @@ res_send(buf, buflen, ans, anssiz)
                                Dprint(_res.options & RES_DEBUG,
                                       (stdout, ";; truncated answer\n"));
                                v_circuit = 1;
-                               _res_close();
+                               res_close();
                                goto same_ns;
                        }
                } /*if vc/dg*/
@@ -671,7 +698,7 @@ res_send(buf, buflen, ans, anssiz)
                DprintQ((_res.options & RES_DEBUG) ||
                        (_res.pfcode & RES_PRF_REPLY),
                        (stdout, ""),
-                       ans, resplen);
+                       ans, (resplen>anssiz)?anssiz:resplen);
                /*
                 * If using virtual circuits, we assume that the first server
                 * is preferred over the rest (i.e. it is on the local
@@ -682,7 +709,7 @@ res_send(buf, buflen, ans, anssiz)
                 */
                if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) ||
                    !(_res.options & RES_STAYOPEN)) {
-                       _res_close();
+                       res_close();
                }
                if (Rhook) {
                        int done = 0, loops = 0;
@@ -698,7 +725,7 @@ res_send(buf, buflen, ans, anssiz)
                                        done = 1;
                                        break;
                                case res_nextns:
-                                       _res_close();
+                                       res_close();
                                        goto next_ns;
                                case res_modified:
                                        /* give the hook another try */
@@ -717,7 +744,7 @@ res_send(buf, buflen, ans, anssiz)
     next_ns: ;
           } /*foreach ns*/
        } /*foreach retry*/
-       _res_close();
+       res_close();
        if (!v_circuit)
                if (!gotsomewhere)
                        errno = ECONNREFUSED;   /* no nameservers found */
@@ -736,7 +763,7 @@ res_send(buf, buflen, ans, anssiz)
  * This routine is not expected to be user visible.
  */
 void
-_res_close()
+res_close()
 {
        if (s >= 0) {
                (void) close(s);
index d85251e..7791322 100644 (file)
@@ -1,2 +1,2 @@
-major=14
+major=15
 minor=0