@cryptotaxi247 / netdata-1 / commits / eeb5551bb

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