diff options
| author | Garrett D'Amore <garrett@damore.org> | 2018-08-19 08:07:02 -0700 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2018-08-27 08:00:23 -0700 |
| commit | 83b7a9afec7b3659974c614cea69fa3abb904d24 (patch) | |
| tree | 7277bda8deb32c91614f236fb942a4c6cfbbe55b /src/platform/posix | |
| parent | 1c3350f6f4a738815c39a67dc0ba1a953a1b9f03 (diff) | |
| download | nng-83b7a9afec7b3659974c614cea69fa3abb904d24.tar.gz nng-83b7a9afec7b3659974c614cea69fa3abb904d24.tar.bz2 nng-83b7a9afec7b3659974c614cea69fa3abb904d24.zip | |
fixes #608 Add TCP support to specify local network interface
This also fixes a leaked TCP connection on a failure path, which we
noticed while working this change.
Diffstat (limited to 'src/platform/posix')
| -rw-r--r-- | src/platform/posix/posix_tcp.h | 8 | ||||
| -rw-r--r-- | src/platform/posix/posix_tcpdial.c | 46 |
2 files changed, 51 insertions, 3 deletions
diff --git a/src/platform/posix/posix_tcp.h b/src/platform/posix/posix_tcp.h index aefce7f7..633a63b5 100644 --- a/src/platform/posix/posix_tcp.h +++ b/src/platform/posix/posix_tcp.h @@ -25,9 +25,11 @@ struct nni_tcp_conn { }; struct nni_tcp_dialer { - nni_list connq; // pending connections - bool closed; - nni_mtx mtx; + nni_list connq; // pending connections + bool closed; + struct sockaddr_storage src; + size_t srclen; + nni_mtx mtx; }; struct nni_tcp_listener { diff --git a/src/platform/posix/posix_tcpdial.c b/src/platform/posix/posix_tcpdial.c index ab3f3545..918ee9ba 100644 --- a/src/platform/posix/posix_tcpdial.c +++ b/src/platform/posix/posix_tcpdial.c @@ -149,6 +149,46 @@ tcp_dialer_cb(nni_posix_pfd *pfd, int ev, void *arg) nni_aio_finish(aio, 0, 0); } +int +nni_tcp_dialer_set_src_addr(nni_tcp_dialer *d, const nni_sockaddr *sa) +{ + struct sockaddr_storage ss; + struct sockaddr_in * sin; + struct sockaddr_in6 * sin6; + size_t sslen; + + if ((sslen = nni_posix_nn2sockaddr(&ss, sa)) == 0) { + return (NNG_EADDRINVAL); + } + // Ensure we are either IPv4 or IPv6, and port is not set. (We + // do not allow binding to a specific port.) + switch (ss.ss_family) { + case AF_INET: + sin = (void *) &ss; + if (sin->sin_port != 0) { + return (NNG_EADDRINVAL); + } + break; + case AF_INET6: + sin6 = (void *) &ss; + if (sin6->sin6_port != 0) { + return (NNG_EADDRINVAL); + } + break; + default: + return (NNG_EADDRINVAL); + } + nni_mtx_lock(&d->mtx); + if (d->closed) { + nni_mtx_unlock(&d->mtx); + return (NNG_ECLOSED); + } + d->src = ss; + d->srclen = sslen; + nni_mtx_unlock(&d->mtx); + return (0); +} + // We don't give local address binding support. Outbound dialers always // get an ephemeral port. void @@ -196,6 +236,12 @@ nni_tcp_dialer_dial(nni_tcp_dialer *d, const nni_sockaddr *sa, nni_aio *aio) rv = NNG_ECLOSED; goto error; } + if (d->srclen != 0) { + if ((rv = bind(fd, (void *) &d->src, d->srclen)) != 0) { + rv = nni_plat_errno(errno); + goto error; + } + } if ((rv = nni_aio_schedule(aio, tcp_dialer_cancel, d)) != 0) { goto error; } |
