Patchwork [v2,1/1] chardev: Support abstract socket namespace in AF_UNIX socket family.

login
register
mail settings
Submitter Alexander Barabash
Date Jan. 8, 2013, 6:53 p.m.
Message ID <1357671226-11334-1-git-send-email-alexander_barabash@mentor.com>
Download mbox | patch
Permalink /patch/210477/
State New
Headers show

Comments

Alexander Barabash - Jan. 8, 2013, 6:53 p.m.
The abstract socket namespace is a nonportable Linux extension.
The sockets' names in this namespace have no connection
with file system pathnames. To specify a named AF_UNIX socket
in the abstract socket namespace, pass true for the boolean flag
"abstract", e.g.:

        qemu -chardev socket,path=NAME_OF_THE_SOCKET,abstract=on

Signed-off-by: Alexander Barabash <alexander_barabash@mentor.com>
---
 qemu-config.c  |    3 +++
 qemu-sockets.c |   35 ++++++++++++++++++++++++++++++-----
 2 files changed, 33 insertions(+), 5 deletions(-)

Patch

diff --git a/qemu-config.c b/qemu-config.c
index 2188c3e..5b0f71e 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -182,6 +182,9 @@  static QemuOptsList qemu_chardev_opts = {
             .name = "ipv6",
             .type = QEMU_OPT_BOOL,
         },{
+            .name = "abstract",
+            .type = QEMU_OPT_BOOL,
+        },{
             .name = "wait",
             .type = QEMU_OPT_BOOL,
         },{
diff --git a/qemu-sockets.c b/qemu-sockets.c
index 3537bf3..b1c3a79 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -56,6 +56,9 @@  static QemuOptsList dummy_opts = {
         },{
             .name = "ipv6",
             .type = QEMU_OPT_BOOL,
+        },{
+            .name = "abstract",
+            .type = QEMU_OPT_BOOL,
         },
         { /* end if list */ }
     },
@@ -667,7 +670,9 @@  int unix_listen_opts(QemuOpts *opts, Error **errp)
 {
     struct sockaddr_un un;
     const char *path = qemu_opt_get(opts, "path");
+    bool abstract = qemu_opt_get_bool(opts, "abstract", false);
     int sock, fd;
+    socklen_t addrlen = sizeof(un);
 
     sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
     if (sock < 0) {
@@ -678,7 +683,15 @@  int unix_listen_opts(QemuOpts *opts, Error **errp)
     memset(&un, 0, sizeof(un));
     un.sun_family = AF_UNIX;
     if (path && strlen(path)) {
-        snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
+        if (!abstract) {
+            snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
+        } else {
+            int printed_chars;
+            printed_chars = snprintf(un.sun_path + 1, sizeof(un.sun_path) - 1,
+                                     "%s", path);
+            addrlen =
+                offsetof(struct sockaddr_un, sun_path) + 1 + printed_chars;
+        }
     } else {
         char *tmpdir = getenv("TMPDIR");
         snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX",
@@ -694,8 +707,10 @@  int unix_listen_opts(QemuOpts *opts, Error **errp)
         qemu_opt_set(opts, "path", un.sun_path);
     }
 
-    unlink(un.sun_path);
-    if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
+    if (!abstract) {
+        unlink(un.sun_path);
+    }
+    if (bind(sock, (struct sockaddr *) &un, addrlen) < 0) {
         error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED);
         goto err;
     }
@@ -716,8 +731,10 @@  int unix_connect_opts(QemuOpts *opts, Error **errp,
 {
     struct sockaddr_un un;
     const char *path = qemu_opt_get(opts, "path");
+    bool abstract = qemu_opt_get_bool(opts, "abstract", false);
     ConnectState *connect_state = NULL;
     int sock, rc;
+    socklen_t addrlen = sizeof(un);
 
     if (NULL == path) {
         error_setg(errp, "unix connect: no path specified\n");
@@ -738,12 +755,20 @@  int unix_connect_opts(QemuOpts *opts, Error **errp,
 
     memset(&un, 0, sizeof(un));
     un.sun_family = AF_UNIX;
-    snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
+    if (!abstract) {
+        snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
+    } else {
+        int printed_chars;
+        printed_chars = snprintf(un.sun_path + 1, sizeof(un.sun_path) - 1,
+                                 "%s", path);
+        addrlen =
+            offsetof(struct sockaddr_un, sun_path) + 1 + printed_chars;
+    }
 
     /* connect to peer */
     do {
         rc = 0;
-        if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) {
+        if (connect(sock, (struct sockaddr *) &un, addrlen) < 0) {
             rc = -socket_error();
         }
     } while (rc == -EINTR);