Subject | Hash | Author | Date (UTC) |
---|---|---|---|
Lots of changes | 8c803765a4dd6d79e7f61927c47a5f1a19e3db31 | Catalin(ux) M. BOIE | 2023-03-13 05:51:28 |
Record full path of the cert for openssl | 66e89d4e0eaf638859b39c791d82d233e2d0c2c2 | Catalin(ux) M. BOIE | 2023-03-03 18:41:57 |
Improve presentation | 0600fd3c6e5fcb0dd152d0e680ea85a8ae89bd86 | Catalin(ux) M. BOIE | 2022-12-09 17:46:09 |
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 |
File .gitignore changed (mode: 100644) (index dad677a..fe99470) | |||
... | ... | obj/ | |
20 | 20 | *.db | *.db |
21 | 21 | *.asm | *.asm |
22 | 22 | *.tmp | *.tmp |
23 | Makefile.common | ||
24 | *.jar |
File Makefile.common.in added (mode: 100644) (index 0000000..14f7cf4) | |||
1 | CC_SWITCHES := @CC_SWITCHES@ | ||
2 | I_USR := @USR@ | ||
3 | I_USR_BIN := @USR_BIN@ | ||
4 | I_USR_SBIN := @USR_SBIN@ | ||
5 | I_USR_LIB := @USR_LIB@ | ||
6 | I_USR_SHARE := @USR_SHARE@ | ||
7 | I_VAR_LOG := @VAR_LOG@ | ||
8 | I_VAR_LIB := @VAR_LIB@ | ||
9 | I_ETC := @ETC@ | ||
10 | |||
11 | export CC := gcc | ||
12 | export INCS := | ||
13 | export LIBS := | ||
14 | export CFLAGS := $(CC_SWITCHES) | ||
15 | export CFLAGS += -ggdb -Wall -Wextra -pipe | ||
16 | |||
17 | export GNUTLS_LIBS := $(shell pkg-config --libs gnutls) | ||
18 | export GNUTLS_CFLAGS := $(shell pkg-config --cflags gnutls) | ||
19 | |||
20 | export JSON_LIBS := $(shell pkg-config --libs json-c) | ||
21 | export JSON_CFLAGS := $(shell pkg-config --cflags json-c) | ||
22 | |||
23 | export CFLAGSSO := -ldl -lrt -shared -rdynamic -fPIC | ||
24 | |||
25 | export CURL_LIBS := $(shell pkg-config libcurl --libs) | ||
26 | |||
27 | # for shm_open | ||
28 | export LIBS += -lrt | ||
29 |
File Makefile.in changed (mode: 100644) (index ec4811b..746d28d) | |||
1 | export CC := gcc | ||
2 | export INCS += | ||
3 | export LIBS += | ||
4 | export CFLAGS += @CC_SWITCHES@ | ||
5 | export CFLAGS += -ggdb -Wall -Wextra -pipe | ||
6 | export CFLAGS += -D _FORTIFY_SOURCES=2 | ||
1 | ALL := common agent ingestd webd trace misc tools docs | ||
7 | 2 | ||
8 | export GNUTLS_LIBS += $(shell pkg-config --libs gnutls) | ||
9 | export GNUTLS_CFLAGS += $(shell pkg-config --cflags gnutls) | ||
3 | all: $(ALL) | ||
10 | 4 | ||
11 | export JSON_LIBS += $(shell pkg-config --libs json-c) | ||
12 | export JSON_CFLAGS += $(shell pkg-config --cflags json-c) | ||
13 | |||
14 | export CFLAGSSO = $(CFLAGS) -ldl -shared -rdynamic -fPIC | ||
15 | |||
16 | |||
17 | all: common agent ingestd webd trace misc docs | ||
18 | |||
19 | |||
20 | .PHONY: common | ||
5 | .PHONY: $(ALL) | ||
21 | 6 | common: | common: |
22 | 7 | make -R -C common compile | make -R -C common compile |
23 | 8 | ||
24 | .PHONY: agent | ||
25 | 9 | agent: | agent: |
26 | make -R -C agent compile | ||
10 | make -R -C agent | ||
27 | 11 | ||
28 | .PHONY: ingestd | ||
29 | 12 | ingestd: | ingestd: |
30 | make -R -C ingestd compile | ||
13 | make -R -C ingestd | ||
31 | 14 | ||
32 | .PHONY: webd | ||
33 | 15 | webd: | webd: |
34 | make -R -C webd compile | ||
16 | make -R -C webd | ||
35 | 17 | ||
36 | .PHONY: trace | ||
37 | 18 | trace: | trace: |
38 | make -R -C trace compile | ||
19 | make -R -C trace | ||
39 | 20 | ||
40 | .PHONY: misc | ||
41 | 21 | misc: | misc: |
42 | make -R -C misc compile | ||
22 | make -R -C misc | ||
23 | |||
24 | tools: | ||
25 | make -R -C tools | ||
43 | 26 | ||
44 | .PHONY: docs | ||
45 | 27 | docs: | docs: |
46 | make -R -C docs compile | ||
28 | make -R -C docs | ||
29 | |||
47 | 30 | ||
48 | 31 | .PHONY: install | .PHONY: install |
49 | 32 | install: | install: |
50 | 33 | @mkdir -p $(I_VAR_LOG)/ninedogs | @mkdir -p $(I_VAR_LOG)/ninedogs |
34 | @chown -R ninedogs:ninedogs $(I_VAR_LOG)/ninedogs | ||
51 | 35 | @mkdir -p $(I_USR_SHARE)/ninedogs | @mkdir -p $(I_USR_SHARE)/ninedogs |
52 | 36 | @mkdir -p $(I_VAR_LIB)/ninedogs | @mkdir -p $(I_VAR_LIB)/ninedogs |
37 | @chown -R ninedogs:ninedogs $(I_VAR_LIB)/ninedogs | ||
53 | 38 | @make -C agent install | @make -C agent install |
54 | 39 | @make -C ingestd install | @make -C ingestd install |
55 | 40 | @make -C webd install | @make -C webd install |
56 | 41 | @make -C trace install | @make -C trace install |
57 | 42 | @make -C misc install | @make -C misc install |
43 | @make -C tools install | ||
58 | 44 | @mkdir -p $(I_ETC)/nginx/conf.d | @mkdir -p $(I_ETC)/nginx/conf.d |
59 | 45 | @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 |
60 | 46 | @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 |
... | ... | clean: | |
67 | 53 | @make -R -C ingestd clean | @make -R -C ingestd clean |
68 | 54 | @make -R -C webd clean | @make -R -C webd clean |
69 | 55 | @make -R -C trace clean | @make -R -C trace clean |
56 | @make -R -C misc clean | ||
57 | @make -R -C tools clean | ||
70 | 58 |
File TODO changed (mode: 100644) (index fb26266..1b0b498) | |||
1 | 1 | == Urgent == | == Urgent == |
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 | [ ] Seems that running 'php-container' test, the query does not hit the server. | ||
4 | It may be the connection is closed too soon. | ||
5 | [ ] Restarting ingestd - rocketgit builder does not reconnect | ||
6 | [ ] The whole thing with process_db variable 'stable' seems to not work. | ||
7 | Or I do not understand it anymore! | ||
8 | [ ] zend_array_to_params_array could be moved in a more generic .c file? | ||
9 | [ ] nd_params_array seems to be defined in multiple places. | ||
3 | 10 | [ ] | [ ] |
4 | 11 | ||
5 | 12 | ||
6 | 13 | == Non-urgent | == Non-urgent |
14 | [ ] Java + mysql | ||
15 | [ ] We can compare the result set of db queries and suggest some caching. | ||
16 | Better, implement the cache in ninedogs! | ||
17 | [ ] Add informations about replication status and incidents. | ||
7 | 18 | [ ] Both client and server side are free (AGPLv3). | [ ] Both client and server side are free (AGPLv3). |
8 | 19 | Offering this as a SaaS may bring some money to support | Offering this as a SaaS may bring some money to support |
9 | 20 | the development. | the development. |
11 | 22 | [ ] We can easily provide a vault service by hijacking getenv | [ ] We can easily provide a vault service by hijacking getenv |
12 | 23 | And providing a filesystem. | And providing a filesystem. |
13 | 24 | [ ] We can act also as a vault (both env vars and filesystem). | [ ] We can act also as a vault (both env vars and filesystem). |
25 | [ ] Create filters from the log search UI. | ||
26 | [ ] Show hostname mismatch: the one in certificate with the one we are connecting to. | ||
27 | [ ] When connecting somewhere by https, alert if some intermediate or root cert | ||
28 | is not known locally? | ||
14 | 29 | [ ] | [ ] |
15 | 30 | ||
16 | 31 |
File agent/Makefile changed (mode: 100644) (index 93de780..c5ed207) | |||
1 | # This is just to allow us to run make here | ||
2 | .PHONY: all | ||
3 | all: | ||
4 | make -R -C .. agent | ||
1 | include ../Makefile.common | ||
5 | 2 | ||
6 | 3 | COMMON_H += ../common/ids.h ../common/tools.h ../common/decode_text.h \ | COMMON_H += ../common/ids.h ../common/tools.h ../common/decode_text.h \ |
4 | ../common/params.h \ | ||
7 | 5 | ctools.h | ctools.h |
8 | 6 | ||
9 | 7 | CFLAGS += -I../common | CFLAGS += -I../common |
10 | 8 | ||
11 | OBJS := decode.o ctools.o php.o process.o process_core.o process_misc.o \ | ||
9 | OBJS := decode.o ctools.o process.o process_core.o process_misc.o \ | ||
12 | 10 | process_db.o process_ssl.o process_url.o \ | process_db.o process_ssl.o process_url.o \ |
13 | 11 | openssl.o gnutls.o text2process.o \ | openssl.o gnutls.o text2process.o \ |
14 | 12 | python.o curl.o \ | python.o curl.o \ |
13 | php-core.o php-curl.o php-mysql.o php-oci.o php-pg.o php.o \ | ||
14 | c/oci.o \ | ||
15 | php/gd.o \ | ||
16 | trace_encode.o \ | ||
15 | 17 | ../common/tools.o ../common/info.o ../common/decode_text.o | ../common/tools.o ../common/info.o ../common/decode_text.o |
16 | 18 | ||
19 | all: ninedogs_dlsym_env.so ninedogs_dlsym_func.so ninedogs.so | ||
20 | |||
17 | 21 | decode.o: decode.c decode.h process_db.h process_url.h $(COMMON_H) | decode.o: decode.c decode.h process_db.h process_url.h $(COMMON_H) |
18 | 22 | $(CC) $(CFLAGS) -fPIC -c -o $@ $< | $(CC) $(CFLAGS) -fPIC -c -o $@ $< |
19 | 23 | ||
20 | 24 | ctools.o: ctools.c $(COMMON_H) ../common/tools.h | ctools.o: ctools.c $(COMMON_H) ../common/tools.h |
21 | 25 | $(CC) $(CFLAGS) -fPIC -c -o $@ $< | $(CC) $(CFLAGS) -fPIC -c -o $@ $< |
22 | 26 | ||
23 | php.o: php.c php.h process_db.h process_url.h $(COMMON_H) | ||
27 | php-core.o: php-core.c php-core.h $(COMMON_H) | ||
28 | $(CC) $(CFLAGS) -fPIC -c -o $@ $< | ||
29 | |||
30 | php-curl.o: php-curl.c php-curl.h php-core.h process_url.h $(COMMON_H) | ||
31 | $(CC) $(CFLAGS) -fPIC -c -o $@ $< | ||
32 | |||
33 | php-mysql.o: php-mysql.c php-mysql.h php-core.h process_db.h $(COMMON_H) | ||
34 | $(CC) $(CFLAGS) -fPIC -c -o $@ $< | ||
35 | |||
36 | php-oci.o: php-oci.c php-oci.h php-core.h process_db.h $(COMMON_H) | ||
37 | $(CC) $(CFLAGS) -fPIC -c -o $@ $< | ||
38 | |||
39 | php-pg.o: php-pg.c php-pg.h php-core.h process_db.h $(COMMON_H) | ||
40 | $(CC) $(CFLAGS) -fPIC -c -o $@ $< | ||
41 | |||
42 | php.o: php.c php.h process_db.h process_url.h php-oci.h $(COMMON_H) | ||
24 | 43 | $(CC) $(CFLAGS) -fPIC -c -o $@ $< | $(CC) $(CFLAGS) -fPIC -c -o $@ $< |
25 | 44 | ||
26 | 45 | curl.o: curl.c curl.h $(COMMON_H) | curl.o: curl.c curl.h $(COMMON_H) |
... | ... | process_url.o: process_url.c process_url.h $(COMMON_H) | |
54 | 73 | process_ssl.o: process_ssl.c process_ssl.h $(COMMON_H) | process_ssl.o: process_ssl.c process_ssl.h $(COMMON_H) |
55 | 74 | $(CC) $(CFLAGS) -fPIC -c -o $@ $< | $(CC) $(CFLAGS) -fPIC -c -o $@ $< |
56 | 75 | ||
57 | text2process.o: text2process.c text2process.h $(COMMON_H) | ||
76 | text2process.o: text2process.c text2process.h process_db.h process_ssl.h $(COMMON_H) | ||
77 | $(CC) $(CFLAGS) -fPIC -c -o $@ $< | ||
78 | |||
79 | trace_encode.o: trace_encode.c trace_encode.h $(COMMON_H) | ||
58 | 80 | $(CC) $(CFLAGS) -fPIC -c -o $@ $< | $(CC) $(CFLAGS) -fPIC -c -o $@ $< |
59 | 81 | ||
60 | 82 | ninedogs_dlsym_env.so: ninedogs_dlsym_env.c | ninedogs_dlsym_env.so: ninedogs_dlsym_env.c |
... | ... | ninedogs_dlsym_env.so: ninedogs_dlsym_env.c | |
63 | 85 | ninedogs_dlsym_func.so: ninedogs_dlsym_func.c | ninedogs_dlsym_func.so: ninedogs_dlsym_func.c |
64 | 86 | $(CC) $(CFLAGSSO) -Wl,-soname,ninedogs_dlsym_func.so -o $@ $< | $(CC) $(CFLAGSSO) -Wl,-soname,ninedogs_dlsym_func.so -o $@ $< |
65 | 87 | ||
88 | |||
89 | c/oci.o: c/oci.c c/oci.h process_db.h $(COMMON_H) | ||
90 | $(CC) $(CFLAGS) -fPIC -c -o $@ $< | ||
91 | |||
92 | |||
93 | php/gd.o: php/gd.c php/gd.h $(COMMON_H) | ||
94 | $(CC) $(CFLAGS) -fPIC -c -o $@ $< | ||
95 | |||
96 | |||
66 | 97 | ninedogs.so: ninedogs.c $(OBJS) $(COMMON_H) ../common/shared.h curl.h \ | ninedogs.so: ninedogs.c $(OBJS) $(COMMON_H) ../common/shared.h curl.h \ |
67 | process_db.h process_url.h | ||
98 | process_db.h process_url.h trace_encode.h | ||
68 | 99 | $(CC) $(CFLAGS) $(CFLAGSSO) -Wl,-soname,ninedogs.so -o $@ ninedogs.c \ | $(CC) $(CFLAGS) $(CFLAGSSO) -Wl,-soname,ninedogs.so -o $@ ninedogs.c \ |
69 | 100 | $(OBJS) $(LIBS) $(GNUTLS_LIBS) | $(OBJS) $(LIBS) $(GNUTLS_LIBS) |
70 | 101 | ||
71 | |||
72 | compile: ninedogs_dlsym_env.so ninedogs_dlsym_func.so ninedogs.so | ||
73 | |||
74 | 102 | .PHONY: clean | .PHONY: clean |
75 | 103 | clean: | clean: |
76 | 104 | @rm -f ninedogs*.so.* *.strace *.log *.out *.o | @rm -f ninedogs*.so.* *.strace *.log *.out *.o |
77 | 105 | ||
78 | 106 | install: all | install: all |
79 | @mkdir -p $(I_USR_LIB) | ||
107 | @mkdir -p $(I_USR_LIB)/ninedogs | ||
80 | 108 | cp -vd ninedogs*.so $(I_USR_LIB) | cp -vd ninedogs*.so $(I_USR_LIB) |
81 | 109 |
File agent/c/TODO added (mode: 100644) (index 0000000..c126628) | |||
1 | == Urgent == | ||
2 | [ ] We understand only OCI_NTV_SYNTAX for OciStmtPrepare | ||
3 | [ ] When we detach from a server, we need to clean all stmts linked with it. | ||
4 | [ ] | ||
5 | |||
6 | == Not urgent == | ||
7 | [ ] Add 'rcode' decoding. | ||
8 | [ ] Decode SUCCESS_WITH_INFO | ||
9 | [ ] If we bind the same position/name, should we overwrite a previous entry in nd_params_array_one? | ||
10 | [ ] | ||
11 |
File agent/c/oci.c added (mode: 100644) (index 0000000..f473562) | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <string.h> | ||
4 | |||
5 | #include "../../common/ids.h" | ||
6 | #include "../../common/tools.h" | ||
7 | #include "../ctools.h" | ||
8 | #include "../ninedogs.h" | ||
9 | #include "../process_db.h" | ||
10 | #include "oci.h" | ||
11 | |||
12 | // TODO: what about 'ind' and sending nulls | ||
13 | |||
14 | #define OCI_STMT_TRACK_MAX 100 | ||
15 | struct oci_stmt_track | ||
16 | { | ||
17 | void *stmt; | ||
18 | const char *q; | ||
19 | unsigned int q_len; | ||
20 | unsigned int pad; | ||
21 | struct nd_params_array binds; | ||
22 | }; | ||
23 | static __thread struct oci_stmt_track track[OCI_STMT_TRACK_MAX]; | ||
24 | |||
25 | static void stmt_clean(void *stmt) | ||
26 | { | ||
27 | for (unsigned i = 0; i < OCI_STMT_TRACK_MAX; i++) { | ||
28 | if (track[i].stmt == stmt) { | ||
29 | memset(&track[i], 0, sizeof(track[i])); | ||
30 | break; | ||
31 | } | ||
32 | } | ||
33 | } | ||
34 | |||
35 | static struct oci_stmt_track *stmt_find(const void *stmt) | ||
36 | { | ||
37 | for (unsigned i = 0; i < OCI_STMT_TRACK_MAX; i++) { | ||
38 | if (track[i].stmt == stmt) | ||
39 | return &track[i]; | ||
40 | } | ||
41 | |||
42 | return NULL; | ||
43 | } | ||
44 | |||
45 | static struct oci_stmt_track *stmt_alloc(const void *func, void *stmt) | ||
46 | { | ||
47 | for (unsigned i = 0; i < OCI_STMT_TRACK_MAX; i++) { | ||
48 | if (track[i].stmt == NULL) { | ||
49 | track[i].stmt = stmt; | ||
50 | return &track[i]; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | xlog(0, "%s: cannot find a free slot for stmt %p!\n", func, stmt); | ||
55 | return NULL; | ||
56 | } | ||
57 | |||
58 | static void stmt_add_query(void *stmt, const char *q, | ||
59 | const unsigned int q_len) | ||
60 | { | ||
61 | struct oci_stmt_track *s = stmt_find(stmt); | ||
62 | if (!s) | ||
63 | s = stmt_alloc(__func__, stmt); | ||
64 | if (!s) | ||
65 | return; | ||
66 | s->q = q; | ||
67 | s->q_len = q_len; | ||
68 | } | ||
69 | |||
70 | static unsigned char dty_to_nd_type(unsigned short dty) | ||
71 | { | ||
72 | switch (dty) { | ||
73 | case 2: return ND_TYPE_STRING; // SQLT_NUM | ||
74 | case 3: return ND_TYPE_INT; | ||
75 | case 5: return ND_TYPE_STRING; | ||
76 | case 8: return ND_TYPE_STRING; // SQLT_LONG seems to be string | ||
77 | default: return ND_TYPE_UNK; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | // TODO: this should be moved into 'process_db.c' | ||
82 | /* @bind_or_def: 0=bind, 1=def | ||
83 | */ | ||
84 | static void stmt_bind_or_def_by_name_or_pos(const int bind_or_def, void *stmt, | ||
85 | const char *name, const unsigned int pos, unsigned short dty, | ||
86 | void *value, const int value_size) | ||
87 | { | ||
88 | xlog(1, "%s: bind_or_def=%u stmt=%p name=[%s] pos=[%u]" | ||
89 | " dty=%hu value=%p value_size=%d\n", | ||
90 | __func__, bind_or_def, stmt, name, pos, dty, | ||
91 | value, value_size); | ||
92 | |||
93 | struct oci_stmt_track *q = stmt_find(stmt); | ||
94 | if (!q) | ||
95 | q = stmt_alloc(__func__, stmt); | ||
96 | if (!q) | ||
97 | return; | ||
98 | |||
99 | for (unsigned short i = 0; i < ND_PARAMS_MAX; i++) { | ||
100 | struct nd_params_array_one *o = &q->binds.list[i]; | ||
101 | |||
102 | if (o->type != ND_TYPE_FREE_SLOT) | ||
103 | continue; | ||
104 | |||
105 | if (name) { | ||
106 | snprintf(o->name, sizeof(o->name), "%s", name); | ||
107 | o->bind_type = ND_PARAMS_BIND_TYPE_NAME; | ||
108 | } else { | ||
109 | o->pos = pos; | ||
110 | o->bind_type = ND_PARAMS_BIND_TYPE_POS; | ||
111 | } | ||
112 | o->type = dty_to_nd_type(dty); | ||
113 | o->pointer = 1; | ||
114 | o->str = value; | ||
115 | o->length = value_size; | ||
116 | o->bind_way = bind_or_def; | ||
117 | break; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | static void stmt_bind_by_name(void *stmt, const char *name, unsigned short dty, | ||
122 | void *value, const int value_size) | ||
123 | { | ||
124 | stmt_bind_or_def_by_name_or_pos(ND_PARAMS_BIND_WAY_BOTH, stmt, | ||
125 | name, 0 /*pos*/, dty, value, value_size); | ||
126 | } | ||
127 | |||
128 | static void stmt_bind_by_pos(void *stmt, const unsigned int pos, unsigned short dty, | ||
129 | void *value, const int value_size) | ||
130 | { | ||
131 | stmt_bind_or_def_by_name_or_pos(ND_PARAMS_BIND_WAY_BOTH, stmt, | ||
132 | NULL/*name*/, pos, dty, value, value_size); | ||
133 | } | ||
134 | |||
135 | static void stmt_def_by_name(void *stmt, const char *name, unsigned short dty, | ||
136 | void *value, const int value_size) | ||
137 | { | ||
138 | stmt_bind_or_def_by_name_or_pos(ND_PARAMS_BIND_WAY_OUT, stmt, | ||
139 | name, 0 /*pos*/, dty, value, value_size); | ||
140 | } | ||
141 | |||
142 | static void stmt_def_by_pos(void *stmt, const unsigned int pos, unsigned short dty, | ||
143 | void *value, const int value_size) | ||
144 | { | ||
145 | stmt_bind_or_def_by_name_or_pos(ND_PARAMS_BIND_WAY_OUT, stmt, | ||
146 | NULL/*name*/, pos, dty, value, value_size); | ||
147 | } | ||
148 | |||
149 | |||
150 | // TODO: check ** | ||
151 | static sword (*old_OCIAttrSet)(void *, unsigned int, void *, unsigned int, | ||
152 | unsigned int, void *); | ||
153 | sword OCIAttrSet(void *h, unsigned int htype, void *attr, unsigned int attr_size, | ||
154 | unsigned int attr_type, void *oci_err) | ||
155 | { | ||
156 | if (!old_OCIAttrSet) | ||
157 | old_OCIAttrSet = ninedogs_dlsym("OCIAttrSet"); | ||
158 | |||
159 | xlog(100, "%s(h=%p htype=%u attr=%p attr_size=%u attr_type=%u oci_err=%p)\n", | ||
160 | __func__, h, htype, attr, attr_size, attr_type, oci_err); | ||
161 | sword ret = old_OCIAttrSet(h, htype, attr, attr_size, attr_type, oci_err); | ||
162 | my_trace(__func__, "i", 'R', h, htype, attr, attr_size, attr_type, oci_err, ret); | ||
163 | |||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | static sword (*old_OCIBindByName)(void *, void **, void *, const char *, | ||
168 | int, void *, int, unsigned short, void *, unsigned short *, | ||
169 | unsigned short *, unsigned int, unsigned int *, unsigned int); | ||
170 | sword OCIBindByName(void *stmt, void **bind, void *oci_error, | ||
171 | const char *ph, int ph_len, void *value, int value_size, | ||
172 | unsigned short dty, void *ind, unsigned short *alen, | ||
173 | unsigned short *rcode, unsigned int maxarr_len, | ||
174 | unsigned int *curelep, unsigned int mode) | ||
175 | { | ||
176 | if (!old_OCIBindByName) | ||
177 | old_OCIBindByName = ninedogs_dlsym("OCIBindByName"); | ||
178 | |||
179 | sword ret = old_OCIBindByName(stmt, bind, oci_error, ph, ph_len, | ||
180 | value, value_size, dty, ind, alen, rcode, maxarr_len, | ||
181 | curelep, mode); | ||
182 | // we do not send 'value' because it may not be set at this time | ||
183 | my_trace(__func__, "i", 'R', stmt, bind, oci_error, ph, ph_len, | ||
184 | value_size, dty, ind, alen, rcode, maxarr_len, | ||
185 | curelep, mode, ret); | ||
186 | if (alen) { | ||
187 | char dump[256 * 4 + 1]; | ||
188 | bin2hex_ascii(dump, alen, 16); | ||
189 | xlog(0, " DEBUG: alen: %s.\n", dump); | ||
190 | } | ||
191 | |||
192 | if (ret == 0) | ||
193 | stmt_bind_by_name(stmt, ph, dty, value, value_size); | ||
194 | |||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | static sword (*old_OCIDefineByPos)(void *, void **, void *, unsigned int, | ||
199 | void *, int, unsigned short, void *, | ||
200 | unsigned short *, unsigned short *, unsigned int); | ||
201 | sword OCIDefineByPos(void *stmt, void **defn, void *oci_error, unsigned int pos, | ||
202 | void *value, int value_size, unsigned short dty, void *ind, | ||
203 | unsigned short *rlen, unsigned short *rcode, unsigned int mode) | ||
204 | { | ||
205 | if (!old_OCIDefineByPos) | ||
206 | old_OCIDefineByPos = ninedogs_dlsym("OCIDefineByPos"); | ||
207 | |||
208 | sword ret = old_OCIDefineByPos(stmt, defn, oci_error, pos, | ||
209 | value, value_size, dty, ind, rlen, rcode, mode); | ||
210 | my_trace(__func__, "i", 'R', stmt, defn, oci_error, pos, | ||
211 | value_size, dty, ind, rlen, rcode, mode, ret); | ||
212 | |||
213 | #if 0 | ||
214 | if (alen && *alen) { | ||
215 | char dump[256 * 4 + 1]; | ||
216 | bin2hex_ascii(dump, *alen, 16); | ||
217 | xlog(0, " DEBUG: alen: %s.\n", dump); | ||
218 | } | ||
219 | #endif | ||
220 | |||
221 | // TODO: store also the query in the tracking; send it only once to the tracer? | ||
222 | |||
223 | if (ret == 0) | ||
224 | stmt_def_by_pos(stmt, pos, dty, value, value_size); | ||
225 | |||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | static void (*old_OCIHandleAlloc)(const void *, void **, unsigned int, | ||
230 | size_t, void **); | ||
231 | void OCIHandleAlloc(const void *parent, void **dbh, unsigned int type, | ||
232 | size_t extra_mem, void **user_mem) | ||
233 | { | ||
234 | if (!old_OCIHandleAlloc) | ||
235 | old_OCIHandleAlloc = ninedogs_dlsym("OCIHandleAlloc"); | ||
236 | |||
237 | old_OCIHandleAlloc(parent, dbh, type, extra_mem, user_mem); | ||
238 | my_trace(__func__, "i", 'R', parent, dbh, type, extra_mem, user_mem); | ||
239 | |||
240 | //if (type == 4) // 4=stmt | ||
241 | // stmt_clean(stmt); TODO - we may want to record 'parent'? | ||
242 | } | ||
243 | |||
244 | static void (*old_OCIHandleFree)(void *, unsigned int); | ||
245 | void OCIHandleFree(void *hnd, unsigned int type) | ||
246 | { | ||
247 | if (!old_OCIHandleFree) | ||
248 | old_OCIHandleFree = ninedogs_dlsym("OCIHandleFree"); | ||
249 | |||
250 | old_OCIHandleFree(hnd, type); | ||
251 | my_trace(__func__, "i", 'R', hnd, type); | ||
252 | |||
253 | if (type == 4) // 4=stmt | ||
254 | stmt_clean(hnd); | ||
255 | } | ||
256 | |||
257 | // TODO: check ** | ||
258 | static sword (*old_OCIServerAttach)(void *, void *, char *, int, unsigned int); | ||
259 | sword OCIServerAttach(void *oci_server, void *oci_error, char *db_link, | ||
260 | int db_link_len, unsigned int mode) | ||
261 | { | ||
262 | if (!old_OCIServerAttach) | ||
263 | old_OCIServerAttach = ninedogs_dlsym("OCIServerAttach"); | ||
264 | |||
265 | my_trace(__func__, "i", 'c', oci_server, oci_error, db_link, db_link_len, mode); | ||
266 | sword ret = old_OCIServerAttach(oci_server, oci_error, db_link, db_link_len, mode); | ||
267 | my_trace(__func__, "i", 'r', oci_server, oci_error, db_link, db_link_len, mode, ret); | ||
268 | |||
269 | return ret; | ||
270 | } | ||
271 | |||
272 | static sword (*old_OCIServerDetach)(void *, void *, unsigned int); | ||
273 | sword OCIServerDetach(void *oci_server, void *oci_error, unsigned int mode) | ||
274 | { | ||
275 | if (!old_OCIServerDetach) | ||
276 | old_OCIServerDetach = ninedogs_dlsym("OCIServerDetach"); | ||
277 | |||
278 | my_trace(__func__, "i", 'c', oci_server, oci_error, mode); | ||
279 | sword ret = old_OCIServerDetach(oci_server, oci_error, mode); | ||
280 | my_trace(__func__, "i", 'r', oci_server, oci_error, mode, ret); | ||
281 | |||
282 | return ret; | ||
283 | } | ||
284 | |||
285 | static sword (*old_OCIStmtExecute)(void *, void *, void *, unsigned int, | ||
286 | unsigned int, void *, void *, unsigned int); | ||
287 | sword OCIStmtExecute(void *svc, void *stmt, void *err, unsigned int iters, | ||
288 | unsigned int rowoff, void *snap_in, void *snap_out, unsigned int mode) | ||
289 | { | ||
290 | if (!old_OCIStmtExecute) | ||
291 | old_OCIStmtExecute = ninedogs_dlsym("OCIStmtExecute"); | ||
292 | |||
293 | struct oci_stmt_track *q = stmt_find(stmt); | ||
294 | if (q) | ||
295 | my_trace(__func__, "i", 'm', stmt, ND_PARAMS_BIND_WAY_IN, | ||
296 | &q->binds, q->q, q->q_len); | ||
297 | my_trace(__func__, "i", 'c', svc, stmt, err, iters, rowoff, snap_in, snap_out, mode); | ||
298 | sword ret = old_OCIStmtExecute(svc, stmt, err, iters, rowoff, snap_in, snap_out, mode); | ||
299 | my_trace(__func__, "i", 'r', svc, stmt, err, iters, rowoff, snap_in, snap_out, mode, ret); | ||
300 | if (((ret == 0) || (ret == 1)) && q) | ||
301 | my_trace(__func__, "i", 'm', stmt, ND_PARAMS_BIND_WAY_OUT, &q->binds); | ||
302 | |||
303 | return ret; | ||
304 | } | ||
305 | |||
306 | // TODO: check ** | ||
307 | static sword (*old_OCIStmtPrepare)(void *, void *, const char *, unsigned int, | ||
308 | unsigned int, unsigned int); | ||
309 | sword OCIStmtPrepare(void *stmt, void *oci_error, const char *q, | ||
310 | unsigned int q_len, unsigned int lang, unsigned int mode) | ||
311 | { | ||
312 | if (!old_OCIStmtPrepare) | ||
313 | old_OCIStmtPrepare = ninedogs_dlsym("OCIStmtPrepare"); | ||
314 | |||
315 | sword ret = old_OCIStmtPrepare(stmt, oci_error, q, q_len, lang, mode); | ||
316 | my_trace(__func__, "i", 'R', stmt, oci_error, q, q_len, lang, mode, ret); | ||
317 | |||
318 | if (ret == 0) | ||
319 | stmt_add_query(stmt, q, q_len); | ||
320 | |||
321 | return ret; | ||
322 | } | ||
323 | |||
324 | static sword (*old_OCITransCommit)(void *, void *, unsigned int); | ||
325 | sword OCITransCommit(void *svc, void *oci_error, unsigned int flags) | ||
326 | { | ||
327 | if (!old_OCITransCommit) | ||
328 | old_OCITransCommit = ninedogs_dlsym("OCITransCommit"); | ||
329 | |||
330 | my_trace(__func__, "i", 'c', svc, oci_error, flags); | ||
331 | sword ret = old_OCITransCommit(svc, oci_error, flags); | ||
332 | my_trace(__func__, "i", 'r', svc, oci_error, flags, ret); | ||
333 | |||
334 | return ret; | ||
335 | } | ||
336 | |||
337 | static sword (*old_OCITransRollback)(void *, void *, unsigned int); | ||
338 | sword OCITransRollback(void *svc, void *oci_error, unsigned int flags) | ||
339 | { | ||
340 | if (!old_OCITransRollback) | ||
341 | old_OCITransRollback = ninedogs_dlsym("OCITransRollback"); | ||
342 | |||
343 | my_trace(__func__, "i", 'c', svc, oci_error, flags); | ||
344 | sword ret = old_OCITransRollback(svc, oci_error, flags); | ||
345 | my_trace(__func__, "i", 'r', svc, oci_error, flags, ret); | ||
346 | |||
347 | return ret; | ||
348 | } | ||
349 | |||
350 | static sword (*old_OCITransStart)(void *, void *, unsigned int, unsigned int); | ||
351 | sword OCITransStart(void *svc, void *oci_error, unsigned int timeout, | ||
352 | unsigned int flags) | ||
353 | { | ||
354 | if (!old_OCITransStart) | ||
355 | old_OCITransStart = ninedogs_dlsym("OCITransStart"); | ||
356 | |||
357 | sword ret = old_OCITransStart(svc, oci_error, timeout, flags); | ||
358 | my_trace(__func__, "i", 'R', svc, oci_error, flags, timeout, ret); | ||
359 | |||
360 | return ret; | ||
361 | } | ||
362 | |||
363 | // TODO: OCISessionBegin | ||
364 | // TODO: OCIHandleFree | ||
365 | // TODO: OCISessionEnd | ||
366 | // TODO: OCITerminate ? | ||
367 | // TODO: OCIEnvCreate | ||
368 | // TODO: '2' variants! | ||
369 | // TODO: OCIStmtRelease |
File agent/c/oci.h added (mode: 100644) (index 0000000..99bccb0) | |||
1 | typedef signed int sword; | ||
2 | |||
3 | sword OCIAttrSet(void *h, unsigned int htype, void *attr, unsigned int attr_size, | ||
4 | unsigned int attr_type, void *oci_err); | ||
5 | sword OCIBindByName(void *stmt, void **bind, void *oci_error, | ||
6 | const char *ph, int ph_len, void *value, int value_size, | ||
7 | unsigned short dty, void *ind, unsigned short *alen, | ||
8 | unsigned short *rcode, unsigned int maxarr_len, | ||
9 | unsigned int *curelep, unsigned int mode); | ||
10 | sword OCIDefineByPos(void *stmt, void **defn, void *oci_error, unsigned int pos, | ||
11 | void *value, int value_size, unsigned short dty, void *ind, | ||
12 | unsigned short *rlen, unsigned short *rcode, unsigned int mode); | ||
13 | void OCIHandleAlloc(const void *parent, void **dbh, unsigned int type, | ||
14 | size_t extra_mem, void **user_mem); | ||
15 | void OCIHandleFree(void *hnd, unsigned int type); | ||
16 | sword OCIServerAttach(void *oci_server, void *oci_error, char *db_link, | ||
17 | int db_link_len, unsigned int mode); | ||
18 | sword OCIServerDetach(void *oci_server, void *oci_error, unsigned int mode); | ||
19 | sword OCIStmtExecute(void *svc, void *stmt, void *err, unsigned int iters, | ||
20 | unsigned int rowoff, void *snap_in, void *snap_out, unsigned int mode); | ||
21 | sword OCIStmtPrepare(void *stmt, void *err, const char *q, unsigned int q_len, | ||
22 | unsigned int lang, unsigned int mode); | ||
23 | sword OCITransCommit(void *svc, void *oci_error, unsigned int flags); | ||
24 | sword OCITransRollback(void *svc, void *oci_error, unsigned int flags); | ||
25 | sword OCITransStart(void *svc, void *oci_error, unsigned int timeout, | ||
26 | unsigned int flags); | ||
27 |
File agent/ctools.c changed (mode: 100644) (index 48835b7..11cb5f2) | |||
... | ... | void send_sysinfo(void) | |
1116 | 1116 | ||
1117 | 1117 | unsigned char *buf; | unsigned char *buf; |
1118 | 1118 | unsigned int len; | unsigned int len; |
1119 | pack(&buf, &len, "T4 NN u8" "18 58 q8" "r8 f8 s8" "b8 w8 W8" "p2 h8 H8 i4", | ||
1119 | pack(&buf, &len, "T4 _N u8" "18 58 q8" "r8 f8 s8" "b8 w8 W8" "p2 h8 H8 i4", | ||
1120 | 1120 | NINEDOGS_NET_CORE_SYSINFO, s.uptime, | NINEDOGS_NET_CORE_SYSINFO, s.uptime, |
1121 | 1121 | s.loads[0], s.loads[1], s.loads[2], | s.loads[0], s.loads[1], s.loads[2], |
1122 | 1122 | s.totalram, s.freeram, s.sharedram, | s.totalram, s.freeram, s.sharedram, |
File agent/ctools.h changed (mode: 100644) (index e93e17b..15beff4) | |||
1 | #include <sys/syscall.h> | ||
2 | |||
1 | 3 | #include <arpa/inet.h> | #include <arpa/inet.h> |
2 | 4 | #include <netinet/in.h> | #include <netinet/in.h> |
3 | 5 | #include <netinet/tcp.h> | #include <netinet/tcp.h> |
4 | 6 | ||
7 | // On RockyLinux 8, gettid is not defined | ||
8 | #if (__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 30)) | ||
9 | #define gettid() (syscall(SYS_gettid)) | ||
10 | #endif | ||
11 | |||
5 | 12 | struct private | struct private |
6 | 13 | { | { |
7 | 14 | int domain; | int domain; |
File agent/curl.c changed (mode: 100644) (index ebfc058..19e9728) | |||
8 | 8 | extern void *(*old_malloc)(size_t size); | extern void *(*old_malloc)(size_t size); |
9 | 9 | extern void xlog(const unsigned int level, const char *format, ...); | extern void xlog(const unsigned int level, const char *format, ...); |
10 | 10 | extern void *ninedogs_dlsym(const char *sym); | extern void *ninedogs_dlsym(const char *sym); |
11 | extern void my_trace(const char *func, const char type, ...); | ||
11 | extern void my_trace(const char *func, const char *tf, const char type, ...); | ||
12 | 12 | ||
13 | 13 | ||
14 | 14 | // Track setopt stuff | // Track setopt stuff |
... | ... | CURL *curl_easy_init(void) | |
107 | 107 | old_curl_easy_init = ninedogs_dlsym("curl_easy_init"); | old_curl_easy_init = ninedogs_dlsym("curl_easy_init"); |
108 | 108 | ||
109 | 109 | CURL *ret = old_curl_easy_init(); | CURL *ret = old_curl_easy_init(); |
110 | my_trace(__func__, 'R', ret); | ||
110 | my_trace(__func__, "i", 'R', ret); | ||
111 | 111 | xlog(100, "%s: ret=%p\n", __func__, ret); | xlog(100, "%s: ret=%p\n", __func__, ret); |
112 | 112 | ||
113 | 113 | return ret; | return ret; |
... | ... | CURLcode curl_easy_setopt(CURL *handle, CURLoption option, ...) | |
125 | 125 | old_curl_easy_setopt = ninedogs_dlsym("curl_easy_setopt"); | old_curl_easy_setopt = ninedogs_dlsym("curl_easy_setopt"); |
126 | 126 | ||
127 | 127 | const struct my_curl_easyoption *oi = curl_easy_option_by_id(option); | const struct my_curl_easyoption *oi = curl_easy_option_by_id(option); |
128 | if (!oi) | ||
128 | if (!oi) { | ||
129 | my_trace(__func__, "i", 'R', handle, 0xff, "?", 0, NULL, 43); | ||
129 | 130 | return 43; // CURLE_BAD_FUNCTION_ARGUMENT | return 43; // CURLE_BAD_FUNCTION_ARGUMENT |
131 | } | ||
130 | 132 | ||
131 | 133 | xlog(100, " DEBUG: setopt %d name=[%s] type=%d (3=obj, 4=str)\n", | xlog(100, " DEBUG: setopt %d name=[%s] type=%d (3=obj, 4=str)\n", |
132 | 134 | option, oi->name, oi->type); | option, oi->name, oi->type); |
... | ... | CURLcode curl_easy_setopt(CURL *handle, CURLoption option, ...) | |
186 | 188 | } | } |
187 | 189 | } while (0); | } while (0); |
188 | 190 | ||
189 | my_trace(__func__, 'R', handle, oi->type, oi->name, len, a, ret); | ||
191 | my_trace(__func__, "i", 'R', handle, oi->type, oi->name, len, a, ret); | ||
190 | 192 | ||
191 | 193 | return ret; | return ret; |
192 | 194 | } | } |
... | ... | CURLcode curl_easy_perform(CURL *handle) | |
208 | 210 | } else { // user set the len after data | } else { // user set the len after data |
209 | 211 | xlog(101, " DEBUG: %s: we need to log post data as meta!\n", __func__); | xlog(101, " DEBUG: %s: we need to log post data as meta!\n", __func__); |
210 | 212 | } | } |
211 | my_trace(__func__, 'm', "POSTFIELDS", handle, q->post_data, | ||
213 | my_trace(__func__, "i", 'm', "POSTFIELDS", handle, q->post_data, | ||
212 | 214 | q->post_data_len); | q->post_data_len); |
213 | 215 | break; | break; |
214 | 216 | } | } |
215 | 217 | ||
216 | my_trace(__func__, 'c', handle); | ||
218 | my_trace(__func__, "i", 'c', handle); | ||
217 | 219 | CURLcode ret = old_curl_easy_perform(handle); | CURLcode ret = old_curl_easy_perform(handle); |
218 | my_trace(__func__, 'r', handle, ret); | ||
220 | my_trace(__func__, "i", 'r', handle, ret); | ||
219 | 221 | xlog(100, "%s: ret=%d\n", __func__, ret); | xlog(100, "%s: ret=%d\n", __func__, ret); |
220 | 222 | ||
221 | 223 | return ret; | return ret; |
... | ... | void curl_easy_cleanup(CURL *handle) | |
230 | 232 | curl_track_del(handle); | curl_track_del(handle); |
231 | 233 | ||
232 | 234 | old_curl_easy_cleanup(handle); | old_curl_easy_cleanup(handle); |
233 | my_trace(__func__, 'R', handle); | ||
235 | my_trace(__func__, "i", 'R', handle); | ||
234 | 236 | } | } |
235 | 237 |
File agent/java/agent/Makefile changed (mode: 100644) (index b218671..56afa3c) | |||
1 | CLASSES := AtmTransformer.class QueryTransformer.class MyInstrumentationAgent.class | ||
1 | include ../../../Makefile.common | ||
2 | |||
3 | CLASSES := QueryTransformer.class MyInstrumentationAgent.class | ||
2 | 4 | JARS := javassist.jar ninedogs.jar | JARS := javassist.jar ninedogs.jar |
3 | 5 | ||
4 | 6 | ninedogs-agent.jar: Makefile META-INF/MANIFEST.MF ninedogs.jar $(CLASSES) | ninedogs-agent.jar: Makefile META-INF/MANIFEST.MF ninedogs.jar $(CLASSES) |
... | ... | MyInstrumentationAgent.class: MyInstrumentationAgent.java | |
24 | 26 | javac -cp . MyInstrumentationAgent.java | javac -cp . MyInstrumentationAgent.java |
25 | 27 | ||
26 | 28 | install: ninedogs-agent.jar | install: ninedogs-agent.jar |
27 | @mkdir -p $(if $(I_USR_SHARE), $(I_USR_SHARE), /usr/share)/ninedogs | ||
28 | @cp -v $(JARS) $(if $(I_USR_SHARE), $(I_USR_SHARE), /usr/share)/ninedogs/ | ||
29 | @mkdir -p $(I_USR_SHARE)/ninedogs | ||
30 | @cp -v ninedogs-agent.jar ninedogs.jar javassist.jar \ | ||
31 | $(I_USR_SHARE)/ninedogs/ | ||
32 | |||
29 | 33 |
File agent/java/agent/MyInstrumentationAgent.java changed (mode: 100644) (index c90a2c2..deec73d) | |||
... | ... | import java.lang.instrument.Instrumentation; | |
4 | 4 | ||
5 | 5 | public class MyInstrumentationAgent | public class MyInstrumentationAgent |
6 | 6 | { | { |
7 | private static void transform(Class<?> clazz, ClassLoader classLoader, Instrumentation instrumentation) | ||
7 | private static void transform(Class<?> clazz, ClassLoader classLoader, | ||
8 | Instrumentation instrumentation) | ||
8 | 9 | { | { |
9 | 10 | String n = clazz.getName(); | String n = clazz.getName(); |
10 | 11 | ||
11 | //System.err.println("MyInstrumentationAgent.transform: clazz.getName()=" + n + " classLoader=" + classLoader); | ||
12 | //System.err.println("MyInstrumentationAgent.transform: clazz.getName()=[" | ||
13 | // + n + "] classLoader=[" + classLoader + "]"); | ||
12 | 14 | ||
13 | 15 | //if (n.equals("org.postgresql.Driver")) { | //if (n.equals("org.postgresql.Driver")) { |
14 | 16 | // AtmTransformer dt = new AtmTransformer(n, classLoader); | // AtmTransformer dt = new AtmTransformer(n, classLoader); |
... | ... | public class MyInstrumentationAgent | |
17 | 19 | // QueryTransformer dt = new QueryTransformer(n, classLoader); | // QueryTransformer dt = new QueryTransformer(n, classLoader); |
18 | 20 | // instrumentation.addTransformer(dt, true); | // instrumentation.addTransformer(dt, true); |
19 | 21 | //if (n.equals("sun.security.ssl.X509TrustManagerImpl")) { | //if (n.equals("sun.security.ssl.X509TrustManagerImpl")) { |
22 | // QueryTransformer qt = new QueryTransformer(n, classLoader); | ||
23 | // instrumentation.addTransformer(qt, true); // true = can retransform | ||
24 | //} else if (n.equals("oracle.jdbc.OracleResultSet")) { | ||
25 | // QueryTransformer qt = new QueryTransformer(n, classLoader); | ||
26 | // instrumentation.addTransformer(qt, true); // true = can retransform | ||
27 | //} else { | ||
28 | // return; | ||
29 | //} | ||
30 | |||
31 | //if (n.startsWith("oracle.jdbc.")) { | ||
20 | 32 | QueryTransformer qt = new QueryTransformer(n, classLoader); | QueryTransformer qt = new QueryTransformer(n, classLoader); |
21 | 33 | instrumentation.addTransformer(qt, true); // true = can retransform | instrumentation.addTransformer(qt, true); // true = can retransform |
22 | 34 | //} else { | //} else { |
23 | 35 | // return; | // return; |
24 | 36 | //} | //} |
25 | 37 | ||
26 | try { | ||
27 | instrumentation.retransformClasses(clazz); | ||
28 | } catch (Exception ex) { | ||
29 | System.err.println(" transform: fail: " + ex); | ||
30 | // TODO: next line was un-commented | ||
31 | ///throw new RuntimeException(" Transform failed for class: [" + n + "]", ex); | ||
38 | if (instrumentation.isModifiableClass(clazz)) { | ||
39 | try { | ||
40 | instrumentation.retransformClasses(clazz); | ||
41 | } catch (Exception ex) { | ||
42 | throw new RuntimeException(" Transform failed for class: [" + n + "]", ex); | ||
43 | } | ||
44 | } else { | ||
45 | System.out.println(" Class [" + n + "] is not modifiable!"); | ||
32 | 46 | } | } |
33 | 47 | } | } |
34 | 48 | ||
35 | private static void transformClass(String className, Instrumentation instrumentation) | ||
49 | private static void transformClass(String className, | ||
50 | Instrumentation instrumentation) | ||
36 | 51 | { | { |
37 | 52 | Class<?> targetCls = null; | Class<?> targetCls = null; |
38 | 53 | ClassLoader targetClassLoader = null; | ClassLoader targetClassLoader = null; |
39 | 54 | ||
40 | System.err.println("MyInstrumentationAgent.transformClass(" + className + ")..."); | ||
55 | //System.err.println("MyInstrumentationAgent.transformClass(" | ||
56 | // + className + ")..."); | ||
41 | 57 | ||
42 | // see if we can get the class using forName | ||
43 | //System.err.println(" trying using forName..."); | ||
58 | if (1 == 1) { // this is the cause for 'circular'!!! | ||
44 | 59 | try { | try { |
45 | targetCls = Class.forName(className); | ||
60 | targetCls = Class.forName(className); // name, initialize, loader | ||
61 | //System.err.println(" targetCls=" + targetCls); | ||
46 | 62 | targetClassLoader = targetCls.getClassLoader(); | targetClassLoader = targetCls.getClassLoader(); |
63 | //System.err.println(" targetClassLoader=" + targetClassLoader); | ||
47 | 64 | transform(targetCls, targetClassLoader, instrumentation); | transform(targetCls, targetClassLoader, instrumentation); |
48 | //System.err.println(" forName worked! return"); | ||
49 | 65 | return; | return; |
50 | 66 | } catch (Exception ex) { | } catch (Exception ex) { |
51 | ///System.err.println(" Exception: " + ex); | ||
67 | System.err.println(" Exception: " + ex); | ||
68 | //throw ClassNotFoundException(" No loader for class"); | ||
69 | } | ||
52 | 70 | } | } |
53 | //System.err.println("Class [" + className + "] not found with Class.forName"); | ||
54 | |||
55 | //System.err.println(" iterating all classes..."); | ||
56 | // otherwise iterate all loaded classes and find what we want | ||
57 | 71 | ||
58 | 72 | for (Class<?> clazz: instrumentation.getAllLoadedClasses()) { | for (Class<?> clazz: instrumentation.getAllLoadedClasses()) { |
59 | 73 | //System.err.println(" comparing with " + clazz.getName()); | //System.err.println(" comparing with " + clazz.getName()); |
... | ... | public class MyInstrumentationAgent | |
65 | 79 | } | } |
66 | 80 | } | } |
67 | 81 | ||
68 | ///System.err.println(" failed to find class " + className); | ||
82 | //System.err.println(" class not found"); | ||
69 | 83 | //throw new RuntimeException("Failed to find class [" + className + "]"); | //throw new RuntimeException("Failed to find class [" + className + "]"); |
70 | 84 | } | } |
71 | 85 | ||
72 | 86 | public static void premain(String agentArgs, Instrumentation inst) | public static void premain(String agentArgs, Instrumentation inst) |
73 | 87 | { | { |
74 | System.err.println("MyInstrumentationAgent.Premain..."); | ||
88 | System.err.println("MyInstrumentationAgent.premain..."); | ||
75 | 89 | ||
76 | 90 | if (1 == 0) { | if (1 == 0) { |
77 | 91 | // This crashes badly | // This crashes badly |
78 | 92 | // Transform all classes | // Transform all classes |
79 | 93 | for (Class<?> clazz: inst.getAllLoadedClasses()) { | for (Class<?> clazz: inst.getAllLoadedClasses()) { |
80 | //System.err.println(" iter " + clazz.getName()); | ||
81 | transformClass(clazz.getName(), inst); | ||
94 | if (clazz.getName().startsWith("oracle") || clazz.getName().startsWith("java/sql")) { | ||
95 | System.err.println(" iter1 " + clazz.getName()); | ||
96 | transformClass(clazz.getName(), inst); | ||
97 | } | ||
82 | 98 | } | } |
83 | 99 | } else { | } else { |
100 | if (2 == 2) { // seems we do not need to activate these | ||
101 | transformClass("java.sql.Statement", inst); | ||
102 | transformClass("java.sql.ResultSet", inst); | ||
103 | transformClass("java.sql.PreparedStatement", inst); | ||
104 | transformClass("java.sql.CallableStatement", inst); | ||
105 | transformClass("java.sql.Connection", inst); | ||
106 | transformClass("java.sql.Driver", inst); | ||
107 | transformClass("java.sql.DriverManager", inst); | ||
108 | transformClass("java.sql.DriverAction", inst); | ||
109 | transformClass("java.sql.Wrapper", inst); | ||
110 | } | ||
111 | |||
84 | 112 | // This generates Exception in thread "main" java.lang.ClassCircularityError: java/lang/WeakPairMap$Pair$Weak | // This generates Exception in thread "main" java.lang.ClassCircularityError: java/lang/WeakPairMap$Pair$Weak |
85 | //transformClass("org.postgresql.Driver", inst); | ||
86 | transformClass("org.postgresql.jdbc.PgPreparedStatement", inst); | ||
87 | transformClass("org.postgresql.jdbc.PgResultSet", inst); | ||
113 | // Maybe because I tried to capture interfaces. No, it was because I returned 'bytecode' instead of null. | ||
114 | if (1 == 1) { | ||
115 | transformClass("org.postgresql.Driver", inst); | ||
88 | 116 | transformClass("org.postgresql.jdbc.PgConnection", inst); | transformClass("org.postgresql.jdbc.PgConnection", inst); |
117 | transformClass("org.postgresql.jdbc.PgPreparedStatement", inst); | ||
89 | 118 | transformClass("org.postgresql.jdbc.PgStatement", inst); | transformClass("org.postgresql.jdbc.PgStatement", inst); |
119 | transformClass("org.postgresql.jdbc.PgResultSet", inst); | ||
120 | } | ||
90 | 121 | ||
91 | 122 | if (1 == 0) { | if (1 == 0) { |
123 | // Most of these are 'interfaces', not 'classes'! | ||
124 | // But, without transorming these, the important ones are NOT working! Not so sure anymore! | ||
125 | // Probably is something linked with intializations | ||
126 | transformClass("oracle.jdbc.OraclePreparedStatement", inst); | ||
127 | transformClass("oracle.jdbc.OracleResultSet", inst); | ||
128 | transformClass("oracle.jdbc.OracleConnection", inst); | ||
129 | transformClass("oracle.jdbc.OracleStatement", inst); | ||
130 | transformClass("oracle.jdbc.OracleCallableStatement", inst); | ||
131 | } | ||
132 | |||
133 | if (1 == 0) { | ||
134 | transformClass("oracle.jdbc.OracleConnection", inst); | ||
135 | transformClass("oracle.jdbc.OracleConnectionBuilder", inst); | ||
136 | transformClass("oracle.jdbc.OracleConnectionStringBuilder", inst); // this is interface | ||
137 | transformClass("oracle.jdbc.OracleConnectionStringBuilderImpl", inst); | ||
138 | transformClass("oracle.jdbc.OracleConnectionWrapper", inst); // This is very important; without it we cannot access oracle/jdbc/driver/OraclePreparedStatementWrapper/execute | ||
139 | } | ||
140 | |||
141 | if (1 == 0) { | ||
142 | transformClass("oracle.jdbc.internal.OracleConnection", inst); | ||
143 | transformClass("oracle.jdbc.internal.OraclePreparedStatement", inst); | ||
144 | transformClass("oracle.jdbc.internal.OracleStatement", inst); | ||
145 | transformClass("oracle.jdbc.internal.OracleCallableStatement", inst); | ||
146 | transformClass("oracle.jdbc.internal.AbstractConnectionBuilder", inst); | ||
147 | } | ||
148 | |||
149 | transformClass("oracle.jdbc.driver.PhysicalConnection", inst); // STAY! | ||
150 | transformClass("oracle.jdbc.driver.OracleDriver", inst); // STAY! | ||
151 | transformClass("oracle.jdbc.driver.OracleStatement", inst); // STAY! | ||
152 | transformClass("oracle.jdbc.driver.OracleStatementWrapper", inst); // STAY! | ||
153 | transformClass("oracle.jdbc.driver.OraclePreparedStatementWrapper", inst); // STAY! | ||
154 | transformClass("oracle.jdbc.driver.OracleCallableStatementWrapper", inst); // STAY! | ||
155 | transformClass("oracle.jdbc.driver.InsensitiveScrollableResultSet", inst); // STAY! for ResultSet.next() | ||
156 | |||
157 | if (2 == 0) { | ||
158 | transformClass("oracle.jdbc.driver.OracleSql", inst); | ||
159 | transformClass("oracle.jdbc.driver.OracleResultSet", inst); | ||
160 | transformClass("oracle.jdbc.driver.GeneratedPhysicalConnection", inst); | ||
161 | transformClass("oracle.jdbc.driver.OracleDriverExtension", inst); | ||
162 | transformClass("oracle.jdbc.driver.OraclePreparedStatement", inst); | ||
163 | transformClass("oracle.jdbc.driver.OracleCallableStatement", inst); | ||
164 | transformClass("oracle.jdbc.driver.OracleClosedStatement", inst); | ||
165 | transformClass("oracle.jdbc.driver.GeneratedStatement", inst); | ||
166 | } | ||
167 | |||
168 | if (1 == 0) { | ||
169 | transformClass("oracle.jdbc.driver.T2CConnection", inst); | ||
170 | transformClass("oracle.jdbc.driver.T2CStatement", inst); | ||
171 | transformClass("oracle.jdbc.driver.T2CPreparedStatement", inst); | ||
172 | transformClass("oracle.jdbc.driver.T2CDirectPathPreparedStatement", inst); | ||
173 | transformClass("oracle.jdbc.driver.T2CDriverExtension", inst); | ||
174 | |||
175 | transformClass("oracle.jdbc.driver.T4CConnection", inst); | ||
176 | transformClass("oracle.jdbc.driver.T4CStatement", inst); | ||
177 | transformClass("oracle.jdbc.driver.T4CPreparedStatement", inst); | ||
178 | transformClass("oracle.jdbc.driver.T4CDirectPathPreparedStatement", inst); | ||
179 | transformClass("oracle.jdbc.driver.T4CDriverExtension", inst); | ||
180 | } | ||
181 | |||
182 | // MySQL | ||
183 | transformClass("com.mysql.jdbc.Driver", inst); | ||
184 | transformClass("com.mysql.cj.jdbc.Driver", inst); | ||
185 | transformClass("com.mysql.cj.jdbc.ConnectionImpl", inst); | ||
186 | transformClass("com.mysql.cj.jdbc.NonRegisteringDriver", inst); | ||
187 | transformClass("com.mysql.cj.jdbc.ClientPreparedStatement", inst); | ||
188 | transformClass("com.mysql.cj.jdbc.StatementImpl", inst); | ||
189 | transformClass("com.mysql.cj.jdbc.result.ResultSetImpl", inst); | ||
190 | |||
191 | if (1 == 1) { | ||
92 | 192 | transformClass("java.net.http.HttpClient", inst); | transformClass("java.net.http.HttpClient", inst); |
93 | 193 | } | } |
94 | 194 | ||
95 | 195 | //transformClass("sun.security.ssl.X509TrustManager", inst); // not working | //transformClass("sun.security.ssl.X509TrustManager", inst); // not working |
96 | 196 | //transformClass("javax.net.ssl", inst); // not working | //transformClass("javax.net.ssl", inst); // not working |
97 | 197 | ||
98 | if (1 == 0) { | ||
198 | if (1 == 1) { | ||
99 | 199 | transformClass("sun.security.ssl.X509TrustManagerImpl", inst); | transformClass("sun.security.ssl.X509TrustManagerImpl", inst); |
100 | transformClass("java.security.cert.X509Certificate", inst); | ||
200 | //interface transformClass("java.security.cert.X509Certificate", inst); | ||
101 | 201 | transformClass("java.security.cert.Certificate", inst); | transformClass("java.security.cert.Certificate", inst); |
102 | 202 | transformClass("java.security.cert.CertificateFactory", inst); | transformClass("java.security.cert.CertificateFactory", inst); |
103 | 203 | } | } |
... | ... | public class MyInstrumentationAgent | |
111 | 211 | //transformClass("java.io.FileInputStream", inst); | //transformClass("java.io.FileInputStream", inst); |
112 | 212 | //transformClass("java.io.ByteArrayInputStream", inst); | //transformClass("java.io.ByteArrayInputStream", inst); |
113 | 213 | ||
114 | if (1 == 0) { | ||
214 | if (1 == 1) { | ||
115 | 215 | transformClass("javax.net.ssl.X509TrustManager", inst); | transformClass("javax.net.ssl.X509TrustManager", inst); |
116 | 216 | transformClass("javax.net.ssl.X509KeyManager", inst); | transformClass("javax.net.ssl.X509KeyManager", inst); |
117 | 217 | transformClass("sun.security.provider.X509Factory", inst); | transformClass("sun.security.provider.X509Factory", inst); |
... | ... | public class MyInstrumentationAgent | |
120 | 220 | } | } |
121 | 221 | } | } |
122 | 222 | ||
123 | System.err.println("Premain finish..."); | ||
223 | if (2 == 2) { | ||
224 | for (Class<?> clazz: inst.getAllLoadedClasses()) { | ||
225 | if (clazz.getName().startsWith("oracle.jdbc.") | ||
226 | || clazz.getName().startsWith("org.postgresql.") | ||
227 | || clazz.getName().startsWith("com.mysql.") | ||
228 | || clazz.getName().startsWith("java.sql.")) { | ||
229 | System.err.println(" iter2 " + clazz.getName()); | ||
230 | transformClass(clazz.getName(), inst); | ||
231 | } | ||
232 | } | ||
233 | } | ||
234 | |||
235 | System.err.println("MyInstrumentationAgent.premain... done"); | ||
124 | 236 | } | } |
125 | 237 | } | } |
126 | 238 |
File agent/java/agent/QueryTransformer.java changed (mode: 100644) (index 29ec08e..0850459) | |||
... | ... | import javassist.CtMethod; | |
7 | 7 | import javassist.CtConstructor; | import javassist.CtConstructor; |
8 | 8 | import javassist.NotFoundException; | import javassist.NotFoundException; |
9 | 9 | ||
10 | import java.lang.Exception; | ||
10 | 11 | import java.io.IOException; | import java.io.IOException; |
11 | 12 | import java.lang.instrument.ClassFileTransformer; | import java.lang.instrument.ClassFileTransformer; |
12 | 13 | import java.lang.instrument.IllegalClassFormatException; | import java.lang.instrument.IllegalClassFormatException; |
... | ... | import java.security.ProtectionDomain; | |
14 | 15 | ||
15 | 16 | public class QueryTransformer implements ClassFileTransformer | public class QueryTransformer implements ClassFileTransformer |
16 | 17 | { | { |
17 | private static final String WITHDRAW_MONEY_METHOD = "executeQuery"; | ||
18 | //private static final String WITHDRAW_MONEY_METHOD = "executeQuery"; | ||
18 | 19 | ||
19 | 20 | /** The internal form class name of the class to transform */ | /** The internal form class name of the class to transform */ |
20 | 21 | private String targetClassName; | private String targetClassName; |
... | ... | public class QueryTransformer implements ClassFileTransformer | |
26 | 27 | { | { |
27 | 28 | //System.err.println("QueryTransformer.QueryTransformer: targetClassname=" | //System.err.println("QueryTransformer.QueryTransformer: targetClassname=" |
28 | 29 | // + targetClassName + " loader=" + targetClassLoader); | // + targetClassName + " loader=" + targetClassLoader); |
29 | this.targetClassName = targetClassName; | ||
30 | this.targetClassName = targetClassName.replaceAll("\\.", "/"); // replace '.' with '/'; | ||
30 | 31 | this.targetClassLoader = targetClassLoader; | this.targetClassLoader = targetClassLoader; |
31 | 32 | } | } |
32 | 33 | ||
34 | /* | ||
35 | * @loader - the defining loader, may be null if bootstrap loader | ||
36 | * @className - example: "java/util/List" | ||
37 | * @classBeingRedefined - null if is a class load | ||
38 | * We should return null if we do not perform any transformation | ||
39 | */ | ||
33 | 40 | @Override | @Override |
34 | public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, | ||
35 | ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException | ||
41 | public byte[] transform(ClassLoader loader, String className, | ||
42 | Class<?> classBeingRedefined, ProtectionDomain protectionDomain, | ||
43 | byte[] classfileBuffer) throws IllegalClassFormatException | ||
36 | 44 | { | { |
37 | 45 | byte[] byteCode = classfileBuffer; | byte[] byteCode = classfileBuffer; |
38 | 46 | ||
47 | if (!className.equals(this.targetClassName)) { | ||
48 | //System.err.println(" ignore class [" + className + "] != [" + this.targetClassName + "]"); | ||
49 | return null; | ||
50 | } | ||
51 | |||
39 | 52 | if (loader != null) { | if (loader != null) { |
40 | 53 | if (!loader.equals(this.targetClassLoader)) { | if (!loader.equals(this.targetClassLoader)) { |
41 | 54 | //System.err.println(" ignore loader [" + loader + "] != [" + this.targetClassLoader + "]"); | //System.err.println(" ignore loader [" + loader + "] != [" + this.targetClassLoader + "]"); |
42 | return byteCode; | ||
55 | return null; | ||
43 | 56 | } | } |
44 | 57 | } | } |
45 | 58 | ||
46 | String finalTargetClassName = this.targetClassName.replaceAll("\\.", "/"); //replace . with / | ||
47 | |||
48 | if (!className.equals(finalTargetClassName)) { | ||
49 | //System.err.println(" ignore class [" + className + "] != [" + finalTargetClassName + "]"); | ||
50 | return byteCode; | ||
51 | } | ||
52 | |||
53 | //System.err.println("QueryTransformer.transform(loader=" + loader | ||
54 | // + ", className=" + className | ||
55 | // + ", classBeignRedefined=" + classBeingRedefined.getName() | ||
56 | // + ", protectionDomain=" + protectionDomain | ||
57 | // + ")..."); | ||
59 | // Activating this will generate a Permission error! | ||
60 | if (1 == 0) | ||
61 | System.out.println("QueryTransformer.transform(loader=" + loader | ||
62 | + ", className=" + className | ||
63 | + ", classBeignRedefined=" + classBeingRedefined.getName() | ||
64 | + ", protectionDomain=" + protectionDomain | ||
65 | + ")..."); | ||
58 | 66 | ||
59 | 67 | //String s = new String(byteCode); | //String s = new String(byteCode); |
60 | 68 | //System.err.println(" bytecode before: " + s); | //System.err.println(" bytecode before: " + s); |
61 | 69 | try { | try { |
62 | 70 | ClassPool cp = ClassPool.getDefault(); | ClassPool cp = ClassPool.getDefault(); |
63 | CtClass cc = cp.get(targetClassName); | ||
71 | CtClass cc = cp.get(targetClassName.replaceAll("/", ".")); | ||
64 | 72 | //CtMethod m = cc.getDeclaredMethod(WITHDRAW_MONEY_METHOD); | //CtMethod m = cc.getDeclaredMethod(WITHDRAW_MONEY_METHOD); |
65 | 73 | //System.err.println(" CtMethod: " + m); | //System.err.println(" CtMethod: " + m); |
66 | 74 | ||
67 | 75 | // seems this crashes at some point | // seems this crashes at some point |
68 | if (className.equals("TODO java/io/File TODO")) { | ||
76 | if (className.equals("TODO java/io/File TODO") | ||
77 | || className.startsWith("todo org/postgresql/")) { | ||
78 | //System.err.println(" Iterating constructors..."); | ||
69 | 79 | CtConstructor[] cons = cc.getDeclaredConstructors(); | CtConstructor[] cons = cc.getDeclaredConstructors(); |
70 | 80 | for (CtConstructor con : cons) { | for (CtConstructor con : cons) { |
71 | 81 | StringBuilder sb = new StringBuilder(); | StringBuilder sb = new StringBuilder(); |
72 | 82 | StringBuilder eb = new StringBuilder(); | StringBuilder eb = new StringBuilder(); |
73 | 83 | ||
74 | 84 | String sig = con.getSignature(); | String sig = con.getSignature(); |
75 | System.err.println(" constructor: " + con + " sig=" + sig); | ||
76 | sb.append("ninedogs.log(\"constructor for class " + className + " " + sig + " this=\" + this + \" $0=\" + $0);"); | ||
77 | eb.append("ninedogs.log(\" exit this: \" + this + \" $0=\" + $0);"); // seems 'this' is always null... | ||
85 | //System.err.println(" constructor: " + con + " sig=" + sig); | ||
86 | // todo this generates error: sb.append("ninedogs.log(\"constructor for class " | ||
87 | // + className + " " + sig + " this=\" + this + \" $0=\" + $0);"); | ||
88 | sb.append("ninedogs.log(\"constructor for class [" | ||
89 | + className + "] sig=[" + sig + "]\");"); | ||
90 | eb.append("ninedogs.log(\" exit this: \" + this + \" R=\" + $_);"); // seems 'this' is always null... | ||
78 | 91 | ||
79 | 92 | CtClass[] pTypes = con.getParameterTypes(); | CtClass[] pTypes = con.getParameterTypes(); |
80 | 93 | for (int i = 0; i < pTypes.length; i++) | for (int i = 0; i < pTypes.length; i++) |
81 | 94 | sb.append("ninedogs.log(\" c-para[" + i + "] [" + pTypes[i].getName() + "]: \" + $args[" + i + "]);"); | sb.append("ninedogs.log(\" c-para[" + i + "] [" + pTypes[i].getName() + "]: \" + $args[" + i + "]);"); |
82 | 95 | ||
83 | con.insertBefore("{" + sb.toString() + "}"); | ||
84 | con.insertAfter("{" + eb.toString() + "}"); | ||
96 | if (sb.length() > 0) | ||
97 | con.insertBefore("{" + sb.toString() + "}"); | ||
98 | if (eb.length() > 0) | ||
99 | con.insertAfter("{" + eb.toString() + "}"); | ||
85 | 100 | } | } |
86 | 101 | } | } |
87 | 102 | ||
88 | ///System.err.println(" Iterating methods..."); | ||
103 | //System.err.println(" Iterating methods..."); | ||
89 | 104 | // Searchy for (Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection; | // Searchy for (Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection; |
90 | 105 | CtMethod[] methods = cc.getDeclaredMethods(); | CtMethod[] methods = cc.getDeclaredMethods(); |
91 | 106 | //CtMethod m = cc.getDeclaredMethod("connect", params); | //CtMethod m = cc.getDeclaredMethod("connect", params); |
92 | 107 | for (CtMethod m : methods) { | for (CtMethod m : methods) { |
93 | 108 | String sig = m.getSignature(); | String sig = m.getSignature(); |
94 | ///System.err.println(" method " + m.getName() + " sig: " + sig + "..."); | ||
109 | //System.err.println(" className=[" + className + "] method=[" + m.getName() + "] sig=[" + sig + "] byteCode.length=" + byteCode.length); | ||
95 | 110 | ||
96 | 111 | StringBuilder sb = new StringBuilder(); | StringBuilder sb = new StringBuilder(); |
97 | 112 | StringBuilder eb = new StringBuilder(); | StringBuilder eb = new StringBuilder(); |
98 | 113 | StringBuilder ee = new StringBuilder(); | StringBuilder ee = new StringBuilder(); |
99 | //CtClass etype = ClassPool.getDefault().get("java.io.IOException"); | ||
114 | CtClass etype = ClassPool.getDefault().get("java.lang.Exception"); | ||
100 | 115 | // TODO: for postgresql code the next code was un-commented! | // TODO: for postgresql code the next code was un-commented! |
101 | 116 | //CtClass etype = cp.get("org.postgresql.util.PSQLException"); | //CtClass etype = cp.get("org.postgresql.util.PSQLException"); |
102 | 117 | ||
103 | 118 | // This is heavy debug | // This is heavy debug |
104 | 119 | //sb.append("System.err.println(\"method " + className + "." + m.getName() + " " + sig + "\");"); | //sb.append("System.err.println(\"method " + className + "." + m.getName() + " " + sig + "\");"); |
105 | ///sb.append("ninedogs.log(\"method " + className + "." + m.getName() + " " + sig + "\");"); | ||
106 | ///eb.append("ninedogs.log(\" ret: \" + $_);"); | ||
107 | |||
108 | if (className.equals("org/postgresql/Driver") | ||
109 | && m.getName().equals("connect") | ||
110 | && sig.equals("(Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection;")) { | ||
111 | System.err.println("========= Intercept connect [" + className + "]"); | ||
112 | sb.append("ninedogs.log(\"db pg con s \" + $1);"); | ||
113 | eb.append("ninedogs.log(\"db pg con e \");"); | ||
114 | ee.append("ninedogs.log(\"db pg con x \" + $e + \"; Cause: \" + $e.getCause() + \" \" + $e.getStackTrace() + \".\"); throw $e;"); | ||
115 | } else if (className.equals("org/postgresql/jdbc/PgConnection") | ||
116 | && m.getName().equals("prepareStatement") | ||
117 | && (sig.equals("(Ljava/lang/String;III)Ljava/sql/PreparedStatement;"))) { | ||
118 | System.err.println("========= Intercept prepareStatement [" + className + "] [" + sig + "]"); | ||
119 | sb.append("ninedogs.log(\"db pg ps s \" + $1);"); | ||
120 | eb.append("ninedogs.log(\"db pg ps e \");"); | ||
121 | ee.append("ninedogs.log(\"db pg ps x \" + $e + \"; Cause: \" + $e.getCause() + \" \" + $e.getStackTrace() + \".\"); throw $e;"); | ||
122 | } else if (className.equals("org/postgresql/jdbc/PgStatement") | ||
123 | && m.getName().equals("executeInternal") | ||
124 | && (sig.equals("(Lorg/postgresql/core/CachedQuery;Lorg/postgresql/core/ParameterList;I)V"))) { | ||
125 | System.err.println("========= Intercept executeInternal[" + className + "] [" + sig + "]"); | ||
126 | sb.append("ninedogs.log(\"db pg exe s \" + $1 + \" \" + $2);"); | ||
127 | eb.append("ninedogs.log(\"db pg exe e \");"); | ||
128 | ee.append("ninedogs.log(\"db pg exe x \" + $e + \"; Cause: \" + $e.getCause() + \" \" + $e.getStackTrace() + \".\"); throw $e;"); | ||
120 | sb.append("ninedogs.log(\"GEN method [" + className + "/" + m.getName() + "] sig=[" + sig + "]: begin\");"); | ||
121 | // this seems to not be available - sb.append("try { ninedogs.log(\" this=\" + this); } catch (Exception e) {}"); | ||
122 | // seems I get a compile error - sb.append("try { ninedogs.log(\" $0=\" + $0); } catch (Exception e) {}"); | ||
123 | eb.append("ninedogs.log(\"GEN method [" + className + "/" + m.getName() + "] sig=[" + sig + "]: R=[\" + $_ + \"]\");"); | ||
124 | // todo - seems is not working: | ||
125 | // if we activate it, it will be executed before specific exception! | ||
126 | //ee.append("ninedogs.log(\"GEN method [" + className + "/" + m.getName() + "] sig=[" + sig + "]: EXCEPTION: [\" + $e + \"]\"); throw $e;"); | ||
127 | |||
128 | Boolean ignore_most = false; | ||
129 | |||
130 | ////////////////////////////////////////////////////////////// MySQL start | ||
131 | if (className.equals("com/mysql/cj/jdbc/NonRegisteringDriver")) { | ||
132 | if (m.getName().equals("connect") | ||
133 | && sig.equals("(Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection;")) { | ||
134 | sb.append("ninedogs.db('M', 'c', 's', $0, $1, $2, null);"); | ||
135 | eb.append("ninedogs.db('M', 'c', 'e', $0, $1, $2, $_);"); | ||
136 | ee.append("ninedogs.db('M', 'c', 'x', $0, $1, $2, $e); throw $e;"); | ||
137 | } else if (ignore_most) { | ||
138 | continue; | ||
139 | } | ||
140 | } else if (className.equals("com/mysql/cj/jdbc/ConnectionImpl")) { | ||
141 | if (m.getName().equals("prepareStatement")) { | ||
142 | if (sig.equals("(Ljava/lang/String;)Ljava/sql/PreparedStatement;")) { // con.prepareStatement("SELECT ? AS id"); | ||
143 | sb.append("ninedogs.db('M', 'p', 's', $0, $1, null, null);"); // TODO: not sure we need this | ||
144 | eb.append("ninedogs.db('M', 'p', 'e', $0, $1, $_, null);"); | ||
145 | ee.append("ninedogs.db('M', 'p', 'x', $0, $1, $e, null); throw $e;"); | ||
146 | } else if (ignore_most) { | ||
147 | continue; | ||
148 | } | ||
149 | } else if (m.getName().equals("createStatement") | ||
150 | && sig.equals("()Ljava/sql/Statement;")) { // it links 'con' with 'stmt'; 'sb' is not really useful | ||
151 | eb.append("ninedogs.db('M', 'f', 'e', $0, $_, null, null);"); | ||
152 | ee.append("ninedogs.db('M', 'f', 'x', $0, $e, null, null); throw $e;"); | ||
153 | } else if (m.getName().equals("close") && sig.equals("()V")) { | ||
154 | eb.append("ninedogs.db('M', 'x', 'e', $0, null, null, null);"); | ||
155 | ee.append("ninedogs.db('M', 'x', 'x', $0, $e, null, null); throw $e;"); | ||
156 | } else if (ignore_most) { | ||
157 | continue; | ||
158 | } | ||
159 | } else if (className.equals("com/mysql/cj/jdbc/ClientPreparedStatement")) { | ||
160 | if (m.getName().equals("getInstance")) { // TODO - really used? | ||
161 | if (sig.equals("(Lcom/mysql/cj/jdbc/JdbcConnection;Ljava/lang/String;Ljava/lang/String;)Lcom/mysql/cj/jdbc/ClientPreparedStatement;")) { | ||
162 | sb.append("ninedogs.db('M', 'p', 's', $0, $1, null, null);"); // TODO: not sure we need this | ||
163 | eb.append("ninedogs.db('M', 'p', 'e', $0, $1, $_, null);"); | ||
164 | ee.append("ninedogs.db('M', 'p', 'x', $0, $1, $e, null); throw $e;"); | ||
165 | } else if (sig.equals("TODO ()Ljava/sql/ResultSet;")) { | ||
166 | sb.append("ninedogs.db('M', 'e', 's', $0, null, null, null);"); | ||
167 | eb.append("ninedogs.db('M', 'e', 'e', $0, $_, null, null);"); | ||
168 | ee.append("ninedogs.db('M', 'e', 'x', $0, $e, null, null); throw $e;"); | ||
169 | } else if (ignore_most) { | ||
170 | continue; | ||
171 | } | ||
172 | } else if (m.getName().equals("executeQuery")) { | ||
173 | if (sig.equals("()Ljava/sql/ResultSet;")) { | ||
174 | sb.append("ninedogs.db('M', 'e', 's', $0, null, null, null);"); | ||
175 | eb.append("ninedogs.db('M', 'e', 'e', $0, $_, null, null);"); | ||
176 | ee.append("ninedogs.db('M', 'e', 'x', $0, $e, null, null); throw $e;"); | ||
177 | } else if (ignore_most) { | ||
178 | continue; | ||
179 | } | ||
180 | } else if (m.getName().equals("setInt") && sig.equals("(II)V")) { | ||
181 | eb.append("ninedogs.db('M', 'b', 'e', $0, Integer.valueOf($1), Integer.valueOf($2), $_);"); | ||
182 | ee.append("ninedogs.db('M', 'b', 'x', $0, Integer.valueOf($1), Integer.valueOf($2), $e); throw $e;"); | ||
183 | } else if (m.getName().equals("setString") && sig.equals("(ILjava/lang/String;)V")) { | ||
184 | eb.append("ninedogs.db('M', 'S', 'e', $0, Integer.valueOf($1), $2, $_);"); | ||
185 | ee.append("ninedogs.db('M', 'S', 'x', $0, Integer.valueOf($1), $2, $e); throw $e;"); | ||
186 | } else if (ignore_most) { | ||
187 | continue; | ||
188 | } | ||
189 | } else if (className.equals("com/mysql/cj/jdbc/StatementImpl")) { | ||
190 | if (m.getName().equals("close") && sig.equals("()V")) { | ||
191 | eb.append("ninedogs.db('M', 'w', 'e', $0, null, null, null);"); | ||
192 | ee.append("ninedogs.db('M', 'w', 'x', $0, $e, null, null); throw $e;"); | ||
193 | } else if (m.getName().equals("executeQuery") | ||
194 | && sig.equals("(Ljava/lang/String;)Ljava/sql/ResultSet;")) { // this is for normal query | ||
195 | sb.append("ninedogs.db('M', 'Q', 's', $0, $1, null, null);"); | ||
196 | eb.append("ninedogs.db('M', 'Q', 'e', $0, $1, $_, null);"); | ||
197 | ee.append("ninedogs.db('M', 'Q', 'x', $0, $1, $e, null); throw $e;"); | ||
198 | } else if (ignore_most) { | ||
199 | continue; | ||
200 | } | ||
201 | } else if (className.equals("com/mysql/cj/jdbc/result/ResultSetImpl")) { | ||
202 | if (m.getName().equals("next") && sig.equals("()Z")) { | ||
203 | sb.append("ninedogs.log(\"db M " + className + "/" + m.getName() + " s: 0=\" + $0);"); | ||
204 | eb.append("ninedogs.log(\"db M " + className + "/" + m.getName() + " e: 0=\" + $0 + \" R=\" + $_);"); | ||
205 | ee.append("ninedogs.log(\"db M " + className + "/" + m.getName() + " x: 0=\" + $0 + \" e=[\" + $e + \"]; Cause: \" + $e.getCause() + \" \" + $e.getStackTrace() + \".\"); throw $e;"); | ||
206 | } else if (ignore_most) { | ||
207 | continue; | ||
208 | } | ||
209 | ////////////////////////////////////////////////////////////// MySQL END | ||
210 | |||
211 | ////////////////////////////////////////////////////////////// PostgreSQL start | ||
212 | } else if (className.equals("org/postgresql/Driver")) { | ||
213 | if (m.getName().equals("connect") | ||
214 | && sig.equals("(Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection;")) { | ||
215 | sb.append("ninedogs.db('P', 'c', 's', $0, $1, $2, null);"); | ||
216 | eb.append("ninedogs.db('P', 'c', 'e', $0, $1, $2, $_);"); | ||
217 | ee.append("ninedogs.db('P', 'c', 'x', $0, $1, $2, $e); throw $e;"); // + \" e=[\" + $e + \"]; Cause: \" + $e.getCause() + \" \" + $e.getStackTrace() + \".\"); throw $e;"); | ||
218 | } else if (ignore_most) { | ||
219 | continue; | ||
220 | } | ||
221 | } else if (className.equals("org/postgresql/jdbc/PgPreparedStatement")) { // 'close' does not exists (it is the one from PgStatement) | ||
222 | if (m.getName().equals("executeQuery")) { | ||
223 | if (sig.equals("(Lorg/postgresql/core/CachedQuery;Lorg/postgresql/core/ParameterList;I)V")) { | ||
224 | sb.append("ninedogs.log(\"db P " + className + "/" + m.getName() + " s: 0=\" + $0);"); | ||
225 | eb.append("ninedogs.log(\"db P " + className + "/" + m.getName() + " e: 0=\" + $0 + \" R=\" + $_);"); | ||
226 | ee.append("ninedogs.log(\"db P " + className + "/" + m.getName() + " x: 0=\" + $0 + \" e=[\" + $e + \"]; Cause: \" + $e.getCause() + \" \" + $e.getStackTrace() + \".\"); throw $e;"); | ||
227 | } else if (sig.equals("()Ljava/sql/ResultSet;")) { | ||
228 | sb.append("ninedogs.db('P', 'e', 's', $0, null, null, null);"); | ||
229 | eb.append("ninedogs.db('P', 'e', 'e', $0, $_, null, null);"); | ||
230 | ee.append("ninedogs.db('P', 'e', 'x', $0, $e, null, null); throw $e;"); | ||
231 | } else if (ignore_most) { | ||
232 | continue; | ||
233 | } | ||
234 | } else if (m.getName().equals("setInt") && sig.equals("(II)V")) { | ||
235 | eb.append("ninedogs.db('P', 'b', 'e', $0, Integer.valueOf($1), Integer.valueOf($2), $_);"); | ||
236 | ee.append("ninedogs.db('P', 'b', 'x', $0, Integer.valueOf($1), Integer.valueOf($2), $e); throw $e;"); | ||
237 | } else if (m.getName().equals("setString") && sig.equals("(ILjava/lang/String;)V")) { | ||
238 | eb.append("ninedogs.db('P', 'S', 'e', $0, Integer.valueOf($1), $2, $_);"); | ||
239 | ee.append("ninedogs.db('P', 'S', 'x', $0, Integer.valueOf($1), $2, $e); throw $e;"); | ||
240 | } else if (ignore_most) { | ||
241 | continue; | ||
242 | } | ||
243 | } else if (className.equals("org/postgresql/jdbc/PgStatement")) { | ||
244 | if (m.getName().equals("close") && sig.equals("()V")) { | ||
245 | eb.append("ninedogs.db('P', 'w', 'e', $0, null, null, null);"); | ||
246 | ee.append("ninedogs.db('P', 'w', 'x', $0, $e, null, null); throw $e;"); | ||
247 | } else if (m.getName().equals("executeQuery") | ||
248 | && sig.equals("(Ljava/lang/String;)Ljava/sql/ResultSet;")) { // this is for normal query | ||
249 | sb.append("ninedogs.db('P', 'Q', 's', $0, $1, null, null);"); | ||
250 | eb.append("ninedogs.db('P', 'Q', 'e', $0, $1, $_, null);"); | ||
251 | ee.append("ninedogs.db('P', 'Q', 'x', $0, $1, $e, null); throw $e;"); | ||
252 | } else if (m.getName().equals("executeQuery") | ||
253 | && sig.equals("()Ljava/sql/ResultSet;")) { // this is for prepared query | ||
254 | sb.append("ninedogs.db('P', 'P', 's', $0, null, null, null);"); | ||
255 | eb.append("ninedogs.db('P', 'P', 'e', $0, $_, null, null);"); | ||
256 | ee.append("ninedogs.db('P', 'P', 'x', $0, $e, null, null); throw $e;"); | ||
257 | } else if (ignore_most) { | ||
258 | continue; | ||
259 | } | ||
260 | } else if (className.equals("org/postgresql/jdbc/PgResultSet")) { | ||
261 | if (m.getName().equals("next") && sig.equals("()Z")) { | ||
262 | sb.append("ninedogs.log(\"db P " + className + "/" + m.getName() + " s: 0=\" + $0);"); | ||
263 | eb.append("ninedogs.log(\"db P " + className + "/" + m.getName() + " e: 0=\" + $0 + \" R=\" + $_);"); | ||
264 | ee.append("ninedogs.log(\"db P " + className + "/" + m.getName() + " x: 0=\" + $0 + \" e=[\" + $e + \"]; Cause: \" + $e.getCause() + \" \" + $e.getStackTrace() + \".\"); throw $e;"); | ||
265 | } else if (ignore_most) { | ||
266 | continue; | ||
267 | } | ||
268 | } else if (className.equals("org/postgresql/jdbc/PgConnection")) { | ||
269 | if (m.getName().equals("close") && sig.equals("()V")) { | ||
270 | eb.append("ninedogs.db('P', 'x', 'e', $0, null, null, null);"); | ||
271 | ee.append("ninedogs.db('P', 'x', 'x', $0, $e, null, null); throw $e;"); | ||
272 | } else if (m.getName().equals("createStatement") | ||
273 | && sig.equals("()Ljava/sql/Statement;")) { // it links 'con' with 'stmt'; 'sb' is not really useful | ||
274 | eb.append("ninedogs.db('P', 'f', 'e', $0, $_, null, null);"); | ||
275 | ee.append("ninedogs.db('P', 'f', 'x', $0, $e, null, null); throw $e;"); | ||
276 | } else if (m.getName().equals("prepareStatement")) { | ||
277 | if (sig.equals("(Ljava/lang/String;)Ljava/sql/PreparedStatement;")) { // con.prepareStatement("SELECT ? AS id"); | ||
278 | sb.append("ninedogs.db('P', 'p', 's', $0, $1, null, null);"); // TODO: not sure we need this | ||
279 | eb.append("ninedogs.db('P', 'p', 'e', $0, $1, $_, null);"); | ||
280 | ee.append("ninedogs.db('P', 'p', 'x', $0, $1, $e, null); throw $e;"); | ||
281 | } else if (ignore_most) { | ||
282 | continue; | ||
283 | } | ||
284 | } else if (ignore_most) { | ||
285 | continue; | ||
286 | } | ||
287 | ////////////////////////////////////////////////////////////// PostgreSQL END | ||
288 | |||
289 | ////////////////////////////////////////////////////////////// Certs start | ||
129 | 290 | } else if (className.equals("sun/security/provider/X509Factory") | } else if (className.equals("sun/security/provider/X509Factory") |
130 | 291 | && m.getName().equals("engineGenerateCertificate") | && m.getName().equals("engineGenerateCertificate") |
131 | && (sig.equals("(Ljava/io/InputStream;)Ljava/security/cert/Certificate;"))) { | ||
132 | //System.err.println(" Overwrite engineGenerateCertificate ================================="); | ||
292 | && sig.equals("(Ljava/io/InputStream;)Ljava/security/cert/Certificate;")) { | ||
133 | 293 | eb.append("ninedogs.log_cert($1, $_);"); | eb.append("ninedogs.log_cert($1, $_);"); |
134 | 294 | } else if (className.equals("java/security/cert/X509Certificate")) { | } else if (className.equals("java/security/cert/X509Certificate")) { |
295 | ////////////////////////////////////////////////////////////// Certs END | ||
296 | |||
297 | ////////////////////////////////////////////////////////////// Oracle starts | ||
298 | } else if (className.equals("oracle/jdbc/driver/OracleDriver")) { // seems we get this connection in java/sql/DriverManager! | ||
299 | if (m.getName().equals("connect")) { | ||
300 | if (sig.equals("(Ljava/lang/String;Ljava/util/Properties;Loracle/jdbc/internal/AbstractConnectionBuilder;)Ljava/sql/Connection;")) { | ||
301 | sb.append("ninedogs.db('O', 'c', 's', $0, $1, $2, null);"); | ||
302 | eb.append("ninedogs.db('O', 'c', 'e', $0, $1, $2, $_);"); | ||
303 | ee.append("ninedogs.db('O', 'c', 'x', $0, $1, $2, $e); throw $e;"); | ||
304 | } else { | ||
305 | continue; | ||
306 | } | ||
307 | } else if (ignore_most) { | ||
308 | continue; | ||
309 | } | ||
310 | } else if (className.equals("oracle/jdbc/driver/PreparedStatement")) { | ||
311 | if (m.getName().equals("execute") && sig.equals("()Z")) { | ||
312 | sb.append("ninedogs.db('O', 'e', 's', $0, null, null, null);"); | ||
313 | eb.append("ninedogs.db('O', 'e', 'e', $0, $_, null, null);"); | ||
314 | ee.append("ninedogs.db('O', 'e', 'x', $0, $e, null, null); throw $e;"); | ||
315 | } else if (ignore_most) { | ||
316 | continue; | ||
317 | } | ||
318 | } else if (className.equals("oracle/jdbc/driver/PhysicalConnection")) { | ||
319 | if (m.getName().equals("prepareStatementInternal")) { // STAY! | ||
320 | if (sig.equals("(Ljava/lang/String;Ljava/util/Properties;)Loracle/jdbc/driver/OraclePreparedStatement;")) { // STAY! | ||
321 | sb.append("ninedogs.db('O', 'p', 's', $0, $1, null, null);"); | ||
322 | eb.append("ninedogs.db('O', 'p', 'e', $0, $1, $_, null);"); | ||
323 | ee.append("ninedogs.db('O', 'p', 'x', $0, $1, $e, null); throw $e;"); | ||
324 | } else { | ||
325 | continue; | ||
326 | } | ||
327 | } else if (m.getName().equals("prepareStatement")) { | ||
328 | continue; | ||
329 | } else if (m.getName().equals("createStatement") | ||
330 | && sig.equals("()Ljava/sql/Statement;")) { // STAY! | ||
331 | eb.append("ninedogs.db('O', 'f', 'e', $0, $_, null, null);"); | ||
332 | ee.append("ninedogs.db('O', 'f', 'x', $0, $e, null, null); throw $e;"); | ||
333 | } else if (m.getName().equals("commit") | ||
334 | && sig.equals("()V")) { // STAY! | ||
335 | sb.append("ninedogs.log(\"db O " + className + "/" + m.getName() + " s: 0=\" + $0);"); | ||
336 | eb.append("ninedogs.log(\"db O " + className + "/" + m.getName() + " e: 0=\" + $0 + \" R=\" + $_);"); | ||
337 | ee.append("ninedogs.log(\"db O " + className + "/" + m.getName() + " x: 0=\" + $0 + \" e=[\" + $e + \"]; Cause: \" + $e.getCause() + \" \" + $e.getStackTrace() + \".\"); throw $e;"); | ||
338 | } else if (m.getName().equals("rollback") | ||
339 | && sig.equals("()V")) { // STAY! | ||
340 | sb.append("ninedogs.log(\"db O " + className + "/" + m.getName() + " s: 0=\" + $0);"); | ||
341 | eb.append("ninedogs.log(\"db O " + className + "/" + m.getName() + " e: 0=\" + $0 + \" R=\" + $_);"); | ||
342 | ee.append("ninedogs.log(\"db O " + className + "/" + m.getName() + " x: 0=\" + $0 + \" e=[\" + $e + \"]; Cause: \" + $e.getCause() + \" \" + $e.getStackTrace() + \".\"); throw $e;"); | ||
343 | } else if (m.getName().equals("close") | ||
344 | && sig.equals("()V")) { // STAY! | ||
345 | eb.append("ninedogs.db('O', 'x', 'e', $0, null, null, null);"); | ||
346 | ee.append("ninedogs.db('O', 'x', 'x', $0, $e, null, null); throw $e;"); | ||
347 | } else if (ignore_most) { | ||
348 | continue; | ||
349 | } | ||
350 | } else if (className.equals("oracle/jdbc/driver/OraclePreparedStatementWrapper")) { | ||
351 | if (m.getName().equals("execute") && sig.equals("()Z")) { // STAY! | ||
352 | sb.append("ninedogs.db('O', 'E', 's', $0, null, null, null);"); | ||
353 | eb.append("ninedogs.db('O', 'E', 'e', $0, $_ == true ? $0 : null, null, null);"); // we cannot pass directly bool | ||
354 | ee.append("ninedogs.db('O', 'E', 'x', $0, $e, null, null); throw $e;"); | ||
355 | } else if (m.getName().equals("setInt") && sig.equals("(II)V")) { // STAY! | ||
356 | eb.append("ninedogs.db('O', 'b', 'e', $0, Integer.valueOf($1), Integer.valueOf($2), $_);"); | ||
357 | ee.append("ninedogs.db('O', 'b', 'x', $0, Integer.valueOf($1), Integer.valueOf($2), $e); throw $e;"); | ||
358 | } else if (ignore_most) { | ||
359 | continue; | ||
360 | } | ||
361 | } else if (className.equals("oracle/jdbc/driver/OracleStatement")) { | ||
362 | if (m.getName().equals("executeQuery") | ||
363 | && sig.equals("(Ljava/lang/String;)Ljava/sql/ResultSet;")) { // STAY! | ||
364 | sb.append("ninedogs.db('O', 'Q', 's', $0, $1, null, null);"); | ||
365 | eb.append("ninedogs.db('O', 'Q', 'e', $0, $1, $_, null);"); | ||
366 | ee.append("ninedogs.db('O', 'Q', 'x', $0, $1, $e, null); throw $e;"); | ||
367 | } else if (ignore_most) { | ||
368 | continue; | ||
369 | } | ||
370 | } else if (className.equals("oracle/jdbc/driver/InsensitiveScrollableResultSet")) { | ||
371 | if (m.getName().equals("next") | ||
372 | && sig.equals("()Z")) { | ||
373 | sb.append("ninedogs.log(\"db O " + className + "/" + m.getName() + " s: 0=\" + $0);"); | ||
374 | eb.append("ninedogs.log(\"db O " + className + "/" + m.getName() + " e: 0=\" + $0 + \" R=\" + $_);"); | ||
375 | ee.append("ninedogs.log(\"db O " + className + "/" + m.getName() + " x: 0=\" + $0 + \" e=[\" + $e + \"]; Cause: \" + $e.getCause() + \" \" + $e.getStackTrace() + \".\"); throw $e;"); | ||
376 | } else if (ignore_most) { | ||
377 | continue; | ||
378 | } | ||
379 | } else if (className.equals("oracle/jdbc/driver/OracleStatementWrapper")) { | ||
380 | if (m.getName().equals("execute") && sig.equals("()Z")) { | ||
381 | sb.append("ninedogs.log(\"db O " + className + "/" + m.getName() + " s: 0=\" + $0);"); | ||
382 | eb.append("ninedogs.log(\"db O " + className + "/" + m.getName() + " e: 0=\" + $0 + \" R=\" + $_);"); | ||
383 | ee.append("ninedogs.log(\"db O " + className + "/" + m.getName() + " x: 0=\" + $0 + \" e=[\" + $e + \"]; Cause: \" + $e.getCause() + \" \" + $e.getStackTrace() + \".\"); throw $e;"); | ||
384 | } else if (m.getName().equals("close") && sig.equals("()V")) { // STAY! | ||
385 | eb.append("ninedogs.db('O', 'w', 'e', $0, null, null, null);"); | ||
386 | ee.append("ninedogs.db('O', 'w', 'x', $0, $e, null, null); throw $e;"); | ||
387 | } else if (m.getName().equals("executeQuery") | ||
388 | && sig.equals("(Ljava/lang/String;)Ljava/sql/ResultSet;")) { | ||
389 | continue; | ||
390 | } else if (m.getName().equals("getResultSet") | ||
391 | && sig.equals("()Ljava/sql/ResultSet;")) { // STAY! TODO - not clear if we need 's' variant (if a db round trip takes place) | ||
392 | sb.append("ninedogs.db('O', 'g', 's', $0, null, null, null);"); | ||
393 | eb.append("ninedogs.db('O', 'g', 'e', $0, $_, null, null);"); | ||
394 | ee.append("ninedogs.db('O', 'g', 'x', $0, $e, null, null); throw $e;"); | ||
395 | } else if (ignore_most) { | ||
396 | continue; | ||
397 | } | ||
398 | ////////////////////////////////////////////////////////////// Oracle END | ||
135 | 399 | } else { | } else { |
136 | //System.err.println(" unknown class " + className + " in QueryTransformer! ==================="); | ||
137 | //sb.append("ninedogs.log(\"gen " + className + " " + m.getName() + " " + sig + "\");"); | ||
138 | //eb.append("ninedogs.log(\" db pg gen done " + className + " " + m.getName() + " " + sig + "\");"); | ||
139 | //continue; | ||
400 | //System.err.println(" unknown class " + className + "/" + m.getName() + " in QueryTransformer! ==================="); | ||
401 | //sb.append("ninedogs.log(\" gen b " + clas /Name + " " + m.getName() + " " + sig + "\");"); | ||
402 | //eb.append("ninedogs.log(\" gen e " + className + "/" + m.getName() + " " + sig + "\");"); | ||
403 | if (ignore_most) | ||
404 | continue; | ||
140 | 405 | } | } |
141 | 406 | ||
142 | 407 | /* | /* |
... | ... | public class QueryTransformer implements ClassFileTransformer | |
155 | 420 | //sb.append("sbArgs.append(System.identityHashCode( $0 ) );"); | //sb.append("sbArgs.append(System.identityHashCode( $0 ) );"); |
156 | 421 | */ | */ |
157 | 422 | ||
158 | //CtClass[] pTypes = m.getParameterTypes(); | ||
159 | //for (int i = 0; i < pTypes.length; i++) { | ||
160 | //if ((i == 0) && (pTypes[i].toString() == "java.lang.String")) | ||
161 | ///sb.append("ninedogs.log(\" para[" + i + "] [" + pTypes[i].getName() + "]: \" + $args[" + i + "]);"); | ||
162 | // pType.toString() - too verbose | ||
423 | if (1 == 1) { | ||
424 | CtClass[] pTypes = m.getParameterTypes(); | ||
425 | for (int i = 0; i < pTypes.length; i++) { | ||
426 | sb.append("ninedogs.log(\" para[" + i + "] [" + pTypes[i].getName() | ||
427 | + "]: \" + $args[" + i + "]);"); | ||
163 | 428 | ||
164 | //if (pTypes[i].isPrimitive()) { | ||
165 | // sb.append("System.err.println(\" para prim " + i + ": " + pTypes[i].toString() + " prim: \" + $args[" + i + "]);"); | ||
166 | //} else { | ||
167 | // sb.append("System.err.println(\" para !prim " + i + ": \" + System.identityHashCode($args[" + i + "]));"); | ||
168 | //} | ||
169 | //sb.append("System.err.println(\" para " + i + ": class: \" + $args[" + i + "].getClass());"); | ||
170 | //} | ||
429 | if (1 == 0) { | ||
430 | if (pTypes[i].toString() == "java.lang.String") { | ||
431 | //sb.append("System.err.println(\" " + m.getName() + ": para " + i | ||
432 | // + " str: " + pTypes[i].getName() + ": \" + $args[" + i + "]);"); | ||
433 | //sb.append("ninedogs.log(\" para[" + i + "] [" + pTypes[i].getName() | ||
434 | // + "]: \" + $args[" + i + "]);"); | ||
435 | //pType.toString() - too verbose | ||
436 | } else if (pTypes[i].isPrimitive()) { | ||
437 | sb.append("System.err.println(\" " + className + ": " + m.getName() + ": para " + i | ||
438 | + " prim: " + pTypes[i].toString() + ": value=[\" + $args[" + i + "] + \"]\");"); | ||
439 | //sb.append("System.err.println(\" " + m.getName() + ": para " + i + " name: " + pTypes[i].getName() + ": \" + $args[" + i + "]);"); | ||
440 | } else { | ||
441 | sb.append("System.err.println(\" " + className + ": " + m.getName() + ": para " + i | ||
442 | + " !prim: hash=\" + System.identityHashCode($args[" + i + "])" | ||
443 | + " + \": class: \" + $args[" + i + "].getClass() + \" value=[\" + $args[" + i + "] + \"]\");"); | ||
444 | } | ||
445 | } | ||
446 | } | ||
447 | } | ||
171 | 448 | ||
172 | /* | ||
449 | /* | ||
173 | 450 | m.insertBefore("{" + sb.toString() + "}"); | m.insertBefore("{" + sb.toString() + "}"); |
174 | 451 | ||
175 | 452 | eb.append("endTime = System.currentTimeMillis();"); | eb.append("endTime = System.currentTimeMillis();"); |
176 | 453 | eb.append("opTime = endTime - startTime;"); | eb.append("opTime = endTime - startTime;"); |
177 | 454 | eb.append("System.err.println(\" " + m.getName() + ": \" + opTime + \"ms: \" + $_);"); | eb.append("System.err.println(\" " + m.getName() + ": \" + opTime + \"ms: \" + $_);"); |
178 | 455 | m.insertAfter("{" + eb.toString() + "}"); | m.insertAfter("{" + eb.toString() + "}"); |
179 | */ | ||
456 | */ | ||
180 | 457 | ||
181 | if (sb.length() > 0) | ||
182 | m.insertBefore("{" + sb.toString() + "}"); | ||
183 | if (eb.length() > 0) | ||
184 | m.insertAfter("{" + eb.toString() + "}"); | ||
185 | // TODO: this code was un-commented - see above | ||
186 | //if (ee.length() > 0) | ||
187 | // m.addCatch("{" + ee.toString() + "}", etype); | ||
458 | try { | ||
459 | if (sb.length() > 0) | ||
460 | m.insertBefore("try {" + sb.toString() + "} catch (Exception _e) {}"); | ||
461 | if (eb.length() > 0) | ||
462 | m.insertAfter("try {" + eb.toString() + "} catch (Exception _e) {}"); | ||
463 | if (ee.length() > 0) | ||
464 | m.addCatch("{" + ee.toString() + "}", etype); | ||
465 | } catch (Exception e) { | ||
466 | System.err.println("Cannot insert code [" + className + "/" + m.getName() + ": " + e); | ||
467 | } | ||
188 | 468 | } | } |
189 | 469 | ||
190 | 470 | byteCode = cc.toBytecode(); | byteCode = cc.toBytecode(); |
191 | 471 | //System.err.println(" bytecode after: " + byteCode); | //System.err.println(" bytecode after: " + byteCode); |
192 | 472 | cc.detach(); | cc.detach(); |
193 | //System.err.println(" bytecode rewritten ok"); | ||
194 | } catch (NotFoundException | CannotCompileException | IOException e) { | ||
473 | } catch (Exception e) { | ||
195 | 474 | System.err.println(" QueryTransformer.transform Exception: " + e); | System.err.println(" QueryTransformer.transform Exception: " + e); |
475 | return null; | ||
196 | 476 | } | } |
197 | 477 | ||
198 | 478 | return byteCode; | return byteCode; |
File agent/java/agent/ninedogs.java changed (mode: 100644) (index f57bcf4..9e3c52a) | |||
1 | 1 | import java.io.*; | import java.io.*; |
2 | import java.lang.Integer; | ||
3 | import java.util.Properties; | ||
2 | 4 | import java.security.cert.X509Certificate; | import java.security.cert.X509Certificate; |
3 | 5 | ||
4 | 6 | public class ninedogs | public class ninedogs |
... | ... | public class ninedogs | |
9 | 11 | ||
10 | 12 | public static void init() | public static void init() |
11 | 13 | { | { |
12 | System.err.println("ninedogs.init"); | ||
14 | //System.err.println("ninedogs.init"); | ||
13 | 15 | ||
14 | 16 | // First time, get() returns 'null' | // First time, get() returns 'null' |
15 | 17 | if (init.get() != null) | if (init.get() != null) |
... | ... | public class ninedogs | |
19 | 21 | file = new File("/dev/ninedogs"); | file = new File("/dev/ninedogs"); |
20 | 22 | fd = new FileOutputStream(file); | fd = new FileOutputStream(file); |
21 | 23 | init.set(1); | init.set(1); |
22 | System.err.println("ninedogs.init: init=" + init.get()); | ||
24 | //System.err.println("ninedogs.init: init=" + init.get()); | ||
23 | 25 | } catch (Exception e) { | } catch (Exception e) { |
24 | 26 | System.err.println("ninedogs.init: exception " + e); | System.err.println("ninedogs.init: exception " + e); |
25 | 27 | } | } |
26 | 28 | } | } |
27 | 29 | ||
28 | public static void metric(byte[] s) | ||
30 | public static void write(byte[] s) | ||
29 | 31 | { | { |
30 | 32 | init(); | init(); |
31 | 33 | ||
... | ... | public class ninedogs | |
39 | 41 | } | } |
40 | 42 | } | } |
41 | 43 | ||
42 | public static void log(String s) | ||
44 | public static byte[] string2ninedogs(char type, byte[] ch) | ||
43 | 45 | { | { |
44 | int stklen = Thread.currentThread().getStackTrace().length; | ||
45 | String prefix = ""; | ||
46 | |||
47 | if (stklen >= 5) | ||
48 | stklen -= 5; | ||
49 | for (int i = 0; i < stklen; i++) | ||
50 | prefix += " "; | ||
46 | if (ch.length == 0) | ||
47 | return new byte[] {}; | ||
51 | 48 | ||
52 | System.err.println("T" + Thread.currentThread() + " " + prefix + s); | ||
53 | } | ||
54 | |||
55 | public static byte[] string2ninedogs(String type, byte[] ch) | ||
56 | { | ||
57 | byte[] header = type.getBytes(); | ||
58 | byte[] len = Integer.toString(ch.length).getBytes(); | ||
59 | byte[] ret = new byte[header.length + len.length + 1 + ch.length]; | ||
49 | byte[] len = String.format("%1$04x", ch.length).getBytes(); | ||
50 | byte[] ret = new byte[1 + len.length + ch.length]; | ||
60 | 51 | Integer off = 0; | Integer off = 0; |
61 | |||
62 | System.arraycopy(header, 0, ret, 0, header.length); off += header.length; | ||
52 | ret[off++] = (byte) type; | ||
63 | 53 | System.arraycopy(len, 0, ret, off, len.length); off += len.length; | System.arraycopy(len, 0, ret, off, len.length); off += len.length; |
64 | ret[off] = ' '; off += 1; | ||
65 | 54 | System.arraycopy(ch, 0, ret, off, ch.length); | System.arraycopy(ch, 0, ret, off, ch.length); |
66 | 55 | ||
67 | 56 | return ret; | return ret; |
68 | 57 | } | } |
69 | 58 | ||
70 | public static byte[] string2ninedogs(String type, String s) | ||
59 | public static byte[] string2ninedogs(char type, String s) | ||
71 | 60 | { | { |
72 | 61 | byte[] ch = s.getBytes(); | byte[] ch = s.getBytes(); |
73 | 62 | return string2ninedogs(type, ch); | return string2ninedogs(type, ch); |
74 | 63 | } | } |
75 | 64 | ||
65 | public static void log(String s) | ||
66 | { | ||
67 | int stklen = Thread.currentThread().getStackTrace().length; | ||
68 | String prefix = ""; | ||
69 | |||
70 | //if (stklen >= 5) | ||
71 | // stklen -= 5; | ||
72 | for (int i = 0; i < stklen; i++) | ||
73 | prefix += " "; | ||
74 | |||
75 | //System.err.println("T" + Thread.currentThread() + " " + prefix + s); | ||
76 | byte[] x = string2ninedogs('L', Thread.currentThread() + "\t" + stklen + "\t" + prefix + s + "\n\0"); | ||
77 | write(x); | ||
78 | } | ||
79 | |||
76 | 80 | public static void log_cert(java.io.InputStream is, | public static void log_cert(java.io.InputStream is, |
77 | 81 | java.security.cert.Certificate cert) | java.security.cert.Certificate cert) |
78 | 82 | { | { |
... | ... | public class ninedogs | |
86 | 90 | Long ts; | Long ts; |
87 | 91 | int off = 0; | int off = 0; |
88 | 92 | ||
89 | subj = string2ninedogs("s", x.getSubjectX500Principal().toString()); | ||
90 | issuer = string2ninedogs("i", x.getIssuerX500Principal().toString()); | ||
91 | alg = string2ninedogs("a", x.getPublicKey().getAlgorithm().toString()); | ||
92 | ser = string2ninedogs("x", x.getSerialNumber().toString(16)); | ||
93 | //ser = string2ninedogs("x", x.getSerialNumber().toByteArray()); | ||
93 | subj = string2ninedogs('s', x.getSubjectX500Principal().toString()); | ||
94 | issuer = string2ninedogs('i', x.getIssuerX500Principal().toString()); | ||
95 | alg = string2ninedogs('a', x.getPublicKey().getAlgorithm().toString()); | ||
96 | ser = string2ninedogs('x', x.getSerialNumber().toString(16)); | ||
97 | //ser = string2ninedogs('x', x.getSerialNumber().toByteArray()); | ||
94 | 98 | ||
95 | 99 | ts = x.getNotBefore().getTime() / 1000; | ts = x.getNotBefore().getTime() / 1000; |
96 | start = string2ninedogs("S", Long.toString(ts)); | ||
100 | start = string2ninedogs('S', Long.toString(ts)); | ||
97 | 101 | ||
98 | 102 | ts = x.getNotAfter().getTime() / 1000; | ts = x.getNotAfter().getTime() / 1000; |
99 | end = string2ninedogs("E", Long.toString(ts)); | ||
103 | end = string2ninedogs('E', Long.toString(ts)); | ||
100 | 104 | ||
101 | 105 | byte[] last = new byte[1 + 1 + subj.length + issuer.length + alg.length + ser.length + start.length + end.length + 1]; | byte[] last = new byte[1 + 1 + subj.length + issuer.length + alg.length + ser.length + start.length + end.length + 1]; |
102 | 106 | last[off] = 'c'; off += 1; // c = cert | last[off] = 'c'; off += 1; // c = cert |
... | ... | public class ninedogs | |
108 | 112 | System.arraycopy(start, 0, last, off, start.length); off += start.length; | System.arraycopy(start, 0, last, off, start.length); off += start.length; |
109 | 113 | System.arraycopy(end, 0, last, off, end.length); off += end.length; | System.arraycopy(end, 0, last, off, end.length); off += end.length; |
110 | 114 | last[off++] = 0; | last[off++] = 0; |
111 | metric(last); | ||
115 | write(last); | ||
116 | } | ||
117 | |||
118 | public static void db(char db_type, char type, char subtype, | ||
119 | Object parent_this, Object p1, Object p2, Object p3) | ||
120 | { | ||
121 | byte[] hash, str ={}, str2 = {}, ret = {}, ex = {}, ex_cause = {}; | ||
122 | int off = 0; | ||
123 | String r = null; | ||
124 | Object e = null; | ||
125 | |||
126 | try { | ||
127 | String shash = parent_this != null ? Integer.toHexString(parent_this.hashCode()) : null; | ||
128 | hash = string2ninedogs('h', shash); | ||
129 | String hp1 = p1 != null ? Integer.toHexString(p1.hashCode()) : null; | ||
130 | String hp2 = p2 != null ? Integer.toHexString(p2.hashCode()) : null; | ||
131 | String hp3 = p3 != null ? Integer.toHexString(p3.hashCode()) : null; | ||
132 | |||
133 | log("ninedogs.db: db_type=" + db_type + " type=" + type | ||
134 | + " subtype=" + subtype + " hash=" + shash | ||
135 | + " p1=[" + p1 + "] p2=[" + p2 + "] p3=[" + p3 + "]"); | ||
136 | |||
137 | if ((subtype != 's') && (subtype != 'e') && (subtype != 'x')) { | ||
138 | log("ninedogs.db: invalid subtype " + subtype + "!"); | ||
139 | return; | ||
140 | } | ||
141 | |||
142 | if (type == 'c') { | ||
143 | Properties oprops = (Properties) p2, props = new Properties(); | ||
144 | props.putAll(oprops); | ||
145 | props.remove("password"); | ||
146 | str = string2ninedogs('c', (String) p1 + " " + props.toString()); | ||
147 | r = hp3; | ||
148 | e = p3; | ||
149 | } else if (type == 'Q') { // execute normal query | ||
150 | str = string2ninedogs('q', (String) p1); | ||
151 | r = hp2; | ||
152 | e = p2; | ||
153 | } else if (type == 'P') { // PgStatement.executeQuery | ||
154 | r = hp1; | ||
155 | e = p1; | ||
156 | } else if ((type == 'e') || (type == 'E') || (type == 'P')) { | ||
157 | r = hp1; | ||
158 | e = p1; | ||
159 | } else if (type == 'f') { // create statement | ||
160 | r = hp1; | ||
161 | e = p1; | ||
162 | } else if (type == 'p') { // create prepared statement | ||
163 | str = string2ninedogs('q', (String) p1); | ||
164 | r = hp2; | ||
165 | e = p2; | ||
166 | } else if (type == 'w') { // Statement/close | ||
167 | e = p1; | ||
168 | } else if (type == 'x') { // connection/close | ||
169 | e = p1; | ||
170 | } else if (type == 'g') { // getResultSet | ||
171 | r = hp1; | ||
172 | e = p1; | ||
173 | } else if (type == 'b') { // [P] setInt | ||
174 | Integer index = (Integer) p1; | ||
175 | str = string2ninedogs('i', index.toString()); | ||
176 | Integer value = (Integer) p2; | ||
177 | str2 = string2ninedogs('v', value.toString()); | ||
178 | e = p3; | ||
179 | } else if (type == 'S') { // [P] setString | ||
180 | Integer index = (Integer) p1; | ||
181 | str = string2ninedogs('i', index.toString()); | ||
182 | str2 = string2ninedogs('s', (String) p2); | ||
183 | e = p3; | ||
184 | } else { | ||
185 | log("ninedogs.db: invalid type " + type + "!"); | ||
186 | return; | ||
187 | } | ||
188 | |||
189 | if ((subtype == 'e') && (r != null)) { | ||
190 | ret = string2ninedogs('R', r); | ||
191 | } else if (subtype == 'x') { | ||
192 | Exception e0 = (java.lang.Exception) e; | ||
193 | ex = string2ninedogs('e', e0.toString()); | ||
194 | java.lang.Throwable t = e0.getCause(); | ||
195 | if (t != null) | ||
196 | ex_cause = string2ninedogs('E', t.toString()); | ||
197 | } | ||
198 | |||
199 | int len = 1 + 1 + 1 + 1 + hash.length + str.length | ||
200 | + str2.length + ret.length + ex.length + ex_cause.length + 1; | ||
201 | //log("ninedogs.db: packing " + len + " bytes"); | ||
202 | byte[] last = new byte[len]; | ||
203 | last[off++] = 'D'; // D = db | ||
204 | last[off++] = (byte) db_type; | ||
205 | last[off++] = (byte) type; | ||
206 | last[off++] = (byte) subtype; | ||
207 | System.arraycopy(hash, 0, last, off, hash.length); off += hash.length; | ||
208 | System.arraycopy(str, 0, last, off, str.length); off += str.length; | ||
209 | System.arraycopy(str2, 0, last, off, str2.length); off += str2.length; | ||
210 | System.arraycopy(ret, 0, last, off, ret.length); off += ret.length; | ||
211 | System.arraycopy(ex, 0, last, off, ex.length); off += ex.length; | ||
212 | System.arraycopy(ex_cause, 0, last, off, ex_cause.length); off += ex_cause.length; // TODO: use this | ||
213 | last[off++] = 0; | ||
214 | write(last); | ||
215 | //log("ninedogs.db: wrote " + len + " bytes"); | ||
216 | } catch (Exception _e) { | ||
217 | log("ninedogs.db: exception: " + _e); | ||
218 | } | ||
112 | 219 | } | } |
113 | 220 | } | } |
114 | 221 |
File agent/ninedogs.TODO changed (mode: 100644) (index 5a2fa57..afc944c) | |||
... | ... | to: | |
13 | 13 | To add: | To add: |
14 | 14 | - | - |
15 | 15 | ||
16 | [ ] If a trqacer does not update a counter in 10s, consider it dead. | ||
17 | [ ] Remember user what was the prepared query (because we will not have it | ||
18 | in clear at the execution time). | ||
19 | [ ] socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 10 | ||
20 | [ ] Load ninedogs.so with an environemnt variable to replace ninedogs.dlsym.so. | ||
21 | [ ] | ||
22 |
File agent/ninedogs.c changed (mode: 100644) (index d1a322b..daff96b) | |||
56 | 56 | #include "info.h" | #include "info.h" |
57 | 57 | #include "decode_text.h" | #include "decode_text.h" |
58 | 58 | #include "curl.h" | #include "curl.h" |
59 | #include "trace_encode.h" | ||
59 | 60 | ||
60 | 61 | #define FB_FLAGS_NETSOCK (1 << 0) | #define FB_FLAGS_NETSOCK (1 << 0) |
61 | 62 | #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 |
... | ... | static struct dlopen_node dlopen_nodes[DLOPEN_MAX_ENTRIES]; // TODO: we need loc | |
85 | 86 | static unsigned char my_malloc[20ULL * 65536ULL]; | static unsigned char my_malloc[20ULL * 65536ULL]; |
86 | 87 | static unsigned long my_malloc_pos; | static unsigned long my_malloc_pos; |
87 | 88 | ||
89 | static unsigned int msgs_lost; | ||
90 | static char shared_inited; | ||
88 | 91 | static struct shared *shared; | static struct shared *shared; |
89 | static unsigned char shared_inited; | ||
90 | 92 | static struct nd_info_shared *nd_info; | static struct nd_info_shared *nd_info; |
91 | 93 | static unsigned char nd_info_inited; | static unsigned char nd_info_inited; |
92 | 94 | char trace_enabled = 1; | char trace_enabled = 1; |
... | ... | static int (*old_fstatat)(int dirfd, const char *restrict pathname, | |
143 | 145 | static int (*old_fstatat64)(int dirfd, const char *restrict pathname, | static int (*old_fstatat64)(int dirfd, const char *restrict pathname, |
144 | 146 | struct stat64 *restrict statbuf, int flags); | struct stat64 *restrict statbuf, int flags); |
145 | 147 | static pid_t (*old_fork)(void); | static pid_t (*old_fork)(void); |
148 | static int (*old_shm_open)(const char *name, int oflag, mode_t mode); | ||
146 | 149 | ||
147 | 150 | /* fd helpers */ | /* fd helpers */ |
148 | 151 | static struct fd_node *fd_search(const int fd) | static struct fd_node *fd_search(const int fd) |
... | ... | static struct fd_node *fd_search(const int fd) | |
161 | 164 | ||
162 | 165 | static struct fd_node *fd_add(const int fd) | static struct fd_node *fd_add(const int fd) |
163 | 166 | { | { |
164 | int save_errno; | ||
167 | int saved_errno; | ||
165 | 168 | ||
166 | 169 | struct fd_node *q; | struct fd_node *q; |
167 | 170 | ||
... | ... | static struct fd_node *fd_add(const int fd) | |
172 | 175 | q = q->next; | q = q->next; |
173 | 176 | } | } |
174 | 177 | if (!q) { | if (!q) { |
175 | save_errno = errno; | ||
178 | saved_errno = errno; | ||
176 | 179 | q = old_malloc(sizeof(struct fd_node)); | q = old_malloc(sizeof(struct fd_node)); |
177 | errno = save_errno; | ||
180 | errno = saved_errno; | ||
178 | 181 | if (!q) | if (!q) |
179 | 182 | return NULL; | return NULL; |
180 | 183 | memset(q, 0, sizeof(struct fd_node)); | memset(q, 0, sizeof(struct fd_node)); |
... | ... | static void fd_del(const int fd) | |
204 | 207 | } | } |
205 | 208 | } | } |
206 | 209 | ||
207 | /* Functions */ | ||
208 | static void my_trace_put8(unsigned char *buf, unsigned int *i, const uint8_t v) | ||
209 | { | ||
210 | buf[*i] = v; *i = *i + 1; | ||
211 | } | ||
212 | |||
213 | static void my_trace_put16(unsigned char *buf, unsigned int *i, const uint16_t v) | ||
214 | { | ||
215 | uint16_t u = htobe16(v); | ||
216 | memcpy(buf + *i, &u, 2); *i = *i + 2; | ||
217 | } | ||
218 | |||
219 | static void my_trace_put32(unsigned char *buf, unsigned int *i, const uint32_t v) | ||
220 | { | ||
221 | uint32_t u = htobe32(v); | ||
222 | memcpy(buf + *i, &u, 4); *i = *i + 4; | ||
223 | } | ||
224 | |||
225 | static void my_trace_put64(unsigned char *buf, unsigned int *i, const uint64_t v) | ||
226 | { | ||
227 | uint64_t u = htobe64(v); | ||
228 | memcpy(buf + *i, &u, 8); *i = *i + 8; | ||
229 | } | ||
230 | |||
231 | static void my_trace_put_double(unsigned char *buf, unsigned int *i, const double v) | ||
232 | { | ||
233 | uint64_t u; | ||
234 | memcpy(&u, &v, 8); | ||
235 | my_trace_put64(buf, i, u); | ||
236 | } | ||
237 | |||
238 | static void my_trace_put_bool(unsigned char *buf, unsigned int *i, const char v) | ||
239 | { | ||
240 | buf[*i] = v; *i = *i + 1; | ||
241 | } | ||
242 | |||
243 | static void my_trace_put(unsigned char *buf, unsigned int *i, | ||
244 | const void *in, const size_t in_len) | ||
245 | { | ||
246 | if (in_len == 0) | ||
247 | return; | ||
248 | |||
249 | memcpy(buf + *i, in, in_len); | ||
250 | *i = *i + in_len; | ||
251 | } | ||
252 | |||
253 | // Seems that all fields are stored in BE order | ||
254 | static void my_trace_sockaddr(unsigned char *buf, unsigned int *i, | ||
255 | const struct sockaddr *a, const int len) | ||
256 | { | ||
257 | my_trace_put16(buf, i, len); | ||
258 | my_trace_put(buf, i, a, a ? len : 0); | ||
259 | } | ||
260 | |||
261 | static void my_trace_put_stat(unsigned char *buf, unsigned int *i, struct stat *s) | ||
262 | { | ||
263 | my_trace_put64(buf, i, s->st_dev); | ||
264 | my_trace_put64(buf, i, s->st_ino); | ||
265 | my_trace_put32(buf, i, s->st_mode); | ||
266 | my_trace_put64(buf, i, s->st_nlink); | ||
267 | my_trace_put32(buf, i, s->st_uid); | ||
268 | my_trace_put32(buf, i, s->st_gid); | ||
269 | my_trace_put64(buf, i, s->st_rdev); | ||
270 | my_trace_put64(buf, i, s->st_size); | ||
271 | my_trace_put64(buf, i, s->st_blksize); | ||
272 | my_trace_put64(buf, i, s->st_blocks); | ||
273 | my_trace_put64(buf, i, s->st_atim.tv_sec); | ||
274 | my_trace_put32(buf, i, s->st_atim.tv_nsec); | ||
275 | my_trace_put64(buf, i, s->st_mtim.tv_sec); | ||
276 | my_trace_put32(buf, i, s->st_mtim.tv_nsec); | ||
277 | my_trace_put64(buf, i, s->st_ctim.tv_sec); | ||
278 | my_trace_put32(buf, i, s->st_ctim.tv_nsec); | ||
279 | } | ||
280 | |||
281 | static void my_trace_put_string_array(unsigned char *buf, unsigned int *i, char *list[]) | ||
282 | { | ||
283 | unsigned int j = 0; | ||
284 | |||
285 | while (1) { | ||
286 | if (!list[j]) { | ||
287 | my_trace_put32(buf, i, 0); | ||
288 | break; | ||
289 | } | ||
290 | |||
291 | unsigned short len = strlen(list[j]); | ||
292 | my_trace_put16(buf, i, len); | ||
293 | my_trace_put(buf, i, list[j], len); | ||
294 | j++; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | static void my_trace_put_hostent(unsigned char *buf, unsigned int *i, struct hostent *he) | ||
299 | { | ||
300 | if (!he) | ||
301 | return; | ||
302 | |||
303 | int len = strlen(he->h_name); | ||
304 | my_trace_put8(buf, i, len); | ||
305 | my_trace_put(buf, i, he->h_name, len); | ||
306 | |||
307 | for (int j = 0; ; j++) { | ||
308 | if (!he->h_aliases[j]) { | ||
309 | my_trace_put8(buf, i, 0); | ||
310 | break; | ||
311 | } | ||
312 | |||
313 | len = strlen(he->h_aliases[j]); | ||
314 | my_trace_put8(buf, i, len); | ||
315 | my_trace_put(buf, i, he->h_aliases[j], len); | ||
316 | } | ||
317 | |||
318 | my_trace_put8(buf, i, he->h_addrtype); | ||
319 | my_trace_put8(buf, i, he->h_length); | ||
320 | |||
321 | int count = 0; | ||
322 | for (int j = 0; ; j++) { | ||
323 | if (!he->h_addr_list[j]) | ||
324 | break; | ||
325 | count++; | ||
326 | } | ||
327 | |||
328 | my_trace_put8(buf, i, count); | ||
329 | for (int j = 0; j < count; j++) { | ||
330 | xlog(0, " DEBUG: addr[%d]=[%s]\n", j, he->h_addr_list[j]); | ||
331 | my_trace_put(buf, i, he->h_addr_list[j], he->h_length); | ||
332 | } | ||
333 | } | ||
334 | |||
335 | 210 | /* | /* |
336 | 211 | * Returns how many byte were stored in | * Returns how many byte were stored in |
337 | 212 | */ | */ |
338 | 213 | static unsigned int my_trace_encode(unsigned char *buf, | static unsigned int my_trace_encode(unsigned char *buf, |
339 | const char *func, const char type, int save_errno, va_list va) | ||
214 | const char *func, const char *tf, const char type, const int saved_errno, va_list va) | ||
340 | 215 | { | { |
341 | 216 | unsigned int i, ic; | unsigned int i, ic; |
342 | 217 | ||
218 | xlog(100, "%s: func=[%s] tf=[%s] type=%c trace_depth=%hu saved_errno=%d\n", | ||
219 | __func__, func, tf, type, trace_depth, saved_errno); | ||
220 | |||
343 | 221 | i = 2; // first two bytes are for length | i = 2; // first two bytes are for length |
344 | 222 | my_trace_put8(buf, &i, SHARED_FUNC); | my_trace_put8(buf, &i, SHARED_FUNC); |
345 | 223 | ||
346 | 224 | struct timeval tv; | struct timeval tv; |
347 | 225 | gettimeofday(&tv, NULL); | gettimeofday(&tv, NULL); |
348 | 226 | my_trace_put64(buf, &i, tv.tv_sec * 1000 + tv.tv_usec / 1000); | my_trace_put64(buf, &i, tv.tv_sec * 1000 + tv.tv_usec / 1000); |
227 | uint8_t tf_len = strlen(tf); | ||
228 | my_trace_put8(buf, &i, tf_len); | ||
229 | my_trace_put(buf, &i, tf, tf_len); | ||
349 | 230 | my_trace_put16(buf, &i, trace_depth); | my_trace_put16(buf, &i, trace_depth); |
350 | 231 | unsigned short flen = strlen(func); | unsigned short flen = strlen(func); |
351 | 232 | my_trace_put16(buf, &i, flen); | my_trace_put16(buf, &i, flen); |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
389 | 270 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
390 | 271 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
391 | 272 | if (ret == -1) | if (ret == -1) |
392 | my_trace_put32(buf, &i, save_errno); | ||
273 | my_trace_put32(buf, &i, saved_errno); | ||
393 | 274 | } | } |
394 | 275 | } else if (strcmp(func, "accept4") == 0) { | } else if (strcmp(func, "accept4") == 0) { |
395 | 276 | my_trace_put32(buf, &i, va_arg(va, int)); // sock | my_trace_put32(buf, &i, va_arg(va, int)); // sock |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
407 | 288 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
408 | 289 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
409 | 290 | if (ret == -1) | if (ret == -1) |
410 | my_trace_put32(buf, &i, save_errno); | ||
291 | my_trace_put32(buf, &i, saved_errno); | ||
411 | 292 | } | } |
412 | 293 | } break; | } break; |
413 | 294 | ||
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
420 | 301 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
421 | 302 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
422 | 303 | if (ret == -1) | if (ret == -1) |
423 | my_trace_put32(buf, &i, save_errno); | ||
304 | my_trace_put32(buf, &i, saved_errno); | ||
424 | 305 | } break; | } break; |
425 | 306 | ||
426 | 307 | case 'c': | case 'c': |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
430 | 311 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
431 | 312 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
432 | 313 | if (ret == -1) | if (ret == -1) |
433 | my_trace_put32(buf, &i, save_errno); | ||
314 | my_trace_put32(buf, &i, saved_errno); | ||
434 | 315 | } | } |
435 | 316 | } else if (strcmp(func, "connect") == 0) { | } else if (strcmp(func, "connect") == 0) { |
436 | 317 | my_trace_put32(buf, &i, va_arg(va, int)); // sock | my_trace_put32(buf, &i, va_arg(va, int)); // sock |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
443 | 324 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
444 | 325 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
445 | 326 | if (ret == -1) | if (ret == -1) |
446 | my_trace_put32(buf, &i, save_errno); | ||
327 | my_trace_put32(buf, &i, saved_errno); | ||
447 | 328 | } | } |
448 | 329 | } else if (strcmp(func, "curl_easy_cleanup") == 0) { | } else if (strcmp(func, "curl_easy_cleanup") == 0) { |
449 | 330 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // handle |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
465 | 346 | } | } |
466 | 347 | } | } |
467 | 348 | } else if (strcmp(func, "curl_easy_perform") == 0) { | } else if (strcmp(func, "curl_easy_perform") == 0) { |
468 | if (type == 'm') { | ||
349 | if (type == 'm') { // TODO: this is strange! | ||
469 | 350 | char *info = va_arg(va, char *); | char *info = va_arg(va, char *); |
470 | 351 | unsigned char len = strlen(info); | unsigned char len = strlen(info); |
471 | 352 | my_trace_put8(buf, &i, len); | my_trace_put8(buf, &i, len); |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
548 | 429 | uint64_t h = (uint64_t) va_arg(va, void *); | uint64_t h = (uint64_t) va_arg(va, void *); |
549 | 430 | my_trace_put64(buf, &i, h); | my_trace_put64(buf, &i, h); |
550 | 431 | if (h == 0) | if (h == 0) |
551 | my_trace_put32(buf, &i, save_errno); | ||
432 | my_trace_put32(buf, &i, saved_errno); | ||
552 | 433 | } | } |
553 | 434 | } else if (strcmp(func, "dlclose") == 0) { | } else if (strcmp(func, "dlclose") == 0) { |
554 | 435 | uint64_t h = (uint64_t) va_arg(va, void *); | uint64_t h = (uint64_t) va_arg(va, void *); |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
556 | 437 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
557 | 438 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
558 | 439 | if (ret == -1) | if (ret == -1) |
559 | my_trace_put32(buf, &i, save_errno); | ||
440 | my_trace_put32(buf, &i, saved_errno); | ||
560 | 441 | } break; | } break; |
561 | 442 | ||
562 | 443 | case 'e': | case 'e': |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
571 | 452 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
572 | 453 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
573 | 454 | if (ret == -1) | if (ret == -1) |
574 | my_trace_put32(buf, &i, save_errno); | ||
455 | my_trace_put32(buf, &i, saved_errno); | ||
575 | 456 | } | } |
576 | 457 | } break; | } break; |
577 | 458 | ||
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
580 | 461 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
581 | 462 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
582 | 463 | if (ret == -1) | if (ret == -1) |
583 | my_trace_put32(buf, &i, save_errno); | ||
464 | my_trace_put32(buf, &i, saved_errno); | ||
584 | 465 | } else if ((strcmp(func, "fstatat") == 0) | } else if ((strcmp(func, "fstatat") == 0) |
585 | 466 | || (strcmp(func, "fstatat64") == 0)) { | || (strcmp(func, "fstatat64") == 0)) { |
586 | 467 | my_trace_put16(buf, &i, va_arg(va, int)); // dirfd | my_trace_put16(buf, &i, va_arg(va, int)); // dirfd |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
595 | 476 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
596 | 477 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
597 | 478 | if (ret == -1) | if (ret == -1) |
598 | my_trace_put32(buf, &i, save_errno); | ||
479 | my_trace_put32(buf, &i, saved_errno); | ||
599 | 480 | } | } |
600 | 481 | } else if ((strcmp(func, "fsync") == 0) | } else if ((strcmp(func, "fsync") == 0) |
601 | 482 | || (strcmp(func, "fdatasync") == 0)) { | || (strcmp(func, "fdatasync") == 0)) { |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
604 | 485 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
605 | 486 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
606 | 487 | if (ret == -1) | if (ret == -1) |
607 | my_trace_put32(buf, &i, save_errno); | ||
488 | my_trace_put32(buf, &i, saved_errno); | ||
489 | } | ||
490 | } else if (strcmp(func, "ftruncate") == 0) { | ||
491 | my_trace_put32(buf, &i, va_arg(va, int)); // fd | ||
492 | my_trace_put64(buf, &i, va_arg(va, uint64_t)); // length | ||
493 | if (type == 'r') { | ||
494 | int ret = va_arg(va, int); | ||
495 | my_trace_put32(buf, &i, ret); | ||
496 | if (ret == -1) | ||
497 | my_trace_put32(buf, &i, saved_errno); | ||
608 | 498 | } | } |
609 | 499 | } break; | } break; |
610 | 500 | ||
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
636 | 526 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
637 | 527 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
638 | 528 | if (ret == -1) | if (ret == -1) |
639 | my_trace_put32(buf, &i, save_errno); | ||
529 | my_trace_put32(buf, &i, saved_errno); | ||
640 | 530 | } | } |
641 | 531 | } else if (strcmp(func, "gethostbyname_r") == 0) { | } else if (strcmp(func, "gethostbyname_r") == 0) { |
642 | 532 | char *name = va_arg(va, char *); | char *name = va_arg(va, char *); |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
670 | 560 | my_trace_put16(buf, &i, max); | my_trace_put16(buf, &i, max); |
671 | 561 | my_trace_put(buf, &i, xbuf, max); | my_trace_put(buf, &i, xbuf, max); |
672 | 562 | } else { | } else { |
673 | my_trace_put32(buf, &i, save_errno); | ||
563 | my_trace_put32(buf, &i, saved_errno); | ||
674 | 564 | } | } |
675 | 565 | } | } |
676 | 566 | } else if (strcmp(func, "getsockopt") == 0) { | } else if (strcmp(func, "getsockopt") == 0) { |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
684 | 574 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
685 | 575 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
686 | 576 | if (ret == -1) | if (ret == -1) |
687 | my_trace_put32(buf, &i, save_errno); | ||
577 | my_trace_put32(buf, &i, saved_errno); | ||
578 | } break; | ||
579 | |||
580 | case 'i': | ||
581 | if ((strcmp(func, "imagecreate") == 0) | ||
582 | || (strcmp(func, "imagecreatetruecolor") == 0)) { | ||
583 | my_trace_put64(buf, &i, va_arg(va, uint64_t)); // w | ||
584 | my_trace_put64(buf, &i, va_arg(va, uint64_t)); // h | ||
585 | struct nd_gd_img *img = va_arg(va, struct nd_gd_img *); | ||
586 | my_trace_put64(buf, &i, (uint64_t) img->im); | ||
587 | } else if (strcmp(func, "imagedestroy") == 0) { | ||
588 | struct nd_gd_img *img = va_arg(va, struct nd_gd_img *); | ||
589 | my_trace_put64(buf, &i, (uint64_t) img->im); | ||
590 | my_trace_put32(buf, &i, img->elap.tv_sec * 1000 + img->elap.tv_usec / 1000); | ||
591 | my_trace_put_bool(buf, &i, va_arg(va, int)); // ret | ||
592 | } break; | ||
593 | |||
594 | case 'j': | ||
595 | if (strcmp(func, "java/db/connect") == 0) { | ||
596 | struct nd_db_conn *c = va_arg(va, struct nd_db_conn *); | ||
597 | my_trace_put8(buf, &i, c->type); | ||
598 | my_trace_put16(buf, &i, c->conn_str_len); | ||
599 | my_trace_put(buf, &i, c->conn_str, c->conn_str_len); | ||
600 | if (type == 'r') { | ||
601 | my_trace_put64(buf, &i, (uint64_t) c->dbh); | ||
602 | if (c->dbh != NULL) { | ||
603 | } else { | ||
604 | my_trace_put16(buf, &i, (uint64_t) c->ex_len); | ||
605 | my_trace_put(buf, &i, c->ex, c->ex_len); | ||
606 | } | ||
607 | } | ||
608 | } else if (strcmp(func, "java/db/close") == 0) { | ||
609 | struct nd_db_conn *c = va_arg(va, struct nd_db_conn *); | ||
610 | my_trace_put8(buf, &i, c->type); | ||
611 | my_trace_put64(buf, &i, (uint64_t) c->dbh); | ||
612 | } else if ((strcmp(func, "java/db/prepared/execute") == 0) | ||
613 | || (strcmp(func, "java/db/stmt/execute") == 0)) { | ||
614 | struct nd_db_stmt *e = va_arg(va, struct nd_db_stmt *); | ||
615 | my_trace_put8(buf, &i, e->type); | ||
616 | my_trace_put64(buf, &i, (uint64_t) e->stmt); | ||
617 | if (type == 'r') { | ||
618 | my_trace_put64(buf, &i, (uint64_t) e->res); | ||
619 | if (e->res == NULL) { | ||
620 | my_trace_put16(buf, &i, (uint64_t) e->ex_len); | ||
621 | my_trace_put(buf, &i, e->ex, e->ex_len); | ||
622 | } | ||
623 | #if 0 | ||
624 | TODO | ||
625 | if (e->ret == 1) { | ||
626 | my_trace_put64(buf, &i, e->num); | ||
627 | my_trace_put64(buf, &i, e->aff); | ||
628 | } | ||
629 | #endif | ||
630 | } | ||
631 | } else if (strcmp(func, "java/db/prepare") == 0) { | ||
632 | struct nd_db_stmt *e = va_arg(va, struct nd_db_stmt *); | ||
633 | my_trace_put8(buf, &i, e->type); | ||
634 | my_trace_put64(buf, &i, (uint64_t) e->dbh); | ||
635 | my_trace_put16(buf, &i, e->q_len); | ||
636 | my_trace_put(buf, &i, e->q, e->q_len); | ||
637 | if (type == 'r') { | ||
638 | my_trace_put64(buf, &i, (uint64_t) e->stmt); | ||
639 | if (e->stmt == NULL) { | ||
640 | my_trace_put16(buf, &i, (uint64_t) e->ex_len); | ||
641 | my_trace_put(buf, &i, e->ex, e->ex_len); | ||
642 | } | ||
643 | } | ||
644 | } else if (strcmp(func, "java/db/stmt/create") == 0) { | ||
645 | struct nd_db_stmt *e = va_arg(va, struct nd_db_stmt *); | ||
646 | my_trace_put8(buf, &i, e->type); | ||
647 | my_trace_put64(buf, &i, (uint64_t) e->dbh); | ||
648 | my_trace_put64(buf, &i, (uint64_t) e->stmt); | ||
649 | if (e->stmt == NULL) { | ||
650 | my_trace_put16(buf, &i, (uint64_t) e->ex_len); | ||
651 | my_trace_put(buf, &i, e->ex, e->ex_len); | ||
652 | } | ||
653 | } else if (strcmp(func, "java/db/stmt/close") == 0) { | ||
654 | struct nd_db_stmt *e = va_arg(va, struct nd_db_stmt *); | ||
655 | my_trace_put8(buf, &i, e->type); | ||
656 | my_trace_put64(buf, &i, (uint64_t) e->stmt); | ||
657 | } else if (strcmp(func, "java/db/stmt/execute/sql") == 0) { | ||
658 | struct nd_db_stmt *e = va_arg(va, struct nd_db_stmt *); | ||
659 | my_trace_put8(buf, &i, e->type); | ||
660 | my_trace_put64(buf, &i, (uint64_t) e->stmt); | ||
661 | my_trace_put16(buf, &i, e->q_len); | ||
662 | my_trace_put(buf, &i, e->q, e->q_len); | ||
663 | if (type == 'r') { | ||
664 | my_trace_put64(buf, &i, (uint64_t) e->res); | ||
665 | if (e->res == NULL) { | ||
666 | my_trace_put16(buf, &i, (uint64_t) e->ex_len); | ||
667 | my_trace_put(buf, &i, e->ex, e->ex_len); | ||
668 | } | ||
669 | } | ||
670 | } else if (strcmp(func, "java/db/result/get") == 0) { | ||
671 | struct nd_db_stmt *e = va_arg(va, struct nd_db_stmt *); | ||
672 | my_trace_put8(buf, &i, e->type); | ||
673 | my_trace_put64(buf, &i, (uint64_t) e->stmt); | ||
674 | if (type == 'r') { | ||
675 | my_trace_put64(buf, &i, (uint64_t) e->res); | ||
676 | if (e->res == NULL) { | ||
677 | my_trace_put16(buf, &i, (uint64_t) e->ex_len); | ||
678 | my_trace_put(buf, &i, e->ex, e->ex_len); | ||
679 | } | ||
680 | } | ||
681 | } else if (strcmp(func, "java/db/stmt/setInt") == 0) { | ||
682 | struct nd_db_stmt *e = va_arg(va, struct nd_db_stmt *); | ||
683 | my_trace_put8(buf, &i, e->type); | ||
684 | my_trace_put64(buf, &i, (uint64_t) e->stmt); | ||
685 | my_trace_put8(buf, &i, e->params.list[1].length); // abuse alert - used as index | ||
686 | my_trace_put32(buf, &i, e->params.list[0].l); | ||
687 | my_trace_put64(buf, &i, (uint64_t) e->res); | ||
688 | if (e->res == NULL) { | ||
689 | my_trace_put16(buf, &i, (uint64_t) e->ex_len); | ||
690 | my_trace_put(buf, &i, e->ex, e->ex_len); | ||
691 | } | ||
692 | } else if (strcmp(func, "java/db/stmt/setString") == 0) { | ||
693 | struct nd_db_stmt *e = va_arg(va, struct nd_db_stmt *); | ||
694 | my_trace_put8(buf, &i, e->type); | ||
695 | my_trace_put64(buf, &i, (uint64_t) e->stmt); | ||
696 | my_trace_put8(buf, &i, e->params.list[1].length); // abuse alert - used as index | ||
697 | my_trace_put16(buf, &i, e->params.list[0].length); | ||
698 | my_trace_put(buf, &i, e->params.list[0].str, e->params.list[0].length); | ||
699 | my_trace_put64(buf, &i, (uint64_t) e->res); | ||
700 | if (e->res == NULL) { | ||
701 | my_trace_put16(buf, &i, (uint64_t) e->ex_len); | ||
702 | my_trace_put(buf, &i, e->ex, e->ex_len); | ||
703 | } | ||
688 | 704 | } break; | } break; |
689 | 705 | ||
690 | 706 | case 'l': | case 'l': |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
694 | 710 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
695 | 711 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
696 | 712 | if (ret == -1) | if (ret == -1) |
697 | my_trace_put32(buf, &i, save_errno); | ||
713 | my_trace_put32(buf, &i, saved_errno); | ||
698 | 714 | } else if (strcmp(func, "lseek") == 0) { | } else if (strcmp(func, "lseek") == 0) { |
699 | 715 | my_trace_put32(buf, &i, va_arg(va, int)); // fd | my_trace_put32(buf, &i, va_arg(va, int)); // fd |
700 | 716 | my_trace_put64(buf, &i, va_arg(va, uint64_t)); // off | my_trace_put64(buf, &i, va_arg(va, uint64_t)); // off |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
703 | 719 | ssize_t ret = va_arg(va, ssize_t); | ssize_t ret = va_arg(va, ssize_t); |
704 | 720 | my_trace_put64(buf, &i, ret); | my_trace_put64(buf, &i, ret); |
705 | 721 | if (ret == -1) | if (ret == -1) |
706 | my_trace_put32(buf, &i, save_errno); | ||
722 | my_trace_put32(buf, &i, saved_errno); | ||
707 | 723 | } | } |
708 | 724 | } break; | } break; |
709 | 725 | ||
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
718 | 734 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
719 | 735 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
720 | 736 | if (ret == -1) | if (ret == -1) |
721 | my_trace_put32(buf, &i, save_errno); | ||
737 | my_trace_put32(buf, &i, saved_errno); | ||
722 | 738 | } | } |
723 | 739 | } else if (strcmp(func, "mysqli_autocommit") == 0) { | } else if (strcmp(func, "mysqli_autocommit") == 0) { |
724 | 740 | struct db_autocommit *a = va_arg(va, struct db_autocommit *); | struct db_autocommit *a = va_arg(va, struct db_autocommit *); |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
727 | 743 | if (type == 'r') | if (type == 'r') |
728 | 744 | my_trace_put_bool(buf, &i, a->ret); | my_trace_put_bool(buf, &i, a->ret); |
729 | 745 | } else if (strcmp(func, "mysqli_close") == 0) { | } else if (strcmp(func, "mysqli_close") == 0) { |
730 | struct conn *c = va_arg(va, struct conn *); | ||
746 | struct nd_db_conn *c = va_arg(va, struct nd_db_conn *); | ||
731 | 747 | my_trace_put64(buf, &i, (uint64_t) c->dbh); | my_trace_put64(buf, &i, (uint64_t) c->dbh); |
732 | 748 | if (type == 'r') | if (type == 'r') |
733 | my_trace_put_bool(buf, &i, c->ret); | ||
749 | my_trace_put_bool(buf, &i, c->ok); | ||
734 | 750 | } else if (strcmp(func, "mysqli_connect") == 0) { | } else if (strcmp(func, "mysqli_connect") == 0) { |
735 | struct conn *c = va_arg(va, struct conn *); | ||
751 | struct nd_db_conn *c = va_arg(va, struct nd_db_conn *); | ||
736 | 752 | my_trace_put32(buf, &i, c->conn_str_len); | my_trace_put32(buf, &i, c->conn_str_len); |
737 | 753 | my_trace_put(buf, &i, c->conn_str, c->conn_str_len); | my_trace_put(buf, &i, c->conn_str, c->conn_str_len); |
738 | 754 | if (type == 'r') | if (type == 'r') |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
753 | 769 | struct free_result *fr = va_arg(va, struct free_result *); | struct free_result *fr = va_arg(va, struct free_result *); |
754 | 770 | my_trace_put64(buf, &i, (uint64_t) fr->res); | my_trace_put64(buf, &i, (uint64_t) fr->res); |
755 | 771 | } else if (strcmp(func, "mysqli_prepare") == 0) { | } else if (strcmp(func, "mysqli_prepare") == 0) { |
756 | struct prepare *p = va_arg(va, struct prepare *); | ||
772 | struct nd_db_stmt *p = va_arg(va, struct nd_db_stmt *); | ||
757 | 773 | my_trace_put64(buf, &i, (uint64_t) p->dbh); | my_trace_put64(buf, &i, (uint64_t) p->dbh); |
758 | 774 | my_trace_put16(buf, &i, p->q_len); | my_trace_put16(buf, &i, p->q_len); |
759 | 775 | my_trace_put(buf, &i, p->q, p->q_len); | my_trace_put(buf, &i, p->q, p->q_len); |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
770 | 786 | my_trace_put64(buf, &i, q->aff); | my_trace_put64(buf, &i, q->aff); |
771 | 787 | } | } |
772 | 788 | } else if (strcmp(func, "mysqli_real_connect") == 0) { | } else if (strcmp(func, "mysqli_real_connect") == 0) { |
773 | struct conn *c = va_arg(va, struct conn *); | ||
789 | struct nd_db_conn *c = va_arg(va, struct nd_db_conn *); | ||
774 | 790 | my_trace_put64(buf, &i, (uint64_t) c->dbh); | my_trace_put64(buf, &i, (uint64_t) c->dbh); |
775 | 791 | my_trace_put32(buf, &i, c->conn_str_len); | my_trace_put32(buf, &i, c->conn_str_len); |
776 | 792 | my_trace_put(buf, &i, c->conn_str, c->conn_str_len); | my_trace_put(buf, &i, c->conn_str, c->conn_str_len); |
777 | 793 | my_trace_put32(buf, &i, c->flags); | my_trace_put32(buf, &i, c->flags); |
778 | 794 | if (type == 'r') | if (type == 'r') |
779 | my_trace_put_bool(buf, &i, c->ret); | ||
795 | my_trace_put_bool(buf, &i, c->ok); | ||
780 | 796 | } else if (strcmp(func, "mysqli_stmt_bind_param") == 0) { | } else if (strcmp(func, "mysqli_stmt_bind_param") == 0) { |
781 | 797 | struct nd_db_bind *b = va_arg(va, struct nd_db_bind *); | struct nd_db_bind *b = va_arg(va, struct nd_db_bind *); |
782 | 798 | my_trace_put64(buf, &i, (uint64_t) b->stmt); | my_trace_put64(buf, &i, (uint64_t) b->stmt); |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
784 | 800 | my_trace_put(buf, &i, b->types, b->types_len); | my_trace_put(buf, &i, b->types, b->types_len); |
785 | 801 | if (type == 'r') | if (type == 'r') |
786 | 802 | my_trace_put_bool(buf, &i, b->ret); | my_trace_put_bool(buf, &i, b->ret); |
803 | } else if (strcmp(func, "mysqli_stmt_close") == 0) { | ||
804 | struct nd_db_stmt *e = va_arg(va, struct nd_db_stmt *); | ||
805 | my_trace_put64(buf, &i, (uint64_t) e->stmt); | ||
806 | if (type == 'r') | ||
807 | my_trace_put_bool(buf, &i, e->ret); | ||
787 | 808 | } else if (strcmp(func, "mysqli_stmt_execute") == 0) { | } else if (strcmp(func, "mysqli_stmt_execute") == 0) { |
788 | struct nd_db_execute *e = va_arg(va, struct nd_db_execute *); | ||
809 | struct nd_db_stmt *e = va_arg(va, struct nd_db_stmt *); | ||
789 | 810 | my_trace_put64(buf, &i, (uint64_t) e->stmt); | my_trace_put64(buf, &i, (uint64_t) e->stmt); |
790 | if (type == 'c') { | ||
791 | my_trace_put16(buf, &i, e->params.len); | ||
792 | for (unsigned short j = 0; j < e->params.len; j++) { | ||
793 | struct params_array_one *pa = &e->params.list[j]; | ||
794 | my_trace_put8(buf, &i, pa->type); | ||
795 | if (pa->type == ND_TYPE_LONG) { | ||
796 | my_trace_put64(buf, &i, pa->l); | ||
797 | } else if (pa->type == ND_TYPE_DOUBLE) { | ||
798 | my_trace_put_double(buf, &i, pa->d); | ||
799 | } else if (pa->type == ND_TYPE_STRING) { | ||
800 | my_trace_put16(buf, &i, pa->length); | ||
801 | my_trace_put(buf, &i, pa->str, pa->length); | ||
802 | } | ||
803 | } | ||
804 | } | ||
811 | if (type == 'c') | ||
812 | my_trace_put_params(buf, &i, &e->params, | ||
813 | ND_PARAMS_BIND_WAY_BOTH); | ||
805 | 814 | if (type == 'r') { | if (type == 'r') { |
806 | 815 | my_trace_put_bool(buf, &i, e->ret); | my_trace_put_bool(buf, &i, e->ret); |
807 | 816 | if (e->ret == 1) { | if (e->ret == 1) { |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
810 | 819 | } | } |
811 | 820 | } | } |
812 | 821 | } else if (strcmp(func, "mysqli_stmt_prepare") == 0) { | } else if (strcmp(func, "mysqli_stmt_prepare") == 0) { |
813 | struct prepare *p = va_arg(va, struct prepare *); | ||
822 | struct nd_db_stmt *p = va_arg(va, struct nd_db_stmt *); | ||
814 | 823 | my_trace_put64(buf, &i, (uint64_t) p->stmt); | my_trace_put64(buf, &i, (uint64_t) p->stmt); |
815 | 824 | my_trace_put16(buf, &i, p->q_len); | my_trace_put16(buf, &i, p->q_len); |
816 | 825 | my_trace_put(buf, &i, p->q, p->q_len); | my_trace_put(buf, &i, p->q, p->q_len); |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
835 | 844 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
836 | 845 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
837 | 846 | if (ret == -1) | if (ret == -1) |
838 | my_trace_put32(buf, &i, save_errno); | ||
847 | my_trace_put32(buf, &i, saved_errno); | ||
839 | 848 | } | } |
840 | 849 | } break; | } break; |
841 | 850 | ||
842 | 851 | case 'o': | case 'o': |
843 | if ((strcmp(func, "open") == 0) | ||
852 | if (strcmp(func, "oci_bind_by_name") == 0) { | ||
853 | struct nd_db_stmt *s = va_arg(va, struct nd_db_stmt *); | ||
854 | my_trace_put64(buf, &i, (uint64_t) s->stmt); | ||
855 | } else if (strcmp(func, "oci_close") == 0) { | ||
856 | struct nd_db_conn *c = va_arg(va, struct nd_db_conn *); | ||
857 | my_trace_put64(buf, &i, (uint64_t) c->dbh); | ||
858 | } else if (strcmp(func, "oci_execute") == 0) { | ||
859 | struct nd_db_stmt *s = va_arg(va, struct nd_db_stmt *); | ||
860 | my_trace_put64(buf, &i, (uint64_t) s->stmt); | ||
861 | my_trace_put64(buf, &i, (uint64_t) s->oci.mode); | ||
862 | if (type == 'r') | ||
863 | my_trace_put_bool(buf, &i, (uint64_t) s->ret); | ||
864 | } else if (strcmp(func, "oci_parse") == 0) { | ||
865 | struct nd_db_stmt *s = va_arg(va, struct nd_db_stmt *); | ||
866 | my_trace_put64(buf, &i, (uint64_t) s->dbh); | ||
867 | my_trace_put16(buf, &i, (uint16_t) s->q_len); | ||
868 | my_trace_put(buf, &i, s->q, s->q_len); | ||
869 | if (type == 'r') | ||
870 | my_trace_put64(buf, &i, (uint64_t) s->stmt); | ||
871 | } else if (strcmp(func, "oci_pconnect") == 0) { | ||
872 | struct nd_db_conn *c = va_arg(va, struct nd_db_conn *); | ||
873 | my_trace_put32(buf, &i, c->conn_str_len); | ||
874 | my_trace_put(buf, &i, c->conn_str, c->conn_str_len); | ||
875 | if (type == 'r') | ||
876 | my_trace_put64(buf, &i, (uint64_t) c->dbh); | ||
877 | } else if ((strcmp(func, "open") == 0) | ||
844 | 878 | || (strcmp(func, "open64") == 0) | || (strcmp(func, "open64") == 0) |
845 | 879 | || (strcmp(func, "openat") == 0)) { | || (strcmp(func, "openat") == 0)) { |
846 | 880 | if (strcmp(func, "openat") == 0) | if (strcmp(func, "openat") == 0) |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
855 | 889 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
856 | 890 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
857 | 891 | if (ret == -1) | if (ret == -1) |
858 | my_trace_put32(buf, &i, save_errno); | ||
892 | my_trace_put32(buf, &i, saved_errno); | ||
893 | } | ||
894 | } break; | ||
895 | |||
896 | case 'O': | ||
897 | if (strcmp(func, "OCIAttrSet") == 0) { | ||
898 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // h | ||
899 | my_trace_put32(buf, &i, va_arg(va, uint32_t)); // htype | ||
900 | void *attr = va_arg(va, void *); | ||
901 | uint32_t attr_size = va_arg(va, uint32_t); | ||
902 | uint32_t attr_type = va_arg(va, uint32_t); | ||
903 | if (attr_type == 23) // do not send password | ||
904 | attr_size = 0; | ||
905 | my_trace_put32(buf, &i, attr_size); | ||
906 | my_trace_put(buf, &i, attr, attr_size); | ||
907 | my_trace_put32(buf, &i, attr_type); | ||
908 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // err | ||
909 | my_trace_put32(buf, &i, va_arg(va, int32_t)); // ret | ||
910 | } else if (strcmp(func, "OCIBindByName") == 0) { | ||
911 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // stmt | ||
912 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // bind | ||
913 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // oci_error | ||
914 | const char *ph = va_arg(va, char *); | ||
915 | int ph_len = va_arg(va, int), ph_len2; | ||
916 | ph_len2 = ph_len > 0 ? ph_len : (int) strlen(ph); | ||
917 | my_trace_put32(buf, &i, ph_len2); | ||
918 | my_trace_put(buf, &i, ph, ph_len2); | ||
919 | int value_size = va_arg(va, int); | ||
920 | my_trace_put32(buf, &i, value_size); | ||
921 | my_trace_put16(buf, &i, va_arg(va, unsigned int)); // dty | ||
922 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // ind | ||
923 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, unsigned short *)); // alen | ||
924 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, unsigned short *)); // rcode | ||
925 | my_trace_put32(buf, &i, va_arg(va, unsigned int)); // maxarr_len | ||
926 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, unsigned int *)); // curelep | ||
927 | my_trace_put32(buf, &i, va_arg(va, uint32_t)); // mode | ||
928 | my_trace_put32(buf, &i, va_arg(va, int32_t)); // ret | ||
929 | } else if (strcmp(func, "OCIDefineByPos") == 0) { | ||
930 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // stmt | ||
931 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // def | ||
932 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // oci_error | ||
933 | my_trace_put32(buf, &i, va_arg(va, uint32_t)); // pos | ||
934 | my_trace_put32(buf, &i, va_arg(va, int)); // value_size | ||
935 | my_trace_put16(buf, &i, va_arg(va, unsigned int)); // dty | ||
936 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // ind | ||
937 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, unsigned short *)); // rlen | ||
938 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, unsigned short *)); // rcode | ||
939 | my_trace_put32(buf, &i, va_arg(va, uint32_t)); // mode | ||
940 | my_trace_put32(buf, &i, va_arg(va, int32_t)); // ret | ||
941 | } else if (strcmp(func, "OCIHandleAlloc") == 0) { | ||
942 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // parent | ||
943 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // dbh | ||
944 | my_trace_put32(buf, &i, va_arg(va, uint32_t)); // type | ||
945 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, size_t)); // extra_mem | ||
946 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // user_mem | ||
947 | } else if (strcmp(func, "OCIHandleFree") == 0) { | ||
948 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // hnd | ||
949 | my_trace_put32(buf, &i, va_arg(va, uint32_t)); // type | ||
950 | } else if (strcmp(func, "OCIServerAttach") == 0) { | ||
951 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // oci_server | ||
952 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // oci_error | ||
953 | char *db_link = va_arg(va, char *); | ||
954 | int32_t db_link_len = va_arg(va, int32_t), a; | ||
955 | a = db_link_len < 0 ? 0 : db_link_len; | ||
956 | my_trace_put32(buf, &i, a); | ||
957 | my_trace_put(buf, &i, db_link, a); | ||
958 | my_trace_put32(buf, &i, va_arg(va, uint32_t)); // mode | ||
959 | if (type == 'r') | ||
960 | my_trace_put32(buf, &i, va_arg(va, int32_t)); // ret | ||
961 | } else if (strcmp(func, "OCIServerDetach") == 0) { | ||
962 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // oci_server | ||
963 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // oci_error | ||
964 | my_trace_put32(buf, &i, va_arg(va, uint32_t)); // mode | ||
965 | if (type == 'r') | ||
966 | my_trace_put32(buf, &i, va_arg(va, int32_t)); // ret | ||
967 | } else if (strcmp(func, "OCIStmtExecute") == 0) { | ||
968 | if (type == 'm') { | ||
969 | uint64_t stmt = (uint64_t) va_arg(va, void *); | ||
970 | uint8_t bind_way = va_arg(va, int); | ||
971 | struct nd_params_array *pa = va_arg(va, struct nd_params_array *); | ||
972 | my_trace_put64(buf, &i, stmt); | ||
973 | my_trace_put8(buf, &i, bind_way); | ||
974 | my_trace_put_params(buf, &i, pa, bind_way); | ||
975 | if (bind_way == ND_PARAMS_BIND_WAY_IN) { | ||
976 | char *q = va_arg(va, char *); | ||
977 | unsigned short q_len = va_arg(va, unsigned int); | ||
978 | my_trace_put16(buf, &i, q_len); | ||
979 | my_trace_put(buf, &i, q, q_len); | ||
980 | } | ||
981 | } else { | ||
982 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // svc | ||
983 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // stmt | ||
984 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // err | ||
985 | my_trace_put32(buf, &i, va_arg(va, unsigned int)); // iters | ||
986 | my_trace_put32(buf, &i, va_arg(va, unsigned int)); // rowoff | ||
987 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // snap_in | ||
988 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // snap_out | ||
989 | my_trace_put32(buf, &i, va_arg(va, unsigned int)); // mode | ||
990 | if (type == 'r') | ||
991 | my_trace_put32(buf, &i, va_arg(va, int)); // ret | ||
859 | 992 | } | } |
993 | } else if (strcmp(func, "OCIStmtPrepare") == 0) { | ||
994 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // stmt | ||
995 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // oci_error | ||
996 | char *q = va_arg(va, char *); | ||
997 | uint16_t q_len = va_arg(va, uint32_t); | ||
998 | my_trace_put16(buf, &i, q_len); | ||
999 | my_trace_put(buf, &i, q, q_len); | ||
1000 | my_trace_put32(buf, &i, va_arg(va, unsigned int)); // lang | ||
1001 | my_trace_put32(buf, &i, va_arg(va, unsigned int)); // mode | ||
1002 | my_trace_put32(buf, &i, va_arg(va, int)); // ret | ||
1003 | } else if (strcmp(func, "OCITransCommit") == 0) { | ||
1004 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // svc | ||
1005 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // oci_error | ||
1006 | my_trace_put32(buf, &i, va_arg(va, unsigned int)); // flags | ||
1007 | if (type == 'r') | ||
1008 | my_trace_put32(buf, &i, va_arg(va, int)); // ret | ||
1009 | } else if (strcmp(func, "OCITransRollback") == 0) { | ||
1010 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // svc | ||
1011 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // oci_error | ||
1012 | my_trace_put32(buf, &i, va_arg(va, unsigned int)); // flags | ||
1013 | if (type == 'r') | ||
1014 | my_trace_put32(buf, &i, va_arg(va, int)); // ret | ||
1015 | } else if (strcmp(func, "OCITransStart") == 0) { | ||
1016 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // svc | ||
1017 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // oci_error | ||
1018 | my_trace_put32(buf, &i, va_arg(va, unsigned int)); // timeout | ||
1019 | my_trace_put32(buf, &i, va_arg(va, unsigned int)); // flags | ||
1020 | my_trace_put32(buf, &i, va_arg(va, int)); // ret | ||
860 | 1021 | } break; | } break; |
861 | 1022 | ||
862 | 1023 | case 'p': | case 'p': |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
874 | 1035 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
875 | 1036 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
876 | 1037 | if (ret == -1) | if (ret == -1) |
877 | my_trace_put32(buf, &i, save_errno); | ||
1038 | my_trace_put32(buf, &i, saved_errno); | ||
878 | 1039 | } | } |
879 | 1040 | } else if ((strcmp(func, "pread") == 0) | } else if ((strcmp(func, "pread") == 0) |
880 | 1041 | || (strcmp(func, "pread64") == 0)) { | || (strcmp(func, "pread64") == 0)) { |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
894 | 1055 | my_trace_put16(buf, &i, max); | my_trace_put16(buf, &i, max); |
895 | 1056 | my_trace_put(buf, &i, buf2, max); // data | my_trace_put(buf, &i, buf2, max); // data |
896 | 1057 | } else if (ret == -1) | } else if (ret == -1) |
897 | my_trace_put32(buf, &i, save_errno); | ||
1058 | my_trace_put32(buf, &i, saved_errno); | ||
898 | 1059 | } | } |
899 | 1060 | } else if (strcmp(func, "pthread_join") == 0) { | } else if (strcmp(func, "pthread_join") == 0) { |
900 | 1061 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, pthread_t)); | my_trace_put64(buf, &i, (uint64_t) va_arg(va, pthread_t)); |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
902 | 1063 | void **retval = va_arg(va, void **); | void **retval = va_arg(va, void **); |
903 | 1064 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
904 | 1065 | if (ret == -1) { | if (ret == -1) { |
905 | my_trace_put32(buf, &i, save_errno); | ||
1066 | my_trace_put32(buf, &i, saved_errno); | ||
906 | 1067 | } else { | } else { |
907 | 1068 | my_trace_put64(buf, &i, retval ? (uint64_t) *retval : 0); | my_trace_put64(buf, &i, retval ? (uint64_t) *retval : 0); |
908 | 1069 | } | } |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
915 | 1076 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
916 | 1077 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
917 | 1078 | if (ret == -1) | if (ret == -1) |
918 | my_trace_put32(buf, &i, save_errno); | ||
1079 | my_trace_put32(buf, &i, saved_errno); | ||
919 | 1080 | } else if (strcmp(func, "pthread_attr_setstacksize") == 0) { | } else if (strcmp(func, "pthread_attr_setstacksize") == 0) { |
920 | 1081 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // attr | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // attr |
921 | 1082 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, size_t)); // stack size | my_trace_put64(buf, &i, (uint64_t) va_arg(va, size_t)); // stack size |
922 | 1083 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
923 | 1084 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
924 | 1085 | if (ret == -1) | if (ret == -1) |
925 | my_trace_put32(buf, &i, save_errno); | ||
1086 | my_trace_put32(buf, &i, saved_errno); | ||
926 | 1087 | } else if (strcmp(func, "pthread_create") == 0) { | } else if (strcmp(func, "pthread_create") == 0) { |
927 | 1088 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, uint64_t)); // thread | my_trace_put64(buf, &i, (uint64_t) va_arg(va, uint64_t)); // thread |
928 | 1089 | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // attr TODO - how to encode it? | my_trace_put64(buf, &i, (uint64_t) va_arg(va, void *)); // attr TODO - how to encode it? |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
930 | 1091 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
931 | 1092 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
932 | 1093 | if (ret == -1) | if (ret == -1) |
933 | my_trace_put32(buf, &i, save_errno); | ||
1094 | my_trace_put32(buf, &i, saved_errno); | ||
934 | 1095 | } else if ((strcmp(func, "pwrite") == 0) | } else if ((strcmp(func, "pwrite") == 0) |
935 | 1096 | || (strcmp(func, "pwrite64") == 0)) { | || (strcmp(func, "pwrite64") == 0)) { |
936 | 1097 | void *buf2 = NULL; | void *buf2 = NULL; |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
949 | 1110 | ssize_t ret = va_arg(va, ssize_t); | ssize_t ret = va_arg(va, ssize_t); |
950 | 1111 | my_trace_put64(buf, &i, ret); | my_trace_put64(buf, &i, ret); |
951 | 1112 | if (ret == -1) | if (ret == -1) |
952 | my_trace_put32(buf, &i, save_errno); | ||
1113 | my_trace_put32(buf, &i, saved_errno); | ||
953 | 1114 | } | } |
954 | 1115 | } else if (strcmp(func, "pg_close") == 0) { | } else if (strcmp(func, "pg_close") == 0) { |
955 | struct conn *c = va_arg(va, struct conn *); | ||
1116 | struct nd_db_conn *c = va_arg(va, struct nd_db_conn *); | ||
956 | 1117 | my_trace_put64(buf, &i, (uint64_t) c->dbh); | my_trace_put64(buf, &i, (uint64_t) c->dbh); |
957 | 1118 | } else if ((strcmp(func, "pg_connect") == 0) | } else if ((strcmp(func, "pg_connect") == 0) |
958 | 1119 | || (strcmp(func, "pg_pconnect") == 0)) { | || (strcmp(func, "pg_pconnect") == 0)) { |
959 | struct conn *c = va_arg(va, struct conn *); | ||
1120 | struct nd_db_conn *c = va_arg(va, struct nd_db_conn *); | ||
960 | 1121 | my_trace_put32(buf, &i, c->conn_str_len); | my_trace_put32(buf, &i, c->conn_str_len); |
961 | 1122 | my_trace_put(buf, &i, c->conn_str, c->conn_str_len); | my_trace_put(buf, &i, c->conn_str, c->conn_str_len); |
962 | 1123 | if (type == 'r') | if (type == 'r') |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
973 | 1134 | my_trace_put64(buf, &i, (uint64_t) q->dbh); | my_trace_put64(buf, &i, (uint64_t) q->dbh); |
974 | 1135 | my_trace_put16(buf, &i, q->q_len); | my_trace_put16(buf, &i, q->q_len); |
975 | 1136 | my_trace_put(buf, &i, q->q, q->q_len); | my_trace_put(buf, &i, q->q, q->q_len); |
976 | if (type == 'c') { | ||
977 | my_trace_put16(buf, &i, q->params.len); | ||
978 | for (unsigned short j = 0; j < q->params.len; j++) { | ||
979 | struct params_array_one *pa = &q->params.list[j]; | ||
980 | my_trace_put8(buf, &i, pa->type); | ||
981 | if (pa->type == ND_TYPE_LONG) { | ||
982 | my_trace_put64(buf, &i, pa->l); | ||
983 | } else if (pa->type == ND_TYPE_DOUBLE) { | ||
984 | my_trace_put_double(buf, &i, pa->d); | ||
985 | } else if (pa->type == ND_TYPE_STRING) { | ||
986 | my_trace_put16(buf, &i, pa->length); | ||
987 | my_trace_put(buf, &i, pa->str, pa->length); | ||
988 | } | ||
989 | } | ||
990 | } | ||
1137 | if (type == 'c') | ||
1138 | my_trace_put_params(buf, &i, &q->params, | ||
1139 | ND_PARAMS_BIND_WAY_BOTH); | ||
991 | 1140 | if (type == 'r') { | if (type == 'r') { |
992 | 1141 | my_trace_put64(buf, &i, (uint64_t) q->res); | my_trace_put64(buf, &i, (uint64_t) q->res); |
993 | 1142 | my_trace_put64(buf, &i, q->num); | my_trace_put64(buf, &i, q->num); |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
1021 | 1170 | my_trace_put(buf, &i, buf2, max); // data | my_trace_put(buf, &i, buf2, max); // data |
1022 | 1171 | } | } |
1023 | 1172 | if (ret == -1) | if (ret == -1) |
1024 | my_trace_put32(buf, &i, save_errno); | ||
1173 | my_trace_put32(buf, &i, saved_errno); | ||
1025 | 1174 | } | } |
1026 | 1175 | } else if (strcmp(func, "recv") == 0) { | } else if (strcmp(func, "recv") == 0) { |
1027 | 1176 | void *buf2 = NULL; | void *buf2 = NULL; |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
1041 | 1190 | my_trace_put(buf, &i, buf2, max); // data | my_trace_put(buf, &i, buf2, max); // data |
1042 | 1191 | } | } |
1043 | 1192 | if (ret == -1) | if (ret == -1) |
1044 | my_trace_put32(buf, &i, save_errno); | ||
1193 | my_trace_put32(buf, &i, saved_errno); | ||
1045 | 1194 | } | } |
1195 | } else if (strcmp(func, "recvmsg") == 0) { | ||
1196 | my_trace_put32(buf, &i, va_arg(va, int)); // sock | ||
1197 | // TODO | ||
1046 | 1198 | } else if (strcmp(func, "recvfrom") == 0) { | } else if (strcmp(func, "recvfrom") == 0) { |
1047 | 1199 | my_trace_put32(buf, &i, va_arg(va, int)); // sock | my_trace_put32(buf, &i, va_arg(va, int)); // sock |
1048 | 1200 | struct sockaddr *addr = NULL; | struct sockaddr *addr = NULL; |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
1059 | 1211 | ssize_t ret = va_arg(va, ssize_t); | ssize_t ret = va_arg(va, ssize_t); |
1060 | 1212 | my_trace_put64(buf, &i, ret); | my_trace_put64(buf, &i, ret); |
1061 | 1213 | if (ret == -1) { | if (ret == -1) { |
1062 | my_trace_put32(buf, &i, save_errno); | ||
1214 | my_trace_put32(buf, &i, saved_errno); | ||
1063 | 1215 | } else if (ret > 0) { // TODO: not sure if ret is 0 if addr is filled or not | } else if (ret > 0) { // TODO: not sure if ret is 0 if addr is filled or not |
1064 | 1216 | unsigned short max = ret; | unsigned short max = ret; |
1065 | 1217 | if (max > 128) max = 128; | if (max > 128) max = 128; |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
1091 | 1243 | ssize_t ret = va_arg(va, ssize_t); | ssize_t ret = va_arg(va, ssize_t); |
1092 | 1244 | my_trace_put64(buf, &i, ret); | my_trace_put64(buf, &i, ret); |
1093 | 1245 | if (ret == -1) | if (ret == -1) |
1094 | my_trace_put32(buf, &i, save_errno); | ||
1246 | my_trace_put32(buf, &i, saved_errno); | ||
1095 | 1247 | } | } |
1096 | 1248 | } else if (strcmp(func, "sendmsg") == 0) { | } else if (strcmp(func, "sendmsg") == 0) { |
1097 | 1249 | my_trace_put32(buf, &i, va_arg(va, int)); // sock | my_trace_put32(buf, &i, va_arg(va, int)); // sock |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
1112 | 1264 | ssize_t ret = va_arg(va, ssize_t); | ssize_t ret = va_arg(va, ssize_t); |
1113 | 1265 | my_trace_put64(buf, &i, ret); | my_trace_put64(buf, &i, ret); |
1114 | 1266 | if (ret == -1) | if (ret == -1) |
1115 | my_trace_put32(buf, &i, save_errno); | ||
1267 | my_trace_put32(buf, &i, saved_errno); | ||
1116 | 1268 | } | } |
1117 | 1269 | } else if (strcmp(func, "setsockopt") == 0) { | } else if (strcmp(func, "setsockopt") == 0) { |
1118 | 1270 | my_trace_put32(buf, &i, va_arg(va, int)); // sock | my_trace_put32(buf, &i, va_arg(va, int)); // sock |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
1125 | 1277 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
1126 | 1278 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
1127 | 1279 | if (ret == -1) | if (ret == -1) |
1128 | my_trace_put32(buf, &i, save_errno); | ||
1280 | my_trace_put32(buf, &i, saved_errno); | ||
1129 | 1281 | } else if (strcmp(func, "socket") == 0) { | } else if (strcmp(func, "socket") == 0) { |
1130 | 1282 | my_trace_put32(buf, &i, va_arg(va, int)); // domain | my_trace_put32(buf, &i, va_arg(va, int)); // domain |
1131 | 1283 | my_trace_put32(buf, &i, va_arg(va, int)); // type | my_trace_put32(buf, &i, va_arg(va, int)); // type |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
1133 | 1285 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
1134 | 1286 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
1135 | 1287 | if (ret == -1) | if (ret == -1) |
1136 | my_trace_put32(buf, &i, save_errno); | ||
1288 | my_trace_put32(buf, &i, saved_errno); | ||
1137 | 1289 | } else if (strcmp(func, "sqlite3_bind_double") == 0) { | } else if (strcmp(func, "sqlite3_bind_double") == 0) { |
1138 | 1290 | my_trace_put64(buf, &i, va_arg(va, uint64_t)); // stmt | my_trace_put64(buf, &i, va_arg(va, uint64_t)); // stmt |
1139 | 1291 | my_trace_put32(buf, &i, va_arg(va, int)); // index | my_trace_put32(buf, &i, va_arg(va, int)); // index |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
1212 | 1364 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
1213 | 1365 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
1214 | 1366 | if (ret == -1) | if (ret == -1) |
1215 | my_trace_put32(buf, &i, save_errno); | ||
1367 | my_trace_put32(buf, &i, saved_errno); | ||
1216 | 1368 | } | } |
1217 | 1369 | } else if (strcmp(func, "syslog") == 0) { | } else if (strcmp(func, "syslog") == 0) { |
1218 | 1370 | my_trace_put32(buf, &i, va_arg(va, int)); // prio | my_trace_put32(buf, &i, va_arg(va, int)); // prio |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
1230 | 1382 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
1231 | 1383 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
1232 | 1384 | if (ret == -1) | if (ret == -1) |
1233 | my_trace_put32(buf, &i, save_errno); | ||
1385 | my_trace_put32(buf, &i, saved_errno); | ||
1234 | 1386 | } | } |
1235 | 1387 | } break; | } break; |
1236 | 1388 | ||
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
1244 | 1396 | int ret = va_arg(va, int); | int ret = va_arg(va, int); |
1245 | 1397 | my_trace_put32(buf, &i, ret); | my_trace_put32(buf, &i, ret); |
1246 | 1398 | if (ret == -1) | if (ret == -1) |
1247 | my_trace_put32(buf, &i, save_errno); | ||
1399 | my_trace_put32(buf, &i, saved_errno); | ||
1248 | 1400 | } | } |
1249 | 1401 | } break; | } break; |
1250 | 1402 | ||
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
1266 | 1418 | ssize_t ret = va_arg(va, ssize_t); | ssize_t ret = va_arg(va, ssize_t); |
1267 | 1419 | my_trace_put64(buf, &i, ret); | my_trace_put64(buf, &i, ret); |
1268 | 1420 | if (ret == -1) | if (ret == -1) |
1269 | my_trace_put32(buf, &i, save_errno); | ||
1421 | my_trace_put32(buf, &i, saved_errno); | ||
1270 | 1422 | } | } |
1271 | 1423 | } break; | } break; |
1272 | 1424 | } | } |
... | ... | static unsigned int my_trace_encode(unsigned char *buf, | |
1277 | 1429 | uint16_t _u16 = htobe16(i); | uint16_t _u16 = htobe16(i); |
1278 | 1430 | memcpy(buf, &_u16, 2); | memcpy(buf, &_u16, 2); |
1279 | 1431 | ||
1432 | //char dump[i * 4 + 1]; | ||
1433 | //bin2hex_ascii(dump, buf, i); | ||
1434 | //xlog(0, "%s: packed %u bytes: %s\n", __func__, i, dump); | ||
1280 | 1435 | return i; | return i; |
1281 | 1436 | } | } |
1282 | 1437 | ||
1283 | void my_trace(const char *func, const char type, ...) | ||
1438 | /* | ||
1439 | * @tf - trace flags | ||
1440 | */ | ||
1441 | void my_trace(const char *func, const char *tf, const char type, ...) | ||
1284 | 1442 | { | { |
1285 | 1443 | static __thread unsigned char out[64000]; // I had to reduce this for .NET! Stack too small! | static __thread unsigned char out[64000]; // I had to reduce this for .NET! Stack too small! |
1286 | int save_errno; | ||
1287 | 1444 | va_list va; | va_list va; |
1288 | int locked, r; | ||
1289 | |||
1290 | save_errno = errno; | ||
1445 | int r; | ||
1291 | 1446 | ||
1292 | if (nd_info_inited && nd_info->do_fill_buffer == 1) { | ||
1293 | unsigned int size, off = 0; | ||
1294 | int r = sem_wait(&nd_info->sem); // TODO: check error code | ||
1295 | nd_info->do_fill_buffer = 0; | ||
1447 | int saved_errno = errno; | ||
1448 | do { | ||
1449 | if (nd_info_inited && (nd_info->do_fill_buffer == 1)) { | ||
1450 | unsigned int size, off = 0; | ||
1451 | sem_wait(&nd_info->sem); // TODO: check error code | ||
1452 | nd_info->do_fill_buffer = 0; | ||
1453 | |||
1454 | uint32_t u32 = htobe32(nd_proc_start); | ||
1455 | nd_info->buf[off++] = 'S'; | ||
1456 | memcpy(nd_info->buf + off, &u32, 4); off += 4; | ||
1457 | |||
1458 | size = export_fd_nodes(nd_info->buf + off, | ||
1459 | sizeof(nd_info->buf) - off, fd_nodes, 32); | ||
1460 | off += size; | ||
1461 | |||
1462 | nd_info->buf_size = off; | ||
1463 | nd_info->buffer_is_filled = 1; | ||
1464 | sem_post(&nd_info->sem); // TODO: check error code | ||
1465 | } | ||
1296 | 1466 | ||
1297 | uint32_t u32 = htobe32(nd_proc_start); | ||
1298 | nd_info->buf[off++] = 'S'; | ||
1299 | memcpy(nd_info->buf + off, &u32, 4); off += 4; | ||
1467 | if (shared_inited == 0) | ||
1468 | break; | ||
1300 | 1469 | ||
1301 | size = export_fd_nodes(nd_info->buf + off, | ||
1302 | sizeof(nd_info->buf) - off, fd_nodes, 32); | ||
1303 | off += size; | ||
1470 | if (trace_enabled == 0) | ||
1471 | break; | ||
1304 | 1472 | ||
1305 | nd_info->buf_size = off; | ||
1306 | nd_info->buffer_is_filled = 1; | ||
1307 | r = sem_post(&nd_info->sem); // TODO: check error code | ||
1308 | } | ||
1473 | int locked = 0; | ||
1474 | while (1) { | ||
1475 | unsigned int ava, i; | ||
1309 | 1476 | ||
1310 | if (shared_inited == 0) | ||
1311 | return; | ||
1477 | if (shared->client_flags & ND_SHARED_ONLY_HIGH_LEVEL) { | ||
1478 | if (!strstr(tf, "i")) | ||
1479 | break; | ||
1480 | } | ||
1312 | 1481 | ||
1313 | if (trace_enabled == 0) | ||
1314 | return; | ||
1482 | xlog(200, "%s func=%s tf=[%s] type=%c trace_depth=%hu errno=%d\n", | ||
1483 | __func__, func, tf, type, trace_depth, errno); | ||
1315 | 1484 | ||
1316 | xlog(200, "%s func=%s type=%c errno=%d\n", | ||
1317 | __func__, func, type, errno); | ||
1485 | va_start(va, type); | ||
1486 | i = my_trace_encode(out, func, tf, type, saved_errno, va); | ||
1487 | va_end(va); | ||
1488 | if (i == 0) { | ||
1489 | xlog(1, "I do not know how to encode [%s][%c]!\n", func, type); | ||
1490 | break; | ||
1491 | } | ||
1492 | char dump[i * 4 + 1]; | ||
1493 | bin2hex_ascii(dump, out, i); | ||
1494 | xlog(201, " gen: %s\n", dump); | ||
1495 | |||
1496 | // TODO: use an internal buffer if we cannot take the lock and move back to 'trywait' | ||
1497 | xlog(201, " head=%u tail=%u junk=%u to_copy=%u [before lock]\n", | ||
1498 | shared->head, shared->tail, shared->junk, i); | ||
1499 | r = sem_wait(&shared->sem1); | ||
1500 | if (r == -1) { | ||
1501 | xlog(1, "sem_trywait sem1 error: %m\n"); | ||
1502 | break; | ||
1503 | } | ||
1504 | locked = 1; | ||
1505 | |||
1506 | if (shared->head < shared->tail) { | ||
1507 | // s.....head.....tail....e | ||
1508 | // head=3 tail=5: 0..h.t.7 => size8-(tail5-head3)=6 => ava = 6 | ||
1509 | ava = shared->buf_size - (shared->tail - shared->head); | ||
1510 | } else if (shared->head == shared->tail) { | ||
1511 | ava = shared->buf_size - 1; | ||
1512 | } else { // s....tail....head....e 0t...h...9 head=5 tail=1 => ava=4 | ||
1513 | ava = shared->head - shared->tail; | ||
1514 | } | ||
1515 | if (ava < i) { // TODO: add to an internal buffer | ||
1516 | xlog(1, "%s: not enough available: ava[%u] < i[%u]\n", | ||
1517 | __func__, ava, i); | ||
1518 | msgs_lost++; | ||
1519 | break; | ||
1520 | } | ||
1521 | unsigned int max = shared->buf_size - shared->tail; // size=11 tail=5 max=6: .....t..... | ||
1522 | if (max > i) { // enough space | ||
1523 | memcpy(shared->buf + shared->tail, out, i); | ||
1524 | shared->tail += i; | ||
1525 | } else { // split copy | ||
1526 | memcpy(shared->buf + shared->tail, out, max); | ||
1527 | memcpy(shared->buf, out + max, i - max); | ||
1528 | shared->tail = i - max; // size=13 head=2 tail=5 i=9 max=8: ..h..t....... => 89h..01234567 => tail=1 | ||
1529 | } | ||
1318 | 1530 | ||
1319 | locked = 0; | ||
1320 | do { | ||
1321 | unsigned int ava, i; | ||
1531 | if (msgs_lost == 0) | ||
1532 | break; | ||
1322 | 1533 | ||
1323 | va_start(va, type); | ||
1324 | i = my_trace_encode(out, func, type, save_errno, va); | ||
1325 | va_end(va); | ||
1326 | if (i == 0) { | ||
1327 | xlog(1, "I do not know how to encode [%s][%c]!\n", func, type); | ||
1534 | // TODO: inject here '-msgs_lost' message and loop | ||
1535 | // TODO: maybe insert it as a flag in every message? | ||
1536 | // TODO: or just append it to the current message | ||
1328 | 1537 | break; | break; |
1329 | 1538 | } | } |
1330 | 1539 | ||
1331 | char dump[i * 4 + 1]; | ||
1332 | bin2hex_ascii(dump, out, i); | ||
1333 | xlog(201, " gen: %s\n", dump); | ||
1540 | if (locked) { | ||
1541 | r = sem_post(&shared->sem1); // was sem2 | ||
1542 | if (r == -1) | ||
1543 | xlog(1, "sem_post sem1 error: %m\n"); | ||
1334 | 1544 | ||
1335 | // TODO: use an internal buffer if we cannot take the lock and move back to 'trywait' | ||
1336 | xlog(201, " head=%u tail=%u to_copy=%u [start]\n", | ||
1337 | shared->head, shared->tail, i); | ||
1338 | r = sem_wait(&shared->sem1); | ||
1339 | if (r == -1) { | ||
1340 | xlog(1, "sem_trywait sem1 error: %m\n"); | ||
1341 | break; | ||
1545 | xlog(201, " head=%u tail=%u [after unlock]\n", | ||
1546 | shared->head, shared->tail); | ||
1342 | 1547 | } | } |
1343 | locked = 1; | ||
1344 | |||
1345 | if (shared->head < shared->tail) { | ||
1346 | // s.....head.....tail....e | ||
1347 | // head=3 tail=5: 0..h.t.7 => size8-(tail5-head3)=6 => ava = 6 | ||
1348 | ava = shared->buf_size - (shared->tail - shared->head); | ||
1349 | } else if (shared->head == shared->tail) { | ||
1350 | ava = shared->buf_size - 1; | ||
1351 | } else { // s....tail....head....e 0t...h...9 head=5 tail=1 => ava=4 | ||
1352 | ava = shared->head - shared->tail; | ||
1353 | } | ||
1354 | if (ava < i) { | ||
1355 | xlog(1, "%s: not enough available: ava[%u] < i[%u]\n", | ||
1356 | __func__, ava, i); | ||
1357 | shared->msgs_lost++; // TODO: add to an internal buffer | ||
1358 | break; | ||
1359 | } | ||
1360 | unsigned int max = shared->buf_size - shared->tail; // size=11 tail=5 max=6: .....t..... | ||
1361 | if (max > i) { // enough space | ||
1362 | memcpy(shared->buf + shared->tail, out, i); | ||
1363 | shared->tail += i; | ||
1364 | } else { // split copy | ||
1365 | memcpy(shared->buf + shared->tail, out, max); | ||
1366 | memcpy(shared->buf, out + max, i - max); | ||
1367 | shared->tail = i - max; // size=13 head=2 tail=5 i=9 max=8: ..h..t....... => 89h..01234567 => tail=1 | ||
1368 | } | ||
1369 | } while (0); | ||
1370 | |||
1371 | if (locked) { | ||
1372 | r = sem_post(&shared->sem1); // was sem2 | ||
1373 | if (r == -1) | ||
1374 | xlog(1, "sem_post sem1 error: %m\n"); | ||
1375 | |||
1376 | xlog(201, " head=%u tail=%u [got lock]\n", | ||
1377 | shared->head, shared->tail); | ||
1378 | } | ||
1379 | 1548 | ||
1380 | if (type == 'c') | ||
1381 | trace_depth++; | ||
1382 | else if (type == 'r') | ||
1383 | trace_depth--; | ||
1549 | if (type == 'c') | ||
1550 | trace_depth++; | ||
1551 | else if (type == 'r') | ||
1552 | trace_depth--; | ||
1553 | } while (0); | ||
1384 | 1554 | ||
1385 | errno = save_errno; | ||
1555 | errno = saved_errno; | ||
1386 | 1556 | } | } |
1387 | 1557 | ||
1388 | 1558 | static void my_on_exit(int ret, void *junk) | static void my_on_exit(int ret, void *junk) |
1389 | 1559 | { | { |
1390 | 1560 | xlog(100, "my_on_exit ret=%d junk=%p!\n", ret, junk); | xlog(100, "my_on_exit ret=%d junk=%p!\n", ret, junk); |
1391 | my_trace("-stop", 'R', ret); | ||
1561 | my_trace("-stop", "i", 'R', ret); | ||
1392 | 1562 | ninedogs_process_core(NINEDOGS_CORE_STOP, &ret); | ninedogs_process_core(NINEDOGS_CORE_STOP, &ret); |
1393 | 1563 | } | } |
1394 | 1564 | ||
... | ... | void _exit(int status) | |
1397 | 1567 | { | { |
1398 | 1568 | //write(1, "_exit\n", 6); | //write(1, "_exit\n", 6); |
1399 | 1569 | xlog(1, "my _exit status=%d!\n", status); | xlog(1, "my _exit status=%d!\n", status); |
1400 | my_trace("-stop", 'R', status); | ||
1570 | my_trace("-stop", "i", 'R', status); | ||
1401 | 1571 | old__exit(status); | old__exit(status); |
1402 | 1572 | } | } |
1403 | 1573 | #endif | #endif |
... | ... | static void my_segv(int sig) | |
1417 | 1587 | for (int j = 0; j < r; j++) | for (int j = 0; j < r; j++) |
1418 | 1588 | xlog(0, " %s\n", a[j]); | xlog(0, " %s\n", a[j]); |
1419 | 1589 | } | } |
1420 | my_trace("-segv", 'R', a, r); | ||
1590 | my_trace("-segv", "i", 'R', a, r); | ||
1421 | 1591 | ||
1422 | 1592 | exit(1); | exit(1); |
1423 | 1593 | } | } |
... | ... | static void ninedogs_child(void) | |
1484 | 1654 | __attribute__((destructor)) void ninedogs_fini(void) | __attribute__((destructor)) void ninedogs_fini(void) |
1485 | 1655 | { | { |
1486 | 1656 | xlog(20, "%s\n", __func__); | xlog(20, "%s\n", __func__); |
1487 | //my_trace("-dest", "r"); | ||
1657 | //my_trace("-dest", "i", 'R'); | ||
1488 | 1658 | ||
1489 | 1659 | if (shared_inited) { | if (shared_inited) { |
1490 | 1660 | char name[32]; | char name[32]; |
... | ... | __attribute__((constructor)) void ninedogs_init(void) | |
1529 | 1699 | if (ninedogs_inited == 1) | if (ninedogs_inited == 1) |
1530 | 1700 | return; | return; |
1531 | 1701 | ||
1702 | // We need to do that here, else we will be called again | ||
1703 | ninedogs_inited = 1; | ||
1704 | |||
1532 | 1705 | nd_proc_start = time(NULL); | nd_proc_start = time(NULL); |
1533 | 1706 | ||
1534 | 1707 | //write(1, "ninedogs: init start\n", 21); | //write(1, "ninedogs: init start\n", 21); |
... | ... | __attribute__((constructor)) void ninedogs_init(void) | |
1578 | 1751 | ||
1579 | 1752 | log_file = getenv("FORCE_NET_LOG"); | log_file = getenv("FORCE_NET_LOG"); |
1580 | 1753 | if (log_file != NULL) | if (log_file != NULL) |
1581 | Log = open(log_file, O_WRONLY | O_APPEND, 0700); | ||
1754 | Log = old_open(log_file, O_WRONLY | O_APPEND, 0700); | ||
1582 | 1755 | else | else |
1583 | 1756 | Log = dup(2); // TODO | Log = dup(2); // TODO |
1584 | 1757 | ||
... | ... | __attribute__((constructor)) void ninedogs_init(void) | |
1783 | 1956 | ||
1784 | 1957 | old_fstatat = old_dlsym(RTLD_NEXT, "fstatat"); | old_fstatat = old_dlsym(RTLD_NEXT, "fstatat"); |
1785 | 1958 | if (old_fstatat == NULL) { | if (old_fstatat == NULL) { |
1786 | xlog(0, " cannot resolve 'fstatat'!\n"); | ||
1787 | exit(1); | ||
1959 | xlog(1, " cannot resolve 'fstatat'!\n"); | ||
1960 | //exit(1); | ||
1788 | 1961 | } | } |
1789 | 1962 | ||
1790 | 1963 | old_fstatat64 = old_dlsym(RTLD_NEXT, "fstatat64"); | old_fstatat64 = old_dlsym(RTLD_NEXT, "fstatat64"); |
1791 | 1964 | if (old_fstatat64 == NULL) { | if (old_fstatat64 == NULL) { |
1792 | xlog(0, " cannot resolve 'fstatat64'!\n"); | ||
1793 | exit(1); | ||
1965 | xlog(1, " cannot resolve 'fstatat64'!\n"); | ||
1966 | //exit(1); | ||
1794 | 1967 | } | } |
1795 | 1968 | ||
1796 | 1969 | old_fork = old_dlsym(RTLD_NEXT, "fork"); | old_fork = old_dlsym(RTLD_NEXT, "fork"); |
... | ... | __attribute__((constructor)) void ninedogs_init(void) | |
1799 | 1972 | exit(1); | exit(1); |
1800 | 1973 | } | } |
1801 | 1974 | ||
1975 | old_shm_open = old_dlsym(RTLD_NEXT, "shm_open"); | ||
1976 | if (old_shm_open == NULL) { | ||
1977 | xlog(0, " cannot resolve 'shm_open'!\n"); | ||
1978 | exit(1); | ||
1979 | } | ||
1980 | |||
1802 | 1981 | ||
1803 | 1982 | x = getenv("NINEDOGS_VERBOSE"); | x = getenv("NINEDOGS_VERBOSE"); |
1804 | 1983 | if (x != NULL) | if (x != NULL) |
... | ... | __attribute__((constructor)) void ninedogs_init(void) | |
1811 | 1990 | ||
1812 | 1991 | // Preparing the nd-trace support | // Preparing the nd-trace support |
1813 | 1992 | do { | do { |
1993 | if (shared_inited == 1) | ||
1994 | break; | ||
1995 | |||
1996 | xlog(1, "Initializing shared memory for pid %u...\n", getpid()); | ||
1997 | |||
1814 | 1998 | char name[32]; | char name[32]; |
1815 | 1999 | snprintf(name, sizeof(name), "/ninedogs-%d", getpid()); | snprintf(name, sizeof(name), "/ninedogs-%d", getpid()); |
1816 | int shm = shm_open(name, O_RDWR | O_CREAT | O_EXCL, | ||
2000 | int shm = old_shm_open(name, O_RDWR | O_CREAT | O_EXCL, | ||
1817 | 2001 | S_IRUSR | S_IWUSR); | S_IRUSR | S_IWUSR); |
1818 | 2002 | if (shm == -1) { | if (shm == -1) { |
1819 | xlog(0, "Cannot create shm: %m\n"); | ||
2003 | xlog(0, "Cannot create shm [%s]: %m\n", name); | ||
1820 | 2004 | break; | break; |
1821 | 2005 | } | } |
1822 | 2006 | ||
... | ... | __attribute__((constructor)) void ninedogs_init(void) | |
1833 | 2017 | } | } |
1834 | 2018 | xlog(200, "%s: tracing mmap=%p\n", __func__, shared); | xlog(200, "%s: tracing mmap=%p\n", __func__, shared); |
1835 | 2019 | ||
2020 | if (shared->inited == 1) { | ||
2021 | xlog(1, "Shared was already initialized!\n"); | ||
2022 | break; | ||
2023 | } | ||
2024 | |||
1836 | 2025 | if (sem_init(&shared->sem1, 1, 0 /* locked */) == -1) { | if (sem_init(&shared->sem1, 1, 0 /* locked */) == -1) { |
1837 | 2026 | xlog(0, "Cannot do sem_init sem1: %m\n"); | xlog(0, "Cannot do sem_init sem1: %m\n"); |
1838 | 2027 | break; | break; |
... | ... | __attribute__((constructor)) void ninedogs_init(void) | |
1840 | 2029 | ||
1841 | 2030 | shared->version = SHARED_VERSION; | shared->version = SHARED_VERSION; |
1842 | 2031 | shared->buf_size = sizeof(shared->buf); | shared->buf_size = sizeof(shared->buf); |
1843 | shared->msgs_lost = 0; | ||
1844 | // We want force from start start the wrap around | ||
2032 | shared->junk = 0; | ||
2033 | // We want force from start the wrap around | ||
1845 | 2034 | shared->tail = shared->head = shared->buf_size - 1; | shared->tail = shared->head = shared->buf_size - 1; |
2035 | shared->client_flags = 0; | ||
2036 | shared->inited = 1; | ||
1846 | 2037 | ||
1847 | 2038 | if (sem_post(&shared->sem1) == -1) { | if (sem_post(&shared->sem1) == -1) { |
1848 | 2039 | xlog(0, "Cannot do sem_post sem1: %m\n"); | xlog(0, "Cannot do sem_post sem1: %m\n"); |
... | ... | __attribute__((constructor)) void ninedogs_init(void) | |
1854 | 2045 | ||
1855 | 2046 | // Preparing the nd-info support | // Preparing the nd-info support |
1856 | 2047 | do { | do { |
2048 | if (nd_info_inited == 1) | ||
2049 | break; | ||
2050 | |||
1857 | 2051 | char name[48]; | char name[48]; |
1858 | 2052 | snprintf(name, sizeof(name), "/ninedogs-info-%d", getpid()); | snprintf(name, sizeof(name), "/ninedogs-info-%d", getpid()); |
1859 | int shm = shm_open(name, O_RDWR | O_CREAT | O_EXCL, | ||
2053 | int shm = old_shm_open(name, O_RDWR | O_CREAT | O_EXCL, | ||
1860 | 2054 | S_IRUSR | S_IWUSR); | S_IRUSR | S_IWUSR); |
1861 | 2055 | if (shm == -1) { | if (shm == -1) { |
1862 | xlog(0, "Cannot create shm: %m\n"); | ||
2056 | xlog(0, "Cannot create shm [%s]: %m\n", name); | ||
1863 | 2057 | break; | break; |
1864 | 2058 | } | } |
1865 | 2059 | ||
... | ... | __attribute__((constructor)) void ninedogs_init(void) | |
1893 | 2087 | nd_info_inited = 1; | nd_info_inited = 1; |
1894 | 2088 | } while (0); | } while (0); |
1895 | 2089 | ||
1896 | ninedogs_inited = 1; | ||
2090 | //ninedogs_inited = 1; - done above | ||
1897 | 2091 | //xlog(1, " init ended.\n"); | //xlog(1, " init ended.\n"); |
1898 | 2092 | //write(1, "ninedogs: init done\n", 20); | //write(1, "ninedogs: init done\n", 20); |
1899 | 2093 | ||
... | ... | __attribute__((constructor)) void ninedogs_init(void) | |
1903 | 2097 | x = getenv("JAVA_TOOL_OPTIONS"); | x = getenv("JAVA_TOOL_OPTIONS"); |
1904 | 2098 | if (!x) | if (!x) |
1905 | 2099 | x = ""; | x = ""; |
1906 | snprintf(env, sizeof(env), | ||
1907 | "-javaagent:/usr/share/ninedogs/ninedogs-agent.jar %s", x); | ||
1908 | setenv("JAVA_TOOL_OPTIONS", env, 1); | ||
2100 | else | ||
2101 | xlog(40, "old JAVA_TOOL_OPTIONS: [%s]\n", x); | ||
2102 | if (!strstr(x, "ninedogs-agent.jar")) { | ||
2103 | snprintf(env, sizeof(env), | ||
2104 | "-javaagent:/usr/share/ninedogs/ninedogs-agent.jar %s", x); | ||
2105 | setenv("JAVA_TOOL_OPTIONS", env, 1); | ||
2106 | } | ||
1909 | 2107 | ||
1910 | 2108 | /* .NET stuff */ | /* .NET stuff */ |
1911 | 2109 | /* | /* |
... | ... | int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) | |
2071 | 2269 | xlog(100, "bind(sockfd=%d)\n", sockfd); | xlog(100, "bind(sockfd=%d)\n", sockfd); |
2072 | 2270 | ||
2073 | 2271 | int ret = old_bind(sockfd, addr, addrlen); | int ret = old_bind(sockfd, addr, addrlen); |
2074 | my_trace(__func__, 'R', sockfd, addr, addrlen, ret); | ||
2272 | my_trace(__func__, "", 'R', sockfd, addr, addrlen, ret); | ||
2075 | 2273 | ||
2076 | 2274 | if (ret == 0) { | if (ret == 0) { |
2077 | 2275 | struct fd_node *q = fd_search(sockfd); | struct fd_node *q = fd_search(sockfd); |
... | ... | int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) | |
2087 | 2285 | int setsockopt(int sockfd, int level, int optname, const void *optval, | int setsockopt(int sockfd, int level, int optname, const void *optval, |
2088 | 2286 | socklen_t optlen) | socklen_t optlen) |
2089 | 2287 | { | { |
2288 | if (!old_setsockopt) | ||
2289 | old_setsockopt = ninedogs_dlsym("setsockopt"); | ||
2290 | |||
2090 | 2291 | int ret = old_setsockopt(sockfd, level, optname, optval, optlen); | int ret = old_setsockopt(sockfd, level, optname, optval, optlen); |
2091 | my_trace(__func__, 'R', sockfd, level, optname, optlen, optval, ret); | ||
2292 | my_trace(__func__, "", 'R', sockfd, level, optname, optlen, optval, ret); | ||
2092 | 2293 | ||
2093 | 2294 | return ret; | return ret; |
2094 | 2295 | } | } |
2095 | 2296 | ||
2096 | 2297 | int socket(int domain, int type, int protocol) | int socket(int domain, int type, int protocol) |
2097 | 2298 | { | { |
2299 | if (!old_socket) | ||
2300 | old_socket = ninedogs_dlsym("socket"); | ||
2301 | |||
2098 | 2302 | char sprotocol[16]; | char sprotocol[16]; |
2099 | 2303 | nd_decode_socket_protocol(sprotocol, sizeof(sprotocol), protocol); | nd_decode_socket_protocol(sprotocol, sizeof(sprotocol), protocol); |
2100 | 2304 | xlog(100, "socket(domain=%s[%d], type=%s, protocol=%s)\n", | xlog(100, "socket(domain=%s[%d], type=%s, protocol=%s)\n", |
2101 | 2305 | sdomain(domain), domain, stype(type), sprotocol); | sdomain(domain), domain, stype(type), sprotocol); |
2102 | 2306 | ||
2103 | 2307 | int sockfd = old_socket(domain, type, protocol); | int sockfd = old_socket(domain, type, protocol); |
2104 | my_trace(__func__, 'R', domain, type, protocol, sockfd); | ||
2308 | my_trace(__func__, "", 'R', domain, type, protocol, sockfd); | ||
2105 | 2309 | ||
2106 | 2310 | struct fd_node *q = fd_add(sockfd); | struct fd_node *q = fd_add(sockfd); |
2107 | 2311 | if (q) { | if (q) { |
... | ... | int close(int fd) | |
2123 | 2327 | ||
2124 | 2328 | fd_del(fd); | fd_del(fd); |
2125 | 2329 | ||
2126 | my_trace(__func__, 'c', fd); | ||
2330 | my_trace(__func__, "", 'c', fd); | ||
2127 | 2331 | int ret = old_close(fd); | int ret = old_close(fd); |
2128 | my_trace(__func__, 'r', fd, ret); | ||
2332 | my_trace(__func__, "", 'r', fd, ret); | ||
2129 | 2333 | ||
2130 | 2334 | return ret; | return ret; |
2131 | 2335 | } | } |
... | ... | static void write_common_post(struct fd_node *q, ssize_t ret) | |
2144 | 2348 | ||
2145 | 2349 | ssize_t write(int fd, const void *buf, size_t count) | ssize_t write(int fd, const void *buf, size_t count) |
2146 | 2350 | { | { |
2351 | if (!old_write) | ||
2352 | old_write = ninedogs_dlsym("write"); | ||
2353 | |||
2147 | 2354 | struct fd_node *q = fd_search(fd); | struct fd_node *q = fd_search(fd); |
2148 | 2355 | if (q) { | if (q) { |
2149 | 2356 | if (q->type == FD_NODE_DEV_NINEDOGS) { | if (q->type == FD_NODE_DEV_NINEDOGS) { |
... | ... | ssize_t write(int fd, const void *buf, size_t count) | |
2157 | 2364 | ||
2158 | 2365 | dump(200, "write", buf, count); | dump(200, "write", buf, count); |
2159 | 2366 | ||
2160 | my_trace(__func__, 'c', fd, buf, count); | ||
2367 | my_trace(__func__, "", 'c', fd, buf, count); | ||
2161 | 2368 | ssize_t ret = old_write(fd, buf, count); | ssize_t ret = old_write(fd, buf, count); |
2162 | my_trace(__func__, 'r', fd, count, ret); | ||
2369 | my_trace(__func__, "", 'r', fd, count, ret); | ||
2163 | 2370 | ||
2164 | 2371 | write_common_post(q, ret); | write_common_post(q, ret); |
2165 | 2372 | if (q && (ret > 0)) | if (q && (ret > 0)) |
... | ... | ssize_t write(int fd, const void *buf, size_t count) | |
2170 | 2377 | ||
2171 | 2378 | 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) |
2172 | 2379 | { | { |
2380 | if (!old_send) | ||
2381 | old_send = ninedogs_dlsym("send"); | ||
2382 | |||
2173 | 2383 | xlog(110, "%s(sockfd=%d, buf, len=%zu, flags=0x%x)\n", | xlog(110, "%s(sockfd=%d, buf, len=%zu, flags=0x%x)\n", |
2174 | 2384 | __func__, sockfd, len, flags); | __func__, sockfd, len, flags); |
2175 | 2385 | ||
2176 | 2386 | struct fd_node *q = fd_search(sockfd); | struct fd_node *q = fd_search(sockfd); |
2177 | 2387 | ||
2178 | my_trace(__func__, 'c', sockfd, buf, len, flags); | ||
2388 | my_trace(__func__, "", 'c', sockfd, buf, len, flags); | ||
2179 | 2389 | ssize_t ret = old_send(sockfd, buf, len, flags); | ssize_t ret = old_send(sockfd, buf, len, flags); |
2180 | my_trace(__func__, 'r', sockfd, len, flags, ret); | ||
2390 | my_trace(__func__, "", 'r', sockfd, len, flags, ret); | ||
2181 | 2391 | ||
2182 | 2392 | write_common_post(q, ret); | write_common_post(q, ret); |
2183 | 2393 | ||
... | ... | ssize_t send(int sockfd, const void *buf, size_t len, int flags) | |
2187 | 2397 | 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, |
2188 | 2398 | const struct sockaddr *dest_addr, socklen_t addrlen) | const struct sockaddr *dest_addr, socklen_t addrlen) |
2189 | 2399 | { | { |
2400 | if (!old_sendto) | ||
2401 | old_sendto = ninedogs_dlsym("sendto"); | ||
2402 | |||
2190 | 2403 | xlog(110, "sendto(sockfd, %d, buf, len=%zu, flags=0x%x, ...)\n", | xlog(110, "sendto(sockfd, %d, buf, len=%zu, flags=0x%x, ...)\n", |
2191 | 2404 | sockfd, len, flags); | sockfd, len, flags); |
2192 | 2405 | ||
2193 | 2406 | struct fd_node *q = fd_search(sockfd); | struct fd_node *q = fd_search(sockfd); |
2194 | 2407 | ||
2195 | my_trace(__func__, 'c', sockfd, buf, len, flags, dest_addr, addrlen); | ||
2408 | my_trace(__func__, "", 'c', sockfd, buf, len, flags, dest_addr, addrlen); | ||
2196 | 2409 | ssize_t ret = old_sendto(sockfd, buf, len, flags, dest_addr, addrlen); | ssize_t ret = old_sendto(sockfd, buf, len, flags, dest_addr, addrlen); |
2197 | my_trace(__func__, 'r', sockfd, len, flags, ret); | ||
2410 | my_trace(__func__, "", 'r', sockfd, len, flags, ret); | ||
2198 | 2411 | ||
2199 | 2412 | write_common_post(q, ret); | write_common_post(q, ret); |
2200 | 2413 | ||
... | ... | ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, | |
2206 | 2419 | */ | */ |
2207 | 2420 | ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) | ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) |
2208 | 2421 | { | { |
2422 | if (!old_sendmsg) | ||
2423 | old_sendmsg = ninedogs_dlsym("sendmsg"); | ||
2424 | |||
2209 | 2425 | xlog(100, "sendmsg(sockfd=%d, ..., flags=0x%x)\n", | xlog(100, "sendmsg(sockfd=%d, ..., flags=0x%x)\n", |
2210 | 2426 | sockfd, flags); | sockfd, flags); |
2211 | 2427 | ||
... | ... | ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) | |
2215 | 2431 | for (unsigned i = 0; i < msg->msg_iovlen; i++) | for (unsigned i = 0; i < msg->msg_iovlen; i++) |
2216 | 2432 | 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); |
2217 | 2433 | ||
2218 | my_trace(__func__, 'c', sockfd, msg, flags); | ||
2434 | my_trace(__func__, "", 'c', sockfd, msg, flags); | ||
2219 | 2435 | ssize_t ret = old_sendmsg(sockfd, msg, flags); | ssize_t ret = old_sendmsg(sockfd, msg, flags); |
2220 | my_trace(__func__, 'r', sockfd, flags, ret); | ||
2436 | my_trace(__func__, "", 'r', sockfd, flags, ret); | ||
2221 | 2437 | ||
2222 | 2438 | write_common_post(q, ret); | write_common_post(q, ret); |
2223 | 2439 | ||
... | ... | ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) | |
2228 | 2444 | ssize_t (*old_lseek)(int fd, off_t off, int whence); | ssize_t (*old_lseek)(int fd, off_t off, int whence); |
2229 | 2445 | ssize_t lseek(int fd, off_t off, int whence) | ssize_t lseek(int fd, off_t off, int whence) |
2230 | 2446 | { | { |
2447 | if (!old_lseek) | ||
2448 | old_lseek = ninedogs_dlsym("lseek"); | ||
2449 | |||
2231 | 2450 | xlog(110, "%s(fd=%d, off=%zu, whence=%d)\n", __func__, fd, off, whence); | xlog(110, "%s(fd=%d, off=%zu, whence=%d)\n", __func__, fd, off, whence); |
2232 | 2451 | ||
2233 | 2452 | if (!old_lseek) | if (!old_lseek) |
... | ... | ssize_t lseek(int fd, off_t off, int whence) | |
2235 | 2454 | ||
2236 | 2455 | struct fd_node *q = fd_search(fd); | struct fd_node *q = fd_search(fd); |
2237 | 2456 | ||
2238 | my_trace(__func__, 'c', fd, off, whence); | ||
2457 | my_trace(__func__, "", 'c', fd, off, whence); | ||
2239 | 2458 | ssize_t ret = old_lseek(fd, off, whence); | ssize_t ret = old_lseek(fd, off, whence); |
2240 | my_trace(__func__, 'r', fd, off, whence, ret); | ||
2459 | my_trace(__func__, "", 'r', fd, off, whence, ret); | ||
2241 | 2460 | ||
2242 | 2461 | if (q && (ret > 0)) | if (q && (ret > 0)) |
2243 | 2462 | q->file.off = ret; | q->file.off = ret; |
... | ... | static void read_common_post(struct fd_node *q, ssize_t ret) | |
2261 | 2480 | ssize_t (*old_read)(int fd, void *buf, size_t count); | ssize_t (*old_read)(int fd, void *buf, size_t count); |
2262 | 2481 | ssize_t read(int fd, void *buf, size_t count) | ssize_t read(int fd, void *buf, size_t count) |
2263 | 2482 | { | { |
2483 | if (!old_read) | ||
2484 | old_read = ninedogs_dlsym("read"); | ||
2485 | |||
2264 | 2486 | xlog(110, "%s(fd=%d, buf, count=%zu)\n", __func__, fd, count); | xlog(110, "%s(fd=%d, buf, count=%zu)\n", __func__, fd, count); |
2265 | 2487 | ||
2266 | 2488 | if (!old_read) | if (!old_read) |
... | ... | ssize_t read(int fd, void *buf, size_t count) | |
2268 | 2490 | ||
2269 | 2491 | struct fd_node *q = fd_search(fd); | struct fd_node *q = fd_search(fd); |
2270 | 2492 | ||
2271 | my_trace(__func__, 'c', fd, count); | ||
2493 | my_trace(__func__, "", 'c', fd, count); | ||
2272 | 2494 | ssize_t ret = old_read(fd, buf, count); | ssize_t ret = old_read(fd, buf, count); |
2273 | my_trace(__func__, 'r', fd, buf, count, ret); | ||
2495 | my_trace(__func__, "", 'r', fd, buf, count, ret); | ||
2274 | 2496 | ||
2275 | 2497 | read_common_post(q, ret); | read_common_post(q, ret); |
2276 | 2498 | if (q && (ret > 0)) | if (q && (ret > 0)) |
... | ... | ssize_t read(int fd, void *buf, size_t count) | |
2281 | 2503 | ||
2282 | 2504 | ssize_t recv(int sockfd, void *buf, size_t len, int flags) | ssize_t recv(int sockfd, void *buf, size_t len, int flags) |
2283 | 2505 | { | { |
2506 | if (!old_recv) | ||
2507 | old_recv = ninedogs_dlsym("recv"); | ||
2508 | |||
2284 | 2509 | xlog(110, "%s(sockfd=%d, buf, len=%zu, flags=0x%x)\n", | xlog(110, "%s(sockfd=%d, buf, len=%zu, flags=0x%x)\n", |
2285 | 2510 | __func__, sockfd, len, flags); | __func__, sockfd, len, flags); |
2286 | 2511 | ||
2287 | 2512 | struct fd_node *q = fd_search(sockfd); | struct fd_node *q = fd_search(sockfd); |
2288 | 2513 | ||
2289 | my_trace(__func__, 'c', sockfd, len, flags); | ||
2514 | my_trace(__func__, "", 'c', sockfd, len, flags); | ||
2290 | 2515 | ssize_t ret = old_recv(sockfd, buf, len, flags); | ssize_t ret = old_recv(sockfd, buf, len, flags); |
2291 | my_trace(__func__, 'r', sockfd, buf, len, flags, ret); | ||
2516 | my_trace(__func__, "", 'r', sockfd, buf, len, flags, ret); | ||
2292 | 2517 | ||
2293 | 2518 | read_common_post(q, ret); | read_common_post(q, ret); |
2294 | 2519 | ||
... | ... | ssize_t recv(int sockfd, void *buf, size_t len, int flags) | |
2297 | 2522 | ||
2298 | 2523 | ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags) | ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags) |
2299 | 2524 | { | { |
2525 | if (!old_recvmsg) | ||
2526 | old_recvmsg = ninedogs_dlsym("recvmsg"); | ||
2527 | |||
2300 | 2528 | xlog(110, "%s(sockfd=%d, msg, flags=0x%x)\n", | xlog(110, "%s(sockfd=%d, msg, flags=0x%x)\n", |
2301 | 2529 | __func__, sockfd, flags); | __func__, sockfd, flags); |
2302 | 2530 | ||
2303 | 2531 | struct fd_node *q = fd_search(sockfd); | struct fd_node *q = fd_search(sockfd); |
2304 | 2532 | ||
2305 | my_trace(__func__, 'c', sockfd, msg, flags); | ||
2533 | my_trace(__func__, "", 'c', sockfd, msg, flags); | ||
2306 | 2534 | ssize_t ret = old_recvmsg(sockfd, msg, flags); | ssize_t ret = old_recvmsg(sockfd, msg, flags); |
2307 | my_trace(__func__, 'r', sockfd, msg, flags, ret); | ||
2535 | my_trace(__func__, "", 'r', sockfd, msg, flags, ret); | ||
2308 | 2536 | ||
2309 | 2537 | #if 0 | #if 0 |
2310 | 2538 | ssize_t rest = ret; | ssize_t rest = ret; |
... | ... | ssize_t recvfrom(int sockfd, void *restrict buf, size_t len, int flags, | |
2325 | 2553 | { | { |
2326 | 2554 | struct fd_node *q = fd_search(sockfd); | struct fd_node *q = fd_search(sockfd); |
2327 | 2555 | ||
2328 | my_trace(__func__, 'c', sockfd, len, addrlen ? *addrlen : 0, flags); | ||
2556 | if (!old_recvfrom) | ||
2557 | old_recvfrom = ninedogs_dlsym("recvfrom"); | ||
2558 | |||
2559 | my_trace(__func__, "", 'c', sockfd, len, addrlen ? *addrlen : 0, flags); | ||
2329 | 2560 | ssize_t ret = old_recvfrom(sockfd, buf, len, flags, src_addr, addrlen); | ssize_t ret = old_recvfrom(sockfd, buf, len, flags, src_addr, addrlen); |
2330 | my_trace(__func__, 'r', sockfd, len, src_addr, addrlen ? *addrlen : 0, flags, ret, buf); | ||
2561 | my_trace(__func__, "", 'r', sockfd, len, src_addr, addrlen ? *addrlen : 0, flags, ret, buf); | ||
2331 | 2562 | ||
2332 | 2563 | read_common_post(q, ret); | read_common_post(q, ret); |
2333 | 2564 | ||
... | ... | static void accept_common(int sock, int new) | |
2350 | 2581 | b->type = FD_NODE_SOCKET; | b->type = FD_NODE_SOCKET; |
2351 | 2582 | b->socket.backlog = 0; | b->socket.backlog = 0; |
2352 | 2583 | b->socket.accepts = 0; | b->socket.accepts = 0; |
2584 | b->socket.accept_fd = sock + 1; // 0 is considered invalid | ||
2353 | 2585 | } | } |
2354 | 2586 | ||
2355 | 2587 | if (a && b) { | if (a && b) { |
... | ... | static void accept_common(int sock, int new) | |
2364 | 2596 | */ | */ |
2365 | 2597 | int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) | int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) |
2366 | 2598 | { | { |
2599 | if (!old_accept) | ||
2600 | old_accept = ninedogs_dlsym("accept"); | ||
2601 | |||
2367 | 2602 | xlog(100, "accept(sockfd=%d, ...)\n", sockfd); | xlog(100, "accept(sockfd=%d, ...)\n", sockfd); |
2368 | 2603 | ||
2369 | my_trace(__func__, 'c', sockfd, addrlen ? *addrlen : 0); | ||
2604 | my_trace(__func__, "", 'c', sockfd, addrlen ? *addrlen : 0); | ||
2370 | 2605 | int new_sock = old_accept(sockfd, addr, addrlen); | int new_sock = old_accept(sockfd, addr, addrlen); |
2371 | my_trace(__func__, 'r', sockfd, addr, addrlen ? *addrlen : 0, new_sock); | ||
2606 | my_trace(__func__, "", 'r', sockfd, addr, addrlen ? *addrlen : 0, new_sock); | ||
2372 | 2607 | accept_common(sockfd, new_sock); | accept_common(sockfd, new_sock); |
2373 | 2608 | return new_sock; | return new_sock; |
2374 | 2609 | } | } |
... | ... | int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) | |
2378 | 2613 | */ | */ |
2379 | 2614 | int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) | int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) |
2380 | 2615 | { | { |
2616 | if (!old_accept4) | ||
2617 | old_accept4 = ninedogs_dlsym("accept4"); | ||
2618 | |||
2381 | 2619 | xlog(100, "accept4(sockfd=%d, ...flags=0x%x)\n", sockfd, flags); | xlog(100, "accept4(sockfd=%d, ...flags=0x%x)\n", sockfd, flags); |
2382 | 2620 | ||
2383 | my_trace(__func__, 'c', sockfd, addrlen ? *addrlen : 0, flags); | ||
2621 | my_trace(__func__, "", 'c', sockfd, addrlen ? *addrlen : 0, flags); | ||
2384 | 2622 | int new_sock = old_accept4(sockfd, addr, addrlen, flags); | int new_sock = old_accept4(sockfd, addr, addrlen, flags); |
2385 | my_trace(__func__, 'r', sockfd, addr, addrlen ? *addrlen : 0, | ||
2623 | my_trace(__func__, "", 'r', sockfd, addr, addrlen ? *addrlen : 0, | ||
2386 | 2624 | flags, new_sock); | flags, new_sock); |
2387 | 2625 | accept_common(sockfd, new_sock); | accept_common(sockfd, new_sock); |
2388 | 2626 | return new_sock; | return new_sock; |
... | ... | int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) | |
2396 | 2634 | ||
2397 | 2635 | xlog(100, "connect(sockfd=%d)\n", sockfd); | xlog(100, "connect(sockfd=%d)\n", sockfd); |
2398 | 2636 | ||
2399 | my_trace(__func__, 'c', sockfd, addr, addrlen); | ||
2637 | my_trace(__func__, "", 'c', sockfd, addr, addrlen); | ||
2400 | 2638 | int ret = old_connect(sockfd, addr, addrlen); | int ret = old_connect(sockfd, addr, addrlen); |
2401 | my_trace(__func__, 'r', sockfd, ret); | ||
2639 | my_trace(__func__, "", 'r', sockfd, ret); | ||
2402 | 2640 | if ((ret == 0) || (errno == EAGAIN) || (errno == EINPROGRESS)) { | if ((ret == 0) || (errno == EAGAIN) || (errno == EINPROGRESS)) { |
2403 | 2641 | struct fd_node *q = fd_search(sockfd); | struct fd_node *q = fd_search(sockfd); |
2404 | 2642 | if (q) { | if (q) { |
... | ... | int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) | |
2414 | 2652 | ||
2415 | 2653 | int poll(struct pollfd *fds, nfds_t nfds, int timeout) | int poll(struct pollfd *fds, nfds_t nfds, int timeout) |
2416 | 2654 | { | { |
2655 | if (!old_poll) | ||
2656 | old_poll = ninedogs_dlsym("poll"); | ||
2657 | |||
2417 | 2658 | xlog(100, "poll(fds, %d, %d)\n", nfds, timeout); | xlog(100, "poll(fds, %d, %d)\n", nfds, timeout); |
2418 | 2659 | ||
2419 | my_trace(__func__, 'c', fds, nfds, timeout); | ||
2660 | my_trace(__func__, "", 'c', fds, nfds, timeout); | ||
2420 | 2661 | int ret = old_poll(fds, nfds, timeout); | int ret = old_poll(fds, nfds, timeout); |
2421 | my_trace(__func__, 'r', fds, nfds, timeout, ret); | ||
2662 | my_trace(__func__, "", 'r', fds, nfds, timeout, ret); | ||
2422 | 2663 | ||
2423 | 2664 | return ret; | return ret; |
2424 | 2665 | } | } |
2425 | 2666 | ||
2426 | 2667 | struct hostent *gethostbyname(const char *name) | struct hostent *gethostbyname(const char *name) |
2427 | 2668 | { | { |
2669 | if (!old_gethostbyname) | ||
2670 | old_gethostbyname = ninedogs_dlsym("gethostbyname"); | ||
2671 | |||
2428 | 2672 | xlog(100, "gethostbyname(%s)\n", name); | xlog(100, "gethostbyname(%s)\n", name); |
2429 | 2673 | ||
2430 | my_trace(__func__, 'c', name); | ||
2674 | my_trace(__func__, "i", 'c', name); | ||
2431 | 2675 | struct hostent *ret = old_gethostbyname(name); | struct hostent *ret = old_gethostbyname(name); |
2432 | my_trace(__func__, 'r', name, ret); | ||
2676 | my_trace(__func__, "i", 'r', name, ret); | ||
2433 | 2677 | ||
2434 | 2678 | return ret; | return ret; |
2435 | 2679 | } | } |
... | ... | int gethostbyname_r(const char *name, struct hostent *restrict ret, | |
2447 | 2691 | old_gethostbyname_r = ninedogs_dlsym("gethostbyname_r"); | old_gethostbyname_r = ninedogs_dlsym("gethostbyname_r"); |
2448 | 2692 | ||
2449 | 2693 | xlog(100, "gethostbyname_r('%s', buflen=%zu)\n", name, buflen); | xlog(100, "gethostbyname_r('%s', buflen=%zu)\n", name, buflen); |
2450 | my_trace(__func__, 'c', name); | ||
2694 | my_trace(__func__, "i", 'c', name); | ||
2451 | 2695 | int r = old_gethostbyname_r(name, ret, buf, buflen, result, h_errnop); | int r = old_gethostbyname_r(name, ret, buf, buflen, result, h_errnop); |
2452 | 2696 | 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", |
2453 | 2697 | name, buflen, r, *h_errnop, result ? *result : NULL); | name, buflen, r, *h_errnop, result ? *result : NULL); |
2454 | my_trace(__func__, 'r', name, r, *h_errnop, *result); | ||
2698 | my_trace(__func__, "i", 'r', name, r, *h_errnop, *result); | ||
2455 | 2699 | ||
2456 | 2700 | return r; | return r; |
2457 | 2701 | } | } |
... | ... | int gethostbyname_r(const char *name, struct hostent *restrict ret, | |
2459 | 2703 | int getaddrinfo(const char *restrict node, const char *restrict service, | int getaddrinfo(const char *restrict node, const char *restrict service, |
2460 | 2704 | const struct addrinfo *restrict hints, struct addrinfo **restrict res) | const struct addrinfo *restrict hints, struct addrinfo **restrict res) |
2461 | 2705 | { | { |
2706 | if (!old_getaddrinfo) | ||
2707 | old_getaddrinfo = ninedogs_dlsym("getaddrinfo"); | ||
2708 | |||
2462 | 2709 | xlog(100, "getaddrinfo(node=%s, service=%s, hints=0x%x)\n", | xlog(100, "getaddrinfo(node=%s, service=%s, hints=0x%x)\n", |
2463 | 2710 | node, service, hints ? hints : 0); | node, service, hints ? hints : 0); |
2464 | 2711 | ||
2465 | my_trace(__func__, 'c', node, service, hints); | ||
2712 | my_trace(__func__, "", 'c', node, service, hints); | ||
2466 | 2713 | int ret = old_getaddrinfo(node, service, hints, res); | int ret = old_getaddrinfo(node, service, hints, res); |
2467 | my_trace(__func__, 'r', node, service, hints, res, ret); | ||
2714 | my_trace(__func__, "", 'r', node, service, hints, res, ret); | ||
2468 | 2715 | ||
2469 | 2716 | return ret; | return ret; |
2470 | 2717 | } | } |
... | ... | int pthread_create(pthread_t *restrict thread, | |
2473 | 2720 | const pthread_attr_t *restrict attr, void *(*start_routine)(void *), | const pthread_attr_t *restrict attr, void *(*start_routine)(void *), |
2474 | 2721 | void *restrict arg) | void *restrict arg) |
2475 | 2722 | { | { |
2723 | if (!old_pthread_create) | ||
2724 | old_pthread_create = ninedogs_dlsym("pthread_create"); | ||
2725 | |||
2476 | 2726 | //xlog(2, "%s\n", __func__); | //xlog(2, "%s\n", __func__); |
2477 | 2727 | int ret = old_pthread_create(thread, attr, start_routine, arg); | int ret = old_pthread_create(thread, attr, start_routine, arg); |
2478 | my_trace(__func__, 'R', ret == 0 ? *thread : 0, attr, arg, ret); | ||
2728 | my_trace(__func__, "", 'R', ret == 0 ? *thread : 0, attr, arg, ret); | ||
2479 | 2729 | ||
2480 | 2730 | return ret; | return ret; |
2481 | 2731 | } | } |
... | ... | int pthread_join(pthread_t thread, void **retval) | |
2488 | 2738 | ||
2489 | 2739 | //xlog(2, "pthread_join\n"); | //xlog(2, "pthread_join\n"); |
2490 | 2740 | int ret = old_pthread_join(thread, retval); | int ret = old_pthread_join(thread, retval); |
2491 | my_trace(__func__, 'R', thread, ret, ret == 0 ? retval : NULL); | ||
2741 | my_trace(__func__, "", 'R', thread, ret, ret == 0 ? retval : NULL); | ||
2492 | 2742 | ||
2493 | 2743 | return ret; | return ret; |
2494 | 2744 | } | } |
... | ... | int pthread_attr_init(pthread_attr_t *attr) | |
2501 | 2751 | ||
2502 | 2752 | xlog(2, "%s\n", __func__); | xlog(2, "%s\n", __func__); |
2503 | 2753 | int ret = old_pthread_attr_init(attr); | int ret = old_pthread_attr_init(attr); |
2504 | my_trace(__func__, 'R', attr, ret); | ||
2754 | my_trace(__func__, "", 'R', attr, ret); | ||
2505 | 2755 | ||
2506 | 2756 | return ret; | return ret; |
2507 | 2757 | } | } |
... | ... | int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) | |
2512 | 2762 | if (!old_pthread_attr_setstacksize) | if (!old_pthread_attr_setstacksize) |
2513 | 2763 | old_pthread_attr_setstacksize = ninedogs_dlsym("pthread_attr_setstacksize"); | old_pthread_attr_setstacksize = ninedogs_dlsym("pthread_attr_setstacksize"); |
2514 | 2764 | ||
2515 | xlog(2, "pthread_attr_setstacksize(%p, %zu)\n", attr, stacksize); | ||
2765 | xlog(50, "pthread_attr_setstacksize(%p, %zu)\n", attr, stacksize); | ||
2516 | 2766 | ||
2517 | 2767 | int ret = old_pthread_attr_setstacksize(attr, stacksize); | int ret = old_pthread_attr_setstacksize(attr, stacksize); |
2518 | my_trace(__func__, 'R', attr, stacksize, ret); | ||
2768 | my_trace(__func__, "", 'R', attr, stacksize, ret); | ||
2519 | 2769 | ||
2520 | 2770 | return ret; | return ret; |
2521 | 2771 | } | } |
... | ... | int pthread_setname_np(pthread_t thread, const char *name) | |
2526 | 2776 | if (!old_pthread_setname_np) | if (!old_pthread_setname_np) |
2527 | 2777 | old_pthread_setname_np = ninedogs_dlsym("pthread_setname_np"); | old_pthread_setname_np = ninedogs_dlsym("pthread_setname_np"); |
2528 | 2778 | ||
2529 | xlog(2, "pthread_setname_np(%lu, %s)\n", thread, name); | ||
2779 | xlog(50, "pthread_setname_np(%lu, %s)\n", thread, name); | ||
2530 | 2780 | int ret = old_pthread_setname_np(thread, name); | int ret = old_pthread_setname_np(thread, name); |
2531 | my_trace(__func__, 'R', thread, name, ret); | ||
2781 | my_trace(__func__, "", 'R', thread, name, ret); | ||
2532 | 2782 | ||
2533 | 2783 | return ret; | return ret; |
2534 | 2784 | } | } |
... | ... | int pthread_setname_np(pthread_t thread, const char *name) | |
2537 | 2787 | int getsockopt(int sockfd, int level, int optname, void *restrict optval, | int getsockopt(int sockfd, int level, int optname, void *restrict optval, |
2538 | 2788 | socklen_t *restrict optlen) | socklen_t *restrict optlen) |
2539 | 2789 | { | { |
2790 | if (!old_getsockopt) | ||
2791 | old_getsockopt = ninedogs_dlsym("getsockopt"); | ||
2792 | |||
2540 | 2793 | xlog(50, "%s(%d, %d, %d, %p, %u)\n", | xlog(50, "%s(%d, %d, %d, %p, %u)\n", |
2541 | 2794 | __func__, sockfd, level, optname, optval, optlen); | __func__, sockfd, level, optname, optval, optlen); |
2542 | 2795 | ||
... | ... | int getsockopt(int sockfd, int level, int optname, void *restrict optval, | |
2560 | 2813 | break; | break; |
2561 | 2814 | } | } |
2562 | 2815 | ||
2563 | my_trace(__func__, 'R', sockfd, level, optname, optval, *optlen, r); | ||
2816 | my_trace(__func__, "", 'R', sockfd, level, optname, optval, *optlen, r); | ||
2564 | 2817 | ||
2565 | 2818 | return r; | return r; |
2566 | 2819 | } | } |
2567 | 2820 | ||
2568 | 2821 | int execve(const char *pathname, char *const argv[], char *const envp[]) | int execve(const char *pathname, char *const argv[], char *const envp[]) |
2569 | 2822 | { | { |
2823 | if (!old_execve) | ||
2824 | old_execve = ninedogs_dlsym("execve"); | ||
2825 | |||
2570 | 2826 | xlog(2, "%s(%s, ...)\n", __func__, pathname); | xlog(2, "%s(%s, ...)\n", __func__, pathname); |
2571 | 2827 | ||
2572 | my_trace(__func__, 'c', pathname, argv, envp); | ||
2828 | my_trace(__func__, "", 'c', pathname, argv, envp); | ||
2573 | 2829 | int ret = old_execve(pathname, argv, envp); | int ret = old_execve(pathname, argv, envp); |
2574 | my_trace(__func__, 'r', pathname, argv, envp, ret); | ||
2830 | my_trace(__func__, "", 'r', pathname, argv, envp, ret); | ||
2575 | 2831 | ||
2576 | 2832 | xlog(2, " ret=%d\n", ret); | xlog(2, " ret=%d\n", ret); |
2577 | 2833 | ||
... | ... | static int open_common_pre(const char *pathname) | |
2594 | 2850 | } | } |
2595 | 2851 | ||
2596 | 2852 | q->type = FD_NODE_DEV_NINEDOGS; | q->type = FD_NODE_DEV_NINEDOGS; |
2597 | xlog(10, "ninedogs special /dev file opened fd=%d\n", ret); | ||
2853 | xlog(50, "ninedogs special /dev file opened fd=%d\n", ret); | ||
2598 | 2854 | ||
2599 | 2855 | return ret; | return ret; |
2600 | 2856 | } | } |
... | ... | int memfd_create(const char *name, unsigned int flags) | |
2624 | 2880 | old_memfd_create = ninedogs_dlsym("memfd_create"); | old_memfd_create = ninedogs_dlsym("memfd_create"); |
2625 | 2881 | ||
2626 | 2882 | xlog(100, "%s(%s, 0x%x)\n", __func__, name, flags); | xlog(100, "%s(%s, 0x%x)\n", __func__, name, flags); |
2627 | my_trace(__func__, 'c', name, flags); | ||
2883 | my_trace(__func__, "", 'c', name, flags); | ||
2628 | 2884 | int ret = old_memfd_create(name, flags); | int ret = old_memfd_create(name, flags); |
2629 | my_trace(__func__, 'r', name, flags, ret); | ||
2885 | my_trace(__func__, "", 'r', name, flags, ret); | ||
2630 | 2886 | open_common_post(FD_NODE_MEMFD, name, flags, 0, ret); | open_common_post(FD_NODE_MEMFD, name, flags, 0, ret); |
2631 | 2887 | xlog(101, " ret=%d\n", ret); | xlog(101, " ret=%d\n", ret); |
2632 | 2888 | ||
... | ... | int timerfd_create(int clockid, int flags) | |
2640 | 2896 | old_timerfd_create = ninedogs_dlsym("timerfd_create"); | old_timerfd_create = ninedogs_dlsym("timerfd_create"); |
2641 | 2897 | ||
2642 | 2898 | xlog(100, "%s(%d, 0x%x)\n", __func__, clockid, flags); | xlog(100, "%s(%d, 0x%x)\n", __func__, clockid, flags); |
2643 | my_trace(__func__, 'c', clockid, flags); | ||
2899 | my_trace(__func__, "", 'c', clockid, flags); | ||
2644 | 2900 | int ret = old_timerfd_create(clockid, flags); | int ret = old_timerfd_create(clockid, flags); |
2645 | my_trace(__func__, 'r', clockid, flags, ret); | ||
2901 | my_trace(__func__, "", 'r', clockid, flags, ret); | ||
2646 | 2902 | open_common_post(FD_NODE_TIMERFD, "", flags, clockid, ret); | open_common_post(FD_NODE_TIMERFD, "", flags, clockid, ret); |
2647 | 2903 | xlog(101, " ret=%d\n", ret); | xlog(101, " ret=%d\n", ret); |
2648 | 2904 | ||
... | ... | int open(const char *pathname, int flags, ...) | |
2654 | 2910 | mode_t mode = 0; | mode_t mode = 0; |
2655 | 2911 | va_list va; | va_list va; |
2656 | 2912 | ||
2913 | // We are getting the addresss with getenv | ||
2914 | if (!old_open) | ||
2915 | ninedogs_init(); | ||
2916 | |||
2657 | 2917 | if (__OPEN_NEEDS_MODE(flags)) { | if (__OPEN_NEEDS_MODE(flags)) { |
2658 | 2918 | va_start(va, flags); | va_start(va, flags); |
2659 | 2919 | mode = va_arg(va, mode_t); | mode = va_arg(va, mode_t); |
... | ... | int open(const char *pathname, int flags, ...) | |
2665 | 2925 | return ret; | return ret; |
2666 | 2926 | ||
2667 | 2927 | xlog(100, "%s(%s, 0x%x, 0x%x)\n", __func__, pathname, flags, mode); | xlog(100, "%s(%s, 0x%x, 0x%x)\n", __func__, pathname, flags, mode); |
2668 | my_trace(__func__, 'c', pathname, flags, mode); | ||
2928 | my_trace(__func__, "", 'c', pathname, flags, mode); | ||
2669 | 2929 | ret = old_open(pathname, flags, mode); | ret = old_open(pathname, flags, mode); |
2670 | my_trace(__func__, 'r', pathname, flags, mode, ret); | ||
2930 | my_trace(__func__, "", 'r', pathname, flags, mode, ret); | ||
2671 | 2931 | open_common_post(FD_NODE_FILE, pathname, flags, mode, ret); | open_common_post(FD_NODE_FILE, pathname, flags, mode, ret); |
2672 | 2932 | xlog(101, " ret=%d\n", ret); | xlog(101, " ret=%d\n", ret); |
2673 | 2933 | ||
... | ... | int open(const char *pathname, int flags, ...) | |
2676 | 2936 | ||
2677 | 2937 | int open64(const char *pathname, int flags, ...) | int open64(const char *pathname, int flags, ...) |
2678 | 2938 | { | { |
2939 | if (!old_open64) | ||
2940 | old_open64 = ninedogs_dlsym("open64"); | ||
2941 | |||
2679 | 2942 | mode_t mode = 0; | mode_t mode = 0; |
2680 | 2943 | va_list va; | va_list va; |
2681 | 2944 | ||
... | ... | int open64(const char *pathname, int flags, ...) | |
2690 | 2953 | return ret; | return ret; |
2691 | 2954 | ||
2692 | 2955 | xlog(100, "%s(%s, %d, %d)\n", __func__, pathname, flags, mode); | xlog(100, "%s(%s, %d, %d)\n", __func__, pathname, flags, mode); |
2693 | my_trace(__func__, 'c', pathname, flags, mode); | ||
2956 | my_trace(__func__, "", 'c', pathname, flags, mode); | ||
2694 | 2957 | ret = old_open64(pathname, flags, mode); | ret = old_open64(pathname, flags, mode); |
2695 | my_trace(__func__, 'r', pathname, flags, mode, ret); | ||
2958 | my_trace(__func__, "", 'r', pathname, flags, mode, ret); | ||
2696 | 2959 | open_common_post(FD_NODE_FILE, pathname, flags, mode, ret); | open_common_post(FD_NODE_FILE, pathname, flags, mode, ret); |
2697 | 2960 | xlog(101, " ret=%d\n", ret); | xlog(101, " ret=%d\n", ret); |
2698 | 2961 | ||
... | ... | int open64(const char *pathname, int flags, ...) | |
2701 | 2964 | ||
2702 | 2965 | int openat(int dirfd, const char *pathname, int flags, ...) | int openat(int dirfd, const char *pathname, int flags, ...) |
2703 | 2966 | { | { |
2967 | if (!old_openat) | ||
2968 | old_openat = ninedogs_dlsym("openat"); | ||
2969 | |||
2704 | 2970 | mode_t mode = 0; | mode_t mode = 0; |
2705 | 2971 | va_list va; | va_list va; |
2706 | 2972 | ||
... | ... | int openat(int dirfd, const char *pathname, int flags, ...) | |
2715 | 2981 | return ret; | return ret; |
2716 | 2982 | ||
2717 | 2983 | xlog(100, "%s(%d, %s, %d, %d)\n", __func__, dirfd, pathname, flags, mode); | xlog(100, "%s(%d, %s, %d, %d)\n", __func__, dirfd, pathname, flags, mode); |
2718 | my_trace(__func__, 'c', dirfd, pathname, flags, mode); | ||
2984 | my_trace(__func__, "", 'c', dirfd, pathname, flags, mode); | ||
2719 | 2985 | ret = old_openat(dirfd, pathname, flags, mode); | ret = old_openat(dirfd, pathname, flags, mode); |
2720 | my_trace(__func__, 'r', dirfd, pathname, flags, mode, ret); | ||
2986 | my_trace(__func__, "", 'r', dirfd, pathname, flags, mode, ret); | ||
2721 | 2987 | open_common_post(FD_NODE_FILE, pathname, flags, mode, ret); | open_common_post(FD_NODE_FILE, pathname, flags, mode, ret); |
2722 | 2988 | xlog(101, " ret=%d\n", ret); | xlog(101, " ret=%d\n", ret); |
2723 | 2989 | ||
... | ... | int openat(int dirfd, const char *pathname, int flags, ...) | |
2729 | 2995 | static int my_stat(const char *restrict pathname, struct stat *restrict statbuf) | static int my_stat(const char *restrict pathname, struct stat *restrict statbuf) |
2730 | 2996 | { | { |
2731 | 2997 | xlog(20, "%s(%s, %p)\n", __func__, pathname, statbuf); | xlog(20, "%s(%s, %p)\n", __func__, pathname, statbuf); |
2732 | my_trace(__func__, 'c', pathname, statbuf); | ||
2998 | my_trace(__func__, "", 'c', pathname, statbuf); | ||
2733 | 2999 | int ret = old_stat(pathname, statbuf); | int ret = old_stat(pathname, statbuf); |
2734 | my_trace(__func__, 'r', pathname, statbuf, ret); | ||
3000 | my_trace(__func__, "", 'r', pathname, statbuf, ret); | ||
2735 | 3001 | xlog(25, " ret=%d\n", ret); | xlog(25, " ret=%d\n", ret); |
2736 | 3002 | ||
2737 | 3003 | return ret; | return ret; |
... | ... | void *dlopen(const char *filename, int flags) | |
2767 | 3033 | if (!old_dlopen) | if (!old_dlopen) |
2768 | 3034 | return NULL; | return NULL; |
2769 | 3035 | ||
2770 | my_trace(__func__, 'c', filename, flags); | ||
3036 | my_trace(__func__, "", 'c', filename, flags); | ||
2771 | 3037 | void *ret = old_dlopen(filename, flags); | void *ret = old_dlopen(filename, flags); |
2772 | my_trace(__func__, 'r', filename, flags, ret); | ||
3038 | my_trace(__func__, "", 'r', filename, flags, ret); | ||
2773 | 3039 | if (filename && ret) { | if (filename && ret) { |
2774 | 3040 | // TODO: should I add only 'flags=GLOBAL' entries? | // TODO: should I add only 'flags=GLOBAL' entries? |
2775 | 3041 | unsigned found = 0, first_free = DLOPEN_MAX_ENTRIES; | unsigned found = 0, first_free = DLOPEN_MAX_ENTRIES; |
... | ... | int dlclose(void *h) | |
2826 | 3092 | } | } |
2827 | 3093 | } | } |
2828 | 3094 | ||
2829 | my_trace(__func__, 'R', h, ret); | ||
3095 | my_trace(__func__, "", 'R', h, ret); | ||
2830 | 3096 | ||
2831 | 3097 | return ret; | return ret; |
2832 | 3098 | } | } |
... | ... | int dlclose(void *h) | |
2836 | 3102 | */ | */ |
2837 | 3103 | void *ninedogs_dlsym(const char *sym) | void *ninedogs_dlsym(const char *sym) |
2838 | 3104 | { | { |
3105 | // We are getting the addresss with getenv | ||
3106 | ninedogs_init(); | ||
3107 | |||
2839 | 3108 | xlog(100, "%s: sym [%s]\n", __func__, sym); | xlog(100, "%s: sym [%s]\n", __func__, sym); |
2840 | 3109 | ||
2841 | 3110 | void *ret = old_dlsym(RTLD_NEXT, sym); | void *ret = old_dlsym(RTLD_NEXT, sym); |
... | ... | void *ninedogs_dlsym(const char *sym) | |
2859 | 3128 | ||
2860 | 3129 | ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) | ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) |
2861 | 3130 | { | { |
2862 | // Seems we cannot use ninedogs_dlsym here! | ||
3131 | // We are getting the addresss with getenv | ||
2863 | 3132 | if (!old_getrandom) | if (!old_getrandom) |
2864 | 3133 | ninedogs_init(); | ninedogs_init(); |
2865 | 3134 | ||
2866 | 3135 | xlog(100, "%s(%p, %zu, 0x%x) [old_getrandom=%p]\n", | xlog(100, "%s(%p, %zu, 0x%x) [old_getrandom=%p]\n", |
2867 | 3136 | __func__, buf, buflen, flags, old_getrandom); | __func__, buf, buflen, flags, old_getrandom); |
2868 | 3137 | ||
2869 | my_trace(__func__, 'c', buflen, flags); | ||
3138 | my_trace(__func__, "", 'c', buflen, flags); | ||
2870 | 3139 | ssize_t ret = old_getrandom(buf, buflen, flags); | ssize_t ret = old_getrandom(buf, buflen, flags); |
2871 | my_trace(__func__, 'r', buf, buflen, flags, ret); | ||
3140 | my_trace(__func__, "", 'r', buf, buflen, flags, ret); | ||
2872 | 3141 | ||
2873 | 3142 | return ret; | return ret; |
2874 | 3143 | } | } |
... | ... | int nanosleep(const struct timespec *req, struct timespec *rem) | |
2881 | 3150 | xlog(100, "%s(%ld.%09ld, %p)\n", | xlog(100, "%s(%ld.%09ld, %p)\n", |
2882 | 3151 | __func__, req->tv_sec, req->tv_nsec, rem); | __func__, req->tv_sec, req->tv_nsec, rem); |
2883 | 3152 | ||
2884 | my_trace(__func__, 'c', req); | ||
3153 | my_trace(__func__, "", 'c', req); | ||
2885 | 3154 | int ret = old_nanosleep(req, rem); | int ret = old_nanosleep(req, rem); |
2886 | my_trace(__func__, 'r', req, rem, ret); | ||
3155 | my_trace(__func__, "", 'r', req, rem, ret); | ||
2887 | 3156 | ||
2888 | 3157 | return ret; | return ret; |
2889 | 3158 | } | } |
... | ... | int unlink(const char *pathname) | |
2895 | 3164 | ||
2896 | 3165 | xlog(100, "%s(%s)\n", __func__, pathname); | xlog(100, "%s(%s)\n", __func__, pathname); |
2897 | 3166 | ||
2898 | my_trace(__func__, 'c', pathname); | ||
3167 | my_trace(__func__, "", 'c', pathname); | ||
2899 | 3168 | int ret = old_unlink(pathname); | int ret = old_unlink(pathname); |
2900 | my_trace(__func__, 'r', pathname, ret); | ||
3169 | my_trace(__func__, "", 'r', pathname, ret); | ||
2901 | 3170 | ||
2902 | 3171 | return ret; | return ret; |
2903 | 3172 | } | } |
... | ... | int listen(int sock, int backlog) | |
2910 | 3179 | xlog(100, "%s(%d, %d)\n", __func__, sock, backlog); | xlog(100, "%s(%d, %d)\n", __func__, sock, backlog); |
2911 | 3180 | ||
2912 | 3181 | int ret = old_listen(sock, backlog); | int ret = old_listen(sock, backlog); |
2913 | my_trace(__func__, 'R', sock, backlog, ret); | ||
3182 | my_trace(__func__, "", 'R', sock, backlog, ret); | ||
2914 | 3183 | ||
2915 | 3184 | struct fd_node *q = fd_search(sock); | struct fd_node *q = fd_search(sock); |
2916 | 3185 | if (q) | if (q) |
... | ... | void syslog(int priority, const char *format, ...) | |
2934 | 3203 | va_end(va); | va_end(va); |
2935 | 3204 | ||
2936 | 3205 | old_syslog(priority, buf); | old_syslog(priority, buf); |
2937 | my_trace(__func__, 'R', priority, buf); | ||
3206 | my_trace(__func__, "", 'R', priority, buf); | ||
2938 | 3207 | } | } |
2939 | 3208 | ||
2940 | 3209 | int fstatat(int dirfd, const char *restrict pathname, | int fstatat(int dirfd, const char *restrict pathname, |
... | ... | int fstatat(int dirfd, const char *restrict pathname, | |
2945 | 3214 | ||
2946 | 3215 | 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); |
2947 | 3216 | ||
2948 | my_trace(__func__, 'c', dirfd, pathname, flags); | ||
3217 | my_trace(__func__, "", 'c', dirfd, pathname, flags); | ||
2949 | 3218 | int ret = old_fstatat(dirfd, pathname, statbuf, flags); | int ret = old_fstatat(dirfd, pathname, statbuf, flags); |
2950 | my_trace(__func__, 'r', dirfd, pathname, statbuf, flags, ret); | ||
3219 | my_trace(__func__, "", 'r', dirfd, pathname, statbuf, flags, ret); | ||
2951 | 3220 | ||
2952 | 3221 | return ret; | return ret; |
2953 | 3222 | } | } |
... | ... | int fstatat64(int dirfd, const char *restrict pathname, | |
2961 | 3230 | xlog(100, "%s(%d, %s, %p, 0x%x)\n", | xlog(100, "%s(%d, %s, %p, 0x%x)\n", |
2962 | 3231 | __func__, dirfd, pathname, statbuf, flags); | __func__, dirfd, pathname, statbuf, flags); |
2963 | 3232 | ||
2964 | my_trace(__func__, 'c', dirfd, pathname, flags); | ||
3233 | my_trace(__func__, "", 'c', dirfd, pathname, flags); | ||
2965 | 3234 | int ret = old_fstatat64(dirfd, pathname, statbuf, flags); | int ret = old_fstatat64(dirfd, pathname, statbuf, flags); |
2966 | my_trace(__func__, 'r', dirfd, pathname, statbuf, flags, ret); | ||
3235 | my_trace(__func__, "", 'r', dirfd, pathname, statbuf, flags, ret); | ||
2967 | 3236 | ||
2968 | 3237 | return ret; | return ret; |
2969 | 3238 | } | } |
2970 | 3239 | ||
2971 | 3240 | int stat(const char *restrict pathname, struct stat *restrict statbuf) | int stat(const char *restrict pathname, struct stat *restrict statbuf) |
2972 | 3241 | { | { |
3242 | // We are getting the addresss with getenv | ||
2973 | 3243 | if (!old_stat) | if (!old_stat) |
2974 | old_stat = ninedogs_dlsym("stat"); | ||
3244 | ninedogs_init(); | ||
2975 | 3245 | ||
2976 | 3246 | xlog(100, "%s(%s, %p)\n", __func__, pathname, statbuf); | xlog(100, "%s(%s, %p)\n", __func__, pathname, statbuf); |
2977 | 3247 | ||
2978 | my_trace(__func__, 'c', pathname); | ||
3248 | my_trace(__func__, "", 'c', pathname); | ||
2979 | 3249 | int ret = old_stat(pathname, statbuf); | int ret = old_stat(pathname, statbuf); |
2980 | my_trace(__func__, 'r', pathname, statbuf, ret); | ||
3250 | my_trace(__func__, "", 'r', pathname, statbuf, ret); | ||
2981 | 3251 | ||
2982 | 3252 | return ret; | return ret; |
2983 | 3253 | } | } |
... | ... | int fork(void) | |
2990 | 3260 | xlog(100, "%s()\n", __func__); | xlog(100, "%s()\n", __func__); |
2991 | 3261 | ||
2992 | 3262 | int ret = old_fork(); | int ret = old_fork(); |
2993 | my_trace(__func__, 'R', ret); | ||
3263 | my_trace(__func__, "", 'R', ret); | ||
3264 | |||
3265 | return ret; | ||
3266 | } | ||
3267 | |||
3268 | int shm_open(const char *name, int oflag, mode_t mode) | ||
3269 | { | ||
3270 | if (!old_shm_open) | ||
3271 | old_shm_open = ninedogs_dlsym("shm_open"); | ||
3272 | |||
3273 | my_trace(__func__, "", 'r', name, oflag, mode); | ||
3274 | int ret = old_shm_open(name, oflag, mode); | ||
3275 | my_trace(__func__, "", 'r', name, oflag, mode, ret); | ||
2994 | 3276 | ||
2995 | 3277 | return ret; | return ret; |
2996 | 3278 | } | } |
... | ... | int fsync(int fd) | |
3002 | 3284 | old_fsync = ninedogs_dlsym("fsync"); | old_fsync = ninedogs_dlsym("fsync"); |
3003 | 3285 | ||
3004 | 3286 | xlog(100, "%s(%d)\n", __func__, fd); | xlog(100, "%s(%d)\n", __func__, fd); |
3005 | my_trace(__func__, 'c', fd); | ||
3287 | my_trace(__func__, "", 'c', fd); | ||
3006 | 3288 | int ret = old_fsync(fd); | int ret = old_fsync(fd); |
3007 | my_trace(__func__, 'r', fd, ret); | ||
3289 | my_trace(__func__, "", 'r', fd, ret); | ||
3008 | 3290 | ||
3009 | 3291 | return ret; | return ret; |
3010 | 3292 | } | } |
... | ... | int fdatasync(int fd) | |
3016 | 3298 | old_fdatasync = ninedogs_dlsym("fdatasync"); | old_fdatasync = ninedogs_dlsym("fdatasync"); |
3017 | 3299 | ||
3018 | 3300 | xlog(100, "%s(%d)\n", __func__, fd); | xlog(100, "%s(%d)\n", __func__, fd); |
3019 | my_trace(__func__, 'c', fd); | ||
3301 | my_trace(__func__, "", 'c', fd); | ||
3020 | 3302 | int ret = old_fdatasync(fd); | int ret = old_fdatasync(fd); |
3021 | my_trace(__func__, 'r', fd, ret); | ||
3303 | my_trace(__func__, "", 'r', fd, ret); | ||
3022 | 3304 | ||
3023 | 3305 | return ret; | return ret; |
3024 | 3306 | } | } |
... | ... | ssize_t pread(int fd, void *buf, size_t count, off_t offset) | |
3030 | 3312 | old_pread = ninedogs_dlsym("pread"); | old_pread = ninedogs_dlsym("pread"); |
3031 | 3313 | ||
3032 | 3314 | 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); |
3033 | my_trace(__func__, 'c', fd, count, offset); | ||
3315 | my_trace(__func__, "", 'c', fd, count, offset); | ||
3034 | 3316 | ssize_t ret = old_pread(fd, buf, count, offset); | ssize_t ret = old_pread(fd, buf, count, offset); |
3035 | my_trace(__func__, 'r', fd, buf, count, offset, ret); | ||
3317 | my_trace(__func__, "", 'r', fd, buf, count, offset, ret); | ||
3036 | 3318 | ||
3037 | 3319 | return ret; | return ret; |
3038 | 3320 | } | } |
... | ... | ssize_t pread64(int fd, void *buf, size_t count, off_t offset) | |
3044 | 3326 | old_pread64 = ninedogs_dlsym("pread64"); | old_pread64 = ninedogs_dlsym("pread64"); |
3045 | 3327 | ||
3046 | 3328 | 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); |
3047 | my_trace(__func__, 'c', fd, count, offset); | ||
3329 | my_trace(__func__, "", 'c', fd, count, offset); | ||
3048 | 3330 | ssize_t ret = old_pread64(fd, buf, count, offset); | ssize_t ret = old_pread64(fd, buf, count, offset); |
3049 | my_trace(__func__, 'r', fd, buf, count, offset, ret); | ||
3331 | my_trace(__func__, "", 'r', fd, buf, count, offset, ret); | ||
3050 | 3332 | ||
3051 | 3333 | return ret; | return ret; |
3052 | 3334 | } | } |
... | ... | ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset) | |
3058 | 3340 | old_pwrite = ninedogs_dlsym("pwrite"); | old_pwrite = ninedogs_dlsym("pwrite"); |
3059 | 3341 | ||
3060 | 3342 | 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); |
3061 | my_trace(__func__, 'c', fd, buf, count, offset); | ||
3343 | my_trace(__func__, "", 'c', fd, buf, count, offset); | ||
3062 | 3344 | ssize_t ret = old_pwrite(fd, buf, count, offset); | ssize_t ret = old_pwrite(fd, buf, count, offset); |
3063 | my_trace(__func__, 'r', fd, count, offset, ret); | ||
3345 | my_trace(__func__, "", 'r', fd, count, offset, ret); | ||
3064 | 3346 | ||
3065 | 3347 | return ret; | return ret; |
3066 | 3348 | } | } |
... | ... | ssize_t pwrite64(int fd, const void *buf, size_t count, off_t offset) | |
3072 | 3354 | old_pwrite64 = ninedogs_dlsym("pwrite64"); | old_pwrite64 = ninedogs_dlsym("pwrite64"); |
3073 | 3355 | ||
3074 | 3356 | 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); |
3075 | my_trace(__func__, 'c', fd, buf, count, offset); | ||
3357 | my_trace(__func__, "", 'c', fd, buf, count, offset); | ||
3076 | 3358 | ssize_t ret = old_pwrite64(fd, buf, count, offset); | ssize_t ret = old_pwrite64(fd, buf, count, offset); |
3077 | my_trace(__func__, 'r', fd, count, offset, ret); | ||
3359 | my_trace(__func__, "", 'r', fd, count, offset, ret); | ||
3360 | |||
3361 | return ret; | ||
3362 | } | ||
3363 | |||
3364 | int ftruncate(int fd, off_t length) | ||
3365 | { | ||
3366 | static int (*old_ftruncate)(int fd, off_t length) = NULL; | ||
3367 | |||
3368 | if (!old_ftruncate) | ||
3369 | old_ftruncate = ninedogs_dlsym("ftruncate"); | ||
3370 | |||
3371 | xlog(100, "%s(fd=%d, %zu)\n", __func__, fd, length); | ||
3372 | my_trace(__func__, "", 'c', fd, length); | ||
3373 | int ret = old_ftruncate(fd, length); | ||
3374 | my_trace(__func__, "", 'r', fd, length, ret); | ||
3375 | |||
3376 | if (ret == 0) { | ||
3377 | struct fd_node *q = fd_search(fd); | ||
3378 | if (q && (q->type == FD_NODE_MEMFD)) { | ||
3379 | q->file.max = length; | ||
3380 | } | ||
3381 | } | ||
3078 | 3382 | ||
3079 | 3383 | return ret; | return ret; |
3080 | 3384 | } | } |
... | ... | int sqlite3_open(const char *filename, void **ppdb) | |
3088 | 3392 | ||
3089 | 3393 | xlog(100, "%s(%s)\n", __func__, filename); | xlog(100, "%s(%s)\n", __func__, filename); |
3090 | 3394 | ||
3091 | my_trace(__func__, 'c', filename); | ||
3395 | my_trace(__func__, "", 'c', filename); | ||
3092 | 3396 | int ret = old_sqlite3_open(filename, ppdb); | int ret = old_sqlite3_open(filename, ppdb); |
3093 | my_trace(__func__, 'r', filename, ppdb, ret); | ||
3397 | my_trace(__func__, "", 'r', filename, ppdb, ret); | ||
3094 | 3398 | ||
3095 | 3399 | return ret; | return ret; |
3096 | 3400 | } | } |
... | ... | int sqlite3_open_v2(const char *filename, void **ppdb, int flags, const char *vf | |
3105 | 3409 | xlog(100, "%s(%s, ppdb, 0x%x, %s)\n", | xlog(100, "%s(%s, ppdb, 0x%x, %s)\n", |
3106 | 3410 | __func__, filename, flags, vfs); | __func__, filename, flags, vfs); |
3107 | 3411 | ||
3108 | my_trace(__func__, 'c', filename, flags, vfs); | ||
3412 | my_trace(__func__, "", 'c', filename, flags, vfs); | ||
3109 | 3413 | int ret = old_sqlite3_open_v2(filename, ppdb, flags, vfs); | int ret = old_sqlite3_open_v2(filename, ppdb, flags, vfs); |
3110 | my_trace(__func__, 'r', filename, ppdb ? *ppdb : NULL, flags, vfs, ret); | ||
3414 | my_trace(__func__, "", 'r', filename, ppdb ? *ppdb : NULL, flags, vfs, ret); | ||
3111 | 3415 | ||
3112 | 3416 | return ret; | return ret; |
3113 | 3417 | } | } |
... | ... | int sqlite3_open16(const char *filename, void **ppdb) | |
3122 | 3426 | xlog(100, "%s('%s', ppdb)\n", | xlog(100, "%s('%s', ppdb)\n", |
3123 | 3427 | __func__, filename); | __func__, filename); |
3124 | 3428 | ||
3125 | my_trace(__func__, 'c', filename); | ||
3429 | my_trace(__func__, "", 'c', filename); | ||
3126 | 3430 | int ret = old_sqlite3_open16(filename, ppdb); | int ret = old_sqlite3_open16(filename, ppdb); |
3127 | my_trace(__func__, 'r', filename, ppdb, ret); | ||
3431 | my_trace(__func__, "", 'r', filename, ppdb, ret); | ||
3128 | 3432 | ||
3129 | 3433 | return ret; | return ret; |
3130 | 3434 | } | } |
... | ... | int sqlite3_exec(void *h, const char *sql, | |
3140 | 3444 | if (!old_sqlite3_exec) | if (!old_sqlite3_exec) |
3141 | 3445 | old_sqlite3_exec = ninedogs_dlsym("sqlite3_exec"); | old_sqlite3_exec = ninedogs_dlsym("sqlite3_exec"); |
3142 | 3446 | ||
3143 | //my_trace(__func__, 'c', h, sql, callback, callback_arg); | ||
3447 | //my_trace(__func__, "", 'c', h, sql, callback, callback_arg); | ||
3144 | 3448 | int ret = old_sqlite3_exec(h, sql, callback, callback_arg, errmsg); | int ret = old_sqlite3_exec(h, sql, callback, callback_arg, errmsg); |
3145 | 3449 | 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", |
3146 | 3450 | __func__, h, sql, callback, callback_arg, errmsg ? *errmsg : "?"); | __func__, h, sql, callback, callback_arg, errmsg ? *errmsg : "?"); |
3147 | //my_trace(__func__, 'r', h, sql, callback, callback_arg, errmsg); | ||
3451 | //my_trace(__func__, "", 'r', h, sql, callback, callback_arg, errmsg); | ||
3148 | 3452 | ||
3149 | 3453 | return ret; | return ret; |
3150 | 3454 | } | } |
... | ... | int sqlite3_prepare_v2(void *h, const char *sql, int nByte, void **stmt, const c | |
3156 | 3460 | if (!old_sqlite3_prepare_v2) | if (!old_sqlite3_prepare_v2) |
3157 | 3461 | old_sqlite3_prepare_v2 = ninedogs_dlsym("sqlite3_prepare_v2"); | old_sqlite3_prepare_v2 = ninedogs_dlsym("sqlite3_prepare_v2"); |
3158 | 3462 | ||
3159 | my_trace(__func__, 'c', h, sql, nByte); | ||
3463 | my_trace(__func__, "", 'c', h, sql, nByte); | ||
3160 | 3464 | int ret = old_sqlite3_prepare_v2(h, sql, nByte, stmt, tail); | int ret = old_sqlite3_prepare_v2(h, sql, nByte, stmt, tail); |
3161 | 3465 | 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", |
3162 | 3466 | __func__, h, sql, nByte, stmt ? *stmt : NULL, tail ? *tail : "", ret); | __func__, h, sql, nByte, stmt ? *stmt : NULL, tail ? *tail : "", ret); |
3163 | my_trace(__func__, 'r', h, sql, nByte, stmt ? *stmt : NULL, ret); | ||
3467 | my_trace(__func__, "", 'r', h, sql, nByte, stmt ? *stmt : NULL, ret); | ||
3164 | 3468 | // TODO: do we need 'tail'? | // TODO: do we need 'tail'? |
3165 | 3469 | ||
3166 | 3470 | return ret; | return ret; |
... | ... | int sqlite3_finalize(void *pstmt) | |
3175 | 3479 | ||
3176 | 3480 | int ret = old_sqlite3_finalize(pstmt); | int ret = old_sqlite3_finalize(pstmt); |
3177 | 3481 | xlog(100, "%s(pstmt=%p) = %d\n", __func__, pstmt); | xlog(100, "%s(pstmt=%p) = %d\n", __func__, pstmt); |
3178 | my_trace(__func__, 'R', pstmt, ret); | ||
3482 | my_trace(__func__, "", 'R', pstmt, ret); | ||
3179 | 3483 | ||
3180 | 3484 | return ret; | return ret; |
3181 | 3485 | } | } |
... | ... | int sqlite3_step(void *stmt) | |
3187 | 3491 | if (!old_sqlite3_step) | if (!old_sqlite3_step) |
3188 | 3492 | old_sqlite3_step = ninedogs_dlsym("sqlite3_step"); | old_sqlite3_step = ninedogs_dlsym("sqlite3_step"); |
3189 | 3493 | ||
3190 | my_trace(__func__, 'c', stmt); | ||
3494 | my_trace(__func__, "", 'c', stmt); | ||
3191 | 3495 | int ret = old_sqlite3_step(stmt); | int ret = old_sqlite3_step(stmt); |
3192 | 3496 | xlog(100, "%s(stmt=%p) = %d\n", __func__, stmt, ret); | xlog(100, "%s(stmt=%p) = %d\n", __func__, stmt, ret); |
3193 | my_trace(__func__, 'r', stmt, ret); | ||
3497 | my_trace(__func__, "", 'r', stmt, ret); | ||
3194 | 3498 | ||
3195 | 3499 | return ret; | return ret; |
3196 | 3500 | } | } |
... | ... | int sqlite3_bind_double(void *stmt, int index, double value) | |
3204 | 3508 | ||
3205 | 3509 | int ret = old_sqlite3_bind_double(stmt, index, value); | int ret = old_sqlite3_bind_double(stmt, index, value); |
3206 | 3510 | 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); |
3207 | my_trace(__func__, 'R', stmt, index, value, ret); | ||
3511 | my_trace(__func__, "", 'R', stmt, index, value, ret); | ||
3208 | 3512 | ||
3209 | 3513 | return ret; | return ret; |
3210 | 3514 | } | } |
... | ... | int sqlite3_bind_int(void *stmt, int index, int value) | |
3218 | 3522 | ||
3219 | 3523 | int ret = old_sqlite3_bind_int(stmt, index, value); | int ret = old_sqlite3_bind_int(stmt, index, value); |
3220 | 3524 | 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); |
3221 | my_trace(__func__, 'R', stmt, index, value, ret); | ||
3525 | my_trace(__func__, "", 'R', stmt, index, value, ret); | ||
3222 | 3526 | ||
3223 | 3527 | return ret; | return ret; |
3224 | 3528 | } | } |
... | ... | int sqlite3_bind_int64(void *stmt, int index, uint64_t value) | |
3232 | 3536 | ||
3233 | 3537 | int ret = old_sqlite3_bind_int64(stmt, index, value); | int ret = old_sqlite3_bind_int64(stmt, index, value); |
3234 | 3538 | 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); |
3235 | my_trace(__func__, 'R', stmt, index, value, ret); | ||
3539 | my_trace(__func__, "", 'R', stmt, index, value, ret); | ||
3236 | 3540 | ||
3237 | 3541 | return ret; | return ret; |
3238 | 3542 | } | } |
... | ... | int sqlite3_bind_text(void *stmt, int index, const char *value, int len, void *f | |
3246 | 3550 | ||
3247 | 3551 | int ret = old_sqlite3_bind_text(stmt, index, value, len, func); | int ret = old_sqlite3_bind_text(stmt, index, value, len, func); |
3248 | 3552 | 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); |
3249 | my_trace(__func__, 'R', stmt, index, value, len, ret); | ||
3553 | my_trace(__func__, "", 'R', stmt, index, value, len, ret); | ||
3250 | 3554 | ||
3251 | 3555 | return ret; | return ret; |
3252 | 3556 | } | } |
File agent/ninedogs.h changed (mode: 100644) (index 58b0edd..f692475) | |||
1 | 1 | void ninedogs_fini(void); | void ninedogs_fini(void); |
2 | 2 | void ninedogs_init(void); | void ninedogs_init(void); |
3 | void my_trace(const char *func, const char type, ...); | ||
3 | void my_trace(const char *func, const char *tf, const char type, ...); | ||
4 | 4 | void *ninedogs_dlsym(const char *sym); | void *ninedogs_dlsym(const char *sym); |
5 | 5 |
File agent/php-core.c added (mode: 100644) (index 0000000..a9c8174) | |||
1 | /* | ||
2 | * Description: Monitoring application | ||
3 | * Author: Catalin(ux) M. BOIE | ||
4 | * E-mail: catab at embedromix dot ro | ||
5 | * Web: https://rocketgit.com/user/catalinux/ninedogs | ||
6 | */ | ||
7 | |||
8 | #include <signal.h> | ||
9 | #include <pthread.h> | ||
10 | #include <stdarg.h> | ||
11 | #include <stdio.h> | ||
12 | #include <stdlib.h> | ||
13 | #include <syslog.h> | ||
14 | #include <dlfcn.h> | ||
15 | #include <fcntl.h> | ||
16 | #include <string.h> | ||
17 | #include <unistd.h> | ||
18 | #include <sys/stat.h> | ||
19 | #include <sys/types.h> | ||
20 | #include <sys/stat.h> | ||
21 | #include <sys/time.h> | ||
22 | #include <time.h> | ||
23 | #include <errno.h> | ||
24 | #include <dirent.h> | ||
25 | #include <asm/unistd.h> | ||
26 | #include <fcntl.h> | ||
27 | #include <sys/socket.h> | ||
28 | #include <arpa/inet.h> | ||
29 | #include <netinet/in.h> | ||
30 | #include <netinet/tcp.h> | ||
31 | #include <poll.h> | ||
32 | #include <netdb.h> | ||
33 | #include <ctype.h> | ||
34 | |||
35 | #include "php-core.h" | ||
36 | #include "ids.h" | ||
37 | #include "tools.h" | ||
38 | #include "ctools.h" | ||
39 | |||
40 | char *php_get_value(const struct zval *z) | ||
41 | { | ||
42 | static char ret[4096]; | ||
43 | const struct zval *next; | ||
44 | |||
45 | if (!z) | ||
46 | return "NULL"; | ||
47 | |||
48 | switch (z->u1.v.type) { | ||
49 | case 0: return ""; | ||
50 | case 1: return ""; | ||
51 | case 2: return ""; | ||
52 | case 3: return ""; | ||
53 | case 4: snprintf(ret, sizeof(ret), "%ld", z->value.lval); return ret; | ||
54 | case 5: snprintf(ret, sizeof(ret), "%f", z->value.dval); return ret; | ||
55 | case 6: { | ||
56 | struct zend_string *zs = z->value.str; | ||
57 | return zs->val; } | ||
58 | case 8: | ||
59 | snprintf(ret, sizeof(ret), "%p", z->value.p); return ret; | ||
60 | case 9: | ||
61 | snprintf(ret, sizeof(ret), "%p", z->value.p); return ret; | ||
62 | case 10: | ||
63 | next = &z->value.ref->val; | ||
64 | return php_get_value(next); | ||
65 | case 12: | ||
66 | next = z->value.zv; | ||
67 | return php_get_value(next); | ||
68 | default: | ||
69 | snprintf(ret, sizeof(ret), "?%hhu: %p", | ||
70 | z->u1.v.type, z->value.str); return ret; | ||
71 | } | ||
72 | } | ||
73 | |||
74 | char *php_get_type(const struct zval *z) | ||
75 | { | ||
76 | static char s[8]; | ||
77 | |||
78 | if (!z) | ||
79 | return "NULL"; | ||
80 | |||
81 | switch (z->u1.v.type) { | ||
82 | case 0: return "undef"; | ||
83 | case 1: return "null"; | ||
84 | case 2: return "false"; | ||
85 | case 3: return "true"; | ||
86 | case 4: return "long"; | ||
87 | case 5: return "double"; | ||
88 | case 6: return "string"; | ||
89 | case 7: return "array"; | ||
90 | case 8: return "object"; | ||
91 | case 9: return "resource"; | ||
92 | case 10: return "ref"; | ||
93 | case 12: return "indirect"; | ||
94 | default: sprintf(s, "?%hhu", z->u1.v.type); return s; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | void php_zval_dump_buf(char *buf, const size_t size, | ||
99 | const char *prefix, const struct zval *z) | ||
100 | { | ||
101 | if (!z) { | ||
102 | snprintf(buf, size, "zval is null"); | ||
103 | return; | ||
104 | } | ||
105 | |||
106 | snprintf(buf, size, "%s%p: type=%s value=[%s] type_flags=%hhu extra=%hu num_args=%u", | ||
107 | prefix, z, php_get_type(z), php_get_value(z), | ||
108 | z->u1.v.type_flags, | ||
109 | z->u1.v.u.extra, z->u2.num_args); | ||
110 | } | ||
111 | |||
112 | void php_zval_dump(const char *prefix, const struct zval *z) | ||
113 | { | ||
114 | char s[4096]; | ||
115 | |||
116 | php_zval_dump_buf(s, sizeof(s), prefix, z); | ||
117 | xlog(100, "%s\n", s); | ||
118 | } | ||
119 | |||
120 | static void php_zed_dump(const char *prefix, struct zend_execute_data *p) | ||
121 | { | ||
122 | unsigned int num_args, s, i; | ||
123 | struct zval *z; | ||
124 | char x[64]; | ||
125 | |||
126 | if (!p) { | ||
127 | xlog(100, "%szed is null!\n", prefix); | ||
128 | return; | ||
129 | } | ||
130 | |||
131 | num_args = p->This.u2.num_args; | ||
132 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
133 | dump(100, "zed", p, sizeof(struct zval) * (s + num_args)); | ||
134 | |||
135 | xlog(100, "%szed: p=%p num_args=%hu return_value=%p\n", | ||
136 | prefix, p, num_args, p->return_value); | ||
137 | //php_zval_dump(prefix, p->return_value); | ||
138 | snprintf(x, sizeof(x), "%s This: ", prefix); | ||
139 | php_zval_dump(x, &p->This); | ||
140 | |||
141 | for (i = 0; i < num_args; i++) { | ||
142 | char zs[1024]; | ||
143 | |||
144 | z = (struct zval *) p + s; s++; | ||
145 | php_zval_dump_buf(zs, sizeof(zs), "", z); | ||
146 | xlog(100, "%s para %u: %s\n", prefix, i, zs); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | // TODO this is really not related to parameters - rename it | ||
151 | // this is obsolete. Use 'zend_to_binary' - not so sure: his is to fill nd_params_array, | ||
152 | // zend_to_binary is to binary pack an array. | ||
153 | void zend_array_to_params_array(struct nd_params_array *p, struct zend_array *za) | ||
154 | { | ||
155 | unsigned int i = 0; | ||
156 | |||
157 | xlog(100, " %s: nTableMask=0x%x nNumUsed=%u nNumOfElements=%u nTableSize=%u" | ||
158 | " nInternalPointer=%u flags=0x%x[%s]\n", | ||
159 | __func__, | ||
160 | za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize, | ||
161 | za->nInternalPointer, za->u.flags, za->u.flags & 4 ? "packed" : ""); | ||
162 | |||
163 | struct Bucket *bs = za->arData, *be = za->arData + za->nNumUsed; | ||
164 | for (; bs != be; bs++) { | ||
165 | struct zval *_z = &bs->val; | ||
166 | |||
167 | if (_z && (_z->u1.v.type == 12)) // 12=IS_INDIRECT | ||
168 | _z = _z->value.zv; | ||
169 | |||
170 | if (_z->u1.v.type == 0 /*IS_UNDEF*/) { | ||
171 | xlog(101, " para h=%lu: type undef\n", bs->h); | ||
172 | continue; | ||
173 | } | ||
174 | |||
175 | if (_z->u1.v.type == 10) { // REFERENCE | ||
176 | xlog(101, " is a reference!\n"); | ||
177 | _z = &_z->value.ref->val; | ||
178 | } | ||
179 | |||
180 | struct zend_string *zs = bs->key; | ||
181 | xlog(101, " para: bs=%p h=%lu key=[%p] type %s: val: %s\n", | ||
182 | bs, bs->h, zs, php_get_type(_z), php_get_value(_z)); | ||
183 | |||
184 | p->list[i].bind_way = ND_PARAMS_BIND_WAY_NONE; | ||
185 | p->list[i].bind_type = ND_PARAMS_BIND_TYPE_NONE; | ||
186 | p->list[i].pointer = 0; // TODO: we may need to revisit this. | ||
187 | |||
188 | if (_z->u1.v.type == 1) { | ||
189 | p->list[i].type = ND_TYPE_NULL; | ||
190 | } else if (_z->u1.v.type == 2) { | ||
191 | p->list[i].type = ND_TYPE_STRING; | ||
192 | p->list[i].str = "false"; | ||
193 | p->list[i].length = 5; | ||
194 | } else if (_z->u1.v.type == 3) { | ||
195 | p->list[i].type = ND_TYPE_STRING; | ||
196 | p->list[i].str = "true"; | ||
197 | p->list[i].length = 4; | ||
198 | } else if (_z->u1.v.type == 4) { | ||
199 | p->list[i].type = ND_TYPE_LONG; | ||
200 | p->list[i].l = _z->value.lval; | ||
201 | } else if (_z->u1.v.type == 5) { | ||
202 | p->list[i].type = ND_TYPE_DOUBLE; | ||
203 | p->list[i].d = _z->value.dval; | ||
204 | } else if (_z->u1.v.type == 6) { | ||
205 | p->list[i].type = ND_TYPE_STRING; | ||
206 | struct zend_string *zs = _z->value.str; | ||
207 | p->list[i].str = zs->val; | ||
208 | p->list[i].length = zs->len; | ||
209 | } else { | ||
210 | p->list[i].type = ND_TYPE_NULL; | ||
211 | xlog(1, " %s: I do not how to encode %d type! Encode as NULL\n", | ||
212 | __func__, _z->u1.v.type); | ||
213 | } | ||
214 | |||
215 | i++; | ||
216 | if (i == ND_PARAMS_MAX) | ||
217 | break; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | static unsigned int zend_simple_to_binary(unsigned char *out, | ||
222 | const size_t out_size, struct zval *z) | ||
223 | { | ||
224 | unsigned int off = 0; | ||
225 | uint16_t u16; | ||
226 | uint64_t u64; | ||
227 | |||
228 | if (off + 1 + 8 > out_size) // 1+8 for a long | ||
229 | return 0; | ||
230 | |||
231 | if (z->u1.v.type == 1) { | ||
232 | out[off++] = ND_TYPE_NULL; | ||
233 | } else if (z->u1.v.type == 2) { | ||
234 | out[off++] = ND_TYPE_FALSE; | ||
235 | } else if (z->u1.v.type == 3) { | ||
236 | out[off++] = ND_TYPE_TRUE; | ||
237 | } else if (z->u1.v.type == 4) { | ||
238 | out[off++] = ND_TYPE_LONG; | ||
239 | u64 = htobe64(z->value.lval); | ||
240 | memcpy(out + off, &u64, 8); off += 8; | ||
241 | } else if (z->u1.v.type == 5) { | ||
242 | out[off++] = ND_TYPE_DOUBLE; | ||
243 | uint64_t u64 = htobe64(z->value.lval); | ||
244 | memcpy(out + off, &u64, 8); off += 8; | ||
245 | } else if (z->u1.v.type == 6) { | ||
246 | out[off++] = ND_TYPE_STRING; | ||
247 | struct zend_string *zs = z->value.str; | ||
248 | if (off + 2 + zs->len > out_size) | ||
249 | return 0; | ||
250 | u16 = htobe16(zs->len); | ||
251 | memcpy(out + off, &u16, 2); off += 2; | ||
252 | memcpy(out + off, zs->val, zs->len); off += zs->len; | ||
253 | } else if (z->u1.v.type == 8) { // object | ||
254 | out[off++] = ND_TYPE_POINTER; | ||
255 | u64 = htobe64(z->value.lval); | ||
256 | memcpy(out + off, &u64, 8); off += 8; | ||
257 | } else if (z->u1.v.type == 9) { // resource | ||
258 | out[off++] = ND_TYPE_POINTER; | ||
259 | u64 = htobe64(z->value.lval); | ||
260 | memcpy(out + off, &u64, 8); off += 8; | ||
261 | } else { | ||
262 | out[off++] = ND_TYPE_UNK; | ||
263 | xlog(1, " %s: I do not how to encode %d type! Encode as NULL\n", | ||
264 | __func__, z->u1.v.type); | ||
265 | } | ||
266 | |||
267 | return off; | ||
268 | } | ||
269 | |||
270 | // Returns the number of bytes stored in 'out' | ||
271 | static unsigned int zend_array_to_binary(unsigned char *out, const size_t out_size, | ||
272 | struct zend_array *za) | ||
273 | { | ||
274 | xlog(100, " %s: nTableMask=0x%x nNumUsed=%u nNumOfElements=%u nTableSize=%u" | ||
275 | " nInternalPointer=%u flags=0x%x[%s]\n", | ||
276 | __func__, | ||
277 | za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize, | ||
278 | za->nInternalPointer, za->u.flags, za->u.flags & 4 ? "packed" : ""); | ||
279 | |||
280 | unsigned int off = 0; | ||
281 | out[off++] = ND_TYPE_ARRAY_START; | ||
282 | |||
283 | struct Bucket *bs = za->arData, *be = za->arData + za->nNumUsed; | ||
284 | for (; bs != be; bs++) { | ||
285 | struct zval *_z = &bs->val; | ||
286 | |||
287 | if (_z && (_z->u1.v.type == 12)) // 12=IS_INDIRECT | ||
288 | _z = _z->value.zv; | ||
289 | |||
290 | if (_z->u1.v.type == 0 /*IS_UNDEF*/) { | ||
291 | xlog(101, " para h=%lu: type undef\n", bs->h); | ||
292 | continue; | ||
293 | } | ||
294 | |||
295 | if (_z->u1.v.type == 10) { // REFERENCE | ||
296 | xlog(101, " is a reference!\n"); | ||
297 | _z = &_z->value.ref->val; | ||
298 | } | ||
299 | |||
300 | struct zend_string *zs = bs->key; | ||
301 | xlog(101, " para: bs=%p h=%lu key=[%p] type %s: val: %s\n", | ||
302 | bs, bs->h, zs, php_get_type(_z), php_get_value(_z)); | ||
303 | |||
304 | unsigned int r = zend_simple_to_binary(out + off, out_size - off, _z); | ||
305 | if (r == 0) | ||
306 | break; | ||
307 | off += r; | ||
308 | } | ||
309 | |||
310 | out[off++] = ND_TYPE_ARRAY_END; | ||
311 | |||
312 | return off; | ||
313 | } | ||
314 | |||
315 | // Returns the number of bytes stored in 'out' | ||
316 | unsigned int zend_to_binary(unsigned char *out, const size_t out_size, | ||
317 | struct zval *z) | ||
318 | { | ||
319 | if (z->u1.v.type == 7) | ||
320 | return zend_array_to_binary(out, out_size, z->value.arr); | ||
321 | |||
322 | return zend_simple_to_binary(out, out_size, z); | ||
323 | } | ||
324 | |||
325 | void php_set_para(struct zend_execute_data *e, const unsigned int i, | ||
326 | const struct zval *para) | ||
327 | { | ||
328 | unsigned int s; | ||
329 | struct zval *dst; | ||
330 | |||
331 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
332 | dst = (struct zval *) e + s + i; | ||
333 | memcpy(dst, para, sizeof(struct zval)); | ||
334 | } | ||
335 |
File agent/php-core.h added (mode: 100644) (index 0000000..9b07134) | |||
1 | #ifndef NINEDOGS_PHP_CORE_H | ||
2 | #define NINEDOGS_PHP_CORE_H 1 | ||
3 | |||
4 | #include <stdint.h> // for uint32_t | ||
5 | |||
6 | #include "../common/params.h" | ||
7 | |||
8 | extern void *(*old_malloc)(size_t size); | ||
9 | extern void (*old_free)(void *p); | ||
10 | |||
11 | |||
12 | struct zend_function_entry | ||
13 | { | ||
14 | const char *fname; | ||
15 | void *handler; | ||
16 | void *arg_info; | ||
17 | unsigned int num_args; | ||
18 | unsigned int flags; | ||
19 | }; | ||
20 | |||
21 | struct zend_module_entry | ||
22 | { | ||
23 | unsigned short size; | ||
24 | unsigned short pad1; | ||
25 | unsigned int zend_api; | ||
26 | unsigned char zend_debug; | ||
27 | unsigned char zts; | ||
28 | unsigned char pad2[6]; | ||
29 | void *ini_entry; | ||
30 | void *deps; | ||
31 | const char *name; | ||
32 | struct zend_function_entry *functions; | ||
33 | void *junk[5]; | ||
34 | const char *version; | ||
35 | size_t globals_size; | ||
36 | void *globals; | ||
37 | void *globals_ctor; | ||
38 | void *globals_dtor; | ||
39 | void *post_deactivate_func; | ||
40 | int module_started; | ||
41 | unsigned char type; | ||
42 | unsigned char pad3[3]; | ||
43 | void *handle; | ||
44 | int module_number; | ||
45 | int pad4; | ||
46 | const char *build_id; | ||
47 | }; | ||
48 | |||
49 | typedef long zend_long; | ||
50 | typedef unsigned long zend_ulong; | ||
51 | |||
52 | struct zend_refcounted_h | ||
53 | { | ||
54 | unsigned int refcount; | ||
55 | unsigned int type_info; | ||
56 | }; | ||
57 | |||
58 | struct zend_resource | ||
59 | { | ||
60 | struct zend_refcounted_h gc; | ||
61 | int handle; | ||
62 | int type; | ||
63 | void *ptr; | ||
64 | }; | ||
65 | |||
66 | struct zend_string | ||
67 | { | ||
68 | struct zend_refcounted_h gc; | ||
69 | zend_ulong hash; | ||
70 | size_t len; | ||
71 | char val[1]; | ||
72 | char pad1[7]; | ||
73 | }; | ||
74 | |||
75 | struct zend_array | ||
76 | { | ||
77 | struct zend_refcounted_h gc; | ||
78 | union { | ||
79 | struct { | ||
80 | unsigned char flags; | ||
81 | unsigned char _unused; | ||
82 | unsigned char nIteratorsCount; | ||
83 | unsigned char _unused2; | ||
84 | } v; | ||
85 | unsigned int flags; | ||
86 | } u; | ||
87 | unsigned int nTableMask; | ||
88 | union { | ||
89 | uint32_t *arHash; | ||
90 | struct Bucket *arData; | ||
91 | struct zval *arPacked; | ||
92 | }; | ||
93 | unsigned int nNumUsed; | ||
94 | unsigned int nNumOfElements; | ||
95 | unsigned int nTableSize; | ||
96 | unsigned int nInternalPointer; | ||
97 | zend_long nNextFreeElement; | ||
98 | void *dtor; | ||
99 | }; | ||
100 | |||
101 | union zend_value | ||
102 | { | ||
103 | zend_long lval; | ||
104 | double dval; | ||
105 | void *p; | ||
106 | struct zend_string *str; | ||
107 | struct zend_array *arr; | ||
108 | struct zend_resource *res; | ||
109 | struct zend_reference *ref; | ||
110 | struct zval *zv; | ||
111 | struct { | ||
112 | unsigned int w1; | ||
113 | unsigned int w2; | ||
114 | } ww; | ||
115 | }; | ||
116 | |||
117 | struct zval | ||
118 | { | ||
119 | union zend_value value; | ||
120 | union { | ||
121 | unsigned int type_info; | ||
122 | struct { | ||
123 | unsigned char type; | ||
124 | unsigned char type_flags; | ||
125 | union { | ||
126 | unsigned short extra; | ||
127 | } u; | ||
128 | } v; | ||
129 | } u1; | ||
130 | union { | ||
131 | unsigned int num_args; | ||
132 | } u2; | ||
133 | }; | ||
134 | |||
135 | struct Bucket | ||
136 | { | ||
137 | struct zval val; | ||
138 | zend_ulong h; | ||
139 | struct zend_string *key; | ||
140 | }; | ||
141 | |||
142 | struct zend_reference | ||
143 | { | ||
144 | struct zend_refcounted_h gc; | ||
145 | struct zval val; | ||
146 | void *sources; | ||
147 | }; | ||
148 | |||
149 | struct zend_execute_data | ||
150 | { | ||
151 | void *opline; | ||
152 | struct zend_execute_data *call; | ||
153 | struct zval *return_value; | ||
154 | void *func; | ||
155 | struct zval This; | ||
156 | struct zend_execute_data *prev; | ||
157 | struct zend_array *symbol_table; | ||
158 | void **runtime_cache; | ||
159 | struct zend_array *extra_named_params; | ||
160 | }; | ||
161 | |||
162 | struct TODOpgsql_link_handle | ||
163 | { | ||
164 | void *conn; // PGconn | ||
165 | struct zend_string *hash; | ||
166 | struct HashTable *notices; | ||
167 | unsigned char persistent; // bool | ||
168 | //zend_object std; | ||
169 | unsigned char pad1[7]; | ||
170 | }; | ||
171 | |||
172 | unsigned int zend_to_binary(unsigned char *out, const size_t out_size, | ||
173 | struct zval *z); | ||
174 | void php_zval_dump_buf(char *buf, const size_t size, | ||
175 | const char *prefix, const struct zval *z); | ||
176 | void php_zval_dump(const char *prefix, const struct zval *z); | ||
177 | void php_set_para(struct zend_execute_data *e, const unsigned int i, | ||
178 | const struct zval *para); | ||
179 | void zend_array_to_params_array(struct nd_params_array *p, | ||
180 | struct zend_array *za); | ||
181 | char *php_get_type(const struct zval *z); | ||
182 | char *php_get_value(const struct zval *z); | ||
183 | |||
184 | #endif |
File agent/php-curl.c added (mode: 100644) (index 0000000..ce50e26) | |||
1 | #include <stdio.h> | ||
2 | #include <string.h> | ||
3 | |||
4 | #include "ids.h" | ||
5 | #include "tools.h" | ||
6 | #include "ctools.h" | ||
7 | |||
8 | #include "curl.h" | ||
9 | #include "php-curl.h" | ||
10 | #include "process_url.h" | ||
11 | |||
12 | static void *(*old_curl_init)(struct zend_execute_data *, struct zval *); | ||
13 | static void *my_curl_init(struct zend_execute_data *e, struct zval *retv) | ||
14 | { | ||
15 | struct nd_url b; | ||
16 | |||
17 | unsigned int num_args = e->This.u2.num_args; | ||
18 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
19 | |||
20 | if (num_args > 0) { | ||
21 | unsigned int s = (sizeof(struct zend_execute_data) | ||
22 | + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
23 | |||
24 | // url | ||
25 | struct zval *z = (struct zval *) e + s; s++; | ||
26 | php_zval_dump(" url: ", z); | ||
27 | struct zend_string *xs = z->value.str; | ||
28 | b.url = xs->val; | ||
29 | b.url_len = xs->len; | ||
30 | } else { | ||
31 | b.url = NULL; | ||
32 | b.url_len = 0; | ||
33 | } | ||
34 | |||
35 | void *ret = old_curl_init(e, retv); | ||
36 | if (!retv) | ||
37 | return ret; | ||
38 | |||
39 | if ((retv->u1.v.type == 7) || (retv->u1.v.type == 8)) { // resource or object | ||
40 | b.handle = retv->value.p; | ||
41 | } else if (retv->u1.v.type == 2) { // false | ||
42 | b.handle = NULL; | ||
43 | } | ||
44 | |||
45 | ninedogs_process_url("curl_init", NINEDOGS_URL_INIT_END, &b); | ||
46 | |||
47 | return ret; | ||
48 | } | ||
49 | |||
50 | static void *(*old_curl_exec)(struct zend_execute_data *, struct zval *); | ||
51 | static void *my_curl_exec(struct zend_execute_data *e, struct zval *retv) | ||
52 | { | ||
53 | struct nd_url b = { .url_len = 0, .sret_len = 0 }; | ||
54 | |||
55 | unsigned int num_args = e->This.u2.num_args; | ||
56 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
57 | |||
58 | unsigned int s = (sizeof(struct zend_execute_data) | ||
59 | + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
60 | |||
61 | // handle | ||
62 | struct zval *z = (struct zval *) e + s; s++; | ||
63 | php_zval_dump(" handle: ", z); | ||
64 | b.handle = z->value.p; | ||
65 | |||
66 | ninedogs_process_url("curl_exec", NINEDOGS_URL_START, &b); | ||
67 | void *ret = old_curl_exec(e, retv); | ||
68 | if (!retv) | ||
69 | return ret; | ||
70 | |||
71 | if (retv->u1.v.type == 6) { // string | ||
72 | struct zend_string *xs = retv->value.str; | ||
73 | b.ret = 2; | ||
74 | b.sret = xs->val; | ||
75 | b.sret_len = xs->len; | ||
76 | } else if (retv->u1.v.type == 2) { // false | ||
77 | b.ret = 0; | ||
78 | } else if (retv->u1.v.type == 3) { // true | ||
79 | b.ret = 1; | ||
80 | } | ||
81 | // TODO: propagate errors | ||
82 | |||
83 | ninedogs_process_url("curl_exec", NINEDOGS_URL_END, &b); | ||
84 | |||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | static void *(*old_curl_close)(struct zend_execute_data *, struct zval *); | ||
89 | static void *my_curl_close(struct zend_execute_data *e, struct zval *retv) | ||
90 | { | ||
91 | struct nd_url b = { .url_len = 0, .sret_len = 0 }; | ||
92 | |||
93 | unsigned int num_args = e->This.u2.num_args; | ||
94 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
95 | |||
96 | unsigned int s = (sizeof(struct zend_execute_data) | ||
97 | + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
98 | |||
99 | // handle | ||
100 | struct zval *z = (struct zval *) e + s; s++; | ||
101 | php_zval_dump(" handle: ", z); | ||
102 | b.handle = z->value.p; | ||
103 | |||
104 | void *ret = old_curl_close(e, retv); | ||
105 | if (!retv) | ||
106 | return ret; | ||
107 | |||
108 | ninedogs_process_url("curl_close", NINEDOGS_URL_CLOSE_END, &b); | ||
109 | |||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | static void *(*old_curl_setopt)(struct zend_execute_data *, struct zval *); | ||
114 | static void *my_curl_setopt(struct zend_execute_data *e, struct zval *retv) | ||
115 | { | ||
116 | struct nd_url b = { .url_len = 0, .sret_len = 0 }; | ||
117 | |||
118 | unsigned int num_args = e->This.u2.num_args; | ||
119 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
120 | |||
121 | unsigned int s = (sizeof(struct zend_execute_data) | ||
122 | + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
123 | |||
124 | // handle | ||
125 | struct zval *z = (struct zval *) e + s; s++; | ||
126 | php_zval_dump(" handle: ", z); | ||
127 | b.handle = z->value.p; | ||
128 | |||
129 | // option | ||
130 | z = (struct zval *) e + s; s++; | ||
131 | php_zval_dump(" option: ", z); | ||
132 | const struct my_curl_easyoption *oi = curl_easy_option_by_id(z->value.lval); | ||
133 | if (oi) | ||
134 | snprintf(b.op, sizeof(b.op), "%s", oi->name); | ||
135 | else | ||
136 | snprintf(b.op, sizeof(b.op), "?%ld?", z->value.lval); | ||
137 | xlog(100, " option name = %s\n", b.op); | ||
138 | |||
139 | // value | ||
140 | z = (struct zval *) e + s; s++; | ||
141 | php_zval_dump(" value: ", z); | ||
142 | b.op_value_len = zend_to_binary(b.op_value, sizeof(b.op_value), z); | ||
143 | |||
144 | void *ret = old_curl_setopt(e, retv); | ||
145 | if (!retv) | ||
146 | return ret; | ||
147 | php_zval_dump(" retv: ", retv); | ||
148 | |||
149 | if (retv->u1.v.type == 2) { // false | ||
150 | b.ret = 0; | ||
151 | } else if (retv->u1.v.type == 3) { // true | ||
152 | b.ret = 1; | ||
153 | } | ||
154 | // TODO: propagate errors | ||
155 | |||
156 | ninedogs_process_url("curl_setopt", NINEDOGS_URL_SETOPT_END, &b); | ||
157 | |||
158 | return ret; | ||
159 | } | ||
160 | |||
161 | void php_curl_hook(struct zend_function_entry *fe) | ||
162 | { | ||
163 | if (strcmp(fe->fname, "curl_close") == 0) { | ||
164 | old_curl_close = fe->handler; | ||
165 | fe->handler = my_curl_close; | ||
166 | } else if (strcmp(fe->fname, "curl_init") == 0) { | ||
167 | old_curl_init = fe->handler; | ||
168 | fe->handler = my_curl_init; | ||
169 | } else if (strcmp(fe->fname, "curl_exec") == 0) { | ||
170 | old_curl_exec = fe->handler; | ||
171 | fe->handler = my_curl_exec; | ||
172 | } else if (strcmp(fe->fname, "curl_setopt") == 0) { | ||
173 | old_curl_setopt = fe->handler; | ||
174 | fe->handler = my_curl_setopt; | ||
175 | } else { | ||
176 | //xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname); | ||
177 | } | ||
178 | } |
File agent/php-curl.h added (mode: 100644) (index 0000000..d469bd9) | |||
1 | #include "php-core.h" | ||
2 | |||
3 | void php_curl_hook(struct zend_function_entry *fe); | ||
4 |
File agent/php-mysql.c added (mode: 100644) (index 0000000..0cae262) | |||
1 | #include <stdio.h> | ||
2 | #include <string.h> | ||
3 | |||
4 | #include "ids.h" | ||
5 | #include "tools.h" | ||
6 | #include "php-mysql.h" | ||
7 | #include "process_db.h" | ||
8 | |||
9 | static void *(*old_mysqli_error)(struct zend_execute_data *, struct zval *); | ||
10 | static void *(*old_mysqli_affected_rows)(struct zend_execute_data *, struct zval *); | ||
11 | static void *(*old_mysqli_num_rows)(struct zend_execute_data *, struct zval *); | ||
12 | static void *(*old_mysqli_stmt_affected_rows)(struct zend_execute_data *, struct zval *); | ||
13 | static void *(*old_mysqli_stmt_num_rows)(struct zend_execute_data *, struct zval *); | ||
14 | |||
15 | static void php_mysqli_set_error(struct zend_execute_data *e, | ||
16 | struct zval *link, struct query *q) | ||
17 | { | ||
18 | struct zval rz; | ||
19 | |||
20 | e->This.u2.num_args = 1; | ||
21 | php_set_para(e, 0, link); | ||
22 | |||
23 | // TODO: we need also the numeric representation of the error! | ||
24 | xlog(50, " calling mysqli_error...\n"); | ||
25 | old_mysqli_error(e, &rz); | ||
26 | |||
27 | if (rz.u1.v.type == 6) { // string | ||
28 | q->err = rz.value.str->val; | ||
29 | q->err_len = rz.value.str->len; | ||
30 | xlog(40, "%s: set error to [%s]\n", __func__, q->err); | ||
31 | } else { | ||
32 | q->err = "?"; | ||
33 | q->err_len = 1; | ||
34 | } | ||
35 | } | ||
36 | |||
37 | static void php_mysqli_set_num_aff(struct zend_execute_data *e, struct zval *res, | ||
38 | struct query *q) | ||
39 | { | ||
40 | struct zval rz; | ||
41 | |||
42 | e->This.u2.num_args = 1; | ||
43 | |||
44 | //xlog(1, " calling old pg_affected_rows...\n"); | ||
45 | //php_zed_dump(" e: ", e); | ||
46 | old_mysqli_affected_rows(e, &rz); // we need to pass a link here | ||
47 | php_zval_dump(" aff_rows: ", &rz); | ||
48 | q->aff = rz.value.lval; | ||
49 | |||
50 | php_set_para(e, 0, res); | ||
51 | //xlog(1, " calling old pg_num_rows...\n"); | ||
52 | //php_zed_dump(" e: ", e); | ||
53 | old_mysqli_num_rows(e, &rz); // we need a result here | ||
54 | php_zval_dump(" num_rows: ", &rz); | ||
55 | q->num = rz.value.lval; | ||
56 | } | ||
57 | |||
58 | static void php_mysqli_stmt_set_num_aff(struct zend_execute_data *e, | ||
59 | struct nd_db_stmt *stmt) | ||
60 | { | ||
61 | struct zval rz; | ||
62 | |||
63 | e->This.u2.num_args = 1; | ||
64 | |||
65 | //xlog(1, " calling old mysqli_stmt_affected_rows...\n"); | ||
66 | //php_zed_dump(" e: ", e); | ||
67 | old_mysqli_stmt_affected_rows(e, &rz); | ||
68 | php_zval_dump(" aff_rows: ", &rz); | ||
69 | stmt->aff = rz.value.lval; | ||
70 | |||
71 | //xlog(1, " calling old mysqli_stmt_num_rows...\n"); | ||
72 | //php_zed_dump(" e: ", e); | ||
73 | old_mysqli_stmt_num_rows(e, &rz); | ||
74 | php_zval_dump(" num_rows: ", &rz); | ||
75 | stmt->num = rz.value.lval; | ||
76 | } | ||
77 | |||
78 | static void *(*old_mysqli_connect)(struct zend_execute_data *, struct zval *); | ||
79 | static void *my_mysqli_connect(struct zend_execute_data *e, struct zval *retv) | ||
80 | { | ||
81 | void *ret; | ||
82 | unsigned int num_args, s; | ||
83 | struct zval *z; | ||
84 | struct nd_db_conn c; | ||
85 | char *host = "", *user = "", *db = "", *sock = ""; | ||
86 | int port = 0; | ||
87 | |||
88 | num_args = e->This.u2.num_args; | ||
89 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
90 | |||
91 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
92 | c.type = 'M'; | ||
93 | c.stable = 0; | ||
94 | c.ex = NULL; // TODO | ||
95 | |||
96 | if (num_args >= 1) { // host | ||
97 | z = (struct zval *) e + s; s++; | ||
98 | //php_zval_dump(" host: ", z); | ||
99 | if (z->u1.v.type == 6) // string | ||
100 | host = z->value.str->val; | ||
101 | } | ||
102 | |||
103 | if (num_args >= 2) { // user | ||
104 | z = (struct zval *) e + s; s++; | ||
105 | if (z->u1.v.type == 6) // string | ||
106 | user = z->value.str->val; | ||
107 | } | ||
108 | |||
109 | if (num_args >= 3) // pass | ||
110 | s++; | ||
111 | |||
112 | if (num_args >= 4) { // db | ||
113 | z = (struct zval *) e + s; s++; | ||
114 | if (z->u1.v.type == 6) // string | ||
115 | db = z->value.str->val; | ||
116 | } | ||
117 | |||
118 | if (num_args >= 5) { // port | ||
119 | z = (struct zval *) e + s; s++; | ||
120 | if (z->u1.v.type == 4) // long | ||
121 | port = z->value.lval; | ||
122 | } | ||
123 | |||
124 | if (num_args >= 6) { // socket | ||
125 | z = (struct zval *) e + s; s++; | ||
126 | if (z->u1.v.type == 6) // string | ||
127 | sock = z->value.str->val; | ||
128 | } | ||
129 | |||
130 | char conn_str[512]; | ||
131 | snprintf(conn_str, sizeof(conn_str), | ||
132 | "host=%s user=%s port=%d db=%s socket=%s", | ||
133 | host, user, port, db, sock); | ||
134 | c.conn_str = conn_str; | ||
135 | c.conn_str_len = strlen(c.conn_str); | ||
136 | |||
137 | ninedogs_process_db("mysqli_connect", NINEDOGS_DB_CONN_START, &c); | ||
138 | ret = old_mysqli_connect(e, retv); | ||
139 | if (!retv) { | ||
140 | xlog(1, "DEBUG: old_mysqli_connect returned retv NULL\n"); | ||
141 | return ret; | ||
142 | } | ||
143 | //php_zval_dump(" retv: ", retv); | ||
144 | // TODO: how to test for error? if (core_globals.last_error_message) { | ||
145 | |||
146 | // PHP7 returns resource, PHP8.1 returns object | ||
147 | if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) | ||
148 | c.dbh = retv->value.p; | ||
149 | else | ||
150 | c.dbh = NULL; | ||
151 | ninedogs_process_db("mysqli_connect", NINEDOGS_DB_CONN_END, &c); | ||
152 | |||
153 | return ret; | ||
154 | } | ||
155 | |||
156 | static void *(*old_mysqli_real_connect)(struct zend_execute_data *, struct zval *); | ||
157 | static void *my_mysqli_real_connect(struct zend_execute_data *e, struct zval *retv) | ||
158 | { | ||
159 | void *ret; | ||
160 | unsigned int num_args, s; | ||
161 | struct zval *z; | ||
162 | struct nd_db_conn c; | ||
163 | char *host = "", *user = "", *db = "", *sock = ""; | ||
164 | int port = 0; | ||
165 | |||
166 | num_args = e->This.u2.num_args; | ||
167 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
168 | |||
169 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
170 | c.type = 'M'; | ||
171 | c.stable = 0; | ||
172 | c.flags = 0; | ||
173 | c.ex = NULL; // TODO | ||
174 | |||
175 | if (num_args >= 1) { // dbh | ||
176 | z = (struct zval *) e + s; s++; | ||
177 | if ((z->u1.v.type == 8) || (z->u1.v.type == 9)) // object or resource | ||
178 | c.dbh = z->value.p; | ||
179 | } | ||
180 | |||
181 | if (num_args >= 2) { // host | ||
182 | z = (struct zval *) e + s; s++; | ||
183 | //php_zval_dump(" host: ", z); | ||
184 | if (z->u1.v.type == 6) // string | ||
185 | host = z->value.str->val; | ||
186 | } | ||
187 | |||
188 | if (num_args >= 3) { // user | ||
189 | z = (struct zval *) e + s; s++; | ||
190 | if (z->u1.v.type == 6) // string | ||
191 | user = z->value.str->val; | ||
192 | } | ||
193 | |||
194 | if (num_args >= 4) // pass | ||
195 | s++; | ||
196 | |||
197 | if (num_args >= 5) { // db | ||
198 | z = (struct zval *) e + s; s++; | ||
199 | if (z->u1.v.type == 6) // string | ||
200 | db = z->value.str->val; | ||
201 | } | ||
202 | |||
203 | if (num_args >= 6) { // port | ||
204 | z = (struct zval *) e + s; s++; | ||
205 | if (z->u1.v.type == 4) // long | ||
206 | port = z->value.lval; | ||
207 | } | ||
208 | |||
209 | if (num_args >= 7) { // socket | ||
210 | z = (struct zval *) e + s; s++; | ||
211 | if (z->u1.v.type == 6) // string | ||
212 | sock = z->value.str->val; | ||
213 | } | ||
214 | |||
215 | if (num_args >= 8) { // flags | ||
216 | z = (struct zval *) e + s; s++; | ||
217 | if (z->u1.v.type == 4) // long | ||
218 | c.flags = z->value.lval; | ||
219 | } | ||
220 | |||
221 | char conn_str[512]; | ||
222 | snprintf(conn_str, sizeof(conn_str), | ||
223 | "host=%s user=%s port=%d db=%s socket=%s", | ||
224 | host, user, port, db, sock); | ||
225 | c.conn_str = conn_str; | ||
226 | c.conn_str_len = strlen(c.conn_str); | ||
227 | |||
228 | ninedogs_process_db("mysqli_real_connect", NINEDOGS_DB_CONN_START, &c); | ||
229 | ret = old_mysqli_real_connect(e, retv); | ||
230 | if (!retv) { | ||
231 | xlog(1, "DEBUG: old_mysqli_real_connect returned retv NULL\n"); | ||
232 | return ret; | ||
233 | } | ||
234 | //php_zval_dump(" retv: ", retv); | ||
235 | // TODO: how to test for error? if (core_globals.last_error_message) { | ||
236 | |||
237 | // PHP7 returns resource, PHP8.1 returns object | ||
238 | if (retv->u1.v.type == 3) | ||
239 | c.ok = 1; | ||
240 | else | ||
241 | c.ok = 0; | ||
242 | ninedogs_process_db("mysqli_real_connect", NINEDOGS_DB_CONN_END, &c); | ||
243 | |||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | static void *(*old_mysqli_query)(struct zend_execute_data *, struct zval *); | ||
248 | static void *my_mysqli_query(struct zend_execute_data *e, struct zval *retv) | ||
249 | { | ||
250 | void *ret; | ||
251 | unsigned int num_args, copy_num_args, s; | ||
252 | struct zend_string *q; | ||
253 | struct zval *z, copy_para, *para; | ||
254 | char do_restore = 0; | ||
255 | struct query qs; | ||
256 | |||
257 | num_args = e->This.u2.num_args; | ||
258 | |||
259 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
260 | |||
261 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
262 | para = (struct zval *) e + s; | ||
263 | nd_db_qs_init('M', &qs); | ||
264 | |||
265 | // link | ||
266 | z = (struct zval *) e + s; s++; | ||
267 | php_zval_dump(" dbh: ", z); | ||
268 | qs.dbh = z->value.p; | ||
269 | |||
270 | // query | ||
271 | z = (struct zval *) e + s; s++; | ||
272 | q = z->value.str; | ||
273 | xlog(50, " query=%s\n", q->val); | ||
274 | qs.q = q->val; | ||
275 | qs.q_len = q->len; | ||
276 | |||
277 | // mode | ||
278 | if (num_args >= 3) { | ||
279 | z = (struct zval *) e + s; s++; | ||
280 | xlog(50, " mode=0x%lx\n", z->value.lval); | ||
281 | } | ||
282 | |||
283 | ninedogs_process_db("mysqli_query", NINEDOGS_DB_QUERY_START, &qs); | ||
284 | ret = old_mysqli_query(e, retv); | ||
285 | if (!retv) | ||
286 | return ret; | ||
287 | php_zval_dump(" retv: ", retv); | ||
288 | |||
289 | copy_num_args = num_args; | ||
290 | memcpy(©_para, para, sizeof(struct zval)); | ||
291 | |||
292 | if (retv->u1.v.type == 2) { // false | ||
293 | // TODO php_mysqli_set_error(e, dbh, &qs); // TODO is qs.res set here? | ||
294 | // TODO: do we set num and aff? | ||
295 | qs.res = (void *) 0; | ||
296 | } else if (retv->u1.v.type == 3) { // true (for queries not returning rows) | ||
297 | qs.num = qs.aff = 0; | ||
298 | qs.res = (void *) 1; | ||
299 | } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource | ||
300 | qs.res = retv->value.p; | ||
301 | php_mysqli_set_num_aff(e, retv, &qs); | ||
302 | do_restore = 1; | ||
303 | } | ||
304 | |||
305 | e->This.u2.num_args = copy_num_args; | ||
306 | if (do_restore) | ||
307 | memcpy(para, ©_para, sizeof(struct zval)); | ||
308 | |||
309 | ninedogs_process_db("mysqli_query", NINEDOGS_DB_QUERY_END, &qs); | ||
310 | |||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | static void *(*old_mysqli_close)(struct zend_execute_data *, struct zval *); | ||
315 | static void *my_mysqli_close(struct zend_execute_data *e, struct zval *retv) | ||
316 | { | ||
317 | struct nd_db_conn c; | ||
318 | |||
319 | unsigned int num_args = e->This.u2.num_args; | ||
320 | |||
321 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
322 | |||
323 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
324 | c.type = 'M'; | ||
325 | |||
326 | // link | ||
327 | struct zval *z = (struct zval *) e + s; s++; | ||
328 | php_zval_dump(" dbh: ", z); | ||
329 | c.dbh = z->value.p; | ||
330 | |||
331 | void *ret = old_mysqli_close(e, retv); | ||
332 | if (!retv) | ||
333 | return ret; | ||
334 | php_zval_dump(" retv: ", retv); | ||
335 | |||
336 | if (retv->u1.v.type == 2) { // false | ||
337 | c.ok = 0; | ||
338 | // TODO php_mysqli_set_error(e, dbh, &qs); // TODO is qs.res set here? | ||
339 | // TODO: do we set num and aff? | ||
340 | } else if (retv->u1.v.type == 3) { // true (for queries not returning rows) | ||
341 | c.ok = 1; | ||
342 | } | ||
343 | |||
344 | ninedogs_process_db("mysqli_close", NINEDOGS_DB_CONN_CLOSE, &c); | ||
345 | |||
346 | return ret; | ||
347 | } | ||
348 | |||
349 | static void *(*old_mysqli_fetch_all)(struct zend_execute_data *, struct zval *); | ||
350 | static void *my_mysqli_fetch_all(struct zend_execute_data *e, struct zval *retv) | ||
351 | { | ||
352 | struct query q; | ||
353 | |||
354 | unsigned int num_args = e->This.u2.num_args; | ||
355 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
356 | |||
357 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
358 | q.type = 'M'; | ||
359 | |||
360 | // res | ||
361 | struct zval *z = (struct zval *) e + s; s++; | ||
362 | php_zval_dump(" res: ", z); | ||
363 | q.res = z->value.p; | ||
364 | |||
365 | // mode | ||
366 | if (num_args >= 2) { | ||
367 | z = (struct zval *) e + s; s++; | ||
368 | q.mode = z->value.lval; | ||
369 | xlog(50, " mode=0x%lx\n", q.mode); | ||
370 | } else { | ||
371 | q.mode = 2; // MYSQLI_NUM | ||
372 | } | ||
373 | |||
374 | ninedogs_process_db("mysqli_fetch_all", NINEDOGS_DB_FETCH_START, &q); | ||
375 | void *ret = old_mysqli_fetch_all(e, retv); | ||
376 | if (!retv) | ||
377 | return ret; | ||
378 | php_zval_dump(" retv: ", retv); | ||
379 | |||
380 | // TODO php_mysqli_set_error(e, dbh, &qs); // TODO is qs.res set here? | ||
381 | if (retv->u1.v.type == 7) { // array | ||
382 | struct zend_array *a = retv->value.arr; | ||
383 | q.num = a->nNumUsed; | ||
384 | //q.ret = 0; | ||
385 | // TODO: do we set num and aff? Should we? We already count them in 'execute'. | ||
386 | } else if (retv->u1.v.type == 3) { // true (for queries not returning rows) | ||
387 | q.num = 0; | ||
388 | //q.ret = 1; | ||
389 | } | ||
390 | |||
391 | ninedogs_process_db("mysqli_fetch_all", NINEDOGS_DB_FETCH_END, &q); | ||
392 | |||
393 | return ret; | ||
394 | } | ||
395 | |||
396 | static void *(*old_mysqli_fetch_array)(struct zend_execute_data *, struct zval *); | ||
397 | static void *my_mysqli_fetch_array(struct zend_execute_data *e, struct zval *retv) | ||
398 | { | ||
399 | struct query q; | ||
400 | |||
401 | unsigned int num_args = e->This.u2.num_args; | ||
402 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
403 | |||
404 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
405 | q.type = 'M'; | ||
406 | |||
407 | // res | ||
408 | struct zval *z = (struct zval *) e + s; s++; | ||
409 | php_zval_dump(" res: ", z); | ||
410 | q.res = z->value.p; | ||
411 | |||
412 | // mode | ||
413 | if (num_args >= 2) { | ||
414 | z = (struct zval *) e + s; s++; | ||
415 | q.mode = z->value.lval; | ||
416 | xlog(50, " mode=0x%lx\n", q.mode); | ||
417 | } else { | ||
418 | q.mode = 3; // MYSQLI_BOTH | ||
419 | } | ||
420 | |||
421 | ninedogs_process_db("mysqli_fetch_array", NINEDOGS_DB_FETCH_START, &q); | ||
422 | void *ret = old_mysqli_fetch_array(e, retv); | ||
423 | if (!retv) | ||
424 | return ret; | ||
425 | php_zval_dump(" retv: ", retv); | ||
426 | |||
427 | if (retv->u1.v.type == 7) { // array | ||
428 | q.ret = 2; | ||
429 | } else if (retv->u1.v.type == 2) { // false - TODO set error | ||
430 | q.ret = 1; | ||
431 | } else { | ||
432 | q.ret = 0; | ||
433 | } | ||
434 | |||
435 | ninedogs_process_db("mysqli_fetch_array", NINEDOGS_DB_FETCH_END, &q); | ||
436 | |||
437 | return ret; | ||
438 | } | ||
439 | |||
440 | static void *(*old_mysqli_free_result)(struct zend_execute_data *, struct zval *); | ||
441 | static void *my_mysqli_free_result(struct zend_execute_data *e, struct zval *retv) | ||
442 | { | ||
443 | struct free_result fr; | ||
444 | |||
445 | unsigned int num_args = e->This.u2.num_args; | ||
446 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
447 | |||
448 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
449 | fr.type = 'M'; | ||
450 | |||
451 | // res | ||
452 | struct zval *z = (struct zval *) e + s; s++; | ||
453 | php_zval_dump(" res: ", z); | ||
454 | fr.res = z->value.p; | ||
455 | |||
456 | void *ret = old_mysqli_free_result(e, retv); | ||
457 | if (!retv) | ||
458 | return ret; | ||
459 | |||
460 | ninedogs_process_db("mysqli_free_result", NINEDOGS_DB_FREE_RESULT, &fr); | ||
461 | |||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | static void *(*old_mysqli_stmt_close)(struct zend_execute_data *, struct zval *); | ||
466 | static void *my_mysqli_stmt_close(struct zend_execute_data *e, struct zval *retv) | ||
467 | { | ||
468 | struct nd_db_stmt stmt; | ||
469 | |||
470 | unsigned int num_args = e->This.u2.num_args; | ||
471 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
472 | |||
473 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
474 | stmt.type = 'M'; | ||
475 | |||
476 | // stmt | ||
477 | struct zval *z = (struct zval *) e + s; s++; | ||
478 | php_zval_dump(" stmt: ", z); | ||
479 | stmt.stmt = z->value.p; | ||
480 | |||
481 | ninedogs_process_db("mysqli_stmt_close", NINEDOGS_DB_STMT_CLOSE_START, &stmt); | ||
482 | void *ret = old_mysqli_stmt_close(e, retv); | ||
483 | if (!retv) | ||
484 | return ret; | ||
485 | |||
486 | if (retv->u1.v.type == 3) { // true | ||
487 | stmt.ret = 1; | ||
488 | } else if (retv->u1.v.type == 2) { // false | ||
489 | stmt.ret = 0; | ||
490 | } | ||
491 | |||
492 | ninedogs_process_db("mysqli_stmt_close", NINEDOGS_DB_STMT_CLOSE_END, &stmt); | ||
493 | |||
494 | return ret; | ||
495 | } | ||
496 | |||
497 | static void *(*old_mysqli_stmt_execute)(struct zend_execute_data *, struct zval *); | ||
498 | static void *my_mysqli_stmt_execute(struct zend_execute_data *e, struct zval *retv) | ||
499 | { | ||
500 | struct nd_db_stmt stmt; | ||
501 | char do_restore = 0; | ||
502 | |||
503 | unsigned int num_args = e->This.u2.num_args; | ||
504 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
505 | |||
506 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
507 | nd_db_stmt_init('M', &stmt); | ||
508 | |||
509 | struct zval *para = (struct zval *) e + s; | ||
510 | |||
511 | // stmt | ||
512 | struct zval *z = (struct zval *) e + s; s++; | ||
513 | php_zval_dump(" stmt: ", z); | ||
514 | stmt.stmt = z->value.p; | ||
515 | |||
516 | if (num_args >= 2) { | ||
517 | z = (struct zval *) e + s; s++; | ||
518 | struct zend_array *za = z->value.arr; | ||
519 | zend_array_to_params_array(&stmt.params, za); | ||
520 | } | ||
521 | |||
522 | unsigned int copy_num_args = num_args; | ||
523 | struct zval copy_para; | ||
524 | memcpy(©_para, para, sizeof(struct zval)); | ||
525 | |||
526 | ninedogs_process_db("mysqli_stmt_execute", NINEDOGS_DB_EXECUTE_START, &stmt); | ||
527 | void *ret = old_mysqli_stmt_execute(e, retv); | ||
528 | if (!retv) | ||
529 | return ret; | ||
530 | |||
531 | if (retv->u1.v.type == 3) { // true | ||
532 | stmt.ret = 1; | ||
533 | php_mysqli_stmt_set_num_aff(e, &stmt); | ||
534 | do_restore = 1; | ||
535 | } else if (retv->u1.v.type == 2) { // false | ||
536 | stmt.ret = 0; | ||
537 | } | ||
538 | |||
539 | e->This.u2.num_args = copy_num_args; | ||
540 | if (do_restore) | ||
541 | memcpy(para, ©_para, sizeof(struct zval)); | ||
542 | |||
543 | ninedogs_process_db("mysqli_stmt_execute", NINEDOGS_DB_EXECUTE_END, &stmt); | ||
544 | |||
545 | return ret; | ||
546 | } | ||
547 | |||
548 | static void *(*old_mysqli_prepare)(struct zend_execute_data *, struct zval *); | ||
549 | static void *my_mysqli_prepare(struct zend_execute_data *e, struct zval *retv) | ||
550 | { | ||
551 | struct nd_db_stmt stmt; | ||
552 | |||
553 | unsigned int num_args = e->This.u2.num_args; | ||
554 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
555 | |||
556 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
557 | stmt.type = 'M'; | ||
558 | |||
559 | // link | ||
560 | struct zval *z = (struct zval *) e + s; s++; | ||
561 | php_zval_dump(" link: ", z); | ||
562 | stmt.dbh = z->value.p; | ||
563 | |||
564 | // query | ||
565 | z = (struct zval *) e + s; s++; | ||
566 | struct zend_string *xs = z->value.str; | ||
567 | xlog(50, " query=%s\n", xs->val); | ||
568 | stmt.q = xs->val; | ||
569 | stmt.q_len = xs->len; | ||
570 | |||
571 | ninedogs_process_db("mysqli_prepare", NINEDOGS_DB_PREPARE_START, &stmt); | ||
572 | void *ret = old_mysqli_prepare(e, retv); | ||
573 | if (!retv) | ||
574 | return ret; | ||
575 | php_zval_dump(" retv: ", retv); | ||
576 | |||
577 | // PHP7 returns resource, PHP8.1 returns object | ||
578 | if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { | ||
579 | stmt.stmt = retv->value.p; | ||
580 | } else if (retv->u1.v.type == 2) { // false | ||
581 | stmt.stmt = NULL; | ||
582 | } | ||
583 | |||
584 | ninedogs_process_db("mysqli_prepare", NINEDOGS_DB_PREPARE_END, &stmt); | ||
585 | |||
586 | return ret; | ||
587 | } | ||
588 | |||
589 | static void *(*old_mysqli_stmt_prepare)(struct zend_execute_data *, struct zval *); | ||
590 | static void *my_mysqli_stmt_prepare(struct zend_execute_data *e, struct zval *retv) | ||
591 | { | ||
592 | struct nd_db_stmt stmt; | ||
593 | |||
594 | unsigned int num_args = e->This.u2.num_args; | ||
595 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
596 | |||
597 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
598 | stmt.type = 'M'; | ||
599 | |||
600 | // stmt | ||
601 | struct zval *z = (struct zval *) e + s; s++; | ||
602 | php_zval_dump(" stmt: ", z); | ||
603 | stmt.stmt = z->value.p; | ||
604 | |||
605 | // query | ||
606 | z = (struct zval *) e + s; s++; | ||
607 | struct zend_string *xs = z->value.str; | ||
608 | xlog(50, " query=%s\n", xs->val); | ||
609 | stmt.q = xs->val; | ||
610 | stmt.q_len = xs->len; | ||
611 | |||
612 | ninedogs_process_db("mysqli_stmt_prepare", NINEDOGS_DB_PREPARE_START, &stmt); | ||
613 | void *ret = old_mysqli_stmt_prepare(e, retv); | ||
614 | if (!retv) | ||
615 | return ret; | ||
616 | php_zval_dump(" retv: ", retv); | ||
617 | |||
618 | if (retv->u1.v.type == 3) { // true | ||
619 | stmt.ret = 1; | ||
620 | } else if (retv->u1.v.type == 2) { // false | ||
621 | stmt.ret = 0; | ||
622 | } | ||
623 | |||
624 | ninedogs_process_db("mysqli_stmt_prepare", NINEDOGS_DB_PREPARE_END, &stmt); | ||
625 | |||
626 | return ret; | ||
627 | } | ||
628 | |||
629 | static void *(*old_mysqli_autocommit)(struct zend_execute_data *, struct zval *); | ||
630 | static void *my_mysqli_autocommit(struct zend_execute_data *e, struct zval *retv) | ||
631 | { | ||
632 | struct db_autocommit a; | ||
633 | |||
634 | unsigned int num_args = e->This.u2.num_args; | ||
635 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
636 | |||
637 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
638 | a.type = 'M'; | ||
639 | |||
640 | // link | ||
641 | struct zval *z = (struct zval *) e + s; s++; | ||
642 | a.link = z->value.p; | ||
643 | |||
644 | z = (struct zval *) e + s; s++; | ||
645 | php_zval_dump(" bool: ", z); | ||
646 | a.value = z->u1.v.type == 3; | ||
647 | |||
648 | ninedogs_process_db("mysqli_autocommit", NINEDOGS_DB_AUTOCOMMIT_START, &a); | ||
649 | void *ret = old_mysqli_autocommit(e, retv); | ||
650 | if (!retv) | ||
651 | return ret; | ||
652 | |||
653 | if (retv->u1.v.type == 3) { // true | ||
654 | a.ret = 1; | ||
655 | } else if (retv->u1.v.type == 2) { // false | ||
656 | a.ret = 0; | ||
657 | } | ||
658 | |||
659 | ninedogs_process_db("mysqli_autocommit", NINEDOGS_DB_AUTOCOMMIT_END, &a); | ||
660 | |||
661 | return ret; | ||
662 | } | ||
663 | |||
664 | static void *(*old_mysqli_stmt_bind_param)(struct zend_execute_data *, struct zval *); | ||
665 | static void *my_mysqli_stmt_bind_param(struct zend_execute_data *e, struct zval *retv) | ||
666 | { | ||
667 | struct nd_db_bind b; | ||
668 | |||
669 | unsigned int num_args = e->This.u2.num_args; | ||
670 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
671 | |||
672 | unsigned int s = (sizeof(struct zend_execute_data) | ||
673 | + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
674 | b.type = 'M'; | ||
675 | |||
676 | // stmt | ||
677 | struct zval *z = (struct zval *) e + s; s++; | ||
678 | //php_zval_dump(" stmt: ", z); | ||
679 | b.stmt = z->value.p; | ||
680 | |||
681 | // types | ||
682 | z = (struct zval *) e + s; s++; | ||
683 | struct zend_string *xs = z->value.str; | ||
684 | b.types = xs->val; | ||
685 | b.types_len = xs->len; | ||
686 | |||
687 | ninedogs_process_db("mysqli_stmt_bind_param", | ||
688 | NINEDOGS_DB_BIND_PARAM_START, &b); | ||
689 | void *ret = old_mysqli_stmt_bind_param(e, retv); | ||
690 | if (!retv) | ||
691 | return ret; | ||
692 | |||
693 | if (retv->u1.v.type == 3) { // true | ||
694 | b.ret = 1; | ||
695 | } else if (retv->u1.v.type == 2) { // false | ||
696 | b.ret = 0; | ||
697 | } | ||
698 | |||
699 | ninedogs_process_db("mysqli_stmt_bind_param", | ||
700 | NINEDOGS_DB_BIND_PARAM_END, &b); | ||
701 | |||
702 | return ret; | ||
703 | } | ||
704 | |||
705 | void php_mysql_hook(struct zend_function_entry *fe) | ||
706 | { | ||
707 | if (strcmp(fe->fname, "mysqli_autocommit") == 0) { | ||
708 | old_mysqli_autocommit = fe->handler; | ||
709 | fe->handler = my_mysqli_autocommit; | ||
710 | } else if (strcmp(fe->fname, "mysqli_close") == 0) { | ||
711 | old_mysqli_close = fe->handler; | ||
712 | fe->handler = my_mysqli_close; | ||
713 | } else if (strcmp(fe->fname, "mysqli_affected_rows") == 0) { | ||
714 | old_mysqli_affected_rows = fe->handler; | ||
715 | } else if (strcmp(fe->fname, "mysqli_connect") == 0) { | ||
716 | old_mysqli_connect = fe->handler; | ||
717 | fe->handler = my_mysqli_connect; | ||
718 | } else if (strcmp(fe->fname, "mysqli_error") == 0) { | ||
719 | old_mysqli_error = fe->handler; | ||
720 | } else if (strcmp(fe->fname, "mysqli_fetch_all") == 0) { | ||
721 | old_mysqli_fetch_all = fe->handler; | ||
722 | fe->handler = my_mysqli_fetch_all; | ||
723 | } else if (strcmp(fe->fname, "mysqli_fetch_array") == 0) { | ||
724 | old_mysqli_fetch_array = fe->handler; | ||
725 | fe->handler = my_mysqli_fetch_array; | ||
726 | } else if (strcmp(fe->fname, "mysqli_free_result") == 0) { | ||
727 | old_mysqli_free_result = fe->handler; | ||
728 | fe->handler = my_mysqli_free_result; | ||
729 | } else if (strcmp(fe->fname, "mysqli_query") == 0) { | ||
730 | old_mysqli_query = fe->handler; | ||
731 | fe->handler = my_mysqli_query; | ||
732 | } else if (strcmp(fe->fname, "mysqli_prepare") == 0) { | ||
733 | old_mysqli_prepare = fe->handler; | ||
734 | fe->handler = my_mysqli_prepare; | ||
735 | } else if (strcmp(fe->fname, "mysqli_num_rows") == 0) { | ||
736 | old_mysqli_num_rows = fe->handler; | ||
737 | } else if (strcmp(fe->fname, "mysqli_real_connect") == 0) { | ||
738 | old_mysqli_real_connect = fe->handler; | ||
739 | fe->handler = my_mysqli_real_connect; | ||
740 | } else if (strcmp(fe->fname, "mysqli_stmt_affected_rows") == 0) { | ||
741 | old_mysqli_stmt_affected_rows = fe->handler; | ||
742 | } else if (strcmp(fe->fname, "mysqli_stmt_close") == 0) { | ||
743 | old_mysqli_stmt_close = fe->handler; | ||
744 | fe->handler = my_mysqli_stmt_close; | ||
745 | } else if (strcmp(fe->fname, "mysqli_stmt_execute") == 0) { | ||
746 | old_mysqli_stmt_execute = fe->handler; | ||
747 | fe->handler = my_mysqli_stmt_execute; | ||
748 | } else if (strcmp(fe->fname, "mysqli_stmt_bind_param") == 0) { | ||
749 | old_mysqli_stmt_bind_param = fe->handler; | ||
750 | fe->handler = my_mysqli_stmt_bind_param; | ||
751 | } else if (strcmp(fe->fname, "mysqli_stmt_num_rows") == 0) { | ||
752 | old_mysqli_stmt_num_rows = fe->handler; | ||
753 | } else if (strcmp(fe->fname, "mysqli_stmt_prepare") == 0) { | ||
754 | old_mysqli_stmt_prepare = fe->handler; | ||
755 | fe->handler = my_mysqli_stmt_prepare; | ||
756 | } else { | ||
757 | //xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname); | ||
758 | } | ||
759 | } |
File agent/php-mysql.h added (mode: 100644) (index 0000000..a12d31c) | |||
1 | #include "php-core.h" | ||
2 | |||
3 | void php_mysql_hook(struct zend_function_entry *fe); | ||
4 |
File agent/php-oci.c added (mode: 100644) (index 0000000..23e76d2) | |||
1 | #include <stdio.h> | ||
2 | #include <string.h> | ||
3 | |||
4 | #include "ids.h" | ||
5 | #include "tools.h" | ||
6 | #include "php-oci.h" | ||
7 | #include "process_db.h" | ||
8 | |||
9 | |||
10 | static void *(*old_oci_bind_by_name)(struct zend_execute_data *, struct zval *); | ||
11 | static void *my_oci_bind_by_name(struct zend_execute_data *e, struct zval *retv) | ||
12 | { | ||
13 | unsigned int num_args, s; | ||
14 | struct nd_db_stmt stmt; | ||
15 | long max_length = -1, type = 0; | ||
16 | void *var; | ||
17 | |||
18 | num_args = e->This.u2.num_args; | ||
19 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
20 | |||
21 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
22 | nd_db_stmt_init('O', &stmt); | ||
23 | |||
24 | // stmt | ||
25 | struct zval *z = (struct zval *) e + s; s++; | ||
26 | php_zval_dump(" stmt: ", z); | ||
27 | stmt.stmt = z->value.p; | ||
28 | |||
29 | // param name | ||
30 | z = (struct zval *) e + s; s++; | ||
31 | struct zend_string *q = z->value.str; | ||
32 | php_zval_dump(" param: ", z); | ||
33 | char *param = q->val; | ||
34 | unsigned short param_len = q->len; | ||
35 | |||
36 | // 'var' - reference to variabile | ||
37 | z = (struct zval *) e + s; s++; | ||
38 | q = z->value.str; | ||
39 | php_zval_dump(" var: ", z); | ||
40 | var = z->value.p; | ||
41 | |||
42 | if (num_args >= 4) { | ||
43 | z = (struct zval *) e + s; s++; | ||
44 | max_length = z->value.lval; | ||
45 | } | ||
46 | |||
47 | if (num_args >= 5) { | ||
48 | z = (struct zval *) e + s; s++; | ||
49 | type = z->value.lval; | ||
50 | } | ||
51 | |||
52 | // TODO: this is still in development | ||
53 | xlog(1, "%s: stmt=%p param=[%s][%hu] var=[%p] max_length=%ld type=%ld\n", | ||
54 | __func__, stmt.stmt, param, param_len, var, max_length, type); | ||
55 | |||
56 | void *ret = old_oci_bind_by_name(e, retv); | ||
57 | if (!retv) | ||
58 | return ret; | ||
59 | |||
60 | if (retv->u1.v.type == 3) { // true | ||
61 | stmt.ret = 1; | ||
62 | } else if (retv->u1.v.type == 2) { // false | ||
63 | stmt.ret = 0; | ||
64 | } | ||
65 | |||
66 | ninedogs_process_db("oci_bind_by_name", NINEDOGS_DB_BIND_ONE_PARAM, &stmt); | ||
67 | |||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | static void *(*old_oci_close)(struct zend_execute_data *, struct zval *); | ||
72 | static void *my_oci_close(struct zend_execute_data *e, struct zval *retv) | ||
73 | { | ||
74 | unsigned int num_args, s; | ||
75 | struct nd_db_conn c; | ||
76 | |||
77 | num_args = e->This.u2.num_args; | ||
78 | //xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
79 | |||
80 | c.type = 'O'; | ||
81 | c.stable = 0; | ||
82 | c.ex = NULL; // TODO | ||
83 | if (num_args == 1) { | ||
84 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
85 | // handler, may be null | ||
86 | struct zval *z = (struct zval *) e + s; s++; | ||
87 | c.dbh = z->value.p; | ||
88 | //xlog(101, " h=%p\n", c.dbh); | ||
89 | } else { | ||
90 | c.dbh = NULL; | ||
91 | } | ||
92 | |||
93 | void *ret = old_oci_close(e, retv); | ||
94 | ninedogs_process_db("oci_close", NINEDOGS_DB_CONN_CLOSE, &c); | ||
95 | |||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | static void *(*old_oci_execute)(struct zend_execute_data *, struct zval *); | ||
100 | static void *my_oci_execute(struct zend_execute_data *e, struct zval *retv) | ||
101 | { | ||
102 | unsigned int num_args, s; | ||
103 | char do_restore = 0; | ||
104 | struct nd_db_stmt stmt; | ||
105 | |||
106 | num_args = e->This.u2.num_args; | ||
107 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
108 | |||
109 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
110 | nd_db_stmt_init('O', &stmt); | ||
111 | stmt.oci.mode = 0x00000020; // 0x00000020 = OCI_COMMIT_ON_SUCCESS | ||
112 | |||
113 | struct zval *para = (struct zval *) e + s; | ||
114 | |||
115 | // stmt | ||
116 | struct zval *z = (struct zval *) e + s; s++; | ||
117 | php_zval_dump(" stmt: ", z); | ||
118 | stmt.stmt = z->value.p; | ||
119 | |||
120 | if (num_args >= 2) { | ||
121 | z = (struct zval *) e + s; s++; | ||
122 | stmt.oci.mode = z->value.lval; | ||
123 | } | ||
124 | xlog(100, "%s: stmt=%p mode=%ld\n", __func__, stmt.stmt, stmt.oci.mode); | ||
125 | |||
126 | unsigned int copy_num_args = num_args; | ||
127 | struct zval copy_para; | ||
128 | memcpy(©_para, para, sizeof(struct zval)); | ||
129 | |||
130 | ninedogs_process_db("oci_execute", NINEDOGS_DB_EXECUTE_START, &stmt); | ||
131 | void *ret = old_oci_execute(e, retv); | ||
132 | if (!retv) | ||
133 | return ret; | ||
134 | |||
135 | if (retv->u1.v.type == 3) { // true | ||
136 | stmt.ret = 1; | ||
137 | // TODO php_oci_stmt_set_num_aff(e, &stmt); | ||
138 | do_restore = 1; | ||
139 | } else if (retv->u1.v.type == 2) { // false | ||
140 | stmt.ret = 0; | ||
141 | } | ||
142 | |||
143 | e->This.u2.num_args = copy_num_args; | ||
144 | if (do_restore) | ||
145 | memcpy(para, ©_para, sizeof(struct zval)); | ||
146 | |||
147 | ninedogs_process_db("oci_execute", NINEDOGS_DB_EXECUTE_END, &stmt); | ||
148 | |||
149 | return ret; | ||
150 | } | ||
151 | |||
152 | static void *(*old_oci_parse)(struct zend_execute_data *, struct zval *); | ||
153 | static void *my_oci_parse(struct zend_execute_data *e, struct zval *retv) | ||
154 | { | ||
155 | unsigned int num_args, s; | ||
156 | struct nd_db_stmt stmt; | ||
157 | |||
158 | num_args = e->This.u2.num_args; | ||
159 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
160 | |||
161 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
162 | nd_db_stmt_init('O', &stmt); | ||
163 | |||
164 | // dbh | ||
165 | struct zval *z = (struct zval *) e + s; s++; | ||
166 | php_zval_dump(" stmt: ", z); | ||
167 | stmt.dbh = z->value.p; | ||
168 | |||
169 | // sql | ||
170 | z = (struct zval *) e + s; s++; | ||
171 | struct zend_string *q = z->value.str; | ||
172 | stmt.q = q->val; | ||
173 | stmt.q_len = q->len; | ||
174 | |||
175 | xlog(100, "%s: dbh=%p sql=%s\n", __func__, stmt.dbh, stmt.q); | ||
176 | |||
177 | ninedogs_process_db("oci_parse", NINEDOGS_DB_PREPARE_START, &stmt); | ||
178 | void *ret = old_oci_parse(e, retv); | ||
179 | if (!retv) | ||
180 | return ret; | ||
181 | |||
182 | if (retv->u1.v.type == 2) { // false | ||
183 | stmt.stmt = NULL; | ||
184 | } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource | ||
185 | stmt.stmt = retv->value.p; | ||
186 | } | ||
187 | |||
188 | ninedogs_process_db("oci_parse", NINEDOGS_DB_PREPARE_END, &stmt); | ||
189 | |||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | static void *(*old_oci_pconnect)(struct zend_execute_data *, struct zval *); | ||
194 | static void *my_oci_pconnect(struct zend_execute_data *e, struct zval *retv) | ||
195 | { | ||
196 | unsigned int num_args, s; | ||
197 | struct zval *z; | ||
198 | struct nd_db_conn c; | ||
199 | char *user = "", *conn = "", *encoding = ""; | ||
200 | int session_mode = 0; // 0 = OCI_DEFAULT | ||
201 | |||
202 | num_args = e->This.u2.num_args; | ||
203 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
204 | |||
205 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
206 | c.type = 'O'; | ||
207 | c.stable = 0; | ||
208 | c.ex = NULL; // TODO | ||
209 | |||
210 | if (num_args >= 1) { // username | ||
211 | z = (struct zval *) e + s; s++; | ||
212 | //php_zval_dump(" host: ", z); | ||
213 | if (z->u1.v.type == 6) // string | ||
214 | user = z->value.str->val; | ||
215 | } | ||
216 | |||
217 | if (num_args >= 2) // pass | ||
218 | s++; | ||
219 | |||
220 | if (num_args >= 3) { // conn (can be null) | ||
221 | z = (struct zval *) e + s; s++; | ||
222 | if (z->u1.v.type == 6) // string | ||
223 | conn = z->value.str->val; | ||
224 | } | ||
225 | |||
226 | if (num_args >= 4) { // encoding | ||
227 | z = (struct zval *) e + s; s++; | ||
228 | if (z->u1.v.type == 4) // long | ||
229 | encoding = z->value.str->val; | ||
230 | } | ||
231 | |||
232 | if (num_args >= 5) { // session mode | ||
233 | z = (struct zval *) e + s; s++; | ||
234 | if (z->u1.v.type == 4) // long | ||
235 | session_mode = z->value.lval; | ||
236 | } | ||
237 | |||
238 | char conn_str[512]; | ||
239 | snprintf(conn_str, sizeof(conn_str), | ||
240 | "user=%s conn=[%s] encoding=%s session_mode=%d", | ||
241 | user, conn, encoding, session_mode); | ||
242 | c.conn_str = conn_str; | ||
243 | c.conn_str_len = strlen(c.conn_str); | ||
244 | |||
245 | ninedogs_process_db("oci_pconnect", NINEDOGS_DB_CONN_START, &c); | ||
246 | void *ret = old_oci_pconnect(e, retv); | ||
247 | if (!retv) { | ||
248 | xlog(0, "DEBUG: old_oci_pconnect returned retv NULL\n"); | ||
249 | return ret; | ||
250 | } | ||
251 | |||
252 | php_zval_dump(" retv: ", retv); | ||
253 | // TODO: how to test for error? if (core_globals.last_error_message) { | ||
254 | |||
255 | // PHP7 returns resource, PHP8.1 returns object | ||
256 | if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) | ||
257 | c.dbh = retv->value.p; | ||
258 | else | ||
259 | c.dbh = NULL; | ||
260 | ninedogs_process_db("oci_pconnect", NINEDOGS_DB_CONN_END, &c); | ||
261 | |||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | void php_oci_hook(struct zend_function_entry *fe) | ||
266 | { | ||
267 | if (strcmp(fe->fname, "oci_bind_by_name") == 0) { | ||
268 | old_oci_bind_by_name = fe->handler; | ||
269 | fe->handler = my_oci_bind_by_name; | ||
270 | } else if (strcmp(fe->fname, "oci_close") == 0) { | ||
271 | old_oci_close = fe->handler; | ||
272 | fe->handler = my_oci_close; | ||
273 | } else if (strcmp(fe->fname, "oci_execute") == 0) { | ||
274 | old_oci_execute = fe->handler; | ||
275 | fe->handler = my_oci_execute; | ||
276 | } else if (strcmp(fe->fname, "oci_parse") == 0) { | ||
277 | old_oci_parse = fe->handler; | ||
278 | fe->handler = my_oci_parse; | ||
279 | } else if (strcmp(fe->fname, "oci_pconnect") == 0) { | ||
280 | old_oci_pconnect = fe->handler; | ||
281 | fe->handler = my_oci_pconnect; | ||
282 | } | ||
283 | } |
File agent/php-oci.h added (mode: 100644) (index 0000000..779f8be) | |||
1 | #include "php-core.h" | ||
2 | |||
3 | void php_oci_hook(struct zend_function_entry *fe); | ||
4 |
File agent/php-pg.c added (mode: 100644) (index 0000000..23aacb1) | |||
1 | #include <string.h> | ||
2 | |||
3 | #include "ids.h" | ||
4 | #include "tools.h" | ||
5 | #include "php-pg.h" | ||
6 | #include "process_db.h" | ||
7 | |||
8 | static void *(*old_pg_last_error)(struct zend_execute_data *, struct zval *); | ||
9 | static void *my_pg_last_error(struct zend_execute_data *e, struct zval *retv) | ||
10 | { | ||
11 | void *ret; | ||
12 | unsigned int num_args; | ||
13 | |||
14 | num_args = e->This.u2.num_args; | ||
15 | xlog(1, "%s: e=%p num_args=%hu\n", | ||
16 | __func__, e, num_args); | ||
17 | |||
18 | ret = old_pg_last_error(e, retv); | ||
19 | if (!retv) | ||
20 | return ret; | ||
21 | //php_zval_dump(" retv: ", retv); | ||
22 | |||
23 | return ret; | ||
24 | } | ||
25 | |||
26 | static void *(*old_pg_close)(struct zend_execute_data *, struct zval *); | ||
27 | static void *my_pg_close(struct zend_execute_data *e, struct zval *retv) | ||
28 | { | ||
29 | void *ret; | ||
30 | unsigned int num_args, s; | ||
31 | struct zval *z; | ||
32 | struct nd_db_conn c; | ||
33 | |||
34 | num_args = e->This.u2.num_args; | ||
35 | //xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
36 | |||
37 | c.type = 'P'; | ||
38 | c.stable = 0; | ||
39 | c.ex = NULL; // TODO | ||
40 | if (num_args == 1) { | ||
41 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
42 | // handler, may be null | ||
43 | z = (struct zval *) e + s; s++; | ||
44 | c.dbh = z->value.p; | ||
45 | //xlog(101, " h=%p\n", c.dbh); | ||
46 | } else { | ||
47 | c.dbh = NULL; | ||
48 | } | ||
49 | |||
50 | ret = old_pg_close(e, retv); | ||
51 | ninedogs_process_db("pg_close", NINEDOGS_DB_CONN_CLOSE, &c); | ||
52 | |||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | static void *(*old_pg_connect)(struct zend_execute_data *, struct zval *); | ||
57 | static void *my_pg_connect(struct zend_execute_data *e, struct zval *retv) | ||
58 | { | ||
59 | void *ret; | ||
60 | unsigned int num_args, s; | ||
61 | struct zval *z; | ||
62 | struct zend_string *q; | ||
63 | struct nd_db_conn c; | ||
64 | |||
65 | num_args = e->This.u2.num_args; | ||
66 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
67 | |||
68 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
69 | c.type = 'P'; | ||
70 | c.stable = 0; | ||
71 | c.ex = NULL; // TODO | ||
72 | |||
73 | // connection string | ||
74 | z = (struct zval *) e + s; s++; | ||
75 | q = z->value.str; | ||
76 | c.conn_str = q->val; | ||
77 | c.conn_str_len = q->len; | ||
78 | //xlog(50, " conn[%u]: %s\n", c.conn_str_len, c.conn_str); | ||
79 | |||
80 | ninedogs_process_db("pg_connect", NINEDOGS_DB_CONN_START, &c); | ||
81 | ret = old_pg_connect(e, retv); | ||
82 | if (!retv) { | ||
83 | xlog(0, "DEBUG: old_pg_connect returned retv NULL\n"); | ||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | php_zval_dump(" retv: ", retv); | ||
88 | // TODO: how to test for error? if (core_globals.last_error_message) { | ||
89 | |||
90 | // PHP7 returns resource, PHP8.1 returns object | ||
91 | if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) | ||
92 | c.dbh = retv->value.p; | ||
93 | else | ||
94 | c.dbh = NULL; | ||
95 | ninedogs_process_db("pg_connect", NINEDOGS_DB_CONN_END, &c); | ||
96 | |||
97 | return ret; | ||
98 | } | ||
99 | |||
100 | static void *(*old_pg_pconnect)(struct zend_execute_data *, struct zval *); | ||
101 | static void *my_pg_pconnect(struct zend_execute_data *e, struct zval *retv) | ||
102 | { | ||
103 | void *ret; | ||
104 | unsigned int num_args, s; | ||
105 | struct zval *z; | ||
106 | struct zend_string *q; | ||
107 | struct nd_db_conn c; | ||
108 | |||
109 | num_args = e->This.u2.num_args; | ||
110 | xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
111 | |||
112 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
113 | c.type = 'P'; | ||
114 | c.stable = 0; | ||
115 | c.ex = NULL; // TODO | ||
116 | |||
117 | // connection string | ||
118 | z = (struct zval *) e + s; s++; | ||
119 | q = z->value.str; | ||
120 | c.conn_str = q->val; | ||
121 | c.conn_str_len = q->len; | ||
122 | xlog(50, " conn: %s\n", c.conn_str); | ||
123 | |||
124 | ninedogs_process_db("pg_pconnect", NINEDOGS_DB_CONN_START, &c); | ||
125 | ret = old_pg_pconnect(e, retv); | ||
126 | if (!retv) | ||
127 | return ret; | ||
128 | |||
129 | php_zval_dump(" retv: ", retv); | ||
130 | // TODO: how to test for error? if (core_globals.last_error_message) { | ||
131 | |||
132 | // PHP7 returns resource, PHP8.1 returns object | ||
133 | if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) | ||
134 | c.dbh = retv->value.p; | ||
135 | else | ||
136 | c.dbh = NULL; | ||
137 | ninedogs_process_db("pg_pconnect", NINEDOGS_DB_CONN_END, &c); | ||
138 | |||
139 | return ret; | ||
140 | } | ||
141 | |||
142 | static void *(*old_pg_affected_rows)(struct zend_execute_data *, struct zval *); | ||
143 | |||
144 | static void *(*old_pg_free_result)(struct zend_execute_data *, struct zval *); | ||
145 | static void *my_pg_free_result(struct zend_execute_data *e, struct zval *retv) | ||
146 | { | ||
147 | struct free_result fr; | ||
148 | |||
149 | unsigned int num_args = e->This.u2.num_args; | ||
150 | xlog(200, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
151 | //php_zed_dump(" e: ", e); | ||
152 | //php_zval_dump(" retv: ", retv); | ||
153 | |||
154 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
155 | fr.type = 'P'; | ||
156 | |||
157 | // res | ||
158 | struct zval *z = (struct zval *) e + s; s++; | ||
159 | fr.res = z->value.p; | ||
160 | |||
161 | void *ret = old_pg_free_result(e, retv); | ||
162 | // 'ret' is null here | ||
163 | |||
164 | if (retv->u1.v.type == 3) { // true | ||
165 | fr.ok = 1; | ||
166 | } else { | ||
167 | // TODO: can we get an error code here? | ||
168 | fr.ok = 0; | ||
169 | } | ||
170 | |||
171 | ninedogs_process_db("pg_free_result", NINEDOGS_DB_FREE_RESULT, &fr); | ||
172 | |||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | static void *(*old_pg_num_rows)(struct zend_execute_data *, struct zval *); | ||
177 | static void *my_pg_num_rows(struct zend_execute_data *e, struct zval *retv) | ||
178 | { | ||
179 | void *ret; | ||
180 | |||
181 | //unsigned int num_args = e->This.u2.num_args; | ||
182 | //xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
183 | //php_zed_dump(" e: ", e); | ||
184 | //php_zval_dump(" retv: ", retv); | ||
185 | |||
186 | ret = old_pg_num_rows(e, retv); | ||
187 | if (!retv) | ||
188 | return ret; | ||
189 | |||
190 | //php_zval_dump(" retv: ", retv); | ||
191 | |||
192 | return ret; | ||
193 | } | ||
194 | |||
195 | static void php_pg_set_last_error(struct zend_execute_data *e, | ||
196 | struct zval *dbh, struct query *q) | ||
197 | { | ||
198 | struct zval rz; | ||
199 | |||
200 | e->This.u2.num_args = dbh ? 1 : 0; | ||
201 | if (dbh) | ||
202 | php_set_para(e, 0, dbh); | ||
203 | |||
204 | // TODO: we need also the numeric representation of the error! | ||
205 | xlog(50, " calling pg_last_error...\n"); | ||
206 | old_pg_last_error(e, &rz); | ||
207 | //xlog(1, " pg_last_error returned %p; type=%s value=%s\n", | ||
208 | // tr, php_get_type(&rz), php_get_value(&rz)); | ||
209 | |||
210 | if (rz.u1.v.type == 6) { // string | ||
211 | q->err = rz.value.str->val; | ||
212 | q->err_len = rz.value.str->len; | ||
213 | xlog(40, "%s: set error to [%s]\n", __func__, q->err); | ||
214 | } else { | ||
215 | q->err = "?"; | ||
216 | q->err_len = 1; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | static void php_pg_set_num_aff(struct zend_execute_data *e, struct zval *res, | ||
221 | struct query *q) | ||
222 | { | ||
223 | struct zval rz; | ||
224 | |||
225 | e->This.u2.num_args = 1; | ||
226 | |||
227 | php_set_para(e, 0, res); | ||
228 | |||
229 | xlog(100, " calling old pg_num_rows...\n"); | ||
230 | //php_zed_dump(" e: ", e); | ||
231 | old_pg_num_rows(e, &rz); | ||
232 | php_zval_dump(" rz: ", &rz); | ||
233 | q->num = rz.value.lval; | ||
234 | |||
235 | xlog(100, " calling old pg_affected_rows...\n"); | ||
236 | //php_zed_dump(" e: ", e); | ||
237 | old_pg_affected_rows(e, &rz); | ||
238 | php_zval_dump(" rz: ", &rz); | ||
239 | q->aff = rz.value.lval; | ||
240 | } | ||
241 | |||
242 | static void *(*old_pg_query)(struct zend_execute_data *, struct zval *); | ||
243 | static void *my_pg_query(struct zend_execute_data *e, struct zval *retv) | ||
244 | { | ||
245 | void *ret; | ||
246 | unsigned int num_args, copy_num_args, s; | ||
247 | struct zend_string *q; | ||
248 | struct zval *dbh = NULL, *z, copy_para, *para; | ||
249 | char do_restore = 0; | ||
250 | struct query qs; | ||
251 | |||
252 | num_args = e->This.u2.num_args; | ||
253 | |||
254 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
255 | |||
256 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
257 | para = (struct zval *) e + s; | ||
258 | nd_db_qs_init('P', &qs); | ||
259 | |||
260 | if (num_args == 2) { | ||
261 | // link | ||
262 | z = (struct zval *) e + s; s++; | ||
263 | //php_zval_dump(" dbh: ", z); | ||
264 | qs.dbh = z->value.p; | ||
265 | } else { | ||
266 | qs.dbh = NULL; | ||
267 | } | ||
268 | |||
269 | // query | ||
270 | z = (struct zval *) e + s; s++; | ||
271 | q = z->value.str; | ||
272 | xlog(50, " query=%s\n", q->val); | ||
273 | qs.q = q->val; | ||
274 | qs.q_len = q->len; | ||
275 | |||
276 | ninedogs_process_db("pg_query", NINEDOGS_DB_QUERY_START, &qs); | ||
277 | ret = old_pg_query(e, retv); | ||
278 | if (!retv) | ||
279 | return ret; | ||
280 | |||
281 | xlog(100, " old %s returned type=%s value=%s\n", | ||
282 | __func__, php_get_type(retv), php_get_value(retv)); | ||
283 | |||
284 | copy_num_args = num_args; | ||
285 | memcpy(©_para, para, sizeof(struct zval)); | ||
286 | |||
287 | if (retv->u1.v.type == 2) { // false | ||
288 | php_pg_set_last_error(e, dbh, &qs); // TODO is qs.res set here? | ||
289 | } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource | ||
290 | qs.res = retv->value.p; | ||
291 | php_pg_set_num_aff(e, retv, &qs); | ||
292 | do_restore = 1; | ||
293 | } | ||
294 | |||
295 | e->This.u2.num_args = copy_num_args; | ||
296 | if (do_restore) | ||
297 | memcpy(para, ©_para, sizeof(struct zval)); | ||
298 | |||
299 | ninedogs_process_db("pg_query", NINEDOGS_DB_QUERY_END, &qs); | ||
300 | |||
301 | return ret; | ||
302 | } | ||
303 | |||
304 | static void *(*old_pg_send_query)(struct zend_execute_data *, struct zval *); | ||
305 | static void *my_pg_send_query(struct zend_execute_data *e, struct zval *retv) | ||
306 | { | ||
307 | void *ret; | ||
308 | unsigned int num_args, s; | ||
309 | struct zend_string *q; | ||
310 | struct zval *dbh = NULL, *z; | ||
311 | struct query qs; | ||
312 | |||
313 | num_args = e->This.u2.num_args; | ||
314 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
315 | |||
316 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
317 | nd_db_qs_init('P', &qs); | ||
318 | |||
319 | // link | ||
320 | z = (struct zval *) e + s; s++; | ||
321 | php_zval_dump(" dbh: ", z); | ||
322 | qs.dbh = z->value.p; | ||
323 | |||
324 | // query | ||
325 | z = (struct zval *) e + s; s++; | ||
326 | q = z->value.str; | ||
327 | qs.q = q->val; | ||
328 | qs.q_len = q->len; | ||
329 | xlog(100, " query=%s\n", qs.q); | ||
330 | |||
331 | ninedogs_process_db("pg_send_query", NINEDOGS_DB_QUERY_START, &qs); | ||
332 | ret = old_pg_send_query(e, retv); | ||
333 | if (!retv) | ||
334 | return ret; | ||
335 | |||
336 | xlog(101, " old %s returned type=%s value=%s\n", | ||
337 | __func__, php_get_type(retv), php_get_value(retv)); | ||
338 | |||
339 | qs.res = NULL; | ||
340 | if ((retv->u1.v.type == 2) || (retv->u1.v.type == 4)) { // false or int | ||
341 | php_pg_set_last_error(e, dbh, &qs); | ||
342 | } else if (retv->u1.v.type == 3) { // true = success | ||
343 | qs.num = qs.aff = 0; | ||
344 | qs.res = (void *) 1; // signal ok | ||
345 | } | ||
346 | |||
347 | ninedogs_process_db("pg_send_query", NINEDOGS_DB_QUERY_END, &qs); | ||
348 | |||
349 | return ret; | ||
350 | } | ||
351 | |||
352 | // TODO: not clear if on PHP 7 the parameter could be null | ||
353 | static void *(*old_pg_get_result)(struct zend_execute_data *, struct zval *); | ||
354 | static void *my_pg_get_result(struct zend_execute_data *e, struct zval *retv) | ||
355 | { | ||
356 | void *ret; | ||
357 | unsigned int num_args, copy_num_args, s; | ||
358 | struct zval *dbh = NULL, *z, copy_para, *para; | ||
359 | char do_restore = 0; | ||
360 | struct query qs; | ||
361 | |||
362 | num_args = e->This.u2.num_args; | ||
363 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
364 | |||
365 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
366 | para = (struct zval *) e + s; | ||
367 | nd_db_qs_init('P', &qs); | ||
368 | |||
369 | // link | ||
370 | z = (struct zval *) e + s; s++; | ||
371 | //php_zval_dump(" dbh: ", z); | ||
372 | qs.dbh = z->value.p; | ||
373 | |||
374 | ninedogs_process_db("pg_get_result", NINEDOGS_DB_QUERY_START, &qs); | ||
375 | ret = old_pg_get_result(e, retv); | ||
376 | if (!retv) | ||
377 | return ret; | ||
378 | |||
379 | xlog(100, " old %s returned type=%s value=%s\n", | ||
380 | __func__, php_get_type(retv), php_get_value(retv)); | ||
381 | |||
382 | copy_num_args = num_args; | ||
383 | memcpy(©_para, para, sizeof(struct zval)); | ||
384 | |||
385 | if (retv->u1.v.type == 2) { // false | ||
386 | php_pg_set_last_error(e, dbh, &qs); | ||
387 | } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource | ||
388 | qs.err = NULL; | ||
389 | qs.res = retv->value.p; | ||
390 | php_pg_set_num_aff(e, retv, &qs); | ||
391 | do_restore = 1; | ||
392 | } | ||
393 | |||
394 | e->This.u2.num_args = copy_num_args; | ||
395 | if (do_restore) | ||
396 | memcpy(para, ©_para, sizeof(struct zval)); | ||
397 | |||
398 | ninedogs_process_db("pg_get_result", NINEDOGS_DB_QUERY_END, &qs); | ||
399 | |||
400 | return ret; | ||
401 | } | ||
402 | |||
403 | static void *(*old_pg_query_params)(struct zend_execute_data *, struct zval *); | ||
404 | static void *my_pg_query_params(struct zend_execute_data *e, struct zval *retv) | ||
405 | { | ||
406 | void *ret; | ||
407 | unsigned int num_args, s; | ||
408 | struct zval copy_para, *para, *z; | ||
409 | struct zend_string *q; | ||
410 | unsigned int copy_num_args; | ||
411 | void *dbh = NULL; | ||
412 | char do_restore = 0; | ||
413 | struct query qs; | ||
414 | |||
415 | num_args = e->This.u2.num_args; | ||
416 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
417 | //php_zed_dump(" e0: ", e); | ||
418 | //php_zval_dump(" retv0: ", retv); | ||
419 | |||
420 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
421 | para = (struct zval *) e + s; | ||
422 | qs.type = 'P'; | ||
423 | |||
424 | if (num_args == 3) { | ||
425 | // link | ||
426 | z = (struct zval *) e + s; s++; | ||
427 | qs.dbh = z->value.p; | ||
428 | } else { | ||
429 | qs.dbh = NULL; | ||
430 | } | ||
431 | |||
432 | // query | ||
433 | z = (struct zval *) e + s; s++; | ||
434 | q = z->value.str; | ||
435 | qs.q = q->val; | ||
436 | qs.q_len = q->len; | ||
437 | |||
438 | // params (array) | ||
439 | z = (struct zval *) e + s; s++; | ||
440 | struct zend_array *za = z->value.arr; | ||
441 | zend_array_to_params_array(&qs.params, za); | ||
442 | |||
443 | ninedogs_process_db("pg_query_params", NINEDOGS_DB_QUERY_START, &qs); | ||
444 | ret = old_pg_query_params(e, retv); | ||
445 | //xlog(200, " old %s: type=%s value=%s\n", | ||
446 | // __func__, php_get_type(retv), php_get_value(retv)); | ||
447 | //php_zed_dump(" e1: ", e); | ||
448 | //php_zval_dump(" retv after calling old func: ", retv); | ||
449 | |||
450 | copy_num_args = e->This.u2.num_args; | ||
451 | memcpy(©_para, para, sizeof(struct zval)); | ||
452 | |||
453 | if (retv->u1.v.type == 2) { // false | ||
454 | php_pg_set_last_error(e, dbh, &qs); | ||
455 | } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource | ||
456 | qs.res = retv->value.p; | ||
457 | php_pg_set_num_aff(e, retv, &qs); | ||
458 | do_restore = 1; | ||
459 | } | ||
460 | |||
461 | //php_zval_dump(" retv before ret: ", retv); | ||
462 | |||
463 | e->This.u2.num_args = copy_num_args; | ||
464 | if (do_restore) | ||
465 | memcpy(para, ©_para, sizeof(struct zval)); | ||
466 | |||
467 | ninedogs_process_db("pg_query_params", NINEDOGS_DB_QUERY_END, &qs); | ||
468 | |||
469 | return ret; | ||
470 | } | ||
471 | |||
472 | static void *(*old_pg_send_query_params)(struct zend_execute_data *, struct zval *); | ||
473 | static void *my_pg_send_query_params(struct zend_execute_data *e, struct zval *retv) | ||
474 | { | ||
475 | void *ret; | ||
476 | unsigned int s; | ||
477 | struct zval *z; | ||
478 | struct zval *dbh; | ||
479 | struct zend_string *q; | ||
480 | struct query qs; | ||
481 | |||
482 | unsigned int num_args = e->This.u2.num_args; | ||
483 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
484 | //php_zed_dump(" e0: ", e); | ||
485 | //php_zval_dump(" retv0: ", retv); | ||
486 | |||
487 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
488 | qs.type = 'P'; | ||
489 | |||
490 | // link | ||
491 | dbh = (struct zval *) e + s; s++; | ||
492 | qs.dbh = dbh->value.p; | ||
493 | |||
494 | // query | ||
495 | z = (struct zval *) e + s; s++; | ||
496 | q = z->value.str; | ||
497 | qs.q = q->val; | ||
498 | qs.q_len = q->len; | ||
499 | |||
500 | // params (array) | ||
501 | z = (struct zval *) e + s; s++; | ||
502 | struct zend_array *za = z->value.arr; | ||
503 | zend_array_to_params_array(&qs.params, za); | ||
504 | |||
505 | ninedogs_process_db("pg_send_query_params", NINEDOGS_DB_QUERY_START, &qs); | ||
506 | ret = old_pg_send_query_params(e, retv); | ||
507 | //xlog(200, " old %s: type=%s value=%s\n", | ||
508 | // __func__, php_get_type(retv), php_get_value(retv)); | ||
509 | //php_zed_dump(" e1: ", e); | ||
510 | //php_zval_dump(" retv after calling old func: ", retv); | ||
511 | |||
512 | qs.res = NULL; | ||
513 | if ((retv->u1.v.type == 2) || (retv->u1.v.type == 4)) { // false or int (probably 0) | ||
514 | php_pg_set_last_error(e, dbh, &qs); | ||
515 | } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource | ||
516 | qs.num = qs.aff = 0; | ||
517 | qs.res = (void *) 1; // signal ok | ||
518 | } | ||
519 | |||
520 | ninedogs_process_db("pg_send_query_params", NINEDOGS_DB_QUERY_END, &qs); | ||
521 | |||
522 | return ret; | ||
523 | } | ||
524 | |||
525 | void php_pg_hook(struct zend_function_entry *fe) | ||
526 | { | ||
527 | if (strcmp(fe->fname, "pg_close") == 0) { | ||
528 | old_pg_close = fe->handler; | ||
529 | fe->handler = my_pg_close; | ||
530 | } else if (strcmp(fe->fname, "pg_connect") == 0) { | ||
531 | old_pg_connect = fe->handler; | ||
532 | fe->handler = my_pg_connect; | ||
533 | } else if (strcmp(fe->fname, "pg_pconnect") == 0) { | ||
534 | old_pg_pconnect = fe->handler; | ||
535 | fe->handler = my_pg_pconnect; | ||
536 | } else if (strcmp(fe->fname, "pg_num_rows") == 0) { | ||
537 | old_pg_num_rows = fe->handler; | ||
538 | fe->handler = my_pg_num_rows; | ||
539 | } else if (strcmp(fe->fname, "pg_affected_rows") == 0) { | ||
540 | old_pg_affected_rows = fe->handler; | ||
541 | } else if (strcmp(fe->fname, "pg_free_result") == 0) { | ||
542 | old_pg_free_result = fe->handler; | ||
543 | fe->handler = my_pg_free_result; | ||
544 | } else if (strcmp(fe->fname, "pg_query") == 0) { | ||
545 | old_pg_query = fe->handler; | ||
546 | fe->handler = my_pg_query; | ||
547 | } else if (strcmp(fe->fname, "pg_send_query") == 0) { | ||
548 | old_pg_send_query = fe->handler; | ||
549 | fe->handler = my_pg_send_query; | ||
550 | } else if (strcmp(fe->fname, "pg_query_params") == 0) { | ||
551 | old_pg_query_params = fe->handler; | ||
552 | fe->handler = my_pg_query_params; | ||
553 | } else if (strcmp(fe->fname, "pg_send_query_params") == 0) { | ||
554 | old_pg_send_query_params = fe->handler; | ||
555 | fe->handler = my_pg_send_query_params; | ||
556 | } else if (strcmp(fe->fname, "pg_last_error") == 0) { | ||
557 | old_pg_last_error = fe->handler; | ||
558 | fe->handler = my_pg_last_error; | ||
559 | } else if (strcmp(fe->fname, "pg_get_result") == 0) { | ||
560 | old_pg_get_result = fe->handler; | ||
561 | fe->handler = my_pg_get_result; | ||
562 | } else { | ||
563 | //xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname); | ||
564 | } | ||
565 | } |
File agent/php-pg.h added (mode: 100644) (index 0000000..a460cec) | |||
1 | #include "php-core.h" | ||
2 | |||
3 | void php_pg_hook(struct zend_function_entry *fe); | ||
4 |
File agent/php.TODO changed (mode: 100644) (index ca81503..b31b4f2) | |||
1 | 1 | [ ] We need to fill qs->err_code using PGSQL_DIAG_SQLSTATE. | [ ] We need to fill qs->err_code using PGSQL_DIAG_SQLSTATE. |
2 | 2 | [ ] Capture pg_close ($db is optional). | [ ] Capture pg_close ($db is optional). |
3 | [ ] MySQL: decode parameters for 'mysqli_stmt_bind_param'. | ||
3 | 4 | [ ] | [ ] |
File agent/php.c changed (mode: 100644) (index b6613e0..231485b) | |||
38 | 38 | #include <netdb.h> | #include <netdb.h> |
39 | 39 | #include <ctype.h> | #include <ctype.h> |
40 | 40 | ||
41 | #include "ids.h" | ||
42 | #include "php.h" | ||
41 | //#include "ids.h" | ||
43 | 42 | #include "tools.h" | #include "tools.h" |
44 | #include "ctools.h" | ||
45 | #include "process_db.h" | ||
46 | #include "process_url.h" | ||
47 | #include "curl.h" | ||
48 | |||
49 | |||
50 | extern void *(*old_malloc)(size_t size); | ||
51 | extern void (*old_free)(void *p); | ||
52 | |||
53 | |||
54 | struct zend_function_entry | ||
55 | { | ||
56 | const char *fname; | ||
57 | void *handler; | ||
58 | void *arg_info; | ||
59 | unsigned int num_args; | ||
60 | unsigned int flags; | ||
61 | }; | ||
62 | |||
63 | struct zend_module_entry | ||
64 | { | ||
65 | unsigned short size; | ||
66 | unsigned short pad1; | ||
67 | unsigned int zend_api; | ||
68 | unsigned char zend_debug; | ||
69 | unsigned char zts; | ||
70 | unsigned char pad2[6]; | ||
71 | void *ini_entry; | ||
72 | void *deps; | ||
73 | const char *name; | ||
74 | struct zend_function_entry *functions; | ||
75 | void *junk[5]; | ||
76 | const char *version; | ||
77 | size_t globals_size; | ||
78 | void *globals; | ||
79 | void *globals_ctor; | ||
80 | void *globals_dtor; | ||
81 | void *post_deactivate_func; | ||
82 | int module_started; | ||
83 | unsigned char type; | ||
84 | unsigned char pad3[3]; | ||
85 | void *handle; | ||
86 | int module_number; | ||
87 | int pad4; | ||
88 | const char *build_id; | ||
89 | }; | ||
90 | |||
91 | typedef long zend_long; | ||
92 | typedef unsigned long zend_ulong; | ||
93 | |||
94 | struct zend_refcounted_h | ||
95 | { | ||
96 | unsigned int refcount; | ||
97 | unsigned int type_info; | ||
98 | }; | ||
99 | |||
100 | struct zend_resource | ||
101 | { | ||
102 | struct zend_refcounted_h gc; | ||
103 | int handle; | ||
104 | int type; | ||
105 | void *ptr; | ||
106 | }; | ||
107 | |||
108 | struct zend_string | ||
109 | { | ||
110 | struct zend_refcounted_h gc; | ||
111 | zend_ulong hash; | ||
112 | size_t len; | ||
113 | char val[1]; | ||
114 | char pad1[7]; | ||
115 | }; | ||
116 | |||
117 | struct zend_array | ||
118 | { | ||
119 | struct zend_refcounted_h gc; | ||
120 | union { | ||
121 | struct { | ||
122 | unsigned char flags; | ||
123 | unsigned char _unused; | ||
124 | unsigned char nIteratorsCount; | ||
125 | unsigned char _unused2; | ||
126 | } v; | ||
127 | unsigned int flags; | ||
128 | } u; | ||
129 | unsigned int nTableMask; | ||
130 | union { | ||
131 | uint32_t *arHash; | ||
132 | struct Bucket *arData; | ||
133 | struct zval *arPacked; | ||
134 | }; | ||
135 | unsigned int nNumUsed; | ||
136 | unsigned int nNumOfElements; | ||
137 | unsigned int nTableSize; | ||
138 | unsigned int nInternalPointer; | ||
139 | zend_long nNextFreeElement; | ||
140 | void *dtor; | ||
141 | }; | ||
142 | |||
143 | union zend_value | ||
144 | { | ||
145 | zend_long lval; | ||
146 | double dval; | ||
147 | void *p; | ||
148 | struct zend_string *str; | ||
149 | struct zend_array *arr; | ||
150 | struct zend_resource *res; | ||
151 | struct zend_reference *ref; | ||
152 | struct zval *zv; | ||
153 | struct { | ||
154 | unsigned int w1; | ||
155 | unsigned int w2; | ||
156 | } ww; | ||
157 | }; | ||
158 | |||
159 | struct zval | ||
160 | { | ||
161 | union zend_value value; | ||
162 | union { | ||
163 | unsigned int type_info; | ||
164 | struct { | ||
165 | unsigned char type; | ||
166 | unsigned char type_flags; | ||
167 | union { | ||
168 | unsigned short extra; | ||
169 | } u; | ||
170 | } v; | ||
171 | } u1; | ||
172 | union { | ||
173 | unsigned int num_args; | ||
174 | } u2; | ||
175 | }; | ||
176 | |||
177 | struct Bucket | ||
178 | { | ||
179 | struct zval val; | ||
180 | zend_ulong h; | ||
181 | struct zend_string *key; | ||
182 | }; | ||
183 | |||
184 | struct zend_reference | ||
185 | { | ||
186 | struct zend_refcounted_h gc; | ||
187 | struct zval val; | ||
188 | void *sources; | ||
189 | }; | ||
190 | |||
191 | struct zend_execute_data | ||
192 | { | ||
193 | void *opline; | ||
194 | struct zend_execute_data *call; | ||
195 | struct zval *return_value; | ||
196 | void *func; | ||
197 | struct zval This; | ||
198 | struct zend_execute_data *prev; | ||
199 | struct zend_array *symbol_table; | ||
200 | void **runtime_cache; | ||
201 | struct zend_array *extra_named_params; | ||
202 | }; | ||
203 | |||
204 | struct TODOpgsql_link_handle | ||
205 | { | ||
206 | void *conn; // PGconn | ||
207 | struct zend_string *hash; | ||
208 | struct HashTable *notices; | ||
209 | unsigned char persistent; // bool | ||
210 | //zend_object std; | ||
211 | unsigned char pad1[7]; | ||
212 | }; | ||
213 | |||
214 | static char *php_get_value(const struct zval *z) | ||
215 | { | ||
216 | static char ret[4096]; | ||
217 | const struct zval *next; | ||
218 | |||
219 | if (!z) | ||
220 | return "NULL"; | ||
221 | |||
222 | switch (z->u1.v.type) { | ||
223 | case 0: return ""; | ||
224 | case 1: return ""; | ||
225 | case 2: return ""; | ||
226 | case 3: return ""; | ||
227 | case 4: snprintf(ret, sizeof(ret), "%ld", z->value.lval); return ret; | ||
228 | case 5: snprintf(ret, sizeof(ret), "%f", z->value.dval); return ret; | ||
229 | case 6: | ||
230 | struct zend_string *zs = z->value.str; | ||
231 | return zs->val; | ||
232 | case 8: | ||
233 | snprintf(ret, sizeof(ret), "%p", z->value.p); return ret; | ||
234 | case 9: | ||
235 | snprintf(ret, sizeof(ret), "%p", z->value.p); return ret; | ||
236 | case 10: | ||
237 | next = &z->value.ref->val; | ||
238 | return php_get_value(next); | ||
239 | case 12: | ||
240 | next = z->value.zv; | ||
241 | return php_get_value(next); | ||
242 | default: | ||
243 | snprintf(ret, sizeof(ret), "?%hhu: %p", | ||
244 | z->u1.v.type, z->value.str); return ret; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | static char *php_get_type(const struct zval *z) | ||
249 | { | ||
250 | static char s[8]; | ||
251 | |||
252 | if (!z) | ||
253 | return "NULL"; | ||
254 | |||
255 | switch (z->u1.v.type) { | ||
256 | case 0: return "undef"; | ||
257 | case 1: return "null"; | ||
258 | case 2: return "false"; | ||
259 | case 3: return "true"; | ||
260 | case 4: return "long"; | ||
261 | case 5: return "double"; | ||
262 | case 6: return "string"; | ||
263 | case 7: return "array"; | ||
264 | case 8: return "object"; | ||
265 | case 9: return "resource"; | ||
266 | case 10: return "ref"; | ||
267 | case 12: return "indirect"; | ||
268 | default: sprintf(s, "?%hhu", z->u1.v.type); return s; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | static void php_zval_dump_buf(char *buf, const size_t size, | ||
273 | const char *prefix, const struct zval *z) | ||
274 | { | ||
275 | if (!z) { | ||
276 | snprintf(buf, size, "zval is null"); | ||
277 | return; | ||
278 | } | ||
279 | |||
280 | snprintf(buf, size, "%s%p: type=%s value=[%s] type_flags=%hhu extra=%hu num_args=%u", | ||
281 | prefix, z, php_get_type(z), php_get_value(z), | ||
282 | z->u1.v.type_flags, | ||
283 | z->u1.v.u.extra, z->u2.num_args); | ||
284 | } | ||
285 | |||
286 | static void php_zval_dump(const char *prefix, const struct zval *z) | ||
287 | { | ||
288 | char s[4096]; | ||
289 | |||
290 | php_zval_dump_buf(s, sizeof(s), prefix, z); | ||
291 | xlog(100, "%s\n", s); | ||
292 | } | ||
293 | |||
294 | static void php_zed_dump(const char *prefix, struct zend_execute_data *p) | ||
295 | { | ||
296 | unsigned int num_args, s, i; | ||
297 | struct zval *z; | ||
298 | char x[64]; | ||
299 | |||
300 | if (!p) { | ||
301 | xlog(100, "%szed is null!\n", prefix); | ||
302 | return; | ||
303 | } | ||
304 | |||
305 | num_args = p->This.u2.num_args; | ||
306 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
307 | dump(100, "zed", p, sizeof(struct zval) * (s + num_args)); | ||
308 | |||
309 | xlog(100, "%szed: p=%p num_args=%hu return_value=%p\n", | ||
310 | prefix, p, num_args, p->return_value); | ||
311 | //php_zval_dump(prefix, p->return_value); | ||
312 | snprintf(x, sizeof(x), "%s This: ", prefix); | ||
313 | php_zval_dump(x, &p->This); | ||
314 | |||
315 | for (i = 0; i < num_args; i++) { | ||
316 | char zs[1024]; | ||
317 | |||
318 | z = (struct zval *) p + s; s++; | ||
319 | php_zval_dump_buf(zs, sizeof(zs), "", z); | ||
320 | xlog(100, "%s para %u: %s\n", prefix, i, zs); | ||
321 | } | ||
322 | } | ||
323 | |||
324 | // TODO this is really not related to parameters - rename it | ||
325 | // this is obsolete. Use 'zend_to_binary' | ||
326 | static void zend_array_to_params_array(struct params_array *p, struct zend_array *za) | ||
327 | { | ||
328 | unsigned int i = 0; | ||
329 | |||
330 | xlog(100, " %s: nTableMask=0x%x nNumUsed=%u nNumOfElements=%u nTableSize=%u" | ||
331 | " nInternalPointer=%u flags=0x%x[%s]\n", | ||
332 | __func__, | ||
333 | za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize, | ||
334 | za->nInternalPointer, za->u.flags, za->u.flags & 4 ? "packed" : ""); | ||
335 | |||
336 | p->len = za->nNumUsed; | ||
337 | if (p->len > ND_PARAMS_MAX) | ||
338 | p->len = ND_PARAMS_MAX; | ||
339 | |||
340 | struct Bucket *bs = za->arData, *be = za->arData + za->nNumUsed; | ||
341 | for (; bs != be; bs++) { | ||
342 | struct zval *_z = &bs->val; | ||
343 | |||
344 | if (_z && (_z->u1.v.type == 12)) // 12=IS_INDIRECT | ||
345 | _z = _z->value.zv; | ||
346 | |||
347 | if (_z->u1.v.type == 0 /*IS_UNDEF*/) { | ||
348 | xlog(101, " para h=%lu: type undef\n", bs->h); | ||
349 | continue; | ||
350 | } | ||
351 | |||
352 | if (_z->u1.v.type == 10) { // REFERENCE | ||
353 | xlog(101, " is a reference!\n"); | ||
354 | _z = &_z->value.ref->val; | ||
355 | } | ||
356 | |||
357 | struct zend_string *zs = bs->key; | ||
358 | xlog(101, " para: bs=%p h=%lu key=[%p] type %s: val: %s\n", | ||
359 | bs, bs->h, zs, php_get_type(_z), php_get_value(_z)); | ||
360 | |||
361 | if (_z->u1.v.type == 1) { | ||
362 | p->list[i].type = ND_TYPE_NULL; | ||
363 | } else if (_z->u1.v.type == 2) { | ||
364 | p->list[i].type = ND_TYPE_STRING; | ||
365 | p->list[i].str = "false"; | ||
366 | p->list[i].length = 5; | ||
367 | } else if (_z->u1.v.type == 3) { | ||
368 | p->list[i].type = ND_TYPE_STRING; | ||
369 | p->list[i].str = "true"; | ||
370 | p->list[i].length = 4; | ||
371 | } else if (_z->u1.v.type == 4) { | ||
372 | p->list[i].type = ND_TYPE_LONG; | ||
373 | p->list[i].l = _z->value.lval; | ||
374 | } else if (_z->u1.v.type == 5) { | ||
375 | p->list[i].type = ND_TYPE_DOUBLE; | ||
376 | p->list[i].d = _z->value.dval; | ||
377 | } else if (_z->u1.v.type == 6) { | ||
378 | p->list[i].type = ND_TYPE_STRING; | ||
379 | struct zend_string *zs = _z->value.str; | ||
380 | p->list[i].str = zs->val; | ||
381 | p->list[i].length = zs->len; | ||
382 | } else { | ||
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); | ||
386 | } | ||
387 | |||
388 | i++; | ||
389 | if (i == p->len) | ||
390 | break; | ||
391 | } | ||
392 | } | ||
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 | |||
498 | static void php_set_para(struct zend_execute_data *e, const unsigned int i, | ||
499 | const struct zval *para) | ||
500 | { | ||
501 | unsigned int s; | ||
502 | struct zval *dst; | ||
503 | |||
504 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
505 | dst = (struct zval *) e + s + i; | ||
506 | memcpy(dst, para, sizeof(struct zval)); | ||
507 | } | ||
508 | |||
509 | |||
510 | static void *(*old_pg_last_error)(struct zend_execute_data *, struct zval *); | ||
511 | static void *my_pg_last_error(struct zend_execute_data *e, struct zval *retv) | ||
512 | { | ||
513 | void *ret; | ||
514 | unsigned int num_args; | ||
515 | |||
516 | num_args = e->This.u2.num_args; | ||
517 | xlog(1, "%s: e=%p num_args=%hu\n", | ||
518 | __func__, e, num_args); | ||
519 | |||
520 | ret = old_pg_last_error(e, retv); | ||
521 | if (!retv) | ||
522 | return ret; | ||
523 | //php_zval_dump(" retv: ", retv); | ||
524 | |||
525 | return ret; | ||
526 | } | ||
527 | |||
528 | static void *(*old_pg_close)(struct zend_execute_data *, struct zval *); | ||
529 | static void *my_pg_close(struct zend_execute_data *e, struct zval *retv) | ||
530 | { | ||
531 | void *ret; | ||
532 | unsigned int num_args, s; | ||
533 | struct zval *z; | ||
534 | struct conn cs; | ||
535 | |||
536 | num_args = e->This.u2.num_args; | ||
537 | //xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
538 | |||
539 | cs.type = 'P'; | ||
540 | if (num_args == 1) { | ||
541 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
542 | // handler, may be null | ||
543 | z = (struct zval *) e + s; s++; | ||
544 | cs.dbh = z->value.p; | ||
545 | //xlog(101, " h=%p\n", cs.dbh); | ||
546 | } else { | ||
547 | cs.dbh = NULL; | ||
548 | } | ||
549 | |||
550 | ret = old_pg_close(e, retv); | ||
551 | ninedogs_process_db("pg_close", NINEDOGS_DB_CONN_CLOSE, &cs); | ||
552 | |||
553 | return ret; | ||
554 | } | ||
555 | |||
556 | static void *(*old_pg_connect)(struct zend_execute_data *, struct zval *); | ||
557 | static void *my_pg_connect(struct zend_execute_data *e, struct zval *retv) | ||
558 | { | ||
559 | void *ret; | ||
560 | unsigned int num_args, s; | ||
561 | struct zval *z; | ||
562 | struct zend_string *q; | ||
563 | struct conn cs; | ||
564 | |||
565 | num_args = e->This.u2.num_args; | ||
566 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
567 | |||
568 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
569 | cs.type = 'P'; | ||
570 | |||
571 | // connection string | ||
572 | z = (struct zval *) e + s; s++; | ||
573 | q = z->value.str; | ||
574 | cs.conn_str = q->val; | ||
575 | cs.conn_str_len = q->len; | ||
576 | //xlog(50, " conn[%u]: %s\n", cs.conn_str_len, cs.conn_str); | ||
577 | |||
578 | ninedogs_process_db("pg_connect", NINEDOGS_DB_CONN_START, &cs); | ||
579 | ret = old_pg_connect(e, retv); | ||
580 | if (!retv) { | ||
581 | xlog(0, "DEBUG: old_pg_connect returned retv NULL\n"); | ||
582 | return ret; | ||
583 | } | ||
584 | |||
585 | php_zval_dump(" retv: ", retv); | ||
586 | // TODO: how to test for error? if (core_globals.last_error_message) { | ||
587 | |||
588 | // PHP7 returns resource, PHP8.1 returns object | ||
589 | if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) | ||
590 | cs.dbh = retv->value.p; | ||
591 | else | ||
592 | cs.dbh = NULL; | ||
593 | ninedogs_process_db("pg_connect", NINEDOGS_DB_CONN_END, &cs); | ||
594 | |||
595 | return ret; | ||
596 | } | ||
597 | |||
598 | static void *(*old_pg_pconnect)(struct zend_execute_data *, struct zval *); | ||
599 | static void *my_pg_pconnect(struct zend_execute_data *e, struct zval *retv) | ||
600 | { | ||
601 | void *ret; | ||
602 | unsigned int num_args, s; | ||
603 | struct zval *z; | ||
604 | struct zend_string *q; | ||
605 | struct conn cs; | ||
606 | |||
607 | num_args = e->This.u2.num_args; | ||
608 | xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
609 | |||
610 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
611 | cs.type = 'P'; | ||
612 | |||
613 | // connection string | ||
614 | z = (struct zval *) e + s; s++; | ||
615 | q = z->value.str; | ||
616 | cs.conn_str = q->val; | ||
617 | cs.conn_str_len = q->len; | ||
618 | xlog(50, " conn: %s\n", cs.conn_str); | ||
619 | |||
620 | ninedogs_process_db("pg_pconnect", NINEDOGS_DB_CONN_START, &cs); | ||
621 | ret = old_pg_pconnect(e, retv); | ||
622 | if (!retv) | ||
623 | return ret; | ||
624 | |||
625 | php_zval_dump(" retv: ", retv); | ||
626 | // TODO: how to test for error? if (core_globals.last_error_message) { | ||
627 | |||
628 | // PHP7 returns resource, PHP8.1 returns object | ||
629 | if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) | ||
630 | cs.dbh = retv->value.p; | ||
631 | else | ||
632 | cs.dbh = NULL; | ||
633 | ninedogs_process_db("pg_pconnect", NINEDOGS_DB_CONN_END, &cs); | ||
634 | |||
635 | return ret; | ||
636 | } | ||
637 | |||
638 | static void *(*old_pg_affected_rows)(struct zend_execute_data *, struct zval *); | ||
639 | |||
640 | static void *(*old_pg_free_result)(struct zend_execute_data *, struct zval *); | ||
641 | static void *my_pg_free_result(struct zend_execute_data *e, struct zval *retv) | ||
642 | { | ||
643 | void *ret; | ||
644 | unsigned int s; | ||
645 | struct zval *z; | ||
646 | struct free_result fr; | ||
647 | |||
648 | unsigned int num_args = e->This.u2.num_args; | ||
649 | xlog(200, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
650 | //php_zed_dump(" e: ", e); | ||
651 | //php_zval_dump(" retv: ", retv); | ||
652 | |||
653 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
654 | fr.type = 'P'; | ||
655 | |||
656 | // res | ||
657 | z = (struct zval *) e + s; s++; | ||
658 | fr.res = z->value.p; | ||
659 | |||
660 | ret = old_pg_free_result(e, retv); | ||
661 | // 'ret' is null here | ||
662 | |||
663 | if (retv->u1.v.type == 3) { // true | ||
664 | fr.ok = 1; | ||
665 | } else { | ||
666 | // TODO: can we get an error code here? | ||
667 | fr.ok = 0; | ||
668 | } | ||
669 | |||
670 | ninedogs_process_db("pg_free_result", NINEDOGS_DB_FREE_RESULT, &fr); | ||
671 | |||
672 | return ret; | ||
673 | } | ||
674 | |||
675 | static void *(*old_pg_num_rows)(struct zend_execute_data *, struct zval *); | ||
676 | static void *my_pg_num_rows(struct zend_execute_data *e, struct zval *retv) | ||
677 | { | ||
678 | void *ret; | ||
679 | |||
680 | //unsigned int num_args = e->This.u2.num_args; | ||
681 | //xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
682 | //php_zed_dump(" e: ", e); | ||
683 | //php_zval_dump(" retv: ", retv); | ||
684 | |||
685 | ret = old_pg_num_rows(e, retv); | ||
686 | if (!retv) | ||
687 | return ret; | ||
688 | |||
689 | //php_zval_dump(" retv: ", retv); | ||
690 | |||
691 | return ret; | ||
692 | } | ||
693 | |||
694 | static void php_pg_set_last_error(struct zend_execute_data *e, | ||
695 | struct zval *dbh, struct query *q) | ||
696 | { | ||
697 | struct zval rz; | ||
698 | |||
699 | e->This.u2.num_args = dbh ? 1 : 0; | ||
700 | if (dbh) | ||
701 | php_set_para(e, 0, dbh); | ||
702 | |||
703 | // TODO: we need also the numeric representation of the error! | ||
704 | xlog(50, " calling pg_last_error...\n"); | ||
705 | old_pg_last_error(e, &rz); | ||
706 | //xlog(1, " pg_last_error returned %p; type=%s value=%s\n", | ||
707 | // tr, php_get_type(&rz), php_get_value(&rz)); | ||
708 | |||
709 | if (rz.u1.v.type == 6) { // string | ||
710 | q->err = rz.value.str->val; | ||
711 | q->err_len = rz.value.str->len; | ||
712 | xlog(40, "%s: set error to [%s]\n", __func__, q->err); | ||
713 | } else { | ||
714 | q->err = "?"; | ||
715 | q->err_len = 1; | ||
716 | } | ||
717 | } | ||
718 | |||
719 | static void php_pg_set_num_aff(struct zend_execute_data *e, struct zval *res, | ||
720 | struct query *q) | ||
721 | { | ||
722 | struct zval rz; | ||
723 | |||
724 | e->This.u2.num_args = 1; | ||
725 | |||
726 | php_set_para(e, 0, res); | ||
727 | |||
728 | //xlog(1, " calling old pg_num_rows...\n"); | ||
729 | //php_zed_dump(" e: ", e); | ||
730 | old_pg_num_rows(e, &rz); | ||
731 | //php_zval_dump(" rz: ", &rz); | ||
732 | q->num = rz.value.lval; | ||
733 | |||
734 | //xlog(1, " calling old pg_affected_rows...\n"); | ||
735 | //php_zed_dump(" e: ", e); | ||
736 | old_pg_affected_rows(e, &rz); | ||
737 | //php_zval_dump(" rz: ", &rz); | ||
738 | q->aff = rz.value.lval; | ||
739 | } | ||
740 | |||
741 | static void *(*old_pg_query)(struct zend_execute_data *, struct zval *); | ||
742 | static void *my_pg_query(struct zend_execute_data *e, struct zval *retv) | ||
743 | { | ||
744 | void *ret; | ||
745 | unsigned int num_args, copy_num_args, s; | ||
746 | struct zend_string *q; | ||
747 | struct zval *dbh = NULL, *z, copy_para, *para; | ||
748 | char do_restore = 0; | ||
749 | struct query qs; | ||
750 | |||
751 | num_args = e->This.u2.num_args; | ||
752 | |||
753 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
754 | |||
755 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
756 | para = (struct zval *) e + s; | ||
757 | qs.type = 'P'; // if dbh is null, we do not know the type | ||
758 | qs.params.len = 0; | ||
759 | |||
760 | if (num_args == 2) { | ||
761 | // link | ||
762 | z = (struct zval *) e + s; s++; | ||
763 | //php_zval_dump(" dbh: ", z); | ||
764 | qs.dbh = z->value.p; | ||
765 | } else { | ||
766 | qs.dbh = NULL; | ||
767 | } | ||
768 | |||
769 | // query | ||
770 | z = (struct zval *) e + s; s++; | ||
771 | q = z->value.str; | ||
772 | xlog(50, " query=%s\n", q->val); | ||
773 | qs.q = q->val; | ||
774 | qs.q_len = q->len; | ||
775 | |||
776 | ninedogs_process_db("pg_query", NINEDOGS_DB_QUERY_START, &qs); | ||
777 | ret = old_pg_query(e, retv); | ||
778 | if (!retv) | ||
779 | return ret; | ||
780 | |||
781 | xlog(100, " old %s returned type=%s value=%s\n", | ||
782 | __func__, php_get_type(retv), php_get_value(retv)); | ||
783 | |||
784 | copy_num_args = num_args; | ||
785 | memcpy(©_para, para, sizeof(struct zval)); | ||
786 | |||
787 | if (retv->u1.v.type == 2) { // false | ||
788 | php_pg_set_last_error(e, dbh, &qs); // TODO is qs.res set here? | ||
789 | } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource | ||
790 | qs.res = retv->value.p; | ||
791 | php_pg_set_num_aff(e, retv, &qs); | ||
792 | do_restore = 1; | ||
793 | } | ||
794 | |||
795 | e->This.u2.num_args = copy_num_args; | ||
796 | if (do_restore) | ||
797 | memcpy(para, ©_para, sizeof(struct zval)); | ||
798 | |||
799 | ninedogs_process_db("pg_query", NINEDOGS_DB_QUERY_END, &qs); | ||
800 | |||
801 | return ret; | ||
802 | } | ||
803 | |||
804 | static void *(*old_pg_send_query)(struct zend_execute_data *, struct zval *); | ||
805 | static void *my_pg_send_query(struct zend_execute_data *e, struct zval *retv) | ||
806 | { | ||
807 | void *ret; | ||
808 | unsigned int num_args, s; | ||
809 | struct zend_string *q; | ||
810 | struct zval *dbh = NULL, *z; | ||
811 | struct query qs; | ||
812 | |||
813 | num_args = e->This.u2.num_args; | ||
814 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
815 | |||
816 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
817 | qs.type = 'P'; | ||
818 | qs.params.len = 0; | ||
819 | |||
820 | // link | ||
821 | z = (struct zval *) e + s; s++; | ||
822 | php_zval_dump(" dbh: ", z); | ||
823 | qs.dbh = z->value.p; | ||
824 | |||
825 | // query | ||
826 | z = (struct zval *) e + s; s++; | ||
827 | q = z->value.str; | ||
828 | qs.q = q->val; | ||
829 | qs.q_len = q->len; | ||
830 | xlog(100, " query=%s\n", qs.q); | ||
831 | |||
832 | ninedogs_process_db("pg_send_query", NINEDOGS_DB_QUERY_START, &qs); | ||
833 | ret = old_pg_send_query(e, retv); | ||
834 | if (!retv) | ||
835 | return ret; | ||
836 | |||
837 | xlog(101, " old %s returned type=%s value=%s\n", | ||
838 | __func__, php_get_type(retv), php_get_value(retv)); | ||
839 | |||
840 | qs.res = NULL; | ||
841 | if ((retv->u1.v.type == 2) || (retv->u1.v.type == 4)) { // false or int | ||
842 | php_pg_set_last_error(e, dbh, &qs); | ||
843 | } else if (retv->u1.v.type == 3) { // true = success | ||
844 | qs.num = qs.aff = 0; | ||
845 | qs.res = (void *) 1; // signal ok | ||
846 | } | ||
847 | |||
848 | ninedogs_process_db("pg_send_query", NINEDOGS_DB_QUERY_END, &qs); | ||
849 | |||
850 | return ret; | ||
851 | } | ||
852 | |||
853 | // TODO: not clear if on PHP 7 the parameter could be null | ||
854 | static void *(*old_pg_get_result)(struct zend_execute_data *, struct zval *); | ||
855 | static void *my_pg_get_result(struct zend_execute_data *e, struct zval *retv) | ||
856 | { | ||
857 | void *ret; | ||
858 | unsigned int num_args, copy_num_args, s; | ||
859 | struct zval *dbh = NULL, *z, copy_para, *para; | ||
860 | char do_restore = 0; | ||
861 | struct query qs; | ||
862 | |||
863 | num_args = e->This.u2.num_args; | ||
864 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
865 | |||
866 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
867 | para = (struct zval *) e + s; | ||
868 | qs.type = 'P'; | ||
869 | qs.q = NULL; | ||
870 | qs.params.len = 0; | ||
871 | |||
872 | // link | ||
873 | z = (struct zval *) e + s; s++; | ||
874 | //php_zval_dump(" dbh: ", z); | ||
875 | qs.dbh = z->value.p; | ||
876 | |||
877 | ninedogs_process_db("pg_get_result", NINEDOGS_DB_QUERY_START, &qs); | ||
878 | ret = old_pg_get_result(e, retv); | ||
879 | if (!retv) | ||
880 | return ret; | ||
881 | |||
882 | xlog(100, " old %s returned type=%s value=%s\n", | ||
883 | __func__, php_get_type(retv), php_get_value(retv)); | ||
884 | |||
885 | copy_num_args = num_args; | ||
886 | memcpy(©_para, para, sizeof(struct zval)); | ||
887 | |||
888 | if (retv->u1.v.type == 2) { // false | ||
889 | php_pg_set_last_error(e, dbh, &qs); | ||
890 | } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource | ||
891 | qs.err = NULL; | ||
892 | qs.res = retv->value.p; | ||
893 | php_pg_set_num_aff(e, retv, &qs); | ||
894 | do_restore = 1; | ||
895 | } | ||
896 | |||
897 | e->This.u2.num_args = copy_num_args; | ||
898 | if (do_restore) | ||
899 | memcpy(para, ©_para, sizeof(struct zval)); | ||
900 | |||
901 | ninedogs_process_db("pg_get_result", NINEDOGS_DB_QUERY_END, &qs); | ||
902 | |||
903 | return ret; | ||
904 | } | ||
905 | |||
906 | static void *(*old_pg_query_params)(struct zend_execute_data *, struct zval *); | ||
907 | static void *my_pg_query_params(struct zend_execute_data *e, struct zval *retv) | ||
908 | { | ||
909 | void *ret; | ||
910 | unsigned int num_args, s; | ||
911 | struct zval copy_para, *para, *z; | ||
912 | struct zend_string *q; | ||
913 | unsigned int copy_num_args; | ||
914 | void *dbh = NULL; | ||
915 | char do_restore = 0; | ||
916 | struct query qs; | ||
917 | |||
918 | num_args = e->This.u2.num_args; | ||
919 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
920 | //php_zed_dump(" e0: ", e); | ||
921 | //php_zval_dump(" retv0: ", retv); | ||
922 | |||
923 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
924 | para = (struct zval *) e + s; | ||
925 | qs.type = 'P'; | ||
926 | |||
927 | if (num_args == 3) { | ||
928 | // link | ||
929 | z = (struct zval *) e + s; s++; | ||
930 | qs.dbh = z->value.p; | ||
931 | } else { | ||
932 | qs.dbh = NULL; | ||
933 | } | ||
934 | |||
935 | // query | ||
936 | z = (struct zval *) e + s; s++; | ||
937 | q = z->value.str; | ||
938 | qs.q = q->val; | ||
939 | qs.q_len = q->len; | ||
940 | |||
941 | // params (array) | ||
942 | z = (struct zval *) e + s; s++; | ||
943 | struct zend_array *za = z->value.arr; | ||
944 | zend_array_to_params_array(&qs.params, za); | ||
945 | |||
946 | ninedogs_process_db("pg_query_params", NINEDOGS_DB_QUERY_START, &qs); | ||
947 | ret = old_pg_query_params(e, retv); | ||
948 | //xlog(200, " old %s: type=%s value=%s\n", | ||
949 | // __func__, php_get_type(retv), php_get_value(retv)); | ||
950 | //php_zed_dump(" e1: ", e); | ||
951 | //php_zval_dump(" retv after calling old func: ", retv); | ||
952 | |||
953 | copy_num_args = e->This.u2.num_args; | ||
954 | memcpy(©_para, para, sizeof(struct zval)); | ||
955 | |||
956 | if (retv->u1.v.type == 2) { // false | ||
957 | php_pg_set_last_error(e, dbh, &qs); | ||
958 | } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource | ||
959 | qs.res = retv->value.p; | ||
960 | php_pg_set_num_aff(e, retv, &qs); | ||
961 | do_restore = 1; | ||
962 | } | ||
963 | |||
964 | //php_zval_dump(" retv before ret: ", retv); | ||
965 | |||
966 | e->This.u2.num_args = copy_num_args; | ||
967 | if (do_restore) | ||
968 | memcpy(para, ©_para, sizeof(struct zval)); | ||
969 | |||
970 | ninedogs_process_db("pg_query_params", NINEDOGS_DB_QUERY_END, &qs); | ||
971 | |||
972 | return ret; | ||
973 | } | ||
974 | |||
975 | static void *(*old_pg_send_query_params)(struct zend_execute_data *, struct zval *); | ||
976 | static void *my_pg_send_query_params(struct zend_execute_data *e, struct zval *retv) | ||
977 | { | ||
978 | void *ret; | ||
979 | unsigned int s; | ||
980 | struct zval *z; | ||
981 | struct zval *dbh; | ||
982 | struct zend_string *q; | ||
983 | struct query qs; | ||
984 | |||
985 | unsigned int num_args = e->This.u2.num_args; | ||
986 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
987 | //php_zed_dump(" e0: ", e); | ||
988 | //php_zval_dump(" retv0: ", retv); | ||
989 | |||
990 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
991 | qs.type = 'P'; | ||
992 | |||
993 | // link | ||
994 | dbh = (struct zval *) e + s; s++; | ||
995 | qs.dbh = dbh->value.p; | ||
996 | |||
997 | // query | ||
998 | z = (struct zval *) e + s; s++; | ||
999 | q = z->value.str; | ||
1000 | qs.q = q->val; | ||
1001 | qs.q_len = q->len; | ||
1002 | |||
1003 | // params (array) | ||
1004 | z = (struct zval *) e + s; s++; | ||
1005 | struct zend_array *za = z->value.arr; | ||
1006 | zend_array_to_params_array(&qs.params, za); | ||
1007 | |||
1008 | ninedogs_process_db("pg_send_query_params", NINEDOGS_DB_QUERY_START, &qs); | ||
1009 | ret = old_pg_send_query_params(e, retv); | ||
1010 | //xlog(200, " old %s: type=%s value=%s\n", | ||
1011 | // __func__, php_get_type(retv), php_get_value(retv)); | ||
1012 | //php_zed_dump(" e1: ", e); | ||
1013 | //php_zval_dump(" retv after calling old func: ", retv); | ||
1014 | |||
1015 | qs.res = NULL; | ||
1016 | if ((retv->u1.v.type == 2) || (retv->u1.v.type == 4)) { // false or int (probably 0) | ||
1017 | php_pg_set_last_error(e, dbh, &qs); | ||
1018 | } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource | ||
1019 | qs.num = qs.aff = 0; | ||
1020 | qs.res = (void *) 1; // signal ok | ||
1021 | } | ||
1022 | |||
1023 | ninedogs_process_db("pg_send_query_params", NINEDOGS_DB_QUERY_END, &qs); | ||
1024 | |||
1025 | return ret; | ||
1026 | } | ||
1027 | |||
1028 | |||
1029 | |||
1030 | static void *(*old_mysqli_error)(struct zend_execute_data *, struct zval *); | ||
1031 | static void *(*old_mysqli_affected_rows)(struct zend_execute_data *, struct zval *); | ||
1032 | static void *(*old_mysqli_num_rows)(struct zend_execute_data *, struct zval *); | ||
1033 | static void *(*old_mysqli_stmt_affected_rows)(struct zend_execute_data *, struct zval *); | ||
1034 | static void *(*old_mysqli_stmt_num_rows)(struct zend_execute_data *, struct zval *); | ||
1035 | |||
1036 | static void php_mysqli_set_error(struct zend_execute_data *e, | ||
1037 | struct zval *link, struct query *q) | ||
1038 | { | ||
1039 | struct zval rz; | ||
1040 | |||
1041 | e->This.u2.num_args = 1; | ||
1042 | php_set_para(e, 0, link); | ||
1043 | |||
1044 | // TODO: we need also the numeric representation of the error! | ||
1045 | xlog(50, " calling mysqli_error...\n"); | ||
1046 | old_mysqli_error(e, &rz); | ||
1047 | |||
1048 | if (rz.u1.v.type == 6) { // string | ||
1049 | q->err = rz.value.str->val; | ||
1050 | q->err_len = rz.value.str->len; | ||
1051 | xlog(40, "%s: set error to [%s]\n", __func__, q->err); | ||
1052 | } else { | ||
1053 | q->err = "?"; | ||
1054 | q->err_len = 1; | ||
1055 | } | ||
1056 | } | ||
1057 | |||
1058 | static void php_mysqli_set_num_aff(struct zend_execute_data *e, struct zval *res, | ||
1059 | struct query *q) | ||
1060 | { | ||
1061 | struct zval rz; | ||
1062 | |||
1063 | e->This.u2.num_args = 1; | ||
1064 | |||
1065 | //xlog(1, " calling old pg_affected_rows...\n"); | ||
1066 | //php_zed_dump(" e: ", e); | ||
1067 | old_mysqli_affected_rows(e, &rz); // we need to pass a link here | ||
1068 | php_zval_dump(" aff_rows: ", &rz); | ||
1069 | q->aff = rz.value.lval; | ||
1070 | |||
1071 | php_set_para(e, 0, res); | ||
1072 | //xlog(1, " calling old pg_num_rows...\n"); | ||
1073 | //php_zed_dump(" e: ", e); | ||
1074 | old_mysqli_num_rows(e, &rz); // we need a result here | ||
1075 | php_zval_dump(" num_rows: ", &rz); | ||
1076 | q->num = rz.value.lval; | ||
1077 | } | ||
1078 | |||
1079 | static void php_mysqli_stmt_set_num_aff(struct zend_execute_data *e, | ||
1080 | struct nd_db_execute *q) | ||
1081 | { | ||
1082 | struct zval rz; | ||
1083 | |||
1084 | e->This.u2.num_args = 1; | ||
1085 | |||
1086 | //xlog(1, " calling old mysqli_stmt_affected_rows...\n"); | ||
1087 | //php_zed_dump(" e: ", e); | ||
1088 | old_mysqli_stmt_affected_rows(e, &rz); | ||
1089 | php_zval_dump(" aff_rows: ", &rz); | ||
1090 | q->aff = rz.value.lval; | ||
1091 | |||
1092 | //xlog(1, " calling old mysqli_stmt_num_rows...\n"); | ||
1093 | //php_zed_dump(" e: ", e); | ||
1094 | old_mysqli_stmt_num_rows(e, &rz); | ||
1095 | php_zval_dump(" num_rows: ", &rz); | ||
1096 | q->num = rz.value.lval; | ||
1097 | } | ||
1098 | |||
1099 | void *(*old_mysqli_connect)(struct zend_execute_data *, struct zval *); | ||
1100 | static void *my_mysqli_connect(struct zend_execute_data *e, struct zval *retv) | ||
1101 | { | ||
1102 | void *ret; | ||
1103 | unsigned int num_args, s; | ||
1104 | struct zval *z; | ||
1105 | struct conn cs; | ||
1106 | char *host = "", *user = "", *db = "", *sock = ""; | ||
1107 | int port = 0; | ||
1108 | |||
1109 | num_args = e->This.u2.num_args; | ||
1110 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
1111 | |||
1112 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
1113 | cs.type = 'M'; | ||
1114 | |||
1115 | if (num_args >= 1) { // host | ||
1116 | z = (struct zval *) e + s; s++; | ||
1117 | //php_zval_dump(" host: ", z); | ||
1118 | if (z->u1.v.type == 6) // string | ||
1119 | host = z->value.str->val; | ||
1120 | } | ||
1121 | |||
1122 | if (num_args >= 2) { // user | ||
1123 | z = (struct zval *) e + s; s++; | ||
1124 | if (z->u1.v.type == 6) // string | ||
1125 | user = z->value.str->val; | ||
1126 | } | ||
1127 | |||
1128 | if (num_args >= 3) // pass | ||
1129 | s++; | ||
1130 | |||
1131 | if (num_args >= 4) { // db | ||
1132 | z = (struct zval *) e + s; s++; | ||
1133 | if (z->u1.v.type == 6) // string | ||
1134 | db = z->value.str->val; | ||
1135 | } | ||
1136 | |||
1137 | if (num_args >= 5) { // port | ||
1138 | z = (struct zval *) e + s; s++; | ||
1139 | if (z->u1.v.type == 4) // long | ||
1140 | port = z->value.lval; | ||
1141 | } | ||
1142 | |||
1143 | if (num_args >= 6) { // socket | ||
1144 | z = (struct zval *) e + s; s++; | ||
1145 | if (z->u1.v.type == 6) // string | ||
1146 | sock = z->value.str->val; | ||
1147 | } | ||
1148 | |||
1149 | char conn_str[512]; | ||
1150 | snprintf(conn_str, sizeof(conn_str), | ||
1151 | "host=%s user=%s port=%d db=%s socket=%s", | ||
1152 | host, user, port, db, sock); | ||
1153 | cs.conn_str = conn_str; | ||
1154 | cs.conn_str_len = strlen(cs.conn_str); | ||
1155 | |||
1156 | ninedogs_process_db("mysqli_connect", NINEDOGS_DB_CONN_START, &cs); | ||
1157 | ret = old_mysqli_connect(e, retv); | ||
1158 | if (!retv) { | ||
1159 | xlog(1, "DEBUG: old_mysqli_connect returned retv NULL\n"); | ||
1160 | return ret; | ||
1161 | } | ||
1162 | //php_zval_dump(" retv: ", retv); | ||
1163 | // TODO: how to test for error? if (core_globals.last_error_message) { | ||
1164 | |||
1165 | // PHP7 returns resource, PHP8.1 returns object | ||
1166 | if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) | ||
1167 | cs.dbh = retv->value.p; | ||
1168 | else | ||
1169 | cs.dbh = NULL; | ||
1170 | ninedogs_process_db("mysqli_connect", NINEDOGS_DB_CONN_END, &cs); | ||
1171 | |||
1172 | return ret; | ||
1173 | } | ||
1174 | |||
1175 | void *(*old_mysqli_real_connect)(struct zend_execute_data *, struct zval *); | ||
1176 | static void *my_mysqli_real_connect(struct zend_execute_data *e, struct zval *retv) | ||
1177 | { | ||
1178 | void *ret; | ||
1179 | unsigned int num_args, s; | ||
1180 | struct zval *z; | ||
1181 | struct conn cs; | ||
1182 | char *host = "", *user = "", *db = "", *sock = ""; | ||
1183 | int port = 0; | ||
1184 | |||
1185 | num_args = e->This.u2.num_args; | ||
1186 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
1187 | |||
1188 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
1189 | cs.type = 'M'; | ||
1190 | cs.flags = 0; | ||
1191 | |||
1192 | if (num_args >= 1) { // dbh | ||
1193 | z = (struct zval *) e + s; s++; | ||
1194 | if ((z->u1.v.type == 8) || (z->u1.v.type == 9)) // object or resource | ||
1195 | cs.dbh = z->value.p; | ||
1196 | } | ||
1197 | |||
1198 | if (num_args >= 2) { // host | ||
1199 | z = (struct zval *) e + s; s++; | ||
1200 | //php_zval_dump(" host: ", z); | ||
1201 | if (z->u1.v.type == 6) // string | ||
1202 | host = z->value.str->val; | ||
1203 | } | ||
1204 | |||
1205 | if (num_args >= 3) { // user | ||
1206 | z = (struct zval *) e + s; s++; | ||
1207 | if (z->u1.v.type == 6) // string | ||
1208 | user = z->value.str->val; | ||
1209 | } | ||
1210 | |||
1211 | if (num_args >= 4) // pass | ||
1212 | s++; | ||
1213 | |||
1214 | if (num_args >= 5) { // db | ||
1215 | z = (struct zval *) e + s; s++; | ||
1216 | if (z->u1.v.type == 6) // string | ||
1217 | db = z->value.str->val; | ||
1218 | } | ||
1219 | |||
1220 | if (num_args >= 6) { // port | ||
1221 | z = (struct zval *) e + s; s++; | ||
1222 | if (z->u1.v.type == 4) // long | ||
1223 | port = z->value.lval; | ||
1224 | } | ||
1225 | |||
1226 | if (num_args >= 7) { // socket | ||
1227 | z = (struct zval *) e + s; s++; | ||
1228 | if (z->u1.v.type == 6) // string | ||
1229 | sock = z->value.str->val; | ||
1230 | } | ||
1231 | |||
1232 | if (num_args >= 8) { // flags | ||
1233 | z = (struct zval *) e + s; s++; | ||
1234 | if (z->u1.v.type == 4) // long | ||
1235 | cs.flags = z->value.lval; | ||
1236 | } | ||
1237 | |||
1238 | char conn_str[512]; | ||
1239 | snprintf(conn_str, sizeof(conn_str), | ||
1240 | "host=%s user=%s port=%d db=%s socket=%s", | ||
1241 | host, user, port, db, sock); | ||
1242 | cs.conn_str = conn_str; | ||
1243 | cs.conn_str_len = strlen(cs.conn_str); | ||
1244 | |||
1245 | ninedogs_process_db("mysqli_real_connect", NINEDOGS_DB_CONN_START, &cs); | ||
1246 | ret = old_mysqli_real_connect(e, retv); | ||
1247 | if (!retv) { | ||
1248 | xlog(1, "DEBUG: old_mysqli_real_connect returned retv NULL\n"); | ||
1249 | return ret; | ||
1250 | } | ||
1251 | //php_zval_dump(" retv: ", retv); | ||
1252 | // TODO: how to test for error? if (core_globals.last_error_message) { | ||
1253 | |||
1254 | // PHP7 returns resource, PHP8.1 returns object | ||
1255 | if (retv->u1.v.type == 3) | ||
1256 | cs.ret = 1; | ||
1257 | else | ||
1258 | cs.ret = 0; | ||
1259 | ninedogs_process_db("mysqli_real_connect", NINEDOGS_DB_CONN_END, &cs); | ||
1260 | |||
1261 | return ret; | ||
1262 | } | ||
1263 | |||
1264 | void *(*old_mysqli_query)(struct zend_execute_data *, struct zval *); | ||
1265 | static void *my_mysqli_query(struct zend_execute_data *e, struct zval *retv) | ||
1266 | { | ||
1267 | void *ret; | ||
1268 | unsigned int num_args, copy_num_args, s; | ||
1269 | struct zend_string *q; | ||
1270 | struct zval *z, copy_para, *para; | ||
1271 | char do_restore = 0; | ||
1272 | struct query qs; | ||
1273 | |||
1274 | num_args = e->This.u2.num_args; | ||
1275 | |||
1276 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
1277 | |||
1278 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
1279 | para = (struct zval *) e + s; | ||
1280 | qs.type = 'M'; | ||
1281 | qs.params.len = 0; | ||
1282 | |||
1283 | // link | ||
1284 | z = (struct zval *) e + s; s++; | ||
1285 | php_zval_dump(" dbh: ", z); | ||
1286 | qs.dbh = z->value.p; | ||
1287 | |||
1288 | // query | ||
1289 | z = (struct zval *) e + s; s++; | ||
1290 | q = z->value.str; | ||
1291 | xlog(50, " query=%s\n", q->val); | ||
1292 | qs.q = q->val; | ||
1293 | qs.q_len = q->len; | ||
1294 | |||
1295 | // mode | ||
1296 | if (num_args >= 3) { | ||
1297 | z = (struct zval *) e + s; s++; | ||
1298 | xlog(50, " mode=0x%lx\n", z->value.lval); | ||
1299 | } | ||
1300 | |||
1301 | ninedogs_process_db("mysqli_query", NINEDOGS_DB_QUERY_START, &qs); | ||
1302 | ret = old_mysqli_query(e, retv); | ||
1303 | if (!retv) | ||
1304 | return ret; | ||
1305 | php_zval_dump(" retv: ", retv); | ||
1306 | |||
1307 | copy_num_args = num_args; | ||
1308 | memcpy(©_para, para, sizeof(struct zval)); | ||
1309 | |||
1310 | if (retv->u1.v.type == 2) { // false | ||
1311 | // TODO php_mysqli_set_error(e, dbh, &qs); // TODO is qs.res set here? | ||
1312 | // TODO: do we set num and aff? | ||
1313 | qs.res = (void *) 0; | ||
1314 | } else if (retv->u1.v.type == 3) { // true (for queries not returning rows) | ||
1315 | qs.num = qs.aff = 0; | ||
1316 | qs.res = (void *) 1; | ||
1317 | } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource | ||
1318 | qs.res = retv->value.p; | ||
1319 | php_mysqli_set_num_aff(e, retv, &qs); | ||
1320 | do_restore = 1; | ||
1321 | } | ||
1322 | |||
1323 | e->This.u2.num_args = copy_num_args; | ||
1324 | if (do_restore) | ||
1325 | memcpy(para, ©_para, sizeof(struct zval)); | ||
1326 | |||
1327 | ninedogs_process_db("mysqli_query", NINEDOGS_DB_QUERY_END, &qs); | ||
1328 | |||
1329 | return ret; | ||
1330 | } | ||
1331 | |||
1332 | void *(*old_mysqli_close)(struct zend_execute_data *, struct zval *); | ||
1333 | static void *my_mysqli_close(struct zend_execute_data *e, struct zval *retv) | ||
1334 | { | ||
1335 | struct conn c; | ||
1336 | |||
1337 | unsigned int num_args = e->This.u2.num_args; | ||
1338 | |||
1339 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
1340 | |||
1341 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
1342 | c.type = 'M'; | ||
1343 | |||
1344 | // link | ||
1345 | struct zval *z = (struct zval *) e + s; s++; | ||
1346 | php_zval_dump(" dbh: ", z); | ||
1347 | c.dbh = z->value.p; | ||
1348 | |||
1349 | void *ret = old_mysqli_close(e, retv); | ||
1350 | if (!retv) | ||
1351 | return ret; | ||
1352 | php_zval_dump(" retv: ", retv); | ||
1353 | |||
1354 | if (retv->u1.v.type == 2) { // false | ||
1355 | c.ret = 0; | ||
1356 | // TODO php_mysqli_set_error(e, dbh, &qs); // TODO is qs.res set here? | ||
1357 | // TODO: do we set num and aff? | ||
1358 | } else if (retv->u1.v.type == 3) { // true (for queries not returning rows) | ||
1359 | c.ret = 1; | ||
1360 | } | ||
1361 | |||
1362 | ninedogs_process_db("mysqli_close", NINEDOGS_DB_CONN_CLOSE, &c); | ||
1363 | |||
1364 | return ret; | ||
1365 | } | ||
1366 | |||
1367 | void *(*old_mysqli_fetch_all)(struct zend_execute_data *, struct zval *); | ||
1368 | static void *my_mysqli_fetch_all(struct zend_execute_data *e, struct zval *retv) | ||
1369 | { | ||
1370 | struct query q; | ||
1371 | |||
1372 | unsigned int num_args = e->This.u2.num_args; | ||
1373 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
1374 | |||
1375 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
1376 | q.type = 'M'; | ||
1377 | |||
1378 | // res | ||
1379 | struct zval *z = (struct zval *) e + s; s++; | ||
1380 | php_zval_dump(" res: ", z); | ||
1381 | q.res = z->value.p; | ||
1382 | |||
1383 | // mode | ||
1384 | if (num_args >= 2) { | ||
1385 | z = (struct zval *) e + s; s++; | ||
1386 | q.mode = z->value.lval; | ||
1387 | xlog(50, " mode=0x%lx\n", q.mode); | ||
1388 | } else { | ||
1389 | q.mode = 2; // MYSQLI_NUM | ||
1390 | } | ||
1391 | |||
1392 | ninedogs_process_db("mysqli_fetch_all", NINEDOGS_DB_FETCH_START, &q); | ||
1393 | void *ret = old_mysqli_fetch_all(e, retv); | ||
1394 | if (!retv) | ||
1395 | return ret; | ||
1396 | php_zval_dump(" retv: ", retv); | ||
1397 | |||
1398 | // TODO php_mysqli_set_error(e, dbh, &qs); // TODO is qs.res set here? | ||
1399 | if (retv->u1.v.type == 7) { // array | ||
1400 | struct zend_array *a = retv->value.arr; | ||
1401 | q.num = a->nNumUsed; | ||
1402 | //q.ret = 0; | ||
1403 | // TODO: do we set num and aff? Should we? We already count them in 'execute'. | ||
1404 | } else if (retv->u1.v.type == 3) { // true (for queries not returning rows) | ||
1405 | q.num = 0; | ||
1406 | //q.ret = 1; | ||
1407 | } | ||
1408 | |||
1409 | ninedogs_process_db("mysqli_fetch_all", NINEDOGS_DB_FETCH_END, &q); | ||
1410 | |||
1411 | return ret; | ||
1412 | } | ||
1413 | |||
1414 | void *(*old_mysqli_fetch_array)(struct zend_execute_data *, struct zval *); | ||
1415 | static void *my_mysqli_fetch_array(struct zend_execute_data *e, struct zval *retv) | ||
1416 | { | ||
1417 | struct query q; | ||
1418 | |||
1419 | unsigned int num_args = e->This.u2.num_args; | ||
1420 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
1421 | |||
1422 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
1423 | q.type = 'M'; | ||
1424 | |||
1425 | // res | ||
1426 | struct zval *z = (struct zval *) e + s; s++; | ||
1427 | php_zval_dump(" res: ", z); | ||
1428 | q.res = z->value.p; | ||
1429 | |||
1430 | // mode | ||
1431 | if (num_args >= 2) { | ||
1432 | z = (struct zval *) e + s; s++; | ||
1433 | q.mode = z->value.lval; | ||
1434 | xlog(50, " mode=0x%lx\n", q.mode); | ||
1435 | } else { | ||
1436 | q.mode = 3; // MYSQLI_BOTH | ||
1437 | } | ||
1438 | |||
1439 | ninedogs_process_db("mysqli_fetch_array", NINEDOGS_DB_FETCH_START, &q); | ||
1440 | void *ret = old_mysqli_fetch_array(e, retv); | ||
1441 | if (!retv) | ||
1442 | return ret; | ||
1443 | php_zval_dump(" retv: ", retv); | ||
1444 | |||
1445 | if (retv->u1.v.type == 7) { // array | ||
1446 | q.ret = 2; | ||
1447 | } else if (retv->u1.v.type == 2) { // false - TODO set error | ||
1448 | q.ret = 1; | ||
1449 | } else { | ||
1450 | q.ret = 0; | ||
1451 | } | ||
1452 | |||
1453 | ninedogs_process_db("mysqli_fetch_array", NINEDOGS_DB_FETCH_END, &q); | ||
1454 | |||
1455 | return ret; | ||
1456 | } | ||
1457 | |||
1458 | void *(*old_mysqli_free_result)(struct zend_execute_data *, struct zval *); | ||
1459 | static void *my_mysqli_free_result(struct zend_execute_data *e, struct zval *retv) | ||
1460 | { | ||
1461 | struct free_result fr; | ||
1462 | |||
1463 | unsigned int num_args = e->This.u2.num_args; | ||
1464 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
1465 | |||
1466 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
1467 | fr.type = 'M'; | ||
1468 | |||
1469 | // res | ||
1470 | struct zval *z = (struct zval *) e + s; s++; | ||
1471 | php_zval_dump(" res: ", z); | ||
1472 | fr.res = z->value.p; | ||
1473 | |||
1474 | void *ret = old_mysqli_free_result(e, retv); | ||
1475 | if (!retv) | ||
1476 | return ret; | ||
1477 | |||
1478 | fr.ok = 1; | ||
1479 | ninedogs_process_db("mysqli_free_result", NINEDOGS_DB_FREE_RESULT, &fr); | ||
1480 | |||
1481 | return ret; | ||
1482 | } | ||
1483 | |||
1484 | void *(*old_mysqli_stmt_execute)(struct zend_execute_data *, struct zval *); | ||
1485 | static void *my_mysqli_stmt_execute(struct zend_execute_data *e, struct zval *retv) | ||
1486 | { | ||
1487 | struct nd_db_execute ex; | ||
1488 | char do_restore = 0; | ||
1489 | |||
1490 | unsigned int num_args = e->This.u2.num_args; | ||
1491 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
1492 | |||
1493 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
1494 | ex.type = 'M'; | ||
1495 | ex.params.len = 0; | ||
1496 | |||
1497 | struct zval *para = (struct zval *) e + s; | ||
1498 | |||
1499 | // stmt | ||
1500 | struct zval *z = (struct zval *) e + s; s++; | ||
1501 | php_zval_dump(" stmt: ", z); | ||
1502 | ex.stmt = z->value.p; | ||
1503 | |||
1504 | if (num_args >= 2) { | ||
1505 | z = (struct zval *) e + s; s++; | ||
1506 | struct zend_array *za = z->value.arr; | ||
1507 | zend_array_to_params_array(&ex.params, za); | ||
1508 | } | ||
1509 | |||
1510 | unsigned int copy_num_args = num_args; | ||
1511 | struct zval copy_para; | ||
1512 | memcpy(©_para, para, sizeof(struct zval)); | ||
1513 | |||
1514 | ninedogs_process_db("mysqli_stmt_execute", NINEDOGS_DB_EXECUTE_START, &ex); | ||
1515 | void *ret = old_mysqli_stmt_execute(e, retv); | ||
1516 | if (!retv) | ||
1517 | return ret; | ||
1518 | |||
1519 | if (retv->u1.v.type == 3) { // true | ||
1520 | ex.ret = 1; | ||
1521 | php_mysqli_stmt_set_num_aff(e, &ex); | ||
1522 | do_restore = 1; | ||
1523 | } else if (retv->u1.v.type == 2) { // false | ||
1524 | ex.ret = 0; | ||
1525 | } | ||
1526 | |||
1527 | e->This.u2.num_args = copy_num_args; | ||
1528 | if (do_restore) | ||
1529 | memcpy(para, ©_para, sizeof(struct zval)); | ||
1530 | |||
1531 | ninedogs_process_db("mysqli_stmt_execute", NINEDOGS_DB_EXECUTE_END, &ex); | ||
1532 | |||
1533 | return ret; | ||
1534 | } | ||
1535 | |||
1536 | void *(*old_mysqli_prepare)(struct zend_execute_data *, struct zval *); | ||
1537 | static void *my_mysqli_prepare(struct zend_execute_data *e, struct zval *retv) | ||
1538 | { | ||
1539 | struct prepare p; | ||
1540 | |||
1541 | unsigned int num_args = e->This.u2.num_args; | ||
1542 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
1543 | |||
1544 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
1545 | p.type = 'M'; | ||
1546 | |||
1547 | // link | ||
1548 | struct zval *z = (struct zval *) e + s; s++; | ||
1549 | php_zval_dump(" link: ", z); | ||
1550 | p.dbh = z->value.p; | ||
1551 | |||
1552 | // query | ||
1553 | z = (struct zval *) e + s; s++; | ||
1554 | struct zend_string *xs = z->value.str; | ||
1555 | xlog(50, " query=%s\n", xs->val); | ||
1556 | p.q = xs->val; | ||
1557 | p.q_len = xs->len; | ||
1558 | |||
1559 | ninedogs_process_db("mysqli_prepare", NINEDOGS_DB_PREPARE_START, &p); | ||
1560 | void *ret = old_mysqli_prepare(e, retv); | ||
1561 | if (!retv) | ||
1562 | return ret; | ||
1563 | php_zval_dump(" retv: ", retv); | ||
1564 | |||
1565 | // PHP7 returns resource, PHP8.1 returns object | ||
1566 | if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { | ||
1567 | p.stmt = retv->value.p; | ||
1568 | } else if (retv->u1.v.type == 2) { // false | ||
1569 | p.stmt = NULL; | ||
1570 | } | ||
1571 | |||
1572 | ninedogs_process_db("mysqli_prepare", NINEDOGS_DB_PREPARE_END, &p); | ||
1573 | |||
1574 | return ret; | ||
1575 | } | ||
1576 | |||
1577 | void *(*old_mysqli_stmt_prepare)(struct zend_execute_data *, struct zval *); | ||
1578 | static void *my_mysqli_stmt_prepare(struct zend_execute_data *e, struct zval *retv) | ||
1579 | { | ||
1580 | struct prepare p; | ||
1581 | |||
1582 | unsigned int num_args = e->This.u2.num_args; | ||
1583 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
1584 | |||
1585 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
1586 | p.type = 'M'; | ||
1587 | |||
1588 | // stmt | ||
1589 | struct zval *z = (struct zval *) e + s; s++; | ||
1590 | php_zval_dump(" stmt: ", z); | ||
1591 | p.stmt = z->value.p; | ||
1592 | |||
1593 | // query | ||
1594 | z = (struct zval *) e + s; s++; | ||
1595 | struct zend_string *xs = z->value.str; | ||
1596 | xlog(50, " query=%s\n", xs->val); | ||
1597 | p.q = xs->val; | ||
1598 | p.q_len = xs->len; | ||
1599 | |||
1600 | ninedogs_process_db("mysqli_stmt_prepare", NINEDOGS_DB_PREPARE_START, &p); | ||
1601 | void *ret = old_mysqli_stmt_prepare(e, retv); | ||
1602 | if (!retv) | ||
1603 | return ret; | ||
1604 | php_zval_dump(" retv: ", retv); | ||
1605 | |||
1606 | if (retv->u1.v.type == 3) { // true | ||
1607 | p.ret = 1; | ||
1608 | } else if (retv->u1.v.type == 2) { // false | ||
1609 | p.ret = 0; | ||
1610 | } | ||
1611 | |||
1612 | ninedogs_process_db("mysqli_stmt_prepare", NINEDOGS_DB_PREPARE_END, &p); | ||
1613 | |||
1614 | return ret; | ||
1615 | } | ||
1616 | |||
1617 | void *(*old_mysqli_autocommit)(struct zend_execute_data *, struct zval *); | ||
1618 | static void *my_mysqli_autocommit(struct zend_execute_data *e, struct zval *retv) | ||
1619 | { | ||
1620 | struct db_autocommit a; | ||
1621 | |||
1622 | unsigned int num_args = e->This.u2.num_args; | ||
1623 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
1624 | |||
1625 | unsigned int s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
1626 | a.type = 'M'; | ||
1627 | |||
1628 | // link | ||
1629 | struct zval *z = (struct zval *) e + s; s++; | ||
1630 | a.link = z->value.p; | ||
1631 | |||
1632 | z = (struct zval *) e + s; s++; | ||
1633 | php_zval_dump(" bool: ", z); | ||
1634 | a.value = z->u1.v.type == 3; | ||
1635 | |||
1636 | ninedogs_process_db("mysqli_autocommit", NINEDOGS_DB_AUTOCOMMIT_START, &a); | ||
1637 | void *ret = old_mysqli_autocommit(e, retv); | ||
1638 | if (!retv) | ||
1639 | return ret; | ||
1640 | |||
1641 | if (retv->u1.v.type == 3) { // true | ||
1642 | a.ret = 1; | ||
1643 | } else if (retv->u1.v.type == 2) { // false | ||
1644 | a.ret = 0; | ||
1645 | } | ||
1646 | |||
1647 | ninedogs_process_db("mysqli_autocommit", NINEDOGS_DB_AUTOCOMMIT_END, &a); | ||
1648 | |||
1649 | return ret; | ||
1650 | } | ||
1651 | |||
1652 | void *(*old_mysqli_stmt_bind_param)(struct zend_execute_data *, struct zval *); | ||
1653 | static void *my_mysqli_stmt_bind_param(struct zend_execute_data *e, struct zval *retv) | ||
1654 | { | ||
1655 | struct nd_db_bind b; | ||
1656 | |||
1657 | unsigned int num_args = e->This.u2.num_args; | ||
1658 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
1659 | |||
1660 | unsigned int s = (sizeof(struct zend_execute_data) | ||
1661 | + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
1662 | b.type = 'M'; | ||
1663 | |||
1664 | // stmt | ||
1665 | struct zval *z = (struct zval *) e + s; s++; | ||
1666 | //php_zval_dump(" stmt: ", z); | ||
1667 | b.stmt = z->value.p; | ||
1668 | |||
1669 | // types | ||
1670 | z = (struct zval *) e + s; s++; | ||
1671 | struct zend_string *xs = z->value.str; | ||
1672 | b.types = xs->val; | ||
1673 | b.types_len = xs->len; | ||
1674 | |||
1675 | ninedogs_process_db("mysqli_stmt_bind_param", | ||
1676 | NINEDOGS_DB_BIND_PARAM_START, &b); | ||
1677 | void *ret = old_mysqli_stmt_bind_param(e, retv); | ||
1678 | if (!retv) | ||
1679 | return ret; | ||
1680 | |||
1681 | if (retv->u1.v.type == 3) { // true | ||
1682 | b.ret = 1; | ||
1683 | } else if (retv->u1.v.type == 2) { // false | ||
1684 | b.ret = 0; | ||
1685 | } | ||
1686 | |||
1687 | ninedogs_process_db("mysqli_stmt_bind_param", | ||
1688 | NINEDOGS_DB_BIND_PARAM_END, &b); | ||
1689 | |||
1690 | return ret; | ||
1691 | } | ||
1692 | |||
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 | |||
1844 | |||
43 | //#include "ctools.h" | ||
44 | #include "php.h" | ||
1845 | 45 | ||
1846 | struct zend_module_entry *(*old_get_module)(void); | ||
46 | static struct zend_module_entry *(*old_get_module)(void); | ||
1847 | 47 | static struct zend_module_entry *php_hook_get_module_func(void) | static struct zend_module_entry *php_hook_get_module_func(void) |
1848 | 48 | { | { |
1849 | 49 | struct zend_module_entry *z, *new; | struct zend_module_entry *z, *new; |
... | ... | static struct zend_module_entry *php_hook_get_module_func(void) | |
1897 | 97 | fe = new->functions; | fe = new->functions; |
1898 | 98 | while (fe && fe->fname) { | while (fe && fe->fname) { |
1899 | 99 | xlog(100, " func %s handler=%p\n", fe->fname, fe->handler); | xlog(100, " func %s handler=%p\n", fe->fname, fe->handler); |
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 | } | ||
100 | if (strncmp(fe->fname, "oci_", 4) == 0) { | ||
101 | php_oci_hook(fe); | ||
102 | } else if (strncmp(fe->fname, "curl_", 5) == 0) { | ||
103 | php_curl_hook(fe); | ||
1916 | 104 | } else if (strncmp(fe->fname, "pg_", 3) == 0) { | } else if (strncmp(fe->fname, "pg_", 3) == 0) { |
1917 | if (strcmp(fe->fname, "pg_close") == 0) { | ||
1918 | old_pg_close = fe->handler; | ||
1919 | fe->handler = my_pg_close; | ||
1920 | } else if (strcmp(fe->fname, "pg_connect") == 0) { | ||
1921 | old_pg_connect = fe->handler; | ||
1922 | fe->handler = my_pg_connect; | ||
1923 | } else if (strcmp(fe->fname, "pg_pconnect") == 0) { | ||
1924 | old_pg_pconnect = fe->handler; | ||
1925 | fe->handler = my_pg_pconnect; | ||
1926 | } else if (strcmp(fe->fname, "pg_num_rows") == 0) { | ||
1927 | old_pg_num_rows = fe->handler; | ||
1928 | fe->handler = my_pg_num_rows; | ||
1929 | } else if (strcmp(fe->fname, "pg_affected_rows") == 0) { | ||
1930 | old_pg_affected_rows = fe->handler; | ||
1931 | } else if (strcmp(fe->fname, "pg_free_result") == 0) { | ||
1932 | old_pg_free_result = fe->handler; | ||
1933 | fe->handler = my_pg_free_result; | ||
1934 | } else if (strcmp(fe->fname, "pg_query") == 0) { | ||
1935 | old_pg_query = fe->handler; | ||
1936 | fe->handler = my_pg_query; | ||
1937 | } else if (strcmp(fe->fname, "pg_send_query") == 0) { | ||
1938 | old_pg_send_query = fe->handler; | ||
1939 | fe->handler = my_pg_send_query; | ||
1940 | } else if (strcmp(fe->fname, "pg_query_params") == 0) { | ||
1941 | old_pg_query_params = fe->handler; | ||
1942 | fe->handler = my_pg_query_params; | ||
1943 | } else if (strcmp(fe->fname, "pg_send_query_params") == 0) { | ||
1944 | old_pg_send_query_params = fe->handler; | ||
1945 | fe->handler = my_pg_send_query_params; | ||
1946 | } else if (strcmp(fe->fname, "pg_last_error") == 0) { | ||
1947 | old_pg_last_error = fe->handler; | ||
1948 | fe->handler = my_pg_last_error; | ||
1949 | } else if (strcmp(fe->fname, "pg_get_result") == 0) { | ||
1950 | old_pg_get_result = fe->handler; | ||
1951 | fe->handler = my_pg_get_result; | ||
1952 | } else { | ||
1953 | //xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname); | ||
1954 | } | ||
105 | php_pg_hook(fe); | ||
1955 | 106 | } else if (strncmp(fe->fname, "mysqli_", 7) == 0) { | } else if (strncmp(fe->fname, "mysqli_", 7) == 0) { |
1956 | if (strcmp(fe->fname, "mysqli_autocommit") == 0) { | ||
1957 | old_mysqli_autocommit = fe->handler; | ||
1958 | fe->handler = my_mysqli_autocommit; | ||
1959 | } else if (strcmp(fe->fname, "mysqli_close") == 0) { | ||
1960 | old_mysqli_close = fe->handler; | ||
1961 | fe->handler = my_mysqli_close; | ||
1962 | } else if (strcmp(fe->fname, "mysqli_affected_rows") == 0) { | ||
1963 | old_mysqli_stmt_affected_rows = fe->handler; | ||
1964 | } else if (strcmp(fe->fname, "mysqli_connect") == 0) { | ||
1965 | old_mysqli_connect = fe->handler; | ||
1966 | fe->handler = my_mysqli_connect; | ||
1967 | } else if (strcmp(fe->fname, "mysqli_error") == 0) { | ||
1968 | old_mysqli_error = fe->handler; | ||
1969 | } else if (strcmp(fe->fname, "mysqli_fetch_all") == 0) { | ||
1970 | old_mysqli_fetch_all = fe->handler; | ||
1971 | fe->handler = my_mysqli_fetch_all; | ||
1972 | } else if (strcmp(fe->fname, "mysqli_fetch_array") == 0) { | ||
1973 | old_mysqli_fetch_array = fe->handler; | ||
1974 | fe->handler = my_mysqli_fetch_array; | ||
1975 | } else if (strcmp(fe->fname, "mysqli_free_result") == 0) { | ||
1976 | old_mysqli_free_result = fe->handler; | ||
1977 | fe->handler = my_mysqli_free_result; | ||
1978 | } else if (strcmp(fe->fname, "mysqli_query") == 0) { | ||
1979 | old_mysqli_query = fe->handler; | ||
1980 | fe->handler = my_mysqli_query; | ||
1981 | } else if (strcmp(fe->fname, "mysqli_prepare") == 0) { | ||
1982 | old_mysqli_prepare = fe->handler; | ||
1983 | fe->handler = my_mysqli_prepare; | ||
1984 | } else if (strcmp(fe->fname, "mysqli_num_rows") == 0) { | ||
1985 | old_mysqli_num_rows = fe->handler; | ||
1986 | } else if (strcmp(fe->fname, "mysqli_real_connect") == 0) { | ||
1987 | old_mysqli_real_connect = fe->handler; | ||
1988 | fe->handler = my_mysqli_real_connect; | ||
1989 | } else if (strcmp(fe->fname, "mysqli_stmt_affected_rows") == 0) { | ||
1990 | old_mysqli_stmt_affected_rows = fe->handler; | ||
1991 | } else if (strcmp(fe->fname, "mysqli_stmt_execute") == 0) { | ||
1992 | old_mysqli_stmt_execute = fe->handler; | ||
1993 | fe->handler = my_mysqli_stmt_execute; | ||
1994 | } else if (strcmp(fe->fname, "mysqli_stmt_bind_param") == 0) { | ||
1995 | old_mysqli_stmt_bind_param = fe->handler; | ||
1996 | fe->handler = my_mysqli_stmt_bind_param; | ||
1997 | } else if (strcmp(fe->fname, "mysqli_stmt_num_rows") == 0) { | ||
1998 | old_mysqli_stmt_num_rows = fe->handler; | ||
1999 | } else if (strcmp(fe->fname, "mysqli_stmt_prepare") == 0) { | ||
2000 | old_mysqli_stmt_prepare = fe->handler; | ||
2001 | fe->handler = my_mysqli_stmt_prepare; | ||
2002 | } else { | ||
2003 | //xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname); | ||
2004 | } | ||
107 | php_mysql_hook(fe); | ||
108 | } else if (strncmp(fe->fname, "image", 5) == 0) { | ||
109 | php_gd_hook(fe); | ||
2005 | 110 | } | } |
2006 | 111 | fe++; | fe++; |
2007 | 112 | } | } |
File agent/php.h changed (mode: 100644) (index b2242cd..6d33ae8) | |||
1 | #include "php-curl.h" | ||
2 | #include "php-mysql.h" | ||
3 | #include "php-oci.h" | ||
4 | #include "php-pg.h" | ||
5 | |||
6 | #include "php/gd.h" | ||
1 | 7 | ||
2 | 8 | void *php_hook(void *x); | void *php_hook(void *x); |
3 | 9 |
File agent/php/gd.c added (mode: 100644) (index 0000000..efc1633) | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <string.h> | ||
4 | |||
5 | #include "../../common/ids.h" | ||
6 | #include "../../common/tools.h" | ||
7 | #include "../ctools.h" | ||
8 | #include "../ninedogs.h" | ||
9 | #include "../process_db.h" | ||
10 | #include "gd.h" | ||
11 | |||
12 | #define ND_GD_IMG_MAX 100 | ||
13 | static __thread struct nd_gd_img track[ND_GD_IMG_MAX]; | ||
14 | |||
15 | static void im_clean(const void *im) | ||
16 | { | ||
17 | for (unsigned i = 0; i < ND_GD_IMG_MAX; i++) { | ||
18 | if (track[i].im == im) { | ||
19 | memset(&track[i], 0, sizeof(struct nd_gd_img)); | ||
20 | break; | ||
21 | } | ||
22 | } | ||
23 | } | ||
24 | |||
25 | static struct nd_gd_img *im_find(const void *im) | ||
26 | { | ||
27 | for (unsigned i = 0; i < ND_GD_IMG_MAX; i++) { | ||
28 | if (track[i].im == im) | ||
29 | return &track[i]; | ||
30 | } | ||
31 | |||
32 | return NULL; | ||
33 | } | ||
34 | |||
35 | static struct nd_gd_img *im_alloc(struct nd_gd_img *img) | ||
36 | { | ||
37 | for (unsigned i = 0; i < ND_GD_IMG_MAX; i++) { | ||
38 | if (track[i].im == NULL) { | ||
39 | memcpy(&track[i].im, img, sizeof(struct nd_gd_img)); | ||
40 | return &track[i]; | ||
41 | } | ||
42 | } | ||
43 | |||
44 | return NULL; | ||
45 | } | ||
46 | |||
47 | static void im_add(struct nd_gd_img *img) | ||
48 | { | ||
49 | struct nd_gd_img *s = im_find(img); | ||
50 | if (!s) | ||
51 | s = im_alloc(img); | ||
52 | } | ||
53 | |||
54 | |||
55 | static void *(*old_gd_imagecreate)(struct zend_execute_data *, struct zval *); | ||
56 | static void *my_gd_imagecreate(struct zend_execute_data *e, struct zval *retv) | ||
57 | { | ||
58 | unsigned int num_args, s; | ||
59 | struct nd_gd_img img; | ||
60 | long w, h; | ||
61 | |||
62 | num_args = e->This.u2.num_args; | ||
63 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
64 | |||
65 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
66 | |||
67 | // w | ||
68 | struct zval *z = (struct zval *) e + s; s++; | ||
69 | php_zval_dump(" w=", z); | ||
70 | w = z->value.lval; | ||
71 | |||
72 | // h | ||
73 | z = (struct zval *) e + s; s++; | ||
74 | php_zval_dump(" h=", z); | ||
75 | h = z->value.lval; | ||
76 | |||
77 | img.elap.tv_sec = img.elap.tv_usec = 0; | ||
78 | ninedogs_now(&img.start); | ||
79 | void *ret = old_gd_imagecreate(e, retv); | ||
80 | if (!retv) | ||
81 | return ret; | ||
82 | |||
83 | if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource | ||
84 | img.im = retv->value.p; | ||
85 | im_add(&img); | ||
86 | } else if (retv->u1.v.type == 2) { // false | ||
87 | img.im = NULL; | ||
88 | } | ||
89 | |||
90 | my_trace("imagecreate", "i", 'R', w, h, &img); | ||
91 | |||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | static void *(*old_gd_imagecreatetruecolor)(struct zend_execute_data *, struct zval *); | ||
96 | static void *my_gd_imagecreatetruecolor(struct zend_execute_data *e, struct zval *retv) | ||
97 | { | ||
98 | unsigned int num_args, s; | ||
99 | struct nd_gd_img img; | ||
100 | long w, h; | ||
101 | |||
102 | num_args = e->This.u2.num_args; | ||
103 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
104 | |||
105 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
106 | |||
107 | // w | ||
108 | struct zval *z = (struct zval *) e + s; s++; | ||
109 | php_zval_dump(" w=", z); | ||
110 | w = z->value.lval; | ||
111 | |||
112 | // h | ||
113 | z = (struct zval *) e + s; s++; | ||
114 | php_zval_dump(" h=", z); | ||
115 | h = z->value.lval; | ||
116 | |||
117 | img.elap.tv_sec = img.elap.tv_usec = 0; | ||
118 | ninedogs_now(&img.start); | ||
119 | void *ret = old_gd_imagecreatetruecolor(e, retv); | ||
120 | if (!retv) | ||
121 | return ret; | ||
122 | |||
123 | if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource | ||
124 | img.im = retv->value.p; | ||
125 | im_add(&img); | ||
126 | } else if (retv->u1.v.type == 2) { // false | ||
127 | img.im = NULL; | ||
128 | } | ||
129 | |||
130 | my_trace("imagecreatetruecolor", "i", 'R', w, h, &img); | ||
131 | |||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | static void *(*old_gd_imagedestroy)(struct zend_execute_data *, struct zval *); | ||
136 | static void *my_gd_imagedestroy(struct zend_execute_data *e, struct zval *retv) | ||
137 | { | ||
138 | unsigned int num_args, s; | ||
139 | struct nd_gd_img *img; | ||
140 | struct timeval end; | ||
141 | void *im; | ||
142 | int r; | ||
143 | |||
144 | num_args = e->This.u2.num_args; | ||
145 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | ||
146 | |||
147 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | ||
148 | |||
149 | // im | ||
150 | struct zval *z = (struct zval *) e + s; s++; | ||
151 | php_zval_dump(" im=", z); | ||
152 | im = z->value.p; | ||
153 | |||
154 | void *ret = old_gd_imagedestroy(e, retv); | ||
155 | if (!retv) | ||
156 | return ret; | ||
157 | |||
158 | img = im_find(im); | ||
159 | if (img) { | ||
160 | ninedogs_now(&end); | ||
161 | my_time_diff(&img->elap, &end, &img->start); | ||
162 | } | ||
163 | |||
164 | if (retv->u1.v.type == 2) // false | ||
165 | r = 0; | ||
166 | else | ||
167 | r = 1; | ||
168 | my_trace("imagedestroy", "i", 'R', img, r); | ||
169 | im_clean(im); | ||
170 | |||
171 | return ret; | ||
172 | } | ||
173 | |||
174 | void php_gd_hook(struct zend_function_entry *fe) | ||
175 | { | ||
176 | if (strcmp(fe->fname, "imagecreate") == 0) { | ||
177 | old_gd_imagecreate = fe->handler; | ||
178 | fe->handler = my_gd_imagecreate; | ||
179 | } else if (strcmp(fe->fname, "imagecreatetruecolor") == 0) { | ||
180 | old_gd_imagecreatetruecolor = fe->handler; | ||
181 | fe->handler = my_gd_imagecreatetruecolor; | ||
182 | } else if (strcmp(fe->fname, "imagedestroy") == 0) { | ||
183 | old_gd_imagedestroy = fe->handler; | ||
184 | fe->handler = my_gd_imagedestroy; | ||
185 | } | ||
186 | } |
File agent/php/gd.h added (mode: 100644) (index 0000000..b041d85) | |||
1 | #include "../php-core.h" | ||
2 | |||
3 | struct nd_gd_img | ||
4 | { | ||
5 | void *im; | ||
6 | struct timeval start, elap; | ||
7 | }; | ||
8 | |||
9 | void php_gd_hook(struct zend_function_entry *fe); |
File agent/process_core.c changed (mode: 100644) (index 28f33e7..f3cc298) | |||
... | ... | void ninedogs_process_core(const unsigned int type, const void *d) | |
34 | 34 | xlog(100, "%s: type=%s\n", __func__, type2name(type)); | xlog(100, "%s: type=%s\n", __func__, type2name(type)); |
35 | 35 | ||
36 | 36 | switch (type) { | switch (type) { |
37 | case NINEDOGS_CORE_START: | ||
37 | case NINEDOGS_CORE_START: { | ||
38 | 38 | if (start.tv_sec > 0) | if (start.tv_sec > 0) |
39 | 39 | return; | return; |
40 | 40 | ||
... | ... | void ninedogs_process_core(const unsigned int type, const void *d) | |
42 | 42 | xlog(101, "%s: DEBUG: set start to %ld.%03ld\n", | xlog(101, "%s: DEBUG: set start to %ld.%03ld\n", |
43 | 43 | __func__, start.tv_sec, start.tv_usec / 1000); | __func__, start.tv_sec, start.tv_usec / 1000); |
44 | 44 | ||
45 | do { | ||
46 | struct utsname u; | ||
47 | |||
48 | int r = uname(&u); | ||
49 | if (r == -1) { | ||
50 | xlog(1, "Cannot call uname: %m\n"); | ||
51 | break; | ||
52 | } | ||
53 | |||
54 | pack(&buf, &len, "T4 NN ss ns" "rs vs" "ms", | ||
55 | NINEDOGS_NET_CORE_UNAME, | ||
56 | u.sysname, strlen(u.sysname), u.nodename, strlen(u.nodename), | ||
57 | u.release, strlen(u.release), u.version, strlen(u.version), | ||
58 | u.machine, strlen(u.machine)); | ||
59 | if (buf) | ||
60 | server_enqueue(buf, len); | ||
61 | } while (0); | ||
62 | break; | ||
63 | |||
64 | case NINEDOGS_CORE_STOP: | ||
45 | struct utsname u; | ||
46 | int r = uname(&u); | ||
47 | if (r == -1) { | ||
48 | xlog(1, "Cannot call uname: %m\n"); | ||
49 | break; | ||
50 | } | ||
51 | |||
52 | pack(&buf, &len, "T4 _t ss ns" "rs vs" "ms", | ||
53 | NINEDOGS_NET_CORE_UNAME, &start, | ||
54 | u.sysname, strlen(u.sysname), u.nodename, strlen(u.nodename), | ||
55 | u.release, strlen(u.release), u.version, strlen(u.version), | ||
56 | u.machine, strlen(u.machine)); | ||
57 | if (buf) | ||
58 | server_enqueue(buf, len); | ||
59 | } break; | ||
60 | |||
61 | case NINEDOGS_CORE_STOP: { | ||
65 | 62 | int *exit_code = (int *) d; | int *exit_code = (int *) d; |
66 | char *s = getenv("NINEDOGS_SYNC_FLUSH"); | ||
63 | char *sync_flush = getenv("NINEDOGS_SYNC_FLUSH"); | ||
67 | 64 | ||
68 | 65 | ninedogs_now(&stop); | ninedogs_now(&stop); |
69 | 66 | xlog(101, "%s: DEBUG: set stop to %ld.%03ld\n", | xlog(101, "%s: DEBUG: set stop to %ld.%03ld\n", |
... | ... | void ninedogs_process_core(const unsigned int type, const void *d) | |
75 | 72 | ninedogs_process_url_flush(); | ninedogs_process_url_flush(); |
76 | 73 | ||
77 | 74 | // TODO: add page faults, wall time, sys time etc. (getrusage) | // TODO: add page faults, wall time, sys time etc. (getrusage) |
78 | pack(&buf, &len, "T4 st tt x4", | ||
75 | pack(&buf, &len, "T4 st _t x4", | ||
79 | 76 | NINEDOGS_NET_CORE_STOP, &start, &stop, *exit_code); | NINEDOGS_NET_CORE_STOP, &start, &stop, *exit_code); |
80 | 77 | if (buf) | if (buf) |
81 | 78 | server_enqueue(buf, len); | server_enqueue(buf, len); |
82 | 79 | ||
83 | server_pat(s ? 1 : 0); | ||
80 | server_pat(sync_flush ? 1 : 0); | ||
84 | 81 | ||
85 | 82 | server_stop(); | server_stop(); |
86 | break; | ||
83 | } break; | ||
87 | 84 | } | } |
88 | 85 | } | } |
89 | 86 |
File agent/process_db.c changed (mode: 100644) (index 6ec5d24..f6d7611) | |||
9 | 9 | #include "process.h" | #include "process.h" |
10 | 10 | #include "process_db.h" | #include "process_db.h" |
11 | 11 | ||
12 | extern void my_trace(const char *func, const char type, ...); | ||
12 | extern void my_trace(const char *func, const char *tf, const char type, ...); | ||
13 | 13 | extern void *(*old_malloc)(size_t size); | extern void *(*old_malloc)(size_t size); |
14 | 14 | extern void (*old_free)(void *p); | extern void (*old_free)(void *p); |
15 | 15 | ||
... | ... | static unsigned int gran = 60; // granularity of reports, in seconds | |
17 | 17 | static unsigned int max_query_len = 8192; // should be received from server? TODO | static unsigned int max_query_len = 8192; // should be received from server? TODO |
18 | 18 | ||
19 | 19 | // query stuff | // query stuff |
20 | static __thread void *last_db_handle; | ||
20 | static __thread struct nd_db_conn *last_db_cn; | ||
21 | 21 | ||
22 | 22 | struct query_node | struct query_node |
23 | 23 | { | { |
... | ... | static void query_reset_node(struct query_node *qn) | |
42 | 42 | qn->process_sum.tv_sec = qn->process_sum.tv_usec = 0; | qn->process_sum.tv_sec = qn->process_sum.tv_usec = 0; |
43 | 43 | qn->rows = qn->aff = qn->count = 0; | qn->rows = qn->aff = qn->count = 0; |
44 | 44 | qn->free_calls = qn->free_errs = 0; | qn->free_calls = qn->free_errs = 0; |
45 | qn->res = NULL; | ||
45 | 46 | } | } |
46 | 47 | ||
47 | 48 | static void query_init_node(struct query_node *qn) | static void query_init_node(struct query_node *qn) |
... | ... | static void query_send_node(const struct query_node *qn) | |
64 | 65 | return; | return; |
65 | 66 | } | } |
66 | 67 | ||
67 | pack(&buf, &len, "T4 hb c8 r8 A8" "_t it at et" "x8 y8", | ||
68 | NINEDOGS_NET_DB_QUERY_STATS, qn->hash, sizeof(qn->hash), qn->count, qn->rows, qn->aff, | ||
68 | pack(&buf, &len, "T4 hb" "c8 r8 A8" "_t it at et" "x8 y8", | ||
69 | NINEDOGS_NET_DB_QUERY_STATS, qn->hash, sizeof(qn->hash), | ||
70 | qn->count, qn->rows, qn->aff, | ||
69 | 71 | &qn->ts, &qn->min, &qn->max, &qn->elap, | &qn->ts, &qn->min, &qn->max, &qn->elap, |
70 | 72 | qn->free_calls, qn->free_errs); | qn->free_calls, qn->free_errs); |
71 | 73 | if (!buf) { | if (!buf) { |
... | ... | static void query_hash(unsigned char *hash, const char *q, const unsigned int q_ | |
83 | 85 | ||
84 | 86 | ///////////////////////////////////////////////////// conn stuff | ///////////////////////////////////////////////////// conn stuff |
85 | 87 | ||
86 | struct conn_node | ||
87 | { | ||
88 | char type; | ||
89 | char pad1[3]; | ||
90 | unsigned int count; // how many connections took place | ||
91 | const void *handle; | ||
92 | char *conn_str; | ||
93 | unsigned int conn_str_len; | ||
94 | unsigned int pad2; | ||
95 | struct timeval last_query_try; | ||
96 | struct timeval ts, min, max, elap; | ||
97 | struct query_node *qh, *qt; | ||
98 | struct conn_node *next; | ||
99 | }; | ||
100 | |||
101 | static __thread struct conn_node *conn_head, *conn_tail; | ||
88 | static __thread struct nd_db_conn *conn_head, *conn_tail; | ||
102 | 89 | ||
103 | static struct conn_node *conn_get(const char type, const char *conn_str, | ||
104 | const unsigned int conn_str_len) | ||
90 | static struct nd_db_conn *conn_get_by_conn_str(const char type, | ||
91 | const char *conn_str, const unsigned int conn_str_len) | ||
105 | 92 | { | { |
106 | struct conn_node *cn; | ||
93 | struct nd_db_conn *cn; | ||
107 | 94 | ||
108 | 95 | xlog(50, "%s: searching for conn_str [%s]\n", __func__, conn_str); | xlog(50, "%s: searching for conn_str [%s]\n", __func__, conn_str); |
109 | 96 | cn = conn_head; | cn = conn_head; |
110 | 97 | while (cn) { | while (cn) { |
111 | 98 | if ((cn->type == type) | if ((cn->type == type) |
112 | 99 | && (cn->conn_str_len == conn_str_len) | && (cn->conn_str_len == conn_str_len) |
113 | && (strcmp(cn->conn_str, conn_str) == 0)) { | ||
114 | xlog(50, " found it; cn=%p cn->handle=%p\n", cn, cn->handle); | ||
100 | && (strncmp(cn->conn_str, conn_str, conn_str_len) == 0)) { | ||
101 | xlog(50, " found it; cn=%p cn->dbh=%p\n", cn, cn->dbh); | ||
115 | 102 | return cn; | return cn; |
116 | 103 | } | } |
117 | 104 | cn = cn->next; | cn = cn->next; |
... | ... | static struct conn_node *conn_get(const char type, const char *conn_str, | |
121 | 108 | return NULL; | return NULL; |
122 | 109 | } | } |
123 | 110 | ||
124 | static struct conn_node *conn_get_by_handle(const void *handle) | ||
111 | static struct nd_db_conn *conn_get_by_dbh(const void *dbh) | ||
125 | 112 | { | { |
126 | struct conn_node *cn; | ||
113 | struct nd_db_conn *cn; | ||
127 | 114 | ||
128 | xlog(50, "%s: searching for conn handle [%p]\n", __func__, handle); | ||
115 | xlog(50, "%s: searching for dbh [%p]\n", __func__, dbh); | ||
129 | 116 | cn = conn_head; | cn = conn_head; |
130 | 117 | while (cn) { | while (cn) { |
131 | if (cn->handle == handle) { | ||
118 | if (cn->dbh == dbh) { | ||
132 | 119 | xlog(50, " found a prev conn cn=%p\n", cn); | xlog(50, " found a prev conn cn=%p\n", cn); |
133 | 120 | return cn; | return cn; |
134 | 121 | } | } |
... | ... | static struct conn_node *conn_get_by_handle(const void *handle) | |
139 | 126 | return NULL; | return NULL; |
140 | 127 | } | } |
141 | 128 | ||
142 | static void conn_reset_node(struct conn_node *cn) | ||
129 | static void conn_reset_node(struct nd_db_conn *cn) | ||
143 | 130 | { | { |
144 | 131 | struct query_node *qn; | struct query_node *qn; |
145 | 132 | ||
... | ... | static void conn_reset_node(struct conn_node *cn) | |
157 | 144 | } | } |
158 | 145 | } | } |
159 | 146 | ||
160 | static void conn_init_node(struct conn_node *cn) | ||
147 | static void conn_init_node(struct nd_db_conn *cn) | ||
161 | 148 | { | { |
162 | 149 | cn->type = '0'; | cn->type = '0'; |
163 | cn->handle = NULL; | ||
150 | cn->dbh = NULL; | ||
164 | 151 | cn->qh = cn->qt = NULL; | cn->qh = cn->qt = NULL; |
165 | 152 | cn->ts.tv_usec = 0; | cn->ts.tv_usec = 0; |
166 | 153 | conn_reset_node(cn); | conn_reset_node(cn); |
167 | 154 | } | } |
168 | 155 | ||
169 | static void conn_send_node(const struct conn_node *cn) | ||
156 | static void conn_send_node(const struct nd_db_conn *cn) | ||
170 | 157 | { | { |
171 | 158 | struct query_node *qn; | struct query_node *qn; |
172 | 159 | unsigned char *buf; | unsigned char *buf; |
... | ... | static void conn_send_node(const struct conn_node *cn) | |
191 | 178 | } | } |
192 | 179 | } | } |
193 | 180 | ||
194 | static void conn_flush_node(struct conn_node *cn, const unsigned int u) | ||
181 | static void conn_flush_node(struct nd_db_conn *cn, const unsigned int u) | ||
195 | 182 | { | { |
196 | 183 | if (cn->ts.tv_sec == 0) | if (cn->ts.tv_sec == 0) |
197 | 184 | cn->ts.tv_sec = u * gran; | cn->ts.tv_sec = u * gran; |
... | ... | static void conn_flush_node(struct conn_node *cn, const unsigned int u) | |
206 | 193 | ||
207 | 194 | static void conn_flush(void) | static void conn_flush(void) |
208 | 195 | { | { |
209 | struct conn_node *cn; | ||
196 | struct nd_db_conn *cn; | ||
210 | 197 | ||
211 | 198 | xlog(50, "%s\n", __func__); | xlog(50, "%s\n", __func__); |
212 | 199 | cn = conn_head; | cn = conn_head; |
... | ... | static void conn_flush(void) | |
219 | 206 | //////////////////// common section | //////////////////// common section |
220 | 207 | static struct query_node *query_get_by_res(const char type, const void *res) | static struct query_node *query_get_by_res(const char type, const void *res) |
221 | 208 | { | { |
222 | struct conn_node *cn; | ||
209 | struct nd_db_conn *cn; | ||
223 | 210 | struct query_node *qn; | struct query_node *qn; |
224 | 211 | ||
225 | xlog(50, "%s: searching for res %p\n", __func__, res); | ||
212 | xlog(50, "%s: searching for type %c and res %p\n", __func__, type, res); | ||
226 | 213 | cn = conn_head; | cn = conn_head; |
227 | 214 | while (cn) { | while (cn) { |
228 | 215 | if (cn->type == type) { | if (cn->type == type) { |
... | ... | static struct query_node *query_get_by_res(const char type, const void *res) | |
244 | 231 | ||
245 | 232 | void query_send_string(const unsigned char *hash) | void query_send_string(const unsigned char *hash) |
246 | 233 | { | { |
247 | struct conn_node *cn; | ||
234 | struct nd_db_conn *cn; | ||
248 | 235 | struct query_node *qn = NULL; | struct query_node *qn = NULL; |
249 | 236 | unsigned char *buf; | unsigned char *buf; |
250 | 237 | unsigned int len; | unsigned int len; |
... | ... | void ninedogs_process_db(const char *func, const unsigned int type, void *d) | |
283 | 270 | unsigned char hash[32]; | unsigned char hash[32]; |
284 | 271 | struct timeval t, elap; | struct timeval t, elap; |
285 | 272 | unsigned int u; | unsigned int u; |
286 | struct conn *cs; | ||
273 | struct nd_db_conn *cn0, *cn; | ||
287 | 274 | struct query *qs; | struct query *qs; |
275 | struct nd_db_stmt *stmt; | ||
288 | 276 | struct timeval end; | struct timeval end; |
289 | 277 | char *q_copy; | char *q_copy; |
290 | 278 | unsigned int q_len; | unsigned int q_len; |
... | ... | void ninedogs_process_db(const char *func, const unsigned int type, void *d) | |
292 | 280 | xlog(100, "%s: type=%u\n", __func__, type); | xlog(100, "%s: type=%u\n", __func__, type); |
293 | 281 | ||
294 | 282 | switch (type) { | switch (type) { |
295 | case NINEDOGS_DB_CONN_START: | ||
296 | cs = (struct conn *) d; | ||
297 | struct conn_node *cn = conn_get(cs->type, cs->conn_str, cs->conn_str_len); | ||
283 | case NINEDOGS_DB_CONN_START: { | ||
284 | cn0 = (struct nd_db_conn *) d; | ||
285 | cn = conn_get_by_conn_str(cn0->type, | ||
286 | cn0->conn_str, cn0->conn_str_len); | ||
298 | 287 | if (!cn) { | if (!cn) { |
299 | char *conn_str_copy = old_malloc(cs->conn_str_len + 1); | ||
288 | char *conn_str_copy = old_malloc(cn0->conn_str_len + 1); | ||
300 | 289 | if (!conn_str_copy) { | if (!conn_str_copy) { |
301 | 290 | xlog(1, " cannot alloc memory!\n"); | xlog(1, " cannot alloc memory!\n"); |
302 | 291 | break; | break; |
303 | 292 | } | } |
304 | memcpy(conn_str_copy, cs->conn_str, cs->conn_str_len); | ||
305 | conn_str_copy[cs->conn_str_len] = '\0'; | ||
293 | memcpy(conn_str_copy, cn0->conn_str, cn0->conn_str_len); | ||
294 | conn_str_copy[cn0->conn_str_len] = '\0'; | ||
306 | 295 | ||
307 | cn = old_malloc(sizeof(struct conn_node)); | ||
296 | cn = old_malloc(sizeof(struct nd_db_conn)); | ||
308 | 297 | if (!cn) { | if (!cn) { |
309 | 298 | xlog(1, " cannot alloc memory!\n"); | xlog(1, " cannot alloc memory!\n"); |
310 | 299 | old_free(conn_str_copy); | old_free(conn_str_copy); |
311 | 300 | break; | break; |
312 | 301 | } | } |
313 | xlog(100, " allocated conn cn=%p\n", cn); | ||
302 | xlog(200, " allocated conn cn=%p\n", cn); | ||
314 | 303 | cn->conn_str = conn_str_copy; | cn->conn_str = conn_str_copy; |
315 | cn->conn_str_len = cs->conn_str_len; | ||
304 | cn->conn_str_len = cn0->conn_str_len; | ||
316 | 305 | conn_init_node(cn); | conn_init_node(cn); |
317 | 306 | cn->next = conn_head; | cn->next = conn_head; |
318 | cn->type = cs->type; | ||
319 | ninedogs_now(&cs->start); | ||
307 | cn->type = cn0->type; | ||
308 | cn->stable = 1; | ||
309 | ninedogs_now(&cn->start); | ||
320 | 310 | ||
321 | 311 | conn_head = cn; | conn_head = cn; |
322 | 312 | if (!conn_tail) | if (!conn_tail) |
323 | 313 | conn_tail = cn; | conn_tail = cn; |
324 | 314 | } | } |
325 | cs->cn = cn; | ||
326 | my_trace(func, 'c', cs); | ||
327 | break; | ||
315 | my_trace(func, "i", 'c', cn); | ||
316 | } break; | ||
328 | 317 | ||
329 | case NINEDOGS_DB_CONN_END: | ||
330 | cs = (struct conn *) d; | ||
331 | cn = cs->cn; | ||
318 | case NINEDOGS_DB_CONN_END: { | ||
319 | cn0 = (struct nd_db_conn *) d; | ||
332 | 320 | ninedogs_now(&end); | ninedogs_now(&end); |
321 | if (cn0->stable == 0) { | ||
322 | cn = conn_get_by_conn_str(cn0->type, | ||
323 | cn0->conn_str, cn0->conn_str_len); | ||
324 | if (!cn) | ||
325 | break; | ||
326 | |||
327 | cn->dbh = cn0->dbh; // only here we have the real one | ||
328 | xlog(1, "DEBUG: cn0->ex=%p\n", cn0->ex); | ||
329 | cn->ex = nd_strdup(cn0->ex, -1); | ||
330 | cn->ex_len = cn0->ex_len; | ||
331 | } else { | ||
332 | cn = cn0; | ||
333 | } | ||
333 | 334 | u = end.tv_sec / gran; | u = end.tv_sec / gran; |
334 | 335 | conn_flush_node(cn, u); | conn_flush_node(cn, u); |
335 | 336 | ||
336 | 337 | cn->count++; | cn->count++; |
337 | cn->handle = cs->dbh; | ||
338 | 338 | cn->ts.tv_sec = u * gran; | cn->ts.tv_sec = u * gran; |
339 | my_time_diff(&elap, &end, &cs->start); | ||
339 | my_time_diff(&elap, &end, &cn->start); | ||
340 | 340 | my_time_add(&cn->elap, &elap); | my_time_add(&cn->elap, &elap); |
341 | 341 | if (my_time_compare(&cn->min, &elap) > 0) | if (my_time_compare(&cn->min, &elap) > 0) |
342 | 342 | cn->min = elap; | cn->min = elap; |
343 | 343 | if (my_time_compare(&cn->max, &elap) < 0) | if (my_time_compare(&cn->max, &elap) < 0) |
344 | 344 | cn->max = elap; | cn->max = elap; |
345 | last_db_handle = cn; | ||
345 | last_db_cn = cn; | ||
346 | 346 | // TODO: if cs->dbh is null, there is an error! | // TODO: if cs->dbh is null, there is an error! |
347 | my_trace(func, 'r', cs); | ||
348 | break; | ||
347 | my_trace(func, "i", 'r', cn); | ||
348 | } break; | ||
349 | 349 | ||
350 | case NINEDOGS_DB_CONN_CLOSE: | ||
351 | cs = (struct conn *) d; | ||
350 | case NINEDOGS_DB_CONN_CLOSE: { // TODO: we should mark the connection as free! | ||
351 | cn0 = (struct nd_db_conn *) d; | ||
352 | if (cn0->stable == 0) { | ||
353 | cn = conn_get_by_dbh(cn0->dbh); | ||
354 | if (!cn) | ||
355 | break; | ||
356 | } else { | ||
357 | cn = cn0; | ||
358 | } | ||
352 | 359 | ||
353 | if (last_db_handle == cs) | ||
354 | last_db_handle = NULL; | ||
360 | if (last_db_cn == cn) | ||
361 | last_db_cn = NULL; | ||
355 | 362 | ||
356 | my_trace(func, 'R', cs); | ||
357 | break; | ||
363 | my_trace(func, "i", 'R', cn); | ||
364 | } break; | ||
358 | 365 | ||
359 | case NINEDOGS_DB_QUERY_START: | ||
366 | case NINEDOGS_DB_QUERY_START: { | ||
360 | 367 | qs = (struct query *) d; | qs = (struct query *) d; |
361 | 368 | ||
362 | 369 | if (qs->q_len > max_query_len) | if (qs->q_len > max_query_len) |
... | ... | void ninedogs_process_db(const char *func, const unsigned int type, void *d) | |
365 | 372 | q_len = qs->q_len; | q_len = qs->q_len; |
366 | 373 | ||
367 | 374 | if (qs->dbh == NULL) { | if (qs->dbh == NULL) { |
368 | if (last_db_handle == NULL) { | ||
369 | xlog(100, " last_db_handle is NULL!\n"); | ||
375 | if (last_db_cn == NULL) { | ||
376 | xlog(100, " last_db_cn is NULL!\n"); | ||
370 | 377 | break; | break; |
371 | 378 | } | } |
372 | cn = last_db_handle; | ||
379 | cn = last_db_cn; | ||
373 | 380 | } else { | } else { |
374 | cn = conn_get_by_handle(qs->dbh); | ||
381 | cn = conn_get_by_dbh(qs->dbh); | ||
375 | 382 | if (!cn) | if (!cn) |
376 | 383 | break; | break; |
377 | 384 | } | } |
... | ... | void ninedogs_process_db(const char *func, const unsigned int type, void *d) | |
415 | 422 | old_free(q_copy); | old_free(q_copy); |
416 | 423 | break; | break; |
417 | 424 | } | } |
418 | xlog(100, " allocated qn=%p for res %p\n", qn, qs->res); | ||
419 | 425 | query_init_node(qn); | query_init_node(qn); |
420 | 426 | memcpy(qn->hash, hash, sizeof(qn->hash)); | memcpy(qn->hash, hash, sizeof(qn->hash)); |
421 | 427 | qn->query = q_copy; | qn->query = q_copy; |
... | ... | void ninedogs_process_db(const char *func, const unsigned int type, void *d) | |
427 | 433 | cn->qt = qn; | cn->qt = qn; |
428 | 434 | } | } |
429 | 435 | qs->qn = qn; | qs->qn = qn; |
430 | my_trace(func, 'c', qs); | ||
431 | break; | ||
436 | my_trace(func, "i", 'c', qs); | ||
437 | } break; | ||
432 | 438 | ||
433 | case NINEDOGS_DB_QUERY_END: | ||
439 | case NINEDOGS_DB_QUERY_END: { | ||
434 | 440 | qs = (struct query *) d; | qs = (struct query *) d; |
435 | 441 | ninedogs_now(&end); | ninedogs_now(&end); |
436 | 442 | u = end.tv_sec / gran; | u = end.tv_sec / gran; |
... | ... | void ninedogs_process_db(const char *func, const unsigned int type, void *d) | |
447 | 453 | qn->res = qs->res; | qn->res = qs->res; |
448 | 454 | qn->rows += qs->num; | qn->rows += qs->num; |
449 | 455 | qn->aff += qs->aff; | qn->aff += qs->aff; |
450 | my_time_diff(&elap, &qs->end, &qs->start); | ||
456 | my_time_diff(&elap, &end, &qs->start); | ||
451 | 457 | my_time_add(&qn->elap, &elap); | my_time_add(&qn->elap, &elap); |
452 | 458 | if (my_time_compare(&qn->min, &elap) > 0) | if (my_time_compare(&qn->min, &elap) > 0) |
453 | 459 | qn->min = elap; | qn->min = elap; |
... | ... | void ninedogs_process_db(const char *func, const unsigned int type, void *d) | |
457 | 463 | xlog(100, " set qn->last_start from qs->start\n"); | xlog(100, " set qn->last_start from qs->start\n"); |
458 | 464 | qn->last_start = qs->start; | qn->last_start = qs->start; |
459 | 465 | } | } |
460 | my_trace(func, 'r', qs); | ||
461 | break; | ||
466 | my_trace(func, "i", 'r', qs); | ||
467 | } break; | ||
462 | 468 | ||
463 | 469 | case NINEDOGS_DB_FETCH_START: | case NINEDOGS_DB_FETCH_START: |
464 | 470 | qs = (struct query *) d; | qs = (struct query *) d; |
465 | my_trace(func, 'c', qs); | ||
471 | my_trace(func, "i", 'c', qs); | ||
466 | 472 | break; | break; |
467 | 473 | ||
468 | 474 | case NINEDOGS_DB_FETCH_END: | case NINEDOGS_DB_FETCH_END: |
469 | 475 | qs = (struct query *) d; | qs = (struct query *) d; |
470 | my_trace(func, 'r', qs); | ||
476 | my_trace(func, "i", 'r', qs); | ||
477 | break; | ||
478 | |||
479 | case NINEDOGS_DB_RESULT_GET_START: | ||
480 | stmt = (struct nd_db_stmt *) d; | ||
481 | my_trace(func, "i", 'c', stmt); | ||
482 | break; | ||
483 | |||
484 | case NINEDOGS_DB_RESULT_GET_END: | ||
485 | stmt = (struct nd_db_stmt *) d; | ||
486 | my_trace(func, "i", 'r', stmt); | ||
471 | 487 | break; | break; |
472 | 488 | ||
473 | 489 | case NINEDOGS_DB_PREPARE_START: | case NINEDOGS_DB_PREPARE_START: |
474 | my_trace(func, 'c', (struct prepare *) d); | ||
490 | my_trace(func, "i", 'c', (struct prepare *) d); | ||
475 | 491 | break; | break; |
476 | 492 | ||
477 | 493 | case NINEDOGS_DB_PREPARE_END: | case NINEDOGS_DB_PREPARE_END: |
478 | my_trace(func, 'r', (struct prepare *) d); | ||
494 | my_trace(func, "i", 'r', (struct prepare *) d); | ||
479 | 495 | break; | break; |
480 | 496 | ||
481 | 497 | case NINEDOGS_DB_EXECUTE_START: | case NINEDOGS_DB_EXECUTE_START: |
482 | my_trace(func, 'c', (struct nd_db_execute *) d); | ||
498 | my_trace(func, "i", 'c', d); | ||
483 | 499 | break; | break; |
484 | 500 | ||
485 | 501 | case NINEDOGS_DB_EXECUTE_END: | case NINEDOGS_DB_EXECUTE_END: |
486 | my_trace(func, 'r', (struct nd_db_execute *) d); | ||
502 | my_trace(func, "i", 'r', d); | ||
503 | break; | ||
504 | |||
505 | case NINEDOGS_DB_STATEMENT_CREATE_END: | ||
506 | my_trace(func, "i", 'R', (struct nd_db_stmt *) d); | ||
507 | break; | ||
508 | |||
509 | case NINEDOGS_DB_STATEMENT_CLOSE_END: | ||
510 | my_trace(func, "i", 'R', (struct nd_db_stmt *) d); | ||
487 | 511 | break; | break; |
488 | 512 | ||
489 | 513 | case NINEDOGS_DB_AUTOCOMMIT_START: | case NINEDOGS_DB_AUTOCOMMIT_START: |
490 | my_trace(func, 'c', (struct db_autocommit *) d); | ||
514 | my_trace(func, "i", 'c', (struct db_autocommit *) d); | ||
491 | 515 | break; | break; |
492 | 516 | ||
493 | 517 | case NINEDOGS_DB_AUTOCOMMIT_END: | case NINEDOGS_DB_AUTOCOMMIT_END: |
494 | my_trace(func, 'r', (struct db_autocommit *) d); | ||
518 | my_trace(func, "i", 'r', (struct db_autocommit *) d); | ||
495 | 519 | break; | break; |
496 | 520 | ||
497 | 521 | case NINEDOGS_DB_BIND_PARAM_START: | case NINEDOGS_DB_BIND_PARAM_START: |
498 | my_trace(func, 'c', (struct nd_db_bind *) d); | ||
522 | my_trace(func, "i", 'c', (struct nd_db_bind *) d); | ||
499 | 523 | break; | break; |
500 | 524 | ||
501 | 525 | case NINEDOGS_DB_BIND_PARAM_END: | case NINEDOGS_DB_BIND_PARAM_END: |
502 | my_trace(func, 'r', (struct nd_db_bind *) d); | ||
526 | my_trace(func, "i", 'r', (struct nd_db_bind *) d); | ||
527 | break; | ||
528 | |||
529 | case NINEDOGS_DB_BIND_ONE_PARAM: | ||
530 | // We need to search for statement first and copy the parameter. why? | ||
531 | my_trace(func, "i", 'R', d); | ||
503 | 532 | break; | break; |
504 | 533 | ||
505 | case NINEDOGS_DB_FREE_RESULT: | ||
534 | case NINEDOGS_DB_FREE_RESULT: { | ||
506 | 535 | struct free_result *fr = (struct free_result *) d; | struct free_result *fr = (struct free_result *) d; |
507 | 536 | ||
508 | 537 | qn = query_get_by_res(fr->type, fr->res); | qn = query_get_by_res(fr->type, fr->res); |
... | ... | void ninedogs_process_db(const char *func, const unsigned int type, void *d) | |
516 | 545 | //my_time_add(&qn->process_sum, &elap); | //my_time_add(&qn->process_sum, &elap); |
517 | 546 | ||
518 | 547 | qn->res = NULL; | qn->res = NULL; |
519 | my_trace(func, 'R', fr); | ||
548 | my_trace(func, "i", 'R', fr); | ||
549 | } break; | ||
550 | |||
551 | case NINEDOGS_DB_STMT_CLOSE_START: | ||
552 | my_trace(func, "i", 'c', (struct nd_db_stmt *) d); | ||
520 | 553 | break; | break; |
554 | |||
555 | case NINEDOGS_DB_STMT_CLOSE_END: | ||
556 | my_trace(func, "i", 'r', (struct nd_db_stmt *) d); | ||
557 | break; | ||
558 | |||
521 | 559 | } | } |
522 | 560 | ||
523 | 561 | ninedogs_process_post(); | ninedogs_process_post(); |
... | ... | void ninedogs_process_db_flush(void) | |
529 | 567 | ||
530 | 568 | conn_flush(); | conn_flush(); |
531 | 569 | } | } |
570 | |||
571 | void nd_db_qs_init(const char type, struct query *qs) | ||
572 | { | ||
573 | qs->type = type; | ||
574 | qs->q = NULL; | ||
575 | for (unsigned short i = 0; i < ND_PARAMS_MAX; i++) | ||
576 | qs->params.list[i].type = ND_TYPE_FREE_SLOT; | ||
577 | } | ||
578 | |||
579 | void nd_db_stmt_init(const char type, struct nd_db_stmt *s) | ||
580 | { | ||
581 | s->type = type; | ||
582 | s->q = NULL; | ||
583 | for (unsigned short i = 0; i < ND_PARAMS_MAX; i++) | ||
584 | s->params.list[i].type = ND_TYPE_FREE_SLOT; | ||
585 | } |
File agent/process_db.h changed (mode: 100644) (index dce5b00..f33d8b8) | |||
1 | #include <sys/time.h> | ||
1 | #ifndef NINEDOGS_PROCESS_DB_H | ||
2 | #define NINEDOGS_PROCESS_DB_H 1 | ||
2 | 3 | ||
3 | struct conn | ||
4 | { | ||
5 | void *cn; // this is used in process_db | ||
6 | char type; | ||
7 | char ret; | ||
8 | char pad1[2]; | ||
9 | unsigned int conn_str_len; | ||
10 | char *conn_str; | ||
11 | void *dbh; | ||
12 | struct timeval start; | ||
13 | int flags; // used at least by mysqli_real_connect | ||
14 | int pad2; | ||
15 | }; | ||
4 | #include <sys/time.h> | ||
16 | 5 | ||
17 | #define ND_PARAMS_MAX 100 | ||
6 | #include "../common/params.h" | ||
18 | 7 | ||
19 | #define ND_PARAMS_TYPE_NULL 0 | ||
20 | #define ND_PARAMS_TYPE_LONG 1 | ||
21 | #define ND_PARAMS_TYPE_DOUBLE 2 | ||
22 | #define ND_PARAMS_TYPE_STRING 3 | ||
23 | struct params_array_one | ||
8 | struct nd_db_conn | ||
24 | 9 | { | { |
25 | unsigned char type; // see ND_PARAMS_TYPE_* | ||
26 | unsigned char pad1; | ||
27 | unsigned short length; // for 'str' | ||
28 | unsigned char pad2[4]; | ||
29 | union { | ||
30 | char *str; | ||
31 | double d; | ||
32 | long l; | ||
33 | }; | ||
34 | }; | ||
35 | |||
36 | struct params_array | ||
37 | { | ||
38 | unsigned short len; | ||
39 | unsigned short pad[3]; | ||
40 | struct params_array_one list[ND_PARAMS_MAX]; | ||
10 | char type; | ||
11 | char pad1; | ||
12 | unsigned short ex_len; | ||
13 | unsigned int count; // how many connections took place | ||
14 | const void *dbh; | ||
15 | const char *conn_str, *ex; | ||
16 | unsigned short conn_str_len; | ||
17 | unsigned short ok:1; // TODO: we should store this in 'res' | ||
18 | unsigned short stable:1; // if 1, it is a real cn, not one passed to process_db | ||
19 | unsigned short pad2:14; | ||
20 | unsigned int flags; | ||
21 | struct timeval last_query_try, start; | ||
22 | struct timeval ts, min, max, elap; | ||
23 | struct query_node *qh, *qt; | ||
24 | struct nd_db_conn *next; | ||
41 | 25 | }; | }; |
42 | 26 | ||
43 | 27 | struct query | struct query |
44 | 28 | { | { |
45 | 29 | void *cn; // this is used in process_db | void *cn; // this is used in process_db |
46 | 30 | void *qn; // this is used in process_db | void *qn; // this is used in process_db |
47 | struct params_array params; // this is used in process_db | ||
31 | struct nd_params_array params; // this is used in process_db | ||
48 | 32 | char type; | char type; |
49 | 33 | char ret; // used at least by mysqli_fetch_array | char ret; // used at least by mysqli_fetch_array |
50 | 34 | char pad1[2]; | char pad1[2]; |
... | ... | struct query | |
52 | 36 | unsigned int q_len; | unsigned int q_len; |
53 | 37 | unsigned int pad2; | unsigned int pad2; |
54 | 38 | void *dbh; | void *dbh; |
55 | struct timeval start, end; | ||
56 | char *q; | ||
39 | struct timeval start; | ||
40 | const char *q; | ||
57 | 41 | char *err, *err_code; | char *err, *err_code; |
58 | 42 | unsigned long num, aff, mode; // 'mode' is used by mysql | unsigned long num, aff, mode; // 'mode' is used by mysql |
59 | 43 | void *res; | void *res; |
... | ... | struct free_result | |
68 | 52 | void *res; | void *res; |
69 | 53 | }; | }; |
70 | 54 | ||
71 | struct prepare | ||
72 | { | ||
73 | char *q; | ||
74 | char type; | ||
75 | char ret; | ||
76 | char pad[2]; | ||
77 | unsigned int q_len; | ||
78 | void *dbh; | ||
79 | void *stmt; | ||
80 | }; | ||
81 | |||
82 | struct nd_db_execute | ||
55 | #define ND_DB_STMT_RET_IS_BOOL 1 | ||
56 | struct nd_db_stmt | ||
83 | 57 | { | { |
84 | 58 | void *stmt; | void *stmt; |
85 | struct params_array params; // this is used in process_db | ||
59 | const char *q, *ex; | ||
60 | struct nd_params_array params; // this is used in process_db | ||
86 | 61 | char type; | char type; |
87 | 62 | char ret; | char ret; |
88 | char pad1[6]; | ||
63 | unsigned short flags; // See ND_DB_STMT_* | ||
64 | unsigned int q_len; // TODO decide between 16 and 32 | ||
65 | void *dbh; | ||
66 | void *res; | ||
89 | 67 | unsigned long num, aff; | unsigned long num, aff; |
68 | unsigned short ex_len; | ||
69 | unsigned short pad[3]; | ||
70 | // db specific | ||
71 | union { | ||
72 | struct { | ||
73 | long mode; | ||
74 | } oci; | ||
75 | }; | ||
90 | 76 | }; | }; |
91 | 77 | ||
92 | 78 | struct db_autocommit | struct db_autocommit |
... | ... | void ninedogs_process_db(const char *func, const unsigned int type, void *d); | |
115 | 101 | ||
116 | 102 | void ninedogs_process_db_flush(void); | void ninedogs_process_db_flush(void); |
117 | 103 | ||
104 | void nd_db_qs_init(const char type, struct query *qs); | ||
105 | void nd_db_stmt_init(const char type, struct nd_db_stmt *s); | ||
106 | |||
107 | #endif |
File agent/process_ssl.c changed (mode: 100644) (index ef05bcf..e1fce02) | |||
... | ... | static void send_info(const char *info, const unsigned short info_len) | |
17 | 17 | unsigned char *buf; | unsigned char *buf; |
18 | 18 | unsigned int len; | unsigned int len; |
19 | 19 | ||
20 | pack(&buf, &len, "T4 NN vs", | ||
20 | pack(&buf, &len, "T4 _N vs", | ||
21 | 21 | NINEDOGS_NET_SSL_INFO, info, info_len); | NINEDOGS_NET_SSL_INFO, info, info_len); |
22 | 22 | if (!buf) | if (!buf) |
23 | 23 | return; | return; |
... | ... | static void cert_send_node(const struct cert *cn) | |
32 | 32 | unsigned char *buf; | unsigned char *buf; |
33 | 33 | unsigned int len; | unsigned int len; |
34 | 34 | ||
35 | pack(&buf, &len, "T4 NN ps" "us" "is" "s8 e8" "nb tc as" "ks K4", | ||
35 | pack(&buf, &len, "T4 _N ps" "us" "is" "s8 e8" "nb tc as" "ks K4", | ||
36 | 36 | NINEDOGS_NET_SSL_CERT, cn->uri, cn->uri_len, | NINEDOGS_NET_SSL_CERT, cn->uri, cn->uri_len, |
37 | 37 | cn->subj, cn->subj_len, | cn->subj, cn->subj_len, |
38 | 38 | cn->issuer, cn->issuer_len, | cn->issuer, cn->issuer_len, |
... | ... | void ninedogs_process_ssl(const unsigned int type, const void *d) | |
148 | 148 | xlog(10, "%s: type=%s d=%p\n", __func__, type2name(type), d); | xlog(10, "%s: type=%s d=%p\n", __func__, type2name(type), d); |
149 | 149 | ||
150 | 150 | switch (type) { | switch (type) { |
151 | case NINEDOGS_SSL_INFO: | ||
151 | case NINEDOGS_SSL_INFO: { | ||
152 | 152 | const struct ssl_info *i = (const struct ssl_info *) d; | const struct ssl_info *i = (const struct ssl_info *) d; |
153 | 153 | send_info(i->info, i->info_len); | send_info(i->info, i->info_len); |
154 | break; | ||
154 | } break; | ||
155 | 155 | ||
156 | case NINEDOGS_SSL_CERT: | ||
156 | case NINEDOGS_SSL_CERT: { | ||
157 | 157 | const struct cert *c = (const struct cert *) d; | const struct cert *c = (const struct cert *) d; |
158 | 158 | char send = 0; | char send = 0; |
159 | 159 | cn = cert_get_by_uri(c->uri); | cn = cert_get_by_uri(c->uri); |
... | ... | void ninedogs_process_ssl(const unsigned int type, const void *d) | |
197 | 197 | ||
198 | 198 | if (send) | if (send) |
199 | 199 | cert_send_node(cn); | cert_send_node(cn); |
200 | break; | ||
200 | } break; | ||
201 | 201 | } | } |
202 | 202 | ||
203 | 203 | ninedogs_process_post(); | ninedogs_process_post(); |
File agent/process_url.c changed (mode: 100644) (index 864a37a..042135f) | |||
9 | 9 | #include "process.h" | #include "process.h" |
10 | 10 | #include "process_url.h" | #include "process_url.h" |
11 | 11 | ||
12 | extern void my_trace(const char *func, const char type, ...); | ||
12 | extern void my_trace(const char *func, const char *tf, const char type, ...); | ||
13 | 13 | extern void *(*old_malloc)(size_t size); | extern void *(*old_malloc)(size_t size); |
14 | 14 | extern void (*old_free)(void *p); | extern void (*old_free)(void *p); |
15 | 15 | ||
... | ... | void ninedogs_process_url(const char *func, const unsigned int type, void *d) | |
222 | 222 | switch (type) { | switch (type) { |
223 | 223 | // url may be null! we need to intercept 'setopt' and use it | // url may be null! we need to intercept 'setopt' and use it |
224 | 224 | // TODO: what is the reason to hook this for stats?! Only to capture the url | // TODO: what is the reason to hook this for stats?! Only to capture the url |
225 | case NINEDOGS_URL_INIT_END: | ||
225 | case NINEDOGS_URL_INIT_END: { | ||
226 | 226 | in = (struct nd_url *) d; | in = (struct nd_url *) d; |
227 | 227 | q = search_or_create(in); | q = search_or_create(in); |
228 | 228 | if (!q) | if (!q) |
229 | 229 | break; | break; |
230 | my_trace(func, 'R', in); | ||
231 | break; | ||
230 | my_trace(func, "i", 'R', in); | ||
231 | } break; | ||
232 | 232 | ||
233 | case NINEDOGS_URL_SETOPT_END: | ||
233 | case NINEDOGS_URL_SETOPT_END: { | ||
234 | 234 | in = (struct nd_url *) d; | in = (struct nd_url *) d; |
235 | 235 | q = search_or_create(in); | q = search_or_create(in); |
236 | 236 | if (!q) | if (!q) |
237 | 237 | break; | break; |
238 | my_trace(func, 'R', in); | ||
239 | break; | ||
238 | my_trace(func, "i", 'R', in); | ||
239 | } break; | ||
240 | 240 | ||
241 | case NINEDOGS_URL_CLOSE_END: | ||
241 | case NINEDOGS_URL_CLOSE_END: { | ||
242 | 242 | in = (struct nd_url *) d; | in = (struct nd_url *) d; |
243 | 243 | q = search_or_create(in); | q = search_or_create(in); |
244 | 244 | if (!q) | if (!q) |
245 | 245 | break; | break; |
246 | my_trace(func, 'R', in); | ||
247 | break; | ||
246 | my_trace(func, "i", 'R', in); | ||
247 | } break; | ||
248 | 248 | ||
249 | case NINEDOGS_URL_START: | ||
249 | case NINEDOGS_URL_START: { | ||
250 | 250 | in = (struct nd_url *) d; | in = (struct nd_url *) d; |
251 | 251 | q = search_or_create(in); | q = search_or_create(in); |
252 | 252 | if (!q) | if (!q) |
253 | 253 | break; | break; |
254 | 254 | ||
255 | 255 | in->node = q; // to be used in _END | in->node = q; // to be used in _END |
256 | my_trace(func, 'c', in); | ||
256 | my_trace(func, "i", 'c', in); | ||
257 | 257 | ninedogs_now(&in->start); | ninedogs_now(&in->start); |
258 | break; | ||
258 | } break; | ||
259 | 259 | ||
260 | case NINEDOGS_URL_END: | ||
260 | case NINEDOGS_URL_END: { | ||
261 | 261 | in = (struct nd_url *) d; | in = (struct nd_url *) d; |
262 | 262 | ninedogs_now(&end); | ninedogs_now(&end); |
263 | 263 | u = end.tv_sec / gran; | u = end.tv_sec / gran; |
... | ... | void ninedogs_process_url(const char *func, const unsigned int type, void *d) | |
282 | 282 | } else { | } else { |
283 | 283 | q->errors++; | q->errors++; |
284 | 284 | } | } |
285 | my_trace(func, 'r', in); | ||
286 | break; | ||
285 | my_trace(func, "i", 'r', in); | ||
286 | } break; | ||
287 | 287 | } | } |
288 | 288 | ||
289 | 289 | ninedogs_process_post(); | ninedogs_process_post(); |
File agent/python.c changed (mode: 100644) (index e08913e..e1e504f) | |||
... | ... | static char *python_get_value(const struct zval *z) | |
213 | 213 | case 3: return ""; | case 3: return ""; |
214 | 214 | case 4: snprintf(ret, sizeof(ret), "%ld", z->value.lval); return ret; | case 4: snprintf(ret, sizeof(ret), "%ld", z->value.lval); return ret; |
215 | 215 | case 5: snprintf(ret, sizeof(ret), "%f", z->value.dval); return ret; | case 5: snprintf(ret, sizeof(ret), "%f", z->value.dval); return ret; |
216 | case 6: | ||
216 | case 6: { | ||
217 | 217 | struct zend_string *zs = z->value.str; | struct zend_string *zs = z->value.str; |
218 | return zs->val; | ||
218 | return zs->val; } | ||
219 | 219 | case 8: | case 8: |
220 | 220 | snprintf(ret, sizeof(ret), "%p", z->value.p); return ret; | snprintf(ret, sizeof(ret), "%p", z->value.p); return ret; |
221 | 221 | case 9: | case 9: |
... | ... | static void python_zed_dump(const char *prefix, struct zend_execute_data *p) | |
308 | 308 | } | } |
309 | 309 | } | } |
310 | 310 | ||
311 | #if 0 | ||
311 | 312 | static void zend_array_to_params_array(struct query *q, struct zend_array *za) | static void zend_array_to_params_array(struct query *q, struct zend_array *za) |
312 | 313 | { | { |
313 | 314 | unsigned int i = 0, max; | unsigned int i = 0, max; |
... | ... | static void zend_array_to_params_array(struct query *q, struct zend_array *za) | |
343 | 344 | bs, bs->h, zs, python_get_type(_z), python_get_value(_z)); | bs, bs->h, zs, python_get_type(_z), python_get_value(_z)); |
344 | 345 | ||
345 | 346 | if (_z->u1.v.type == 4) { | if (_z->u1.v.type == 4) { |
346 | q->params.list[i].type = ND_PARAMS_TYPE_LONG; | ||
347 | q->params.list[i].type = ND_TYPE_LONG; | ||
347 | 348 | q->params.list[i].l = _z->value.lval; | q->params.list[i].l = _z->value.lval; |
348 | 349 | } else if (_z->u1.v.type == 5) { | } else if (_z->u1.v.type == 5) { |
349 | q->params.list[i].type = ND_PARAMS_TYPE_DOUBLE; | ||
350 | q->params.list[i].type = ND_TYPE_DOUBLE; | ||
350 | 351 | q->params.list[i].d = _z->value.dval; | q->params.list[i].d = _z->value.dval; |
351 | 352 | } else if (_z->u1.v.type == 6) { | } else if (_z->u1.v.type == 6) { |
352 | q->params.list[i].type = ND_PARAMS_TYPE_STRING; | ||
353 | q->params.list[i].type = ND_TYPE_STRING; | ||
353 | 354 | struct zend_string *zs = _z->value.str; | struct zend_string *zs = _z->value.str; |
354 | 355 | q->params.list[i].str = zs->val; | q->params.list[i].str = zs->val; |
355 | 356 | q->params.list[i].length = zs->len; | q->params.list[i].length = zs->len; |
... | ... | static void zend_array_to_params_array(struct query *q, struct zend_array *za) | |
360 | 361 | break; | break; |
361 | 362 | } | } |
362 | 363 | } | } |
364 | #endif | ||
363 | 365 | ||
364 | 366 | void *(*old_python_pg_last_error)(struct zend_execute_data *, struct zval *); | void *(*old_python_pg_last_error)(struct zend_execute_data *, struct zval *); |
365 | 367 | static void *my_pg_last_error(struct zend_execute_data *e, struct zval *retv) | static void *my_pg_last_error(struct zend_execute_data *e, struct zval *retv) |
... | ... | static void *my_pg_close(struct zend_execute_data *e, struct zval *retv) | |
386 | 388 | void *ret; | void *ret; |
387 | 389 | unsigned int num_args, s; | unsigned int num_args, s; |
388 | 390 | struct zval *z; | struct zval *z; |
389 | struct conn cs; | ||
391 | struct nd_db_conn c; | ||
390 | 392 | ||
391 | 393 | num_args = e->This.u2.num_args; | num_args = e->This.u2.num_args; |
392 | 394 | //xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | //xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); |
393 | 395 | ||
394 | cs.type = 'P'; | ||
396 | c.type = 'P'; | ||
395 | 397 | if (num_args == 1) { | if (num_args == 1) { |
396 | 398 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); |
397 | 399 | // handler, may be null | // handler, may be null |
398 | 400 | z = (struct zval *) e + s; s++; | z = (struct zval *) e + s; s++; |
399 | cs.dbh = z->value.p; | ||
400 | //xlog(101, " h=%p\n", cs.dbh); | ||
401 | c.dbh = z->value.p; | ||
402 | //xlog(101, " h=%p\n", c.dbh); | ||
401 | 403 | } else { | } else { |
402 | cs.dbh = NULL; | ||
404 | c.dbh = NULL; | ||
403 | 405 | } | } |
404 | 406 | ||
405 | 407 | ret = old_python_pg_close(e, retv); | ret = old_python_pg_close(e, retv); |
406 | ninedogs_process_db("pg_close", NINEDOGS_DB_CONN_CLOSE, &cs); | ||
408 | ninedogs_process_db("pg_close", NINEDOGS_DB_CONN_CLOSE, &c); | ||
407 | 409 | ||
408 | 410 | return ret; | return ret; |
409 | 411 | } | } |
... | ... | static void *my_pg_connect(struct zend_execute_data *e, struct zval *retv) | |
415 | 417 | unsigned int num_args, s; | unsigned int num_args, s; |
416 | 418 | struct zval *z; | struct zval *z; |
417 | 419 | struct zend_string *q; | struct zend_string *q; |
418 | struct conn cs; | ||
420 | struct nd_db_conn c; | ||
419 | 421 | ||
420 | 422 | num_args = e->This.u2.num_args; | num_args = e->This.u2.num_args; |
421 | 423 | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args); |
422 | 424 | ||
423 | 425 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); |
424 | cs.type = 'P'; | ||
426 | c.type = 'P'; | ||
425 | 427 | ||
426 | 428 | // connection string | // connection string |
427 | 429 | z = (struct zval *) e + s; s++; | z = (struct zval *) e + s; s++; |
428 | 430 | q = z->value.str; | q = z->value.str; |
429 | cs.conn_str = q->val; | ||
430 | cs.conn_str_len = q->len; | ||
431 | //xlog(50, " conn[%u]: %s\n", cs.conn_str_len, cs.conn_str); | ||
431 | c.conn_str = q->val; | ||
432 | c.conn_str_len = q->len; | ||
433 | //xlog(50, " conn[%u]: %s\n", c.conn_str_len, c.conn_str); | ||
432 | 434 | ||
433 | ninedogs_process_db("pg_connect", NINEDOGS_DB_CONN_START, &cs); | ||
435 | ninedogs_process_db("pg_connect", NINEDOGS_DB_CONN_START, &c); | ||
434 | 436 | ret = old_python_pg_connect(e, retv); | ret = old_python_pg_connect(e, retv); |
435 | 437 | if (!retv) { | if (!retv) { |
436 | 438 | xlog(0, "DEBUG: old_python_pg_connect returned retv NULL\n"); | xlog(0, "DEBUG: old_python_pg_connect returned retv NULL\n"); |
... | ... | static void *my_pg_connect(struct zend_execute_data *e, struct zval *retv) | |
442 | 444 | ||
443 | 445 | // python7 returns resource, python8.1 returns object | // python7 returns resource, python8.1 returns object |
444 | 446 | if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) | if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) |
445 | cs.dbh = retv->value.p; | ||
447 | c.dbh = retv->value.p; | ||
446 | 448 | else | else |
447 | cs.dbh = NULL; | ||
448 | ninedogs_process_db("pg_connect", NINEDOGS_DB_CONN_END, &cs); | ||
449 | c.dbh = NULL; | ||
450 | ninedogs_process_db("pg_connect", NINEDOGS_DB_CONN_END, &c); | ||
449 | 451 | ||
450 | 452 | return ret; | return ret; |
451 | 453 | } | } |
... | ... | static void *my_pg_pconnect(struct zend_execute_data *e, struct zval *retv) | |
457 | 459 | unsigned int num_args, s; | unsigned int num_args, s; |
458 | 460 | struct zval *z; | struct zval *z; |
459 | 461 | struct zend_string *q; | struct zend_string *q; |
460 | struct conn cs; | ||
462 | struct nd_db_conn c; | ||
461 | 463 | ||
462 | 464 | num_args = e->This.u2.num_args; | num_args = e->This.u2.num_args; |
463 | 465 | xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args); | xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args); |
464 | 466 | ||
465 | 467 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); |
466 | cs.type = 'P'; | ||
468 | c.type = 'P'; | ||
467 | 469 | ||
468 | 470 | // connection string | // connection string |
469 | 471 | z = (struct zval *) e + s; s++; | z = (struct zval *) e + s; s++; |
470 | 472 | q = z->value.str; | q = z->value.str; |
471 | cs.conn_str = q->val; | ||
472 | cs.conn_str_len = q->len; | ||
473 | xlog(50, " conn: %s\n", cs.conn_str); | ||
473 | c.conn_str = q->val; | ||
474 | c.conn_str_len = q->len; | ||
475 | xlog(50, " conn: %s\n", c.conn_str); | ||
474 | 476 | ||
475 | ninedogs_process_db("pg_pconnect", NINEDOGS_DB_CONN_START, &cs); | ||
477 | ninedogs_process_db("pg_pconnect", NINEDOGS_DB_CONN_START, &c); | ||
476 | 478 | ret = old_python_pg_pconnect(e, retv); | ret = old_python_pg_pconnect(e, retv); |
477 | 479 | if (!retv) | if (!retv) |
478 | 480 | return ret; | return ret; |
... | ... | static void *my_pg_pconnect(struct zend_execute_data *e, struct zval *retv) | |
482 | 484 | ||
483 | 485 | // python7 returns resource, python8.1 returns object | // python7 returns resource, python8.1 returns object |
484 | 486 | if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) | if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) |
485 | cs.dbh = retv->value.p; | ||
487 | c.dbh = retv->value.p; | ||
486 | 488 | else | else |
487 | cs.dbh = NULL; | ||
488 | ninedogs_process_db("pg_pconnect", NINEDOGS_DB_CONN_END, &cs); | ||
489 | c.dbh = NULL; | ||
490 | ninedogs_process_db("pg_pconnect", NINEDOGS_DB_CONN_END, &c); | ||
489 | 491 | ||
490 | 492 | return ret; | return ret; |
491 | 493 | } | } |
... | ... | static void *my_pg_query(struct zend_execute_data *e, struct zval *retv) | |
619 | 621 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); |
620 | 622 | para = (struct zval *) e + s; | para = (struct zval *) e + s; |
621 | 623 | qs.type = 'P'; // if dbh is null, we do not know the type | qs.type = 'P'; // if dbh is null, we do not know the type |
622 | qs.params.len = 0; | ||
623 | 624 | ||
624 | 625 | if (num_args == 2) { | if (num_args == 2) { |
625 | 626 | // link | // link |
... | ... | static void *my_pg_send_query(struct zend_execute_data *e, struct zval *retv) | |
679 | 680 | ||
680 | 681 | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); | s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval); |
681 | 682 | qs.type = 'P'; | qs.type = 'P'; |
682 | qs.params.len = 0; | ||
683 | 683 | ||
684 | 684 | // link | // link |
685 | 685 | z = (struct zval *) e + s; s++; | z = (struct zval *) e + s; s++; |
... | ... | static void *my_pg_get_result(struct zend_execute_data *e, struct zval *retv) | |
731 | 731 | para = (struct zval *) e + s; | para = (struct zval *) e + s; |
732 | 732 | qs.type = 'P'; | qs.type = 'P'; |
733 | 733 | qs.q = NULL; | qs.q = NULL; |
734 | qs.params.len = 0; | ||
735 | 734 | ||
736 | 735 | // link | // link |
737 | 736 | z = (struct zval *) e + s; s++; | z = (struct zval *) e + s; s++; |
File agent/text2process.c changed (mode: 100644) (index d6c5582..32efd68) | |||
1 | #include <string.h> | ||
1 | #include <errno.h> | ||
2 | #include <stdio.h> | ||
2 | 3 | #include <stdlib.h> | #include <stdlib.h> |
4 | #include <string.h> | ||
3 | 5 | ||
4 | 6 | #include "text2process.h" | #include "text2process.h" |
5 | 7 | ||
7 | 9 | #include "tools.h" | #include "tools.h" |
8 | 10 | #include "ctools.h" | #include "ctools.h" |
9 | 11 | #include "process_ssl.h" | #include "process_ssl.h" |
12 | #include "process_db.h" | ||
10 | 13 | ||
11 | 14 | extern char trace_enabled; | extern char trace_enabled; |
12 | 15 | ||
16 | /* | ||
17 | * Decodes a t2p token (Thhhh...): T=type, hhhh-len_in_hexa | ||
18 | */ | ||
19 | static const char *t2p_decode(char *x, const char *s, unsigned int *off, | ||
20 | const unsigned int len, unsigned int *xlen) | ||
21 | { | ||
22 | const char *ret; | ||
23 | |||
24 | if (*off + 1 + 4 > len) { | ||
25 | xlog(1, "%s: Len %u is too small (1) s+off=[%s]!\n", | ||
26 | __func__, len - *off, s + *off); | ||
27 | return NULL; | ||
28 | } | ||
29 | |||
30 | *x = s[*off]; *off = *off + 1; | ||
31 | |||
32 | char hhhh[5]; | ||
33 | memcpy(hhhh, s + *off, 4); *off = *off + 4; ret = s + *off; | ||
34 | hhhh[4] = '\0'; | ||
35 | *xlen = strtoul(hhhh, NULL, 16); | ||
36 | |||
37 | if (*off + *xlen > len) { | ||
38 | xlog(1, "%s: Len is too small! off=%u len=%u xlen=%u\n", | ||
39 | __func__, *off, len, *xlen); | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | *off = *off + *xlen; | ||
44 | |||
45 | return ret; | ||
46 | } | ||
47 | |||
13 | 48 | // Example: Js38 C=ES, O=ACCV, OU=PKIACCV, CN=ACCVRAIZ1i38 C=ES, O=ACCV, | // Example: Js38 C=ES, O=ACCV, OU=PKIACCV, CN=ACCVRAIZ1i38 C=ES, O=ACCV, |
14 | 49 | // OU=PKIACCV, CN=ACCVRAIZ1a3 RSAx16 5ec3b7a6437fa4e0S10 1304588257E10 1924940257 | // OU=PKIACCV, CN=ACCVRAIZ1a3 RSAx16 5ec3b7a6437fa4e0S10 1304588257E10 1924940257 |
15 | 50 | static void t2p_cert(const char *s, const unsigned int len) | static void t2p_cert(const char *s, const unsigned int len) |
... | ... | static void t2p_cert(const char *s, const unsigned int len) | |
35 | 70 | xlog(0, "%s: type '%c' has not enough data: %s\n", __func__, type, s + off); | xlog(0, "%s: type '%c' has not enough data: %s\n", __func__, type, s + off); |
36 | 71 | return; | return; |
37 | 72 | } | } |
38 | if (s[off] != ' ') { | ||
39 | xlog(0, "%s: type '%c': sublen=%u: ' ' not present at s=[%s]", | ||
40 | __func__, type, sublen, s + off); | ||
41 | return; | ||
42 | } | ||
43 | off++; | ||
44 | 73 | ||
45 | 74 | xlog(0, " type=%c sublen=%u s=%s\n", type, sublen, s + off); | xlog(0, " type=%c sublen=%u s=%s\n", type, sublen, s + off); |
46 | 75 | switch (type) { | switch (type) { |
... | ... | static void t2p_cert(const char *s, const unsigned int len) | |
67 | 96 | ninedogs_process_ssl(NINEDOGS_SSL_CERT, &c); | ninedogs_process_ssl(NINEDOGS_SSL_CERT, &c); |
68 | 97 | } | } |
69 | 98 | ||
70 | void text2process(const char *s, unsigned int len) | ||
99 | // Examples: | ||
100 | // Pcsh00085674cd4dc003djdbc:postgresql://localhost:5432/ninedogs?ApplicationName=pg1 | ||
101 | // Pceh00085674cd4dR0008239963d8 | ||
102 | // TODO: we need to dealocate memory! | ||
103 | static void t2p_db(const char *s, const unsigned int len) | ||
71 | 104 | { | { |
72 | xlog(1, "%s: s=%s\n", __func__, s); | ||
105 | unsigned int off = 0, xlen, max, etype = 0, index = 0, svalue_len = 0; | ||
106 | char db_type, type, subtype, x; | ||
107 | unsigned long hash = 0, R = 0; | ||
108 | const char *q0 = NULL, *conn_str = NULL, *ex = NULL; | ||
109 | unsigned short q0_len = 0, conn_str_len = 0, ex_len = 0; | ||
110 | int value = 0; | ||
111 | char svalue[65536] = {}; | ||
112 | |||
113 | xlog(90, "%s: s=[%s] len=%u\n", __func__, s, len); | ||
114 | |||
115 | if (len < 4) | ||
116 | return; | ||
117 | |||
118 | db_type = s[off++]; | ||
119 | type = s[off++]; | ||
120 | subtype = s[off++]; | ||
121 | xlog(1, " db_type=%c type=%c subtype=%c\n", db_type, type, subtype); | ||
122 | |||
123 | while (off < len) { | ||
124 | const char *r = t2p_decode(&x, s, &off, len, &xlen); | ||
125 | if (!r) | ||
126 | return; | ||
127 | if (x == 'h') { | ||
128 | char shash[17]; | ||
129 | max = sizeof(shash) - 1; | ||
130 | if (max > xlen) | ||
131 | max = xlen; | ||
132 | memcpy(shash, r, max); shash[max] = '\0'; | ||
133 | hash = strtoul(shash, NULL, 16); | ||
134 | xlog(1, " hash=0x%lx\n", hash); | ||
135 | } else if (x == 'R') { | ||
136 | char sret[17]; | ||
137 | max = sizeof(sret) - 1; | ||
138 | if (max > xlen) | ||
139 | max = xlen; | ||
140 | memcpy(sret, r, max); sret[max] = '\0'; | ||
141 | R = strtoul(sret, NULL, 16); | ||
142 | xlog(1, " R=0x%lx\n", R); | ||
143 | } else if (x == 'c') { | ||
144 | conn_str = r; | ||
145 | conn_str_len = xlen; | ||
146 | xlog(90, " conn_str=[%s] conn_str_len=%hu\n", conn_str, conn_str_len); | ||
147 | } else if (x == 'q') { | ||
148 | q0 = r; | ||
149 | q0_len = xlen; | ||
150 | xlog(90, " q=[%s] q_len=%hu\n", q0, q0_len); | ||
151 | } else if (x == 'e') { | ||
152 | ex = r; | ||
153 | ex_len = xlen; | ||
154 | xlog(90, " ex=[%s] ex_len=%hu\n", ex, ex_len); | ||
155 | } else if (x == 'i') { // index for setInt & co. | ||
156 | char tmp[32]; | ||
157 | max = sizeof(tmp) - 1; | ||
158 | if (max > xlen) | ||
159 | max = xlen; | ||
160 | memcpy(tmp, r, max); tmp[max] = '\0'; | ||
161 | index = strtoul(tmp, NULL, 10); | ||
162 | xlog(90, " index=%u\n", index); | ||
163 | } else if (x == 'v') { // value for setInt | ||
164 | char tmp[32]; | ||
165 | max = sizeof(tmp) - 1; | ||
166 | if (max > xlen) | ||
167 | max = xlen; | ||
168 | memcpy(tmp, r, max); tmp[max] = '\0'; | ||
169 | value = strtol(tmp, NULL, 10); | ||
170 | xlog(90, " value=%d\n", value); | ||
171 | } else if (x == 's') { // value for setString | ||
172 | svalue_len = sizeof(svalue) - 1; | ||
173 | if (svalue_len > xlen) | ||
174 | svalue_len = xlen; | ||
175 | memcpy(svalue, r, svalue_len); svalue[svalue_len] = '\0'; | ||
176 | xlog(90, " svalue_len=%u svalue=%s\n", svalue_len, svalue); | ||
177 | } else { | ||
178 | xlog(1, "%s: cannot decode type %c! Ignore it.\n", __func__, x); | ||
179 | } | ||
180 | } | ||
181 | |||
182 | if (type == 'c') { // connection open | ||
183 | struct nd_db_conn c; | ||
184 | c.type = db_type; | ||
185 | c.stable = 0; | ||
186 | c.conn_str = conn_str; | ||
187 | c.conn_str_len = conn_str_len; | ||
188 | c.ex = ex; c.ex_len = ex_len; | ||
189 | if (subtype == 's') { | ||
190 | etype = NINEDOGS_DB_CONN_START; | ||
191 | } else { | ||
192 | c.dbh = (void *) R; | ||
193 | etype = NINEDOGS_DB_CONN_END; | ||
194 | } | ||
195 | ninedogs_process_db("java/db/connect", etype, &c); | ||
196 | } else if (type == 'x') { // connection close | ||
197 | struct nd_db_conn c; | ||
198 | c.type = db_type; | ||
199 | c.stable = 0; | ||
200 | c.dbh = (void *) hash; | ||
201 | ninedogs_process_db("java/db/close", NINEDOGS_DB_CONN_CLOSE, &c); | ||
202 | } else if ((type == 'e') || (type == 'E') || (type == 'P')) { | ||
203 | // e/E: [] [ResultSet(e)/Boolean(E) rs1 = ps.executeQuery()] | ||
204 | // P: [P] [ResultSet rs1 = ps.executeQuery()] | ||
205 | struct nd_db_stmt stmt; | ||
206 | stmt.type = db_type; | ||
207 | stmt.stmt = (void *) hash; | ||
208 | stmt.flags |= type == 'E' ? ND_DB_STMT_RET_IS_BOOL : 0; | ||
209 | stmt.res = (void *) R; | ||
210 | stmt.ex = ex; stmt.ex_len = ex_len; | ||
211 | if (subtype == 's') | ||
212 | etype = NINEDOGS_DB_EXECUTE_START; | ||
213 | else | ||
214 | etype = NINEDOGS_DB_EXECUTE_END; | ||
215 | if (type == 'P') | ||
216 | ninedogs_process_db("java/db/stmt/execute", etype, &stmt); | ||
217 | else | ||
218 | ninedogs_process_db("java/db/prepared/execute", etype, &stmt); | ||
219 | } else if (type == 'p') { // [PreparedStatement stmt = con.prepareStatement("SELECT ? AS id")] | ||
220 | struct nd_db_stmt stmt; | ||
221 | stmt.type = db_type; | ||
222 | stmt.dbh = (void *) hash; | ||
223 | stmt.q = q0; | ||
224 | stmt.q_len = q0_len; | ||
225 | stmt.stmt = (void *) R; | ||
226 | stmt.ex = ex; stmt.ex_len = ex_len; | ||
227 | if (subtype == 's') | ||
228 | etype = NINEDOGS_DB_PREPARE_START; | ||
229 | else | ||
230 | etype = NINEDOGS_DB_PREPARE_END; | ||
231 | ninedogs_process_db("java/db/prepare", etype, &stmt); | ||
232 | } else if (type == 'f') { // [Statement stmt = con.createStatement()] | ||
233 | struct nd_db_stmt stmt; | ||
234 | stmt.type = db_type; | ||
235 | stmt.dbh = (void *) hash; | ||
236 | stmt.stmt = (void *) R; | ||
237 | stmt.ex = ex; stmt.ex_len = ex_len; | ||
238 | ninedogs_process_db("java/db/stmt/create", NINEDOGS_DB_STATEMENT_CREATE_END, &stmt); | ||
239 | } else if (type == 'w') { // [stmt.close()] | ||
240 | struct nd_db_stmt stmt; | ||
241 | stmt.type = db_type; | ||
242 | stmt.stmt = (void *) hash; | ||
243 | ninedogs_process_db("java/db/stmt/close", NINEDOGS_DB_STATEMENT_CLOSE_END, &stmt); | ||
244 | } else if (type == 'Q') { // [ResultSet rs2 = stmt.executeQuery("SELECT * FROM n1 LIMIT 2");] | ||
245 | struct nd_db_stmt stmt; | ||
246 | stmt.type = db_type; | ||
247 | stmt.stmt = (void *) hash; | ||
248 | stmt.q = q0; | ||
249 | stmt.q_len = q0_len; | ||
250 | stmt.res = (void *) R; | ||
251 | stmt.ex = ex; stmt.ex_len = ex_len; | ||
252 | if (subtype == 's') | ||
253 | etype = NINEDOGS_DB_PREPARE_START; | ||
254 | else | ||
255 | etype = NINEDOGS_DB_PREPARE_END; | ||
256 | ninedogs_process_db("java/db/stmt/execute/sql", etype, &stmt); | ||
257 | } else if (type == 'g') { // [ResultSet rs2 = p1.getResultSet()] | ||
258 | struct nd_db_stmt stmt; | ||
259 | stmt.type = db_type; | ||
260 | stmt.stmt = (void *) hash; | ||
261 | stmt.res = (void *) R; | ||
262 | stmt.ex = ex; stmt.ex_len = ex_len; | ||
263 | if (subtype == 's') | ||
264 | etype = NINEDOGS_DB_RESULT_GET_START; | ||
265 | else | ||
266 | etype = NINEDOGS_DB_RESULT_GET_END; | ||
267 | ninedogs_process_db("java/db/result/get", etype, &stmt); | ||
268 | } else if (type == 'b') { // [P] [ps.setInt(1, 12345)] | ||
269 | struct nd_db_stmt stmt; | ||
270 | stmt.type = db_type; | ||
271 | stmt.stmt = (void *) hash; | ||
272 | if (subtype == 'x') | ||
273 | stmt.res = NULL; | ||
274 | else | ||
275 | stmt.res = (void *) 1; // just to signal that is ok | ||
276 | stmt.ex = ex; stmt.ex_len = ex_len; | ||
277 | stmt.params.list[1].length = index; // abuse alert - used as index | ||
278 | stmt.params.list[0].l = value; | ||
279 | ninedogs_process_db("java/db/stmt/setInt", | ||
280 | NINEDOGS_DB_BIND_ONE_PARAM, &stmt); | ||
281 | } else if (type == 'S') { // [P] [ps.setString(2, "abc")] | ||
282 | struct nd_db_stmt stmt; | ||
283 | stmt.type = db_type; | ||
284 | stmt.stmt = (void *) hash; | ||
285 | if (subtype == 'x') | ||
286 | stmt.res = NULL; | ||
287 | else | ||
288 | stmt.res = (void *) 1; // just to signal that is ok | ||
289 | stmt.ex = ex; stmt.ex_len = ex_len; | ||
290 | stmt.params.list[1].length = index; // abuse alert - used as index | ||
291 | stmt.params.list[0].str = svalue; | ||
292 | stmt.params.list[0].length = svalue_len; | ||
293 | ninedogs_process_db("java/db/stmt/setString", | ||
294 | NINEDOGS_DB_BIND_ONE_PARAM, &stmt); | ||
295 | } else { | ||
296 | xlog(1, "%s: Unknown type [%c]!\n", __func__, type); | ||
297 | } | ||
298 | } | ||
299 | |||
300 | void text2process(const char *s, const unsigned int len) | ||
301 | { | ||
302 | xlog(100, "%s: s=%s\n", __func__, s); | ||
73 | 303 | ||
74 | 304 | if (s[len - 1] != '\0') { | if (s[len - 1] != '\0') { |
75 | 305 | xlog(0, " Seems we do not have the full string s[len - 1]=[0x%02hhx]!\n", | xlog(0, " Seems we do not have the full string s[len - 1]=[0x%02hhx]!\n", |
... | ... | void text2process(const char *s, unsigned int len) | |
83 | 313 | return; | return; |
84 | 314 | } | } |
85 | 315 | ||
316 | errno = 0; | ||
317 | |||
86 | 318 | switch (s[0]) { | switch (s[0]) { |
87 | case 'c': t2p_cert(s + 1, len - 1); break; | ||
88 | default: xlog(0, "Unknown text type [%c]!\n", s[0]); | ||
319 | case 'c': t2p_cert(s + 1, len - 2); break; | ||
320 | case 'D': t2p_db(s + 1, len - 2); break; | ||
321 | case 'L': xlog(0, "L: %s", s + 1); break; | ||
322 | default: xlog(1, "Unknown text type [%c] [%s]!\n", s[0], s); | ||
89 | 323 | } | } |
90 | 324 | } | } |
91 | 325 |
File agent/text2process.h changed (mode: 100644) (index 07f47d9..09f195d) | |||
1 | void text2process(const char *s, unsigned int len); | ||
1 | void text2process(const char *s, const unsigned int len); | ||
2 | 2 |
File agent/trace_encode.c added (mode: 100644) (index 0000000..e325706) | |||
1 | #include "trace_encode.h" | ||
2 | |||
3 | #include "../common/ids.h" | ||
4 | |||
5 | extern void xlog(const unsigned int level, const char *format, ...); | ||
6 | |||
7 | void my_trace_put8(unsigned char *buf, unsigned int *i, const uint8_t v) | ||
8 | { | ||
9 | buf[*i] = v; *i = *i + 1; | ||
10 | } | ||
11 | |||
12 | void my_trace_put16(unsigned char *buf, unsigned int *i, const uint16_t v) | ||
13 | { | ||
14 | uint16_t u = htobe16(v); | ||
15 | memcpy(buf + *i, &u, 2); *i = *i + 2; | ||
16 | } | ||
17 | |||
18 | void my_trace_put32(unsigned char *buf, unsigned int *i, const uint32_t v) | ||
19 | { | ||
20 | uint32_t u = htobe32(v); | ||
21 | memcpy(buf + *i, &u, 4); *i = *i + 4; | ||
22 | } | ||
23 | |||
24 | void my_trace_put64(unsigned char *buf, unsigned int *i, const uint64_t v) | ||
25 | { | ||
26 | uint64_t u = htobe64(v); | ||
27 | memcpy(buf + *i, &u, 8); *i = *i + 8; | ||
28 | } | ||
29 | |||
30 | void my_trace_put_double(unsigned char *buf, unsigned int *i, const double v) | ||
31 | { | ||
32 | uint64_t u; | ||
33 | memcpy(&u, &v, 8); | ||
34 | my_trace_put64(buf, i, u); | ||
35 | } | ||
36 | |||
37 | void my_trace_put_bool(unsigned char *buf, unsigned int *i, const char v) | ||
38 | { | ||
39 | buf[*i] = v; *i = *i + 1; | ||
40 | } | ||
41 | |||
42 | void my_trace_put(unsigned char *buf, unsigned int *i, | ||
43 | const void *in, const size_t in_len) | ||
44 | { | ||
45 | //xlog(1, "%s: i=%u in=%p in_len=%zu\n", | ||
46 | // __func__, i, in, in_len); | ||
47 | |||
48 | if (!in) { | ||
49 | xlog(1, "in is NULL!\n"); | ||
50 | return; | ||
51 | } | ||
52 | |||
53 | if (in_len == 0) | ||
54 | return; | ||
55 | |||
56 | memcpy(buf + *i, in, in_len); | ||
57 | *i = *i + in_len; | ||
58 | } | ||
59 | |||
60 | // Seems that all fields are stored in BE order | ||
61 | void my_trace_sockaddr(unsigned char *buf, unsigned int *i, | ||
62 | const struct sockaddr *a, const int len) | ||
63 | { | ||
64 | my_trace_put16(buf, i, len); | ||
65 | my_trace_put(buf, i, a, a ? len : 0); | ||
66 | } | ||
67 | |||
68 | void my_trace_put_stat(unsigned char *buf, unsigned int *i, struct stat *s) | ||
69 | { | ||
70 | my_trace_put64(buf, i, s->st_dev); | ||
71 | my_trace_put64(buf, i, s->st_ino); | ||
72 | my_trace_put32(buf, i, s->st_mode); | ||
73 | my_trace_put64(buf, i, s->st_nlink); | ||
74 | my_trace_put32(buf, i, s->st_uid); | ||
75 | my_trace_put32(buf, i, s->st_gid); | ||
76 | my_trace_put64(buf, i, s->st_rdev); | ||
77 | my_trace_put64(buf, i, s->st_size); | ||
78 | my_trace_put64(buf, i, s->st_blksize); | ||
79 | my_trace_put64(buf, i, s->st_blocks); | ||
80 | my_trace_put64(buf, i, s->st_atim.tv_sec); | ||
81 | my_trace_put32(buf, i, s->st_atim.tv_nsec); | ||
82 | my_trace_put64(buf, i, s->st_mtim.tv_sec); | ||
83 | my_trace_put32(buf, i, s->st_mtim.tv_nsec); | ||
84 | my_trace_put64(buf, i, s->st_ctim.tv_sec); | ||
85 | my_trace_put32(buf, i, s->st_ctim.tv_nsec); | ||
86 | } | ||
87 | |||
88 | void my_trace_put_string_array(unsigned char *buf, unsigned int *i, char *list[]) | ||
89 | { | ||
90 | unsigned int j = 0; | ||
91 | |||
92 | while (1) { | ||
93 | if (!list[j]) { | ||
94 | my_trace_put32(buf, i, 0); | ||
95 | break; | ||
96 | } | ||
97 | |||
98 | unsigned short len = strlen(list[j]); | ||
99 | my_trace_put16(buf, i, len); | ||
100 | my_trace_put(buf, i, list[j], len); | ||
101 | j++; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | void my_trace_put_hostent(unsigned char *buf, unsigned int *i, struct hostent *he) | ||
106 | { | ||
107 | if (!he) | ||
108 | return; | ||
109 | |||
110 | int len = strlen(he->h_name); | ||
111 | my_trace_put8(buf, i, len); | ||
112 | my_trace_put(buf, i, he->h_name, len); | ||
113 | |||
114 | for (int j = 0; ; j++) { | ||
115 | if (!he->h_aliases[j]) { | ||
116 | my_trace_put8(buf, i, 0); | ||
117 | break; | ||
118 | } | ||
119 | |||
120 | len = strlen(he->h_aliases[j]); | ||
121 | my_trace_put8(buf, i, len); | ||
122 | my_trace_put(buf, i, he->h_aliases[j], len); | ||
123 | } | ||
124 | |||
125 | my_trace_put8(buf, i, he->h_addrtype); | ||
126 | my_trace_put8(buf, i, he->h_length); | ||
127 | |||
128 | int count = 0; | ||
129 | for (int j = 0; ; j++) { | ||
130 | if (!he->h_addr_list[j]) | ||
131 | break; | ||
132 | count++; | ||
133 | } | ||
134 | |||
135 | my_trace_put8(buf, i, count); | ||
136 | for (int j = 0; j < count; j++) { | ||
137 | xlog(0, " DEBUG: addr[%d]=[%s]\n", j, he->h_addr_list[j]); | ||
138 | my_trace_put(buf, i, he->h_addr_list[j], he->h_length); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | void my_trace_put_params(unsigned char *buf, unsigned int *i, | ||
143 | const struct nd_params_array *pa, const unsigned char filter_bind_way) | ||
144 | { | ||
145 | xlog(1, "%s: filter_bind_way=%hhu\n", __func__, filter_bind_way); | ||
146 | |||
147 | for (unsigned short j = 0; j < ND_PARAMS_MAX; j++) { | ||
148 | const struct nd_params_array_one *o = &pa->list[j]; | ||
149 | if (o->type == ND_TYPE_FREE_SLOT) // TODO: ever happens? | ||
150 | continue; | ||
151 | |||
152 | xlog(1, "%s: j=%hu type=%hhu bind_way=%hhu bind_type=%hhu pointer=%hhu i=%d str=%p\n", | ||
153 | __func__, j, o->type, o->bind_way, o->bind_type, o->pointer, o->i, &o->str); | ||
154 | if ((filter_bind_way & o->bind_way) == 0) | ||
155 | continue; | ||
156 | |||
157 | my_trace_put8(buf, i, o->type); | ||
158 | my_trace_put8(buf, i, (o->bind_way << 2) | o->bind_type); | ||
159 | |||
160 | if (o->bind_type == ND_PARAMS_BIND_TYPE_NAME) { | ||
161 | unsigned char name_len = strlen(o->name); | ||
162 | my_trace_put8(buf, i, name_len); | ||
163 | my_trace_put(buf, i, o->name, name_len); | ||
164 | } else if (o->bind_type == ND_PARAMS_BIND_TYPE_POS) { | ||
165 | my_trace_put16(buf, i, o->pos); | ||
166 | } | ||
167 | |||
168 | if (o->type == ND_TYPE_INT) { | ||
169 | my_trace_put32(buf, i, o->pointer ? * (int *) o->str : o->i); | ||
170 | } else if (o->type == ND_TYPE_LONG) { | ||
171 | my_trace_put64(buf, i, o->pointer ? * (long *) o->str : o->l); | ||
172 | } else if (o->type == ND_TYPE_DOUBLE) { | ||
173 | my_trace_put_double(buf, i, o->pointer ? * (double *) o->str : o->d); | ||
174 | } else if (o->type == ND_TYPE_STRING) { | ||
175 | my_trace_put16(buf, i, o->length); | ||
176 | my_trace_put(buf, i, o->str, o->length); | ||
177 | } else if (o->type == ND_TYPE_UNK) { | ||
178 | my_trace_put16(buf, i, o->length); | ||
179 | my_trace_put(buf, i, o->str, o->length); | ||
180 | } | ||
181 | } | ||
182 | |||
183 | my_trace_put8(buf, i, ND_TYPE_LAST); | ||
184 | } |
File agent/trace_encode.h added (mode: 100644) (index 0000000..ebd2682) | |||
1 | #include <sys/stat.h> | ||
2 | |||
3 | #include <netdb.h> | ||
4 | #include <stdint.h> | ||
5 | #include <string.h> | ||
6 | |||
7 | #include "process_db.h" | ||
8 | |||
9 | void my_trace_put8(unsigned char *buf, unsigned int *i, const uint8_t v); | ||
10 | void my_trace_put16(unsigned char *buf, unsigned int *i, const uint16_t v); | ||
11 | void my_trace_put32(unsigned char *buf, unsigned int *i, const uint32_t v); | ||
12 | void my_trace_put64(unsigned char *buf, unsigned int *i, const uint64_t v); | ||
13 | void my_trace_put_double(unsigned char *buf, unsigned int *i, const double v); | ||
14 | void my_trace_put_bool(unsigned char *buf, unsigned int *i, const char v); | ||
15 | void my_trace_put(unsigned char *buf, unsigned int *i, | ||
16 | const void *in, const size_t in_len); | ||
17 | void my_trace_sockaddr(unsigned char *buf, unsigned int *i, | ||
18 | const struct sockaddr *a, const int len); | ||
19 | void my_trace_put_stat(unsigned char *buf, unsigned int *i, struct stat *s); | ||
20 | void my_trace_put_string_array(unsigned char *buf, unsigned int *i, char *list[]); | ||
21 | void my_trace_put_hostent(unsigned char *buf, unsigned int *i, struct hostent *he); | ||
22 | void my_trace_put_params(unsigned char *buf, unsigned int *i, | ||
23 | const struct nd_params_array *pa, const unsigned char filter_bind_way); | ||
24 |
File common/Makefile changed (mode: 100644) (index d7a4557..2f2a920) | |||
1 | # This is just to allow us to run make here | ||
2 | .PHONY: all | ||
3 | all: | ||
4 | make -C .. common | ||
1 | include ../Makefile.common | ||
5 | 2 | ||
6 | OBJS := tools.o sctools.o info.o decode_text.o | ||
3 | OBJS := tools.o sctools.o info.o decode_text.o bin2json.o \ | ||
4 | bin2struct.o | ||
5 | |||
6 | all: $(OBJS) | ||
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 | ||
14 | info.o: info.c info.h shared.h decode_text.h tools.h | ||
15 | 15 | $(CC) $(CFLAGS) -fPIC -c $< | $(CC) $(CFLAGS) -fPIC -c $< |
16 | 16 | ||
17 | 17 | decode_text.o: decode_text.c decode_text.h tools.h | decode_text.o: decode_text.c decode_text.h tools.h |
18 | 18 | $(CC) $(CFLAGS) -fPIC -c $< | $(CC) $(CFLAGS) -fPIC -c $< |
19 | 19 | ||
20 | bin2json.o: bin2json.c bin2json.h tools.h bin2struct.h | ||
21 | $(CC) $(CFLAGS) $(JSON_CFLAGS) -fPIC -c $< | ||
22 | |||
23 | bin2struct.o: bin2struct.c bin2struct.h ids.h tools.h | ||
24 | $(CC) $(CFLAGS) -fPIC -c $< | ||
25 | |||
20 | 26 | .PHONY: clean | .PHONY: clean |
21 | 27 | clean: | clean: |
22 | 28 | @rm -f *.o | @rm -f *.o |
File common/bin2json.c added (mode: 100644) (index 0000000..e3f805f) | |||
1 | #include <string.h> | ||
2 | |||
3 | #include "ids.h" | ||
4 | #include "tools.h" | ||
5 | #include "bin2struct.h" | ||
6 | #include "bin2json.h" | ||
7 | |||
8 | /* | ||
9 | * Returns how much bytes were used or -1 on error | ||
10 | */ | ||
11 | int nd_bin2json(struct json_object **pj, | ||
12 | const unsigned char *buf, const off_t buf_len) | ||
13 | { | ||
14 | int ret = -1; | ||
15 | struct json_object *j; | ||
16 | off_t off = 0; | ||
17 | do { | ||
18 | *pj = NULL; | ||
19 | |||
20 | //char dump[buf_len * 4 + 1]; | ||
21 | //bin2hex_ascii(dump, buf, buf_len); | ||
22 | //xlog(0, " %s: %s\n", __func__, dump); | ||
23 | |||
24 | if (buf_len < 4 + 1 + 4) { | ||
25 | xlog(0, " %s: Short len (1) %zu\n", __func__, buf_len); | ||
26 | return 0; | ||
27 | } | ||
28 | |||
29 | unsigned int plen, type; | ||
30 | memcpy(&plen, buf + off, 4); off += 4; | ||
31 | plen = be32toh(plen); | ||
32 | if (off + plen > buf_len) { | ||
33 | xlog(0, " %s: Short len (2) %zu\n", __func__, buf_len); | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | if (buf[off++] != 'T') { | ||
38 | xlog(0, " %s: 'T' not found!\n", __func__); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | memcpy(&type, buf + off, 4); off += 4; | ||
43 | type = be32toh(type); | ||
44 | xlog(0, " %s: plen=%u type=0x%x\n", __func__, plen, type); | ||
45 | |||
46 | j = json_object_new_object(); | ||
47 | if (!j) { | ||
48 | xlog(0, " %s: Cannot alloc memory for JSON!\n", __func__); | ||
49 | return -1; | ||
50 | } | ||
51 | |||
52 | int r = -1; | ||
53 | ret = 4 + plen; // sizeof(plen) + plen | ||
54 | switch (type) { | ||
55 | case NINEDOGS_NET_CORE_SYSINFO: { | ||
56 | struct nd_sysinfo s; | ||
57 | r = nd_bin2struct_core_sysinfo(&s, buf + off, plen - 1 - 4); // plen - 'T' - 'type' | ||
58 | if (r == -1) { | ||
59 | ret = -1; | ||
60 | break; | ||
61 | } | ||
62 | json_object_object_add(j, "ts", json_object_new_uint64(s.ts)); | ||
63 | json_object_object_add(j, "uptime", json_object_new_int(s.si.uptime)); | ||
64 | json_object_object_add(j, "load1", json_object_new_int(s.si.loads[0])); | ||
65 | json_object_object_add(j, "tram", json_object_new_uint64(s.si.totalram * s.si.mem_unit)); | ||
66 | json_object_object_add(j, "fram", json_object_new_uint64(s.si.freeram * s.si.mem_unit)); | ||
67 | json_object_object_add(j, "fswap", json_object_new_uint64(s.si.freeswap * s.si.mem_unit)); | ||
68 | json_object_object_add(j, "procs", json_object_new_uint64(s.si.procs)); | ||
69 | json_object_object_add(j, "totalhigh", json_object_new_uint64(s.si.totalhigh * s.si.mem_unit)); | ||
70 | json_object_object_add(j, "freehigh", json_object_new_uint64(s.si.freehigh * s.si.mem_unit)); | ||
71 | json_object_object_add(j, "sharedram", json_object_new_uint64(s.si.sharedram * s.si.mem_unit)); | ||
72 | json_object_object_add(j, "bufferram", json_object_new_uint64(s.si.bufferram * s.si.mem_unit)); | ||
73 | } break; | ||
74 | |||
75 | default: | ||
76 | xlog(0, "%s: unknown type 0x%x\n", __func__, type); | ||
77 | break; | ||
78 | } | ||
79 | if (r == -1) | ||
80 | break; | ||
81 | |||
82 | *pj = j; | ||
83 | xlog(0, " %s: returning %d and a good json\n", __func__, ret); | ||
84 | return ret; | ||
85 | } while (0); | ||
86 | json_object_put(j); | ||
87 | xlog(0, " %s: returning %d and NULL json\n", __func__, ret); | ||
88 | return ret; | ||
89 | } |
File common/bin2json.h added (mode: 100644) (index 0000000..d52eb68) | |||
1 | #include <json.h> | ||
2 | |||
3 | int nd_bin2json(struct json_object **pj, | ||
4 | const unsigned char *buf, const off_t buf_len); | ||
5 |
File common/bin2struct.c added (mode: 100644) (index 0000000..8c78631) | |||
1 | #include <endian.h> | ||
2 | #include <string.h> | ||
3 | |||
4 | #include "tools.h" | ||
5 | #include "bin2struct.h" | ||
6 | |||
7 | int nd_bin2struct_core_sysinfo(struct nd_sysinfo *s, | ||
8 | const unsigned char *buf, const unsigned int len) | ||
9 | { | ||
10 | unsigned int off = 0, ioff; | ||
11 | unsigned int r; | ||
12 | char c; | ||
13 | |||
14 | while (off + 1 + 1 <= len) { | ||
15 | ioff = off; | ||
16 | c = buf[off++]; | ||
17 | switch (c) { | ||
18 | case '_': r = unpack(&s->ts, 't', sizeof(s->ts), buf, len, &off); break; | ||
19 | case 'u': r = unpack(&s->si.uptime, '8', sizeof(s->si.uptime), buf, len, &off); break; | ||
20 | case '1': r = unpack(&s->si.loads[0], '8', sizeof(s->si.loads[0]), buf, len, &off); break; | ||
21 | case '5': r = unpack(&s->si.loads[1], '8', sizeof(s->si.loads[1]), buf, len, &off); break; | ||
22 | case 'q': r = unpack(&s->si.loads[2], '8', sizeof(s->si.loads[2]), buf, len, &off); break; | ||
23 | case 'r': r = unpack(&s->si.totalram, '8', sizeof(s->si.totalram), buf, len, &off); break; | ||
24 | case 'f': r = unpack(&s->si.freeram, '8', sizeof(s->si.freeram), buf, len, &off); break; | ||
25 | case 's': r = unpack(&s->si.sharedram, '8', sizeof(s->si.sharedram), buf, len, &off); break; | ||
26 | case 'b': r = unpack(&s->si.bufferram, '8', sizeof(s->si.bufferram), buf, len, &off); break; | ||
27 | case 'w': r = unpack(&s->si.totalswap, '8', sizeof(s->si.totalswap), buf, len, &off); break; | ||
28 | case 'W': r = unpack(&s->si.freeswap, '8', sizeof(s->si.freeswap), buf, len, &off); break; | ||
29 | case 'p': r = unpack(&s->si.procs, '2', sizeof(s->si.procs), buf, len, &off); break; | ||
30 | case 'h': r = unpack(&s->si.totalhigh, '8', sizeof(s->si.totalhigh), buf, len, &off); break; | ||
31 | case 'H': r = unpack(&s->si.freehigh, '8', sizeof(s->si.freehigh), buf, len, &off); break; | ||
32 | case 'i': r = unpack(&s->si.mem_unit, '4', sizeof(s->si.mem_unit), buf, len, &off); break; | ||
33 | default: r = 0xFFFFFFFE; break; | ||
34 | } | ||
35 | if (r >= 0xFFFFFFF0) { | ||
36 | xlog(1, "%s: Cannot decode core sysinfo r=0x%08x c=%c[0x%02hhx] off=%u/%u!\n", | ||
37 | __func__, r, c, c, ioff, len); | ||
38 | return -1; | ||
39 | } | ||
40 | } | ||
41 | |||
42 | xlog(10, "%s: ts=%llu uptime=%lu loads1=%lu loads5=%lu" | ||
43 | " loads15=%lu totalram=%lu freeram=%lu sharedram=%lu" | ||
44 | " bufferram=%lu totalswap=%lu freeswap=%lu procs=%u" | ||
45 | " totalhigh=%lu freehigh=%lu mem_unit=%u\n", | ||
46 | __func__, s->ts, s->si.uptime, s->si.loads[0], s->si.loads[1], | ||
47 | s->si.loads[2], s->si.totalram, s->si.freeram, s->si.sharedram, | ||
48 | s->si.bufferram, s->si.totalswap, s->si.freeswap, s->si.procs, | ||
49 | s->si.totalhigh, s->si.freehigh, s->si.mem_unit); | ||
50 | |||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | int nd_bin2struct_cert(struct ninedogs_cert *cert, const unsigned char *buf, | ||
55 | const unsigned int len) | ||
56 | { | ||
57 | char c; | ||
58 | unsigned int off = 0; | ||
59 | unsigned int r; | ||
60 | unsigned char serial[63]; | ||
61 | unsigned short serial_len = 0; | ||
62 | |||
63 | strcpy(cert->path, "?"); | ||
64 | strcpy(cert->subj, "?"); | ||
65 | strcpy(cert->issuer, "?"); | ||
66 | cert->not_before = 0; | ||
67 | cert->not_after = 0; | ||
68 | strcpy(cert->sig_alg, "?"); | ||
69 | strcpy(cert->pk_alg, "?"); | ||
70 | cert->pk_bits = 0; | ||
71 | strcpy(cert->serial, ""); | ||
72 | |||
73 | while (off + 1 + 1 <= len) { | ||
74 | c = buf[off++]; | ||
75 | switch (c) { | ||
76 | case '_': r = unpack(&cert->ts, 't', sizeof(cert->ts), buf, len, &off); break; | ||
77 | case 'p': r = unpack(cert->path, 's', sizeof(cert->path), buf, len, &off); break; | ||
78 | case 'u': r = unpack(cert->subj, 's', sizeof(cert->subj), buf, len, &off); break; | ||
79 | case 'i': r = unpack(cert->issuer, 's', sizeof(cert->issuer), buf, len, &off); break; | ||
80 | case 's': r = unpack(&cert->not_before, '8', sizeof(cert->not_before), buf, len, &off); break; | ||
81 | case 'e': r = unpack(&cert->not_after, '8', sizeof(cert->not_after), buf, len, &off); break; | ||
82 | case 'a': r = unpack(cert->sig_alg, 's', sizeof(cert->sig_alg), buf, len, &off); break; | ||
83 | case 'n': r = unpack(serial, 'b', sizeof(serial), buf, len, &off); serial_len = r; break; | ||
84 | case 't': r = unpack(&cert->type, 'c', sizeof(cert->type), buf, len, &off); break; | ||
85 | case 'k': r = unpack(cert->pk_alg, 's', sizeof(cert->pk_alg), buf, len, &off); break; | ||
86 | case 'K': r = unpack(&cert->pk_bits, '4', sizeof(cert->pk_bits), buf, len, &off); break; | ||
87 | default: r = 0xFFFFFFFE; break; | ||
88 | } | ||
89 | if (r >= 0xFFFFFFF0) { | ||
90 | char dump[len * 2 + 1]; | ||
91 | bin2hex(dump, buf, len); | ||
92 | xlog(1, "%s: Cannot decode ssl cert r=0x%08x c=%c[0x%02hhx] off=%u/%u [%s]!\n", | ||
93 | __func__, r, c, c, off, len, dump); | ||
94 | return -1; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | bin2hex(cert->serial, serial, serial_len); | ||
99 | |||
100 | xlog(100, "%s: ts=%llu path=[%s] subj=[%s] issuer=[%s] not_before=[%llu]" | ||
101 | " not_after=[%llu] serial=[%s] type=%c sig_alg=[%s]" | ||
102 | " pk_alg=[%s] pk_bits=%u\n", | ||
103 | __func__, cert->ts, cert->path, cert->subj, cert->issuer, | ||
104 | cert->not_before, cert->not_after, cert->serial, cert->type, | ||
105 | cert->sig_alg, cert->pk_alg, cert->pk_bits); | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | /* related to save_app */ | ||
111 | int nd_bin2struct_app(struct ninedogs_app *cu, | ||
112 | const unsigned char *buf, const unsigned int len) | ||
113 | { | ||
114 | unsigned int off = 0; | ||
115 | |||
116 | memset(cu, 0, sizeof(struct ninedogs_app)); | ||
117 | |||
118 | if (len < 8 + 2) { | ||
119 | xlog(1, "%s: too less data [%u]!\n", len); | ||
120 | return -1; | ||
121 | } | ||
122 | |||
123 | memcpy(&cu->ts, buf + off, 8); off += 8; | ||
124 | cu->ts = be64toh(cu->ts); | ||
125 | |||
126 | memcpy(&cu->cmdline_len, buf + off, 2); off += 2; | ||
127 | cu->cmdline_len = be16toh(cu->cmdline_len); | ||
128 | |||
129 | if (len - off < cu->cmdline_len) { | ||
130 | xlog(1, "%s: too less data [%u] (needed %u)!\n", | ||
131 | len - off, cu->cmdline_len); | ||
132 | return -1; | ||
133 | } | ||
134 | |||
135 | unsigned int max = sizeof(cu->cmdline) - 1; | ||
136 | if (max > cu->cmdline_len) | ||
137 | max = cu->cmdline_len; | ||
138 | memcpy(cu->cmdline, buf + off, max); | ||
139 | cu->cmdline[max] = '\0'; | ||
140 | |||
141 | char conv[4096]; | ||
142 | nd_app_nice(conv, sizeof(conv), cu->cmdline, cu->cmdline_len); | ||
143 | xlog(50, "%s: ts=%llu cmdline_len=%u cmdline=[%s]\n", | ||
144 | __func__, cu->ts, cu->cmdline_len, conv); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 |
File common/bin2struct.h added (mode: 100644) (index 0000000..5291efc) | |||
1 | #include <sys/sysinfo.h> | ||
2 | |||
3 | struct nd_sysinfo | ||
4 | { | ||
5 | unsigned long long ts; | ||
6 | struct sysinfo si; | ||
7 | }; | ||
8 | |||
9 | int nd_bin2struct_core_sysinfo(struct nd_sysinfo *s, | ||
10 | const unsigned char *buf, const unsigned int len); | ||
11 | |||
12 | |||
13 | struct ninedogs_cert | ||
14 | { | ||
15 | char path[256]; | ||
16 | unsigned long long not_before; | ||
17 | unsigned long long not_after; | ||
18 | char subj[512]; | ||
19 | char issuer[512]; | ||
20 | char serial[128]; | ||
21 | char sig_alg[32]; | ||
22 | char pk_alg[32]; | ||
23 | unsigned int pk_bits; | ||
24 | char type; | ||
25 | char pad[3]; | ||
26 | unsigned long long ts; | ||
27 | }; | ||
28 | |||
29 | int nd_bin2struct_cert(struct ninedogs_cert *c, const unsigned char *buf, | ||
30 | const unsigned int len); | ||
31 | |||
32 | struct ninedogs_app | ||
33 | { | ||
34 | unsigned long long ts; | ||
35 | unsigned short cmdline_len; | ||
36 | unsigned short pad[3]; | ||
37 | char cmdline[4096]; | ||
38 | }; | ||
39 | |||
40 | int nd_bin2struct_app(struct ninedogs_app *cu, | ||
41 | const unsigned char *buf, const unsigned int len); | ||
42 |
File common/decode_text.c changed (mode: 100644) (index f456c1e..7b9732a) | |||
... | ... | void nd_decode_curl_code(char *out, const size_t out_size, const int code) | |
143 | 143 | switch (code) { | switch (code) { |
144 | 144 | case 0: snprintf(out, out_size, "ok"); return; | case 0: snprintf(out, out_size, "ok"); return; |
145 | 145 | case 43: snprintf(out, out_size, "bad_func_arg"); return; | case 43: snprintf(out, out_size, "bad_func_arg"); return; |
146 | case 60: snprintf(out, out_size, "peer_failed_verification"); return; | ||
146 | 147 | } | } |
147 | 148 | ||
148 | 149 | snprintf(out, out_size, "?%d?", code); | snprintf(out, out_size, "?%d?", code); |
149 | 150 | } | } |
151 | |||
152 | |||
153 | void nd_decode_oci_handle_alloc_type(char *out, const size_t out_size, | ||
154 | const unsigned int v) | ||
155 | { | ||
156 | switch (v) { | ||
157 | case 1: snprintf(out, out_size, "env"); return; | ||
158 | case 2: snprintf(out, out_size, "error"); return; | ||
159 | case 3: snprintf(out, out_size, "svcctx"); return; | ||
160 | case 4: snprintf(out, out_size, "stmt"); return; | ||
161 | case 5: snprintf(out, out_size, "bind"); return; | ||
162 | case 6: snprintf(out, out_size, "define"); return; | ||
163 | case 7: snprintf(out, out_size, "describe"); return; | ||
164 | case 8: snprintf(out, out_size, "server"); return; | ||
165 | case 9: snprintf(out, out_size, "session"); return; | ||
166 | case 10: snprintf(out, out_size, "trans"); return; | ||
167 | case 11: snprintf(out, out_size, "complexobj"); return; | ||
168 | case 12: snprintf(out, out_size, "security"); return; | ||
169 | case 13: snprintf(out, out_size, "subsription"); return; | ||
170 | case 14: snprintf(out, out_size, "dirpath_ctx"); return; | ||
171 | case 15: snprintf(out, out_size, "dirpath_column_array"); return; | ||
172 | case 16: snprintf(out, out_size, "dirpath_stream"); return; | ||
173 | case 17: snprintf(out, out_size, "proc"); return; | ||
174 | case 18: snprintf(out, out_size, "dirpath_fn_ctx"); return; | ||
175 | case 19: snprintf(out, out_size, "dirpath_fn_col_array"); return; | ||
176 | case 20: snprintf(out, out_size, "xadsession"); return; | ||
177 | case 21: snprintf(out, out_size, "xadtable"); return; | ||
178 | case 22: snprintf(out, out_size, "xadfield"); return; | ||
179 | case 23: snprintf(out, out_size, "xadgranule"); return; | ||
180 | case 24: snprintf(out, out_size, "xadrecord"); return; | ||
181 | case 25: snprintf(out, out_size, "xadio"); return; | ||
182 | case 26: snprintf(out, out_size, "cpool"); return; | ||
183 | case 27: snprintf(out, out_size, "spool"); return; | ||
184 | case 28: snprintf(out, out_size, "admin"); return; | ||
185 | case 29: snprintf(out, out_size, "event"); return; | ||
186 | case 30: snprintf(out, out_size, "soda_collection"); return; | ||
187 | case 31: snprintf(out, out_size, "soda_document"); return; | ||
188 | case 32: snprintf(out, out_size, "soda_coll_cursor"); return; | ||
189 | case 33: snprintf(out, out_size, "soda_oper_options"); return; | ||
190 | case 34: snprintf(out, out_size, "soda_output_options"); return; | ||
191 | case 35: snprintf(out, out_size, "soda_metadata"); return; | ||
192 | case 36: snprintf(out, out_size, "async"); return; | ||
193 | case 37: snprintf(out, out_size, "last"); return; | ||
194 | } | ||
195 | |||
196 | snprintf(out, out_size, "?%u?", v); | ||
197 | } | ||
198 | |||
199 | void nd_decode_oci_attr_type(char *out, const size_t out_size, const unsigned int code) | ||
200 | { | ||
201 | switch (code) { | ||
202 | case 1: snprintf(out, out_size, "fncode"); return; | ||
203 | case 2: snprintf(out, out_size, "object"); return; | ||
204 | case 3: snprintf(out, out_size, "nonblocking_mode"); return; | ||
205 | case 4: snprintf(out, out_size, "sqlcode"); return; | ||
206 | case 5: snprintf(out, out_size, "env"); return; | ||
207 | case 6: snprintf(out, out_size, "server"); return; | ||
208 | case 7: snprintf(out, out_size, "session"); return; | ||
209 | case 8: snprintf(out, out_size, "trans"); return; | ||
210 | case 9: snprintf(out, out_size, "row_count"); return; | ||
211 | case 10: snprintf(out, out_size, "sqlfncode"); return; | ||
212 | case 11: snprintf(out, out_size, "prefetch_rows"); return; | ||
213 | case 12: snprintf(out, out_size, "nested_prefetch_rows"); return; | ||
214 | case 13: snprintf(out, out_size, "prefetch_memory"); return; | ||
215 | case 14: snprintf(out, out_size, "nested_prefetch_memory"); return; | ||
216 | case 15: snprintf(out, out_size, "char_count"); return; | ||
217 | case 16: snprintf(out, out_size, "fsprecision"); return; | ||
218 | case 17: snprintf(out, out_size, "lfprecision"); return; | ||
219 | case 18: snprintf(out, out_size, "param_count"); return; | ||
220 | case 19: snprintf(out, out_size, "rowid"); return; | ||
221 | case 20: snprintf(out, out_size, "charset"); return; | ||
222 | case 21: snprintf(out, out_size, "nchar"); return; | ||
223 | case 22: snprintf(out, out_size, "username"); return; | ||
224 | case 23: snprintf(out, out_size, "password"); return; | ||
225 | case 24: snprintf(out, out_size, "stmt_type"); return; | ||
226 | case 25: snprintf(out, out_size, "internal_name"); return; | ||
227 | case 26: snprintf(out, out_size, "external_name"); return; | ||
228 | case 27: snprintf(out, out_size, "xid"); return; | ||
229 | case 28: snprintf(out, out_size, "trans_lock"); return; | ||
230 | case 29: snprintf(out, out_size, "trans_name"); return; | ||
231 | case 30: snprintf(out, out_size, "heapalloc"); return; | ||
232 | case 31: snprintf(out, out_size, "charset_id"); return; | ||
233 | case 32: snprintf(out, out_size, "charset_form"); return; | ||
234 | case 33: snprintf(out, out_size, "maxdata_size"); return; | ||
235 | case 34: snprintf(out, out_size, "cache_opt_size"); return; | ||
236 | case 35: snprintf(out, out_size, "cache_max_size"); return; | ||
237 | case 36: snprintf(out, out_size, "pinoption"); return; | ||
238 | case 37: snprintf(out, out_size, "alloc_duration"); return; | ||
239 | case 38: snprintf(out, out_size, "pin_duration"); return; | ||
240 | case 39: snprintf(out, out_size, "fdo"); return; | ||
241 | case 40: snprintf(out, out_size, "postprocessing_callback"); return; | ||
242 | case 41: snprintf(out, out_size, "postprocessing_context"); return; | ||
243 | case 42: snprintf(out, out_size, "rows_returned"); return; | ||
244 | case 43: snprintf(out, out_size, "focbk"); return; | ||
245 | case 44: snprintf(out, out_size, "in_v8_mode"); return; | ||
246 | case 45: snprintf(out, out_size, "lobempty"); return; | ||
247 | case 46: snprintf(out, out_size, "sesslang"); return; | ||
248 | case 47: snprintf(out, out_size, "visibility"); return; | ||
249 | case 48: snprintf(out, out_size, "relative_msgid"); return; | ||
250 | case 49: snprintf(out, out_size, "sequence_deviation"); return; | ||
251 | case 50: snprintf(out, out_size, "consumer_name"); return; | ||
252 | } | ||
253 | |||
254 | snprintf(out, out_size, "?%u?", code); | ||
255 | } | ||
256 | |||
257 | void nd_decode_oci_lang(char *out, const size_t out_size, const unsigned int code) | ||
258 | { | ||
259 | switch (code) { | ||
260 | case 1: snprintf(out, out_size, "OCI_NTV_SYNTAX"); return; | ||
261 | case 2: snprintf(out, out_size, "OCI_V7_SYNTAX"); return; | ||
262 | case 3: snprintf(out, out_size, "OCI_V8_SYNTAX"); return; | ||
263 | case 0xffffffff: snprintf(out, out_size, "OCI_FOREIGN_SYNTAX"); return; | ||
264 | } | ||
265 | |||
266 | snprintf(out, out_size, "?%u?", code); | ||
267 | } | ||
268 | |||
269 | void nd_decode_oci_mode(char *out, const size_t out_size, const unsigned int mode) | ||
270 | { | ||
271 | if (mode == 0) { | ||
272 | snprintf(out, out_size, "default"); | ||
273 | return; | ||
274 | } | ||
275 | char *so = ""; if (mode & 0x0010) so = "|cache_searchonly"; | ||
276 | char *w = ""; if (mode & 0x0020) w = "|plsql_warnings"; | ||
277 | char *i = ""; if (mode & 0x0400) i = "|impl_results_client"; | ||
278 | char *id = ""; if (mode & 0x2000) id = "|get_sql_id"; | ||
279 | char *ph = ""; if (mode & 0x40000) ph = "|oci_placeholder"; | ||
280 | char *nb = ""; if (mode & 0x80000000) ph = "|non_blocking"; | ||
281 | |||
282 | snprintf(out, out_size, "0x%x%s%s%s%s%s%s", | ||
283 | mode, so, w, i, id, ph, nb); | ||
284 | } | ||
285 | |||
286 | void nd_decode_oci_bind_mode(char *out, const size_t out_size, const unsigned int mode) | ||
287 | { | ||
288 | if (mode == 0) { | ||
289 | snprintf(out, out_size, "default"); | ||
290 | return; | ||
291 | } | ||
292 | char *dae = ""; if (mode & 0x00000002) dae = "|data_at_exec"; | ||
293 | char *df = ""; if (mode & 0x00000002) df = "|dynamic_fetch"; | ||
294 | char *pw = ""; if (mode & 0x00000004) pw = "|piece_wise"; | ||
295 | char *bs = ""; if (mode & 0x00000040) bs = "|bind_soft"; | ||
296 | char *ds = ""; if (mode & 0x00000080) ds = "|define_soft"; | ||
297 | char *iov = ""; if (mode & 0x00000200) iov = "|iov"; | ||
298 | |||
299 | snprintf(out, out_size, "0x%x%s%s%s%s%s%s", | ||
300 | mode, dae, df, pw, bs, ds, iov); | ||
301 | } | ||
302 | |||
303 | void nd_decode_oci_ret(char *out, const size_t out_size, const int ret) | ||
304 | { | ||
305 | switch (ret) { | ||
306 | case -3123: snprintf(out, out_size, "STILL_EXECUTE"); return; | ||
307 | case -2: snprintf(out, out_size, "INVALID_HANDLE"); return; | ||
308 | case -1: snprintf(out, out_size, "ERROR"); return; | ||
309 | case 0: snprintf(out, out_size, "SUCCESS"); return; | ||
310 | case 1: snprintf(out, out_size, "SUCCESS_WITH_INFO"); return; | ||
311 | case 99: snprintf(out, out_size, "NEED_DATA"); return; | ||
312 | case 100: snprintf(out, out_size, "NO_DATA"); return; | ||
313 | } | ||
314 | |||
315 | snprintf(out, out_size, "?%d?", ret); | ||
316 | } | ||
317 | |||
318 | void nd_decode_oci_dty(char *out, const size_t out_size, const unsigned short code) | ||
319 | { | ||
320 | switch (code) { | ||
321 | case 1: snprintf(out, out_size, "SQLT_CHR"); return; | ||
322 | case 2: snprintf(out, out_size, "SQLT_NUM"); return; | ||
323 | case 3: snprintf(out, out_size, "SQLT_INT"); return; | ||
324 | case 4: snprintf(out, out_size, "SQLT_FLT"); return; | ||
325 | case 5: snprintf(out, out_size, "SQLT_STR"); return; | ||
326 | case 6: snprintf(out, out_size, "SQLT_VNU"); return; | ||
327 | case 7: snprintf(out, out_size, "SQLT_PDN"); return; | ||
328 | case 8: snprintf(out, out_size, "SQLT_LNG"); return; | ||
329 | case 9: snprintf(out, out_size, "SQLT_VCS"); return; | ||
330 | case 10: snprintf(out, out_size, "SQLT_NON"); return; | ||
331 | case 11: snprintf(out, out_size, "SQLT_RID"); return; | ||
332 | case 12: snprintf(out, out_size, "SQLT_DAT"); return; | ||
333 | case 15: snprintf(out, out_size, "SQLT_VBI"); return; | ||
334 | case 21: snprintf(out, out_size, "SQLT_BFLOAT"); return; | ||
335 | case 22: snprintf(out, out_size, "SQLT_BDOUBLE"); return; | ||
336 | case 23: snprintf(out, out_size, "SQLT_BIN"); return; | ||
337 | case 24: snprintf(out, out_size, "SQLT_LBI"); return; | ||
338 | case 68: snprintf(out, out_size, "SQLT_UIN"); return; | ||
339 | case 91: snprintf(out, out_size, "SQLT_SLS"); return; | ||
340 | case 94: snprintf(out, out_size, "SQLT_LVC"); return; | ||
341 | case 95: snprintf(out, out_size, "SQLT_LVB"); return; | ||
342 | case 96: snprintf(out, out_size, "SQLT_AFC"); return; | ||
343 | case 97: snprintf(out, out_size, "SQLT_AVC"); return; | ||
344 | case 100: snprintf(out, out_size, "SQLT_IBFLOAT"); return; | ||
345 | case 101: snprintf(out, out_size, "SQLT_IBDOUBLE"); return; | ||
346 | case 102: snprintf(out, out_size, "SQLT_CUR"); return; | ||
347 | case 104: snprintf(out, out_size, "SQLT_RDD"); return; | ||
348 | case 105: snprintf(out, out_size, "SQLT_LAB"); return; | ||
349 | case 106: snprintf(out, out_size, "SQLT_OSL"); return; | ||
350 | case 108: snprintf(out, out_size, "SQLT_NTY"); return; | ||
351 | case 110: snprintf(out, out_size, "SQLT_REF"); return; | ||
352 | case 112: snprintf(out, out_size, "SQLT_CLOB"); return; | ||
353 | case 113: snprintf(out, out_size, "SQLT_BLOB"); return; | ||
354 | case 114: snprintf(out, out_size, "SQLT_BFILEE"); return; | ||
355 | case 115: snprintf(out, out_size, "SQLT_CFILEE"); return; | ||
356 | case 116: snprintf(out, out_size, "SQLT_RSET"); return; | ||
357 | case 119: snprintf(out, out_size, "SQLT_JSON"); return; | ||
358 | case 122: snprintf(out, out_size, "SQLT_NCO"); return; | ||
359 | case 155: snprintf(out, out_size, "SQLT_VST"); return; | ||
360 | case 156: snprintf(out, out_size, "SQLT_ODT"); return; | ||
361 | case 184: snprintf(out, out_size, "SQLT_DATE"); return; | ||
362 | case 185: snprintf(out, out_size, "SQLT_TIME"); return; | ||
363 | case 186: snprintf(out, out_size, "SQLT_TIME_TZ"); return; | ||
364 | case 187: snprintf(out, out_size, "SQLT_TIMESTAMP"); return; | ||
365 | case 188: snprintf(out, out_size, "SQLT_TIMESTAMP_TZ"); return; | ||
366 | case 189: snprintf(out, out_size, "SQLT_INTERVAL_YM"); return; | ||
367 | case 190: snprintf(out, out_size, "SQLT_INTERVAL_DS"); return; | ||
368 | case 232: snprintf(out, out_size, "SQLT_TIMESTAMP_LTZ"); return; | ||
369 | case 241: snprintf(out, out_size, "SQLT_PNTY"); return; | ||
370 | case 250: snprintf(out, out_size, "SQLT_REC"); return; | ||
371 | case 251: snprintf(out, out_size, "SQLT_TAB"); return; | ||
372 | case 252: snprintf(out, out_size, "SQLT_BOL"); return; | ||
373 | } | ||
374 | |||
375 | snprintf(out, out_size, "?%hu?", code); | ||
376 | } | ||
377 | |||
378 | void nd_decode_oci_trans_commit_flags(char *out, const size_t out_size, const unsigned int v) | ||
379 | { | ||
380 | if (v == 0) { | ||
381 | snprintf(out, out_size, "default"); | ||
382 | return; | ||
383 | } | ||
384 | char *tp = ""; if (v & 0x01000000) tp = "|two_phase"; | ||
385 | char *wb = ""; if (v & 0x00000001) wb = "|write_batch"; | ||
386 | char *wi = ""; if (v & 0x00000002) wi = "|write_immed"; | ||
387 | char *ww = ""; if (v & 0x00000004) ww = "|write_wait"; | ||
388 | char *wnw = ""; if (v & 0x00000008) wnw = "|write_no_wait"; | ||
389 | |||
390 | snprintf(out, out_size, "0x%x%s%s%s%s%s", | ||
391 | v, tp, wb, wi, ww, wnw); | ||
392 | } | ||
393 | |||
394 | void nd_decode_oci_trans_rollback_flags(char *out, const size_t out_size, const unsigned int v) | ||
395 | { | ||
396 | if (v == 0) { | ||
397 | snprintf(out, out_size, "default"); | ||
398 | return; | ||
399 | } | ||
400 | |||
401 | snprintf(out, out_size, "0x%x", v); | ||
402 | } | ||
403 | |||
404 | void nd_decode_oci_trans_start_flags(char *out, const size_t out_size, const unsigned int v) | ||
405 | { | ||
406 | if (v == 0) { | ||
407 | snprintf(out, out_size, "default"); | ||
408 | return; | ||
409 | } | ||
410 | char *tn = ""; if (v & 0x00000001) tn = "|new"; | ||
411 | char *jo = ""; if (v & 0x00000002) jo = "|join"; | ||
412 | char *re = ""; if (v & 0x00000004) re = "|resume"; | ||
413 | char *pr = ""; if (v & 0x00000008) pr = "|promote"; | ||
414 | char *ro = ""; if (v & 0x00000100) ro = "|read_only"; | ||
415 | char *rw = ""; if (v & 0x00000200) rw = "|read_write"; | ||
416 | char *ser = ""; if (v & 0x00000400) ser = "|serializable"; | ||
417 | char *lo = ""; if (v & 0x000010000) lo = "|loose"; | ||
418 | char *ti = ""; if (v & 0x000020000) ti = "|tight"; | ||
419 | char *nm = ""; if (v & 0x000100000) nm = "|no_migrate"; | ||
420 | char *se = ""; if (v & 0x000200000) se = "|separable"; | ||
421 | char *or = ""; if (v & 0x000400000) or = "|ots_resume"; | ||
422 | |||
423 | snprintf(out, out_size, "0x%x%s%s%s%s%s%s%s%s%s%s%s%s", | ||
424 | v, tn, jo, re, pr, ro, rw, ser, lo, ti, nm, se, or); | ||
425 | } | ||
426 | |||
427 | void nd_decode_oci_execute_mode(char *out, const size_t out_size, const unsigned int v) | ||
428 | { | ||
429 | char *p1 = ""; if (v & 0x00000001) p1 = "|batch"; | ||
430 | char *p2 = ""; if (v & 0x00000002) p2 = "|exact_fetch"; | ||
431 | char *p3 = ""; if (v & 0x00000008) p3 = "|stmt_scrollable_readonly"; | ||
432 | char *p4 = ""; if (v & 0x00000010) p4 = "|describe_only"; | ||
433 | char *p5 = ""; if (v & 0x00000020) p5 = "|commit_on_success"; else p5 = "|no_auto_commit"; | ||
434 | char *p6 = ""; if (v & 0x00000080) p6 = "|batch_errors"; | ||
435 | char *p7 = ""; if (v & 0x00000100) p7 = "|parse_only"; | ||
436 | char *p8 = ""; if (v & 0x00000400) p8 = "|show_dml_warnings"; | ||
437 | char *p9 = ""; if (v & 0x00020000) p9 = "|result_cache"; | ||
438 | char *p10 = ""; if (v & 0x00040000) p10 = "|no_result_cache"; | ||
439 | char *p11 = ""; if (v & 0x00100000) p11 = "|return_row_count_array"; | ||
440 | |||
441 | snprintf(out, out_size, "0x%x%s%s%s%s%s%s%s%s%s%s%s", | ||
442 | v, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); | ||
443 | } | ||
444 |
File common/decode_text.h changed (mode: 100644) (index 92f6e8c..3b59d25) | |||
... | ... | void nd_decode_timerfd_flags(char *out, const size_t out_size, const int flags); | |
7 | 7 | void nd_decode_sockaddr(char *out, const void *s, const socklen_t sl); | void nd_decode_sockaddr(char *out, const void *s, const socklen_t sl); |
8 | 8 | void nd_decode_curl_code(char *out, const size_t out_size, const int code); | void nd_decode_curl_code(char *out, const size_t out_size, const int code); |
9 | 9 | ||
10 | void nd_decode_oci_handle_alloc_type(char *out, const size_t out_size, const unsigned int code); | ||
11 | void nd_decode_oci_attr_type(char *out, const size_t out_size, const unsigned int code); | ||
12 | void nd_decode_oci_lang(char *out, const size_t out_size, const unsigned int code); | ||
13 | void nd_decode_oci_mode(char *out, const size_t out_size, const unsigned int mode); | ||
14 | void nd_decode_oci_bind_mode(char *out, const size_t out_size, const unsigned int mode); | ||
15 | void nd_decode_oci_ret(char *out, const size_t out_size, const int ret); | ||
16 | void nd_decode_oci_dty(char *out, const size_t out_size, const unsigned short code); | ||
17 | void nd_decode_oci_trans_commit_flags(char *out, const size_t out_size, const unsigned int v); | ||
18 | void nd_decode_oci_trans_rollback_flags(char *out, const size_t out_size, const unsigned int v); | ||
19 | void nd_decode_oci_trans_start_flags(char *out, const size_t out_size, const unsigned int v); | ||
20 | void nd_decode_oci_execute_mode(char *out, const size_t out_size, const unsigned int v); | ||
21 |
File common/ids.h changed (mode: 100644) (index 8da5991..2151586) | |||
... | ... | enum | |
64 | 64 | NINEDOGS_DB_AUTOCOMMIT_END, | NINEDOGS_DB_AUTOCOMMIT_END, |
65 | 65 | NINEDOGS_DB_BIND_PARAM_START, | NINEDOGS_DB_BIND_PARAM_START, |
66 | 66 | NINEDOGS_DB_BIND_PARAM_END, | NINEDOGS_DB_BIND_PARAM_END, |
67 | NINEDOGS_DB_STATEMENT_CREATE_END, | ||
68 | NINEDOGS_DB_STATEMENT_CLOSE_END, | ||
69 | NINEDOGS_DB_RESULT_GET_START, | ||
70 | NINEDOGS_DB_RESULT_GET_END, | ||
71 | NINEDOGS_DB_BIND_ONE_PARAM, | ||
72 | NINEDOGS_DB_STMT_CLOSE_START, | ||
73 | NINEDOGS_DB_STMT_CLOSE_END, | ||
67 | 74 | NINEDOGS_DB_MAX // this must be last | NINEDOGS_DB_MAX // this must be last |
68 | 75 | }; | }; |
69 | 76 | ||
... | ... | enum | |
85 | 92 | NINEDOGS_URL_MAX // this must be last | NINEDOGS_URL_MAX // this must be last |
86 | 93 | }; | }; |
87 | 94 | ||
95 | // TODO: move this into params.h? | ||
88 | 96 | enum | enum |
89 | 97 | { | { |
98 | ND_TYPE_FREE_SLOT, | ||
90 | 99 | ND_TYPE_NULL, | ND_TYPE_NULL, |
91 | 100 | ND_TYPE_LONG, | ND_TYPE_LONG, |
92 | 101 | ND_TYPE_DOUBLE, | ND_TYPE_DOUBLE, |
... | ... | enum | |
96 | 105 | ND_TYPE_ARRAY_START, | ND_TYPE_ARRAY_START, |
97 | 106 | ND_TYPE_ARRAY_END, | ND_TYPE_ARRAY_END, |
98 | 107 | ND_TYPE_POINTER, | ND_TYPE_POINTER, |
99 | ND_TYPE_UNK | ||
108 | ND_TYPE_UNK, | ||
109 | ND_TYPE_INT, | ||
110 | ND_TYPE_LAST // marker that we sent everything | ||
100 | 111 | }; | }; |
101 | 112 | ||
113 | // bit masks for tracer (shared->client_flags) | ||
114 | #define ND_SHARED_ONLY_HIGH_LEVEL 1 | ||
115 |
File common/info.c changed (mode: 100644) (index 3ce6d03..9929355) | |||
3 | 3 | ||
4 | 4 | #include <stdio.h> // temp | #include <stdio.h> // temp |
5 | 5 | ||
6 | #include "tools.h" | ||
6 | 7 | #include "shared.h" | #include "shared.h" |
7 | 8 | #include "info.h" | #include "info.h" |
8 | 9 | #include "decode_text.h" | #include "decode_text.h" |
9 | 10 | ||
10 | extern void xlog(const unsigned int level, const char *format, ...); | ||
11 | 11 | ||
12 | 12 | /* | /* |
13 | 13 | * Export one fd node, returns the number of bytes | * Export one fd node, returns the number of bytes |
... | ... | static unsigned int export_fd_node(unsigned char *out, const struct fd_node *n) | |
42 | 42 | memcpy(out + off, &n->socket.bind, n->socket.bind_len); off += n->socket.bind_len; | memcpy(out + off, &n->socket.bind, n->socket.bind_len); off += n->socket.bind_len; |
43 | 43 | u16 = htobe16(n->socket.peer_len); memcpy(out + off, &u16, 2); off += 2; | u16 = htobe16(n->socket.peer_len); memcpy(out + off, &u16, 2); off += 2; |
44 | 44 | memcpy(out + off, &n->socket.peer, n->socket.peer_len); off += n->socket.peer_len; | memcpy(out + off, &n->socket.peer, n->socket.peer_len); off += n->socket.peer_len; |
45 | u32 = htobe32(n->socket.accept_fd); memcpy(out + off, &u32, 4); off += 4; | ||
45 | 46 | break; | break; |
46 | 47 | ||
47 | 48 | case FD_NODE_MEMFD: | case FD_NODE_MEMFD: |
... | ... | static unsigned int export_fd_node(unsigned char *out, const struct fd_node *n) | |
51 | 52 | memcpy(out + off, n->file.path, path_len); off += path_len; | memcpy(out + off, n->file.path, path_len); off += path_len; |
52 | 53 | u32 = htobe32(n->file.flags); memcpy(out + off, &u32, 4); off += 4; | u32 = htobe32(n->file.flags); memcpy(out + off, &u32, 4); off += 4; |
53 | 54 | u64 = htobe64(n->file.off); memcpy(out + off, &u64, 8); off += 8; | u64 = htobe64(n->file.off); memcpy(out + off, &u64, 8); off += 8; |
55 | u64 = htobe64(n->file.max); memcpy(out + off, &u64, 8); off += 8; | ||
54 | 56 | break; | break; |
55 | 57 | ||
56 | 58 | case FD_NODE_TIMERFD: | case FD_NODE_TIMERFD: |
... | ... | int decode_fd_node(struct fd_node *n, unsigned char *in, unsigned int *poff) | |
152 | 154 | memcpy(&n->socket.bind, in + off, n->socket.bind_len); off += n->socket.bind_len; | memcpy(&n->socket.bind, in + off, n->socket.bind_len); off += n->socket.bind_len; |
153 | 155 | memcpy(&u16, in + off, 2); off += 2; n->socket.peer_len = be16toh(u16); | memcpy(&u16, in + off, 2); off += 2; n->socket.peer_len = be16toh(u16); |
154 | 156 | memcpy(&n->socket.peer, in + off, n->socket.peer_len); off += n->socket.peer_len; | memcpy(&n->socket.peer, in + off, n->socket.peer_len); off += n->socket.peer_len; |
157 | memcpy(&u32, in + off, 4); off += 4; n->socket.accept_fd = be32toh(u32); | ||
155 | 158 | break; | break; |
156 | 159 | ||
157 | 160 | case FD_NODE_MEMFD: | case FD_NODE_MEMFD: |
... | ... | int decode_fd_node(struct fd_node *n, unsigned char *in, unsigned int *poff) | |
162 | 165 | memcpy(n->file.path, in + off, max); n->file.path[max] = '\0'; off += path_len; | memcpy(n->file.path, in + off, max); n->file.path[max] = '\0'; off += path_len; |
163 | 166 | memcpy(&u32, in + off, 4); off += 4; n->file.flags = be32toh(u32); | memcpy(&u32, in + off, 4); off += 4; n->file.flags = be32toh(u32); |
164 | 167 | memcpy(&u64, in + off, 8); off += 8; n->file.off = be64toh(u64); | memcpy(&u64, in + off, 8); off += 8; n->file.off = be64toh(u64); |
168 | memcpy(&u64, in + off, 8); off += 8; n->file.max = be64toh(u64); | ||
165 | 169 | break; | break; |
166 | 170 | ||
167 | 171 | case FD_NODE_TIMERFD: | case FD_NODE_TIMERFD: |
... | ... | void decode_fd_node_to_text(char *out, const size_t out_size, struct fd_node *n) | |
189 | 193 | char base[1024]; | char base[1024]; |
190 | 194 | ||
191 | 195 | switch (n->type) { | switch (n->type) { |
192 | case FD_NODE_FILE: | ||
196 | case FD_NODE_FILE: { | ||
193 | 197 | snprintf(base, sizeof(base), | snprintf(base, sizeof(base), |
194 | 198 | "file fd=%d path=[%s] flags=0x%x mode=0x%x off=%lu", | "file fd=%d path=[%s] flags=0x%x mode=0x%x off=%lu", |
195 | 199 | n->fd, n->file.path, n->file.flags, n->file.mode, n->file.off); | n->fd, n->file.path, n->file.flags, n->file.mode, n->file.off); |
196 | break; | ||
200 | } break; | ||
197 | 201 | ||
198 | case FD_NODE_SOCKET: | ||
202 | case FD_NODE_SOCKET: { | ||
199 | 203 | char bind[1024], peer[1024]; | char bind[1024], peer[1024]; |
200 | 204 | ||
201 | 205 | if (n->socket.bind_len > 0) | if (n->socket.bind_len > 0) |
... | ... | void decode_fd_node_to_text(char *out, const size_t out_size, struct fd_node *n) | |
212 | 216 | nd_decode_socket_type(type, sizeof(type), n->socket.type); | nd_decode_socket_type(type, sizeof(type), n->socket.type); |
213 | 217 | nd_decode_socket_protocol(protocol, sizeof(protocol), n->socket.protocol); | nd_decode_socket_protocol(protocol, sizeof(protocol), n->socket.protocol); |
214 | 218 | ||
219 | char accept_fd[32]; | ||
220 | if (n->socket.accept_fd == 0) | ||
221 | accept_fd[0] = '\0'; | ||
222 | else | ||
223 | snprintf(accept_fd, sizeof(accept_fd), | ||
224 | " accept_fd=%d", n->socket.accept_fd); | ||
225 | |||
215 | 226 | snprintf(base, sizeof(base), | 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; | ||
227 | "socket fd=%d %s/%s bind=[%s] peer=[%s] backlog=%d accepts=%lu" | ||
228 | "%s", | ||
229 | n->fd, type, protocol, bind, peer, n->socket.backlog, | ||
230 | n->socket.accepts, accept_fd); | ||
231 | } break; | ||
219 | 232 | ||
220 | case FD_NODE_MEMFD: | ||
233 | case FD_NODE_MEMFD: { | ||
221 | 234 | char mfd_flags[64]; | char mfd_flags[64]; |
222 | 235 | nd_decode_memfd_flags(mfd_flags, sizeof(mfd_flags), n->file.flags); | 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; | ||
236 | snprintf(base, sizeof(base), "memfd fd=%d path=[%s] flags=%s off=%lu size=%lu", | ||
237 | n->fd, n->file.path, mfd_flags, n->file.off, n->file.max); | ||
238 | } break; | ||
226 | 239 | ||
227 | case FD_NODE_TIMERFD: | ||
240 | case FD_NODE_TIMERFD: { | ||
228 | 241 | char clock[32], flags[64]; | char clock[32], flags[64]; |
229 | 242 | nd_decode_clockid(clock, sizeof(clock), n->file.mode); | nd_decode_clockid(clock, sizeof(clock), n->file.mode); |
230 | 243 | nd_decode_timerfd_flags(flags, sizeof(flags), n->file.flags); | nd_decode_timerfd_flags(flags, sizeof(flags), n->file.flags); |
231 | 244 | snprintf(base, sizeof(base), "timerfd fd=%d clock=%s flags=%s", | snprintf(base, sizeof(base), "timerfd fd=%d clock=%s flags=%s", |
232 | 245 | n->fd, clock, flags); | n->fd, clock, flags); |
233 | break; | ||
246 | } break; | ||
234 | 247 | ||
235 | 248 | default: | default: |
236 | 249 | snprintf(out, out_size, "fd=%d unknown type %hhu", n->fd, n->type); | snprintf(out, out_size, "fd=%d unknown type %hhu", n->fd, n->type); |
237 | 250 | return; | return; |
238 | 251 | } | } |
239 | 252 | ||
240 | snprintf(out, out_size, "%s ops=%lu/%lu bytes=%lu/%lu errs=%lu/%lu", base, | ||
253 | snprintf(out, out_size, "%s ops=%lu/%lu bytes=%lu/%lu errs=%lu/%lu [r/w]", base, | ||
241 | 254 | n->stats[0][0], n->stats[0][1], | n->stats[0][0], n->stats[0][1], |
242 | 255 | n->stats[1][0], n->stats[1][1], | n->stats[1][0], n->stats[1][1], |
243 | 256 | n->stats[2][0], n->stats[2][1]); | n->stats[2][0], n->stats[2][1]); |
File common/params.h added (mode: 100644) (index 0000000..be0720b) | |||
1 | #ifndef ND_PARAMS_H | ||
2 | #define ND_PARAMS_H 1 | ||
3 | |||
4 | #define ND_PARAMS_BIND_WAY_NONE 0 | ||
5 | #define ND_PARAMS_BIND_WAY_IN 1 | ||
6 | #define ND_PARAMS_BIND_WAY_OUT 2 | ||
7 | #define ND_PARAMS_BIND_WAY_BOTH 3 | ||
8 | |||
9 | #define ND_PARAMS_BIND_TYPE_NONE 0 | ||
10 | #define ND_PARAMS_BIND_TYPE_NAME 1 | ||
11 | #define ND_PARAMS_BIND_TYPE_POS 2 | ||
12 | |||
13 | struct nd_params_array_one | ||
14 | { | ||
15 | unsigned char type; // see ND_TYPE_* | ||
16 | |||
17 | unsigned char bind_way:2; // See ND_PARAMS_BIND_WAY_* | ||
18 | unsigned char bind_type:2; // See ND_PARAMS_BIND_TYPE_* | ||
19 | unsigned char pointer:1; // if 1, all values are stored at 'str' pointer | ||
20 | unsigned char pad1:3; | ||
21 | |||
22 | unsigned short length; // for 'str' | ||
23 | union { | ||
24 | char name[20]; | ||
25 | unsigned short pos; | ||
26 | }; | ||
27 | union { | ||
28 | char *str; | ||
29 | double d; | ||
30 | long l; | ||
31 | int i; | ||
32 | }; | ||
33 | }; | ||
34 | |||
35 | #define ND_PARAMS_MAX 100 | ||
36 | struct nd_params_array | ||
37 | { | ||
38 | struct nd_params_array_one list[ND_PARAMS_MAX]; | ||
39 | }; | ||
40 | |||
41 | #endif |
File common/sctools.c changed (mode: 100644) (index 4427cc9..57fe62c) | |||
1 | #include <libgen.h> | ||
2 | #include <stdio.h> | ||
1 | 3 | #include <string.h> | #include <string.h> |
2 | 4 | ||
3 | 5 | #include "sctools.h" | #include "sctools.h" |
4 | 6 | #include "tools.h" | #include "tools.h" |
5 | 7 | ||
6 | extern void xlog(const unsigned int level, const char *format, ...); | ||
8 | int nd_for_each_user(int (*cb)(const unsigned int uid, const char *user_dir)) | ||
9 | { | ||
10 | const char *path = "/var/lib/ninedogs/users/by-uid/*/*/*"; | ||
7 | 11 | ||
12 | glob_t g; | ||
13 | int r = glob(path, GLOB_NOSORT | GLOB_ONLYDIR, NULL, &g); | ||
14 | if (r == GLOB_NOMATCH) | ||
15 | return 0; | ||
16 | if (r != 0) { | ||
17 | fprintf(stderr, " cannot load users: %m!\n"); | ||
18 | return -1; | ||
19 | } | ||
8 | 20 | ||
9 | int decode_cert(struct ninedogs_cert *cert, const unsigned char *buf, | ||
10 | const unsigned int len) | ||
11 | { | ||
12 | char c; | ||
13 | unsigned int off = 0; | ||
14 | unsigned int r; | ||
15 | unsigned char serial[63]; | ||
16 | unsigned short serial_len = 0; | ||
17 | |||
18 | strcpy(cert->path, "?"); | ||
19 | strcpy(cert->subj, "?"); | ||
20 | strcpy(cert->issuer, "?"); | ||
21 | cert->not_before = 0; | ||
22 | cert->not_after = 0; | ||
23 | strcpy(cert->sig_alg, "?"); | ||
24 | strcpy(cert->pk_alg, "?"); | ||
25 | cert->pk_bits = 0; | ||
26 | strcpy(cert->serial, ""); | ||
27 | |||
28 | while (off + 1 + 1 <= len) { | ||
29 | c = buf[off++]; | ||
30 | switch (c) { | ||
31 | case 'N': r = unpack(&cert->ts, 't', sizeof(cert->ts), buf, len, &off); break; | ||
32 | case 'p': r = unpack(cert->path, 's', sizeof(cert->path), buf, len, &off); break; | ||
33 | case 'u': r = unpack(cert->subj, 's', sizeof(cert->subj), buf, len, &off); break; | ||
34 | case 'i': r = unpack(cert->issuer, 's', sizeof(cert->issuer), buf, len, &off); break; | ||
35 | case 's': r = unpack(&cert->not_before, '8', sizeof(cert->not_before), buf, len, &off); break; | ||
36 | case 'e': r = unpack(&cert->not_after, '8', sizeof(cert->not_after), buf, len, &off); break; | ||
37 | case 'a': r = unpack(cert->sig_alg, 's', sizeof(cert->sig_alg), buf, len, &off); break; | ||
38 | case 'n': r = unpack(serial, 'b', sizeof(serial), buf, len, &off); serial_len = r; break; | ||
39 | case 't': r = unpack(&cert->type, 'c', sizeof(cert->type), buf, len, &off); break; | ||
40 | case 'k': r = unpack(cert->pk_alg, 's', sizeof(cert->pk_alg), buf, len, &off); break; | ||
41 | case 'K': r = unpack(&cert->pk_bits, '4', sizeof(cert->pk_bits), buf, len, &off); break; | ||
42 | default: r = 0xFFFFFFFE; break; | ||
43 | } | ||
44 | if (r >= 0xFFFFFFF0) { | ||
45 | char dump[len * 2 + 1]; | ||
46 | bin2hex(dump, buf, len); | ||
47 | xlog(1, "%s: Cannot decode ssl cert r=0x%08x c=%c[0x%02hhx] off=%u/%u [%s]!\n", | ||
48 | __func__, r, c, c, off, len, dump); | ||
49 | return -1; | ||
21 | int ret = g.gl_pathc; | ||
22 | for (unsigned i = 0; i < g.gl_pathc; i++) { | ||
23 | unsigned int uid = strtoul(basename(g.gl_pathv[i]), NULL, 16); | ||
24 | r = cb(uid, g.gl_pathv[i]); | ||
25 | if (r == -1) { | ||
26 | ret = -1; | ||
27 | break; | ||
50 | 28 | } | } |
51 | 29 | } | } |
30 | globfree(&g); | ||
31 | |||
32 | return ret; | ||
33 | } | ||
34 | |||
35 | int nd_load_certs(glob_t *g, const unsigned int uid) | ||
36 | { | ||
37 | char path[1024]; | ||
52 | 38 | ||
53 | bin2hex(cert->serial, serial, serial_len); | ||
39 | snprintf(path, sizeof(path), | ||
40 | "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x/cert/*", | ||
41 | uid, uid >> 8, uid); | ||
54 | 42 | ||
55 | xlog(1, "%s: ts=%llu path=[%s] subj=[%s] issuer=[%s] not_before=[%llu]" | ||
56 | " not_after=[%llu] serial=[%s] type=%c sig_alg=[%s]" | ||
57 | " pk_alg=[%s] pk_bits=%u\n", | ||
58 | __func__, cert->ts, cert->path, cert->subj, cert->issuer, | ||
59 | cert->not_before, cert->not_after, cert->serial, cert->type, | ||
60 | cert->sig_alg, cert->pk_alg, cert->pk_bits); | ||
43 | int r = glob(path, GLOB_NOSORT | GLOB_ONLYDIR, NULL, g); | ||
44 | if (r == GLOB_NOMATCH) | ||
45 | return 0; | ||
46 | if (r != 0) | ||
47 | return r; | ||
61 | 48 | ||
62 | return 0; | ||
49 | return g->gl_pathc; | ||
63 | 50 | } | } |
51 | |||
52 | int nd_load_cert_users(glob_t *g, const char *cert_path) | ||
53 | { | ||
54 | char path[1024]; | ||
55 | |||
56 | snprintf(path, sizeof(path), "%s/users/*/*/*", cert_path); | ||
57 | int r = glob(path, 0 /*flags*/, NULL, g); | ||
58 | if (r == GLOB_NOMATCH) | ||
59 | return 0; | ||
60 | if (r != 0) | ||
61 | return r; | ||
62 | |||
63 | return g->gl_pathc; | ||
64 | } | ||
65 |
File common/sctools.h changed (mode: 100644) (index 7c63b50..7fb099f) | |||
1 | struct ninedogs_cert | ||
2 | { | ||
3 | char path[256]; | ||
4 | unsigned long long not_before; | ||
5 | unsigned long long not_after; | ||
6 | char subj[512]; | ||
7 | char issuer[512]; | ||
8 | char serial[128]; | ||
9 | char sig_alg[32]; | ||
10 | char pk_alg[32]; | ||
11 | unsigned int pk_bits; | ||
12 | char type; | ||
13 | char pad[3]; | ||
14 | unsigned long long ts; | ||
15 | }; | ||
1 | #include <glob.h> | ||
16 | 2 | ||
17 | int decode_cert(struct ninedogs_cert *c, const unsigned char *buf, | ||
18 | const unsigned int len); | ||
3 | int nd_for_each_user(int (*cb)(const unsigned int uid, const char *user_dir)); | ||
4 | |||
5 | int nd_load_certs(glob_t *g, const unsigned int uid); | ||
6 | |||
7 | int nd_load_cert_users(glob_t *g, const char *cert_path); | ||
19 | 8 |
File common/shared.h changed (mode: 100644) (index ab487bb..447b158) | |||
10 | 10 | ||
11 | 11 | struct shared | struct shared |
12 | 12 | { | { |
13 | sem_t sem1; | ||
14 | unsigned int head, tail; // these can be changed only under semaphore | ||
15 | unsigned int new_tail; | ||
16 | unsigned int buf_size; // client may be compiled with another version and need to know this | ||
17 | unsigned int msgs_lost; | ||
18 | unsigned char version; | ||
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]; | ||
13 | sem_t sem1; | ||
14 | volatile unsigned int head, tail; // these can be changed only under semaphore | ||
15 | volatile unsigned int junk; | ||
16 | unsigned int buf_size; // client may be compiled with another version and need to know this | ||
17 | unsigned int client_flags; // set by a tracer | ||
18 | unsigned char version; | ||
19 | unsigned char done; // set by the target program when it exits; on fork we should make this a counter (TODO) | ||
20 | unsigned char inited; | ||
21 | unsigned char clients; | ||
22 | unsigned char buf[2000000]; | ||
22 | 23 | }; | }; |
23 | 24 | ||
24 | 25 | ||
... | ... | struct fd_node | |
51 | 52 | int flags; | int flags; |
52 | 53 | mode_t mode; // used also as timerfd::clockid | mode_t mode; // used also as timerfd::clockid |
53 | 54 | off_t off; | off_t off; |
55 | off_t max; // was is set by ftruncate | ||
54 | 56 | } file; | } file; |
55 | 57 | struct { | struct { |
56 | 58 | int domain, type, protocol, backlog; | int domain, type, protocol, backlog; |
57 | 59 | struct sockaddr_storage bind, peer; | struct sockaddr_storage bind, peer; |
58 | 60 | socklen_t bind_len, peer_len; | socklen_t bind_len, peer_len; |
59 | 61 | uint64_t accepts; | uint64_t accepts; |
62 | int accept_fd; // if this is a result of the accept, it will contain the fd doing accept | ||
63 | int pad; | ||
60 | 64 | } socket; | } socket; |
61 | 65 | }; | }; |
62 | 66 | uint64_t stats[3][2]; // 0=ops/1=bytes/2=errors | 0=read/1=write | uint64_t stats[3][2]; // 0=ops/1=bytes/2=errors | 0=read/1=write |
File common/tools.c changed (mode: 100644) (index adb2c61..567f64e) | |||
1 | 1 | #define _GNU_SOURCE 500 | #define _GNU_SOURCE 500 |
2 | 2 | ||
3 | #include <stdio.h> | ||
4 | 3 | #include <ctype.h> | #include <ctype.h> |
4 | #include <curl/curl.h> | ||
5 | #include <endian.h> | ||
6 | #include <libgen.h> | ||
7 | #include <stdio.h> | ||
5 | 8 | #include <unistd.h> | #include <unistd.h> |
6 | 9 | #include <stdio.h> | #include <stdio.h> |
7 | 10 | #include <stdlib.h> | #include <stdlib.h> |
8 | 11 | #include <stdarg.h> | #include <stdarg.h> |
9 | 12 | #include <string.h> | #include <string.h> |
10 | #include <sys/socket.h> | ||
11 | 13 | #include <sys/random.h> | #include <sys/random.h> |
14 | #include <sys/socket.h> | ||
12 | 15 | #include <sys/time.h> | #include <sys/time.h> |
13 | 16 | #include <sys/types.h> | #include <sys/types.h> |
14 | 17 | #include <arpa/inet.h> | #include <arpa/inet.h> |
28 | 31 | #include "tools.h" | #include "tools.h" |
29 | 32 | ||
30 | 33 | ||
31 | extern void xlog(const unsigned int level, const char *format, ...); | ||
32 | |||
33 | |||
34 | 34 | void ninedogs_now(struct timeval *tv) | void ninedogs_now(struct timeval *tv) |
35 | 35 | { | { |
36 | 36 | gettimeofday(tv, NULL); | gettimeofday(tv, NULL); |
... | ... | static unsigned char hex2bin_one(const char d) | |
81 | 81 | if ((d >= 'A') && (d <= 'F')) | if ((d >= 'A') && (d <= 'F')) |
82 | 82 | return d - 'A' + 10; | return d - 'A' + 10; |
83 | 83 | ||
84 | xlog(0, " invalid hex char: %c[%02hhx]\n", d, d); | ||
84 | xlog(1, " invalid hex char: %c[%02hhx]\n", d, d); | ||
85 | 85 | return 0xFF; // signal error | return 0xFF; // signal error |
86 | 86 | } | } |
87 | 87 | ||
... | ... | void pack(unsigned char **pbuf, unsigned int *len, const char *fmt, ...) | |
175 | 175 | case 't': needed += 8; va_arg(va, struct timeval *); break; // timeval | case 't': needed += 8; va_arg(va, struct timeval *); break; // timeval |
176 | 176 | case 'N': needed += 8; break; // "now" | case 'N': needed += 8; break; // "now" |
177 | 177 | default: | default: |
178 | xlog(0, "invalid format [%c]!\n", *f); | ||
178 | xlog(1, "invalid format [%c]!\n", *f); | ||
179 | 179 | abort(); | abort(); |
180 | 180 | } | } |
181 | 181 | ||
... | ... | void pack(unsigned char **pbuf, unsigned int *len, const char *fmt, ...) | |
186 | 186 | ||
187 | 187 | q = p = malloc(needed); | q = p = malloc(needed); |
188 | 188 | if (!p) { | if (!p) { |
189 | xlog(0, "cannot alloc mem [%u]!\n", needed); | ||
189 | xlog(1, "cannot alloc mem [%u]!\n", needed); | ||
190 | 190 | return; | return; |
191 | 191 | } | } |
192 | 192 | ||
... | ... | void pack(unsigned char **pbuf, unsigned int *len, const char *fmt, ...) | |
252 | 252 | memcpy(q, &u64be, 8); q += 8; | memcpy(q, &u64be, 8); q += 8; |
253 | 253 | break; | break; |
254 | 254 | ||
255 | case 't': // struct timeval | ||
255 | case 't': { // struct timeval | ||
256 | 256 | struct timeval *tv = va_arg(va, struct timeval *); | struct timeval *tv = va_arg(va, struct timeval *); |
257 | 257 | u64 = tv->tv_sec * 1000 + tv->tv_usec / 1000; | u64 = tv->tv_sec * 1000 + tv->tv_usec / 1000; |
258 | 258 | u64be = htobe64(u64); | u64be = htobe64(u64); |
259 | 259 | memcpy(q, &u64be, 8); q += 8; | memcpy(q, &u64be, 8); q += 8; |
260 | break; | ||
260 | } break; | ||
261 | 261 | ||
262 | case 'N': // struct timeval "now" | ||
262 | case 'N': { // struct timeval "now" | ||
263 | 263 | struct timeval now; | struct timeval now; |
264 | 264 | ninedogs_now(&now); | ninedogs_now(&now); |
265 | 265 | u64 = now.tv_sec * 1000 + now.tv_usec / 1000; | u64 = now.tv_sec * 1000 + now.tv_usec / 1000; |
266 | 266 | u64be = htobe64(u64); | u64be = htobe64(u64); |
267 | 267 | memcpy(q, &u64be, 8); q += 8; | memcpy(q, &u64be, 8); q += 8; |
268 | break; | ||
268 | } break; | ||
269 | 269 | ||
270 | 270 | default: | default: |
271 | xlog(0, "invalid format [%c]!\n", *f); | ||
271 | xlog(1, "invalid format [%c]!\n", *f); | ||
272 | 272 | abort(); | abort(); |
273 | 273 | } | } |
274 | 274 | ||
... | ... | unsigned int unpack(void *dst, const char type, const unsigned int max, | |
336 | 336 | return 0xFFFFFFF1; | return 0xFFFFFFF1; |
337 | 337 | } | } |
338 | 338 | if (u32 + 1 > max) { | if (u32 + 1 > max) { |
339 | xlog(0, " u32[%u] + 1 > max[%u]\n", u32, max); | ||
339 | xlog(1, " u32[%u] + 1 > max[%u]\n", u32, max); | ||
340 | 340 | return 0xFFFFFFF2; | return 0xFFFFFFF2; |
341 | 341 | } | } |
342 | 342 | memcpy(dst, buf + *off, u32); *off = *off + u32; | memcpy(dst, buf + *off, u32); *off = *off + u32; |
... | ... | unsigned int unpack(void *dst, const char type, const unsigned int max, | |
371 | 371 | //Log(60, " decoded u32 %u\n", u32); | //Log(60, " decoded u32 %u\n", u32); |
372 | 372 | break; | break; |
373 | 373 | ||
374 | case 'N': // "now", timestamp | ||
374 | case '_': // "now", timestamp | ||
375 | 375 | case '8': // u64, unsigned | case '8': // u64, unsigned |
376 | 376 | case 't': // timeval | case 't': // timeval |
377 | 377 | if (*off + 8 > len) | if (*off + 8 > len) |
... | ... | char mkdir_recursive(const char *dir, const mode_t mode) | |
421 | 421 | if (!p) | if (!p) |
422 | 422 | break; | break; |
423 | 423 | *p = '\0'; | *p = '\0'; |
424 | r = mkdir(path, mode); | ||
424 | r = mkdir(path, mode | S_IXUSR); | ||
425 | 425 | *p = '/'; | *p = '/'; |
426 | if ((r == -1) && (errno != EEXIST)) | ||
426 | if ((r == -1) && (errno != EEXIST)) { | ||
427 | xlog(1, "%s: cannot create dir [%s]: %m\n", __func__, path); | ||
427 | 428 | return -1; | return -1; |
429 | } | ||
428 | 430 | q = p + 1; | q = p + 1; |
429 | 431 | } while (1); | } while (1); |
430 | 432 | ||
431 | r = mkdir(path, mode); | ||
432 | if ((r == -1) && (errno != EEXIST)) | ||
433 | r = mkdir(path, mode | S_IXUSR); | ||
434 | if ((r == -1) && (errno != EEXIST)) { | ||
435 | xlog(1, "%s: cannot create dir [%s]: %m\n", __func__, path); | ||
433 | 436 | return -1; | return -1; |
437 | } | ||
434 | 438 | ||
435 | 439 | return 0; | return 0; |
436 | 440 | } | } |
... | ... | int save_buf(int fd, const void *buf, const unsigned int len) | |
472 | 476 | ||
473 | 477 | off = 0; | off = 0; |
474 | 478 | do { | do { |
475 | xlog(14, "%s: Writing %u, off %u bytes to fd %d\n", __func__, len - off, off, fd); | ||
479 | xlog(50, "%s: Writing %u, off %u bytes to fd %d\n", __func__, len - off, off, fd); | ||
476 | 480 | ssize_t n = write(fd, buf + off, len - off); | ssize_t n = write(fd, buf + off, len - off); |
477 | 481 | if (n == -1) { | if (n == -1) { |
478 | 482 | if (errno == EAGAIN) | if (errno == EAGAIN) |
... | ... | int save_buf(int fd, const void *buf, const unsigned int len) | |
486 | 490 | return len; | return len; |
487 | 491 | } | } |
488 | 492 | ||
489 | int save_file(const char *path, const void *buf, const unsigned int len) | ||
493 | int save_file(const char *path, const mode_t mode, | ||
494 | const void *buf, const unsigned int len) | ||
490 | 495 | { | { |
491 | 496 | do { | do { |
492 | xlog(14, "%s: Saving %u bytes to %s\n", __func__, len, path); | ||
493 | int fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0600); | ||
497 | char *copy = nd_strdup(path, -1); | ||
498 | char *dir = dirname(copy); | ||
499 | int r = mkdir_recursive(dir, 0600); | ||
500 | free(copy); | ||
501 | if (r == -1) | ||
502 | break; | ||
503 | |||
504 | xlog(50, "%s: Saving %u bytes to %s\n", __func__, len, path); | ||
505 | int fd = open(path, mode, 0600); | ||
494 | 506 | if (fd == -1) { | if (fd == -1) { |
495 | 507 | xlog(1, "%s: [%s] error: %m\n", __func__, path); | xlog(1, "%s: [%s] error: %m\n", __func__, path); |
496 | 508 | break; | break; |
497 | 509 | } | } |
498 | 510 | ||
499 | int r = save_buf(fd, buf, len); | ||
511 | r = save_buf(fd, buf, len); | ||
500 | 512 | close(fd); | close(fd); |
501 | 513 | if (r == -1) | if (r == -1) |
502 | 514 | break; | break; |
... | ... | int save_file(const char *path, const void *buf, const unsigned int len) | |
507 | 519 | return -1; | return -1; |
508 | 520 | } | } |
509 | 521 | ||
510 | int save_dir_file(const char *dir, const char *file, const void *buf, | ||
511 | const unsigned int len) | ||
522 | int save_dir_file(const char *dir, const char *file, const mode_t mode, | ||
523 | const void *buf, const unsigned int len) | ||
512 | 524 | { | { |
513 | 525 | char path[4096]; | char path[4096]; |
514 | 526 | ||
515 | 527 | snprintf(path, sizeof(path), "%s/%s", dir, file); | snprintf(path, sizeof(path), "%s/%s", dir, file); |
516 | return save_file(path, buf, len); | ||
528 | return save_file(path, mode, buf, len); | ||
517 | 529 | } | } |
518 | 530 | ||
519 | 531 | int load_file(void *buf, const size_t buf_size, const char *path) | int load_file(void *buf, const size_t buf_size, const char *path) |
520 | 532 | { | { |
521 | 533 | do { | do { |
522 | xlog(14, "%s: Loading max %u bytes from %s\n", __func__, buf_size, path); | ||
534 | xlog(50, "%s: Loading max %u bytes from %s\n", __func__, buf_size, path); | ||
523 | 535 | int fd = open(path, O_RDONLY); | int fd = open(path, O_RDONLY); |
524 | 536 | if (fd == -1) { | if (fd == -1) { |
525 | 537 | xlog(1, "%s: [%s] error: %m\n", __func__, path); | xlog(1, "%s: [%s] error: %m\n", __func__, path); |
... | ... | int load_dir_file_text(char *buf, const size_t buf_size, const char *dir, | |
563 | 575 | return r; | return r; |
564 | 576 | } | } |
565 | 577 | ||
578 | int nd_stat_dir_file(struct stat *s, const char *dir, const char *file) | ||
579 | { | ||
580 | char path[4096]; | ||
581 | snprintf(path, sizeof(path), "%s/%s", dir, file); | ||
582 | return stat(path, s); | ||
583 | } | ||
584 | |||
585 | char *nd_strdup(const char *s, int len) | ||
586 | { | ||
587 | if (!s || (len == 0)) | ||
588 | return NULL; | ||
589 | |||
590 | if (len == -1) | ||
591 | len = strlen(s); | ||
592 | |||
593 | char *ret = malloc(len + 1); | ||
594 | if (!ret) | ||
595 | return NULL; | ||
596 | |||
597 | memcpy(ret, s, len); | ||
598 | ret[len] = '\0'; | ||
599 | |||
600 | return ret; | ||
601 | } | ||
602 | |||
603 | /* | ||
604 | * Loads a string from an user file | ||
605 | */ | ||
606 | int nd_load_uid_file_str(void *out, const size_t out_size, | ||
607 | const unsigned int uid, const char *file) | ||
608 | { | ||
609 | char path[1024]; | ||
610 | snprintf(path, sizeof(path), | ||
611 | "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x", | ||
612 | uid, uid >> 8, uid); | ||
613 | int r = load_dir_file(out, out_size, path, file); | ||
614 | if (r == -1) | ||
615 | return -1; | ||
616 | |||
617 | if ((unsigned long) r < out_size) { | ||
618 | char *out2 = (char *) out; | ||
619 | out2[r] = '\0'; | ||
620 | } | ||
621 | |||
622 | return r; | ||
623 | } | ||
624 | |||
625 | /* | ||
626 | * Loads a long from an user file | ||
627 | */ | ||
628 | int nd_load_uid_file_long(long *out, const unsigned int uid, const char *file) | ||
629 | { | ||
630 | long ret; | ||
631 | |||
632 | int r = nd_load_uid_file_str(&ret, sizeof(ret), uid, file); | ||
633 | if (r == -1) | ||
634 | return -1; | ||
635 | |||
636 | *out = be64toh(ret); | ||
637 | |||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | /* | ||
642 | * Saves a long into a user file | ||
643 | */ | ||
644 | int nd_save_uid_file_long(const unsigned int uid, const char *file, | ||
645 | const long v) | ||
646 | { | ||
647 | const long v2 = htobe64(v); | ||
648 | |||
649 | char path[1024]; | ||
650 | snprintf(path, sizeof(path), | ||
651 | "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x", | ||
652 | uid, uid >> 8, uid); | ||
653 | int r = save_dir_file(path, file, O_CREAT | O_TRUNC | O_WRONLY, | ||
654 | &v2, 8); | ||
655 | if (r == -1) | ||
656 | return -1; | ||
657 | |||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | /* | ||
662 | * Convert a /proc/?/cmdline to a printable form | ||
663 | */ | ||
664 | void nd_app_nice(char *out, const unsigned out_size, | ||
665 | const char *in, const unsigned in_len) | ||
666 | { | ||
667 | unsigned j = 0; | ||
668 | |||
669 | if (out_size < 3) | ||
670 | return; | ||
671 | |||
672 | out[j++] = '['; | ||
673 | for (unsigned i = 0; i < in_len; i++) { | ||
674 | if (j + 3 > out_size - 1) | ||
675 | break; | ||
676 | if (in[i] == '\0') { | ||
677 | if (i == in_len - 1) | ||
678 | break; | ||
679 | out[j++] = ']'; | ||
680 | out[j++] = ' '; | ||
681 | out[j++] = '['; | ||
682 | } else { | ||
683 | out[j++] = in[i]; | ||
684 | } | ||
685 | } | ||
686 | |||
687 | out[j++] = ']'; | ||
688 | out[j] = '\0'; | ||
689 | } | ||
690 | |||
691 | void nd_ts_to_str(char *out, const size_t out_size, const unsigned long ts) | ||
692 | { | ||
693 | struct tm tm; | ||
694 | time_t t = ts; | ||
695 | |||
696 | gmtime_r(&t, &tm); | ||
697 | strftime(out, out_size, "%F %T", &tm); | ||
698 | } | ||
699 | |||
700 | /* | ||
701 | * Append a string, respecting limits | ||
702 | */ | ||
703 | void nd_str_append(char *out, const size_t out_size, size_t *off, | ||
704 | const char *fmt, ...) | ||
705 | { | ||
706 | if (*off >= out_size) | ||
707 | return; | ||
708 | |||
709 | va_list va; | ||
710 | |||
711 | va_start(va, fmt); | ||
712 | int r = vsnprintf(out + *off, out_size - *off, fmt, va); | ||
713 | va_end(va); | ||
714 | |||
715 | if ((r > 0) && ((unsigned long) r < out_size - *off)) | ||
716 | *off = *off + r; | ||
717 | } | ||
718 | |||
719 | /* | ||
720 | * Removes end characters in @what string | ||
721 | */ | ||
722 | void nd_rtrim(char *s, const char *what) | ||
723 | { | ||
724 | char *q = s; | ||
725 | |||
726 | while (*q != '\0') | ||
727 | q++; | ||
728 | q--; | ||
729 | |||
730 | while (q >= s) { | ||
731 | if (!strchr(what, *q)) | ||
732 | break; | ||
733 | *q = '\0'; | ||
734 | q--; | ||
735 | } | ||
736 | } | ||
737 | |||
738 | /* | ||
739 | * Helper for nd_send_mail | ||
740 | */ | ||
741 | struct upload_status { size_t read, total; char *data; } nd_send_mail_status; | ||
742 | static size_t nd_send_mail_payload(char *ptr, size_t size, size_t nmemb, | ||
743 | void *user) | ||
744 | { | ||
745 | struct upload_status *us = user; | ||
746 | size_t rest; | ||
747 | |||
748 | xlog(50, "%s: read=%zu total=%zu\n", __func__, us->read, us->total); | ||
749 | |||
750 | rest = us->total - us->read; | ||
751 | if (rest > size * nmemb) | ||
752 | rest = size * nmemb; | ||
753 | |||
754 | memcpy(ptr, us->data + us->read, rest); | ||
755 | us->read += rest; | ||
756 | |||
757 | return rest; | ||
758 | } | ||
759 | |||
760 | int nd_send_mail(const char *to, const char *from, const char *from_nice, | ||
761 | const char *subject, const char *body) | ||
762 | { | ||
763 | CURL *c; | ||
764 | CURLcode res; | ||
765 | struct curl_slist *tos = NULL; | ||
766 | char final[64 * 4096]; | ||
767 | struct timeval now; | ||
768 | char date[100]; | ||
769 | |||
770 | ninedogs_now(&now); | ||
771 | struct tm tm = *gmtime(&now.tv_sec); | ||
772 | strftime(date, sizeof(date), "%a, %d %b %y %T %z", &tm); | ||
773 | snprintf(final, sizeof(final), | ||
774 | "Date: %s\r\n" | ||
775 | "To: %s\r\n" | ||
776 | "From: %s <%s>\r\n" | ||
777 | "Message-ID: ninedogs-notification-%ld\r\n" | ||
778 | "Subject: %s\r\n" | ||
779 | "\r\n" /* empty line to divide headers from body, see RFC5322 */ | ||
780 | "%s\r\n", | ||
781 | date, to, from_nice, from, now.tv_sec, subject, body); | ||
782 | xlog(1, "%s: final:\n%s\n", __func__, final); | ||
783 | |||
784 | c = curl_easy_init(); | ||
785 | if (!c) | ||
786 | return -1; | ||
787 | |||
788 | curl_easy_setopt(c, CURLOPT_URL, "smtp://localhost:25"); | ||
789 | //curl_easy_setopt(c, CURLOPT_USERNAME, "kurt"); | ||
790 | //curl_easy_setopt(c, CURLOPT_PASSWORD, "xipj3plmq"); | ||
791 | /* Set the authorization identity (identity to act as) */ | ||
792 | //curl_easy_setopt(c, CURLOPT_SASL_AUTHZID, "ursel"); | ||
793 | /* Force PLAIN authentication */ | ||
794 | //curl_easy_setopt(c, CURLOPT_LOGIN_OPTIONS, "AUTH=PLAIN"); | ||
795 | |||
796 | //todo curl_easy_setopt(c, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL); | ||
797 | curl_easy_setopt(c, CURLOPT_MAIL_FROM, from); | ||
798 | curl_easy_setopt(c, CURLOPT_VERBOSE, 1L); | ||
799 | |||
800 | tos = curl_slist_append(tos, to); | ||
801 | curl_easy_setopt(c, CURLOPT_MAIL_RCPT, tos); | ||
802 | |||
803 | curl_easy_setopt(c, CURLOPT_READFUNCTION, nd_send_mail_payload); | ||
804 | nd_send_mail_status.data = final; | ||
805 | nd_send_mail_status.read = 0; | ||
806 | nd_send_mail_status.total = strlen(final); | ||
807 | curl_easy_setopt(c, CURLOPT_READDATA, &nd_send_mail_status); | ||
808 | curl_easy_setopt(c, CURLOPT_UPLOAD, 1L); | ||
809 | |||
810 | res = curl_easy_perform(c); | ||
811 | if (res == CURLE_OK) | ||
812 | curl_slist_free_all(tos); | ||
813 | |||
814 | curl_easy_cleanup(c); | ||
815 | |||
816 | return 0; | ||
817 | } | ||
818 | |||
819 | /* | ||
820 | * User notification | ||
821 | */ | ||
822 | int nd_user_notify(const unsigned int uid, const char *subject, | ||
823 | const char *body) | ||
824 | { | ||
825 | char email[1024]; | ||
826 | |||
827 | int r = nd_load_uid_file_str(email, sizeof(email), uid, "email"); | ||
828 | if (r == -1) | ||
829 | return -1; | ||
830 | nd_rtrim(email, "\n\r\t "); | ||
831 | xlog(1, "%s: email=[%s]\n", __func__, email); | ||
832 | |||
833 | return nd_send_mail(email, "ninedogs-mail@embedromix.ro", | ||
834 | "Ninedogs certificate expiration", | ||
835 | subject, body); | ||
836 | } | ||
837 |
File common/tools.h changed (mode: 100644) (index f133996..a8815ee) | |||
1 | #include <sys/stat.h> | ||
1 | 2 | #include <sys/time.h> | #include <sys/time.h> |
2 | 3 | #include <stdlib.h> | #include <stdlib.h> |
3 | 4 | ||
5 | extern void xlog(const unsigned int level, const char *format, ...); | ||
6 | |||
4 | 7 | void ninedogs_now(struct timeval *tv); | void ninedogs_now(struct timeval *tv); |
5 | 8 | ||
6 | 9 | void bin2hex(char *out, const void *buf, const unsigned int len); | void bin2hex(char *out, const void *buf, const unsigned int len); |
... | ... | unsigned long long get_day(time_t now); | |
23 | 26 | unsigned long long get_hour(time_t now); | unsigned long long get_hour(time_t now); |
24 | 27 | ||
25 | 28 | int save_buf(int fd, const void *buf, const unsigned int len); | int save_buf(int fd, const void *buf, const unsigned int len); |
26 | int save_file(const char *path, const void *buf, const unsigned int len); | ||
27 | int save_dir_file(const char *dir, const char *file, const void *buf, | ||
28 | const unsigned int len); | ||
29 | int save_file(const char *path, const mode_t mode, | ||
30 | const void *buf, const unsigned int len); | ||
31 | int save_dir_file(const char *dir, const char *file, const mode_t mode, | ||
32 | const void *buf, const unsigned int len); | ||
29 | 33 | int load_file(void *buf, const size_t buf_size, const char *path); | int load_file(void *buf, const size_t buf_size, const char *path); |
30 | 34 | int load_dir_file(void *buf, const size_t buf_size, | int load_dir_file(void *buf, const size_t buf_size, |
31 | 35 | const char *dir, const char *file); | const char *dir, const char *file); |
32 | 36 | int load_dir_file_text(char *buf, const size_t buf_size, | int load_dir_file_text(char *buf, const size_t buf_size, |
33 | 37 | const char *dir, const char *file); | const char *dir, const char *file); |
34 | 38 | ||
39 | int nd_stat_dir_file(struct stat *s, const char *dir, const char *file); | ||
40 | |||
41 | char *nd_strdup(const char *s, int len); | ||
42 | |||
43 | int nd_load_uid_file_str(void *out, const size_t out_size, | ||
44 | const unsigned int uid, const char *file); | ||
45 | |||
46 | int nd_load_uid_file_long(long *out, const unsigned int uid, | ||
47 | const char *file); | ||
48 | int nd_save_uid_file_long(const unsigned int uid, const char *file, | ||
49 | const long v); | ||
50 | |||
51 | void nd_app_nice(char *out, const unsigned out_size, | ||
52 | const char *in, const unsigned in_len); | ||
53 | |||
54 | void nd_ts_to_str(char *out, const size_t out_size, | ||
55 | const unsigned long ts); | ||
56 | |||
57 | void nd_str_append(char *out, const size_t out_size, size_t *off, | ||
58 | const char *fmt, ...); | ||
59 | |||
60 | void nd_rtrim(char *s, const char *what); | ||
61 | |||
62 | int nd_send_mail(const char *to, const char *from, | ||
63 | const char *from_nice, | ||
64 | const char *subject, const char *body); | ||
65 | |||
66 | int nd_user_notify(const unsigned int uid, const char *subject, | ||
67 | const char *body); | ||
68 |
File debian/control changed (mode: 100644) (index 84ff626..4f8a92e) | |||
... | ... | Source: ninedogs | |
2 | 2 | Maintainer: Catalin(ux) M. BOIE <catab@embedromix.ro> | Maintainer: Catalin(ux) M. BOIE <catab@embedromix.ro> |
3 | 3 | Section: misc | Section: misc |
4 | 4 | Priority: optional | Priority: optional |
5 | Build-Depends: debhelper (>= 9), libgnutls28-dev, json-c-dev, libcap-dev, texlive-latex-base, texlive-latex-extra, catalinux+Conn | ||
5 | Build-Depends: debhelper (>= 9), libgnutls28-dev, json-c-dev, libcap-dev, texlive-latex-base, texlive-latex-extra, libcurl-dev, catalinux+Conn | ||
6 | 6 | Standards-Version: 3.9.6 | Standards-Version: 3.9.6 |
7 | 7 | Homepage: https://rocketgit.com/user/catalinux/ninedogs | Homepage: https://rocketgit.com/user/catalinux/ninedogs |
8 | 8 | Vcs-Git: git://rocketgit.com/user/catalinux/ninedogs | Vcs-Git: git://rocketgit.com/user/catalinux/ninedogs |
... | ... | Vcs-Browser: https://rocketgit.com/user/catalinux/ninedogs | |
10 | 10 | ||
11 | 11 | Package: ninedogs | Package: ninedogs |
12 | 12 | Architecture: all | Architecture: all |
13 | Depends: ${shlibs:Depends}, ${misc:Depends}, libgnutls30, json-c, libcap, catalinux+Conn | ||
13 | Depends: ${shlibs:Depends}, ${misc:Depends}, libgnutls30, json-c, libcap, libcurl, catalinux+Conn | ||
14 | 14 | Description: Light and fast application monitoring and tracing | Description: Light and fast application monitoring and tracing |
File docs/Makefile changed (mode: 100644) (index ad88c82..98f21bf) | |||
... | ... | PDFs := pre1.pdf | |
2 | 2 | ||
3 | 3 | all: $(PDFs) | all: $(PDFs) |
4 | 4 | ||
5 | compile: $(PDFs) | ||
6 | |||
7 | 5 | pre1.pdf: pre1.tex | pre1.pdf: pre1.tex |
8 | 6 | pdflatex $< && pdflatex $< | pdflatex $< && pdflatex $< |
9 | 7 |
File docs/colors1.png added (mode: 100644) (index 0000000..0c2222b) |
File docs/pre1.tex changed (mode: 100644) (index 5e966f5..2ae00f1) | |||
... | ... | recvfrom(5, "\7\0\0\2\0\0\0\2\0\0\0", 32768, MSG_DONTWAIT, NULL, NULL) = 11 | |
275 | 275 | \tiny | \tiny |
276 | 276 | \begin{verbatim} | \begin{verbatim} |
277 | 277 | mysqli_real_connect(link=0x7ffba947f190, 'host=h1 user=ninedogs port=3306 db=ninedogs socket=', | mysqli_real_connect(link=0x7ffba947f190, 'host=h1 user=ninedogs port=3306 db=ninedogs socket=', |
278 | flags='0x20|COMPRESS') | ||
278 | flags=0x20|COMPRESS) | ||
279 | 279 | mysqli_real_connect(link=0x7ffba947f190, 'host=h1 user=ninedogs port=3306 db=ninedogs socket=', | mysqli_real_connect(link=0x7ffba947f190, 'host=h1 user=ninedogs port=3306 db=ninedogs socket=', |
280 | flags='0x20|COMPRESS') = ok | ||
280 | flags=0x20|COMPRESS) = ok | ||
281 | 281 | \end{verbatim} | \end{verbatim} |
282 | 282 | \end{block} | \end{block} |
283 | 283 | \end{frame} | \end{frame} |
File docs/pre1.txt changed (mode: 100644) (index a3035c0..fd94e7b) | |||
... | ... | Ideas for the first presentation | |
15 | 15 | - Explain "augmented". | - Explain "augmented". |
16 | 16 | - Language: C | - Language: C |
17 | 17 | - Where you can find the latest version of this presentation? | - Where you can find the latest version of this presentation? |
18 | - Switch to 16:9 format | ||
19 | - No re-compilation, no hard deployment procedure => easy all over | ||
20 | - Package management security updates not done. | ||
21 | - add color1.png | ||
18 | 22 | - | - |
19 | 23 | ||
20 | 24 | - Ce probleme vrei sa le rezolvi? | - Ce probleme vrei sa le rezolvi? |
File duilder changed (mode: 100755) (index 090eaa8..beaa5e0) | |||
... | ... | else | |
543 | 543 | fi | fi |
544 | 544 | ||
545 | 545 | if [ "${CC_SWITCHES}" = "" ]; then | if [ "${CC_SWITCHES}" = "" ]; then |
546 | CC_SWITCHES="-O3 -fstack-reuse=all -flto -Wtrampolines -Wl,-z,noexecstack -Wl,-z,now -Wl,-z,relro -Wl,-O1 -Wl,-z,noexecstack -fstack-protector-all -Wcast-align -Wformat=2 -Wformat-security -fno-common -Wmissing-prototypes -Wmissing-declarations -Wstrict-overflow -Wstrict-prototypes -fno-guess-branch-probability -fbounds-check -Wl,-O3 -Wpadded -ftree-loop-distribution -ftree-vectorize -ftree-loop-if-convert -ftree-loop-im -ftree-parallelize-loops=4 -fcf-protection -fstack-clash-protection -Wimplicit-fallthrough -fanalyzer" | ||
546 | CC_SWITCHES="-O3 -fstack-reuse=all -flto=auto|-flto -Wtrampolines -Wl,-z,noexecstack -Wl,-z,now -Wl,-z,relro -Wl,-O1 -Wl,-z,noexecstack -fstack-protector-all -Wcast-align -Wformat=2 -Wformat-security -fno-common -Wmissing-prototypes -Wmissing-declarations -Wstrict-overflow -Wstrict-prototypes -fno-guess-branch-probability -fbounds-check -Wl,-O3 -Wpadded -ftree-loop-distribution -ftree-vectorize -ftree-loop-if-convert -ftree-loop-im -ftree-parallelize-loops=4 -fcf-protection -fstack-clash-protection -Wimplicit-fallthrough -D_FORTIFY_SOURCES=3|-D_FORTIFY_SOURCES=2 -fanalyzer" | ||
547 | 547 | fi | fi |
548 | 548 | ||
549 | 549 | if [ "1" = "1" ]; then | if [ "1" = "1" ]; then |
550 | 550 | _CC_SWITCHES="" | _CC_SWITCHES="" |
551 | 551 | echo "[*] Search for valid compiler flags..." | echo "[*] Search for valid compiler flags..." |
552 | 552 | add="" | add="" |
553 | for s in ${CC_SWITCHES}; do | ||
554 | echo -n " [*] Testing switch [${s}]..." | ||
555 | case ${s} in | ||
556 | -Wformat-security) extra=" -Wformat" ;; | ||
557 | *) extra="" ;; | ||
558 | esac | ||
559 | set +e | ||
560 | echo "int main(void) { return 0; }" \ | ||
561 | | gcc ${extra} ${s} -x c -pipe - -o /dev/null 2>>duilder.log | ||
562 | E=${?} | ||
563 | set -e | ||
564 | if [ "${E}" != "0" ]; then | ||
565 | echo "not supported" | ||
566 | else | ||
567 | echo "supported" | ||
568 | _CC_SWITCHES="${_CC_SWITCHES}${add}${s}" | ||
569 | add=" " | ||
570 | fi | ||
553 | for s0 in ${CC_SWITCHES}; do | ||
554 | list=(${s0/|/ }) | ||
555 | for s in ${list}; do | ||
556 | echo -n " [*] Testing switch [${s}]..." | ||
557 | case ${s} in | ||
558 | -Wformat-security) extra=" -Wformat" ;; | ||
559 | *) extra="" ;; | ||
560 | esac | ||
561 | set +e | ||
562 | echo "int main(void) { return 0; }" \ | ||
563 | | gcc ${extra} ${s} -x c -pipe - -o /dev/null 2>>duilder.log | ||
564 | E=${?} | ||
565 | set -e | ||
566 | if [ "${E}" != "0" ]; then | ||
567 | echo "not supported" | ||
568 | else | ||
569 | echo "supported" | ||
570 | _CC_SWITCHES="${_CC_SWITCHES}${add}${s}" | ||
571 | add=" " | ||
572 | break # first try will win | ||
573 | fi | ||
574 | done | ||
571 | 575 | done | done |
572 | 576 | fi | fi |
573 | 577 | ||
... | ... | if [ "${BUILD_SDEB}" = "1" ]; then | |
688 | 692 | AUTOGENERATE="${AUTOGENERATE} debian/control.in debian/changelog.in" | AUTOGENERATE="${AUTOGENERATE} debian/control.in debian/changelog.in" |
689 | 693 | AUTOGENERATE="${AUTOGENERATE} debian/copyright.in debian/rules.in" | AUTOGENERATE="${AUTOGENERATE} debian/copyright.in debian/rules.in" |
690 | 694 | fi | fi |
695 | AUTOGENERATE="${AUTOGENERATE} $(find . -name '*.in')" | ||
691 | 696 | ||
692 | 697 | echo "[*] Autogenerate files from .in..." | echo "[*] Autogenerate files from .in..." |
693 | 698 | for f in ${AUTOGENERATE}; do | for f in ${AUTOGENERATE}; do |
File ingestd/Makefile changed (mode: 100644) (index be65fb6..d4dc875) | |||
1 | COMMON_H += ../common/ids.h ../common/tools.h ../common/sctools.h stools.h priv.h | ||
2 | OBJS := ../common/tools.o ../common/sctools.o stools.o \ | ||
1 | include ../Makefile.common | ||
2 | |||
3 | COMMON_H += ../common/ids.h ../common/tools.h ../common/bin2struct.h stools.h priv.h | ||
4 | OBJS := ../common/tools.o ../common/bin2struct.o \ | ||
5 | stools.o \ | ||
3 | 6 | decode.o decode_core.o decode_db.o decode_ssl.o | decode.o decode_core.o decode_db.o decode_ssl.o |
4 | 7 | ||
5 | 8 | CFLAGS += -I../common | CFLAGS += -I../common |
6 | 9 | ||
7 | all: | ||
8 | make -R -C .. ingestd | ||
9 | |||
10 | compile: ninedogs-ingestd | ||
10 | all: ninedogs-ingestd | ||
11 | 11 | ||
12 | 12 | stools.o: stools.c $(COMMON_H) | stools.o: stools.c $(COMMON_H) |
13 | 13 | $(CC) $(CFLAGS) -c $< | $(CC) $(CFLAGS) -c $< |
... | ... | stools.o: stools.c $(COMMON_H) | |
15 | 15 | decode.o: decode.c decode.h $(COMMON_H) | decode.o: decode.c decode.h $(COMMON_H) |
16 | 16 | $(CC) $(CFLAGS) -c $< | $(CC) $(CFLAGS) -c $< |
17 | 17 | ||
18 | decode_core.o: decode_core.c decode_core.h $(COMMON_H) | ||
18 | decode_core.o: decode_core.c decode_core.h $(COMMON_H) \ | ||
19 | ../common/bin2struct.h | ||
19 | 20 | $(CC) $(CFLAGS) -c $< | $(CC) $(CFLAGS) -c $< |
20 | 21 | ||
21 | 22 | decode_db.o: decode_db.c decode_db.h $(COMMON_H) | decode_db.o: decode_db.c decode_db.h $(COMMON_H) |
... | ... | install: ninedogs-ingestd | |
32 | 33 | @cp ninedogs-ingestd $(I_USR_SBIN) | @cp ninedogs-ingestd $(I_USR_SBIN) |
33 | 34 | @mkdir -pv $(I_USR)/lib/systemd/system | @mkdir -pv $(I_USR)/lib/systemd/system |
34 | 35 | cp -vd *.service $(I_USR)/lib/systemd/system/ | cp -vd *.service $(I_USR)/lib/systemd/system/ |
36 | @systemctl daemon-reload | ||
35 | 37 | ||
36 | 38 | .PHONY: clean | .PHONY: clean |
37 | 39 | clean: | clean: |
File ingestd/TODO added (mode: 100644) (index 0000000..c3e3da1) | |||
1 | [ ] Send local IPs | ||
2 | [ ] Seems the server is requesting a query twice! | ||
3 | [ ] |
File ingestd/decode.c changed (mode: 100644) (index 8055396..0276430) | |||
... | ... | unsigned int decode(struct Conn *C, unsigned char *buf, const unsigned int len) | |
24 | 24 | Log(20, "%s: dump: len=%u %s\n", __func__, len, dump); | Log(20, "%s: dump: len=%u %s\n", __func__, len, dump); |
25 | 25 | free(dump); | free(dump); |
26 | 26 | ||
27 | struct priv *p = Conn_get_private(C); | ||
28 | |||
27 | 29 | while (off + 4 + 1 + 4 < len) { | while (off + 4 + 1 + 4 < len) { |
28 | 30 | flags = 0; | flags = 0; |
29 | 31 | ioff = off; | ioff = off; |
... | ... | unsigned int decode(struct Conn *C, unsigned char *buf, const unsigned int len) | |
33 | 35 | return 0; | return 0; |
34 | 36 | ||
35 | 37 | if (buf[off++] != 'T') { | if (buf[off++] != 'T') { |
36 | Log(2, "Invalid frame (not starting with T)!\n"); | ||
38 | Log(2, "Invalid frame (not starting with 'T')!\n"); | ||
37 | 39 | Conn_close(C); | Conn_close(C); |
38 | 40 | return 0; | return 0; |
39 | 41 | } | } |
... | ... | unsigned int decode(struct Conn *C, unsigned char *buf, const unsigned int len) | |
63 | 65 | else if ((flags & DECODE_FLAGS_NO_SAVE) == 0) | else if ((flags & DECODE_FLAGS_NO_SAVE) == 0) |
64 | 66 | save_data(C, buf + ioff, 4 + plen, ts); | save_data(C, buf + ioff, 4 + plen, ts); |
65 | 67 | ||
68 | save_machine_visibility(C, ts); | ||
69 | |||
66 | 70 | off += plen - 1 - 4; | off += plen - 1 - 4; |
67 | 71 | } | } |
68 | 72 | ||
69 | struct priv *p = Conn_get_private(C); | ||
70 | 73 | if ((p->stop_received == 1) && (p->req_pending == 0)) { | if ((p->stop_received == 1) && (p->req_pending == 0)) { |
71 | 74 | Log(10, "stop_received == 1 and req_pending is 0 => close connection\n"); | Log(10, "stop_received == 1 and req_pending is 0 => close connection\n"); |
72 | 75 | Conn_close(C); | Conn_close(C); |
File ingestd/decode_core.c changed (mode: 100644) (index 903ecf6..99cad31) | |||
9 | 9 | #include "tools.h" | #include "tools.h" |
10 | 10 | #include "stools.h" | #include "stools.h" |
11 | 11 | #include "priv.h" | #include "priv.h" |
12 | #include "bin2struct.h" | ||
12 | 13 | ||
13 | 14 | static int decode_core_id(struct Conn *C, | static int decode_core_id(struct Conn *C, |
14 | unsigned char *buf, const unsigned int len) | ||
15 | unsigned char *buf, const unsigned int len, unsigned long long *ts) | ||
15 | 16 | { | { |
16 | 17 | unsigned int off = 0, ioff; | unsigned int off = 0, ioff; |
17 | 18 | struct priv *p = Conn_get_private(C); | struct priv *p = Conn_get_private(C); |
... | ... | static int decode_core_id(struct Conn *C, | |
24 | 25 | ioff = off; | ioff = off; |
25 | 26 | c = buf[off++]; | c = buf[off++]; |
26 | 27 | switch (c) { | switch (c) { |
28 | case '_': r = unpack(ts, 't', sizeof(*ts), buf, len, &off); break; | ||
27 | 29 | case 'I': r = unpack(&p->id.id, 's', 33, buf, len, &off); break; | case 'I': r = unpack(&p->id.id, 's', 33, buf, len, &off); break; |
28 | 30 | default: r = 0xFFFFFFFE; break; | default: r = 0xFFFFFFFE; break; |
29 | 31 | } | } |
... | ... | static int decode_core_uname(struct Conn *C, | |
106 | 108 | ioff = off; | ioff = off; |
107 | 109 | c = buf[off++]; | c = buf[off++]; |
108 | 110 | switch (c) { | switch (c) { |
109 | case 'N': r = unpack(ts, 't', sizeof(*ts), buf, len, &off); break; | ||
111 | case '_': r = unpack(ts, 't', sizeof(*ts), buf, len, &off); break; | ||
110 | 112 | case 's': r = unpack(&p->uname.sysname, 's', sizeof(p->uname.sysname), buf, len, &off); break; | case 's': r = unpack(&p->uname.sysname, 's', sizeof(p->uname.sysname), buf, len, &off); break; |
111 | 113 | case 'n': r = unpack(&p->uname.nodename, 's', sizeof(p->uname.nodename), buf, len, &off); break; | case 'n': r = unpack(&p->uname.nodename, 's', sizeof(p->uname.nodename), buf, len, &off); break; |
112 | 114 | case 'r': r = unpack(&p->uname.release, 's', sizeof(p->uname.release), buf, len, &off); break; | case 'r': r = unpack(&p->uname.release, 's', sizeof(p->uname.release), buf, len, &off); break; |
... | ... | static int decode_core_uname(struct Conn *C, | |
128 | 130 | return 0; | return 0; |
129 | 131 | } | } |
130 | 132 | ||
131 | static int decode_core_sysinfo(unsigned char *buf, const unsigned int len, | ||
132 | unsigned long long *ts) | ||
133 | { | ||
134 | unsigned int off = 0, ioff; | ||
135 | unsigned int r; | ||
136 | char c; | ||
137 | struct sysinfo s; | ||
138 | |||
139 | while (off + 1 + 1 <= len) { | ||
140 | ioff = off; | ||
141 | c = buf[off++]; | ||
142 | switch (c) { | ||
143 | case 'N': r = unpack(ts, 't', sizeof(*ts), buf, len, &off); break; | ||
144 | case 'u': r = unpack(&s.uptime, '8', sizeof(s.uptime), buf, len, &off); break; | ||
145 | case '1': r = unpack(&s.loads[0], '8', sizeof(s.loads[0]), buf, len, &off); break; | ||
146 | case '5': r = unpack(&s.loads[1], '8', sizeof(s.loads[1]), buf, len, &off); break; | ||
147 | case 'q': r = unpack(&s.loads[2], '8', sizeof(s.loads[2]), buf, len, &off); break; | ||
148 | case 'r': r = unpack(&s.totalram, '8', sizeof(s.totalram), buf, len, &off); break; | ||
149 | case 'f': r = unpack(&s.freeram, '8', sizeof(s.freeram), buf, len, &off); break; | ||
150 | case 's': r = unpack(&s.sharedram, '8', sizeof(s.sharedram), buf, len, &off); break; | ||
151 | case 'b': r = unpack(&s.bufferram, '8', sizeof(s.bufferram), buf, len, &off); break; | ||
152 | case 'w': r = unpack(&s.totalswap, '8', sizeof(s.totalswap), buf, len, &off); break; | ||
153 | case 'W': r = unpack(&s.freeswap, '8', sizeof(s.freeswap), buf, len, &off); break; | ||
154 | case 'p': r = unpack(&s.procs, '2', sizeof(s.procs), buf, len, &off); break; | ||
155 | case 'h': r = unpack(&s.totalhigh, '8', sizeof(s.totalhigh), buf, len, &off); break; | ||
156 | case 'H': r = unpack(&s.freehigh, '8', sizeof(s.freehigh), buf, len, &off); break; | ||
157 | case 'i': r = unpack(&s.mem_unit, '4', sizeof(s.mem_unit), buf, len, &off); break; | ||
158 | default: r = 0xFFFFFFFE; break; | ||
159 | } | ||
160 | if (r >= 0xFFFFFFF0) { | ||
161 | Log(1, "%s: Cannot decode core sysinfo r=0x%08x c=%c[0x%02hhx] off=%u/%u!\n", | ||
162 | __func__, r, c, c, ioff, len); | ||
163 | return -1; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | Log(10, "%s: ts=%llu uptime=%lu loads1=%lu loads5=%lu loads15=%lu totalram=%lu" | ||
168 | " freeram=%lu sharedram=%lu bufferram=%lu totalswap=%lu" | ||
169 | " freeswap=%lu procs=%u totalhigh=%lu freehigh=%lu mem_unit=%u\n", | ||
170 | __func__, *ts, s.uptime, s.loads[0], s.loads[1], s.loads[2], s.totalram, | ||
171 | s.freeram, s.sharedram, s.bufferram, s.totalswap, | ||
172 | s.freeswap, s.procs, s.totalhigh, s.freehigh, s.mem_unit); | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | 133 | static int decode_core_stop(struct Conn *C, | static int decode_core_stop(struct Conn *C, |
178 | 134 | unsigned char *buf, const unsigned int len) | unsigned char *buf, const unsigned int len) |
179 | 135 | { | { |
... | ... | static int decode_core_stop(struct Conn *C, | |
189 | 145 | c = buf[off++]; | c = buf[off++]; |
190 | 146 | switch (c) { | switch (c) { |
191 | 147 | case 's': r = unpack(&start, 't', sizeof(start), buf, len, &off); break; | case 's': r = unpack(&start, 't', sizeof(start), buf, len, &off); break; |
192 | case 't': r = unpack(&stop, 't', sizeof(stop), buf, len, &off); break; | ||
148 | case '_': r = unpack(&stop, 't', sizeof(stop), buf, len, &off); break; | ||
193 | 149 | case 'x': r = unpack(&exit_code, '4', sizeof(exit_code), buf, len, &off); break; | case 'x': r = unpack(&exit_code, '4', sizeof(exit_code), buf, len, &off); break; |
194 | 150 | default: r = 0xFFFFFFFE; break; | default: r = 0xFFFFFFFE; break; |
195 | 151 | } | } |
... | ... | int decode_core(struct Conn *C, const unsigned int type, | |
215 | 171 | unsigned char *buf, const unsigned int len, unsigned int *flags, | unsigned char *buf, const unsigned int len, unsigned int *flags, |
216 | 172 | unsigned long long *ts) | unsigned long long *ts) |
217 | 173 | { | { |
174 | int r; | ||
218 | 175 | char *dump = Conn_dump(buf, len); | char *dump = Conn_dump(buf, len); |
219 | 176 | Log(20, "%s: dump: type=%u len=%u %s\n", __func__, type, len, dump); | Log(20, "%s: dump: type=%u len=%u %s\n", __func__, type, len, dump); |
220 | 177 | free(dump); | free(dump); |
... | ... | int decode_core(struct Conn *C, const unsigned int type, | |
225 | 182 | switch (type) { | switch (type) { |
226 | 183 | case NINEDOGS_NET_CORE_ID: | case NINEDOGS_NET_CORE_ID: |
227 | 184 | *flags = *flags | DECODE_FLAGS_NO_SAVE; | *flags = *flags | DECODE_FLAGS_NO_SAVE; |
228 | return decode_core_id(C, buf, len); | ||
185 | return decode_core_id(C, buf, len, ts); | ||
229 | 186 | case NINEDOGS_NET_CORE_PROC: | case NINEDOGS_NET_CORE_PROC: |
230 | 187 | return decode_core_proc(C, buf, len); | return decode_core_proc(C, buf, len); |
231 | 188 | case NINEDOGS_NET_CORE_UNAME: | case NINEDOGS_NET_CORE_UNAME: |
232 | 189 | return decode_core_uname(C, buf, len, ts); | return decode_core_uname(C, buf, len, ts); |
233 | case NINEDOGS_NET_CORE_SYSINFO: | ||
234 | return decode_core_sysinfo(buf, len, ts); | ||
190 | case NINEDOGS_NET_CORE_SYSINFO: { | ||
191 | struct nd_sysinfo s; | ||
192 | r = nd_bin2struct_core_sysinfo(&s, buf, len); | ||
193 | if (r != -1) | ||
194 | *ts = s.ts; | ||
195 | return r; } | ||
235 | 196 | case NINEDOGS_NET_CORE_STOP: | case NINEDOGS_NET_CORE_STOP: |
236 | 197 | return decode_core_stop(C, buf, len); | return decode_core_stop(C, buf, len); |
237 | 198 | default: | default: |
File ingestd/decode_db.c changed (mode: 100644) (index a48bd29..249caeb) | |||
... | ... | static int decode_query_stats(struct Conn *C, unsigned char *buf, const unsigned | |
88 | 88 | // If we cannot find the query, we need to request it | // If we cannot find the query, we need to request it |
89 | 89 | struct priv *p = Conn_get_private(C); | struct priv *p = Conn_get_private(C); |
90 | 90 | char path[4096]; | char path[4096]; |
91 | snprintf(path, sizeof(path), "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x/q/%c%c/%c%c/%s/q", | ||
91 | snprintf(path, sizeof(path), | ||
92 | "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x" | ||
93 | "/q/%c%c/%c%c/%s/q", | ||
92 | 94 | p->id.client_id, p->id.client_id >> 8, p->id.client_id, | p->id.client_id, p->id.client_id >> 8, p->id.client_id, |
93 | shash[0], shash[1], shash[2], shash[3], shash + 4); | ||
95 | shash[0], shash[1], shash[2], shash[3], shash); | ||
94 | 96 | int r2 = stat(path, &s); | int r2 = stat(path, &s); |
95 | 97 | if ((r2 == -1) && (errno == ENOENT)) { | if ((r2 == -1) && (errno == ENOENT)) { |
96 | 98 | unsigned char *b; | unsigned char *b; |
97 | 99 | unsigned int blen; | unsigned int blen; |
98 | Log(1, " Requesting query %s from client because [%s] not found (%m)...\n", shash, path); | ||
100 | Log(1, " Requesting query %s from client because [%s] not found (%m)...\n", | ||
101 | shash, path); | ||
99 | 102 | pack(&b, &blen, "T4 hb", | pack(&b, &blen, "T4 hb", |
100 | 103 | NINEDOGS_NET_DB_QUERY_STRING, hash, sizeof(hash)); | NINEDOGS_NET_DB_QUERY_STRING, hash, sizeof(hash)); |
101 | 104 | if (b) { | if (b) { |
... | ... | static int decode_query_string(struct Conn *C, | |
117 | 120 | unsigned int off = 0; | unsigned int off = 0; |
118 | 121 | unsigned char hash[32]; | unsigned char hash[32]; |
119 | 122 | char shash[65], query[8192 + 1]; | char shash[65], query[8192 + 1]; |
120 | char path[4096]; | ||
121 | 123 | ||
122 | 124 | while (off + 1 + 1 <= len) { | while (off + 1 + 1 <= len) { |
123 | 125 | unsigned int r; | unsigned int r; |
... | ... | static int decode_query_string(struct Conn *C, | |
139 | 141 | __func__, shash, query); | __func__, shash, query); |
140 | 142 | ||
141 | 143 | // Store query | // Store query |
142 | bin2hex(shash, hash, sizeof(hash)); | ||
143 | 144 | struct priv *p = Conn_get_private(C); | struct priv *p = Conn_get_private(C); |
144 | 145 | p->req_pending--; | p->req_pending--; |
145 | snprintf(path, sizeof(path), "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x/q/%c%c/%c%c/%s", | ||
146 | char dir[4096]; | ||
147 | snprintf(dir, sizeof(dir), | ||
148 | "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x" | ||
149 | "/q/%c%c/%c%c/%s", | ||
146 | 150 | p->id.client_id, p->id.client_id >> 8, p->id.client_id, | p->id.client_id, p->id.client_id >> 8, p->id.client_id, |
147 | shash[0], shash[1], shash[2], shash[3], shash + 4); | ||
148 | int ret = mkdir_recursive(path, 0700); | ||
151 | shash[0], shash[1], shash[2], shash[3], shash); | ||
152 | int ret = save_dir_file(dir, shash, O_CREAT | O_WRONLY | O_TRUNC, | ||
153 | query, strlen(query)); | ||
149 | 154 | if (ret == -1) { | if (ret == -1) { |
150 | Log(1, " cannot create dir [%s]: %m!\n", path); | ||
151 | } else { | ||
152 | strcat(path, "/"); | ||
153 | strcat(path, "q"); | ||
154 | ret = save_file(path, query, strlen(query)); | ||
155 | if (ret != 0) | ||
156 | Log(1, " cannot save query to [%s]: %m\n", path); | ||
155 | Log(1, " cannot save query to [%s/%s]: %m\n", dir, shash); | ||
156 | return -1; | ||
157 | 157 | } | } |
158 | 158 | ||
159 | 159 | return 0; | return 0; |
File ingestd/decode_ssl.c changed (mode: 100644) (index 43a4922..6d84ece) | |||
6 | 6 | #include "ids.h" | #include "ids.h" |
7 | 7 | #include "decode_ssl.h" | #include "decode_ssl.h" |
8 | 8 | #include "tools.h" | #include "tools.h" |
9 | #include "sctools.h" | ||
9 | #include "bin2struct.h" | ||
10 | 10 | #include "stools.h" | #include "stools.h" |
11 | 11 | #include "priv.h" | #include "priv.h" |
12 | 12 | ||
... | ... | static int save_info(struct Conn *C, | |
23 | 23 | while (off + 1 + 1 <= len) { | while (off + 1 + 1 <= len) { |
24 | 24 | c = buf[off++]; | c = buf[off++]; |
25 | 25 | switch (c) { | switch (c) { |
26 | case 'N': r = unpack(&ts, 't', sizeof(ts), buf, len, &off); break; | ||
26 | case '_': r = unpack(&ts, 't', sizeof(ts), buf, len, &off); break; | ||
27 | 27 | case 'v': r = unpack(info, 's', sizeof(info), buf, len, &off); break; | case 'v': r = unpack(info, 's', sizeof(info), buf, len, &off); break; |
28 | 28 | default: r = 0xFFFFFFFE; break; | default: r = 0xFFFFFFFE; break; |
29 | 29 | } | } |
... | ... | static int save_info(struct Conn *C, | |
39 | 39 | Log(10, "%s: ts=%llu info=[%s]\n", __func__, ts, info); | Log(10, "%s: ts=%llu info=[%s]\n", __func__, ts, info); |
40 | 40 | ||
41 | 41 | struct priv *p = Conn_get_private(C); | struct priv *p = Conn_get_private(C); |
42 | char xpath[4096]; | ||
43 | snprintf(xpath, sizeof(xpath), "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x/ssl", | ||
42 | char dir[4096]; | ||
43 | snprintf(dir, sizeof(dir), | ||
44 | "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x/ssl", | ||
44 | 45 | p->id.client_id, p->id.client_id >> 8, p->id.client_id); | p->id.client_id, p->id.client_id >> 8, p->id.client_id); |
45 | mkdir_recursive(xpath, 0700); | ||
46 | |||
47 | strcat(xpath, "/ver"); | ||
48 | int ret = save_file(xpath, buf, len); | ||
46 | int ret = save_dir_file(dir, "ver", O_CREAT | O_TRUNC | O_WRONLY, buf, len); | ||
49 | 47 | if (ret != 0) | if (ret != 0) |
50 | Log(1, " cannot save ssl info to [%s]: %m\n", xpath); | ||
48 | Log(1, " cannot save ssl info to [%s/ver]: %m\n", dir); | ||
51 | 49 | ||
52 | 50 | return 0; | return 0; |
53 | 51 | } | } |
... | ... | static int save_cert(struct Conn *C, | |
60 | 58 | ||
61 | 59 | Log(10, "%s: len=%u\n", __func__, len); | Log(10, "%s: len=%u\n", __func__, len); |
62 | 60 | ||
63 | r = decode_cert(&cert, buf, len); | ||
61 | r = nd_bin2struct_cert(&cert, buf, len); | ||
64 | 62 | if (r == -1) | if (r == -1) |
65 | 63 | return -1; | return -1; |
66 | 64 | ||
... | ... | static int save_cert(struct Conn *C, | |
69 | 67 | char cert_hash[65]; | char cert_hash[65]; |
70 | 68 | ninedogs_sha256_hex(cert_hash, to_hash, strlen(to_hash)); | ninedogs_sha256_hex(cert_hash, to_hash, strlen(to_hash)); |
71 | 69 | struct priv *p = Conn_get_private(C); | struct priv *p = Conn_get_private(C); |
72 | char xpath[4096]; | ||
73 | snprintf(xpath, sizeof(xpath), | ||
70 | char dir[4096]; | ||
71 | snprintf(dir, sizeof(dir), | ||
74 | 72 | "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x/cert/%s", | "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x/cert/%s", |
75 | p->id.client_id, p->id.client_id >> 8, p->id.client_id, cert_hash + 44); | ||
76 | mkdir_recursive(xpath, 0700); | ||
73 | p->id.client_id, p->id.client_id >> 8, p->id.client_id, | ||
74 | cert_hash + 44); | ||
77 | 75 | ||
78 | 76 | // We need to signal what machines are using this cert | // We need to signal what machines are using this cert |
79 | save_app(xpath, C, cert.ts); | ||
77 | save_app(dir, C, cert.ts); | ||
80 | 78 | ||
81 | strcat(xpath, "/data"); | ||
82 | r = save_file(xpath, buf, len); | ||
83 | if (r != 0) | ||
84 | Log(1, " cannot save cert to [%s]: %m\n", xpath); | ||
79 | r = save_dir_file(dir, "/data", O_CREAT | O_WRONLY | O_TRUNC, buf, len); | ||
80 | if (r != 0) { | ||
81 | Log(1, " cannot save cert to [%s/data]: %m\n", dir); | ||
82 | return -1; | ||
83 | } | ||
85 | 84 | ||
86 | 85 | return 0; | return 0; |
87 | 86 | } | } |
File ingestd/ninedogs-ingestd.service changed (mode: 100644) (index 6e80962..6ac6cab) | |||
1 | 1 | [Unit] | [Unit] |
2 | Description=Ninedogs ingestion daemon | ||
2 | Description = Ninedogs ingestion daemon | ||
3 | 3 | ||
4 | 4 | [Service] | [Service] |
5 | Type=exec | ||
6 | ExecStart=/date/sync/no-crypt/sync1/Dev/ninedogs/ingestd/ninedogs-ingestd | ||
7 | PrivateTmp=true | ||
8 | Restart=on-failure | ||
9 | RestartSec=10 | ||
10 | ProtectSystem=full | ||
11 | NoNewPrivileges=yes | ||
5 | Type = exec | ||
6 | ExecStart = /date/sync/no-crypt/sync1/Dev/ninedogs/ingestd/ninedogs-ingestd | ||
7 | PrivateTmp = true | ||
8 | Restart = on-failure | ||
9 | RestartSec = 10 | ||
10 | ProtectSystem = full | ||
11 | NoNewPrivileges = yes | ||
12 | User = ninedogs | ||
13 | Group = ninedogs | ||
12 | 14 | ||
13 | 15 | [Install] | [Install] |
14 | WantedBy=multi-user.target | ||
16 | WantedBy = multi-user.target |
File ingestd/priv.h changed (mode: 100644) (index 9892f29..f84cfca) | |||
... | ... | struct priv { | |
15 | 15 | int dsttime; | int dsttime; |
16 | 16 | } id; | } id; |
17 | 17 | ||
18 | struct utsname uname; | ||
19 | unsigned char pad3[2]; | ||
18 | struct utsname uname; | ||
19 | unsigned char pad3[2]; | ||
20 | 20 | ||
21 | unsigned int sent_ws:1; | ||
22 | unsigned int stop_received:1; | ||
23 | unsigned int pad4:30; | ||
24 | int fd; | ||
25 | unsigned int fd_ts; | ||
26 | unsigned int req_pending; // how many answers we wait from client | ||
21 | unsigned int sent_ws:1; | ||
22 | unsigned int stop_received:1; | ||
23 | unsigned int first_saved:1; | ||
24 | unsigned int pad4:29; | ||
25 | |||
26 | int fd; | ||
27 | unsigned int fd_ts; | ||
28 | unsigned int req_pending; // how many answers we wait from client | ||
29 | unsigned long long last_seen_day; | ||
27 | 30 | }; | }; |
File ingestd/stools.c changed (mode: 100644) (index 89f837f..10c809b) | |||
... | ... | int save_data_check(struct Conn *C, const unsigned char *buf, const unsigned int | |
55 | 55 | ||
56 | 56 | // We do not want to overwrite an existing file | // We do not want to overwrite an existing file |
57 | 57 | do { | do { |
58 | snprintf(path, sizeof(path), "/var/lib/ninedogs/check/%llu-%u-%s-%08x", | ||
58 | snprintf(path, sizeof(path), | ||
59 | "/var/lib/ninedogs/check/%llu-%u-%s-%08x", | ||
59 | 60 | ts, p->id.client_id, p->id.id, rand()); | ts, p->id.client_id, p->id.id, rand()); |
60 | 61 | Log(10, " saving to %s\n", path); | Log(10, " saving to %s\n", path); |
61 | 62 | fd = open(path, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0600); | fd = open(path, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0600); |
... | ... | int save_data(struct Conn *C, const unsigned char *buf, const unsigned int len, | |
97 | 98 | char path[4096], sts[16]; | char path[4096], sts[16]; |
98 | 99 | ||
99 | 100 | snprintf(path, sizeof(path), | snprintf(path, sizeof(path), |
100 | "/var/lib/ninedogs/%02hhx/%02hhx/%08x/data/%c%c/%c%c/%s/t", | ||
101 | "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x" | ||
102 | "/data/%c%c/%c%c/%s/t", | ||
101 | 103 | p->id.client_id, p->id.client_id >> 8, p->id.client_id, | p->id.client_id, p->id.client_id >> 8, p->id.client_id, |
102 | p->id.id[0], p->id.id[1], p->id.id[2], p->id.id[3], p->id.id + 4); | ||
104 | p->id.id[0], p->id.id[1], p->id.id[2], p->id.id[3], | ||
105 | p->id.id); | ||
103 | 106 | mkdir_recursive(path, 0700); | mkdir_recursive(path, 0700); |
104 | 107 | strcat(path, "/"); | strcat(path, "/"); |
105 | 108 | snprintf(sts, sizeof(sts), "%llu", hour); | snprintf(sts, sizeof(sts), "%llu", hour); |
... | ... | int save_data(struct Conn *C, const unsigned char *buf, const unsigned int len, | |
121 | 124 | return 0; | return 0; |
122 | 125 | } | } |
123 | 126 | ||
127 | /* | ||
128 | * Save details about when a machine appeared and when was the last time seen | ||
129 | */ | ||
130 | int save_machine_visibility(struct Conn *C, const unsigned long long ts) | ||
131 | { | ||
132 | struct priv *p = Conn_get_private(C); | ||
133 | struct stat s; | ||
134 | unsigned short off; | ||
135 | int r; | ||
136 | |||
137 | if ((p->id.client_id == 0) || (ts == 0)) | ||
138 | return 0; | ||
139 | |||
140 | Log(10, "%s: client_id=%u ts=%llu\n", | ||
141 | __func__, p->id.client_id, ts); | ||
142 | |||
143 | char dir[4096]; | ||
144 | snprintf(dir, sizeof(dir), | ||
145 | "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x" | ||
146 | "/data/%c%c/%c%c/%s", | ||
147 | p->id.client_id, p->id.client_id >> 8, p->id.client_id, | ||
148 | p->id.id[0], p->id.id[1], p->id.id[2], p->id.id[3], p->id.id); | ||
149 | |||
150 | unsigned char out[64]; | ||
151 | unsigned long long u64 = htobe64(ts); | ||
152 | off = 0; | ||
153 | memcpy(out + off, &u64, 8); off += 8; | ||
154 | |||
155 | r = nd_stat_dir_file(&s, dir, "first_seen"); | ||
156 | if ((p->first_saved == 0) && (r == -1)) { | ||
157 | Log(10, " saving first_seen to %s/first [%llu]\n", dir, ts); | ||
158 | r = save_dir_file(dir, "first_seen", O_CREAT | O_WRONLY | O_TRUNC, out, off); | ||
159 | if (r == -1) | ||
160 | return -1; | ||
161 | p->first_saved = 1; | ||
162 | } | ||
163 | |||
164 | unsigned long long day = get_day(ts / 1000); | ||
165 | if (p->last_seen_day != day) { | ||
166 | Log(10, " saving last_seen %s/last_seen [%llu]\n", dir, ts); | ||
167 | int r = save_dir_file(dir, "last_seen", O_CREAT | O_WRONLY | O_TRUNC, out, off); | ||
168 | if (r == -1) | ||
169 | return -1; | ||
170 | p->last_seen_day = day; | ||
171 | } | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
124 | 176 | int save_app(const char *dst, struct Conn *C, const unsigned long long ts) | int save_app(const char *dst, struct Conn *C, const unsigned long long ts) |
125 | 177 | { | { |
126 | 178 | struct priv *p = Conn_get_private(C); | struct priv *p = Conn_get_private(C); |
... | ... | int save_app(const char *dst, struct Conn *C, const unsigned long long ts) | |
128 | 180 | Log(10, "%s: dst=[%s] client_id=%u ts=%llu\n", | Log(10, "%s: dst=[%s] client_id=%u ts=%llu\n", |
129 | 181 | __func__, dst, p->id.client_id, ts); | __func__, dst, p->id.client_id, ts); |
130 | 182 | ||
131 | char path[4096]; | ||
132 | snprintf(path, sizeof(path), "%s/users/%c%c/%s", | ||
133 | dst, p->id.id[0], p->id.id[1], p->id.id + 2); | ||
134 | mkdir_recursive(path, 0700); | ||
183 | char dir[4096]; | ||
184 | snprintf(dir, sizeof(dir), "%s/users/%c%c/%s", | ||
185 | dst, p->id.id[0], p->id.id[1], p->id.id); | ||
186 | mkdir_recursive(dir, 0700); | ||
135 | 187 | ||
136 | 188 | unsigned char hash[32]; | unsigned char hash[32]; |
137 | 189 | ninedogs_sha256(hash, p->id.cmdline, p->id.cmdline_len); | ninedogs_sha256(hash, p->id.cmdline, p->id.cmdline_len); |
138 | 190 | char shash[9]; | char shash[9]; |
139 | 191 | sprintf(shash, "%08x", *(unsigned int *) hash); | sprintf(shash, "%08x", *(unsigned int *) hash); |
140 | 192 | ||
141 | strcat(path, "/"); | ||
142 | strcat(path, shash); | ||
193 | Log(10, " saving to %s/%s\n", dir, shash); | ||
194 | unsigned char out[4096]; | ||
195 | unsigned short off = 0; | ||
196 | unsigned long long u64 = htobe64(ts); | ||
197 | unsigned short b = htobe16(p->id.cmdline_len); | ||
143 | 198 | ||
144 | Log(10, " saving to %s\n", path); | ||
145 | int fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0600); | ||
146 | if (fd == -1) { | ||
147 | Log(1, " Cannot open [%s]: %m\n", path); | ||
148 | return -1; | ||
149 | } | ||
199 | memcpy(out + off, &u64, 8); off += 8; | ||
200 | memcpy(out + off, &b, 2); off += 2; | ||
201 | memcpy(out + off, p->id.cmdline, p->id.cmdline_len); off += p->id.cmdline_len; | ||
150 | 202 | ||
151 | int r; | ||
152 | unsigned long long u64 = htobe64(ts); | ||
153 | r = save_buf(fd, &u64, 8); | ||
154 | if (r != -1) { | ||
155 | unsigned short b = htobe16(p->id.cmdline_len); | ||
156 | r = save_buf(fd, &b, sizeof(b)); | ||
157 | } | ||
158 | if (r != -1) | ||
159 | r = save_buf(fd, p->id.cmdline, p->id.cmdline_len); | ||
160 | close(fd); | ||
161 | if (r == -1) { | ||
162 | unlink(path); | ||
203 | int r = save_dir_file(dir, shash, O_CREAT | O_WRONLY | O_TRUNC, | ||
204 | out, off); | ||
205 | if (r == -1) | ||
163 | 206 | return -1; | return -1; |
164 | } | ||
165 | 207 | ||
166 | 208 | return 0; | return 0; |
167 | 209 | } | } |
File ingestd/stools.h changed (mode: 100644) (index c5786ab..969ee38) | |||
... | ... | int save_data_check(struct Conn *C, const unsigned char *buf, | |
13 | 13 | int save_data(struct Conn *C, const unsigned char *buf, | int save_data(struct Conn *C, const unsigned char *buf, |
14 | 14 | const unsigned int len, const unsigned long long ts); | const unsigned int len, const unsigned long long ts); |
15 | 15 | ||
16 | int save_app(const char *dst, struct Conn *C, | ||
17 | const unsigned long long ts); | ||
16 | int save_machine_visibility(struct Conn *C, const unsigned long long ts); | ||
17 | |||
18 | int save_app(const char *dst, struct Conn *C, const unsigned long long ts); | ||
18 | 19 |
File misc/Makefile changed (mode: 100644) (index f9044f9..2b09e6c) | |||
1 | # This is just to allow us to run make here | ||
2 | .PHONY: all | ||
3 | all: | ||
4 | make -R -C .. misc | ||
1 | include ../Makefile.common | ||
5 | 2 | ||
6 | 3 | COMMON_H += ../common/shared.h ../common/tools.h ../common/info.h \ | COMMON_H += ../common/shared.h ../common/tools.h ../common/info.h \ |
7 | 4 | ../common/decode_text.h | ../common/decode_text.h |
... | ... | CFLAGS += -I../common | |
10 | 7 | ||
11 | 8 | OBJS := ../common/tools.o ../common/info.o ../common/decode_text.o | OBJS := ../common/tools.o ../common/info.o ../common/decode_text.o |
12 | 9 | ||
10 | all: nd-info | ||
11 | |||
12 | #TODO: Are we using -fPIC for all *.o? | ||
13 | 13 | #decode.o: decode.c decode.h process_db.h $(COMMON_H) | #decode.o: decode.c decode.h process_db.h $(COMMON_H) |
14 | 14 | # $(CC) $(CFLAGS) -fPIC -c -o $@ $< | # $(CC) $(CFLAGS) -fPIC -c -o $@ $< |
15 | 15 | ||
16 | 16 | nd-info: nd-info.c $(COMMON_H) $(OBJS) | nd-info: nd-info.c $(COMMON_H) $(OBJS) |
17 | 17 | $(CC) $(CFLAGS) $@.c -o $@ $(OBJS) $(LIBS) | $(CC) $(CFLAGS) $@.c -o $@ $(OBJS) $(LIBS) |
18 | 18 | ||
19 | compile: nd-info | ||
20 | |||
21 | 19 | .PHONY: clean | .PHONY: clean |
22 | 20 | clean: | clean: |
23 | 21 | @rm -f nd-info *.sinfo *.log *.out *.o | @rm -f nd-info *.sinfo *.log *.out *.o |
File ninedogs.spec changed (mode: 100644) (index e73c08e..cc545ab) | |||
... | ... | Provides: ninedogs | |
14 | 14 | Conflicts: ninedogs | Conflicts: ninedogs |
15 | 15 | ||
16 | 16 | Requires: json-c, gnutls, libcap, catalinux+Conn, nginx-filesystem | Requires: json-c, gnutls, libcap, catalinux+Conn, nginx-filesystem |
17 | Requires: libcurl | ||
17 | 18 | ||
18 | BuildRequires: systemd-rpm-macros, json-c-devel, gnutls-devel, libcap-devel, catalinux+Conn | ||
19 | BuildRequires: systemd-rpm-macros, json-c-devel, gnutls-devel, libcap-devel | ||
20 | BuildRequires: libcurl-devel, catalinux+Conn | ||
19 | 21 | # To generate the pdfs: | # To generate the pdfs: |
20 | BuildRequires: texlive-latex, texlive-beamer, texlive-adjustbox, texlive-babel-english | ||
21 | BuildRequires: texlive-hyperref, texlive-url | ||
22 | BuildRequires: texlive-latex, texlive-beamer, texlive-adjustbox | ||
23 | BuildRequires: texlive-babel-english, texlive-hyperref, texlive-url | ||
24 | # For tests - TODO - postgres | ||
25 | BuildRequires: mysql-connector-java | ||
22 | 26 | ||
23 | 27 | %description | %description |
24 | 28 | Light and fast APM | Light and fast APM |
... | ... | Light and fast APM | |
26 | 30 | %post | %post |
27 | 31 | %systemd_post ninedogs-ingestd.service | %systemd_post ninedogs-ingestd.service |
28 | 32 | %systemd_post ninedogs-webd.service | %systemd_post ninedogs-webd.service |
33 | %systemd_post ninedogs-cert-notify.timer | ||
34 | |||
35 | %pre | ||
36 | getent group ninedogs >/dev/null || groupadd -r ninedogs | ||
37 | getent passwd ninedogs >/dev/null || useradd -r -g ninedogs -s /bin/bash -m -d /home/ninedogs -c "ninedogs user" ninedogs | ||
29 | 38 | ||
30 | 39 | %preun | %preun |
31 | 40 | %systemd_preun ninedogs-ingestd.service | %systemd_preun ninedogs-ingestd.service |
File test/c/oracle/.gitignore copied from file test/info/.gitignore (similarity 100%) |
File test/c/oracle/Dockerfile added (mode: 100644) (index 0000000..0401a3d) | |||
1 | FROM oraclelinux:8 | ||
2 | |||
3 | # TODO: catalinux+ninedogs | ||
4 | |||
5 | RUN echo "1" | ||
6 | RUN dnf -y --setopt=nodocs install oracle-release-el8 oracle-instantclient-release-el8 \ | ||
7 | oracle-epel-release-el8 oraclelinux-release-el8 \ | ||
8 | oraclelinux-developer-release-el8 \ | ||
9 | gcc make \ | ||
10 | https://rocketgit.com/op/pkgrepo/main/global/testing/rocky/8/x86_64/os/rocketgit-global-testing-1.1-1.noarch.rpm \ | ||
11 | \ | ||
12 | && dnf -y install oracle-instantclient-devel | ||
13 | |||
14 | RUN dnf -y update | ||
15 | RUN dnf -y install gnutls-devel json-c-devel libcap-devel catalinux+Conn \ | ||
16 | texlive-latex texlive-beamer texlive-adjustbox texlive-babel-english \ | ||
17 | texlive-hyperref texlive-url | ||
18 | |||
19 | RUN dnf -y install strace gdb gcc-c++ less cscope | ||
20 | |||
21 | RUN mkdir /nd | ||
22 | COPY copy/ /nd/ | ||
23 | RUN cd /nd && ./configure && make common && make agent && make -R -C agent install && make trace && make -R -C trace install |
File test/c/oracle/build.sh added (mode: 100755) (index 0000000..41185a9) | |||
1 | #!/bin/bash | ||
2 | |||
3 | set -u | ||
4 | set -e | ||
5 | |||
6 | mkdir -p copy | ||
7 | rsync -a ../../../ --exclude 'test/' \ | ||
8 | --include 'configure' --include '*.c' --include '*.h' --include 'duilder' --include 'Makefile*' \ | ||
9 | --exclude '*.*' \ | ||
10 | copy | ||
11 | |||
12 | docker="podman" | ||
13 | |||
14 | ${docker} build \ | ||
15 | --tag="ninedogs-c-oracle:latest" \ | ||
16 | . | ||
17 | |||
18 | #rm -rf copy |
File test/c/oracle/demo.c added (mode: 100644) (index 0000000..f4b01c5) | |||
1 | #include <time.h> | ||
2 | |||
3 | #include <stdio.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <string.h> | ||
6 | #include <oci.h> | ||
7 | #include <unistd.h> | ||
8 | |||
9 | /* Define SQL statements to be used in program. */ | ||
10 | static OCIEnv *envhp = NULL; | ||
11 | static OCIError *errhp = NULL; | ||
12 | |||
13 | static void checkerr(/*_ OCIError *errhp, sword status _*/); | ||
14 | static void free_handles(/*svchp, srvhp, authp, stmthp, stmthp1, stmthp2*/); | ||
15 | static void logout_detach_server(/*svchp, srvhp, authp*/); | ||
16 | static sword finish_demo(/*svchp, srvhp, authp, stmthp, stmthp1, stmthp2 */); | ||
17 | static sword status; | ||
18 | static boolean logged_on = FALSE; | ||
19 | |||
20 | int main(int argc, char *argv[]) | ||
21 | { | ||
22 | sword empno, sal, deptno; | ||
23 | sword len, len2, rv, dsize, dsize2; | ||
24 | sb4 deptlen = 14; | ||
25 | sb2 sal_ind, job_ind; | ||
26 | sb2 db_type, db2_type; | ||
27 | sb1 name_buf[20], name2_buf[20]; | ||
28 | text *cp, *dept; | ||
29 | |||
30 | sb2 ind[2]; /* indicator */ | ||
31 | ub2 alen[2]; /* actual length */ | ||
32 | ub2 rlen[2]; /* return length */ | ||
33 | |||
34 | OCIDescribe *dschndl1 = (OCIDescribe *) 0, | ||
35 | *dschndl2 = (OCIDescribe *) 0, | ||
36 | *dschndl3 = (OCIDescribe *) 0; | ||
37 | |||
38 | OCISession *authp = (OCISession *) 0; | ||
39 | OCIServer *srvhp = NULL; | ||
40 | OCISvcCtx *svchp = NULL; | ||
41 | OCIStmt *inserthp = NULL, | ||
42 | *stmthp = NULL, | ||
43 | *stmthp1 = NULL; | ||
44 | OCIDefine *defnp = (OCIDefine *) 0; | ||
45 | |||
46 | OCIBind *bnd1p = (OCIBind *) 0; /* the first bind handle */ | ||
47 | OCIBind *bnd2p = (OCIBind *) 0; /* the second bind handle */ | ||
48 | OCIBind *bnd3p = (OCIBind *) 0; /* the third bind handle */ | ||
49 | OCIBind *bnd4p = (OCIBind *) 0; /* the fourth bind handle */ | ||
50 | OCIBind *bnd5p = (OCIBind *) 0; /* the fifth bind handle */ | ||
51 | OCIBind *bnd6p = (OCIBind *) 0; /* the sixth bind handle */ | ||
52 | |||
53 | sword errcode = 0; | ||
54 | |||
55 | sleep(1); // allow ninedogs to attach | ||
56 | |||
57 | errcode = OCIEnvCreate((OCIEnv **) &envhp, (ub4) OCI_DEFAULT, | ||
58 | (dvoid *) 0, (dvoid * (*)(dvoid *,size_t)) 0, | ||
59 | (dvoid * (*)(dvoid *, dvoid *, size_t)) 0, | ||
60 | (void (*)(dvoid *, dvoid *)) 0, (size_t) 0, (dvoid **) 0); | ||
61 | if (errcode != 0) { | ||
62 | printf("OCIEnvCreate failed with errcode = %d.\n", errcode); | ||
63 | exit(1); | ||
64 | } | ||
65 | |||
66 | (void) OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &errhp, OCI_HTYPE_ERROR, | ||
67 | (size_t) 0, (dvoid **) 0); | ||
68 | |||
69 | /* server contexts */ | ||
70 | (void) OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &srvhp, OCI_HTYPE_SERVER, | ||
71 | (size_t) 0, (dvoid **) 0); | ||
72 | |||
73 | (void) OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &svchp, OCI_HTYPE_SVCCTX, | ||
74 | (size_t) 0, (dvoid **) 0); | ||
75 | |||
76 | checkerr(errhp, OCIServerAttach(srvhp, errhp, (const OraText *) "r1i:61521/XE", 12, 0)); | ||
77 | |||
78 | /* set attribute server context in the service context */ | ||
79 | (void) OCIAttrSet( (dvoid *) svchp, OCI_HTYPE_SVCCTX, (dvoid *)srvhp, | ||
80 | (ub4) 0, OCI_ATTR_SERVER, (OCIError *) errhp); | ||
81 | |||
82 | (void) OCIHandleAlloc((dvoid *) envhp, (dvoid **)&authp, | ||
83 | (ub4) OCI_HTYPE_SESSION, (size_t) 0, (dvoid **) 0); | ||
84 | |||
85 | (void) OCIAttrSet((dvoid *) authp, (ub4) OCI_HTYPE_SESSION, | ||
86 | "system", 6, (ub4) OCI_ATTR_USERNAME, errhp); | ||
87 | |||
88 | (void) OCIAttrSet((dvoid *) authp, (ub4) OCI_HTYPE_SESSION, | ||
89 | "pass", 4, (ub4) OCI_ATTR_PASSWORD, errhp); | ||
90 | |||
91 | checkerr(errhp, OCISessionBegin ( svchp, errhp, authp, OCI_CRED_RDBMS, | ||
92 | (ub4) OCI_DEFAULT)); | ||
93 | |||
94 | (void) OCIAttrSet((dvoid *) svchp, (ub4) OCI_HTYPE_SVCCTX, | ||
95 | (dvoid *) authp, (ub4) 0, | ||
96 | (ub4) OCI_ATTR_SESSION, errhp); | ||
97 | |||
98 | logged_on = TRUE; | ||
99 | |||
100 | |||
101 | checkerr(errhp, OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &stmthp, | ||
102 | OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0)); | ||
103 | |||
104 | |||
105 | // Create the table | ||
106 | char *sql = "CREATE TABLE demo (a int, b varchar(30))"; | ||
107 | OCIStmtPrepare(stmthp, errhp, (const OraText *) sql, strlen(sql), | ||
108 | (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT); | ||
109 | OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1 /*iters*/, (ub4) 0 /*rowoff*/, | ||
110 | (CONST OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_DEFAULT); | ||
111 | |||
112 | |||
113 | // Delete everything from 'demo' table | ||
114 | OCIStmt *del1 = NULL; | ||
115 | checkerr(errhp, OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &del1, OCI_HTYPE_STMT, 0, NULL)); | ||
116 | sql = "DELETE FROM demo"; | ||
117 | checkerr(errhp, OCIStmtPrepare(del1, errhp, (const OraText *) sql, | ||
118 | (ub4) strlen(sql), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); | ||
119 | if ((status = OCIStmtExecute(svchp, del1, errhp, (ub4) 1 /*iters*/, (ub4) 0 /*rowoff*/, | ||
120 | (CONST OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_DEFAULT)) | ||
121 | && (status != 1)) { | ||
122 | checkerr(errhp, status); | ||
123 | finish_demo(svchp, srvhp, authp,stmthp, stmthp1,inserthp); | ||
124 | return OCI_ERROR; | ||
125 | } | ||
126 | |||
127 | |||
128 | // insert | ||
129 | int a = 1, c = 0xcc; | ||
130 | char b[128]; | ||
131 | checkerr(errhp, OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &inserthp, | ||
132 | OCI_HTYPE_STMT, 0, NULL)); | ||
133 | sql = "INSERT INTO demo(a, b) VALUES (:a + 1, :b) RETURNING a INTO :c"; | ||
134 | checkerr(errhp, OCIStmtPrepare(inserthp, errhp, (const OraText *) sql, | ||
135 | (ub4) strlen(sql), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); | ||
136 | /* Bind the placeholders in the INSERT statement. */ | ||
137 | snprintf(b, sizeof(b), "b=%ld", time(NULL)); | ||
138 | printf("&a=%p &b=%p &c=%p\n", &a, &b, &c); | ||
139 | if ( | ||
140 | (status = OCIBindByName(inserthp, &bnd1p, errhp, (text *) ":a", | ||
141 | -1, (dvoid *) &a, sizeof(a), SQLT_INT, (dvoid *) 0, | ||
142 | (ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)) || | ||
143 | (status = OCIBindByName(inserthp, &bnd2p, errhp, (text *) ":b", | ||
144 | -1, (dvoid *) b, strlen(b) + 1, SQLT_STR, (dvoid *) 0, | ||
145 | (ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)) || | ||
146 | (status = OCIBindByName(inserthp, &bnd3p, errhp, (text *) ":c", | ||
147 | -1, (dvoid *) &c, sizeof(c), SQLT_INT, (dvoid *) 0, | ||
148 | (ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)) | ||
149 | ) { | ||
150 | checkerr(errhp, status); | ||
151 | finish_demo(svchp, srvhp, authp,stmthp, stmthp1,inserthp); | ||
152 | return OCI_ERROR; | ||
153 | } | ||
154 | if ((status = OCIStmtExecute(svchp, inserthp, errhp, (ub4) 1 /*iters*/, (ub4) 0 /*rowoff*/, | ||
155 | (CONST OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_DEFAULT)) | ||
156 | && (status != 1)) { | ||
157 | checkerr(errhp, status); | ||
158 | finish_demo(svchp, srvhp, authp,stmthp, stmthp1,inserthp); | ||
159 | return OCI_ERROR; | ||
160 | } | ||
161 | |||
162 | |||
163 | OCIStmt *sel1 = NULL; | ||
164 | char s1[256], n1[16], o1[2]; | ||
165 | sb2 ind1d, ind1s1, ind1n1, ind1o1, ind1e, ind1num; | ||
166 | ub2 rlen1d, rcode1d; | ||
167 | ub2 rlen1s1, rcode1s1; | ||
168 | ub2 rlen1n1, rcode1n1; | ||
169 | ub2 rlen1o1, rcode1o1; | ||
170 | ub2 rlen1e, rcode1e; | ||
171 | ub2 rlen1num, rcode1num; | ||
172 | int d; | ||
173 | char e[32]; | ||
174 | unsigned char num[21]; // this is an internal representation: https://docs.oracle.com/cd/A58617_01/server.804/a58234/datatype.htm | ||
175 | OCIDefine *para_d = NULL, *para_s1 = NULL, *para_n1 = NULL, *para_o1 = NULL, *para_e = NULL, *para_num = NULL; | ||
176 | checkerr(errhp, OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &sel1, | ||
177 | OCI_HTYPE_STMT, 0, NULL)); | ||
178 | sql = "SELECT demo.a, demo.b, NULL AS bla, demo.b AS overflow1, demo.a AS long1, demo.a AS num1 FROM demo"; | ||
179 | checkerr(errhp, OCIStmtPrepare(sel1, errhp, (const OraText *) sql, | ||
180 | (ub4) strlen(sql), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); | ||
181 | if ((status = OCIDefineByPos(sel1, ¶_d, errhp, 1 /*pos*/, | ||
182 | (dvoid *) &d, (sword) sizeof(d), SQLT_INT, | ||
183 | (dvoid *) &ind1d, &rlen1d, &rcode1d, OCI_DEFAULT /*mode*/))) { | ||
184 | checkerr(errhp, status); | ||
185 | finish_demo(svchp, srvhp, authp,stmthp, stmthp1,inserthp); | ||
186 | return OCI_ERROR; | ||
187 | } | ||
188 | if ((status = OCIDefineByPos(sel1, ¶_s1, errhp, 2 /*pos*/, | ||
189 | (dvoid *) &s1, (sword) sizeof(s1), SQLT_STR, | ||
190 | (dvoid *) &ind1s1, (ub2 *) &rlen1s1, &rcode1s1, | ||
191 | OCI_DEFAULT /*mode*/))) { | ||
192 | checkerr(errhp, status); | ||
193 | finish_demo(svchp, srvhp, authp,stmthp, stmthp1,inserthp); | ||
194 | return OCI_ERROR; | ||
195 | } | ||
196 | if ((status = OCIDefineByPos(sel1, ¶_n1, errhp, 3 /*pos*/, | ||
197 | (dvoid *) &n1, (sword) sizeof(n1), SQLT_STR, | ||
198 | (dvoid *) &ind1n1, (ub2 *) &rlen1n1, &rcode1n1, | ||
199 | OCI_DEFAULT /*mode*/))) { | ||
200 | checkerr(errhp, status); | ||
201 | finish_demo(svchp, srvhp, authp,stmthp, stmthp1,inserthp); | ||
202 | return OCI_ERROR; | ||
203 | } | ||
204 | if ((status = OCIDefineByPos(sel1, ¶_o1, errhp, 4 /*pos*/, | ||
205 | (dvoid *) &o1, (sword) sizeof(o1), SQLT_STR, | ||
206 | (dvoid *) &ind1o1, (ub2 *) &rlen1o1, &rcode1o1, | ||
207 | OCI_DEFAULT /*mode*/))) { | ||
208 | checkerr(errhp, status); | ||
209 | finish_demo(svchp, srvhp, authp,stmthp, stmthp1,inserthp); | ||
210 | return OCI_ERROR; | ||
211 | } | ||
212 | if ((status = OCIDefineByPos(sel1, ¶_e, errhp, 5 /*pos*/, | ||
213 | (dvoid *) &e, (sword) sizeof(e), SQLT_LNG, | ||
214 | (dvoid *) &ind1e, (ub2 *) &rlen1e, &rcode1e, | ||
215 | OCI_DEFAULT /*mode*/))) { | ||
216 | checkerr(errhp, status); | ||
217 | finish_demo(svchp, srvhp, authp,stmthp, stmthp1,inserthp); | ||
218 | return OCI_ERROR; | ||
219 | } | ||
220 | if ((status = OCIDefineByPos(sel1, ¶_num, errhp, 6 /*pos*/, | ||
221 | (dvoid *) &num, (sword) sizeof(num), SQLT_NUM, | ||
222 | (dvoid *) &ind1num, (ub2 *) &rlen1num, &rcode1num, | ||
223 | OCI_DEFAULT /*mode*/))) { | ||
224 | checkerr(errhp, status); | ||
225 | finish_demo(svchp, srvhp, authp,stmthp, stmthp1,inserthp); | ||
226 | return OCI_ERROR; | ||
227 | } | ||
228 | if ((status = OCIStmtExecute(svchp, sel1, errhp, (ub4) 1 /*iters*/, (ub4) 0 /*rowoff*/, | ||
229 | (CONST OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_DEFAULT)) | ||
230 | && (status != 1)) { | ||
231 | checkerr(errhp, status); | ||
232 | finish_demo(svchp, srvhp, authp,stmthp, stmthp1,inserthp); | ||
233 | return OCI_ERROR; | ||
234 | } | ||
235 | printf("d: ind1=%hd rlen1=%hu rcode1=%hu\n", ind1d, rlen1d, rcode1d); | ||
236 | printf("s1: ind1=%hd rlen1=%hu rcode1=%hu\n", ind1s1, rlen1s1, rcode1s1); | ||
237 | printf("n1: ind1=%hd rlen1=%hu rcode1=%hu\n", ind1n1, rlen1n1, rcode1n1); | ||
238 | printf("o1: ind1=%hd rlen1=%hu rcode1=%hu\n", ind1o1, rlen1o1, rcode1o1); | ||
239 | printf("e: ind1=%hd rlen1=%hu rcode1=%hu\n", ind1e, rlen1e, rcode1e); | ||
240 | printf("num: ind1=%hd rlen1=%hu rcode1=%hu\n", ind1num, rlen1num, rcode1num); | ||
241 | printf("d=%d s1=[%s] o1=[%s] e=[%s] num=[%s]\n", d, s1, o1, e, num); | ||
242 | |||
243 | /* Commit the change. */ | ||
244 | if (status = OCITransCommit(svchp, errhp, OCI_TRANS_WRITEIMMED)) { | ||
245 | checkerr(errhp, status); | ||
246 | finish_demo(svchp, srvhp, authp,stmthp, stmthp1,inserthp); | ||
247 | return OCI_ERROR; | ||
248 | } | ||
249 | |||
250 | OCITransRollback(svchp, errhp, OCI_DEFAULT); | ||
251 | } | ||
252 | |||
253 | |||
254 | void checkerr(OCIError *errhp, sword status) | ||
255 | { | ||
256 | text errbuf[512]; | ||
257 | sb4 errcode = 0; | ||
258 | |||
259 | switch (status) | ||
260 | { | ||
261 | case OCI_SUCCESS: | ||
262 | break; | ||
263 | case OCI_SUCCESS_WITH_INFO: | ||
264 | (void) printf("Error - OCI_SUCCESS_WITH_INFO\n"); | ||
265 | break; | ||
266 | case OCI_NEED_DATA: | ||
267 | (void) printf("Error - OCI_NEED_DATA\n"); | ||
268 | break; | ||
269 | case OCI_NO_DATA: | ||
270 | (void) printf("Error - OCI_NODATA\n"); | ||
271 | break; | ||
272 | case OCI_ERROR: | ||
273 | (void) OCIErrorGet((dvoid *)errhp, (ub4) 1, (text *) NULL, &errcode, | ||
274 | errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR); | ||
275 | (void) printf("Error - %.*s\n", 512, errbuf); | ||
276 | break; | ||
277 | case OCI_INVALID_HANDLE: | ||
278 | (void) printf("Error - OCI_INVALID_HANDLE\n"); | ||
279 | break; | ||
280 | case OCI_STILL_EXECUTING: | ||
281 | (void) printf("Error - OCI_STILL_EXECUTE\n"); | ||
282 | break; | ||
283 | case OCI_CONTINUE: | ||
284 | (void) printf("Error - OCI_CONTINUE\n"); | ||
285 | break; | ||
286 | default: | ||
287 | break; | ||
288 | } | ||
289 | } | ||
290 | |||
291 | /* ----------------------------------------------------------------- */ | ||
292 | /* Free the specified handles */ | ||
293 | /* ----------------------------------------------------------------- */ | ||
294 | void free_handles(svchp, srvhp, authp, stmthp, stmthp1, stmthp2) | ||
295 | OCISvcCtx *svchp; | ||
296 | OCIServer *srvhp; | ||
297 | OCISession *authp; | ||
298 | OCIStmt *stmthp; | ||
299 | OCIStmt *stmthp1; | ||
300 | OCIStmt *stmthp2; | ||
301 | { | ||
302 | if (srvhp) | ||
303 | (void) OCIHandleFree((dvoid *) srvhp, (ub4) OCI_HTYPE_SERVER); | ||
304 | if (svchp) | ||
305 | (void) OCIHandleFree((dvoid *) svchp, (ub4) OCI_HTYPE_SVCCTX); | ||
306 | if (errhp) | ||
307 | (void) OCIHandleFree((dvoid *) errhp, (ub4) OCI_HTYPE_ERROR); | ||
308 | if (authp) | ||
309 | (void) OCIHandleFree((dvoid *) authp, (ub4) OCI_HTYPE_SESSION); | ||
310 | if (stmthp) | ||
311 | (void) OCIHandleFree((dvoid *) stmthp, (ub4) OCI_HTYPE_STMT); | ||
312 | if (stmthp1) | ||
313 | (void) OCIHandleFree((dvoid *) stmthp1, (ub4) OCI_HTYPE_STMT); | ||
314 | if (stmthp2) | ||
315 | (void) OCIHandleFree((dvoid *) stmthp2, (ub4) OCI_HTYPE_STMT); | ||
316 | |||
317 | if (envhp) | ||
318 | (void) OCIHandleFree((dvoid *) envhp, (ub4) OCI_HTYPE_ENV); | ||
319 | |||
320 | return; | ||
321 | } | ||
322 | |||
323 | /*-------------------------------------------------------------------*/ | ||
324 | /* Logout and detach from the server */ | ||
325 | /*-------------------------------------------------------------------*/ | ||
326 | void logout_detach_server(svchp, srvhp, authp) | ||
327 | OCISvcCtx *svchp; | ||
328 | OCIServer *srvhp; | ||
329 | OCISession *authp; | ||
330 | { | ||
331 | if ((status = OCISessionEnd(svchp, errhp, authp, (ub4) 0))) | ||
332 | { | ||
333 | printf("FAILED: OCISessionEnd()\n"); | ||
334 | checkerr(errhp, status); | ||
335 | } | ||
336 | |||
337 | if ((status = OCIServerDetach(srvhp, errhp, (ub4) OCI_DEFAULT))) | ||
338 | { | ||
339 | printf("FAILED: OCIServerDetach()\n"); | ||
340 | checkerr(errhp, status); | ||
341 | } | ||
342 | |||
343 | return; | ||
344 | } | ||
345 | |||
346 | /*---------------------------------------------------------------------*/ | ||
347 | /* Finish demo and clean up */ | ||
348 | /*---------------------------------------------------------------------*/ | ||
349 | sword finish_demo(svchp, srvhp, authp, stmthp, stmthp1, stmthp2) | ||
350 | OCISvcCtx *svchp; | ||
351 | OCIServer *srvhp; | ||
352 | OCISession *authp; | ||
353 | OCIStmt *stmthp; | ||
354 | OCIStmt *stmthp1; | ||
355 | OCIStmt *stmthp2; | ||
356 | { | ||
357 | |||
358 | if (logged_on) | ||
359 | logout_detach_server(svchp, srvhp, authp); | ||
360 | |||
361 | free_handles(svchp, srvhp, authp, stmthp, stmthp1, stmthp2); | ||
362 | |||
363 | OCITerminate(OCI_DEFAULT); | ||
364 | |||
365 | return OCI_SUCCESS; | ||
366 | } | ||
367 | |||
368 | /* end of file cdemo81.c */ | ||
369 |
File test/c/oracle/exec-dev-1.sh added (mode: 100755) (index 0000000..64de4e6) | |||
1 | podman run -ti \ | ||
2 | -v ${PWD}/1:/1 \ | ||
3 | -v ${PWD}/demo.c:/usr/share/oracle/21/client64/demo/demo.c \ | ||
4 | --rm \ | ||
5 | --namespace nd-test \ | ||
6 | ninedogs-c-oracle:latest \ | ||
7 | /1 2>&1 | tee exec-dev-1.out | ||
8 | |||
9 |
File test/c/oracle/exec-dev-bash.sh added (mode: 100755) (index 0000000..c77947b) | |||
1 | # -v ${PWD}/1.php:/1.php \ | ||
2 | |||
3 | podman run -ti \ | ||
4 | -v ${PWD}/1:/1 \ | ||
5 | --rm \ | ||
6 | --namespace nd-test \ | ||
7 | ninedogs-c-oracle:latest \ | ||
8 | bash | ||
9 | |||
10 |
File test/curl/1.c changed (mode: 100644) (index fd48740..5abb80c) | |||
... | ... | int main(void) | |
15 | 15 | ||
16 | 16 | struct curl_slist *list = NULL; | struct curl_slist *list = NULL; |
17 | 17 | list = curl_slist_append(list, "Content-Type: application/json"); | list = curl_slist_append(list, "Content-Type: application/json"); |
18 | list = curl_slist_append(list, "X-ninedogs-bla: 1🐱"); | ||
18 | list = curl_slist_append(list, "X-ninedogs-bla: 1🐱end"); | ||
19 | 19 | ||
20 | 20 | ||
21 | 21 | CURL *curl = curl_easy_init(); | CURL *curl = curl_easy_init(); |
22 | usleep(1000 * 1000); | ||
22 | 23 | curl_easy_setopt(curl, CURLOPT_URL, "https://localhost"); | curl_easy_setopt(curl, CURLOPT_URL, "https://localhost"); |
24 | usleep(500 * 1000); | ||
23 | 25 | curl_easy_setopt(curl, CURLOPT_POST, 1); | curl_easy_setopt(curl, CURLOPT_POST, 1); |
24 | 26 | curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body); | curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body); |
27 | usleep(500 * 1000); | ||
25 | 28 | curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body_len); | curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body_len); |
29 | usleep(200 * 1000); | ||
26 | 30 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); |
27 | 31 | curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); | curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); |
32 | curl_easy_setopt(curl, 0xffffff01, 1); // invalid option | ||
28 | 33 | CURLcode res = curl_easy_perform(curl); | CURLcode res = curl_easy_perform(curl); |
29 | 34 | ||
35 | usleep(2000 * 1000); | ||
30 | 36 | curl_slist_free_all(list); | curl_slist_free_all(list); |
31 | 37 | ||
32 | 38 | curl_easy_cleanup(curl); | curl_easy_cleanup(curl); |
File test/curl/1.run changed (mode: 100755) (index 2a51e0d..87e17d8) | |||
... | ... | export NINEDOGS_VERBOSE=200 | |
12 | 12 | #export LD_DEBUG_OUTPUT=1.ld.txt | #export LD_DEBUG_OUTPUT=1.ld.txt |
13 | 13 | ||
14 | 14 | ./1 &>1.out & | ./1 &>1.out & |
15 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1.nd -p ${!} | ||
15 | #LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace --only-high-level -o 1.nd -p ${!} | ||
16 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace --only-high-level -p ${!} | ||
17 | #LD_PRELOAD= LD_DEBUG= gdb ../../trace/nd-trace | ||
16 | 18 |
File test/curl/3.php changed (mode: 100644) (index 83df484..00bc6bc) | |||
... | ... | if (curl_error($c)) | |
17 | 17 | ||
18 | 18 | curl_close($c); | curl_close($c); |
19 | 19 | ||
20 | fclose($fp); | ||
21 |
File test/curl/3.run changed (mode: 100755) (index 5672b31..ce59fb5) | |||
... | ... | export NINEDOGS_VERBOSE=201 | |
10 | 10 | #export LD_DEBUG_OUTPUT=1.ld.txt | #export LD_DEBUG_OUTPUT=1.ld.txt |
11 | 11 | ||
12 | 12 | php 3.php &>3.out & | php 3.php &>3.out & |
13 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 3.nd -p ${!} | ||
13 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace --only-high-level -o 3.nd -p ${!} | ||
14 | 14 |
File test/go/.gitignore copied from file test/info/.gitignore (similarity 100%) |
File test/go/1.go added (mode: 100644) (index 0000000..b9c65fe) | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "crypto/sha256" | ||
5 | "fmt" | ||
6 | "time" | ||
7 | ) | ||
8 | |||
9 | func main() { | ||
10 | time.Sleep(2 * time.Second); | ||
11 | |||
12 | s := "sha256 this string" | ||
13 | |||
14 | h := sha256.New() | ||
15 | |||
16 | h.Write([]byte(s)) | ||
17 | |||
18 | bs := h.Sum(nil) | ||
19 | |||
20 | fmt.Println(s) | ||
21 | fmt.Printf("%x\n", bs) | ||
22 | } | ||
23 |
File test/go/1.run copied from file test/curl/1.run (similarity 91%) (mode: 100755) (index 2a51e0d..6eb618c) | |||
2 | 2 | ||
3 | 3 | set -e | set -e |
4 | 4 | ||
5 | gcc 1.c -o 1 -l curl | ||
5 | go build 1.go | ||
6 | 6 | ||
7 | 7 | export LD_PRELOAD=../../agent/ninedogs.so | export LD_PRELOAD=../../agent/ninedogs.so |
8 | 8 |
File test/go/TODO added (mode: 100644) (index 0000000..5b81e81) | |||
1 | [ ] Find a way to do the tracing. Right now, go programs are | ||
2 | statically linked. :( | ||
3 | [ ] |
File test/info/.gitignore changed (mode: 100644) (index d00491f..f122112) | |||
1 | 1 | 1 | 1 |
2 | *.info |
File test/info/1.c changed (mode: 100644) (index 36757bd..777fd91) | |||
7 | 7 | #include <arpa/inet.h> | #include <arpa/inet.h> |
8 | 8 | #include <fcntl.h> | #include <fcntl.h> |
9 | 9 | #include <stdio.h> | #include <stdio.h> |
10 | #include <stdlib.h> | ||
10 | 11 | #include <string.h> | #include <string.h> |
11 | 12 | #include <unistd.h> | #include <unistd.h> |
12 | 13 | ||
... | ... | int main(void) | |
92 | 93 | ||
93 | 94 | ||
94 | 95 | // memfd | // memfd |
95 | int mfd = memfd_create("bla", MFD_HUGETLB); | ||
96 | int mfd = memfd_create("bla", MFD_CLOEXEC | MFD_ALLOW_SEALING); | ||
97 | if (mfd == -1) | ||
98 | printf("cannot create memfd: %m\n"); | ||
99 | r = ftruncate(mfd, 200); | ||
100 | if (r == -1) | ||
101 | printf("cannot truncate memfd: %m\n"); | ||
96 | 102 | write(mfd, "3456", 4); | write(mfd, "3456", 4); |
97 | 103 | ||
98 | 104 | ||
... | ... | int main(void) | |
100 | 106 | int tfd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK); | int tfd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK); |
101 | 107 | printf("tfd = %d: %m\n", tfd); | printf("tfd = %d: %m\n", tfd); |
102 | 108 | ||
103 | |||
109 | system("ls -l /proc/self/fd"); | ||
104 | 110 | sleep(2); | sleep(2); |
105 | 111 | ||
106 | 112 | return 0; | return 0; |
File test/info/1.run changed (mode: 100755) (index dbe9497..10b7304) | |||
... | ... | export NINEDOGS_VERBOSE=200 | |
13 | 13 | ||
14 | 14 | ./1 &>1.out & | ./1 &>1.out & |
15 | 15 | LD_PRELOAD= LD_DEBUG= sleep 1 | LD_PRELOAD= LD_DEBUG= sleep 1 |
16 | LD_PRELOAD= LD_DEBUG= strace -s2000 -tt -q -o 1.nd_info.strace ../../misc/nd-info -p ${!} | ||
16 | #LD_PRELOAD= LD_DEBUG= strace -s2000 -tt -q -o 1.nd_info.strace ../../misc/nd-info -p ${!} | ||
17 | LD_PRELOAD= LD_DEBUG= ../../misc/nd-info -p ${!} &>1.info | ||
17 | 18 |
File test/java/mysql/my1.java added (mode: 100644) (index 0000000..b72d820) | |||
1 | import java.sql.Connection; | ||
2 | import java.sql.DriverManager; | ||
3 | import java.sql.PreparedStatement; | ||
4 | import java.sql.Statement; | ||
5 | import java.sql.ResultSet; | ||
6 | import java.sql.SQLException; | ||
7 | |||
8 | public class my1 { | ||
9 | public static void main(String args[]) { | ||
10 | try { | ||
11 | System.err.println("Starting..."); | ||
12 | //Class.forName("com.mysql.jdbc.Driver"); | ||
13 | |||
14 | System.err.println(""); | ||
15 | System.err.println("getConnection..."); | ||
16 | Connection con = DriverManager | ||
17 | .getConnection("jdbc:mysql://localhost/ninedogs", | ||
18 | "ninedogs", "pass"); | ||
19 | System.err.println("Opened database successfully con=" + con); | ||
20 | |||
21 | System.err.println(""); | ||
22 | System.err.println("Query (prepared) [PreparedStatement ps = con.prepareStatement(SELECT ? AS id, ? AS str1)]..."); | ||
23 | PreparedStatement ps = con.prepareStatement("SELECT ? AS id, ? AS str1"); | ||
24 | System.err.println("Prepared statement: " + ps); | ||
25 | |||
26 | System.err.println(""); | ||
27 | System.err.println("Binding para 1 [ps.setInt(1, 12345)]..."); | ||
28 | ps.setInt(1, 12345); | ||
29 | |||
30 | System.err.println(""); | ||
31 | System.err.println("Binding para 2 [ps.setString(2, \"abc\")]..."); | ||
32 | ps.setString(2, "abc"); | ||
33 | |||
34 | System.err.println(""); | ||
35 | System.err.println("Binding invalid para 100 [ps.setInt(100, 111)]..."); | ||
36 | try { ps.setInt(100, 111); } catch (Exception e) { System.err.println("EXEC: " + e); } | ||
37 | |||
38 | System.err.println(""); | ||
39 | System.err.println("Executing prepared query [ResultSet rs1 = ps.executeQuery()]..."); | ||
40 | ResultSet rs1 = ps.executeQuery(); | ||
41 | System.err.println("Executing prepared query... done rs1=" + rs1); | ||
42 | |||
43 | System.err.println(""); | ||
44 | System.err.println("Looping [rs1.next()]..."); | ||
45 | while (rs1.next()) { | ||
46 | int id = rs1.getInt("id"); | ||
47 | System.err.println(" id=" + id); | ||
48 | } | ||
49 | |||
50 | System.err.println(""); | ||
51 | System.err.println("Closing prepared statement [ps.close()]..."); | ||
52 | ps.close(); | ||
53 | |||
54 | |||
55 | System.err.println(""); | ||
56 | System.err.println("Creating statement [Statement stmt = con.createStatement()] (link con with stmt)..."); | ||
57 | Statement stmt = con.createStatement(); | ||
58 | |||
59 | System.err.println(""); | ||
60 | System.err.println("Query (normal)... [ResultSet rs2 = stmt.executeQuery('SELECT ...')]"); | ||
61 | ResultSet rs2 = stmt.executeQuery("SELECT * FROM n1 LIMIT 2"); | ||
62 | System.err.println("Query (normal) done rs2=" + rs2); | ||
63 | |||
64 | System.err.println(""); | ||
65 | System.err.println("Looping [rs2.next()]..."); | ||
66 | while (rs2.next()) { | ||
67 | int id = rs2.getInt("id"); | ||
68 | System.err.println(" id=" + id); | ||
69 | } | ||
70 | |||
71 | System.err.println(""); | ||
72 | System.err.println("Closing statement [stmt.close()]..."); | ||
73 | stmt.close(); | ||
74 | |||
75 | System.err.println(""); System.err.println("Closing connection [con.close()]..."); | ||
76 | con.close(); | ||
77 | System.err.println("Done"); | ||
78 | } catch (Exception e) { | ||
79 | e.printStackTrace(); | ||
80 | System.err.println(e.getClass().getName()+": " + e.getMessage()); | ||
81 | System.exit(0); | ||
82 | } | ||
83 | |||
84 | } | ||
85 | } |
File test/java/mysql/my1.jdb.run added (mode: 100755) (index 0000000..ab7ed1c) | |||
1 | #!/bin/bash | ||
2 | |||
3 | set -e | ||
4 | |||
5 | if [ my1.class -ot my1.java ]; then | ||
6 | echo "Compiling..." | ||
7 | javac my1.java | ||
8 | fi | ||
9 | |||
10 | # -Xdiag \ | ||
11 | # -verbose:class \ | ||
12 | #strace -s2000 -tt -f -o my1.tmp.strace \ | ||
13 | jdb \ | ||
14 | -classpath /usr/share/java/postgresql-jdbc.jar:. my1 | ||
15 |
File test/java/mysql/my1.run added (mode: 100755) (index 0000000..bc40d1d) | |||
1 | #!/bin/bash | ||
2 | |||
3 | set -e | ||
4 | |||
5 | if [ my1.class -ot my1.java ]; then | ||
6 | echo "Compiling..." | ||
7 | javac my1.java | ||
8 | fi | ||
9 | |||
10 | # We need postgreql-jdbc package | ||
11 | |||
12 | export LD_PRELOAD=../../../agent/ninedogs.so | ||
13 | |||
14 | export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro | ||
15 | export NINEDOGS_SERVER_PORT=36000 | ||
16 | export NINEDOGS_ID=ba446a981b387e831db3f6a730c55552 | ||
17 | export NINEDOGS_VERBOSE=11 | ||
18 | export NINEDOGS_SYNC_FLUSH=1 | ||
19 | |||
20 | #export LD_DEBUG=all | ||
21 | #export LD_DEBUG_OUTPUT=1.ld.txt | ||
22 | |||
23 | #strace -tt -f -s2000 -o my1.strace \ | ||
24 | #ltrace -s200 -f -tt -S -o my1.ltrace \ | ||
25 | #java -cp /usr/share/java/postgresql-jdbc.jar:. my1 | ||
26 | |||
27 | |||
28 | # -javaagent:../../agent/java/agent/ninedogs-agent.jar \ | ||
29 | # -Xdiag \ | ||
30 | #strace -s20000 -tt -f -e\!mprotect,gettid -o my1.strace \ | ||
31 | java \ | ||
32 | -cp /usr/share/java/mysql-connector-java.jar:. my1 &>my1.out & | ||
33 | |||
34 | echo "Runing trace..." | ||
35 | LD_PRELOAD= LD_DEBUG= ../../../trace/nd-trace --only-high-level -o my1.nd -p ${!} | ||
36 |
File test/java/oracle/TODO added (mode: 100644) (index 0000000..2861835) | |||
1 | [ ] Add DataSource mode to connect to db. Also for rest of the db types. | ||
2 | [ ] |
File test/java/oracle/sqlplus-XE.sh added (mode: 100755) (index 0000000..dff9586) | |||
1 | #!/bin/bash | ||
2 | |||
3 | podman exec -it nd-java-oracle sqlplus -F system/pass@XE | ||
4 |
File test/java/oracle/sqlplus.sh added (mode: 100755) (index 0000000..5360638) | |||
1 | #!/bin/bash | ||
2 | |||
3 | podman exec -it nd-java-oracle sqlplus -S -F system/pass@XEPDB1 | ||
4 |
File test/java/oracle/start_oracle.sh added (mode: 100755) (index 0000000..3c68905) | |||
1 | #!/bin/bash | ||
2 | |||
3 | set -e | ||
4 | |||
5 | if [ ! -r ojdbc11.jar ]; then | ||
6 | wget https://download.oracle.com/otn-pub/otn_software/jdbc/218/ojdbc11.jar | ||
7 | fi | ||
8 | |||
9 | url="container-registry.oracle.com/database/express:21.3.0-xe" | ||
10 | podman pull ${url} || : | ||
11 | podman stop -t0 nd-java-oracle 2>/dev/null || : | ||
12 | podman rm nd-java-oracle &>/dev/null || : | ||
13 | podman run --rm -d \ | ||
14 | --name nd-java-oracle \ | ||
15 | -p 61521:1521 -p 65500:5500 \ | ||
16 | -e ORACLE_PWD=pass \ | ||
17 | -e ORACLE_CHARACTERSET=AL32UTF8 \ | ||
18 | ${url} || : | ||
19 | echo -n "Waiting for db to start..." | ||
20 | while [ 1 ]; do | ||
21 | echo -n "." | ||
22 | ./test-conn.sh <<-EOF &>/dev/null | ||
23 | SELECT 1 FROM dual; | ||
24 | EXIT; | ||
25 | / | ||
26 | EOF | ||
27 | if [ "${?}" = "0" ]; then | ||
28 | break | ||
29 | fi | ||
30 | sleep 3 | ||
31 | done | ||
32 | echo |
File test/java/oracle/t1.java added (mode: 100644) (index 0000000..d914b51) | |||
1 | import java.sql.*; | ||
2 | import java.util.Properties; | ||
3 | |||
4 | class t1 | ||
5 | { | ||
6 | public static void main(String args[]) | ||
7 | { | ||
8 | try { | ||
9 | Class.forName("oracle.jdbc.driver.OracleDriver"); | ||
10 | |||
11 | System.out.println(""); System.out.println("Creating connection..."); | ||
12 | Connection con = DriverManager.getConnection( | ||
13 | "jdbc:oracle:thin:@localhost:61521:XE", "system", "pass"); | ||
14 | System.out.println("Creating connection... done con=" + con); | ||
15 | |||
16 | System.out.println(""); System.out.println("Setting autocommit to false..."); | ||
17 | con.setAutoCommit(false); | ||
18 | |||
19 | System.out.println(""); System.out.println("Creating statement [Statement stmt = con.createStatement()] con=" + con + "..."); | ||
20 | Statement stmt = con.createStatement(); | ||
21 | System.out.println("Creating statement [Statement stmt = con.createStatement()] stmt=" + stmt); | ||
22 | |||
23 | System.out.println(""); System.out.println("Executing query [ResultSet rs = stmt.executeQuery(\"select 123456789 from dual\")]..."); | ||
24 | ResultSet rs = stmt.executeQuery("select 123456789 from dual"); | ||
25 | System.out.println("Executing query... done rs=" + rs); | ||
26 | |||
27 | System.out.println(""); | ||
28 | System.out.println("Looping ResultSet rs=" + rs); | ||
29 | while (rs.next()) | ||
30 | System.out.println("ZZZZZZZZZZZZZZZ: " + rs.getInt(1)); | ||
31 | |||
32 | System.out.println(""); | ||
33 | System.out.println("Closing statement stmt=" + stmt + " [stmt.close()]..."); | ||
34 | stmt.close(); | ||
35 | System.out.println("Closing statement stmt=" + stmt + "... done"); | ||
36 | |||
37 | |||
38 | // prepared statement | ||
39 | System.out.println(""); | ||
40 | System.out.println("Creating prepared statement [PreparedStatement p1 = con.prepareStatement(\"SELECT ? AS F1, ? AS F2 FROM dual\")]..."); | ||
41 | PreparedStatement p1 = con.prepareStatement("SELECT ? AS F1, ? AS F2 FROM dual"); | ||
42 | System.out.println("Creating prepared statement... done p1=" + p1); | ||
43 | |||
44 | System.out.println(""); | ||
45 | System.out.println("Binding parameters [p1.setInt(1, 12345)]..."); | ||
46 | p1.setInt(1, 12345); | ||
47 | |||
48 | System.out.println(""); | ||
49 | System.out.println("Binding parameters [p1.setInt(2, \"abcde\")]..."); | ||
50 | p1.setString(2, "abcde"); | ||
51 | |||
52 | System.err.println(""); | ||
53 | System.err.println("Binding invalid para 100 [ps.setInt(100, 111)]..."); | ||
54 | try { p1.setInt(100, 111); } catch (Exception e) { System.err.println("EXEC: " + e); } | ||
55 | |||
56 | System.out.println(""); | ||
57 | System.out.println("Executing prepared [p1.execute()] p1=" + p1 + "..."); | ||
58 | p1.execute(); | ||
59 | System.out.println("Executing prepared... done"); | ||
60 | |||
61 | |||
62 | // Seems this is specific to Oracle | ||
63 | System.out.println(""); | ||
64 | System.out.println("Getting result set [ResultSet rs2 = p1.getResultSet()] (p1=" + p1 + ")..."); | ||
65 | ResultSet rs2 = p1.getResultSet(); | ||
66 | System.out.println("Getting result set... done rs2=" + rs2); | ||
67 | |||
68 | System.out.println(""); | ||
69 | System.out.println("Looping (rs2=" + rs2 + ")..."); | ||
70 | while (rs2.next()) { | ||
71 | float f1 = rs2.getFloat("F1"); | ||
72 | String f2 = rs2.getString("F2"); | ||
73 | System.out.println("f1=" + f1 + " f2=" + f2); | ||
74 | } | ||
75 | |||
76 | System.out.println(""); System.out.println("Closing p1=" + p1 + "..."); | ||
77 | p1.close(); | ||
78 | |||
79 | System.out.println(""); System.out.println("Commiting..."); | ||
80 | con.commit(); | ||
81 | System.out.println("Commiting... done"); | ||
82 | |||
83 | System.out.println(""); System.out.println("Rolling back..."); | ||
84 | con.rollback(); | ||
85 | System.out.println("Rolling back... done"); | ||
86 | |||
87 | System.out.println(""); System.out.println("Closing connection (no parameters) con=" + con + "..."); | ||
88 | con.close(); | ||
89 | System.out.println("Closing connection... done"); | ||
90 | } catch (Exception e) | ||
91 | { | ||
92 | System.out.println("ZZZZZZZZZZZZZZZZ Exception: " + e); | ||
93 | } | ||
94 | |||
95 | System.out.println("Done!"); | ||
96 | } | ||
97 | } | ||
98 |
File test/java/oracle/t1.jdb.run added (mode: 100755) (index 0000000..b73cc24) | |||
1 | #!/bin/bash | ||
2 | |||
3 | set -e | ||
4 | |||
5 | if [ t1.class -ot t1.java ]; then | ||
6 | echo "Compiling..." | ||
7 | javac t1.java | ||
8 | fi | ||
9 | |||
10 | # -Xdiag \ | ||
11 | # -verbose:class \ | ||
12 | #strace -s2000 -tt -f -o t1.tmp.strace \ | ||
13 | jdb -classpath ojdbc11.jar:. t1 | ||
14 |
File test/java/oracle/t1.run copied from file test/java/pg/pg1.run (similarity 50%) (mode: 100755) (index e3bb4c2..36283ee) | |||
2 | 2 | ||
3 | 3 | set -e | set -e |
4 | 4 | ||
5 | if [ pg1.class -ot pg1.java ]; then | ||
5 | if [ t1.class -ot t1.java ]; then | ||
6 | 6 | echo "Compiling..." | echo "Compiling..." |
7 | javac pg1.java | ||
7 | javac t1.java | ||
8 | 8 | fi | fi |
9 | 9 | ||
10 | 10 | # We need postgreql-jdbc package | # We need postgreql-jdbc package |
... | ... | export LD_PRELOAD=../../../agent/ninedogs.so | |
14 | 14 | export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro | export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro |
15 | 15 | export NINEDOGS_SERVER_PORT=36000 | export NINEDOGS_SERVER_PORT=36000 |
16 | 16 | export NINEDOGS_ID=ba446a981b387e831db3f6a730c55552 | export NINEDOGS_ID=ba446a981b387e831db3f6a730c55552 |
17 | export NINEDOGS_VERBOSE=10 | ||
17 | export NINEDOGS_VERBOSE=11 | ||
18 | 18 | export NINEDOGS_SYNC_FLUSH=1 | export NINEDOGS_SYNC_FLUSH=1 |
19 | 19 | ||
20 | 20 | #export LD_DEBUG=all | #export LD_DEBUG=all |
... | ... | export NINEDOGS_SYNC_FLUSH=1 | |
22 | 22 | ||
23 | 23 | #strace -tt -f -s2000 -o 1.strace \ | #strace -tt -f -s2000 -o 1.strace \ |
24 | 24 | #ltrace -s200 -f -tt -S -o 1.ltrace \ | #ltrace -s200 -f -tt -S -o 1.ltrace \ |
25 | #java -cp /usr/share/java/postgresql-jdbc.jar:. pg1 | ||
25 | #java -cp /usr/share/java/postgresql-jdbc.jar:. t1 | ||
26 | 26 | ||
27 | #strace -s20000 -f -o 1.strace \ | ||
28 | # -javaagent:../../agent/java/agent/ninedogs-agent.jar \ | ||
27 | # -verbose:class \ | ||
28 | # -Xdiag \ | ||
29 | #strace -s20000 -f -q -o t1.strace -e\!brk,futex,getpid,gettid,lseek,sysinfo,mmap,munmap,mprotect,pread64 \ | ||
29 | 30 | java \ | java \ |
30 | -Xdiag \ | ||
31 | -cp /usr/share/java/postgresql-jdbc.jar:. pg1 2>&1 | tee 1.out & | ||
31 | -cp ojdbc11.jar:. t1 &>t1.out & | ||
32 | 32 | ||
33 | 33 | echo "Runing trace..." | echo "Runing trace..." |
34 | LD_PRELOAD= LD_DEBUG= ../../../trace/nd-trace -o 1.nd -p ${!} | ||
34 | LD_PRELOAD= LD_DEBUG= ../../../trace/nd-trace --only-high-level -o t1.nd -p ${!} | ||
35 | 35 | ||
36 | # ninedogs must inject this: | ||
37 | # -javaagent:../../../agent/java/agent/ninedogs-agent.jar | ||
36 | #LD_PRELOAD= LD_DEBUG= podman stop -t0 nd-java-oracle | ||
38 | 37 |
File test/java/oracle/t2.java added (mode: 100644) (index 0000000..470d4a8) | |||
1 | // Prepared statement test | ||
2 | |||
3 | import java.sql.*; | ||
4 | import java.util.Properties; | ||
5 | |||
6 | class t2 | ||
7 | { | ||
8 | public static void main(String args[]) | ||
9 | { | ||
10 | try { | ||
11 | Class.forName("oracle.jdbc.driver.OracleDriver"); | ||
12 | |||
13 | System.out.println("Creating connection..."); | ||
14 | Connection con = DriverManager.getConnection( | ||
15 | "jdbc:oracle:thin:@localhost:61521:XE", "system", "pass"); | ||
16 | System.out.println("Creating connection... done con=" + con); | ||
17 | |||
18 | System.out.println("Creating prepared statement..."); | ||
19 | PreparedStatement p1 = con.prepareStatement("SELECT ? AS F1, ? AS F2 FROM dual"); | ||
20 | System.out.println("Creating prepared statement... done p1=" + p1); | ||
21 | |||
22 | System.out.println("Binding parameters..."); | ||
23 | p1.setInt(1, 12345); | ||
24 | p1.setString(2, "abcde"); | ||
25 | System.out.println("Executing prepared (no result expected!)..."); | ||
26 | p1.execute(); | ||
27 | System.out.println("Executing prepared (no result expected!)... done"); | ||
28 | |||
29 | System.out.println("Getting result set..."); | ||
30 | ResultSet rs2 = p1.getResultSet(); | ||
31 | System.out.println("Getting result set... done rs2=" + rs2); | ||
32 | System.out.println("Calling next()..."); | ||
33 | while (rs2.next()) { | ||
34 | float f1 = rs2.getFloat("F1"); | ||
35 | System.out.println("f1=" + f1); | ||
36 | } | ||
37 | } catch (Exception e) | ||
38 | { | ||
39 | System.out.println("ZZZZZZZZZZZZZZZZ Exception: " + e); | ||
40 | } | ||
41 | |||
42 | System.out.println("Done!"); | ||
43 | } | ||
44 | } | ||
45 |
File test/java/oracle/t2.jdb.run added (mode: 100755) (index 0000000..edbf857) | |||
1 | #!/bin/bash | ||
2 | |||
3 | set -e | ||
4 | |||
5 | if [ t2.class -ot t2.java ]; then | ||
6 | echo "Compiling..." | ||
7 | javac t2.java | ||
8 | fi | ||
9 | |||
10 | # -Xdiag \ | ||
11 | # -verbose:class \ | ||
12 | #strace -s2000 -tt -f -o t2.tmp.strace \ | ||
13 | jdb -classpath ojdbc11.jar:. t2 | ||
14 |
File test/java/oracle/t2.run copied from file test/java/pg/pg1.run (similarity 50%) (mode: 100755) (index e3bb4c2..fe0b807) | |||
2 | 2 | ||
3 | 3 | set -e | set -e |
4 | 4 | ||
5 | if [ pg1.class -ot pg1.java ]; then | ||
5 | if [ t2.class -ot t2.java ]; then | ||
6 | 6 | echo "Compiling..." | echo "Compiling..." |
7 | javac pg1.java | ||
7 | javac t2.java | ||
8 | 8 | fi | fi |
9 | 9 | ||
10 | 10 | # We need postgreql-jdbc package | # We need postgreql-jdbc package |
... | ... | export LD_PRELOAD=../../../agent/ninedogs.so | |
14 | 14 | export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro | export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro |
15 | 15 | export NINEDOGS_SERVER_PORT=36000 | export NINEDOGS_SERVER_PORT=36000 |
16 | 16 | export NINEDOGS_ID=ba446a981b387e831db3f6a730c55552 | export NINEDOGS_ID=ba446a981b387e831db3f6a730c55552 |
17 | export NINEDOGS_VERBOSE=10 | ||
17 | export NINEDOGS_VERBOSE=49 | ||
18 | 18 | export NINEDOGS_SYNC_FLUSH=1 | export NINEDOGS_SYNC_FLUSH=1 |
19 | 19 | ||
20 | 20 | #export LD_DEBUG=all | #export LD_DEBUG=all |
... | ... | export NINEDOGS_SYNC_FLUSH=1 | |
22 | 22 | ||
23 | 23 | #strace -tt -f -s2000 -o 1.strace \ | #strace -tt -f -s2000 -o 1.strace \ |
24 | 24 | #ltrace -s200 -f -tt -S -o 1.ltrace \ | #ltrace -s200 -f -tt -S -o 1.ltrace \ |
25 | #java -cp /usr/share/java/postgresql-jdbc.jar:. pg1 | ||
25 | #java -cp /usr/share/java/postgresql-jdbc.jar:. t2 | ||
26 | 26 | ||
27 | #strace -s20000 -f -o 1.strace \ | ||
28 | # -javaagent:../../agent/java/agent/ninedogs-agent.jar \ | ||
27 | # -verbose:class \ | ||
28 | # -Xdiag \ | ||
29 | strace -s20000 -f -q -o t2.strace -e\!brk,futex,getpid,gettid,lseek,sysinfo,mmap,munmap,mprotect,pread64 \ | ||
29 | 30 | java \ | java \ |
30 | -Xdiag \ | ||
31 | -cp /usr/share/java/postgresql-jdbc.jar:. pg1 2>&1 | tee 1.out & | ||
31 | -cp ojdbc11.jar:. t2 2>&1 | tee t2.out & | ||
32 | 32 | ||
33 | 33 | echo "Runing trace..." | echo "Runing trace..." |
34 | LD_PRELOAD= LD_DEBUG= ../../../trace/nd-trace -o 1.nd -p ${!} | ||
34 | LD_PRELOAD= LD_DEBUG= ../../../trace/nd-trace -o t2.nd -p ${!} | ||
35 | 35 | ||
36 | # ninedogs must inject this: | ||
37 | # -javaagent:../../../agent/java/agent/ninedogs-agent.jar | ||
36 | #LD_PRELOAD= LD_DEBUG= podman stop -t0 nd-java-oracle | ||
38 | 37 |
File test/java/oracle/t_con_err.java added (mode: 100644) (index 0000000..f2db8c8) | |||
1 | import java.sql.*; | ||
2 | import java.util.Properties; | ||
3 | |||
4 | class t_con_err | ||
5 | { | ||
6 | public static void main(String args[]) | ||
7 | { | ||
8 | try { | ||
9 | Class.forName("oracle.jdbc.driver.OracleDriver"); | ||
10 | |||
11 | try { | ||
12 | System.out.println("Creating connection con0..."); | ||
13 | Properties props = new Properties(); | ||
14 | props.put("user", "user-bla"); | ||
15 | props.put("password", "password-bla"); | ||
16 | props.put("v$session.program", "Application name"); | ||
17 | Connection con0 = DriverManager.getConnection( | ||
18 | "jdbc:oracle:thin:@wrong-host:61521:XE", props); | ||
19 | System.out.println("Creating connection con0... done"); | ||
20 | } catch (Exception e) { | ||
21 | } | ||
22 | } catch (Exception e) | ||
23 | { | ||
24 | System.out.println("ZZZZZZZZZZZZZZZZ Exception: " + e); | ||
25 | } | ||
26 | |||
27 | System.out.println("Done!"); | ||
28 | } | ||
29 | } | ||
30 |
File test/java/oracle/t_con_err.sh added (mode: 100755) (index 0000000..be65e15) | |||
1 | #!/bin/bash | ||
2 | |||
3 | set -e | ||
4 | |||
5 | if [ t_con_err.class -ot t_con_err.java ]; then | ||
6 | echo "Compiling..." | ||
7 | javac t_con_err.java | ||
8 | fi | ||
9 | |||
10 | # We need postgreql-jdbc package | ||
11 | |||
12 | export LD_PRELOAD=../../../agent/ninedogs.so | ||
13 | |||
14 | export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro | ||
15 | export NINEDOGS_SERVER_PORT=36000 | ||
16 | export NINEDOGS_ID=ba446a981b387e831db3f6a730c55552 | ||
17 | export NINEDOGS_VERBOSE=49 | ||
18 | export NINEDOGS_SYNC_FLUSH=1 | ||
19 | |||
20 | #export LD_DEBUG=all | ||
21 | #export LD_DEBUG_OUTPUT=1.ld.txt | ||
22 | |||
23 | #strace -tt -f -s2000 -o 1.strace \ | ||
24 | #ltrace -s200 -f -tt -S -o 1.ltrace \ | ||
25 | #java -cp /usr/share/java/postgresql-jdbc.jar:. t_con_err | ||
26 | |||
27 | # -verbose:class \ | ||
28 | # -Xdiag \ | ||
29 | #strace -s20000 -f -q -o t_con_err.strace -e\!brk,futex,getpid,gettid,lseek,sysinfo,mmap,munmap,mprotect,pread64 \ | ||
30 | java \ | ||
31 | -cp ojdbc11.jar:. t_con_err &>t_con_err.out & | ||
32 | |||
33 | echo "Runing trace..." | ||
34 | LD_PRELOAD= LD_DEBUG= ../../../trace/nd-trace -o t_con_err.nd -p ${!} | ||
35 | |||
36 | #LD_PRELOAD= LD_DEBUG= podman stop -t0 nd-java-oracle | ||
37 |
File test/java/pg/1-no-nd-ja.sh added (mode: 100755) (index 0000000..d7c182f) | |||
1 | #!/bin/bash | ||
2 | |||
3 | set -e | ||
4 | |||
5 | if [ pg1.class -ot pg1.java ]; then | ||
6 | echo "Compiling..." | ||
7 | javac pg1.java | ||
8 | fi | ||
9 | |||
10 | # We need postgreql-jdbc package | ||
11 | |||
12 | #strace -s20000 -f -o 1.strace \ | ||
13 | # -javaagent:../../agent/java/agent/ninedogs-agent.jar \ | ||
14 | java \ | ||
15 | -javaagent:../../../agent/java/agent/ninedogs-agent.jar \ | ||
16 | -cp /usr/share/java/postgresql-jdbc.jar:. pg1 2>&1 | tee 1-no-nd.out | ||
17 |
File test/java/pg/1-no-nd.run added (mode: 100755) (index 0000000..0ff5d2b) | |||
1 | #!/bin/bash | ||
2 | |||
3 | set -e | ||
4 | |||
5 | if [ pg1.class -ot pg1.java ]; then | ||
6 | echo "Compiling..." | ||
7 | javac pg1.java | ||
8 | fi | ||
9 | |||
10 | # We need postgreql-jdbc package | ||
11 | |||
12 | #strace -s20000 -f -o 1.strace \ | ||
13 | # -javaagent:../../agent/java/agent/ninedogs-agent.jar \ | ||
14 | java \ | ||
15 | -cp /usr/share/java/postgresql-jdbc.jar:. pg1 2>&1 | tee 1-no-nd.out | ||
16 |
File test/java/pg/pg1.java changed (mode: 100644) (index ec3004b..1ffa904) | |||
... | ... | import java.sql.SQLException; | |
7 | 7 | ||
8 | 8 | public class pg1 { | public class pg1 { |
9 | 9 | public static void main(String args[]) { | public static void main(String args[]) { |
10 | Connection c = null; | ||
11 | 10 | try { | try { |
12 | 11 | System.err.println("Starting..."); | System.err.println("Starting..."); |
13 | |||
14 | 12 | Class.forName("org.postgresql.Driver"); | Class.forName("org.postgresql.Driver"); |
13 | |||
14 | System.err.println(""); | ||
15 | 15 | System.err.println("getConnection..."); | System.err.println("getConnection..."); |
16 | c = DriverManager | ||
16 | Connection con = DriverManager | ||
17 | 17 | .getConnection("jdbc:postgresql://localhost:5432/ninedogs?ApplicationName=pg1", | .getConnection("jdbc:postgresql://localhost:5432/ninedogs?ApplicationName=pg1", |
18 | "ninedogs", ""); | ||
19 | System.err.println("Opened database successfully"); | ||
20 | |||
21 | System.err.println("Query (prepared)..."); | ||
22 | System.err.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx prepare start"); | ||
23 | PreparedStatement preparedStatement = c.prepareStatement("SELECT ? AS id"); | ||
24 | System.err.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx prepare end"); | ||
25 | preparedStatement.setInt(1, 1); | ||
26 | System.err.println("Prepared statement: " + preparedStatement); | ||
27 | |||
28 | System.err.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx execute q start"); | ||
29 | ResultSet rs1 = preparedStatement.executeQuery(); | ||
30 | System.err.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx execute q end"); | ||
18 | "ninedogs", ""); | ||
19 | System.err.println("Opened database successfully con=" + con); | ||
20 | |||
21 | System.err.println(""); | ||
22 | System.err.println("Query (prepared) [PreparedStatement ps = con.prepareStatement(SELECT ? AS id, ? AS str1)]..."); | ||
23 | PreparedStatement ps = con.prepareStatement("SELECT ? AS id, ? AS str1"); | ||
24 | System.err.println("Prepared statement: " + ps); | ||
25 | |||
26 | System.err.println(""); | ||
27 | System.err.println("Binding para 1 [ps.setInt(1, 12345)]..."); | ||
28 | ps.setInt(1, 12345); | ||
29 | |||
30 | System.err.println(""); | ||
31 | System.err.println("Binding para 2 [ps.setString(2, \"abc\")]..."); | ||
32 | ps.setString(2, "abc"); | ||
33 | |||
34 | System.err.println(""); | ||
35 | System.err.println("Binding invalid para 100 [ps.setInt(100, 111)]..."); | ||
36 | try { ps.setInt(100, 111); } catch (Exception e) { System.err.println("EXEC: " + e); } | ||
37 | |||
38 | System.err.println(""); | ||
39 | System.err.println("Executing prepared query [ResultSet rs1 = ps.executeQuery()]..."); | ||
40 | ResultSet rs1 = ps.executeQuery(); | ||
41 | System.err.println("Executing prepared query... done rs1=" + rs1); | ||
42 | |||
43 | System.err.println(""); | ||
44 | System.err.println("Looping [rs1.next()]..."); | ||
31 | 45 | while (rs1.next()) { | while (rs1.next()) { |
32 | 46 | int id = rs1.getInt("id"); | int id = rs1.getInt("id"); |
33 | 47 | System.err.println(" id=" + id); | System.err.println(" id=" + id); |
34 | 48 | } | } |
35 | 49 | ||
36 | 50 | System.err.println(""); | System.err.println(""); |
37 | System.err.println("Query (normal)..."); | ||
38 | Statement stmt = c.createStatement(); | ||
51 | System.err.println("Closing prepared statement [ps.close()]..."); | ||
52 | ps.close(); | ||
53 | |||
54 | |||
55 | System.err.println(""); | ||
56 | System.err.println("Creating statement [Statement stmt = con.createStatement()] (link con with stmt)..."); | ||
57 | Statement stmt = con.createStatement(); | ||
58 | |||
59 | System.err.println(""); | ||
60 | System.err.println("Query (normal)... [ResultSet rs2 = stmt.executeQuery('SELECT ...')]"); | ||
39 | 61 | ResultSet rs2 = stmt.executeQuery("SELECT * FROM n1 LIMIT 2"); | ResultSet rs2 = stmt.executeQuery("SELECT * FROM n1 LIMIT 2"); |
40 | System.err.println("Query (normal) done"); | ||
62 | System.err.println("Query (normal) done rs2=" + rs2); | ||
63 | |||
64 | System.err.println(""); | ||
65 | System.err.println("Looping [rs2.next()]..."); | ||
41 | 66 | while (rs2.next()) { | while (rs2.next()) { |
42 | 67 | int id = rs2.getInt("id"); | int id = rs2.getInt("id"); |
43 | 68 | System.err.println(" id=" + id); | System.err.println(" id=" + id); |
44 | 69 | } | } |
70 | |||
71 | System.err.println(""); | ||
72 | System.err.println("Closing statement [stmt.close()]..."); | ||
45 | 73 | stmt.close(); | stmt.close(); |
46 | 74 | ||
47 | c.close(); | ||
75 | System.err.println(""); System.err.println("Closing connection [con.close()]..."); | ||
76 | con.close(); | ||
48 | 77 | System.err.println("Done"); | System.err.println("Done"); |
49 | 78 | } catch (Exception e) { | } catch (Exception e) { |
50 | 79 | e.printStackTrace(); | e.printStackTrace(); |
File test/java/pg/pg1.jdb.run added (mode: 100755) (index 0000000..e11ca2c) | |||
1 | #!/bin/bash | ||
2 | |||
3 | set -e | ||
4 | |||
5 | if [ pg1.class -ot pg1.java ]; then | ||
6 | echo "Compiling..." | ||
7 | javac pg1.java | ||
8 | fi | ||
9 | |||
10 | # -Xdiag \ | ||
11 | # -verbose:class \ | ||
12 | #strace -s2000 -tt -f -o pg1.tmp.strace \ | ||
13 | jdb \ | ||
14 | -classpath /usr/share/java/postgresql-jdbc.jar:. pg1 | ||
15 |
File test/java/pg/pg1.run changed (mode: 100755) (index e3bb4c2..53fb625) | |||
... | ... | export LD_PRELOAD=../../../agent/ninedogs.so | |
14 | 14 | export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro | export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro |
15 | 15 | export NINEDOGS_SERVER_PORT=36000 | export NINEDOGS_SERVER_PORT=36000 |
16 | 16 | export NINEDOGS_ID=ba446a981b387e831db3f6a730c55552 | export NINEDOGS_ID=ba446a981b387e831db3f6a730c55552 |
17 | export NINEDOGS_VERBOSE=10 | ||
17 | export NINEDOGS_VERBOSE=110 | ||
18 | 18 | export NINEDOGS_SYNC_FLUSH=1 | export NINEDOGS_SYNC_FLUSH=1 |
19 | 19 | ||
20 | 20 | #export LD_DEBUG=all | #export LD_DEBUG=all |
21 | 21 | #export LD_DEBUG_OUTPUT=1.ld.txt | #export LD_DEBUG_OUTPUT=1.ld.txt |
22 | 22 | ||
23 | #strace -tt -f -s2000 -o 1.strace \ | ||
24 | #ltrace -s200 -f -tt -S -o 1.ltrace \ | ||
23 | #strace -tt -f -s2000 -o pg1.strace \ | ||
24 | #ltrace -s200 -f -tt -S -o pg1.ltrace \ | ||
25 | 25 | #java -cp /usr/share/java/postgresql-jdbc.jar:. pg1 | #java -cp /usr/share/java/postgresql-jdbc.jar:. pg1 |
26 | 26 | ||
27 | #strace -s20000 -f -o 1.strace \ | ||
27 | |||
28 | 28 | # -javaagent:../../agent/java/agent/ninedogs-agent.jar \ | # -javaagent:../../agent/java/agent/ninedogs-agent.jar \ |
29 | # -Xdiag \ | ||
30 | #strace -s20000 -tt -f -e\!mprotect,gettid -o pg1.strace \ | ||
29 | 31 | java \ | java \ |
30 | -Xdiag \ | ||
31 | -cp /usr/share/java/postgresql-jdbc.jar:. pg1 2>&1 | tee 1.out & | ||
32 | -cp /usr/share/java/postgresql-jdbc.jar:. pg1 &>pg1.out & | ||
32 | 33 | ||
33 | 34 | echo "Runing trace..." | echo "Runing trace..." |
34 | LD_PRELOAD= LD_DEBUG= ../../../trace/nd-trace -o 1.nd -p ${!} | ||
35 | |||
36 | # ninedogs must inject this: | ||
37 | # -javaagent:../../../agent/java/agent/ninedogs-agent.jar | ||
35 | LD_PRELOAD= LD_DEBUG= ../../../trace/nd-trace --only-high-level -o pg1.nd -p ${!} | ||
38 | 36 |
File test/openssl/expired.sh copied from file test/openssl/run.sh (similarity 74%) (mode: 100755) (index 85565d3..0cb3ee1) | |||
1 | 1 | #!/bin/bash | #!/bin/bash |
2 | 2 | ||
3 | if [ ! -r certificate.crt ]; then | ||
3 | if [ ! -r expired-certificate.crt ]; then | ||
4 | 4 | openssl req -x509 \ | openssl req -x509 \ |
5 | 5 | -utf8 \ | -utf8 \ |
6 | 6 | -sha256 \ | -sha256 \ |
7 | 7 | -nodes \ | -nodes \ |
8 | -days 365 \ | ||
8 | -days 1 \ | ||
9 | 9 | -set_serial 0x112233 \ | -set_serial 0x112233 \ |
10 | -subj '/C=RO/CN=aaa.example.com/L=Brasov/O=openssl' \ | ||
10 | -subj '/C=RO/CN=expired.example.com/L=Brasov/O=openssl' \ | ||
11 | 11 | -addext 'subjectAltName = DNS:bbb.example.com, DNS:ccc.example.com, DNS:șșș.example.com' \ | -addext 'subjectAltName = DNS:bbb.example.com, DNS:ccc.example.com, DNS:șșș.example.com' \ |
12 | 12 | -newkey rsa:4096 \ | -newkey rsa:4096 \ |
13 | 13 | -keyout private.key \ | -keyout private.key \ |
14 | -out certificate.crt | ||
14 | -out expired-certificate.crt | ||
15 | 15 | fi | fi |
16 | 16 | ||
17 | 17 | # To debug | # To debug |
... | ... | export LD_DEBUG_OUTPUT="1.ld.txt" | |
31 | 31 | export DEBUGINFOD_URLS= | export DEBUGINFOD_URLS= |
32 | 32 | ||
33 | 33 | #export GNUTLS_DEBUG_LEVEL=99 | #export GNUTLS_DEBUG_LEVEL=99 |
34 | #export SSLKEYLOGFILE=run.key | ||
34 | #export SSLKEYLOGFILE=expired.key | ||
35 | 35 | ||
36 | 36 | #strace -tt -f -s2000 -o 1.strace \ | #strace -tt -f -s2000 -o 1.strace \ |
37 | 37 | #valgrind -v --trace-children=yes \ | #valgrind -v --trace-children=yes \ |
38 | 38 | #ltrace -S -s200 -f -tt -S -o 1.ltrace \ | #ltrace -S -s200 -f -tt -S -o 1.ltrace \ |
39 | openssl x509 -in certificate.crt -text -noout 2>&1 | LD_PRELOAD= LD_DEBUG= tee run.out | ||
39 | openssl x509 -in expired-certificate.crt -text -noout 2>&1 | LD_PRELOAD= LD_DEBUG= tee expired.out | ||
40 | 40 | ||
41 | 41 |
File test/openssl/expiring.sh added (mode: 100755) (index 0000000..2eea4bb) | |||
1 | #!/bin/bash | ||
2 | |||
3 | rm -f expiring-certificate.crt | ||
4 | openssl req -x509 \ | ||
5 | -utf8 \ | ||
6 | -sha256 \ | ||
7 | -nodes \ | ||
8 | -days 13 \ | ||
9 | -set_serial 0x112233ee \ | ||
10 | -subj '/C=RO/CN=expiring.example.com/L=Brasov/O=openssl' \ | ||
11 | -addext 'subjectAltName = DNS:bbb.example.com, DNS:ccc.example.com, DNS:șșș.example.com' \ | ||
12 | -newkey rsa:4096 \ | ||
13 | -keyout private.key \ | ||
14 | -out expiring-certificate.crt | ||
15 | |||
16 | # To debug | ||
17 | #openssl s_server -cert fullchain.pem -key privkey.pem -port 6002 -debug -status_verbose -msg | ||
18 | |||
19 | export LD_PRELOAD=../../agent/ninedogs.so | ||
20 | |||
21 | export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro | ||
22 | export NINEDOGS_SERVER_PORT=36000 | ||
23 | export NINEDOGS_ID=ba446a981b387e831db3f6a730c55552 | ||
24 | export NINEDOGS_VERBOSE=50 | ||
25 | export NINEDOGS_SYNC_FLUSH=1 | ||
26 | |||
27 | #export LD_DEBUG=all | ||
28 | export LD_DEBUG_OUTPUT="expiring.ld.txt" | ||
29 | |||
30 | export DEBUGINFOD_URLS= | ||
31 | |||
32 | #export GNUTLS_DEBUG_LEVEL=99 | ||
33 | #export SSLKEYLOGFILE=run.key | ||
34 | |||
35 | #strace -tt -f -s2000 -o 1.strace \ | ||
36 | #valgrind -v --trace-children=yes \ | ||
37 | #ltrace -S -s200 -f -tt -S -o 1.ltrace \ | ||
38 | openssl x509 -in expiring-certificate.crt -text -noout 2>&1 | LD_PRELOAD= LD_DEBUG= tee expiring.out | ||
39 | |||
40 | # To have another user | ||
41 | openssl x509 -in expiring-certificate.crt -text 2>&1 | LD_PRELOAD= LD_DEBUG= tee -a expiring.out | ||
42 |
File test/php-container/exec.sh changed (mode: 100755) (index a41ea9d..bb187dc) | |||
8 | 8 | #strace -s200 -tt -f -q -o podman.strace \ | #strace -s200 -tt -f -q -o podman.strace \ |
9 | 9 | podman run -ti --rm \ | podman run -ti --rm \ |
10 | 10 | \ | \ |
11 | -e NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro \ | ||
12 | -e NINEDOGS_SERVER_PORT=36000 \ | ||
13 | -e NINEDOGS_ID=ba446a981b387e831db3f6a730c55513 \ | ||
11 | 14 | -e LD_PRELOAD=ninedogs.so \ | -e LD_PRELOAD=ninedogs.so \ |
12 | 15 | \ | \ |
13 | 16 | -v ${PWD}/1.php:/1.php \ | -v ${PWD}/1.php:/1.php \ |
File test/php-dns/1.run changed (mode: 100755) (index 4b7d12e..3ba0032) | |||
... | ... | export DEBUGINFOD_URLS= | |
17 | 17 | #strace -tt -f -s2000 -o 1.strace \ | #strace -tt -f -s2000 -o 1.strace \ |
18 | 18 | #ltrace -s200 -f -tt -S -o 1.ltrace \ | #ltrace -s200 -f -tt -S -o 1.ltrace \ |
19 | 19 | php 1.php &>1.out & | php 1.php &>1.out & |
20 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1.nd -p ${!} | ||
20 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace --only-high-level -o 1.nd -p ${!} | ||
21 | 21 |
File test/php-mysql/1.run changed (mode: 100755) (index e5cbc8e..1b05148) | |||
... | ... | export DEBUGINFOD_URLS= | |
17 | 17 | #valgrind -v --trace-children=yes \ | #valgrind -v --trace-children=yes \ |
18 | 18 | #strace -tt -f -s2000 -o 1.strace \ | #strace -tt -f -s2000 -o 1.strace \ |
19 | 19 | php 1.php &>1.out & | php 1.php &>1.out & |
20 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1.nd -p ${!} | ||
20 | #LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1.nd -p ${!} | ||
21 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace --only-high-level -o 1.nd -p ${!} | ||
21 | 22 |
File test/php-mysql/1.run.gdb copied from file test/php-pg/1.run.gdb (similarity 100%) |
File test/php-mysql/1.run.gdb.sh copied from file test/php-pg/1.run.gdb.sh (similarity 100%) |
File test/php-mysql/1.vg.run copied from file test/php-mysql/1.run (similarity 68%) (mode: 100755) (index e5cbc8e..1be6147) | |||
... | ... | export DEBUGINFOD_URLS= | |
16 | 16 | #ltrace -s200 -f -tt -S -o 1.ltrace \ | #ltrace -s200 -f -tt -S -o 1.ltrace \ |
17 | 17 | #valgrind -v --trace-children=yes \ | #valgrind -v --trace-children=yes \ |
18 | 18 | #strace -tt -f -s2000 -o 1.strace \ | #strace -tt -f -s2000 -o 1.strace \ |
19 | php 1.php &>1.out & | ||
20 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1.nd -p ${!} | ||
19 | valgrind -v --track-origins=yes php 1.php &>1.vg.out </dev/null & | ||
20 | #LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1.nd -p ${!} | ||
21 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace --only-high-level -o 1.vg.nd -p ${!} | ||
21 | 22 |
File test/php-mysql/stmt_bind_param.php changed (mode: 100644) (index 4045b38..4528162) | |||
... | ... | mysqli_stmt_execute($stmt); | |
31 | 31 | echo 'Calling mysqli_stmt_execute 2...' . "\n"; | echo 'Calling mysqli_stmt_execute 2...' . "\n"; |
32 | 32 | $a = 2; $b = $a + 1; $c = 8.4; $d = 'bla2'; $e = 'bla3'; | $a = 2; $b = $a + 1; $c = 8.4; $d = 'bla2'; $e = 'bla3'; |
33 | 33 | mysqli_stmt_execute($stmt); | mysqli_stmt_execute($stmt); |
34 | mysqli_stmt_close($stmt); | ||
34 | 35 | ||
35 | 36 | echo 'Done!' . "\n"; | echo 'Done!' . "\n"; |
36 | 37 |
File test/php-mysql/stmt_bind_param.run changed (mode: 100755) (index bca3d2f..ab189f2) | |||
... | ... | export DEBUGINFOD_URLS= | |
17 | 17 | #valgrind -v --trace-children=yes \ | #valgrind -v --trace-children=yes \ |
18 | 18 | #strace -tt -f -s2000 -o stmt_bind_param.strace \ | #strace -tt -f -s2000 -o stmt_bind_param.strace \ |
19 | 19 | php stmt_bind_param.php &>stmt_bind_param.out & | php stmt_bind_param.php &>stmt_bind_param.out & |
20 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o stmt_bind_param.nd -p ${!} | ||
20 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace --only-high-level -o stmt_bind_param.nd -p ${!} | ||
21 | 21 |
File test/php-oracle/1 copied from file test/php-container/1 (similarity 58%) (mode: 100755) (index 5454f81..4f27c4a) | |||
2 | 2 | ||
3 | 3 | # This will be executed inside the container | # This will be executed inside the container |
4 | 4 | ||
5 | echo "TERM=${TERM}" | ||
6 | |||
5 | 7 | export LD_PRELOAD=ninedogs.so | export LD_PRELOAD=ninedogs.so |
6 | export NINEDOGS_VERBOSE=0 | ||
8 | export NINEDOGS_VERBOSE=1 | ||
7 | 9 | php /1.php & | php /1.php & |
10 | #LD_PRELOAD= nd-trace --only-high-level -p ${!} | ||
8 | 11 | LD_PRELOAD= nd-trace -p ${!} | LD_PRELOAD= nd-trace -p ${!} |
9 | 12 |
File test/php-oracle/1.php added (mode: 100644) (index 0000000..8d6a23a) | |||
1 | <?php | ||
2 | |||
3 | sleep(1); | ||
4 | |||
5 | $db = oci_pconnect('system', 'pass', 'r1i:61521/XE', "", OCI_DEFAULT); | ||
6 | if ($db === FALSE) | ||
7 | die(); | ||
8 | |||
9 | $stid = oci_parse($db, 'SELECT :p1 AS xx, NULL AS yy FROM dual'); | ||
10 | $p1 = 'before'; | ||
11 | oci_bind_by_name($stid, ':p1', $p1); | ||
12 | $p1 = 'after'; // setting value AFTER binding! | ||
13 | oci_execute($stid); | ||
14 | oci_execute($stid, OCI_NO_AUTO_COMMIT); | ||
15 | $row = oci_fetch_array($stid, OCI_ASSOC|OCI_RETURN_NULLS); | ||
16 | print_r($row); | ||
17 | oci_free_statement($stid); | ||
18 | |||
19 | oci_close($db); | ||
20 | |||
21 | echo 'Done!' . "\n"; |
File test/php-oracle/Dockerfile added (mode: 100644) (index 0000000..f43bfeb) | |||
1 | FROM oraclelinux:8 | ||
2 | |||
3 | # TODO: catalinux+ninedogs | ||
4 | |||
5 | RUN echo "1" | ||
6 | RUN dnf -y --setopt=nodocs install oracle-release-el8 oracle-instantclient-release-el8 \ | ||
7 | oracle-epel-release-el8 oraclelinux-release-el8 \ | ||
8 | oraclelinux-developer-release-el8 \ | ||
9 | gcc make \ | ||
10 | https://rocketgit.com/op/pkgrepo/main/global/testing/rocky/8/x86_64/os/rocketgit-global-testing-1.1-1.noarch.rpm \ | ||
11 | \ | ||
12 | && dnf -y module enable php:8.0 \ | ||
13 | \ | ||
14 | && dnf -y install oracle-instantclient-devel \ | ||
15 | php-cli php-opcache php-pear php-devel | ||
16 | |||
17 | RUN pecl install oci8-3.0.1 | ||
18 | |||
19 | RUN echo "extension=oci8.so" >> /etc/php.ini | ||
20 | |||
21 | RUN dnf -y update | ||
22 | RUN dnf -y install gnutls-devel json-c-devel libcap-devel catalinux+Conn \ | ||
23 | texlive-latex texlive-beamer texlive-adjustbox texlive-babel-english \ | ||
24 | texlive-hyperref texlive-url | ||
25 | |||
26 | RUN dnf -y install strace gdb | ||
27 | |||
28 | RUN mkdir /nd | ||
29 | COPY copy/ /nd/ | ||
30 | RUN cd /nd && ./configure && make common && make agent && make -R -C agent install && make trace && make -R -C trace install |
File test/php-oracle/build.sh added (mode: 100755) (index 0000000..0e29305) | |||
1 | #!/bin/bash | ||
2 | |||
3 | set -u | ||
4 | set -e | ||
5 | |||
6 | mkdir -p copy | ||
7 | rsync -a ../../ --exclude 'test/' \ | ||
8 | --include 'configure' --include '*.c' --include '*.h' --include 'duilder' --include 'Makefile*' \ | ||
9 | --exclude '*.*' \ | ||
10 | copy | ||
11 | |||
12 | docker="podman" | ||
13 | |||
14 | ${docker} build \ | ||
15 | --tag="ninedogs-php-oracle:latest" \ | ||
16 | . | ||
17 | |||
18 | #rm -rf copy |
File test/php-oracle/exec-dev-1.sh added (mode: 100755) (index 0000000..45fcdf1) | |||
1 | podman run -ti \ | ||
2 | -v ${PWD}/1.php:/1.php \ | ||
3 | -v ${PWD}/1:/1 \ | ||
4 | --rm \ | ||
5 | --namespace nd-test \ | ||
6 | ninedogs-php-oracle:latest \ | ||
7 | /1 2>&1 | tee exec-dev-1.out | ||
8 | |||
9 |
File test/php-oracle/exec-dev-bash.sh added (mode: 100755) (index 0000000..5993480) | |||
1 | podman run -ti \ | ||
2 | -v ${PWD}/1.php:/1.php \ | ||
3 | -v ${PWD}/1:/1 \ | ||
4 | --rm \ | ||
5 | --namespace nd-test \ | ||
6 | ninedogs-php-oracle:latest \ | ||
7 | bash | ||
8 | |||
9 |
File test/php-pg/1.run changed (mode: 100755) (index 0d2f00a..09cc4a3) | |||
... | ... | export DEBUGINFOD_URLS= | |
17 | 17 | #valgrind -v --trace-children=yes \ | #valgrind -v --trace-children=yes \ |
18 | 18 | #strace -tt -f -s2000 -o 1.strace \ | #strace -tt -f -s2000 -o 1.strace \ |
19 | 19 | php 1.php &>1.out & | php 1.php &>1.out & |
20 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1.nd -p ${!} | ||
20 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace --only-high-level -o 1.nd -p ${!} |
File test/php/gd/.gitignore added (mode: 100644) (index 0000000..e33609d) | |||
1 | *.png |
File test/php/gd/1.php added (mode: 100644) (index 0000000..ae28576) | |||
1 | <?php | ||
2 | error_reporting(E_ALL); | ||
3 | |||
4 | sleep(1); | ||
5 | |||
6 | for ($i = 0; $i < 10; $i++) { | ||
7 | $im = imagecreatetruecolor(100, 100); | ||
8 | $color = imagecolorallocate($im, 0, 255, 0); | ||
9 | imagestring($im, 5, 3, 9, 'bla', $color); | ||
10 | imagepng($im, '1.png'); | ||
11 | usleep(1000 * $i * 100); | ||
12 | imagedestroy($im); | ||
13 | } | ||
14 | |||
15 | exit(1); | ||
16 | |||
17 |
File test/php/gd/1.run copied from file test/php-dns/1.run (similarity 72%) (mode: 100755) (index 4b7d12e..0635d57) | |||
1 | 1 | #!/bin/bash | #!/bin/bash |
2 | 2 | ||
3 | export LD_PRELOAD=../../agent/ninedogs.so | ||
3 | export LD_PRELOAD=../../../agent/ninedogs.so | ||
4 | 4 | ||
5 | 5 | export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro | export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro |
6 | 6 | export NINEDOGS_SERVER_PORT=36000 | export NINEDOGS_SERVER_PORT=36000 |
... | ... | export LD_DEBUG_OUTPUT=1.ld.txt | |
13 | 13 | ||
14 | 14 | export DEBUGINFOD_URLS= | export DEBUGINFOD_URLS= |
15 | 15 | ||
16 | #ltrace -s200 -f -tt -S -o 1.ltrace \ | ||
16 | 17 | #valgrind -v --trace-children=yes \ | #valgrind -v --trace-children=yes \ |
17 | 18 | #strace -tt -f -s2000 -o 1.strace \ | #strace -tt -f -s2000 -o 1.strace \ |
18 | #ltrace -s200 -f -tt -S -o 1.ltrace \ | ||
19 | 19 | php 1.php &>1.out & | php 1.php &>1.out & |
20 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1.nd -p ${!} | ||
21 | |||
20 | LD_PRELOAD= LD_DEBUG= ../../../trace/nd-trace --only-high-level -o 1.nd -p ${!} | ||
21 | LD_PRELOAD= LD_DEBUG= cat 1.nd |
File test/php/redis/1.php added (mode: 100644) (index 0000000..ac30f7a) | |||
1 | <?php | ||
2 | error_reporting(E_ALL); | ||
3 | |||
4 | sleep(1); | ||
5 | |||
6 | $redis = phpiredis_connect('127.0.0.1', 56379); // normal connection | ||
7 | |||
8 | $response = phpiredis_command_bs($redis, array('DEL', 'test0')); | ||
9 | |||
10 | for ($i = 0; $i < 1000; $i++) { | ||
11 | $response = phpiredis_multi_command_bs($redis, | ||
12 | array( | ||
13 | array('SET', 'test' . $i, $i), | ||
14 | array('GET', 'test' . $i) | ||
15 | ) | ||
16 | ); | ||
17 | } | ||
18 | |||
19 | $response = phpiredis_multi_command_bs($redis, | ||
20 | array( | ||
21 | array('GET', 'test0') | ||
22 | ) | ||
23 | ); | ||
24 | |||
25 | print_r($response); |
File test/php/redis/1.run copied from file test/php-pg/1.run (similarity 75%) (mode: 100755) (index 0d2f00a..122a997) | |||
1 | 1 | #!/bin/bash | #!/bin/bash |
2 | 2 | ||
3 | export LD_PRELOAD=../../agent/ninedogs.so | ||
3 | export LD_PRELOAD=../../../agent/ninedogs.so | ||
4 | 4 | ||
5 | 5 | export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro | export NINEDOGS_SERVER_HOSTNAME=rg.embedromix.ro |
6 | 6 | export NINEDOGS_SERVER_PORT=36000 | export NINEDOGS_SERVER_PORT=36000 |
... | ... | export DEBUGINFOD_URLS= | |
17 | 17 | #valgrind -v --trace-children=yes \ | #valgrind -v --trace-children=yes \ |
18 | 18 | #strace -tt -f -s2000 -o 1.strace \ | #strace -tt -f -s2000 -o 1.strace \ |
19 | 19 | php 1.php &>1.out & | php 1.php &>1.out & |
20 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -o 1.nd -p ${!} | ||
20 | LD_PRELOAD= LD_DEBUG= ../../../trace/nd-trace -o 1.nd -p ${!} | ||
21 | LD_PRELOAD= LD_DEBUG= cat 1.nd |
File test/redis/.gitignore added (mode: 100644) (index 0000000..58c2a9d) | |||
1 | *.rdb |
File test/redis/1.run added (mode: 100755) (index 0000000..6ec084f) | |||
1 | #!/bin/bash | ||
2 | |||
3 | set -e | ||
4 | |||
5 | export LD_PRELOAD=../../agent/ninedogs.so | ||
6 | |||
7 | export NINEDOGS_VERBOSE=300 | ||
8 | |||
9 | #export LD_DEBUG=symbols | ||
10 | export LD_DEBUG_OUTPUT=1.ld.txt | ||
11 | |||
12 | /usr/bin/redis-server --port 56379 &>1.out & | ||
13 | LD_PRELOAD= LD_DEBUG= ../../trace/nd-trace -p ${!} | ||
14 |
File tools/Makefile changed (mode: 100644) (index 3ae7ac7..4424a54) | |||
1 | 1 | include ../Makefile.common | include ../Makefile.common |
2 | 2 | ||
3 | 3 | COMMON_H += ../common/ids.h ../common/tools.h ../common/decode_text.h \ | COMMON_H += ../common/ids.h ../common/tools.h ../common/decode_text.h \ |
4 | ../common/params.h \ | ||
5 | ctools.h | ||
4 | ../common/sctools.h ../common/bin2struct.h | ||
6 | 5 | ||
7 | 6 | CFLAGS += -I../common | CFLAGS += -I../common |
8 | 7 | ||
9 | 8 | OBJS := \ | OBJS := \ |
10 | ../common/tools.o ../common/info.o ../common/decode_text.o | ||
9 | ../common/tools.o ../common/info.o ../common/decode_text.o \ | ||
10 | ../common/sctools.o ../common/bin2struct.o | ||
11 | 11 | ||
12 | 12 | ALL_TOOLS := cert-notify | ALL_TOOLS := cert-notify |
13 | 13 | ||
14 | 14 | all: $(ALL_TOOLS) | all: $(ALL_TOOLS) |
15 | 15 | ||
16 | 16 | cert-notify: cert-notify.c Makefile $(COMMON_H) $(OBJS) | cert-notify: cert-notify.c Makefile $(COMMON_H) $(OBJS) |
17 | $(CC) $(CFLAGS) $@.c -o $@ $(OBJS) | ||
17 | $(CC) $(CFLAGS) $@.c -o $@ $(OBJS) $(CURL_LIBS) | ||
18 | 18 | ||
19 | 19 | .PHONY: clean | .PHONY: clean |
20 | 20 | clean: | clean: |
21 | 21 | @rm -f $(ALL_TOOLS) | @rm -f $(ALL_TOOLS) |
22 | 22 | ||
23 | 23 | install: all | install: all |
24 | @mkdir -p $(if $(I_USR_BIN), $(I_USR_BIN), /usr/bin) | ||
24 | @mkdir -p $(I_USR_BIN) | ||
25 | 25 | cp -vd $(ALL_TOOLS) $(I_USR_BIN) | cp -vd $(ALL_TOOLS) $(I_USR_BIN) |
26 | |||
26 | @mkdir -pv $(I_USR)/lib/systemd/system | ||
27 | cp -vd *.service *.timer $(I_USR)/lib/systemd/system/ |
File tools/TODO changed (mode: 100644) (index acdcb58..edeca5a) | |||
1 | 1 | [ ] Log when the cert was last time used. | [ ] Log when the cert was last time used. |
2 | [ ] Logic: | ||
3 | for each uid | ||
4 | list /var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x | ||
5 | foreach cert/%s hash file | ||
6 | test expiration | ||
7 | notify if needed (rate-limit) | ||
8 | [ ] Seems I need the full path to cvertificate. Can we extract it? | ||
9 | [ ] Should I keep track of last notification per usr or per cert? | ||
2 | 10 | [ ] | [ ] |
File tools/cert-notify.c changed (mode: 100644) (index e69de29..395742f) | |||
1 | #include <libgen.h> | ||
2 | #include <stdarg.h> | ||
3 | #include <stdio.h> | ||
4 | |||
5 | #include <bin2struct.h> | ||
6 | #include <sctools.h> | ||
7 | #include <tools.h> | ||
8 | |||
9 | static unsigned debug = 10; | ||
10 | |||
11 | void xlog(const unsigned int level, const char *format, ...) | ||
12 | { | ||
13 | va_list ap; | ||
14 | char a[4096]; | ||
15 | size_t len; | ||
16 | |||
17 | if (level > debug) | ||
18 | return; | ||
19 | |||
20 | va_start(ap, format); | ||
21 | len = vsnprintf(a, sizeof(a), format, ap); | ||
22 | va_end(ap); | ||
23 | |||
24 | if (len >= sizeof(a) - 1) | ||
25 | len = sizeof(a) - 1; | ||
26 | a[len] = '\0'; | ||
27 | fprintf(stderr, "%s", a); | ||
28 | } | ||
29 | |||
30 | static int user_cb(const unsigned int uid, const char *user_dir) | ||
31 | { | ||
32 | glob_t certs; | ||
33 | struct timeval now; | ||
34 | int r, ret = 0; | ||
35 | long hours, last_notification; | ||
36 | char msg[64 * 4096]; | ||
37 | size_t msg_off = 0; | ||
38 | char *add = ""; | ||
39 | unsigned int count = 0; | ||
40 | |||
41 | xlog(0, "%s: uid=%u user_dir=[%s]\n", | ||
42 | __func__, uid, user_dir); | ||
43 | |||
44 | r = nd_load_uid_file_long(&hours, uid, | ||
45 | "settings/certs/cert-notification-hours-before"); | ||
46 | if (r == -1) | ||
47 | hours = 15 * 24; | ||
48 | xlog(10, " hour = %ld\n", hours); | ||
49 | |||
50 | r = nd_load_uid_file_long(&last_notification, uid, | ||
51 | "state/certs/cert-notification-last"); | ||
52 | if (r == -1) | ||
53 | last_notification = 0; | ||
54 | xlog(10, " last_notification = %ld\n", last_notification); | ||
55 | |||
56 | ninedogs_now(&now); | ||
57 | if (last_notification + 24 * 3600 > now.tv_sec) { | ||
58 | xlog(1, " notification too early; last was at %u [%d]\n", | ||
59 | last_notification, last_notification + 24 * 3600 - now.tv_sec); | ||
60 | return 0; | ||
61 | } | ||
62 | long next_notification = now.tv_sec + 24 * 3600; // compute proper "tomorrow" | ||
63 | r = nd_save_uid_file_long(uid, "state/certs/cert-notification-last", next_notification); | ||
64 | if (r == -1) | ||
65 | return -1; | ||
66 | |||
67 | r = nd_load_certs(&certs, uid); | ||
68 | if (r <= 0) | ||
69 | return r; | ||
70 | for (unsigned int i = 0; i < certs.gl_pathc; i++) { | ||
71 | unsigned char data[4096]; | ||
72 | r = load_dir_file(data, sizeof(data), certs.gl_pathv[i], "data"); | ||
73 | if (r == -1) { | ||
74 | ret = -1; | ||
75 | break; | ||
76 | } | ||
77 | |||
78 | struct ninedogs_cert cert; | ||
79 | r = nd_bin2struct_cert(&cert, data, r); | ||
80 | if (r == -1) { | ||
81 | ret = -1; | ||
82 | break; | ||
83 | } | ||
84 | |||
85 | if (cert.not_after < (unsigned long) now.tv_sec) // already expired | ||
86 | continue; | ||
87 | |||
88 | if (cert.not_after - hours * 3600 >= (unsigned long) now.tv_sec) // expire in the future | ||
89 | continue; | ||
90 | |||
91 | char not_before[32], not_after[32]; | ||
92 | nd_ts_to_str(not_before, sizeof(not_before), cert.not_before); | ||
93 | nd_ts_to_str(not_after, sizeof(not_after), cert.not_after); | ||
94 | xlog(0, " subj=[%s] path=[%s] issuer=[%s] serial=[%s] %s -> %s\n", | ||
95 | cert.subj, cert.path, cert.issuer, cert.serial, not_before, not_after); | ||
96 | nd_str_append(msg, sizeof(msg), &msg_off, | ||
97 | "%sSubject: %s\nIssuer: %s\nPath: %s\nSerial: %s" | ||
98 | "\nNot before: %s\nNot after: %s\n", | ||
99 | add, cert.subj, cert.issuer, cert.path, cert.serial, | ||
100 | not_before, not_after); | ||
101 | add = "\n\n"; | ||
102 | |||
103 | glob_t users; | ||
104 | r = nd_load_cert_users(&users, certs.gl_pathv[i]); | ||
105 | if (r == -1) { | ||
106 | ret = -1; | ||
107 | break; | ||
108 | } | ||
109 | nd_str_append(msg, sizeof(msg), &msg_off, "Users:\n"); | ||
110 | for (unsigned j = 0; j < users.gl_pathc; j++) { | ||
111 | // example: /var/lib/ninedogs/users/by-uid/01/00/00000001/cert/dcf86835cf357b94393a/users/ba/ba446a981b387e831db3f6a730c55552/379561e8 | ||
112 | // Warning! dirname modifies string in place! | ||
113 | |||
114 | unsigned char data[4096]; | ||
115 | int r = load_file(data, sizeof(data), users.gl_pathv[j]); | ||
116 | if (r == -1) | ||
117 | return -1; | ||
118 | struct ninedogs_app app; | ||
119 | r = nd_bin2struct_app(&app, data, r); | ||
120 | if (r == -1) { | ||
121 | ret = -1; | ||
122 | break; | ||
123 | } | ||
124 | |||
125 | char *q = dirname(users.gl_pathv[j]); | ||
126 | char *user_client_id = basename(q); q = dirname(q); | ||
127 | char cmd[4096], sts[64]; | ||
128 | nd_app_nice(cmd, sizeof(cmd), app.cmdline, app.cmdline_len); | ||
129 | nd_ts_to_str(sts, sizeof(sts), app.ts / 1000); | ||
130 | xlog(0, " user_client_id=[%s]" | ||
131 | "\n cmdline=[%s] ts=%lld [%s]\n", | ||
132 | user_client_id, cmd, app.ts, sts); | ||
133 | nd_str_append(msg, sizeof(msg), &msg_off, | ||
134 | " Command: %s\n Last start of command: %s\n", | ||
135 | cmd, sts); | ||
136 | } | ||
137 | globfree(&users); | ||
138 | xlog(0, "\n"); | ||
139 | if (ret == -1) | ||
140 | break; | ||
141 | count++; | ||
142 | } | ||
143 | globfree(&certs); | ||
144 | if (ret != 0) | ||
145 | return ret; | ||
146 | |||
147 | xlog(1, "%s: msg:\n=======================\n%s\n=================\n", __func__, msg); | ||
148 | char subject[128]; | ||
149 | snprintf(subject, sizeof(subject), | ||
150 | "Expiring certificates (%u)", count); | ||
151 | nd_user_notify(uid, subject, msg); | ||
152 | |||
153 | return ret; | ||
154 | } | ||
155 | |||
156 | int main(void) | ||
157 | { | ||
158 | nd_for_each_user(user_cb); | ||
159 | |||
160 | return 0; | ||
161 | } |
File tools/ninedogs-cert-notify.service added (mode: 100644) (index 0000000..96ce6ec) | |||
1 | [Unit] | ||
2 | Description = Notify users about certificates problems (about to expire etc.) | ||
3 | Documentation = https://rocketgit.com/user/catalinux/ninedogs | ||
4 | |||
5 | [Service] | ||
6 | ExecStart = /usr/bin/cert-notify | ||
7 | Type = simple | ||
8 | User = ninedogs | ||
9 | Group = ninedogs |
File tools/ninedogs-cert-notify.timer added (mode: 100644) (index 0000000..50b2ce1) | |||
1 | [Unit] | ||
2 | Description = Notify users about certificates problems (about to expire etc.) | ||
3 | |||
4 | [Timer] | ||
5 | OnCalendar = hourly | ||
6 | Persistent = true | ||
7 | |||
8 | [Install] | ||
9 | WantedBy=timers.target |
File trace/.gitignore changed (mode: 100644) (index c9b8944..6b00866) | |||
1 | 1 | nd-trace | nd-trace |
2 | show-colors |
File trace/Makefile changed (mode: 100644) (index 9cefeea..0a39190) | |||
1 | # This is just to allow us to run make here | ||
2 | .PHONY: all | ||
3 | all: | ||
4 | make -R -C .. trace | ||
1 | include ../Makefile.common | ||
5 | 2 | ||
6 | 3 | COMMON_H += ../common/shared.h ../common/tools.h ../common/decode_text.h \ | COMMON_H += ../common/shared.h ../common/tools.h ../common/decode_text.h \ |
7 | ../common/ids.h | ||
4 | ../common/ids.h ../common/params.h | ||
8 | 5 | ||
9 | 6 | CFLAGS += -I../common | CFLAGS += -I../common |
10 | 7 | ||
11 | 8 | OBJS := ../common/tools.o ../common/decode_text.o | OBJS := ../common/tools.o ../common/decode_text.o |
12 | 9 | ||
13 | #decode.o: decode.c decode.h process_db.h $(COMMON_H) | ||
14 | # $(CC) $(CFLAGS) -fPIC -c -o $@ $< | ||
10 | all: nd-trace | ||
15 | 11 | ||
16 | 12 | nd-trace: nd-trace.c $(COMMON_H) $(OBJS) | nd-trace: nd-trace.c $(COMMON_H) $(OBJS) |
17 | 13 | $(CC) $(CFLAGS) $@.c -o $@ $(OBJS) $(LIBS) | $(CC) $(CFLAGS) $@.c -o $@ $(OBJS) $(LIBS) |
18 | 14 | ||
19 | compile: nd-trace | ||
20 | |||
21 | 15 | .PHONY: clean | .PHONY: clean |
22 | 16 | clean: | clean: |
23 | 17 | @rm -f nd-trace *.strace *.log *.out *.o | @rm -f nd-trace *.strace *.log *.out *.o |
File trace/TODO changed (mode: 100644) (index d8d97e0..c37a8c0) | |||
4 | 4 | ||
5 | 5 | == Non urgent == | == Non urgent == |
6 | 6 | [ ] We need to respect UTF-8 in bin2hex_ascii | [ ] We need to respect UTF-8 in bin2hex_ascii |
7 | [ ] show if a semaphore is locked or not | ||
8 | [ ] Ask the 'server' to provide the prepared statement/connection if we attached too late. | ||
9 | [ ] How much time it took (Bogdan S). | ||
10 | [ ] Colors (Bogdan S). | ||
11 | [ ] Do not use colors if output is not a tty! | ||
12 | [ ] When using TLS, trace also meta info: expiration, CN etc. | ||
7 | 13 | [ ] | [ ] |
8 |
File trace/nd-trace.c changed (mode: 100644) (index 2265606..375f3e5) | |||
25 | 25 | #include <unistd.h> | #include <unistd.h> |
26 | 26 | ||
27 | 27 | #include "ids.h" | #include "ids.h" |
28 | #include "params.h" | ||
28 | 29 | #include "shared.h" | #include "shared.h" |
29 | 30 | #include "tools.h" | #include "tools.h" |
30 | 31 | #include "decode_text.h" | #include "decode_text.h" |
31 | 32 | ||
33 | struct theme | ||
34 | { | ||
35 | char *name; | ||
36 | unsigned int colors; | ||
37 | unsigned int color_default; | ||
38 | |||
39 | unsigned int color_func_i_c, color_func_i_r, color_func_i_m; | ||
40 | unsigned int color_func_n_c, color_func_n_r, color_func_n_m; | ||
41 | unsigned int color_ts_s, color_ts_e, color_ts_bad; | ||
42 | unsigned int color_ret_ok, color_ret_error, color_flags; | ||
43 | }; | ||
44 | |||
45 | static const struct theme themes[] = | ||
46 | { | ||
47 | { .name = "def", | ||
48 | .colors = 256, .color_default = 3, | ||
49 | .color_func_i_c = 196, .color_func_i_r = 202, .color_func_i_m = 207, | ||
50 | .color_func_n_c = 46, .color_func_n_r = 70, .color_func_n_m = 90, | ||
51 | .color_ts_s = 246, .color_ts_e = 255, .color_ts_bad = 196, | ||
52 | .color_ret_ok = 48, .color_ret_error = 197, .color_flags = 46 | ||
53 | }, | ||
54 | { .name = NULL } | ||
55 | }; | ||
56 | static const char *theme_name = "def"; | ||
57 | static const char *theme_s1 = "", *theme_s2 = "", *theme_e = ""; | ||
58 | static const struct theme *theme = NULL; | ||
59 | |||
32 | 60 | static const struct option options[] = | static const struct option options[] = |
33 | 61 | { | { |
34 | {"pid", required_argument, NULL, 'p'}, | ||
35 | {"output", required_argument, NULL, 'o'}, | ||
36 | {NULL, 0, NULL, 0} | ||
62 | {"pid", required_argument, NULL, 'p'}, | ||
63 | {"output", required_argument, NULL, 'o'}, | ||
64 | {"only-high-level", no_argument, NULL, 'H'}, | ||
65 | {"theme", required_argument, NULL, 't'}, | ||
66 | {NULL, 0, NULL, 0} | ||
37 | 67 | }; | }; |
38 | 68 | ||
39 | 69 | static void usage(void) | static void usage(void) |
40 | 70 | { | { |
41 | 71 | fprintf(stderr, | fprintf(stderr, |
42 | 72 | "Usage: nd-trace [options]\n" | "Usage: nd-trace [options]\n" |
43 | " --pid -p pid to trace (can be added multiple times)\n" | ||
44 | " --output -o where to store the output\n" | ||
73 | " --pid -p pid to trace (can be added multiple times)\n" | ||
74 | " --output -o where to store the output\n" | ||
75 | " --only-high-level -H log only high level, if possible\n" | ||
76 | " --theme -t do not show output with colors ['def']\n" | ||
77 | " If output is not a tty, no theme is used\n" | ||
45 | 78 | "\n"); | "\n"); |
46 | 79 | exit(1); | exit(1); |
47 | 80 | } | } |
48 | 81 | ||
49 | 82 | static FILE *outf; | static FILE *outf; |
50 | 83 | static unsigned int do_exit; | static unsigned int do_exit; |
84 | static pid_t pids[256]; | ||
85 | static unsigned int no_pids; | ||
86 | static char only_high_level; | ||
87 | static uint64_t last_ts; | ||
88 | |||
89 | /* | ||
90 | * Set the theme | ||
91 | */ | ||
92 | static void nd_trace_color_set_theme(void) | ||
93 | { | ||
94 | unsigned theme_colors; | ||
95 | |||
96 | if (!isatty(fileno(outf))) | ||
97 | return; | ||
98 | |||
99 | const char *term = getenv("TERM"); | ||
100 | //fprintf(outf, "TERM=[%s]\n", term); fflush(outf); | ||
101 | if (term == NULL) | ||
102 | return; | ||
103 | |||
104 | if (strcmp(term, "xterm-256color") == 0) { | ||
105 | theme_colors = 256; | ||
106 | } else if (strcmp(term, "xterm") == 0) { | ||
107 | theme_colors = 16; | ||
108 | } else { | ||
109 | return; | ||
110 | } | ||
111 | |||
112 | //fprintf(outf, "Searching for theme [%s] and %u colors...\n", | ||
113 | // theme_name, theme_colors); fflush(outf); | ||
114 | for (int i = 0; themes[i].name != NULL; i++) { | ||
115 | if (strcmp(themes[i].name, theme_name) != 0) | ||
116 | continue; | ||
117 | if (themes[i].colors != theme_colors) | ||
118 | continue; | ||
119 | theme = &themes[i]; | ||
120 | break; | ||
121 | } | ||
122 | if (!theme) { | ||
123 | fprintf(outf, " Theme [%s/%u] not found, using no theme.\n", | ||
124 | theme_name, theme_colors); | ||
125 | return; | ||
126 | } | ||
127 | |||
128 | if (theme->colors == 16) { | ||
129 | theme_s1 = "\x1b["; theme_s2 = "m"; | ||
130 | theme_e = "\x1b[0m"; | ||
131 | } else if (theme->colors == 256) { | ||
132 | theme_s1 = "\x1b[38;5;"; theme_s2 = "m"; | ||
133 | theme_e = "\x1b[0m"; | ||
134 | } | ||
135 | |||
136 | fprintf(outf, "Theme set to [%s] based on term [%s]; colors=%u\n", | ||
137 | theme->name, term, theme->colors); | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * Color output | ||
142 | */ | ||
143 | static void nd_trace_color(char *out, const size_t out_size, | ||
144 | const char *str, const char *category, const char type, | ||
145 | const char *flags, const uint64_t u64) | ||
146 | { | ||
147 | char scolor[4] = { 0 }; | ||
148 | //fprintf(outf, "%s: str=[%s] category=[%s] u64=%lu\n", | ||
149 | // __func__, str, category, u64); fflush(outf); | ||
150 | |||
151 | if (!theme) | ||
152 | goto no_theme; | ||
153 | |||
154 | unsigned color = theme->color_default; | ||
155 | if (strcmp(category, "func") == 0) { | ||
156 | if (strstr("i", flags)) { | ||
157 | if ((type == 'c') || (type == 'R')) | ||
158 | color = theme->color_func_i_c; | ||
159 | else if (type == 'r') | ||
160 | color = theme->color_func_i_r; | ||
161 | else if (type == 'm') | ||
162 | color = theme->color_func_i_m; | ||
163 | } else { | ||
164 | if ((type == 'c') || (type == 'R')) | ||
165 | color = theme->color_func_n_c; | ||
166 | else if (type == 'r') | ||
167 | color = theme->color_func_n_r; | ||
168 | else if (type == 'm') | ||
169 | color = theme->color_func_n_m; | ||
170 | } | ||
171 | } else if (strcmp(category, "ts") == 0) { // 'u64' contains milliseconds | ||
172 | if (u64 >= 2000) | ||
173 | color = theme->color_ts_bad; | ||
174 | else if (u64 >= 1000) | ||
175 | color = theme->color_ts_e; | ||
176 | else | ||
177 | color = theme->color_ts_s + u64 / 100; | ||
178 | } else if (strcmp(category, "error") == 0) { | ||
179 | if (u64 == 0) | ||
180 | color = theme->color_ret_ok; | ||
181 | else | ||
182 | color = theme->color_ret_error; | ||
183 | } else if (strcmp(category, "flags") == 0) { | ||
184 | color = theme->color_flags; | ||
185 | } | ||
186 | snprintf(scolor, sizeof(scolor), "%u", color); | ||
187 | |||
188 | no_theme: | ||
189 | int r = snprintf(out, out_size, "%s%s%s%s%s", | ||
190 | theme_s1, scolor, theme_s2, str, theme_e); | ||
191 | // we will not color things if we do not have enough space | ||
192 | if ((unsigned) r > out_size) | ||
193 | snprintf(out, out_size, "%s", str); | ||
194 | } | ||
195 | |||
51 | 196 | ||
52 | 197 | static uint8_t decode8(unsigned char *d, unsigned int *i) | static uint8_t decode8(unsigned char *d, unsigned int *i) |
53 | 198 | { | { |
... | ... | static uint64_t decode64(unsigned char *d, unsigned int *i) | |
81 | 226 | return be64toh(u); | return be64toh(u); |
82 | 227 | } | } |
83 | 228 | ||
84 | static uint8_t decode_bool(const char *prefix, char *out, size_t out_size, | ||
229 | static uint8_t decode_bool(const char *prefix, char *out0, size_t out_size, | ||
85 | 230 | unsigned char *d, unsigned int *i) | unsigned char *d, unsigned int *i) |
86 | 231 | { | { |
232 | char out[out_size]; | ||
233 | |||
87 | 234 | uint8_t v = d[*i]; *i = *i + 1; | uint8_t v = d[*i]; *i = *i + 1; |
88 | 235 | snprintf(out, out_size, "%s%s", prefix, v == 0 ? "nok" : "ok"); | snprintf(out, out_size, "%s%s", prefix, v == 0 ? "nok" : "ok"); |
236 | nd_trace_color(out0, out_size, out, "error", '-', "", 0); | ||
89 | 237 | return v; | return v; |
90 | 238 | } | } |
91 | 239 | ||
92 | 240 | // TODO: more to add from /usr/include/asm-generic/errno.h | // TODO: more to add from /usr/include/asm-generic/errno.h |
93 | static void decode_errno(char *out, unsigned out_max, const int e) | ||
241 | // TODO: move this in common | ||
242 | static void decode_errno(char *out0, unsigned out_max, const int e) | ||
94 | 243 | { | { |
244 | char out[out_max]; | ||
245 | |||
95 | 246 | switch (e) { | switch (e) { |
96 | 247 | case EPERM: snprintf(out, out_max, "EPERM"); break; | case EPERM: snprintf(out, out_max, "EPERM"); break; |
97 | 248 | case ENOENT: snprintf(out, out_max, "ENOENT"); break; | case ENOENT: snprintf(out, out_max, "ENOENT"); break; |
... | ... | static void decode_errno(char *out, unsigned out_max, const int e) | |
134 | 285 | ||
135 | 286 | default: snprintf(out, out_max, "%d", e); break; | default: snprintf(out, out_max, "%d", e); break; |
136 | 287 | } | } |
288 | |||
289 | nd_trace_color(out0, out_max, out, "error", '-', "", 0); | ||
137 | 290 | } | } |
138 | 291 | ||
139 | 292 | static int decode_ret_int(char *out, unsigned out_max, | static int decode_ret_int(char *out, unsigned out_max, |
... | ... | static void *decode_ret_pointer(char *out, unsigned out_max, | |
179 | 332 | return ret; | return ret; |
180 | 333 | } | } |
181 | 334 | ||
335 | char out2[32]; | ||
336 | nd_trace_color(out2, sizeof(out2), "NULL", "error", '-', "", 0); | ||
337 | snprintf(out, out_max, " = %s", out2); | ||
338 | |||
339 | return ret; | ||
340 | } | ||
341 | |||
342 | static void *decode_ret_pointer_errno(char *out, unsigned out_max, | ||
343 | unsigned char *d, unsigned int *i) | ||
344 | { | ||
345 | void *ret = (void *) decode64(d, i); | ||
346 | if (ret) { | ||
347 | snprintf(out, out_max, " = %p", ret); | ||
348 | return ret; | ||
349 | } | ||
350 | |||
182 | 351 | int xerrno = decode32(d, i); | int xerrno = decode32(d, i); |
183 | 352 | char err[64]; | char err[64]; |
184 | 353 | decode_errno(err, sizeof(err), xerrno); | decode_errno(err, sizeof(err), xerrno); |
185 | snprintf(out, out_max, " = %p (%s)", ret, err); | ||
354 | char out2[64]; | ||
355 | nd_trace_color(out2, sizeof(out2), err, "error", '-', "", 0); | ||
356 | snprintf(out, out_max, " = %p (%s)", ret, out2); | ||
186 | 357 | ||
187 | 358 | return ret; | return ret; |
188 | 359 | } | } |
... | ... | static socklen_t decode_sockaddr(char *out, unsigned char *d, unsigned int *i) | |
218 | 389 | return sl; | return sl; |
219 | 390 | } | } |
220 | 391 | ||
221 | static int decode_sock_level(char *out, unsigned out_size, | ||
392 | static int decode_sock_level(char *out0, unsigned out_size, | ||
222 | 393 | unsigned char *d, unsigned int *i) | unsigned char *d, unsigned int *i) |
223 | 394 | { | { |
395 | char out[out_size]; | ||
396 | |||
224 | 397 | int level = decode32(d, i); | int level = decode32(d, i); |
225 | 398 | ||
226 | 399 | switch (level) { | switch (level) { |
... | ... | static int decode_sock_level(char *out, unsigned out_size, | |
236 | 409 | default: snprintf(out, out_size, "todo(%d)", level); break; | default: snprintf(out, out_size, "todo(%d)", level); break; |
237 | 410 | } | } |
238 | 411 | ||
412 | nd_trace_color(out0, out_size, out, "flags", '-', "", 0); | ||
239 | 413 | return level; | return level; |
240 | 414 | } | } |
241 | 415 | ||
... | ... | static void decode_sock_optname_socket(char *out, unsigned out_size, | |
265 | 439 | } | } |
266 | 440 | } | } |
267 | 441 | ||
442 | #ifndef IP_RECVERR_RFC4884 | ||
443 | #define IP_RECVERR_RFC4884 26 | ||
444 | #endif | ||
268 | 445 | static void decode_sock_optname_ip(char *out, unsigned out_size, | static void decode_sock_optname_ip(char *out, unsigned out_size, |
269 | 446 | const int optname) | const int optname) |
270 | 447 | { | { |
... | ... | static void decode_sock_optname_ip(char *out, unsigned out_size, | |
326 | 503 | } | } |
327 | 504 | } | } |
328 | 505 | ||
506 | #ifndef IPV6_MULTICAST_ALL | ||
507 | #define IPV6_MULTICAST_ALL 29 | ||
508 | #endif | ||
509 | #ifndef IPV6_ROUTER_ALERT_ISOLATE | ||
510 | #define IPV6_ROUTER_ALERT_ISOLATE 30 | ||
511 | #endif | ||
512 | #ifndef IPV6_RECVERR_RFC4884 | ||
513 | #define IPV6_RECVERR_RFC4884 31 | ||
514 | #endif | ||
329 | 515 | static void decode_sock_optname_ipv6(char *out, unsigned out_size, | static void decode_sock_optname_ipv6(char *out, unsigned out_size, |
330 | 516 | const int optname) | const int optname) |
331 | 517 | { | { |
... | ... | static void decode_sock_optname_ipv6(char *out, unsigned out_size, | |
388 | 574 | } | } |
389 | 575 | } | } |
390 | 576 | ||
577 | #ifndef TCP_ZEROCOPY_RECEIVE | ||
578 | #define TCP_ZEROCOPY_RECEIVE 35 | ||
579 | #endif | ||
580 | #ifndef TCP_INQ | ||
581 | #define TCP_INQ 36 | ||
582 | #endif | ||
583 | #ifndef TCP_TX_DELAY | ||
584 | #define TCP_TX_DELAY 37 | ||
585 | #endif | ||
586 | #ifndef UDP_GRO | ||
587 | #define UDP_GRO 104 | ||
588 | #endif | ||
391 | 589 | static void decode_sock_optname_tcp(char *out, unsigned out_size, | static void decode_sock_optname_tcp(char *out, unsigned out_size, |
392 | 590 | const int optname) | const int optname) |
393 | 591 | { | { |
... | ... | static void decode_sock_optname_tcp(char *out, unsigned out_size, | |
434 | 632 | } | } |
435 | 633 | } | } |
436 | 634 | ||
635 | #ifndef UDP_SEGMENT | ||
636 | #define UDP_SEGMENT 103 | ||
637 | #endif | ||
437 | 638 | static void decode_sock_optname_udp(char *out, unsigned out_size, | static void decode_sock_optname_udp(char *out, unsigned out_size, |
438 | 639 | const int optname) | const int optname) |
439 | 640 | { | { |
... | ... | static int decode_mysqli_mode(char *out, size_t out_size, | |
696 | 897 | } | } |
697 | 898 | ||
698 | 899 | static void decode_query_params(char *out, size_t out_size, | static void decode_query_params(char *out, size_t out_size, |
699 | unsigned char *d, unsigned int *i) | ||
900 | unsigned char filter_bind_way, unsigned char *d, unsigned int *i) | ||
700 | 901 | { | { |
902 | unsigned short j; | ||
701 | 903 | size_t len, rest = out_size - 1 - 1; // -1 for \0 and -1 for '}' | size_t len, rest = out_size - 1 - 1; // -1 for \0 and -1 for '}' |
702 | 904 | ||
703 | uint16_t params_len = decode16(d, i); | ||
704 | if (params_len == 0) { | ||
705 | out[0] = '\0'; | ||
706 | return; | ||
707 | } | ||
905 | //fprintf(outf, "%s: filter_bind_way=%hhu\n", __func__, filter_bind_way); | ||
708 | 906 | ||
709 | 907 | if (rest >= 2) { | if (rest >= 2) { |
710 | 908 | strcpy(out, " {"); | strcpy(out, " {"); |
... | ... | static void decode_query_params(char *out, size_t out_size, | |
712 | 910 | } | } |
713 | 911 | ||
714 | 912 | char *add = "", do_break = 0; | char *add = "", do_break = 0; |
715 | for (unsigned short j = 0; j < params_len; j++) { | ||
913 | j = 1; | ||
914 | while (1) { | ||
716 | 915 | char value[64]; | char value[64]; |
717 | 916 | uint8_t type = decode8(d, i); | uint8_t type = decode8(d, i); |
718 | if (type == 0) { // NULL | ||
917 | if (type == ND_TYPE_LAST) | ||
918 | break; | ||
919 | |||
920 | uint8_t bind_info = decode8(d, i); // (o->bind_way << 2) | o->bind_type | ||
921 | uint8_t bind_type = bind_info & 3; | ||
922 | uint8_t bind_way = (bind_info >> 2) & 3; | ||
923 | char head[128]; | ||
924 | |||
925 | const char *way = ""; | ||
926 | if (bind_way == ND_PARAMS_BIND_WAY_IN) | ||
927 | way = "IN:"; | ||
928 | else if (bind_way == ND_PARAMS_BIND_WAY_OUT) | ||
929 | way = "OUT:"; | ||
930 | else if (bind_way == ND_PARAMS_BIND_WAY_BOTH) | ||
931 | way = "IN/OUT:"; | ||
932 | |||
933 | //fprintf(outf, " filter_bind_way=[%s] type=%hhu bind_type=%hhu bind_way=%hhu\n", | ||
934 | // way, type, bind_type, bind_way); | ||
935 | |||
936 | if (bind_type == ND_PARAMS_BIND_TYPE_NAME) { | ||
937 | uint8_t name_len = decode8(d, i); | ||
938 | char name[name_len * 4 + 1]; | ||
939 | bin2hex_ascii(name, d + *i, name_len); *i = *i + name_len; | ||
940 | snprintf(head, sizeof(head), "%s'%s'", way, name); | ||
941 | } else if (bind_type == ND_PARAMS_BIND_TYPE_POS) { | ||
942 | snprintf(head, sizeof(head), "%s%hu", way, decode16(d, i)); | ||
943 | } else { | ||
944 | snprintf(head, sizeof(head), "%s%hu", way, j); | ||
945 | } | ||
946 | |||
947 | if (type == ND_TYPE_NULL) { // NULL | ||
719 | 948 | snprintf(value, sizeof(value), | snprintf(value, sizeof(value), |
720 | "%hu:NULL", j + 1); | ||
721 | } else if (type == 1) { // long | ||
949 | "%s:NULL", head); | ||
950 | } else if (type == ND_TYPE_INT) { | ||
722 | 951 | snprintf(value, sizeof(value), | snprintf(value, sizeof(value), |
723 | "%hu:long:%ld", j + 1, decode64(d, i)); | ||
724 | } else if (type == 2) { // double | ||
952 | "%s:int:%d", head, decode32(d, i)); | ||
953 | } else if (type == ND_TYPE_LONG) { | ||
954 | snprintf(value, sizeof(value), | ||
955 | "%s:long:%ld", head, decode64(d, i)); | ||
956 | } else if (type == ND_TYPE_DOUBLE) { | ||
725 | 957 | double dd; | double dd; |
726 | 958 | uint64_t u = decode64(d, i); | uint64_t u = decode64(d, i); |
727 | 959 | memcpy(&dd, &u, 8); | memcpy(&dd, &u, 8); |
728 | 960 | snprintf(value, sizeof(value), | snprintf(value, sizeof(value), |
729 | "%hu:double:%f", j + 1, dd); | ||
730 | } else if (type == 3) { // string | ||
961 | "%s:double:%f", head, dd); | ||
962 | } else if ((type == ND_TYPE_STRING) || (type == ND_TYPE_UNK)) { | ||
731 | 963 | uint16_t len = decode16(d, i); | uint16_t len = decode16(d, i); |
732 | 964 | char s[len * 4 + 1]; | char s[len * 4 + 1]; |
733 | 965 | bin2hex_ascii(s, d + *i, len); *i = *i + len; | bin2hex_ascii(s, d + *i, len); *i = *i + len; |
734 | 966 | snprintf(value, sizeof(value), | snprintf(value, sizeof(value), |
735 | "%hu:str:'%s'", j + 1, s); | ||
967 | "%s:str:'%s'", head, s); | ||
736 | 968 | } else { | } else { |
737 | 969 | snprintf(value, sizeof(value), | snprintf(value, sizeof(value), |
738 | "%hu:unk, ...", j + 1); | ||
970 | "%s:unk, ...", head); | ||
739 | 971 | do_break = 1; // we cannot continue | do_break = 1; // we cannot continue |
740 | 972 | } | } |
741 | 973 | ||
... | ... | static void decode_query_params(char *out, size_t out_size, | |
743 | 975 | if (len > rest) | if (len > rest) |
744 | 976 | break; | break; |
745 | 977 | ||
746 | strcat(out, add); | ||
747 | strcat(out, value); | ||
748 | add = ", "; | ||
749 | rest -= len; | ||
978 | if (filter_bind_way & bind_way) { | ||
979 | strcat(out, add); | ||
980 | strcat(out, value); | ||
981 | add = ", "; | ||
982 | rest -= len; | ||
983 | } | ||
750 | 984 | ||
751 | 985 | if (do_break) | if (do_break) |
752 | 986 | break; | break; |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
909 | 1143 | { | { |
910 | 1144 | unsigned int i = 0; | unsigned int i = 0; |
911 | 1145 | unsigned short func_len, trace_depth; | unsigned short func_len, trace_depth; |
912 | char type, line[64000], rest[2000]; | ||
1146 | char type, line[64000], line2[64000], rest[4000]; | ||
913 | 1147 | uint64_t t; | uint64_t t; |
914 | 1148 | ||
915 | 1149 | line[0] = '\0'; | line[0] = '\0'; |
1150 | line2[0] = '\0'; | ||
916 | 1151 | rest[0] = '\0'; | rest[0] = '\0'; |
917 | 1152 | ||
918 | 1153 | t = decode64(d, &i); | t = decode64(d, &i); |
1154 | uint8_t tf_len = decode8(d, &i); | ||
1155 | char tf[tf_len + 1]; | ||
1156 | memcpy(tf, d + i, tf_len); i += tf_len; | ||
1157 | tf[tf_len] = '\0'; | ||
919 | 1158 | trace_depth = decode16(d, &i); | trace_depth = decode16(d, &i); |
920 | 1159 | func_len = decode16(d, &i); | func_len = decode16(d, &i); |
921 | 1160 | char func[func_len * 4 + 1]; | char func[func_len * 4 + 1]; |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
923 | 1162 | type = d[i++]; | type = d[i++]; |
924 | 1163 | uint32_t pid = decode32(d, &i); | uint32_t pid = decode32(d, &i); |
925 | 1164 | uint32_t tid = decode32(d, &i); | uint32_t tid = decode32(d, &i); |
926 | //fprintf(outf, "%s: t=%lu func_len=%hu func=[%s] type=%c pid=%u tid=%u\n", | ||
927 | // __func__, t, func_len, func, type, pid, tid); | ||
1165 | //fprintf(outf, "%s: t=%lu func_len=%hu func=[%s] tf=[%s] type=%c pid=%u tid=%u\n", | ||
1166 | // __func__, t, func_len, func, tf, type, pid, tid); | ||
1167 | |||
1168 | if (only_high_level && !strstr(tf, "i")) | ||
1169 | return; | ||
928 | 1170 | ||
929 | 1171 | switch (func[0]) { | switch (func[0]) { |
930 | 1172 | case '-': // project specific | case '-': // project specific |
931 | 1173 | if (strcmp(func, "-stop") == 0) { | if (strcmp(func, "-stop") == 0) { |
932 | 1174 | int ret = decode32(d, &i); | int ret = decode32(d, &i); |
933 | sprintf(line, "() = %d", ret); | ||
1175 | sprintf(rest, "exit code = %d", ret); | ||
1176 | char color[64]; | ||
1177 | nd_trace_color(color, sizeof(color), rest, "error", '-', "", ret); | ||
1178 | sprintf(line, ": %s", color); | ||
934 | 1179 | if (pid == parent) do_exit++; | if (pid == parent) do_exit++; |
935 | 1180 | } else if (strcmp(func, "-segv") == 0) { | } else if (strcmp(func, "-segv") == 0) { |
936 | 1181 | int r = decode32(d, &i); | int r = decode32(d, &i); |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
943 | 1188 | strcat(line, l); | strcat(line, l); |
944 | 1189 | } | } |
945 | 1190 | if (pid == parent) do_exit++; | if (pid == parent) do_exit++; |
1191 | } else if (strcmp(func, "-msgs_lost") == 0) { | ||
1192 | sprintf(rest, "ninedogs: messages lost: %u", decode32(d, &i)); | ||
1193 | nd_trace_color(line, sizeof(line), rest, "error", '-', "", 1); | ||
946 | 1194 | } break; | } break; |
947 | 1195 | ||
948 | 1196 | case 'a': | case 'a': |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
1018 | 1266 | uint8_t oplen = decode8(d, &i); | uint8_t oplen = decode8(d, &i); |
1019 | 1267 | char op[oplen * 4 + 1]; | char op[oplen * 4 + 1]; |
1020 | 1268 | bin2hex_ascii(op, d + i, oplen); i += oplen; | bin2hex_ascii(op, d + i, oplen); i += oplen; |
1021 | char types[4096]; | ||
1269 | char types[4096], types2[4096]; | ||
1022 | 1270 | decode_types(types, sizeof(types), d, &i); | decode_types(types, sizeof(types), d, &i); |
1271 | nd_trace_color(types2, sizeof(types2), types, "flags", type, tf, 0); | ||
1023 | 1272 | if (type == 'r') { | if (type == 'r') { |
1024 | uint8_t ret = decode8(d, &i); | ||
1273 | uint8_t ret = decode8(d, &i); // TODO: decode error | ||
1025 | 1274 | snprintf(rest, sizeof(rest), " = %s", ret == 1 ? "ok" : "nok"); | snprintf(rest, sizeof(rest), " = %s", ret == 1 ? "ok" : "nok"); |
1026 | 1275 | } | } |
1027 | sprintf(line, "(0x%lx, %s, %s)%s", handle, op, types, rest); | ||
1276 | sprintf(line, "(0x%lx, %s, %s)%s", handle, op, types2, rest); | ||
1028 | 1277 | } else if (strcmp(func, "curl_exec") == 0) { // php | } else if (strcmp(func, "curl_exec") == 0) { // php |
1029 | 1278 | uint64_t handle = decode64(d, &i); | uint64_t handle = decode64(d, &i); |
1030 | 1279 | if (type == 'r') { | if (type == 'r') { |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
1047 | 1296 | } else if (strcmp(func, "curl_easy_perform") == 0) { | } else if (strcmp(func, "curl_easy_perform") == 0) { |
1048 | 1297 | if (type == 'm') { | if (type == 'm') { |
1049 | 1298 | uint8_t len = decode8(d, &i); | uint8_t len = decode8(d, &i); |
1050 | char info[len * 4 + 1]; | ||
1299 | char info[len * 4 + 1], info2[len * 4 + 1]; | ||
1051 | 1300 | bin2hex_ascii(info, d + i, len); i += len; | bin2hex_ascii(info, d + i, len); i += len; |
1301 | nd_trace_color(info2, sizeof(info2), info, "flags", type, tf, 0); | ||
1052 | 1302 | uint64_t handle = decode64(d, &i); | uint64_t handle = decode64(d, &i); |
1053 | 1303 | uint16_t post_len = decode16(d, &i); | uint16_t post_len = decode16(d, &i); |
1054 | 1304 | char post[post_len * 4 + 1]; | char post[post_len * 4 + 1]; |
1055 | 1305 | bin2hex_ascii(post, d + i, post_len); i += post_len; | bin2hex_ascii(post, d + i, post_len); i += post_len; |
1056 | sprintf(line, "(0x%lx) %s: %s", handle, info, post); | ||
1306 | sprintf(line, "(0x%lx): meta: %s: %s", handle, info2, post); | ||
1057 | 1307 | } else { | } else { |
1058 | 1308 | uint64_t handle = decode64(d, &i); | uint64_t handle = decode64(d, &i); |
1059 | 1309 | if (type == 'r') { | if (type == 'r') { |
1060 | 1310 | int ret = decode32(d, &i); | int ret = decode32(d, &i); |
1061 | 1311 | nd_decode_curl_code(rest, sizeof(rest), ret); | nd_decode_curl_code(rest, sizeof(rest), ret); |
1062 | sprintf(line, "(0x%lx) = %s", handle, rest); | ||
1312 | char sret[sizeof(rest)]; | ||
1313 | nd_trace_color(sret, sizeof(sret), rest, | ||
1314 | "error", type, tf, ret == 0 ? 0 : 1); | ||
1315 | sprintf(line, "(0x%lx) = %s", handle, sret); | ||
1063 | 1316 | } else { | } else { |
1064 | 1317 | sprintf(line, "(0x%lx)", handle); | sprintf(line, "(0x%lx)", handle); |
1065 | 1318 | } | } |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
1069 | 1322 | uint64_t handle = decode64(d, &i); | uint64_t handle = decode64(d, &i); |
1070 | 1323 | uint8_t type = decode8(d, &i); | uint8_t type = decode8(d, &i); |
1071 | 1324 | uint8_t option_len = decode8(d, &i); | uint8_t option_len = decode8(d, &i); |
1072 | char option[option_len * 4 + 1]; | ||
1325 | char option[option_len * 4 + 1], option2[option_len * 4 + 32]; | ||
1073 | 1326 | bin2hex_ascii(option, d + i, option_len); i += option_len; | bin2hex_ascii(option, d + i, option_len); i += option_len; |
1327 | nd_trace_color(option2, sizeof(option2), option, "flags", type, tf, 0); | ||
1074 | 1328 | if ((type == 0) || (type == 2)) { // long or off_t | if ((type == 0) || (type == 2)) { // long or off_t |
1075 | 1329 | snprintf(rest, sizeof(rest), "%ld", decode64(d, &i)); | snprintf(rest, sizeof(rest), "%ld", decode64(d, &i)); |
1076 | 1330 | } else if ((type == 3) || (type == 4)) { // object or string | } else if ((type == 3) || (type == 4)) { // object or string |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
1090 | 1344 | snprintf(rest, sizeof(rest), "%p", (void *) decode64(d, &i)); | snprintf(rest, sizeof(rest), "%p", (void *) decode64(d, &i)); |
1091 | 1345 | } | } |
1092 | 1346 | int ret = decode32(d, &i); | int ret = decode32(d, &i); |
1093 | char sret[32]; | ||
1347 | char sret[32], sret2[64]; | ||
1094 | 1348 | nd_decode_curl_code(sret, sizeof(sret), ret); | nd_decode_curl_code(sret, sizeof(sret), ret); |
1349 | nd_trace_color(sret2, sizeof(sret2), sret, | ||
1350 | "error", type, tf, ret == 0 ? 0 : 1); | ||
1095 | 1351 | sprintf(line, "(0x%lx, %s, %s) = %s", | sprintf(line, "(0x%lx, %s, %s) = %s", |
1096 | handle, option, rest, sret); | ||
1352 | handle, option2, rest, sret2); | ||
1097 | 1353 | } break; | } break; |
1098 | 1354 | ||
1099 | 1355 | case 'd': | case 'd': |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
1104 | 1360 | char flags[128]; | char flags[128]; |
1105 | 1361 | decode_dlopen_flags(flags, sizeof(flags), d, &i); | decode_dlopen_flags(flags, sizeof(flags), d, &i); |
1106 | 1362 | if (type == 'r') | if (type == 'r') |
1107 | decode_ret_pointer(rest, sizeof(rest), d, &i); | ||
1363 | decode_ret_pointer_errno(rest, sizeof(rest), d, &i); | ||
1108 | 1364 | sprintf(line, "('%s', '%s')%s", filename, flags, rest); | sprintf(line, "('%s', '%s')%s", filename, flags, rest); |
1109 | 1365 | } else if (strcmp(func, "dlclose") == 0) { | } else if (strcmp(func, "dlclose") == 0) { |
1110 | 1366 | void *h = (void *) decode64(d, &i); | void *h = (void *) decode64(d, &i); |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
1121 | 1377 | decode_string_array(argv, sizeof(argv), d, &i); | decode_string_array(argv, sizeof(argv), d, &i); |
1122 | 1378 | decode_string_array(envp, sizeof(envp), d, &i); | decode_string_array(envp, sizeof(envp), d, &i); |
1123 | 1379 | if (type == 'r') | if (type == 'r') |
1124 | decode_ret_pointer(rest, sizeof(rest), d, &i); | ||
1380 | decode_ret_pointer_errno(rest, sizeof(rest), d, &i); | ||
1125 | 1381 | sprintf(line, "('%s', %s, %s)%s", | sprintf(line, "('%s', %s, %s)%s", |
1126 | 1382 | pathname, argv, envp, rest); | pathname, argv, envp, rest); |
1383 | // special action here. We need to switch to the new pid | ||
1384 | // TODO: close previous one? | ||
1385 | if (no_pids < 256) { | ||
1386 | pids[no_pids] = pid; | ||
1387 | no_pids++; | ||
1388 | } | ||
1127 | 1389 | } break; | } break; |
1128 | 1390 | ||
1129 | 1391 | case 'f': | case 'f': |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
1140 | 1402 | decode_stat(sstat, sizeof(sstat), d, &i); | decode_stat(sstat, sizeof(sstat), d, &i); |
1141 | 1403 | int flags = decode32(d, &i); | int flags = decode32(d, &i); |
1142 | 1404 | if (type == 'r') | if (type == 'r') |
1143 | decode_ret_pointer(rest, sizeof(rest), d, &i); | ||
1405 | decode_ret_pointer_errno(rest, sizeof(rest), d, &i); | ||
1144 | 1406 | sprintf(line, "(%s, '%s', {%s}, 0x%x)%s", | sprintf(line, "(%s, '%s', {%s}, 0x%x)%s", |
1145 | 1407 | dirfd, pathname, sstat, flags, rest); | dirfd, pathname, sstat, flags, rest); |
1146 | 1408 | } else if ((strcmp(func, "fsync") == 0) | } else if ((strcmp(func, "fsync") == 0) |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
1149 | 1411 | if (type == 'r') | if (type == 'r') |
1150 | 1412 | decode_ret_int(rest, sizeof(rest), d, &i); | decode_ret_int(rest, sizeof(rest), d, &i); |
1151 | 1413 | sprintf(line, "(%d)%s", fd, rest); | sprintf(line, "(%d)%s", fd, rest); |
1414 | } else if (strcmp(func, "ftruncate") == 0) { | ||
1415 | int fd = decode32(d, &i); | ||
1416 | uint64_t len = decode64(d, &i); | ||
1417 | if (type == 'r') | ||
1418 | decode_ret_int(rest, sizeof(rest), d, &i); | ||
1419 | sprintf(line, "(fd=%d, len=%lu)%s", fd, len, rest); | ||
1152 | 1420 | } break; | } break; |
1153 | 1421 | ||
1154 | 1422 | case 'g': | case 'g': |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
1234 | 1502 | sock, level, optname, optval, optlen, rest); | sock, level, optname, optval, optlen, rest); |
1235 | 1503 | } break; | } break; |
1236 | 1504 | ||
1505 | case 'i': | ||
1506 | if ((strcmp(func, "imagecreate") == 0) | ||
1507 | || (strcmp(func, "imagecreatetruecolor") == 0)) { | ||
1508 | uint64_t w = decode64(d, &i); | ||
1509 | uint64_t h = decode64(d, &i); | ||
1510 | decode_ret_pointer(rest, sizeof(rest), d, &i); | ||
1511 | sprintf(line, "(w=%lu, h=%lu)%s", w, h, rest); | ||
1512 | } else if (strcmp(func, "imagedestroy") == 0) { | ||
1513 | uint64_t im = decode64(d, &i); | ||
1514 | uint32_t elap_ms = decode32(d, &i); | ||
1515 | decode_bool("", rest, sizeof(rest), d, &i); | ||
1516 | char elap[64], elap2[64]; | ||
1517 | snprintf(elap, sizeof(elap), "[image generation time: %ums]", elap_ms); | ||
1518 | nd_trace_color(elap2, sizeof(elap2), elap, "ts", type, tf, elap_ms); | ||
1519 | sprintf(line, "(0x%lx) = %s %s", im, rest, elap2); | ||
1520 | } | ||
1521 | break; | ||
1522 | |||
1523 | case 'j': | ||
1524 | if (strcmp(func, "java/db/connect") == 0) { | ||
1525 | char db_type = decode8(d, &i); | ||
1526 | uint16_t cs_len = decode16(d, &i); | ||
1527 | char cs[cs_len * 4 + 1]; | ||
1528 | bin2hex_ascii(cs, d + i, cs_len); i += cs_len; | ||
1529 | if (type == 'r') { | ||
1530 | uint64_t dbh = decode64(d, &i); | ||
1531 | if (dbh != 0) { | ||
1532 | snprintf(rest, sizeof(rest), " = 0x%lx", dbh); | ||
1533 | } else { | ||
1534 | uint16_t ex_len = decode16(d, &i); | ||
1535 | char ex[ex_len * 4 + 1]; | ||
1536 | bin2hex_ascii(ex, d + i, ex_len); i += ex_len; | ||
1537 | snprintf(rest, sizeof(rest), " = nok [%s]", ex); | ||
1538 | } | ||
1539 | } | ||
1540 | sprintf(line, "/%c('%s')%s", db_type, cs, rest); | ||
1541 | } else if (strcmp(func, "java/db/close") == 0) { | ||
1542 | char db_type = decode8(d, &i); | ||
1543 | uint64_t dbh = decode64(d, &i); | ||
1544 | sprintf(line, "/%c(0x%lx) = ok", db_type, dbh); | ||
1545 | } else if ((strcmp(func, "java/db/prepared/execute") == 0) | ||
1546 | || (strcmp(func, "java/db/stmt/execute") == 0)) { | ||
1547 | char db_type = decode8(d, &i); | ||
1548 | uint64_t stmt = decode64(d, &i); | ||
1549 | if (type == 'r') { | ||
1550 | uint64_t res = decode64(d, &i); | ||
1551 | if (res != 0) { | ||
1552 | snprintf(rest, sizeof(rest), " = ok"); | ||
1553 | } else { | ||
1554 | uint16_t ex_len = decode16(d, &i); | ||
1555 | char ex[ex_len * 4 + 1]; | ||
1556 | bin2hex_ascii(ex, d + i, ex_len); i += ex_len; | ||
1557 | snprintf(rest, sizeof(rest), " = nok [%s]", ex); | ||
1558 | } | ||
1559 | } | ||
1560 | sprintf(line, "/%c(0x%lx)%s", db_type, stmt, rest); | ||
1561 | } else if (strcmp(func, "java/db/prepare") == 0) { | ||
1562 | char db_type = decode8(d, &i); | ||
1563 | uint64_t dbh = decode64(d, &i); | ||
1564 | uint16_t q_len = decode16(d, &i); | ||
1565 | char q[q_len * 4 + 1]; | ||
1566 | bin2hex_ascii(q, d + i, q_len); i += q_len; | ||
1567 | if (type == 'r') { | ||
1568 | uint64_t stmt = decode64(d, &i); | ||
1569 | if (stmt != 0) { | ||
1570 | snprintf(rest, sizeof(rest), " = 0x%lx", stmt); | ||
1571 | } else { | ||
1572 | uint16_t ex_len = decode16(d, &i); | ||
1573 | char ex[ex_len * 4 + 1]; | ||
1574 | bin2hex_ascii(ex, d + i, ex_len); i += ex_len; | ||
1575 | snprintf(rest, sizeof(rest), " = nok [%s]", ex); | ||
1576 | } | ||
1577 | } | ||
1578 | sprintf(line, "/%c(0x%lx, '%s')%s", db_type, dbh, q, rest); | ||
1579 | } else if (strcmp(func, "java/db/stmt/create") == 0) { | ||
1580 | char db_type = decode8(d, &i); | ||
1581 | uint64_t dbh = decode64(d, &i); | ||
1582 | uint64_t stmt = decode64(d, &i); | ||
1583 | if (stmt != 0) { | ||
1584 | snprintf(rest, sizeof(rest), " = 0x%lx", stmt); | ||
1585 | } else { | ||
1586 | uint16_t ex_len = decode16(d, &i); | ||
1587 | char ex[ex_len * 4 + 1]; | ||
1588 | bin2hex_ascii(ex, d + i, ex_len); i += ex_len; | ||
1589 | snprintf(rest, sizeof(rest), " = nok [%s]", ex); | ||
1590 | } | ||
1591 | sprintf(line, "/%c(0x%lx)%s", db_type, dbh, rest); | ||
1592 | } else if (strcmp(func, "java/db/stmt/close") == 0) { | ||
1593 | char db_type = decode8(d, &i); | ||
1594 | uint64_t stmt = decode64(d, &i); | ||
1595 | sprintf(line, "/%c(0x%lx) = ok", db_type, stmt); | ||
1596 | } else if (strcmp(func, "java/db/stmt/execute/sql") == 0) { | ||
1597 | char db_type = decode8(d, &i); | ||
1598 | uint64_t stmt = decode64(d, &i); | ||
1599 | uint16_t q_len = decode16(d, &i); | ||
1600 | char q[q_len * 4 + 1]; | ||
1601 | bin2hex_ascii(q, d + i, q_len); i += q_len; | ||
1602 | if (type == 'r') { | ||
1603 | uint64_t res = decode64(d, &i); | ||
1604 | if (res != 0) { | ||
1605 | snprintf(rest, sizeof(rest), " = 0x%lx", res); | ||
1606 | } else { | ||
1607 | uint16_t ex_len = decode16(d, &i); | ||
1608 | char ex[ex_len * 4 + 1]; | ||
1609 | bin2hex_ascii(ex, d + i, ex_len); i += ex_len; | ||
1610 | snprintf(rest, sizeof(rest), " = nok [%s]", ex); | ||
1611 | } | ||
1612 | } | ||
1613 | sprintf(line, "/%c(0x%lx, '%s')%s", db_type, stmt, q, rest); | ||
1614 | } else if (strcmp(func, "java/db/result/get") == 0) { | ||
1615 | char db_type = decode8(d, &i); | ||
1616 | uint64_t stmt = decode64(d, &i); | ||
1617 | if (type == 'r') { | ||
1618 | uint64_t res = decode64(d, &i); | ||
1619 | if (res != 0) { | ||
1620 | snprintf(rest, sizeof(rest), " = 0x%lx", res); | ||
1621 | } else { | ||
1622 | uint16_t ex_len = decode16(d, &i); | ||
1623 | char ex[ex_len * 4 + 1]; | ||
1624 | bin2hex_ascii(ex, d + i, ex_len); i += ex_len; | ||
1625 | snprintf(rest, sizeof(rest), " = nok [%s]", ex); | ||
1626 | } | ||
1627 | } | ||
1628 | sprintf(line, "/%c(0x%lx)%s", db_type, stmt, rest); | ||
1629 | } else if (strcmp(func, "java/db/stmt/setInt") == 0) { | ||
1630 | //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump); | ||
1631 | char db_type = decode8(d, &i); | ||
1632 | uint64_t stmt = decode64(d, &i); | ||
1633 | uint8_t index = decode8(d, &i); | ||
1634 | int32_t value = decode32(d, &i); | ||
1635 | uint64_t res = decode64(d, &i); | ||
1636 | if (res != 0) { | ||
1637 | snprintf(rest, sizeof(rest), " = ok"); | ||
1638 | } else { | ||
1639 | uint16_t ex_len = decode16(d, &i); | ||
1640 | char ex[ex_len * 4 + 1]; | ||
1641 | bin2hex_ascii(ex, d + i, ex_len); i += ex_len; | ||
1642 | snprintf(rest, sizeof(rest), " = nok [%s]", ex); | ||
1643 | } | ||
1644 | sprintf(line, "/%c(0x%lx, %hhu, %d)%s", | ||
1645 | db_type, stmt, index, value, rest); | ||
1646 | } else if (strcmp(func, "java/db/stmt/setString") == 0) { | ||
1647 | //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump); | ||
1648 | char db_type = decode8(d, &i); | ||
1649 | uint64_t stmt = decode64(d, &i); | ||
1650 | uint8_t index = decode8(d, &i); | ||
1651 | uint16_t vlen = decode16(d, &i); | ||
1652 | char value[vlen * 4 + 1]; | ||
1653 | bin2hex_ascii(value, d + i, vlen); i += vlen; | ||
1654 | uint64_t res = decode64(d, &i); | ||
1655 | if (res != 0) { | ||
1656 | snprintf(rest, sizeof(rest), " = ok"); | ||
1657 | } else { | ||
1658 | uint16_t ex_len = decode16(d, &i); | ||
1659 | char ex[ex_len * 4 + 1]; | ||
1660 | bin2hex_ascii(ex, d + i, ex_len); i += ex_len; | ||
1661 | snprintf(rest, sizeof(rest), " = nok [%s]", ex); | ||
1662 | } | ||
1663 | sprintf(line, "/%c(0x%lx, %hhu, '%s')%s", | ||
1664 | db_type, stmt, index, value, rest); | ||
1665 | } break; | ||
1666 | |||
1237 | 1667 | case 'l': | case 'l': |
1238 | 1668 | if (strcmp(func, "listen") == 0) { | if (strcmp(func, "listen") == 0) { |
1239 | 1669 | //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump); | //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump); |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
1345 | 1775 | decode_mysql_real_connect_flags(flags, sizeof(flags), d, &i); | decode_mysql_real_connect_flags(flags, sizeof(flags), d, &i); |
1346 | 1776 | if (type == 'r') | if (type == 'r') |
1347 | 1777 | decode_bool(" = ", rest, sizeof(rest), d, &i); | decode_bool(" = ", rest, sizeof(rest), d, &i); |
1348 | sprintf(line, "(link=0x%lx, '%s', flags='%s')%s", link, cs, flags, rest); | ||
1778 | sprintf(line, "(link=0x%lx, '%s', flags=%s)%s", link, cs, flags, rest); | ||
1349 | 1779 | } else if (strcmp(func, "mysqli_stmt_bind_param") == 0) { | } else if (strcmp(func, "mysqli_stmt_bind_param") == 0) { |
1350 | 1780 | //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump); | //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump); |
1351 | 1781 | uint64_t stmt = decode64(d, &i); | uint64_t stmt = decode64(d, &i); |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
1356 | 1786 | decode_bool(" = ", rest, sizeof(rest), d, &i); | decode_bool(" = ", rest, sizeof(rest), d, &i); |
1357 | 1787 | sprintf(line, "(stmt=0x%lx, types='%s', ...)%s", | sprintf(line, "(stmt=0x%lx, types='%s', ...)%s", |
1358 | 1788 | stmt, types, rest); | stmt, types, rest); |
1789 | } else if (strcmp(func, "mysqli_stmt_close") == 0) { | ||
1790 | //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump); | ||
1791 | uint64_t stmt = decode64(d, &i); | ||
1792 | if (type == 'r') { | ||
1793 | uint8_t ret = decode8(d, &i); | ||
1794 | snprintf(rest, sizeof(rest), " = %s", ret == 1 ? "ok" : "nok"); | ||
1795 | } | ||
1796 | sprintf(line, "(stmt=0x%lx)%s", stmt, rest); | ||
1359 | 1797 | } else if (strcmp(func, "mysqli_stmt_execute") == 0) { | } else if (strcmp(func, "mysqli_stmt_execute") == 0) { |
1360 | 1798 | //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump); | //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump); |
1361 | 1799 | uint64_t stmt = decode64(d, &i); | uint64_t stmt = decode64(d, &i); |
1362 | 1800 | if (type == 'c') { | if (type == 'c') { |
1363 | decode_query_params(rest, sizeof(rest), d, &i); | ||
1801 | decode_query_params(rest, sizeof(rest), | ||
1802 | ND_PARAMS_BIND_WAY_BOTH, d, &i); | ||
1364 | 1803 | sprintf(line, "(stmt=0x%lx%s%s)", | sprintf(line, "(stmt=0x%lx%s%s)", |
1365 | 1804 | stmt, rest[0] ? ", " : "", rest); | stmt, rest[0] ? ", " : "", rest); |
1366 | 1805 | } else if (type == 'r') { | } else if (type == 'r') { |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
1404 | 1843 | } break; | } break; |
1405 | 1844 | ||
1406 | 1845 | case 'o': | case 'o': |
1407 | if ((strcmp(func, "open") == 0) | ||
1846 | if (strcmp(func, "oci_bind_by_name") == 0) { | ||
1847 | uint64_t stmt = decode64(d, &i); | ||
1848 | sprintf(line, "(stmt=0x%lx)", stmt); | ||
1849 | } else if (strcmp(func, "oci_close") == 0) { | ||
1850 | uint64_t h = decode64(d, &i); | ||
1851 | sprintf(line, "(0x%lx)", h); | ||
1852 | } else if (strcmp(func, "oci_execute") == 0) { | ||
1853 | uint64_t stmt = decode64(d, &i); | ||
1854 | uint64_t mode = decode64(d, &i); | ||
1855 | if (type == 'r') { | ||
1856 | uint8_t ret = decode8(d, &i); | ||
1857 | if (ret == 1) | ||
1858 | snprintf(rest, sizeof(rest), " = ok"); | ||
1859 | else | ||
1860 | snprintf(rest, sizeof(rest), " = nok"); | ||
1861 | } | ||
1862 | char s_mode[128]; | ||
1863 | nd_decode_oci_execute_mode(s_mode, sizeof(s_mode), mode); | ||
1864 | sprintf(line, "(stmt=0x%lx, %s)%s", stmt, s_mode, rest); | ||
1865 | } else if (strcmp(func, "oci_parse") == 0) { | ||
1866 | uint64_t dbh = decode64(d, &i); | ||
1867 | uint16_t q_len = decode16(d, &i); | ||
1868 | char q[q_len * 4 + 1]; | ||
1869 | bin2hex_ascii(q, d + i, q_len); i += q_len; | ||
1870 | if (type == 'r') { | ||
1871 | uint64_t stmt = decode64(d, &i); | ||
1872 | snprintf(rest, sizeof(rest), " = 0x%lx", stmt); | ||
1873 | } | ||
1874 | sprintf(line, "(dbh=0x%lx, '%s')%s", dbh, q, rest); | ||
1875 | } else if (strcmp(func, "oci_pconnect") == 0) { | ||
1876 | //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump); | ||
1877 | uint32_t cs_len = decode32(d, &i); | ||
1878 | char cs[cs_len * 4 + 1]; | ||
1879 | bin2hex_ascii(cs, d + i, cs_len); i += cs_len; | ||
1880 | if (type == 'r') { | ||
1881 | uint64_t h = decode64(d, &i); | ||
1882 | snprintf(rest, sizeof(rest), " = 0x%lx", h); | ||
1883 | } | ||
1884 | sprintf(line, "('%s')%s", cs, rest); | ||
1885 | } else if ((strcmp(func, "open") == 0) | ||
1408 | 1886 | || (strcmp(func, "open64") == 0) | || (strcmp(func, "open64") == 0) |
1409 | 1887 | || (strcmp(func, "openat") == 0)) { | || (strcmp(func, "openat") == 0)) { |
1410 | 1888 | char dirfd[32]; | char dirfd[32]; |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
1423 | 1901 | dirfd, pathname, flags, mode, rest); | dirfd, pathname, flags, mode, rest); |
1424 | 1902 | } break; | } break; |
1425 | 1903 | ||
1904 | case 'O': | ||
1905 | if (strcmp(func, "OCIAttrSet") == 0) { | ||
1906 | uint64_t h = decode64(d, &i); | ||
1907 | uint32_t htype = decode32(d, &i); | ||
1908 | unsigned int attr_size = decode32(d, &i); | ||
1909 | char attr[attr_size * 4 + 1]; | ||
1910 | bin2hex_ascii(attr, d + i, attr_size); i += attr_size; | ||
1911 | unsigned int attr_type = decode32(d, &i); | ||
1912 | uint64_t err = decode64(d, &i); | ||
1913 | char s_htype[32]; | ||
1914 | nd_decode_oci_handle_alloc_type(s_htype, sizeof(s_htype), htype); | ||
1915 | char s_attr_type[32]; | ||
1916 | nd_decode_oci_attr_type(s_attr_type, sizeof(s_attr_type), attr_type); | ||
1917 | int32_t ret = decode32(d, &i); | ||
1918 | sprintf(line, "(h=0x%lx, htype=%s, attr='%s'" | ||
1919 | ", attr_type=%s, err=0x%lx) = %d", | ||
1920 | h, s_htype, attr, s_attr_type, err, ret); | ||
1921 | } else if (strcmp(func, "OCIBindByName") == 0) { | ||
1922 | uint64_t stmt = decode64(d, &i); | ||
1923 | uint64_t bind = decode64(d, &i); | ||
1924 | uint64_t oci_error = decode64(d, &i); | ||
1925 | unsigned int ph_len = decode32(d, &i); | ||
1926 | char ph[ph_len * 4 + 1]; | ||
1927 | bin2hex_ascii(ph, d + i, ph_len); i += ph_len; | ||
1928 | int value_size = decode32(d, &i); | ||
1929 | uint16_t dty = decode16(d, &i); | ||
1930 | uint64_t ind = decode64(d, &i); | ||
1931 | uint64_t alen = decode64(d, &i); | ||
1932 | uint64_t rcode = decode64(d, &i); | ||
1933 | uint32_t maxarr_len = decode32(d, &i); | ||
1934 | uint64_t curelep = decode64(d, &i); | ||
1935 | uint32_t mode = decode32(d, &i); | ||
1936 | int32_t ret = decode32(d, &i); | ||
1937 | char s_dty[32], s_ind[32], s_mode[128], s_ret[32]; | ||
1938 | nd_decode_oci_dty(s_dty, sizeof(s_dty), dty); | ||
1939 | //nd_decode_oci_ind(s_ind, sizeof(s_ind), ind); | ||
1940 | nd_decode_oci_bind_mode(s_mode, sizeof(s_mode), mode); | ||
1941 | nd_decode_oci_ret(s_ret, sizeof(s_ret), ret); | ||
1942 | sprintf(line, "(0x%lx, 0x%lx, 0x%lx, '%s', value, value_size=%d" | ||
1943 | ", dty=%s, ind=0x%lx, alen=0x%lx, rcode=0x%lx, %u, curelep=0x%lx, mode=%s) = %s", | ||
1944 | stmt, bind, oci_error, ph, value_size, | ||
1945 | s_dty, ind, alen, rcode, maxarr_len, curelep, s_mode, s_ret); | ||
1946 | } else if (strcmp(func, "OCIDefineByPos") == 0) { | ||
1947 | uint64_t stmt = decode64(d, &i); | ||
1948 | uint64_t def = decode64(d, &i); | ||
1949 | uint64_t oci_error = decode64(d, &i); | ||
1950 | uint32_t pos = decode32(d, &i); | ||
1951 | int value_size = decode32(d, &i); | ||
1952 | uint16_t dty = decode16(d, &i); | ||
1953 | uint64_t ind = decode64(d, &i); | ||
1954 | uint64_t rlen = decode64(d, &i); | ||
1955 | uint64_t rcode = decode64(d, &i); | ||
1956 | uint32_t mode = decode32(d, &i); | ||
1957 | int32_t ret = decode32(d, &i); | ||
1958 | char s_dty[32], s_ind[32], s_mode[128], s_ret[32]; | ||
1959 | nd_decode_oci_dty(s_dty, sizeof(s_dty), dty); | ||
1960 | //nd_decode_oci_ind(s_ind, sizeof(s_ind), ind); | ||
1961 | nd_decode_oci_bind_mode(s_mode, sizeof(s_mode), mode); | ||
1962 | nd_decode_oci_ret(s_ret, sizeof(s_ret), ret); | ||
1963 | sprintf(line, "(0x%lx, 0x%lx, 0x%lx, pos=%u, value, value_size=%d" | ||
1964 | ", %s, ind=0x%lx, rlen=0x%lx, rcode=0x%lx, mode=%s) = %s", | ||
1965 | stmt, def, oci_error, pos, value_size, | ||
1966 | s_dty, ind, rlen, rcode, s_mode, s_ret); | ||
1967 | } else if (strcmp(func, "OCIHandleAlloc") == 0) { | ||
1968 | uint64_t parent = decode64(d, &i); | ||
1969 | uint64_t dbh = decode64(d, &i); | ||
1970 | uint32_t type = decode32(d, &i); | ||
1971 | size_t extra_mem = decode64(d, &i); | ||
1972 | uint64_t user_mem = decode64(d, &i); | ||
1973 | char s_type[32]; | ||
1974 | nd_decode_oci_handle_alloc_type(s_type, sizeof(s_type), type); | ||
1975 | sprintf(line, "(0x%lx, 0x%lx, %s, %zu, 0x%lx)", | ||
1976 | parent, dbh, s_type, extra_mem, user_mem); | ||
1977 | } else if (strcmp(func, "OCIHandleFree") == 0) { | ||
1978 | uint64_t hnd = decode64(d, &i); | ||
1979 | uint32_t type = decode32(d, &i); | ||
1980 | char s_type[32]; | ||
1981 | nd_decode_oci_handle_alloc_type(s_type, sizeof(s_type), type); | ||
1982 | sprintf(line, "(0x%lx, %s)", hnd, s_type); | ||
1983 | } else if (strcmp(func, "OCIServerAttach") == 0) { | ||
1984 | uint64_t oci_server = decode64(d, &i); | ||
1985 | uint64_t oci_error = decode64(d, &i); | ||
1986 | int32_t db_link_len = decode32(d, &i), a; | ||
1987 | a = db_link_len < 0 ? 0 : db_link_len; | ||
1988 | char db_link[a * 4 + 1]; | ||
1989 | bin2hex_ascii(db_link, d + i, a); i += a; | ||
1990 | uint32_t mode = decode32(d, &i); | ||
1991 | if (type == 'r') | ||
1992 | snprintf(rest, sizeof(rest), " = %d", decode32(d, &i)); | ||
1993 | char s_mode[128]; | ||
1994 | nd_decode_oci_mode(s_mode, sizeof(s_mode), mode); | ||
1995 | sprintf(line, "(0x%lx, 0x%lx, '%s', %d, mode=%s)%s", | ||
1996 | oci_server, oci_error, db_link, db_link_len, s_mode, rest); | ||
1997 | } else if (strcmp(func, "OCIServerDetach") == 0) { | ||
1998 | uint64_t oci_server = decode64(d, &i); | ||
1999 | uint64_t oci_error = decode64(d, &i); | ||
2000 | uint32_t mode = decode32(d, &i); | ||
2001 | if (type == 'r') | ||
2002 | snprintf(rest, sizeof(rest), " = %d", decode32(d, &i)); | ||
2003 | char s_mode[128]; | ||
2004 | nd_decode_oci_mode(s_mode, sizeof(s_mode), mode); | ||
2005 | sprintf(line, "(0x%lx, 0x%lx, mode=%s)%s", | ||
2006 | oci_server, oci_error, s_mode, rest); | ||
2007 | } else if (strcmp(func, "OCIStmtExecute") == 0) { | ||
2008 | //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump); | ||
2009 | if (type == 'm') { | ||
2010 | uint64_t stmt = decode64(d, &i); | ||
2011 | unsigned char bind_way = decode8(d, &i); | ||
2012 | decode_query_params(rest, sizeof(rest), bind_way, d, &i); | ||
2013 | if (bind_way == ND_PARAMS_BIND_WAY_IN) { | ||
2014 | uint16_t q_len = decode16(d, &i); | ||
2015 | char q[q_len * 4 + 1]; | ||
2016 | bin2hex_ascii(q, d + i, q_len); i += q_len; | ||
2017 | sprintf(line, ": meta: stmt=0x%lx: sql: %s", stmt, q); | ||
2018 | if (strcmp(rest, " {}") != 0) | ||
2019 | sprintf(line2, ": meta: stmt=0x%lx: binds:%s", stmt, rest); | ||
2020 | } else { | ||
2021 | sprintf(line, ": meta: stmt=0x%lx: binds:%s", stmt, rest); | ||
2022 | } | ||
2023 | } else { | ||
2024 | uint64_t svc = decode64(d, &i); | ||
2025 | uint64_t stmt = decode64(d, &i); | ||
2026 | uint64_t err = decode64(d, &i); | ||
2027 | uint32_t iters = decode32(d, &i); | ||
2028 | uint32_t rowoff = decode32(d, &i); | ||
2029 | uint64_t snap_in = decode64(d, &i); | ||
2030 | uint64_t snap_out = decode64(d, &i); | ||
2031 | uint32_t mode = decode32(d, &i); | ||
2032 | if (type == 'r') { | ||
2033 | int ret = decode32(d, &i); | ||
2034 | char s_ret[32]; | ||
2035 | nd_decode_oci_ret(s_ret, sizeof(s_ret), ret); | ||
2036 | snprintf(rest, sizeof(rest), " = %s", s_ret); | ||
2037 | } | ||
2038 | char s_mode[128]; | ||
2039 | nd_decode_oci_execute_mode(s_mode, sizeof(s_mode), mode); | ||
2040 | sprintf(line, "(0x%lx, 0x%lx, 0x%lx iters=%u rowoff=%u, 0x%lx, 0x%lx, %s)%s", | ||
2041 | svc, stmt, err, iters, rowoff, snap_in, snap_out, s_mode, rest); | ||
2042 | } | ||
2043 | } else if (strcmp(func, "OCIStmtPrepare") == 0) { | ||
2044 | //char dump[4096]; bin2hex_ascii(dump, d + i, 128); fprintf(outf, "DUMP[%s][%c]: %s\n", func, type, dump); | ||
2045 | uint64_t stmt = decode64(d, &i); | ||
2046 | uint64_t oci_error = decode64(d, &i); | ||
2047 | uint16_t q_len = decode16(d, &i); | ||
2048 | char q[q_len * 4 + 1]; | ||
2049 | bin2hex_ascii(q, d + i, q_len); i += q_len; | ||
2050 | uint32_t lang = decode32(d, &i); | ||
2051 | uint32_t mode = decode32(d, &i); | ||
2052 | int32_t ret = decode32(d, &i); | ||
2053 | char s_lang[32], s_mode[128]; | ||
2054 | nd_decode_oci_lang(s_lang, sizeof(s_lang), lang); | ||
2055 | nd_decode_oci_mode(s_mode, sizeof(s_mode), mode); | ||
2056 | sprintf(line, "(0x%lx, 0x%lx, '%s', %s, mode=%s) = %d", | ||
2057 | stmt, oci_error, q, s_lang, s_mode, ret); | ||
2058 | } else if (strcmp(func, "OCITransCommit") == 0) { | ||
2059 | uint64_t svc = decode64(d, &i); | ||
2060 | uint64_t oci_error = decode64(d, &i); | ||
2061 | uint32_t flags = decode32(d, &i); | ||
2062 | if (type == 'r') { | ||
2063 | int ret = decode32(d, &i); | ||
2064 | char s_ret[32]; | ||
2065 | nd_decode_oci_ret(s_ret, sizeof(s_ret), ret); | ||
2066 | snprintf(rest, sizeof(rest), " = %s", s_ret); | ||
2067 | } | ||
2068 | char s_flags[128]; | ||
2069 | nd_decode_oci_trans_commit_flags(s_flags, sizeof(s_flags), flags); | ||
2070 | sprintf(line, "(0x%lx, 0x%lx, %s)%s", | ||
2071 | svc, oci_error, s_flags, rest); | ||
2072 | } else if (strcmp(func, "OCITransRollback") == 0) { | ||
2073 | uint64_t svc = decode64(d, &i); | ||
2074 | uint64_t oci_error = decode64(d, &i); | ||
2075 | uint32_t flags = decode32(d, &i); | ||
2076 | if (type == 'r') { | ||
2077 | int ret = decode32(d, &i); | ||
2078 | char s_ret[32]; | ||
2079 | nd_decode_oci_ret(s_ret, sizeof(s_ret), ret); | ||
2080 | snprintf(rest, sizeof(rest), " = %s", s_ret); | ||
2081 | } | ||
2082 | char s_flags[128]; | ||
2083 | nd_decode_oci_trans_rollback_flags(s_flags, sizeof(s_flags), flags); | ||
2084 | sprintf(line, "(0x%lx, 0x%lx, %s)%s", | ||
2085 | svc, oci_error, s_flags, rest); | ||
2086 | } else if (strcmp(func, "OCITransStart") == 0) { | ||
2087 | uint64_t svc = decode64(d, &i); | ||
2088 | uint64_t oci_error = decode64(d, &i); | ||
2089 | uint32_t timeout = decode32(d, &i); | ||
2090 | uint32_t flags = decode32(d, &i); | ||
2091 | int ret = decode32(d, &i); | ||
2092 | char s_flags[128], s_ret[32]; | ||
2093 | nd_decode_oci_trans_start_flags(s_flags, sizeof(s_flags), flags); | ||
2094 | nd_decode_oci_ret(s_ret, sizeof(s_ret), ret); | ||
2095 | sprintf(line, "(0x%lx, 0x%lx, %us, %s) = %s", | ||
2096 | svc, oci_error, timeout, s_flags, s_ret); | ||
2097 | } break; | ||
2098 | |||
1426 | 2099 | case 'p': | case 'p': |
1427 | 2100 | if (strcmp(func, "poll") == 0) { | if (strcmp(func, "poll") == 0) { |
1428 | 2101 | uint16_t nf = decode32(d, &i); | uint16_t nf = decode32(d, &i); |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
1514 | 2187 | char q[q_len * 4 + 1]; | char q[q_len * 4 + 1]; |
1515 | 2188 | bin2hex_ascii(q, d + i, q_len); i += q_len; | bin2hex_ascii(q, d + i, q_len); i += q_len; |
1516 | 2189 | if (type == 'c') { | if (type == 'c') { |
1517 | decode_query_params(rest, sizeof(rest), d, &i); | ||
2190 | decode_query_params(rest, sizeof(rest), | ||
2191 | ND_PARAMS_BIND_WAY_BOTH, d, &i); | ||
1518 | 2192 | } else if (type == 'r') { | } else if (type == 'r') { |
1519 | 2193 | uint64_t res = decode64(d, &i); | uint64_t res = decode64(d, &i); |
1520 | 2194 | uint64_t rows = decode64(d, &i); | uint64_t rows = decode64(d, &i); |
... | ... | static void decode_func(const uint32_t parent, unsigned char *d) | |
1864 | 2538 | memset(space, ' ', max); | memset(space, ' ', max); |
1865 | 2539 | space[max] = '\0'; | space[max] = '\0'; |
1866 | 2540 | ||
1867 | if (pid == tid) | ||
1868 | fprintf(outf, "%lu.%03lu %10u%s %s%s\n", | ||
1869 | t / 1000, t % 1000, pid, space, func, line); | ||
1870 | else | ||
1871 | fprintf(outf, "%lu.%03lu %10u %10u%s %s%s\n", | ||
1872 | t / 1000, t % 1000, pid, tid, space, func, line); | ||
2541 | char cfunc[128]; | ||
2542 | if (theme) | ||
2543 | nd_trace_color(cfunc, sizeof(cfunc), func, "func", type, tf, 0); | ||
2544 | |||
2545 | char sts[32], sts2[64]; | ||
2546 | snprintf(sts, sizeof(sts), "%lu.%03lu", t / 1000, t % 1000); | ||
2547 | nd_trace_color(sts2, sizeof(sts2), sts, "ts", '-', "", | ||
2548 | last_ts == 0 ? 0 : t - last_ts); | ||
2549 | |||
2550 | if (pid == tid) { | ||
2551 | fprintf(outf, "%s %10u %s %s%s\n", | ||
2552 | sts2, pid, space, theme ? cfunc : func, line); | ||
2553 | if (line2[0] != '\0') | ||
2554 | fprintf(outf, "%s %10u %s %s%s\n", | ||
2555 | sts2, pid, space, theme ? cfunc : func, line2); | ||
2556 | } else { | ||
2557 | fprintf(outf, "%s %10u %10u %s %s%s\n", | ||
2558 | sts2, pid, tid, space, theme ? cfunc : func, line); | ||
2559 | if (line2[0] != '\0') | ||
2560 | fprintf(outf, "%s %10u %10u %s %s%s\n", | ||
2561 | sts2, pid, tid, space, theme ? cfunc : func, line2); | ||
2562 | } | ||
2563 | |||
2564 | last_ts = t; | ||
1873 | 2565 | } | } |
1874 | 2566 | ||
1875 | 2567 | static void decode(const pid_t parent, unsigned char *d, size_t len) | static void decode(const pid_t parent, unsigned char *d, size_t len) |
... | ... | int main(int argc, char *argv[]) | |
1893 | 2585 | int c, r; | int c, r; |
1894 | 2586 | int options_index = 0; | int options_index = 0; |
1895 | 2587 | char *out_file = NULL; | char *out_file = NULL; |
1896 | pid_t pids[256]; | ||
1897 | 2588 | int sm[256]; | int sm[256]; |
1898 | 2589 | char version[256]; | char version[256]; |
1899 | 2590 | struct shared *shared[256]; | struct shared *shared[256]; |
1900 | unsigned int no_pids = 0; | ||
1901 | 2591 | ||
1902 | 2592 | // Disabling ninedogs.so for the tracer | // Disabling ninedogs.so for the tracer |
1903 | 2593 | int fd = open("/dev/ninedogs", O_WRONLY); | int fd = open("/dev/ninedogs", O_WRONLY); |
... | ... | int main(int argc, char *argv[]) | |
1913 | 2603 | ||
1914 | 2604 | setlinebuf(stderr); | setlinebuf(stderr); |
1915 | 2605 | ||
1916 | while ((c = getopt_long(argc, argv, "p:o:", options, &options_index)) != -1) { | ||
2606 | while ((c = getopt_long(argc, argv, "p:o:Ht:", options, &options_index)) != -1) { | ||
1917 | 2607 | switch (c) { | switch (c) { |
1918 | 2608 | case 'o': out_file = optarg; break; | case 'o': out_file = optarg; break; |
1919 | 2609 | case 'p': if (no_pids < 256) pids[no_pids++] = strtoull(optarg, NULL, 10); break; | case 'p': if (no_pids < 256) pids[no_pids++] = strtoull(optarg, NULL, 10); break; |
2610 | case 'H': only_high_level = 1; break; | ||
2611 | case 't': theme_name = optarg; break; | ||
1920 | 2612 | default: usage(); | default: usage(); |
1921 | 2613 | } | } |
1922 | 2614 | } | } |
... | ... | int main(int argc, char *argv[]) | |
1940 | 2632 | ||
1941 | 2633 | //pid_t my_pid = getpid(); | //pid_t my_pid = getpid(); |
1942 | 2634 | ||
1943 | again: | ||
1944 | for (unsigned i = 0; i < no_pids; i++) { | ||
1945 | if (sm[i] >= 0) | ||
1946 | continue; | ||
1947 | |||
1948 | char name[32]; | ||
1949 | snprintf(name, sizeof(name), "/ninedogs-%d", pids[i]); | ||
1950 | sm[i] = shm_open(name, O_RDWR, 0); | ||
1951 | if (sm[i] == -1) { | ||
1952 | //fprintf(stderr, "%u: Cannot do shm_open: %m\n", pids[i]); | ||
1953 | continue; | ||
1954 | } | ||
1955 | fprintf(stderr, "%u: shm_open returned %d\n", pids[i], sm[i]); | ||
1956 | |||
1957 | shared[i] = mmap(NULL, sizeof(struct shared), | ||
1958 | PROT_READ | PROT_WRITE, MAP_SHARED, sm[i], 0); | ||
1959 | if (shared[i] == MAP_FAILED) { | ||
1960 | //fprintf(stderr, "Cannot mmap i%u: %m\n", i); | ||
1961 | close(sm[i]); | ||
1962 | sm[i] = -1; | ||
1963 | continue; | ||
1964 | } | ||
1965 | |||
1966 | fprintf(stderr, "%u: Attached\n", pids[i]); | ||
1967 | |||
1968 | #if 0 | ||
1969 | unsigned j = 0; | ||
1970 | shared[i]->buf[j++] = SHARED_CMD_INIT; | ||
1971 | shared[i]->buf[j++] = SHARED_VERSION; | ||
1972 | memcpy(shared[i]->buf + j, &my_pid, sizeof(pid_t)); | ||
1973 | j += sizeof(pid_t); | ||
1974 | |||
1975 | r = sem_post(&shared[i]->sem1); | ||
1976 | if (r == -1) { | ||
1977 | fprintf(stderr, "%u: Cannot post sem1: %m\n", pids[i]); | ||
1978 | return 1; | ||
1979 | } | ||
1980 | #endif | ||
1981 | } | ||
2635 | nd_trace_color_set_theme(); | ||
1982 | 2636 | ||
2637 | again: | ||
1983 | 2638 | for (unsigned i = 0; i < no_pids; i++) { | for (unsigned i = 0; i < no_pids; i++) { |
1984 | 2639 | unsigned char *p; | unsigned char *p; |
1985 | unsigned int ava; | ||
2640 | unsigned int ava, head, tail, used; | ||
1986 | 2641 | unsigned char buf[64000]; | unsigned char buf[64000]; |
1987 | 2642 | struct stat s; | struct stat s; |
1988 | 2643 | ||
2644 | if (sm[i] < 0) { | ||
2645 | char name[32]; | ||
2646 | snprintf(name, sizeof(name), "/ninedogs-%d", pids[i]); | ||
2647 | sm[i] = shm_open(name, O_RDWR, 0); | ||
2648 | if (sm[i] == -1) { | ||
2649 | //fprintf(stderr, "%u: Cannot do shm_open: %m\n", pids[i]); | ||
2650 | continue; | ||
2651 | } | ||
2652 | //fprintf(stderr, "%u: shm_open returned %d\n", pids[i], sm[i]); | ||
2653 | |||
2654 | shared[i] = mmap(NULL, sizeof(struct shared), | ||
2655 | PROT_READ | PROT_WRITE, MAP_SHARED, sm[i], 0); | ||
2656 | if (shared[i] == MAP_FAILED) { | ||
2657 | fprintf(stderr, "%u: Cannot mmap: %m\n", pids[i]); | ||
2658 | close(sm[i]); | ||
2659 | sm[i] = -1; | ||
2660 | continue; | ||
2661 | } | ||
2662 | |||
2663 | fprintf(stderr, "%u: attached\n", pids[i]); | ||
2664 | // we use '|' because we may have a concurrent tracer attached | ||
2665 | shared[i]->clients++; | ||
2666 | shared[i]->client_flags |= only_high_level == 1 ? ND_SHARED_ONLY_HIGH_LEVEL : 0; | ||
2667 | } | ||
2668 | |||
1989 | 2669 | if (do_exit == no_pids) { | if (do_exit == no_pids) { |
2670 | shared[i]->clients--; | ||
1990 | 2671 | fprintf(stderr, "Bye!\n"); | fprintf(stderr, "Bye!\n"); |
1991 | 2672 | break; | break; |
1992 | 2673 | } | } |
... | ... | int main(int argc, char *argv[]) | |
2004 | 2685 | return 1; | return 1; |
2005 | 2686 | } | } |
2006 | 2687 | ||
2688 | // Only here we can read 'head' and 'tail' | ||
2689 | head = shared[i]->head; | ||
2690 | tail = shared[i]->tail; | ||
2691 | |||
2007 | 2692 | r = sem_post(&shared[i]->sem1); | r = sem_post(&shared[i]->sem1); |
2008 | 2693 | if (r == -1) { | if (r == -1) { |
2009 | 2694 | fprintf(stderr, "%u: Cannot post sem1: %m\n", pids[i]); | fprintf(stderr, "%u: Cannot post sem1: %m\n", pids[i]); |
... | ... | int main(int argc, char *argv[]) | |
2016 | 2701 | } | } |
2017 | 2702 | ||
2018 | 2703 | // tail-1 points to last value available | // tail-1 points to last value available |
2019 | if (shared[i]->tail == shared[i]->head) | ||
2704 | if (tail == head) | ||
2020 | 2705 | continue; | continue; |
2021 | else if (shared[i]->head < shared[i]->tail) // 01h3t5 => ava = 2 | ||
2022 | ava = shared[i]->tail - shared[i]->head; | ||
2706 | else if (head < tail) // 01h3t5 => ava = 2 | ||
2707 | ava = tail - head; | ||
2023 | 2708 | else // 01t345h78 => ava = 2 + (9 - 6) = 5 | else // 01t345h78 => ava = 2 + (9 - 6) = 5 |
2024 | ava = shared[i]->tail + (shared[i]->buf_size - shared[i]->head); | ||
2709 | ava = tail + (shared[i]->buf_size - head); | ||
2025 | 2710 | ||
2026 | //fprintf(outf, "RING[%u]: head=%u tail=%u new_tail=%u msgs_lost=%u [after lock]\n", | ||
2027 | // i, shared[i]->head, shared[i]->tail, shared[i]->new_tail, shared[i]->msgs_lost); | ||
2711 | //fprintf(outf, "RING[%u]: head=%u tail=%u ava=%u [after lock]\n", | ||
2712 | // i, head, tail, ava); | ||
2028 | 2713 | ||
2029 | 2714 | //char dump[ava * 4 + 1]; | //char dump[ava * 4 + 1]; |
2030 | 2715 | //bin2hex_ascii(dump, shared[i]->buf + shared[i]->head, ava); | //bin2hex_ascii(dump, shared[i]->buf + shared[i]->head, ava); |
2031 | 2716 | //fprintf(outf, "DUMP0[%hu]: %s\n", ava, dump); | //fprintf(outf, "DUMP0[%hu]: %s\n", ava, dump); |
2032 | 2717 | ||
2718 | used = 0; | ||
2033 | 2719 | while (ava >= 2) { | while (ava >= 2) { |
2034 | 2720 | unsigned short plen; | unsigned short plen; |
2035 | 2721 | ||
2036 | 2722 | // TODO: we may have a byte at the end and the other at the beginning! | // TODO: we may have a byte at the end and the other at the beginning! |
2037 | if (shared[i]->buf_size - shared[i]->head == 1) { // ...h size=4 h=3 => max=1 or ..h. max=2 | ||
2723 | if (shared[i]->buf_size - head == 1) { // ...h size=4 h=3 => max=1 or ..h. max=2 | ||
2038 | 2724 | // Split length! | // Split length! |
2039 | plen = shared[i]->buf[shared[i]->head] << 8; | ||
2725 | plen = shared[i]->buf[head] << 8; | ||
2040 | 2726 | plen |= shared[i]->buf[0]; | plen |= shared[i]->buf[0]; |
2041 | 2727 | } else { | } else { |
2042 | memcpy(&plen, shared[i]->buf + shared[i]->head, sizeof(plen)); | ||
2728 | memcpy(&plen, shared[i]->buf + head, sizeof(plen)); | ||
2043 | 2729 | plen = be16toh(plen); | plen = be16toh(plen); |
2044 | 2730 | } | } |
2045 | 2731 | if (plen > ava) { | if (plen > ava) { |
... | ... | int main(int argc, char *argv[]) | |
2048 | 2734 | break; | break; |
2049 | 2735 | } | } |
2050 | 2736 | ||
2051 | if (shared[i]->head + plen <= shared[i]->buf_size) { // dddt...hddd size=11, head=7, plen=4 => 10 <= 11 | ||
2052 | p = shared[i]->buf + shared[i]->head; | ||
2737 | if (head + plen <= shared[i]->buf_size) { // dddt...hddd size=11, head=7, plen=4 => 10 <= 11 | ||
2738 | p = shared[i]->buf + head; | ||
2053 | 2739 | } 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 |
2054 | unsigned int max = shared[i]->buf_size - shared[i]->head; | ||
2740 | unsigned int max = shared[i]->buf_size - head; | ||
2055 | 2741 | if (max > plen) max = plen; | if (max > plen) max = plen; |
2056 | 2742 | //fprintf(outf, " DEBUG: split data. max=%u\n", max); | //fprintf(outf, " DEBUG: split data. max=%u\n", max); |
2057 | 2743 | //fprintf(outf, " DEBUG: copy to buf from %p+%u, %u bytes\n", shared[i]->buf, shared[i]->head, max); | //fprintf(outf, " DEBUG: copy to buf from %p+%u, %u bytes\n", shared[i]->buf, shared[i]->head, max); |
2058 | memcpy(buf, shared[i]->buf + shared[i]->head, max); | ||
2744 | memcpy(buf, shared[i]->buf + head, max); | ||
2059 | 2745 | //fprintf(outf, " DEBUG: copy to buf+%u from %p, %u bytes\n", max, shared[i]->buf, plen - max); | //fprintf(outf, " DEBUG: copy to buf+%u from %p, %u bytes\n", max, shared[i]->buf, plen - max); |
2060 | 2746 | memcpy(buf + max, shared[i]->buf, plen - max); | memcpy(buf + max, shared[i]->buf, plen - max); |
2061 | 2747 | p = buf; | p = buf; |
... | ... | int main(int argc, char *argv[]) | |
2065 | 2751 | char dump[plen * 4 + 1]; | char dump[plen * 4 + 1]; |
2066 | 2752 | bin2hex_ascii(dump, p, plen); | bin2hex_ascii(dump, p, plen); |
2067 | 2753 | fprintf(outf, "%u: DUMP[%hu] head=%u: %s\n", | fprintf(outf, "%u: DUMP[%hu] head=%u: %s\n", |
2068 | pids[i], plen, shared[i]->head, dump); | ||
2754 | pids[i], plen, head, dump); | ||
2069 | 2755 | } | } |
2070 | 2756 | ||
2071 | 2757 | decode(pids[i], p + 2, plen - 2); | decode(pids[i], p + 2, plen - 2); |
2072 | 2758 | ||
2073 | shared[i]->head = (shared[i]->head + plen) % shared[i]->buf_size; | ||
2074 | 2759 | ava -= plen; | ava -= plen; |
2075 | //fprintf(outf, " DEBUG: ava[%u] after substracting plen[%hu]; no_pids=%u\n", ava, plen, no_pids); | ||
2760 | head = (head + plen) % shared[i]->buf_size; | ||
2761 | used += plen; | ||
2762 | //fprintf(outf, " DEBUG: ava[%u] after substracting plen[%hu]; no_pids=%u\n", | ||
2763 | // ava, plen, no_pids); | ||
2764 | } | ||
2765 | |||
2766 | r = sem_wait(&shared[i]->sem1); | ||
2767 | if (r == -1) { | ||
2768 | fprintf(stderr, "%u: Cannot wait for sem1: %m\n", pids[i]); | ||
2769 | return 1; | ||
2770 | } | ||
2771 | |||
2772 | // Only here we can change 'head' | ||
2773 | shared[i]->head = head; | ||
2774 | shared[i]->junk++; | ||
2775 | //fprintf(outf, " DEBUG: shared[%u]->head moved to %u\n", i, shared[i]->head); | ||
2776 | |||
2777 | r = sem_post(&shared[i]->sem1); | ||
2778 | if (r == -1) { | ||
2779 | fprintf(stderr, "%u: Cannot post sem1: %m\n", pids[i]); | ||
2780 | return 1; | ||
2076 | 2781 | } | } |
2077 | 2782 | } | } |
2078 | 2783 | ||
2079 | if (!do_exit) | ||
2784 | if (!do_exit) { | ||
2785 | usleep(100 * 1000); | ||
2080 | 2786 | goto again; | goto again; |
2787 | } | ||
2081 | 2788 | ||
2082 | 2789 | // TODO: print some stats | // TODO: print some stats |
2083 | 2790 | return 0; | return 0; |
File trace/show-colors.c added (mode: 100644) (index 0000000..d978a2e) | |||
1 | #include <stdio.h> | ||
2 | |||
3 | |||
4 | int main(void) | ||
5 | { | ||
6 | printf("256 colors:\n"); | ||
7 | // background | ||
8 | // first 16 are special | ||
9 | for (int i = 0; i < 2; i++) { | ||
10 | for (int j = 0; j < 8; j++) { | ||
11 | int color = i * 8 + j; | ||
12 | printf("\e[48;5;%dm %4d \e[0m", color, color); | ||
13 | } | ||
14 | printf("\n"); | ||
15 | } | ||
16 | for (int i = 16; i < 256; i++) { | ||
17 | printf("\e[48;5;%dm %4d \e[0m", i, i); | ||
18 | if (i % 15 == 0) | ||
19 | printf("\n"); | ||
20 | } | ||
21 | printf("\n"); | ||
22 | |||
23 | // foreground | ||
24 | for (int i = 0; i < 32; i++) { | ||
25 | for (int j = 0; j < 8; j++) { | ||
26 | int color = i * 8 + j; | ||
27 | printf("\e[38;5;%dm %8d \e[0m", color, color); | ||
28 | } | ||
29 | printf("\n"); | ||
30 | } | ||
31 | printf("\n"); | ||
32 | |||
33 | |||
34 | printf("8 colors:\n"); | ||
35 | for (int i = 30; i < 38; i++) | ||
36 | printf("\e[%dm %4d \e[0m", i, i); | ||
37 | printf("\n"); | ||
38 | |||
39 | for (int i = 30; i < 38; i++) | ||
40 | printf("\e[1;%dm %4d \e[0m", i, i); | ||
41 | printf("\n"); | ||
42 | |||
43 | return 0; | ||
44 | } |
File webd/Makefile changed (mode: 100644) (index cd69c58..ad0a3da) | |||
1 | COMMON_H += ../common/ids.h ../common/tools.h ../common/sctools.h stools.h priv.h | ||
2 | OBJS := ../common/tools.o ../common/sctools.o stools.o certs.o | ||
1 | include ../Makefile.common | ||
3 | 2 | ||
4 | CFLAGS += -I../common $(JSON_CFLAGS) | ||
3 | COMMON_H += ../common/ids.h ../common/tools.h ../common/bin2struct.h \ | ||
4 | stools.h priv.h | ||
5 | OBJS := ../common/tools.o ../common/bin2struct.o ../common/bin2json.o \ | ||
6 | stools.o certs.o machines.o data.o | ||
5 | 7 | ||
6 | all: | ||
7 | make -R -C .. webd | ||
8 | CFLAGS += -I../common $(JSON_CFLAGS) | ||
8 | 9 | ||
9 | compile: ninedogs-webd | ||
10 | all: ninedogs-webd | ||
10 | 11 | ||
11 | 12 | stools.o: stools.c $(COMMON_H) | stools.o: stools.c $(COMMON_H) |
12 | 13 | $(CC) $(CFLAGS) -c $< | $(CC) $(CFLAGS) -c $< |
... | ... | stools.o: stools.c $(COMMON_H) | |
14 | 15 | certs.o: certs.c $(COMMON_H) | certs.o: certs.c $(COMMON_H) |
15 | 16 | $(CC) $(CFLAGS) -c $< | $(CC) $(CFLAGS) -c $< |
16 | 17 | ||
18 | machines.o: machines.c $(COMMON_H) | ||
19 | $(CC) $(CFLAGS) -c $< | ||
20 | |||
21 | data.o: data.c $(COMMON_H) ../common/bin2json.h | ||
22 | $(CC) $(CFLAGS) -c $< | ||
23 | |||
17 | 24 | ninedogs-webd: ninedogs-webd.c certs.h $(OBJS) | ninedogs-webd: ninedogs-webd.c certs.h $(OBJS) |
18 | 25 | $(CC) $(CFLAGS) $@.c -o $@ $(OBJS) -lConn -lcap $(LIBS) \ | $(CC) $(CFLAGS) $@.c -o $@ $(OBJS) -lConn -lcap $(LIBS) \ |
19 | 26 | $(JSON_LIBS) $(GNUTLS_LIBS) | $(JSON_LIBS) $(GNUTLS_LIBS) |
... | ... | install: ninedogs-webd | |
25 | 32 | @cp -av webroot $(I_USR_SHARE)/ninedogs | @cp -av webroot $(I_USR_SHARE)/ninedogs |
26 | 33 | @mkdir -pv $(I_USR)/lib/systemd/system | @mkdir -pv $(I_USR)/lib/systemd/system |
27 | 34 | cp -vd *.service $(I_USR)/lib/systemd/system/ | cp -vd *.service $(I_USR)/lib/systemd/system/ |
35 | @systemctl daemon-reload | ||
28 | 36 | ||
29 | 37 | .PHONY: clean | .PHONY: clean |
30 | 38 | clean: | clean: |
File webd/TODO changed (mode: 100644) (index 8148f87..3834693) | |||
20 | 20 | to be able to send the updats. | to be able to send the updats. |
21 | 21 | [ ] Seems I cannot use 'use strict' in init.js because 'wv' wil not be global! | [ ] Seems I cannot use 'use strict' in init.js because 'wv' wil not be global! |
22 | 22 | [ ] We should inform the user if browser time is off from the real time. | [ ] We should inform the user if browser time is off from the real time. |
23 | [ ] Mark expired certificates. | ||
24 | [ ] Mark last use of cached items and evict them. | ||
23 | 25 | [ ] | [ ] |
File webd/certs.c changed (mode: 100644) (index b431d44..910776b) | |||
4 | 4 | ||
5 | 5 | #include "priv.h" | #include "priv.h" |
6 | 6 | #include "tools.h" | #include "tools.h" |
7 | #include "sctools.h" | ||
7 | #include "bin2struct.h" | ||
8 | 8 | #include "stools.h" | #include "stools.h" |
9 | 9 | #include "certs.h" | #include "certs.h" |
10 | 10 | ||
... | ... | static int certs_load_one(struct Conn *C, const char *dir, | |
25 | 25 | if (r == -1) | if (r == -1) |
26 | 26 | return -1; | return -1; |
27 | 27 | ||
28 | r = decode_cert(&cert, data, r); | ||
28 | r = nd_bin2struct_cert(&cert, data, r); | ||
29 | 29 | if (r == -1) | if (r == -1) |
30 | 30 | return -1; | return -1; |
31 | 31 | ||
32 | if (cert.ts < start_from) { | ||
33 | xlog(0, "Ignoring [%s] because cert.ts[%lu] < start_from[%lu]\n", | ||
32 | if (cert.ts <= start_from) { | ||
33 | xlog(100, "Ignoring [%s] because cert.ts[%lu] <= start_from[%lu]\n", | ||
34 | 34 | cert.subj, cert.ts, start_from); | cert.subj, cert.ts, start_from); |
35 | 35 | return 0; | return 0; |
36 | 36 | } | } |
... | ... | int certs_load(struct Conn *C, const unsigned long long start_from, | |
77 | 77 | { | { |
78 | 78 | char path[4096]; | char path[4096]; |
79 | 79 | ||
80 | xlog(0, "%s: loading certs updated after %u...\n", __func__, start_from); | ||
80 | xlog(100, "%s: loading certs updated after %llu...\n", __func__, start_from); | ||
81 | 81 | ||
82 | 82 | *next_start = start_from; | *next_start = start_from; |
83 | 83 | ||
... | ... | int certs_load(struct Conn *C, const unsigned long long start_from, | |
86 | 86 | snprintf(path, sizeof(path), | snprintf(path, sizeof(path), |
87 | 87 | "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x/cert/*", | "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x/cert/*", |
88 | 88 | p->u.uid, p->u.uid >> 8, p->u.uid); | p->u.uid, p->u.uid >> 8, p->u.uid); |
89 | xlog(0, " searching in %s\n", path); | ||
89 | xlog(100, " searching in %s\n", path); | ||
90 | 90 | ||
91 | 91 | glob_t g; | glob_t g; |
92 | 92 | int r = glob(path, GLOB_NOSORT, NULL, &g); | int r = glob(path, GLOB_NOSORT, NULL, &g); |
... | ... | int certs_load(struct Conn *C, const unsigned long long start_from, | |
95 | 95 | return -1; | return -1; |
96 | 96 | } | } |
97 | 97 | ||
98 | xlog(0, "found %u certs\n", g.gl_pathc); | ||
98 | xlog(100, "found %u certs\n", g.gl_pathc); | ||
99 | 99 | int ret = g.gl_pathc; | int ret = g.gl_pathc; |
100 | 100 | for (unsigned i = 0; i < g.gl_pathc; i++) { | for (unsigned i = 0; i < g.gl_pathc; i++) { |
101 | xlog(0, "Found file [%s]\n", g.gl_pathv[i]); | ||
102 | 101 | r = certs_load_one(C, g.gl_pathv[i], start_from, next_start); | r = certs_load_one(C, g.gl_pathv[i], start_from, next_start); |
103 | 102 | if (r == -1) | if (r == -1) |
104 | 103 | ret = -1; | ret = -1; |
File webd/data.c added (mode: 100644) (index 0000000..39ac581) | |||
1 | #include <sys/stat.h> | ||
2 | |||
3 | #include <glob.h> | ||
4 | #include <libgen.h> | ||
5 | #include <time.h> | ||
6 | #include <stdio.h> | ||
7 | |||
8 | #include "priv.h" | ||
9 | #include "tools.h" | ||
10 | #include "sctools.h" | ||
11 | #include "stools.h" | ||
12 | #include "data.h" | ||
13 | #include "bin2json.h" | ||
14 | |||
15 | /* | ||
16 | * Loads one machine | ||
17 | * Returns -1 on error | ||
18 | */ | ||
19 | static int data_load_one(struct Conn *C, char *dir, | ||
20 | const char *machine_id, const unsigned long long hour) | ||
21 | { | ||
22 | xlog(0, "%s: dir=[%s] hour=[%llu]\n", __func__, dir, hour); | ||
23 | |||
24 | do { | ||
25 | char file[16]; | ||
26 | snprintf(file, sizeof(file), "%llu", hour); | ||
27 | |||
28 | struct stat s; | ||
29 | int r = nd_stat_dir_file(&s, dir, file); | ||
30 | if (r == -1) { | ||
31 | xlog(100, " File [%s/%s] not found\n", dir, file); | ||
32 | break; | ||
33 | } | ||
34 | |||
35 | unsigned char *p = malloc(s.st_size); | ||
36 | if (!p) { | ||
37 | xlog(100, " Cannot alloc memory (%zu)!\n", s.st_size); | ||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | r = load_dir_file(p, s.st_size, dir, file); | ||
42 | if (r == -1) { | ||
43 | free(p); | ||
44 | return -1; | ||
45 | } | ||
46 | |||
47 | off_t off = 0; | ||
48 | while (off < s.st_size) { | ||
49 | xlog(0, " %s: off=%zu/%zu\n", __func__, off, s.st_size); | ||
50 | struct json_object *j; | ||
51 | r = nd_bin2json(&j, p + off, s.st_size - off); | ||
52 | if (r <= 0) | ||
53 | break; | ||
54 | off += r; | ||
55 | |||
56 | if (!j) | ||
57 | continue; | ||
58 | |||
59 | const char *sj = json_object_to_json_string(j); // TODO: check error code | ||
60 | char code[64000]; | ||
61 | snprintf(code, sizeof(code), "wv.machines.func.add_data('%s', %s);", | ||
62 | machine_id, sj); | ||
63 | push_code(C, code, "machine-data"); | ||
64 | json_object_put(j); | ||
65 | } | ||
66 | } while (0); | ||
67 | |||
68 | // We need to signal that an hour was sent completely | ||
69 | char code[256]; | ||
70 | snprintf(code, sizeof(code), "wv.machines.func.data_done('%s');", | ||
71 | machine_id); | ||
72 | push_code(C, code, "machine-data-done"); | ||
73 | |||
74 | return 1; | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | * Loads machine data | ||
79 | * Returns 0 on success, -1 on error. | ||
80 | */ | ||
81 | int data_load(struct Conn *C, const char *machine_id, const unsigned long long hour) | ||
82 | { | ||
83 | struct priv *p = Conn_get_private(C); | ||
84 | char dir[4096]; | ||
85 | snprintf(dir, sizeof(dir), | ||
86 | "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x/data/%c%c/%c%c/%s/t", | ||
87 | p->u.uid, p->u.uid >> 8, p->u.uid, | ||
88 | machine_id[0], machine_id[1], machine_id[2], machine_id[3], machine_id); | ||
89 | int r = data_load_one(C, dir, machine_id, hour); | ||
90 | if (r == -1) | ||
91 | return -1; | ||
92 | |||
93 | return 0; | ||
94 | } |
File webd/data.h added (mode: 100644) (index 0000000..030cb66) | |||
1 | #include <Conn.h> | ||
2 | |||
3 | int data_load(struct Conn *C, const char *machine_id, | ||
4 | const unsigned long long hour); |
File webd/machines.TODO added (mode: 100644) (index 0000000..07a3dbb) | |||
1 | [ ] Hierarchy | ||
2 | [ ] A host not yet added may be added to a special list | ||
3 | [ ] |
File webd/machines.c added (mode: 100644) (index 0000000..eb6ad3f) | |||
1 | #include <glob.h> | ||
2 | #include <libgen.h> | ||
3 | #include <time.h> | ||
4 | #include <stdio.h> | ||
5 | |||
6 | #include "priv.h" | ||
7 | #include "tools.h" | ||
8 | #include "sctools.h" | ||
9 | #include "stools.h" | ||
10 | #include "machines.h" | ||
11 | |||
12 | /* | ||
13 | * Loads one machine | ||
14 | * Returns -1 on error | ||
15 | */ | ||
16 | static int machines_load_one(struct Conn *C, char *dir, | ||
17 | const unsigned long long start_from, unsigned long long *next_start) | ||
18 | { | ||
19 | int r; | ||
20 | struct json_object *j; | ||
21 | const char *sj; | ||
22 | unsigned long long first_seen, last_seen; | ||
23 | |||
24 | xlog(0, " %s: dir=[%s]\n", __func__, dir); | ||
25 | |||
26 | r = load_dir_file(&first_seen, sizeof(first_seen), dir, "first_seen"); | ||
27 | if (r == -1) | ||
28 | return -1; | ||
29 | first_seen = be64toh(first_seen); | ||
30 | |||
31 | r = load_dir_file(&last_seen, sizeof(last_seen), dir, "last_seen"); | ||
32 | if (r == -1) | ||
33 | return -1; | ||
34 | last_seen = be64toh(last_seen); | ||
35 | |||
36 | if (first_seen <= start_from) { | ||
37 | xlog(100, " Ignoring because first_seen[%llu] <= start_from[%llu]\n", | ||
38 | first_seen, start_from); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | // TODO: deal with error codes | ||
43 | xlog(0, " Sending [%s]...\n", dir); | ||
44 | j = json_object_new_object(); | ||
45 | if (!j) { | ||
46 | xlog(0, " Cannot alloc memory for answer!\n"); | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | char *id = basename(dir); | ||
51 | json_object_object_add(j, "id", json_object_new_string(id)); | ||
52 | json_object_object_add(j, "first_seen", json_object_new_uint64(first_seen / 1000)); | ||
53 | json_object_object_add(j, "last_seen", json_object_new_uint64(last_seen / 1000)); | ||
54 | sj = json_object_to_json_string(j); | ||
55 | |||
56 | char code[8192]; | ||
57 | snprintf(code, sizeof(code), "wv.machines.func.update(%s);", sj); | ||
58 | push_code(C, code, "machine-update"); | ||
59 | json_object_put(j); | ||
60 | |||
61 | // TODO: not sure this is correct | ||
62 | if (*next_start < first_seen) | ||
63 | *next_start = first_seen; | ||
64 | |||
65 | return 1; | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * Loads machines | ||
70 | * @start_from is used to send only the updates | ||
71 | * Returns number of entries loaded, -1 on error. | ||
72 | */ | ||
73 | int machines_load(struct Conn *C, const unsigned long long start_from, | ||
74 | unsigned long long *next_start) | ||
75 | { | ||
76 | char path[4096]; | ||
77 | |||
78 | xlog(100, "%s: loading machines updated after %u...\n", __func__, start_from); | ||
79 | |||
80 | *next_start = start_from; | ||
81 | |||
82 | struct priv *p = Conn_get_private(C); | ||
83 | |||
84 | snprintf(path, sizeof(path), | ||
85 | "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x/data/*/*/*", | ||
86 | p->u.uid, p->u.uid >> 8, p->u.uid); | ||
87 | xlog(100, " searching in %s\n", path); | ||
88 | |||
89 | glob_t g; | ||
90 | int r = glob(path, GLOB_NOSORT, NULL, &g); | ||
91 | if (r != 0) { | ||
92 | xlog(0, " cannot load machines: %m!\n"); | ||
93 | return -1; | ||
94 | } | ||
95 | |||
96 | xlog(100, " found %u machine(s)\n", g.gl_pathc); | ||
97 | int ret = g.gl_pathc; | ||
98 | for (unsigned i = 0; i < g.gl_pathc; i++) { | ||
99 | xlog(0, " %s: Found file [%s]\n", __func__, g.gl_pathv[i]); | ||
100 | r = machines_load_one(C, g.gl_pathv[i], start_from, next_start); | ||
101 | if (r == -1) | ||
102 | ret = -1; | ||
103 | } | ||
104 | globfree(&g); | ||
105 | |||
106 | return ret; | ||
107 | } |
File webd/machines.h added (mode: 100644) (index 0000000..bc52440) | |||
1 | #include <Conn.h> | ||
2 | |||
3 | int machines_load(struct Conn *C, const unsigned long long start_from, | ||
4 | unsigned long long *next_start); | ||
5 |
File webd/ninedogs-webd.c changed (mode: 100644) (index daa886d..260dd5e) | |||
26 | 26 | #include "tools.h" | #include "tools.h" |
27 | 27 | #include "stools.h" | #include "stools.h" |
28 | 28 | #include "certs.h" | #include "certs.h" |
29 | #include "machines.h" | ||
29 | 30 | ||
30 | 31 | /* Global variables */ | /* Global variables */ |
31 | 32 | unsigned int debug = 3; // recommended 1 for production | unsigned int debug = 3; // recommended 1 for production |
... | ... | static void trigger(struct Conn *C) | |
116 | 117 | push_file(C, DIR "/js/lstate.js"); | push_file(C, DIR "/js/lstate.js"); |
117 | 118 | push_file(C, DIR "/js/estate.js"); | push_file(C, DIR "/js/estate.js"); |
118 | 119 | push_file(C, DIR "/js/grid.js"); | push_file(C, DIR "/js/grid.js"); |
120 | push_file(C, DIR "/js/tab.js"); | ||
119 | 121 | push_file(C, DIR "/js/time.js"); | push_file(C, DIR "/js/time.js"); |
120 | 122 | push_file(C, DIR "/js/certs.js"); | push_file(C, DIR "/js/certs.js"); |
123 | push_file(C, DIR "/js/machines.js"); | ||
124 | //push_file(C, DIR "/js/machine_data.js"); | ||
121 | 125 | push_file(C, DIR "/js/set.js"); | push_file(C, DIR "/js/set.js"); |
122 | 126 | push_file(C, DIR "/js/reports.js"); | push_file(C, DIR "/js/reports.js"); |
123 | 127 | push_file(C, DIR "/js/admin.js"); | push_file(C, DIR "/js/admin.js"); |
... | ... | static void login_save_logout_cookie(struct Conn *C) | |
307 | 311 | "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x/cookies", | "/var/lib/ninedogs/users/by-uid/%02hhx/%02hhx/%08x/cookies", |
308 | 312 | p->u.uid & 0xFF, (p->u.uid >> 8) & 0xFF, p->u.uid); | p->u.uid & 0xFF, (p->u.uid >> 8) & 0xFF, p->u.uid); |
309 | 313 | Log(0, " Saving cookie into [%s]\n", dir); | Log(0, " Saving cookie into [%s]\n", dir); |
310 | mkdir_recursive(dir, 0700); | ||
311 | save_dir_file(dir, p->u.cookie, "", 0); | ||
314 | save_dir_file(dir, p->u.cookie, O_CREAT | O_TRUNC | O_WRONLY, "", 0); | ||
312 | 315 | } while (0); | } while (0); |
313 | 316 | } | } |
314 | 317 | ||
... | ... | static unsigned int settings_save(const char *dir, | |
501 | 504 | { | { |
502 | 505 | int r; | int r; |
503 | 506 | ||
504 | r = save_dir_file(dir, file, value, strlen(value)); | ||
507 | r = save_dir_file(dir, file, O_CREAT | O_TRUNC | O_WRONLY, value, strlen(value)); | ||
505 | 508 | if (r == -1) | if (r == -1) |
506 | 509 | return 0; | return 0; |
507 | 510 | ||
... | ... | static void certs(struct Conn *C, struct json_object *j) | |
596 | 599 | push_code(C, code, "set-answer"); | push_code(C, code, "set-answer"); |
597 | 600 | } | } |
598 | 601 | ||
602 | static void machines(struct Conn *C, struct json_object *j) | ||
603 | { | ||
604 | struct json_object *q; | ||
605 | |||
606 | Log(0, "%llu %s json:\n%s\n", | ||
607 | Conn_get_id(C), __func__, json_object_to_json_string_ext(j, | ||
608 | JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY)); | ||
609 | |||
610 | json_object_object_get_ex(j, "subop", &q); | ||
611 | const char *subop = json_object_get_string(q); | ||
612 | if (!subop) { | ||
613 | Log(0, "\tNo subop! Abort!\n"); | ||
614 | return; | ||
615 | } | ||
616 | |||
617 | json_object_object_get_ex(j, "id", &q); | ||
618 | const char *machine_id = json_object_get_string(q); | ||
619 | |||
620 | json_object_object_get_ex(j, "ts", &q); | ||
621 | const unsigned long long ts = json_object_get_uint64(q); | ||
622 | |||
623 | Log(0, "%llu %s subop %s\n", Conn_get_id(C), __func__, subop); | ||
624 | if (strcmp(subop, "send-data") == 0) { | ||
625 | if (!machine_id || !ts) { | ||
626 | Log(0, "%s: No machine_id or ts!\n", __func__); | ||
627 | return; | ||
628 | } | ||
629 | data_load(C, machine_id, get_hour(ts)); // TODO: check error code | ||
630 | return; | ||
631 | } else { | ||
632 | Log(0, "Unknown subop!\n"); | ||
633 | } | ||
634 | } | ||
635 | |||
599 | 636 | /* | /* |
600 | 637 | * Processing estate from clients | * Processing estate from clients |
601 | 638 | */ | */ |
602 | 639 | static void estate(struct Conn *C, struct json_object *j) | static void estate(struct Conn *C, struct json_object *j) |
603 | 640 | { | { |
604 | struct json_object *q; | ||
641 | struct json_object *q, *data; | ||
642 | char code[512]; | ||
605 | 643 | ||
606 | Log(0, "%llu %s json:\n%s\n", | ||
607 | Conn_get_id(C), __func__, json_object_to_json_string_ext(j, | ||
644 | Log(0, "%llu %s: json:\n%s\n", | ||
645 | Conn_get_id(C), __func__, | ||
646 | json_object_to_json_string_ext(j, | ||
608 | 647 | JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY)); | JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY)); |
609 | 648 | ||
610 | json_object_object_get_ex(j, "files", &q); | ||
649 | json_object_object_get_ex(j, "data", &data); | ||
650 | |||
651 | json_object_object_get_ex(data, "files", &q); | ||
611 | 652 | const char *files = json_object_get_string(q); | const char *files = json_object_get_string(q); |
612 | 653 | if (files) { | if (files) { |
613 | 654 | Log(0, "\testate: files: %s!\n", files); | Log(0, "\testate: files: %s!\n", files); |
614 | 655 | } | } |
615 | 656 | ||
616 | 657 | unsigned long long start_from = 0, next_start; | unsigned long long start_from = 0, next_start; |
617 | json_object_object_get_ex(j, "certs", &q); | ||
658 | json_object_object_get_ex(data, "certs", &q); | ||
618 | 659 | const char *certs = json_object_get_string(q); | const char *certs = json_object_get_string(q); |
619 | 660 | if (certs) { | if (certs) { |
620 | 661 | start_from = strtoull(certs, NULL, 10); | start_from = strtoull(certs, NULL, 10); |
... | ... | static void estate(struct Conn *C, struct json_object *j) | |
623 | 664 | int r = certs_load(C, start_from, &next_start); | int r = certs_load(C, start_from, &next_start); |
624 | 665 | // TODO: what to do in case of errors? | // TODO: what to do in case of errors? |
625 | 666 | // We should notify the client that is not ok yet. | // We should notify the client that is not ok yet. |
626 | char code[512]; | ||
627 | 667 | if (r >= 0) | if (r >= 0) |
628 | 668 | snprintf(code, sizeof(code), | snprintf(code, sizeof(code), |
629 | 669 | "wv.estate.func.update('certs', '%llu');" | "wv.estate.func.update('certs', '%llu');" |
... | ... | static void estate(struct Conn *C, struct json_object *j) | |
633 | 673 | snprintf(code, sizeof(code), | snprintf(code, sizeof(code), |
634 | 674 | "wv.lstate.func.update('certs-ok', 0);"); | "wv.lstate.func.update('certs-ok', 0);"); |
635 | 675 | push_code(C, code, "certs-ok"); | push_code(C, code, "certs-ok"); |
676 | |||
677 | json_object_object_get_ex(data, "machines", &q); | ||
678 | const char *machines = json_object_get_string(q); | ||
679 | if (machines) { | ||
680 | start_from = strtoull(machines, NULL, 10); | ||
681 | Log(0, "\testate: machines: start_from=%llu!\n", start_from); | ||
682 | } | ||
683 | r = machines_load(C, start_from, &next_start); | ||
684 | // TODO: what to do in case of errors? | ||
685 | // We should notify the client that is not ok yet. | ||
686 | if (r >= 0) | ||
687 | snprintf(code, sizeof(code), | ||
688 | "wv.estate.func.update('machines', '%llu');" | ||
689 | "wv.lstate.func.update('machines-ok', 1);", | ||
690 | next_start); | ||
691 | else | ||
692 | snprintf(code, sizeof(code), | ||
693 | "wv.lstate.func.update('machines-ok', 0);"); | ||
694 | push_code(C, code, "machines-ok"); | ||
636 | 695 | } | } |
637 | 696 | ||
638 | 697 | static void process_json(struct Conn *C, struct json_object *j) | static void process_json(struct Conn *C, struct json_object *j) |
... | ... | static void process_json(struct Conn *C, struct json_object *j) | |
766 | 825 | return; | return; |
767 | 826 | } | } |
768 | 827 | ||
828 | if (strcmp(s_op, "machines") == 0) { | ||
829 | machines(C, j); | ||
830 | json_object_put(answer); | ||
831 | return; | ||
832 | } | ||
833 | |||
769 | 834 | if (strcmp(s_op, "estate") == 0) { | if (strcmp(s_op, "estate") == 0) { |
770 | 835 | estate(C, j); | estate(C, j); |
771 | 836 | json_object_put(answer); | json_object_put(answer); |
... | ... | static void process_json(struct Conn *C, struct json_object *j) | |
778 | 843 | return; | return; |
779 | 844 | } | } |
780 | 845 | ||
781 | Log(0, "\tInvalid operation [%s]!\n", s_op); | ||
846 | Log(0, "\t%s: Invalid operation [%s]!\n", __func__, s_op); | ||
782 | 847 | json_object_put(answer); | json_object_put(answer); |
783 | 848 | } | } |
784 | 849 |
File webd/ninedogs-webd.service changed (mode: 100644) (index f57aec8..2bf43a8) | |||
1 | 1 | [Unit] | [Unit] |
2 | Description=Ninedogs Websocket daemon | ||
2 | Description = Ninedogs Websocket daemon | ||
3 | 3 | ||
4 | 4 | [Service] | [Service] |
5 | Type=exec | ||
6 | ExecStart=/date/sync/no-crypt/sync1/Dev/ninedogs/webd/ninedogs-webd | ||
7 | #User=rocketgit | ||
8 | #Group=rocketgit | ||
9 | PrivateTmp=true | ||
10 | Restart=on-failure | ||
11 | RestartSec=10 | ||
12 | ProtectSystem=full | ||
13 | NoNewPrivileges=yes | ||
5 | Type = exec | ||
6 | ExecStart = /date/sync/no-crypt/sync1/Dev/ninedogs/webd/ninedogs-webd | ||
7 | PrivateTmp = true | ||
8 | Restart = on-failure | ||
9 | RestartSec = 10 | ||
10 | ProtectSystem = full | ||
11 | NoNewPrivileges = yes | ||
12 | User = ninedogs | ||
13 | Group = ninedogs | ||
14 | 14 | ||
15 | 15 | [Install] | [Install] |
16 | WantedBy=multi-user.target | ||
16 | WantedBy = multi-user.target |
File webd/webroot/index.html changed (mode: 100644) (index cb1dafc..6666fe3) | |||
9 | 9 | <link rel="stylesheet" href="main.css"> | <link rel="stylesheet" href="main.css"> |
10 | 10 | </head> | </head> |
11 | 11 | ||
12 | <body onLoad="my_start()"> | ||
13 | |||
14 | 12 | <!-- | <!-- |
15 | 13 | // This file is part of ninedogs project | // This file is part of ninedogs project |
16 | 14 | // Copyright: Catalin(ux) M. BOIE | // Copyright: Catalin(ux) M. BOIE |
17 | 15 | --> | --> |
18 | 16 | ||
19 | <!-- <span id="app_status">Unknown queue status</span> --> | ||
20 | <span id="my_status">Unknown status</span> | ||
21 | <span id="add_status">-</span> | ||
22 | |||
23 | |||
24 | <div id="main_menu" class="menu">?</div> | ||
17 | <body onLoad="my_start()"> | ||
18 | <div id="main_menu" class="menu">?</div> | ||
25 | 19 | ||
26 | <div id="body" class="content">?</div> | ||
20 | <div id="my_body">?</div> | ||
27 | 21 | ||
28 | <br /> | ||
29 | <div class="bottom"> | ||
30 | <small>Copyright: Catalin(ux) M. BOIE</small> | ||
31 | </div> | ||
22 | <div id="my_status">Unknown status</div> | ||
23 | <div id="add_status">-</div> | ||
32 | 24 | ||
33 | <details> | ||
34 | <summary>Debug</summary> | ||
35 | <div id="debug"></div> | ||
36 | </details> | ||
25 | <div class="bottom"> | ||
26 | <small>Copyright: Catalin(ux) M. BOIE</small> | ||
27 | </div> | ||
37 | 28 | ||
29 | <div> | ||
30 | <details> | ||
31 | <summary>Debug</summary> | ||
32 | <div id="debug"></div> | ||
33 | </details> | ||
34 | </div> | ||
38 | 35 | </body> | </body> |
39 | 36 | ||
40 | 37 | </html> | </html> |
File webd/webroot/js/certs.js changed (mode: 100644) (index 69716cf..870f463) | |||
... | ... | wv.certs.func.main = function() | |
65 | 65 | // Called by server to add an cert | // Called by server to add an cert |
66 | 66 | wv.certs.func.update = function(i) | wv.certs.func.update = function(i) |
67 | 67 | { | { |
68 | wv.debug('certs.func.update...'); | ||
68 | //wv.debug('certs.func.update...'); | ||
69 | 69 | certs = wv.conf.func.load('certs'); | certs = wv.conf.func.load('certs'); |
70 | 70 | if (typeof certs.list === 'undefined') | if (typeof certs.list === 'undefined') |
71 | 71 | certs.list = {}; | certs.list = {}; |
File webd/webroot/js/grid.js changed (mode: 100644) (index 87c209e..571cdab) | |||
... | ... | wv.grid.func.drop = function(e) | |
111 | 111 | const a = src_id.split('/'); | const a = src_id.split('/'); |
112 | 112 | ||
113 | 113 | const what = a[0]; | const what = a[0]; |
114 | data = wv.conf.func.load(what); | ||
114 | var data = wv.conf.func.load(what); | ||
115 | 115 | if (typeof data === 'undefined') | if (typeof data === 'undefined') |
116 | 116 | return; | return; |
117 | 117 | ||
... | ... | wv.grid.func.drop = function(e) | |
134 | 134 | */ | */ |
135 | 135 | wv.grid.func.display = function(what) | wv.grid.func.display = function(what) |
136 | 136 | { | { |
137 | wv.debug('grid.func.display'); | ||
137 | wv.debug('grid.func.display what=' + what); | ||
138 | 138 | ||
139 | 139 | data = wv.conf.func.load(what); | data = wv.conf.func.load(what); |
140 | 140 | if (typeof data === 'undefined') { | if (typeof data === 'undefined') { |
141 | 141 | wv.debug('data for ' + what + ' is not defined'); | wv.debug('data for ' + what + ' is not defined'); |
142 | 142 | return; | return; |
143 | 143 | } | } |
144 | if (typeof data.events === 'undefined') | ||
145 | data.events = {} | ||
146 | |||
144 | 147 | var div = document.getElementById(data.target_div); | var div = document.getElementById(data.target_div); |
148 | if (!div) { | ||
149 | console.log('cannot find div [' + data.target_div + ']'); | ||
150 | return; | ||
151 | } | ||
145 | 152 | ||
146 | 153 | if (typeof data.list === 'undefined') { | if (typeof data.list === 'undefined') { |
147 | 154 | if (typeof data.text_no_data === 'undefined') | if (typeof data.text_no_data === 'undefined') |
... | ... | wv.grid.func.display = function(what) | |
171 | 178 | var tr = thead.insertRow(); | var tr = thead.insertRow(); |
172 | 179 | if (typeof data.fields_order === 'undefined') | if (typeof data.fields_order === 'undefined') |
173 | 180 | data.fields_order = Object.keys(data.fields); | data.fields_order = Object.keys(data.fields); |
181 | console.log('data.fields_order='); console.log(data.fields_order); | ||
174 | 182 | // TODO: if the server pushes more fields, we must refresh data.fields_order | // TODO: if the server pushes more fields, we must refresh data.fields_order |
175 | 183 | data.fields_order.forEach((f, junk) => { | data.fields_order.forEach((f, junk) => { |
176 | 184 | var th = document.createElement('th'); | var th = document.createElement('th'); |
... | ... | wv.grid.func.display = function(what) | |
193 | 201 | si.style.color = 'white'; | si.style.color = 'white'; |
194 | 202 | si.style.backgroundColor = 'red'; | si.style.backgroundColor = 'red'; |
195 | 203 | si.style.float = 'right'; | si.style.float = 'right'; |
204 | si.style.cursor = 'pointer'; | ||
196 | 205 | if ((typeof data.sort_info[f] === 'undefined') | if ((typeof data.sort_info[f] === 'undefined') |
197 | 206 | || (data.sort_info[f].order == 0)) { | || (data.sort_info[f].order == 0)) { |
198 | 207 | x = ''; | x = ''; |
... | ... | wv.grid.func.display = function(what) | |
213 | 222 | var tbody = t.createTBody(); | var tbody = t.createTBody(); |
214 | 223 | data.sort_keys.forEach((key, index) => { | data.sort_keys.forEach((key, index) => { |
215 | 224 | var tr = tbody.insertRow(); | var tr = tbody.insertRow(); |
225 | tr.id = what + '/' + key + '/tr'; | ||
226 | if (typeof data.events.row_click !== 'undefined') { | ||
227 | tr.style.cursor = 'pointer'; | ||
228 | tr.onclick = function() { data.events.row_click.func(this.id); }; | ||
229 | } | ||
230 | |||
216 | 231 | data.fields_order.forEach((f, junk) => { | data.fields_order.forEach((f, junk) => { |
217 | 232 | var td = tr.insertCell(); | var td = tr.insertCell(); |
218 | 233 | td.style.border = '1px solid black'; | td.style.border = '1px solid black'; |
... | ... | wv.grid.func.display = function(what) | |
228 | 243 | }); | }); |
229 | 244 | t.appendChild(tbody); | t.appendChild(tbody); |
230 | 245 | ||
231 | try { | ||
232 | div.removeChild(div.children[0]); | ||
233 | } catch (e) {} | ||
234 | div.appendChild(t); | ||
246 | div.replaceChildren(t); | ||
235 | 247 | } | } |
236 | 248 |
File webd/webroot/js/machine_data.js added (mode: 100644) (index 0000000..66cd94b) | |||
1 | // machine_data.js | ||
2 | |||
3 | wv.module.func.load('conf'); | ||
4 | wv.module.func.load('time'); | ||
5 | wv.module.func.load('grid'); | ||
6 | wv.module.func.load('tab'); | ||
7 | |||
8 | try { | ||
9 | |||
10 | if (typeof wv.machine_data === 'undefined') | ||
11 | wv.machine_data = {}; | ||
12 | if (typeof wv.machine_data.html === 'undefined') | ||
13 | wv.machine_data.html = {}; | ||
14 | if (typeof wv.machine_data.func === 'undefined') | ||
15 | wv.machine_data.func = {}; | ||
16 | if (typeof wv.machine_data.queue === 'undefined') | ||
17 | wv.machine_data.queue = {}; | ||
18 | |||
19 | wv.machine_data.html.main = ` | ||
20 | <!-- <b>List of machine_data</b> | ||
21 | <div id="machine_data_list"></div> --> | ||
22 | <div id="machine_data_tabs" class="flex1" style="flex-grow: 1"></div> | ||
23 | `; | ||
24 | |||
25 | // === Functions === | ||
26 | |||
27 | wv.machine_data.func.render_type = function(t) | ||
28 | { | ||
29 | if (t == "O") | ||
30 | return "OpenSSL"; | ||
31 | else if (t == "G") | ||
32 | return "GnuTLS"; | ||
33 | else if (t == "J") | ||
34 | return "Java"; | ||
35 | |||
36 | return t; | ||
37 | } | ||
38 | |||
39 | wv.machine_data.func.machine_body = function(name, pos, o) | ||
40 | { | ||
41 | console.log('machine_body: name=' + name + ' pos=' + pos); | ||
42 | |||
43 | const id = name + '/' + pos + '/b'; | ||
44 | var div = document.getElementById(id); | ||
45 | if (!div) { | ||
46 | console.log(' DEBUG: div with id ' + id + ' not found'); | ||
47 | return; | ||
48 | } | ||
49 | div.innerHTML = 'Machine ' + o.name + '<br />' | ||
50 | + '<pre>' + JSON.stringify(o) + '</pre>'; | ||
51 | |||
52 | // Requesting data | ||
53 | // TODO: check if is cached first! In a generic way. | ||
54 | const j = { | ||
55 | op: 'machine_data', | ||
56 | subop: 'send-data', | ||
57 | id: o.name, | ||
58 | ts: Math.trunc(Date.now() / 1000) | ||
59 | }; | ||
60 | wv.util.send(JSON.stringify(j)); | ||
61 | } | ||
62 | |||
63 | wv.machine_data.func.machine_click = function(id) | ||
64 | { | ||
65 | console.log('machine_click: id=' + id); | ||
66 | const a = id.split('/'); | ||
67 | const what = a[0]; | ||
68 | const machine_id = a[1]; | ||
69 | const o = { name: machine_id, func: wv.machine_data.func.machine_body }; | ||
70 | wv.tab.func.add_tab(what, o); | ||
71 | } | ||
72 | |||
73 | wv.machine_data.func.list_machine_data = function(name, o) | ||
74 | { | ||
75 | console.log('func.list_machine_data: name=' + name); | ||
76 | |||
77 | machine_data = wv.conf.func.load(name); | ||
78 | machine_data.target_div = 'machine_data_list'; | ||
79 | machine_data.fields = { | ||
80 | id: { name: 'ID' }, | ||
81 | first_seen: { name: 'First seen', render: wv.time.func.render_ts }, | ||
82 | last_seen: { name: 'Last seen', render: wv.time.func.render_ts } | ||
83 | }; | ||
84 | machine_data.sort_info = { | ||
85 | id: { order: 1 } | ||
86 | }; | ||
87 | machine_data.events = { | ||
88 | row_click: { func: wv.machine_data.func.machine_click } | ||
89 | }; | ||
90 | machine_data.text_no_data = 'No machine_data found.'; | ||
91 | wv.grid.func.display(name); | ||
92 | } | ||
93 | |||
94 | wv.machine_data.func.show_machine_data = function() | ||
95 | { | ||
96 | machine_data = { | ||
97 | name: 'machine_data', | ||
98 | target_div: 'machine_data_tabs', | ||
99 | tabs: [ | ||
100 | { | ||
101 | name: 'machine_data', | ||
102 | body: '<div id="machine_data_list" />', | ||
103 | func: wv.machine_data.func.list_machine_data, | ||
104 | func_para: 'machine_data', | ||
105 | can_be_closed: 0 | ||
106 | } | ||
107 | ], | ||
108 | style: { | ||
109 | main_class: 'flex1', | ||
110 | main: [ | ||
111 | { name: 'display', value: 'flex' }, | ||
112 | { name: 'flex-direction', value: 'column' } | ||
113 | ], | ||
114 | body_group_class: 'flex1', | ||
115 | body_group: [ | ||
116 | { name: 'flex-grow', value: '1' } | ||
117 | ], | ||
118 | body: [ | ||
119 | { name: 'flex-grow', value: '1' } | ||
120 | ] | ||
121 | } | ||
122 | }; | ||
123 | wv.tab.func.display(machine_data); | ||
124 | // TODO: move flex stuff in 'tab.js' and remove it from here. | ||
125 | } | ||
126 | |||
127 | // This is called when 'machine_data' menu is clicked | ||
128 | wv.machine_data.func.main = function() | ||
129 | { | ||
130 | if (wv.login.ok != 1) { | ||
131 | div_body.innerHTML = 'You must login.'; | ||
132 | return; | ||
133 | } | ||
134 | |||
135 | div_body.innerHTML = wv.machine_data.html.main; | ||
136 | wv.machine_data.func.show_machine_data(); | ||
137 | } | ||
138 | |||
139 | // Called by server to add an cert | ||
140 | wv.machine_data.func.update = function(machine_id, j) | ||
141 | { | ||
142 | //wv.debug('machine_data.func.update: machine_id=' + machine_id); | ||
143 | //console.log(j); | ||
144 | |||
145 | var job = wv.machines.jobs[machine_id]; | ||
146 | if (typeof job.data === 'undefined') | ||
147 | job.data = {}; | ||
148 | const ts = j.ts; | ||
149 | delete j.ts; | ||
150 | job.data[ts] = j; | ||
151 | // TODO: save data in cache | ||
152 | // Requesting previous date | ||
153 | job.end -= 24 * 3600; | ||
154 | job.status = 1; | ||
155 | wv.machines.func.process_jobs(); | ||
156 | } | ||
157 | |||
158 | wv.machine_data.func.update_answer = function(status, msg) | ||
159 | { | ||
160 | wv.debug('machine_data.func.update_answer status=' + status + ' msg=' + msg); | ||
161 | |||
162 | if (status == 1) { // ok | ||
163 | var b = document.getElementById('set_status_ok'); | ||
164 | } else { | ||
165 | var b = document.getElementById('set_status_err'); | ||
166 | } | ||
167 | b.innerHTML = msg; | ||
168 | |||
169 | return true; | ||
170 | } | ||
171 | |||
172 | wv.machine_data.func.init = function() | ||
173 | { | ||
174 | } | ||
175 | |||
176 | } catch (e) { | ||
177 | console.log('machine_data.js exception: ' + e); | ||
178 | } |
File webd/webroot/js/machines.js added (mode: 100644) (index 0000000..5ac6b4c) | |||
1 | // machines.js | ||
2 | |||
3 | wv.module.func.load('conf'); | ||
4 | wv.module.func.load('time'); | ||
5 | wv.module.func.load('grid'); | ||
6 | wv.module.func.load('tab'); | ||
7 | |||
8 | try { | ||
9 | |||
10 | if (typeof wv.machines === 'undefined') | ||
11 | wv.machines = {}; | ||
12 | if (typeof wv.machines.html === 'undefined') | ||
13 | wv.machines.html = {}; | ||
14 | if (typeof wv.machines.func === 'undefined') | ||
15 | wv.machines.func = {}; | ||
16 | |||
17 | if (typeof wv.machines.jobs === 'undefined') | ||
18 | wv.machines.jobs = {}; | ||
19 | |||
20 | wv.machines.html.main = ` | ||
21 | <!-- <b>List of machines</b> | ||
22 | <div id="machines_list"></div> --> | ||
23 | <div id="machines_tabs" class="flex1" style="flex-grow: 1"></div> | ||
24 | `; | ||
25 | |||
26 | // === Functions === | ||
27 | |||
28 | wv.machines.func.render_type = function(t) | ||
29 | { | ||
30 | if (t == "O") | ||
31 | return "OpenSSL"; | ||
32 | else if (t == "G") | ||
33 | return "GnuTLS"; | ||
34 | else if (t == "J") | ||
35 | return "Java"; | ||
36 | |||
37 | return t; | ||
38 | } | ||
39 | |||
40 | wv.machines.func.draw_one = function(job, x, y1, y2, color) | ||
41 | { | ||
42 | job.ctx.beginPath(); | ||
43 | job.ctx.moveTo(x + 0, y1); | ||
44 | job.ctx.lineTo(x + 0, y2); | ||
45 | job.ctx.lineTo(x + 2, y2); | ||
46 | job.ctx.lineTo(x + 2, y1); | ||
47 | job.ctx.closePath(); | ||
48 | job.ctx.fillStyle = color; | ||
49 | job.ctx.fill(); | ||
50 | //job.ctx.lineWidth = 1; | ||
51 | //job.ctx.stroke(); | ||
52 | } | ||
53 | |||
54 | wv.machines.func.draw_graph = function(job) | ||
55 | { | ||
56 | console.log('func.draw_graph'); | ||
57 | |||
58 | job.ctx.clearRect(0, 0, job.canvas.width, job.canvas.height); | ||
59 | |||
60 | const keys = Object.keys(job.data); | ||
61 | const one_graph_height = 100; | ||
62 | const space_between_graphs = 30; | ||
63 | |||
64 | // Compute maximums | ||
65 | var count = 0; | ||
66 | var max = {}; | ||
67 | keys.forEach((ts, junk) => { | ||
68 | const metrics = Object.keys(job.data[ts]); | ||
69 | metrics.forEach((k, junk) => { | ||
70 | if (typeof max[k] === 'undefined') | ||
71 | max[k] = job.data[ts][k]; | ||
72 | else if (max[k] < job.data[ts][k]) | ||
73 | max[k] = job.data[ts][k]; | ||
74 | }); | ||
75 | count++; | ||
76 | }); | ||
77 | console.log('max: ' + JSON.stringify(max)); | ||
78 | |||
79 | // Compute factors | ||
80 | const factor = {}; | ||
81 | Object.keys(max).forEach((k, junk) => { | ||
82 | factor[k] = max[k] / one_graph_height; | ||
83 | }); | ||
84 | console.log('factor: ' + JSON.stringify(factor)); | ||
85 | |||
86 | // Draw rectangles around graphics | ||
87 | pos = 1; | ||
88 | var x = job.canvas.width - 20; | ||
89 | Object.keys(max).forEach((k, junk) => { | ||
90 | const y1 = 10 + pos * (one_graph_height + space_between_graphs); | ||
91 | const y2 = y1 - one_graph_height; | ||
92 | job.ctx.font = "13pt Arial"; | ||
93 | job.ctx.fillStyle = 'red'; | ||
94 | job.ctx.fillText(k, 11, y2 - 5); | ||
95 | job.ctx.beginPath(); | ||
96 | job.ctx.moveTo(0 + 10, y1); | ||
97 | job.ctx.lineTo(0 + 10, y2); | ||
98 | job.ctx.lineTo(x + 10, y2); | ||
99 | job.ctx.lineTo(x + 10, y1); | ||
100 | job.ctx.closePath(); | ||
101 | job.ctx.fillStyle = 'black'; | ||
102 | job.ctx.fill(); | ||
103 | pos++; | ||
104 | }); | ||
105 | |||
106 | for (i = 0; i < keys.length; i++) { | ||
107 | var ts = keys[i]; // milliseconds | ||
108 | var x = 10 + Math.trunc((ts / 1000 - job.start) / 60) * 3; | ||
109 | pos = 1; | ||
110 | Object.keys(max).forEach((k, junk) => { | ||
111 | const h = Math.trunc(job.data[ts][k] / factor[k]); | ||
112 | const y1 = 10 + pos * (one_graph_height + space_between_graphs); | ||
113 | const y2 = y1 - h; | ||
114 | wv.machines.func.draw_one(job, x, y1, y2, '#0f0'); | ||
115 | pos++; | ||
116 | }); | ||
117 | //console.log('ts=' + ts + ' start=' + job.start + ' h=' + h + ' x=' + x + ' y2=' + y2); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | wv.machines.func.process_job = function(job) | ||
122 | { | ||
123 | console.log('job.status=' + job.status); | ||
124 | |||
125 | if (job.status == 0) { | ||
126 | console.log('preparing canvas...'); | ||
127 | job.canvas = document.getElementById(job.canvas_id); | ||
128 | job.canvas.width = 1200; | ||
129 | job.canvas.height = 2000; | ||
130 | job.canvas.style.backgroundColor = '#eee'; | ||
131 | job.ctx = job.canvas.getContext('2d'); | ||
132 | //job.ctx.beginPath(); | ||
133 | //job.ctx.moveTo(25, 25); | ||
134 | //job.ctx.lineTo(105, 50); | ||
135 | //job.ctx.lineTo(105, 150); | ||
136 | //job.ctx.fill(); | ||
137 | job.data = {}; | ||
138 | job.status = 1; | ||
139 | } | ||
140 | if (job.status == 1) { | ||
141 | if (job.start > job.end) { // we have all data | ||
142 | console.log('We have all data!'); | ||
143 | job.status = 2; | ||
144 | //console.log('job.data:' + JSON.stringify(job.data)); | ||
145 | wv.machines.func.draw_graph(job); | ||
146 | } else { | ||
147 | console.log('requesting ts ' + job.end + ' (start=' + job.start + ') diff=' + (job.end - job.start)); | ||
148 | // TODO: check if is cached first! In a generic way. | ||
149 | const json = { | ||
150 | op: 'machines', | ||
151 | subop: 'send-data', | ||
152 | id: job.id, | ||
153 | ts: job.end | ||
154 | }; | ||
155 | wv.util.send(JSON.stringify(json)); | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | |||
160 | wv.machines.func.add_data = function(machine_id, j) | ||
161 | { | ||
162 | wv.debug('machines.func.add_data: machine_id=' + machine_id); | ||
163 | //console.log(j); | ||
164 | |||
165 | var job = wv.machines.jobs[machine_id]; | ||
166 | const ts = j.ts; | ||
167 | delete j.ts; | ||
168 | if (ts >= job.start * 1000) | ||
169 | job.data[ts] = j; | ||
170 | // TODO: save data in cache | ||
171 | } | ||
172 | |||
173 | wv.machines.func.data_done = function(machine_id) | ||
174 | { | ||
175 | wv.debug('machines.func.data_done: machine_id=' + machine_id); | ||
176 | |||
177 | var job = wv.machines.jobs[machine_id]; | ||
178 | |||
179 | // Progress bar | ||
180 | job.ctx.clearRect(0, 0, job.canvas.width, job.canvas.height); | ||
181 | job.ctx.beginPath(); | ||
182 | job.ctx.moveTo(10, 10); | ||
183 | job.ctx.lineTo(5 * Object.keys(job.data).length, 10); | ||
184 | job.ctx.lineTo(5 * Object.keys(job.data).length, 15); | ||
185 | job.ctx.lineTo(10, 15); | ||
186 | job.ctx.closePath(); | ||
187 | job.ctx.fillStyle = 'yellow'; | ||
188 | job.ctx.fill(); | ||
189 | job.ctx.lineWidth = 1; | ||
190 | job.ctx.stroke(); | ||
191 | |||
192 | job.end -= 3600; | ||
193 | job.status = 1; | ||
194 | wv.machines.func.process_job(job); | ||
195 | } | ||
196 | |||
197 | wv.machines.func.machine_body = function(name, pos, o) | ||
198 | { | ||
199 | console.log('machine_body: name=' + name + ' pos=' + pos); | ||
200 | |||
201 | const id = name + '/' + pos + '/b'; | ||
202 | var div = document.getElementById(id); | ||
203 | if (!div) { | ||
204 | console.log(' DEBUG: div with id ' + id + ' not found'); | ||
205 | return; | ||
206 | } | ||
207 | const canvas_id = id + '/canvas'; | ||
208 | div.innerHTML = '<canvas id = "' + id + '/canvas' + '"></canvas>'; | ||
209 | |||
210 | // Add the job to the global queue | ||
211 | const end = Math.trunc(Date.now() / 1000); | ||
212 | wv.machines.jobs[o.name] = { | ||
213 | id: o.name, | ||
214 | start: end - 2 * 3600, // todo 25 | ||
215 | end: end, | ||
216 | canvas_id: id + '/canvas', | ||
217 | status: 0 // 0 = prepare canvas, 1 = send/recv_request, 2 = 3 = done | ||
218 | }; | ||
219 | wv.machines.func.process_job(wv.machines.jobs[o.name]); | ||
220 | } | ||
221 | |||
222 | wv.machines.func.machine_click = function(id) | ||
223 | { | ||
224 | console.log('machine_click: id=' + id); | ||
225 | const a = id.split('/'); | ||
226 | const what = a[0]; | ||
227 | const machine_id = a[1]; | ||
228 | const o = { name: machine_id, func: wv.machines.func.machine_body }; | ||
229 | wv.tab.func.add_tab(what, o); | ||
230 | } | ||
231 | |||
232 | wv.machines.func.list_machines = function(name, o) | ||
233 | { | ||
234 | console.log('func.list_machines: name=' + name); | ||
235 | |||
236 | machines = wv.conf.func.load(name); | ||
237 | machines.target_div = 'machines_list'; | ||
238 | machines.fields = { | ||
239 | id: { name: 'ID' }, | ||
240 | first_seen: { name: 'First seen', render: wv.time.func.render_ts }, | ||
241 | last_seen: { name: 'Last seen', render: wv.time.func.render_ts } | ||
242 | }; | ||
243 | machines.sort_info = { | ||
244 | id: { order: 1 } | ||
245 | }; | ||
246 | machines.events = { | ||
247 | row_click: { func: wv.machines.func.machine_click } | ||
248 | }; | ||
249 | machines.text_no_data = 'No machines found.'; | ||
250 | wv.grid.func.display(name); | ||
251 | } | ||
252 | |||
253 | wv.machines.func.show_machines = function() | ||
254 | { | ||
255 | machines = { | ||
256 | name: 'machines', | ||
257 | target_div: 'machines_tabs', | ||
258 | tabs: [ | ||
259 | { | ||
260 | name: 'Machines', | ||
261 | body: '<div id="machines_list" />', | ||
262 | func: wv.machines.func.list_machines, | ||
263 | func_para: 'machines', | ||
264 | can_be_closed: 0 | ||
265 | } | ||
266 | ], | ||
267 | style: { | ||
268 | main_class: 'flex1', | ||
269 | main: [ | ||
270 | { name: 'display', value: 'flex' }, | ||
271 | { name: 'flex-direction', value: 'column' } | ||
272 | ], | ||
273 | body_group_class: 'flex1', | ||
274 | body_group: [ | ||
275 | { name: 'flex-grow', value: '1' } | ||
276 | ], | ||
277 | body: [ | ||
278 | { name: 'flex-grow', value: '1' } | ||
279 | ] | ||
280 | } | ||
281 | }; | ||
282 | wv.tab.func.display(machines); | ||
283 | // TODO: move flex stuff in 'tab.js' and remove it from here. | ||
284 | } | ||
285 | |||
286 | // This is called when 'machines' menu is clicked | ||
287 | wv.machines.func.main = function() | ||
288 | { | ||
289 | if (wv.login.ok != 1) { | ||
290 | div_body.innerHTML = 'You must login.'; | ||
291 | return; | ||
292 | } | ||
293 | |||
294 | div_body.innerHTML = wv.machines.html.main; | ||
295 | wv.machines.func.show_machines(); | ||
296 | } | ||
297 | |||
298 | // Called by server to add an cert | ||
299 | wv.machines.func.update = function(i) | ||
300 | { | ||
301 | wv.debug('machines.func.update...'); | ||
302 | machines = wv.conf.func.load('machines'); | ||
303 | if (typeof machines.list === 'undefined') | ||
304 | machines.list = {}; | ||
305 | machines.list[i.id] = i; | ||
306 | wv.conf.func.update('machines', 'list', machines.list); | ||
307 | } | ||
308 | |||
309 | wv.machines.func.update_answer = function(status, msg) | ||
310 | { | ||
311 | wv.debug('machines.func.update_answer status=' + status + ' msg=' + msg); | ||
312 | |||
313 | if (status == 1) { // ok | ||
314 | var b = document.getElementById('set_status_ok'); | ||
315 | } else { | ||
316 | var b = document.getElementById('set_status_err'); | ||
317 | } | ||
318 | b.innerHTML = msg; | ||
319 | |||
320 | return true; | ||
321 | } | ||
322 | |||
323 | wv.machines.func.init = function() | ||
324 | { | ||
325 | } | ||
326 | |||
327 | } catch (e) { | ||
328 | console.log('machines.js exception: ' + e); | ||
329 | } |
File webd/webroot/js/menu.js changed (mode: 100644) (index c87bb27..0586e3d) | |||
... | ... | wv.menu = function(w) | |
6 | 6 | ||
7 | 7 | switch (w) { | switch (w) { |
8 | 8 | case 'set': wv.set.func.main(); break; | case 'set': wv.set.func.main(); break; |
9 | case 'machines': wv.machines.func.main(); break; | ||
9 | 10 | case 'certs': wv.certs.func.main(); break; | case 'certs': wv.certs.func.main(); break; |
10 | 11 | case 'admin': wv.admin.func.main(); break; | case 'admin': wv.admin.func.main(); break; |
11 | 12 | default: wv.home.func.main(); break; | default: wv.home.func.main(); break; |
... | ... | wv.menu = function(w) | |
16 | 17 | wv.html.main_menu = ` | wv.html.main_menu = ` |
17 | 18 | <span class="menu_item" onclick="wv.menu('home')">Home</span> | <span class="menu_item" onclick="wv.menu('home')">Home</span> |
18 | 19 | <span class="menu_item" onclick="wv.menu('set')">Settings</span> | <span class="menu_item" onclick="wv.menu('set')">Settings</span> |
20 | <span class="menu_item" onclick="wv.menu('machines')">Machines</span> | ||
19 | 21 | <span class="menu_item" onclick="wv.menu('certs')">Certificates</span> | <span class="menu_item" onclick="wv.menu('certs')">Certificates</span> |
20 | 22 | <span class="menu_item menu_admin" onclick="wv.menu('admin')">Admin</span> | <span class="menu_item menu_admin" onclick="wv.menu('admin')">Admin</span> |
21 | 23 | <span class="menu_item" onclick="wv.login.func.logout()">Logout</span> | <span class="menu_item" onclick="wv.login.func.logout()">Logout</span> |
22 | <br /><br /> | ||
23 | 24 | `; | `; |
File webd/webroot/js/tab.js added (mode: 100644) (index 0000000..976d680) | |||
1 | // tab.js | ||
2 | //wv.module.func.load('conf'); | ||
3 | |||
4 | try { | ||
5 | |||
6 | if (typeof wv.tab === 'undefined') | ||
7 | wv.tab = {}; | ||
8 | if (typeof wv.tab.func === 'undefined') | ||
9 | wv.tab.func = {}; | ||
10 | |||
11 | // Here we keep all the tabs, indexed by 'name' | ||
12 | if (typeof wv.tab.list === 'undefined') | ||
13 | wv.tab.list = {}; | ||
14 | |||
15 | wv.tab.func.drag_start = function(e) | ||
16 | { | ||
17 | e.dataTransfer.setData('text/plain', e.target.id); | ||
18 | } | ||
19 | |||
20 | wv.tab.func.drag_enter = function(e) | ||
21 | { | ||
22 | e.preventDefault(); // without this, we cannot drop | ||
23 | } | ||
24 | |||
25 | wv.tab.func.drag_over = function(e) | ||
26 | { | ||
27 | e.preventDefault(); // whitout this, we cannot drop | ||
28 | } | ||
29 | |||
30 | wv.tab.func.drag_leave = function(e) | ||
31 | { | ||
32 | } | ||
33 | |||
34 | wv.tab.func.drop = function(e) | ||
35 | { | ||
36 | e.preventDefault(); // without this, browser redirects to the id of the column :( | ||
37 | |||
38 | //console.log('tab.func.drop:'); console.log(e); | ||
39 | const src_id = e.dataTransfer.getData('text/plain'); | ||
40 | const dst_id = e.target.id; | ||
41 | |||
42 | const a = src_id.split('/'); | ||
43 | const name = a[0]; | ||
44 | var data = wv.tab.list[name]; | ||
45 | if (typeof data === 'undefined') | ||
46 | return; | ||
47 | |||
48 | const src_f = a[1]; | ||
49 | |||
50 | const d = dst_id.split('/'); | ||
51 | const dst_f = d[1]; | ||
52 | |||
53 | var i_src = data.tab_order.indexOf(src_f); | ||
54 | var i_dst = data.tab_order.indexOf(dst_f); | ||
55 | data.tab_order.splice(i_src, 1); | ||
56 | data.tab_order.splice(i_dst, 0, src_f); | ||
57 | wv.tab.func.display(data); | ||
58 | } | ||
59 | |||
60 | wv.tab.func.activate_tab = function(id) | ||
61 | { | ||
62 | var id; | ||
63 | |||
64 | const a = id.split('/'); | ||
65 | const name = a[0]; | ||
66 | var data = wv.tab.list[name]; | ||
67 | |||
68 | var parent = document.getElementById(data.target_div); | ||
69 | |||
70 | var top = parent.children[0]; | ||
71 | keys = Object.keys(top.children); | ||
72 | id = name + '/' + a[1] + '/h/label'; | ||
73 | keys.forEach((k, junk) => { | ||
74 | label = top.children[k].children[0]; | ||
75 | if (label.id == id) | ||
76 | label.style.color = 'red'; | ||
77 | else | ||
78 | label.style.color = 'black'; | ||
79 | }); | ||
80 | |||
81 | // body | ||
82 | var bot = parent.children[1]; | ||
83 | keys = Object.keys(bot.children); | ||
84 | id = name + '/' + a[1] + '/b'; | ||
85 | keys.forEach((k, junk) => { | ||
86 | if (bot.children[k].id == id) | ||
87 | bot.children[k].style.display = 'block'; | ||
88 | else | ||
89 | bot.children[k].style.display = 'none'; | ||
90 | }); | ||
91 | } | ||
92 | |||
93 | // TODO: move this in util? | ||
94 | wv.tab.func.apply_style = function(obj, i, key) | ||
95 | { | ||
96 | if (typeof i.style[key + '_class'] !== 'undefined') | ||
97 | obj.classList.add(i.style[key + '_class']); | ||
98 | |||
99 | if (typeof i.style[key] !== 'undefined') { | ||
100 | keys = Object.keys(i.style[key]); | ||
101 | keys.forEach((c, junk) => { | ||
102 | x = i.style[key][c]; | ||
103 | obj.style[x['name']] = x['value']; | ||
104 | }); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | wv.tab.func.close_tab = function(id) | ||
109 | { | ||
110 | const a = id.split('/'); | ||
111 | const name = a[0]; | ||
112 | const pos = a[1]; | ||
113 | |||
114 | var data = wv.tab.list[name]; | ||
115 | var index = data.tab_order.indexOf(pos).toString(); | ||
116 | //console.log('id=' + id + ' index=' + index + ' todo check type'); | ||
117 | data.tab_order.splice(index, 1); // todo this is not correct | ||
118 | data.tabs.splice(index, 1); | ||
119 | //console.log('active_tab=' + data.active_tab + ' index=' + index); | ||
120 | if (data.active_tab === index) | ||
121 | data.active_tab = '0'; | ||
122 | wv.tab.func.display(data); | ||
123 | } | ||
124 | |||
125 | // TODO: we need to check if the tab is already open. Not clear. | ||
126 | wv.tab.func.add_tab = function(name, o) | ||
127 | { | ||
128 | //console.log('func.add_tab: name=' + name); console.log(o); | ||
129 | var data = wv.tab.list[name]; | ||
130 | |||
131 | var index = data.tabs.push(o) - 1; | ||
132 | index = index.toString(); // because Object.keys return strings | ||
133 | //console.log('new index=' + index); | ||
134 | data.tab_order.push(index); | ||
135 | data.active_tab = index; | ||
136 | //console.log('set active tab to ' + data.active_tab); | ||
137 | wv.tab.func.display(data); | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * Draws tabs | ||
142 | * @i - info about tabs | ||
143 | */ | ||
144 | // TODO: if we delete the current tab, we need to make active the left one or the right one | ||
145 | // TODO: we should not redraw what was not changed! | ||
146 | wv.tab.func.display = function(i) | ||
147 | { | ||
148 | var div, text; | ||
149 | |||
150 | wv.debug('tab.func.display i.name=' + i.name); | ||
151 | |||
152 | // Is already rendered? | ||
153 | if (typeof wv.tab.list[i.name] === 'undefined') | ||
154 | wv.tab.list[i.name] = i; | ||
155 | i = wv.tab.list[i.name]; | ||
156 | |||
157 | var tab_group = document.createElement('div'); | ||
158 | tab_group.id = i.name + '/group'; | ||
159 | tab_group.classList.add('tab_main_div'); | ||
160 | tab_group.style.border = '1px solid black'; | ||
161 | tab_group.style.margin = '3px'; | ||
162 | tab_group.style.padding = '5px'; | ||
163 | wv.tab.func.apply_style(tab_group, i, 'main'); | ||
164 | |||
165 | if (typeof i.tab_order === 'undefined') | ||
166 | i.tab_order = Object.keys(i.tabs); | ||
167 | |||
168 | var tab_header = document.createElement('div'); | ||
169 | tab_header.id = i.name + '/header'; | ||
170 | wv.tab.func.apply_style(tab_header, i, 'header_group'); | ||
171 | var tab_body = document.createElement('div'); | ||
172 | tab_body.id = i.name + '/body'; | ||
173 | wv.tab.func.apply_style(tab_body, i, 'body_group'); | ||
174 | //console.log('i.tab_order:'); console.log(i.tab_order); | ||
175 | i.tab_order.forEach((t, junk) => { | ||
176 | //if (typeof i.tabs[t].my_dirty === 'undefined') | ||
177 | // i.tabs[t].my_dirty = 1; | ||
178 | //if (i.tabs[t].my_dirty == 0) | ||
179 | // continue; | ||
180 | // TODO: whos sets my_dirty? Not so easy - we need to copy the previous DOM | ||
181 | |||
182 | var base_id = i.name + '/' + t; | ||
183 | if (typeof i.active_tab === 'undefined') | ||
184 | i.active_tab = t; | ||
185 | |||
186 | // header | ||
187 | var d = document.createElement('div'); | ||
188 | d.id = base_id + '/h'; | ||
189 | d.style.padding = '2px 4px'; | ||
190 | //d.style.margin = '0 2px'; | ||
191 | d.style.display = 'inline-block'; // todo switch to flex | ||
192 | d.style.border = '1px solid black'; | ||
193 | d.draggable = 'true'; | ||
194 | d.addEventListener('dragstart', wv.tab.func.drag_start); | ||
195 | d.addEventListener('dragenter', wv.tab.func.drag_enter); | ||
196 | d.addEventListener('dragover', wv.tab.func.drag_over); | ||
197 | d.addEventListener('dragleave', wv.tab.func.drag_leave); | ||
198 | d.addEventListener('drop', wv.tab.func.drop); | ||
199 | |||
200 | var label = document.createElement('span'); | ||
201 | label.id = base_id + '/h/label'; | ||
202 | label.style.color = 'black'; | ||
203 | label.style.cursor = 'pointer'; | ||
204 | if (i.active_tab == t) | ||
205 | label.style.color = 'red'; | ||
206 | text = document.createTextNode(i.tabs[t].name); | ||
207 | label.appendChild(text); | ||
208 | label.onclick = function() { wv.tab.func.activate_tab(this.id); }; | ||
209 | d.appendChild(label); | ||
210 | |||
211 | if ((typeof i.tabs[t].can_be_closed === 'undefined') | ||
212 | || (i.tabs[t].can_be_closed == 1)) { | ||
213 | text = document.createTextNode(' '); | ||
214 | d.appendChild(text); | ||
215 | |||
216 | var close = document.createElement('span'); | ||
217 | close.id = base_id + '/h-close'; | ||
218 | close.style.color = 'white'; | ||
219 | close.style.backgroundColor = 'red'; | ||
220 | close.style.border = '1px solid black'; | ||
221 | close.style.cursor = 'pointer'; | ||
222 | text = document.createTextNode('x'); | ||
223 | close.appendChild(text); | ||
224 | close.onclick = function() { wv.tab.func.close_tab(this.id); }; | ||
225 | d.appendChild(close); | ||
226 | } | ||
227 | |||
228 | wv.tab.func.apply_style(d, i, 'header'); | ||
229 | tab_header.appendChild(d); | ||
230 | |||
231 | // body | ||
232 | var d = document.createElement('div'); | ||
233 | d.id = base_id + '/b'; | ||
234 | d.style.border = '1px solid black'; | ||
235 | d.style.padding = '3px'; | ||
236 | if (i.active_tab == t) | ||
237 | d.style.display = 'block'; | ||
238 | else | ||
239 | d.style.display = 'none'; | ||
240 | |||
241 | wv.tab.func.apply_style(d, i, 'body'); | ||
242 | |||
243 | if (typeof i.tabs[t].body !== 'undefined') { | ||
244 | //console.log('we have body: ' + i.tabs[t].body); | ||
245 | d.innerHTML = i.tabs[t].body; | ||
246 | } | ||
247 | tab_body.appendChild(d); | ||
248 | }); | ||
249 | |||
250 | div = document.getElementById(i.target_div); | ||
251 | div.replaceChildren(tab_header, tab_body); | ||
252 | |||
253 | // We can call functions only after we populated the DOM | ||
254 | i.tab_order.forEach((t, junk) => { | ||
255 | if (typeof i.tabs[t].func !== 'undefined') { | ||
256 | if (typeof i.tabs[t].func_para !== 'undefined') | ||
257 | para = i.tabs[t].func_para; | ||
258 | else | ||
259 | para = i.name + '/' + t; | ||
260 | //console.log('DEBUG: we have a func attached to t=' + t); | ||
261 | i.tabs[t].func(i.name, t, i.tabs[t]); | ||
262 | } | ||
263 | }); | ||
264 | } | ||
265 | |||
266 | } catch (e) { | ||
267 | console.log('tab.js exception: ' + e); | ||
268 | } |
File webd/webroot/js/util.js changed (mode: 100644) (index 70a6df5..0bfad0f) | |||
... | ... | wv.util.func.notify = function(from, msg) | |
49 | 49 | ||
50 | 50 | wv.util.send = function(s) | wv.util.send = function(s) |
51 | 51 | { | { |
52 | wv.debug('Sending: ' + s); | ||
52 | //wv.debug('Sending: ' + s); | ||
53 | 53 | ws.send(s); | ws.send(s); |
54 | 54 | } | } |
55 | 55 |
File webd/webroot/main.css changed (mode: 100644) (index 9f61879..54bc7c3) | |||
1 | body { | ||
2 | padding: 5px; | ||
3 | x-display: flex; | ||
4 | x-flex-direction: column; | ||
1 | html { | ||
5 | 2 | font-family: sans; | font-family: sans; |
6 | font-size: 9pt; | ||
3 | font-size: 11pt; | ||
7 | 4 | margin: 0; | margin: 0; |
5 | height: 100%; | ||
8 | 6 | } | } |
9 | 7 | ||
10 | pre { | ||
11 | margin: 0; | ||
8 | body { | ||
9 | margin: 3px; | ||
10 | display: flex; | ||
11 | flex-direction: column; | ||
12 | height: 100%; | ||
13 | } | ||
14 | |||
15 | .flex1 { | ||
16 | display: flex; | ||
17 | flex-direction: column; | ||
12 | 18 | } | } |
13 | 19 | ||
14 | 20 | #my_status, #app_status, #add_status { | #my_status, #app_status, #add_status { |
15 | 21 | border: 1px solid black; | border: 1px solid black; |
16 | 22 | padding: 3px; | padding: 3px; |
17 | margin: 2px; | ||
23 | margin: 2px 0; | ||
18 | 24 | display: inline-block; | display: inline-block; |
19 | x-flex: 1 100%; | ||
20 | 25 | } | } |
21 | 26 | ||
22 | 27 | .menu { | .menu { |
23 | 28 | xxx-border: 1px solid black; | xxx-border: 1px solid black; |
24 | margin: 2px; | ||
29 | margin: 2px 0; | ||
25 | 30 | padding: 0 5px 0 0; | padding: 0 5px 0 0; |
26 | x-flex: 1 100%; | ||
27 | x-display: flex; | ||
28 | x-flex-direction: row; | ||
29 | x-flex-wrap: wrap; | ||
30 | x-justify-content: flex-start; | ||
31 | x-align-items: stretch; | ||
32 | x-align-content: flex-start; | ||
33 | 31 | } | } |
34 | 32 | ||
35 | 33 | .menu_item { | .menu_item { |
36 | 34 | border: 1px solid green; | border: 1px solid green; |
37 | margin: 0 5px 0 0; | ||
38 | padding: 5px; | ||
35 | padding: 2px 4px; | ||
39 | 36 | background-color: yellow; | background-color: yellow; |
40 | 37 | font-weight: bold; | font-weight: bold; |
41 | 38 | cursor: pointer; | cursor: pointer; |
... | ... | pre { | |
46 | 43 | display: none; | display: none; |
47 | 44 | } | } |
48 | 45 | ||
49 | .content { | ||
46 | #my_body { | ||
50 | 47 | xxx-border: 1px solid black; | xxx-border: 1px solid black; |
51 | margin: 2px; | ||
48 | margin: 2px 0; | ||
52 | 49 | xxx-padding: 5px; | xxx-padding: 5px; |
53 | 50 | ||
54 | x-flex: 1 100%; | ||
55 | x-display: flex; | ||
56 | x-flex-direction: column; | ||
57 | x-flex-wrap: wrap; | ||
58 | x-justify-content: flex-start; | ||
59 | x-align-items: stretch; | ||
60 | x-align-content: flex-start; | ||
51 | flex-grow: 1; | ||
52 | |||
53 | display: flex; | ||
54 | flex-direction: column; | ||
61 | 55 | } | } |
62 | 56 | ||
63 | 57 | .gem { | .gem { |
File webd/webroot/main.js changed (mode: 100644) (index 6582ce7..538d8b4) | |||
... | ... | function my_start() | |
128 | 128 | div_debug = document.getElementById('debug'); | div_debug = document.getElementById('debug'); |
129 | 129 | div_status = document.getElementById('my_status'); | div_status = document.getElementById('my_status'); |
130 | 130 | div_menu = document.getElementById('main_menu'); | div_menu = document.getElementById('main_menu'); |
131 | div_body = document.getElementById('body'); | ||
131 | div_body = document.getElementById('my_body'); | ||
132 | 132 | ||
133 | 133 | // Ask permission for notifications (if not already granted) | // Ask permission for notifications (if not already granted) |
134 | 134 | Notification.requestPermission().then(function(r) { notify_perm = r; }); | Notification.requestPermission().then(function(r) { notify_perm = r; }); |
Date/time (UTC) | Type | Misc | Labels |
---|---|---|---|
2023-03-15 06:48 | build | fedora-37-x86_64 | worker/r1 builder/color=fff worker_elap/1126s wait_time/174912s date/2023-03-13 time/05:53 |
2023-03-15 07:05 | build | fedora-rawhide-x86_64 | worker/r1 builder/color=fff worker_elap/964s wait_time/176093s date/2023-03-13 time/05:53 |