]> git.proxmox.com Git - mirror_frr.git/blob - lib/log_vty.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / lib / log_vty.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Logging - VTY code
4 * Copyright (C) 2019 Cumulus Networks, Inc.
5 * Stephen Worley
6 */
7
8 #include <zebra.h>
9
10 #include "lib/log_vty.h"
11 #include "command.h"
12 #include "lib/log.h"
13 #include "lib/zlog_targets.h"
14 #include "lib/zlog_5424.h"
15 #include "lib/lib_errors.h"
16 #include "lib/printfrr.h"
17 #include "lib/systemd.h"
18
19 #include "lib/log_vty_clippy.c"
20
21 #define ZLOG_MAXLVL(a, b) MAX(a, b)
22
23 DEFINE_HOOK(zlog_rotate, (), ());
24 DEFINE_HOOK(zlog_cli_show, (struct vty * vty), (vty));
25
26 static unsigned logmsgs_with_persist_bt;
27
28 static const int log_default_lvl = LOG_DEBUG;
29
30 static int log_config_stdout_lvl = ZLOG_DISABLED;
31 static int log_config_syslog_lvl = ZLOG_DISABLED;
32 static int log_cmdline_stdout_lvl = ZLOG_DISABLED;
33 static int log_cmdline_syslog_lvl = ZLOG_DISABLED;
34
35 static struct zlog_cfg_file zt_file_cmdline = {
36 .prio_min = ZLOG_DISABLED,
37 .ts_subsec = LOG_TIMESTAMP_PRECISION,
38 };
39 static struct zlog_cfg_file zt_file = {
40 .prio_min = ZLOG_DISABLED,
41 .ts_subsec = LOG_TIMESTAMP_PRECISION,
42 };
43 static struct zlog_cfg_filterfile zt_filterfile = {
44 .parent =
45 {
46 .prio_min = ZLOG_DISABLED,
47 .ts_subsec = LOG_TIMESTAMP_PRECISION,
48 },
49 };
50
51 static struct zlog_cfg_file zt_stdout_file = {
52 .prio_min = ZLOG_DISABLED,
53 .ts_subsec = LOG_TIMESTAMP_PRECISION,
54 };
55 static struct zlog_cfg_5424 zt_stdout_journald = {
56 .prio_min = ZLOG_DISABLED,
57
58 .fmt = ZLOG_FMT_JOURNALD,
59 .dst = ZLOG_5424_DST_UNIX,
60 .filename = "/run/systemd/journal/socket",
61
62 /* this can't be changed through config since this target substitutes
63 * in for the "plain" stdout target
64 */
65 .facility = LOG_DAEMON,
66 .kw_version = false,
67 .kw_location = true,
68 .kw_uid = true,
69 .kw_ec = true,
70 .kw_args = true,
71 };
72 static bool stdout_journald_in_use;
73
74 const char *zlog_progname;
75 static const char *zlog_protoname;
76
77 static const struct facility_map {
78 int facility;
79 const char *name;
80 size_t match;
81 } syslog_facilities[] = {
82 {LOG_KERN, "kern", 1},
83 {LOG_USER, "user", 2},
84 {LOG_MAIL, "mail", 1},
85 {LOG_DAEMON, "daemon", 1},
86 {LOG_AUTH, "auth", 1},
87 {LOG_SYSLOG, "syslog", 1},
88 {LOG_LPR, "lpr", 2},
89 {LOG_NEWS, "news", 1},
90 {LOG_UUCP, "uucp", 2},
91 {LOG_CRON, "cron", 1},
92 #ifdef LOG_FTP
93 {LOG_FTP, "ftp", 1},
94 #endif
95 {LOG_LOCAL0, "local0", 6},
96 {LOG_LOCAL1, "local1", 6},
97 {LOG_LOCAL2, "local2", 6},
98 {LOG_LOCAL3, "local3", 6},
99 {LOG_LOCAL4, "local4", 6},
100 {LOG_LOCAL5, "local5", 6},
101 {LOG_LOCAL6, "local6", 6},
102 {LOG_LOCAL7, "local7", 6},
103 {0, NULL, 0},
104 };
105
106 static const char * const zlog_priority[] = {
107 "emergencies", "alerts", "critical", "errors", "warnings",
108 "notifications", "informational", "debugging", NULL,
109 };
110
111 const char *zlog_priority_str(int priority)
112 {
113 if (priority > LOG_DEBUG)
114 return "???";
115 return zlog_priority[priority];
116 }
117
118 const char *facility_name(int facility)
119 {
120 const struct facility_map *fm;
121
122 for (fm = syslog_facilities; fm->name; fm++)
123 if (fm->facility == facility)
124 return fm->name;
125 return "";
126 }
127
128 int facility_match(const char *str)
129 {
130 const struct facility_map *fm;
131
132 for (fm = syslog_facilities; fm->name; fm++)
133 if (!strncmp(str, fm->name, fm->match))
134 return fm->facility;
135 return -1;
136 }
137
138 int log_level_match(const char *s)
139 {
140 int level;
141
142 for (level = 0; zlog_priority[level] != NULL; level++)
143 if (!strncmp(s, zlog_priority[level], 2))
144 return level;
145 return ZLOG_DISABLED;
146 }
147
148 void zlog_rotate(void)
149 {
150 zlog_file_rotate(&zt_file);
151 zlog_file_rotate(&zt_filterfile.parent);
152 zlog_file_rotate(&zt_file_cmdline);
153 hook_call(zlog_rotate);
154 }
155
156
157 void log_show_syslog(struct vty *vty)
158 {
159 int level = zlog_syslog_get_prio_min();
160
161 vty_out(vty, "Syslog logging: ");
162 if (level == ZLOG_DISABLED)
163 vty_out(vty, "disabled\n");
164 else
165 vty_out(vty, "level %s, facility %s, ident %s\n",
166 zlog_priority[level],
167 facility_name(zlog_syslog_get_facility()),
168 zlog_progname);
169 }
170
171 DEFUN_NOSH (show_logging,
172 show_logging_cmd,
173 "show logging",
174 SHOW_STR
175 "Show current logging configuration\n")
176 {
177 int stdout_prio;
178
179 log_show_syslog(vty);
180
181 stdout_prio = stdout_journald_in_use ? zt_stdout_journald.prio_min
182 : zt_stdout_file.prio_min;
183
184 vty_out(vty, "Stdout logging: ");
185 if (stdout_prio == ZLOG_DISABLED)
186 vty_out(vty, "disabled");
187 else
188 vty_out(vty, "level %s", zlog_priority[stdout_prio]);
189 vty_out(vty, "\n");
190
191 vty_out(vty, "File logging: ");
192 if (zt_file.prio_min == ZLOG_DISABLED || !zt_file.filename)
193 vty_out(vty, "disabled");
194 else
195 vty_out(vty, "level %s, filename %s",
196 zlog_priority[zt_file.prio_min], zt_file.filename);
197 vty_out(vty, "\n");
198
199 if (zt_filterfile.parent.prio_min != ZLOG_DISABLED
200 && zt_filterfile.parent.filename)
201 vty_out(vty, "Filtered-file logging: level %s, filename %s\n",
202 zlog_priority[zt_filterfile.parent.prio_min],
203 zt_filterfile.parent.filename);
204
205 if (log_cmdline_syslog_lvl != ZLOG_DISABLED)
206 vty_out(vty,
207 "From command line: \"--log syslog --log-level %s\"\n",
208 zlog_priority[log_cmdline_syslog_lvl]);
209 if (log_cmdline_stdout_lvl != ZLOG_DISABLED)
210 vty_out(vty,
211 "From command line: \"--log stdout --log-level %s\"\n",
212 zlog_priority[log_cmdline_stdout_lvl]);
213 if (zt_file_cmdline.prio_min != ZLOG_DISABLED)
214 vty_out(vty,
215 "From command line: \"--log file:%s --log-level %s\"\n",
216 zt_file_cmdline.filename,
217 zlog_priority[zt_file_cmdline.prio_min]);
218
219 vty_out(vty, "Protocol name: %s\n", zlog_protoname);
220 vty_out(vty, "Record priority: %s\n",
221 (zt_file.record_priority ? "enabled" : "disabled"));
222 vty_out(vty, "Timestamp precision: %d\n", zt_file.ts_subsec);
223
224 hook_call(zlog_cli_show, vty);
225 return CMD_SUCCESS;
226 }
227
228 static void log_stdout_apply_level(void)
229 {
230 int maxlvl;
231
232 maxlvl = ZLOG_MAXLVL(log_config_stdout_lvl, log_cmdline_stdout_lvl);
233
234 if (stdout_journald_in_use) {
235 zt_stdout_journald.prio_min = maxlvl;
236 zlog_5424_apply_meta(&zt_stdout_journald);
237 } else {
238 zt_stdout_file.prio_min = maxlvl;
239 zlog_file_set_other(&zt_stdout_file);
240 }
241 }
242
243 DEFPY (config_log_stdout,
244 config_log_stdout_cmd,
245 "log stdout [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>$levelarg]",
246 "Logging control\n"
247 "Set stdout logging level\n"
248 LOG_LEVEL_DESC)
249 {
250 int level;
251
252 if (levelarg) {
253 level = log_level_match(levelarg);
254 if (level == ZLOG_DISABLED)
255 return CMD_ERR_NO_MATCH;
256 } else
257 level = log_default_lvl;
258
259 log_config_stdout_lvl = level;
260 log_stdout_apply_level();
261 return CMD_SUCCESS;
262 }
263
264 DEFUN (no_config_log_stdout,
265 no_config_log_stdout_cmd,
266 "no log stdout [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
267 NO_STR
268 "Logging control\n"
269 "Cancel logging to stdout\n"
270 LOG_LEVEL_DESC)
271 {
272 log_config_stdout_lvl = ZLOG_DISABLED;
273 log_stdout_apply_level();
274 return CMD_SUCCESS;
275 }
276
277 DEFUN_HIDDEN (config_log_monitor,
278 config_log_monitor_cmd,
279 "log monitor [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
280 "Logging control\n"
281 "Set terminal line (monitor) logging level\n"
282 LOG_LEVEL_DESC)
283 {
284 vty_out(vty, "%% \"log monitor\" is deprecated and does nothing.\n");
285 return CMD_SUCCESS;
286 }
287
288 DEFUN_HIDDEN (no_config_log_monitor,
289 no_config_log_monitor_cmd,
290 "no log monitor [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
291 NO_STR
292 "Logging control\n"
293 "Disable terminal line (monitor) logging\n"
294 LOG_LEVEL_DESC)
295 {
296 return CMD_SUCCESS;
297 }
298
299 DEFPY_NOSH (debug_uid_backtrace,
300 debug_uid_backtrace_cmd,
301 "[no] debug unique-id UID backtrace",
302 NO_STR
303 DEBUG_STR
304 "Options per individual log message, by unique ID\n"
305 "Log message unique ID (XXXXX-XXXXX)\n"
306 "Add backtrace to log when message is printed\n")
307 {
308 struct xrefdata search, *xrd;
309 struct xrefdata_logmsg *xrdl;
310 uint8_t flag;
311
312 strlcpy(search.uid, uid, sizeof(search.uid));
313 xrd = xrefdata_uid_find(&xrefdata_uid, &search);
314
315 if (!xrd)
316 return CMD_ERR_NOTHING_TODO;
317
318 if (xrd->xref->type != XREFT_LOGMSG) {
319 vty_out(vty, "%% ID \"%s\" is not a log message\n", uid);
320 return CMD_WARNING;
321 }
322 xrdl = container_of(xrd, struct xrefdata_logmsg, xrefdata);
323
324 flag = (vty->node == CONFIG_NODE) ? LOGMSG_FLAG_PERSISTENT
325 : LOGMSG_FLAG_EPHEMERAL;
326
327 if ((xrdl->fl_print_bt & flag) == (no ? 0 : flag))
328 return CMD_SUCCESS;
329 if (flag == LOGMSG_FLAG_PERSISTENT)
330 logmsgs_with_persist_bt += no ? -1 : 1;
331
332 xrdl->fl_print_bt ^= flag;
333 return CMD_SUCCESS;
334 }
335
336 static int set_log_file(struct zlog_cfg_file *target, struct vty *vty,
337 const char *fname, int loglevel)
338 {
339 char path[MAXPATHLEN + 1];
340 const char *fullpath;
341 bool ok;
342
343
344 /* Path detection. */
345 if (!IS_DIRECTORY_SEP(*fname)) {
346 char cwd[MAXPATHLEN + 1];
347
348 cwd[MAXPATHLEN] = '\0';
349
350 if (getcwd(cwd, MAXPATHLEN) == NULL) {
351 flog_err_sys(EC_LIB_SYSTEM_CALL,
352 "config_log_file: Unable to alloc mem!");
353 return CMD_WARNING_CONFIG_FAILED;
354 }
355
356 int pr = snprintf(path, sizeof(path), "%s/%s", cwd, fname);
357 if (pr < 0 || (unsigned int)pr >= sizeof(path)) {
358 flog_err_sys(
359 EC_LIB_SYSTEM_CALL,
360 "%s: Path too long ('%s/%s'); system maximum is %u",
361 __func__, cwd, fname, MAXPATHLEN);
362 return CMD_WARNING_CONFIG_FAILED;
363 }
364
365 fullpath = path;
366 } else
367 fullpath = fname;
368
369 target->prio_min = loglevel;
370 ok = zlog_file_set_filename(target, fullpath);
371
372 if (!ok) {
373 if (vty)
374 vty_out(vty, "can't open logfile %s\n", fname);
375 return CMD_WARNING_CONFIG_FAILED;
376 }
377 return CMD_SUCCESS;
378 }
379
380 void command_setup_early_logging(const char *dest, const char *level)
381 {
382 int nlevel;
383 char *sep;
384 int len;
385 char type[8];
386
387 if (level) {
388 nlevel = log_level_match(level);
389
390 if (nlevel == ZLOG_DISABLED) {
391 fprintf(stderr, "invalid log level \"%s\"\n", level);
392 exit(1);
393 }
394 } else
395 nlevel = log_default_lvl;
396
397 if (!dest)
398 return;
399
400 sep = strchr(dest, ':');
401 len = sep ? (int)(sep - dest) : (int)strlen(dest);
402
403 snprintfrr(type, sizeof(type), "%.*s", len, dest);
404
405 if (strcmp(type, "stdout") == 0) {
406 log_cmdline_stdout_lvl = nlevel;
407 log_stdout_apply_level();
408 return;
409 }
410 if (strcmp(type, "syslog") == 0) {
411 log_cmdline_syslog_lvl = nlevel;
412 zlog_syslog_set_prio_min(ZLOG_MAXLVL(log_config_syslog_lvl,
413 log_cmdline_syslog_lvl));
414 return;
415 }
416 if (strcmp(type, "file") == 0 && sep) {
417 sep++;
418 set_log_file(&zt_file_cmdline, NULL, sep, nlevel);
419 return;
420 }
421 if (strcmp(type, "monitor") == 0 && sep) {
422 struct zlog_live_cfg cfg = {};
423 unsigned long fd;
424 char *endp;
425
426 sep++;
427 fd = strtoul(sep, &endp, 10);
428 if (!*sep || *endp) {
429 fprintf(stderr, "invalid monitor fd \"%s\"\n", sep);
430 exit(1);
431 }
432
433 zlog_live_open_fd(&cfg, nlevel, fd);
434 zlog_live_disown(&cfg);
435 return;
436 }
437
438 fprintf(stderr, "invalid log target \"%s\" (\"%s\")\n", type, dest);
439 exit(1);
440 }
441
442 DEFUN (clear_log_cmdline,
443 clear_log_cmdline_cmd,
444 "clear log cmdline-targets",
445 CLEAR_STR
446 "Logging control\n"
447 "Disable log targets specified at startup by --log option\n")
448 {
449 zt_file_cmdline.prio_min = ZLOG_DISABLED;
450 zlog_file_set_other(&zt_file_cmdline);
451
452 log_cmdline_syslog_lvl = ZLOG_DISABLED;
453 zlog_syslog_set_prio_min(ZLOG_MAXLVL(log_config_syslog_lvl,
454 log_cmdline_syslog_lvl));
455
456 log_cmdline_stdout_lvl = ZLOG_DISABLED;
457 log_stdout_apply_level();
458
459 return CMD_SUCCESS;
460 }
461
462 DEFPY (config_log_file,
463 config_log_file_cmd,
464 "log file FILENAME [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>$levelarg]",
465 "Logging control\n"
466 "Logging to file\n"
467 "Logging filename\n"
468 LOG_LEVEL_DESC)
469 {
470 int level = log_default_lvl;
471
472 if (levelarg) {
473 level = log_level_match(levelarg);
474 if (level == ZLOG_DISABLED)
475 return CMD_ERR_NO_MATCH;
476 }
477 return set_log_file(&zt_file, vty, filename, level);
478 }
479
480 DEFUN (no_config_log_file,
481 no_config_log_file_cmd,
482 "no log file [FILENAME [LEVEL]]",
483 NO_STR
484 "Logging control\n"
485 "Cancel logging to file\n"
486 "Logging file name\n"
487 "Logging level\n")
488 {
489 zt_file.prio_min = ZLOG_DISABLED;
490 zlog_file_set_other(&zt_file);
491 return CMD_SUCCESS;
492 }
493
494 DEFPY (config_log_syslog,
495 config_log_syslog_cmd,
496 "log syslog [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>$levelarg]",
497 "Logging control\n"
498 "Set syslog logging level\n"
499 LOG_LEVEL_DESC)
500 {
501 int level;
502
503 if (levelarg) {
504 level = log_level_match(levelarg);
505
506 if (level == ZLOG_DISABLED)
507 return CMD_ERR_NO_MATCH;
508 } else
509 level = log_default_lvl;
510
511 log_config_syslog_lvl = level;
512 zlog_syslog_set_prio_min(ZLOG_MAXLVL(log_config_syslog_lvl,
513 log_cmdline_syslog_lvl));
514 return CMD_SUCCESS;
515 }
516
517 DEFUN (no_config_log_syslog,
518 no_config_log_syslog_cmd,
519 "no log syslog [<kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7>] [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
520 NO_STR
521 "Logging control\n"
522 "Cancel logging to syslog\n"
523 LOG_FACILITY_DESC
524 LOG_LEVEL_DESC)
525 {
526 log_config_syslog_lvl = ZLOG_DISABLED;
527 zlog_syslog_set_prio_min(ZLOG_MAXLVL(log_config_syslog_lvl,
528 log_cmdline_syslog_lvl));
529 return CMD_SUCCESS;
530 }
531
532 DEFPY (config_log_facility,
533 config_log_facility_cmd,
534 "log facility <kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7>$facilityarg",
535 "Logging control\n"
536 "Facility parameter for syslog messages\n"
537 LOG_FACILITY_DESC)
538 {
539 int facility = facility_match(facilityarg);
540
541 zlog_syslog_set_facility(facility);
542 return CMD_SUCCESS;
543 }
544
545 DEFUN (no_config_log_facility,
546 no_config_log_facility_cmd,
547 "no log facility [<kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7>]",
548 NO_STR
549 "Logging control\n"
550 "Reset syslog facility to default (daemon)\n"
551 LOG_FACILITY_DESC)
552 {
553 zlog_syslog_set_facility(LOG_DAEMON);
554 return CMD_SUCCESS;
555 }
556
557 DEFUN (config_log_record_priority,
558 config_log_record_priority_cmd,
559 "log record-priority",
560 "Logging control\n"
561 "Log the priority of the message within the message\n")
562 {
563 zt_file.record_priority = true;
564 zlog_file_set_other(&zt_file);
565 if (!stdout_journald_in_use) {
566 zt_stdout_file.record_priority = true;
567 zlog_file_set_other(&zt_stdout_file);
568 }
569 zt_filterfile.parent.record_priority = true;
570 zlog_file_set_other(&zt_filterfile.parent);
571 return CMD_SUCCESS;
572 }
573
574 DEFUN (no_config_log_record_priority,
575 no_config_log_record_priority_cmd,
576 "no log record-priority",
577 NO_STR
578 "Logging control\n"
579 "Do not log the priority of the message within the message\n")
580 {
581 zt_file.record_priority = false;
582 zlog_file_set_other(&zt_file);
583 if (!stdout_journald_in_use) {
584 zt_stdout_file.record_priority = false;
585 zlog_file_set_other(&zt_stdout_file);
586 }
587 zt_filterfile.parent.record_priority = false;
588 zlog_file_set_other(&zt_filterfile.parent);
589 return CMD_SUCCESS;
590 }
591
592 DEFPY (config_log_timestamp_precision,
593 config_log_timestamp_precision_cmd,
594 "log timestamp precision (0-6)",
595 "Logging control\n"
596 "Timestamp configuration\n"
597 "Set the timestamp precision\n"
598 "Number of subsecond digits\n")
599 {
600 zt_file.ts_subsec = precision;
601 zlog_file_set_other(&zt_file);
602 if (!stdout_journald_in_use) {
603 zt_stdout_file.ts_subsec = precision;
604 zlog_file_set_other(&zt_stdout_file);
605 }
606 zt_filterfile.parent.ts_subsec = precision;
607 zlog_file_set_other(&zt_filterfile.parent);
608 return CMD_SUCCESS;
609 }
610
611 DEFUN (no_config_log_timestamp_precision,
612 no_config_log_timestamp_precision_cmd,
613 "no log timestamp precision [(0-6)]",
614 NO_STR
615 "Logging control\n"
616 "Timestamp configuration\n"
617 "Reset the timestamp precision to the default value of 0\n"
618 "Number of subsecond digits\n")
619 {
620 zt_file.ts_subsec = 0;
621 zlog_file_set_other(&zt_file);
622 if (!stdout_journald_in_use) {
623 zt_stdout_file.ts_subsec = 0;
624 zlog_file_set_other(&zt_stdout_file);
625 }
626 zt_filterfile.parent.ts_subsec = 0;
627 zlog_file_set_other(&zt_filterfile.parent);
628 return CMD_SUCCESS;
629 }
630
631 DEFPY (config_log_ec,
632 config_log_ec_cmd,
633 "[no] log error-category",
634 NO_STR
635 "Logging control\n"
636 "Prefix log message text with [EC 9999] code\n")
637 {
638 zlog_set_prefix_ec(!no);
639 return CMD_SUCCESS;
640 }
641
642 DEFPY (config_log_xid,
643 config_log_xid_cmd,
644 "[no] log unique-id",
645 NO_STR
646 "Logging control\n"
647 "Prefix log message text with [XXXXX-XXXXX] identifier\n")
648 {
649 zlog_set_prefix_xid(!no);
650 return CMD_SUCCESS;
651 }
652
653 DEFPY (config_log_filterfile,
654 config_log_filterfile_cmd,
655 "log filtered-file FILENAME [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>$levelarg]",
656 "Logging control\n"
657 "Logging to file with string filter\n"
658 "Logging filename\n"
659 LOG_LEVEL_DESC)
660 {
661 int level = log_default_lvl;
662
663 if (levelarg) {
664 level = log_level_match(levelarg);
665 if (level == ZLOG_DISABLED)
666 return CMD_ERR_NO_MATCH;
667 }
668 return set_log_file(&zt_filterfile.parent, vty, filename, level);
669 }
670
671 DEFUN (no_config_log_filterfile,
672 no_config_log_filterfile_cmd,
673 "no log filtered-file [FILENAME [LEVEL]]",
674 NO_STR
675 "Logging control\n"
676 "Cancel logging to file with string filter\n"
677 "Logging file name\n"
678 "Logging level\n")
679 {
680 zt_filterfile.parent.prio_min = ZLOG_DISABLED;
681 zlog_file_set_other(&zt_filterfile.parent);
682 return CMD_SUCCESS;
683 }
684
685 DEFPY (log_filter,
686 log_filter_cmd,
687 "[no] log filter-text WORD$filter",
688 NO_STR
689 "Logging control\n"
690 FILTER_LOG_STR
691 "String to filter by\n")
692 {
693 int ret = 0;
694
695 if (no)
696 ret = zlog_filter_del(filter);
697 else
698 ret = zlog_filter_add(filter);
699
700 if (ret == 1) {
701 vty_out(vty, "%% filter table full\n");
702 return CMD_WARNING;
703 } else if (ret != 0) {
704 vty_out(vty, "%% failed to %s log filter\n",
705 (no ? "remove" : "apply"));
706 return CMD_WARNING;
707 }
708
709 vty_out(vty, " %s\n", filter);
710 return CMD_SUCCESS;
711 }
712
713 /* Clear all log filters */
714 DEFPY (log_filter_clear,
715 log_filter_clear_cmd,
716 "clear log filter-text",
717 CLEAR_STR
718 "Logging control\n"
719 FILTER_LOG_STR)
720 {
721 zlog_filter_clear();
722 return CMD_SUCCESS;
723 }
724
725 /* Show log filter */
726 DEFPY (show_log_filter,
727 show_log_filter_cmd,
728 "show logging filter-text",
729 SHOW_STR
730 "Show current logging configuration\n"
731 FILTER_LOG_STR)
732 {
733 char log_filters[ZLOG_FILTERS_MAX * (ZLOG_FILTER_LENGTH_MAX + 3)] = "";
734 int len = 0;
735
736 len = zlog_filter_dump(log_filters, sizeof(log_filters));
737
738 if (len == -1) {
739 vty_out(vty, "%% failed to get filters\n");
740 return CMD_WARNING;
741 }
742
743 if (len != 0)
744 vty_out(vty, "%s", log_filters);
745
746 return CMD_SUCCESS;
747 }
748
749 /* Enable/disable 'immediate' mode, with no output buffering */
750 DEFPY (log_immediate_mode,
751 log_immediate_mode_cmd,
752 "[no] log immediate-mode",
753 NO_STR
754 "Logging control\n"
755 "Output immediately, without buffering\n")
756 {
757 zlog_set_immediate(!no);
758 return CMD_SUCCESS;
759 }
760
761 void log_config_write(struct vty *vty)
762 {
763 bool show_cmdline_hint = false;
764
765 if (zt_file.prio_min != ZLOG_DISABLED && zt_file.filename) {
766 vty_out(vty, "log file %s", zt_file.filename);
767
768 if (zt_file.prio_min != log_default_lvl)
769 vty_out(vty, " %s", zlog_priority[zt_file.prio_min]);
770 vty_out(vty, "\n");
771 }
772
773 if (zt_filterfile.parent.prio_min != ZLOG_DISABLED
774 && zt_filterfile.parent.filename) {
775 vty_out(vty, "log filtered-file %s",
776 zt_filterfile.parent.filename);
777
778 if (zt_filterfile.parent.prio_min != log_default_lvl)
779 vty_out(vty, " %s",
780 zlog_priority[zt_filterfile.parent.prio_min]);
781 vty_out(vty, "\n");
782 }
783
784 if (log_config_stdout_lvl != ZLOG_DISABLED) {
785 vty_out(vty, "log stdout");
786
787 if (log_config_stdout_lvl != log_default_lvl)
788 vty_out(vty, " %s",
789 zlog_priority[log_config_stdout_lvl]);
790 vty_out(vty, "\n");
791 }
792
793 if (log_config_syslog_lvl != ZLOG_DISABLED) {
794 vty_out(vty, "log syslog");
795
796 if (log_config_syslog_lvl != log_default_lvl)
797 vty_out(vty, " %s",
798 zlog_priority[log_config_syslog_lvl]);
799 vty_out(vty, "\n");
800 }
801
802 if (log_cmdline_syslog_lvl != ZLOG_DISABLED) {
803 vty_out(vty,
804 "! \"log syslog %s\" enabled by \"--log\" startup option\n",
805 zlog_priority[log_cmdline_syslog_lvl]);
806 show_cmdline_hint = true;
807 }
808 if (log_cmdline_stdout_lvl != ZLOG_DISABLED) {
809 vty_out(vty,
810 "! \"log stdout %s\" enabled by \"--log\" startup option\n",
811 zlog_priority[log_cmdline_stdout_lvl]);
812 show_cmdline_hint = true;
813 }
814 if (zt_file_cmdline.prio_min != ZLOG_DISABLED) {
815 vty_out(vty,
816 "! \"log file %s %s\" enabled by \"--log\" startup option\n",
817 zt_file_cmdline.filename,
818 zlog_priority[zt_file_cmdline.prio_min]);
819 show_cmdline_hint = true;
820 }
821 if (show_cmdline_hint)
822 vty_out(vty,
823 "! use \"clear log cmdline-targets\" to remove this target\n");
824
825 if (zlog_syslog_get_facility() != LOG_DAEMON)
826 vty_out(vty, "log facility %s\n",
827 facility_name(zlog_syslog_get_facility()));
828
829 if (zt_file.record_priority == 1)
830 vty_out(vty, "log record-priority\n");
831
832 if (zt_file.ts_subsec > 0)
833 vty_out(vty, "log timestamp precision %d\n",
834 zt_file.ts_subsec);
835
836 if (!zlog_get_prefix_ec())
837 vty_out(vty, "no log error-category\n");
838 if (!zlog_get_prefix_xid())
839 vty_out(vty, "no log unique-id\n");
840
841 if (logmsgs_with_persist_bt) {
842 struct xrefdata *xrd;
843 struct xrefdata_logmsg *xrdl;
844
845 vty_out(vty, "!\n");
846
847 frr_each (xrefdata_uid, &xrefdata_uid, xrd) {
848 if (xrd->xref->type != XREFT_LOGMSG)
849 continue;
850
851 xrdl = container_of(xrd, struct xrefdata_logmsg,
852 xrefdata);
853 if (xrdl->fl_print_bt & LOGMSG_FLAG_PERSISTENT)
854 vty_out(vty, "debug unique-id %s backtrace\n",
855 xrd->uid);
856 }
857 }
858 }
859
860 static int log_vty_init(const char *progname, const char *protoname,
861 unsigned short instance, uid_t uid, gid_t gid)
862 {
863 zlog_progname = progname;
864 zlog_protoname = protoname;
865
866 zlog_set_prefix_ec(true);
867 zlog_set_prefix_xid(true);
868
869 zlog_filterfile_init(&zt_filterfile);
870
871 if (sd_stdout_is_journal) {
872 stdout_journald_in_use = true;
873 zlog_5424_init(&zt_stdout_journald);
874 zlog_5424_apply_dst(&zt_stdout_journald);
875 } else
876 zlog_file_set_fd(&zt_stdout_file, STDOUT_FILENO);
877 return 0;
878 }
879
880 __attribute__((_CONSTRUCTOR(475))) static void log_vty_preinit(void)
881 {
882 hook_register(zlog_init, log_vty_init);
883 }
884
885 void log_cmd_init(void)
886 {
887 install_element(VIEW_NODE, &show_logging_cmd);
888 install_element(ENABLE_NODE, &clear_log_cmdline_cmd);
889
890 install_element(CONFIG_NODE, &config_log_stdout_cmd);
891 install_element(CONFIG_NODE, &no_config_log_stdout_cmd);
892 install_element(CONFIG_NODE, &config_log_monitor_cmd);
893 install_element(CONFIG_NODE, &no_config_log_monitor_cmd);
894 install_element(CONFIG_NODE, &config_log_file_cmd);
895 install_element(CONFIG_NODE, &no_config_log_file_cmd);
896 install_element(CONFIG_NODE, &config_log_syslog_cmd);
897 install_element(CONFIG_NODE, &no_config_log_syslog_cmd);
898 install_element(CONFIG_NODE, &config_log_facility_cmd);
899 install_element(CONFIG_NODE, &no_config_log_facility_cmd);
900 install_element(CONFIG_NODE, &config_log_record_priority_cmd);
901 install_element(CONFIG_NODE, &no_config_log_record_priority_cmd);
902 install_element(CONFIG_NODE, &config_log_timestamp_precision_cmd);
903 install_element(CONFIG_NODE, &no_config_log_timestamp_precision_cmd);
904 install_element(CONFIG_NODE, &config_log_ec_cmd);
905 install_element(CONFIG_NODE, &config_log_xid_cmd);
906
907 install_element(VIEW_NODE, &show_log_filter_cmd);
908 install_element(CONFIG_NODE, &log_filter_cmd);
909 install_element(CONFIG_NODE, &log_filter_clear_cmd);
910 install_element(CONFIG_NODE, &config_log_filterfile_cmd);
911 install_element(CONFIG_NODE, &no_config_log_filterfile_cmd);
912 install_element(CONFIG_NODE, &log_immediate_mode_cmd);
913
914 install_element(ENABLE_NODE, &debug_uid_backtrace_cmd);
915 install_element(CONFIG_NODE, &debug_uid_backtrace_cmd);
916
917 log_5424_cmd_init();
918 }