--- adt.c Thu Feb 15 02:20:45 2001 +++ adt-passive.c Sun May 26 01:50:48 2002 @@ -171,9 +171,9 @@ char *FindDesc = "Performing local case insensitive substring search"; char GotComplete, GotLocal, GotRecent, FilesAreRemote; char Flat, Readme, Silent, Path[250], Action; char InitialSetup; -char Connected; +char Connected, Passive_FTP; char MaskSIGINT, GotSIGINT; int (*disp_init) (); int (*disp_cleanup) (); @@ -2039,8 +2039,43 @@ return (result >= 100) && (result < 400); } +int bftp_getdataconnection_passive(struct sockaddr_in *sin, char *buf) { + int d, i, a[7]; + char *p = buf; + + /* send PASV command */ + if (!bftp_io) return -1; + fflush(bftp_io); rewind(bftp_io); + fputs("PASV\r\n", bftp_io); + fflush(bftp_io); rewind(bftp_io); + if (!fgets(buf, BFTP_BUFSIZE, bftp_io)) return -1; + + /* response should be "227 Entering Passive Mode (A,B,C,D,E,F)\r\n" + * where A-F are numbers from 0 to 255. The IP address to connect + * to for data is A.B.C.D, and the port is (E<<8 + F) + */ + for (i = 0; i < 7; i++) { + d = 0; + while (*p && (*p < '0' || *p > '9')) p++; + while (*p && (*p >= '0' && *p <= '9')) d = ((d * 10) + (*p-'0')), p++; + if (d > 255) return -1; + a[i] = d; + } + + if (!*p || (a[0] != 227)) return -1; + + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = htonl((a[1]<<24) | (a[2]<<16) | (a[3]<<8) | a[4]); + sin->sin_port = htons((a[5]<<8) | a[6]); + + i = sizeof(struct sockaddr_in); + if ((d = socket(PF_INET, SOCK_STREAM, 0)) < 0) return -1; + if (connect(d, (struct sockaddr *) sin, i) < 0) { close(d); return -1; } + return d; +} + int bftp_getdataconnection() { struct sockaddr_in sin; struct hostent *hp; @@ -2092,13 +2127,22 @@ sprintf(buf, "Getting %s...", remote); progress(buf); - if ((s = bftp_getdataconnection()) >= 0) { + s = (Passive_FTP) + ? bftp_getdataconnection_passive(&sin, buf) + : bftp_getdataconnection(); + if (s >= 0) { sprintf(buf, "RETR %s\n", remote); if (bftp_cmd(buf)) { i = sizeof(sin); - if ((d = accept(s, (struct sockaddr *) & sin, &i)) >= 0) { + if (Passive_FTP) { + d = s; s = -1; + } + else { + d = accept(s, (struct sockaddr *) & sin, &i); + } + if (d >= 0) { if ((out = fopen(local, "w"))) { int len, k, start = time(NULL), t; float kps; @@ -2273,8 +2317,9 @@ int bftp_init() { Connected = 0; + Passive_FTP = 0; trans_options = bftp_options; trans_connect = bftp_connect; trans_disconnect = bftp_disconnect; trans_remopen = bftp_remopen; @@ -2283,8 +2328,15 @@ return 0; } +int pftp_init() +{ + bftp_init(); + Passive_FTP = 1; + return 0; +} + #endif /* =================================FIND CLIENT=============================== */ #ifndef NO_FIND_CLIENT @@ -4144,8 +4196,9 @@ TRANSFER TransferTypes[] = { #ifndef NO_BUILTIN_FTP "bftp", "Builtin FTP: Use internal ftp routines to download files ", bftp_init, + "pftp", "Passive FTP: passive-mode ftp. useful if you are firewalled ", pftp_init, #endif #ifndef NO_EXTERNAL_FTP "ftp", "External FTP: Use the 'ftp' program to download files ", xftp_init, #endif