blob: 687ef4be59843fc10690123d3e8341cde7f50c9a [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 Weltecd7c1be2010-05-11 10:41:34 +0200176 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200177 "Print all messages related to a IMSI\n")
178{
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,
193 "logging filter all <0-1>",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200194 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200195 "Print all messages to the console\n")
196{
197 struct telnet_connection *conn;
198
199 conn = (struct telnet_connection *) vty->priv;
200 if (!conn->dbg) {
201 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
202 return CMD_WARNING;
203 }
204
205 log_set_all_filter(conn->dbg, atoi(argv[0]));
206 return CMD_SUCCESS;
207}
208
209DEFUN(logging_use_clr,
210 logging_use_clr_cmd,
211 "logging color <0-1>",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200212 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200213 "Use color for printing messages\n")
214{
215 struct telnet_connection *conn;
216
217 conn = (struct telnet_connection *) vty->priv;
218 if (!conn->dbg) {
219 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
220 return CMD_WARNING;
221 }
222
223 log_set_use_color(conn->dbg, atoi(argv[0]));
224 return CMD_SUCCESS;
225}
226
227DEFUN(logging_prnt_timestamp,
228 logging_prnt_timestamp_cmd,
229 "logging timestamp <0-1>",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200230 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200231 "Print the timestamp of each message\n")
232{
233 struct telnet_connection *conn;
234
235 conn = (struct telnet_connection *) vty->priv;
236 if (!conn->dbg) {
237 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
238 return CMD_WARNING;
239 }
240
241 log_set_print_timestamp(conn->dbg, atoi(argv[0]));
242 return CMD_SUCCESS;
243}
244
245/* FIXME: those have to be kept in sync with the log levels and categories */
Harald Welteb2e49182010-05-13 19:47:01 +0200246#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 +0200247#define CATEGORIES_HELP \
248 "A-bis Radio Link Layer (RLL)\n" \
249 "Layer3 Call Control (CC)\n" \
250 "Layer3 Mobility Management (MM)\n" \
251 "Layer3 Radio Resource (RR)\n" \
252 "A-bis Radio Signalling Link (RSL)\n" \
253 "A-bis Network Management / O&M (NM/OML)\n" \
254 "Layer3 Short Messagaging Service (SMS)\n" \
255 "Paging Subsystem\n" \
256 "MNCC API for Call Control application\n" \
257 "A-bis Input Subsystem\n" \
258 "A-bis Input Driver for Signalling\n" \
259 "A-bis Input Driver for B-Channel (voice data)\n" \
260 "A-bis B-Channel / Sub-channel Multiplexer\n" \
261 "Radio Measurements\n" \
262 "SCCP\n" \
263 "Mobile Switching Center\n" \
264 "Media Gateway Control Protocol\n" \
265 "Hand-over\n" \
266 "Database Layer\n" \
267 "Reference Counting\n" \
268 "GPRS Core\n" \
269 "GPRS Network Service (NS)\n" \
270 "GPRS BSS Gateway Protocol (BSSGP)\n" \
Harald Welteb2e49182010-05-13 19:47:01 +0200271 "GPRS Logical Link Control Protocol (LLC)\n" \
272 "GPRS Sub-Network Dependent Control Protocol (SNDCP)\n" \
Harald Weltecd7c1be2010-05-11 10:41:34 +0200273 "Global setting for all subsytems\n"
274
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200275#define VTY_DEBUG_LEVELS "(everything|debug|info|notice|error|fatal)"
Harald Weltecd7c1be2010-05-11 10:41:34 +0200276#define LEVELS_HELP \
277 "Log simply everything\n" \
278 "Log debug messages and higher levels\n" \
279 "Log informational messages and higher levels\n" \
280 "Log noticable messages and higher levels\n" \
281 "Log error messages and higher levels\n" \
282 "Log only fatal messages\n"
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200283DEFUN(logging_level,
284 logging_level_cmd,
285 "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS,
Harald Weltecd7c1be2010-05-11 10:41:34 +0200286 LOGGING_STR
287 "Set the log level for a specified category\n"
288 CATEGORIES_HELP
289 LEVELS_HELP)
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200290{
291 struct telnet_connection *conn;
292 int category = log_parse_category(argv[0]);
293 int level = log_parse_level(argv[1]);
294
295 conn = (struct telnet_connection *) vty->priv;
296 if (!conn->dbg) {
297 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
298 return CMD_WARNING;
299 }
300
Harald Welte6fab2362010-05-11 10:21:45 +0200301 if (level < 0) {
302 vty_out(vty, "Invalid level `%s'%s", argv[1], VTY_NEWLINE);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200303 return CMD_WARNING;
304 }
305
Harald Welte6fab2362010-05-11 10:21:45 +0200306 /* Check for special case where we want to set global log level */
307 if (!strcmp(argv[0], "all")) {
308 log_set_log_level(conn->dbg, level);
309 return CMD_SUCCESS;
310 }
311
312 if (category < 0) {
313 vty_out(vty, "Invalid category `%s'%s", argv[0], VTY_NEWLINE);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200314 return CMD_WARNING;
315 }
316
317 conn->dbg->categories[category].enabled = 1;
318 conn->dbg->categories[category].loglevel = level;
319
320 return CMD_SUCCESS;
321}
322
323DEFUN(logging_set_category_mask,
324 logging_set_category_mask_cmd,
325 "logging set log mask MASK",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200326 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200327 "Decide which categories to output.\n")
328{
329 struct telnet_connection *conn;
330
331 conn = (struct telnet_connection *) vty->priv;
332 if (!conn->dbg) {
333 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
334 return CMD_WARNING;
335 }
336
337 log_parse_category_mask(conn->dbg, argv[0]);
338 return CMD_SUCCESS;
339}
340
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200341DEFUN(diable_logging,
342 disable_logging_cmd,
343 "logging disable",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200344 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200345 "Disables logging to this vty\n")
346{
347 struct telnet_connection *conn;
348
349 conn = (struct telnet_connection *) vty->priv;
350 if (!conn->dbg) {
351 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
352 return CMD_WARNING;
353 }
354
355 log_del_target(conn->dbg);
356 talloc_free(conn->dbg);
357 conn->dbg = NULL;
358 return CMD_SUCCESS;
359}
360
Harald Welte6f656962010-05-11 11:12:37 +0200361static void vty_print_logtarget(struct vty *vty, const struct log_info *info,
362 const struct log_target *tgt)
363{
364 unsigned int i;
365
366 vty_out(vty, " Global Loglevel: %s%s",
367 log_level_str(tgt->loglevel), VTY_NEWLINE);
368 vty_out(vty, " Use color: %s, Print Timestamp: %s%s",
369 tgt->use_color ? "On" : "Off",
370 tgt->print_timestamp ? "On" : "Off", VTY_NEWLINE);
371
372 vty_out(vty, " Log Level specific information:%s", VTY_NEWLINE);
373
374 for (i = 0; i < info->num_cat; i++) {
375 const struct log_category *cat = &tgt->categories[i];
376 vty_out(vty, " %-10s %-10s %-8s %s%s",
377 info->cat[i].name+1, log_level_str(cat->loglevel),
378 cat->enabled ? "Enabled" : "Disabled",
379 info->cat[i].description,
380 VTY_NEWLINE);
381 }
382}
383
384#define SHOW_LOG_STR "Show current logging configuration\n"
385
386DEFUN(show_logging_vty,
387 show_logging_vty_cmd,
388 "show logging vty",
389 SHOW_STR SHOW_LOG_STR
390 "Show current logging configuration for this vty\n")
391{
392 struct telnet_connection *conn;
393
394 conn = (struct telnet_connection *) vty->priv;
395 if (!conn->dbg) {
396 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
397 return CMD_WARNING;
398 }
399 vty_print_logtarget(vty, &log_info, conn->dbg);
400
401 return CMD_SUCCESS;
402}
403
Harald Welte197dea92010-05-14 17:59:53 +0200404gDEFUN(cfg_description, cfg_description_cmd,
405 "description .TEXT",
406 "Save human-readable decription of the object\n")
407{
408 char **dptr = vty->index_sub;
409 struct buffer *b;
410
411 if (!dptr) {
412 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
413 return CMD_WARNING;
414 }
415
416 b = vty_argv_to_buffer(argc, argv, 0);
417 if (!b)
418 return CMD_WARNING;
419
420 if (*dptr)
421 talloc_free(*dptr);
422
423 *dptr = talloc_strdup(NULL, buffer_getstr(b));
424
425 buffer_free(b);
426
427 return CMD_SUCCESS;
428}
429
430gDEFUN(cfg_no_description, cfg_no_description_cmd,
431 "no description",
432 NO_STR
433 "Remove description of the object\n")
434{
435 char **dptr = vty->index_sub;
436
437 if (!dptr) {
438 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
439 return CMD_WARNING;
440 }
441
442 if (*dptr) {
443 talloc_free(*dptr);
444 *dptr = NULL;
445 }
446
447 return CMD_SUCCESS;
448}
449
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200450void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *net)
451{
452 vty_out(vty, "Channel Requests : %lu total, %lu no channel%s",
453 counter_get(net->stats.chreq.total),
454 counter_get(net->stats.chreq.no_channel), VTY_NEWLINE);
Holger Hans Peter Freyther3ba36d52010-04-17 06:48:29 +0200455 vty_out(vty, "Channel Failures : %lu rf_failures, %lu rll failures%s",
456 counter_get(net->stats.chan.rf_fail),
457 counter_get(net->stats.chan.rll_err), VTY_NEWLINE);
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200458 vty_out(vty, "Paging : %lu attempted, %lu complete, %lu expired%s",
459 counter_get(net->stats.paging.attempted),
460 counter_get(net->stats.paging.completed),
461 counter_get(net->stats.paging.expired), VTY_NEWLINE);
Holger Hans Peter Freytherbb110f92010-04-12 10:45:52 +0200462 vty_out(vty, "BTS failures : %lu OML, %lu RSL%s",
463 counter_get(net->stats.bts.oml_fail),
464 counter_get(net->stats.bts.rsl_fail), VTY_NEWLINE);
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200465}
466
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200467void openbsc_vty_add_cmds()
468{
Harald Welteb4d5b172010-05-12 16:10:35 +0000469 install_element_ve(&enable_logging_cmd);
470 install_element_ve(&disable_logging_cmd);
471 install_element_ve(&logging_fltr_imsi_cmd);
472 install_element_ve(&logging_fltr_all_cmd);
473 install_element_ve(&logging_use_clr_cmd);
474 install_element_ve(&logging_prnt_timestamp_cmd);
475 install_element_ve(&logging_set_category_mask_cmd);
476 install_element_ve(&logging_level_cmd);
477 install_element_ve(&show_logging_vty_cmd);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200478}