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