--- ./src/ftp.cc 2013-07-13 15:22:32.000000000 +0200 +++ ./src/ftp.cc 2013-12-21 15:39:23.015056228 +0100 @@ -2816,6 +2816,7 @@ } ftpState->listenForDataChannel(temp, ftpState->entry->url()); + ftpState->data.listenConn = temp; } /// \ingroup ServerProtocolFTPInternal @@ -2851,14 +2852,19 @@ // pull out the internal IP address bytes to send in PORT command... // source them from the listen_conn->local - + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + getsockname(ftpState->data.listenConn->fd, (struct sockaddr *) &addr, &addrlen); + unsigned char port_high = ntohs(addr.sin_port) >> 8; + unsigned char port_low = ntohs(addr.sin_port) & 0xff; + struct addrinfo *AI = NULL; ftpState->data.listenConn->local.GetAddrInfo(AI, AF_INET); unsigned char *addrptr = (unsigned char *) &((struct sockaddr_in*)AI->ai_addr)->sin_addr; - unsigned char *portptr = (unsigned char *) &((struct sockaddr_in*)AI->ai_addr)->sin_port; + // unsigned char *portptr = (unsigned char *) &((struct sockaddr_in*)AI->ai_addr)->sin_port; snprintf(cbuf, CTRL_BUFLEN, "PORT %d,%d,%d,%d,%d,%d\r\n", addrptr[0], addrptr[1], addrptr[2], addrptr[3], - portptr[0], portptr[1]); + port_high, port_low); ftpState->writeCommand(cbuf); ftpState->state = SENT_PORT; @@ -2907,15 +2913,25 @@ ftpFail(ftpState); return; } - - char buf[MAX_IPSTRLEN]; - + unsigned int port; + struct sockaddr_storage addr; + socklen_t addrlen = sizeof(addr); + getsockname(ftpState->data.listenConn->fd, (struct sockaddr *) &addr, &addrlen); + if (addr.ss_family == AF_INET) { + struct sockaddr_in *addr4 = (struct sockaddr_in*) &addr; + port = ntohs( addr4->sin_port ); + } else { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &addr; + port = ntohs( addr6->sin6_port ); + } + + char buf[MAX_IPSTRLEN]; /* RFC 2428 defines EPRT as IPv6 equivalent to IPv4 PORT command. */ /* Which can be used by EITHER protocol. */ - snprintf(cbuf, CTRL_BUFLEN, "EPRT |%d|%s|%d|\r\n", + snprintf(cbuf, CTRL_BUFLEN, "EPRT |%d|%s|%u|\r\n", ( ftpState->data.listenConn->local.IsIPv6() ? 2 : 1 ), ftpState->data.listenConn->local.NtoA(buf,MAX_IPSTRLEN), - ftpState->data.listenConn->local.GetPort() ); + port); ftpState->writeCommand(cbuf); ftpState->state = SENT_EPRT;