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