blob: 4e5dc29191cc9c0fcbec4be47cf0f705a77076b2 [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
74DEFUN(enable_logging,
75 enable_logging_cmd,
76 "logging enable",
Harald Weltecd7c1be2010-05-11 10:41:34 +020077 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +020078 "Enables logging to this vty\n")
79{
80 struct telnet_connection *conn;
81
82 conn = (struct telnet_connection *) vty->priv;
83 if (conn->dbg) {
84 vty_out(vty, "Logging already enabled.%s", VTY_NEWLINE);
85 return CMD_WARNING;
86 }
87
88 conn->dbg = log_target_create_vty(vty);
89 if (!conn->dbg)
90 return CMD_WARNING;
91
92 log_add_target(conn->dbg);
93 return CMD_SUCCESS;
94}
95
96DEFUN(logging_fltr_imsi,
97 logging_fltr_imsi_cmd,
98 "logging filter imsi IMSI",
Harald Weltecd7c1be2010-05-11 10:41:34 +020099 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200100 "Print all messages related to a IMSI\n")
101{
102 struct telnet_connection *conn;
103
104 conn = (struct telnet_connection *) vty->priv;
105 if (!conn->dbg) {
106 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
107 return CMD_WARNING;
108 }
109
110 log_set_imsi_filter(conn->dbg, argv[0]);
111 return CMD_SUCCESS;
112}
113
114DEFUN(logging_fltr_all,
115 logging_fltr_all_cmd,
116 "logging filter all <0-1>",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200117 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200118 "Print all messages to the console\n")
119{
120 struct telnet_connection *conn;
121
122 conn = (struct telnet_connection *) vty->priv;
123 if (!conn->dbg) {
124 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
125 return CMD_WARNING;
126 }
127
128 log_set_all_filter(conn->dbg, atoi(argv[0]));
129 return CMD_SUCCESS;
130}
131
132DEFUN(logging_use_clr,
133 logging_use_clr_cmd,
134 "logging color <0-1>",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200135 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200136 "Use color for printing messages\n")
137{
138 struct telnet_connection *conn;
139
140 conn = (struct telnet_connection *) vty->priv;
141 if (!conn->dbg) {
142 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
143 return CMD_WARNING;
144 }
145
146 log_set_use_color(conn->dbg, atoi(argv[0]));
147 return CMD_SUCCESS;
148}
149
150DEFUN(logging_prnt_timestamp,
151 logging_prnt_timestamp_cmd,
152 "logging timestamp <0-1>",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200153 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200154 "Print the timestamp of each message\n")
155{
156 struct telnet_connection *conn;
157
158 conn = (struct telnet_connection *) vty->priv;
159 if (!conn->dbg) {
160 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
161 return CMD_WARNING;
162 }
163
164 log_set_print_timestamp(conn->dbg, atoi(argv[0]));
165 return CMD_SUCCESS;
166}
167
168/* FIXME: those have to be kept in sync with the log levels and categories */
Harald Welteb2e49182010-05-13 19:47:01 +0200169#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 +0200170#define CATEGORIES_HELP \
171 "A-bis Radio Link Layer (RLL)\n" \
172 "Layer3 Call Control (CC)\n" \
173 "Layer3 Mobility Management (MM)\n" \
174 "Layer3 Radio Resource (RR)\n" \
175 "A-bis Radio Signalling Link (RSL)\n" \
176 "A-bis Network Management / O&M (NM/OML)\n" \
177 "Layer3 Short Messagaging Service (SMS)\n" \
178 "Paging Subsystem\n" \
179 "MNCC API for Call Control application\n" \
180 "A-bis Input Subsystem\n" \
181 "A-bis Input Driver for Signalling\n" \
182 "A-bis Input Driver for B-Channel (voice data)\n" \
183 "A-bis B-Channel / Sub-channel Multiplexer\n" \
184 "Radio Measurements\n" \
185 "SCCP\n" \
186 "Mobile Switching Center\n" \
187 "Media Gateway Control Protocol\n" \
188 "Hand-over\n" \
189 "Database Layer\n" \
190 "Reference Counting\n" \
191 "GPRS Core\n" \
192 "GPRS Network Service (NS)\n" \
193 "GPRS BSS Gateway Protocol (BSSGP)\n" \
Harald Welteb2e49182010-05-13 19:47:01 +0200194 "GPRS Logical Link Control Protocol (LLC)\n" \
195 "GPRS Sub-Network Dependent Control Protocol (SNDCP)\n" \
Harald Weltecd7c1be2010-05-11 10:41:34 +0200196 "Global setting for all subsytems\n"
197
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200198#define VTY_DEBUG_LEVELS "(everything|debug|info|notice|error|fatal)"
Harald Weltecd7c1be2010-05-11 10:41:34 +0200199#define LEVELS_HELP \
200 "Log simply everything\n" \
201 "Log debug messages and higher levels\n" \
202 "Log informational messages and higher levels\n" \
203 "Log noticable messages and higher levels\n" \
204 "Log error messages and higher levels\n" \
205 "Log only fatal messages\n"
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200206DEFUN(logging_level,
207 logging_level_cmd,
208 "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS,
Harald Weltecd7c1be2010-05-11 10:41:34 +0200209 LOGGING_STR
210 "Set the log level for a specified category\n"
211 CATEGORIES_HELP
212 LEVELS_HELP)
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200213{
214 struct telnet_connection *conn;
215 int category = log_parse_category(argv[0]);
216 int level = log_parse_level(argv[1]);
217
218 conn = (struct telnet_connection *) vty->priv;
219 if (!conn->dbg) {
220 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
221 return CMD_WARNING;
222 }
223
Harald Welte6fab2362010-05-11 10:21:45 +0200224 if (level < 0) {
225 vty_out(vty, "Invalid level `%s'%s", argv[1], VTY_NEWLINE);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200226 return CMD_WARNING;
227 }
228
Harald Welte6fab2362010-05-11 10:21:45 +0200229 /* Check for special case where we want to set global log level */
230 if (!strcmp(argv[0], "all")) {
231 log_set_log_level(conn->dbg, level);
232 return CMD_SUCCESS;
233 }
234
235 if (category < 0) {
236 vty_out(vty, "Invalid category `%s'%s", argv[0], VTY_NEWLINE);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200237 return CMD_WARNING;
238 }
239
240 conn->dbg->categories[category].enabled = 1;
241 conn->dbg->categories[category].loglevel = level;
242
243 return CMD_SUCCESS;
244}
245
246DEFUN(logging_set_category_mask,
247 logging_set_category_mask_cmd,
248 "logging set log mask MASK",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200249 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200250 "Decide which categories to output.\n")
251{
252 struct telnet_connection *conn;
253
254 conn = (struct telnet_connection *) vty->priv;
255 if (!conn->dbg) {
256 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
257 return CMD_WARNING;
258 }
259
260 log_parse_category_mask(conn->dbg, argv[0]);
261 return CMD_SUCCESS;
262}
263
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200264DEFUN(diable_logging,
265 disable_logging_cmd,
266 "logging disable",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200267 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200268 "Disables logging to this vty\n")
269{
270 struct telnet_connection *conn;
271
272 conn = (struct telnet_connection *) vty->priv;
273 if (!conn->dbg) {
274 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
275 return CMD_WARNING;
276 }
277
278 log_del_target(conn->dbg);
279 talloc_free(conn->dbg);
280 conn->dbg = NULL;
281 return CMD_SUCCESS;
282}
283
Harald Welte6f656962010-05-11 11:12:37 +0200284static void vty_print_logtarget(struct vty *vty, const struct log_info *info,
285 const struct log_target *tgt)
286{
287 unsigned int i;
288
289 vty_out(vty, " Global Loglevel: %s%s",
290 log_level_str(tgt->loglevel), VTY_NEWLINE);
291 vty_out(vty, " Use color: %s, Print Timestamp: %s%s",
292 tgt->use_color ? "On" : "Off",
293 tgt->print_timestamp ? "On" : "Off", VTY_NEWLINE);
294
295 vty_out(vty, " Log Level specific information:%s", VTY_NEWLINE);
296
297 for (i = 0; i < info->num_cat; i++) {
298 const struct log_category *cat = &tgt->categories[i];
299 vty_out(vty, " %-10s %-10s %-8s %s%s",
300 info->cat[i].name+1, log_level_str(cat->loglevel),
301 cat->enabled ? "Enabled" : "Disabled",
302 info->cat[i].description,
303 VTY_NEWLINE);
304 }
305}
306
307#define SHOW_LOG_STR "Show current logging configuration\n"
308
309DEFUN(show_logging_vty,
310 show_logging_vty_cmd,
311 "show logging vty",
312 SHOW_STR SHOW_LOG_STR
313 "Show current logging configuration for this vty\n")
314{
315 struct telnet_connection *conn;
316
317 conn = (struct telnet_connection *) vty->priv;
318 if (!conn->dbg) {
319 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
320 return CMD_WARNING;
321 }
322 vty_print_logtarget(vty, &log_info, conn->dbg);
323
324 return CMD_SUCCESS;
325}
326
Harald Welte197dea92010-05-14 17:59:53 +0200327gDEFUN(cfg_description, cfg_description_cmd,
328 "description .TEXT",
329 "Save human-readable decription of the object\n")
330{
331 char **dptr = vty->index_sub;
332 struct buffer *b;
333
334 if (!dptr) {
335 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
336 return CMD_WARNING;
337 }
338
339 b = vty_argv_to_buffer(argc, argv, 0);
340 if (!b)
341 return CMD_WARNING;
342
343 if (*dptr)
344 talloc_free(*dptr);
345
346 *dptr = talloc_strdup(NULL, buffer_getstr(b));
347
348 buffer_free(b);
349
350 return CMD_SUCCESS;
351}
352
353gDEFUN(cfg_no_description, cfg_no_description_cmd,
354 "no description",
355 NO_STR
356 "Remove description of the object\n")
357{
358 char **dptr = vty->index_sub;
359
360 if (!dptr) {
361 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
362 return CMD_WARNING;
363 }
364
365 if (*dptr) {
366 talloc_free(*dptr);
367 *dptr = NULL;
368 }
369
370 return CMD_SUCCESS;
371}
372
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200373void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *net)
374{
375 vty_out(vty, "Channel Requests : %lu total, %lu no channel%s",
376 counter_get(net->stats.chreq.total),
377 counter_get(net->stats.chreq.no_channel), VTY_NEWLINE);
Holger Hans Peter Freyther3ba36d52010-04-17 06:48:29 +0200378 vty_out(vty, "Channel Failures : %lu rf_failures, %lu rll failures%s",
379 counter_get(net->stats.chan.rf_fail),
380 counter_get(net->stats.chan.rll_err), VTY_NEWLINE);
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200381 vty_out(vty, "Paging : %lu attempted, %lu complete, %lu expired%s",
382 counter_get(net->stats.paging.attempted),
383 counter_get(net->stats.paging.completed),
384 counter_get(net->stats.paging.expired), VTY_NEWLINE);
Holger Hans Peter Freytherbb110f92010-04-12 10:45:52 +0200385 vty_out(vty, "BTS failures : %lu OML, %lu RSL%s",
386 counter_get(net->stats.bts.oml_fail),
387 counter_get(net->stats.bts.rsl_fail), VTY_NEWLINE);
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200388}
389
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200390void openbsc_vty_add_cmds()
391{
Harald Welteb4d5b172010-05-12 16:10:35 +0000392 install_element_ve(&enable_logging_cmd);
393 install_element_ve(&disable_logging_cmd);
394 install_element_ve(&logging_fltr_imsi_cmd);
395 install_element_ve(&logging_fltr_all_cmd);
396 install_element_ve(&logging_use_clr_cmd);
397 install_element_ve(&logging_prnt_timestamp_cmd);
398 install_element_ve(&logging_set_category_mask_cmd);
399 install_element_ve(&logging_level_cmd);
400 install_element_ve(&show_logging_vty_cmd);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200401}