blob: 20321356ff8b6ac89908219d30254c54b8ea72e9 [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,
135 "short name NAME",
136 "Set the short GSM network name\n" NAME_CMD_STR NAME_STR)
137{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100138 osmo_talloc_replace_string(gsmnet, &gsmnet->name_short, argv[0]);
139 return CMD_SUCCESS;
140}
141
142DEFUN(cfg_net_name_long,
143 cfg_net_name_long_cmd,
144 "long name NAME",
145 "Set the long GSM network name\n" NAME_CMD_STR NAME_STR)
146{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100147 osmo_talloc_replace_string(gsmnet, &gsmnet->name_long, argv[0]);
148 return CMD_SUCCESS;
149}
150
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200151#define ENCRYPTION_STR "Encryption options\n"
152
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100153DEFUN(cfg_net_encryption,
154 cfg_net_encryption_cmd,
Eric Wilda7f80202021-06-09 04:04:06 +0200155 "encryption a5 <0-4> [<0-4>] [<0-4>] [<0-4>] [<0-4>]",
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200156 ENCRYPTION_STR
157 "GSM A5 Air Interface Encryption.\n"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100158 "A5/n Algorithm Number\n"
159 "A5/n Algorithm Number\n"
160 "A5/n Algorithm Number\n"
Eric Wilda7f80202021-06-09 04:04:06 +0200161 "A5/n Algorithm Number\n"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100162 "A5/n Algorithm Number\n")
163{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100164 unsigned int i;
165
166 gsmnet->a5_encryption_mask = 0;
167 for (i = 0; i < argc; i++)
168 gsmnet->a5_encryption_mask |= (1 << atoi(argv[i]));
169
170 return CMD_SUCCESS;
171}
172
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200173DEFUN(cfg_net_encryption_uea,
174 cfg_net_encryption_uea_cmd,
175 "encryption uea <0-2> [<0-2>] [<0-2>]",
176 ENCRYPTION_STR
Harald Welte505a94a2021-02-06 17:12:20 +0100177 "UTRAN (3G) encryption algorithms to allow: 0 = UEA0 (no encryption), 1 = UEA1, 2 = UEA2.\n"
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200178 "UEAn Algorithm Number\n"
179 "UEAn Algorithm Number\n"
180 "UEAn Algorithm Number\n"
181 )
182{
183 unsigned int i;
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200184
Harald Welte505a94a2021-02-06 17:12:20 +0100185 gsmnet->uea_encryption_mask = 0;
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200186 for (i = 0; i < argc; i++)
Harald Welte505a94a2021-02-06 17:12:20 +0100187 gsmnet->uea_encryption_mask |= (1 << atoi(argv[i]));
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200188
189 return CMD_SUCCESS;
190}
191
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100192DEFUN(cfg_net_authentication,
193 cfg_net_authentication_cmd,
194 "authentication (optional|required)",
195 "Whether to enforce MS authentication in 2G\n"
196 "Allow MS to attach via 2G BSC without authentication\n"
197 "Always do authentication\n")
198{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100199 gsmnet->authentication_required = (argv[0][0] == 'r') ? true : false;
200
201 return CMD_SUCCESS;
202}
203
204DEFUN(cfg_net_rrlp_mode, cfg_net_rrlp_mode_cmd,
205 "rrlp mode (none|ms-based|ms-preferred|ass-preferred)",
206 "Radio Resource Location Protocol\n"
207 "Set the Radio Resource Location Protocol Mode\n"
208 "Don't send RRLP request\n"
209 "Request MS-based location\n"
210 "Request any location, prefer MS-based\n"
211 "Request any location, prefer MS-assisted\n")
212{
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700213 gsmnet->rrlp.mode = msc_rrlp_mode_parse(argv[0]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100214
215 return CMD_SUCCESS;
216}
217
218DEFUN(cfg_net_mm_info, cfg_net_mm_info_cmd,
219 "mm info (0|1)",
220 "Mobility Management\n"
221 "Send MM INFO after LOC UPD ACCEPT\n"
222 "Disable\n" "Enable\n")
223{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100224 gsmnet->send_mm_info = atoi(argv[0]);
225
226 return CMD_SUCCESS;
227}
228
229DEFUN(cfg_net_timezone,
230 cfg_net_timezone_cmd,
231 "timezone <-19-19> (0|15|30|45)",
232 "Set the Timezone Offset of the network\n"
233 "Timezone offset (hours)\n"
234 "Timezone offset (00 minutes)\n"
235 "Timezone offset (15 minutes)\n"
236 "Timezone offset (30 minutes)\n"
237 "Timezone offset (45 minutes)\n"
238 )
239{
240 struct gsm_network *net = vty->index;
241 int tzhr = atoi(argv[0]);
242 int tzmn = atoi(argv[1]);
243
244 net->tz.hr = tzhr;
245 net->tz.mn = tzmn;
246 net->tz.dst = 0;
247 net->tz.override = 1;
248
249 return CMD_SUCCESS;
250}
251
252DEFUN(cfg_net_timezone_dst,
253 cfg_net_timezone_dst_cmd,
254 "timezone <-19-19> (0|15|30|45) <0-2>",
255 "Set the Timezone Offset of the network\n"
256 "Timezone offset (hours)\n"
257 "Timezone offset (00 minutes)\n"
258 "Timezone offset (15 minutes)\n"
259 "Timezone offset (30 minutes)\n"
260 "Timezone offset (45 minutes)\n"
261 "DST offset (hours)\n"
262 )
263{
264 struct gsm_network *net = vty->index;
265 int tzhr = atoi(argv[0]);
266 int tzmn = atoi(argv[1]);
267 int tzdst = atoi(argv[2]);
268
269 net->tz.hr = tzhr;
270 net->tz.mn = tzmn;
271 net->tz.dst = tzdst;
272 net->tz.override = 1;
273
274 return CMD_SUCCESS;
275}
276
277DEFUN(cfg_net_no_timezone,
278 cfg_net_no_timezone_cmd,
279 "no timezone",
280 NO_STR
281 "Disable network timezone override, use system tz\n")
282{
283 struct gsm_network *net = vty->index;
284
285 net->tz.override = 0;
286
287 return CMD_SUCCESS;
288}
289
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700290/* NOTE: actually this is subscriber expiration timeout */
291#define PER_LOC_UPD_STR "Periodic Location Updating Interval\n"
292
293DEFUN_DEPRECATED(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
294 "periodic location update <6-1530>",
295 PER_LOC_UPD_STR PER_LOC_UPD_STR PER_LOC_UPD_STR
296 "Periodic Location Updating Interval in Minutes\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100297{
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700298 int minutes = atoi(argv[0]);
299 int rc;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100300
Vadim Yanitskiy9a282302021-11-28 03:44:13 +0300301 vty_out(vty, "%% 'periodic location update' is now deprecated. "
302 "Use 'msc' / 'timer vlr T3212' to change subscriber expiration "
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700303 "timeout.%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100304
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700305 /* We used to double this value and add a minute when scheduling the
306 * expiration timer. Let's emulate the old behaviour here. */
307 minutes = minutes * 2 + 1;
308 vty_out(vty, "%% Setting T3212 to %d minutes "
309 "(emulating the old behaviour).%s",
310 minutes, VTY_NEWLINE);
311
312 rc = osmo_tdef_set(msc_tdefs_vlr, 3212, minutes, OSMO_TDEF_M);
313 return rc ? CMD_WARNING : CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100314}
315
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700316DEFUN_DEPRECATED(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
317 "no periodic location update",
318 NO_STR PER_LOC_UPD_STR PER_LOC_UPD_STR PER_LOC_UPD_STR)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100319{
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700320 int rc;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100321
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700322 vty_out(vty, "%% 'periodic location update' is now deprecated: "
323 "use 'timer T3212' to change subscriber expiration "
324 "timeout.%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100325
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700326 rc = osmo_tdef_set(msc_tdefs_vlr, 3212, 0, OSMO_TDEF_M);
327 return rc ? CMD_WARNING : CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100328}
329
Keith Whyte991bb422019-08-08 15:43:40 +0200330DEFUN(cfg_net_call_wait, cfg_net_call_wait_cmd,
331 "call-waiting",
332 "Enable Call Waiting on the Network\n")
333{
334 struct gsm_network *net = vty->index;
335
336 net->call_waiting = true;
337
338 return CMD_SUCCESS;
339}
340
341DEFUN(cfg_net_no_call_wait, cfg_net_no_call_wait_cmd,
342 "no call-waiting",
343 NO_STR
344 "Disable Call Waiting on the Network\n")
345{
346 struct gsm_network *net = vty->index;
347
348 net->call_waiting = false;
349
350 return CMD_SUCCESS;
351}
352
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100353static int config_write_net(struct vty *vty)
354{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100355 int i;
356
357 vty_out(vty, "network%s", VTY_NEWLINE);
358 vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
359 vty_out(vty, " mobile network code %s%s",
360 osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
361 vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
362 vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
363 vty_out(vty, " encryption a5");
364 for (i = 0; i < 8; i++) {
365 if (gsmnet->a5_encryption_mask & (1 << i))
366 vty_out(vty, " %u", i);
367 }
368 vty_out(vty, "%s", VTY_NEWLINE);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200369
Harald Welte505a94a2021-02-06 17:12:20 +0100370 vty_out(vty, " encryption uea");
371 for (i = 0; i < 8; i++) {
372 if (gsmnet->uea_encryption_mask & (1 << i))
373 vty_out(vty, " %u", i);
374 }
375 vty_out(vty, "%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100376 vty_out(vty, " authentication %s%s",
377 gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE);
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700378 vty_out(vty, " rrlp mode %s%s", msc_rrlp_mode_name(gsmnet->rrlp.mode),
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100379 VTY_NEWLINE);
380 vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
381 if (gsmnet->tz.override != 0) {
382 if (gsmnet->tz.dst)
383 vty_out(vty, " timezone %d %d %d%s",
384 gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
385 VTY_NEWLINE);
386 else
387 vty_out(vty, " timezone %d %d%s",
388 gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
389 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100390
Keith Whyte991bb422019-08-08 15:43:40 +0200391 if (!gsmnet->call_waiting)
392 vty_out(vty, " no call-waiting%s", VTY_NEWLINE);
393
Pau Espin Pedrol53639ea2022-10-18 14:33:15 +0200394 mgcp_client_pool_config_write(vty, " ");
395
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100396 return CMD_SUCCESS;
397}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200398
399static struct cmd_node msc_node = {
400 MSC_NODE,
401 "%s(config-msc)# ",
402 1,
403};
404
405DEFUN(cfg_msc, cfg_msc_cmd,
406 "msc", "Configure MSC options")
407{
408 vty->node = MSC_NODE;
409 return CMD_SUCCESS;
410}
411
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100412#define MNCC_STR "Configure Mobile Network Call Control\n"
413#define MNCC_GUARD_TIMEOUT_STR "Set global guard timer for mncc interface activity\n"
414#define MNCC_GUARD_TIMEOUT_VALUE_STR "guard timer value (sec.)\n"
415
Harald Welte1a62db22022-05-17 12:06:58 +0200416DEFUN_DEPRECATED(cfg_sms_database, cfg_sms_database_cmd,
Keith Whyte1587ffb2020-08-28 13:36:58 +0200417 "sms-database PATH",
418 "Set the path to the MSC-SMS database file\n"
419 "Relative or absolute file system path to the database file (default is '" SMS_DEFAULT_DB_FILE_PATH "')\n")
420{
Harald Welted302bb12022-05-17 13:31:14 +0200421 osmo_talloc_replace_string(gsmnet, &gsmnet->sms_queue_cfg->db_file_path, argv[0]);
Keith Whyte1587ffb2020-08-28 13:36:58 +0200422 return CMD_SUCCESS;
423}
424
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100425DEFUN(cfg_msc_mncc_internal,
426 cfg_msc_mncc_internal_cmd,
427 "mncc internal",
428 MNCC_STR "Use internal MNCC handler (default; changes need a program restart)\n")
429{
430 gsm_network_set_mncc_sock_path(gsmnet, NULL);
431 return CMD_SUCCESS;
432}
433
434DEFUN(cfg_msc_mncc_external,
435 cfg_msc_mncc_external_cmd,
436 "mncc external MNCC_SOCKET_PATH",
437 MNCC_STR "Use external MNCC handler (changes need a program restart)\n"
438 "File system path to create the MNCC unix domain socket at\n")
439{
440 gsm_network_set_mncc_sock_path(gsmnet, argv[0]);
441 return CMD_SUCCESS;
442}
443
Philipp Maier9ca7b312018-10-10 17:00:49 +0200444DEFUN(cfg_msc_mncc_guard_timeout,
445 cfg_msc_mncc_guard_timeout_cmd,
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100446 "mncc guard-timeout <0-255>",
447 MNCC_STR
448 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR)
Philipp Maier9ca7b312018-10-10 17:00:49 +0200449{
450 gsmnet->mncc_guard_timeout = atoi(argv[0]);
451 return CMD_SUCCESS;
452}
453
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100454ALIAS_DEPRECATED(cfg_msc_mncc_guard_timeout,
455 cfg_msc_deprecated_mncc_guard_timeout_cmd,
456 "mncc-guard-timeout <0-255>",
457 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR);
458
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700459#define NCSS_STR "Configure call independent Supplementary Services\n"
460
461DEFUN(cfg_msc_ncss_guard_timeout,
462 cfg_msc_ncss_guard_timeout_cmd,
463 "ncss guard-timeout <0-255>",
464 NCSS_STR "Set guard timer for session activity\n"
465 "guard timer value (sec.), or 0 to disable\n")
466{
467 gsmnet->ncss_guard_timeout = atoi(argv[0]);
468 return CMD_SUCCESS;
469}
470
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200471DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
472 "assign-tmsi",
473 "Assign TMSI during Location Updating.\n")
474{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200475 gsmnet->vlr->cfg.assign_tmsi = true;
476 return CMD_SUCCESS;
477}
478
479DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
480 "no assign-tmsi",
481 NO_STR "Assign TMSI during Location Updating.\n")
482{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200483 gsmnet->vlr->cfg.assign_tmsi = false;
484 return CMD_SUCCESS;
485}
486
Keith Whytea1a70be2021-05-16 02:59:52 +0200487DEFUN_ATTR(cfg_msc_lcls_disable, cfg_msc_lcls_disable_cmd,
488 "lcls-permitted",
489 "Globally allow LCLS (Local Call Local Switch) for all calls on this MSC.\n",
490 CMD_ATTR_IMMEDIATE)
491{
492 gsmnet->lcls_permitted = true;
493 return CMD_SUCCESS;
494}
495
496DEFUN_ATTR(cfg_msc_no_lcls_disable, cfg_msc_no_lcls_disable_cmd,
497 "no lcls-permitted",
498 NO_STR "Globally disable LCLS (Local Call Local Switch) for all calls on this MSC.\n",
499 CMD_ATTR_IMMEDIATE)
500{
501 gsmnet->lcls_permitted = false;
502 return CMD_SUCCESS;
503}
504
Philipp Maierfbf66102017-04-09 12:32:51 +0200505DEFUN(cfg_msc_cs7_instance_a,
506 cfg_msc_cs7_instance_a_cmd,
507 "cs7-instance-a <0-15>",
508 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
509{
Philipp Maierfbf66102017-04-09 12:32:51 +0200510 gsmnet->a.cs7_instance = atoi(argv[0]);
511 return CMD_SUCCESS;
512}
513
514DEFUN(cfg_msc_cs7_instance_iu,
515 cfg_msc_cs7_instance_iu_cmd,
516 "cs7-instance-iu <0-15>",
517 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
518{
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100519#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200520 gsmnet->iu.cs7_instance = atoi(argv[0]);
521 return CMD_SUCCESS;
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100522#else
523 vty_out(vty, "WARNING: 'cs7-instance-iu' without effect: built without Iu support%s",
524 VTY_NEWLINE);
525 return CMD_WARNING;
526#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200527}
528
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100529DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
530 "auth-tuple-max-reuse-count <-1-2147483647>",
531 "Configure authentication tuple re-use\n"
532 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
533{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100534 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
535 return CMD_SUCCESS;
536}
537
538DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
539 "auth-tuple-reuse-on-error (0|1)",
540 "Configure authentication tuple re-use when HLR is not responsive\n"
Oliver Smithd6e24fd2019-01-09 10:46:43 +0100541 "Never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
542 "If the HLR does not deliver new tuples, do re-use already available old ones.\n")
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100543{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100544 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
545 return CMD_SUCCESS;
546}
547
Oliver Smith0fec28a2018-12-14 10:52:52 +0100548DEFUN(cfg_msc_check_imei_rqd, cfg_msc_check_imei_rqd_cmd,
Oliver Smith03ded912019-05-02 10:40:50 +0200549 "check-imei-rqd (0|1|early)",
Oliver Smith0fec28a2018-12-14 10:52:52 +0100550 "Send each IMEI to the EIR to ask if it is permitted or not. The EIR is implemented as part of OsmoHLR, "
551 "and can optionally save the IMEI in the HLR.\n"
552 "Do not send IMEIs to the EIR\n"
Oliver Smith03ded912019-05-02 10:40:50 +0200553 "Send each IMEI to the EIR\n"
554 "Send each IMEI to the EIR, and do it at the start of the location update. This allows the EIR to receive the"
555 " 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 +0100556{
Oliver Smith03ded912019-05-02 10:40:50 +0200557 if (strcmp(argv[0], "0") == 0) {
558 gsmnet->vlr->cfg.check_imei_rqd = false;
559 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
560 } else if (strcmp(argv[0], "1") == 0) {
561 gsmnet->vlr->cfg.check_imei_rqd = true;
562 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
563 } else if (strcmp(argv[0], "early") == 0) {
564 gsmnet->vlr->cfg.check_imei_rqd = true;
565 gsmnet->vlr->cfg.retrieve_imeisv_early = true;
566 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100567 return CMD_SUCCESS;
568}
569
Alexander Couzensae167fc2020-09-25 05:25:16 +0200570DEFUN_DEPRECATED(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100571 "paging response-timer (default|<1-65535>)",
572 "Configure Paging\n"
573 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
574 " BSS or RNC\n"
575 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
576 "Set paging timeout in seconds\n")
577{
Alexander Couzensae167fc2020-09-25 05:25:16 +0200578 int rat;
579 int paging_response_timer;
Pau Espin Pedrolb08a3802019-09-16 19:01:37 +0200580 if (!strcmp(argv[0], "default"))
Alexander Couzensae167fc2020-09-25 05:25:16 +0200581 paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100582 else
Alexander Couzensae167fc2020-09-25 05:25:16 +0200583 paging_response_timer = atoi(argv[0]);
584
585 for (rat = 0; rat < OSMO_RAT_COUNT; rat++) {
586 osmo_tdef_set(msc_ran_infra[rat].tdefs, -4, paging_response_timer, OSMO_TDEF_S);
587 }
588
589 vty_out(vty, "%% paging response-timer is deprecated.%s"
590 "%% All ran timer has been modified.%s"
591 "%% use 'timer <geran|utran|sgs> X4 %s' instead%s",
592 VTY_NEWLINE, VTY_NEWLINE, argv[0], VTY_NEWLINE);
593
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100594 return CMD_SUCCESS;
595}
596
Harald Welte69c54a82018-02-09 20:41:14 +0100597DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
598 "emergency-call route-to-msisdn MSISDN",
599 "Configure Emergency Call Behaviour\n"
600 "MSISDN to which Emergency Calls are Dispatched\n"
601 "MSISDN (E.164 Phone Number)\n")
602{
Harald Welte69c54a82018-02-09 20:41:14 +0100603 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
604
605 return CMD_SUCCESS;
606}
607
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700608/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
609DEFUN(cfg_msc_sms_over_gsup, cfg_msc_sms_over_gsup_cmd,
610 "sms-over-gsup",
611 "Enable routing of SMS messages over GSUP\n")
612{
613 gsmnet->sms_over_gsup = true;
614 return CMD_SUCCESS;
615}
616
617/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
618DEFUN(cfg_msc_no_sms_over_gsup, cfg_msc_no_sms_over_gsup_cmd,
619 "no sms-over-gsup",
620 NO_STR "Disable routing of SMS messages over GSUP\n")
621{
622 gsmnet->sms_over_gsup = false;
623 return CMD_SUCCESS;
624}
625
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100626/* FIXME: This should rather be in the form of
627 * handover-number range 001234xxx
628 * and
629 * handover-number range 001234xxx FIRST LAST
630 */
631DEFUN(cfg_msc_handover_number_range, cfg_msc_handover_number_range_cmd,
632 "handover-number range MSISDN_FIRST MSISDN_LAST",
633 "Configure a range of MSISDN to be assigned to incoming inter-MSC Handovers for call forwarding.\n"
634 "Configure a handover number range\n"
635 "First Handover Number MSISDN\n"
636 "Last Handover Number MSISDN\n")
637{
638 char *endp;
639 uint64_t range_start;
640 uint64_t range_end;
641
642 /* FIXME leading zeros?? */
643
644 errno = 0;
645 range_start = strtoull(argv[0], &endp, 10);
646 if (errno || *endp != '\0') {
647 vty_out(vty, "%% Error parsing handover-number range start: %s%s",
648 argv[0], VTY_NEWLINE);
649 return CMD_WARNING;
650 }
651
652 errno = 0;
653 range_end = strtoull(argv[1], &endp, 10);
654 if (errno || *endp != '\0') {
655 vty_out(vty, "%% Error parsing handover-number range end: %s%s",
656 argv[1], VTY_NEWLINE);
657 return CMD_WARNING;
658 }
659
660 if (range_start > range_end) {
661 vty_out(vty, "%% Error: handover-number range end must be > than the range start, but"
662 " %"PRIu64" > %"PRIu64"%s", range_start, range_end, VTY_NEWLINE);
663 return CMD_WARNING;
664 }
665
666 gsmnet->handover_number.range_start = range_start;
667 gsmnet->handover_number.range_end = range_end;
668 return CMD_SUCCESS;
669}
670
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200671#define OSMUX_STR "RTP multiplexing\n"
672DEFUN(cfg_msc_osmux,
673 cfg_msc_osmux_cmd,
674 "osmux (on|off|only)",
675 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
676{
677 if (strcmp(argv[0], "off") == 0)
678 gsmnet->use_osmux = OSMUX_USAGE_OFF;
679 else if (strcmp(argv[0], "on") == 0)
680 gsmnet->use_osmux = OSMUX_USAGE_ON;
681 else if (strcmp(argv[0], "only") == 0)
682 gsmnet->use_osmux = OSMUX_USAGE_ONLY;
683
684 return CMD_SUCCESS;
685}
686
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +0200687#define NRI_STR "Mapping of Network Resource Indicators to this MSC, for MSC pooling\n"
688DEFUN(cfg_msc_nri_bitlen, cfg_msc_nri_bitlen_cmd,
689 "nri bitlen <0-15>",
690 NRI_STR
691 "Set number of NRI bits to place in TMSI identities (always starting just after the most significant octet)\n"
692 "bit count (default: " OSMO_STRINGIFY_VAL(NRI_BITLEN_DEFAULT) ")\n")
693{
694 gsmnet->vlr->cfg.nri_bitlen = atoi(argv[0]);
695 return CMD_SUCCESS;
696}
697
698#define NRI_STR "Mapping of Network Resource Indicators to this MSC, for MSC pooling\n"
699#define NRI_ARGS_TO_STR_FMT "%s%s%s"
700#define NRI_ARGS_TO_STR_ARGS(ARGC, ARGV) ARGV[0], (ARGC>1)? ".." : "", (ARGC>1)? ARGV[1] : ""
701#define NRI_FIRST_LAST_STR "First value of the NRI value range, should not surpass the configured 'nri bitlen'.\n" \
702 "Last value of the NRI value range, should not surpass the configured 'nri bitlen' and be larger than the" \
703 " first value; if omitted, apply only the first value.\n"
704
705DEFUN(cfg_msc_nri_add, cfg_msc_nri_add_cmd,
706 "nri add <0-32767> [<0-32767>]",
707 NRI_STR "Add NRI value or range to the NRI mapping for this MSC\n"
708 NRI_FIRST_LAST_STR)
709{
710 const char *message;
711 int rc = osmo_nri_ranges_vty_add(&message, NULL, gsmnet->vlr->cfg.nri_ranges, argc, argv, gsmnet->vlr->cfg.nri_bitlen);
712 if (message) {
713 vty_out(vty, "%% %s: " NRI_ARGS_TO_STR_FMT, message, NRI_ARGS_TO_STR_ARGS(argc, argv));
714 }
715 if (rc < 0)
716 return CMD_WARNING;
717 return CMD_SUCCESS;
718}
719
720DEFUN(cfg_msc_nri_del, cfg_msc_nri_del_cmd,
721 "nri del <0-32767> [<0-32767>]",
722 NRI_STR "Remove NRI value or range from the NRI mapping for this MSC\n"
723 NRI_FIRST_LAST_STR)
724{
725 const char *message;
726 int rc = osmo_nri_ranges_vty_del(&message, NULL, gsmnet->vlr->cfg.nri_ranges, argc, argv);
727 if (message) {
728 vty_out(vty, "%% %s: " NRI_ARGS_TO_STR_FMT, message, NRI_ARGS_TO_STR_ARGS(argc, argv));
729 }
730 if (rc < 0)
731 return CMD_WARNING;
732 return CMD_SUCCESS;
733}
734
735static void msc_write_nri(struct vty *vty)
736{
737 struct osmo_nri_range *r;
738
739 llist_for_each_entry(r, &gsmnet->vlr->cfg.nri_ranges->entries, entry) {
740 if (osmo_nri_range_validate(r, 255))
741 vty_out(vty, " %% INVALID RANGE:");
742 vty_out(vty, " nri add %d", r->first);
743 if (r->first != r->last)
744 vty_out(vty, " %d", r->last);
745 vty_out(vty, "%s", VTY_NEWLINE);
746 }
747}
748
749DEFUN(show_nri, show_nri_cmd,
750 "show nri",
751 SHOW_STR NRI_STR)
752{
753 msc_write_nri(vty);
754 return CMD_SUCCESS;
755}
756
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200757static int config_write_msc(struct vty *vty)
758{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200759 vty_out(vty, "msc%s", VTY_NEWLINE);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100760 if (gsmnet->mncc_sock_path)
761 vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE);
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100762 vty_out(vty, " mncc guard-timeout %i%s",
Philipp Maier9ca7b312018-10-10 17:00:49 +0200763 gsmnet->mncc_guard_timeout, VTY_NEWLINE);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700764 vty_out(vty, " ncss guard-timeout %i%s",
765 gsmnet->ncss_guard_timeout, VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200766 vty_out(vty, " %sassign-tmsi%s",
767 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
Keith Whytea1a70be2021-05-16 02:59:52 +0200768 if (gsmnet->lcls_permitted)
769 vty_out(vty, " lcls-permitted%s", VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200770
Philipp Maierfbf66102017-04-09 12:32:51 +0200771 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
772 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100773#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200774 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
775 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100776#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200777
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100778 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
779 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
780 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
781 VTY_NEWLINE);
782 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
783 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
784 VTY_NEWLINE);
785
Oliver Smith03ded912019-05-02 10:40:50 +0200786 if (gsmnet->vlr->cfg.check_imei_rqd) {
787 if (gsmnet->vlr->cfg.retrieve_imeisv_early)
788 vty_out(vty, " check-imei-rqd early%s", VTY_NEWLINE);
789 else
790 vty_out(vty, " check-imei-rqd 1%s", VTY_NEWLINE);
791 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100792
Harald Welte69c54a82018-02-09 20:41:14 +0100793 if (gsmnet->emergency.route_to_msisdn) {
794 vty_out(vty, " emergency-call route-to-msisdn %s%s",
795 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
796 }
797
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700798 if (gsmnet->sms_over_gsup)
799 vty_out(vty, " sms-over-gsup%s", VTY_NEWLINE);
800
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100801 if (gsmnet->handover_number.range_start || gsmnet->handover_number.range_end)
802 vty_out(vty, " handover-number range %"PRIu64" %"PRIu64"%s",
803 gsmnet->handover_number.range_start, gsmnet->handover_number.range_end,
804 VTY_NEWLINE);
805
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200806 if (gsmnet->use_osmux != OSMUX_USAGE_OFF) {
807 vty_out(vty, " osmux %s%s", gsmnet->use_osmux == OSMUX_USAGE_ON ? "on" : "only",
808 VTY_NEWLINE);
809 }
810
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200811 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200812#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200813 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200814#endif
815
Neels Hofmeyr880b9502019-05-09 02:01:55 +0200816 neighbor_ident_vty_write(vty);
817
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +0700818 /* Timer introspection commands (generic osmo_tdef API) */
819 osmo_tdef_vty_groups_write(vty, " ");
820
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +0200821 msc_write_nri(vty);
822
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200823 return CMD_SUCCESS;
824}
825
Maxc51609a2018-11-09 17:13:00 +0100826DEFUN(show_bsc, show_bsc_cmd,
827 "show bsc", SHOW_STR "BSC\n")
828{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100829 struct ran_peer *rp;
830 llist_for_each_entry(rp, &gsmnet->a.sri->ran_peers, entry) {
831 vty_out(vty, "BSC %s %s%s",
832 osmo_sccp_inst_addr_name(gsmnet->a.sri->sccp, &rp->peer_addr),
833 osmo_fsm_inst_state_name(rp->fi),
834 VTY_NEWLINE);
Maxc51609a2018-11-09 17:13:00 +0100835 }
836
837 return CMD_SUCCESS;
838}
839
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100840static const char *get_trans_proto_str(const struct gsm_trans *trans)
841{
842 static char buf[256];
843
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100844 switch (trans->type) {
845 case TRANS_CC:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100846 snprintf(buf, sizeof(buf), "%s %4u %4u",
847 gsm48_cc_state_name(trans->cc.state),
848 trans->cc.Tcurrent,
849 trans->cc.T308_second);
850 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100851 case TRANS_SMS:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700852 snprintf(buf, sizeof(buf), "CP:%s RP:%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100853 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
854 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
855 break;
856 default:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700857 return NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100858 }
859
860 return buf;
861}
862
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700863/* Prefix a given format string with a given amount of spaces */
864#define MSC_VTY_DUMP(vty, offset, fmt, args...) \
865 vty_out(vty, "%*s" fmt, offset, "", ##args)
866
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200867/* Print value of a named flag, prefixed with a given amount of spaces */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700868#define MSC_VTY_DUMP_FLAG(vty, offset, name, flag) \
869 MSC_VTY_DUMP(vty, offset + 2, "%s: %*s%s%s", \
870 name, 30 - (int)strlen(name), "", \
871 flag ? "true" : "false", \
872 VTY_NEWLINE)
873
874enum msc_vty_dump_flags {
875 MSC_VTY_DUMP_F_SUBSCR = (1 << 0),
876 MSC_VTY_DUMP_F_CONNECTION = (1 << 1),
877 MSC_VTY_DUMP_F_TRANSACTION = (1 << 2),
878};
879
880static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans,
881 int offset, uint8_t dump_flags)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100882{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700883 const char *proto_str;
884
885 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
886 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
887 vlr_subscr_name(msc_a_vsub(trans->msc_a)),
888 VTY_NEWLINE);
889 }
890
891 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200892 /* (If msc_a exists, there *must* be a non-null msc_a->c.msub) */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700893 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
894 trans->msc_a ? msub_ran_conn_name(trans->msc_a->c.msub)
895 : "(not established)",
896 VTY_NEWLINE);
897 }
898
899 MSC_VTY_DUMP(vty, offset, "Unique (global) identifier: 0x%08x%s",
900 trans->callref, VTY_NEWLINE);
901 MSC_VTY_DUMP(vty, offset, "GSM 04.07 identifier (%s): %u%s",
902 (trans->transaction_id & 0x08) ? "MO" : "MT",
903 trans->transaction_id,
904 VTY_NEWLINE);
905
906 MSC_VTY_DUMP(vty, offset, "Type: %s%s",
907 trans_type_name(trans->type),
908 VTY_NEWLINE);
909
910 if ((proto_str = get_trans_proto_str(trans))) {
911 MSC_VTY_DUMP(vty, offset, "Protocol specific: %s%s",
912 proto_str, VTY_NEWLINE);
913 }
914}
915
916static void vty_dump_one_conn(struct vty *vty, const struct msub *msub,
917 int offset, uint8_t dump_flags)
918{
919 struct vlr_subscr *vsub = msub_vsub(msub);
920 struct msc_a *msc_a = msub_msc_a(msub);
921 char buf[128];
922
923 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
924 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
925 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
926 vlr_subscr_name(vsub),
927 VTY_NEWLINE);
928 }
929
930 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
931 msub_ran_conn_name(msub),
932 VTY_NEWLINE);
933 MSC_VTY_DUMP(vty, offset, "RAN connection state: %s%s",
934 osmo_fsm_inst_state_name(msc_a->c.fi),
935 VTY_NEWLINE);
936
937 if (vsub) {
938 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
Neels Hofmeyr41c03332020-06-24 15:02:27 +0200939 msc_a->via_cell.lai.lac, msc_a->via_cell.cell_identity,
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700940 VTY_NEWLINE);
941 }
942
943 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
944 osmo_use_count_total(&msc_a->use_count),
945 VTY_NEWLINE);
946 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
947 osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count),
948 VTY_NEWLINE);
949
950 /* Transactions of this connection */
951 if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
952 struct gsm_trans *trans;
953 unsigned int i = 0;
954
955 /* Both subscriber and connection info is already printed */
956 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_CONNECTION;
957 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
958
959 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
960 if (trans->msc_a != msc_a)
961 continue;
962 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
963 i++, VTY_NEWLINE);
964 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
965 }
966 }
967}
968
969static void vty_dump_one_subscr(struct vty *vty, struct vlr_subscr *vsub,
970 int offset, uint8_t dump_flags)
971{
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700972 struct timespec now;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700973 char buf[128];
974
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700975 if (vsub->name[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700976 MSC_VTY_DUMP(vty, offset, "Name: '%s'%s",
977 vsub->name, VTY_NEWLINE);
978 }
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700979 if (vsub->msisdn[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700980 MSC_VTY_DUMP(vty, offset, "MSISDN: %s%s",
981 vsub->msisdn, VTY_NEWLINE);
982 }
983
984 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
985 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
986 VTY_NEWLINE);
987 MSC_VTY_DUMP(vty, offset, "RAN type: %s%s",
988 osmo_rat_type_name(vsub->cs.attached_via_ran),
989 VTY_NEWLINE);
990
991 MSC_VTY_DUMP(vty, offset, "IMSI: %s%s",
992 vsub->imsi, VTY_NEWLINE);
993 if (vsub->tmsi != GSM_RESERVED_TMSI) {
994 MSC_VTY_DUMP(vty, offset, "TMSI: %08X%s",
995 vsub->tmsi, VTY_NEWLINE);
996 }
997 if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
998 MSC_VTY_DUMP(vty, offset, "New TMSI: %08X%s",
999 vsub->tmsi_new, VTY_NEWLINE);
1000 }
1001 if (vsub->imei[0] != '\0') {
1002 MSC_VTY_DUMP(vty, offset, "IMEI: %s%s",
1003 vsub->imei, VTY_NEWLINE);
1004 }
1005 if (vsub->imeisv[0] != '\0') {
1006 MSC_VTY_DUMP(vty, offset, "IMEISV: %s%s",
1007 vsub->imeisv, VTY_NEWLINE);
1008 }
1009
1010 MSC_VTY_DUMP(vty, offset, "Flags: %s", VTY_NEWLINE);
1011 MSC_VTY_DUMP_FLAG(vty, offset, "IMSI detached",
1012 vsub->imsi_detached_flag);
1013 MSC_VTY_DUMP_FLAG(vty, offset, "Conf. by radio contact",
1014 vsub->conf_by_radio_contact_ind);
1015 MSC_VTY_DUMP_FLAG(vty, offset, "Subscr. data conf. by HLR",
1016 vsub->sub_dataconf_by_hlr_ind);
1017 MSC_VTY_DUMP_FLAG(vty, offset, "Location conf. in HLR",
1018 vsub->loc_conf_in_hlr_ind);
1019 MSC_VTY_DUMP_FLAG(vty, offset, "Subscriber dormant",
1020 vsub->dormant_ind);
1021 MSC_VTY_DUMP_FLAG(vty, offset, "Received cancel location",
1022 vsub->cancel_loc_rx);
1023 MSC_VTY_DUMP_FLAG(vty, offset, "MS not reachable",
1024 vsub->ms_not_reachable_flag);
1025 MSC_VTY_DUMP_FLAG(vty, offset, "LA allowed",
1026 vsub->la_allowed);
1027
1028 if (vsub->last_tuple) {
1029 struct vlr_auth_tuple *t = vsub->last_tuple;
1030 MSC_VTY_DUMP(vty, offset, "A3A8 last tuple (used %d times): %s",
1031 t->use_count, VTY_NEWLINE);
1032 MSC_VTY_DUMP(vty, offset + 2, "seq # : %d%s",
1033 t->key_seq, VTY_NEWLINE);
1034 MSC_VTY_DUMP(vty, offset + 2, "RAND : %s%s",
1035 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
1036 VTY_NEWLINE);
1037 MSC_VTY_DUMP(vty, offset + 2, "SRES : %s%s",
1038 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
1039 VTY_NEWLINE);
1040 MSC_VTY_DUMP(vty, offset + 2, "Kc : %s%s",
1041 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
1042 VTY_NEWLINE);
1043 }
1044
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +07001045 if (!vlr_timer(vsub->vlr, 3212)) {
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +07001046 MSC_VTY_DUMP(vty, offset, "Expires: never (T3212 is disabled)%s",
1047 VTY_NEWLINE);
1048 } else if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) {
1049 MSC_VTY_DUMP(vty, offset, "Expires: never%s",
1050 VTY_NEWLINE);
1051 } else if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
1052 MSC_VTY_DUMP(vty, offset, "Expires: in %ld min %ld sec%s",
1053 (vsub->expire_lu - now.tv_sec) / 60,
1054 (vsub->expire_lu - now.tv_sec) % 60,
1055 VTY_NEWLINE);
1056 }
1057
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001058 MSC_VTY_DUMP(vty, offset, "Paging: %s paging for %d requests%s",
1059 vsub->cs.is_paging ? "is" : "not",
1060 llist_count(&vsub->cs.requests),
1061 VTY_NEWLINE);
1062
1063 /* SGs related */
1064 MSC_VTY_DUMP(vty, offset, "SGs-state: %s%s",
1065 osmo_fsm_inst_state_name(vsub->sgs_fsm),
1066 VTY_NEWLINE);
1067 MSC_VTY_DUMP(vty, offset, "SGs-MME: %s%s",
Vadim Yanitskiydcf28682019-05-29 22:34:13 +07001068 vsub->sgs.mme_name[0] != '\0' ? vsub->sgs.mme_name : "(none)",
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001069 VTY_NEWLINE);
1070
1071 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
1072 osmo_use_count_total(&vsub->use_count),
1073 VTY_NEWLINE);
1074 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
1075 osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count),
1076 VTY_NEWLINE);
1077
1078 /* Connection(s) and/or transactions of this subscriber */
1079 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
1080 struct msub *msub = msub_for_vsub(vsub);
1081 if (!msub)
1082 return;
1083
1084 /* Subscriber info is already printed */
1085 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
1086
1087 MSC_VTY_DUMP(vty, offset, "Connection: %s", VTY_NEWLINE);
1088 vty_dump_one_conn(vty, msub, offset + 2, dump_flags);
1089 } else if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
1090 struct gsm_trans *trans;
1091 unsigned int i = 0;
1092
1093 /* Subscriber info is already printed */
1094 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
1095 /* Do not print connection info, but mention it */
1096 dump_flags |= MSC_VTY_DUMP_F_CONNECTION;
1097
1098 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1099 if (trans->vsub != vsub)
1100 continue;
1101 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
1102 i++, VTY_NEWLINE);
1103 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
1104 }
1105 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001106}
1107
1108DEFUN(show_msc_transaction, show_msc_transaction_cmd,
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001109 "show transaction",
1110 SHOW_STR "Transactions\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001111{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001112 struct gsm_trans *trans;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001113 uint8_t flags = 0x00;
1114 unsigned int i = 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001115
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001116 flags |= MSC_VTY_DUMP_F_CONNECTION;
1117 flags |= MSC_VTY_DUMP_F_SUBSCR;
1118
1119 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1120 vty_out(vty, " Transaction #%02u: %s", i++, VTY_NEWLINE);
1121 vty_dump_one_trans(vty, trans, 4, flags);
1122 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001123
1124 return CMD_SUCCESS;
1125}
1126
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001127DEFUN(show_msc_conn, show_msc_conn_cmd,
1128 "show connection [trans]",
1129 SHOW_STR "Subscriber Connections\n"
1130 "Show child transactions of each connection\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001131{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001132 uint8_t flags = 0x00;
1133 unsigned int i = 0;
1134 struct msub *msub;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001135
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001136 if (argc > 0)
1137 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1138 flags |= MSC_VTY_DUMP_F_SUBSCR;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001139
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001140 llist_for_each_entry(msub, &msub_list, entry) {
1141 vty_out(vty, " Connection #%02u: %s", i++, VTY_NEWLINE);
1142 vty_dump_one_conn(vty, msub, 4, flags);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001143 }
1144
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001145 return CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001146}
1147
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001148#define SUBSCR_FLAGS "[(conn|trans|conn+trans)]"
1149#define SUBSCR_FLAGS_HELP \
1150 "Show child connections\n" \
1151 "Show child transactions\n" \
1152 "Show child connections and transactions\n"
1153
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001154/* Subscriber */
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001155DEFUN(show_subscr_cache, show_subscr_cache_cmd,
1156 "show subscriber cache " SUBSCR_FLAGS,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001157 SHOW_STR "Show information about subscribers\n"
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001158 "Display contents of subscriber cache\n"
1159 SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001160{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001161 struct vlr_subscr *vsub;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001162 unsigned int count = 0;
1163 uint8_t flags = 0x00;
1164 unsigned int i = 0;
1165
1166 if (argc && strcmp(argv[0], "conn") == 0)
1167 flags |= MSC_VTY_DUMP_F_CONNECTION;
1168 else if (argc && strcmp(argv[0], "trans") == 0)
1169 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1170 else if (argc && strcmp(argv[0], "conn+trans") == 0)
1171 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001172
1173 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
1174 if (++count > 100) {
1175 vty_out(vty, "%% More than %d subscribers in cache,"
1176 " stopping here.%s", count-1, VTY_NEWLINE);
1177 break;
1178 }
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001179 vty_out(vty, " Subscriber #%02u: %s", i++, VTY_NEWLINE);
1180 vty_dump_one_subscr(vty, vsub, 4, flags);
Harald Welte69c54a82018-02-09 20:41:14 +01001181 }
1182
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001183 return CMD_SUCCESS;
1184}
1185
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001186DEFUN(sms_send_pend,
1187 sms_send_pend_cmd,
1188 "sms send pending",
1189 "SMS related commands\n" "SMS Sending related commands\n"
1190 "Send all pending SMS")
1191{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001192 struct gsm_sms *sms;
1193 unsigned long long sms_id = 0;
1194
1195 while (1) {
1196 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1197 if (!sms)
1198 break;
1199
1200 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001201 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001202
1203 sms_id = sms->id + 1;
1204 }
1205
1206 return CMD_SUCCESS;
1207}
1208
1209DEFUN(sms_delete_expired,
1210 sms_delete_expired_cmd,
1211 "sms delete expired",
1212 "SMS related commands\n" "SMS Database related commands\n"
1213 "Delete all expired SMS")
1214{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001215 struct gsm_sms *sms;
1216 unsigned long long sms_id = 0;
1217 long long num_deleted = 0;
1218
1219 while (1) {
1220 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1221 if (!sms)
1222 break;
1223
1224 /* Skip SMS which are currently queued for sending. */
1225 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
1226 continue;
1227
1228 /* Expiration check is performed by the DB layer. */
1229 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
1230 num_deleted++;
1231
1232 sms_id = sms->id + 1;
1233 }
1234
1235 if (num_deleted == 0) {
1236 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
1237 return CMD_WARNING;
1238 }
1239
1240 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
1241 return CMD_SUCCESS;
1242}
1243
1244static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +02001245 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001246 char *str, uint8_t tp_pid)
1247{
1248 struct gsm_network *net = receiver->vlr->user_ctx;
1249 struct gsm_sms *sms;
1250
Harald Welte39b55482018-04-09 19:19:33 +02001251 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Vadim Yanitskiydb4839c2019-12-01 18:52:58 +07001252 if (!sms) {
1253 LOGP(DLSMS, LOGL_ERROR, "Failed to allocate SMS\n");
1254 return CMD_WARNING;
1255 }
1256
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001257 sms->protocol_id = tp_pid;
1258
1259 /* store in database for the queue */
1260 if (db_sms_store(sms) != 0) {
1261 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
1262 sms_free(sms);
1263 return CMD_WARNING;
1264 }
1265 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
1266
1267 sms_free(sms);
1268 sms_queue_trigger(net->sms_queue);
1269 return CMD_SUCCESS;
1270}
1271
1272static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
1273 const char *type,
1274 const char *id)
1275{
1276 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001277 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001278 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001279 return vlr_subscr_find_by_imsi(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001280 else if (!strcmp(type, "tmsi"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001281 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id), VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001282
1283 return NULL;
1284}
1285#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
1286#define SUBSCR_HELP "Operations on a Subscriber\n" \
1287 "Identify subscriber by MSISDN (phone number)\n" \
1288 "Legacy alias for 'msisdn'\n" \
1289 "Identify subscriber by IMSI\n" \
1290 "Identify subscriber by TMSI\n" \
Vadim Yanitskiy3ccd8232019-05-16 01:35:23 +07001291 "Legacy alias for 'imsi'\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001292 "Identifier for the subscriber\n"
1293
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001294DEFUN(show_subscr, show_subscr_cmd,
1295 "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
1296 SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001297{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001298 struct vlr_subscr *vsub;
1299 uint8_t flags = 0x00;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001300
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001301 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001302 if (!vsub) {
1303 vty_out(vty, "%% No subscriber found for %s %s%s",
1304 argv[0], argv[1], VTY_NEWLINE);
1305 return CMD_WARNING;
1306 }
1307
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001308 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
1309 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
1310 * 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 +01001311 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001312
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001313 if (argc > 2 && strcmp(argv[2], "conn") == 0)
1314 flags |= MSC_VTY_DUMP_F_CONNECTION;
1315 else if (argc > 2 && strcmp(argv[2], "trans") == 0)
1316 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1317 else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
1318 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
1319
1320 vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
1321 vty_dump_one_subscr(vty, vsub, 4, flags);
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001322
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001323 return CMD_SUCCESS;
1324}
1325
Vadim Yanitskiyb7ddbf32020-01-20 21:30:09 +07001326DEFUN_DEPRECATED(subscriber_create, subscriber_create_cmd,
1327 "subscriber create imsi ID",
1328 "Operations on a Subscriber\n"
1329 "Create new subscriber\n"
1330 "Identify the subscriber by his IMSI\n"
1331 "Identifier for the subscriber\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001332{
1333 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
1334 VTY_NEWLINE);
1335 return CMD_WARNING;
1336}
1337
1338DEFUN(subscriber_send_pending_sms,
1339 subscriber_send_pending_sms_cmd,
1340 "subscriber " SUBSCR_TYPES " ID sms pending-send",
1341 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
1342{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001343 struct vlr_subscr *vsub;
1344 struct gsm_sms *sms;
1345
1346 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1347 if (!vsub) {
1348 vty_out(vty, "%% No subscriber found for %s %s%s",
1349 argv[0], argv[1], VTY_NEWLINE);
1350 return CMD_WARNING;
1351 }
1352
1353 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
1354 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001355 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001356
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001357 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001358
1359 return CMD_SUCCESS;
1360}
1361
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001362DEFUN(subscriber_sms_delete_all,
1363 subscriber_sms_delete_all_cmd,
1364 "subscriber " SUBSCR_TYPES " ID sms delete-all",
1365 SUBSCR_HELP "SMS Operations\n"
1366 "Delete all SMS to be delivered to this subscriber"
1367 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
1368 " WILL BE LOST.\n")
1369{
1370 struct vlr_subscr *vsub;
1371
1372 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1373 if (!vsub) {
1374 vty_out(vty, "%% No subscriber found for %s %s%s",
1375 argv[0], argv[1], VTY_NEWLINE);
1376 return CMD_WARNING;
1377 }
1378
1379 db_sms_delete_by_msisdn(vsub->msisdn);
1380
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001381 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001382
1383 return CMD_SUCCESS;
1384}
1385
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001386DEFUN(subscriber_send_sms,
1387 subscriber_send_sms_cmd,
1388 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1389 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1390{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001391 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001392 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001393 char *str;
1394 int rc;
1395
1396 if (!vsub) {
1397 vty_out(vty, "%% No subscriber found for %s %s%s",
1398 argv[0], argv[1], VTY_NEWLINE);
1399 rc = CMD_WARNING;
1400 goto err;
1401 }
1402
Harald Welte39b55482018-04-09 19:19:33 +02001403 if (!strcmp(argv[2], "msisdn"))
1404 sender_msisdn = argv[3];
1405 else {
1406 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1407 if (!sender) {
1408 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1409 rc = CMD_WARNING;
1410 goto err;
1411 }
1412 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001413 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001414 }
1415
1416 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001417 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001418 talloc_free(str);
1419
1420err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001421 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001422 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001423
1424 return rc;
1425}
1426
1427DEFUN(subscriber_silent_sms,
1428 subscriber_silent_sms_cmd,
1429
1430 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1431 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1432{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001433 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001434 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001435 char *str;
1436 int rc;
1437
1438 if (!vsub) {
1439 vty_out(vty, "%% No subscriber found for %s %s%s",
1440 argv[0], argv[1], VTY_NEWLINE);
1441 rc = CMD_WARNING;
1442 goto err;
1443 }
1444
Harald Welte39b55482018-04-09 19:19:33 +02001445 if (!strcmp(argv[2], "msisdn")) {
1446 sender_msisdn = argv[3];
1447 } else {
1448 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1449 if (!sender) {
1450 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1451 rc = CMD_WARNING;
1452 goto err;
1453 }
1454 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001455 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001456 }
1457
1458 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001459 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001460 talloc_free(str);
1461
1462err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001463 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001464 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001465
1466 return rc;
1467}
1468
Sylvain Munaut93558302019-02-14 20:13:08 +01001469#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001470#define CHAN_TYPE_HELP \
1471 "Any channel\n" \
1472 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001473 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001474 "Any TCH channel\n" \
1475 "SDCCH channel\n"
1476
Sylvain Munaut93558302019-02-14 20:13:08 +01001477#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1478#define CHAN_MODE_HELP \
1479 "Signalling only\n" \
1480 "Speech with HR codec\n" \
1481 "Speech with FR codec\n" \
1482 "Speech with EFR codec\n" \
1483 "Speech with AMR codec\n"
1484
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001485DEFUN(subscriber_silent_call_start,
1486 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001487 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001488 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001489 CHAN_TYPE_HELP CHAN_MODE_HELP
1490 "Target IP for RTP traffic (default 127.0.0.1)\n"
1491 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001492{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001493 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001494 struct gsm0808_channel_type ct;
1495 const char *ip;
1496 uint16_t port;
1497 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001498
1499 if (!vsub) {
1500 vty_out(vty, "%% No subscriber found for %s %s%s",
1501 argv[0], argv[1], VTY_NEWLINE);
1502 return CMD_WARNING;
1503 }
1504
Sylvain Munaut93558302019-02-14 20:13:08 +01001505 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001506
Sylvain Munaut93558302019-02-14 20:13:08 +01001507 if (!strcmp(argv[3], "signalling")) {
1508 ct.ch_indctr = GSM0808_CHAN_SIGN;
1509 ct.perm_spch[0] = 0; /* Spare but required */
1510 ct.perm_spch_len = 1;
1511 } else if (!strcmp(argv[3], "speech-hr")) {
1512 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1513 ct.perm_spch[0] = GSM0808_PERM_HR1;
1514 ct.perm_spch_len = 1;
1515 } else if (!strcmp(argv[3], "speech-fr")) {
1516 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1517 ct.perm_spch[0] = GSM0808_PERM_FR1;
1518 ct.perm_spch_len = 1;
1519 } else if (!strcmp(argv[3], "speech-efr")) {
1520 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1521 ct.perm_spch[0] = GSM0808_PERM_FR2;
1522 ct.perm_spch_len = 1;
1523 } else if (!strcmp(argv[3], "speech-amr")) {
1524 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1525 ct.perm_spch[0] = GSM0808_PERM_FR3;
1526 ct.perm_spch[1] = GSM0808_PERM_HR3;
1527 ct.perm_spch_len = 2;
1528 }
1529
1530 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1531
1532 if (!strcmp(argv[2], "tch/f"))
1533 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1534 else if (!strcmp(argv[2], "tch/h"))
1535 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1536 else if (!strcmp(argv[2], "tch/any"))
1537 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1538 else if (!strcmp(argv[2], "sdcch")) {
1539 if (speech) {
1540 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1541 return CMD_WARNING;
1542 }
1543 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1544 } else
1545 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1546
1547 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1548 port = argc >= 6 ? atoi(argv[5]) : 4000;
1549
1550 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001551 switch (rc) {
1552 case -ENODEV:
1553 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1554 break;
1555 default:
1556 if (rc)
1557 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1558 else
1559 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1560 break;
1561 }
1562
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001563 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001564 return rc ? CMD_WARNING : CMD_SUCCESS;
1565}
1566
1567DEFUN(subscriber_silent_call_stop,
1568 subscriber_silent_call_stop_cmd,
1569 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1570 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1571 CHAN_TYPE_HELP)
1572{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001573 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1574 int rc;
1575
1576 if (!vsub) {
1577 vty_out(vty, "%% No subscriber found for %s %s%s",
1578 argv[0], argv[1], VTY_NEWLINE);
1579 return CMD_WARNING;
1580 }
1581
1582 rc = gsm_silent_call_stop(vsub);
1583 switch (rc) {
1584 case -ENODEV:
1585 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1586 break;
1587 case -ENOENT:
1588 vty_out(vty, "%% Subscriber has no silent call active%s",
1589 VTY_NEWLINE);
1590 break;
1591 default:
1592 if (rc)
1593 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1594 else
1595 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1596 break;
1597 }
1598
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001599 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001600 return rc ? CMD_WARNING : CMD_SUCCESS;
1601}
1602
1603DEFUN(subscriber_ussd_notify,
1604 subscriber_ussd_notify_cmd,
1605 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1606 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1607 "Alerting Level 0\n"
1608 "Alerting Level 1\n"
1609 "Alerting Level 2\n"
1610 "Text of USSD message to send\n")
1611{
1612 char *text;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001613 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001614 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1615 int level;
1616
1617 if (!vsub) {
1618 vty_out(vty, "%% No subscriber found for %s %s%s",
1619 argv[0], argv[1], VTY_NEWLINE);
1620 return CMD_WARNING;
1621 }
1622
1623 level = atoi(argv[2]);
1624 text = argv_concat(argv, argc, 3);
1625 if (!text) {
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001626 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001627 return CMD_WARNING;
1628 }
1629
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001630 msc_a = msc_a_for_vsub(vsub, true);
1631 if (!msc_a || msc_a->c.remote_to) {
1632 vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001633 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001634 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001635 talloc_free(text);
1636 return CMD_WARNING;
1637 }
1638
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001639 msc_send_ussd_notify(msc_a, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001640 /* FIXME: since we don't allocate a transaction here,
1641 * we use dummy GSM 04.07 transaction ID. */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001642 msc_send_ussd_release_complete(msc_a, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001643
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001644 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001645 talloc_free(text);
1646 return CMD_SUCCESS;
1647}
1648
1649DEFUN(subscriber_paging,
1650 subscriber_paging_cmd,
1651 "subscriber " SUBSCR_TYPES " ID paging",
1652 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1653{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001654 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001655 struct paging_request *req;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001656
1657 if (!vsub) {
1658 vty_out(vty, "%% No subscriber found for %s %s%s",
1659 argv[0], argv[1], VTY_NEWLINE);
1660 return CMD_WARNING;
1661 }
1662
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001663 req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL,
1664 NULL, NULL, "manual Paging from VTY");
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001665 if (req)
1666 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1667 else
1668 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1669
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001670 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001671 return req ? CMD_SUCCESS : CMD_WARNING;
1672}
1673
1674static int loop_by_char(uint8_t ch)
1675{
1676 switch (ch) {
1677 case 'a':
1678 return GSM414_LOOP_A;
1679 case 'b':
1680 return GSM414_LOOP_B;
1681 case 'c':
1682 return GSM414_LOOP_C;
1683 case 'd':
1684 return GSM414_LOOP_D;
1685 case 'e':
1686 return GSM414_LOOP_E;
1687 case 'f':
1688 return GSM414_LOOP_F;
1689 case 'i':
1690 return GSM414_LOOP_I;
1691 }
1692 return -1;
1693}
1694
1695DEFUN(subscriber_mstest_close,
1696 subscriber_mstest_close_cmd,
1697 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1698 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1699 "Close a TCH Loop inside the MS\n"
1700 "Loop Type A\n"
1701 "Loop Type B\n"
1702 "Loop Type C\n"
1703 "Loop Type D\n"
1704 "Loop Type E\n"
1705 "Loop Type F\n"
1706 "Loop Type I\n")
1707{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001708 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001709 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1710 const char *loop_str;
1711 int loop_mode;
1712
1713 if (!vsub) {
1714 vty_out(vty, "%% No subscriber found for %s %s%s",
1715 argv[0], argv[1], VTY_NEWLINE);
1716 return CMD_WARNING;
1717 }
1718
1719 loop_str = argv[2];
1720 loop_mode = loop_by_char(loop_str[0]);
1721
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001722 msc_a = msc_a_for_vsub(vsub, true);
1723 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001724 vty_out(vty, "%% An active connection is required for %s %s%s",
1725 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001726 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001727 return CMD_WARNING;
1728 }
1729
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001730 gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001731
Vadim Yanitskiy817ad902020-07-29 05:47:01 +07001732 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001733 return CMD_SUCCESS;
1734}
1735
1736DEFUN(subscriber_mstest_open,
1737 subscriber_mstest_open_cmd,
1738 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1739 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1740 "Open a TCH Loop inside the MS\n")
1741{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001742 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001743 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1744
1745 if (!vsub) {
1746 vty_out(vty, "%% No subscriber found for %s %s%s",
1747 argv[0], argv[1], VTY_NEWLINE);
1748 return CMD_WARNING;
1749 }
1750
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001751 msc_a = msc_a_for_vsub(vsub, true);
1752 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001753 vty_out(vty, "%% An active connection is required for %s %s%s",
1754 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001755 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001756 return CMD_WARNING;
1757 }
1758
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001759 gsm0414_tx_open_loop_cmd(msc_a);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001760
Vadim Yanitskiy817ad902020-07-29 05:47:01 +07001761 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001762 return CMD_SUCCESS;
1763}
1764
1765DEFUN(ena_subscr_expire,
1766 ena_subscr_expire_cmd,
1767 "subscriber " SUBSCR_TYPES " ID expire",
1768 SUBSCR_HELP "Expire the subscriber Now\n")
1769{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001770 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1771 argv[1]);
1772
1773 if (!vsub) {
1774 vty_out(vty, "%% No subscriber found for %s %s%s",
1775 argv[0], argv[1], VTY_NEWLINE);
1776 return CMD_WARNING;
1777 }
1778
1779 if (vlr_subscr_expire(vsub))
1780 vty_out(vty, "%% VLR released subscriber %s%s",
1781 vlr_subscr_name(vsub), VTY_NEWLINE);
1782
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001783 if (osmo_use_count_total(&vsub->use_count) > 1)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001784 vty_out(vty, "%% Subscriber %s is still in use,"
1785 " should be released soon%s",
1786 vlr_subscr_name(vsub), VTY_NEWLINE);
1787
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001788 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001789 return CMD_SUCCESS;
1790}
1791
1792static int scall_cbfn(unsigned int subsys, unsigned int signal,
1793 void *handler_data, void *signal_data)
1794{
1795 struct scall_signal_data *sigdata = signal_data;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001796 struct vty *vty = sigdata->vty;
1797
1798 if (!vty_is_active(vty))
1799 return 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001800
1801 switch (signal) {
1802 case S_SCALL_SUCCESS:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001803 vty_out(vty, "%% Silent call success%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001804 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001805 case S_SCALL_FAILED:
1806 vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE);
1807 break;
1808 case S_SCALL_DETACHED:
1809 vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001810 break;
1811 }
1812 return 0;
1813}
1814
1815DEFUN(show_stats,
1816 show_stats_cmd,
1817 "show statistics",
1818 SHOW_STR "Display network statistics\n")
1819{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001820 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001821 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_ATTACH)->current,
1822 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_NORMAL)->current,
1823 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_PERIODIC)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001824 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001825 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001826 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_DETACH)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001827 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001828 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001829 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_COMPLETED)->current,
1830 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_FAILED)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001831 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001832 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001833 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_SUBMITTED)->current,
1834 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_NO_RECEIVER)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001835 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001836 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001837 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_DELIVERED)->current,
1838 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_RP_ERR_MEM)->current,
1839 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_RP_ERR_OTHER)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001840 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001841 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001842 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MO_SETUP)->current,
1843 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MO_CONNECT_ACK)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001844 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001845 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001846 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MT_SETUP)->current,
1847 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MT_CONNECT)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001848 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001849 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001850 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_REQUESTS)->current,
1851 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_ESTABLISHED)->current,
1852 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_REQUESTS)->current
1853 - rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_ESTABLISHED)->current,
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001854 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001855 vty_out(vty, "MT 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_MT_REQUESTS)->current,
1857 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_ESTABLISHED)->current,
1858 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_REQUESTS)->current
1859 - rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_ESTABLISHED)->current,
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001860 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001861 return CMD_SUCCESS;
1862}
1863
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001864
1865DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1866 "mncc-int", "Configure internal MNCC handler")
1867{
1868 vty->node = MNCC_INT_NODE;
1869
1870 return CMD_SUCCESS;
1871}
1872
1873static struct cmd_node mncc_int_node = {
1874 MNCC_INT_NODE,
1875 "%s(config-mncc-int)# ",
1876 1,
1877};
1878
1879static const struct value_string tchf_codec_names[] = {
1880 { GSM48_CMODE_SPEECH_V1, "fr" },
1881 { GSM48_CMODE_SPEECH_EFR, "efr" },
1882 { GSM48_CMODE_SPEECH_AMR, "amr" },
1883 { 0, NULL }
1884};
1885
1886static const struct value_string tchh_codec_names[] = {
1887 { GSM48_CMODE_SPEECH_V1, "hr" },
1888 { GSM48_CMODE_SPEECH_AMR, "amr" },
1889 { 0, NULL }
1890};
1891
1892static int config_write_mncc_int(struct vty *vty)
1893{
1894 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1895 vty_out(vty, " default-codec tch-f %s%s",
1896 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1897 VTY_NEWLINE);
1898 vty_out(vty, " default-codec tch-h %s%s",
1899 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1900 VTY_NEWLINE);
1901
1902 return CMD_SUCCESS;
1903}
1904
1905DEFUN(mnccint_def_codec_f,
1906 mnccint_def_codec_f_cmd,
1907 "default-codec tch-f (fr|efr|amr)",
1908 "Set default codec\n" "Codec for TCH/F\n"
1909 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1910{
1911 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1912
1913 return CMD_SUCCESS;
1914}
1915
1916DEFUN(mnccint_def_codec_h,
1917 mnccint_def_codec_h_cmd,
1918 "default-codec tch-h (hr|amr)",
1919 "Set default codec\n" "Codec for TCH/H\n"
1920 "Half-Rate\n" "Adaptive Multi-Rate\n")
1921{
1922 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1923
1924 return CMD_SUCCESS;
1925}
1926
1927
1928DEFUN(logging_fltr_imsi,
1929 logging_fltr_imsi_cmd,
1930 "logging filter imsi IMSI",
1931 LOGGING_STR FILTER_STR
1932 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1933{
1934 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001935 struct log_target *tgt = osmo_log_vty2tgt(vty);
1936 const char *imsi = argv[0];
1937
1938 if (!tgt)
1939 return CMD_WARNING;
1940
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001941 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001942
1943 if (!vlr_subscr) {
1944 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1945 argv[0], VTY_NEWLINE);
1946 return CMD_WARNING;
1947 }
1948
1949 log_set_filter_vlr_subscr(tgt, vlr_subscr);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001950 vlr_subscr_put(vlr_subscr, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001951 return CMD_SUCCESS;
1952}
1953
1954static struct cmd_node hlr_node = {
1955 HLR_NODE,
1956 "%s(config-hlr)# ",
1957 1,
1958};
1959
1960DEFUN(cfg_hlr, cfg_hlr_cmd,
1961 "hlr", "Configure connection to the HLR")
1962{
1963 vty->node = HLR_NODE;
1964 return CMD_SUCCESS;
1965}
1966
1967DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1968 "Remote GSUP address of the HLR\n"
1969 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1970{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001971 talloc_free((void*)gsmnet->gsup_server_addr_str);
1972 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1973 return CMD_SUCCESS;
1974}
1975
1976DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1977 "Remote GSUP port of the HLR\n"
1978 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1979{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001980 gsmnet->gsup_server_port = atoi(argv[0]);
1981 return CMD_SUCCESS;
1982}
1983
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001984DEFUN(cfg_hlr_ipa_name,
1985 cfg_hlr_ipa_name_cmd,
1986 "ipa-name NAME",
1987 "Set the IPA name of this MSC\n"
1988 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1989 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
1990 "The default is 'MSC-00-00-00-00-00-00'.\n")
1991{
1992 if (vty->type != VTY_FILE) {
1993 vty_out(vty, "The IPA name cannot be changed at run-time; "
Martin Hauke3f07dac2019-11-14 17:49:08 +01001994 "It can only be set in the configuration file.%s", VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001995 return CMD_WARNING;
1996 }
1997
1998 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
1999 return CMD_SUCCESS;
2000}
2001
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002002static int config_write_hlr(struct vty *vty)
2003{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002004 vty_out(vty, "hlr%s", VTY_NEWLINE);
2005 vty_out(vty, " remote-ip %s%s",
2006 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
2007 vty_out(vty, " remote-port %u%s",
2008 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002009 if (gsmnet->msc_ipa_name)
2010 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002011 return CMD_SUCCESS;
2012}
2013
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002014void msc_vty_init(struct gsm_network *msc_network)
2015{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01002016 OSMO_ASSERT(gsmnet == NULL);
2017 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002018
2019 osmo_stats_vty_add_cmds();
2020
2021 install_element(CONFIG_NODE, &cfg_net_cmd);
2022 install_node(&net_node, config_write_net);
2023 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
2024 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
2025 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
2026 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
2027 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +02002028 install_element(GSMNET_NODE, &cfg_net_encryption_uea_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002029 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
2030 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
2031 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
2032 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
2033 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
2034 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
2035 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
2036 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Keith Whyte991bb422019-08-08 15:43:40 +02002037 install_element(GSMNET_NODE, &cfg_net_call_wait_cmd);
2038 install_element(GSMNET_NODE, &cfg_net_no_call_wait_cmd);
Pau Espin Pedrol53639ea2022-10-18 14:33:15 +02002039 mgcp_client_pool_vty_init(GSMNET_NODE, MGW_NODE, NULL, msc_network->mgw.mgw_pool);
Pau Espin Pedrolb44cf2d2022-10-17 18:09:15 +02002040
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002041
2042 install_element(CONFIG_NODE, &cfg_msc_cmd);
2043 install_node(&msc_node, config_write_msc);
Keith Whyte1587ffb2020-08-28 13:36:58 +02002044 install_element(MSC_NODE, &cfg_sms_database_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002045 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Keith Whytea1a70be2021-05-16 02:59:52 +02002046 install_element(MSC_NODE, &cfg_msc_lcls_disable_cmd);
2047 install_element(MSC_NODE, &cfg_msc_no_lcls_disable_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01002048 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
2049 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02002050 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01002051 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07002052 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002053 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01002054 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
2055 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01002056 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02002057 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
2058 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01002059 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01002060 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07002061 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
2062 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +02002063 install_element(MSC_NODE, &cfg_msc_osmux_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002064 install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd);
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +02002065 install_element(MSC_NODE, &cfg_msc_nri_bitlen_cmd);
2066 install_element(MSC_NODE, &cfg_msc_nri_add_cmd);
2067 install_element(MSC_NODE, &cfg_msc_nri_del_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002068
2069 neighbor_ident_vty_init(msc_network);
Philipp Maierfbf66102017-04-09 12:32:51 +02002070
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +07002071 /* Timer configuration commands (generic osmo_tdef API) */
2072 osmo_tdef_vty_groups_init(MSC_NODE, msc_tdef_group);
2073
Pau Espin Pedrolb44cf2d2022-10-17 18:09:15 +02002074 /* Deprecated: Old MGCP config without pooling support in MSC node: */
Pau Espin Pedrol9e3bab92023-06-13 19:57:57 +02002075 mgcp_client_vty_init(msc_network, MSC_NODE, msc_network->mgw.conf);
Pau Espin Pedrolb44cf2d2022-10-17 18:09:15 +02002076
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002077#ifdef BUILD_IU
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002078 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 +02002079#endif
Harald Welte0df904d2018-12-03 11:00:04 +01002080 sgs_vty_init();
Harald Welte1a62db22022-05-17 12:06:58 +02002081 smsc_vty_init(msc_network);
Andreas Eversbergf8ac7342023-04-23 12:22:25 +02002082 asci_vty_init(msc_network);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002083
Stefan Sperling617ac802018-02-22 17:58:20 +01002084 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002085
2086 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
2087
2088 install_element_ve(&show_subscr_cmd);
2089 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01002090 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002091 install_element_ve(&show_msc_conn_cmd);
2092 install_element_ve(&show_msc_transaction_cmd);
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +02002093 install_element_ve(&show_nri_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002094
2095 install_element_ve(&sms_send_pend_cmd);
2096 install_element_ve(&sms_delete_expired_cmd);
2097
2098 install_element_ve(&subscriber_create_cmd);
2099 install_element_ve(&subscriber_send_sms_cmd);
2100 install_element_ve(&subscriber_silent_sms_cmd);
2101 install_element_ve(&subscriber_silent_call_start_cmd);
2102 install_element_ve(&subscriber_silent_call_stop_cmd);
2103 install_element_ve(&subscriber_ussd_notify_cmd);
2104 install_element_ve(&subscriber_mstest_close_cmd);
2105 install_element_ve(&subscriber_mstest_open_cmd);
2106 install_element_ve(&subscriber_paging_cmd);
2107 install_element_ve(&show_stats_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002108 install_element_ve(&logging_fltr_imsi_cmd);
2109
2110 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002111 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01002112 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002113
2114 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
2115 install_node(&mncc_int_node, config_write_mncc_int);
2116 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
2117 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
2118
2119 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
2120
2121 install_element(CONFIG_NODE, &cfg_hlr_cmd);
2122 install_node(&hlr_node, config_write_hlr);
2123 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
2124 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002125 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002126}