Subject: libwrap change for IPv6
To: None <tech-net@netbsd.org>
From: None <itojun@iijlab.net>
List: tech-net
Date: 08/11/1999 23:48:28
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <13412.934382891.1@coconut.itojun.org>
Content-Transfer-Encoding: 7bit

	I've made a patch for IPv6 support in libwrap.  This is based on
	NetBSD 1.4 code (hence tcp_wrapper 7.4), and should be easily applied
	to NetBSD-current code.  This involves following changes:
	- IPv6 addresses on getpeername() will be handled correctly.
	  This is done by changing sockaddr_in to sockaddr_storage or sockaddr
	  as necessary.
	- you can wrap numeric addresses by square bracket, to avoid
	  colon issue (used as separator for /etc/hosts.{allow,deny}).
	- now it depends on more recent API functions like inet_pton().
	- API change: s/struct sockaddr_in */struct sockaddr */ in struct
	  host_info.

	A line in /etc/hosts.allow will look like this:
		telnetd: 127.0.0.1/255.255.255.255 [::1/128] [3ffe::/ffff::]
	now prefixlen is allowed for IPv6 case, for obvious reasons.

	There are other patch available on the net but they change separator
	from colon to pipe sign, so it makes /etc/hosts.allow incompatible
	with previous installations.  I thought we should not impact
	compatibility with other systems so I used square brackets.

	The patch is attached below.  Please comment before I commit it
	into the repository.
	Of course, I'll be submitting this to Wietse for the merge (for
	latest tcp_wrapper), but due to the last two items I may need to
	do more for portability (but I hate to reimplement inet_pton by
	myself).

itojun

------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <13412.934382891.2@coconut.itojun.org>
Content-Transfer-Encoding: 7bit

? hosts_access.po
? options.po
? shell_cmd.po
? rfc931.po
? eval.po
? hosts_ctl.po
? refuse.po
? percent_x.po
? clean_exit.po
? fix_options.po
? socket.po
? workarounds.po
? update.po
? misc.po
? diag.po
? hosts_access.cat3
? hosts_access.cat5
? hosts_options.cat5
Index: Makefile
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/lib/libwrap/Makefile,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -r1.1.1.1 -r1.2
*** Makefile	1999/08/11 08:16:05	1.1.1.1
--- Makefile	1999/08/11 12:18:15	1.2
***************
*** 15,20 ****
--- 15,22 ----
  INCS= tcpd.h
  INCSDIR=/usr/include
  
+ MKPIC=	no
+ 
  .include "Makefile.cflags"
  
  .include <bsd.lib.mk>
Index: Makefile.cflags
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/lib/libwrap/Makefile.cflags,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -r1.1.1.1 -r1.2
*** Makefile.cflags	1999/08/11 08:16:05	1.1.1.1
--- Makefile.cflags	1999/08/11 12:18:15	1.2
***************
*** 11,13 ****
--- 11,15 ----
  # we don't want to use it in wrapper-related utilities (such as
  # tcpdmatch) that include this file.
  #CPPFLAGS+=-DPARANOID
+ 
+ CPPFLAGS+=-Dss_family=__ss_family -Dss_len=__ss_len -DINET6
Index: fix_options.c
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/lib/libwrap/fix_options.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -r1.1.1.1 -r1.2
*** fix_options.c	1999/08/11 08:16:05	1.1.1.1
--- fix_options.c	1999/08/11 14:15:07	1.2
***************
*** 40,45 ****
--- 40,56 ----
      struct protoent *ip;
      int     fd = request->fd;
      int     len = sizeof lbuf;
+     struct sockaddr_storage ss;
+     int sslen;
+ 
+     /* check if this is AF_INET socket */
+     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;
Index: hosts_access.c
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/lib/libwrap/hosts_access.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -c -r1.1.1.1 -r1.3
*** hosts_access.c	1999/08/11 08:16:05	1.1.1.1
--- hosts_access.c	1999/08/11 14:34:41	1.3
***************
*** 46,51 ****
--- 46,54 ----
  #include <netgroup.h>
  #include <rpcsvc/ypclnt.h>
  #endif
+ #ifdef INET6
+ #include <sys/socket.h>
+ #endif
  
  extern int errno;
  
***************
*** 96,101 ****
--- 99,107 ----
  static int rbl_match __P((char *, char *));
  static int string_match __P((char *, char *));
  static int masked_match __P((char *, char *, char *));
+ #ifdef INET6
+ static int masked_match6 __P((char *, char *, char *));
+ #endif
  
  /* Size of logical line buffer. */
  
***************
*** 201,206 ****
--- 207,213 ----
  int   (*match_fn) __P((char *, struct request_info *));
  {
      char   *tok;
+     int l;
  
      /*
       * Process tokens one at a time. We have exhausted all possible matches
***************
*** 212,217 ****
--- 219,229 ----
      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 */ ;
***************
*** 289,295 ****
      } else if (strncmp(tok, "{RBL}.", 6) == 0) { /* RBL lookup in domain */
  	return rbl_match(tok+6, eval_hostaddr(host));
      } else if ((mask = split_at(tok, '/')) != 0) {	/* net/mask */
! 	return (masked_match(tok, mask, eval_hostaddr(host)));
      } else {					/* anything else */
  	return (string_match(tok, eval_hostaddr(host))
  	    || (NOT_INADDR(tok) && string_match(tok, eval_hostname(host))));
--- 301,308 ----
      } else if (strncmp(tok, "{RBL}.", 6) == 0) { /* RBL lookup in domain */
  	return rbl_match(tok+6, eval_hostaddr(host));
      } else if ((mask = split_at(tok, '/')) != 0) {	/* net/mask */
! 	return (masked_match(tok, mask, eval_hostaddr(host))
! 	    || masked_match6(tok, mask, eval_hostaddr(host)));
      } else {					/* anything else */
  	return (string_match(tok, eval_hostaddr(host))
  	    || (NOT_INADDR(tok) && string_match(tok, eval_hostname(host))));
***************
*** 380,382 ****
--- 393,439 ----
      }
      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;
+     struct in6_addr mask;
+     struct in6_addr addr;
+     int masklen;
+     int fail;
+     int i;
+ 
+     if (inet_pton(AF_INET6, string, &addr) != 1)
+ 	return (NO);
+     fail = 0;
+     if (inet_pton(AF_INET6, net_tok, &net) != 1)
+ 	fail++;
+     if (strchr(mask_tok, ':') == NULL) {
+ 	masklen = atoi(mask_tok);
+ 	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 (inet_pton(AF_INET6, mask_tok, &mask) != 1)
+ 	    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
Index: misc.c
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/lib/libwrap/misc.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -r1.1.1.1 -r1.2
*** misc.c	1999/08/11 08:16:05	1.1.1.1
--- misc.c	1999/08/11 14:15:08	1.2
***************
*** 61,71 ****
--- 61,96 ----
  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;
+     return cp;
+ #endif
  }
  
  /* dot_quad_addr - convert dotted quad to internal form */
Index: rfc931.c
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/lib/libwrap/rfc931.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -c -r1.1.1.1 -r1.3
*** rfc931.c	1999/08/11 08:16:06	1.1.1.1
--- rfc931.c	1999/08/11 14:15:08	1.3
***************
*** 80,104 ****
  /* 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;
  char   *dest;
  {
      unsigned rmt_port;
      unsigned our_port;
!     struct sockaddr_in rmt_query_sin;
!     struct sockaddr_in our_query_sin;
      char    user[256];			/* XXX */
      char    buffer[512];		/* XXX */
      char   *cp;
      char   *result = unknown;
      FILE   *fp;
  
  #ifdef __GNUC__
      (void)&result; /* Avoid longjmp clobbering */
      (void)&fp;	/* XXX gcc */
  #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
--- 80,126 ----
  /* rfc931 - return remote user name, given socket structures */
  
  void    rfc931(rmt_sin, our_sin, dest)
! struct sockaddr *rmt_sin;
! struct sockaddr *our_sin;
  char   *dest;
  {
      unsigned rmt_port;
      unsigned our_port;
!     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;
  
  #ifdef __GNUC__
      (void)&result; /* Avoid longjmp clobbering */
      (void)&fp;	/* XXX gcc */
  #endif
  
+     /* 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);
+ 	break;
+ #ifdef INET6
+     case AF_INET6:
+ 	salen = sizeof(struct sockaddr_in6);
+ 	break;
+ #endif
+     default:
+ 	STRN_CPY(dest, result, STRING_LENGTH);
+ 	return;
+     }
+ 
      /*
       * 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
***************
*** 109,115 ****
       * sockets.
       */
  
!     if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
  	setbuf(fp, (char *) 0);
  
  	/*
--- 131,137 ----
       * sockets.
       */
  
!     if ((fp = fsocket(rmt_sin->sa_family, SOCK_STREAM, 0)) != 0) {
  	setbuf(fp, (char *) 0);
  
  	/*
***************
*** 129,143 ****
  	     * 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);
  
  	    if (bind(fileno(fp), (struct sockaddr *) & our_query_sin,
! 		     sizeof(our_query_sin)) >= 0 &&
  		connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
! 			sizeof(rmt_query_sin)) >= 0) {
  
  		/*
  		 * Send query to server. Neglect the risk that a 13-byte
--- 151,185 ----
  	     * addresses from the query socket.
  	     */
  
! 	    memcpy(&our_query_sin, our_sin, salen);
! 	    switch (our_query_sin.ss_family) {
! 	    case AF_INET:
! 		our_portp = &((struct sockaddr_in *)&our_query_sin)->sin_port;
! 		break;
! #ifdef INET6
! 	    case AF_INET6:
! 		our_portp = &((struct sockaddr_in6 *)&our_query_sin)->sin6_port;
! 		break;
! #endif
! 	    }
! 	    *rmt_portp = htons(ANY_PORT);
! 	    memcpy(&rmt_query_sin, rmt_sin, salen);
! 	    switch (rmt_query_sin.ss_family) {
! 	    case AF_INET:
! 		rmt_portp = &((struct sockaddr_in *)&rmt_query_sin)->sin_port;
! 		break;
! #ifdef INET6
! 	    case AF_INET6:
! 		rmt_portp = &((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port;
! 		break;
! #endif
! 	    }
! 	    *rmt_portp = htons(RFC931_PORT);
  
  	    if (bind(fileno(fp), (struct sockaddr *) & our_query_sin,
! 		     salen) >= 0 &&
  		connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
! 			salen) >= 0) {
  
  		/*
  		 * Send query to server. Neglect the risk that a 13-byte
***************
*** 146,153 ****
  		 */
  
  		fprintf(fp, "%u,%u\r\n",
! 			ntohs(rmt_sin->sin_port),
! 			ntohs(our_sin->sin_port));
  		fflush(fp);
  
  		/*
--- 188,195 ----
  		 */
  
  		fprintf(fp, "%u,%u\r\n",
! 			ntohs(*rmt_portp),
! 			ntohs(*our_portp));
  		fflush(fp);
  
  		/*
***************
*** 161,168 ****
  		    && 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) {
  
  		    /*
  		     * Strip trailing carriage return. It is part of the
--- 203,210 ----
  		    && ferror(fp) == 0 && feof(fp) == 0
  		    && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
  			      &rmt_port, &our_port, user) == 3
! 		    && ntohs(*rmt_portp) == rmt_port
! 		    && ntohs(*our_portp) == our_port) {
  
  		    /*
  		     * Strip trailing carriage return. It is part of the
Index: socket.c
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/lib/libwrap/socket.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -c -r1.1.1.1 -r1.3
*** socket.c	1999/08/11 08:16:06	1.1.1.1
--- socket.c	1999/08/11 14:15:08	1.3
***************
*** 81,88 ****
  void    sock_host(request)
  struct request_info *request;
  {
!     static struct sockaddr_in client;
!     static struct sockaddr_in server;
      int     len;
      char    buf[BUFSIZ];
      int     fd = request->fd;
--- 81,88 ----
  void    sock_host(request)
  struct request_info *request;
  {
!     static struct sockaddr_storage client;
!     static struct sockaddr_storage server;
      int     len;
      char    buf[BUFSIZ];
      int     fd = request->fd;
***************
*** 96,101 ****
--- 96,103 ----
       * 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,117 ****
  	memset(buf, 0 sizeof(buf));
  #endif
      }
!     request->client->sin = &client;
  
      /*
       * Determine the server binding. This is used for client username
--- 113,119 ----
  	memset(buf, 0 sizeof(buf));
  #endif
      }
!     request->client->sin = (struct sockaddr *)&client;
  
      /*
       * Determine the server binding. This is used for client username
***************
*** 124,130 ****
  	tcpd_warn("getsockname: %m");
  	return;
      }
!     request->server->sin = &server;
  }
  
  /* sock_hostaddr - map endpoint address to printable form */
--- 126,132 ----
  	tcpd_warn("getsockname: %m");
  	return;
      }
!     request->server->sin = (struct sockaddr *)&server;
  }
  
  /* sock_hostaddr - map endpoint address to printable form */
***************
*** 132,141 ****
  void    sock_hostaddr(host)
  struct host_info *host;
  {
!     struct sockaddr_in *sin = host->sin;
  
!     if (sin != 0)
! 	STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr));
  }
  
  /* sock_hostname - map endpoint address to host name */
--- 134,159 ----
  void    sock_hostaddr(host)
  struct host_info *host;
  {
!     struct sockaddr *sa = host->sin;
!     int salen;
  
!     if (!sa)
! 	return;
!     switch (sa->sa_family) {
!     case AF_INET:
! 	salen = sizeof(struct sockaddr_in);
! 	break;
! #ifdef INET6
!     case AF_INET6:
! 	salen = sizeof(struct sockaddr_in6);
! 	break;
! #endif
!     default:
! 	salen = sizeof(struct sockaddr);
! 	break;
!     }
!     getnameinfo(sa, salen, host->addr, sizeof(host->addr), NULL, 0,
! 	NI_NUMERICHOST);
  }
  
  /* sock_hostname - map endpoint address to host name */
***************
*** 143,151 ****
  void    sock_hostname(host)
  struct host_info *host;
  {
!     struct sockaddr_in *sin = host->sin;
      struct hostent *hp;
      int     i;
  
      /*
       * On some systems, for example Solaris 2.3, gethostbyaddr(0.0.0.0) does
--- 161,172 ----
  void    sock_hostname(host)
  struct host_info *host;
  {
!     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,162 ****
       * 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) {
  
  	STRN_CPY(host->name, hp->h_name, sizeof(host->name));
  
--- 175,200 ----
       * have to special-case 0.0.0.0, in order to avoid false alerts from the
       * host name/address checking code below.
       */
!     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:
! 	/* XXX more special cases? */
! 	ap = (char *)&((struct sockaddr_in6 *)sin)->sin6_addr;
! 	alen = sizeof(struct in6_addr);
! 	break;
! #endif
!     defalut:
! 	return;
!     }
!     if ((hp = gethostbyaddr(ap, alen, af)) != 0) {
  
  	STRN_CPY(host->name, hp->h_name, sizeof(host->name));
  
***************
*** 173,179 ****
  	 * we're in big trouble anyway.
  	 */
  
! 	if ((hp = gethostbyname(host->name)) == 0) {
  
  	    /*
  	     * Unable to verify that the host name matches the address. This
--- 211,217 ----
  	 * we're in big trouble anyway.
  	 */
  
! 	if ((hp = gethostbyname2(host->name, af)) == 0) {
  
  	    /*
  	     * Unable to verify that the host name matches the address. This
***************
*** 205,213 ****
  	     */
  
  	    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)
  		    return;			/* name is good, keep it */
  	    }
  
--- 243,249 ----
  	     */
  
  	    for (i = 0; hp->h_addr_list[i]; i++) {
! 		if (memcmp(hp->h_addr_list[i], (char *) ap, alen) == 0)
  		    return;			/* name is good, keep it */
  	    }
  
***************
*** 218,224 ****
  	     */
  
  	    tcpd_warn("host name/address mismatch: %s != %s",
! 		      inet_ntoa(sin->sin_addr), hp->h_name);
  	}
  	/* name is bad, clobber it */
  	(void)strncpy(host->name, paranoid, sizeof(host->name) - 1);
--- 254,260 ----
  	     */
  
  	    tcpd_warn("host name/address mismatch: %s != %s",
! 		      inet_ntop(af, ap, hbuf, sizeof(hbuf)), hp->h_name);
  	}
  	/* name is bad, clobber it */
  	(void)strncpy(host->name, paranoid, sizeof(host->name) - 1);
***************
*** 231,237 ****
  int     fd;
  {
      char    buf[BUFSIZ];
!     struct sockaddr_in sin;
      int     size = sizeof(sin);
  
      /*
--- 267,273 ----
  int     fd;
  {
      char    buf[BUFSIZ];
!     struct sockaddr_storage sin;
      int     size = sizeof(sin);
  
      /*
Index: tcpd.h
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/lib/libwrap/tcpd.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -r1.1.1.1 -r1.2
*** tcpd.h	1999/08/11 08:16:06	1.1.1.1
--- tcpd.h	1999/08/11 12:18:16	1.2
***************
*** 12,18 ****
  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 t_unitdata *unit;		/* TLI transport address or 0 */
      struct request_info *request;	/* for shared information */
  };
--- 12,18 ----
  struct host_info {
      char    name[STRING_LENGTH];	/* access via eval_hostname(host) */
      char    addr[STRING_LENGTH];	/* access via eval_hostaddr(host) */
!     struct sockaddr *sin;		/* socket address or 0 */
      struct t_unitdata *unit;		/* TLI transport address or 0 */
      struct request_info *request;	/* for shared information */
  };
***************
*** 81,87 ****
  extern char *percent_x			/* do %<char> 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 *));
  extern void clean_exit			/* clean up and exit */
  		__P((struct request_info *));
  extern void refuse			/* clean up and exit */
--- 81,87 ----
  extern char *percent_x			/* do %<char> expansion */
  		__P((char *, int, char *, struct request_info *));
  extern void rfc931			/* client name from RFC 931 daemon */
! 		__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 */
Index: update.c
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/lib/libwrap/update.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -r1.1.1.1 -r1.2
*** update.c	1999/08/11 08:16:06	1.1.1.1
--- update.c	1999/08/11 12:18:17	1.2
***************
*** 56,65 ****
  	    request->fd = va_arg(ap, int);
  	    continue;
  	case RQ_CLIENT_SIN:
! 	    request->client->sin = va_arg(ap, struct sockaddr_in *);
  	    continue;
  	case RQ_SERVER_SIN:
! 	    request->server->sin = va_arg(ap, struct sockaddr_in *);
  	    continue;
  
  	    /*
--- 56,65 ----
  	    request->fd = va_arg(ap, int);
  	    continue;
  	case RQ_CLIENT_SIN:
! 	    request->client->sin = va_arg(ap, struct sockaddr *);
  	    continue;
  	case RQ_SERVER_SIN:
! 	    request->server->sin = va_arg(ap, struct sockaddr *);
  	    continue;
  
  	    /*
Index: workarounds.c
===================================================================
RCS file: /cvsroot/kame/kame/netbsd/lib/libwrap/workarounds.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -r1.1.1.1 -r1.2
*** workarounds.c	1999/08/11 08:16:06	1.1.1.1
--- workarounds.c	1999/08/11 14:15:09	1.2
***************
*** 141,150 ****
  
      if ((ret = recvfrom(sock, buf, buflen, flags, from, fromlen)) >= 0) {
  	if (from->sa_family == 0) {
! 	    struct sockaddr my_addr;
  	    int     my_addr_len = sizeof(my_addr);
  
! 	    if (getsockname(0, &my_addr, &my_addr_len)) {
  		tcpd_warn("getsockname: %m");
  	    } else {
  		from->sa_family = my_addr.sa_family;
--- 141,150 ----
  
      if ((ret = recvfrom(sock, buf, buflen, flags, from, fromlen)) >= 0) {
  	if (from->sa_family == 0) {
! 	    struct sockaddr_storage my_addr;
  	    int     my_addr_len = sizeof(my_addr);
  
! 	    if (getsockname(0, (struct sockaddr *)&my_addr, &my_addr_len)) {
  		tcpd_warn("getsockname: %m");
  	    } else {
  		from->sa_family = my_addr.sa_family;

------- =_aaaaaaaaaa0--