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