Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: IPv6 support in zftp



IPv6 support in zftp.  The IPv6-specific code *should* work, but it
isn't properly tested because I don't have an IPv6-capable ftp server.
(Or an IPv6-capable *anything* server, for that matter, but that's a
separate project in the works.)

There's a bit of ugliness involved in trying to support IPv6 when we can't
be sure that the IPv6 interfaces will work at run time.  For example,
Linux 2.2 by default configures with IPv6 disabled, but of course all
the structures are there in the headers anyway.  So rather than use
only IPv6 sockets, as RFC 2553 would have us do, we first try using an
IPv6 socket for IPv6-only addresses, and then if that fails then we try
using an IPv4 socket for IPv4 addresses.  Once we have a connection,
all future sockets created for that session use the same protocol.

IPv6 support is conditional upon having AF_INET6 and IN6ADDR_LOOPBACK_INIT
defined.  The latter isn't actually required, it's just the easiest
way to test for the existence of struct sockaddr_in6, which is the
real requirement.  inet_ntop() and inet_pton() are also required to
support IPv6, since we need the capability to convert IPv6 addresses in
both directions.

The code is flexible about host name lookup functions.  If RFC
2553's getipnodebyname() isn't available (I have yet to see a full
implementation), it can simulate it using RFC 2133's gethostbyname2().
If that's not available either, then you can't have IPv6 host name
lookups, but you can still use IPv6 addresses directly and you still
get IPv4 host name lookups.

-zefram

diff -cr zsh-/Src/Modules/zftp.c Src/Modules/zftp.c
*** zsh-/Src/Modules/zftp.c	Tue Nov 23 23:47:29 1999
--- Src/Modules/zftp.c	Wed Nov 24 04:27:29 1999
***************
*** 42,48 ****
--- 42,51 ----
   */
  
  /* needed in prototypes for statics */
+ struct hostent;
  struct sockaddr_in;
+ struct sockaddr_in6;
+ union zftp_sockaddr;
  struct zftp_session;
  typedef struct zftp_session *Zftp_session;
  
***************
*** 71,81 ****
  # undef HAVE_POLL
  #endif
  
! /* pinch the definition from <netinet/in.h> for deficient headers */
! #ifndef INADDR_NONE
! # define INADDR_NONE 0xffffffff
  #endif
  
  /*
   * For FTP block mode
   *
--- 74,205 ----
  # undef HAVE_POLL
  #endif
  
! /* Is IPv6 supported by the library? */
! 
! #if defined(AF_INET6) && defined(IN6ADDR_LOOPBACK_INIT) \
! 	&& defined(HAVE_INET_NTOP) && defined(HAVE_INET_PTON)
! # define SUPPORT_IPV6 1
! #endif
! 
! union zftp_sockaddr {
! 	struct sockaddr a;
! 	struct sockaddr_in in;
! #ifdef SUPPORT_IPV6
! 	struct sockaddr_in6 in6;
! #endif
! };
! 
! /* We use the RFC 2553 interfaces.  If the functions don't exist in the library,
!    simulate them. */
! 
! #ifndef INET_ADDRSTRLEN
! # define INET_ADDRSTRLEN 16
  #endif
  
+ #ifndef INET6_ADDRSTRLEN
+ # define INET6_ADDRSTRLEN 46
+ #endif
+ 
+ /**/  
+ #ifndef HAVE_INET_NTOP
+ 
+ /**/    
+ static char const *
+ inet_ntop(int af, void const *cp, char *buf, size_t len)
+ {       
+         if(af != AF_INET) {
+                 errno = EAFNOSUPPORT;
+                 return NULL;
+         } 
+         if(len < INET_ADDRSTRLEN) {
+                 errno = ENOSPC;
+                 return NULL;
+         }
+         strcpy(buf, inet_ntoa(*(struct in_addr *)cp));
+         return buf;
+ }
+ 
+ /**/  
+ #endif /* !HAVE_INET_NTOP */
+ 
+ /**/
+ #ifndef HAVE_INET_PTON
+ 
+ /**/
+ static int
+ inet_pton(int af, char const *src, void *dst)
+ {
+         if(af != AF_INET) {
+                 errno = EAFNOSUPPORT;
+                 return -1;
+         }
+         return !!inet_aton(src, dst);
+ }
+ 
+ /**/
+ #endif /* !HAVE_INET_PTON */
+ 
+ /**/
+ #ifndef HAVE_GETIPNODEBYNAME
+ 
+ /* note: this is not a complete implementation.  If ignores the flags,
+    and does not provide the memory allocation of the standard interface.
+    Each returned structure will overwrite the previous one. */
+ 
+ /**/
+ static struct hostent *
+ getipnodebyname(char const *name, int af, int flags, int *errorp)
+ {
+ 	static struct hostent ahe;
+ 	static char nbuf[16];
+ 	static char *addrlist[] = { nbuf, NULL };
+ # ifdef SUPPORT_IPV6
+ 	static char pbuf[INET6_ADDRSTRLEN];
+ # else
+ 	static char pbuf[INET_ADDRSTRLEN];
+ # endif
+ 	struct hostent *he;
+ 	if(inet_pton(af, name, nbuf) == 1) {
+ 		inet_ntop(af, nbuf, pbuf, sizeof(pbuf));
+ 		ahe.h_name = pbuf;
+ 		ahe.h_aliases = addrlist+1;
+ 		ahe.h_addrtype = af;
+ 		ahe.h_length = (af == AF_INET) ? 4 : 16;
+ 		ahe.h_addr_list = addrlist;
+ 		return &ahe;
+ 	}
+ 	he = gethostbyname2(name, af);
+ 	if(!he)
+ 		*errorp = h_errno;
+ 	return he;
+ }
+ 
+ /**/
+ # ifndef HAVE_GETHOSTBYNAME2
+ 
+ /**/
+ static struct hostent *
+ gethostbyname2(char const *name, int af)
+ {
+ 	if(af != AF_INET) {
+ 		h_errno = NO_RECOVERY;
+ 		return NULL;
+ 	}
+ 	return gethostbyname(name);
+ }
+ 
+ /**/
+ # endif /* !HAVE_GETHOSTBYNAME2 */
+ 
+ /**/
+ static void
+ freehostent(struct hostent *ptr)
+ {
+ }
+ 
+ /**/
+ #endif /* !HAVE_GETIPNODEBYNAME */
+ 
  /*
   * For FTP block mode
   *
***************
*** 292,298 ****
      char **userparams;		/* user parameters set by zftp_params */
      int cfd;			/* control file descriptor */
      FILE *cin;			/* control input file */
!     struct sockaddr_in sock;	/* the socket for the control connection */
      int dfd;			/* data connection */
      int has_size;		/* understands SIZE? */
      int has_mdtm;		/* understands MDTM? */
--- 416,423 ----
      char **userparams;		/* user parameters set by zftp_params */
      int cfd;			/* control file descriptor */
      FILE *cin;			/* control input file */
!     union zftp_sockaddr sock;	/* this end of the control connection */
!     union zftp_sockaddr peer;	/* far end of the control connection */
      int dfd;			/* data connection */
      int has_size;		/* understands SIZE? */
      int has_mdtm;		/* understands MDTM? */
***************
*** 846,852 ****
  
  /**/
  static int
! zfopendata(char *name, struct sockaddr_in *zdsockp, int *is_passivep)
  {
      if (!(zfprefs & (ZFPF_SNDP|ZFPF_PASV))) {
  	zwarnnam(name, "Must set preference S or P to transfer data", NULL, 0);
--- 971,977 ----
  
  /**/
  static int
! zfopendata(char *name, union zftp_sockaddr *zdsockp, int *is_passivep)
  {
      if (!(zfprefs & (ZFPF_SNDP|ZFPF_PASV))) {
  	zwarnnam(name, "Must set preference S or P to transfer data", NULL, 0);
***************
*** 858,872 ****
  	return 1;
      }
  
-     *zdsockp = zfsess->sock;
-     zdsockp->sin_family = AF_INET;
- 
      if (!(zfstatusp[zfsessno] & ZFST_NOPS) && (zfprefs & ZFPF_PASV)) {
! 	char *ptr;
! 	int i, nums[6], err;
! 	unsigned char iaddr[4], iport[2];
  
! 	if (zfsendcmd("PASV\r\n") == 6)
  	    return 1;
  	else if (lastcode >= 500 && lastcode <= 504) {
  	    /*
--- 983,999 ----
  	return 1;
      }
  
      if (!(zfstatusp[zfsessno] & ZFST_NOPS) && (zfprefs & ZFPF_PASV)) {
! 	char *psv_cmd;
! 	int err, salen;
  
! #ifdef SUPPORT_IPV6
! 	if(zfsess->peer.a.sa_family == AF_INET6)
! 	    psv_cmd = "EPSV\r\n";
! 	else
! #endif /* SUPPORT_IPV6 */
! 	    psv_cmd = "PASV\r\n";
! 	if (zfsendcmd(psv_cmd) == 6)
  	    return 1;
  	else if (lastcode >= 500 && lastcode <= 504) {
  	    /*
***************
*** 877,908 ****
  	    zfclosedata();
  	    return zfopendata(name, zdsockp, is_passivep);
  	}
! 	/*
! 	 * OK, now we need to know what port we're looking at,
! 	 * which is cunningly concealed in the reply.
! 	 * lastmsg already has the reply code expunged.
! 	 */
! 	for (ptr = lastmsg; *ptr; ptr++)
! 	    if (isdigit(STOUC(*ptr)))
! 		break;
! 	if (sscanf(ptr, "%d,%d,%d,%d,%d,%d",
! 		   nums, nums+1, nums+2, nums+3, nums+4, nums+5) != 6) {
! 	    zwarnnam(name, "bad response to PASV: %s", lastmsg, 0);
! 	    zfclosedata();
! 	    return 1;
! 	}
! 	for (i = 0; i < 4; i++)
! 	    iaddr[i] = STOUC(nums[i]);
! 	iport[0] = STOUC(nums[4]);
! 	iport[1] = STOUC(nums[5]);
  
! 	memcpy(&zdsockp->sin_addr, iaddr, sizeof(iaddr));
! 	memcpy(&zdsockp->sin_port, iport, sizeof(iport));
  
  	/* we should timeout this connect */
  	do {
! 	    err = connect(zfsess->dfd,
! 			  (struct sockaddr *)zdsockp, sizeof(*zdsockp));
  	} while (err && errno == EINTR && !errflag);
  
  	if (err) {
--- 1004,1076 ----
  	    zfclosedata();
  	    return zfopendata(name, zdsockp, is_passivep);
  	}
! 	zdsockp->a.sa_family = zfsess->peer.a.sa_family;
! #ifdef SUPPORT_IPV6
! 	if(zfsess->peer.a.sa_family == AF_INET6) {
! 	    /* see RFC 2428 for explanation */
! 	    char const *ptr, *end;
! 	    char delim, portbuf[6], *pbp;
! 	    unsigned long portnum;
! 	    ptr = strchr(lastmsg, '(');
! 	    if(!ptr) {
! 	    bad_epsv:
! 		zwarnnam(name, "bad response to EPSV: %s", lastmsg, 0);
! 		zfclosedata();
! 		return 1;
! 	    }
! 	    delim = ptr[1];
! 	    if(delim < 33 || delim > 126 || ptr[2] != delim || ptr[3] != delim)
! 		goto bad_epsv;
! 	    ptr += 3;
! 	    end = strchr(ptr, delim);
! 	    if(!end || end[1] != ')')
! 		goto bad_epsv;
! 	    while(ptr != end && *ptr == '0')
! 		ptr++;
! 	    if(ptr == end || (end-ptr) > 5 || !isdigit(STOUC(*ptr)))
! 		goto bad_epsv;
! 	    memcpy(portbuf, ptr, (end-ptr));
! 	    portbuf[end-ptr] = 0;
! 	    portnum = strtoul(portbuf, &pbp, 10);
! 	    if(*pbp || portnum > 65535UL)
! 		goto bad_epsv;
! 	    *zdsockp = zfsess->peer;
! 	    zdsockp->in6.sin6_port = htons((unsigned)portnum);
! 	    salen = sizeof(struct sockaddr_in6);
! 	} else
! #endif /* SUPPORT_IPV6 */
! 	{
! 	    char *ptr;
! 	    int i, nums[6];
! 	    unsigned char iaddr[4], iport[2];
  
! 	    /*
! 	     * OK, now we need to know what port we're looking at,
! 	     * which is cunningly concealed in the reply.
! 	     * lastmsg already has the reply code expunged.
! 	     */
! 	    for (ptr = lastmsg; *ptr; ptr++)
! 		if (isdigit(STOUC(*ptr)))
! 		    break;
! 	    if (sscanf(ptr, "%d,%d,%d,%d,%d,%d",
! 		       nums, nums+1, nums+2, nums+3, nums+4, nums+5) != 6) {
! 		zwarnnam(name, "bad response to PASV: %s", lastmsg, 0);
! 		zfclosedata();
! 		return 1;
! 	    }
! 	    for (i = 0; i < 4; i++)
! 		iaddr[i] = STOUC(nums[i]);
! 	    iport[0] = STOUC(nums[4]);
! 	    iport[1] = STOUC(nums[5]);
! 
! 	    memcpy(&zdsockp->in.sin_addr, iaddr, sizeof(iaddr));
! 	    memcpy(&zdsockp->in.sin_port, iport, sizeof(iport));
! 	    salen = sizeof(struct sockaddr_in);
! 	}
  
  	/* we should timeout this connect */
  	do {
! 	    err = connect(zfsess->dfd, (struct sockaddr *)zdsockp, salen);
  	} while (err && errno == EINTR && !errflag);
  
  	if (err) {
***************
*** 913,920 ****
  
  	*is_passivep = 1;
      } else {
  	char portcmd[40];
! 	unsigned char *addr, *port;
  	int ret, len;
  
  	if (!(zfprefs & ZFPF_SNDP)) {
--- 1081,1091 ----
  
  	*is_passivep = 1;
      } else {
+ #ifdef SUPPORT_IPV6
+ 	char portcmd[8+INET6_ADDRSTRLEN+9];
+ #else
  	char portcmd[40];
! #endif
  	int ret, len;
  
  	if (!(zfprefs & ZFPF_SNDP)) {
***************
*** 922,932 ****
  	    return 1;
  	}
  
! 	zdsockp->sin_port = 0;	/* to be set by bind() */
! 	len = sizeof(*zdsockp);
  	/* need to do timeout stuff and probably handle EINTR here */
! 	if (bind(zfsess->dfd, (struct sockaddr *)zdsockp,
! 		 sizeof(*zdsockp)) < 0)
  	    ret = 1;
  	else if (getsockname(zfsess->dfd, (struct sockaddr *)zdsockp,
  			     &len) < 0)
--- 1093,1111 ----
  	    return 1;
  	}
  
! 	*zdsockp = zfsess->sock;
! #ifdef SUPPORT_IPV6
! 	if(zdsockp->a.sa_family == AF_INET6) {
! 	    zdsockp->in6.sin6_port = 0;	/* to be set by bind() */
! 	    len = sizeof(struct sockaddr_in6);
! 	} else
! #endif /* SUPPORT_IPV6 */
! 	{
! 	    zdsockp->in.sin_port = 0;	/* to be set by bind() */
! 	    len = sizeof(struct sockaddr_in);
! 	}
  	/* need to do timeout stuff and probably handle EINTR here */
! 	if (bind(zfsess->dfd, (struct sockaddr *)zdsockp, len) < 0)
  	    ret = 1;
  	else if (getsockname(zfsess->dfd, (struct sockaddr *)zdsockp,
  			     &len) < 0)
***************
*** 944,953 ****
  	    return 1;
  	}
  
! 	addr = (unsigned char *) &zdsockp->sin_addr;
! 	port = (unsigned char *) &zdsockp->sin_port;
! 	sprintf(portcmd, "PORT %d,%d,%d,%d,%d,%d\r\n",
! 		addr[0],addr[1],addr[2],addr[3],port[0],port[1]);
  	if (zfsendcmd(portcmd) >= 5) {
  	    zwarnnam(name, "port command failed", NULL, 0);
  	    zfclosedata();
--- 1123,1144 ----
  	    return 1;
  	}
  
! #ifdef SUPPORT_IPV6
! 	if(zdsockp->a.sa_family == AF_INET6) {
! 	    /* see RFC 2428 for explanation */
! 	    strcpy(portcmd, "EPRT |2|");
! 	    inet_ntop(AF_INET6, &zdsockp->in6.sin6_addr,
! 		portcmd+8, INET6_ADDRSTRLEN);
! 	    sprintf(strchr(portcmd, 0), "|%u|\r\n",
! 		(unsigned)ntohs(zdsockp->in6.sin6_port));
! 	} else
! #endif /* SUPPORT_IPV6 */
! 	{
! 	    unsigned char *addr = (unsigned char *) &zdsockp->in.sin_addr;
! 	    unsigned char *port = (unsigned char *) &zdsockp->in.sin_port;
! 	    sprintf(portcmd, "PORT %d,%d,%d,%d,%d,%d\r\n",
! 		    addr[0],addr[1],addr[2],addr[3],port[0],port[1]);
! 	}
  	if (zfsendcmd(portcmd) >= 5) {
  	    zwarnnam(name, "port command failed", NULL, 0);
  	    zfclosedata();
***************
*** 988,994 ****
  zfgetdata(char *name, char *rest, char *cmd, int getsize)
  {
      int len, newfd, is_passive;
!     struct sockaddr_in zdsock;
  
      if (zfopendata(name, &zdsock, &is_passive))
  	return 1;
--- 1179,1185 ----
  zfgetdata(char *name, char *rest, char *cmd, int getsize)
  {
      int len, newfd, is_passive;
!     union zftp_sockaddr zdsock;
  
      if (zfopendata(name, &zdsock, &is_passive))
  	return 1;
***************
*** 1618,1629 ****
  static int
  zftp_open(char *name, char **args, int flags)
  {
-     struct in_addr ipaddr;
      struct protoent *zprotop;
      struct servent *zservp;
      struct hostent *zhostp = NULL;
      char **addrp, *fname;
      int err, len, tmout;
  
      if (!*args) {
  	if (zfsess->userparams)
--- 1809,1820 ----
  static int
  zftp_open(char *name, char **args, int flags)
  {
      struct protoent *zprotop;
      struct servent *zservp;
      struct hostent *zhostp = NULL;
      char **addrp, *fname;
      int err, len, tmout;
+     int herrno, af, salen;
  
      if (!*args) {
  	if (zfsess->userparams)
***************
*** 1671,1759 ****
      }
      zfalarm(tmout);
  
!     /*
!      * Now this is what I like.  A library which provides decent higher
!      * level functions to do things like converting address types.  It saves
!      * so much trouble.  Pity about the rest of the network interface, though.
!      */
!     ipaddr.s_addr = inet_addr(args[0]);
!     if (ipaddr.s_addr != INADDR_NONE) {
! 	/*
! 	 * hmmm, we don't necessarily want to do this... maybe the
! 	 * user is actively trying to avoid a bad nameserver.
! 	 * perhaps better just to set ZFTP_HOST to the dot address, too.
! 	 * that way shell functions know how it was opened.
! 	 *
! 	 * 	zhostp = gethostbyaddr(&ipaddr, sizeof(ipaddr), AF_INET);
! 	 *
! 	 * or, we could have a `no_lookup' flag.
! 	 */
! 	zfsetparam("ZFTP_HOST", ztrdup(args[0]), ZFPM_READONLY);
! 	zfsess->sock.sin_family = AF_INET;
!     } else {
! 	zhostp = gethostbyname(args[0]);
  	if (!zhostp || errflag) {
  	    /* should use herror() here if available, but maybe
  	     * needs configure test. on AIX it's present but not
  	     * in headers.
  	     */
  	    zwarnnam(name, "host not found: %s", args[0], 0);
  	    alarm(0);
  	    return 1;
  	}
- 	zfsess->sock.sin_family = zhostp->h_addrtype;
  	zfsetparam("ZFTP_HOST", ztrdup(zhostp->h_name), ZFPM_READONLY);
-     }
  
!     zfsess->sock.sin_port = zservp->s_port;
!     zfsess->cfd = socket(zfsess->sock.sin_family, SOCK_STREAM, 0);
!     if (zfsess->cfd < 0) {
! 	zwarnnam(name, "socket failed: %e", NULL, errno);
! 	zfunsetparam("ZFTP_HOST");
! 	alarm(0);
! 	return 1;
!     }
!     /* counts as `open' so long as it's not negative */
!     zfnopen++;
  
!     /*
!      * now connect the socket.  manual pages all say things like `this is all
!      * explained oh-so-wonderfully in some other manual page'.  not.
!      */
  
!     err = 1;
  
!     if (ipaddr.s_addr != INADDR_NONE) {
! 	/* dot address */
! 	memcpy(&zfsess->sock.sin_addr, &ipaddr, sizeof(ipaddr));
! 	do {
! 	    err = connect(zfsess->cfd, (struct sockaddr *)&zfsess->sock,
! 			  sizeof(zfsess->sock));
! 	} while (err && errno == EINTR && !errflag);
!     } else {
! 	/* host name: try all possible IP's */
! 	for (addrp = zhostp->h_addr_list; *addrp; addrp++) {
! 	    memcpy(&zfsess->sock.sin_addr, *addrp, zhostp->h_length);
  	    do {
! 		err = connect(zfsess->cfd, (struct sockaddr *)&zfsess->sock,
! 			      sizeof(zfsess->sock));
  	    } while (err && errno == EINTR && !errflag);
  	    /* you can check whether it's worth retrying here */
  	}
-     }
  
!     alarm(0);
  
!     if (err < 0) {
! 	zwarnnam(name, "connect failed: %e", NULL, errno);
! 	zfclose(0);
! 	return 1;
      }
!     zfsetparam("ZFTP_IP", ztrdup(inet_ntoa(zfsess->sock.sin_addr)),
! 	       ZFPM_READONLY);
      /* now we can talk to the control connection */
      zcfinish = 0;
- 
  
      /*
       * Move the fd out of the user-visible range.  We need to do
--- 1862,1965 ----
      }
      zfalarm(tmout);
  
! #ifdef SUPPORT_IPV6
!     for(af=AF_INET6; 1; af = AF_INET)
! # define SUCCEEDED() break
! # define FAILED() if(af == AF_INET) { } else continue
! #else
!     af = AF_INET;
! # define SUCCEEDED() do { } while(0)
! # define FAILED() do { } while(0)
! #endif
!     {
!     	zhostp = getipnodebyname(args[0], af, 0, &herrno);
  	if (!zhostp || errflag) {
  	    /* should use herror() here if available, but maybe
  	     * needs configure test. on AIX it's present but not
  	     * in headers.
  	     */
+ 	    FAILED();
  	    zwarnnam(name, "host not found: %s", args[0], 0);
  	    alarm(0);
  	    return 1;
  	}
  	zfsetparam("ZFTP_HOST", ztrdup(zhostp->h_name), ZFPM_READONLY);
  
! 	zfsess->peer.a.sa_family = af;
! #ifdef SUPPORT_IPV6
! 	if(af == AF_INET6) {
! 	    zfsess->peer.in6.sin6_port = zservp->s_port;
! 	    zfsess->peer.in6.sin6_flowinfo = 0;
! # ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
! 	    zfsess->peer.in6.sin6_scope_id = 0;
! # endif
! 	    salen = sizeof(struct sockaddr_in6);
! 	} else
! #endif /* SUPPORT_IPV6 */
! 	{
! 	    zfsess->peer.in.sin_port = zservp->s_port;
! 	    salen = sizeof(struct sockaddr_in);
! 	}
  
! 	zfsess->cfd = socket(af, SOCK_STREAM, 0);
! 	if (zfsess->cfd < 0) {
! 	    freehostent(zhostp);
! 	    zfunsetparam("ZFTP_HOST");
! 	    FAILED();
! 	    zwarnnam(name, "socket failed: %e", NULL, errno);
! 	    alarm(0);
! 	    return 1;
! 	}
! 	/* counts as `open' so long as it's not negative */
! 	zfnopen++;
! 
! 	/*
! 	 * now connect the socket.  manual pages all say things like `this is
! 	 * all explained oh-so-wonderfully in some other manual page'.  not.
! 	 */
  
! 	err = 1;
  
! 	/* try all possible IP's */
! 	for (addrp = zhostp->h_addr_list; err && *addrp; addrp++) {
! #ifdef SUPPORT_IPV6
! 	    if(af == AF_INET6)
! 		memcpy(&zfsess->peer.in6.sin6_addr, *addrp, zhostp->h_length);
! 	    else
! #endif /* SUPPORT_IPV6 */
! 		memcpy(&zfsess->peer.in.sin_addr, *addrp, zhostp->h_length);
  	    do {
! 		err = connect(zfsess->cfd, (struct sockaddr *)&zfsess->peer,
! 			      salen);
  	    } while (err && errno == EINTR && !errflag);
  	    /* you can check whether it's worth retrying here */
  	}
  
! 	if (err) {
! 	    freehostent(zhostp);
! 	    zfclose(0);
! 	    FAILED();
! 	    zwarnnam(name, "connect failed: %e", NULL, errno);
! 	    alarm(0);
! 	    return 1;
! 	}
  
! 	SUCCEEDED();
      }
!     alarm(0);
!     {
! #ifdef SUPPORT_IPV6
! 	char pbuf[INET6_ADDRSTRLEN];
! #else
! 	char pbuf[INET_ADDRSTRLEN];
! #endif
! 	addrp--;
! 	inet_ntop(af, *addrp, pbuf, sizeof(pbuf));
! 	zfsetparam("ZFTP_IP", ztrdup(pbuf), ZFPM_READONLY);
!     }
!     freehostent(zhostp);
      /* now we can talk to the control connection */
      zcfinish = 0;
  
      /*
       * Move the fd out of the user-visible range.  We need to do
diff -cr zsh-/acconfig.h acconfig.h
*** zsh-/acconfig.h	Tue Nov 23 23:47:18 1999
--- acconfig.h	Wed Nov 24 00:53:48 1999
***************
*** 133,138 ****
--- 133,141 ----
  /* Define if your system's struct direct has a member named d_stat.  */
  #undef HAVE_STRUCT_DIRECT_D_STAT
  
+ /* Define if your system's struct sockaddr_in6 has a member named sin6_scope_id.  */
+ #undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
+ 
  /* Define to be a string corresponding the vendor of the machine */
  #undef VENDOR
  
diff -cr zsh-/configure.in configure.in
*** zsh-/configure.in	Tue Nov 23 23:47:18 1999
--- configure.in	Wed Nov 24 00:52:56 1999
***************
*** 773,778 ****
--- 773,786 ----
  #endif
  ], struct direct, d_stat)
  
+ dnl Check IPv6 socket address structure type
+ zsh_STRUCT_MEMBER([
+ #ifdef HAVE_SYS_TYPES_H
+ # include <sys/types.h>
+ #endif
+ #include <netinet/in.h>
+ ], struct sockaddr_in6, sin6_scope_id)
+ 
  dnl need to integrate this function
  dnl AC_FUNC_STRFTIME
  
***************
*** 783,788 ****
--- 791,797 ----
                sigprocmask setuid seteuid setreuid setresuid setsid strerror \
                nis_list initgroups fchdir cap_get_proc readlink nice \
  	      getgrgid getgrnam getpwent getpwnam getpwuid setpgrp \
+ 	      inet_pton inet_ntop getipnodebyname gethostbyname2 \
  	      fseeko ftello mmap munmap msync ftruncate setlocale)
  
  dnl ---------------
END



Messages sorted by: Reverse Date, Date, Thread, Author