From 1e8c736a70b5d05a77eaa2de825b32ac99588fd6 Mon Sep 17 00:00:00 2001 From: itojun Date: Tue, 31 Aug 1999 13:58:58 +0000 Subject: [PATCH] Apply IPv6 support patch. Note that all IPv6 address must be wrapped with square bracket, like: ALL: [::1/128] 127.0.0.1/255.255.255.255 Increase shlib minor. ftp://ftp.kame.net/pub/kame/misc/tcp_wrappers-76-v6-19990831.diff.gz --- distrib/sets/lists/base/shl.mi | 4 +- lib/libwrap/Makefile.cflags | 6 +- lib/libwrap/fix_options.c | 18 +++++- lib/libwrap/hosts_access.5 | 14 ++++- lib/libwrap/hosts_access.c | 100 ++++++++++++++++++++++++++++++++- lib/libwrap/misc.c | 28 ++++++++- lib/libwrap/rfc931.c | 93 ++++++++++++++++++++++++------ lib/libwrap/shlib_version | 4 +- lib/libwrap/socket.c | 86 +++++++++++++++++++++------- lib/libwrap/tcpd.h | 6 +- lib/libwrap/update.c | 8 +-- lib/libwrap/workarounds.c | 8 +-- usr.sbin/tcpdchk/scaffold.c | 61 ++++++++++++++++++-- usr.sbin/tcpdchk/tcpdchk.c | 35 ++++++++++-- usr.sbin/tcpdmatch/tcpdmatch.8 | 7 ++- usr.sbin/tcpdmatch/tcpdmatch.c | 58 +++++++++++++++---- 16 files changed, 454 insertions(+), 82 deletions(-) diff --git a/distrib/sets/lists/base/shl.mi b/distrib/sets/lists/base/shl.mi index 81e10077bed6..53d523f60a98 100644 --- a/distrib/sets/lists/base/shl.mi +++ b/distrib/sets/lists/base/shl.mi @@ -1,4 +1,4 @@ -# $NetBSD: shl.mi,v 1.34 1999/08/27 16:24:02 itojun Exp $ +# $NetBSD: shl.mi,v 1.35 1999/08/31 13:58:59 itojun Exp $ ./usr/lib/libamu.so.1.1 ./usr/lib/libbfd.so.3.0 ./usr/lib/libbz2.so.0.0 @@ -24,5 +24,5 @@ ./usr/lib/libtermlib.so.0.0 ./usr/lib/libusb.so.0.0 ./usr/lib/libutil.so.5.1 -./usr/lib/libwrap.so.0.1 +./usr/lib/libwrap.so.0.2 ./usr/lib/libz.so.0.1 diff --git a/lib/libwrap/Makefile.cflags b/lib/libwrap/Makefile.cflags index 591e0eab1a34..9cf6aaa44512 100644 --- a/lib/libwrap/Makefile.cflags +++ b/lib/libwrap/Makefile.cflags @@ -1,13 +1,17 @@ -# $NetBSD: Makefile.cflags,v 1.4 1997/10/26 20:52:47 christos Exp $ +# $NetBSD: Makefile.cflags,v 1.5 1999/08/31 13:58:58 itojun Exp $ CPPFLAGS+=-DFACILITY=LOG_AUTHPRIV -DSEVERITY=LOG_INFO CPPFLAGS+=-DREAL_DAEMON_DIR=\"/usr/libexec\" -DHOSTS_ACCESS -DDAEMON_UMASK=022 CPPFLAGS+=-DRFC931_TIMEOUT=10 -DALWAYS_HOSTNAME -DSYS_ERRLIST_DEFINED CPPFLAGS+=-DHOSTS_ALLOW=\"/etc/hosts.allow\" -DHOSTS_DENY=\"/etc/hosts.deny\" CPPFLAGS+=-DPROCESS_OPTIONS -DNETGROUP +CPPFLAGS+=-Dss_family=__ss_family -Dss_len=__ss_len # -DPARANOID is not used by libwrap, only by programs that use it. # in this case inetd does not use it (probably rightly so) and so # we don't want to use it in wrapper-related utilities (such as # tcpdmatch) that include this file. #CPPFLAGS+=-DPARANOID + +# IPv6 +CPPFLAGS+=-DINET6 diff --git a/lib/libwrap/fix_options.c b/lib/libwrap/fix_options.c index 91d111d7edb2..1fe4103faa62 100644 --- a/lib/libwrap/fix_options.c +++ b/lib/libwrap/fix_options.c @@ -1,4 +1,4 @@ -/* $NetBSD: fix_options.c,v 1.4 1999/08/27 16:06:17 itojun Exp $ */ +/* $NetBSD: fix_options.c,v 1.5 1999/08/31 13:58:58 itojun Exp $ */ /* * Routine to disable IP-level socket options. This code was taken from 4.4BSD @@ -12,7 +12,7 @@ #if 0 static char sccsid[] = "@(#) fix_options.c 1.6 97/04/08 02:29:19"; #else -__RCSID("$NetBSD: fix_options.c,v 1.4 1999/08/27 16:06:17 itojun Exp $"); +__RCSID("$NetBSD: fix_options.c,v 1.5 1999/08/31 13:58:58 itojun Exp $"); #endif #endif @@ -53,7 +53,21 @@ struct request_info *request; unsigned int opt; int optlen; struct in_addr dummy; + 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; + if ((ip = getprotobyname("ip")) != 0) ipproto = ip->p_proto; else diff --git a/lib/libwrap/hosts_access.5 b/lib/libwrap/hosts_access.5 index 8ae5ab37f4c9..8009a9b0f217 100644 --- a/lib/libwrap/hosts_access.5 +++ b/lib/libwrap/hosts_access.5 @@ -64,6 +64,8 @@ daemon_list : client_list : option : option ... \fIclient_list\fR is a list of one or more host names, host addresses, patterns or wildcards (see below) that will be matched against the client host name or address. +When a client_list item needs to include colon character (for IPv6 addresses), +the item needs to be wrapped with square bracket. .PP The more complex forms \fIdaemon@host\fR and \fIuser@host\fR are explained in the sections on server endpoint patterns and on client @@ -97,6 +99,16 @@ An expression of the form `n.n.n.n/m.m.m.m\' is interpreted as a 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\'. +Note that `m.m.m.m\' portion must always be specified. +.IP \(bu +An expression of the form `ipv6-addr/ipv6-mask\' is interpreted as +masked IPv6 address match, just like masked IPv4 address match (see above). +Note that `ipv6-mask\' portion must always be specified. +.IP \(bu +An expression of the form `ipv6-addr/prefixlen\' is interpreted as +masked IPv6 address match (with mask specified by numeric prefixlen), +just like masked IPv4 address match (see above). +Note that `prefixlen\' portion must always be specified. .SH WILDCARDS The access control language supports explicit wildcards: .IP ALL @@ -378,4 +390,4 @@ Eindhoven University of Technology Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands \" @(#) hosts_access.5 1.20 95/01/30 19:51:46 -\" $NetBSD: hosts_access.5,v 1.9 1999/08/02 16:09:41 bouyer Exp $ +\" $NetBSD: hosts_access.5,v 1.10 1999/08/31 13:58:58 itojun Exp $ diff --git a/lib/libwrap/hosts_access.c b/lib/libwrap/hosts_access.c index f6725a73a5bb..46d4a7603050 100644 --- a/lib/libwrap/hosts_access.c +++ b/lib/libwrap/hosts_access.c @@ -1,4 +1,4 @@ -/* $NetBSD: hosts_access.c,v 1.9 1999/08/27 16:06:17 itojun Exp $ */ +/* $NetBSD: hosts_access.c,v 1.10 1999/08/31 13:58:58 itojun Exp $ */ /* * This module implements a simple access control language that is based on @@ -24,7 +24,7 @@ #if 0 static char sccsid[] = "@(#) hosts_access.c 1.21 97/02/12 02:13:22"; #else -__RCSID("$NetBSD: hosts_access.c,v 1.9 1999/08/27 16:06:17 itojun Exp $"); +__RCSID("$NetBSD: hosts_access.c,v 1.10 1999/08/31 13:58:58 itojun Exp $"); #endif #endif @@ -32,6 +32,9 @@ __RCSID("$NetBSD: hosts_access.c,v 1.9 1999/08/27 16:06:17 itojun Exp $"); #include #include +#ifdef INET6 +#include +#endif #include #include #include @@ -96,6 +99,10 @@ static int host_match __P((char *, struct host_info *)); static int rbl_match __P((char *, char *)); static int string_match __P((char *, char *)); static int masked_match __P((char *, char *, char *)); +static int masked_match4 __P((char *, char *, char *)); +#ifdef INET6 +static int masked_match6 __P((char *, char *, char *)); +#endif /* Size of logical line buffer. */ @@ -202,6 +209,7 @@ struct request_info *request; int (*match_fn) __P((char *, struct request_info *)); { char *tok; + int l; /* * Process tokens one at a time. We have exhausted all possible matches @@ -213,6 +221,11 @@ int (*match_fn) __P((char *, struct request_info *)); for (tok = strtok(list, sep); tok != 0; tok = strtok((char *) 0, sep)) { if (STR_EQ(tok, "EXCEPT")) /* EXCEPT: give up */ return (NO); + l = strlen(tok); + if (*tok == '[' && tok[l - 1] == ']') { + tok[l - 1] = '\0'; + tok++; + } if (match_fn(tok, request)) { /* YES: look for exceptions */ while ((tok = strtok((char *) 0, sep)) && STR_NE(tok, "EXCEPT")) /* VOID */ ; @@ -361,6 +374,23 @@ static int masked_match(net_tok, mask_tok, string) char *net_tok; char *mask_tok; char *string; +{ +#ifndef INET6 + return masked_match4(net_tok, mask_tok, string); +#else + if (dot_quad_addr(net_tok, NULL) != INADDR_NONE + && dot_quad_addr(mask_tok, NULL) != INADDR_NONE + && dot_quad_addr(string, NULL) != INADDR_NONE) { + return masked_match4(net_tok, mask_tok, string); + } else + return masked_match6(net_tok, mask_tok, string); +#endif +} + +static int masked_match4(net_tok, mask_tok, string) +char *net_tok; +char *mask_tok; +char *string; { unsigned long net; unsigned long mask; @@ -381,3 +411,69 @@ char *string; } return ((addr & mask) == net); } + +#ifdef INET6 +/* Ugly because it covers IPv4 mapped address. I hate mapped addresses. */ +static int masked_match6(net_tok, mask_tok, string) +char *net_tok; +char *mask_tok; +char *string; +{ + struct in6_addr net; + struct in6_addr mask; + struct in6_addr addr; + int masklen; + int fail; + int i; + int maskoff; + int netaf; + const int sizoff64 = sizeof(struct in6_addr) - sizeof(struct in_addr); + + memset(&addr, 0, sizeof(addr)); + if (inet_pton(AF_INET6, string, &addr) == 1) + ; /* okay */ + else if (inet_pton(AF_INET, string, &addr.s6_addr[sizoff64]) == 1) + addr.s6_addr[10] = addr.s6_addr[11] = 0xff; + else + return NO; + + memset(&net, 0, sizeof(net)); + if (inet_pton(AF_INET6, net_tok, &net) == 1) { + netaf = AF_INET6; + maskoff = 0; + } else if (inet_pton(AF_INET, net_tok, &net.s6_addr[sizoff64]) == 1) { + netaf = AF_INET; + maskoff = sizoff64; + net.s6_addr[10] = net.s6_addr[11] = 0xff; + } else + return NO; + + fail = 0; + if (mask_tok[strspn(mask_tok, "0123456789")] == '\0') { + masklen = atoi(mask_tok) + maskoff * 8; + if (0 <= masklen && masklen <= 128) { + memset(&mask, 0, sizeof(mask)); + memset(&mask, 0xff, masklen / 8); + if (masklen % 8) { + ((u_char *)&mask)[masklen / 8] = + (0xff00 >> (masklen % 8)) & 0xff; + } + } else + fail++; + } else if (netaf == AF_INET6 && inet_pton(AF_INET6, mask_tok, &mask) == 1) + ; /* okay */ + else if (netaf == AF_INET + && inet_pton(AF_INET, mask_tok, &mask.s6_addr[12]) == 1) { + memset(&mask, 0xff, sizoff64); + } else + fail++; + if (fail) { + tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok); + return (NO); /* not tcpd_jump() */ + } + + for (i = 0; i < sizeof(addr); i++) + addr.s6_addr[i] &= mask.s6_addr[i]; + return (memcmp(&addr, &net, sizeof(addr)) == 0); +} +#endif diff --git a/lib/libwrap/misc.c b/lib/libwrap/misc.c index 1321289d8b2e..79a5237ecaf7 100644 --- a/lib/libwrap/misc.c +++ b/lib/libwrap/misc.c @@ -1,4 +1,4 @@ -/* $NetBSD: misc.c,v 1.6 1999/07/03 12:30:41 simonb Exp $ */ +/* $NetBSD: misc.c,v 1.7 1999/08/31 13:58:58 itojun Exp $ */ /* * Misc routines that are used by tcpd and by tcpdchk. @@ -11,7 +11,7 @@ #if 0 static char sccsic[] = "@(#) misc.c 1.2 96/02/11 17:01:29"; #else -__RCSID("$NetBSD: misc.c,v 1.6 1999/07/03 12:30:41 simonb Exp $"); +__RCSID("$NetBSD: misc.c,v 1.7 1999/08/31 13:58:58 itojun Exp $"); #endif #endif @@ -61,11 +61,35 @@ char *split_at(string, delimiter) char *string; int delimiter; { +#if 0 char *cp; if ((cp = strchr(string, delimiter)) != 0) *cp++ = 0; return (cp); +#else + char *cp; + int bracket; + + 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; +#endif } /* dot_quad_addr - convert dotted quad to internal form */ diff --git a/lib/libwrap/rfc931.c b/lib/libwrap/rfc931.c index e43468d2ca65..8fb827064726 100644 --- a/lib/libwrap/rfc931.c +++ b/lib/libwrap/rfc931.c @@ -1,4 +1,4 @@ -/* $NetBSD: rfc931.c,v 1.5 1999/07/03 12:30:41 simonb Exp $ */ +/* $NetBSD: rfc931.c,v 1.6 1999/08/31 13:58:58 itojun Exp $ */ /* * rfc931() speaks a common subset of the RFC 931, AUTH, TAP, IDENT and RFC @@ -16,7 +16,7 @@ #if 0 static char sccsid[] = "@(#) rfc931.c 1.10 95/01/02 16:11:34"; #else -__RCSID("$NetBSD: rfc931.c,v 1.5 1999/07/03 12:30:41 simonb Exp $"); +__RCSID("$NetBSD: rfc931.c,v 1.6 1999/08/31 13:58:58 itojun Exp $"); #endif #endif @@ -80,19 +80,56 @@ int sig; /* rfc931 - return remote user name, given socket structures */ void rfc931(rmt_sin, our_sin, dest) -struct sockaddr_in *rmt_sin; -struct sockaddr_in *our_sin; +struct sockaddr *rmt_sin; +struct sockaddr *our_sin; char *dest; { unsigned rmt_port; unsigned our_port; - struct sockaddr_in rmt_query_sin; - struct sockaddr_in our_query_sin; + struct sockaddr_storage rmt_query_sin; + struct sockaddr_storage our_query_sin; char user[256]; /* XXX */ char buffer[512]; /* XXX */ char *cp; char *result = unknown; FILE *fp; + int salen; + u_short *rmt_portp; + u_short *our_portp; + + /* address family must be the same */ + if (rmt_sin->sa_family != our_sin->sa_family) { + STRN_CPY(dest, result, STRING_LENGTH); + return; + } + switch (rmt_sin->sa_family) { + case AF_INET: + salen = sizeof(struct sockaddr_in); + rmt_portp = &((struct sockaddr_in *)&rmt_sin)->sin_port; + break; +#ifdef INET6 + case AF_INET6: + salen = sizeof(struct sockaddr_in6); + rmt_portp = &((struct sockaddr_in6 *)&rmt_sin)->sin6_port; + break; +#endif + default: + STRN_CPY(dest, result, STRING_LENGTH); + return; + } + switch (our_sin->sa_family) { + case AF_INET: + our_portp = &((struct sockaddr_in *)&our_sin)->sin_port; + break; +#ifdef INET6 + case AF_INET6: + our_portp = &((struct sockaddr_in6 *)&our_sin)->sin6_port; + break; +#endif + default: + STRN_CPY(dest, result, STRING_LENGTH); + return; + } #ifdef __GNUC__ (void)&result; /* Avoid longjmp clobbering */ @@ -109,7 +146,7 @@ char *dest; * sockets. */ - if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) { + if ((fp = fsocket(rmt_sin->sa_family, SOCK_STREAM, 0)) != 0) { setbuf(fp, (char *) 0); /* @@ -129,15 +166,37 @@ char *dest; * addresses from the query socket. */ - our_query_sin = *our_sin; - our_query_sin.sin_port = htons(ANY_PORT); - rmt_query_sin = *rmt_sin; - rmt_query_sin.sin_port = htons(RFC931_PORT); + memcpy(&our_query_sin, our_sin, salen); + switch (our_query_sin.ss_family) { + case AF_INET: + ((struct sockaddr_in *)&our_query_sin)->sin_port = + htons(ANY_PORT); + break; +#ifdef INET6 + case AF_INET6: + ((struct sockaddr_in6 *)&our_query_sin)->sin6_port = + htons(ANY_PORT); + break; +#endif + } + memcpy(&rmt_query_sin, rmt_sin, salen); + switch (rmt_query_sin.ss_family) { + case AF_INET: + ((struct sockaddr_in *)&rmt_query_sin)->sin_port = + htons(RFC931_PORT); + break; +#ifdef INET6 + case AF_INET6: + ((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port = + htons(RFC931_PORT); + break; +#endif + } if (bind(fileno(fp), (struct sockaddr *) & our_query_sin, - sizeof(our_query_sin)) >= 0 && + salen) >= 0 && connect(fileno(fp), (struct sockaddr *) & rmt_query_sin, - sizeof(rmt_query_sin)) >= 0) { + salen) >= 0) { /* * Send query to server. Neglect the risk that a 13-byte @@ -146,8 +205,8 @@ char *dest; */ fprintf(fp, "%u,%u\r\n", - ntohs(rmt_sin->sin_port), - ntohs(our_sin->sin_port)); + ntohs(*rmt_portp), + ntohs(*our_portp)); fflush(fp); /* @@ -161,8 +220,8 @@ char *dest; && ferror(fp) == 0 && feof(fp) == 0 && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s", &rmt_port, &our_port, user) == 3 - && ntohs(rmt_sin->sin_port) == rmt_port - && ntohs(our_sin->sin_port) == our_port) { + && ntohs(*rmt_portp) == rmt_port + && ntohs(*our_portp) == our_port) { /* * Strip trailing carriage return. It is part of the diff --git a/lib/libwrap/shlib_version b/lib/libwrap/shlib_version index bdf1de196686..be322de59071 100644 --- a/lib/libwrap/shlib_version +++ b/lib/libwrap/shlib_version @@ -1,5 +1,5 @@ -# $NetBSD: shlib_version,v 1.4 1999/08/27 16:24:01 itojun Exp $ +# $NetBSD: shlib_version,v 1.5 1999/08/31 13:58:58 itojun Exp $ # Remember to update distrib/sets/lists/base/shl.* when changing # major=0 -minor=1 +minor=2 diff --git a/lib/libwrap/socket.c b/lib/libwrap/socket.c index a69a6518ce82..46349abca6ac 100644 --- a/lib/libwrap/socket.c +++ b/lib/libwrap/socket.c @@ -1,4 +1,4 @@ -/* $NetBSD: socket.c,v 1.6 1999/08/27 16:06:17 itojun Exp $ */ +/* $NetBSD: socket.c,v 1.7 1999/08/31 13:58:58 itojun Exp $ */ /* * This module determines the type of socket (datagram, stream), the client @@ -22,7 +22,7 @@ #if 0 static char sccsid[] = "@(#) socket.c 1.15 97/03/21 19:27:24"; #else -__RCSID("$NetBSD: socket.c,v 1.6 1999/08/27 16:06:17 itojun Exp $"); +__RCSID("$NetBSD: socket.c,v 1.7 1999/08/31 13:58:58 itojun Exp $"); #endif #endif @@ -81,8 +81,8 @@ char *name; void sock_host(request) struct request_info *request; { - static struct sockaddr_in client; - static struct sockaddr_in server; + static struct sockaddr_storage client; + static struct sockaddr_storage server; int len; char buf[BUFSIZ]; int fd = request->fd; @@ -96,6 +96,8 @@ struct request_info *request; * really should verify that client.sin_family gets the value AF_INET, * but this program has already caused too much grief on systems with * broken library code. + * + * XXX the last sentence is untrue as we support AF_INET6 as well :-) */ len = sizeof(client); @@ -111,7 +113,7 @@ struct request_info *request; memset(buf, 0 sizeof(buf)); #endif } - request->client->sin = &client; + request->client->sin = (struct sockaddr *)&client; /* * Determine the server binding. This is used for client username @@ -124,7 +126,7 @@ struct request_info *request; tcpd_warn("getsockname: %m"); return; } - request->server->sin = &server; + request->server->sin = (struct sockaddr *)&server; } /* sock_hostaddr - map endpoint address to printable form */ @@ -132,10 +134,28 @@ struct request_info *request; void sock_hostaddr(host) struct host_info *host; { - struct sockaddr_in *sin = host->sin; + struct sockaddr *sa = host->sin; + int alen, af; + char *ap; - if (sin != 0) - STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr)); + if (!sa) + return; + switch (sa->sa_family) { + case AF_INET: + ap = (char *)&((struct sockaddr_in *)sa)->sin_addr; + alen = sizeof(struct in_addr); + break; +#ifdef INET6 + case AF_INET6: + ap = (char *)&((struct sockaddr_in6 *)sa)->sin6_addr; + alen = sizeof(struct in6_addr); + break; +#endif + default: + return; + } + host->addr[0] = '\0'; + inet_ntop(af, ap, host->addr, sizeof(host->addr)); } /* sock_hostname - map endpoint address to host name */ @@ -143,9 +163,12 @@ struct host_info *host; void sock_hostname(host) struct host_info *host; { - struct sockaddr_in *sin = host->sin; + struct sockaddr *sin = host->sin; struct hostent *hp; int i; + int af, alen; + char *ap; + char hbuf[MAXHOSTNAMELEN]; /* * On some systems, for example Solaris 2.3, gethostbyaddr(0.0.0.0) does @@ -154,9 +177,31 @@ 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. */ - if (sin != 0 && sin->sin_addr.s_addr != 0 - && (hp = gethostbyaddr((char *) &(sin->sin_addr), - sizeof(sin->sin_addr), AF_INET)) != 0) { + if (!sin) + return; + switch (af = sin->sa_family) { + case AF_INET: + if (((struct sockaddr_in *)sin)->sin_addr.s_addr == 0) + return; + ap = (char *)&((struct sockaddr_in *)sin)->sin_addr; + alen = sizeof(struct in_addr); + break; +#ifdef INET6 + case AF_INET6: + ap = (char *)&((struct sockaddr_in6 *)sin)->sin6_addr; + alen = sizeof(struct in6_addr); + /* special case on reverse lookup: mapped addr. I hate it */ + if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { + af = AF_INET; + ap += (sizeof(struct in6_addr) - sizeof(struct in_addr)); + alen = sizeof(struct in_addr); + } + break; +#endif + default: + return; + } + if ((hp = gethostbyaddr(ap, alen, af)) != 0) { STRN_CPY(host->name, hp->h_name, sizeof(host->name)); @@ -173,15 +218,15 @@ struct host_info *host; * we're in big trouble anyway. */ - if ((hp = gethostbyname(host->name)) == 0) { + if ((hp = gethostbyname2(host->name, af)) == 0) { /* * Unable to verify that the host name matches the address. This * may be a transient problem or a botched name server setup. */ - tcpd_warn("can't verify hostname: gethostbyname(%s) failed", - host->name); + tcpd_warn("can't verify hostname: gethostbyname2(%s, %d) failed", + host->name, af); } else if (STR_NE(host->name, hp->h_name) && STR_NE(host->name, "localhost")) { @@ -205,9 +250,7 @@ struct host_info *host; */ for (i = 0; hp->h_addr_list[i]; i++) { - if (memcmp(hp->h_addr_list[i], - (char *) &sin->sin_addr, - sizeof(sin->sin_addr)) == 0) + if (memcmp(hp->h_addr_list[i], (char *) ap, alen) == 0) return; /* name is good, keep it */ } @@ -218,7 +261,8 @@ struct host_info *host; */ tcpd_warn("host name/address mismatch: %s != %.*s", - inet_ntoa(sin->sin_addr), STRING_LENGTH, hp->h_name); + inet_ntop(af, ap, hbuf, sizeof(hbuf)), + STRING_LENGTH, hp->h_name); } /* name is bad, clobber it */ (void)strncpy(host->name, paranoid, sizeof(host->name) - 1); @@ -231,7 +275,7 @@ static void sock_sink(fd) int fd; { char buf[BUFSIZ]; - struct sockaddr_in sin; + struct sockaddr_storage sin; int size = sizeof(sin); /* diff --git a/lib/libwrap/tcpd.h b/lib/libwrap/tcpd.h index c6cb000c01ec..c65dd1d4b6fd 100644 --- a/lib/libwrap/tcpd.h +++ b/lib/libwrap/tcpd.h @@ -1,4 +1,4 @@ -/* $NetBSD: tcpd.h,v 1.7 1999/07/03 12:30:42 simonb Exp $ */ +/* $NetBSD: tcpd.h,v 1.8 1999/08/31 13:58:58 itojun Exp $ */ /* * @(#) tcpd.h 1.5 96/03/19 16:22:24 * @@ -12,7 +12,7 @@ struct host_info { char name[STRING_LENGTH]; /* access via eval_hostname(host) */ char addr[STRING_LENGTH]; /* access via eval_hostaddr(host) */ - struct sockaddr_in *sin; /* socket address or 0 */ + struct sockaddr *sin; /* socket address or 0 */ struct t_unitdata *unit; /* TLI transport address or 0 */ struct request_info *request; /* for shared information */ }; @@ -81,7 +81,7 @@ extern void shell_cmd /* execute shell command */ extern char *percent_x /* do % expansion */ __P((char *, int, char *, struct request_info *)); extern void rfc931 /* client name from RFC 931 daemon */ - __P((struct sockaddr_in *, struct sockaddr_in *, char *)); + __P((struct sockaddr *, struct sockaddr *, char *)); extern void clean_exit /* clean up and exit */ __P((struct request_info *)); extern void refuse /* clean up and exit */ diff --git a/lib/libwrap/update.c b/lib/libwrap/update.c index 8c1ed817a1b3..a91458d2a298 100644 --- a/lib/libwrap/update.c +++ b/lib/libwrap/update.c @@ -1,4 +1,4 @@ -/* $NetBSD: update.c,v 1.5 1999/07/03 12:30:42 simonb Exp $ */ +/* $NetBSD: update.c,v 1.6 1999/08/31 13:58:58 itojun Exp $ */ /* * Routines for controlled update/initialization of request structures. @@ -20,7 +20,7 @@ #if 0 static char sccsid[] = "@(#) update.c 1.1 94/12/28 17:42:56"; #else -__RCSID("$NetBSD: update.c,v 1.5 1999/07/03 12:30:42 simonb Exp $"); +__RCSID("$NetBSD: update.c,v 1.6 1999/08/31 13:58:58 itojun Exp $"); #endif #endif @@ -56,10 +56,10 @@ va_list ap; request->fd = va_arg(ap, int); continue; case RQ_CLIENT_SIN: - request->client->sin = va_arg(ap, struct sockaddr_in *); + request->client->sin = va_arg(ap, struct sockaddr *); continue; case RQ_SERVER_SIN: - request->server->sin = va_arg(ap, struct sockaddr_in *); + request->server->sin = va_arg(ap, struct sockaddr *); continue; /* diff --git a/lib/libwrap/workarounds.c b/lib/libwrap/workarounds.c index 7ec050e2d7ee..bfcaba33fde2 100644 --- a/lib/libwrap/workarounds.c +++ b/lib/libwrap/workarounds.c @@ -1,4 +1,4 @@ -/* $NetBSD: workarounds.c,v 1.4 1999/07/03 12:30:42 simonb Exp $ */ +/* $NetBSD: workarounds.c,v 1.5 1999/08/31 13:58:58 itojun Exp $ */ /* * Workarounds for known system software bugs. This module provides wrappers @@ -14,7 +14,7 @@ #if 0 char sccsid[] = "@(#) workarounds.c 1.6 96/03/19 16:22:25"; #else -__RCSID("$NetBSD: workarounds.c,v 1.4 1999/07/03 12:30:42 simonb Exp $"); +__RCSID("$NetBSD: workarounds.c,v 1.5 1999/08/31 13:58:58 itojun Exp $"); #endif #endif @@ -141,10 +141,10 @@ int *fromlen; if ((ret = recvfrom(sock, buf, buflen, flags, from, fromlen)) >= 0) { if (from->sa_family == 0) { - struct sockaddr my_addr; + struct sockaddr_storage my_addr; int my_addr_len = sizeof(my_addr); - if (getsockname(0, &my_addr, &my_addr_len)) { + if (getsockname(0, (struct sockaddr *)&my_addr, &my_addr_len)) { tcpd_warn("getsockname: %m"); } else { from->sa_family = my_addr.sa_family; diff --git a/usr.sbin/tcpdchk/scaffold.c b/usr.sbin/tcpdchk/scaffold.c index 5a11d14dcc91..ebb3f05ea62d 100644 --- a/usr.sbin/tcpdchk/scaffold.c +++ b/usr.sbin/tcpdchk/scaffold.c @@ -1,4 +1,4 @@ -/* $NetBSD: scaffold.c,v 1.6 1999/08/27 16:07:23 itojun Exp $ */ +/* $NetBSD: scaffold.c,v 1.7 1999/08/31 13:58:58 itojun Exp $ */ /* * Routines for testing only. Not really industrial strength. @@ -11,7 +11,7 @@ #if 0 static char sccs_id[] = "@(#) scaffold.c 1.6 97/03/21 19:27:24"; #else -__RCSID("$NetBSD: scaffold.c,v 1.6 1999/08/27 16:07:23 itojun Exp $"); +__RCSID("$NetBSD: scaffold.c,v 1.7 1999/08/31 13:58:58 itojun Exp $"); #endif #endif @@ -70,6 +70,7 @@ struct hostent *hp; exit(1); } memset((char *) &hb->host, 0, sizeof(hb->host)); + hb->host.h_addrtype = hp->h_addrtype; hb->host.h_length = hp->h_length; hb->host.h_addr_list = hb->addr_list; hb->host.h_addr_list[count] = 0; @@ -92,6 +93,9 @@ char *host; struct hostent *hp; static struct hostent h; static char *addr_list[2]; +#ifdef INET6 + static struct in6_addr in6; +#endif /* * Host address: translate it to internal form. @@ -101,8 +105,18 @@ char *host; h.h_addr_list = addr_list; h.h_addr_list[0] = (char *) &addr; h.h_length = sizeof(addr); + h.h_addrtype = AF_INET; return (dup_hostent(&h)); } +#ifdef INET6 + if (inet_pton(AF_INET6, host, &in6) == 1) { + h.h_addr_list = addr_list; + h.h_addr_list[0] = (char *) &in6; + h.h_length = sizeof(in6); + h.h_addrtype = AF_INET6; + return (dup_hostent(&h)); + } +#endif /* * Map host name to a series of addresses. Watch out for non-internet @@ -110,10 +124,28 @@ char *host; * been "enhanced" to accept numeric addresses. Make a copy of the * address list so that later gethostbyXXX() calls will not clobber it. */ - if (NOT_INADDR(host) == 0) { +#ifdef INET6 + if (NOT_INADDR(host) == 0 && inet_pton(AF_INET6, host, &in6) == 1) +#else + if (NOT_INADDR(host) == 0) +#endif + { tcpd_warn("%s: not an internet address", host); return (0); } +#ifdef INET6 + /* + * XXX this behavior may, or may not be desirable. + * - we may better use getipnodebyname() to addresses of get both AFs, + * however, getipnodebyname() is not widely implemented. + * - it may be better to have a way to specify the AF to use. + */ + if ((hp = gethostbyname2(host, AF_INET)) == 0 + && (hp = gethostbyname2(host, AF_INET6)) == 0) { + tcpd_warn("%s: host not found", host); + return (0); + } +#else if ((hp = gethostbyname(host)) == 0) { tcpd_warn("%s: host not found", host); return (0); @@ -122,6 +154,7 @@ char *host; tcpd_warn("%d: not an internet host", hp->h_addrtype); return (0); } +#endif if (STR_NE(host, hp->h_name)) { tcpd_warn("%s: hostname alias", host); tcpd_warn("(official name: %.*s)", STRING_LENGTH, hp->h_name); @@ -135,20 +168,36 @@ int check_dns(host) char *host; { struct request_info request; - struct sockaddr_in sin; + struct sockaddr_storage sin; struct hostent *hp; int count; char *addr; + char *ap; + int alen; if ((hp = find_inet_addr(host)) == 0) return (0); request_init(&request, RQ_CLIENT_SIN, &sin, 0); sock_methods(&request); memset((char *) &sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; + sin.ss_family = hp->h_addrtype; + switch (hp->h_addrtype) { + case AF_INET: + ap = (char *)&((struct sockaddr_in *)&sin)->sin_addr; + alen = sizeof(struct in6_addr); + break; +#ifdef INET6 + case AF_INET6: + ap = (char *)&((struct sockaddr_in6 *)&sin)->sin6_addr; + alen = sizeof(struct in6_addr); + break; +#endif + default: + return (0); + } for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) { - memcpy((char *) &sin.sin_addr, addr, sizeof(sin.sin_addr)); + memcpy(ap, addr, alen); /* * Force host name and address conversions. Use the request structure diff --git a/usr.sbin/tcpdchk/tcpdchk.c b/usr.sbin/tcpdchk/tcpdchk.c index 434d7048d718..4e8f3f323a84 100644 --- a/usr.sbin/tcpdchk/tcpdchk.c +++ b/usr.sbin/tcpdchk/tcpdchk.c @@ -1,4 +1,4 @@ -/* $NetBSD: tcpdchk.c,v 1.8 1999/08/27 16:07:23 itojun Exp $ */ +/* $NetBSD: tcpdchk.c,v 1.9 1999/08/31 13:58:58 itojun Exp $ */ /* * tcpdchk - examine all tcpd access control rules and inetd.conf entries @@ -21,7 +21,7 @@ #if 0 static char sccsid[] = "@(#) tcpdchk.c 1.8 97/02/12 02:13:25"; #else -__RCSID("$NetBSD: tcpdchk.c,v 1.8 1999/08/27 16:07:23 itojun Exp $"); +__RCSID("$NetBSD: tcpdchk.c,v 1.9 1999/08/31 13:58:58 itojun Exp $"); #endif #endif @@ -29,6 +29,9 @@ __RCSID("$NetBSD: tcpdchk.c,v 1.8 1999/08/27 16:07:23 itojun Exp $"); #include #include +#ifdef INET6 +#include +#endif #include #include #include @@ -341,10 +344,20 @@ char *list; char *cp; char *host; int clients = 0; +#ifdef INET6 + int l; +#endif strcpy(buf, list); for (cp = strtok(buf, sep); cp != 0; cp = strtok((char *) 0, sep)) { +#ifdef INET6 + l = strlen(cp); + if (cp[0] == '[' && cp[l - 1] == ']') { + cp[l - 1] = '\0'; + cp++; + } +#endif if (STR_EQ(cp, "EXCEPT")) { clients = 0; } else { @@ -441,8 +454,22 @@ char *pat; #endif #endif } else if ((mask = split_at(pat, '/')) != NULL) { /* network/netmask */ - if (dot_quad_addr(pat, NULL) != 0 - || dot_quad_addr(mask, NULL) != 0) +#ifdef INET6 + struct in6_addr in6; +#endif + if (dot_quad_addr(pat, NULL) != INADDR_NONE + || dot_quad_addr(mask, NULL) != INADDR_NONE) + ; /*okay*/ +#ifdef INET6 + else if (inet_pton(AF_INET6, pat, &in6) == 1 + && inet_pton(AF_INET6, mask, &in6) == 1) + ; /*okay*/ + else if (inet_pton(AF_INET6, pat, &in6) == 1 + && strchr(mask, ':') == NULL + && 0 <= atoi(mask) && atoi(mask) <= 128) + ; /*okay*/ +#endif + else tcpd_warn("%s/%s: bad net/mask pattern", pat, mask); } else if (STR_EQ(pat, "FAIL")) { /* obsolete */ tcpd_warn("FAIL is no longer recognized"); diff --git a/usr.sbin/tcpdmatch/tcpdmatch.8 b/usr.sbin/tcpdmatch/tcpdmatch.8 index c0ebda25cd90..b5bd2bc7a111 100644 --- a/usr.sbin/tcpdmatch/tcpdmatch.8 +++ b/usr.sbin/tcpdmatch/tcpdmatch.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: tcpdmatch.8,v 1.3 1998/01/09 08:11:51 perry Exp $ +.\" $NetBSD: tcpdmatch.8,v 1.4 1999/08/31 13:58:58 itojun Exp $ .\" .TH TCPDMATCH 8 .SH NAME @@ -98,3 +98,8 @@ Eindhoven University of Technology Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands \" @(#) tcpdmatch.8 1.5 96/02/11 17:01:35 +.SH BUGS +If you specify FQDN hostname as client, +they will be recognized only as IPv4 or IPv6 address, +which should be recognized as both. +This should be solved when getipnodebyname(3) is supplied. diff --git a/usr.sbin/tcpdmatch/tcpdmatch.c b/usr.sbin/tcpdmatch/tcpdmatch.c index c32d5d4a4de1..34c7ec9de05a 100644 --- a/usr.sbin/tcpdmatch/tcpdmatch.c +++ b/usr.sbin/tcpdmatch/tcpdmatch.c @@ -1,4 +1,4 @@ -/* $NetBSD: tcpdmatch.c,v 1.5 1999/05/09 16:06:33 christos Exp $ */ +/* $NetBSD: tcpdmatch.c,v 1.6 1999/08/31 13:58:58 itojun Exp $ */ /* * tcpdmatch - explain what tcpd would do in a specific case @@ -20,7 +20,7 @@ #if 0 static char sccsid[] = "@(#) tcpdmatch.c 1.5 96/02/11 17:01:36"; #else -__RCSID("$NetBSD: tcpdmatch.c,v 1.5 1999/05/09 16:06:33 christos Exp $"); +__RCSID("$NetBSD: tcpdmatch.c,v 1.6 1999/08/31 13:58:58 itojun Exp $"); #endif #endif @@ -75,9 +75,14 @@ char **argv; int ch; char *inetcf = 0; int count; - struct sockaddr_in server_sin; - struct sockaddr_in client_sin; + struct sockaddr_storage server_sin; + struct sockaddr_storage client_sin; struct stat st; + char *ap; + int alen; +#ifdef INET6 + struct sockaddr_in6 in6; +#endif /* * Show what rule actually matched. @@ -180,12 +185,25 @@ char **argv; if ((hp = find_inet_addr(server)) == 0) exit(1); memset((char *) &server_sin, 0, sizeof(server_sin)); - server_sin.sin_family = AF_INET; + 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 in_addr); + break; +#ifdef INET6 + case AF_INET6: + ap = (char *)&((struct sockaddr_in6 *)&server_sin)->sin6_addr; + alen = sizeof(struct in6_addr); + break; +#endif + default: + exit(1); + } request_set(&request, RQ_SERVER_SIN, &server_sin, 0); for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) { - memcpy((char *) &server_sin.sin_addr, addr, - sizeof(server_sin.sin_addr)); + memcpy(ap, addr, alen); /* * Force evaluation of server host name and address. Host name @@ -215,6 +233,13 @@ char **argv; tcpdmatch(&request); exit(0); } +#ifdef INET6 + if (inet_pton(AF_INET6, client, &in6) == 1) { + request_set(&request, RQ_CLIENT_ADDR, client, 0); + tcpdmatch(&request); + exit(0); + } +#endif /* * Perhaps they are testing special client hostname patterns that aren't @@ -237,12 +262,25 @@ char **argv; if ((hp = find_inet_addr(client)) == 0) exit(1); memset((char *) &client_sin, 0, sizeof(client_sin)); - client_sin.sin_family = AF_INET; + 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 in_addr); + break; +#ifdef INET6 + case AF_INET6: + ap = (char *)&((struct sockaddr_in6 *)&client_sin)->sin6_addr; + alen = sizeof(struct in6_addr); + break; +#endif + default: + exit(1); + } request_set(&request, RQ_CLIENT_SIN, &client_sin, 0); for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) { - memcpy((char *) &client_sin.sin_addr, addr, - sizeof(client_sin.sin_addr)); + memcpy(ap, addr, alen); /* * Force evaluation of client host name and address. Host name