blob: 0282350434cdcfb8d5161a2e03cf25d04b1095c3 [file] [log] [blame]
Neels Hofmeyr17518fe2017-06-20 04:35:06 +02001/*
2 * (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
Holger Hans Peter Freyther2d6ad132014-12-05 09:35:30 +01003 * (C) 2009-2014 by Holger Hans Peter Freyther
Harald Welte3fb0b6f2010-05-19 19:02:52 +02004 * All Rights Reserved
5 *
Harald Weltee08da972017-11-13 01:00:26 +09006 * SPDX-License-Identifier: GPL-2.0+
7 *
Harald Welte3fb0b6f2010-05-19 19:02:52 +02008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23
24#include <stdlib.h>
25#include <string.h>
26
Harald Welte28222962011-02-18 20:37:04 +010027#include "../../config.h"
28
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010029#include <osmocom/core/talloc.h>
30#include <osmocom/core/logging.h>
Neels Hofmeyrba0762d2018-09-10 13:56:03 +020031#include <osmocom/core/logging_internal.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010032#include <osmocom/core/utils.h>
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +000033#include <osmocom/core/strrb.h>
34#include <osmocom/core/loggingrb.h>
Harald Welteaa00f992016-12-02 15:30:02 +010035#include <osmocom/core/gsmtap.h>
Harald Weltee4d9a2c2020-09-27 11:28:58 +020036#include <osmocom/core/application.h>
Harald Welte3fb0b6f2010-05-19 19:02:52 +020037
38#include <osmocom/vty/command.h>
39#include <osmocom/vty/buffer.h>
40#include <osmocom/vty/vty.h>
41#include <osmocom/vty/telnet_interface.h>
42#include <osmocom/vty/logging.h>
43
Harald Welte28222962011-02-18 20:37:04 +010044#define LOG_STR "Configure logging sub-system\n"
Neels Hofmeyrba0762d2018-09-10 13:56:03 +020045#define LEVEL_STR "Set the log level for a specified category\n"
46
Neels Hofmeyr9540c242018-09-12 00:20:50 +020047#define CATEGORY_ALL_STR "Deprecated alias for 'force-all'\n"
48#define FORCE_ALL_STR \
49 "Globally force all logging categories to a specific level. This is released by the" \
50 " 'no logging level force-all' command. Note: any 'logging level <category> <level>'" \
51 " commands will have no visible effect after this, until the forced level is released.\n"
52#define NO_FORCE_ALL_STR \
53 "Release any globally forced log level set with 'logging level force-all <level>'\n"
Neels Hofmeyrba0762d2018-09-10 13:56:03 +020054
Neels Hofmeyr9540c242018-09-12 00:20:50 +020055#define LOG_LEVEL_ARGS "(debug|info|notice|error|fatal)"
Neels Hofmeyrba0762d2018-09-10 13:56:03 +020056#define LOG_LEVEL_STRS \
57 "Log debug messages and higher levels\n" \
58 "Log informational messages and higher levels\n" \
59 "Log noticeable messages and higher levels\n" \
60 "Log error messages and higher levels\n" \
61 "Log only fatal messages\n"
62
Neels Hofmeyr9540c242018-09-12 00:20:50 +020063#define EVERYTHING_STR "Deprecated alias for 'no logging level force-all'\n"
Harald Welte28222962011-02-18 20:37:04 +010064
Harald Welte8c648252017-10-16 15:17:03 +020065/*! \file logging_vty.c
Neels Hofmeyr87e45502017-06-20 00:17:59 +020066 * Configuration of logging from VTY
Harald Welte96e2a002017-06-12 21:44:18 +020067 *
Harald Welte8c648252017-10-16 15:17:03 +020068 * This module implements
69 * - functions that permit configuration of the libosmocore logging
70 * framework from VTY commands in the configure -> logging node.
71 *
72 * - functions that permit logging *to* a VTY session. Basically each
73 * VTY session gets its own log target, with configurable
74 * per-subsystem log levels. This is performed internally via the
75 * \ref log_target_create_vty function.
76 *
77 * You have to call \ref logging_vty_add_cmds from your application
78 * once to enable both of the above.
79 *
Harald Welte96e2a002017-06-12 21:44:18 +020080 */
81
Harald Welte76e72ab2011-02-17 15:52:39 +010082static void _vty_output(struct log_target *tgt,
83 unsigned int level, const char *line)
Harald Welte3fb0b6f2010-05-19 19:02:52 +020084{
85 struct vty *vty = tgt->tgt_vty.vty;
86 vty_out(vty, "%s", line);
87 /* This is an ugly hack, but there is no easy way... */
88 if (strchr(line, '\n'))
89 vty_out(vty, "\r");
90}
91
92struct log_target *log_target_create_vty(struct vty *vty)
93{
94 struct log_target *target;
95
96 target = log_target_create();
97 if (!target)
98 return NULL;
99
100 target->tgt_vty.vty = vty;
101 target->output = _vty_output;
102 return target;
103}
104
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200105/*! Get tgt with log lock acquired, return and release lock with warning if tgt
106 * is not found. Lock must be released later with log_tgt_mutex_unlock().
107 */
108#define ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt) \
109 do { \
110 log_tgt_mutex_lock(); \
111 tgt = osmo_log_vty2tgt(vty); \
112 if (!(tgt)) { \
113 log_tgt_mutex_unlock(); \
114 return CMD_WARNING; \
115 } \
116 } while (0)
117
118#define RET_WITH_UNLOCK(ret) \
119 do { \
120 log_tgt_mutex_unlock(); \
121 return (ret); \
122 } while (0)
123
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200124DEFUN(enable_logging,
125 enable_logging_cmd,
126 "logging enable",
127 LOGGING_STR
128 "Enables logging to this vty\n")
129{
130 struct telnet_connection *conn;
131
132 conn = (struct telnet_connection *) vty->priv;
133 if (conn->dbg) {
134 vty_out(vty, "Logging already enabled.%s", VTY_NEWLINE);
135 return CMD_WARNING;
136 }
137
138 conn->dbg = log_target_create_vty(vty);
139 if (!conn->dbg)
140 return CMD_WARNING;
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200141 log_tgt_mutex_lock();
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200142 log_add_target(conn->dbg);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200143 RET_WITH_UNLOCK(CMD_SUCCESS);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200144}
145
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200146/*! Get log target associated to VTY console.
147 * \param[in] vty Log target type
148 * \returns Log target (if logging enabled), NULL otherwise
149 * Must be called with mutex osmo_log_tgt_mutex held, see log_tgt_mutex_lock.
150 */
Harald Weltea62648b2011-02-18 21:03:27 +0100151struct log_target *osmo_log_vty2tgt(struct vty *vty)
152{
153 struct telnet_connection *conn;
154
155 if (vty->node == CFG_LOG_NODE)
156 return vty->index;
157
158
159 conn = (struct telnet_connection *) vty->priv;
160 if (!conn->dbg)
161 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
162
163 return conn->dbg;
164}
165
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200166DEFUN(logging_fltr_all,
167 logging_fltr_all_cmd,
168 "logging filter all (0|1)",
169 LOGGING_STR FILTER_STR
170 "Do you want to log all messages?\n"
171 "Only print messages matched by other filters\n"
172 "Bypass filter and print all messages\n")
173{
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200174 struct log_target *tgt;
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200175
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200176 ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200177
Harald Weltea62648b2011-02-18 21:03:27 +0100178 log_set_all_filter(tgt, atoi(argv[0]));
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200179 RET_WITH_UNLOCK(CMD_SUCCESS);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200180}
181
182DEFUN(logging_use_clr,
183 logging_use_clr_cmd,
184 "logging color (0|1)",
185 LOGGING_STR "Configure color-printing for log messages\n"
186 "Don't use color for printing messages\n"
187 "Use color for printing messages\n")
188{
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200189 struct log_target *tgt;
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200190
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200191 ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200192
Harald Weltea62648b2011-02-18 21:03:27 +0100193 log_set_use_color(tgt, atoi(argv[0]));
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200194 RET_WITH_UNLOCK(CMD_SUCCESS);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200195}
196
197DEFUN(logging_prnt_timestamp,
198 logging_prnt_timestamp_cmd,
199 "logging timestamp (0|1)",
200 LOGGING_STR "Configure log message timestamping\n"
201 "Don't prefix each log message\n"
202 "Prefix each log message with current timestamp\n")
203{
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200204 struct log_target *tgt;
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200205
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200206 ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200207
Harald Weltea62648b2011-02-18 21:03:27 +0100208 log_set_print_timestamp(tgt, atoi(argv[0]));
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200209 RET_WITH_UNLOCK(CMD_SUCCESS);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200210}
211
Holger Hans Peter Freyther2d6ad132014-12-05 09:35:30 +0100212DEFUN(logging_prnt_ext_timestamp,
213 logging_prnt_ext_timestamp_cmd,
214 "logging print extended-timestamp (0|1)",
215 LOGGING_STR "Log output settings\n"
216 "Configure log message timestamping\n"
217 "Don't prefix each log message\n"
218 "Prefix each log message with current timestamp with YYYYMMDDhhmmssnnn\n")
219{
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200220 struct log_target *tgt;
Holger Hans Peter Freyther2d6ad132014-12-05 09:35:30 +0100221
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200222 ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt);
Holger Hans Peter Freyther2d6ad132014-12-05 09:35:30 +0100223
224 log_set_print_extended_timestamp(tgt, atoi(argv[0]));
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200225 RET_WITH_UNLOCK(CMD_SUCCESS);
Holger Hans Peter Freyther2d6ad132014-12-05 09:35:30 +0100226}
227
228DEFUN(logging_prnt_cat,
229 logging_prnt_cat_cmd,
230 "logging print category (0|1)",
231 LOGGING_STR "Log output settings\n"
232 "Configure log message\n"
233 "Don't prefix each log message\n"
234 "Prefix each log message with category/subsystem name\n")
235{
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200236 struct log_target *tgt;
237 ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt);
Holger Hans Peter Freyther2d6ad132014-12-05 09:35:30 +0100238
239 log_set_print_category(tgt, atoi(argv[0]));
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200240 RET_WITH_UNLOCK(CMD_SUCCESS);
Holger Hans Peter Freyther2d6ad132014-12-05 09:35:30 +0100241}
242
Neels Hofmeyrbd7bd392018-01-16 01:52:29 +0100243DEFUN(logging_prnt_cat_hex,
244 logging_prnt_cat_hex_cmd,
245 "logging print category-hex (0|1)",
246 LOGGING_STR "Log output settings\n"
247 "Configure log message\n"
248 "Don't prefix each log message\n"
249 "Prefix each log message with category/subsystem nr in hex ('<000b>')\n")
250{
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200251 struct log_target *tgt;
Neels Hofmeyrbd7bd392018-01-16 01:52:29 +0100252
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200253 ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt);
Neels Hofmeyrbd7bd392018-01-16 01:52:29 +0100254
255 log_set_print_category_hex(tgt, atoi(argv[0]));
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200256 RET_WITH_UNLOCK(CMD_SUCCESS);
Neels Hofmeyrbd7bd392018-01-16 01:52:29 +0100257}
258
Neels Hofmeyr886e5482018-01-16 01:49:37 +0100259DEFUN(logging_prnt_level,
260 logging_prnt_level_cmd,
261 "logging print level (0|1)",
262 LOGGING_STR "Log output settings\n"
263 "Configure log message\n"
264 "Don't prefix each log message\n"
265 "Prefix each log message with the log level name\n")
266{
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200267 struct log_target *tgt;
Neels Hofmeyr886e5482018-01-16 01:49:37 +0100268
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200269 ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt);
Neels Hofmeyr886e5482018-01-16 01:49:37 +0100270
271 log_set_print_level(tgt, atoi(argv[0]));
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200272 RET_WITH_UNLOCK(CMD_SUCCESS);
Neels Hofmeyr886e5482018-01-16 01:49:37 +0100273}
274
Neels Hofmeyr22772cc2018-02-06 00:52:08 +0100275static const struct value_string logging_print_file_args[] = {
276 { LOG_FILENAME_NONE, "0" },
277 { LOG_FILENAME_PATH, "1" },
278 { LOG_FILENAME_BASENAME, "basename" },
279 { 0, NULL }
280};
281
Neels Hofmeyrc6fd2452018-01-16 01:57:38 +0100282DEFUN(logging_prnt_file,
283 logging_prnt_file_cmd,
Neels Hofmeyr77ae45d2018-08-27 20:32:36 +0200284 "logging print file (0|1|basename) [last]",
Neels Hofmeyrc6fd2452018-01-16 01:57:38 +0100285 LOGGING_STR "Log output settings\n"
286 "Configure log message\n"
287 "Don't prefix each log message\n"
288 "Prefix each log message with the source file and line\n"
Neels Hofmeyr77ae45d2018-08-27 20:32:36 +0200289 "Prefix each log message with the source file's basename (strip leading paths) and line\n"
290 "Log source file info at the end of a log line. If omitted, log source file info just"
291 " before the log text.\n")
Neels Hofmeyrc6fd2452018-01-16 01:57:38 +0100292{
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200293 struct log_target *tgt;
Neels Hofmeyrc6fd2452018-01-16 01:57:38 +0100294
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200295 ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt);
Neels Hofmeyrc6fd2452018-01-16 01:57:38 +0100296
Neels Hofmeyr22772cc2018-02-06 00:52:08 +0100297 log_set_print_filename2(tgt, get_string_value(logging_print_file_args, argv[0]));
Neels Hofmeyr77ae45d2018-08-27 20:32:36 +0200298 if (argc > 1)
299 log_set_print_filename_pos(tgt, LOG_FILENAME_POS_LINE_END);
300 else
301 log_set_print_filename_pos(tgt, LOG_FILENAME_POS_HEADER_END);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200302 RET_WITH_UNLOCK(CMD_SUCCESS);
Neels Hofmeyrc6fd2452018-01-16 01:57:38 +0100303}
304
Neels Hofmeyrba0762d2018-09-10 13:56:03 +0200305static void add_category_strings(char **cmd_str_p, char **doc_str_p,
306 const struct log_info *categories)
307{
Pau Espin Pedrolc21ba152019-08-02 20:32:34 +0200308 char buf[128];
Neels Hofmeyrba0762d2018-09-10 13:56:03 +0200309 int i;
310 for (i = 0; i < categories->num_cat; i++) {
311 if (categories->cat[i].name == NULL)
312 continue;
313 /* skip the leading 'D' in each category name, hence '+ 1' */
Pau Espin Pedrolc21ba152019-08-02 20:32:34 +0200314 osmo_str_tolower_buf(buf, sizeof(buf), categories->cat[i].name + 1);
Neels Hofmeyrba0762d2018-09-10 13:56:03 +0200315 osmo_talloc_asprintf(tall_log_ctx, *cmd_str_p, "%s%s",
Pau Espin Pedrolc21ba152019-08-02 20:32:34 +0200316 i ? "|" : "", buf);
Neels Hofmeyrba0762d2018-09-10 13:56:03 +0200317 osmo_talloc_asprintf(tall_log_ctx, *doc_str_p, "%s\n",
318 categories->cat[i].description);
319 }
320}
321
322static void gen_logging_level_cmd_strs(struct cmd_element *cmd,
323 const char *level_args, const char *level_strs)
324{
325 char *cmd_str = NULL;
326 char *doc_str = NULL;
327
328 assert_loginfo(__func__);
329
330 OSMO_ASSERT(cmd->string == NULL);
331 OSMO_ASSERT(cmd->doc == NULL);
332
Neels Hofmeyr9540c242018-09-12 00:20:50 +0200333 osmo_talloc_asprintf(tall_log_ctx, cmd_str, "logging level (");
Neels Hofmeyrba0762d2018-09-10 13:56:03 +0200334 osmo_talloc_asprintf(tall_log_ctx, doc_str,
335 LOGGING_STR
Neels Hofmeyr9540c242018-09-12 00:20:50 +0200336 LEVEL_STR);
Neels Hofmeyrba0762d2018-09-10 13:56:03 +0200337 add_category_strings(&cmd_str, &doc_str, osmo_log_info);
338 osmo_talloc_asprintf(tall_log_ctx, cmd_str, ") %s", level_args);
339 osmo_talloc_asprintf(tall_log_ctx, doc_str, "%s", level_strs);
340
Harald Weltebebec212020-07-15 12:21:29 +0200341 talloc_set_name_const(cmd_str, "vty_log_level_cmd_str");
342 talloc_set_name_const(doc_str, "vty_log_level_doc_str");
343
Neels Hofmeyrba0762d2018-09-10 13:56:03 +0200344 cmd->string = cmd_str;
345 cmd->doc = doc_str;
346}
347
Neels Hofmeyr9540c242018-09-12 00:20:50 +0200348/* logging level (<categories>) (debug|...|fatal) */
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200349DEFUN(logging_level,
350 logging_level_cmd,
Pablo Neira Ayuso04139f12011-03-09 13:05:08 +0100351 NULL, /* cmdstr is dynamically set in logging_vty_add_cmds(). */
352 NULL) /* same thing for helpstr. */
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200353{
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200354 struct log_target *tgt;
Harald Weltea62648b2011-02-18 21:03:27 +0100355 int category = log_parse_category(argv[0]);
356 int level = log_parse_level(argv[1]);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200357
Harald Weltea62648b2011-02-18 21:03:27 +0100358 if (level < 0) {
359 vty_out(vty, "Invalid level `%s'%s", argv[1], VTY_NEWLINE);
Pau Espin Pedrol57d11182020-01-02 16:21:14 +0100360 return CMD_WARNING;
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200361 }
362
Harald Weltea62648b2011-02-18 21:03:27 +0100363 if (category < 0) {
364 vty_out(vty, "Invalid category `%s'%s", argv[0], VTY_NEWLINE);
Pau Espin Pedrol57d11182020-01-02 16:21:14 +0100365 return CMD_WARNING;
Harald Weltea62648b2011-02-18 21:03:27 +0100366 }
367
Pau Espin Pedrol57d11182020-01-02 16:21:14 +0100368 ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt);
369
Harald Weltea62648b2011-02-18 21:03:27 +0100370 tgt->categories[category].enabled = 1;
371 tgt->categories[category].loglevel = level;
372
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200373 RET_WITH_UNLOCK(CMD_SUCCESS);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200374}
375
Neels Hofmeyr28fc0782018-09-12 02:32:02 +0200376DEFUN(logging_level_set_all, logging_level_set_all_cmd,
377 "logging level set-all " LOG_LEVEL_ARGS,
378 LOGGING_STR LEVEL_STR
379 "Once-off set all categories to the given log level. There is no single command"
380 " to take back these changes -- each category is set to the given level, period.\n"
381 LOG_LEVEL_STRS)
382{
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200383 struct log_target *tgt;
Neels Hofmeyr28fc0782018-09-12 02:32:02 +0200384 int level = log_parse_level(argv[0]);
385 int i;
Neels Hofmeyrea6f5192018-10-01 15:51:18 +0200386
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200387 ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt);
Neels Hofmeyrea6f5192018-10-01 15:51:18 +0200388
Neels Hofmeyr28fc0782018-09-12 02:32:02 +0200389 for (i = 0; i < osmo_log_info->num_cat; i++) {
390 struct log_category *cat = &tgt->categories[i];
391 /* skip empty entries in the array */
392 if (!osmo_log_info->cat[i].name)
393 continue;
394
395 cat->enabled = 1;
396 cat->loglevel = level;
397 }
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200398 RET_WITH_UNLOCK(CMD_SUCCESS);
Neels Hofmeyr28fc0782018-09-12 02:32:02 +0200399}
400
Neels Hofmeyr9540c242018-09-12 00:20:50 +0200401/* logging level (<categories>) everything */
Neels Hofmeyr7e0686c2018-09-10 20:58:52 +0200402DEFUN_DEPRECATED(deprecated_logging_level_everything, deprecated_logging_level_everything_cmd,
403 NULL, /* cmdstr is dynamically set in logging_vty_add_cmds(). */
404 NULL) /* same thing for helpstr. */
405{
406 vty_out(vty, "%% Ignoring deprecated logging level 'everything' keyword%s", VTY_NEWLINE);
407 return CMD_SUCCESS;
408}
409
Neels Hofmeyr9540c242018-09-12 00:20:50 +0200410DEFUN(logging_level_force_all, logging_level_force_all_cmd,
411 "logging level force-all " LOG_LEVEL_ARGS,
412 LOGGING_STR LEVEL_STR FORCE_ALL_STR LOG_LEVEL_STRS)
413{
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200414 struct log_target *tgt;
Neels Hofmeyr9540c242018-09-12 00:20:50 +0200415 int level = log_parse_level(argv[0]);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200416
417 ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt);
418
Neels Hofmeyr9540c242018-09-12 00:20:50 +0200419 log_set_log_level(tgt, level);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200420 RET_WITH_UNLOCK(CMD_SUCCESS);
Neels Hofmeyr9540c242018-09-12 00:20:50 +0200421}
422
423DEFUN(no_logging_level_force_all, no_logging_level_force_all_cmd,
424 "no logging level force-all",
425 NO_STR LOGGING_STR LEVEL_STR NO_FORCE_ALL_STR)
426{
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200427 struct log_target *tgt;
428
429 ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt);
430
Neels Hofmeyr9540c242018-09-12 00:20:50 +0200431 log_set_log_level(tgt, 0);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200432 RET_WITH_UNLOCK(CMD_SUCCESS);
Neels Hofmeyr9540c242018-09-12 00:20:50 +0200433}
434
435/* 'logging level all (debug|...|fatal)' */
436ALIAS_DEPRECATED(logging_level_force_all, deprecated_logging_level_all_cmd,
437 "logging level all " LOG_LEVEL_ARGS,
438 LOGGING_STR LEVEL_STR CATEGORY_ALL_STR LOG_LEVEL_STRS);
439
440/* 'logging level all everything' */
441ALIAS_DEPRECATED(no_logging_level_force_all, deprecated_logging_level_all_everything_cmd,
442 "logging level all everything",
443 LOGGING_STR LEVEL_STR CATEGORY_ALL_STR EVERYTHING_STR);
444
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200445DEFUN(logging_set_category_mask,
446 logging_set_category_mask_cmd,
Holger Hans Peter Freyther146d1d32011-10-03 23:15:41 +0200447 "logging set-log-mask MASK",
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200448 LOGGING_STR
Holger Hans Peter Freyther146d1d32011-10-03 23:15:41 +0200449 "Set the logmask of this logging target\n"
Neels Hofmeyr84ea2e02017-12-09 05:53:18 +0100450 "List of logging categories to log, e.g. 'abc:mno:xyz'. Available log categories depend on the specific"
451 " application, refer to the 'logging level' command. Optionally add individual log levels like"
452 " 'abc,1:mno,3:xyz,5', where the level numbers are"
453 " " OSMO_STRINGIFY(LOGL_DEBUG) "=" OSMO_STRINGIFY_VAL(LOGL_DEBUG)
454 " " OSMO_STRINGIFY(LOGL_INFO) "=" OSMO_STRINGIFY_VAL(LOGL_INFO)
455 " " OSMO_STRINGIFY(LOGL_NOTICE) "=" OSMO_STRINGIFY_VAL(LOGL_NOTICE)
456 " " OSMO_STRINGIFY(LOGL_ERROR) "=" OSMO_STRINGIFY_VAL(LOGL_ERROR)
457 " " OSMO_STRINGIFY(LOGL_FATAL) "=" OSMO_STRINGIFY_VAL(LOGL_FATAL)
458 "\n")
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200459{
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200460 struct log_target *tgt;
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200461
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200462 ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200463
Harald Weltea62648b2011-02-18 21:03:27 +0100464 log_parse_category_mask(tgt, argv[0]);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200465 RET_WITH_UNLOCK(CMD_SUCCESS);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200466}
467
Holger Hans Peter Freyther146d1d32011-10-03 23:15:41 +0200468ALIAS_DEPRECATED(logging_set_category_mask,
469 logging_set_category_mask_old_cmd,
470 "logging set log mask MASK",
471 LOGGING_STR
472 "Decide which categories to output.\n"
Neels Hofmeyr84ea2e02017-12-09 05:53:18 +0100473 "Log commands\n" "Mask commands\n"
474 "'set log mask' is deprecated, please refer to the docs of 'set-log-mask' instead\n");
Holger Hans Peter Freyther146d1d32011-10-03 23:15:41 +0200475
476
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200477DEFUN(diable_logging,
478 disable_logging_cmd,
479 "logging disable",
480 LOGGING_STR
481 "Disables logging to this vty\n")
482{
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200483 struct log_target *tgt;
Harald Weltea62648b2011-02-18 21:03:27 +0100484 struct telnet_connection *conn = (struct telnet_connection *) vty->priv;
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200485
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200486 ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200487
Harald Weltea62648b2011-02-18 21:03:27 +0100488 log_del_target(tgt);
489 talloc_free(tgt);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200490 conn->dbg = NULL;
Harald Weltea62648b2011-02-18 21:03:27 +0100491
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200492 RET_WITH_UNLOCK(CMD_SUCCESS);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200493}
494
495static void vty_print_logtarget(struct vty *vty, const struct log_info *info,
496 const struct log_target *tgt)
497{
498 unsigned int i;
499
500 vty_out(vty, " Global Loglevel: %s%s",
501 log_level_str(tgt->loglevel), VTY_NEWLINE);
502 vty_out(vty, " Use color: %s, Print Timestamp: %s%s",
503 tgt->use_color ? "On" : "Off",
504 tgt->print_timestamp ? "On" : "Off", VTY_NEWLINE);
505
506 vty_out(vty, " Log Level specific information:%s", VTY_NEWLINE);
507
508 for (i = 0; i < info->num_cat; i++) {
509 const struct log_category *cat = &tgt->categories[i];
Daniel Willmann55363a92016-11-15 10:05:51 +0100510 /* Skip categories that were not initialized */
511 if (!info->cat[i].name)
512 continue;
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200513 vty_out(vty, " %-10s %-10s %-8s %s%s",
514 info->cat[i].name+1, log_level_str(cat->loglevel),
515 cat->enabled ? "Enabled" : "Disabled",
516 info->cat[i].description,
517 VTY_NEWLINE);
518 }
Harald Welte6d2d4d62013-03-10 09:53:24 +0000519
520 vty_out(vty, " Log Filter 'ALL': %s%s",
Neels Hofmeyr8b86cd72017-02-23 18:03:28 +0100521 tgt->filter_map & (1 << LOG_FLT_ALL) ? "Enabled" : "Disabled",
Harald Welte6d2d4d62013-03-10 09:53:24 +0000522 VTY_NEWLINE);
523
Harald Weltefb84f322013-06-06 07:33:54 +0200524 /* print application specific filters */
525 if (info->print_fn)
526 info->print_fn(vty, info, tgt);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200527}
528
529#define SHOW_LOG_STR "Show current logging configuration\n"
530
531DEFUN(show_logging_vty,
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000532 show_logging_vty_cmd,
533 "show logging vty",
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200534 SHOW_STR SHOW_LOG_STR
535 "Show current logging configuration for this vty\n")
536{
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200537 struct log_target *tgt;
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200538
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200539 ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt);
Harald Weltea62648b2011-02-18 21:03:27 +0100540
541 vty_print_logtarget(vty, osmo_log_info, tgt);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200542 RET_WITH_UNLOCK(CMD_SUCCESS);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200543}
544
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000545DEFUN(show_alarms,
546 show_alarms_cmd,
547 "show alarms",
548 SHOW_STR SHOW_LOG_STR
549 "Show the contents of the logging ringbuffer\n")
550{
551 int i, num_alarms;
552 struct osmo_strrb *rb;
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200553 struct log_target *tgt;
554
555 log_tgt_mutex_lock();
556 tgt = log_target_find(LOG_TGT_TYPE_STRRB, NULL);
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000557 if (!tgt) {
558 vty_out(vty, "%% No alarms, run 'log alarms <2-32700>'%s",
559 VTY_NEWLINE);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200560 RET_WITH_UNLOCK(CMD_WARNING);
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000561 }
562
563 rb = tgt->tgt_rb.rb;
564 num_alarms = osmo_strrb_elements(rb);
565
566 vty_out(vty, "%% Showing %i alarms%s", num_alarms, VTY_NEWLINE);
567
568 for (i = 0; i < num_alarms; i++)
569 vty_out(vty, "%% %s%s", osmo_strrb_get_nth(rb, i),
570 VTY_NEWLINE);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200571 RET_WITH_UNLOCK(CMD_SUCCESS);
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000572}
573
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200574gDEFUN(cfg_description, cfg_description_cmd,
575 "description .TEXT",
Thorsten Alteholza81055d2017-03-02 22:13:48 +0100576 "Save human-readable description of the object\n"
Holger Hans Peter Freytherc9b3e062012-07-25 13:02:49 +0200577 "Text until the end of the line\n")
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200578{
579 char **dptr = vty->index_sub;
580
581 if (!dptr) {
582 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
583 return CMD_WARNING;
584 }
585
Holger Hans Peter Freytherff0670e2011-02-24 14:20:41 +0100586 if (*dptr)
587 talloc_free(*dptr);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200588 *dptr = argv_concat(argv, argc, 0);
Holger Hans Peter Freyther6a75d162013-07-14 09:07:11 +0200589 if (!*dptr)
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200590 return CMD_WARNING;
591
592 return CMD_SUCCESS;
593}
594
595gDEFUN(cfg_no_description, cfg_no_description_cmd,
596 "no description",
597 NO_STR
598 "Remove description of the object\n")
599{
600 char **dptr = vty->index_sub;
601
602 if (!dptr) {
603 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
604 return CMD_WARNING;
605 }
606
607 if (*dptr) {
608 talloc_free(*dptr);
609 *dptr = NULL;
610 }
611
612 return CMD_SUCCESS;
613}
614
Harald Welte28222962011-02-18 20:37:04 +0100615/* Support for configuration of log targets != the current vty */
616
617struct cmd_node cfg_log_node = {
618 CFG_LOG_NODE,
619 "%s(config-log)# ",
620 1
621};
622
Harald Welte28222962011-02-18 20:37:04 +0100623#ifdef HAVE_SYSLOG_H
624
625#include <syslog.h>
626
627static const int local_sysl_map[] = {
628 [0] = LOG_LOCAL0,
629 [1] = LOG_LOCAL1,
630 [2] = LOG_LOCAL2,
631 [3] = LOG_LOCAL3,
632 [4] = LOG_LOCAL4,
633 [5] = LOG_LOCAL5,
634 [6] = LOG_LOCAL6,
635 [7] = LOG_LOCAL7
636};
637
Harald Weltede79cee2011-02-24 23:47:57 +0100638/* From VTY core code */
639extern struct host host;
640
Harald Welte28222962011-02-18 20:37:04 +0100641static int _cfg_log_syslog(struct vty *vty, int facility)
642{
643 struct log_target *tgt;
644
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200645 log_tgt_mutex_lock();
Harald Welte28222962011-02-18 20:37:04 +0100646 /* First delete the old syslog target, if any */
647 tgt = log_target_find(LOG_TGT_TYPE_SYSLOG, NULL);
648 if (tgt)
649 log_target_destroy(tgt);
650
Harald Weltede79cee2011-02-24 23:47:57 +0100651 tgt = log_target_create_syslog(host.app_info->name, 0, facility);
Harald Welte28222962011-02-18 20:37:04 +0100652 if (!tgt) {
653 vty_out(vty, "%% Unable to open syslog%s", VTY_NEWLINE);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200654 RET_WITH_UNLOCK(CMD_WARNING);
Harald Welte28222962011-02-18 20:37:04 +0100655 }
656 log_add_target(tgt);
657
658 vty->index = tgt;
659 vty->node = CFG_LOG_NODE;
660
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200661 RET_WITH_UNLOCK(CMD_SUCCESS);
Harald Welte28222962011-02-18 20:37:04 +0100662}
663
664DEFUN(cfg_log_syslog_local, cfg_log_syslog_local_cmd,
665 "log syslog local <0-7>",
666 LOG_STR "Logging via syslog\n" "Syslog LOCAL facility\n"
667 "Local facility number\n")
668{
669 int local = atoi(argv[0]);
670 int facility = local_sysl_map[local];
671
672 return _cfg_log_syslog(vty, facility);
673}
674
675static struct value_string sysl_level_names[] = {
676 { LOG_AUTHPRIV, "authpriv" },
677 { LOG_CRON, "cron" },
678 { LOG_DAEMON, "daemon" },
679 { LOG_FTP, "ftp" },
680 { LOG_LPR, "lpr" },
681 { LOG_MAIL, "mail" },
682 { LOG_NEWS, "news" },
683 { LOG_USER, "user" },
684 { LOG_UUCP, "uucp" },
685 /* only for value -> string conversion */
686 { LOG_LOCAL0, "local 0" },
687 { LOG_LOCAL1, "local 1" },
688 { LOG_LOCAL2, "local 2" },
689 { LOG_LOCAL3, "local 3" },
690 { LOG_LOCAL4, "local 4" },
691 { LOG_LOCAL5, "local 5" },
692 { LOG_LOCAL6, "local 6" },
693 { LOG_LOCAL7, "local 7" },
694 { 0, NULL }
695};
696
697DEFUN(cfg_log_syslog, cfg_log_syslog_cmd,
698 "log syslog (authpriv|cron|daemon|ftp|lpr|mail|news|user|uucp)",
Holger Hans Peter Freythera4463fd2011-10-03 23:17:36 +0200699 LOG_STR "Logging via syslog\n"
700 "Security/authorization messages facility\n"
701 "Clock daemon (cron/at) facility\n"
702 "General system daemon facility\n"
703 "Ftp daemon facility\n"
704 "Line printer facility\n"
705 "Mail facility\n"
706 "News facility\n"
707 "Generic facility\n"
708 "UUCP facility\n")
Harald Welte28222962011-02-18 20:37:04 +0100709{
710 int facility = get_string_value(sysl_level_names, argv[0]);
711
712 return _cfg_log_syslog(vty, facility);
713}
714
715DEFUN(cfg_no_log_syslog, cfg_no_log_syslog_cmd,
716 "no log syslog",
717 NO_STR LOG_STR "Logging via syslog\n")
718{
719 struct log_target *tgt;
720
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200721 log_tgt_mutex_lock();
Harald Welte28222962011-02-18 20:37:04 +0100722 tgt = log_target_find(LOG_TGT_TYPE_SYSLOG, NULL);
723 if (!tgt) {
724 vty_out(vty, "%% No syslog target found%s",
725 VTY_NEWLINE);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200726 RET_WITH_UNLOCK(CMD_WARNING);
Harald Welte28222962011-02-18 20:37:04 +0100727 }
728
729 log_target_destroy(tgt);
730
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200731 RET_WITH_UNLOCK(CMD_SUCCESS);
Harald Welte28222962011-02-18 20:37:04 +0100732}
733#endif /* HAVE_SYSLOG_H */
734
Vadim Yanitskiye7bf4352020-09-09 03:36:48 +0700735DEFUN(cfg_log_systemd_journal, cfg_log_systemd_journal_cmd,
736 "log systemd-journal [raw]",
737 LOG_STR "Logging to systemd-journal\n"
738 "Offload rendering of the meta information (location, category) to systemd\n")
739{
740#ifdef ENABLE_SYSTEMD_LOGGING
741 struct log_target *tgt;
742 bool raw = argc > 0;
743
744 log_tgt_mutex_lock();
745 tgt = log_target_find(LOG_TGT_TYPE_SYSTEMD, NULL);
746 if (tgt == NULL) {
747 tgt = log_target_create_systemd(raw);
748 if (tgt == NULL) {
749 vty_out(vty, "%% Unable to create systemd-journal "
750 "log target%s", VTY_NEWLINE);
751 RET_WITH_UNLOCK(CMD_WARNING);
752 }
753 log_add_target(tgt);
754 } else if (tgt->sd_journal.raw != raw) {
755 log_target_systemd_set_raw(tgt, raw);
756 }
757
758 vty->index = tgt;
759 vty->node = CFG_LOG_NODE;
760
761 RET_WITH_UNLOCK(CMD_SUCCESS);
762#else
763 vty_out(vty, "%% systemd-journal logging is not available "
764 "in this build of libosmocore%s", VTY_NEWLINE);
765 return CMD_WARNING;
766#endif /* ENABLE_SYSTEMD_LOGGING */
767}
768
769DEFUN(cfg_no_log_systemd_journal, cfg_no_log_systemd_journal_cmd,
770 "no log systemd-journal",
771 NO_STR LOG_STR "Logging to systemd-journal\n")
772{
773#ifdef ENABLE_SYSTEMD_LOGGING
774 struct log_target *tgt;
775
776 log_tgt_mutex_lock();
777 tgt = log_target_find(LOG_TGT_TYPE_SYSTEMD, NULL);
778 if (!tgt) {
779 vty_out(vty, "%% No systemd-journal logging active%s", VTY_NEWLINE);
780 RET_WITH_UNLOCK(CMD_WARNING);
781 }
782
783 log_target_destroy(tgt);
784
785 RET_WITH_UNLOCK(CMD_SUCCESS);
786#else
787 vty_out(vty, "%% systemd-journal logging is not available "
788 "in this build of libosmocore%s", VTY_NEWLINE);
789 return CMD_WARNING;
790#endif /* ENABLE_SYSTEMD_LOGGING */
791}
792
Harald Welteaa00f992016-12-02 15:30:02 +0100793DEFUN(cfg_log_gsmtap, cfg_log_gsmtap_cmd,
794 "log gsmtap [HOSTNAME]",
Neels Hofmeyrfd9ec3b2016-12-11 01:48:26 +0100795 LOG_STR "Logging via GSMTAP\n"
796 "Host name to send the GSMTAP logging to (UDP port 4729)\n")
Harald Welteaa00f992016-12-02 15:30:02 +0100797{
Max2f153b52018-01-04 12:25:57 +0100798 const char *hostname = argc ? argv[0] : "127.0.0.1";
Harald Welteaa00f992016-12-02 15:30:02 +0100799 struct log_target *tgt;
800
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200801 log_tgt_mutex_lock();
Harald Welteaa00f992016-12-02 15:30:02 +0100802 tgt = log_target_find(LOG_TGT_TYPE_GSMTAP, hostname);
803 if (!tgt) {
804 tgt = log_target_create_gsmtap(hostname, GSMTAP_UDP_PORT,
805 host.app_info->name, false,
806 true);
807 if (!tgt) {
Max2f153b52018-01-04 12:25:57 +0100808 vty_out(vty, "%% Unable to create GSMTAP log for %s%s",
809 hostname, VTY_NEWLINE);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200810 RET_WITH_UNLOCK(CMD_WARNING);
Harald Welteaa00f992016-12-02 15:30:02 +0100811 }
812 log_add_target(tgt);
813 }
814
815 vty->index = tgt;
816 vty->node = CFG_LOG_NODE;
817
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200818 RET_WITH_UNLOCK(CMD_SUCCESS);
Harald Welteaa00f992016-12-02 15:30:02 +0100819}
820
Harald Welte28222962011-02-18 20:37:04 +0100821DEFUN(cfg_log_stderr, cfg_log_stderr_cmd,
822 "log stderr",
823 LOG_STR "Logging via STDERR of the process\n")
824{
825 struct log_target *tgt;
826
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200827 log_tgt_mutex_lock();
Harald Welte28222962011-02-18 20:37:04 +0100828 tgt = log_target_find(LOG_TGT_TYPE_STDERR, NULL);
829 if (!tgt) {
830 tgt = log_target_create_stderr();
831 if (!tgt) {
832 vty_out(vty, "%% Unable to create stderr log%s",
833 VTY_NEWLINE);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200834 RET_WITH_UNLOCK(CMD_WARNING);
Harald Welte28222962011-02-18 20:37:04 +0100835 }
836 log_add_target(tgt);
837 }
838
839 vty->index = tgt;
840 vty->node = CFG_LOG_NODE;
841
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200842 RET_WITH_UNLOCK(CMD_SUCCESS);
Harald Welte28222962011-02-18 20:37:04 +0100843}
844
845DEFUN(cfg_no_log_stderr, cfg_no_log_stderr_cmd,
846 "no log stderr",
847 NO_STR LOG_STR "Logging via STDERR of the process\n")
848{
849 struct log_target *tgt;
850
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200851 log_tgt_mutex_lock();
Harald Welte28222962011-02-18 20:37:04 +0100852 tgt = log_target_find(LOG_TGT_TYPE_STDERR, NULL);
853 if (!tgt) {
854 vty_out(vty, "%% No stderr logging active%s", VTY_NEWLINE);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200855 RET_WITH_UNLOCK(CMD_WARNING);
Harald Welte28222962011-02-18 20:37:04 +0100856 }
857
858 log_target_destroy(tgt);
Harald Weltee4d9a2c2020-09-27 11:28:58 +0200859 osmo_stderr_target = NULL;
Harald Welte28222962011-02-18 20:37:04 +0100860
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200861 RET_WITH_UNLOCK(CMD_SUCCESS);
Harald Welte28222962011-02-18 20:37:04 +0100862}
863
864DEFUN(cfg_log_file, cfg_log_file_cmd,
865 "log file .FILENAME",
866 LOG_STR "Logging to text file\n" "Filename\n")
867{
868 const char *fname = argv[0];
869 struct log_target *tgt;
870
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200871 log_tgt_mutex_lock();
Harald Welte28222962011-02-18 20:37:04 +0100872 tgt = log_target_find(LOG_TGT_TYPE_FILE, fname);
873 if (!tgt) {
874 tgt = log_target_create_file(fname);
875 if (!tgt) {
876 vty_out(vty, "%% Unable to create file `%s'%s",
877 fname, VTY_NEWLINE);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200878 RET_WITH_UNLOCK(CMD_WARNING);
Harald Welte28222962011-02-18 20:37:04 +0100879 }
880 log_add_target(tgt);
881 }
882
883 vty->index = tgt;
884 vty->node = CFG_LOG_NODE;
885
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200886 RET_WITH_UNLOCK(CMD_SUCCESS);
Harald Welte28222962011-02-18 20:37:04 +0100887}
888
889
890DEFUN(cfg_no_log_file, cfg_no_log_file_cmd,
891 "no log file .FILENAME",
892 NO_STR LOG_STR "Logging to text file\n" "Filename\n")
893{
894 const char *fname = argv[0];
895 struct log_target *tgt;
896
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200897 log_tgt_mutex_lock();
Harald Welte28222962011-02-18 20:37:04 +0100898 tgt = log_target_find(LOG_TGT_TYPE_FILE, fname);
899 if (!tgt) {
900 vty_out(vty, "%% No such log file `%s'%s",
901 fname, VTY_NEWLINE);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200902 RET_WITH_UNLOCK(CMD_WARNING);
Harald Welte28222962011-02-18 20:37:04 +0100903 }
904
905 log_target_destroy(tgt);
906
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200907 RET_WITH_UNLOCK(CMD_SUCCESS);
Harald Welte28222962011-02-18 20:37:04 +0100908}
909
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000910DEFUN(cfg_log_alarms, cfg_log_alarms_cmd,
911 "log alarms <2-32700>",
912 LOG_STR "Logging alarms to osmo_strrb\n"
913 "Maximum number of messages to log\n")
914{
915 struct log_target *tgt;
916 unsigned int rbsize = atoi(argv[0]);
917
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200918
919 log_tgt_mutex_lock();
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000920 tgt = log_target_find(LOG_TGT_TYPE_STRRB, NULL);
921 if (tgt)
922 log_target_destroy(tgt);
923
924 tgt = log_target_create_rb(rbsize);
925 if (!tgt) {
926 vty_out(vty, "%% Unable to create osmo_strrb (size %u)%s",
927 rbsize, VTY_NEWLINE);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200928 RET_WITH_UNLOCK(CMD_WARNING);
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000929 }
930 log_add_target(tgt);
931
932 vty->index = tgt;
933 vty->node = CFG_LOG_NODE;
934
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200935 RET_WITH_UNLOCK(CMD_SUCCESS);
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000936}
937
938DEFUN(cfg_no_log_alarms, cfg_no_log_alarms_cmd,
939 "no log alarms",
940 NO_STR LOG_STR "Logging alarms to osmo_strrb\n")
941{
942 struct log_target *tgt;
943
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200944 log_tgt_mutex_lock();
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000945 tgt = log_target_find(LOG_TGT_TYPE_STRRB, NULL);
946 if (!tgt) {
947 vty_out(vty, "%% No osmo_strrb target found%s", VTY_NEWLINE);
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200948 RET_WITH_UNLOCK(CMD_WARNING);
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000949 }
950
951 log_target_destroy(tgt);
952
Pau Espin Pedrold12f6982019-09-17 18:38:58 +0200953 RET_WITH_UNLOCK(CMD_SUCCESS);
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000954}
955
Harald Welte28222962011-02-18 20:37:04 +0100956static int config_write_log_single(struct vty *vty, struct log_target *tgt)
957{
Pau Espin Pedrolc21ba152019-08-02 20:32:34 +0200958 char level_buf[128];
Harald Welte28222962011-02-18 20:37:04 +0100959 int i;
Harald Welte28222962011-02-18 20:37:04 +0100960
961 switch (tgt->type) {
962 case LOG_TGT_TYPE_VTY:
963 return 1;
964 break;
965 case LOG_TGT_TYPE_STDERR:
966 vty_out(vty, "log stderr%s", VTY_NEWLINE);
967 break;
968 case LOG_TGT_TYPE_SYSLOG:
969#ifdef HAVE_SYSLOG_H
970 vty_out(vty, "log syslog %s%s",
971 get_value_string(sysl_level_names,
972 tgt->tgt_syslog.facility),
973 VTY_NEWLINE);
974#endif
975 break;
976 case LOG_TGT_TYPE_FILE:
977 vty_out(vty, "log file %s%s", tgt->tgt_file.fname, VTY_NEWLINE);
978 break;
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000979 case LOG_TGT_TYPE_STRRB:
980 vty_out(vty, "log alarms %zu%s",
981 log_target_rb_avail_size(tgt), VTY_NEWLINE);
982 break;
Harald Welteaa00f992016-12-02 15:30:02 +0100983 case LOG_TGT_TYPE_GSMTAP:
984 vty_out(vty, "log gsmtap %s%s",
985 tgt->tgt_gsmtap.hostname, VTY_NEWLINE);
986 break;
Vadim Yanitskiye7bf4352020-09-09 03:36:48 +0700987 case LOG_TGT_TYPE_SYSTEMD:
988 vty_out(vty, "log systemd-journal%s%s",
989 tgt->sd_journal.raw ? " raw" : "",
990 VTY_NEWLINE);
991 break;
Harald Welte28222962011-02-18 20:37:04 +0100992 }
993
Harald Welte0d67f482018-09-25 20:16:14 +0200994 vty_out(vty, " logging filter all %u%s",
Neels Hofmeyr8b86cd72017-02-23 18:03:28 +0100995 tgt->filter_map & (1 << LOG_FLT_ALL) ? 1 : 0, VTY_NEWLINE);
Harald Weltefb84f322013-06-06 07:33:54 +0200996 /* save filters outside of libosmocore, i.e. in app code */
997 if (osmo_log_info->save_fn)
998 osmo_log_info->save_fn(vty, osmo_log_info, tgt);
Harald Welte2da47f12012-10-22 19:31:54 +0200999
Harald Welte0d67f482018-09-25 20:16:14 +02001000 vty_out(vty, " logging color %u%s", tgt->use_color ? 1 : 0,
Harald Welte28222962011-02-18 20:37:04 +01001001 VTY_NEWLINE);
Vadim Yanitskiy5c4b9852019-07-28 04:36:37 +07001002 vty_out(vty, " logging print category-hex %d%s",
1003 tgt->print_category_hex ? 1 : 0, VTY_NEWLINE);
Harald Welte0d67f482018-09-25 20:16:14 +02001004 vty_out(vty, " logging print category %d%s",
Michael McTernan78933462015-03-20 15:29:25 +01001005 tgt->print_category ? 1 : 0, VTY_NEWLINE);
Holger Hans Peter Freyther2d6ad132014-12-05 09:35:30 +01001006 if (tgt->print_ext_timestamp)
Harald Welte0d67f482018-09-25 20:16:14 +02001007 vty_out(vty, " logging print extended-timestamp 1%s", VTY_NEWLINE);
Holger Hans Peter Freyther2d6ad132014-12-05 09:35:30 +01001008 else
Harald Welte0d67f482018-09-25 20:16:14 +02001009 vty_out(vty, " logging timestamp %u%s",
Holger Hans Peter Freyther2d6ad132014-12-05 09:35:30 +01001010 tgt->print_timestamp ? 1 : 0, VTY_NEWLINE);
Neels Hofmeyr886e5482018-01-16 01:49:37 +01001011 if (tgt->print_level)
Harald Welte0d67f482018-09-25 20:16:14 +02001012 vty_out(vty, " logging print level 1%s", VTY_NEWLINE);
1013 vty_out(vty, " logging print file %s%s",
Neels Hofmeyr22772cc2018-02-06 00:52:08 +01001014 get_value_string(logging_print_file_args, tgt->print_filename2),
1015 VTY_NEWLINE);
Harald Welte28222962011-02-18 20:37:04 +01001016
Neels Hofmeyr098038a2018-09-11 23:49:13 +02001017 if (tgt->loglevel) {
1018 const char *level_str = get_value_string_or_null(loglevel_strs, tgt->loglevel);
Pau Espin Pedrolc21ba152019-08-02 20:32:34 +02001019 if (!level_str) {
Neels Hofmeyr9540c242018-09-12 00:20:50 +02001020 vty_out(vty, "%% Invalid log level %u for 'force-all'%s",
1021 tgt->loglevel, VTY_NEWLINE);
Pau Espin Pedrolc21ba152019-08-02 20:32:34 +02001022 } else {
1023 osmo_str_tolower_buf(level_buf, sizeof(level_buf), level_str);
1024 vty_out(vty, " logging level force-all %s%s", level_buf, VTY_NEWLINE);
1025 }
Neels Hofmeyr098038a2018-09-11 23:49:13 +02001026 }
Harald Welte28222962011-02-18 20:37:04 +01001027
1028 for (i = 0; i < osmo_log_info->num_cat; i++) {
1029 const struct log_category *cat = &tgt->categories[i];
Pau Espin Pedrolc21ba152019-08-02 20:32:34 +02001030 char cat_name[128];
Neels Hofmeyr098038a2018-09-11 23:49:13 +02001031 const char *level_str;
Harald Welte28222962011-02-18 20:37:04 +01001032
Harald Welte1a02cfc2013-03-19 10:37:39 +01001033 /* skip empty entries in the array */
1034 if (!osmo_log_info->cat[i].name)
1035 continue;
1036
Pau Espin Pedrolc21ba152019-08-02 20:32:34 +02001037 osmo_str_tolower_buf(cat_name, sizeof(cat_name), osmo_log_info->cat[i].name + 1);
Neels Hofmeyr098038a2018-09-11 23:49:13 +02001038
1039 level_str = get_value_string_or_null(loglevel_strs, cat->loglevel);
1040 if (!level_str) {
1041 vty_out(vty, "%% Invalid log level %u for %s%s", cat->loglevel, cat_name,
1042 VTY_NEWLINE);
1043 continue;
1044 }
1045
Pau Espin Pedrolc21ba152019-08-02 20:32:34 +02001046 osmo_str_tolower_buf(level_buf, sizeof(level_buf), level_str);
Harald Welte0d67f482018-09-25 20:16:14 +02001047 vty_out(vty, " logging level %s", cat_name);
Pau Espin Pedrolc21ba152019-08-02 20:32:34 +02001048 vty_out(vty, " %s%s", level_buf, VTY_NEWLINE);
Harald Welte28222962011-02-18 20:37:04 +01001049 }
1050
Harald Welte28222962011-02-18 20:37:04 +01001051 return 1;
1052}
1053
1054static int config_write_log(struct vty *vty)
1055{
Pau Espin Pedrold12f6982019-09-17 18:38:58 +02001056 log_tgt_mutex_lock();
Harald Welte28222962011-02-18 20:37:04 +01001057 struct log_target *dbg = vty->index;
1058
1059 llist_for_each_entry(dbg, &osmo_log_target_list, entry)
1060 config_write_log_single(vty, dbg);
1061
Pau Espin Pedrold12f6982019-09-17 18:38:58 +02001062 log_tgt_mutex_unlock();
Harald Welte28222962011-02-18 20:37:04 +01001063 return 1;
1064}
1065
Harald Welte11eb4b52018-06-09 17:41:31 +02001066static int log_deprecated_func(struct cmd_element *cmd, struct vty *vty, int argc, const char *argv[])
1067{
1068 vty_out(vty, "%% Ignoring deprecated '%s'%s", cmd->string, VTY_NEWLINE);
Vadim Yanitskiy4abda9e2019-11-21 00:19:36 +07001069 return CMD_SUCCESS; /* Otherwise the process would terminate */
Harald Welte11eb4b52018-06-09 17:41:31 +02001070}
1071
1072void logging_vty_add_deprecated_subsys(void *ctx, const char *name)
1073{
1074 struct cmd_element *cmd = talloc_zero(ctx, struct cmd_element);
1075 OSMO_ASSERT(cmd);
Vadim Yanitskiy75c242e2019-11-21 00:06:53 +07001076 cmd->string = talloc_asprintf(cmd, "logging level %s " LOG_LEVEL_ARGS, name);
Harald Welte11eb4b52018-06-09 17:41:31 +02001077 cmd->func = log_deprecated_func;
Neels Hofmeyrba0762d2018-09-10 13:56:03 +02001078 cmd->doc = LEVEL_STR
Harald Welte11eb4b52018-06-09 17:41:31 +02001079 "Deprecated Category\n";
1080 cmd->attr = CMD_ATTR_DEPRECATED;
1081
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07001082 install_lib_element(CFG_LOG_NODE, cmd);
Harald Welte11eb4b52018-06-09 17:41:31 +02001083}
1084
Neels Hofmeyrd0b3b9e2019-07-29 19:28:08 +02001085/* logp (<categories>) (debug|...|fatal) .LOGMESSAGE*/
1086DEFUN(vty_logp,
1087 vty_logp_cmd,
1088 NULL, /* cmdstr is dynamically set in gen_vty_logp_cmd_strs(). */
1089 NULL) /* same thing for helpstr. */
1090{
1091 int category = log_parse_category(argv[0]);
1092 int level = log_parse_level(argv[1]);
1093 char *str = argv_concat(argv, argc, 2);
1094 LOGP(category, level, "%s\n", str);
1095 return CMD_SUCCESS;
1096}
1097
1098static void gen_vty_logp_cmd_strs(struct cmd_element *cmd)
1099{
1100 char *cmd_str = NULL;
1101 char *doc_str = NULL;
1102
1103 assert_loginfo(__func__);
1104
1105 OSMO_ASSERT(cmd->string == NULL);
1106 OSMO_ASSERT(cmd->doc == NULL);
1107
1108 osmo_talloc_asprintf(tall_log_ctx, cmd_str, "logp (");
1109 osmo_talloc_asprintf(tall_log_ctx, doc_str,
1110 "Print a message on all log outputs; useful for placing markers in test logs\n");
1111 add_category_strings(&cmd_str, &doc_str, osmo_log_info);
1112 osmo_talloc_asprintf(tall_log_ctx, cmd_str, ") %s", LOG_LEVEL_ARGS);
1113 osmo_talloc_asprintf(tall_log_ctx, doc_str, "%s", LOG_LEVEL_STRS);
1114
1115 osmo_talloc_asprintf(tall_log_ctx, cmd_str, " .LOGMESSAGE");
1116 osmo_talloc_asprintf(tall_log_ctx, doc_str,
1117 "Arbitrary message to log on given category and log level\n");
1118
Harald Weltebebec212020-07-15 12:21:29 +02001119 talloc_set_name_const(cmd_str, "vty_logp_cmd_str");
1120 talloc_set_name_const(doc_str, "vty_logp_doc_str");
1121
Neels Hofmeyrd0b3b9e2019-07-29 19:28:08 +02001122 cmd->string = cmd_str;
1123 cmd->doc = doc_str;
1124}
1125
Harald Welte8c648252017-10-16 15:17:03 +02001126/*! Register logging related commands to the VTY. Call this once from
1127 * your application if you want to support those commands. */
Maxc65c5b42017-03-15 13:20:23 +01001128void logging_vty_add_cmds()
Harald Welte3fb0b6f2010-05-19 19:02:52 +02001129{
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07001130 install_lib_element_ve(&enable_logging_cmd);
1131 install_lib_element_ve(&disable_logging_cmd);
1132 install_lib_element_ve(&logging_fltr_all_cmd);
1133 install_lib_element_ve(&logging_use_clr_cmd);
1134 install_lib_element_ve(&logging_prnt_timestamp_cmd);
1135 install_lib_element_ve(&logging_prnt_ext_timestamp_cmd);
1136 install_lib_element_ve(&logging_prnt_cat_cmd);
1137 install_lib_element_ve(&logging_prnt_cat_hex_cmd);
1138 install_lib_element_ve(&logging_prnt_level_cmd);
1139 install_lib_element_ve(&logging_prnt_file_cmd);
1140 install_lib_element_ve(&logging_set_category_mask_cmd);
1141 install_lib_element_ve(&logging_set_category_mask_old_cmd);
Pablo Neira Ayuso04139f12011-03-09 13:05:08 +01001142
Neels Hofmeyr9540c242018-09-12 00:20:50 +02001143 /* logging level (<categories>) (debug|...|fatal) */
Neels Hofmeyrba0762d2018-09-10 13:56:03 +02001144 gen_logging_level_cmd_strs(&logging_level_cmd,
Neels Hofmeyr9540c242018-09-12 00:20:50 +02001145 LOG_LEVEL_ARGS,
Neels Hofmeyr7e0686c2018-09-10 20:58:52 +02001146 LOG_LEVEL_STRS);
Neels Hofmeyr9540c242018-09-12 00:20:50 +02001147 /* logging level (<categories>) everything */
Neels Hofmeyr7e0686c2018-09-10 20:58:52 +02001148 gen_logging_level_cmd_strs(&deprecated_logging_level_everything_cmd,
1149 "everything", EVERYTHING_STR);
Neels Hofmeyrba0762d2018-09-10 13:56:03 +02001150
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07001151 install_lib_element_ve(&logging_level_cmd);
1152 install_lib_element_ve(&logging_level_set_all_cmd);
1153 install_lib_element_ve(&logging_level_force_all_cmd);
1154 install_lib_element_ve(&no_logging_level_force_all_cmd);
1155 install_lib_element_ve(&deprecated_logging_level_everything_cmd);
1156 install_lib_element_ve(&deprecated_logging_level_all_cmd);
1157 install_lib_element_ve(&deprecated_logging_level_all_everything_cmd);
Harald Welte28222962011-02-18 20:37:04 +01001158
Neels Hofmeyrd0b3b9e2019-07-29 19:28:08 +02001159 gen_vty_logp_cmd_strs(&vty_logp_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07001160 install_lib_element_ve(&vty_logp_cmd);
Neels Hofmeyrd0b3b9e2019-07-29 19:28:08 +02001161
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07001162 install_lib_element_ve(&show_logging_vty_cmd);
1163 install_lib_element_ve(&show_alarms_cmd);
Pau Espin Pedrol0c2a46d2019-08-20 10:39:05 +02001164
Harald Welte28222962011-02-18 20:37:04 +01001165 install_node(&cfg_log_node, config_write_log);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07001166 install_lib_element(CFG_LOG_NODE, &logging_fltr_all_cmd);
1167 install_lib_element(CFG_LOG_NODE, &logging_use_clr_cmd);
1168 install_lib_element(CFG_LOG_NODE, &logging_prnt_timestamp_cmd);
1169 install_lib_element(CFG_LOG_NODE, &logging_prnt_ext_timestamp_cmd);
1170 install_lib_element(CFG_LOG_NODE, &logging_prnt_cat_cmd);
1171 install_lib_element(CFG_LOG_NODE, &logging_prnt_cat_hex_cmd);
1172 install_lib_element(CFG_LOG_NODE, &logging_prnt_level_cmd);
1173 install_lib_element(CFG_LOG_NODE, &logging_prnt_file_cmd);
1174 install_lib_element(CFG_LOG_NODE, &logging_level_cmd);
1175 install_lib_element(CFG_LOG_NODE, &logging_level_set_all_cmd);
1176 install_lib_element(CFG_LOG_NODE, &logging_level_force_all_cmd);
1177 install_lib_element(CFG_LOG_NODE, &no_logging_level_force_all_cmd);
1178 install_lib_element(CFG_LOG_NODE, &deprecated_logging_level_everything_cmd);
1179 install_lib_element(CFG_LOG_NODE, &deprecated_logging_level_all_cmd);
1180 install_lib_element(CFG_LOG_NODE, &deprecated_logging_level_all_everything_cmd);
Harald Welte28222962011-02-18 20:37:04 +01001181
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07001182 install_lib_element(CONFIG_NODE, &cfg_log_stderr_cmd);
1183 install_lib_element(CONFIG_NODE, &cfg_no_log_stderr_cmd);
1184 install_lib_element(CONFIG_NODE, &cfg_log_file_cmd);
1185 install_lib_element(CONFIG_NODE, &cfg_no_log_file_cmd);
1186 install_lib_element(CONFIG_NODE, &cfg_log_alarms_cmd);
1187 install_lib_element(CONFIG_NODE, &cfg_no_log_alarms_cmd);
Harald Welte28222962011-02-18 20:37:04 +01001188#ifdef HAVE_SYSLOG_H
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07001189 install_lib_element(CONFIG_NODE, &cfg_log_syslog_cmd);
1190 install_lib_element(CONFIG_NODE, &cfg_log_syslog_local_cmd);
1191 install_lib_element(CONFIG_NODE, &cfg_no_log_syslog_cmd);
Harald Welte28222962011-02-18 20:37:04 +01001192#endif
Vadim Yanitskiye7bf4352020-09-09 03:36:48 +07001193 install_lib_element(CONFIG_NODE, &cfg_log_systemd_journal_cmd);
1194 install_lib_element(CONFIG_NODE, &cfg_no_log_systemd_journal_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07001195 install_lib_element(CONFIG_NODE, &cfg_log_gsmtap_cmd);
Harald Welte3fb0b6f2010-05-19 19:02:52 +02001196}