blob: 134a8d3a3213d2f051f607f930b5a35ed2105d52 [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
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200123DEFUN(enable_logging,
124 enable_logging_cmd,
125 "logging enable",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200126 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200127 "Enables logging to this vty\n")
128{
129 struct telnet_connection *conn;
130
131 conn = (struct telnet_connection *) vty->priv;
132 if (conn->dbg) {
133 vty_out(vty, "Logging already enabled.%s", VTY_NEWLINE);
134 return CMD_WARNING;
135 }
136
137 conn->dbg = log_target_create_vty(vty);
138 if (!conn->dbg)
139 return CMD_WARNING;
140
141 log_add_target(conn->dbg);
142 return CMD_SUCCESS;
143}
144
145DEFUN(logging_fltr_imsi,
146 logging_fltr_imsi_cmd,
147 "logging filter imsi IMSI",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200148 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200149 "Print all messages related to a IMSI\n")
150{
151 struct telnet_connection *conn;
152
153 conn = (struct telnet_connection *) vty->priv;
154 if (!conn->dbg) {
155 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
156 return CMD_WARNING;
157 }
158
159 log_set_imsi_filter(conn->dbg, argv[0]);
160 return CMD_SUCCESS;
161}
162
163DEFUN(logging_fltr_all,
164 logging_fltr_all_cmd,
165 "logging filter all <0-1>",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200166 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200167 "Print all messages to the console\n")
168{
169 struct telnet_connection *conn;
170
171 conn = (struct telnet_connection *) vty->priv;
172 if (!conn->dbg) {
173 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
174 return CMD_WARNING;
175 }
176
177 log_set_all_filter(conn->dbg, atoi(argv[0]));
178 return CMD_SUCCESS;
179}
180
181DEFUN(logging_use_clr,
182 logging_use_clr_cmd,
183 "logging color <0-1>",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200184 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200185 "Use color for printing messages\n")
186{
187 struct telnet_connection *conn;
188
189 conn = (struct telnet_connection *) vty->priv;
190 if (!conn->dbg) {
191 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
192 return CMD_WARNING;
193 }
194
195 log_set_use_color(conn->dbg, atoi(argv[0]));
196 return CMD_SUCCESS;
197}
198
199DEFUN(logging_prnt_timestamp,
200 logging_prnt_timestamp_cmd,
201 "logging timestamp <0-1>",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200202 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200203 "Print the timestamp of each message\n")
204{
205 struct telnet_connection *conn;
206
207 conn = (struct telnet_connection *) vty->priv;
208 if (!conn->dbg) {
209 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
210 return CMD_WARNING;
211 }
212
213 log_set_print_timestamp(conn->dbg, atoi(argv[0]));
214 return CMD_SUCCESS;
215}
216
217/* FIXME: those have to be kept in sync with the log levels and categories */
Harald Welteb2e49182010-05-13 19:47:01 +0200218#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 +0200219#define CATEGORIES_HELP \
220 "A-bis Radio Link Layer (RLL)\n" \
221 "Layer3 Call Control (CC)\n" \
222 "Layer3 Mobility Management (MM)\n" \
223 "Layer3 Radio Resource (RR)\n" \
224 "A-bis Radio Signalling Link (RSL)\n" \
225 "A-bis Network Management / O&M (NM/OML)\n" \
226 "Layer3 Short Messagaging Service (SMS)\n" \
227 "Paging Subsystem\n" \
228 "MNCC API for Call Control application\n" \
229 "A-bis Input Subsystem\n" \
230 "A-bis Input Driver for Signalling\n" \
231 "A-bis Input Driver for B-Channel (voice data)\n" \
232 "A-bis B-Channel / Sub-channel Multiplexer\n" \
233 "Radio Measurements\n" \
234 "SCCP\n" \
235 "Mobile Switching Center\n" \
236 "Media Gateway Control Protocol\n" \
237 "Hand-over\n" \
238 "Database Layer\n" \
239 "Reference Counting\n" \
240 "GPRS Core\n" \
241 "GPRS Network Service (NS)\n" \
242 "GPRS BSS Gateway Protocol (BSSGP)\n" \
Harald Welteb2e49182010-05-13 19:47:01 +0200243 "GPRS Logical Link Control Protocol (LLC)\n" \
244 "GPRS Sub-Network Dependent Control Protocol (SNDCP)\n" \
Harald Weltecd7c1be2010-05-11 10:41:34 +0200245 "Global setting for all subsytems\n"
246
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200247#define VTY_DEBUG_LEVELS "(everything|debug|info|notice|error|fatal)"
Harald Weltecd7c1be2010-05-11 10:41:34 +0200248#define LEVELS_HELP \
249 "Log simply everything\n" \
250 "Log debug messages and higher levels\n" \
251 "Log informational messages and higher levels\n" \
252 "Log noticable messages and higher levels\n" \
253 "Log error messages and higher levels\n" \
254 "Log only fatal messages\n"
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200255DEFUN(logging_level,
256 logging_level_cmd,
257 "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS,
Harald Weltecd7c1be2010-05-11 10:41:34 +0200258 LOGGING_STR
259 "Set the log level for a specified category\n"
260 CATEGORIES_HELP
261 LEVELS_HELP)
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200262{
263 struct telnet_connection *conn;
264 int category = log_parse_category(argv[0]);
265 int level = log_parse_level(argv[1]);
266
267 conn = (struct telnet_connection *) vty->priv;
268 if (!conn->dbg) {
269 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
270 return CMD_WARNING;
271 }
272
Harald Welte6fab2362010-05-11 10:21:45 +0200273 if (level < 0) {
274 vty_out(vty, "Invalid level `%s'%s", argv[1], VTY_NEWLINE);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200275 return CMD_WARNING;
276 }
277
Harald Welte6fab2362010-05-11 10:21:45 +0200278 /* Check for special case where we want to set global log level */
279 if (!strcmp(argv[0], "all")) {
280 log_set_log_level(conn->dbg, level);
281 return CMD_SUCCESS;
282 }
283
284 if (category < 0) {
285 vty_out(vty, "Invalid category `%s'%s", argv[0], VTY_NEWLINE);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200286 return CMD_WARNING;
287 }
288
289 conn->dbg->categories[category].enabled = 1;
290 conn->dbg->categories[category].loglevel = level;
291
292 return CMD_SUCCESS;
293}
294
295DEFUN(logging_set_category_mask,
296 logging_set_category_mask_cmd,
297 "logging set log mask MASK",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200298 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200299 "Decide which categories to output.\n")
300{
301 struct telnet_connection *conn;
302
303 conn = (struct telnet_connection *) vty->priv;
304 if (!conn->dbg) {
305 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
306 return CMD_WARNING;
307 }
308
309 log_parse_category_mask(conn->dbg, argv[0]);
310 return CMD_SUCCESS;
311}
312
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200313DEFUN(diable_logging,
314 disable_logging_cmd,
315 "logging disable",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200316 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200317 "Disables logging to this vty\n")
318{
319 struct telnet_connection *conn;
320
321 conn = (struct telnet_connection *) vty->priv;
322 if (!conn->dbg) {
323 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
324 return CMD_WARNING;
325 }
326
327 log_del_target(conn->dbg);
328 talloc_free(conn->dbg);
329 conn->dbg = NULL;
330 return CMD_SUCCESS;
331}
332
Harald Welte6f656962010-05-11 11:12:37 +0200333static void vty_print_logtarget(struct vty *vty, const struct log_info *info,
334 const struct log_target *tgt)
335{
336 unsigned int i;
337
338 vty_out(vty, " Global Loglevel: %s%s",
339 log_level_str(tgt->loglevel), VTY_NEWLINE);
340 vty_out(vty, " Use color: %s, Print Timestamp: %s%s",
341 tgt->use_color ? "On" : "Off",
342 tgt->print_timestamp ? "On" : "Off", VTY_NEWLINE);
343
344 vty_out(vty, " Log Level specific information:%s", VTY_NEWLINE);
345
346 for (i = 0; i < info->num_cat; i++) {
347 const struct log_category *cat = &tgt->categories[i];
348 vty_out(vty, " %-10s %-10s %-8s %s%s",
349 info->cat[i].name+1, log_level_str(cat->loglevel),
350 cat->enabled ? "Enabled" : "Disabled",
351 info->cat[i].description,
352 VTY_NEWLINE);
353 }
354}
355
356#define SHOW_LOG_STR "Show current logging configuration\n"
357
358DEFUN(show_logging_vty,
359 show_logging_vty_cmd,
360 "show logging vty",
361 SHOW_STR SHOW_LOG_STR
362 "Show current logging configuration for this vty\n")
363{
364 struct telnet_connection *conn;
365
366 conn = (struct telnet_connection *) vty->priv;
367 if (!conn->dbg) {
368 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
369 return CMD_WARNING;
370 }
371 vty_print_logtarget(vty, &log_info, conn->dbg);
372
373 return CMD_SUCCESS;
374}
375
Harald Welte197dea92010-05-14 17:59:53 +0200376gDEFUN(cfg_description, cfg_description_cmd,
377 "description .TEXT",
378 "Save human-readable decription of the object\n")
379{
380 char **dptr = vty->index_sub;
381 struct buffer *b;
382
383 if (!dptr) {
384 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
385 return CMD_WARNING;
386 }
387
388 b = vty_argv_to_buffer(argc, argv, 0);
389 if (!b)
390 return CMD_WARNING;
391
392 if (*dptr)
393 talloc_free(*dptr);
394
395 *dptr = talloc_strdup(NULL, buffer_getstr(b));
396
397 buffer_free(b);
398
399 return CMD_SUCCESS;
400}
401
402gDEFUN(cfg_no_description, cfg_no_description_cmd,
403 "no description",
404 NO_STR
405 "Remove description of the object\n")
406{
407 char **dptr = vty->index_sub;
408
409 if (!dptr) {
410 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
411 return CMD_WARNING;
412 }
413
414 if (*dptr) {
415 talloc_free(*dptr);
416 *dptr = NULL;
417 }
418
419 return CMD_SUCCESS;
420}
421
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200422void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *net)
423{
424 vty_out(vty, "Channel Requests : %lu total, %lu no channel%s",
425 counter_get(net->stats.chreq.total),
426 counter_get(net->stats.chreq.no_channel), VTY_NEWLINE);
Holger Hans Peter Freyther3ba36d52010-04-17 06:48:29 +0200427 vty_out(vty, "Channel Failures : %lu rf_failures, %lu rll failures%s",
428 counter_get(net->stats.chan.rf_fail),
429 counter_get(net->stats.chan.rll_err), VTY_NEWLINE);
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200430 vty_out(vty, "Paging : %lu attempted, %lu complete, %lu expired%s",
431 counter_get(net->stats.paging.attempted),
432 counter_get(net->stats.paging.completed),
433 counter_get(net->stats.paging.expired), VTY_NEWLINE);
Holger Hans Peter Freytherbb110f92010-04-12 10:45:52 +0200434 vty_out(vty, "BTS failures : %lu OML, %lu RSL%s",
435 counter_get(net->stats.bts.oml_fail),
436 counter_get(net->stats.bts.rsl_fail), VTY_NEWLINE);
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200437}
438
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200439void openbsc_vty_add_cmds()
440{
Harald Welteb4d5b172010-05-12 16:10:35 +0000441 install_element_ve(&enable_logging_cmd);
442 install_element_ve(&disable_logging_cmd);
443 install_element_ve(&logging_fltr_imsi_cmd);
444 install_element_ve(&logging_fltr_all_cmd);
445 install_element_ve(&logging_use_clr_cmd);
446 install_element_ve(&logging_prnt_timestamp_cmd);
447 install_element_ve(&logging_set_category_mask_cmd);
448 install_element_ve(&logging_level_cmd);
449 install_element_ve(&show_logging_vty_cmd);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200450}