aboutsummaryrefslogtreecommitdiffstats
path: root/src/libtrace/libtrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libtrace/libtrace.c')
-rw-r--r--src/libtrace/libtrace.c609
1 files changed, 609 insertions, 0 deletions
diff --git a/src/libtrace/libtrace.c b/src/libtrace/libtrace.c
new file mode 100644
index 000000000..a785ec698
--- /dev/null
+++ b/src/libtrace/libtrace.c
@@ -0,0 +1,609 @@
1#define _GNU_SOURCE
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <dlfcn.h>
6#include <sys/types.h>
7#include <unistd.h>
8#include <sys/socket.h>
9#include <netinet/in.h>
10#include <arpa/inet.h>
11#include <sys/un.h>
12#include <sys/stat.h>
13
14// break recursivity on fopen call
15typedef FILE *(*orig_fopen_t)(const char *pathname, const char *mode);
16static orig_fopen_t orig_fopen = NULL;
17typedef FILE *(*orig_fopen64_t)(const char *pathname, const char *mode);
18static orig_fopen64_t orig_fopen64 = NULL;
19
20//
21// pid
22//
23static pid_t mypid = 0;
24static inline pid_t pid(void) {
25 if (!mypid)
26 mypid = getpid();
27 return mypid;
28}
29
30//
31// process name
32//
33#define MAXNAME 16
34static char myname[MAXNAME];
35static int nameinit = 0;
36static char *name(void) {
37 if (!nameinit) {
38 // initialize the name of the process based on /proc/PID/comm
39 memset(myname, 0, MAXNAME);
40
41 pid_t p = pid();
42 char *fname;
43 if (asprintf(&fname, "/proc/%u/comm", p) == -1)
44 return "unknown";
45
46 // read file
47 if (!orig_fopen)
48 orig_fopen = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen");
49 FILE *fp = orig_fopen(fname, "r");
50 if (!fp)
51 return "unknown";
52 if (fgets(myname, MAXNAME, fp) == NULL) {
53 fclose(fp);
54 free(fname);
55 return "unknown";
56 }
57
58 // clean '\n'
59 char *ptr = strchr(myname, '\n');
60 if (ptr)
61 *ptr = '\0';
62
63 fclose(fp);
64 free(fname);
65 nameinit = 1;
66 }
67
68 return myname;
69}
70
71//
72// network
73//
74typedef struct {
75 int val;
76 char *name;
77} XTable;
78
79static XTable socket_type[] = {
80#ifdef SOCK_STREAM
81 { SOCK_STREAM, "SOCK_STREAM" },
82#endif
83#ifdef SOCK_DGRAM
84 { SOCK_DGRAM, "SOCK_DGRAM" },
85#endif
86#ifdef SOCK_RAW
87 { SOCK_RAW, "SOCK_RAW" },
88#endif
89#ifdef SOCK_RDM
90 { SOCK_RDM, "SOCK_RDM" },
91#endif
92#ifdef SOCK_SEQPACKET
93 { SOCK_SEQPACKET, "SOCK_SEQPACKET" },
94#endif
95#ifdef SOCK_DCCP
96 { SOCK_DCCP, "SOCK_DCCP" },
97#endif
98 { 0, NULL} // NULL terminated
99};
100
101static XTable socket_domain[] = {
102#ifdef AF_INET
103 { AF_INET, "AF_INET" },
104#endif
105#ifdef AF_INET6
106 { AF_INET6, "AF_INET6" },
107#endif
108#ifdef AF_LOCAL
109 { AF_LOCAL, "AF_LOCAL" },
110#endif
111#ifdef AF_PACKET
112 { AF_PACKET, "AF_PACKET" },
113#endif
114#ifdef AF_IPX
115 { AF_IPX, "AF_IPX" },
116#endif
117#ifdef AF_NETLINK
118 { AF_NETLINK, "AF_NETLINK" },
119#endif
120#ifdef AF_X25
121 { AF_X25, "AF_X25" },
122#endif
123#ifdef AF_AX25
124 { AF_AX25, "AF_AX25" },
125#endif
126#ifdef AF_ATMPVC
127 { AF_ATMPVC, "AF_ATMPVC" },
128#endif
129#ifdef AF_APPLETALK
130 { AF_APPLETALK, "AF_APPLETALK" },
131#endif
132 { 0, NULL} // NULL terminated
133};
134
135static XTable socket_protocol[] = {
136#ifdef IPPROTO_IP
137 { IPPROTO_IP, "IPPROTO_IP" },
138#endif
139#ifdef IPPROTO_ICMP
140 { IPPROTO_ICMP, "IPPROTO_ICMP" },
141#endif
142#ifdef IPPROTO_IGMP
143 { IPPROTO_IGMP, "IPPROTO_IGMP" },
144#endif
145#ifdef IPPROTO_IPIP
146 { IPPROTO_IPIP, "IPPROTO_IPIP" },
147#endif
148#ifdef IPPROTO_TCP
149 { IPPROTO_TCP, "IPPROTO_TCP" },
150#endif
151#ifdef IPPROTO_EGP
152 { IPPROTO_EGP, "IPPROTO_EGP" },
153#endif
154#ifdef IPPROTO_PUP
155 { IPPROTO_PUP, "IPPROTO_PUP" },
156#endif
157#ifdef IPPROTO_UDP
158 { IPPROTO_UDP, "IPPROTO_UDP" },
159#endif
160#ifdef IPPROTO_IDP
161 { IPPROTO_IDP, "IPPROTO_IDP" },
162#endif
163#ifdef IPPROTO_DCCP
164 { IPPROTO_DCCP, "IPPROTO_DCCP" },
165#endif
166#ifdef IPPROTO_RSVP
167 { IPPROTO_RSVP, "IPPROTO_RSVP" },
168#endif
169#ifdef IPPROTO_GRE
170 { IPPROTO_GRE, "IPPROTO_GRE" },
171#endif
172#ifdef IPPROTO_IPV6
173 { IPPROTO_IPV6, "IPPROTO_IPV6" },
174#endif
175#ifdef IPPROTO_ESP
176 { IPPROTO_ESP, "IPPROTO_ESP" },
177#endif
178#ifdef IPPROTO_AH
179 { IPPROTO_AH, "IPPROTO_AH" },
180#endif
181#ifdef IPPROTO_BEETPH
182 { IPPROTO_BEETPH, "IPPROTO_BEETPH" },
183#endif
184#ifdef IPPROTO_PIM
185 { IPPROTO_PIM, "IPPROTO_PIM" },
186#endif
187#ifdef IPPROTO_COMP
188 { IPPROTO_COMP, "IPPROTO_COMP" },
189#endif
190#ifdef IPPROTO_SCTP
191 { IPPROTO_SCTP, "IPPROTO_SCTP" },
192#endif
193#ifdef IPPROTO_UDPLITE
194 { IPPROTO_UDPLITE, "IPPROTO_UDPLITE" },
195#endif
196#ifdef IPPROTO_RAW
197 { IPPROTO_RAW, "IPPROTO_RAW" },
198#endif
199 { 0, NULL} // NULL terminated
200};
201
202static char *translate(XTable *table, int val) {
203 while (table->name != NULL) {
204 if (val == table->val)
205 return table->name;
206 table++;
207 }
208
209 return NULL;
210}
211
212static void print_sockaddr(const char *call, const struct sockaddr *addr) {
213 if (addr->sa_family == AF_INET) {
214 struct sockaddr_in *a = (struct sockaddr_in *) addr;
215 printf("%u:%s:%s %s:%u\n", pid(), name(), call, inet_ntoa(a->sin_addr), ntohs(a->sin_port));
216 }
217 else if (addr->sa_family == AF_INET6) {
218 struct sockaddr_in6 *a = (struct sockaddr_in6 *) addr;
219 char str[INET6_ADDRSTRLEN];
220 inet_ntop(AF_INET6, &(a->sin6_addr), str, INET6_ADDRSTRLEN);
221 printf("%u:%s:%s %s\n", pid(), name(), call, str);
222 }
223 else if (addr->sa_family == AF_UNIX) {
224 struct sockaddr_un *a = (struct sockaddr_un *) addr;
225 if (a->sun_path[0])
226 printf("%u:%s:%s %s\n", pid(), name(), call, a->sun_path);
227 else
228 printf("%u:%s:%s @%s\n", pid(), name(), call, a->sun_path + 1);
229 }
230 else {
231 printf("%u:%s:%s family %d\n", pid(), name(), call, addr->sa_family);
232 }
233}
234
235//
236// syscalls
237//
238
239// open
240typedef int (*orig_open_t)(const char *pathname, int flags, mode_t mode);
241static orig_open_t orig_open = NULL;
242int open(const char *pathname, int flags, mode_t mode) {
243 if (!orig_open)
244 orig_open = (orig_open_t)dlsym(RTLD_NEXT, "open");
245
246 int rv = orig_open(pathname, flags, mode);
247 printf("%u:%s:open %s\n", pid(), name(), pathname);
248 return rv;
249}
250
251typedef int (*orig_open64_t)(const char *pathname, int flags, mode_t mode);
252static orig_open64_t orig_open64 = NULL;
253int open64(const char *pathname, int flags, mode_t mode) {
254 if (!orig_open64)
255 orig_open64 = (orig_open64_t)dlsym(RTLD_NEXT, "open64");
256
257 int rv = orig_open64(pathname, flags, mode);
258 printf("%u:%s:open64 %s\n", pid(), name(), pathname);
259 return rv;
260}
261
262// openat
263typedef int (*orig_openat_t)(int dirfd, const char *pathname, int flags, mode_t mode);
264static orig_openat_t orig_openat = NULL;
265int openat(int dirfd, const char *pathname, int flags, mode_t mode) {
266 if (!orig_openat)
267 orig_openat = (orig_openat_t)dlsym(RTLD_NEXT, "openat");
268
269 int rv = orig_openat(dirfd, pathname, flags, mode);
270 printf("%u:%s:openat %s\n", pid(), name(), pathname);
271 return rv;
272}
273
274typedef int (*orig_openat64_t)(int dirfd, const char *pathname, int flags, mode_t mode);
275static orig_openat64_t orig_openat64 = NULL;
276int openat64(int dirfd, const char *pathname, int flags, mode_t mode) {
277 if (!orig_openat64)
278 orig_openat64 = (orig_openat64_t)dlsym(RTLD_NEXT, "openat64");
279
280 int rv = orig_openat64(dirfd, pathname, flags, mode);
281 printf("%u:%s:openat64 %s\n", pid(), name(), pathname);
282 return rv;
283}
284
285
286// fopen
287FILE *fopen(const char *pathname, const char *mode) {
288 if (!orig_fopen)
289 orig_fopen = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen");
290
291 FILE *rv = orig_fopen(pathname, mode);
292 printf("%u:%s:fopen %s\n", pid(), name(), pathname);
293 return rv;
294}
295
296FILE *fopen64(const char *pathname, const char *mode) {
297 if (!orig_fopen64)
298 orig_fopen64 = (orig_fopen_t)dlsym(RTLD_NEXT, "fopen64");
299
300 FILE *rv = orig_fopen64(pathname, mode);
301 printf("%u:%s:fopen64 %s\n", pid(), name(), pathname);
302 return rv;
303}
304
305
306// freopen
307typedef FILE *(*orig_freopen_t)(const char *pathname, const char *mode, FILE *stream);
308static orig_freopen_t orig_freopen = NULL;
309FILE *freopen(const char *pathname, const char *mode, FILE *stream) {
310 if (!orig_freopen)
311 orig_freopen = (orig_freopen_t)dlsym(RTLD_NEXT, "freopen");
312
313 FILE *rv = orig_freopen(pathname, mode, stream);
314 printf("%u:%s:freopen %s\n", pid(), name(), pathname);
315 return rv;
316}
317
318typedef FILE *(*orig_freopen64_t)(const char *pathname, const char *mode, FILE *stream);
319static orig_freopen64_t orig_freopen64 = NULL;
320FILE *freopen64(const char *pathname, const char *mode, FILE *stream) {
321 if (!orig_freopen64)
322 orig_freopen64 = (orig_freopen64_t)dlsym(RTLD_NEXT, "freopen64");
323
324 FILE *rv = orig_freopen64(pathname, mode, stream);
325 printf("%u:%s:freopen64 %s\n", pid(), name(), pathname);
326 return rv;
327}
328
329// unlink
330typedef int (*orig_unlink_t)(const char *pathname);
331static orig_unlink_t orig_unlink = NULL;
332int unlink(const char *pathname) {
333 if (!orig_unlink)
334 orig_unlink = (orig_unlink_t)dlsym(RTLD_NEXT, "unlink");
335
336 int rv = orig_unlink(pathname);
337 printf("%u:%s:unlink %s\n", pid(), name(), pathname);
338 return rv;
339}
340
341typedef int (*orig_unlinkat_t)(int dirfd, const char *pathname, int flags);
342static orig_unlinkat_t orig_unlinkat = NULL;
343int unlinkat(int dirfd, const char *pathname, int flags) {
344 if (!orig_unlinkat)
345 orig_unlinkat = (orig_unlinkat_t)dlsym(RTLD_NEXT, "unlinkat");
346
347 int rv = orig_unlinkat(dirfd, pathname, flags);
348 printf("%u:%s:unlinkat %s\n", pid(), name(), pathname);
349 return rv;
350}
351
352// mkdir/mkdirat/rmdir
353typedef int (*orig_mkdir_t)(const char *pathname, mode_t mode);
354static orig_mkdir_t orig_mkdir = NULL;
355int mkdir(const char *pathname, mode_t mode) {
356 if (!orig_mkdir)
357 orig_mkdir = (orig_mkdir_t)dlsym(RTLD_NEXT, "mkdir");
358
359 int rv = orig_mkdir(pathname, mode);
360 printf("%u:%s:mkdir %s\n", pid(), name(), pathname);
361 return rv;
362}
363
364typedef int (*orig_mkdirat_t)(int dirfd, const char *pathname, mode_t mode);
365static orig_mkdirat_t orig_mkdirat = NULL;
366int mkdirat(int dirfd, const char *pathname, mode_t mode) {
367 if (!orig_mkdirat)
368 orig_mkdirat = (orig_mkdirat_t)dlsym(RTLD_NEXT, "mkdirat");
369
370 int rv = orig_mkdirat(dirfd, pathname, mode);
371 printf("%u:%s:mkdirat %s\n", pid(), name(), pathname);
372 return rv;
373}
374
375typedef int (*orig_rmdir_t)(const char *pathname);
376static orig_rmdir_t orig_rmdir = NULL;
377int rmdir(const char *pathname) {
378 if (!orig_rmdir)
379 orig_rmdir = (orig_rmdir_t)dlsym(RTLD_NEXT, "rmdir");
380
381 int rv = orig_rmdir(pathname);
382 printf("%u:%s:rmdir %s\n", pid(), name(), pathname);
383 return rv;
384}
385
386// stat
387typedef int (*orig_stat_t)(const char *pathname, struct stat *buf);
388static orig_stat_t orig_stat = NULL;
389int stat(const char *pathname, struct stat *buf) {
390 if (!orig_stat)
391 orig_stat = (orig_stat_t)dlsym(RTLD_NEXT, "stat");
392
393 int rv = orig_stat(pathname, buf);
394 printf("%u:%s:stat %s\n", pid(), name(), pathname);
395 return rv;
396}
397
398typedef int (*orig_stat64_t)(const char *pathname, struct stat64 *buf);
399static orig_stat64_t orig_stat64 = NULL;
400int stat64(const char *pathname, struct stat64 *buf) {
401 if (!orig_stat)
402 orig_stat64 = (orig_stat64_t)dlsym(RTLD_NEXT, "stat");
403
404 int rv = orig_stat64(pathname, buf);
405 printf("%u:%s:stat %s\n", pid(), name(), pathname);
406 return rv;
407}
408
409
410// access
411typedef int (*orig_access_t)(const char *pathname, int mode);
412static orig_access_t orig_access = NULL;
413int access(const char *pathname, int mode) {
414 if (!orig_access)
415 orig_access = (orig_access_t)dlsym(RTLD_NEXT, "access");
416
417 int rv = orig_access(pathname, mode);
418 printf("%u:%s:access %s\n", pid(), name(), pathname);
419 return rv;
420}
421
422
423// connect
424typedef int (*orig_connect_t)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
425static orig_connect_t orig_connect = NULL;
426int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
427 if (!orig_connect)
428 orig_connect = (orig_connect_t)dlsym(RTLD_NEXT, "connect");
429
430 int rv = orig_connect(sockfd, addr, addrlen);
431 print_sockaddr("connect", addr);
432
433 return rv;
434}
435
436// socket
437typedef int (*orig_socket_t)(int domain, int type, int protocol);
438static orig_socket_t orig_socket = NULL;
439static char buf[1024];
440int socket(int domain, int type, int protocol) {
441 if (!orig_socket)
442 orig_socket = (orig_socket_t)dlsym(RTLD_NEXT, "socket");
443
444 int rv = orig_socket(domain, type, protocol);
445 char *ptr = buf;
446 ptr += sprintf(ptr, "%u:%s:socket ", pid(), name());
447 char *str = translate(socket_domain, domain);
448 if (str == NULL)
449 ptr += sprintf(ptr, "%d ", domain);
450 else
451 ptr += sprintf(ptr, "%s ", str);
452
453 int t = type; // glibc uses higher bits for various other purposes
454#ifdef SOCK_CLOEXEC
455 t &= ~SOCK_CLOEXEC;
456#endif
457#ifdef SOCK_NONBLOCK
458 t &= ~SOCK_NONBLOCK;
459#endif
460 str = translate(socket_type, t);
461 if (str == NULL)
462 ptr += sprintf(ptr, "%d ", type);
463 else
464 ptr += sprintf(ptr, "%s ", str);
465
466 str = translate(socket_protocol, protocol);
467 if (str == NULL)
468 ptr += sprintf(ptr, "%d", protocol);
469 else
470 ptr += sprintf(ptr, "%s", str);
471
472 printf("%s\n", buf);
473 return rv;
474}
475
476// bind
477typedef int (*orig_bind_t)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
478static orig_bind_t orig_bind = NULL;
479int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
480 if (!orig_bind)
481 orig_bind = (orig_bind_t)dlsym(RTLD_NEXT, "bind");
482
483 int rv = orig_bind(sockfd, addr, addrlen);
484 print_sockaddr("bind", addr);
485
486 return rv;
487}
488
489#if 0 //todo: fix compilation problems
490typedef int (*orig_accept_t)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
491static orig_accept_t orig_accept = NULL;
492int accept(int sockfd, struct sockaddr *addr, socklen_t addrlen) {
493 if (!orig_accept)
494 orig_accept = (orig_accept_t)dlsym(RTLD_NEXT, "accept");
495
496 int rv = orig_accept(sockfd, addr, addrlen);
497 print_sockaddr("accept", addr);
498
499 return rv;
500}
501#endif
502
503typedef int (*orig_system_t)(const char *command);
504static orig_system_t orig_system = NULL;
505int system(const char *command) {
506 if (!orig_system)
507 orig_system = (orig_system_t)dlsym(RTLD_NEXT, "system");
508
509 int rv = orig_system(command);
510 printf("%u:%s:system %s\n", pid(), name(), command);
511
512 return rv;
513}
514
515typedef int (*orig_setuid_t)(uid_t uid);
516static orig_setuid_t orig_setuid = NULL;
517int setuid(uid_t uid) {
518 if (!orig_setuid)
519 orig_setuid = (orig_setuid_t)dlsym(RTLD_NEXT, "setuid");
520
521 int rv = orig_setuid(uid);
522 printf("%u:%s:setuid %d\n", pid(), name(), uid);
523
524 return rv;
525}
526
527typedef int (*orig_setgid_t)(gid_t gid);
528static orig_setgid_t orig_setgid = NULL;
529int setgid(gid_t gid) {
530 if (!orig_setgid)
531 orig_setgid = (orig_setgid_t)dlsym(RTLD_NEXT, "setgid");
532
533 int rv = orig_setgid(gid);
534 printf("%u:%s:setgid %d\n", pid(), name(), gid);
535
536 return rv;
537}
538
539typedef int (*orig_setfsuid_t)(uid_t uid);
540static orig_setfsuid_t orig_setfsuid = NULL;
541int setfsuid(uid_t uid) {
542 if (!orig_setfsuid)
543 orig_setfsuid = (orig_setfsuid_t)dlsym(RTLD_NEXT, "setfsuid");
544
545 int rv = orig_setfsuid(uid);
546 printf("%u:%s:setfsuid %d\n", pid(), name(), uid);
547
548 return rv;
549}
550
551typedef int (*orig_setfsgid_t)(gid_t gid);
552static orig_setfsgid_t orig_setfsgid = NULL;
553int setfsgid(gid_t gid) {
554 if (!orig_setfsgid)
555 orig_setfsgid = (orig_setfsgid_t)dlsym(RTLD_NEXT, "setfsgid");
556
557 int rv = orig_setfsgid(gid);
558 printf("%u:%s:setfsgid %d\n", pid(), name(), gid);
559
560 return rv;
561}
562
563typedef int (*orig_setreuid_t)(uid_t ruid, uid_t euid);
564static orig_setreuid_t orig_setreuid = NULL;
565int setreuid(uid_t ruid, uid_t euid) {
566 if (!orig_setreuid)
567 orig_setreuid = (orig_setreuid_t)dlsym(RTLD_NEXT, "setreuid");
568
569 int rv = orig_setreuid(ruid, euid);
570 printf("%u:%s:setreuid %d %d\n", pid(), name(), ruid, euid);
571
572 return rv;
573}
574
575typedef int (*orig_setregid_t)(gid_t rgid, gid_t egid);
576static orig_setregid_t orig_setregid = NULL;
577int setregid(gid_t rgid, gid_t egid) {
578 if (!orig_setregid)
579 orig_setregid = (orig_setregid_t)dlsym(RTLD_NEXT, "setregid");
580
581 int rv = orig_setregid(rgid, egid);
582 printf("%u:%s:setregid %d %d\n", pid(), name(), rgid, egid);
583
584 return rv;
585}
586
587typedef int (*orig_setresuid_t)(uid_t ruid, uid_t euid, uid_t suid);
588static orig_setresuid_t orig_setresuid = NULL;
589int setresuid(uid_t ruid, uid_t euid, uid_t suid) {
590 if (!orig_setresuid)
591 orig_setresuid = (orig_setresuid_t)dlsym(RTLD_NEXT, "setresuid");
592
593 int rv = orig_setresuid(ruid, euid, suid);
594 printf("%u:%s:setresuid %d %d %d\n", pid(), name(), ruid, euid, suid);
595
596 return rv;
597}
598
599typedef int (*orig_setresgid_t)(gid_t rgid, gid_t egid, gid_t sgid);
600static orig_setresgid_t orig_setresgid = NULL;
601int setresgid(gid_t rgid, gid_t egid, gid_t sgid) {
602 if (!orig_setresgid)
603 orig_setresgid = (orig_setresgid_t)dlsym(RTLD_NEXT, "setresgid");
604
605 int rv = orig_setresgid(rgid, egid, sgid);
606 printf("%u:%s:setresgid %d %d %d\n", pid(), name(), rgid, egid, sgid);
607
608 return rv;
609} \ No newline at end of file