local-sockets.h 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #ifndef NETDATA_LOCAL_SOCKETS_H
  3. #define NETDATA_LOCAL_SOCKETS_H
  4. #include "libnetdata/libnetdata.h"
  5. // disable libmnl for the moment
  6. #undef HAVE_LIBMNL
  7. #ifdef HAVE_LIBMNL
  8. #include <linux/inet_diag.h>
  9. #include <linux/sock_diag.h>
  10. #include <linux/unix_diag.h>
  11. #include <linux/netlink.h>
  12. #include <libmnl/libmnl.h>
  13. #endif
  14. #define UID_UNSET (uid_t)(UINT32_MAX)
  15. // --------------------------------------------------------------------------------------------------------------------
  16. // hashtable for keeping the namespaces
  17. // key and value is the namespace inode
  18. #define SIMPLE_HASHTABLE_VALUE_TYPE uint64_t
  19. #define SIMPLE_HASHTABLE_NAME _NET_NS
  20. #include "libnetdata/simple_hashtable.h"
  21. // --------------------------------------------------------------------------------------------------------------------
  22. // hashtable for keeping the sockets of PIDs
  23. // key is the inode
  24. struct pid_socket;
  25. #define SIMPLE_HASHTABLE_VALUE_TYPE struct pid_socket
  26. #define SIMPLE_HASHTABLE_NAME _PID_SOCKET
  27. #include "libnetdata/simple_hashtable.h"
  28. // --------------------------------------------------------------------------------------------------------------------
  29. // hashtable for keeping all the sockets
  30. // key is the inode
  31. struct local_socket;
  32. #define SIMPLE_HASHTABLE_VALUE_TYPE struct local_socket
  33. #define SIMPLE_HASHTABLE_NAME _LOCAL_SOCKET
  34. #include "libnetdata/simple_hashtable.h"
  35. // --------------------------------------------------------------------------------------------------------------------
  36. // hashtable for keeping all local IPs
  37. // key is XXH3_64bits hash of the IP
  38. union ipv46;
  39. #define SIMPLE_HASHTABLE_VALUE_TYPE union ipv46
  40. #define SIMPLE_HASHTABLE_NAME _LOCAL_IP
  41. #include "libnetdata/simple_hashtable.h"
  42. // --------------------------------------------------------------------------------------------------------------------
  43. // hashtable for keeping all listening ports
  44. // key is XXH3_64bits hash of the family, protocol, port number, namespace
  45. struct local_port;
  46. #define SIMPLE_HASHTABLE_VALUE_TYPE struct local_port
  47. #define SIMPLE_HASHTABLE_NAME _LISTENING_PORT
  48. #include "libnetdata/simple_hashtable.h"
  49. // --------------------------------------------------------------------------------------------------------------------
  50. struct local_socket_state;
  51. typedef void (*local_sockets_cb_t)(struct local_socket_state *state, struct local_socket *n, void *data);
  52. typedef struct local_socket_state {
  53. struct {
  54. bool listening;
  55. bool inbound;
  56. bool outbound;
  57. bool local;
  58. bool tcp4;
  59. bool tcp6;
  60. bool udp4;
  61. bool udp6;
  62. bool pid;
  63. bool cmdline;
  64. bool comm;
  65. bool uid;
  66. bool namespaces;
  67. size_t max_errors;
  68. local_sockets_cb_t cb;
  69. void *data;
  70. const char *host_prefix;
  71. } config;
  72. struct {
  73. size_t pid_fds_processed;
  74. size_t pid_fds_opendir_failed;
  75. size_t pid_fds_readlink_failed;
  76. size_t pid_fds_parse_failed;
  77. size_t errors_encountered;
  78. } stats;
  79. #ifdef HAVE_LIBMNL
  80. bool use_nl;
  81. struct mnl_socket *nl;
  82. uint16_t tmp_protocol;
  83. #endif
  84. uint64_t proc_self_net_ns_inode;
  85. SIMPLE_HASHTABLE_NET_NS ns_hashtable;
  86. SIMPLE_HASHTABLE_PID_SOCKET pid_sockets_hashtable;
  87. SIMPLE_HASHTABLE_LOCAL_SOCKET sockets_hashtable;
  88. SIMPLE_HASHTABLE_LOCAL_IP local_ips_hashtable;
  89. SIMPLE_HASHTABLE_LISTENING_PORT listening_ports_hashtable;
  90. } LS_STATE;
  91. // --------------------------------------------------------------------------------------------------------------------
  92. typedef enum __attribute__((packed)) {
  93. SOCKET_DIRECTION_NONE = 0,
  94. SOCKET_DIRECTION_LISTEN = (1 << 0), // a listening socket
  95. SOCKET_DIRECTION_INBOUND = (1 << 1), // an inbound socket connecting a remote system to a local listening socket
  96. SOCKET_DIRECTION_OUTBOUND = (1 << 2), // a socket initiated by this system, connecting to another system
  97. SOCKET_DIRECTION_LOCAL = (1 << 3), // the socket connecting 2 localhost applications
  98. } SOCKET_DIRECTION;
  99. #ifndef TASK_COMM_LEN
  100. #define TASK_COMM_LEN 16
  101. #endif
  102. struct pid_socket {
  103. uint64_t inode;
  104. pid_t pid;
  105. uid_t uid;
  106. uint64_t net_ns_inode;
  107. char *cmdline;
  108. char comm[TASK_COMM_LEN];
  109. };
  110. struct local_port {
  111. uint16_t protocol;
  112. uint16_t family;
  113. uint16_t port;
  114. uint64_t net_ns_inode;
  115. };
  116. union ipv46 {
  117. uint32_t ipv4;
  118. struct in6_addr ipv6;
  119. };
  120. struct socket_endpoint {
  121. uint16_t protocol;
  122. uint16_t family;
  123. uint16_t port;
  124. union ipv46 ip;
  125. };
  126. static inline void ipv6_to_in6_addr(const char *ipv6_str, struct in6_addr *d) {
  127. char buf[9];
  128. for (size_t k = 0; k < 4; ++k) {
  129. memcpy(buf, ipv6_str + (k * 8), 8);
  130. buf[sizeof(buf) - 1] = '\0';
  131. d->s6_addr32[k] = strtoul(buf, NULL, 16);
  132. }
  133. }
  134. typedef struct local_socket {
  135. uint64_t inode;
  136. uint64_t net_ns_inode;
  137. int state;
  138. struct socket_endpoint local;
  139. struct socket_endpoint remote;
  140. pid_t pid;
  141. SOCKET_DIRECTION direction;
  142. uint8_t timer;
  143. uint8_t retransmits;
  144. uint32_t expires;
  145. uint32_t rqueue;
  146. uint32_t wqueue;
  147. uid_t uid;
  148. char comm[TASK_COMM_LEN];
  149. char *cmdline;
  150. struct local_port local_port_key;
  151. XXH64_hash_t local_ip_hash;
  152. XXH64_hash_t remote_ip_hash;
  153. XXH64_hash_t local_port_hash;
  154. } LOCAL_SOCKET;
  155. // --------------------------------------------------------------------------------------------------------------------
  156. static inline void local_sockets_log(LS_STATE *ls, const char *format, ...) __attribute__ ((format(__printf__, 2, 3)));
  157. static inline void local_sockets_log(LS_STATE *ls, const char *format, ...) {
  158. if(++ls->stats.errors_encountered == ls->config.max_errors) {
  159. nd_log(NDLS_COLLECTORS, NDLP_ERR, "LOCAL-SOCKETS: max number of logs reached. Not logging anymore");
  160. return;
  161. }
  162. if(ls->stats.errors_encountered > ls->config.max_errors)
  163. return;
  164. char buf[16384];
  165. va_list args;
  166. va_start(args, format);
  167. vsnprintf(buf, sizeof(buf), format, args);
  168. va_end(args);
  169. nd_log(NDLS_COLLECTORS, NDLP_ERR, "LOCAL-SOCKETS: %s", buf);
  170. }
  171. // --------------------------------------------------------------------------------------------------------------------
  172. static void local_sockets_foreach_local_socket_call_cb(LS_STATE *ls) {
  173. for(SIMPLE_HASHTABLE_SLOT_LOCAL_SOCKET *sl = simple_hashtable_first_read_only_LOCAL_SOCKET(&ls->sockets_hashtable);
  174. sl;
  175. sl = simple_hashtable_next_read_only_LOCAL_SOCKET(&ls->sockets_hashtable, sl)) {
  176. LOCAL_SOCKET *n = SIMPLE_HASHTABLE_SLOT_DATA(sl);
  177. if(!n) continue;
  178. if((ls->config.listening && n->direction & SOCKET_DIRECTION_LISTEN) ||
  179. (ls->config.local && n->direction & SOCKET_DIRECTION_LOCAL) ||
  180. (ls->config.inbound && n->direction & SOCKET_DIRECTION_INBOUND) ||
  181. (ls->config.outbound && n->direction & SOCKET_DIRECTION_OUTBOUND)
  182. ) {
  183. // we have to call the callback for this socket
  184. if (ls->config.cb)
  185. ls->config.cb(ls, n, ls->config.data);
  186. }
  187. }
  188. }
  189. // --------------------------------------------------------------------------------------------------------------------
  190. static inline void local_sockets_fix_cmdline(char* str) {
  191. char *s = str;
  192. // map invalid characters to underscores
  193. while(*s) {
  194. if(*s == '|' || iscntrl(*s)) *s = '_';
  195. s++;
  196. }
  197. }
  198. // --------------------------------------------------------------------------------------------------------------------
  199. static inline bool
  200. local_sockets_read_proc_inode_link(LS_STATE *ls, const char *filename, uint64_t *inode, const char *type) {
  201. char link_target[FILENAME_MAX + 1];
  202. *inode = 0;
  203. ssize_t len = readlink(filename, link_target, sizeof(link_target) - 1);
  204. if (len == -1) {
  205. local_sockets_log(ls, "cannot read '%s' link '%s'", type, filename);
  206. ls->stats.pid_fds_readlink_failed++;
  207. return false;
  208. }
  209. link_target[len] = '\0';
  210. len = strlen(type);
  211. if(strncmp(link_target, type, len) == 0 && link_target[len] == ':' && link_target[len + 1] == '[' && isdigit(link_target[len + 2])) {
  212. *inode = strtoull(&link_target[len + 2], NULL, 10);
  213. // ll_log(ls, "read link of type '%s' '%s' from '%s', inode = %"PRIu64, type, link_target, filename, *inode);
  214. return true;
  215. }
  216. else {
  217. // ll_log(ls, "cannot read '%s' link '%s' from '%s'", type, link_target, filename);
  218. ls->stats.pid_fds_processed++;
  219. return false;
  220. }
  221. }
  222. static inline bool local_sockets_is_path_a_pid(const char *s) {
  223. if(!s || !*s) return false;
  224. while(*s) {
  225. if(!isdigit(*s++))
  226. return false;
  227. }
  228. return true;
  229. }
  230. static inline bool local_sockets_find_all_sockets_in_proc(LS_STATE *ls, const char *proc_filename) {
  231. DIR *proc_dir;
  232. struct dirent *proc_entry;
  233. char filename[FILENAME_MAX + 1];
  234. char comm[TASK_COMM_LEN];
  235. char cmdline[8192];
  236. const char *cmdline_trimmed;
  237. uint64_t net_ns_inode;
  238. proc_dir = opendir(proc_filename);
  239. if (proc_dir == NULL) {
  240. local_sockets_log(ls, "cannot opendir() '%s'", proc_filename);
  241. ls->stats.pid_fds_readlink_failed++;
  242. return false;
  243. }
  244. while ((proc_entry = readdir(proc_dir)) != NULL) {
  245. if(proc_entry->d_type != DT_DIR)
  246. continue;
  247. if(!strcmp(proc_entry->d_name, ".") || !strcmp(proc_entry->d_name, ".."))
  248. continue;
  249. if(!local_sockets_is_path_a_pid(proc_entry->d_name))
  250. continue;
  251. // Build the path to the fd directory of the process
  252. snprintfz(filename, FILENAME_MAX, "%s/%s/fd/", proc_filename, proc_entry->d_name);
  253. DIR *fd_dir = opendir(filename);
  254. if (fd_dir == NULL) {
  255. local_sockets_log(ls, "cannot opendir() '%s'", filename);
  256. ls->stats.pid_fds_opendir_failed++;
  257. continue;
  258. }
  259. comm[0] = '\0';
  260. cmdline[0] = '\0';
  261. cmdline_trimmed = NULL;
  262. pid_t pid = (pid_t)strtoul(proc_entry->d_name, NULL, 10);
  263. if(!pid) {
  264. local_sockets_log(ls, "cannot parse pid of '%s'", proc_entry->d_name);
  265. closedir(fd_dir);
  266. continue;
  267. }
  268. net_ns_inode = 0;
  269. uid_t uid = UID_UNSET;
  270. struct dirent *fd_entry;
  271. while ((fd_entry = readdir(fd_dir)) != NULL) {
  272. if(fd_entry->d_type != DT_LNK)
  273. continue;
  274. snprintfz(filename, sizeof(filename), "%s/%s/fd/%s", proc_filename, proc_entry->d_name, fd_entry->d_name);
  275. uint64_t inode = 0;
  276. if(!local_sockets_read_proc_inode_link(ls, filename, &inode, "socket"))
  277. continue;
  278. SIMPLE_HASHTABLE_SLOT_PID_SOCKET *sl = simple_hashtable_get_slot_PID_SOCKET(&ls->pid_sockets_hashtable, inode, &inode, true);
  279. struct pid_socket *ps = SIMPLE_HASHTABLE_SLOT_DATA(sl);
  280. if(!ps || (ps->pid == 1 && pid != 1)) {
  281. if(uid == UID_UNSET && ls->config.uid) {
  282. char status_buf[512];
  283. snprintfz(filename, sizeof(filename), "%s/%s/status", proc_filename, proc_entry->d_name);
  284. if (read_txt_file(filename, status_buf, sizeof(status_buf)))
  285. local_sockets_log(ls, "cannot open file: %s\n", filename);
  286. else {
  287. char *u = strstr(status_buf, "Uid:");
  288. if(u) {
  289. u += 4;
  290. while(isspace(*u)) u++; // skip spaces
  291. while(*u >= '0' && *u <= '9') u++; // skip the first number (real uid)
  292. while(isspace(*u)) u++; // skip spaces again
  293. uid = strtol(u, NULL, 10); // parse the 2nd number (effective uid)
  294. }
  295. }
  296. }
  297. if(!comm[0] && ls->config.comm) {
  298. snprintfz(filename, sizeof(filename), "%s/%s/comm", proc_filename, proc_entry->d_name);
  299. if (read_txt_file(filename, comm, sizeof(comm)))
  300. local_sockets_log(ls, "cannot open file: %s\n", filename);
  301. else {
  302. size_t clen = strlen(comm);
  303. if(comm[clen - 1] == '\n')
  304. comm[clen - 1] = '\0';
  305. }
  306. }
  307. if(!cmdline[0] && ls->config.cmdline) {
  308. snprintfz(filename, sizeof(filename), "%s/%s/cmdline", proc_filename, proc_entry->d_name);
  309. if (read_proc_cmdline(filename, cmdline, sizeof(cmdline)))
  310. local_sockets_log(ls, "cannot open file: %s\n", filename);
  311. else {
  312. local_sockets_fix_cmdline(cmdline);
  313. cmdline_trimmed = trim(cmdline);
  314. }
  315. }
  316. if(!net_ns_inode && ls->config.namespaces) {
  317. snprintfz(filename, sizeof(filename), "%s/%s/ns/net", proc_filename, proc_entry->d_name);
  318. if(local_sockets_read_proc_inode_link(ls, filename, &net_ns_inode, "net")) {
  319. SIMPLE_HASHTABLE_SLOT_NET_NS *sl_ns = simple_hashtable_get_slot_NET_NS(&ls->ns_hashtable, net_ns_inode, (uint64_t *)net_ns_inode, true);
  320. simple_hashtable_set_slot_NET_NS(&ls->ns_hashtable, sl_ns, net_ns_inode, (uint64_t *)net_ns_inode);
  321. }
  322. }
  323. if(!ps)
  324. ps = callocz(1, sizeof(*ps));
  325. ps->inode = inode;
  326. ps->pid = pid;
  327. ps->uid = uid;
  328. ps->net_ns_inode = net_ns_inode;
  329. strncpyz(ps->comm, comm, sizeof(ps->comm) - 1);
  330. if(ps->cmdline)
  331. freez(ps->cmdline);
  332. ps->cmdline = cmdline_trimmed ? strdupz(cmdline_trimmed) : NULL;
  333. simple_hashtable_set_slot_PID_SOCKET(&ls->pid_sockets_hashtable, sl, inode, ps);
  334. }
  335. }
  336. closedir(fd_dir);
  337. }
  338. closedir(proc_dir);
  339. return true;
  340. }
  341. // --------------------------------------------------------------------------------------------------------------------
  342. static bool local_sockets_is_ipv4_mapped_ipv6_address(const struct in6_addr *addr) {
  343. // An IPv4-mapped IPv6 address starts with 80 bits of zeros followed by 16 bits of ones
  344. static const unsigned char ipv4_mapped_prefix[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF };
  345. return memcmp(addr->s6_addr, ipv4_mapped_prefix, 12) == 0;
  346. }
  347. static bool local_sockets_is_loopback_address(struct socket_endpoint *se) {
  348. if (se->family == AF_INET) {
  349. // For IPv4, loopback addresses are in the 127.0.0.0/8 range
  350. return (ntohl(se->ip.ipv4) >> 24) == 127; // Check if the first byte is 127
  351. } else if (se->family == AF_INET6) {
  352. // Check if the address is an IPv4-mapped IPv6 address
  353. if (local_sockets_is_ipv4_mapped_ipv6_address(&se->ip.ipv6)) {
  354. // Extract the last 32 bits (IPv4 address) and check if it's in the 127.0.0.0/8 range
  355. uint8_t *ip6 = (uint8_t *)&se->ip.ipv6;
  356. const uint32_t ipv4_addr = *((const uint32_t *)(ip6 + 12));
  357. return (ntohl(ipv4_addr) >> 24) == 127;
  358. }
  359. // For IPv6, loopback address is ::1
  360. return memcmp(&se->ip.ipv6, &in6addr_loopback, sizeof(se->ip.ipv6)) == 0;
  361. }
  362. return false;
  363. }
  364. static inline bool local_sockets_is_ipv4_reserved_address(uint32_t ip) {
  365. // Check for the reserved address ranges
  366. ip = ntohl(ip);
  367. return (
  368. (ip >> 24 == 10) || // Private IP range (A class)
  369. (ip >> 20 == (172 << 4) + 1) || // Private IP range (B class)
  370. (ip >> 16 == (192 << 8) + 168) || // Private IP range (C class)
  371. (ip >> 24 == 127) || // Loopback address (127.0.0.0)
  372. (ip >> 24 == 0) || // Reserved (0.0.0.0)
  373. (ip >> 24 == 169 && (ip >> 16) == 254) || // Link-local address (169.254.0.0)
  374. (ip >> 16 == (192 << 8) + 0) // Test-Net (192.0.0.0)
  375. );
  376. }
  377. static inline bool local_sockets_is_private_address(struct socket_endpoint *se) {
  378. if (se->family == AF_INET) {
  379. return local_sockets_is_ipv4_reserved_address(se->ip.ipv4);
  380. }
  381. else if (se->family == AF_INET6) {
  382. uint8_t *ip6 = (uint8_t *)&se->ip.ipv6;
  383. // Check if the address is an IPv4-mapped IPv6 address
  384. if (local_sockets_is_ipv4_mapped_ipv6_address(&se->ip.ipv6)) {
  385. // Extract the last 32 bits (IPv4 address) and check if it's in the 127.0.0.0/8 range
  386. const uint32_t ipv4_addr = *((const uint32_t *)(ip6 + 12));
  387. return local_sockets_is_ipv4_reserved_address(ipv4_addr);
  388. }
  389. // Check for link-local addresses (fe80::/10)
  390. if ((ip6[0] == 0xFE) && ((ip6[1] & 0xC0) == 0x80))
  391. return true;
  392. // Check for Unique Local Addresses (ULA) (fc00::/7)
  393. if ((ip6[0] & 0xFE) == 0xFC)
  394. return true;
  395. // Check for multicast addresses (ff00::/8)
  396. if (ip6[0] == 0xFF)
  397. return true;
  398. // For IPv6, loopback address is :: or ::1
  399. return memcmp(&se->ip.ipv6, &in6addr_any, sizeof(se->ip.ipv6)) == 0 ||
  400. memcmp(&se->ip.ipv6, &in6addr_loopback, sizeof(se->ip.ipv6)) == 0;
  401. }
  402. return false;
  403. }
  404. static bool local_sockets_is_multicast_address(struct socket_endpoint *se) {
  405. if (se->family == AF_INET) {
  406. // For IPv4, check if the address is 0.0.0.0
  407. uint32_t ip = htonl(se->ip.ipv4);
  408. return (ip >= 0xE0000000 && ip <= 0xEFFFFFFF); // Multicast address range (224.0.0.0/4)
  409. }
  410. else if (se->family == AF_INET6) {
  411. // For IPv6, check if the address is ff00::/8
  412. uint8_t *ip6 = (uint8_t *)&se->ip.ipv6;
  413. return ip6[0] == 0xff;
  414. }
  415. return false;
  416. }
  417. static bool local_sockets_is_zero_address(struct socket_endpoint *se) {
  418. if (se->family == AF_INET) {
  419. // For IPv4, check if the address is 0.0.0.0
  420. return se->ip.ipv4 == 0;
  421. }
  422. else if (se->family == AF_INET6) {
  423. // For IPv6, check if the address is ::
  424. return memcmp(&se->ip.ipv6, &in6addr_any, sizeof(se->ip.ipv6)) == 0;
  425. }
  426. return false;
  427. }
  428. static inline const char *local_sockets_address_space(struct socket_endpoint *se) {
  429. if(local_sockets_is_zero_address(se))
  430. return "zero";
  431. else if(local_sockets_is_loopback_address(se))
  432. return "loopback";
  433. else if(local_sockets_is_multicast_address(se))
  434. return "multicast";
  435. else if(local_sockets_is_private_address(se))
  436. return "private";
  437. else
  438. return "public";
  439. }
  440. // --------------------------------------------------------------------------------------------------------------------
  441. static inline void local_sockets_index_listening_port(LS_STATE *ls, LOCAL_SOCKET *n) {
  442. if(n->direction & SOCKET_DIRECTION_LISTEN) {
  443. // for the listening sockets, keep a hashtable with all the local ports
  444. // so that we will be able to detect INBOUND sockets
  445. SIMPLE_HASHTABLE_SLOT_LISTENING_PORT *sl_port =
  446. simple_hashtable_get_slot_LISTENING_PORT(&ls->listening_ports_hashtable, n->local_port_hash, &n->local_port_key, true);
  447. struct local_port *port = SIMPLE_HASHTABLE_SLOT_DATA(sl_port);
  448. if(!port)
  449. simple_hashtable_set_slot_LISTENING_PORT(&ls->listening_ports_hashtable, sl_port, n->local_port_hash, &n->local_port_key);
  450. }
  451. }
  452. static inline bool local_sockets_add_socket(LS_STATE *ls, LOCAL_SOCKET *tmp) {
  453. if(!tmp->inode) return false;
  454. SIMPLE_HASHTABLE_SLOT_LOCAL_SOCKET *sl = simple_hashtable_get_slot_LOCAL_SOCKET(&ls->sockets_hashtable, tmp->inode, &tmp->inode, true);
  455. LOCAL_SOCKET *n = SIMPLE_HASHTABLE_SLOT_DATA(sl);
  456. if(n) {
  457. local_sockets_log(ls, "inode %" PRIu64" already exists in hashtable - ignoring duplicate", tmp->inode);
  458. return false;
  459. }
  460. n = (LOCAL_SOCKET *)callocz(1, sizeof(LOCAL_SOCKET));
  461. *n = *tmp; // copy all contents
  462. // fix the key
  463. n->local_port_key.port = n->local.port;
  464. n->local_port_key.family = n->local.family;
  465. n->local_port_key.protocol = n->local.protocol;
  466. n->local_port_key.net_ns_inode = ls->proc_self_net_ns_inode;
  467. n->local_ip_hash = XXH3_64bits(&n->local.ip, sizeof(n->local.ip));
  468. n->remote_ip_hash = XXH3_64bits(&n->remote.ip, sizeof(n->remote.ip));
  469. n->local_port_hash = XXH3_64bits(&n->local_port_key, sizeof(n->local_port_key));
  470. // --- look up a pid for it -----------------------------------------------------------------------------------
  471. SIMPLE_HASHTABLE_SLOT_PID_SOCKET *sl_pid = simple_hashtable_get_slot_PID_SOCKET(&ls->pid_sockets_hashtable, n->inode, &n->inode, false);
  472. struct pid_socket *ps = SIMPLE_HASHTABLE_SLOT_DATA(sl_pid);
  473. if(ps) {
  474. n->net_ns_inode = ps->net_ns_inode;
  475. n->pid = ps->pid;
  476. if(ps->uid != UID_UNSET && n->uid == UID_UNSET)
  477. n->uid = ps->uid;
  478. if(ps->cmdline)
  479. n->cmdline = strdupz(ps->cmdline);
  480. strncpyz(n->comm, ps->comm, sizeof(n->comm) - 1);
  481. }
  482. // --- index it -----------------------------------------------------------------------------------------------
  483. simple_hashtable_set_slot_LOCAL_SOCKET(&ls->sockets_hashtable, sl, n->inode, n);
  484. if(!local_sockets_is_zero_address(&n->local)) {
  485. // put all the local IPs into the local_ips hashtable
  486. // so, we learn all local IPs the system has
  487. SIMPLE_HASHTABLE_SLOT_LOCAL_IP *sl_ip =
  488. simple_hashtable_get_slot_LOCAL_IP(&ls->local_ips_hashtable, n->local_ip_hash, &n->local.ip, true);
  489. union ipv46 *ip = SIMPLE_HASHTABLE_SLOT_DATA(sl_ip);
  490. if(!ip)
  491. simple_hashtable_set_slot_LOCAL_IP(&ls->local_ips_hashtable, sl_ip, n->local_ip_hash, &n->local.ip);
  492. }
  493. // --- 1st phase for direction detection ----------------------------------------------------------------------
  494. if((n->local.protocol == IPPROTO_TCP && n->state == TCP_LISTEN) ||
  495. local_sockets_is_zero_address(&n->local) ||
  496. local_sockets_is_zero_address(&n->remote)) {
  497. // the socket is either in a TCP LISTEN, or
  498. // the remote address is zero
  499. n->direction |= SOCKET_DIRECTION_LISTEN;
  500. }
  501. else if(
  502. local_sockets_is_loopback_address(&n->local) ||
  503. local_sockets_is_loopback_address(&n->remote)) {
  504. // the local IP address is loopback
  505. n->direction |= SOCKET_DIRECTION_LOCAL;
  506. }
  507. else {
  508. // we can't say yet if it is inbound or outboud
  509. // so, mark it as both inbound and outbound
  510. n->direction |= SOCKET_DIRECTION_INBOUND | SOCKET_DIRECTION_OUTBOUND;
  511. }
  512. // --- index it in LISTENING_PORT -----------------------------------------------------------------------------
  513. local_sockets_index_listening_port(ls, n);
  514. return true;
  515. }
  516. #ifdef HAVE_LIBMNL
  517. static inline void local_sockets_netlink_init(LS_STATE *ls) {
  518. ls->use_nl = true;
  519. ls->nl = mnl_socket_open(NETLINK_INET_DIAG);
  520. if (!ls->nl) {
  521. local_sockets_log(ls, "cannot open netlink socket");
  522. ls->use_nl = false;
  523. }
  524. if (mnl_socket_bind(ls->nl, 0, MNL_SOCKET_AUTOPID) < 0) {
  525. local_sockets_log(ls, "cannot bind netlink socket");
  526. ls->use_nl = false;
  527. }
  528. }
  529. static inline void local_sockets_netlink_cleanup(LS_STATE *ls) {
  530. if(ls->nl) {
  531. mnl_socket_close(ls->nl);
  532. ls->nl = NULL;
  533. }
  534. }
  535. static inline int local_sockets_netlink_cb_data(const struct nlmsghdr *nlh, void *data) {
  536. LS_STATE *ls = data;
  537. struct inet_diag_msg *diag_msg = mnl_nlmsg_get_payload(nlh);
  538. LOCAL_SOCKET n = {
  539. .inode = diag_msg->idiag_inode,
  540. .direction = SOCKET_DIRECTION_NONE,
  541. .state = diag_msg->idiag_state,
  542. .local = {
  543. .protocol = ls->tmp_protocol,
  544. .family = diag_msg->idiag_family,
  545. .port = diag_msg->id.idiag_sport,
  546. },
  547. .remote = {
  548. .protocol = ls->tmp_protocol,
  549. .family = diag_msg->idiag_family,
  550. .port = diag_msg->id.idiag_dport,
  551. },
  552. .timer = diag_msg->idiag_timer,
  553. .retransmits = diag_msg->idiag_retrans,
  554. .expires = diag_msg->idiag_expires,
  555. .rqueue = diag_msg->idiag_rqueue,
  556. .wqueue = diag_msg->idiag_wqueue,
  557. .uid = diag_msg->idiag_uid,
  558. };
  559. if (diag_msg->idiag_family == AF_INET) {
  560. memcpy(&n.local.ip.ipv4, diag_msg->id.idiag_src, sizeof(n.local.ip.ipv4));
  561. memcpy(&n.remote.ip.ipv4, diag_msg->id.idiag_dst, sizeof(n.remote.ip.ipv4));
  562. }
  563. else if (diag_msg->idiag_family == AF_INET6) {
  564. memcpy(&n.local.ip.ipv6, diag_msg->id.idiag_src, sizeof(n.local.ip.ipv6));
  565. memcpy(&n.remote.ip.ipv6, diag_msg->id.idiag_dst, sizeof(n.remote.ip.ipv6));
  566. }
  567. local_sockets_add_socket(ls, &n);
  568. return MNL_CB_OK;
  569. }
  570. static inline bool local_sockets_netlink_get_sockets(LS_STATE *ls, uint16_t family, uint16_t protocol) {
  571. ls->tmp_protocol = protocol;
  572. char buf[MNL_SOCKET_BUFFER_SIZE];
  573. struct nlmsghdr *nlh;
  574. struct inet_diag_req_v2 req;
  575. unsigned int seq, portid = mnl_socket_get_portid(ls->nl);
  576. memset(&req, 0, sizeof(req));
  577. req.sdiag_family = family;
  578. req.sdiag_protocol = protocol;
  579. req.idiag_states = -1;
  580. nlh = mnl_nlmsg_put_header(buf);
  581. nlh->nlmsg_type = SOCK_DIAG_BY_FAMILY;
  582. nlh->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
  583. nlh->nlmsg_seq = seq = time(NULL);
  584. mnl_nlmsg_put_extra_header(nlh, sizeof(req));
  585. memcpy(mnl_nlmsg_get_payload(nlh), &req, sizeof(req));
  586. if (mnl_socket_sendto(ls->nl, nlh, nlh->nlmsg_len) < 0) {
  587. local_sockets_log(ls, "mnl_socket_send failed");
  588. return false;
  589. }
  590. ssize_t ret;
  591. while ((ret = mnl_socket_recvfrom(ls->nl, buf, sizeof(buf))) > 0) {
  592. ret = mnl_cb_run(buf, ret, seq, portid, local_sockets_netlink_cb_data, ls);
  593. if (ret <= MNL_CB_STOP)
  594. break;
  595. }
  596. if (ret == -1) {
  597. local_sockets_log(ls, "mnl_socket_recvfrom");
  598. return false;
  599. }
  600. return true;
  601. }
  602. #endif // HAVE_LIBMNL
  603. static inline bool local_sockets_read_proc_net_x(LS_STATE *ls, const char *filename, uint16_t family, uint16_t protocol) {
  604. if(family != AF_INET && family != AF_INET6)
  605. return false;
  606. FILE *fp;
  607. char *line = NULL;
  608. size_t len = 0;
  609. ssize_t read;
  610. fp = fopen(filename, "r");
  611. if (fp == NULL)
  612. return false;
  613. ssize_t min_line_length = (family == AF_INET) ? 105 : 155;
  614. size_t counter = 0;
  615. // Read line by line
  616. while ((read = getline(&line, &len, fp)) != -1) {
  617. if(counter++ == 0) continue; // skip the first line
  618. if(read < min_line_length) {
  619. local_sockets_log(ls, "too small line No %zu of filename '%s': %s", counter, filename, line);
  620. continue;
  621. }
  622. unsigned int local_address, local_port, state, remote_address, remote_port;
  623. uint64_t inode = 0;
  624. char local_address6[33], remote_address6[33];
  625. if(family == AF_INET) {
  626. if (sscanf(line, "%*d: %X:%X %X:%X %X %*X:%*X %*X:%*X %*X %*d %*d %"PRIu64,
  627. &local_address, &local_port, &remote_address, &remote_port, &state, &inode) != 6) {
  628. local_sockets_log(ls, "cannot parse ipv4 line No %zu of filename '%s': %s", counter, filename, line);
  629. continue;
  630. }
  631. }
  632. else if(family == AF_INET6) {
  633. 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,
  634. local_address6, &local_port, remote_address6, &remote_port, &state, &inode) != 6) {
  635. local_sockets_log(ls, "cannot parse ipv6 line No %zu of filename '%s': %s", counter, filename, line);
  636. continue;
  637. }
  638. }
  639. LOCAL_SOCKET n = {
  640. .inode = inode,
  641. .direction = SOCKET_DIRECTION_NONE,
  642. .state = (int)state,
  643. .local = {
  644. .family = family,
  645. .protocol = protocol,
  646. .port = local_port,
  647. },
  648. .remote = {
  649. .family = family,
  650. .protocol = protocol,
  651. .port = remote_port,
  652. },
  653. .uid = UID_UNSET,
  654. };
  655. if(family == AF_INET) {
  656. n.local.ip.ipv4 = local_address;
  657. n.remote.ip.ipv4 = remote_address;
  658. }
  659. else if(family == AF_INET6) {
  660. ipv6_to_in6_addr(local_address6, &n.local.ip.ipv6);
  661. ipv6_to_in6_addr(remote_address6, &n.remote.ip.ipv6);
  662. }
  663. local_sockets_add_socket(ls, &n);
  664. }
  665. fclose(fp);
  666. if (line)
  667. freez(line);
  668. return true;
  669. }
  670. // --------------------------------------------------------------------------------------------------------------------
  671. static inline void local_sockets_detect_directions(LS_STATE *ls) {
  672. for(SIMPLE_HASHTABLE_SLOT_LOCAL_SOCKET *sl = simple_hashtable_first_read_only_LOCAL_SOCKET(&ls->sockets_hashtable);
  673. sl ;
  674. sl = simple_hashtable_next_read_only_LOCAL_SOCKET(&ls->sockets_hashtable, sl)) {
  675. LOCAL_SOCKET *n = SIMPLE_HASHTABLE_SLOT_DATA(sl);
  676. if (!n) continue;
  677. if ((n->direction & (SOCKET_DIRECTION_INBOUND|SOCKET_DIRECTION_OUTBOUND)) !=
  678. (SOCKET_DIRECTION_INBOUND|SOCKET_DIRECTION_OUTBOUND))
  679. continue;
  680. // check if the remote IP is one of our local IPs
  681. {
  682. SIMPLE_HASHTABLE_SLOT_LOCAL_IP *sl_ip =
  683. simple_hashtable_get_slot_LOCAL_IP(&ls->local_ips_hashtable, n->remote_ip_hash, &n->remote.ip, false);
  684. union ipv46 *d = SIMPLE_HASHTABLE_SLOT_DATA(sl_ip);
  685. if (d) {
  686. // the remote IP of this socket is one of our local IPs
  687. n->direction &= ~(SOCKET_DIRECTION_INBOUND|SOCKET_DIRECTION_OUTBOUND);
  688. n->direction |= SOCKET_DIRECTION_LOCAL;
  689. continue;
  690. }
  691. }
  692. // check if the local port is one of our listening ports
  693. {
  694. SIMPLE_HASHTABLE_SLOT_LISTENING_PORT *sl_port =
  695. simple_hashtable_get_slot_LISTENING_PORT(&ls->listening_ports_hashtable, n->local_port_hash, &n->local_port_key, false);
  696. struct local_port *port = SIMPLE_HASHTABLE_SLOT_DATA(sl_port); // do not reference this pointer - is invalid
  697. if(port) {
  698. // the local port of this socket is a port we listen to
  699. n->direction &= ~SOCKET_DIRECTION_OUTBOUND;
  700. }
  701. else
  702. n->direction &= ~SOCKET_DIRECTION_INBOUND;
  703. }
  704. }
  705. }
  706. // --------------------------------------------------------------------------------------------------------------------
  707. static inline void local_sockets_init(LS_STATE *ls) {
  708. simple_hashtable_init_NET_NS(&ls->ns_hashtable, 1024);
  709. simple_hashtable_init_PID_SOCKET(&ls->pid_sockets_hashtable, 65535);
  710. simple_hashtable_init_LOCAL_SOCKET(&ls->sockets_hashtable, 65535);
  711. simple_hashtable_init_LOCAL_IP(&ls->local_ips_hashtable, 4096);
  712. simple_hashtable_init_LISTENING_PORT(&ls->listening_ports_hashtable, 4096);
  713. }
  714. static inline void local_sockets_cleanup(LS_STATE *ls) {
  715. // free the sockets hashtable data
  716. for(SIMPLE_HASHTABLE_SLOT_LOCAL_SOCKET *sl = simple_hashtable_first_read_only_LOCAL_SOCKET(&ls->sockets_hashtable);
  717. sl;
  718. sl = simple_hashtable_next_read_only_LOCAL_SOCKET(&ls->sockets_hashtable, sl)) {
  719. LOCAL_SOCKET *n = SIMPLE_HASHTABLE_SLOT_DATA(sl);
  720. if(!n) continue;
  721. freez(n->cmdline);
  722. freez(n);
  723. }
  724. // free the pid_socket hashtable data
  725. for(SIMPLE_HASHTABLE_SLOT_PID_SOCKET *sl = simple_hashtable_first_read_only_PID_SOCKET(&ls->pid_sockets_hashtable);
  726. sl;
  727. sl = simple_hashtable_next_read_only_PID_SOCKET(&ls->pid_sockets_hashtable, sl)) {
  728. struct pid_socket *ps = SIMPLE_HASHTABLE_SLOT_DATA(sl);
  729. if(!ps) continue;
  730. freez(ps->cmdline);
  731. freez(ps);
  732. }
  733. // free the hashtable
  734. simple_hashtable_destroy_NET_NS(&ls->ns_hashtable);
  735. simple_hashtable_destroy_PID_SOCKET(&ls->pid_sockets_hashtable);
  736. simple_hashtable_destroy_LISTENING_PORT(&ls->listening_ports_hashtable);
  737. simple_hashtable_destroy_LOCAL_IP(&ls->local_ips_hashtable);
  738. simple_hashtable_destroy_LOCAL_SOCKET(&ls->sockets_hashtable);
  739. }
  740. // --------------------------------------------------------------------------------------------------------------------
  741. static inline void local_sockets_do_family_protocol(LS_STATE *ls, const char *filename, uint16_t family, uint16_t protocol) {
  742. #ifdef HAVE_LIBMNL
  743. if(ls->use_nl) {
  744. ls->use_nl = local_sockets_netlink_get_sockets(ls, family, protocol);
  745. if(ls->use_nl)
  746. return;
  747. }
  748. #endif
  749. local_sockets_read_proc_net_x(ls, filename, family, protocol);
  750. }
  751. static inline void local_sockets_read_sockets_from_proc(LS_STATE *ls) {
  752. char path[FILENAME_MAX + 1];
  753. if(ls->config.namespaces) {
  754. snprintfz(path, sizeof(path), "%s/proc/self/ns/net", ls->config.host_prefix);
  755. local_sockets_read_proc_inode_link(ls, path, &ls->proc_self_net_ns_inode, "net");
  756. }
  757. if(ls->config.cmdline || ls->config.comm || ls->config.pid || ls->config.namespaces) {
  758. snprintfz(path, sizeof(path), "%s/proc", ls->config.host_prefix);
  759. local_sockets_find_all_sockets_in_proc(ls, path);
  760. }
  761. if(ls->config.tcp4) {
  762. snprintfz(path, sizeof(path), "%s/proc/net/tcp", ls->config.host_prefix);
  763. local_sockets_do_family_protocol(ls, path, AF_INET, IPPROTO_TCP);
  764. }
  765. if(ls->config.udp4) {
  766. snprintfz(path, sizeof(path), "%s/proc/net/udp", ls->config.host_prefix);
  767. local_sockets_do_family_protocol(ls, path, AF_INET, IPPROTO_UDP);
  768. }
  769. if(ls->config.tcp6) {
  770. snprintfz(path, sizeof(path), "%s/proc/net/tcp6", ls->config.host_prefix);
  771. local_sockets_do_family_protocol(ls, path, AF_INET6, IPPROTO_TCP);
  772. }
  773. if(ls->config.udp6) {
  774. snprintfz(path, sizeof(path), "%s/proc/net/udp6", ls->config.host_prefix);
  775. local_sockets_do_family_protocol(ls, path, AF_INET6, IPPROTO_UDP);
  776. }
  777. }
  778. // --------------------------------------------------------------------------------------------------------------------
  779. struct local_sockets_child_work {
  780. int fd;
  781. uint64_t net_ns_inode;
  782. };
  783. static inline void local_sockets_send_to_parent(struct local_socket_state *ls __maybe_unused, struct local_socket *n, void *data) {
  784. struct local_sockets_child_work *cw = data;
  785. int fd = cw->fd;
  786. if(n->net_ns_inode != cw->net_ns_inode)
  787. return;
  788. // local_sockets_log(ls, "child is sending inode %"PRIu64" of namespace %"PRIu64, n->inode, n->net_ns_inode);
  789. if(write(fd, n, sizeof(*n)) != sizeof(*n))
  790. local_sockets_log(ls, "failed to write local socket to pipe");
  791. size_t len = n->cmdline ? strlen(n->cmdline) + 1 : 0;
  792. if(write(fd, &len, sizeof(len)) != sizeof(len))
  793. local_sockets_log(ls, "failed to write cmdline length to pipe");
  794. if(len)
  795. if(write(fd, n->cmdline, len) != (ssize_t)len)
  796. local_sockets_log(ls, "failed to write cmdline to pipe");
  797. }
  798. static inline bool local_sockets_get_namespace_sockets(LS_STATE *ls, struct pid_socket *ps, pid_t *pid) {
  799. char filename[1024];
  800. snprintfz(filename, sizeof(filename), "%s/proc/%d/ns/net", ls->config.host_prefix, ps->pid);
  801. // verify the pid is in the target namespace
  802. int fd = open(filename, O_RDONLY | O_CLOEXEC);
  803. if (fd == -1) {
  804. local_sockets_log(ls, "cannot open file '%s'", filename);
  805. return false;
  806. }
  807. struct stat statbuf;
  808. if (fstat(fd, &statbuf) == -1) {
  809. close(fd);
  810. local_sockets_log(ls, "failed to get file statistics for '%s'", filename);
  811. return false;
  812. }
  813. if (statbuf.st_ino != ps->net_ns_inode) {
  814. close(fd);
  815. local_sockets_log(ls, "pid %d is not in the wanted network namespace", ps->pid);
  816. return false;
  817. }
  818. int pipefd[2];
  819. if (pipe(pipefd) != 0) {
  820. local_sockets_log(ls, "cannot create pipe");
  821. close(fd);
  822. return false;
  823. }
  824. *pid = fork();
  825. if (*pid == 0) {
  826. // Child process
  827. close(pipefd[0]);
  828. // local_sockets_log(ls, "child is here for inode %"PRIu64" and namespace %"PRIu64, ps->inode, ps->net_ns_inode);
  829. struct local_sockets_child_work cw = {
  830. .net_ns_inode = ps->net_ns_inode,
  831. .fd = pipefd[1],
  832. };
  833. ls->config.host_prefix = ""; // we need the /proc of the container
  834. ls->config.cb = local_sockets_send_to_parent;
  835. ls->config.data = &cw;
  836. ls->config.cmdline = false; // we have these already
  837. ls->config.comm = false; // we have these already
  838. ls->config.pid = false; // we have these already
  839. ls->config.namespaces = false;
  840. ls->proc_self_net_ns_inode = ps->net_ns_inode;
  841. // switch namespace
  842. if (setns(fd, CLONE_NEWNET) == -1) {
  843. local_sockets_log(ls, "failed to switch network namespace at child process");
  844. exit(EXIT_FAILURE);
  845. }
  846. #ifdef HAVE_LIBMNL
  847. local_sockets_netlink_cleanup(ls);
  848. local_sockets_netlink_init(ls);
  849. #endif
  850. // read all sockets from /proc
  851. local_sockets_read_sockets_from_proc(ls);
  852. // send all sockets to parent
  853. local_sockets_foreach_local_socket_call_cb(ls);
  854. // send the terminating socket
  855. struct local_socket zero = {
  856. .net_ns_inode = ps->net_ns_inode,
  857. };
  858. local_sockets_send_to_parent(ls, &zero, &cw);
  859. #ifdef HAVE_LIBMNL
  860. local_sockets_netlink_cleanup(ls);
  861. #endif
  862. close(pipefd[1]); // Close write end of pipe
  863. exit(EXIT_SUCCESS);
  864. }
  865. // parent
  866. close(fd);
  867. close(pipefd[1]);
  868. size_t received = 0;
  869. struct local_socket buf;
  870. while(read(pipefd[0], &buf, sizeof(buf)) == sizeof(buf)) {
  871. size_t len = 0;
  872. if(read(pipefd[0], &len, sizeof(len)) != sizeof(len))
  873. local_sockets_log(ls, "failed to read cmdline length from pipe");
  874. if(len) {
  875. buf.cmdline = mallocz(len);
  876. if(read(pipefd[0], buf.cmdline, len) != (ssize_t)len)
  877. local_sockets_log(ls, "failed to read cmdline from pipe");
  878. }
  879. else
  880. buf.cmdline = NULL;
  881. received++;
  882. struct local_socket zero = {
  883. .net_ns_inode = ps->net_ns_inode,
  884. };
  885. if(memcmp(&buf, &zero, sizeof(buf)) == 0) {
  886. // the terminator
  887. break;
  888. }
  889. SIMPLE_HASHTABLE_SLOT_LOCAL_SOCKET *sl = simple_hashtable_get_slot_LOCAL_SOCKET(&ls->sockets_hashtable, buf.inode, &buf, true);
  890. LOCAL_SOCKET *n = SIMPLE_HASHTABLE_SLOT_DATA(sl);
  891. if(n) {
  892. if(buf.cmdline)
  893. freez(buf.cmdline);
  894. // local_sockets_log(ls,
  895. // "ns inode %" PRIu64" (comm: '%s', pid: %u, ns: %"PRIu64") already exists in hashtable (comm: '%s', pid: %u, ns: %"PRIu64") - ignoring duplicate",
  896. // buf.inode, buf.comm, buf.pid, buf.net_ns_inode, n->comm, n->pid, n->net_ns_inode);
  897. continue;
  898. }
  899. else {
  900. n = mallocz(sizeof(*n));
  901. memcpy(n, &buf, sizeof(*n));
  902. simple_hashtable_set_slot_LOCAL_SOCKET(&ls->sockets_hashtable, sl, n->inode, n);
  903. local_sockets_index_listening_port(ls, n);
  904. }
  905. }
  906. close(pipefd[0]);
  907. return received > 0;
  908. }
  909. static inline void local_socket_waitpid(LS_STATE *ls, pid_t pid) {
  910. if(!pid) return;
  911. int status;
  912. waitpid(pid, &status, 0);
  913. if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
  914. local_sockets_log(ls, "Child exited with status %d", WEXITSTATUS(status));
  915. else if (WIFSIGNALED(status))
  916. local_sockets_log(ls, "Child terminated by signal %d", WTERMSIG(status));
  917. }
  918. static inline void local_sockets_namespaces(LS_STATE *ls) {
  919. pid_t children[5] = { 0 };
  920. size_t last_child = 0;
  921. for(SIMPLE_HASHTABLE_SLOT_NET_NS *sl = simple_hashtable_first_read_only_NET_NS(&ls->ns_hashtable);
  922. sl;
  923. sl = simple_hashtable_next_read_only_NET_NS(&ls->ns_hashtable, sl)) {
  924. uint64_t inode = (uint64_t)SIMPLE_HASHTABLE_SLOT_DATA(sl);
  925. if(inode == ls->proc_self_net_ns_inode)
  926. continue;
  927. // find a pid_socket that has this namespace
  928. for(SIMPLE_HASHTABLE_SLOT_PID_SOCKET *sl_pid = simple_hashtable_first_read_only_PID_SOCKET(&ls->pid_sockets_hashtable) ;
  929. sl_pid ;
  930. sl_pid = simple_hashtable_next_read_only_PID_SOCKET(&ls->pid_sockets_hashtable, sl_pid)) {
  931. struct pid_socket *ps = SIMPLE_HASHTABLE_SLOT_DATA(sl_pid);
  932. if(!ps || ps->net_ns_inode != inode) continue;
  933. if(++last_child >= 5)
  934. last_child = 0;
  935. local_socket_waitpid(ls, children[last_child]);
  936. children[last_child] = 0;
  937. // now we have a pid that has the same namespace inode
  938. if(local_sockets_get_namespace_sockets(ls, ps, &children[last_child]))
  939. break;
  940. }
  941. }
  942. for(size_t i = 0; i < 5 ;i++)
  943. local_socket_waitpid(ls, children[i]);
  944. }
  945. // --------------------------------------------------------------------------------------------------------------------
  946. static inline void local_sockets_process(LS_STATE *ls) {
  947. #ifdef HAVE_LIBMNL
  948. local_sockets_netlink_init(ls);
  949. #endif
  950. ls->config.host_prefix = netdata_configured_host_prefix;
  951. // initialize our hashtables
  952. local_sockets_init(ls);
  953. // read all sockets from /proc
  954. local_sockets_read_sockets_from_proc(ls);
  955. // check all socket namespaces
  956. if(ls->config.namespaces)
  957. local_sockets_namespaces(ls);
  958. // detect the directions of the sockets
  959. if(ls->config.inbound || ls->config.outbound || ls->config.local)
  960. local_sockets_detect_directions(ls);
  961. // call the callback for each socket
  962. local_sockets_foreach_local_socket_call_cb(ls);
  963. // free all memory
  964. local_sockets_cleanup(ls);
  965. #ifdef HAVE_LIBMNL
  966. local_sockets_netlink_cleanup(ls);
  967. #endif
  968. }
  969. static inline void ipv6_address_to_txt(struct in6_addr *in6_addr, char *dst) {
  970. struct sockaddr_in6 sa = { 0 };
  971. sa.sin6_family = AF_INET6;
  972. sa.sin6_port = htons(0);
  973. sa.sin6_addr = *in6_addr;
  974. // Convert to human-readable format
  975. if (inet_ntop(AF_INET6, &(sa.sin6_addr), dst, INET6_ADDRSTRLEN) == NULL)
  976. *dst = '\0';
  977. }
  978. static inline void ipv4_address_to_txt(uint32_t ip, char *dst) {
  979. uint8_t octets[4];
  980. octets[0] = ip & 0xFF;
  981. octets[1] = (ip >> 8) & 0xFF;
  982. octets[2] = (ip >> 16) & 0xFF;
  983. octets[3] = (ip >> 24) & 0xFF;
  984. sprintf(dst, "%u.%u.%u.%u", octets[0], octets[1], octets[2], octets[3]);
  985. }
  986. #endif //NETDATA_LOCAL_SOCKETS_H