| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #include "systemd-internals.h" |
| 4 | |
| 5 | const char *errno_map[] = { |
| 6 | [1] = "1 (EPERM)", // "Operation not permitted", |
| 7 | [2] = "2 (ENOENT)", // "No such file or directory", |
| 8 | [3] = "3 (ESRCH)", // "No such process", |
| 9 | [4] = "4 (EINTR)", // "Interrupted system call", |
| 10 | [5] = "5 (EIO)", // "Input/output error", |
| 11 | [6] = "6 (ENXIO)", // "No such device or address", |
| 12 | [7] = "7 (E2BIG)", // "Argument list too long", |
| 13 | [8] = "8 (ENOEXEC)", // "Exec format error", |
| 14 | [9] = "9 (EBADF)", // "Bad file descriptor", |
| 15 | [10] = "10 (ECHILD)", // "No child processes", |
| 16 | [11] = "11 (EAGAIN)", // "Resource temporarily unavailable", |
| 17 | [12] = "12 (ENOMEM)", // "Cannot allocate memory", |
| 18 | [13] = "13 (EACCES)", // "Permission denied", |
| 19 | [14] = "14 (EFAULT)", // "Bad address", |
| 20 | [15] = "15 (ENOTBLK)", // "Block device required", |
| 21 | [16] = "16 (EBUSY)", // "Device or resource busy", |
| 22 | [17] = "17 (EEXIST)", // "File exists", |
| 23 | [18] = "18 (EXDEV)", // "Invalid cross-device link", |
| 24 | [19] = "19 (ENODEV)", // "No such device", |
| 25 | [20] = "20 (ENOTDIR)", // "Not a directory", |
| 26 | [21] = "21 (EISDIR)", // "Is a directory", |
| 27 | [22] = "22 (EINVAL)", // "Invalid argument", |
| 28 | [23] = "23 (ENFILE)", // "Too many open files in system", |
| 29 | [24] = "24 (EMFILE)", // "Too many open files", |
| 30 | [25] = "25 (ENOTTY)", // "Inappropriate ioctl for device", |
| 31 | [26] = "26 (ETXTBSY)", // "Text file busy", |
| 32 | [27] = "27 (EFBIG)", // "File too large", |
| 33 | [28] = "28 (ENOSPC)", // "No space left on device", |
| 34 | [29] = "29 (ESPIPE)", // "Illegal seek", |
| 35 | [30] = "30 (EROFS)", // "Read-only file system", |
| 36 | [31] = "31 (EMLINK)", // "Too many links", |
| 37 | [32] = "32 (EPIPE)", // "Broken pipe", |
| 38 | [33] = "33 (EDOM)", // "Numerical argument out of domain", |
| 39 | [34] = "34 (ERANGE)", // "Numerical result out of range", |
| 40 | [35] = "35 (EDEADLK)", // "Resource deadlock avoided", |
| 41 | [36] = "36 (ENAMETOOLONG)", // "File name too long", |
| 42 | [37] = "37 (ENOLCK)", // "No locks available", |
| 43 | [38] = "38 (ENOSYS)", // "Function not implemented", |
| 44 | [39] = "39 (ENOTEMPTY)", // "Directory not empty", |
| 45 | [40] = "40 (ELOOP)", // "Too many levels of symbolic links", |
| 46 | [42] = "42 (ENOMSG)", // "No message of desired type", |
| 47 | [43] = "43 (EIDRM)", // "Identifier removed", |
| 48 | [44] = "44 (ECHRNG)", // "Channel number out of range", |
| 49 | [45] = "45 (EL2NSYNC)", // "Level 2 not synchronized", |
| 50 | [46] = "46 (EL3HLT)", // "Level 3 halted", |
| 51 | [47] = "47 (EL3RST)", // "Level 3 reset", |
| 52 | [48] = "48 (ELNRNG)", // "Link number out of range", |
| 53 | [49] = "49 (EUNATCH)", // "Protocol driver not attached", |
| 54 | [50] = "50 (ENOCSI)", // "No CSI structure available", |
| 55 | [51] = "51 (EL2HLT)", // "Level 2 halted", |
| 56 | [52] = "52 (EBADE)", // "Invalid exchange", |
| 57 | [53] = "53 (EBADR)", // "Invalid request descriptor", |
| 58 | [54] = "54 (EXFULL)", // "Exchange full", |
| 59 | [55] = "55 (ENOANO)", // "No anode", |
| 60 | [56] = "56 (EBADRQC)", // "Invalid request code", |
| 61 | [57] = "57 (EBADSLT)", // "Invalid slot", |
| 62 | [59] = "59 (EBFONT)", // "Bad font file format", |
| 63 | [60] = "60 (ENOSTR)", // "Device not a stream", |
| 64 | [61] = "61 (ENODATA)", // "No data available", |
| 65 | [62] = "62 (ETIME)", // "Timer expired", |
| 66 | [63] = "63 (ENOSR)", // "Out of streams resources", |
| 67 | [64] = "64 (ENONET)", // "Machine is not on the network", |
| 68 | [65] = "65 (ENOPKG)", // "Package not installed", |
| 69 | [66] = "66 (EREMOTE)", // "Object is remote", |
| 70 | [67] = "67 (ENOLINK)", // "Link has been severed", |
| 71 | [68] = "68 (EADV)", // "Advertise error", |
| 72 | [69] = "69 (ESRMNT)", // "Srmount error", |
| 73 | [70] = "70 (ECOMM)", // "Communication error on send", |
| 74 | [71] = "71 (EPROTO)", // "Protocol error", |
| 75 | [72] = "72 (EMULTIHOP)", // "Multihop attempted", |
| 76 | [73] = "73 (EDOTDOT)", // "RFS specific error", |
| 77 | [74] = "74 (EBADMSG)", // "Bad message", |
| 78 | [75] = "75 (EOVERFLOW)", // "Value too large for defined data type", |
| 79 | [76] = "76 (ENOTUNIQ)", // "Name not unique on network", |
| 80 | [77] = "77 (EBADFD)", // "File descriptor in bad state", |
| 81 | [78] = "78 (EREMCHG)", // "Remote address changed", |
| 82 | [79] = "79 (ELIBACC)", // "Can not access a needed shared library", |
| 83 | [80] = "80 (ELIBBAD)", // "Accessing a corrupted shared library", |
| 84 | [81] = "81 (ELIBSCN)", // ".lib section in a.out corrupted", |
| 85 | [82] = "82 (ELIBMAX)", // "Attempting to link in too many shared libraries", |
| 86 | [83] = "83 (ELIBEXEC)", // "Cannot exec a shared library directly", |
| 87 | [84] = "84 (EILSEQ)", // "Invalid or incomplete multibyte or wide character", |
| 88 | [85] = "85 (ERESTART)", // "Interrupted system call should be restarted", |
| 89 | [86] = "86 (ESTRPIPE)", // "Streams pipe error", |
| 90 | [87] = "87 (EUSERS)", // "Too many users", |
| 91 | [88] = "88 (ENOTSOCK)", // "Socket operation on non-socket", |
| 92 | [89] = "89 (EDESTADDRREQ)", // "Destination address required", |
| 93 | [90] = "90 (EMSGSIZE)", // "Message too long", |
| 94 | [91] = "91 (EPROTOTYPE)", // "Protocol wrong type for socket", |
| 95 | [92] = "92 (ENOPROTOOPT)", // "Protocol not available", |
| 96 | [93] = "93 (EPROTONOSUPPORT)", // "Protocol not supported", |
| 97 | [94] = "94 (ESOCKTNOSUPPORT)", // "Socket type not supported", |
| 98 | [95] = "95 (ENOTSUP)", // "Operation not supported", |
| 99 | [96] = "96 (EPFNOSUPPORT)", // "Protocol family not supported", |
| 100 | [97] = "97 (EAFNOSUPPORT)", // "Address family not supported by protocol", |
| 101 | [98] = "98 (EADDRINUSE)", // "Address already in use", |
| 102 | [99] = "99 (EADDRNOTAVAIL)", // "Cannot assign requested address", |
| 103 | [100] = "100 (ENETDOWN)", // "Network is down", |
| 104 | [101] = "101 (ENETUNREACH)", // "Network is unreachable", |
| 105 | [102] = "102 (ENETRESET)", // "Network dropped connection on reset", |
| 106 | [103] = "103 (ECONNABORTED)", // "Software caused connection abort", |
| 107 | [104] = "104 (ECONNRESET)", // "Connection reset by peer", |
| 108 | [105] = "105 (ENOBUFS)", // "No buffer space available", |
| 109 | [106] = "106 (EISCONN)", // "Transport endpoint is already connected", |
| 110 | [107] = "107 (ENOTCONN)", // "Transport endpoint is not connected", |
| 111 | [108] = "108 (ESHUTDOWN)", // "Cannot send after transport endpoint shutdown", |
| 112 | [109] = "109 (ETOOMANYREFS)", // "Too many references: cannot splice", |
| 113 | [110] = "110 (ETIMEDOUT)", // "Connection timed out", |
| 114 | [111] = "111 (ECONNREFUSED)", // "Connection refused", |
| 115 | [112] = "112 (EHOSTDOWN)", // "Host is down", |
| 116 | [113] = "113 (EHOSTUNREACH)", // "No route to host", |
| 117 | [114] = "114 (EALREADY)", // "Operation already in progress", |
| 118 | [115] = "115 (EINPROGRESS)", // "Operation now in progress", |
| 119 | [116] = "116 (ESTALE)", // "Stale file handle", |
| 120 | [117] = "117 (EUCLEAN)", // "Structure needs cleaning", |
| 121 | [118] = "118 (ENOTNAM)", // "Not a XENIX named type file", |
| 122 | [119] = "119 (ENAVAIL)", // "No XENIX semaphores available", |
| 123 | [120] = "120 (EISNAM)", // "Is a named type file", |
| 124 | [121] = "121 (EREMOTEIO)", // "Remote I/O error", |
| 125 | [122] = "122 (EDQUOT)", // "Disk quota exceeded", |
| 126 | [123] = "123 (ENOMEDIUM)", // "No medium found", |
| 127 | [124] = "124 (EMEDIUMTYPE)", // "Wrong medium type", |
| 128 | [125] = "125 (ECANCELED)", // "Operation canceled", |
| 129 | [126] = "126 (ENOKEY)", // "Required key not available", |
| 130 | [127] = "127 (EKEYEXPIRED)", // "Key has expired", |
| 131 | [128] = "128 (EKEYREVOKED)", // "Key has been revoked", |
| 132 | [129] = "129 (EKEYREJECTED)", // "Key was rejected by service", |
| 133 | [130] = "130 (EOWNERDEAD)", // "Owner died", |
| 134 | [131] = "131 (ENOTRECOVERABLE)", // "State not recoverable", |
| 135 | [132] = "132 (ERFKILL)", // "Operation not possible due to RF-kill", |
| 136 | [133] = "133 (EHWPOISON)", // "Memory page has hardware error", |
| 137 | }; |
| 138 | |
| 139 | const char *linux_capabilities[] = { |
| 140 | [CAP_CHOWN] = "CHOWN", |
| 141 | [CAP_DAC_OVERRIDE] = "DAC_OVERRIDE", |
| 142 | [CAP_DAC_READ_SEARCH] = "DAC_READ_SEARCH", |
| 143 | [CAP_FOWNER] = "FOWNER", |
| 144 | [CAP_FSETID] = "FSETID", |
| 145 | [CAP_KILL] = "KILL", |
| 146 | [CAP_SETGID] = "SETGID", |
| 147 | [CAP_SETUID] = "SETUID", |
| 148 | [CAP_SETPCAP] = "SETPCAP", |
| 149 | [CAP_LINUX_IMMUTABLE] = "LINUX_IMMUTABLE", |
| 150 | [CAP_NET_BIND_SERVICE] = "NET_BIND_SERVICE", |
| 151 | [CAP_NET_BROADCAST] = "NET_BROADCAST", |
| 152 | [CAP_NET_ADMIN] = "NET_ADMIN", |
| 153 | [CAP_NET_RAW] = "NET_RAW", |
| 154 | [CAP_IPC_LOCK] = "IPC_LOCK", |
| 155 | [CAP_IPC_OWNER] = "IPC_OWNER", |
| 156 | [CAP_SYS_MODULE] = "SYS_MODULE", |
| 157 | [CAP_SYS_RAWIO] = "SYS_RAWIO", |
| 158 | [CAP_SYS_CHROOT] = "SYS_CHROOT", |
| 159 | [CAP_SYS_PTRACE] = "SYS_PTRACE", |
| 160 | [CAP_SYS_PACCT] = "SYS_PACCT", |
| 161 | [CAP_SYS_ADMIN] = "SYS_ADMIN", |
| 162 | [CAP_SYS_BOOT] = "SYS_BOOT", |
| 163 | [CAP_SYS_NICE] = "SYS_NICE", |
| 164 | [CAP_SYS_RESOURCE] = "SYS_RESOURCE", |
| 165 | [CAP_SYS_TIME] = "SYS_TIME", |
| 166 | [CAP_SYS_TTY_CONFIG] = "SYS_TTY_CONFIG", |
| 167 | [CAP_MKNOD] = "MKNOD", |
| 168 | [CAP_LEASE] = "LEASE", |
| 169 | [CAP_AUDIT_WRITE] = "AUDIT_WRITE", |
| 170 | [CAP_AUDIT_CONTROL] = "AUDIT_CONTROL", |
| 171 | [CAP_SETFCAP] = "SETFCAP", |
| 172 | [CAP_MAC_OVERRIDE] = "MAC_OVERRIDE", |
| 173 | [CAP_MAC_ADMIN] = "MAC_ADMIN", |
| 174 | [CAP_SYSLOG] = "SYSLOG", |
| 175 | [CAP_WAKE_ALARM] = "WAKE_ALARM", |
| 176 | [CAP_BLOCK_SUSPEND] = "BLOCK_SUSPEND", |
| 177 | [37 /*CAP_AUDIT_READ*/] = "AUDIT_READ", |
| 178 | [38 /*CAP_PERFMON*/] = "PERFMON", |
| 179 | [39 /*CAP_BPF*/] = "BPF", |
| 180 | [40 /* CAP_CHECKPOINT_RESTORE */] = "CHECKPOINT_RESTORE", |
| 181 | }; |
| 182 | |
| 183 | static const char *syslog_facility_to_name(int facility) |
| 184 | { |
| 185 | switch (facility) { |
| 186 | case LOG_FAC(LOG_KERN): |
| 187 | return "kern"; |
| 188 | case LOG_FAC(LOG_USER): |
| 189 | return "user"; |
| 190 | case LOG_FAC(LOG_MAIL): |
| 191 | return "mail"; |
| 192 | case LOG_FAC(LOG_DAEMON): |
| 193 | return "daemon"; |
| 194 | case LOG_FAC(LOG_AUTH): |
| 195 | return "auth"; |
| 196 | case LOG_FAC(LOG_SYSLOG): |
| 197 | return "syslog"; |
| 198 | case LOG_FAC(LOG_LPR): |
| 199 | return "lpr"; |
| 200 | case LOG_FAC(LOG_NEWS): |
| 201 | return "news"; |
| 202 | case LOG_FAC(LOG_UUCP): |
| 203 | return "uucp"; |
| 204 | case LOG_FAC(LOG_CRON): |
| 205 | return "cron"; |
| 206 | case LOG_FAC(LOG_AUTHPRIV): |
| 207 | return "authpriv"; |
| 208 | case LOG_FAC(LOG_FTP): |
| 209 | return "ftp"; |
| 210 | case LOG_FAC(LOG_LOCAL0): |
| 211 | return "local0"; |
| 212 | case LOG_FAC(LOG_LOCAL1): |
| 213 | return "local1"; |
| 214 | case LOG_FAC(LOG_LOCAL2): |
| 215 | return "local2"; |
| 216 | case LOG_FAC(LOG_LOCAL3): |
| 217 | return "local3"; |
| 218 | case LOG_FAC(LOG_LOCAL4): |
| 219 | return "local4"; |
| 220 | case LOG_FAC(LOG_LOCAL5): |
| 221 | return "local5"; |
| 222 | case LOG_FAC(LOG_LOCAL6): |
| 223 | return "local6"; |
| 224 | case LOG_FAC(LOG_LOCAL7): |
| 225 | return "local7"; |
| 226 | default: |
| 227 | return NULL; |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | static const char *syslog_priority_to_name(int priority) |
| 232 | { |
| 233 | switch (priority) { |
| 234 | case LOG_ALERT: |
| 235 | return "alert"; |
| 236 | case LOG_CRIT: |
| 237 | return "critical"; |
| 238 | case LOG_DEBUG: |
| 239 | return "debug"; |
| 240 | case LOG_EMERG: |
| 241 | return "panic"; |
| 242 | case LOG_ERR: |
| 243 | return "error"; |
| 244 | case LOG_INFO: |
| 245 | return "info"; |
| 246 | case LOG_NOTICE: |
| 247 | return "notice"; |
| 248 | case LOG_WARNING: |
| 249 | return "warning"; |
| 250 | default: |
| 251 | return NULL; |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | FACET_ROW_SEVERITY |
| 256 | syslog_priority_to_facet_severity(FACETS *facets __maybe_unused, FACET_ROW *row, void *data __maybe_unused) |
| 257 | { |
| 258 | // same to |
| 259 | // https://github.com/systemd/systemd/blob/aab9e4b2b86905a15944a1ac81e471b5b7075932/src/basic/terminal-util.c#L1501 |
| 260 | // function get_log_colors() |
| 261 | |
| 262 | FACET_ROW_KEY_VALUE *priority_rkv = dictionary_get(row->dict, "PRIORITY"); |
| 263 | if (!priority_rkv || priority_rkv->empty) |
| 264 | return FACET_ROW_SEVERITY_NORMAL; |
| 265 | |
| 266 | int priority = str2i(buffer_tostring(priority_rkv->wb)); |
| 267 | |
| 268 | if (priority <= LOG_ERR) |
| 269 | return FACET_ROW_SEVERITY_CRITICAL; |
| 270 | |
| 271 | else if (priority <= LOG_WARNING) |
| 272 | return FACET_ROW_SEVERITY_WARNING; |
| 273 | |
| 274 | else if (priority <= LOG_NOTICE) |
| 275 | return FACET_ROW_SEVERITY_NOTICE; |
| 276 | |
| 277 | else if (priority >= LOG_DEBUG) |
| 278 | return FACET_ROW_SEVERITY_DEBUG; |
| 279 | |
| 280 | return FACET_ROW_SEVERITY_NORMAL; |
| 281 | } |
| 282 | |
| 283 | void nd_sd_journal_transform_syslog_facility( |
| 284 | FACETS *facets __maybe_unused, |
| 285 | BUFFER *wb, |
| 286 | FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, |
| 287 | void *data __maybe_unused) |
| 288 | { |
| 289 | const char *v = buffer_tostring(wb); |
| 290 | if (*v && isdigit(*v)) { |
| 291 | int facility = str2i(buffer_tostring(wb)); |
| 292 | const char *name = syslog_facility_to_name(facility); |
| 293 | if (name) { |
| 294 | buffer_flush(wb); |
| 295 | buffer_strcat(wb, name); |
| 296 | } |
| 297 | } |
| 298 | } |
| 299 | |
| 300 | void nd_sd_journal_transform_priority( |
| 301 | FACETS *facets __maybe_unused, |
| 302 | BUFFER *wb, |
| 303 | FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, |
| 304 | void *data __maybe_unused) |
| 305 | { |
| 306 | if (scope == FACETS_TRANSFORM_FACET_SORT) |
| 307 | return; |
| 308 | |
| 309 | const char *v = buffer_tostring(wb); |
| 310 | if (*v && isdigit(*v)) { |
| 311 | int priority = str2i(buffer_tostring(wb)); |
| 312 | const char *name = syslog_priority_to_name(priority); |
| 313 | if (name) { |
| 314 | buffer_flush(wb); |
| 315 | buffer_strcat(wb, name); |
| 316 | } |
| 317 | } |
| 318 | } |
| 319 | |
| 320 | void nd_sd_journal_transform_errno( |
| 321 | FACETS *facets __maybe_unused, |
| 322 | BUFFER *wb, |
| 323 | FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, |
| 324 | void *data __maybe_unused) |
| 325 | { |
| 326 | if (scope == FACETS_TRANSFORM_FACET_SORT) |
| 327 | return; |
| 328 | |
| 329 | const char *v = buffer_tostring(wb); |
| 330 | if (*v && isdigit(*v)) { |
| 331 | unsigned err_no = str2u(buffer_tostring(wb)); |
| 332 | if (err_no > 0 && err_no < sizeof(errno_map) / sizeof(*errno_map)) { |
| 333 | const char *name = errno_map[err_no]; |
| 334 | if (name) { |
| 335 | buffer_flush(wb); |
| 336 | buffer_strcat(wb, name); |
| 337 | } |
| 338 | } |
| 339 | } |
| 340 | } |
| 341 | |
| 342 | DICTIONARY *boot_ids_to_first_ut = NULL; |
| 343 | |
| 344 | void nd_sd_journal_transform_boot_id( |
| 345 | FACETS *facets __maybe_unused, |
| 346 | BUFFER *wb, |
| 347 | FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, |
| 348 | void *data __maybe_unused) |
| 349 | { |
| 350 | const char *boot_id = buffer_tostring(wb); |
| 351 | if (*boot_id && isxdigit(*boot_id)) { |
| 352 | usec_t ut = UINT64_MAX; |
| 353 | usec_t *p_ut = dictionary_get(boot_ids_to_first_ut, boot_id); |
| 354 | if (!p_ut) { |
| 355 | #ifndef HAVE_SD_JOURNAL_RESTART_FIELDS |
| 356 | struct nd_journal_file *njf; |
| 357 | dfe_start_read(nd_journal_files_registry, njf) |
| 358 | { |
| 359 | const char *files[2] = { |
| 360 | [0] = njf_dfe.name, |
| 361 | [1] = NULL, |
| 362 | }; |
| 363 | |
| 364 | sd_journal *j = NULL; |
| 365 | int r = sd_journal_open_files(&j, files, ND_SD_JOURNAL_OPEN_FLAGS); |
| 366 | if (r < 0 || !j) { |
| 367 | internal_error( |
| 368 | true, |
| 369 | "JOURNAL: while looking for the first timestamp of boot_id '%s', " |
| 370 | "sd_journal_open_files('%s') returned %d", |
| 371 | boot_id, |
| 372 | jf_dfe.name, |
| 373 | r); |
| 374 | continue; |
| 375 | } |
| 376 | |
| 377 | ut = nd_journal_file_update_annotation_boot_id(j, njf, boot_id); |
| 378 | sd_journal_close(j); |
| 379 | } |
| 380 | dfe_done(njf); |
| 381 | #endif |
| 382 | } else |
| 383 | ut = *p_ut; |
| 384 | |
| 385 | if (ut && ut != UINT64_MAX) { |
| 386 | char buffer[RFC3339_MAX_LENGTH]; |
| 387 | rfc3339_datetime_ut(buffer, sizeof(buffer), ut, 0, true); |
| 388 | |
| 389 | switch (scope) { |
| 390 | default: |
| 391 | case FACETS_TRANSFORM_DATA: |
| 392 | case FACETS_TRANSFORM_VALUE: |
| 393 | buffer_sprintf(wb, " (%s) ", buffer); |
| 394 | break; |
| 395 | |
| 396 | case FACETS_TRANSFORM_FACET: |
| 397 | case FACETS_TRANSFORM_FACET_SORT: |
| 398 | case FACETS_TRANSFORM_HISTOGRAM: |
| 399 | buffer_flush(wb); |
| 400 | buffer_sprintf(wb, "%s", buffer); |
| 401 | break; |
| 402 | } |
| 403 | } |
| 404 | } |
| 405 | } |
| 406 | |
| 407 | void nd_sd_journal_transform_uid( |
| 408 | FACETS *facets __maybe_unused, |
| 409 | BUFFER *wb, |
| 410 | FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, |
| 411 | void *data __maybe_unused) |
| 412 | { |
| 413 | if (scope == FACETS_TRANSFORM_FACET_SORT) |
| 414 | return; |
| 415 | |
| 416 | const char *v = buffer_tostring(wb); |
| 417 | if (*v && isdigit(*v)) { |
| 418 | uid_t uid = str2i(buffer_tostring(wb)); |
| 419 | CACHED_USERNAME cu = cached_username_get_by_uid(uid); |
| 420 | buffer_contents_replace(wb, string2str(cu.username), string_strlen(cu.username)); |
| 421 | cached_username_release(cu); |
| 422 | } |
| 423 | } |
| 424 | |
| 425 | void nd_sd_journal_transform_gid( |
| 426 | FACETS *facets __maybe_unused, |
| 427 | BUFFER *wb, |
| 428 | FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, |
| 429 | void *data __maybe_unused) |
| 430 | { |
| 431 | if (scope == FACETS_TRANSFORM_FACET_SORT) |
| 432 | return; |
| 433 | |
| 434 | const char *v = buffer_tostring(wb); |
| 435 | if (*v && isdigit(*v)) { |
| 436 | gid_t gid = str2i(buffer_tostring(wb)); |
| 437 | CACHED_GROUPNAME cg = cached_groupname_get_by_gid(gid); |
| 438 | buffer_contents_replace(wb, string2str(cg.groupname), string_strlen(cg.groupname)); |
| 439 | cached_groupname_release(cg); |
| 440 | } |
| 441 | } |
| 442 | |
| 443 | void nd_sd_journal_transform_cap_effective( |
| 444 | FACETS *facets __maybe_unused, |
| 445 | BUFFER *wb, |
| 446 | FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, |
| 447 | void *data __maybe_unused) |
| 448 | { |
| 449 | if (scope == FACETS_TRANSFORM_FACET_SORT) |
| 450 | return; |
| 451 | |
| 452 | const char *v = buffer_tostring(wb); |
| 453 | if (*v && isdigit(*v)) { |
| 454 | uint64_t cap = strtoul(buffer_tostring(wb), NULL, 16); |
| 455 | if (cap) { |
| 456 | buffer_fast_strcat(wb, " (", 2); |
| 457 | for (size_t i = 0, added = 0; i < sizeof(linux_capabilities) / sizeof(linux_capabilities[0]); i++) { |
| 458 | if (linux_capabilities[i] && (cap & (1ULL << i))) { |
| 459 | if (added) |
| 460 | buffer_fast_strcat(wb, " | ", 3); |
| 461 | |
| 462 | buffer_strcat(wb, linux_capabilities[i]); |
| 463 | added++; |
| 464 | } |
| 465 | } |
| 466 | buffer_fast_strcat(wb, ")", 1); |
| 467 | } |
| 468 | } |
| 469 | } |
| 470 | |
| 471 | void nd_sd_journal_transform_timestamp_usec( |
| 472 | FACETS *facets __maybe_unused, |
| 473 | BUFFER *wb, |
| 474 | FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, |
| 475 | void *data __maybe_unused) |
| 476 | { |
| 477 | if (scope == FACETS_TRANSFORM_FACET_SORT) |
| 478 | return; |
| 479 | |
| 480 | const char *v = buffer_tostring(wb); |
| 481 | if (*v && isdigit(*v)) { |
| 482 | uint64_t ut = str2ull(buffer_tostring(wb), NULL); |
| 483 | if (ut) { |
| 484 | char buffer[RFC3339_MAX_LENGTH]; |
| 485 | rfc3339_datetime_ut(buffer, sizeof(buffer), ut, 6, true); |
| 486 | buffer_sprintf(wb, " (%s)", buffer); |
| 487 | } |
| 488 | } |
| 489 | } |
| 490 | |
| 491 | void nd_sd_journal_dynamic_row_id( |
| 492 | FACETS *facets __maybe_unused, |
| 493 | BUFFER *json_array, |
| 494 | FACET_ROW_KEY_VALUE *rkv, |
| 495 | FACET_ROW *row, |
| 496 | void *data __maybe_unused) |
| 497 | { |
| 498 | FACET_ROW_KEY_VALUE *pid_rkv = dictionary_get(row->dict, "_PID"); |
| 499 | const char *pid = pid_rkv ? buffer_tostring(pid_rkv->wb) : FACET_VALUE_UNSET; |
| 500 | |
| 501 | const char *identifier = NULL; |
| 502 | FACET_ROW_KEY_VALUE *container_name_rkv = dictionary_get(row->dict, "CONTAINER_NAME"); |
| 503 | if (container_name_rkv && !container_name_rkv->empty) |
| 504 | identifier = buffer_tostring(container_name_rkv->wb); |
| 505 | |
| 506 | if (!identifier) { |
| 507 | FACET_ROW_KEY_VALUE *syslog_identifier_rkv = dictionary_get(row->dict, "SYSLOG_IDENTIFIER"); |
| 508 | if (syslog_identifier_rkv && !syslog_identifier_rkv->empty) |
| 509 | identifier = buffer_tostring(syslog_identifier_rkv->wb); |
| 510 | |
| 511 | if (!identifier) { |
| 512 | FACET_ROW_KEY_VALUE *comm_rkv = dictionary_get(row->dict, "_COMM"); |
| 513 | if (comm_rkv && !comm_rkv->empty) |
| 514 | identifier = buffer_tostring(comm_rkv->wb); |
| 515 | } |
| 516 | } |
| 517 | |
| 518 | buffer_flush(rkv->wb); |
| 519 | |
| 520 | if (!identifier || !*identifier) |
| 521 | buffer_strcat(rkv->wb, FACET_VALUE_UNSET); |
| 522 | else if (!pid || !*pid) |
| 523 | buffer_sprintf(rkv->wb, "%s", identifier); |
| 524 | else |
| 525 | buffer_sprintf(rkv->wb, "%s[%s]", identifier, pid); |
| 526 | |
| 527 | buffer_json_add_array_item_string(json_array, buffer_tostring(rkv->wb)); |
| 528 | } |
| 529 | |
| 530 | struct message_id_info { |
| 531 | const char *msg; |
| 532 | }; |
| 533 | |
| 534 | static DICTIONARY *known_journal_messages_ids = NULL; |
| 535 | |
| 536 | #define msgid_into_dict(uuid, message) \ |
| 537 | do { \ |
| 538 | i.msg = message; \ |
| 539 | dictionary_set(known_journal_messages_ids, uuid, &i, sizeof(i)); \ |
| 540 | } while (0) |
| 541 | |
| 542 | static void nd_sd_journal_message_ids_init(void) |
| 543 | { |
| 544 | known_journal_messages_ids = dictionary_create(DICT_OPTION_DONT_OVERWRITE_VALUE); |
| 545 | struct message_id_info i = {0}; |
| 546 | |
| 547 | // systemd |
| 548 | // https://github.com/systemd/systemd/blob/main/catalog/systemd.catalog.in |
| 549 | msgid_into_dict("f77379a8490b408bbe5f6940505a777b", "Journal started"); |
| 550 | msgid_into_dict("d93fb3c9c24d451a97cea615ce59c00b", "Journal stopped"); |
| 551 | msgid_into_dict("a596d6fe7bfa4994828e72309e95d61e", "Journal messages suppressed"); |
| 552 | msgid_into_dict("e9bf28e6e834481bb6f48f548ad13606", "Journal messages missed"); |
| 553 | msgid_into_dict("ec387f577b844b8fa948f33cad9a75e6", "Journal disk space usage"); |
| 554 | msgid_into_dict("fc2e22bc6ee647b6b90729ab34a250b1", "Coredump"); |
| 555 | msgid_into_dict("5aadd8e954dc4b1a8c954d63fd9e1137", "Coredump truncated"); |
| 556 | msgid_into_dict("1f4e0a44a88649939aaea34fc6da8c95", "Backtrace"); // not found in systemd catalog |
| 557 | msgid_into_dict("8d45620c1a4348dbb17410da57c60c66", "User Session created"); |
| 558 | msgid_into_dict("3354939424b4456d9802ca8333ed424a", "User Session terminated"); |
| 559 | msgid_into_dict("fcbefc5da23d428093f97c82a9290f7b", "Seat started"); |
| 560 | msgid_into_dict("e7852bfe46784ed0accde04bc864c2d5", "Seat removed"); |
| 561 | msgid_into_dict("24d8d4452573402496068381a6312df2", "VM or container started"); |
| 562 | msgid_into_dict("58432bd3bace477cb514b56381b8a758", "VM or container stopped"); |
| 563 | msgid_into_dict("c7a787079b354eaaa9e77b371893cd27", "Time change"); |
| 564 | msgid_into_dict("45f82f4aef7a4bbf942ce861d1f20990", "Timezone change"); |
| 565 | msgid_into_dict("50876a9db00f4c40bde1a2ad381c3a1b", "System configuration issues"); |
| 566 | msgid_into_dict("b07a249cd024414a82dd00cd181378ff", "System start-up completed"); |
| 567 | msgid_into_dict("eed00a68ffd84e31882105fd973abdd1", "User start-up completed"); |
| 568 | msgid_into_dict("6bbd95ee977941e497c48be27c254128", "Sleep start"); |
| 569 | msgid_into_dict("8811e6df2a8e40f58a94cea26f8ebf14", "Sleep stop"); |
| 570 | msgid_into_dict("98268866d1d54a499c4e98921d93bc40", "System shutdown initiated"); |
| 571 | msgid_into_dict("c14aaf76ec284a5fa1f105f88dfb061c", "System factory reset initiated"); |
| 572 | msgid_into_dict("d9ec5e95e4b646aaaea2fd05214edbda", "Container init crashed"); |
| 573 | msgid_into_dict("3ed0163e868a4417ab8b9e210407a96c", "System reboot failed after crash"); |
| 574 | msgid_into_dict("645c735537634ae0a32b15a7c6cba7d4", "Init execution froze"); |
| 575 | msgid_into_dict("5addb3a06a734d3396b794bf98fb2d01", "Init crashed no coredump"); |
| 576 | msgid_into_dict("5c9e98de4ab94c6a9d04d0ad793bd903", "Init crashed no fork"); |
| 577 | msgid_into_dict("5e6f1f5e4db64a0eaee3368249d20b94", "Init crashed unknown signal"); |
| 578 | msgid_into_dict("83f84b35ee264f74a3896a9717af34cb", "Init crashed systemd signal"); |
| 579 | msgid_into_dict("3a73a98baf5b4b199929e3226c0be783", "Init crashed process signal"); |
| 580 | msgid_into_dict("2ed18d4f78ca47f0a9bc25271c26adb4", "Init crashed waitpid failed"); |
| 581 | msgid_into_dict("56b1cd96f24246c5b607666fda952356", "Init crashed coredump failed"); |
| 582 | msgid_into_dict("4ac7566d4d7548f4981f629a28f0f829", "Init crashed coredump"); |
| 583 | msgid_into_dict("38e8b1e039ad469291b18b44c553a5b7", "Crash shell failed to fork"); |
| 584 | msgid_into_dict("872729b47dbe473eb768ccecd477beda", "Crash shell failed to execute"); |
| 585 | msgid_into_dict("658a67adc1c940b3b3316e7e8628834a", "Selinux failed"); |
| 586 | msgid_into_dict("e6f456bd92004d9580160b2207555186", "Battery low warning"); |
| 587 | msgid_into_dict("267437d33fdd41099ad76221cc24a335", "Battery low powering off"); |
| 588 | msgid_into_dict("79e05b67bc4545d1922fe47107ee60c5", "Manager mainloop failed"); |
| 589 | msgid_into_dict("dbb136b10ef4457ba47a795d62f108c9", "Manager no xdgdir path"); |
| 590 | msgid_into_dict("ed158c2df8884fa584eead2d902c1032", "Init failed to drop capability bounding set of usermode"); |
| 591 | msgid_into_dict("42695b500df048298bee37159caa9f2e", "Init failed to drop capability bounding set"); |
| 592 | msgid_into_dict("bfc2430724ab44499735b4f94cca9295", "User manager can't disable new privileges"); |
| 593 | msgid_into_dict("59288af523be43a28d494e41e26e4510", "Manager failed to start default target"); |
| 594 | msgid_into_dict("689b4fcc97b4486ea5da92db69c9e314", "Manager failed to isolate default target"); |
| 595 | msgid_into_dict("5ed836f1766f4a8a9fc5da45aae23b29", "Manager failed to collect passed file descriptors"); |
| 596 | msgid_into_dict("6a40fbfbd2ba4b8db02fb40c9cd090d7", "Init failed to fix up environment variables"); |
| 597 | msgid_into_dict("0e54470984ac419689743d957a119e2e", "Manager failed to allocate"); |
| 598 | msgid_into_dict("d67fa9f847aa4b048a2ae33535331adb", "Manager failed to write Smack"); |
| 599 | msgid_into_dict("af55a6f75b544431b72649f36ff6d62c", "System shutdown critical error"); |
| 600 | msgid_into_dict("d18e0339efb24a068d9c1060221048c2", "Init failed to fork off valgrind"); |
| 601 | msgid_into_dict("7d4958e842da4a758f6c1cdc7b36dcc5", "Unit starting"); |
| 602 | msgid_into_dict("39f53479d3a045ac8e11786248231fbf", "Unit started"); |
| 603 | msgid_into_dict("be02cf6855d2428ba40df7e9d022f03d", "Unit failed"); |
| 604 | msgid_into_dict("de5b426a63be47a7b6ac3eaac82e2f6f", "Unit stopping"); |
| 605 | msgid_into_dict("9d1aaa27d60140bd96365438aad20286", "Unit stopped"); |
| 606 | msgid_into_dict("d34d037fff1847e6ae669a370e694725", "Unit reloading"); |
| 607 | msgid_into_dict("7b05ebc668384222baa8881179cfda54", "Unit reloaded"); |
| 608 | msgid_into_dict("5eb03494b6584870a536b337290809b3", "Unit restart scheduled"); |
| 609 | msgid_into_dict("ae8f7b866b0347b9af31fe1c80b127c0", "Unit resources"); |
| 610 | msgid_into_dict("7ad2d189f7e94e70a38c781354912448", "Unit success"); |
| 611 | msgid_into_dict("0e4284a0caca4bfc81c0bb6786972673", "Unit skipped"); |
| 612 | msgid_into_dict("d9b373ed55a64feb8242e02dbe79a49c", "Unit failure result"); |
| 613 | msgid_into_dict("641257651c1b4ec9a8624d7a40a9e1e7", "Process execution failed"); |
| 614 | msgid_into_dict("98e322203f7a4ed290d09fe03c09fe15", "Unit process exited"); |
| 615 | msgid_into_dict("0027229ca0644181a76c4e92458afa2e", "Syslog forward missed"); |
| 616 | msgid_into_dict("1dee0369c7fc4736b7099b38ecb46ee7", "Mount point is not empty"); |
| 617 | msgid_into_dict("d989611b15e44c9dbf31e3c81256e4ed", "Unit oomd kill"); // not found in systemd catalog |
| 618 | msgid_into_dict("fe6faa94e7774663a0da52717891d8ef", "Unit out of memory"); |
| 619 | msgid_into_dict("b72ea4a2881545a0b50e200e55b9b06f", "Lid opened"); |
| 620 | msgid_into_dict("b72ea4a2881545a0b50e200e55b9b070", "Lid closed"); |
| 621 | msgid_into_dict("f5f416b862074b28927a48c3ba7d51ff", "System docked"); |
| 622 | msgid_into_dict("51e171bd585248568110144c517cca53", "System undocked"); |
| 623 | msgid_into_dict("b72ea4a2881545a0b50e200e55b9b071", "Power key"); |
| 624 | msgid_into_dict("3e0117101eb243c1b9a50db3494ab10b", "Power key long press"); |
| 625 | msgid_into_dict("9fa9d2c012134ec385451ffe316f97d0", "Reboot key"); |
| 626 | msgid_into_dict("f1c59a58c9d943668965c337caec5975", "Reboot key long press"); |
| 627 | msgid_into_dict("b72ea4a2881545a0b50e200e55b9b072", "Suspend key"); |
| 628 | msgid_into_dict("bfdaf6d312ab4007bc1fe40a15df78e8", "Suspend key long press"); |
| 629 | msgid_into_dict("b72ea4a2881545a0b50e200e55b9b073", "Hibernate key"); |
| 630 | msgid_into_dict("167836df6f7f428e98147227b2dc8945", "Hibernate key long press"); |
| 631 | msgid_into_dict("c772d24e9a884cbeb9ea12625c306c01", "Invalid configuration"); // not found in systemd catalog |
| 632 | msgid_into_dict("1675d7f172174098b1108bf8c7dc8f5d", "DNSSEC validation failed"); |
| 633 | msgid_into_dict("4d4408cfd0d144859184d1e65d7c8a65", "DNSSEC trust anchor revoked"); |
| 634 | msgid_into_dict("36db2dfa5a9045e1bd4af5f93e1cf057", "DNSSEC turned off"); |
| 635 | msgid_into_dict("b61fdac612e94b9182285b998843061f", "Username unsafe"); |
| 636 | msgid_into_dict("1b3bb94037f04bbf81028e135a12d293", "Mount point path not suitable"); |
| 637 | msgid_into_dict("010190138f494e29a0ef6669749531aa", "Device path not suitable"); // not found in systemd catalog |
| 638 | msgid_into_dict("b480325f9c394a7b802c231e51a2752c", "Nobody user unsuitable"); |
| 639 | msgid_into_dict("1c0454c1bd2241e0ac6fefb4bc631433", "Systemd udev settle deprecated"); |
| 640 | msgid_into_dict("7c8a41f37b764941a0e1780b1be2f037", "Time initial sync"); |
| 641 | msgid_into_dict("7db73c8af0d94eeb822ae04323fe6ab6", "Time initial bump"); |
| 642 | msgid_into_dict("9e7066279dc8403da79ce4b1a69064b2", "Shutdown scheduled"); |
| 643 | msgid_into_dict("249f6fb9e6e2428c96f3f0875681ffa3", "Shutdown canceled"); |
| 644 | msgid_into_dict("3f7d5ef3e54f4302b4f0b143bb270cab", "TPM PCR Extended"); |
| 645 | msgid_into_dict("f9b0be465ad540d0850ad32172d57c21", "Memory Trimmed"); |
| 646 | msgid_into_dict("a8fa8dacdb1d443e9503b8be367a6adb", "SysV Service Found"); |
| 647 | msgid_into_dict("187c62eb1e7f463bb530394f52cb090f", "Portable Service attached"); |
| 648 | msgid_into_dict("76c5c754d628490d8ecba4c9d042112b", "Portable Service detached"); |
| 649 | msgid_into_dict("9cf56b8baf9546cf9478783a8de42113", "systemd-networkd sysctl changed by foreign process"); |
| 650 | msgid_into_dict("ad7089f928ac4f7ea00c07457d47ba8a", "SRK into TPM authorization failure"); |
| 651 | msgid_into_dict("b2bcbaf5edf948e093ce50bbea0e81ec", "Secure Attention Key (SAK) was pressed"); |
| 652 | |
| 653 | // dbus |
| 654 | // https://github.com/bus1/dbus-broker/blob/main/src/catalog/catalog-ids.h |
| 655 | msgid_into_dict("7fc63312330b479bb32e598d47cef1a8", "dbus activate no unit"); |
| 656 | msgid_into_dict("ee9799dab1e24d81b7bee7759a543e1b", "dbus activate masked unit"); |
| 657 | msgid_into_dict("a0fa58cafd6f4f0c8d003d16ccf9e797", "dbus broker exited"); |
| 658 | msgid_into_dict("c8c6cde1c488439aba371a664353d9d8", "dbus dirwatch"); |
| 659 | msgid_into_dict("8af3357071af4153af414daae07d38e7", "dbus dispatch stats"); |
| 660 | msgid_into_dict("199d4300277f495f84ba4028c984214c", "dbus no sopeergroup"); |
| 661 | msgid_into_dict("b209c0d9d1764ab38d13b8e00d1784d6", "dbus protocol violation"); |
| 662 | msgid_into_dict("6fa70fa776044fa28be7a21daf42a108", "dbus receive failed"); |
| 663 | msgid_into_dict("0ce0fa61d1a9433dabd67417f6b8e535", "dbus service failed open"); |
| 664 | msgid_into_dict("24dc708d9e6a4226a3efe2033bb744de", "dbus service invalid"); |
| 665 | msgid_into_dict("f15d2347662d483ea9bcd8aa1a691d28", "dbus sighup"); |
| 666 | |
| 667 | // gnome |
| 668 | // https://gitlab.gnome.org/GNOME/gnome-session/-/blob/main/gnome-session/gsm-manager.c |
| 669 | msgid_into_dict("0ce153587afa4095832d233c17a88001", "Gnome SM startup succeeded"); |
| 670 | msgid_into_dict("10dd2dc188b54a5e98970f56499d1f73", "Gnome SM unrecoverable failure"); |
| 671 | |
| 672 | // gnome-shell |
| 673 | // https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/main.js#L56 |
| 674 | msgid_into_dict("f3ea493c22934e26811cd62abe8e203a", "Gnome shell started"); |
| 675 | |
| 676 | // flathub |
| 677 | // https://docs.flatpak.org/de/latest/flatpak-command-reference.html |
| 678 | msgid_into_dict("c7b39b1e006b464599465e105b361485", "Flatpak cache"); |
| 679 | |
| 680 | // ??? |
| 681 | msgid_into_dict("75ba3deb0af041a9a46272ff85d9e73e", "Flathub pulls"); |
| 682 | msgid_into_dict("f02bce89a54e4efab3a94a797d26204a", "Flathub pull errors"); |
| 683 | |
| 684 | // ?? |
| 685 | msgid_into_dict("dd11929c788e48bdbb6276fb5f26b08a", "Boltd starting"); |
| 686 | |
| 687 | // Netdata |
| 688 | msgid_into_dict("1e6061a9fbd44501b3ccc368119f2b69", "Netdata startup"); |
| 689 | msgid_into_dict("ed4cdb8f1beb4ad3b57cb3cae2d162fa", "Netdata connection from child"); |
| 690 | msgid_into_dict("6e2e3839067648968b646045dbf28d66", "Netdata connection to parent"); |
| 691 | msgid_into_dict("9ce0cb58ab8b44df82c4bf1ad9ee22de", "Netdata alert transition"); |
| 692 | msgid_into_dict("6db0018e83e34320ae2a659d78019fb7", "Netdata alert notification"); |
| 693 | msgid_into_dict("23e93dfccbf64e11aac858b9410d8a82", "Netdata fatal message"); |
| 694 | msgid_into_dict("8ddaf5ba33a74078b609250db1e951f3", "Sensor state transition"); |
| 695 | msgid_into_dict("ec87a56120d5431bace51e2fb8bba243", "Netdata log flood protection"); |
| 696 | msgid_into_dict("acb33cb95778476baac702eb7e4e151d", "Netdata Cloud connection"); |
| 697 | msgid_into_dict("d1f59606dd4d41e3b217a0cfcae8e632", "Netdata extreme cardinality"); |
| 698 | msgid_into_dict("02f47d350af5449197bf7a95b605a468", "Netdata exit reason"); |
| 699 | msgid_into_dict("4fdf40816c124623a032b7fe73beacb8", "Netdata dynamic configuration"); |
| 700 | } |
| 701 | |
| 702 | void nd_sd_journal_transform_message_id( |
| 703 | FACETS *facets __maybe_unused, |
| 704 | BUFFER *wb, |
| 705 | FACETS_TRANSFORMATION_SCOPE scope __maybe_unused, |
| 706 | void *data __maybe_unused) |
| 707 | { |
| 708 | const char *message_id = buffer_tostring(wb); |
| 709 | struct message_id_info *i = dictionary_get(known_journal_messages_ids, message_id); |
| 710 | |
| 711 | if (!i) |
| 712 | return; |
| 713 | |
| 714 | switch (scope) { |
| 715 | default: |
| 716 | case FACETS_TRANSFORM_DATA: |
| 717 | case FACETS_TRANSFORM_VALUE: |
| 718 | buffer_sprintf(wb, " (%s)", i->msg); |
| 719 | break; |
| 720 | |
| 721 | case FACETS_TRANSFORM_FACET: |
| 722 | case FACETS_TRANSFORM_FACET_SORT: |
| 723 | case FACETS_TRANSFORM_HISTOGRAM: |
| 724 | buffer_flush(wb); |
| 725 | buffer_strcat(wb, i->msg); |
| 726 | break; |
| 727 | } |
| 728 | } |
| 729 | |
| 730 | void nd_sd_journal_annotations_init(void) |
| 731 | { |
| 732 | cached_usernames_init(); |
| 733 | cached_groupnames_init(); |
| 734 | update_cached_host_users(); |
| 735 | update_cached_host_groups(); |
| 736 | nd_sd_journal_message_ids_init(); |
| 737 | } |