blob: 6597e440ff41fbe9872189140f83cc4b55a2a85d [file] [log] [blame]
Harald Welte68628e82009-03-10 12:17:57 +00001/* OpenBSC interface to quagga VTY */
2/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 */
20
21#include <stdlib.h>
22#include <unistd.h>
23#include <sys/types.h>
24
25#include <vty/command.h>
26#include <vty/vty.h>
27
28#include <arpa/inet.h>
29
Harald Welte1bc77352009-03-10 19:47:51 +000030#include <openbsc/linuxlist.h>
Harald Welte68628e82009-03-10 12:17:57 +000031#include <openbsc/gsm_data.h>
32#include <openbsc/gsm_subscriber.h>
33#include <openbsc/e1_input.h>
Harald Welte1bc77352009-03-10 19:47:51 +000034#include <openbsc/abis_nm.h>
Harald Welte40f82892009-05-23 17:31:39 +000035#include <openbsc/db.h>
Harald Welte68628e82009-03-10 12:17:57 +000036
37static struct gsm_network *gsmnet;
38
39struct cmd_node bts_node = {
40 BTS_NODE,
41 "%s(bts)#",
42 1,
43};
44
45struct cmd_node trx_node = {
46 TRX_NODE,
47 "%s(trx)#",
48 1,
49};
50
51struct cmd_node ts_node = {
52 TS_NODE,
53 "%s(ts)#",
54 1,
55};
56
Harald Welte40f82892009-05-23 17:31:39 +000057struct cmd_node subscr_node = {
58 SUBSCR_NODE,
59 "%s(subscriber)#",
60 1,
61};
62
Harald Welte68628e82009-03-10 12:17:57 +000063static int dummy_config_write(struct vty *v)
64{
65 return CMD_SUCCESS;
66}
67
68static void net_dump_nmstate(struct vty *vty, struct gsm_nm_state *nms)
69{
Harald Welte1bc77352009-03-10 19:47:51 +000070 vty_out(vty,"Oper '%s', Admin %u, Avail '%s'%s",
71 nm_opstate_name(nms->operational), nms->administrative,
72 nm_avail_name(nms->availability), VTY_NEWLINE);
Harald Welte68628e82009-03-10 12:17:57 +000073}
74
75static void net_dump_vty(struct vty *vty, struct gsm_network *net)
76{
Harald Welteef235b52009-03-10 12:34:02 +000077 vty_out(vty, "BSC is on Country Code %u, Network Code %u "
78 "and has %u BTS%s", net->country_code, net->network_code,
79 net->num_bts, VTY_NEWLINE);
Harald Welte1bc77352009-03-10 19:47:51 +000080 vty_out(vty, " Long network name: '%s'%s",
Harald Welte68628e82009-03-10 12:17:57 +000081 net->name_long, VTY_NEWLINE);
Harald Welte1bc77352009-03-10 19:47:51 +000082 vty_out(vty, " Short network name: '%s'%s",
Harald Welte68628e82009-03-10 12:17:57 +000083 net->name_short, VTY_NEWLINE);
84}
85
86DEFUN(show_net, show_net_cmd, "show network",
87 SHOW_STR "Display information about a GSM NETWORK\n")
88{
89 struct gsm_network *net = gsmnet;
90 net_dump_vty(vty, net);
91
92 return CMD_SUCCESS;
93}
94
95static void e1isl_dump_vty(struct vty *vty, struct e1inp_sign_link *e1l)
96{
Harald Welteedb37782009-05-01 14:59:07 +000097 struct e1inp_line *line;
98
99 if (!e1l) {
100 vty_out(vty, " None%s", VTY_NEWLINE);
101 return;
102 }
103
104 line = e1l->ts->line;
105
106 vty_out(vty, " E1 Line %u, Type %s: Timeslot %u, Mode %s%s",
107 line->num, line->driver->name, e1l->ts->num,
Harald Welte1bc77352009-03-10 19:47:51 +0000108 e1inp_signtype_name(e1l->type), VTY_NEWLINE);
Harald Welteedb37782009-05-01 14:59:07 +0000109 vty_out(vty, " E1 TEI %u, SAPI %u%s",
Harald Welte68628e82009-03-10 12:17:57 +0000110 e1l->tei, e1l->sapi, VTY_NEWLINE);
111}
112
113static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
114{
Harald Welte78f2f502009-05-23 16:56:52 +0000115 vty_out(vty, "BTS %u is of %s type, has LAC %u, BSIC %u, TSC %u and %u TRX%s",
Harald Welte68628e82009-03-10 12:17:57 +0000116 bts->nr, btstype2str(bts->type), bts->location_area_code,
Harald Welte78f2f502009-05-23 16:56:52 +0000117 bts->bsic, bts->tsc, bts->num_trx, VTY_NEWLINE);
Harald Welte4cc34222009-05-01 15:12:31 +0000118 if (is_ipaccess_bts(bts))
119 vty_out(vty, " Unit ID: %u/%u/0%s",
120 bts->ip_access.site_id, bts->ip_access.bts_id,
121 VTY_NEWLINE);
Harald Welte68628e82009-03-10 12:17:57 +0000122 vty_out(vty, " NM State: ");
123 net_dump_nmstate(vty, &bts->nm_state);
124 vty_out(vty, " Site Mgr NM State: ");
125 net_dump_nmstate(vty, &bts->site_mgr.nm_state);
126 vty_out(vty, " Paging: FIXME pending requests, %u free slots%s",
127 bts->paging.available_slots, VTY_NEWLINE);
128 vty_out(vty, " E1 Signalling Link:%s", VTY_NEWLINE);
129 e1isl_dump_vty(vty, bts->oml_link);
130 /* FIXME: oml_link, chan_desc */
131}
132
133DEFUN(show_bts, show_bts_cmd, "show bts [number]",
134 SHOW_STR "Display information about a BTS\n"
135 "BTS number")
136{
137 struct gsm_network *net = gsmnet;
138 int bts_nr;
139
140 if (argc != 0) {
141 /* use the BTS number that the user has specified */
142 bts_nr = atoi(argv[0]);
143 if (bts_nr > net->num_bts) {
Harald Welte1bc77352009-03-10 19:47:51 +0000144 vty_out(vty, "%% can't find BTS '%s'%s", argv[0],
Harald Welte68628e82009-03-10 12:17:57 +0000145 VTY_NEWLINE);
146 return CMD_WARNING;
147 }
148 bts_dump_vty(vty, &net->bts[bts_nr]);
149 return CMD_SUCCESS;
150 }
151 /* print all BTS's */
152 for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++)
153 bts_dump_vty(vty, &net->bts[bts_nr]);
154
155 return CMD_SUCCESS;
156}
157
158static void trx_dump_vty(struct vty *vty, struct gsm_bts_trx *trx)
159{
160 vty_out(vty, "TRX %u of BTS %u is on ARFCN %u%s",
161 trx->nr, trx->bts->nr, trx->arfcn, VTY_NEWLINE);
162 vty_out(vty, " NM State: ");
163 net_dump_nmstate(vty, &trx->nm_state);
164 vty_out(vty, " Baseband Transceiver NM State: ");
165 net_dump_nmstate(vty, &trx->bb_transc.nm_state);
166 vty_out(vty, " E1 Signalling Link:%s", VTY_NEWLINE);
167 e1isl_dump_vty(vty, trx->rsl_link);
168}
169
170DEFUN(show_trx,
171 show_trx_cmd,
172 "show trx [bts_nr] [trx_nr]",
173 SHOW_STR "Display information about a TRX\n")
174{
175 struct gsm_network *net = gsmnet;
176 struct gsm_bts *bts = NULL;
177 struct gsm_bts_trx *trx;
178 int bts_nr, trx_nr;
179
180 if (argc >= 1) {
181 /* use the BTS number that the user has specified */
182 bts_nr = atoi(argv[0]);
183 if (bts_nr >= net->num_bts) {
Harald Welte1bc77352009-03-10 19:47:51 +0000184 vty_out(vty, "%% can't find BTS '%s'%s", argv[0],
Harald Welte68628e82009-03-10 12:17:57 +0000185 VTY_NEWLINE);
186 return CMD_WARNING;
187 }
188 bts = &net->bts[bts_nr];
189 }
190 if (argc >= 2) {
191 trx_nr = atoi(argv[1]);
192 if (trx_nr >= bts->num_trx) {
Harald Welte1bc77352009-03-10 19:47:51 +0000193 vty_out(vty, "%% can't find TRX '%s'%s", argv[1],
Harald Welte68628e82009-03-10 12:17:57 +0000194 VTY_NEWLINE);
195 return CMD_WARNING;
196 }
197 trx = &bts->trx[trx_nr];
198 trx_dump_vty(vty, trx);
199 return CMD_SUCCESS;
200 }
201 if (bts) {
202 /* print all TRX in this BTS */
203 for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
204 trx = &bts->trx[trx_nr];
205 trx_dump_vty(vty, trx);
206 }
207 return CMD_SUCCESS;
208 }
209
210 for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) {
211 bts = &net->bts[bts_nr];
212 for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
213 trx = &bts->trx[trx_nr];
214 trx_dump_vty(vty, trx);
215 }
216 }
217
218 return CMD_SUCCESS;
219}
220
221static void ts_dump_vty(struct vty *vty, struct gsm_bts_trx_ts *ts)
222{
223 struct in_addr ia;
224
225 vty_out(vty, "Timeslot %u of TRX %u in BTS %u, phys cfg %s%s",
226 ts->nr, ts->trx->nr, ts->trx->bts->nr,
227 gsm_pchan_name(ts->pchan), VTY_NEWLINE);
228 vty_out(vty, " NM State: ");
229 net_dump_nmstate(vty, &ts->nm_state);
Harald Welte68628e82009-03-10 12:17:57 +0000230 if (is_ipaccess_bts(ts->trx->bts)) {
231 ia.s_addr = ts->abis_ip.bound_ip;
232 vty_out(vty, " Bound IP: %s Port %u FC=%u F8=%u%s",
233 inet_ntoa(ia), ts->abis_ip.bound_port,
234 ts->abis_ip.attr_fc, ts->abis_ip.attr_f8,
235 VTY_NEWLINE);
Harald Welteef235b52009-03-10 12:34:02 +0000236 } else {
237 vty_out(vty, " E1 Line %u, Timeslot %u, Subslot %u%s",
238 ts->e1_link.e1_nr, ts->e1_link.e1_ts,
239 ts->e1_link.e1_ts_ss, VTY_NEWLINE);
Harald Welte68628e82009-03-10 12:17:57 +0000240 }
241}
242
243DEFUN(show_ts,
244 show_ts_cmd,
Harald Welte1bc77352009-03-10 19:47:51 +0000245 "show timeslot [bts_nr] [trx_nr] [ts_nr]",
Harald Welte68628e82009-03-10 12:17:57 +0000246 SHOW_STR "Display information about a TS\n")
247{
248 struct gsm_network *net = gsmnet;
249 struct gsm_bts *bts;
250 struct gsm_bts_trx *trx;
251 struct gsm_bts_trx_ts *ts;
252 int bts_nr, trx_nr, ts_nr;
253
254 if (argc >= 1) {
255 /* use the BTS number that the user has specified */
256 bts_nr = atoi(argv[0]);
257 if (bts_nr >= net->num_bts) {
Harald Welte1bc77352009-03-10 19:47:51 +0000258 vty_out(vty, "%% can't find BTS '%s'%s", argv[0],
Harald Welte68628e82009-03-10 12:17:57 +0000259 VTY_NEWLINE);
260 return CMD_WARNING;
261 }
262 bts = &net->bts[bts_nr];
263 }
264 if (argc >= 2) {
265 trx_nr = atoi(argv[1]);
266 if (trx_nr >= bts->num_trx) {
Harald Welte1bc77352009-03-10 19:47:51 +0000267 vty_out(vty, "%% can't find TRX '%s'%s", argv[1],
Harald Welte68628e82009-03-10 12:17:57 +0000268 VTY_NEWLINE);
269 return CMD_WARNING;
270 }
271 trx = &bts->trx[trx_nr];
272 }
273 if (argc >= 3) {
274 ts_nr = atoi(argv[2]);
275 if (ts_nr >= TRX_NR_TS) {
Harald Welte1bc77352009-03-10 19:47:51 +0000276 vty_out(vty, "%% can't find TS '%s'%s", argv[2],
Harald Welte68628e82009-03-10 12:17:57 +0000277 VTY_NEWLINE);
278 return CMD_WARNING;
279 }
280 ts = &trx->ts[ts_nr];
281 ts_dump_vty(vty, ts);
282 return CMD_SUCCESS;
283 }
284 for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) {
285 bts = &net->bts[bts_nr];
286 for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
287 trx = &bts->trx[trx_nr];
288 for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
289 ts = &trx->ts[ts_nr];
290 ts_dump_vty(vty, ts);
291 }
292 }
293 }
294
295 return CMD_SUCCESS;
296}
297
298static void subscr_dump_vty(struct vty *vty, struct gsm_subscriber *subscr)
299{
Harald Welte40f82892009-05-23 17:31:39 +0000300 vty_out(vty, " ID: %lu, Authorized: %d%s", subscr->id,
301 subscr->authorized, VTY_NEWLINE);
Harald Welte68628e82009-03-10 12:17:57 +0000302 if (subscr->name)
Harald Welte1bc77352009-03-10 19:47:51 +0000303 vty_out(vty, " Name: '%s'%s", subscr->name, VTY_NEWLINE);
Harald Welte68628e82009-03-10 12:17:57 +0000304 if (subscr->extension)
305 vty_out(vty, " Extension: %s%s", subscr->extension,
306 VTY_NEWLINE);
307 if (subscr->imsi)
308 vty_out(vty, " IMSI: %s%s", subscr->imsi, VTY_NEWLINE);
309 if (subscr->tmsi)
310 vty_out(vty, " TMSI: %s%s", subscr->tmsi, VTY_NEWLINE);
311}
312
313static void lchan_dump_vty(struct vty *vty, struct gsm_lchan *lchan)
314{
315 vty_out(vty, "Lchan %u in Timeslot %u of TRX %u in BTS %u, Type %s%s",
316 lchan->nr, lchan->ts->nr, lchan->ts->trx->nr,
317 lchan->ts->trx->bts->nr, gsm_lchan_name(lchan->type),
318 VTY_NEWLINE);
319 vty_out(vty, " Use Count: %u%s", lchan->use_count, VTY_NEWLINE);
320 vty_out(vty, " BS Power %u, MS Power %u%s", lchan->bs_power,
321 lchan->ms_power, VTY_NEWLINE);
322 if (lchan->subscr) {
323 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
324 subscr_dump_vty(vty, lchan->subscr);
325 } else
326 vty_out(vty, " No Subscriber%s", VTY_NEWLINE);
327}
328
Harald Welte4bfdfe72009-06-10 23:11:52 +0800329#if 0
330TODO: callref and remote callref of call must be resolved to get gsm_trans object
Harald Welte68628e82009-03-10 12:17:57 +0000331static void call_dump_vty(struct vty *vty, struct gsm_call *call)
332{
333 vty_out(vty, "Call Type %u, State %u, Transaction ID %u%s",
334 call->type, call->state, call->transaction_id, VTY_NEWLINE);
335
336 if (call->local_lchan) {
337 vty_out(vty, "Call Local Channel:%s", VTY_NEWLINE);
338 lchan_dump_vty(vty, call->local_lchan);
339 } else
340 vty_out(vty, "Call has no Local Channel%s", VTY_NEWLINE);
341
342 if (call->remote_lchan) {
343 vty_out(vty, "Call Remote Channel:%s", VTY_NEWLINE);
344 lchan_dump_vty(vty, call->remote_lchan);
345 } else
346 vty_out(vty, "Call has no Remote Channel%s", VTY_NEWLINE);
347
348 if (call->called_subscr) {
349 vty_out(vty, "Called Subscriber:%s", VTY_NEWLINE);
350 subscr_dump_vty(vty, call->called_subscr);
351 } else
352 vty_out(vty, "Call has no Called Subscriber%s", VTY_NEWLINE);
353}
Harald Welte4bfdfe72009-06-10 23:11:52 +0800354#endif
Harald Welte68628e82009-03-10 12:17:57 +0000355
356DEFUN(show_lchan,
357 show_lchan_cmd,
358 "show lchan [bts_nr] [trx_nr] [ts_nr] [lchan_nr]",
359 SHOW_STR "Display information about a logical channel\n")
360{
361 struct gsm_network *net = gsmnet;
362 struct gsm_bts *bts;
363 struct gsm_bts_trx *trx;
364 struct gsm_bts_trx_ts *ts;
365 struct gsm_lchan *lchan;
366 int bts_nr, trx_nr, ts_nr, lchan_nr;
367
368 if (argc >= 1) {
369 /* use the BTS number that the user has specified */
370 bts_nr = atoi(argv[0]);
371 if (bts_nr >= net->num_bts) {
372 vty_out(vty, "%% can't find BTS %s%s", argv[0],
373 VTY_NEWLINE);
374 return CMD_WARNING;
375 }
376 bts = &net->bts[bts_nr];
377 }
378 if (argc >= 2) {
379 trx_nr = atoi(argv[1]);
380 if (trx_nr >= bts->num_trx) {
381 vty_out(vty, "%% can't find TRX %s%s", argv[1],
382 VTY_NEWLINE);
383 return CMD_WARNING;
384 }
385 trx = &bts->trx[trx_nr];
386 }
387 if (argc >= 3) {
388 ts_nr = atoi(argv[2]);
389 if (ts_nr >= TRX_NR_TS) {
390 vty_out(vty, "%% can't find TS %s%s", argv[2],
391 VTY_NEWLINE);
392 return CMD_WARNING;
393 }
394 ts = &trx->ts[ts_nr];
395 }
396 if (argc >= 4) {
397 lchan_nr = atoi(argv[3]);
398 if (lchan_nr >= TS_MAX_LCHAN) {
399 vty_out(vty, "%% can't find LCHAN %s%s", argv[3],
400 VTY_NEWLINE);
401 return CMD_WARNING;
402 }
403 lchan = &ts->lchan[lchan_nr];
404 lchan_dump_vty(vty, lchan);
405 return CMD_SUCCESS;
406 }
407 for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) {
408 bts = &net->bts[bts_nr];
409 for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
410 trx = &bts->trx[trx_nr];
411 for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
412 ts = &trx->ts[ts_nr];
413 for (lchan_nr = 0; lchan_nr < TS_MAX_LCHAN;
414 lchan_nr++) {
415 lchan = &ts->lchan[lchan_nr];
Harald Welteef235b52009-03-10 12:34:02 +0000416 if (lchan->type == GSM_LCHAN_NONE)
417 continue;
Harald Welte68628e82009-03-10 12:17:57 +0000418 lchan_dump_vty(vty, lchan);
419 }
420 }
421 }
422 }
423
424 return CMD_SUCCESS;
425}
426
Harald Welte1bc77352009-03-10 19:47:51 +0000427static void e1drv_dump_vty(struct vty *vty, struct e1inp_driver *drv)
428{
429 vty_out(vty, "E1 Input Driver %s%s", drv->name, VTY_NEWLINE);
430}
431
432DEFUN(show_e1drv,
433 show_e1drv_cmd,
434 "show e1_driver",
435 SHOW_STR "Display information about available E1 drivers\n")
436{
437 struct e1inp_driver *drv;
438
439 llist_for_each_entry(drv, &e1inp_driver_list, list)
440 e1drv_dump_vty(vty, drv);
441
442 return CMD_SUCCESS;
443}
444
Harald Welte68628e82009-03-10 12:17:57 +0000445static void e1line_dump_vty(struct vty *vty, struct e1inp_line *line)
446{
447 vty_out(vty, "E1 Line Number %u, Name %s, Driver %s%s",
448 line->num, line->name ? line->name : "",
449 line->driver->name, VTY_NEWLINE);
450}
451
452DEFUN(show_e1line,
453 show_e1line_cmd,
454 "show e1_line [line_nr]",
455 SHOW_STR "Display information about a E1 line\n")
456{
Harald Welte1bc77352009-03-10 19:47:51 +0000457 struct e1inp_line *line;
458
459 if (argc >= 1) {
460 int num = atoi(argv[0]);
461 llist_for_each_entry(line, &e1inp_line_list, list) {
462 if (line->num == num) {
463 e1line_dump_vty(vty, line);
464 return CMD_SUCCESS;
465 }
466 }
467 return CMD_WARNING;
468 }
469
470 llist_for_each_entry(line, &e1inp_line_list, list)
471 e1line_dump_vty(vty, line);
472
473 return CMD_SUCCESS;
Harald Welte68628e82009-03-10 12:17:57 +0000474}
475
476static void e1ts_dump_vty(struct vty *vty, struct e1inp_ts *ts)
477{
Harald Welte1bc77352009-03-10 19:47:51 +0000478 vty_out(vty, "E1 Timeslot %2u of Line %u is Type %s%s",
479 ts->num, ts->line->num, e1inp_tstype_name(ts->type),
480 VTY_NEWLINE);
Harald Welte68628e82009-03-10 12:17:57 +0000481}
482
483DEFUN(show_e1ts,
484 show_e1ts_cmd,
485 "show e1_timeslot [line_nr] [ts_nr]",
486 SHOW_STR "Display information about a E1 timeslot\n")
487{
Harald Welte1bc77352009-03-10 19:47:51 +0000488 struct e1inp_line *line;
489 struct e1inp_ts *ts;
490 int ts_nr;
Harald Welte68628e82009-03-10 12:17:57 +0000491
Harald Welte1bc77352009-03-10 19:47:51 +0000492 if (argc == 0) {
493 llist_for_each_entry(line, &e1inp_line_list, list) {
494 for (ts_nr = 0; ts_nr < NUM_E1_TS; ts_nr++) {
495 ts = &line->ts[ts_nr];
496 e1ts_dump_vty(vty, ts);
497 }
498 }
499 return CMD_SUCCESS;
500 }
501 if (argc >= 1) {
502 int num = atoi(argv[0]);
503 llist_for_each_entry(line, &e1inp_line_list, list) {
504 if (line->num == num)
505 break;
506 }
507 if (!line || line->num != num) {
508 vty_out(vty, "E1 line %s is invalid%s",
509 argv[0], VTY_NEWLINE);
510 return CMD_WARNING;
511 }
512 }
513 if (argc >= 2) {
514 ts_nr = atoi(argv[1]);
515 if (ts_nr > NUM_E1_TS) {
516 vty_out(vty, "E1 timeslot %s is invalid%s",
517 argv[1], VTY_NEWLINE);
518 return CMD_WARNING;
519 }
520 ts = &line->ts[ts_nr];
521 e1ts_dump_vty(vty, ts);
522 return CMD_SUCCESS;
523 } else {
524 for (ts_nr = 0; ts_nr < NUM_E1_TS; ts_nr++) {
525 ts = &line->ts[ts_nr];
526 e1ts_dump_vty(vty, ts);
527 }
528 return CMD_SUCCESS;
529 }
530 return CMD_SUCCESS;
Harald Welte68628e82009-03-10 12:17:57 +0000531}
532
Harald Weltebe4b7302009-05-23 16:59:33 +0000533static void paging_dump_vty(struct vty *vty, struct gsm_paging_request *pag)
Harald Weltef5025b62009-03-28 16:55:11 +0000534{
535 vty_out(vty, "Paging on BTS %u%s", pag->bts->nr, VTY_NEWLINE);
536 subscr_dump_vty(vty, pag->subscr);
537}
538
Harald Weltebe4b7302009-05-23 16:59:33 +0000539static void bts_paging_dump_vty(struct vty *vty, struct gsm_bts *bts)
Harald Weltef5025b62009-03-28 16:55:11 +0000540{
541 struct gsm_paging_request *pag;
542
543 llist_for_each_entry(pag, &bts->paging.pending_requests, entry)
544 paging_dump_vty(vty, pag);
545}
546
547DEFUN(show_paging,
548 show_paging_cmd,
549 "show paging [bts_nr]",
Harald Weltebe4b7302009-05-23 16:59:33 +0000550 SHOW_STR "Display information about paging reuqests of a BTS\n")
Harald Weltef5025b62009-03-28 16:55:11 +0000551{
552 struct gsm_network *net = gsmnet;
553 struct gsm_bts *bts;
554 int bts_nr;
555
556 if (argc >= 1) {
557 /* use the BTS number that the user has specified */
558 bts_nr = atoi(argv[0]);
559 if (bts_nr >= net->num_bts) {
560 vty_out(vty, "%% can't find BTS %s%s", argv[0],
561 VTY_NEWLINE);
562 return CMD_WARNING;
563 }
564 bts = &net->bts[bts_nr];
565 bts_paging_dump_vty(vty, bts);
566
567 return CMD_SUCCESS;
568 }
569 for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) {
570 bts = &net->bts[bts_nr];
571 bts_paging_dump_vty(vty, bts);
572 }
573
574 return CMD_SUCCESS;
575}
576
Harald Welte40f82892009-05-23 17:31:39 +0000577/* per-subscriber configuration */
578DEFUN(cfg_subscr,
579 cfg_subscr_cmd,
580 "subscriber IMSI",
581 "Select a Subscriber to configure\n")
582{
583 const char *imsi = argv[0];
584 struct gsm_subscriber *subscr;
585
586 subscr = subscr_get_by_imsi(imsi);
587 if (!subscr) {
588 vty_out(vty, "%% No subscriber for IMSI %s%s",
589 imsi, VTY_NEWLINE);
590 return CMD_WARNING;
591 }
592
593 vty->index = subscr;
594 vty->node = SUBSCR_NODE;
595
596 return CMD_SUCCESS;
597}
598
599
Harald Welte5258fc42009-03-28 19:07:53 +0000600/* per-BTS configuration */
601DEFUN(cfg_bts,
602 cfg_bts_cmd,
603 "bts BTS_NR",
604 "Select a BTS to configure\n")
605{
606 int bts_nr = atoi(argv[0]);
607 struct gsm_bts *bts;
608
609 if (bts_nr >= GSM_MAX_BTS) {
610 vty_out(vty, "%% This Version of OpenBSC only supports %u BTS%s",
611 GSM_MAX_BTS, VTY_NEWLINE);
612 return CMD_WARNING;
613 }
614 bts = &gsmnet->bts[bts_nr];
615 if (bts_nr >= gsmnet->num_bts)
616 gsmnet->num_bts = bts_nr + 1;
617
618 vty->index = bts;
619 vty->node = BTS_NODE;
620
621 return CMD_SUCCESS;
622}
623
624DEFUN(cfg_bts_type,
625 cfg_bts_type_cmd,
626 "type TYPE",
627 "Set the BTS type\n")
628{
629 struct gsm_bts *bts = vty->index;
630
631 //bts->type =
632 return CMD_SUCCESS;
633}
634
635DEFUN(cfg_bts_lac,
636 cfg_bts_lac_cmd,
637 "location_area_code <0-255>",
638 "Set the Location Area Code (LAC) of this BTS\n")
639{
640 struct gsm_bts *bts = vty->index;
641 int lac = atoi(argv[0]);
642
643 if (lac < 0 || lac > 0xff) {
644 vty_out(vty, "%% LAC %d is not in the valid range (0-255)%s",
645 lac, VTY_NEWLINE);
646 return CMD_WARNING;
647 }
648 bts->location_area_code = lac;
649
650 return CMD_SUCCESS;
651}
652
653DEFUN(cfg_bts_tsc,
654 cfg_bts_tsc_cmd,
655 "training_sequence_code <0-255>",
656 "Set the Training Sequence Code (TSC) of this BTS\n")
657{
658 struct gsm_bts *bts = vty->index;
659 int tsc = atoi(argv[0]);
660
661 if (tsc < 0 || tsc > 0xff) {
662 vty_out(vty, "%% TSC %d is not in the valid range (0-255)%s",
663 tsc, VTY_NEWLINE);
664 return CMD_WARNING;
665 }
666 bts->tsc = tsc;
667
668 return CMD_SUCCESS;
669}
670
Harald Welte78f2f502009-05-23 16:56:52 +0000671DEFUN(cfg_bts_bsic,
672 cfg_bts_bsic_cmd,
673 "base_station_id_code <0-63>",
674 "Set the Base Station Identity Code (BSIC) of this BTS\n")
675{
676 struct gsm_bts *bts = vty->index;
677 int bsic = atoi(argv[0]);
678
679 if (bsic < 0 || bsic > 0x3f) {
680 vty_out(vty, "%% TSC %d is not in the valid range (0-255)%s",
681 bsic, VTY_NEWLINE);
682 return CMD_WARNING;
683 }
684 bts->bsic = bsic;
685
686 return CMD_SUCCESS;
687}
688
689
Harald Welte4cc34222009-05-01 15:12:31 +0000690DEFUN(cfg_bts_unit_id,
691 cfg_bts_unit_id_cmd,
692 "unit_id <0-65534> <0-255>",
693 "Set the BTS Unit ID of this BTS\n")
694{
695 struct gsm_bts *bts = vty->index;
696 int site_id = atoi(argv[0]);
697 int bts_id = atoi(argv[1]);
698
699 if (site_id < 0 || site_id > 65534) {
700 vty_out(vty, "%% Site ID %d is not in the valid range%s",
701 site_id, VTY_NEWLINE);
702 return CMD_WARNING;
703 }
704 if (site_id < 0 || site_id > 255) {
705 vty_out(vty, "%% BTS ID %d is not in the valid range%s",
706 bts_id, VTY_NEWLINE);
707 return CMD_WARNING;
708 }
709 bts->ip_access.site_id = site_id;
710 bts->ip_access.bts_id = bts_id;
711
712 return CMD_SUCCESS;
713}
714
Harald Welte5258fc42009-03-28 19:07:53 +0000715/* per TRX configuration */
716DEFUN(cfg_trx,
717 cfg_trx_cmd,
718 "trx TRX_NR",
719 "Select a TRX to configure")
720{
721 int trx_nr = atoi(argv[0]);
722 struct gsm_bts *bts = vty->index;
723 struct gsm_bts_trx *trx;
724
725 if (trx_nr > BTS_MAX_TRX) {
726 vty_out(vty, "%% This version of OpenBSC only supports %u TRX%s",
727 BTS_MAX_TRX+1, VTY_NEWLINE);
728 return CMD_WARNING;
729 }
730
731 if (trx_nr >= bts->num_trx)
732 bts->num_trx = trx_nr+1;
733
734 trx = &bts->trx[trx_nr];
735
736 vty->index = trx;
737 vty->node = TRX_NODE;
738
739 return CMD_SUCCESS;
740}
741
742DEFUN(cfg_trx_arfcn,
743 cfg_trx_arfcn_cmd,
744 "arfcn <1-1024>",
745 "Set the ARFCN for this TRX\n")
746{
747 int arfcn = atoi(argv[0]);
748 struct gsm_bts_trx *trx = vty->index;
749
750 /* FIXME: check if this ARFCN is supported by this TRX */
751
752 trx->arfcn = arfcn;
753
754 /* FIXME: patch ARFCN into SYSTEM INFORMATION */
755 /* FIXME: use OML layer to update the ARFCN */
756 /* FIXME: use RSL layer to update SYSTEM INFORMATION */
757
758 return CMD_SUCCESS;
759}
760
761/* per TS configuration */
762DEFUN(cfg_ts,
763 cfg_ts_cmd,
764 "timeslot TS_NR",
765 "Select a Timeslot to configure")
766{
767 int ts_nr = atoi(argv[0]);
768 struct gsm_bts_trx *trx = vty->index;
769 struct gsm_bts_trx_ts *ts;
770
771 if (ts_nr >= TRX_NR_TS) {
772 vty_out(vty, "%% A GSM TRX only has %u Timeslots per TRX%s",
773 TRX_NR_TS, VTY_NEWLINE);
774 return CMD_WARNING;
775 }
776
777 ts = &trx->ts[ts_nr];
778
779 vty->index = ts;
780 vty->node = TS_NODE;
781
782 return CMD_SUCCESS;
783}
784
785
Harald Welte40f82892009-05-23 17:31:39 +0000786/* Subscriber */
787DEFUN(show_subscr,
788 show_subscr_cmd,
789 "show subscriber [IMSI]",
790 SHOW_STR "Display information about a subscriber\n")
791{
792 const char *imsi;
793 struct gsm_subscriber *subscr;
794
795 if (argc >= 1) {
796 imsi = argv[0];
797 subscr = subscr_get_by_imsi(imsi);
798 if (!subscr) {
799 vty_out(vty, "%% unknown subscriber%s",
800 VTY_NEWLINE);
801 return CMD_WARNING;
802 }
803 subscr_dump_vty(vty, subscr);
804
805 return CMD_SUCCESS;
806 }
807
808 /* FIXME: iterate over all subscribers ? */
809 return CMD_WARNING;
810
811 return CMD_SUCCESS;
812}
813
814DEFUN(cfg_subscr_name,
815 cfg_subscr_name_cmd,
816 "name NAME",
817 "Set the name of the subscriber")
818{
819 const char *name = argv[0];
820 struct gsm_subscriber *subscr = vty->index;
821
822 strncpy(subscr->name, name, sizeof(subscr->name));
823
824 db_sync_subscriber(subscr);
825
826 return CMD_SUCCESS;
827}
828
829DEFUN(cfg_subscr_extension,
830 cfg_subscr_extension_cmd,
831 "extension EXTENSION",
832 "Set the extension of the subscriber")
833{
834 const char *name = argv[0];
835 struct gsm_subscriber *subscr = vty->index;
836
837 strncpy(subscr->extension, name, sizeof(subscr->extension));
838
839 db_sync_subscriber(subscr);
840
841 return CMD_SUCCESS;
842}
843
844DEFUN(cfg_subscr_authorized,
845 cfg_subscr_authorized_cmd,
846 "auth <0-1>",
847 "Set the authorization status of the subscriber")
848{
849 int auth = atoi(argv[0]);
850 struct gsm_subscriber *subscr = vty->index;
851
852 if (auth)
853 subscr->authorized = 1;
854 else
855 subscr->authorized = 0;
856
857 db_sync_subscriber(subscr);
858
859 return CMD_SUCCESS;
860}
861
Harald Welte68628e82009-03-10 12:17:57 +0000862int bsc_vty_init(struct gsm_network *net)
863{
864 gsmnet = net;
865
866 cmd_init(1);
867 vty_init();
868
869 install_element(VIEW_NODE, &show_net_cmd);
870 install_element(VIEW_NODE, &show_bts_cmd);
871 install_element(VIEW_NODE, &show_trx_cmd);
872 install_element(VIEW_NODE, &show_ts_cmd);
873 install_element(VIEW_NODE, &show_lchan_cmd);
Harald Welte1bc77352009-03-10 19:47:51 +0000874
875 install_element(VIEW_NODE, &show_e1drv_cmd);
Harald Welte68628e82009-03-10 12:17:57 +0000876 install_element(VIEW_NODE, &show_e1line_cmd);
877 install_element(VIEW_NODE, &show_e1ts_cmd);
878
Harald Weltef5025b62009-03-28 16:55:11 +0000879 install_element(VIEW_NODE, &show_paging_cmd);
Harald Welte5258fc42009-03-28 19:07:53 +0000880
Harald Welte40f82892009-05-23 17:31:39 +0000881 install_element(VIEW_NODE, &show_subscr_cmd);
882
Harald Welte5258fc42009-03-28 19:07:53 +0000883 install_element(CONFIG_NODE, &cfg_bts_cmd);
Harald Welte68628e82009-03-10 12:17:57 +0000884 install_node(&bts_node, dummy_config_write);
Harald Welte68628e82009-03-10 12:17:57 +0000885 install_default(BTS_NODE);
Harald Welte5258fc42009-03-28 19:07:53 +0000886 install_element(BTS_NODE, &cfg_bts_type_cmd);
887 install_element(BTS_NODE, &cfg_bts_lac_cmd);
888 install_element(BTS_NODE, &cfg_bts_tsc_cmd);
Harald Welte4cc34222009-05-01 15:12:31 +0000889 install_element(BTS_NODE, &cfg_bts_unit_id_cmd);
Harald Welte68628e82009-03-10 12:17:57 +0000890
Harald Welte5258fc42009-03-28 19:07:53 +0000891 install_element(BTS_NODE, &cfg_trx_cmd);
Harald Welte68628e82009-03-10 12:17:57 +0000892 install_node(&trx_node, dummy_config_write);
Harald Welte68628e82009-03-10 12:17:57 +0000893 install_default(TRX_NODE);
Harald Welte5258fc42009-03-28 19:07:53 +0000894 install_element(TRX_NODE, &cfg_trx_arfcn_cmd);
Harald Welte68628e82009-03-10 12:17:57 +0000895
Harald Welte5258fc42009-03-28 19:07:53 +0000896 install_element(TRX_NODE, &cfg_ts_cmd);
Harald Welte68628e82009-03-10 12:17:57 +0000897 install_node(&ts_node, dummy_config_write);
Harald Welte68628e82009-03-10 12:17:57 +0000898 install_default(TS_NODE);
Harald Welte68628e82009-03-10 12:17:57 +0000899
Harald Welte40f82892009-05-23 17:31:39 +0000900 install_element(CONFIG_NODE, &cfg_subscr_cmd);
901 install_node(&subscr_node, dummy_config_write);
902 install_default(SUBSCR_NODE);
903 install_element(SUBSCR_NODE, &cfg_subscr_name_cmd);
904 install_element(SUBSCR_NODE, &cfg_subscr_extension_cmd);
905 install_element(SUBSCR_NODE, &cfg_subscr_authorized_cmd);
906
Harald Welte68628e82009-03-10 12:17:57 +0000907 return 0;
908}