|
|
c00279 |
diff --git a/src/clients/FtpClient.cc b/src/clients/FtpClient.cc
|
|
|
c00279 |
index 777210c..4c80511 100644
|
|
|
c00279 |
--- a/src/clients/FtpClient.cc
|
|
|
c00279 |
+++ b/src/clients/FtpClient.cc
|
|
|
c00279 |
@@ -778,7 +778,8 @@ Ftp::Client::connectDataChannel()
|
|
|
c00279 |
bool
|
|
|
c00279 |
Ftp::Client::openListenSocket()
|
|
|
c00279 |
{
|
|
|
c00279 |
- return false;
|
|
|
c00279 |
+ debugs(9, 3, HERE);
|
|
|
c00279 |
+ return false;
|
|
|
c00279 |
}
|
|
|
c00279 |
|
|
|
c00279 |
/// creates a data channel Comm close callback
|
|
|
c00279 |
diff --git a/src/clients/FtpClient.h b/src/clients/FtpClient.h
|
|
|
c00279 |
index 465fdb7..75dbd3b 100644
|
|
|
c00279 |
--- a/src/clients/FtpClient.h
|
|
|
c00279 |
+++ b/src/clients/FtpClient.h
|
|
|
c00279 |
@@ -118,7 +118,7 @@ public:
|
|
|
c00279 |
bool sendPort();
|
|
|
c00279 |
bool sendPassive();
|
|
|
c00279 |
void connectDataChannel();
|
|
|
c00279 |
- bool openListenSocket();
|
|
|
c00279 |
+ virtual bool openListenSocket();
|
|
|
c00279 |
void switchTimeoutToDataChannel();
|
|
|
c00279 |
|
|
|
c00279 |
CtrlChannel ctrl; ///< FTP control channel state
|
|
|
c00279 |
diff --git a/src/clients/FtpGateway.cc b/src/clients/FtpGateway.cc
|
|
|
c00279 |
index a13cdda..b958b14 100644
|
|
|
c00279 |
--- a/src/clients/FtpGateway.cc
|
|
|
c00279 |
+++ b/src/clients/FtpGateway.cc
|
|
|
c00279 |
@@ -87,6 +87,13 @@ struct GatewayFlags {
|
|
|
c00279 |
class Gateway;
|
|
|
c00279 |
typedef void (StateMethod)(Ftp::Gateway *);
|
|
|
c00279 |
|
|
|
c00279 |
+} // namespace FTP
|
|
|
c00279 |
+
|
|
|
c00279 |
+static void ftpOpenListenSocket(Ftp::Gateway * ftpState, int fallback);
|
|
|
c00279 |
+
|
|
|
c00279 |
+namespace Ftp
|
|
|
c00279 |
+{
|
|
|
c00279 |
+
|
|
|
c00279 |
/// FTP Gateway: An FTP client that takes an HTTP request with an ftp:// URI,
|
|
|
c00279 |
/// converts it into one or more FTP commands, and then
|
|
|
c00279 |
/// converts one or more FTP responses into the final HTTP response.
|
|
|
c00279 |
@@ -137,7 +144,11 @@ public:
|
|
|
c00279 |
|
|
|
c00279 |
/// create a data channel acceptor and start listening.
|
|
|
c00279 |
void listenForDataChannel(const Comm::ConnectionPointer &conn;;
|
|
|
c00279 |
-
|
|
|
c00279 |
+ virtual bool openListenSocket() {
|
|
|
c00279 |
+ debugs(9, 3, HERE);
|
|
|
c00279 |
+ ftpOpenListenSocket(this, 0);
|
|
|
c00279 |
+ return Comm::IsConnOpen(data.conn);
|
|
|
c00279 |
+ }
|
|
|
c00279 |
int checkAuth(const HttpHeader * req_hdr);
|
|
|
c00279 |
void checkUrlpath();
|
|
|
c00279 |
void buildTitleUrl();
|
|
|
c00279 |
@@ -1792,6 +1803,7 @@ ftpOpenListenSocket(Ftp::Gateway * ftpState, int fallback)
|
|
|
c00279 |
}
|
|
|
c00279 |
|
|
|
c00279 |
ftpState->listenForDataChannel(temp);
|
|
|
c00279 |
+ ftpState->data.listenConn = temp;
|
|
|
c00279 |
}
|
|
|
c00279 |
|
|
|
c00279 |
static void
|
|
|
c00279 |
@@ -1827,13 +1839,19 @@ ftpSendPORT(Ftp::Gateway * ftpState)
|
|
|
c00279 |
// pull out the internal IP address bytes to send in PORT command...
|
|
|
c00279 |
// source them from the listen_conn->local
|
|
|
c00279 |
|
|
|
c00279 |
+ struct sockaddr_in addr;
|
|
|
c00279 |
+ socklen_t addrlen = sizeof(addr);
|
|
|
c00279 |
+ getsockname(ftpState->data.listenConn->fd, (struct sockaddr *) &addr, &addrlen);
|
|
|
c00279 |
+ unsigned char port_high = ntohs(addr.sin_port) >> 8;
|
|
|
c00279 |
+ unsigned char port_low = ntohs(addr.sin_port) & 0xff;
|
|
|
c00279 |
+
|
|
|
c00279 |
struct addrinfo *AI = NULL;
|
|
|
c00279 |
ftpState->data.listenConn->local.getAddrInfo(AI, AF_INET);
|
|
|
c00279 |
unsigned char *addrptr = (unsigned char *) &((struct sockaddr_in*)AI->ai_addr)->sin_addr;
|
|
|
c00279 |
- unsigned char *portptr = (unsigned char *) &((struct sockaddr_in*)AI->ai_addr)->sin_port;
|
|
|
c00279 |
+ // unsigned char *portptr = (unsigned char *) &((struct sockaddr_in*)AI->ai_addr)->sin_port;
|
|
|
c00279 |
snprintf(cbuf, CTRL_BUFLEN, "PORT %d,%d,%d,%d,%d,%d\r\n",
|
|
|
c00279 |
addrptr[0], addrptr[1], addrptr[2], addrptr[3],
|
|
|
c00279 |
- portptr[0], portptr[1]);
|
|
|
c00279 |
+ port_high, port_low);
|
|
|
c00279 |
ftpState->writeCommand(cbuf);
|
|
|
c00279 |
ftpState->state = Ftp::Client::SENT_PORT;
|
|
|
c00279 |
|
|
|
c00279 |
@@ -1886,14 +1904,27 @@ ftpSendEPRT(Ftp::Gateway * ftpState)
|
|
|
c00279 |
return;
|
|
|
c00279 |
}
|
|
|
c00279 |
|
|
|
c00279 |
+
|
|
|
c00279 |
+ unsigned int port;
|
|
|
c00279 |
+ struct sockaddr_storage addr;
|
|
|
c00279 |
+ socklen_t addrlen = sizeof(addr);
|
|
|
c00279 |
+ getsockname(ftpState->data.listenConn->fd, (struct sockaddr *) &addr, &addrlen);
|
|
|
c00279 |
+ if (addr.ss_family == AF_INET) {
|
|
|
c00279 |
+ struct sockaddr_in *addr4 = (struct sockaddr_in*) &addr;
|
|
|
c00279 |
+ port = ntohs( addr4->sin_port );
|
|
|
c00279 |
+ } else {
|
|
|
c00279 |
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &addr;
|
|
|
c00279 |
+ port = ntohs( addr6->sin6_port );
|
|
|
c00279 |
+ }
|
|
|
c00279 |
+
|
|
|
c00279 |
char buf[MAX_IPSTRLEN];
|
|
|
c00279 |
|
|
|
c00279 |
/* RFC 2428 defines EPRT as IPv6 equivalent to IPv4 PORT command. */
|
|
|
c00279 |
/* Which can be used by EITHER protocol. */
|
|
|
c00279 |
- snprintf(cbuf, CTRL_BUFLEN, "EPRT |%d|%s|%d|\r\n",
|
|
|
c00279 |
+ snprintf(cbuf, CTRL_BUFLEN, "EPRT |%d|%s|%u|\r\n",
|
|
|
c00279 |
( ftpState->data.listenConn->local.isIPv6() ? 2 : 1 ),
|
|
|
c00279 |
ftpState->data.listenConn->local.toStr(buf,MAX_IPSTRLEN),
|
|
|
c00279 |
- ftpState->data.listenConn->local.port() );
|
|
|
c00279 |
+ port);
|
|
|
c00279 |
|
|
|
c00279 |
ftpState->writeCommand(cbuf);
|
|
|
c00279 |
ftpState->state = Ftp::Client::SENT_EPRT;
|
|
|
c00279 |
@@ -1912,7 +1943,7 @@ ftpReadEPRT(Ftp::Gateway * ftpState)
|
|
|
c00279 |
ftpSendPORT(ftpState);
|
|
|
c00279 |
return;
|
|
|
c00279 |
}
|
|
|
c00279 |
-
|
|
|
c00279 |
+ ftpState->ctrl.message = NULL;
|
|
|
c00279 |
ftpRestOrList(ftpState);
|
|
|
c00279 |
}
|
|
|
c00279 |
|