blob: 9ca9a247f60ff2144e298d2e3b693ab81017c4ed [file] [log] [blame]
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +02001/* OpenBSC logging helper for the VTY */
2/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
3 * (C) 2009-2010 by Holger Hans Peter Freyther
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 */
21
22#include <openbsc/vty.h>
23#include <openbsc/telnet_interface.h>
24
25#include <osmocore/talloc.h>
26
27#include <vty/command.h>
28#include <vty/buffer.h>
29#include <vty/vty.h>
30
31#include <stdlib.h>
32
33static void _vty_output(struct log_target *tgt, const char *line)
34{
35 struct vty *vty = tgt->tgt_vty.vty;
36 vty_out(vty, "%s", line);
37 /* This is an ugly hack, but there is no easy way... */
38 if (strchr(line, '\n'))
39 vty_out(vty, "\r");
40}
41
Harald Welte197dea92010-05-14 17:59:53 +020042struct buffer *vty_argv_to_buffer(int argc, const char *argv[], int base)
43{
44 struct buffer *b = buffer_new(NULL, 1024);
45 int i;
46
47 if (!b)
48 return NULL;
49
50 for (i = base; i < argc; i++) {
51 buffer_putstr(b, argv[i]);
52 buffer_putc(b, ' ');
53 }
54 buffer_putc(b, '\0');
55
56 return b;
57}
58
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +020059struct log_target *log_target_create_vty(struct vty *vty)
60{
61 struct log_target *target;
62
63 target = log_target_create();
64 if (!target)
65 return NULL;
66
67 target->tgt_vty.vty = vty;
68 target->output = _vty_output;
69 return target;
70}
71
Harald Welte62ab20c2010-05-14 18:59:17 +020072/* Down vty node level. */
73gDEFUN(ournode_exit,
74 ournode_exit_cmd, "exit", "Exit current mode and down to previous mode\n")
75{
76 switch (vty->node) {
77 case GSMNET_NODE:
78 vty->node = CONFIG_NODE;
79 vty->index = NULL;
80 break;
81 case BTS_NODE:
82 vty->node = GSMNET_NODE;
83 {
84 /* set vty->index correctly ! */
85 struct gsm_bts *bts = vty->index;
86 vty->index = bts->network;
87 vty->index_sub = NULL;
88 }
89 break;
90 case TRX_NODE:
91 vty->node = BTS_NODE;
92 {
93 /* set vty->index correctly ! */
94 struct gsm_bts_trx *trx = vty->index;
95 vty->index = trx->bts;
96 vty->index_sub = &trx->bts->description;
97 }
98 break;
99 case TS_NODE:
100 vty->node = TRX_NODE;
101 {
102 /* set vty->index correctly ! */
103 struct gsm_bts_trx_ts *ts = vty->index;
104 vty->index = ts->trx;
105 vty->index_sub = &ts->trx->description;
106 }
107 break;
108 case MGCP_NODE:
109 case GBPROXY_NODE:
110 case SGSN_NODE:
111 case NS_NODE:
112 vty->node = CONFIG_NODE;
113 vty->index = NULL;
114 break;
115 default:
116 break;
117 }
118 return CMD_SUCCESS;
119}
120
Harald Welte54f74242010-05-14 19:11:04 +0200121/* End of configuration. */
122gDEFUN(ournode_end,
123 ournode_end_cmd, "end", "End current mode and change to enable mode.")
124{
125 switch (vty->node) {
126 case VIEW_NODE:
127 case ENABLE_NODE:
128 /* Nothing to do. */
129 break;
130 case CONFIG_NODE:
131 case GSMNET_NODE:
132 case BTS_NODE:
133 case TRX_NODE:
134 case TS_NODE:
135 case MGCP_NODE:
136 case GBPROXY_NODE:
137 case SGSN_NODE:
138 case NS_NODE:
139 case VTY_NODE:
140 vty_config_unlock(vty);
141 vty->node = ENABLE_NODE;
142 vty->index = NULL;
143 vty->index_sub = NULL;
144 break;
145 default:
146 break;
147 }
148 return CMD_SUCCESS;
149}
150
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200151DEFUN(enable_logging,
152 enable_logging_cmd,
153 "logging enable",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200154 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200155 "Enables logging to this vty\n")
156{
157 struct telnet_connection *conn;
158
159 conn = (struct telnet_connection *) vty->priv;
160 if (conn->dbg) {
161 vty_out(vty, "Logging already enabled.%s", VTY_NEWLINE);
162 return CMD_WARNING;
163 }
164
165 conn->dbg = log_target_create_vty(vty);
166 if (!conn->dbg)
167 return CMD_WARNING;
168
169 log_add_target(conn->dbg);
170 return CMD_SUCCESS;
171}
172
173DEFUN(logging_fltr_imsi,
174 logging_fltr_imsi_cmd,
175 "logging filter imsi IMSI",
Harald Welte95647152010-05-16 00:00:04 +0200176 LOGGING_STR FILTER_STR
177 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200178{
179 struct telnet_connection *conn;
180
181 conn = (struct telnet_connection *) vty->priv;
182 if (!conn->dbg) {
183 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
184 return CMD_WARNING;
185 }
186
187 log_set_imsi_filter(conn->dbg, argv[0]);
188 return CMD_SUCCESS;
189}
190
191DEFUN(logging_fltr_all,
192 logging_fltr_all_cmd,
Harald Welte95647152010-05-16 00:00:04 +0200193 "logging filter all (0|1)",
194 LOGGING_STR FILTER_STR
195 "Do you want to log all messages?\n"
196 "Only print messages matched by other filters\n"
197 "Bypass filter and print all messages\n")
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200198{
199 struct telnet_connection *conn;
200
201 conn = (struct telnet_connection *) vty->priv;
202 if (!conn->dbg) {
203 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
204 return CMD_WARNING;
205 }
206
207 log_set_all_filter(conn->dbg, atoi(argv[0]));
208 return CMD_SUCCESS;
209}
210
211DEFUN(logging_use_clr,
212 logging_use_clr_cmd,
Harald Welte95647152010-05-16 00:00:04 +0200213 "logging color (0|1)",
214 LOGGING_STR "Configure color-printing for log messages\n"
215 "Don't use color for printing messages\n"
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200216 "Use color for printing messages\n")
217{
218 struct telnet_connection *conn;
219
220 conn = (struct telnet_connection *) vty->priv;
221 if (!conn->dbg) {
222 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
223 return CMD_WARNING;
224 }
225
226 log_set_use_color(conn->dbg, atoi(argv[0]));
227 return CMD_SUCCESS;
228}
229
230DEFUN(logging_prnt_timestamp,
231 logging_prnt_timestamp_cmd,
Harald Welte95647152010-05-16 00:00:04 +0200232 "logging timestamp (0|1)",
233 LOGGING_STR "Configure log message timestamping\n"
234 "Don't prefix each log message\n"
235 "Prefix each log message with current timestamp\n")
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200236{
237 struct telnet_connection *conn;
238
239 conn = (struct telnet_connection *) vty->priv;
240 if (!conn->dbg) {
241 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
242 return CMD_WARNING;
243 }
244
245 log_set_print_timestamp(conn->dbg, atoi(argv[0]));
246 return CMD_SUCCESS;
247}
248
249/* FIXME: those have to be kept in sync with the log levels and categories */
Harald Welteb2e49182010-05-13 19:47:01 +0200250#define VTY_DEBUG_CATEGORIES "(rll|cc|mm|rr|rsl|nm|sms|pag|mncc|inp|mi|mib|mux|meas|sccp|msc|mgcp|ho|db|ref|gprs|ns|bssgp|llc|sndcp|all)"
Harald Weltecd7c1be2010-05-11 10:41:34 +0200251#define CATEGORIES_HELP \
252 "A-bis Radio Link Layer (RLL)\n" \
253 "Layer3 Call Control (CC)\n" \
254 "Layer3 Mobility Management (MM)\n" \
255 "Layer3 Radio Resource (RR)\n" \
256 "A-bis Radio Signalling Link (RSL)\n" \
257 "A-bis Network Management / O&M (NM/OML)\n" \
258 "Layer3 Short Messagaging Service (SMS)\n" \
259 "Paging Subsystem\n" \
260 "MNCC API for Call Control application\n" \
261 "A-bis Input Subsystem\n" \
262 "A-bis Input Driver for Signalling\n" \
263 "A-bis Input Driver for B-Channel (voice data)\n" \
264 "A-bis B-Channel / Sub-channel Multiplexer\n" \
265 "Radio Measurements\n" \
266 "SCCP\n" \
267 "Mobile Switching Center\n" \
268 "Media Gateway Control Protocol\n" \
269 "Hand-over\n" \
270 "Database Layer\n" \
271 "Reference Counting\n" \
272 "GPRS Core\n" \
273 "GPRS Network Service (NS)\n" \
274 "GPRS BSS Gateway Protocol (BSSGP)\n" \
Harald Welteb2e49182010-05-13 19:47:01 +0200275 "GPRS Logical Link Control Protocol (LLC)\n" \
276 "GPRS Sub-Network Dependent Control Protocol (SNDCP)\n" \
Harald Weltecd7c1be2010-05-11 10:41:34 +0200277 "Global setting for all subsytems\n"
278
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200279#define VTY_DEBUG_LEVELS "(everything|debug|info|notice|error|fatal)"
Harald Weltecd7c1be2010-05-11 10:41:34 +0200280#define LEVELS_HELP \
281 "Log simply everything\n" \
282 "Log debug messages and higher levels\n" \
283 "Log informational messages and higher levels\n" \
284 "Log noticable messages and higher levels\n" \
285 "Log error messages and higher levels\n" \
286 "Log only fatal messages\n"
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200287DEFUN(logging_level,
288 logging_level_cmd,
289 "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS,
Harald Weltecd7c1be2010-05-11 10:41:34 +0200290 LOGGING_STR
291 "Set the log level for a specified category\n"
292 CATEGORIES_HELP
293 LEVELS_HELP)
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200294{
295 struct telnet_connection *conn;
296 int category = log_parse_category(argv[0]);
297 int level = log_parse_level(argv[1]);
298
299 conn = (struct telnet_connection *) vty->priv;
300 if (!conn->dbg) {
301 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
302 return CMD_WARNING;
303 }
304
Harald Welte6fab2362010-05-11 10:21:45 +0200305 if (level < 0) {
306 vty_out(vty, "Invalid level `%s'%s", argv[1], VTY_NEWLINE);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200307 return CMD_WARNING;
308 }
309
Harald Welte6fab2362010-05-11 10:21:45 +0200310 /* Check for special case where we want to set global log level */
311 if (!strcmp(argv[0], "all")) {
312 log_set_log_level(conn->dbg, level);
313 return CMD_SUCCESS;
314 }
315
316 if (category < 0) {
317 vty_out(vty, "Invalid category `%s'%s", argv[0], VTY_NEWLINE);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200318 return CMD_WARNING;
319 }
320
321 conn->dbg->categories[category].enabled = 1;
322 conn->dbg->categories[category].loglevel = level;
323
324 return CMD_SUCCESS;
325}
326
327DEFUN(logging_set_category_mask,
328 logging_set_category_mask_cmd,
329 "logging set log mask MASK",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200330 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200331 "Decide which categories to output.\n")
332{
333 struct telnet_connection *conn;
334
335 conn = (struct telnet_connection *) vty->priv;
336 if (!conn->dbg) {
337 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
338 return CMD_WARNING;
339 }
340
341 log_parse_category_mask(conn->dbg, argv[0]);
342 return CMD_SUCCESS;
343}
344
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200345DEFUN(diable_logging,
346 disable_logging_cmd,
347 "logging disable",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200348 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200349 "Disables logging to this vty\n")
350{
351 struct telnet_connection *conn;
352
353 conn = (struct telnet_connection *) vty->priv;
354 if (!conn->dbg) {
355 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
356 return CMD_WARNING;
357 }
358
359 log_del_target(conn->dbg);
360 talloc_free(conn->dbg);
361 conn->dbg = NULL;
362 return CMD_SUCCESS;
363}
364
Harald Welte6f656962010-05-11 11:12:37 +0200365static void vty_print_logtarget(struct vty *vty, const struct log_info *info,
366 const struct log_target *tgt)
367{
368 unsigned int i;
369
370 vty_out(vty, " Global Loglevel: %s%s",
371 log_level_str(tgt->loglevel), VTY_NEWLINE);
372 vty_out(vty, " Use color: %s, Print Timestamp: %s%s",
373 tgt->use_color ? "On" : "Off",
374 tgt->print_timestamp ? "On" : "Off", VTY_NEWLINE);
375
376 vty_out(vty, " Log Level specific information:%s", VTY_NEWLINE);
377
378 for (i = 0; i < info->num_cat; i++) {
379 const struct log_category *cat = &tgt->categories[i];
380 vty_out(vty, " %-10s %-10s %-8s %s%s",
381 info->cat[i].name+1, log_level_str(cat->loglevel),
382 cat->enabled ? "Enabled" : "Disabled",
383 info->cat[i].description,
384 VTY_NEWLINE);
385 }
386}
387
388#define SHOW_LOG_STR "Show current logging configuration\n"
389
390DEFUN(show_logging_vty,
391 show_logging_vty_cmd,
392 "show logging vty",
393 SHOW_STR SHOW_LOG_STR
394 "Show current logging configuration for this vty\n")
395{
396 struct telnet_connection *conn;
397
398 conn = (struct telnet_connection *) vty->priv;
399 if (!conn->dbg) {
400 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
401 return CMD_WARNING;
402 }
403 vty_print_logtarget(vty, &log_info, conn->dbg);
404
405 return CMD_SUCCESS;
406}
407
Harald Welte197dea92010-05-14 17:59:53 +0200408gDEFUN(cfg_description, cfg_description_cmd,
409 "description .TEXT",
410 "Save human-readable decription of the object\n")
411{
412 char **dptr = vty->index_sub;
413 struct buffer *b;
414
415 if (!dptr) {
416 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
417 return CMD_WARNING;
418 }
419
420 b = vty_argv_to_buffer(argc, argv, 0);
421 if (!b)
422 return CMD_WARNING;
423
424 if (*dptr)
425 talloc_free(*dptr);
426
427 *dptr = talloc_strdup(NULL, buffer_getstr(b));
428
429 buffer_free(b);
430
431 return CMD_SUCCESS;
432}
433
434gDEFUN(cfg_no_description, cfg_no_description_cmd,
435 "no description",
436 NO_STR
437 "Remove description of the object\n")
438{
439 char **dptr = vty->index_sub;
440
441 if (!dptr) {
442 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
443 return CMD_WARNING;
444 }
445
446 if (*dptr) {
447 talloc_free(*dptr);
448 *dptr = NULL;
449 }
450
451 return CMD_SUCCESS;
452}
453
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200454void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *net)
455{
456 vty_out(vty, "Channel Requests : %lu total, %lu no channel%s",
457 counter_get(net->stats.chreq.total),
458 counter_get(net->stats.chreq.no_channel), VTY_NEWLINE);
Holger Hans Peter Freyther3ba36d52010-04-17 06:48:29 +0200459 vty_out(vty, "Channel Failures : %lu rf_failures, %lu rll failures%s",
460 counter_get(net->stats.chan.rf_fail),
461 counter_get(net->stats.chan.rll_err), VTY_NEWLINE);
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200462 vty_out(vty, "Paging : %lu attempted, %lu complete, %lu expired%s",
463 counter_get(net->stats.paging.attempted),
464 counter_get(net->stats.paging.completed),
465 counter_get(net->stats.paging.expired), VTY_NEWLINE);
Holger Hans Peter Freytherbb110f92010-04-12 10:45:52 +0200466 vty_out(vty, "BTS failures : %lu OML, %lu RSL%s",
467 counter_get(net->stats.bts.oml_fail),
468 counter_get(net->stats.bts.rsl_fail), VTY_NEWLINE);
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200469}
470
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200471void openbsc_vty_add_cmds()
472{
Harald Welteb4d5b172010-05-12 16:10:35 +0000473 install_element_ve(&enable_logging_cmd);
474 install_element_ve(&disable_logging_cmd);
475 install_element_ve(&logging_fltr_imsi_cmd);
476 install_element_ve(&logging_fltr_all_cmd);
477 install_element_ve(&logging_use_clr_cmd);
478 install_element_ve(&logging_prnt_timestamp_cmd);
479 install_element_ve(&logging_set_category_mask_cmd);
480 install_element_ve(&logging_level_cmd);
481 install_element_ve(&show_logging_vty_cmd);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200482}