mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-12 01:11:27 +02:00
zsh-workers/8764
This commit is contained in:
parent
7cccf04d56
commit
a4a939cfd8
3 changed files with 323 additions and 105 deletions
|
@ -42,7 +42,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* needed in prototypes for statics */
|
/* needed in prototypes for statics */
|
||||||
|
struct hostent;
|
||||||
struct sockaddr_in;
|
struct sockaddr_in;
|
||||||
|
struct sockaddr_in6;
|
||||||
|
union zftp_sockaddr;
|
||||||
struct zftp_session;
|
struct zftp_session;
|
||||||
typedef struct zftp_session *Zftp_session;
|
typedef struct zftp_session *Zftp_session;
|
||||||
|
|
||||||
|
@ -71,11 +74,132 @@ typedef struct zftp_session *Zftp_session;
|
||||||
# undef HAVE_POLL
|
# undef HAVE_POLL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* pinch the definition from <netinet/in.h> for deficient headers */
|
/* Is IPv6 supported by the library? */
|
||||||
#ifndef INADDR_NONE
|
|
||||||
# define INADDR_NONE 0xffffffff
|
#if defined(AF_INET6) && defined(IN6ADDR_LOOPBACK_INIT) \
|
||||||
|
&& defined(HAVE_INET_NTOP) && defined(HAVE_INET_PTON)
|
||||||
|
# define SUPPORT_IPV6 1
|
||||||
#endif
|
#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
|
* For FTP block mode
|
||||||
*
|
*
|
||||||
|
@ -292,7 +416,8 @@ struct zftp_session {
|
||||||
char **userparams; /* user parameters set by zftp_params */
|
char **userparams; /* user parameters set by zftp_params */
|
||||||
int cfd; /* control file descriptor */
|
int cfd; /* control file descriptor */
|
||||||
FILE *cin; /* control input file */
|
FILE *cin; /* control input file */
|
||||||
struct sockaddr_in sock; /* the socket for the control connection */
|
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 dfd; /* data connection */
|
||||||
int has_size; /* understands SIZE? */
|
int has_size; /* understands SIZE? */
|
||||||
int has_mdtm; /* understands MDTM? */
|
int has_mdtm; /* understands MDTM? */
|
||||||
|
@ -846,7 +971,7 @@ zfsendcmd(char *cmd)
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
static int
|
static int
|
||||||
zfopendata(char *name, struct sockaddr_in *zdsockp, int *is_passivep)
|
zfopendata(char *name, union zftp_sockaddr *zdsockp, int *is_passivep)
|
||||||
{
|
{
|
||||||
if (!(zfprefs & (ZFPF_SNDP|ZFPF_PASV))) {
|
if (!(zfprefs & (ZFPF_SNDP|ZFPF_PASV))) {
|
||||||
zwarnnam(name, "Must set preference S or P to transfer data", NULL, 0);
|
zwarnnam(name, "Must set preference S or P to transfer data", NULL, 0);
|
||||||
|
@ -858,15 +983,17 @@ zfopendata(char *name, struct sockaddr_in *zdsockp, int *is_passivep)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*zdsockp = zfsess->sock;
|
|
||||||
zdsockp->sin_family = AF_INET;
|
|
||||||
|
|
||||||
if (!(zfstatusp[zfsessno] & ZFST_NOPS) && (zfprefs & ZFPF_PASV)) {
|
if (!(zfstatusp[zfsessno] & ZFST_NOPS) && (zfprefs & ZFPF_PASV)) {
|
||||||
char *ptr;
|
char *psv_cmd;
|
||||||
int i, nums[6], err;
|
int err, salen;
|
||||||
unsigned char iaddr[4], iport[2];
|
|
||||||
|
|
||||||
if (zfsendcmd("PASV\r\n") == 6)
|
#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;
|
return 1;
|
||||||
else if (lastcode >= 500 && lastcode <= 504) {
|
else if (lastcode >= 500 && lastcode <= 504) {
|
||||||
/*
|
/*
|
||||||
|
@ -877,32 +1004,73 @@ zfopendata(char *name, struct sockaddr_in *zdsockp, int *is_passivep)
|
||||||
zfclosedata();
|
zfclosedata();
|
||||||
return zfopendata(name, zdsockp, is_passivep);
|
return zfopendata(name, zdsockp, is_passivep);
|
||||||
}
|
}
|
||||||
/*
|
zdsockp->a.sa_family = zfsess->peer.a.sa_family;
|
||||||
* OK, now we need to know what port we're looking at,
|
#ifdef SUPPORT_IPV6
|
||||||
* which is cunningly concealed in the reply.
|
if(zfsess->peer.a.sa_family == AF_INET6) {
|
||||||
* lastmsg already has the reply code expunged.
|
/* see RFC 2428 for explanation */
|
||||||
*/
|
char const *ptr, *end;
|
||||||
for (ptr = lastmsg; *ptr; ptr++)
|
char delim, portbuf[6], *pbp;
|
||||||
if (isdigit(STOUC(*ptr)))
|
unsigned long portnum;
|
||||||
break;
|
ptr = strchr(lastmsg, '(');
|
||||||
if (sscanf(ptr, "%d,%d,%d,%d,%d,%d",
|
if(!ptr) {
|
||||||
nums, nums+1, nums+2, nums+3, nums+4, nums+5) != 6) {
|
bad_epsv:
|
||||||
zwarnnam(name, "bad response to PASV: %s", lastmsg, 0);
|
zwarnnam(name, "bad response to EPSV: %s", lastmsg, 0);
|
||||||
zfclosedata();
|
zfclosedata();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
for (i = 0; i < 4; i++)
|
delim = ptr[1];
|
||||||
iaddr[i] = STOUC(nums[i]);
|
if(delim < 33 || delim > 126 || ptr[2] != delim || ptr[3] != delim)
|
||||||
iport[0] = STOUC(nums[4]);
|
goto bad_epsv;
|
||||||
iport[1] = STOUC(nums[5]);
|
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];
|
||||||
|
|
||||||
memcpy(&zdsockp->sin_addr, iaddr, sizeof(iaddr));
|
/*
|
||||||
memcpy(&zdsockp->sin_port, iport, sizeof(iport));
|
* 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 */
|
/* we should timeout this connect */
|
||||||
do {
|
do {
|
||||||
err = connect(zfsess->dfd,
|
err = connect(zfsess->dfd, (struct sockaddr *)zdsockp, salen);
|
||||||
(struct sockaddr *)zdsockp, sizeof(*zdsockp));
|
|
||||||
} while (err && errno == EINTR && !errflag);
|
} while (err && errno == EINTR && !errflag);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -913,8 +1081,11 @@ zfopendata(char *name, struct sockaddr_in *zdsockp, int *is_passivep)
|
||||||
|
|
||||||
*is_passivep = 1;
|
*is_passivep = 1;
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef SUPPORT_IPV6
|
||||||
|
char portcmd[8+INET6_ADDRSTRLEN+9];
|
||||||
|
#else
|
||||||
char portcmd[40];
|
char portcmd[40];
|
||||||
unsigned char *addr, *port;
|
#endif
|
||||||
int ret, len;
|
int ret, len;
|
||||||
|
|
||||||
if (!(zfprefs & ZFPF_SNDP)) {
|
if (!(zfprefs & ZFPF_SNDP)) {
|
||||||
|
@ -922,11 +1093,19 @@ zfopendata(char *name, struct sockaddr_in *zdsockp, int *is_passivep)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
zdsockp->sin_port = 0; /* to be set by bind() */
|
*zdsockp = zfsess->sock;
|
||||||
len = sizeof(*zdsockp);
|
#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 */
|
/* need to do timeout stuff and probably handle EINTR here */
|
||||||
if (bind(zfsess->dfd, (struct sockaddr *)zdsockp,
|
if (bind(zfsess->dfd, (struct sockaddr *)zdsockp, len) < 0)
|
||||||
sizeof(*zdsockp)) < 0)
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
else if (getsockname(zfsess->dfd, (struct sockaddr *)zdsockp,
|
else if (getsockname(zfsess->dfd, (struct sockaddr *)zdsockp,
|
||||||
&len) < 0)
|
&len) < 0)
|
||||||
|
@ -944,10 +1123,22 @@ zfopendata(char *name, struct sockaddr_in *zdsockp, int *is_passivep)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = (unsigned char *) &zdsockp->sin_addr;
|
#ifdef SUPPORT_IPV6
|
||||||
port = (unsigned char *) &zdsockp->sin_port;
|
if(zdsockp->a.sa_family == AF_INET6) {
|
||||||
sprintf(portcmd, "PORT %d,%d,%d,%d,%d,%d\r\n",
|
/* see RFC 2428 for explanation */
|
||||||
addr[0],addr[1],addr[2],addr[3],port[0],port[1]);
|
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) {
|
if (zfsendcmd(portcmd) >= 5) {
|
||||||
zwarnnam(name, "port command failed", NULL, 0);
|
zwarnnam(name, "port command failed", NULL, 0);
|
||||||
zfclosedata();
|
zfclosedata();
|
||||||
|
@ -988,7 +1179,7 @@ static int
|
||||||
zfgetdata(char *name, char *rest, char *cmd, int getsize)
|
zfgetdata(char *name, char *rest, char *cmd, int getsize)
|
||||||
{
|
{
|
||||||
int len, newfd, is_passive;
|
int len, newfd, is_passive;
|
||||||
struct sockaddr_in zdsock;
|
union zftp_sockaddr zdsock;
|
||||||
|
|
||||||
if (zfopendata(name, &zdsock, &is_passive))
|
if (zfopendata(name, &zdsock, &is_passive))
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1618,12 +1809,12 @@ zfsenddata(char *name, int recv, int progress, off_t startat)
|
||||||
static int
|
static int
|
||||||
zftp_open(char *name, char **args, int flags)
|
zftp_open(char *name, char **args, int flags)
|
||||||
{
|
{
|
||||||
struct in_addr ipaddr;
|
|
||||||
struct protoent *zprotop;
|
struct protoent *zprotop;
|
||||||
struct servent *zservp;
|
struct servent *zservp;
|
||||||
struct hostent *zhostp = NULL;
|
struct hostent *zhostp = NULL;
|
||||||
char **addrp, *fname;
|
char **addrp, *fname;
|
||||||
int err, len, tmout;
|
int err, len, tmout;
|
||||||
|
int herrno, af, salen;
|
||||||
|
|
||||||
if (!*args) {
|
if (!*args) {
|
||||||
if (zfsess->userparams)
|
if (zfsess->userparams)
|
||||||
|
@ -1671,90 +1862,105 @@ zftp_open(char *name, char **args, int flags)
|
||||||
}
|
}
|
||||||
zfalarm(tmout);
|
zfalarm(tmout);
|
||||||
|
|
||||||
/*
|
#ifdef SUPPORT_IPV6
|
||||||
* Now this is what I like. A library which provides decent higher
|
for(af=AF_INET6; 1; af = AF_INET)
|
||||||
* level functions to do things like converting address types. It saves
|
# define SUCCEEDED() break
|
||||||
* so much trouble. Pity about the rest of the network interface, though.
|
# define FAILED() if(af == AF_INET) { } else continue
|
||||||
*/
|
#else
|
||||||
ipaddr.s_addr = inet_addr(args[0]);
|
af = AF_INET;
|
||||||
if (ipaddr.s_addr != INADDR_NONE) {
|
# define SUCCEEDED() do { } while(0)
|
||||||
/*
|
# define FAILED() do { } while(0)
|
||||||
* hmmm, we don't necessarily want to do this... maybe the
|
#endif
|
||||||
* user is actively trying to avoid a bad nameserver.
|
{
|
||||||
* perhaps better just to set ZFTP_HOST to the dot address, too.
|
zhostp = getipnodebyname(args[0], af, 0, &herrno);
|
||||||
* 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) {
|
if (!zhostp || errflag) {
|
||||||
/* should use herror() here if available, but maybe
|
/* should use herror() here if available, but maybe
|
||||||
* needs configure test. on AIX it's present but not
|
* needs configure test. on AIX it's present but not
|
||||||
* in headers.
|
* in headers.
|
||||||
*/
|
*/
|
||||||
|
FAILED();
|
||||||
zwarnnam(name, "host not found: %s", args[0], 0);
|
zwarnnam(name, "host not found: %s", args[0], 0);
|
||||||
alarm(0);
|
alarm(0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
zfsess->sock.sin_family = zhostp->h_addrtype;
|
|
||||||
zfsetparam("ZFTP_HOST", ztrdup(zhostp->h_name), ZFPM_READONLY);
|
zfsetparam("ZFTP_HOST", ztrdup(zhostp->h_name), ZFPM_READONLY);
|
||||||
}
|
|
||||||
|
|
||||||
zfsess->sock.sin_port = zservp->s_port;
|
zfsess->peer.a.sa_family = af;
|
||||||
zfsess->cfd = socket(zfsess->sock.sin_family, SOCK_STREAM, 0);
|
#ifdef SUPPORT_IPV6
|
||||||
if (zfsess->cfd < 0) {
|
if(af == AF_INET6) {
|
||||||
zwarnnam(name, "socket failed: %e", NULL, errno);
|
zfsess->peer.in6.sin6_port = zservp->s_port;
|
||||||
zfunsetparam("ZFTP_HOST");
|
zfsess->peer.in6.sin6_flowinfo = 0;
|
||||||
alarm(0);
|
# ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
|
||||||
return 1;
|
zfsess->peer.in6.sin6_scope_id = 0;
|
||||||
}
|
# endif
|
||||||
/* counts as `open' so long as it's not negative */
|
salen = sizeof(struct sockaddr_in6);
|
||||||
zfnopen++;
|
} else
|
||||||
|
#endif /* SUPPORT_IPV6 */
|
||||||
|
{
|
||||||
|
zfsess->peer.in.sin_port = zservp->s_port;
|
||||||
|
salen = sizeof(struct sockaddr_in);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
zfsess->cfd = socket(af, SOCK_STREAM, 0);
|
||||||
* now connect the socket. manual pages all say things like `this is all
|
if (zfsess->cfd < 0) {
|
||||||
* explained oh-so-wonderfully in some other manual page'. not.
|
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++;
|
||||||
|
|
||||||
err = 1;
|
/*
|
||||||
|
* now connect the socket. manual pages all say things like `this is
|
||||||
|
* all explained oh-so-wonderfully in some other manual page'. not.
|
||||||
|
*/
|
||||||
|
|
||||||
if (ipaddr.s_addr != INADDR_NONE) {
|
err = 1;
|
||||||
/* dot address */
|
|
||||||
memcpy(&zfsess->sock.sin_addr, &ipaddr, sizeof(ipaddr));
|
/* try all possible IP's */
|
||||||
do {
|
for (addrp = zhostp->h_addr_list; err && *addrp; addrp++) {
|
||||||
err = connect(zfsess->cfd, (struct sockaddr *)&zfsess->sock,
|
#ifdef SUPPORT_IPV6
|
||||||
sizeof(zfsess->sock));
|
if(af == AF_INET6)
|
||||||
} while (err && errno == EINTR && !errflag);
|
memcpy(&zfsess->peer.in6.sin6_addr, *addrp, zhostp->h_length);
|
||||||
} else {
|
else
|
||||||
/* host name: try all possible IP's */
|
#endif /* SUPPORT_IPV6 */
|
||||||
for (addrp = zhostp->h_addr_list; *addrp; addrp++) {
|
memcpy(&zfsess->peer.in.sin_addr, *addrp, zhostp->h_length);
|
||||||
memcpy(&zfsess->sock.sin_addr, *addrp, zhostp->h_length);
|
|
||||||
do {
|
do {
|
||||||
err = connect(zfsess->cfd, (struct sockaddr *)&zfsess->sock,
|
err = connect(zfsess->cfd, (struct sockaddr *)&zfsess->peer,
|
||||||
sizeof(zfsess->sock));
|
salen);
|
||||||
} while (err && errno == EINTR && !errflag);
|
} while (err && errno == EINTR && !errflag);
|
||||||
/* you can check whether it's worth retrying here */
|
/* 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);
|
alarm(0);
|
||||||
|
{
|
||||||
if (err < 0) {
|
#ifdef SUPPORT_IPV6
|
||||||
zwarnnam(name, "connect failed: %e", NULL, errno);
|
char pbuf[INET6_ADDRSTRLEN];
|
||||||
zfclose(0);
|
#else
|
||||||
return 1;
|
char pbuf[INET_ADDRSTRLEN];
|
||||||
|
#endif
|
||||||
|
addrp--;
|
||||||
|
inet_ntop(af, *addrp, pbuf, sizeof(pbuf));
|
||||||
|
zfsetparam("ZFTP_IP", ztrdup(pbuf), ZFPM_READONLY);
|
||||||
}
|
}
|
||||||
zfsetparam("ZFTP_IP", ztrdup(inet_ntoa(zfsess->sock.sin_addr)),
|
freehostent(zhostp);
|
||||||
ZFPM_READONLY);
|
|
||||||
/* now we can talk to the control connection */
|
/* now we can talk to the control connection */
|
||||||
zcfinish = 0;
|
zcfinish = 0;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Move the fd out of the user-visible range. We need to do
|
* Move the fd out of the user-visible range. We need to do
|
||||||
* this after the connect() on some systems.
|
* this after the connect() on some systems.
|
||||||
|
|
|
@ -133,6 +133,9 @@
|
||||||
/* Define if your system's struct direct has a member named d_stat. */
|
/* Define if your system's struct direct has a member named d_stat. */
|
||||||
#undef HAVE_STRUCT_DIRECT_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 */
|
/* Define to be a string corresponding the vendor of the machine */
|
||||||
#undef VENDOR
|
#undef VENDOR
|
||||||
|
|
||||||
|
|
|
@ -773,6 +773,14 @@ zsh_STRUCT_MEMBER([
|
||||||
#endif
|
#endif
|
||||||
], struct direct, d_stat)
|
], 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 need to integrate this function
|
||||||
dnl AC_FUNC_STRFTIME
|
dnl AC_FUNC_STRFTIME
|
||||||
|
|
||||||
|
@ -783,6 +791,7 @@ AC_CHECK_FUNCS(memcpy memmove \
|
||||||
sigprocmask setuid seteuid setreuid setresuid setsid strerror \
|
sigprocmask setuid seteuid setreuid setresuid setsid strerror \
|
||||||
nis_list initgroups fchdir cap_get_proc readlink nice \
|
nis_list initgroups fchdir cap_get_proc readlink nice \
|
||||||
getgrgid getgrnam getpwent getpwnam getpwuid setpgrp \
|
getgrgid getgrnam getpwent getpwnam getpwuid setpgrp \
|
||||||
|
inet_pton inet_ntop getipnodebyname gethostbyname2 \
|
||||||
fseeko ftello mmap munmap msync ftruncate setlocale)
|
fseeko ftello mmap munmap msync ftruncate setlocale)
|
||||||
|
|
||||||
dnl ---------------
|
dnl ---------------
|
||||||
|
|
Loading…
Reference in a new issue