add support for the info parameter to all external plugin functions (#16915)
* add support for the info parameter to all functions * add SO_CLOEXEC to inbound connections * network-connections aggregated view for servers with dozens of thousands of connections * optimized /proc/net files parsing; aggregated view of network-connections returns sorted sockets to avoid dancing visualization * local-sockets is now using aral * lower the payload returned by network-connections
Costa Tsaousis committed
Feb 2, 2024 at 22:44 UTC
de75ef2f6dccfa1d357d14b86179b8174c3745a5
20 files changed
+760
-391
collectors/apps.plugin/apps_plugin.c
+12
-10
@@ -4399,10 +4399,11 @@ static void apps_plugin_function_processes_help(const char *transaction) {
4399
buffer_json_add_array_item_double(wb, _tmp); \
4400
} while(0)
4401
4402
-static void function_processes(const char *transaction, char *function __maybe_unused,
4402
+static void function_processes(const char *transaction, char *function,
4403
usec_t *stop_monotonic_ut __maybe_unused, bool *cancelled __maybe_unused,
4404
BUFFER *payload __maybe_unused, HTTP_ACCESS access,
4405
const char *source __maybe_unused, void *data __maybe_unused) {
4406
+ time_t now_s = now_realtime_sec();
4407
struct pid_stat *p;
4408
4409
bool show_cmdline = http_access_user_has_enough_access_level_for_endpoint(
@@ -4418,6 +4419,7 @@ static void function_processes(const char *transaction, char *function __maybe_u
4419
pid_t pid = 0;
4420
uid_t uid = 0;
4421
gid_t gid = 0;
4422
+ bool info = false;
4423
4424
bool filter_pid = false, filter_uid = false, filter_gid = false;
4425
@@ -4468,16 +4470,11 @@ static void function_processes(const char *transaction, char *function __maybe_u
4470
apps_plugin_function_processes_help(transaction);
4471
return;
4472
}
4471
- else {
4472
- char msg[1024];
4473
- snprintfz(msg, sizeof(msg), "Invalid parameter '%s'", keyword);
4474
- pluginsd_function_json_error_to_stdout(transaction, HTTP_RESP_BAD_REQUEST, msg);
4475
- return;
4473
+ else if(strcmp(keyword, "info") == 0) {
4474
+ info = true;
4475
}
4476
}
4477
4479
- time_t expires = now_realtime_sec() + update_every;
4480
-
4478
unsigned int cpu_divisor = time_factor * RATES_DETAIL / 100;
4479
unsigned int memory_divisor = 1024;
4480
unsigned int io_divisor = 1024 * RATES_DETAIL;
@@ -4487,9 +4484,13 @@ static void function_processes(const char *transaction, char *function __maybe_u
4484
buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
4485
buffer_json_member_add_string(wb, "type", "table");
4486
buffer_json_member_add_time_t(wb, "update_every", update_every);
4487
+ buffer_json_member_add_boolean(wb, "has_history", false);
4488
buffer_json_member_add_string(wb, "help", APPS_PLUGIN_PROCESSES_FUNCTION_DESCRIPTION);
4489
buffer_json_member_add_array(wb, "data");
4490
4491
+ if(info)
4492
+ goto close_and_send;
4493
+
4494
NETDATA_DOUBLE
4495
UserCPU_max = 0.0
4496
, SysCPU_max = 0.0
@@ -5251,10 +5252,11 @@ static void function_processes(const char *transaction, char *function __maybe_u
5252
}
5253
buffer_json_object_close(wb); // group_by
5254
5254
- buffer_json_member_add_time_t(wb, "expires", expires);
5255
+close_and_send:
5256
+ buffer_json_member_add_time_t(wb, "expires", now_s + update_every);
5257
buffer_json_finalize(wb);
5258
5257
- pluginsd_function_result_to_stdout(transaction, HTTP_RESP_OK, "application/json", expires, wb);
5259
+ pluginsd_function_result_to_stdout(transaction, HTTP_RESP_OK, "application/json", now_s + update_every, wb);
5260
5261
buffer_free(wb);
5262
}
collectors/cgroups.plugin/cgroup-top.c
+2
@@ -107,6 +107,7 @@ int cgroup_function_cgroup_top(BUFFER *wb, const char *function __maybe_unused)
107
buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
108
buffer_json_member_add_string(wb, "type", "table");
109
buffer_json_member_add_time_t(wb, "update_every", 1);
110
+ buffer_json_member_add_boolean(wb, "has_history", false);
111
buffer_json_member_add_string(wb, "help", RRDFUNCTIONS_CGTOP_HELP);
112
buffer_json_member_add_array(wb, "data");
113
@@ -349,6 +350,7 @@ int cgroup_function_systemd_top(BUFFER *wb, const char *function __maybe_unused)
350
buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
351
buffer_json_member_add_string(wb, "type", "table");
352
buffer_json_member_add_time_t(wb, "update_every", 1);
353
+ buffer_json_member_add_boolean(wb, "has_history", false);
354
buffer_json_member_add_string(wb, "help", RRDFUNCTIONS_CGTOP_HELP);
355
buffer_json_member_add_array(wb, "data");
356
collectors/diskspace.plugin/plugin_diskspace.c
+1
@@ -645,6 +645,7 @@ int diskspace_function_mount_points(BUFFER *wb, const char *function __maybe_unu
645
buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
646
buffer_json_member_add_string(wb, "type", "table");
647
buffer_json_member_add_time_t(wb, "update_every", 1);
648
+ buffer_json_member_add_boolean(wb, "has_history", false);
649
buffer_json_member_add_string(wb, "help", RRDFUNCTIONS_DISKSPACE_HELP);
650
buffer_json_member_add_array(wb, "data");
651
collectors/ebpf.plugin/ebpf_functions.c
+12
-4
@@ -292,6 +292,9 @@ static void ebpf_function_socket_manipulation(const char *transaction,
292
rw_spinlock_write_lock(&ebpf_judy_pid.index.rw_spinlock);
293
network_viewer_opt.enabled = CONFIG_BOOLEAN_YES;
294
uint32_t previous;
295
+ bool info = false;
296
+ time_t now_s = now_realtime_sec();
297
+
298
static const char *socket_help = {
299
"ebpf.plugin / socket\n"
300
"\n"
@@ -413,7 +416,8 @@ for (int i = 1; i < PLUGINSD_MAX_WORDS; i++) {
416
ebpf_function_help(transaction, socket_help);
417
rw_spinlock_write_unlock(&ebpf_judy_pid.index.rw_spinlock);
418
return;
416
- }
419
+ } else if (strncmp(keyword, "info", 4) == 0)
420
+ info = true;
421
}
422
rw_spinlock_write_unlock(&ebpf_judy_pid.index.rw_spinlock);
423
@@ -443,8 +447,12 @@ for (int i = 1; i < PLUGINSD_MAX_WORDS; i++) {
447
buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
448
buffer_json_member_add_string(wb, "type", "table");
449
buffer_json_member_add_time_t(wb, "update_every", em->update_every);
450
+ buffer_json_member_add_boolean(wb, "has_history", false);
451
buffer_json_member_add_string(wb, "help", EBPF_PLUGIN_SOCKET_FUNCTION_DESCRIPTION);
452
453
+ if(info)
454
+ goto close_and_send;
455
+
456
// Collect data
457
buffer_json_member_add_array(wb, "data");
458
ebpf_socket_read_open_connections(wb, em);
@@ -652,12 +660,12 @@ for (int i = 1; i < PLUGINSD_MAX_WORDS; i++) {
660
}
661
buffer_json_object_close(wb); // group_by
662
655
- time_t expires = now_realtime_sec() + em->update_every;
656
- buffer_json_member_add_time_t(wb, "expires", expires);
663
+close_and_send:
664
+ buffer_json_member_add_time_t(wb, "expires", now_s + em->update_every);
665
buffer_json_finalize(wb);
666
667
// Lock necessary to avoid race condition
660
- pluginsd_function_result_begin_to_stdout(transaction, HTTP_RESP_OK, "application/json", expires);
668
+ pluginsd_function_result_begin_to_stdout(transaction, HTTP_RESP_OK, "application/json", now_s + em->update_every);
669
670
fwrite(buffer_tostring(wb), buffer_strlen(wb), 1, stdout);
671
collectors/freeipmi.plugin/freeipmi_plugin.c
+21
-3
@@ -1475,14 +1475,31 @@ static void freeimi_function_sensors(const char *transaction, char *function __m
1475
usec_t *stop_monotonic_ut __maybe_unused, bool *cancelled __maybe_unused,
1476
BUFFER *payload __maybe_unused, HTTP_ACCESS access __maybe_unused,
1477
const char *source __maybe_unused, void *data __maybe_unused) {
1478
- time_t expires = now_realtime_sec() + update_every;
1478
+ time_t now_s = now_realtime_sec();
1479
1480
BUFFER *wb = buffer_create(4096, NULL);
1481
buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_NEWLINE_ON_ARRAY_ITEMS);
1482
buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
1483
buffer_json_member_add_string(wb, "type", "table");
1484
buffer_json_member_add_time_t(wb, "update_every", update_every);
1485
+ buffer_json_member_add_boolean(wb, "has_history", false);
1486
buffer_json_member_add_string(wb, "help", "View IPMI sensor readings and its state");
1487
+
1488
+ char function_copy[strlen(function) + 1];
1489
+ memcpy(function_copy, function, sizeof(function_copy));
1490
+ char *words[1024];
1491
+ size_t num_words = quoted_strings_splitter_pluginsd(function_copy, words, 1024);
1492
+ for(size_t i = 1; i < num_words ;i++) {
1493
+ char *param = get_word(words, num_words, i);
1494
+ if(strcmp(param, "info") == 0) {
1495
+ buffer_json_member_add_array(wb, "accepted_params");
1496
+ buffer_json_array_close(wb); // accepted_params
1497
+ buffer_json_member_add_array(wb, "required_params");
1498
+ buffer_json_array_close(wb); // required_params
1499
+ goto close_and_send;
1500
+ }
1501
+ }
1502
+
1503
buffer_json_member_add_array(wb, "data");
1504
1505
struct sensor *sn;
@@ -1608,10 +1625,11 @@ static void freeimi_function_sensors(const char *transaction, char *function __m
1625
}
1626
buffer_json_array_close(wb);
1627
1611
- buffer_json_member_add_time_t(wb, "expires", now_realtime_sec() + 1);
1628
+close_and_send:
1629
+ buffer_json_member_add_time_t(wb, "expires", now_s + update_every);
1630
buffer_json_finalize(wb);
1631
1614
- pluginsd_function_result_to_stdout(transaction, HTTP_RESP_OK, "application/json", expires, wb);
1632
+ pluginsd_function_result_to_stdout(transaction, HTTP_RESP_OK, "application/json", now_s + update_every, wb);
1633
1634
buffer_free(wb);
1635
}
collectors/network-viewer.plugin/network-connections-chart.html
+26
-2
@@ -557,15 +557,39 @@
557
558
const app = updateApps(svg, data, w, h, borderPadding, theme);
559
560
+ app.transition().duration(5000)
561
+
562
simulation = d3.forceSimulation(data)
563
//.force('center', d3.forceCenter(cw, ch).strength(1))
562
- .force("x", d3.forceX(d => d.d3.x).strength(0.05))
563
- .force("y", d3.forceY(d => d.d3.y).strength(0.05))
564
+ .force("x", d3.forceX(d => d.d3.x).strength(d => {
565
+ if(d.counts.listen === d.counts.total)
566
+ return 0.5
567
+ else
568
+ return 0.05
569
+ }))
570
+ .force("y", d3.forceY(d => d.d3.y).strength(d => {
571
+ if(d.counts.listen === d.counts.total)
572
+ return 0.5
573
+ else
574
+ return 0.05
575
+ }))
576
//.force("charge", d3.forceManyBody().strength(-0.05))
577
.force("collide", d3.forceCollide(d => d.d3.size * 1.1 + 15).strength(1))
578
.on('tick', ticked);
579
580
function ticked() {
581
+ data.forEach(d => {
582
+ if(d.x > w - d.d3.size)
583
+ d.x = w - d.d3.size;
584
+ else if(d.x < 0)
585
+ d.x = 0;
586
+
587
+ if(d.y > h - d.d3.size)
588
+ d.y = h - d.d3.size;
589
+ else if(d.y < 0)
590
+ d.y = 0;
591
+ });
592
+
593
app.attr('transform', d => `translate(${d.x}, ${d.y})`);
594
}
595
collectors/network-viewer.plugin/network-viewer.c
+548
-316
@@ -3,12 +3,23 @@
3
#include "collectors/all.h"
4
#include "libnetdata/libnetdata.h"
5
#include "libnetdata/required_dummies.h"
6
+
7
+#define LOCAL_SOCKETS_EXTENDED_MEMBERS struct { \
8
+ size_t count; \
9
+ const char *local_address_space; \
10
+ const char *remote_address_space; \
11
+ } network_viewer;
12
+
13
#include "libnetdata/maps/local-sockets.h"
14
#include "libnetdata/maps/system-users.h"
15
16
#define NETWORK_CONNECTIONS_VIEWER_FUNCTION "network-connections"
17
#define NETWORK_CONNECTIONS_VIEWER_HELP "Network connections explorer"
18
19
+#define SIMPLE_HASHTABLE_VALUE_TYPE LOCAL_SOCKET
20
+#define SIMPLE_HASHTABLE_NAME _AGGREGATED_SOCKETS
21
+#include "libnetdata/simple_hashtable.h"
22
+
23
netdata_mutex_t stdout_mutex = NETDATA_MUTEX_INITIALIZER;
24
static bool plugin_should_exit = false;
25
static USERNAMES_CACHE *uc;
@@ -44,10 +55,7 @@ ENUM_STR_MAP_DEFINE(TCP_STATE) = {
55
};
56
ENUM_STR_DEFINE_FUNCTIONS(TCP_STATE, 0, "unknown");
57
47
-
48
-static void local_socket_to_array(struct local_socket_state *ls, struct local_socket *n, void *data) {
49
- BUFFER *wb = data;
50
-
58
+static void local_socket_to_json_array(BUFFER *wb, LOCAL_SOCKET *n, uint64_t proc_self_net_ns_inode, bool aggregated) {
59
char local_address[INET6_ADDRSTRLEN];
60
char remote_address[INET6_ADDRSTRLEN];
61
char *protocol;
@@ -66,7 +74,7 @@ static void local_socket_to_array(struct local_socket_state *ls, struct local_so
74
return;
75
76
const char *type;
69
- if(n->net_ns_inode == ls->proc_self_net_ns_inode)
77
+ if(n->net_ns_inode == proc_self_net_ns_inode)
78
type = "system";
79
else if(n->net_ns_inode == 0)
80
type = "[unknown]";
@@ -90,55 +98,141 @@ static void local_socket_to_array(struct local_socket_state *ls, struct local_so
98
else
99
buffer_json_add_array_item_string(wb, n->comm);
100
93
- buffer_json_add_array_item_string(wb, n->cmdline);
101
+ // buffer_json_add_array_item_string(wb, string2str(n->cmdline));
102
103
if(n->uid == UID_UNSET) {
96
- buffer_json_add_array_item_uint64(wb, n->uid);
104
+ // buffer_json_add_array_item_uint64(wb, n->uid);
105
buffer_json_add_array_item_string(wb, "[unknown]");
106
}
107
else {
100
- buffer_json_add_array_item_uint64(wb, n->uid);
108
+ // buffer_json_add_array_item_uint64(wb, n->uid);
109
STRING *u = system_usernames_cache_lookup_uid(uc, n->uid);
110
buffer_json_add_array_item_string(wb, string2str(u));
111
string_freez(u);
112
}
113
106
- buffer_json_add_array_item_string(wb, local_address);
107
- buffer_json_add_array_item_uint64(wb, n->local.port);
108
- buffer_json_add_array_item_string(wb, local_sockets_address_space(&n->local));
109
- buffer_json_add_array_item_string(wb, remote_address);
110
- buffer_json_add_array_item_uint64(wb, n->remote.port);
111
- buffer_json_add_array_item_string(wb, local_sockets_address_space(&n->remote));
114
+ if(!aggregated) {
115
+ buffer_json_add_array_item_string(wb, local_address);
116
+ buffer_json_add_array_item_uint64(wb, n->local.port);
117
+ }
118
+ buffer_json_add_array_item_string(wb, n->network_viewer.local_address_space);
119
+
120
+ if(!aggregated) {
121
+ buffer_json_add_array_item_string(wb, remote_address);
122
+ buffer_json_add_array_item_uint64(wb, n->remote.port);
123
+ }
124
+ buffer_json_add_array_item_string(wb, n->network_viewer.remote_address_space);
125
126
uint16_t server_port;
114
- switch(n->direction) {
127
+ const char *server_address;
128
+ const char *client_address_space;
129
+ const char *server_address_space;
130
+ switch (n->direction) {
131
case SOCKET_DIRECTION_LISTEN:
132
case SOCKET_DIRECTION_INBOUND:
133
case SOCKET_DIRECTION_LOCAL_INBOUND:
134
server_port = n->local.port;
135
+ server_address = local_address;
136
+ server_address_space = n->network_viewer.local_address_space;
137
+ client_address_space = n->network_viewer.remote_address_space;
138
break;
139
140
case SOCKET_DIRECTION_OUTBOUND:
141
case SOCKET_DIRECTION_LOCAL_OUTBOUND:
142
server_port = n->remote.port;
143
+ server_address = remote_address;
144
+ server_address_space = n->network_viewer.remote_address_space;
145
+ client_address_space = n->network_viewer.local_address_space;
146
break;
147
148
case SOCKET_DIRECTION_NONE:
149
break;
150
}
151
+ if(aggregated)
152
+ buffer_json_add_array_item_string(wb, server_address);
153
+
154
buffer_json_add_array_item_uint64(wb, server_port);
155
131
- buffer_json_add_array_item_uint64(wb, n->inode);
132
- buffer_json_add_array_item_uint64(wb, n->net_ns_inode);
133
- buffer_json_add_array_item_uint64(wb, 1); // count
156
+ if(aggregated) {
157
+ buffer_json_add_array_item_string(wb, client_address_space);
158
+ buffer_json_add_array_item_string(wb, server_address_space);
159
+ }
160
+
161
+ // buffer_json_add_array_item_uint64(wb, n->inode);
162
+ // buffer_json_add_array_item_uint64(wb, n->net_ns_inode);
163
+ buffer_json_add_array_item_uint64(wb, n->network_viewer.count);
164
}
165
buffer_json_array_close(wb);
166
}
167
168
+static void local_sockets_cb_to_json(LS_STATE *ls, LOCAL_SOCKET *n, void *data) {
169
+ n->network_viewer.count = 1;
170
+ n->network_viewer.local_address_space = local_sockets_address_space(&n->local);
171
+ n->network_viewer.remote_address_space = local_sockets_address_space(&n->remote);
172
+ local_socket_to_json_array(data, n, ls->proc_self_net_ns_inode, false);
173
+}
174
+
175
+static void local_sockets_cb_to_aggregation(LS_STATE *ls __maybe_unused, LOCAL_SOCKET *n, void *data) {
176
+ SIMPLE_HASHTABLE_AGGREGATED_SOCKETS *ht = data;
177
+ n->network_viewer.count = 1;
178
+ n->network_viewer.local_address_space = local_sockets_address_space(&n->local);
179
+ n->network_viewer.remote_address_space = local_sockets_address_space(&n->remote);
180
+
181
+ switch(n->direction) {
182
+ case SOCKET_DIRECTION_INBOUND:
183
+ case SOCKET_DIRECTION_LOCAL_INBOUND:
184
+ case SOCKET_DIRECTION_LISTEN:
185
+ memset(&n->remote.ip, 0, sizeof(n->remote.ip));
186
+ n->remote.port = 0;
187
+ break;
188
+
189
+ case SOCKET_DIRECTION_OUTBOUND:
190
+ case SOCKET_DIRECTION_LOCAL_OUTBOUND:
191
+ memset(&n->local.ip, 0, sizeof(n->remote.ip));
192
+ n->local.port = 0;
193
+ break;
194
+
195
+ case SOCKET_DIRECTION_NONE:
196
+ return;
197
+ }
198
+
199
+ n->inode = 0;
200
+ n->local_ip_hash = 0;
201
+ n->remote_ip_hash = 0;
202
+ n->local_port_hash = 0;
203
+ n->timer = 0;
204
+ n->retransmits = 0;
205
+ n->expires = 0;
206
+ n->rqueue = 0;
207
+ n->wqueue = 0;
208
+ memset(&n->local_port_key, 0, sizeof(n->local_port_key));
209
+
210
+ XXH64_hash_t hash = XXH3_64bits(n, sizeof(*n));
211
+ SIMPLE_HASHTABLE_SLOT_AGGREGATED_SOCKETS *sl = simple_hashtable_get_slot_AGGREGATED_SOCKETS(ht, hash, n, true);
212
+ LOCAL_SOCKET *t = SIMPLE_HASHTABLE_SLOT_DATA(sl);
213
+ if(t) {
214
+ t->network_viewer.count++;
215
+ }
216
+ else {
217
+ t = mallocz(sizeof(*t));
218
+ memcpy(t, n, sizeof(*t));
219
+ t->cmdline = string_dup(t->cmdline);
220
+ simple_hashtable_set_slot_AGGREGATED_SOCKETS(ht, sl, hash, t);
221
+ }
222
+}
223
+
224
+static int local_sockets_compar(const void *a, const void *b) {
225
+ LOCAL_SOCKET *n1 = *(LOCAL_SOCKET **)a, *n2 = *(LOCAL_SOCKET **)b;
226
+ return strcmp(n1->comm, n2->comm);
227
+}
228
+
229
void network_viewer_function(const char *transaction, char *function __maybe_unused, usec_t *stop_monotonic_ut __maybe_unused,
230
bool *cancelled __maybe_unused, BUFFER *payload __maybe_unused, HTTP_ACCESS access __maybe_unused,
231
const char *source __maybe_unused, void *data __maybe_unused) {
232
233
+ time_t now_s = now_realtime_sec();
234
+ bool aggregated = false;
235
+
236
CLEAN_BUFFER *wb = buffer_create(0, NULL);
237
buffer_flush(wb);
238
wb->content_type = CT_APPLICATION_JSON;
@@ -147,360 +241,483 @@ void network_viewer_function(const char *transaction, char *function __maybe_unu
241
buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
242
buffer_json_member_add_string(wb, "type", "table");
243
buffer_json_member_add_time_t(wb, "update_every", 5);
244
+ buffer_json_member_add_boolean(wb, "has_history", false);
245
buffer_json_member_add_string(wb, "help", NETWORK_CONNECTIONS_VIEWER_HELP);
151
- buffer_json_member_add_array(wb, "data");
152
-
153
- LS_STATE ls = {
154
- .config = {
155
- .listening = true,
156
- .inbound = true,
157
- .outbound = true,
158
- .local = true,
159
- .tcp4 = true,
160
- .tcp6 = true,
161
- .udp4 = true,
162
- .udp6 = true,
163
- .pid = true,
164
- .uid = true,
165
- .cmdline = true,
166
- .comm = true,
167
- .namespaces = true,
168
-
169
- .max_errors = 10,
170
-
171
- .cb = local_socket_to_array,
172
- .data = wb,
173
- },
174
- .stats = { 0 },
175
- .sockets_hashtable = { 0 },
176
- .local_ips_hashtable = { 0 },
177
- .listening_ports_hashtable = { 0 },
178
- };
179
-
180
- local_sockets_process(&ls);
246
182
- buffer_json_array_close(wb);
183
- buffer_json_member_add_object(wb, "columns");
247
+#ifdef ENABLE_DETAILED_VIEW
248
+ buffer_json_member_add_array(wb, "accepted_params");
249
{
185
- size_t field_id = 0;
186
-
187
- // Direction
188
- buffer_rrdf_table_add_field(wb, field_id++, "Direction", "Socket Direction",
189
- RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
190
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
191
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
192
- RRDF_FIELD_OPTS_VISIBLE,
193
- NULL);
194
-
195
- // Protocol
196
- buffer_rrdf_table_add_field(wb, field_id++, "Protocol", "Socket Protocol",
197
- RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
198
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
199
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
200
- RRDF_FIELD_OPTS_VISIBLE,
201
- NULL);
202
-
203
- // Type
204
- buffer_rrdf_table_add_field(wb, field_id++, "Namespace", "Namespace",
205
- RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
206
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
207
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
208
- RRDF_FIELD_OPTS_VISIBLE,
209
- NULL);
210
-
211
- // State
212
- buffer_rrdf_table_add_field(wb, field_id++, "State", "Socket State",
213
- RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
214
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
215
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
216
- RRDF_FIELD_OPTS_VISIBLE,
217
- NULL);
218
-
219
- // Pid
220
- buffer_rrdf_table_add_field(wb, field_id++, "PID", "Process ID",
221
- RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
222
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
223
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
224
- RRDF_FIELD_OPTS_VISIBLE,
225
- NULL);
226
-
227
- // Comm
228
- buffer_rrdf_table_add_field(wb, field_id++, "Process", "Process Name",
229
- RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
230
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
231
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
232
- RRDF_FIELD_OPTS_VISIBLE|RRDF_FIELD_OPTS_FULL_WIDTH,
233
- NULL);
234
-
235
- // Cmdline
236
- buffer_rrdf_table_add_field(wb, field_id++, "CommandLine", "Command Line",
237
- RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
238
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
239
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
240
- RRDF_FIELD_OPTS_NONE|RRDF_FIELD_OPTS_FULL_WIDTH,
241
- NULL);
242
-
243
- // Uid
244
- buffer_rrdf_table_add_field(wb, field_id++, "UID", "User ID",
245
- RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
246
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
247
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
248
- RRDF_FIELD_OPTS_NONE,
249
- NULL);
250
-
251
- // Username
252
- buffer_rrdf_table_add_field(wb, field_id++, "User", "Username",
253
- RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
254
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
255
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
256
- RRDF_FIELD_OPTS_VISIBLE,
257
- NULL);
258
-
259
- // Local Address
260
- buffer_rrdf_table_add_field(wb, field_id++, "LocalIP", "Local IP Address",
261
- RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
262
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
263
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
264
- RRDF_FIELD_OPTS_VISIBLE|RRDF_FIELD_OPTS_FULL_WIDTH,
265
- NULL);
266
-
267
- // Local Port
268
- buffer_rrdf_table_add_field(wb, field_id++, "LocalPort", "Local Port",
269
- RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
270
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
271
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
272
- RRDF_FIELD_OPTS_VISIBLE,
273
- NULL);
274
-
275
- // Local Address Space
276
- buffer_rrdf_table_add_field(wb, field_id++, "LocalAddressSpace", "Local IP Address Space",
277
- RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
278
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
279
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
280
- RRDF_FIELD_OPTS_NONE,
281
- NULL);
282
-
283
- // Remote Address
284
- buffer_rrdf_table_add_field(wb, field_id++, "RemoteIP", "Remote IP Address",
285
- RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
286
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
287
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
288
- RRDF_FIELD_OPTS_VISIBLE|RRDF_FIELD_OPTS_FULL_WIDTH,
289
- NULL);
290
-
291
- // Remote Port
292
- buffer_rrdf_table_add_field(wb, field_id++, "RemotePort", "Remote Port",
293
- RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
294
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
295
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
296
- RRDF_FIELD_OPTS_VISIBLE,
297
- NULL);
298
-
299
- // Remote Address Space
300
- buffer_rrdf_table_add_field(wb, field_id++, "RemoteAddressSpace", "Remote IP Address Space",
301
- RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
302
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
303
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
304
- RRDF_FIELD_OPTS_NONE,
305
- NULL);
306
-
307
- // Server Port
308
- buffer_rrdf_table_add_field(wb, field_id++, "ServerPort", "Server Port",
309
- RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
310
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
311
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
312
- RRDF_FIELD_OPTS_NONE,
313
- NULL);
314
-
315
- // inode
316
- buffer_rrdf_table_add_field(wb, field_id++, "Inode", "Socket Inode",
317
- RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
318
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
319
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
320
- RRDF_FIELD_OPTS_NONE,
321
- NULL);
322
-
323
- // Namespace inode
324
- buffer_rrdf_table_add_field(wb, field_id++, "Namespace Inode", "Namespace Inode",
325
- RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
326
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
327
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
328
- RRDF_FIELD_OPTS_NONE,
329
- NULL);
330
-
331
- // Count
332
- buffer_rrdf_table_add_field(wb, field_id++, "Count", "Count",
333
- RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
334
- 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
335
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
336
- RRDF_FIELD_OPTS_NONE,
337
- NULL);
250
+ buffer_json_add_array_item_string(wb, "sockets");
251
}
339
- buffer_json_object_close(wb); // columns
340
- buffer_json_member_add_string(wb, "default_sort_column", "Direction");
341
-
342
- buffer_json_member_add_object(wb, "custom_charts");
252
+ buffer_json_array_close(wb); // accepted_params
253
+ buffer_json_member_add_array(wb, "required_params");
254
{
344
- buffer_json_member_add_object(wb, "Network Map");
255
+ buffer_json_add_array_item_object(wb);
256
{
346
- buffer_json_member_add_string(wb, "type", "network-viewer");
257
+ buffer_json_member_add_string(wb, "id", "sockets");
258
+ buffer_json_member_add_string(wb, "name", "Sockets");
259
+ buffer_json_member_add_string(wb, "help", "Select the source type to query");
260
+ buffer_json_member_add_string(wb, "type", "select");
261
+ buffer_json_member_add_array(wb, "options");
262
+ {
263
+ buffer_json_add_array_item_object(wb);
264
+ {
265
+ buffer_json_member_add_string(wb, "id", "aggregated");
266
+ buffer_json_member_add_string(wb, "name", "Aggregated view of sockets");
267
+ }
268
+ buffer_json_object_close(wb);
269
+ buffer_json_add_array_item_object(wb);
270
+ {
271
+ buffer_json_member_add_string(wb, "id", "detailed");
272
+ buffer_json_member_add_string(wb, "name", "Detailed view of all sockets");
273
+ }
274
+ buffer_json_object_close(wb);
275
+ }
276
+ buffer_json_array_close(wb); // options array
277
}
278
buffer_json_object_close(wb);
279
}
350
- buffer_json_object_close(wb); // custom_charts
280
+ buffer_json_array_close(wb); // required_params
281
+#endif
282
+
283
+ char function_copy[strlen(function) + 1];
284
+ memcpy(function_copy, function, sizeof(function_copy));
285
+ char *words[1024];
286
+ size_t num_words = quoted_strings_splitter_pluginsd(function_copy, words, 1024);
287
+ for(size_t i = 1; i < num_words ;i++) {
288
+ char *param = get_word(words, num_words, i);
289
+ if(strcmp(param, "sockets:aggregated") == 0) {
290
+ aggregated = true;
291
+ }
292
+ else if(strcmp(param, "sockets:detailed") == 0) {
293
+ aggregated = false;
294
+ }
295
+ else if(strcmp(param, "info") == 0) {
296
+ goto close_and_send;
297
+ }
298
+ }
299
352
- buffer_json_member_add_object(wb, "charts");
300
{
354
- // Data Collection Age chart
355
- buffer_json_member_add_object(wb, "Count");
356
- {
357
- buffer_json_member_add_string(wb, "type", "stacked-bar");
358
- buffer_json_member_add_array(wb, "columns");
359
- {
360
- buffer_json_add_array_item_string(wb, "Direction");
361
- }
362
- buffer_json_array_close(wb);
301
+ buffer_json_member_add_array(wb, "data");
302
+
303
+ LS_STATE ls = {
304
+ .config = {
305
+ .listening = true,
306
+ .inbound = true,
307
+ .outbound = true,
308
+ .local = true,
309
+ .tcp4 = true,
310
+ .tcp6 = true,
311
+ .udp4 = true,
312
+ .udp6 = true,
313
+ .pid = true,
314
+ .uid = true,
315
+ .cmdline = true,
316
+ .comm = true,
317
+ .namespaces = true,
318
+
319
+ .max_errors = 10,
320
+ },
321
+ .stats = { 0 },
322
+ .sockets_hashtable = { 0 },
323
+ .local_ips_hashtable = { 0 },
324
+ .listening_ports_hashtable = { 0 },
325
+ };
326
+
327
+ SIMPLE_HASHTABLE_AGGREGATED_SOCKETS ht = { 0 };
328
+ if(aggregated) {
329
+ simple_hashtable_init_AGGREGATED_SOCKETS(&ht, 1024);
330
+ ls.config.cb = local_sockets_cb_to_aggregation;
331
+ ls.config.data = &ht;
332
+ }
333
+ else {
334
+ ls.config.cb = local_sockets_cb_to_json;
335
+ ls.config.data = wb;
336
}
364
- buffer_json_object_close(wb);
337
366
- // Streaming Age chart
367
- buffer_json_member_add_object(wb, "Count");
368
- {
369
- buffer_json_member_add_string(wb, "type", "stacked-bar");
370
- buffer_json_member_add_array(wb, "columns");
371
- {
372
- buffer_json_add_array_item_string(wb, "Process");
338
+ local_sockets_process(&ls);
339
+
340
+ if(aggregated) {
341
+ LOCAL_SOCKET *array[ht.used];
342
+ size_t added = 0;
343
+ uint64_t proc_self_net_ns_inode = ls.proc_self_net_ns_inode;
344
+ for(SIMPLE_HASHTABLE_SLOT_AGGREGATED_SOCKETS *sl = simple_hashtable_first_read_only_AGGREGATED_SOCKETS(&ht);
345
+ sl;
346
+ sl = simple_hashtable_next_read_only_AGGREGATED_SOCKETS(&ht, sl)) {
347
+ LOCAL_SOCKET *n = SIMPLE_HASHTABLE_SLOT_DATA(sl);
348
+ if(!n || added >= ht.used) continue;
349
+
350
+ array[added++] = n;
351
}
374
- buffer_json_array_close(wb);
375
- }
376
- buffer_json_object_close(wb);
352
378
- // DB Duration
379
- buffer_json_member_add_object(wb, "Count");
380
- {
381
- buffer_json_member_add_string(wb, "type", "stacked-bar");
382
- buffer_json_member_add_array(wb, "columns");
383
- {
384
- buffer_json_add_array_item_string(wb, "Protocol");
353
+ qsort(array, added, sizeof(LOCAL_SOCKET *), local_sockets_compar);
354
+
355
+ for(size_t i = 0; i < added ;i++) {
356
+ local_socket_to_json_array(wb, array[i], proc_self_net_ns_inode, true);
357
+ string_freez(array[i]->cmdline);
358
+ freez(array[i]);
359
}
386
- buffer_json_array_close(wb);
360
+
361
+ simple_hashtable_destroy_AGGREGATED_SOCKETS(&ht);
362
}
388
- buffer_json_object_close(wb);
389
- }
390
- buffer_json_object_close(wb); // charts
363
392
- buffer_json_member_add_array(wb, "default_charts");
393
- {
394
- buffer_json_add_array_item_array(wb);
395
- buffer_json_add_array_item_string(wb, "Count");
396
- buffer_json_add_array_item_string(wb, "Direction");
364
buffer_json_array_close(wb);
365
+ buffer_json_member_add_object(wb, "columns");
366
+ {
367
+ size_t field_id = 0;
368
+
369
+ // Direction
370
+ buffer_rrdf_table_add_field(wb, field_id++, "Direction", "Socket Direction",
371
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
372
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
373
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
374
+ RRDF_FIELD_OPTS_VISIBLE,
375
+ NULL);
376
+
377
+ // Protocol
378
+ buffer_rrdf_table_add_field(wb, field_id++, "Protocol", "Socket Protocol",
379
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
380
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
381
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
382
+ RRDF_FIELD_OPTS_VISIBLE,
383
+ NULL);
384
+
385
+ // Type
386
+ buffer_rrdf_table_add_field(wb, field_id++, "Namespace", "Namespace",
387
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
388
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
389
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
390
+ RRDF_FIELD_OPTS_VISIBLE,
391
+ NULL);
392
+
393
+ // State
394
+ buffer_rrdf_table_add_field(wb, field_id++, "State", "Socket State",
395
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
396
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
397
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
398
+ RRDF_FIELD_OPTS_VISIBLE,
399
+ NULL);
400
+
401
+ // Pid
402
+ buffer_rrdf_table_add_field(wb, field_id++, "PID", "Process ID",
403
+ RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
404
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
405
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
406
+ RRDF_FIELD_OPTS_VISIBLE,
407
+ NULL);
408
+
409
+ // Comm
410
+ buffer_rrdf_table_add_field(wb, field_id++, "Process", "Process Name",
411
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
412
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
413
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
414
+ RRDF_FIELD_OPTS_VISIBLE|RRDF_FIELD_OPTS_FULL_WIDTH,
415
+ NULL);
416
+
417
+// // Cmdline
418
+// buffer_rrdf_table_add_field(wb, field_id++, "CommandLine", "Command Line",
419
+// RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
420
+// 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
421
+// RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
422
+// RRDF_FIELD_OPTS_NONE|RRDF_FIELD_OPTS_FULL_WIDTH,
423
+// NULL);
424
+
425
+// // Uid
426
+// buffer_rrdf_table_add_field(wb, field_id++, "UID", "User ID",
427
+// RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
428
+// 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
429
+// RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
430
+// RRDF_FIELD_OPTS_NONE,
431
+// NULL);
432
+
433
+ // Username
434
+ buffer_rrdf_table_add_field(wb, field_id++, "User", "Username",
435
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
436
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
437
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
438
+ RRDF_FIELD_OPTS_VISIBLE,
439
+ NULL);
440
+
441
+ if(!aggregated) {
442
+ // Local Address
443
+ buffer_rrdf_table_add_field(wb, field_id++, "LocalIP", "Local IP Address",
444
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
445
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
446
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
447
+ RRDF_FIELD_OPTS_VISIBLE|RRDF_FIELD_OPTS_FULL_WIDTH,
448
+ NULL);
449
+
450
+ // Local Port
451
+ buffer_rrdf_table_add_field(wb, field_id++, "LocalPort", "Local Port",
452
+ RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
453
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
454
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
455
+ RRDF_FIELD_OPTS_VISIBLE,
456
+ NULL);
457
+ }
458
399
- buffer_json_add_array_item_array(wb);
400
- buffer_json_add_array_item_string(wb, "Count");
401
- buffer_json_add_array_item_string(wb, "Process");
402
- buffer_json_array_close(wb);
403
- }
404
- buffer_json_array_close(wb);
459
+ // Local Address Space
460
+ buffer_rrdf_table_add_field(wb, field_id++, "LocalAddressSpace", "Local IP Address Space",
461
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
462
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
463
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
464
+ RRDF_FIELD_OPTS_NONE,
465
+ NULL);
466
+
467
+ if(!aggregated) {
468
+ // Remote Address
469
+ buffer_rrdf_table_add_field(wb, field_id++, "RemoteIP", "Remote IP Address",
470
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
471
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
472
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
473
+ RRDF_FIELD_OPTS_VISIBLE|RRDF_FIELD_OPTS_FULL_WIDTH,
474
+ NULL);
475
+
476
+ // Remote Port
477
+ buffer_rrdf_table_add_field(wb, field_id++, "RemotePort", "Remote Port",
478
+ RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
479
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
480
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
481
+ RRDF_FIELD_OPTS_VISIBLE,
482
+ NULL);
483
+ }
484
406
- buffer_json_member_add_object(wb, "group_by");
407
- {
408
- buffer_json_member_add_object(wb, "Direction");
409
- {
410
- buffer_json_member_add_string(wb, "name", "Direction");
411
- buffer_json_member_add_array(wb, "columns");
412
- {
413
- buffer_json_add_array_item_string(wb, "Direction");
485
+ // Remote Address Space
486
+ buffer_rrdf_table_add_field(wb, field_id++, "RemoteAddressSpace", "Remote IP Address Space",
487
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
488
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
489
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
490
+ RRDF_FIELD_OPTS_NONE,
491
+ NULL);
492
+
493
+ if(aggregated) {
494
+ // Server IP
495
+ buffer_rrdf_table_add_field(wb, field_id++, "ServerIP", "Server IP Address",
496
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
497
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
498
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
499
+ RRDF_FIELD_OPTS_FULL_WIDTH | (aggregated ? RRDF_FIELD_OPTS_VISIBLE : RRDF_FIELD_OPTS_NONE),
500
+ NULL);
501
}
415
- buffer_json_array_close(wb);
502
+
503
+ // Server Port
504
+ buffer_rrdf_table_add_field(wb, field_id++, "ServerPort", "Server Port",
505
+ RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
506
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
507
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
508
+ aggregated ? RRDF_FIELD_OPTS_VISIBLE : RRDF_FIELD_OPTS_NONE,
509
+ NULL);
510
+
511
+ if(aggregated) {
512
+ // Client Address Space
513
+ buffer_rrdf_table_add_field(wb, field_id++, "ClientAddressSpace", "Client IP Address Space",
514
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
515
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
516
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
517
+ RRDF_FIELD_OPTS_VISIBLE,
518
+ NULL);
519
+
520
+ // Server Address Space
521
+ buffer_rrdf_table_add_field(wb, field_id++, "ServerAddressSpace", "Server IP Address Space",
522
+ RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
523
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
524
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
525
+ RRDF_FIELD_OPTS_VISIBLE,
526
+ NULL);
527
+ }
528
+
529
+// // inode
530
+// buffer_rrdf_table_add_field(wb, field_id++, "Inode", "Socket Inode",
531
+// RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
532
+// 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
533
+// RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
534
+// RRDF_FIELD_OPTS_NONE,
535
+// NULL);
536
+
537
+// // Namespace inode
538
+// buffer_rrdf_table_add_field(wb, field_id++, "Namespace Inode", "Namespace Inode",
539
+// RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
540
+// 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
541
+// RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
542
+// RRDF_FIELD_OPTS_NONE,
543
+// NULL);
544
+
545
+ // Count
546
+ buffer_rrdf_table_add_field(wb, field_id++, "Count", "Number of sockets like this",
547
+ RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE,
548
+ 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL,
549
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
550
+ aggregated ? RRDF_FIELD_OPTS_VISIBLE : RRDF_FIELD_OPTS_NONE,
551
+ NULL);
552
}
417
- buffer_json_object_close(wb);
553
+ buffer_json_object_close(wb); // columns
554
+ buffer_json_member_add_string(wb, "default_sort_column", "Direction");
555
419
- buffer_json_member_add_object(wb, "Protocol");
556
+ buffer_json_member_add_object(wb, "custom_charts");
557
{
421
- buffer_json_member_add_string(wb, "name", "Protocol");
422
- buffer_json_member_add_array(wb, "columns");
558
+ buffer_json_member_add_object(wb, "Network Map");
559
{
424
- buffer_json_add_array_item_string(wb, "Protocol");
560
+ buffer_json_member_add_string(wb, "type", "network-viewer");
561
}
426
- buffer_json_array_close(wb);
562
+ buffer_json_object_close(wb);
563
}
428
- buffer_json_object_close(wb);
564
+ buffer_json_object_close(wb); // custom_charts
565
430
- buffer_json_member_add_object(wb, "Namespace");
566
+ buffer_json_member_add_object(wb, "charts");
567
{
432
- buffer_json_member_add_string(wb, "name", "Namespace");
433
- buffer_json_member_add_array(wb, "columns");
568
+ // Data Collection Age chart
569
+ buffer_json_member_add_object(wb, "Count");
570
{
435
- buffer_json_add_array_item_string(wb, "Namespace");
571
+ buffer_json_member_add_string(wb, "type", "stacked-bar");
572
+ buffer_json_member_add_array(wb, "columns");
573
+ {
574
+ buffer_json_add_array_item_string(wb, "Direction");
575
+ }
576
+ buffer_json_array_close(wb);
577
}
437
- buffer_json_array_close(wb);
438
- }
439
- buffer_json_object_close(wb);
578
+ buffer_json_object_close(wb);
579
441
- buffer_json_member_add_object(wb, "Process");
442
- {
443
- buffer_json_member_add_string(wb, "name", "Process");
444
- buffer_json_member_add_array(wb, "columns");
580
+ // Streaming Age chart
581
+ buffer_json_member_add_object(wb, "Count");
582
{
446
- buffer_json_add_array_item_string(wb, "Process");
583
+ buffer_json_member_add_string(wb, "type", "stacked-bar");
584
+ buffer_json_member_add_array(wb, "columns");
585
+ {
586
+ buffer_json_add_array_item_string(wb, "Process");
587
+ }
588
+ buffer_json_array_close(wb);
589
}
448
- buffer_json_array_close(wb);
449
- }
450
- buffer_json_object_close(wb);
590
+ buffer_json_object_close(wb);
591
452
- buffer_json_member_add_object(wb, "LocalIP");
453
- {
454
- buffer_json_member_add_string(wb, "name", "Local IP");
455
- buffer_json_member_add_array(wb, "columns");
592
+ // DB Duration
593
+ buffer_json_member_add_object(wb, "Count");
594
{
457
- buffer_json_add_array_item_string(wb, "LocalIP");
595
+ buffer_json_member_add_string(wb, "type", "stacked-bar");
596
+ buffer_json_member_add_array(wb, "columns");
597
+ {
598
+ buffer_json_add_array_item_string(wb, "Protocol");
599
+ }
600
+ buffer_json_array_close(wb);
601
}
459
- buffer_json_array_close(wb);
602
+ buffer_json_object_close(wb);
603
}
461
- buffer_json_object_close(wb);
604
+ buffer_json_object_close(wb); // charts
605
463
- buffer_json_member_add_object(wb, "LocalPort");
606
+ buffer_json_member_add_array(wb, "default_charts");
607
{
465
- buffer_json_member_add_string(wb, "name", "Local Port");
466
- buffer_json_member_add_array(wb, "columns");
467
- {
468
- buffer_json_add_array_item_string(wb, "LocalPort");
469
- }
608
+ buffer_json_add_array_item_array(wb);
609
+ buffer_json_add_array_item_string(wb, "Count");
610
+ buffer_json_add_array_item_string(wb, "Direction");
611
+ buffer_json_array_close(wb);
612
+
613
+ buffer_json_add_array_item_array(wb);
614
+ buffer_json_add_array_item_string(wb, "Count");
615
+ buffer_json_add_array_item_string(wb, "Process");
616
buffer_json_array_close(wb);
617
}
472
- buffer_json_object_close(wb);
618
+ buffer_json_array_close(wb);
619
474
- buffer_json_member_add_object(wb, "RemoteIP");
620
+ buffer_json_member_add_object(wb, "group_by");
621
{
476
- buffer_json_member_add_string(wb, "name", "Remote IP");
477
- buffer_json_member_add_array(wb, "columns");
622
+ buffer_json_member_add_object(wb, "Direction");
623
{
479
- buffer_json_add_array_item_string(wb, "RemoteIP");
624
+ buffer_json_member_add_string(wb, "name", "Direction");
625
+ buffer_json_member_add_array(wb, "columns");
626
+ {
627
+ buffer_json_add_array_item_string(wb, "Direction");
628
+ }
629
+ buffer_json_array_close(wb);
630
}
481
- buffer_json_array_close(wb);
482
- }
483
- buffer_json_object_close(wb);
631
+ buffer_json_object_close(wb);
632
485
- buffer_json_member_add_object(wb, "RemotePort");
486
- {
487
- buffer_json_member_add_string(wb, "name", "Remote Port");
488
- buffer_json_member_add_array(wb, "columns");
633
+ buffer_json_member_add_object(wb, "Protocol");
634
{
490
- buffer_json_add_array_item_string(wb, "RemotePort");
635
+ buffer_json_member_add_string(wb, "name", "Protocol");
636
+ buffer_json_member_add_array(wb, "columns");
637
+ {
638
+ buffer_json_add_array_item_string(wb, "Protocol");
639
+ }
640
+ buffer_json_array_close(wb);
641
+ }
642
+ buffer_json_object_close(wb);
643
+
644
+ buffer_json_member_add_object(wb, "Namespace");
645
+ {
646
+ buffer_json_member_add_string(wb, "name", "Namespace");
647
+ buffer_json_member_add_array(wb, "columns");
648
+ {
649
+ buffer_json_add_array_item_string(wb, "Namespace");
650
+ }
651
+ buffer_json_array_close(wb);
652
+ }
653
+ buffer_json_object_close(wb);
654
+
655
+ buffer_json_member_add_object(wb, "Process");
656
+ {
657
+ buffer_json_member_add_string(wb, "name", "Process");
658
+ buffer_json_member_add_array(wb, "columns");
659
+ {
660
+ buffer_json_add_array_item_string(wb, "Process");
661
+ }
662
+ buffer_json_array_close(wb);
663
+ }
664
+ buffer_json_object_close(wb);
665
+
666
+ if(!aggregated) {
667
+ buffer_json_member_add_object(wb, "LocalIP");
668
+ {
669
+ buffer_json_member_add_string(wb, "name", "Local IP");
670
+ buffer_json_member_add_array(wb, "columns");
671
+ {
672
+ buffer_json_add_array_item_string(wb, "LocalIP");
673
+ }
674
+ buffer_json_array_close(wb);
675
+ }
676
+ buffer_json_object_close(wb);
677
+
678
+ buffer_json_member_add_object(wb, "LocalPort");
679
+ {
680
+ buffer_json_member_add_string(wb, "name", "Local Port");
681
+ buffer_json_member_add_array(wb, "columns");
682
+ {
683
+ buffer_json_add_array_item_string(wb, "LocalPort");
684
+ }
685
+ buffer_json_array_close(wb);
686
+ }
687
+ buffer_json_object_close(wb);
688
+
689
+ buffer_json_member_add_object(wb, "RemoteIP");
690
+ {
691
+ buffer_json_member_add_string(wb, "name", "Remote IP");
692
+ buffer_json_member_add_array(wb, "columns");
693
+ {
694
+ buffer_json_add_array_item_string(wb, "RemoteIP");
695
+ }
696
+ buffer_json_array_close(wb);
697
+ }
698
+ buffer_json_object_close(wb);
699
+
700
+ buffer_json_member_add_object(wb, "RemotePort");
701
+ {
702
+ buffer_json_member_add_string(wb, "name", "Remote Port");
703
+ buffer_json_member_add_array(wb, "columns");
704
+ {
705
+ buffer_json_add_array_item_string(wb, "RemotePort");
706
+ }
707
+ buffer_json_array_close(wb);
708
+ }
709
+ buffer_json_object_close(wb);
710
}
492
- buffer_json_array_close(wb);
711
}
494
- buffer_json_object_close(wb);
712
+ buffer_json_object_close(wb); // group_by
713
}
496
- buffer_json_object_close(wb); // group_by
497
-
714
499
- buffer_json_member_add_time_t(wb, "expires", now_realtime_sec() + 1);
715
+close_and_send:
716
+ buffer_json_member_add_time_t(wb, "expires", now_s + 1);
717
buffer_json_finalize(wb);
718
719
netdata_mutex_lock(&stdout_mutex);
503
- pluginsd_function_result_to_stdout(transaction, HTTP_RESP_OK, "application/json", now_realtime_sec(), wb);
720
+ pluginsd_function_result_to_stdout(transaction, HTTP_RESP_OK, "application/json", now_s + 1, wb);
721
netdata_mutex_unlock(&stdout_mutex);
722
}
723
@@ -519,6 +736,21 @@ int main(int argc __maybe_unused, char **argv __maybe_unused) {
736
737
// ----------------------------------------------------------------------------------------------------------------
738
739
+ if(argc == 2 && strcmp(argv[1], "debug") == 0) {
740
+ bool cancelled = false;
741
+ usec_t stop_monotonic_ut = now_monotonic_usec() + 600 * USEC_PER_SEC;
742
+ char buf[] = "network-connections sockets:aggregated";
743
+ network_viewer_function("123", buf, &stop_monotonic_ut, &cancelled,
744
+ NULL, HTTP_ACCESS_ALL, NULL, NULL);
745
+
746
+ char buf2[] = "network-connections sockets:detailed";
747
+ network_viewer_function("123", buf2, &stop_monotonic_ut, &cancelled,
748
+ NULL, HTTP_ACCESS_ALL, NULL, NULL);
749
+ exit(1);
750
+ }
751
+
752
+ // ----------------------------------------------------------------------------------------------------------------
753
+
754
fprintf(stdout, PLUGINSD_KEYWORD_FUNCTION " GLOBAL \"%s\" %d \"%s\" \"top\" "HTTP_ACCESS_FORMAT" %d\n",
755
NETWORK_CONNECTIONS_VIEWER_FUNCTION, 60,
756
NETWORK_CONNECTIONS_VIEWER_HELP,
collectors/plugins.d/local_listeners.c
+1
-1
@@ -40,7 +40,7 @@ static void print_local_listeners(LS_STATE *ls __maybe_unused, LOCAL_SOCKET *n,
40
ipv6_address_to_txt(&n->remote.ip.ipv6, remote_address);
41
}
42
43
- printf("%s|%s|%u|%s\n", protocol_name(n), local_address, n->local.port, n->cmdline ? n->cmdline : "");
43
+ printf("%s|%s|%u|%s\n", protocol_name(n), local_address, n->local.port, string2str(n->cmdline));
44
}
45
46
static void print_local_listeners_debug(LS_STATE *ls __maybe_unused, LOCAL_SOCKET *n, void *data __maybe_unused) {
collectors/plugins.d/pluginsd_functions.c
+4
-1
@@ -13,7 +13,7 @@ static void inflight_functions_insert_callback(const DICTIONARY_ITEM *item, void
13
PARSER *parser = parser_ptr;
14
15
// leave this code as default, so that when the dictionary is destroyed this will be sent back to the caller
16
- pf->code = HTTP_RESP_GATEWAY_TIMEOUT;
16
+ pf->code = HTTP_RESP_SERVICE_UNAVAILABLE;
17
18
const char *transaction = dictionary_acquired_item_name(item);
19
@@ -93,6 +93,9 @@ static void inflight_functions_delete_callback(const DICTIONARY_ITEM *item __may
93
buffer_strlen(pf->result_body_wb),
94
pf->sent_monotonic_ut - pf->started_monotonic_ut, now_realtime_usec() - pf->sent_monotonic_ut);
95
96
+ if(pf->code == HTTP_RESP_SERVICE_UNAVAILABLE && !buffer_strlen(pf->result_body_wb))
97
+ rrd_call_function_error(pf->result_body_wb, "The plugin exited while servicing this call.", pf->code);
98
+
99
pf->result.cb(pf->result_body_wb, pf->code, pf->result.data);
100
101
string_freez(pf->function);
collectors/proc.plugin/proc_diskstats.c
+1
@@ -1042,6 +1042,7 @@ static int diskstats_function_block_devices(BUFFER *wb, const char *function __m
1042
buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
1043
buffer_json_member_add_string(wb, "type", "table");
1044
buffer_json_member_add_time_t(wb, "update_every", 1);
1045
+ buffer_json_member_add_boolean(wb, "has_history", false);
1046
buffer_json_member_add_string(wb, "help", RRDFUNCTIONS_DISKSTATS_HELP);
1047
buffer_json_member_add_array(wb, "data");
1048
collectors/proc.plugin/proc_net_dev.c
+1
@@ -482,6 +482,7 @@ int netdev_function_net_interfaces(BUFFER *wb, const char *function __maybe_unus
482
buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
483
buffer_json_member_add_string(wb, "type", "table");
484
buffer_json_member_add_time_t(wb, "update_every", 1);
485
+ buffer_json_member_add_boolean(wb, "has_history", false);
486
buffer_json_member_add_string(wb, "help", RRDFUNCTIONS_NETDEV_HELP);
487
buffer_json_member_add_array(wb, "data");
488
src/database/rrdfunctions-inflight.c
-1
@@ -427,7 +427,6 @@ int rrd_function_run(RRDHOST *host, BUFFER *result_wb, int timeout_s,
427
428
code = rrd_functions_find_by_name(host, result_wb, sanitized_cmd, sanitized_cmd_length, &host_function_acquired);
429
if(code != HTTP_RESP_OK) {
430
- rrd_call_function_error(result_wb, "not found", code);
430
431
if(result_cb)
432
result_cb(result_wb, code, result_cb_data);
src/database/rrdfunctions-streaming.c
+1
@@ -14,6 +14,7 @@ int rrdhost_function_streaming(BUFFER *wb, const char *function __maybe_unused)
14
buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
15
buffer_json_member_add_string(wb, "type", "table");
16
buffer_json_member_add_time_t(wb, "update_every", 1);
17
+ buffer_json_member_add_boolean(wb, "has_history", false);
18
buffer_json_member_add_string(wb, "help", RRDFUNCTIONS_STREAMING_HELP);
19
buffer_json_member_add_array(wb, "data");
20
src/libnetdata/aral/aral.c
+6
@@ -464,6 +464,12 @@ static inline ARAL_PAGE *aral_acquire_a_free_slot(ARAL *ar TRACE_ALLOCATIONS_FUN
464
return page;
465
}
466
467
+void *aral_callocz_internal(ARAL *ar TRACE_ALLOCATIONS_FUNCTION_DEFINITION_PARAMS) {
468
+ void *r = aral_mallocz_internal(ar TRACE_ALLOCATIONS_FUNCTION_CALL_PARAMS);
469
+ memset(r, 0, ar->config.requested_element_size);
470
+ return r;
471
+}
472
+
473
void *aral_mallocz_internal(ARAL *ar TRACE_ALLOCATIONS_FUNCTION_DEFINITION_PARAMS) {
474
#ifdef FSANITIZE_ADDRESS
475
return mallocz(ar->config.requested_element_size);
src/libnetdata/aral/aral.h
+4
@@ -46,10 +46,12 @@ int aral_unittest(size_t elements);
46
47
#ifdef NETDATA_TRACE_ALLOCATIONS
48
49
+#define aral_callocz(ar) aral_callocz_internal(ar, __FILE__, __FUNCTION__, __LINE__)
50
#define aral_mallocz(ar) aral_mallocz_internal(ar, __FILE__, __FUNCTION__, __LINE__)
51
#define aral_freez(ar, ptr) aral_freez_internal(ar, ptr, __FILE__, __FUNCTION__, __LINE__)
52
#define aral_destroy(ar) aral_destroy_internal(ar, __FILE__, __FUNCTION__, __LINE__)
53
54
+void *aral_callocz_internal(ARAL *ar, const char *file, const char *function, size_t line);
55
void *aral_mallocz_internal(ARAL *ar, const char *file, const char *function, size_t line);
56
void aral_freez_internal(ARAL *ar, void *ptr, const char *file, const char *function, size_t line);
57
void aral_destroy_internal(ARAL *ar, const char *file, const char *function, size_t line);
@@ -57,9 +59,11 @@ void aral_destroy_internal(ARAL *ar, const char *file, const char *function, siz
59
#else // NETDATA_TRACE_ALLOCATIONS
60
61
#define aral_mallocz(ar) aral_mallocz_internal(ar)
62
+#define aral_callocz(ar) aral_callocz_internal(ar)
63
#define aral_freez(ar, ptr) aral_freez_internal(ar, ptr)
64
#define aral_destroy(ar) aral_destroy_internal(ar)
65
66
+void *aral_callocz_internal(ARAL *ar);
67
void *aral_mallocz_internal(ARAL *ar);
68
void aral_freez_internal(ARAL *ar, void *ptr);
69
void aral_destroy_internal(ARAL *ar);
src/libnetdata/buffer/buffer.c
+4
-2
@@ -341,8 +341,10 @@ __attribute__((constructor)) void initialize_ascii_maps(void) {
341
base64_value_from_ascii[i] = 255;
342
}
343
344
- for(size_t i = 0; i < 16 ; i++)
345
- hex_value_from_ascii[(int)hex_digits[i]] = i;
344
+ for(size_t i = 0; i < 16 ; i++) {
345
+ hex_value_from_ascii[(int)toupper(hex_digits[i])] = i;
346
+ hex_value_from_ascii[(int)tolower(hex_digits[i])] = i;
347
+ }
348
349
for(size_t i = 0; i < 64 ; i++)
350
base64_value_from_ascii[(int)base64_digits[i]] = i;
src/libnetdata/inlined.h
+17
-1
@@ -204,12 +204,28 @@ static inline long long str2ll(const char *s, char **endptr) {
204
}
205
}
206
207
+static inline uint32_t str2uint32_hex(const char *src, char **endptr) {
208
+ uint32_t num = 0;
209
+ const unsigned char *s = (const unsigned char *)src;
210
+ unsigned char c;
211
+
212
+ while ((c = hex_value_from_ascii[(uint8_t)*s]) != 255) {
213
+ num = (num << 4) | c;
214
+ s++;
215
+ }
216
+
217
+ if(endptr)
218
+ *endptr = (char *)s;
219
+
220
+ return num;
221
+}
222
+
223
static inline uint64_t str2uint64_hex(const char *src, char **endptr) {
224
uint64_t num = 0;
225
const unsigned char *s = (const unsigned char *)src;
226
unsigned char c;
227
212
- while ((c = hex_value_from_ascii[toupper(*s)]) != 255) {
228
+ while ((c = hex_value_from_ascii[(uint8_t)*s]) != 255) {
229
num = (num << 4) | c;
230
s++;
231
}
src/libnetdata/maps/local-sockets.h
+97
-49
@@ -104,6 +104,9 @@ typedef struct local_socket_state {
104
uint16_t tmp_protocol;
105
#endif
106
107
+ ARAL *local_socket_aral;
108
+ ARAL *pid_socket_aral;
109
+
110
uint64_t proc_self_net_ns_inode;
111
112
SIMPLE_HASHTABLE_NET_NS ns_hashtable;
@@ -162,7 +165,7 @@ static inline void ipv6_to_in6_addr(const char *ipv6_str, struct in6_addr *d) {
165
for (size_t k = 0; k < 4; ++k) {
166
memcpy(buf, ipv6_str + (k * 8), 8);
167
buf[sizeof(buf) - 1] = '\0';
165
- d->s6_addr32[k] = strtoul(buf, NULL, 16);
168
+ d->s6_addr32[k] = str2uint32_hex(buf, NULL);
169
}
170
}
171
@@ -185,13 +188,17 @@ typedef struct local_socket {
188
uid_t uid;
189
190
char comm[TASK_COMM_LEN];
188
- char *cmdline;
191
+ STRING *cmdline;
192
193
struct local_port local_port_key;
194
195
XXH64_hash_t local_ip_hash;
196
XXH64_hash_t remote_ip_hash;
197
XXH64_hash_t local_port_hash;
198
+
199
+#ifdef LOCAL_SOCKETS_EXTENDED_MEMBERS
200
+ LOCAL_SOCKETS_EXTENDED_MEMBERS
201
+#endif
202
} LOCAL_SOCKET;
203
204
// --------------------------------------------------------------------------------------------------------------------
@@ -393,7 +400,7 @@ static inline bool local_sockets_find_all_sockets_in_proc(LS_STATE *ls, const ch
400
}
401
402
if(!ps)
396
- ps = callocz(1, sizeof(*ps));
403
+ ps = aral_callocz(ls->pid_socket_aral);
404
405
ps->inode = inode;
406
ps->pid = pid;
@@ -559,7 +566,7 @@ static inline bool local_sockets_add_socket(LS_STATE *ls, LOCAL_SOCKET *tmp) {
566
return false;
567
}
568
562
- n = (LOCAL_SOCKET *)callocz(1, sizeof(LOCAL_SOCKET));
569
+ n = aral_mallocz(ls->local_socket_aral);
570
*n = *tmp; // copy all contents
571
572
// fix the key
@@ -584,7 +591,8 @@ static inline bool local_sockets_add_socket(LS_STATE *ls, LOCAL_SOCKET *tmp) {
591
n->uid = ps->uid;
592
593
if(ps->cmdline)
587
- n->cmdline = strdupz(ps->cmdline);
594
+ n->cmdline = string_strdupz(ps->cmdline);
595
+
596
strncpyz(n->comm, ps->comm, sizeof(n->comm) - 1);
597
}
598
@@ -731,18 +739,27 @@ static inline bool local_sockets_netlink_get_sockets(LS_STATE *ls, uint16_t fami
739
#endif // HAVE_LIBMNL
740
741
static inline bool local_sockets_read_proc_net_x(LS_STATE *ls, const char *filename, uint16_t family, uint16_t protocol) {
742
+ static bool is_space[256] = {
743
+ [':'] = true,
744
+ [' '] = true,
745
+ };
746
+
747
if(family != AF_INET && family != AF_INET6)
748
return false;
749
737
- FILE *fp;
738
- char *line = NULL;
739
- size_t len = 0;
740
- ssize_t read;
741
-
742
- fp = fopen(filename, "r");
750
+ FILE *fp = fopen(filename, "r");
751
if (fp == NULL)
752
return false;
753
754
+ char *line = malloc(1024); // no mallocz() here because getline() may resize
755
+ if(!line) {
756
+ fclose(fp);
757
+ return false;
758
+ }
759
+
760
+ size_t len = 1024;
761
+ ssize_t read;
762
+
763
ssize_t min_line_length = (family == AF_INET) ? 105 : 155;
764
size_t counter = 0;
765
@@ -755,49 +772,60 @@ static inline bool local_sockets_read_proc_net_x(LS_STATE *ls, const char *filen
772
continue;
773
}
774
758
- unsigned int local_address, local_port, state, remote_address, remote_port;
759
- uint64_t inode = 0;
760
- char local_address6[33], remote_address6[33];
761
-
762
- if(family == AF_INET) {
763
- if (sscanf(line, "%*d: %X:%X %X:%X %X %*X:%*X %*X:%*X %*X %*d %*d %"PRIu64,
764
- &local_address, &local_port, &remote_address, &remote_port, &state, &inode) != 6) {
765
- local_sockets_log(ls, "cannot parse ipv4 line No %zu of filename '%s': %s", counter, filename, line);
766
- continue;
767
- }
768
- }
769
- else if(family == AF_INET6) {
770
- if(sscanf(line, "%*d: %32[0-9A-Fa-f]:%X %32[0-9A-Fa-f]:%X %X %*X:%*X %*X:%*X %*X %*d %*d %"PRIu64,
771
- local_address6, &local_port, remote_address6, &remote_port, &state, &inode) != 6) {
772
- local_sockets_log(ls, "cannot parse ipv6 line No %zu of filename '%s': %s", counter, filename, line);
773
- continue;
774
- }
775
- }
776
-
775
LOCAL_SOCKET n = {
778
- .inode = inode,
776
.direction = SOCKET_DIRECTION_NONE,
780
- .state = (int)state,
777
.local = {
778
.family = family,
779
.protocol = protocol,
784
- .port = local_port,
780
},
781
.remote = {
782
.family = family,
783
.protocol = protocol,
789
- .port = remote_port,
784
},
785
.uid = UID_UNSET,
786
};
787
788
+ char *words[32];
789
+ size_t num_words = quoted_strings_splitter(line, words, 32, is_space);
790
+ // char *sl_txt = get_word(words, num_words, 0);
791
+ char *local_ip_txt = get_word(words, num_words, 1);
792
+ char *local_port_txt = get_word(words, num_words, 2);
793
+ char *remote_ip_txt = get_word(words, num_words, 3);
794
+ char *remote_port_txt = get_word(words, num_words, 4);
795
+ char *state_txt = get_word(words, num_words, 5);
796
+ char *tx_queue_txt = get_word(words, num_words, 6);
797
+ char *rx_queue_txt = get_word(words, num_words, 7);
798
+ char *tr_txt = get_word(words, num_words, 8);
799
+ char *tm_when_txt = get_word(words, num_words, 9);
800
+ char *retrans_txt = get_word(words, num_words, 10);
801
+ char *uid_txt = get_word(words, num_words, 11);
802
+ // char *timeout_txt = get_word(words, num_words, 12);
803
+ char *inode_txt = get_word(words, num_words, 13);
804
+
805
+ if(!local_ip_txt || !local_port_txt || !remote_ip_txt || !remote_port_txt || !state_txt ||
806
+ !tx_queue_txt || !rx_queue_txt || !tr_txt || !tm_when_txt || !retrans_txt || !uid_txt || !inode_txt) {
807
+ local_sockets_log(ls, "cannot parse ipv4 line No %zu of filename '%s'", counter, filename);
808
+ continue;
809
+ }
810
+
811
+ n.local.port = str2uint32_hex(local_port_txt, NULL);
812
+ n.remote.port = str2uint32_hex(remote_port_txt, NULL);
813
+ n.state = str2uint32_hex(state_txt, NULL);
814
+ n.wqueue = str2uint32_hex(tx_queue_txt, NULL);
815
+ n.rqueue = str2uint32_hex(rx_queue_txt, NULL);
816
+ n.timer = str2uint32_hex(tr_txt, NULL);
817
+ n.expires = str2uint32_hex(tm_when_txt, NULL);
818
+ n.retransmits = str2uint32_hex(retrans_txt, NULL);
819
+ n.uid = str2uint32_t(uid_txt, NULL);
820
+ n.inode = str2uint64_t(inode_txt, NULL);
821
+
822
if(family == AF_INET) {
795
- n.local.ip.ipv4 = local_address;
796
- n.remote.ip.ipv4 = remote_address;
823
+ n.local.ip.ipv4 = str2uint32_hex(local_ip_txt, NULL);
824
+ n.remote.ip.ipv4 = str2uint32_hex(remote_ip_txt, NULL);
825
}
826
else if(family == AF_INET6) {
799
- ipv6_to_in6_addr(local_address6, &n.local.ip.ipv6);
800
- ipv6_to_in6_addr(remote_address6, &n.remote.ip.ipv6);
827
+ ipv6_to_in6_addr(local_ip_txt, &n.local.ip.ipv6);
828
+ ipv6_to_in6_addr(remote_ip_txt, &n.remote.ip.ipv6);
829
}
830
831
local_sockets_add_socket(ls, &n);
@@ -806,7 +834,7 @@ static inline bool local_sockets_read_proc_net_x(LS_STATE *ls, const char *filen
834
fclose(fp);
835
836
if (line)
809
- freez(line);
837
+ free(line); // no freez() here because getline() may resize
838
839
return true;
840
}
@@ -881,6 +909,20 @@ static inline void local_sockets_init(LS_STATE *ls) {
909
simple_hashtable_init_LOCAL_SOCKET(&ls->sockets_hashtable, 65535);
910
simple_hashtable_init_LOCAL_IP(&ls->local_ips_hashtable, 4096);
911
simple_hashtable_init_LISTENING_PORT(&ls->listening_ports_hashtable, 4096);
912
+
913
+ ls->local_socket_aral = aral_create(
914
+ "local-sockets",
915
+ sizeof(LOCAL_SOCKET),
916
+ 65536,
917
+ 65536,
918
+ NULL, NULL, NULL, false, true);
919
+
920
+ ls->pid_socket_aral = aral_create(
921
+ "pid-sockets",
922
+ sizeof(struct pid_socket),
923
+ 65536,
924
+ 65536,
925
+ NULL, NULL, NULL, false, true);
926
}
927
928
static inline void local_sockets_cleanup(LS_STATE *ls) {
@@ -891,8 +933,8 @@ static inline void local_sockets_cleanup(LS_STATE *ls) {
933
LOCAL_SOCKET *n = SIMPLE_HASHTABLE_SLOT_DATA(sl);
934
if(!n) continue;
935
894
- freez(n->cmdline);
895
- freez(n);
936
+ string_freez(n->cmdline);
937
+ aral_freez(ls->local_socket_aral, n);
938
}
939
940
// free the pid_socket hashtable data
@@ -903,7 +945,7 @@ static inline void local_sockets_cleanup(LS_STATE *ls) {
945
if(!ps) continue;
946
947
freez(ps->cmdline);
906
- freez(ps);
948
+ aral_freez(ls->pid_socket_aral, ps);
949
}
950
951
// free the hashtable
@@ -912,6 +954,9 @@ static inline void local_sockets_cleanup(LS_STATE *ls) {
954
simple_hashtable_destroy_LISTENING_PORT(&ls->listening_ports_hashtable);
955
simple_hashtable_destroy_LOCAL_IP(&ls->local_ips_hashtable);
956
simple_hashtable_destroy_LOCAL_SOCKET(&ls->sockets_hashtable);
957
+
958
+ aral_destroy(ls->local_socket_aral);
959
+ aral_destroy(ls->pid_socket_aral);
960
}
961
962
// --------------------------------------------------------------------------------------------------------------------
@@ -982,12 +1027,12 @@ static inline void local_sockets_send_to_parent(struct local_socket_state *ls __
1027
if(write(fd, n, sizeof(*n)) != sizeof(*n))
1028
local_sockets_log(ls, "failed to write local socket to pipe");
1029
985
- size_t len = n->cmdline ? strlen(n->cmdline) + 1 : 0;
1030
+ size_t len = n->cmdline ? string_strlen(n->cmdline) + 1 : 0;
1031
if(write(fd, &len, sizeof(len)) != sizeof(len))
1032
local_sockets_log(ls, "failed to write cmdline length to pipe");
1033
1034
if(len)
990
- if(write(fd, n->cmdline, len) != (ssize_t)len)
1035
+ if(write(fd, string2str(n->cmdline), len) != (ssize_t)len)
1036
local_sockets_log(ls, "failed to write cmdline to pipe");
1037
}
1038
@@ -1087,9 +1132,13 @@ static inline bool local_sockets_get_namespace_sockets(LS_STATE *ls, struct pid_
1132
local_sockets_log(ls, "failed to read cmdline length from pipe");
1133
1134
if(len) {
1090
- buf.cmdline = mallocz(len);
1091
- if(read(pipefd[0], buf.cmdline, len) != (ssize_t)len)
1135
+ char cmdline[len + 1];
1136
+ if(read(pipefd[0], cmdline, len) != (ssize_t)len)
1137
local_sockets_log(ls, "failed to read cmdline from pipe");
1138
+ else {
1139
+ cmdline[len] = '\0';
1140
+ buf.cmdline = string_strdupz(cmdline);
1141
+ }
1142
}
1143
else
1144
buf.cmdline = NULL;
@@ -1107,8 +1156,7 @@ static inline bool local_sockets_get_namespace_sockets(LS_STATE *ls, struct pid_
1156
SIMPLE_HASHTABLE_SLOT_LOCAL_SOCKET *sl = simple_hashtable_get_slot_LOCAL_SOCKET(&ls->sockets_hashtable, buf.inode, &buf, true);
1157
LOCAL_SOCKET *n = SIMPLE_HASHTABLE_SLOT_DATA(sl);
1158
if(n) {
1110
- if(buf.cmdline)
1111
- freez(buf.cmdline);
1159
+ string_freez(buf.cmdline);
1160
1161
// local_sockets_log(ls,
1162
// "ns inode %" PRIu64" (comm: '%s', pid: %u, ns: %"PRIu64") already exists in hashtable (comm: '%s', pid: %u, ns: %"PRIu64") - ignoring duplicate",
@@ -1116,7 +1164,7 @@ static inline bool local_sockets_get_namespace_sockets(LS_STATE *ls, struct pid_
1164
continue;
1165
}
1166
else {
1119
- n = mallocz(sizeof(*n));
1167
+ n = aral_mallocz(ls->local_socket_aral);
1168
memcpy(n, &buf, sizeof(*n));
1169
simple_hashtable_set_slot_LOCAL_SOCKET(&ls->sockets_hashtable, sl, n->inode, n);
1170
src/libnetdata/query_progress/progress.c
+1
@@ -408,6 +408,7 @@ int progress_function_result(BUFFER *wb, const char *hostname) {
408
buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
409
buffer_json_member_add_string(wb, "type", "table");
410
buffer_json_member_add_time_t(wb, "update_every", 1);
411
+ buffer_json_member_add_boolean(wb, "has_history", false);
412
buffer_json_member_add_string(wb, "help", RRDFUNCTIONS_PROGRESS_HELP);
413
buffer_json_member_add_array(wb, "data");
414
src/libnetdata/socket/socket.c
+1
-1
@@ -1387,7 +1387,7 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien
1387
struct sockaddr_storage sadr;
1388
socklen_t addrlen = sizeof(sadr);
1389
1390
- int nfd = accept4(fd, (struct sockaddr *)&sadr, &addrlen, flags);
1390
+ int nfd = accept4(fd, (struct sockaddr *)&sadr, &addrlen, flags | SOCK_CLOEXEC);
1391
if (likely(nfd >= 0)) {
1392
if (getnameinfo((struct sockaddr *)&sadr, addrlen, client_ip, (socklen_t)ipsize,
1393
client_port, (socklen_t)portsize, NI_NUMERICHOST | NI_NUMERICSERV) != 0) {