231 lines
5.4 KiB
C
231 lines
5.4 KiB
C
#define _GNU_SOURCE
|
|
|
|
#include "sock_events.h"
|
|
#include "utils.h"
|
|
|
|
#include <dlfcn.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <netinet/in.h>
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/syscall.h>
|
|
#include <sys/types.h>
|
|
#include <sys/un.h>
|
|
#include <unistd.h>
|
|
|
|
#ifdef __ANDROID__
|
|
#define MUTEX_ERRORCHECK PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
|
|
#else
|
|
#define MUTEX_ERRORCHECK PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
|
|
#endif
|
|
|
|
#define IS_OUT true
|
|
#define IS_IN false
|
|
|
|
static void trace_iov(int fd, bool is_out, const char *fn, int ret,
|
|
const struct iovec *iovec, int iovec_count)
|
|
{
|
|
int i, remain;
|
|
if (ret <= 0)
|
|
return;
|
|
|
|
remain = ret;
|
|
for (i = 0; i < iovec_count && remain > 0; i++) {
|
|
const struct iovec *vec = &iovec[i];
|
|
int written_len = vec->iov_len;
|
|
if (remain < vec->iov_len)
|
|
written_len = remain;
|
|
|
|
udtrace_data(fd, is_out, fn, vec->iov_base, written_len);
|
|
|
|
remain -= written_len;
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* Actual socket call handler functions
|
|
***********************************************************************/
|
|
|
|
void sock_ev_socket(int fd, int domain, int type, int protocol)
|
|
{
|
|
if (domain != AF_UNIX)
|
|
return;
|
|
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)
|
|
{
|
|
}
|
|
|
|
void sock_ev_accept(int fd, int ret, int err, struct sockaddr *addr,
|
|
socklen_t *addr_len)
|
|
{
|
|
if (ret < 0)
|
|
return;
|
|
LOG("accept(fd=%d on parent fd=%d)\n", ret, fd);
|
|
udtrace_add_fd_child(fd, ret);
|
|
}
|
|
|
|
void sock_ev_accept4(int fd, int ret, int err, struct sockaddr *addr,
|
|
socklen_t *addr_len, int flags)
|
|
{
|
|
if (ret < 0)
|
|
return;
|
|
LOG("accept(fd=%d on parent fd=%d)\n", ret, fd);
|
|
udtrace_add_fd_child(fd, ret);
|
|
}
|
|
|
|
void sock_ev_send(int fd, int ret, int err, const void *buf, size_t bytes,
|
|
int flags)
|
|
{
|
|
if (ret <= 0)
|
|
return;
|
|
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;
|
|
udtrace_data(fd, IS_IN, "recv", buf, ret);
|
|
}
|
|
|
|
void sock_ev_sendto(int fd, int ret, int err, const void *buf, size_t bytes,
|
|
int flags, const struct sockaddr *addr, socklen_t len)
|
|
{
|
|
if (ret <= 0)
|
|
return;
|
|
udtrace_data(fd, IS_OUT, "sendto", buf, ret);
|
|
}
|
|
|
|
void sock_ev_recvfrom(int fd, int ret, int err, void *buf, size_t bytes,
|
|
int flags, const struct sockaddr *addr, socklen_t *len)
|
|
{
|
|
if (ret <= 0)
|
|
return;
|
|
udtrace_data(fd, IS_IN, "recvfrom", buf, ret);
|
|
}
|
|
|
|
void sock_ev_sendmsg(int fd, int ret, int err, const struct msghdr *msg,
|
|
int flags)
|
|
{
|
|
trace_iov(fd, IS_OUT, "sendmsg", ret, msg->msg_iov, msg->msg_iovlen);
|
|
}
|
|
|
|
void sock_ev_recvmsg(int fd, int ret, int err, const struct msghdr *msg,
|
|
int flags)
|
|
{
|
|
trace_iov(fd, IS_IN, "recvmsg", ret, msg->msg_iov, msg->msg_iovlen);
|
|
}
|
|
|
|
#if !defined(__ANDROID__) || __ANDROID_API__ >= 21
|
|
void sock_ev_sendmmsg(int fd, int ret, int err, const struct mmsghdr *vmessages,
|
|
unsigned int vlen, int flags)
|
|
{
|
|
int i;
|
|
if (ret <= 0)
|
|
return;
|
|
for (i = 0; i < vlen; i++) {
|
|
const struct mmsghdr *mm = &vmessages[i];
|
|
trace_iov(fd, IS_OUT, "sendmmsg", mm->msg_len,
|
|
mm->msg_hdr.msg_iov, mm->msg_hdr.msg_iovlen);
|
|
}
|
|
}
|
|
|
|
void sock_ev_recvmmsg(int fd, int ret, int err, const struct mmsghdr *vmessages,
|
|
unsigned int vlen, int flags, const struct timespec *tmo)
|
|
{
|
|
|
|
int i;
|
|
if (ret <= 0)
|
|
return;
|
|
for (i = 0; i < vlen; i++) {
|
|
const struct mmsghdr *mm = &vmessages[i];
|
|
trace_iov(fd, IS_IN, "recvmmsg", mm->msg_len,
|
|
mm->msg_hdr.msg_iov, mm->msg_hdr.msg_iovlen);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void sock_ev_write(int fd, int ret, int err, const void *buf, size_t bytes)
|
|
{
|
|
if (ret <= 0)
|
|
return;
|
|
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;
|
|
udtrace_data(fd, IS_IN, "read", buf, ret);
|
|
}
|
|
|
|
void sock_ev_close(int fd, int ret, int err)
|
|
{
|
|
udtrace_del_fd(fd);
|
|
}
|
|
|
|
void sock_ev_dup(int fd, int ret, int err)
|
|
{
|
|
if (ret >= 0)
|
|
udtrace_add_fd(ret);
|
|
}
|
|
|
|
void sock_ev_dup2(int fd, int ret, int err, int newfd)
|
|
{
|
|
if (ret >= 0) {
|
|
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) {
|
|
udtrace_del_fd(newfd);
|
|
udtrace_add_fd(ret);
|
|
}
|
|
}
|
|
|
|
void sock_ev_writev(int fd, int ret, int err, const struct iovec *iovec,
|
|
int iovec_count)
|
|
{
|
|
trace_iov(fd, IS_OUT, "writev", ret, iovec, iovec_count);
|
|
}
|
|
|
|
void sock_ev_readv(int fd, int ret, int err, const struct iovec *iovec,
|
|
int iovec_count)
|
|
{
|
|
trace_iov(fd, IS_IN, "readv", ret, iovec, iovec_count);
|
|
}
|
|
|
|
void sock_ev_sendfile(int fd, int ret, int err, int in_fd, off_t *offset,
|
|
size_t bytes)
|
|
{
|
|
fprintf(stderr, "Cnnot trace sendmsg!");
|
|
}
|