@cryptotaxi247 / netdata-1 / commits / 34cbe9f98

Common O/S Caching Layer for users and groups (#18825)

* added cached-uid-usernames to libnetdata * added cached-gid-groupnames * apps.plugin uses the common cache for users and groups * apps.plugin cleanup * network-viewer and systemd-journal now use host prefix to ingest usernames and groups * fix compilation on windows * move unicode functions from windows-events to libnetdata * move sid-to-username from windows-events plugin to libnetdata * common.h in libnetdata for operating system includes and macros * sid uses STRINGs * apps.plugin now exposes per user charts on windows

Costa Tsaousis committed Oct 21, 2024 at 10:04 UTC 34cbe9f98d4f3bdaa298074b1504021d7068247c
46 files changed +1557 -1238
CMakeLists.txt
+12 -9
@@ -768,6 +768,14 @@ set(LIBNETDATA_FILES
768 src/libnetdata/os/windows-perflib/perflib.h
769 src/libnetdata/os/windows-perflib/perflib-names.c
770 src/libnetdata/os/windows-perflib/perflib-dump.c
771 + src/libnetdata/os/system-maps/cached-uid-username.c
772 + src/libnetdata/os/system-maps/cached-uid-username.h
773 + src/libnetdata/os/system-maps/cached-sid-username.c
774 + src/libnetdata/os/system-maps/cached-sid-username.h
775 + src/libnetdata/os/system-maps/cached-gid-groupname.c
776 + src/libnetdata/os/system-maps/cached-gid-groupname.h
777 + src/libnetdata/os/system-maps/cache-host-users-and-groups.c
778 + src/libnetdata/os/system-maps/cache-host-users-and-groups.h
779 src/libnetdata/spawn_server/spawn_server_nofork.c
780 src/libnetdata/spawn_server/spawn_server.h
781 src/libnetdata/spawn_server/spawn_popen.c
@@ -845,6 +853,7 @@ set(LIBNETDATA_FILES
853 src/libnetdata/spawn_server/log-forwarder.h
854 src/libnetdata/log/nd_log-common.h
855 src/libnetdata/log/nd_log-to-windows-common.h
856 + src/libnetdata/common.h
857 )
858
859 if(ENABLE_PLUGIN_EBPF)
@@ -1332,9 +1341,7 @@ set(SYSTEMD_JOURNAL_PLUGIN_FILES
1341 src/collectors/systemd-journal.plugin/systemd-journal-fstat.c
1342 src/collectors/systemd-journal.plugin/systemd-journal-watcher.c
1343 src/collectors/systemd-journal.plugin/systemd-journal-dyncfg.c
1335 - src/libnetdata/maps/system-users.h
1336 - src/libnetdata/maps/system-groups.h
1337 - src/libnetdata/maps/system-services.h
1344 + src/libnetdata/os/system-maps/system-services.h
1345 src/collectors/systemd-journal.plugin/systemd-journal-sampling.h
1346 )
1347
@@ -1464,8 +1471,6 @@ set(WINDOWS_EVENTS_PLUGIN_FILES
1471 src/collectors/windows-events.plugin/windows-events-query.c
1472 src/collectors/windows-events.plugin/windows-events-sources.c
1473 src/collectors/windows-events.plugin/windows-events-sources.h
1467 - src/collectors/windows-events.plugin/windows-events-sid.c
1468 - src/collectors/windows-events.plugin/windows-events-sid.h
1474 src/collectors/windows-events.plugin/windows-events-unicode.c
1475 src/collectors/windows-events.plugin/windows-events-unicode.h
1476 src/collectors/windows-events.plugin/windows-events-xml.c
@@ -2020,7 +2025,6 @@ if(ENABLE_PLUGIN_APPS)
2025 src/collectors/apps.plugin/apps_plugin.h
2026 src/collectors/apps.plugin/apps_functions.c
2027 src/collectors/apps.plugin/apps_targets.c
2023 - src/collectors/apps.plugin/apps_users_and_groups.c
2028 src/collectors/apps.plugin/apps_output.c
2029 src/collectors/apps.plugin/apps_pid_files.c
2030 src/collectors/apps.plugin/apps_pid.c
@@ -2356,7 +2360,7 @@ endif()
2360 if(ENABLE_PLUGIN_LOCAL_LISTENERS)
2361 set(LOCAL_LISTENERS_FILES
2362 src/collectors/utils/local_listeners.c
2359 - src/libnetdata/maps/local-sockets.h
2363 + src/libnetdata/local-sockets/local-sockets.h
2364 )
2365
2366 add_executable(local-listeners ${LOCAL_LISTENERS_FILES})
@@ -2375,8 +2379,7 @@ endif()
2379
2380 if(ENABLE_PLUGIN_NETWORK_VIEWER)
2381 set(NETWORK_VIEWER_FILES
2378 - src/libnetdata/maps/local-sockets.h
2379 - src/libnetdata/maps/system-users.h
2382 + src/libnetdata/local-sockets/local-sockets.h
2383 src/collectors/network-viewer.plugin/network-viewer.c
2384 )
2385
src/collectors/apps.plugin/apps_aggregations.c
+20
@@ -169,6 +169,9 @@ void aggregate_processes_to_targets(void) {
169 #if (PROCESSES_HAVE_GID == 1)
170 zero_all_targets(groups_root_target);
171 #endif
172 +#if (PROCESSES_HAVE_SID == 1)
173 + zero_all_targets(sids_root_target);
174 +#endif
175
176 // this has to be done, before the cleanup
177 struct target *w = NULL, *o = NULL;
@@ -187,6 +190,8 @@ void aggregate_processes_to_targets(void) {
190 // user target
191
192 #if (PROCESSES_HAVE_UID == 1)
193 + update_cached_host_users();
194 +
195 o = p->uid_target;
196 if(likely(p->uid_target && p->uid_target->uid == p->uid))
197 w = p->uid_target;
@@ -204,6 +209,8 @@ void aggregate_processes_to_targets(void) {
209 // user group target
210
211 #if (PROCESSES_HAVE_GID == 1)
212 + update_cached_host_users();
213 +
214 o = p->gid_target;
215 if(likely(p->gid_target && p->gid_target->gid == p->gid))
216 w = p->gid_target;
@@ -214,6 +221,19 @@ void aggregate_processes_to_targets(void) {
221 w = p->gid_target = get_gid_target(p->gid);
222 }
223
224 + aggregate_pid_on_target(w, p, o);
225 +#endif
226 +
227 + // --------------------------------------------------------------------
228 + // sid target
229 +
230 +#if (PROCESSES_HAVE_SID == 1)
231 + o = p->sid_target;
232 + if(likely(p->sid_target && p->sid_target->sid_name == p->sid_name))
233 + w = p->sid_target;
234 + else
235 + w = p->sid_target = get_sid_target(p->sid_name);
236 +
237 aggregate_pid_on_target(w, p, o);
238 #endif
239
src/collectors/apps.plugin/apps_functions.c
+22 -5
@@ -27,7 +27,7 @@ static void apps_plugin_function_processes_help(const char *transaction) {
27 " parent:NAME\n"
28 " Shows only processes that are aggregated under parent `NAME`\n"
29 "\n"
30 -#if (PROCESSES_HAVE_UID == 1)
30 +#if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_SID == 1)
31 " user:NAME\n"
32 " Shows only processes that are running as user name `NAME`.\n"
33 "\n"
@@ -89,6 +89,12 @@ void function_processes(const char *transaction, char *function,
89 size_t num_words = quoted_strings_splitter_whitespace(function, words, PLUGINSD_MAX_WORDS);
90
91 struct target *category = NULL, *user = NULL, *group = NULL; (void)category; (void)user; (void)group;
92 +#if (PROCESSES_HAVE_UID == 1)
93 + struct target *users_sid_root = users_root_target;
94 +#endif
95 +#if (PROCESSES_HAVE_SID == 1)
96 + struct target *users_sid_root = sids_root_target;
97 +#endif
98 const char *process_name = NULL;
99 pid_t pid = 0;
100 uid_t uid = 0; (void)uid;
@@ -110,9 +116,9 @@ void function_processes(const char *transaction, char *function,
116 return;
117 }
118 }
113 -#if (PROCESSES_HAVE_UID == 1)
119 +#if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_SID == 1)
120 else if(!user && strncmp(keyword, PROCESS_FILTER_USER, strlen(PROCESS_FILTER_USER)) == 0) {
115 - user = find_target_by_name(users_root_target, &keyword[strlen(PROCESS_FILTER_USER)]);
121 + user = find_target_by_name(users_sid_root, &keyword[strlen(PROCESS_FILTER_USER)]);
122 if(!user) {
123 pluginsd_function_json_error_to_stdout(transaction, HTTP_RESP_BAD_REQUEST,
124 "No user with that name found.");
@@ -271,6 +277,11 @@ void function_processes(const char *transaction, char *function,
277 continue;
278 #endif
279
280 +#if (PROCESSES_HAVE_SID == 1)
281 + if(user && p->sid_target != user)
282 + continue;
283 +#endif
284 +
285 if(process_name && ((strcmp(pid_stat_comm(p), process_name) != 0 && !p->parent) || (p->parent && strcmp(pid_stat_comm(p), process_name) != 0 && strcmp(pid_stat_comm(p->parent), process_name) != 0)))
286 continue;
287
@@ -323,6 +334,10 @@ void function_processes(const char *transaction, char *function,
334 // uid
335 buffer_json_add_array_item_uint64(wb, p->uid);
336 #endif
337 +#if (PROCESSES_HAVE_SID == 1)
338 + // account
339 + buffer_json_add_array_item_string(wb, p->sid_target ? string2str(p->sid_target->name) : "-");
340 +#endif
341
342 #if (PROCESSES_HAVE_GID == 1)
343 // group
@@ -493,12 +508,14 @@ void function_processes(const char *transaction, char *function,
508 RRDF_FIELD_FILTER_MULTISELECT,
509 RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY, NULL);
510
496 -#if (PROCESSES_HAVE_UID == 1)
511 +#if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_SID == 1)
512 buffer_rrdf_table_add_field(wb, field_id++, "User", "User Owner", RRDF_FIELD_TYPE_STRING,
513 RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
514 RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
515 RRDF_FIELD_FILTER_MULTISELECT,
516 RRDF_FIELD_OPTS_VISIBLE, NULL);
517 +#endif
518 +#if (PROCESSES_HAVE_UID == 1)
519 buffer_rrdf_table_add_field(wb, field_id++, "Uid", "User ID", RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE,
520 RRDF_FIELD_TRANSFORM_NUMBER, 0, NULL, NAN,
521 RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
@@ -1079,7 +1096,7 @@ void function_processes(const char *transaction, char *function,
1096 }
1097 buffer_json_object_close(wb);
1098
1082 -#if (PROCESSES_HAVE_UID == 1)
1099 +#if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_SID == 1)
1100 // group by User
1101 buffer_json_member_add_object(wb, "User");
1102 {
src/collectors/apps.plugin/apps_os_windows.c
+48 -1
@@ -525,7 +525,7 @@ static char *ansi_to_utf8(LPCSTR str) {
525 static __thread WCHAR unicode[PATH_MAX];
526
527 // Step 1: Convert ANSI string (LPSTR) to wide string (UTF-16)
528 - size_t count = any_to_utf16(CP_ACP, unicode, _countof(unicode), str, -1);
528 + size_t count = any_to_utf16(CP_ACP, unicode, _countof(unicode), str, -1, NULL);
529 if (!count) return NULL;
530
531 return wchar_to_utf8(unicode);
@@ -664,6 +664,45 @@ static WCHAR *executable_path_from_cmdline(WCHAR *cmdline) {
664 return NULL;
665 }
666
667 +static BOOL GetProcessUserSID(HANDLE hProcess, PSID *ppSid) {
668 + HANDLE hToken;
669 + BOOL result = FALSE;
670 + DWORD dwSize = 0;
671 + PTOKEN_USER pTokenUser = NULL;
672 +
673 + if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
674 + return FALSE;
675 +
676 + GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
677 + if (dwSize == 0) {
678 + CloseHandle(hToken);
679 + return FALSE;
680 + }
681 +
682 + pTokenUser = (PTOKEN_USER)LocalAlloc(LPTR, dwSize);
683 + if (pTokenUser == NULL) {
684 + CloseHandle(hToken);
685 + return FALSE;
686 + }
687 +
688 + if (GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize)) {
689 + DWORD sidSize = GetLengthSid(pTokenUser->User.Sid);
690 + *ppSid = (PSID)LocalAlloc(LPTR, sidSize);
691 + if (*ppSid) {
692 + if (CopySid(sidSize, *ppSid, pTokenUser->User.Sid)) {
693 + result = TRUE;
694 + } else {
695 + LocalFree(*ppSid);
696 + *ppSid = NULL;
697 + }
698 + }
699 + }
700 +
701 + LocalFree(pTokenUser);
702 + CloseHandle(hToken);
703 + return result;
704 +}
705 +
706 void GetAllProcessesInfo(void) {
707 static __thread wchar_t unicode[PATH_MAX];
708 static __thread DWORD unicode_size = sizeof(unicode) / sizeof(*unicode);
@@ -723,6 +762,14 @@ void GetAllProcessesInfo(void) {
762 }
763 }
764
765 + if(!p->sid_name) {
766 + PSID pSid = NULL;
767 + if (GetProcessUserSID(hProcess, &pSid))
768 + p->sid_name = cached_sid_fullname_or_sid_str(pSid);
769 + else
770 + p->sid_name = string_strdupz("Unknown");
771 + }
772 +
773 CloseHandle(hProcess);
774
775 char *comm = wchar_to_utf8(pe32.szExeFile);
src/collectors/apps.plugin/apps_pid.c
+4
@@ -134,6 +134,10 @@ void del_pid_entry(pid_t pid) {
134 freez(p->fds);
135 #endif
136
137 +#if (PROCESSES_HAVE_SID == 1)
138 + string_freez(p->sid_name);
139 +#endif
140 +
141 string_freez(p->comm_orig);
142 string_freez(p->comm);
143 string_freez(p->cmdline);
src/collectors/apps.plugin/apps_plugin.c
+30 -11
@@ -74,10 +74,10 @@ uint32_t
74 // the metrics. This results in utilization that exceeds the total utilization
75 // of the system.
76 //
77 -// During normalization, we align the per-process utilization, to the total of
78 -// the system. We first consume the exited children utilization and it the
79 -// collected values is above the total, we proportionally scale each reported
80 -// metric.
77 +// During normalization, we align the per-process utilization to the global
78 +// utilization of the system. We first consume the exited children utilization
79 +// and it the collected values is above the total, we proportionally scale each
80 +// reported metric.
81
82 // the total system time, as reported by /proc/stat
83 #if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
@@ -211,9 +211,10 @@ void print_hierarchy(struct pid_stat *root) {
211 static void normalize_utilization(struct target *root) {
212 struct target *w;
213
214 - // childs processing introduces spikes
215 - // here we try to eliminate them by disabling childs processing either for specific dimensions
216 - // or entirely. Of course, either way, we disable it just a single iteration.
214 + // children processing introduces spikes,
215 + // here we try to eliminate them by disabling children processing either
216 + // for specific dimensions or entirely.
217 + // of course, either way, we disable it just for a single iteration.
218
219 kernel_uint_t max_time = os_get_system_cpus() * NSEC_PER_SEC;
220 kernel_uint_t utime = 0, cutime = 0, stime = 0, cstime = 0, gtime = 0, cgtime = 0, minflt = 0, cminflt = 0, majflt = 0, cmajflt = 0;
@@ -249,7 +250,7 @@ static void normalize_utilization(struct target *root) {
250 cgtime_fix_ratio = 1.0; //(NETDATA_DOUBLE)(global_utime + global_stime) / (NETDATA_DOUBLE)(utime + cutime + stime + cstime);
251 }
252 else if((global_utime + global_stime > utime + stime) && (cutime || cstime)) {
252 - // children resources are too high
253 + // children resources are too high,
254 // lower only the children resources
255 utime_fix_ratio =
256 stime_fix_ratio =
@@ -481,7 +482,7 @@ static void parse_args(int argc, char **argv)
482 }
483 #endif
484
484 -#if (PROCESSES_HAVE_UID == 1)
485 +#if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_SID == 1)
486 if(strcmp("no-users", argv[i]) == 0 || strcmp("without-users", argv[i]) == 0) {
487 enable_users_charts = 0;
488 continue;
@@ -544,7 +545,7 @@ static void parse_args(int argc, char **argv)
545 " (default is enabled)\n"
546 "\n"
547 #endif
547 -#if (PROCESSES_HAVE_UID == 1)
548 +#if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_SID == 1)
549 " without-users disable reporting per user charts\n"
550 "\n"
551 #endif
@@ -734,7 +735,18 @@ int main(int argc, char **argv) {
735
736 netdata_log_info("started on pid %d", getpid());
737
737 - apps_users_and_groups_init();
738 +#if (PROCESSES_HAVE_UID == 1)
739 + cached_usernames_init();
740 +#endif
741 +
742 +#if (PROCESSES_HAVE_GID == 1)
743 + cached_groupnames_init();
744 +#endif
745 +
746 +#if (PROCESSES_HAVE_SID == 1)
747 + cached_sid_username_init();
748 +#endif
749 +
750 apps_pids_init();
751 OS_FUNCTION(apps_os_init)();
752
@@ -823,6 +835,13 @@ int main(int argc, char **argv) {
835 }
836 #endif
837
838 +#if (PROCESSES_HAVE_SID == 1)
839 + if (enable_users_charts) {
840 + send_charts_updates_to_netdata(sids_root_target, "user", "user", "User Processes");
841 + send_collected_data_to_netdata(sids_root_target, "user", dt);
842 + }
843 +#endif
844 +
845 fflush(stdout);
846
847 debug_log("done Loop No %zu", global_iterations_counter);
src/collectors/apps.plugin/apps_plugin.h
+41 -40
@@ -22,6 +22,7 @@
22 #define PROCESSES_HAVE_IO_CALLS 0
23 #define PROCESSES_HAVE_UID 1
24 #define PROCESSES_HAVE_GID 1
25 +#define PROCESSES_HAVE_SID 0
26 #define PROCESSES_HAVE_MAJFLT 1
27 #define PROCESSES_HAVE_CHILDREN_FLTS 1
28 #define PROCESSES_HAVE_VMSWAP 0
@@ -65,6 +66,7 @@ struct pid_info {
66 #define PROCESSES_HAVE_IO_CALLS 0
67 #define PROCESSES_HAVE_UID 1
68 #define PROCESSES_HAVE_GID 1
69 +#define PROCESSES_HAVE_SID 0
70 #define PROCESSES_HAVE_MAJFLT 1
71 #define PROCESSES_HAVE_CHILDREN_FLTS 0
72 #define PROCESSES_HAVE_VMSWAP 0
@@ -96,6 +98,7 @@ struct pid_info {
98 #define PROCESSES_HAVE_IO_CALLS 1
99 #define PROCESSES_HAVE_UID 0
100 #define PROCESSES_HAVE_GID 0
101 +#define PROCESSES_HAVE_SID 1
102 #define PROCESSES_HAVE_MAJFLT 0
103 #define PROCESSES_HAVE_CHILDREN_FLTS 0
104 #define PROCESSES_HAVE_VMSWAP 1
@@ -125,6 +128,7 @@ struct pid_info {
128 #define PROCESSES_HAVE_IO_CALLS 1
129 #define PROCESSES_HAVE_UID 1
130 #define PROCESSES_HAVE_GID 1
131 +#define PROCESSES_HAVE_SID 0
132 #define PROCESSES_HAVE_MAJFLT 1
133 #define PROCESSES_HAVE_CHILDREN_FLTS 1
134 #define PROCESSES_HAVE_VMSWAP 1
@@ -149,6 +153,10 @@ extern int max_fds_cache_seconds;
153 #error "Unsupported operating system"
154 #endif
155
156 +#if (PROCESSES_HAVE_UID == 1) && (PROCESSES_HAVE_SID == 1)
157 +#error "Do not enable SID and UID at the same time"
158 +#endif
159 +
160 // --------------------------------------------------------------------------------------------------------------------
161
162 #define MAX_SYSTEM_FD_TO_ALLOW_FILES_PROCESSING 100000
@@ -205,12 +213,12 @@ extern size_t pagesize;
213
214 extern netdata_mutex_t apps_and_stdout_mutex;
215
208 -// ----------------------------------------------------------------------------
216 +// --------------------------------------------------------------------------------------------------------------------
217 // string lengths
218
219 #define MAX_CMDLINE 65536
220
213 -// ----------------------------------------------------------------------------
221 +// --------------------------------------------------------------------------------------------------------------------
222 // to avoid reallocating too frequently when we add file descriptors,
223 // we double the allocation at every increase request.
224
@@ -218,7 +226,7 @@ static inline uint32_t fds_new_size(uint32_t old_size, uint32_t new_fd) {
226 return MAX(old_size * 2, new_fd + 1); // 1 space always
227 }
228
221 -// ----------------------------------------------------------------------------
229 +// --------------------------------------------------------------------------------------------------------------------
230 // some variables for keeping track of processes count by states
231 #if (PROCESSES_HAVE_STATE == 1)
232 typedef enum {
@@ -234,7 +242,7 @@ extern proc_state proc_state_count[PROC_STATUS_END];
242 extern const char *proc_states[];
243 #endif
244
237 -// ----------------------------------------------------------------------------
245 +// --------------------------------------------------------------------------------------------------------------------
246 // the rates we are going to send to netdata will have this detail a value of:
247 // - 1 will send just integer parts to netdata
248 // - 100 will send 2 decimal points
@@ -257,7 +265,7 @@ struct openfds {
265 #define pid_openfds_sum(p) ((p)->openfds.files + (p)->openfds.pipes + (p)->openfds.sockets + (p)->openfds.inotifies + (p)->openfds.eventfds + (p)->openfds.timerfds + (p)->openfds.signalfds + (p)->openfds.eventpolls + (p)->openfds.other)
266 #endif
267
260 -// ----------------------------------------------------------------------------
268 +// --------------------------------------------------------------------------------------------------------------------
269 // target
270 //
271 // target is the structure that processes are aggregated to be reported
@@ -278,6 +286,9 @@ typedef enum __attribute__((packed)) {
286 #endif
287 #if (PROCESSES_HAVE_GID == 1)
288 TARGET_TYPE_GID,
289 +#endif
290 +#if (PROCESSES_HAVE_SID == 1)
291 + TARGET_TYPE_SID,
292 #endif
293 TARGET_TYPE_TREE,
294 } TARGET_TYPE;
@@ -384,6 +395,9 @@ struct target {
395 #if (PROCESSES_HAVE_GID == 1)
396 gid_t gid;
397 #endif
398 +#if (PROCESSES_HAVE_SID == 1)
399 + STRING *sid_name;
400 +#endif
401
402 kernel_uint_t values[PDF_MAX];
403
@@ -405,7 +419,7 @@ struct target {
419 struct target *next;
420 };
421
408 -// ----------------------------------------------------------------------------
422 +// --------------------------------------------------------------------------------------------------------------------
423 // internal flags
424 // handled in code (automatically set)
425
@@ -421,7 +435,7 @@ typedef enum __attribute__((packed)) {
435 PID_LOG_LIMITS_DETAIL = (1 << 6),
436 } PID_LOG;
437
424 -// ----------------------------------------------------------------------------
438 +// --------------------------------------------------------------------------------------------------------------------
439 // pid_stat
440 //
441 // structure to store data for each process running
@@ -460,8 +474,8 @@ struct pid_fd {
474 #endif
475 };
476
463 -#define pid_stat_comm(p) (string2str(p->comm))
464 -#define pid_stat_cmdline(p) (string2str(p->cmdline))
477 +#define pid_stat_comm(p) (string2str((p)->comm))
478 +#define pid_stat_cmdline(p) (string2str((p)->cmdline))
479 uint32_t all_files_len_get(void);
480
481 struct pid_stat {
@@ -485,10 +499,13 @@ struct pid_stat {
499 #if (PROCESSES_HAVE_GID == 1)
500 struct target *gid_target; // gid based targets
501 #endif
502 +#if (PROCESSES_HAVE_SID == 1)
503 + struct target *sid_target; // sid based targets
504 +#endif
505
506 STRING *comm_orig; // the command, as-collected
507 STRING *comm; // the command, sanitized
491 - STRING *name; // the command name if any, sanitized
508 + STRING *name; // the command name, if any, sanitized
509 STRING *cmdline; // the full command line of the program
510
511 #if defined(OS_WINDOWS)
@@ -505,6 +522,9 @@ struct pid_stat {
522 #if (PROCESSES_HAVE_GID == 1)
523 gid_t gid;
524 #endif
525 +#if (PROCESSES_HAVE_SID == 1)
526 + STRING *sid_name;
527 +#endif
528
529 #if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
530 uint32_t sortlist; // higher numbers = top on the process tree
@@ -521,8 +541,8 @@ struct pid_stat {
541 uint32_t fds_size; // the size of the fds array
542 #endif
543
524 - uint32_t children_count; // number of processes directly referencing this
525 - // it is absorbed by apps_groups.conf inheritance
544 + uint32_t children_count; // the number of processes directly referencing this.
545 + // used internally for apps_groups.conf inheritance.
546 // don't rely on it for anything else.
547
548 uint32_t keeploops; // increases by 1 every time keep is 1 and updated 0
@@ -566,32 +586,11 @@ struct pid_stat {
586 #endif
587 };
588
569 -// ----------------------------------------------------------------------------
570 -
571 -#if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_GID == 1)
572 -struct user_or_group_id {
573 - avl_t avl;
574 -
575 - union {
576 -#if (PROCESSES_HAVE_UID == 1)
577 - uid_t uid;
578 -#endif
579 -#if (PROCESSES_HAVE_GID == 1)
580 - gid_t gid;
581 -#endif
582 - } id;
583 -
584 - char *name;
585 -
586 - int updated;
587 -
588 - struct user_or_group_id * next;
589 -};
590 -#endif
589 +// --------------------------------------------------------------------------------------------------------------------
590
591 extern int update_every;
592
594 -// ----------------------------------------------------------------------------
593 +// --------------------------------------------------------------------------------------------------------------------
594 // debugging
595
596 static inline void debug_log_int(const char *fmt, ... ) {
@@ -618,14 +617,14 @@ static inline void debug_log_dummy(void) {}
617 bool managed_log(struct pid_stat *p, PID_LOG log, bool status);
618 void sanitize_apps_plugin_chart_meta(char *buf);
619
621 -// ----------------------------------------------------------------------------
620 +// --------------------------------------------------------------------------------------------------------------------
621 // macro to calculate the incremental rate of a value
622 // each parameter is accessed only ONCE - so it is safe to pass function calls
623 // or other macros as parameters
624
625 #define incremental_rate(rate_variable, last_kernel_variable, new_kernel_value, collected_usec, last_collected_usec, multiplier) do { \
626 kernel_uint_t _new_tmp = new_kernel_value; \
628 - (rate_variable) = (_new_tmp - (last_kernel_variable)) * (USEC_PER_SEC * multiplier) / ((collected_usec) - (last_collected_usec)); \
627 + (rate_variable) = (_new_tmp - (last_kernel_variable)) * (USEC_PER_SEC * (multiplier)) / ((collected_usec) - (last_collected_usec)); \
628 (last_kernel_variable) = _new_tmp; \
629 } while(0)
630
@@ -637,7 +636,6 @@ void sanitize_apps_plugin_chart_meta(char *buf);
636 incremental_rate(p->values[idx], p->raw[idx], value, p->type##_collected_usec, p->last_##type##_collected_usec, CPU_TO_NANOSECONDCORES)
637
638 void apps_managers_and_aggregators_init(void);
640 -void apps_users_and_groups_init(void);
639 void apps_pids_init(void);
640
641 #if (PROCESSES_HAVE_CMDLINE == 1)
@@ -700,13 +698,16 @@ void aggregate_processes_to_targets(void);
698 #if (PROCESSES_HAVE_UID == 1)
699 extern struct target *users_root_target;
700 struct target *get_uid_target(uid_t uid);
703 -struct user_or_group_id *user_id_find(struct user_or_group_id *user_id_to_find);
701 #endif
702
703 #if (PROCESSES_HAVE_GID == 1)
704 extern struct target *groups_root_target;
705 struct target *get_gid_target(gid_t gid);
709 -struct user_or_group_id *group_id_find(struct user_or_group_id *group_id_to_find);
706 +#endif
707 +
708 +#if (PROCESSES_HAVE_SID == 1)
709 +extern struct target *sids_root_target;
710 +struct target *get_sid_target(STRING *sid_name);
711 #endif
712
713 extern struct target *apps_groups_root_target;
src/collectors/apps.plugin/apps_targets.c
+34 -35
@@ -228,24 +228,10 @@ struct target *get_uid_target(uid_t uid) {
228 w->uid = uid;
229 w->id = get_numeric_string(uid);
230
231 - struct user_or_group_id user_id_to_find = {
232 - .id = {
233 - .uid = uid,
234 - }
235 - };
236 - struct user_or_group_id *user_or_group_id = user_id_find(&user_id_to_find);
237 -
238 - if(user_or_group_id && user_or_group_id->name && *user_or_group_id->name)
239 - w->name = string_strdupz(user_or_group_id->name);
240 - else {
241 - struct passwd *pw = getpwuid(uid);
242 - if(!pw || !pw->pw_name || !*pw->pw_name)
243 - w->name = get_numeric_string(uid);
244 - else
245 - w->name = string_strdupz(pw->pw_name);
246 - }
247 -
231 + CACHED_USERNAME cu = cached_username_get_by_uid(uid);
232 + w->name = string_dup(cu.username);
233 w->clean_name = get_clean_name(w->name);
234 + cached_username_release(cu);
235
236 w->next = users_root_target;
237 users_root_target = w;
@@ -272,24 +258,10 @@ struct target *get_gid_target(gid_t gid) {
258 w->gid = gid;
259 w->id = get_numeric_string(gid);
260
275 - struct user_or_group_id group_id_to_find = {
276 - .id = {
277 - .gid = gid,
278 - }
279 - };
280 - struct user_or_group_id *group_id = group_id_find(&group_id_to_find);
281 -
282 - if(group_id && group_id->name)
283 - w->name = string_strdupz(group_id->name);
284 - else {
285 - struct group *gr = getgrgid(gid);
286 - if(!gr || !gr->gr_name || !*gr->gr_name)
287 - w->name = get_numeric_string(gid);
288 - else
289 - w->name = string_strdupz(gr->gr_name);
290 - }
291 -
261 + CACHED_GROUPNAME cg = cached_groupname_get_by_gid(gid);
262 + w->name = string_dup(cg.groupname);
263 w->clean_name = get_clean_name(w->name);
264 + cached_groupname_release(cg);
265
266 w->next = groups_root_target;
267 groups_root_target = w;
@@ -300,6 +272,33 @@ struct target *get_gid_target(gid_t gid) {
272 }
273 #endif
274
275 +// --------------------------------------------------------------------------------------------------------------------
276 +// SID
277 +
278 +#if (PROCESSES_HAVE_SID == 1)
279 +struct target *sids_root_target = NULL;
280 +
281 +struct target *get_sid_target(STRING *sid_name) {
282 + struct target *w;
283 + for(w = sids_root_target ; w ; w = w->next)
284 + if(w->sid_name == sid_name) return w;
285 +
286 + w = callocz(sizeof(struct target), 1);
287 + w->type = TARGET_TYPE_SID;
288 + w->sid_name = string_dup(sid_name);
289 + w->id = string_dup(sid_name);
290 + w->name = string_dup(sid_name);
291 + w->clean_name = get_clean_name(w->name);
292 +
293 + w->next = sids_root_target;
294 + sids_root_target = w;
295 +
296 + debug_log("added uid %s ('%s') target", string2str(w->sid_name), string2str(w->name));
297 +
298 + return w;
299 +}
300 +#endif
301 +
302 // --------------------------------------------------------------------------------------------------------------------
303 // apps_groups.conf
304
@@ -425,7 +424,7 @@ int read_apps_groups_conf(const char *path, const char *file) {
424 managed_list_add(&tree.interpreters, s);
425 }
426
428 - // done with managers, proceed to next line
427 + // done with managers, proceed to the next line
428 continue;
429 }
430
src/collectors/apps.plugin/apps_users_and_groups.c deleted
-224
@@ -1,224 +0,0 @@
1 -// SPDX-License-Identifier: GPL-3.0-or-later
2 -
3 -#include "apps_plugin.h"
4 -
5 -#if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_GID == 1)
6 -
7 -// ----------------------------------------------------------------------------
8 -// read users and groups from files
9 -
10 -enum user_or_group_id_type {
11 - USER_ID,
12 - GROUP_ID
13 -};
14 -
15 -struct user_or_group_ids {
16 - enum user_or_group_id_type type;
17 -
18 - avl_tree_type index;
19 - struct user_or_group_id *root;
20 -
21 - char filename[FILENAME_MAX + 1];
22 -};
23 -
24 -#if (PROCESSES_HAVE_UID == 1)
25 -static int user_id_compare(void* a, void* b) {
26 - if(((struct user_or_group_id *)a)->id.uid < ((struct user_or_group_id *)b)->id.uid)
27 - return -1;
28 -
29 - else if(((struct user_or_group_id *)a)->id.uid > ((struct user_or_group_id *)b)->id.uid)
30 - return 1;
31 -
32 - else
33 - return 0;
34 -}
35 -
36 -static struct user_or_group_ids all_user_ids = {
37 - .type = USER_ID,
38 -
39 - .index = {
40 - NULL,
41 - user_id_compare
42 - },
43 -
44 - .root = NULL,
45 -
46 - .filename = "",
47 -};
48 -#endif
49 -
50 -#if (PROCESSES_HAVE_GID == 1)
51 -static int group_id_compare(void* a, void* b) {
52 - if(((struct user_or_group_id *)a)->id.gid < ((struct user_or_group_id *)b)->id.gid)
53 - return -1;
54 -
55 - else if(((struct user_or_group_id *)a)->id.gid > ((struct user_or_group_id *)b)->id.gid)
56 - return 1;
57 -
58 - else
59 - return 0;
60 -}
61 -
62 -static struct user_or_group_ids all_group_ids = {
63 - .type = GROUP_ID,
64 -
65 - .index = {
66 - NULL,
67 - group_id_compare
68 - },
69 -
70 - .root = NULL,
71 -
72 - .filename = "",
73 -};
74 -#endif
75 -
76 -static int file_changed(const struct stat *statbuf __maybe_unused, struct timespec *last_modification_time __maybe_unused) {
77 -#if defined(OS_MACOS) || defined(OS_WINDOWS)
78 - return 0;
79 -#else
80 - if(likely(statbuf->st_mtim.tv_sec == last_modification_time->tv_sec &&
81 - statbuf->st_mtim.tv_nsec == last_modification_time->tv_nsec)) return 0;
82 -
83 - last_modification_time->tv_sec = statbuf->st_mtim.tv_sec;
84 - last_modification_time->tv_nsec = statbuf->st_mtim.tv_nsec;
85 -
86 - return 1;
87 -#endif
88 -}
89 -
90 -static int read_user_or_group_ids(struct user_or_group_ids *ids, struct timespec *last_modification_time) {
91 - struct stat statbuf;
92 - if(unlikely(stat(ids->filename, &statbuf)))
93 - return 1;
94 - else
95 - if(likely(!file_changed(&statbuf, last_modification_time))) return 0;
96 -
97 - procfile *ff = procfile_open(ids->filename, " :\t", PROCFILE_FLAG_DEFAULT);
98 - if(unlikely(!ff)) return 1;
99 -
100 - ff = procfile_readall(ff);
101 - if(unlikely(!ff)) return 1;
102 -
103 - size_t line, lines = procfile_lines(ff);
104 -
105 - for(line = 0; line < lines ;line++) {
106 - size_t words = procfile_linewords(ff, line);
107 - if(unlikely(words < 3)) continue;
108 -
109 - char *name = procfile_lineword(ff, line, 0);
110 - if(unlikely(!name || !*name)) continue;
111 -
112 - char *id_string = procfile_lineword(ff, line, 2);
113 - if(unlikely(!id_string || !*id_string)) continue;
114 -
115 -
116 - struct user_or_group_id *user_or_group_id = callocz(1, sizeof(struct user_or_group_id));
117 -
118 -#if (PROCESSES_HAVE_UID == 1)
119 - if(ids->type == USER_ID)
120 - user_or_group_id->id.uid = (uid_t) str2ull(id_string, NULL);
121 -#endif
122 -#if (PROCESSES_HAVE_GID == 1)
123 - if(ids->type == GROUP_ID)
124 - user_or_group_id->id.gid = (uid_t) str2ull(id_string, NULL);
125 -#endif
126 -
127 - user_or_group_id->name = strdupz(name);
128 - user_or_group_id->updated = 1;
129 -
130 - struct user_or_group_id *existing_user_id = NULL;
131 -
132 - if(likely(ids->root))
133 - existing_user_id = (struct user_or_group_id *)avl_search(&ids->index, (avl_t *) user_or_group_id);
134 -
135 - if(unlikely(existing_user_id)) {
136 - freez(existing_user_id->name);
137 - existing_user_id->name = user_or_group_id->name;
138 - existing_user_id->updated = 1;
139 - freez(user_or_group_id);
140 - }
141 - else {
142 - if(unlikely(avl_insert(&ids->index, (avl_t *) user_or_group_id) != (void *) user_or_group_id)) {
143 - netdata_log_error("INTERNAL ERROR: duplicate indexing of id during realloc");
144 - }
145 -
146 - user_or_group_id->next = ids->root;
147 - ids->root = user_or_group_id;
148 - }
149 - }
150 -
151 - procfile_close(ff);
152 -
153 - // remove unused ids
154 - struct user_or_group_id *user_or_group_id = ids->root, *prev_user_id = NULL;
155 -
156 - while(user_or_group_id) {
157 - if(unlikely(!user_or_group_id->updated)) {
158 - if(unlikely((struct user_or_group_id *)avl_remove(&ids->index, (avl_t *) user_or_group_id) != user_or_group_id))
159 - netdata_log_error("INTERNAL ERROR: removal of unused id from index, removed a different id");
160 -
161 - if(prev_user_id)
162 - prev_user_id->next = user_or_group_id->next;
163 - else
164 - ids->root = user_or_group_id->next;
165 -
166 - freez(user_or_group_id->name);
167 - freez(user_or_group_id);
168 -
169 - if(prev_user_id)
170 - user_or_group_id = prev_user_id->next;
171 - else
172 - user_or_group_id = ids->root;
173 - }
174 - else {
175 - user_or_group_id->updated = 0;
176 -
177 - prev_user_id = user_or_group_id;
178 - user_or_group_id = user_or_group_id->next;
179 - }
180 - }
181 -
182 - return 0;
183 -}
184 -
185 -#if (PROCESSES_HAVE_UID == 1)
186 -struct user_or_group_id *user_id_find(struct user_or_group_id *user_id_to_find) {
187 - if(*netdata_configured_host_prefix) {
188 - static struct timespec last_passwd_modification_time;
189 - int ret = read_user_or_group_ids(&all_user_ids, &last_passwd_modification_time);
190 -
191 - if(likely(!ret && all_user_ids.index.root))
192 - return (struct user_or_group_id *)avl_search(&all_user_ids.index, (avl_t *)user_id_to_find);
193 - }
194 -
195 - return NULL;
196 -}
197 -#endif
198 -
199 -#if (PROCESSES_HAVE_GID == 1)
200 -struct user_or_group_id *group_id_find(struct user_or_group_id *group_id_to_find) {
201 - if(*netdata_configured_host_prefix) {
202 - static struct timespec last_group_modification_time;
203 - int ret = read_user_or_group_ids(&all_group_ids, &last_group_modification_time);
204 -
205 - if(likely(!ret && all_group_ids.index.root))
206 - return (struct user_or_group_id *)avl_search(&all_group_ids.index, (avl_t *) &group_id_to_find);
207 - }
208 -
209 - return NULL;
210 -}
211 -#endif
212 -#endif
213 -
214 -void apps_users_and_groups_init(void) {
215 -#if (PROCESSES_HAVE_UID == 1)
216 - snprintfz(all_user_ids.filename, FILENAME_MAX, "%s/etc/passwd", netdata_configured_host_prefix);
217 - debug_log("passwd file: '%s'", all_user_ids.filename);
218 -#endif
219 -
220 -#if (PROCESSES_HAVE_GID == 1)
221 - snprintfz(all_group_ids.filename, FILENAME_MAX, "%s/etc/group", netdata_configured_host_prefix);
222 - debug_log("group file: '%s'", all_group_ids.filename);
223 -#endif
224 -}
src/collectors/network-viewer.plugin/network-viewer.c
+7 -8
@@ -23,9 +23,8 @@ static SPAWN_SERVER *spawn_srv = NULL;
23 } aggregated_key; \
24 } network_viewer;
25
26 -#include "libnetdata/maps/local-sockets.h"
27 -#include "libnetdata/maps/system-users.h"
28 -#include "libnetdata/maps/system-services.h"
26 +#include "libnetdata/local-sockets/local-sockets.h"
27 +#include "libnetdata/os/system-maps/system-services.h"
28
29 #define NETWORK_CONNECTIONS_VIEWER_FUNCTION "network-connections"
30 #define NETWORK_CONNECTIONS_VIEWER_HELP "Network connections explorer"
@@ -36,7 +35,6 @@ static SPAWN_SERVER *spawn_srv = NULL;
35
36 netdata_mutex_t stdout_mutex = NETDATA_MUTEX_INITIALIZER;
37 static bool plugin_should_exit = false;
39 -static USERNAMES_CACHE *uc;
38 static SERVICENAMES_CACHE *sc;
39
40 ENUM_STR_MAP_DEFINE(SOCKET_DIRECTION) = {
@@ -151,9 +149,9 @@ static void local_socket_to_json_array(struct sockets_stats *st, const LOCAL_SOC
149 }
150 else {
151 // buffer_json_add_array_item_uint64(wb, n->uid);
154 - STRING *u = system_usernames_cache_lookup_uid(uc, n->uid);
155 - buffer_json_add_array_item_string(wb, string2str(u));
156 - string_freez(u);
152 + CACHED_USERNAME cu = cached_username_get_by_uid(n->uid);
153 + buffer_json_add_array_item_string(wb, string2str(cu.username));
154 + cached_username_release(cu);
155 }
156
157 const struct socket_endpoint *server_endpoint;
@@ -975,7 +973,8 @@ int main(int argc __maybe_unused, char **argv __maybe_unused) {
973 }
974 #endif
975
978 - uc = system_usernames_cache_init();
976 + cached_usernames_init();
977 + update_cached_host_users();
978 sc = system_servicenames_cache_init();
979
980 // ----------------------------------------------------------------------------------------------------------------
src/collectors/systemd-journal.plugin/systemd-journal-annotations.c
+10 -20
@@ -2,18 +2,6 @@
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 -
5 // ----------------------------------------------------------------------------
6
7 const char *errno_map[] = {
@@ -369,9 +357,9 @@ void netdata_systemd_journal_transform_uid(FACETS *facets __maybe_unused, BUFFER
357 const char *v = buffer_tostring(wb);
358 if(*v && isdigit(*v)) {
359 uid_t uid = str2i(buffer_tostring(wb));
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);
360 + CACHED_USERNAME cu = cached_username_get_by_uid(uid);
361 + buffer_contents_replace(wb, string2str(cu.username), string_strlen(cu.username));
362 + cached_username_release(cu);
363 }
364 }
365
@@ -382,9 +370,9 @@ void netdata_systemd_journal_transform_gid(FACETS *facets __maybe_unused, BUFFER
370 const char *v = buffer_tostring(wb);
371 if(*v && isdigit(*v)) {
372 gid_t gid = str2i(buffer_tostring(wb));
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);
373 + CACHED_GROUPNAME cg = cached_groupname_get_by_gid(gid);
374 + buffer_contents_replace(wb, string2str(cg.groupname), string_strlen(cg.groupname));
375 + cached_groupname_release(cg);
376 }
377 }
378
@@ -650,8 +638,10 @@ void netdata_systemd_journal_transform_message_id(FACETS *facets __maybe_unused,
638 // ----------------------------------------------------------------------------
639
640 void netdata_systemd_journal_annotations_init(void) {
653 - systemd_annotations_globals.uc = system_usernames_cache_init();
654 - systemd_annotations_globals.gc = system_groupnames_cache_init();
641 + cached_usernames_init();
642 + cached_groupnames_init();
643 + update_cached_host_users();
644 + update_cached_host_groups();
645 netdata_systemd_journal_message_ids_init();
646 }
647
src/collectors/utils/local_listeners.c
+1 -1
@@ -1,7 +1,7 @@
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "libnetdata/libnetdata.h"
4 -#include "libnetdata/maps/local-sockets.h"
4 +#include "libnetdata/local-sockets/local-sockets.h"
5 #include "libnetdata/required_dummies.h"
6
7 // --------------------------------------------------------------------------------------------------------------------
src/collectors/windows-events.plugin/windows-events-providers.c
+8 -6
@@ -78,7 +78,8 @@ static struct {
78 .spinlock = NETDATA_SPINLOCK_INITIALIZER,
79 };
80
81 -static void provider_load_list(PROVIDER_META_HANDLE *h, WEVT_VARIANT *content, WEVT_VARIANT *property, TXT_UNICODE *dst, struct provider_list *l, EVT_PUBLISHER_METADATA_PROPERTY_ID property_id);
81 +static void provider_load_list(PROVIDER_META_HANDLE *h, WEVT_VARIANT *content, WEVT_VARIANT *property,
82 + TXT_UTF16 *dst, struct provider_list *l, EVT_PUBLISHER_METADATA_PROPERTY_ID property_id);
83
84 const char *provider_get_name(PROVIDER_META_HANDLE *p) {
85 return (p && p->provider && p->provider->name) ? p->provider->name : "__UNKNOWN PROVIDER__";
@@ -226,7 +227,7 @@ PROVIDER_META_HANDLE *provider_get(ND_UUID uuid, LPCWSTR providerName) {
227 if(load_it) {
228 WEVT_VARIANT content = { 0 };
229 WEVT_VARIANT property = { 0 };
229 - TXT_UNICODE unicode = { 0 };
230 + TXT_UTF16 unicode = { 0 };
231
232 provider_detect_platform(h, &content);
233 provider_load_list(h, &content, &property, &unicode, &p->keyword, EvtPublisherMetadataKeywords);
@@ -234,7 +235,7 @@ PROVIDER_META_HANDLE *provider_get(ND_UUID uuid, LPCWSTR providerName) {
235 provider_load_list(h, &content, &property, &unicode, &p->opcodes, EvtPublisherMetadataOpcodes);
236 provider_load_list(h, &content, &property, &unicode, &p->tasks, EvtPublisherMetadataTasks);
237
237 - txt_unicode_cleanup(&unicode);
238 + txt_utf16_cleanup(&unicode);
239 wevt_variant_cleanup(&content);
240 wevt_variant_cleanup(&property);
241 }
@@ -365,7 +366,8 @@ static int compare_ascending(const void *a, const void *b) {
366 // return 0;
367 //}
368
368 -static void provider_load_list(PROVIDER_META_HANDLE *h, WEVT_VARIANT *content, WEVT_VARIANT *property, TXT_UNICODE *dst, struct provider_list *l, EVT_PUBLISHER_METADATA_PROPERTY_ID property_id) {
369 +static void provider_load_list(PROVIDER_META_HANDLE *h, WEVT_VARIANT *content, WEVT_VARIANT *property,
370 + TXT_UTF16 *dst, struct provider_list *l, EVT_PUBLISHER_METADATA_PROPERTY_ID property_id) {
371 if(!h || !h->hMetadata) return;
372
373 EVT_PUBLISHER_METADATA_PROPERTY_ID name_id, message_id, value_id;
@@ -477,7 +479,7 @@ static void provider_load_list(PROVIDER_META_HANDLE *h, WEVT_VARIANT *content, W
479 if (messageID != (uint32_t)-1) {
480 if (EvtFormatMessage_utf16(dst, hMetadata, NULL, messageID, EvtFormatMessageId)) {
481 size_t len;
480 - d->name = unicode2utf8_strdupz(dst->data, &len);
482 + d->name = utf16_to_utf8_strdupz(dst->data, &len);
483 d->len = len;
484 }
485 }
@@ -487,7 +489,7 @@ static void provider_load_list(PROVIDER_META_HANDLE *h, WEVT_VARIANT *content, W
489 if (!d->name && wevt_get_property_from_array(property, hArray, i, name_id)) {
490 fatal_assert(property->data->Type == EvtVarTypeString);
491 size_t len;
490 - d->name = unicode2utf8_strdupz(property->data->StringVal, &len);
492 + d->name = utf16_to_utf8_strdupz(property->data->StringVal, &len);
493 d->len = len;
494 }
495
src/collectors/windows-events.plugin/windows-events-query-evt-variant.c
+7 -6
@@ -21,13 +21,14 @@ static inline void append_utf16(BUFFER *b, LPCWSTR utf16Str, const char *separat
21 remaining = b->size - b->len;
22 }
23
24 - size_t used = utf16_to_utf8(&b->buffer[b->len], remaining, utf16Str, -1);
25 - if(used >= remaining) {
26 - // oops, we need to resize
27 - size_t needed = utf16_to_utf8(NULL, 0, utf16Str, -1); // find the size needed
24 + bool truncated = false;
25 + size_t used = utf16_to_utf8(&b->buffer[b->len], remaining, utf16Str, -1, &truncated);
26 + if(truncated) {
27 + // we need to resize
28 + size_t needed = utf16_to_utf8(NULL, 0, utf16Str, -1, NULL); // find the size needed
29 buffer_need_bytes(b, needed);
30 remaining = b->size - b->len;
30 - used = utf16_to_utf8(&b->buffer[b->len], remaining, utf16Str, -1);
31 + used = utf16_to_utf8(&b->buffer[b->len], remaining, utf16Str, -1, NULL);
32 }
33
34 if(used) {
@@ -113,7 +114,7 @@ static inline void append_filetime(BUFFER *b, FILETIME *ft, const char *separato
114 }
115
116 static inline void append_sid(BUFFER *b, PSID sid, const char *separator) {
116 - buffer_sid_to_sid_str_and_name(sid, b, separator);
117 + cached_sid_to_buffer_append(sid, b, separator);
118 }
119
120 static inline void append_sbyte(BUFFER *b, INT8 n, const char *separator) {
src/collectors/windows-events.plugin/windows-events-query.c
+14 -13
@@ -29,7 +29,8 @@ static const char *EvtGetExtendedStatus_utf8(void) {
29
30 // --------------------------------------------------------------------------------------------------------------------
31
32 -bool EvtFormatMessage_utf16(TXT_UNICODE *dst, EVT_HANDLE hMetadata, EVT_HANDLE hEvent, DWORD dwMessageId, EVT_FORMAT_MESSAGE_FLAGS flags) {
32 +bool EvtFormatMessage_utf16(
33 + TXT_UTF16 *dst, EVT_HANDLE hMetadata, EVT_HANDLE hEvent, DWORD dwMessageId, EVT_FORMAT_MESSAGE_FLAGS flags) {
34 dst->used = 0;
35
36 DWORD size = 0;
@@ -39,7 +40,7 @@ bool EvtFormatMessage_utf16(TXT_UNICODE *dst, EVT_HANDLE hMetadata, EVT_HANDLE h
40 // nd_log(NDLS_COLLECTORS, NDLP_ERR, "EvtFormatMessage() to get message size failed.");
41 goto cleanup;
42 }
42 - txt_unicode_resize(dst, size, false);
43 + txt_utf16_resize(dst, size, false);
44 }
45
46 // First, try to get the message using the existing buffer
@@ -50,7 +51,7 @@ bool EvtFormatMessage_utf16(TXT_UNICODE *dst, EVT_HANDLE hMetadata, EVT_HANDLE h
51 }
52
53 // Try again with the resized buffer
53 - txt_unicode_resize(dst, size, false);
54 + txt_utf16_resize(dst, size, false);
55 if (!EvtFormatMessage(hMetadata, hEvent, dwMessageId, 0, NULL, flags, dst->size, dst->data, &size)) {
56 // nd_log(NDLS_COLLECTORS, NDLP_ERR, "EvtFormatMessage() failed after resizing buffer.");
57 goto cleanup;
@@ -75,23 +76,23 @@ cleanup:
76 }
77
78 static bool EvtFormatMessage_utf8(
78 - TXT_UNICODE *tmp, PROVIDER_META_HANDLE *p, EVT_HANDLE hEvent,
79 + TXT_UTF16 *tmp, PROVIDER_META_HANDLE *p, EVT_HANDLE hEvent,
80 TXT_UTF8 *dst, EVT_FORMAT_MESSAGE_FLAGS flags) {
81
82 dst->src = TXT_SOURCE_EVENT_LOG;
83
84 if(EvtFormatMessage_utf16(tmp, provider_handle(p), hEvent, 0, flags))
84 - return wevt_str_unicode_to_utf8(dst, tmp);
85 + return txt_utf16_to_utf8(dst, tmp);
86
86 - wevt_utf8_empty(dst);
87 + txt_utf8_empty(dst);
88 return false;
89 }
90
90 -bool EvtFormatMessage_Event_utf8(TXT_UNICODE *tmp, PROVIDER_META_HANDLE *p, EVT_HANDLE hEvent, TXT_UTF8 *dst) {
91 +bool EvtFormatMessage_Event_utf8(TXT_UTF16 *tmp, PROVIDER_META_HANDLE *p, EVT_HANDLE hEvent, TXT_UTF8 *dst) {
92 return EvtFormatMessage_utf8(tmp, p, hEvent, dst, EvtFormatMessageEvent);
93 }
94
94 -bool EvtFormatMessage_Xml_utf8(TXT_UNICODE *tmp, PROVIDER_META_HANDLE *p, EVT_HANDLE hEvent, TXT_UTF8 *dst) {
95 +bool EvtFormatMessage_Xml_utf8(TXT_UTF16 *tmp, PROVIDER_META_HANDLE *p, EVT_HANDLE hEvent, TXT_UTF8 *dst) {
96 return EvtFormatMessage_utf8(tmp, p, hEvent, dst, EvtFormatMessageXml);
97 }
98
@@ -130,7 +131,7 @@ static void wevt_get_level(WEVT_LOG *log, WEVT_EVENT *ev, PROVIDER_META_HANDLE *
131 TXT_UTF8 *dst = &log->ops.level;
132 uint64_t value = ev->level;
133
133 - wevt_utf8_empty(dst);
134 + txt_utf8_empty(dst);
135
136 EVT_FORMAT_MESSAGE_FLAGS flags = EvtFormatMessageLevel;
137 WEVT_FIELD_TYPE cache_type = WEVT_FIELD_TYPE_LEVEL;
@@ -182,7 +183,7 @@ static void wevt_get_opcode(WEVT_LOG *log, WEVT_EVENT *ev, PROVIDER_META_HANDLE
183 TXT_UTF8 *dst = &log->ops.opcode;
184 uint64_t value = ev->opcode;
185
185 - wevt_utf8_empty(dst);
186 + txt_utf8_empty(dst);
187
188 EVT_FORMAT_MESSAGE_FLAGS flags = EvtFormatMessageOpcode;
189 WEVT_FIELD_TYPE cache_type = WEVT_FIELD_TYPE_OPCODE;
@@ -224,7 +225,7 @@ static void wevt_get_task(WEVT_LOG *log, WEVT_EVENT *ev, PROVIDER_META_HANDLE *h
225 TXT_UTF8 *dst = &log->ops.task;
226 uint64_t value = ev->task;
227
227 - wevt_utf8_empty(dst);
228 + txt_utf8_empty(dst);
229
230 EVT_FORMAT_MESSAGE_FLAGS flags = EvtFormatMessageTask;
231 WEVT_FIELD_TYPE cache_type = WEVT_FIELD_TYPE_TASK;
@@ -273,7 +274,7 @@ static uint64_t wevt_keyword_handle_reserved(uint64_t value, TXT_UTF8 *dst) {
274 SET_BITS(WEVT_KEYWORD_RESPONSE_TIME, WEVT_KEYWORD_NAME_RESPONSE_TIME),
275 };
276
276 - wevt_utf8_empty(dst);
277 + txt_utf8_empty(dst);
278
279 for(size_t i = 0; i < sizeof(bits) / sizeof(bits[0]) ;i++) {
280 if((value & bits[i].mask) == bits[i].mask) {
@@ -592,7 +593,7 @@ void wevt_closelog6(WEVT_LOG *log) {
593
594 wevt_variant_cleanup(&log->ops.raw.system);
595 wevt_variant_cleanup(&log->ops.raw.user);
595 - txt_unicode_cleanup(&log->ops.unicode);
596 + txt_utf16_cleanup(&log->ops.unicode);
597 txt_utf8_cleanup(&log->ops.channel);
598 txt_utf8_cleanup(&log->ops.provider);
599 txt_utf8_cleanup(&log->ops.computer);
src/collectors/windows-events.plugin/windows-events-query.h
+13 -12
@@ -83,7 +83,7 @@ typedef struct wevt_log {
83 // every string operation overwrites it, multiple times per event log entry
84 // it can be used within any function, for its own purposes,
85 // but never share between functions
86 - TXT_UNICODE unicode;
86 + TXT_UTF16 unicode;
87
88 // string attributes of the current event log entry
89 // valid until another event if fetched
@@ -136,10 +136,11 @@ void wevt_query_done(WEVT_LOG *log);
136
137 bool wevt_get_next_event(WEVT_LOG *log, WEVT_EVENT *ev);
138
139 -bool EvtFormatMessage_utf16(TXT_UNICODE *dst, EVT_HANDLE hMetadata, EVT_HANDLE hEvent, DWORD dwMessageId, EVT_FORMAT_MESSAGE_FLAGS flags);
139 +bool EvtFormatMessage_utf16(
140 + TXT_UTF16 *dst, EVT_HANDLE hMetadata, EVT_HANDLE hEvent, DWORD dwMessageId, EVT_FORMAT_MESSAGE_FLAGS flags);
141
141 -bool EvtFormatMessage_Event_utf8(TXT_UNICODE *tmp, struct provider_meta_handle *p, EVT_HANDLE hEvent, TXT_UTF8 *dst);
142 -bool EvtFormatMessage_Xml_utf8(TXT_UNICODE *tmp, struct provider_meta_handle *p, EVT_HANDLE hEvent, TXT_UTF8 *dst);
142 +bool EvtFormatMessage_Event_utf8(TXT_UTF16 *tmp, struct provider_meta_handle *p, EVT_HANDLE hEvent, TXT_UTF8 *dst);
143 +bool EvtFormatMessage_Xml_utf8(TXT_UTF16 *tmp, struct provider_meta_handle *p, EVT_HANDLE hEvent, TXT_UTF8 *dst);
144
145 void evt_variant_to_buffer(BUFFER *b, EVT_VARIANT *ev, const char *separator);
146
@@ -152,7 +153,7 @@ static inline void wevt_variant_resize(WEVT_VARIANT *v, size_t required_size) {
153 return;
154
155 wevt_variant_cleanup(v);
155 - v->size = compute_new_size(v->size, required_size);
156 + v->size = txt_compute_new_size(v->size, required_size);
157 v->data = mallocz(v->size);
158 }
159
@@ -202,25 +203,25 @@ static inline uint64_t wevt_field_get_uint64_hex(EVT_VARIANT *ev) {
203
204 static inline bool wevt_field_get_string_utf8(EVT_VARIANT *ev, TXT_UTF8 *dst) {
205 if((ev->Type & EVT_VARIANT_TYPE_MASK) == EvtVarTypeNull) {
205 - wevt_utf8_empty(dst);
206 + txt_utf8_empty(dst);
207 return false;
208 }
209
210 fatal_assert((ev->Type & EVT_VARIANT_TYPE_MASK) == EvtVarTypeString);
210 - return wevt_str_wchar_to_utf8(dst, ev->StringVal, -1);
211 + return wchar_to_txt_utf8(dst, ev->StringVal, -1);
212 }
213
213 -bool wevt_convert_user_id_to_name(PSID sid, TXT_UTF8 *dst_account, TXT_UTF8 *dst_domain, TXT_UTF8 *dst_sid_str);
214 +bool cached_sid_to_account_domain_sidstr(PSID sid, TXT_UTF8 *dst_account, TXT_UTF8 *dst_domain, TXT_UTF8 *dst_sid_str);
215 static inline bool wevt_field_get_sid(EVT_VARIANT *ev, TXT_UTF8 *dst_account, TXT_UTF8 *dst_domain, TXT_UTF8 *dst_sid_str) {
216 if((ev->Type & EVT_VARIANT_TYPE_MASK) == EvtVarTypeNull) {
216 - wevt_utf8_empty(dst_account);
217 - wevt_utf8_empty(dst_domain);
218 - wevt_utf8_empty(dst_sid_str);
217 + txt_utf8_empty(dst_account);
218 + txt_utf8_empty(dst_domain);
219 + txt_utf8_empty(dst_sid_str);
220 return false;
221 }
222
223 fatal_assert((ev->Type & EVT_VARIANT_TYPE_MASK) == EvtVarTypeSid);
223 - return wevt_convert_user_id_to_name(ev->SidVal, dst_account, dst_domain, dst_sid_str);
224 + return cached_sid_to_account_domain_sidstr(ev->SidVal, dst_account, dst_domain, dst_sid_str);
225 }
226
227 static inline uint64_t wevt_field_get_filetime_to_ns(EVT_VARIANT *ev) {
src/collectors/windows-events.plugin/windows-events-sid.h deleted
-13
@@ -1,13 +0,0 @@
1 -// SPDX-License-Identifier: GPL-3.0-or-later
2 -
3 -#ifndef NETDATA_WINDOWS_EVENTS_SID_H
4 -#define NETDATA_WINDOWS_EVENTS_SID_H
5 -
6 -#include "windows-events.h"
7 -
8 -struct wevt_log;
9 -bool wevt_convert_user_id_to_name(PSID sid, TXT_UTF8 *dst_account, TXT_UTF8 *dst_domain, TXT_UTF8 *dst_sid_str);
10 -bool buffer_sid_to_sid_str_and_name(PSID sid, BUFFER *dst, const char *prefix);
11 -void sid_cache_init(void);
12 -
13 -#endif //NETDATA_WINDOWS_EVENTS_SID_H
src/collectors/windows-events.plugin/windows-events-unicode.c
-98
@@ -21,24 +21,6 @@ inline void unicode2utf8(char *dst, size_t dst_size, const wchar_t *src) {
21 strncpyz(dst, "[null]", dst_size - 1);
22 }
23
24 -char *unicode2utf8_strdupz(const wchar_t *src, size_t *utf8_len) {
25 - int size = WideCharToMultiByte(CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL);
26 - if (size > 0) {
27 - char *dst = mallocz(size);
28 - WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, size, NULL, NULL);
29 -
30 - if(utf8_len)
31 - *utf8_len = size - 1;
32 -
33 - return dst;
34 - }
35 -
36 - if(utf8_len)
37 - *utf8_len = 0;
38 -
39 - return NULL;
40 -}
41 -
24 wchar_t *channel2unicode(const char *utf8str) {
25 static __thread wchar_t buffer[1024];
26 utf82unicode(buffer, _countof(buffer), utf8str);
@@ -51,18 +33,6 @@ char *channel2utf8(const wchar_t *channel) {
33 return buffer;
34 }
35
54 -char *account2utf8(const wchar_t *user) {
55 - static __thread char buffer[1024];
56 - unicode2utf8(buffer, sizeof(buffer), user);
57 - return buffer;
58 -}
59 -
60 -char *domain2utf8(const wchar_t *domain) {
61 - static __thread char buffer[1024];
62 - unicode2utf8(buffer, sizeof(buffer), domain);
63 - return buffer;
64 -}
65 -
36 char *query2utf8(const wchar_t *query) {
37 static __thread char buffer[16384];
38 unicode2utf8(buffer, sizeof(buffer), query);
@@ -74,71 +44,3 @@ char *provider2utf8(const wchar_t *provider) {
44 unicode2utf8(buffer, sizeof(buffer), provider);
45 return buffer;
46 }
77 -
78 -bool wevt_str_wchar_to_utf8(TXT_UTF8 *dst, const wchar_t *src, int src_len_with_null) {
79 - if(!src || !src_len_with_null)
80 - goto cleanup;
81 -
82 - // make sure the input is null terminated at the exact point we need it
83 - // (otherwise, the output will not be null terminated either)
84 - fatal_assert(src_len_with_null == -1 || (src_len_with_null >= 1 && src[src_len_with_null - 1] == 0));
85 -
86 - // Try to convert using the existing buffer (if it exists, otherwise get the required buffer size)
87 - int size = WideCharToMultiByte(CP_UTF8, 0, src, src_len_with_null, dst->data, (int)dst->size, NULL, NULL);
88 - if(size <= 0 || !dst->data) {
89 - // we have to set a buffer, or increase it
90 -
91 - if(dst->data) {
92 - // we need to increase it the buffer size
93 -
94 - if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
95 - nd_log(NDLS_COLLECTORS, NDLP_ERR, "WideCharToMultiByte() failed.");
96 - goto cleanup;
97 - }
98 -
99 - // we have to find the required buffer size
100 - size = WideCharToMultiByte(CP_UTF8, 0, src, src_len_with_null, NULL, 0, NULL, NULL);
101 - if(size <= 0)
102 - goto cleanup;
103 - }
104 -
105 - // Retry conversion with the new buffer
106 - txt_utf8_resize(dst, size, false);
107 - size = WideCharToMultiByte(CP_UTF8, 0, src, src_len_with_null, dst->data, (int)dst->size, NULL, NULL);
108 - if (size <= 0) {
109 - nd_log(NDLS_COLLECTORS, NDLP_ERR, "WideCharToMultiByte() failed after resizing.");
110 - goto cleanup;
111 - }
112 - }
113 -
114 - // Make sure it is not zero padded at the end
115 - while(size >= 2 && dst->data[size - 2] == 0)
116 - size--;
117 -
118 - dst->used = (size_t)size;
119 -
120 - internal_fatal(strlen(dst->data) + 1 != dst->used,
121 - "Wrong UTF8 string length");
122 -
123 - return true;
124 -
125 -cleanup:
126 - txt_utf8_resize(dst, 128, false);
127 - if(src)
128 - dst->used = snprintfz(dst->data, dst->size, "[failed conv.]") + 1;
129 - else {
130 - dst->data[0] = '\0';
131 - dst->used = 1;
132 - }
133 -
134 - return false;
135 -}
136 -
137 -bool wevt_str_unicode_to_utf8(TXT_UTF8 *dst, TXT_UNICODE *unicode) {
138 - fatal_assert(dst && ((dst->data && dst->size) || (!dst->data && !dst->size)));
139 - fatal_assert(unicode && ((unicode->data && unicode->size) || (!unicode->data && !unicode->size)));
140 -
141 - // pass the entire unicode size, including the null terminator
142 - // so that the resulting utf8 message will be null terminated too.
143 - return wevt_str_wchar_to_utf8(dst, unicode->data, (int)unicode->used);
144 -}
src/collectors/windows-events.plugin/windows-events-unicode.h
-140
@@ -7,87 +7,6 @@
7 #include <windows.h>
8 #include <wchar.h>
9
10 -typedef enum __attribute__((packed)) {
11 - TXT_SOURCE_UNKNOWN = 0,
12 - TXT_SOURCE_PROVIDER,
13 - TXT_SOURCE_FIELD_CACHE,
14 - TXT_SOURCE_EVENT_LOG,
15 - TXT_SOURCE_HARDCODED,
16 -
17 - // terminator
18 - TXT_SOURCE_MAX,
19 -} TXT_SOURCE;
20 -
21 -static inline size_t compute_new_size(size_t old_size, size_t required_size) {
22 - size_t size = (required_size % 2048 == 0) ? required_size : required_size + 2048;
23 - size = (size / 2048) * 2048;
24 -
25 - if(size < old_size * 2)
26 - size = old_size * 2;
27 -
28 - return size;
29 -}
30 -
31 -// --------------------------------------------------------------------------------------------------------------------
32 -// TXT_UTF8
33 -
34 -typedef struct {
35 - char *data;
36 - size_t size; // the allocated size of data buffer
37 - size_t used; // the used size of the data buffer (including null terminators, if any)
38 - TXT_SOURCE src;
39 -} TXT_UTF8;
40 -
41 -static inline void txt_utf8_cleanup(TXT_UTF8 *dst) {
42 - freez(dst->data);
43 - dst->data = NULL;
44 - dst->used = 0;
45 -}
46 -
47 -static inline void txt_utf8_resize(TXT_UTF8 *dst, size_t required_size, bool keep) {
48 - if(required_size <= dst->size)
49 - return;
50 -
51 - size_t new_size = compute_new_size(dst->size, required_size);
52 -
53 - if(keep && dst->data)
54 - dst->data = reallocz(dst->data, new_size);
55 - else {
56 - txt_utf8_cleanup(dst);
57 - dst->data = mallocz(new_size);
58 - dst->used = 0;
59 - }
60 -
61 - dst->size = new_size;
62 -}
63 -
64 -static inline void wevt_utf8_empty(TXT_UTF8 *dst) {
65 - txt_utf8_resize(dst, 1, false);
66 - dst->data[0] = '\0';
67 - dst->used = 1;
68 -}
69 -
70 -static inline void txt_utf8_set(TXT_UTF8 *dst, const char *txt, size_t txt_len) {
71 - txt_utf8_resize(dst, dst->used + txt_len + 1, true);
72 - memcpy(dst->data, txt, txt_len);
73 - dst->used = txt_len + 1;
74 - dst->data[dst->used - 1] = '\0';
75 -}
76 -
77 -static inline void txt_utf8_append(TXT_UTF8 *dst, const char *txt, size_t txt_len) {
78 - if(dst->used <= 1) {
79 - // the destination is empty
80 - txt_utf8_set(dst, txt, txt_len);
81 - }
82 - else {
83 - // there is something already in the buffer
84 - txt_utf8_resize(dst, dst->used + txt_len, true);
85 - memcpy(&dst->data[dst->used - 1], txt, txt_len);
86 - dst->used += txt_len; // the null was already counted
87 - dst->data[dst->used - 1] = '\0';
88 - }
89 -}
90 -
10 #define WINEVENT_NAME_KEYWORDS_SEPARATOR ", "
11 static inline void txt_utf8_add_keywords_separator_if_needed(TXT_UTF8 *dst) {
12 if(dst->used > 1)
@@ -110,75 +29,16 @@ static inline void txt_utf8_set_hex_if_empty(TXT_UTF8 *dst, const char *prefix,
29 }
30 }
31
113 -// --------------------------------------------------------------------------------------------------------------------
114 -// TXT_UNICODE
115 -
116 -typedef struct {
117 - wchar_t *data;
118 - size_t size; // the allocated size of data buffer
119 - size_t used; // the used size of the data buffer (including null terminators, if any)
120 -} TXT_UNICODE;
121 -
122 -static inline void txt_unicode_cleanup(TXT_UNICODE *dst) {
123 - freez(dst->data);
124 -}
125 -
126 -static inline void txt_unicode_resize(TXT_UNICODE *dst, size_t required_size, bool keep) {
127 - if(required_size <= dst->size)
128 - return;
129 -
130 - size_t new_size = compute_new_size(dst->size, required_size);
131 -
132 - if (keep && dst->data) {
133 - dst->data = reallocz(dst->data, new_size * sizeof(wchar_t));
134 - } else {
135 - txt_unicode_cleanup(dst);
136 - dst->data = mallocz(new_size * sizeof(wchar_t));
137 - dst->used = 0;
138 - }
139 -
140 - dst->size = new_size;
141 -}
142 -
143 -static inline void txt_unicode_set(TXT_UNICODE *dst, const wchar_t *txt, size_t txt_len) {
144 - txt_unicode_resize(dst, dst->used + txt_len + 1, true);
145 - memcpy(dst->data, txt, txt_len * sizeof(wchar_t));
146 - dst->used = txt_len + 1;
147 - dst->data[dst->used - 1] = '\0';
148 -}
149 -
150 -static inline void txt_unicode_append(TXT_UNICODE *dst, const wchar_t *txt, size_t txt_len) {
151 - if(dst->used <= 1) {
152 - // the destination is empty
153 - txt_unicode_set(dst, txt, txt_len);
154 - }
155 - else {
156 - // there is something already in the buffer
157 - txt_unicode_resize(dst, dst->used + txt_len, true);
158 - memcpy(&dst->data[dst->used - 1], txt, txt_len * sizeof(wchar_t));
159 - dst->used += txt_len; // the null was already counted
160 - dst->data[dst->used - 1] = '\0';
161 - }
162 -}
163 -
32 // --------------------------------------------------------------------------------------------------------------------
33 // conversions
34
167 -bool wevt_str_unicode_to_utf8(TXT_UTF8 *dst, TXT_UNICODE *unicode);
168 -bool wevt_str_wchar_to_utf8(TXT_UTF8 *dst, const wchar_t *src, int src_len_with_null);
169 -
35 void unicode2utf8(char *dst, size_t dst_size, const wchar_t *src);
36 void utf82unicode(wchar_t *dst, size_t dst_size, const char *src);
37
173 -char *account2utf8(const wchar_t *user);
174 -char *domain2utf8(const wchar_t *domain);
175 -
38 char *channel2utf8(const wchar_t *channel);
39 wchar_t *channel2unicode(const char *utf8str);
40
41 char *query2utf8(const wchar_t *query);
42 char *provider2utf8(const wchar_t *provider);
43
182 -char *unicode2utf8_strdupz(const wchar_t *src, size_t *utf8_len);
183 -
44 #endif //NETDATA_WINDOWS_EVENTS_UNICODE_H
src/collectors/windows-events.plugin/windows-events.c
+1 -1
@@ -1299,7 +1299,7 @@ int main(int argc __maybe_unused, char **argv __maybe_unused) {
1299
1300 wevt_sources_init();
1301 provider_cache_init();
1302 - sid_cache_init();
1302 + cached_sid_username_init();
1303 field_cache_init();
1304
1305 if(!EnableWindowsPrivilege(SE_SECURITY_NAME))
src/collectors/windows-events.plugin/windows-events.h
-1
@@ -126,7 +126,6 @@ typedef enum {
126
127 #include "windows-events-sources.h"
128 #include "windows-events-unicode.h"
129 -#include "windows-events-sid.h"
129 #include "windows-events-xml.h"
130 #include "windows-events-providers.h"
131 #include "windows-events-fields-cache.h"
src/collectors/windows.plugin/perflib-storage.c
-1
@@ -6,7 +6,6 @@
6 #define _COMMON_PLUGIN_NAME PLUGIN_WINDOWS_NAME
7 #define _COMMON_PLUGIN_MODULE_NAME "PerflibStorage"
8 #include "../common-contexts/common-contexts.h"
9 -
9 #include "libnetdata/os/windows-wmi/windows-wmi.h"
10
11 struct logical_disk {
src/database/engine/cache.h
+11
@@ -248,4 +248,15 @@ struct aral_statistics *pgc_aral_statistics(void);
248 size_t pgc_aral_structures(void);
249 size_t pgc_aral_overhead(void);
250
251 +static inline size_t indexing_partition(Word_t ptr, Word_t modulo) __attribute__((const));
252 +static inline size_t indexing_partition(Word_t ptr, Word_t modulo) {
253 +#ifdef ENV64BIT
254 + uint64_t hash = murmur64(ptr);
255 + return hash % modulo;
256 +#else
257 + uint32_t hash = murmur32(ptr);
258 + return hash % modulo;
259 +#endif
260 +}
261 +
262 #endif // DBENGINE_CACHE_H
src/libnetdata/buffer/buffer.h
+2
@@ -3,6 +3,8 @@
3 #ifndef NETDATA_WEB_BUFFER_H
4 #define NETDATA_WEB_BUFFER_H 1
5
6 +#include "../uuid/uuid.h"
7 +#include "../http/content_type.h"
8 #include "../string/utf8.h"
9 #include "../libnetdata.h"
10
src/libnetdata/common.h new
+394
@@ -0,0 +1,394 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#ifndef LIBNETDATA_COMMON_H
4 +#define LIBNETDATA_COMMON_H
5 +
6 +# ifdef __cplusplus
7 +extern "C" {
8 +# endif
9 +
10 +#include "config.h"
11 +
12 +#if defined(NETDATA_DEV_MODE) && !defined(NETDATA_INTERNAL_CHECKS)
13 +#define NETDATA_INTERNAL_CHECKS 1
14 +#endif
15 +
16 +#ifndef SIZEOF_VOID_P
17 +#error SIZEOF_VOID_P is not defined
18 +#endif
19 +
20 +#if SIZEOF_VOID_P == 4
21 +#define ENV32BIT 1
22 +#else
23 +#define ENV64BIT 1
24 +#endif
25 +
26 +#ifdef HAVE_LIBDATACHANNEL
27 +#define ENABLE_WEBRTC 1
28 +#endif
29 +
30 +#define STRINGIFY(x) #x
31 +#define TOSTRING(x) STRINGIFY(x)
32 +
33 +// --------------------------------------------------------------------------------------------------------------------
34 +// NETDATA_OS_TYPE
35 +
36 +#if defined(__FreeBSD__)
37 +#include <pthread_np.h>
38 +#define NETDATA_OS_TYPE "freebsd"
39 +#elif defined(__APPLE__)
40 +#define NETDATA_OS_TYPE "macos"
41 +#elif defined(OS_WINDOWS)
42 +#define NETDATA_OS_TYPE "windows"
43 +#else
44 +#define NETDATA_OS_TYPE "linux"
45 +#endif /* __FreeBSD__, __APPLE__*/
46 +
47 +// --------------------------------------------------------------------------------------------------------------------
48 +// memory allocators
49 +
50 +/* select the memory allocator, based on autoconf findings */
51 +#if defined(ENABLE_JEMALLOC)
52 +
53 +#if defined(HAVE_JEMALLOC_JEMALLOC_H)
54 +#include <jemalloc/jemalloc.h>
55 +#else // !defined(HAVE_JEMALLOC_JEMALLOC_H)
56 +#include <malloc.h>
57 +#endif // !defined(HAVE_JEMALLOC_JEMALLOC_H)
58 +
59 +#elif defined(ENABLE_TCMALLOC)
60 +
61 +#include <google/tcmalloc.h>
62 +
63 +#else /* !defined(ENABLE_JEMALLOC) && !defined(ENABLE_TCMALLOC) */
64 +
65 +#if !(defined(__FreeBSD__) || defined(__APPLE__))
66 +#include <malloc.h>
67 +#endif /* __FreeBSD__ || __APPLE__ */
68 +
69 +#endif /* !defined(ENABLE_JEMALLOC) && !defined(ENABLE_TCMALLOC) */
70 +
71 +// --------------------------------------------------------------------------------------------------------------------
72 +
73 +#include <pthread.h>
74 +#include <errno.h>
75 +#include <stdbool.h>
76 +#include <stdio.h>
77 +#include <stdlib.h>
78 +#include <stdarg.h>
79 +#include <stddef.h>
80 +#include <ctype.h>
81 +#include <string.h>
82 +#include <strings.h>
83 +#include <libgen.h>
84 +#include <dirent.h>
85 +#include <fcntl.h>
86 +#include <getopt.h>
87 +#include <limits.h>
88 +#include <locale.h>
89 +#include <signal.h>
90 +#include <sys/time.h>
91 +#include <sys/types.h>
92 +#include <time.h>
93 +#include <unistd.h>
94 +#include <uv.h>
95 +#include <assert.h>
96 +
97 +#ifdef HAVE_ARPA_INET_H
98 +#include <arpa/inet.h>
99 +#endif
100 +
101 +#ifdef HAVE_NETINET_TCP_H
102 +#include <netinet/tcp.h>
103 +#endif
104 +
105 +#ifdef HAVE_SYS_IOCTL_H
106 +#include <sys/ioctl.h>
107 +#endif
108 +
109 +#ifdef HAVE_GRP_H
110 +#include <grp.h>
111 +#else
112 +typedef uint32_t gid_t;
113 +#endif
114 +
115 +#ifdef HAVE_PWD_H
116 +#include <pwd.h>
117 +#else
118 +typedef uint32_t uid_t;
119 +#endif
120 +
121 +#ifdef HAVE_NET_IF_H
122 +#include <net/if.h>
123 +#endif
124 +
125 +#ifdef HAVE_POLL_H
126 +#include <poll.h>
127 +#endif
128 +
129 +#ifdef HAVE_SYSLOG_H
130 +#include <syslog.h>
131 +#else
132 +/* priorities */
133 +#define LOG_EMERG 0 /* system is unusable */
134 +#define LOG_ALERT 1 /* action must be taken immediately */
135 +#define LOG_CRIT 2 /* critical conditions */
136 +#define LOG_ERR 3 /* error conditions */
137 +#define LOG_WARNING 4 /* warning conditions */
138 +#define LOG_NOTICE 5 /* normal but significant condition */
139 +#define LOG_INFO 6 /* informational */
140 +#define LOG_DEBUG 7 /* debug-level messages */
141 +
142 +/* facility codes */
143 +#define LOG_KERN (0<<3) /* kernel messages */
144 +#define LOG_USER (1<<3) /* random user-level messages */
145 +#define LOG_MAIL (2<<3) /* mail system */
146 +#define LOG_DAEMON (3<<3) /* system daemons */
147 +#define LOG_AUTH (4<<3) /* security/authorization messages */
148 +#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */
149 +#define LOG_LPR (6<<3) /* line printer subsystem */
150 +#define LOG_NEWS (7<<3) /* network news subsystem */
151 +#define LOG_UUCP (8<<3) /* UUCP subsystem */
152 +#define LOG_CRON (9<<3) /* clock daemon */
153 +#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */
154 +#define LOG_FTP (11<<3) /* ftp daemon */
155 +
156 +/* other codes through 15 reserved for system use */
157 +#define LOG_LOCAL0 (16<<3) /* reserved for local use */
158 +#define LOG_LOCAL1 (17<<3) /* reserved for local use */
159 +#define LOG_LOCAL2 (18<<3) /* reserved for local use */
160 +#define LOG_LOCAL3 (19<<3) /* reserved for local use */
161 +#define LOG_LOCAL4 (20<<3) /* reserved for local use */
162 +#define LOG_LOCAL5 (21<<3) /* reserved for local use */
163 +#define LOG_LOCAL6 (22<<3) /* reserved for local use */
164 +#define LOG_LOCAL7 (23<<3) /* reserved for local use */
165 +#endif
166 +
167 +#ifdef HAVE_SYS_MMAN_H
168 +#include <sys/mman.h>
169 +#endif
170 +
171 +#ifdef HAVE_SYS_RESOURCE_H
172 +#include <sys/resource.h>
173 +#endif
174 +
175 +#ifdef HAVE_SYS_SOCKET_H
176 +#include <sys/socket.h>
177 +#endif
178 +
179 +#ifdef HAVE_SYS_WAIT_H
180 +#include <sys/wait.h>
181 +#endif
182 +
183 +#ifdef HAVE_SYS_UN_H
184 +#include <sys/un.h>
185 +#endif
186 +
187 +#ifdef HAVE_SPAWN_H
188 +#include <spawn.h>
189 +#endif
190 +
191 +#ifdef HAVE_NETINET_IN_H
192 +#include <netinet/in.h>
193 +#endif
194 +
195 +#ifdef HAVE_RESOLV_H
196 +#include <resolv.h>
197 +#endif
198 +
199 +#ifdef HAVE_NETDB_H
200 +#include <netdb.h>
201 +#endif
202 +
203 +#ifdef HAVE_SYS_PRCTL_H
204 +#include <sys/prctl.h>
205 +#endif
206 +
207 +#ifdef HAVE_SYS_STAT_H
208 +#include <sys/stat.h>
209 +#endif
210 +
211 +#ifdef HAVE_SYS_VFS_H
212 +#include <sys/vfs.h>
213 +#endif
214 +
215 +#ifdef HAVE_SYS_STATFS_H
216 +#include <sys/statfs.h>
217 +#endif
218 +
219 +#ifdef HAVE_LINUX_MAGIC_H
220 +#include <linux/magic.h>
221 +#endif
222 +
223 +#ifdef HAVE_SYS_MOUNT_H
224 +#include <sys/mount.h>
225 +#endif
226 +
227 +#ifdef HAVE_SYS_STATVFS_H
228 +#include <sys/statvfs.h>
229 +#endif
230 +
231 +// #1408
232 +#ifdef MAJOR_IN_MKDEV
233 +#include <sys/mkdev.h>
234 +#endif
235 +#ifdef MAJOR_IN_SYSMACROS
236 +#include <sys/sysmacros.h>
237 +#endif
238 +
239 +#include <math.h>
240 +#include <float.h>
241 +
242 +#if defined(HAVE_INTTYPES_H)
243 +#include <inttypes.h>
244 +#elif defined(HAVE_STDINT_H)
245 +#include <stdint.h>
246 +#endif
247 +
248 +#include <zlib.h>
249 +
250 +#ifdef HAVE_SYS_CAPABILITY_H
251 +#include <sys/capability.h>
252 +#endif
253 +
254 +#define XXH_INLINE_ALL
255 +#include "xxhash.h"
256 +
257 +// --------------------------------------------------------------------------------------------------------------------
258 +// OpenSSL
259 +
260 +#define OPENSSL_VERSION_095 0x00905100L
261 +#define OPENSSL_VERSION_097 0x0907000L
262 +#define OPENSSL_VERSION_110 0x10100000L
263 +#define OPENSSL_VERSION_111 0x10101000L
264 +#define OPENSSL_VERSION_300 0x30000000L
265 +
266 +#include <openssl/ssl.h>
267 +#include <openssl/rand.h>
268 +#include <openssl/err.h>
269 +#include <openssl/evp.h>
270 +#include <openssl/pem.h>
271 +#if (SSLEAY_VERSION_NUMBER >= OPENSSL_VERSION_097) && (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110)
272 +#include <openssl/conf.h>
273 +#endif
274 +
275 +#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_300
276 +#include <openssl/core_names.h>
277 +#include <openssl/decoder.h>
278 +#endif
279 +
280 +// --------------------------------------------------------------------------------------------------------------------
281 +
282 +#ifndef O_CLOEXEC
283 +#define O_CLOEXEC (0)
284 +#endif
285 +
286 +// --------------------------------------------------------------------------------------------------------------------
287 +// FUNCTION ATTRIBUTES
288 +
289 +#define _cleanup_(x) __attribute__((__cleanup__(x)))
290 +
291 +#ifdef HAVE_FUNC_ATTRIBUTE_RETURNS_NONNULL
292 +#define NEVERNULL __attribute__((returns_nonnull))
293 +#else
294 +#define NEVERNULL
295 +#endif
296 +
297 +#ifdef HAVE_FUNC_ATTRIBUTE_NOINLINE
298 +#define NOINLINE __attribute__((noinline))
299 +#else
300 +#define NOINLINE
301 +#endif
302 +
303 +#ifdef HAVE_FUNC_ATTRIBUTE_MALLOC
304 +#define MALLOCLIKE __attribute__((malloc))
305 +#else
306 +#define MALLOCLIKE
307 +#endif
308 +
309 +#if defined(HAVE_FUNC_ATTRIBUTE_FORMAT_GNU_PRINTF)
310 +#define PRINTFLIKE(f, a) __attribute__ ((format(gnu_printf, f, a)))
311 +#elif defined(HAVE_FUNC_ATTRIBUTE_FORMAT_PRINTF)
312 +#define PRINTFLIKE(f, a) __attribute__ ((format(printf, f, a)))
313 +#else
314 +#define PRINTFLIKE(f, a)
315 +#endif
316 +
317 +#ifdef HAVE_FUNC_ATTRIBUTE_NORETURN
318 +#define NORETURN __attribute__ ((noreturn))
319 +#else
320 +#define NORETURN
321 +#endif
322 +
323 +#ifdef HAVE_FUNC_ATTRIBUTE_WARN_UNUSED_RESULT
324 +#define WARNUNUSED __attribute__ ((warn_unused_result))
325 +#else
326 +#define WARNUNUSED
327 +#endif
328 +
329 +#define UNUSED(x) (void)(x)
330 +
331 +#ifdef __GNUC__
332 +#define UNUSED_FUNCTION(x) __attribute__((unused)) UNUSED_##x
333 +#else
334 +#define UNUSED_FUNCTION(x) UNUSED_##x
335 +#endif
336 +
337 +// --------------------------------------------------------------------------------------------------------------------
338 +// fix for alpine linux
339 +
340 +#if !defined(RUSAGE_THREAD) && defined(RUSAGE_CHILDREN)
341 +#define RUSAGE_THREAD RUSAGE_CHILDREN
342 +#endif
343 +
344 +// --------------------------------------------------------------------------------------------------------------------
345 +// HELPFUL MACROS
346 +
347 +#define ABS(x) (((x) < 0)? (-(x)) : (x))
348 +#define MIN(a,b) (((a)<(b))?(a):(b))
349 +#define MAX(a,b) (((a)>(b))?(a):(b))
350 +#define SWAP(a, b) do { \
351 + typeof(a) _tmp = b; \
352 + b = a; \
353 + a = _tmp; \
354 +} while(0)
355 +
356 +// --------------------------------------------------------------------------------------------------------------------
357 +// NETDATA CLOUD
358 +
359 +// BEWARE: this exists in alarm-notify.sh
360 +#define DEFAULT_CLOUD_BASE_URL "https://app.netdata.cloud"
361 +
362 +// --------------------------------------------------------------------------------------------------------------------
363 +// DBENGINE
364 +
365 +#define RRD_STORAGE_TIERS 5
366 +
367 +// --------------------------------------------------------------------------------------------------------------------
368 +// PIPES
369 +
370 +#define PIPE_READ 0
371 +#define PIPE_WRITE 1
372 +
373 +// --------------------------------------------------------------------------------------------------------------------
374 +// UUIDs
375 +
376 +#define GUID_LEN 36
377 +
378 +// --------------------------------------------------------------------------------------------------------------------
379 +// Macro-only includes
380 +
381 +#include "linked-lists.h"
382 +
383 +// --------------------------------------------------------------------------------------------------------------------
384 +
385 +// Taken from linux kernel
386 +#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
387 +
388 +// --------------------------------------------------------------------------------------------------------------------
389 +
390 +# ifdef __cplusplus
391 +}
392 +# endif
393 +
394 +#endif //LIBNETDATA_COMMON_H
src/libnetdata/inlined.h
-11
@@ -106,17 +106,6 @@ static inline uint64_t murmur64(uint64_t k) {
106 return k;
107 }
108
109 -static inline size_t indexing_partition(Word_t ptr, Word_t modulo) __attribute__((const));
110 -static inline size_t indexing_partition(Word_t ptr, Word_t modulo) {
111 -#ifdef ENV64BIT
112 - uint64_t hash = murmur64(ptr);
113 - return hash % modulo;
114 -#else
115 - uint32_t hash = murmur32(ptr);
116 - return hash % modulo;
117 -#endif
118 -}
119 -
109 static inline unsigned int str2u(const char *s) {
110 unsigned int n = 0;
111
src/libnetdata/libnetdata.c
+4
@@ -2,6 +2,10 @@
2
3 #include "libnetdata.h"
4
5 +#define MALLOC_ALIGNMENT (sizeof(uintptr_t) * 2)
6 +#define size_t_atomic_count(op, var, size) __atomic_## op ##_fetch(&(var), size, __ATOMIC_RELAXED)
7 +#define size_t_atomic_bytes(op, var, size) __atomic_## op ##_fetch(&(var), ((size) % MALLOC_ALIGNMENT)?((size) + MALLOC_ALIGNMENT - ((size) % MALLOC_ALIGNMENT)):(size), __ATOMIC_RELAXED)
8 +
9 #if !defined(MADV_DONTFORK)
10 #define MADV_DONTFORK 0
11 #endif
src/libnetdata/libnetdata.h
+36 -357
@@ -7,323 +7,17 @@
7 extern "C" {
8 # endif
9
10 -#include "config.h"
11 -
12 -#ifdef HAVE_LIBDATACHANNEL
13 -#define ENABLE_WEBRTC 1
14 -#endif
15 -
16 -#define STRINGIFY(x) #x
17 -#define TOSTRING(x) STRINGIFY(x)
10 +#include "common.h"
11
12 #define JUDYHS_INDEX_SIZE_ESTIMATE(key_bytes) (((key_bytes) + sizeof(Word_t) - 1) / sizeof(Word_t) * 4)
13
21 -#if defined(NETDATA_DEV_MODE) && !defined(NETDATA_INTERNAL_CHECKS)
22 -#define NETDATA_INTERNAL_CHECKS 1
23 -#endif
24 -
25 -#ifndef SIZEOF_VOID_P
26 -#error SIZEOF_VOID_P is not defined
27 -#endif
28 -
29 -#if SIZEOF_VOID_P == 4
30 -#define ENV32BIT 1
31 -#else
32 -#define ENV64BIT 1
33 -#endif
34 -
14 // NETDATA_TRACE_ALLOCATIONS does not work under musl libc, so don't enable it
15 //#if defined(NETDATA_INTERNAL_CHECKS) && !defined(NETDATA_TRACE_ALLOCATIONS)
16 //#define NETDATA_TRACE_ALLOCATIONS 1
17 //#endif
18
40 -#define MALLOC_ALIGNMENT (sizeof(uintptr_t) * 2)
41 -#define size_t_atomic_count(op, var, size) __atomic_## op ##_fetch(&(var), size, __ATOMIC_RELAXED)
42 -#define size_t_atomic_bytes(op, var, size) __atomic_## op ##_fetch(&(var), ((size) % MALLOC_ALIGNMENT)?((size) + MALLOC_ALIGNMENT - ((size) % MALLOC_ALIGNMENT)):(size), __ATOMIC_RELAXED)
43 -
44 -// ----------------------------------------------------------------------------
45 -// system include files for all netdata C programs
46 -
47 -/* select the memory allocator, based on autoconf findings */
48 -#if defined(ENABLE_JEMALLOC)
49 -
50 -#if defined(HAVE_JEMALLOC_JEMALLOC_H)
51 -#include <jemalloc/jemalloc.h>
52 -#else // !defined(HAVE_JEMALLOC_JEMALLOC_H)
53 -#include <malloc.h>
54 -#endif // !defined(HAVE_JEMALLOC_JEMALLOC_H)
55 -
56 -#elif defined(ENABLE_TCMALLOC)
57 -
58 -#include <google/tcmalloc.h>
59 -
60 -#else /* !defined(ENABLE_JEMALLOC) && !defined(ENABLE_TCMALLOC) */
61 -
62 -#if !(defined(__FreeBSD__) || defined(__APPLE__))
63 -#include <malloc.h>
64 -#endif /* __FreeBSD__ || __APPLE__ */
65 -
66 -#endif /* !defined(ENABLE_JEMALLOC) && !defined(ENABLE_TCMALLOC) */
67 -
68 -// ----------------------------------------------------------------------------
69 -
70 -#if defined(__FreeBSD__)
71 -#include <pthread_np.h>
72 -#define NETDATA_OS_TYPE "freebsd"
73 -#elif defined(__APPLE__)
74 -#define NETDATA_OS_TYPE "macos"
75 -#elif defined(OS_WINDOWS)
76 -#define NETDATA_OS_TYPE "windows"
77 -#else
78 -#define NETDATA_OS_TYPE "linux"
79 -#endif /* __FreeBSD__, __APPLE__*/
80 -
81 -#include <pthread.h>
82 -#include <errno.h>
83 -#include <stdbool.h>
84 -#include <stdio.h>
85 -#include <stdlib.h>
86 -#include <stdarg.h>
87 -#include <stddef.h>
88 -#include <ctype.h>
89 -#include <string.h>
90 -#include <strings.h>
91 -#include <libgen.h>
92 -#include <dirent.h>
93 -#include <fcntl.h>
94 -#include <getopt.h>
95 -#include <limits.h>
96 -#include <locale.h>
97 -#include <signal.h>
98 -#include <sys/time.h>
99 -#include <sys/types.h>
100 -#include <time.h>
101 -#include <unistd.h>
102 -#include <uv.h>
103 -#include <assert.h>
104 -
105 -#ifdef HAVE_ARPA_INET_H
106 -#include <arpa/inet.h>
107 -#endif
108 -
109 -#ifdef HAVE_NETINET_TCP_H
110 -#include <netinet/tcp.h>
111 -#endif
112 -
113 -#ifdef HAVE_SYS_IOCTL_H
114 -#include <sys/ioctl.h>
115 -#endif
116 -
117 -#ifdef HAVE_GRP_H
118 -#include <grp.h>
119 -#else
120 -typedef uint32_t gid_t;
121 -#endif
122 -
123 -#ifdef HAVE_PWD_H
124 -#include <pwd.h>
125 -#else
126 -typedef uint32_t uid_t;
127 -#endif
128 -
129 -#ifdef HAVE_NET_IF_H
130 -#include <net/if.h>
131 -#endif
132 -
133 -#ifdef HAVE_POLL_H
134 -#include <poll.h>
135 -#endif
136 -
137 -#ifdef HAVE_SYSLOG_H
138 -#include <syslog.h>
139 -#else
140 -/* priorities */
141 -#define LOG_EMERG 0 /* system is unusable */
142 -#define LOG_ALERT 1 /* action must be taken immediately */
143 -#define LOG_CRIT 2 /* critical conditions */
144 -#define LOG_ERR 3 /* error conditions */
145 -#define LOG_WARNING 4 /* warning conditions */
146 -#define LOG_NOTICE 5 /* normal but significant condition */
147 -#define LOG_INFO 6 /* informational */
148 -#define LOG_DEBUG 7 /* debug-level messages */
149 -
150 -/* facility codes */
151 -#define LOG_KERN (0<<3) /* kernel messages */
152 -#define LOG_USER (1<<3) /* random user-level messages */
153 -#define LOG_MAIL (2<<3) /* mail system */
154 -#define LOG_DAEMON (3<<3) /* system daemons */
155 -#define LOG_AUTH (4<<3) /* security/authorization messages */
156 -#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */
157 -#define LOG_LPR (6<<3) /* line printer subsystem */
158 -#define LOG_NEWS (7<<3) /* network news subsystem */
159 -#define LOG_UUCP (8<<3) /* UUCP subsystem */
160 -#define LOG_CRON (9<<3) /* clock daemon */
161 -#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */
162 -#define LOG_FTP (11<<3) /* ftp daemon */
163 -
164 -/* other codes through 15 reserved for system use */
165 -#define LOG_LOCAL0 (16<<3) /* reserved for local use */
166 -#define LOG_LOCAL1 (17<<3) /* reserved for local use */
167 -#define LOG_LOCAL2 (18<<3) /* reserved for local use */
168 -#define LOG_LOCAL3 (19<<3) /* reserved for local use */
169 -#define LOG_LOCAL4 (20<<3) /* reserved for local use */
170 -#define LOG_LOCAL5 (21<<3) /* reserved for local use */
171 -#define LOG_LOCAL6 (22<<3) /* reserved for local use */
172 -#define LOG_LOCAL7 (23<<3) /* reserved for local use */
173 -#endif
174 -
175 -#ifdef HAVE_SYS_MMAN_H
176 -#include <sys/mman.h>
177 -#endif
178 -
179 -#ifdef HAVE_SYS_RESOURCE_H
180 -#include <sys/resource.h>
181 -#endif
182 -
183 -#ifdef HAVE_SYS_SOCKET_H
184 -#include <sys/socket.h>
185 -#endif
186 -
187 -#ifdef HAVE_SYS_WAIT_H
188 -#include <sys/wait.h>
189 -#endif
190 -
191 -#ifdef HAVE_SYS_UN_H
192 -#include <sys/un.h>
193 -#endif
194 -
195 -#ifdef HAVE_SPAWN_H
196 -#include <spawn.h>
197 -#endif
198 -
199 -#ifdef HAVE_NETINET_IN_H
200 -#include <netinet/in.h>
201 -#endif
202 -
203 -#ifdef HAVE_RESOLV_H
204 -#include <resolv.h>
205 -#endif
206 -
207 -#ifdef HAVE_NETDB_H
208 -#include <netdb.h>
209 -#endif
210 -
211 -#ifdef HAVE_SYS_PRCTL_H
212 -#include <sys/prctl.h>
213 -#endif
214 -
215 -#ifdef HAVE_SYS_STAT_H
216 -#include <sys/stat.h>
217 -#endif
218 -
219 -#ifdef HAVE_SYS_VFS_H
220 -#include <sys/vfs.h>
221 -#endif
222 -
223 -#ifdef HAVE_SYS_STATFS_H
224 -#include <sys/statfs.h>
225 -#endif
226 -
227 -#ifdef HAVE_LINUX_MAGIC_H
228 -#include <linux/magic.h>
229 -#endif
230 -
231 -#ifdef HAVE_SYS_MOUNT_H
232 -#include <sys/mount.h>
233 -#endif
234 -
235 -#ifdef HAVE_SYS_STATVFS_H
236 -#include <sys/statvfs.h>
237 -#endif
238 -
239 -// #1408
240 -#ifdef MAJOR_IN_MKDEV
241 -#include <sys/mkdev.h>
242 -#endif
243 -#ifdef MAJOR_IN_SYSMACROS
244 -#include <sys/sysmacros.h>
245 -#endif
246 -
247 -#include <math.h>
248 -#include <float.h>
249 -
250 -#if defined(HAVE_INTTYPES_H)
251 -#include <inttypes.h>
252 -#elif defined(HAVE_STDINT_H)
253 -#include <stdint.h>
254 -#endif
255 -
256 -#include <zlib.h>
257 -
258 -#ifdef HAVE_SYS_CAPABILITY_H
259 -#include <sys/capability.h>
260 -#endif
261 -
262 -
263 -#ifndef O_CLOEXEC
264 -#define O_CLOEXEC (0)
265 -#endif
266 -
267 -// ----------------------------------------------------------------------------
268 -// netdata common definitions
269 -
270 -#define _cleanup_(x) __attribute__((__cleanup__(x)))
271 -
272 -#ifdef HAVE_FUNC_ATTRIBUTE_RETURNS_NONNULL
273 -#define NEVERNULL __attribute__((returns_nonnull))
274 -#else
275 -#define NEVERNULL
276 -#endif
277 -
278 -#ifdef HAVE_FUNC_ATTRIBUTE_NOINLINE
279 -#define NOINLINE __attribute__((noinline))
280 -#else
281 -#define NOINLINE
282 -#endif
283 -
284 -#ifdef HAVE_FUNC_ATTRIBUTE_MALLOC
285 -#define MALLOCLIKE __attribute__((malloc))
286 -#else
287 -#define MALLOCLIKE
288 -#endif
289 -
290 -#if defined(HAVE_FUNC_ATTRIBUTE_FORMAT_GNU_PRINTF)
291 -#define PRINTFLIKE(f, a) __attribute__ ((format(gnu_printf, f, a)))
292 -#elif defined(HAVE_FUNC_ATTRIBUTE_FORMAT_PRINTF)
293 -#define PRINTFLIKE(f, a) __attribute__ ((format(printf, f, a)))
294 -#else
295 -#define PRINTFLIKE(f, a)
296 -#endif
297 -
298 -#ifdef HAVE_FUNC_ATTRIBUTE_NORETURN
299 -#define NORETURN __attribute__ ((noreturn))
300 -#else
301 -#define NORETURN
302 -#endif
303 -
304 -#ifdef HAVE_FUNC_ATTRIBUTE_WARN_UNUSED_RESULT
305 -#define WARNUNUSED __attribute__ ((warn_unused_result))
306 -#else
307 -#define WARNUNUSED
308 -#endif
309 -
19 #include "libjudy/judy-malloc.h"
20
312 -#define ABS(x) (((x) < 0)? (-(x)) : (x))
313 -#define MIN(a,b) (((a)<(b))?(a):(b))
314 -#define MAX(a,b) (((a)>(b))?(a):(b))
315 -#define SWAP(a, b) do { \
316 - typeof(a) _tmp = b; \
317 - b = a; \
318 - a = _tmp; \
319 -} while(0)
320 -
321 -#define GUID_LEN 36
322 -
323 -#define PIPE_READ 0
324 -#define PIPE_WRITE 1
325 -
326 -#include "linked-lists.h"
21 #include "storage-point.h"
22 #include "paths/paths.h"
23
@@ -389,31 +83,11 @@ extern volatile sig_atomic_t netdata_exit;
83 char *read_by_filename(const char *filename, long *file_size);
84 char *find_and_replace(const char *src, const char *find, const char *replace, const char *where);
85
392 -/* fix for alpine linux */
393 -#ifndef RUSAGE_THREAD
394 -#ifdef RUSAGE_CHILDREN
395 -#define RUSAGE_THREAD RUSAGE_CHILDREN
396 -#endif
397 -#endif
398 -
86 #define BITS_IN_A_KILOBIT 1000
87 #define KILOBITS_IN_A_MEGABIT 1000
88
402 -/* misc. */
403 -
404 -#define UNUSED(x) (void)(x)
405 -
406 -#ifdef __GNUC__
407 -#define UNUSED_FUNCTION(x) __attribute__((unused)) UNUSED_##x
408 -#else
409 -#define UNUSED_FUNCTION(x) UNUSED_##x
410 -#endif
411 -
89 #define error_report(x, args...) do { errno_clear(); netdata_log_error(x, ##args); } while(0)
90
414 -// Taken from linux kernel
415 -#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
416 -
91 #include "bitmap64.h"
92
93 #define COMPRESSION_MAX_CHUNK 0x4000
@@ -432,47 +106,55 @@ void netdata_cleanup_and_exit(int ret, const char *action, const char *action_re
106
107 extern const char *netdata_configured_host_prefix;
108
435 -#include "os/os.h"
109 +// safe includes before O/S specific functions
110 +#include "template-enum.h"
111 +#include "libjudy/src/Judy.h"
112 +#include "july/july.h"
113
437 -#define XXH_INLINE_ALL
438 -#include "xxhash.h"
114 +#include "string/string.h"
115 +#include "buffer/buffer.h"
116
117 #include "uuid/uuid.h"
441 -#include "template-enum.h"
442 -#include "http/http_access.h"
118 #include "http/content_type.h"
444 -#include "config/dyncfg.h"
445 -#include "libjudy/src/Judy.h"
446 -#include "july/july.h"
119 +#include "http/http_access.h"
120 +
121 +#include "inlined.h"
122 +#include "parsers/parsers.h"
123 +
124 #include "threads/threads.h"
448 -#include "buffer/buffer.h"
449 -#include "ringbuffer/ringbuffer.h"
450 -#include "c_rhash/c_rhash.h"
125 #include "locks/locks.h"
452 -#include "circular_buffer/circular_buffer.h"
126 +#include "completion/completion.h"
127 +#include "clocks/clocks.h"
128 +#include "simple_pattern/simple_pattern.h"
129 +#include "libnetdata/log/nd_log.h"
130 +
131 +#include "socket/security.h" // must be before windows.h
132 +
133 +// this may include windows.h
134 +#include "os/os.h"
135 +
136 +#include "socket/socket.h"
137 #include "avl/avl.h"
454 -#include "inlined.h"
138 +
139 #include "line_splitter/line_splitter.h"
456 -#include "clocks/clocks.h"
457 -#include "parsers/parsers.h"
140 +#include "c_rhash/c_rhash.h"
141 +#include "ringbuffer/ringbuffer.h"
142 +#include "circular_buffer/circular_buffer.h"
143 +#include "buffered_reader/buffered_reader.h"
144 #include "datetime/iso8601.h"
145 #include "datetime/rfc3339.h"
146 #include "datetime/rfc7231.h"
461 -#include "completion/completion.h"
462 -#include "libnetdata/log/nd_log.h"
147 +#include "sanitizers/sanitizers.h"
148 +
149 +#include "config/dyncfg.h"
150 +#include "config/appconfig.h"
151 #include "spawn_server/spawn_server.h"
152 #include "spawn_server/spawn_popen.h"
465 -#include "simple_pattern/simple_pattern.h"
466 -#include "socket/security.h"
467 -#include "socket/socket.h"
468 -#include "config/appconfig.h"
469 -#include "log/systemd-journal-helpers.h"
470 -#include "buffered_reader/buffered_reader.h"
153 #include "procfile/procfile.h"
472 -#include "string/string.h"
154 #include "dictionary/dictionary.h"
155 #include "dictionary/thread-cache.h"
475 -#include "sanitizers/sanitizers.h"
156 +
157 +#include "log/systemd-journal-helpers.h"
158
159 #if defined(HAVE_LIBBPF) && !defined(__cplusplus)
160 #include "ebpf/ebpf.h"
@@ -494,11 +176,6 @@ extern const char *netdata_configured_host_prefix;
176 #include "functions_evloop/functions_evloop.h"
177 #include "query_progress/progress.h"
178
497 -// BEWARE: this exists in alarm-notify.sh
498 -#define DEFAULT_CLOUD_BASE_URL "https://app.netdata.cloud"
499 -
500 -#define RRD_STORAGE_TIERS 5
501 -
179 static inline size_t struct_natural_alignment(size_t size) __attribute__((const));
180
181 #define STRUCT_NATURAL_ALIGNMENT (sizeof(uintptr_t) * 2)
@@ -644,6 +321,8 @@ bool rrdr_relative_window_to_absolute_query(time_t *after, time_t *before, time_
321 int netdata_base64_decode(unsigned char *out, const unsigned char *in, int in_len);
322 int netdata_base64_encode(unsigned char *encoded, const unsigned char *input, size_t input_size);
323
324 +// --------------------------------------------------------------------------------------------------------------------
325 +
326 static inline void freez_charp(char **p) {
327 freez(*p);
328 }
src/libnetdata/local-sockets/local-sockets.h renamed
src/libnetdata/maps/system-groups.h deleted
-68
@@ -1,68 +0,0 @@
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 - XXH64_hash_t hash = XXH3_64bits(&gid, sizeof(gid));
25 - SIMPLE_HASHTABLE_SLOT_GROUPNAMES_CACHE *sl = simple_hashtable_get_slot_GROUPNAMES_CACHE(&gc->ht, hash, &gid, true);
26 - STRING *g = SIMPLE_HASHTABLE_SLOT_DATA(sl);
27 - if(!g) {
28 - char tmp[1024 + 1];
29 - struct group grp, *result = NULL;
30 -
31 - if (getgrgid_r(gid, &grp, tmp, sizeof(tmp), &result) != 0 || !result || !grp.gr_name || !(*grp.gr_name)) {
32 - char name[50];
33 - snprintfz(name, sizeof(name), "%u", gid);
34 - g = string_strdupz(name);
35 - }
36 - else
37 - g = string_strdupz(grp.gr_name);
38 -
39 - simple_hashtable_set_slot_GROUPNAMES_CACHE(&gc->ht, sl, hash, g);
40 - }
41 -
42 - g = string_dup(g);
43 - spinlock_unlock(&gc->spinlock);
44 - return g;
45 -}
46 -
47 -static inline GROUPNAMES_CACHE *system_groupnames_cache_init(void) {
48 - GROUPNAMES_CACHE *gc = callocz(1, sizeof(*gc));
49 - spinlock_init(&gc->spinlock);
50 - simple_hashtable_init_GROUPNAMES_CACHE(&gc->ht, 100);
51 - return gc;
52 -}
53 -
54 -static inline void system_groupnames_cache_destroy(GROUPNAMES_CACHE *gc) {
55 - spinlock_lock(&gc->spinlock);
56 -
57 - for(SIMPLE_HASHTABLE_SLOT_GROUPNAMES_CACHE *sl = simple_hashtable_first_read_only_GROUPNAMES_CACHE(&gc->ht);
58 - sl;
59 - sl = simple_hashtable_next_read_only_GROUPNAMES_CACHE(&gc->ht, sl)) {
60 - STRING *u = SIMPLE_HASHTABLE_SLOT_DATA(sl);
61 - string_freez(u);
62 - }
63 -
64 - simple_hashtable_destroy_GROUPNAMES_CACHE(&gc->ht);
65 - freez(gc);
66 -}
67 -
68 -#endif //NETDATA_SYSTEM_GROUPS_H
src/libnetdata/maps/system-users.h deleted
-68
@@ -1,68 +0,0 @@
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 - XXH64_hash_t hash = XXH3_64bits(&uid, sizeof(uid));
25 - SIMPLE_HASHTABLE_SLOT_USERNAMES_CACHE *sl = simple_hashtable_get_slot_USERNAMES_CACHE(&uc->ht, hash, &uid, true);
26 - STRING *u = SIMPLE_HASHTABLE_SLOT_DATA(sl);
27 - if(!u) {
28 - char tmp[1024 + 1];
29 - struct passwd pw, *result = NULL;
30 -
31 - if (getpwuid_r(uid, &pw, tmp, sizeof(tmp), &result) != 0 || !result || !pw.pw_name || !(*pw.pw_name)) {
32 - char name[50];
33 - snprintfz(name, sizeof(name), "%u", uid);
34 - u = string_strdupz(name);
35 - }
36 - else
37 - u = string_strdupz(pw.pw_name);
38 -
39 - simple_hashtable_set_slot_USERNAMES_CACHE(&uc->ht, sl, hash, u);
40 - }
41 -
42 - u = string_dup(u);
43 - spinlock_unlock(&uc->spinlock);
44 - return u;
45 -}
46 -
47 -static inline USERNAMES_CACHE *system_usernames_cache_init(void) {
48 - USERNAMES_CACHE *uc = callocz(1, sizeof(*uc));
49 - spinlock_init(&uc->spinlock);
50 - simple_hashtable_init_USERNAMES_CACHE(&uc->ht, 100);
51 - return uc;
52 -}
53 -
54 -static inline void system_usernames_cache_destroy(USERNAMES_CACHE *uc) {
55 - spinlock_lock(&uc->spinlock);
56 -
57 - for(SIMPLE_HASHTABLE_SLOT_USERNAMES_CACHE *sl = simple_hashtable_first_read_only_USERNAMES_CACHE(&uc->ht);
58 - sl;
59 - sl = simple_hashtable_next_read_only_USERNAMES_CACHE(&uc->ht, sl)) {
60 - STRING *u = SIMPLE_HASHTABLE_SLOT_DATA(sl);
61 - string_freez(u);
62 - }
63 -
64 - simple_hashtable_destroy_USERNAMES_CACHE(&uc->ht);
65 - freez(uc);
66 -}
67 -
68 -#endif //NETDATA_SYSTEM_USERS_H
src/libnetdata/os/os.h
+8
@@ -23,8 +23,16 @@
23 #include "os-freebsd-wrappers.h"
24 #include "os-macos-wrappers.h"
25 #include "os-windows-wrappers.h"
26 +#include "system-maps/cached-uid-username.h"
27 +#include "system-maps/cached-gid-groupname.h"
28 +#include "system-maps/cache-host-users-and-groups.h"
29 +#include "system-maps/cached-sid-username.h"
30 #include "windows-perflib/perflib.h"
31
32 +// this includes windows.h to the whole of netdata
33 +// so various conflicts arise
34 +// #include "windows-wmi/windows-wmi.h"
35 +
36 // =====================================================================================================================
37 // common defs for Apple/FreeBSD/Linux
38
src/libnetdata/os/system-maps/cache-host-users-and-groups.c new
+101
@@ -0,0 +1,101 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include "libnetdata/libnetdata.h"
4 +
5 +static bool file_changed(const struct stat *statbuf __maybe_unused, struct timespec *last_modification_time __maybe_unused) {
6 +#if defined(OS_MACOS) || defined(OS_WINDOWS)
7 + return false;
8 +#else
9 + if(likely(statbuf->st_mtim.tv_sec == last_modification_time->tv_sec &&
10 + statbuf->st_mtim.tv_nsec == last_modification_time->tv_nsec)) return false;
11 +
12 + last_modification_time->tv_sec = statbuf->st_mtim.tv_sec;
13 + last_modification_time->tv_nsec = statbuf->st_mtim.tv_nsec;
14 +
15 + return true;
16 +#endif
17 +}
18 +
19 +static size_t read_passwd_or_group(const char *filename, struct timespec *last_modification_time, void (*cb)(uint32_t gid, const char *name, uint32_t version), uint32_t version) {
20 + struct stat statbuf;
21 + if(unlikely(stat(filename, &statbuf) || !file_changed(&statbuf, last_modification_time)))
22 + return 0;
23 +
24 + procfile *ff = procfile_open(filename, " :\t", PROCFILE_FLAG_DEFAULT);
25 + if(unlikely(!ff)) return 0;
26 +
27 + ff = procfile_readall(ff);
28 + if(unlikely(!ff)) return 0;
29 +
30 + size_t line, lines = procfile_lines(ff);
31 +
32 + size_t added = 0;
33 + for(line = 0; line < lines ;line++) {
34 + size_t words = procfile_linewords(ff, line);
35 + if(unlikely(words < 3)) continue;
36 +
37 + char *name = procfile_lineword(ff, line, 0);
38 + if(unlikely(!name || !*name)) continue;
39 +
40 + char *id_string = procfile_lineword(ff, line, 2);
41 + if(unlikely(!id_string || !*id_string)) continue;
42 +
43 + uint32_t id = str2ull(id_string, NULL);
44 +
45 + cb(id, name, version);
46 + added++;
47 + }
48 +
49 + procfile_close(ff);
50 + return added;
51 +}
52 +
53 +void update_cached_host_users(void) {
54 + if(!netdata_configured_host_prefix || !*netdata_configured_host_prefix) return;
55 +
56 + static SPINLOCK spinlock = NETDATA_SPINLOCK_INITIALIZER;
57 + if(!spinlock_trylock(&spinlock)) return;
58 +
59 + char filename[FILENAME_MAX];
60 + static bool initialized = false;
61 +
62 + size_t added = 0;
63 +
64 + if(!initialized) {
65 + initialized = true;
66 + cached_usernames_init();
67 + }
68 +
69 + static uint32_t passwd_version = 0;
70 + static struct timespec passwd_ts = { 0 };
71 + snprintfz(filename, FILENAME_MAX, "%s/etc/passwd", netdata_configured_host_prefix);
72 + added = read_passwd_or_group(filename, &passwd_ts, cached_username_populate_by_uid, ++passwd_version);
73 + if(added) cached_usernames_delete_old_versions(passwd_version);
74 +
75 + spinlock_unlock(&spinlock);
76 +}
77 +
78 +void update_cached_host_groups(void) {
79 + if(!netdata_configured_host_prefix || !*netdata_configured_host_prefix) return;
80 +
81 + static SPINLOCK spinlock = NETDATA_SPINLOCK_INITIALIZER;
82 + if(!spinlock_trylock(&spinlock)) return;
83 +
84 + char filename[FILENAME_MAX];
85 + static bool initialized = false;
86 +
87 + size_t added = 0;
88 +
89 + if(!initialized) {
90 + initialized = true;
91 + cached_groupnames_init();
92 + }
93 +
94 + static uint32_t group_version = 0;
95 + static struct timespec group_ts = { 0 };
96 + snprintfz(filename, FILENAME_MAX, "%s/etc/group", netdata_configured_host_prefix);
97 + added = read_passwd_or_group(filename, &group_ts, cached_groupname_populate_by_gid, ++group_version);
98 + if(added) cached_groupnames_delete_old_versions(group_version);
99 +
100 + spinlock_unlock(&spinlock);
101 +}
src/libnetdata/os/system-maps/cache-host-users-and-groups.h new
+9
@@ -0,0 +1,9 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#ifndef NETDATA_CACHE_HOST_USERS_AND_GROUPS_H
4 +#define NETDATA_CACHE_HOST_USERS_AND_GROUPS_H
5 +
6 +void update_cached_host_users(void);
7 +void update_cached_host_groups(void);
8 +
9 +#endif //NETDATA_CACHE_HOST_USERS_AND_GROUPS_H
src/libnetdata/os/system-maps/cached-gid-groupname.c new
+147
@@ -0,0 +1,147 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include "cached-gid-groupname.h"
4 +
5 +// --------------------------------------------------------------------------------------------------------------------
6 +// hashtable for caching gid to groupname mappings
7 +// key is the gid, value is groupname (STRING)
8 +
9 +#define SIMPLE_HASHTABLE_KEY_TYPE gid_t
10 +#define SIMPLE_HASHTABLE_VALUE_TYPE CACHED_GROUPNAME
11 +#define SIMPLE_HASHTABLE_VALUE2KEY_FUNCTION cached_groupname_to_gid_ptr
12 +#define SIMPLE_HASHTABLE_COMPARE_KEYS_FUNCTION compar_gid_ptr
13 +#define SIMPLE_HASHTABLE_NAME _GROUPNAMES_CACHE
14 +#include "libnetdata/simple_hashtable.h"
15 +
16 +static struct {
17 + bool initialized;
18 + SPINLOCK spinlock;
19 + SIMPLE_HASHTABLE_GROUPNAMES_CACHE ht;
20 +} uc = {
21 + .spinlock = NETDATA_SPINLOCK_INITIALIZER,
22 + .ht = { 0 },
23 +};
24 +
25 +static gid_t *cached_groupname_to_gid_ptr(CACHED_GROUPNAME *cu) {
26 + return &cu->gid;
27 +}
28 +
29 +static bool compar_gid_ptr(gid_t *a, gid_t *b) {
30 + return *a == *b;
31 +}
32 +
33 +void cached_groupname_populate_by_gid(gid_t gid, const char *groupname, uint32_t version) {
34 + internal_fatal(!uc.initialized, "system-users cache needs to be initialized");
35 + if(!groupname || !*groupname) return;
36 +
37 + spinlock_lock(&uc.spinlock);
38 +
39 + XXH64_hash_t hash = XXH3_64bits(&gid, sizeof(gid));
40 + SIMPLE_HASHTABLE_SLOT_GROUPNAMES_CACHE *sl = simple_hashtable_get_slot_GROUPNAMES_CACHE(&uc.ht, hash, &gid, true);
41 + CACHED_GROUPNAME *cg = SIMPLE_HASHTABLE_SLOT_DATA(sl);
42 + if(!cg || (cg->version && version > cg->version)) {
43 + internal_fatal(cg && cg->gid != gid, "invalid gid matched from cache");
44 +
45 + if(cg)
46 + string_freez(cg->groupname);
47 + else
48 + cg = callocz(1, sizeof(*cg));
49 +
50 + cg->version = version;
51 + cg->gid = gid;
52 + cg->groupname = string_strdupz(groupname);
53 + simple_hashtable_set_slot_GROUPNAMES_CACHE(&uc.ht, sl, hash, cg);
54 + }
55 +
56 + spinlock_unlock(&uc.spinlock);
57 +}
58 +
59 +CACHED_GROUPNAME cached_groupname_get_by_gid(gid_t gid) {
60 + internal_fatal(!uc.initialized, "system-users cache needs to be initialized");
61 +
62 + spinlock_lock(&uc.spinlock);
63 +
64 + XXH64_hash_t hash = XXH3_64bits(&gid, sizeof(gid));
65 + SIMPLE_HASHTABLE_SLOT_GROUPNAMES_CACHE *sl = simple_hashtable_get_slot_GROUPNAMES_CACHE(&uc.ht, hash, &gid, true);
66 + CACHED_GROUPNAME *cg = SIMPLE_HASHTABLE_SLOT_DATA(sl);
67 + if(!cg) {
68 + cg = callocz(1, sizeof(*cg));
69 +
70 + static char tmp[1024]; // we are inside a global spinlock - it is ok to be static
71 + struct group gr, *result = NULL;
72 +
73 + if (getgrgid_r(gid, &gr, tmp, sizeof(tmp), &result) != 0 || !result || !gr.gr_name || !(*gr.gr_name)) {
74 + char name[UINT64_MAX_LENGTH];
75 + print_uint64(name, gid);
76 + cg->groupname = string_strdupz(name);
77 + }
78 + else
79 + cg->groupname = string_strdupz(gr.gr_name);
80 +
81 + cg->gid = gid;
82 + simple_hashtable_set_slot_GROUPNAMES_CACHE(&uc.ht, sl, hash, cg);
83 + }
84 +
85 + internal_fatal(cg->gid != gid, "invalid gid matched from cache");
86 +
87 + CACHED_GROUPNAME rc = {
88 + .version = cg->version,
89 + .gid = cg->gid,
90 + .groupname = string_dup(cg->groupname),
91 + };
92 +
93 + spinlock_unlock(&uc.spinlock);
94 + return rc;
95 +}
96 +
97 +void cached_groupname_release(CACHED_GROUPNAME cg) {
98 + string_freez(cg.groupname);
99 +}
100 +
101 +void cached_groupnames_init(void) {
102 + if(uc.initialized) return;
103 + uc.initialized = true;
104 +
105 + spinlock_init(&uc.spinlock);
106 + simple_hashtable_init_GROUPNAMES_CACHE(&uc.ht, 100);
107 +}
108 +
109 +void cached_groupnames_destroy(void) {
110 + if(!uc.initialized) return;
111 +
112 + spinlock_lock(&uc.spinlock);
113 +
114 + for(SIMPLE_HASHTABLE_SLOT_GROUPNAMES_CACHE *sl = simple_hashtable_first_read_only_GROUPNAMES_CACHE(&uc.ht);
115 + sl;
116 + sl = simple_hashtable_next_read_only_GROUPNAMES_CACHE(&uc.ht, sl)) {
117 + CACHED_GROUPNAME *u = SIMPLE_HASHTABLE_SLOT_DATA(sl);
118 + if(u) {
119 + string_freez(u->groupname);
120 + freez(u);
121 + // simple_hashtable_del_slot_GROUPNAMES_CACHE(&uc.ht, sl);
122 + }
123 + }
124 +
125 + simple_hashtable_destroy_GROUPNAMES_CACHE(&uc.ht);
126 + uc.initialized = false;
127 +}
128 +
129 +void cached_groupnames_delete_old_versions(uint32_t version) {
130 + if(!uc.initialized) return;
131 +
132 + spinlock_lock(&uc.spinlock);
133 +
134 + for(SIMPLE_HASHTABLE_SLOT_GROUPNAMES_CACHE *sl = simple_hashtable_first_read_only_GROUPNAMES_CACHE(&uc.ht);
135 + sl;
136 + sl = simple_hashtable_next_read_only_GROUPNAMES_CACHE(&uc.ht, sl)) {
137 + CACHED_GROUPNAME *cg = SIMPLE_HASHTABLE_SLOT_DATA(sl);
138 + if(cg && cg->version && cg->version < version) {
139 + string_freez(cg->groupname);
140 + freez(cg);
141 + simple_hashtable_del_slot_GROUPNAMES_CACHE(&uc.ht, sl);
142 + }
143 + }
144 +
145 + simple_hashtable_destroy_GROUPNAMES_CACHE(&uc.ht);
146 + uc.initialized = false;
147 +}
src/libnetdata/os/system-maps/cached-gid-groupname.h new
+24
@@ -0,0 +1,24 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#ifndef NETDATA_CACHED_UID_GROUPNAME_H
4 +#define NETDATA_CACHED_UID_GROUPNAME_H
5 +
6 +#include "libnetdata/libnetdata.h"
7 +
8 +struct netdata_string;
9 +
10 +typedef struct {
11 + uint32_t version;
12 + gid_t gid;
13 + struct netdata_string *groupname;
14 +} CACHED_GROUPNAME;
15 +
16 +void cached_groupname_populate_by_gid(gid_t gid, const char *groupname, uint32_t version);
17 +CACHED_GROUPNAME cached_groupname_get_by_gid(gid_t gid);
18 +void cached_groupname_release(CACHED_GROUPNAME cg);
19 +void cached_groupnames_delete_old_versions(uint32_t version);
20 +
21 +void cached_groupnames_init(void);
22 +void cached_groupnames_destroy(void);
23 +
24 +#endif //NETDATA_CACHED_UID_GROUPNAME_H
src/libnetdata/os/system-maps/cached-sid-username.c renamed
+65 -45
@@ -1,6 +1,10 @@
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 -#include "windows-events-sid.h"
3 +#include "../../libnetdata.h"
4 +
5 +#if defined(OS_WINDOWS)
6 +#include "cached-sid-username.h"
7 +#include <windows.h>
8 #include <sddl.h>
9
10 typedef struct {
@@ -12,15 +16,10 @@ typedef struct {
16 // IMPORTANT:
17 // This is malloc'd ! You have to manually set fields to zero.
18
15 - const char *account;
16 - const char *domain;
17 - const char *full;
18 - const char *sid_str;
19 -
20 - uint32_t account_len;
21 - uint32_t domain_len;
22 - uint32_t full_len;
23 - uint32_t sid_str_len;
19 + STRING *account;
20 + STRING *domain;
21 + STRING *full;
22 + STRING *sid_str;
23
24 // this needs to be last, because of its variable size
25 SID_KEY key;
@@ -49,11 +48,25 @@ static inline bool sid_cache_compar(SID_KEY *a, SID_KEY *b) {
48 return a->len == b->len && memcmp(&a->sid, &b->sid, a->len) == 0;
49 }
50
52 -void sid_cache_init(void) {
51 +void cached_sid_username_init(void) {
52 simple_hashtable_init_SID(&sid_globals.hashtable, 100);
53 }
54
56 -static void lookup_user(SID_VALUE *sv) {
55 +static char *account2utf8(const wchar_t *user) {
56 + static __thread char buffer[256];
57 + if(utf16_to_utf8(buffer, sizeof(buffer), user, -1, NULL) == 0)
58 + buffer[0] = '\0';
59 + return buffer;
60 +}
61 +
62 +static char *domain2utf8(const wchar_t *domain) {
63 + static __thread char buffer[256];
64 + if(utf16_to_utf8(buffer, sizeof(buffer), domain, -1, NULL) == 0)
65 + buffer[0] = '\0';
66 + return buffer;
67 +}
68 +
69 +static void lookup_user_in_system(SID_VALUE *sv) {
70 static __thread wchar_t account_unicode[256];
71 static __thread wchar_t domain_unicode[256];
72 static __thread char tmp[512 + 2];
@@ -66,28 +79,21 @@ static void lookup_user(SID_VALUE *sv) {
79 const char *account = account2utf8(account_unicode);
80 const char *domain = domain2utf8(domain_unicode);
81 snprintfz(tmp, sizeof(tmp), "%s\\%s", domain, account);
69 - sv->domain = strdupz(domain); sv->domain_len = strlen(sv->domain);
70 - sv->account = strdupz(account); sv->account_len = strlen(sv->account);
71 - sv->full = strdupz(tmp); sv->full_len = strlen(sv->full);
82 + sv->domain = string_strdupz(domain);
83 + sv->account = string_strdupz(account);
84 + sv->full = string_strdupz(tmp);
85 }
86 else {
87 sv->domain = NULL;
88 sv->account = NULL;
89 sv->full = NULL;
77 - sv->domain_len = 0;
78 - sv->account_len = 0;
79 - sv->full_len = 0;
90 }
91
92 wchar_t *sid_string = NULL;
83 - if (ConvertSidToStringSidW(sv->key.sid, &sid_string)) {
84 - sv->sid_str = strdupz(account2utf8(sid_string));
85 - sv->sid_str_len = strlen(sv->sid_str);
86 - }
87 - else {
93 + if (ConvertSidToStringSidW(sv->key.sid, &sid_string))
94 + sv->sid_str = string_strdupz(account2utf8(sid_string));
95 + else
96 sv->sid_str = NULL;
89 - sv->sid_str_len = 0;
90 - }
97 }
98
99 static SID_VALUE *lookup_or_convert_user_id_to_name_lookup(PSID sid) {
@@ -112,7 +118,7 @@ static SID_VALUE *lookup_or_convert_user_id_to_name_lookup(PSID sid) {
118 found = mallocz(tmp_size);
119 memcpy(found, buf, tmp_size);
120
115 - lookup_user(found);
121 + lookup_user_in_system(found);
122
123 // add it to the cache
124 spinlock_lock(&sid_globals.spinlock);
@@ -122,41 +128,44 @@ static SID_VALUE *lookup_or_convert_user_id_to_name_lookup(PSID sid) {
128 return found;
129 }
130
125 -bool wevt_convert_user_id_to_name(PSID sid, TXT_UTF8 *dst_account, TXT_UTF8 *dst_domain, TXT_UTF8 *dst_sid_str) {
131 +bool cached_sid_to_account_domain_sidstr(PSID sid, TXT_UTF8 *dst_account, TXT_UTF8 *dst_domain, TXT_UTF8 *dst_sid_str) {
132 SID_VALUE *found = lookup_or_convert_user_id_to_name_lookup(sid);
133
134 if(found) {
135 if (found->account) {
130 - txt_utf8_resize(dst_account, found->account_len + 1, false);
131 - memcpy(dst_account->data, found->account, found->account_len + 1);
132 - dst_account->used = found->account_len + 1;
136 + txt_utf8_resize(dst_account, string_strlen(found->account) + 1, false);
137 + memcpy(dst_account->data, string2str(found->account), string_strlen(found->account) + 1);
138 + dst_account->used = string_strlen(found->account) + 1;
139 }
134 - else wevt_utf8_empty(dst_account);
140 + else
141 + txt_utf8_empty(dst_account);
142
143 if (found->domain) {
137 - txt_utf8_resize(dst_domain, found->domain_len + 1, false);
138 - memcpy(dst_domain->data, found->domain, found->domain_len + 1);
139 - dst_domain->used = found->domain_len + 1;
144 + txt_utf8_resize(dst_domain, string_strlen(found->domain) + 1, false);
145 + memcpy(dst_domain->data, string2str(found->domain), string_strlen(found->domain) + 1);
146 + dst_domain->used = string_strlen(found->domain) + 1;
147 }
141 - else wevt_utf8_empty(dst_domain);
148 + else
149 + txt_utf8_empty(dst_domain);
150
151 if (found->sid_str) {
144 - txt_utf8_resize(dst_sid_str, found->sid_str_len + 1, false);
145 - memcpy(dst_sid_str->data, found->sid_str, found->sid_str_len + 1);
146 - dst_sid_str->used = found->sid_str_len + 1;
152 + txt_utf8_resize(dst_sid_str, string_strlen(found->sid_str) + 1, false);
153 + memcpy(dst_sid_str->data, string2str(found->sid_str), string_strlen(found->sid_str) + 1);
154 + dst_sid_str->used = string_strlen(found->sid_str) + 1;
155 }
148 - else wevt_utf8_empty(dst_sid_str);
156 + else
157 + txt_utf8_empty(dst_sid_str);
158
159 return true;
160 }
161
153 - wevt_utf8_empty(dst_account);
154 - wevt_utf8_empty(dst_domain);
155 - wevt_utf8_empty(dst_sid_str);
162 + txt_utf8_empty(dst_account);
163 + txt_utf8_empty(dst_domain);
164 + txt_utf8_empty(dst_sid_str);
165 return false;
166 }
167
159 -bool buffer_sid_to_sid_str_and_name(PSID sid, BUFFER *dst, const char *prefix) {
168 +bool cached_sid_to_buffer_append(PSID sid, BUFFER *dst, const char *prefix) {
169 SID_VALUE *found = lookup_or_convert_user_id_to_name_lookup(sid);
170 size_t added = 0;
171
@@ -165,17 +174,28 @@ bool buffer_sid_to_sid_str_and_name(PSID sid, BUFFER *dst, const char *prefix) {
174 if (prefix && *prefix)
175 buffer_strcat(dst, prefix);
176
168 - buffer_fast_strcat(dst, found->full, found->full_len);
177 + buffer_fast_strcat(dst, string2str(found->full), string_strlen(found->full));
178 added++;
179 }
180 if (found->sid_str) {
181 if (prefix && *prefix)
182 buffer_strcat(dst, prefix);
183
175 - buffer_fast_strcat(dst, found->sid_str, found->sid_str_len);
184 + buffer_fast_strcat(dst, string2str(found->sid_str), string_strlen(found->sid_str));
185 added++;
186 }
187 }
188
189 return added > 0;
190 }
191 +
192 +STRING *cached_sid_fullname_or_sid_str(PSID sid) {
193 + SID_VALUE *found = lookup_or_convert_user_id_to_name_lookup(sid);
194 + if(found) {
195 + if(found->full) return string_dup(found->full);
196 + return string_dup(found->sid_str);
197 + }
198 + return NULL;
199 +}
200 +
201 +#endif
\ No newline at end of file
src/libnetdata/os/system-maps/cached-sid-username.h new
+17
@@ -0,0 +1,17 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#ifndef NETDATA_CACHED_SID_USERNAME_H
4 +#define NETDATA_CACHED_SID_USERNAME_H
5 +
6 +#include "../../libnetdata.h"
7 +
8 +#if defined(OS_WINDOWS)
9 +#include "../../string/utf8.h"
10 +
11 +bool cached_sid_to_account_domain_sidstr(void *sid, TXT_UTF8 *dst_account, TXT_UTF8 *dst_domain, TXT_UTF8 *dst_sid_str);
12 +bool cached_sid_to_buffer_append(void *sid, BUFFER *dst, const char *prefix);
13 +void cached_sid_username_init(void);
14 +STRING *cached_sid_fullname_or_sid_str(void *sid);
15 +#endif
16 +
17 +#endif //NETDATA_CACHED_SID_USERNAME_H
src/libnetdata/os/system-maps/cached-uid-username.c new
+148
@@ -0,0 +1,148 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include "cached-uid-username.h"
4 +
5 +// --------------------------------------------------------------------------------------------------------------------
6 +// hashtable for caching uid to username mappings
7 +// key is the uid, value is username (STRING)
8 +
9 +#define SIMPLE_HASHTABLE_KEY_TYPE uid_t
10 +#define SIMPLE_HASHTABLE_VALUE_TYPE CACHED_USERNAME
11 +#define SIMPLE_HASHTABLE_VALUE2KEY_FUNCTION cached_username_to_uid_ptr
12 +#define SIMPLE_HASHTABLE_COMPARE_KEYS_FUNCTION compar_uid_ptr
13 +#define SIMPLE_HASHTABLE_NAME _USERNAMES_CACHE
14 +#include "libnetdata/simple_hashtable.h"
15 +
16 +static struct {
17 + uint32_t version;
18 + bool initialized;
19 + SPINLOCK spinlock;
20 + SIMPLE_HASHTABLE_USERNAMES_CACHE ht;
21 +} uc = {
22 + .spinlock = NETDATA_SPINLOCK_INITIALIZER,
23 + .ht = { 0 },
24 +};
25 +
26 +static uid_t *cached_username_to_uid_ptr(CACHED_USERNAME *cu) {
27 + return &cu->uid;
28 +}
29 +
30 +static bool compar_uid_ptr(uid_t *a, uid_t *b) {
31 + return *a == *b;
32 +}
33 +
34 +void cached_username_populate_by_uid(uid_t uid, const char *username, uint32_t version) {
35 + internal_fatal(!uc.initialized, "system-users cache needs to be initialized");
36 + if(!username || !*username) return;
37 +
38 + spinlock_lock(&uc.spinlock);
39 +
40 + XXH64_hash_t hash = XXH3_64bits(&uid, sizeof(uid));
41 + SIMPLE_HASHTABLE_SLOT_USERNAMES_CACHE *sl = simple_hashtable_get_slot_USERNAMES_CACHE(&uc.ht, hash, &uid, true);
42 + CACHED_USERNAME *cu = SIMPLE_HASHTABLE_SLOT_DATA(sl);
43 + if(!cu || (cu->version && version > cu->version)) {
44 + internal_fatal(cu && cu->uid != uid, "invalid uid matched from cache");
45 +
46 + if(cu)
47 + string_freez(cu->username);
48 + else
49 + cu = callocz(1, sizeof(*cu));
50 +
51 + cu->version = version;
52 + cu->uid = uid;
53 + cu->username = string_strdupz(username);
54 + simple_hashtable_set_slot_USERNAMES_CACHE(&uc.ht, sl, hash, cu);
55 + }
56 +
57 + spinlock_unlock(&uc.spinlock);
58 +}
59 +
60 +CACHED_USERNAME cached_username_get_by_uid(uid_t uid) {
61 + internal_fatal(!uc.initialized, "system-users cache needs to be initialized");
62 +
63 + spinlock_lock(&uc.spinlock);
64 +
65 + XXH64_hash_t hash = XXH3_64bits(&uid, sizeof(uid));
66 + SIMPLE_HASHTABLE_SLOT_USERNAMES_CACHE *sl = simple_hashtable_get_slot_USERNAMES_CACHE(&uc.ht, hash, &uid, true);
67 + CACHED_USERNAME *cu = SIMPLE_HASHTABLE_SLOT_DATA(sl);
68 + if(!cu) {
69 + cu = callocz(1, sizeof(*cu));
70 +
71 + static char tmp[1024]; // we are inside a global spinlock - it is ok to be static
72 + struct passwd pw, *result = NULL;
73 +
74 + if (getpwuid_r(uid, &pw, tmp, sizeof(tmp), &result) != 0 || !result || !pw.pw_name || !(*pw.pw_name)) {
75 + char name[UINT64_MAX_LENGTH];
76 + print_uint64(name, uid);
77 + cu->username = string_strdupz(name);
78 + }
79 + else
80 + cu->username = string_strdupz(pw.pw_name);
81 +
82 + cu->uid = uid;
83 + simple_hashtable_set_slot_USERNAMES_CACHE(&uc.ht, sl, hash, cu);
84 + }
85 +
86 + internal_fatal(cu->uid != uid, "invalid uid matched from cache");
87 +
88 + CACHED_USERNAME rc = {
89 + .version = cu->version,
90 + .uid = cu->uid,
91 + .username = string_dup(cu->username),
92 + };
93 +
94 + spinlock_unlock(&uc.spinlock);
95 + return rc;
96 +}
97 +
98 +void cached_username_release(CACHED_USERNAME cu) {
99 + string_freez(cu.username);
100 +}
101 +
102 +void cached_usernames_init(void) {
103 + if(uc.initialized) return;
104 + uc.initialized = true;
105 +
106 + spinlock_init(&uc.spinlock);
107 + simple_hashtable_init_USERNAMES_CACHE(&uc.ht, 100);
108 +}
109 +
110 +void cached_usernames_destroy(void) {
111 + if(!uc.initialized) return;
112 +
113 + spinlock_lock(&uc.spinlock);
114 +
115 + for(SIMPLE_HASHTABLE_SLOT_USERNAMES_CACHE *sl = simple_hashtable_first_read_only_USERNAMES_CACHE(&uc.ht);
116 + sl;
117 + sl = simple_hashtable_next_read_only_USERNAMES_CACHE(&uc.ht, sl)) {
118 + CACHED_USERNAME *u = SIMPLE_HASHTABLE_SLOT_DATA(sl);
119 + if(u) {
120 + string_freez(u->username);
121 + freez(u);
122 + // simple_hashtable_del_slot_USERNAMES_CACHE(&uc.ht, sl);
123 + }
124 + }
125 +
126 + simple_hashtable_destroy_USERNAMES_CACHE(&uc.ht);
127 + uc.initialized = false;
128 +}
129 +
130 +void cached_usernames_delete_old_versions(uint32_t version) {
131 + if(!uc.initialized) return;
132 +
133 + spinlock_lock(&uc.spinlock);
134 +
135 + for(SIMPLE_HASHTABLE_SLOT_USERNAMES_CACHE *sl = simple_hashtable_first_read_only_USERNAMES_CACHE(&uc.ht);
136 + sl;
137 + sl = simple_hashtable_next_read_only_USERNAMES_CACHE(&uc.ht, sl)) {
138 + CACHED_USERNAME *cu = SIMPLE_HASHTABLE_SLOT_DATA(sl);
139 + if(cu && cu->version && cu->version < version) {
140 + string_freez(cu->username);
141 + freez(cu);
142 + simple_hashtable_del_slot_USERNAMES_CACHE(&uc.ht, sl);
143 + }
144 + }
145 +
146 + simple_hashtable_destroy_USERNAMES_CACHE(&uc.ht);
147 + uc.initialized = false;
148 +}
src/libnetdata/os/system-maps/cached-uid-username.h new
+24
@@ -0,0 +1,24 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#ifndef NETDATA_CACHED_UID_USERNAME_H
4 +#define NETDATA_CACHED_UID_USERNAME_H
5 +
6 +#include "libnetdata/libnetdata.h"
7 +
8 +struct netdata_string;
9 +
10 +typedef struct {
11 + uint32_t version;
12 + uid_t uid;
13 + struct netdata_string *username;
14 +} CACHED_USERNAME;
15 +
16 +void cached_username_populate_by_uid(uid_t uid, const char *username, uint32_t version);
17 +CACHED_USERNAME cached_username_get_by_uid(uid_t uid);
18 +void cached_username_release(CACHED_USERNAME cu);
19 +
20 +void cached_usernames_init(void);
21 +void cached_usernames_destroy(void);
22 +void cached_usernames_delete_old_versions(uint32_t version);
23 +
24 +#endif //NETDATA_CACHED_UID_USERNAME_H
src/libnetdata/os/system-maps/system-services.h renamed
+1 -1
@@ -8,7 +8,7 @@
8
9 // --------------------------------------------------------------------------------------------------------------------
10 // hashtable for caching port and protocol to service name mappings
11 -// key is the combination of protocol and port packed into a uint64_t, value is service name (STRING)
11 +// key is the combination of protocol and port packed into an uint64_t, value is service name (STRING)
12
13 #define SIMPLE_HASHTABLE_VALUE_TYPE STRING
14 #define SIMPLE_HASHTABLE_NAME _SERVICENAMES_CACHE
src/libnetdata/os/windows-perflib/perflib.c
+1 -1
@@ -398,7 +398,7 @@ static inline BOOL getEncodedStringToUTF8(char *dst, size_t dst_len, DWORD CodeP
398 }
399 else {
400 tempBuffer = unicode;
401 - charsCopied = any_to_utf16(CodePage, unicode, _countof(unicode), start, (int)length);
401 + charsCopied = any_to_utf16(CodePage, unicode, _countof(unicode), start, (int)length, NULL);
402 if(!charsCopied) return FALSE;
403 }
404
src/libnetdata/socket/security.h
+1 -21
@@ -1,5 +1,5 @@
1 #ifndef NETDATA_SECURITY_H
2 -# define NETDATA_SECURITY_H
2 +#define NETDATA_SECURITY_H
3
4 typedef enum __attribute__((packed)) {
5 NETDATA_SSL_STATE_NOT_SSL = 1, // This connection is not SSL
@@ -12,26 +12,6 @@ typedef enum __attribute__((packed)) {
12 #define NETDATA_SSL_STREAMING_SENDER_CTX 1
13 #define NETDATA_SSL_EXPORTING_CTX 2
14
15 -#define OPENSSL_VERSION_095 0x00905100L
16 -#define OPENSSL_VERSION_097 0x0907000L
17 -#define OPENSSL_VERSION_110 0x10100000L
18 -#define OPENSSL_VERSION_111 0x10101000L
19 -#define OPENSSL_VERSION_300 0x30000000L
20 -
21 -# include <openssl/ssl.h>
22 -# include <openssl/rand.h>
23 -# include <openssl/err.h>
24 -# include <openssl/evp.h>
25 -# include <openssl/pem.h>
26 -# if (SSLEAY_VERSION_NUMBER >= OPENSSL_VERSION_097) && (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110)
27 -# include <openssl/conf.h>
28 -# endif
29 -
30 -#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_300
31 -#include <openssl/core_names.h>
32 -#include <openssl/decoder.h>
33 -#endif
34 -
15 typedef struct netdata_ssl {
16 SSL *conn; // SSL connection
17 NETDATA_SSL_STATE state; // The state for SSL connection
src/libnetdata/socket/socket.c
+10 -10
@@ -576,7 +576,7 @@ static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition,
576 char buffer2[10 + 1];
577 snprintfz(buffer2, 10, "%d", default_port);
578
579 - char *ip = buffer, *port = buffer2, *interface = "", *portconfig;
579 + char *ip = buffer, *port = buffer2, *iface = "", *portconfig;
580
581 int protocol = IPPROTO_TCP, socktype = SOCK_STREAM;
582 const char *protocol_str = "tcp";
@@ -631,7 +631,7 @@ static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition,
631 if(*e == '%') {
632 *e = '\0';
633 e++;
634 - interface = e;
634 + iface = e;
635 while(*e && *e != ':' && *e != '=') e++;
636 }
637
@@ -668,13 +668,13 @@ static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition,
668 }
669
670 uint32_t scope_id = 0;
671 - if(*interface) {
672 - scope_id = if_nametoindex(interface);
671 + if(*iface) {
672 + scope_id = if_nametoindex(iface);
673 if(!scope_id)
674 nd_log(NDLS_DAEMON, NDLP_ERR,
675 "LISTENER: Cannot find a network interface named '%s'. "
676 "Continuing with limiting the network interface",
677 - interface);
677 + iface);
678 }
679
680 if(!*ip || *ip == '*' || !strcmp(ip, "any") || !strcmp(ip, "all"))
@@ -1035,7 +1035,7 @@ int connect_to_this(const char *definition, int default_port, struct timeval *ti
1035 char default_service[10 + 1];
1036 snprintfz(default_service, 10, "%d", default_port);
1037
1038 - char *host = buffer, *service = default_service, *interface = "";
1038 + char *host = buffer, *service = default_service, *iface = "";
1039 int protocol = IPPROTO_TCP, socktype = SOCK_STREAM;
1040 uint32_t scope_id = 0;
1041
@@ -1074,7 +1074,7 @@ int connect_to_this(const char *definition, int default_port, struct timeval *ti
1074 if(*e == '%') {
1075 *e = '\0';
1076 e++;
1077 - interface = e;
1077 + iface = e;
1078 while(*e && *e != ':') e++;
1079 }
1080
@@ -1092,12 +1092,12 @@ int connect_to_this(const char *definition, int default_port, struct timeval *ti
1092 return -1;
1093 }
1094
1095 - if(*interface) {
1096 - scope_id = if_nametoindex(interface);
1095 + if(*iface) {
1096 + scope_id = if_nametoindex(iface);
1097 if(!scope_id)
1098 nd_log(NDLS_DAEMON, NDLP_ERR,
1099 "Cannot find a network interface named '%s'. Continuing with limiting the network interface",
1100 - interface);
1100 + iface);
1101 }
1102
1103 if(!*service)
src/libnetdata/string/utf8.c
+225 -7
@@ -13,9 +13,12 @@
13 * 3. Always return the number of wide characters written, including the null terminator
14 */
15
16 -size_t any_to_utf16(uint32_t CodePage, wchar_t *dst, size_t dst_size, const char *src, int src_len) {
16 +size_t any_to_utf16(uint32_t CodePage, wchar_t *dst, size_t dst_size, const char *src, int src_len, bool *truncated) {
17 if(!src || src_len == 0) {
18 // invalid input
19 + if(truncated)
20 + *truncated = true;
21 +
22 if(dst && dst_size)
23 *dst = L'\0';
24 return 0;
@@ -23,6 +26,10 @@ size_t any_to_utf16(uint32_t CodePage, wchar_t *dst, size_t dst_size, const char
26
27 if(!dst || !dst_size) {
28 // the caller wants to know the buffer to allocate for the conversion
29 +
30 + if(truncated)
31 + *truncated = true;
32 +
33 int required = MultiByteToWideChar(CodePage, 0, src, src_len, NULL, 0);
34 if(required <= 0) return 0; // error in the conversion
35
@@ -34,6 +41,9 @@ size_t any_to_utf16(uint32_t CodePage, wchar_t *dst, size_t dst_size, const char
41 // do the conversion directly to the destination buffer
42 int rc = MultiByteToWideChar(CodePage, 0, src, src_len, dst, (int)dst_size);
43 if(rc <= 0) {
44 + if(truncated)
45 + *truncated = true;
46 +
47 // conversion failed, let's see why...
48 DWORD status = GetLastError();
49 if(status == ERROR_INSUFFICIENT_BUFFER) {
@@ -81,9 +91,17 @@ size_t any_to_utf16(uint32_t CodePage, wchar_t *dst, size_t dst_size, const char
91
92 size_t len = rc;
93
94 + if(truncated)
95 + *truncated = false;
96 +
97 if(len >= dst_size) {
85 - // truncate it to fit the null
86 - dst[dst_size - 1] = L'\0';
98 + if(dst[dst_size - 1] != L'\0') {
99 + if (truncated)
100 + *truncated = true;
101 +
102 + // Truncate it to fit the null terminator
103 + dst[dst_size - 1] = L'\0';
104 + }
105 return dst_size;
106 }
107
@@ -106,16 +124,24 @@ size_t any_to_utf16(uint32_t CodePage, wchar_t *dst, size_t dst_size, const char
124 * 3. Always return the number of bytes written, including the null terminator
125 */
126
109 -size_t utf16_to_utf8(char *dst, size_t dst_size, const wchar_t *src, int src_len) {
127 +size_t utf16_to_utf8(char *dst, size_t dst_size, const wchar_t *src, int src_len, bool *truncated) {
128 if (!src || src_len == 0) {
129 // invalid input
130 + if(truncated)
131 + *truncated = true;
132 +
133 if(dst && dst_size)
113 - *dst = L'\0';
134 + *dst = '\0';
135 +
136 return 0;
137 }
138
139 if (!dst || dst_size == 0) {
140 // The caller wants to know the buffer size required for the conversion
141 +
142 + if(truncated)
143 + *truncated = true;
144 +
145 int required = WideCharToMultiByte(CP_UTF8, 0, src, src_len, NULL, 0, NULL, NULL);
146 if (required <= 0) return 0; // error in the conversion
147
@@ -126,6 +152,9 @@ size_t utf16_to_utf8(char *dst, size_t dst_size, const wchar_t *src, int src_len
152 // Perform the conversion directly into the destination buffer
153 int rc = WideCharToMultiByte(CP_UTF8, 0, src, src_len, dst, (int)dst_size, NULL, NULL);
154 if (rc <= 0) {
155 + if(truncated)
156 + *truncated = true;
157 +
158 // Conversion failed, let's see why...
159 DWORD status = GetLastError();
160 if (status == ERROR_INSUFFICIENT_BUFFER) {
@@ -173,9 +202,17 @@ size_t utf16_to_utf8(char *dst, size_t dst_size, const wchar_t *src, int src_len
202
203 size_t len = rc;
204
205 + if(truncated)
206 + *truncated = false;
207 +
208 if (len >= dst_size) {
177 - // Truncate it to fit the null terminator
178 - dst[dst_size - 1] = '\0';
209 + if(dst[dst_size - 1] != '\0') {
210 + if (truncated)
211 + *truncated = true;
212 +
213 + // Truncate it to fit the null terminator
214 + dst[dst_size - 1] = '\0';
215 + }
216 return dst_size;
217 }
218
@@ -189,4 +226,185 @@ size_t utf16_to_utf8(char *dst, size_t dst_size, const wchar_t *src, int src_len
226 // The result is already null-terminated
227 return len;
228 }
229 +
230 +// --------------------------------------------------------------------------------------------------------------------
231 +
232 +size_t txt_compute_new_size(size_t old_size, size_t required_size) {
233 + size_t size = (required_size % 2048 == 0) ? required_size : required_size + 2048;
234 + size = (size / 2048) * 2048;
235 +
236 + if(size < old_size * 2)
237 + size = old_size * 2;
238 +
239 + return size;
240 +}
241 +
242 +// --------------------------------------------------------------------------------------------------------------------
243 +// TXT_UTF8
244 +
245 +void txt_utf8_cleanup(TXT_UTF8 *dst) {
246 + freez(dst->data);
247 + dst->data = NULL;
248 + dst->used = 0;
249 +}
250 +
251 +void txt_utf8_resize(TXT_UTF8 *dst, size_t required_size, bool keep) {
252 + if(required_size <= dst->size)
253 + return;
254 +
255 + size_t new_size = txt_compute_new_size(dst->size, required_size);
256 +
257 + if(keep && dst->data)
258 + dst->data = reallocz(dst->data, new_size);
259 + else {
260 + txt_utf8_cleanup(dst);
261 + dst->data = mallocz(new_size);
262 + dst->used = 0;
263 + }
264 +
265 + dst->size = new_size;
266 +}
267 +
268 +void txt_utf8_empty(TXT_UTF8 *dst) {
269 + txt_utf8_resize(dst, 1, false);
270 + dst->data[0] = '\0';
271 + dst->used = 1;
272 +}
273 +
274 +void txt_utf8_set(TXT_UTF8 *dst, const char *txt, size_t txt_len) {
275 + txt_utf8_resize(dst, dst->used + txt_len + 1, true);
276 + memcpy(dst->data, txt, txt_len);
277 + dst->used = txt_len + 1;
278 + dst->data[dst->used - 1] = '\0';
279 +}
280 +
281 +void txt_utf8_append(TXT_UTF8 *dst, const char *txt, size_t txt_len) {
282 + if(dst->used <= 1) {
283 + // the destination is empty
284 + txt_utf8_set(dst, txt, txt_len);
285 + }
286 + else {
287 + // there is something already in the buffer
288 + txt_utf8_resize(dst, dst->used + txt_len, true);
289 + memcpy(&dst->data[dst->used - 1], txt, txt_len);
290 + dst->used += txt_len; // the null was already counted
291 + dst->data[dst->used - 1] = '\0';
292 + }
293 +}
294 +
295 +// --------------------------------------------------------------------------------------------------------------------
296 +// TXT_UTF16
297 +
298 +void txt_utf16_cleanup(TXT_UTF16 *dst) {
299 + freez(dst->data);
300 +}
301 +
302 +void txt_utf16_resize(TXT_UTF16 *dst, size_t required_size, bool keep) {
303 + if(required_size <= dst->size)
304 + return;
305 +
306 + size_t new_size = txt_compute_new_size(dst->size, required_size);
307 +
308 + if (keep && dst->data) {
309 + dst->data = reallocz(dst->data, new_size * sizeof(wchar_t));
310 + } else {
311 + txt_utf16_cleanup(dst);
312 + dst->data = mallocz(new_size * sizeof(wchar_t));
313 + dst->used = 0;
314 + }
315 +
316 + dst->size = new_size;
317 +}
318 +
319 +void txt_utf16_set(TXT_UTF16 *dst, const wchar_t *txt, size_t txt_len) {
320 + txt_utf16_resize(dst, dst->used + txt_len + 1, true);
321 + memcpy(dst->data, txt, txt_len * sizeof(wchar_t));
322 + dst->used = txt_len + 1;
323 + dst->data[dst->used - 1] = '\0';
324 +}
325 +
326 +void txt_utf16_append(TXT_UTF16 *dst, const wchar_t *txt, size_t txt_len) {
327 + if(dst->used <= 1) {
328 + // the destination is empty
329 + txt_utf16_set(dst, txt, txt_len);
330 + }
331 + else {
332 + // there is something already in the buffer
333 + txt_utf16_resize(dst, dst->used + txt_len, true);
334 + memcpy(&dst->data[dst->used - 1], txt, txt_len * sizeof(wchar_t));
335 + dst->used += txt_len; // the null was already counted
336 + dst->data[dst->used - 1] = '\0';
337 + }
338 +}
339 +
340 +// --------------------------------------------------------------------------------------------------------------------
341 +
342 +bool wchar_to_txt_utf8(TXT_UTF8 *dst, const wchar_t *src, int src_len) {
343 + if(!src || !src_len) {
344 + txt_utf8_empty(dst);
345 + return false;
346 + }
347 +
348 + if(!dst->data && !dst->size) {
349 + size_t size = utf16_to_utf8(NULL, 0, src, src_len, NULL);
350 + if(!size) {
351 + txt_utf8_empty(dst);
352 + return false;
353 + }
354 +
355 + // we +1 here to avoid entering the next condition below
356 + txt_utf8_resize(dst, size, false);
357 + }
358 +
359 + bool truncated = false;
360 + dst->used = utf16_to_utf8(dst->data, dst->size, src, src_len, &truncated);
361 + if(truncated) {
362 + // we need to resize
363 + size_t needed = utf16_to_utf8(NULL, 0, src, src_len, NULL); // find the size needed
364 + if(!needed) {
365 + txt_utf8_empty(dst);
366 + return false;
367 + }
368 +
369 + txt_utf8_resize(dst, needed, false);
370 + dst->used = utf16_to_utf8(dst->data, dst->size, src, src_len, NULL);
371 + }
372 +
373 + // Make sure it is not zero padded at the end
374 + while(dst->used >= 2 && dst->data[dst->used - 2] == 0)
375 + dst->used--;
376 +
377 + internal_fatal(strlen(dst->data) + 1 != dst->used,
378 + "Wrong UTF8 string length");
379 +
380 + return true;
381 +}
382 +
383 +bool txt_utf16_to_utf8(TXT_UTF8 *utf8, TXT_UTF16 *utf16) {
384 + fatal_assert(utf8 && ((utf8->data && utf8->size) || (!utf8->data && !utf8->size)));
385 + fatal_assert(utf16 && ((utf16->data && utf16->size) || (!utf16->data && !utf16->size)));
386 +
387 + // pass the entire utf16 size, including the null terminator
388 + // so that the resulting utf8 message will be null terminated too.
389 + return wchar_to_txt_utf8(utf8, utf16->data, (int)utf16->used - 1);
390 +}
391 +
392 +char *utf16_to_utf8_strdupz(const wchar_t *src, size_t *dst_len) {
393 + size_t size = utf16_to_utf8(NULL, 0, src, -1, NULL);
394 + if (size) {
395 + char *dst = mallocz(size);
396 +
397 + size = utf16_to_utf8(dst, size, src, -1, NULL);
398 + if(dst_len)
399 + *dst_len = size - 1;
400 +
401 + return dst;
402 + }
403 +
404 + if(dst_len)
405 + *dst_len = 0;
406 +
407 + return NULL;
408 +}
409 +
410 #endif
src/libnetdata/string/utf8.h
+57 -4
@@ -3,6 +3,8 @@
3 #ifndef NETDATA_STRING_UTF8_H
4 #define NETDATA_STRING_UTF8_H 1
5
6 +#include "../libnetdata.h"
7 +
8 #define IS_UTF8_BYTE(x) ((uint8_t)(x) & (uint8_t)0x80)
9 #define IS_UTF8_STARTBYTE(x) (IS_UTF8_BYTE(x) && ((uint8_t)(x) & (uint8_t)0x40))
10
@@ -15,16 +17,67 @@
17 // return an always null terminated wide string, truncate to given size if destination is not big enough,
18 // src_len can be -1 use all of it.
19 // returns zero on errors, > 0 otherwise (including the null, even if src is not null terminated).
18 -size_t any_to_utf16(uint32_t CodePage, wchar_t *dst, size_t dst_size, const char *src, int src_len);
20 +size_t any_to_utf16(uint32_t CodePage, wchar_t *dst, size_t dst_size, const char *src, int src_len, bool *truncated);
21
22 // always null terminated, truncated if it does not fit, src_len can be -1 to use all of it.
23 // returns zero on errors, > 0 otherwise (including the null, even if src is not null terminated).
22 -#define utf8_to_utf16(utf16, utf16_count, src, src_len) any_to_utf16(CP_UTF8, utf16, utf16_count, src, src_len)
24 +#define utf8_to_utf16(utf16, utf16_count, src, src_len) any_to_utf16(CP_UTF8, utf16, utf16_count, src, src_len, NULL)
25
26 // always null terminated, truncated if it does not fit, src_len can be -1 to use all of it.
27 // returns zero on errors, > 0 otherwise (including the null, even if src is not null terminated).
26 -size_t utf16_to_utf8(char *dst, size_t dst_size, const wchar_t *src, int src_len);
28 +size_t utf16_to_utf8(char *dst, size_t dst_size, const wchar_t *src, int src_len, bool *truncated);
29
28 -#endif
30 +// --------------------------------------------------------------------------------------------------------------------
31 +// TXT_UTF8
32 +
33 +typedef enum __attribute__((packed)) {
34 + TXT_SOURCE_UNKNOWN = 0,
35 + TXT_SOURCE_PROVIDER,
36 + TXT_SOURCE_FIELD_CACHE,
37 + TXT_SOURCE_EVENT_LOG,
38 + TXT_SOURCE_HARDCODED,
39 +
40 + // terminator
41 + TXT_SOURCE_MAX,
42 +} TXT_SOURCE;
43 +
44 +typedef struct {
45 + char *data;
46 + uint32_t size; // the allocated size of data buffer
47 + uint32_t used; // the used size of the data buffer (including null terminators, if any)
48 + TXT_SOURCE src;
49 +} TXT_UTF8;
50 +
51 +void txt_utf8_append(TXT_UTF8 *dst, const char *txt, size_t txt_len);
52 +void txt_utf8_set(TXT_UTF8 *dst, const char *txt, size_t txt_len);
53 +void txt_utf8_empty(TXT_UTF8 *dst);
54 +void txt_utf8_resize(TXT_UTF8 *dst, size_t required_size, bool keep);
55 +void txt_utf8_cleanup(TXT_UTF8 *dst);
56 +
57 +// --------------------------------------------------------------------------------------------------------------------
58 +// TXT_UTF16
59 +
60 +typedef struct {
61 + wchar_t *data;
62 + uint32_t size; // the allocated size of data buffer
63 + uint32_t used; // the used size of the data buffer (including null terminators, if any)
64 +} TXT_UTF16;
65 +
66 +void txt_utf16_cleanup(TXT_UTF16 *dst);
67 +void txt_utf16_resize(TXT_UTF16 *dst, size_t required_size, bool keep);
68 +void txt_utf16_set(TXT_UTF16 *dst, const wchar_t *txt, size_t txt_len);
69 +void txt_utf16_append(TXT_UTF16 *dst, const wchar_t *txt, size_t txt_len);
70 +
71 +// --------------------------------------------------------------------------------------------------------------------
72 +
73 +size_t txt_compute_new_size(size_t old_size, size_t required_size);
74 +
75 +bool txt_utf16_to_utf8(TXT_UTF8 *utf8, TXT_UTF16 *utf16);
76 +bool wchar_to_txt_utf8(TXT_UTF8 *dst, const wchar_t *src, int src_len);
77 +char *utf16_to_utf8_strdupz(const wchar_t *src, size_t *dst_len);
78 +
79 +// --------------------------------------------------------------------------------------------------------------------
80 +
81 +#endif // OS_WINDOWS
82
83 #endif /* NETDATA_STRING_UTF8_H */