int ftp_data(FTP_CON * con, const char *command, const char *file) /* open data socket */ { struct sockaddr_in data, from; struct hostent *host; char host_name[256]; int listen_socket, data_socket; unsigned int len = sizeof(data), fromlen = sizeof(from); int one = 1, status; char *a, *b; memset(&data, 0, sizeof(data)); memset(&from, 0, sizeof(from)); if (gethostname(host_name, sizeof(host_name)) == -1) return FTP_NET_ERROR; if ((host = (struct hostent *) gethostbyname(host_name)) == 0) return FTP_NET_ERROR; if ((listen_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) return FTP_NET_ERROR; if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)) < 0) { closesocket(listen_socket); return FTP_NET_ERROR; } data.sin_family = AF_INET; data.sin_port = htons(0); data.sin_addr.s_addr = *(unsigned long *) *(host->h_addr_list); if (bind(listen_socket, (struct sockaddr *) &data, sizeof(data)) == -1) { closesocket(listen_socket); return FTP_NET_ERROR; } #ifdef OS_WINNT if (getsockname(listen_socket, (struct sockaddr *) &data, (int *)&len) < 0) { #else if (getsockname(listen_socket, (struct sockaddr *) &data, &len) < 0) { #endif closesocket(listen_socket); return FTP_NET_ERROR; } if (listen(listen_socket, 1) != 0) { closesocket(listen_socket); return FTP_NET_ERROR; } a = (char *) &data.sin_addr; b = (char *) &data.sin_port; status = ftp_port(con, FTP_CUT(a[0]), FTP_CUT(a[1]), FTP_CUT(a[2]), FTP_CUT(a[3]), FTP_CUT(b[0]), FTP_CUT(b[1])); if (status != FTP_SUCCESS) return FTP_NET_ERROR; status = ftp_command(con, command, file, 200, 120, 150, 125, 250, EOF); if (status >= 0) return status; #ifdef OS_WINNT data_socket = accept(listen_socket, (struct sockaddr *) &from, (int *)&fromlen); #else data_socket = accept(listen_socket, (struct sockaddr *) &from, &fromlen); #endif if (data_socket == -1) { closesocket(listen_socket); return FTP_NET_ERROR; } closesocket(listen_socket); con->data = data_socket; return status; } /*------------------------------------------------------------------*/ int ftp_close(FTP_CON * con) /* close data connection */ { char str[256]; closesocket(con->data); return ftp_get_message(con, str); }
// // Open data connection // Returns -1 upon failure; a socket descriptor upon success. // static int opendataconn( struct opusftp_globals *ogp, struct ftp_info *info ) { int ts; // Temporary socket LONG len = sizeof(struct sockaddr_in); // Length of socket address int reply; // Reply from FTP commands int bad_pasv = FALSE; // Passive unavailable? // PASV known not to work on this site? if (info->fi_flags & FTP_NO_PASV) bad_pasv = TRUE; // PASV option not enabled? if (!(info->fi_flags & FTP_PASSIVE)) bad_pasv = TRUE; // Create temporary socket if ((ts = socket( AF_INET, SOCK_STREAM, 0 )) >= 0) { // Passive mode? Try it first. if (!bad_pasv) { // Send PASV command to FTP server int pasvreply; pasvreply=ftp_pasv( info ); switch (pasvreply) { case 227: // correct reply if (pasv_to_address( &info->fi_addr, info->fi_iobuf )) { if (connect( ts, (struct sockaddr *)&info->fi_addr, sizeof(info->fi_addr) ) >= 0) return(ts); } bad_pasv = TRUE; break; case 421: // sockect closed by timeout CloseSocket( ts ); return(-1); default: D(bug( "Pasv failed returns %ld\n",pasvreply)); bad_pasv = TRUE; } } // Sendport mode - Passive may have just failed above if (bad_pasv || (info->fi_flags & FTP_NO_PASV)) { getsockname( info->fi_cs, (struct sockaddr*)&info->fi_addr, &len ); // Set port to zero so the system will pick one info->fi_addr.sin_port = 0; if (bind( ts, (struct sockaddr *)&info->fi_addr, sizeof(info->fi_addr) ) >= 0) { // The system will now fill in the port number it picked if (getsockname( ts, (struct sockaddr*)&info->fi_addr, &len ) >= 0) { if (listen( ts, 1 ) >= 0) { // Can TIMEOUT //reply = ftp_port( info, 0, (char *)&info->fi_addr.sin_addr, (char *)&info->fi_addr.sin_port ); reply = ftp_port( info, 0, &info->fi_addr ); if (reply/100 == COMPLETE) return(ts); } else { D(bug( "** listen fail\n" )); info->fi_errno = FTPERR_LISTEN_FAIL; } } else { D(bug( "** getsockname fail\n" )); info->fi_errno = FTPERR_GETSOCKNAME_FAIL; } } else { D(bug( "** bind fail\n" )); info->fi_errno = FTPERR_BIND_FAIL; } } CloseSocket( ts ); } else info->fi_errno = FTPERR_SOCKET_FAIL; return (-1) ; }