blob: 70b3b6bb1deaa8f199e16aa4df61528eef7df675 [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);
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100766 vty_out(vty, " mncc guard-timeout %i%s",
Philipp Maier9ca7b312018-10-10 17:00:49 +0200767 gsmnet->mncc_guard_timeout, VTY_NEWLINE);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700768 vty_out(vty, " ncss guard-timeout %i%s",
769 gsmnet->ncss_guard_timeout, VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200770 vty_out(vty, " %sassign-tmsi%s",
771 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
Keith Whytea1a70be2021-05-16 02:59:52 +0200772 if (gsmnet->lcls_permitted)
773 vty_out(vty, " lcls-permitted%s", VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200774
Philipp Maierfbf66102017-04-09 12:32:51 +0200775 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
776 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100777#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200778 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
779 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100780#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200781
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100782 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
783 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
784 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
785 VTY_NEWLINE);
786 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
787 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
788 VTY_NEWLINE);
789
Oliver Smith03ded912019-05-02 10:40:50 +0200790 if (gsmnet->vlr->cfg.check_imei_rqd) {
791 if (gsmnet->vlr->cfg.retrieve_imeisv_early)
792 vty_out(vty, " check-imei-rqd early%s", VTY_NEWLINE);
793 else
794 vty_out(vty, " check-imei-rqd 1%s", VTY_NEWLINE);
795 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100796
Harald Welte69c54a82018-02-09 20:41:14 +0100797 if (gsmnet->emergency.route_to_msisdn) {
798 vty_out(vty, " emergency-call route-to-msisdn %s%s",
799 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
800 }
801
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700802 if (gsmnet->sms_over_gsup)
803 vty_out(vty, " sms-over-gsup%s", VTY_NEWLINE);
804
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100805 if (gsmnet->handover_number.range_start || gsmnet->handover_number.range_end)
806 vty_out(vty, " handover-number range %"PRIu64" %"PRIu64"%s",
807 gsmnet->handover_number.range_start, gsmnet->handover_number.range_end,
808 VTY_NEWLINE);
809
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200810 if (gsmnet->use_osmux != OSMUX_USAGE_OFF) {
811 vty_out(vty, " osmux %s%s", gsmnet->use_osmux == OSMUX_USAGE_ON ? "on" : "only",
812 VTY_NEWLINE);
813 }
814
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200815 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200816#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200817 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200818#endif
819
Neels Hofmeyr880b9502019-05-09 02:01:55 +0200820 neighbor_ident_vty_write(vty);
821
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +0700822 /* Timer introspection commands (generic osmo_tdef API) */
823 osmo_tdef_vty_groups_write(vty, " ");
824
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +0200825 msc_write_nri(vty);
826
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200827 return CMD_SUCCESS;
828}
829
Maxc51609a2018-11-09 17:13:00 +0100830DEFUN(show_bsc, show_bsc_cmd,
831 "show bsc", SHOW_STR "BSC\n")
832{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100833 struct ran_peer *rp;
834 llist_for_each_entry(rp, &gsmnet->a.sri->ran_peers, entry) {
835 vty_out(vty, "BSC %s %s%s",
836 osmo_sccp_inst_addr_name(gsmnet->a.sri->sccp, &rp->peer_addr),
837 osmo_fsm_inst_state_name(rp->fi),
838 VTY_NEWLINE);
Maxc51609a2018-11-09 17:13:00 +0100839 }
840
841 return CMD_SUCCESS;
842}
843
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100844static const char *get_trans_proto_str(const struct gsm_trans *trans)
845{
846 static char buf[256];
847
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100848 switch (trans->type) {
849 case TRANS_CC:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100850 snprintf(buf, sizeof(buf), "%s %4u %4u",
851 gsm48_cc_state_name(trans->cc.state),
852 trans->cc.Tcurrent,
853 trans->cc.T308_second);
854 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100855 case TRANS_SMS:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700856 snprintf(buf, sizeof(buf), "CP:%s RP:%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100857 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
858 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
859 break;
860 default:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700861 return NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100862 }
863
864 return buf;
865}
866
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700867/* Prefix a given format string with a given amount of spaces */
868#define MSC_VTY_DUMP(vty, offset, fmt, args...) \
869 vty_out(vty, "%*s" fmt, offset, "", ##args)
870
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200871/* Print value of a named flag, prefixed with a given amount of spaces */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700872#define MSC_VTY_DUMP_FLAG(vty, offset, name, flag) \
873 MSC_VTY_DUMP(vty, offset + 2, "%s: %*s%s%s", \
874 name, 30 - (int)strlen(name), "", \
875 flag ? "true" : "false", \
876 VTY_NEWLINE)
877
878enum msc_vty_dump_flags {
879 MSC_VTY_DUMP_F_SUBSCR = (1 << 0),
880 MSC_VTY_DUMP_F_CONNECTION = (1 << 1),
881 MSC_VTY_DUMP_F_TRANSACTION = (1 << 2),
882};
883
884static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans,
885 int offset, uint8_t dump_flags)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100886{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700887 const char *proto_str;
888
889 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
890 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
891 vlr_subscr_name(msc_a_vsub(trans->msc_a)),
892 VTY_NEWLINE);
893 }
894
895 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200896 /* (If msc_a exists, there *must* be a non-null msc_a->c.msub) */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700897 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
898 trans->msc_a ? msub_ran_conn_name(trans->msc_a->c.msub)
899 : "(not established)",
900 VTY_NEWLINE);
901 }
902
903 MSC_VTY_DUMP(vty, offset, "Unique (global) identifier: 0x%08x%s",
904 trans->callref, VTY_NEWLINE);
905 MSC_VTY_DUMP(vty, offset, "GSM 04.07 identifier (%s): %u%s",
906 (trans->transaction_id & 0x08) ? "MO" : "MT",
907 trans->transaction_id,
908 VTY_NEWLINE);
909
910 MSC_VTY_DUMP(vty, offset, "Type: %s%s",
911 trans_type_name(trans->type),
912 VTY_NEWLINE);
913
914 if ((proto_str = get_trans_proto_str(trans))) {
915 MSC_VTY_DUMP(vty, offset, "Protocol specific: %s%s",
916 proto_str, VTY_NEWLINE);
917 }
918}
919
920static void vty_dump_one_conn(struct vty *vty, const struct msub *msub,
921 int offset, uint8_t dump_flags)
922{
923 struct vlr_subscr *vsub = msub_vsub(msub);
924 struct msc_a *msc_a = msub_msc_a(msub);
925 char buf[128];
926
927 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
928 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
929 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
930 vlr_subscr_name(vsub),
931 VTY_NEWLINE);
932 }
933
934 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
935 msub_ran_conn_name(msub),
936 VTY_NEWLINE);
937 MSC_VTY_DUMP(vty, offset, "RAN connection state: %s%s",
938 osmo_fsm_inst_state_name(msc_a->c.fi),
939 VTY_NEWLINE);
940
941 if (vsub) {
942 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
Neels Hofmeyr41c03332020-06-24 15:02:27 +0200943 msc_a->via_cell.lai.lac, msc_a->via_cell.cell_identity,
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700944 VTY_NEWLINE);
945 }
946
947 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
948 osmo_use_count_total(&msc_a->use_count),
949 VTY_NEWLINE);
950 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
951 osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count),
952 VTY_NEWLINE);
953
954 /* Transactions of this connection */
955 if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
956 struct gsm_trans *trans;
957 unsigned int i = 0;
958
959 /* Both subscriber and connection info is already printed */
960 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_CONNECTION;
961 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
962
963 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
964 if (trans->msc_a != msc_a)
965 continue;
966 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
967 i++, VTY_NEWLINE);
968 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
969 }
970 }
971}
972
973static void vty_dump_one_subscr(struct vty *vty, struct vlr_subscr *vsub,
974 int offset, uint8_t dump_flags)
975{
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700976 struct timespec now;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700977 char buf[128];
978
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700979 if (vsub->name[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700980 MSC_VTY_DUMP(vty, offset, "Name: '%s'%s",
981 vsub->name, VTY_NEWLINE);
982 }
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700983 if (vsub->msisdn[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700984 MSC_VTY_DUMP(vty, offset, "MSISDN: %s%s",
985 vsub->msisdn, VTY_NEWLINE);
986 }
987
988 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
989 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
990 VTY_NEWLINE);
991 MSC_VTY_DUMP(vty, offset, "RAN type: %s%s",
992 osmo_rat_type_name(vsub->cs.attached_via_ran),
993 VTY_NEWLINE);
994
995 MSC_VTY_DUMP(vty, offset, "IMSI: %s%s",
996 vsub->imsi, VTY_NEWLINE);
997 if (vsub->tmsi != GSM_RESERVED_TMSI) {
998 MSC_VTY_DUMP(vty, offset, "TMSI: %08X%s",
999 vsub->tmsi, VTY_NEWLINE);
1000 }
1001 if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
1002 MSC_VTY_DUMP(vty, offset, "New TMSI: %08X%s",
1003 vsub->tmsi_new, VTY_NEWLINE);
1004 }
1005 if (vsub->imei[0] != '\0') {
1006 MSC_VTY_DUMP(vty, offset, "IMEI: %s%s",
1007 vsub->imei, VTY_NEWLINE);
1008 }
1009 if (vsub->imeisv[0] != '\0') {
1010 MSC_VTY_DUMP(vty, offset, "IMEISV: %s%s",
1011 vsub->imeisv, VTY_NEWLINE);
1012 }
1013
1014 MSC_VTY_DUMP(vty, offset, "Flags: %s", VTY_NEWLINE);
1015 MSC_VTY_DUMP_FLAG(vty, offset, "IMSI detached",
1016 vsub->imsi_detached_flag);
1017 MSC_VTY_DUMP_FLAG(vty, offset, "Conf. by radio contact",
1018 vsub->conf_by_radio_contact_ind);
1019 MSC_VTY_DUMP_FLAG(vty, offset, "Subscr. data conf. by HLR",
1020 vsub->sub_dataconf_by_hlr_ind);
1021 MSC_VTY_DUMP_FLAG(vty, offset, "Location conf. in HLR",
1022 vsub->loc_conf_in_hlr_ind);
1023 MSC_VTY_DUMP_FLAG(vty, offset, "Subscriber dormant",
1024 vsub->dormant_ind);
1025 MSC_VTY_DUMP_FLAG(vty, offset, "Received cancel location",
1026 vsub->cancel_loc_rx);
1027 MSC_VTY_DUMP_FLAG(vty, offset, "MS not reachable",
1028 vsub->ms_not_reachable_flag);
1029 MSC_VTY_DUMP_FLAG(vty, offset, "LA allowed",
1030 vsub->la_allowed);
1031
1032 if (vsub->last_tuple) {
1033 struct vlr_auth_tuple *t = vsub->last_tuple;
1034 MSC_VTY_DUMP(vty, offset, "A3A8 last tuple (used %d times): %s",
1035 t->use_count, VTY_NEWLINE);
1036 MSC_VTY_DUMP(vty, offset + 2, "seq # : %d%s",
1037 t->key_seq, VTY_NEWLINE);
1038 MSC_VTY_DUMP(vty, offset + 2, "RAND : %s%s",
1039 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
1040 VTY_NEWLINE);
1041 MSC_VTY_DUMP(vty, offset + 2, "SRES : %s%s",
1042 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
1043 VTY_NEWLINE);
1044 MSC_VTY_DUMP(vty, offset + 2, "Kc : %s%s",
1045 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
1046 VTY_NEWLINE);
1047 }
1048
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +07001049 if (!vlr_timer(vsub->vlr, 3212)) {
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +07001050 MSC_VTY_DUMP(vty, offset, "Expires: never (T3212 is disabled)%s",
1051 VTY_NEWLINE);
1052 } else if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) {
1053 MSC_VTY_DUMP(vty, offset, "Expires: never%s",
1054 VTY_NEWLINE);
1055 } else if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
1056 MSC_VTY_DUMP(vty, offset, "Expires: in %ld min %ld sec%s",
1057 (vsub->expire_lu - now.tv_sec) / 60,
1058 (vsub->expire_lu - now.tv_sec) % 60,
1059 VTY_NEWLINE);
1060 }
1061
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001062 MSC_VTY_DUMP(vty, offset, "Paging: %s paging for %d requests%s",
1063 vsub->cs.is_paging ? "is" : "not",
1064 llist_count(&vsub->cs.requests),
1065 VTY_NEWLINE);
1066
1067 /* SGs related */
1068 MSC_VTY_DUMP(vty, offset, "SGs-state: %s%s",
1069 osmo_fsm_inst_state_name(vsub->sgs_fsm),
1070 VTY_NEWLINE);
1071 MSC_VTY_DUMP(vty, offset, "SGs-MME: %s%s",
Vadim Yanitskiydcf28682019-05-29 22:34:13 +07001072 vsub->sgs.mme_name[0] != '\0' ? vsub->sgs.mme_name : "(none)",
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001073 VTY_NEWLINE);
1074
1075 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
1076 osmo_use_count_total(&vsub->use_count),
1077 VTY_NEWLINE);
1078 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
1079 osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count),
1080 VTY_NEWLINE);
1081
1082 /* Connection(s) and/or transactions of this subscriber */
1083 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
1084 struct msub *msub = msub_for_vsub(vsub);
1085 if (!msub)
1086 return;
1087
1088 /* Subscriber info is already printed */
1089 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
1090
1091 MSC_VTY_DUMP(vty, offset, "Connection: %s", VTY_NEWLINE);
1092 vty_dump_one_conn(vty, msub, offset + 2, dump_flags);
1093 } else if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
1094 struct gsm_trans *trans;
1095 unsigned int i = 0;
1096
1097 /* Subscriber info is already printed */
1098 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
1099 /* Do not print connection info, but mention it */
1100 dump_flags |= MSC_VTY_DUMP_F_CONNECTION;
1101
1102 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1103 if (trans->vsub != vsub)
1104 continue;
1105 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
1106 i++, VTY_NEWLINE);
1107 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
1108 }
1109 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001110}
1111
1112DEFUN(show_msc_transaction, show_msc_transaction_cmd,
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001113 "show transaction",
1114 SHOW_STR "Transactions\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001115{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001116 struct gsm_trans *trans;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001117 uint8_t flags = 0x00;
1118 unsigned int i = 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001119
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001120 flags |= MSC_VTY_DUMP_F_CONNECTION;
1121 flags |= MSC_VTY_DUMP_F_SUBSCR;
1122
1123 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1124 vty_out(vty, " Transaction #%02u: %s", i++, VTY_NEWLINE);
1125 vty_dump_one_trans(vty, trans, 4, flags);
1126 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001127
1128 return CMD_SUCCESS;
1129}
1130
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001131DEFUN(show_msc_conn, show_msc_conn_cmd,
1132 "show connection [trans]",
1133 SHOW_STR "Subscriber Connections\n"
1134 "Show child transactions of each connection\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001135{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001136 uint8_t flags = 0x00;
1137 unsigned int i = 0;
1138 struct msub *msub;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001139
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001140 if (argc > 0)
1141 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1142 flags |= MSC_VTY_DUMP_F_SUBSCR;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001143
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001144 llist_for_each_entry(msub, &msub_list, entry) {
1145 vty_out(vty, " Connection #%02u: %s", i++, VTY_NEWLINE);
1146 vty_dump_one_conn(vty, msub, 4, flags);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001147 }
1148
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001149 return CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001150}
1151
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001152#define SUBSCR_FLAGS "[(conn|trans|conn+trans)]"
1153#define SUBSCR_FLAGS_HELP \
1154 "Show child connections\n" \
1155 "Show child transactions\n" \
1156 "Show child connections and transactions\n"
1157
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001158/* Subscriber */
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001159DEFUN(show_subscr_cache, show_subscr_cache_cmd,
1160 "show subscriber cache " SUBSCR_FLAGS,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001161 SHOW_STR "Show information about subscribers\n"
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001162 "Display contents of subscriber cache\n"
1163 SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001164{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001165 struct vlr_subscr *vsub;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001166 unsigned int count = 0;
1167 uint8_t flags = 0x00;
1168 unsigned int i = 0;
1169
1170 if (argc && strcmp(argv[0], "conn") == 0)
1171 flags |= MSC_VTY_DUMP_F_CONNECTION;
1172 else if (argc && strcmp(argv[0], "trans") == 0)
1173 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1174 else if (argc && strcmp(argv[0], "conn+trans") == 0)
1175 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001176
1177 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
1178 if (++count > 100) {
1179 vty_out(vty, "%% More than %d subscribers in cache,"
1180 " stopping here.%s", count-1, VTY_NEWLINE);
1181 break;
1182 }
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001183 vty_out(vty, " Subscriber #%02u: %s", i++, VTY_NEWLINE);
1184 vty_dump_one_subscr(vty, vsub, 4, flags);
Harald Welte69c54a82018-02-09 20:41:14 +01001185 }
1186
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001187 return CMD_SUCCESS;
1188}
1189
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001190DEFUN(sms_send_pend,
1191 sms_send_pend_cmd,
1192 "sms send pending",
1193 "SMS related commands\n" "SMS Sending related commands\n"
1194 "Send all pending SMS")
1195{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001196 struct gsm_sms *sms;
1197 unsigned long long sms_id = 0;
1198
1199 while (1) {
1200 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1201 if (!sms)
1202 break;
1203
1204 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001205 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001206
1207 sms_id = sms->id + 1;
1208 }
1209
1210 return CMD_SUCCESS;
1211}
1212
1213DEFUN(sms_delete_expired,
1214 sms_delete_expired_cmd,
1215 "sms delete expired",
1216 "SMS related commands\n" "SMS Database related commands\n"
1217 "Delete all expired SMS")
1218{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001219 struct gsm_sms *sms;
1220 unsigned long long sms_id = 0;
1221 long long num_deleted = 0;
1222
1223 while (1) {
1224 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1225 if (!sms)
1226 break;
1227
1228 /* Skip SMS which are currently queued for sending. */
1229 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
1230 continue;
1231
1232 /* Expiration check is performed by the DB layer. */
1233 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
1234 num_deleted++;
1235
1236 sms_id = sms->id + 1;
1237 }
1238
1239 if (num_deleted == 0) {
1240 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
1241 return CMD_WARNING;
1242 }
1243
1244 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
1245 return CMD_SUCCESS;
1246}
1247
1248static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +02001249 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001250 char *str, uint8_t tp_pid)
1251{
1252 struct gsm_network *net = receiver->vlr->user_ctx;
1253 struct gsm_sms *sms;
1254
Harald Welte39b55482018-04-09 19:19:33 +02001255 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Vadim Yanitskiydb4839c2019-12-01 18:52:58 +07001256 if (!sms) {
1257 LOGP(DLSMS, LOGL_ERROR, "Failed to allocate SMS\n");
1258 return CMD_WARNING;
1259 }
1260
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001261 sms->protocol_id = tp_pid;
1262
1263 /* store in database for the queue */
1264 if (db_sms_store(sms) != 0) {
1265 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
1266 sms_free(sms);
1267 return CMD_WARNING;
1268 }
1269 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
1270
1271 sms_free(sms);
1272 sms_queue_trigger(net->sms_queue);
1273 return CMD_SUCCESS;
1274}
1275
1276static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
1277 const char *type,
1278 const char *id)
1279{
1280 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001281 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001282 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001283 return vlr_subscr_find_by_imsi(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001284 else if (!strcmp(type, "tmsi"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001285 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id), VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001286
1287 return NULL;
1288}
1289#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
1290#define SUBSCR_HELP "Operations on a Subscriber\n" \
1291 "Identify subscriber by MSISDN (phone number)\n" \
1292 "Legacy alias for 'msisdn'\n" \
1293 "Identify subscriber by IMSI\n" \
1294 "Identify subscriber by TMSI\n" \
Vadim Yanitskiy3ccd8232019-05-16 01:35:23 +07001295 "Legacy alias for 'imsi'\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001296 "Identifier for the subscriber\n"
1297
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001298DEFUN(show_subscr, show_subscr_cmd,
1299 "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
1300 SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001301{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001302 struct vlr_subscr *vsub;
1303 uint8_t flags = 0x00;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001304
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001305 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001306 if (!vsub) {
1307 vty_out(vty, "%% No subscriber found for %s %s%s",
1308 argv[0], argv[1], VTY_NEWLINE);
1309 return CMD_WARNING;
1310 }
1311
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001312 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
1313 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
1314 * 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 +01001315 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001316
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001317 if (argc > 2 && strcmp(argv[2], "conn") == 0)
1318 flags |= MSC_VTY_DUMP_F_CONNECTION;
1319 else if (argc > 2 && strcmp(argv[2], "trans") == 0)
1320 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1321 else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
1322 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
1323
1324 vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
1325 vty_dump_one_subscr(vty, vsub, 4, flags);
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001326
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001327 return CMD_SUCCESS;
1328}
1329
Vadim Yanitskiyb7ddbf32020-01-20 21:30:09 +07001330DEFUN_DEPRECATED(subscriber_create, subscriber_create_cmd,
1331 "subscriber create imsi ID",
1332 "Operations on a Subscriber\n"
1333 "Create new subscriber\n"
1334 "Identify the subscriber by his IMSI\n"
1335 "Identifier for the subscriber\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001336{
1337 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
1338 VTY_NEWLINE);
1339 return CMD_WARNING;
1340}
1341
1342DEFUN(subscriber_send_pending_sms,
1343 subscriber_send_pending_sms_cmd,
1344 "subscriber " SUBSCR_TYPES " ID sms pending-send",
1345 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
1346{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001347 struct vlr_subscr *vsub;
1348 struct gsm_sms *sms;
1349
1350 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1351 if (!vsub) {
1352 vty_out(vty, "%% No subscriber found for %s %s%s",
1353 argv[0], argv[1], VTY_NEWLINE);
1354 return CMD_WARNING;
1355 }
1356
1357 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
1358 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001359 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001360
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001361 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001362
1363 return CMD_SUCCESS;
1364}
1365
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001366DEFUN(subscriber_sms_delete_all,
1367 subscriber_sms_delete_all_cmd,
1368 "subscriber " SUBSCR_TYPES " ID sms delete-all",
1369 SUBSCR_HELP "SMS Operations\n"
1370 "Delete all SMS to be delivered to this subscriber"
1371 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
1372 " WILL BE LOST.\n")
1373{
1374 struct vlr_subscr *vsub;
1375
1376 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1377 if (!vsub) {
1378 vty_out(vty, "%% No subscriber found for %s %s%s",
1379 argv[0], argv[1], VTY_NEWLINE);
1380 return CMD_WARNING;
1381 }
1382
1383 db_sms_delete_by_msisdn(vsub->msisdn);
1384
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001385 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001386
1387 return CMD_SUCCESS;
1388}
1389
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001390DEFUN(subscriber_send_sms,
1391 subscriber_send_sms_cmd,
1392 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1393 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1394{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001395 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001396 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001397 char *str;
1398 int rc;
1399
1400 if (!vsub) {
1401 vty_out(vty, "%% No subscriber found for %s %s%s",
1402 argv[0], argv[1], VTY_NEWLINE);
1403 rc = CMD_WARNING;
1404 goto err;
1405 }
1406
Harald Welte39b55482018-04-09 19:19:33 +02001407 if (!strcmp(argv[2], "msisdn"))
1408 sender_msisdn = argv[3];
1409 else {
1410 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1411 if (!sender) {
1412 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1413 rc = CMD_WARNING;
1414 goto err;
1415 }
1416 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001417 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001418 }
1419
1420 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001421 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001422 talloc_free(str);
1423
1424err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001425 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001426 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001427
1428 return rc;
1429}
1430
1431DEFUN(subscriber_silent_sms,
1432 subscriber_silent_sms_cmd,
1433
1434 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1435 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1436{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001437 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001438 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001439 char *str;
1440 int rc;
1441
1442 if (!vsub) {
1443 vty_out(vty, "%% No subscriber found for %s %s%s",
1444 argv[0], argv[1], VTY_NEWLINE);
1445 rc = CMD_WARNING;
1446 goto err;
1447 }
1448
Harald Welte39b55482018-04-09 19:19:33 +02001449 if (!strcmp(argv[2], "msisdn")) {
1450 sender_msisdn = argv[3];
1451 } else {
1452 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1453 if (!sender) {
1454 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1455 rc = CMD_WARNING;
1456 goto err;
1457 }
1458 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001459 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001460 }
1461
1462 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001463 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001464 talloc_free(str);
1465
1466err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001467 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001468 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001469
1470 return rc;
1471}
1472
Sylvain Munaut93558302019-02-14 20:13:08 +01001473#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001474#define CHAN_TYPE_HELP \
1475 "Any channel\n" \
1476 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001477 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001478 "Any TCH channel\n" \
1479 "SDCCH channel\n"
1480
Sylvain Munaut93558302019-02-14 20:13:08 +01001481#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1482#define CHAN_MODE_HELP \
1483 "Signalling only\n" \
1484 "Speech with HR codec\n" \
1485 "Speech with FR codec\n" \
1486 "Speech with EFR codec\n" \
1487 "Speech with AMR codec\n"
1488
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001489DEFUN(subscriber_silent_call_start,
1490 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001491 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001492 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001493 CHAN_TYPE_HELP CHAN_MODE_HELP
1494 "Target IP for RTP traffic (default 127.0.0.1)\n"
1495 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001496{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001497 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001498 struct gsm0808_channel_type ct;
1499 const char *ip;
1500 uint16_t port;
1501 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001502
1503 if (!vsub) {
1504 vty_out(vty, "%% No subscriber found for %s %s%s",
1505 argv[0], argv[1], VTY_NEWLINE);
1506 return CMD_WARNING;
1507 }
1508
Sylvain Munaut93558302019-02-14 20:13:08 +01001509 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001510
Sylvain Munaut93558302019-02-14 20:13:08 +01001511 if (!strcmp(argv[3], "signalling")) {
1512 ct.ch_indctr = GSM0808_CHAN_SIGN;
1513 ct.perm_spch[0] = 0; /* Spare but required */
1514 ct.perm_spch_len = 1;
1515 } else if (!strcmp(argv[3], "speech-hr")) {
1516 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1517 ct.perm_spch[0] = GSM0808_PERM_HR1;
1518 ct.perm_spch_len = 1;
1519 } else if (!strcmp(argv[3], "speech-fr")) {
1520 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1521 ct.perm_spch[0] = GSM0808_PERM_FR1;
1522 ct.perm_spch_len = 1;
1523 } else if (!strcmp(argv[3], "speech-efr")) {
1524 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1525 ct.perm_spch[0] = GSM0808_PERM_FR2;
1526 ct.perm_spch_len = 1;
1527 } else if (!strcmp(argv[3], "speech-amr")) {
1528 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1529 ct.perm_spch[0] = GSM0808_PERM_FR3;
1530 ct.perm_spch[1] = GSM0808_PERM_HR3;
1531 ct.perm_spch_len = 2;
1532 }
1533
1534 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1535
1536 if (!strcmp(argv[2], "tch/f"))
1537 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1538 else if (!strcmp(argv[2], "tch/h"))
1539 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1540 else if (!strcmp(argv[2], "tch/any"))
1541 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1542 else if (!strcmp(argv[2], "sdcch")) {
1543 if (speech) {
1544 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1545 return CMD_WARNING;
1546 }
1547 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1548 } else
1549 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1550
1551 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1552 port = argc >= 6 ? atoi(argv[5]) : 4000;
1553
1554 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001555 switch (rc) {
1556 case -ENODEV:
1557 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1558 break;
1559 default:
1560 if (rc)
1561 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1562 else
1563 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1564 break;
1565 }
1566
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001567 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001568 return rc ? CMD_WARNING : CMD_SUCCESS;
1569}
1570
1571DEFUN(subscriber_silent_call_stop,
1572 subscriber_silent_call_stop_cmd,
1573 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1574 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1575 CHAN_TYPE_HELP)
1576{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001577 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1578 int rc;
1579
1580 if (!vsub) {
1581 vty_out(vty, "%% No subscriber found for %s %s%s",
1582 argv[0], argv[1], VTY_NEWLINE);
1583 return CMD_WARNING;
1584 }
1585
1586 rc = gsm_silent_call_stop(vsub);
1587 switch (rc) {
1588 case -ENODEV:
1589 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1590 break;
1591 case -ENOENT:
1592 vty_out(vty, "%% Subscriber has no silent call active%s",
1593 VTY_NEWLINE);
1594 break;
1595 default:
1596 if (rc)
1597 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1598 else
1599 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1600 break;
1601 }
1602
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001603 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001604 return rc ? CMD_WARNING : CMD_SUCCESS;
1605}
1606
1607DEFUN(subscriber_ussd_notify,
1608 subscriber_ussd_notify_cmd,
1609 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1610 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1611 "Alerting Level 0\n"
1612 "Alerting Level 1\n"
1613 "Alerting Level 2\n"
1614 "Text of USSD message to send\n")
1615{
1616 char *text;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001617 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001618 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1619 int level;
1620
1621 if (!vsub) {
1622 vty_out(vty, "%% No subscriber found for %s %s%s",
1623 argv[0], argv[1], VTY_NEWLINE);
1624 return CMD_WARNING;
1625 }
1626
1627 level = atoi(argv[2]);
1628 text = argv_concat(argv, argc, 3);
1629 if (!text) {
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001630 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001631 return CMD_WARNING;
1632 }
1633
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001634 msc_a = msc_a_for_vsub(vsub, true);
1635 if (!msc_a || msc_a->c.remote_to) {
1636 vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001637 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001638 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001639 talloc_free(text);
1640 return CMD_WARNING;
1641 }
1642
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001643 msc_send_ussd_notify(msc_a, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001644 /* FIXME: since we don't allocate a transaction here,
1645 * we use dummy GSM 04.07 transaction ID. */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001646 msc_send_ussd_release_complete(msc_a, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001647
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001648 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001649 talloc_free(text);
1650 return CMD_SUCCESS;
1651}
1652
1653DEFUN(subscriber_paging,
1654 subscriber_paging_cmd,
1655 "subscriber " SUBSCR_TYPES " ID paging",
1656 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1657{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001658 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001659 struct paging_request *req;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001660
1661 if (!vsub) {
1662 vty_out(vty, "%% No subscriber found for %s %s%s",
1663 argv[0], argv[1], VTY_NEWLINE);
1664 return CMD_WARNING;
1665 }
1666
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001667 req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL,
1668 NULL, NULL, "manual Paging from VTY");
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001669 if (req)
1670 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1671 else
1672 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1673
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001674 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001675 return req ? CMD_SUCCESS : CMD_WARNING;
1676}
1677
1678static int loop_by_char(uint8_t ch)
1679{
1680 switch (ch) {
1681 case 'a':
1682 return GSM414_LOOP_A;
1683 case 'b':
1684 return GSM414_LOOP_B;
1685 case 'c':
1686 return GSM414_LOOP_C;
1687 case 'd':
1688 return GSM414_LOOP_D;
1689 case 'e':
1690 return GSM414_LOOP_E;
1691 case 'f':
1692 return GSM414_LOOP_F;
1693 case 'i':
1694 return GSM414_LOOP_I;
1695 }
1696 return -1;
1697}
1698
1699DEFUN(subscriber_mstest_close,
1700 subscriber_mstest_close_cmd,
1701 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1702 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1703 "Close a TCH Loop inside the MS\n"
1704 "Loop Type A\n"
1705 "Loop Type B\n"
1706 "Loop Type C\n"
1707 "Loop Type D\n"
1708 "Loop Type E\n"
1709 "Loop Type F\n"
1710 "Loop Type I\n")
1711{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001712 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001713 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1714 const char *loop_str;
1715 int loop_mode;
1716
1717 if (!vsub) {
1718 vty_out(vty, "%% No subscriber found for %s %s%s",
1719 argv[0], argv[1], VTY_NEWLINE);
1720 return CMD_WARNING;
1721 }
1722
1723 loop_str = argv[2];
1724 loop_mode = loop_by_char(loop_str[0]);
1725
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001726 msc_a = msc_a_for_vsub(vsub, true);
1727 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001728 vty_out(vty, "%% An active connection is required for %s %s%s",
1729 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001730 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001731 return CMD_WARNING;
1732 }
1733
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001734 gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001735
Vadim Yanitskiy817ad902020-07-29 05:47:01 +07001736 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001737 return CMD_SUCCESS;
1738}
1739
1740DEFUN(subscriber_mstest_open,
1741 subscriber_mstest_open_cmd,
1742 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1743 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1744 "Open a TCH Loop inside the MS\n")
1745{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001746 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001747 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1748
1749 if (!vsub) {
1750 vty_out(vty, "%% No subscriber found for %s %s%s",
1751 argv[0], argv[1], VTY_NEWLINE);
1752 return CMD_WARNING;
1753 }
1754
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001755 msc_a = msc_a_for_vsub(vsub, true);
1756 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001757 vty_out(vty, "%% An active connection is required for %s %s%s",
1758 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001759 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001760 return CMD_WARNING;
1761 }
1762
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001763 gsm0414_tx_open_loop_cmd(msc_a);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001764
Vadim Yanitskiy817ad902020-07-29 05:47:01 +07001765 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001766 return CMD_SUCCESS;
1767}
1768
1769DEFUN(ena_subscr_expire,
1770 ena_subscr_expire_cmd,
1771 "subscriber " SUBSCR_TYPES " ID expire",
1772 SUBSCR_HELP "Expire the subscriber Now\n")
1773{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001774 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1775 argv[1]);
1776
1777 if (!vsub) {
1778 vty_out(vty, "%% No subscriber found for %s %s%s",
1779 argv[0], argv[1], VTY_NEWLINE);
1780 return CMD_WARNING;
1781 }
1782
1783 if (vlr_subscr_expire(vsub))
1784 vty_out(vty, "%% VLR released subscriber %s%s",
1785 vlr_subscr_name(vsub), VTY_NEWLINE);
1786
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001787 if (osmo_use_count_total(&vsub->use_count) > 1)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001788 vty_out(vty, "%% Subscriber %s is still in use,"
1789 " should be released soon%s",
1790 vlr_subscr_name(vsub), VTY_NEWLINE);
1791
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001792 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001793 return CMD_SUCCESS;
1794}
1795
1796static int scall_cbfn(unsigned int subsys, unsigned int signal,
1797 void *handler_data, void *signal_data)
1798{
1799 struct scall_signal_data *sigdata = signal_data;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001800 struct vty *vty = sigdata->vty;
1801
1802 if (!vty_is_active(vty))
1803 return 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001804
1805 switch (signal) {
1806 case S_SCALL_SUCCESS:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001807 vty_out(vty, "%% Silent call success%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001808 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001809 case S_SCALL_FAILED:
1810 vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE);
1811 break;
1812 case S_SCALL_DETACHED:
1813 vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001814 break;
1815 }
1816 return 0;
1817}
1818
1819DEFUN(show_stats,
1820 show_stats_cmd,
1821 "show statistics",
1822 SHOW_STR "Display network statistics\n")
1823{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001824 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001825 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_ATTACH)->current,
1826 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_NORMAL)->current,
1827 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_PERIODIC)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001828 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001829 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001830 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_DETACH)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001831 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001832 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001833 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_COMPLETED)->current,
1834 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_FAILED)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001835 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001836 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001837 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_SUBMITTED)->current,
1838 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_NO_RECEIVER)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001839 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001840 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001841 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_DELIVERED)->current,
1842 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_RP_ERR_MEM)->current,
1843 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_RP_ERR_OTHER)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001844 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001845 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001846 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MO_SETUP)->current,
1847 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MO_CONNECT_ACK)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001848 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001849 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001850 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MT_SETUP)->current,
1851 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MT_CONNECT)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001852 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001853 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001854 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_REQUESTS)->current,
1855 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_ESTABLISHED)->current,
1856 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,
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001858 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001859 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001860 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_REQUESTS)->current,
1861 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_ESTABLISHED)->current,
1862 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,
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001864 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001865 return CMD_SUCCESS;
1866}
1867
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001868
1869DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1870 "mncc-int", "Configure internal MNCC handler")
1871{
1872 vty->node = MNCC_INT_NODE;
1873
1874 return CMD_SUCCESS;
1875}
1876
1877static struct cmd_node mncc_int_node = {
1878 MNCC_INT_NODE,
1879 "%s(config-mncc-int)# ",
1880 1,
1881};
1882
1883static const struct value_string tchf_codec_names[] = {
1884 { GSM48_CMODE_SPEECH_V1, "fr" },
1885 { GSM48_CMODE_SPEECH_EFR, "efr" },
1886 { GSM48_CMODE_SPEECH_AMR, "amr" },
1887 { 0, NULL }
1888};
1889
1890static const struct value_string tchh_codec_names[] = {
1891 { GSM48_CMODE_SPEECH_V1, "hr" },
1892 { GSM48_CMODE_SPEECH_AMR, "amr" },
1893 { 0, NULL }
1894};
1895
1896static int config_write_mncc_int(struct vty *vty)
1897{
1898 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1899 vty_out(vty, " default-codec tch-f %s%s",
1900 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1901 VTY_NEWLINE);
1902 vty_out(vty, " default-codec tch-h %s%s",
1903 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1904 VTY_NEWLINE);
1905
1906 return CMD_SUCCESS;
1907}
1908
1909DEFUN(mnccint_def_codec_f,
1910 mnccint_def_codec_f_cmd,
1911 "default-codec tch-f (fr|efr|amr)",
1912 "Set default codec\n" "Codec for TCH/F\n"
1913 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1914{
1915 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1916
1917 return CMD_SUCCESS;
1918}
1919
1920DEFUN(mnccint_def_codec_h,
1921 mnccint_def_codec_h_cmd,
1922 "default-codec tch-h (hr|amr)",
1923 "Set default codec\n" "Codec for TCH/H\n"
1924 "Half-Rate\n" "Adaptive Multi-Rate\n")
1925{
1926 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1927
1928 return CMD_SUCCESS;
1929}
1930
1931
1932DEFUN(logging_fltr_imsi,
1933 logging_fltr_imsi_cmd,
1934 "logging filter imsi IMSI",
1935 LOGGING_STR FILTER_STR
1936 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1937{
1938 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001939 struct log_target *tgt = osmo_log_vty2tgt(vty);
1940 const char *imsi = argv[0];
1941
1942 if (!tgt)
1943 return CMD_WARNING;
1944
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001945 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001946
1947 if (!vlr_subscr) {
1948 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1949 argv[0], VTY_NEWLINE);
1950 return CMD_WARNING;
1951 }
1952
1953 log_set_filter_vlr_subscr(tgt, vlr_subscr);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001954 vlr_subscr_put(vlr_subscr, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001955 return CMD_SUCCESS;
1956}
1957
1958static struct cmd_node hlr_node = {
1959 HLR_NODE,
1960 "%s(config-hlr)# ",
1961 1,
1962};
1963
1964DEFUN(cfg_hlr, cfg_hlr_cmd,
1965 "hlr", "Configure connection to the HLR")
1966{
1967 vty->node = HLR_NODE;
1968 return CMD_SUCCESS;
1969}
1970
1971DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1972 "Remote GSUP address of the HLR\n"
1973 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1974{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001975 talloc_free((void*)gsmnet->gsup_server_addr_str);
1976 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1977 return CMD_SUCCESS;
1978}
1979
1980DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1981 "Remote GSUP port of the HLR\n"
1982 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1983{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001984 gsmnet->gsup_server_port = atoi(argv[0]);
1985 return CMD_SUCCESS;
1986}
1987
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001988DEFUN(cfg_hlr_ipa_name,
1989 cfg_hlr_ipa_name_cmd,
1990 "ipa-name NAME",
1991 "Set the IPA name of this MSC\n"
1992 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1993 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
1994 "The default is 'MSC-00-00-00-00-00-00'.\n")
1995{
1996 if (vty->type != VTY_FILE) {
1997 vty_out(vty, "The IPA name cannot be changed at run-time; "
Martin Hauke3f07dac2019-11-14 17:49:08 +01001998 "It can only be set in the configuration file.%s", VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001999 return CMD_WARNING;
2000 }
2001
2002 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
2003 return CMD_SUCCESS;
2004}
2005
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002006static int config_write_hlr(struct vty *vty)
2007{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002008 vty_out(vty, "hlr%s", VTY_NEWLINE);
2009 vty_out(vty, " remote-ip %s%s",
2010 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
2011 vty_out(vty, " remote-port %u%s",
2012 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002013 if (gsmnet->msc_ipa_name)
2014 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002015 return CMD_SUCCESS;
2016}
2017
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002018void msc_vty_init(struct gsm_network *msc_network)
2019{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01002020 OSMO_ASSERT(gsmnet == NULL);
2021 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002022
2023 osmo_stats_vty_add_cmds();
2024
2025 install_element(CONFIG_NODE, &cfg_net_cmd);
2026 install_node(&net_node, config_write_net);
2027 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
2028 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
2029 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
2030 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
2031 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +02002032 install_element(GSMNET_NODE, &cfg_net_encryption_uea_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002033 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
2034 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
2035 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
2036 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
2037 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
2038 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
2039 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
2040 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Keith Whyte991bb422019-08-08 15:43:40 +02002041 install_element(GSMNET_NODE, &cfg_net_call_wait_cmd);
2042 install_element(GSMNET_NODE, &cfg_net_no_call_wait_cmd);
Pau Espin Pedrol53639ea2022-10-18 14:33:15 +02002043 mgcp_client_pool_vty_init(GSMNET_NODE, MGW_NODE, NULL, msc_network->mgw.mgw_pool);
Pau Espin Pedrolb44cf2d2022-10-17 18:09:15 +02002044
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002045
2046 install_element(CONFIG_NODE, &cfg_msc_cmd);
2047 install_node(&msc_node, config_write_msc);
Keith Whyte1587ffb2020-08-28 13:36:58 +02002048 install_element(MSC_NODE, &cfg_sms_database_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002049 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Keith Whytea1a70be2021-05-16 02:59:52 +02002050 install_element(MSC_NODE, &cfg_msc_lcls_disable_cmd);
2051 install_element(MSC_NODE, &cfg_msc_no_lcls_disable_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01002052 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
2053 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02002054 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01002055 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07002056 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002057 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01002058 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
2059 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01002060 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02002061 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
2062 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01002063 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01002064 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07002065 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
2066 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +02002067 install_element(MSC_NODE, &cfg_msc_osmux_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002068 install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd);
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +02002069 install_element(MSC_NODE, &cfg_msc_nri_bitlen_cmd);
2070 install_element(MSC_NODE, &cfg_msc_nri_add_cmd);
2071 install_element(MSC_NODE, &cfg_msc_nri_del_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002072
2073 neighbor_ident_vty_init(msc_network);
Philipp Maierfbf66102017-04-09 12:32:51 +02002074
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +07002075 /* Timer configuration commands (generic osmo_tdef API) */
2076 osmo_tdef_vty_groups_init(MSC_NODE, msc_tdef_group);
2077
Pau Espin Pedrolb44cf2d2022-10-17 18:09:15 +02002078 /* Deprecated: Old MGCP config without pooling support in MSC node: */
Pau Espin Pedrol9e3bab92023-06-13 19:57:57 +02002079 mgcp_client_vty_init(msc_network, MSC_NODE, msc_network->mgw.conf);
Pau Espin Pedrolb44cf2d2022-10-17 18:09:15 +02002080
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002081#ifdef BUILD_IU
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002082 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 +02002083#endif
Harald Welte0df904d2018-12-03 11:00:04 +01002084 sgs_vty_init();
Harald Welte1a62db22022-05-17 12:06:58 +02002085 smsc_vty_init(msc_network);
Andreas Eversbergf8ac7342023-04-23 12:22:25 +02002086 asci_vty_init(msc_network);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002087
Stefan Sperling617ac802018-02-22 17:58:20 +01002088 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002089
2090 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
2091
2092 install_element_ve(&show_subscr_cmd);
2093 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01002094 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002095 install_element_ve(&show_msc_conn_cmd);
2096 install_element_ve(&show_msc_transaction_cmd);
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +02002097 install_element_ve(&show_nri_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002098
2099 install_element_ve(&sms_send_pend_cmd);
2100 install_element_ve(&sms_delete_expired_cmd);
2101
2102 install_element_ve(&subscriber_create_cmd);
2103 install_element_ve(&subscriber_send_sms_cmd);
2104 install_element_ve(&subscriber_silent_sms_cmd);
2105 install_element_ve(&subscriber_silent_call_start_cmd);
2106 install_element_ve(&subscriber_silent_call_stop_cmd);
2107 install_element_ve(&subscriber_ussd_notify_cmd);
2108 install_element_ve(&subscriber_mstest_close_cmd);
2109 install_element_ve(&subscriber_mstest_open_cmd);
2110 install_element_ve(&subscriber_paging_cmd);
2111 install_element_ve(&show_stats_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002112 install_element_ve(&logging_fltr_imsi_cmd);
2113
2114 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002115 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01002116 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002117
2118 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
2119 install_node(&mncc_int_node, config_write_mncc_int);
2120 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
2121 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
2122
2123 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
2124
2125 install_element(CONFIG_NODE, &cfg_hlr_cmd);
2126 install_node(&hlr_node, config_write_hlr);
2127 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
2128 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002129 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002130}