From 8053080cbc1ee98871dd7549fef2a6d80f99a00a Mon Sep 17 00:00:00 2001 From: Yoshinobu Inoue Date: Thu, 3 Feb 2000 10:27:03 +0000 Subject: [PATCH] Missing tcp_wrapper IPv6 support seemed to be a bug, so commit it. Now when tcp_wrapper is enabled by inetd -wW, several accesses which should be permitted are refused only for IPv6, if hostname is used to decide the host to be allowed. IPv6 users will be just upset. About security related concern. -All extensions are wrapped by #ifdef INET6, so people can completely disable the extension by recompile libwrap without INET6 option. -Access via IPv6 is not enabled by default. People need to enable IPv6 access by changing /etc/inetd.conf at first, by adding tcp6 and/or tcp46 entries. -The base of patches are from KAME package and are actually daily used for more than a year in several Japanese IPv6 environments. -Patches are reviewed by markm. Approved by: jkh Submitted by: Hajimu UMEMOTO Reviewed by: markm Obtained from: KAME project --- contrib/tcp_wrappers/Makefile | 41 ++++++-- contrib/tcp_wrappers/fix_options.c | 21 ++++ contrib/tcp_wrappers/hosts_access.5 | 7 ++ contrib/tcp_wrappers/hosts_access.c | 105 +++++++++++++++++++ contrib/tcp_wrappers/misc.c | 24 +++++ contrib/tcp_wrappers/refuse.c | 7 ++ contrib/tcp_wrappers/rfc931.c | 66 ++++++++++++ contrib/tcp_wrappers/scaffold.c | 155 ++++++++++++++++++++++++++++ contrib/tcp_wrappers/socket.c | 149 ++++++++++++++++++++++++++ contrib/tcp_wrappers/tcpd.c | 7 ++ contrib/tcp_wrappers/tcpd.h | 6 ++ contrib/tcp_wrappers/tcpdchk.c | 36 +++++++ contrib/tcp_wrappers/tcpdmatch.c | 55 ++++++++++ contrib/tcp_wrappers/tli.c | 37 ++++++- contrib/tcp_wrappers/update.c | 10 ++ contrib/tcp_wrappers/workarounds.c | 13 +++ lib/libwrap/Makefile | 1 + usr.sbin/tcpdchk/Makefile | 1 + 18 files changed, 729 insertions(+), 12 deletions(-) diff --git a/contrib/tcp_wrappers/Makefile b/contrib/tcp_wrappers/Makefile index 2906c52ddf37..10ede819e4de 100644 --- a/contrib/tcp_wrappers/Makefile +++ b/contrib/tcp_wrappers/Makefile @@ -1,4 +1,5 @@ # @(#) Makefile 1.23 97/03/21 19:27:20 +# $FreeBSD$ what: @echo @@ -21,7 +22,7 @@ what: @echo " dynix epix esix freebsd hpux irix4 irix5 irix6 isc iunix" @echo " linux machten mips(untested) ncrsvr4 netbsd next osf power_unix_211" @echo " ptx-2.x ptx-generic pyramid sco sco-nis sco-od2 sco-os5 sinix sunos4" - @echo " sunos40 sunos5 sysv4 tandem ultrix unicos7 unicos8 unixware1 unixware2" + @echo " sunos40 sunos5 solaris8 sysv4 tandem ultrix unicos7 unicos8 unixware1 unixware2" @echo " uts215 uxp" @echo @echo "If none of these match your environment, edit the system" @@ -131,20 +132,34 @@ epix: NETGROUP=-DNETGROUP TLI= SYSTYPE="-systype bsd43" all # Freebsd and linux by default have no NIS. -386bsd netbsd bsdos: +386bsd bsdos: @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \ EXTRA_CFLAGS=-DSYS_ERRLIST_DEFINED VSYSLOG= all freebsd: + @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ + RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP=-DNETGROUP TLI= \ + EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DINET6 -DUSE_GETIPNODEBY" \ + VSYSLOG= all + +netbsd: @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \ - EXTRA_CFLAGS=-DSYS_ERRLIST_DEFINED VSYSLOG= all + EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DINET6 \ + -Dss_family=__ss_family -Dss_len=__ss_len" VSYSLOG= all linux: @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ - LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ=setenv.o \ - NETGROUP= TLI= EXTRA_CFLAGS="-DBROKEN_SO_LINGER" all + LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ=setenv.o NETGROUP= TLI= \ + EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DBROKEN_SO_LINGER -DINET6=1 \ + -Dss_family=__ss_family -Dss_len=__ss_len" all + +linux-old: + @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ + LIBS="/usr/inet6/lib/libinet6.a -lresolv" \ + RANLIB=ranlib ARFLAGS=rv AUX_OBJ=setenv.o NETGROUP= TLI= \ + EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DBROKEN_SO_LINGER -DINET6=1 -Dss_family=sin6_family -Dsockaddr_storage=sockaddr_in6 -I/usr/inet6/include" all # This is good for many SYSV+BSD hybrids with NIS, probably also for HP-UX 7.x. hpux hpux8 hpux9 hpux10: @@ -196,6 +211,14 @@ sunos5: NETGROUP=-DNETGROUP AUX_OBJ=setenv.o TLI=-DTLI \ BUGS="$(BUGS) -DSOLARIS_24_GETHOSTBYNAME_BUG" all +# SunOS 5.8 is another SYSV4 variant, but has IPv6 support +solaris8: + @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ + LIBS="-lsocket -lnsl" RANLIB=echo ARFLAGS=rv VSYSLOG= \ + NETGROUP=-DNETGROUP AUX_OBJ=setenv.o TLI=-DTLI \ + EXTRA_CFLAGS="-DINET6 -DUSE_GETIPNODEBY -DNO_CLONE_DEVICE \ + -DINT32_T" all + # Generic SYSV40 esix sysv4: @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ @@ -229,7 +252,7 @@ tandem: # Amdahl UTS 2.1.5 (Richard.Richmond@bridge.bst.bls.com) uts215: - @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ + @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ LIBS="-lsocket" RANLIB=echo \ ARFLAGS=rv AUX_OBJ=setenv.o NETGROUP=-DNO_NETGROUP TLI= all @@ -391,7 +414,7 @@ AR = ar # the ones provided with this source distribution. The environ.c module # implements setenv(), getenv(), and putenv(). -AUX_OBJ= setenv.o +#AUX_OBJ= setenv.o #AUX_OBJ= environ.o #AUX_OBJ= environ.o strcasecmp.o @@ -454,7 +477,7 @@ AUX_OBJ= setenv.o # host name aliases. Compile with -DSOLARIS_24_GETHOSTBYNAME_BUG to work # around this. The workaround does no harm on other Solaris versions. -BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DLIBC_CALLS_STRTOK +#BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DLIBC_CALLS_STRTOK #BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DINET_ADDR_BUG #BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DSOLARIS_24_GETHOSTBYNAME_BUG @@ -472,7 +495,7 @@ BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DLIBC_CALLS_STRTOK # If your system supports vsyslog(), comment out the following definition. # If in doubt leave it in, it won't harm. -VSYSLOG = -Dvsyslog=myvsyslog +#VSYSLOG = -Dvsyslog=myvsyslog # End of the system dependencies. ################################# diff --git a/contrib/tcp_wrappers/fix_options.c b/contrib/tcp_wrappers/fix_options.c index b5e81b89bccb..4983a55a47a1 100644 --- a/contrib/tcp_wrappers/fix_options.c +++ b/contrib/tcp_wrappers/fix_options.c @@ -3,6 +3,8 @@ * rlogind and kernel source, but all mistakes in it are my fault. * * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + * + * $FreeBSD$ */ #ifndef lint @@ -11,6 +13,9 @@ static char sccsid[] = "@(#) fix_options.c 1.6 97/04/08 02:29:19"; #include #include +#ifdef INET6 +#include +#endif #include #include #include @@ -41,6 +46,22 @@ struct request_info *request; unsigned int opt; int optlen; struct in_addr dummy; +#ifdef INET6 + struct sockaddr_storage ss; + int sslen; + + /* + * check if this is AF_INET socket + * XXX IPv6 support? + */ + sslen = sizeof(ss); + if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) { + syslog(LOG_ERR, "getpeername: %m"); + clean_exit(request); + } + if (ss.ss_family != AF_INET) + return; +#endif if ((ip = getprotobyname("ip")) != 0) ipproto = ip->p_proto; diff --git a/contrib/tcp_wrappers/hosts_access.5 b/contrib/tcp_wrappers/hosts_access.5 index 49a6bf71d314..27ab2ae648b6 100644 --- a/contrib/tcp_wrappers/hosts_access.5 +++ b/contrib/tcp_wrappers/hosts_access.5 @@ -90,6 +90,13 @@ bitwise AND of the address and the `mask\'. For example, the net/mask pattern `131.155.72.0/255.255.254.0\' matches every address in the range `131.155.72.0\' through `131.155.73.255\'. .IP \(bu +An expression of the form `[n:n:n:n:n:n:n:n]/m\' is interpreted as a +`[net]/prefixlen\' pair. A IPv6 host address is matched if +`prefixlen\' bits of `net\' is equal to the `prefixlen\' bits of the +address. For example, the [net]/prefixlen pattern +`[3ffe:505:2:1::]/64\' matches every address in the range +`3ffe:505:2:1::\' through `3ffe:505:2:1:ffff:ffff:ffff:ffff\'. +.IP \(bu A string that begins with a `/\' character is treated as a file name. A host name or address is matched if it matches any host name or address pattern listed in the named file. The file format is diff --git a/contrib/tcp_wrappers/hosts_access.c b/contrib/tcp_wrappers/hosts_access.c index 27dd81db4565..2b4dcee9ef9a 100644 --- a/contrib/tcp_wrappers/hosts_access.c +++ b/contrib/tcp_wrappers/hosts_access.c @@ -26,7 +26,13 @@ static char sccsid[] = "@(#) hosts_access.c 1.21 97/02/12 02:13:22"; /* System libraries. */ #include +#ifdef INT32_T + typedef uint32_t u_int32_t; +#endif #include +#ifdef INET6 +#include +#endif #include #include #include @@ -84,6 +90,10 @@ static int client_match(); static int host_match(); static int string_match(); static int masked_match(); +#ifdef INET6 +static int masked_match4(); +static int masked_match6(); +#endif /* Size of logical line buffer. */ @@ -313,6 +323,13 @@ char *string; { int n; +#ifdef INET6 + /* convert IPv4 mapped IPv6 address to IPv4 address */ + if (STRN_EQ(string, "::ffff:", 7) + && dot_quad_addr(string + 7) != INADDR_NONE) { + string += 7; + } +#endif if (tok[0] == '.') { /* suffix */ n = strlen(string) - strlen(tok); return (n > 0 && STR_EQ(tok, string + n)); @@ -323,20 +340,55 @@ char *string; } else if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */ return (STRN_EQ(tok, string, n)); } else { /* exact match */ +#ifdef INET6 + struct in6_addr pat, addr; + int len, ret; + char ch; + + len = strlen(tok); + if (*tok == '[' && tok[len - 1] == ']') { + ch = tok[len - 1]; + tok[len - 1] = '\0'; + ret = inet_pton(AF_INET6, tok + 1, pat.s6_addr); + tok[len - 1] = ch; + if (ret != 1 || inet_pton(AF_INET6, string, addr.s6_addr) != 1) + return NO; + return (!memcmp(&pat, &addr, sizeof(struct in6_addr))); + } +#endif return (STR_EQ(tok, string)); } } /* masked_match - match address against netnumber/netmask */ +#ifdef INET6 static int masked_match(net_tok, mask_tok, string) char *net_tok; char *mask_tok; char *string; { + return (masked_match4(net_tok, mask_tok, string) || + masked_match6(net_tok, mask_tok, string)); +} + +static int masked_match4(net_tok, mask_tok, string) +#else +static int masked_match(net_tok, mask_tok, string) +#endif +char *net_tok; +char *mask_tok; +char *string; +{ +#ifdef INET6 + u_int32_t net; + u_int32_t mask; + u_int32_t addr; +#else unsigned long net; unsigned long mask; unsigned long addr; +#endif /* * Disallow forms other than dotted quad: the treatment that inet_addr() @@ -348,8 +400,61 @@ char *string; return (NO); if ((net = dot_quad_addr(net_tok)) == INADDR_NONE || (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) { +#ifndef INET6 tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok); +#endif return (NO); /* not tcpd_jump() */ } return ((addr & mask) == net); } + +#ifdef INET6 +static int masked_match6(net_tok, mask_tok, string) +char *net_tok; +char *mask_tok; +char *string; +{ + struct in6_addr net, addr; + u_int32_t mask; + int len, mask_len, i = 0; + char ch; + + if (inet_pton(AF_INET6, string, addr.s6_addr) != 1) + return NO; + + if (IN6_IS_ADDR_V4MAPPED(&addr)) { + if ((*(u_int32_t *)&net.s6_addr[12] = dot_quad_addr(net_tok)) == INADDR_NONE + || (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) + return (NO); + return ((*(u_int32_t *)&addr.s6_addr[12] & mask) == *(u_int32_t *)&net.s6_addr[12]); + } + + /* match IPv6 address against netnumber/prefixlen */ + len = strlen(net_tok); + if (*net_tok != '[' || net_tok[len - 1] != ']') + return NO; + ch = net_tok[len - 1]; + net_tok[len - 1] = '\0'; + if (inet_pton(AF_INET6, net_tok + 1, net.s6_addr) != 1) { + net_tok[len - 1] = ch; + return NO; + } + net_tok[len - 1] = ch; + if ((mask_len = atoi(mask_tok)) < 0 || mask_len > 128) + return NO; + + while (mask_len > 0) { + if (mask_len < 32) { + mask = htonl(~(0xffffffff >> mask_len)); + if ((*(u_int32_t *)&addr.s6_addr[i] & mask) != (*(u_int32_t *)&net.s6_addr[i] & mask)) + return NO; + break; + } + if (*(u_int32_t *)&addr.s6_addr[i] != *(u_int32_t *)&net.s6_addr[i]) + return NO; + i += 4; + mask_len -= 32; + } + return YES; +} +#endif /* INET6 */ diff --git a/contrib/tcp_wrappers/misc.c b/contrib/tcp_wrappers/misc.c index 87a765379f43..8f04f870e1b4 100644 --- a/contrib/tcp_wrappers/misc.c +++ b/contrib/tcp_wrappers/misc.c @@ -2,6 +2,8 @@ * Misc routines that are used by tcpd and by tcpdchk. * * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + * + * $FreeBSD$ */ #ifndef lint @@ -58,9 +60,31 @@ int delimiter; { char *cp; +#ifdef INET6 + int bracket = 0; + + for (cp = string; cp && *cp; cp++) { + switch (*cp) { + case '[': + bracket++; + break; + case ']': + bracket--; + break; + default: + if (bracket == 0 && *cp == delimiter) { + *cp++ = 0; + return cp; + } + break; + } + } + return (NULL); +#else if ((cp = strchr(string, delimiter)) != 0) *cp++ = 0; return (cp); +#endif } /* dot_quad_addr - convert dotted quad to internal form */ diff --git a/contrib/tcp_wrappers/refuse.c b/contrib/tcp_wrappers/refuse.c index ccf80300529e..fd04e08ae9bf 100644 --- a/contrib/tcp_wrappers/refuse.c +++ b/contrib/tcp_wrappers/refuse.c @@ -5,6 +5,8 @@ * the program is terminated. * * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + * + * $FreeBSD$ */ #ifndef lint @@ -25,7 +27,12 @@ static char sccsid[] = "@(#) refuse.c 1.5 94/12/28 17:42:39"; void refuse(request) struct request_info *request; { +#ifdef INET6 + syslog(deny_severity, "refused connect from %s (%s)", + eval_client(request), eval_hostaddr(request->client)); +#else syslog(deny_severity, "refused connect from %s", eval_client(request)); +#endif clean_exit(request); /* NOTREACHED */ } diff --git a/contrib/tcp_wrappers/rfc931.c b/contrib/tcp_wrappers/rfc931.c index 8176417b8fd6..c666f58f29ca 100644 --- a/contrib/tcp_wrappers/rfc931.c +++ b/contrib/tcp_wrappers/rfc931.c @@ -7,6 +7,8 @@ * Diagnostics are reported through syslog(3). * * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + * + * $FreeBSD$ */ #ifndef lint @@ -68,20 +70,50 @@ int sig; /* rfc931 - return remote user name, given socket structures */ void rfc931(rmt_sin, our_sin, dest) +#ifdef INET6 +struct sockaddr *rmt_sin; +struct sockaddr *our_sin; +#else struct sockaddr_in *rmt_sin; struct sockaddr_in *our_sin; +#endif char *dest; { unsigned rmt_port; unsigned our_port; +#ifdef INET6 + struct sockaddr_storage rmt_query_sin; + struct sockaddr_storage our_query_sin; + int alen; +#else struct sockaddr_in rmt_query_sin; struct sockaddr_in our_query_sin; +#endif char user[256]; /* XXX */ char buffer[512]; /* XXX */ char *cp; char *result = unknown; FILE *fp; +#ifdef INET6 + /* address family must be the same */ + if (rmt_sin->sa_family != our_sin->sa_family) { + STRN_CPY(dest, result, STRING_LENGTH); + return; + } + switch (our_sin->sa_family) { + case AF_INET: + alen = sizeof(struct sockaddr_in); + break; + case AF_INET6: + alen = sizeof(struct sockaddr_in6); + break; + default: + STRN_CPY(dest, result, STRING_LENGTH); + return; + } +#endif + /* * Use one unbuffered stdio stream for writing to and for reading from * the RFC931 etc. server. This is done because of a bug in the SunOS @@ -92,7 +124,11 @@ char *dest; * sockets. */ +#ifdef INET6 + if ((fp = fsocket(our_sin->sa_family, SOCK_STREAM, 0)) != 0) { +#else if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) { +#endif setbuf(fp, (char *) 0); /* @@ -112,6 +148,25 @@ char *dest; * addresses from the query socket. */ +#ifdef INET6 + memcpy(&our_query_sin, our_sin, alen); + memcpy(&rmt_query_sin, rmt_sin, alen); + switch (our_sin->sa_family) { + case AF_INET: + ((struct sockaddr_in *)&our_query_sin)->sin_port = htons(ANY_PORT); + ((struct sockaddr_in *)&rmt_query_sin)->sin_port = htons(RFC931_PORT); + break; + case AF_INET6: + ((struct sockaddr_in6 *)&our_query_sin)->sin6_port = htons(ANY_PORT); + ((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port = htons(RFC931_PORT); + break; + } + + if (bind(fileno(fp), (struct sockaddr *) & our_query_sin, + alen) >= 0 && + connect(fileno(fp), (struct sockaddr *) & rmt_query_sin, + alen) >= 0) { +#else our_query_sin = *our_sin; our_query_sin.sin_port = htons(ANY_PORT); rmt_query_sin = *rmt_sin; @@ -121,6 +176,7 @@ char *dest; sizeof(our_query_sin)) >= 0 && connect(fileno(fp), (struct sockaddr *) & rmt_query_sin, sizeof(rmt_query_sin)) >= 0) { +#endif /* * Send query to server. Neglect the risk that a 13-byte @@ -129,8 +185,13 @@ char *dest; */ fprintf(fp, "%u,%u\r\n", +#ifdef INET6 + ntohs(((struct sockaddr_in *)rmt_sin)->sin_port), + ntohs(((struct sockaddr_in *)our_sin)->sin_port)); +#else ntohs(rmt_sin->sin_port), ntohs(our_sin->sin_port)); +#endif fflush(fp); /* @@ -144,8 +205,13 @@ char *dest; && ferror(fp) == 0 && feof(fp) == 0 && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s", &rmt_port, &our_port, user) == 3 +#ifdef INET6 + && ntohs(((struct sockaddr_in *)rmt_sin)->sin_port) == rmt_port + && ntohs(((struct sockaddr_in *)our_sin)->sin_port) == our_port) { +#else && ntohs(rmt_sin->sin_port) == rmt_port && ntohs(our_sin->sin_port) == our_port) { +#endif /* * Strip trailing carriage return. It is part of the diff --git a/contrib/tcp_wrappers/scaffold.c b/contrib/tcp_wrappers/scaffold.c index afce15a64e4d..ea87c5c65419 100644 --- a/contrib/tcp_wrappers/scaffold.c +++ b/contrib/tcp_wrappers/scaffold.c @@ -2,6 +2,8 @@ * Routines for testing only. Not really industrial strength. * * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + * + * $FreeBSD$ */ #ifndef lint @@ -20,6 +22,7 @@ static char sccs_id[] = "@(#) scaffold.c 1.6 97/03/21 19:27:24"; #include #include #include +#include #ifndef INADDR_NONE #define INADDR_NONE (-1) /* XXX should be 0xffffffff */ @@ -57,6 +60,9 @@ struct hostent *hp; /* void */ ; if ((hb = (struct hostent_block *) malloc(sizeof(struct hostent_block) +#ifdef INET6 + + strlen(hp->h_name) + 1 +#endif + (hp->h_length + sizeof(char *)) * count)) == 0) { fprintf(stderr, "Sorry, out of memory\n"); exit(1); @@ -66,6 +72,11 @@ struct hostent *hp; hb->host.h_addr_list = hb->addr_list; hb->host.h_addr_list[count] = 0; data = (char *) (hb->host.h_addr_list + count + 1); +#ifdef INET6 + hb->host.h_name = data + hp->h_length * count; + strcpy(hb->host.h_name, hp->h_name); + hb->host.h_addrtype = hp->h_addrtype; +#endif for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) { hb->host.h_addr_list[count] = data + hp->h_length * count; @@ -74,6 +85,104 @@ struct hostent *hp; return (&hb->host); } +#if defined(INET6) && !defined(USE_GETIPNODEBY) +/* merge_hostent - merge hostent in one memory block */ + +static struct hostent *merge_hostent(hp1, hp2) +struct hostent *hp1, *hp2; +{ + struct hostent_block { + struct hostent host; + char *addr_list[1]; + }; + struct hostent_block *hb; + int count, count2; + char *data; + char *addr; + + for (count = 0; hp1->h_addr_list[count] != 0; count++) + /* void */ ; + for (count2 = 0; hp2->h_addr_list[count2] != 0; count2++) + /* void */ ; + count += count2; + + if ((hb = (struct hostent_block *) malloc(sizeof(struct hostent_block) + + strlen(hp1->h_name) + 1 + + (hp1->h_length + sizeof(char *)) * count)) == 0) { + fprintf(stderr, "Sorry, out of memory\n"); + exit(1); + } + memset((char *) &hb->host, 0, sizeof(hb->host)); + hb->host.h_length = hp1->h_length; + hb->host.h_addr_list = hb->addr_list; + hb->host.h_addr_list[count] = 0; + data = (char *) (hb->host.h_addr_list + count + 1); + hb->host.h_name = data + hp1->h_length * count; + strcpy(hb->host.h_name, hp1->h_name); + hb->host.h_addrtype = hp1->h_addrtype; + + for (count = 0; (addr = hp1->h_addr_list[count]) != 0; count++) { + hb->host.h_addr_list[count] = data + hp1->h_length * count; + memcpy(hb->host.h_addr_list[count], addr, hp1->h_length); + } + for (count2 = 0; (addr = hp2->h_addr_list[count2]) != 0; count2++) { + hb->host.h_addr_list[count] = data + hp1->h_length * count; + memcpy(hb->host.h_addr_list[count], addr, hp1->h_length); + ++count; + } + return (&hb->host); +} +#endif + +static struct hostent *gethostbyname64(host) +char *host; +{ + struct hostent *hp = NULL, *hp2 = NULL; +#ifdef USE_GETIPNODEBY + int h_error; + + if ((hp = getipnodebyname(host, AF_INET6, + AI_V4MAPPED | AI_ADDRCONFIG | AI_ALL, + &h_error)) != 0) { + hp2 = dup_hostent(hp); + freehostent(hp); + return (hp2); + } +#else + struct hostent *hp1; + u_long res_options; + + if ((_res.options & RES_INIT) == 0) { + if (res_init() < 0) { + tcpd_warn("%s: res_init() failed", host); + return (NULL); + } + } + res_options = _res.options; +#ifdef INET6 + _res.options |= RES_USE_INET6; + if ((hp1 = gethostbyname2(host, AF_INET6)) != NULL) + hp1 = dup_hostent(hp1); +#endif + if ((hp2 = gethostbyname2(host, AF_INET)) != NULL) + hp2 = dup_hostent(hp2); + _res.options = res_options; +#ifdef INET6 + if (hp1 && hp2) { + hp = merge_hostent(hp1, hp2); + free((char *) hp1); + free((char *) hp2); + return (hp); + } + if (hp1) + return (hp1); +#endif + if (hp2) + return (hp2); +#endif + return (NULL); +} + /* find_inet_addr - find all addresses for this host, result to free() */ struct hostent *find_inet_addr(host) @@ -83,6 +192,7 @@ char *host; struct hostent *hp; static struct hostent h; static char *addr_list[2]; + static char hnamebuf[BUFSIZ]; /* * Host address: translate it to internal form. @@ -91,6 +201,11 @@ char *host; h.h_addr_list = addr_list; h.h_addr_list[0] = (char *) &addr; h.h_length = sizeof(addr); +#ifdef INET6 + h.h_addrtype = AF_INET; + h.h_name = hnamebuf; + strcpy(h.h_name, host); +#endif return (dup_hostent(&h)); } @@ -104,19 +219,33 @@ char *host; tcpd_warn("%s: not an internet address", host); return (0); } +#ifdef INET6 + if ((hp = gethostbyname64(host)) == 0) { +#else if ((hp = gethostbyname(host)) == 0) { +#endif tcpd_warn("%s: host not found", host); return (0); } +#ifdef INET6 + if (hp->h_addrtype != AF_INET6) { + tcpd_warn("%d: not an internet host", hp->h_addrtype); + free((char *) hp); +#else if (hp->h_addrtype != AF_INET) { tcpd_warn("%d: not an internet host", hp->h_addrtype); +#endif return (0); } if (STR_NE(host, hp->h_name)) { tcpd_warn("%s: hostname alias", host); tcpd_warn("(official name: %.*s)", STRING_LENGTH, hp->h_name); } +#ifdef INET6 + return (hp); +#else return (dup_hostent(hp)); +#endif } /* check_dns - give each address thorough workout, return address count */ @@ -125,7 +254,13 @@ int check_dns(host) char *host; { struct request_info request; +#ifdef INET6 + struct sockaddr_storage sin; + char *ap; + int alen; +#else struct sockaddr_in sin; +#endif struct hostent *hp; int count; char *addr; @@ -135,10 +270,30 @@ char *host; request_init(&request, RQ_CLIENT_SIN, &sin, 0); sock_methods(&request); memset((char *) &sin, 0, sizeof(sin)); +#ifdef INET6 + sin.ss_family = hp->h_addrtype; + switch (hp->h_addrtype) { + case AF_INET: + ap = (char *)&((struct sockaddr_in *)&sin)->sin_addr; + alen = sizeof(struct sockaddr_in); + break; + case AF_INET6: + ap = (char *)&((struct sockaddr_in6 *)&sin)->sin6_addr; + alen = sizeof(struct sockaddr_in6); + break; + default: + return (0); + } +#else sin.sin_family = AF_INET; +#endif for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) { +#ifdef INET6 + memcpy(ap, addr, alen); +#else memcpy((char *) &sin.sin_addr, addr, sizeof(sin.sin_addr)); +#endif /* * Force host name and address conversions. Use the request structure diff --git a/contrib/tcp_wrappers/socket.c b/contrib/tcp_wrappers/socket.c index c659b166698f..d2370e0e967b 100644 --- a/contrib/tcp_wrappers/socket.c +++ b/contrib/tcp_wrappers/socket.c @@ -13,6 +13,8 @@ * Diagnostics are reported through syslog(3). * * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + * + * $FreeBSD$ */ #ifndef lint @@ -30,6 +32,12 @@ static char sccsid[] = "@(#) socket.c 1.15 97/03/21 19:27:24"; #include #include +#ifdef INET6 +#ifndef USE_GETIPNODEBY +#include +#endif +#endif + extern char *inet_ntoa(); /* Local stuff. */ @@ -74,8 +82,13 @@ char *name; void sock_host(request) struct request_info *request; { +#ifdef INET6 + static struct sockaddr_storage client; + static struct sockaddr_storage server; +#else static struct sockaddr_in client; static struct sockaddr_in server; +#endif int len; char buf[BUFSIZ]; int fd = request->fd; @@ -104,7 +117,11 @@ struct request_info *request; memset(buf, 0 sizeof(buf)); #endif } +#ifdef INET6 + request->client->sin = (struct sockaddr *)&client; +#else request->client->sin = &client; +#endif /* * Determine the server binding. This is used for client username @@ -117,7 +134,11 @@ struct request_info *request; tcpd_warn("getsockname: %m"); return; } +#ifdef INET6 + request->server->sin = (struct sockaddr *)&server; +#else request->server->sin = &server; +#endif } /* sock_hostaddr - map endpoint address to printable form */ @@ -125,10 +146,33 @@ struct request_info *request; void sock_hostaddr(host) struct host_info *host; { +#ifdef INET6 + struct sockaddr *sin = host->sin; + char *ap; + int alen; + + if (!sin) + return; + switch (sin->sa_family) { + case AF_INET: + ap = (char *)&((struct sockaddr_in *)sin)->sin_addr; + alen = sizeof(struct in_addr); + break; + case AF_INET6: + ap = (char *)&((struct sockaddr_in6 *)sin)->sin6_addr; + alen = sizeof(struct in6_addr); + break; + default: + return; + } + host->addr[0] = '\0'; + inet_ntop(sin->sa_family, ap, host->addr, sizeof(host->addr)); +#else struct sockaddr_in *sin = host->sin; if (sin != 0) STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr)); +#endif } /* sock_hostname - map endpoint address to host name */ @@ -136,8 +180,21 @@ struct host_info *host; void sock_hostname(host) struct host_info *host; { +#ifdef INET6 + struct sockaddr *sin = host->sin; + char addr[128]; +#ifdef USE_GETIPNODEBY + int h_error; +#else + u_long res_options; +#endif + struct hostent *hp = NULL; + char *ap; + int alen; +#else struct sockaddr_in *sin = host->sin; struct hostent *hp; +#endif int i; /* @@ -147,11 +204,42 @@ struct host_info *host; * have to special-case 0.0.0.0, in order to avoid false alerts from the * host name/address checking code below. */ +#ifdef INET6 + if (sin != NULL) { + switch (sin->sa_family) { + case AF_INET: + if (((struct sockaddr_in *)sin)->sin_addr.s_addr == 0) { + strcpy(host->name, paranoid); /* name is bad, clobber it */ + return; + } + ap = (char *) &((struct sockaddr_in *)sin)->sin_addr; + alen = sizeof(struct in_addr); + break; + case AF_INET6: + ap = (char *) &((struct sockaddr_in6 *)sin)->sin6_addr; + alen = sizeof(struct in6_addr); + break; + defalut: + strcpy(host->name, paranoid); /* name is bad, clobber it */ + return; + } +#ifdef USE_GETIPNODEBY + hp = getipnodebyaddr(ap, alen, sin->sa_family, &h_error); +#else + hp = gethostbyaddr(ap, alen, sin->sa_family); +#endif + } + if (hp) { +#else if (sin != 0 && sin->sin_addr.s_addr != 0 && (hp = gethostbyaddr((char *) &(sin->sin_addr), sizeof(sin->sin_addr), AF_INET)) != 0) { +#endif STRN_CPY(host->name, hp->h_name, sizeof(host->name)); +#if defined(INET6) && defined(USE_GETIPNODEBY) + freehostent(hp); +#endif /* * Verify that the address is a member of the address list returned @@ -166,15 +254,53 @@ struct host_info *host; * we're in big trouble anyway. */ +#ifdef INET6 +#ifdef USE_GETIPNODEBY + hp = getipnodebyname(host->name, sin->sa_family, + AI_V4MAPPED | AI_ADDRCONFIG | AI_ALL, &h_error); +#else + if ((_res.options & RES_INIT) == 0) { + if (res_init() < 0) { + inet_ntop(sin->sa_family, ap, addr, sizeof(addr)); + tcpd_warn("can't verify hostname: res_init() for %s failed", + addr); + strcpy(host->name, paranoid); /* name is bad, clobber it */ + return; + } + } + res_options = _res.options; + if (sin->sa_family == AF_INET6) + _res.options |= RES_USE_INET6; + else + _res.options &= ~RES_USE_INET6; + hp = gethostbyname2(host->name, + (sin->sa_family == AF_INET6 && + IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sin)->sin6_addr)) ? + AF_INET : sin->sa_family); + _res.options = res_options; +#endif + if (!hp) { +#else if ((hp = gethostbyname(host->name)) == 0) { +#endif /* * Unable to verify that the host name matches the address. This * may be a transient problem or a botched name server setup. */ +#ifdef INET6 +#ifdef USE_GETIPNODEBY + tcpd_warn("can't verify hostname: getipnodebyname(%s, %s) failed", +#else + tcpd_warn("can't verify hostname: gethostbyname2(%s, %s) failed", +#endif + host->name, + (sin->sa_family == AF_INET) ? "AF_INET" : "AF_INET6"); +#else tcpd_warn("can't verify hostname: gethostbyname(%s) failed", host->name); +#endif } else if (STR_NE(host->name, hp->h_name) && STR_NE(host->name, "localhost")) { @@ -198,10 +324,19 @@ struct host_info *host; */ for (i = 0; hp->h_addr_list[i]; i++) { +#ifdef INET6 + if (memcmp(hp->h_addr_list[i], ap, alen) == 0) { +#ifdef USE_GETIPNODEBY + freehostent(hp); +#endif + return; /* name is good, keep it */ + } +#else if (memcmp(hp->h_addr_list[i], (char *) &sin->sin_addr, sizeof(sin->sin_addr)) == 0) return; /* name is good, keep it */ +#endif } /* @@ -210,10 +345,20 @@ struct host_info *host; * server. */ +#ifdef INET6 + inet_ntop(sin->sa_family, ap, addr, sizeof(addr)); + tcpd_warn("host name/address mismatch: %s != %.*s", + addr, STRING_LENGTH, hp->h_name); +#else tcpd_warn("host name/address mismatch: %s != %.*s", inet_ntoa(sin->sin_addr), STRING_LENGTH, hp->h_name); +#endif } strcpy(host->name, paranoid); /* name is bad, clobber it */ +#if defined(INET6) && defined(USE_GETIPNODEBY) + if (hp) + freehostent(hp); +#endif } } @@ -223,7 +368,11 @@ static void sock_sink(fd) int fd; { char buf[BUFSIZ]; +#ifdef INET6 + struct sockaddr_storage sin; +#else struct sockaddr_in sin; +#endif int size = sizeof(sin); /* diff --git a/contrib/tcp_wrappers/tcpd.c b/contrib/tcp_wrappers/tcpd.c index d865b9cce8eb..55c6853c1881 100644 --- a/contrib/tcp_wrappers/tcpd.c +++ b/contrib/tcp_wrappers/tcpd.c @@ -8,6 +8,8 @@ * are logged through syslog(3). * * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + * + * $FreeBSD$ */ #ifndef lint @@ -120,7 +122,12 @@ char **argv; /* Report request and invoke the real daemon program. */ +#ifdef INET6 + syslog(allow_severity, "connect from %s (%s)", + eval_client(&request), eval_hostaddr(request.client)); +#else syslog(allow_severity, "connect from %s", eval_client(&request)); +#endif closelog(); (void) execv(path, argv); syslog(LOG_ERR, "error: cannot execute %s: %m", path); diff --git a/contrib/tcp_wrappers/tcpd.h b/contrib/tcp_wrappers/tcpd.h index 3eecc9115997..fec20a262baf 100644 --- a/contrib/tcp_wrappers/tcpd.h +++ b/contrib/tcp_wrappers/tcpd.h @@ -2,6 +2,8 @@ * @(#) tcpd.h 1.5 96/03/19 16:22:24 * * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + * + * $FreeBSD$ */ /* Structure to describe one communications endpoint. */ @@ -11,7 +13,11 @@ struct host_info { char name[STRING_LENGTH]; /* access via eval_hostname(host) */ char addr[STRING_LENGTH]; /* access via eval_hostaddr(host) */ +#ifdef INET6 + struct sockaddr *sin; /* socket address or 0 */ +#else struct sockaddr_in *sin; /* socket address or 0 */ +#endif struct t_unitdata *unit; /* TLI transport address or 0 */ struct request_info *request; /* for shared information */ }; diff --git a/contrib/tcp_wrappers/tcpdchk.c b/contrib/tcp_wrappers/tcpdchk.c index 6a317d9a84aa..a2804a264d6f 100644 --- a/contrib/tcp_wrappers/tcpdchk.c +++ b/contrib/tcp_wrappers/tcpdchk.c @@ -24,6 +24,9 @@ static char sccsid[] = "@(#) tcpdchk.c 1.8 97/02/12 02:13:25"; #include #include +#ifdef INET6 +#include +#endif #include #include #include @@ -403,6 +406,26 @@ char *pat; } } +#ifdef INET6 +static int is_inet6_addr(pat) + char *pat; +{ + struct in6_addr addr; + int len, ret; + char ch; + + if (*pat != '[') + return (0); + len = strlen(pat); + if ((ch = pat[len - 1]) != ']') + return (0); + pat[len - 1] = '\0'; + ret = inet_pton(AF_INET6, pat + 1, &addr); + pat[len - 1] = ch; + return (ret == 1); +} +#endif + /* check_host - criticize host pattern */ static int check_host(pat) @@ -449,14 +472,27 @@ char *pat; tcpd_warn("open %s: %m", pat); } } else if (mask = split_at(pat, '/')) { /* network/netmask */ +#ifdef INET6 + int mask_len; + + if ((dot_quad_addr(pat) == INADDR_NONE + || dot_quad_addr(mask) == INADDR_NONE) + && (!is_inet6_addr(pat) + || ((mask_len = atoi(mask)) < 0 || mask_len > 128))) +#else if (dot_quad_addr(pat) == INADDR_NONE || dot_quad_addr(mask) == INADDR_NONE) +#endif tcpd_warn("%s/%s: bad net/mask pattern", pat, mask); } else if (STR_EQ(pat, "FAIL")) { /* obsolete */ tcpd_warn("FAIL is no longer recognized"); tcpd_warn("(use EXCEPT or DENY instead)"); } else if (reserved_name(pat)) { /* other reserved */ /* void */ ; +#ifdef INET6 + } else if (is_inet6_addr(pat)) { /* IPv6 address */ + addr_count = 1; +#endif } else if (NOT_INADDR(pat)) { /* internet name */ if (pat[strlen(pat) - 1] == '.') { tcpd_warn("%s: domain or host name ends in dot", pat); diff --git a/contrib/tcp_wrappers/tcpdmatch.c b/contrib/tcp_wrappers/tcpdmatch.c index b1cf75f25cee..f8c8dc12456f 100644 --- a/contrib/tcp_wrappers/tcpdmatch.c +++ b/contrib/tcp_wrappers/tcpdmatch.c @@ -11,6 +11,8 @@ * that would normally be reported via the syslog daemon. * * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + * + * $FreeBSD$ */ #ifndef lint @@ -68,8 +70,15 @@ char **argv; int ch; char *inetcf = 0; int count; +#ifdef INET6 + struct sockaddr_storage server_sin; + struct sockaddr_storage client_sin; + char *ap; + int alen; +#else struct sockaddr_in server_sin; struct sockaddr_in client_sin; +#endif struct stat st; /* @@ -173,12 +182,35 @@ char **argv; if ((hp = find_inet_addr(server)) == 0) exit(1); memset((char *) &server_sin, 0, sizeof(server_sin)); +#ifdef INET6 + server_sin.ss_family = hp->h_addrtype; + switch (hp->h_addrtype) { + case AF_INET: + ap = (char *)&((struct sockaddr_in *)&server_sin)->sin_addr; + alen = sizeof(struct sockaddr_in); + break; + case AF_INET6: + ap = (char *)&((struct sockaddr_in6 *)&server_sin)->sin6_addr; + alen = sizeof(struct sockaddr_in6); + break; + default: + exit(1); + } +#ifdef SIN6_LEN + server_sin.ss_len = alen; +#endif +#else server_sin.sin_family = AF_INET; +#endif request_set(&request, RQ_SERVER_SIN, &server_sin, 0); for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) { +#ifdef INET6 + memcpy(ap, addr, alen); +#else memcpy((char *) &server_sin.sin_addr, addr, sizeof(server_sin.sin_addr)); +#endif /* * Force evaluation of server host name and address. Host name @@ -230,12 +262,35 @@ char **argv; if ((hp = find_inet_addr(client)) == 0) exit(1); memset((char *) &client_sin, 0, sizeof(client_sin)); +#ifdef INET6 + client_sin.ss_family = hp->h_addrtype; + switch (hp->h_addrtype) { + case AF_INET: + ap = (char *)&((struct sockaddr_in *)&client_sin)->sin_addr; + alen = sizeof(struct sockaddr_in); + break; + case AF_INET6: + ap = (char *)&((struct sockaddr_in6 *)&client_sin)->sin6_addr; + alen = sizeof(struct sockaddr_in6); + break; + default: + exit(1); + } +#ifdef SIN6_LEN + client_sin.ss_len = alen; +#endif +#else client_sin.sin_family = AF_INET; +#endif request_set(&request, RQ_CLIENT_SIN, &client_sin, 0); for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) { +#ifdef INET6 + memcpy(ap, addr, alen); +#else memcpy((char *) &client_sin.sin_addr, addr, sizeof(client_sin.sin_addr)); +#endif /* * Force evaluation of client host name and address. Host name diff --git a/contrib/tcp_wrappers/tli.c b/contrib/tcp_wrappers/tli.c index 14579d1cbacb..36d6f7eff398 100644 --- a/contrib/tcp_wrappers/tli.c +++ b/contrib/tcp_wrappers/tli.c @@ -12,6 +12,8 @@ * Diagnostics are reported through syslog(3). * * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + * + * $FreeBSD$ */ #ifndef lint @@ -65,8 +67,13 @@ static void tli_sink(); void tli_host(request) struct request_info *request; { +#ifdef INET6 + static struct sockaddr_storage client; + static struct sockaddr_storage server; +#else static struct sockaddr_in client; static struct sockaddr_in server; +#endif /* * If we discover that we are using an IP transport, pretend we never @@ -75,15 +82,31 @@ struct request_info *request; */ tli_endpoints(request); +#ifdef INET6 if ((request->config = tli_transport(request->fd)) != 0 - && STR_EQ(request->config->nc_protofmly, "inet")) { + && (STR_EQ(request->config->nc_protofmly, "inet") || + STR_EQ(request->config->nc_protofmly, "inet6"))) { +#else + if ((request->config = tli_transport(request->fd)) != 0 + && STR_EQ(request->config->nc_protofmly, "inet")) { +#endif if (request->client->unit != 0) { +#ifdef INET6 + client = *(struct sockaddr_storage *) request->client->unit->addr.buf; + request->client->sin = (struct sockaddr *) &client; +#else client = *(struct sockaddr_in *) request->client->unit->addr.buf; request->client->sin = &client; +#endif } if (request->server->unit != 0) { - server = *(struct sockaddr_in *) request->server->unit->addr.buf; - request->server->sin = &server; +#ifdef INET6 + server = *(struct sockaddr_storage *) request->server->unit->addr.buf; + request->server->sin = (struct sockaddr *) &server; +#else + server = *(struct sockaddr_in *) request->server->unit->addr.buf; + request->server->sin = &server; +#endif } tli_cleanup(request); sock_methods(request); @@ -187,7 +210,15 @@ int fd; } while (config = getnetconfig(handlep)) { if (stat(config->nc_device, &from_config) == 0) { +#ifdef NO_CLONE_DEVICE + /* + * If the network devices are not cloned (as is the case for + * Solaris 8 Beta), we must compare the major device numbers. + */ + if (major(from_config.st_rdev) == major(from_client.st_rdev)) +#else if (minor(from_config.st_rdev) == major(from_client.st_rdev)) +#endif break; } } diff --git a/contrib/tcp_wrappers/update.c b/contrib/tcp_wrappers/update.c index a76cf2bb2375..b612d5e02466 100644 --- a/contrib/tcp_wrappers/update.c +++ b/contrib/tcp_wrappers/update.c @@ -11,6 +11,8 @@ * Diagnostics are reported through syslog(3). * * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + * + * $FreeBSD$ */ #ifndef lint @@ -46,10 +48,18 @@ va_list ap; request->fd = va_arg(ap, int); continue; case RQ_CLIENT_SIN: +#ifdef INET6 + request->client->sin = va_arg(ap, struct sockaddr *); +#else request->client->sin = va_arg(ap, struct sockaddr_in *); +#endif continue; case RQ_SERVER_SIN: +#ifdef INET6 + request->server->sin = va_arg(ap, struct sockaddr *); +#else request->server->sin = va_arg(ap, struct sockaddr_in *); +#endif continue; /* diff --git a/contrib/tcp_wrappers/workarounds.c b/contrib/tcp_wrappers/workarounds.c index 9ffa247a90ba..1ad2c6471ef3 100644 --- a/contrib/tcp_wrappers/workarounds.c +++ b/contrib/tcp_wrappers/workarounds.c @@ -5,6 +5,8 @@ * systems. * * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + * + * $FreeBSD$ */ #ifndef lint @@ -166,11 +168,22 @@ struct sockaddr *sa; int *len; { int ret; +#ifdef INET6 + struct sockaddr *sin = sa; +#else struct sockaddr_in *sin = (struct sockaddr_in *) sa; +#endif if ((ret = getpeername(sock, sa, len)) >= 0 +#ifdef INET6 + && ((sin->su_si.si_family == AF_INET6 + && IN6_IS_ADDR_UNSPECIFIED(&sin->su_sin6.sin6_addr)) + || (sin->su_si.si_family == AF_INET + && sin->su_sin.sin_addr.s_addr == 0))) { +#else && sa->sa_family == AF_INET && sin->sin_addr.s_addr == 0) { +#endif errno = ENOTCONN; return (-1); } else { diff --git a/lib/libwrap/Makefile b/lib/libwrap/Makefile index 83800677642f..ab565d0b6b12 100644 --- a/lib/libwrap/Makefile +++ b/lib/libwrap/Makefile @@ -15,6 +15,7 @@ CFLAGS+=-DFACILITY=LOG_AUTH -DHOSTS_ACCESS -DNETGROUP -DDAEMON_UMASK=022 \ -DSEVERITY=LOG_INFO -DRFC931_TIMEOUT=10 \ -DHOSTS_DENY=\"/etc/hosts.deny\" -DHOSTS_ALLOW=\"/etc/hosts.allow\" \ -DSYS_ERRLIST_DEFINED -DALWAYS_HOSTNAME +CFLAGS+=-DINET6 -DUSE_GETIPNODEBY SRCS= clean_exit.c diag.c eval.c fix_options.c fromhost.c \ hosts_access.c hosts_ctl.c misc.c myvsyslog.c options.c \ diff --git a/usr.sbin/tcpdchk/Makefile b/usr.sbin/tcpdchk/Makefile index d802eef045c2..86639f71fff7 100644 --- a/usr.sbin/tcpdchk/Makefile +++ b/usr.sbin/tcpdchk/Makefile @@ -11,6 +11,7 @@ SRCS= tcpdchk.c fakelog.c inetcf.c scaffold.c CFLAGS= -DREAL_DAEMON_DIR=\"/usr/libexec\" \ -DSEVERITY=LOG_INFO -DRFC931_TIMEOUT=10 \ -DHOSTS_DENY=\"/etc/hosts.deny\" -DHOSTS_ALLOW=\"/etc/hosts.allow\" +CFLAGS+=-DINET6 -DUSE_GETIPNODEBY DPADD= ${LIBWRAP} LDADD= -lwrap