List of commits:
Subject Hash Author Date (UTC)
Added curl support c374ad15d2d5548d168084c0e8506929803e9bf0 Catalin(ux) M. BOIE 2022-11-30 11:28:48
More Latex modules were missing ff5bec2cfba2cf77e0115f89124cdeb83dfbc73d Catalin(ux) M. BOIE 2022-11-24 16:52:48
Forgot to add beamer 1080ddc6497af77b66fd57eb7b9da0abaf75cb2a Catalin(ux) M. BOIE 2022-11-24 16:39:30
Mispelled docs 463d312e5ddc8b237e03a4d9b4cfb33524393fb0 Catalin(ux) M. BOIE 2022-11-24 16:11:45
More docs updated 83876ce8fcf9ae03c189e4fc7f354bf67f328916 Catalin(ux) M. BOIE 2022-11-24 15:59:05
Record bytes read/written on fds 428c3905bb135725ac3bd2ecfe5949e434b179b5 Catalin(ux) M. BOIE 2022-11-24 15:58:25
A lot of small fixes 9a5841916f3f0870ca091f457102c7512b21808a Catalin(ux) M. BOIE 2022-11-23 07:28:06
Added pthread_join + small fixes a5206c335f8c858d791f114da7361190196ad4a4 Catalin(ux) M. BOIE 2022-11-21 14:05:31
Lots of updates 5583e8dbd607b684a14ced92b4d2ffdacbcf57e1 Catalin(ux) M. BOIE 2022-11-18 05:40:05
mysql, sqlite3, depth d9d83cafbd372d1055fa2e51cdf3deb2396f5d08 Catalin(ux) M. BOIE 2022-11-07 05:58:04
More spec fixes 3867b17137b5397c3eeabdcbbc232417ad212a27 Catalin(ux) M. BOIE 2022-10-25 19:04:28
More spec fixes 68abc4ce485fbbcc18a232e57b956f9e2b016d72 Catalin(ux) M. BOIE 2022-10-25 18:48:22
Fixed installation paths in Makefiles c98920bd55f7cd2ebcec7083e2360009d8c16b29 Catalin(ux) M. BOIE 2022-10-25 18:19:49
Debian support added, create correctly the paths for install 512c13ca06dda005504cdeab831431c943dde74a Catalin(ux) M. BOIE 2022-10-25 06:19:50
Bump version to 0.6 for a stupid reason (mass with dupdump) c4d10510ddf944965a80d9a3e5f4ac62b84a103e Catalin(ux) M. BOIE 2022-10-25 06:04:33
History update c83cd94af87636bc67bf9526ca0a65734ce96fac Catalin(ux) M. BOIE 2022-10-22 10:34:01
TODO update b1cbf0845dada017466763126d8569f62ace4cb4 Catalin(ux) M. BOIE 2022-10-22 08:20:20
Need libcap 4cdcd084fcf0e089e074aa0b090bc6f569a5d625 Catalin(ux) M. BOIE 2022-10-22 07:32:51
Removed BuildArch 54a76d595eb787edbd887d567eb5b29a6261cb4a Catalin(ux) M. BOIE 2022-10-21 18:51:41
Add 'catalinux+' for Conn d7b41a60e091fdd10aee5b45355c07896155853b Catalin(ux) M. BOIE 2022-10-21 18:39:11
Commit c374ad15d2d5548d168084c0e8506929803e9bf0 - Added curl support
Author: Catalin(ux) M. BOIE
Author date (UTC): 2022-11-30 11:28
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2022-11-30 11:28
Parent(s): ff5bec2cfba2cf77e0115f89124cdeb83dfbc73d
Signer:
Signing key:
Signing status: N
Tree: 6a1b0c1def21b41f4456f2dbdc67ecfa60e17d2c
File Lines added Lines deleted
.gitignore 1 0
Makefile.in 6 1
TODO 8 0
agent/Makefile 10 5
agent/ctools.c 0 11
agent/ctools.h 0 1
agent/curl.TODO 4 0
agent/curl.c 98 0
agent/curl.h 25 0
agent/ninedogs.TODO 2 0
agent/ninedogs.c 424 354
common/Makefile 7 1
common/decode_text.c 149 0
common/decode_text.h 9 0
common/info.c 245 0
common/info.h 8 0
common/shared.h 48 3
docs/pre1.tex 99 5
docs/pre1.txt 6 0
misc/.gitignore 1 0
misc/Makefile 28 0
misc/TODO 2 0
misc/nd-info.c 188 0
test/curl/.gitignore 1 0
test/curl/1.c 35 0
test/curl/1.run 16 0
test/info/.gitignore 1 0
test/info/1.c 109 0
test/info/1.run 17 0
test/php-sock/1.run 1 1
test/php-sock/2.run 1 1
test/trace/.gitignore 2 0
test/trace/lseek.c 12 0
test/trace/lseek.run 4 4
trace/Makefile 2 2
trace/nd-trace.c 131 62
File .gitignore changed (mode: 100644) (index c3ccba7..dad677a)
... ... obj/
19 19 *.nd *.nd
20 20 *.db *.db
21 21 *.asm *.asm
22 *.tmp
File Makefile.in changed (mode: 100644) (index d2ec340..ec4811b)
... ... export JSON_CFLAGS += $(shell pkg-config --cflags json-c)
14 14 export CFLAGSSO = $(CFLAGS) -ldl -shared -rdynamic -fPIC export CFLAGSSO = $(CFLAGS) -ldl -shared -rdynamic -fPIC
15 15
16 16
17 all: common agent ingestd webd trace docs
17 all: common agent ingestd webd trace misc docs
18 18
19 19
20 20 .PHONY: common .PHONY: common
 
... ... webd:
37 37 trace: trace:
38 38 make -R -C trace compile make -R -C trace compile
39 39
40 .PHONY: misc
41 misc:
42 make -R -C misc compile
43
40 44 .PHONY: docs .PHONY: docs
41 45 docs: docs:
42 46 make -R -C docs compile make -R -C docs compile
 
... ... install:
50 54 @make -C ingestd install @make -C ingestd install
51 55 @make -C webd install @make -C webd install
52 56 @make -C trace install @make -C trace install
57 @make -C misc install
53 58 @mkdir -p $(I_ETC)/nginx/conf.d @mkdir -p $(I_ETC)/nginx/conf.d
54 59 @cp -vd samples/nginx.conf $(I_ETC)/nginx/conf.d/ninedogs.conf.sample @cp -vd samples/nginx.conf $(I_ETC)/nginx/conf.d/ninedogs.conf.sample
55 60 @cp -vd --no-clobber samples/nginx.conf $(I_ETC)/nginx/conf.d/ninedogs.conf @cp -vd --no-clobber samples/nginx.conf $(I_ETC)/nginx/conf.d/ninedogs.conf
File TODO changed (mode: 100644) (index 9d281a9..3dbb04c)
1 == Urgent ==
2 [ ] Seems curl is taking over SEGV handling. Prevent that, but allow the handler to be called.
3 [ ]
4
5 == Non-urgent
6
1 7 [ ] Both client and server side are free (AGPLv3). [ ] Both client and server side are free (AGPLv3).
2 8 Offering this as a SaaS may bring some money to support Offering this as a SaaS may bring some money to support
3 9 the development. the development.
4 10 [ ] Figure out what to do with SELinux/AppArmor. [ ] Figure out what to do with SELinux/AppArmor.
11 [ ] We can easily provide a vault service by hijacking getenv
12 And providing a filesystem.
5 13 [ ] [ ]
6 14
7 15
File agent/Makefile changed (mode: 100644) (index c980a15..c78f0f3)
3 3 all: all:
4 4 make -R -C .. agent make -R -C .. agent
5 5
6 COMMON_H += ../common/ids.h ../common/tools.h ctools.h
6 COMMON_H += ../common/ids.h ../common/tools.h ../common/decode_text.h \
7 ctools.h
7 8
8 9 CFLAGS += -I../common CFLAGS += -I../common
9 10
10 11 OBJS := decode.o ctools.o php.o process.o process_core.o process_misc.o \ OBJS := decode.o ctools.o php.o process.o process_core.o process_misc.o \
11 12 process_db.o process_ssl.o openssl.o gnutls.o text2process.o \ process_db.o process_ssl.o openssl.o gnutls.o text2process.o \
12 python.o \
13 ../common/tools.o
13 python.o curl.o \
14 ../common/tools.o ../common/info.o ../common/decode_text.o
14 15
15 16 decode.o: decode.c decode.h process_db.h $(COMMON_H) decode.o: decode.c decode.h process_db.h $(COMMON_H)
16 17 $(CC) $(CFLAGS) -fPIC -c -o $@ $< $(CC) $(CFLAGS) -fPIC -c -o $@ $<
 
... ... ctools.o: ctools.c $(COMMON_H) ../common/tools.h
21 22 php.o: php.c php.h process_db.h $(COMMON_H) php.o: php.c php.h process_db.h $(COMMON_H)
22 23 $(CC) $(CFLAGS) -fPIC -c -o $@ $< $(CC) $(CFLAGS) -fPIC -c -o $@ $<
23 24
25 curl.o: curl.c curl.h $(COMMON_H)
26 $(CC) $(CFLAGS) -fPIC -c -o $@ $<
27
24 28 python.o: python.c python.h process_db.h $(COMMON_H) python.o: python.c python.h process_db.h $(COMMON_H)
25 29 $(CC) $(CFLAGS) -fPIC -c -o $@ $< $(CC) $(CFLAGS) -fPIC -c -o $@ $<
26 30
 
... ... ninedogs_dlsym_env.so: ninedogs_dlsym_env.c
54 58 ninedogs_dlsym_func.so: ninedogs_dlsym_func.c ninedogs_dlsym_func.so: ninedogs_dlsym_func.c
55 59 $(CC) $(CFLAGSSO) -Wl,-soname,ninedogs_dlsym_func.so -o $@ $< $(CC) $(CFLAGSSO) -Wl,-soname,ninedogs_dlsym_func.so -o $@ $<
56 60
57 ninedogs.so: ninedogs.c $(OBJS) $(COMMON_H) ../common/shared.h
58 $(CC) $(CFLAGS) $(CFLAGSSO) -Wl,-soname,ninedogs.so -o $@ ninedogs.c $(OBJS) $(LIBS) $(GNUTLS_LIBS)
61 ninedogs.so: ninedogs.c $(OBJS) $(COMMON_H) ../common/shared.h curl.h
62 $(CC) $(CFLAGS) $(CFLAGSSO) -Wl,-soname,ninedogs.so -o $@ ninedogs.c \
63 $(OBJS) $(LIBS) $(GNUTLS_LIBS)
59 64
60 65
61 66 compile: ninedogs_dlsym_env.so ninedogs_dlsym_func.so ninedogs.so compile: ninedogs_dlsym_env.so ninedogs_dlsym_func.so ninedogs.so
File agent/ctools.c changed (mode: 100644) (index 74c4135..48835b7)
... ... char *stype(const int type)
100 100 } }
101 101 } }
102 102
103 char *sprotocol(const int protocol)
104 {
105 static char tmp[16];
106
107 switch (protocol) {
108 case IPPROTO_TCP: return "tcp";
109 case IPPROTO_UDP: return "udp";
110 default: snprintf(tmp, sizeof(tmp), "%d", protocol); return tmp;
111 }
112 }
113
114 103 /* /*
115 104 * Fills @out with domain/type/address/port string * Fills @out with domain/type/address/port string
116 105 */ */
File agent/ctools.h changed (mode: 100644) (index 0898a92..e93e17b)
... ... extern struct info fdinfo;
42 42
43 43 char *sdomain(const int domain); char *sdomain(const int domain);
44 44 char *stype(const int type); char *stype(const int type);
45 char *sprotocol(const int protocol);
46 45 void saddr(char *out, const size_t out_len, void saddr(char *out, const size_t out_len,
47 46 const struct sockaddr *sa); const struct sockaddr *sa);
48 47
File agent/curl.TODO added (mode: 100644) (index 0000000..bb2c060)
1 [ ] Decode slist
2 [ ] Call 'getinfo'; after perform to log details?
3 [ ] What about blobs?
4 [ ]
File agent/curl.c added (mode: 100644) (index 0000000..3dbb5c4)
1 #include <stdarg.h>
2
3 #include "curl.h"
4
5 extern void xlog(const unsigned int level, const char *format, ...);
6 extern void *ninedogs_dlsym(const char *sym);
7 extern void my_trace(const char *func, const char type, ...);
8
9
10 static const struct my_curl_easyoption *(*old_curl_easy_option_by_id)(CURLoption id);
11 const struct my_curl_easyoption *curl_easy_option_by_id(CURLoption id)
12 {
13 if (!old_curl_easy_option_by_id)
14 old_curl_easy_option_by_id = ninedogs_dlsym("curl_easy_option_by_id");
15
16 return old_curl_easy_option_by_id(id);
17 }
18
19 static CURL *(*old_curl_easy_init)(void);
20 CURL *curl_easy_init(void)
21 {
22 if (!old_curl_easy_init)
23 old_curl_easy_init = ninedogs_dlsym("curl_easy_init");
24
25 CURL *ret = old_curl_easy_init();
26 my_trace(__func__, 'R', ret);
27 xlog(100, "%s: ret=%p\n", __func__, ret);
28
29 return ret;
30 }
31
32 static CURLcode (*old_curl_easy_setopt)(CURL *handle, CURLoption option, ...);
33 CURLcode curl_easy_setopt(CURL *handle, CURLoption option, ...)
34 {
35 va_list va;
36 CURLcode ret;
37
38 if (!old_curl_easy_setopt)
39 old_curl_easy_setopt = ninedogs_dlsym("curl_easy_setopt");
40
41 const struct my_curl_easyoption *oi = curl_easy_option_by_id(option);
42 if (!oi)
43 return 43; // CURLE_BAD_FUNCTION_ARGUMENT
44
45 xlog(100, " DEBUG: option %d name=[%s] type=%d\n",
46 option, oi->name, oi->type);
47
48 va_start(va, option);
49 switch (oi->type) {
50 case 0: // long
51 case 2: // off_t
52 long a = va_arg(va, long);
53 ret = old_curl_easy_setopt(handle, option, a);
54 my_trace(__func__, 'R', handle, oi->type, oi->name, a, ret);
55 break;
56
57 case 1: // values
58 case 3: // object
59 case 4: // string
60 case 5: // slist
61 case 6: // cbptr
62 case 7: // blob
63 case 8: // function
64 default:
65 void *p = va_arg(va, void *);
66 ret = old_curl_easy_setopt(handle, option, p);
67 my_trace(__func__, 'R', handle, oi->type, oi->name, p, ret);
68 break;
69 }
70 va_end(va);
71 xlog(100, "%s: ret=%d\n", __func__, ret);
72
73 return ret;
74 }
75
76 static CURLcode (*old_curl_easy_perform)(CURL *handle);
77 CURLcode curl_easy_perform(CURL *handle)
78 {
79 if (!old_curl_easy_perform)
80 old_curl_easy_perform = ninedogs_dlsym("curl_easy_perform");
81
82 my_trace(__func__, 'c', handle);
83 CURLcode ret = old_curl_easy_perform(handle);
84 my_trace(__func__, 'r', handle, ret);
85 xlog(100, "%s: ret=%d\n", __func__, ret);
86
87 return ret;
88 }
89
90 static void (*old_curl_easy_cleanup)(CURL *handle);
91 void curl_easy_cleanup(CURL *handle)
92 {
93 if (!old_curl_easy_cleanup)
94 old_curl_easy_cleanup = ninedogs_dlsym("curl_easy_cleanup");
95
96 old_curl_easy_cleanup(handle);
97 my_trace(__func__, 'R', handle);
98 }
File agent/curl.h added (mode: 100644) (index 0000000..06fc52d)
1 typedef void CURL;
2 typedef int CURLcode;
3 typedef int CURLoption;
4
5 struct my_curl_easyoption
6 {
7 const char *name;
8 CURLoption id;
9 int type;
10 unsigned int flags;
11 int pad;
12 };
13
14 struct my_curl_slist
15 {
16 char *data;
17 struct my_curl_slist *next;
18 };
19
20 const struct my_curl_easyoption *curl_easy_option_by_id(CURLoption id);
21 CURL *curl_easy_init(void);
22 CURLcode curl_easy_setopt(CURL *handle, CURLoption option, ...);
23 CURLcode curl_easy_perform(CURL *handle);
24 void curl_easy_cleanup(CURL *handle);
25
File agent/ninedogs.TODO changed (mode: 100644) (index 02995cd..5a2fa57)
1 [ ] At a trace start, dump the file descriptors, else the trace is useless.
2 [ ]
1 3
2 4 Move from: Move from:
3 5 int ret = va_arg(va, int); int ret = va_arg(va, int);
File agent/ninedogs.c changed (mode: 100644) (index 7cbea49..a54b4da)
11 11 #define __USE_LARGEFILE64 #define __USE_LARGEFILE64
12 12 #define __USE_FILE_OFFSET64 #define __USE_FILE_OFFSET64
13 13
14 #include <sys/mman.h>
15 #include <sys/random.h>
16 #include <sys/socket.h>
17 #include <sys/stat.h>
18 #include <sys/time.h>
19 #include <sys/timerfd.h>
20 #include <sys/types.h>
21 #include <sys/un.h>
22
14 23 #include <signal.h> #include <signal.h>
15 24 #include <pthread.h> #include <pthread.h>
16 25 #include <stdarg.h> #include <stdarg.h>
 
21 30 #include <fcntl.h> #include <fcntl.h>
22 31 #include <string.h> #include <string.h>
23 32 #include <unistd.h> #include <unistd.h>
24 #include <sys/mman.h>
25 #include <sys/random.h>
26 #include <sys/stat.h>
27 #include <sys/time.h>
28 #include <sys/types.h>
29 33 #include <time.h> #include <time.h>
30 34 #include <errno.h> #include <errno.h>
31 35 #include <dirent.h> #include <dirent.h>
32 #include <asm/unistd.h>
33 36 #include <fcntl.h> #include <fcntl.h>
34 #include <sys/socket.h>
35 #include <sys/un.h>
36 37 #include <arpa/inet.h> #include <arpa/inet.h>
37 38 #include <netinet/in.h> #include <netinet/in.h>
38 39 #include <netinet/tcp.h> #include <netinet/tcp.h>
39 40 #include <poll.h> #include <poll.h>
40 41 #include <netdb.h> #include <netdb.h>
41 42 #include <ctype.h> #include <ctype.h>
42 #include <semaphore.h>
43 43 #include <execinfo.h> #include <execinfo.h>
44 44
45 45 #include "ninedogs.h" #include "ninedogs.h"
 
52 52 #include "process_db.h" #include "process_db.h"
53 53 #include "text2process.h" #include "text2process.h"
54 54 #include "shared.h" #include "shared.h"
55 #include "info.h"
56 #include "decode_text.h"
57 #include "curl.h"
55 58
56 59 #define FB_FLAGS_NETSOCK (1 << 0) #define FB_FLAGS_NETSOCK (1 << 0)
57 60 #define FB_FLAGS_COMM (1 << 1) // the fd is used to communicate with us #define FB_FLAGS_COMM (1 << 1) // the fd is used to communicate with us
 
... ... struct mem_node
65 68 }; };
66 69 static __thread struct mem_node *mem_hash[64]; static __thread struct mem_node *mem_hash[64];
67 70
68 #define FD_NODE_DEV_NINEDOGS 1
69 struct fd_node
70 {
71 int fd;
72 unsigned int flags;
73 struct fd_node *next;
74 int real_flags;
75 mode_t mode;
76 char path[PATH_MAX];
77 uint64_t read_ops, write_ops;
78 uint64_t read_errs, write_errs;
79 uint64_t read_bytes, write_bytes;
80 };
81 static __thread struct fd_node *fd_nodes[32]; // TODO must be shared, but we need locking
71 static struct fd_node *fd_nodes[32]; // TODO we need locking
82 72
83 73 #define DLOPEN_MAX_ENTRIES 512 #define DLOPEN_MAX_ENTRIES 512
84 74 struct dlopen_node struct dlopen_node
 
... ... static unsigned char my_malloc[20ULL * 65536ULL];
95 85 static unsigned long my_malloc_pos; static unsigned long my_malloc_pos;
96 86
97 87 static struct shared *shared; static struct shared *shared;
98 static char shared_inited;
88 static unsigned char shared_inited;
89 static struct nd_info_shared *nd_info;
90 static unsigned char nd_info_inited;
99 91 char trace_enabled = 1; char trace_enabled = 1;
100 92 static __thread unsigned short trace_depth; static __thread unsigned short trace_depth;
101 93
94 static time_t nd_proc_start;
102 95 static char ninedogs_inited; static char ninedogs_inited;
103 96 static void *(*old_realloc)(void *ptr, size_t size); static void *(*old_realloc)(void *ptr, size_t size);
104 97 void *(*old_malloc)(size_t size); void *(*old_malloc)(size_t size);
105 98 void (*old_free)(void *ptr); void (*old_free)(void *ptr);
106 static int (*old_bind)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
107 99 static int (*old_setsockopt)(int sockfd, int level, int optname, const void *optval, socklen_t optlen); static int (*old_setsockopt)(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
108 100 static int (*old_socket)(int domain, int type, int protocol); static int (*old_socket)(int domain, int type, int protocol);
109 101 static int (*old_close)(int fd); static int (*old_close)(int fd);
 
... ... static ssize_t (*old_recvfrom)(int sockfd, void *restrict buf, size_t len, int
117 109 struct sockaddr *restrict src_addr, socklen_t *restrict addrlen); struct sockaddr *restrict src_addr, socklen_t *restrict addrlen);
118 110 static int (*old_accept)(int sockfd, struct sockaddr *addr, socklen_t *addrlen); static int (*old_accept)(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
119 111 static int (*old_accept4)(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags); static int (*old_accept4)(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
120 static int (*old_connect)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
121 112 static int (*old_poll)(struct pollfd *fds, nfds_t nfds, int timeout); static int (*old_poll)(struct pollfd *fds, nfds_t nfds, int timeout);
122 113 static struct hostent *(*old_gethostbyname)(const char *name); static struct hostent *(*old_gethostbyname)(const char *name);
123 114 int (*old_getaddrinfo)(const char *restrict node, const char *restrict service, int (*old_getaddrinfo)(const char *restrict node, const char *restrict service,
 
... ... static struct fd_node *fd_add(const int fd)
191 182 } }
192 183
193 184 q->fd = fd; q->fd = fd;
194 q->flags = 0;
185 memset(q->stats, 0, sizeof(q->stats));
186
187 xlog(100, "%s: adding fd %d in q %p\n", __func__, fd, q);
195 188
196 189 return q; return q;
197 190 } }
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
451 444 if (ret == -1) if (ret == -1)
452 445 my_trace_put32(buf, &i, save_errno); my_trace_put32(buf, &i, save_errno);
453 446 } }
447 } else if (strcmp(func, "curl_easy_cleanup") == 0) {
448 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle
449 } else if (strcmp(func, "curl_easy_init") == 0) {
450 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle
451 } else if (strcmp(func, "curl_easy_perform") == 0) {
452 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle
453 if (type == 'r')
454 my_trace_put32(buf, &i, va_arg(va, int)); // ret
455 } else if (strcmp(func, "curl_easy_setopt") == 0) {
456 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle
457 uint8_t type = va_arg(va, int);
458 my_trace_put8(buf, &i, type);
459 char *option = va_arg(va, char *);
460 uint8_t option_len = strlen(option);
461 my_trace_put8(buf, &i, option_len);
462 my_trace_put(buf, &i, option, option_len);
463 if ((type == 0) || (type == 2)) {
464 my_trace_put64(buf, &i, va_arg(va, uint64_t));
465 } else if (type == 4) { // string
466 char *s = va_arg(va, char *);
467 xlog(1, " DEBUG: s=[%s]\n", s);
468 uint16_t len = strlen(s);
469 my_trace_put16(buf, &i, len);
470 my_trace_put(buf, &i, s, len);
471 } else if (type == 5) { // slist
472 struct my_curl_slist *q, *q0 = va_arg(va, struct my_curl_slist *);
473 q = q0;
474 while (q) {
475 uint16_t len = strlen(q->data);
476 my_trace_put16(buf, &i, len);
477 my_trace_put(buf, &i, q->data, len);
478 q = q->next;
479 }
480 my_trace_put16(buf, &i, 0);
481 } else {
482 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *));
483 }
484 my_trace_put32(buf, &i, va_arg(va, int)); // ret
454 485 } break; } break;
455 486
456 487 case 'd': case 'd':
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
611 642 my_trace_put32(buf, &i, ret); my_trace_put32(buf, &i, ret);
612 643 if (ret == -1) if (ret == -1)
613 644 my_trace_put32(buf, &i, save_errno); my_trace_put32(buf, &i, save_errno);
645 } else if (strcmp(func, "lseek") == 0) {
646 my_trace_put32(buf, &i, va_arg(va, int)); // fd
647 my_trace_put64(buf, &i, va_arg(va, uint64_t)); // off
648 my_trace_put32(buf, &i, va_arg(va, int)); // whence
649 if (type == 'r') {
650 ssize_t ret = va_arg(va, ssize_t);
651 my_trace_put64(buf, &i, ret);
652 if (ret == -1)
653 my_trace_put32(buf, &i, save_errno);
654 }
614 655 } break; } break;
615 656
616 657 case 'm': case 'm':
617 if (strcmp(func, "mysqli_autocommit") == 0) {
658 if (strcmp(func, "memfd_create") == 0) {
659 char *name = va_arg(va, char *);
660 unsigned short len = strlen(name);
661 my_trace_put16(buf, &i, len);
662 my_trace_put(buf, &i, name, len);
663 my_trace_put32(buf, &i, va_arg(va, unsigned int)); // flags
664 if (type == 'r') {
665 int ret = va_arg(va, int);
666 my_trace_put32(buf, &i, ret);
667 if (ret == -1)
668 my_trace_put32(buf, &i, save_errno);
669 }
670 } else if (strcmp(func, "mysqli_autocommit") == 0) {
618 671 struct db_autocommit *a = va_arg(va, struct db_autocommit *); struct db_autocommit *a = va_arg(va, struct db_autocommit *);
619 672 my_trace_put64(buf, &i, (uint64_t) a->link); my_trace_put64(buf, &i, (uint64_t) a->link);
620 673 my_trace_put_bool(buf, &i, a->value); my_trace_put_bool(buf, &i, a->value);
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
898 951 } break; } break;
899 952
900 953 case 'r': case 'r':
901 if (strcmp(func, "recv") == 0) {
954 if (strcmp(func, "read") == 0) {
955 void *buf2 = NULL;
956 my_trace_put32(buf, &i, va_arg(va, int)); // fd
957 if (type == 'r')
958 buf2 = va_arg(va, void *);
959 my_trace_put64(buf, &i, va_arg(va, size_t)); // count
960 if (type == 'r') {
961 ssize_t ret = va_arg(va, ssize_t);
962 my_trace_put64(buf, &i, ret);
963 if (ret > 0) {
964 unsigned short max = ret;
965 if (max > 128)
966 max = 128;
967 my_trace_put16(buf, &i, max);
968 my_trace_put(buf, &i, buf2, max); // data
969 }
970 if (ret == -1)
971 my_trace_put32(buf, &i, save_errno);
972 }
973 } else if (strcmp(func, "recv") == 0) {
902 974 void *buf2 = NULL; void *buf2 = NULL;
903 975 my_trace_put32(buf, &i, va_arg(va, int)); // sock my_trace_put32(buf, &i, va_arg(va, int)); // sock
904 976 if (type == 'r') if (type == 'r')
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
1100 1172 my_trace_put(buf, &i, str, len); my_trace_put(buf, &i, str, len);
1101 1173 } break; } break;
1102 1174
1175 case 't':
1176 if (strcmp(func, "timerfd_create") == 0) {
1177 my_trace_put32(buf, &i, va_arg(va, int)); // clockid
1178 my_trace_put32(buf, &i, va_arg(va, int)); // flags
1179 if (type == 'r') {
1180 int ret = va_arg(va, int);
1181 my_trace_put32(buf, &i, ret);
1182 if (ret == -1)
1183 my_trace_put32(buf, &i, save_errno);
1184 }
1185 } break;
1186
1103 1187 case 'u': case 'u':
1104 1188 if (strcmp(func, "unlink") == 0) { if (strcmp(func, "unlink") == 0) {
1105 1189 char *pathname = va_arg(va, char *); char *pathname = va_arg(va, char *);
 
... ... void my_trace(const char *func, const char type, ...)
1153 1237 va_list va; va_list va;
1154 1238 int locked, r; int locked, r;
1155 1239
1240 save_errno = errno;
1241
1242 if (nd_info_inited && nd_info->do_fill_buffer == 1) {
1243 unsigned int size, off = 0;
1244 int r = sem_wait(&nd_info->sem); // TODO: check error code
1245 nd_info->do_fill_buffer = 0;
1246
1247 uint32_t u32 = htobe32(nd_proc_start);
1248 nd_info->buf[off++] = 'S';
1249 memcpy(nd_info->buf + off, &u32, 4); off += 4;
1250
1251 size = export_fd_nodes(nd_info->buf + off,
1252 sizeof(nd_info->buf) - off, fd_nodes, 32);
1253 off += size;
1254
1255 nd_info->buf_size = off;
1256 nd_info->buffer_is_filled = 1;
1257 r = sem_post(&nd_info->sem); // TODO: check error code
1258 }
1259
1156 1260 if (shared_inited == 0) if (shared_inited == 0)
1157 1261 return; return;
1158 1262
1159 1263 if (trace_enabled == 0) if (trace_enabled == 0)
1160 1264 return; return;
1161 1265
1162 save_errno = errno;
1163
1164 1266 xlog(200, "%s func=%s type=%c errno=%d\n", xlog(200, "%s func=%s type=%c errno=%d\n",
1165 1267 __func__, func, type, errno); __func__, func, type, errno);
1166 1268
 
... ... __attribute__((destructor)) void ninedogs_fini(void)
1333 1435 { {
1334 1436 xlog(20, "%s\n", __func__); xlog(20, "%s\n", __func__);
1335 1437 //my_trace("-dest", "r"); //my_trace("-dest", "r");
1438
1336 1439 if (shared_inited) { if (shared_inited) {
1337 char name[128];
1440 char name[32];
1338 1441 snprintf(name, sizeof(name), "ninedogs-%d", getpid()); snprintf(name, sizeof(name), "ninedogs-%d", getpid());
1339 1442 shm_unlink(name); shm_unlink(name);
1340 // TODO: should we munmap?
1443 // TODO munmap(shared, sizeof(struct shared));
1444 }
1445
1446 if (nd_info_inited) {
1447 char name[48];
1448 snprintf(name, sizeof(name), "ninedogs-info-%d", getpid());
1449 shm_unlink(name);
1450 // TODO munmap(nd_info, sizeof(struct nd_info_shared));
1341 1451 } }
1342 1452 } }
1343 1453
 
... ... __attribute__((constructor)) void ninedogs_init(void)
1369 1479 if (ninedogs_inited == 1) if (ninedogs_inited == 1)
1370 1480 return; return;
1371 1481
1482 nd_proc_start = time(NULL);
1483
1372 1484 //write(1, "ninedogs: init start\n", 21); //write(1, "ninedogs: init start\n", 21);
1373 1485 dlh = dlmopen(LM_ID_BASE, "/usr/lib64/ninedogs_dlsym_env.so", dlh = dlmopen(LM_ID_BASE, "/usr/lib64/ninedogs_dlsym_env.so",
1374 1486 RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND); RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);
 
... ... __attribute__((constructor)) void ninedogs_init(void)
1442 1554 exit(1); exit(1);
1443 1555 } }
1444 1556
1445 old_bind = old_dlsym(RTLD_NEXT, "bind");
1446 if (old_bind == NULL) {
1447 xlog(0, " cannot resolve 'bind'!\n");
1448 exit(1);
1449 }
1450
1451 1557 old_setsockopt = old_dlsym(RTLD_NEXT, "setsockopt"); old_setsockopt = old_dlsym(RTLD_NEXT, "setsockopt");
1452 1558 if (old_setsockopt == NULL) { if (old_setsockopt == NULL) {
1453 1559 xlog(0, " cannot resolve 'setsockopt'!\n"); xlog(0, " cannot resolve 'setsockopt'!\n");
 
... ... __attribute__((constructor)) void ninedogs_init(void)
1514 1620 exit(1); exit(1);
1515 1621 } }
1516 1622
1517 old_connect = old_dlsym(RTLD_NEXT, "connect");
1518 if (old_connect == NULL) {
1519 xlog(0, " cannot resolve 'connect'!\n");
1520 exit(1);
1521 }
1522
1523 1623 old_poll = old_dlsym(RTLD_NEXT, "poll"); old_poll = old_dlsym(RTLD_NEXT, "poll");
1524 1624 if (old_poll == NULL) { if (old_poll == NULL) {
1525 1625 xlog(0, " cannot resolve 'poll'!\n"); xlog(0, " cannot resolve 'poll'!\n");
 
... ... __attribute__((constructor)) void ninedogs_init(void)
1683 1783 } }
1684 1784 xlog(200, "%s: tracing mmap=%p\n", __func__, shared); xlog(200, "%s: tracing mmap=%p\n", __func__, shared);
1685 1785
1686 if (sem_init(&shared->sem1, 1, 1) == -1) {
1786 if (sem_init(&shared->sem1, 1, 0 /* locked */) == -1) {
1687 1787 xlog(0, "Cannot do sem_init sem1: %m\n"); xlog(0, "Cannot do sem_init sem1: %m\n");
1688 1788 break; break;
1689 1789 } }
 
... ... __attribute__((constructor)) void ninedogs_init(void)
1694 1794 // We want force from start start the wrap around // We want force from start start the wrap around
1695 1795 shared->tail = shared->head = shared->buf_size - 1; shared->tail = shared->head = shared->buf_size - 1;
1696 1796
1797 if (sem_post(&shared->sem1) == -1) {
1798 xlog(0, "Cannot do sem_post sem1: %m\n");
1799 break;
1800 }
1801
1697 1802 shared_inited = 1; shared_inited = 1;
1698 1803 } while (0); } while (0);
1699 1804
1805 // Preparing the nd-info support
1806 do {
1807 char name[48];
1808 snprintf(name, sizeof(name), "/ninedogs-info-%d", getpid());
1809 int shm = shm_open(name, O_RDWR | O_CREAT | O_EXCL,
1810 S_IRUSR | S_IWUSR);
1811 if (shm == -1) {
1812 xlog(0, "Cannot create shm: %m\n");
1813 break;
1814 }
1815
1816 if (ftruncate(shm, sizeof(struct nd_info_shared)) == -1) {
1817 xlog(0, "Cannot do ftruncate: %m\n");
1818 break;
1819 }
1820
1821 nd_info = mmap(NULL, sizeof(struct shared),
1822 PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
1823 if (nd_info == MAP_FAILED) {
1824 xlog(0, "Cannot do mmap for info: %m\n");
1825 break;
1826 }
1827 xlog(200, "%s: info mmap=%p\n", __func__, nd_info);
1828
1829 if (sem_init(&nd_info->sem, 1, 0 /* locked */) == -1) {
1830 xlog(0, "Cannot do sem_init info sem: %m\n");
1831 break;
1832 }
1833
1834 nd_info->version = 1;
1835 nd_info->do_fill_buffer = 0;
1836 nd_info->buffer_is_filled = 0;
1837
1838 if (sem_post(&nd_info->sem) == -1) {
1839 xlog(0, "Cannot do sem_post sem: %m\n");
1840 break;
1841 }
1842
1843 nd_info_inited = 1;
1844 } while (0);
1845
1700 1846 ninedogs_inited = 1; ninedogs_inited = 1;
1701 1847 //xlog(1, " init ended.\n"); //xlog(1, " init ended.\n");
1702 1848 //write(1, "ninedogs: init done\n", 20); //write(1, "ninedogs: init done\n", 20);
 
... ... void *reallocarray(void *ptr, size_t nmemb, size_t size)
1866 2012 } }
1867 2013 #endif #endif
1868 2014
2015 static int (*old_bind)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
1869 2016 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
1870 2017 { {
1871 struct node *q;
1872 struct sockaddr_storage new;
1873 char tmp[128];
1874 int ret;
1875
1876 2018 if (!old_bind) if (!old_bind)
1877 return -1;
1878
1879 saddr(tmp, sizeof(tmp), (struct sockaddr *) addr);
1880 xlog(100, "bind(sockfd=%d, %s)\n", sockfd, tmp);
1881
1882 memcpy(&new, addr, addrlen);
2019 old_bind = ninedogs_dlsym("bind");
1883 2020
1884 /* We do not touch non network sockets */
1885 q = get(sockfd);
1886 do {
1887 if (q == NULL)
1888 break;
2021 xlog(100, "bind(sockfd=%d)\n", sockfd);
1889 2022
1890 if ((q->priv.flags & FB_FLAGS_NETSOCK) == 0)
1891 break;
1892
1893 //q->priv.flags |= FB_FLAGS_BIND_CALLED;
1894 } while (0);
2023 int ret = old_bind(sockfd, addr, addrlen);
2024 my_trace(__func__, 'R', sockfd, addr, addrlen, ret);
1895 2025
1896 ret = old_bind(sockfd, (struct sockaddr *) &new, addrlen);
1897 my_trace(__func__, 'R', sockfd, &new, addrlen, ret);
2026 if (ret == 0) {
2027 struct fd_node *q = fd_search(sockfd);
2028 if (q) {
2029 memcpy(&q->socket.bind, addr, addrlen);
2030 q->socket.bind_len = addrlen;
2031 }
2032 }
1898 2033
1899 2034 return ret; return ret;
1900 2035 } }
 
... ... int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
1902 2037 int setsockopt(int sockfd, int level, int optname, const void *optval, int setsockopt(int sockfd, int level, int optname, const void *optval,
1903 2038 socklen_t optlen) socklen_t optlen)
1904 2039 { {
1905 int ret;
1906
1907 #if 0
1908 if (level == SOL_SOCKET) {
1909 if (optname == SO_KEEPALIVE)
1910 return 1; //set_ka(sockfd);
1911 if (optname == SO_REUSEADDR)
1912 return 1; //set_reuseaddr(sockfd);
1913 if (optname == SO_MARK)
1914 return 1; //set_fwmark(sockfd);
1915 if (optname == SO_PRIORITY)
1916 return 1; //set_prio(sockfd);
1917 }
1918
1919 if (level == IPPROTO_IP) {
1920 if (optname == IP_TOS)
1921 return 1; //set_tos(sockfd);
1922 if (optname == IP_TTL)
1923 return 1; //set_ttl(sockfd);
1924 }
1925
1926 if (level == IPPROTO_TCP) {
1927 if (optname == TCP_KEEPIDLE)
1928 return 1; //set_ka_idle(sockfd);
1929 if (optname == TCP_MAXSEG)
1930 return 1; //set_mss(sockfd);
1931 if (optname == TCP_NODELAY)
1932 return 1; //set_nodelay(sockfd);
1933 }
1934 #endif
1935
1936 2040 my_trace(__func__, 'c', sockfd, level, optname, optlen, optval); my_trace(__func__, 'c', sockfd, level, optname, optlen, optval);
1937 ret = old_setsockopt(sockfd, level, optname, optval, optlen);
2041 int ret = old_setsockopt(sockfd, level, optname, optval, optlen);
1938 2042 my_trace(__func__, 'r', sockfd, ret); my_trace(__func__, 'r', sockfd, ret);
1939 2043
1940 2044 return ret; return ret;
1941 2045 } }
1942 2046
1943 /*
1944 * Helper called when a socket is created: socket, accept
1945 */
1946 static void socket_create_callback(const int sockfd, int domain, int type)
1947 {
1948 struct private p;
1949
1950 xlog(60, " socket_create_callback(%d, %s, %s)\n",
1951 sockfd, sdomain(domain), stype(type));
1952
1953 p.domain = domain;
1954 p.type = type;
1955 p.flags = FB_FLAGS_NETSOCK;
1956 memset(&p.dest, 0, sizeof(struct sockaddr_storage));
1957 p.dest_len = 0;
1958 p.limit = 0;
1959 p.rest = 0;
1960 p.last.tv_sec = p.last.tv_usec = 0;
1961 add(sockfd, &p);
1962 }
1963
1964 2047 int socket(int domain, int type, int protocol) int socket(int domain, int type, int protocol)
1965 2048 { {
1966 int sockfd;
1967
2049 char sprotocol[16];
2050 nd_decode_socket_protocol(sprotocol, sizeof(sprotocol), protocol);
1968 2051 xlog(100, "socket(domain=%s[%d], type=%s, protocol=%s)\n", xlog(100, "socket(domain=%s[%d], type=%s, protocol=%s)\n",
1969 sdomain(domain), domain, stype(type), sprotocol(protocol));
2052 sdomain(domain), domain, stype(type), sprotocol);
1970 2053
1971 sockfd = old_socket(domain, type, protocol);
1972 //if (sockfd != -1)
1973 // socket_create_callback(sockfd, domain, type);
2054 int sockfd = old_socket(domain, type, protocol);
1974 2055 my_trace(__func__, 'R', domain, type, protocol, sockfd); my_trace(__func__, 'R', domain, type, protocol, sockfd);
1975 2056
2057 struct fd_node *q = fd_add(sockfd);
2058 if (q) {
2059 q->type = FD_NODE_SOCKET;
2060 q->socket.domain = domain;
2061 q->socket.type = type;
2062 q->socket.protocol = protocol;
2063 q->socket.backlog = 0;
2064 q->socket.accepts = 0;
2065 }
2066
1976 2067 return sockfd; return sockfd;
1977 2068 } }
1978 2069
1979 2070 int close(int fd) int close(int fd)
1980 2071 { {
1981 int ret;
1982
1983 2072 if (!old_close) if (!old_close)
1984 return 0;
2073 old_close = ninedogs_dlsym("close");
1985 2074
1986 //xlog(1, "close(fd=%d)\n", fd);
1987
1988 //del(fd);
1989 2075 fd_del(fd); fd_del(fd);
1990 2076
1991 2077 my_trace(__func__, 'c', fd); my_trace(__func__, 'c', fd);
1992 ret = old_close(fd);
2078 int ret = old_close(fd);
1993 2079 my_trace(__func__, 'r', fd, ret); my_trace(__func__, 'r', fd, ret);
1994 2080
1995 2081 return ret; return ret;
 
... ... static void write_common_post(struct fd_node *q, ssize_t ret)
2000 2086 if (!q) if (!q)
2001 2087 return; return;
2002 2088
2003 q->write_ops++;
2089 q->stats[0][1]++;
2004 2090 if (ret == -1) if (ret == -1)
2005 q->write_errs++;
2091 q->stats[2][1]++;
2006 2092 else else
2007 q->write_bytes += ret;
2093 q->stats[1][1] += ret;
2008 2094 } }
2009 2095
2010 2096 ssize_t write(int fd, const void *buf, size_t count) ssize_t write(int fd, const void *buf, size_t count)
2011 2097 { {
2012 ssize_t ret;
2013
2014 2098 struct fd_node *q = fd_search(fd); struct fd_node *q = fd_search(fd);
2015 2099 if (q) { if (q) {
2016 if (q->flags & FD_NODE_DEV_NINEDOGS) {
2100 if (q->type == FD_NODE_DEV_NINEDOGS) {
2017 2101 text2process(buf, count); text2process(buf, count);
2018 2102 return count; return count;
2019 2103 } }
 
... ... ssize_t write(int fd, const void *buf, size_t count)
2025 2109 dump(200, "write", buf, count); dump(200, "write", buf, count);
2026 2110
2027 2111 my_trace(__func__, 'c', fd, buf, count); my_trace(__func__, 'c', fd, buf, count);
2028 ret = old_write(fd, buf, count);
2112 ssize_t ret = old_write(fd, buf, count);
2029 2113 my_trace(__func__, 'r', fd, count, ret); my_trace(__func__, 'r', fd, count, ret);
2030 2114
2031 2115 write_common_post(q, ret); write_common_post(q, ret);
2116 if (q && (ret > 0))
2117 q->file.off += ret;
2032 2118
2033 2119 return ret; return ret;
2034 2120 } }
2035 2121
2036 2122 ssize_t send(int sockfd, const void *buf, size_t len, int flags) ssize_t send(int sockfd, const void *buf, size_t len, int flags)
2037 2123 { {
2038 ssize_t ret;
2039
2040 2124 xlog(110, "%s(sockfd=%d, buf, len=%zu, flags=0x%x)\n", xlog(110, "%s(sockfd=%d, buf, len=%zu, flags=0x%x)\n",
2041 2125 __func__, sockfd, len, flags); __func__, sockfd, len, flags);
2042 2126
2043 2127 struct fd_node *q = fd_search(sockfd); struct fd_node *q = fd_search(sockfd);
2044 2128
2045 2129 my_trace(__func__, 'c', sockfd, buf, len, flags); my_trace(__func__, 'c', sockfd, buf, len, flags);
2046 ret = old_send(sockfd, buf, len, flags);
2130 ssize_t ret = old_send(sockfd, buf, len, flags);
2047 2131 my_trace(__func__, 'r', sockfd, len, flags, ret); my_trace(__func__, 'r', sockfd, len, flags, ret);
2048 2132
2049 2133 write_common_post(q, ret); write_common_post(q, ret);
 
... ... ssize_t send(int sockfd, const void *buf, size_t len, int flags)
2054 2138 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
2055 2139 const struct sockaddr *dest_addr, socklen_t addrlen) const struct sockaddr *dest_addr, socklen_t addrlen)
2056 2140 { {
2057 ssize_t ret;
2058
2059 2141 xlog(110, "sendto(sockfd, %d, buf, len=%zu, flags=0x%x, ...)\n", xlog(110, "sendto(sockfd, %d, buf, len=%zu, flags=0x%x, ...)\n",
2060 2142 sockfd, len, flags); sockfd, len, flags);
2061 2143
2062 2144 struct fd_node *q = fd_search(sockfd); struct fd_node *q = fd_search(sockfd);
2063 2145
2064 2146 my_trace(__func__, 'c', sockfd, buf, len, flags, dest_addr, addrlen); my_trace(__func__, 'c', sockfd, buf, len, flags, dest_addr, addrlen);
2065 ret = old_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
2147 ssize_t ret = old_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
2066 2148 my_trace(__func__, 'r', sockfd, len, flags, ret); my_trace(__func__, 'r', sockfd, len, flags, ret);
2067 2149
2068 2150 write_common_post(q, ret); write_common_post(q, ret);
 
... ... ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
2075 2157 */ */
2076 2158 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)
2077 2159 { {
2078 ssize_t ret;
2079 /* see below
2080 struct sockaddr_storage new_dest;
2081 */
2082
2083 2160 xlog(100, "sendmsg(sockfd=%d, ..., flags=0x%x)\n", xlog(100, "sendmsg(sockfd=%d, ..., flags=0x%x)\n",
2084 2161 sockfd, flags); sockfd, flags);
2085 2162
 
... ... ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)
2090 2167 dump(200, "sendmsg", msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len); dump(200, "sendmsg", msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
2091 2168
2092 2169 my_trace(__func__, 'c', sockfd, msg, flags); my_trace(__func__, 'c', sockfd, msg, flags);
2093 ret = old_sendmsg(sockfd, msg, flags);
2094 xlog(101, " returned %zd\n", ret);
2170 ssize_t ret = old_sendmsg(sockfd, msg, flags);
2095 2171 my_trace(__func__, 'r', sockfd, flags, ret); my_trace(__func__, 'r', sockfd, flags, ret);
2096 2172
2097 2173 write_common_post(q, ret); write_common_post(q, ret);
 
... ... ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)
2099 2175 return ret; return ret;
2100 2176 } }
2101 2177
2178 // TODO: trace
2179 ssize_t (*old_lseek)(int fd, off_t off, int whence);
2180 ssize_t lseek(int fd, off_t off, int whence)
2181 {
2182 xlog(110, "%s(fd=%d, off=%zu, whence=%d)\n", __func__, fd, off, whence);
2183
2184 if (!old_lseek)
2185 old_lseek = ninedogs_dlsym("lseek");
2186
2187 struct fd_node *q = fd_search(fd);
2188
2189 my_trace(__func__, 'c', fd, off, whence);
2190 ssize_t ret = old_lseek(fd, off, whence);
2191 my_trace(__func__, 'r', fd, off, whence, ret);
2192
2193 if (q && (ret > 0))
2194 q->file.off = ret;
2195
2196 return ret;
2197 }
2198
2199
2102 2200 static void read_common_post(struct fd_node *q, ssize_t ret) static void read_common_post(struct fd_node *q, ssize_t ret)
2103 2201 { {
2104 2202 if (!q) if (!q)
2105 2203 return; return;
2106 2204
2107 q->read_ops++;
2205 q->stats[0][0]++;
2108 2206 if (ret == -1) if (ret == -1)
2109 q->read_errs++;
2207 q->stats[2][0]++;
2110 2208 else else
2111 q->read_bytes += ret;
2209 q->stats[1][0] += ret;
2210 }
2211
2212 ssize_t (*old_read)(int fd, void *buf, size_t count);
2213 ssize_t read(int fd, void *buf, size_t count)
2214 {
2215 xlog(110, "%s(fd=%d, buf, count=%zu)\n", __func__, fd, count);
2216
2217 if (!old_read)
2218 old_read = ninedogs_dlsym("read");
2219
2220 struct fd_node *q = fd_search(fd);
2221
2222 my_trace(__func__, 'c', fd, count);
2223 ssize_t ret = old_read(fd, buf, count);
2224 my_trace(__func__, 'r', fd, buf, count, ret);
2225
2226 read_common_post(q, ret);
2227 if (q && (ret > 0))
2228 q->file.off += ret;
2229
2230 return ret;
2112 2231 } }
2113 2232
2114 2233 ssize_t recv(int sockfd, void *buf, size_t len, int flags) ssize_t recv(int sockfd, void *buf, size_t len, int flags)
 
... ... ssize_t recvfrom(int sockfd, void *restrict buf, size_t len, int flags,
2166 2285 return ret; return ret;
2167 2286 } }
2168 2287
2288 static void accept_common(int sock, int new)
2289 {
2290 struct fd_node *a, *b;
2291
2292 a = fd_search(sock);
2293 if (a)
2294 a->socket.accepts++;
2295
2296 if (new == -1)
2297 return;
2298
2299 b = fd_add(new);
2300 if (b) {
2301 b->type = FD_NODE_SOCKET;
2302 b->socket.backlog = 0;
2303 b->socket.accepts = 0;
2304 }
2305
2306 if (a && b) {
2307 b->socket.domain = a->socket.domain;
2308 b->socket.type = a->socket.type;
2309 b->socket.protocol = a->socket.protocol;
2310 }
2311 }
2312
2169 2313 /* /*
2170 2314 * We have to hijack accept because the program may be a daemon. * We have to hijack accept because the program may be a daemon.
2171 2315 */ */
2172 2316 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
2173 2317 { {
2174 int new_sock;
2175 struct node *q;
2176 struct private *p;
2177
2178 2318 xlog(100, "accept(sockfd=%d, ...)\n", sockfd); xlog(100, "accept(sockfd=%d, ...)\n", sockfd);
2179 2319
2180 2320 my_trace(__func__, 'c', sockfd, addrlen ? *addrlen : 0); my_trace(__func__, 'c', sockfd, addrlen ? *addrlen : 0);
2181 new_sock = old_accept(sockfd, addr, addrlen);
2182 if (new_sock != -1) {
2183 /* We must find out domain and type for accepting socket */
2184 q = get(sockfd);
2185 if (q != NULL) {
2186 p = &q->priv;
2187
2188 socket_create_callback(new_sock, p->domain, p->type);
2189 }
2190 }
2321 int new_sock = old_accept(sockfd, addr, addrlen);
2191 2322 my_trace(__func__, 'r', sockfd, addr, addrlen ? *addrlen : 0, new_sock); my_trace(__func__, 'r', sockfd, addr, addrlen ? *addrlen : 0, new_sock);
2192
2323 accept_common(sockfd, new_sock);
2193 2324 return new_sock; return new_sock;
2194 2325 } }
2195 2326
 
... ... int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
2198 2329 */ */
2199 2330 int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
2200 2331 { {
2201 int new_sock;
2202 struct node *q;
2203 struct private *p;
2204
2205 2332 xlog(100, "accept4(sockfd=%d, ...flags=0x%x)\n", sockfd, flags); xlog(100, "accept4(sockfd=%d, ...flags=0x%x)\n", sockfd, flags);
2206 2333
2207 2334 my_trace(__func__, 'c', sockfd, addrlen ? *addrlen : 0, flags); my_trace(__func__, 'c', sockfd, addrlen ? *addrlen : 0, flags);
2208 new_sock = old_accept4(sockfd, addr, addrlen, flags);
2209 if (new_sock != -1) {
2210 /* We must find out domain and type for accepting socket */
2211 q = get(sockfd);
2212 if (q != NULL) {
2213 p = &q->priv;
2214
2215 socket_create_callback(new_sock, p->domain, p->type);
2216 }
2217 }
2335 int new_sock = old_accept4(sockfd, addr, addrlen, flags);
2218 2336 my_trace(__func__, 'r', sockfd, addr, addrlen ? *addrlen : 0, my_trace(__func__, 'r', sockfd, addr, addrlen ? *addrlen : 0,
2219 2337 flags, new_sock); flags, new_sock);
2220
2338 accept_common(sockfd, new_sock);
2221 2339 return new_sock; return new_sock;
2222 2340 } }
2223 2341
2342 static int (*old_connect)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
2224 2343 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
2225 2344 { {
2226 //struct node *q;
2227 int ret;
2228 char sdest[128];
2345 if (!old_connect)
2346 old_connect = ninedogs_dlsym("connect");
2229 2347
2230 saddr(sdest, sizeof(sdest), addr);
2231 xlog(100, "connect(sockfd=%d, %s)\n", sockfd, sdest);
2232
2233 // TODO
2234 //q = get(sockfd);
2235 //if (q)
2236 // gettimeofday(&q->priv.conn_time, NULL);
2348 xlog(100, "connect(sockfd=%d)\n", sockfd);
2237 2349
2238 2350 my_trace(__func__, 'c', sockfd, addr, addrlen); my_trace(__func__, 'c', sockfd, addr, addrlen);
2239 ret = old_connect(sockfd, addr, addrlen);
2240 if (ret == 0) {
2241 //struct timeval e, f;
2242
2243 //gettimeofday(&e, NULL);
2244 //my_time_diff(&f, &e, &q->priv.conn_time);
2245 //xlog(100, " took %u.%03u\n", f.tv_sec, f.tv_usec / 1000);
2351 int ret = old_connect(sockfd, addr, addrlen);
2352 my_trace(__func__, 'r', sockfd, ret);
2353 if ((ret == 0) || (errno == EAGAIN) || (errno == EINPROGRESS)) {
2354 struct fd_node *q = fd_search(sockfd);
2355 if (q) {
2356 memcpy(&q->socket.peer, addr, addrlen);
2357 q->socket.peer_len = addrlen;
2358 }
2246 2359 } else { } else {
2247 2360 xlog(100, " failed: %m\n"); xlog(100, " failed: %m\n");
2248 2361 } }
2249 my_trace(__func__, 'r', sockfd, ret);
2250 2362
2251 2363 return ret; return ret;
2252 2364 } }
2253 2365
2254 2366 int poll(struct pollfd *fds, nfds_t nfds, int timeout) int poll(struct pollfd *fds, nfds_t nfds, int timeout)
2255 2367 { {
2256 int ret;
2257
2258 2368 xlog(100, "poll(fds, %d, %d)\n", nfds, timeout); xlog(100, "poll(fds, %d, %d)\n", nfds, timeout);
2259 2369
2260 2370 my_trace(__func__, 'c', fds, nfds, timeout); my_trace(__func__, 'c', fds, nfds, timeout);
2261 ret = old_poll(fds, nfds, timeout);
2371 int ret = old_poll(fds, nfds, timeout);
2262 2372 my_trace(__func__, 'r', fds, nfds, timeout, ret); my_trace(__func__, 'r', fds, nfds, timeout, ret);
2263 2373
2264 2374 return ret; return ret;
 
... ... int poll(struct pollfd *fds, nfds_t nfds, int timeout)
2266 2376
2267 2377 struct hostent *gethostbyname(const char *name) struct hostent *gethostbyname(const char *name)
2268 2378 { {
2269 struct hostent *ret;
2270
2271 2379 xlog(100, "gethostbyname(%s)\n", name); xlog(100, "gethostbyname(%s)\n", name);
2272 2380
2273 2381 my_trace(__func__, 'c', name); my_trace(__func__, 'c', name);
2274 ret = old_gethostbyname(name);
2382 struct hostent *ret = old_gethostbyname(name);
2275 2383 my_trace(__func__, 'r', name, ret); my_trace(__func__, 'r', name, ret);
2276 2384
2277 2385 return ret; return ret;
 
... ... int gethostbyname_r(const char *name, struct hostent *restrict ret,
2286 2394 struct hostent **restrict result, struct hostent **restrict result,
2287 2395 int *restrict h_errnop) int *restrict h_errnop)
2288 2396 { {
2289 int r;
2290
2291 2397 if (!old_gethostbyname_r) if (!old_gethostbyname_r)
2292 2398 old_gethostbyname_r = ninedogs_dlsym("gethostbyname_r"); old_gethostbyname_r = ninedogs_dlsym("gethostbyname_r");
2293 2399
2294 2400 xlog(100, "gethostbyname_r('%s', buflen=%zu)\n", name, buflen); xlog(100, "gethostbyname_r('%s', buflen=%zu)\n", name, buflen);
2295 2401 my_trace(__func__, 'c', name); my_trace(__func__, 'c', name);
2296 r = old_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
2402 int r = old_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
2297 2403 xlog(100, "gethostbyname_r('%s', buflen=%zu) = %d h_errno=%d *result=%p\n", xlog(100, "gethostbyname_r('%s', buflen=%zu) = %d h_errno=%d *result=%p\n",
2298 2404 name, buflen, r, *h_errnop, result ? *result : NULL); name, buflen, r, *h_errnop, result ? *result : NULL);
2299 2405 my_trace(__func__, 'r', name, r, *h_errnop, *result); my_trace(__func__, 'r', name, r, *h_errnop, *result);
 
... ... int gethostbyname_r(const char *name, struct hostent *restrict ret,
2304 2410 int getaddrinfo(const char *restrict node, const char *restrict service, int getaddrinfo(const char *restrict node, const char *restrict service,
2305 2411 const struct addrinfo *restrict hints, struct addrinfo **restrict res) const struct addrinfo *restrict hints, struct addrinfo **restrict res)
2306 2412 { {
2307 int ret;
2308
2309 2413 xlog(100, "getaddrinfo(node=%s, service=%s, hints=0x%x)\n", xlog(100, "getaddrinfo(node=%s, service=%s, hints=0x%x)\n",
2310 2414 node, service, hints ? hints : 0); node, service, hints ? hints : 0);
2311 2415
2312 2416 my_trace(__func__, 'c', node, service, hints); my_trace(__func__, 'c', node, service, hints);
2313 ret = old_getaddrinfo(node, service, hints, res);
2417 int ret = old_getaddrinfo(node, service, hints, res);
2314 2418 my_trace(__func__, 'r', node, service, hints, res, ret); my_trace(__func__, 'r', node, service, hints, res, ret);
2315 2419
2316 2420 return ret; return ret;
 
... ... int pthread_create(pthread_t *restrict thread,
2320 2424 const pthread_attr_t *restrict attr, void *(*start_routine)(void *), const pthread_attr_t *restrict attr, void *(*start_routine)(void *),
2321 2425 void *restrict arg) void *restrict arg)
2322 2426 { {
2323 int ret;
2324
2325 2427 //xlog(2, "%s\n", __func__); //xlog(2, "%s\n", __func__);
2326 ret = old_pthread_create(thread, attr, start_routine, arg);
2428 int ret = old_pthread_create(thread, attr, start_routine, arg);
2327 2429 my_trace(__func__, 'R', ret == 0 ? *thread : 0, attr, arg, ret); my_trace(__func__, 'R', ret == 0 ? *thread : 0, attr, arg, ret);
2328 2430
2329 2431 return ret; return ret;
 
... ... int pthread_create(pthread_t *restrict thread,
2332 2434 // TODO: trace // TODO: trace
2333 2435 int pthread_join(pthread_t thread, void **retval) int pthread_join(pthread_t thread, void **retval)
2334 2436 { {
2335 int ret;
2336
2337 2437 if (!old_pthread_join) if (!old_pthread_join)
2338 2438 old_pthread_join = ninedogs_dlsym("pthread_join"); old_pthread_join = ninedogs_dlsym("pthread_join");
2339 2439
2340 2440 //xlog(2, "pthread_join\n"); //xlog(2, "pthread_join\n");
2341 ret = old_pthread_join(thread, retval);
2441 int ret = old_pthread_join(thread, retval);
2342 2442 my_trace(__func__, 'R', thread, ret, ret == 0 ? retval : NULL); my_trace(__func__, 'R', thread, ret, ret == 0 ? retval : NULL);
2343 2443
2344 2444 return ret; return ret;
 
... ... int pthread_join(pthread_t thread, void **retval)
2347 2447 #if 0 #if 0
2348 2448 int pthread_attr_init(pthread_attr_t *attr) int pthread_attr_init(pthread_attr_t *attr)
2349 2449 { {
2350 int ret;
2351
2352 2450 if (!old_pthread_attr_init) if (!old_pthread_attr_init)
2353 2451 old_pthread_attr_init = ninedogs_dlsym("pthread_attr_init"); old_pthread_attr_init = ninedogs_dlsym("pthread_attr_init");
2354 2452
2355 2453 xlog(2, "%s\n", __func__); xlog(2, "%s\n", __func__);
2356 ret = old_pthread_attr_init(attr);
2454 int ret = old_pthread_attr_init(attr);
2357 2455 my_trace(__func__, 'R', attr, ret); my_trace(__func__, 'R', attr, ret);
2358 2456
2359 2457 return ret; return ret;
 
... ... int pthread_attr_init(pthread_attr_t *attr)
2362 2460
2363 2461 int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
2364 2462 { {
2365 int ret;
2366
2367 2463 if (!old_pthread_attr_setstacksize) if (!old_pthread_attr_setstacksize)
2368 2464 old_pthread_attr_setstacksize = ninedogs_dlsym("pthread_attr_setstacksize"); old_pthread_attr_setstacksize = ninedogs_dlsym("pthread_attr_setstacksize");
2369 2465
2370 2466 xlog(2, "pthread_attr_setstacksize(%p, %zu)\n", attr, stacksize); xlog(2, "pthread_attr_setstacksize(%p, %zu)\n", attr, stacksize);
2371 2467
2372 ret = old_pthread_attr_setstacksize(attr, stacksize);
2468 int ret = old_pthread_attr_setstacksize(attr, stacksize);
2373 2469 my_trace(__func__, 'R', attr, stacksize, ret); my_trace(__func__, 'R', attr, stacksize, ret);
2374 2470
2375 2471 return ret; return ret;
 
... ... int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
2378 2474 static int (*old_pthread_setname_np)(pthread_t thread, const char *name); static int (*old_pthread_setname_np)(pthread_t thread, const char *name);
2379 2475 int pthread_setname_np(pthread_t thread, const char *name) int pthread_setname_np(pthread_t thread, const char *name)
2380 2476 { {
2381 int ret;
2382
2383 2477 if (!old_pthread_setname_np) if (!old_pthread_setname_np)
2384 2478 old_pthread_setname_np = ninedogs_dlsym("pthread_setname_np"); old_pthread_setname_np = ninedogs_dlsym("pthread_setname_np");
2385 2479
2386 2480 xlog(2, "pthread_setname_np(%lu, %s)\n", thread, name); xlog(2, "pthread_setname_np(%lu, %s)\n", thread, name);
2387 ret = old_pthread_setname_np(thread, name);
2481 int ret = old_pthread_setname_np(thread, name);
2388 2482 my_trace(__func__, 'R', thread, name, ret); my_trace(__func__, 'R', thread, name, ret);
2389 2483
2390 2484 return ret; return ret;
 
... ... int pthread_setname_np(pthread_t thread, const char *name)
2394 2488 int getsockopt(int sockfd, int level, int optname, void *restrict optval, int getsockopt(int sockfd, int level, int optname, void *restrict optval,
2395 2489 socklen_t *restrict optlen) socklen_t *restrict optlen)
2396 2490 { {
2397 int r;
2398
2399 2491 xlog(50, "%s(%d, %d, %d, %p, %u)\n", xlog(50, "%s(%d, %d, %d, %p, %u)\n",
2400 2492 __func__, sockfd, level, optname, optval, optlen); __func__, sockfd, level, optname, optval, optlen);
2401 2493
2402 r = old_getsockopt(sockfd, level, optname, optval, optlen);
2494 int r = old_getsockopt(sockfd, level, optname, optval, optlen);
2403 2495 while ((level == SOL_SOCKET) && (optname == SO_ERROR)) { while ((level == SOL_SOCKET) && (optname == SO_ERROR)) {
2404 2496 struct node *q; struct node *q;
2405 2497 int err = *(int *) optval; int err = *(int *) optval;
 
... ... int getsockopt(int sockfd, int level, int optname, void *restrict optval,
2426 2518
2427 2519 int execve(const char *pathname, char *const argv[], char *const envp[]) int execve(const char *pathname, char *const argv[], char *const envp[])
2428 2520 { {
2429 int ret;
2430
2431 2521 xlog(2, "%s(%s, ...)\n", __func__, pathname); xlog(2, "%s(%s, ...)\n", __func__, pathname);
2432 2522
2433 2523 my_trace(__func__, 'c', pathname, argv, envp); my_trace(__func__, 'c', pathname, argv, envp);
2434 ret = old_execve(pathname, argv, envp);
2524 int ret = old_execve(pathname, argv, envp);
2435 2525 my_trace(__func__, 'r', pathname, argv, envp, ret); my_trace(__func__, 'r', pathname, argv, envp, ret);
2436 2526
2437 2527 xlog(2, " ret=%d\n", ret); xlog(2, " ret=%d\n", ret);
 
... ... static int open_common_pre(const char *pathname)
2454 2544 return -1; return -1;
2455 2545 } }
2456 2546
2457 q->flags |= FD_NODE_DEV_NINEDOGS;
2458 xlog(10, "ninedogs special /dev file opened fd=%d flags=0x%08x\n",
2459 ret, q->flags);
2547 q->type = FD_NODE_DEV_NINEDOGS;
2548 xlog(10, "ninedogs special /dev file opened fd=%d\n", ret);
2460 2549
2461 2550 return ret; return ret;
2462 2551 } }
2463 2552
2464 static void open_common_post(const char *pathname, int flags, mode_t mode, int fd)
2553 static void open_common_post(const unsigned char type, const char *pathname,
2554 int flags, mode_t mode, int fd)
2465 2555 { {
2556 if (fd == -1)
2557 return;
2558
2466 2559 struct fd_node *q = fd_add(fd); struct fd_node *q = fd_add(fd);
2467 2560 if (!q) if (!q)
2468 2561 return; return;
2469 2562
2470 snprintf(q->path, sizeof(q->path), "%s", pathname);
2471 q->real_flags = flags;
2472 q->mode = mode;
2563 q->type = type;
2564 snprintf(q->file.path, sizeof(q->file.path), "%s", pathname);
2565 q->file.flags = flags;
2566 q->file.mode = mode;
2567 q->file.off = 0;
2568 }
2569
2570 // TODO: trace
2571 static int (*old_memfd_create)(const char *name, unsigned int flags);
2572 int memfd_create(const char *name, unsigned int flags)
2573 {
2574 if (!old_memfd_create)
2575 old_memfd_create = ninedogs_dlsym("memfd_create");
2576
2577 xlog(100, "%s(%s, 0x%x)\n", __func__, name, flags);
2578 my_trace(__func__, 'c', name, flags);
2579 int ret = old_memfd_create(name, flags);
2580 my_trace(__func__, 'r', name, flags, ret);
2581 open_common_post(FD_NODE_MEMFD, name, flags, 0, ret);
2582 xlog(101, " ret=%d\n", ret);
2583
2584 return ret;
2585 }
2586
2587 static int (*old_timerfd_create)(int clockid, int flags);
2588 int timerfd_create(int clockid, int flags)
2589 {
2590 if (!old_timerfd_create)
2591 old_timerfd_create = ninedogs_dlsym("timerfd_create");
2592
2593 xlog(100, "%s(%d, 0x%x)\n", __func__, clockid, flags);
2594 my_trace(__func__, 'c', clockid, flags);
2595 int ret = old_timerfd_create(clockid, flags);
2596 my_trace(__func__, 'r', clockid, flags, ret);
2597 open_common_post(FD_NODE_TIMERFD, "", flags, clockid, ret);
2598 xlog(101, " ret=%d\n", ret);
2599
2600 return ret;
2473 2601 } }
2474 2602
2475 2603 int open(const char *pathname, int flags, ...) int open(const char *pathname, int flags, ...)
2476 2604 { {
2477 int ret;
2478 2605 mode_t mode = 0; mode_t mode = 0;
2479 2606 va_list va; va_list va;
2480 2607
 
... ... int open(const char *pathname, int flags, ...)
2484 2611 va_end(va); va_end(va);
2485 2612 } }
2486 2613
2487 ret = open_common_pre(pathname);
2614 int ret = open_common_pre(pathname);
2488 2615 if (ret != -1) if (ret != -1)
2489 2616 return ret; return ret;
2490 2617
2491 xlog(100, "%s(%s, %d, %d)\n", __func__, pathname, flags, mode);
2618 xlog(100, "%s(%s, 0x%x, 0x%x)\n", __func__, pathname, flags, mode);
2492 2619 my_trace(__func__, 'c', pathname, flags, mode); my_trace(__func__, 'c', pathname, flags, mode);
2493 2620 ret = old_open(pathname, flags, mode); ret = old_open(pathname, flags, mode);
2494 2621 my_trace(__func__, 'r', pathname, flags, mode, ret); my_trace(__func__, 'r', pathname, flags, mode, ret);
2495 open_common_post(pathname, flags, mode, ret);
2622 open_common_post(FD_NODE_FILE, pathname, flags, mode, ret);
2496 2623 xlog(101, " ret=%d\n", ret); xlog(101, " ret=%d\n", ret);
2497 2624
2498 2625 return ret; return ret;
 
... ... int open(const char *pathname, int flags, ...)
2500 2627
2501 2628 int open64(const char *pathname, int flags, ...) int open64(const char *pathname, int flags, ...)
2502 2629 { {
2503 int ret;
2504 2630 mode_t mode = 0; mode_t mode = 0;
2505 2631 va_list va; va_list va;
2506 2632
 
... ... int open64(const char *pathname, int flags, ...)
2510 2636 va_end(va); va_end(va);
2511 2637 } }
2512 2638
2513 ret = open_common_pre(pathname);
2639 int ret = open_common_pre(pathname);
2514 2640 if (ret != -1) if (ret != -1)
2515 2641 return ret; return ret;
2516 2642
 
... ... int open64(const char *pathname, int flags, ...)
2518 2644 my_trace(__func__, 'c', pathname, flags, mode); my_trace(__func__, 'c', pathname, flags, mode);
2519 2645 ret = old_open64(pathname, flags, mode); ret = old_open64(pathname, flags, mode);
2520 2646 my_trace(__func__, 'r', pathname, flags, mode, ret); my_trace(__func__, 'r', pathname, flags, mode, ret);
2521 open_common_post(pathname, flags, mode, ret);
2647 open_common_post(FD_NODE_FILE, pathname, flags, mode, ret);
2522 2648 xlog(101, " ret=%d\n", ret); xlog(101, " ret=%d\n", ret);
2523 2649
2524 2650 return ret; return ret;
 
... ... int open64(const char *pathname, int flags, ...)
2526 2652
2527 2653 int openat(int dirfd, const char *pathname, int flags, ...) int openat(int dirfd, const char *pathname, int flags, ...)
2528 2654 { {
2529 int ret;
2530 2655 mode_t mode = 0; mode_t mode = 0;
2531 2656 va_list va; va_list va;
2532 2657
 
... ... int openat(int dirfd, const char *pathname, int flags, ...)
2536 2661 va_end(va); va_end(va);
2537 2662 } }
2538 2663
2539 ret = open_common_pre(pathname);
2664 int ret = open_common_pre(pathname);
2540 2665 if (ret != -1) if (ret != -1)
2541 2666 return ret; return ret;
2542 2667
 
... ... int openat(int dirfd, const char *pathname, int flags, ...)
2544 2669 my_trace(__func__, 'c', dirfd, pathname, flags, mode); my_trace(__func__, 'c', dirfd, pathname, flags, mode);
2545 2670 ret = old_openat(dirfd, pathname, flags, mode); ret = old_openat(dirfd, pathname, flags, mode);
2546 2671 my_trace(__func__, 'r', dirfd, pathname, flags, mode, ret); my_trace(__func__, 'r', dirfd, pathname, flags, mode, ret);
2547 open_common_post(pathname, flags, mode, ret);
2672 open_common_post(FD_NODE_FILE, pathname, flags, mode, ret);
2548 2673 xlog(101, " ret=%d\n", ret); xlog(101, " ret=%d\n", ret);
2549 2674
2550 2675 return ret; return ret;
 
... ... int openat(int dirfd, const char *pathname, int flags, ...)
2554 2679 // TODO: remove this // TODO: remove this
2555 2680 static int my_stat(const char *restrict pathname, struct stat *restrict statbuf) static int my_stat(const char *restrict pathname, struct stat *restrict statbuf)
2556 2681 { {
2557 int ret;
2558
2559 2682 xlog(20, "%s(%s, %p)\n", __func__, pathname, statbuf); xlog(20, "%s(%s, %p)\n", __func__, pathname, statbuf);
2560 2683 my_trace(__func__, 'c', pathname, statbuf); my_trace(__func__, 'c', pathname, statbuf);
2561 ret = old_stat(pathname, statbuf);
2684 int ret = old_stat(pathname, statbuf);
2562 2685 my_trace(__func__, 'r', pathname, statbuf, ret); my_trace(__func__, 'r', pathname, statbuf, ret);
2563 2686 xlog(25, " ret=%d\n", ret); xlog(25, " ret=%d\n", ret);
2564 2687
 
... ... static int my_stat(const char *restrict pathname, struct stat *restrict statbuf)
2568 2691
2569 2692 void *dlsym(void *restrict handle, const char *restrict symbol) void *dlsym(void *restrict handle, const char *restrict symbol)
2570 2693 { {
2571 void *ret;
2572
2573 2694 if (!old_dlsym) if (!old_dlsym)
2574 2695 return NULL; return NULL;
2575 2696
2576 2697 xlog(50, "%s(%p, %s)\n", __func__, handle, symbol); xlog(50, "%s(%p, %s)\n", __func__, handle, symbol);
2577 ret = old_dlsym(handle, symbol);
2698 void *ret = old_dlsym(handle, symbol);
2578 2699 xlog(50, "%s(%p, %s) = %p\n", __func__, handle, symbol, ret); xlog(50, "%s(%p, %s) = %p\n", __func__, handle, symbol, ret);
2579 2700
2580 2701 if (!ret) if (!ret)
 
... ... void *dlsym(void *restrict handle, const char *restrict symbol)
2594 2715
2595 2716 void *dlopen(const char *filename, int flags) void *dlopen(const char *filename, int flags)
2596 2717 { {
2597 void *ret;
2598
2599 2718 if (!old_dlopen) if (!old_dlopen)
2600 2719 return NULL; return NULL;
2601 2720
2602 2721 my_trace(__func__, 'c', filename, flags); my_trace(__func__, 'c', filename, flags);
2603 ret = old_dlopen(filename, flags);
2722 void *ret = old_dlopen(filename, flags);
2604 2723 my_trace(__func__, 'r', filename, flags, ret); my_trace(__func__, 'r', filename, flags, ret);
2605 2724 if (filename && ret) { if (filename && ret) {
2606 2725 // TODO: should I add only 'flags=GLOBAL' entries? // TODO: should I add only 'flags=GLOBAL' entries?
 
... ... void *dlopen(const char *filename, int flags)
2638 2757
2639 2758 int dlclose(void *h) int dlclose(void *h)
2640 2759 { {
2641 int ret;
2642
2643 2760 xlog(100, "%s(%p)\n", __func__, h); xlog(100, "%s(%p)\n", __func__, h);
2644 2761
2645 2762 if (!old_dlclose) if (!old_dlclose)
2646 2763 return 0; return 0;
2647 2764
2648 ret = old_dlclose(h);
2765 int ret = old_dlclose(h);
2649 2766 if (ret == 0) { if (ret == 0) {
2650 2767 for (unsigned i = 0; i < DLOPEN_MAX_ENTRIES; i++) { for (unsigned i = 0; i < DLOPEN_MAX_ENTRIES; i++) {
2651 2768 if (dlopen_nodes[i].p == h) { if (dlopen_nodes[i].p == h) {
 
... ... int dlclose(void *h)
2670 2787 */ */
2671 2788 void *ninedogs_dlsym(const char *sym) void *ninedogs_dlsym(const char *sym)
2672 2789 { {
2673 void *ret;
2674
2675 2790 xlog(100, "%s: sym [%s]\n", __func__, sym); xlog(100, "%s: sym [%s]\n", __func__, sym);
2676 2791
2677 ret = old_dlsym(RTLD_NEXT, sym);
2792 void *ret = old_dlsym(RTLD_NEXT, sym);
2678 2793 if (ret) if (ret)
2679 2794 return ret; return ret;
2680 2795
 
... ... void *ninedogs_dlsym(const char *sym)
2695 2810
2696 2811 ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) ssize_t getrandom(void *buf, size_t buflen, unsigned int flags)
2697 2812 { {
2698 ssize_t ret;
2699
2813 // Seems we cannot use ninedogs_dlsym here!
2700 2814 if (!old_getrandom) if (!old_getrandom)
2701 2815 ninedogs_init(); ninedogs_init();
2702 2816
 
... ... ssize_t getrandom(void *buf, size_t buflen, unsigned int flags)
2704 2818 __func__, buf, buflen, flags, old_getrandom); __func__, buf, buflen, flags, old_getrandom);
2705 2819
2706 2820 my_trace(__func__, 'c', buflen, flags); my_trace(__func__, 'c', buflen, flags);
2707 ret = old_getrandom(buf, buflen, flags);
2821 ssize_t ret = old_getrandom(buf, buflen, flags);
2708 2822 my_trace(__func__, 'r', buf, buflen, flags, ret); my_trace(__func__, 'r', buf, buflen, flags, ret);
2709 2823
2710 2824 return ret; return ret;
 
... ... ssize_t getrandom(void *buf, size_t buflen, unsigned int flags)
2712 2826
2713 2827 int nanosleep(const struct timespec *req, struct timespec *rem) int nanosleep(const struct timespec *req, struct timespec *rem)
2714 2828 { {
2715 int ret;
2716
2717 2829 if (!old_nanosleep) if (!old_nanosleep)
2718 ninedogs_init();
2830 old_nanosleep = ninedogs_dlsym("nanosleep");
2719 2831
2720 2832 xlog(100, "%s(%ld.%09ld, %p)\n", xlog(100, "%s(%ld.%09ld, %p)\n",
2721 2833 __func__, req->tv_sec, req->tv_nsec, rem); __func__, req->tv_sec, req->tv_nsec, rem);
2722 2834
2723 2835 my_trace(__func__, 'c', req); my_trace(__func__, 'c', req);
2724 ret = old_nanosleep(req, rem);
2836 int ret = old_nanosleep(req, rem);
2725 2837 my_trace(__func__, 'r', req, rem, ret); my_trace(__func__, 'r', req, rem, ret);
2726 2838
2727 2839 return ret; return ret;
 
... ... int nanosleep(const struct timespec *req, struct timespec *rem)
2729 2841
2730 2842 int unlink(const char *pathname) int unlink(const char *pathname)
2731 2843 { {
2732 int ret;
2733
2734 2844 if (!old_unlink) if (!old_unlink)
2735 ninedogs_init();
2845 old_unlink = ninedogs_dlsym("unlink");
2736 2846
2737 2847 xlog(100, "%s(%s)\n", __func__, pathname); xlog(100, "%s(%s)\n", __func__, pathname);
2738 2848
2739 2849 my_trace(__func__, 'c', pathname); my_trace(__func__, 'c', pathname);
2740 ret = old_unlink(pathname);
2850 int ret = old_unlink(pathname);
2741 2851 my_trace(__func__, 'r', pathname, ret); my_trace(__func__, 'r', pathname, ret);
2742 2852
2743 2853 return ret; return ret;
 
... ... int unlink(const char *pathname)
2745 2855
2746 2856 int listen(int sock, int backlog) int listen(int sock, int backlog)
2747 2857 { {
2748 int ret;
2749
2750 2858 if (!old_listen) if (!old_listen)
2751 ninedogs_init();
2859 old_listen = ninedogs_dlsym("listen");
2752 2860
2753 2861 xlog(100, "%s(%d, %d)\n", __func__, sock, backlog); xlog(100, "%s(%d, %d)\n", __func__, sock, backlog);
2754 2862
2755 ret = old_listen(sock, backlog);
2863 int ret = old_listen(sock, backlog);
2756 2864 my_trace(__func__, 'R', sock, backlog, ret); my_trace(__func__, 'R', sock, backlog, ret);
2757 2865
2866 struct fd_node *q = fd_search(sock);
2867 if (q)
2868 q->socket.backlog = backlog;
2869
2758 2870 return ret; return ret;
2759 2871 } }
2760 2872
 
... ... void syslog(int priority, const char *format, ...)
2764 2876 char buf[4096]; char buf[4096];
2765 2877
2766 2878 if (!old_syslog) if (!old_syslog)
2767 ninedogs_init();
2879 old_syslog = ninedogs_dlsym("syslog");
2768 2880
2769 2881 xlog(100, "%s(%d)\n", __func__, priority); xlog(100, "%s(%d)\n", __func__, priority);
2770 2882
 
... ... void syslog(int priority, const char *format, ...)
2779 2891 int fstatat(int dirfd, const char *restrict pathname, int fstatat(int dirfd, const char *restrict pathname,
2780 2892 struct stat *restrict statbuf, int flags) struct stat *restrict statbuf, int flags)
2781 2893 { {
2782 int ret;
2783
2784 2894 if (!old_fstatat) if (!old_fstatat)
2785 ninedogs_init();
2895 old_fstatat = ninedogs_dlsym("fstatat");
2786 2896
2787 2897 xlog(100, "%s(%d, %s, %p, 0x%x)\n", __func__, dirfd, pathname, statbuf, flags); xlog(100, "%s(%d, %s, %p, 0x%x)\n", __func__, dirfd, pathname, statbuf, flags);
2788 2898
2789 2899 my_trace(__func__, 'c', dirfd, pathname, flags); my_trace(__func__, 'c', dirfd, pathname, flags);
2790 ret = old_fstatat(dirfd, pathname, statbuf, flags);
2900 int ret = old_fstatat(dirfd, pathname, statbuf, flags);
2791 2901 my_trace(__func__, 'r', dirfd, pathname, statbuf, flags, ret); my_trace(__func__, 'r', dirfd, pathname, statbuf, flags, ret);
2792 2902
2793 2903 return ret; return ret;
 
... ... int fstatat(int dirfd, const char *restrict pathname,
2796 2906 int fstatat64(int dirfd, const char *restrict pathname, int fstatat64(int dirfd, const char *restrict pathname,
2797 2907 struct stat64 *restrict statbuf, int flags) struct stat64 *restrict statbuf, int flags)
2798 2908 { {
2799 int ret;
2800
2801 2909 if (!old_fstatat64) if (!old_fstatat64)
2802 ninedogs_init();
2910 old_fstatat64 = ninedogs_dlsym("fstatat64");
2803 2911
2804 2912 xlog(100, "%s(%d, %s, %p, 0x%x)\n", xlog(100, "%s(%d, %s, %p, 0x%x)\n",
2805 2913 __func__, dirfd, pathname, statbuf, flags); __func__, dirfd, pathname, statbuf, flags);
2806 2914
2807 2915 my_trace(__func__, 'c', dirfd, pathname, flags); my_trace(__func__, 'c', dirfd, pathname, flags);
2808 ret = old_fstatat64(dirfd, pathname, statbuf, flags);
2916 int ret = old_fstatat64(dirfd, pathname, statbuf, flags);
2809 2917 my_trace(__func__, 'r', dirfd, pathname, statbuf, flags, ret); my_trace(__func__, 'r', dirfd, pathname, statbuf, flags, ret);
2810 2918
2811 2919 return ret; return ret;
 
... ... int fstatat64(int dirfd, const char *restrict pathname,
2813 2921
2814 2922 int stat(const char *restrict pathname, struct stat *restrict statbuf) int stat(const char *restrict pathname, struct stat *restrict statbuf)
2815 2923 { {
2816 int ret;
2817
2818 2924 if (!old_stat) if (!old_stat)
2819 ninedogs_init();
2925 old_stat = ninedogs_dlsym("stat");
2820 2926
2821 2927 xlog(100, "%s(%s, %p)\n", __func__, pathname, statbuf); xlog(100, "%s(%s, %p)\n", __func__, pathname, statbuf);
2822 2928
2823 2929 my_trace(__func__, 'c', pathname); my_trace(__func__, 'c', pathname);
2824 ret = old_stat(pathname, statbuf);
2930 int ret = old_stat(pathname, statbuf);
2825 2931 my_trace(__func__, 'r', pathname, statbuf, ret); my_trace(__func__, 'r', pathname, statbuf, ret);
2826 2932
2827 2933 return ret; return ret;
 
... ... int stat(const char *restrict pathname, struct stat *restrict statbuf)
2829 2935
2830 2936 int fork(void) int fork(void)
2831 2937 { {
2832 int ret;
2833
2834 2938 if (!old_fork) if (!old_fork)
2835 ninedogs_init();
2939 old_fork = ninedogs_dlsym("fork");
2836 2940
2837 2941 xlog(100, "%s()\n", __func__); xlog(100, "%s()\n", __func__);
2838 2942
2839 ret = old_fork();
2943 int ret = old_fork();
2840 2944 my_trace(__func__, 'R', ret); my_trace(__func__, 'R', ret);
2841 2945
2842 2946 return ret; return ret;
 
... ... int fork(void)
2845 2949 static int (*old_fsync)(int fd); static int (*old_fsync)(int fd);
2846 2950 int fsync(int fd) int fsync(int fd)
2847 2951 { {
2848 int ret;
2849
2850 2952 if (!old_fsync) if (!old_fsync)
2851 2953 old_fsync = ninedogs_dlsym("fsync"); old_fsync = ninedogs_dlsym("fsync");
2852 2954
2853 2955 xlog(100, "%s(%d)\n", __func__, fd); xlog(100, "%s(%d)\n", __func__, fd);
2854 2956 my_trace(__func__, 'c', fd); my_trace(__func__, 'c', fd);
2855 ret = old_fsync(fd);
2957 int ret = old_fsync(fd);
2856 2958 my_trace(__func__, 'r', fd, ret); my_trace(__func__, 'r', fd, ret);
2857 2959
2858 2960 return ret; return ret;
 
... ... int fsync(int fd)
2861 2963 static int (*old_fdatasync)(int fd); static int (*old_fdatasync)(int fd);
2862 2964 int fdatasync(int fd) int fdatasync(int fd)
2863 2965 { {
2864 int ret;
2865
2866 2966 if (!old_fdatasync) if (!old_fdatasync)
2867 2967 old_fdatasync = ninedogs_dlsym("fdatasync"); old_fdatasync = ninedogs_dlsym("fdatasync");
2868 2968
2869 2969 xlog(100, "%s(%d)\n", __func__, fd); xlog(100, "%s(%d)\n", __func__, fd);
2870 2970 my_trace(__func__, 'c', fd); my_trace(__func__, 'c', fd);
2871 ret = old_fdatasync(fd);
2971 int ret = old_fdatasync(fd);
2872 2972 my_trace(__func__, 'r', fd, ret); my_trace(__func__, 'r', fd, ret);
2873 2973
2874 2974 return ret; return ret;
 
... ... int fdatasync(int fd)
2877 2977 static ssize_t (*old_pread)(int fd, void *buf, size_t count, off_t offset); static ssize_t (*old_pread)(int fd, void *buf, size_t count, off_t offset);
2878 2978 ssize_t pread(int fd, void *buf, size_t count, off_t offset) ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2879 2979 { {
2880 ssize_t ret;
2881
2882 2980 if (!old_pread) if (!old_pread)
2883 2981 old_pread = ninedogs_dlsym("pread"); old_pread = ninedogs_dlsym("pread");
2884 2982
2885 2983 xlog(100, "%s(%d, %p, %zu, %zd)\n", __func__, fd, buf, count, offset); xlog(100, "%s(%d, %p, %zu, %zd)\n", __func__, fd, buf, count, offset);
2886 2984 my_trace(__func__, 'c', fd, count, offset); my_trace(__func__, 'c', fd, count, offset);
2887 ret = old_pread(fd, buf, count, offset);
2985 ssize_t ret = old_pread(fd, buf, count, offset);
2888 2986 my_trace(__func__, 'r', fd, buf, count, offset, ret); my_trace(__func__, 'r', fd, buf, count, offset, ret);
2889 2987
2890 2988 return ret; return ret;
 
... ... ssize_t pread(int fd, void *buf, size_t count, off_t offset)
2893 2991 static ssize_t (*old_pread64)(int fd, void *buf, size_t count, off_t offset); static ssize_t (*old_pread64)(int fd, void *buf, size_t count, off_t offset);
2894 2992 ssize_t pread64(int fd, void *buf, size_t count, off_t offset) ssize_t pread64(int fd, void *buf, size_t count, off_t offset)
2895 2993 { {
2896 ssize_t ret;
2897
2898 2994 if (!old_pread64) if (!old_pread64)
2899 2995 old_pread64 = ninedogs_dlsym("pread64"); old_pread64 = ninedogs_dlsym("pread64");
2900 2996
2901 2997 xlog(100, "%s(%d, %p, %zu, %zd)\n", __func__, fd, buf, count, offset); xlog(100, "%s(%d, %p, %zu, %zd)\n", __func__, fd, buf, count, offset);
2902 2998 my_trace(__func__, 'c', fd, count, offset); my_trace(__func__, 'c', fd, count, offset);
2903 ret = old_pread64(fd, buf, count, offset);
2999 ssize_t ret = old_pread64(fd, buf, count, offset);
2904 3000 my_trace(__func__, 'r', fd, buf, count, offset, ret); my_trace(__func__, 'r', fd, buf, count, offset, ret);
2905 3001
2906 3002 return ret; return ret;
 
... ... ssize_t pread64(int fd, void *buf, size_t count, off_t offset)
2909 3005 static ssize_t (*old_pwrite)(int fd, const void *buf, size_t count, off_t offset); static ssize_t (*old_pwrite)(int fd, const void *buf, size_t count, off_t offset);
2910 3006 ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset) ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
2911 3007 { {
2912 ssize_t ret;
2913
2914 3008 if (!old_pwrite) if (!old_pwrite)
2915 3009 old_pwrite = ninedogs_dlsym("pwrite"); old_pwrite = ninedogs_dlsym("pwrite");
2916 3010
2917 3011 xlog(100, "%s(%d, %p, %zu, %zd)\n", __func__, fd, buf, count, offset); xlog(100, "%s(%d, %p, %zu, %zd)\n", __func__, fd, buf, count, offset);
2918 3012 my_trace(__func__, 'c', fd, buf, count, offset); my_trace(__func__, 'c', fd, buf, count, offset);
2919 ret = old_pwrite(fd, buf, count, offset);
3013 ssize_t ret = old_pwrite(fd, buf, count, offset);
2920 3014 my_trace(__func__, 'r', fd, count, offset, ret); my_trace(__func__, 'r', fd, count, offset, ret);
2921 3015
2922 3016 return ret; return ret;
 
... ... ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
2925 3019 static ssize_t (*old_pwrite64)(int fd, const void *buf, size_t count, off_t offset); static ssize_t (*old_pwrite64)(int fd, const void *buf, size_t count, off_t offset);
2926 3020 ssize_t pwrite64(int fd, const void *buf, size_t count, off_t offset) ssize_t pwrite64(int fd, const void *buf, size_t count, off_t offset)
2927 3021 { {
2928 ssize_t ret;
2929
2930 3022 if (!old_pwrite64) if (!old_pwrite64)
2931 3023 old_pwrite64 = ninedogs_dlsym("pwrite64"); old_pwrite64 = ninedogs_dlsym("pwrite64");
2932 3024
2933 3025 xlog(100, "%s(%d, %p, %zu, %zd)\n", __func__, fd, buf, count, offset); xlog(100, "%s(%d, %p, %zu, %zd)\n", __func__, fd, buf, count, offset);
2934 3026 my_trace(__func__, 'c', fd, buf, count, offset); my_trace(__func__, 'c', fd, buf, count, offset);
2935 ret = old_pwrite64(fd, buf, count, offset);
3027 ssize_t ret = old_pwrite64(fd, buf, count, offset);
2936 3028 my_trace(__func__, 'r', fd, count, offset, ret); my_trace(__func__, 'r', fd, count, offset, ret);
2937 3029
2938 3030 return ret; return ret;
 
... ... static int (*old_sqlite3_open)(const char *, void **);
2942 3034 int sqlite3_open(const char *filename, void **ppdb); int sqlite3_open(const char *filename, void **ppdb);
2943 3035 int sqlite3_open(const char *filename, void **ppdb) int sqlite3_open(const char *filename, void **ppdb)
2944 3036 { {
2945 int ret;
2946
2947 3037 if (!old_sqlite3_open) if (!old_sqlite3_open)
2948 3038 old_sqlite3_open = ninedogs_dlsym("sqlite3_open"); old_sqlite3_open = ninedogs_dlsym("sqlite3_open");
2949 3039
2950 3040 xlog(100, "%s(%s)\n", __func__, filename); xlog(100, "%s(%s)\n", __func__, filename);
2951 3041
2952 3042 my_trace(__func__, 'c', filename); my_trace(__func__, 'c', filename);
2953 ret = old_sqlite3_open(filename, ppdb);
3043 int ret = old_sqlite3_open(filename, ppdb);
2954 3044 my_trace(__func__, 'r', filename, ppdb, ret); my_trace(__func__, 'r', filename, ppdb, ret);
2955 3045
2956 3046 return ret; return ret;
 
... ... static int (*old_sqlite3_open_v2)(const char *, void **, int, const char *);
2960 3050 int sqlite3_open_v2(const char *filename, void **ppdb, int flags, const char *vfs); int sqlite3_open_v2(const char *filename, void **ppdb, int flags, const char *vfs);
2961 3051 int sqlite3_open_v2(const char *filename, void **ppdb, int flags, const char *vfs) int sqlite3_open_v2(const char *filename, void **ppdb, int flags, const char *vfs)
2962 3052 { {
2963 int ret;
2964
2965 3053 if (!old_sqlite3_open_v2) if (!old_sqlite3_open_v2)
2966 3054 old_sqlite3_open_v2 = ninedogs_dlsym("sqlite3_open_v2"); old_sqlite3_open_v2 = ninedogs_dlsym("sqlite3_open_v2");
2967 3055
 
... ... int sqlite3_open_v2(const char *filename, void **ppdb, int flags, const char *vf
2969 3057 __func__, filename, flags, vfs); __func__, filename, flags, vfs);
2970 3058
2971 3059 my_trace(__func__, 'c', filename, flags, vfs); my_trace(__func__, 'c', filename, flags, vfs);
2972 ret = old_sqlite3_open_v2(filename, ppdb, flags, vfs);
3060 int ret = old_sqlite3_open_v2(filename, ppdb, flags, vfs);
2973 3061 my_trace(__func__, 'r', filename, ppdb ? *ppdb : NULL, flags, vfs, ret); my_trace(__func__, 'r', filename, ppdb ? *ppdb : NULL, flags, vfs, ret);
2974 3062
2975 3063 return ret; return ret;
 
... ... static int (*old_sqlite3_open16)(const char *, void **);
2979 3067 int sqlite3_open16(const char *filename, void **ppdb); int sqlite3_open16(const char *filename, void **ppdb);
2980 3068 int sqlite3_open16(const char *filename, void **ppdb) int sqlite3_open16(const char *filename, void **ppdb)
2981 3069 { {
2982 int ret;
2983
2984 3070 if (!old_sqlite3_open16) if (!old_sqlite3_open16)
2985 3071 old_sqlite3_open16 = ninedogs_dlsym("sqlite3_open16"); old_sqlite3_open16 = ninedogs_dlsym("sqlite3_open16");
2986 3072
 
... ... int sqlite3_open16(const char *filename, void **ppdb)
2988 3074 __func__, filename); __func__, filename);
2989 3075
2990 3076 my_trace(__func__, 'c', filename); my_trace(__func__, 'c', filename);
2991 ret = old_sqlite3_open16(filename, ppdb);
3077 int ret = old_sqlite3_open16(filename, ppdb);
2992 3078 my_trace(__func__, 'r', filename, ppdb, ret); my_trace(__func__, 'r', filename, ppdb, ret);
2993 3079
2994 3080 return ret; return ret;
 
... ... int sqlite3_exec(void *h, const char *sql,
3002 3088 int sqlite3_exec(void *h, const char *sql, int sqlite3_exec(void *h, const char *sql,
3003 3089 int (*callback)(void *, int, char **, char **), void *callback_arg, char **errmsg) int (*callback)(void *, int, char **, char **), void *callback_arg, char **errmsg)
3004 3090 { {
3005 int ret;
3006
3007 3091 if (!old_sqlite3_exec) if (!old_sqlite3_exec)
3008 3092 old_sqlite3_exec = ninedogs_dlsym("sqlite3_exec"); old_sqlite3_exec = ninedogs_dlsym("sqlite3_exec");
3009 3093
3010 3094 //my_trace(__func__, 'c', h, sql, callback, callback_arg); //my_trace(__func__, 'c', h, sql, callback, callback_arg);
3011 ret = old_sqlite3_exec(h, sql, callback, callback_arg, errmsg);
3095 int ret = old_sqlite3_exec(h, sql, callback, callback_arg, errmsg);
3012 3096 xlog(100, "%s(h=%p, sql='%s', cb=%p, cba=%p, err='%s')\n", xlog(100, "%s(h=%p, sql='%s', cb=%p, cba=%p, err='%s')\n",
3013 3097 __func__, h, sql, callback, callback_arg, errmsg ? *errmsg : "?"); __func__, h, sql, callback, callback_arg, errmsg ? *errmsg : "?");
3014 3098 //my_trace(__func__, 'r', h, sql, callback, callback_arg, errmsg); //my_trace(__func__, 'r', h, sql, callback, callback_arg, errmsg);
 
... ... static int (*old_sqlite3_prepare_v2)(void *, const char *, int, void **, const c
3020 3104 int sqlite3_prepare_v2(void *h, const char *sql, int nByte, void **stmt, const char **tail); int sqlite3_prepare_v2(void *h, const char *sql, int nByte, void **stmt, const char **tail);
3021 3105 int sqlite3_prepare_v2(void *h, const char *sql, int nByte, void **stmt, const char **tail) int sqlite3_prepare_v2(void *h, const char *sql, int nByte, void **stmt, const char **tail)
3022 3106 { {
3023 int ret;
3024
3025 3107 if (!old_sqlite3_prepare_v2) if (!old_sqlite3_prepare_v2)
3026 3108 old_sqlite3_prepare_v2 = ninedogs_dlsym("sqlite3_prepare_v2"); old_sqlite3_prepare_v2 = ninedogs_dlsym("sqlite3_prepare_v2");
3027 3109
3028 3110 my_trace(__func__, 'c', h, sql, nByte); my_trace(__func__, 'c', h, sql, nByte);
3029 ret = old_sqlite3_prepare_v2(h, sql, nByte, stmt, tail);
3111 int ret = old_sqlite3_prepare_v2(h, sql, nByte, stmt, tail);
3030 3112 xlog(100, "%s(h=%p, sql='%s', nByte=%d, *stmt=%p, tail=[%s]) = %d\n", xlog(100, "%s(h=%p, sql='%s', nByte=%d, *stmt=%p, tail=[%s]) = %d\n",
3031 3113 __func__, h, sql, nByte, stmt ? *stmt : NULL, tail ? *tail : "", ret); __func__, h, sql, nByte, stmt ? *stmt : NULL, tail ? *tail : "", ret);
3032 3114 my_trace(__func__, 'r', h, sql, nByte, stmt ? *stmt : NULL, ret); my_trace(__func__, 'r', h, sql, nByte, stmt ? *stmt : NULL, ret);
 
... ... static int (*old_sqlite3_finalize)(void *);
3039 3121 int sqlite3_finalize(void *pstmt); int sqlite3_finalize(void *pstmt);
3040 3122 int sqlite3_finalize(void *pstmt) int sqlite3_finalize(void *pstmt)
3041 3123 { {
3042 int ret;
3043
3044 3124 if (!old_sqlite3_finalize) if (!old_sqlite3_finalize)
3045 3125 old_sqlite3_finalize = ninedogs_dlsym("sqlite3_finalize"); old_sqlite3_finalize = ninedogs_dlsym("sqlite3_finalize");
3046 3126
3047 ret = old_sqlite3_finalize(pstmt);
3127 int ret = old_sqlite3_finalize(pstmt);
3048 3128 xlog(100, "%s(pstmt=%p) = %d\n", __func__, pstmt); xlog(100, "%s(pstmt=%p) = %d\n", __func__, pstmt);
3049 3129 my_trace(__func__, 'R', pstmt, ret); my_trace(__func__, 'R', pstmt, ret);
3050 3130
 
... ... static int (*old_sqlite3_step)(void *);
3055 3135 int sqlite3_step(void *stmt); int sqlite3_step(void *stmt);
3056 3136 int sqlite3_step(void *stmt) int sqlite3_step(void *stmt)
3057 3137 { {
3058 int ret;
3059
3060 3138 if (!old_sqlite3_step) if (!old_sqlite3_step)
3061 3139 old_sqlite3_step = ninedogs_dlsym("sqlite3_step"); old_sqlite3_step = ninedogs_dlsym("sqlite3_step");
3062 3140
3063 3141 my_trace(__func__, 'c', stmt); my_trace(__func__, 'c', stmt);
3064 ret = old_sqlite3_step(stmt);
3142 int ret = old_sqlite3_step(stmt);
3065 3143 xlog(100, "%s(stmt=%p) = %d\n", __func__, stmt, ret); xlog(100, "%s(stmt=%p) = %d\n", __func__, stmt, ret);
3066 3144 my_trace(__func__, 'r', stmt, ret); my_trace(__func__, 'r', stmt, ret);
3067 3145
 
... ... static int (*old_sqlite3_bind_double)(void *, int, double);
3072 3150 int sqlite3_bind_double(void *stmt, int index, double value); int sqlite3_bind_double(void *stmt, int index, double value);
3073 3151 int sqlite3_bind_double(void *stmt, int index, double value) int sqlite3_bind_double(void *stmt, int index, double value)
3074 3152 { {
3075 int ret;
3076
3077 3153 if (!old_sqlite3_bind_double) if (!old_sqlite3_bind_double)
3078 3154 old_sqlite3_bind_double = ninedogs_dlsym("sqlite3_bind_double"); old_sqlite3_bind_double = ninedogs_dlsym("sqlite3_bind_double");
3079 3155
3080 ret = old_sqlite3_bind_double(stmt, index, value);
3156 int ret = old_sqlite3_bind_double(stmt, index, value);
3081 3157 xlog(100, "%s(stmt=%p, %d, %f) = %d\n", __func__, stmt, index, value, ret); xlog(100, "%s(stmt=%p, %d, %f) = %d\n", __func__, stmt, index, value, ret);
3082 3158 my_trace(__func__, 'R', stmt, index, value, ret); my_trace(__func__, 'R', stmt, index, value, ret);
3083 3159
 
... ... static int (*old_sqlite3_bind_int)(void *, int, int);
3088 3164 int sqlite3_bind_int(void *stmt, int index, int value); int sqlite3_bind_int(void *stmt, int index, int value);
3089 3165 int sqlite3_bind_int(void *stmt, int index, int value) int sqlite3_bind_int(void *stmt, int index, int value)
3090 3166 { {
3091 int ret;
3092
3093 3167 if (!old_sqlite3_bind_int) if (!old_sqlite3_bind_int)
3094 3168 old_sqlite3_bind_int = ninedogs_dlsym("sqlite3_bind_int"); old_sqlite3_bind_int = ninedogs_dlsym("sqlite3_bind_int");
3095 3169
3096 ret = old_sqlite3_bind_int(stmt, index, value);
3170 int ret = old_sqlite3_bind_int(stmt, index, value);
3097 3171 xlog(100, "%s(stmt=%p, %d, %d) = %d\n", __func__, stmt, index, value, ret); xlog(100, "%s(stmt=%p, %d, %d) = %d\n", __func__, stmt, index, value, ret);
3098 3172 my_trace(__func__, 'R', stmt, index, value, ret); my_trace(__func__, 'R', stmt, index, value, ret);
3099 3173
 
... ... static int (*old_sqlite3_bind_int64)(void *, int, uint64_t);
3104 3178 int sqlite3_bind_int64(void *stmt, int index, uint64_t value); int sqlite3_bind_int64(void *stmt, int index, uint64_t value);
3105 3179 int sqlite3_bind_int64(void *stmt, int index, uint64_t value) int sqlite3_bind_int64(void *stmt, int index, uint64_t value)
3106 3180 { {
3107 int ret;
3108
3109 3181 if (!old_sqlite3_bind_int64) if (!old_sqlite3_bind_int64)
3110 3182 old_sqlite3_bind_int64 = ninedogs_dlsym("sqlite3_bind_int64"); old_sqlite3_bind_int64 = ninedogs_dlsym("sqlite3_bind_int64");
3111 3183
3112 ret = old_sqlite3_bind_int64(stmt, index, value);
3184 int ret = old_sqlite3_bind_int64(stmt, index, value);
3113 3185 xlog(100, "%s(stmt=%p, %d, %ld) = %d\n", __func__, stmt, index, value, ret); xlog(100, "%s(stmt=%p, %d, %ld) = %d\n", __func__, stmt, index, value, ret);
3114 3186 my_trace(__func__, 'R', stmt, index, value, ret); my_trace(__func__, 'R', stmt, index, value, ret);
3115 3187
 
... ... static int (*old_sqlite3_bind_text)(void *, int, const char *, int, void *);
3120 3192 int sqlite3_bind_text(void *stmt, int index, const char *value, int len, void *func); int sqlite3_bind_text(void *stmt, int index, const char *value, int len, void *func);
3121 3193 int sqlite3_bind_text(void *stmt, int index, const char *value, int len, void *func) int sqlite3_bind_text(void *stmt, int index, const char *value, int len, void *func)
3122 3194 { {
3123 int ret;
3124
3125 3195 if (!old_sqlite3_bind_text) if (!old_sqlite3_bind_text)
3126 3196 old_sqlite3_bind_text = ninedogs_dlsym("sqlite3_bind_text"); old_sqlite3_bind_text = ninedogs_dlsym("sqlite3_bind_text");
3127 3197
3128 ret = old_sqlite3_bind_text(stmt, index, value, len, func);
3198 int ret = old_sqlite3_bind_text(stmt, index, value, len, func);
3129 3199 xlog(100, "%s(stmt=%p, %d, '%s', len=%d) = %d\n", __func__, stmt, index, value, len, ret); xlog(100, "%s(stmt=%p, %d, '%s', len=%d) = %d\n", __func__, stmt, index, value, len, ret);
3130 3200 my_trace(__func__, 'R', stmt, index, value, len, ret); my_trace(__func__, 'R', stmt, index, value, len, ret);
3131 3201
File common/Makefile changed (mode: 100644) (index 50cf03c..d7a4557)
3 3 all: all:
4 4 make -C .. common make -C .. common
5 5
6 OBJS := tools.o sctools.o
6 OBJS := tools.o sctools.o info.o decode_text.o
7 7
8 8 tools.o: tools.c tools.h tools.o: tools.c tools.h
9 9 $(CC) $(CFLAGS) -fPIC -c $< $(CC) $(CFLAGS) -fPIC -c $<
 
... ... tools.o: tools.c tools.h
11 11 sctools.o: sctools.c sctools.h tools.h sctools.o: sctools.c sctools.h tools.h
12 12 $(CC) $(CFLAGS) -fPIC -c $< $(CC) $(CFLAGS) -fPIC -c $<
13 13
14 info.o: info.c info.h shared.h decode_text.h
15 $(CC) $(CFLAGS) -fPIC -c $<
16
17 decode_text.o: decode_text.c decode_text.h tools.h
18 $(CC) $(CFLAGS) -fPIC -c $<
19
14 20 .PHONY: clean .PHONY: clean
15 21 clean: clean:
16 22 @rm -f *.o @rm -f *.o
File common/decode_text.c added (mode: 100644) (index 0000000..f456c1e)
1 #define _GNU_SOURCE
2
3 #include <sys/mman.h>
4 #include <sys/timerfd.h>
5 #include <sys/un.h>
6
7 #include <arpa/inet.h>
8 #include <linux/memfd.h>
9 #include <stdio.h>
10
11 #include "tools.h"
12 #include "decode_text.h"
13
14 void nd_decode_socket_domain(char *out, const size_t out_size, const int d)
15 {
16 switch (d) {
17 case AF_UNIX: snprintf(out, out_size, "unix"); return;
18 case AF_INET: snprintf(out, out_size, "ipv4"); return;
19 case AF_INET6: snprintf(out, out_size, "ipv6"); return;
20 case AF_KEY: snprintf(out, out_size, "key"); return;
21 case AF_NETLINK: snprintf(out, out_size, "netlink"); return;
22 case AF_PACKET: snprintf(out, out_size, "packet"); return;
23 }
24 snprintf(out, out_size, "?%d?", d);
25 }
26
27 void nd_decode_socket_type(char *out, const size_t out_size, const int t)
28 {
29 switch (t) {
30 case SOCK_STREAM: snprintf(out, out_size, "stream"); return;
31 case SOCK_DGRAM: snprintf(out, out_size, "dgram"); return;
32 case SOCK_SEQPACKET: snprintf(out, out_size, "seqpacket"); return;
33 case SOCK_RAW: snprintf(out, out_size, "raw"); return;
34 }
35 snprintf(out, out_size, "?%d?", t);
36 }
37
38 void nd_decode_socket_protocol(char *out, const size_t out_size, const int t)
39 {
40 switch (t) {
41 case IPPROTO_IP: snprintf(out, out_size, "ip"); return;
42 case IPPROTO_ICMP: snprintf(out, out_size, "icmp"); return;
43 case IPPROTO_IGMP: snprintf(out, out_size, "igmp"); return;
44 case IPPROTO_IPIP: snprintf(out, out_size, "ipip"); return;
45 case IPPROTO_TCP: snprintf(out, out_size, "tcp"); return;
46 case IPPROTO_EGP: snprintf(out, out_size, "egp"); return;
47 case IPPROTO_PUP: snprintf(out, out_size, "pup"); return;
48 case IPPROTO_UDP: snprintf(out, out_size, "udp"); return;
49 case IPPROTO_DCCP: snprintf(out, out_size, "dccp"); return;
50 case IPPROTO_IPV6: snprintf(out, out_size, "ipv6"); return;
51 case IPPROTO_GRE: snprintf(out, out_size, "gre"); return;
52 case IPPROTO_ESP: snprintf(out, out_size, "esp"); return;
53 case IPPROTO_SCTP: snprintf(out, out_size, "sctp"); return;
54 case IPPROTO_UDPLITE: snprintf(out, out_size, "udplite"); return;
55 case IPPROTO_MPLS: snprintf(out, out_size, "mpls"); return;
56 case IPPROTO_ETHERNET: snprintf(out, out_size, "ethernet"); return;
57 case IPPROTO_RAW: snprintf(out, out_size, "raw"); return;
58 case IPPROTO_MPTCP: snprintf(out, out_size, "mptcp"); return;
59 }
60 snprintf(out, out_size, "?%d?", t);
61 }
62
63 void nd_decode_clockid(char *out, const size_t out_size, const int clockid)
64 {
65 switch (clockid) {
66 case CLOCK_REALTIME: snprintf(out, out_size, "realtime"); return;
67 case CLOCK_MONOTONIC: snprintf(out, out_size, "monotonic"); return;
68 case CLOCK_BOOTTIME: snprintf(out, out_size, "boottime"); return;
69 case CLOCK_REALTIME_ALARM: snprintf(out, out_size, "realtime_alarm"); return;
70 case CLOCK_BOOTTIME_ALARM: snprintf(out, out_size, "boottime_alarm"); return;
71 }
72
73 snprintf(out, out_size, "?%d?", clockid);
74 }
75
76 void nd_decode_memfd_flags(char *out, const size_t out_size, const unsigned int flags)
77 {
78 char *ce = ""; if (flags & MFD_CLOEXEC) ce = "|cloexec";
79 char *as = ""; if (flags & MFD_ALLOW_SEALING) as = "|allow_sealing";
80 char *h = ""; if (flags & MFD_HUGETLB) h = "|hugetlb";
81 char *h2m = ""; if (flags & MFD_HUGE_2MB) h2m = "|huge_2m";
82 char *h1g = ""; if (flags & MFD_HUGE_1GB) h1g = "|huge_1g";
83 char *h2g = ""; if (flags & MFD_HUGE_2GB) h1g = "|huge_2g";
84
85 snprintf(out, out_size, "0x%x%s%s%s%s%s%s",
86 flags, ce, as, h, h2m, h1g, h2g);
87 }
88
89 void nd_decode_timerfd_flags(char *out, const size_t out_size, const int flags)
90 {
91 // create
92 char *nb = ""; if (flags & TFD_NONBLOCK) nb = "|nonblock";
93 char *ce = ""; if (flags & TFD_CLOEXEC) ce = "|cloexec";
94 // settime
95 char *abs = ""; if (flags & TFD_TIMER_ABSTIME) abs = "|abstime";
96 char *on_set = ""; if (flags & TFD_TIMER_CANCEL_ON_SET) on_set = "|on_set";
97
98 snprintf(out, out_size, "0x%x%s%s%s%s",
99 flags, nb, ce, abs, on_set);
100 }
101
102 void nd_decode_sockaddr(char *out, const void *s, const socklen_t sl)
103 {
104 const struct sockaddr_in *t;
105
106 t = (const struct sockaddr_in *) s;
107 //sprintf(out, "%s: sin_family=%d\n", __func__, t->sin_family); return;
108 switch (t->sin_family) {
109 case AF_INET:
110 if (sl < sizeof(struct sockaddr_in))
111 break;
112 struct sockaddr_in *s4 = (struct sockaddr_in *) s;
113 char addr[16];
114 inet_ntop(s4->sin_family, &s4->sin_addr, addr, sizeof(addr));
115 sprintf(out, "ipv4/%s/%hu",
116 addr, be16toh(s4->sin_port));
117 return;
118
119 case AF_INET6:
120 if (sl < sizeof(struct sockaddr_in6))
121 break;
122 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) s;
123 char addr6[40];
124 inet_ntop(s6->sin6_family, &s6->sin6_addr, addr6, sizeof(addr6));
125 sprintf(out, "ipv6/%s/%hu/flow=%u/scope=%u",
126 addr6, be16toh(s6->sin6_port),
127 be32toh(s6->sin6_flowinfo), be32toh(s6->sin6_scope_id));
128 return;
129
130 case AF_UNIX:
131 if (sl < sizeof(struct sockaddr_un))
132 break;
133 struct sockaddr_un *su = (struct sockaddr_un *) s;
134 sprintf(out, "unix/'%s'", su->sun_path);
135 return;
136 }
137
138 bin2hex(out, s, sl);
139 }
140
141 void nd_decode_curl_code(char *out, const size_t out_size, const int code)
142 {
143 switch (code) {
144 case 0: snprintf(out, out_size, "ok"); return;
145 case 43: snprintf(out, out_size, "bad_func_arg"); return;
146 }
147
148 snprintf(out, out_size, "?%d?", code);
149 }
File common/decode_text.h added (mode: 100644) (index 0000000..92f6e8c)
1 void nd_decode_socket_domain(char *out, const size_t out_size, const int d);
2 void nd_decode_socket_type(char *out, const size_t out_size, const int t);
3 void nd_decode_socket_protocol(char *out, const size_t out_size, const int t);
4 void nd_decode_clockid(char *out, const size_t out_size, const int clockid);
5 void nd_decode_memfd_flags(char *out, const size_t out_size, const unsigned int flags);
6 void nd_decode_timerfd_flags(char *out, const size_t out_size, const int flags);
7 void nd_decode_sockaddr(char *out, const void *s, const socklen_t sl);
8 void nd_decode_curl_code(char *out, const size_t out_size, const int code);
9
File common/info.c added (mode: 100644) (index 0000000..3ce6d03)
1 #include <stdint.h>
2 #include <string.h>
3
4 #include <stdio.h> // temp
5
6 #include "shared.h"
7 #include "info.h"
8 #include "decode_text.h"
9
10 extern void xlog(const unsigned int level, const char *format, ...);
11
12 /*
13 * Export one fd node, returns the number of bytes
14 */
15 static unsigned int export_fd_node(unsigned char *out, const struct fd_node *n)
16 {
17 unsigned short off = 0;
18 uint16_t u16, path_len;
19 uint32_t u32;
20 uint64_t u64;
21
22 u32 = htobe32(n->fd); memcpy(out + off, &u32, 4); off += 4;
23 out[off++] = n->type;
24 switch (n->type) {
25 case FD_NODE_FILE:
26 path_len = strlen(n->file.path);
27 u16 = htobe16(path_len);
28 memcpy(out + off, &u16, 2); off += 2;
29 memcpy(out + off, n->file.path, path_len); off += path_len;
30 u32 = htobe32(n->file.flags); memcpy(out + off, &u32, 4); off += 4;
31 u32 = htobe32(n->file.mode); memcpy(out + off, &u32, 4); off += 4;
32 u64 = htobe64(n->file.off); memcpy(out + off, &u64, 8); off += 8;
33 break;
34
35 case FD_NODE_SOCKET:
36 u32 = htobe32(n->socket.domain); memcpy(out + off, &u32, 4); off += 4;
37 u32 = htobe32(n->socket.type); memcpy(out + off, &u32, 4); off += 4;
38 u32 = htobe32(n->socket.protocol); memcpy(out + off, &u32, 4); off += 4;
39 u32 = htobe32(n->socket.backlog); memcpy(out + off, &u32, 4); off += 4;
40 u64 = htobe64(n->socket.accepts); memcpy(out + off, &u64, 8); off += 8;
41 u16 = htobe16(n->socket.bind_len); memcpy(out + off, &u16, 2); off += 2;
42 memcpy(out + off, &n->socket.bind, n->socket.bind_len); off += n->socket.bind_len;
43 u16 = htobe16(n->socket.peer_len); memcpy(out + off, &u16, 2); off += 2;
44 memcpy(out + off, &n->socket.peer, n->socket.peer_len); off += n->socket.peer_len;
45 break;
46
47 case FD_NODE_MEMFD:
48 path_len = strlen(n->file.path);
49 u16 = htobe16(path_len);
50 memcpy(out + off, &u16, 2); off += 2;
51 memcpy(out + off, n->file.path, path_len); off += path_len;
52 u32 = htobe32(n->file.flags); memcpy(out + off, &u32, 4); off += 4;
53 u64 = htobe64(n->file.off); memcpy(out + off, &u64, 8); off += 8;
54 break;
55
56 case FD_NODE_TIMERFD:
57 u32 = htobe32(n->file.mode); memcpy(out + off, &u32, 4); off += 4; // clockid
58 u32 = htobe32(n->file.flags); memcpy(out + off, &u32, 4); off += 4;
59 break;
60
61 default: return 0xffffffff;
62 }
63
64 for (unsigned char i = 0; i < 3; i++) {
65 for (unsigned char j = 0; j < 2; j++) {
66 //xlog(100, " off=%u stats[%hhu][%s]=%lu\n",
67 // off, i, j == 0 ? "r" : "w", n->stats[i][j]);
68 u64 = htobe64(n->stats[i][j]);
69 memcpy(out + off, &u64, 8); off += 8;
70 }
71 }
72
73 return off;
74 }
75
76 /*
77 * Output sfd info in @out buffer and the size in out_len.
78 * Return 0xffffffff on error, else the final size.
79 */
80 unsigned int export_fd_nodes(unsigned char *out, unsigned int out_size,
81 struct fd_node **nodes, const unsigned int nodes_len)
82 {
83 const struct fd_node *n;
84 unsigned int count = 0, off = 0;
85 unsigned char do_break = 0;
86
87 out[off++] = 'F'; // fd nodes
88 off += 4; // here will be the big endian count of entries
89
90 for (unsigned int i = 0; i < nodes_len; i++) {
91 n = nodes[i];
92 while (n) {
93 if ((n->fd == -1)
94 || (n->type == FD_NODE_DEV_NINEDOGS)
95 || (n->fd >= 100)) {
96 n = n->next;
97 continue;
98 }
99
100 unsigned char exp[4096];
101 unsigned int size = export_fd_node(exp, n);
102 if ((size == 0xffffffff) || (size > out_size - off)) {
103 do_break = 1;
104 break;
105 }
106 memcpy(out + off, exp, size); off += size;
107 count++;
108 n = n->next;
109 }
110 if (do_break)
111 break;
112 }
113
114 count = htobe32(count);
115 memcpy(out + 1, &count, 4);
116
117 return off;
118 }
119
120 /*
121 * Decode a fd_node binary dump
122 * Returns -1 on error
123 */
124 int decode_fd_node(struct fd_node *n, unsigned char *in, unsigned int *poff)
125 {
126 uint16_t u16, path_len, max;
127 uint32_t u32;
128 uint64_t u64;
129 unsigned int off = *poff;
130
131 memcpy(&u32, in + off, 4); n->fd = be32toh(u32); off += 4;
132 n->type = in[off++];
133 switch (n->type) {
134 case FD_NODE_FILE:
135 memcpy(&u16, in + off, 2); off += 2; path_len = be16toh(u16);
136 max = sizeof(n->file.path) - 1;
137 if (max > path_len)
138 max = path_len;
139 memcpy(n->file.path, in + off, max); n->file.path[max] = '\0'; off += path_len;
140 memcpy(&u32, in + off, 4); off += 4; n->file.flags = be32toh(u32);
141 memcpy(&u32, in + off, 4); off += 4; n->file.mode = be32toh(u32);
142 memcpy(&u64, in + off, 8); off += 8; n->file.off = be64toh(u64);
143 break;
144
145 case FD_NODE_SOCKET:
146 memcpy(&u32, in + off, 4); off += 4; n->socket.domain = be32toh(u32);
147 memcpy(&u32, in + off, 4); off += 4; n->socket.type = be32toh(u32);
148 memcpy(&u32, in + off, 4); off += 4; n->socket.protocol = be32toh(u32);
149 memcpy(&u32, in + off, 4); off += 4; n->socket.backlog = be32toh(u32);
150 memcpy(&u64, in + off, 8); off += 8; n->socket.accepts = be64toh(u64);
151 memcpy(&u16, in + off, 2); off += 2; n->socket.bind_len = be16toh(u16);
152 memcpy(&n->socket.bind, in + off, n->socket.bind_len); off += n->socket.bind_len;
153 memcpy(&u16, in + off, 2); off += 2; n->socket.peer_len = be16toh(u16);
154 memcpy(&n->socket.peer, in + off, n->socket.peer_len); off += n->socket.peer_len;
155 break;
156
157 case FD_NODE_MEMFD:
158 memcpy(&u16, in + off, 2); off += 2; path_len = be16toh(u16);
159 max = sizeof(n->file.path) - 1;
160 if (max > path_len)
161 max = path_len;
162 memcpy(n->file.path, in + off, max); n->file.path[max] = '\0'; off += path_len;
163 memcpy(&u32, in + off, 4); off += 4; n->file.flags = be32toh(u32);
164 memcpy(&u64, in + off, 8); off += 8; n->file.off = be64toh(u64);
165 break;
166
167 case FD_NODE_TIMERFD:
168 memcpy(&u32, in + off, 4); off += 4; n->file.mode = be32toh(u32); // clockid
169 memcpy(&u32, in + off, 4); off += 4; n->file.flags = be32toh(u32);
170 break;
171
172 default: return -1;
173 }
174
175 for (unsigned char i = 0; i < 3; i++) {
176 for (unsigned int j = 0; j < 2; j++) {
177 memcpy(&u64, in + off, 8); off += 8;
178 n->stats[i][j] = be64toh(u64);
179 }
180 }
181
182 *poff = off;
183
184 return 0;
185 }
186
187 void decode_fd_node_to_text(char *out, const size_t out_size, struct fd_node *n)
188 {
189 char base[1024];
190
191 switch (n->type) {
192 case FD_NODE_FILE:
193 snprintf(base, sizeof(base),
194 "file fd=%d path=[%s] flags=0x%x mode=0x%x off=%lu",
195 n->fd, n->file.path, n->file.flags, n->file.mode, n->file.off);
196 break;
197
198 case FD_NODE_SOCKET:
199 char bind[1024], peer[1024];
200
201 if (n->socket.bind_len > 0)
202 nd_decode_sockaddr(bind, &n->socket.bind, n->socket.bind_len);
203 else
204 strcpy(bind, "n/a");
205
206 if (n->socket.peer_len > 0)
207 nd_decode_sockaddr(peer, &n->socket.peer, n->socket.peer_len);
208 else
209 strcpy(peer, "n/a");
210
211 char type[32], protocol[16];
212 nd_decode_socket_type(type, sizeof(type), n->socket.type);
213 nd_decode_socket_protocol(protocol, sizeof(protocol), n->socket.protocol);
214
215 snprintf(base, sizeof(base),
216 "socket fd=%d %s/%s bind=[%s] peer=[%s] backlog=%d accepts=%lu",
217 n->fd, type, protocol, bind, peer, n->socket.backlog, n->socket.accepts);
218 break;
219
220 case FD_NODE_MEMFD:
221 char mfd_flags[64];
222 nd_decode_memfd_flags(mfd_flags, sizeof(mfd_flags), n->file.flags);
223 snprintf(base, sizeof(base), "memfd fd=%d path=[%s] flags=%s off=%lu",
224 n->fd, n->file.path, mfd_flags, n->file.off);
225 break;
226
227 case FD_NODE_TIMERFD:
228 char clock[32], flags[64];
229 nd_decode_clockid(clock, sizeof(clock), n->file.mode);
230 nd_decode_timerfd_flags(flags, sizeof(flags), n->file.flags);
231 snprintf(base, sizeof(base), "timerfd fd=%d clock=%s flags=%s",
232 n->fd, clock, flags);
233 break;
234
235 default:
236 snprintf(out, out_size, "fd=%d unknown type %hhu", n->fd, n->type);
237 return;
238 }
239
240 snprintf(out, out_size, "%s ops=%lu/%lu bytes=%lu/%lu errs=%lu/%lu", base,
241 n->stats[0][0], n->stats[0][1],
242 n->stats[1][0], n->stats[1][1],
243 n->stats[2][0], n->stats[2][1]);
244 }
245
File common/info.h added (mode: 100644) (index 0000000..43ef467)
1
2 unsigned int export_fd_nodes(unsigned char *out, unsigned int out_size,
3 struct fd_node **nodes, const unsigned int nodes_len);
4
5 int decode_fd_node(struct fd_node *n, unsigned char *in, unsigned int *poff);
6
7 void decode_fd_node_to_text(char *out, const size_t out_size, struct fd_node *n);
8
File common/shared.h changed (mode: 100644) (index f1aa8b8..ab487bb)
1 #include <arpa/inet.h>
2 #include <semaphore.h>
3 #include <limits.h> // PATH_MAX
4
1 5 #define SHARED_VERSION 1 #define SHARED_VERSION 1
2 6
3 7 // commands // commands
 
... ... struct shared
9 13 sem_t sem1; sem_t sem1;
10 14 unsigned int head, tail; // these can be changed only under semaphore unsigned int head, tail; // these can be changed only under semaphore
11 15 unsigned int new_tail; unsigned int new_tail;
12 unsigned int buf_size; // client may be compiled with another version and need to knows this
16 unsigned int buf_size; // client may be compiled with another version and need to know this
13 17 unsigned int msgs_lost; unsigned int msgs_lost;
14 18 unsigned char version; unsigned char version;
15 unsigned char pad[3];
16 unsigned char buf[1000000];
19 unsigned char done; // set by the target program when it exits; on fork we should make this a counter
20 unsigned char pad[2];
21 unsigned char buf[1024 * 1024];
22 };
23
24
25 struct nd_info_shared
26 {
27 sem_t sem;
28 unsigned char version;
29 unsigned char do_fill_buffer; // set by nd-info
30 unsigned char buffer_is_filled; // set by agent
31 unsigned char pad;
32 unsigned int buf_size;
33 unsigned char buf[1024 * 1024];
17 34 }; };
18 35
36
37 #define FD_NODE_DEV_NINEDOGS 1
38 #define FD_NODE_FILE 2
39 #define FD_NODE_SOCKET 3
40 #define FD_NODE_MEMFD 4
41 #define FD_NODE_TIMERFD 5
42 struct fd_node
43 {
44 int fd;
45 unsigned char type; // See FD_NODE_*
46 unsigned char pad2[3];
47 struct fd_node *next;
48 union {
49 struct {
50 char path[PATH_MAX];
51 int flags;
52 mode_t mode; // used also as timerfd::clockid
53 off_t off;
54 } file;
55 struct {
56 int domain, type, protocol, backlog;
57 struct sockaddr_storage bind, peer;
58 socklen_t bind_len, peer_len;
59 uint64_t accepts;
60 } socket;
61 };
62 uint64_t stats[3][2]; // 0=ops/1=bytes/2=errors | 0=read/1=write
63 };
File docs/pre1.tex changed (mode: 100644) (index 4532234..98e1c33)
7 7 \usepackage{url} \usepackage{url}
8 8 \usepackage[utf8]{inputenc} \usepackage[utf8]{inputenc}
9 9
10 \title{ninedogs project introduction}
11 \subtitle{ninedogs workshop for Devs and DevOps (tracing)}
12 \author{Catalin(ux) M. BOIE - ninedogs@embedromix.ro}
13 \date{2022-11-09}
10 \title{ninedogs project}
11 \subtitle{Augumented high and low-level tracing}
12 \author{\small Catalin(ux) M. BOIE - ninedogs@embedromix.ro}
13 \date{\small 2022-11-09}
14 14 %\titlegraphic{\includegraphics[width=2.5cm]{ninedogs.svg}} %\titlegraphic{\includegraphics[width=2.5cm]{ninedogs.svg}}
15 15
16 16
 
26 26
27 27 \section{Introduction} \section{Introduction}
28 28
29 \subsection{What, how, why?}
29 \subsection{Why, what, how?}
30
31 \begin{frame}
32 \begin{block}{Why?}
33 \begin{itemize}
34 \item You want high-level tracing.
35 \item You cannot use standard tools in some environments.
36 \item You want to see decrypted information.
37 \item You want a very low impact on performance.
38 \end{itemize}
39 \end{block}
40 \end{frame}
30 41
31 42 \begin{frame} \begin{frame}
32 43 \begin{block}{What is ninedogs?} \begin{block}{What is ninedogs?}
 
66 77 \end{block} \end{block}
67 78 \end{frame} \end{frame}
68 79
80 \begin{frame}
81 \begin{block}{Why strace is better (if it can be used)?}
82 \begin{itemize}
83 \item strace can be used on static linked binaries, ninedogs cannot.
84 In practice, this is rarely encountered.
85 \end{itemize}
86 \end{block}
87 \end{frame}
88
69 89 \begin{frame} \begin{frame}
70 90 \begin{block}{What is the performance impact of ninedogs tracing} \begin{block}{What is the performance impact of ninedogs tracing}
71 91 \begin{itemize} \begin{itemize}
 
... ... docker run -e LD_PRELOAD=ninedogs.so image command
147 167
148 168 \subsection{Real life examples} \subsection{Real life examples}
149 169
170 \begin{frame}[fragile]{curl - https}
171 \begin{block}{C code}
172 \tiny
173 \begin{verbatim}
174 char *body = "{\"a\": \"1\"}";
175 long body_len = strlen(body);
176
177 struct curl_slist *list = NULL;
178 list = curl_slist_append(list, "Content-Type: application/json");
179 list = curl_slist_append(list, "X-ninedogs-bla: 1");
180
181 CURL *curl = curl_easy_init();
182 curl_easy_setopt(curl, CURLOPT_URL, "https://localhost");
183 curl_easy_setopt(curl, CURLOPT_POST, 1);
184 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
185 curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body_len);
186 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
187 CURLcode res = curl_easy_perform(curl);
188
189 curl_slist_free_all(list);
190 curl_easy_cleanup(curl);
191 \end{verbatim}
192 \end{block}
193 \begin{block}{strace}
194 \tiny
195 \begin{verbatim}
196 connect(5, {sa_family=AF_INET, sin_port=htons(443), sin_addr=inet_addr("127.0.0.1")}, 16) =
197 -1 EINPROGRESS (Operation now in progress)
198 write(5, "\26\3\1\2\0\1\0\1\374\3\3\3216\344\242\206\353\355...
199 read(5, "\201\3010M\237\371n\177v\330\fR\203\304k\332ic\253...
200 \end{verbatim}
201 \end{block}
202 \end{frame}
203
204
205 \begin{frame}[fragile]{curl - https - continuation}
206 \begin{block}{C code}
207 \tiny
208 \begin{verbatim}
209 char *body = "{\"a\": \"1\"}";
210 long body_len = strlen(body);
211
212 struct curl_slist *list = NULL;
213 list = curl_slist_append(list, "Content-Type: application/json");
214 list = curl_slist_append(list, "X-ninedogs-bla: 1");
215
216 CURL *curl = curl_easy_init();
217 curl_easy_setopt(curl, CURLOPT_URL, "https://localhost");
218 curl_easy_setopt(curl, CURLOPT_POST, 1);
219 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
220 curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body_len);
221 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
222 CURLcode res = curl_easy_perform(curl);
223
224 curl_slist_free_all(list);
225 curl_easy_cleanup(curl);
226 \end{verbatim}
227 \end{block}
228 \begin{block}{nd-trace}
229 \tiny
230 \begin{verbatim}
231 curl_easy_init() = 0x1c2b960
232 curl_easy_setopt(0x1c2b960, CURLOPT_URL, 'https://localhost') = ok
233 curl_easy_setopt(0x1c2b960, CURLOPT_POST, 1) = ok
234 curl_easy_setopt(0x1c2b960, CURLOPT_POSTFIELDS, 0x402010) = ok
235 curl_easy_setopt(0x1c2b960, CURLOPT_POSTFIELDSIZE, 10) = ok
236 curl_easy_setopt(0x1c2b960, CURLOPT_HTTPHEADER, {'Content-Type: application/json', 'X-ninedogs-bla: 1'}) = ok
237 curl_easy_perform(0x1c2b960)
238 curl_easy_cleanup(0x1c2b960)
239 \end{verbatim}
240 \end{block}
241 \end{frame}
242
243
150 244 \begin{frame}[fragile]{MySQL connection} \begin{frame}[fragile]{MySQL connection}
151 245 \begin{block}{PHP code} \begin{block}{PHP code}
152 246 \tiny \tiny
File docs/pre1.txt changed (mode: 100644) (index b68d436..8eb2369)
... ... Ideas for the first presentation
10 10 - Sponsors? - Sponsors?
11 11 - License! - License!
12 12 - Multiple slides, show how to use it. - Multiple slides, show how to use it.
13 - Insist on free software
14 - One tool to rule them all.
13 15 - -
14 16
17 - Ce probleme vrei sa le rezolvi?
18 - Cum te ajuta produsul meu sa-ti rezolvi problemele?
19 - De ce e mai bun decit alte solutii de pe piata?
20
File misc/.gitignore added (mode: 100644) (index 0000000..c9636ce)
1 nd-info
File misc/Makefile added (mode: 100644) (index 0000000..f9044f9)
1 # This is just to allow us to run make here
2 .PHONY: all
3 all:
4 make -R -C .. misc
5
6 COMMON_H += ../common/shared.h ../common/tools.h ../common/info.h \
7 ../common/decode_text.h
8
9 CFLAGS += -I../common
10
11 OBJS := ../common/tools.o ../common/info.o ../common/decode_text.o
12
13 #decode.o: decode.c decode.h process_db.h $(COMMON_H)
14 # $(CC) $(CFLAGS) -fPIC -c -o $@ $<
15
16 nd-info: nd-info.c $(COMMON_H) $(OBJS)
17 $(CC) $(CFLAGS) $@.c -o $@ $(OBJS) $(LIBS)
18
19 compile: nd-info
20
21 .PHONY: clean
22 clean:
23 @rm -f nd-info *.sinfo *.log *.out *.o
24
25 install: all
26 @mkdir -p $(I_USR_BIN)
27 cp -vd nd-info $(I_USR_BIN)
28
File misc/TODO added (mode: 100644) (index 0000000..e09a48b)
1 [ ] Report position inside file
2 [ ]
File misc/nd-info.c added (mode: 100644) (index 0000000..ae97b84)
1 #define _XOPEN_SOURCE 500
2 #define _GNU_SOURCE
3
4 #include <sys/mman.h>
5 #include <sys/socket.h>
6 #include <sys/stat.h>
7 #include <sys/types.h>
8 #include <sys/un.h>
9
10 #include <arpa/inet.h>
11 #include <dlfcn.h>
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <getopt.h>
15 #include <netdb.h>
16 #include <netinet/tcp.h>
17 #include <netinet/udp.h>
18 #include <poll.h>
19 #include <semaphore.h>
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <syslog.h>
25 #include <time.h>
26 #include <unistd.h>
27
28 #include "shared.h"
29 #include "tools.h"
30 #include "tools.h"
31 #include "info.h"
32
33 static const struct option options[] =
34 {
35 {"pid", required_argument, NULL, 'p'},
36 {NULL, 0, NULL, 0}
37 };
38
39 static void usage(void)
40 {
41 fprintf(stderr,
42 "Usage: nd-info [options]\n"
43 " --pid -p pid to get nfo for\n"
44 "\n");
45 exit(1);
46 }
47
48 int main(int argc, char *argv[])
49 {
50 int c, r;
51 int options_index = 0;
52 pid_t pid = -1;
53 int sm;
54 unsigned char version, do_exit = 0;
55 struct nd_info_shared *shared;
56
57 // Disabling ninedogs.so
58 int fd = open("/dev/ninedogs", O_WRONLY);
59 if (fd != -1) {
60 write(fd, "disable", 7);
61 close(fd);
62 }
63
64 setlinebuf(stdout);
65 setlinebuf(stderr);
66
67 while ((c = getopt_long(argc, argv, "p:", options, &options_index)) != -1) {
68 switch (c) {
69 case 'p': pid = strtoull(optarg, NULL, 10); break;
70 default: usage();
71 }
72 }
73
74 if (pid == -1) {
75 fprintf(stderr, "Error: no pid specified with -p!\n");
76 return 1;
77 }
78
79 int tries = 100;
80 char name[32];
81 snprintf(name, sizeof(name), "/ninedogs-info-%d", pid);
82 while (tries > 0) {
83 sm = shm_open(name, O_RDWR, 0);
84 if (sm != -1)
85 break;
86 usleep(10 * 1000);
87 tries--;
88 }
89 if (sm == -1) {
90 fprintf(stderr, "nd-info: %u: Cannot do shm_open: %m\n", pid);
91 return 1;
92 }
93
94 shared = mmap(NULL, sizeof(struct nd_info_shared),
95 PROT_READ | PROT_WRITE, MAP_SHARED, sm, 0);
96 if (shared == MAP_FAILED) {
97 fprintf(stderr, "nd-info: Cannot mmap: %m\n");
98 return 1;
99 }
100
101 r = sem_wait(&shared->sem);
102 if (r == -1) {
103 fprintf(stderr, "nd-info: %u: Cannot wait for sem: %m\n", pid);
104 return 1;
105 }
106
107 version = shared->version;
108 fprintf(stderr, "%u: peer version is %hhu\n", pid, version);
109
110 // Signal that we want data
111 shared->do_fill_buffer = 1;
112
113 r = sem_post(&shared->sem);
114 if (r == -1) {
115 fprintf(stderr, "nd-info: %u: Cannot post sem: %m\n", pid);
116 return 1;
117 }
118
119 if (version > 1) {
120 fprintf(stderr, "nd-info: Process version[%hhu] is bigger than known[%hhu]!\n",
121 version, 1);
122 return 1;
123 }
124
125 fprintf(stderr, "nd-info: waiting for data...\n");
126 again:
127 r = sem_wait(&shared->sem);
128 if (r == -1) {
129 fprintf(stderr, "nd-info: %u: Cannot wait for sem: %m\n", pid);
130 return 1;
131 }
132
133 while (shared->buffer_is_filled == 1) {
134 unsigned int off = 0;
135 while (off < shared->buf_size) {
136 unsigned char type = shared->buf[off++];
137 if (type == 'S') {
138 uint32_t u32;
139 memcpy(&u32, shared->buf + off, 4); off += 4;
140 time_t now, t = be32toh(u32);
141 now = time(NULL);
142 printf("Process started %lus ago at %s", now - t, ctime(&t));
143 } else if (type == 'F') {
144 unsigned int count;
145 memcpy(&count, shared->buf + off, 4); off += 4; count = be32toh(count);
146 printf("File descriptors:\n");
147 //fprintf(stderr, "DEBUG: count=%u\n", count);
148 // TODO: test if len is bigger than shared->buf_size
149 for (unsigned int i = 0; i < count; i++) {
150 //fprintf(stderr, " DEBUG: off=%u\n", off);
151 struct fd_node n;
152 int z = decode_fd_node(&n, shared->buf, &off);
153 if (z == -1) {
154 fprintf(stderr, "Cannot decode fd_node!\n");
155 return 1;
156 }
157 char dump[4096];
158 decode_fd_node_to_text(dump, sizeof(dump), &n);
159 printf(" %s\n", dump);
160 }
161 } else {
162 char dump[shared->buf_size * 4 + 1];
163 bin2hex_ascii(dump, shared->buf, shared->buf_size);
164 fprintf(stderr, "decoding %u bytes: %s\n",
165 shared->buf_size, dump);
166
167 fprintf(stderr, "I do not know how to decode type 0x%02hhx\n",
168 shared->buf[off]);
169 return 1;
170 }
171 }
172
173 do_exit = 1;
174 break;
175 }
176
177 r = sem_post(&shared->sem);
178 if (r == -1) {
179 fprintf(stderr, "nd-info: %u: Cannot post sem: %m\n", pid);
180 return 1;
181 }
182
183 if (do_exit)
184 return 0;
185
186 goto again;
187 }
188
File test/curl/.gitignore added (mode: 100644) (index 0000000..d00491f)
1 1
File test/curl/1.c added (mode: 100644) (index 0000000..1e7d2c6)
1 #define _GNU_SOURCE
2
3 #include <curl/curl.h>
4 #include <string.h>
5 #include <unistd.h>
6
7 int main(void)
8 {
9 char *body = "{\"a\": \"1\"}";
10 long body_len = strlen(body);
11
12 sleep(1); // allow nd-trace to attach
13
14 struct curl_slist *list = NULL;
15 list = curl_slist_append(list, "Content-Type: application/json");
16 list = curl_slist_append(list, "X-ninedogs-bla: 1");
17
18
19 CURL *curl = curl_easy_init();
20 curl_easy_setopt(curl, CURLOPT_URL, "https://localhost");
21 curl_easy_setopt(curl, CURLOPT_POST, 1);
22 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
23 curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body_len);
24 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
25 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
26 CURLcode res = curl_easy_perform(curl);
27
28 curl_slist_free_all(list);
29
30 curl_easy_cleanup(curl);
31
32 return 0;
33 }
34
35
File test/curl/1.run added (mode: 100755) (index 0000000..2a51e0d)
1 #!/bin/bash
2
3 set -e
4
5 gcc 1.c -o 1 -l curl
6
7 export LD_PRELOAD=../../agent/ninedogs.so
8
9 export NINEDOGS_VERBOSE=200
10
11 #export LD_DEBUG=symbols
12 #export LD_DEBUG_OUTPUT=1.ld.txt
13
14 ./1 &>1.out &
15 LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1.nd -p ${!}
16
File test/info/.gitignore added (mode: 100644) (index 0000000..d00491f)
1 1
File test/info/1.c added (mode: 100644) (index 0000000..36757bd)
1 #define _GNU_SOURCE
2
3 #include <sys/mman.h>
4 #include <sys/timerfd.h>
5 #include <sys/un.h>
6
7 #include <arpa/inet.h>
8 #include <fcntl.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <unistd.h>
12
13 int main(void)
14 {
15 int r;
16 int fd[10];
17 for (int i = 0; i < 4; i++)
18 fd[i] = open("/dev/null", O_RDONLY);
19
20 // Should reurn an error (read-only fd)
21 write(fd[0], "abcde", 5);
22
23 int f = open("1.tmp", O_RDWR | O_CREAT, 0666);
24 write(f, "abcde", 5);
25
26 lseek(f, 3, SEEK_SET);
27
28
29 // AF_INET + stream
30 struct sockaddr_in sa;
31 int sock1 = socket(AF_INET, SOCK_STREAM, 0);
32 printf("sock1 = %d\n", sock1);
33 int flags = fcntl(sock1, F_GETFL);
34 fcntl(sock1, F_SETFL, flags | O_NONBLOCK);
35 memset(&sa, 0, sizeof(sa));
36 sa.sin_family = AF_INET;
37 sa.sin_port = htons(65432);
38 sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
39 socklen_t len1 = sizeof(sa);
40 bind(sock1, (struct sockaddr *) &sa, len1);
41 listen(sock1, 10);
42
43 struct sockaddr_in cl;
44 int sock2 = socket(AF_INET, SOCK_STREAM, 0);
45 flags = fcntl(sock2, F_GETFL);
46 fcntl(sock2, F_SETFL, flags | O_NONBLOCK);
47 printf("sock2 = %d\n", sock2);
48 memset(&cl, 0, sizeof(cl));
49 cl.sin_family = AF_INET;
50 cl.sin_port = htons(65432);
51 cl.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
52 socklen_t len2 = sizeof(cl);
53 connect(sock2, (struct sockaddr *) &cl, len2);
54 printf("sock2 connect: %m\n");
55
56 struct sockaddr_storage ss;
57 socklen_t len3 = sizeof(ss);
58 int client = accept(sock1, (struct sockaddr *) &ss, &len3);
59 printf("client = %d\n", client);
60
61
62 // AF_UNIX + SEQPACKET test
63 struct sockaddr_un u;
64 int sock10 = socket(AF_UNIX, SOCK_SEQPACKET, 0);
65 flags = fcntl(sock10, F_GETFL);
66 fcntl(sock10, F_SETFL, flags | O_NONBLOCK);
67 printf("sock10 = %d\n", sock10);
68 memset(&u, 0, sizeof(u));
69 u.sun_family = AF_UNIX;
70 strncpy(u.sun_path, "1.unix.tmp", sizeof(u.sun_path) - 1);
71 socklen_t len10 = sizeof(u);
72 unlink("1.unix.tmp");
73 bind(sock10, (struct sockaddr *) &u, len10);
74 listen(sock10, 50000);
75
76 struct sockaddr_un cl10;
77 int sock11 = socket(AF_UNIX, SOCK_SEQPACKET, 0);
78 flags = fcntl(sock11, F_GETFL);
79 fcntl(sock11, F_SETFL, flags | O_NONBLOCK);
80 printf("sock11 = %d\n", sock11);
81 memset(&cl10, 0, sizeof(cl10));
82 cl10.sun_family = AF_UNIX;
83 strncpy(cl10.sun_path, "1.unix.tmp", sizeof(cl10.sun_path) - 1);
84 socklen_t len11 = sizeof(cl10);
85 connect(sock11, (struct sockaddr *) &cl10, len11);
86 printf("sock11 connect: %m\n");
87
88 int client12 = accept(sock10, NULL, NULL);
89 printf("client12 = %d: %m\n", client12);
90
91 send(client12, "abc", 3, MSG_DONTWAIT);
92
93
94 // memfd
95 int mfd = memfd_create("bla", MFD_HUGETLB);
96 write(mfd, "3456", 4);
97
98
99 // timerfd
100 int tfd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK);
101 printf("tfd = %d: %m\n", tfd);
102
103
104 sleep(2);
105
106 return 0;
107 }
108
109
File test/info/1.run added (mode: 100755) (index 0000000..dbe9497)
1 #!/bin/bash
2
3 set -e
4
5 gcc 1.c -o 1
6
7 export LD_PRELOAD=../../agent/ninedogs.so
8
9 export NINEDOGS_VERBOSE=200
10
11 #export LD_DEBUG=symbols
12 #export LD_DEBUG_OUTPUT=1.ld.txt
13
14 ./1 &>1.out &
15 LD_PRELOAD= LD_DEBUG= sleep 1
16 LD_PRELOAD= LD_DEBUG= strace -s2000 -tt -q -o 1.nd_info.strace ../../misc/nd-info -p ${!}
17
File test/php-sock/1.run changed (mode: 100755) (index fb758cc..5969e23)
1 1 #!/bin/bash #!/bin/bash
2 2
3 export LD_PRELOAD=../../src/ninedogs.so
3 export LD_PRELOAD=../../agent/ninedogs.so
4 4
5 5 export FORCE_NET_VERBOSE=100 export FORCE_NET_VERBOSE=100
6 6 #export LD_DEBUG=symbols #export LD_DEBUG=symbols
File test/php-sock/2.run changed (mode: 100755) (index 36b78e4..a7240eb)
1 1 #!/bin/bash #!/bin/bash
2 2
3 export LD_PRELOAD=../../src/ninedogs.so
3 export LD_PRELOAD=../../agent/ninedogs.so
4 4
5 5 export FORCE_NET_VERBOSE=100 export FORCE_NET_VERBOSE=100
6 6 #export LD_DEBUG=symbols #export LD_DEBUG=symbols
File test/trace/.gitignore changed (mode: 100644) (index 3474893..e6fbaa2)
... ... segv
6 6 thread1 thread1
7 7 coredump coredump
8 8 syslog1 syslog1
9 *.tmp
10 lseek
File test/trace/lseek.c added (mode: 100644) (index 0000000..d6d8e6f)
1 #include <fcntl.h>
2
3 int main(int argc, char *argv[])
4 {
5 sleep(1);
6
7 int fd = open("lseek.tmp", O_CREAT | O_TRUNC, 0600);
8
9 lseek(fd, 3, SEEK_SET);
10
11 return 0;
12 }
File test/trace/lseek.run copied from file test/trace/syslog1.run (similarity 60%) (mode: 100755) (index 0587a2f..9f406bf)
2 2
3 3 set -e set -e
4 4
5 gcc -Wall syslog1.c -o syslog1
5 gcc -Wall lseek.c -o lseek
6 6
7 7 export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro
8 8 export NINEDOGS_SERVER_PORT=36000 export NINEDOGS_SERVER_PORT=36000
 
... ... export NINEDOGS_VERBOSE=400
11 11 export NINEDOGS_SYNC_FLUSH=1 export NINEDOGS_SYNC_FLUSH=1
12 12
13 13 #export LD_DEBUG=all #export LD_DEBUG=all
14 export LD_DEBUG_OUTPUT=syslog1.ld.txt
14 export LD_DEBUG_OUTPUT=lseek.ld.txt
15 15
16 16 export DEBUGINFOD_URLS= export DEBUGINFOD_URLS=
17 17
18 LD_PRELOAD=../../agent/ninedogs.so ./syslog1 &> syslog1.out &
19 ../../trace/nd-trace -o syslog1.nd -p ${!}
18 LD_PRELOAD=../../agent/ninedogs.so ./lseek &> lseek.out &
19 ../../trace/nd-trace -o lseek.nd -p ${!}
20 20
File trace/Makefile changed (mode: 100644) (index 719fd7e..2630ccd)
3 3 all: all:
4 4 make -R -C .. trace make -R -C .. trace
5 5
6 COMMON_H += ../common/shared.h ../common/tools.h
6 COMMON_H += ../common/shared.h ../common/tools.h ../common/decode_text.h
7 7
8 8 CFLAGS += -I../common CFLAGS += -I../common
9 9
10 OBJS := ../common/tools.o
10 OBJS := ../common/tools.o ../common/decode_text.o
11 11
12 12 #decode.o: decode.c decode.h process_db.h $(COMMON_H) #decode.o: decode.c decode.h process_db.h $(COMMON_H)
13 13 # $(CC) $(CFLAGS) -fPIC -c -o $@ $< # $(CC) $(CFLAGS) -fPIC -c -o $@ $<
File trace/nd-trace.c changed (mode: 100644) (index 6843c12..c2de1f5)
26 26
27 27 #include "shared.h" #include "shared.h"
28 28 #include "tools.h" #include "tools.h"
29 #include "decode_text.h"
29 30
30 31 static const struct option options[] = static const struct option options[] =
31 32 { {
 
... ... static uint8_t decode_bool(const char *prefix, char *out, size_t out_size,
87 88 return v; return v;
88 89 } }
89 90
90 static char *decode_socket_domain(const int d)
91 {
92 switch (d) {
93 case AF_UNIX: return "unix";
94 case AF_INET: return "ipv4";
95 case AF_INET6: return "ipv6";
96 case AF_KEY: return "key";
97 case AF_NETLINK: return "netlink";
98 case AF_PACKET: return "packet";
99 }
100
101 return "?";
102 }
103
104 static char *decode_socket_type(const int t)
105 {
106 switch (t) {
107 case SOCK_STREAM: return "stream";
108 case SOCK_DGRAM: return "dgram";
109 case SOCK_SEQPACKET: return "seqpacket";
110 case SOCK_RAW: return "raw";
111 }
112
113 return "?";
114 }
115
116 91 // TODO: more to add from /usr/include/asm-generic/errno.h // TODO: more to add from /usr/include/asm-generic/errno.h
117 92 static void decode_errno(char *out, unsigned out_max, const int e) static void decode_errno(char *out, unsigned out_max, const int e)
118 93 { {
 
... ... static socklen_t decode_sockaddr(char *out, unsigned char *d, unsigned int *i)
237 212
238 213 memcpy(&ss, d + *i, sl); *i = *i + sl; memcpy(&ss, d + *i, sl); *i = *i + sl;
239 214
240 switch (ss.ss_family) {
241 case AF_INET:
242 struct sockaddr_in *s4 = (struct sockaddr_in *) &ss;
243 char addr[16];
244 inet_ntop(ss.ss_family, &s4->sin_addr, addr, sizeof(addr));
245 sprintf(out, "ipv4/%s/%hu",
246 addr, be16toh(s4->sin_port));
247 break;
248
249 case AF_INET6:
250 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &ss;
251 char addr6[40];
252 inet_ntop(ss.ss_family, &s6->sin6_addr, addr6, sizeof(addr6));
253 sprintf(out, "ipv6/%s/%hu/flow=%u/scope=%u",
254 addr6, be16toh(s6->sin6_port),
255 be32toh(s6->sin6_flowinfo), be32toh(s6->sin6_scope_id));
256 break;
257
258 case AF_UNIX:
259 struct sockaddr_un *su = (struct sockaddr_un *) &ss;
260 sprintf(out, "unix/'%s'", su->sun_path);
261 break;
262
263 default:
264 bin2hex(out, &ss, sl);
265 break;
266 }
215 nd_decode_sockaddr(out, &ss, sl);
267 216
268 217 return sl; return sl;
269 218 } }
 
... ... static void decode_string_array(char *out, size_t out_size,
581 530 size_t rest = out_size; size_t rest = out_size;
582 531 char *add = ""; char *add = "";
583 532
584 strcpy(out, "");
533 if (out_size < 1)
534 return;
535
536 if (out_size < 3) {
537 strcpy(out, "");
538 return;
539 }
540
541 strcpy(out, "{");
585 542
586 543 while (1) { while (1) {
587 544 unsigned short len = decode16(d, i); unsigned short len = decode16(d, i);
 
... ... static void decode_string_array(char *out, size_t out_size,
592 549 bin2hex_ascii(e, d + *i, len); *i = *i + len; bin2hex_ascii(e, d + *i, len); *i = *i + len;
593 550
594 551 unsigned int e_len = strlen(e); unsigned int e_len = strlen(e);
595 if (e_len + 2 > rest) // 2 for ', '
552 if (2 + e_len + 2 > rest) // 2 for 2x"'" and 2 for ', ' or '}'
596 553 break; break;
597 554
598 555 strcat(out, add); strcat(out, add);
556
557 strcat(out, "'");
599 558 strcat(out, e); strcat(out, e);
559 strcat(out, "'");
560
600 561 add = ", "; add = ", ";
601 562 rest -= e_len + 2; rest -= e_len + 2;
602 563 } }
564
565 strcat(out, "}");
603 566 } }
604 567
605 568 static int decode_sqlite3_ret(char *out, unsigned out_size, static int decode_sqlite3_ret(char *out, unsigned out_size,
 
... ... static int decode_h_errno(char *out, const size_t out_size, unsigned char *d, un
800 763 case NO_DATA: snprintf(out, out_size, "NO_DATA"); break; case NO_DATA: snprintf(out, out_size, "NO_DATA"); break;
801 764 case NO_RECOVERY: snprintf(out, out_size, "NO_RECOVERY"); break; case NO_RECOVERY: snprintf(out, out_size, "NO_RECOVERY"); break;
802 765 case TRY_AGAIN: snprintf(out, out_size, "TRY_AGAIN"); break; case TRY_AGAIN: snprintf(out, out_size, "TRY_AGAIN"); break;
803 default: snprintf(out, out_size, "todd(%d)", ret);
766 default: snprintf(out, out_size, "todo(%d)", ret);
804 767 } }
805 768
806 769 return ret; return ret;
 
... ... static void decode_hostent(char *out, const size_t out_size, unsigned char *d, u
842 805 name, aliases, addrs); name, aliases, addrs);
843 806 } }
844 807
808 static int decode_whence(char *out, const size_t out_size, unsigned char *d, unsigned int *i)
809 {
810 int ret = decode32(d, i);
811
812 switch (ret) {
813 case SEEK_SET: snprintf(out, out_size, "SEEK_SET"); break;
814 case SEEK_CUR: snprintf(out, out_size, "SEEK_CUR"); break;
815 case SEEK_END: snprintf(out, out_size, "SEEK_END"); break;
816 case SEEK_DATA: snprintf(out, out_size, "SEEK_DATA"); break;
817 case SEEK_HOLE: snprintf(out, out_size, "SEEK_HOLE"); break;
818 default: snprintf(out, out_size, "todo(%d)", ret);
819 }
820
821 return ret;
822 }
823
845 824 static void decode_func(const uint32_t parent, unsigned char *d) static void decode_func(const uint32_t parent, unsigned char *d)
846 825 { {
847 826 unsigned int i = 0; unsigned int i = 0;
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
937 916 decode_ret_int(rest, sizeof(rest), d, &i); decode_ret_int(rest, sizeof(rest), d, &i);
938 917 sprintf(line, "(%d)%s", sock, rest); sprintf(line, "(%d)%s", sock, rest);
939 918 } }
919 } else if (strcmp(func, "curl_easy_cleanup") == 0) {
920 uint64_t handle = decode64(d, &i);
921 sprintf(line, "(0x%lx)", handle);
922 } else if (strcmp(func, "curl_easy_init") == 0) {
923 uint64_t handle = decode64(d, &i);
924 sprintf(line, "() = 0x%lx", handle);
925 } else if (strcmp(func, "curl_easy_perform") == 0) {
926 uint64_t handle = decode64(d, &i);
927 if (type == 'r') {
928 int ret = decode32(d, &i);
929 nd_decode_curl_code(rest, sizeof(rest), ret);
930 sprintf(line, "(0x%lx) = %s", handle, rest);
931 } else {
932 sprintf(line, "(0x%lx)", handle);
933 }
934 } else if (strcmp(func, "curl_easy_setopt") == 0) {
935 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
936 uint64_t handle = decode64(d, &i);
937 uint8_t type = decode8(d, &i);
938 uint8_t option_len = decode8(d, &i);
939 char option[option_len * 4 + 1];
940 bin2hex_ascii(option, d + i, option_len); i += option_len;
941 if ((type == 0) || (type == 2)) { // long
942 snprintf(rest, sizeof(rest), "%ld", decode64(d, &i));
943 } else if (type == 4) { // string
944 uint16_t len = decode16(d, &i);
945 char s[len * 4 + 1];
946 bin2hex_ascii(s, d + i, len); i += len;
947 snprintf(rest, sizeof(rest), "'%s'", s);
948 } else if (type == 5) { // slist
949 decode_string_array(rest, sizeof(rest), d, &i);
950 } else {
951 snprintf(rest, sizeof(rest), "%p", (void *) decode64(d, &i));
952 }
953 int ret = decode32(d, &i);
954 char sret[32];
955 nd_decode_curl_code(sret, sizeof(sret), ret);
956 sprintf(line, "(0x%lx, CURLOPT_%s, %s) = %s",
957 handle, option, rest, sret);
940 958 } break; } break;
941 959
942 960 case 'd': case 'd':
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
965 983 decode_string_array(envp, sizeof(envp), d, &i); decode_string_array(envp, sizeof(envp), d, &i);
966 984 if (type == 'r') if (type == 'r')
967 985 decode_ret_pointer(rest, sizeof(rest), d, &i); decode_ret_pointer(rest, sizeof(rest), d, &i);
968 sprintf(line, "('%s', {%s}, {%s})%s",
986 sprintf(line, "('%s', %s, %s)%s",
969 987 pathname, argv, envp, rest); pathname, argv, envp, rest);
970 988 } break; } break;
971 989
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1084 1102 int backlog = decode32(d, &i); int backlog = decode32(d, &i);
1085 1103 decode_ret_int(rest, sizeof(rest), d, &i); decode_ret_int(rest, sizeof(rest), d, &i);
1086 1104 sprintf(line, "(%d, %d)%s", sock, backlog, rest); sprintf(line, "(%d, %d)%s", sock, backlog, rest);
1105 } else if (strcmp(func, "lseek") == 0) {
1106 int fd = decode32(d, &i);
1107 int64_t off = decode64(d, &i);
1108 char whence[32];
1109 decode_whence(whence, sizeof(whence), d, &i);
1110 if (type == 'r')
1111 decode_ret_int64(rest, sizeof(rest), d, &i);
1112 sprintf(line, "(%d, %zd, %s)%s", fd, off, whence, rest);
1087 1113 } break; } break;
1088 1114
1089 1115 case 'm': case 'm':
1090 if (strcmp(func, "mysqli_autocommit") == 0) {
1116 if (strcmp(func, "memfd_create") == 0) {
1117 uint16_t len = decode16(d, &i);
1118 char name[len * 4 + 1];
1119 bin2hex_ascii(name, d + i, len); i += len;
1120 uint32_t flags = decode32(d, &i);
1121 char sflags[64];
1122 nd_decode_memfd_flags(sflags, sizeof(sflags), flags);
1123 if (type == 'r')
1124 decode_ret_int(rest, sizeof(rest), d, &i);
1125 sprintf(line, "('%s', %s)%s", name, sflags, rest);
1126 } else if (strcmp(func, "mysqli_autocommit") == 0) {
1091 1127 uint64_t link = decode64(d, &i); uint64_t link = decode64(d, &i);
1092 1128 uint8_t value = decode8(d, &i); uint8_t value = decode8(d, &i);
1093 1129 if (type == 'r') if (type == 'r')
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1403 1439 } break; } break;
1404 1440
1405 1441 case 'r': case 'r':
1406 if (strcmp(func, "recv") == 0) {
1442 if (strcmp(func, "read") == 0) {
1443 int fd = decode32(d, &i);
1444 size_t count = decode64(d, &i);
1445 sprintf(rest, ", %zu)", count);
1446 if (type == 'c') {
1447 sprintf(line, "(%d, buf%s", fd, rest);
1448 } else if (type == 'r') {
1449 ssize_t ret = decode_ret_int64(rest, sizeof(rest), d, &i);
1450 if (ret != -1) {
1451 unsigned short max = decode16(d, &i);
1452 char data[max * 4 + 1];
1453 bin2hex_ascii(data, d + i, max); i += max;
1454 sprintf(line, "(%d, '%s'%s)%s",
1455 fd, data,
1456 max < ret ? "..." : "", rest);
1457 } else {
1458 sprintf(line, "(%d)%s", fd, rest);
1459 }
1460 }
1461 } else if (strcmp(func, "recv") == 0) {
1407 1462 int sock = decode32(d, &i); int sock = decode32(d, &i);
1408 1463 size_t len = decode64(d, &i); size_t len = decode64(d, &i);
1409 1464 int flags = decode32(d, &i); int flags = decode32(d, &i);
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1509 1564 int xtype = decode32(d, &i); int xtype = decode32(d, &i);
1510 1565 int xprotocol = decode32(d, &i); int xprotocol = decode32(d, &i);
1511 1566 decode_ret_int(rest, sizeof(rest), d, &i); decode_ret_int(rest, sizeof(rest), d, &i);
1512 sprintf(line, "(%s, %s, %d)%s",
1513 decode_socket_domain(xdomain),
1514 decode_socket_type(xtype), xprotocol, rest);
1567 char dom[32], type[32];
1568 nd_decode_socket_domain(dom, sizeof(dom), xdomain);
1569 nd_decode_socket_type(type, sizeof(type), xtype);
1570 sprintf(line, "(%s, %s, %d)%s", dom, type, xprotocol, rest);
1571 // todo: why I do not decode protocol?!
1515 1572 } else if (strcmp(func, "sqlite3_bind_double") == 0) { } else if (strcmp(func, "sqlite3_bind_double") == 0) {
1516 1573 uint64_t stmt = decode64(d, &i); uint64_t stmt = decode64(d, &i);
1517 1574 int index = decode32(d, &i); int index = decode32(d, &i);
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1618 1675 sprintf(line, "(%s, '%s')", sprio, data); sprintf(line, "(%s, '%s')", sprio, data);
1619 1676 } break; } break;
1620 1677
1678 case 't':
1679 if (strcmp(func, "timerfd_create") == 0) {
1680 int clockid = decode32(d, &i);
1681 int flags = decode32(d, &i);
1682 char sclock[32], sflags[64];
1683 nd_decode_clockid(sclock, sizeof(sclock), clockid);
1684 nd_decode_timerfd_flags(sflags, sizeof(sflags), flags);
1685 if (type == 'r')
1686 decode_ret_int(rest, sizeof(rest), d, &i);
1687 sprintf(line, "(%s, %s)%s", sclock, sflags, rest);
1688 } break;
1689
1621 1690 case 'u': case 'u':
1622 1691 if (strcmp(func, "unlink") == 0) { if (strcmp(func, "unlink") == 0) {
1623 1692 uint16_t len = decode16(d, &i); uint16_t len = decode16(d, &i);
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/catalinux/ninedogs

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/catalinux/ninedogs

Clone this repository using git:
git clone git://git.rocketgit.com/user/catalinux/ninedogs

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main