diff options
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/ftp/fetch.c | 33 | ||||
-rw-r--r-- | usr.bin/ftp/ftp.c | 49 | ||||
-rw-r--r-- | usr.bin/ftp/ftp_var.h | 2 | ||||
-rw-r--r-- | usr.bin/ftp/main.c | 3 |
4 files changed, 71 insertions, 16 deletions
diff --git a/usr.bin/ftp/fetch.c b/usr.bin/ftp/fetch.c index a494e7e..bc8adf1 100644 --- a/usr.bin/ftp/fetch.c +++ b/usr.bin/ftp/fetch.c @@ -219,26 +219,47 @@ url_get(origline, proxyenv) { s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s == -1) { + res = res->ai_next; + if (res) + continue; warn("Can't create socket"); goto cleanup_url_get; } - if (dobind && bind(s, (struct sockaddr *)&bindto, - ((struct sockaddr *)&bindto)->sa_len) == -1) { - getnameinfo((struct sockaddr *)&bindto, - ((struct sockaddr *)&bindto)->sa_len, + if (dobind) { + struct addrinfo *bindres; + int binderr = -1; + + for (bindres = bindres0; + bindres != NULL; + bindres = bindres->ai_next) + if (bindres->ai_family == res->ai_family) + break; + if (bindres == NULL) + bindres = bindres0; + binderr = bind(s, bindres->ai_addr, bindres->ai_addrlen); + if (binderr == -1) + { + res = res->ai_next; + if (res) { + (void)close(s); + continue; + } + getnameinfo(bindres->ai_addr, bindres->ai_addrlen, nameinfo, sizeof(nameinfo), NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID); /* XXX check error? */ warn("Can't bind to %s", nameinfo); goto cleanup_url_get; + } } if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { - close(s); res = res->ai_next; - if (res) + if (res) { + (void)close(s); continue; + } warn("Can't connect to %s", host); goto cleanup_url_get; } diff --git a/usr.bin/ftp/ftp.c b/usr.bin/ftp/ftp.c index 1fe1c75..c31cb94 100644 --- a/usr.bin/ftp/ftp.c +++ b/usr.bin/ftp/ftp.c @@ -143,19 +143,40 @@ hookup(host0, port) while (1) { s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s < 0) { + res = res->ai_next; + if (res) + continue; warn("socket"); code = -1; return (0); } - if (dobind && - bind(s, (struct sockaddr *)&bindto, - ((struct sockaddr *)&bindto)->sa_len) == -1) { + if (dobind) { + struct addrinfo *bindres; + int binderr = -1; + + for (bindres = bindres0; + bindres != NULL; + bindres = bindres->ai_next) + if (bindres->ai_family == res->ai_family) + break; + if (bindres == NULL) + bindres = bindres0; + binderr = bind(s, bindres->ai_addr, + bindres->ai_addrlen); + if (binderr == -1) + { + res = res->ai_next; + if (res) { + (void)close(s); + continue; + } warn("bind"); - goto next; + code = -1; + goto bad; + } } if (connect(s, res->ai_addr, res->ai_addrlen) == 0) break; - next: if (res->ai_next) { char hname[INET6_ADDRSTRLEN]; getnameinfo(res->ai_addr, res->ai_addrlen, @@ -1159,10 +1180,24 @@ initconn() warn("socket"); return (1); } - if (dobind && bind(data, (struct sockaddr *)&bindto, - ((struct sockaddr *)&bindto)->sa_len) == -1) { + if (dobind) { + struct addrinfo *bindres; + int binderr = -1; + + for (bindres = bindres0; + bindres != NULL; + bindres = bindres->ai_next) + if (bindres->ai_family == data_addr.su_family) + break; + if (bindres == NULL) + bindres = bindres0; + binderr = bind(data, bindres->ai_addr, + bindres->ai_addrlen); + if (binderr == -1) + { warn("bind"); goto bad; + } } if ((options & SO_DEBUG) && setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, diff --git a/usr.bin/ftp/ftp_var.h b/usr.bin/ftp/ftp_var.h index cd9b0bd..8694bcc 100644 --- a/usr.bin/ftp/ftp_var.h +++ b/usr.bin/ftp/ftp_var.h @@ -144,7 +144,7 @@ char *httpport; /* port number to use for http connections */ char *gateport; /* port number to use for gateftp connections */ int dobind; /* bind to specific address */ -struct sockaddr_storage bindto; /* address to bind to */ +struct addrinfo * bindres0; /* addrinfo for address to bind to */ jmp_buf toplevel; /* non-local goto stuff for cmd scanner */ diff --git a/usr.bin/ftp/main.c b/usr.bin/ftp/main.c index 5a1e5e6..48bf77e 100644 --- a/usr.bin/ftp/main.c +++ b/usr.bin/ftp/main.c @@ -237,8 +237,7 @@ main(argc, argv) warnx("%s", strerror(errno)); exit(1); } - memcpy(&bindto, res->ai_addr, res->ai_addrlen); - freeaddrinfo(res); + bindres0 = res; } /* |