diff --git a/configure.ac b/configure.ac index dd19598062..e41f2b5bd0 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 7235439f7c..8e88d053f4 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 94de5e1570..785ac07c23 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 6e8b9295cd..7406eebb7e 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 d8cc77c76f..d1050c0741 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 c98e633b9b..3b72f98ae6 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 00df15a36e..bf32402621 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 5147ea5227..9f9a340d44 100644 --- a/src/util/network.h +++ b/src/util/network.h @@ -15,6 +15,9 @@ # include # include +# ifdef HAVE_SYS_UN_H +# include +# endif # include # include @@ -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;