diff options
author | shin <shin@FreeBSD.org> | 2000-02-12 17:59:06 +0000 |
---|---|---|
committer | shin <shin@FreeBSD.org> | 2000-02-12 17:59:06 +0000 |
commit | ce3ac581a39661c68d153da77856c5e521e5e322 (patch) | |
tree | 5f721cc349fd60fa07883c1edea9d3e50d92730c /usr.bin/ftp/ftp.c | |
parent | 0a2a73d5508f74fa8b717c3afbf2c50e4c14150c (diff) | |
download | FreeBSD-src-ce3ac581a39661c68d153da77856c5e521e5e322.zip FreeBSD-src-ce3ac581a39661c68d153da77856c5e521e5e322.tar.gz |
Add more dual stack consideration.
-Should retry as much as possible when dest addr and
source addr(specified with -s option) address family
missmatch happend
Approved by: jkh
Diffstat (limited to 'usr.bin/ftp/ftp.c')
-rw-r--r-- | usr.bin/ftp/ftp.c | 49 |
1 files changed, 42 insertions, 7 deletions
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, |