aboutsummaryrefslogtreecommitdiff
path: root/src/platform
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform')
-rw-r--r--src/platform/posix/posix_aio.h3
-rw-r--r--src/platform/posix/posix_epdesc.c55
-rw-r--r--src/platform/posix/posix_ipc.c16
-rw-r--r--src/platform/posix/posix_tcp.c2
-rw-r--r--src/platform/windows/win_ipc.c52
5 files changed, 110 insertions, 18 deletions
diff --git a/src/platform/posix/posix_aio.h b/src/platform/posix/posix_aio.h
index 15dae06c..3954f225 100644
--- a/src/platform/posix/posix_aio.h
+++ b/src/platform/posix/posix_aio.h
@@ -34,7 +34,7 @@ extern int nni_posix_pipedesc_sockname(nni_posix_pipedesc *, nni_sockaddr *);
extern int nni_posix_pipedesc_set_nodelay(nni_posix_pipedesc *, bool);
extern int nni_posix_pipedesc_set_keepalive(nni_posix_pipedesc *, bool);
-extern int nni_posix_epdesc_init(nni_posix_epdesc **);
+extern int nni_posix_epdesc_init(nni_posix_epdesc **, int);
extern void nni_posix_epdesc_set_local(nni_posix_epdesc *, void *, size_t);
extern void nni_posix_epdesc_set_remote(nni_posix_epdesc *, void *, size_t);
extern void nni_posix_epdesc_fini(nni_posix_epdesc *);
@@ -43,5 +43,6 @@ extern void nni_posix_epdesc_connect(nni_posix_epdesc *, nni_aio *);
extern int nni_posix_epdesc_listen(nni_posix_epdesc *);
extern void nni_posix_epdesc_accept(nni_posix_epdesc *, nni_aio *);
extern int nni_posix_epdesc_sockname(nni_posix_epdesc *, nni_sockaddr *);
+extern int nni_posix_epdesc_set_permissions(nni_posix_epdesc *, mode_t);
#endif // PLATFORM_POSIX_AIO_H
diff --git a/src/platform/posix/posix_epdesc.c b/src/platform/posix/posix_epdesc.c
index f97f12b8..0f63304f 100644
--- a/src/platform/posix/posix_epdesc.c
+++ b/src/platform/posix/posix_epdesc.c
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/un.h>
@@ -38,10 +39,13 @@ struct nni_posix_epdesc {
nni_list connectq;
nni_list acceptq;
bool closed;
+ bool started;
struct sockaddr_storage locaddr;
struct sockaddr_storage remaddr;
socklen_t loclen;
socklen_t remlen;
+ mode_t perms; // UNIX sockets only
+ int mode; // end point mode (dialer/listener)
nni_mtx mtx;
};
@@ -287,17 +291,35 @@ nni_posix_epdesc_listen(nni_posix_epdesc *ed)
#endif
if (bind(fd, (struct sockaddr *) ss, len) < 0) {
- nni_mtx_unlock(&ed->mtx);
rv = nni_plat_errno(errno);
+ nni_mtx_unlock(&ed->mtx);
(void) close(fd);
return (rv);
}
+ // For UNIX domain sockets, optionally set the permission bits.
+ // This is done after the bind and before listen, and on the file
+ // rather than the file descriptor.
+ // Experiments have shown that chmod() works correctly, provided that
+ // it is done *before* the listen() operation, whereas fchmod seems to
+ // have no impact. This behavior was observed on both macOS and Linux.
+ // YMMV on other platforms.
+ if ((ss->ss_family == AF_UNIX) && (ed->perms != 0)) {
+ struct sockaddr_un *sun = (void *) ss;
+ mode_t perms = ed->perms & ~(S_IFMT);
+ if ((rv = chmod(sun->sun_path, perms)) != 0) {
+ rv = nni_plat_errno(errno);
+ nni_mtx_unlock(&ed->mtx);
+ close(fd);
+ return (rv);
+ }
+ }
+
// Listen -- 128 depth is probably sufficient. If it isn't, other
// bad things are going to happen.
if (listen(fd, 128) != 0) {
- nni_mtx_unlock(&ed->mtx);
rv = nni_plat_errno(errno);
+ nni_mtx_unlock(&ed->mtx);
(void) close(fd);
return (rv);
}
@@ -311,6 +333,7 @@ nni_posix_epdesc_listen(nni_posix_epdesc *ed)
nni_mtx_unlock(&ed->mtx);
return (rv);
}
+ ed->started = true;
nni_mtx_unlock(&ed->mtx);
return (0);
}
@@ -384,6 +407,7 @@ nni_posix_epdesc_connect(nni_posix_epdesc *ed, nni_aio *aio)
if ((rv = connect(fd, (void *) &ed->remaddr, ed->remlen)) == 0) {
// Immediate connect, cool! This probably only happens on
// loopback, and probably not on every platform.
+ ed->started = true;
nni_posix_epdesc_finish(aio, 0, fd);
nni_mtx_unlock(&ed->mtx);
return;
@@ -403,6 +427,7 @@ nni_posix_epdesc_connect(nni_posix_epdesc *ed, nni_aio *aio)
// We have to submit to the pollq, because the connection is pending.
ed->node.fd = fd;
+ ed->started = true;
if ((rv = nni_posix_pollq_add(&ed->node)) != 0) {
ed->node.fd = -1;
nni_mtx_unlock(&ed->mtx);
@@ -418,7 +443,7 @@ nni_posix_epdesc_connect(nni_posix_epdesc *ed, nni_aio *aio)
}
int
-nni_posix_epdesc_init(nni_posix_epdesc **edp)
+nni_posix_epdesc_init(nni_posix_epdesc **edp, int mode)
{
nni_posix_epdesc *ed;
int rv;
@@ -439,6 +464,9 @@ nni_posix_epdesc_init(nni_posix_epdesc **edp)
ed->node.data = ed;
ed->node.fd = -1;
ed->closed = false;
+ ed->started = false;
+ ed->perms = 0; // zero means use default (no change)
+ ed->mode = mode;
nni_aio_list_init(&ed->connectq);
nni_aio_list_init(&ed->acceptq);
@@ -476,6 +504,27 @@ nni_posix_epdesc_set_remote(nni_posix_epdesc *ed, void *sa, size_t len)
nni_mtx_unlock(&ed->mtx);
}
+int
+nni_posix_epdesc_set_permissions(nni_posix_epdesc *ed, mode_t mode)
+{
+ nni_mtx_lock(&ed->mtx);
+ if (ed->mode != NNI_EP_MODE_LISTEN) {
+ nni_mtx_unlock(&ed->mtx);
+ return (NNG_ENOTSUP);
+ }
+ if (ed->started) {
+ nni_mtx_unlock(&ed->mtx);
+ return (NNG_EBUSY);
+ }
+ if ((mode & S_IFMT) != 0) {
+ nni_mtx_unlock(&ed->mtx);
+ return (NNG_EINVAL);
+ }
+ ed->perms = mode | S_IFSOCK; // we set IFSOCK to ensure non-zero
+ nni_mtx_unlock(&ed->mtx);
+ return (0);
+}
+
void
nni_posix_epdesc_fini(nni_posix_epdesc *ed)
{
diff --git a/src/platform/posix/posix_ipc.c b/src/platform/posix/posix_ipc.c
index f7cfc0db..c1bb9292 100644
--- a/src/platform/posix/posix_ipc.c
+++ b/src/platform/posix/posix_ipc.c
@@ -49,7 +49,7 @@ nni_plat_ipc_ep_init(nni_plat_ipc_ep **epp, const nni_sockaddr *sa, int mode)
int rv;
struct sockaddr_un sun;
- if ((rv = nni_posix_epdesc_init(&ed)) != 0) {
+ if ((rv = nni_posix_epdesc_init(&ed, mode)) != 0) {
return (rv);
}
switch (mode) {
@@ -87,6 +87,20 @@ nni_plat_ipc_ep_close(nni_plat_ipc_ep *ep)
nni_posix_epdesc_close((void *) ep);
}
+int
+nni_plat_ipc_ep_set_permissions(nni_plat_ipc_ep *ep, uint32_t bits)
+{
+ return (nni_posix_epdesc_set_permissions((void *) ep, (mode_t) bits));
+}
+
+int
+nni_plat_ipc_ep_set_security_descriptor(nni_plat_ipc_ep *ep, void *attr)
+{
+ NNI_ARG_UNUSED(ep);
+ NNI_ARG_UNUSED(attr);
+ return (NNG_ENOTSUP);
+}
+
// UNIX DOMAIN SOCKETS -- these have names in the file namespace.
// We are going to check to see if there was a name already there.
// If there was, and nothing is listening (ECONNREFUSED), then we
diff --git a/src/platform/posix/posix_tcp.c b/src/platform/posix/posix_tcp.c
index 81ec330b..c00f9433 100644
--- a/src/platform/posix/posix_tcp.c
+++ b/src/platform/posix/posix_tcp.c
@@ -36,7 +36,7 @@ nni_plat_tcp_ep_init(nni_plat_tcp_ep **epp, const nni_sockaddr *lsa,
NNI_ARG_UNUSED(mode);
- if ((rv = nni_posix_epdesc_init(&ed)) != 0) {
+ if ((rv = nni_posix_epdesc_init(&ed, mode)) != 0) {
return (rv);
}
diff --git a/src/platform/windows/win_ipc.c b/src/platform/windows/win_ipc.c
index d372f639..7d118672 100644
--- a/src/platform/windows/win_ipc.c
+++ b/src/platform/windows/win_ipc.c
@@ -21,14 +21,15 @@ struct nni_plat_ipc_pipe {
};
struct nni_plat_ipc_ep {
- char path[NNG_MAXADDRLEN + 16];
- nni_sockaddr addr;
- int mode;
- int started;
- HANDLE p; // accept side only
- nni_win_event acc_ev; // accept side only
- nni_aio * con_aio; // conn side only
- nni_list_node node; // conn side uses this
+ char path[NNG_MAXADDRLEN + 16];
+ nni_sockaddr addr;
+ int mode;
+ bool started;
+ HANDLE p; // accept side only
+ nni_win_event acc_ev; // accept side only
+ nni_aio * con_aio; // conn side only
+ nni_list_node node; // conn side uses this
+ SECURITY_ATTRIBUTES sec_attr;
};
static int nni_win_ipc_pipe_start(nni_win_event *, nni_aio *);
@@ -203,7 +204,10 @@ nni_plat_ipc_ep_init(nni_plat_ipc_ep **epp, const nni_sockaddr *sa, int mode)
}
ZeroMemory(ep, sizeof(*ep));
- ep->mode = mode;
+ ep->mode = mode;
+ ep->sec_attr.nLength = sizeof(ep->sec_attr);
+ ep->sec_attr.lpSecurityDescriptor = NULL;
+ ep->sec_attr.bInheritHandle = FALSE;
NNI_LIST_NODE_INIT(&ep->node);
ep->addr = *sa;
@@ -214,6 +218,30 @@ nni_plat_ipc_ep_init(nni_plat_ipc_ep **epp, const nni_sockaddr *sa, int mode)
}
int
+nni_plat_ipc_ep_set_permissions(nni_plat_ipc_ep *ep, uint32_t bits)
+{
+ NNI_ARG_UNUSED(ep);
+ NNI_ARG_UNUSED(bits);
+ return (NNG_ENOTSUP);
+}
+
+int
+nni_plat_ipc_ep_set_security_descriptor(nni_plat_ipc_ep *ep, void *desc)
+{
+ if (ep->started) {
+ return (NNG_EBUSY);
+ }
+ if (ep->mode != NNI_EP_MODE_LISTEN) {
+ return (NNG_ENOTSUP);
+ }
+ if (!IsValidSecurityDescriptor((SECURITY_DESCRIPTOR *) desc)) {
+ return (NNG_EINVAL);
+ }
+ ep->sec_attr.lpSecurityDescriptor = desc;
+ return (0);
+}
+
+int
nni_plat_ipc_ep_listen(nni_plat_ipc_ep *ep)
{
int rv;
@@ -233,7 +261,7 @@ nni_plat_ipc_ep_listen(nni_plat_ipc_ep *ep)
FILE_FLAG_FIRST_PIPE_INSTANCE,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT |
PIPE_REJECT_REMOTE_CLIENTS,
- PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, NULL);
+ PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, &ep->sec_attr);
if (p == INVALID_HANDLE_VALUE) {
if ((rv = GetLastError()) == ERROR_ACCESS_DENIED) {
rv = NNG_EADDRINUSE;
@@ -252,7 +280,7 @@ nni_plat_ipc_ep_listen(nni_plat_ipc_ep *ep)
}
ep->p = p;
- ep->started = 1;
+ ep->started = true;
return (0);
failed:
@@ -281,7 +309,7 @@ nni_win_ipc_acc_finish(nni_win_event *evt, nni_aio *aio)
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT |
PIPE_REJECT_REMOTE_CLIENTS,
- PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, NULL);
+ PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, &ep->sec_attr);
if (newp == INVALID_HANDLE_VALUE) {
rv = nni_win_error(GetLastError());
// We connected, but as we cannot get a new pipe,