mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-29 12:03:03 +00:00
IPv6 support.
This is required for forthcoming IPv6 ready installer. Obtained from: KAME
This commit is contained in:
parent
b2874e0082
commit
f7c67fc880
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=62649
@ -1,12 +1,13 @@
|
||||
# $FreeBSD$
|
||||
|
||||
LIB= ftpio
|
||||
SHLIB_MAJOR= 5
|
||||
SHLIB_MAJOR= 6
|
||||
SHLIB_MINOR= 0
|
||||
|
||||
SRCS= ftpio.c ftperr.c
|
||||
INCS= ftpio.h
|
||||
CFLAGS+= -I${.CURDIR} -Wall
|
||||
CFLAGS+= -DINET6
|
||||
MAN3= ftpio.3
|
||||
CLEANFILES= ftperr.c
|
||||
|
||||
|
@ -18,7 +18,8 @@
|
||||
221 Service closing control connection
|
||||
225 Data connection open; no transfer in progress
|
||||
226 Requested file action successful
|
||||
227 Entering Passive Mode
|
||||
227 Entering Passive Mode
|
||||
229 Entering Extended Passive Mode
|
||||
230 User logged in, proceed
|
||||
250 Requested file action okay, completed
|
||||
257 File/directory created
|
||||
|
@ -39,7 +39,10 @@
|
||||
.Nm ftpPassive ,
|
||||
.Nm ftpVerbose ,
|
||||
.Nm ftpGetURL ,
|
||||
.Nm ftpPutURL
|
||||
.Nm ftpPutURL ,
|
||||
.Nm ftpLoginAf ,
|
||||
.Nm ftpGetURLAf ,
|
||||
.Nm ftpPutURLAf
|
||||
.Nd FTPIO User library
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <ftpio.h>
|
||||
@ -71,6 +74,12 @@
|
||||
.Fn ftpGetURL "char *url, char *user, char *passwd, int *retcode"
|
||||
.Ft FILE *
|
||||
.Fn ftpPutURL "char *url, char *user, char *passwd, int *retcode"
|
||||
.Ft int
|
||||
.Fn ftpLoginAf "char *host" "int af" "char *user" "char *passwd" "int ftp_port" "int verbose" "int *retcode"
|
||||
.Ft FILE *
|
||||
.Fn ftpGetURLAf "char *url" "int af" "char *user" "char *passwd" "int *retcode"
|
||||
.Ft FILE *
|
||||
.Fn ftpPutURLAf "char *url" "int af" "char *user" "char *passwd" "int *retcode"
|
||||
|
||||
.Sh DESCRIPTION
|
||||
These functions implement a high-level library for managing FTP connections.
|
||||
@ -186,6 +195,16 @@ operations except that no server stream is ever returned - the connection
|
||||
to the server closes when the file has been completely written. Use the
|
||||
lower-level routines if multiple puts are required as it will be far more
|
||||
efficient.
|
||||
.Pp
|
||||
.Fn ftpLoginAf ,
|
||||
.Fn ftpGetURLAf ,
|
||||
.Fn ftpPutURLAf
|
||||
are same as
|
||||
.Fn ftpLogin ,
|
||||
.Fn ftpGetURL ,
|
||||
.Fn ftpPutURL
|
||||
except that they are able to specify address family
|
||||
.Fa af .
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width FTP_PASSIVE_MODE -offset 123
|
||||
.It Ev FTP_TIMEOUT
|
||||
|
@ -58,13 +58,14 @@ static __inline char *get_a_line(FTP_t ftp);
|
||||
static int get_a_number(FTP_t ftp, char **q);
|
||||
static int botch(char *func, char *botch_state);
|
||||
static int cmd(FTP_t ftp, const char *fmt, ...);
|
||||
static int ftp_login_session(FTP_t ftp, char *host, char *user, char *passwd, int port, int verbose);
|
||||
static int ftp_login_session(FTP_t ftp, char *host, int af, char *user, char *passwd, int port, int verbose);
|
||||
static int ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t *seekto);
|
||||
static int ftp_close(FTP_t ftp);
|
||||
static int get_url_info(char *url_in, char *host_ret, int *port_ret, char *name_ret);
|
||||
static void ftp_timeout(int sig);
|
||||
static void ftp_set_timeout(void);
|
||||
static void ftp_clear_timeout(void);
|
||||
static void ai_unmapped(struct addrinfo *);
|
||||
|
||||
|
||||
/* Global status variable - ick */
|
||||
@ -79,6 +80,8 @@ int FtpTimedOut;
|
||||
#define FTP_QUIT_HAPPY 221
|
||||
#define FTP_TRANSFER_HAPPY 226
|
||||
#define FTP_PASSIVE_HAPPY 227
|
||||
#define FTP_LPASSIVE_HAPPY 228
|
||||
#define FTP_EPASSIVE_HAPPY 229
|
||||
#define FTP_CHDIR_HAPPY 250
|
||||
|
||||
/* FTP unhappy status codes */
|
||||
@ -266,6 +269,16 @@ ftpGet(FILE *fp, char *file, off_t *seekto)
|
||||
/* Returns a standard FILE pointer type representing an open control connection */
|
||||
FILE *
|
||||
ftpLogin(char *host, char *user, char *passwd, int port, int verbose, int *retcode)
|
||||
{
|
||||
#ifdef INET6
|
||||
return ftpLoginAf(host, AF_UNSPEC, user, passwd, port, verbose, retcode);
|
||||
#else
|
||||
return ftpLoginAf(host, AF_INET, user, passwd, port, verbose, retcode);
|
||||
#endif
|
||||
}
|
||||
|
||||
FILE *
|
||||
ftpLoginAf(char *host, int af, char *user, char *passwd, int port, int verbose, int *retcode)
|
||||
{
|
||||
FTP_t n;
|
||||
FILE *fp;
|
||||
@ -277,7 +290,7 @@ ftpLogin(char *host, char *user, char *passwd, int port, int verbose, int *retco
|
||||
|
||||
n = ftp_new();
|
||||
fp = NULL;
|
||||
if (n && ftp_login_session(n, host, user, passwd, port, verbose) == SUCCESS) {
|
||||
if (n && ftp_login_session(n, host, af, user, passwd, port, verbose) == SUCCESS) {
|
||||
fp = funopen(n, ftp_read_method, ftp_write_method, NULL, ftp_close_method); /* BSD 4.4 function! */
|
||||
fp->_file = n->fd_ctrl;
|
||||
}
|
||||
@ -323,17 +336,43 @@ ftpPassive(FILE *fp, int st)
|
||||
|
||||
if (ftp->is_passive == st)
|
||||
return SUCCESS;
|
||||
i = cmd(ftp, "PASV");
|
||||
if (i < 0)
|
||||
return i;
|
||||
if (i != FTP_PASSIVE_HAPPY)
|
||||
return FAILURE;
|
||||
switch (ftp->addrtype) {
|
||||
case AF_INET:
|
||||
i = cmd(ftp, "PASV");
|
||||
if (i < 0)
|
||||
return i;
|
||||
if (i != FTP_PASSIVE_HAPPY)
|
||||
return FAILURE;
|
||||
break;
|
||||
case AF_INET6:
|
||||
i = cmd(ftp, "EPSV");
|
||||
if (i < 0)
|
||||
return i;
|
||||
if (i != FTP_EPASSIVE_HAPPY) {
|
||||
i = cmd(ftp, "LPSV");
|
||||
if (i < 0)
|
||||
return i;
|
||||
if (i != FTP_LPASSIVE_HAPPY)
|
||||
return FAILURE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ftp->is_passive = !ftp->is_passive;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
FILE *
|
||||
ftpGetURL(char *url, char *user, char *passwd, int *retcode)
|
||||
{
|
||||
#ifdef INET6
|
||||
return ftpGetURLAf(url, AF_UNSPEC, user, passwd, retcode);
|
||||
#else
|
||||
return ftpGetURLAf(url, AF_INET, user, passwd, retcode);
|
||||
#endif
|
||||
}
|
||||
|
||||
FILE *
|
||||
ftpGetURLAf(char *url, int af, char *user, char *passwd, int *retcode)
|
||||
{
|
||||
char host[255], name[255];
|
||||
int port;
|
||||
@ -364,7 +403,7 @@ ftpGetURL(char *url, char *user, char *passwd, int *retcode)
|
||||
prev_host = NULL;
|
||||
}
|
||||
}
|
||||
fp = ftpLogin(host, user, passwd, port, 0, retcode);
|
||||
fp = ftpLoginAf(host, af, user, passwd, port, 0, retcode);
|
||||
if (fp) {
|
||||
fp2 = ftpGet(fp, name, NULL);
|
||||
if (!fp2) {
|
||||
@ -384,6 +423,17 @@ ftpGetURL(char *url, char *user, char *passwd, int *retcode)
|
||||
|
||||
FILE *
|
||||
ftpPutURL(char *url, char *user, char *passwd, int *retcode)
|
||||
{
|
||||
#ifdef INET6
|
||||
return ftpPutURLAf(url, AF_UNSPEC, user, passwd, retcode);
|
||||
#else
|
||||
return ftpPutURLAf(url, AF_INET, user, passwd, retcode);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
FILE *
|
||||
ftpPutURLAf(char *url, int af, char *user, char *passwd, int *retcode)
|
||||
{
|
||||
char host[255], name[255];
|
||||
int port;
|
||||
@ -397,7 +447,7 @@ ftpPutURL(char *url, char *user, char *passwd, int *retcode)
|
||||
fp = NULL;
|
||||
}
|
||||
if (get_url_info(url, host, &port, name) == SUCCESS) {
|
||||
fp = ftpLogin(host, user, passwd, port, 0, retcode);
|
||||
fp = ftpLoginAf(host, af, user, passwd, port, 0, retcode);
|
||||
if (fp) {
|
||||
fp2 = ftpPut(fp, name);
|
||||
if (!fp2) {
|
||||
@ -672,12 +722,13 @@ cmd(FTP_t ftp, const char *fmt, ...)
|
||||
}
|
||||
|
||||
static int
|
||||
ftp_login_session(FTP_t ftp, char *host, char *user, char *passwd, int port, int verbose)
|
||||
ftp_login_session(FTP_t ftp, char *host, int af,
|
||||
char *user, char *passwd, int port, int verbose)
|
||||
{
|
||||
struct hostent *he = NULL;
|
||||
struct sockaddr_in sin;
|
||||
char pbuf[10];
|
||||
struct addrinfo hints, *res, *res0;
|
||||
int err;
|
||||
int s;
|
||||
unsigned long temp;
|
||||
int i;
|
||||
|
||||
if (networkInit() != SUCCESS)
|
||||
@ -698,30 +749,36 @@ ftp_login_session(FTP_t ftp, char *host, char *user, char *passwd, int port, int
|
||||
if (!port)
|
||||
port = 21;
|
||||
|
||||
temp = inet_addr(host);
|
||||
if (temp != INADDR_NONE) {
|
||||
ftp->addrtype = sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = temp;
|
||||
}
|
||||
else {
|
||||
he = gethostbyname(host);
|
||||
if (!he) {
|
||||
ftp->error = 0;
|
||||
return FAILURE;
|
||||
}
|
||||
ftp->addrtype = sin.sin_family = he->h_addrtype;
|
||||
bcopy(he->h_addr, (char *)&sin.sin_addr, he->h_length);
|
||||
}
|
||||
|
||||
sin.sin_port = htons(port);
|
||||
|
||||
if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0) {
|
||||
ftp->error = -1;
|
||||
snprintf(pbuf, sizeof(pbuf), "%d", port);
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = af;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = 0;
|
||||
err = getaddrinfo(host, pbuf, &hints, &res0);
|
||||
if (err) {
|
||||
ftp->error = 0;
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
|
||||
(void)close(s);
|
||||
s = -1;
|
||||
for (res = res0; res; res = res->ai_next) {
|
||||
ai_unmapped(res);
|
||||
ftp->addrtype = res->ai_family;
|
||||
|
||||
if ((s = socket(res->ai_family, res->ai_socktype,
|
||||
res->ai_protocol)) < 0)
|
||||
continue;
|
||||
|
||||
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
|
||||
(void)close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
freeaddrinfo(res0);
|
||||
if (s < 0) {
|
||||
ftp->error = errno;
|
||||
return FAILURE;
|
||||
}
|
||||
@ -745,11 +802,14 @@ ftp_login_session(FTP_t ftp, char *host, char *user, char *passwd, int port, int
|
||||
static int
|
||||
ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t *seekto)
|
||||
{
|
||||
int i,s;
|
||||
int i,l,s;
|
||||
char *q;
|
||||
unsigned char addr[64];
|
||||
struct sockaddr_in sin;
|
||||
u_long a;
|
||||
union sockaddr_cmn {
|
||||
struct sockaddr_in sin4;
|
||||
struct sockaddr_in6 sin6;
|
||||
} sin;
|
||||
char *cmdstr;
|
||||
|
||||
if (!fp)
|
||||
return FAILURE;
|
||||
@ -764,35 +824,101 @@ ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t
|
||||
}
|
||||
|
||||
if (ftp->is_passive) {
|
||||
if (ftp->is_verbose)
|
||||
fprintf(stderr, "Sending PASV\n");
|
||||
if (writes(ftp->fd_ctrl, "PASV\r\n")) {
|
||||
ftp_close(ftp);
|
||||
if (FtpTimedOut)
|
||||
ftp->error = FTP_TIMED_OUT;
|
||||
return FTP_TIMED_OUT;
|
||||
if (ftp->addrtype == AF_INET) {
|
||||
if (ftp->is_verbose)
|
||||
fprintf(stderr, "Sending PASV\n");
|
||||
if (writes(ftp->fd_ctrl, "PASV\r\n")) {
|
||||
ftp_close(ftp);
|
||||
if (FtpTimedOut)
|
||||
ftp->error = FTP_TIMED_OUT;
|
||||
return FTP_TIMED_OUT;
|
||||
}
|
||||
i = get_a_number(ftp, &q);
|
||||
if (check_code(ftp, i, FTP_PASSIVE_HAPPY)) {
|
||||
ftp_close(ftp);
|
||||
return i;
|
||||
}
|
||||
cmdstr = "PASV";
|
||||
} else {
|
||||
if (ftp->is_verbose)
|
||||
fprintf(stderr, "Sending EPSV\n");
|
||||
if (writes(ftp->fd_ctrl, "EPSV\r\n")) {
|
||||
ftp_close(ftp);
|
||||
if (FtpTimedOut)
|
||||
ftp->error = FTP_TIMED_OUT;
|
||||
return FTP_TIMED_OUT;
|
||||
}
|
||||
i = get_a_number(ftp, &q);
|
||||
if (check_code(ftp, i, FTP_EPASSIVE_HAPPY)) {
|
||||
if (ftp->is_verbose)
|
||||
fprintf(stderr, "Sending LPSV\n");
|
||||
if (writes(ftp->fd_ctrl, "LPSV\r\n")) {
|
||||
ftp_close(ftp);
|
||||
if (FtpTimedOut)
|
||||
ftp->error = FTP_TIMED_OUT;
|
||||
return FTP_TIMED_OUT;
|
||||
}
|
||||
i = get_a_number(ftp, &q);
|
||||
if (check_code(ftp, i, FTP_LPASSIVE_HAPPY)) {
|
||||
ftp_close(ftp);
|
||||
return i;
|
||||
}
|
||||
cmdstr = "LPSV";
|
||||
} else
|
||||
cmdstr = "EPSV";
|
||||
}
|
||||
i = get_a_number(ftp, &q);
|
||||
if (check_code(ftp, i, FTP_PASSIVE_HAPPY)) {
|
||||
ftp_close(ftp);
|
||||
return i;
|
||||
}
|
||||
while (*q && !isdigit(*q))
|
||||
while (*q && *q != '(') /* ) */
|
||||
q++;
|
||||
if (!*q) {
|
||||
ftp_close(ftp);
|
||||
return FAILURE;
|
||||
}
|
||||
q--;
|
||||
for (i = 0; i < 6; i++) {
|
||||
if (strcmp(cmdstr, "PASV") == 0 || strcmp(cmdstr, "LPSV") == 0) {
|
||||
l = (ftp->addrtype == AF_INET ? 6 : 21);
|
||||
for (i = 0; i < l; i++) {
|
||||
q++;
|
||||
addr[i] = strtol(q, &q, 10);
|
||||
}
|
||||
|
||||
sin.sin4.sin_family = ftp->addrtype;
|
||||
if (ftp->addrtype == AF_INET6) {
|
||||
sin.sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
bcopy(addr + 2, (char *)&sin.sin6.sin6_addr, 16);
|
||||
bcopy(addr + 19, (char *)&sin.sin6.sin6_port, 2);
|
||||
} else {
|
||||
sin.sin4.sin_len = sizeof(struct sockaddr_in);
|
||||
bcopy(addr, (char *)&sin.sin4.sin_addr, 4);
|
||||
bcopy(addr + 4, (char *)&sin.sin4.sin_port, 2);
|
||||
}
|
||||
} else if (strcmp(cmdstr, "EPSV") == 0) {
|
||||
int port;
|
||||
int sinlen;
|
||||
q++;
|
||||
addr[i] = strtol(q, &q, 10);
|
||||
if (sscanf(q, "%c%c%c%d%c", &addr[0], &addr[1], &addr[2],
|
||||
&port, &addr[3]) != 5
|
||||
|| addr[0] != addr[1] || addr[0] != addr[2] || addr[0] != addr[3]) {
|
||||
ftp_close(ftp);
|
||||
return FAILURE;
|
||||
}
|
||||
sinlen = sizeof(sin);
|
||||
if (getpeername(ftp->fd_ctrl, (struct sockaddr *)&sin, &sinlen) < 0) {
|
||||
ftp_close(ftp);
|
||||
return FAILURE;
|
||||
}
|
||||
switch (sin.sin4.sin_family) {
|
||||
case AF_INET:
|
||||
sin.sin4.sin_port = htons(port);
|
||||
break;
|
||||
case AF_INET6:
|
||||
sin.sin6.sin6_port = htons(port);
|
||||
break;
|
||||
default:
|
||||
ftp_close(ftp);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
sin.sin_family = ftp->addrtype;
|
||||
bcopy(addr, (char *)&sin.sin_addr, 4);
|
||||
bcopy(addr + 4, (char *)&sin.sin_port, 2);
|
||||
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
|
||||
if (connect(s, (struct sockaddr *)&sin, sin.sin4.sin_len) < 0) {
|
||||
(void)close(s);
|
||||
return FAILURE;
|
||||
}
|
||||
@ -817,39 +943,85 @@ ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t
|
||||
else {
|
||||
int fd,portrange;
|
||||
|
||||
#ifdef IPV6_PORTRANGE
|
||||
if (ftp->addrtype == AF_INET6) {
|
||||
portrange = IPV6_PORTRANGE_HIGH;
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_PORTRANGE, (char *)
|
||||
&portrange, sizeof(portrange)) < 0) {
|
||||
close(s);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef IP_PORTRANGE
|
||||
portrange = IP_PORTRANGE_HIGH;
|
||||
if (setsockopt(s, IPPROTO_IP, IP_PORTRANGE, (char *)
|
||||
&portrange, sizeof(portrange)) < 0) {
|
||||
close(s);
|
||||
return FAILURE;
|
||||
};
|
||||
if (ftp->addrtype == AF_INET) {
|
||||
portrange = IP_PORTRANGE_HIGH;
|
||||
if (setsockopt(s, IPPROTO_IP, IP_PORTRANGE, (char *)
|
||||
&portrange, sizeof(portrange)) < 0) {
|
||||
close(s);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
i = sizeof sin;
|
||||
getsockname(ftp->fd_ctrl, (struct sockaddr *)&sin, &i);
|
||||
sin.sin_port = 0;
|
||||
i = sizeof sin;
|
||||
sin.sin4.sin_port = 0;
|
||||
i = ((struct sockaddr *)&sin)->sa_len;
|
||||
if (bind(s, (struct sockaddr *)&sin, i) < 0) {
|
||||
close(s);
|
||||
return FAILURE;
|
||||
}
|
||||
i = sizeof sin;
|
||||
getsockname(s,(struct sockaddr *)&sin,&i);
|
||||
if (listen(s, 1) < 0) {
|
||||
close(s);
|
||||
return FAILURE;
|
||||
}
|
||||
a = ntohl(sin.sin_addr.s_addr);
|
||||
i = cmd(ftp, "PORT %d,%d,%d,%d,%d,%d",
|
||||
(a >> 24) & 0xff,
|
||||
(a >> 16) & 0xff,
|
||||
(a >> 8) & 0xff,
|
||||
a & 0xff,
|
||||
(ntohs(sin.sin_port) >> 8) & 0xff,
|
||||
ntohs(sin.sin_port) & 0xff);
|
||||
if (check_code(ftp, i, FTP_PORT_HAPPY)) {
|
||||
close(s);
|
||||
return i;
|
||||
if (sin.sin4.sin_family == AF_INET) {
|
||||
u_long a;
|
||||
a = ntohl(sin.sin4.sin_addr.s_addr);
|
||||
i = cmd(ftp, "PORT %d,%d,%d,%d,%d,%d",
|
||||
(a >> 24) & 0xff,
|
||||
(a >> 16) & 0xff,
|
||||
(a >> 8) & 0xff,
|
||||
a & 0xff,
|
||||
(ntohs(sin.sin4.sin_port) >> 8) & 0xff,
|
||||
ntohs(sin.sin4.sin_port) & 0xff);
|
||||
if (check_code(ftp, i, FTP_PORT_HAPPY)) {
|
||||
close(s);
|
||||
return i;
|
||||
}
|
||||
} else {
|
||||
#define UC(b) (((int)b)&0xff)
|
||||
char *a;
|
||||
char hname[INET6_ADDRSTRLEN];
|
||||
|
||||
if (getnameinfo((struct sockaddr *)&sin, sin.sin6.sin6_len,
|
||||
hname, sizeof(hname),
|
||||
NULL, 0, NI_NUMERICHOST) != 0) {
|
||||
goto try_lprt;
|
||||
}
|
||||
i = cmd(ftp, "EPRT |%d|%s|%d|", 2, hname,
|
||||
htons(sin.sin6.sin6_port));
|
||||
if (check_code(ftp, i, FTP_PORT_HAPPY)) {
|
||||
try_lprt:
|
||||
a = (char *)&sin.sin6.sin6_addr;
|
||||
i = cmd(ftp,
|
||||
"LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
|
||||
6, 16,
|
||||
UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]),
|
||||
UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]),
|
||||
UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]),
|
||||
UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]),
|
||||
2,
|
||||
(ntohs(sin.sin4.sin_port) >> 8) & 0xff,
|
||||
ntohs(sin.sin4.sin_port) & 0xff);
|
||||
if (check_code(ftp, i, FTP_PORT_HAPPY)) {
|
||||
close(s);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (seekto && *seekto) {
|
||||
i = cmd(ftp, "REST %d", *seekto);
|
||||
@ -881,3 +1053,30 @@ ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t
|
||||
else
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
static void
|
||||
ai_unmapped(struct addrinfo *ai)
|
||||
{
|
||||
struct sockaddr_in6 *sin6;
|
||||
struct sockaddr_in sin;
|
||||
|
||||
if (ai->ai_family != AF_INET6)
|
||||
return;
|
||||
if (ai->ai_addrlen != sizeof(struct sockaddr_in6) ||
|
||||
sizeof(sin) > ai->ai_addrlen)
|
||||
return;
|
||||
sin6 = (struct sockaddr_in6 *)ai->ai_addr;
|
||||
if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
|
||||
return;
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_len = sizeof(struct sockaddr_in);
|
||||
memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12],
|
||||
sizeof(sin.sin_addr));
|
||||
sin.sin_port = sin6->sin6_port;
|
||||
|
||||
ai->ai_family = AF_INET;
|
||||
memcpy(ai->ai_addr, &sin, sin.sin_len);
|
||||
ai->ai_addrlen = sin.sin_len;
|
||||
}
|
||||
|
@ -63,6 +63,9 @@ extern FILE *ftpGetURL(char *url, char *user, char *passwd, int *retcode);
|
||||
extern FILE *ftpPutURL(char *url, char *user, char *passwd, int *retcode);
|
||||
extern time_t ftpGetModtime(FILE *fp, char *s);
|
||||
extern const char *ftpErrString(int error);
|
||||
extern FILE *ftpLoginAf(char *host, int af, char *user, char *passwd, int port, int verbose, int *retcode);
|
||||
extern FILE *ftpGetURLAf(char *url, int af, char *user, char *passwd, int *retcode);
|
||||
extern FILE *ftpPutURLAf(char *url, int af, char *user, char *passwd, int *retcode);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _FTP_H_INCLUDE */
|
||||
|
Loading…
Reference in New Issue
Block a user