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