From: downsj Date: Thu, 13 Mar 1997 19:07:19 +0000 (+0000) Subject: Integrate BIND 4.9.5 resolver and associated routines. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=7949d54b55503bacbfd3b02073ac82545fb19755;p=openbsd Integrate BIND 4.9.5 resolver and associated routines. Includes the DNS aware getnetby*() routines and IPv6 support. --- 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#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 @@ -66,6 +66,7 @@ static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.13 1997/01/30 05:56:06 dera #include #include #include +#include #ifdef YP #include #include @@ -73,6 +74,8 @@ static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.13 1997/01/30 05:56:06 dera #include "ypinternal.h" #endif +#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */ + #define MAXALIASES 35 #define MAXADDRS 35 @@ -85,10 +88,22 @@ static char *__ypdomain; static struct hostent host; static char *host_aliases[MAXALIASES]; static char hostbuf[BUFSIZ+1]; -static struct in_addr host_addr; +static u_char host_addr[16]; /* IPv4 or IPv6 */ static FILE *hostf = NULL; static int stayopen = 0; +static void map_v4v6_address __P((const char *src, char *dst)); +static void map_v4v6_hostent __P((struct hostent *hp, char **bp, int *len)); + +#ifdef RESOLVSORT +static void addrsort __P((char **, int)); +#endif + +static int hokchar __P((const char *)); + +static const char AskedForGot[] = + "gethostby*.getanswer: asked for \"%s\", got \"%s\""; + #if PACKETSZ > 1024 #define MAXPACKET PACKETSZ #else @@ -105,15 +120,14 @@ typedef union { char ac; } align; -static int qcomp __P((struct in_addr **, struct in_addr **)); -static struct hostent *getanswer __P((querybuf *, int, int)); -static int hbadchar __P((char *)); +static struct hostent *getanswer __P((const querybuf *, int, const char *, + int)); extern int h_errno; static int -hbadchar(p) - char *p; +hokchar(p) + const char *p; { char c; @@ -121,7 +135,7 @@ hbadchar(p) * Many people do not obey RFC 822 and 1035. The valid * characters are a-z, A-Z, 0-9, '-' and . But the others * tested for below can happen, and we must be more permissive - * until those idiots clean up their act. + * than the resolver until those idiots clean up their act. */ while ((c = *p++)) { if (('a' >= c && c <= 'z') || @@ -130,28 +144,50 @@ hbadchar(p) continue; if (strchr("-_/.[]\\", c) || (c == '.' && p[1] == '.')) - return 1; + return 0; } - return 0; + return 1; } static struct hostent * -getanswer(answer, anslen, iquery) - querybuf *answer; +getanswer(answer, anslen, qname, qtype) + const querybuf *answer; int anslen; - int iquery; + const char *qname; + int qtype; { - register HEADER *hp; - register u_char *cp; + register const HEADER *hp; + register const u_char *cp; register int n; - u_char *eom; - char *bp, **ap; + const u_char *eom; + char *bp, **ap, **hap; int type, class, buflen, ancount, qdcount; - int haveanswer, getclass = C_ANY; - char **hap; - int good = 1; + int haveanswer, had_error; + int toobig = 0; + char tbuf[MAXDNAME]; + const char *tname; + int (*name_ok) __P((const char *)); + tname = qname; + host.h_name = NULL; eom = answer->buf + anslen; + switch (qtype) { + case T_A: + case T_AAAA: +#ifdef USE_RESOLV_NAME_OK + name_ok = res_hnok; + break; +#endif + case T_PTR: +#ifdef USE_RESOLV_NAME_OK + name_ok = res_dnok; +#else + name_ok = hokchar; +#endif + break; + default: + return (NULL); /* XXX should be abort(); */ + } /* * find first satisfactory answer */ @@ -159,34 +195,29 @@ getanswer(answer, anslen, iquery) ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); bp = hostbuf; - buflen = sizeof(hostbuf); - cp = answer->buf + sizeof(HEADER); - if (qdcount) { - if (iquery) { - if ((n = dn_expand((u_char *)answer->buf, - (u_char *)eom, (u_char *)cp, bp, - buflen)) < 0) { - h_errno = NO_RECOVERY; - return ((struct hostent *) NULL); - } - cp += n + QFIXEDSZ; - host.h_name = bp; - n = strlen(bp); - if (n >= MAXHOSTNAMELEN) - host.h_name[MAXHOSTNAMELEN-1] = '\0'; - n++; - bp += n; - buflen -= n; - } else - cp += __dn_skipname(cp, eom) + QFIXEDSZ; - while (--qdcount > 0) - cp += __dn_skipname(cp, eom) + QFIXEDSZ; - } else if (iquery) { - if (hp->aa) - h_errno = HOST_NOT_FOUND; - else - h_errno = TRY_AGAIN; - return ((struct hostent *) NULL); + buflen = sizeof hostbuf; + cp = answer->buf + HFIXEDSZ; + if (qdcount != 1) { + h_errno = NO_RECOVERY; + return (NULL); + } + n = dn_expand(answer->buf, eom, cp, bp, buflen); + if ((n < 0) || !(*name_ok)(bp)) { + h_errno = NO_RECOVERY; + return (NULL); + } + cp += n + QFIXEDSZ; + if (qtype == T_A || qtype == T_AAAA) { + /* res_send() has already verified that the query name is the + * same as the one we sent; this just gets the expanded name + * (i.e., with the succeeding search-domain tacked on). + */ + n = strlen(bp) + 1; /* for the \0 */ + host.h_name = bp; + bp += n; + buflen -= n; + /* The qname can be abbreviated, but h_name is now absolute. */ + qname = host.h_name; } ap = host_aliases; *ap = NULL; @@ -195,124 +226,258 @@ getanswer(answer, anslen, iquery) *hap = NULL; host.h_addr_list = h_addr_ptrs; haveanswer = 0; - if (ancount > MAXADDRS) - ancount = MAXADDRS; - while (--ancount >= 0 && cp < eom) { - if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom, - (u_char *)cp, bp, buflen)) < 0) - break; - cp += n; + had_error = 0; + while (ancount-- > 0 && cp < eom && !had_error) { + n = dn_expand(answer->buf, eom, cp, bp, buflen); + if ((n < 0) || !(*name_ok)(bp)) { + had_error++; + continue; + } + cp += n; /* name */ type = _getshort(cp); - cp += sizeof(u_int16_t); + cp += INT16SZ; /* type */ class = _getshort(cp); - cp += sizeof(u_int16_t) + sizeof(u_int32_t); + cp += INT16SZ + INT32SZ; /* class, TTL */ n = _getshort(cp); - cp += sizeof(u_int16_t); - if (type == T_CNAME) { + cp += INT16SZ; /* len */ + if (class != C_IN) { + /* XXX - debug? syslog? */ cp += n; + continue; /* XXX - had_error++ ? */ + } + if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { if (ap >= &host_aliases[MAXALIASES-1]) continue; + n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); + if ((n < 0) || !(*name_ok)(tbuf)) { + had_error++; + continue; + } + cp += n; + /* Store alias. */ *ap++ = bp; - n = strlen(bp) + 1; - if (n > MAXHOSTNAMELEN) - bp[MAXHOSTNAMELEN-1] = '\0'; + n = strlen(bp) + 1; /* for the \0 */ + bp += n; + buflen -= n; + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > buflen) { + had_error++; + continue; + } + strcpy(bp, tbuf); + host.h_name = bp; bp += n; buflen -= n; continue; } - if (iquery && type == T_PTR) { - if ((n = dn_expand((u_char *)answer->buf, - (u_char *)eom, (u_char *)cp, bp, - buflen)) < 0) - break; + if (qtype == T_PTR && type == T_CNAME) { + n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); + if ((n < 0) || !res_hnok(tbuf)) { + had_error++; + continue; + } cp += n; - host.h_name = bp; - n = strlen(host.h_name); - if (n >= MAXHOSTNAMELEN) - host.h_name[MAXHOSTNAMELEN-1] = '\0'; - goto gotent; + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > buflen) { + had_error++; + continue; + } + strcpy(bp, tbuf); + tname = bp; + bp += n; + buflen -= n; + continue; } - if (iquery || type != T_A) { -#ifdef DEBUG - if (_res.options & RES_DEBUG) - printf("unexpected answer type %d, size %d\n", - type, n); -#endif + if (type != qtype) { + syslog(LOG_NOTICE|LOG_AUTH, + "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", + qname, p_class(C_IN), p_type(qtype), + p_type(type)); cp += n; - continue; + continue; /* XXX - had_error++ ? */ } - - if (haveanswer) { - if (n != host.h_length) { + switch (type) { + case T_PTR: + if (strcasecmp(tname, bp) != 0) { + syslog(LOG_NOTICE|LOG_AUTH, + AskedForGot, qname, bp); cp += n; - continue; + continue; /* XXX - had_error++ ? */ } - if (class != getclass) { + n = dn_expand(answer->buf, eom, cp, bp, buflen); + if ((n < 0) || !res_hnok(bp)) { + had_error++; + break; + } +#if MULTI_PTRS_ARE_ALIASES + cp += n; + if (!haveanswer) + host.h_name = bp; + else if (ap < &host_aliases[MAXALIASES-1]) + *ap++ = bp; + else + n = -1; + if (n != -1) { + n = strlen(bp) + 1; /* for the \0 */ + bp += n; + buflen -= n; + } + break; +#else + host.h_name = bp; + if (_res.options & RES_USE_INET6) { + n = strlen(bp) + 1; /* for the \0 */ + bp += n; + buflen -= n; + map_v4v6_hostent(&host, &bp, &buflen); + } + h_errno = NETDB_SUCCESS; + return (&host); +#endif + case T_A: + case T_AAAA: + if (strcasecmp(host.h_name, bp) != 0) { + syslog(LOG_NOTICE|LOG_AUTH, + AskedForGot, host.h_name, bp); + cp += n; + continue; /* XXX - had_error++ ? */ + } + if (n != host.h_length) { cp += n; continue; } - } else { - host.h_length = n; - getclass = class; - host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; - if (host.h_addrtype == AF_INET) - host.h_length = INADDRSZ; - if (!iquery) { + if (!haveanswer) { + register int nn; + host.h_name = bp; - bp += strlen(bp) + 1; - if (strlen(host.h_name) >= MAXHOSTNAMELEN) - host.h_name[MAXHOSTNAMELEN-1] = '\0'; + nn = strlen(bp) + 1; /* for the \0 */ + bp += nn; + buflen -= nn; } - } - bp += sizeof(align) - ((u_long)bp % sizeof(align)); + bp += sizeof(align) - ((u_long)bp % sizeof(align)); - if (bp + n >= &hostbuf[sizeof(hostbuf)]) { + if (bp + n >= &hostbuf[sizeof hostbuf]) { +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf("size (%d) too big\n", n); +#endif + had_error++; + continue; + } + if (hap >= &h_addr_ptrs[MAXADDRS-1]) { + if (!toobig++) #ifdef DEBUG - if (_res.options & RES_DEBUG) - printf("size (%d) too big\n", n); + if (_res.options & RES_DEBUG) + printf("Too many addresses (%d)\n", MAXADDRS); #endif + cp += n; + continue; + } + bcopy(cp, *hap++ = bp, n); + bp += n; + buflen -= n; + cp += n; break; + default: + abort(); } - bcopy(cp, *hap++ = bp, n); - bp +=n; - cp += n; - haveanswer++; - } - if (!haveanswer) { - h_errno = TRY_AGAIN; - return ((struct hostent *) NULL); - } - *ap = NULL; - *hap = NULL; - if (_res.nsort) { - qsort(host.h_addr_list, haveanswer, - sizeof(struct in_addr), - (int (*)__P((const void *, const void *)))qcomp); + if (!had_error) + haveanswer++; } -gotent: - if (hbadchar(host.h_name)) - good = 0; - for (ap = host_aliases; good && *ap; ap++) - if (hbadchar(*ap)) - good = 0; - if (good) + if (haveanswer) { + *ap = NULL; + *hap = NULL; +# if defined(RESOLVSORT) + /* + * Note: we sort even if host can take only one address + * in its return structures - should give it the "best" + * address in that case, not some random one + */ + if (_res.nsort && haveanswer > 1 && qtype == T_A) + addrsort(h_addr_ptrs, haveanswer); +# endif /*RESOLVSORT*/ + if (!host.h_name) { + n = strlen(qname) + 1; /* for the \0 */ + if (n > buflen) + goto try_again; + strcpy(bp, qname); + host.h_name = bp; + bp += n; + buflen -= n; + } + if (_res.options & RES_USE_INET6) + map_v4v6_hostent(&host, &bp, &buflen); + h_errno = NETDB_SUCCESS; return (&host); - h_errno = NO_RECOVERY; - return ((struct hostent *) NULL); + } + try_again: + h_errno = TRY_AGAIN; + return (NULL); } struct hostent * gethostbyname(name) const char *name; +{ + struct hostent *hp; + extern struct hostent *_gethtbyname2(); + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return (_gethtbyname2(name, AF_INET)); + + if (_res.options & RES_USE_INET6) { + hp = gethostbyname2(name, AF_INET6); + if (hp) + return (hp); + } + return (gethostbyname2(name, AF_INET)); +} + +struct hostent * +gethostbyname2(name, af) + const char *name; + int af; { querybuf buf; register const char *cp; - int n, i; - extern struct hostent *_gethtbyname(), *_yp_gethtbyname(); + char *bp; + int n, size, type, len, i; + extern struct hostent *_gethtbyname2(), *_yp_gethtbyname(); register struct hostent *hp; char lookups[MAXDNSLUS]; + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return (_gethtbyname2(name, af)); + + switch (af) { + case AF_INET: + size = INADDRSZ; + type = T_A; + break; + case AF_INET6: + size = IN6ADDRSZ; + type = T_AAAA; + break; + default: + h_errno = NETDB_INTERNAL; + errno = EAFNOSUPPORT; + return (NULL); + } + + host.h_addrtype = af; + host.h_length = size; + + /* + * if there aren't any dots, it could be a user-level alias. + * this is also done in res_query() since we are not the only + * function that looks up host names. + */ + if (!strchr(name, '.') && (cp = __hostalias(name))) + name = cp; + /* * disallow names consisting only of digits/dots, unless * they end in a dot. @@ -327,26 +492,58 @@ gethostbyname(name) * Fake up a hostent as if we'd actually * done a lookup. */ - if (!inet_aton(name, &host_addr)) { + if (inet_pton(af, name, host_addr) <= 0) { h_errno = HOST_NOT_FOUND; - return((struct hostent *) NULL); + return (NULL); } - host.h_name = (char *)name; + strncpy(hostbuf, name, MAXDNAME); + hostbuf[MAXDNAME] = '\0'; + bp = hostbuf + MAXDNAME; + len = sizeof hostbuf - MAXDNAME; + host.h_name = hostbuf; host.h_aliases = host_aliases; host_aliases[0] = NULL; - host.h_addrtype = AF_INET; - host.h_length = sizeof(u_int32_t); - h_addr_ptrs[0] = (char *)&host_addr; + h_addr_ptrs[0] = (char *)host_addr; h_addr_ptrs[1] = NULL; host.h_addr_list = h_addr_ptrs; + if (_res.options & RES_USE_INET6) + map_v4v6_hostent(&host, &bp, &len); + h_errno = NETDB_SUCCESS; return (&host); } if (!isdigit(*cp) && *cp != '.') break; } - - if ((_res.options & RES_INIT) == 0 && res_init() == -1) - return (_gethtbyname(name)); + if (isxdigit(name[0]) || name[0] == ':') + for (cp = name;; ++cp) { + if (!*cp) { + if (*--cp == '.') + break; + /* + * All-IPv6-legal, no dot at the end. + * Fake up a hostent as if we'd actually + * done a lookup. + */ + if (inet_pton(af, name, host_addr) <= 0) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + strncpy(hostbuf, name, MAXDNAME); + hostbuf[MAXDNAME] = '\0'; + bp = hostbuf + MAXDNAME; + len = sizeof hostbuf - MAXDNAME; + host.h_name = hostbuf; + host.h_aliases = host_aliases; + host_aliases[0] = NULL; + h_addr_ptrs[0] = (char *)host_addr; + h_addr_ptrs[1] = NULL; + host.h_addr_list = h_addr_ptrs; + h_errno = NETDB_SUCCESS; + return (&host); + } + if (!isxdigit(*cp) && *cp != ':' && *cp != '.') + break; + } bcopy(_res.lookups, lookups, sizeof lookups); if (lookups[0] == '\0') @@ -357,11 +554,13 @@ gethostbyname(name) switch (lookups[i]) { #ifdef YP case 'y': - hp = _yp_gethtbyname(name); + /* YP only suports AF_INET. */ + if (af == AF_INET) + hp = _yp_gethtbyname(name); break; #endif case 'b': - if ((n = res_search(name, C_IN, T_A, buf.buf, + if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf))) < 0) { #ifdef DEBUG if (_res.options & RES_DEBUG) @@ -369,10 +568,10 @@ gethostbyname(name) #endif break; } - hp = getanswer(&buf, n, 0); + hp = getanswer(&buf, n, name, type); break; case 'f': - hp = _gethtbyname(name); + hp = _gethtbyname2(name, af); break; } } @@ -380,27 +579,69 @@ gethostbyname(name) } struct hostent * -gethostbyaddr(addr, len, type) - const char *addr; - int len, type; +gethostbyaddr(addr, len, af) + const char *addr; /* XXX should have been def'd as u_char! */ + int len, af; { - int n, i; + const u_char *uaddr = (const u_char *)addr; + static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; + static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; + int n, size, i; querybuf buf; register struct hostent *hp; - char qbuf[MAXDNAME]; + char qbuf[MAXDNAME+1], *qp; extern struct hostent *_gethtbyaddr(), *_yp_gethtbyaddr(); char lookups[MAXDNSLUS]; - if (type != AF_INET) - return ((struct hostent *) NULL); - (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", - ((unsigned)addr[3] & 0xff), - ((unsigned)addr[2] & 0xff), - ((unsigned)addr[1] & 0xff), - ((unsigned)addr[0] & 0xff)); - if ((_res.options & RES_INIT) == 0 && res_init() == -1) - return (_gethtbyaddr(addr, len, type)); + return (_gethtbyaddr(addr, len, af)); + + if (af == AF_INET6 && len == IN6ADDRSZ && + (!bcmp(uaddr, mapped, sizeof mapped) || + !bcmp(uaddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + addr += sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + switch (af) { + case AF_INET: + size = INADDRSZ; + break; + case AF_INET6: + size = IN6ADDRSZ; + break; + default: + errno = EAFNOSUPPORT; + h_errno = NETDB_INTERNAL; + return (NULL); + } + if (size != len) { + errno = EINVAL; + h_errno = NETDB_INTERNAL; + return (NULL); + } + switch (af) { + case AF_INET: + (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", + (uaddr[3] & 0xff), + (uaddr[2] & 0xff), + (uaddr[1] & 0xff), + (uaddr[0] & 0xff)); + break; + case AF_INET6: + qp = qbuf; + for (n = IN6ADDRSZ - 1; n >= 0; n--) { + qp += sprintf(qp, "%x.%x.", + uaddr[n] & 0xf, + (uaddr[n] >> 4) & 0xf); + } + strcpy(qp, "ip6.int"); + break; + default: + abort(); + } bcopy(_res.lookups, lookups, sizeof lookups); if (lookups[0] == '\0') @@ -411,29 +652,38 @@ gethostbyaddr(addr, len, type) switch (lookups[i]) { #ifdef YP case 'y': - hp = _yp_gethtbyaddr(addr); + /* YP only supports AF_INET. */ + if (af == AF_INET) + hp = _yp_gethtbyaddr(addr); break; #endif case 'b': - n = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf)); + n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, + sizeof buf.buf); if (n < 0) { #ifdef DEBUG if (_res.options & RES_DEBUG) printf("res_query failed\n"); #endif - break; + return (NULL); } - hp = getanswer(&buf, n, 1); - if (hp == NULL) - break; - hp->h_addrtype = type; + if (!(hp = getanswer(&buf, n, qbuf, T_PTR))) + return (NULL); /* h_errno was set by getanswer() */ + hp->h_addrtype = af; hp->h_length = len; - h_addr_ptrs[0] = (char *)&host_addr; - h_addr_ptrs[1] = (char *)0; - host_addr = *(struct in_addr *)addr; + bcopy(addr, host_addr, len); + h_addr_ptrs[0] = (char *)host_addr; + h_addr_ptrs[1] = NULL; + if (af == AF_INET && (_res.options & RES_USE_INET6)) { + map_v4v6_address((char*)host_addr, + (char*)host_addr); + hp->h_addrtype = AF_INET6; + hp->h_length = IN6ADDRSZ; + } + h_errno = NETDB_SUCCESS; break; case 'f': - hp = _gethtbyaddr(addr, len, type); + hp = _gethtbyaddr(addr, len, af); break; } } @@ -465,35 +715,51 @@ _gethtent() { char *p; register char *cp, **q; + int af, len; - if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL) + if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) { + h_errno = NETDB_INTERNAL; return (NULL); -again: - if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) + } + again: + if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) { + h_errno = HOST_NOT_FOUND; return (NULL); + } if (*p == '#') goto again; - cp = strpbrk(p, "#\n"); - if (cp == NULL) + if (!(cp = strpbrk(p, "#\n"))) goto again; *cp = '\0'; - cp = strpbrk(p, " \t"); - if (cp == NULL) + if (!(cp = strpbrk(p, " \t"))) goto again; *cp++ = '\0'; - /* THIS STUFF IS INTERNET SPECIFIC */ - h_addr_ptrs[0] = (char *)&host_addr; + if ((_res.options & RES_USE_INET6) && + inet_pton(AF_INET6, p, host_addr) > 0) { + af = AF_INET6; + len = IN6ADDRSZ; + } else if (inet_pton(AF_INET, p, host_addr) > 0) { + if (_res.options & RES_USE_INET6) { + map_v4v6_address((char*)host_addr, (char*)host_addr); + af = AF_INET6; + len = IN6ADDRSZ; + } else { + af = AF_INET; + len = INADDRSZ; + } + } else { + goto again; + } + h_addr_ptrs[0] = (char *)host_addr; h_addr_ptrs[1] = NULL; - (void) inet_aton(p, &host_addr); host.h_addr_list = h_addr_ptrs; - host.h_length = sizeof(u_int32_t); - host.h_addrtype = AF_INET; + host.h_length = len; + host.h_addrtype = af; while (*cp == ' ' || *cp == '\t') cp++; host.h_name = cp; q = host.h_aliases = host_aliases; - cp = strpbrk(cp, " \t"); - if (cp != NULL) + if (cp = strpbrk(cp, " \t")) *cp++ = '\0'; while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { @@ -502,70 +768,73 @@ again: } if (q < &host_aliases[MAXALIASES - 1]) *q++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) + if (cp = strpbrk(cp, " \t")) *cp++ = '\0'; } *q = NULL; + if (_res.options & RES_USE_INET6) { + char *bp = hostbuf; + int buflen = sizeof hostbuf; + + map_v4v6_hostent(&host, &bp, &buflen); + } + h_errno = NETDB_SUCCESS; return (&host); } struct hostent * _gethtbyname(name) const char *name; +{ + extern struct hostent *_gethtbyname2(); + struct hostent *hp; + + if (_res.options & RES_USE_INET6) { + hp = _gethtbyname2(name, AF_INET6); + if (hp) + return (hp); + } + return (_gethtbyname2(name, AF_INET)); +} + +struct hostent * +_gethtbyname2(name, af) + const char *name; + int af; { register struct hostent *p; register char **cp; _sethtent(0); while (p = _gethtent()) { + if (p->h_addrtype != af) + continue; if (strcasecmp(p->h_name, name) == 0) break; for (cp = p->h_aliases; *cp != 0; cp++) if (strcasecmp(*cp, name) == 0) goto found; } -found: + found: _endhtent(); - if (p==NULL) - h_errno = HOST_NOT_FOUND; return (p); } struct hostent * -_gethtbyaddr(addr, len, type) +_gethtbyaddr(addr, len, af) const char *addr; - int len, type; + int len, af; { register struct hostent *p; _sethtent(0); while (p = _gethtent()) - if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) + if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len)) break; _endhtent(); - if (p==NULL) - h_errno = HOST_NOT_FOUND; return (p); } -static int -qcomp(a1, a2) - struct in_addr **a1, **a2; -{ - int pos1, pos2; - - for (pos1 = 0; pos1 < _res.nsort; pos1++) - if (_res.sort_list[pos1].addr.s_addr == - ((*a1)->s_addr & _res.sort_list[pos1].mask)) - break; - for (pos2 = 0; pos2 < _res.nsort; pos2++) - if (_res.sort_list[pos2].addr.s_addr == - ((*a2)->s_addr & _res.sort_list[pos2].mask)) - break; - return pos1 - pos2; -} - #ifdef YP struct hostent * _yphostent(line) @@ -687,10 +956,104 @@ _yp_gethtbyname(name) __ypcurrent = NULL; r = yp_match(__ypdomain, "hosts.byname", name, strlen(name), &__ypcurrent, &__ypcurrentlen); - if (r==0) + if (r == 0) hp = _yphostent(__ypcurrent); - if (hp==NULL) + if (hp == NULL) h_errno = HOST_NOT_FOUND; return (hp); } #endif + +static void +map_v4v6_address(src, dst) + const char *src; + char *dst; +{ + u_char *p = (u_char *)dst; + char tmp[INADDRSZ]; + int i; + + /* Stash a temporary copy so our caller can update in place. */ + bcopy(src, tmp, INADDRSZ); + /* Mark this ipv6 addr as a mapped ipv4. */ + for (i = 0; i < 10; i++) + *p++ = 0x00; + *p++ = 0xff; + *p++ = 0xff; + /* Retrieve the saved copy and we're done. */ + bcopy(tmp, (void*)p, INADDRSZ); +} + +static void +map_v4v6_hostent(hp, bpp, lenp) + struct hostent *hp; + char **bpp; + int *lenp; +{ + char **ap; + + if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) + return; + hp->h_addrtype = AF_INET6; + hp->h_length = IN6ADDRSZ; + for (ap = hp->h_addr_list; *ap; ap++) { + int i = sizeof(align) - ((u_long)*bpp % sizeof(align)); + + if (*lenp < (i + IN6ADDRSZ)) { + /* Out of memory. Truncate address list here. XXX */ + *ap = NULL; + return; + } + *bpp += i; + *lenp -= i; + map_v4v6_address(*ap, *bpp); + *ap = *bpp; + *bpp += IN6ADDRSZ; + *lenp -= IN6ADDRSZ; + } +} + +#ifdef RESOLVSORT +static void +addrsort(ap, num) + char **ap; + int num; +{ + int i, j; + char **p; + short aval[MAXADDRS]; + int needsort = 0; + + p = ap; + for (i = 0; i < num; i++, p++) { + for (j = 0 ; (unsigned)j < _res.nsort; j++) + if (_res.sort_list[j].addr.s_addr == + (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask)) + break; + aval[i] = j; + if (needsort == 0 && i > 0 && j < aval[i-1]) + needsort = i; + } + if (!needsort) + return; + + while (needsort < num) { + for (j = needsort - 1; j >= 0; j--) { + if (aval[j] > aval[j+1]) { + char *hp; + + i = aval[j]; + aval[j] = aval[j+1]; + aval[j+1] = i; + + hp = ap[j]; + ap[j] = ap[j+1]; + ap[j+1] = hp; + + } else + break; + } + needsort++; + } +} +#endif 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 @@ -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 @@ -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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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 +#include #include #include #include #include -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 #include #include #include @@ -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 +#include +#include +#include + +#include +#include +#include +#include + +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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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 +#include +#include +#include + +#include +#include + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +/* + * 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 #include #include #include @@ -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 #include -#include #include -#include +#include + #include +#include #include + #include #include -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