console-socket: Add an optional component to UNIX socket abstract names
Allows multiple instances of obmc-console-server to run concurrently
without interfering with each other.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Change-Id: I7ef9c14e554c687e8d606e1eaaed82a7f1c06d98
diff --git a/console-client.c b/console-client.c
index 052ece2..af1094f 100644
--- a/console-client.c
+++ b/console-client.c
@@ -15,6 +15,7 @@
*/
#include <err.h>
+#include <errno.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdint.h>
@@ -209,6 +210,7 @@
static int client_init(struct console_client *client)
{
struct sockaddr_un addr;
+ ssize_t len;
int rc;
client->console_sd = socket(AF_UNIX, SOCK_STREAM, 0);
@@ -219,17 +221,24 @@
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
- memcpy(&addr.sun_path, &console_socket_path, console_socket_path_len);
-
- rc = connect(client->console_sd, (struct sockaddr *)&addr,
- sizeof(addr) - sizeof(addr.sun_path) + console_socket_path_len);
- if (rc) {
- warn("Can't connect to console server");
- close(client->console_sd);
- return -1;
+ len = console_socket_path(&addr, NULL);
+ if (len < 0) {
+ if (errno)
+ warn("Failed to configure socket: %s", strerror(errno));
+ else
+ warn("Socket name length exceeds buffer limits");
+ goto cleanup;
}
- return 0;
+ rc = connect(client->console_sd, (struct sockaddr *)&addr,
+ sizeof(addr) - sizeof(addr.sun_path) + len);
+ if (!rc)
+ return 0;
+
+ warn("Can't connect to console server");
+cleanup:
+ close(client->console_sd);
+ return -1;
}
static void client_fini(struct console_client *client)
diff --git a/console-server.h b/console-server.h
index d6822c5..b6ab1b8 100644
--- a/console-server.h
+++ b/console-server.h
@@ -23,6 +23,7 @@
#include <time.h>
#include <systemd/sd-bus.h>
#include <sys/time.h>
+#include <sys/un.h>
struct console;
struct config;
@@ -138,9 +139,11 @@
int config_parse_logsize(const char *size_str, size_t *size);
/* socket paths */
-extern const char *console_socket_path;
-extern const size_t console_socket_path_len;
-extern const char *console_socket_path_readable;
+ssize_t console_socket_path(struct sockaddr_un *addr, const char *id);
+
+typedef char (socket_path_t)[sizeof(((struct sockaddr_un *)NULL)->sun_path)];
+ssize_t console_socket_path_readable(const struct sockaddr_un *addr,
+ size_t addrlen, socket_path_t path);
/* utils */
int write_buf_to_fd(int fd, const uint8_t *buf, size_t len);
diff --git a/console-socket.c b/console-socket.c
index 9e1cf30..b0cd452 100644
--- a/console-socket.c
+++ b/console-socket.c
@@ -14,9 +14,53 @@
* limitations under the License.
*/
+#include "console-server.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/un.h>
#include <sys/types.h>
-const char console_socket_path[] = "\0obmc-console";
-const size_t console_socket_path_len = sizeof(console_socket_path) - 1;
-const char *console_socket_path_readable = console_socket_path + 1;
+#define CONSOLE_SOCKET_PREFIX "obmc-console"
+ssize_t console_socket_path(struct sockaddr_un *addr, const char *id)
+{
+ char *sun_path;
+ ssize_t rc;
+
+ sun_path = (char *)addr + sizeof(*addr) - sizeof(addr->sun_path);
+
+ if (id) {
+ rc = snprintf(sun_path + 1, sizeof(addr->sun_path) - 1,
+ CONSOLE_SOCKET_PREFIX ".%s", id);
+ } else {
+ rc = snprintf(sun_path + 1, sizeof(addr->sun_path) - 1,
+ CONSOLE_SOCKET_PREFIX);
+ }
+
+ if (rc < 0)
+ return rc;
+
+ if (rc > (sizeof(addr->sun_path) - 1)) {
+ errno = 0;
+ return -1;
+ }
+
+ sun_path[0] = '\0';
+
+ return rc + 1 /* Capture NUL prefix */;
+}
+
+ssize_t console_socket_path_readable(const struct sockaddr_un *addr,
+ size_t addrlen, socket_path_t path)
+{
+ const char *src = (const char *)addr;
+ const size_t len = addrlen - sizeof(addr->sun_family) - 1;
+
+ memcpy(path, src + sizeof(addr->sun_family) + 1, len);
+ path[len] = '\0';
+
+ return len; /* strlen() style */
+}
diff --git a/socket-handler.c b/socket-handler.c
index be7daa4..00044f4 100644
--- a/socket-handler.c
+++ b/socket-handler.c
@@ -306,6 +306,8 @@
{
struct socket_handler *sh = to_socket_handler(handler);
struct sockaddr_un addr;
+ size_t addrlen;
+ ssize_t len;
int rc;
sh->console = console;
@@ -320,26 +322,39 @@
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
- memcpy(&addr.sun_path, &console_socket_path, console_socket_path_len);
+ len = console_socket_path(&addr, NULL);
+ if (len < 0) {
+ if (errno)
+ warn("Failed to configure socket: %s", strerror(errno));
+ else
+ warn("Socket name length exceeds buffer limits");
+ goto cleanup;
+ }
- rc = bind(sh->sd, (struct sockaddr *)&addr,
- sizeof(addr) - sizeof(addr.sun_path) + console_socket_path_len);
+ addrlen = sizeof(addr) - sizeof(addr.sun_path) + len;
+
+ rc = bind(sh->sd, (struct sockaddr *)&addr, addrlen);
if (rc) {
- warn("Can't bind to socket path %s",
- console_socket_path_readable);
- return -1;
+ socket_path_t name;
+ console_socket_path_readable(&addr, addrlen, name);
+ warn("Can't bind to socket path %s (terminated at first null)",
+ name);
+ goto cleanup;
}
rc = listen(sh->sd, 1);
if (rc) {
warn("Can't listen for incoming connections");
- return -1;
+ goto cleanup;
}
sh->poller = console_poller_register(console, handler, socket_poll,
NULL, sh->sd, POLLIN, NULL);
return 0;
+cleanup:
+ close(sh->sd);
+ return -1;
}
static void socket_fini(struct handler *handler)
diff --git a/test/test-client-escape.c b/test/test-client-escape.c
index 76e9c15..eeae015 100644
--- a/test/test-client-escape.c
+++ b/test/test-client-escape.c
@@ -18,11 +18,12 @@
#include <stdint.h>
#include <stdio.h>
-#define main __main
#define read __read
+#include "console-socket.c"
+#define main __main
#include "console-client.c"
-#undef main
#undef read
+#undef main
struct test {
enum esc_type esc_type;
@@ -153,11 +154,6 @@
struct test_ctx ctxs[ARRAY_SIZE(tests)];
-/* stubs for console socket */
-const char *console_socket_path = "";
-const size_t console_socket_path_len = 1;
-const char *console_socket_path_readable = 0;
-
int write_buf_to_fd(int fd, const uint8_t *buf, size_t len)
{
struct test_ctx *ctx = &ctxs[fd];