blob: fe6ae8883e637e7c229dd479ae382de853f70666 [file] [log] [blame]
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001/* MSC interface to quagga VTY */
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002/* (C) 2016-2018 by sysmocom s.m.f.c. GmbH <info@sysmocom.de>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02003 * Based on OpenBSC interface to quagga VTY (libmsc/vty_interface_layer3.c)
Harald Welte7b222aa2017-12-23 19:30:32 +01004 * (C) 2009-2017 by Harald Welte <laforge@gnumonks.org>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02005 * (C) 2009-2011 by Holger Hans Peter Freyther
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23/* NOTE: I would have liked to call this the MSC_NODE instead of the MSC_NODE,
24 * but MSC_NODE already exists to configure a remote MSC for osmo-bsc. */
25
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020026#include "../../bscconfig.h"
27
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020028#include <inttypes.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010029#include <limits.h>
30
31#include <osmocom/gsm/protocol/gsm_08_58.h>
32#include <osmocom/gsm/protocol/gsm_04_14.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020033
34#include <osmocom/vty/command.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010035#include <osmocom/vty/logging.h>
Stefan Sperling617ac802018-02-22 17:58:20 +010036#include <osmocom/vty/misc.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010037#include <osmocom/vty/stats.h>
38
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020039#ifdef BUILD_IU
40#include <osmocom/ranap/iu_client.h>
41#endif
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020042
Neels Hofmeyr90843962017-09-04 15:04:35 +020043#include <osmocom/msc/vty.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010044#include <osmocom/msc/osmo_msc.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020045#include <osmocom/msc/gsm_data.h>
46#include <osmocom/msc/gsm_subscriber.h>
47#include <osmocom/msc/vlr.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010048#include <osmocom/msc/transaction.h>
49#include <osmocom/msc/db.h>
50#include <osmocom/msc/sms_queue.h>
51#include <osmocom/msc/silent_call.h>
52#include <osmocom/msc/gsm_04_80.h>
53#include <osmocom/msc/gsm_04_14.h>
54#include <osmocom/msc/signal.h>
55#include <osmocom/msc/mncc_int.h>
Vadim Yanitskiy1b891302018-08-04 01:33:08 +070056#include <osmocom/msc/rrlp.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010057
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010058static struct gsm_network *gsmnet = NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010059
60struct cmd_node net_node = {
61 GSMNET_NODE,
62 "%s(config-net)# ",
63 1,
64};
65
66#define NETWORK_STR "Configure the GSM network\n"
67#define CODE_CMD_STR "Code commands\n"
68#define NAME_CMD_STR "Name Commands\n"
69#define NAME_STR "Name to use\n"
70
71DEFUN(cfg_net,
72 cfg_net_cmd,
73 "network", NETWORK_STR)
74{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010075 vty->index = gsmnet;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010076 vty->node = GSMNET_NODE;
77
78 return CMD_SUCCESS;
79}
80
81DEFUN(cfg_net_ncc,
82 cfg_net_ncc_cmd,
83 "network country code <1-999>",
84 "Set the GSM network country code\n"
85 "Country commands\n"
86 CODE_CMD_STR
87 "Network Country Code to use\n")
88{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010089 gsmnet->plmn.mcc = atoi(argv[0]);
90
91 return CMD_SUCCESS;
92}
93
94DEFUN(cfg_net_mnc,
95 cfg_net_mnc_cmd,
96 "mobile network code <0-999>",
97 "Set the GSM mobile network code\n"
98 "Network Commands\n"
99 CODE_CMD_STR
100 "Mobile Network Code to use\n")
101{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100102 uint16_t mnc;
103 bool mnc_3_digits;
104
105 if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
106 vty_out(vty, "%% Error decoding MNC: %s%s", argv[0], VTY_NEWLINE);
107 return CMD_WARNING;
108 }
109
110 gsmnet->plmn.mnc = mnc;
111 gsmnet->plmn.mnc_3_digits = mnc_3_digits;
112
113 return CMD_SUCCESS;
114}
115
116DEFUN(cfg_net_name_short,
117 cfg_net_name_short_cmd,
118 "short name NAME",
119 "Set the short GSM network name\n" NAME_CMD_STR NAME_STR)
120{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100121 osmo_talloc_replace_string(gsmnet, &gsmnet->name_short, argv[0]);
122 return CMD_SUCCESS;
123}
124
125DEFUN(cfg_net_name_long,
126 cfg_net_name_long_cmd,
127 "long name NAME",
128 "Set the long GSM network name\n" NAME_CMD_STR NAME_STR)
129{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100130 osmo_talloc_replace_string(gsmnet, &gsmnet->name_long, argv[0]);
131 return CMD_SUCCESS;
132}
133
134DEFUN(cfg_net_encryption,
135 cfg_net_encryption_cmd,
136 "encryption a5 <0-3> [<0-3>] [<0-3>] [<0-3>]",
137 "Encryption options\n"
138 "GSM A5 Air Interface Encryption\n"
139 "A5/n Algorithm Number\n"
140 "A5/n Algorithm Number\n"
141 "A5/n Algorithm Number\n"
142 "A5/n Algorithm Number\n")
143{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100144 unsigned int i;
145
146 gsmnet->a5_encryption_mask = 0;
147 for (i = 0; i < argc; i++)
148 gsmnet->a5_encryption_mask |= (1 << atoi(argv[i]));
149
150 return CMD_SUCCESS;
151}
152
153DEFUN(cfg_net_authentication,
154 cfg_net_authentication_cmd,
155 "authentication (optional|required)",
156 "Whether to enforce MS authentication in 2G\n"
157 "Allow MS to attach via 2G BSC without authentication\n"
158 "Always do authentication\n")
159{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100160 gsmnet->authentication_required = (argv[0][0] == 'r') ? true : false;
161
162 return CMD_SUCCESS;
163}
164
165DEFUN(cfg_net_rrlp_mode, cfg_net_rrlp_mode_cmd,
166 "rrlp mode (none|ms-based|ms-preferred|ass-preferred)",
167 "Radio Resource Location Protocol\n"
168 "Set the Radio Resource Location Protocol Mode\n"
169 "Don't send RRLP request\n"
170 "Request MS-based location\n"
171 "Request any location, prefer MS-based\n"
172 "Request any location, prefer MS-assisted\n")
173{
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700174 gsmnet->rrlp.mode = msc_rrlp_mode_parse(argv[0]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100175
176 return CMD_SUCCESS;
177}
178
179DEFUN(cfg_net_mm_info, cfg_net_mm_info_cmd,
180 "mm info (0|1)",
181 "Mobility Management\n"
182 "Send MM INFO after LOC UPD ACCEPT\n"
183 "Disable\n" "Enable\n")
184{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100185 gsmnet->send_mm_info = atoi(argv[0]);
186
187 return CMD_SUCCESS;
188}
189
190DEFUN(cfg_net_timezone,
191 cfg_net_timezone_cmd,
192 "timezone <-19-19> (0|15|30|45)",
193 "Set the Timezone Offset of the network\n"
194 "Timezone offset (hours)\n"
195 "Timezone offset (00 minutes)\n"
196 "Timezone offset (15 minutes)\n"
197 "Timezone offset (30 minutes)\n"
198 "Timezone offset (45 minutes)\n"
199 )
200{
201 struct gsm_network *net = vty->index;
202 int tzhr = atoi(argv[0]);
203 int tzmn = atoi(argv[1]);
204
205 net->tz.hr = tzhr;
206 net->tz.mn = tzmn;
207 net->tz.dst = 0;
208 net->tz.override = 1;
209
210 return CMD_SUCCESS;
211}
212
213DEFUN(cfg_net_timezone_dst,
214 cfg_net_timezone_dst_cmd,
215 "timezone <-19-19> (0|15|30|45) <0-2>",
216 "Set the Timezone Offset of the network\n"
217 "Timezone offset (hours)\n"
218 "Timezone offset (00 minutes)\n"
219 "Timezone offset (15 minutes)\n"
220 "Timezone offset (30 minutes)\n"
221 "Timezone offset (45 minutes)\n"
222 "DST offset (hours)\n"
223 )
224{
225 struct gsm_network *net = vty->index;
226 int tzhr = atoi(argv[0]);
227 int tzmn = atoi(argv[1]);
228 int tzdst = atoi(argv[2]);
229
230 net->tz.hr = tzhr;
231 net->tz.mn = tzmn;
232 net->tz.dst = tzdst;
233 net->tz.override = 1;
234
235 return CMD_SUCCESS;
236}
237
238DEFUN(cfg_net_no_timezone,
239 cfg_net_no_timezone_cmd,
240 "no timezone",
241 NO_STR
242 "Disable network timezone override, use system tz\n")
243{
244 struct gsm_network *net = vty->index;
245
246 net->tz.override = 0;
247
248 return CMD_SUCCESS;
249}
250
251DEFUN(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
252 "periodic location update <6-1530>",
253 "Periodic Location Updating Interval\n"
254 "Periodic Location Updating Interval\n"
255 "Periodic Location Updating Interval\n"
256 "Periodic Location Updating Interval in Minutes\n")
257{
258 struct gsm_network *net = vty->index;
259
260 net->t3212 = atoi(argv[0]) / 6;
261
262 return CMD_SUCCESS;
263}
264
265DEFUN(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
266 "no periodic location update",
267 NO_STR
268 "Periodic Location Updating Interval\n"
269 "Periodic Location Updating Interval\n"
270 "Periodic Location Updating Interval\n")
271{
272 struct gsm_network *net = vty->index;
273
274 net->t3212 = 0;
275
276 return CMD_SUCCESS;
277}
278
279static int config_write_net(struct vty *vty)
280{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100281 int i;
282
283 vty_out(vty, "network%s", VTY_NEWLINE);
284 vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
285 vty_out(vty, " mobile network code %s%s",
286 osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
287 vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
288 vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
289 vty_out(vty, " encryption a5");
290 for (i = 0; i < 8; i++) {
291 if (gsmnet->a5_encryption_mask & (1 << i))
292 vty_out(vty, " %u", i);
293 }
294 vty_out(vty, "%s", VTY_NEWLINE);
295 vty_out(vty, " authentication %s%s",
296 gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE);
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700297 vty_out(vty, " rrlp mode %s%s", msc_rrlp_mode_name(gsmnet->rrlp.mode),
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100298 VTY_NEWLINE);
299 vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
300 if (gsmnet->tz.override != 0) {
301 if (gsmnet->tz.dst)
302 vty_out(vty, " timezone %d %d %d%s",
303 gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
304 VTY_NEWLINE);
305 else
306 vty_out(vty, " timezone %d %d%s",
307 gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
308 }
309 if (gsmnet->t3212 == 0)
310 vty_out(vty, " no periodic location update%s", VTY_NEWLINE);
311 else
312 vty_out(vty, " periodic location update %u%s",
313 gsmnet->t3212 * 6, VTY_NEWLINE);
314
315 if (gsmnet->emergency.route_to_msisdn) {
316 vty_out(vty, " emergency-call route-to-msisdn %s%s",
317 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
318 }
319
320 return CMD_SUCCESS;
321}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200322
323static struct cmd_node msc_node = {
324 MSC_NODE,
325 "%s(config-msc)# ",
326 1,
327};
328
329DEFUN(cfg_msc, cfg_msc_cmd,
330 "msc", "Configure MSC options")
331{
332 vty->node = MSC_NODE;
333 return CMD_SUCCESS;
334}
335
336DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
337 "assign-tmsi",
338 "Assign TMSI during Location Updating.\n")
339{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200340 gsmnet->vlr->cfg.assign_tmsi = true;
341 return CMD_SUCCESS;
342}
343
344DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
345 "no assign-tmsi",
346 NO_STR "Assign TMSI during Location Updating.\n")
347{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200348 gsmnet->vlr->cfg.assign_tmsi = false;
349 return CMD_SUCCESS;
350}
351
Philipp Maierfbf66102017-04-09 12:32:51 +0200352DEFUN(cfg_msc_cs7_instance_a,
353 cfg_msc_cs7_instance_a_cmd,
354 "cs7-instance-a <0-15>",
355 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
356{
Philipp Maierfbf66102017-04-09 12:32:51 +0200357 gsmnet->a.cs7_instance = atoi(argv[0]);
358 return CMD_SUCCESS;
359}
360
361DEFUN(cfg_msc_cs7_instance_iu,
362 cfg_msc_cs7_instance_iu_cmd,
363 "cs7-instance-iu <0-15>",
364 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
365{
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100366#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200367 gsmnet->iu.cs7_instance = atoi(argv[0]);
368 return CMD_SUCCESS;
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100369#else
370 vty_out(vty, "WARNING: 'cs7-instance-iu' without effect: built without Iu support%s",
371 VTY_NEWLINE);
372 return CMD_WARNING;
373#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200374}
375
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100376DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
377 "auth-tuple-max-reuse-count <-1-2147483647>",
378 "Configure authentication tuple re-use\n"
379 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
380{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100381 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
382 return CMD_SUCCESS;
383}
384
385DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
386 "auth-tuple-reuse-on-error (0|1)",
387 "Configure authentication tuple re-use when HLR is not responsive\n"
388 "0 = never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
389 "1 = if the HLR does not deliver new tuples, do re-use already available old ones.\n")
390{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100391 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
392 return CMD_SUCCESS;
393}
394
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100395DEFUN(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
396 "paging response-timer (default|<1-65535>)",
397 "Configure Paging\n"
398 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
399 " BSS or RNC\n"
400 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
401 "Set paging timeout in seconds\n")
402{
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100403 if (!strcmp(argv[1], "default"))
404 gsmnet->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
405 else
406 gsmnet->paging_response_timer = atoi(argv[0]);
407 return CMD_SUCCESS;
408}
409
Harald Welte69c54a82018-02-09 20:41:14 +0100410DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
411 "emergency-call route-to-msisdn MSISDN",
412 "Configure Emergency Call Behaviour\n"
413 "MSISDN to which Emergency Calls are Dispatched\n"
414 "MSISDN (E.164 Phone Number)\n")
415{
Harald Welte69c54a82018-02-09 20:41:14 +0100416 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
417
418 return CMD_SUCCESS;
419}
420
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200421static int config_write_msc(struct vty *vty)
422{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200423 vty_out(vty, "msc%s", VTY_NEWLINE);
424 vty_out(vty, " %sassign-tmsi%s",
425 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
426
Philipp Maierfbf66102017-04-09 12:32:51 +0200427 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
428 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100429#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200430 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
431 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100432#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200433
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100434 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
435 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
436 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
437 VTY_NEWLINE);
438 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
439 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
440 VTY_NEWLINE);
441
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100442 if (gsmnet->paging_response_timer != MSC_PAGING_RESPONSE_TIMER_DEFAULT)
443 vty_out(vty, " paging response-timer %u%s", gsmnet->paging_response_timer, VTY_NEWLINE);
444
Harald Welte69c54a82018-02-09 20:41:14 +0100445 if (gsmnet->emergency.route_to_msisdn) {
446 vty_out(vty, " emergency-call route-to-msisdn %s%s",
447 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
448 }
449
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200450 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200451#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200452 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200453#endif
454
455 return CMD_SUCCESS;
456}
457
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100458static void vty_conn_hdr(struct vty *vty)
459{
460 vty_out(vty, "--ConnId ------------Subscriber RAN --LAC Use --Tokens C A5 State%s",
461 VTY_NEWLINE);
462}
463
464static void vty_dump_one_conn(struct vty *vty, const struct gsm_subscriber_connection *conn)
465{
466 vty_out(vty, "%08x %22s %3s %5u %3u %08x %c /%1u %27s %s",
467 conn->a.conn_id,
468 conn->vsub ? vlr_subscr_name(conn->vsub) : "-",
469 conn->via_ran == RAN_UTRAN_IU ? "Iu" : "A",
470 conn->lac,
471 conn->use_count,
472 conn->use_tokens,
473 conn->received_cm_service_request ? 'C' : '-',
474 conn->encr.alg_id,
Neels Hofmeyr4d3a66b2018-03-31 18:45:59 +0200475 conn->fi ? osmo_fsm_inst_state_name(conn->fi) : "-",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100476 VTY_NEWLINE);
477}
478
479DEFUN(show_msc_conn, show_msc_conn_cmd,
480 "show connection", SHOW_STR "Subscriber Connections\n")
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200481{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100482 struct gsm_subscriber_connection *conn;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200483
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100484 vty_conn_hdr(vty);
485 llist_for_each_entry(conn, &gsmnet->subscr_conns, entry)
486 vty_dump_one_conn(vty, conn);
487
488 return CMD_SUCCESS;
489}
490
491static void vty_trans_hdr(struct vty *vty)
492{
493 vty_out(vty, "------------Subscriber --ConnId -P TI -CallRef Proto%s",
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200494 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100495}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200496
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100497static const char *get_trans_proto_str(const struct gsm_trans *trans)
498{
499 static char buf[256];
500
501 switch (trans->protocol) {
502 case GSM48_PDISC_CC:
503 snprintf(buf, sizeof(buf), "%s %4u %4u",
504 gsm48_cc_state_name(trans->cc.state),
505 trans->cc.Tcurrent,
506 trans->cc.T308_second);
507 break;
508 case GSM48_PDISC_SMS:
509 snprintf(buf, sizeof(buf), "%s %s",
510 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
511 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
512 break;
513 default:
514 buf[0] = '\0';
515 break;
516 }
517
518 return buf;
519}
520
521static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans)
522{
523 vty_out(vty, "%22s %08x %s %02u %08x %s%s",
524 trans->vsub ? vlr_subscr_name(trans->vsub) : "-",
525 trans->conn ? trans->conn->a.conn_id : 0,
526 gsm48_pdisc_name(trans->protocol),
527 trans->transaction_id,
528 trans->callref,
529 get_trans_proto_str(trans), VTY_NEWLINE);
530}
531
532DEFUN(show_msc_transaction, show_msc_transaction_cmd,
533 "show transaction", SHOW_STR "Transactions\n")
534{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100535 struct gsm_trans *trans;
536
537 vty_trans_hdr(vty);
538 llist_for_each_entry(trans, &gsmnet->trans_list, entry)
539 vty_dump_one_trans(vty, trans);
540
541 return CMD_SUCCESS;
542}
543
544static void subscr_dump_full_vty(struct vty *vty, struct vlr_subscr *vsub)
545{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100546 struct gsm_trans *trans;
547 int reqs;
548 struct llist_head *entry;
549
550 if (strlen(vsub->name))
551 vty_out(vty, " Name: '%s'%s", vsub->name, VTY_NEWLINE);
552 if (strlen(vsub->msisdn))
553 vty_out(vty, " Extension: %s%s", vsub->msisdn,
554 VTY_NEWLINE);
555 vty_out(vty, " LAC: %d/0x%x%s",
556 vsub->lac, vsub->lac, VTY_NEWLINE);
557 vty_out(vty, " IMSI: %s%s", vsub->imsi, VTY_NEWLINE);
558 if (vsub->tmsi != GSM_RESERVED_TMSI)
559 vty_out(vty, " TMSI: %08X%s", vsub->tmsi,
560 VTY_NEWLINE);
561 if (vsub->tmsi_new != GSM_RESERVED_TMSI)
562 vty_out(vty, " new TMSI: %08X%s", vsub->tmsi_new,
563 VTY_NEWLINE);
564
565#if 0
566 /* TODO: add this to vlr_subscr? */
567 if (vsub->auth_info.auth_algo != AUTH_ALGO_NONE) {
568 struct gsm_auth_info *i = &vsub->auth_info;
569 vty_out(vty, " A3A8 algorithm id: %d%s",
570 i->auth_algo, VTY_NEWLINE);
571 vty_out(vty, " A3A8 Ki: %s%s",
572 osmo_hexdump(i->a3a8_ki, i->a3a8_ki_len),
573 VTY_NEWLINE);
574 }
575#endif
576
577 if (vsub->last_tuple) {
578 struct gsm_auth_tuple *t = vsub->last_tuple;
579 vty_out(vty, " A3A8 last tuple (used %d times):%s",
580 t->use_count, VTY_NEWLINE);
581 vty_out(vty, " seq # : %d%s",
582 t->key_seq, VTY_NEWLINE);
583 vty_out(vty, " RAND : %s%s",
584 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
585 VTY_NEWLINE);
586 vty_out(vty, " SRES : %s%s",
587 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
588 VTY_NEWLINE);
589 vty_out(vty, " Kc : %s%s",
590 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
591 VTY_NEWLINE);
592 }
593
594 reqs = 0;
595 llist_for_each(entry, &vsub->cs.requests)
596 reqs += 1;
597 vty_out(vty, " Paging: %s paging for %d requests%s",
598 vsub->cs.is_paging ? "is" : "not", reqs, VTY_NEWLINE);
599 vty_out(vty, " Use count: %u%s", vsub->use_count, VTY_NEWLINE);
600
601 /* Connection */
602 if (vsub->msc_conn_ref) {
603 struct gsm_subscriber_connection *conn = vsub->msc_conn_ref;
604 vty_conn_hdr(vty);
605 vty_dump_one_conn(vty, conn);
606 }
607
608 /* Transactions */
609 vty_trans_hdr(vty);
610 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
611 if (trans->vsub != vsub)
612 continue;
613 vty_dump_one_trans(vty, trans);
614 }
615}
616
617/* Subscriber */
618DEFUN(show_subscr_cache,
619 show_subscr_cache_cmd,
620 "show subscriber cache",
621 SHOW_STR "Show information about subscribers\n"
622 "Display contents of subscriber cache\n")
623{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100624 struct vlr_subscr *vsub;
625 int count = 0;
626
627 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
628 if (++count > 100) {
629 vty_out(vty, "%% More than %d subscribers in cache,"
630 " stopping here.%s", count-1, VTY_NEWLINE);
631 break;
632 }
633 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
634 subscr_dump_full_vty(vty, vsub);
Harald Welte69c54a82018-02-09 20:41:14 +0100635 }
636
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200637 return CMD_SUCCESS;
638}
639
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100640DEFUN(sms_send_pend,
641 sms_send_pend_cmd,
642 "sms send pending",
643 "SMS related commands\n" "SMS Sending related commands\n"
644 "Send all pending SMS")
645{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100646 struct gsm_sms *sms;
647 unsigned long long sms_id = 0;
648
649 while (1) {
650 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
651 if (!sms)
652 break;
653
654 if (sms->receiver)
655 gsm411_send_sms_subscr(sms->receiver, sms);
656
657 sms_id = sms->id + 1;
658 }
659
660 return CMD_SUCCESS;
661}
662
663DEFUN(sms_delete_expired,
664 sms_delete_expired_cmd,
665 "sms delete expired",
666 "SMS related commands\n" "SMS Database related commands\n"
667 "Delete all expired SMS")
668{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100669 struct gsm_sms *sms;
670 unsigned long long sms_id = 0;
671 long long num_deleted = 0;
672
673 while (1) {
674 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
675 if (!sms)
676 break;
677
678 /* Skip SMS which are currently queued for sending. */
679 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
680 continue;
681
682 /* Expiration check is performed by the DB layer. */
683 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
684 num_deleted++;
685
686 sms_id = sms->id + 1;
687 }
688
689 if (num_deleted == 0) {
690 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
691 return CMD_WARNING;
692 }
693
694 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
695 return CMD_SUCCESS;
696}
697
698static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +0200699 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100700 char *str, uint8_t tp_pid)
701{
702 struct gsm_network *net = receiver->vlr->user_ctx;
703 struct gsm_sms *sms;
704
Harald Welte39b55482018-04-09 19:19:33 +0200705 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100706 sms->protocol_id = tp_pid;
707
708 /* store in database for the queue */
709 if (db_sms_store(sms) != 0) {
710 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
711 sms_free(sms);
712 return CMD_WARNING;
713 }
714 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
715
716 sms_free(sms);
717 sms_queue_trigger(net->sms_queue);
718 return CMD_SUCCESS;
719}
720
721static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
722 const char *type,
723 const char *id)
724{
725 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
726 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id);
727 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
728 return vlr_subscr_find_by_imsi(gsmnet->vlr, id);
729 else if (!strcmp(type, "tmsi"))
730 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id));
731
732 return NULL;
733}
734#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
735#define SUBSCR_HELP "Operations on a Subscriber\n" \
736 "Identify subscriber by MSISDN (phone number)\n" \
737 "Legacy alias for 'msisdn'\n" \
738 "Identify subscriber by IMSI\n" \
739 "Identify subscriber by TMSI\n" \
740 "Identify subscriber by database ID\n" \
741 "Identifier for the subscriber\n"
742
743DEFUN(show_subscr,
744 show_subscr_cmd,
745 "show subscriber " SUBSCR_TYPES " ID",
746 SHOW_STR SUBSCR_HELP)
747{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100748 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
749 argv[1]);
750
751 if (!vsub) {
752 vty_out(vty, "%% No subscriber found for %s %s%s",
753 argv[0], argv[1], VTY_NEWLINE);
754 return CMD_WARNING;
755 }
756
757 subscr_dump_full_vty(vty, vsub);
758
759 vlr_subscr_put(vsub);
760
761 return CMD_SUCCESS;
762}
763
764DEFUN(subscriber_create,
765 subscriber_create_cmd,
766 "subscriber create imsi ID",
767 "Operations on a Subscriber\n" \
768 "Create new subscriber\n" \
769 "Identify the subscriber by his IMSI\n" \
770 "Identifier for the subscriber\n")
771{
772 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
773 VTY_NEWLINE);
774 return CMD_WARNING;
775}
776
777DEFUN(subscriber_send_pending_sms,
778 subscriber_send_pending_sms_cmd,
779 "subscriber " SUBSCR_TYPES " ID sms pending-send",
780 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
781{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100782 struct vlr_subscr *vsub;
783 struct gsm_sms *sms;
784
785 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
786 if (!vsub) {
787 vty_out(vty, "%% No subscriber found for %s %s%s",
788 argv[0], argv[1], VTY_NEWLINE);
789 return CMD_WARNING;
790 }
791
792 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
793 if (sms)
794 gsm411_send_sms_subscr(sms->receiver, sms);
795
796 vlr_subscr_put(vsub);
797
798 return CMD_SUCCESS;
799}
800
801DEFUN(subscriber_send_sms,
802 subscriber_send_sms_cmd,
803 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
804 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
805{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100806 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +0200807 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100808 char *str;
809 int rc;
810
811 if (!vsub) {
812 vty_out(vty, "%% No subscriber found for %s %s%s",
813 argv[0], argv[1], VTY_NEWLINE);
814 rc = CMD_WARNING;
815 goto err;
816 }
817
Harald Welte39b55482018-04-09 19:19:33 +0200818 if (!strcmp(argv[2], "msisdn"))
819 sender_msisdn = argv[3];
820 else {
821 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
822 if (!sender) {
823 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
824 rc = CMD_WARNING;
825 goto err;
826 }
827 sender_msisdn = sender->msisdn;
828 vlr_subscr_put(sender);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100829 }
830
831 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +0200832 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100833 talloc_free(str);
834
835err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100836 if (vsub)
837 vlr_subscr_put(vsub);
838
839 return rc;
840}
841
842DEFUN(subscriber_silent_sms,
843 subscriber_silent_sms_cmd,
844
845 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
846 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
847{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100848 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +0200849 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100850 char *str;
851 int rc;
852
853 if (!vsub) {
854 vty_out(vty, "%% No subscriber found for %s %s%s",
855 argv[0], argv[1], VTY_NEWLINE);
856 rc = CMD_WARNING;
857 goto err;
858 }
859
Harald Welte39b55482018-04-09 19:19:33 +0200860 if (!strcmp(argv[2], "msisdn")) {
861 sender_msisdn = argv[3];
862 } else {
863 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
864 if (!sender) {
865 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
866 rc = CMD_WARNING;
867 goto err;
868 }
869 sender_msisdn = sender->msisdn;
870 vlr_subscr_put(sender);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100871 }
872
873 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +0200874 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100875 talloc_free(str);
876
877err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100878 if (vsub)
879 vlr_subscr_put(vsub);
880
881 return rc;
882}
883
884#define CHAN_TYPES "(any|tch/f|tch/any|sdcch)"
885#define CHAN_TYPE_HELP \
886 "Any channel\n" \
887 "TCH/F channel\n" \
888 "Any TCH channel\n" \
889 "SDCCH channel\n"
890
891DEFUN(subscriber_silent_call_start,
892 subscriber_silent_call_start_cmd,
893 "subscriber " SUBSCR_TYPES " ID silent-call start (any|tch/f|tch/any|sdcch)",
894 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
895 CHAN_TYPE_HELP)
896{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100897 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
898 int rc, type;
899
900 if (!vsub) {
901 vty_out(vty, "%% No subscriber found for %s %s%s",
902 argv[0], argv[1], VTY_NEWLINE);
903 return CMD_WARNING;
904 }
905
906 if (!strcmp(argv[2], "tch/f"))
907 type = RSL_CHANNEED_TCH_F;
908 else if (!strcmp(argv[2], "tch/any"))
909 type = RSL_CHANNEED_TCH_ForH;
910 else if (!strcmp(argv[2], "sdcch"))
911 type = RSL_CHANNEED_SDCCH;
912 else
913 type = RSL_CHANNEED_ANY; /* Defaults to ANY */
914
915 rc = gsm_silent_call_start(vsub, vty, type);
916 switch (rc) {
917 case -ENODEV:
918 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
919 break;
920 default:
921 if (rc)
922 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
923 else
924 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
925 break;
926 }
927
928 vlr_subscr_put(vsub);
929 return rc ? CMD_WARNING : CMD_SUCCESS;
930}
931
932DEFUN(subscriber_silent_call_stop,
933 subscriber_silent_call_stop_cmd,
934 "subscriber " SUBSCR_TYPES " ID silent-call stop",
935 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
936 CHAN_TYPE_HELP)
937{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100938 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
939 int rc;
940
941 if (!vsub) {
942 vty_out(vty, "%% No subscriber found for %s %s%s",
943 argv[0], argv[1], VTY_NEWLINE);
944 return CMD_WARNING;
945 }
946
947 rc = gsm_silent_call_stop(vsub);
948 switch (rc) {
949 case -ENODEV:
950 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
951 break;
952 case -ENOENT:
953 vty_out(vty, "%% Subscriber has no silent call active%s",
954 VTY_NEWLINE);
955 break;
956 default:
957 if (rc)
958 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
959 else
960 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
961 break;
962 }
963
964 vlr_subscr_put(vsub);
965 return rc ? CMD_WARNING : CMD_SUCCESS;
966}
967
968DEFUN(subscriber_ussd_notify,
969 subscriber_ussd_notify_cmd,
970 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
971 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
972 "Alerting Level 0\n"
973 "Alerting Level 1\n"
974 "Alerting Level 2\n"
975 "Text of USSD message to send\n")
976{
977 char *text;
978 struct gsm_subscriber_connection *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100979 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
980 int level;
981
982 if (!vsub) {
983 vty_out(vty, "%% No subscriber found for %s %s%s",
984 argv[0], argv[1], VTY_NEWLINE);
985 return CMD_WARNING;
986 }
987
988 level = atoi(argv[2]);
989 text = argv_concat(argv, argc, 3);
990 if (!text) {
991 vlr_subscr_put(vsub);
992 return CMD_WARNING;
993 }
994
995 conn = connection_for_subscr(vsub);
996 if (!conn) {
997 vty_out(vty, "%% An active connection is required for %s %s%s",
998 argv[0], argv[1], VTY_NEWLINE);
999 vlr_subscr_put(vsub);
1000 talloc_free(text);
1001 return CMD_WARNING;
1002 }
1003
1004 msc_send_ussd_notify(conn, level, text);
1005 msc_send_ussd_release_complete(conn);
1006
1007 vlr_subscr_put(vsub);
1008 talloc_free(text);
1009 return CMD_SUCCESS;
1010}
1011
1012DEFUN(subscriber_paging,
1013 subscriber_paging_cmd,
1014 "subscriber " SUBSCR_TYPES " ID paging",
1015 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1016{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001017 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1018 struct subscr_request *req;
1019
1020 if (!vsub) {
1021 vty_out(vty, "%% No subscriber found for %s %s%s",
1022 argv[0], argv[1], VTY_NEWLINE);
1023 return CMD_WARNING;
1024 }
1025
1026 req = subscr_request_conn(vsub, NULL, NULL, "manual Paging from VTY");
1027 if (req)
1028 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1029 else
1030 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1031
1032 vlr_subscr_put(vsub);
1033 return req ? CMD_SUCCESS : CMD_WARNING;
1034}
1035
1036static int loop_by_char(uint8_t ch)
1037{
1038 switch (ch) {
1039 case 'a':
1040 return GSM414_LOOP_A;
1041 case 'b':
1042 return GSM414_LOOP_B;
1043 case 'c':
1044 return GSM414_LOOP_C;
1045 case 'd':
1046 return GSM414_LOOP_D;
1047 case 'e':
1048 return GSM414_LOOP_E;
1049 case 'f':
1050 return GSM414_LOOP_F;
1051 case 'i':
1052 return GSM414_LOOP_I;
1053 }
1054 return -1;
1055}
1056
1057DEFUN(subscriber_mstest_close,
1058 subscriber_mstest_close_cmd,
1059 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1060 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1061 "Close a TCH Loop inside the MS\n"
1062 "Loop Type A\n"
1063 "Loop Type B\n"
1064 "Loop Type C\n"
1065 "Loop Type D\n"
1066 "Loop Type E\n"
1067 "Loop Type F\n"
1068 "Loop Type I\n")
1069{
1070 struct gsm_subscriber_connection *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001071 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1072 const char *loop_str;
1073 int loop_mode;
1074
1075 if (!vsub) {
1076 vty_out(vty, "%% No subscriber found for %s %s%s",
1077 argv[0], argv[1], VTY_NEWLINE);
1078 return CMD_WARNING;
1079 }
1080
1081 loop_str = argv[2];
1082 loop_mode = loop_by_char(loop_str[0]);
1083
1084 conn = connection_for_subscr(vsub);
1085 if (!conn) {
1086 vty_out(vty, "%% An active connection is required for %s %s%s",
1087 argv[0], argv[1], VTY_NEWLINE);
1088 vlr_subscr_put(vsub);
1089 return CMD_WARNING;
1090 }
1091
1092 gsm0414_tx_close_tch_loop_cmd(conn, loop_mode);
1093
1094 return CMD_SUCCESS;
1095}
1096
1097DEFUN(subscriber_mstest_open,
1098 subscriber_mstest_open_cmd,
1099 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1100 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1101 "Open a TCH Loop inside the MS\n")
1102{
1103 struct gsm_subscriber_connection *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001104 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1105
1106 if (!vsub) {
1107 vty_out(vty, "%% No subscriber found for %s %s%s",
1108 argv[0], argv[1], VTY_NEWLINE);
1109 return CMD_WARNING;
1110 }
1111
1112 conn = connection_for_subscr(vsub);
1113 if (!conn) {
1114 vty_out(vty, "%% An active connection is required for %s %s%s",
1115 argv[0], argv[1], VTY_NEWLINE);
1116 vlr_subscr_put(vsub);
1117 return CMD_WARNING;
1118 }
1119
1120 gsm0414_tx_open_loop_cmd(conn);
1121
1122 return CMD_SUCCESS;
1123}
1124
1125DEFUN(ena_subscr_expire,
1126 ena_subscr_expire_cmd,
1127 "subscriber " SUBSCR_TYPES " ID expire",
1128 SUBSCR_HELP "Expire the subscriber Now\n")
1129{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001130 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1131 argv[1]);
1132
1133 if (!vsub) {
1134 vty_out(vty, "%% No subscriber found for %s %s%s",
1135 argv[0], argv[1], VTY_NEWLINE);
1136 return CMD_WARNING;
1137 }
1138
1139 if (vlr_subscr_expire(vsub))
1140 vty_out(vty, "%% VLR released subscriber %s%s",
1141 vlr_subscr_name(vsub), VTY_NEWLINE);
1142
1143 if (vsub->use_count > 1)
1144 vty_out(vty, "%% Subscriber %s is still in use,"
1145 " should be released soon%s",
1146 vlr_subscr_name(vsub), VTY_NEWLINE);
1147
1148 vlr_subscr_put(vsub);
1149 return CMD_SUCCESS;
1150}
1151
1152static int scall_cbfn(unsigned int subsys, unsigned int signal,
1153 void *handler_data, void *signal_data)
1154{
1155 struct scall_signal_data *sigdata = signal_data;
1156 struct vty *vty = sigdata->data;
1157
1158 switch (signal) {
1159 case S_SCALL_SUCCESS:
1160 vty_out(vty, "%% silent call success%s", VTY_NEWLINE);
1161 break;
1162 case S_SCALL_EXPIRED:
1163 vty_out(vty, "%% silent call expired paging%s", VTY_NEWLINE);
1164 break;
1165 }
1166 return 0;
1167}
1168
1169DEFUN(show_stats,
1170 show_stats_cmd,
1171 "show statistics",
1172 SHOW_STR "Display network statistics\n")
1173{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001174 vty_out(vty, "Location Update : %lu attach, %lu normal, %lu periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001175 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1176 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1177 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001178 VTY_NEWLINE);
1179 vty_out(vty, "IMSI Detach Indications : %lu%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001180 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001181 VTY_NEWLINE);
1182 vty_out(vty, "Location Updating Results: %lu completed, %lu failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001183 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1184 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001185 VTY_NEWLINE);
1186 vty_out(vty, "SMS MO : %lu submitted, %lu no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001187 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1188 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001189 VTY_NEWLINE);
1190 vty_out(vty, "SMS MT : %lu delivered, %lu no memory, %lu other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001191 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1192 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1193 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001194 VTY_NEWLINE);
1195 vty_out(vty, "MO Calls : %lu setup, %lu connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001196 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1197 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001198 VTY_NEWLINE);
1199 vty_out(vty, "MT Calls : %lu setup, %lu connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001200 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1201 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001202 VTY_NEWLINE);
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001203 vty_out(vty, "MO NC SS/USSD : %lu requests, %lu established, %lu rejected%s",
1204 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current,
1205 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1206 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current
1207 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1208 VTY_NEWLINE);
1209 vty_out(vty, "MT NC SS/USSD : %lu requests, %lu established, %lu rejected%s",
1210 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current,
1211 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1212 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current
1213 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1214 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001215 return CMD_SUCCESS;
1216}
1217
1218DEFUN(show_smsqueue,
1219 show_smsqueue_cmd,
1220 "show sms-queue",
1221 SHOW_STR "Display SMSqueue statistics\n")
1222{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001223 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001224 return CMD_SUCCESS;
1225}
1226
1227DEFUN(smsqueue_trigger,
1228 smsqueue_trigger_cmd,
1229 "sms-queue trigger",
1230 "SMS Queue\n" "Trigger sending messages\n")
1231{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001232 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001233 return CMD_SUCCESS;
1234}
1235
1236DEFUN(smsqueue_max,
1237 smsqueue_max_cmd,
1238 "sms-queue max-pending <1-500>",
1239 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1240{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001241 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001242 return CMD_SUCCESS;
1243}
1244
1245DEFUN(smsqueue_clear,
1246 smsqueue_clear_cmd,
1247 "sms-queue clear",
1248 "SMS Queue\n" "Clear the queue of pending SMS\n")
1249{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001250 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001251 return CMD_SUCCESS;
1252}
1253
1254DEFUN(smsqueue_fail,
1255 smsqueue_fail_cmd,
1256 "sms-queue max-failure <1-500>",
1257 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1258{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001259 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001260 return CMD_SUCCESS;
1261}
1262
1263
1264DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1265 "mncc-int", "Configure internal MNCC handler")
1266{
1267 vty->node = MNCC_INT_NODE;
1268
1269 return CMD_SUCCESS;
1270}
1271
1272static struct cmd_node mncc_int_node = {
1273 MNCC_INT_NODE,
1274 "%s(config-mncc-int)# ",
1275 1,
1276};
1277
1278static const struct value_string tchf_codec_names[] = {
1279 { GSM48_CMODE_SPEECH_V1, "fr" },
1280 { GSM48_CMODE_SPEECH_EFR, "efr" },
1281 { GSM48_CMODE_SPEECH_AMR, "amr" },
1282 { 0, NULL }
1283};
1284
1285static const struct value_string tchh_codec_names[] = {
1286 { GSM48_CMODE_SPEECH_V1, "hr" },
1287 { GSM48_CMODE_SPEECH_AMR, "amr" },
1288 { 0, NULL }
1289};
1290
1291static int config_write_mncc_int(struct vty *vty)
1292{
1293 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1294 vty_out(vty, " default-codec tch-f %s%s",
1295 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1296 VTY_NEWLINE);
1297 vty_out(vty, " default-codec tch-h %s%s",
1298 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1299 VTY_NEWLINE);
1300
1301 return CMD_SUCCESS;
1302}
1303
1304DEFUN(mnccint_def_codec_f,
1305 mnccint_def_codec_f_cmd,
1306 "default-codec tch-f (fr|efr|amr)",
1307 "Set default codec\n" "Codec for TCH/F\n"
1308 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1309{
1310 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1311
1312 return CMD_SUCCESS;
1313}
1314
1315DEFUN(mnccint_def_codec_h,
1316 mnccint_def_codec_h_cmd,
1317 "default-codec tch-h (hr|amr)",
1318 "Set default codec\n" "Codec for TCH/H\n"
1319 "Half-Rate\n" "Adaptive Multi-Rate\n")
1320{
1321 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1322
1323 return CMD_SUCCESS;
1324}
1325
1326
1327DEFUN(logging_fltr_imsi,
1328 logging_fltr_imsi_cmd,
1329 "logging filter imsi IMSI",
1330 LOGGING_STR FILTER_STR
1331 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1332{
1333 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001334 struct log_target *tgt = osmo_log_vty2tgt(vty);
1335 const char *imsi = argv[0];
1336
1337 if (!tgt)
1338 return CMD_WARNING;
1339
1340 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi);
1341
1342 if (!vlr_subscr) {
1343 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1344 argv[0], VTY_NEWLINE);
1345 return CMD_WARNING;
1346 }
1347
1348 log_set_filter_vlr_subscr(tgt, vlr_subscr);
1349 return CMD_SUCCESS;
1350}
1351
1352static struct cmd_node hlr_node = {
1353 HLR_NODE,
1354 "%s(config-hlr)# ",
1355 1,
1356};
1357
1358DEFUN(cfg_hlr, cfg_hlr_cmd,
1359 "hlr", "Configure connection to the HLR")
1360{
1361 vty->node = HLR_NODE;
1362 return CMD_SUCCESS;
1363}
1364
1365DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1366 "Remote GSUP address of the HLR\n"
1367 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1368{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001369 talloc_free((void*)gsmnet->gsup_server_addr_str);
1370 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1371 return CMD_SUCCESS;
1372}
1373
1374DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1375 "Remote GSUP port of the HLR\n"
1376 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1377{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001378 gsmnet->gsup_server_port = atoi(argv[0]);
1379 return CMD_SUCCESS;
1380}
1381
1382static int config_write_hlr(struct vty *vty)
1383{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001384 vty_out(vty, "hlr%s", VTY_NEWLINE);
1385 vty_out(vty, " remote-ip %s%s",
1386 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1387 vty_out(vty, " remote-port %u%s",
1388 gsmnet->gsup_server_port, VTY_NEWLINE);
1389 return CMD_SUCCESS;
1390}
1391
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001392void msc_vty_init(struct gsm_network *msc_network)
1393{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001394 OSMO_ASSERT(gsmnet == NULL);
1395 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001396
1397 osmo_stats_vty_add_cmds();
1398
1399 install_element(CONFIG_NODE, &cfg_net_cmd);
1400 install_node(&net_node, config_write_net);
1401 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1402 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1403 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1404 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1405 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
1406 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1407 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1408 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1409 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1410 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1411 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1412 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1413 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001414
1415 install_element(CONFIG_NODE, &cfg_msc_cmd);
1416 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001417 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
1418 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001419 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
1420 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001421 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
1422 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01001423 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01001424 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001425
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02001426 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001427#ifdef BUILD_IU
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +01001428 ranap_iu_vty_init(MSC_NODE, &msc_network->iu.rab_assign_addr_enc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001429#endif
Stefan Sperling617ac802018-02-22 17:58:20 +01001430 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001431
1432 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
1433
1434 install_element_ve(&show_subscr_cmd);
1435 install_element_ve(&show_subscr_cache_cmd);
1436 install_element_ve(&show_msc_conn_cmd);
1437 install_element_ve(&show_msc_transaction_cmd);
1438
1439 install_element_ve(&sms_send_pend_cmd);
1440 install_element_ve(&sms_delete_expired_cmd);
1441
1442 install_element_ve(&subscriber_create_cmd);
1443 install_element_ve(&subscriber_send_sms_cmd);
1444 install_element_ve(&subscriber_silent_sms_cmd);
1445 install_element_ve(&subscriber_silent_call_start_cmd);
1446 install_element_ve(&subscriber_silent_call_stop_cmd);
1447 install_element_ve(&subscriber_ussd_notify_cmd);
1448 install_element_ve(&subscriber_mstest_close_cmd);
1449 install_element_ve(&subscriber_mstest_open_cmd);
1450 install_element_ve(&subscriber_paging_cmd);
1451 install_element_ve(&show_stats_cmd);
1452 install_element_ve(&show_smsqueue_cmd);
1453 install_element_ve(&logging_fltr_imsi_cmd);
1454
1455 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
1456 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
1457 install_element(ENABLE_NODE, &smsqueue_max_cmd);
1458 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
1459 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
1460 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
1461
1462 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
1463 install_node(&mncc_int_node, config_write_mncc_int);
1464 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
1465 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
1466
1467 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
1468
1469 install_element(CONFIG_NODE, &cfg_hlr_cmd);
1470 install_node(&hlr_node, config_write_hlr);
1471 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
1472 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001473}