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