blob: 1f389f45503dae1a37d1b5e63b5ba13b88d00481 [file] [log] [blame]
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001/* MSC interface to quagga VTY */
Vadim Yanitskiy999a5932023-05-18 17:22:26 +07002/* (C) 2016-2018 by sysmocom s.f.m.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 Hofmeyr9aac5c22020-05-27 00:04:26 +020036#include <osmocom/gsm/gsm23236.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020037
Maxc51609a2018-11-09 17:13:00 +010038#include <osmocom/sigtran/sccp_helpers.h>
39
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +070040#include <osmocom/vty/tdef_vty.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020041#include <osmocom/vty/command.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010042#include <osmocom/vty/logging.h>
Stefan Sperling617ac802018-02-22 17:58:20 +010043#include <osmocom/vty/misc.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010044#include <osmocom/vty/stats.h>
45
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020046#ifdef BUILD_IU
47#include <osmocom/ranap/iu_client.h>
48#endif
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020049
Neels Hofmeyr90843962017-09-04 15:04:35 +020050#include <osmocom/msc/vty.h>
51#include <osmocom/msc/gsm_data.h>
52#include <osmocom/msc/gsm_subscriber.h>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010053#include <osmocom/msc/msub.h>
54#include <osmocom/msc/msc_a.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020055#include <osmocom/msc/vlr.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010056#include <osmocom/msc/transaction.h>
57#include <osmocom/msc/db.h>
58#include <osmocom/msc/sms_queue.h>
59#include <osmocom/msc/silent_call.h>
60#include <osmocom/msc/gsm_04_80.h>
61#include <osmocom/msc/gsm_04_14.h>
62#include <osmocom/msc/signal.h>
63#include <osmocom/msc/mncc_int.h>
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +020064#include <osmocom/msc/osmux.h>
Vadim Yanitskiy1b891302018-08-04 01:33:08 +070065#include <osmocom/msc/rrlp.h>
Harald Welte0df904d2018-12-03 11:00:04 +010066#include <osmocom/msc/vlr_sgs.h>
67#include <osmocom/msc/sgs_vty.h>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010068#include <osmocom/msc/sccp_ran.h>
69#include <osmocom/msc/ran_peer.h>
Alexander Couzensae167fc2020-09-25 05:25:16 +020070#include <osmocom/msc/ran_infra.h>
Andreas Eversbergf8ac7342023-04-23 12:22:25 +020071#include <osmocom/msc/asci_vty.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010072
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010073static struct gsm_network *gsmnet = NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010074
Vadim Yanitskiy9b56cd82020-01-25 06:38:44 +070075static struct cmd_node net_node = {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010076 GSMNET_NODE,
77 "%s(config-net)# ",
78 1,
79};
80
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +010081#define VSUB_USE_VTY "VTY"
82
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010083#define NETWORK_STR "Configure the GSM network\n"
84#define CODE_CMD_STR "Code commands\n"
85#define NAME_CMD_STR "Name Commands\n"
86#define NAME_STR "Name to use\n"
87
88DEFUN(cfg_net,
89 cfg_net_cmd,
90 "network", NETWORK_STR)
91{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010092 vty->index = gsmnet;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010093 vty->node = GSMNET_NODE;
94
95 return CMD_SUCCESS;
96}
97
98DEFUN(cfg_net_ncc,
99 cfg_net_ncc_cmd,
100 "network country code <1-999>",
101 "Set the GSM network country code\n"
102 "Country commands\n"
103 CODE_CMD_STR
104 "Network Country Code to use\n")
105{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100106 gsmnet->plmn.mcc = atoi(argv[0]);
107
108 return CMD_SUCCESS;
109}
110
111DEFUN(cfg_net_mnc,
112 cfg_net_mnc_cmd,
113 "mobile network code <0-999>",
114 "Set the GSM mobile network code\n"
115 "Network Commands\n"
116 CODE_CMD_STR
117 "Mobile Network Code to use\n")
118{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100119 uint16_t mnc;
120 bool mnc_3_digits;
121
122 if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
123 vty_out(vty, "%% Error decoding MNC: %s%s", argv[0], VTY_NEWLINE);
124 return CMD_WARNING;
125 }
126
127 gsmnet->plmn.mnc = mnc;
128 gsmnet->plmn.mnc_3_digits = mnc_3_digits;
129
130 return CMD_SUCCESS;
131}
132
133DEFUN(cfg_net_name_short,
134 cfg_net_name_short_cmd,
Vadim Yanitskiy57b36e52023-07-21 00:51:48 +0700135 "short name .NAME",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100136 "Set the short GSM network name\n" NAME_CMD_STR NAME_STR)
137{
Vadim Yanitskiy57b36e52023-07-21 00:51:48 +0700138 if (gsmnet->name_short != NULL)
139 talloc_free(gsmnet->name_short);
140 gsmnet->name_short = argv_concat(argv, argc, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100141 return CMD_SUCCESS;
142}
143
144DEFUN(cfg_net_name_long,
145 cfg_net_name_long_cmd,
Vadim Yanitskiy57b36e52023-07-21 00:51:48 +0700146 "long name .NAME",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100147 "Set the long GSM network name\n" NAME_CMD_STR NAME_STR)
148{
Vadim Yanitskiy57b36e52023-07-21 00:51:48 +0700149 if (gsmnet->name_long != NULL)
150 talloc_free(gsmnet->name_long);
151 gsmnet->name_long = argv_concat(argv, argc, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100152 return CMD_SUCCESS;
153}
154
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200155#define ENCRYPTION_STR "Encryption options\n"
156
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100157DEFUN(cfg_net_encryption,
158 cfg_net_encryption_cmd,
Eric Wilda7f80202021-06-09 04:04:06 +0200159 "encryption a5 <0-4> [<0-4>] [<0-4>] [<0-4>] [<0-4>]",
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200160 ENCRYPTION_STR
161 "GSM A5 Air Interface Encryption.\n"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100162 "A5/n Algorithm Number\n"
163 "A5/n Algorithm Number\n"
164 "A5/n Algorithm Number\n"
Eric Wilda7f80202021-06-09 04:04:06 +0200165 "A5/n Algorithm Number\n"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100166 "A5/n Algorithm Number\n")
167{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100168 unsigned int i;
169
170 gsmnet->a5_encryption_mask = 0;
171 for (i = 0; i < argc; i++)
172 gsmnet->a5_encryption_mask |= (1 << atoi(argv[i]));
173
174 return CMD_SUCCESS;
175}
176
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200177DEFUN(cfg_net_encryption_uea,
178 cfg_net_encryption_uea_cmd,
179 "encryption uea <0-2> [<0-2>] [<0-2>]",
180 ENCRYPTION_STR
Harald Welte505a94a2021-02-06 17:12:20 +0100181 "UTRAN (3G) encryption algorithms to allow: 0 = UEA0 (no encryption), 1 = UEA1, 2 = UEA2.\n"
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200182 "UEAn Algorithm Number\n"
183 "UEAn Algorithm Number\n"
184 "UEAn Algorithm Number\n"
185 )
186{
187 unsigned int i;
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200188
Harald Welte505a94a2021-02-06 17:12:20 +0100189 gsmnet->uea_encryption_mask = 0;
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200190 for (i = 0; i < argc; i++)
Harald Welte505a94a2021-02-06 17:12:20 +0100191 gsmnet->uea_encryption_mask |= (1 << atoi(argv[i]));
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200192
193 return CMD_SUCCESS;
194}
195
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100196DEFUN(cfg_net_authentication,
197 cfg_net_authentication_cmd,
198 "authentication (optional|required)",
199 "Whether to enforce MS authentication in 2G\n"
200 "Allow MS to attach via 2G BSC without authentication\n"
201 "Always do authentication\n")
202{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100203 gsmnet->authentication_required = (argv[0][0] == 'r') ? true : false;
204
205 return CMD_SUCCESS;
206}
207
208DEFUN(cfg_net_rrlp_mode, cfg_net_rrlp_mode_cmd,
209 "rrlp mode (none|ms-based|ms-preferred|ass-preferred)",
210 "Radio Resource Location Protocol\n"
211 "Set the Radio Resource Location Protocol Mode\n"
212 "Don't send RRLP request\n"
213 "Request MS-based location\n"
214 "Request any location, prefer MS-based\n"
215 "Request any location, prefer MS-assisted\n")
216{
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700217 gsmnet->rrlp.mode = msc_rrlp_mode_parse(argv[0]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100218
219 return CMD_SUCCESS;
220}
221
222DEFUN(cfg_net_mm_info, cfg_net_mm_info_cmd,
223 "mm info (0|1)",
224 "Mobility Management\n"
225 "Send MM INFO after LOC UPD ACCEPT\n"
226 "Disable\n" "Enable\n")
227{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100228 gsmnet->send_mm_info = atoi(argv[0]);
229
230 return CMD_SUCCESS;
231}
232
233DEFUN(cfg_net_timezone,
234 cfg_net_timezone_cmd,
235 "timezone <-19-19> (0|15|30|45)",
236 "Set the Timezone Offset of the network\n"
237 "Timezone offset (hours)\n"
238 "Timezone offset (00 minutes)\n"
239 "Timezone offset (15 minutes)\n"
240 "Timezone offset (30 minutes)\n"
241 "Timezone offset (45 minutes)\n"
242 )
243{
244 struct gsm_network *net = vty->index;
245 int tzhr = atoi(argv[0]);
246 int tzmn = atoi(argv[1]);
247
248 net->tz.hr = tzhr;
249 net->tz.mn = tzmn;
250 net->tz.dst = 0;
251 net->tz.override = 1;
252
253 return CMD_SUCCESS;
254}
255
256DEFUN(cfg_net_timezone_dst,
257 cfg_net_timezone_dst_cmd,
258 "timezone <-19-19> (0|15|30|45) <0-2>",
259 "Set the Timezone Offset of the network\n"
260 "Timezone offset (hours)\n"
261 "Timezone offset (00 minutes)\n"
262 "Timezone offset (15 minutes)\n"
263 "Timezone offset (30 minutes)\n"
264 "Timezone offset (45 minutes)\n"
265 "DST offset (hours)\n"
266 )
267{
268 struct gsm_network *net = vty->index;
269 int tzhr = atoi(argv[0]);
270 int tzmn = atoi(argv[1]);
271 int tzdst = atoi(argv[2]);
272
273 net->tz.hr = tzhr;
274 net->tz.mn = tzmn;
275 net->tz.dst = tzdst;
276 net->tz.override = 1;
277
278 return CMD_SUCCESS;
279}
280
281DEFUN(cfg_net_no_timezone,
282 cfg_net_no_timezone_cmd,
283 "no timezone",
284 NO_STR
285 "Disable network timezone override, use system tz\n")
286{
287 struct gsm_network *net = vty->index;
288
289 net->tz.override = 0;
290
291 return CMD_SUCCESS;
292}
293
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700294/* NOTE: actually this is subscriber expiration timeout */
295#define PER_LOC_UPD_STR "Periodic Location Updating Interval\n"
296
297DEFUN_DEPRECATED(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
298 "periodic location update <6-1530>",
299 PER_LOC_UPD_STR PER_LOC_UPD_STR PER_LOC_UPD_STR
300 "Periodic Location Updating Interval in Minutes\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100301{
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700302 int minutes = atoi(argv[0]);
303 int rc;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100304
Vadim Yanitskiy9a282302021-11-28 03:44:13 +0300305 vty_out(vty, "%% 'periodic location update' is now deprecated. "
306 "Use 'msc' / 'timer vlr T3212' to change subscriber expiration "
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700307 "timeout.%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100308
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700309 /* We used to double this value and add a minute when scheduling the
310 * expiration timer. Let's emulate the old behaviour here. */
311 minutes = minutes * 2 + 1;
312 vty_out(vty, "%% Setting T3212 to %d minutes "
313 "(emulating the old behaviour).%s",
314 minutes, VTY_NEWLINE);
315
316 rc = osmo_tdef_set(msc_tdefs_vlr, 3212, minutes, OSMO_TDEF_M);
317 return rc ? CMD_WARNING : CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100318}
319
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700320DEFUN_DEPRECATED(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
321 "no periodic location update",
322 NO_STR PER_LOC_UPD_STR PER_LOC_UPD_STR PER_LOC_UPD_STR)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100323{
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700324 int rc;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100325
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700326 vty_out(vty, "%% 'periodic location update' is now deprecated: "
327 "use 'timer T3212' to change subscriber expiration "
328 "timeout.%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100329
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700330 rc = osmo_tdef_set(msc_tdefs_vlr, 3212, 0, OSMO_TDEF_M);
331 return rc ? CMD_WARNING : CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100332}
333
Keith Whyte991bb422019-08-08 15:43:40 +0200334DEFUN(cfg_net_call_wait, cfg_net_call_wait_cmd,
335 "call-waiting",
336 "Enable Call Waiting on the Network\n")
337{
338 struct gsm_network *net = vty->index;
339
340 net->call_waiting = true;
341
342 return CMD_SUCCESS;
343}
344
345DEFUN(cfg_net_no_call_wait, cfg_net_no_call_wait_cmd,
346 "no call-waiting",
347 NO_STR
348 "Disable Call Waiting on the Network\n")
349{
350 struct gsm_network *net = vty->index;
351
352 net->call_waiting = false;
353
354 return CMD_SUCCESS;
355}
356
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100357static int config_write_net(struct vty *vty)
358{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100359 int i;
360
361 vty_out(vty, "network%s", VTY_NEWLINE);
362 vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
363 vty_out(vty, " mobile network code %s%s",
364 osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
365 vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
366 vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
367 vty_out(vty, " encryption a5");
368 for (i = 0; i < 8; i++) {
369 if (gsmnet->a5_encryption_mask & (1 << i))
370 vty_out(vty, " %u", i);
371 }
372 vty_out(vty, "%s", VTY_NEWLINE);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200373
Harald Welte505a94a2021-02-06 17:12:20 +0100374 vty_out(vty, " encryption uea");
375 for (i = 0; i < 8; i++) {
376 if (gsmnet->uea_encryption_mask & (1 << i))
377 vty_out(vty, " %u", i);
378 }
379 vty_out(vty, "%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100380 vty_out(vty, " authentication %s%s",
381 gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE);
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700382 vty_out(vty, " rrlp mode %s%s", msc_rrlp_mode_name(gsmnet->rrlp.mode),
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100383 VTY_NEWLINE);
384 vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
385 if (gsmnet->tz.override != 0) {
386 if (gsmnet->tz.dst)
387 vty_out(vty, " timezone %d %d %d%s",
388 gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
389 VTY_NEWLINE);
390 else
391 vty_out(vty, " timezone %d %d%s",
392 gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
393 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100394
Keith Whyte991bb422019-08-08 15:43:40 +0200395 if (!gsmnet->call_waiting)
396 vty_out(vty, " no call-waiting%s", VTY_NEWLINE);
397
Pau Espin Pedrol53639ea2022-10-18 14:33:15 +0200398 mgcp_client_pool_config_write(vty, " ");
399
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100400 return CMD_SUCCESS;
401}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200402
403static struct cmd_node msc_node = {
404 MSC_NODE,
405 "%s(config-msc)# ",
406 1,
407};
408
409DEFUN(cfg_msc, cfg_msc_cmd,
410 "msc", "Configure MSC options")
411{
412 vty->node = MSC_NODE;
413 return CMD_SUCCESS;
414}
415
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100416#define MNCC_STR "Configure Mobile Network Call Control\n"
417#define MNCC_GUARD_TIMEOUT_STR "Set global guard timer for mncc interface activity\n"
418#define MNCC_GUARD_TIMEOUT_VALUE_STR "guard timer value (sec.)\n"
419
Harald Welte1a62db22022-05-17 12:06:58 +0200420DEFUN_DEPRECATED(cfg_sms_database, cfg_sms_database_cmd,
Keith Whyte1587ffb2020-08-28 13:36:58 +0200421 "sms-database PATH",
422 "Set the path to the MSC-SMS database file\n"
423 "Relative or absolute file system path to the database file (default is '" SMS_DEFAULT_DB_FILE_PATH "')\n")
424{
Harald Welted302bb12022-05-17 13:31:14 +0200425 osmo_talloc_replace_string(gsmnet, &gsmnet->sms_queue_cfg->db_file_path, argv[0]);
Keith Whyte1587ffb2020-08-28 13:36:58 +0200426 return CMD_SUCCESS;
427}
428
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100429DEFUN(cfg_msc_mncc_internal,
430 cfg_msc_mncc_internal_cmd,
431 "mncc internal",
432 MNCC_STR "Use internal MNCC handler (default; changes need a program restart)\n")
433{
434 gsm_network_set_mncc_sock_path(gsmnet, NULL);
435 return CMD_SUCCESS;
436}
437
438DEFUN(cfg_msc_mncc_external,
439 cfg_msc_mncc_external_cmd,
440 "mncc external MNCC_SOCKET_PATH",
441 MNCC_STR "Use external MNCC handler (changes need a program restart)\n"
442 "File system path to create the MNCC unix domain socket at\n")
443{
444 gsm_network_set_mncc_sock_path(gsmnet, argv[0]);
445 return CMD_SUCCESS;
446}
447
Philipp Maier9ca7b312018-10-10 17:00:49 +0200448DEFUN(cfg_msc_mncc_guard_timeout,
449 cfg_msc_mncc_guard_timeout_cmd,
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100450 "mncc guard-timeout <0-255>",
451 MNCC_STR
452 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR)
Philipp Maier9ca7b312018-10-10 17:00:49 +0200453{
454 gsmnet->mncc_guard_timeout = atoi(argv[0]);
455 return CMD_SUCCESS;
456}
457
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100458ALIAS_DEPRECATED(cfg_msc_mncc_guard_timeout,
459 cfg_msc_deprecated_mncc_guard_timeout_cmd,
460 "mncc-guard-timeout <0-255>",
461 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR);
462
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700463#define NCSS_STR "Configure call independent Supplementary Services\n"
464
465DEFUN(cfg_msc_ncss_guard_timeout,
466 cfg_msc_ncss_guard_timeout_cmd,
467 "ncss guard-timeout <0-255>",
468 NCSS_STR "Set guard timer for session activity\n"
469 "guard timer value (sec.), or 0 to disable\n")
470{
471 gsmnet->ncss_guard_timeout = atoi(argv[0]);
472 return CMD_SUCCESS;
473}
474
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200475DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
476 "assign-tmsi",
477 "Assign TMSI during Location Updating.\n")
478{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200479 gsmnet->vlr->cfg.assign_tmsi = true;
480 return CMD_SUCCESS;
481}
482
483DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
484 "no assign-tmsi",
485 NO_STR "Assign TMSI during Location Updating.\n")
486{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200487 gsmnet->vlr->cfg.assign_tmsi = false;
488 return CMD_SUCCESS;
489}
490
Keith Whytea1a70be2021-05-16 02:59:52 +0200491DEFUN_ATTR(cfg_msc_lcls_disable, cfg_msc_lcls_disable_cmd,
492 "lcls-permitted",
493 "Globally allow LCLS (Local Call Local Switch) for all calls on this MSC.\n",
494 CMD_ATTR_IMMEDIATE)
495{
496 gsmnet->lcls_permitted = true;
497 return CMD_SUCCESS;
498}
499
500DEFUN_ATTR(cfg_msc_no_lcls_disable, cfg_msc_no_lcls_disable_cmd,
501 "no lcls-permitted",
502 NO_STR "Globally disable LCLS (Local Call Local Switch) for all calls on this MSC.\n",
503 CMD_ATTR_IMMEDIATE)
504{
505 gsmnet->lcls_permitted = false;
506 return CMD_SUCCESS;
507}
508
Philipp Maierfbf66102017-04-09 12:32:51 +0200509DEFUN(cfg_msc_cs7_instance_a,
510 cfg_msc_cs7_instance_a_cmd,
511 "cs7-instance-a <0-15>",
512 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
513{
Philipp Maierfbf66102017-04-09 12:32:51 +0200514 gsmnet->a.cs7_instance = atoi(argv[0]);
515 return CMD_SUCCESS;
516}
517
518DEFUN(cfg_msc_cs7_instance_iu,
519 cfg_msc_cs7_instance_iu_cmd,
520 "cs7-instance-iu <0-15>",
521 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
522{
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100523#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200524 gsmnet->iu.cs7_instance = atoi(argv[0]);
525 return CMD_SUCCESS;
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100526#else
527 vty_out(vty, "WARNING: 'cs7-instance-iu' without effect: built without Iu support%s",
528 VTY_NEWLINE);
529 return CMD_WARNING;
530#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200531}
532
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100533DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
534 "auth-tuple-max-reuse-count <-1-2147483647>",
535 "Configure authentication tuple re-use\n"
536 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
537{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100538 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
539 return CMD_SUCCESS;
540}
541
542DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
543 "auth-tuple-reuse-on-error (0|1)",
544 "Configure authentication tuple re-use when HLR is not responsive\n"
Oliver Smithd6e24fd2019-01-09 10:46:43 +0100545 "Never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
546 "If the HLR does not deliver new tuples, do re-use already available old ones.\n")
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100547{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100548 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
549 return CMD_SUCCESS;
550}
551
Oliver Smith0fec28a2018-12-14 10:52:52 +0100552DEFUN(cfg_msc_check_imei_rqd, cfg_msc_check_imei_rqd_cmd,
Oliver Smith03ded912019-05-02 10:40:50 +0200553 "check-imei-rqd (0|1|early)",
Oliver Smith0fec28a2018-12-14 10:52:52 +0100554 "Send each IMEI to the EIR to ask if it is permitted or not. The EIR is implemented as part of OsmoHLR, "
555 "and can optionally save the IMEI in the HLR.\n"
556 "Do not send IMEIs to the EIR\n"
Oliver Smith03ded912019-05-02 10:40:50 +0200557 "Send each IMEI to the EIR\n"
558 "Send each IMEI to the EIR, and do it at the start of the location update. This allows the EIR to receive the"
559 " 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 +0100560{
Oliver Smith03ded912019-05-02 10:40:50 +0200561 if (strcmp(argv[0], "0") == 0) {
562 gsmnet->vlr->cfg.check_imei_rqd = false;
563 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
564 } else if (strcmp(argv[0], "1") == 0) {
565 gsmnet->vlr->cfg.check_imei_rqd = true;
566 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
567 } else if (strcmp(argv[0], "early") == 0) {
568 gsmnet->vlr->cfg.check_imei_rqd = true;
569 gsmnet->vlr->cfg.retrieve_imeisv_early = true;
570 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100571 return CMD_SUCCESS;
572}
573
Alexander Couzensae167fc2020-09-25 05:25:16 +0200574DEFUN_DEPRECATED(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100575 "paging response-timer (default|<1-65535>)",
576 "Configure Paging\n"
577 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
578 " BSS or RNC\n"
579 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
580 "Set paging timeout in seconds\n")
581{
Alexander Couzensae167fc2020-09-25 05:25:16 +0200582 int rat;
583 int paging_response_timer;
Pau Espin Pedrolb08a3802019-09-16 19:01:37 +0200584 if (!strcmp(argv[0], "default"))
Alexander Couzensae167fc2020-09-25 05:25:16 +0200585 paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100586 else
Alexander Couzensae167fc2020-09-25 05:25:16 +0200587 paging_response_timer = atoi(argv[0]);
588
589 for (rat = 0; rat < OSMO_RAT_COUNT; rat++) {
590 osmo_tdef_set(msc_ran_infra[rat].tdefs, -4, paging_response_timer, OSMO_TDEF_S);
591 }
592
593 vty_out(vty, "%% paging response-timer is deprecated.%s"
594 "%% All ran timer has been modified.%s"
595 "%% use 'timer <geran|utran|sgs> X4 %s' instead%s",
596 VTY_NEWLINE, VTY_NEWLINE, argv[0], VTY_NEWLINE);
597
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100598 return CMD_SUCCESS;
599}
600
Harald Welte69c54a82018-02-09 20:41:14 +0100601DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
602 "emergency-call route-to-msisdn MSISDN",
603 "Configure Emergency Call Behaviour\n"
604 "MSISDN to which Emergency Calls are Dispatched\n"
605 "MSISDN (E.164 Phone Number)\n")
606{
Harald Welte69c54a82018-02-09 20:41:14 +0100607 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
608
609 return CMD_SUCCESS;
610}
611
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700612/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
613DEFUN(cfg_msc_sms_over_gsup, cfg_msc_sms_over_gsup_cmd,
614 "sms-over-gsup",
615 "Enable routing of SMS messages over GSUP\n")
616{
617 gsmnet->sms_over_gsup = true;
618 return CMD_SUCCESS;
619}
620
621/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
622DEFUN(cfg_msc_no_sms_over_gsup, cfg_msc_no_sms_over_gsup_cmd,
623 "no sms-over-gsup",
624 NO_STR "Disable routing of SMS messages over GSUP\n")
625{
626 gsmnet->sms_over_gsup = false;
627 return CMD_SUCCESS;
628}
629
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100630/* FIXME: This should rather be in the form of
631 * handover-number range 001234xxx
632 * and
633 * handover-number range 001234xxx FIRST LAST
634 */
635DEFUN(cfg_msc_handover_number_range, cfg_msc_handover_number_range_cmd,
636 "handover-number range MSISDN_FIRST MSISDN_LAST",
637 "Configure a range of MSISDN to be assigned to incoming inter-MSC Handovers for call forwarding.\n"
638 "Configure a handover number range\n"
639 "First Handover Number MSISDN\n"
640 "Last Handover Number MSISDN\n")
641{
642 char *endp;
643 uint64_t range_start;
644 uint64_t range_end;
645
646 /* FIXME leading zeros?? */
647
648 errno = 0;
649 range_start = strtoull(argv[0], &endp, 10);
650 if (errno || *endp != '\0') {
651 vty_out(vty, "%% Error parsing handover-number range start: %s%s",
652 argv[0], VTY_NEWLINE);
653 return CMD_WARNING;
654 }
655
656 errno = 0;
657 range_end = strtoull(argv[1], &endp, 10);
658 if (errno || *endp != '\0') {
659 vty_out(vty, "%% Error parsing handover-number range end: %s%s",
660 argv[1], VTY_NEWLINE);
661 return CMD_WARNING;
662 }
663
664 if (range_start > range_end) {
665 vty_out(vty, "%% Error: handover-number range end must be > than the range start, but"
666 " %"PRIu64" > %"PRIu64"%s", range_start, range_end, VTY_NEWLINE);
667 return CMD_WARNING;
668 }
669
670 gsmnet->handover_number.range_start = range_start;
671 gsmnet->handover_number.range_end = range_end;
672 return CMD_SUCCESS;
673}
674
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200675#define OSMUX_STR "RTP multiplexing\n"
676DEFUN(cfg_msc_osmux,
677 cfg_msc_osmux_cmd,
678 "osmux (on|off|only)",
679 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
680{
681 if (strcmp(argv[0], "off") == 0)
682 gsmnet->use_osmux = OSMUX_USAGE_OFF;
683 else if (strcmp(argv[0], "on") == 0)
684 gsmnet->use_osmux = OSMUX_USAGE_ON;
685 else if (strcmp(argv[0], "only") == 0)
686 gsmnet->use_osmux = OSMUX_USAGE_ONLY;
687
688 return CMD_SUCCESS;
689}
690
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +0200691#define NRI_STR "Mapping of Network Resource Indicators to this MSC, for MSC pooling\n"
692DEFUN(cfg_msc_nri_bitlen, cfg_msc_nri_bitlen_cmd,
693 "nri bitlen <0-15>",
694 NRI_STR
695 "Set number of NRI bits to place in TMSI identities (always starting just after the most significant octet)\n"
696 "bit count (default: " OSMO_STRINGIFY_VAL(NRI_BITLEN_DEFAULT) ")\n")
697{
698 gsmnet->vlr->cfg.nri_bitlen = atoi(argv[0]);
699 return CMD_SUCCESS;
700}
701
702#define NRI_STR "Mapping of Network Resource Indicators to this MSC, for MSC pooling\n"
703#define NRI_ARGS_TO_STR_FMT "%s%s%s"
704#define NRI_ARGS_TO_STR_ARGS(ARGC, ARGV) ARGV[0], (ARGC>1)? ".." : "", (ARGC>1)? ARGV[1] : ""
705#define NRI_FIRST_LAST_STR "First value of the NRI value range, should not surpass the configured 'nri bitlen'.\n" \
706 "Last value of the NRI value range, should not surpass the configured 'nri bitlen' and be larger than the" \
707 " first value; if omitted, apply only the first value.\n"
708
709DEFUN(cfg_msc_nri_add, cfg_msc_nri_add_cmd,
710 "nri add <0-32767> [<0-32767>]",
711 NRI_STR "Add NRI value or range to the NRI mapping for this MSC\n"
712 NRI_FIRST_LAST_STR)
713{
714 const char *message;
715 int rc = osmo_nri_ranges_vty_add(&message, NULL, gsmnet->vlr->cfg.nri_ranges, argc, argv, gsmnet->vlr->cfg.nri_bitlen);
716 if (message) {
717 vty_out(vty, "%% %s: " NRI_ARGS_TO_STR_FMT, message, NRI_ARGS_TO_STR_ARGS(argc, argv));
718 }
719 if (rc < 0)
720 return CMD_WARNING;
721 return CMD_SUCCESS;
722}
723
724DEFUN(cfg_msc_nri_del, cfg_msc_nri_del_cmd,
725 "nri del <0-32767> [<0-32767>]",
726 NRI_STR "Remove NRI value or range from the NRI mapping for this MSC\n"
727 NRI_FIRST_LAST_STR)
728{
729 const char *message;
730 int rc = osmo_nri_ranges_vty_del(&message, NULL, gsmnet->vlr->cfg.nri_ranges, argc, argv);
731 if (message) {
732 vty_out(vty, "%% %s: " NRI_ARGS_TO_STR_FMT, message, NRI_ARGS_TO_STR_ARGS(argc, argv));
733 }
734 if (rc < 0)
735 return CMD_WARNING;
736 return CMD_SUCCESS;
737}
738
739static void msc_write_nri(struct vty *vty)
740{
741 struct osmo_nri_range *r;
742
743 llist_for_each_entry(r, &gsmnet->vlr->cfg.nri_ranges->entries, entry) {
744 if (osmo_nri_range_validate(r, 255))
745 vty_out(vty, " %% INVALID RANGE:");
746 vty_out(vty, " nri add %d", r->first);
747 if (r->first != r->last)
748 vty_out(vty, " %d", r->last);
749 vty_out(vty, "%s", VTY_NEWLINE);
750 }
751}
752
753DEFUN(show_nri, show_nri_cmd,
754 "show nri",
755 SHOW_STR NRI_STR)
756{
757 msc_write_nri(vty);
758 return CMD_SUCCESS;
759}
760
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200761static int config_write_msc(struct vty *vty)
762{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200763 vty_out(vty, "msc%s", VTY_NEWLINE);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100764 if (gsmnet->mncc_sock_path)
765 vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE);
Vadim Yanitskiy4fa6c2f2023-12-22 01:53:53 +0700766 else
767 vty_out(vty, " mncc internal%s", VTY_NEWLINE);
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100768 vty_out(vty, " mncc guard-timeout %i%s",
Philipp Maier9ca7b312018-10-10 17:00:49 +0200769 gsmnet->mncc_guard_timeout, VTY_NEWLINE);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700770 vty_out(vty, " ncss guard-timeout %i%s",
771 gsmnet->ncss_guard_timeout, VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200772 vty_out(vty, " %sassign-tmsi%s",
773 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
Keith Whytea1a70be2021-05-16 02:59:52 +0200774 if (gsmnet->lcls_permitted)
775 vty_out(vty, " lcls-permitted%s", VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200776
Philipp Maierfbf66102017-04-09 12:32:51 +0200777 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
778 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100779#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200780 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
781 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100782#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200783
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100784 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
785 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
786 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
787 VTY_NEWLINE);
788 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
789 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
790 VTY_NEWLINE);
791
Oliver Smith03ded912019-05-02 10:40:50 +0200792 if (gsmnet->vlr->cfg.check_imei_rqd) {
793 if (gsmnet->vlr->cfg.retrieve_imeisv_early)
794 vty_out(vty, " check-imei-rqd early%s", VTY_NEWLINE);
795 else
796 vty_out(vty, " check-imei-rqd 1%s", VTY_NEWLINE);
797 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100798
Harald Welte69c54a82018-02-09 20:41:14 +0100799 if (gsmnet->emergency.route_to_msisdn) {
800 vty_out(vty, " emergency-call route-to-msisdn %s%s",
801 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
802 }
803
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700804 if (gsmnet->sms_over_gsup)
805 vty_out(vty, " sms-over-gsup%s", VTY_NEWLINE);
806
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100807 if (gsmnet->handover_number.range_start || gsmnet->handover_number.range_end)
808 vty_out(vty, " handover-number range %"PRIu64" %"PRIu64"%s",
809 gsmnet->handover_number.range_start, gsmnet->handover_number.range_end,
810 VTY_NEWLINE);
811
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200812 if (gsmnet->use_osmux != OSMUX_USAGE_OFF) {
813 vty_out(vty, " osmux %s%s", gsmnet->use_osmux == OSMUX_USAGE_ON ? "on" : "only",
814 VTY_NEWLINE);
815 }
816
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200817 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200818#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200819 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200820#endif
821
Neels Hofmeyr880b9502019-05-09 02:01:55 +0200822 neighbor_ident_vty_write(vty);
823
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +0700824 /* Timer introspection commands (generic osmo_tdef API) */
825 osmo_tdef_vty_groups_write(vty, " ");
826
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +0200827 msc_write_nri(vty);
828
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200829 return CMD_SUCCESS;
830}
831
Maxc51609a2018-11-09 17:13:00 +0100832DEFUN(show_bsc, show_bsc_cmd,
833 "show bsc", SHOW_STR "BSC\n")
834{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100835 struct ran_peer *rp;
836 llist_for_each_entry(rp, &gsmnet->a.sri->ran_peers, entry) {
837 vty_out(vty, "BSC %s %s%s",
838 osmo_sccp_inst_addr_name(gsmnet->a.sri->sccp, &rp->peer_addr),
839 osmo_fsm_inst_state_name(rp->fi),
840 VTY_NEWLINE);
Maxc51609a2018-11-09 17:13:00 +0100841 }
842
843 return CMD_SUCCESS;
844}
845
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100846static const char *get_trans_proto_str(const struct gsm_trans *trans)
847{
848 static char buf[256];
849
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100850 switch (trans->type) {
851 case TRANS_CC:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100852 snprintf(buf, sizeof(buf), "%s %4u %4u",
853 gsm48_cc_state_name(trans->cc.state),
854 trans->cc.Tcurrent,
855 trans->cc.T308_second);
856 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100857 case TRANS_SMS:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700858 snprintf(buf, sizeof(buf), "CP:%s RP:%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100859 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
860 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
861 break;
862 default:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700863 return NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100864 }
865
866 return buf;
867}
868
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700869/* Prefix a given format string with a given amount of spaces */
870#define MSC_VTY_DUMP(vty, offset, fmt, args...) \
871 vty_out(vty, "%*s" fmt, offset, "", ##args)
872
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200873/* Print value of a named flag, prefixed with a given amount of spaces */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700874#define MSC_VTY_DUMP_FLAG(vty, offset, name, flag) \
875 MSC_VTY_DUMP(vty, offset + 2, "%s: %*s%s%s", \
876 name, 30 - (int)strlen(name), "", \
877 flag ? "true" : "false", \
878 VTY_NEWLINE)
879
880enum msc_vty_dump_flags {
881 MSC_VTY_DUMP_F_SUBSCR = (1 << 0),
882 MSC_VTY_DUMP_F_CONNECTION = (1 << 1),
883 MSC_VTY_DUMP_F_TRANSACTION = (1 << 2),
884};
885
886static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans,
887 int offset, uint8_t dump_flags)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100888{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700889 const char *proto_str;
890
891 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
892 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
893 vlr_subscr_name(msc_a_vsub(trans->msc_a)),
894 VTY_NEWLINE);
895 }
896
897 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200898 /* (If msc_a exists, there *must* be a non-null msc_a->c.msub) */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700899 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
900 trans->msc_a ? msub_ran_conn_name(trans->msc_a->c.msub)
901 : "(not established)",
902 VTY_NEWLINE);
903 }
904
905 MSC_VTY_DUMP(vty, offset, "Unique (global) identifier: 0x%08x%s",
906 trans->callref, VTY_NEWLINE);
907 MSC_VTY_DUMP(vty, offset, "GSM 04.07 identifier (%s): %u%s",
908 (trans->transaction_id & 0x08) ? "MO" : "MT",
909 trans->transaction_id,
910 VTY_NEWLINE);
911
912 MSC_VTY_DUMP(vty, offset, "Type: %s%s",
913 trans_type_name(trans->type),
914 VTY_NEWLINE);
915
916 if ((proto_str = get_trans_proto_str(trans))) {
917 MSC_VTY_DUMP(vty, offset, "Protocol specific: %s%s",
918 proto_str, VTY_NEWLINE);
919 }
920}
921
922static void vty_dump_one_conn(struct vty *vty, const struct msub *msub,
923 int offset, uint8_t dump_flags)
924{
925 struct vlr_subscr *vsub = msub_vsub(msub);
926 struct msc_a *msc_a = msub_msc_a(msub);
927 char buf[128];
928
929 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
930 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
931 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
932 vlr_subscr_name(vsub),
933 VTY_NEWLINE);
934 }
935
936 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
937 msub_ran_conn_name(msub),
938 VTY_NEWLINE);
939 MSC_VTY_DUMP(vty, offset, "RAN connection state: %s%s",
940 osmo_fsm_inst_state_name(msc_a->c.fi),
941 VTY_NEWLINE);
942
943 if (vsub) {
944 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
Neels Hofmeyr41c03332020-06-24 15:02:27 +0200945 msc_a->via_cell.lai.lac, msc_a->via_cell.cell_identity,
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700946 VTY_NEWLINE);
947 }
948
949 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
950 osmo_use_count_total(&msc_a->use_count),
951 VTY_NEWLINE);
952 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
953 osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count),
954 VTY_NEWLINE);
955
956 /* Transactions of this connection */
957 if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
958 struct gsm_trans *trans;
959 unsigned int i = 0;
960
961 /* Both subscriber and connection info is already printed */
962 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_CONNECTION;
963 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
964
965 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
966 if (trans->msc_a != msc_a)
967 continue;
968 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
969 i++, VTY_NEWLINE);
970 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
971 }
972 }
973}
974
975static void vty_dump_one_subscr(struct vty *vty, struct vlr_subscr *vsub,
976 int offset, uint8_t dump_flags)
977{
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700978 struct timespec now;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700979 char buf[128];
980
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700981 if (vsub->name[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700982 MSC_VTY_DUMP(vty, offset, "Name: '%s'%s",
983 vsub->name, VTY_NEWLINE);
984 }
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700985 if (vsub->msisdn[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700986 MSC_VTY_DUMP(vty, offset, "MSISDN: %s%s",
987 vsub->msisdn, VTY_NEWLINE);
988 }
989
990 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
991 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
992 VTY_NEWLINE);
993 MSC_VTY_DUMP(vty, offset, "RAN type: %s%s",
994 osmo_rat_type_name(vsub->cs.attached_via_ran),
995 VTY_NEWLINE);
996
997 MSC_VTY_DUMP(vty, offset, "IMSI: %s%s",
998 vsub->imsi, VTY_NEWLINE);
999 if (vsub->tmsi != GSM_RESERVED_TMSI) {
1000 MSC_VTY_DUMP(vty, offset, "TMSI: %08X%s",
1001 vsub->tmsi, VTY_NEWLINE);
1002 }
1003 if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
1004 MSC_VTY_DUMP(vty, offset, "New TMSI: %08X%s",
1005 vsub->tmsi_new, VTY_NEWLINE);
1006 }
1007 if (vsub->imei[0] != '\0') {
1008 MSC_VTY_DUMP(vty, offset, "IMEI: %s%s",
1009 vsub->imei, VTY_NEWLINE);
1010 }
1011 if (vsub->imeisv[0] != '\0') {
1012 MSC_VTY_DUMP(vty, offset, "IMEISV: %s%s",
1013 vsub->imeisv, VTY_NEWLINE);
1014 }
1015
1016 MSC_VTY_DUMP(vty, offset, "Flags: %s", VTY_NEWLINE);
1017 MSC_VTY_DUMP_FLAG(vty, offset, "IMSI detached",
1018 vsub->imsi_detached_flag);
1019 MSC_VTY_DUMP_FLAG(vty, offset, "Conf. by radio contact",
1020 vsub->conf_by_radio_contact_ind);
1021 MSC_VTY_DUMP_FLAG(vty, offset, "Subscr. data conf. by HLR",
1022 vsub->sub_dataconf_by_hlr_ind);
1023 MSC_VTY_DUMP_FLAG(vty, offset, "Location conf. in HLR",
1024 vsub->loc_conf_in_hlr_ind);
1025 MSC_VTY_DUMP_FLAG(vty, offset, "Subscriber dormant",
1026 vsub->dormant_ind);
1027 MSC_VTY_DUMP_FLAG(vty, offset, "Received cancel location",
1028 vsub->cancel_loc_rx);
1029 MSC_VTY_DUMP_FLAG(vty, offset, "MS not reachable",
1030 vsub->ms_not_reachable_flag);
1031 MSC_VTY_DUMP_FLAG(vty, offset, "LA allowed",
1032 vsub->la_allowed);
1033
1034 if (vsub->last_tuple) {
1035 struct vlr_auth_tuple *t = vsub->last_tuple;
1036 MSC_VTY_DUMP(vty, offset, "A3A8 last tuple (used %d times): %s",
1037 t->use_count, VTY_NEWLINE);
1038 MSC_VTY_DUMP(vty, offset + 2, "seq # : %d%s",
1039 t->key_seq, VTY_NEWLINE);
1040 MSC_VTY_DUMP(vty, offset + 2, "RAND : %s%s",
1041 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
1042 VTY_NEWLINE);
1043 MSC_VTY_DUMP(vty, offset + 2, "SRES : %s%s",
1044 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
1045 VTY_NEWLINE);
1046 MSC_VTY_DUMP(vty, offset + 2, "Kc : %s%s",
1047 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
1048 VTY_NEWLINE);
1049 }
1050
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +07001051 if (!vlr_timer(vsub->vlr, 3212)) {
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +07001052 MSC_VTY_DUMP(vty, offset, "Expires: never (T3212 is disabled)%s",
1053 VTY_NEWLINE);
1054 } else if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) {
1055 MSC_VTY_DUMP(vty, offset, "Expires: never%s",
1056 VTY_NEWLINE);
1057 } else if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
1058 MSC_VTY_DUMP(vty, offset, "Expires: in %ld min %ld sec%s",
1059 (vsub->expire_lu - now.tv_sec) / 60,
1060 (vsub->expire_lu - now.tv_sec) % 60,
1061 VTY_NEWLINE);
1062 }
1063
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001064 MSC_VTY_DUMP(vty, offset, "Paging: %s paging for %d requests%s",
1065 vsub->cs.is_paging ? "is" : "not",
1066 llist_count(&vsub->cs.requests),
1067 VTY_NEWLINE);
1068
1069 /* SGs related */
1070 MSC_VTY_DUMP(vty, offset, "SGs-state: %s%s",
1071 osmo_fsm_inst_state_name(vsub->sgs_fsm),
1072 VTY_NEWLINE);
1073 MSC_VTY_DUMP(vty, offset, "SGs-MME: %s%s",
Vadim Yanitskiydcf28682019-05-29 22:34:13 +07001074 vsub->sgs.mme_name[0] != '\0' ? vsub->sgs.mme_name : "(none)",
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001075 VTY_NEWLINE);
1076
1077 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
1078 osmo_use_count_total(&vsub->use_count),
1079 VTY_NEWLINE);
1080 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
1081 osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count),
1082 VTY_NEWLINE);
1083
1084 /* Connection(s) and/or transactions of this subscriber */
1085 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
1086 struct msub *msub = msub_for_vsub(vsub);
1087 if (!msub)
1088 return;
1089
1090 /* Subscriber info is already printed */
1091 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
1092
1093 MSC_VTY_DUMP(vty, offset, "Connection: %s", VTY_NEWLINE);
1094 vty_dump_one_conn(vty, msub, offset + 2, dump_flags);
1095 } else if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
1096 struct gsm_trans *trans;
1097 unsigned int i = 0;
1098
1099 /* Subscriber info is already printed */
1100 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
1101 /* Do not print connection info, but mention it */
1102 dump_flags |= MSC_VTY_DUMP_F_CONNECTION;
1103
1104 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1105 if (trans->vsub != vsub)
1106 continue;
1107 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
1108 i++, VTY_NEWLINE);
1109 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
1110 }
1111 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001112}
1113
1114DEFUN(show_msc_transaction, show_msc_transaction_cmd,
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001115 "show transaction",
1116 SHOW_STR "Transactions\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001117{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001118 struct gsm_trans *trans;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001119 uint8_t flags = 0x00;
1120 unsigned int i = 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001121
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001122 flags |= MSC_VTY_DUMP_F_CONNECTION;
1123 flags |= MSC_VTY_DUMP_F_SUBSCR;
1124
1125 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1126 vty_out(vty, " Transaction #%02u: %s", i++, VTY_NEWLINE);
1127 vty_dump_one_trans(vty, trans, 4, flags);
1128 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001129
1130 return CMD_SUCCESS;
1131}
1132
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001133DEFUN(show_msc_conn, show_msc_conn_cmd,
1134 "show connection [trans]",
1135 SHOW_STR "Subscriber Connections\n"
1136 "Show child transactions of each connection\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001137{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001138 uint8_t flags = 0x00;
1139 unsigned int i = 0;
1140 struct msub *msub;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001141
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001142 if (argc > 0)
1143 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1144 flags |= MSC_VTY_DUMP_F_SUBSCR;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001145
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001146 llist_for_each_entry(msub, &msub_list, entry) {
1147 vty_out(vty, " Connection #%02u: %s", i++, VTY_NEWLINE);
1148 vty_dump_one_conn(vty, msub, 4, flags);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001149 }
1150
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001151 return CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001152}
1153
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001154#define SUBSCR_FLAGS "[(conn|trans|conn+trans)]"
1155#define SUBSCR_FLAGS_HELP \
1156 "Show child connections\n" \
1157 "Show child transactions\n" \
1158 "Show child connections and transactions\n"
1159
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001160/* Subscriber */
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001161DEFUN(show_subscr_cache, show_subscr_cache_cmd,
1162 "show subscriber cache " SUBSCR_FLAGS,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001163 SHOW_STR "Show information about subscribers\n"
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001164 "Display contents of subscriber cache\n"
1165 SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001166{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001167 struct vlr_subscr *vsub;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001168 unsigned int count = 0;
1169 uint8_t flags = 0x00;
1170 unsigned int i = 0;
1171
1172 if (argc && strcmp(argv[0], "conn") == 0)
1173 flags |= MSC_VTY_DUMP_F_CONNECTION;
1174 else if (argc && strcmp(argv[0], "trans") == 0)
1175 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1176 else if (argc && strcmp(argv[0], "conn+trans") == 0)
1177 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001178
1179 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
1180 if (++count > 100) {
1181 vty_out(vty, "%% More than %d subscribers in cache,"
1182 " stopping here.%s", count-1, VTY_NEWLINE);
1183 break;
1184 }
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001185 vty_out(vty, " Subscriber #%02u: %s", i++, VTY_NEWLINE);
1186 vty_dump_one_subscr(vty, vsub, 4, flags);
Harald Welte69c54a82018-02-09 20:41:14 +01001187 }
1188
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001189 return CMD_SUCCESS;
1190}
1191
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001192DEFUN(sms_send_pend,
1193 sms_send_pend_cmd,
1194 "sms send pending",
1195 "SMS related commands\n" "SMS Sending related commands\n"
1196 "Send all pending SMS")
1197{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001198 struct gsm_sms *sms;
1199 unsigned long long sms_id = 0;
1200
1201 while (1) {
1202 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1203 if (!sms)
1204 break;
1205
1206 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001207 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001208
1209 sms_id = sms->id + 1;
1210 }
1211
1212 return CMD_SUCCESS;
1213}
1214
1215DEFUN(sms_delete_expired,
1216 sms_delete_expired_cmd,
1217 "sms delete expired",
1218 "SMS related commands\n" "SMS Database related commands\n"
1219 "Delete all expired SMS")
1220{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001221 struct gsm_sms *sms;
1222 unsigned long long sms_id = 0;
1223 long long num_deleted = 0;
1224
1225 while (1) {
1226 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1227 if (!sms)
1228 break;
1229
1230 /* Skip SMS which are currently queued for sending. */
1231 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
1232 continue;
1233
1234 /* Expiration check is performed by the DB layer. */
1235 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
1236 num_deleted++;
1237
1238 sms_id = sms->id + 1;
1239 }
1240
1241 if (num_deleted == 0) {
1242 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
1243 return CMD_WARNING;
1244 }
1245
1246 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
1247 return CMD_SUCCESS;
1248}
1249
1250static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +02001251 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001252 char *str, uint8_t tp_pid)
1253{
1254 struct gsm_network *net = receiver->vlr->user_ctx;
1255 struct gsm_sms *sms;
1256
Harald Welte39b55482018-04-09 19:19:33 +02001257 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Vadim Yanitskiydb4839c2019-12-01 18:52:58 +07001258 if (!sms) {
1259 LOGP(DLSMS, LOGL_ERROR, "Failed to allocate SMS\n");
1260 return CMD_WARNING;
1261 }
1262
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001263 sms->protocol_id = tp_pid;
1264
1265 /* store in database for the queue */
1266 if (db_sms_store(sms) != 0) {
1267 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
1268 sms_free(sms);
1269 return CMD_WARNING;
1270 }
1271 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
1272
1273 sms_free(sms);
1274 sms_queue_trigger(net->sms_queue);
1275 return CMD_SUCCESS;
1276}
1277
1278static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
1279 const char *type,
1280 const char *id)
1281{
1282 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001283 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001284 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001285 return vlr_subscr_find_by_imsi(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001286 else if (!strcmp(type, "tmsi"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001287 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id), VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001288
1289 return NULL;
1290}
1291#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
1292#define SUBSCR_HELP "Operations on a Subscriber\n" \
1293 "Identify subscriber by MSISDN (phone number)\n" \
1294 "Legacy alias for 'msisdn'\n" \
1295 "Identify subscriber by IMSI\n" \
1296 "Identify subscriber by TMSI\n" \
Vadim Yanitskiy3ccd8232019-05-16 01:35:23 +07001297 "Legacy alias for 'imsi'\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001298 "Identifier for the subscriber\n"
1299
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001300DEFUN(show_subscr, show_subscr_cmd,
1301 "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
1302 SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001303{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001304 struct vlr_subscr *vsub;
1305 uint8_t flags = 0x00;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001306
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001307 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001308 if (!vsub) {
1309 vty_out(vty, "%% No subscriber found for %s %s%s",
1310 argv[0], argv[1], VTY_NEWLINE);
1311 return CMD_WARNING;
1312 }
1313
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001314 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
1315 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
1316 * 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 +01001317 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001318
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001319 if (argc > 2 && strcmp(argv[2], "conn") == 0)
1320 flags |= MSC_VTY_DUMP_F_CONNECTION;
1321 else if (argc > 2 && strcmp(argv[2], "trans") == 0)
1322 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1323 else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
1324 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
1325
1326 vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
1327 vty_dump_one_subscr(vty, vsub, 4, flags);
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001328
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001329 return CMD_SUCCESS;
1330}
1331
Vadim Yanitskiyb7ddbf32020-01-20 21:30:09 +07001332DEFUN_DEPRECATED(subscriber_create, subscriber_create_cmd,
1333 "subscriber create imsi ID",
1334 "Operations on a Subscriber\n"
1335 "Create new subscriber\n"
1336 "Identify the subscriber by his IMSI\n"
1337 "Identifier for the subscriber\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001338{
1339 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
1340 VTY_NEWLINE);
1341 return CMD_WARNING;
1342}
1343
1344DEFUN(subscriber_send_pending_sms,
1345 subscriber_send_pending_sms_cmd,
1346 "subscriber " SUBSCR_TYPES " ID sms pending-send",
1347 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
1348{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001349 struct vlr_subscr *vsub;
1350 struct gsm_sms *sms;
1351
1352 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1353 if (!vsub) {
1354 vty_out(vty, "%% No subscriber found for %s %s%s",
1355 argv[0], argv[1], VTY_NEWLINE);
1356 return CMD_WARNING;
1357 }
1358
1359 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
1360 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001361 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001362
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001363 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001364
1365 return CMD_SUCCESS;
1366}
1367
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001368DEFUN(subscriber_sms_delete_all,
1369 subscriber_sms_delete_all_cmd,
1370 "subscriber " SUBSCR_TYPES " ID sms delete-all",
1371 SUBSCR_HELP "SMS Operations\n"
1372 "Delete all SMS to be delivered to this subscriber"
1373 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
1374 " WILL BE LOST.\n")
1375{
1376 struct vlr_subscr *vsub;
1377
1378 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1379 if (!vsub) {
1380 vty_out(vty, "%% No subscriber found for %s %s%s",
1381 argv[0], argv[1], VTY_NEWLINE);
1382 return CMD_WARNING;
1383 }
1384
1385 db_sms_delete_by_msisdn(vsub->msisdn);
1386
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001387 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001388
1389 return CMD_SUCCESS;
1390}
1391
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001392DEFUN(subscriber_send_sms,
1393 subscriber_send_sms_cmd,
1394 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1395 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1396{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001397 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001398 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001399 char *str;
1400 int rc;
1401
1402 if (!vsub) {
1403 vty_out(vty, "%% No subscriber found for %s %s%s",
1404 argv[0], argv[1], VTY_NEWLINE);
1405 rc = CMD_WARNING;
1406 goto err;
1407 }
1408
Harald Welte39b55482018-04-09 19:19:33 +02001409 if (!strcmp(argv[2], "msisdn"))
1410 sender_msisdn = argv[3];
1411 else {
1412 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1413 if (!sender) {
1414 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1415 rc = CMD_WARNING;
1416 goto err;
1417 }
1418 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001419 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001420 }
1421
1422 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001423 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001424 talloc_free(str);
1425
1426err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001427 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001428 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001429
1430 return rc;
1431}
1432
1433DEFUN(subscriber_silent_sms,
1434 subscriber_silent_sms_cmd,
1435
1436 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1437 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1438{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001439 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001440 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001441 char *str;
1442 int rc;
1443
1444 if (!vsub) {
1445 vty_out(vty, "%% No subscriber found for %s %s%s",
1446 argv[0], argv[1], VTY_NEWLINE);
1447 rc = CMD_WARNING;
1448 goto err;
1449 }
1450
Harald Welte39b55482018-04-09 19:19:33 +02001451 if (!strcmp(argv[2], "msisdn")) {
1452 sender_msisdn = argv[3];
1453 } else {
1454 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1455 if (!sender) {
1456 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1457 rc = CMD_WARNING;
1458 goto err;
1459 }
1460 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001461 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001462 }
1463
1464 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001465 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001466 talloc_free(str);
1467
1468err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001469 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001470 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001471
1472 return rc;
1473}
1474
Sylvain Munaut93558302019-02-14 20:13:08 +01001475#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001476#define CHAN_TYPE_HELP \
1477 "Any channel\n" \
1478 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001479 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001480 "Any TCH channel\n" \
1481 "SDCCH channel\n"
1482
Sylvain Munaut93558302019-02-14 20:13:08 +01001483#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1484#define CHAN_MODE_HELP \
1485 "Signalling only\n" \
1486 "Speech with HR codec\n" \
1487 "Speech with FR codec\n" \
1488 "Speech with EFR codec\n" \
1489 "Speech with AMR codec\n"
1490
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001491DEFUN(subscriber_silent_call_start,
1492 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001493 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001494 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001495 CHAN_TYPE_HELP CHAN_MODE_HELP
1496 "Target IP for RTP traffic (default 127.0.0.1)\n"
1497 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001498{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001499 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001500 struct gsm0808_channel_type ct;
1501 const char *ip;
1502 uint16_t port;
1503 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001504
1505 if (!vsub) {
1506 vty_out(vty, "%% No subscriber found for %s %s%s",
1507 argv[0], argv[1], VTY_NEWLINE);
1508 return CMD_WARNING;
1509 }
1510
Sylvain Munaut93558302019-02-14 20:13:08 +01001511 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001512
Sylvain Munaut93558302019-02-14 20:13:08 +01001513 if (!strcmp(argv[3], "signalling")) {
1514 ct.ch_indctr = GSM0808_CHAN_SIGN;
1515 ct.perm_spch[0] = 0; /* Spare but required */
1516 ct.perm_spch_len = 1;
1517 } else if (!strcmp(argv[3], "speech-hr")) {
1518 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1519 ct.perm_spch[0] = GSM0808_PERM_HR1;
1520 ct.perm_spch_len = 1;
1521 } else if (!strcmp(argv[3], "speech-fr")) {
1522 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1523 ct.perm_spch[0] = GSM0808_PERM_FR1;
1524 ct.perm_spch_len = 1;
1525 } else if (!strcmp(argv[3], "speech-efr")) {
1526 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1527 ct.perm_spch[0] = GSM0808_PERM_FR2;
1528 ct.perm_spch_len = 1;
1529 } else if (!strcmp(argv[3], "speech-amr")) {
1530 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1531 ct.perm_spch[0] = GSM0808_PERM_FR3;
1532 ct.perm_spch[1] = GSM0808_PERM_HR3;
1533 ct.perm_spch_len = 2;
1534 }
1535
1536 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1537
1538 if (!strcmp(argv[2], "tch/f"))
1539 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1540 else if (!strcmp(argv[2], "tch/h"))
1541 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1542 else if (!strcmp(argv[2], "tch/any"))
1543 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1544 else if (!strcmp(argv[2], "sdcch")) {
1545 if (speech) {
1546 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1547 return CMD_WARNING;
1548 }
1549 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1550 } else
1551 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1552
1553 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1554 port = argc >= 6 ? atoi(argv[5]) : 4000;
1555
1556 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001557 switch (rc) {
1558 case -ENODEV:
1559 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1560 break;
1561 default:
1562 if (rc)
1563 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1564 else
1565 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1566 break;
1567 }
1568
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001569 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001570 return rc ? CMD_WARNING : CMD_SUCCESS;
1571}
1572
1573DEFUN(subscriber_silent_call_stop,
1574 subscriber_silent_call_stop_cmd,
1575 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1576 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1577 CHAN_TYPE_HELP)
1578{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001579 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1580 int rc;
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 rc = gsm_silent_call_stop(vsub);
1589 switch (rc) {
1590 case -ENODEV:
1591 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1592 break;
1593 case -ENOENT:
1594 vty_out(vty, "%% Subscriber has no silent call active%s",
1595 VTY_NEWLINE);
1596 break;
1597 default:
1598 if (rc)
1599 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1600 else
1601 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1602 break;
1603 }
1604
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001605 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001606 return rc ? CMD_WARNING : CMD_SUCCESS;
1607}
1608
1609DEFUN(subscriber_ussd_notify,
1610 subscriber_ussd_notify_cmd,
1611 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1612 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1613 "Alerting Level 0\n"
1614 "Alerting Level 1\n"
1615 "Alerting Level 2\n"
1616 "Text of USSD message to send\n")
1617{
1618 char *text;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001619 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001620 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1621 int level;
1622
1623 if (!vsub) {
1624 vty_out(vty, "%% No subscriber found for %s %s%s",
1625 argv[0], argv[1], VTY_NEWLINE);
1626 return CMD_WARNING;
1627 }
1628
1629 level = atoi(argv[2]);
1630 text = argv_concat(argv, argc, 3);
1631 if (!text) {
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001632 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001633 return CMD_WARNING;
1634 }
1635
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001636 msc_a = msc_a_for_vsub(vsub, true);
1637 if (!msc_a || msc_a->c.remote_to) {
1638 vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001639 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001640 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001641 talloc_free(text);
1642 return CMD_WARNING;
1643 }
1644
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001645 msc_send_ussd_notify(msc_a, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001646 /* FIXME: since we don't allocate a transaction here,
1647 * we use dummy GSM 04.07 transaction ID. */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001648 msc_send_ussd_release_complete(msc_a, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001649
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001650 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001651 talloc_free(text);
1652 return CMD_SUCCESS;
1653}
1654
1655DEFUN(subscriber_paging,
1656 subscriber_paging_cmd,
1657 "subscriber " SUBSCR_TYPES " ID paging",
1658 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1659{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001660 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001661 struct paging_request *req;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001662
1663 if (!vsub) {
1664 vty_out(vty, "%% No subscriber found for %s %s%s",
1665 argv[0], argv[1], VTY_NEWLINE);
1666 return CMD_WARNING;
1667 }
1668
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001669 req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL,
1670 NULL, NULL, "manual Paging from VTY");
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001671 if (req)
1672 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1673 else
1674 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1675
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001676 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001677 return req ? CMD_SUCCESS : CMD_WARNING;
1678}
1679
1680static int loop_by_char(uint8_t ch)
1681{
1682 switch (ch) {
1683 case 'a':
1684 return GSM414_LOOP_A;
1685 case 'b':
1686 return GSM414_LOOP_B;
1687 case 'c':
1688 return GSM414_LOOP_C;
1689 case 'd':
1690 return GSM414_LOOP_D;
1691 case 'e':
1692 return GSM414_LOOP_E;
1693 case 'f':
1694 return GSM414_LOOP_F;
1695 case 'i':
1696 return GSM414_LOOP_I;
1697 }
1698 return -1;
1699}
1700
1701DEFUN(subscriber_mstest_close,
1702 subscriber_mstest_close_cmd,
1703 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1704 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1705 "Close a TCH Loop inside the MS\n"
1706 "Loop Type A\n"
1707 "Loop Type B\n"
1708 "Loop Type C\n"
1709 "Loop Type D\n"
1710 "Loop Type E\n"
1711 "Loop Type F\n"
1712 "Loop Type I\n")
1713{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001714 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001715 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1716 const char *loop_str;
1717 int loop_mode;
1718
1719 if (!vsub) {
1720 vty_out(vty, "%% No subscriber found for %s %s%s",
1721 argv[0], argv[1], VTY_NEWLINE);
1722 return CMD_WARNING;
1723 }
1724
1725 loop_str = argv[2];
1726 loop_mode = loop_by_char(loop_str[0]);
1727
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001728 msc_a = msc_a_for_vsub(vsub, true);
1729 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001730 vty_out(vty, "%% An active connection is required for %s %s%s",
1731 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001732 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001733 return CMD_WARNING;
1734 }
1735
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001736 gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001737
Vadim Yanitskiy817ad902020-07-29 05:47:01 +07001738 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001739 return CMD_SUCCESS;
1740}
1741
1742DEFUN(subscriber_mstest_open,
1743 subscriber_mstest_open_cmd,
1744 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1745 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1746 "Open a TCH Loop inside the MS\n")
1747{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001748 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001749 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1750
1751 if (!vsub) {
1752 vty_out(vty, "%% No subscriber found for %s %s%s",
1753 argv[0], argv[1], VTY_NEWLINE);
1754 return CMD_WARNING;
1755 }
1756
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001757 msc_a = msc_a_for_vsub(vsub, true);
1758 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001759 vty_out(vty, "%% An active connection is required for %s %s%s",
1760 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001761 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001762 return CMD_WARNING;
1763 }
1764
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001765 gsm0414_tx_open_loop_cmd(msc_a);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001766
Vadim Yanitskiy817ad902020-07-29 05:47:01 +07001767 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001768 return CMD_SUCCESS;
1769}
1770
1771DEFUN(ena_subscr_expire,
1772 ena_subscr_expire_cmd,
1773 "subscriber " SUBSCR_TYPES " ID expire",
1774 SUBSCR_HELP "Expire the subscriber Now\n")
1775{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001776 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1777 argv[1]);
1778
1779 if (!vsub) {
1780 vty_out(vty, "%% No subscriber found for %s %s%s",
1781 argv[0], argv[1], VTY_NEWLINE);
1782 return CMD_WARNING;
1783 }
1784
1785 if (vlr_subscr_expire(vsub))
1786 vty_out(vty, "%% VLR released subscriber %s%s",
1787 vlr_subscr_name(vsub), VTY_NEWLINE);
1788
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001789 if (osmo_use_count_total(&vsub->use_count) > 1)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001790 vty_out(vty, "%% Subscriber %s is still in use,"
1791 " should be released soon%s",
1792 vlr_subscr_name(vsub), VTY_NEWLINE);
1793
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001794 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001795 return CMD_SUCCESS;
1796}
1797
1798static int scall_cbfn(unsigned int subsys, unsigned int signal,
1799 void *handler_data, void *signal_data)
1800{
1801 struct scall_signal_data *sigdata = signal_data;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001802 struct vty *vty = sigdata->vty;
1803
1804 if (!vty_is_active(vty))
1805 return 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001806
1807 switch (signal) {
1808 case S_SCALL_SUCCESS:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001809 vty_out(vty, "%% Silent call success%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001810 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001811 case S_SCALL_FAILED:
1812 vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE);
1813 break;
1814 case S_SCALL_DETACHED:
1815 vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001816 break;
1817 }
1818 return 0;
1819}
1820
1821DEFUN(show_stats,
1822 show_stats_cmd,
1823 "show statistics",
1824 SHOW_STR "Display network statistics\n")
1825{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001826 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001827 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_ATTACH)->current,
1828 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_NORMAL)->current,
1829 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_PERIODIC)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001830 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001831 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001832 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_DETACH)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001833 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001834 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001835 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_COMPLETED)->current,
1836 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_FAILED)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001837 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001838 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001839 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_SUBMITTED)->current,
1840 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_NO_RECEIVER)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001841 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001842 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001843 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_DELIVERED)->current,
1844 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_RP_ERR_MEM)->current,
1845 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_RP_ERR_OTHER)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001846 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001847 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001848 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MO_SETUP)->current,
1849 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MO_CONNECT_ACK)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001850 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001851 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001852 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MT_SETUP)->current,
1853 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MT_CONNECT)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001854 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001855 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001856 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_REQUESTS)->current,
1857 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_ESTABLISHED)->current,
1858 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_REQUESTS)->current
1859 - rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_ESTABLISHED)->current,
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001860 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001861 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001862 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_REQUESTS)->current,
1863 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_ESTABLISHED)->current,
1864 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_REQUESTS)->current
1865 - rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_ESTABLISHED)->current,
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001866 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001867 return CMD_SUCCESS;
1868}
1869
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001870
1871DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1872 "mncc-int", "Configure internal MNCC handler")
1873{
1874 vty->node = MNCC_INT_NODE;
1875
1876 return CMD_SUCCESS;
1877}
1878
1879static struct cmd_node mncc_int_node = {
1880 MNCC_INT_NODE,
1881 "%s(config-mncc-int)# ",
1882 1,
1883};
1884
1885static const struct value_string tchf_codec_names[] = {
1886 { GSM48_CMODE_SPEECH_V1, "fr" },
1887 { GSM48_CMODE_SPEECH_EFR, "efr" },
1888 { GSM48_CMODE_SPEECH_AMR, "amr" },
1889 { 0, NULL }
1890};
1891
1892static const struct value_string tchh_codec_names[] = {
1893 { GSM48_CMODE_SPEECH_V1, "hr" },
1894 { GSM48_CMODE_SPEECH_AMR, "amr" },
1895 { 0, NULL }
1896};
1897
1898static int config_write_mncc_int(struct vty *vty)
1899{
1900 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1901 vty_out(vty, " default-codec tch-f %s%s",
1902 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1903 VTY_NEWLINE);
1904 vty_out(vty, " default-codec tch-h %s%s",
1905 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1906 VTY_NEWLINE);
1907
1908 return CMD_SUCCESS;
1909}
1910
1911DEFUN(mnccint_def_codec_f,
1912 mnccint_def_codec_f_cmd,
1913 "default-codec tch-f (fr|efr|amr)",
1914 "Set default codec\n" "Codec for TCH/F\n"
1915 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1916{
1917 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1918
1919 return CMD_SUCCESS;
1920}
1921
1922DEFUN(mnccint_def_codec_h,
1923 mnccint_def_codec_h_cmd,
1924 "default-codec tch-h (hr|amr)",
1925 "Set default codec\n" "Codec for TCH/H\n"
1926 "Half-Rate\n" "Adaptive Multi-Rate\n")
1927{
1928 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1929
1930 return CMD_SUCCESS;
1931}
1932
1933
1934DEFUN(logging_fltr_imsi,
1935 logging_fltr_imsi_cmd,
1936 "logging filter imsi IMSI",
1937 LOGGING_STR FILTER_STR
1938 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1939{
1940 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001941 struct log_target *tgt = osmo_log_vty2tgt(vty);
1942 const char *imsi = argv[0];
1943
1944 if (!tgt)
1945 return CMD_WARNING;
1946
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001947 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001948
1949 if (!vlr_subscr) {
1950 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1951 argv[0], VTY_NEWLINE);
1952 return CMD_WARNING;
1953 }
1954
1955 log_set_filter_vlr_subscr(tgt, vlr_subscr);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001956 vlr_subscr_put(vlr_subscr, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001957 return CMD_SUCCESS;
1958}
1959
1960static struct cmd_node hlr_node = {
1961 HLR_NODE,
1962 "%s(config-hlr)# ",
1963 1,
1964};
1965
1966DEFUN(cfg_hlr, cfg_hlr_cmd,
1967 "hlr", "Configure connection to the HLR")
1968{
1969 vty->node = HLR_NODE;
1970 return CMD_SUCCESS;
1971}
1972
1973DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1974 "Remote GSUP address of the HLR\n"
1975 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1976{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001977 talloc_free((void*)gsmnet->gsup_server_addr_str);
1978 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1979 return CMD_SUCCESS;
1980}
1981
1982DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1983 "Remote GSUP port of the HLR\n"
1984 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1985{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001986 gsmnet->gsup_server_port = atoi(argv[0]);
1987 return CMD_SUCCESS;
1988}
1989
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001990DEFUN(cfg_hlr_ipa_name,
1991 cfg_hlr_ipa_name_cmd,
1992 "ipa-name NAME",
1993 "Set the IPA name of this MSC\n"
1994 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1995 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
Mychaela N. Falconiad0880fa2023-12-18 03:20:10 +00001996 "The default is 'unnamed-MSC'.\n")
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001997{
1998 if (vty->type != VTY_FILE) {
1999 vty_out(vty, "The IPA name cannot be changed at run-time; "
Martin Hauke3f07dac2019-11-14 17:49:08 +01002000 "It can only be set in the configuration file.%s", VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002001 return CMD_WARNING;
2002 }
2003
2004 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
2005 return CMD_SUCCESS;
2006}
2007
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002008static int config_write_hlr(struct vty *vty)
2009{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002010 vty_out(vty, "hlr%s", VTY_NEWLINE);
2011 vty_out(vty, " remote-ip %s%s",
2012 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
2013 vty_out(vty, " remote-port %u%s",
2014 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002015 if (gsmnet->msc_ipa_name)
2016 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002017 return CMD_SUCCESS;
2018}
2019
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002020void msc_vty_init(struct gsm_network *msc_network)
2021{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01002022 OSMO_ASSERT(gsmnet == NULL);
2023 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002024
2025 osmo_stats_vty_add_cmds();
2026
2027 install_element(CONFIG_NODE, &cfg_net_cmd);
2028 install_node(&net_node, config_write_net);
2029 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
2030 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
2031 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
2032 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
2033 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +02002034 install_element(GSMNET_NODE, &cfg_net_encryption_uea_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002035 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
2036 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
2037 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
2038 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
2039 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
2040 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
2041 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
2042 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Keith Whyte991bb422019-08-08 15:43:40 +02002043 install_element(GSMNET_NODE, &cfg_net_call_wait_cmd);
2044 install_element(GSMNET_NODE, &cfg_net_no_call_wait_cmd);
Pau Espin Pedrol53639ea2022-10-18 14:33:15 +02002045 mgcp_client_pool_vty_init(GSMNET_NODE, MGW_NODE, NULL, msc_network->mgw.mgw_pool);
Pau Espin Pedrolb44cf2d2022-10-17 18:09:15 +02002046
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002047
2048 install_element(CONFIG_NODE, &cfg_msc_cmd);
2049 install_node(&msc_node, config_write_msc);
Keith Whyte1587ffb2020-08-28 13:36:58 +02002050 install_element(MSC_NODE, &cfg_sms_database_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002051 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Keith Whytea1a70be2021-05-16 02:59:52 +02002052 install_element(MSC_NODE, &cfg_msc_lcls_disable_cmd);
2053 install_element(MSC_NODE, &cfg_msc_no_lcls_disable_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01002054 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
2055 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02002056 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01002057 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07002058 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002059 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01002060 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
2061 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01002062 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02002063 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
2064 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01002065 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01002066 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07002067 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
2068 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +02002069 install_element(MSC_NODE, &cfg_msc_osmux_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002070 install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd);
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +02002071 install_element(MSC_NODE, &cfg_msc_nri_bitlen_cmd);
2072 install_element(MSC_NODE, &cfg_msc_nri_add_cmd);
2073 install_element(MSC_NODE, &cfg_msc_nri_del_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002074
2075 neighbor_ident_vty_init(msc_network);
Philipp Maierfbf66102017-04-09 12:32:51 +02002076
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +07002077 /* Timer configuration commands (generic osmo_tdef API) */
2078 osmo_tdef_vty_groups_init(MSC_NODE, msc_tdef_group);
2079
Pau Espin Pedrolb44cf2d2022-10-17 18:09:15 +02002080 /* Deprecated: Old MGCP config without pooling support in MSC node: */
Pau Espin Pedrol9e3bab92023-06-13 19:57:57 +02002081 mgcp_client_vty_init(msc_network, MSC_NODE, msc_network->mgw.conf);
Pau Espin Pedrolb44cf2d2022-10-17 18:09:15 +02002082
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002083#ifdef BUILD_IU
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002084 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 +02002085#endif
Harald Welte0df904d2018-12-03 11:00:04 +01002086 sgs_vty_init();
Harald Welte1a62db22022-05-17 12:06:58 +02002087 smsc_vty_init(msc_network);
Andreas Eversbergf8ac7342023-04-23 12:22:25 +02002088 asci_vty_init(msc_network);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002089
Stefan Sperling617ac802018-02-22 17:58:20 +01002090 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002091
2092 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
2093
2094 install_element_ve(&show_subscr_cmd);
2095 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01002096 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002097 install_element_ve(&show_msc_conn_cmd);
2098 install_element_ve(&show_msc_transaction_cmd);
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +02002099 install_element_ve(&show_nri_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002100
2101 install_element_ve(&sms_send_pend_cmd);
2102 install_element_ve(&sms_delete_expired_cmd);
2103
2104 install_element_ve(&subscriber_create_cmd);
2105 install_element_ve(&subscriber_send_sms_cmd);
2106 install_element_ve(&subscriber_silent_sms_cmd);
2107 install_element_ve(&subscriber_silent_call_start_cmd);
2108 install_element_ve(&subscriber_silent_call_stop_cmd);
2109 install_element_ve(&subscriber_ussd_notify_cmd);
2110 install_element_ve(&subscriber_mstest_close_cmd);
2111 install_element_ve(&subscriber_mstest_open_cmd);
2112 install_element_ve(&subscriber_paging_cmd);
2113 install_element_ve(&show_stats_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002114 install_element_ve(&logging_fltr_imsi_cmd);
2115
2116 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002117 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01002118 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002119
2120 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
2121 install_node(&mncc_int_node, config_write_mncc_int);
2122 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
2123 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
2124
2125 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
2126
2127 install_element(CONFIG_NODE, &cfg_hlr_cmd);
2128 install_node(&hlr_node, config_write_hlr);
2129 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
2130 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002131 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002132}