blob: 896d79a9611a8fd7cb229b97f731a60826ad1288 [file] [log] [blame]
Harald Welte3fb0b6f2010-05-19 19:02:52 +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 <stdlib.h>
23#include <string.h>
24
25#include <osmocore/talloc.h>
26#include <osmocore/logging.h>
27
28//#include <openbsc/vty.h>
29
30#include <osmocom/vty/command.h>
31#include <osmocom/vty/buffer.h>
32#include <osmocom/vty/vty.h>
33#include <osmocom/vty/telnet_interface.h>
34#include <osmocom/vty/logging.h>
35
Harald Welte4ebdf742010-05-19 19:54:00 +020036extern const struct log_info *osmo_log_info;
Harald Welte3fb0b6f2010-05-19 19:02:52 +020037
38static void _vty_output(struct log_target *tgt, const char *line)
39{
40 struct vty *vty = tgt->tgt_vty.vty;
41 vty_out(vty, "%s", line);
42 /* This is an ugly hack, but there is no easy way... */
43 if (strchr(line, '\n'))
44 vty_out(vty, "\r");
45}
46
47struct log_target *log_target_create_vty(struct vty *vty)
48{
49 struct log_target *target;
50
51 target = log_target_create();
52 if (!target)
53 return NULL;
54
55 target->tgt_vty.vty = vty;
56 target->output = _vty_output;
57 return target;
58}
59
60DEFUN(enable_logging,
61 enable_logging_cmd,
62 "logging enable",
63 LOGGING_STR
64 "Enables logging to this vty\n")
65{
66 struct telnet_connection *conn;
67
68 conn = (struct telnet_connection *) vty->priv;
69 if (conn->dbg) {
70 vty_out(vty, "Logging already enabled.%s", VTY_NEWLINE);
71 return CMD_WARNING;
72 }
73
74 conn->dbg = log_target_create_vty(vty);
75 if (!conn->dbg)
76 return CMD_WARNING;
77
78 log_add_target(conn->dbg);
79 return CMD_SUCCESS;
80}
81
82DEFUN(logging_fltr_all,
83 logging_fltr_all_cmd,
84 "logging filter all (0|1)",
85 LOGGING_STR FILTER_STR
86 "Do you want to log all messages?\n"
87 "Only print messages matched by other filters\n"
88 "Bypass filter and print all messages\n")
89{
90 struct telnet_connection *conn;
91
92 conn = (struct telnet_connection *) vty->priv;
93 if (!conn->dbg) {
94 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
95 return CMD_WARNING;
96 }
97
98 log_set_all_filter(conn->dbg, atoi(argv[0]));
99 return CMD_SUCCESS;
100}
101
102DEFUN(logging_use_clr,
103 logging_use_clr_cmd,
104 "logging color (0|1)",
105 LOGGING_STR "Configure color-printing for log messages\n"
106 "Don't use color for printing messages\n"
107 "Use color for printing messages\n")
108{
109 struct telnet_connection *conn;
110
111 conn = (struct telnet_connection *) vty->priv;
112 if (!conn->dbg) {
113 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
114 return CMD_WARNING;
115 }
116
117 log_set_use_color(conn->dbg, atoi(argv[0]));
118 return CMD_SUCCESS;
119}
120
121DEFUN(logging_prnt_timestamp,
122 logging_prnt_timestamp_cmd,
123 "logging timestamp (0|1)",
124 LOGGING_STR "Configure log message timestamping\n"
125 "Don't prefix each log message\n"
126 "Prefix each log message with current timestamp\n")
127{
128 struct telnet_connection *conn;
129
130 conn = (struct telnet_connection *) vty->priv;
131 if (!conn->dbg) {
132 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
133 return CMD_WARNING;
134 }
135
136 log_set_print_timestamp(conn->dbg, atoi(argv[0]));
137 return CMD_SUCCESS;
138}
139
140/* FIXME: those have to be kept in sync with the log levels and categories */
141#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)"
142#define CATEGORIES_HELP \
143 "A-bis Radio Link Layer (RLL)\n" \
144 "Layer3 Call Control (CC)\n" \
145 "Layer3 Mobility Management (MM)\n" \
146 "Layer3 Radio Resource (RR)\n" \
147 "A-bis Radio Signalling Link (RSL)\n" \
148 "A-bis Network Management / O&M (NM/OML)\n" \
149 "Layer3 Short Messagaging Service (SMS)\n" \
150 "Paging Subsystem\n" \
151 "MNCC API for Call Control application\n" \
152 "A-bis Input Subsystem\n" \
153 "A-bis Input Driver for Signalling\n" \
154 "A-bis Input Driver for B-Channel (voice data)\n" \
155 "A-bis B-Channel / Sub-channel Multiplexer\n" \
156 "Radio Measurements\n" \
157 "SCCP\n" \
158 "Mobile Switching Center\n" \
159 "Media Gateway Control Protocol\n" \
160 "Hand-over\n" \
161 "Database Layer\n" \
162 "Reference Counting\n" \
163 "GPRS Core\n" \
164 "GPRS Network Service (NS)\n" \
165 "GPRS BSS Gateway Protocol (BSSGP)\n" \
166 "GPRS Logical Link Control Protocol (LLC)\n" \
167 "GPRS Sub-Network Dependent Control Protocol (SNDCP)\n" \
168 "Global setting for all subsytems\n"
169
170#define VTY_DEBUG_LEVELS "(everything|debug|info|notice|error|fatal)"
171#define LEVELS_HELP \
172 "Log simply everything\n" \
173 "Log debug messages and higher levels\n" \
174 "Log informational messages and higher levels\n" \
175 "Log noticable messages and higher levels\n" \
176 "Log error messages and higher levels\n" \
177 "Log only fatal messages\n"
178DEFUN(logging_level,
179 logging_level_cmd,
180 "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS,
181 LOGGING_STR
182 "Set the log level for a specified category\n"
183 CATEGORIES_HELP
184 LEVELS_HELP)
185{
186 struct telnet_connection *conn;
187 int category = log_parse_category(argv[0]);
188 int level = log_parse_level(argv[1]);
189
190 conn = (struct telnet_connection *) vty->priv;
191 if (!conn->dbg) {
192 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
193 return CMD_WARNING;
194 }
195
196 if (level < 0) {
197 vty_out(vty, "Invalid level `%s'%s", argv[1], VTY_NEWLINE);
198 return CMD_WARNING;
199 }
200
201 /* Check for special case where we want to set global log level */
202 if (!strcmp(argv[0], "all")) {
203 log_set_log_level(conn->dbg, level);
204 return CMD_SUCCESS;
205 }
206
207 if (category < 0) {
208 vty_out(vty, "Invalid category `%s'%s", argv[0], VTY_NEWLINE);
209 return CMD_WARNING;
210 }
211
212 conn->dbg->categories[category].enabled = 1;
213 conn->dbg->categories[category].loglevel = level;
214
215 return CMD_SUCCESS;
216}
217
218DEFUN(logging_set_category_mask,
219 logging_set_category_mask_cmd,
220 "logging set log mask MASK",
221 LOGGING_STR
222 "Decide which categories to output.\n")
223{
224 struct telnet_connection *conn;
225
226 conn = (struct telnet_connection *) vty->priv;
227 if (!conn->dbg) {
228 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
229 return CMD_WARNING;
230 }
231
232 log_parse_category_mask(conn->dbg, argv[0]);
233 return CMD_SUCCESS;
234}
235
236DEFUN(diable_logging,
237 disable_logging_cmd,
238 "logging disable",
239 LOGGING_STR
240 "Disables logging to this vty\n")
241{
242 struct telnet_connection *conn;
243
244 conn = (struct telnet_connection *) vty->priv;
245 if (!conn->dbg) {
246 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
247 return CMD_WARNING;
248 }
249
250 log_del_target(conn->dbg);
251 talloc_free(conn->dbg);
252 conn->dbg = NULL;
253 return CMD_SUCCESS;
254}
255
256static void vty_print_logtarget(struct vty *vty, const struct log_info *info,
257 const struct log_target *tgt)
258{
259 unsigned int i;
260
261 vty_out(vty, " Global Loglevel: %s%s",
262 log_level_str(tgt->loglevel), VTY_NEWLINE);
263 vty_out(vty, " Use color: %s, Print Timestamp: %s%s",
264 tgt->use_color ? "On" : "Off",
265 tgt->print_timestamp ? "On" : "Off", VTY_NEWLINE);
266
267 vty_out(vty, " Log Level specific information:%s", VTY_NEWLINE);
268
269 for (i = 0; i < info->num_cat; i++) {
270 const struct log_category *cat = &tgt->categories[i];
271 vty_out(vty, " %-10s %-10s %-8s %s%s",
272 info->cat[i].name+1, log_level_str(cat->loglevel),
273 cat->enabled ? "Enabled" : "Disabled",
274 info->cat[i].description,
275 VTY_NEWLINE);
276 }
277}
278
279#define SHOW_LOG_STR "Show current logging configuration\n"
280
281DEFUN(show_logging_vty,
282 show_logging_vty_cmd,
283 "show logging vty",
284 SHOW_STR SHOW_LOG_STR
285 "Show current logging configuration for this vty\n")
286{
287 struct telnet_connection *conn;
288
289 conn = (struct telnet_connection *) vty->priv;
290 if (!conn->dbg) {
291 vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
292 return CMD_WARNING;
293 }
Harald Welte4ebdf742010-05-19 19:54:00 +0200294 vty_print_logtarget(vty, osmo_log_info, conn->dbg);
Harald Welte3fb0b6f2010-05-19 19:02:52 +0200295
296 return CMD_SUCCESS;
297}
298
299gDEFUN(cfg_description, cfg_description_cmd,
300 "description .TEXT",
301 "Save human-readable decription of the object\n")
302{
303 char **dptr = vty->index_sub;
304
305 if (!dptr) {
306 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
307 return CMD_WARNING;
308 }
309
310 *dptr = argv_concat(argv, argc, 0);
311 if (!dptr)
312 return CMD_WARNING;
313
314 return CMD_SUCCESS;
315}
316
317gDEFUN(cfg_no_description, cfg_no_description_cmd,
318 "no description",
319 NO_STR
320 "Remove description of the object\n")
321{
322 char **dptr = vty->index_sub;
323
324 if (!dptr) {
325 vty_out(vty, "vty->index_sub == NULL%s", VTY_NEWLINE);
326 return CMD_WARNING;
327 }
328
329 if (*dptr) {
330 talloc_free(*dptr);
331 *dptr = NULL;
332 }
333
334 return CMD_SUCCESS;
335}
336
337void logging_vty_add_cmds()
338{
339 install_element_ve(&enable_logging_cmd);
340 install_element_ve(&disable_logging_cmd);
341 install_element_ve(&logging_fltr_all_cmd);
342 install_element_ve(&logging_use_clr_cmd);
343 install_element_ve(&logging_prnt_timestamp_cmd);
344 install_element_ve(&logging_set_category_mask_cmd);
345 install_element_ve(&logging_level_cmd);
346 install_element_ve(&show_logging_vty_cmd);
347}