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 LIBS=$old_libs
dnl Availability of various common headers (non-fatal if missing). 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]) sys/poll.h syslog.h mntent.h net/ethernet.h linux/magic.h])
AC_CHECK_LIB([intl],[gettext],[]) AC_CHECK_LIB([intl],[gettext],[])

View File

@ -541,7 +541,6 @@ static int qemudWritePidFile(const char *pidFile) {
static int qemudListenUnix(struct qemud_server *server, static int qemudListenUnix(struct qemud_server *server,
char *path, int readonly, int auth) { char *path, int readonly, int auth) {
struct qemud_socket *sock; struct qemud_socket *sock;
struct sockaddr_un addr;
mode_t oldmask; mode_t oldmask;
gid_t oldgrp; gid_t oldgrp;
char ebuf[1024]; char ebuf[1024];
@ -552,10 +551,15 @@ static int qemudListenUnix(struct qemud_server *server,
} }
sock->readonly = readonly; sock->readonly = readonly;
sock->port = -1;
sock->type = QEMUD_SOCK_TYPE_UNIX; sock->type = QEMUD_SOCK_TYPE_UNIX;
sock->auth = auth; sock->auth = auth;
sock->path = path; 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) { if ((sock->fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
VIR_ERROR(_("Failed to create socket: %s"), VIR_ERROR(_("Failed to create socket: %s"),
@ -567,14 +571,13 @@ static int qemudListenUnix(struct qemud_server *server,
virSetNonBlock(sock->fd) < 0) virSetNonBlock(sock->fd) < 0)
goto cleanup; goto cleanup;
memset(&addr, 0, sizeof(addr)); sock->addr.data.un.sun_family = AF_UNIX;
addr.sun_family = AF_UNIX; if (virStrcpyStatic(sock->addr.data.un.sun_path, path) == NULL) {
if (virStrcpyStatic(addr.sun_path, path) == NULL) {
VIR_ERROR(_("Path %s too long for unix socket"), path); VIR_ERROR(_("Path %s too long for unix socket"), path);
goto cleanup; goto cleanup;
} }
if (addr.sun_path[0] == '@') if (sock->addr.data.un.sun_path[0] == '@')
addr.sun_path[0] = '\0'; sock->addr.data.un.sun_path[0] = '\0';
oldgrp = getgid(); oldgrp = getgid();
oldmask = umask(readonly ? ~unix_sock_ro_mask : ~unix_sock_rw_mask); oldmask = umask(readonly ? ~unix_sock_ro_mask : ~unix_sock_rw_mask);
@ -583,7 +586,7 @@ static int qemudListenUnix(struct qemud_server *server,
goto cleanup; 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"), VIR_ERROR(_("Failed to bind socket to '%s': %s"),
path, virStrerror(errno, ebuf, sizeof ebuf)); path, virStrerror(errno, ebuf, sizeof ebuf));
goto cleanup; goto cleanup;
@ -692,16 +695,7 @@ remoteListenTCP (struct qemud_server *server,
return -1; return -1;
for (i = 0; i < nfds; ++i) { 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]; char ebuf[1024];
socklen_t salen = sizeof(s);
if (VIR_ALLOC(sock) < 0) { if (VIR_ALLOC(sock) < 0) {
VIR_ERROR(_("remoteListenTCP: calloc: %s"), VIR_ERROR(_("remoteListenTCP: calloc: %s"),
@ -709,6 +703,7 @@ remoteListenTCP (struct qemud_server *server,
goto cleanup; goto cleanup;
} }
sock->addr.len = sizeof(sock->addr.data.stor);
sock->readonly = 0; sock->readonly = 0;
sock->next = server->sockets; sock->next = server->sockets;
server->sockets = sock; server->sockets = sock;
@ -718,17 +713,11 @@ remoteListenTCP (struct qemud_server *server,
sock->type = type; sock->type = type;
sock->auth = auth; 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; goto cleanup;
if (s.sa.sa_family == AF_INET) { if (!(sock->addrstr = virSocketFormatAddrFull(&sock->addr, true, ";")))
sock->port = htons(s.sa_in.sin_port); goto cleanup;
#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 (virSetCloseExec(sock->fd) < 0 || if (virSetCloseExec(sock->fd) < 0 ||
virSetNonBlock(sock->fd) < 0) virSetNonBlock(sock->fd) < 0)
@ -1043,8 +1032,9 @@ static int qemudNetworkInit(struct qemud_server *server) {
*/ */
sock = server->sockets; sock = server->sockets;
while (sock) { while (sock) {
if (sock->port != -1 && sock->type == QEMUD_SOCK_TYPE_TLS) { if (virSocketGetPort(&sock->addr) != -1 &&
port = sock->port; sock->type == QEMUD_SOCK_TYPE_TLS) {
port = virSocketGetPort(&sock->addr);
break; break;
} }
sock = sock->next; 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) { static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket *sock) {
int fd; int fd;
struct sockaddr_storage addr; virSocketAddr addr;
socklen_t addrlen = (socklen_t) (sizeof addr); char *addrstr = NULL;
struct qemud_client *client = NULL; struct qemud_client *client = NULL;
int no_slow_start = 1; int no_slow_start = 1;
int i; 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]; char ebuf[1024];
if (errno == EAGAIN) if (errno == EAGAIN)
return 0; return 0;
@ -1329,11 +1320,17 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
virStrerror(errno, ebuf, sizeof ebuf)); virStrerror(errno, ebuf, sizeof ebuf));
return -1; 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) { 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; goto error;
} }
@ -1384,8 +1381,9 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
client->readonly = sock->readonly; client->readonly = sock->readonly;
client->type = sock->type; client->type = sock->type;
client->auth = sock->auth; client->auth = sock->auth;
memcpy (&client->addr, &addr, sizeof addr); client->addr = addr;
client->addrlen = addrlen; client->addrstr = addrstr;
addrstr = NULL;
for (i = 0 ; i < VIR_DOMAIN_EVENT_ID_LAST ; i++) { for (i = 0 ; i < VIR_DOMAIN_EVENT_ID_LAST ; i++) {
client->domainEventCallbackID[i] = -1; 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 */ /* Client is running as root, so disable auth */
if (uid == 0) { 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; client->auth = REMOTE_AUTH_NONE;
} }
} }
@ -1451,8 +1450,8 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
goto error; goto error;
} else { } else {
PROBE(CLIENT_TLS_FAIL, "fd=%d", client->fd); PROBE(CLIENT_TLS_FAIL, "fd=%d", client->fd);
VIR_ERROR(_("TLS handshake failed: %s"), VIR_ERROR(_("TLS handshake failed for client %s: %s"),
gnutls_strerror (ret)); addrstr, gnutls_strerror (ret));
goto error; goto error;
} }
} }
@ -1477,10 +1476,13 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
error: error:
if (client) { if (client) {
if (client->tlssession) gnutls_deinit (client->tlssession); if (client->tlssession) gnutls_deinit (client->tlssession);
if (client) if (client) {
VIR_FREE(client->addrstr);
VIR_FREE(client->rx); VIR_FREE(client->rx);
}
VIR_FREE(client); VIR_FREE(client);
} }
VIR_FREE(addrstr);
close (fd); close (fd);
PROBE(CLIENT_DISCONNECT, "fd=%d", fd); PROBE(CLIENT_DISCONNECT, "fd=%d", fd);
return -1; return -1;
@ -1530,6 +1532,7 @@ void qemudDispatchClientFailure(struct qemud_client *client) {
close(client->fd); close(client->fd);
client->fd = -1; client->fd = -1;
} }
VIR_FREE(client->addrstr);
} }
@ -2448,6 +2451,7 @@ static void qemudCleanup(struct qemud_server *server) {
sock->path[0] != '@') sock->path[0] != '@')
unlink(sock->path); unlink(sock->path);
VIR_FREE(sock->path); VIR_FREE(sock->path);
VIR_FREE(sock->addrstr);
VIR_FREE(sock); VIR_FREE(sock);
sock = next; sock = next;

View File

@ -48,6 +48,7 @@
# include "qemu_protocol.h" # include "qemu_protocol.h"
# include "logging.h" # include "logging.h"
# include "threads.h" # include "threads.h"
# include "network.h"
# if WITH_DTRACE # if WITH_DTRACE
# ifndef LIBVIRTD_PROBES_H # ifndef LIBVIRTD_PROBES_H
@ -61,8 +62,8 @@
LIBVIRTD_ ## NAME(__VA_ARGS__); \ LIBVIRTD_ ## NAME(__VA_ARGS__); \
} }
# else # else
# define PROBE(NAME, FMT, ...) \ # define PROBE(NAME, FMT, ...) \
VIR_DEBUG_INT("trace." __FILE__, __func__, __LINE__, \ VIR_DEBUG_INT("trace." __FILE__, __func__, __LINE__, \
#NAME ": " FMT, __VA_ARGS__); #NAME ": " FMT, __VA_ARGS__);
# endif # endif
@ -197,8 +198,8 @@ struct qemud_client {
unsigned int closing :1; unsigned int closing :1;
int domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LAST]; int domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LAST];
struct sockaddr_storage addr; virSocketAddr addr;
socklen_t addrlen; const char *addrstr;
int type; /* qemud_sock_type */ int type; /* qemud_sock_type */
gnutls_session_t tlssession; gnutls_session_t tlssession;
@ -252,12 +253,16 @@ struct qemud_client {
struct qemud_socket { struct qemud_socket {
char *path; char *path;
virSocketAddr addr;
const char *addrstr;
int fd; int fd;
int watch; int watch;
int readonly; int readonly;
int type; /* qemud_sock_type */ int type; /* qemud_sock_type */
int auth; int auth;
int port;
struct qemud_socket *next; struct qemud_socket *next;
}; };

View File

@ -2,6 +2,8 @@ probe libvirt.daemon.client.connect = process("libvirtd").mark("client_connect")
{ {
fd = $arg1; fd = $arg1;
readonly = $arg2; readonly = $arg2;
localAddr = user_string($arg3);
remoteAddr = user_string($arg4);
} }
probe libvirt.daemon.client.disconnect = process("libvirtd").mark("client_disconnect") probe libvirt.daemon.client.disconnect = process("libvirtd").mark("client_disconnect")

View File

@ -1,5 +1,5 @@
provider libvirtd { 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_disconnect(int fd);
probe client_auth_allow(int fd, int authtype, const char *identity); 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); VIR_FREE(localAddr);
goto error; goto error;
} }
if ((localAddr = virSocketFormatAddrFull(&sa, true, ";")) == NULL) { if ((remoteAddr = virSocketFormatAddrFull(&sa, true, ";")) == NULL) {
VIR_FREE(localAddr); VIR_FREE(localAddr);
remoteDispatchConnError(rerr, conn); remoteDispatchConnError(rerr, conn);
goto error; goto error;

View File

@ -1,10 +1,10 @@
#!/usr/bin/stap #!/usr/bin/stap
probe libvirt.daemon.client.connect { 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 { 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 { probe libvirt.daemon.client.tls_allow {

View File

@ -15,6 +15,9 @@
# include <sys/types.h> # include <sys/types.h>
# include <sys/socket.h> # include <sys/socket.h>
# ifdef HAVE_SYS_UN_H
# include <sys/un.h>
# endif
# include <netdb.h> # include <netdb.h>
# include <stdbool.h> # include <stdbool.h>
@ -24,6 +27,9 @@ typedef struct {
struct sockaddr_storage stor; struct sockaddr_storage stor;
struct sockaddr_in inet4; struct sockaddr_in inet4;
struct sockaddr_in6 inet6; struct sockaddr_in6 inet6;
# ifdef HAVE_SYS_UN_H
struct sockaddr_un un;
# endif
} data; } data;
socklen_t len; socklen_t len;
} virSocketAddr; } virSocketAddr;