blob: 53d44dc7db753a5b2634e3f9cbcf62a6794ef9b3 [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 Hofmeyr84da6b12016-05-20 21:59:55 +020036
Maxc51609a2018-11-09 17:13:00 +010037#include <osmocom/sigtran/sccp_helpers.h>
38
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +070039#include <osmocom/vty/tdef_vty.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020040#include <osmocom/vty/command.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010041#include <osmocom/vty/logging.h>
Stefan Sperling617ac802018-02-22 17:58:20 +010042#include <osmocom/vty/misc.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010043#include <osmocom/vty/stats.h>
44
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020045#ifdef BUILD_IU
46#include <osmocom/ranap/iu_client.h>
47#endif
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020048
Neels Hofmeyr90843962017-09-04 15:04:35 +020049#include <osmocom/msc/vty.h>
50#include <osmocom/msc/gsm_data.h>
51#include <osmocom/msc/gsm_subscriber.h>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010052#include <osmocom/msc/msub.h>
53#include <osmocom/msc/msc_a.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020054#include <osmocom/msc/vlr.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010055#include <osmocom/msc/transaction.h>
56#include <osmocom/msc/db.h>
57#include <osmocom/msc/sms_queue.h>
58#include <osmocom/msc/silent_call.h>
59#include <osmocom/msc/gsm_04_80.h>
60#include <osmocom/msc/gsm_04_14.h>
61#include <osmocom/msc/signal.h>
62#include <osmocom/msc/mncc_int.h>
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +020063#include <osmocom/msc/osmux.h>
Vadim Yanitskiy1b891302018-08-04 01:33:08 +070064#include <osmocom/msc/rrlp.h>
Harald Welte0df904d2018-12-03 11:00:04 +010065#include <osmocom/msc/vlr_sgs.h>
66#include <osmocom/msc/sgs_vty.h>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010067#include <osmocom/msc/sccp_ran.h>
68#include <osmocom/msc/ran_peer.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010069
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010070static struct gsm_network *gsmnet = NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010071
72struct cmd_node net_node = {
73 GSMNET_NODE,
74 "%s(config-net)# ",
75 1,
76};
77
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +010078#define VSUB_USE_VTY "VTY"
79
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010080#define NETWORK_STR "Configure the GSM network\n"
81#define CODE_CMD_STR "Code commands\n"
82#define NAME_CMD_STR "Name Commands\n"
83#define NAME_STR "Name to use\n"
84
85DEFUN(cfg_net,
86 cfg_net_cmd,
87 "network", NETWORK_STR)
88{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010089 vty->index = gsmnet;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010090 vty->node = GSMNET_NODE;
91
92 return CMD_SUCCESS;
93}
94
95DEFUN(cfg_net_ncc,
96 cfg_net_ncc_cmd,
97 "network country code <1-999>",
98 "Set the GSM network country code\n"
99 "Country commands\n"
100 CODE_CMD_STR
101 "Network Country Code to use\n")
102{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100103 gsmnet->plmn.mcc = atoi(argv[0]);
104
105 return CMD_SUCCESS;
106}
107
108DEFUN(cfg_net_mnc,
109 cfg_net_mnc_cmd,
110 "mobile network code <0-999>",
111 "Set the GSM mobile network code\n"
112 "Network Commands\n"
113 CODE_CMD_STR
114 "Mobile Network Code to use\n")
115{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100116 uint16_t mnc;
117 bool mnc_3_digits;
118
119 if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
120 vty_out(vty, "%% Error decoding MNC: %s%s", argv[0], VTY_NEWLINE);
121 return CMD_WARNING;
122 }
123
124 gsmnet->plmn.mnc = mnc;
125 gsmnet->plmn.mnc_3_digits = mnc_3_digits;
126
127 return CMD_SUCCESS;
128}
129
130DEFUN(cfg_net_name_short,
131 cfg_net_name_short_cmd,
132 "short name NAME",
133 "Set the short GSM network name\n" NAME_CMD_STR NAME_STR)
134{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100135 osmo_talloc_replace_string(gsmnet, &gsmnet->name_short, argv[0]);
136 return CMD_SUCCESS;
137}
138
139DEFUN(cfg_net_name_long,
140 cfg_net_name_long_cmd,
141 "long name NAME",
142 "Set the long GSM network name\n" NAME_CMD_STR NAME_STR)
143{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100144 osmo_talloc_replace_string(gsmnet, &gsmnet->name_long, argv[0]);
145 return CMD_SUCCESS;
146}
147
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200148#define ENCRYPTION_STR "Encryption options\n"
149
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100150DEFUN(cfg_net_encryption,
151 cfg_net_encryption_cmd,
152 "encryption a5 <0-3> [<0-3>] [<0-3>] [<0-3>]",
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200153 ENCRYPTION_STR
154 "GSM A5 Air Interface Encryption.\n"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100155 "A5/n Algorithm Number\n"
156 "A5/n Algorithm Number\n"
157 "A5/n Algorithm Number\n"
158 "A5/n Algorithm Number\n")
159{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100160 unsigned int i;
161
162 gsmnet->a5_encryption_mask = 0;
163 for (i = 0; i < argc; i++)
164 gsmnet->a5_encryption_mask |= (1 << atoi(argv[i]));
165
166 return CMD_SUCCESS;
167}
168
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200169/* So far just a boolean switch, a future patch might add individual config for UEA1 and UEA2, see OS#4143 */
170DEFUN(cfg_net_encryption_uea,
171 cfg_net_encryption_uea_cmd,
172 "encryption uea <0-2> [<0-2>] [<0-2>]",
173 ENCRYPTION_STR
174 "UTRAN (3G) encryption algorithms to allow: 0 = UEA0 (no encryption), 1 = UEA1, 2 = UEA2."
175 " NOTE: the current implementation does not allow free choice of combining encryption algorithms yet."
176 " The only valid settings are either 'encryption uea 0' or 'encryption uea 1 2'.\n"
177 "UEAn Algorithm Number\n"
178 "UEAn Algorithm Number\n"
179 "UEAn Algorithm Number\n"
180 )
181{
182 unsigned int i;
183 uint8_t mask = 0;
184
185 for (i = 0; i < argc; i++)
186 mask |= (1 << atoi(argv[i]));
187
188 if (mask == (1 << 0)) {
189 /* UEA0. Disable encryption. */
190 gsmnet->uea_encryption = false;
191 } else if (mask == ((1 << 1) | (1 << 2))) {
192 /* UEA1 and UEA2. Enable encryption. */
193 gsmnet->uea_encryption = true;
194 } else {
195 vty_out(vty,
196 "%% Error: the current implementation does not allow free choice of combining%s"
197 "%% encryption algorithms yet. The only valid settings are either%s"
198 "%% encryption uea 0%s"
199 "%% or%s"
200 "%% encryption uea 1 2%s",
201 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
202 return CMD_WARNING;
203 }
204
205 return CMD_SUCCESS;
206}
207
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100208DEFUN(cfg_net_authentication,
209 cfg_net_authentication_cmd,
210 "authentication (optional|required)",
211 "Whether to enforce MS authentication in 2G\n"
212 "Allow MS to attach via 2G BSC without authentication\n"
213 "Always do authentication\n")
214{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100215 gsmnet->authentication_required = (argv[0][0] == 'r') ? true : false;
216
217 return CMD_SUCCESS;
218}
219
220DEFUN(cfg_net_rrlp_mode, cfg_net_rrlp_mode_cmd,
221 "rrlp mode (none|ms-based|ms-preferred|ass-preferred)",
222 "Radio Resource Location Protocol\n"
223 "Set the Radio Resource Location Protocol Mode\n"
224 "Don't send RRLP request\n"
225 "Request MS-based location\n"
226 "Request any location, prefer MS-based\n"
227 "Request any location, prefer MS-assisted\n")
228{
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700229 gsmnet->rrlp.mode = msc_rrlp_mode_parse(argv[0]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100230
231 return CMD_SUCCESS;
232}
233
234DEFUN(cfg_net_mm_info, cfg_net_mm_info_cmd,
235 "mm info (0|1)",
236 "Mobility Management\n"
237 "Send MM INFO after LOC UPD ACCEPT\n"
238 "Disable\n" "Enable\n")
239{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100240 gsmnet->send_mm_info = atoi(argv[0]);
241
242 return CMD_SUCCESS;
243}
244
245DEFUN(cfg_net_timezone,
246 cfg_net_timezone_cmd,
247 "timezone <-19-19> (0|15|30|45)",
248 "Set the Timezone Offset of the network\n"
249 "Timezone offset (hours)\n"
250 "Timezone offset (00 minutes)\n"
251 "Timezone offset (15 minutes)\n"
252 "Timezone offset (30 minutes)\n"
253 "Timezone offset (45 minutes)\n"
254 )
255{
256 struct gsm_network *net = vty->index;
257 int tzhr = atoi(argv[0]);
258 int tzmn = atoi(argv[1]);
259
260 net->tz.hr = tzhr;
261 net->tz.mn = tzmn;
262 net->tz.dst = 0;
263 net->tz.override = 1;
264
265 return CMD_SUCCESS;
266}
267
268DEFUN(cfg_net_timezone_dst,
269 cfg_net_timezone_dst_cmd,
270 "timezone <-19-19> (0|15|30|45) <0-2>",
271 "Set the Timezone Offset of the network\n"
272 "Timezone offset (hours)\n"
273 "Timezone offset (00 minutes)\n"
274 "Timezone offset (15 minutes)\n"
275 "Timezone offset (30 minutes)\n"
276 "Timezone offset (45 minutes)\n"
277 "DST offset (hours)\n"
278 )
279{
280 struct gsm_network *net = vty->index;
281 int tzhr = atoi(argv[0]);
282 int tzmn = atoi(argv[1]);
283 int tzdst = atoi(argv[2]);
284
285 net->tz.hr = tzhr;
286 net->tz.mn = tzmn;
287 net->tz.dst = tzdst;
288 net->tz.override = 1;
289
290 return CMD_SUCCESS;
291}
292
293DEFUN(cfg_net_no_timezone,
294 cfg_net_no_timezone_cmd,
295 "no timezone",
296 NO_STR
297 "Disable network timezone override, use system tz\n")
298{
299 struct gsm_network *net = vty->index;
300
301 net->tz.override = 0;
302
303 return CMD_SUCCESS;
304}
305
306DEFUN(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
307 "periodic location update <6-1530>",
308 "Periodic Location Updating Interval\n"
309 "Periodic Location Updating Interval\n"
310 "Periodic Location Updating Interval\n"
311 "Periodic Location Updating Interval in Minutes\n")
312{
313 struct gsm_network *net = vty->index;
314
315 net->t3212 = atoi(argv[0]) / 6;
316
317 return CMD_SUCCESS;
318}
319
320DEFUN(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
321 "no periodic location update",
322 NO_STR
323 "Periodic Location Updating Interval\n"
324 "Periodic Location Updating Interval\n"
325 "Periodic Location Updating Interval\n")
326{
327 struct gsm_network *net = vty->index;
328
329 net->t3212 = 0;
330
331 return CMD_SUCCESS;
332}
333
Keith Whyte991bb422019-08-08 15:43:40 +0200334DEFUN(cfg_net_call_wait, cfg_net_call_wait_cmd,
335 "call-waiting",
336 "Enable Call Waiting on the Network\n")
337{
338 struct gsm_network *net = vty->index;
339
340 net->call_waiting = true;
341
342 return CMD_SUCCESS;
343}
344
345DEFUN(cfg_net_no_call_wait, cfg_net_no_call_wait_cmd,
346 "no call-waiting",
347 NO_STR
348 "Disable Call Waiting on the Network\n")
349{
350 struct gsm_network *net = vty->index;
351
352 net->call_waiting = false;
353
354 return CMD_SUCCESS;
355}
356
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100357static int config_write_net(struct vty *vty)
358{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100359 int i;
360
361 vty_out(vty, "network%s", VTY_NEWLINE);
362 vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
363 vty_out(vty, " mobile network code %s%s",
364 osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
365 vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
366 vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
367 vty_out(vty, " encryption a5");
368 for (i = 0; i < 8; i++) {
369 if (gsmnet->a5_encryption_mask & (1 << i))
370 vty_out(vty, " %u", i);
371 }
372 vty_out(vty, "%s", VTY_NEWLINE);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200373
374 if (!gsmnet->uea_encryption)
375 vty_out(vty, " encryption uea 0%s", VTY_NEWLINE);
376 else
377 vty_out(vty, " encryption uea 1 2%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100378 vty_out(vty, " authentication %s%s",
379 gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE);
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700380 vty_out(vty, " rrlp mode %s%s", msc_rrlp_mode_name(gsmnet->rrlp.mode),
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100381 VTY_NEWLINE);
382 vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
383 if (gsmnet->tz.override != 0) {
384 if (gsmnet->tz.dst)
385 vty_out(vty, " timezone %d %d %d%s",
386 gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
387 VTY_NEWLINE);
388 else
389 vty_out(vty, " timezone %d %d%s",
390 gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
391 }
392 if (gsmnet->t3212 == 0)
393 vty_out(vty, " no periodic location update%s", VTY_NEWLINE);
394 else
395 vty_out(vty, " periodic location update %u%s",
396 gsmnet->t3212 * 6, VTY_NEWLINE);
397
398 if (gsmnet->emergency.route_to_msisdn) {
399 vty_out(vty, " emergency-call route-to-msisdn %s%s",
400 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
401 }
402
Keith Whyte991bb422019-08-08 15:43:40 +0200403 if (!gsmnet->call_waiting)
404 vty_out(vty, " no call-waiting%s", VTY_NEWLINE);
405
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100406 return CMD_SUCCESS;
407}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200408
409static struct cmd_node msc_node = {
410 MSC_NODE,
411 "%s(config-msc)# ",
412 1,
413};
414
415DEFUN(cfg_msc, cfg_msc_cmd,
416 "msc", "Configure MSC options")
417{
418 vty->node = MSC_NODE;
419 return CMD_SUCCESS;
420}
421
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100422#define MNCC_STR "Configure Mobile Network Call Control\n"
423#define MNCC_GUARD_TIMEOUT_STR "Set global guard timer for mncc interface activity\n"
424#define MNCC_GUARD_TIMEOUT_VALUE_STR "guard timer value (sec.)\n"
425
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100426DEFUN(cfg_msc_mncc_internal,
427 cfg_msc_mncc_internal_cmd,
428 "mncc internal",
429 MNCC_STR "Use internal MNCC handler (default; changes need a program restart)\n")
430{
431 gsm_network_set_mncc_sock_path(gsmnet, NULL);
432 return CMD_SUCCESS;
433}
434
435DEFUN(cfg_msc_mncc_external,
436 cfg_msc_mncc_external_cmd,
437 "mncc external MNCC_SOCKET_PATH",
438 MNCC_STR "Use external MNCC handler (changes need a program restart)\n"
439 "File system path to create the MNCC unix domain socket at\n")
440{
441 gsm_network_set_mncc_sock_path(gsmnet, argv[0]);
442 return CMD_SUCCESS;
443}
444
Philipp Maier9ca7b312018-10-10 17:00:49 +0200445DEFUN(cfg_msc_mncc_guard_timeout,
446 cfg_msc_mncc_guard_timeout_cmd,
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100447 "mncc guard-timeout <0-255>",
448 MNCC_STR
449 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR)
Philipp Maier9ca7b312018-10-10 17:00:49 +0200450{
451 gsmnet->mncc_guard_timeout = atoi(argv[0]);
452 return CMD_SUCCESS;
453}
454
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100455ALIAS_DEPRECATED(cfg_msc_mncc_guard_timeout,
456 cfg_msc_deprecated_mncc_guard_timeout_cmd,
457 "mncc-guard-timeout <0-255>",
458 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR);
459
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700460#define NCSS_STR "Configure call independent Supplementary Services\n"
461
462DEFUN(cfg_msc_ncss_guard_timeout,
463 cfg_msc_ncss_guard_timeout_cmd,
464 "ncss guard-timeout <0-255>",
465 NCSS_STR "Set guard timer for session activity\n"
466 "guard timer value (sec.), or 0 to disable\n")
467{
468 gsmnet->ncss_guard_timeout = atoi(argv[0]);
469 return CMD_SUCCESS;
470}
471
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200472DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
473 "assign-tmsi",
474 "Assign TMSI during Location Updating.\n")
475{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200476 gsmnet->vlr->cfg.assign_tmsi = true;
477 return CMD_SUCCESS;
478}
479
480DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
481 "no assign-tmsi",
482 NO_STR "Assign TMSI during Location Updating.\n")
483{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200484 gsmnet->vlr->cfg.assign_tmsi = false;
485 return CMD_SUCCESS;
486}
487
Philipp Maierfbf66102017-04-09 12:32:51 +0200488DEFUN(cfg_msc_cs7_instance_a,
489 cfg_msc_cs7_instance_a_cmd,
490 "cs7-instance-a <0-15>",
491 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
492{
Philipp Maierfbf66102017-04-09 12:32:51 +0200493 gsmnet->a.cs7_instance = atoi(argv[0]);
494 return CMD_SUCCESS;
495}
496
497DEFUN(cfg_msc_cs7_instance_iu,
498 cfg_msc_cs7_instance_iu_cmd,
499 "cs7-instance-iu <0-15>",
500 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
501{
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100502#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200503 gsmnet->iu.cs7_instance = atoi(argv[0]);
504 return CMD_SUCCESS;
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100505#else
506 vty_out(vty, "WARNING: 'cs7-instance-iu' without effect: built without Iu support%s",
507 VTY_NEWLINE);
508 return CMD_WARNING;
509#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200510}
511
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100512DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
513 "auth-tuple-max-reuse-count <-1-2147483647>",
514 "Configure authentication tuple re-use\n"
515 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
516{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100517 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
518 return CMD_SUCCESS;
519}
520
521DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
522 "auth-tuple-reuse-on-error (0|1)",
523 "Configure authentication tuple re-use when HLR is not responsive\n"
Oliver Smithd6e24fd2019-01-09 10:46:43 +0100524 "Never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
525 "If the HLR does not deliver new tuples, do re-use already available old ones.\n")
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100526{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100527 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
528 return CMD_SUCCESS;
529}
530
Oliver Smith0fec28a2018-12-14 10:52:52 +0100531DEFUN(cfg_msc_check_imei_rqd, cfg_msc_check_imei_rqd_cmd,
Oliver Smith03ded912019-05-02 10:40:50 +0200532 "check-imei-rqd (0|1|early)",
Oliver Smith0fec28a2018-12-14 10:52:52 +0100533 "Send each IMEI to the EIR to ask if it is permitted or not. The EIR is implemented as part of OsmoHLR, "
534 "and can optionally save the IMEI in the HLR.\n"
535 "Do not send IMEIs to the EIR\n"
Oliver Smith03ded912019-05-02 10:40:50 +0200536 "Send each IMEI to the EIR\n"
537 "Send each IMEI to the EIR, and do it at the start of the location update. This allows the EIR to receive the"
538 " 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 +0100539{
Oliver Smith03ded912019-05-02 10:40:50 +0200540 if (strcmp(argv[0], "0") == 0) {
541 gsmnet->vlr->cfg.check_imei_rqd = false;
542 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
543 } else if (strcmp(argv[0], "1") == 0) {
544 gsmnet->vlr->cfg.check_imei_rqd = true;
545 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
546 } else if (strcmp(argv[0], "early") == 0) {
547 gsmnet->vlr->cfg.check_imei_rqd = true;
548 gsmnet->vlr->cfg.retrieve_imeisv_early = true;
549 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100550 return CMD_SUCCESS;
551}
552
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100553DEFUN(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
554 "paging response-timer (default|<1-65535>)",
555 "Configure Paging\n"
556 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
557 " BSS or RNC\n"
558 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
559 "Set paging timeout in seconds\n")
560{
Pau Espin Pedrolb08a3802019-09-16 19:01:37 +0200561 if (!strcmp(argv[0], "default"))
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100562 gsmnet->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
563 else
564 gsmnet->paging_response_timer = atoi(argv[0]);
565 return CMD_SUCCESS;
566}
567
Harald Welte69c54a82018-02-09 20:41:14 +0100568DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
569 "emergency-call route-to-msisdn MSISDN",
570 "Configure Emergency Call Behaviour\n"
571 "MSISDN to which Emergency Calls are Dispatched\n"
572 "MSISDN (E.164 Phone Number)\n")
573{
Harald Welte69c54a82018-02-09 20:41:14 +0100574 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
575
576 return CMD_SUCCESS;
577}
578
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700579/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
580DEFUN(cfg_msc_sms_over_gsup, cfg_msc_sms_over_gsup_cmd,
581 "sms-over-gsup",
582 "Enable routing of SMS messages over GSUP\n")
583{
584 gsmnet->sms_over_gsup = true;
585 return CMD_SUCCESS;
586}
587
588/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
589DEFUN(cfg_msc_no_sms_over_gsup, cfg_msc_no_sms_over_gsup_cmd,
590 "no sms-over-gsup",
591 NO_STR "Disable routing of SMS messages over GSUP\n")
592{
593 gsmnet->sms_over_gsup = false;
594 return CMD_SUCCESS;
595}
596
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100597/* FIXME: This should rather be in the form of
598 * handover-number range 001234xxx
599 * and
600 * handover-number range 001234xxx FIRST LAST
601 */
602DEFUN(cfg_msc_handover_number_range, cfg_msc_handover_number_range_cmd,
603 "handover-number range MSISDN_FIRST MSISDN_LAST",
604 "Configure a range of MSISDN to be assigned to incoming inter-MSC Handovers for call forwarding.\n"
605 "Configure a handover number range\n"
606 "First Handover Number MSISDN\n"
607 "Last Handover Number MSISDN\n")
608{
609 char *endp;
610 uint64_t range_start;
611 uint64_t range_end;
612
613 /* FIXME leading zeros?? */
614
615 errno = 0;
616 range_start = strtoull(argv[0], &endp, 10);
617 if (errno || *endp != '\0') {
618 vty_out(vty, "%% Error parsing handover-number range start: %s%s",
619 argv[0], VTY_NEWLINE);
620 return CMD_WARNING;
621 }
622
623 errno = 0;
624 range_end = strtoull(argv[1], &endp, 10);
625 if (errno || *endp != '\0') {
626 vty_out(vty, "%% Error parsing handover-number range end: %s%s",
627 argv[1], VTY_NEWLINE);
628 return CMD_WARNING;
629 }
630
631 if (range_start > range_end) {
632 vty_out(vty, "%% Error: handover-number range end must be > than the range start, but"
633 " %"PRIu64" > %"PRIu64"%s", range_start, range_end, VTY_NEWLINE);
634 return CMD_WARNING;
635 }
636
637 gsmnet->handover_number.range_start = range_start;
638 gsmnet->handover_number.range_end = range_end;
639 return CMD_SUCCESS;
640}
641
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200642#define OSMUX_STR "RTP multiplexing\n"
643DEFUN(cfg_msc_osmux,
644 cfg_msc_osmux_cmd,
645 "osmux (on|off|only)",
646 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
647{
648 if (strcmp(argv[0], "off") == 0)
649 gsmnet->use_osmux = OSMUX_USAGE_OFF;
650 else if (strcmp(argv[0], "on") == 0)
651 gsmnet->use_osmux = OSMUX_USAGE_ON;
652 else if (strcmp(argv[0], "only") == 0)
653 gsmnet->use_osmux = OSMUX_USAGE_ONLY;
654
655 return CMD_SUCCESS;
656}
657
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200658static int config_write_msc(struct vty *vty)
659{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200660 vty_out(vty, "msc%s", VTY_NEWLINE);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100661 if (gsmnet->mncc_sock_path)
662 vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE);
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100663 vty_out(vty, " mncc guard-timeout %i%s",
Philipp Maier9ca7b312018-10-10 17:00:49 +0200664 gsmnet->mncc_guard_timeout, VTY_NEWLINE);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700665 vty_out(vty, " ncss guard-timeout %i%s",
666 gsmnet->ncss_guard_timeout, VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200667 vty_out(vty, " %sassign-tmsi%s",
668 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
669
Philipp Maierfbf66102017-04-09 12:32:51 +0200670 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
671 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100672#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200673 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
674 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100675#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200676
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100677 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
678 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
679 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
680 VTY_NEWLINE);
681 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
682 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
683 VTY_NEWLINE);
684
Oliver Smith03ded912019-05-02 10:40:50 +0200685 if (gsmnet->vlr->cfg.check_imei_rqd) {
686 if (gsmnet->vlr->cfg.retrieve_imeisv_early)
687 vty_out(vty, " check-imei-rqd early%s", VTY_NEWLINE);
688 else
689 vty_out(vty, " check-imei-rqd 1%s", VTY_NEWLINE);
690 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100691
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100692 if (gsmnet->paging_response_timer != MSC_PAGING_RESPONSE_TIMER_DEFAULT)
693 vty_out(vty, " paging response-timer %u%s", gsmnet->paging_response_timer, VTY_NEWLINE);
694
Harald Welte69c54a82018-02-09 20:41:14 +0100695 if (gsmnet->emergency.route_to_msisdn) {
696 vty_out(vty, " emergency-call route-to-msisdn %s%s",
697 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
698 }
699
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700700 if (gsmnet->sms_over_gsup)
701 vty_out(vty, " sms-over-gsup%s", VTY_NEWLINE);
702
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100703 if (gsmnet->handover_number.range_start || gsmnet->handover_number.range_end)
704 vty_out(vty, " handover-number range %"PRIu64" %"PRIu64"%s",
705 gsmnet->handover_number.range_start, gsmnet->handover_number.range_end,
706 VTY_NEWLINE);
707
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200708 if (gsmnet->use_osmux != OSMUX_USAGE_OFF) {
709 vty_out(vty, " osmux %s%s", gsmnet->use_osmux == OSMUX_USAGE_ON ? "on" : "only",
710 VTY_NEWLINE);
711 }
712
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200713 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200714#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200715 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200716#endif
717
Neels Hofmeyr880b9502019-05-09 02:01:55 +0200718 neighbor_ident_vty_write(vty);
719
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +0700720 /* Timer introspection commands (generic osmo_tdef API) */
721 osmo_tdef_vty_groups_write(vty, " ");
722
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200723 return CMD_SUCCESS;
724}
725
Maxc51609a2018-11-09 17:13:00 +0100726DEFUN(show_bsc, show_bsc_cmd,
727 "show bsc", SHOW_STR "BSC\n")
728{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100729 struct ran_peer *rp;
730 llist_for_each_entry(rp, &gsmnet->a.sri->ran_peers, entry) {
731 vty_out(vty, "BSC %s %s%s",
732 osmo_sccp_inst_addr_name(gsmnet->a.sri->sccp, &rp->peer_addr),
733 osmo_fsm_inst_state_name(rp->fi),
734 VTY_NEWLINE);
Maxc51609a2018-11-09 17:13:00 +0100735 }
736
737 return CMD_SUCCESS;
738}
739
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100740static const char *get_trans_proto_str(const struct gsm_trans *trans)
741{
742 static char buf[256];
743
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100744 switch (trans->type) {
745 case TRANS_CC:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100746 snprintf(buf, sizeof(buf), "%s %4u %4u",
747 gsm48_cc_state_name(trans->cc.state),
748 trans->cc.Tcurrent,
749 trans->cc.T308_second);
750 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100751 case TRANS_SMS:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700752 snprintf(buf, sizeof(buf), "CP:%s RP:%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100753 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
754 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
755 break;
756 default:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700757 return NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100758 }
759
760 return buf;
761}
762
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700763/* Prefix a given format string with a given amount of spaces */
764#define MSC_VTY_DUMP(vty, offset, fmt, args...) \
765 vty_out(vty, "%*s" fmt, offset, "", ##args)
766
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200767/* Print value of a named flag, prefixed with a given amount of spaces */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700768#define MSC_VTY_DUMP_FLAG(vty, offset, name, flag) \
769 MSC_VTY_DUMP(vty, offset + 2, "%s: %*s%s%s", \
770 name, 30 - (int)strlen(name), "", \
771 flag ? "true" : "false", \
772 VTY_NEWLINE)
773
774enum msc_vty_dump_flags {
775 MSC_VTY_DUMP_F_SUBSCR = (1 << 0),
776 MSC_VTY_DUMP_F_CONNECTION = (1 << 1),
777 MSC_VTY_DUMP_F_TRANSACTION = (1 << 2),
778};
779
780static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans,
781 int offset, uint8_t dump_flags)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100782{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700783 const char *proto_str;
784
785 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
786 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
787 vlr_subscr_name(msc_a_vsub(trans->msc_a)),
788 VTY_NEWLINE);
789 }
790
791 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200792 /* (If msc_a exists, there *must* be a non-null msc_a->c.msub) */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700793 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
794 trans->msc_a ? msub_ran_conn_name(trans->msc_a->c.msub)
795 : "(not established)",
796 VTY_NEWLINE);
797 }
798
799 MSC_VTY_DUMP(vty, offset, "Unique (global) identifier: 0x%08x%s",
800 trans->callref, VTY_NEWLINE);
801 MSC_VTY_DUMP(vty, offset, "GSM 04.07 identifier (%s): %u%s",
802 (trans->transaction_id & 0x08) ? "MO" : "MT",
803 trans->transaction_id,
804 VTY_NEWLINE);
805
806 MSC_VTY_DUMP(vty, offset, "Type: %s%s",
807 trans_type_name(trans->type),
808 VTY_NEWLINE);
809
810 if ((proto_str = get_trans_proto_str(trans))) {
811 MSC_VTY_DUMP(vty, offset, "Protocol specific: %s%s",
812 proto_str, VTY_NEWLINE);
813 }
814}
815
816static void vty_dump_one_conn(struct vty *vty, const struct msub *msub,
817 int offset, uint8_t dump_flags)
818{
819 struct vlr_subscr *vsub = msub_vsub(msub);
820 struct msc_a *msc_a = msub_msc_a(msub);
821 char buf[128];
822
823 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
824 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
825 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
826 vlr_subscr_name(vsub),
827 VTY_NEWLINE);
828 }
829
830 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
831 msub_ran_conn_name(msub),
832 VTY_NEWLINE);
833 MSC_VTY_DUMP(vty, offset, "RAN connection state: %s%s",
834 osmo_fsm_inst_state_name(msc_a->c.fi),
835 VTY_NEWLINE);
836
837 if (vsub) {
838 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
839 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
840 VTY_NEWLINE);
841 }
842
843 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
844 osmo_use_count_total(&msc_a->use_count),
845 VTY_NEWLINE);
846 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
847 osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count),
848 VTY_NEWLINE);
849
850 /* Transactions of this connection */
851 if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
852 struct gsm_trans *trans;
853 unsigned int i = 0;
854
855 /* Both subscriber and connection info is already printed */
856 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_CONNECTION;
857 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
858
859 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
860 if (trans->msc_a != msc_a)
861 continue;
862 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
863 i++, VTY_NEWLINE);
864 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
865 }
866 }
867}
868
869static void vty_dump_one_subscr(struct vty *vty, struct vlr_subscr *vsub,
870 int offset, uint8_t dump_flags)
871{
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700872 struct gsm_network *net;
873 struct timespec now;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700874 char buf[128];
875
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700876 if (vsub->name[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700877 MSC_VTY_DUMP(vty, offset, "Name: '%s'%s",
878 vsub->name, VTY_NEWLINE);
879 }
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700880 if (vsub->msisdn[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700881 MSC_VTY_DUMP(vty, offset, "MSISDN: %s%s",
882 vsub->msisdn, VTY_NEWLINE);
883 }
884
885 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
886 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
887 VTY_NEWLINE);
888 MSC_VTY_DUMP(vty, offset, "RAN type: %s%s",
889 osmo_rat_type_name(vsub->cs.attached_via_ran),
890 VTY_NEWLINE);
891
892 MSC_VTY_DUMP(vty, offset, "IMSI: %s%s",
893 vsub->imsi, VTY_NEWLINE);
894 if (vsub->tmsi != GSM_RESERVED_TMSI) {
895 MSC_VTY_DUMP(vty, offset, "TMSI: %08X%s",
896 vsub->tmsi, VTY_NEWLINE);
897 }
898 if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
899 MSC_VTY_DUMP(vty, offset, "New TMSI: %08X%s",
900 vsub->tmsi_new, VTY_NEWLINE);
901 }
902 if (vsub->imei[0] != '\0') {
903 MSC_VTY_DUMP(vty, offset, "IMEI: %s%s",
904 vsub->imei, VTY_NEWLINE);
905 }
906 if (vsub->imeisv[0] != '\0') {
907 MSC_VTY_DUMP(vty, offset, "IMEISV: %s%s",
908 vsub->imeisv, VTY_NEWLINE);
909 }
910
911 MSC_VTY_DUMP(vty, offset, "Flags: %s", VTY_NEWLINE);
912 MSC_VTY_DUMP_FLAG(vty, offset, "IMSI detached",
913 vsub->imsi_detached_flag);
914 MSC_VTY_DUMP_FLAG(vty, offset, "Conf. by radio contact",
915 vsub->conf_by_radio_contact_ind);
916 MSC_VTY_DUMP_FLAG(vty, offset, "Subscr. data conf. by HLR",
917 vsub->sub_dataconf_by_hlr_ind);
918 MSC_VTY_DUMP_FLAG(vty, offset, "Location conf. in HLR",
919 vsub->loc_conf_in_hlr_ind);
920 MSC_VTY_DUMP_FLAG(vty, offset, "Subscriber dormant",
921 vsub->dormant_ind);
922 MSC_VTY_DUMP_FLAG(vty, offset, "Received cancel location",
923 vsub->cancel_loc_rx);
924 MSC_VTY_DUMP_FLAG(vty, offset, "MS not reachable",
925 vsub->ms_not_reachable_flag);
926 MSC_VTY_DUMP_FLAG(vty, offset, "LA allowed",
927 vsub->la_allowed);
928
929 if (vsub->last_tuple) {
930 struct vlr_auth_tuple *t = vsub->last_tuple;
931 MSC_VTY_DUMP(vty, offset, "A3A8 last tuple (used %d times): %s",
932 t->use_count, VTY_NEWLINE);
933 MSC_VTY_DUMP(vty, offset + 2, "seq # : %d%s",
934 t->key_seq, VTY_NEWLINE);
935 MSC_VTY_DUMP(vty, offset + 2, "RAND : %s%s",
936 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
937 VTY_NEWLINE);
938 MSC_VTY_DUMP(vty, offset + 2, "SRES : %s%s",
939 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
940 VTY_NEWLINE);
941 MSC_VTY_DUMP(vty, offset + 2, "Kc : %s%s",
942 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
943 VTY_NEWLINE);
944 }
945
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700946 /* XXX move t3212 into struct vlr_instance? */
947 net = vsub->vlr->user_ctx;
948 if (!net->t3212) {
949 MSC_VTY_DUMP(vty, offset, "Expires: never (T3212 is disabled)%s",
950 VTY_NEWLINE);
951 } else if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) {
952 MSC_VTY_DUMP(vty, offset, "Expires: never%s",
953 VTY_NEWLINE);
954 } else if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
955 MSC_VTY_DUMP(vty, offset, "Expires: in %ld min %ld sec%s",
956 (vsub->expire_lu - now.tv_sec) / 60,
957 (vsub->expire_lu - now.tv_sec) % 60,
958 VTY_NEWLINE);
959 }
960
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700961 MSC_VTY_DUMP(vty, offset, "Paging: %s paging for %d requests%s",
962 vsub->cs.is_paging ? "is" : "not",
963 llist_count(&vsub->cs.requests),
964 VTY_NEWLINE);
965
966 /* SGs related */
967 MSC_VTY_DUMP(vty, offset, "SGs-state: %s%s",
968 osmo_fsm_inst_state_name(vsub->sgs_fsm),
969 VTY_NEWLINE);
970 MSC_VTY_DUMP(vty, offset, "SGs-MME: %s%s",
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700971 vsub->sgs.mme_name[0] != '\0' ? vsub->sgs.mme_name : "(none)",
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700972 VTY_NEWLINE);
973
974 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
975 osmo_use_count_total(&vsub->use_count),
976 VTY_NEWLINE);
977 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
978 osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count),
979 VTY_NEWLINE);
980
981 /* Connection(s) and/or transactions of this subscriber */
982 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
983 struct msub *msub = msub_for_vsub(vsub);
984 if (!msub)
985 return;
986
987 /* Subscriber info is already printed */
988 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
989
990 MSC_VTY_DUMP(vty, offset, "Connection: %s", VTY_NEWLINE);
991 vty_dump_one_conn(vty, msub, offset + 2, dump_flags);
992 } else if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
993 struct gsm_trans *trans;
994 unsigned int i = 0;
995
996 /* Subscriber info is already printed */
997 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
998 /* Do not print connection info, but mention it */
999 dump_flags |= MSC_VTY_DUMP_F_CONNECTION;
1000
1001 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1002 if (trans->vsub != vsub)
1003 continue;
1004 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
1005 i++, VTY_NEWLINE);
1006 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
1007 }
1008 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001009}
1010
1011DEFUN(show_msc_transaction, show_msc_transaction_cmd,
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001012 "show transaction",
1013 SHOW_STR "Transactions\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001014{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001015 struct gsm_trans *trans;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001016 uint8_t flags = 0x00;
1017 unsigned int i = 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001018
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001019 flags |= MSC_VTY_DUMP_F_CONNECTION;
1020 flags |= MSC_VTY_DUMP_F_SUBSCR;
1021
1022 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1023 vty_out(vty, " Transaction #%02u: %s", i++, VTY_NEWLINE);
1024 vty_dump_one_trans(vty, trans, 4, flags);
1025 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001026
1027 return CMD_SUCCESS;
1028}
1029
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001030DEFUN(show_msc_conn, show_msc_conn_cmd,
1031 "show connection [trans]",
1032 SHOW_STR "Subscriber Connections\n"
1033 "Show child transactions of each connection\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001034{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001035 uint8_t flags = 0x00;
1036 unsigned int i = 0;
1037 struct msub *msub;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001038
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001039 if (argc > 0)
1040 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1041 flags |= MSC_VTY_DUMP_F_SUBSCR;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001042
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001043 llist_for_each_entry(msub, &msub_list, entry) {
1044 vty_out(vty, " Connection #%02u: %s", i++, VTY_NEWLINE);
1045 vty_dump_one_conn(vty, msub, 4, flags);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001046 }
1047
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001048 return CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001049}
1050
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001051#define SUBSCR_FLAGS "[(conn|trans|conn+trans)]"
1052#define SUBSCR_FLAGS_HELP \
1053 "Show child connections\n" \
1054 "Show child transactions\n" \
1055 "Show child connections and transactions\n"
1056
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001057/* Subscriber */
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001058DEFUN(show_subscr_cache, show_subscr_cache_cmd,
1059 "show subscriber cache " SUBSCR_FLAGS,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001060 SHOW_STR "Show information about subscribers\n"
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001061 "Display contents of subscriber cache\n"
1062 SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001063{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001064 struct vlr_subscr *vsub;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001065 unsigned int count = 0;
1066 uint8_t flags = 0x00;
1067 unsigned int i = 0;
1068
1069 if (argc && strcmp(argv[0], "conn") == 0)
1070 flags |= MSC_VTY_DUMP_F_CONNECTION;
1071 else if (argc && strcmp(argv[0], "trans") == 0)
1072 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1073 else if (argc && strcmp(argv[0], "conn+trans") == 0)
1074 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001075
1076 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
1077 if (++count > 100) {
1078 vty_out(vty, "%% More than %d subscribers in cache,"
1079 " stopping here.%s", count-1, VTY_NEWLINE);
1080 break;
1081 }
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001082 vty_out(vty, " Subscriber #%02u: %s", i++, VTY_NEWLINE);
1083 vty_dump_one_subscr(vty, vsub, 4, flags);
Harald Welte69c54a82018-02-09 20:41:14 +01001084 }
1085
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001086 return CMD_SUCCESS;
1087}
1088
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001089DEFUN(sms_send_pend,
1090 sms_send_pend_cmd,
1091 "sms send pending",
1092 "SMS related commands\n" "SMS Sending related commands\n"
1093 "Send all pending SMS")
1094{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001095 struct gsm_sms *sms;
1096 unsigned long long sms_id = 0;
1097
1098 while (1) {
1099 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1100 if (!sms)
1101 break;
1102
1103 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001104 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001105
1106 sms_id = sms->id + 1;
1107 }
1108
1109 return CMD_SUCCESS;
1110}
1111
1112DEFUN(sms_delete_expired,
1113 sms_delete_expired_cmd,
1114 "sms delete expired",
1115 "SMS related commands\n" "SMS Database related commands\n"
1116 "Delete all expired SMS")
1117{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001118 struct gsm_sms *sms;
1119 unsigned long long sms_id = 0;
1120 long long num_deleted = 0;
1121
1122 while (1) {
1123 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1124 if (!sms)
1125 break;
1126
1127 /* Skip SMS which are currently queued for sending. */
1128 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
1129 continue;
1130
1131 /* Expiration check is performed by the DB layer. */
1132 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
1133 num_deleted++;
1134
1135 sms_id = sms->id + 1;
1136 }
1137
1138 if (num_deleted == 0) {
1139 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
1140 return CMD_WARNING;
1141 }
1142
1143 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
1144 return CMD_SUCCESS;
1145}
1146
1147static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +02001148 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001149 char *str, uint8_t tp_pid)
1150{
1151 struct gsm_network *net = receiver->vlr->user_ctx;
1152 struct gsm_sms *sms;
1153
Harald Welte39b55482018-04-09 19:19:33 +02001154 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Vadim Yanitskiydb4839c2019-12-01 18:52:58 +07001155 if (!sms) {
1156 LOGP(DLSMS, LOGL_ERROR, "Failed to allocate SMS\n");
1157 return CMD_WARNING;
1158 }
1159
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001160 sms->protocol_id = tp_pid;
1161
1162 /* store in database for the queue */
1163 if (db_sms_store(sms) != 0) {
1164 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
1165 sms_free(sms);
1166 return CMD_WARNING;
1167 }
1168 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
1169
1170 sms_free(sms);
1171 sms_queue_trigger(net->sms_queue);
1172 return CMD_SUCCESS;
1173}
1174
1175static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
1176 const char *type,
1177 const char *id)
1178{
1179 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001180 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001181 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001182 return vlr_subscr_find_by_imsi(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001183 else if (!strcmp(type, "tmsi"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001184 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id), VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001185
1186 return NULL;
1187}
1188#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
1189#define SUBSCR_HELP "Operations on a Subscriber\n" \
1190 "Identify subscriber by MSISDN (phone number)\n" \
1191 "Legacy alias for 'msisdn'\n" \
1192 "Identify subscriber by IMSI\n" \
1193 "Identify subscriber by TMSI\n" \
Vadim Yanitskiy3ccd8232019-05-16 01:35:23 +07001194 "Legacy alias for 'imsi'\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001195 "Identifier for the subscriber\n"
1196
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001197DEFUN(show_subscr, show_subscr_cmd,
1198 "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
1199 SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001200{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001201 struct vlr_subscr *vsub;
1202 uint8_t flags = 0x00;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001203
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001204 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001205 if (!vsub) {
1206 vty_out(vty, "%% No subscriber found for %s %s%s",
1207 argv[0], argv[1], VTY_NEWLINE);
1208 return CMD_WARNING;
1209 }
1210
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001211 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
1212 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
1213 * 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 +01001214 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001215
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001216 if (argc > 2 && strcmp(argv[2], "conn") == 0)
1217 flags |= MSC_VTY_DUMP_F_CONNECTION;
1218 else if (argc > 2 && strcmp(argv[2], "trans") == 0)
1219 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1220 else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
1221 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
1222
1223 vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
1224 vty_dump_one_subscr(vty, vsub, 4, flags);
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001225
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001226 return CMD_SUCCESS;
1227}
1228
Vadim Yanitskiyb7ddbf32020-01-20 21:30:09 +07001229DEFUN_DEPRECATED(subscriber_create, subscriber_create_cmd,
1230 "subscriber create imsi ID",
1231 "Operations on a Subscriber\n"
1232 "Create new subscriber\n"
1233 "Identify the subscriber by his IMSI\n"
1234 "Identifier for the subscriber\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001235{
1236 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
1237 VTY_NEWLINE);
1238 return CMD_WARNING;
1239}
1240
1241DEFUN(subscriber_send_pending_sms,
1242 subscriber_send_pending_sms_cmd,
1243 "subscriber " SUBSCR_TYPES " ID sms pending-send",
1244 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
1245{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001246 struct vlr_subscr *vsub;
1247 struct gsm_sms *sms;
1248
1249 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1250 if (!vsub) {
1251 vty_out(vty, "%% No subscriber found for %s %s%s",
1252 argv[0], argv[1], VTY_NEWLINE);
1253 return CMD_WARNING;
1254 }
1255
1256 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
1257 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001258 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001259
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001260 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001261
1262 return CMD_SUCCESS;
1263}
1264
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001265DEFUN(subscriber_sms_delete_all,
1266 subscriber_sms_delete_all_cmd,
1267 "subscriber " SUBSCR_TYPES " ID sms delete-all",
1268 SUBSCR_HELP "SMS Operations\n"
1269 "Delete all SMS to be delivered to this subscriber"
1270 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
1271 " WILL BE LOST.\n")
1272{
1273 struct vlr_subscr *vsub;
1274
1275 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1276 if (!vsub) {
1277 vty_out(vty, "%% No subscriber found for %s %s%s",
1278 argv[0], argv[1], VTY_NEWLINE);
1279 return CMD_WARNING;
1280 }
1281
1282 db_sms_delete_by_msisdn(vsub->msisdn);
1283
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001284 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001285
1286 return CMD_SUCCESS;
1287}
1288
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001289DEFUN(subscriber_send_sms,
1290 subscriber_send_sms_cmd,
1291 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1292 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1293{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001294 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001295 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001296 char *str;
1297 int rc;
1298
1299 if (!vsub) {
1300 vty_out(vty, "%% No subscriber found for %s %s%s",
1301 argv[0], argv[1], VTY_NEWLINE);
1302 rc = CMD_WARNING;
1303 goto err;
1304 }
1305
Harald Welte39b55482018-04-09 19:19:33 +02001306 if (!strcmp(argv[2], "msisdn"))
1307 sender_msisdn = argv[3];
1308 else {
1309 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1310 if (!sender) {
1311 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1312 rc = CMD_WARNING;
1313 goto err;
1314 }
1315 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001316 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001317 }
1318
1319 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001320 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001321 talloc_free(str);
1322
1323err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001324 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001325 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001326
1327 return rc;
1328}
1329
1330DEFUN(subscriber_silent_sms,
1331 subscriber_silent_sms_cmd,
1332
1333 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1334 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1335{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001336 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001337 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001338 char *str;
1339 int rc;
1340
1341 if (!vsub) {
1342 vty_out(vty, "%% No subscriber found for %s %s%s",
1343 argv[0], argv[1], VTY_NEWLINE);
1344 rc = CMD_WARNING;
1345 goto err;
1346 }
1347
Harald Welte39b55482018-04-09 19:19:33 +02001348 if (!strcmp(argv[2], "msisdn")) {
1349 sender_msisdn = argv[3];
1350 } else {
1351 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1352 if (!sender) {
1353 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1354 rc = CMD_WARNING;
1355 goto err;
1356 }
1357 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001358 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001359 }
1360
1361 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001362 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001363 talloc_free(str);
1364
1365err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001366 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001367 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001368
1369 return rc;
1370}
1371
Sylvain Munaut93558302019-02-14 20:13:08 +01001372#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001373#define CHAN_TYPE_HELP \
1374 "Any channel\n" \
1375 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001376 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001377 "Any TCH channel\n" \
1378 "SDCCH channel\n"
1379
Sylvain Munaut93558302019-02-14 20:13:08 +01001380#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1381#define CHAN_MODE_HELP \
1382 "Signalling only\n" \
1383 "Speech with HR codec\n" \
1384 "Speech with FR codec\n" \
1385 "Speech with EFR codec\n" \
1386 "Speech with AMR codec\n"
1387
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001388DEFUN(subscriber_silent_call_start,
1389 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001390 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001391 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001392 CHAN_TYPE_HELP CHAN_MODE_HELP
1393 "Target IP for RTP traffic (default 127.0.0.1)\n"
1394 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001395{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001396 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001397 struct gsm0808_channel_type ct;
1398 const char *ip;
1399 uint16_t port;
1400 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001401
1402 if (!vsub) {
1403 vty_out(vty, "%% No subscriber found for %s %s%s",
1404 argv[0], argv[1], VTY_NEWLINE);
1405 return CMD_WARNING;
1406 }
1407
Sylvain Munaut93558302019-02-14 20:13:08 +01001408 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001409
Sylvain Munaut93558302019-02-14 20:13:08 +01001410 if (!strcmp(argv[3], "signalling")) {
1411 ct.ch_indctr = GSM0808_CHAN_SIGN;
1412 ct.perm_spch[0] = 0; /* Spare but required */
1413 ct.perm_spch_len = 1;
1414 } else if (!strcmp(argv[3], "speech-hr")) {
1415 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1416 ct.perm_spch[0] = GSM0808_PERM_HR1;
1417 ct.perm_spch_len = 1;
1418 } else if (!strcmp(argv[3], "speech-fr")) {
1419 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1420 ct.perm_spch[0] = GSM0808_PERM_FR1;
1421 ct.perm_spch_len = 1;
1422 } else if (!strcmp(argv[3], "speech-efr")) {
1423 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1424 ct.perm_spch[0] = GSM0808_PERM_FR2;
1425 ct.perm_spch_len = 1;
1426 } else if (!strcmp(argv[3], "speech-amr")) {
1427 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1428 ct.perm_spch[0] = GSM0808_PERM_FR3;
1429 ct.perm_spch[1] = GSM0808_PERM_HR3;
1430 ct.perm_spch_len = 2;
1431 }
1432
1433 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1434
1435 if (!strcmp(argv[2], "tch/f"))
1436 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1437 else if (!strcmp(argv[2], "tch/h"))
1438 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1439 else if (!strcmp(argv[2], "tch/any"))
1440 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1441 else if (!strcmp(argv[2], "sdcch")) {
1442 if (speech) {
1443 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1444 return CMD_WARNING;
1445 }
1446 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1447 } else
1448 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1449
1450 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1451 port = argc >= 6 ? atoi(argv[5]) : 4000;
1452
1453 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001454 switch (rc) {
1455 case -ENODEV:
1456 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1457 break;
1458 default:
1459 if (rc)
1460 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1461 else
1462 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1463 break;
1464 }
1465
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001466 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001467 return rc ? CMD_WARNING : CMD_SUCCESS;
1468}
1469
1470DEFUN(subscriber_silent_call_stop,
1471 subscriber_silent_call_stop_cmd,
1472 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1473 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1474 CHAN_TYPE_HELP)
1475{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001476 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1477 int rc;
1478
1479 if (!vsub) {
1480 vty_out(vty, "%% No subscriber found for %s %s%s",
1481 argv[0], argv[1], VTY_NEWLINE);
1482 return CMD_WARNING;
1483 }
1484
1485 rc = gsm_silent_call_stop(vsub);
1486 switch (rc) {
1487 case -ENODEV:
1488 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1489 break;
1490 case -ENOENT:
1491 vty_out(vty, "%% Subscriber has no silent call active%s",
1492 VTY_NEWLINE);
1493 break;
1494 default:
1495 if (rc)
1496 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1497 else
1498 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1499 break;
1500 }
1501
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001502 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001503 return rc ? CMD_WARNING : CMD_SUCCESS;
1504}
1505
1506DEFUN(subscriber_ussd_notify,
1507 subscriber_ussd_notify_cmd,
1508 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1509 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1510 "Alerting Level 0\n"
1511 "Alerting Level 1\n"
1512 "Alerting Level 2\n"
1513 "Text of USSD message to send\n")
1514{
1515 char *text;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001516 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001517 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1518 int level;
1519
1520 if (!vsub) {
1521 vty_out(vty, "%% No subscriber found for %s %s%s",
1522 argv[0], argv[1], VTY_NEWLINE);
1523 return CMD_WARNING;
1524 }
1525
1526 level = atoi(argv[2]);
1527 text = argv_concat(argv, argc, 3);
1528 if (!text) {
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001529 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001530 return CMD_WARNING;
1531 }
1532
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001533 msc_a = msc_a_for_vsub(vsub, true);
1534 if (!msc_a || msc_a->c.remote_to) {
1535 vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001536 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001537 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001538 talloc_free(text);
1539 return CMD_WARNING;
1540 }
1541
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001542 msc_send_ussd_notify(msc_a, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001543 /* FIXME: since we don't allocate a transaction here,
1544 * we use dummy GSM 04.07 transaction ID. */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001545 msc_send_ussd_release_complete(msc_a, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001546
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001547 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001548 talloc_free(text);
1549 return CMD_SUCCESS;
1550}
1551
1552DEFUN(subscriber_paging,
1553 subscriber_paging_cmd,
1554 "subscriber " SUBSCR_TYPES " ID paging",
1555 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1556{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001557 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001558 struct paging_request *req;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001559
1560 if (!vsub) {
1561 vty_out(vty, "%% No subscriber found for %s %s%s",
1562 argv[0], argv[1], VTY_NEWLINE);
1563 return CMD_WARNING;
1564 }
1565
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001566 req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL,
1567 NULL, NULL, "manual Paging from VTY");
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001568 if (req)
1569 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1570 else
1571 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1572
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001573 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001574 return req ? CMD_SUCCESS : CMD_WARNING;
1575}
1576
1577static int loop_by_char(uint8_t ch)
1578{
1579 switch (ch) {
1580 case 'a':
1581 return GSM414_LOOP_A;
1582 case 'b':
1583 return GSM414_LOOP_B;
1584 case 'c':
1585 return GSM414_LOOP_C;
1586 case 'd':
1587 return GSM414_LOOP_D;
1588 case 'e':
1589 return GSM414_LOOP_E;
1590 case 'f':
1591 return GSM414_LOOP_F;
1592 case 'i':
1593 return GSM414_LOOP_I;
1594 }
1595 return -1;
1596}
1597
1598DEFUN(subscriber_mstest_close,
1599 subscriber_mstest_close_cmd,
1600 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1601 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1602 "Close a TCH Loop inside the MS\n"
1603 "Loop Type A\n"
1604 "Loop Type B\n"
1605 "Loop Type C\n"
1606 "Loop Type D\n"
1607 "Loop Type E\n"
1608 "Loop Type F\n"
1609 "Loop Type I\n")
1610{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001611 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001612 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1613 const char *loop_str;
1614 int loop_mode;
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 loop_str = argv[2];
1623 loop_mode = loop_by_char(loop_str[0]);
1624
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001625 msc_a = msc_a_for_vsub(vsub, true);
1626 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001627 vty_out(vty, "%% An active connection is required for %s %s%s",
1628 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001629 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001630 return CMD_WARNING;
1631 }
1632
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001633 gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001634
1635 return CMD_SUCCESS;
1636}
1637
1638DEFUN(subscriber_mstest_open,
1639 subscriber_mstest_open_cmd,
1640 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1641 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1642 "Open a TCH Loop inside the MS\n")
1643{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001644 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001645 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1646
1647 if (!vsub) {
1648 vty_out(vty, "%% No subscriber found for %s %s%s",
1649 argv[0], argv[1], VTY_NEWLINE);
1650 return CMD_WARNING;
1651 }
1652
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001653 msc_a = msc_a_for_vsub(vsub, true);
1654 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001655 vty_out(vty, "%% An active connection is required for %s %s%s",
1656 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001657 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001658 return CMD_WARNING;
1659 }
1660
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001661 gsm0414_tx_open_loop_cmd(msc_a);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001662
1663 return CMD_SUCCESS;
1664}
1665
1666DEFUN(ena_subscr_expire,
1667 ena_subscr_expire_cmd,
1668 "subscriber " SUBSCR_TYPES " ID expire",
1669 SUBSCR_HELP "Expire the subscriber Now\n")
1670{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001671 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1672 argv[1]);
1673
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
1680 if (vlr_subscr_expire(vsub))
1681 vty_out(vty, "%% VLR released subscriber %s%s",
1682 vlr_subscr_name(vsub), VTY_NEWLINE);
1683
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001684 if (osmo_use_count_total(&vsub->use_count) > 1)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001685 vty_out(vty, "%% Subscriber %s is still in use,"
1686 " should be released soon%s",
1687 vlr_subscr_name(vsub), VTY_NEWLINE);
1688
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001689 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001690 return CMD_SUCCESS;
1691}
1692
1693static int scall_cbfn(unsigned int subsys, unsigned int signal,
1694 void *handler_data, void *signal_data)
1695{
1696 struct scall_signal_data *sigdata = signal_data;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001697 struct vty *vty = sigdata->vty;
1698
1699 if (!vty_is_active(vty))
1700 return 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001701
1702 switch (signal) {
1703 case S_SCALL_SUCCESS:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001704 vty_out(vty, "%% Silent call success%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001705 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001706 case S_SCALL_FAILED:
1707 vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE);
1708 break;
1709 case S_SCALL_DETACHED:
1710 vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001711 break;
1712 }
1713 return 0;
1714}
1715
1716DEFUN(show_stats,
1717 show_stats_cmd,
1718 "show statistics",
1719 SHOW_STR "Display network statistics\n")
1720{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001721 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001722 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1723 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1724 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001725 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001726 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001727 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001728 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001729 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001730 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1731 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001732 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001733 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001734 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1735 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001736 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001737 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001738 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1739 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1740 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001741 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001742 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001743 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1744 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001745 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001746 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001747 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1748 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001749 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001750 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001751 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current,
1752 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1753 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current
1754 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1755 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001756 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001757 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current,
1758 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1759 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current
1760 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1761 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001762 return CMD_SUCCESS;
1763}
1764
1765DEFUN(show_smsqueue,
1766 show_smsqueue_cmd,
1767 "show sms-queue",
1768 SHOW_STR "Display SMSqueue statistics\n")
1769{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001770 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001771 return CMD_SUCCESS;
1772}
1773
1774DEFUN(smsqueue_trigger,
1775 smsqueue_trigger_cmd,
1776 "sms-queue trigger",
1777 "SMS Queue\n" "Trigger sending messages\n")
1778{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001779 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001780 return CMD_SUCCESS;
1781}
1782
1783DEFUN(smsqueue_max,
1784 smsqueue_max_cmd,
1785 "sms-queue max-pending <1-500>",
1786 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1787{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001788 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001789 return CMD_SUCCESS;
1790}
1791
1792DEFUN(smsqueue_clear,
1793 smsqueue_clear_cmd,
1794 "sms-queue clear",
1795 "SMS Queue\n" "Clear the queue of pending SMS\n")
1796{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001797 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001798 return CMD_SUCCESS;
1799}
1800
1801DEFUN(smsqueue_fail,
1802 smsqueue_fail_cmd,
1803 "sms-queue max-failure <1-500>",
1804 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1805{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001806 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001807 return CMD_SUCCESS;
1808}
1809
1810
1811DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1812 "mncc-int", "Configure internal MNCC handler")
1813{
1814 vty->node = MNCC_INT_NODE;
1815
1816 return CMD_SUCCESS;
1817}
1818
1819static struct cmd_node mncc_int_node = {
1820 MNCC_INT_NODE,
1821 "%s(config-mncc-int)# ",
1822 1,
1823};
1824
1825static const struct value_string tchf_codec_names[] = {
1826 { GSM48_CMODE_SPEECH_V1, "fr" },
1827 { GSM48_CMODE_SPEECH_EFR, "efr" },
1828 { GSM48_CMODE_SPEECH_AMR, "amr" },
1829 { 0, NULL }
1830};
1831
1832static const struct value_string tchh_codec_names[] = {
1833 { GSM48_CMODE_SPEECH_V1, "hr" },
1834 { GSM48_CMODE_SPEECH_AMR, "amr" },
1835 { 0, NULL }
1836};
1837
1838static int config_write_mncc_int(struct vty *vty)
1839{
1840 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1841 vty_out(vty, " default-codec tch-f %s%s",
1842 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1843 VTY_NEWLINE);
1844 vty_out(vty, " default-codec tch-h %s%s",
1845 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1846 VTY_NEWLINE);
1847
1848 return CMD_SUCCESS;
1849}
1850
1851DEFUN(mnccint_def_codec_f,
1852 mnccint_def_codec_f_cmd,
1853 "default-codec tch-f (fr|efr|amr)",
1854 "Set default codec\n" "Codec for TCH/F\n"
1855 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1856{
1857 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1858
1859 return CMD_SUCCESS;
1860}
1861
1862DEFUN(mnccint_def_codec_h,
1863 mnccint_def_codec_h_cmd,
1864 "default-codec tch-h (hr|amr)",
1865 "Set default codec\n" "Codec for TCH/H\n"
1866 "Half-Rate\n" "Adaptive Multi-Rate\n")
1867{
1868 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1869
1870 return CMD_SUCCESS;
1871}
1872
1873
1874DEFUN(logging_fltr_imsi,
1875 logging_fltr_imsi_cmd,
1876 "logging filter imsi IMSI",
1877 LOGGING_STR FILTER_STR
1878 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1879{
1880 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001881 struct log_target *tgt = osmo_log_vty2tgt(vty);
1882 const char *imsi = argv[0];
1883
1884 if (!tgt)
1885 return CMD_WARNING;
1886
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001887 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001888
1889 if (!vlr_subscr) {
1890 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1891 argv[0], VTY_NEWLINE);
1892 return CMD_WARNING;
1893 }
1894
1895 log_set_filter_vlr_subscr(tgt, vlr_subscr);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001896 vlr_subscr_put(vlr_subscr, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001897 return CMD_SUCCESS;
1898}
1899
1900static struct cmd_node hlr_node = {
1901 HLR_NODE,
1902 "%s(config-hlr)# ",
1903 1,
1904};
1905
1906DEFUN(cfg_hlr, cfg_hlr_cmd,
1907 "hlr", "Configure connection to the HLR")
1908{
1909 vty->node = HLR_NODE;
1910 return CMD_SUCCESS;
1911}
1912
1913DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1914 "Remote GSUP address of the HLR\n"
1915 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1916{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001917 talloc_free((void*)gsmnet->gsup_server_addr_str);
1918 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1919 return CMD_SUCCESS;
1920}
1921
1922DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1923 "Remote GSUP port of the HLR\n"
1924 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1925{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001926 gsmnet->gsup_server_port = atoi(argv[0]);
1927 return CMD_SUCCESS;
1928}
1929
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001930DEFUN(cfg_hlr_ipa_name,
1931 cfg_hlr_ipa_name_cmd,
1932 "ipa-name NAME",
1933 "Set the IPA name of this MSC\n"
1934 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1935 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
1936 "The default is 'MSC-00-00-00-00-00-00'.\n")
1937{
1938 if (vty->type != VTY_FILE) {
1939 vty_out(vty, "The IPA name cannot be changed at run-time; "
Martin Hauke3f07dac2019-11-14 17:49:08 +01001940 "It can only be set in the configuration file.%s", VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001941 return CMD_WARNING;
1942 }
1943
1944 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
1945 return CMD_SUCCESS;
1946}
1947
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001948static int config_write_hlr(struct vty *vty)
1949{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001950 vty_out(vty, "hlr%s", VTY_NEWLINE);
1951 vty_out(vty, " remote-ip %s%s",
1952 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1953 vty_out(vty, " remote-port %u%s",
1954 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001955 if (gsmnet->msc_ipa_name)
1956 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001957 return CMD_SUCCESS;
1958}
1959
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001960void msc_vty_init(struct gsm_network *msc_network)
1961{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001962 OSMO_ASSERT(gsmnet == NULL);
1963 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001964
1965 osmo_stats_vty_add_cmds();
1966
1967 install_element(CONFIG_NODE, &cfg_net_cmd);
1968 install_node(&net_node, config_write_net);
1969 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1970 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1971 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1972 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1973 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +02001974 install_element(GSMNET_NODE, &cfg_net_encryption_uea_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001975 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1976 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1977 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1978 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1979 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1980 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1981 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1982 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Keith Whyte991bb422019-08-08 15:43:40 +02001983 install_element(GSMNET_NODE, &cfg_net_call_wait_cmd);
1984 install_element(GSMNET_NODE, &cfg_net_no_call_wait_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001985
1986 install_element(CONFIG_NODE, &cfg_msc_cmd);
1987 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001988 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01001989 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
1990 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02001991 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01001992 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07001993 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001994 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001995 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
1996 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01001997 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001998 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
1999 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01002000 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01002001 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07002002 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
2003 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +02002004 install_element(MSC_NODE, &cfg_msc_osmux_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002005 install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd);
2006
2007 neighbor_ident_vty_init(msc_network);
Philipp Maierfbf66102017-04-09 12:32:51 +02002008
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +07002009 /* Timer configuration commands (generic osmo_tdef API) */
2010 osmo_tdef_vty_groups_init(MSC_NODE, msc_tdef_group);
2011
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02002012 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002013#ifdef BUILD_IU
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002014 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 +02002015#endif
Harald Welte0df904d2018-12-03 11:00:04 +01002016 sgs_vty_init();
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002017
Stefan Sperling617ac802018-02-22 17:58:20 +01002018 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002019
2020 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
2021
2022 install_element_ve(&show_subscr_cmd);
2023 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01002024 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002025 install_element_ve(&show_msc_conn_cmd);
2026 install_element_ve(&show_msc_transaction_cmd);
2027
2028 install_element_ve(&sms_send_pend_cmd);
2029 install_element_ve(&sms_delete_expired_cmd);
2030
2031 install_element_ve(&subscriber_create_cmd);
2032 install_element_ve(&subscriber_send_sms_cmd);
2033 install_element_ve(&subscriber_silent_sms_cmd);
2034 install_element_ve(&subscriber_silent_call_start_cmd);
2035 install_element_ve(&subscriber_silent_call_stop_cmd);
2036 install_element_ve(&subscriber_ussd_notify_cmd);
2037 install_element_ve(&subscriber_mstest_close_cmd);
2038 install_element_ve(&subscriber_mstest_open_cmd);
2039 install_element_ve(&subscriber_paging_cmd);
2040 install_element_ve(&show_stats_cmd);
2041 install_element_ve(&show_smsqueue_cmd);
2042 install_element_ve(&logging_fltr_imsi_cmd);
2043
2044 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
2045 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
2046 install_element(ENABLE_NODE, &smsqueue_max_cmd);
2047 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
2048 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
2049 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01002050 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002051
2052 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
2053 install_node(&mncc_int_node, config_write_mncc_int);
2054 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
2055 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
2056
2057 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
2058
2059 install_element(CONFIG_NODE, &cfg_hlr_cmd);
2060 install_node(&hlr_node, config_write_hlr);
2061 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
2062 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002063 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002064}