Merge branch 'nate-i50189-unix' into 'master'
See merge request SchedMD/dev/slurm!1691
diff --git a/doc/man/man8/slurmrestd.8 b/doc/man/man8/slurmrestd.8
index d97b0e9..7fad583 100644
--- a/doc/man/man8/slurmrestd.8
+++ b/doc/man/man8/slurmrestd.8
@@ -1,4 +1,4 @@
-.TH slurmrestd "8" "Slurm REST Daemon" "June 2025" "Slurm REST Daemon"
+.TH slurmrestd "8" "Slurm REST Daemon" "August 2025" "Slurm REST Daemon"
.SH "NAME"
slurmrestd \- Interface to Slurm via REST API.
@@ -32,7 +32,7 @@
.IP
.TP
-\fBunix:/path/to/socket\fR
+\fBunix:///path/to/socket\fR
Listen on local UNIX socket. Must have permission to create socket in
filesystem.
.IP
diff --git a/src/common/http.c b/src/common/http.c
index dee446e..73e03c8 100644
--- a/src/common/http.c
+++ b/src/common/http.c
@@ -146,7 +146,8 @@
T(URL_SCHEME_INVALID, "INVALID"),
T(URL_SCHEME_HTTP, "http"),
T(URL_SCHEME_HTTPS, "https"),
- T(URL_SCHEME_INVALID_MAX, "INVALID_MAX")
+ T(URL_SCHEME_UNIX, "unix"),
+ T(URL_SCHEME_INVALID_MAX, "INVALID_MAX"),
};
#undef T
diff --git a/src/common/http.h b/src/common/http.h
index 2c134f9..8705a2a 100644
--- a/src/common/http.h
+++ b/src/common/http.h
@@ -147,6 +147,7 @@
URL_SCHEME_INVALID = 0,
URL_SCHEME_HTTP,
URL_SCHEME_HTTPS,
+ URL_SCHEME_UNIX, /* UNIX Socket - Not IANA registered */
URL_SCHEME_INVALID_MAX /* place holder */
} url_scheme_t;
diff --git a/src/conmgr/con.c b/src/conmgr/con.c
index 84a126f..fdaaa44 100644
--- a/src/conmgr/con.c
+++ b/src/conmgr/con.c
@@ -995,80 +995,58 @@
return false;
}
-extern int conmgr_create_listen_socket(conmgr_con_type_t type,
- conmgr_con_flags_t flags,
- const char *listen_on,
- const conmgr_events_t *events, void *arg)
+static int _add_unix_listener(conmgr_con_type_t type, conmgr_con_flags_t flags,
+ const char *listen_on, const char *unixsock,
+ const conmgr_events_t *events, void *arg)
{
- static const char UNIX_PREFIX[] = "unix:";
- const char *unixsock = xstrstr(listen_on, UNIX_PREFIX);
+ slurm_addr_t addr = { 0 };
+ int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ int rc = EINVAL;
+
+ if (fd < 0)
+ fatal("%s: socket() failed: %m", __func__);
+
+ addr = sockaddr_from_unix_path(unixsock);
+
+ if (addr.ss_family != AF_UNIX)
+ fatal("%s: [%s] Invalid Unix socket path: %s",
+ __func__, listen_on, unixsock);
+
+ log_flag(CONMGR, "%s: [%pA] attempting to bind() and listen() UNIX socket",
+ __func__, &addr);
+
+ if (unlink(unixsock) && (errno != ENOENT))
+ error("Error unlink(%s): %m", unixsock);
+
+ /* bind() will EINVAL if socklen=sizeof(addr) */
+ if ((rc = bind(fd, (const struct sockaddr *) &addr,
+ sizeof(struct sockaddr_un))))
+ fatal("%s: [%s] Unable to bind UNIX socket: %m",
+ __func__, listen_on);
+
+ fd_set_oob(fd, 0);
+
+ rc = listen(fd, SLURM_DEFAULT_LISTEN_BACKLOG);
+ if (rc < 0)
+ fatal("%s: [%s] unable to listen(): %m",
+ __func__, listen_on);
+
+ return add_connection(type, NULL, fd, -1, events, flags, &addr,
+ sizeof(addr), true, unixsock, NULL, arg);
+}
+
+static int _add_socket_listener(conmgr_con_type_t type,
+ conmgr_con_flags_t flags, const char *listen_on,
+ url_t *url, const conmgr_events_t *events,
+ void *arg)
+{
int rc = SLURM_SUCCESS;
struct addrinfo *addrlist = NULL;
- /* check for name local sockets */
- if (unixsock) {
- slurm_addr_t addr = {0};
- int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
-
- if (fd < 0)
- fatal("%s: socket() failed: %m", __func__);
-
- unixsock += sizeof(UNIX_PREFIX) - 1;
- if (unixsock[0] == '\0')
- fatal("%s: [%s] Invalid UNIX socket",
- __func__, listen_on);
-
- addr = sockaddr_from_unix_path(unixsock);
-
- if (addr.ss_family != AF_UNIX)
- fatal("%s: [%s] Invalid Unix socket path: %s",
- __func__, listen_on, unixsock);
-
- log_flag(CONMGR, "%s: [%pA] attempting to bind() and listen() UNIX socket",
- __func__, &addr);
-
- if (unlink(unixsock) && (errno != ENOENT))
- error("Error unlink(%s): %m", unixsock);
-
- /* bind() will EINVAL if socklen=sizeof(addr) */
- if ((rc = bind(fd, (const struct sockaddr *) &addr,
- sizeof(struct sockaddr_un))))
- fatal("%s: [%s] Unable to bind UNIX socket: %m",
- __func__, listen_on);
-
- fd_set_oob(fd, 0);
-
- rc = listen(fd, SLURM_DEFAULT_LISTEN_BACKLOG);
- if (rc < 0)
- fatal("%s: [%s] unable to listen(): %m",
- __func__, listen_on);
-
- return add_connection(type, NULL, fd, -1, events, flags, &addr,
- sizeof(addr), true, unixsock, NULL, arg);
- } else {
- url_t url = URL_INITIALIZER;
- buf_t buffer = {
- .magic = BUF_MAGIC,
- };
-
- buffer.head = (void *) listen_on;
- buffer.processed = buffer.size = strlen(listen_on);
-
- /* split up host and port */
- if ((rc = url_parser_g_parse("listener", &buffer, &url)))
- fatal("%s: Unable to parse %s: %s",
- __func__, listen_on, slurm_strerror(rc));
-
- if (url.scheme == URL_SCHEME_HTTPS)
- flags |= CON_FLAG_TLS_SERVER;
-
- /* resolve out the host and port if provided */
- if (!(addrlist = xgetaddrinfo(url.host, url.port)))
- fatal("%s: Unable to listen on %s:%s(%s): %m",
- __func__, url.host, url.port, listen_on);
-
- url_free_members(&url);
- }
+ /* resolve out the host and port if provided */
+ if (!(addrlist = xgetaddrinfo(url->host, url->port)))
+ fatal("%s: Unable to listen on %s:%s(%s): %m",
+ __func__, url->host, url->port, listen_on);
/*
* Create a socket for every address returned
@@ -1121,7 +1099,46 @@
}
freeaddrinfo(addrlist);
+ return rc;
+}
+extern int conmgr_create_listen_socket(conmgr_con_type_t type,
+ conmgr_con_flags_t flags,
+ const char *listen_on,
+ const conmgr_events_t *events, void *arg)
+{
+ int rc = SLURM_SUCCESS;
+ url_t url = URL_INITIALIZER;
+ buf_t buffer = {
+ .magic = BUF_MAGIC,
+ .head = (void *) listen_on,
+ .processed = strlen(listen_on),
+ .size = strlen(listen_on),
+ .shadow = true,
+ };
+
+ if ((rc = url_parser_g_parse(__func__, &buffer, &url)))
+ fatal("%s: Unable to parse %s: %s",
+ __func__, listen_on, slurm_strerror(rc));
+
+ switch (url.scheme) {
+ case URL_SCHEME_UNIX:
+ rc = _add_unix_listener(type, flags, listen_on, url.path,
+ events, arg);
+ break;
+ case URL_SCHEME_HTTPS:
+ flags |= CON_FLAG_TLS_SERVER;
+ /* fall through */
+ case URL_SCHEME_HTTP:
+ case URL_SCHEME_INVALID:
+ rc = _add_socket_listener(type, flags, listen_on, &url, events,
+ arg);
+ break;
+ case URL_SCHEME_INVALID_MAX:
+ fatal_abort("should never happen");
+ }
+
+ url_free_members(&url);
return rc;
}
diff --git a/src/plugins/http_parser/libhttp_parser/libhttp_parser.c b/src/plugins/http_parser/libhttp_parser/libhttp_parser.c
index f49bafe..36cb6e2 100644
--- a/src/plugins/http_parser/libhttp_parser/libhttp_parser.c
+++ b/src/plugins/http_parser/libhttp_parser/libhttp_parser.c
@@ -54,6 +54,9 @@
const char plugin_type[] = HTTP_PARSER_PREFIX LIBHTTP_PARSER_PLUGIN;
const uint32_t plugin_version = SLURM_VERSION_NUMBER;
+#define UNIX_PREFIX "unix:"
+#define UNIX_PREFIX_BYTES strlen("unix:")
+
#define LOG_PARSE(state, fmt, ...) \
_log_parse(state, NULL, 0, __func__, fmt, ##__VA_ARGS__)
#define LOG_PARSE_AT(state, at, bytes, fmt, ...) \
@@ -455,6 +458,33 @@
/*
* Parse URL where only the port is given.
* Examples:
+ * unix:/path/to/socket
+ *
+ * RET
+ * SLURM_SUCCESS: parsed port successfully
+ * ESLURM_URL_UNSUPPORTED_FORMAT: not a port only URL
+ * *: error
+ */
+static int _parse_unix_url(const char *name, const buf_t *buffer, url_t *dst)
+{
+ const char *data = get_buf_data(buffer);
+ const size_t bytes = get_buf_offset(buffer);
+
+ if (xstrncmp(UNIX_PREFIX, data, UNIX_PREFIX_BYTES))
+ return ESLURM_URL_UNSUPPORTED_FORMAT;
+
+ if (data[UNIX_PREFIX_BYTES] == '\0')
+ return ESLURM_URL_EMPTY;
+
+ dst->scheme = URL_SCHEME_UNIX;
+ dst->path = xstrndup((data + UNIX_PREFIX_BYTES),
+ (bytes - UNIX_PREFIX_BYTES));
+ return SLURM_SUCCESS;
+}
+
+/*
+ * Parse URL where only the port is given.
+ * Examples:
* :8080
* :ssh
*
@@ -576,9 +606,14 @@
* Try using libhttp_parser's builtin URL parser and then try additional
* parsers for formats it doesn't support
*/
- if ((rc = _library_url_parse(name, buffer, dst))) {
- if (rc == ESLURM_URL_UNSUPPORTED_FORMAT)
- rc = _parse_only_port(name, buffer, dst);
+ rc = _library_url_parse(name, buffer, dst);
+ if (rc == ESLURM_URL_UNSUPPORTED_FORMAT) {
+ url_free_members(dst);
+ rc = _parse_only_port(name, buffer, dst);
+ }
+ if (rc == ESLURM_URL_UNSUPPORTED_FORMAT) {
+ url_free_members(dst);
+ rc = _parse_unix_url(name, buffer, dst);
}
if (rc) {