Include socket address in client probe data

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
This commit is contained in:
Daniel P. Berrange 2010-10-21 15:45:12 +01:00
parent 968eb4e5cd
commit 4b16b9c77f
8 changed files with 66 additions and 49 deletions

View File

@ -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],[])

View File

@ -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;

View File

@ -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;
};

View File

@ -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")

View File

@ -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);

View File

@ -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;

View File

@ -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 {

View File

@ -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;