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