summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Downs <downsj@cvs.openbsd.org>1997-03-13 19:07:42 +0000
committerJason Downs <downsj@cvs.openbsd.org>1997-03-13 19:07:42 +0000
commit6f186362d0923eb9f92a696a1132378f6854f243 (patch)
treec516aca93e6026f753f6dcf2f004073ee9cd8ca3
parent6e0f740fe402f51cdf52c350f93fbda7a6328142 (diff)
Integrate BIND 4.9.5 resolver and associated routines.
Includes the DNS aware getnetby*() routines and IPv6 support.
-rw-r--r--lib/libc/net/Makefile.inc15
-rw-r--r--lib/libc/net/base64.c319
-rw-r--r--lib/libc/net/gethostbyname.348
-rw-r--r--lib/libc/net/gethostnamadr.c775
-rw-r--r--lib/libc/net/getnetbyaddr.c6
-rw-r--r--lib/libc/net/getnetbyname.c4
-rw-r--r--lib/libc/net/getnetent.323
-rw-r--r--lib/libc/net/getnetnamadr.c291
-rw-r--r--lib/libc/net/herror.c26
-rw-r--r--lib/libc/net/inet_addr.c82
-rw-r--r--lib/libc/net/inet_net_ntop.c139
-rw-r--r--lib/libc/net/inet_net_pton.c207
-rw-r--r--lib/libc/net/inet_neta.c82
-rw-r--r--lib/libc/net/inet_ntop.c194
-rw-r--r--lib/libc/net/inet_pton.c220
-rw-r--r--lib/libc/net/nsap_addr.c55
-rw-r--r--lib/libc/net/res_comp.c174
-rw-r--r--lib/libc/net/res_data.c117
-rw-r--r--lib/libc/net/res_debug.c1055
-rw-r--r--lib/libc/net/res_init.c259
-rw-r--r--lib/libc/net/res_mkquery.c139
-rw-r--r--lib/libc/net/res_query.c116
-rw-r--r--lib/libc/net/res_send.c111
-rw-r--r--lib/libc/shlib_version2
24 files changed, 3666 insertions, 793 deletions
diff --git a/lib/libc/net/Makefile.inc b/lib/libc/net/Makefile.inc
index 04831f4f2d9..03f7349e5e7 100644
--- a/lib/libc/net/Makefile.inc
+++ b/lib/libc/net/Makefile.inc
@@ -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
index 00000000000..59788bee1ba
--- /dev/null
+++ b/lib/libc/net/base64.c
@@ -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);
+}
diff --git a/lib/libc/net/gethostbyname.3 b/lib/libc/net/gethostbyname.3
index 8dfdb88cf0b..1394fa34678 100644
--- a/lib/libc/net/gethostbyname.3
+++ b/lib/libc/net/gethostbyname.3
@@ -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.
@@ -31,11 +31,12 @@
.\" 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.
diff --git a/lib/libc/net/gethostnamadr.c b/lib/libc/net/gethostnamadr.c
index 83e0225a656..9826b468050 100644
--- a/lib/libc/net/gethostnamadr.c
+++ b/lib/libc/net/gethostnamadr.c
@@ -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,11 +768,17 @@ 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);
}
@@ -514,58 +786,55 @@ 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
diff --git a/lib/libc/net/getnetbyaddr.c b/lib/libc/net/getnetbyaddr.c
index aabd741a88d..3d2b6e03526 100644
--- a/lib/libc/net/getnetbyaddr.c
+++ b/lib/libc/net/getnetbyaddr.c
@@ -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;
diff --git a/lib/libc/net/getnetbyname.c b/lib/libc/net/getnetbyname.c
index d2a5b8679ad..764c78b361c 100644
--- a/lib/libc/net/getnetbyname.c
+++ b/lib/libc/net/getnetbyname.c
@@ -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;
diff --git a/lib/libc/net/getnetent.3 b/lib/libc/net/getnetent.3
index 9cd54a817ce..a3aebf43102 100644
--- a/lib/libc/net/getnetent.3
+++ b/lib/libc/net/getnetent.3
@@ -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
index 00000000000..cc6ccc42756
--- /dev/null
+++ b/lib/libc/net/getnetnamadr.c
@@ -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));
+}
diff --git a/lib/libc/net/herror.c b/lib/libc/net/herror.c
index 40da6562ada..737bb115a7f 100644
--- a/lib/libc/net/herror.c
+++ b/lib/libc/net/herror.c
@@ -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:
@@ -12,12 +16,12 @@
* 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
@@ -52,16 +56,22 @@
*/
#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 */
diff --git a/lib/libc/net/inet_addr.c b/lib/libc/net/inet_addr.c
index 99a6f66ad2c..ef8ee4963bc 100644
--- a/lib/libc/net/inet_addr.c
+++ b/lib/libc/net/inet_addr.c
@@ -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:
@@ -12,12 +16,12 @@
* 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
@@ -29,12 +33,38 @@
* 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
index 00000000000..943ec44550f
--- /dev/null
+++ b/lib/libc/net/inet_net_ntop.c
@@ -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
index 00000000000..b529e836645
--- /dev/null
+++ b/lib/libc/net/inet_net_pton.c
@@ -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
index 00000000000..dffd1631b13
--- /dev/null
+++ b/lib/libc/net/inet_neta.c
@@ -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
index 00000000000..64d0d137680
--- /dev/null
+++ b/lib/libc/net/inet_ntop.c
@@ -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
index 00000000000..8ffe81ed12f
--- /dev/null
+++ b/lib/libc/net/inet_pton.c
@@ -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);
+}
diff --git a/lib/libc/net/nsap_addr.c b/lib/libc/net/nsap_addr.c
index ce0a60a7d81..e62d952a07b 100644
--- a/lib/libc/net/nsap_addr.c
+++ b/lib/libc/net/nsap_addr.c
@@ -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;
diff --git a/lib/libc/net/res_comp.c b/lib/libc/net/res_comp.c
index f64a81d7ce5..2e98003b851 100644
--- a/lib/libc/net/res_comp.c
+++ b/lib/libc/net/res_comp.c
@@ -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:
@@ -12,12 +16,12 @@
* 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
@@ -52,19 +56,28 @@
*/
#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
index 00000000000..b0d19c36bb7
--- /dev/null
+++ b/lib/libc/net/res_data.c
@@ -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",
+};
diff --git a/lib/libc/net/res_debug.c b/lib/libc/net/res_debug.c
index ae6c030a1f0..7fd6d4a21c6 100644
--- a/lib/libc/net/res_debug.c
+++ b/lib/libc/net/res_debug.c
@@ -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:
@@ -48,63 +52,61 @@
* 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,7 +847,7 @@ __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;
}
@@ -677,54 +855,144 @@ __p_rr(cp, msg, file)
}
/*
+ * 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
*/
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);
}
diff --git a/lib/libc/net/res_init.c b/lib/libc/net/res_init.c
index 6f4f39ef9f1..46b93611269 100644
--- a/lib/libc/net/res_init.c
+++ b/lib/libc/net/res_init.c
@@ -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:
@@ -12,12 +16,12 @@
* 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
@@ -52,33 +56,69 @@
*/
#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;
diff --git a/lib/libc/net/res_mkquery.c b/lib/libc/net/res_mkquery.c
index 6fbd6a38599..5faba01748d 100644
--- a/lib/libc/net/res_mkquery.c
+++ b/lib/libc/net/res_mkquery.c
@@ -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:
@@ -12,12 +16,12 @@
* 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
@@ -52,14 +56,22 @@
*/
#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);
}
diff --git a/lib/libc/net/res_query.c b/lib/libc/net/res_query.c
index fb2d22c1192..fcb39540099 100644
--- a/lib/libc/net/res_query.c
+++ b/lib/libc/net/res_query.c
@@ -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:
@@ -12,12 +16,12 @@
* 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
@@ -52,16 +56,23 @@
*/
#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);
diff --git a/lib/libc/net/res_send.c b/lib/libc/net/res_send.c
index 1efd17df2b8..bfc01f9b6af 100644
--- a/lib/libc/net/res_send.c
+++ b/lib/libc/net/res_send.c
@@ -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.
*
@@ -52,7 +56,12 @@
*/
#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);
diff --git a/lib/libc/shlib_version b/lib/libc/shlib_version
index d85251eba7d..77913220429 100644
--- a/lib/libc/shlib_version
+++ b/lib/libc/shlib_version
@@ -1,2 +1,2 @@
-major=14
+major=15
minor=0