From 377d3cf830c24a8ac870628e6c8dbd0a9c908231 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 25 Dec 2016 17:21:29 +0100 Subject: [PATCH] add a LD_PRELOAD wrapper to trace client <-> qmuxd communications --- qmi/ld_preload_wrapper/Makefile | 13 +++ qmi/ld_preload_wrapper/qmuxd_wrapper.c | 127 +++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 qmi/ld_preload_wrapper/Makefile create mode 100644 qmi/ld_preload_wrapper/qmuxd_wrapper.c diff --git a/qmi/ld_preload_wrapper/Makefile b/qmi/ld_preload_wrapper/Makefile new file mode 100644 index 0000000..8d42ba3 --- /dev/null +++ b/qmi/ld_preload_wrapper/Makefile @@ -0,0 +1,13 @@ +CFLAGS=-fPIC -Wall +LDFLAGS=-shared -ldl + +all: qmuxd_wrapper.so + +%.o: %.c + $(CC) $(CFLAGS) -o $@ -c $^ + +qmuxd_wrapper.so: qmuxd_wrapper.o + $(CC) $(LDFLAGS) -o $@ $^ + +clean: + @rm -f qmuxd_wrapper.so *.o diff --git a/qmi/ld_preload_wrapper/qmuxd_wrapper.c b/qmi/ld_preload_wrapper/qmuxd_wrapper.c new file mode 100644 index 0000000..7b2830d --- /dev/null +++ b/qmi/ld_preload_wrapper/qmuxd_wrapper.c @@ -0,0 +1,127 @@ +#define _GNU_SOURCE +#include +#include +#include + +#include +#include +#include + +static char hexd_buff[4096]; +static const char hex_chars[] = "0123456789abcdef"; + +static char *_osmo_hexdump(const unsigned char *buf, int len, char *delim) +{ + int i; + char *cur = hexd_buff; + + hexd_buff[0] = 0; + for (i = 0; i < len; i++) { + const char *delimp = delim; + int len_remain = sizeof(hexd_buff) - (cur - hexd_buff); + if (len_remain < 3) + break; + + *cur++ = hex_chars[buf[i] >> 4]; + *cur++ = hex_chars[buf[i] & 0xf]; + + while (len_remain > 1 && *delimp) { + *cur++ = *delimp++; + len_remain--; + } + + *cur = 0; + } + hexd_buff[sizeof(hexd_buff)-1] = 0; + return hexd_buff; +} + +static char *osmo_hexdump(const unsigned char *buf, int len) +{ + return _osmo_hexdump(buf, len, " "); +} + + + + +/* Function pointers to hold the value of the glibc functions */ +static ssize_t (*real_write)(int fd, const void *buf, size_t count); +static ssize_t (*real_read)(int fd, void *buf, size_t count); +static int (*real_connect)(int fd, const struct sockaddr *addr, socklen_t addrlen); +static ssize_t (*real_send)(int sockfd, const void *buf, size_t len, int flags); +static ssize_t (*real_recv)(int sockfd, void *buf, size_t len, int flags); +static int (*real_close)(int fd); + +static int trace_fds[16]= { -1, }; +static int num_trace_fds = 0; + +static void dump_qmuxd(int fd, int to_qmux, const void *buf, size_t len) +{ + int i; + + for (i = 0; i < num_trace_fds; i++) { + if (trace_fds[i] == fd) + printf("%s_qmuxd(%u, %04x): %s\n", to_qmux ? "to" : "from", fd, len, osmo_hexdump(buf, len)); + } +} + +/* wrapping write function call */ +ssize_t write(int fd, const void *buf, size_t count) +{ + dump_qmuxd(fd, 1, buf, count); + + real_write = dlsym(RTLD_NEXT, "write"); + return real_write(fd, buf, count); +} + +ssize_t read(int fd, void *buf, size_t count) +{ + dump_qmuxd(fd, 0, buf, count); + + real_read = dlsym(RTLD_NEXT, "read"); + return real_read(fd, buf, count); +} + +ssize_t send(int fd, const void *buf, size_t count, int flags) +{ + dump_qmuxd(fd, 1, buf, count); + + real_send = dlsym(RTLD_NEXT, "send"); + return real_send(fd, buf, count, flags); +} + +ssize_t recv(int fd, void *buf, size_t len, int flags) +{ + dump_qmuxd(fd, 0, buf, len); + + real_recv = dlsym(RTLD_NEXT, "recv"); + return real_recv(fd, buf, len, flags); +} + +int connect(int fd, const struct sockaddr *addr, socklen_t addrlen) +{ + if (addr->sa_family == AF_UNIX) { + struct sockaddr_un *sun = (struct sockaddr_un *)addr; + if (!strcmp(sun->sun_path, "/var/qmux_connect_socket")) { + printf("Found socketfd to qmuxd: %d\n", fd); + trace_fds[num_trace_fds++] = fd; + } + } + + real_connect = dlsym(RTLD_NEXT, "connect"); + return real_connect(fd, addr, addrlen); +} + +int close(int fd) +{ + int i; + + for (i = 0; i < num_trace_fds; i++) { + if (trace_fds[i] == fd) { + printf("Closed socketfd to qmuxd: %d\n", fd); + trace_fds[i] = -1; + } + } + real_close = dlsym(RTLD_NEXT, "close"); + return real_close(fd); +}