blob: 5e3a2229c1209398b30ef4d263b729cf9ce9c9dd [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>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010071
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010072static struct gsm_network *gsmnet = NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010073
Vadim Yanitskiy9b56cd82020-01-25 06:38:44 +070074static struct cmd_node net_node = {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010075 GSMNET_NODE,
76 "%s(config-net)# ",
77 1,
78};
79
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +010080#define VSUB_USE_VTY "VTY"
81
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010082#define NETWORK_STR "Configure the GSM network\n"
83#define CODE_CMD_STR "Code commands\n"
84#define NAME_CMD_STR "Name Commands\n"
85#define NAME_STR "Name to use\n"
86
87DEFUN(cfg_net,
88 cfg_net_cmd,
89 "network", NETWORK_STR)
90{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010091 vty->index = gsmnet;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010092 vty->node = GSMNET_NODE;
93
94 return CMD_SUCCESS;
95}
96
97DEFUN(cfg_net_ncc,
98 cfg_net_ncc_cmd,
99 "network country code <1-999>",
100 "Set the GSM network country code\n"
101 "Country commands\n"
102 CODE_CMD_STR
103 "Network Country Code to use\n")
104{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100105 gsmnet->plmn.mcc = atoi(argv[0]);
106
107 return CMD_SUCCESS;
108}
109
110DEFUN(cfg_net_mnc,
111 cfg_net_mnc_cmd,
112 "mobile network code <0-999>",
113 "Set the GSM mobile network code\n"
114 "Network Commands\n"
115 CODE_CMD_STR
116 "Mobile Network Code to use\n")
117{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100118 uint16_t mnc;
119 bool mnc_3_digits;
120
121 if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
122 vty_out(vty, "%% Error decoding MNC: %s%s", argv[0], VTY_NEWLINE);
123 return CMD_WARNING;
124 }
125
126 gsmnet->plmn.mnc = mnc;
127 gsmnet->plmn.mnc_3_digits = mnc_3_digits;
128
129 return CMD_SUCCESS;
130}
131
132DEFUN(cfg_net_name_short,
133 cfg_net_name_short_cmd,
134 "short name NAME",
135 "Set the short GSM network name\n" NAME_CMD_STR NAME_STR)
136{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100137 osmo_talloc_replace_string(gsmnet, &gsmnet->name_short, argv[0]);
138 return CMD_SUCCESS;
139}
140
141DEFUN(cfg_net_name_long,
142 cfg_net_name_long_cmd,
143 "long name NAME",
144 "Set the long GSM network name\n" NAME_CMD_STR NAME_STR)
145{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100146 osmo_talloc_replace_string(gsmnet, &gsmnet->name_long, argv[0]);
147 return CMD_SUCCESS;
148}
149
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200150#define ENCRYPTION_STR "Encryption options\n"
151
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100152DEFUN(cfg_net_encryption,
153 cfg_net_encryption_cmd,
Eric Wilda7f80202021-06-09 04:04:06 +0200154 "encryption a5 <0-4> [<0-4>] [<0-4>] [<0-4>] [<0-4>]",
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200155 ENCRYPTION_STR
156 "GSM A5 Air Interface Encryption.\n"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100157 "A5/n Algorithm Number\n"
158 "A5/n Algorithm Number\n"
159 "A5/n Algorithm Number\n"
Eric Wilda7f80202021-06-09 04:04:06 +0200160 "A5/n Algorithm Number\n"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100161 "A5/n Algorithm Number\n")
162{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100163 unsigned int i;
164
165 gsmnet->a5_encryption_mask = 0;
166 for (i = 0; i < argc; i++)
167 gsmnet->a5_encryption_mask |= (1 << atoi(argv[i]));
168
169 return CMD_SUCCESS;
170}
171
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200172DEFUN(cfg_net_encryption_uea,
173 cfg_net_encryption_uea_cmd,
174 "encryption uea <0-2> [<0-2>] [<0-2>]",
175 ENCRYPTION_STR
Harald Welte505a94a2021-02-06 17:12:20 +0100176 "UTRAN (3G) encryption algorithms to allow: 0 = UEA0 (no encryption), 1 = UEA1, 2 = UEA2.\n"
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200177 "UEAn Algorithm Number\n"
178 "UEAn Algorithm Number\n"
179 "UEAn Algorithm Number\n"
180 )
181{
182 unsigned int i;
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200183
Harald Welte505a94a2021-02-06 17:12:20 +0100184 gsmnet->uea_encryption_mask = 0;
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200185 for (i = 0; i < argc; i++)
Harald Welte505a94a2021-02-06 17:12:20 +0100186 gsmnet->uea_encryption_mask |= (1 << atoi(argv[i]));
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200187
188 return CMD_SUCCESS;
189}
190
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100191DEFUN(cfg_net_authentication,
192 cfg_net_authentication_cmd,
193 "authentication (optional|required)",
194 "Whether to enforce MS authentication in 2G\n"
195 "Allow MS to attach via 2G BSC without authentication\n"
196 "Always do authentication\n")
197{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100198 gsmnet->authentication_required = (argv[0][0] == 'r') ? true : false;
199
200 return CMD_SUCCESS;
201}
202
203DEFUN(cfg_net_rrlp_mode, cfg_net_rrlp_mode_cmd,
204 "rrlp mode (none|ms-based|ms-preferred|ass-preferred)",
205 "Radio Resource Location Protocol\n"
206 "Set the Radio Resource Location Protocol Mode\n"
207 "Don't send RRLP request\n"
208 "Request MS-based location\n"
209 "Request any location, prefer MS-based\n"
210 "Request any location, prefer MS-assisted\n")
211{
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700212 gsmnet->rrlp.mode = msc_rrlp_mode_parse(argv[0]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100213
214 return CMD_SUCCESS;
215}
216
217DEFUN(cfg_net_mm_info, cfg_net_mm_info_cmd,
218 "mm info (0|1)",
219 "Mobility Management\n"
220 "Send MM INFO after LOC UPD ACCEPT\n"
221 "Disable\n" "Enable\n")
222{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100223 gsmnet->send_mm_info = atoi(argv[0]);
224
225 return CMD_SUCCESS;
226}
227
228DEFUN(cfg_net_timezone,
229 cfg_net_timezone_cmd,
230 "timezone <-19-19> (0|15|30|45)",
231 "Set the Timezone Offset of the network\n"
232 "Timezone offset (hours)\n"
233 "Timezone offset (00 minutes)\n"
234 "Timezone offset (15 minutes)\n"
235 "Timezone offset (30 minutes)\n"
236 "Timezone offset (45 minutes)\n"
237 )
238{
239 struct gsm_network *net = vty->index;
240 int tzhr = atoi(argv[0]);
241 int tzmn = atoi(argv[1]);
242
243 net->tz.hr = tzhr;
244 net->tz.mn = tzmn;
245 net->tz.dst = 0;
246 net->tz.override = 1;
247
248 return CMD_SUCCESS;
249}
250
251DEFUN(cfg_net_timezone_dst,
252 cfg_net_timezone_dst_cmd,
253 "timezone <-19-19> (0|15|30|45) <0-2>",
254 "Set the Timezone Offset of the network\n"
255 "Timezone offset (hours)\n"
256 "Timezone offset (00 minutes)\n"
257 "Timezone offset (15 minutes)\n"
258 "Timezone offset (30 minutes)\n"
259 "Timezone offset (45 minutes)\n"
260 "DST offset (hours)\n"
261 )
262{
263 struct gsm_network *net = vty->index;
264 int tzhr = atoi(argv[0]);
265 int tzmn = atoi(argv[1]);
266 int tzdst = atoi(argv[2]);
267
268 net->tz.hr = tzhr;
269 net->tz.mn = tzmn;
270 net->tz.dst = tzdst;
271 net->tz.override = 1;
272
273 return CMD_SUCCESS;
274}
275
276DEFUN(cfg_net_no_timezone,
277 cfg_net_no_timezone_cmd,
278 "no timezone",
279 NO_STR
280 "Disable network timezone override, use system tz\n")
281{
282 struct gsm_network *net = vty->index;
283
284 net->tz.override = 0;
285
286 return CMD_SUCCESS;
287}
288
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700289/* NOTE: actually this is subscriber expiration timeout */
290#define PER_LOC_UPD_STR "Periodic Location Updating Interval\n"
291
292DEFUN_DEPRECATED(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
293 "periodic location update <6-1530>",
294 PER_LOC_UPD_STR PER_LOC_UPD_STR PER_LOC_UPD_STR
295 "Periodic Location Updating Interval in Minutes\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100296{
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700297 int minutes = atoi(argv[0]);
298 int rc;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100299
Vadim Yanitskiy9a282302021-11-28 03:44:13 +0300300 vty_out(vty, "%% 'periodic location update' is now deprecated. "
301 "Use 'msc' / 'timer vlr T3212' to change subscriber expiration "
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700302 "timeout.%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100303
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700304 /* We used to double this value and add a minute when scheduling the
305 * expiration timer. Let's emulate the old behaviour here. */
306 minutes = minutes * 2 + 1;
307 vty_out(vty, "%% Setting T3212 to %d minutes "
308 "(emulating the old behaviour).%s",
309 minutes, VTY_NEWLINE);
310
311 rc = osmo_tdef_set(msc_tdefs_vlr, 3212, minutes, OSMO_TDEF_M);
312 return rc ? CMD_WARNING : CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100313}
314
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700315DEFUN_DEPRECATED(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
316 "no periodic location update",
317 NO_STR PER_LOC_UPD_STR PER_LOC_UPD_STR PER_LOC_UPD_STR)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100318{
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700319 int rc;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100320
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700321 vty_out(vty, "%% 'periodic location update' is now deprecated: "
322 "use 'timer T3212' to change subscriber expiration "
323 "timeout.%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100324
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700325 rc = osmo_tdef_set(msc_tdefs_vlr, 3212, 0, OSMO_TDEF_M);
326 return rc ? CMD_WARNING : CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100327}
328
Keith Whyte991bb422019-08-08 15:43:40 +0200329DEFUN(cfg_net_call_wait, cfg_net_call_wait_cmd,
330 "call-waiting",
331 "Enable Call Waiting on the Network\n")
332{
333 struct gsm_network *net = vty->index;
334
335 net->call_waiting = true;
336
337 return CMD_SUCCESS;
338}
339
340DEFUN(cfg_net_no_call_wait, cfg_net_no_call_wait_cmd,
341 "no call-waiting",
342 NO_STR
343 "Disable Call Waiting on the Network\n")
344{
345 struct gsm_network *net = vty->index;
346
347 net->call_waiting = false;
348
349 return CMD_SUCCESS;
350}
351
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100352static int config_write_net(struct vty *vty)
353{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100354 int i;
355
356 vty_out(vty, "network%s", VTY_NEWLINE);
357 vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
358 vty_out(vty, " mobile network code %s%s",
359 osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
360 vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
361 vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
362 vty_out(vty, " encryption a5");
363 for (i = 0; i < 8; i++) {
364 if (gsmnet->a5_encryption_mask & (1 << i))
365 vty_out(vty, " %u", i);
366 }
367 vty_out(vty, "%s", VTY_NEWLINE);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200368
Harald Welte505a94a2021-02-06 17:12:20 +0100369 vty_out(vty, " encryption uea");
370 for (i = 0; i < 8; i++) {
371 if (gsmnet->uea_encryption_mask & (1 << i))
372 vty_out(vty, " %u", i);
373 }
374 vty_out(vty, "%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100375 vty_out(vty, " authentication %s%s",
376 gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE);
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700377 vty_out(vty, " rrlp mode %s%s", msc_rrlp_mode_name(gsmnet->rrlp.mode),
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100378 VTY_NEWLINE);
379 vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
380 if (gsmnet->tz.override != 0) {
381 if (gsmnet->tz.dst)
382 vty_out(vty, " timezone %d %d %d%s",
383 gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
384 VTY_NEWLINE);
385 else
386 vty_out(vty, " timezone %d %d%s",
387 gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
388 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100389
Keith Whyte991bb422019-08-08 15:43:40 +0200390 if (!gsmnet->call_waiting)
391 vty_out(vty, " no call-waiting%s", VTY_NEWLINE);
392
Pau Espin Pedrol53639ea2022-10-18 14:33:15 +0200393 mgcp_client_pool_config_write(vty, " ");
394
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100395 return CMD_SUCCESS;
396}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200397
398static struct cmd_node msc_node = {
399 MSC_NODE,
400 "%s(config-msc)# ",
401 1,
402};
403
404DEFUN(cfg_msc, cfg_msc_cmd,
405 "msc", "Configure MSC options")
406{
407 vty->node = MSC_NODE;
408 return CMD_SUCCESS;
409}
410
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100411#define MNCC_STR "Configure Mobile Network Call Control\n"
412#define MNCC_GUARD_TIMEOUT_STR "Set global guard timer for mncc interface activity\n"
413#define MNCC_GUARD_TIMEOUT_VALUE_STR "guard timer value (sec.)\n"
414
Harald Welte1a62db22022-05-17 12:06:58 +0200415DEFUN_DEPRECATED(cfg_sms_database, cfg_sms_database_cmd,
Keith Whyte1587ffb2020-08-28 13:36:58 +0200416 "sms-database PATH",
417 "Set the path to the MSC-SMS database file\n"
418 "Relative or absolute file system path to the database file (default is '" SMS_DEFAULT_DB_FILE_PATH "')\n")
419{
Harald Welted302bb12022-05-17 13:31:14 +0200420 osmo_talloc_replace_string(gsmnet, &gsmnet->sms_queue_cfg->db_file_path, argv[0]);
Keith Whyte1587ffb2020-08-28 13:36:58 +0200421 return CMD_SUCCESS;
422}
423
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100424DEFUN(cfg_msc_mncc_internal,
425 cfg_msc_mncc_internal_cmd,
426 "mncc internal",
427 MNCC_STR "Use internal MNCC handler (default; changes need a program restart)\n")
428{
429 gsm_network_set_mncc_sock_path(gsmnet, NULL);
430 return CMD_SUCCESS;
431}
432
433DEFUN(cfg_msc_mncc_external,
434 cfg_msc_mncc_external_cmd,
435 "mncc external MNCC_SOCKET_PATH",
436 MNCC_STR "Use external MNCC handler (changes need a program restart)\n"
437 "File system path to create the MNCC unix domain socket at\n")
438{
439 gsm_network_set_mncc_sock_path(gsmnet, argv[0]);
440 return CMD_SUCCESS;
441}
442
Philipp Maier9ca7b312018-10-10 17:00:49 +0200443DEFUN(cfg_msc_mncc_guard_timeout,
444 cfg_msc_mncc_guard_timeout_cmd,
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100445 "mncc guard-timeout <0-255>",
446 MNCC_STR
447 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR)
Philipp Maier9ca7b312018-10-10 17:00:49 +0200448{
449 gsmnet->mncc_guard_timeout = atoi(argv[0]);
450 return CMD_SUCCESS;
451}
452
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100453ALIAS_DEPRECATED(cfg_msc_mncc_guard_timeout,
454 cfg_msc_deprecated_mncc_guard_timeout_cmd,
455 "mncc-guard-timeout <0-255>",
456 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR);
457
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700458#define NCSS_STR "Configure call independent Supplementary Services\n"
459
460DEFUN(cfg_msc_ncss_guard_timeout,
461 cfg_msc_ncss_guard_timeout_cmd,
462 "ncss guard-timeout <0-255>",
463 NCSS_STR "Set guard timer for session activity\n"
464 "guard timer value (sec.), or 0 to disable\n")
465{
466 gsmnet->ncss_guard_timeout = atoi(argv[0]);
467 return CMD_SUCCESS;
468}
469
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200470DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
471 "assign-tmsi",
472 "Assign TMSI during Location Updating.\n")
473{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200474 gsmnet->vlr->cfg.assign_tmsi = true;
475 return CMD_SUCCESS;
476}
477
478DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
479 "no assign-tmsi",
480 NO_STR "Assign TMSI during Location Updating.\n")
481{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200482 gsmnet->vlr->cfg.assign_tmsi = false;
483 return CMD_SUCCESS;
484}
485
Keith Whytea1a70be2021-05-16 02:59:52 +0200486DEFUN_ATTR(cfg_msc_lcls_disable, cfg_msc_lcls_disable_cmd,
487 "lcls-permitted",
488 "Globally allow LCLS (Local Call Local Switch) for all calls on this MSC.\n",
489 CMD_ATTR_IMMEDIATE)
490{
491 gsmnet->lcls_permitted = true;
492 return CMD_SUCCESS;
493}
494
495DEFUN_ATTR(cfg_msc_no_lcls_disable, cfg_msc_no_lcls_disable_cmd,
496 "no lcls-permitted",
497 NO_STR "Globally disable LCLS (Local Call Local Switch) for all calls on this MSC.\n",
498 CMD_ATTR_IMMEDIATE)
499{
500 gsmnet->lcls_permitted = false;
501 return CMD_SUCCESS;
502}
503
Philipp Maierfbf66102017-04-09 12:32:51 +0200504DEFUN(cfg_msc_cs7_instance_a,
505 cfg_msc_cs7_instance_a_cmd,
506 "cs7-instance-a <0-15>",
507 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
508{
Philipp Maierfbf66102017-04-09 12:32:51 +0200509 gsmnet->a.cs7_instance = atoi(argv[0]);
510 return CMD_SUCCESS;
511}
512
513DEFUN(cfg_msc_cs7_instance_iu,
514 cfg_msc_cs7_instance_iu_cmd,
515 "cs7-instance-iu <0-15>",
516 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
517{
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100518#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200519 gsmnet->iu.cs7_instance = atoi(argv[0]);
520 return CMD_SUCCESS;
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100521#else
522 vty_out(vty, "WARNING: 'cs7-instance-iu' without effect: built without Iu support%s",
523 VTY_NEWLINE);
524 return CMD_WARNING;
525#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200526}
527
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100528DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
529 "auth-tuple-max-reuse-count <-1-2147483647>",
530 "Configure authentication tuple re-use\n"
531 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
532{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100533 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
534 return CMD_SUCCESS;
535}
536
537DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
538 "auth-tuple-reuse-on-error (0|1)",
539 "Configure authentication tuple re-use when HLR is not responsive\n"
Oliver Smithd6e24fd2019-01-09 10:46:43 +0100540 "Never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
541 "If the HLR does not deliver new tuples, do re-use already available old ones.\n")
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100542{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100543 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
544 return CMD_SUCCESS;
545}
546
Oliver Smith0fec28a2018-12-14 10:52:52 +0100547DEFUN(cfg_msc_check_imei_rqd, cfg_msc_check_imei_rqd_cmd,
Oliver Smith03ded912019-05-02 10:40:50 +0200548 "check-imei-rqd (0|1|early)",
Oliver Smith0fec28a2018-12-14 10:52:52 +0100549 "Send each IMEI to the EIR to ask if it is permitted or not. The EIR is implemented as part of OsmoHLR, "
550 "and can optionally save the IMEI in the HLR.\n"
551 "Do not send IMEIs to the EIR\n"
Oliver Smith03ded912019-05-02 10:40:50 +0200552 "Send each IMEI to the EIR\n"
553 "Send each IMEI to the EIR, and do it at the start of the location update. This allows the EIR to receive the"
554 " 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 +0100555{
Oliver Smith03ded912019-05-02 10:40:50 +0200556 if (strcmp(argv[0], "0") == 0) {
557 gsmnet->vlr->cfg.check_imei_rqd = false;
558 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
559 } else if (strcmp(argv[0], "1") == 0) {
560 gsmnet->vlr->cfg.check_imei_rqd = true;
561 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
562 } else if (strcmp(argv[0], "early") == 0) {
563 gsmnet->vlr->cfg.check_imei_rqd = true;
564 gsmnet->vlr->cfg.retrieve_imeisv_early = true;
565 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100566 return CMD_SUCCESS;
567}
568
Alexander Couzensae167fc2020-09-25 05:25:16 +0200569DEFUN_DEPRECATED(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100570 "paging response-timer (default|<1-65535>)",
571 "Configure Paging\n"
572 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
573 " BSS or RNC\n"
574 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
575 "Set paging timeout in seconds\n")
576{
Alexander Couzensae167fc2020-09-25 05:25:16 +0200577 int rat;
578 int paging_response_timer;
Pau Espin Pedrolb08a3802019-09-16 19:01:37 +0200579 if (!strcmp(argv[0], "default"))
Alexander Couzensae167fc2020-09-25 05:25:16 +0200580 paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100581 else
Alexander Couzensae167fc2020-09-25 05:25:16 +0200582 paging_response_timer = atoi(argv[0]);
583
584 for (rat = 0; rat < OSMO_RAT_COUNT; rat++) {
585 osmo_tdef_set(msc_ran_infra[rat].tdefs, -4, paging_response_timer, OSMO_TDEF_S);
586 }
587
588 vty_out(vty, "%% paging response-timer is deprecated.%s"
589 "%% All ran timer has been modified.%s"
590 "%% use 'timer <geran|utran|sgs> X4 %s' instead%s",
591 VTY_NEWLINE, VTY_NEWLINE, argv[0], VTY_NEWLINE);
592
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100593 return CMD_SUCCESS;
594}
595
Harald Welte69c54a82018-02-09 20:41:14 +0100596DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
597 "emergency-call route-to-msisdn MSISDN",
598 "Configure Emergency Call Behaviour\n"
599 "MSISDN to which Emergency Calls are Dispatched\n"
600 "MSISDN (E.164 Phone Number)\n")
601{
Harald Welte69c54a82018-02-09 20:41:14 +0100602 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
603
604 return CMD_SUCCESS;
605}
606
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700607/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
608DEFUN(cfg_msc_sms_over_gsup, cfg_msc_sms_over_gsup_cmd,
609 "sms-over-gsup",
610 "Enable routing of SMS messages over GSUP\n")
611{
612 gsmnet->sms_over_gsup = true;
613 return CMD_SUCCESS;
614}
615
616/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
617DEFUN(cfg_msc_no_sms_over_gsup, cfg_msc_no_sms_over_gsup_cmd,
618 "no sms-over-gsup",
619 NO_STR "Disable routing of SMS messages over GSUP\n")
620{
621 gsmnet->sms_over_gsup = false;
622 return CMD_SUCCESS;
623}
624
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100625/* FIXME: This should rather be in the form of
626 * handover-number range 001234xxx
627 * and
628 * handover-number range 001234xxx FIRST LAST
629 */
630DEFUN(cfg_msc_handover_number_range, cfg_msc_handover_number_range_cmd,
631 "handover-number range MSISDN_FIRST MSISDN_LAST",
632 "Configure a range of MSISDN to be assigned to incoming inter-MSC Handovers for call forwarding.\n"
633 "Configure a handover number range\n"
634 "First Handover Number MSISDN\n"
635 "Last Handover Number MSISDN\n")
636{
637 char *endp;
638 uint64_t range_start;
639 uint64_t range_end;
640
641 /* FIXME leading zeros?? */
642
643 errno = 0;
644 range_start = strtoull(argv[0], &endp, 10);
645 if (errno || *endp != '\0') {
646 vty_out(vty, "%% Error parsing handover-number range start: %s%s",
647 argv[0], VTY_NEWLINE);
648 return CMD_WARNING;
649 }
650
651 errno = 0;
652 range_end = strtoull(argv[1], &endp, 10);
653 if (errno || *endp != '\0') {
654 vty_out(vty, "%% Error parsing handover-number range end: %s%s",
655 argv[1], VTY_NEWLINE);
656 return CMD_WARNING;
657 }
658
659 if (range_start > range_end) {
660 vty_out(vty, "%% Error: handover-number range end must be > than the range start, but"
661 " %"PRIu64" > %"PRIu64"%s", range_start, range_end, VTY_NEWLINE);
662 return CMD_WARNING;
663 }
664
665 gsmnet->handover_number.range_start = range_start;
666 gsmnet->handover_number.range_end = range_end;
667 return CMD_SUCCESS;
668}
669
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200670#define OSMUX_STR "RTP multiplexing\n"
671DEFUN(cfg_msc_osmux,
672 cfg_msc_osmux_cmd,
673 "osmux (on|off|only)",
674 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
675{
676 if (strcmp(argv[0], "off") == 0)
677 gsmnet->use_osmux = OSMUX_USAGE_OFF;
678 else if (strcmp(argv[0], "on") == 0)
679 gsmnet->use_osmux = OSMUX_USAGE_ON;
680 else if (strcmp(argv[0], "only") == 0)
681 gsmnet->use_osmux = OSMUX_USAGE_ONLY;
682
683 return CMD_SUCCESS;
684}
685
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +0200686#define NRI_STR "Mapping of Network Resource Indicators to this MSC, for MSC pooling\n"
687DEFUN(cfg_msc_nri_bitlen, cfg_msc_nri_bitlen_cmd,
688 "nri bitlen <0-15>",
689 NRI_STR
690 "Set number of NRI bits to place in TMSI identities (always starting just after the most significant octet)\n"
691 "bit count (default: " OSMO_STRINGIFY_VAL(NRI_BITLEN_DEFAULT) ")\n")
692{
693 gsmnet->vlr->cfg.nri_bitlen = atoi(argv[0]);
694 return CMD_SUCCESS;
695}
696
697#define NRI_STR "Mapping of Network Resource Indicators to this MSC, for MSC pooling\n"
698#define NRI_ARGS_TO_STR_FMT "%s%s%s"
699#define NRI_ARGS_TO_STR_ARGS(ARGC, ARGV) ARGV[0], (ARGC>1)? ".." : "", (ARGC>1)? ARGV[1] : ""
700#define NRI_FIRST_LAST_STR "First value of the NRI value range, should not surpass the configured 'nri bitlen'.\n" \
701 "Last value of the NRI value range, should not surpass the configured 'nri bitlen' and be larger than the" \
702 " first value; if omitted, apply only the first value.\n"
703
704DEFUN(cfg_msc_nri_add, cfg_msc_nri_add_cmd,
705 "nri add <0-32767> [<0-32767>]",
706 NRI_STR "Add NRI value or range to the NRI mapping for this MSC\n"
707 NRI_FIRST_LAST_STR)
708{
709 const char *message;
710 int rc = osmo_nri_ranges_vty_add(&message, NULL, gsmnet->vlr->cfg.nri_ranges, argc, argv, gsmnet->vlr->cfg.nri_bitlen);
711 if (message) {
712 vty_out(vty, "%% %s: " NRI_ARGS_TO_STR_FMT, message, NRI_ARGS_TO_STR_ARGS(argc, argv));
713 }
714 if (rc < 0)
715 return CMD_WARNING;
716 return CMD_SUCCESS;
717}
718
719DEFUN(cfg_msc_nri_del, cfg_msc_nri_del_cmd,
720 "nri del <0-32767> [<0-32767>]",
721 NRI_STR "Remove NRI value or range from the NRI mapping for this MSC\n"
722 NRI_FIRST_LAST_STR)
723{
724 const char *message;
725 int rc = osmo_nri_ranges_vty_del(&message, NULL, gsmnet->vlr->cfg.nri_ranges, argc, argv);
726 if (message) {
727 vty_out(vty, "%% %s: " NRI_ARGS_TO_STR_FMT, message, NRI_ARGS_TO_STR_ARGS(argc, argv));
728 }
729 if (rc < 0)
730 return CMD_WARNING;
731 return CMD_SUCCESS;
732}
733
734static void msc_write_nri(struct vty *vty)
735{
736 struct osmo_nri_range *r;
737
738 llist_for_each_entry(r, &gsmnet->vlr->cfg.nri_ranges->entries, entry) {
739 if (osmo_nri_range_validate(r, 255))
740 vty_out(vty, " %% INVALID RANGE:");
741 vty_out(vty, " nri add %d", r->first);
742 if (r->first != r->last)
743 vty_out(vty, " %d", r->last);
744 vty_out(vty, "%s", VTY_NEWLINE);
745 }
746}
747
748DEFUN(show_nri, show_nri_cmd,
749 "show nri",
750 SHOW_STR NRI_STR)
751{
752 msc_write_nri(vty);
753 return CMD_SUCCESS;
754}
755
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200756static int config_write_msc(struct vty *vty)
757{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200758 vty_out(vty, "msc%s", VTY_NEWLINE);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100759 if (gsmnet->mncc_sock_path)
760 vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE);
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100761 vty_out(vty, " mncc guard-timeout %i%s",
Philipp Maier9ca7b312018-10-10 17:00:49 +0200762 gsmnet->mncc_guard_timeout, VTY_NEWLINE);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700763 vty_out(vty, " ncss guard-timeout %i%s",
764 gsmnet->ncss_guard_timeout, VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200765 vty_out(vty, " %sassign-tmsi%s",
766 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
Keith Whytea1a70be2021-05-16 02:59:52 +0200767 if (gsmnet->lcls_permitted)
768 vty_out(vty, " lcls-permitted%s", VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200769
Philipp Maierfbf66102017-04-09 12:32:51 +0200770 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
771 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100772#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200773 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
774 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100775#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200776
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100777 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
778 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
779 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
780 VTY_NEWLINE);
781 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
782 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
783 VTY_NEWLINE);
784
Oliver Smith03ded912019-05-02 10:40:50 +0200785 if (gsmnet->vlr->cfg.check_imei_rqd) {
786 if (gsmnet->vlr->cfg.retrieve_imeisv_early)
787 vty_out(vty, " check-imei-rqd early%s", VTY_NEWLINE);
788 else
789 vty_out(vty, " check-imei-rqd 1%s", VTY_NEWLINE);
790 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100791
Harald Welte69c54a82018-02-09 20:41:14 +0100792 if (gsmnet->emergency.route_to_msisdn) {
793 vty_out(vty, " emergency-call route-to-msisdn %s%s",
794 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
795 }
796
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700797 if (gsmnet->sms_over_gsup)
798 vty_out(vty, " sms-over-gsup%s", VTY_NEWLINE);
799
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100800 if (gsmnet->handover_number.range_start || gsmnet->handover_number.range_end)
801 vty_out(vty, " handover-number range %"PRIu64" %"PRIu64"%s",
802 gsmnet->handover_number.range_start, gsmnet->handover_number.range_end,
803 VTY_NEWLINE);
804
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200805 if (gsmnet->use_osmux != OSMUX_USAGE_OFF) {
806 vty_out(vty, " osmux %s%s", gsmnet->use_osmux == OSMUX_USAGE_ON ? "on" : "only",
807 VTY_NEWLINE);
808 }
809
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200810 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200811#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200812 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200813#endif
814
Neels Hofmeyr880b9502019-05-09 02:01:55 +0200815 neighbor_ident_vty_write(vty);
816
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +0700817 /* Timer introspection commands (generic osmo_tdef API) */
818 osmo_tdef_vty_groups_write(vty, " ");
819
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +0200820 msc_write_nri(vty);
821
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200822 return CMD_SUCCESS;
823}
824
Maxc51609a2018-11-09 17:13:00 +0100825DEFUN(show_bsc, show_bsc_cmd,
826 "show bsc", SHOW_STR "BSC\n")
827{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100828 struct ran_peer *rp;
829 llist_for_each_entry(rp, &gsmnet->a.sri->ran_peers, entry) {
830 vty_out(vty, "BSC %s %s%s",
831 osmo_sccp_inst_addr_name(gsmnet->a.sri->sccp, &rp->peer_addr),
832 osmo_fsm_inst_state_name(rp->fi),
833 VTY_NEWLINE);
Maxc51609a2018-11-09 17:13:00 +0100834 }
835
836 return CMD_SUCCESS;
837}
838
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100839static const char *get_trans_proto_str(const struct gsm_trans *trans)
840{
841 static char buf[256];
842
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100843 switch (trans->type) {
844 case TRANS_CC:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100845 snprintf(buf, sizeof(buf), "%s %4u %4u",
846 gsm48_cc_state_name(trans->cc.state),
847 trans->cc.Tcurrent,
848 trans->cc.T308_second);
849 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100850 case TRANS_SMS:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700851 snprintf(buf, sizeof(buf), "CP:%s RP:%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100852 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
853 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
854 break;
855 default:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700856 return NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100857 }
858
859 return buf;
860}
861
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700862/* Prefix a given format string with a given amount of spaces */
863#define MSC_VTY_DUMP(vty, offset, fmt, args...) \
864 vty_out(vty, "%*s" fmt, offset, "", ##args)
865
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200866/* Print value of a named flag, prefixed with a given amount of spaces */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700867#define MSC_VTY_DUMP_FLAG(vty, offset, name, flag) \
868 MSC_VTY_DUMP(vty, offset + 2, "%s: %*s%s%s", \
869 name, 30 - (int)strlen(name), "", \
870 flag ? "true" : "false", \
871 VTY_NEWLINE)
872
873enum msc_vty_dump_flags {
874 MSC_VTY_DUMP_F_SUBSCR = (1 << 0),
875 MSC_VTY_DUMP_F_CONNECTION = (1 << 1),
876 MSC_VTY_DUMP_F_TRANSACTION = (1 << 2),
877};
878
879static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans,
880 int offset, uint8_t dump_flags)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100881{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700882 const char *proto_str;
883
884 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
885 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
886 vlr_subscr_name(msc_a_vsub(trans->msc_a)),
887 VTY_NEWLINE);
888 }
889
890 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200891 /* (If msc_a exists, there *must* be a non-null msc_a->c.msub) */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700892 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
893 trans->msc_a ? msub_ran_conn_name(trans->msc_a->c.msub)
894 : "(not established)",
895 VTY_NEWLINE);
896 }
897
898 MSC_VTY_DUMP(vty, offset, "Unique (global) identifier: 0x%08x%s",
899 trans->callref, VTY_NEWLINE);
900 MSC_VTY_DUMP(vty, offset, "GSM 04.07 identifier (%s): %u%s",
901 (trans->transaction_id & 0x08) ? "MO" : "MT",
902 trans->transaction_id,
903 VTY_NEWLINE);
904
905 MSC_VTY_DUMP(vty, offset, "Type: %s%s",
906 trans_type_name(trans->type),
907 VTY_NEWLINE);
908
909 if ((proto_str = get_trans_proto_str(trans))) {
910 MSC_VTY_DUMP(vty, offset, "Protocol specific: %s%s",
911 proto_str, VTY_NEWLINE);
912 }
913}
914
915static void vty_dump_one_conn(struct vty *vty, const struct msub *msub,
916 int offset, uint8_t dump_flags)
917{
918 struct vlr_subscr *vsub = msub_vsub(msub);
919 struct msc_a *msc_a = msub_msc_a(msub);
920 char buf[128];
921
922 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
923 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
924 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
925 vlr_subscr_name(vsub),
926 VTY_NEWLINE);
927 }
928
929 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
930 msub_ran_conn_name(msub),
931 VTY_NEWLINE);
932 MSC_VTY_DUMP(vty, offset, "RAN connection state: %s%s",
933 osmo_fsm_inst_state_name(msc_a->c.fi),
934 VTY_NEWLINE);
935
936 if (vsub) {
937 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
Neels Hofmeyr41c03332020-06-24 15:02:27 +0200938 msc_a->via_cell.lai.lac, msc_a->via_cell.cell_identity,
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700939 VTY_NEWLINE);
940 }
941
942 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
943 osmo_use_count_total(&msc_a->use_count),
944 VTY_NEWLINE);
945 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
946 osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count),
947 VTY_NEWLINE);
948
949 /* Transactions of this connection */
950 if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
951 struct gsm_trans *trans;
952 unsigned int i = 0;
953
954 /* Both subscriber and connection info is already printed */
955 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_CONNECTION;
956 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
957
958 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
959 if (trans->msc_a != msc_a)
960 continue;
961 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
962 i++, VTY_NEWLINE);
963 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
964 }
965 }
966}
967
968static void vty_dump_one_subscr(struct vty *vty, struct vlr_subscr *vsub,
969 int offset, uint8_t dump_flags)
970{
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700971 struct timespec now;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700972 char buf[128];
973
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700974 if (vsub->name[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700975 MSC_VTY_DUMP(vty, offset, "Name: '%s'%s",
976 vsub->name, VTY_NEWLINE);
977 }
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700978 if (vsub->msisdn[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700979 MSC_VTY_DUMP(vty, offset, "MSISDN: %s%s",
980 vsub->msisdn, VTY_NEWLINE);
981 }
982
983 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
984 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
985 VTY_NEWLINE);
986 MSC_VTY_DUMP(vty, offset, "RAN type: %s%s",
987 osmo_rat_type_name(vsub->cs.attached_via_ran),
988 VTY_NEWLINE);
989
990 MSC_VTY_DUMP(vty, offset, "IMSI: %s%s",
991 vsub->imsi, VTY_NEWLINE);
992 if (vsub->tmsi != GSM_RESERVED_TMSI) {
993 MSC_VTY_DUMP(vty, offset, "TMSI: %08X%s",
994 vsub->tmsi, VTY_NEWLINE);
995 }
996 if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
997 MSC_VTY_DUMP(vty, offset, "New TMSI: %08X%s",
998 vsub->tmsi_new, VTY_NEWLINE);
999 }
1000 if (vsub->imei[0] != '\0') {
1001 MSC_VTY_DUMP(vty, offset, "IMEI: %s%s",
1002 vsub->imei, VTY_NEWLINE);
1003 }
1004 if (vsub->imeisv[0] != '\0') {
1005 MSC_VTY_DUMP(vty, offset, "IMEISV: %s%s",
1006 vsub->imeisv, VTY_NEWLINE);
1007 }
1008
1009 MSC_VTY_DUMP(vty, offset, "Flags: %s", VTY_NEWLINE);
1010 MSC_VTY_DUMP_FLAG(vty, offset, "IMSI detached",
1011 vsub->imsi_detached_flag);
1012 MSC_VTY_DUMP_FLAG(vty, offset, "Conf. by radio contact",
1013 vsub->conf_by_radio_contact_ind);
1014 MSC_VTY_DUMP_FLAG(vty, offset, "Subscr. data conf. by HLR",
1015 vsub->sub_dataconf_by_hlr_ind);
1016 MSC_VTY_DUMP_FLAG(vty, offset, "Location conf. in HLR",
1017 vsub->loc_conf_in_hlr_ind);
1018 MSC_VTY_DUMP_FLAG(vty, offset, "Subscriber dormant",
1019 vsub->dormant_ind);
1020 MSC_VTY_DUMP_FLAG(vty, offset, "Received cancel location",
1021 vsub->cancel_loc_rx);
1022 MSC_VTY_DUMP_FLAG(vty, offset, "MS not reachable",
1023 vsub->ms_not_reachable_flag);
1024 MSC_VTY_DUMP_FLAG(vty, offset, "LA allowed",
1025 vsub->la_allowed);
1026
1027 if (vsub->last_tuple) {
1028 struct vlr_auth_tuple *t = vsub->last_tuple;
1029 MSC_VTY_DUMP(vty, offset, "A3A8 last tuple (used %d times): %s",
1030 t->use_count, VTY_NEWLINE);
1031 MSC_VTY_DUMP(vty, offset + 2, "seq # : %d%s",
1032 t->key_seq, VTY_NEWLINE);
1033 MSC_VTY_DUMP(vty, offset + 2, "RAND : %s%s",
1034 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
1035 VTY_NEWLINE);
1036 MSC_VTY_DUMP(vty, offset + 2, "SRES : %s%s",
1037 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
1038 VTY_NEWLINE);
1039 MSC_VTY_DUMP(vty, offset + 2, "Kc : %s%s",
1040 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
1041 VTY_NEWLINE);
1042 }
1043
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +07001044 if (!vlr_timer(vsub->vlr, 3212)) {
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +07001045 MSC_VTY_DUMP(vty, offset, "Expires: never (T3212 is disabled)%s",
1046 VTY_NEWLINE);
1047 } else if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) {
1048 MSC_VTY_DUMP(vty, offset, "Expires: never%s",
1049 VTY_NEWLINE);
1050 } else if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
1051 MSC_VTY_DUMP(vty, offset, "Expires: in %ld min %ld sec%s",
1052 (vsub->expire_lu - now.tv_sec) / 60,
1053 (vsub->expire_lu - now.tv_sec) % 60,
1054 VTY_NEWLINE);
1055 }
1056
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001057 MSC_VTY_DUMP(vty, offset, "Paging: %s paging for %d requests%s",
1058 vsub->cs.is_paging ? "is" : "not",
1059 llist_count(&vsub->cs.requests),
1060 VTY_NEWLINE);
1061
1062 /* SGs related */
1063 MSC_VTY_DUMP(vty, offset, "SGs-state: %s%s",
1064 osmo_fsm_inst_state_name(vsub->sgs_fsm),
1065 VTY_NEWLINE);
1066 MSC_VTY_DUMP(vty, offset, "SGs-MME: %s%s",
Vadim Yanitskiydcf28682019-05-29 22:34:13 +07001067 vsub->sgs.mme_name[0] != '\0' ? vsub->sgs.mme_name : "(none)",
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001068 VTY_NEWLINE);
1069
1070 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
1071 osmo_use_count_total(&vsub->use_count),
1072 VTY_NEWLINE);
1073 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
1074 osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count),
1075 VTY_NEWLINE);
1076
1077 /* Connection(s) and/or transactions of this subscriber */
1078 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
1079 struct msub *msub = msub_for_vsub(vsub);
1080 if (!msub)
1081 return;
1082
1083 /* Subscriber info is already printed */
1084 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
1085
1086 MSC_VTY_DUMP(vty, offset, "Connection: %s", VTY_NEWLINE);
1087 vty_dump_one_conn(vty, msub, offset + 2, dump_flags);
1088 } else if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
1089 struct gsm_trans *trans;
1090 unsigned int i = 0;
1091
1092 /* Subscriber info is already printed */
1093 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
1094 /* Do not print connection info, but mention it */
1095 dump_flags |= MSC_VTY_DUMP_F_CONNECTION;
1096
1097 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1098 if (trans->vsub != vsub)
1099 continue;
1100 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
1101 i++, VTY_NEWLINE);
1102 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
1103 }
1104 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001105}
1106
1107DEFUN(show_msc_transaction, show_msc_transaction_cmd,
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001108 "show transaction",
1109 SHOW_STR "Transactions\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001110{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001111 struct gsm_trans *trans;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001112 uint8_t flags = 0x00;
1113 unsigned int i = 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001114
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001115 flags |= MSC_VTY_DUMP_F_CONNECTION;
1116 flags |= MSC_VTY_DUMP_F_SUBSCR;
1117
1118 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1119 vty_out(vty, " Transaction #%02u: %s", i++, VTY_NEWLINE);
1120 vty_dump_one_trans(vty, trans, 4, flags);
1121 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001122
1123 return CMD_SUCCESS;
1124}
1125
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001126DEFUN(show_msc_conn, show_msc_conn_cmd,
1127 "show connection [trans]",
1128 SHOW_STR "Subscriber Connections\n"
1129 "Show child transactions of each connection\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001130{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001131 uint8_t flags = 0x00;
1132 unsigned int i = 0;
1133 struct msub *msub;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001134
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001135 if (argc > 0)
1136 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1137 flags |= MSC_VTY_DUMP_F_SUBSCR;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001138
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001139 llist_for_each_entry(msub, &msub_list, entry) {
1140 vty_out(vty, " Connection #%02u: %s", i++, VTY_NEWLINE);
1141 vty_dump_one_conn(vty, msub, 4, flags);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001142 }
1143
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001144 return CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001145}
1146
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001147#define SUBSCR_FLAGS "[(conn|trans|conn+trans)]"
1148#define SUBSCR_FLAGS_HELP \
1149 "Show child connections\n" \
1150 "Show child transactions\n" \
1151 "Show child connections and transactions\n"
1152
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001153/* Subscriber */
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001154DEFUN(show_subscr_cache, show_subscr_cache_cmd,
1155 "show subscriber cache " SUBSCR_FLAGS,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001156 SHOW_STR "Show information about subscribers\n"
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001157 "Display contents of subscriber cache\n"
1158 SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001159{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001160 struct vlr_subscr *vsub;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001161 unsigned int count = 0;
1162 uint8_t flags = 0x00;
1163 unsigned int i = 0;
1164
1165 if (argc && strcmp(argv[0], "conn") == 0)
1166 flags |= MSC_VTY_DUMP_F_CONNECTION;
1167 else if (argc && strcmp(argv[0], "trans") == 0)
1168 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1169 else if (argc && strcmp(argv[0], "conn+trans") == 0)
1170 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001171
1172 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
1173 if (++count > 100) {
1174 vty_out(vty, "%% More than %d subscribers in cache,"
1175 " stopping here.%s", count-1, VTY_NEWLINE);
1176 break;
1177 }
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001178 vty_out(vty, " Subscriber #%02u: %s", i++, VTY_NEWLINE);
1179 vty_dump_one_subscr(vty, vsub, 4, flags);
Harald Welte69c54a82018-02-09 20:41:14 +01001180 }
1181
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001182 return CMD_SUCCESS;
1183}
1184
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001185DEFUN(sms_send_pend,
1186 sms_send_pend_cmd,
1187 "sms send pending",
1188 "SMS related commands\n" "SMS Sending related commands\n"
1189 "Send all pending SMS")
1190{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001191 struct gsm_sms *sms;
1192 unsigned long long sms_id = 0;
1193
1194 while (1) {
1195 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1196 if (!sms)
1197 break;
1198
1199 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001200 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001201
1202 sms_id = sms->id + 1;
1203 }
1204
1205 return CMD_SUCCESS;
1206}
1207
1208DEFUN(sms_delete_expired,
1209 sms_delete_expired_cmd,
1210 "sms delete expired",
1211 "SMS related commands\n" "SMS Database related commands\n"
1212 "Delete all expired SMS")
1213{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001214 struct gsm_sms *sms;
1215 unsigned long long sms_id = 0;
1216 long long num_deleted = 0;
1217
1218 while (1) {
1219 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1220 if (!sms)
1221 break;
1222
1223 /* Skip SMS which are currently queued for sending. */
1224 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
1225 continue;
1226
1227 /* Expiration check is performed by the DB layer. */
1228 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
1229 num_deleted++;
1230
1231 sms_id = sms->id + 1;
1232 }
1233
1234 if (num_deleted == 0) {
1235 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
1236 return CMD_WARNING;
1237 }
1238
1239 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
1240 return CMD_SUCCESS;
1241}
1242
1243static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +02001244 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001245 char *str, uint8_t tp_pid)
1246{
1247 struct gsm_network *net = receiver->vlr->user_ctx;
1248 struct gsm_sms *sms;
1249
Harald Welte39b55482018-04-09 19:19:33 +02001250 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Vadim Yanitskiydb4839c2019-12-01 18:52:58 +07001251 if (!sms) {
1252 LOGP(DLSMS, LOGL_ERROR, "Failed to allocate SMS\n");
1253 return CMD_WARNING;
1254 }
1255
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001256 sms->protocol_id = tp_pid;
1257
1258 /* store in database for the queue */
1259 if (db_sms_store(sms) != 0) {
1260 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
1261 sms_free(sms);
1262 return CMD_WARNING;
1263 }
1264 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
1265
1266 sms_free(sms);
1267 sms_queue_trigger(net->sms_queue);
1268 return CMD_SUCCESS;
1269}
1270
1271static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
1272 const char *type,
1273 const char *id)
1274{
1275 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001276 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001277 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001278 return vlr_subscr_find_by_imsi(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001279 else if (!strcmp(type, "tmsi"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001280 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id), VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001281
1282 return NULL;
1283}
1284#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
1285#define SUBSCR_HELP "Operations on a Subscriber\n" \
1286 "Identify subscriber by MSISDN (phone number)\n" \
1287 "Legacy alias for 'msisdn'\n" \
1288 "Identify subscriber by IMSI\n" \
1289 "Identify subscriber by TMSI\n" \
Vadim Yanitskiy3ccd8232019-05-16 01:35:23 +07001290 "Legacy alias for 'imsi'\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001291 "Identifier for the subscriber\n"
1292
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001293DEFUN(show_subscr, show_subscr_cmd,
1294 "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
1295 SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001296{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001297 struct vlr_subscr *vsub;
1298 uint8_t flags = 0x00;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001299
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001300 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001301 if (!vsub) {
1302 vty_out(vty, "%% No subscriber found for %s %s%s",
1303 argv[0], argv[1], VTY_NEWLINE);
1304 return CMD_WARNING;
1305 }
1306
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001307 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
1308 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
1309 * 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 +01001310 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001311
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001312 if (argc > 2 && strcmp(argv[2], "conn") == 0)
1313 flags |= MSC_VTY_DUMP_F_CONNECTION;
1314 else if (argc > 2 && strcmp(argv[2], "trans") == 0)
1315 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1316 else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
1317 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
1318
1319 vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
1320 vty_dump_one_subscr(vty, vsub, 4, flags);
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001321
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001322 return CMD_SUCCESS;
1323}
1324
Vadim Yanitskiyb7ddbf32020-01-20 21:30:09 +07001325DEFUN_DEPRECATED(subscriber_create, subscriber_create_cmd,
1326 "subscriber create imsi ID",
1327 "Operations on a Subscriber\n"
1328 "Create new subscriber\n"
1329 "Identify the subscriber by his IMSI\n"
1330 "Identifier for the subscriber\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001331{
1332 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
1333 VTY_NEWLINE);
1334 return CMD_WARNING;
1335}
1336
1337DEFUN(subscriber_send_pending_sms,
1338 subscriber_send_pending_sms_cmd,
1339 "subscriber " SUBSCR_TYPES " ID sms pending-send",
1340 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
1341{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001342 struct vlr_subscr *vsub;
1343 struct gsm_sms *sms;
1344
1345 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1346 if (!vsub) {
1347 vty_out(vty, "%% No subscriber found for %s %s%s",
1348 argv[0], argv[1], VTY_NEWLINE);
1349 return CMD_WARNING;
1350 }
1351
1352 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
1353 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001354 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001355
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001356 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001357
1358 return CMD_SUCCESS;
1359}
1360
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001361DEFUN(subscriber_sms_delete_all,
1362 subscriber_sms_delete_all_cmd,
1363 "subscriber " SUBSCR_TYPES " ID sms delete-all",
1364 SUBSCR_HELP "SMS Operations\n"
1365 "Delete all SMS to be delivered to this subscriber"
1366 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
1367 " WILL BE LOST.\n")
1368{
1369 struct vlr_subscr *vsub;
1370
1371 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1372 if (!vsub) {
1373 vty_out(vty, "%% No subscriber found for %s %s%s",
1374 argv[0], argv[1], VTY_NEWLINE);
1375 return CMD_WARNING;
1376 }
1377
1378 db_sms_delete_by_msisdn(vsub->msisdn);
1379
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001380 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001381
1382 return CMD_SUCCESS;
1383}
1384
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001385DEFUN(subscriber_send_sms,
1386 subscriber_send_sms_cmd,
1387 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1388 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1389{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001390 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001391 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001392 char *str;
1393 int rc;
1394
1395 if (!vsub) {
1396 vty_out(vty, "%% No subscriber found for %s %s%s",
1397 argv[0], argv[1], VTY_NEWLINE);
1398 rc = CMD_WARNING;
1399 goto err;
1400 }
1401
Harald Welte39b55482018-04-09 19:19:33 +02001402 if (!strcmp(argv[2], "msisdn"))
1403 sender_msisdn = argv[3];
1404 else {
1405 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1406 if (!sender) {
1407 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1408 rc = CMD_WARNING;
1409 goto err;
1410 }
1411 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001412 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001413 }
1414
1415 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001416 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001417 talloc_free(str);
1418
1419err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001420 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001421 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001422
1423 return rc;
1424}
1425
1426DEFUN(subscriber_silent_sms,
1427 subscriber_silent_sms_cmd,
1428
1429 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1430 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1431{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001432 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001433 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001434 char *str;
1435 int rc;
1436
1437 if (!vsub) {
1438 vty_out(vty, "%% No subscriber found for %s %s%s",
1439 argv[0], argv[1], VTY_NEWLINE);
1440 rc = CMD_WARNING;
1441 goto err;
1442 }
1443
Harald Welte39b55482018-04-09 19:19:33 +02001444 if (!strcmp(argv[2], "msisdn")) {
1445 sender_msisdn = argv[3];
1446 } else {
1447 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1448 if (!sender) {
1449 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1450 rc = CMD_WARNING;
1451 goto err;
1452 }
1453 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001454 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001455 }
1456
1457 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001458 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001459 talloc_free(str);
1460
1461err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001462 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001463 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001464
1465 return rc;
1466}
1467
Sylvain Munaut93558302019-02-14 20:13:08 +01001468#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001469#define CHAN_TYPE_HELP \
1470 "Any channel\n" \
1471 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001472 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001473 "Any TCH channel\n" \
1474 "SDCCH channel\n"
1475
Sylvain Munaut93558302019-02-14 20:13:08 +01001476#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1477#define CHAN_MODE_HELP \
1478 "Signalling only\n" \
1479 "Speech with HR codec\n" \
1480 "Speech with FR codec\n" \
1481 "Speech with EFR codec\n" \
1482 "Speech with AMR codec\n"
1483
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001484DEFUN(subscriber_silent_call_start,
1485 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001486 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001487 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001488 CHAN_TYPE_HELP CHAN_MODE_HELP
1489 "Target IP for RTP traffic (default 127.0.0.1)\n"
1490 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001491{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001492 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001493 struct gsm0808_channel_type ct;
1494 const char *ip;
1495 uint16_t port;
1496 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001497
1498 if (!vsub) {
1499 vty_out(vty, "%% No subscriber found for %s %s%s",
1500 argv[0], argv[1], VTY_NEWLINE);
1501 return CMD_WARNING;
1502 }
1503
Sylvain Munaut93558302019-02-14 20:13:08 +01001504 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001505
Sylvain Munaut93558302019-02-14 20:13:08 +01001506 if (!strcmp(argv[3], "signalling")) {
1507 ct.ch_indctr = GSM0808_CHAN_SIGN;
1508 ct.perm_spch[0] = 0; /* Spare but required */
1509 ct.perm_spch_len = 1;
1510 } else if (!strcmp(argv[3], "speech-hr")) {
1511 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1512 ct.perm_spch[0] = GSM0808_PERM_HR1;
1513 ct.perm_spch_len = 1;
1514 } else if (!strcmp(argv[3], "speech-fr")) {
1515 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1516 ct.perm_spch[0] = GSM0808_PERM_FR1;
1517 ct.perm_spch_len = 1;
1518 } else if (!strcmp(argv[3], "speech-efr")) {
1519 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1520 ct.perm_spch[0] = GSM0808_PERM_FR2;
1521 ct.perm_spch_len = 1;
1522 } else if (!strcmp(argv[3], "speech-amr")) {
1523 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1524 ct.perm_spch[0] = GSM0808_PERM_FR3;
1525 ct.perm_spch[1] = GSM0808_PERM_HR3;
1526 ct.perm_spch_len = 2;
1527 }
1528
1529 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1530
1531 if (!strcmp(argv[2], "tch/f"))
1532 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1533 else if (!strcmp(argv[2], "tch/h"))
1534 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1535 else if (!strcmp(argv[2], "tch/any"))
1536 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1537 else if (!strcmp(argv[2], "sdcch")) {
1538 if (speech) {
1539 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1540 return CMD_WARNING;
1541 }
1542 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1543 } else
1544 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1545
1546 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1547 port = argc >= 6 ? atoi(argv[5]) : 4000;
1548
1549 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001550 switch (rc) {
1551 case -ENODEV:
1552 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1553 break;
1554 default:
1555 if (rc)
1556 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1557 else
1558 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1559 break;
1560 }
1561
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001562 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001563 return rc ? CMD_WARNING : CMD_SUCCESS;
1564}
1565
1566DEFUN(subscriber_silent_call_stop,
1567 subscriber_silent_call_stop_cmd,
1568 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1569 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1570 CHAN_TYPE_HELP)
1571{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001572 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1573 int rc;
1574
1575 if (!vsub) {
1576 vty_out(vty, "%% No subscriber found for %s %s%s",
1577 argv[0], argv[1], VTY_NEWLINE);
1578 return CMD_WARNING;
1579 }
1580
1581 rc = gsm_silent_call_stop(vsub);
1582 switch (rc) {
1583 case -ENODEV:
1584 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1585 break;
1586 case -ENOENT:
1587 vty_out(vty, "%% Subscriber has no silent call active%s",
1588 VTY_NEWLINE);
1589 break;
1590 default:
1591 if (rc)
1592 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1593 else
1594 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1595 break;
1596 }
1597
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001598 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001599 return rc ? CMD_WARNING : CMD_SUCCESS;
1600}
1601
1602DEFUN(subscriber_ussd_notify,
1603 subscriber_ussd_notify_cmd,
1604 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1605 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1606 "Alerting Level 0\n"
1607 "Alerting Level 1\n"
1608 "Alerting Level 2\n"
1609 "Text of USSD message to send\n")
1610{
1611 char *text;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001612 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001613 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1614 int level;
1615
1616 if (!vsub) {
1617 vty_out(vty, "%% No subscriber found for %s %s%s",
1618 argv[0], argv[1], VTY_NEWLINE);
1619 return CMD_WARNING;
1620 }
1621
1622 level = atoi(argv[2]);
1623 text = argv_concat(argv, argc, 3);
1624 if (!text) {
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001625 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001626 return CMD_WARNING;
1627 }
1628
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001629 msc_a = msc_a_for_vsub(vsub, true);
1630 if (!msc_a || msc_a->c.remote_to) {
1631 vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001632 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001633 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001634 talloc_free(text);
1635 return CMD_WARNING;
1636 }
1637
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001638 msc_send_ussd_notify(msc_a, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001639 /* FIXME: since we don't allocate a transaction here,
1640 * we use dummy GSM 04.07 transaction ID. */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001641 msc_send_ussd_release_complete(msc_a, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001642
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001643 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001644 talloc_free(text);
1645 return CMD_SUCCESS;
1646}
1647
1648DEFUN(subscriber_paging,
1649 subscriber_paging_cmd,
1650 "subscriber " SUBSCR_TYPES " ID paging",
1651 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1652{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001653 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001654 struct paging_request *req;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001655
1656 if (!vsub) {
1657 vty_out(vty, "%% No subscriber found for %s %s%s",
1658 argv[0], argv[1], VTY_NEWLINE);
1659 return CMD_WARNING;
1660 }
1661
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001662 req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL,
1663 NULL, NULL, "manual Paging from VTY");
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001664 if (req)
1665 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1666 else
1667 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1668
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001669 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001670 return req ? CMD_SUCCESS : CMD_WARNING;
1671}
1672
1673static int loop_by_char(uint8_t ch)
1674{
1675 switch (ch) {
1676 case 'a':
1677 return GSM414_LOOP_A;
1678 case 'b':
1679 return GSM414_LOOP_B;
1680 case 'c':
1681 return GSM414_LOOP_C;
1682 case 'd':
1683 return GSM414_LOOP_D;
1684 case 'e':
1685 return GSM414_LOOP_E;
1686 case 'f':
1687 return GSM414_LOOP_F;
1688 case 'i':
1689 return GSM414_LOOP_I;
1690 }
1691 return -1;
1692}
1693
1694DEFUN(subscriber_mstest_close,
1695 subscriber_mstest_close_cmd,
1696 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1697 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1698 "Close a TCH Loop inside the MS\n"
1699 "Loop Type A\n"
1700 "Loop Type B\n"
1701 "Loop Type C\n"
1702 "Loop Type D\n"
1703 "Loop Type E\n"
1704 "Loop Type F\n"
1705 "Loop Type I\n")
1706{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001707 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001708 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1709 const char *loop_str;
1710 int loop_mode;
1711
1712 if (!vsub) {
1713 vty_out(vty, "%% No subscriber found for %s %s%s",
1714 argv[0], argv[1], VTY_NEWLINE);
1715 return CMD_WARNING;
1716 }
1717
1718 loop_str = argv[2];
1719 loop_mode = loop_by_char(loop_str[0]);
1720
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001721 msc_a = msc_a_for_vsub(vsub, true);
1722 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001723 vty_out(vty, "%% An active connection is required for %s %s%s",
1724 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001725 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001726 return CMD_WARNING;
1727 }
1728
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001729 gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001730
Vadim Yanitskiy817ad902020-07-29 05:47:01 +07001731 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001732 return CMD_SUCCESS;
1733}
1734
1735DEFUN(subscriber_mstest_open,
1736 subscriber_mstest_open_cmd,
1737 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1738 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1739 "Open a TCH Loop inside the MS\n")
1740{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001741 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001742 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1743
1744 if (!vsub) {
1745 vty_out(vty, "%% No subscriber found for %s %s%s",
1746 argv[0], argv[1], VTY_NEWLINE);
1747 return CMD_WARNING;
1748 }
1749
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001750 msc_a = msc_a_for_vsub(vsub, true);
1751 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001752 vty_out(vty, "%% An active connection is required for %s %s%s",
1753 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001754 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001755 return CMD_WARNING;
1756 }
1757
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001758 gsm0414_tx_open_loop_cmd(msc_a);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001759
Vadim Yanitskiy817ad902020-07-29 05:47:01 +07001760 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001761 return CMD_SUCCESS;
1762}
1763
1764DEFUN(ena_subscr_expire,
1765 ena_subscr_expire_cmd,
1766 "subscriber " SUBSCR_TYPES " ID expire",
1767 SUBSCR_HELP "Expire the subscriber Now\n")
1768{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001769 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1770 argv[1]);
1771
1772 if (!vsub) {
1773 vty_out(vty, "%% No subscriber found for %s %s%s",
1774 argv[0], argv[1], VTY_NEWLINE);
1775 return CMD_WARNING;
1776 }
1777
1778 if (vlr_subscr_expire(vsub))
1779 vty_out(vty, "%% VLR released subscriber %s%s",
1780 vlr_subscr_name(vsub), VTY_NEWLINE);
1781
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001782 if (osmo_use_count_total(&vsub->use_count) > 1)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001783 vty_out(vty, "%% Subscriber %s is still in use,"
1784 " should be released soon%s",
1785 vlr_subscr_name(vsub), VTY_NEWLINE);
1786
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001787 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001788 return CMD_SUCCESS;
1789}
1790
1791static int scall_cbfn(unsigned int subsys, unsigned int signal,
1792 void *handler_data, void *signal_data)
1793{
1794 struct scall_signal_data *sigdata = signal_data;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001795 struct vty *vty = sigdata->vty;
1796
1797 if (!vty_is_active(vty))
1798 return 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001799
1800 switch (signal) {
1801 case S_SCALL_SUCCESS:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001802 vty_out(vty, "%% Silent call success%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001803 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001804 case S_SCALL_FAILED:
1805 vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE);
1806 break;
1807 case S_SCALL_DETACHED:
1808 vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001809 break;
1810 }
1811 return 0;
1812}
1813
1814DEFUN(show_stats,
1815 show_stats_cmd,
1816 "show statistics",
1817 SHOW_STR "Display network statistics\n")
1818{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001819 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001820 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_ATTACH)->current,
1821 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_NORMAL)->current,
1822 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_PERIODIC)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001823 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001824 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001825 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_DETACH)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001826 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001827 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001828 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_COMPLETED)->current,
1829 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_FAILED)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001830 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001831 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001832 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_SUBMITTED)->current,
1833 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_NO_RECEIVER)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001834 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001835 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001836 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_DELIVERED)->current,
1837 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_RP_ERR_MEM)->current,
1838 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_RP_ERR_OTHER)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001839 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001840 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001841 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MO_SETUP)->current,
1842 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MO_CONNECT_ACK)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001843 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001844 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001845 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MT_SETUP)->current,
1846 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MT_CONNECT)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001847 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001848 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001849 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_REQUESTS)->current,
1850 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_ESTABLISHED)->current,
1851 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_REQUESTS)->current
1852 - rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_ESTABLISHED)->current,
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001853 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001854 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001855 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_REQUESTS)->current,
1856 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_ESTABLISHED)->current,
1857 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_REQUESTS)->current
1858 - rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_ESTABLISHED)->current,
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001859 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001860 return CMD_SUCCESS;
1861}
1862
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001863
1864DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1865 "mncc-int", "Configure internal MNCC handler")
1866{
1867 vty->node = MNCC_INT_NODE;
1868
1869 return CMD_SUCCESS;
1870}
1871
1872static struct cmd_node mncc_int_node = {
1873 MNCC_INT_NODE,
1874 "%s(config-mncc-int)# ",
1875 1,
1876};
1877
1878static const struct value_string tchf_codec_names[] = {
1879 { GSM48_CMODE_SPEECH_V1, "fr" },
1880 { GSM48_CMODE_SPEECH_EFR, "efr" },
1881 { GSM48_CMODE_SPEECH_AMR, "amr" },
1882 { 0, NULL }
1883};
1884
1885static const struct value_string tchh_codec_names[] = {
1886 { GSM48_CMODE_SPEECH_V1, "hr" },
1887 { GSM48_CMODE_SPEECH_AMR, "amr" },
1888 { 0, NULL }
1889};
1890
1891static int config_write_mncc_int(struct vty *vty)
1892{
1893 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1894 vty_out(vty, " default-codec tch-f %s%s",
1895 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1896 VTY_NEWLINE);
1897 vty_out(vty, " default-codec tch-h %s%s",
1898 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1899 VTY_NEWLINE);
1900
1901 return CMD_SUCCESS;
1902}
1903
1904DEFUN(mnccint_def_codec_f,
1905 mnccint_def_codec_f_cmd,
1906 "default-codec tch-f (fr|efr|amr)",
1907 "Set default codec\n" "Codec for TCH/F\n"
1908 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1909{
1910 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1911
1912 return CMD_SUCCESS;
1913}
1914
1915DEFUN(mnccint_def_codec_h,
1916 mnccint_def_codec_h_cmd,
1917 "default-codec tch-h (hr|amr)",
1918 "Set default codec\n" "Codec for TCH/H\n"
1919 "Half-Rate\n" "Adaptive Multi-Rate\n")
1920{
1921 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1922
1923 return CMD_SUCCESS;
1924}
1925
1926
1927DEFUN(logging_fltr_imsi,
1928 logging_fltr_imsi_cmd,
1929 "logging filter imsi IMSI",
1930 LOGGING_STR FILTER_STR
1931 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1932{
1933 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001934 struct log_target *tgt = osmo_log_vty2tgt(vty);
1935 const char *imsi = argv[0];
1936
1937 if (!tgt)
1938 return CMD_WARNING;
1939
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001940 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001941
1942 if (!vlr_subscr) {
1943 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1944 argv[0], VTY_NEWLINE);
1945 return CMD_WARNING;
1946 }
1947
1948 log_set_filter_vlr_subscr(tgt, vlr_subscr);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001949 vlr_subscr_put(vlr_subscr, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001950 return CMD_SUCCESS;
1951}
1952
1953static struct cmd_node hlr_node = {
1954 HLR_NODE,
1955 "%s(config-hlr)# ",
1956 1,
1957};
1958
1959DEFUN(cfg_hlr, cfg_hlr_cmd,
1960 "hlr", "Configure connection to the HLR")
1961{
1962 vty->node = HLR_NODE;
1963 return CMD_SUCCESS;
1964}
1965
1966DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1967 "Remote GSUP address of the HLR\n"
1968 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1969{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001970 talloc_free((void*)gsmnet->gsup_server_addr_str);
1971 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1972 return CMD_SUCCESS;
1973}
1974
1975DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1976 "Remote GSUP port of the HLR\n"
1977 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1978{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001979 gsmnet->gsup_server_port = atoi(argv[0]);
1980 return CMD_SUCCESS;
1981}
1982
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001983DEFUN(cfg_hlr_ipa_name,
1984 cfg_hlr_ipa_name_cmd,
1985 "ipa-name NAME",
1986 "Set the IPA name of this MSC\n"
1987 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1988 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
1989 "The default is 'MSC-00-00-00-00-00-00'.\n")
1990{
1991 if (vty->type != VTY_FILE) {
1992 vty_out(vty, "The IPA name cannot be changed at run-time; "
Martin Hauke3f07dac2019-11-14 17:49:08 +01001993 "It can only be set in the configuration file.%s", VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001994 return CMD_WARNING;
1995 }
1996
1997 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
1998 return CMD_SUCCESS;
1999}
2000
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002001static int config_write_hlr(struct vty *vty)
2002{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002003 vty_out(vty, "hlr%s", VTY_NEWLINE);
2004 vty_out(vty, " remote-ip %s%s",
2005 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
2006 vty_out(vty, " remote-port %u%s",
2007 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002008 if (gsmnet->msc_ipa_name)
2009 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002010 return CMD_SUCCESS;
2011}
2012
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002013void msc_vty_init(struct gsm_network *msc_network)
2014{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01002015 OSMO_ASSERT(gsmnet == NULL);
2016 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002017
2018 osmo_stats_vty_add_cmds();
2019
2020 install_element(CONFIG_NODE, &cfg_net_cmd);
2021 install_node(&net_node, config_write_net);
2022 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
2023 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
2024 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
2025 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
2026 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +02002027 install_element(GSMNET_NODE, &cfg_net_encryption_uea_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002028 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
2029 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
2030 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
2031 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
2032 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
2033 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
2034 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
2035 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Keith Whyte991bb422019-08-08 15:43:40 +02002036 install_element(GSMNET_NODE, &cfg_net_call_wait_cmd);
2037 install_element(GSMNET_NODE, &cfg_net_no_call_wait_cmd);
Pau Espin Pedrol53639ea2022-10-18 14:33:15 +02002038 mgcp_client_pool_vty_init(GSMNET_NODE, MGW_NODE, NULL, msc_network->mgw.mgw_pool);
Pau Espin Pedrolb44cf2d2022-10-17 18:09:15 +02002039
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002040
2041 install_element(CONFIG_NODE, &cfg_msc_cmd);
2042 install_node(&msc_node, config_write_msc);
Keith Whyte1587ffb2020-08-28 13:36:58 +02002043 install_element(MSC_NODE, &cfg_sms_database_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002044 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Keith Whytea1a70be2021-05-16 02:59:52 +02002045 install_element(MSC_NODE, &cfg_msc_lcls_disable_cmd);
2046 install_element(MSC_NODE, &cfg_msc_no_lcls_disable_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01002047 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
2048 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02002049 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01002050 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07002051 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002052 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01002053 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
2054 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01002055 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02002056 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
2057 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01002058 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01002059 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07002060 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
2061 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +02002062 install_element(MSC_NODE, &cfg_msc_osmux_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002063 install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd);
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +02002064 install_element(MSC_NODE, &cfg_msc_nri_bitlen_cmd);
2065 install_element(MSC_NODE, &cfg_msc_nri_add_cmd);
2066 install_element(MSC_NODE, &cfg_msc_nri_del_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002067
2068 neighbor_ident_vty_init(msc_network);
Philipp Maierfbf66102017-04-09 12:32:51 +02002069
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +07002070 /* Timer configuration commands (generic osmo_tdef API) */
2071 osmo_tdef_vty_groups_init(MSC_NODE, msc_tdef_group);
2072
Pau Espin Pedrolb44cf2d2022-10-17 18:09:15 +02002073 /* Deprecated: Old MGCP config without pooling support in MSC node: */
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02002074 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Pau Espin Pedrolb44cf2d2022-10-17 18:09:15 +02002075
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002076#ifdef BUILD_IU
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002077 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 +02002078#endif
Harald Welte0df904d2018-12-03 11:00:04 +01002079 sgs_vty_init();
Harald Welte1a62db22022-05-17 12:06:58 +02002080 smsc_vty_init(msc_network);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002081
Stefan Sperling617ac802018-02-22 17:58:20 +01002082 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002083
2084 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
2085
2086 install_element_ve(&show_subscr_cmd);
2087 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01002088 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002089 install_element_ve(&show_msc_conn_cmd);
2090 install_element_ve(&show_msc_transaction_cmd);
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +02002091 install_element_ve(&show_nri_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002092
2093 install_element_ve(&sms_send_pend_cmd);
2094 install_element_ve(&sms_delete_expired_cmd);
2095
2096 install_element_ve(&subscriber_create_cmd);
2097 install_element_ve(&subscriber_send_sms_cmd);
2098 install_element_ve(&subscriber_silent_sms_cmd);
2099 install_element_ve(&subscriber_silent_call_start_cmd);
2100 install_element_ve(&subscriber_silent_call_stop_cmd);
2101 install_element_ve(&subscriber_ussd_notify_cmd);
2102 install_element_ve(&subscriber_mstest_close_cmd);
2103 install_element_ve(&subscriber_mstest_open_cmd);
2104 install_element_ve(&subscriber_paging_cmd);
2105 install_element_ve(&show_stats_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002106 install_element_ve(&logging_fltr_imsi_cmd);
2107
2108 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002109 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01002110 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002111
2112 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
2113 install_node(&mncc_int_node, config_write_mncc_int);
2114 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
2115 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
2116
2117 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
2118
2119 install_element(CONFIG_NODE, &cfg_hlr_cmd);
2120 install_node(&hlr_node, config_write_hlr);
2121 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
2122 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002123 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002124}