mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-21 12:05:17 +00:00
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:
parent
968eb4e5cd
commit
4b16b9c77f
@ -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],[])
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user