diff options
Diffstat (limited to 'lib/libfetch')
-rw-r--r-- | lib/libfetch/common.c | 35 | ||||
-rw-r--r-- | lib/libfetch/common.h | 1 | ||||
-rw-r--r-- | lib/libfetch/fetch.3 | 5 |
3 files changed, 37 insertions, 4 deletions
diff --git a/lib/libfetch/common.c b/lib/libfetch/common.c index c01837a..ea1c81d 100644 --- a/lib/libfetch/common.c +++ b/lib/libfetch/common.c @@ -227,6 +227,28 @@ _fetch_ref(conn_t *conn) /* + * Bind a socket to a specific local address + */ +int +_fetch_bind(int sd, int af, const char *addr) +{ + struct addrinfo hints, *res, *res0; + int err; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = af; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + if ((err = getaddrinfo(addr, NULL, &hints, &res0)) != 0) + return (-1); + for (res = res0; res; res = res->ai_next) + if (bind(sd, res->ai_addr, res->ai_addrlen) == 0) + return (0); + return (-1); +} + + +/* * Establish a TCP connection to the specified port on the specified host. */ conn_t * @@ -234,6 +256,7 @@ _fetch_connect(const char *host, int port, int af, int verbose) { conn_t *conn; char pbuf[10]; + const char *bindaddr; struct addrinfo hints, *res, *res0; int sd, err; @@ -252,19 +275,25 @@ _fetch_connect(const char *host, int port, int af, int verbose) _netdb_seterr(err); return (NULL); } + bindaddr = getenv("FETCH_BIND_ADDRESS"); if (verbose) _fetch_info("connecting to %s:%d", host, port); /* try to connect */ - for (sd = -1, res = res0; res; res = res->ai_next) { + for (sd = -1, res = res0; res; sd = -1, res = res->ai_next) { if ((sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) continue; - if (connect(sd, res->ai_addr, res->ai_addrlen) != -1) + if (bindaddr != NULL && *bindaddr != '\0' && + _fetch_bind(sd, res->ai_family, bindaddr) != 0) { + _fetch_info("failed to bind to '%s'", bindaddr); + close(sd); + continue; + } + if (connect(sd, res->ai_addr, res->ai_addrlen) == 0) break; close(sd); - sd = -1; } freeaddrinfo(res0); if (sd == -1) { diff --git a/lib/libfetch/common.h b/lib/libfetch/common.h index adc0f38..6f65259 100644 --- a/lib/libfetch/common.h +++ b/lib/libfetch/common.h @@ -76,6 +76,7 @@ void _fetch_syserr(void); void _fetch_info(const char *, ...); int _fetch_default_port(const char *); int _fetch_default_proxy_port(const char *); +int _fetch_bind(int, int, const char *); conn_t *_fetch_connect(const char *, int, int, int); conn_t *_fetch_reopen(int); conn_t *_fetch_ref(conn_t *); diff --git a/lib/libfetch/fetch.3 b/lib/libfetch/fetch.3 index 540b42f..5bbfa2e 100644 --- a/lib/libfetch/fetch.3 +++ b/lib/libfetch/fetch.3 @@ -444,7 +444,10 @@ Invalid URL The accompanying error message includes a protocol-specific error code and message, e.g. "File is not available (404 Not Found)" .Sh ENVIRONMENT -.Bl -tag -width FTP_PASSIVE_MODE +.Bl -tag -width FETCH_BIND_ADDRESS +.It Ev FETCH_BIND_ADDRESS +Specifies a hostname or IP address to which sockets used for outgoing +connections will be bound. .It Ev FTP_LOGIN Default FTP login if none was provided in the URL. .It Ev FTP_PASSIVE_MODE |