udtrace/libc_overrides.c

221 lines
7.9 KiB
C

/*
* (C) 2018 by Harald Welte <laforge@gnumonks.org>
* based on modified code from tcpsnitch
* (C) 2016 by Gregory Vander Schueren <gregory.vanderschueren@gmail.com>
*/
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "sock_events.h"
#include "utils.h"
#define EXPORT __attribute__((visibility("default")))
#define LIBC_VERSION (__GLIBC__ * 100 + __GLIBC_MINOR__)
#define arg2 a
#define arg3 arg2, b
#define arg4 arg3, c
#define arg5 arg4, d
#define arg6 arg5, e
#define override(FUNCTION, RETURN_TYPE, ARGS_COUNT, ...) \
typedef RETURN_TYPE (*FUNCTION##_type)(int fd, __VA_ARGS__); \
FUNCTION##_type orig_##FUNCTION; \
\
EXPORT RETURN_TYPE FUNCTION(int fd, __VA_ARGS__) { \
if (!orig_##FUNCTION) \
orig_##FUNCTION = \
(FUNCTION##_type)dlsym(RTLD_NEXT, #FUNCTION); \
RETURN_TYPE ret = orig_##FUNCTION(fd, arg##ARGS_COUNT); \
int err = errno; \
if (is_unix_socket(fd)) \
sock_ev_##FUNCTION(fd, ret, err, arg##ARGS_COUNT); \
errno = err; \
return ret; \
}
#define override_1arg(FUNCTION, RETURN_TYPE) \
typedef RETURN_TYPE (*FUNCTION##_type)(int fd); \
FUNCTION##_type orig_##FUNCTION; \
\
EXPORT RETURN_TYPE FUNCTION(int fd) { \
if (!orig_##FUNCTION) \
orig_##FUNCTION = \
(FUNCTION##_type)dlsym(RTLD_NEXT, #FUNCTION); \
RETURN_TYPE ret = orig_##FUNCTION(fd); \
int err = errno; \
if (is_unix_socket(fd)) sock_ev_##FUNCTION(fd, ret, err); \
errno = err; \
return ret; \
}
/*
Use "standard" font here to generate ASCII arts:
http://patorjk.com/software/taag/#p=display&f=Standard
*/
/*
____ ___ ____ _ _______ _____ _ ____ ___
/ ___| / _ \ / ___| |/ / ____|_ _| / \ | _ \_ _|
\___ \| | | | | | ' /| _| | | / _ \ | |_) | |
___) | |_| | |___| . \| |___ | | / ___ \| __/| |
|____/ \___/ \____|_|\_\_____| |_| /_/ \_\_| |___|
sys/socket.h - Internet Protocol family
functions: socket(), bind(), connect(), listen(), accept(),
accept4(), send(), recv(), sendto(), recvfrom(), sendmsg(),
recvmsg(), sendmmsg(), recvmmsg(),
*/
typedef int (*socket_type)(int domain, int type, int protocol);
socket_type orig_socket;
EXPORT int socket(int domain, int type, int protocol) {
if (!orig_socket) orig_socket = (socket_type)dlsym(RTLD_NEXT, "socket");
int fd = orig_socket(domain, type, protocol);
sock_ev_socket(fd, domain, type, protocol);
return fd;
}
typedef int (*connect_type)(int fd, const struct sockaddr *addr, socklen_t len);
connect_type orig_connect;
EXPORT int connect(int fd, const struct sockaddr *addr, socklen_t len) {
if (!orig_connect)
orig_connect = (connect_type)dlsym(RTLD_NEXT, "connect");
int ret = orig_connect(fd, addr, len);
int err = errno;
if (is_unix_socket(fd)) sock_ev_connect(fd, ret, err, addr, len);
errno = err;
return ret;
}
override(bind, int, 3, const struct sockaddr *a, socklen_t b);
override(listen, int, 2, int a);
override(accept, int, 3, struct sockaddr *a, socklen_t *b);
override(accept4, int, 4, struct sockaddr *a, socklen_t *b, int c);
#if defined(__ANDROID__) && __ANDROID_API__ <= 19
override(send, ssize_t, 4, const void *a, size_t b, unsigned int c);
override(recv, ssize_t, 4, void *a, size_t b, unsigned int c);
#else
override(send, ssize_t, 4, const void *a, size_t b, int c);
override(recv, ssize_t, 4, void *a, size_t b, int c);
#endif
override(sendto, ssize_t, 6, const void *a, size_t b, int c,
const struct sockaddr *d, socklen_t e);
#if defined(__ANDROID__) && __ANDROID_API__ <= 19
override(recvfrom, ssize_t, 6, void *a, size_t b, unsigned int c,
const struct sockaddr *d, socklen_t *e);
#elif defined(__ANDROID__)
override(recvfrom, ssize_t, 6, void *a, size_t b, int c,
const struct sockaddr *d, socklen_t *e);
#else
override(recvfrom, ssize_t, 6, void *a, size_t b, int c, struct sockaddr *d,
socklen_t *e);
#endif
#if defined(__ANDROID__) && __ANDROID_API__ <= 19
override(sendmsg, ssize_t, 3, const struct msghdr *a, unsigned int b);
override(recvmsg, ssize_t, 3, struct msghdr *a, unsigned int b);
#else
override(sendmsg, ssize_t, 3, const struct msghdr *a, int b);
override(recvmsg, ssize_t, 3, struct msghdr *a, int b);
#endif
#if defined(__ANDROID__) && __ANDROID_API__ >= 21
override(sendmmsg, int, 4, const struct mmsghdr *a, unsigned int b, int c);
override(recvmmsg, int, 5, struct mmsghdr *a, unsigned int b, int c,
const struct timespec *d);
#elif LIBC_VERSION > 219 // Absolutely not sure this is the right boundary!
override(sendmmsg, int, 4, struct mmsghdr *a, unsigned int b, int c);
override(recvmmsg, int, 5, struct mmsghdr *a, unsigned int b, int c,
struct timespec *d);
#else
override(sendmmsg, int, 4, struct mmsghdr *a, unsigned int b, int c);
override(recvmmsg, int, 5, struct mmsghdr *a, unsigned int b, int c,
const struct timespec *d);
#endif
/*
_ _ _ _ ___ ____ _____ ____ _ ____ ___
| | | | \ | |_ _/ ___|_ _| _ \ / \ | _ \_ _|
| | | | \| || |\___ \ | | | | | | / _ \ | |_) | |
| |_| | |\ || | ___) || | | |_| | / ___ \| __/| |
\___/|_| \_|___|____/ |_| |____/ /_/ \_\_| |___|
unistd.h - standard symbolic constants and types
functions: write(), read(), close(), fork(), dup(), dup2(), dup3()
*/
override(write, ssize_t, 3, const void *a, size_t b);
override(read, ssize_t, 3, void *a, size_t b);
typedef int (*close_type)(int fd);
close_type orig_close;
EXPORT int close(int fd) {
if (!orig_close) orig_close = (close_type)dlsym(RTLD_NEXT, "close");
bool is_unix = is_unix_socket(fd);
int ret = orig_close(fd);
int err = errno;
if (is_unix) sock_ev_close(fd, ret, err);
errno = err;
return ret;
}
override_1arg(dup, int);
override(dup2, int, 2, int a);
override(dup3, int, 3, int a, int b);
/*
_ _ _ _____ _ ____ ___
| | | |_ _/ _ \ / \ | _ \_ _|
| | | || | | | | / _ \ | |_) | |
| |_| || | |_| | / ___ \| __/| |
\___/|___\___/ /_/ \_\_| |___|
sys/uio.h - definitions for vector I/O operations
functions: writev(), readv()
*/
override(writev, ssize_t, 3, const struct iovec *a, int b);
override(readv, ssize_t, 3, const struct iovec *a, int b);
/*
____ _____ _ _ ____ _____ ___ _ _____ _ ____ ___
/ ___|| ____| \ | | _ \| ___|_ _| | | ____| / \ | _ \_ _|
\___ \| _| | \| | | | | |_ | || | | _| / _ \ | |_) | |
___) | |___| |\ | |_| | _| | || |___| |___ / ___ \| __/| |
|____/|_____|_| \_|____/|_| |___|_____|_____| /_/ \_\_| |___|
sendfile.h - transfer data between file descriptors
functions: sendfile()
*/
override(sendfile, ssize_t, 4, int a, off_t *b, size_t c);