allow local-listeners to associate container sockets with pids (#18807)
Costa Tsaousis committed
Oct 17, 2024 at 18:36 UTC
eeb5551bb9438bdf7949f2d25f2d1980c5094b5f
2 files changed
+97
-103
src/collectors/utils/local_listeners.c
+2
-62
@@ -6,35 +6,6 @@
6
7
// --------------------------------------------------------------------------------------------------------------------
8
9
-static const char *protocol_name(LOCAL_SOCKET *n) {
10
- if(n->local.family == AF_INET) {
11
- if(n->local.protocol == IPPROTO_TCP)
12
- return "TCP";
13
- else if(n->local.protocol == IPPROTO_UDP)
14
- return "UDP";
15
- else
16
- return "UNKNOWN_IPV4";
17
- }
18
- else if(is_local_socket_ipv46(n)) {
19
- if (n->local.protocol == IPPROTO_TCP)
20
- return "TCP46";
21
- else if(n->local.protocol == IPPROTO_UDP)
22
- return "UDP46";
23
- else
24
- return "UNKNOWN_IPV46";
25
- }
26
- else if(n->local.family == AF_INET6) {
27
- if (n->local.protocol == IPPROTO_TCP)
28
- return "TCP6";
29
- else if(n->local.protocol == IPPROTO_UDP)
30
- return "UDP6";
31
- else
32
- return "UNKNOWN_IPV6";
33
- }
34
- else
35
- return "UNKNOWN";
36
-}
37
-
9
static void print_local_listeners(LS_STATE *ls __maybe_unused, const LOCAL_SOCKET *nn, void *data __maybe_unused) {
10
LOCAL_SOCKET *n = (LOCAL_SOCKET *)nn;
11
@@ -54,38 +25,7 @@ static void print_local_listeners(LS_STATE *ls __maybe_unused, const LOCAL_SOCKE
25
ipv6_address_to_txt(&n->remote.ip.ipv6, remote_address);
26
}
27
57
- printf("%s|%s|%u|%s\n", protocol_name(n), local_address, n->local.port, string2str(n->cmdline));
58
-}
59
-
60
-static void print_local_listeners_debug(LS_STATE *ls __maybe_unused, const LOCAL_SOCKET *nn, void *data __maybe_unused) {
61
- LOCAL_SOCKET *n = (LOCAL_SOCKET *)nn;
62
-
63
- char local_address[INET6_ADDRSTRLEN];
64
- char remote_address[INET6_ADDRSTRLEN];
65
-
66
- if(n->local.family == AF_INET) {
67
- ipv4_address_to_txt(n->local.ip.ipv4, local_address);
68
- ipv4_address_to_txt(n->remote.ip.ipv4, remote_address);
69
- }
70
- else if(n->local.family == AF_INET6) {
71
- ipv6_address_to_txt(&n->local.ip.ipv6, local_address);
72
- ipv6_address_to_txt(&n->remote.ip.ipv6, remote_address);
73
- }
74
-
75
- printf("%s, direction=%s%s%s%s%s pid=%d, state=0x%0x, ns=%"PRIu64", local=%s[:%u], remote=%s[:%u], uid=%u, comm=%s\n",
76
- protocol_name(n),
77
- (n->direction & SOCKET_DIRECTION_LISTEN) ? "LISTEN," : "",
78
- (n->direction & SOCKET_DIRECTION_INBOUND) ? "INBOUND," : "",
79
- (n->direction & SOCKET_DIRECTION_OUTBOUND) ? "OUTBOUND," : "",
80
- (n->direction & (SOCKET_DIRECTION_LOCAL_INBOUND|SOCKET_DIRECTION_LOCAL_OUTBOUND)) ? "LOCAL," : "",
81
- (n->direction == 0) ? "NONE," : "",
82
- n->pid,
83
- (unsigned int)n->state,
84
- n->net_ns_inode,
85
- local_address, n->local.port,
86
- remote_address, n->remote.port,
87
- n->uid,
88
- n->comm);
28
+ printf("%s|%s|%u|%s\n", local_sockets_protocol_name(n), local_address, n->local.port, string2str(n->cmdline));
29
}
30
31
// --------------------------------------------------------------------------------------------------------------------
@@ -244,7 +184,7 @@ int main(int argc, char **argv) {
184
ls.config.uid = true;
185
ls.config.procfile = false;
186
ls.config.max_errors = SIZE_MAX;
247
- ls.config.cb = print_local_listeners_debug;
187
+ ls.config.cb = local_listeners_print_socket;
188
189
debug = true;
190
}
src/libnetdata/maps/local-sockets.h
+95
-41
@@ -409,14 +409,94 @@ static inline const char *local_sockets_address_space(const struct socket_endpoi
409
return "public";
410
}
411
412
-// --------------------------------------------------------------------------------------------------------------------
412
+static inline void ipv6_address_to_txt(const struct in6_addr *in6_addr, char *dst) {
413
+ struct sockaddr_in6 sa = { 0 };
414
+
415
+ sa.sin6_family = AF_INET6;
416
+ sa.sin6_port = htons(0);
417
+ sa.sin6_addr = *in6_addr;
418
+
419
+ // Convert to human-readable format
420
+ if (inet_ntop(AF_INET6, &(sa.sin6_addr), dst, INET6_ADDRSTRLEN) == NULL)
421
+ *dst = '\0';
422
+}
423
+
424
+static inline void ipv4_address_to_txt(uint32_t ip, char *dst) {
425
+ uint8_t octets[4];
426
+ octets[0] = ip & 0xFF;
427
+ octets[1] = (ip >> 8) & 0xFF;
428
+ octets[2] = (ip >> 16) & 0xFF;
429
+ octets[3] = (ip >> 24) & 0xFF;
430
+ sprintf(dst, "%u.%u.%u.%u", octets[0], octets[1], octets[2], octets[3]);
431
+}
432
433
static inline bool is_local_socket_ipv46(const LOCAL_SOCKET *n) {
434
return n->local.family == AF_INET6 &&
416
- n->direction == SOCKET_DIRECTION_LISTEN &&
417
- local_sockets_is_zero_address(&n->local) &&
418
- n->ipv6ony.checked &&
419
- n->ipv6ony.ipv46;
435
+ n->direction == SOCKET_DIRECTION_LISTEN &&
436
+ local_sockets_is_zero_address(&n->local) &&
437
+ n->ipv6ony.checked &&
438
+ n->ipv6ony.ipv46;
439
+}
440
+
441
+static inline const char *local_sockets_protocol_name(LOCAL_SOCKET *n) {
442
+ if(n->local.family == AF_INET) {
443
+ if(n->local.protocol == IPPROTO_TCP)
444
+ return "TCP";
445
+ else if(n->local.protocol == IPPROTO_UDP)
446
+ return "UDP";
447
+ else
448
+ return "UNKNOWN_IPV4";
449
+ }
450
+ else if(is_local_socket_ipv46(n)) {
451
+ if (n->local.protocol == IPPROTO_TCP)
452
+ return "TCP46";
453
+ else if(n->local.protocol == IPPROTO_UDP)
454
+ return "UDP46";
455
+ else
456
+ return "UNKNOWN_IPV46";
457
+ }
458
+ else if(n->local.family == AF_INET6) {
459
+ if (n->local.protocol == IPPROTO_TCP)
460
+ return "TCP6";
461
+ else if(n->local.protocol == IPPROTO_UDP)
462
+ return "UDP6";
463
+ else
464
+ return "UNKNOWN_IPV6";
465
+ }
466
+ else
467
+ return "UNKNOWN";
468
+}
469
+
470
+static inline void local_listeners_print_socket(LS_STATE *ls __maybe_unused, const LOCAL_SOCKET *nn, void *data __maybe_unused) {
471
+ LOCAL_SOCKET *n = (LOCAL_SOCKET *)nn;
472
+
473
+ char local_address[INET6_ADDRSTRLEN];
474
+ char remote_address[INET6_ADDRSTRLEN];
475
+
476
+ if(n->local.family == AF_INET) {
477
+ ipv4_address_to_txt(n->local.ip.ipv4, local_address);
478
+ ipv4_address_to_txt(n->remote.ip.ipv4, remote_address);
479
+ }
480
+ else if(n->local.family == AF_INET6) {
481
+ ipv6_address_to_txt(&n->local.ip.ipv6, local_address);
482
+ ipv6_address_to_txt(&n->remote.ip.ipv6, remote_address);
483
+ }
484
+
485
+ printf("%s, direction=%s%s%s%s%s pid=%d, state=0x%0x, ns=%"PRIu64", local=%s[:%u], remote=%s[:%u], uid=%u, inode=%"PRIu64", comm=%s\n",
486
+ local_sockets_protocol_name(n),
487
+ (n->direction & SOCKET_DIRECTION_LISTEN) ? "LISTEN," : "",
488
+ (n->direction & SOCKET_DIRECTION_INBOUND) ? "INBOUND," : "",
489
+ (n->direction & SOCKET_DIRECTION_OUTBOUND) ? "OUTBOUND," : "",
490
+ (n->direction & (SOCKET_DIRECTION_LOCAL_INBOUND|SOCKET_DIRECTION_LOCAL_OUTBOUND)) ? "LOCAL," : "",
491
+ (n->direction == 0) ? "NONE," : "",
492
+ n->pid,
493
+ (unsigned int)n->state,
494
+ n->net_ns_inode,
495
+ local_address, n->local.port,
496
+ remote_address, n->remote.port,
497
+ n->uid,
498
+ n->inode,
499
+ n->comm);
500
}
501
502
// --------------------------------------------------------------------------------------------------------------------
@@ -550,6 +630,7 @@ static inline bool local_sockets_find_all_sockets_in_proc(LS_STATE *ls, const ch
630
if(!local_sockets_read_proc_inode_link(ls, filename, &inode, "socket"))
631
continue;
632
633
+ // fprintf(stderr, "%d: PID %d is using socket inode %"PRIu64"\n", gettid_uncached(), pid, inode);
634
SIMPLE_HASHTABLE_SLOT_PID_SOCKET *sl = simple_hashtable_get_slot_PID_SOCKET(&ls->pid_sockets_hashtable, inode, &inode, true);
635
struct pid_socket *ps = SIMPLE_HASHTABLE_SLOT_DATA(sl);
636
if(!ps || (ps->pid == 1 && pid != 1)) {
@@ -610,6 +691,7 @@ static inline bool local_sockets_find_all_sockets_in_proc(LS_STATE *ls, const ch
691
692
ps->cmdline = cmdline_trimmed ? strdupz(cmdline_trimmed) : NULL;
693
simple_hashtable_set_slot_PID_SOCKET(&ls->pid_sockets_hashtable, sl, inode, ps);
694
+ // fprintf(stderr, "%d: PID %d indexed for using socket inode %"PRIu64"\n", gettid_uncached(), pid, inode);
695
}
696
}
697
@@ -672,11 +754,15 @@ static inline bool local_sockets_add_socket(LS_STATE *ls, LOCAL_SOCKET *tmp) {
754
if(ps->uid != UID_UNSET && n->uid == UID_UNSET)
755
n->uid = ps->uid;
756
675
- if(ps->cmdline)
757
+ if(ps->cmdline) {
758
+ if(n->cmdline) string_freez(n->cmdline);
759
n->cmdline = string_strdupz(ps->cmdline);
760
+ }
761
762
strncpyz(n->comm, ps->comm, sizeof(n->comm) - 1);
763
}
764
+// else
765
+// fprintf(stderr, "%d: No PID found for inode %"PRIu64"\n", gettid_uncached(), n->inode);
766
767
// --- index it -----------------------------------------------------------------------------------------------
768
@@ -1483,25 +1569,14 @@ static inline bool local_sockets_get_namespace_sockets_with_pid(LS_STATE *ls, st
1569
1570
spinlock_lock(&ls->spinlock);
1571
1486
- SIMPLE_HASHTABLE_SLOT_LOCAL_SOCKET *sl = simple_hashtable_get_slot_LOCAL_SOCKET(&ls->sockets_hashtable, buf.inode, &buf, true);
1487
- LOCAL_SOCKET *n = SIMPLE_HASHTABLE_SLOT_DATA(sl);
1488
- if(n) {
1572
+ if(!local_sockets_add_socket(ls, &buf)) {
1573
+ // fprintf(stderr, "Failed to add duplicate namespace socket inode %"PRIu64"\n", buf.inode);
1574
string_freez(buf.cmdline);
1490
-
1491
-// local_sockets_log(ls,
1492
-// "ns inode %" PRIu64" (comm: '%s', pid: %u, ns: %"PRIu64") already exists in hashtable (comm: '%s', pid: %u, ns: %"PRIu64") - ignoring duplicate",
1493
-// buf.inode, buf.comm, buf.pid, buf.net_ns_inode, n->comm, n->pid, n->net_ns_inode);
1494
-
1575
if(ls->config.report)
1576
__atomic_add_fetch(&ls->stats.namespaces_sockets_existing, 1, __ATOMIC_RELAXED);
1577
}
1578
else {
1499
- n = aral_mallocz(ls->local_socket_aral);
1500
- memcpy(n, &buf, sizeof(*n));
1501
- simple_hashtable_set_slot_LOCAL_SOCKET(&ls->sockets_hashtable, sl, n->inode, n);
1502
-
1503
- local_sockets_index_listening_port(ls, n);
1504
-
1579
+ // fprintf(stderr, "Added namespace socket inode %"PRIu64"\n", buf.inode);
1580
if(ls->config.report)
1581
__atomic_add_fetch(&ls->stats.namespaces_sockets_new, 1, __ATOMIC_RELAXED);
1582
}
@@ -1740,25 +1815,4 @@ static inline void local_sockets_process(LS_STATE *ls) {
1815
local_sockets_cleanup(ls);
1816
}
1817
1743
-static inline void ipv6_address_to_txt(const struct in6_addr *in6_addr, char *dst) {
1744
- struct sockaddr_in6 sa = { 0 };
1745
-
1746
- sa.sin6_family = AF_INET6;
1747
- sa.sin6_port = htons(0);
1748
- sa.sin6_addr = *in6_addr;
1749
-
1750
- // Convert to human-readable format
1751
- if (inet_ntop(AF_INET6, &(sa.sin6_addr), dst, INET6_ADDRSTRLEN) == NULL)
1752
- *dst = '\0';
1753
-}
1754
-
1755
-static inline void ipv4_address_to_txt(uint32_t ip, char *dst) {
1756
- uint8_t octets[4];
1757
- octets[0] = ip & 0xFF;
1758
- octets[1] = (ip >> 8) & 0xFF;
1759
- octets[2] = (ip >> 16) & 0xFF;
1760
- octets[3] = (ip >> 24) & 0xFF;
1761
- sprintf(dst, "%u.%u.%u.%u", octets[0], octets[1], octets[2], octets[3]);
1762
-}
1763
-
1818
#endif //NETDATA_LOCAL_SOCKETS_H