[libvirt] [PATCH 2/2] Include socket address in client probe data

Daniel P. Berrange berrange at redhat.com
Thu Oct 21 18:19:33 UTC 2010


It is useful to know where the client is connecting from,
so include the socket address in probe data.

* daemon/libvirtd.h: Use virSocketAddr for storing client
  address and keep printable address handy for logging
* daemon/libvirtd.c: Include socket address in client
  connect/disconnect probes
* daemon/probes.d: Add socket address to probes
* examples/systemtap/client.stp: Print socket address
* src/util/network.h: Add sockaddr_un to virSocketAddr union
---
 configure.ac                  |    2 +-
 daemon/libvirtd.c             |   82 +++++++++++++++++++++-------------------
 daemon/libvirtd.h             |   15 +++++--
 daemon/libvirtd.stp           |    2 +
 daemon/probes.d               |    2 +-
 daemon/remote.c               |    2 +-
 examples/systemtap/client.stp |    4 +-
 src/util/network.h            |    6 +++
 8 files changed, 66 insertions(+), 49 deletions(-)

diff --git a/configure.ac b/configure.ac
index dd19598..e41f2b5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -108,7 +108,7 @@ AC_CHECK_FUNCS([pthread_sigmask pthread_mutexattr_init])
 LIBS=$old_libs
 
 dnl Availability of various common headers (non-fatal if missing).
-AC_CHECK_HEADERS([pwd.h paths.h regex.h sys/syslimits.h \
+AC_CHECK_HEADERS([pwd.h paths.h regex.h sys/syslimits.h sys/un.h \
   sys/poll.h syslog.h mntent.h net/ethernet.h linux/magic.h])
 
 AC_CHECK_LIB([intl],[gettext],[])
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 7235439..8e88d05 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -541,7 +541,6 @@ static int qemudWritePidFile(const char *pidFile) {
 static int qemudListenUnix(struct qemud_server *server,
                            char *path, int readonly, int auth) {
     struct qemud_socket *sock;
-    struct sockaddr_un addr;
     mode_t oldmask;
     gid_t oldgrp;
     char ebuf[1024];
@@ -552,10 +551,15 @@ static int qemudListenUnix(struct qemud_server *server,
     }
 
     sock->readonly = readonly;
-    sock->port = -1;
     sock->type = QEMUD_SOCK_TYPE_UNIX;
     sock->auth = auth;
     sock->path = path;
+    sock->addr.len = sizeof(sock->addr.data.un);
+    if (!(sock->addrstr = strdup(path))) {
+        VIR_ERROR(_("Failed to copy socket address: %s"),
+                  virStrerror(errno, ebuf, sizeof ebuf));
+        goto cleanup;
+    }
 
     if ((sock->fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
         VIR_ERROR(_("Failed to create socket: %s"),
@@ -567,14 +571,13 @@ static int qemudListenUnix(struct qemud_server *server,
         virSetNonBlock(sock->fd) < 0)
         goto cleanup;
 
-    memset(&addr, 0, sizeof(addr));
-    addr.sun_family = AF_UNIX;
-    if (virStrcpyStatic(addr.sun_path, path) == NULL) {
+    sock->addr.data.un.sun_family = AF_UNIX;
+    if (virStrcpyStatic(sock->addr.data.un.sun_path, path) == NULL) {
         VIR_ERROR(_("Path %s too long for unix socket"), path);
         goto cleanup;
     }
-    if (addr.sun_path[0] == '@')
-        addr.sun_path[0] = '\0';
+    if (sock->addr.data.un.sun_path[0] == '@')
+        sock->addr.data.un.sun_path[0] = '\0';
 
     oldgrp = getgid();
     oldmask = umask(readonly ? ~unix_sock_ro_mask : ~unix_sock_rw_mask);
@@ -583,7 +586,7 @@ static int qemudListenUnix(struct qemud_server *server,
         goto cleanup;
     }
 
-    if (bind(sock->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+    if (bind(sock->fd, &sock->addr.data.sa, sock->addr.len) < 0) {
         VIR_ERROR(_("Failed to bind socket to '%s': %s"),
                   path, virStrerror(errno, ebuf, sizeof ebuf));
         goto cleanup;
@@ -692,16 +695,7 @@ remoteListenTCP (struct qemud_server *server,
         return -1;
 
     for (i = 0; i < nfds; ++i) {
-        union {
-            struct sockaddr_storage sa_stor;
-            struct sockaddr sa;
-            struct sockaddr_in sa_in;
-#ifdef AF_INET6
-            struct sockaddr_in6 sa_in6;
-#endif
-        } s;
         char ebuf[1024];
-        socklen_t salen = sizeof(s);
 
         if (VIR_ALLOC(sock) < 0) {
             VIR_ERROR(_("remoteListenTCP: calloc: %s"),
@@ -709,6 +703,7 @@ remoteListenTCP (struct qemud_server *server,
             goto cleanup;
         }
 
+        sock->addr.len = sizeof(sock->addr.data.stor);
         sock->readonly = 0;
         sock->next = server->sockets;
         server->sockets = sock;
@@ -718,17 +713,11 @@ remoteListenTCP (struct qemud_server *server,
         sock->type = type;
         sock->auth = auth;
 
-        if (getsockname(sock->fd, &s.sa, &salen) < 0)
+        if (getsockname(sock->fd, &sock->addr.data.sa, &sock->addr.len) < 0)
             goto cleanup;
 
-        if (s.sa.sa_family == AF_INET) {
-            sock->port = htons(s.sa_in.sin_port);
-#ifdef AF_INET6
-        } else if (s.sa.sa_family == AF_INET6)
-            sock->port = htons(s.sa_in6.sin6_port);
-#endif
-        else
-            sock->port = -1;
+        if (!(sock->addrstr = virSocketFormatAddrFull(&sock->addr, true, ";")))
+            goto cleanup;
 
         if (virSetCloseExec(sock->fd) < 0 ||
             virSetNonBlock(sock->fd) < 0)
@@ -1043,8 +1032,9 @@ static int qemudNetworkInit(struct qemud_server *server) {
          */
         sock = server->sockets;
         while (sock) {
-            if (sock->port != -1 && sock->type == QEMUD_SOCK_TYPE_TLS) {
-                port = sock->port;
+            if (virSocketGetPort(&sock->addr) != -1 &&
+                sock->type == QEMUD_SOCK_TYPE_TLS) {
+                port = virSocketGetPort(&sock->addr);
                 break;
             }
             sock = sock->next;
@@ -1315,13 +1305,14 @@ int qemudGetSocketIdentity(int fd, uid_t *uid, pid_t *pid) {
 
 static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket *sock) {
     int fd;
-    struct sockaddr_storage addr;
-    socklen_t addrlen = (socklen_t) (sizeof addr);
+    virSocketAddr addr;
+    char *addrstr = NULL;
     struct qemud_client *client = NULL;
     int no_slow_start = 1;
     int i;
 
-    if ((fd = accept(sock->fd, (struct sockaddr *)&addr, &addrlen)) < 0) {
+    addr.len = sizeof(addr.data.stor);
+    if ((fd = accept(sock->fd, &addr.data.sa, &addr.len)) < 0) {
         char ebuf[1024];
         if (errno == EAGAIN)
             return 0;
@@ -1329,11 +1320,17 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
                   virStrerror(errno, ebuf, sizeof ebuf));
         return -1;
     }
+    if (!(addrstr = virSocketFormatAddrFull(&addr, true, ";"))) {
+        VIR_ERROR0(_("Failed to format addresss: out of memory"));
+        goto error;
+    }
 
-    PROBE(CLIENT_CONNECT, "fd=%d, readonly=%d", fd, sock->readonly);
+    PROBE(CLIENT_CONNECT, "fd=%d, readonly=%d localAddr=%s remoteAddr=%s",
+          fd, sock->readonly, sock->addrstr, addrstr);
 
     if (server->nclients >= max_clients) {
-        VIR_ERROR(_("Too many active clients (%d), dropping connection"), max_clients);
+        VIR_ERROR(_("Too many active clients (%d), dropping connection from %s"),
+                  max_clients, addrstr);
         goto error;
     }
 
@@ -1384,8 +1381,9 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
     client->readonly = sock->readonly;
     client->type = sock->type;
     client->auth = sock->auth;
-    memcpy (&client->addr, &addr, sizeof addr);
-    client->addrlen = addrlen;
+    client->addr = addr;
+    client->addrstr = addrstr;
+    addrstr = NULL;
 
     for (i = 0 ; i < VIR_DOMAIN_EVENT_ID_LAST ; i++) {
         client->domainEventCallbackID[i] = -1;
@@ -1411,7 +1409,8 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
 
         /* Client is running as root, so disable auth */
         if (uid == 0) {
-            VIR_INFO(_("Turn off polkit auth for privileged client %d"), pid);
+            VIR_INFO(_("Turn off polkit auth for privileged client pid %d from %s"),
+                     pid, addrstr);
             client->auth = REMOTE_AUTH_NONE;
         }
     }
@@ -1451,8 +1450,8 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
                 goto error;
         } else {
             PROBE(CLIENT_TLS_FAIL, "fd=%d", client->fd);
-            VIR_ERROR(_("TLS handshake failed: %s"),
-                      gnutls_strerror (ret));
+            VIR_ERROR(_("TLS handshake failed for client %s: %s"),
+                      addrstr, gnutls_strerror (ret));
             goto error;
         }
     }
@@ -1477,10 +1476,13 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
 error:
     if (client) {
         if (client->tlssession) gnutls_deinit (client->tlssession);
-        if (client)
+        if (client) {
+            VIR_FREE(client->addrstr);
             VIR_FREE(client->rx);
+        }
         VIR_FREE(client);
     }
+    VIR_FREE(addrstr);
     close (fd);
     PROBE(CLIENT_DISCONNECT, "fd=%d", fd);
     return -1;
@@ -1530,6 +1532,7 @@ void qemudDispatchClientFailure(struct qemud_client *client) {
         close(client->fd);
         client->fd = -1;
     }
+    VIR_FREE(client->addrstr);
 }
 
 
@@ -2448,6 +2451,7 @@ static void qemudCleanup(struct qemud_server *server) {
             sock->path[0] != '@')
             unlink(sock->path);
         VIR_FREE(sock->path);
+        VIR_FREE(sock->addrstr);
 
         VIR_FREE(sock);
         sock = next;
diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h
index 94de5e1..785ac07 100644
--- a/daemon/libvirtd.h
+++ b/daemon/libvirtd.h
@@ -48,6 +48,7 @@
 # include "qemu_protocol.h"
 # include "logging.h"
 # include "threads.h"
+# include "network.h"
 
 # if WITH_DTRACE
 #  ifndef LIBVIRTD_PROBES_H
@@ -61,8 +62,8 @@
         LIBVIRTD_ ## NAME(__VA_ARGS__);                      \
     }
 # else
-#  define PROBE(NAME, FMT, ...)                                 \
-    VIR_DEBUG_INT("trace." __FILE__, __func__, __LINE__,        \
+#  define PROBE(NAME, FMT, ...)                              \
+    VIR_DEBUG_INT("trace." __FILE__, __func__, __LINE__,     \
                   #NAME ": " FMT, __VA_ARGS__);
 # endif
 
@@ -197,8 +198,8 @@ struct qemud_client {
     unsigned int closing :1;
     int domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LAST];
 
-    struct sockaddr_storage addr;
-    socklen_t addrlen;
+    virSocketAddr addr;
+    const char *addrstr;
 
     int type; /* qemud_sock_type */
     gnutls_session_t tlssession;
@@ -252,12 +253,16 @@ struct qemud_client {
 
 struct qemud_socket {
     char *path;
+
+    virSocketAddr addr;
+    const char *addrstr;
+
     int fd;
     int watch;
     int readonly;
     int type; /* qemud_sock_type */
     int auth;
-    int port;
+
     struct qemud_socket *next;
 };
 
diff --git a/daemon/libvirtd.stp b/daemon/libvirtd.stp
index 6e8b929..7406eeb 100644
--- a/daemon/libvirtd.stp
+++ b/daemon/libvirtd.stp
@@ -2,6 +2,8 @@ probe libvirt.daemon.client.connect = process("libvirtd").mark("client_connect")
 {
   fd = $arg1;
   readonly = $arg2;
+  localAddr = user_string($arg3);
+  remoteAddr = user_string($arg4);
 }
 
 probe libvirt.daemon.client.disconnect = process("libvirtd").mark("client_disconnect")
diff --git a/daemon/probes.d b/daemon/probes.d
index d8cc77c..d1050c0 100644
--- a/daemon/probes.d
+++ b/daemon/probes.d
@@ -1,5 +1,5 @@
 provider libvirtd {
-	 probe client_connect(int fd, int readonly);
+	 probe client_connect(int fd, int readonly, const char *localAddr, const char *remoteAddr);
 	 probe client_disconnect(int fd);
 
 	 probe client_auth_allow(int fd, int authtype, const char *identity);
diff --git a/daemon/remote.c b/daemon/remote.c
index c98e633..3b72f98 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -3687,7 +3687,7 @@ remoteDispatchAuthSaslInit (struct qemud_server *server,
         VIR_FREE(localAddr);
         goto error;
     }
-    if ((localAddr = virSocketFormatAddrFull(&sa, true, ";")) == NULL) {
+    if ((remoteAddr = virSocketFormatAddrFull(&sa, true, ";")) == NULL) {
         VIR_FREE(localAddr);
         remoteDispatchConnError(rerr, conn);
         goto error;
diff --git a/examples/systemtap/client.stp b/examples/systemtap/client.stp
index 00df15a..bf32402 100644
--- a/examples/systemtap/client.stp
+++ b/examples/systemtap/client.stp
@@ -1,10 +1,10 @@
 #!/usr/bin/stap
 
 probe libvirt.daemon.client.connect {
-      printf("Client fd=%d connected readonly=%d\n", fd, readonly);
+      printf("Client fd=%d connected readonly=%d addr=%s\n", fd, readonly, addr);
 }
 probe libvirt.daemon.client.disconnect {
-      printf("Client fd=%d disconnected\n", fd);
+      printf("Client fd=%d disconnected addr=%s\n", fd, addr);
 }
 
 probe libvirt.daemon.client.tls_allow {
diff --git a/src/util/network.h b/src/util/network.h
index 5147ea5..9f9a340 100644
--- a/src/util/network.h
+++ b/src/util/network.h
@@ -15,6 +15,9 @@
 
 # include <sys/types.h>
 # include <sys/socket.h>
+# ifdef HAVE_SYS_UN_H
+#  include <sys/un.h>
+# endif
 # include <netdb.h>
 # include <stdbool.h>
 
@@ -24,6 +27,9 @@ typedef struct {
         struct sockaddr_storage stor;
         struct sockaddr_in inet4;
         struct sockaddr_in6 inet6;
+# ifdef HAVE_SYS_UN_H
+        struct sockaddr_un un;
+# endif
     } data;
     socklen_t len;
 } virSocketAddr;
-- 
1.7.2.3




More information about the libvir-list mailing list