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