blob: 4674e2e68653c4371297321c0ae820eb07aad15e [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 Hofmeyr4ac80092019-03-04 02:46:37 +010026#include "config.h"
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020027
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020028#include <inttypes.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010029#include <limits.h>
30
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010031#include <osmocom/core/use_count.h>
32
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010033#include <osmocom/gsm/protocol/gsm_08_58.h>
34#include <osmocom/gsm/protocol/gsm_04_14.h>
Philipp Maier8fa2dbe2019-03-19 18:51:37 +010035#include <osmocom/gsm/protocol/gsm_08_08.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020036
Maxc51609a2018-11-09 17:13:00 +010037#include <osmocom/sigtran/sccp_helpers.h>
38
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020039#include <osmocom/vty/command.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010040#include <osmocom/vty/logging.h>
Stefan Sperling617ac802018-02-22 17:58:20 +010041#include <osmocom/vty/misc.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010042#include <osmocom/vty/stats.h>
43
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020044#ifdef BUILD_IU
45#include <osmocom/ranap/iu_client.h>
46#endif
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020047
Neels Hofmeyr90843962017-09-04 15:04:35 +020048#include <osmocom/msc/vty.h>
49#include <osmocom/msc/gsm_data.h>
50#include <osmocom/msc/gsm_subscriber.h>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010051#include <osmocom/msc/msub.h>
52#include <osmocom/msc/msc_a.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020053#include <osmocom/msc/vlr.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010054#include <osmocom/msc/transaction.h>
55#include <osmocom/msc/db.h>
56#include <osmocom/msc/sms_queue.h>
57#include <osmocom/msc/silent_call.h>
58#include <osmocom/msc/gsm_04_80.h>
59#include <osmocom/msc/gsm_04_14.h>
60#include <osmocom/msc/signal.h>
61#include <osmocom/msc/mncc_int.h>
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +020062#include <osmocom/msc/osmux.h>
Vadim Yanitskiy1b891302018-08-04 01:33:08 +070063#include <osmocom/msc/rrlp.h>
Harald Welte0df904d2018-12-03 11:00:04 +010064#include <osmocom/msc/vlr_sgs.h>
65#include <osmocom/msc/sgs_vty.h>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010066#include <osmocom/msc/sccp_ran.h>
67#include <osmocom/msc/ran_peer.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010068
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010069static struct gsm_network *gsmnet = NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010070
71struct cmd_node net_node = {
72 GSMNET_NODE,
73 "%s(config-net)# ",
74 1,
75};
76
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +010077#define VSUB_USE_VTY "VTY"
78
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010079#define NETWORK_STR "Configure the GSM network\n"
80#define CODE_CMD_STR "Code commands\n"
81#define NAME_CMD_STR "Name Commands\n"
82#define NAME_STR "Name to use\n"
83
84DEFUN(cfg_net,
85 cfg_net_cmd,
86 "network", NETWORK_STR)
87{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010088 vty->index = gsmnet;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010089 vty->node = GSMNET_NODE;
90
91 return CMD_SUCCESS;
92}
93
94DEFUN(cfg_net_ncc,
95 cfg_net_ncc_cmd,
96 "network country code <1-999>",
97 "Set the GSM network country code\n"
98 "Country commands\n"
99 CODE_CMD_STR
100 "Network Country Code to use\n")
101{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100102 gsmnet->plmn.mcc = atoi(argv[0]);
103
104 return CMD_SUCCESS;
105}
106
107DEFUN(cfg_net_mnc,
108 cfg_net_mnc_cmd,
109 "mobile network code <0-999>",
110 "Set the GSM mobile network code\n"
111 "Network Commands\n"
112 CODE_CMD_STR
113 "Mobile Network Code to use\n")
114{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100115 uint16_t mnc;
116 bool mnc_3_digits;
117
118 if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
119 vty_out(vty, "%% Error decoding MNC: %s%s", argv[0], VTY_NEWLINE);
120 return CMD_WARNING;
121 }
122
123 gsmnet->plmn.mnc = mnc;
124 gsmnet->plmn.mnc_3_digits = mnc_3_digits;
125
126 return CMD_SUCCESS;
127}
128
129DEFUN(cfg_net_name_short,
130 cfg_net_name_short_cmd,
131 "short name NAME",
132 "Set the short GSM network name\n" NAME_CMD_STR NAME_STR)
133{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100134 osmo_talloc_replace_string(gsmnet, &gsmnet->name_short, argv[0]);
135 return CMD_SUCCESS;
136}
137
138DEFUN(cfg_net_name_long,
139 cfg_net_name_long_cmd,
140 "long name NAME",
141 "Set the long GSM network name\n" NAME_CMD_STR NAME_STR)
142{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100143 osmo_talloc_replace_string(gsmnet, &gsmnet->name_long, argv[0]);
144 return CMD_SUCCESS;
145}
146
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200147#define ENCRYPTION_STR "Encryption options\n"
148
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100149DEFUN(cfg_net_encryption,
150 cfg_net_encryption_cmd,
151 "encryption a5 <0-3> [<0-3>] [<0-3>] [<0-3>]",
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200152 ENCRYPTION_STR
153 "GSM A5 Air Interface Encryption.\n"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100154 "A5/n Algorithm Number\n"
155 "A5/n Algorithm Number\n"
156 "A5/n Algorithm Number\n"
157 "A5/n Algorithm Number\n")
158{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100159 unsigned int i;
160
161 gsmnet->a5_encryption_mask = 0;
162 for (i = 0; i < argc; i++)
163 gsmnet->a5_encryption_mask |= (1 << atoi(argv[i]));
164
165 return CMD_SUCCESS;
166}
167
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200168/* So far just a boolean switch, a future patch might add individual config for UEA1 and UEA2, see OS#4143 */
169DEFUN(cfg_net_encryption_uea,
170 cfg_net_encryption_uea_cmd,
171 "encryption uea <0-2> [<0-2>] [<0-2>]",
172 ENCRYPTION_STR
173 "UTRAN (3G) encryption algorithms to allow: 0 = UEA0 (no encryption), 1 = UEA1, 2 = UEA2."
174 " NOTE: the current implementation does not allow free choice of combining encryption algorithms yet."
175 " The only valid settings are either 'encryption uea 0' or 'encryption uea 1 2'.\n"
176 "UEAn Algorithm Number\n"
177 "UEAn Algorithm Number\n"
178 "UEAn Algorithm Number\n"
179 )
180{
181 unsigned int i;
182 uint8_t mask = 0;
183
184 for (i = 0; i < argc; i++)
185 mask |= (1 << atoi(argv[i]));
186
187 if (mask == (1 << 0)) {
188 /* UEA0. Disable encryption. */
189 gsmnet->uea_encryption = false;
190 } else if (mask == ((1 << 1) | (1 << 2))) {
191 /* UEA1 and UEA2. Enable encryption. */
192 gsmnet->uea_encryption = true;
193 } else {
194 vty_out(vty,
195 "%% Error: the current implementation does not allow free choice of combining%s"
196 "%% encryption algorithms yet. The only valid settings are either%s"
197 "%% encryption uea 0%s"
198 "%% or%s"
199 "%% encryption uea 1 2%s",
200 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
201 return CMD_WARNING;
202 }
203
204 return CMD_SUCCESS;
205}
206
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100207DEFUN(cfg_net_authentication,
208 cfg_net_authentication_cmd,
209 "authentication (optional|required)",
210 "Whether to enforce MS authentication in 2G\n"
211 "Allow MS to attach via 2G BSC without authentication\n"
212 "Always do authentication\n")
213{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100214 gsmnet->authentication_required = (argv[0][0] == 'r') ? true : false;
215
216 return CMD_SUCCESS;
217}
218
219DEFUN(cfg_net_rrlp_mode, cfg_net_rrlp_mode_cmd,
220 "rrlp mode (none|ms-based|ms-preferred|ass-preferred)",
221 "Radio Resource Location Protocol\n"
222 "Set the Radio Resource Location Protocol Mode\n"
223 "Don't send RRLP request\n"
224 "Request MS-based location\n"
225 "Request any location, prefer MS-based\n"
226 "Request any location, prefer MS-assisted\n")
227{
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700228 gsmnet->rrlp.mode = msc_rrlp_mode_parse(argv[0]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100229
230 return CMD_SUCCESS;
231}
232
233DEFUN(cfg_net_mm_info, cfg_net_mm_info_cmd,
234 "mm info (0|1)",
235 "Mobility Management\n"
236 "Send MM INFO after LOC UPD ACCEPT\n"
237 "Disable\n" "Enable\n")
238{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100239 gsmnet->send_mm_info = atoi(argv[0]);
240
241 return CMD_SUCCESS;
242}
243
244DEFUN(cfg_net_timezone,
245 cfg_net_timezone_cmd,
246 "timezone <-19-19> (0|15|30|45)",
247 "Set the Timezone Offset of the network\n"
248 "Timezone offset (hours)\n"
249 "Timezone offset (00 minutes)\n"
250 "Timezone offset (15 minutes)\n"
251 "Timezone offset (30 minutes)\n"
252 "Timezone offset (45 minutes)\n"
253 )
254{
255 struct gsm_network *net = vty->index;
256 int tzhr = atoi(argv[0]);
257 int tzmn = atoi(argv[1]);
258
259 net->tz.hr = tzhr;
260 net->tz.mn = tzmn;
261 net->tz.dst = 0;
262 net->tz.override = 1;
263
264 return CMD_SUCCESS;
265}
266
267DEFUN(cfg_net_timezone_dst,
268 cfg_net_timezone_dst_cmd,
269 "timezone <-19-19> (0|15|30|45) <0-2>",
270 "Set the Timezone Offset of the network\n"
271 "Timezone offset (hours)\n"
272 "Timezone offset (00 minutes)\n"
273 "Timezone offset (15 minutes)\n"
274 "Timezone offset (30 minutes)\n"
275 "Timezone offset (45 minutes)\n"
276 "DST offset (hours)\n"
277 )
278{
279 struct gsm_network *net = vty->index;
280 int tzhr = atoi(argv[0]);
281 int tzmn = atoi(argv[1]);
282 int tzdst = atoi(argv[2]);
283
284 net->tz.hr = tzhr;
285 net->tz.mn = tzmn;
286 net->tz.dst = tzdst;
287 net->tz.override = 1;
288
289 return CMD_SUCCESS;
290}
291
292DEFUN(cfg_net_no_timezone,
293 cfg_net_no_timezone_cmd,
294 "no timezone",
295 NO_STR
296 "Disable network timezone override, use system tz\n")
297{
298 struct gsm_network *net = vty->index;
299
300 net->tz.override = 0;
301
302 return CMD_SUCCESS;
303}
304
305DEFUN(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
306 "periodic location update <6-1530>",
307 "Periodic Location Updating Interval\n"
308 "Periodic Location Updating Interval\n"
309 "Periodic Location Updating Interval\n"
310 "Periodic Location Updating Interval in Minutes\n")
311{
312 struct gsm_network *net = vty->index;
313
314 net->t3212 = atoi(argv[0]) / 6;
315
316 return CMD_SUCCESS;
317}
318
319DEFUN(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
320 "no periodic location update",
321 NO_STR
322 "Periodic Location Updating Interval\n"
323 "Periodic Location Updating Interval\n"
324 "Periodic Location Updating Interval\n")
325{
326 struct gsm_network *net = vty->index;
327
328 net->t3212 = 0;
329
330 return CMD_SUCCESS;
331}
332
333static int config_write_net(struct vty *vty)
334{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100335 int i;
336
337 vty_out(vty, "network%s", VTY_NEWLINE);
338 vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
339 vty_out(vty, " mobile network code %s%s",
340 osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
341 vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
342 vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
343 vty_out(vty, " encryption a5");
344 for (i = 0; i < 8; i++) {
345 if (gsmnet->a5_encryption_mask & (1 << i))
346 vty_out(vty, " %u", i);
347 }
348 vty_out(vty, "%s", VTY_NEWLINE);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200349
350 if (!gsmnet->uea_encryption)
351 vty_out(vty, " encryption uea 0%s", VTY_NEWLINE);
352 else
353 vty_out(vty, " encryption uea 1 2%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100354 vty_out(vty, " authentication %s%s",
355 gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE);
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700356 vty_out(vty, " rrlp mode %s%s", msc_rrlp_mode_name(gsmnet->rrlp.mode),
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100357 VTY_NEWLINE);
358 vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
359 if (gsmnet->tz.override != 0) {
360 if (gsmnet->tz.dst)
361 vty_out(vty, " timezone %d %d %d%s",
362 gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
363 VTY_NEWLINE);
364 else
365 vty_out(vty, " timezone %d %d%s",
366 gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
367 }
368 if (gsmnet->t3212 == 0)
369 vty_out(vty, " no periodic location update%s", VTY_NEWLINE);
370 else
371 vty_out(vty, " periodic location update %u%s",
372 gsmnet->t3212 * 6, VTY_NEWLINE);
373
374 if (gsmnet->emergency.route_to_msisdn) {
375 vty_out(vty, " emergency-call route-to-msisdn %s%s",
376 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
377 }
378
379 return CMD_SUCCESS;
380}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200381
382static struct cmd_node msc_node = {
383 MSC_NODE,
384 "%s(config-msc)# ",
385 1,
386};
387
388DEFUN(cfg_msc, cfg_msc_cmd,
389 "msc", "Configure MSC options")
390{
391 vty->node = MSC_NODE;
392 return CMD_SUCCESS;
393}
394
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100395#define MNCC_STR "Configure Mobile Network Call Control\n"
396#define MNCC_GUARD_TIMEOUT_STR "Set global guard timer for mncc interface activity\n"
397#define MNCC_GUARD_TIMEOUT_VALUE_STR "guard timer value (sec.)\n"
398
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100399DEFUN(cfg_msc_mncc_internal,
400 cfg_msc_mncc_internal_cmd,
401 "mncc internal",
402 MNCC_STR "Use internal MNCC handler (default; changes need a program restart)\n")
403{
404 gsm_network_set_mncc_sock_path(gsmnet, NULL);
405 return CMD_SUCCESS;
406}
407
408DEFUN(cfg_msc_mncc_external,
409 cfg_msc_mncc_external_cmd,
410 "mncc external MNCC_SOCKET_PATH",
411 MNCC_STR "Use external MNCC handler (changes need a program restart)\n"
412 "File system path to create the MNCC unix domain socket at\n")
413{
414 gsm_network_set_mncc_sock_path(gsmnet, argv[0]);
415 return CMD_SUCCESS;
416}
417
Philipp Maier9ca7b312018-10-10 17:00:49 +0200418DEFUN(cfg_msc_mncc_guard_timeout,
419 cfg_msc_mncc_guard_timeout_cmd,
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100420 "mncc guard-timeout <0-255>",
421 MNCC_STR
422 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR)
Philipp Maier9ca7b312018-10-10 17:00:49 +0200423{
424 gsmnet->mncc_guard_timeout = atoi(argv[0]);
425 return CMD_SUCCESS;
426}
427
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100428ALIAS_DEPRECATED(cfg_msc_mncc_guard_timeout,
429 cfg_msc_deprecated_mncc_guard_timeout_cmd,
430 "mncc-guard-timeout <0-255>",
431 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR);
432
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700433#define NCSS_STR "Configure call independent Supplementary Services\n"
434
435DEFUN(cfg_msc_ncss_guard_timeout,
436 cfg_msc_ncss_guard_timeout_cmd,
437 "ncss guard-timeout <0-255>",
438 NCSS_STR "Set guard timer for session activity\n"
439 "guard timer value (sec.), or 0 to disable\n")
440{
441 gsmnet->ncss_guard_timeout = atoi(argv[0]);
442 return CMD_SUCCESS;
443}
444
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200445DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
446 "assign-tmsi",
447 "Assign TMSI during Location Updating.\n")
448{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200449 gsmnet->vlr->cfg.assign_tmsi = true;
450 return CMD_SUCCESS;
451}
452
453DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
454 "no assign-tmsi",
455 NO_STR "Assign TMSI during Location Updating.\n")
456{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200457 gsmnet->vlr->cfg.assign_tmsi = false;
458 return CMD_SUCCESS;
459}
460
Philipp Maierfbf66102017-04-09 12:32:51 +0200461DEFUN(cfg_msc_cs7_instance_a,
462 cfg_msc_cs7_instance_a_cmd,
463 "cs7-instance-a <0-15>",
464 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
465{
Philipp Maierfbf66102017-04-09 12:32:51 +0200466 gsmnet->a.cs7_instance = atoi(argv[0]);
467 return CMD_SUCCESS;
468}
469
470DEFUN(cfg_msc_cs7_instance_iu,
471 cfg_msc_cs7_instance_iu_cmd,
472 "cs7-instance-iu <0-15>",
473 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
474{
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100475#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200476 gsmnet->iu.cs7_instance = atoi(argv[0]);
477 return CMD_SUCCESS;
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100478#else
479 vty_out(vty, "WARNING: 'cs7-instance-iu' without effect: built without Iu support%s",
480 VTY_NEWLINE);
481 return CMD_WARNING;
482#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200483}
484
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100485DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
486 "auth-tuple-max-reuse-count <-1-2147483647>",
487 "Configure authentication tuple re-use\n"
488 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
489{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100490 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
491 return CMD_SUCCESS;
492}
493
494DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
495 "auth-tuple-reuse-on-error (0|1)",
496 "Configure authentication tuple re-use when HLR is not responsive\n"
Oliver Smithd6e24fd2019-01-09 10:46:43 +0100497 "Never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
498 "If the HLR does not deliver new tuples, do re-use already available old ones.\n")
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100499{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100500 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
501 return CMD_SUCCESS;
502}
503
Oliver Smith0fec28a2018-12-14 10:52:52 +0100504DEFUN(cfg_msc_check_imei_rqd, cfg_msc_check_imei_rqd_cmd,
Oliver Smith03ded912019-05-02 10:40:50 +0200505 "check-imei-rqd (0|1|early)",
Oliver Smith0fec28a2018-12-14 10:52:52 +0100506 "Send each IMEI to the EIR to ask if it is permitted or not. The EIR is implemented as part of OsmoHLR, "
507 "and can optionally save the IMEI in the HLR.\n"
508 "Do not send IMEIs to the EIR\n"
Oliver Smith03ded912019-05-02 10:40:50 +0200509 "Send each IMEI to the EIR\n"
510 "Send each IMEI to the EIR, and do it at the start of the location update. This allows the EIR to receive the"
511 " IMEI, even if the MS would get rejected when the MSC sends the location update request to the HLR.\n")
Oliver Smith0fec28a2018-12-14 10:52:52 +0100512{
Oliver Smith03ded912019-05-02 10:40:50 +0200513 if (strcmp(argv[0], "0") == 0) {
514 gsmnet->vlr->cfg.check_imei_rqd = false;
515 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
516 } else if (strcmp(argv[0], "1") == 0) {
517 gsmnet->vlr->cfg.check_imei_rqd = true;
518 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
519 } else if (strcmp(argv[0], "early") == 0) {
520 gsmnet->vlr->cfg.check_imei_rqd = true;
521 gsmnet->vlr->cfg.retrieve_imeisv_early = true;
522 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100523 return CMD_SUCCESS;
524}
525
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100526DEFUN(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
527 "paging response-timer (default|<1-65535>)",
528 "Configure Paging\n"
529 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
530 " BSS or RNC\n"
531 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
532 "Set paging timeout in seconds\n")
533{
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100534 if (!strcmp(argv[1], "default"))
535 gsmnet->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
536 else
537 gsmnet->paging_response_timer = atoi(argv[0]);
538 return CMD_SUCCESS;
539}
540
Harald Welte69c54a82018-02-09 20:41:14 +0100541DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
542 "emergency-call route-to-msisdn MSISDN",
543 "Configure Emergency Call Behaviour\n"
544 "MSISDN to which Emergency Calls are Dispatched\n"
545 "MSISDN (E.164 Phone Number)\n")
546{
Harald Welte69c54a82018-02-09 20:41:14 +0100547 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
548
549 return CMD_SUCCESS;
550}
551
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700552/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
553DEFUN(cfg_msc_sms_over_gsup, cfg_msc_sms_over_gsup_cmd,
554 "sms-over-gsup",
555 "Enable routing of SMS messages over GSUP\n")
556{
557 gsmnet->sms_over_gsup = true;
558 return CMD_SUCCESS;
559}
560
561/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
562DEFUN(cfg_msc_no_sms_over_gsup, cfg_msc_no_sms_over_gsup_cmd,
563 "no sms-over-gsup",
564 NO_STR "Disable routing of SMS messages over GSUP\n")
565{
566 gsmnet->sms_over_gsup = false;
567 return CMD_SUCCESS;
568}
569
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100570/* FIXME: This should rather be in the form of
571 * handover-number range 001234xxx
572 * and
573 * handover-number range 001234xxx FIRST LAST
574 */
575DEFUN(cfg_msc_handover_number_range, cfg_msc_handover_number_range_cmd,
576 "handover-number range MSISDN_FIRST MSISDN_LAST",
577 "Configure a range of MSISDN to be assigned to incoming inter-MSC Handovers for call forwarding.\n"
578 "Configure a handover number range\n"
579 "First Handover Number MSISDN\n"
580 "Last Handover Number MSISDN\n")
581{
582 char *endp;
583 uint64_t range_start;
584 uint64_t range_end;
585
586 /* FIXME leading zeros?? */
587
588 errno = 0;
589 range_start = strtoull(argv[0], &endp, 10);
590 if (errno || *endp != '\0') {
591 vty_out(vty, "%% Error parsing handover-number range start: %s%s",
592 argv[0], VTY_NEWLINE);
593 return CMD_WARNING;
594 }
595
596 errno = 0;
597 range_end = strtoull(argv[1], &endp, 10);
598 if (errno || *endp != '\0') {
599 vty_out(vty, "%% Error parsing handover-number range end: %s%s",
600 argv[1], VTY_NEWLINE);
601 return CMD_WARNING;
602 }
603
604 if (range_start > range_end) {
605 vty_out(vty, "%% Error: handover-number range end must be > than the range start, but"
606 " %"PRIu64" > %"PRIu64"%s", range_start, range_end, VTY_NEWLINE);
607 return CMD_WARNING;
608 }
609
610 gsmnet->handover_number.range_start = range_start;
611 gsmnet->handover_number.range_end = range_end;
612 return CMD_SUCCESS;
613}
614
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200615#define OSMUX_STR "RTP multiplexing\n"
616DEFUN(cfg_msc_osmux,
617 cfg_msc_osmux_cmd,
618 "osmux (on|off|only)",
619 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
620{
621 if (strcmp(argv[0], "off") == 0)
622 gsmnet->use_osmux = OSMUX_USAGE_OFF;
623 else if (strcmp(argv[0], "on") == 0)
624 gsmnet->use_osmux = OSMUX_USAGE_ON;
625 else if (strcmp(argv[0], "only") == 0)
626 gsmnet->use_osmux = OSMUX_USAGE_ONLY;
627
628 return CMD_SUCCESS;
629}
630
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200631static int config_write_msc(struct vty *vty)
632{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200633 vty_out(vty, "msc%s", VTY_NEWLINE);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100634 if (gsmnet->mncc_sock_path)
635 vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE);
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100636 vty_out(vty, " mncc guard-timeout %i%s",
Philipp Maier9ca7b312018-10-10 17:00:49 +0200637 gsmnet->mncc_guard_timeout, VTY_NEWLINE);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700638 vty_out(vty, " ncss guard-timeout %i%s",
639 gsmnet->ncss_guard_timeout, VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200640 vty_out(vty, " %sassign-tmsi%s",
641 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
642
Philipp Maierfbf66102017-04-09 12:32:51 +0200643 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
644 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100645#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200646 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
647 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100648#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200649
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100650 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
651 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
652 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
653 VTY_NEWLINE);
654 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
655 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
656 VTY_NEWLINE);
657
Oliver Smith03ded912019-05-02 10:40:50 +0200658 if (gsmnet->vlr->cfg.check_imei_rqd) {
659 if (gsmnet->vlr->cfg.retrieve_imeisv_early)
660 vty_out(vty, " check-imei-rqd early%s", VTY_NEWLINE);
661 else
662 vty_out(vty, " check-imei-rqd 1%s", VTY_NEWLINE);
663 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100664
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100665 if (gsmnet->paging_response_timer != MSC_PAGING_RESPONSE_TIMER_DEFAULT)
666 vty_out(vty, " paging response-timer %u%s", gsmnet->paging_response_timer, VTY_NEWLINE);
667
Harald Welte69c54a82018-02-09 20:41:14 +0100668 if (gsmnet->emergency.route_to_msisdn) {
669 vty_out(vty, " emergency-call route-to-msisdn %s%s",
670 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
671 }
672
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700673 if (gsmnet->sms_over_gsup)
674 vty_out(vty, " sms-over-gsup%s", VTY_NEWLINE);
675
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100676 if (gsmnet->handover_number.range_start || gsmnet->handover_number.range_end)
677 vty_out(vty, " handover-number range %"PRIu64" %"PRIu64"%s",
678 gsmnet->handover_number.range_start, gsmnet->handover_number.range_end,
679 VTY_NEWLINE);
680
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200681 if (gsmnet->use_osmux != OSMUX_USAGE_OFF) {
682 vty_out(vty, " osmux %s%s", gsmnet->use_osmux == OSMUX_USAGE_ON ? "on" : "only",
683 VTY_NEWLINE);
684 }
685
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200686 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200687#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200688 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200689#endif
690
Neels Hofmeyr880b9502019-05-09 02:01:55 +0200691 neighbor_ident_vty_write(vty);
692
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200693 return CMD_SUCCESS;
694}
695
Maxc51609a2018-11-09 17:13:00 +0100696DEFUN(show_bsc, show_bsc_cmd,
697 "show bsc", SHOW_STR "BSC\n")
698{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100699 struct ran_peer *rp;
700 llist_for_each_entry(rp, &gsmnet->a.sri->ran_peers, entry) {
701 vty_out(vty, "BSC %s %s%s",
702 osmo_sccp_inst_addr_name(gsmnet->a.sri->sccp, &rp->peer_addr),
703 osmo_fsm_inst_state_name(rp->fi),
704 VTY_NEWLINE);
Maxc51609a2018-11-09 17:13:00 +0100705 }
706
707 return CMD_SUCCESS;
708}
709
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100710static const char *get_trans_proto_str(const struct gsm_trans *trans)
711{
712 static char buf[256];
713
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100714 switch (trans->type) {
715 case TRANS_CC:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100716 snprintf(buf, sizeof(buf), "%s %4u %4u",
717 gsm48_cc_state_name(trans->cc.state),
718 trans->cc.Tcurrent,
719 trans->cc.T308_second);
720 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100721 case TRANS_SMS:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700722 snprintf(buf, sizeof(buf), "CP:%s RP:%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100723 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
724 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
725 break;
726 default:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700727 return NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100728 }
729
730 return buf;
731}
732
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700733/* Prefix a given format string with a given amount of spaces */
734#define MSC_VTY_DUMP(vty, offset, fmt, args...) \
735 vty_out(vty, "%*s" fmt, offset, "", ##args)
736
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200737/* Print value of a named flag, prefixed with a given amount of spaces */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700738#define MSC_VTY_DUMP_FLAG(vty, offset, name, flag) \
739 MSC_VTY_DUMP(vty, offset + 2, "%s: %*s%s%s", \
740 name, 30 - (int)strlen(name), "", \
741 flag ? "true" : "false", \
742 VTY_NEWLINE)
743
744enum msc_vty_dump_flags {
745 MSC_VTY_DUMP_F_SUBSCR = (1 << 0),
746 MSC_VTY_DUMP_F_CONNECTION = (1 << 1),
747 MSC_VTY_DUMP_F_TRANSACTION = (1 << 2),
748};
749
750static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans,
751 int offset, uint8_t dump_flags)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100752{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700753 const char *proto_str;
754
755 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
756 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
757 vlr_subscr_name(msc_a_vsub(trans->msc_a)),
758 VTY_NEWLINE);
759 }
760
761 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200762 /* (If msc_a exists, there *must* be a non-null msc_a->c.msub) */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700763 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
764 trans->msc_a ? msub_ran_conn_name(trans->msc_a->c.msub)
765 : "(not established)",
766 VTY_NEWLINE);
767 }
768
769 MSC_VTY_DUMP(vty, offset, "Unique (global) identifier: 0x%08x%s",
770 trans->callref, VTY_NEWLINE);
771 MSC_VTY_DUMP(vty, offset, "GSM 04.07 identifier (%s): %u%s",
772 (trans->transaction_id & 0x08) ? "MO" : "MT",
773 trans->transaction_id,
774 VTY_NEWLINE);
775
776 MSC_VTY_DUMP(vty, offset, "Type: %s%s",
777 trans_type_name(trans->type),
778 VTY_NEWLINE);
779
780 if ((proto_str = get_trans_proto_str(trans))) {
781 MSC_VTY_DUMP(vty, offset, "Protocol specific: %s%s",
782 proto_str, VTY_NEWLINE);
783 }
784}
785
786static void vty_dump_one_conn(struct vty *vty, const struct msub *msub,
787 int offset, uint8_t dump_flags)
788{
789 struct vlr_subscr *vsub = msub_vsub(msub);
790 struct msc_a *msc_a = msub_msc_a(msub);
791 char buf[128];
792
793 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
794 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
795 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
796 vlr_subscr_name(vsub),
797 VTY_NEWLINE);
798 }
799
800 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
801 msub_ran_conn_name(msub),
802 VTY_NEWLINE);
803 MSC_VTY_DUMP(vty, offset, "RAN connection state: %s%s",
804 osmo_fsm_inst_state_name(msc_a->c.fi),
805 VTY_NEWLINE);
806
807 if (vsub) {
808 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
809 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
810 VTY_NEWLINE);
811 }
812
813 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
814 osmo_use_count_total(&msc_a->use_count),
815 VTY_NEWLINE);
816 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
817 osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count),
818 VTY_NEWLINE);
819
820 /* Transactions of this connection */
821 if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
822 struct gsm_trans *trans;
823 unsigned int i = 0;
824
825 /* Both subscriber and connection info is already printed */
826 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_CONNECTION;
827 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
828
829 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
830 if (trans->msc_a != msc_a)
831 continue;
832 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
833 i++, VTY_NEWLINE);
834 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
835 }
836 }
837}
838
839static void vty_dump_one_subscr(struct vty *vty, struct vlr_subscr *vsub,
840 int offset, uint8_t dump_flags)
841{
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700842 struct gsm_network *net;
843 struct timespec now;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700844 char buf[128];
845
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700846 if (vsub->name[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700847 MSC_VTY_DUMP(vty, offset, "Name: '%s'%s",
848 vsub->name, VTY_NEWLINE);
849 }
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700850 if (vsub->msisdn[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700851 MSC_VTY_DUMP(vty, offset, "MSISDN: %s%s",
852 vsub->msisdn, VTY_NEWLINE);
853 }
854
855 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
856 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
857 VTY_NEWLINE);
858 MSC_VTY_DUMP(vty, offset, "RAN type: %s%s",
859 osmo_rat_type_name(vsub->cs.attached_via_ran),
860 VTY_NEWLINE);
861
862 MSC_VTY_DUMP(vty, offset, "IMSI: %s%s",
863 vsub->imsi, VTY_NEWLINE);
864 if (vsub->tmsi != GSM_RESERVED_TMSI) {
865 MSC_VTY_DUMP(vty, offset, "TMSI: %08X%s",
866 vsub->tmsi, VTY_NEWLINE);
867 }
868 if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
869 MSC_VTY_DUMP(vty, offset, "New TMSI: %08X%s",
870 vsub->tmsi_new, VTY_NEWLINE);
871 }
872 if (vsub->imei[0] != '\0') {
873 MSC_VTY_DUMP(vty, offset, "IMEI: %s%s",
874 vsub->imei, VTY_NEWLINE);
875 }
876 if (vsub->imeisv[0] != '\0') {
877 MSC_VTY_DUMP(vty, offset, "IMEISV: %s%s",
878 vsub->imeisv, VTY_NEWLINE);
879 }
880
881 MSC_VTY_DUMP(vty, offset, "Flags: %s", VTY_NEWLINE);
882 MSC_VTY_DUMP_FLAG(vty, offset, "IMSI detached",
883 vsub->imsi_detached_flag);
884 MSC_VTY_DUMP_FLAG(vty, offset, "Conf. by radio contact",
885 vsub->conf_by_radio_contact_ind);
886 MSC_VTY_DUMP_FLAG(vty, offset, "Subscr. data conf. by HLR",
887 vsub->sub_dataconf_by_hlr_ind);
888 MSC_VTY_DUMP_FLAG(vty, offset, "Location conf. in HLR",
889 vsub->loc_conf_in_hlr_ind);
890 MSC_VTY_DUMP_FLAG(vty, offset, "Subscriber dormant",
891 vsub->dormant_ind);
892 MSC_VTY_DUMP_FLAG(vty, offset, "Received cancel location",
893 vsub->cancel_loc_rx);
894 MSC_VTY_DUMP_FLAG(vty, offset, "MS not reachable",
895 vsub->ms_not_reachable_flag);
896 MSC_VTY_DUMP_FLAG(vty, offset, "LA allowed",
897 vsub->la_allowed);
898
899 if (vsub->last_tuple) {
900 struct vlr_auth_tuple *t = vsub->last_tuple;
901 MSC_VTY_DUMP(vty, offset, "A3A8 last tuple (used %d times): %s",
902 t->use_count, VTY_NEWLINE);
903 MSC_VTY_DUMP(vty, offset + 2, "seq # : %d%s",
904 t->key_seq, VTY_NEWLINE);
905 MSC_VTY_DUMP(vty, offset + 2, "RAND : %s%s",
906 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
907 VTY_NEWLINE);
908 MSC_VTY_DUMP(vty, offset + 2, "SRES : %s%s",
909 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
910 VTY_NEWLINE);
911 MSC_VTY_DUMP(vty, offset + 2, "Kc : %s%s",
912 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
913 VTY_NEWLINE);
914 }
915
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700916 /* XXX move t3212 into struct vlr_instance? */
917 net = vsub->vlr->user_ctx;
918 if (!net->t3212) {
919 MSC_VTY_DUMP(vty, offset, "Expires: never (T3212 is disabled)%s",
920 VTY_NEWLINE);
921 } else if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) {
922 MSC_VTY_DUMP(vty, offset, "Expires: never%s",
923 VTY_NEWLINE);
924 } else if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
925 MSC_VTY_DUMP(vty, offset, "Expires: in %ld min %ld sec%s",
926 (vsub->expire_lu - now.tv_sec) / 60,
927 (vsub->expire_lu - now.tv_sec) % 60,
928 VTY_NEWLINE);
929 }
930
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700931 MSC_VTY_DUMP(vty, offset, "Paging: %s paging for %d requests%s",
932 vsub->cs.is_paging ? "is" : "not",
933 llist_count(&vsub->cs.requests),
934 VTY_NEWLINE);
935
936 /* SGs related */
937 MSC_VTY_DUMP(vty, offset, "SGs-state: %s%s",
938 osmo_fsm_inst_state_name(vsub->sgs_fsm),
939 VTY_NEWLINE);
940 MSC_VTY_DUMP(vty, offset, "SGs-MME: %s%s",
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700941 vsub->sgs.mme_name[0] != '\0' ? vsub->sgs.mme_name : "(none)",
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700942 VTY_NEWLINE);
943
944 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
945 osmo_use_count_total(&vsub->use_count),
946 VTY_NEWLINE);
947 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
948 osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count),
949 VTY_NEWLINE);
950
951 /* Connection(s) and/or transactions of this subscriber */
952 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
953 struct msub *msub = msub_for_vsub(vsub);
954 if (!msub)
955 return;
956
957 /* Subscriber info is already printed */
958 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
959
960 MSC_VTY_DUMP(vty, offset, "Connection: %s", VTY_NEWLINE);
961 vty_dump_one_conn(vty, msub, offset + 2, dump_flags);
962 } else if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
963 struct gsm_trans *trans;
964 unsigned int i = 0;
965
966 /* Subscriber info is already printed */
967 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
968 /* Do not print connection info, but mention it */
969 dump_flags |= MSC_VTY_DUMP_F_CONNECTION;
970
971 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
972 if (trans->vsub != vsub)
973 continue;
974 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
975 i++, VTY_NEWLINE);
976 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
977 }
978 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100979}
980
981DEFUN(show_msc_transaction, show_msc_transaction_cmd,
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700982 "show transaction",
983 SHOW_STR "Transactions\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100984{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100985 struct gsm_trans *trans;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700986 uint8_t flags = 0x00;
987 unsigned int i = 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100988
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700989 flags |= MSC_VTY_DUMP_F_CONNECTION;
990 flags |= MSC_VTY_DUMP_F_SUBSCR;
991
992 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
993 vty_out(vty, " Transaction #%02u: %s", i++, VTY_NEWLINE);
994 vty_dump_one_trans(vty, trans, 4, flags);
995 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100996
997 return CMD_SUCCESS;
998}
999
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001000DEFUN(show_msc_conn, show_msc_conn_cmd,
1001 "show connection [trans]",
1002 SHOW_STR "Subscriber Connections\n"
1003 "Show child transactions of each connection\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001004{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001005 uint8_t flags = 0x00;
1006 unsigned int i = 0;
1007 struct msub *msub;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001008
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001009 if (argc > 0)
1010 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1011 flags |= MSC_VTY_DUMP_F_SUBSCR;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001012
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001013 llist_for_each_entry(msub, &msub_list, entry) {
1014 vty_out(vty, " Connection #%02u: %s", i++, VTY_NEWLINE);
1015 vty_dump_one_conn(vty, msub, 4, flags);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001016 }
1017
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001018 return CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001019}
1020
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001021#define SUBSCR_FLAGS "[(conn|trans|conn+trans)]"
1022#define SUBSCR_FLAGS_HELP \
1023 "Show child connections\n" \
1024 "Show child transactions\n" \
1025 "Show child connections and transactions\n"
1026
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001027/* Subscriber */
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001028DEFUN(show_subscr_cache, show_subscr_cache_cmd,
1029 "show subscriber cache " SUBSCR_FLAGS,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001030 SHOW_STR "Show information about subscribers\n"
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001031 "Display contents of subscriber cache\n"
1032 SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001033{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001034 struct vlr_subscr *vsub;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001035 unsigned int count = 0;
1036 uint8_t flags = 0x00;
1037 unsigned int i = 0;
1038
1039 if (argc && strcmp(argv[0], "conn") == 0)
1040 flags |= MSC_VTY_DUMP_F_CONNECTION;
1041 else if (argc && strcmp(argv[0], "trans") == 0)
1042 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1043 else if (argc && strcmp(argv[0], "conn+trans") == 0)
1044 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001045
1046 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
1047 if (++count > 100) {
1048 vty_out(vty, "%% More than %d subscribers in cache,"
1049 " stopping here.%s", count-1, VTY_NEWLINE);
1050 break;
1051 }
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001052 vty_out(vty, " Subscriber #%02u: %s", i++, VTY_NEWLINE);
1053 vty_dump_one_subscr(vty, vsub, 4, flags);
Harald Welte69c54a82018-02-09 20:41:14 +01001054 }
1055
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001056 return CMD_SUCCESS;
1057}
1058
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001059DEFUN(sms_send_pend,
1060 sms_send_pend_cmd,
1061 "sms send pending",
1062 "SMS related commands\n" "SMS Sending related commands\n"
1063 "Send all pending SMS")
1064{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001065 struct gsm_sms *sms;
1066 unsigned long long sms_id = 0;
1067
1068 while (1) {
1069 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1070 if (!sms)
1071 break;
1072
1073 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001074 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001075
1076 sms_id = sms->id + 1;
1077 }
1078
1079 return CMD_SUCCESS;
1080}
1081
1082DEFUN(sms_delete_expired,
1083 sms_delete_expired_cmd,
1084 "sms delete expired",
1085 "SMS related commands\n" "SMS Database related commands\n"
1086 "Delete all expired SMS")
1087{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001088 struct gsm_sms *sms;
1089 unsigned long long sms_id = 0;
1090 long long num_deleted = 0;
1091
1092 while (1) {
1093 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1094 if (!sms)
1095 break;
1096
1097 /* Skip SMS which are currently queued for sending. */
1098 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
1099 continue;
1100
1101 /* Expiration check is performed by the DB layer. */
1102 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
1103 num_deleted++;
1104
1105 sms_id = sms->id + 1;
1106 }
1107
1108 if (num_deleted == 0) {
1109 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
1110 return CMD_WARNING;
1111 }
1112
1113 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
1114 return CMD_SUCCESS;
1115}
1116
1117static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +02001118 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001119 char *str, uint8_t tp_pid)
1120{
1121 struct gsm_network *net = receiver->vlr->user_ctx;
1122 struct gsm_sms *sms;
1123
Harald Welte39b55482018-04-09 19:19:33 +02001124 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001125 sms->protocol_id = tp_pid;
1126
1127 /* store in database for the queue */
1128 if (db_sms_store(sms) != 0) {
1129 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
1130 sms_free(sms);
1131 return CMD_WARNING;
1132 }
1133 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
1134
1135 sms_free(sms);
1136 sms_queue_trigger(net->sms_queue);
1137 return CMD_SUCCESS;
1138}
1139
1140static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
1141 const char *type,
1142 const char *id)
1143{
1144 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001145 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001146 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001147 return vlr_subscr_find_by_imsi(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001148 else if (!strcmp(type, "tmsi"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001149 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id), VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001150
1151 return NULL;
1152}
1153#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
1154#define SUBSCR_HELP "Operations on a Subscriber\n" \
1155 "Identify subscriber by MSISDN (phone number)\n" \
1156 "Legacy alias for 'msisdn'\n" \
1157 "Identify subscriber by IMSI\n" \
1158 "Identify subscriber by TMSI\n" \
Vadim Yanitskiy3ccd8232019-05-16 01:35:23 +07001159 "Legacy alias for 'imsi'\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001160 "Identifier for the subscriber\n"
1161
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001162DEFUN(show_subscr, show_subscr_cmd,
1163 "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
1164 SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001165{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001166 struct vlr_subscr *vsub;
1167 uint8_t flags = 0x00;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001168
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001169 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001170 if (!vsub) {
1171 vty_out(vty, "%% No subscriber found for %s %s%s",
1172 argv[0], argv[1], VTY_NEWLINE);
1173 return CMD_WARNING;
1174 }
1175
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001176 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
1177 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
1178 * this, and since this is not multi-threaded, this vlr_subscr_put() cannot possibly reach a count of 0. */
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001179 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001180
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001181 if (argc > 2 && strcmp(argv[2], "conn") == 0)
1182 flags |= MSC_VTY_DUMP_F_CONNECTION;
1183 else if (argc > 2 && strcmp(argv[2], "trans") == 0)
1184 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1185 else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
1186 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
1187
1188 vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
1189 vty_dump_one_subscr(vty, vsub, 4, flags);
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001190
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001191 return CMD_SUCCESS;
1192}
1193
1194DEFUN(subscriber_create,
1195 subscriber_create_cmd,
1196 "subscriber create imsi ID",
1197 "Operations on a Subscriber\n" \
1198 "Create new subscriber\n" \
1199 "Identify the subscriber by his IMSI\n" \
1200 "Identifier for the subscriber\n")
1201{
1202 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
1203 VTY_NEWLINE);
1204 return CMD_WARNING;
1205}
1206
1207DEFUN(subscriber_send_pending_sms,
1208 subscriber_send_pending_sms_cmd,
1209 "subscriber " SUBSCR_TYPES " ID sms pending-send",
1210 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
1211{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001212 struct vlr_subscr *vsub;
1213 struct gsm_sms *sms;
1214
1215 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1216 if (!vsub) {
1217 vty_out(vty, "%% No subscriber found for %s %s%s",
1218 argv[0], argv[1], VTY_NEWLINE);
1219 return CMD_WARNING;
1220 }
1221
1222 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
1223 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001224 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001225
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001226 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001227
1228 return CMD_SUCCESS;
1229}
1230
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001231DEFUN(subscriber_sms_delete_all,
1232 subscriber_sms_delete_all_cmd,
1233 "subscriber " SUBSCR_TYPES " ID sms delete-all",
1234 SUBSCR_HELP "SMS Operations\n"
1235 "Delete all SMS to be delivered to this subscriber"
1236 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
1237 " WILL BE LOST.\n")
1238{
1239 struct vlr_subscr *vsub;
1240
1241 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1242 if (!vsub) {
1243 vty_out(vty, "%% No subscriber found for %s %s%s",
1244 argv[0], argv[1], VTY_NEWLINE);
1245 return CMD_WARNING;
1246 }
1247
1248 db_sms_delete_by_msisdn(vsub->msisdn);
1249
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001250 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001251
1252 return CMD_SUCCESS;
1253}
1254
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001255DEFUN(subscriber_send_sms,
1256 subscriber_send_sms_cmd,
1257 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1258 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1259{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001260 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001261 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001262 char *str;
1263 int rc;
1264
1265 if (!vsub) {
1266 vty_out(vty, "%% No subscriber found for %s %s%s",
1267 argv[0], argv[1], VTY_NEWLINE);
1268 rc = CMD_WARNING;
1269 goto err;
1270 }
1271
Harald Welte39b55482018-04-09 19:19:33 +02001272 if (!strcmp(argv[2], "msisdn"))
1273 sender_msisdn = argv[3];
1274 else {
1275 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1276 if (!sender) {
1277 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1278 rc = CMD_WARNING;
1279 goto err;
1280 }
1281 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001282 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001283 }
1284
1285 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001286 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001287 talloc_free(str);
1288
1289err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001290 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001291 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001292
1293 return rc;
1294}
1295
1296DEFUN(subscriber_silent_sms,
1297 subscriber_silent_sms_cmd,
1298
1299 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1300 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1301{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001302 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001303 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001304 char *str;
1305 int rc;
1306
1307 if (!vsub) {
1308 vty_out(vty, "%% No subscriber found for %s %s%s",
1309 argv[0], argv[1], VTY_NEWLINE);
1310 rc = CMD_WARNING;
1311 goto err;
1312 }
1313
Harald Welte39b55482018-04-09 19:19:33 +02001314 if (!strcmp(argv[2], "msisdn")) {
1315 sender_msisdn = argv[3];
1316 } else {
1317 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1318 if (!sender) {
1319 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1320 rc = CMD_WARNING;
1321 goto err;
1322 }
1323 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001324 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001325 }
1326
1327 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001328 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001329 talloc_free(str);
1330
1331err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001332 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001333 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001334
1335 return rc;
1336}
1337
Sylvain Munaut93558302019-02-14 20:13:08 +01001338#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001339#define CHAN_TYPE_HELP \
1340 "Any channel\n" \
1341 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001342 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001343 "Any TCH channel\n" \
1344 "SDCCH channel\n"
1345
Sylvain Munaut93558302019-02-14 20:13:08 +01001346#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1347#define CHAN_MODE_HELP \
1348 "Signalling only\n" \
1349 "Speech with HR codec\n" \
1350 "Speech with FR codec\n" \
1351 "Speech with EFR codec\n" \
1352 "Speech with AMR codec\n"
1353
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001354DEFUN(subscriber_silent_call_start,
1355 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001356 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001357 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001358 CHAN_TYPE_HELP CHAN_MODE_HELP
1359 "Target IP for RTP traffic (default 127.0.0.1)\n"
1360 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001361{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001362 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001363 struct gsm0808_channel_type ct;
1364 const char *ip;
1365 uint16_t port;
1366 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001367
1368 if (!vsub) {
1369 vty_out(vty, "%% No subscriber found for %s %s%s",
1370 argv[0], argv[1], VTY_NEWLINE);
1371 return CMD_WARNING;
1372 }
1373
Sylvain Munaut93558302019-02-14 20:13:08 +01001374 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001375
Sylvain Munaut93558302019-02-14 20:13:08 +01001376 if (!strcmp(argv[3], "signalling")) {
1377 ct.ch_indctr = GSM0808_CHAN_SIGN;
1378 ct.perm_spch[0] = 0; /* Spare but required */
1379 ct.perm_spch_len = 1;
1380 } else if (!strcmp(argv[3], "speech-hr")) {
1381 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1382 ct.perm_spch[0] = GSM0808_PERM_HR1;
1383 ct.perm_spch_len = 1;
1384 } else if (!strcmp(argv[3], "speech-fr")) {
1385 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1386 ct.perm_spch[0] = GSM0808_PERM_FR1;
1387 ct.perm_spch_len = 1;
1388 } else if (!strcmp(argv[3], "speech-efr")) {
1389 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1390 ct.perm_spch[0] = GSM0808_PERM_FR2;
1391 ct.perm_spch_len = 1;
1392 } else if (!strcmp(argv[3], "speech-amr")) {
1393 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1394 ct.perm_spch[0] = GSM0808_PERM_FR3;
1395 ct.perm_spch[1] = GSM0808_PERM_HR3;
1396 ct.perm_spch_len = 2;
1397 }
1398
1399 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1400
1401 if (!strcmp(argv[2], "tch/f"))
1402 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1403 else if (!strcmp(argv[2], "tch/h"))
1404 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1405 else if (!strcmp(argv[2], "tch/any"))
1406 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1407 else if (!strcmp(argv[2], "sdcch")) {
1408 if (speech) {
1409 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1410 return CMD_WARNING;
1411 }
1412 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1413 } else
1414 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1415
1416 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1417 port = argc >= 6 ? atoi(argv[5]) : 4000;
1418
1419 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001420 switch (rc) {
1421 case -ENODEV:
1422 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1423 break;
1424 default:
1425 if (rc)
1426 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1427 else
1428 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1429 break;
1430 }
1431
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001432 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001433 return rc ? CMD_WARNING : CMD_SUCCESS;
1434}
1435
1436DEFUN(subscriber_silent_call_stop,
1437 subscriber_silent_call_stop_cmd,
1438 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1439 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1440 CHAN_TYPE_HELP)
1441{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001442 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1443 int rc;
1444
1445 if (!vsub) {
1446 vty_out(vty, "%% No subscriber found for %s %s%s",
1447 argv[0], argv[1], VTY_NEWLINE);
1448 return CMD_WARNING;
1449 }
1450
1451 rc = gsm_silent_call_stop(vsub);
1452 switch (rc) {
1453 case -ENODEV:
1454 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1455 break;
1456 case -ENOENT:
1457 vty_out(vty, "%% Subscriber has no silent call active%s",
1458 VTY_NEWLINE);
1459 break;
1460 default:
1461 if (rc)
1462 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1463 else
1464 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1465 break;
1466 }
1467
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001468 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001469 return rc ? CMD_WARNING : CMD_SUCCESS;
1470}
1471
1472DEFUN(subscriber_ussd_notify,
1473 subscriber_ussd_notify_cmd,
1474 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1475 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1476 "Alerting Level 0\n"
1477 "Alerting Level 1\n"
1478 "Alerting Level 2\n"
1479 "Text of USSD message to send\n")
1480{
1481 char *text;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001482 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001483 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1484 int level;
1485
1486 if (!vsub) {
1487 vty_out(vty, "%% No subscriber found for %s %s%s",
1488 argv[0], argv[1], VTY_NEWLINE);
1489 return CMD_WARNING;
1490 }
1491
1492 level = atoi(argv[2]);
1493 text = argv_concat(argv, argc, 3);
1494 if (!text) {
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001495 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001496 return CMD_WARNING;
1497 }
1498
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001499 msc_a = msc_a_for_vsub(vsub, true);
1500 if (!msc_a || msc_a->c.remote_to) {
1501 vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001502 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001503 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001504 talloc_free(text);
1505 return CMD_WARNING;
1506 }
1507
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001508 msc_send_ussd_notify(msc_a, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001509 /* FIXME: since we don't allocate a transaction here,
1510 * we use dummy GSM 04.07 transaction ID. */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001511 msc_send_ussd_release_complete(msc_a, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001512
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001513 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001514 talloc_free(text);
1515 return CMD_SUCCESS;
1516}
1517
1518DEFUN(subscriber_paging,
1519 subscriber_paging_cmd,
1520 "subscriber " SUBSCR_TYPES " ID paging",
1521 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1522{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001523 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001524 struct paging_request *req;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001525
1526 if (!vsub) {
1527 vty_out(vty, "%% No subscriber found for %s %s%s",
1528 argv[0], argv[1], VTY_NEWLINE);
1529 return CMD_WARNING;
1530 }
1531
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001532 req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL,
1533 NULL, NULL, "manual Paging from VTY");
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001534 if (req)
1535 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1536 else
1537 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1538
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001539 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001540 return req ? CMD_SUCCESS : CMD_WARNING;
1541}
1542
1543static int loop_by_char(uint8_t ch)
1544{
1545 switch (ch) {
1546 case 'a':
1547 return GSM414_LOOP_A;
1548 case 'b':
1549 return GSM414_LOOP_B;
1550 case 'c':
1551 return GSM414_LOOP_C;
1552 case 'd':
1553 return GSM414_LOOP_D;
1554 case 'e':
1555 return GSM414_LOOP_E;
1556 case 'f':
1557 return GSM414_LOOP_F;
1558 case 'i':
1559 return GSM414_LOOP_I;
1560 }
1561 return -1;
1562}
1563
1564DEFUN(subscriber_mstest_close,
1565 subscriber_mstest_close_cmd,
1566 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1567 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1568 "Close a TCH Loop inside the MS\n"
1569 "Loop Type A\n"
1570 "Loop Type B\n"
1571 "Loop Type C\n"
1572 "Loop Type D\n"
1573 "Loop Type E\n"
1574 "Loop Type F\n"
1575 "Loop Type I\n")
1576{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001577 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001578 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1579 const char *loop_str;
1580 int loop_mode;
1581
1582 if (!vsub) {
1583 vty_out(vty, "%% No subscriber found for %s %s%s",
1584 argv[0], argv[1], VTY_NEWLINE);
1585 return CMD_WARNING;
1586 }
1587
1588 loop_str = argv[2];
1589 loop_mode = loop_by_char(loop_str[0]);
1590
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001591 msc_a = msc_a_for_vsub(vsub, true);
1592 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001593 vty_out(vty, "%% An active connection is required for %s %s%s",
1594 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001595 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001596 return CMD_WARNING;
1597 }
1598
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001599 gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001600
1601 return CMD_SUCCESS;
1602}
1603
1604DEFUN(subscriber_mstest_open,
1605 subscriber_mstest_open_cmd,
1606 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1607 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1608 "Open a TCH Loop inside the MS\n")
1609{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001610 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001611 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1612
1613 if (!vsub) {
1614 vty_out(vty, "%% No subscriber found for %s %s%s",
1615 argv[0], argv[1], VTY_NEWLINE);
1616 return CMD_WARNING;
1617 }
1618
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001619 msc_a = msc_a_for_vsub(vsub, true);
1620 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001621 vty_out(vty, "%% An active connection is required for %s %s%s",
1622 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001623 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001624 return CMD_WARNING;
1625 }
1626
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001627 gsm0414_tx_open_loop_cmd(msc_a);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001628
1629 return CMD_SUCCESS;
1630}
1631
1632DEFUN(ena_subscr_expire,
1633 ena_subscr_expire_cmd,
1634 "subscriber " SUBSCR_TYPES " ID expire",
1635 SUBSCR_HELP "Expire the subscriber Now\n")
1636{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001637 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1638 argv[1]);
1639
1640 if (!vsub) {
1641 vty_out(vty, "%% No subscriber found for %s %s%s",
1642 argv[0], argv[1], VTY_NEWLINE);
1643 return CMD_WARNING;
1644 }
1645
1646 if (vlr_subscr_expire(vsub))
1647 vty_out(vty, "%% VLR released subscriber %s%s",
1648 vlr_subscr_name(vsub), VTY_NEWLINE);
1649
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001650 if (osmo_use_count_total(&vsub->use_count) > 1)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001651 vty_out(vty, "%% Subscriber %s is still in use,"
1652 " should be released soon%s",
1653 vlr_subscr_name(vsub), VTY_NEWLINE);
1654
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001655 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001656 return CMD_SUCCESS;
1657}
1658
1659static int scall_cbfn(unsigned int subsys, unsigned int signal,
1660 void *handler_data, void *signal_data)
1661{
1662 struct scall_signal_data *sigdata = signal_data;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001663 struct vty *vty = sigdata->vty;
1664
1665 if (!vty_is_active(vty))
1666 return 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001667
1668 switch (signal) {
1669 case S_SCALL_SUCCESS:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001670 vty_out(vty, "%% Silent call success%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001671 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001672 case S_SCALL_FAILED:
1673 vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE);
1674 break;
1675 case S_SCALL_DETACHED:
1676 vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001677 break;
1678 }
1679 return 0;
1680}
1681
1682DEFUN(show_stats,
1683 show_stats_cmd,
1684 "show statistics",
1685 SHOW_STR "Display network statistics\n")
1686{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001687 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001688 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1689 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1690 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001691 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001692 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001693 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001694 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001695 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001696 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1697 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001698 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001699 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001700 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1701 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001702 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001703 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001704 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1705 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1706 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001707 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001708 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001709 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1710 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001711 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001712 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001713 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1714 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001715 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001716 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001717 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current,
1718 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1719 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current
1720 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1721 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001722 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001723 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current,
1724 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1725 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current
1726 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1727 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001728 return CMD_SUCCESS;
1729}
1730
1731DEFUN(show_smsqueue,
1732 show_smsqueue_cmd,
1733 "show sms-queue",
1734 SHOW_STR "Display SMSqueue statistics\n")
1735{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001736 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001737 return CMD_SUCCESS;
1738}
1739
1740DEFUN(smsqueue_trigger,
1741 smsqueue_trigger_cmd,
1742 "sms-queue trigger",
1743 "SMS Queue\n" "Trigger sending messages\n")
1744{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001745 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001746 return CMD_SUCCESS;
1747}
1748
1749DEFUN(smsqueue_max,
1750 smsqueue_max_cmd,
1751 "sms-queue max-pending <1-500>",
1752 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1753{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001754 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001755 return CMD_SUCCESS;
1756}
1757
1758DEFUN(smsqueue_clear,
1759 smsqueue_clear_cmd,
1760 "sms-queue clear",
1761 "SMS Queue\n" "Clear the queue of pending SMS\n")
1762{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001763 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001764 return CMD_SUCCESS;
1765}
1766
1767DEFUN(smsqueue_fail,
1768 smsqueue_fail_cmd,
1769 "sms-queue max-failure <1-500>",
1770 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1771{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001772 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001773 return CMD_SUCCESS;
1774}
1775
1776
1777DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1778 "mncc-int", "Configure internal MNCC handler")
1779{
1780 vty->node = MNCC_INT_NODE;
1781
1782 return CMD_SUCCESS;
1783}
1784
1785static struct cmd_node mncc_int_node = {
1786 MNCC_INT_NODE,
1787 "%s(config-mncc-int)# ",
1788 1,
1789};
1790
1791static const struct value_string tchf_codec_names[] = {
1792 { GSM48_CMODE_SPEECH_V1, "fr" },
1793 { GSM48_CMODE_SPEECH_EFR, "efr" },
1794 { GSM48_CMODE_SPEECH_AMR, "amr" },
1795 { 0, NULL }
1796};
1797
1798static const struct value_string tchh_codec_names[] = {
1799 { GSM48_CMODE_SPEECH_V1, "hr" },
1800 { GSM48_CMODE_SPEECH_AMR, "amr" },
1801 { 0, NULL }
1802};
1803
1804static int config_write_mncc_int(struct vty *vty)
1805{
1806 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1807 vty_out(vty, " default-codec tch-f %s%s",
1808 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1809 VTY_NEWLINE);
1810 vty_out(vty, " default-codec tch-h %s%s",
1811 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1812 VTY_NEWLINE);
1813
1814 return CMD_SUCCESS;
1815}
1816
1817DEFUN(mnccint_def_codec_f,
1818 mnccint_def_codec_f_cmd,
1819 "default-codec tch-f (fr|efr|amr)",
1820 "Set default codec\n" "Codec for TCH/F\n"
1821 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1822{
1823 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1824
1825 return CMD_SUCCESS;
1826}
1827
1828DEFUN(mnccint_def_codec_h,
1829 mnccint_def_codec_h_cmd,
1830 "default-codec tch-h (hr|amr)",
1831 "Set default codec\n" "Codec for TCH/H\n"
1832 "Half-Rate\n" "Adaptive Multi-Rate\n")
1833{
1834 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1835
1836 return CMD_SUCCESS;
1837}
1838
1839
1840DEFUN(logging_fltr_imsi,
1841 logging_fltr_imsi_cmd,
1842 "logging filter imsi IMSI",
1843 LOGGING_STR FILTER_STR
1844 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1845{
1846 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001847 struct log_target *tgt = osmo_log_vty2tgt(vty);
1848 const char *imsi = argv[0];
1849
1850 if (!tgt)
1851 return CMD_WARNING;
1852
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001853 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001854
1855 if (!vlr_subscr) {
1856 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1857 argv[0], VTY_NEWLINE);
1858 return CMD_WARNING;
1859 }
1860
1861 log_set_filter_vlr_subscr(tgt, vlr_subscr);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001862 vlr_subscr_put(vlr_subscr, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001863 return CMD_SUCCESS;
1864}
1865
1866static struct cmd_node hlr_node = {
1867 HLR_NODE,
1868 "%s(config-hlr)# ",
1869 1,
1870};
1871
1872DEFUN(cfg_hlr, cfg_hlr_cmd,
1873 "hlr", "Configure connection to the HLR")
1874{
1875 vty->node = HLR_NODE;
1876 return CMD_SUCCESS;
1877}
1878
1879DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1880 "Remote GSUP address of the HLR\n"
1881 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1882{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001883 talloc_free((void*)gsmnet->gsup_server_addr_str);
1884 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1885 return CMD_SUCCESS;
1886}
1887
1888DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1889 "Remote GSUP port of the HLR\n"
1890 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1891{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001892 gsmnet->gsup_server_port = atoi(argv[0]);
1893 return CMD_SUCCESS;
1894}
1895
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001896DEFUN(cfg_hlr_ipa_name,
1897 cfg_hlr_ipa_name_cmd,
1898 "ipa-name NAME",
1899 "Set the IPA name of this MSC\n"
1900 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1901 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
1902 "The default is 'MSC-00-00-00-00-00-00'.\n")
1903{
1904 if (vty->type != VTY_FILE) {
1905 vty_out(vty, "The IPA name cannot be changed at run-time; "
1906 "It can only be set in the configuraton file.%s", VTY_NEWLINE);
1907 return CMD_WARNING;
1908 }
1909
1910 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
1911 return CMD_SUCCESS;
1912}
1913
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001914static int config_write_hlr(struct vty *vty)
1915{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001916 vty_out(vty, "hlr%s", VTY_NEWLINE);
1917 vty_out(vty, " remote-ip %s%s",
1918 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1919 vty_out(vty, " remote-port %u%s",
1920 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001921 if (gsmnet->msc_ipa_name)
1922 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001923 return CMD_SUCCESS;
1924}
1925
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001926void msc_vty_init(struct gsm_network *msc_network)
1927{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001928 OSMO_ASSERT(gsmnet == NULL);
1929 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001930
1931 osmo_stats_vty_add_cmds();
1932
1933 install_element(CONFIG_NODE, &cfg_net_cmd);
1934 install_node(&net_node, config_write_net);
1935 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1936 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1937 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1938 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1939 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +02001940 install_element(GSMNET_NODE, &cfg_net_encryption_uea_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001941 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1942 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1943 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1944 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1945 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1946 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1947 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1948 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001949
1950 install_element(CONFIG_NODE, &cfg_msc_cmd);
1951 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001952 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01001953 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
1954 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02001955 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01001956 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07001957 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001958 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001959 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
1960 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01001961 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001962 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
1963 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01001964 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01001965 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07001966 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
1967 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +02001968 install_element(MSC_NODE, &cfg_msc_osmux_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001969 install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd);
1970
1971 neighbor_ident_vty_init(msc_network);
Philipp Maierfbf66102017-04-09 12:32:51 +02001972
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02001973 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001974#ifdef BUILD_IU
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001975 ranap_iu_vty_init(MSC_NODE, (enum ranap_nsap_addr_enc*)&msc_network->iu.rab_assign_addr_enc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001976#endif
Harald Welte0df904d2018-12-03 11:00:04 +01001977 sgs_vty_init();
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001978
Stefan Sperling617ac802018-02-22 17:58:20 +01001979 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001980
1981 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
1982
1983 install_element_ve(&show_subscr_cmd);
1984 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01001985 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001986 install_element_ve(&show_msc_conn_cmd);
1987 install_element_ve(&show_msc_transaction_cmd);
1988
1989 install_element_ve(&sms_send_pend_cmd);
1990 install_element_ve(&sms_delete_expired_cmd);
1991
1992 install_element_ve(&subscriber_create_cmd);
1993 install_element_ve(&subscriber_send_sms_cmd);
1994 install_element_ve(&subscriber_silent_sms_cmd);
1995 install_element_ve(&subscriber_silent_call_start_cmd);
1996 install_element_ve(&subscriber_silent_call_stop_cmd);
1997 install_element_ve(&subscriber_ussd_notify_cmd);
1998 install_element_ve(&subscriber_mstest_close_cmd);
1999 install_element_ve(&subscriber_mstest_open_cmd);
2000 install_element_ve(&subscriber_paging_cmd);
2001 install_element_ve(&show_stats_cmd);
2002 install_element_ve(&show_smsqueue_cmd);
2003 install_element_ve(&logging_fltr_imsi_cmd);
2004
2005 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
2006 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
2007 install_element(ENABLE_NODE, &smsqueue_max_cmd);
2008 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
2009 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
2010 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01002011 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002012
2013 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
2014 install_node(&mncc_int_node, config_write_mncc_int);
2015 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
2016 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
2017
2018 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
2019
2020 install_element(CONFIG_NODE, &cfg_hlr_cmd);
2021 install_node(&hlr_node, config_write_hlr);
2022 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
2023 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002024 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002025}