Network viewer: filter by username (#16911)
* add users to network-connections function * cleaner and simpler filters; removed IPs and ports, added serverPort
Costa Tsaousis committed
Feb 2, 2024 at 02:33 UTC
2a4dd3252615197dd8db4ba85b48d222e32c1b27
9 files changed
+281
-147
CMakeLists.txt
+5
-2
@@ -1104,6 +1104,8 @@ set(SYSTEMD_JOURNAL_PLUGIN_FILES
1104
collectors/systemd-journal.plugin/systemd-journal-fstat.c
1105
collectors/systemd-journal.plugin/systemd-journal-watcher.c
1106
collectors/systemd-journal.plugin/systemd-journal-dyncfg.c
1107
+ src/libnetdata/maps/system-users.h
1108
+ src/libnetdata/maps/system-groups.h
1109
)
1110
1111
set(STREAMING_PLUGIN_FILES
@@ -1984,7 +1986,7 @@ endif()
1986
if(ENABLE_PLUGIN_LOCAL_LISTENERS)
1987
set(LOCAL_LISTENERS_FILES
1988
collectors/plugins.d/local_listeners.c
1987
- collectors/plugins.d/local-sockets.h
1989
+ src/libnetdata/maps/local-sockets.h
1990
)
1991
1992
add_executable(local-listeners ${LOCAL_LISTENERS_FILES})
@@ -2003,7 +2005,8 @@ endif()
2005
2006
if(ENABLE_PLUGIN_NETWORK_VIEWER)
2007
set(NETWORK_VIEWER_FILES
2006
- collectors/plugins.d/local-sockets.h
2008
+ src/libnetdata/maps/local-sockets.h
2009
+ src/libnetdata/maps/system-users.h
2010
collectors/network-viewer.plugin/network-viewer.c
2011
)
2012
collectors/network-viewer.plugin/network-viewer.c
+68
-8
@@ -3,17 +3,20 @@
3
#include "collectors/all.h"
4
#include "libnetdata/libnetdata.h"
5
#include "libnetdata/required_dummies.h"
6
-#include "collectors/plugins.d/local-sockets.h"
6
+#include "libnetdata/maps/local-sockets.h"
7
+#include "libnetdata/maps/system-users.h"
8
9
#define NETWORK_CONNECTIONS_VIEWER_FUNCTION "network-connections"
10
#define NETWORK_CONNECTIONS_VIEWER_HELP "Network connections explorer"
11
12
netdata_mutex_t stdout_mutex = NETDATA_MUTEX_INITIALIZER;
13
static bool plugin_should_exit = false;
14
+static USERNAMES_CACHE *uc;
15
16
ENUM_STR_MAP_DEFINE(SOCKET_DIRECTION) = {
17
{ .id = SOCKET_DIRECTION_LISTEN, .name = "listen" },
16
- { .id = SOCKET_DIRECTION_LOCAL, .name = "local" },
18
+ { .id = SOCKET_DIRECTION_LOCAL_INBOUND, .name = "local" },
19
+ { .id = SOCKET_DIRECTION_LOCAL_OUTBOUND, .name = "local" },
20
{ .id = SOCKET_DIRECTION_INBOUND, .name = "inbound" },
21
{ .id = SOCKET_DIRECTION_OUTBOUND, .name = "outbound" },
22
@@ -88,12 +91,43 @@ static void local_socket_to_array(struct local_socket_state *ls, struct local_so
91
buffer_json_add_array_item_string(wb, n->comm);
92
93
buffer_json_add_array_item_string(wb, n->cmdline);
94
+
95
+ if(n->uid == UID_UNSET) {
96
+ buffer_json_add_array_item_uint64(wb, n->uid);
97
+ buffer_json_add_array_item_string(wb, "[unknown]");
98
+ }
99
+ else {
100
+ buffer_json_add_array_item_uint64(wb, n->uid);
101
+ STRING *u = system_usernames_cache_lookup_uid(uc, n->uid);
102
+ buffer_json_add_array_item_string(wb, string2str(u));
103
+ string_freez(u);
104
+ }
105
+
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));
112
+
113
+ uint16_t server_port;
114
+ switch(n->direction) {
115
+ case SOCKET_DIRECTION_LISTEN:
116
+ case SOCKET_DIRECTION_INBOUND:
117
+ case SOCKET_DIRECTION_LOCAL_INBOUND:
118
+ server_port = n->local.port;
119
+ break;
120
+
121
+ case SOCKET_DIRECTION_OUTBOUND:
122
+ case SOCKET_DIRECTION_LOCAL_OUTBOUND:
123
+ server_port = n->remote.port;
124
+ break;
125
+
126
+ case SOCKET_DIRECTION_NONE:
127
+ break;
128
+ }
129
+ buffer_json_add_array_item_uint64(wb, server_port);
130
+
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
@@ -186,7 +220,7 @@ void network_viewer_function(const char *transaction, char *function __maybe_unu
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,
189
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
223
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
224
RRDF_FIELD_OPTS_VISIBLE,
225
NULL);
226
@@ -206,11 +240,27 @@ void network_viewer_function(const char *transaction, char *function __maybe_unu
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,
213
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
263
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
264
RRDF_FIELD_OPTS_VISIBLE|RRDF_FIELD_OPTS_FULL_WIDTH,
265
NULL);
266
@@ -218,7 +268,7 @@ void network_viewer_function(const char *transaction, char *function __maybe_unu
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,
221
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
271
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
272
RRDF_FIELD_OPTS_VISIBLE,
273
NULL);
274
@@ -234,7 +284,7 @@ void network_viewer_function(const char *transaction, char *function __maybe_unu
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,
237
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
287
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
288
RRDF_FIELD_OPTS_VISIBLE|RRDF_FIELD_OPTS_FULL_WIDTH,
289
NULL);
290
@@ -242,7 +292,7 @@ void network_viewer_function(const char *transaction, char *function __maybe_unu
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,
245
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
295
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
296
RRDF_FIELD_OPTS_VISIBLE,
297
NULL);
298
@@ -254,6 +304,14 @@ void network_viewer_function(const char *transaction, char *function __maybe_unu
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,
@@ -266,7 +324,7 @@ void network_viewer_function(const char *transaction, char *function __maybe_unu
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,
269
- RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT,
327
+ RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE,
328
RRDF_FIELD_OPTS_NONE,
329
NULL);
330
@@ -457,6 +515,8 @@ int main(int argc __maybe_unused, char **argv __maybe_unused) {
515
netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX");
516
if(verify_netdata_host_prefix(true) == -1) exit(1);
517
518
+ uc = system_usernames_cache_init();
519
+
520
// ----------------------------------------------------------------------------------------------------------------
521
522
fprintf(stdout, PLUGINSD_KEYWORD_FUNCTION " GLOBAL \"%s\" %d \"%s\" \"top\" "HTTP_ACCESS_FORMAT" %d\n",
collectors/plugins.d/local_listeners.c
+3
-2
@@ -1,6 +1,7 @@
1
// SPDX-License-Identifier: GPL-3.0-or-later
2
3
-#include "local-sockets.h"
3
+#include "libnetdata/libnetdata.h"
4
+#include "libnetdata/maps/local-sockets.h"
5
#include "libnetdata/required_dummies.h"
6
7
// --------------------------------------------------------------------------------------------------------------------
@@ -60,7 +61,7 @@ static void print_local_listeners_debug(LS_STATE *ls __maybe_unused, LOCAL_SOCKE
61
(n->direction & SOCKET_DIRECTION_LISTEN) ? "LISTEN," : "",
62
(n->direction & SOCKET_DIRECTION_INBOUND) ? "INBOUND," : "",
63
(n->direction & SOCKET_DIRECTION_OUTBOUND) ? "OUTBOUND," : "",
63
- (n->direction & SOCKET_DIRECTION_LOCAL) ? "LOCAL," : "",
64
+ (n->direction & (SOCKET_DIRECTION_LOCAL_INBOUND|SOCKET_DIRECTION_LOCAL_OUTBOUND)) ? "LOCAL," : "",
65
(n->direction == 0) ? "NONE," : "",
66
n->pid,
67
n->state,
collectors/systemd-journal.plugin/systemd-internals.h
+1
-1
@@ -122,7 +122,7 @@ void journal_init_files_and_directories(void);
122
void function_systemd_journal(const char *transaction, char *function, usec_t *stop_monotonic_ut, bool *cancelled, BUFFER *payload, HTTP_ACCESS access __maybe_unused, const char *source, void *data);
123
void journal_file_update_header(const char *filename, struct journal_file *jf);
124
125
-void netdata_systemd_journal_message_ids_init(void);
125
+void netdata_systemd_journal_annotations_init(void);
126
void netdata_systemd_journal_transform_message_id(FACETS *facets, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope, void *data);
127
128
void *journal_watcher_main(void *arg);
collectors/systemd-journal.plugin/systemd-journal-annotations.c
+29
-107
@@ -2,6 +2,20 @@
2
3
#include "systemd-internals.h"
4
5
+// ----------------------------------------------------------------------------
6
+#include "libnetdata/maps/system-users.h"
7
+#include "libnetdata/maps/system-groups.h"
8
+
9
+static struct {
10
+ USERNAMES_CACHE *uc;
11
+ GROUPNAMES_CACHE *gc;
12
+} systemd_annotations_globals = {
13
+ .uc = NULL,
14
+ .gc = NULL,
15
+};
16
+
17
+// ----------------------------------------------------------------------------
18
+
19
const char *errno_map[] = {
20
[1] = "1 (EPERM)", // "Operation not permitted",
21
[2] = "2 (ENOENT)", // "No such file or directory",
@@ -246,30 +260,6 @@ FACET_ROW_SEVERITY syslog_priority_to_facet_severity(FACETS *facets __maybe_unus
260
return FACET_ROW_SEVERITY_NORMAL;
261
}
262
249
-static char *uid_to_username(uid_t uid, char *buffer, size_t buffer_size) {
250
- static __thread char tmp[1024 + 1];
251
- struct passwd pw, *result = NULL;
252
-
253
- if (getpwuid_r(uid, &pw, tmp, sizeof(tmp), &result) != 0 || !result || !pw.pw_name || !(*pw.pw_name))
254
- snprintfz(buffer, buffer_size - 1, "%u", uid);
255
- else
256
- snprintfz(buffer, buffer_size - 1, "%u (%s)", uid, pw.pw_name);
257
-
258
- return buffer;
259
-}
260
-
261
-static char *gid_to_groupname(gid_t gid, char* buffer, size_t buffer_size) {
262
- static __thread char tmp[1024];
263
- struct group grp, *result = NULL;
264
-
265
- if (getgrgid_r(gid, &grp, tmp, sizeof(tmp), &result) != 0 || !result || !grp.gr_name || !(*grp.gr_name))
266
- snprintfz(buffer, buffer_size - 1, "%u", gid);
267
- else
268
- snprintfz(buffer, buffer_size - 1, "%u (%s)", gid, grp.gr_name);
269
-
270
- return buffer;
271
-}
272
-
263
void netdata_systemd_journal_transform_syslog_facility(FACETS *facets __maybe_unused, BUFFER *wb, FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, void *data __maybe_unused) {
264
const char *v = buffer_tostring(wb);
265
if(*v && isdigit(*v)) {
@@ -315,82 +305,6 @@ void netdata_systemd_journal_transform_errno(FACETS *facets __maybe_unused, BUFF
305
}
306
307
// ----------------------------------------------------------------------------
318
-// UID and GID transformation
319
-
320
-#define UID_GID_HASHTABLE_SIZE 10000
321
-
322
-struct word_t2str_hashtable_entry {
323
- struct word_t2str_hashtable_entry *next;
324
- Word_t hash;
325
- size_t len;
326
- char str[];
327
-};
328
-
329
-struct word_t2str_hashtable {
330
- SPINLOCK spinlock;
331
- size_t size;
332
- struct word_t2str_hashtable_entry *hashtable[UID_GID_HASHTABLE_SIZE];
333
-};
334
-
335
-struct word_t2str_hashtable uid_hashtable = {
336
- .size = UID_GID_HASHTABLE_SIZE,
337
-};
338
-
339
-struct word_t2str_hashtable gid_hashtable = {
340
- .size = UID_GID_HASHTABLE_SIZE,
341
-};
342
-
343
-struct word_t2str_hashtable_entry **word_t2str_hashtable_slot(struct word_t2str_hashtable *ht, Word_t hash) {
344
- size_t slot = hash % ht->size;
345
- struct word_t2str_hashtable_entry **e = &ht->hashtable[slot];
346
-
347
- while(*e && (*e)->hash != hash)
348
- e = &((*e)->next);
349
-
350
- return e;
351
-}
352
-
353
-const char *uid_to_username_cached(uid_t uid, size_t *length) {
354
- spinlock_lock(&uid_hashtable.spinlock);
355
-
356
- struct word_t2str_hashtable_entry **e = word_t2str_hashtable_slot(&uid_hashtable, uid);
357
- if(!(*e)) {
358
- static __thread char buf[1024];
359
- const char *name = uid_to_username(uid, buf, sizeof(buf));
360
- size_t size = strlen(name) + 1;
361
-
362
- *e = callocz(1, sizeof(struct word_t2str_hashtable_entry) + size);
363
- (*e)->len = size - 1;
364
- (*e)->hash = uid;
365
- memcpy((*e)->str, name, size);
366
- }
367
-
368
- spinlock_unlock(&uid_hashtable.spinlock);
369
-
370
- *length = (*e)->len;
371
- return (*e)->str;
372
-}
373
-
374
-const char *gid_to_groupname_cached(gid_t gid, size_t *length) {
375
- spinlock_lock(&gid_hashtable.spinlock);
376
-
377
- struct word_t2str_hashtable_entry **e = word_t2str_hashtable_slot(&gid_hashtable, gid);
378
- if(!(*e)) {
379
- static __thread char buf[1024];
380
- const char *name = gid_to_groupname(gid, buf, sizeof(buf));
381
- size_t size = strlen(name) + 1;
382
-
383
- *e = callocz(1, sizeof(struct word_t2str_hashtable_entry) + size);
384
- (*e)->len = size - 1;
385
- (*e)->hash = gid;
386
- memcpy((*e)->str, name, size);
387
- }
388
-
389
- spinlock_unlock(&gid_hashtable.spinlock);
390
-
391
- *length = (*e)->len;
392
- return (*e)->str;
393
-}
308
309
DICTIONARY *boot_ids_to_first_ut = NULL;
310
@@ -455,9 +369,9 @@ void netdata_systemd_journal_transform_uid(FACETS *facets __maybe_unused, BUFFER
369
const char *v = buffer_tostring(wb);
370
if(*v && isdigit(*v)) {
371
uid_t uid = str2i(buffer_tostring(wb));
458
- size_t len;
459
- const char *name = uid_to_username_cached(uid, &len);
460
- buffer_contents_replace(wb, name, len);
372
+ STRING *u = system_usernames_cache_lookup_uid(systemd_annotations_globals.uc, uid);
373
+ buffer_contents_replace(wb, string2str(u), string_strlen(u));
374
+ string_freez(u);
375
}
376
}
377
@@ -468,9 +382,9 @@ void netdata_systemd_journal_transform_gid(FACETS *facets __maybe_unused, BUFFER
382
const char *v = buffer_tostring(wb);
383
if(*v && isdigit(*v)) {
384
gid_t gid = str2i(buffer_tostring(wb));
471
- size_t len;
472
- const char *name = gid_to_groupname_cached(gid, &len);
473
- buffer_contents_replace(wb, name, len);
385
+ STRING *g = system_groupnames_cache_lookup_gid(systemd_annotations_globals.gc, gid);
386
+ buffer_contents_replace(wb, string2str(g), string_strlen(g));
387
+ string_freez(g);
388
}
389
}
390
@@ -557,7 +471,7 @@ struct message_id_info {
471
472
static DICTIONARY *known_journal_messages_ids = NULL;
473
560
-void netdata_systemd_journal_message_ids_init(void) {
474
+static void netdata_systemd_journal_message_ids_init(void) {
475
known_journal_messages_ids = dictionary_create(DICT_OPTION_DONT_OVERWRITE_VALUE);
476
477
struct message_id_info i = { 0 };
@@ -712,6 +626,14 @@ void netdata_systemd_journal_transform_message_id(FACETS *facets __maybe_unused,
626
627
// ----------------------------------------------------------------------------
628
629
+void netdata_systemd_journal_annotations_init(void) {
630
+ systemd_annotations_globals.uc = system_usernames_cache_init();
631
+ systemd_annotations_globals.gc = system_groupnames_cache_init();
632
+ netdata_systemd_journal_message_ids_init();
633
+}
634
+
635
+// ----------------------------------------------------------------------------
636
+
637
//static void netdata_systemd_journal_rich_message(FACETS *facets __maybe_unused, BUFFER *json_array, FACET_ROW_KEY_VALUE *rkv, FACET_ROW *row __maybe_unused, void *data __maybe_unused) {
638
// buffer_json_add_array_item_object(json_array);
639
// buffer_json_member_add_string(json_array, "value", buffer_tostring(rkv->wb));
collectors/systemd-journal.plugin/systemd-main.c
+3
-3
@@ -8,7 +8,7 @@
8
netdata_mutex_t stdout_mutex = NETDATA_MUTEX_INITIALIZER;
9
static bool plugin_should_exit = false;
10
11
-static bool journal_data_direcories_exist() {
11
+static bool journal_data_directories_exist() {
12
struct stat st;
13
for (unsigned i = 0; i < MAX_JOURNAL_DIRECTORIES && journal_directories[i].path; i++) {
14
if ((stat(string2str(journal_directories[i].path), &st) == 0) && S_ISDIR(st.st_mode))
@@ -28,10 +28,10 @@ int main(int argc __maybe_unused, char **argv __maybe_unused) {
28
// ------------------------------------------------------------------------
29
// initialization
30
31
- netdata_systemd_journal_message_ids_init();
31
+ netdata_systemd_journal_annotations_init();
32
journal_init_files_and_directories();
33
34
- if (!journal_data_direcories_exist()) {
34
+ if (!journal_data_directories_exist()) {
35
nd_log_collector(NDLP_INFO, "unable to locate journal data directories. Exiting...");
36
fprintf(stdout, "DISABLE\n");
37
fflush(stdout);
src/libnetdata/maps/local-sockets.h
renamed
+38
-24
@@ -117,10 +117,11 @@ typedef struct local_socket_state {
117
118
typedef enum __attribute__((packed)) {
119
SOCKET_DIRECTION_NONE = 0,
120
- SOCKET_DIRECTION_LISTEN = (1 << 0), // a listening socket
121
- SOCKET_DIRECTION_INBOUND = (1 << 1), // an inbound socket connecting a remote system to a local listening socket
122
- SOCKET_DIRECTION_OUTBOUND = (1 << 2), // a socket initiated by this system, connecting to another system
123
- SOCKET_DIRECTION_LOCAL = (1 << 3), // the socket connecting 2 localhost applications
120
+ SOCKET_DIRECTION_LISTEN = (1 << 0), // a listening socket
121
+ SOCKET_DIRECTION_INBOUND = (1 << 1), // an inbound socket connecting a remote system to a local listening socket
122
+ SOCKET_DIRECTION_OUTBOUND = (1 << 2), // a socket initiated by this system, connecting to another system
123
+ SOCKET_DIRECTION_LOCAL_INBOUND = (1 << 3), // the socket connecting 2 localhost applications
124
+ SOCKET_DIRECTION_LOCAL_OUTBOUND = (1 << 4), // the socket connecting 2 localhost applications
125
} SOCKET_DIRECTION;
126
127
#ifndef TASK_COMM_LEN
@@ -224,7 +225,7 @@ static void local_sockets_foreach_local_socket_call_cb(LS_STATE *ls) {
225
if(!n) continue;
226
227
if((ls->config.listening && n->direction & SOCKET_DIRECTION_LISTEN) ||
227
- (ls->config.local && n->direction & SOCKET_DIRECTION_LOCAL) ||
228
+ (ls->config.local && n->direction & (SOCKET_DIRECTION_LOCAL_INBOUND|SOCKET_DIRECTION_LOCAL_OUTBOUND)) ||
229
(ls->config.inbound && n->direction & SOCKET_DIRECTION_INBOUND) ||
230
(ls->config.outbound && n->direction & SOCKET_DIRECTION_OUTBOUND)
231
) {
@@ -612,12 +613,6 @@ static inline bool local_sockets_add_socket(LS_STATE *ls, LOCAL_SOCKET *tmp) {
613
// the remote address is zero
614
n->direction |= SOCKET_DIRECTION_LISTEN;
615
}
615
- else if(
616
- local_sockets_is_loopback_address(&n->local) ||
617
- local_sockets_is_loopback_address(&n->remote)) {
618
- // the local IP address is loopback
619
- n->direction |= SOCKET_DIRECTION_LOCAL;
620
- }
616
else {
617
// we can't say yet if it is inbound or outboud
618
// so, mark it as both inbound and outbound
@@ -826,9 +821,23 @@ static inline void local_sockets_detect_directions(LS_STATE *ls) {
821
if (!n) continue;
822
823
if ((n->direction & (SOCKET_DIRECTION_INBOUND|SOCKET_DIRECTION_OUTBOUND)) !=
829
- (SOCKET_DIRECTION_INBOUND|SOCKET_DIRECTION_OUTBOUND))
824
+ (SOCKET_DIRECTION_INBOUND|SOCKET_DIRECTION_OUTBOUND))
825
continue;
826
827
+ // check if the local port is one of our listening ports
828
+ {
829
+ SIMPLE_HASHTABLE_SLOT_LISTENING_PORT *sl_port =
830
+ simple_hashtable_get_slot_LISTENING_PORT(&ls->listening_ports_hashtable, n->local_port_hash, &n->local_port_key, false);
831
+
832
+ struct local_port *port = SIMPLE_HASHTABLE_SLOT_DATA(sl_port); // do not reference this pointer - is invalid
833
+ if(port) {
834
+ // the local port of this socket is a port we listen to
835
+ n->direction &= ~SOCKET_DIRECTION_OUTBOUND;
836
+ }
837
+ else
838
+ n->direction &= ~SOCKET_DIRECTION_INBOUND;
839
+ }
840
+
841
// check if the remote IP is one of our local IPs
842
{
843
SIMPLE_HASHTABLE_SLOT_LOCAL_IP *sl_ip =
@@ -837,24 +846,29 @@ static inline void local_sockets_detect_directions(LS_STATE *ls) {
846
union ipv46 *d = SIMPLE_HASHTABLE_SLOT_DATA(sl_ip);
847
if (d) {
848
// the remote IP of this socket is one of our local IPs
840
- n->direction &= ~(SOCKET_DIRECTION_INBOUND|SOCKET_DIRECTION_OUTBOUND);
841
- n->direction |= SOCKET_DIRECTION_LOCAL;
849
+ if(n->direction & SOCKET_DIRECTION_INBOUND) {
850
+ n->direction &= ~SOCKET_DIRECTION_INBOUND;
851
+ n->direction |= SOCKET_DIRECTION_LOCAL_INBOUND;
852
+ }
853
+ else if(n->direction & SOCKET_DIRECTION_OUTBOUND) {
854
+ n->direction &= ~SOCKET_DIRECTION_OUTBOUND;
855
+ n->direction |= SOCKET_DIRECTION_LOCAL_OUTBOUND;
856
+ }
857
continue;
858
}
859
}
860
846
- // check if the local port is one of our listening ports
847
- {
848
- SIMPLE_HASHTABLE_SLOT_LISTENING_PORT *sl_port =
849
- simple_hashtable_get_slot_LISTENING_PORT(&ls->listening_ports_hashtable, n->local_port_hash, &n->local_port_key, false);
850
-
851
- struct local_port *port = SIMPLE_HASHTABLE_SLOT_DATA(sl_port); // do not reference this pointer - is invalid
852
- if(port) {
853
- // the local port of this socket is a port we listen to
861
+ if (local_sockets_is_loopback_address(&n->local) ||
862
+ local_sockets_is_loopback_address(&n->remote)) {
863
+ // both IP addresses are loopback
864
+ if(n->direction & SOCKET_DIRECTION_INBOUND) {
865
+ n->direction &= ~SOCKET_DIRECTION_INBOUND;
866
+ n->direction |= SOCKET_DIRECTION_LOCAL_INBOUND;
867
+ }
868
+ else if(n->direction & SOCKET_DIRECTION_OUTBOUND) {
869
n->direction &= ~SOCKET_DIRECTION_OUTBOUND;
870
+ n->direction |= SOCKET_DIRECTION_LOCAL_OUTBOUND;
871
}
856
- else
857
- n->direction &= ~SOCKET_DIRECTION_INBOUND;
872
}
873
}
874
}
src/libnetdata/maps/system-groups.h
new
+67
@@ -0,0 +1,67 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#ifndef NETDATA_SYSTEM_GROUPS_H
4
+#define NETDATA_SYSTEM_GROUPS_H
5
+
6
+#include "libnetdata/libnetdata.h"
7
+
8
+// --------------------------------------------------------------------------------------------------------------------
9
+// hashtable for caching uid to username mappings
10
+// key is the uid, value is username (STRING)
11
+
12
+#define SIMPLE_HASHTABLE_VALUE_TYPE STRING
13
+#define SIMPLE_HASHTABLE_NAME _GROUPNAMES_CACHE
14
+#include "libnetdata/simple_hashtable.h"
15
+
16
+typedef struct groupnames_cache {
17
+ SPINLOCK spinlock;
18
+ SIMPLE_HASHTABLE_GROUPNAMES_CACHE ht;
19
+} GROUPNAMES_CACHE;
20
+
21
+static inline STRING *system_groupnames_cache_lookup_gid(GROUPNAMES_CACHE *gc, gid_t gid) {
22
+ spinlock_lock(&gc->spinlock);
23
+
24
+ SIMPLE_HASHTABLE_SLOT_GROUPNAMES_CACHE *sl = simple_hashtable_get_slot_GROUPNAMES_CACHE(&gc->ht, gid, &gid, true);
25
+ STRING *g = SIMPLE_HASHTABLE_SLOT_DATA(sl);
26
+ if(!g) {
27
+ char tmp[1024 + 1];
28
+ struct group grp, *result = NULL;
29
+
30
+ if (getgrgid_r(gid, &grp, tmp, sizeof(tmp), &result) != 0 || !result || !grp.gr_name || !(*grp.gr_name)) {
31
+ char name[50];
32
+ snprintfz(name, sizeof(name), "%u", gid);
33
+ g = string_strdupz(name);
34
+ }
35
+ else
36
+ g = string_strdupz(grp.gr_name);
37
+
38
+ simple_hashtable_set_slot_GROUPNAMES_CACHE(&gc->ht, sl, gid, g);
39
+ }
40
+
41
+ g = string_dup(g);
42
+ spinlock_unlock(&gc->spinlock);
43
+ return g;
44
+}
45
+
46
+static inline GROUPNAMES_CACHE *system_groupnames_cache_init(void) {
47
+ GROUPNAMES_CACHE *gc = callocz(1, sizeof(*gc));
48
+ spinlock_init(&gc->spinlock);
49
+ simple_hashtable_init_GROUPNAMES_CACHE(&gc->ht, 100);
50
+ return gc;
51
+}
52
+
53
+static inline void system_groupnames_cache_destroy(GROUPNAMES_CACHE *gc) {
54
+ spinlock_lock(&gc->spinlock);
55
+
56
+ for(SIMPLE_HASHTABLE_SLOT_GROUPNAMES_CACHE *sl = simple_hashtable_first_read_only_GROUPNAMES_CACHE(&gc->ht);
57
+ sl;
58
+ sl = simple_hashtable_next_read_only_GROUPNAMES_CACHE(&gc->ht, sl)) {
59
+ STRING *u = SIMPLE_HASHTABLE_SLOT_DATA(sl);
60
+ string_freez(u);
61
+ }
62
+
63
+ simple_hashtable_destroy_GROUPNAMES_CACHE(&gc->ht);
64
+ freez(gc);
65
+}
66
+
67
+#endif //NETDATA_SYSTEM_GROUPS_H
src/libnetdata/maps/system-users.h
new
+67
@@ -0,0 +1,67 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#ifndef NETDATA_SYSTEM_USERS_H
4
+#define NETDATA_SYSTEM_USERS_H
5
+
6
+#include "libnetdata/libnetdata.h"
7
+
8
+// --------------------------------------------------------------------------------------------------------------------
9
+// hashtable for caching uid to username mappings
10
+// key is the uid, value is username (STRING)
11
+
12
+#define SIMPLE_HASHTABLE_VALUE_TYPE STRING
13
+#define SIMPLE_HASHTABLE_NAME _USERNAMES_CACHE
14
+#include "libnetdata/simple_hashtable.h"
15
+
16
+typedef struct usernames_cache {
17
+ SPINLOCK spinlock;
18
+ SIMPLE_HASHTABLE_USERNAMES_CACHE ht;
19
+} USERNAMES_CACHE;
20
+
21
+static inline STRING *system_usernames_cache_lookup_uid(USERNAMES_CACHE *uc, uid_t uid) {
22
+ spinlock_lock(&uc->spinlock);
23
+
24
+ SIMPLE_HASHTABLE_SLOT_USERNAMES_CACHE *sl = simple_hashtable_get_slot_USERNAMES_CACHE(&uc->ht, uid, &uid, true);
25
+ STRING *u = SIMPLE_HASHTABLE_SLOT_DATA(sl);
26
+ if(!u) {
27
+ char tmp[1024 + 1];
28
+ struct passwd pw, *result = NULL;
29
+
30
+ if (getpwuid_r(uid, &pw, tmp, sizeof(tmp), &result) != 0 || !result || !pw.pw_name || !(*pw.pw_name)) {
31
+ char name[50];
32
+ snprintfz(name, sizeof(name), "%u", uid);
33
+ u = string_strdupz(name);
34
+ }
35
+ else
36
+ u = string_strdupz(pw.pw_name);
37
+
38
+ simple_hashtable_set_slot_USERNAMES_CACHE(&uc->ht, sl, uid, u);
39
+ }
40
+
41
+ u = string_dup(u);
42
+ spinlock_unlock(&uc->spinlock);
43
+ return u;
44
+}
45
+
46
+static inline USERNAMES_CACHE *system_usernames_cache_init(void) {
47
+ USERNAMES_CACHE *uc = callocz(1, sizeof(*uc));
48
+ spinlock_init(&uc->spinlock);
49
+ simple_hashtable_init_USERNAMES_CACHE(&uc->ht, 100);
50
+ return uc;
51
+}
52
+
53
+static inline void system_usernames_cache_destroy(USERNAMES_CACHE *uc) {
54
+ spinlock_lock(&uc->spinlock);
55
+
56
+ for(SIMPLE_HASHTABLE_SLOT_USERNAMES_CACHE *sl = simple_hashtable_first_read_only_USERNAMES_CACHE(&uc->ht);
57
+ sl;
58
+ sl = simple_hashtable_next_read_only_USERNAMES_CACHE(&uc->ht, sl)) {
59
+ STRING *u = SIMPLE_HASHTABLE_SLOT_DATA(sl);
60
+ string_freez(u);
61
+ }
62
+
63
+ simple_hashtable_destroy_USERNAMES_CACHE(&uc->ht);
64
+ freez(uc);
65
+}
66
+
67
+#endif //NETDATA_SYSTEM_USERS_H