summaryrefslogtreecommitdiff
path: root/Src/Modules/zftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Modules/zftp.c')
-rw-r--r--Src/Modules/zftp.c259
1 files changed, 54 insertions, 205 deletions
diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c
index 0f70f9417..46f30da74 100644
--- a/Src/Modules/zftp.c
+++ b/Src/Modules/zftp.c
@@ -46,7 +46,6 @@ struct hostent;
struct in_addr;
struct sockaddr_in;
struct sockaddr_in6;
-union zftp_sockaddr;
struct zftp_session;
typedef struct zftp_session *Zftp_session;
@@ -77,6 +76,7 @@ typedef struct zftp_session *Zftp_session;
#include <netinet/ip.h>
#include <arpa/inet.h>
+#include "tcp.h"
#include "zftp.mdh"
#include "zftp.pro"
@@ -96,11 +96,9 @@ typedef struct zftp_session *Zftp_session;
# 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
+#ifdef USE_LOCAL_H_ERRNO
+int h_errno;
#endif
union zftp_sockaddr {
@@ -115,153 +113,6 @@ union zftp_sockaddr {
int h_errno;
#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 *
-zsh_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;
-}
-
-#else /* !HAVE_INET_NTOP */
-
-# define zsh_inet_ntop inet_ntop
-
-/**/
-#endif /* !HAVE_INET_NTOP */
-
-/**/
-#ifndef HAVE_INET_PTON
-
-/**/
-# ifndef HAVE_INET_ATON
-
-# ifndef INADDR_NONE
-# define INADDR_NONE 0xffffffffUL
-# endif
-
-/**/
-static int zsh_inet_aton(char const *src, struct in_addr *dst)
-{
- return (dst->s_addr = inet_addr(src)) != INADDR_NONE;
-}
-
-#else /* !HAVE_INET_ATON */
-
-# define zsh_inet_aton inet_aton
-
-/**/
-# endif /* !HAVE_INET_ATON */
-
-/**/
-static int
-zsh_inet_pton(int af, char const *src, void *dst)
-{
- if(af != AF_INET) {
- errno = EAFNOSUPPORT;
- return -1;
- }
- return !!zsh_inet_aton(src, dst);
-}
-
-#else /* !HAVE_INET_PTON */
-
-# define zsh_inet_pton inet_pton
-
-/**/
-#endif /* !HAVE_INET_PTON */
-
-/**/
-#ifndef HAVE_GETIPNODEBYNAME
-
-/**/
-# ifndef HAVE_GETHOSTBYNAME2
-
-/**/
-static struct hostent *
-zsh_gethostbyname2(char const *name, int af)
-{
- if(af != AF_INET) {
- h_errno = NO_RECOVERY;
- return NULL;
- }
- return gethostbyname(name);
-}
-
-#else /* !HAVE_GETHOSTBYNAME2 */
-
-# define zsh_gethostbyname2 gethostbyname2
-
-/**/
-# endif /* !HAVE_GETHOSTBYNAME2 */
-
-
-/* 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 *
-zsh_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(zsh_inet_pton(af, name, nbuf) == 1) {
- zsh_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 = zsh_gethostbyname2(name, af);
- if(!he)
- *errorp = h_errno;
- return he;
-}
-/**/
-static void
-freehostent(struct hostent *ptr)
-{
-}
-
-#else /* !HAVE_GETIPNODEBYNAME */
-
-# define zsh_getipnodebyname getipnodebyname
-
-/**/
-#endif /* !HAVE_GETIPNODEBYNAME */
-
/*
* For FTP block mode
*
@@ -476,10 +327,8 @@ struct zftp_session {
char *name; /* name of session */
char **params; /* parameters ordered as in zfparams */
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 */
+ struct tcp_session control; /* the control connection */
int dfd; /* data connection */
int has_size; /* understands SIZE? */
int has_mdtm; /* understands MDTM? */
@@ -821,7 +670,7 @@ zfgetline(char *ln, int lnsize, int tmout)
cmdbuf[0] = (char)IAC;
cmdbuf[1] = (char)DONT;
cmdbuf[2] = ch;
- write(zfsess->cfd, cmdbuf, 3);
+ write(zfsess->control.fd, cmdbuf, 3);
continue;
case DO:
@@ -831,7 +680,7 @@ zfgetline(char *ln, int lnsize, int tmout)
cmdbuf[0] = (char)IAC;
cmdbuf[1] = (char)WONT;
cmdbuf[2] = ch;
- write(zfsess->cfd, cmdbuf, 3);
+ write(zfsess->control.fd, cmdbuf, 3);
continue;
case EOF:
@@ -881,7 +730,7 @@ zfgetmsg(void)
char line[256], *ptr, *verbose;
int stopit, printing = 0, tmout;
- if (zfsess->cfd == -1)
+ if (zfsess->control.fd == -1)
return 6;
zsfree(lastmsg);
lastmsg = NULL;
@@ -1009,7 +858,7 @@ zfsendcmd(char *cmd)
*/
int ret, tmout;
- if (zfsess->cfd == -1)
+ if (zfsess->control.fd == -1)
return 6;
tmout = getiparam("ZFTP_TMOUT");
if (setjmp(zfalrmbuf)) {
@@ -1018,7 +867,7 @@ zfsendcmd(char *cmd)
return 6;
}
zfalarm(tmout);
- ret = write(zfsess->cfd, cmd, strlen(cmd));
+ ret = write(zfsess->control.fd, cmd, strlen(cmd));
alarm(0);
if (ret <= 0) {
@@ -1035,7 +884,7 @@ zfsendcmd(char *cmd)
/**/
static int
-zfopendata(char *name, union zftp_sockaddr *zdsockp, int *is_passivep)
+zfopendata(char *name, union tcp_sockaddr *zdsockp, int *is_passivep)
{
if (!(zfprefs & (ZFPF_SNDP|ZFPF_PASV))) {
zwarnnam(name, "Must set preference S or P to transfer data", NULL, 0);
@@ -1052,7 +901,7 @@ zfopendata(char *name, union zftp_sockaddr *zdsockp, int *is_passivep)
int err, salen;
#ifdef SUPPORT_IPV6
- if(zfsess->peer.a.sa_family == AF_INET6)
+ if(zfsess->control.peer.a.sa_family == AF_INET6)
psv_cmd = "EPSV\r\n";
else
#endif /* SUPPORT_IPV6 */
@@ -1068,9 +917,9 @@ zfopendata(char *name, union zftp_sockaddr *zdsockp, int *is_passivep)
zfclosedata();
return zfopendata(name, zdsockp, is_passivep);
}
- zdsockp->a.sa_family = zfsess->peer.a.sa_family;
+ zdsockp->a.sa_family = zfsess->control.peer.a.sa_family;
#ifdef SUPPORT_IPV6
- if(zfsess->peer.a.sa_family == AF_INET6) {
+ if(zfsess->control.peer.a.sa_family == AF_INET6) {
/* see RFC 2428 for explanation */
char const *ptr, *end;
char delim, portbuf[6], *pbp;
@@ -1098,7 +947,7 @@ zfopendata(char *name, union zftp_sockaddr *zdsockp, int *is_passivep)
portnum = strtoul(portbuf, &pbp, 10);
if(*pbp || portnum > 65535UL)
goto bad_epsv;
- *zdsockp = zfsess->peer;
+ *zdsockp = zfsess->control.peer;
zdsockp->in6.sin6_port = htons((unsigned)portnum);
salen = sizeof(struct sockaddr_in6);
} else
@@ -1157,7 +1006,7 @@ zfopendata(char *name, union zftp_sockaddr *zdsockp, int *is_passivep)
return 1;
}
- *zdsockp = zfsess->sock;
+ *zdsockp = zfsess->control.sock;
#ifdef SUPPORT_IPV6
if(zdsockp->a.sa_family == AF_INET6) {
zdsockp->in6.sin6_port = 0; /* to be set by bind() */
@@ -1243,7 +1092,7 @@ static int
zfgetdata(char *name, char *rest, char *cmd, int getsize)
{
int len, newfd, is_passive;
- union zftp_sockaddr zdsock;
+ union tcp_sockaddr zdsock;
if (zfopendata(name, &zdsock, &is_passive))
return 1;
@@ -1831,8 +1680,8 @@ zfsenddata(char *name, int recv, int progress, off_t startat)
/* the following is black magic, as far as I'm concerned. */
/* what are we going to do if it fails? not a lot, actually. */
- send(zfsess->cfd, (char *)msg, 3, 0);
- send(zfsess->cfd, (char *)msg+3, 1, MSG_OOB);
+ send(zfsess->control.fd, (char *)msg, 3, 0);
+ send(zfsess->control.fd, (char *)msg+3, 1, MSG_OOB);
zfsendcmd("ABOR\r\n");
if (lastcode == 226) {
@@ -1893,7 +1742,7 @@ zftp_open(char *name, char **args, int flags)
* Probably this is the safest thing to do. It's possible
* a `QUIT' will hang, though.
*/
- if (zfsess->cfd != -1)
+ if (zfsess->control.fd != -1)
zfclose(0);
/* this is going to give 0. why bother? */
@@ -1950,24 +1799,24 @@ zftp_open(char *name, char **args, int flags)
}
zfsetparam("ZFTP_HOST", ztrdup(zhostp->h_name), ZFPM_READONLY);
- zfsess->peer.a.sa_family = af;
+ zfsess->control.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;
+ zfsess->control.peer.in6.sin6_port = zservp->s_port;
+ zfsess->control.peer.in6.sin6_flowinfo = 0;
# ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
- zfsess->peer.in6.sin6_scope_id = 0;
+ zfsess->control.peer.in6.sin6_scope_id = 0;
# endif
salen = sizeof(struct sockaddr_in6);
} else
#endif /* SUPPORT_IPV6 */
{
- zfsess->peer.in.sin_port = zservp->s_port;
+ zfsess->control.peer.in.sin_port = zservp->s_port;
salen = sizeof(struct sockaddr_in);
}
- zfsess->cfd = socket(af, SOCK_STREAM, 0);
- if (zfsess->cfd < 0) {
+ tcp_socket(af, SOCK_STREAM, 0, &(zfsess->control));
+ if (zfsess->control.fd < 0) {
freehostent(zhostp);
zfunsetparam("ZFTP_HOST");
FAILED();
@@ -1989,12 +1838,12 @@ zftp_open(char *name, char **args, int flags)
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);
+ memcpy(&zfsess->control.peer.in6.sin6_addr, *addrp, zhostp->h_length);
else
#endif /* SUPPORT_IPV6 */
- memcpy(&zfsess->peer.in.sin_addr, *addrp, zhostp->h_length);
+ memcpy(&zfsess->control.peer.in.sin_addr, *addrp, zhostp->h_length);
do {
- err = connect(zfsess->cfd, (struct sockaddr *)&zfsess->peer,
+ err = connect(zfsess->control.fd, (struct sockaddr *)&zfsess->control.peer,
salen);
} while (err && errno == EINTR && !errflag);
/* you can check whether it's worth retrying here */
@@ -2030,15 +1879,15 @@ zftp_open(char *name, char **args, int flags)
* Move the fd out of the user-visible range. We need to do
* this after the connect() on some systems.
*/
- zfsess->cfd = zfmovefd(zfsess->cfd);
+ zfsess->control.fd = zfmovefd(zfsess->control.fd);
#if defined(F_SETFD) && defined(FD_CLOEXEC)
/* If the shell execs a program, we don't want this fd left open. */
- fcntl(zfsess->cfd, F_SETFD, FD_CLOEXEC);
+ fcntl(zfsess->control.fd, F_SETFD, FD_CLOEXEC);
#endif
- len = sizeof(zfsess->sock);
- if (getsockname(zfsess->cfd, (struct sockaddr *)&zfsess->sock, &len) < 0) {
+ len = sizeof(zfsess->control.sock);
+ if (getsockname(zfsess->control.fd, (struct sockaddr *)&zfsess->control.sock, &len) < 0) {
zwarnnam(name, "getsockname failed: %e", NULL, errno);
zfclose(0);
return 1;
@@ -2050,20 +1899,20 @@ zftp_open(char *name, char **args, int flags)
* do clever things with SIGURG.
*/
len = 1;
- setsockopt(zfsess->cfd, SOL_SOCKET, SO_OOBINLINE,
+ setsockopt(zfsess->control.fd, SOL_SOCKET, SO_OOBINLINE,
(char *)&len, sizeof(len));
#endif
#if defined(IP_TOS) && defined(IPTOS_LOWDELAY)
/* for control connection we want low delay. please don't laugh. */
len = IPTOS_LOWDELAY;
- setsockopt(zfsess->cfd, IPPROTO_IP, IP_TOS, (char *)&len, sizeof(len));
+ setsockopt(zfsess->control.fd, IPPROTO_IP, IP_TOS, (char *)&len, sizeof(len));
#endif
/*
* We use stdio with line buffering for convenience on input.
* On output, we can just dump a complete message to the fd via write().
*/
- zfsess->cin = fdopen(zfsess->cfd, "r");
+ zfsess->cin = fdopen(zfsess->control.fd, "r");
if (!zfsess->cin) {
zwarnnam(name, "file handling error", NULL, 0);
@@ -2107,17 +1956,17 @@ zftp_open(char *name, char **args, int flags)
unlink(fname);
}
- if (zfsess->cfd == -1) {
+ if (zfsess->control.fd == -1) {
/* final paranoid check */
return 1;
}
zfsetparam("ZFTP_MODE", ztrdup("S"), ZFPM_READONLY);
/* if remaining arguments, use them to log in. */
- if (zfsess->cfd > -1 && *++args)
+ if (zfsess->control.fd > -1 && *++args)
return zftp_login(name, args, flags);
/* if something wayward happened, connection was already closed */
- return zfsess->cfd == -1;
+ return zfsess->control.fd == -1;
}
/*
@@ -2311,7 +2160,7 @@ zftp_login(char *name, char **args, int flags)
}
zsfree(ucmd);
- if (zfsess->cfd == -1)
+ if (zfsess->control.fd == -1)
return 1;
if (stopit == 2 || (lastcode != 230 && lastcode != 202)) {
zwarnnam(name, "login failed", NULL, 0);
@@ -2390,7 +2239,7 @@ zftp_test(char *name, char **args, int flags)
struct timeval tv;
# endif /* HAVE_POLL */
- if (zfsess->cfd == -1)
+ if (zfsess->control.fd == -1)
return 1;
# ifdef HAVE_POLL
@@ -2398,7 +2247,7 @@ zftp_test(char *name, char **args, int flags)
/* safety first, though I think POLLIN is more common */
# define POLLIN POLLNORM
# endif /* HAVE_POLL */
- pfd.fd = zfsess->cfd;
+ pfd.fd = zfsess->control.fd;
pfd.events = POLLIN;
if ((ret = poll(&pfd, 1, 0)) < 0 && errno != EINTR && errno != EAGAIN)
zfclose(0);
@@ -2408,10 +2257,10 @@ zftp_test(char *name, char **args, int flags)
}
# else
FD_ZERO(&f);
- FD_SET(zfsess->cfd, &f);
+ FD_SET(zfsess->control.fd, &f);
tv.tv_sec = 0;
tv.tv_usec = 0;
- if ((ret = select(zfsess->cfd +1, (SELECT_ARG_2_T) &f,
+ if ((ret = select(zfsess->control.fd +1, (SELECT_ARG_2_T) &f,
NULL, NULL, &tv)) < 0
&& errno != EINTR)
zfclose(0);
@@ -2420,8 +2269,8 @@ zftp_test(char *name, char **args, int flags)
zfgetmsg();
}
# endif /* HAVE_POLL */
- /* if we now have zfsess->cfd == -1, then we've just been dumped out. */
- return (zfsess->cfd == -1) ? 2 : 0;
+ /* if we now have zfsess->control.fd == -1, then we've just been dumped out. */
+ return (zfsess->control.fd == -1) ? 2 : 0;
#else
zfwarnnam(name, "not supported on this system.", NULL, 0);
return 3;
@@ -2843,7 +2692,7 @@ zfclose(int leaveparams)
char **aptr;
Eprog prog;
- if (zfsess->cfd == -1)
+ if (zfsess->control.fd == -1)
return;
zfclosing = 1;
@@ -2859,10 +2708,10 @@ zfclose(int leaveparams)
fclose(zfsess->cin);
zfsess->cin = NULL;
}
- if (zfsess->cfd != -1) {
+ if (zfsess->control.fd != -1) {
zfnopen--;
- close(zfsess->cfd);
- zfsess->cfd = -1;
+ close(zfsess->control.fd);
+ zfsess->control.fd = -1;
}
if (zfstatfd != -1) {
@@ -2935,7 +2784,7 @@ newsession(char *nm)
if (!nptr) {
zfsess = (Zftp_session) zcalloc(sizeof(struct zftp_session));
zfsess->name = ztrdup(nm);
- zfsess->cfd = zfsess->dfd = -1;
+ zfsess->control.fd = zfsess->dfd = -1;
zfsess->params = (char **) zcalloc(sizeof(zfparams));
zaddlinknode(zfsessions, zfsess);
@@ -3150,7 +2999,7 @@ bin_zftp(char *name, char **args, char *ops, int func)
int oldstatus = zfstatusp[zfsessno];
lseek(zfstatfd, 0, 0);
read(zfstatfd, (char *)zfstatusp, sizeof(int)*zfsesscnt);
- if (zfsess->cfd != -1 && (zfstatusp[zfsessno] & ZFST_CLOS)) {
+ if (zfsess->control.fd != -1 && (zfstatusp[zfsessno] & ZFST_CLOS)) {
/* got closed in subshell without us knowing */
zcfinish = 2;
zfclose(0);
@@ -3171,7 +3020,7 @@ bin_zftp(char *name, char **args, char *ops, int func)
}
}
#if defined(HAVE_SELECT) || defined (HAVE_POLL)
- if (zfsess->cfd != -1 && !(zptr->flags & (ZFTP_TEST|ZFTP_SESS))) {
+ if (zfsess->control.fd != -1 && !(zptr->flags & (ZFTP_TEST|ZFTP_SESS))) {
/*
* Test the connection for a bad fd or incoming message, but
* only if the connection was last heard of open, and
@@ -3181,7 +3030,7 @@ bin_zftp(char *name, char **args, char *ops, int func)
ret = zftp_test("zftp test", NULL, 0);
}
#endif
- if ((zptr->flags & ZFTP_CONN) && zfsess->cfd == -1) {
+ if ((zptr->flags & ZFTP_CONN) && zfsess->control.fd == -1) {
if (ret != 2) {
/*
* with ret == 2, we just got dumped out in the test,