static int ftp_init_transfer(void) { if (!ftp_connected()) return -1; if (!sock_dup(ftp->ctrl, &ftp->data)) return -1; if (ftp_is_passive()) { ftp_trace("Initializing passive connection.\n"); struct sockaddr_storage sa; memcpy(&sa, sock_remote_addr(ftp->ctrl), sizeof(struct sockaddr_storage)); unsigned char pac[6] = { 0 }; unsigned short ipv6_port = { 0 }; if (!ftp_pasv(sa.ss_family != AF_INET, pac, &ipv6_port)) { ftp_trace("PASV/EPSV failed.\n"); sock_destroy(ftp->data); ftp->data = NULL; return -1; } socklen_t len = sizeof(struct sockaddr_in); if (sa.ss_family == AF_INET) { memcpy(&((struct sockaddr_in*)&sa)->sin_addr, pac, (size_t)4); memcpy(&((struct sockaddr_in*)&sa)->sin_port, pac+4, (size_t)2); } #ifdef HAVE_IPV6 else if (sa.ss_family == AF_INET6) { ((struct sockaddr_in6*)&sa)->sin6_port = htons(ipv6_port); len = sizeof(struct sockaddr_in6); } #endif else { ftp_trace("Do not know how to handle family %d.\n", sa.ss_family); sock_destroy(ftp->data); ftp->data = NULL; return -1; } struct sockaddr_storage tmp; memcpy(&tmp, sock_remote_addr(ftp->ctrl), sizeof(struct sockaddr_storage)); if (is_reserved((struct sockaddr*) &sa) || is_multicast((struct sockaddr*) &sa) || (is_private((struct sockaddr*) &sa) != is_private((struct sockaddr*) &tmp)) || (is_loopback((struct sockaddr*) &sa) != is_loopback((struct sockaddr*) &tmp))) { // Invalid address returned by PASV. Replace with address from control // socket. ftp_err(_("Address returned by PASV seems to be incorrect.\n")); ((struct sockaddr_in*)&sa)->sin_addr = ((struct sockaddr_in*)&tmp)->sin_addr; } if (!sock_connect_addr(ftp->data, (struct sockaddr*) &sa, len)) { ftp_trace("Could not connect to address from PASV/EPSV.\n"); perror("connect()"); sock_destroy(ftp->data); ftp->data = NULL; return -1; } } else { ftp_trace("Initializing active connection.\n"); const struct sockaddr* local = sock_local_addr(ftp->data); sock_listen(ftp->data, local->sa_family); if (local->sa_family == AF_INET) { struct sockaddr_in* tmp = (struct sockaddr_in*)local; unsigned char* a = (unsigned char *)&tmp->sin_addr; unsigned char* p = (unsigned char *)&tmp->sin_port; ftp_set_tmp_verbosity(vbError); ftp_cmd("PORT %d,%d,%d,%d,%d,%d", a[0], a[1], a[2], a[3], p[0], p[1]); } #ifdef HAVE_IPV6 else if (local->sa_family == AF_INET6) { char* addr = printable_address(local); ftp_set_tmp_verbosity(vbError); ftp_cmd("EPRT |2|%s|%u|", addr, ntohs(((struct sockaddr_in6*)local)->sin6_port)); free(addr); } #endif else { ftp_trace("Do not know how to handle family %d.\n", local->sa_family); sock_destroy(ftp->data); ftp->data = NULL; return -1; } if(ftp->code != ctComplete) { ftp_trace("PORT/EPRT not successful\n"); sock_destroy(ftp->data); ftp->data = NULL; return -1; } } sock_throughput(ftp->data); return 0; }
int ftp_open_url(url_t *urlp, bool reset_vars) { bool use_proxy; int i; if(reset_vars) ftp_reset_vars(); /* don't assume server is in ascii mode initially even if RFC says so */ ftp->prev_type = '?'; #ifdef HAVE_POSIX_SIGSETJMP if(sigsetjmp(open_timeout_jmp, 1)) #else if(setjmp(open_timeout_jmp)) #endif { ftp_close(); ftp_err(_("Connection timeout after %u seconds\n"), ftp->open_timeout); return 1; } ftp_set_signal(SIGALRM, ftp_open_handler); alarm(ftp->open_timeout); use_proxy = (proxy_type(urlp) != 0); ftp_err(_("Looking up %s... "), use_proxy ? gvProxyUrl->hostname : urlp->hostname); /* Set the default port (22) for SSH if no port is specified. We * need to do this here, 'cause host_lookup() sets it to 21 * (default port for vanilla FTP) */ if(urlp->protocol) { if(strcmp(urlp->protocol, "sftp") == 0) url_setprotocol(urlp, "ssh"); if(strcmp(urlp->protocol, "ssh") == 0 && urlp->port == -1) urlp->port = 22; /* default SSH port */ } ftp->host = host_create(use_proxy ? gvProxyUrl : urlp); if(!host_lookup(ftp->host)) { herror(host_getname(ftp->host)); alarm(0); ftp_set_signal(SIGALRM, SIG_IGN); return -1; } /* keep the value in urlp->port urlp->port = ntohs(ftp->host->port); and set it to 21 if it is -1 */ if(urlp->port == -1) { urlp->port = 21; } fprintf(stderr, "\r "); i = strlen(use_proxy ? gvProxyUrl->hostname : urlp->hostname); while(i--) fprintf(stderr, " "); fprintf(stderr, "\r"); ftp_trace("\n"); #ifdef HAVE_LIBSSH if(urlp->protocol && strcmp(urlp->protocol, "ssh") == 0) { int ret = ssh_open_url(urlp); alarm(0); return ret; } #endif if(urlp->protocol && strcmp(urlp->protocol, "ftp") != 0) { ftp_err(_("Sorry, don't know how to handle your '%s' protocol\n" "trying 'ftp' instead...\n"), urlp->protocol); url_setprotocol(urlp, 0); } if(use_proxy) { ftp_err(_("Connecting to proxy %s at port %d...\n"), host_getoname(ftp->host), urlp->port); } else { ftp_err(_("Connecting to %s at port %d...\n"), host_getoname(ftp->host), urlp->port); } ftp->ctrl = sock_create(); if (ftp->ctrl == 0) { ftp_err(_("Unable to create socket.\n")); alarm(0); ftp_set_signal(SIGALRM, SIG_IGN); return -1; } if(!sock_connect_host(ftp->ctrl, ftp->host)) { alarm(0); ftp_set_signal(SIGALRM, SIG_IGN); return -1; } sock_lowdelay(ftp->ctrl); char* ip = host_getip(ftp->host); ftp_err(_("Connected to %s ([%s]:%d).\n"), host_getoname(ftp->host), ip, urlp->port); free(ip); /* read startup message from server */ ftp_set_tmp_verbosity(vbCommand); ftp_read_reply(); if(ftp->fullcode == 120) { ftp_set_tmp_verbosity(vbCommand); ftp_read_reply(); } alarm(0); ftp_set_signal(SIGALRM, SIG_IGN); if(!sock_connected(ftp->ctrl)) { ftp_close(); return 1; } ftp->connected = (ftp->fullcode == 220); if(ftp->connected) { void (*tracefunq)(const char *fmt, ...); url_destroy(ftp->url); ftp->url = url_clone(urlp); tracefunq = (ftp->verbosity == vbDebug ? ftp_err : ftp_trace); char* remote_addr = printable_address(sock_remote_addr(ftp->ctrl)), *local_addr = printable_address(sock_local_addr(ftp->ctrl)); tracefunq("remote address: %s\n", remote_addr); tracefunq("local address: %s\n", local_addr); free(remote_addr); free(local_addr); return 0; } else { ftp_close(); return 1; } }
static int ftp_init_transfer(void) { struct sockaddr_storage sa; unsigned char *a, *p; if(!ftp_connected()) return -1; if (!(ftp->data = sock_create())) { return -1; } sock_copy(ftp->data, ftp->ctrl); if (ftp_is_passive()) { memcpy(&sa, sock_remote_addr(ftp->ctrl), sizeof(struct sockaddr_storage)); unsigned char pac[6]; unsigned short ipv6_port; if (!ftp_pasv(sa.ss_family != AF_INET, pac, &ipv6_port)) goto err1; socklen_t len = sizeof(struct sockaddr_in); if (sa.ss_family == AF_INET) { memcpy(&((struct sockaddr_in*)&sa)->sin_addr, pac, (size_t)4); memcpy(&((struct sockaddr_in*)&sa)->sin_port, pac+4, (size_t)2); } #ifdef HAVE_IPV6 else if (sa.ss_family == AF_INET6) { ((struct sockaddr_in6*)&sa)->sin6_port = htons(ipv6_port); len = sizeof(struct sockaddr_in6); } #endif else return -1; struct sockaddr_storage tmp; memcpy(&tmp, sock_remote_addr(ftp->ctrl), sizeof(struct sockaddr_storage)); if (is_reserved((struct sockaddr*) &sa) || is_multicast((struct sockaddr*) &sa) || (is_private((struct sockaddr*) &sa) != is_private((struct sockaddr*) &tmp)) || (is_loopback((struct sockaddr*) &sa) != is_loopback((struct sockaddr*) &tmp))) { // Invalid address returned by PASV. Replace with address from control // socket. ftp_err(_("Address returned by PASV seems to be incorrect.\n")); ((struct sockaddr_in*)&sa)->sin_addr = ((struct sockaddr_in*)&tmp)->sin_addr; } if (!sock_connect_addr(ftp->data, (struct sockaddr*) &sa, len)) { perror("connect()"); goto err1; } } else { const struct sockaddr* local = sock_local_addr(ftp->data); sock_listen(ftp->data, local->sa_family); if (local->sa_family == AF_INET) { struct sockaddr_in* tmp = (struct sockaddr_in*)local; a = (unsigned char *)&tmp->sin_addr; p = (unsigned char *)&tmp->sin_port; ftp_set_tmp_verbosity(vbError); ftp_cmd("PORT %d,%d,%d,%d,%d,%d", a[0], a[1], a[2], a[3], p[0], p[1]); } #ifdef HAVE_IPV6 else if (local->sa_family == AF_INET6) { char* addr = printable_address(local); ftp_set_tmp_verbosity(vbError); ftp_cmd("EPRT |2|%s|%u", addr, ntohs(((struct sockaddr_in6*)local)->sin6_port)); free(addr); } #endif else goto err1; if(ftp->code != ctComplete) goto err1; } sock_throughput(ftp->data); return 0; err1: sock_destroy(ftp->data); ftp->data = 0; return -1; }