List of commits:
Subject Hash Author Date (UTC)
More curl tracing info 04013af7a216e6cf7f363b3895ffcebe78859a65 Catalin(ux) M. BOIE 2022-12-09 17:45:46
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
Commit 04013af7a216e6cf7f363b3895ffcebe78859a65 - More curl tracing info
Author: Catalin(ux) M. BOIE
Author date (UTC): 2022-12-09 17:45
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2022-12-09 17:45
Parent(s): c374ad15d2d5548d168084c0e8506929803e9bf0
Signer:
Signing key:
Signing status: N
Tree: d66ae7b541d4b726cafb648b536b7cf38897080e
File Lines added Lines deleted
TODO 2 1
agent/Makefile 11 5
agent/curl.TODO 11 3
agent/curl.c 149 12
agent/curl.h 1 0
agent/decode.c 12 0
agent/ninedogs.c 84 35
agent/php.c 288 12
agent/process_core.c 2 0
agent/process_url.c 297 0
agent/process_url.h 25 0
common/ids.h 31 1
common/tools.c 1 0
test/curl/.gitignore 3 0
test/curl/1.c 3 1
test/curl/1b.c 3 1
test/curl/1b.run 16 0
test/curl/1c.c 3 1
test/curl/1c.run 16 0
test/curl/2.php 19 0
test/curl/2.run 3 5
test/curl/3.php 21 0
test/curl/3.run 3 5
trace/Makefile 2 1
trace/TODO 2 5
trace/nd-trace.c 202 67
File TODO changed (mode: 100644) (index 3dbb04c..fb26266)
2 2 [ ] Seems curl is taking over SEGV handling. Prevent that, but allow the handler to be called. [ ] Seems curl is taking over SEGV handling. Prevent that, but allow the handler to be called.
3 3 [ ] [ ]
4 4
5 == Non-urgent
6 5
6 == Non-urgent
7 7 [ ] Both client and server side are free (AGPLv3). [ ] Both client and server side are free (AGPLv3).
8 8 Offering this as a SaaS may bring some money to support Offering this as a SaaS may bring some money to support
9 9 the development. the development.
10 10 [ ] Figure out what to do with SELinux/AppArmor. [ ] Figure out what to do with SELinux/AppArmor.
11 11 [ ] We can easily provide a vault service by hijacking getenv [ ] We can easily provide a vault service by hijacking getenv
12 12 And providing a filesystem. And providing a filesystem.
13 [ ] We can act also as a vault (both env vars and filesystem).
13 14 [ ] [ ]
14 15
15 16
File agent/Makefile changed (mode: 100644) (index c78f0f3..93de780)
... ... COMMON_H += ../common/ids.h ../common/tools.h ../common/decode_text.h \
9 9 CFLAGS += -I../common CFLAGS += -I../common
10 10
11 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 \
12 process_db.o process_ssl.o openssl.o gnutls.o text2process.o \
12 process_db.o process_ssl.o process_url.o \
13 openssl.o gnutls.o text2process.o \
13 14 python.o curl.o \ python.o curl.o \
14 15 ../common/tools.o ../common/info.o ../common/decode_text.o ../common/tools.o ../common/info.o ../common/decode_text.o
15 16
16 decode.o: decode.c decode.h process_db.h $(COMMON_H)
17 decode.o: decode.c decode.h process_db.h process_url.h $(COMMON_H)
17 18 $(CC) $(CFLAGS) -fPIC -c -o $@ $< $(CC) $(CFLAGS) -fPIC -c -o $@ $<
18 19
19 20 ctools.o: ctools.c $(COMMON_H) ../common/tools.h ctools.o: ctools.c $(COMMON_H) ../common/tools.h
20 21 $(CC) $(CFLAGS) -fPIC -c -o $@ $< $(CC) $(CFLAGS) -fPIC -c -o $@ $<
21 22
22 php.o: php.c php.h process_db.h $(COMMON_H)
23 php.o: php.c php.h process_db.h process_url.h $(COMMON_H)
23 24 $(CC) $(CFLAGS) -fPIC -c -o $@ $< $(CC) $(CFLAGS) -fPIC -c -o $@ $<
24 25
25 26 curl.o: curl.c curl.h $(COMMON_H) curl.o: curl.c curl.h $(COMMON_H)
 
... ... gnutls.o: gnutls.c gnutls.h process_ssl.h $(COMMON_H)
37 38 process.o: process.c process.h $(COMMON_H) process.o: process.c process.h $(COMMON_H)
38 39 $(CC) $(CFLAGS) -fPIC -c -o $@ $< $(CC) $(CFLAGS) -fPIC -c -o $@ $<
39 40
40 process_core.o: process_core.c process_core.h $(COMMON_H)
41 process_core.o: process_core.c process_core.h \
42 process_db.h process_misc.h process_ssl.h process_url.h $(COMMON_H)
41 43 $(CC) $(CFLAGS) -fPIC -c -o $@ $< $(CC) $(CFLAGS) -fPIC -c -o $@ $<
42 44
43 45 process_misc.o: process_misc.c process_misc.h $(COMMON_H) process_misc.o: process_misc.c process_misc.h $(COMMON_H)
 
... ... process_misc.o: process_misc.c process_misc.h $(COMMON_H)
46 48 process_db.o: process_db.c process_db.h $(COMMON_H) process_db.o: process_db.c process_db.h $(COMMON_H)
47 49 $(CC) $(CFLAGS) -fPIC -c -o $@ $< $(CC) $(CFLAGS) -fPIC -c -o $@ $<
48 50
51 process_url.o: process_url.c process_url.h $(COMMON_H)
52 $(CC) $(CFLAGS) -fPIC -c -o $@ $<
53
49 54 process_ssl.o: process_ssl.c process_ssl.h $(COMMON_H) process_ssl.o: process_ssl.c process_ssl.h $(COMMON_H)
50 55 $(CC) $(CFLAGS) -fPIC -c -o $@ $< $(CC) $(CFLAGS) -fPIC -c -o $@ $<
51 56
 
... ... ninedogs_dlsym_env.so: ninedogs_dlsym_env.c
58 63 ninedogs_dlsym_func.so: ninedogs_dlsym_func.c ninedogs_dlsym_func.so: ninedogs_dlsym_func.c
59 64 $(CC) $(CFLAGSSO) -Wl,-soname,ninedogs_dlsym_func.so -o $@ $< $(CC) $(CFLAGSSO) -Wl,-soname,ninedogs_dlsym_func.so -o $@ $<
60 65
61 ninedogs.so: ninedogs.c $(OBJS) $(COMMON_H) ../common/shared.h curl.h
66 ninedogs.so: ninedogs.c $(OBJS) $(COMMON_H) ../common/shared.h curl.h \
67 process_db.h process_url.h
62 68 $(CC) $(CFLAGS) $(CFLAGSSO) -Wl,-soname,ninedogs.so -o $@ ninedogs.c \ $(CC) $(CFLAGS) $(CFLAGSSO) -Wl,-soname,ninedogs.so -o $@ ninedogs.c \
63 69 $(OBJS) $(LIBS) $(GNUTLS_LIBS) $(OBJS) $(LIBS) $(GNUTLS_LIBS)
64 70
File agent/curl.TODO changed (mode: 100644) (index bb2c060..db4a7f6)
1 [ ] Decode slist
2 [ ] Call 'getinfo'; after perform to log details?
1 [ ] We are not using process_url stuff!
2 [ ] Call 'getinfo' to log details?
3 Yes, we should!
3 4 [ ] What about blobs? [ ] What about blobs?
4 [ ]
5 [ ] We must not store all URLs. Can be a lot.
6 Just register the most expensive.
7 [ ] Before 'perform', we need to log POSTFIELDS if what we logged was not ok
8 (body containing multiple '\0'.
9 [ ] There is another option to set POST data with copy? What to do about it?
10 [ ] Intercept curl_easy_duphandle
11 [ ] Intercept curl_easy_reset
12 [ ]
File agent/curl.c changed (mode: 100644) (index 3dbb5c4..ebfc058)
1 #include <unistd.h>
1 2 #include <stdarg.h> #include <stdarg.h>
3 #include <errno.h>
4 #include <string.h>
2 5
3 6 #include "curl.h" #include "curl.h"
4 7
8 extern void *(*old_malloc)(size_t size);
5 9 extern void xlog(const unsigned int level, const char *format, ...); extern void xlog(const unsigned int level, const char *format, ...);
6 10 extern void *ninedogs_dlsym(const char *sym); extern void *ninedogs_dlsym(const char *sym);
7 11 extern void my_trace(const char *func, const char type, ...); extern void my_trace(const char *func, const char type, ...);
8 12
9 13
14 // Track setopt stuff
15 struct curl_track
16 {
17 CURL *handle;
18 long post_data_len;
19 void *post_data;
20 struct curl_track *next;
21 };
22 static __thread struct curl_track *curl_tracks[32];
23
24 static struct curl_track *curl_track_find(CURL *handle)
25 {
26 struct curl_track *q;
27
28 int k = ((unsigned long) handle >> 32) % 32;
29 q = curl_tracks[k];
30 while (q) {
31 if (q->handle == handle)
32 return q;
33 q = q->next;
34 }
35
36 return NULL;
37 }
38
39 static struct curl_track *curl_track_add(CURL *handle)
40 {
41 int save_errno;
42 struct curl_track *q;
43
44 int k = ((unsigned long) handle >> 32) % 32;
45 q = curl_tracks[k];
46 while (q) {
47 if (q->handle == NULL)
48 break;
49 q = q->next;
50 }
51
52 if (!q) {
53 save_errno = errno;
54 q = old_malloc(sizeof(struct curl_track));
55 errno = save_errno;
56 if (!q)
57 return NULL;
58 memset(q, 0, sizeof(struct curl_track));
59 q->next = curl_tracks[k];
60 curl_tracks[k] = q;
61 }
62
63 q->handle = handle;
64 q->post_data_len = -1;
65 q->post_data= NULL;
66
67 return q;
68 }
69
70 static void curl_track_del(CURL *handle)
71 {
72 struct curl_track *q;
73
74 int k = ((unsigned long) handle >> 32) % 32;
75 q = curl_tracks[k];
76 while (q) {
77 if (q->handle == NULL) {
78 q->handle = NULL;
79 break;
80 }
81 q = q->next;
82 }
83 }
84
10 85 static const struct my_curl_easyoption *(*old_curl_easy_option_by_id)(CURLoption id); static const struct my_curl_easyoption *(*old_curl_easy_option_by_id)(CURLoption id);
11 86 const struct my_curl_easyoption *curl_easy_option_by_id(CURLoption id) const struct my_curl_easyoption *curl_easy_option_by_id(CURLoption id)
12 87 { {
 
... ... const struct my_curl_easyoption *curl_easy_option_by_id(CURLoption id)
16 91 return old_curl_easy_option_by_id(id); return old_curl_easy_option_by_id(id);
17 92 } }
18 93
94 static const struct my_curl_easyoption *(*old_curl_easy_option_next)(const struct my_curl_easyoption *);
95 const struct my_curl_easyoption *curl_easy_option_next(const struct my_curl_easyoption *prev)
96 {
97 if (!old_curl_easy_option_next)
98 old_curl_easy_option_next = ninedogs_dlsym("curl_easy_option_next");
99
100 return old_curl_easy_option_next(prev);
101 }
102
19 103 static CURL *(*old_curl_easy_init)(void); static CURL *(*old_curl_easy_init)(void);
20 104 CURL *curl_easy_init(void) CURL *curl_easy_init(void)
21 105 { {
 
... ... CURLcode curl_easy_setopt(CURL *handle, CURLoption option, ...)
34 118 { {
35 119 va_list va; va_list va;
36 120 CURLcode ret; CURLcode ret;
121 struct curl_track *q = NULL;
122 long a;
37 123
38 124 if (!old_curl_easy_setopt) if (!old_curl_easy_setopt)
39 125 old_curl_easy_setopt = ninedogs_dlsym("curl_easy_setopt"); old_curl_easy_setopt = ninedogs_dlsym("curl_easy_setopt");
 
... ... CURLcode curl_easy_setopt(CURL *handle, CURLoption option, ...)
42 128 if (!oi) if (!oi)
43 129 return 43; // CURLE_BAD_FUNCTION_ARGUMENT return 43; // CURLE_BAD_FUNCTION_ARGUMENT
44 130
45 xlog(100, " DEBUG: option %d name=[%s] type=%d\n",
131 xlog(100, " DEBUG: setopt %d name=[%s] type=%d (3=obj, 4=str)\n",
46 132 option, oi->name, oi->type); option, oi->name, oi->type);
47 133
48 va_start(va, option);
134 #if 0
49 135 switch (oi->type) { switch (oi->type) {
50 136 case 0: // long 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 137 case 1: // values case 1: // values
138 case 2: // off_t
58 139 case 3: // object case 3: // object
59 140 case 4: // string case 4: // string
60 141 case 5: // slist case 5: // slist
 
... ... CURLcode curl_easy_setopt(CURL *handle, CURLoption option, ...)
62 143 case 7: // blob case 7: // blob
63 144 case 8: // function case 8: // function
64 145 default: 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 146 break; break;
69 147 } }
148 #endif
149 va_start(va, option);
150 a = va_arg(va, long);
70 151 va_end(va); va_end(va);
71 xlog(100, "%s: ret=%d\n", __func__, ret);
152
153 long len = -1;
154 if ((oi->type == 3) || (oi->type == 4)) // object or string
155 len = strlen((char *) a);
156
157 ret = old_curl_easy_setopt(handle, option, a);
158 xlog(100, "%s: old returned ret=%d\n", __func__, ret);
159
160 q = curl_track_find(handle);
161 if (!q)
162 q = curl_track_add(handle);
163
164 do {
165 if (!q)
166 break;
167
168 // If size was defined, we can log whole post fields.
169 // If not, we will postpone till before 'perform'.
170 if (option == 60) { // CURLOPT_POSTFIELDSSIZE
171 q->post_data_len = a;
172 xlog(101, " DEBUG: post_data_len set to %ld!\n", q->post_data_len);
173 break;
174 }
175
176 if (option == 10015) { // CURLOPT_POSTFIELDS
177 if (q->post_data_len == -1) {
178 q->post_data = (void *) a;
179 len = -1;
180 xlog(101, " DEBUG: size was not defined! Delay dump.\n");
181 } else {
182 len = q->post_data_len;
183 q->post_data_len = -2; // to not log it again in 'perform'
184 xlog(101, " DEBUG: size was defined! We can dump here (below).\n");
185 }
186 }
187 } while (0);
188
189 my_trace(__func__, 'R', handle, oi->type, oi->name, len, a, ret);
72 190
73 191 return ret; return ret;
74 192 } }
 
... ... CURLcode curl_easy_perform(CURL *handle)
79 197 if (!old_curl_easy_perform) if (!old_curl_easy_perform)
80 198 old_curl_easy_perform = ninedogs_dlsym("curl_easy_perform"); old_curl_easy_perform = ninedogs_dlsym("curl_easy_perform");
81 199
200 struct curl_track *q = curl_track_find(handle);
201 while (q && q->post_data) {
202 if (q->post_data_len == -2) // we did the dump already
203 break;
204
205 if (q->post_data_len == -1) { // no len set, assume '\0' string
206 xlog(101, " DEBUG: %s: no len set, assume zero terminated string, as meta!\n", __func__);
207 q->post_data_len = strlen(q->post_data);
208 } else { // user set the len after data
209 xlog(101, " DEBUG: %s: we need to log post data as meta!\n", __func__);
210 }
211 my_trace(__func__, 'm', "POSTFIELDS", handle, q->post_data,
212 q->post_data_len);
213 break;
214 }
215
82 216 my_trace(__func__, 'c', handle); my_trace(__func__, 'c', handle);
83 217 CURLcode ret = old_curl_easy_perform(handle); CURLcode ret = old_curl_easy_perform(handle);
84 218 my_trace(__func__, 'r', handle, ret); my_trace(__func__, 'r', handle, ret);
 
... ... void curl_easy_cleanup(CURL *handle)
93 227 if (!old_curl_easy_cleanup) if (!old_curl_easy_cleanup)
94 228 old_curl_easy_cleanup = ninedogs_dlsym("curl_easy_cleanup"); old_curl_easy_cleanup = ninedogs_dlsym("curl_easy_cleanup");
95 229
230 curl_track_del(handle);
231
96 232 old_curl_easy_cleanup(handle); old_curl_easy_cleanup(handle);
97 233 my_trace(__func__, 'R', handle); my_trace(__func__, 'R', handle);
98 234 } }
235
File agent/curl.h changed (mode: 100644) (index 06fc52d..777bd65)
... ... struct my_curl_slist
18 18 }; };
19 19
20 20 const struct my_curl_easyoption *curl_easy_option_by_id(CURLoption id); const struct my_curl_easyoption *curl_easy_option_by_id(CURLoption id);
21 const struct my_curl_easyoption *curl_easy_option_next(const struct my_curl_easyoption *prev);
21 22 CURL *curl_easy_init(void); CURL *curl_easy_init(void);
22 23 CURLcode curl_easy_setopt(CURL *handle, CURLoption option, ...); CURLcode curl_easy_setopt(CURL *handle, CURLoption option, ...);
23 24 CURLcode curl_easy_perform(CURL *handle); CURLcode curl_easy_perform(CURL *handle);
File agent/decode.c changed (mode: 100644) (index f68c2bd..8d8f1ac)
5 5 #include "../common/tools.h" #include "../common/tools.h"
6 6 #include "decode.h" #include "decode.h"
7 7 #include "process_db.h" #include "process_db.h"
8 #include "process_url.h"
8 9
9 10
10 11 extern void xlog(const unsigned int level, const char *format, ...); extern void xlog(const unsigned int level, const char *format, ...);
 
... ... unsigned int decode_server_message(const void *buf, const unsigned int len)
67 68 unsigned int r = unpack(hash, 'b', sizeof(hash), ibuf, ioff, &off); unsigned int r = unpack(hash, 'b', sizeof(hash), ibuf, ioff, &off);
68 69 if (r < 0xFFFFFFF0) if (r < 0xFFFFFFF0)
69 70 query_send_string(hash); query_send_string(hash);
71 } else if (type == NINEDOGS_NET_URL_STRING) {
72 unsigned char hash[32];
73
74 if (ibuf[off++] != 'h') {
75 xlog(1, " ibuf[off] != 'h'\n", ibuf[off - 1]);
76 ioff = 0;
77 return 1;
78 }
79 unsigned int r = unpack(hash, 'b', sizeof(hash), ibuf, ioff, &off);
80 if (r < 0xFFFFFFF0)
81 url_send_string(hash);
70 82 } else { } else {
71 83 xlog(10, " unknown type 0x%08x\n", type); xlog(10, " unknown type 0x%08x\n", type);
72 84 } }
File agent/ninedogs.c changed (mode: 100644) (index a54b4da..d1a322b)
50 50 #include "ctools.h" #include "ctools.h"
51 51 #include "process_core.h" #include "process_core.h"
52 52 #include "process_db.h" #include "process_db.h"
53 #include "process_url.h"
53 54 #include "text2process.h" #include "text2process.h"
54 55 #include "shared.h" #include "shared.h"
55 56 #include "info.h" #include "info.h"
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
448 449 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle
449 450 } else if (strcmp(func, "curl_easy_init") == 0) { } else if (strcmp(func, "curl_easy_init") == 0) {
450 451 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle
452 } else if (strcmp(func, "curl_init") == 0) { // php
453 struct nd_url *u = va_arg(va, struct nd_url *);
454 my_trace_put64(buf, &i, (uint64_t) u->handle);
455 my_trace_put16(buf, &i, u->url_len);
456 my_trace_put(buf, &i, u->url, u->url_len);
457 } else if (strcmp(func, "curl_exec") == 0) { // php
458 struct nd_url *u = va_arg(va, struct nd_url *);
459 my_trace_put64(buf, &i, (uint64_t) u->handle);
460 if (type == 'r') {
461 my_trace_put_bool(buf, &i, u->ret);
462 if (u->ret == 2) {
463 my_trace_put16(buf, &i, u->sret_len);
464 my_trace_put(buf, &i, u->sret, u->sret_len);
465 }
466 }
451 467 } else if (strcmp(func, "curl_easy_perform") == 0) { } else if (strcmp(func, "curl_easy_perform") == 0) {
452 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle
468 if (type == 'm') {
469 char *info = va_arg(va, char *);
470 unsigned char len = strlen(info);
471 my_trace_put8(buf, &i, len);
472 my_trace_put(buf, &i, info, len);
473 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle
474 void *p = va_arg(va, void *);
475 long p_len = va_arg(va, long);
476 if (p_len > 64000) p_len = 64000;
477 my_trace_put16(buf, &i, p_len);
478 my_trace_put(buf, &i, p, p_len);
479 } else {
480 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle
481 if (type == 'r')
482 my_trace_put32(buf, &i, va_arg(va, int)); // ret
483 }
484 } else if (strcmp(func, "curl_setopt") == 0) { // php
485 struct nd_url *u = va_arg(va, struct nd_url *);
486 my_trace_put64(buf, &i, (uint64_t) u->handle);
487 uint8_t oplen = strlen(u->op);
488 my_trace_put8(buf, &i, oplen);
489 my_trace_put(buf, &i, u->op, oplen);
490 my_trace_put(buf, &i, u->op_value, u->op_value_len);
453 491 if (type == 'r') if (type == 'r')
454 my_trace_put32(buf, &i, va_arg(va, int)); // ret
492 my_trace_put_bool(buf, &i, u->ret);
455 493 } else if (strcmp(func, "curl_easy_setopt") == 0) { } else if (strcmp(func, "curl_easy_setopt") == 0) {
456 494 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle
457 495 uint8_t type = va_arg(va, int); uint8_t type = va_arg(va, int);
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
460 498 uint8_t option_len = strlen(option); uint8_t option_len = strlen(option);
461 499 my_trace_put8(buf, &i, option_len); my_trace_put8(buf, &i, option_len);
462 500 my_trace_put(buf, &i, option, option_len); 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);
501 if ((type == 0) || (type == 2)) { // long
502 va_arg(va, long); // ignore len
503 my_trace_put64(buf, &i, va_arg(va, long)); // a
504 } else if ((type == 3) || (type == 4)) { // object or string
505 long len = va_arg(va, long);
506 my_trace_put64(buf, &i, len);
507 if (len >= 0) {
508 char *s = va_arg(va, char *);
509 if (!s) {
510 my_trace_put16(buf, &i, 0);
511 } else {
512 uint16_t len = strlen(s);
513 my_trace_put16(buf, &i, len);
514 my_trace_put(buf, &i, s, len);
515 }
516 } else {
517 va_arg(va, long); // ignore 'a'
518 }
471 519 } else if (type == 5) { // slist } else if (type == 5) { // slist
472 struct my_curl_slist *q, *q0 = va_arg(va, struct my_curl_slist *);
473 q = q0;
520 va_arg(va, long); // ignore len
521 struct my_curl_slist *q = va_arg(va, struct my_curl_slist *);
474 522 while (q) { while (q) {
475 523 uint16_t len = strlen(q->data); uint16_t len = strlen(q->data);
476 524 my_trace_put16(buf, &i, len); my_trace_put16(buf, &i, len);
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
479 527 } }
480 528 my_trace_put16(buf, &i, 0); my_trace_put16(buf, &i, 0);
481 529 } else { } else {
482 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *));
530 va_arg(va, long); // ignore len
531 my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // pointer
483 532 } }
484 my_trace_put32(buf, &i, va_arg(va, int)); // ret
533 //my_trace_put32(buf, &i, va_arg(va, int)); // ret
534 int ret = va_arg(va, int);
535 my_trace_put32(buf, &i, ret);
536 xlog(100, "%s: DEBUG: option=[%s] type=%hhu ret=%d\n",
537 __func__, option, type, ret);
485 538 } break; } break;
486 539
487 540 case 'd': case 'd':
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
739 792 for (unsigned short j = 0; j < e->params.len; j++) { for (unsigned short j = 0; j < e->params.len; j++) {
740 793 struct params_array_one *pa = &e->params.list[j]; struct params_array_one *pa = &e->params.list[j];
741 794 my_trace_put8(buf, &i, pa->type); my_trace_put8(buf, &i, pa->type);
742 if (pa->type == ND_PARAMS_TYPE_LONG) {
795 if (pa->type == ND_TYPE_LONG) {
743 796 my_trace_put64(buf, &i, pa->l); my_trace_put64(buf, &i, pa->l);
744 } else if (pa->type == ND_PARAMS_TYPE_DOUBLE) {
797 } else if (pa->type == ND_TYPE_DOUBLE) {
745 798 my_trace_put_double(buf, &i, pa->d); my_trace_put_double(buf, &i, pa->d);
746 } else if (pa->type == ND_PARAMS_TYPE_STRING) {
799 } else if (pa->type == ND_TYPE_STRING) {
747 800 my_trace_put16(buf, &i, pa->length); my_trace_put16(buf, &i, pa->length);
748 801 my_trace_put(buf, &i, pa->str, pa->length); my_trace_put(buf, &i, pa->str, pa->length);
749 802 } }
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
925 978 for (unsigned short j = 0; j < q->params.len; j++) { for (unsigned short j = 0; j < q->params.len; j++) {
926 979 struct params_array_one *pa = &q->params.list[j]; struct params_array_one *pa = &q->params.list[j];
927 980 my_trace_put8(buf, &i, pa->type); my_trace_put8(buf, &i, pa->type);
928 if (pa->type == ND_PARAMS_TYPE_LONG) {
981 if (pa->type == ND_TYPE_LONG) {
929 982 my_trace_put64(buf, &i, pa->l); my_trace_put64(buf, &i, pa->l);
930 } else if (pa->type == ND_PARAMS_TYPE_DOUBLE) {
983 } else if (pa->type == ND_TYPE_DOUBLE) {
931 984 my_trace_put_double(buf, &i, pa->d); my_trace_put_double(buf, &i, pa->d);
932 } else if (pa->type == ND_PARAMS_TYPE_STRING) {
985 } else if (pa->type == ND_TYPE_STRING) {
933 986 my_trace_put16(buf, &i, pa->length); my_trace_put16(buf, &i, pa->length);
934 987 my_trace_put(buf, &i, pa->str, pa->length); my_trace_put(buf, &i, pa->str, pa->length);
935 988 } }
 
... ... static unsigned int my_trace_encode(unsigned char *buf,
1063 1116 } }
1064 1117 } else if (strcmp(func, "setsockopt") == 0) { } else if (strcmp(func, "setsockopt") == 0) {
1065 1118 my_trace_put32(buf, &i, va_arg(va, int)); // sock my_trace_put32(buf, &i, va_arg(va, int)); // sock
1066 if (type == 'c') {
1067 my_trace_put32(buf, &i, va_arg(va, int)); // level
1068 my_trace_put32(buf, &i, va_arg(va, int)); // optname
1069 socklen_t optlen = va_arg(va, socklen_t);
1070 my_trace_put32(buf, &i, optlen);
1071 const void *optval = va_arg(va, void *);
1072 my_trace_put(buf, &i, optval, optlen);
1073 } else {
1074 int ret = va_arg(va, int);
1075 my_trace_put32(buf, &i, ret);
1076 if (ret == -1)
1077 my_trace_put32(buf, &i, save_errno);
1078 }
1119 my_trace_put32(buf, &i, va_arg(va, int)); // level
1120 my_trace_put32(buf, &i, va_arg(va, int)); // optname
1121 socklen_t optlen = va_arg(va, socklen_t);
1122 my_trace_put32(buf, &i, optlen);
1123 const void *optval = va_arg(va, void *);
1124 my_trace_put(buf, &i, optval, optlen);
1125 int ret = va_arg(va, int);
1126 my_trace_put32(buf, &i, ret);
1127 if (ret == -1)
1128 my_trace_put32(buf, &i, save_errno);
1079 1129 } else if (strcmp(func, "socket") == 0) { } else if (strcmp(func, "socket") == 0) {
1080 1130 my_trace_put32(buf, &i, va_arg(va, int)); // domain my_trace_put32(buf, &i, va_arg(va, int)); // domain
1081 1131 my_trace_put32(buf, &i, va_arg(va, int)); // type my_trace_put32(buf, &i, va_arg(va, int)); // type
 
... ... int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
2037 2087 int setsockopt(int sockfd, int level, int optname, const void *optval, int setsockopt(int sockfd, int level, int optname, const void *optval,
2038 2088 socklen_t optlen) socklen_t optlen)
2039 2089 { {
2040 my_trace(__func__, 'c', sockfd, level, optname, optlen, optval);
2041 2090 int ret = old_setsockopt(sockfd, level, optname, optval, optlen); int ret = old_setsockopt(sockfd, level, optname, optval, optlen);
2042 my_trace(__func__, 'r', sockfd, ret);
2091 my_trace(__func__, 'R', sockfd, level, optname, optlen, optval, ret);
2043 2092
2044 2093 return ret; return ret;
2045 2094 } }
File agent/php.c changed (mode: 100644) (index c52cd55..b6613e0)
43 43 #include "tools.h" #include "tools.h"
44 44 #include "ctools.h" #include "ctools.h"
45 45 #include "process_db.h" #include "process_db.h"
46 #include "process_url.h"
47 #include "curl.h"
46 48
47 49
48 50 extern void *(*old_malloc)(size_t size); extern void *(*old_malloc)(size_t size);
 
... ... static void php_zed_dump(const char *prefix, struct zend_execute_data *p)
319 321 } }
320 322 } }
321 323
324 // TODO this is really not related to parameters - rename it
325 // this is obsolete. Use 'zend_to_binary'
322 326 static void zend_array_to_params_array(struct params_array *p, struct zend_array *za) static void zend_array_to_params_array(struct params_array *p, struct zend_array *za)
323 327 { {
324 328 unsigned int i = 0; unsigned int i = 0;
325 329
326 xlog(100, " nTableMask=0x%x nNumUsed=%u nNumOfElements=%u nTableSize=%u"
330 xlog(100, " %s: nTableMask=0x%x nNumUsed=%u nNumOfElements=%u nTableSize=%u"
327 331 " nInternalPointer=%u flags=0x%x[%s]\n", " nInternalPointer=%u flags=0x%x[%s]\n",
332 __func__,
328 333 za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize, za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize,
329 334 za->nInternalPointer, za->u.flags, za->u.flags & 4 ? "packed" : ""); za->nInternalPointer, za->u.flags, za->u.flags & 4 ? "packed" : "");
330 335
 
... ... static void zend_array_to_params_array(struct params_array *p, struct zend_array
354 359 bs, bs->h, zs, php_get_type(_z), php_get_value(_z)); bs, bs->h, zs, php_get_type(_z), php_get_value(_z));
355 360
356 361 if (_z->u1.v.type == 1) { if (_z->u1.v.type == 1) {
357 p->list[i].type = ND_PARAMS_TYPE_NULL;
362 p->list[i].type = ND_TYPE_NULL;
358 363 } else if (_z->u1.v.type == 2) { } else if (_z->u1.v.type == 2) {
359 p->list[i].type = ND_PARAMS_TYPE_STRING;
364 p->list[i].type = ND_TYPE_STRING;
360 365 p->list[i].str = "false"; p->list[i].str = "false";
361 366 p->list[i].length = 5; p->list[i].length = 5;
362 367 } else if (_z->u1.v.type == 3) { } else if (_z->u1.v.type == 3) {
363 p->list[i].type = ND_PARAMS_TYPE_STRING;
368 p->list[i].type = ND_TYPE_STRING;
364 369 p->list[i].str = "true"; p->list[i].str = "true";
365 370 p->list[i].length = 4; p->list[i].length = 4;
366 371 } else if (_z->u1.v.type == 4) { } else if (_z->u1.v.type == 4) {
367 p->list[i].type = ND_PARAMS_TYPE_LONG;
372 p->list[i].type = ND_TYPE_LONG;
368 373 p->list[i].l = _z->value.lval; p->list[i].l = _z->value.lval;
369 374 } else if (_z->u1.v.type == 5) { } else if (_z->u1.v.type == 5) {
370 p->list[i].type = ND_PARAMS_TYPE_DOUBLE;
375 p->list[i].type = ND_TYPE_DOUBLE;
371 376 p->list[i].d = _z->value.dval; p->list[i].d = _z->value.dval;
372 377 } else if (_z->u1.v.type == 6) { } else if (_z->u1.v.type == 6) {
373 p->list[i].type = ND_PARAMS_TYPE_STRING;
378 p->list[i].type = ND_TYPE_STRING;
374 379 struct zend_string *zs = _z->value.str; struct zend_string *zs = _z->value.str;
375 380 p->list[i].str = zs->val; p->list[i].str = zs->val;
376 381 p->list[i].length = zs->len; p->list[i].length = zs->len;
377 382 } else { } else {
378 p->list[i].type = ND_PARAMS_TYPE_NULL;
379 xlog(1, " I do not how to encode this type!\n");
383 p->list[i].type = ND_TYPE_NULL;
384 xlog(1, " %s: I do not how to encode %d type! Encode as NULL\n",
385 __func__, _z->u1.v.type);
380 386 } }
381 387
382 388 i++; i++;
 
... ... static void zend_array_to_params_array(struct params_array *p, struct zend_array
385 391 } }
386 392 } }
387 393
394 static unsigned int zend_simple_to_binary(unsigned char *out, const size_t out_size,
395 struct zval *z)
396 {
397 unsigned int off = 0;
398 uint16_t u16;
399 uint64_t u64;
400
401 if (off + 1 + 8 > out_size) // 1+8 for a long
402 return 0;
403
404 if (z->u1.v.type == 1) {
405 out[off++] = ND_TYPE_NULL;
406 } else if (z->u1.v.type == 2) {
407 out[off++] = ND_TYPE_FALSE;
408 } else if (z->u1.v.type == 3) {
409 out[off++] = ND_TYPE_TRUE;
410 } else if (z->u1.v.type == 4) {
411 out[off++] = ND_TYPE_LONG;
412 u64 = htobe64(z->value.lval);
413 memcpy(out + off, &u64, 8); off += 8;
414 } else if (z->u1.v.type == 5) {
415 out[off++] = ND_TYPE_DOUBLE;
416 uint64_t u64 = htobe64(z->value.lval);
417 memcpy(out + off, &u64, 8); off += 8;
418 } else if (z->u1.v.type == 6) {
419 out[off++] = ND_TYPE_STRING;
420 struct zend_string *zs = z->value.str;
421 if (off + 2 + zs->len > out_size)
422 return 0;
423 u16 = htobe16(zs->len);
424 memcpy(out + off, &u16, 2); off += 2;
425 memcpy(out + off, zs->val, zs->len); off += zs->len;
426 } else if (z->u1.v.type == 8) { // object
427 out[off++] = ND_TYPE_POINTER;
428 u64 = htobe64(z->value.lval);
429 memcpy(out + off, &u64, 8); off += 8;
430 } else if (z->u1.v.type == 9) { // resource
431 out[off++] = ND_TYPE_POINTER;
432 u64 = htobe64(z->value.lval);
433 memcpy(out + off, &u64, 8); off += 8;
434 } else {
435 out[off++] = ND_TYPE_UNK;
436 xlog(1, " %s: I do not how to encode %d type! Encode as NULL\n",
437 __func__, z->u1.v.type);
438 }
439
440 return off;
441 }
442
443 // Returns the number of bytes stored in 'out'
444 static unsigned int zend_array_to_binary(unsigned char *out, const size_t out_size,
445 struct zend_array *za)
446 {
447 xlog(100, " %s: nTableMask=0x%x nNumUsed=%u nNumOfElements=%u nTableSize=%u"
448 " nInternalPointer=%u flags=0x%x[%s]\n",
449 __func__,
450 za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize,
451 za->nInternalPointer, za->u.flags, za->u.flags & 4 ? "packed" : "");
452
453 unsigned int off = 0;
454 out[off++] = ND_TYPE_ARRAY_START;
455
456 struct Bucket *bs = za->arData, *be = za->arData + za->nNumUsed;
457 for (; bs != be; bs++) {
458 struct zval *_z = &bs->val;
459
460 if (_z && (_z->u1.v.type == 12)) // 12=IS_INDIRECT
461 _z = _z->value.zv;
462
463 if (_z->u1.v.type == 0 /*IS_UNDEF*/) {
464 xlog(101, " para h=%lu: type undef\n", bs->h);
465 continue;
466 }
467
468 if (_z->u1.v.type == 10) { // REFERENCE
469 xlog(101, " is a reference!\n");
470 _z = &_z->value.ref->val;
471 }
472
473 struct zend_string *zs = bs->key;
474 xlog(101, " para: bs=%p h=%lu key=[%p] type %s: val: %s\n",
475 bs, bs->h, zs, php_get_type(_z), php_get_value(_z));
476
477 unsigned int r = zend_simple_to_binary(out + off, out_size - off, _z);
478 if (r == 0)
479 break;
480 off += r;
481 }
482
483 out[off++] = ND_TYPE_ARRAY_END;
484
485 return off;
486 }
487
488 // Returns the number of bytes stored in 'out'
489 static unsigned int zend_to_binary(unsigned char *out, const size_t out_size,
490 struct zval *z)
491 {
492 if (z->u1.v.type == 7)
493 return zend_array_to_binary(out, out_size, z->value.arr);
494
495 return zend_simple_to_binary(out, out_size, z);
496 }
497
388 498 static void php_set_para(struct zend_execute_data *e, const unsigned int i, static void php_set_para(struct zend_execute_data *e, const unsigned int i,
389 499 const struct zval *para) const struct zval *para)
390 500 { {
 
... ... static void *my_mysqli_stmt_bind_param(struct zend_execute_data *e, struct zval
1581 1691 } }
1582 1692
1583 1693
1694 //////////////////////////////////////// C U R L
1695 void *(*old_curl_init)(struct zend_execute_data *, struct zval *);
1696 static void *my_curl_init(struct zend_execute_data *e, struct zval *retv)
1697 {
1698 struct nd_url b;
1699
1700 unsigned int num_args = e->This.u2.num_args;
1701 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
1702
1703 if (num_args > 0) {
1704 unsigned int s = (sizeof(struct zend_execute_data)
1705 + sizeof(struct zval) - 1) / sizeof(struct zval);
1706
1707 // url
1708 struct zval *z = (struct zval *) e + s; s++;
1709 php_zval_dump(" url: ", z);
1710 struct zend_string *xs = z->value.str;
1711 b.url = xs->val;
1712 b.url_len = xs->len;
1713 } else {
1714 b.url = NULL;
1715 b.url_len = 0;
1716 }
1717
1718 void *ret = old_curl_init(e, retv);
1719 if (!retv)
1720 return ret;
1721
1722 if ((retv->u1.v.type == 7) || (retv->u1.v.type == 8)) { // resource or object
1723 b.handle = retv->value.p;
1724 } else if (retv->u1.v.type == 2) { // false
1725 b.handle = NULL;
1726 }
1727
1728 ninedogs_process_url("curl_init", NINEDOGS_URL_INIT_END, &b);
1729
1730 return ret;
1731 }
1732
1733 void *(*old_curl_exec)(struct zend_execute_data *, struct zval *);
1734 static void *my_curl_exec(struct zend_execute_data *e, struct zval *retv)
1735 {
1736 struct nd_url b = { .url_len = 0, .sret_len = 0 };
1737
1738 unsigned int num_args = e->This.u2.num_args;
1739 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
1740
1741 unsigned int s = (sizeof(struct zend_execute_data)
1742 + sizeof(struct zval) - 1) / sizeof(struct zval);
1743
1744 // handle
1745 struct zval *z = (struct zval *) e + s; s++;
1746 php_zval_dump(" handle: ", z);
1747 b.handle = z->value.p;
1748
1749 ninedogs_process_url("curl_exec", NINEDOGS_URL_START, &b);
1750 void *ret = old_curl_exec(e, retv);
1751 if (!retv)
1752 return ret;
1753
1754 if (retv->u1.v.type == 6) { // string
1755 struct zend_string *xs = retv->value.str;
1756 b.ret = 2;
1757 b.sret = xs->val;
1758 b.sret_len = xs->len;
1759 } else if (retv->u1.v.type == 2) { // false
1760 b.ret = 0;
1761 } else if (retv->u1.v.type == 3) { // true
1762 b.ret = 1;
1763 }
1764 // TODO: propagate errors
1765
1766 ninedogs_process_url("curl_exec", NINEDOGS_URL_END, &b);
1767
1768 return ret;
1769 }
1770
1771 void *(*old_curl_close)(struct zend_execute_data *, struct zval *);
1772 static void *my_curl_close(struct zend_execute_data *e, struct zval *retv)
1773 {
1774 struct nd_url b = { .url_len = 0, .sret_len = 0 };
1775
1776 unsigned int num_args = e->This.u2.num_args;
1777 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
1778
1779 unsigned int s = (sizeof(struct zend_execute_data)
1780 + sizeof(struct zval) - 1) / sizeof(struct zval);
1781
1782 // handle
1783 struct zval *z = (struct zval *) e + s; s++;
1784 php_zval_dump(" handle: ", z);
1785 b.handle = z->value.p;
1786
1787 void *ret = old_curl_close(e, retv);
1788 if (!retv)
1789 return ret;
1790
1791 ninedogs_process_url("curl_close", NINEDOGS_URL_CLOSE_END, &b);
1792
1793 return ret;
1794 }
1795
1796 void *(*old_curl_setopt)(struct zend_execute_data *, struct zval *);
1797 static void *my_curl_setopt(struct zend_execute_data *e, struct zval *retv)
1798 {
1799 struct nd_url b = { .url_len = 0, .sret_len = 0 };
1800
1801 unsigned int num_args = e->This.u2.num_args;
1802 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
1803
1804 unsigned int s = (sizeof(struct zend_execute_data)
1805 + sizeof(struct zval) - 1) / sizeof(struct zval);
1806
1807 // handle
1808 struct zval *z = (struct zval *) e + s; s++;
1809 php_zval_dump(" handle: ", z);
1810 b.handle = z->value.p;
1811
1812 // option
1813 z = (struct zval *) e + s; s++;
1814 php_zval_dump(" option: ", z);
1815 const struct my_curl_easyoption *oi = curl_easy_option_by_id(z->value.lval);
1816 if (oi)
1817 snprintf(b.op, sizeof(b.op), "%s", oi->name);
1818 else
1819 snprintf(b.op, sizeof(b.op), "?%ld?", z->value.lval);
1820 xlog(100, " option name = %s\n", b.op);
1821
1822 // value
1823 z = (struct zval *) e + s; s++;
1824 php_zval_dump(" value: ", z);
1825 b.op_value_len = zend_to_binary(b.op_value, sizeof(b.op_value), z);
1826
1827 void *ret = old_curl_setopt(e, retv);
1828 if (!retv)
1829 return ret;
1830 php_zval_dump(" retv: ", retv);
1831
1832 if (retv->u1.v.type == 2) { // false
1833 b.ret = 0;
1834 } else if (retv->u1.v.type == 3) { // true
1835 b.ret = 1;
1836 }
1837 // TODO: propagate errors
1838
1839 ninedogs_process_url("curl_setopt", NINEDOGS_URL_SETOPT_END, &b);
1840
1841 return ret;
1842 }
1843
1584 1844
1585 1845
1586 1846 struct zend_module_entry *(*old_get_module)(void); struct zend_module_entry *(*old_get_module)(void);
 
... ... static struct zend_module_entry *php_hook_get_module_func(void)
1637 1897 fe = new->functions; fe = new->functions;
1638 1898 while (fe && fe->fname) { while (fe && fe->fname) {
1639 1899 xlog(100, " func %s handler=%p\n", fe->fname, fe->handler); xlog(100, " func %s handler=%p\n", fe->fname, fe->handler);
1640 if (strncmp(fe->fname, "pg_", 3) == 0) {
1900 if (strncmp(fe->fname, "curl_", 5) == 0) {
1901 if (strcmp(fe->fname, "curl_close") == 0) {
1902 old_curl_close = fe->handler;
1903 fe->handler = my_curl_close;
1904 } else if (strcmp(fe->fname, "curl_init") == 0) {
1905 old_curl_init = fe->handler;
1906 fe->handler = my_curl_init;
1907 } else if (strcmp(fe->fname, "curl_exec") == 0) {
1908 old_curl_exec = fe->handler;
1909 fe->handler = my_curl_exec;
1910 } else if (strcmp(fe->fname, "curl_setopt") == 0) {
1911 old_curl_setopt = fe->handler;
1912 fe->handler = my_curl_setopt;
1913 } else {
1914 //xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname);
1915 }
1916 } else if (strncmp(fe->fname, "pg_", 3) == 0) {
1641 1917 if (strcmp(fe->fname, "pg_close") == 0) { if (strcmp(fe->fname, "pg_close") == 0) {
1642 1918 old_pg_close = fe->handler; old_pg_close = fe->handler;
1643 1919 fe->handler = my_pg_close; fe->handler = my_pg_close;
 
... ... static struct zend_module_entry *php_hook_get_module_func(void)
1674 1950 old_pg_get_result = fe->handler; old_pg_get_result = fe->handler;
1675 1951 fe->handler = my_pg_get_result; fe->handler = my_pg_get_result;
1676 1952 } else { } else {
1677 xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname);
1953 //xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname);
1678 1954 } }
1679 1955 } else if (strncmp(fe->fname, "mysqli_", 7) == 0) { } else if (strncmp(fe->fname, "mysqli_", 7) == 0) {
1680 1956 if (strcmp(fe->fname, "mysqli_autocommit") == 0) { if (strcmp(fe->fname, "mysqli_autocommit") == 0) {
 
... ... static struct zend_module_entry *php_hook_get_module_func(void)
1724 2000 old_mysqli_stmt_prepare = fe->handler; old_mysqli_stmt_prepare = fe->handler;
1725 2001 fe->handler = my_mysqli_stmt_prepare; fe->handler = my_mysqli_stmt_prepare;
1726 2002 } else { } else {
1727 xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname);
2003 //xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname);
1728 2004 } }
1729 2005 } }
1730 2006 fe++; fe++;
File agent/process_core.c changed (mode: 100644) (index d2da5f1..28f33e7)
11 11 #include "process_misc.h" #include "process_misc.h"
12 12 #include "process_db.h" #include "process_db.h"
13 13 #include "process_ssl.h" #include "process_ssl.h"
14 #include "process_url.h"
14 15
15 16 static struct timeval start, stop; static struct timeval start, stop;
16 17
 
... ... void ninedogs_process_core(const unsigned int type, const void *d)
71 72 ninedogs_process_db_flush(); ninedogs_process_db_flush();
72 73 ninedogs_process_misc_flush(); ninedogs_process_misc_flush();
73 74 ninedogs_process_ssl_flush(); ninedogs_process_ssl_flush();
75 ninedogs_process_url_flush();
74 76
75 77 // TODO: add page faults, wall time, sys time etc. (getrusage) // TODO: add page faults, wall time, sys time etc. (getrusage)
76 78 pack(&buf, &len, "T4 st tt x4", pack(&buf, &len, "T4 st tt x4",
File agent/process_url.c added (mode: 100644) (index 0000000..864a37a)
1 //#include <stdio.h>
2 #include <string.h>
3 //#include <pthread.h>
4 //#include <stdarg.h>
5
6 #include "ids.h"
7 #include "tools.h"
8 #include "ctools.h"
9 #include "process.h"
10 #include "process_url.h"
11
12 extern void my_trace(const char *func, const char type, ...);
13 extern void *(*old_malloc)(size_t size);
14 extern void (*old_free)(void *p);
15
16 static unsigned int gran = 60; // granularity of reports, in seconds
17 static unsigned int max_url_len = 8192;
18
19 struct url_node
20 {
21 char *url;
22 unsigned char hash[32];
23 void *handle;
24 struct timeval ts, min, max, elap; // "ts" is the granularity interval timestamp
25 unsigned long long count, errors;
26 unsigned int url_len;
27 unsigned int post_field_size_called:1;
28 unsigned int pad1:31;
29 struct url_node *next;
30 };
31 static __thread struct url_node *url_head, *url_tail;
32
33
34 static void url_reset_node(struct url_node *q)
35 {
36 q->elap.tv_sec = q->elap.tv_usec = 0;
37 q->min.tv_sec = 2000000000; q->min.tv_usec = 0;
38 q->max.tv_sec = q->max.tv_usec = 0;
39 q->ts.tv_sec = 0;
40 q->count = q->errors = 0;
41 }
42
43 static void url_init_node(struct url_node *q)
44 {
45 q->ts.tv_usec = 0;
46 q->url = NULL;
47 q->url_len = 0;
48 memset(q->hash, 0, sizeof(q->hash));
49 url_reset_node(q);
50 }
51
52 // We do not send the url because it may be big (see url_send_string).
53 // The server will request it if it doesn't have it.
54 static void url_send_node(const struct url_node *q)
55 {
56 unsigned char *buf;
57 unsigned int len;
58
59 xlog(50, "%s: q=%p\n", __func__, q);
60
61 if (q->count == 0) {
62 xlog(1, " ignoring because count=0!\n");
63 return;
64 }
65
66 pack(&buf, &len, "T4 hb c8" "_t it at et C8 E8",
67 NINEDOGS_NET_URL_NODE, q->hash, sizeof(q->hash), q->count,
68 &q->ts, &q->min, &q->max, &q->elap, q->count, q->errors);
69 if (!buf) {
70 xlog(50, "%s: cannot allocate memory!\n", __func__);
71 return;
72 }
73
74 server_enqueue(buf, len);
75 }
76
77 static void url_hash(unsigned char *hash, const char *u, const unsigned int u_len)
78 {
79 ninedogs_sha256(hash, u, u_len);
80 }
81
82 static void url_flush_node(struct url_node *q, const unsigned int u)
83 {
84 if (q->ts.tv_sec == 0)
85 q->ts.tv_sec = u * gran;
86 if (q->ts.tv_sec / gran == u)
87 return;
88
89 xlog(40, "%s: q->ts.tv_sec/gran=%u u=%u\n",
90 __func__, q->ts.tv_sec / gran, u);
91 url_send_node(q);
92 url_reset_node(q); // TODO: what if sending is not working?
93 }
94
95 static void url_flush(void)
96 {
97 xlog(50, "%s\n", __func__);
98 struct url_node *q = url_head;
99 while (q) {
100 url_flush_node(q, 0); // 0 to force flush
101 q = q->next;
102 }
103 }
104
105 void url_send_string(const unsigned char *hash)
106 {
107 struct url_node *q = NULL;
108 unsigned char *buf;
109 unsigned int len;
110
111 q = url_head;
112 while (q) {
113 if (memcmp(q->hash, hash, 32) == 0)
114 break;
115 q = q->next;
116 }
117 if (!q) {
118 xlog(50, "%s: hash not found!\n", __func__);
119 return;
120 }
121
122 pack(&buf, &len, "T4 hb qs",
123 NINEDOGS_NET_URL_STRING, q->hash, sizeof(q->hash),
124 q->url, q->url_len);
125 if (!buf) {
126 xlog(50, "%s: cannot allocate memory!\n", __func__);
127 return;
128 }
129
130 server_enqueue(buf, len);
131 }
132
133 static struct url_node *search_or_create(struct nd_url *in)
134 {
135 unsigned char hash[32];
136 struct url_node *q = NULL;
137
138 xlog(100, "%s: in->url_len=%u\n", __func__, in->url_len);
139
140 if (in->url_len > 0) {
141 xlog(101, " %s: searching by url [%s]\n", __func__, in->url);
142 char hash_computed = 0;
143 q = url_head;
144 while (q) {
145 if (q->url_len != in->url_len) {
146 q = q->next;
147 continue;
148 }
149 if (hash_computed == 0) {
150 url_hash(hash, in->url, in->url_len);
151 hash_computed = 1;
152 }
153 if (memcmp(q->hash, hash, sizeof(q->hash)) == 0) {
154 xlog(100, " url found by hash q=%p\n", q);
155 return q;
156 }
157 q = q->next;
158 }
159 }
160
161 // Search by handle
162 if (in->handle) {
163 xlog(101, " %s: searching by handle %p\n", __func__, in->handle);
164 q = url_head;
165 while (q) {
166 if (q->handle == in->handle)
167 return q;
168 q = q->next;
169 }
170 }
171
172 // Not found, alloc
173 char *url_copy = NULL;
174 unsigned int url_len = 0;
175 if (in->url_len > 0) {
176 if (in->url_len > max_url_len)
177 url_len = max_url_len;
178 else
179 url_len = in->url_len;
180
181 url_copy = old_malloc(url_len + 1);
182 if (!url_copy) {
183 xlog(1, " cannot alloc memory!\n");
184 return NULL;
185 }
186 memcpy(url_copy, in->url, url_len);
187 url_copy[url_len] = '\0';
188 }
189
190 q = old_malloc(sizeof(struct url_node));
191 if (!q) {
192 old_free(url_copy);
193 return NULL;
194 }
195 xlog(100, " %s: allocated q=%p\n", __func__, q);
196 url_init_node(q);
197 q->handle = in->handle;
198 memcpy(q->hash, hash, sizeof(q->hash));
199 q->url = url_copy;
200 q->url_len = url_len;
201 q->post_field_size_called = 0;
202
203 q->next = url_head;
204 url_head = q;
205 if (!url_tail)
206 url_tail = q;
207
208 xlog(100, " %s: returning q=%p\n", __func__, q);
209 return q;
210 }
211
212 void ninedogs_process_url(const char *func, const unsigned int type, void *d)
213 {
214 struct url_node *q;
215 struct nd_url *in;
216 struct timeval elap;
217 unsigned int u;
218 struct timeval end;
219
220 xlog(100, "%s: type=%u\n", __func__, type);
221
222 switch (type) {
223 // url may be null! we need to intercept 'setopt' and use it
224 // TODO: what is the reason to hook this for stats?! Only to capture the url
225 case NINEDOGS_URL_INIT_END:
226 in = (struct nd_url *) d;
227 q = search_or_create(in);
228 if (!q)
229 break;
230 my_trace(func, 'R', in);
231 break;
232
233 case NINEDOGS_URL_SETOPT_END:
234 in = (struct nd_url *) d;
235 q = search_or_create(in);
236 if (!q)
237 break;
238 my_trace(func, 'R', in);
239 break;
240
241 case NINEDOGS_URL_CLOSE_END:
242 in = (struct nd_url *) d;
243 q = search_or_create(in);
244 if (!q)
245 break;
246 my_trace(func, 'R', in);
247 break;
248
249 case NINEDOGS_URL_START:
250 in = (struct nd_url *) d;
251 q = search_or_create(in);
252 if (!q)
253 break;
254
255 in->node = q; // to be used in _END
256 my_trace(func, 'c', in);
257 ninedogs_now(&in->start);
258 break;
259
260 case NINEDOGS_URL_END:
261 in = (struct nd_url *) d;
262 ninedogs_now(&end);
263 u = end.tv_sec / gran;
264
265 q = in->node;
266 xlog(101, " i->node = %p\n", in->node);
267 if (!q)
268 break;
269 url_flush_node(q, u);
270
271 q->ts.tv_sec = u * gran;
272 q->count++;
273
274 if (in->ret == 1) { // ok
275 xlog(100, " updating stats on q %p\n", q);
276 my_time_diff(&elap, &end, &in->start);
277 my_time_add(&q->elap, &elap);
278 if (my_time_compare(&q->min, &elap) > 0)
279 q->min = elap;
280 if (my_time_compare(&q->max, &elap) < 0)
281 q->max = elap;
282 } else {
283 q->errors++;
284 }
285 my_trace(func, 'r', in);
286 break;
287 }
288
289 ninedogs_process_post();
290 }
291
292 void ninedogs_process_url_flush(void)
293 {
294 xlog(50, "%s...\n", __func__);
295
296 url_flush();
297 }
File agent/process_url.h added (mode: 100644) (index 0000000..6c4390a)
1 #include <sys/time.h>
2
3 struct nd_url
4 {
5 void *handle;
6 void *node;
7 unsigned char ret;
8 char pad;
9 unsigned short op_value_len;
10 unsigned int url_len;
11 char *url;
12 char *sret;
13 unsigned short sret_len;
14 char pad2[6];
15 char op[32];
16 unsigned char op_value[4096];
17 struct timeval start;
18 };
19
20 void url_send_string(const unsigned char *hash);
21
22 void ninedogs_process_url(const char *func, const unsigned int type, void *d);
23
24 void ninedogs_process_url_flush(void);
25
File common/ids.h changed (mode: 100644) (index 1e80c52..8da5991)
... ... enum
22 22
23 23 NINEDOGS_NET_SSL_INFO = 0x00003000, NINEDOGS_NET_SSL_INFO = 0x00003000,
24 24 NINEDOGS_NET_SSL_CERT, NINEDOGS_NET_SSL_CERT,
25 NINEDOGS_NET_SSL_MAX // this is the last element of NINEDOGS_NET_SSL_*
25 NINEDOGS_NET_SSL_MAX, // this is the last element of NINEDOGS_NET_SSL_*
26
27 NINEDOGS_NET_URL_INFO = 0x00004000,
28 NINEDOGS_NET_URL_NODE,
29 NINEDOGS_NET_URL_STRING,
30 NINEDOGS_NET_URL_MAX // this is the last element of NINEDOGS_NET_URL_*
26 31 }; };
27 32
28 33
 
... ... enum
69 74 NINEDOGS_SSL_MAX // this is the last element of NINEDOGS_SSL_* NINEDOGS_SSL_MAX // this is the last element of NINEDOGS_SSL_*
70 75 }; };
71 76
77 enum
78 {
79 NINEDOGS_URL_INIT_START,
80 NINEDOGS_URL_INIT_END,
81 NINEDOGS_URL_START,
82 NINEDOGS_URL_END,
83 NINEDOGS_URL_SETOPT_END,
84 NINEDOGS_URL_CLOSE_END,
85 NINEDOGS_URL_MAX // this must be last
86 };
87
88 enum
89 {
90 ND_TYPE_NULL,
91 ND_TYPE_LONG,
92 ND_TYPE_DOUBLE,
93 ND_TYPE_STRING,
94 ND_TYPE_TRUE,
95 ND_TYPE_FALSE,
96 ND_TYPE_ARRAY_START,
97 ND_TYPE_ARRAY_END,
98 ND_TYPE_POINTER,
99 ND_TYPE_UNK
100 };
101
File common/tools.c changed (mode: 100644) (index 85d7ac5..adb2c61)
... ... int load_dir_file_text(char *buf, const size_t buf_size, const char *dir,
562 562
563 563 return r; return r;
564 564 } }
565
File test/curl/.gitignore changed (mode: 100644) (index d00491f..6856b33)
1 1 1 1
2 1b
3 1c
4 *.body
File test/curl/1.c changed (mode: 100644) (index 1e7d2c6..fd48740)
1 // set the len after pointer
2
1 3 #define _GNU_SOURCE #define _GNU_SOURCE
2 4
3 5 #include <curl/curl.h> #include <curl/curl.h>
 
... ... int main(void)
13 15
14 16 struct curl_slist *list = NULL; struct curl_slist *list = NULL;
15 17 list = curl_slist_append(list, "Content-Type: application/json"); list = curl_slist_append(list, "Content-Type: application/json");
16 list = curl_slist_append(list, "X-ninedogs-bla: 1");
18 list = curl_slist_append(list, "X-ninedogs-bla: 1🐱");
17 19
18 20
19 21 CURL *curl = curl_easy_init(); CURL *curl = curl_easy_init();
File test/curl/1b.c copied from file test/curl/1.c (similarity 95%) (mode: 100644) (index 1e7d2c6..2c79676)
1 // Now we set the len before pointer
2
1 3 #define _GNU_SOURCE #define _GNU_SOURCE
2 4
3 5 #include <curl/curl.h> #include <curl/curl.h>
 
... ... int main(void)
19 21 CURL *curl = curl_easy_init(); CURL *curl = curl_easy_init();
20 22 curl_easy_setopt(curl, CURLOPT_URL, "https://localhost"); curl_easy_setopt(curl, CURLOPT_URL, "https://localhost");
21 23 curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_POST, 1);
22 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
23 24 curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body_len); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body_len);
25 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
24 26 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
25 27 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
26 28 CURLcode res = curl_easy_perform(curl); CURLcode res = curl_easy_perform(curl);
File test/curl/1b.run added (mode: 100755) (index 0000000..c4361e7)
1 #!/bin/bash
2
3 set -e
4
5 gcc 1b.c -o 1b -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=1b.ld.txt
13
14 ./1b &>1.out &
15 LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1b.nd -p ${!}
16
File test/curl/1c.c copied from file test/curl/1.c (similarity 89%) (mode: 100644) (index 1e7d2c6..bc05b5a)
1 // Now we do not set the len
2
1 3 #define _GNU_SOURCE #define _GNU_SOURCE
2 4
3 5 #include <curl/curl.h> #include <curl/curl.h>
 
... ... int main(void)
19 21 CURL *curl = curl_easy_init(); CURL *curl = curl_easy_init();
20 22 curl_easy_setopt(curl, CURLOPT_URL, "https://localhost"); curl_easy_setopt(curl, CURLOPT_URL, "https://localhost");
21 23 curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_POST, 1);
24 //curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body_len);
22 25 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
23 curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body_len);
24 26 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
25 27 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
26 28 CURLcode res = curl_easy_perform(curl); CURLcode res = curl_easy_perform(curl);
File test/curl/1c.run added (mode: 100755) (index 0000000..3e592d9)
1 #!/bin/bash
2
3 set -e
4
5 gcc 1c.c -o 1c -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=1c.ld.txt
13
14 ./1c &>1.out &
15 LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1c.nd -p ${!}
16
File test/curl/2.php added (mode: 100644) (index 0000000..dae63b3)
1 <?php
2 error_reporting(E_ALL);
3
4 $c = curl_init('https://localhost');
5 $fp = fopen('2.body', 'w');
6
7 curl_setopt($c, CURLOPT_VERBOSE, 1);
8 curl_setopt($c, CURLOPT_FILE, $fp);
9
10 $x = curl_exec($c);
11 var_dump($x);
12
13 if (curl_error($c))
14 fwrite($fp, curl_error($c));
15
16 curl_close($c);
17
18 fclose($fp);
19
File test/curl/2.run copied from file test/curl/1.run (similarity 50%) (mode: 100755) (index 2a51e0d..559558a)
2 2
3 3 set -e set -e
4 4
5 gcc 1.c -o 1 -l curl
6
7 5 export LD_PRELOAD=../../agent/ninedogs.so export LD_PRELOAD=../../agent/ninedogs.so
8 6
9 export NINEDOGS_VERBOSE=200
7 export NINEDOGS_VERBOSE=201
10 8
11 9 #export LD_DEBUG=symbols #export LD_DEBUG=symbols
12 10 #export LD_DEBUG_OUTPUT=1.ld.txt #export LD_DEBUG_OUTPUT=1.ld.txt
13 11
14 ./1 &>1.out &
15 LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1.nd -p ${!}
12 php 2.php &>2.out &
13 LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 2.nd -p ${!}
16 14
File test/curl/3.php added (mode: 100644) (index 0000000..83df484)
1 <?php
2 error_reporting(E_ALL);
3
4 $c = curl_init();
5
6 curl_setopt($c, CURLOPT_URL, 'https://localhost');
7 curl_setopt($c, CURLOPT_VERBOSE, 1);
8
9 $h = array('Content-type: application/json', 'X-ninedogs: bla');
10 curl_setopt($c, CURLOPT_HTTPHEADER, $h);
11
12 $x = curl_exec($c);
13 var_dump($x);
14
15 if (curl_error($c))
16 echo curl_error($c) . "\n";
17
18 curl_close($c);
19
20 fclose($fp);
21
File test/curl/3.run copied from file test/curl/1.run (similarity 50%) (mode: 100755) (index 2a51e0d..5672b31)
2 2
3 3 set -e set -e
4 4
5 gcc 1.c -o 1 -l curl
6
7 5 export LD_PRELOAD=../../agent/ninedogs.so export LD_PRELOAD=../../agent/ninedogs.so
8 6
9 export NINEDOGS_VERBOSE=200
7 export NINEDOGS_VERBOSE=201
10 8
11 9 #export LD_DEBUG=symbols #export LD_DEBUG=symbols
12 10 #export LD_DEBUG_OUTPUT=1.ld.txt #export LD_DEBUG_OUTPUT=1.ld.txt
13 11
14 ./1 &>1.out &
15 LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1.nd -p ${!}
12 php 3.php &>3.out &
13 LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 3.nd -p ${!}
16 14
File trace/Makefile changed (mode: 100644) (index 2630ccd..9cefeea)
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 ../common/decode_text.h
6 COMMON_H += ../common/shared.h ../common/tools.h ../common/decode_text.h \
7 ../common/ids.h
7 8
8 9 CFLAGS += -I../common CFLAGS += -I../common
9 10
File trace/TODO changed (mode: 100644) (index 28e4a4e..d8d97e0)
1 1 == Urgent == == Urgent ==
2 [ ] All functions must have 'c' and 'r'
3 Example: close can take a lot of time!
4 Not all, but the ones which may wait.
5 [ ] After fork, only the parent sees "-stop"!
6 2 [ ] [ ]
7 3
8 4
9 5 == Non urgent == == Non urgent ==
10 6 [ ] We need to respect UTF-8 in bin2hex_ascii [ ] We need to respect UTF-8 in bin2hex_ascii
11 [ ]
7 [ ]
8
File trace/nd-trace.c changed (mode: 100644) (index c2de1f5..2265606)
24 24 #include <syslog.h> #include <syslog.h>
25 25 #include <unistd.h> #include <unistd.h>
26 26
27 #include "ids.h"
27 28 #include "shared.h" #include "shared.h"
28 29 #include "tools.h" #include "tools.h"
29 30 #include "decode_text.h" #include "decode_text.h"
 
... ... static void usage(void)
45 46 exit(1); exit(1);
46 47 } }
47 48
48 static FILE *out;
49 static FILE *outf;
49 50 static unsigned int do_exit; static unsigned int do_exit;
50 51
51 52 static uint8_t decode8(unsigned char *d, unsigned int *i) static uint8_t decode8(unsigned char *d, unsigned int *i)
 
... ... static int decode_whence(char *out, const size_t out_size, unsigned char *d, uns
821 822 return ret; return ret;
822 823 } }
823 824
825 // TODO: we need to check if out is large enough
826 static void decode_types(char *out, const size_t out_size,
827 unsigned char *buf, unsigned int *i)
828 {
829 unsigned int off = 0;
830 uint16_t u16;
831 int64_t d64;
832 uint64_t u64;
833 char *add = "";
834 unsigned char depth = 0;
835 char tmp[4096];
836
837 do {
838 unsigned char type = buf[*i]; *i = *i + 1;
839 switch (type) {
840 case ND_TYPE_ARRAY_START:
841 strcat(out + off, add); off += strlen(add);
842 out[off++] = '{';
843 depth++;
844 add = "";
845 break;
846
847 case ND_TYPE_ARRAY_END:
848 out[off++] = '}';
849 depth--;
850 add = ", ";
851 break;
852
853 case ND_TYPE_STRING:
854 memcpy(&u16, buf + *i, 2); *i = *i + 2;
855 u16 = be16toh(u16);
856 bin2hex_ascii(tmp, buf + *i, u16); *i = *i + u16;
857 off += sprintf(out + off, "%s'%s'", add, tmp);
858 add = ", ";
859 break;
860
861 case ND_TYPE_TRUE:
862 off += sprintf(out + off, "%strue", add);
863 add = ", ";
864 break;
865
866 case ND_TYPE_FALSE:
867 off += sprintf(out + off, "%sfalse", add);
868 add = ", ";
869 break;
870
871 case ND_TYPE_NULL:
872 off += sprintf(out + off, "%snull", add);
873 add = ", ";
874 break;
875
876 case ND_TYPE_UNK:
877 off += sprintf(out + off, "%s?", add);
878 add = ", ";
879 break;
880
881 case ND_TYPE_LONG:
882 memcpy(&d64, buf + *i, 8); *i = *i + 8;
883 d64 = be64toh(d64);
884 off += sprintf(out + off, "%s%ld", add, d64);
885 add = ", ";
886 break;
887
888 case ND_TYPE_DOUBLE:
889 memcpy(&d64, buf + *i, 8); *i = *i + 8;
890 d64 = be64toh(d64);
891 double d;
892 memcpy(&d, &d64, 8);
893 off += sprintf(out + off, "%s%f", add, d);
894 add = ", ";
895 break;
896
897 case ND_TYPE_POINTER:
898 memcpy(&u64, buf + *i, 8); *i = *i + 8;
899 u64 = be64toh(u64);
900 off += sprintf(out + off, "%s0x%lx", add, u64);
901 add = ", ";
902 break;
903
904 }
905 } while (depth > 0);
906 }
907
824 908 static void decode_func(const uint32_t parent, unsigned char *d) static void decode_func(const uint32_t parent, unsigned char *d)
825 909 { {
826 910 unsigned int i = 0; unsigned int i = 0;
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
839 923 type = d[i++]; type = d[i++];
840 924 uint32_t pid = decode32(d, &i); uint32_t pid = decode32(d, &i);
841 925 uint32_t tid = decode32(d, &i); uint32_t tid = decode32(d, &i);
842 //fprintf(out, "%s: t=%lu func_len=%hu func=[%s] type=%c pid=%u tid=%u\n",
926 //fprintf(outf, "%s: t=%lu func_len=%hu func=[%s] type=%c pid=%u tid=%u\n",
843 927 // __func__, t, func_len, func, type, pid, tid); // __func__, t, func_len, func, type, pid, tid);
844 928
845 929 switch (func[0]) { switch (func[0]) {
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
919 1003 } else if (strcmp(func, "curl_easy_cleanup") == 0) { } else if (strcmp(func, "curl_easy_cleanup") == 0) {
920 1004 uint64_t handle = decode64(d, &i); uint64_t handle = decode64(d, &i);
921 1005 sprintf(line, "(0x%lx)", handle); sprintf(line, "(0x%lx)", handle);
1006 } else if (strcmp(func, "curl_init") == 0) { // php
1007 uint64_t handle = decode64(d, &i);
1008 uint16_t len = decode16(d, &i);
1009 if (len == 0) {
1010 sprintf(line, "() = 0x%lx", handle);
1011 } else {
1012 char url[len * 4 + 1];
1013 bin2hex_ascii(url, d + i, len); i += len;
1014 sprintf(line, "('%s') = 0x%lx", url, handle);
1015 }
1016 } else if (strcmp(func, "curl_setopt") == 0) { // php
1017 uint64_t handle = decode64(d, &i);
1018 uint8_t oplen = decode8(d, &i);
1019 char op[oplen * 4 + 1];
1020 bin2hex_ascii(op, d + i, oplen); i += oplen;
1021 char types[4096];
1022 decode_types(types, sizeof(types), d, &i);
1023 if (type == 'r') {
1024 uint8_t ret = decode8(d, &i);
1025 snprintf(rest, sizeof(rest), " = %s", ret == 1 ? "ok" : "nok");
1026 }
1027 sprintf(line, "(0x%lx, %s, %s)%s", handle, op, types, rest);
1028 } else if (strcmp(func, "curl_exec") == 0) { // php
1029 uint64_t handle = decode64(d, &i);
1030 if (type == 'r') {
1031 uint8_t ret = decode8(d, &i);
1032 if (ret == 2) {
1033 uint16_t sret_len = decode16(d, &i);
1034 char sret[sret_len * 4 + 1];
1035 bin2hex_ascii(sret, d + i, sret_len); i += sret_len;
1036 snprintf(rest, sizeof(rest), " = '%s'", sret);
1037 } else if (ret == 0) {
1038 snprintf(rest, sizeof(rest), " = nok");
1039 } else {
1040 snprintf(rest, sizeof(rest), " = ok");
1041 }
1042 }
1043 sprintf(line, "(0x%lx)%s", handle, rest);
922 1044 } else if (strcmp(func, "curl_easy_init") == 0) { } else if (strcmp(func, "curl_easy_init") == 0) {
923 1045 uint64_t handle = decode64(d, &i); uint64_t handle = decode64(d, &i);
924 1046 sprintf(line, "() = 0x%lx", handle); sprintf(line, "() = 0x%lx", handle);
925 1047 } else if (strcmp(func, "curl_easy_perform") == 0) { } 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);
1048 if (type == 'm') {
1049 uint8_t len = decode8(d, &i);
1050 char info[len * 4 + 1];
1051 bin2hex_ascii(info, d + i, len); i += len;
1052 uint64_t handle = decode64(d, &i);
1053 uint16_t post_len = decode16(d, &i);
1054 char post[post_len * 4 + 1];
1055 bin2hex_ascii(post, d + i, post_len); i += post_len;
1056 sprintf(line, "(0x%lx) %s: %s", handle, info, post);
931 1057 } else { } else {
932 sprintf(line, "(0x%lx)", handle);
1058 uint64_t handle = decode64(d, &i);
1059 if (type == 'r') {
1060 int ret = decode32(d, &i);
1061 nd_decode_curl_code(rest, sizeof(rest), ret);
1062 sprintf(line, "(0x%lx) = %s", handle, rest);
1063 } else {
1064 sprintf(line, "(0x%lx)", handle);
1065 }
933 1066 } }
934 1067 } else if (strcmp(func, "curl_easy_setopt") == 0) { } 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);
1068 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
936 1069 uint64_t handle = decode64(d, &i); uint64_t handle = decode64(d, &i);
937 1070 uint8_t type = decode8(d, &i); uint8_t type = decode8(d, &i);
938 1071 uint8_t option_len = decode8(d, &i); uint8_t option_len = decode8(d, &i);
939 1072 char option[option_len * 4 + 1]; char option[option_len * 4 + 1];
940 1073 bin2hex_ascii(option, d + i, option_len); i += option_len; bin2hex_ascii(option, d + i, option_len); i += option_len;
941 if ((type == 0) || (type == 2)) { // long
1074 if ((type == 0) || (type == 2)) { // long or off_t
942 1075 snprintf(rest, sizeof(rest), "%ld", decode64(d, &i)); 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);
1076 } else if ((type == 3) || (type == 4)) { // object or string
1077 long len = decode64(d, &i);
1078 if (len >= 0) {
1079 uint16_t s_len = decode16(d, &i);
1080 char s[s_len * 4 + 1];
1081 bin2hex_ascii(s, d + i, len); i += s_len;
1082 snprintf(rest, sizeof(rest), "'%s'", s);
1083 } else {
1084 snprintf(rest, sizeof(rest),
1085 "[cannot dump yet because size was not set yet]");
1086 }
948 1087 } else if (type == 5) { // slist } else if (type == 5) { // slist
949 1088 decode_string_array(rest, sizeof(rest), d, &i); decode_string_array(rest, sizeof(rest), d, &i);
950 1089 } else { } else {
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
953 1092 int ret = decode32(d, &i); int ret = decode32(d, &i);
954 1093 char sret[32]; char sret[32];
955 1094 nd_decode_curl_code(sret, sizeof(sret), ret); nd_decode_curl_code(sret, sizeof(sret), ret);
956 sprintf(line, "(0x%lx, CURLOPT_%s, %s) = %s",
1095 sprintf(line, "(0x%lx, %s, %s) = %s",
957 1096 handle, option, rest, sret); handle, option, rest, sret);
958 1097 } break; } break;
959 1098
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1082 1221 } }
1083 1222 } }
1084 1223 } else if (strcmp(func, "getsockopt") == 0) { } else if (strcmp(func, "getsockopt") == 0) {
1085 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1224 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1086 1225 int sock = decode32(d, &i); int sock = decode32(d, &i);
1087 1226 char level[32], optname[32]; char level[32], optname[32];
1088 1227 int ilevel = decode_sock_level(level, sizeof(level), d, &i); int ilevel = decode_sock_level(level, sizeof(level), d, &i);
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1097 1236
1098 1237 case 'l': case 'l':
1099 1238 if (strcmp(func, "listen") == 0) { if (strcmp(func, "listen") == 0) {
1100 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1239 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1101 1240 int sock = decode32(d, &i); int sock = decode32(d, &i);
1102 1241 int backlog = decode32(d, &i); int backlog = decode32(d, &i);
1103 1242 decode_ret_int(rest, sizeof(rest), d, &i); decode_ret_int(rest, sizeof(rest), d, &i);
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1136 1275 decode_bool(" = ", rest, sizeof(rest), d, &i); decode_bool(" = ", rest, sizeof(rest), d, &i);
1137 1276 sprintf(line, "(link=0x%lx)%s", link, rest); sprintf(line, "(link=0x%lx)%s", link, rest);
1138 1277 } else if (strcmp(func, "mysqli_connect") == 0) { } else if (strcmp(func, "mysqli_connect") == 0) {
1139 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1278 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1140 1279 uint32_t cs_len = decode32(d, &i); uint32_t cs_len = decode32(d, &i);
1141 1280 char cs[cs_len * 4 + 1]; char cs[cs_len * 4 + 1];
1142 1281 bin2hex_ascii(cs, d + i, cs_len); i += cs_len; bin2hex_ascii(cs, d + i, cs_len); i += cs_len;
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1208 1347 decode_bool(" = ", rest, sizeof(rest), d, &i); decode_bool(" = ", rest, sizeof(rest), d, &i);
1209 1348 sprintf(line, "(link=0x%lx, '%s', flags='%s')%s", link, cs, flags, rest); sprintf(line, "(link=0x%lx, '%s', flags='%s')%s", link, cs, flags, rest);
1210 1349 } else if (strcmp(func, "mysqli_stmt_bind_param") == 0) { } else if (strcmp(func, "mysqli_stmt_bind_param") == 0) {
1211 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1350 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1212 1351 uint64_t stmt = decode64(d, &i); uint64_t stmt = decode64(d, &i);
1213 1352 unsigned short types_len = decode16(d, &i); unsigned short types_len = decode16(d, &i);
1214 1353 char types[types_len * 4 + 1]; char types[types_len * 4 + 1];
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1218 1357 sprintf(line, "(stmt=0x%lx, types='%s', ...)%s", sprintf(line, "(stmt=0x%lx, types='%s', ...)%s",
1219 1358 stmt, types, rest); stmt, types, rest);
1220 1359 } else if (strcmp(func, "mysqli_stmt_execute") == 0) { } else if (strcmp(func, "mysqli_stmt_execute") == 0) {
1221 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1360 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1222 1361 uint64_t stmt = decode64(d, &i); uint64_t stmt = decode64(d, &i);
1223 1362 if (type == 'c') { if (type == 'c') {
1224 1363 decode_query_params(rest, sizeof(rest), d, &i); decode_query_params(rest, sizeof(rest), d, &i);
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1352 1491 sprintf(line, "(0x%lx)", h); sprintf(line, "(0x%lx)", h);
1353 1492 } else if ((strcmp(func, "pg_connect") == 0) } else if ((strcmp(func, "pg_connect") == 0)
1354 1493 || (strcmp(func, "pg_pconnect") == 0)) { || (strcmp(func, "pg_pconnect") == 0)) {
1355 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1494 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1356 1495 uint32_t cs_len = decode32(d, &i); uint32_t cs_len = decode32(d, &i);
1357 1496 char cs[cs_len * 4 + 1]; char cs[cs_len * 4 + 1];
1358 1497 bin2hex_ascii(cs, d + i, cs_len); i += cs_len; bin2hex_ascii(cs, d + i, cs_len); i += cs_len;
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1369 1508 || (strcmp(func, "pg_query_params") == 0) || (strcmp(func, "pg_query_params") == 0)
1370 1509 || (strcmp(func, "pg_send_query") == 0) || (strcmp(func, "pg_send_query") == 0)
1371 1510 || (strcmp(func, "pg_send_query_params") == 0)) { || (strcmp(func, "pg_send_query_params") == 0)) {
1372 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1511 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1373 1512 uint64_t dbh = decode64(d, &i); uint64_t dbh = decode64(d, &i);
1374 1513 uint16_t q_len = decode16(d, &i); uint16_t q_len = decode16(d, &i);
1375 1514 char q[q_len * 4 + 1]; char q[q_len * 4 + 1];
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1393 1532 } }
1394 1533 sprintf(line, "(h=0x%lx, '%s')%s", dbh, q, rest); sprintf(line, "(h=0x%lx, '%s')%s", dbh, q, rest);
1395 1534 } else if (strcmp(func, "pg_get_result") == 0) { } else if (strcmp(func, "pg_get_result") == 0) {
1396 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1535 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1397 1536 uint64_t dbh = decode64(d, &i); uint64_t dbh = decode64(d, &i);
1398 1537 if (type == 'r') { if (type == 'r') {
1399 1538 uint64_t res = decode64(d, &i); uint64_t res = decode64(d, &i);
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1404 1543 } }
1405 1544 sprintf(line, "(h=0x%lx)%s", dbh, rest); sprintf(line, "(h=0x%lx)%s", dbh, rest);
1406 1545 } else if (strcmp(func, "pthread_join") == 0) { } else if (strcmp(func, "pthread_join") == 0) {
1407 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1546 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1408 1547 uint64_t thread = decode64(d, &i); uint64_t thread = decode64(d, &i);
1409 1548 int ret = decode_ret_int(rest, sizeof(rest), d, &i); int ret = decode_ret_int(rest, sizeof(rest), d, &i);
1410 1549 uint64_t retval = 0; uint64_t retval = 0;
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1413 1552 sprintf(line, "(thread=0x%lx, retval=0x%lx)%s", sprintf(line, "(thread=0x%lx, retval=0x%lx)%s",
1414 1553 thread, retval, rest); thread, retval, rest);
1415 1554 } else if (strcmp(func, "pthread_attr_setstacksize") == 0) { } else if (strcmp(func, "pthread_attr_setstacksize") == 0) {
1416 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1555 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1417 1556 uint64_t attr = decode64(d, &i); uint64_t attr = decode64(d, &i);
1418 1557 size_t stack_size = decode64(d, &i); size_t stack_size = decode64(d, &i);
1419 1558 decode_ret_int(rest, sizeof(rest), d, &i); decode_ret_int(rest, sizeof(rest), d, &i);
1420 1559 sprintf(line, "(attr=0x%lx, %zu)%s", sprintf(line, "(attr=0x%lx, %zu)%s",
1421 1560 attr, stack_size, rest); attr, stack_size, rest);
1422 1561 } else if (strcmp(func, "pthread_create") == 0) { } else if (strcmp(func, "pthread_create") == 0) {
1423 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1562 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1424 1563 uint64_t thread = decode64(d, &i); uint64_t thread = decode64(d, &i);
1425 1564 uint64_t attr = decode64(d, &i); uint64_t attr = decode64(d, &i);
1426 1565 uint64_t arg = decode64(d, &i); uint64_t arg = decode64(d, &i);
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1428 1567 sprintf(line, "(thread=0x%lx, attr=0x%lx, arg=0x%lx)%s", sprintf(line, "(thread=0x%lx, attr=0x%lx, arg=0x%lx)%s",
1429 1568 thread, attr, arg, rest); thread, attr, arg, rest);
1430 1569 } else if (strcmp(func, "pthread_setname_np") == 0) { } else if (strcmp(func, "pthread_setname_np") == 0) {
1431 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1570 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1432 1571 uint64_t thread = decode64(d, &i); uint64_t thread = decode64(d, &i);
1433 1572 uint16_t len = decode16(d, &i); uint16_t len = decode16(d, &i);
1434 1573 char name[len * 4 + 1]; char name[len * 4 + 1];
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1545 1684 } }
1546 1685 } else if (strcmp(func, "setsockopt") == 0) { } else if (strcmp(func, "setsockopt") == 0) {
1547 1686 int sock = decode32(d, &i); int sock = decode32(d, &i);
1548 if (type == 'c') {
1549 char level[32], optname[32];
1550 int ilevel = decode_sock_level(level, sizeof(level), d, &i);
1551 decode_sock_optname(optname, sizeof(optname), ilevel, d, &i);
1552 socklen_t optlen = decode32(d, &i);
1553 char optval[optlen * 2 + 1];
1554 bin2hex(optval, d + i, optlen); i+= optlen;
1555 sprintf(line, "(%d, %s, %s, 0x%s, %u)",
1556 sock, level, optname, optval, optlen);
1557 } else {
1558 decode_ret_int(rest, sizeof(rest), d, &i);
1559 sprintf(line, "(%d)%s", sock, rest);
1560 }
1687 char level[32], optname[32];
1688 int ilevel = decode_sock_level(level, sizeof(level), d, &i);
1689 decode_sock_optname(optname, sizeof(optname), ilevel, d, &i);
1690 socklen_t optlen = decode32(d, &i);
1691 char optval[optlen * 2 + 1];
1692 bin2hex(optval, d + i, optlen); i+= optlen;
1693 decode_ret_int(rest, sizeof(rest), d, &i);
1694 sprintf(line, "(%d, %s, %s, 0x%s, %u)%s",
1695 sock, level, optname, optval, optlen, rest);
1561 1696 } else if (strcmp(func, "socket") == 0) { } else if (strcmp(func, "socket") == 0) {
1562 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1697 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1563 1698 int xdomain = decode32(d, &i); int xdomain = decode32(d, &i);
1564 1699 int xtype = decode32(d, &i); int xtype = decode32(d, &i);
1565 1700 int xprotocol = decode32(d, &i); int xprotocol = decode32(d, &i);
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1604 1739 decode_sqlite3_ret(rest, sizeof(rest), d, &i); decode_sqlite3_ret(rest, sizeof(rest), d, &i);
1605 1740 sprintf(line, "(0x%lx)%s%s", stmt, rest[0] ? " = " : "", rest); sprintf(line, "(0x%lx)%s%s", stmt, rest[0] ? " = " : "", rest);
1606 1741 } else if (strcmp(func, "sqlite3_open_v2") == 0) { } else if (strcmp(func, "sqlite3_open_v2") == 0) {
1607 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1742 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1608 1743 uint16_t filename_len = decode16(d, &i); uint16_t filename_len = decode16(d, &i);
1609 1744 char filename[filename_len * 4 + 1]; char filename[filename_len * 4 + 1];
1610 1745 bin2hex_ascii(filename, d + i, filename_len); i += filename_len; bin2hex_ascii(filename, d + i, filename_len); i += filename_len;
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1627 1762 filename, pdb, flags, vfs, err); filename, pdb, flags, vfs, err);
1628 1763 } }
1629 1764 } else if (strcmp(func, "sqlite3_prepare_v2") == 0) { } else if (strcmp(func, "sqlite3_prepare_v2") == 0) {
1630 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1765 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1631 1766 uint64_t h = decode64(d, &i); uint64_t h = decode64(d, &i);
1632 1767 uint32_t sql_len = decode32(d, &i); uint32_t sql_len = decode32(d, &i);
1633 1768 char sql[sql_len * 4 + 1]; char sql[sql_len * 4 + 1];
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1644 1779 h, sql, nByte, stmt, err); h, sql, nByte, stmt, err);
1645 1780 } }
1646 1781 } else if (strcmp(func, "sqlite3_step") == 0) { } else if (strcmp(func, "sqlite3_step") == 0) {
1647 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1782 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1648 1783 uint64_t stmt = decode64(d, &i); uint64_t stmt = decode64(d, &i);
1649 1784 if (type == 'c') { if (type == 'c') {
1650 1785 sprintf(line, "(0x%lx)", stmt); sprintf(line, "(0x%lx)", stmt);
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1666 1801 sprintf(line, "('%s', {%s})%s", pathname, sstat, rest); sprintf(line, "('%s', {%s})%s", pathname, sstat, rest);
1667 1802 } }
1668 1803 } else if (strcmp(func, "syslog") == 0) { } else if (strcmp(func, "syslog") == 0) {
1669 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP[%s][%c]: %s\n", func, type, dump);
1804 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump);
1670 1805 char sprio[32]; char sprio[32];
1671 1806 decode_syslog_prio(sprio, sizeof(sprio), d, &i); decode_syslog_prio(sprio, sizeof(sprio), d, &i);
1672 1807 int len = decode16(d, &i); int len = decode16(d, &i);
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1699 1834
1700 1835 case 'w': case 'w':
1701 1836 if (strcmp(func, "write") == 0) { if (strcmp(func, "write") == 0) {
1702 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(out, "DUMP: %s\n", dump);
1837 //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP: %s\n", dump);
1703 1838 int fd = decode32(d, &i); int fd = decode32(d, &i);
1704 1839 size_t count = decode64(d, &i); size_t count = decode64(d, &i);
1705 1840 if (type == 'c') { if (type == 'c') {
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1717 1852 } break; } break;
1718 1853 } }
1719 1854 if (line[0] == '\0') { if (line[0] == '\0') {
1720 fprintf(out, "I do not know how to decode func [%s] type [%c]!\n",
1855 fprintf(outf, "I do not know how to decode func [%s] type [%c]!\n",
1721 1856 func, type); func, type);
1722 1857 return; return;
1723 1858 } }
 
... ... static void decode_func(const uint32_t parent, unsigned char *d)
1730 1865 space[max] = '\0'; space[max] = '\0';
1731 1866
1732 1867 if (pid == tid) if (pid == tid)
1733 fprintf(out, "%lu.%03lu %10u%s %s%s\n",
1868 fprintf(outf, "%lu.%03lu %10u%s %s%s\n",
1734 1869 t / 1000, t % 1000, pid, space, func, line); t / 1000, t % 1000, pid, space, func, line);
1735 1870 else else
1736 fprintf(out, "%lu.%03lu %10u %10u%s %s%s\n",
1871 fprintf(outf, "%lu.%03lu %10u %10u%s %s%s\n",
1737 1872 t / 1000, t % 1000, pid, tid, space, func, line); t / 1000, t % 1000, pid, tid, space, func, line);
1738 1873 } }
1739 1874
 
... ... static void decode(const pid_t parent, unsigned char *d, size_t len)
1746 1881 if (type == 'F') { if (type == 'F') {
1747 1882 decode_func(parent, d + i); decode_func(parent, d + i);
1748 1883 } else { } else {
1749 fprintf(out, "I do not know how to decode type [%c]!\n", type);
1884 fprintf(outf, "I do not know how to decode type [%c]!\n", type);
1750 1885 char dump[len * 4 + 1]; char dump[len * 4 + 1];
1751 1886 bin2hex_ascii(dump, d, len); bin2hex_ascii(dump, d, len);
1752 fprintf(out, "Decode %s\n", dump);
1887 fprintf(outf, "Decode %s\n", dump);
1753 1888 } }
1754 1889 } }
1755 1890
 
... ... int main(int argc, char *argv[])
1792 1927 } }
1793 1928
1794 1929 if (!out_file) { if (!out_file) {
1795 out = stderr;
1930 outf = stderr;
1796 1931 } else { } else {
1797 1932 fprintf(stderr, "Saving output to [%s]\n", out_file); fprintf(stderr, "Saving output to [%s]\n", out_file);
1798 out = fopen(out_file, "w");
1799 if (!out) {
1933 outf = fopen(out_file, "w");
1934 if (!outf) {
1800 1935 fprintf(stderr, "Error: cannot open [%s]: %m\n", out_file); fprintf(stderr, "Error: cannot open [%s]: %m\n", out_file);
1801 1936 return 1; return 1;
1802 1937 } }
1803 1938 } }
1804 setlinebuf(out);
1939 setlinebuf(outf);
1805 1940
1806 1941 //pid_t my_pid = getpid(); //pid_t my_pid = getpid();
1807 1942
 
... ... int main(int argc, char *argv[])
1858 1993
1859 1994 fstat(sm[i], &s); fstat(sm[i], &s);
1860 1995 if (s.st_size == 0) { if (s.st_size == 0) {
1861 //fprintf(out, "%u: Shared memory size is zero!\n", pids[i]);
1996 //fprintf(outf, "%u: Shared memory size is zero!\n", pids[i]);
1862 1997 continue; continue;
1863 1998 } }
1864 //fprintf(out, "%u: Shared memory size: %ld\n", pids[i], s.st_size);
1999 //fprintf(outf, "%u: Shared memory size: %ld\n", pids[i], s.st_size);
1865 2000
1866 2001 r = sem_wait(&shared[i]->sem1); r = sem_wait(&shared[i]->sem1);
1867 2002 if (r == -1) { if (r == -1) {
 
... ... int main(int argc, char *argv[])
1877 2012
1878 2013 if (version[i] == 0) { if (version[i] == 0) {
1879 2014 version[i] = shared[i]->version; version[i] = shared[i]->version;
1880 fprintf(out, "%u: version is %hhu\n", pids[i], version[i]);
2015 fprintf(outf, "%u: version is %hhu\n", pids[i], version[i]);
1881 2016 } }
1882 2017
1883 2018 // tail-1 points to last value available // tail-1 points to last value available
 
... ... int main(int argc, char *argv[])
1888 2023 else // 01t345h78 => ava = 2 + (9 - 6) = 5 else // 01t345h78 => ava = 2 + (9 - 6) = 5
1889 2024 ava = shared[i]->tail + (shared[i]->buf_size - shared[i]->head); ava = shared[i]->tail + (shared[i]->buf_size - shared[i]->head);
1890 2025
1891 //fprintf(out, "RING[%u]: head=%u tail=%u new_tail=%u msgs_lost=%u [after lock]\n",
2026 //fprintf(outf, "RING[%u]: head=%u tail=%u new_tail=%u msgs_lost=%u [after lock]\n",
1892 2027 // i, shared[i]->head, shared[i]->tail, shared[i]->new_tail, shared[i]->msgs_lost); // i, shared[i]->head, shared[i]->tail, shared[i]->new_tail, shared[i]->msgs_lost);
1893 2028
1894 2029 //char dump[ava * 4 + 1]; //char dump[ava * 4 + 1];
1895 2030 //bin2hex_ascii(dump, shared[i]->buf + shared[i]->head, ava); //bin2hex_ascii(dump, shared[i]->buf + shared[i]->head, ava);
1896 //fprintf(out, "DUMP0[%hu]: %s\n", ava, dump);
2031 //fprintf(outf, "DUMP0[%hu]: %s\n", ava, dump);
1897 2032
1898 2033 while (ava >= 2) { while (ava >= 2) {
1899 2034 unsigned short plen; unsigned short plen;
 
... ... int main(int argc, char *argv[])
1908 2043 plen = be16toh(plen); plen = be16toh(plen);
1909 2044 } }
1910 2045 if (plen > ava) { if (plen > ava) {
1911 fprintf(out, "%u: Too short packet: plen=%hu > ava[%u]!\n",
2046 fprintf(outf, "%u: Too short packet: plen=%hu > ava[%u]!\n",
1912 2047 pids[i], plen, ava); pids[i], plen, ava);
1913 2048 break; break;
1914 2049 } }
 
... ... int main(int argc, char *argv[])
1918 2053 } else { // split data! dddt...hddd size=11, head=7, plen=8 => max=4 } else { // split data! dddt...hddd size=11, head=7, plen=8 => max=4
1919 2054 unsigned int max = shared[i]->buf_size - shared[i]->head; unsigned int max = shared[i]->buf_size - shared[i]->head;
1920 2055 if (max > plen) max = plen; if (max > plen) max = plen;
1921 //fprintf(out, " DEBUG: split data. max=%u\n", max);
1922 //fprintf(out, " DEBUG: copy to buf from %p+%u, %u bytes\n", shared[i]->buf, shared[i]->head, max);
2056 //fprintf(outf, " DEBUG: split data. max=%u\n", max);
2057 //fprintf(outf, " DEBUG: copy to buf from %p+%u, %u bytes\n", shared[i]->buf, shared[i]->head, max);
1923 2058 memcpy(buf, shared[i]->buf + shared[i]->head, max); memcpy(buf, shared[i]->buf + shared[i]->head, max);
1924 //fprintf(out, " DEBUG: copy to buf+%u from %p, %u bytes\n", max, shared[i]->buf, plen - max);
2059 //fprintf(outf, " DEBUG: copy to buf+%u from %p, %u bytes\n", max, shared[i]->buf, plen - max);
1925 2060 memcpy(buf + max, shared[i]->buf, plen - max); memcpy(buf + max, shared[i]->buf, plen - max);
1926 2061 p = buf; p = buf;
1927 2062 } }
 
... ... int main(int argc, char *argv[])
1929 2064 if (0) { if (0) {
1930 2065 char dump[plen * 4 + 1]; char dump[plen * 4 + 1];
1931 2066 bin2hex_ascii(dump, p, plen); bin2hex_ascii(dump, p, plen);
1932 fprintf(out, "%u: DUMP[%hu] head=%u: %s\n",
2067 fprintf(outf, "%u: DUMP[%hu] head=%u: %s\n",
1933 2068 pids[i], plen, shared[i]->head, dump); pids[i], plen, shared[i]->head, dump);
1934 2069 } }
1935 2070
 
... ... int main(int argc, char *argv[])
1937 2072
1938 2073 shared[i]->head = (shared[i]->head + plen) % shared[i]->buf_size; shared[i]->head = (shared[i]->head + plen) % shared[i]->buf_size;
1939 2074 ava -= plen; ava -= plen;
1940 //fprintf(out, " DEBUG: ava[%u] after substracting plen[%hu]; no_pids=%u\n", ava, plen, no_pids);
2075 //fprintf(outf, " DEBUG: ava[%u] after substracting plen[%hu]; no_pids=%u\n", ava, plen, no_pids);
1941 2076 } }
1942 2077 } }
1943 2078
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