summaryrefslogtreecommitdiff
path: root/src/platform/posix/posix_sockaddr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/posix/posix_sockaddr.c')
-rw-r--r--src/platform/posix/posix_sockaddr.c75
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