- sockaddr_in Addr;
- sockaddr_in Addr2;
- socklen_t Jnk = sizeof(Addr);
- if (getsockname(DataListenFd,(sockaddr *)&Addr,&Jnk) < 0)
- return _error->Errno("getsockname","Could not determine the socket's name");
- Jnk = sizeof(Addr2);
- if (getsockname(ServerFd,(sockaddr *)&Addr2,&Jnk) < 0)
- return _error->Errno("getsockname","Could not determine the socket's name");
-
- // This bit ripped from qftp
- unsigned long badr = ntohl(*(unsigned long *)&Addr2.sin_addr);
- unsigned long bp = ntohs(Addr.sin_port);
-
- // Send the port command
+ struct sockaddr_storage Addr;
+ socklen_t AddrLen = sizeof(Addr);
+ if (getsockname(DataListenFd,(sockaddr *)&Addr,&AddrLen) < 0)
+ return _error->Errno("getsockname",_("Could not determine the socket's name"));
+
+
+ // Reverse the address. We need the server address and the data port.
+ char Name[NI_MAXHOST];
+ char Service[NI_MAXSERV];
+ char Service2[NI_MAXSERV];
+ getnameinfo((struct sockaddr *)&Addr,AddrLen,
+ Name,sizeof(Name),Service,sizeof(Service),
+ NI_NUMERICHOST|NI_NUMERICSERV);
+ getnameinfo((struct sockaddr *)&ServerAddr,ServerAddrLen,
+ Name,sizeof(Name),Service2,sizeof(Service2),
+ NI_NUMERICHOST|NI_NUMERICSERV);
+
+ // Send off an IPv4 address in the old port format
+ if (((struct sockaddr *)&Addr)->sa_family == AF_INET &&
+ ForceExtended == false)
+ {
+ // Convert the dots in the quad into commas
+ for (char *I = Name; *I != 0; I++)
+ if (*I == '.')
+ *I = ',';
+ unsigned long Port = atoi(Service);
+
+ // Send the port command
+ unsigned int Tag;
+ string Msg;
+ if (WriteMsg(Tag,Msg,"PORT %s,%d,%d",
+ Name,
+ (int)(Port >> 8) & 0xff, (int)(Port & 0xff)) == false)
+ return false;
+ if (Tag >= 400)
+ return _error->Error(_("Unable to send PORT command"));
+ return true;
+ }
+
+ // Construct an EPRT command
+ unsigned Proto = 0;
+ for (unsigned J = 0; AFMap[J].Family != 0; J++)
+ if (AFMap[J].Family == ((struct sockaddr *)&Addr)->sa_family)
+ Proto = AFMap[J].IETFFamily;
+ if (Proto == 0)
+ return _error->Error(_("Unknown address family %u (AF_*)"),
+ ((struct sockaddr *)&Addr)->sa_family);
+
+ // Send the EPRT command