summaryrefslogtreecommitdiffstats
path: root/qmi/ld_preload_wrapper/qmuxd_wrapper.c
blob: 7b2830dd6637bf71fccfdd6048f200a07589a304 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

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);
}