blob: a2d3258c00ee3286ae116bcc0ba934ac8d56e4e7 [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
Harald Weltecd7c1be2010-05-11 10:41:34 +020033#define LOGGING_STR "Configure log message to this terminal\n"
34
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +020035static void _vty_output(struct log_target *tgt, const char *line)
36{
37 struct vty *vty = tgt->tgt_vty.vty;
38 vty_out(vty, "%s", line);
39 /* This is an ugly hack, but there is no easy way... */
40 if (strchr(line, '\n'))
41 vty_out(vty, "\r");
42}
43
Harald Welte197dea92010-05-14 17:59:53 +020044struct buffer *vty_argv_to_buffer(int argc, const char *argv[], int base)
45{
46 struct buffer *b = buffer_new(NULL, 1024);
47 int i;
48
49 if (!b)
50 return NULL;
51
52 for (i = base; i < argc; i++) {
53 buffer_putstr(b, argv[i]);
54 buffer_putc(b, ' ');
55 }
56 buffer_putc(b, '\0');
57
58 return b;
59}
60
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +020061struct log_target *log_target_create_vty(struct vty *vty)
62{
63 struct log_target *target;
64
65 target = log_target_create();
66 if (!target)
67 return NULL;
68
69 target->tgt_vty.vty = vty;
70 target->output = _vty_output;
71 return target;
72}
73
Harald Welte62ab20c2010-05-14 18:59:17 +020074/* Down vty node level. */
75gDEFUN(ournode_exit,
76 ournode_exit_cmd, "exit", "Exit current mode and down to previous mode\n")
77{
78 switch (vty->node) {
79 case GSMNET_NODE:
80 vty->node = CONFIG_NODE;
81 vty->index = NULL;
82 break;
83 case BTS_NODE:
84 vty->node = GSMNET_NODE;
85 {
86 /* set vty->index correctly ! */
87 struct gsm_bts *bts = vty->index;
88 vty->index = bts->network;
89 vty->index_sub = NULL;
90 }
91 break;
92 case TRX_NODE:
93 vty->node = BTS_NODE;
94 {
95 /* set vty->index correctly ! */
96 struct gsm_bts_trx *trx = vty->index;
97 vty->index = trx->bts;
98 vty->index_sub = &trx->bts->description;
99 }
100 break;
101 case TS_NODE:
102 vty->node = TRX_NODE;
103 {
104 /* set vty->index correctly ! */
105 struct gsm_bts_trx_ts *ts = vty->index;
106 vty->index = ts->trx;
107 vty->index_sub = &ts->trx->description;
108 }
109 break;
110 case MGCP_NODE:
111 case GBPROXY_NODE:
112 case SGSN_NODE:
113 case NS_NODE:
114 vty->node = CONFIG_NODE;
115 vty->index = NULL;
116 break;
117 default:
118 break;
119 }
120 return CMD_SUCCESS;
121}
122
Harald Welte54f74242010-05-14 19:11:04 +0200123/* End of configuration. */
124gDEFUN(ournode_end,
125 ournode_end_cmd, "end", "End current mode and change to enable mode.")
126{
127 switch (vty->node) {
128 case VIEW_NODE:
129 case ENABLE_NODE:
130 /* Nothing to do. */
131 break;
132 case CONFIG_NODE:
133 case GSMNET_NODE:
134 case BTS_NODE:
135 case TRX_NODE:
136 case TS_NODE:
137 case MGCP_NODE:
138 case GBPROXY_NODE:
139 case SGSN_NODE:
140 case NS_NODE:
141 case VTY_NODE:
142 vty_config_unlock(vty);
143 vty->node = ENABLE_NODE;
144 vty->index = NULL;
145 vty->index_sub = NULL;
146 break;
147 default:
148 break;
149 }
150 return CMD_SUCCESS;
151}
152
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200153DEFUN(enable_logging,
154 enable_logging_cmd,
155 "logging enable",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200156 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200157 "Enables logging to this vty\n")
158{
159 struct telnet_connection *conn;
160
161 conn = (struct telnet_connection *) vty->priv;
162 if (conn->dbg) {
163 vty_out(vty, "Logging already enabled.%s", VTY_NEWLINE);
164 return CMD_WARNING;
165 }
166
167 conn->dbg = log_target_create_vty(vty);
168 if (!conn->dbg)
169 return CMD_WARNING;
170
171 log_add_target(conn->dbg);
172 return CMD_SUCCESS;
173}
174
175DEFUN(logging_fltr_imsi,
176 logging_fltr_imsi_cmd,
177 "logging filter imsi IMSI",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200178 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200179 "Print all messages related to a IMSI\n")
180{
181 struct telnet_connection *conn;
182
183 conn = (struct telnet_connection *) vty->priv;
184 if (!conn->dbg) {
185 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
186 return CMD_WARNING;
187 }
188
189 log_set_imsi_filter(conn->dbg, argv[0]);
190 return CMD_SUCCESS;
191}
192
193DEFUN(logging_fltr_all,
194 logging_fltr_all_cmd,
195 "logging filter all <0-1>",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200196 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200197 "Print all messages to the console\n")
198{
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,
213 "logging color <0-1>",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200214 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200215 "Use color for printing messages\n")
216{
217 struct telnet_connection *conn;
218
219 conn = (struct telnet_connection *) vty->priv;
220 if (!conn->dbg) {
221 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
222 return CMD_WARNING;
223 }
224
225 log_set_use_color(conn->dbg, atoi(argv[0]));
226 return CMD_SUCCESS;
227}
228
229DEFUN(logging_prnt_timestamp,
230 logging_prnt_timestamp_cmd,
231 "logging timestamp <0-1>",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200232 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200233 "Print the timestamp of each message\n")
234{
235 struct telnet_connection *conn;
236
237 conn = (struct telnet_connection *) vty->priv;
238 if (!conn->dbg) {
239 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
240 return CMD_WARNING;
241 }
242
243 log_set_print_timestamp(conn->dbg, atoi(argv[0]));
244 return CMD_SUCCESS;
245}
246
247/* FIXME: those have to be kept in sync with the log levels and categories */
Harald Welteb2e49182010-05-13 19:47:01 +0200248#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 +0200249#define CATEGORIES_HELP \
250 "A-bis Radio Link Layer (RLL)\n" \
251 "Layer3 Call Control (CC)\n" \
252 "Layer3 Mobility Management (MM)\n" \
253 "Layer3 Radio Resource (RR)\n" \
254 "A-bis Radio Signalling Link (RSL)\n" \
255 "A-bis Network Management / O&M (NM/OML)\n" \
256 "Layer3 Short Messagaging Service (SMS)\n" \
257 "Paging Subsystem\n" \
258 "MNCC API for Call Control application\n" \
259 "A-bis Input Subsystem\n" \
260 "A-bis Input Driver for Signalling\n" \
261 "A-bis Input Driver for B-Channel (voice data)\n" \
262 "A-bis B-Channel / Sub-channel Multiplexer\n" \
263 "Radio Measurements\n" \
264 "SCCP\n" \
265 "Mobile Switching Center\n" \
266 "Media Gateway Control Protocol\n" \
267 "Hand-over\n" \
268 "Database Layer\n" \
269 "Reference Counting\n" \
270 "GPRS Core\n" \
271 "GPRS Network Service (NS)\n" \
272 "GPRS BSS Gateway Protocol (BSSGP)\n" \
Harald Welteb2e49182010-05-13 19:47:01 +0200273 "GPRS Logical Link Control Protocol (LLC)\n" \
274 "GPRS Sub-Network Dependent Control Protocol (SNDCP)\n" \
Harald Weltecd7c1be2010-05-11 10:41:34 +0200275 "Global setting for all subsytems\n"
276
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200277#define VTY_DEBUG_LEVELS "(everything|debug|info|notice|error|fatal)"
Harald Weltecd7c1be2010-05-11 10:41:34 +0200278#define LEVELS_HELP \
279 "Log simply everything\n" \
280 "Log debug messages and higher levels\n" \
281 "Log informational messages and higher levels\n" \
282 "Log noticable messages and higher levels\n" \
283 "Log error messages and higher levels\n" \
284 "Log only fatal messages\n"
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200285DEFUN(logging_level,
286 logging_level_cmd,
287 "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS,
Harald Weltecd7c1be2010-05-11 10:41:34 +0200288 LOGGING_STR
289 "Set the log level for a specified category\n"
290 CATEGORIES_HELP
291 LEVELS_HELP)
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200292{
293 struct telnet_connection *conn;
294 int category = log_parse_category(argv[0]);
295 int level = log_parse_level(argv[1]);
296
297 conn = (struct telnet_connection *) vty->priv;
298 if (!conn->dbg) {
299 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
300 return CMD_WARNING;
301 }
302
Harald Welte6fab2362010-05-11 10:21:45 +0200303 if (level < 0) {
304 vty_out(vty, "Invalid level `%s'%s", argv[1], VTY_NEWLINE);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200305 return CMD_WARNING;
306 }
307
Harald Welte6fab2362010-05-11 10:21:45 +0200308 /* Check for special case where we want to set global log level */
309 if (!strcmp(argv[0], "all")) {
310 log_set_log_level(conn->dbg, level);
311 return CMD_SUCCESS;
312 }
313
314 if (category < 0) {
315 vty_out(vty, "Invalid category `%s'%s", argv[0], VTY_NEWLINE);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200316 return CMD_WARNING;
317 }
318
319 conn->dbg->categories[category].enabled = 1;
320 conn->dbg->categories[category].loglevel = level;
321
322 return CMD_SUCCESS;
323}
324
325DEFUN(logging_set_category_mask,
326 logging_set_category_mask_cmd,
327 "logging set log mask MASK",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200328 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200329 "Decide which categories to output.\n")
330{
331 struct telnet_connection *conn;
332
333 conn = (struct telnet_connection *) vty->priv;
334 if (!conn->dbg) {
335 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
336 return CMD_WARNING;
337 }
338
339 log_parse_category_mask(conn->dbg, argv[0]);
340 return CMD_SUCCESS;
341}
342
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200343DEFUN(diable_logging,
344 disable_logging_cmd,
345 "logging disable",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200346 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200347 "Disables logging to this vty\n")
348{
349 struct telnet_connection *conn;
350
351 conn = (struct telnet_connection *) vty->priv;
352 if (!conn->dbg) {
353 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
354 return CMD_WARNING;
355 }
356
357 log_del_target(conn->dbg);
358 talloc_free(conn->dbg);
359 conn->dbg = NULL;
360 return CMD_SUCCESS;
361}
362
Harald Welte6f656962010-05-11 11:12:37 +0200363static void vty_print_logtarget(struct vty *vty, const struct log_info *info,
364 const struct log_target *tgt)
365{
366 unsigned int i;
367
368 vty_out(vty, " Global Loglevel: %s%s",
369 log_level_str(tgt->loglevel), VTY_NEWLINE);
370 vty_out(vty, " Use color: %s, Print Timestamp: %s%s",
371 tgt->use_color ? "On" : "Off",
372 tgt->print_timestamp ? "On" : "Off", VTY_NEWLINE);
373
374 vty_out(vty, " Log Level specific information:%s", VTY_NEWLINE);
375
376 for (i = 0; i < info->num_cat; i++) {
377 const struct log_category *cat = &tgt->categories[i];
378 vty_out(vty, " %-10s %-10s %-8s %s%s",
379 info->cat[i].name+1, log_level_str(cat->loglevel),
380 cat->enabled ? "Enabled" : "Disabled",
381 info->cat[i].description,
382 VTY_NEWLINE);
383 }
384}
385
386#define SHOW_LOG_STR "Show current logging configuration\n"
387
388DEFUN(show_logging_vty,
389 show_logging_vty_cmd,
390 "show logging vty",
391 SHOW_STR SHOW_LOG_STR
392 "Show current logging configuration for this vty\n")
393{
394 struct telnet_connection *conn;
395
396 conn = (struct telnet_connection *) vty->priv;
397 if (!conn->dbg) {
398 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
399 return CMD_WARNING;
400 }
401 vty_print_logtarget(vty, &log_info, conn->dbg);
402
403 return CMD_SUCCESS;
404}
405
Harald Welte197dea92010-05-14 17:59:53 +0200406gDEFUN(cfg_description, cfg_description_cmd,
407 "description .TEXT",
408 "Save human-readable decription of the object\n")
409{
410 char **dptr = vty->index_sub;
411 struct buffer *b;
412
413 if (!dptr) {
414 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
415 return CMD_WARNING;
416 }
417
418 b = vty_argv_to_buffer(argc, argv, 0);
419 if (!b)
420 return CMD_WARNING;
421
422 if (*dptr)
423 talloc_free(*dptr);
424
425 *dptr = talloc_strdup(NULL, buffer_getstr(b));
426
427 buffer_free(b);
428
429 return CMD_SUCCESS;
430}
431
432gDEFUN(cfg_no_description, cfg_no_description_cmd,
433 "no description",
434 NO_STR
435 "Remove description of the object\n")
436{
437 char **dptr = vty->index_sub;
438
439 if (!dptr) {
440 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
441 return CMD_WARNING;
442 }
443
444 if (*dptr) {
445 talloc_free(*dptr);
446 *dptr = NULL;
447 }
448
449 return CMD_SUCCESS;
450}
451
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200452void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *net)
453{
454 vty_out(vty, "Channel Requests : %lu total, %lu no channel%s",
455 counter_get(net->stats.chreq.total),
456 counter_get(net->stats.chreq.no_channel), VTY_NEWLINE);
Holger Hans Peter Freyther3ba36d52010-04-17 06:48:29 +0200457 vty_out(vty, "Channel Failures : %lu rf_failures, %lu rll failures%s",
458 counter_get(net->stats.chan.rf_fail),
459 counter_get(net->stats.chan.rll_err), VTY_NEWLINE);
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200460 vty_out(vty, "Paging : %lu attempted, %lu complete, %lu expired%s",
461 counter_get(net->stats.paging.attempted),
462 counter_get(net->stats.paging.completed),
463 counter_get(net->stats.paging.expired), VTY_NEWLINE);
Holger Hans Peter Freytherbb110f92010-04-12 10:45:52 +0200464 vty_out(vty, "BTS failures : %lu OML, %lu RSL%s",
465 counter_get(net->stats.bts.oml_fail),
466 counter_get(net->stats.bts.rsl_fail), VTY_NEWLINE);
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200467}
468
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200469void openbsc_vty_add_cmds()
470{
Harald Welteb4d5b172010-05-12 16:10:35 +0000471 install_element_ve(&enable_logging_cmd);
472 install_element_ve(&disable_logging_cmd);
473 install_element_ve(&logging_fltr_imsi_cmd);
474 install_element_ve(&logging_fltr_all_cmd);
475 install_element_ve(&logging_use_clr_cmd);
476 install_element_ve(&logging_prnt_timestamp_cmd);
477 install_element_ve(&logging_set_category_mask_cmd);
478 install_element_ve(&logging_level_cmd);
479 install_element_ve(&show_logging_vty_cmd);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200480}