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