blob: be05a95aa530bd4aad0eecb991aa67cb30bea9ee [file] [log] [blame]
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001/* MSC interface to quagga VTY */
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002/* (C) 2016-2018 by sysmocom s.m.f.c. GmbH <info@sysmocom.de>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02003 * Based on OpenBSC interface to quagga VTY (libmsc/vty_interface_layer3.c)
Harald Welte7b222aa2017-12-23 19:30:32 +01004 * (C) 2009-2017 by Harald Welte <laforge@gnumonks.org>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02005 * (C) 2009-2011 by Holger Hans Peter Freyther
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23/* NOTE: I would have liked to call this the MSC_NODE instead of the MSC_NODE,
24 * but MSC_NODE already exists to configure a remote MSC for osmo-bsc. */
25
Neels Hofmeyr4ac80092019-03-04 02:46:37 +010026#include "config.h"
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020027
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020028#include <inttypes.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010029#include <limits.h>
30
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010031#include <osmocom/core/use_count.h>
32
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010033#include <osmocom/gsm/protocol/gsm_08_58.h>
34#include <osmocom/gsm/protocol/gsm_04_14.h>
Philipp Maier8fa2dbe2019-03-19 18:51:37 +010035#include <osmocom/gsm/protocol/gsm_08_08.h>
Neels 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
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100393 return CMD_SUCCESS;
394}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200395
396static struct cmd_node msc_node = {
397 MSC_NODE,
398 "%s(config-msc)# ",
399 1,
400};
401
402DEFUN(cfg_msc, cfg_msc_cmd,
403 "msc", "Configure MSC options")
404{
405 vty->node = MSC_NODE;
406 return CMD_SUCCESS;
407}
408
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100409#define MNCC_STR "Configure Mobile Network Call Control\n"
410#define MNCC_GUARD_TIMEOUT_STR "Set global guard timer for mncc interface activity\n"
411#define MNCC_GUARD_TIMEOUT_VALUE_STR "guard timer value (sec.)\n"
412
Harald Welte1a62db22022-05-17 12:06:58 +0200413DEFUN_DEPRECATED(cfg_sms_database, cfg_sms_database_cmd,
Keith Whyte1587ffb2020-08-28 13:36:58 +0200414 "sms-database PATH",
415 "Set the path to the MSC-SMS database file\n"
416 "Relative or absolute file system path to the database file (default is '" SMS_DEFAULT_DB_FILE_PATH "')\n")
417{
Harald Welted302bb12022-05-17 13:31:14 +0200418 osmo_talloc_replace_string(gsmnet, &gsmnet->sms_queue_cfg->db_file_path, argv[0]);
Keith Whyte1587ffb2020-08-28 13:36:58 +0200419 return CMD_SUCCESS;
420}
421
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100422DEFUN(cfg_msc_mncc_internal,
423 cfg_msc_mncc_internal_cmd,
424 "mncc internal",
425 MNCC_STR "Use internal MNCC handler (default; changes need a program restart)\n")
426{
427 gsm_network_set_mncc_sock_path(gsmnet, NULL);
428 return CMD_SUCCESS;
429}
430
431DEFUN(cfg_msc_mncc_external,
432 cfg_msc_mncc_external_cmd,
433 "mncc external MNCC_SOCKET_PATH",
434 MNCC_STR "Use external MNCC handler (changes need a program restart)\n"
435 "File system path to create the MNCC unix domain socket at\n")
436{
437 gsm_network_set_mncc_sock_path(gsmnet, argv[0]);
438 return CMD_SUCCESS;
439}
440
Philipp Maier9ca7b312018-10-10 17:00:49 +0200441DEFUN(cfg_msc_mncc_guard_timeout,
442 cfg_msc_mncc_guard_timeout_cmd,
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100443 "mncc guard-timeout <0-255>",
444 MNCC_STR
445 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR)
Philipp Maier9ca7b312018-10-10 17:00:49 +0200446{
447 gsmnet->mncc_guard_timeout = atoi(argv[0]);
448 return CMD_SUCCESS;
449}
450
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100451ALIAS_DEPRECATED(cfg_msc_mncc_guard_timeout,
452 cfg_msc_deprecated_mncc_guard_timeout_cmd,
453 "mncc-guard-timeout <0-255>",
454 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR);
455
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700456#define NCSS_STR "Configure call independent Supplementary Services\n"
457
458DEFUN(cfg_msc_ncss_guard_timeout,
459 cfg_msc_ncss_guard_timeout_cmd,
460 "ncss guard-timeout <0-255>",
461 NCSS_STR "Set guard timer for session activity\n"
462 "guard timer value (sec.), or 0 to disable\n")
463{
464 gsmnet->ncss_guard_timeout = atoi(argv[0]);
465 return CMD_SUCCESS;
466}
467
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200468DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
469 "assign-tmsi",
470 "Assign TMSI during Location Updating.\n")
471{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200472 gsmnet->vlr->cfg.assign_tmsi = true;
473 return CMD_SUCCESS;
474}
475
476DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
477 "no assign-tmsi",
478 NO_STR "Assign TMSI during Location Updating.\n")
479{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200480 gsmnet->vlr->cfg.assign_tmsi = false;
481 return CMD_SUCCESS;
482}
483
Keith Whytea1a70be2021-05-16 02:59:52 +0200484DEFUN_ATTR(cfg_msc_lcls_disable, cfg_msc_lcls_disable_cmd,
485 "lcls-permitted",
486 "Globally allow LCLS (Local Call Local Switch) for all calls on this MSC.\n",
487 CMD_ATTR_IMMEDIATE)
488{
489 gsmnet->lcls_permitted = true;
490 return CMD_SUCCESS;
491}
492
493DEFUN_ATTR(cfg_msc_no_lcls_disable, cfg_msc_no_lcls_disable_cmd,
494 "no lcls-permitted",
495 NO_STR "Globally disable LCLS (Local Call Local Switch) for all calls on this MSC.\n",
496 CMD_ATTR_IMMEDIATE)
497{
498 gsmnet->lcls_permitted = false;
499 return CMD_SUCCESS;
500}
501
Philipp Maierfbf66102017-04-09 12:32:51 +0200502DEFUN(cfg_msc_cs7_instance_a,
503 cfg_msc_cs7_instance_a_cmd,
504 "cs7-instance-a <0-15>",
505 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
506{
Philipp Maierfbf66102017-04-09 12:32:51 +0200507 gsmnet->a.cs7_instance = atoi(argv[0]);
508 return CMD_SUCCESS;
509}
510
511DEFUN(cfg_msc_cs7_instance_iu,
512 cfg_msc_cs7_instance_iu_cmd,
513 "cs7-instance-iu <0-15>",
514 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
515{
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100516#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200517 gsmnet->iu.cs7_instance = atoi(argv[0]);
518 return CMD_SUCCESS;
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100519#else
520 vty_out(vty, "WARNING: 'cs7-instance-iu' without effect: built without Iu support%s",
521 VTY_NEWLINE);
522 return CMD_WARNING;
523#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200524}
525
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100526DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
527 "auth-tuple-max-reuse-count <-1-2147483647>",
528 "Configure authentication tuple re-use\n"
529 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
530{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100531 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
532 return CMD_SUCCESS;
533}
534
535DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
536 "auth-tuple-reuse-on-error (0|1)",
537 "Configure authentication tuple re-use when HLR is not responsive\n"
Oliver Smithd6e24fd2019-01-09 10:46:43 +0100538 "Never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
539 "If the HLR does not deliver new tuples, do re-use already available old ones.\n")
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100540{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100541 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
542 return CMD_SUCCESS;
543}
544
Oliver Smith0fec28a2018-12-14 10:52:52 +0100545DEFUN(cfg_msc_check_imei_rqd, cfg_msc_check_imei_rqd_cmd,
Oliver Smith03ded912019-05-02 10:40:50 +0200546 "check-imei-rqd (0|1|early)",
Oliver Smith0fec28a2018-12-14 10:52:52 +0100547 "Send each IMEI to the EIR to ask if it is permitted or not. The EIR is implemented as part of OsmoHLR, "
548 "and can optionally save the IMEI in the HLR.\n"
549 "Do not send IMEIs to the EIR\n"
Oliver Smith03ded912019-05-02 10:40:50 +0200550 "Send each IMEI to the EIR\n"
551 "Send each IMEI to the EIR, and do it at the start of the location update. This allows the EIR to receive the"
552 " 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 +0100553{
Oliver Smith03ded912019-05-02 10:40:50 +0200554 if (strcmp(argv[0], "0") == 0) {
555 gsmnet->vlr->cfg.check_imei_rqd = false;
556 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
557 } else if (strcmp(argv[0], "1") == 0) {
558 gsmnet->vlr->cfg.check_imei_rqd = true;
559 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
560 } else if (strcmp(argv[0], "early") == 0) {
561 gsmnet->vlr->cfg.check_imei_rqd = true;
562 gsmnet->vlr->cfg.retrieve_imeisv_early = true;
563 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100564 return CMD_SUCCESS;
565}
566
Alexander Couzensae167fc2020-09-25 05:25:16 +0200567DEFUN_DEPRECATED(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100568 "paging response-timer (default|<1-65535>)",
569 "Configure Paging\n"
570 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
571 " BSS or RNC\n"
572 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
573 "Set paging timeout in seconds\n")
574{
Alexander Couzensae167fc2020-09-25 05:25:16 +0200575 int rat;
576 int paging_response_timer;
Pau Espin Pedrolb08a3802019-09-16 19:01:37 +0200577 if (!strcmp(argv[0], "default"))
Alexander Couzensae167fc2020-09-25 05:25:16 +0200578 paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100579 else
Alexander Couzensae167fc2020-09-25 05:25:16 +0200580 paging_response_timer = atoi(argv[0]);
581
582 for (rat = 0; rat < OSMO_RAT_COUNT; rat++) {
583 osmo_tdef_set(msc_ran_infra[rat].tdefs, -4, paging_response_timer, OSMO_TDEF_S);
584 }
585
586 vty_out(vty, "%% paging response-timer is deprecated.%s"
587 "%% All ran timer has been modified.%s"
588 "%% use 'timer <geran|utran|sgs> X4 %s' instead%s",
589 VTY_NEWLINE, VTY_NEWLINE, argv[0], VTY_NEWLINE);
590
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100591 return CMD_SUCCESS;
592}
593
Harald Welte69c54a82018-02-09 20:41:14 +0100594DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
595 "emergency-call route-to-msisdn MSISDN",
596 "Configure Emergency Call Behaviour\n"
597 "MSISDN to which Emergency Calls are Dispatched\n"
598 "MSISDN (E.164 Phone Number)\n")
599{
Harald Welte69c54a82018-02-09 20:41:14 +0100600 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
601
602 return CMD_SUCCESS;
603}
604
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700605/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
606DEFUN(cfg_msc_sms_over_gsup, cfg_msc_sms_over_gsup_cmd,
607 "sms-over-gsup",
608 "Enable routing of SMS messages over GSUP\n")
609{
610 gsmnet->sms_over_gsup = true;
611 return CMD_SUCCESS;
612}
613
614/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
615DEFUN(cfg_msc_no_sms_over_gsup, cfg_msc_no_sms_over_gsup_cmd,
616 "no sms-over-gsup",
617 NO_STR "Disable routing of SMS messages over GSUP\n")
618{
619 gsmnet->sms_over_gsup = false;
620 return CMD_SUCCESS;
621}
622
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100623/* FIXME: This should rather be in the form of
624 * handover-number range 001234xxx
625 * and
626 * handover-number range 001234xxx FIRST LAST
627 */
628DEFUN(cfg_msc_handover_number_range, cfg_msc_handover_number_range_cmd,
629 "handover-number range MSISDN_FIRST MSISDN_LAST",
630 "Configure a range of MSISDN to be assigned to incoming inter-MSC Handovers for call forwarding.\n"
631 "Configure a handover number range\n"
632 "First Handover Number MSISDN\n"
633 "Last Handover Number MSISDN\n")
634{
635 char *endp;
636 uint64_t range_start;
637 uint64_t range_end;
638
639 /* FIXME leading zeros?? */
640
641 errno = 0;
642 range_start = strtoull(argv[0], &endp, 10);
643 if (errno || *endp != '\0') {
644 vty_out(vty, "%% Error parsing handover-number range start: %s%s",
645 argv[0], VTY_NEWLINE);
646 return CMD_WARNING;
647 }
648
649 errno = 0;
650 range_end = strtoull(argv[1], &endp, 10);
651 if (errno || *endp != '\0') {
652 vty_out(vty, "%% Error parsing handover-number range end: %s%s",
653 argv[1], VTY_NEWLINE);
654 return CMD_WARNING;
655 }
656
657 if (range_start > range_end) {
658 vty_out(vty, "%% Error: handover-number range end must be > than the range start, but"
659 " %"PRIu64" > %"PRIu64"%s", range_start, range_end, VTY_NEWLINE);
660 return CMD_WARNING;
661 }
662
663 gsmnet->handover_number.range_start = range_start;
664 gsmnet->handover_number.range_end = range_end;
665 return CMD_SUCCESS;
666}
667
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200668#define OSMUX_STR "RTP multiplexing\n"
669DEFUN(cfg_msc_osmux,
670 cfg_msc_osmux_cmd,
671 "osmux (on|off|only)",
672 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
673{
674 if (strcmp(argv[0], "off") == 0)
675 gsmnet->use_osmux = OSMUX_USAGE_OFF;
676 else if (strcmp(argv[0], "on") == 0)
677 gsmnet->use_osmux = OSMUX_USAGE_ON;
678 else if (strcmp(argv[0], "only") == 0)
679 gsmnet->use_osmux = OSMUX_USAGE_ONLY;
680
681 return CMD_SUCCESS;
682}
683
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +0200684#define NRI_STR "Mapping of Network Resource Indicators to this MSC, for MSC pooling\n"
685DEFUN(cfg_msc_nri_bitlen, cfg_msc_nri_bitlen_cmd,
686 "nri bitlen <0-15>",
687 NRI_STR
688 "Set number of NRI bits to place in TMSI identities (always starting just after the most significant octet)\n"
689 "bit count (default: " OSMO_STRINGIFY_VAL(NRI_BITLEN_DEFAULT) ")\n")
690{
691 gsmnet->vlr->cfg.nri_bitlen = atoi(argv[0]);
692 return CMD_SUCCESS;
693}
694
695#define NRI_STR "Mapping of Network Resource Indicators to this MSC, for MSC pooling\n"
696#define NRI_ARGS_TO_STR_FMT "%s%s%s"
697#define NRI_ARGS_TO_STR_ARGS(ARGC, ARGV) ARGV[0], (ARGC>1)? ".." : "", (ARGC>1)? ARGV[1] : ""
698#define NRI_FIRST_LAST_STR "First value of the NRI value range, should not surpass the configured 'nri bitlen'.\n" \
699 "Last value of the NRI value range, should not surpass the configured 'nri bitlen' and be larger than the" \
700 " first value; if omitted, apply only the first value.\n"
701
702DEFUN(cfg_msc_nri_add, cfg_msc_nri_add_cmd,
703 "nri add <0-32767> [<0-32767>]",
704 NRI_STR "Add NRI value or range to the NRI mapping for this MSC\n"
705 NRI_FIRST_LAST_STR)
706{
707 const char *message;
708 int rc = osmo_nri_ranges_vty_add(&message, NULL, gsmnet->vlr->cfg.nri_ranges, argc, argv, gsmnet->vlr->cfg.nri_bitlen);
709 if (message) {
710 vty_out(vty, "%% %s: " NRI_ARGS_TO_STR_FMT, message, NRI_ARGS_TO_STR_ARGS(argc, argv));
711 }
712 if (rc < 0)
713 return CMD_WARNING;
714 return CMD_SUCCESS;
715}
716
717DEFUN(cfg_msc_nri_del, cfg_msc_nri_del_cmd,
718 "nri del <0-32767> [<0-32767>]",
719 NRI_STR "Remove NRI value or range from the NRI mapping for this MSC\n"
720 NRI_FIRST_LAST_STR)
721{
722 const char *message;
723 int rc = osmo_nri_ranges_vty_del(&message, NULL, gsmnet->vlr->cfg.nri_ranges, argc, argv);
724 if (message) {
725 vty_out(vty, "%% %s: " NRI_ARGS_TO_STR_FMT, message, NRI_ARGS_TO_STR_ARGS(argc, argv));
726 }
727 if (rc < 0)
728 return CMD_WARNING;
729 return CMD_SUCCESS;
730}
731
732static void msc_write_nri(struct vty *vty)
733{
734 struct osmo_nri_range *r;
735
736 llist_for_each_entry(r, &gsmnet->vlr->cfg.nri_ranges->entries, entry) {
737 if (osmo_nri_range_validate(r, 255))
738 vty_out(vty, " %% INVALID RANGE:");
739 vty_out(vty, " nri add %d", r->first);
740 if (r->first != r->last)
741 vty_out(vty, " %d", r->last);
742 vty_out(vty, "%s", VTY_NEWLINE);
743 }
744}
745
746DEFUN(show_nri, show_nri_cmd,
747 "show nri",
748 SHOW_STR NRI_STR)
749{
750 msc_write_nri(vty);
751 return CMD_SUCCESS;
752}
753
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200754static int config_write_msc(struct vty *vty)
755{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200756 vty_out(vty, "msc%s", VTY_NEWLINE);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100757 if (gsmnet->mncc_sock_path)
758 vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE);
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100759 vty_out(vty, " mncc guard-timeout %i%s",
Philipp Maier9ca7b312018-10-10 17:00:49 +0200760 gsmnet->mncc_guard_timeout, VTY_NEWLINE);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700761 vty_out(vty, " ncss guard-timeout %i%s",
762 gsmnet->ncss_guard_timeout, VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200763 vty_out(vty, " %sassign-tmsi%s",
764 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
Keith Whytea1a70be2021-05-16 02:59:52 +0200765 if (gsmnet->lcls_permitted)
766 vty_out(vty, " lcls-permitted%s", VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200767
Philipp Maierfbf66102017-04-09 12:32:51 +0200768 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
769 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100770#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200771 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
772 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100773#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200774
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100775 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
776 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
777 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
778 VTY_NEWLINE);
779 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
780 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
781 VTY_NEWLINE);
782
Oliver Smith03ded912019-05-02 10:40:50 +0200783 if (gsmnet->vlr->cfg.check_imei_rqd) {
784 if (gsmnet->vlr->cfg.retrieve_imeisv_early)
785 vty_out(vty, " check-imei-rqd early%s", VTY_NEWLINE);
786 else
787 vty_out(vty, " check-imei-rqd 1%s", VTY_NEWLINE);
788 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100789
Harald Welte69c54a82018-02-09 20:41:14 +0100790 if (gsmnet->emergency.route_to_msisdn) {
791 vty_out(vty, " emergency-call route-to-msisdn %s%s",
792 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
793 }
794
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700795 if (gsmnet->sms_over_gsup)
796 vty_out(vty, " sms-over-gsup%s", VTY_NEWLINE);
797
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100798 if (gsmnet->handover_number.range_start || gsmnet->handover_number.range_end)
799 vty_out(vty, " handover-number range %"PRIu64" %"PRIu64"%s",
800 gsmnet->handover_number.range_start, gsmnet->handover_number.range_end,
801 VTY_NEWLINE);
802
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200803 if (gsmnet->use_osmux != OSMUX_USAGE_OFF) {
804 vty_out(vty, " osmux %s%s", gsmnet->use_osmux == OSMUX_USAGE_ON ? "on" : "only",
805 VTY_NEWLINE);
806 }
807
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200808 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200809#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200810 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200811#endif
812
Neels Hofmeyr880b9502019-05-09 02:01:55 +0200813 neighbor_ident_vty_write(vty);
814
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +0700815 /* Timer introspection commands (generic osmo_tdef API) */
816 osmo_tdef_vty_groups_write(vty, " ");
817
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +0200818 msc_write_nri(vty);
819
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200820 return CMD_SUCCESS;
821}
822
Maxc51609a2018-11-09 17:13:00 +0100823DEFUN(show_bsc, show_bsc_cmd,
824 "show bsc", SHOW_STR "BSC\n")
825{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100826 struct ran_peer *rp;
827 llist_for_each_entry(rp, &gsmnet->a.sri->ran_peers, entry) {
828 vty_out(vty, "BSC %s %s%s",
829 osmo_sccp_inst_addr_name(gsmnet->a.sri->sccp, &rp->peer_addr),
830 osmo_fsm_inst_state_name(rp->fi),
831 VTY_NEWLINE);
Maxc51609a2018-11-09 17:13:00 +0100832 }
833
834 return CMD_SUCCESS;
835}
836
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100837static const char *get_trans_proto_str(const struct gsm_trans *trans)
838{
839 static char buf[256];
840
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100841 switch (trans->type) {
842 case TRANS_CC:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100843 snprintf(buf, sizeof(buf), "%s %4u %4u",
844 gsm48_cc_state_name(trans->cc.state),
845 trans->cc.Tcurrent,
846 trans->cc.T308_second);
847 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100848 case TRANS_SMS:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700849 snprintf(buf, sizeof(buf), "CP:%s RP:%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100850 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
851 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
852 break;
853 default:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700854 return NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100855 }
856
857 return buf;
858}
859
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700860/* Prefix a given format string with a given amount of spaces */
861#define MSC_VTY_DUMP(vty, offset, fmt, args...) \
862 vty_out(vty, "%*s" fmt, offset, "", ##args)
863
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200864/* Print value of a named flag, prefixed with a given amount of spaces */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700865#define MSC_VTY_DUMP_FLAG(vty, offset, name, flag) \
866 MSC_VTY_DUMP(vty, offset + 2, "%s: %*s%s%s", \
867 name, 30 - (int)strlen(name), "", \
868 flag ? "true" : "false", \
869 VTY_NEWLINE)
870
871enum msc_vty_dump_flags {
872 MSC_VTY_DUMP_F_SUBSCR = (1 << 0),
873 MSC_VTY_DUMP_F_CONNECTION = (1 << 1),
874 MSC_VTY_DUMP_F_TRANSACTION = (1 << 2),
875};
876
877static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans,
878 int offset, uint8_t dump_flags)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100879{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700880 const char *proto_str;
881
882 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
883 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
884 vlr_subscr_name(msc_a_vsub(trans->msc_a)),
885 VTY_NEWLINE);
886 }
887
888 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200889 /* (If msc_a exists, there *must* be a non-null msc_a->c.msub) */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700890 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
891 trans->msc_a ? msub_ran_conn_name(trans->msc_a->c.msub)
892 : "(not established)",
893 VTY_NEWLINE);
894 }
895
896 MSC_VTY_DUMP(vty, offset, "Unique (global) identifier: 0x%08x%s",
897 trans->callref, VTY_NEWLINE);
898 MSC_VTY_DUMP(vty, offset, "GSM 04.07 identifier (%s): %u%s",
899 (trans->transaction_id & 0x08) ? "MO" : "MT",
900 trans->transaction_id,
901 VTY_NEWLINE);
902
903 MSC_VTY_DUMP(vty, offset, "Type: %s%s",
904 trans_type_name(trans->type),
905 VTY_NEWLINE);
906
907 if ((proto_str = get_trans_proto_str(trans))) {
908 MSC_VTY_DUMP(vty, offset, "Protocol specific: %s%s",
909 proto_str, VTY_NEWLINE);
910 }
911}
912
913static void vty_dump_one_conn(struct vty *vty, const struct msub *msub,
914 int offset, uint8_t dump_flags)
915{
916 struct vlr_subscr *vsub = msub_vsub(msub);
917 struct msc_a *msc_a = msub_msc_a(msub);
918 char buf[128];
919
920 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
921 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
922 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
923 vlr_subscr_name(vsub),
924 VTY_NEWLINE);
925 }
926
927 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
928 msub_ran_conn_name(msub),
929 VTY_NEWLINE);
930 MSC_VTY_DUMP(vty, offset, "RAN connection state: %s%s",
931 osmo_fsm_inst_state_name(msc_a->c.fi),
932 VTY_NEWLINE);
933
934 if (vsub) {
935 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
Neels Hofmeyr41c03332020-06-24 15:02:27 +0200936 msc_a->via_cell.lai.lac, msc_a->via_cell.cell_identity,
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700937 VTY_NEWLINE);
938 }
939
940 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
941 osmo_use_count_total(&msc_a->use_count),
942 VTY_NEWLINE);
943 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
944 osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count),
945 VTY_NEWLINE);
946
947 /* Transactions of this connection */
948 if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
949 struct gsm_trans *trans;
950 unsigned int i = 0;
951
952 /* Both subscriber and connection info is already printed */
953 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_CONNECTION;
954 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
955
956 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
957 if (trans->msc_a != msc_a)
958 continue;
959 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
960 i++, VTY_NEWLINE);
961 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
962 }
963 }
964}
965
966static void vty_dump_one_subscr(struct vty *vty, struct vlr_subscr *vsub,
967 int offset, uint8_t dump_flags)
968{
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700969 struct timespec now;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700970 char buf[128];
971
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700972 if (vsub->name[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700973 MSC_VTY_DUMP(vty, offset, "Name: '%s'%s",
974 vsub->name, VTY_NEWLINE);
975 }
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700976 if (vsub->msisdn[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700977 MSC_VTY_DUMP(vty, offset, "MSISDN: %s%s",
978 vsub->msisdn, VTY_NEWLINE);
979 }
980
981 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
982 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
983 VTY_NEWLINE);
984 MSC_VTY_DUMP(vty, offset, "RAN type: %s%s",
985 osmo_rat_type_name(vsub->cs.attached_via_ran),
986 VTY_NEWLINE);
987
988 MSC_VTY_DUMP(vty, offset, "IMSI: %s%s",
989 vsub->imsi, VTY_NEWLINE);
990 if (vsub->tmsi != GSM_RESERVED_TMSI) {
991 MSC_VTY_DUMP(vty, offset, "TMSI: %08X%s",
992 vsub->tmsi, VTY_NEWLINE);
993 }
994 if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
995 MSC_VTY_DUMP(vty, offset, "New TMSI: %08X%s",
996 vsub->tmsi_new, VTY_NEWLINE);
997 }
998 if (vsub->imei[0] != '\0') {
999 MSC_VTY_DUMP(vty, offset, "IMEI: %s%s",
1000 vsub->imei, VTY_NEWLINE);
1001 }
1002 if (vsub->imeisv[0] != '\0') {
1003 MSC_VTY_DUMP(vty, offset, "IMEISV: %s%s",
1004 vsub->imeisv, VTY_NEWLINE);
1005 }
1006
1007 MSC_VTY_DUMP(vty, offset, "Flags: %s", VTY_NEWLINE);
1008 MSC_VTY_DUMP_FLAG(vty, offset, "IMSI detached",
1009 vsub->imsi_detached_flag);
1010 MSC_VTY_DUMP_FLAG(vty, offset, "Conf. by radio contact",
1011 vsub->conf_by_radio_contact_ind);
1012 MSC_VTY_DUMP_FLAG(vty, offset, "Subscr. data conf. by HLR",
1013 vsub->sub_dataconf_by_hlr_ind);
1014 MSC_VTY_DUMP_FLAG(vty, offset, "Location conf. in HLR",
1015 vsub->loc_conf_in_hlr_ind);
1016 MSC_VTY_DUMP_FLAG(vty, offset, "Subscriber dormant",
1017 vsub->dormant_ind);
1018 MSC_VTY_DUMP_FLAG(vty, offset, "Received cancel location",
1019 vsub->cancel_loc_rx);
1020 MSC_VTY_DUMP_FLAG(vty, offset, "MS not reachable",
1021 vsub->ms_not_reachable_flag);
1022 MSC_VTY_DUMP_FLAG(vty, offset, "LA allowed",
1023 vsub->la_allowed);
1024
1025 if (vsub->last_tuple) {
1026 struct vlr_auth_tuple *t = vsub->last_tuple;
1027 MSC_VTY_DUMP(vty, offset, "A3A8 last tuple (used %d times): %s",
1028 t->use_count, VTY_NEWLINE);
1029 MSC_VTY_DUMP(vty, offset + 2, "seq # : %d%s",
1030 t->key_seq, VTY_NEWLINE);
1031 MSC_VTY_DUMP(vty, offset + 2, "RAND : %s%s",
1032 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
1033 VTY_NEWLINE);
1034 MSC_VTY_DUMP(vty, offset + 2, "SRES : %s%s",
1035 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
1036 VTY_NEWLINE);
1037 MSC_VTY_DUMP(vty, offset + 2, "Kc : %s%s",
1038 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
1039 VTY_NEWLINE);
1040 }
1041
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +07001042 if (!vlr_timer(vsub->vlr, 3212)) {
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +07001043 MSC_VTY_DUMP(vty, offset, "Expires: never (T3212 is disabled)%s",
1044 VTY_NEWLINE);
1045 } else if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) {
1046 MSC_VTY_DUMP(vty, offset, "Expires: never%s",
1047 VTY_NEWLINE);
1048 } else if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
1049 MSC_VTY_DUMP(vty, offset, "Expires: in %ld min %ld sec%s",
1050 (vsub->expire_lu - now.tv_sec) / 60,
1051 (vsub->expire_lu - now.tv_sec) % 60,
1052 VTY_NEWLINE);
1053 }
1054
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001055 MSC_VTY_DUMP(vty, offset, "Paging: %s paging for %d requests%s",
1056 vsub->cs.is_paging ? "is" : "not",
1057 llist_count(&vsub->cs.requests),
1058 VTY_NEWLINE);
1059
1060 /* SGs related */
1061 MSC_VTY_DUMP(vty, offset, "SGs-state: %s%s",
1062 osmo_fsm_inst_state_name(vsub->sgs_fsm),
1063 VTY_NEWLINE);
1064 MSC_VTY_DUMP(vty, offset, "SGs-MME: %s%s",
Vadim Yanitskiydcf28682019-05-29 22:34:13 +07001065 vsub->sgs.mme_name[0] != '\0' ? vsub->sgs.mme_name : "(none)",
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001066 VTY_NEWLINE);
1067
1068 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
1069 osmo_use_count_total(&vsub->use_count),
1070 VTY_NEWLINE);
1071 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
1072 osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count),
1073 VTY_NEWLINE);
1074
1075 /* Connection(s) and/or transactions of this subscriber */
1076 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
1077 struct msub *msub = msub_for_vsub(vsub);
1078 if (!msub)
1079 return;
1080
1081 /* Subscriber info is already printed */
1082 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
1083
1084 MSC_VTY_DUMP(vty, offset, "Connection: %s", VTY_NEWLINE);
1085 vty_dump_one_conn(vty, msub, offset + 2, dump_flags);
1086 } else if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
1087 struct gsm_trans *trans;
1088 unsigned int i = 0;
1089
1090 /* Subscriber info is already printed */
1091 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
1092 /* Do not print connection info, but mention it */
1093 dump_flags |= MSC_VTY_DUMP_F_CONNECTION;
1094
1095 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1096 if (trans->vsub != vsub)
1097 continue;
1098 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
1099 i++, VTY_NEWLINE);
1100 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
1101 }
1102 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001103}
1104
1105DEFUN(show_msc_transaction, show_msc_transaction_cmd,
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001106 "show transaction",
1107 SHOW_STR "Transactions\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001108{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001109 struct gsm_trans *trans;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001110 uint8_t flags = 0x00;
1111 unsigned int i = 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001112
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001113 flags |= MSC_VTY_DUMP_F_CONNECTION;
1114 flags |= MSC_VTY_DUMP_F_SUBSCR;
1115
1116 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1117 vty_out(vty, " Transaction #%02u: %s", i++, VTY_NEWLINE);
1118 vty_dump_one_trans(vty, trans, 4, flags);
1119 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001120
1121 return CMD_SUCCESS;
1122}
1123
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001124DEFUN(show_msc_conn, show_msc_conn_cmd,
1125 "show connection [trans]",
1126 SHOW_STR "Subscriber Connections\n"
1127 "Show child transactions of each connection\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001128{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001129 uint8_t flags = 0x00;
1130 unsigned int i = 0;
1131 struct msub *msub;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001132
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001133 if (argc > 0)
1134 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1135 flags |= MSC_VTY_DUMP_F_SUBSCR;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001136
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001137 llist_for_each_entry(msub, &msub_list, entry) {
1138 vty_out(vty, " Connection #%02u: %s", i++, VTY_NEWLINE);
1139 vty_dump_one_conn(vty, msub, 4, flags);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001140 }
1141
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001142 return CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001143}
1144
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001145#define SUBSCR_FLAGS "[(conn|trans|conn+trans)]"
1146#define SUBSCR_FLAGS_HELP \
1147 "Show child connections\n" \
1148 "Show child transactions\n" \
1149 "Show child connections and transactions\n"
1150
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001151/* Subscriber */
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001152DEFUN(show_subscr_cache, show_subscr_cache_cmd,
1153 "show subscriber cache " SUBSCR_FLAGS,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001154 SHOW_STR "Show information about subscribers\n"
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001155 "Display contents of subscriber cache\n"
1156 SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001157{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001158 struct vlr_subscr *vsub;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001159 unsigned int count = 0;
1160 uint8_t flags = 0x00;
1161 unsigned int i = 0;
1162
1163 if (argc && strcmp(argv[0], "conn") == 0)
1164 flags |= MSC_VTY_DUMP_F_CONNECTION;
1165 else if (argc && strcmp(argv[0], "trans") == 0)
1166 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1167 else if (argc && strcmp(argv[0], "conn+trans") == 0)
1168 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001169
1170 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
1171 if (++count > 100) {
1172 vty_out(vty, "%% More than %d subscribers in cache,"
1173 " stopping here.%s", count-1, VTY_NEWLINE);
1174 break;
1175 }
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001176 vty_out(vty, " Subscriber #%02u: %s", i++, VTY_NEWLINE);
1177 vty_dump_one_subscr(vty, vsub, 4, flags);
Harald Welte69c54a82018-02-09 20:41:14 +01001178 }
1179
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001180 return CMD_SUCCESS;
1181}
1182
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001183DEFUN(sms_send_pend,
1184 sms_send_pend_cmd,
1185 "sms send pending",
1186 "SMS related commands\n" "SMS Sending related commands\n"
1187 "Send all pending SMS")
1188{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001189 struct gsm_sms *sms;
1190 unsigned long long sms_id = 0;
1191
1192 while (1) {
1193 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1194 if (!sms)
1195 break;
1196
1197 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001198 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001199
1200 sms_id = sms->id + 1;
1201 }
1202
1203 return CMD_SUCCESS;
1204}
1205
1206DEFUN(sms_delete_expired,
1207 sms_delete_expired_cmd,
1208 "sms delete expired",
1209 "SMS related commands\n" "SMS Database related commands\n"
1210 "Delete all expired SMS")
1211{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001212 struct gsm_sms *sms;
1213 unsigned long long sms_id = 0;
1214 long long num_deleted = 0;
1215
1216 while (1) {
1217 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1218 if (!sms)
1219 break;
1220
1221 /* Skip SMS which are currently queued for sending. */
1222 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
1223 continue;
1224
1225 /* Expiration check is performed by the DB layer. */
1226 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
1227 num_deleted++;
1228
1229 sms_id = sms->id + 1;
1230 }
1231
1232 if (num_deleted == 0) {
1233 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
1234 return CMD_WARNING;
1235 }
1236
1237 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
1238 return CMD_SUCCESS;
1239}
1240
1241static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +02001242 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001243 char *str, uint8_t tp_pid)
1244{
1245 struct gsm_network *net = receiver->vlr->user_ctx;
1246 struct gsm_sms *sms;
1247
Harald Welte39b55482018-04-09 19:19:33 +02001248 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Vadim Yanitskiydb4839c2019-12-01 18:52:58 +07001249 if (!sms) {
1250 LOGP(DLSMS, LOGL_ERROR, "Failed to allocate SMS\n");
1251 return CMD_WARNING;
1252 }
1253
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001254 sms->protocol_id = tp_pid;
1255
1256 /* store in database for the queue */
1257 if (db_sms_store(sms) != 0) {
1258 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
1259 sms_free(sms);
1260 return CMD_WARNING;
1261 }
1262 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
1263
1264 sms_free(sms);
1265 sms_queue_trigger(net->sms_queue);
1266 return CMD_SUCCESS;
1267}
1268
1269static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
1270 const char *type,
1271 const char *id)
1272{
1273 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001274 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001275 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001276 return vlr_subscr_find_by_imsi(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001277 else if (!strcmp(type, "tmsi"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001278 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id), VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001279
1280 return NULL;
1281}
1282#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
1283#define SUBSCR_HELP "Operations on a Subscriber\n" \
1284 "Identify subscriber by MSISDN (phone number)\n" \
1285 "Legacy alias for 'msisdn'\n" \
1286 "Identify subscriber by IMSI\n" \
1287 "Identify subscriber by TMSI\n" \
Vadim Yanitskiy3ccd8232019-05-16 01:35:23 +07001288 "Legacy alias for 'imsi'\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001289 "Identifier for the subscriber\n"
1290
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001291DEFUN(show_subscr, show_subscr_cmd,
1292 "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
1293 SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001294{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001295 struct vlr_subscr *vsub;
1296 uint8_t flags = 0x00;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001297
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001298 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001299 if (!vsub) {
1300 vty_out(vty, "%% No subscriber found for %s %s%s",
1301 argv[0], argv[1], VTY_NEWLINE);
1302 return CMD_WARNING;
1303 }
1304
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001305 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
1306 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
1307 * 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 +01001308 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001309
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001310 if (argc > 2 && strcmp(argv[2], "conn") == 0)
1311 flags |= MSC_VTY_DUMP_F_CONNECTION;
1312 else if (argc > 2 && strcmp(argv[2], "trans") == 0)
1313 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1314 else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
1315 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
1316
1317 vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
1318 vty_dump_one_subscr(vty, vsub, 4, flags);
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001319
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001320 return CMD_SUCCESS;
1321}
1322
Vadim Yanitskiyb7ddbf32020-01-20 21:30:09 +07001323DEFUN_DEPRECATED(subscriber_create, subscriber_create_cmd,
1324 "subscriber create imsi ID",
1325 "Operations on a Subscriber\n"
1326 "Create new subscriber\n"
1327 "Identify the subscriber by his IMSI\n"
1328 "Identifier for the subscriber\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001329{
1330 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
1331 VTY_NEWLINE);
1332 return CMD_WARNING;
1333}
1334
1335DEFUN(subscriber_send_pending_sms,
1336 subscriber_send_pending_sms_cmd,
1337 "subscriber " SUBSCR_TYPES " ID sms pending-send",
1338 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
1339{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001340 struct vlr_subscr *vsub;
1341 struct gsm_sms *sms;
1342
1343 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1344 if (!vsub) {
1345 vty_out(vty, "%% No subscriber found for %s %s%s",
1346 argv[0], argv[1], VTY_NEWLINE);
1347 return CMD_WARNING;
1348 }
1349
1350 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
1351 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001352 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001353
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001354 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001355
1356 return CMD_SUCCESS;
1357}
1358
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001359DEFUN(subscriber_sms_delete_all,
1360 subscriber_sms_delete_all_cmd,
1361 "subscriber " SUBSCR_TYPES " ID sms delete-all",
1362 SUBSCR_HELP "SMS Operations\n"
1363 "Delete all SMS to be delivered to this subscriber"
1364 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
1365 " WILL BE LOST.\n")
1366{
1367 struct vlr_subscr *vsub;
1368
1369 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1370 if (!vsub) {
1371 vty_out(vty, "%% No subscriber found for %s %s%s",
1372 argv[0], argv[1], VTY_NEWLINE);
1373 return CMD_WARNING;
1374 }
1375
1376 db_sms_delete_by_msisdn(vsub->msisdn);
1377
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001378 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001379
1380 return CMD_SUCCESS;
1381}
1382
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001383DEFUN(subscriber_send_sms,
1384 subscriber_send_sms_cmd,
1385 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1386 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1387{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001388 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001389 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001390 char *str;
1391 int rc;
1392
1393 if (!vsub) {
1394 vty_out(vty, "%% No subscriber found for %s %s%s",
1395 argv[0], argv[1], VTY_NEWLINE);
1396 rc = CMD_WARNING;
1397 goto err;
1398 }
1399
Harald Welte39b55482018-04-09 19:19:33 +02001400 if (!strcmp(argv[2], "msisdn"))
1401 sender_msisdn = argv[3];
1402 else {
1403 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1404 if (!sender) {
1405 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1406 rc = CMD_WARNING;
1407 goto err;
1408 }
1409 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001410 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001411 }
1412
1413 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001414 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001415 talloc_free(str);
1416
1417err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001418 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001419 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001420
1421 return rc;
1422}
1423
1424DEFUN(subscriber_silent_sms,
1425 subscriber_silent_sms_cmd,
1426
1427 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1428 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1429{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001430 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001431 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001432 char *str;
1433 int rc;
1434
1435 if (!vsub) {
1436 vty_out(vty, "%% No subscriber found for %s %s%s",
1437 argv[0], argv[1], VTY_NEWLINE);
1438 rc = CMD_WARNING;
1439 goto err;
1440 }
1441
Harald Welte39b55482018-04-09 19:19:33 +02001442 if (!strcmp(argv[2], "msisdn")) {
1443 sender_msisdn = argv[3];
1444 } else {
1445 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1446 if (!sender) {
1447 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1448 rc = CMD_WARNING;
1449 goto err;
1450 }
1451 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001452 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001453 }
1454
1455 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001456 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001457 talloc_free(str);
1458
1459err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001460 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001461 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001462
1463 return rc;
1464}
1465
Sylvain Munaut93558302019-02-14 20:13:08 +01001466#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001467#define CHAN_TYPE_HELP \
1468 "Any channel\n" \
1469 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001470 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001471 "Any TCH channel\n" \
1472 "SDCCH channel\n"
1473
Sylvain Munaut93558302019-02-14 20:13:08 +01001474#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1475#define CHAN_MODE_HELP \
1476 "Signalling only\n" \
1477 "Speech with HR codec\n" \
1478 "Speech with FR codec\n" \
1479 "Speech with EFR codec\n" \
1480 "Speech with AMR codec\n"
1481
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001482DEFUN(subscriber_silent_call_start,
1483 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001484 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001485 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001486 CHAN_TYPE_HELP CHAN_MODE_HELP
1487 "Target IP for RTP traffic (default 127.0.0.1)\n"
1488 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001489{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001490 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001491 struct gsm0808_channel_type ct;
1492 const char *ip;
1493 uint16_t port;
1494 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001495
1496 if (!vsub) {
1497 vty_out(vty, "%% No subscriber found for %s %s%s",
1498 argv[0], argv[1], VTY_NEWLINE);
1499 return CMD_WARNING;
1500 }
1501
Sylvain Munaut93558302019-02-14 20:13:08 +01001502 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001503
Sylvain Munaut93558302019-02-14 20:13:08 +01001504 if (!strcmp(argv[3], "signalling")) {
1505 ct.ch_indctr = GSM0808_CHAN_SIGN;
1506 ct.perm_spch[0] = 0; /* Spare but required */
1507 ct.perm_spch_len = 1;
1508 } else if (!strcmp(argv[3], "speech-hr")) {
1509 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1510 ct.perm_spch[0] = GSM0808_PERM_HR1;
1511 ct.perm_spch_len = 1;
1512 } else if (!strcmp(argv[3], "speech-fr")) {
1513 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1514 ct.perm_spch[0] = GSM0808_PERM_FR1;
1515 ct.perm_spch_len = 1;
1516 } else if (!strcmp(argv[3], "speech-efr")) {
1517 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1518 ct.perm_spch[0] = GSM0808_PERM_FR2;
1519 ct.perm_spch_len = 1;
1520 } else if (!strcmp(argv[3], "speech-amr")) {
1521 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1522 ct.perm_spch[0] = GSM0808_PERM_FR3;
1523 ct.perm_spch[1] = GSM0808_PERM_HR3;
1524 ct.perm_spch_len = 2;
1525 }
1526
1527 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1528
1529 if (!strcmp(argv[2], "tch/f"))
1530 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1531 else if (!strcmp(argv[2], "tch/h"))
1532 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1533 else if (!strcmp(argv[2], "tch/any"))
1534 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1535 else if (!strcmp(argv[2], "sdcch")) {
1536 if (speech) {
1537 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1538 return CMD_WARNING;
1539 }
1540 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1541 } else
1542 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1543
1544 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1545 port = argc >= 6 ? atoi(argv[5]) : 4000;
1546
1547 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001548 switch (rc) {
1549 case -ENODEV:
1550 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1551 break;
1552 default:
1553 if (rc)
1554 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1555 else
1556 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1557 break;
1558 }
1559
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001560 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001561 return rc ? CMD_WARNING : CMD_SUCCESS;
1562}
1563
1564DEFUN(subscriber_silent_call_stop,
1565 subscriber_silent_call_stop_cmd,
1566 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1567 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1568 CHAN_TYPE_HELP)
1569{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001570 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1571 int rc;
1572
1573 if (!vsub) {
1574 vty_out(vty, "%% No subscriber found for %s %s%s",
1575 argv[0], argv[1], VTY_NEWLINE);
1576 return CMD_WARNING;
1577 }
1578
1579 rc = gsm_silent_call_stop(vsub);
1580 switch (rc) {
1581 case -ENODEV:
1582 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1583 break;
1584 case -ENOENT:
1585 vty_out(vty, "%% Subscriber has no silent call active%s",
1586 VTY_NEWLINE);
1587 break;
1588 default:
1589 if (rc)
1590 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1591 else
1592 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1593 break;
1594 }
1595
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001596 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001597 return rc ? CMD_WARNING : CMD_SUCCESS;
1598}
1599
1600DEFUN(subscriber_ussd_notify,
1601 subscriber_ussd_notify_cmd,
1602 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1603 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1604 "Alerting Level 0\n"
1605 "Alerting Level 1\n"
1606 "Alerting Level 2\n"
1607 "Text of USSD message to send\n")
1608{
1609 char *text;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001610 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001611 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1612 int level;
1613
1614 if (!vsub) {
1615 vty_out(vty, "%% No subscriber found for %s %s%s",
1616 argv[0], argv[1], VTY_NEWLINE);
1617 return CMD_WARNING;
1618 }
1619
1620 level = atoi(argv[2]);
1621 text = argv_concat(argv, argc, 3);
1622 if (!text) {
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001623 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001624 return CMD_WARNING;
1625 }
1626
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001627 msc_a = msc_a_for_vsub(vsub, true);
1628 if (!msc_a || msc_a->c.remote_to) {
1629 vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001630 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001631 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001632 talloc_free(text);
1633 return CMD_WARNING;
1634 }
1635
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001636 msc_send_ussd_notify(msc_a, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001637 /* FIXME: since we don't allocate a transaction here,
1638 * we use dummy GSM 04.07 transaction ID. */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001639 msc_send_ussd_release_complete(msc_a, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001640
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001641 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001642 talloc_free(text);
1643 return CMD_SUCCESS;
1644}
1645
1646DEFUN(subscriber_paging,
1647 subscriber_paging_cmd,
1648 "subscriber " SUBSCR_TYPES " ID paging",
1649 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1650{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001651 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001652 struct paging_request *req;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001653
1654 if (!vsub) {
1655 vty_out(vty, "%% No subscriber found for %s %s%s",
1656 argv[0], argv[1], VTY_NEWLINE);
1657 return CMD_WARNING;
1658 }
1659
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001660 req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL,
1661 NULL, NULL, "manual Paging from VTY");
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001662 if (req)
1663 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1664 else
1665 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1666
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001667 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001668 return req ? CMD_SUCCESS : CMD_WARNING;
1669}
1670
1671static int loop_by_char(uint8_t ch)
1672{
1673 switch (ch) {
1674 case 'a':
1675 return GSM414_LOOP_A;
1676 case 'b':
1677 return GSM414_LOOP_B;
1678 case 'c':
1679 return GSM414_LOOP_C;
1680 case 'd':
1681 return GSM414_LOOP_D;
1682 case 'e':
1683 return GSM414_LOOP_E;
1684 case 'f':
1685 return GSM414_LOOP_F;
1686 case 'i':
1687 return GSM414_LOOP_I;
1688 }
1689 return -1;
1690}
1691
1692DEFUN(subscriber_mstest_close,
1693 subscriber_mstest_close_cmd,
1694 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1695 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1696 "Close a TCH Loop inside the MS\n"
1697 "Loop Type A\n"
1698 "Loop Type B\n"
1699 "Loop Type C\n"
1700 "Loop Type D\n"
1701 "Loop Type E\n"
1702 "Loop Type F\n"
1703 "Loop Type I\n")
1704{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001705 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001706 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1707 const char *loop_str;
1708 int loop_mode;
1709
1710 if (!vsub) {
1711 vty_out(vty, "%% No subscriber found for %s %s%s",
1712 argv[0], argv[1], VTY_NEWLINE);
1713 return CMD_WARNING;
1714 }
1715
1716 loop_str = argv[2];
1717 loop_mode = loop_by_char(loop_str[0]);
1718
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001719 msc_a = msc_a_for_vsub(vsub, true);
1720 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001721 vty_out(vty, "%% An active connection is required for %s %s%s",
1722 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001723 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001724 return CMD_WARNING;
1725 }
1726
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001727 gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001728
Vadim Yanitskiy817ad902020-07-29 05:47:01 +07001729 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001730 return CMD_SUCCESS;
1731}
1732
1733DEFUN(subscriber_mstest_open,
1734 subscriber_mstest_open_cmd,
1735 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1736 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1737 "Open a TCH Loop inside the MS\n")
1738{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001739 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001740 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1741
1742 if (!vsub) {
1743 vty_out(vty, "%% No subscriber found for %s %s%s",
1744 argv[0], argv[1], VTY_NEWLINE);
1745 return CMD_WARNING;
1746 }
1747
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001748 msc_a = msc_a_for_vsub(vsub, true);
1749 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001750 vty_out(vty, "%% An active connection is required for %s %s%s",
1751 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001752 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001753 return CMD_WARNING;
1754 }
1755
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001756 gsm0414_tx_open_loop_cmd(msc_a);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001757
Vadim Yanitskiy817ad902020-07-29 05:47:01 +07001758 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001759 return CMD_SUCCESS;
1760}
1761
1762DEFUN(ena_subscr_expire,
1763 ena_subscr_expire_cmd,
1764 "subscriber " SUBSCR_TYPES " ID expire",
1765 SUBSCR_HELP "Expire the subscriber Now\n")
1766{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001767 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1768 argv[1]);
1769
1770 if (!vsub) {
1771 vty_out(vty, "%% No subscriber found for %s %s%s",
1772 argv[0], argv[1], VTY_NEWLINE);
1773 return CMD_WARNING;
1774 }
1775
1776 if (vlr_subscr_expire(vsub))
1777 vty_out(vty, "%% VLR released subscriber %s%s",
1778 vlr_subscr_name(vsub), VTY_NEWLINE);
1779
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001780 if (osmo_use_count_total(&vsub->use_count) > 1)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001781 vty_out(vty, "%% Subscriber %s is still in use,"
1782 " should be released soon%s",
1783 vlr_subscr_name(vsub), VTY_NEWLINE);
1784
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001785 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001786 return CMD_SUCCESS;
1787}
1788
1789static int scall_cbfn(unsigned int subsys, unsigned int signal,
1790 void *handler_data, void *signal_data)
1791{
1792 struct scall_signal_data *sigdata = signal_data;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001793 struct vty *vty = sigdata->vty;
1794
1795 if (!vty_is_active(vty))
1796 return 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001797
1798 switch (signal) {
1799 case S_SCALL_SUCCESS:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001800 vty_out(vty, "%% Silent call success%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001801 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001802 case S_SCALL_FAILED:
1803 vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE);
1804 break;
1805 case S_SCALL_DETACHED:
1806 vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001807 break;
1808 }
1809 return 0;
1810}
1811
1812DEFUN(show_stats,
1813 show_stats_cmd,
1814 "show statistics",
1815 SHOW_STR "Display network statistics\n")
1816{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001817 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001818 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_ATTACH)->current,
1819 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_NORMAL)->current,
1820 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_PERIODIC)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001821 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001822 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001823 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_DETACH)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001824 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001825 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001826 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_COMPLETED)->current,
1827 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_FAILED)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001828 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001829 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001830 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_SUBMITTED)->current,
1831 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_NO_RECEIVER)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001832 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001833 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001834 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_DELIVERED)->current,
1835 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_RP_ERR_MEM)->current,
1836 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_RP_ERR_OTHER)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001837 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001838 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001839 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MO_SETUP)->current,
1840 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MO_CONNECT_ACK)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001841 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001842 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001843 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MT_SETUP)->current,
1844 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MT_CONNECT)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001845 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001846 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001847 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_REQUESTS)->current,
1848 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_ESTABLISHED)->current,
1849 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,
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001851 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001852 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001853 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_REQUESTS)->current,
1854 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_ESTABLISHED)->current,
1855 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,
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001857 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001858 return CMD_SUCCESS;
1859}
1860
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001861
1862DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1863 "mncc-int", "Configure internal MNCC handler")
1864{
1865 vty->node = MNCC_INT_NODE;
1866
1867 return CMD_SUCCESS;
1868}
1869
1870static struct cmd_node mncc_int_node = {
1871 MNCC_INT_NODE,
1872 "%s(config-mncc-int)# ",
1873 1,
1874};
1875
1876static const struct value_string tchf_codec_names[] = {
1877 { GSM48_CMODE_SPEECH_V1, "fr" },
1878 { GSM48_CMODE_SPEECH_EFR, "efr" },
1879 { GSM48_CMODE_SPEECH_AMR, "amr" },
1880 { 0, NULL }
1881};
1882
1883static const struct value_string tchh_codec_names[] = {
1884 { GSM48_CMODE_SPEECH_V1, "hr" },
1885 { GSM48_CMODE_SPEECH_AMR, "amr" },
1886 { 0, NULL }
1887};
1888
1889static int config_write_mncc_int(struct vty *vty)
1890{
1891 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1892 vty_out(vty, " default-codec tch-f %s%s",
1893 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1894 VTY_NEWLINE);
1895 vty_out(vty, " default-codec tch-h %s%s",
1896 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1897 VTY_NEWLINE);
1898
1899 return CMD_SUCCESS;
1900}
1901
1902DEFUN(mnccint_def_codec_f,
1903 mnccint_def_codec_f_cmd,
1904 "default-codec tch-f (fr|efr|amr)",
1905 "Set default codec\n" "Codec for TCH/F\n"
1906 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1907{
1908 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1909
1910 return CMD_SUCCESS;
1911}
1912
1913DEFUN(mnccint_def_codec_h,
1914 mnccint_def_codec_h_cmd,
1915 "default-codec tch-h (hr|amr)",
1916 "Set default codec\n" "Codec for TCH/H\n"
1917 "Half-Rate\n" "Adaptive Multi-Rate\n")
1918{
1919 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1920
1921 return CMD_SUCCESS;
1922}
1923
1924
1925DEFUN(logging_fltr_imsi,
1926 logging_fltr_imsi_cmd,
1927 "logging filter imsi IMSI",
1928 LOGGING_STR FILTER_STR
1929 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1930{
1931 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001932 struct log_target *tgt = osmo_log_vty2tgt(vty);
1933 const char *imsi = argv[0];
1934
1935 if (!tgt)
1936 return CMD_WARNING;
1937
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001938 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001939
1940 if (!vlr_subscr) {
1941 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1942 argv[0], VTY_NEWLINE);
1943 return CMD_WARNING;
1944 }
1945
1946 log_set_filter_vlr_subscr(tgt, vlr_subscr);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001947 vlr_subscr_put(vlr_subscr, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001948 return CMD_SUCCESS;
1949}
1950
1951static struct cmd_node hlr_node = {
1952 HLR_NODE,
1953 "%s(config-hlr)# ",
1954 1,
1955};
1956
1957DEFUN(cfg_hlr, cfg_hlr_cmd,
1958 "hlr", "Configure connection to the HLR")
1959{
1960 vty->node = HLR_NODE;
1961 return CMD_SUCCESS;
1962}
1963
1964DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1965 "Remote GSUP address of the HLR\n"
1966 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1967{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001968 talloc_free((void*)gsmnet->gsup_server_addr_str);
1969 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1970 return CMD_SUCCESS;
1971}
1972
1973DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1974 "Remote GSUP port of the HLR\n"
1975 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1976{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001977 gsmnet->gsup_server_port = atoi(argv[0]);
1978 return CMD_SUCCESS;
1979}
1980
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001981DEFUN(cfg_hlr_ipa_name,
1982 cfg_hlr_ipa_name_cmd,
1983 "ipa-name NAME",
1984 "Set the IPA name of this MSC\n"
1985 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1986 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
1987 "The default is 'MSC-00-00-00-00-00-00'.\n")
1988{
1989 if (vty->type != VTY_FILE) {
1990 vty_out(vty, "The IPA name cannot be changed at run-time; "
Martin Hauke3f07dac2019-11-14 17:49:08 +01001991 "It can only be set in the configuration file.%s", VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001992 return CMD_WARNING;
1993 }
1994
1995 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
1996 return CMD_SUCCESS;
1997}
1998
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001999static int config_write_hlr(struct vty *vty)
2000{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002001 vty_out(vty, "hlr%s", VTY_NEWLINE);
2002 vty_out(vty, " remote-ip %s%s",
2003 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
2004 vty_out(vty, " remote-port %u%s",
2005 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002006 if (gsmnet->msc_ipa_name)
2007 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002008 return CMD_SUCCESS;
2009}
2010
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002011void msc_vty_init(struct gsm_network *msc_network)
2012{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01002013 OSMO_ASSERT(gsmnet == NULL);
2014 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002015
2016 osmo_stats_vty_add_cmds();
2017
2018 install_element(CONFIG_NODE, &cfg_net_cmd);
2019 install_node(&net_node, config_write_net);
2020 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
2021 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
2022 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
2023 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
2024 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +02002025 install_element(GSMNET_NODE, &cfg_net_encryption_uea_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002026 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
2027 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
2028 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
2029 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
2030 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
2031 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
2032 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
2033 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Keith Whyte991bb422019-08-08 15:43:40 +02002034 install_element(GSMNET_NODE, &cfg_net_call_wait_cmd);
2035 install_element(GSMNET_NODE, &cfg_net_no_call_wait_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002036
2037 install_element(CONFIG_NODE, &cfg_msc_cmd);
2038 install_node(&msc_node, config_write_msc);
Keith Whyte1587ffb2020-08-28 13:36:58 +02002039 install_element(MSC_NODE, &cfg_sms_database_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002040 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Keith Whytea1a70be2021-05-16 02:59:52 +02002041 install_element(MSC_NODE, &cfg_msc_lcls_disable_cmd);
2042 install_element(MSC_NODE, &cfg_msc_no_lcls_disable_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01002043 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
2044 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02002045 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01002046 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07002047 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002048 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01002049 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
2050 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01002051 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02002052 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
2053 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01002054 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01002055 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07002056 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
2057 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +02002058 install_element(MSC_NODE, &cfg_msc_osmux_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002059 install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd);
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +02002060 install_element(MSC_NODE, &cfg_msc_nri_bitlen_cmd);
2061 install_element(MSC_NODE, &cfg_msc_nri_add_cmd);
2062 install_element(MSC_NODE, &cfg_msc_nri_del_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002063
2064 neighbor_ident_vty_init(msc_network);
Philipp Maierfbf66102017-04-09 12:32:51 +02002065
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +07002066 /* Timer configuration commands (generic osmo_tdef API) */
2067 osmo_tdef_vty_groups_init(MSC_NODE, msc_tdef_group);
2068
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02002069 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002070#ifdef BUILD_IU
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002071 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 +02002072#endif
Harald Welte0df904d2018-12-03 11:00:04 +01002073 sgs_vty_init();
Harald Welte1a62db22022-05-17 12:06:58 +02002074 smsc_vty_init(msc_network);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002075
Stefan Sperling617ac802018-02-22 17:58:20 +01002076 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002077
2078 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
2079
2080 install_element_ve(&show_subscr_cmd);
2081 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01002082 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002083 install_element_ve(&show_msc_conn_cmd);
2084 install_element_ve(&show_msc_transaction_cmd);
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +02002085 install_element_ve(&show_nri_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002086
2087 install_element_ve(&sms_send_pend_cmd);
2088 install_element_ve(&sms_delete_expired_cmd);
2089
2090 install_element_ve(&subscriber_create_cmd);
2091 install_element_ve(&subscriber_send_sms_cmd);
2092 install_element_ve(&subscriber_silent_sms_cmd);
2093 install_element_ve(&subscriber_silent_call_start_cmd);
2094 install_element_ve(&subscriber_silent_call_stop_cmd);
2095 install_element_ve(&subscriber_ussd_notify_cmd);
2096 install_element_ve(&subscriber_mstest_close_cmd);
2097 install_element_ve(&subscriber_mstest_open_cmd);
2098 install_element_ve(&subscriber_paging_cmd);
2099 install_element_ve(&show_stats_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002100 install_element_ve(&logging_fltr_imsi_cmd);
2101
2102 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002103 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01002104 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002105
2106 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
2107 install_node(&mncc_int_node, config_write_mncc_int);
2108 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
2109 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
2110
2111 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
2112
2113 install_element(CONFIG_NODE, &cfg_hlr_cmd);
2114 install_node(&hlr_node, config_write_hlr);
2115 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
2116 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002117 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002118}