blob: 8c78caa2df65e6a4be3558b65af239a2f8d63e19 [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
44struct log_target *log_target_create_vty(struct vty *vty)
45{
46 struct log_target *target;
47
48 target = log_target_create();
49 if (!target)
50 return NULL;
51
52 target->tgt_vty.vty = vty;
53 target->output = _vty_output;
54 return target;
55}
56
57DEFUN(enable_logging,
58 enable_logging_cmd,
59 "logging enable",
Harald Weltecd7c1be2010-05-11 10:41:34 +020060 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +020061 "Enables logging to this vty\n")
62{
63 struct telnet_connection *conn;
64
65 conn = (struct telnet_connection *) vty->priv;
66 if (conn->dbg) {
67 vty_out(vty, "Logging already enabled.%s", VTY_NEWLINE);
68 return CMD_WARNING;
69 }
70
71 conn->dbg = log_target_create_vty(vty);
72 if (!conn->dbg)
73 return CMD_WARNING;
74
75 log_add_target(conn->dbg);
76 return CMD_SUCCESS;
77}
78
79DEFUN(logging_fltr_imsi,
80 logging_fltr_imsi_cmd,
81 "logging filter imsi IMSI",
Harald Weltecd7c1be2010-05-11 10:41:34 +020082 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +020083 "Print all messages related to a IMSI\n")
84{
85 struct telnet_connection *conn;
86
87 conn = (struct telnet_connection *) vty->priv;
88 if (!conn->dbg) {
89 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
90 return CMD_WARNING;
91 }
92
93 log_set_imsi_filter(conn->dbg, argv[0]);
94 return CMD_SUCCESS;
95}
96
97DEFUN(logging_fltr_all,
98 logging_fltr_all_cmd,
99 "logging filter all <0-1>",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200100 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200101 "Print all messages to the console\n")
102{
103 struct telnet_connection *conn;
104
105 conn = (struct telnet_connection *) vty->priv;
106 if (!conn->dbg) {
107 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
108 return CMD_WARNING;
109 }
110
111 log_set_all_filter(conn->dbg, atoi(argv[0]));
112 return CMD_SUCCESS;
113}
114
115DEFUN(logging_use_clr,
116 logging_use_clr_cmd,
117 "logging color <0-1>",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200118 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200119 "Use color for printing messages\n")
120{
121 struct telnet_connection *conn;
122
123 conn = (struct telnet_connection *) vty->priv;
124 if (!conn->dbg) {
125 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
126 return CMD_WARNING;
127 }
128
129 log_set_use_color(conn->dbg, atoi(argv[0]));
130 return CMD_SUCCESS;
131}
132
133DEFUN(logging_prnt_timestamp,
134 logging_prnt_timestamp_cmd,
135 "logging timestamp <0-1>",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200136 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200137 "Print the timestamp of each message\n")
138{
139 struct telnet_connection *conn;
140
141 conn = (struct telnet_connection *) vty->priv;
142 if (!conn->dbg) {
143 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
144 return CMD_WARNING;
145 }
146
147 log_set_print_timestamp(conn->dbg, atoi(argv[0]));
148 return CMD_SUCCESS;
149}
150
151/* FIXME: those have to be kept in sync with the log levels and categories */
Harald Welteb2e49182010-05-13 19:47:01 +0200152#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 +0200153#define CATEGORIES_HELP \
154 "A-bis Radio Link Layer (RLL)\n" \
155 "Layer3 Call Control (CC)\n" \
156 "Layer3 Mobility Management (MM)\n" \
157 "Layer3 Radio Resource (RR)\n" \
158 "A-bis Radio Signalling Link (RSL)\n" \
159 "A-bis Network Management / O&M (NM/OML)\n" \
160 "Layer3 Short Messagaging Service (SMS)\n" \
161 "Paging Subsystem\n" \
162 "MNCC API for Call Control application\n" \
163 "A-bis Input Subsystem\n" \
164 "A-bis Input Driver for Signalling\n" \
165 "A-bis Input Driver for B-Channel (voice data)\n" \
166 "A-bis B-Channel / Sub-channel Multiplexer\n" \
167 "Radio Measurements\n" \
168 "SCCP\n" \
169 "Mobile Switching Center\n" \
170 "Media Gateway Control Protocol\n" \
171 "Hand-over\n" \
172 "Database Layer\n" \
173 "Reference Counting\n" \
174 "GPRS Core\n" \
175 "GPRS Network Service (NS)\n" \
176 "GPRS BSS Gateway Protocol (BSSGP)\n" \
Harald Welteb2e49182010-05-13 19:47:01 +0200177 "GPRS Logical Link Control Protocol (LLC)\n" \
178 "GPRS Sub-Network Dependent Control Protocol (SNDCP)\n" \
Harald Weltecd7c1be2010-05-11 10:41:34 +0200179 "Global setting for all subsytems\n"
180
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200181#define VTY_DEBUG_LEVELS "(everything|debug|info|notice|error|fatal)"
Harald Weltecd7c1be2010-05-11 10:41:34 +0200182#define LEVELS_HELP \
183 "Log simply everything\n" \
184 "Log debug messages and higher levels\n" \
185 "Log informational messages and higher levels\n" \
186 "Log noticable messages and higher levels\n" \
187 "Log error messages and higher levels\n" \
188 "Log only fatal messages\n"
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200189DEFUN(logging_level,
190 logging_level_cmd,
191 "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS,
Harald Weltecd7c1be2010-05-11 10:41:34 +0200192 LOGGING_STR
193 "Set the log level for a specified category\n"
194 CATEGORIES_HELP
195 LEVELS_HELP)
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200196{
197 struct telnet_connection *conn;
198 int category = log_parse_category(argv[0]);
199 int level = log_parse_level(argv[1]);
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
Harald Welte6fab2362010-05-11 10:21:45 +0200207 if (level < 0) {
208 vty_out(vty, "Invalid level `%s'%s", argv[1], VTY_NEWLINE);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200209 return CMD_WARNING;
210 }
211
Harald Welte6fab2362010-05-11 10:21:45 +0200212 /* Check for special case where we want to set global log level */
213 if (!strcmp(argv[0], "all")) {
214 log_set_log_level(conn->dbg, level);
215 return CMD_SUCCESS;
216 }
217
218 if (category < 0) {
219 vty_out(vty, "Invalid category `%s'%s", argv[0], VTY_NEWLINE);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200220 return CMD_WARNING;
221 }
222
223 conn->dbg->categories[category].enabled = 1;
224 conn->dbg->categories[category].loglevel = level;
225
226 return CMD_SUCCESS;
227}
228
229DEFUN(logging_set_category_mask,
230 logging_set_category_mask_cmd,
231 "logging set log mask MASK",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200232 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200233 "Decide which categories to output.\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_parse_category_mask(conn->dbg, argv[0]);
244 return CMD_SUCCESS;
245}
246
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200247DEFUN(diable_logging,
248 disable_logging_cmd,
249 "logging disable",
Harald Weltecd7c1be2010-05-11 10:41:34 +0200250 LOGGING_STR
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200251 "Disables logging to this vty\n")
252{
253 struct telnet_connection *conn;
254
255 conn = (struct telnet_connection *) vty->priv;
256 if (!conn->dbg) {
257 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
258 return CMD_WARNING;
259 }
260
261 log_del_target(conn->dbg);
262 talloc_free(conn->dbg);
263 conn->dbg = NULL;
264 return CMD_SUCCESS;
265}
266
Harald Welte6f656962010-05-11 11:12:37 +0200267static void vty_print_logtarget(struct vty *vty, const struct log_info *info,
268 const struct log_target *tgt)
269{
270 unsigned int i;
271
272 vty_out(vty, " Global Loglevel: %s%s",
273 log_level_str(tgt->loglevel), VTY_NEWLINE);
274 vty_out(vty, " Use color: %s, Print Timestamp: %s%s",
275 tgt->use_color ? "On" : "Off",
276 tgt->print_timestamp ? "On" : "Off", VTY_NEWLINE);
277
278 vty_out(vty, " Log Level specific information:%s", VTY_NEWLINE);
279
280 for (i = 0; i < info->num_cat; i++) {
281 const struct log_category *cat = &tgt->categories[i];
282 vty_out(vty, " %-10s %-10s %-8s %s%s",
283 info->cat[i].name+1, log_level_str(cat->loglevel),
284 cat->enabled ? "Enabled" : "Disabled",
285 info->cat[i].description,
286 VTY_NEWLINE);
287 }
288}
289
290#define SHOW_LOG_STR "Show current logging configuration\n"
291
292DEFUN(show_logging_vty,
293 show_logging_vty_cmd,
294 "show logging vty",
295 SHOW_STR SHOW_LOG_STR
296 "Show current logging configuration for this vty\n")
297{
298 struct telnet_connection *conn;
299
300 conn = (struct telnet_connection *) vty->priv;
301 if (!conn->dbg) {
302 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
303 return CMD_WARNING;
304 }
305 vty_print_logtarget(vty, &log_info, conn->dbg);
306
307 return CMD_SUCCESS;
308}
309
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200310void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *net)
311{
312 vty_out(vty, "Channel Requests : %lu total, %lu no channel%s",
313 counter_get(net->stats.chreq.total),
314 counter_get(net->stats.chreq.no_channel), VTY_NEWLINE);
Holger Hans Peter Freyther3ba36d52010-04-17 06:48:29 +0200315 vty_out(vty, "Channel Failures : %lu rf_failures, %lu rll failures%s",
316 counter_get(net->stats.chan.rf_fail),
317 counter_get(net->stats.chan.rll_err), VTY_NEWLINE);
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200318 vty_out(vty, "Paging : %lu attempted, %lu complete, %lu expired%s",
319 counter_get(net->stats.paging.attempted),
320 counter_get(net->stats.paging.completed),
321 counter_get(net->stats.paging.expired), VTY_NEWLINE);
Holger Hans Peter Freytherbb110f92010-04-12 10:45:52 +0200322 vty_out(vty, "BTS failures : %lu OML, %lu RSL%s",
323 counter_get(net->stats.bts.oml_fail),
324 counter_get(net->stats.bts.rsl_fail), VTY_NEWLINE);
Holger Hans Peter Freythere0ec3262010-04-15 11:28:14 +0200325}
326
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200327void openbsc_vty_add_cmds()
328{
Harald Welteb4d5b172010-05-12 16:10:35 +0000329 install_element_ve(&enable_logging_cmd);
330 install_element_ve(&disable_logging_cmd);
331 install_element_ve(&logging_fltr_imsi_cmd);
332 install_element_ve(&logging_fltr_all_cmd);
333 install_element_ve(&logging_use_clr_cmd);
334 install_element_ve(&logging_prnt_timestamp_cmd);
335 install_element_ve(&logging_set_category_mask_cmd);
336 install_element_ve(&logging_level_cmd);
337 install_element_ve(&show_logging_vty_cmd);
Holger Hans Peter Freyther3c712322010-04-06 11:55:37 +0200338}