blob: e4e0937414e608d01337a62fa21dbcd9cd7b69e8 [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 +0200172/* So far just a boolean switch, a future patch might add individual config for UEA1 and UEA2, see OS#4143 */
173DEFUN(cfg_net_encryption_uea,
174 cfg_net_encryption_uea_cmd,
175 "encryption uea <0-2> [<0-2>] [<0-2>]",
176 ENCRYPTION_STR
177 "UTRAN (3G) encryption algorithms to allow: 0 = UEA0 (no encryption), 1 = UEA1, 2 = UEA2."
178 " NOTE: the current implementation does not allow free choice of combining encryption algorithms yet."
179 " The only valid settings are either 'encryption uea 0' or 'encryption uea 1 2'.\n"
180 "UEAn Algorithm Number\n"
181 "UEAn Algorithm Number\n"
182 "UEAn Algorithm Number\n"
183 )
184{
185 unsigned int i;
186 uint8_t mask = 0;
187
188 for (i = 0; i < argc; i++)
189 mask |= (1 << atoi(argv[i]));
190
191 if (mask == (1 << 0)) {
192 /* UEA0. Disable encryption. */
193 gsmnet->uea_encryption = false;
194 } else if (mask == ((1 << 1) | (1 << 2))) {
195 /* UEA1 and UEA2. Enable encryption. */
196 gsmnet->uea_encryption = true;
197 } else {
198 vty_out(vty,
199 "%% Error: the current implementation does not allow free choice of combining%s"
200 "%% encryption algorithms yet. The only valid settings are either%s"
201 "%% encryption uea 0%s"
202 "%% or%s"
203 "%% encryption uea 1 2%s",
204 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
205 return CMD_WARNING;
206 }
207
208 return CMD_SUCCESS;
209}
210
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100211DEFUN(cfg_net_authentication,
212 cfg_net_authentication_cmd,
213 "authentication (optional|required)",
214 "Whether to enforce MS authentication in 2G\n"
215 "Allow MS to attach via 2G BSC without authentication\n"
216 "Always do authentication\n")
217{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100218 gsmnet->authentication_required = (argv[0][0] == 'r') ? true : false;
219
220 return CMD_SUCCESS;
221}
222
223DEFUN(cfg_net_rrlp_mode, cfg_net_rrlp_mode_cmd,
224 "rrlp mode (none|ms-based|ms-preferred|ass-preferred)",
225 "Radio Resource Location Protocol\n"
226 "Set the Radio Resource Location Protocol Mode\n"
227 "Don't send RRLP request\n"
228 "Request MS-based location\n"
229 "Request any location, prefer MS-based\n"
230 "Request any location, prefer MS-assisted\n")
231{
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700232 gsmnet->rrlp.mode = msc_rrlp_mode_parse(argv[0]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100233
234 return CMD_SUCCESS;
235}
236
237DEFUN(cfg_net_mm_info, cfg_net_mm_info_cmd,
238 "mm info (0|1)",
239 "Mobility Management\n"
240 "Send MM INFO after LOC UPD ACCEPT\n"
241 "Disable\n" "Enable\n")
242{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100243 gsmnet->send_mm_info = atoi(argv[0]);
244
245 return CMD_SUCCESS;
246}
247
248DEFUN(cfg_net_timezone,
249 cfg_net_timezone_cmd,
250 "timezone <-19-19> (0|15|30|45)",
251 "Set the Timezone Offset of the network\n"
252 "Timezone offset (hours)\n"
253 "Timezone offset (00 minutes)\n"
254 "Timezone offset (15 minutes)\n"
255 "Timezone offset (30 minutes)\n"
256 "Timezone offset (45 minutes)\n"
257 )
258{
259 struct gsm_network *net = vty->index;
260 int tzhr = atoi(argv[0]);
261 int tzmn = atoi(argv[1]);
262
263 net->tz.hr = tzhr;
264 net->tz.mn = tzmn;
265 net->tz.dst = 0;
266 net->tz.override = 1;
267
268 return CMD_SUCCESS;
269}
270
271DEFUN(cfg_net_timezone_dst,
272 cfg_net_timezone_dst_cmd,
273 "timezone <-19-19> (0|15|30|45) <0-2>",
274 "Set the Timezone Offset of the network\n"
275 "Timezone offset (hours)\n"
276 "Timezone offset (00 minutes)\n"
277 "Timezone offset (15 minutes)\n"
278 "Timezone offset (30 minutes)\n"
279 "Timezone offset (45 minutes)\n"
280 "DST offset (hours)\n"
281 )
282{
283 struct gsm_network *net = vty->index;
284 int tzhr = atoi(argv[0]);
285 int tzmn = atoi(argv[1]);
286 int tzdst = atoi(argv[2]);
287
288 net->tz.hr = tzhr;
289 net->tz.mn = tzmn;
290 net->tz.dst = tzdst;
291 net->tz.override = 1;
292
293 return CMD_SUCCESS;
294}
295
296DEFUN(cfg_net_no_timezone,
297 cfg_net_no_timezone_cmd,
298 "no timezone",
299 NO_STR
300 "Disable network timezone override, use system tz\n")
301{
302 struct gsm_network *net = vty->index;
303
304 net->tz.override = 0;
305
306 return CMD_SUCCESS;
307}
308
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700309/* NOTE: actually this is subscriber expiration timeout */
310#define PER_LOC_UPD_STR "Periodic Location Updating Interval\n"
311
312DEFUN_DEPRECATED(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
313 "periodic location update <6-1530>",
314 PER_LOC_UPD_STR PER_LOC_UPD_STR PER_LOC_UPD_STR
315 "Periodic Location Updating Interval in Minutes\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100316{
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700317 int minutes = atoi(argv[0]);
318 int rc;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100319
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700320 vty_out(vty, "%% 'periodic location update' is now deprecated: "
321 "use 'timer T3212' to change subscriber expiration "
322 "timeout.%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100323
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700324 /* We used to double this value and add a minute when scheduling the
325 * expiration timer. Let's emulate the old behaviour here. */
326 minutes = minutes * 2 + 1;
327 vty_out(vty, "%% Setting T3212 to %d minutes "
328 "(emulating the old behaviour).%s",
329 minutes, VTY_NEWLINE);
330
331 rc = osmo_tdef_set(msc_tdefs_vlr, 3212, minutes, OSMO_TDEF_M);
332 return rc ? CMD_WARNING : CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100333}
334
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700335DEFUN_DEPRECATED(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
336 "no periodic location update",
337 NO_STR PER_LOC_UPD_STR PER_LOC_UPD_STR PER_LOC_UPD_STR)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100338{
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700339 int rc;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100340
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700341 vty_out(vty, "%% 'periodic location update' is now deprecated: "
342 "use 'timer T3212' to change subscriber expiration "
343 "timeout.%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100344
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700345 rc = osmo_tdef_set(msc_tdefs_vlr, 3212, 0, OSMO_TDEF_M);
346 return rc ? CMD_WARNING : CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100347}
348
Keith Whyte991bb422019-08-08 15:43:40 +0200349DEFUN(cfg_net_call_wait, cfg_net_call_wait_cmd,
350 "call-waiting",
351 "Enable Call Waiting on the Network\n")
352{
353 struct gsm_network *net = vty->index;
354
355 net->call_waiting = true;
356
357 return CMD_SUCCESS;
358}
359
360DEFUN(cfg_net_no_call_wait, cfg_net_no_call_wait_cmd,
361 "no call-waiting",
362 NO_STR
363 "Disable Call Waiting on the Network\n")
364{
365 struct gsm_network *net = vty->index;
366
367 net->call_waiting = false;
368
369 return CMD_SUCCESS;
370}
371
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100372static int config_write_net(struct vty *vty)
373{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100374 int i;
375
376 vty_out(vty, "network%s", VTY_NEWLINE);
377 vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
378 vty_out(vty, " mobile network code %s%s",
379 osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
380 vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
381 vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
382 vty_out(vty, " encryption a5");
383 for (i = 0; i < 8; i++) {
384 if (gsmnet->a5_encryption_mask & (1 << i))
385 vty_out(vty, " %u", i);
386 }
387 vty_out(vty, "%s", VTY_NEWLINE);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200388
389 if (!gsmnet->uea_encryption)
390 vty_out(vty, " encryption uea 0%s", VTY_NEWLINE);
391 else
392 vty_out(vty, " encryption uea 1 2%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100393 vty_out(vty, " authentication %s%s",
394 gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE);
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700395 vty_out(vty, " rrlp mode %s%s", msc_rrlp_mode_name(gsmnet->rrlp.mode),
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100396 VTY_NEWLINE);
397 vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
398 if (gsmnet->tz.override != 0) {
399 if (gsmnet->tz.dst)
400 vty_out(vty, " timezone %d %d %d%s",
401 gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
402 VTY_NEWLINE);
403 else
404 vty_out(vty, " timezone %d %d%s",
405 gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
406 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100407
Keith Whyte991bb422019-08-08 15:43:40 +0200408 if (!gsmnet->call_waiting)
409 vty_out(vty, " no call-waiting%s", VTY_NEWLINE);
410
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100411 return CMD_SUCCESS;
412}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200413
414static struct cmd_node msc_node = {
415 MSC_NODE,
416 "%s(config-msc)# ",
417 1,
418};
419
420DEFUN(cfg_msc, cfg_msc_cmd,
421 "msc", "Configure MSC options")
422{
423 vty->node = MSC_NODE;
424 return CMD_SUCCESS;
425}
426
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100427#define MNCC_STR "Configure Mobile Network Call Control\n"
428#define MNCC_GUARD_TIMEOUT_STR "Set global guard timer for mncc interface activity\n"
429#define MNCC_GUARD_TIMEOUT_VALUE_STR "guard timer value (sec.)\n"
430
Keith Whyte1587ffb2020-08-28 13:36:58 +0200431DEFUN(cfg_sms_database, cfg_sms_database_cmd,
432 "sms-database PATH",
433 "Set the path to the MSC-SMS database file\n"
434 "Relative or absolute file system path to the database file (default is '" SMS_DEFAULT_DB_FILE_PATH "')\n")
435{
436 osmo_talloc_replace_string(gsmnet, &gsmnet->sms_db_file_path, argv[0]);
437 return CMD_SUCCESS;
438}
439
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100440DEFUN(cfg_msc_mncc_internal,
441 cfg_msc_mncc_internal_cmd,
442 "mncc internal",
443 MNCC_STR "Use internal MNCC handler (default; changes need a program restart)\n")
444{
445 gsm_network_set_mncc_sock_path(gsmnet, NULL);
446 return CMD_SUCCESS;
447}
448
449DEFUN(cfg_msc_mncc_external,
450 cfg_msc_mncc_external_cmd,
451 "mncc external MNCC_SOCKET_PATH",
452 MNCC_STR "Use external MNCC handler (changes need a program restart)\n"
453 "File system path to create the MNCC unix domain socket at\n")
454{
455 gsm_network_set_mncc_sock_path(gsmnet, argv[0]);
456 return CMD_SUCCESS;
457}
458
Philipp Maier9ca7b312018-10-10 17:00:49 +0200459DEFUN(cfg_msc_mncc_guard_timeout,
460 cfg_msc_mncc_guard_timeout_cmd,
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100461 "mncc guard-timeout <0-255>",
462 MNCC_STR
463 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR)
Philipp Maier9ca7b312018-10-10 17:00:49 +0200464{
465 gsmnet->mncc_guard_timeout = atoi(argv[0]);
466 return CMD_SUCCESS;
467}
468
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100469ALIAS_DEPRECATED(cfg_msc_mncc_guard_timeout,
470 cfg_msc_deprecated_mncc_guard_timeout_cmd,
471 "mncc-guard-timeout <0-255>",
472 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR);
473
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700474#define NCSS_STR "Configure call independent Supplementary Services\n"
475
476DEFUN(cfg_msc_ncss_guard_timeout,
477 cfg_msc_ncss_guard_timeout_cmd,
478 "ncss guard-timeout <0-255>",
479 NCSS_STR "Set guard timer for session activity\n"
480 "guard timer value (sec.), or 0 to disable\n")
481{
482 gsmnet->ncss_guard_timeout = atoi(argv[0]);
483 return CMD_SUCCESS;
484}
485
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200486DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
487 "assign-tmsi",
488 "Assign TMSI during Location Updating.\n")
489{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200490 gsmnet->vlr->cfg.assign_tmsi = true;
491 return CMD_SUCCESS;
492}
493
494DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
495 "no assign-tmsi",
496 NO_STR "Assign TMSI during Location Updating.\n")
497{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200498 gsmnet->vlr->cfg.assign_tmsi = false;
499 return CMD_SUCCESS;
500}
501
Keith Whytea1a70be2021-05-16 02:59:52 +0200502DEFUN_ATTR(cfg_msc_lcls_disable, cfg_msc_lcls_disable_cmd,
503 "lcls-permitted",
504 "Globally allow LCLS (Local Call Local Switch) for all calls on this MSC.\n",
505 CMD_ATTR_IMMEDIATE)
506{
507 gsmnet->lcls_permitted = true;
508 return CMD_SUCCESS;
509}
510
511DEFUN_ATTR(cfg_msc_no_lcls_disable, cfg_msc_no_lcls_disable_cmd,
512 "no lcls-permitted",
513 NO_STR "Globally disable LCLS (Local Call Local Switch) for all calls on this MSC.\n",
514 CMD_ATTR_IMMEDIATE)
515{
516 gsmnet->lcls_permitted = false;
517 return CMD_SUCCESS;
518}
519
Philipp Maierfbf66102017-04-09 12:32:51 +0200520DEFUN(cfg_msc_cs7_instance_a,
521 cfg_msc_cs7_instance_a_cmd,
522 "cs7-instance-a <0-15>",
523 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
524{
Philipp Maierfbf66102017-04-09 12:32:51 +0200525 gsmnet->a.cs7_instance = atoi(argv[0]);
526 return CMD_SUCCESS;
527}
528
529DEFUN(cfg_msc_cs7_instance_iu,
530 cfg_msc_cs7_instance_iu_cmd,
531 "cs7-instance-iu <0-15>",
532 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
533{
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100534#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200535 gsmnet->iu.cs7_instance = atoi(argv[0]);
536 return CMD_SUCCESS;
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100537#else
538 vty_out(vty, "WARNING: 'cs7-instance-iu' without effect: built without Iu support%s",
539 VTY_NEWLINE);
540 return CMD_WARNING;
541#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200542}
543
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100544DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
545 "auth-tuple-max-reuse-count <-1-2147483647>",
546 "Configure authentication tuple re-use\n"
547 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
548{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100549 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
550 return CMD_SUCCESS;
551}
552
553DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
554 "auth-tuple-reuse-on-error (0|1)",
555 "Configure authentication tuple re-use when HLR is not responsive\n"
Oliver Smithd6e24fd2019-01-09 10:46:43 +0100556 "Never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
557 "If the HLR does not deliver new tuples, do re-use already available old ones.\n")
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100558{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100559 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
560 return CMD_SUCCESS;
561}
562
Oliver Smith0fec28a2018-12-14 10:52:52 +0100563DEFUN(cfg_msc_check_imei_rqd, cfg_msc_check_imei_rqd_cmd,
Oliver Smith03ded912019-05-02 10:40:50 +0200564 "check-imei-rqd (0|1|early)",
Oliver Smith0fec28a2018-12-14 10:52:52 +0100565 "Send each IMEI to the EIR to ask if it is permitted or not. The EIR is implemented as part of OsmoHLR, "
566 "and can optionally save the IMEI in the HLR.\n"
567 "Do not send IMEIs to the EIR\n"
Oliver Smith03ded912019-05-02 10:40:50 +0200568 "Send each IMEI to the EIR\n"
569 "Send each IMEI to the EIR, and do it at the start of the location update. This allows the EIR to receive the"
570 " 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 +0100571{
Oliver Smith03ded912019-05-02 10:40:50 +0200572 if (strcmp(argv[0], "0") == 0) {
573 gsmnet->vlr->cfg.check_imei_rqd = false;
574 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
575 } else if (strcmp(argv[0], "1") == 0) {
576 gsmnet->vlr->cfg.check_imei_rqd = true;
577 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
578 } else if (strcmp(argv[0], "early") == 0) {
579 gsmnet->vlr->cfg.check_imei_rqd = true;
580 gsmnet->vlr->cfg.retrieve_imeisv_early = true;
581 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100582 return CMD_SUCCESS;
583}
584
Alexander Couzensae167fc2020-09-25 05:25:16 +0200585DEFUN_DEPRECATED(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100586 "paging response-timer (default|<1-65535>)",
587 "Configure Paging\n"
588 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
589 " BSS or RNC\n"
590 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
591 "Set paging timeout in seconds\n")
592{
Alexander Couzensae167fc2020-09-25 05:25:16 +0200593 int rat;
594 int paging_response_timer;
Pau Espin Pedrolb08a3802019-09-16 19:01:37 +0200595 if (!strcmp(argv[0], "default"))
Alexander Couzensae167fc2020-09-25 05:25:16 +0200596 paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100597 else
Alexander Couzensae167fc2020-09-25 05:25:16 +0200598 paging_response_timer = atoi(argv[0]);
599
600 for (rat = 0; rat < OSMO_RAT_COUNT; rat++) {
601 osmo_tdef_set(msc_ran_infra[rat].tdefs, -4, paging_response_timer, OSMO_TDEF_S);
602 }
603
604 vty_out(vty, "%% paging response-timer is deprecated.%s"
605 "%% All ran timer has been modified.%s"
606 "%% use 'timer <geran|utran|sgs> X4 %s' instead%s",
607 VTY_NEWLINE, VTY_NEWLINE, argv[0], VTY_NEWLINE);
608
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100609 return CMD_SUCCESS;
610}
611
Harald Welte69c54a82018-02-09 20:41:14 +0100612DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
613 "emergency-call route-to-msisdn MSISDN",
614 "Configure Emergency Call Behaviour\n"
615 "MSISDN to which Emergency Calls are Dispatched\n"
616 "MSISDN (E.164 Phone Number)\n")
617{
Harald Welte69c54a82018-02-09 20:41:14 +0100618 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
619
620 return CMD_SUCCESS;
621}
622
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700623/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
624DEFUN(cfg_msc_sms_over_gsup, cfg_msc_sms_over_gsup_cmd,
625 "sms-over-gsup",
626 "Enable routing of SMS messages over GSUP\n")
627{
628 gsmnet->sms_over_gsup = true;
629 return CMD_SUCCESS;
630}
631
632/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
633DEFUN(cfg_msc_no_sms_over_gsup, cfg_msc_no_sms_over_gsup_cmd,
634 "no sms-over-gsup",
635 NO_STR "Disable routing of SMS messages over GSUP\n")
636{
637 gsmnet->sms_over_gsup = false;
638 return CMD_SUCCESS;
639}
640
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100641/* FIXME: This should rather be in the form of
642 * handover-number range 001234xxx
643 * and
644 * handover-number range 001234xxx FIRST LAST
645 */
646DEFUN(cfg_msc_handover_number_range, cfg_msc_handover_number_range_cmd,
647 "handover-number range MSISDN_FIRST MSISDN_LAST",
648 "Configure a range of MSISDN to be assigned to incoming inter-MSC Handovers for call forwarding.\n"
649 "Configure a handover number range\n"
650 "First Handover Number MSISDN\n"
651 "Last Handover Number MSISDN\n")
652{
653 char *endp;
654 uint64_t range_start;
655 uint64_t range_end;
656
657 /* FIXME leading zeros?? */
658
659 errno = 0;
660 range_start = strtoull(argv[0], &endp, 10);
661 if (errno || *endp != '\0') {
662 vty_out(vty, "%% Error parsing handover-number range start: %s%s",
663 argv[0], VTY_NEWLINE);
664 return CMD_WARNING;
665 }
666
667 errno = 0;
668 range_end = strtoull(argv[1], &endp, 10);
669 if (errno || *endp != '\0') {
670 vty_out(vty, "%% Error parsing handover-number range end: %s%s",
671 argv[1], VTY_NEWLINE);
672 return CMD_WARNING;
673 }
674
675 if (range_start > range_end) {
676 vty_out(vty, "%% Error: handover-number range end must be > than the range start, but"
677 " %"PRIu64" > %"PRIu64"%s", range_start, range_end, VTY_NEWLINE);
678 return CMD_WARNING;
679 }
680
681 gsmnet->handover_number.range_start = range_start;
682 gsmnet->handover_number.range_end = range_end;
683 return CMD_SUCCESS;
684}
685
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200686#define OSMUX_STR "RTP multiplexing\n"
687DEFUN(cfg_msc_osmux,
688 cfg_msc_osmux_cmd,
689 "osmux (on|off|only)",
690 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
691{
692 if (strcmp(argv[0], "off") == 0)
693 gsmnet->use_osmux = OSMUX_USAGE_OFF;
694 else if (strcmp(argv[0], "on") == 0)
695 gsmnet->use_osmux = OSMUX_USAGE_ON;
696 else if (strcmp(argv[0], "only") == 0)
697 gsmnet->use_osmux = OSMUX_USAGE_ONLY;
698
699 return CMD_SUCCESS;
700}
701
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +0200702#define NRI_STR "Mapping of Network Resource Indicators to this MSC, for MSC pooling\n"
703DEFUN(cfg_msc_nri_bitlen, cfg_msc_nri_bitlen_cmd,
704 "nri bitlen <0-15>",
705 NRI_STR
706 "Set number of NRI bits to place in TMSI identities (always starting just after the most significant octet)\n"
707 "bit count (default: " OSMO_STRINGIFY_VAL(NRI_BITLEN_DEFAULT) ")\n")
708{
709 gsmnet->vlr->cfg.nri_bitlen = atoi(argv[0]);
710 return CMD_SUCCESS;
711}
712
713#define NRI_STR "Mapping of Network Resource Indicators to this MSC, for MSC pooling\n"
714#define NRI_ARGS_TO_STR_FMT "%s%s%s"
715#define NRI_ARGS_TO_STR_ARGS(ARGC, ARGV) ARGV[0], (ARGC>1)? ".." : "", (ARGC>1)? ARGV[1] : ""
716#define NRI_FIRST_LAST_STR "First value of the NRI value range, should not surpass the configured 'nri bitlen'.\n" \
717 "Last value of the NRI value range, should not surpass the configured 'nri bitlen' and be larger than the" \
718 " first value; if omitted, apply only the first value.\n"
719
720DEFUN(cfg_msc_nri_add, cfg_msc_nri_add_cmd,
721 "nri add <0-32767> [<0-32767>]",
722 NRI_STR "Add NRI value or range to the NRI mapping for this MSC\n"
723 NRI_FIRST_LAST_STR)
724{
725 const char *message;
726 int rc = osmo_nri_ranges_vty_add(&message, NULL, gsmnet->vlr->cfg.nri_ranges, argc, argv, gsmnet->vlr->cfg.nri_bitlen);
727 if (message) {
728 vty_out(vty, "%% %s: " NRI_ARGS_TO_STR_FMT, message, NRI_ARGS_TO_STR_ARGS(argc, argv));
729 }
730 if (rc < 0)
731 return CMD_WARNING;
732 return CMD_SUCCESS;
733}
734
735DEFUN(cfg_msc_nri_del, cfg_msc_nri_del_cmd,
736 "nri del <0-32767> [<0-32767>]",
737 NRI_STR "Remove NRI value or range from the NRI mapping for this MSC\n"
738 NRI_FIRST_LAST_STR)
739{
740 const char *message;
741 int rc = osmo_nri_ranges_vty_del(&message, NULL, gsmnet->vlr->cfg.nri_ranges, argc, argv);
742 if (message) {
743 vty_out(vty, "%% %s: " NRI_ARGS_TO_STR_FMT, message, NRI_ARGS_TO_STR_ARGS(argc, argv));
744 }
745 if (rc < 0)
746 return CMD_WARNING;
747 return CMD_SUCCESS;
748}
749
750static void msc_write_nri(struct vty *vty)
751{
752 struct osmo_nri_range *r;
753
754 llist_for_each_entry(r, &gsmnet->vlr->cfg.nri_ranges->entries, entry) {
755 if (osmo_nri_range_validate(r, 255))
756 vty_out(vty, " %% INVALID RANGE:");
757 vty_out(vty, " nri add %d", r->first);
758 if (r->first != r->last)
759 vty_out(vty, " %d", r->last);
760 vty_out(vty, "%s", VTY_NEWLINE);
761 }
762}
763
764DEFUN(show_nri, show_nri_cmd,
765 "show nri",
766 SHOW_STR NRI_STR)
767{
768 msc_write_nri(vty);
769 return CMD_SUCCESS;
770}
771
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200772static int config_write_msc(struct vty *vty)
773{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200774 vty_out(vty, "msc%s", VTY_NEWLINE);
Keith Whyte1587ffb2020-08-28 13:36:58 +0200775 if (gsmnet->sms_db_file_path && strcmp(gsmnet->sms_db_file_path, SMS_DEFAULT_DB_FILE_PATH))
776 vty_out(vty, " sms-database %s%s", gsmnet->sms_db_file_path, VTY_NEWLINE);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100777 if (gsmnet->mncc_sock_path)
778 vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE);
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100779 vty_out(vty, " mncc guard-timeout %i%s",
Philipp Maier9ca7b312018-10-10 17:00:49 +0200780 gsmnet->mncc_guard_timeout, VTY_NEWLINE);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700781 vty_out(vty, " ncss guard-timeout %i%s",
782 gsmnet->ncss_guard_timeout, VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200783 vty_out(vty, " %sassign-tmsi%s",
784 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
Keith Whytea1a70be2021-05-16 02:59:52 +0200785 if (gsmnet->lcls_permitted)
786 vty_out(vty, " lcls-permitted%s", VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200787
Philipp Maierfbf66102017-04-09 12:32:51 +0200788 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
789 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100790#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200791 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
792 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100793#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200794
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100795 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
796 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
797 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
798 VTY_NEWLINE);
799 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
800 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
801 VTY_NEWLINE);
802
Oliver Smith03ded912019-05-02 10:40:50 +0200803 if (gsmnet->vlr->cfg.check_imei_rqd) {
804 if (gsmnet->vlr->cfg.retrieve_imeisv_early)
805 vty_out(vty, " check-imei-rqd early%s", VTY_NEWLINE);
806 else
807 vty_out(vty, " check-imei-rqd 1%s", VTY_NEWLINE);
808 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100809
Harald Welte69c54a82018-02-09 20:41:14 +0100810 if (gsmnet->emergency.route_to_msisdn) {
811 vty_out(vty, " emergency-call route-to-msisdn %s%s",
812 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
813 }
814
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700815 if (gsmnet->sms_over_gsup)
816 vty_out(vty, " sms-over-gsup%s", VTY_NEWLINE);
817
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100818 if (gsmnet->handover_number.range_start || gsmnet->handover_number.range_end)
819 vty_out(vty, " handover-number range %"PRIu64" %"PRIu64"%s",
820 gsmnet->handover_number.range_start, gsmnet->handover_number.range_end,
821 VTY_NEWLINE);
822
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200823 if (gsmnet->use_osmux != OSMUX_USAGE_OFF) {
824 vty_out(vty, " osmux %s%s", gsmnet->use_osmux == OSMUX_USAGE_ON ? "on" : "only",
825 VTY_NEWLINE);
826 }
827
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200828 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200829#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200830 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200831#endif
832
Neels Hofmeyr880b9502019-05-09 02:01:55 +0200833 neighbor_ident_vty_write(vty);
834
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +0700835 /* Timer introspection commands (generic osmo_tdef API) */
836 osmo_tdef_vty_groups_write(vty, " ");
837
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +0200838 msc_write_nri(vty);
839
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200840 return CMD_SUCCESS;
841}
842
Maxc51609a2018-11-09 17:13:00 +0100843DEFUN(show_bsc, show_bsc_cmd,
844 "show bsc", SHOW_STR "BSC\n")
845{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100846 struct ran_peer *rp;
847 llist_for_each_entry(rp, &gsmnet->a.sri->ran_peers, entry) {
848 vty_out(vty, "BSC %s %s%s",
849 osmo_sccp_inst_addr_name(gsmnet->a.sri->sccp, &rp->peer_addr),
850 osmo_fsm_inst_state_name(rp->fi),
851 VTY_NEWLINE);
Maxc51609a2018-11-09 17:13:00 +0100852 }
853
854 return CMD_SUCCESS;
855}
856
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100857static const char *get_trans_proto_str(const struct gsm_trans *trans)
858{
859 static char buf[256];
860
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100861 switch (trans->type) {
862 case TRANS_CC:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100863 snprintf(buf, sizeof(buf), "%s %4u %4u",
864 gsm48_cc_state_name(trans->cc.state),
865 trans->cc.Tcurrent,
866 trans->cc.T308_second);
867 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100868 case TRANS_SMS:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700869 snprintf(buf, sizeof(buf), "CP:%s RP:%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100870 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
871 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
872 break;
873 default:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700874 return NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100875 }
876
877 return buf;
878}
879
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700880/* Prefix a given format string with a given amount of spaces */
881#define MSC_VTY_DUMP(vty, offset, fmt, args...) \
882 vty_out(vty, "%*s" fmt, offset, "", ##args)
883
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200884/* Print value of a named flag, prefixed with a given amount of spaces */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700885#define MSC_VTY_DUMP_FLAG(vty, offset, name, flag) \
886 MSC_VTY_DUMP(vty, offset + 2, "%s: %*s%s%s", \
887 name, 30 - (int)strlen(name), "", \
888 flag ? "true" : "false", \
889 VTY_NEWLINE)
890
891enum msc_vty_dump_flags {
892 MSC_VTY_DUMP_F_SUBSCR = (1 << 0),
893 MSC_VTY_DUMP_F_CONNECTION = (1 << 1),
894 MSC_VTY_DUMP_F_TRANSACTION = (1 << 2),
895};
896
897static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans,
898 int offset, uint8_t dump_flags)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100899{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700900 const char *proto_str;
901
902 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
903 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
904 vlr_subscr_name(msc_a_vsub(trans->msc_a)),
905 VTY_NEWLINE);
906 }
907
908 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200909 /* (If msc_a exists, there *must* be a non-null msc_a->c.msub) */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700910 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
911 trans->msc_a ? msub_ran_conn_name(trans->msc_a->c.msub)
912 : "(not established)",
913 VTY_NEWLINE);
914 }
915
916 MSC_VTY_DUMP(vty, offset, "Unique (global) identifier: 0x%08x%s",
917 trans->callref, VTY_NEWLINE);
918 MSC_VTY_DUMP(vty, offset, "GSM 04.07 identifier (%s): %u%s",
919 (trans->transaction_id & 0x08) ? "MO" : "MT",
920 trans->transaction_id,
921 VTY_NEWLINE);
922
923 MSC_VTY_DUMP(vty, offset, "Type: %s%s",
924 trans_type_name(trans->type),
925 VTY_NEWLINE);
926
927 if ((proto_str = get_trans_proto_str(trans))) {
928 MSC_VTY_DUMP(vty, offset, "Protocol specific: %s%s",
929 proto_str, VTY_NEWLINE);
930 }
931}
932
933static void vty_dump_one_conn(struct vty *vty, const struct msub *msub,
934 int offset, uint8_t dump_flags)
935{
936 struct vlr_subscr *vsub = msub_vsub(msub);
937 struct msc_a *msc_a = msub_msc_a(msub);
938 char buf[128];
939
940 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
941 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
942 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
943 vlr_subscr_name(vsub),
944 VTY_NEWLINE);
945 }
946
947 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
948 msub_ran_conn_name(msub),
949 VTY_NEWLINE);
950 MSC_VTY_DUMP(vty, offset, "RAN connection state: %s%s",
951 osmo_fsm_inst_state_name(msc_a->c.fi),
952 VTY_NEWLINE);
953
954 if (vsub) {
955 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
Neels Hofmeyr41c03332020-06-24 15:02:27 +0200956 msc_a->via_cell.lai.lac, msc_a->via_cell.cell_identity,
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700957 VTY_NEWLINE);
958 }
959
960 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
961 osmo_use_count_total(&msc_a->use_count),
962 VTY_NEWLINE);
963 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
964 osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count),
965 VTY_NEWLINE);
966
967 /* Transactions of this connection */
968 if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
969 struct gsm_trans *trans;
970 unsigned int i = 0;
971
972 /* Both subscriber and connection info is already printed */
973 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_CONNECTION;
974 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
975
976 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
977 if (trans->msc_a != msc_a)
978 continue;
979 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
980 i++, VTY_NEWLINE);
981 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
982 }
983 }
984}
985
986static void vty_dump_one_subscr(struct vty *vty, struct vlr_subscr *vsub,
987 int offset, uint8_t dump_flags)
988{
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700989 struct timespec now;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700990 char buf[128];
991
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700992 if (vsub->name[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700993 MSC_VTY_DUMP(vty, offset, "Name: '%s'%s",
994 vsub->name, VTY_NEWLINE);
995 }
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700996 if (vsub->msisdn[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700997 MSC_VTY_DUMP(vty, offset, "MSISDN: %s%s",
998 vsub->msisdn, VTY_NEWLINE);
999 }
1000
1001 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
1002 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
1003 VTY_NEWLINE);
1004 MSC_VTY_DUMP(vty, offset, "RAN type: %s%s",
1005 osmo_rat_type_name(vsub->cs.attached_via_ran),
1006 VTY_NEWLINE);
1007
1008 MSC_VTY_DUMP(vty, offset, "IMSI: %s%s",
1009 vsub->imsi, VTY_NEWLINE);
1010 if (vsub->tmsi != GSM_RESERVED_TMSI) {
1011 MSC_VTY_DUMP(vty, offset, "TMSI: %08X%s",
1012 vsub->tmsi, VTY_NEWLINE);
1013 }
1014 if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
1015 MSC_VTY_DUMP(vty, offset, "New TMSI: %08X%s",
1016 vsub->tmsi_new, VTY_NEWLINE);
1017 }
1018 if (vsub->imei[0] != '\0') {
1019 MSC_VTY_DUMP(vty, offset, "IMEI: %s%s",
1020 vsub->imei, VTY_NEWLINE);
1021 }
1022 if (vsub->imeisv[0] != '\0') {
1023 MSC_VTY_DUMP(vty, offset, "IMEISV: %s%s",
1024 vsub->imeisv, VTY_NEWLINE);
1025 }
1026
1027 MSC_VTY_DUMP(vty, offset, "Flags: %s", VTY_NEWLINE);
1028 MSC_VTY_DUMP_FLAG(vty, offset, "IMSI detached",
1029 vsub->imsi_detached_flag);
1030 MSC_VTY_DUMP_FLAG(vty, offset, "Conf. by radio contact",
1031 vsub->conf_by_radio_contact_ind);
1032 MSC_VTY_DUMP_FLAG(vty, offset, "Subscr. data conf. by HLR",
1033 vsub->sub_dataconf_by_hlr_ind);
1034 MSC_VTY_DUMP_FLAG(vty, offset, "Location conf. in HLR",
1035 vsub->loc_conf_in_hlr_ind);
1036 MSC_VTY_DUMP_FLAG(vty, offset, "Subscriber dormant",
1037 vsub->dormant_ind);
1038 MSC_VTY_DUMP_FLAG(vty, offset, "Received cancel location",
1039 vsub->cancel_loc_rx);
1040 MSC_VTY_DUMP_FLAG(vty, offset, "MS not reachable",
1041 vsub->ms_not_reachable_flag);
1042 MSC_VTY_DUMP_FLAG(vty, offset, "LA allowed",
1043 vsub->la_allowed);
1044
1045 if (vsub->last_tuple) {
1046 struct vlr_auth_tuple *t = vsub->last_tuple;
1047 MSC_VTY_DUMP(vty, offset, "A3A8 last tuple (used %d times): %s",
1048 t->use_count, VTY_NEWLINE);
1049 MSC_VTY_DUMP(vty, offset + 2, "seq # : %d%s",
1050 t->key_seq, VTY_NEWLINE);
1051 MSC_VTY_DUMP(vty, offset + 2, "RAND : %s%s",
1052 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
1053 VTY_NEWLINE);
1054 MSC_VTY_DUMP(vty, offset + 2, "SRES : %s%s",
1055 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
1056 VTY_NEWLINE);
1057 MSC_VTY_DUMP(vty, offset + 2, "Kc : %s%s",
1058 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
1059 VTY_NEWLINE);
1060 }
1061
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +07001062 if (!vlr_timer(vsub->vlr, 3212)) {
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +07001063 MSC_VTY_DUMP(vty, offset, "Expires: never (T3212 is disabled)%s",
1064 VTY_NEWLINE);
1065 } else if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) {
1066 MSC_VTY_DUMP(vty, offset, "Expires: never%s",
1067 VTY_NEWLINE);
1068 } else if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
1069 MSC_VTY_DUMP(vty, offset, "Expires: in %ld min %ld sec%s",
1070 (vsub->expire_lu - now.tv_sec) / 60,
1071 (vsub->expire_lu - now.tv_sec) % 60,
1072 VTY_NEWLINE);
1073 }
1074
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001075 MSC_VTY_DUMP(vty, offset, "Paging: %s paging for %d requests%s",
1076 vsub->cs.is_paging ? "is" : "not",
1077 llist_count(&vsub->cs.requests),
1078 VTY_NEWLINE);
1079
1080 /* SGs related */
1081 MSC_VTY_DUMP(vty, offset, "SGs-state: %s%s",
1082 osmo_fsm_inst_state_name(vsub->sgs_fsm),
1083 VTY_NEWLINE);
1084 MSC_VTY_DUMP(vty, offset, "SGs-MME: %s%s",
Vadim Yanitskiydcf28682019-05-29 22:34:13 +07001085 vsub->sgs.mme_name[0] != '\0' ? vsub->sgs.mme_name : "(none)",
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001086 VTY_NEWLINE);
1087
1088 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
1089 osmo_use_count_total(&vsub->use_count),
1090 VTY_NEWLINE);
1091 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
1092 osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count),
1093 VTY_NEWLINE);
1094
1095 /* Connection(s) and/or transactions of this subscriber */
1096 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
1097 struct msub *msub = msub_for_vsub(vsub);
1098 if (!msub)
1099 return;
1100
1101 /* Subscriber info is already printed */
1102 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
1103
1104 MSC_VTY_DUMP(vty, offset, "Connection: %s", VTY_NEWLINE);
1105 vty_dump_one_conn(vty, msub, offset + 2, dump_flags);
1106 } else if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
1107 struct gsm_trans *trans;
1108 unsigned int i = 0;
1109
1110 /* Subscriber info is already printed */
1111 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
1112 /* Do not print connection info, but mention it */
1113 dump_flags |= MSC_VTY_DUMP_F_CONNECTION;
1114
1115 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1116 if (trans->vsub != vsub)
1117 continue;
1118 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
1119 i++, VTY_NEWLINE);
1120 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
1121 }
1122 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001123}
1124
1125DEFUN(show_msc_transaction, show_msc_transaction_cmd,
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001126 "show transaction",
1127 SHOW_STR "Transactions\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001128{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001129 struct gsm_trans *trans;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001130 uint8_t flags = 0x00;
1131 unsigned int i = 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001132
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001133 flags |= MSC_VTY_DUMP_F_CONNECTION;
1134 flags |= MSC_VTY_DUMP_F_SUBSCR;
1135
1136 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1137 vty_out(vty, " Transaction #%02u: %s", i++, VTY_NEWLINE);
1138 vty_dump_one_trans(vty, trans, 4, flags);
1139 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001140
1141 return CMD_SUCCESS;
1142}
1143
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001144DEFUN(show_msc_conn, show_msc_conn_cmd,
1145 "show connection [trans]",
1146 SHOW_STR "Subscriber Connections\n"
1147 "Show child transactions of each connection\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001148{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001149 uint8_t flags = 0x00;
1150 unsigned int i = 0;
1151 struct msub *msub;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001152
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001153 if (argc > 0)
1154 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1155 flags |= MSC_VTY_DUMP_F_SUBSCR;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001156
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001157 llist_for_each_entry(msub, &msub_list, entry) {
1158 vty_out(vty, " Connection #%02u: %s", i++, VTY_NEWLINE);
1159 vty_dump_one_conn(vty, msub, 4, flags);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001160 }
1161
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001162 return CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001163}
1164
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001165#define SUBSCR_FLAGS "[(conn|trans|conn+trans)]"
1166#define SUBSCR_FLAGS_HELP \
1167 "Show child connections\n" \
1168 "Show child transactions\n" \
1169 "Show child connections and transactions\n"
1170
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001171/* Subscriber */
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001172DEFUN(show_subscr_cache, show_subscr_cache_cmd,
1173 "show subscriber cache " SUBSCR_FLAGS,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001174 SHOW_STR "Show information about subscribers\n"
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001175 "Display contents of subscriber cache\n"
1176 SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001177{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001178 struct vlr_subscr *vsub;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001179 unsigned int count = 0;
1180 uint8_t flags = 0x00;
1181 unsigned int i = 0;
1182
1183 if (argc && strcmp(argv[0], "conn") == 0)
1184 flags |= MSC_VTY_DUMP_F_CONNECTION;
1185 else if (argc && strcmp(argv[0], "trans") == 0)
1186 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1187 else if (argc && strcmp(argv[0], "conn+trans") == 0)
1188 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001189
1190 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
1191 if (++count > 100) {
1192 vty_out(vty, "%% More than %d subscribers in cache,"
1193 " stopping here.%s", count-1, VTY_NEWLINE);
1194 break;
1195 }
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001196 vty_out(vty, " Subscriber #%02u: %s", i++, VTY_NEWLINE);
1197 vty_dump_one_subscr(vty, vsub, 4, flags);
Harald Welte69c54a82018-02-09 20:41:14 +01001198 }
1199
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001200 return CMD_SUCCESS;
1201}
1202
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001203DEFUN(sms_send_pend,
1204 sms_send_pend_cmd,
1205 "sms send pending",
1206 "SMS related commands\n" "SMS Sending related commands\n"
1207 "Send all pending SMS")
1208{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001209 struct gsm_sms *sms;
1210 unsigned long long sms_id = 0;
1211
1212 while (1) {
1213 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1214 if (!sms)
1215 break;
1216
1217 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001218 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001219
1220 sms_id = sms->id + 1;
1221 }
1222
1223 return CMD_SUCCESS;
1224}
1225
1226DEFUN(sms_delete_expired,
1227 sms_delete_expired_cmd,
1228 "sms delete expired",
1229 "SMS related commands\n" "SMS Database related commands\n"
1230 "Delete all expired SMS")
1231{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001232 struct gsm_sms *sms;
1233 unsigned long long sms_id = 0;
1234 long long num_deleted = 0;
1235
1236 while (1) {
1237 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1238 if (!sms)
1239 break;
1240
1241 /* Skip SMS which are currently queued for sending. */
1242 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
1243 continue;
1244
1245 /* Expiration check is performed by the DB layer. */
1246 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
1247 num_deleted++;
1248
1249 sms_id = sms->id + 1;
1250 }
1251
1252 if (num_deleted == 0) {
1253 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
1254 return CMD_WARNING;
1255 }
1256
1257 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
1258 return CMD_SUCCESS;
1259}
1260
1261static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +02001262 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001263 char *str, uint8_t tp_pid)
1264{
1265 struct gsm_network *net = receiver->vlr->user_ctx;
1266 struct gsm_sms *sms;
1267
Harald Welte39b55482018-04-09 19:19:33 +02001268 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Vadim Yanitskiydb4839c2019-12-01 18:52:58 +07001269 if (!sms) {
1270 LOGP(DLSMS, LOGL_ERROR, "Failed to allocate SMS\n");
1271 return CMD_WARNING;
1272 }
1273
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001274 sms->protocol_id = tp_pid;
1275
1276 /* store in database for the queue */
1277 if (db_sms_store(sms) != 0) {
1278 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
1279 sms_free(sms);
1280 return CMD_WARNING;
1281 }
1282 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
1283
1284 sms_free(sms);
1285 sms_queue_trigger(net->sms_queue);
1286 return CMD_SUCCESS;
1287}
1288
1289static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
1290 const char *type,
1291 const char *id)
1292{
1293 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001294 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001295 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001296 return vlr_subscr_find_by_imsi(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001297 else if (!strcmp(type, "tmsi"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001298 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id), VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001299
1300 return NULL;
1301}
1302#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
1303#define SUBSCR_HELP "Operations on a Subscriber\n" \
1304 "Identify subscriber by MSISDN (phone number)\n" \
1305 "Legacy alias for 'msisdn'\n" \
1306 "Identify subscriber by IMSI\n" \
1307 "Identify subscriber by TMSI\n" \
Vadim Yanitskiy3ccd8232019-05-16 01:35:23 +07001308 "Legacy alias for 'imsi'\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001309 "Identifier for the subscriber\n"
1310
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001311DEFUN(show_subscr, show_subscr_cmd,
1312 "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
1313 SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001314{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001315 struct vlr_subscr *vsub;
1316 uint8_t flags = 0x00;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001317
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001318 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001319 if (!vsub) {
1320 vty_out(vty, "%% No subscriber found for %s %s%s",
1321 argv[0], argv[1], VTY_NEWLINE);
1322 return CMD_WARNING;
1323 }
1324
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001325 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
1326 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
1327 * 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 +01001328 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001329
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001330 if (argc > 2 && strcmp(argv[2], "conn") == 0)
1331 flags |= MSC_VTY_DUMP_F_CONNECTION;
1332 else if (argc > 2 && strcmp(argv[2], "trans") == 0)
1333 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1334 else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
1335 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
1336
1337 vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
1338 vty_dump_one_subscr(vty, vsub, 4, flags);
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001339
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001340 return CMD_SUCCESS;
1341}
1342
Vadim Yanitskiyb7ddbf32020-01-20 21:30:09 +07001343DEFUN_DEPRECATED(subscriber_create, subscriber_create_cmd,
1344 "subscriber create imsi ID",
1345 "Operations on a Subscriber\n"
1346 "Create new subscriber\n"
1347 "Identify the subscriber by his IMSI\n"
1348 "Identifier for the subscriber\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001349{
1350 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
1351 VTY_NEWLINE);
1352 return CMD_WARNING;
1353}
1354
1355DEFUN(subscriber_send_pending_sms,
1356 subscriber_send_pending_sms_cmd,
1357 "subscriber " SUBSCR_TYPES " ID sms pending-send",
1358 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
1359{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001360 struct vlr_subscr *vsub;
1361 struct gsm_sms *sms;
1362
1363 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1364 if (!vsub) {
1365 vty_out(vty, "%% No subscriber found for %s %s%s",
1366 argv[0], argv[1], VTY_NEWLINE);
1367 return CMD_WARNING;
1368 }
1369
1370 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
1371 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001372 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001373
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001374 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001375
1376 return CMD_SUCCESS;
1377}
1378
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001379DEFUN(subscriber_sms_delete_all,
1380 subscriber_sms_delete_all_cmd,
1381 "subscriber " SUBSCR_TYPES " ID sms delete-all",
1382 SUBSCR_HELP "SMS Operations\n"
1383 "Delete all SMS to be delivered to this subscriber"
1384 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
1385 " WILL BE LOST.\n")
1386{
1387 struct vlr_subscr *vsub;
1388
1389 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1390 if (!vsub) {
1391 vty_out(vty, "%% No subscriber found for %s %s%s",
1392 argv[0], argv[1], VTY_NEWLINE);
1393 return CMD_WARNING;
1394 }
1395
1396 db_sms_delete_by_msisdn(vsub->msisdn);
1397
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001398 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001399
1400 return CMD_SUCCESS;
1401}
1402
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001403DEFUN(subscriber_send_sms,
1404 subscriber_send_sms_cmd,
1405 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1406 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1407{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001408 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001409 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001410 char *str;
1411 int rc;
1412
1413 if (!vsub) {
1414 vty_out(vty, "%% No subscriber found for %s %s%s",
1415 argv[0], argv[1], VTY_NEWLINE);
1416 rc = CMD_WARNING;
1417 goto err;
1418 }
1419
Harald Welte39b55482018-04-09 19:19:33 +02001420 if (!strcmp(argv[2], "msisdn"))
1421 sender_msisdn = argv[3];
1422 else {
1423 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1424 if (!sender) {
1425 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1426 rc = CMD_WARNING;
1427 goto err;
1428 }
1429 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001430 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001431 }
1432
1433 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001434 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001435 talloc_free(str);
1436
1437err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001438 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001439 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001440
1441 return rc;
1442}
1443
1444DEFUN(subscriber_silent_sms,
1445 subscriber_silent_sms_cmd,
1446
1447 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1448 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1449{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001450 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001451 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001452 char *str;
1453 int rc;
1454
1455 if (!vsub) {
1456 vty_out(vty, "%% No subscriber found for %s %s%s",
1457 argv[0], argv[1], VTY_NEWLINE);
1458 rc = CMD_WARNING;
1459 goto err;
1460 }
1461
Harald Welte39b55482018-04-09 19:19:33 +02001462 if (!strcmp(argv[2], "msisdn")) {
1463 sender_msisdn = argv[3];
1464 } else {
1465 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1466 if (!sender) {
1467 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1468 rc = CMD_WARNING;
1469 goto err;
1470 }
1471 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001472 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001473 }
1474
1475 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001476 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001477 talloc_free(str);
1478
1479err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001480 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001481 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001482
1483 return rc;
1484}
1485
Sylvain Munaut93558302019-02-14 20:13:08 +01001486#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001487#define CHAN_TYPE_HELP \
1488 "Any channel\n" \
1489 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001490 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001491 "Any TCH channel\n" \
1492 "SDCCH channel\n"
1493
Sylvain Munaut93558302019-02-14 20:13:08 +01001494#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1495#define CHAN_MODE_HELP \
1496 "Signalling only\n" \
1497 "Speech with HR codec\n" \
1498 "Speech with FR codec\n" \
1499 "Speech with EFR codec\n" \
1500 "Speech with AMR codec\n"
1501
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001502DEFUN(subscriber_silent_call_start,
1503 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001504 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001505 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001506 CHAN_TYPE_HELP CHAN_MODE_HELP
1507 "Target IP for RTP traffic (default 127.0.0.1)\n"
1508 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001509{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001510 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001511 struct gsm0808_channel_type ct;
1512 const char *ip;
1513 uint16_t port;
1514 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001515
1516 if (!vsub) {
1517 vty_out(vty, "%% No subscriber found for %s %s%s",
1518 argv[0], argv[1], VTY_NEWLINE);
1519 return CMD_WARNING;
1520 }
1521
Sylvain Munaut93558302019-02-14 20:13:08 +01001522 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001523
Sylvain Munaut93558302019-02-14 20:13:08 +01001524 if (!strcmp(argv[3], "signalling")) {
1525 ct.ch_indctr = GSM0808_CHAN_SIGN;
1526 ct.perm_spch[0] = 0; /* Spare but required */
1527 ct.perm_spch_len = 1;
1528 } else if (!strcmp(argv[3], "speech-hr")) {
1529 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1530 ct.perm_spch[0] = GSM0808_PERM_HR1;
1531 ct.perm_spch_len = 1;
1532 } else if (!strcmp(argv[3], "speech-fr")) {
1533 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1534 ct.perm_spch[0] = GSM0808_PERM_FR1;
1535 ct.perm_spch_len = 1;
1536 } else if (!strcmp(argv[3], "speech-efr")) {
1537 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1538 ct.perm_spch[0] = GSM0808_PERM_FR2;
1539 ct.perm_spch_len = 1;
1540 } else if (!strcmp(argv[3], "speech-amr")) {
1541 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1542 ct.perm_spch[0] = GSM0808_PERM_FR3;
1543 ct.perm_spch[1] = GSM0808_PERM_HR3;
1544 ct.perm_spch_len = 2;
1545 }
1546
1547 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1548
1549 if (!strcmp(argv[2], "tch/f"))
1550 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1551 else if (!strcmp(argv[2], "tch/h"))
1552 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1553 else if (!strcmp(argv[2], "tch/any"))
1554 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1555 else if (!strcmp(argv[2], "sdcch")) {
1556 if (speech) {
1557 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1558 return CMD_WARNING;
1559 }
1560 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1561 } else
1562 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1563
1564 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1565 port = argc >= 6 ? atoi(argv[5]) : 4000;
1566
1567 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001568 switch (rc) {
1569 case -ENODEV:
1570 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1571 break;
1572 default:
1573 if (rc)
1574 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1575 else
1576 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1577 break;
1578 }
1579
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001580 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001581 return rc ? CMD_WARNING : CMD_SUCCESS;
1582}
1583
1584DEFUN(subscriber_silent_call_stop,
1585 subscriber_silent_call_stop_cmd,
1586 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1587 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1588 CHAN_TYPE_HELP)
1589{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001590 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1591 int rc;
1592
1593 if (!vsub) {
1594 vty_out(vty, "%% No subscriber found for %s %s%s",
1595 argv[0], argv[1], VTY_NEWLINE);
1596 return CMD_WARNING;
1597 }
1598
1599 rc = gsm_silent_call_stop(vsub);
1600 switch (rc) {
1601 case -ENODEV:
1602 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1603 break;
1604 case -ENOENT:
1605 vty_out(vty, "%% Subscriber has no silent call active%s",
1606 VTY_NEWLINE);
1607 break;
1608 default:
1609 if (rc)
1610 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1611 else
1612 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1613 break;
1614 }
1615
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001616 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001617 return rc ? CMD_WARNING : CMD_SUCCESS;
1618}
1619
1620DEFUN(subscriber_ussd_notify,
1621 subscriber_ussd_notify_cmd,
1622 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1623 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1624 "Alerting Level 0\n"
1625 "Alerting Level 1\n"
1626 "Alerting Level 2\n"
1627 "Text of USSD message to send\n")
1628{
1629 char *text;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001630 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001631 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1632 int level;
1633
1634 if (!vsub) {
1635 vty_out(vty, "%% No subscriber found for %s %s%s",
1636 argv[0], argv[1], VTY_NEWLINE);
1637 return CMD_WARNING;
1638 }
1639
1640 level = atoi(argv[2]);
1641 text = argv_concat(argv, argc, 3);
1642 if (!text) {
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001643 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001644 return CMD_WARNING;
1645 }
1646
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001647 msc_a = msc_a_for_vsub(vsub, true);
1648 if (!msc_a || msc_a->c.remote_to) {
1649 vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001650 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001651 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001652 talloc_free(text);
1653 return CMD_WARNING;
1654 }
1655
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001656 msc_send_ussd_notify(msc_a, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001657 /* FIXME: since we don't allocate a transaction here,
1658 * we use dummy GSM 04.07 transaction ID. */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001659 msc_send_ussd_release_complete(msc_a, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001660
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001661 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001662 talloc_free(text);
1663 return CMD_SUCCESS;
1664}
1665
1666DEFUN(subscriber_paging,
1667 subscriber_paging_cmd,
1668 "subscriber " SUBSCR_TYPES " ID paging",
1669 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1670{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001671 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001672 struct paging_request *req;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001673
1674 if (!vsub) {
1675 vty_out(vty, "%% No subscriber found for %s %s%s",
1676 argv[0], argv[1], VTY_NEWLINE);
1677 return CMD_WARNING;
1678 }
1679
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001680 req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL,
1681 NULL, NULL, "manual Paging from VTY");
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001682 if (req)
1683 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1684 else
1685 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1686
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001687 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001688 return req ? CMD_SUCCESS : CMD_WARNING;
1689}
1690
1691static int loop_by_char(uint8_t ch)
1692{
1693 switch (ch) {
1694 case 'a':
1695 return GSM414_LOOP_A;
1696 case 'b':
1697 return GSM414_LOOP_B;
1698 case 'c':
1699 return GSM414_LOOP_C;
1700 case 'd':
1701 return GSM414_LOOP_D;
1702 case 'e':
1703 return GSM414_LOOP_E;
1704 case 'f':
1705 return GSM414_LOOP_F;
1706 case 'i':
1707 return GSM414_LOOP_I;
1708 }
1709 return -1;
1710}
1711
1712DEFUN(subscriber_mstest_close,
1713 subscriber_mstest_close_cmd,
1714 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1715 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1716 "Close a TCH Loop inside the MS\n"
1717 "Loop Type A\n"
1718 "Loop Type B\n"
1719 "Loop Type C\n"
1720 "Loop Type D\n"
1721 "Loop Type E\n"
1722 "Loop Type F\n"
1723 "Loop Type I\n")
1724{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001725 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001726 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1727 const char *loop_str;
1728 int loop_mode;
1729
1730 if (!vsub) {
1731 vty_out(vty, "%% No subscriber found for %s %s%s",
1732 argv[0], argv[1], VTY_NEWLINE);
1733 return CMD_WARNING;
1734 }
1735
1736 loop_str = argv[2];
1737 loop_mode = loop_by_char(loop_str[0]);
1738
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001739 msc_a = msc_a_for_vsub(vsub, true);
1740 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001741 vty_out(vty, "%% An active connection is required for %s %s%s",
1742 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001743 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001744 return CMD_WARNING;
1745 }
1746
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001747 gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001748
Vadim Yanitskiy817ad902020-07-29 05:47:01 +07001749 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001750 return CMD_SUCCESS;
1751}
1752
1753DEFUN(subscriber_mstest_open,
1754 subscriber_mstest_open_cmd,
1755 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1756 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1757 "Open a TCH Loop inside the MS\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
1762 if (!vsub) {
1763 vty_out(vty, "%% No subscriber found for %s %s%s",
1764 argv[0], argv[1], VTY_NEWLINE);
1765 return CMD_WARNING;
1766 }
1767
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001768 msc_a = msc_a_for_vsub(vsub, true);
1769 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001770 vty_out(vty, "%% An active connection is required for %s %s%s",
1771 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001772 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001773 return CMD_WARNING;
1774 }
1775
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001776 gsm0414_tx_open_loop_cmd(msc_a);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001777
Vadim Yanitskiy817ad902020-07-29 05:47:01 +07001778 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001779 return CMD_SUCCESS;
1780}
1781
1782DEFUN(ena_subscr_expire,
1783 ena_subscr_expire_cmd,
1784 "subscriber " SUBSCR_TYPES " ID expire",
1785 SUBSCR_HELP "Expire the subscriber Now\n")
1786{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001787 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1788 argv[1]);
1789
1790 if (!vsub) {
1791 vty_out(vty, "%% No subscriber found for %s %s%s",
1792 argv[0], argv[1], VTY_NEWLINE);
1793 return CMD_WARNING;
1794 }
1795
1796 if (vlr_subscr_expire(vsub))
1797 vty_out(vty, "%% VLR released subscriber %s%s",
1798 vlr_subscr_name(vsub), VTY_NEWLINE);
1799
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001800 if (osmo_use_count_total(&vsub->use_count) > 1)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001801 vty_out(vty, "%% Subscriber %s is still in use,"
1802 " should be released soon%s",
1803 vlr_subscr_name(vsub), VTY_NEWLINE);
1804
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001805 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001806 return CMD_SUCCESS;
1807}
1808
1809static int scall_cbfn(unsigned int subsys, unsigned int signal,
1810 void *handler_data, void *signal_data)
1811{
1812 struct scall_signal_data *sigdata = signal_data;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001813 struct vty *vty = sigdata->vty;
1814
1815 if (!vty_is_active(vty))
1816 return 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001817
1818 switch (signal) {
1819 case S_SCALL_SUCCESS:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001820 vty_out(vty, "%% Silent call success%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001821 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001822 case S_SCALL_FAILED:
1823 vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE);
1824 break;
1825 case S_SCALL_DETACHED:
1826 vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001827 break;
1828 }
1829 return 0;
1830}
1831
1832DEFUN(show_stats,
1833 show_stats_cmd,
1834 "show statistics",
1835 SHOW_STR "Display network statistics\n")
1836{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001837 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001838 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_ATTACH)->current,
1839 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_NORMAL)->current,
1840 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_PERIODIC)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001841 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001842 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001843 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_TYPE_DETACH)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001844 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001845 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001846 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_COMPLETED)->current,
1847 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_LOC_UPDATE_FAILED)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001848 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001849 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001850 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_SUBMITTED)->current,
1851 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_NO_RECEIVER)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001852 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001853 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001854 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_DELIVERED)->current,
1855 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_RP_ERR_MEM)->current,
1856 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_SMS_RP_ERR_OTHER)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001857 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001858 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001859 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MO_SETUP)->current,
1860 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MO_CONNECT_ACK)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001861 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001862 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001863 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MT_SETUP)->current,
1864 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_CALL_MT_CONNECT)->current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001865 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001866 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001867 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_REQUESTS)->current,
1868 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_ESTABLISHED)->current,
1869 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_REQUESTS)->current
1870 - rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MO_ESTABLISHED)->current,
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001871 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001872 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Pau Espin Pedrol2e21a682021-06-04 16:45:44 +02001873 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_REQUESTS)->current,
1874 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_ESTABLISHED)->current,
1875 rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_REQUESTS)->current
1876 - rate_ctr_group_get_ctr(gsmnet->msc_ctrs, MSC_CTR_NC_SS_MT_ESTABLISHED)->current,
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001877 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001878 return CMD_SUCCESS;
1879}
1880
1881DEFUN(show_smsqueue,
1882 show_smsqueue_cmd,
1883 "show sms-queue",
1884 SHOW_STR "Display SMSqueue statistics\n")
1885{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001886 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001887 return CMD_SUCCESS;
1888}
1889
1890DEFUN(smsqueue_trigger,
1891 smsqueue_trigger_cmd,
1892 "sms-queue trigger",
1893 "SMS Queue\n" "Trigger sending messages\n")
1894{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001895 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001896 return CMD_SUCCESS;
1897}
1898
1899DEFUN(smsqueue_max,
1900 smsqueue_max_cmd,
1901 "sms-queue max-pending <1-500>",
1902 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1903{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001904 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001905 return CMD_SUCCESS;
1906}
1907
1908DEFUN(smsqueue_clear,
1909 smsqueue_clear_cmd,
1910 "sms-queue clear",
1911 "SMS Queue\n" "Clear the queue of pending SMS\n")
1912{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001913 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001914 return CMD_SUCCESS;
1915}
1916
1917DEFUN(smsqueue_fail,
1918 smsqueue_fail_cmd,
1919 "sms-queue max-failure <1-500>",
1920 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1921{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001922 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001923 return CMD_SUCCESS;
1924}
1925
1926
1927DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1928 "mncc-int", "Configure internal MNCC handler")
1929{
1930 vty->node = MNCC_INT_NODE;
1931
1932 return CMD_SUCCESS;
1933}
1934
1935static struct cmd_node mncc_int_node = {
1936 MNCC_INT_NODE,
1937 "%s(config-mncc-int)# ",
1938 1,
1939};
1940
1941static const struct value_string tchf_codec_names[] = {
1942 { GSM48_CMODE_SPEECH_V1, "fr" },
1943 { GSM48_CMODE_SPEECH_EFR, "efr" },
1944 { GSM48_CMODE_SPEECH_AMR, "amr" },
1945 { 0, NULL }
1946};
1947
1948static const struct value_string tchh_codec_names[] = {
1949 { GSM48_CMODE_SPEECH_V1, "hr" },
1950 { GSM48_CMODE_SPEECH_AMR, "amr" },
1951 { 0, NULL }
1952};
1953
1954static int config_write_mncc_int(struct vty *vty)
1955{
1956 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1957 vty_out(vty, " default-codec tch-f %s%s",
1958 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1959 VTY_NEWLINE);
1960 vty_out(vty, " default-codec tch-h %s%s",
1961 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1962 VTY_NEWLINE);
1963
1964 return CMD_SUCCESS;
1965}
1966
1967DEFUN(mnccint_def_codec_f,
1968 mnccint_def_codec_f_cmd,
1969 "default-codec tch-f (fr|efr|amr)",
1970 "Set default codec\n" "Codec for TCH/F\n"
1971 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1972{
1973 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1974
1975 return CMD_SUCCESS;
1976}
1977
1978DEFUN(mnccint_def_codec_h,
1979 mnccint_def_codec_h_cmd,
1980 "default-codec tch-h (hr|amr)",
1981 "Set default codec\n" "Codec for TCH/H\n"
1982 "Half-Rate\n" "Adaptive Multi-Rate\n")
1983{
1984 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1985
1986 return CMD_SUCCESS;
1987}
1988
1989
1990DEFUN(logging_fltr_imsi,
1991 logging_fltr_imsi_cmd,
1992 "logging filter imsi IMSI",
1993 LOGGING_STR FILTER_STR
1994 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1995{
1996 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001997 struct log_target *tgt = osmo_log_vty2tgt(vty);
1998 const char *imsi = argv[0];
1999
2000 if (!tgt)
2001 return CMD_WARNING;
2002
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01002003 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002004
2005 if (!vlr_subscr) {
2006 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
2007 argv[0], VTY_NEWLINE);
2008 return CMD_WARNING;
2009 }
2010
2011 log_set_filter_vlr_subscr(tgt, vlr_subscr);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01002012 vlr_subscr_put(vlr_subscr, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002013 return CMD_SUCCESS;
2014}
2015
2016static struct cmd_node hlr_node = {
2017 HLR_NODE,
2018 "%s(config-hlr)# ",
2019 1,
2020};
2021
2022DEFUN(cfg_hlr, cfg_hlr_cmd,
2023 "hlr", "Configure connection to the HLR")
2024{
2025 vty->node = HLR_NODE;
2026 return CMD_SUCCESS;
2027}
2028
2029DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
2030 "Remote GSUP address of the HLR\n"
2031 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
2032{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002033 talloc_free((void*)gsmnet->gsup_server_addr_str);
2034 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
2035 return CMD_SUCCESS;
2036}
2037
2038DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
2039 "Remote GSUP port of the HLR\n"
2040 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
2041{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002042 gsmnet->gsup_server_port = atoi(argv[0]);
2043 return CMD_SUCCESS;
2044}
2045
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002046DEFUN(cfg_hlr_ipa_name,
2047 cfg_hlr_ipa_name_cmd,
2048 "ipa-name NAME",
2049 "Set the IPA name of this MSC\n"
2050 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
2051 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
2052 "The default is 'MSC-00-00-00-00-00-00'.\n")
2053{
2054 if (vty->type != VTY_FILE) {
2055 vty_out(vty, "The IPA name cannot be changed at run-time; "
Martin Hauke3f07dac2019-11-14 17:49:08 +01002056 "It can only be set in the configuration file.%s", VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002057 return CMD_WARNING;
2058 }
2059
2060 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
2061 return CMD_SUCCESS;
2062}
2063
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002064static int config_write_hlr(struct vty *vty)
2065{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002066 vty_out(vty, "hlr%s", VTY_NEWLINE);
2067 vty_out(vty, " remote-ip %s%s",
2068 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
2069 vty_out(vty, " remote-port %u%s",
2070 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002071 if (gsmnet->msc_ipa_name)
2072 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002073 return CMD_SUCCESS;
2074}
2075
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002076void msc_vty_init(struct gsm_network *msc_network)
2077{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01002078 OSMO_ASSERT(gsmnet == NULL);
2079 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002080
2081 osmo_stats_vty_add_cmds();
2082
2083 install_element(CONFIG_NODE, &cfg_net_cmd);
2084 install_node(&net_node, config_write_net);
2085 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
2086 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
2087 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
2088 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
2089 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +02002090 install_element(GSMNET_NODE, &cfg_net_encryption_uea_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002091 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
2092 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
2093 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
2094 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
2095 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
2096 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
2097 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
2098 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Keith Whyte991bb422019-08-08 15:43:40 +02002099 install_element(GSMNET_NODE, &cfg_net_call_wait_cmd);
2100 install_element(GSMNET_NODE, &cfg_net_no_call_wait_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002101
2102 install_element(CONFIG_NODE, &cfg_msc_cmd);
2103 install_node(&msc_node, config_write_msc);
Keith Whyte1587ffb2020-08-28 13:36:58 +02002104 install_element(MSC_NODE, &cfg_sms_database_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002105 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Keith Whytea1a70be2021-05-16 02:59:52 +02002106 install_element(MSC_NODE, &cfg_msc_lcls_disable_cmd);
2107 install_element(MSC_NODE, &cfg_msc_no_lcls_disable_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01002108 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
2109 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02002110 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01002111 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07002112 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002113 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01002114 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
2115 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01002116 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02002117 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
2118 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01002119 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01002120 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07002121 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
2122 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +02002123 install_element(MSC_NODE, &cfg_msc_osmux_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002124 install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd);
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +02002125 install_element(MSC_NODE, &cfg_msc_nri_bitlen_cmd);
2126 install_element(MSC_NODE, &cfg_msc_nri_add_cmd);
2127 install_element(MSC_NODE, &cfg_msc_nri_del_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002128
2129 neighbor_ident_vty_init(msc_network);
Philipp Maierfbf66102017-04-09 12:32:51 +02002130
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +07002131 /* Timer configuration commands (generic osmo_tdef API) */
2132 osmo_tdef_vty_groups_init(MSC_NODE, msc_tdef_group);
2133
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02002134 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002135#ifdef BUILD_IU
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002136 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 +02002137#endif
Harald Welte0df904d2018-12-03 11:00:04 +01002138 sgs_vty_init();
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002139
Stefan Sperling617ac802018-02-22 17:58:20 +01002140 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002141
2142 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
2143
2144 install_element_ve(&show_subscr_cmd);
2145 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01002146 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002147 install_element_ve(&show_msc_conn_cmd);
2148 install_element_ve(&show_msc_transaction_cmd);
Neels Hofmeyr9aac5c22020-05-27 00:04:26 +02002149 install_element_ve(&show_nri_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002150
2151 install_element_ve(&sms_send_pend_cmd);
2152 install_element_ve(&sms_delete_expired_cmd);
2153
2154 install_element_ve(&subscriber_create_cmd);
2155 install_element_ve(&subscriber_send_sms_cmd);
2156 install_element_ve(&subscriber_silent_sms_cmd);
2157 install_element_ve(&subscriber_silent_call_start_cmd);
2158 install_element_ve(&subscriber_silent_call_stop_cmd);
2159 install_element_ve(&subscriber_ussd_notify_cmd);
2160 install_element_ve(&subscriber_mstest_close_cmd);
2161 install_element_ve(&subscriber_mstest_open_cmd);
2162 install_element_ve(&subscriber_paging_cmd);
2163 install_element_ve(&show_stats_cmd);
2164 install_element_ve(&show_smsqueue_cmd);
2165 install_element_ve(&logging_fltr_imsi_cmd);
2166
2167 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
2168 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
2169 install_element(ENABLE_NODE, &smsqueue_max_cmd);
2170 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
2171 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
2172 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01002173 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002174
2175 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
2176 install_node(&mncc_int_node, config_write_mncc_int);
2177 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
2178 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
2179
2180 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
2181
2182 install_element(CONFIG_NODE, &cfg_hlr_cmd);
2183 install_node(&hlr_node, config_write_hlr);
2184 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
2185 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002186 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002187}