diff options
author | Jason Downs <downsj@cvs.openbsd.org> | 1997-03-13 19:07:42 +0000 |
---|---|---|
committer | Jason Downs <downsj@cvs.openbsd.org> | 1997-03-13 19:07:42 +0000 |
commit | 6f186362d0923eb9f92a696a1132378f6854f243 (patch) | |
tree | c516aca93e6026f753f6dcf2f004073ee9cd8ca3 | |
parent | 6e0f740fe402f51cdf52c350f93fbda7a6328142 (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.inc | 15 | ||||
-rw-r--r-- | lib/libc/net/base64.c | 319 | ||||
-rw-r--r-- | lib/libc/net/gethostbyname.3 | 48 | ||||
-rw-r--r-- | lib/libc/net/gethostnamadr.c | 775 | ||||
-rw-r--r-- | lib/libc/net/getnetbyaddr.c | 6 | ||||
-rw-r--r-- | lib/libc/net/getnetbyname.c | 4 | ||||
-rw-r--r-- | lib/libc/net/getnetent.3 | 23 | ||||
-rw-r--r-- | lib/libc/net/getnetnamadr.c | 291 | ||||
-rw-r--r-- | lib/libc/net/herror.c | 26 | ||||
-rw-r--r-- | lib/libc/net/inet_addr.c | 82 | ||||
-rw-r--r-- | lib/libc/net/inet_net_ntop.c | 139 | ||||
-rw-r--r-- | lib/libc/net/inet_net_pton.c | 207 | ||||
-rw-r--r-- | lib/libc/net/inet_neta.c | 82 | ||||
-rw-r--r-- | lib/libc/net/inet_ntop.c | 194 | ||||
-rw-r--r-- | lib/libc/net/inet_pton.c | 220 | ||||
-rw-r--r-- | lib/libc/net/nsap_addr.c | 55 | ||||
-rw-r--r-- | lib/libc/net/res_comp.c | 174 | ||||
-rw-r--r-- | lib/libc/net/res_data.c | 117 | ||||
-rw-r--r-- | lib/libc/net/res_debug.c | 1055 | ||||
-rw-r--r-- | lib/libc/net/res_init.c | 259 | ||||
-rw-r--r-- | lib/libc/net/res_mkquery.c | 139 | ||||
-rw-r--r-- | lib/libc/net/res_query.c | 116 | ||||
-rw-r--r-- | lib/libc/net/res_send.c | 111 | ||||
-rw-r--r-- | lib/libc/shlib_version | 2 |
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 |