blob: 0eaa7fd3bc0c0bbddcb9a8b634138666477ae7e5 [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>
31#include <osmocom/core/utils.h>
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +000032#include <osmocom/core/strrb.h>
33#include <osmocom/core/loggingrb.h>
Harald Welteaa00f992016-12-02 15:30:02 +010034#include <osmocom/core/gsmtap.h>
Harald Welte3fb0b6f2010-05-19 19:02:52 +020035
36#include <osmocom/vty/command.h>
37#include <osmocom/vty/buffer.h>
38#include <osmocom/vty/vty.h>
39#include <osmocom/vty/telnet_interface.h>
40#include <osmocom/vty/logging.h>
41
Harald Welte28222962011-02-18 20:37:04 +010042#define LOG_STR "Configure logging sub-system\n"
43
Harald Welte8c648252017-10-16 15:17:03 +020044/*! \file logging_vty.c
Neels Hofmeyr87e45502017-06-20 00:17:59 +020045 * Configuration of logging from VTY
Harald Welte96e2a002017-06-12 21:44:18 +020046 *
Harald Welte8c648252017-10-16 15:17:03 +020047 * This module implements
48 * - functions that permit configuration of the libosmocore logging
49 * framework from VTY commands in the configure -> logging node.
50 *
51 * - functions that permit logging *to* a VTY session. Basically each
52 * VTY session gets its own log target, with configurable
53 * per-subsystem log levels. This is performed internally via the
54 * \ref log_target_create_vty function.
55 *
56 * You have to call \ref logging_vty_add_cmds from your application
57 * once to enable both of the above.
58 *
Harald Welte96e2a002017-06-12 21:44:18 +020059 */
60
Harald Welte4ebdf742010-05-19 19:54:00 +020061extern const struct log_info *osmo_log_info;
Harald Welte3fb0b6f2010-05-19 19:02:52 +020062
Harald Welte76e72ab2011-02-17 15:52:39 +010063static void _vty_output(struct log_target *tgt,
64 unsigned int level, const char *line)
Harald Welte3fb0b6f2010-05-19 19:02:52 +020065{
66 struct vty *vty = tgt->tgt_vty.vty;
67 vty_out(vty, "%s", line);
68 /* This is an ugly hack, but there is no easy way... */
69 if (strchr(line, '\n'))
70 vty_out(vty, "\r");
71}
72
73struct log_target *log_target_create_vty(struct vty *vty)
74{
75 struct log_target *target;
76
77 target = log_target_create();
78 if (!target)
79 return NULL;
80
81 target->tgt_vty.vty = vty;
82 target->output = _vty_output;
83 return target;
84}
85
86DEFUN(enable_logging,
87 enable_logging_cmd,
88 "logging enable",
89 LOGGING_STR
90 "Enables logging to this vty\n")
91{
92 struct telnet_connection *conn;
93
94 conn = (struct telnet_connection *) vty->priv;
95 if (conn->dbg) {
96 vty_out(vty, "Logging already enabled.%s", VTY_NEWLINE);
97 return CMD_WARNING;
98 }
99
100 conn->dbg = log_target_create_vty(vty);
101 if (!conn->dbg)
102 return CMD_WARNING;
103
104 log_add_target(conn->dbg);
105 return CMD_SUCCESS;
106}
107
Harald Weltea62648b2011-02-18 21:03:27 +0100108struct log_target *osmo_log_vty2tgt(struct vty *vty)
109{
110 struct telnet_connection *conn;
111
112 if (vty->node == CFG_LOG_NODE)
113 return vty->index;
114
115
116 conn = (struct telnet_connection *) vty->priv;
117 if (!conn->dbg)
118 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
119
120 return conn->dbg;
121}
122
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200123DEFUN(logging_fltr_all,
124 logging_fltr_all_cmd,
125 "logging filter all (0|1)",
126 LOGGING_STR FILTER_STR
127 "Do you want to log all messages?\n"
128 "Only print messages matched by other filters\n"
129 "Bypass filter and print all messages\n")
130{
Harald Weltea62648b2011-02-18 21:03:27 +0100131 struct log_target *tgt = osmo_log_vty2tgt(vty);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200132
Harald Weltea62648b2011-02-18 21:03:27 +0100133 if (!tgt)
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200134 return CMD_WARNING;
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200135
Harald Weltea62648b2011-02-18 21:03:27 +0100136 log_set_all_filter(tgt, atoi(argv[0]));
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200137 return CMD_SUCCESS;
138}
139
140DEFUN(logging_use_clr,
141 logging_use_clr_cmd,
142 "logging color (0|1)",
143 LOGGING_STR "Configure color-printing for log messages\n"
144 "Don't use color for printing messages\n"
145 "Use color for printing messages\n")
146{
Harald Weltea62648b2011-02-18 21:03:27 +0100147 struct log_target *tgt = osmo_log_vty2tgt(vty);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200148
Harald Weltea62648b2011-02-18 21:03:27 +0100149 if (!tgt)
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200150 return CMD_WARNING;
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200151
Harald Weltea62648b2011-02-18 21:03:27 +0100152 log_set_use_color(tgt, atoi(argv[0]));
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200153 return CMD_SUCCESS;
154}
155
156DEFUN(logging_prnt_timestamp,
157 logging_prnt_timestamp_cmd,
158 "logging timestamp (0|1)",
159 LOGGING_STR "Configure log message timestamping\n"
160 "Don't prefix each log message\n"
161 "Prefix each log message with current timestamp\n")
162{
Harald Weltea62648b2011-02-18 21:03:27 +0100163 struct log_target *tgt = osmo_log_vty2tgt(vty);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200164
Harald Weltea62648b2011-02-18 21:03:27 +0100165 if (!tgt)
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200166 return CMD_WARNING;
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200167
Harald Weltea62648b2011-02-18 21:03:27 +0100168 log_set_print_timestamp(tgt, atoi(argv[0]));
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200169 return CMD_SUCCESS;
170}
171
Holger Hans Peter Freyther2d6ad132014-12-05 09:35:30 +0100172DEFUN(logging_prnt_ext_timestamp,
173 logging_prnt_ext_timestamp_cmd,
174 "logging print extended-timestamp (0|1)",
175 LOGGING_STR "Log output settings\n"
176 "Configure log message timestamping\n"
177 "Don't prefix each log message\n"
178 "Prefix each log message with current timestamp with YYYYMMDDhhmmssnnn\n")
179{
180 struct log_target *tgt = osmo_log_vty2tgt(vty);
181
182 if (!tgt)
183 return CMD_WARNING;
184
185 log_set_print_extended_timestamp(tgt, atoi(argv[0]));
186 return CMD_SUCCESS;
187}
188
189DEFUN(logging_prnt_cat,
190 logging_prnt_cat_cmd,
191 "logging print category (0|1)",
192 LOGGING_STR "Log output settings\n"
193 "Configure log message\n"
194 "Don't prefix each log message\n"
195 "Prefix each log message with category/subsystem name\n")
196{
197 struct log_target *tgt = osmo_log_vty2tgt(vty);
198
199 if (!tgt)
200 return CMD_WARNING;
201
202 log_set_print_category(tgt, atoi(argv[0]));
203 return CMD_SUCCESS;
204}
205
Neels Hofmeyrbd7bd392018-01-16 01:52:29 +0100206DEFUN(logging_prnt_cat_hex,
207 logging_prnt_cat_hex_cmd,
208 "logging print category-hex (0|1)",
209 LOGGING_STR "Log output settings\n"
210 "Configure log message\n"
211 "Don't prefix each log message\n"
212 "Prefix each log message with category/subsystem nr in hex ('<000b>')\n")
213{
214 struct log_target *tgt = osmo_log_vty2tgt(vty);
215
216 if (!tgt)
217 return CMD_WARNING;
218
219 log_set_print_category_hex(tgt, atoi(argv[0]));
220 return CMD_SUCCESS;
221}
222
Neels Hofmeyr886e5482018-01-16 01:49:37 +0100223DEFUN(logging_prnt_level,
224 logging_prnt_level_cmd,
225 "logging print level (0|1)",
226 LOGGING_STR "Log output settings\n"
227 "Configure log message\n"
228 "Don't prefix each log message\n"
229 "Prefix each log message with the log level name\n")
230{
231 struct log_target *tgt = osmo_log_vty2tgt(vty);
232
233 if (!tgt)
234 return CMD_WARNING;
235
236 log_set_print_level(tgt, atoi(argv[0]));
237 return CMD_SUCCESS;
238}
239
Neels Hofmeyrc6fd2452018-01-16 01:57:38 +0100240DEFUN(logging_prnt_file,
241 logging_prnt_file_cmd,
242 "logging print file (0|1|basename)",
243 LOGGING_STR "Log output settings\n"
244 "Configure log message\n"
245 "Don't prefix each log message\n"
246 "Prefix each log message with the source file and line\n"
247 "Prefix each log message with the source file's basename (strip leading paths) and line\n")
248{
249 struct log_target *tgt = osmo_log_vty2tgt(vty);
250 enum log_filename_type lft;
251
252 if (!tgt)
253 return CMD_WARNING;
254
255 if (!strcmp(argv[0], "basename"))
256 lft = LOG_FILENAME_BASENAME;
257 else
258 lft = atoi(argv[0])? LOG_FILENAME_PATH : LOG_FILENAME_NONE;
259 log_set_print_filename2(tgt, lft);
260 return CMD_SUCCESS;
261}
262
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200263DEFUN(logging_level,
264 logging_level_cmd,
Pablo Neira Ayuso04139f12011-03-09 13:05:08 +0100265 NULL, /* cmdstr is dynamically set in logging_vty_add_cmds(). */
266 NULL) /* same thing for helpstr. */
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200267{
Harald Weltea62648b2011-02-18 21:03:27 +0100268 int category = log_parse_category(argv[0]);
269 int level = log_parse_level(argv[1]);
270 struct log_target *tgt = osmo_log_vty2tgt(vty);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200271
Harald Weltea62648b2011-02-18 21:03:27 +0100272 if (!tgt)
273 return CMD_WARNING;
274
275 if (level < 0) {
276 vty_out(vty, "Invalid level `%s'%s", argv[1], VTY_NEWLINE);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200277 return CMD_WARNING;
278 }
279
Maxed0eda22017-07-06 17:09:01 +0200280 if (strcmp(argv[1], "everything") == 0) { /* FIXME: remove this check once 'everything' is phased out */
281 vty_out(vty, "%% Ignoring deprecated logging level %s%s", argv[1], VTY_NEWLINE);
282 return CMD_SUCCESS;
283 }
284
Harald Weltea62648b2011-02-18 21:03:27 +0100285 /* Check for special case where we want to set global log level */
286 if (!strcmp(argv[0], "all")) {
287 log_set_log_level(tgt, level);
288 return CMD_SUCCESS;
289 }
290
291 if (category < 0) {
292 vty_out(vty, "Invalid category `%s'%s", argv[0], VTY_NEWLINE);
293 return CMD_WARNING;
294 }
295
296 tgt->categories[category].enabled = 1;
297 tgt->categories[category].loglevel = level;
298
299 return CMD_SUCCESS;
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200300}
301
302DEFUN(logging_set_category_mask,
303 logging_set_category_mask_cmd,
Holger Hans Peter Freyther146d1d32011-10-03 23:15:41 +0200304 "logging set-log-mask MASK",
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200305 LOGGING_STR
Holger Hans Peter Freyther146d1d32011-10-03 23:15:41 +0200306 "Set the logmask of this logging target\n"
Neels Hofmeyr84ea2e02017-12-09 05:53:18 +0100307 "List of logging categories to log, e.g. 'abc:mno:xyz'. Available log categories depend on the specific"
308 " application, refer to the 'logging level' command. Optionally add individual log levels like"
309 " 'abc,1:mno,3:xyz,5', where the level numbers are"
310 " " OSMO_STRINGIFY(LOGL_DEBUG) "=" OSMO_STRINGIFY_VAL(LOGL_DEBUG)
311 " " OSMO_STRINGIFY(LOGL_INFO) "=" OSMO_STRINGIFY_VAL(LOGL_INFO)
312 " " OSMO_STRINGIFY(LOGL_NOTICE) "=" OSMO_STRINGIFY_VAL(LOGL_NOTICE)
313 " " OSMO_STRINGIFY(LOGL_ERROR) "=" OSMO_STRINGIFY_VAL(LOGL_ERROR)
314 " " OSMO_STRINGIFY(LOGL_FATAL) "=" OSMO_STRINGIFY_VAL(LOGL_FATAL)
315 "\n")
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200316{
Harald Weltea62648b2011-02-18 21:03:27 +0100317 struct log_target *tgt = osmo_log_vty2tgt(vty);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200318
Harald Weltea62648b2011-02-18 21:03:27 +0100319 if (!tgt)
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200320 return CMD_WARNING;
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200321
Harald Weltea62648b2011-02-18 21:03:27 +0100322 log_parse_category_mask(tgt, argv[0]);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200323 return CMD_SUCCESS;
324}
325
Holger Hans Peter Freyther146d1d32011-10-03 23:15:41 +0200326ALIAS_DEPRECATED(logging_set_category_mask,
327 logging_set_category_mask_old_cmd,
328 "logging set log mask MASK",
329 LOGGING_STR
330 "Decide which categories to output.\n"
Neels Hofmeyr84ea2e02017-12-09 05:53:18 +0100331 "Log commands\n" "Mask commands\n"
332 "'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 +0200333
334
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200335DEFUN(diable_logging,
336 disable_logging_cmd,
337 "logging disable",
338 LOGGING_STR
339 "Disables logging to this vty\n")
340{
Harald Weltea62648b2011-02-18 21:03:27 +0100341 struct log_target *tgt = osmo_log_vty2tgt(vty);
342 struct telnet_connection *conn = (struct telnet_connection *) vty->priv;
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200343
Harald Weltea62648b2011-02-18 21:03:27 +0100344 if (!tgt)
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200345 return CMD_WARNING;
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200346
Harald Weltea62648b2011-02-18 21:03:27 +0100347 log_del_target(tgt);
348 talloc_free(tgt);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200349 conn->dbg = NULL;
Harald Weltea62648b2011-02-18 21:03:27 +0100350
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200351 return CMD_SUCCESS;
352}
353
354static void vty_print_logtarget(struct vty *vty, const struct log_info *info,
355 const struct log_target *tgt)
356{
357 unsigned int i;
358
359 vty_out(vty, " Global Loglevel: %s%s",
360 log_level_str(tgt->loglevel), VTY_NEWLINE);
361 vty_out(vty, " Use color: %s, Print Timestamp: %s%s",
362 tgt->use_color ? "On" : "Off",
363 tgt->print_timestamp ? "On" : "Off", VTY_NEWLINE);
364
365 vty_out(vty, " Log Level specific information:%s", VTY_NEWLINE);
366
367 for (i = 0; i < info->num_cat; i++) {
368 const struct log_category *cat = &tgt->categories[i];
Daniel Willmann55363a92016-11-15 10:05:51 +0100369 /* Skip categories that were not initialized */
370 if (!info->cat[i].name)
371 continue;
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200372 vty_out(vty, " %-10s %-10s %-8s %s%s",
373 info->cat[i].name+1, log_level_str(cat->loglevel),
374 cat->enabled ? "Enabled" : "Disabled",
375 info->cat[i].description,
376 VTY_NEWLINE);
377 }
Harald Welte6d2d4d62013-03-10 09:53:24 +0000378
379 vty_out(vty, " Log Filter 'ALL': %s%s",
Neels Hofmeyr8b86cd72017-02-23 18:03:28 +0100380 tgt->filter_map & (1 << LOG_FLT_ALL) ? "Enabled" : "Disabled",
Harald Welte6d2d4d62013-03-10 09:53:24 +0000381 VTY_NEWLINE);
382
Harald Weltefb84f322013-06-06 07:33:54 +0200383 /* print application specific filters */
384 if (info->print_fn)
385 info->print_fn(vty, info, tgt);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200386}
387
388#define SHOW_LOG_STR "Show current logging configuration\n"
389
390DEFUN(show_logging_vty,
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000391 show_logging_vty_cmd,
392 "show logging vty",
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200393 SHOW_STR SHOW_LOG_STR
394 "Show current logging configuration for this vty\n")
395{
Harald Weltea62648b2011-02-18 21:03:27 +0100396 struct log_target *tgt = osmo_log_vty2tgt(vty);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200397
Harald Weltea62648b2011-02-18 21:03:27 +0100398 if (!tgt)
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200399 return CMD_WARNING;
Harald Weltea62648b2011-02-18 21:03:27 +0100400
401 vty_print_logtarget(vty, osmo_log_info, tgt);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200402
403 return CMD_SUCCESS;
404}
405
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000406DEFUN(show_alarms,
407 show_alarms_cmd,
408 "show alarms",
409 SHOW_STR SHOW_LOG_STR
410 "Show the contents of the logging ringbuffer\n")
411{
412 int i, num_alarms;
413 struct osmo_strrb *rb;
414 struct log_target *tgt = log_target_find(LOG_TGT_TYPE_STRRB, NULL);
415 if (!tgt) {
416 vty_out(vty, "%% No alarms, run 'log alarms <2-32700>'%s",
417 VTY_NEWLINE);
418 return CMD_WARNING;
419 }
420
421 rb = tgt->tgt_rb.rb;
422 num_alarms = osmo_strrb_elements(rb);
423
424 vty_out(vty, "%% Showing %i alarms%s", num_alarms, VTY_NEWLINE);
425
426 for (i = 0; i < num_alarms; i++)
427 vty_out(vty, "%% %s%s", osmo_strrb_get_nth(rb, i),
428 VTY_NEWLINE);
429
430 return CMD_SUCCESS;
431}
432
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200433gDEFUN(cfg_description, cfg_description_cmd,
434 "description .TEXT",
Thorsten Alteholza81055d2017-03-02 22:13:48 +0100435 "Save human-readable description of the object\n"
Holger Hans Peter Freytherc9b3e062012-07-25 13:02:49 +0200436 "Text until the end of the line\n")
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200437{
438 char **dptr = vty->index_sub;
439
440 if (!dptr) {
441 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
442 return CMD_WARNING;
443 }
444
Holger Hans Peter Freytherff0670e2011-02-24 14:20:41 +0100445 if (*dptr)
446 talloc_free(*dptr);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200447 *dptr = argv_concat(argv, argc, 0);
Holger Hans Peter Freyther6a75d162013-07-14 09:07:11 +0200448 if (!*dptr)
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200449 return CMD_WARNING;
450
451 return CMD_SUCCESS;
452}
453
454gDEFUN(cfg_no_description, cfg_no_description_cmd,
455 "no description",
456 NO_STR
457 "Remove description of the object\n")
458{
459 char **dptr = vty->index_sub;
460
461 if (!dptr) {
462 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
463 return CMD_WARNING;
464 }
465
466 if (*dptr) {
467 talloc_free(*dptr);
468 *dptr = NULL;
469 }
470
471 return CMD_SUCCESS;
472}
473
Harald Welte28222962011-02-18 20:37:04 +0100474/* Support for configuration of log targets != the current vty */
475
476struct cmd_node cfg_log_node = {
477 CFG_LOG_NODE,
478 "%s(config-log)# ",
479 1
480};
481
Harald Welte28222962011-02-18 20:37:04 +0100482#ifdef HAVE_SYSLOG_H
483
484#include <syslog.h>
485
486static const int local_sysl_map[] = {
487 [0] = LOG_LOCAL0,
488 [1] = LOG_LOCAL1,
489 [2] = LOG_LOCAL2,
490 [3] = LOG_LOCAL3,
491 [4] = LOG_LOCAL4,
492 [5] = LOG_LOCAL5,
493 [6] = LOG_LOCAL6,
494 [7] = LOG_LOCAL7
495};
496
Harald Weltede79cee2011-02-24 23:47:57 +0100497/* From VTY core code */
498extern struct host host;
499
Harald Welte28222962011-02-18 20:37:04 +0100500static int _cfg_log_syslog(struct vty *vty, int facility)
501{
502 struct log_target *tgt;
503
504 /* First delete the old syslog target, if any */
505 tgt = log_target_find(LOG_TGT_TYPE_SYSLOG, NULL);
506 if (tgt)
507 log_target_destroy(tgt);
508
Harald Weltede79cee2011-02-24 23:47:57 +0100509 tgt = log_target_create_syslog(host.app_info->name, 0, facility);
Harald Welte28222962011-02-18 20:37:04 +0100510 if (!tgt) {
511 vty_out(vty, "%% Unable to open syslog%s", VTY_NEWLINE);
512 return CMD_WARNING;
513 }
514 log_add_target(tgt);
515
516 vty->index = tgt;
517 vty->node = CFG_LOG_NODE;
518
519 return CMD_SUCCESS;
520}
521
522DEFUN(cfg_log_syslog_local, cfg_log_syslog_local_cmd,
523 "log syslog local <0-7>",
524 LOG_STR "Logging via syslog\n" "Syslog LOCAL facility\n"
525 "Local facility number\n")
526{
527 int local = atoi(argv[0]);
528 int facility = local_sysl_map[local];
529
530 return _cfg_log_syslog(vty, facility);
531}
532
533static struct value_string sysl_level_names[] = {
534 { LOG_AUTHPRIV, "authpriv" },
535 { LOG_CRON, "cron" },
536 { LOG_DAEMON, "daemon" },
537 { LOG_FTP, "ftp" },
538 { LOG_LPR, "lpr" },
539 { LOG_MAIL, "mail" },
540 { LOG_NEWS, "news" },
541 { LOG_USER, "user" },
542 { LOG_UUCP, "uucp" },
543 /* only for value -> string conversion */
544 { LOG_LOCAL0, "local 0" },
545 { LOG_LOCAL1, "local 1" },
546 { LOG_LOCAL2, "local 2" },
547 { LOG_LOCAL3, "local 3" },
548 { LOG_LOCAL4, "local 4" },
549 { LOG_LOCAL5, "local 5" },
550 { LOG_LOCAL6, "local 6" },
551 { LOG_LOCAL7, "local 7" },
552 { 0, NULL }
553};
554
555DEFUN(cfg_log_syslog, cfg_log_syslog_cmd,
556 "log syslog (authpriv|cron|daemon|ftp|lpr|mail|news|user|uucp)",
Holger Hans Peter Freythera4463fd2011-10-03 23:17:36 +0200557 LOG_STR "Logging via syslog\n"
558 "Security/authorization messages facility\n"
559 "Clock daemon (cron/at) facility\n"
560 "General system daemon facility\n"
561 "Ftp daemon facility\n"
562 "Line printer facility\n"
563 "Mail facility\n"
564 "News facility\n"
565 "Generic facility\n"
566 "UUCP facility\n")
Harald Welte28222962011-02-18 20:37:04 +0100567{
568 int facility = get_string_value(sysl_level_names, argv[0]);
569
570 return _cfg_log_syslog(vty, facility);
571}
572
573DEFUN(cfg_no_log_syslog, cfg_no_log_syslog_cmd,
574 "no log syslog",
575 NO_STR LOG_STR "Logging via syslog\n")
576{
577 struct log_target *tgt;
578
579 tgt = log_target_find(LOG_TGT_TYPE_SYSLOG, NULL);
580 if (!tgt) {
581 vty_out(vty, "%% No syslog target found%s",
582 VTY_NEWLINE);
583 return CMD_WARNING;
584 }
585
586 log_target_destroy(tgt);
587
588 return CMD_SUCCESS;
589}
590#endif /* HAVE_SYSLOG_H */
591
Harald Welteaa00f992016-12-02 15:30:02 +0100592DEFUN(cfg_log_gsmtap, cfg_log_gsmtap_cmd,
593 "log gsmtap [HOSTNAME]",
Neels Hofmeyrfd9ec3b2016-12-11 01:48:26 +0100594 LOG_STR "Logging via GSMTAP\n"
595 "Host name to send the GSMTAP logging to (UDP port 4729)\n")
Harald Welteaa00f992016-12-02 15:30:02 +0100596{
Max2f153b52018-01-04 12:25:57 +0100597 const char *hostname = argc ? argv[0] : "127.0.0.1";
Harald Welteaa00f992016-12-02 15:30:02 +0100598 struct log_target *tgt;
599
600 tgt = log_target_find(LOG_TGT_TYPE_GSMTAP, hostname);
601 if (!tgt) {
602 tgt = log_target_create_gsmtap(hostname, GSMTAP_UDP_PORT,
603 host.app_info->name, false,
604 true);
605 if (!tgt) {
Max2f153b52018-01-04 12:25:57 +0100606 vty_out(vty, "%% Unable to create GSMTAP log for %s%s",
607 hostname, VTY_NEWLINE);
Harald Welteaa00f992016-12-02 15:30:02 +0100608 return CMD_WARNING;
609 }
610 log_add_target(tgt);
611 }
612
613 vty->index = tgt;
614 vty->node = CFG_LOG_NODE;
615
616 return CMD_SUCCESS;
617}
618
Harald Welte28222962011-02-18 20:37:04 +0100619DEFUN(cfg_log_stderr, cfg_log_stderr_cmd,
620 "log stderr",
621 LOG_STR "Logging via STDERR of the process\n")
622{
623 struct log_target *tgt;
624
625 tgt = log_target_find(LOG_TGT_TYPE_STDERR, NULL);
626 if (!tgt) {
627 tgt = log_target_create_stderr();
628 if (!tgt) {
629 vty_out(vty, "%% Unable to create stderr log%s",
630 VTY_NEWLINE);
631 return CMD_WARNING;
632 }
633 log_add_target(tgt);
634 }
635
636 vty->index = tgt;
637 vty->node = CFG_LOG_NODE;
638
639 return CMD_SUCCESS;
640}
641
642DEFUN(cfg_no_log_stderr, cfg_no_log_stderr_cmd,
643 "no log stderr",
644 NO_STR LOG_STR "Logging via STDERR of the process\n")
645{
646 struct log_target *tgt;
647
648 tgt = log_target_find(LOG_TGT_TYPE_STDERR, NULL);
649 if (!tgt) {
650 vty_out(vty, "%% No stderr logging active%s", VTY_NEWLINE);
651 return CMD_WARNING;
652 }
653
654 log_target_destroy(tgt);
655
656 return CMD_SUCCESS;
657}
658
659DEFUN(cfg_log_file, cfg_log_file_cmd,
660 "log file .FILENAME",
661 LOG_STR "Logging to text file\n" "Filename\n")
662{
663 const char *fname = argv[0];
664 struct log_target *tgt;
665
666 tgt = log_target_find(LOG_TGT_TYPE_FILE, fname);
667 if (!tgt) {
668 tgt = log_target_create_file(fname);
669 if (!tgt) {
670 vty_out(vty, "%% Unable to create file `%s'%s",
671 fname, VTY_NEWLINE);
672 return CMD_WARNING;
673 }
674 log_add_target(tgt);
675 }
676
677 vty->index = tgt;
678 vty->node = CFG_LOG_NODE;
679
680 return CMD_SUCCESS;
681}
682
683
684DEFUN(cfg_no_log_file, cfg_no_log_file_cmd,
685 "no log file .FILENAME",
686 NO_STR LOG_STR "Logging to text file\n" "Filename\n")
687{
688 const char *fname = argv[0];
689 struct log_target *tgt;
690
691 tgt = log_target_find(LOG_TGT_TYPE_FILE, fname);
692 if (!tgt) {
693 vty_out(vty, "%% No such log file `%s'%s",
694 fname, VTY_NEWLINE);
695 return CMD_WARNING;
696 }
697
698 log_target_destroy(tgt);
699
700 return CMD_SUCCESS;
701}
702
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000703DEFUN(cfg_log_alarms, cfg_log_alarms_cmd,
704 "log alarms <2-32700>",
705 LOG_STR "Logging alarms to osmo_strrb\n"
706 "Maximum number of messages to log\n")
707{
708 struct log_target *tgt;
709 unsigned int rbsize = atoi(argv[0]);
710
711 tgt = log_target_find(LOG_TGT_TYPE_STRRB, NULL);
712 if (tgt)
713 log_target_destroy(tgt);
714
715 tgt = log_target_create_rb(rbsize);
716 if (!tgt) {
717 vty_out(vty, "%% Unable to create osmo_strrb (size %u)%s",
718 rbsize, VTY_NEWLINE);
719 return CMD_WARNING;
720 }
721 log_add_target(tgt);
722
723 vty->index = tgt;
724 vty->node = CFG_LOG_NODE;
725
726 return CMD_SUCCESS;
727}
728
729DEFUN(cfg_no_log_alarms, cfg_no_log_alarms_cmd,
730 "no log alarms",
731 NO_STR LOG_STR "Logging alarms to osmo_strrb\n")
732{
733 struct log_target *tgt;
734
735 tgt = log_target_find(LOG_TGT_TYPE_STRRB, NULL);
736 if (!tgt) {
737 vty_out(vty, "%% No osmo_strrb target found%s", VTY_NEWLINE);
738 return CMD_WARNING;
739 }
740
741 log_target_destroy(tgt);
742
743 return CMD_SUCCESS;
744}
745
Harald Welte28222962011-02-18 20:37:04 +0100746static int config_write_log_single(struct vty *vty, struct log_target *tgt)
747{
748 int i;
749 char level_lower[32];
750
751 switch (tgt->type) {
752 case LOG_TGT_TYPE_VTY:
753 return 1;
754 break;
755 case LOG_TGT_TYPE_STDERR:
756 vty_out(vty, "log stderr%s", VTY_NEWLINE);
757 break;
758 case LOG_TGT_TYPE_SYSLOG:
759#ifdef HAVE_SYSLOG_H
760 vty_out(vty, "log syslog %s%s",
761 get_value_string(sysl_level_names,
762 tgt->tgt_syslog.facility),
763 VTY_NEWLINE);
764#endif
765 break;
766 case LOG_TGT_TYPE_FILE:
767 vty_out(vty, "log file %s%s", tgt->tgt_file.fname, VTY_NEWLINE);
768 break;
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000769 case LOG_TGT_TYPE_STRRB:
770 vty_out(vty, "log alarms %zu%s",
771 log_target_rb_avail_size(tgt), VTY_NEWLINE);
772 break;
Harald Welteaa00f992016-12-02 15:30:02 +0100773 case LOG_TGT_TYPE_GSMTAP:
774 vty_out(vty, "log gsmtap %s%s",
775 tgt->tgt_gsmtap.hostname, VTY_NEWLINE);
776 break;
Harald Welte28222962011-02-18 20:37:04 +0100777 }
778
Harald Welte2da47f12012-10-22 19:31:54 +0200779 vty_out(vty, " logging filter all %u%s",
Neels Hofmeyr8b86cd72017-02-23 18:03:28 +0100780 tgt->filter_map & (1 << LOG_FLT_ALL) ? 1 : 0, VTY_NEWLINE);
Harald Weltefb84f322013-06-06 07:33:54 +0200781 /* save filters outside of libosmocore, i.e. in app code */
782 if (osmo_log_info->save_fn)
783 osmo_log_info->save_fn(vty, osmo_log_info, tgt);
Harald Welte2da47f12012-10-22 19:31:54 +0200784
Harald Welte28222962011-02-18 20:37:04 +0100785 vty_out(vty, " logging color %u%s", tgt->use_color ? 1 : 0,
786 VTY_NEWLINE);
Holger Hans Peter Freyther879acef2015-01-27 11:06:51 +0100787 vty_out(vty, " logging print category %d%s",
Michael McTernan78933462015-03-20 15:29:25 +0100788 tgt->print_category ? 1 : 0, VTY_NEWLINE);
Holger Hans Peter Freyther2d6ad132014-12-05 09:35:30 +0100789 if (tgt->print_ext_timestamp)
790 vty_out(vty, " logging print extended-timestamp 1%s", VTY_NEWLINE);
791 else
792 vty_out(vty, " logging timestamp %u%s",
793 tgt->print_timestamp ? 1 : 0, VTY_NEWLINE);
Neels Hofmeyr886e5482018-01-16 01:49:37 +0100794 if (tgt->print_level)
795 vty_out(vty, " logging print level 1%s", VTY_NEWLINE);
Neels Hofmeyrc6fd2452018-01-16 01:57:38 +0100796 if (tgt->print_filename)
797 vty_out(vty, " logging print file 1%s", VTY_NEWLINE);
Harald Welte28222962011-02-18 20:37:04 +0100798
799 /* stupid old osmo logging API uses uppercase strings... */
800 osmo_str2lower(level_lower, log_level_str(tgt->loglevel));
801 vty_out(vty, " logging level all %s%s", level_lower, VTY_NEWLINE);
802
803 for (i = 0; i < osmo_log_info->num_cat; i++) {
804 const struct log_category *cat = &tgt->categories[i];
805 char cat_lower[32];
806
Harald Welte1a02cfc2013-03-19 10:37:39 +0100807 /* skip empty entries in the array */
808 if (!osmo_log_info->cat[i].name)
809 continue;
810
Harald Welte28222962011-02-18 20:37:04 +0100811 /* stupid old osmo logging API uses uppercase strings... */
812 osmo_str2lower(cat_lower, osmo_log_info->cat[i].name+1);
813 osmo_str2lower(level_lower, log_level_str(cat->loglevel));
814
Maxed0eda22017-07-06 17:09:01 +0200815 if (strcmp(level_lower, "everything") != 0) /* FIXME: remove this check once 'everything' is phased out */
816 vty_out(vty, " logging level %s %s%s", cat_lower, level_lower, VTY_NEWLINE);
817 else
818 LOGP(DLSTATS, LOGL_ERROR, "logging level everything is deprecated and should not be used\n");
Harald Welte28222962011-02-18 20:37:04 +0100819 }
820
821 /* FIXME: levels */
822
823 return 1;
824}
825
826static int config_write_log(struct vty *vty)
827{
828 struct log_target *dbg = vty->index;
829
830 llist_for_each_entry(dbg, &osmo_log_target_list, entry)
831 config_write_log_single(vty, dbg);
832
833 return 1;
834}
835
Harald Welte8c648252017-10-16 15:17:03 +0200836/*! Register logging related commands to the VTY. Call this once from
837 * your application if you want to support those commands. */
Maxc65c5b42017-03-15 13:20:23 +0100838void logging_vty_add_cmds()
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200839{
840 install_element_ve(&enable_logging_cmd);
841 install_element_ve(&disable_logging_cmd);
842 install_element_ve(&logging_fltr_all_cmd);
843 install_element_ve(&logging_use_clr_cmd);
844 install_element_ve(&logging_prnt_timestamp_cmd);
Holger Hans Peter Freyther2d6ad132014-12-05 09:35:30 +0100845 install_element_ve(&logging_prnt_ext_timestamp_cmd);
846 install_element_ve(&logging_prnt_cat_cmd);
Neels Hofmeyrbd7bd392018-01-16 01:52:29 +0100847 install_element_ve(&logging_prnt_cat_hex_cmd);
Neels Hofmeyr886e5482018-01-16 01:49:37 +0100848 install_element_ve(&logging_prnt_level_cmd);
Neels Hofmeyrc6fd2452018-01-16 01:57:38 +0100849 install_element_ve(&logging_prnt_file_cmd);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200850 install_element_ve(&logging_set_category_mask_cmd);
Holger Hans Peter Freyther146d1d32011-10-03 23:15:41 +0200851 install_element_ve(&logging_set_category_mask_old_cmd);
Pablo Neira Ayuso04139f12011-03-09 13:05:08 +0100852
853 /* Logging level strings are generated dynamically. */
Maxc65c5b42017-03-15 13:20:23 +0100854 logging_level_cmd.string = log_vty_command_string();
855 logging_level_cmd.doc = log_vty_command_description();
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200856 install_element_ve(&logging_level_cmd);
857 install_element_ve(&show_logging_vty_cmd);
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000858 install_element_ve(&show_alarms_cmd);
Harald Welte28222962011-02-18 20:37:04 +0100859
860 install_node(&cfg_log_node, config_write_log);
Harald Weltea62648b2011-02-18 21:03:27 +0100861 install_element(CFG_LOG_NODE, &logging_fltr_all_cmd);
862 install_element(CFG_LOG_NODE, &logging_use_clr_cmd);
863 install_element(CFG_LOG_NODE, &logging_prnt_timestamp_cmd);
Holger Hans Peter Freyther2d6ad132014-12-05 09:35:30 +0100864 install_element(CFG_LOG_NODE, &logging_prnt_ext_timestamp_cmd);
865 install_element(CFG_LOG_NODE, &logging_prnt_cat_cmd);
Neels Hofmeyrbd7bd392018-01-16 01:52:29 +0100866 install_element(CFG_LOG_NODE, &logging_prnt_cat_hex_cmd);
Neels Hofmeyr886e5482018-01-16 01:49:37 +0100867 install_element(CFG_LOG_NODE, &logging_prnt_level_cmd);
Neels Hofmeyrc6fd2452018-01-16 01:57:38 +0100868 install_element(CFG_LOG_NODE, &logging_prnt_file_cmd);
Harald Weltea62648b2011-02-18 21:03:27 +0100869 install_element(CFG_LOG_NODE, &logging_level_cmd);
Harald Welte28222962011-02-18 20:37:04 +0100870
871 install_element(CONFIG_NODE, &cfg_log_stderr_cmd);
872 install_element(CONFIG_NODE, &cfg_no_log_stderr_cmd);
873 install_element(CONFIG_NODE, &cfg_log_file_cmd);
874 install_element(CONFIG_NODE, &cfg_no_log_file_cmd);
Katerina Barone-Adesi3309a432013-02-21 05:16:29 +0000875 install_element(CONFIG_NODE, &cfg_log_alarms_cmd);
876 install_element(CONFIG_NODE, &cfg_no_log_alarms_cmd);
Harald Welte28222962011-02-18 20:37:04 +0100877#ifdef HAVE_SYSLOG_H
878 install_element(CONFIG_NODE, &cfg_log_syslog_cmd);
879 install_element(CONFIG_NODE, &cfg_log_syslog_local_cmd);
880 install_element(CONFIG_NODE, &cfg_no_log_syslog_cmd);
881#endif
Harald Welteaa00f992016-12-02 15:30:02 +0100882 install_element(CONFIG_NODE, &cfg_log_gsmtap_cmd);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200883}