diff options
Diffstat (limited to 'loader2')
-rw-r--r-- | loader2/ftp.c | 183 | ||||
-rw-r--r-- | loader2/ftp.h | 3 | ||||
-rw-r--r-- | loader2/urls.c | 2 |
3 files changed, 139 insertions, 49 deletions
diff --git a/loader2/ftp.c b/loader2/ftp.c index 6e6d402a9..6d7969f95 100644 --- a/loader2/ftp.c +++ b/loader2/ftp.c @@ -250,11 +250,13 @@ static int getHostAddress(const char * host, void * address, int family) { int ftpOpen(char *host, int family, char *name, char *password, char *proxy, int port) { static int sock; - struct in_addr serverAddress; + struct in_addr addr; + struct in6_addr addr6; struct sockaddr_in destPort; + struct sockaddr_in6 destPort6; struct passwd * pw; char * buf; - int rc; + int rc = 0; if (port < 0) port = IPPORT_FTP; @@ -279,20 +281,37 @@ int ftpOpen(char *host, int family, char *name, char *password, host = proxy; } - if ((rc = getHostAddress(host, &serverAddress, AF_INET))) return rc; + if (family == AF_INET) + rc = getHostAddress(host, &addr, AF_INET); + else if (family == AF_INET6) + rc = getHostAddress(host, &addr6, AF_INET6); - sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + if (rc) + return rc; + + sock = socket(family, SOCK_STREAM, IPPROTO_IP); if (sock < 0) { return FTPERR_FAILED_CONNECT; } - destPort.sin_family = AF_INET; - destPort.sin_port = htons(port); - destPort.sin_addr = serverAddress; + if (family == AF_INET) { + destPort.sin_family = family; + destPort.sin_port = htons(port); + destPort.sin_addr = addr; - if (connect(sock, (struct sockaddr *) &destPort, sizeof(destPort))) { - close(sock); - return FTPERR_FAILED_CONNECT; + if (connect(sock, (struct sockaddr *) &destPort, sizeof(destPort))) { + close(sock); + return FTPERR_FAILED_CONNECT; + } + } else if (family == AF_INET6) { + destPort6.sin6_family = family; + destPort6.sin6_port = htons(port); + destPort6.sin6_addr = addr6; + + if (connect(sock, (struct sockaddr *) &destPort6, sizeof(destPort6))) { + close(sock); + return FTPERR_FAILED_CONNECT; + } } /* ftpCheckResponse() assumes the socket is nonblocking */ @@ -323,55 +342,115 @@ int ftpOpen(char *host, int family, char *name, char *password, return sock; } -int ftpGetFileDesc(int sock, char * remotename) { +int ftpGetFileDesc(int sock, struct in6_addr host, int family, + char * remotename) { int dataSocket; struct sockaddr_in dataAddress; + struct sockaddr_in6 dataAddress6; int i, j; char * passReply; char * chptr; char * retrCommand; int rc; - if (write(sock, "PASV\r\n", 6) != 6) { - return FTPERR_SERVER_IO_ERROR; + if (family == AF_INET) { + if (write(sock, "PASV\r\n", 6) != 6) { + return FTPERR_SERVER_IO_ERROR; + } + } else if (family == AF_INET6) { + if (write(sock, "EPSV\r\n", 6) != 6) { + return FTPERR_SERVER_IO_ERROR; + } } - if ((rc = ftpCheckResponse(sock, &passReply))) - return FTPERR_PASSIVE_ERROR; - chptr = passReply; - while (*chptr && *chptr != '(') chptr++; - if (*chptr != '(') return FTPERR_PASSIVE_ERROR; - chptr++; - passReply = chptr; - while (*chptr && *chptr != ')') chptr++; - if (*chptr != ')') return FTPERR_PASSIVE_ERROR; - *chptr-- = '\0'; - - while (*chptr && *chptr != ',') chptr--; - if (*chptr != ',') return FTPERR_PASSIVE_ERROR; - chptr--; - while (*chptr && *chptr != ',') chptr--; - if (*chptr != ',') return FTPERR_PASSIVE_ERROR; - *chptr++ = '\0'; - - /* now passReply points to the IP portion, and chptr points to the - port number portion */ - - dataAddress.sin_family = AF_INET; - if (sscanf(chptr, "%d,%d", &i, &j) != 2) { + if ((rc = ftpCheckResponse(sock, &passReply))) { return FTPERR_PASSIVE_ERROR; } - dataAddress.sin_port = htons((i << 8) + j); - chptr = passReply; - while (*chptr++) { - if (*chptr == ',') *chptr = '.'; + /* get IP address and port number from server response */ + if (family == AF_INET) { + /* we have a PASV response of the form: + * 227 Entering Passive Mode (209,132,176,30,57,229) + * where 209.132.176.30 is the IP, and 57 & 229 are the ports + */ + chptr = passReply; + while (*chptr && *chptr != '(') chptr++; + if (*chptr != '(') { + return FTPERR_PASSIVE_ERROR; + } + chptr++; + passReply = chptr; + while (*chptr && *chptr != ')') chptr++; + if (*chptr != ')') { + return FTPERR_PASSIVE_ERROR; + } + *chptr-- = '\0'; + while (*chptr && *chptr != ',') chptr--; + if (*chptr != ',') { + return FTPERR_PASSIVE_ERROR; + } + chptr--; + while (*chptr && *chptr != ',') chptr--; + if (*chptr != ',') { + return FTPERR_PASSIVE_ERROR; + } + *chptr++ = '\0'; + + /* now passReply points to the IP portion + * and chptr points to the port number portion + */ + if (sscanf(chptr, "%d,%d", &i, &j) != 2) { + return FTPERR_PASSIVE_ERROR; + } + } else if (family == AF_INET6) { + /* we have an EPSV response of the form: + * 229 Entering Extended Passive Mode (|||51626|) + * where 51626 is the port + */ + chptr = passReply; + while (*chptr && *chptr != '(') chptr++; + if (*chptr != '(') { + return FTPERR_PASSIVE_ERROR; + } + chptr++; + while (*chptr && *chptr == '|') chptr++; + passReply = chptr; + while (*chptr && *chptr != '|') chptr++; + *chptr = '\0'; + chptr = passReply; + + /* now chptr contains our port number */ + if (sscanf(chptr, "%d", &i) != 1) { + return FTPERR_PASSIVE_ERROR; + } } - if (!inet_pton(AF_INET, passReply, &dataAddress.sin_addr)) - return FTPERR_PASSIVE_ERROR; + /* build our sockaddr */ + if (family == AF_INET) { + dataAddress.sin_family = family; + dataAddress.sin_port = htons((i << 8) + j); + + /* passReply contains the IP address, but with commands insteaad of + * periods, so change those + */ + chptr = passReply; + while (*chptr++) { + if (*chptr == ',') *chptr = '.'; + } - dataSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + if (!inet_pton(family, passReply, &dataAddress.sin_addr)) { + return FTPERR_PASSIVE_ERROR; + } + } else if (family == AF_INET6) { + dataAddress6.sin6_family = family; + dataAddress6.sin6_port = htons(i); + + /* we don't get this in an EPSV reply, but we got it as a param */ + memset(&dataAddress6.sin6_addr, 0, sizeof(struct in6_addr)); + memcpy(&dataAddress6.sin6_addr, &host, sizeof(host)); + } + + dataSocket = socket(family, SOCK_STREAM, IPPROTO_IP); if (dataSocket < 0) { return FTPERR_FAILED_CONNECT; } @@ -384,10 +463,18 @@ int ftpGetFileDesc(int sock, char * remotename) { return FTPERR_SERVER_IO_ERROR; } - if (connect(dataSocket, (struct sockaddr *) &dataAddress, - sizeof(dataAddress))) { - close(dataSocket); - return FTPERR_FAILED_DATA_CONNECT; + if (family == AF_INET) { + if (connect(dataSocket, (struct sockaddr *) &dataAddress, + sizeof(dataAddress))) { + close(dataSocket); + return FTPERR_FAILED_DATA_CONNECT; + } + } else if (family == AF_INET6) { + if (connect(dataSocket, (struct sockaddr *) &dataAddress6, + sizeof(dataAddress6))) { + close(dataSocket); + return FTPERR_FAILED_DATA_CONNECT; + } } if ((rc = ftpCheckResponse(sock, NULL))) { @@ -625,3 +712,5 @@ int httpGetFileDesc(char * hostname, int port, char * remotename, char *extraHea return sock; } + +/* vim:set shiftwidth=4 softtabstop=4: */ diff --git a/loader2/ftp.h b/loader2/ftp.h index 99f7329d3..1c2a1c634 100644 --- a/loader2/ftp.h +++ b/loader2/ftp.h @@ -25,7 +25,8 @@ const char * ftpStrerror(int ftpErrno, urlprotocol protocol); int ftpOpen(char * host, int family, char * name, char * password, char * proxy, int port); int ftpGetFile(int sock, char * remotename, int dest); -int ftpGetFileDesc(int sock, char * remotename); +int ftpGetFileDesc(int sock, struct in6_addr host, int family, + char * remotename); int ftpGetFileDone(int sock); int httpGetFileDesc(char * hostname, int port, char * remotename, char *extraHeaders); diff --git a/loader2/urls.c b/loader2/urls.c index d13a83f5f..ad76683f4 100644 --- a/loader2/urls.c +++ b/loader2/urls.c @@ -196,7 +196,7 @@ int urlinstStartTransfer(struct iurlinfo * ui, char * filename, return -2; } - fd = ftpGetFileDesc(ui->ftpPort, buf); + fd = ftpGetFileDesc(ui->ftpPort, addr6, family, buf); if (fd < 0) { close(ui->ftpPort); if (!silentErrors) |