Blob Blame History Raw
--- ./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;