From 75e95789179b2efac88fd0f8d6555722695e3f94 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 26 Mar 2018 18:21:03 +0200 Subject: prepare for different payload dissectors --- Makefile | 1 + sock_events.c | 50 ++++++++++++----------- utils.c | 129 +++++++++++++++++++++++++++++++++++++++------------------- utils.h | 12 ++++-- 4 files changed, 125 insertions(+), 67 deletions(-) diff --git a/Makefile b/Makefile index 4ff2901..9978e73 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ LIB_SRCS = utils.c sock_events.c libc_overrides.c +CFLAGS = -Wall default: libudtrace.so diff --git a/sock_events.c b/sock_events.c index 523f45a..9340d7d 100644 --- a/sock_events.c +++ b/sock_events.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #ifdef __ANDROID__ @@ -25,13 +26,6 @@ #define IS_OUT true #define IS_IN false -static void trace_data(int fd, bool is_out, const char *fn, const uint8_t *data, unsigned int len) -{ - if (!data || !len) - return; - fprintf(stderr, "%d %s %c %s\n", fd, fn, is_out ? 'W' : 'R', udtrace_hexdump(data, len, "")); -} - static void trace_iov(int fd, bool is_out, const char *fn, int ret, const struct iovec *iovec, int iovec_count) { @@ -46,7 +40,7 @@ static void trace_iov(int fd, bool is_out, const char *fn, int ret, if (remain < vec->iov_len) written_len = remain; - trace_data(fd, is_out, fn, vec->iov_base, written_len); + udtrace_data(fd, is_out, fn, vec->iov_base, written_len); remain -= written_len; } @@ -60,16 +54,26 @@ void sock_ev_socket(int fd, int domain, int type, int protocol) { if (domain != AF_UNIX) return; - add_fd(fd); + udtrace_add_fd(fd); } void sock_ev_bind(int fd, int ret, int err, const struct sockaddr *addr, socklen_t len) { + const struct sockaddr_un *sun = (const struct sockaddr_un *) addr; + if (ret < 0) + return; + LOG("bind(%d, \"%s\")\n", fd, sun->sun_path); + udtrace_fd_set_path(fd, sun->sun_path); } void sock_ev_connect(int fd, int ret, int err, const struct sockaddr *addr, socklen_t len) { + const struct sockaddr_un *sun = (const struct sockaddr_un *) addr; + if (ret < 0) + return; + LOG("connect(%d, \"%s\")\n", fd, sun->sun_path); + udtrace_fd_set_path(fd, sun->sun_path); } void sock_ev_listen(int fd, int ret, int err, int backlog) @@ -81,7 +85,7 @@ void sock_ev_accept(int fd, int ret, int err, struct sockaddr *addr, { if (ret < 0) return; - add_fd(ret); + udtrace_add_fd(ret); } void sock_ev_accept4(int fd, int ret, int err, struct sockaddr *addr, @@ -89,7 +93,7 @@ void sock_ev_accept4(int fd, int ret, int err, struct sockaddr *addr, { if (ret < 0) return; - add_fd(ret); + udtrace_add_fd(ret); } void sock_ev_send(int fd, int ret, int err, const void *buf, size_t bytes, @@ -97,14 +101,14 @@ void sock_ev_send(int fd, int ret, int err, const void *buf, size_t bytes, { if (ret <= 0) return; - trace_data(fd, IS_OUT, "send", buf, ret); + udtrace_data(fd, IS_OUT, "send", buf, ret); } void sock_ev_recv(int fd, int ret, int err, void *buf, size_t bytes, int flags) { if (ret <= 0) return; - trace_data(fd, IS_IN, "recv", buf, ret); + udtrace_data(fd, IS_IN, "recv", buf, ret); } void sock_ev_sendto(int fd, int ret, int err, const void *buf, size_t bytes, @@ -112,7 +116,7 @@ void sock_ev_sendto(int fd, int ret, int err, const void *buf, size_t bytes, { if (ret <= 0) return; - trace_data(fd, IS_OUT, "sendto", buf, ret); + udtrace_data(fd, IS_OUT, "sendto", buf, ret); } void sock_ev_recvfrom(int fd, int ret, int err, void *buf, size_t bytes, @@ -120,7 +124,7 @@ void sock_ev_recvfrom(int fd, int ret, int err, void *buf, size_t bytes, { if (ret <= 0) return; - trace_data(fd, IS_IN, "recvfrom", buf, ret); + udtrace_data(fd, IS_IN, "recvfrom", buf, ret); } void sock_ev_sendmsg(int fd, int ret, int err, const struct msghdr *msg, @@ -168,40 +172,40 @@ void sock_ev_write(int fd, int ret, int err, const void *buf, size_t bytes) { if (ret <= 0) return; - trace_data(fd, IS_OUT, "write", buf, ret); + udtrace_data(fd, IS_OUT, "write", buf, ret); } void sock_ev_read(int fd, int ret, int err, void *buf, size_t bytes) { if (ret <= 0) return; - trace_data(fd, IS_IN, "read", buf, ret); + udtrace_data(fd, IS_IN, "read", buf, ret); } void sock_ev_close(int fd, int ret, int err) { - del_fd(fd); + udtrace_del_fd(fd); } void sock_ev_dup(int fd, int ret, int err) { if (ret >= 0) - add_fd(ret); + udtrace_add_fd(ret); } void sock_ev_dup2(int fd, int ret, int err, int newfd) { if (ret >= 0) { - del_fd(newfd); - add_fd(ret); + udtrace_del_fd(newfd); + udtrace_add_fd(ret); } } void sock_ev_dup3(int fd, int ret, int err, int newfd, int flags) { if (ret >= 0) { - del_fd(newfd); - add_fd(ret); + udtrace_del_fd(newfd); + udtrace_add_fd(ret); } } diff --git a/utils.c b/utils.c index 0c763bc..55499af 100644 --- a/utils.c +++ b/utils.c @@ -3,36 +3,77 @@ #include #include #include +#include #include "utils.h" #define MAX_UNIX_FDS 32 -#define LOG(fmt, args ...) \ - fprintf(stderr, ">>> UDTRACE: " fmt, ## args) - /*********************************************************************** * Utility functions ***********************************************************************/ -static int unix_fds[MAX_UNIX_FDS]; +/* taken from libosmocore */ +static char hexd_buff[4096]; +static const char hex_chars[] = "0123456789abcdef"; +static char *hexdump(const unsigned char *buf, int len, char *delim) +{ + int i; + char *cur = hexd_buff; -__attribute__ ((constructor)) static void udtrace_init(void) { + 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; +} + +typedef void (*udtrace_dissector)(int fd, bool is_out, const char *fn, const uint8_t *data, unsigned int len); + +static void default_dissector(int fd, bool is_out, const char *fn, const uint8_t *data, unsigned int len) +{ + fprintf(stderr, "%d %s %c %s\n", fd, fn, is_out ? 'W' : 'R', hexdump(data, len, "")); +} + +struct sock_state { + int fd; + const char *path; + udtrace_dissector dissector; +}; + +static struct sock_state unix_fds[MAX_UNIX_FDS]; + +__attribute__ ((constructor)) static void udtrace_init(void) +{ int i; LOG("Unix Domain Socket Trace initialized\n"); for (i = 0; i < ARRAY_SIZE(unix_fds); i++) { - unix_fds[i] = -1; + unix_fds[i] = (struct sock_state) { -1, NULL, NULL }; } } /* add a file descriptor from the list of to-be-traced ones */ -void add_fd(int fd) +void udtrace_add_fd(int fd) { int i; for (i = 0; i < ARRAY_SIZE(unix_fds); i++) { - if (unix_fds[i] == -1) { + if (unix_fds[i].fd == -1) { LOG("Adding FD %d\n", fd); - unix_fds[i] = fd; + unix_fds[i].fd = fd; return; } } @@ -40,56 +81,62 @@ void add_fd(int fd) } /* delete a file descriptor from the list of to-be-traced ones */ -void del_fd(int fd) +void udtrace_del_fd(int fd) { int i; for (i = 0; i < ARRAY_SIZE(unix_fds); i++) { - if (unix_fds[i] == fd) { + if (unix_fds[i].fd == fd) { LOG("Removing FD %d\n", fd); - unix_fds[i] = -1; + free((void *) unix_fds[i].path); + unix_fds[i] = (struct sock_state) { -1, NULL, NULL }; return; } } LOG("Couldn't delete UNIX FD %d (no such FD)\n", fd); } -/* is the given file descriptor part of the to-be-traced unix domain fd's? */ -bool is_unix_socket(int fd) +static void udtrace_resolve_dissector(struct sock_state *ss) +{ + /* FIXME: actual useful dissectors resovled by path */ + ss->dissector = &default_dissector; +} + +/* set the path of a given fd */ +void udtrace_fd_set_path(int fd, const char *path) { int i; for (i = 0; i < ARRAY_SIZE(unix_fds); i++) { - if (unix_fds[i] == fd) - return true; + if (unix_fds[i].fd == fd) { + unix_fds[i].path = strdup(path); + udtrace_resolve_dissector(&unix_fds[i]); + return; + } } - return false; } - -/* taken from libosmocore */ -static char hexd_buff[4096]; -static const char hex_chars[] = "0123456789abcdef"; -char *udtrace_hexdump(const unsigned char *buf, int len, char *delim) +const struct sock_state *udtrace_sstate_by_fd(int fd) { 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]; + for (i = 0; i < ARRAY_SIZE(unix_fds); i++) { + if (unix_fds[i].fd == fd) + return &unix_fds[i]; + } + return NULL; +} - while (len_remain > 1 && *delimp) { - *cur++ = *delimp++; - len_remain--; - } +/* is the given file descriptor part of the to-be-traced unix domain fd's? */ +bool is_unix_socket(int fd) +{ + if (udtrace_sstate_by_fd(fd)) + return true; + else + return false; +} - *cur = 0; - } - hexd_buff[sizeof(hexd_buff)-1] = 0; - return hexd_buff; +void udtrace_data(int fd, bool is_out, const char *fn, const uint8_t *data, unsigned int len) +{ + const struct sock_state *ss = udtrace_sstate_by_fd(fd); + if (!data || !len || !ss) + return; + ss->dissector(fd, is_out, fn, data, len); } diff --git a/utils.h b/utils.h index 8148518..f1f52f4 100644 --- a/utils.h +++ b/utils.h @@ -3,13 +3,19 @@ /*! Determine number of elements in an array of static size */ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define LOG(fmt, args ...) \ + fprintf(stderr, ">>> UDTRACE: " fmt, ## args) + /* add a file descriptor from the list of to-be-traced ones */ -void add_fd(int fd); +void udtrace_add_fd(int fd); /* delete a file descriptor from the list of to-be-traced ones */ -void del_fd(int fd); +void udtrace_del_fd(int fd); + +/* set the path of a given fd */ +void udtrace_fd_set_path(int fd, const char *path); /* is the given file descriptor part of the to-be-traced unix domain fd's? */ bool is_unix_socket(int fd); -char *udtrace_hexdump(const unsigned char *buf, int len, char *delim); +void udtrace_data(int fd, bool is_out, const char *fn, const uint8_t *data, unsigned int len); -- cgit v1.2.3