diff options
Diffstat (limited to 'src/platform/posix/posix_sockaddr.c')
| -rw-r--r-- | src/platform/posix/posix_sockaddr.c | 75 |
1 files changed, 62 insertions, 13 deletions
diff --git a/src/platform/posix/posix_sockaddr.c b/src/platform/posix/posix_sockaddr.c index dc795cfe..a569132c 100644 --- a/src/platform/posix/posix_sockaddr.c +++ b/src/platform/posix/posix_sockaddr.c @@ -25,13 +25,14 @@ size_t nni_posix_nn2sockaddr(void *sa, const nni_sockaddr *na) { - struct sockaddr_in * sin; - struct sockaddr_in6 * sin6; - struct sockaddr_un * spath; - const nng_sockaddr_in * nsin; - const nng_sockaddr_in6 * nsin6; - const nng_sockaddr_path *nspath; - size_t sz; + struct sockaddr_in * sin; + struct sockaddr_in6 * sin6; + struct sockaddr_un * spath; + const nng_sockaddr_in * nsin; + const nng_sockaddr_in6 * nsin6; + const nng_sockaddr_path * nspath; + const nng_sockaddr_abstract *nsabs; + size_t sz; if ((sa == NULL) || (na == NULL)) { return (0); @@ -70,12 +71,33 @@ nni_posix_nn2sockaddr(void *sa, const nni_sockaddr *na) } spath->sun_family = PF_UNIX; return (sizeof(*spath)); + + case NNG_AF_ABSTRACT: + spath = (void *) sa; + nsabs = &na->s_abstract; + if (nsabs->sa_len >= sizeof (spath->sun_path)) { + return (0); + } + memset(spath, 0, sizeof(*spath)); + spath->sun_family = PF_UNIX; + spath->sun_path[0] = '\0'; // abstract starts with nul + + // We support auto-bind with an empty string. There is + // a subtle caveat here, which is that we cannot bind to + // the *empty* name. + if (nsabs->sa_len == 0) { + return (sizeof (sa_family_t)); // auto bind + } else { + memcpy(&spath->sun_path[1], nsabs->sa_name, + nsabs->sa_len); + return (sizeof(sa_family_t) + 1 + nsabs->sa_len); + } } return (0); } int -nni_posix_sockaddr2nn(nni_sockaddr *na, const void *sa) +nni_posix_sockaddr2nn(nni_sockaddr *na, const void *sa, size_t sz) { const struct sockaddr_in * sin; const struct sockaddr_in6 *sin6; @@ -83,12 +105,16 @@ nni_posix_sockaddr2nn(nni_sockaddr *na, const void *sa) nng_sockaddr_in * nsin; nng_sockaddr_in6 * nsin6; nng_sockaddr_path * nspath; + nng_sockaddr_abstract * nsabs; if ((na == NULL) || (sa == NULL)) { return (-1); } switch (((struct sockaddr *) sa)->sa_family) { case AF_INET: + if (sz < sizeof(*sin)) { + return (-1); + } sin = (void *) sa; nsin = &na->s_in; nsin->sa_family = NNG_AF_INET; @@ -96,6 +122,9 @@ nni_posix_sockaddr2nn(nni_sockaddr *na, const void *sa) nsin->sa_addr = sin->sin_addr.s_addr; break; case AF_INET6: + if (sz < sizeof(*sin6)) { + return (-1); + } sin6 = (void *) sa; nsin6 = &na->s_in6; nsin6->sa_family = NNG_AF_INET6; @@ -104,11 +133,31 @@ nni_posix_sockaddr2nn(nni_sockaddr *na, const void *sa) memcpy(nsin6->sa_addr, sin6->sin6_addr.s6_addr, 16); break; case AF_UNIX: - spath = (void *) sa; - nspath = &na->s_ipc; - nspath->sa_family = NNG_AF_IPC; - (void) snprintf(nspath->sa_path, sizeof(nspath->sa_path), "%s", - spath->sun_path); + // AF_UNIX can be NNG_AF_IPC, or NNG_AF_ABSTRACT. + spath = (void *) sa; + if ((sz < sizeof(sa_family_t)) || (sz > sizeof(*spath))) { + return (-1); + } + // Now we need to look more closely. + sz -= sizeof(sa_family_t); + if (sz == 0) { + // Unnamed socket. These will be treated using + // auto-bind if we actually listen to them, and + // it is impossible to connect them. + nsabs = &na->s_abstract; + nsabs->sa_family = NNG_AF_ABSTRACT; + nsabs->sa_len = 0; + } else if (spath->sun_path[0] == 0) { + nsabs = &na->s_abstract; + nsabs->sa_family = NNG_AF_ABSTRACT; + nsabs->sa_len = sz - 1; + memcpy(nsabs->sa_name, &spath->sun_path[1], sz - 1); + } else { + nspath = &na->s_ipc; + nspath->sa_family = NNG_AF_IPC; + nni_strlcpy(nspath->sa_path, spath->sun_path, + sizeof(nspath->sa_path)); + } break; default: // We should never see this - the OS should always be |
