blob: 06eb2a56ade19d3c2ebf0815d8c8fc08301decf2 [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
42struct log_target *log_target_create_vty(struct vty *vty)
43{
44 struct log_target *target;
45
46 target = log_target_create();
47 if (!target)
48 return NULL;
49
50 target->tgt_vty.vty = vty;
51 target->output = _vty_output;
52 return target;
53}
54
Harald Welte62ab20c2010-05-14 18:59:17 +020055/* Down vty node level. */
56gDEFUN(ournode_exit,
57 ournode_exit_cmd, "exit", "Exit current mode and down to previous mode\n")
58{
59 switch (vty->node) {
60 case GSMNET_NODE:
61 vty->node = CONFIG_NODE;
62 vty->index = NULL;
63 break;
64 case BTS_NODE:
65 vty->node = GSMNET_NODE;
66 {
67 /* set vty->index correctly ! */
68 struct gsm_bts *bts = vty->index;
69 vty->index = bts->network;
70 vty->index_sub = NULL;
71 }
72 break;
73 case TRX_NODE:
74 vty->node = BTS_NODE;
75 {
76 /* set vty->index correctly ! */
77 struct gsm_bts_trx *trx = vty->index;
78 vty->index = trx->bts;
79 vty->index_sub = &trx->bts->description;
80 }
81 break;
82 case TS_NODE:
83 vty->node = TRX_NODE;
84 {
85 /* set vty->index correctly ! */
86 struct gsm_bts_trx_ts *ts = vty->index;
87 vty->index = ts->trx;
88 vty->index_sub = &ts->trx->description;
89 }
90 break;
91 case MGCP_NODE:
92 case GBPROXY_NODE:
93 case SGSN_NODE:
94 case NS_NODE:
95 vty->node = CONFIG_NODE;
96 vty->index = NULL;
97 break;
98 default:
99 break;
100 }
101 return CMD_SUCCESS;
102}
103
Harald Welte54f74242010-05-14 19:11:04 +0200104/* End of configuration. */
105gDEFUN(ournode_end,
106 ournode_end_cmd, "end", "End current mode and change to enable mode.")
107{
108 switch (vty->node) {
109 case VIEW_NODE:
110 case ENABLE_NODE:
111 /* Nothing to do. */
112 break;
113 case CONFIG_NODE:
114 case GSMNET_NODE:
115 case BTS_NODE:
116 case TRX_NODE:
117 case TS_NODE:
118 case MGCP_NODE:
119 case GBPROXY_NODE:
120 case SGSN_NODE:
121 case NS_NODE:
122 case VTY_NODE:
123 vty_config_unlock(vty);
124 vty->node = ENABLE_NODE;
125 vty->index = NULL;
126 vty->index_sub = NULL;
127 break;
128 default:
129 break;
130 }
131 return CMD_SUCCESS;
132}
133
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200134DEFUN(enable_logging,
135 enable_logging_cmd,
136 "logging enable",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200137 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200138 "Enables logging to this vty\n")
139{
140 struct telnet_connection *conn;
141
142 conn = (struct telnet_connection *) vty->priv;
143 if (conn->dbg) {
144 vty_out(vty, "Logging already enabled.%s", VTY_NEWLINE);
145 return CMD_WARNING;
146 }
147
148 conn->dbg = log_target_create_vty(vty);
149 if (!conn->dbg)
150 return CMD_WARNING;
151
152 log_add_target(conn->dbg);
153 return CMD_SUCCESS;
154}
155
156DEFUN(logging_fltr_imsi,
157 logging_fltr_imsi_cmd,
158 "logging filter imsi IMSI",
Harald Welte95647152010-05-16 00:00:04 +0200159 LOGGING_STR FILTER_STR
160 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200161{
162 struct telnet_connection *conn;
163
164 conn = (struct telnet_connection *) vty->priv;
165 if (!conn->dbg) {
166 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
167 return CMD_WARNING;
168 }
169
170 log_set_imsi_filter(conn->dbg, argv[0]);
171 return CMD_SUCCESS;
172}
173
174DEFUN(logging_fltr_all,
175 logging_fltr_all_cmd,
Harald Welte95647152010-05-16 00:00:04 +0200176 "logging filter all (0|1)",
177 LOGGING_STR FILTER_STR
178 "Do you want to log all messages?\n"
179 "Only print messages matched by other filters\n"
180 "Bypass filter and print all messages\n")
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200181{
182 struct telnet_connection *conn;
183
184 conn = (struct telnet_connection *) vty->priv;
185 if (!conn->dbg) {
186 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
187 return CMD_WARNING;
188 }
189
190 log_set_all_filter(conn->dbg, atoi(argv[0]));
191 return CMD_SUCCESS;
192}
193
194DEFUN(logging_use_clr,
195 logging_use_clr_cmd,
Harald Welte95647152010-05-16 00:00:04 +0200196 "logging color (0|1)",
197 LOGGING_STR "Configure color-printing for log messages\n"
198 "Don't use color for printing messages\n"
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200199 "Use color for printing messages\n")
200{
201 struct telnet_connection *conn;
202
203 conn = (struct telnet_connection *) vty->priv;
204 if (!conn->dbg) {
205 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
206 return CMD_WARNING;
207 }
208
209 log_set_use_color(conn->dbg, atoi(argv[0]));
210 return CMD_SUCCESS;
211}
212
213DEFUN(logging_prnt_timestamp,
214 logging_prnt_timestamp_cmd,
Harald Welte95647152010-05-16 00:00:04 +0200215 "logging timestamp (0|1)",
216 LOGGING_STR "Configure log message timestamping\n"
217 "Don't prefix each log message\n"
218 "Prefix each log message with current timestamp\n")
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200219{
220 struct telnet_connection *conn;
221
222 conn = (struct telnet_connection *) vty->priv;
223 if (!conn->dbg) {
224 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
225 return CMD_WARNING;
226 }
227
228 log_set_print_timestamp(conn->dbg, atoi(argv[0]));
229 return CMD_SUCCESS;
230}
231
232/* FIXME: those have to be kept in sync with the log levels and categories */
Harald Welteb2e49182010-05-13 19:47:01 +0200233#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 +0200234#define CATEGORIES_HELP \
235 "A-bis Radio Link Layer (RLL)\n" \
236 "Layer3 Call Control (CC)\n" \
237 "Layer3 Mobility Management (MM)\n" \
238 "Layer3 Radio Resource (RR)\n" \
239 "A-bis Radio Signalling Link (RSL)\n" \
240 "A-bis Network Management / O&M (NM/OML)\n" \
241 "Layer3 Short Messagaging Service (SMS)\n" \
242 "Paging Subsystem\n" \
243 "MNCC API for Call Control application\n" \
244 "A-bis Input Subsystem\n" \
245 "A-bis Input Driver for Signalling\n" \
246 "A-bis Input Driver for B-Channel (voice data)\n" \
247 "A-bis B-Channel / Sub-channel Multiplexer\n" \
248 "Radio Measurements\n" \
249 "SCCP\n" \
250 "Mobile Switching Center\n" \
251 "Media Gateway Control Protocol\n" \
252 "Hand-over\n" \
253 "Database Layer\n" \
254 "Reference Counting\n" \
255 "GPRS Core\n" \
256 "GPRS Network Service (NS)\n" \
257 "GPRS BSS Gateway Protocol (BSSGP)\n" \
Harald Welteb2e49182010-05-13 19:47:01 +0200258 "GPRS Logical Link Control Protocol (LLC)\n" \
259 "GPRS Sub-Network Dependent Control Protocol (SNDCP)\n" \
Harald Weltecd7c1be2010-05-11 10:41:34 +0200260 "Global setting for all subsytems\n"
261
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200262#define VTY_DEBUG_LEVELS "(everything|debug|info|notice|error|fatal)"
Harald Weltecd7c1be2010-05-11 10:41:34 +0200263#define LEVELS_HELP \
264 "Log simply everything\n" \
265 "Log debug messages and higher levels\n" \
266 "Log informational messages and higher levels\n" \
267 "Log noticable messages and higher levels\n" \
268 "Log error messages and higher levels\n" \
269 "Log only fatal messages\n"
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200270DEFUN(logging_level,
271 logging_level_cmd,
272 "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS,
Harald Weltecd7c1be2010-05-11 10:41:34 +0200273 LOGGING_STR
274 "Set the log level for a specified category\n"
275 CATEGORIES_HELP
276 LEVELS_HELP)
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200277{
278 struct telnet_connection *conn;
279 int category = log_parse_category(argv[0]);
280 int level = log_parse_level(argv[1]);
281
282 conn = (struct telnet_connection *) vty->priv;
283 if (!conn->dbg) {
284 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
285 return CMD_WARNING;
286 }
287
Harald Welte6fab2362010-05-11 10:21:45 +0200288 if (level < 0) {
289 vty_out(vty, "Invalid level `%s'%s", argv[1], VTY_NEWLINE);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200290 return CMD_WARNING;
291 }
292
Harald Welte6fab2362010-05-11 10:21:45 +0200293 /* Check for special case where we want to set global log level */
294 if (!strcmp(argv[0], "all")) {
295 log_set_log_level(conn->dbg, level);
296 return CMD_SUCCESS;
297 }
298
299 if (category < 0) {
300 vty_out(vty, "Invalid category `%s'%s", argv[0], VTY_NEWLINE);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200301 return CMD_WARNING;
302 }
303
304 conn->dbg->categories[category].enabled = 1;
305 conn->dbg->categories[category].loglevel = level;
306
307 return CMD_SUCCESS;
308}
309
310DEFUN(logging_set_category_mask,
311 logging_set_category_mask_cmd,
312 "logging set log mask MASK",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200313 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200314 "Decide which categories to output.\n")
315{
316 struct telnet_connection *conn;
317
318 conn = (struct telnet_connection *) vty->priv;
319 if (!conn->dbg) {
320 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
321 return CMD_WARNING;
322 }
323
324 log_parse_category_mask(conn->dbg, argv[0]);
325 return CMD_SUCCESS;
326}
327
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200328DEFUN(diable_logging,
329 disable_logging_cmd,
330 "logging disable",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200331 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200332 "Disables logging to this vty\n")
333{
334 struct telnet_connection *conn;
335
336 conn = (struct telnet_connection *) vty->priv;
337 if (!conn->dbg) {
338 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
339 return CMD_WARNING;
340 }
341
342 log_del_target(conn->dbg);
343 talloc_free(conn->dbg);
344 conn->dbg = NULL;
345 return CMD_SUCCESS;
346}
347
Harald Welte6f656962010-05-11 11:12:37 +0200348static void vty_print_logtarget(struct vty *vty, const struct log_info *info,
349 const struct log_target *tgt)
350{
351 unsigned int i;
352
353 vty_out(vty, " Global Loglevel: %s%s",
354 log_level_str(tgt->loglevel), VTY_NEWLINE);
355 vty_out(vty, " Use color: %s, Print Timestamp: %s%s",
356 tgt->use_color ? "On" : "Off",
357 tgt->print_timestamp ? "On" : "Off", VTY_NEWLINE);
358
359 vty_out(vty, " Log Level specific information:%s", VTY_NEWLINE);
360
361 for (i = 0; i < info->num_cat; i++) {
362 const struct log_category *cat = &tgt->categories[i];
363 vty_out(vty, " %-10s %-10s %-8s %s%s",
364 info->cat[i].name+1, log_level_str(cat->loglevel),
365 cat->enabled ? "Enabled" : "Disabled",
366 info->cat[i].description,
367 VTY_NEWLINE);
368 }
369}
370
371#define SHOW_LOG_STR "Show current logging configuration\n"
372
373DEFUN(show_logging_vty,
374 show_logging_vty_cmd,
375 "show logging vty",
376 SHOW_STR SHOW_LOG_STR
377 "Show current logging configuration for this vty\n")
378{
379 struct telnet_connection *conn;
380
381 conn = (struct telnet_connection *) vty->priv;
382 if (!conn->dbg) {
383 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
384 return CMD_WARNING;
385 }
386 vty_print_logtarget(vty, &log_info, conn->dbg);
387
388 return CMD_SUCCESS;
389}
390
Harald Welte197dea92010-05-14 17:59:53 +0200391gDEFUN(cfg_description, cfg_description_cmd,
392 "description .TEXT",
393 "Save human-readable decription of the object\n")
394{
395 char **dptr = vty->index_sub;
Harald Welte197dea92010-05-14 17:59:53 +0200396
397 if (!dptr) {
398 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
399 return CMD_WARNING;
400 }
401
Harald Welte20474ad2010-05-16 19:28:32 +0200402 *dptr = argv_concat(argv, argc, 0);
403 if (!dptr)
Harald Welte197dea92010-05-14 17:59:53 +0200404 return CMD_WARNING;
405
Harald Welte197dea92010-05-14 17:59:53 +0200406 return CMD_SUCCESS;
407}
408
409gDEFUN(cfg_no_description, cfg_no_description_cmd,
410 "no description",
411 NO_STR
412 "Remove description of the object\n")
413{
414 char **dptr = vty->index_sub;
415
416 if (!dptr) {
417 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
418 return CMD_WARNING;
419 }
420
421 if (*dptr) {
422 talloc_free(*dptr);
423 *dptr = NULL;
424 }
425
426 return CMD_SUCCESS;
427}
428
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200429void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *net)
430{
431 vty_out(vty, "Channel Requests : %lu total, %lu no channel%s",
432 counter_get(net->stats.chreq.total),
433 counter_get(net->stats.chreq.no_channel), VTY_NEWLINE);
Holger Hans Peter Freyther3ba36d52010-04-17 06:48:29 +0200434 vty_out(vty, "Channel Failures : %lu rf_failures, %lu rll failures%s",
435 counter_get(net->stats.chan.rf_fail),
436 counter_get(net->stats.chan.rll_err), VTY_NEWLINE);
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200437 vty_out(vty, "Paging : %lu attempted, %lu complete, %lu expired%s",
438 counter_get(net->stats.paging.attempted),
439 counter_get(net->stats.paging.completed),
440 counter_get(net->stats.paging.expired), VTY_NEWLINE);
Holger Hans Peter Freytherbb110f92010-04-12 10:45:52 +0200441 vty_out(vty, "BTS failures : %lu OML, %lu RSL%s",
442 counter_get(net->stats.bts.oml_fail),
443 counter_get(net->stats.bts.rsl_fail), VTY_NEWLINE);
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200444}
445
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200446void openbsc_vty_add_cmds()
447{
Harald Welteb4d5b172010-05-12 16:10:35 +0000448 install_element_ve(&enable_logging_cmd);
449 install_element_ve(&disable_logging_cmd);
450 install_element_ve(&logging_fltr_imsi_cmd);
451 install_element_ve(&logging_fltr_all_cmd);
452 install_element_ve(&logging_use_clr_cmd);
453 install_element_ve(&logging_prnt_timestamp_cmd);
454 install_element_ve(&logging_set_category_mask_cmd);
455 install_element_ve(&logging_level_cmd);
456 install_element_ve(&show_logging_vty_cmd);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200457}