blob: a92609d7fdc022b1b711ac9705fd34c23f8ac07b [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
Vadim Yanitskiy9b56cd82020-01-25 06:38:44 +070072static struct cmd_node net_node = {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010073 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
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700306/* NOTE: actually this is subscriber expiration timeout */
307#define PER_LOC_UPD_STR "Periodic Location Updating Interval\n"
308
309DEFUN_DEPRECATED(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
310 "periodic location update <6-1530>",
311 PER_LOC_UPD_STR PER_LOC_UPD_STR PER_LOC_UPD_STR
312 "Periodic Location Updating Interval in Minutes\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100313{
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700314 int minutes = atoi(argv[0]);
315 int rc;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100316
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700317 vty_out(vty, "%% 'periodic location update' is now deprecated: "
318 "use 'timer T3212' to change subscriber expiration "
319 "timeout.%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100320
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700321 /* We used to double this value and add a minute when scheduling the
322 * expiration timer. Let's emulate the old behaviour here. */
323 minutes = minutes * 2 + 1;
324 vty_out(vty, "%% Setting T3212 to %d minutes "
325 "(emulating the old behaviour).%s",
326 minutes, VTY_NEWLINE);
327
328 rc = osmo_tdef_set(msc_tdefs_vlr, 3212, minutes, OSMO_TDEF_M);
329 return rc ? CMD_WARNING : CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100330}
331
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700332DEFUN_DEPRECATED(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
333 "no periodic location update",
334 NO_STR PER_LOC_UPD_STR PER_LOC_UPD_STR PER_LOC_UPD_STR)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100335{
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700336 int rc;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100337
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700338 vty_out(vty, "%% 'periodic location update' is now deprecated: "
339 "use 'timer T3212' to change subscriber expiration "
340 "timeout.%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100341
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700342 rc = osmo_tdef_set(msc_tdefs_vlr, 3212, 0, OSMO_TDEF_M);
343 return rc ? CMD_WARNING : CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100344}
345
Keith Whyte991bb422019-08-08 15:43:40 +0200346DEFUN(cfg_net_call_wait, cfg_net_call_wait_cmd,
347 "call-waiting",
348 "Enable Call Waiting on the Network\n")
349{
350 struct gsm_network *net = vty->index;
351
352 net->call_waiting = true;
353
354 return CMD_SUCCESS;
355}
356
357DEFUN(cfg_net_no_call_wait, cfg_net_no_call_wait_cmd,
358 "no call-waiting",
359 NO_STR
360 "Disable Call Waiting on the Network\n")
361{
362 struct gsm_network *net = vty->index;
363
364 net->call_waiting = false;
365
366 return CMD_SUCCESS;
367}
368
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100369static int config_write_net(struct vty *vty)
370{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100371 int i;
372
373 vty_out(vty, "network%s", VTY_NEWLINE);
374 vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
375 vty_out(vty, " mobile network code %s%s",
376 osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
377 vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
378 vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
379 vty_out(vty, " encryption a5");
380 for (i = 0; i < 8; i++) {
381 if (gsmnet->a5_encryption_mask & (1 << i))
382 vty_out(vty, " %u", i);
383 }
384 vty_out(vty, "%s", VTY_NEWLINE);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200385
386 if (!gsmnet->uea_encryption)
387 vty_out(vty, " encryption uea 0%s", VTY_NEWLINE);
388 else
389 vty_out(vty, " encryption uea 1 2%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100390 vty_out(vty, " authentication %s%s",
391 gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE);
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700392 vty_out(vty, " rrlp mode %s%s", msc_rrlp_mode_name(gsmnet->rrlp.mode),
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100393 VTY_NEWLINE);
394 vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
395 if (gsmnet->tz.override != 0) {
396 if (gsmnet->tz.dst)
397 vty_out(vty, " timezone %d %d %d%s",
398 gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
399 VTY_NEWLINE);
400 else
401 vty_out(vty, " timezone %d %d%s",
402 gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
403 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100404
Keith Whyte991bb422019-08-08 15:43:40 +0200405 if (!gsmnet->call_waiting)
406 vty_out(vty, " no call-waiting%s", VTY_NEWLINE);
407
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100408 return CMD_SUCCESS;
409}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200410
411static struct cmd_node msc_node = {
412 MSC_NODE,
413 "%s(config-msc)# ",
414 1,
415};
416
417DEFUN(cfg_msc, cfg_msc_cmd,
418 "msc", "Configure MSC options")
419{
420 vty->node = MSC_NODE;
421 return CMD_SUCCESS;
422}
423
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100424#define MNCC_STR "Configure Mobile Network Call Control\n"
425#define MNCC_GUARD_TIMEOUT_STR "Set global guard timer for mncc interface activity\n"
426#define MNCC_GUARD_TIMEOUT_VALUE_STR "guard timer value (sec.)\n"
427
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100428DEFUN(cfg_msc_mncc_internal,
429 cfg_msc_mncc_internal_cmd,
430 "mncc internal",
431 MNCC_STR "Use internal MNCC handler (default; changes need a program restart)\n")
432{
433 gsm_network_set_mncc_sock_path(gsmnet, NULL);
434 return CMD_SUCCESS;
435}
436
437DEFUN(cfg_msc_mncc_external,
438 cfg_msc_mncc_external_cmd,
439 "mncc external MNCC_SOCKET_PATH",
440 MNCC_STR "Use external MNCC handler (changes need a program restart)\n"
441 "File system path to create the MNCC unix domain socket at\n")
442{
443 gsm_network_set_mncc_sock_path(gsmnet, argv[0]);
444 return CMD_SUCCESS;
445}
446
Philipp Maier9ca7b312018-10-10 17:00:49 +0200447DEFUN(cfg_msc_mncc_guard_timeout,
448 cfg_msc_mncc_guard_timeout_cmd,
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100449 "mncc guard-timeout <0-255>",
450 MNCC_STR
451 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR)
Philipp Maier9ca7b312018-10-10 17:00:49 +0200452{
453 gsmnet->mncc_guard_timeout = atoi(argv[0]);
454 return CMD_SUCCESS;
455}
456
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100457ALIAS_DEPRECATED(cfg_msc_mncc_guard_timeout,
458 cfg_msc_deprecated_mncc_guard_timeout_cmd,
459 "mncc-guard-timeout <0-255>",
460 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR);
461
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700462#define NCSS_STR "Configure call independent Supplementary Services\n"
463
464DEFUN(cfg_msc_ncss_guard_timeout,
465 cfg_msc_ncss_guard_timeout_cmd,
466 "ncss guard-timeout <0-255>",
467 NCSS_STR "Set guard timer for session activity\n"
468 "guard timer value (sec.), or 0 to disable\n")
469{
470 gsmnet->ncss_guard_timeout = atoi(argv[0]);
471 return CMD_SUCCESS;
472}
473
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200474DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
475 "assign-tmsi",
476 "Assign TMSI during Location Updating.\n")
477{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200478 gsmnet->vlr->cfg.assign_tmsi = true;
479 return CMD_SUCCESS;
480}
481
482DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
483 "no assign-tmsi",
484 NO_STR "Assign TMSI during Location Updating.\n")
485{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200486 gsmnet->vlr->cfg.assign_tmsi = false;
487 return CMD_SUCCESS;
488}
489
Philipp Maierfbf66102017-04-09 12:32:51 +0200490DEFUN(cfg_msc_cs7_instance_a,
491 cfg_msc_cs7_instance_a_cmd,
492 "cs7-instance-a <0-15>",
493 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
494{
Philipp Maierfbf66102017-04-09 12:32:51 +0200495 gsmnet->a.cs7_instance = atoi(argv[0]);
496 return CMD_SUCCESS;
497}
498
499DEFUN(cfg_msc_cs7_instance_iu,
500 cfg_msc_cs7_instance_iu_cmd,
501 "cs7-instance-iu <0-15>",
502 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
503{
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100504#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200505 gsmnet->iu.cs7_instance = atoi(argv[0]);
506 return CMD_SUCCESS;
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100507#else
508 vty_out(vty, "WARNING: 'cs7-instance-iu' without effect: built without Iu support%s",
509 VTY_NEWLINE);
510 return CMD_WARNING;
511#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200512}
513
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100514DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
515 "auth-tuple-max-reuse-count <-1-2147483647>",
516 "Configure authentication tuple re-use\n"
517 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
518{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100519 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
520 return CMD_SUCCESS;
521}
522
523DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
524 "auth-tuple-reuse-on-error (0|1)",
525 "Configure authentication tuple re-use when HLR is not responsive\n"
Oliver Smithd6e24fd2019-01-09 10:46:43 +0100526 "Never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
527 "If the HLR does not deliver new tuples, do re-use already available old ones.\n")
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100528{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100529 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
530 return CMD_SUCCESS;
531}
532
Oliver Smith0fec28a2018-12-14 10:52:52 +0100533DEFUN(cfg_msc_check_imei_rqd, cfg_msc_check_imei_rqd_cmd,
Oliver Smith03ded912019-05-02 10:40:50 +0200534 "check-imei-rqd (0|1|early)",
Oliver Smith0fec28a2018-12-14 10:52:52 +0100535 "Send each IMEI to the EIR to ask if it is permitted or not. The EIR is implemented as part of OsmoHLR, "
536 "and can optionally save the IMEI in the HLR.\n"
537 "Do not send IMEIs to the EIR\n"
Oliver Smith03ded912019-05-02 10:40:50 +0200538 "Send each IMEI to the EIR\n"
539 "Send each IMEI to the EIR, and do it at the start of the location update. This allows the EIR to receive the"
540 " 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 +0100541{
Oliver Smith03ded912019-05-02 10:40:50 +0200542 if (strcmp(argv[0], "0") == 0) {
543 gsmnet->vlr->cfg.check_imei_rqd = false;
544 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
545 } else if (strcmp(argv[0], "1") == 0) {
546 gsmnet->vlr->cfg.check_imei_rqd = true;
547 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
548 } else if (strcmp(argv[0], "early") == 0) {
549 gsmnet->vlr->cfg.check_imei_rqd = true;
550 gsmnet->vlr->cfg.retrieve_imeisv_early = true;
551 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100552 return CMD_SUCCESS;
553}
554
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100555DEFUN(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
556 "paging response-timer (default|<1-65535>)",
557 "Configure Paging\n"
558 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
559 " BSS or RNC\n"
560 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
561 "Set paging timeout in seconds\n")
562{
Pau Espin Pedrolb08a3802019-09-16 19:01:37 +0200563 if (!strcmp(argv[0], "default"))
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100564 gsmnet->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
565 else
566 gsmnet->paging_response_timer = atoi(argv[0]);
567 return CMD_SUCCESS;
568}
569
Harald Welte69c54a82018-02-09 20:41:14 +0100570DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
571 "emergency-call route-to-msisdn MSISDN",
572 "Configure Emergency Call Behaviour\n"
573 "MSISDN to which Emergency Calls are Dispatched\n"
574 "MSISDN (E.164 Phone Number)\n")
575{
Harald Welte69c54a82018-02-09 20:41:14 +0100576 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
577
578 return CMD_SUCCESS;
579}
580
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700581/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
582DEFUN(cfg_msc_sms_over_gsup, cfg_msc_sms_over_gsup_cmd,
583 "sms-over-gsup",
584 "Enable routing of SMS messages over GSUP\n")
585{
586 gsmnet->sms_over_gsup = true;
587 return CMD_SUCCESS;
588}
589
590/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
591DEFUN(cfg_msc_no_sms_over_gsup, cfg_msc_no_sms_over_gsup_cmd,
592 "no sms-over-gsup",
593 NO_STR "Disable routing of SMS messages over GSUP\n")
594{
595 gsmnet->sms_over_gsup = false;
596 return CMD_SUCCESS;
597}
598
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100599/* FIXME: This should rather be in the form of
600 * handover-number range 001234xxx
601 * and
602 * handover-number range 001234xxx FIRST LAST
603 */
604DEFUN(cfg_msc_handover_number_range, cfg_msc_handover_number_range_cmd,
605 "handover-number range MSISDN_FIRST MSISDN_LAST",
606 "Configure a range of MSISDN to be assigned to incoming inter-MSC Handovers for call forwarding.\n"
607 "Configure a handover number range\n"
608 "First Handover Number MSISDN\n"
609 "Last Handover Number MSISDN\n")
610{
611 char *endp;
612 uint64_t range_start;
613 uint64_t range_end;
614
615 /* FIXME leading zeros?? */
616
617 errno = 0;
618 range_start = strtoull(argv[0], &endp, 10);
619 if (errno || *endp != '\0') {
620 vty_out(vty, "%% Error parsing handover-number range start: %s%s",
621 argv[0], VTY_NEWLINE);
622 return CMD_WARNING;
623 }
624
625 errno = 0;
626 range_end = strtoull(argv[1], &endp, 10);
627 if (errno || *endp != '\0') {
628 vty_out(vty, "%% Error parsing handover-number range end: %s%s",
629 argv[1], VTY_NEWLINE);
630 return CMD_WARNING;
631 }
632
633 if (range_start > range_end) {
634 vty_out(vty, "%% Error: handover-number range end must be > than the range start, but"
635 " %"PRIu64" > %"PRIu64"%s", range_start, range_end, VTY_NEWLINE);
636 return CMD_WARNING;
637 }
638
639 gsmnet->handover_number.range_start = range_start;
640 gsmnet->handover_number.range_end = range_end;
641 return CMD_SUCCESS;
642}
643
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200644#define OSMUX_STR "RTP multiplexing\n"
645DEFUN(cfg_msc_osmux,
646 cfg_msc_osmux_cmd,
647 "osmux (on|off|only)",
648 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
649{
650 if (strcmp(argv[0], "off") == 0)
651 gsmnet->use_osmux = OSMUX_USAGE_OFF;
652 else if (strcmp(argv[0], "on") == 0)
653 gsmnet->use_osmux = OSMUX_USAGE_ON;
654 else if (strcmp(argv[0], "only") == 0)
655 gsmnet->use_osmux = OSMUX_USAGE_ONLY;
656
657 return CMD_SUCCESS;
658}
659
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200660static int config_write_msc(struct vty *vty)
661{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200662 vty_out(vty, "msc%s", VTY_NEWLINE);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100663 if (gsmnet->mncc_sock_path)
664 vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE);
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100665 vty_out(vty, " mncc guard-timeout %i%s",
Philipp Maier9ca7b312018-10-10 17:00:49 +0200666 gsmnet->mncc_guard_timeout, VTY_NEWLINE);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700667 vty_out(vty, " ncss guard-timeout %i%s",
668 gsmnet->ncss_guard_timeout, VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200669 vty_out(vty, " %sassign-tmsi%s",
670 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
671
Philipp Maierfbf66102017-04-09 12:32:51 +0200672 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
673 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100674#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200675 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
676 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100677#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200678
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100679 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
680 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
681 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
682 VTY_NEWLINE);
683 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
684 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
685 VTY_NEWLINE);
686
Oliver Smith03ded912019-05-02 10:40:50 +0200687 if (gsmnet->vlr->cfg.check_imei_rqd) {
688 if (gsmnet->vlr->cfg.retrieve_imeisv_early)
689 vty_out(vty, " check-imei-rqd early%s", VTY_NEWLINE);
690 else
691 vty_out(vty, " check-imei-rqd 1%s", VTY_NEWLINE);
692 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100693
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100694 if (gsmnet->paging_response_timer != MSC_PAGING_RESPONSE_TIMER_DEFAULT)
695 vty_out(vty, " paging response-timer %u%s", gsmnet->paging_response_timer, VTY_NEWLINE);
696
Harald Welte69c54a82018-02-09 20:41:14 +0100697 if (gsmnet->emergency.route_to_msisdn) {
698 vty_out(vty, " emergency-call route-to-msisdn %s%s",
699 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
700 }
701
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700702 if (gsmnet->sms_over_gsup)
703 vty_out(vty, " sms-over-gsup%s", VTY_NEWLINE);
704
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100705 if (gsmnet->handover_number.range_start || gsmnet->handover_number.range_end)
706 vty_out(vty, " handover-number range %"PRIu64" %"PRIu64"%s",
707 gsmnet->handover_number.range_start, gsmnet->handover_number.range_end,
708 VTY_NEWLINE);
709
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200710 if (gsmnet->use_osmux != OSMUX_USAGE_OFF) {
711 vty_out(vty, " osmux %s%s", gsmnet->use_osmux == OSMUX_USAGE_ON ? "on" : "only",
712 VTY_NEWLINE);
713 }
714
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200715 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200716#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200717 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200718#endif
719
Neels Hofmeyr880b9502019-05-09 02:01:55 +0200720 neighbor_ident_vty_write(vty);
721
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +0700722 /* Timer introspection commands (generic osmo_tdef API) */
723 osmo_tdef_vty_groups_write(vty, " ");
724
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200725 return CMD_SUCCESS;
726}
727
Maxc51609a2018-11-09 17:13:00 +0100728DEFUN(show_bsc, show_bsc_cmd,
729 "show bsc", SHOW_STR "BSC\n")
730{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100731 struct ran_peer *rp;
732 llist_for_each_entry(rp, &gsmnet->a.sri->ran_peers, entry) {
733 vty_out(vty, "BSC %s %s%s",
734 osmo_sccp_inst_addr_name(gsmnet->a.sri->sccp, &rp->peer_addr),
735 osmo_fsm_inst_state_name(rp->fi),
736 VTY_NEWLINE);
Maxc51609a2018-11-09 17:13:00 +0100737 }
738
739 return CMD_SUCCESS;
740}
741
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100742static const char *get_trans_proto_str(const struct gsm_trans *trans)
743{
744 static char buf[256];
745
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100746 switch (trans->type) {
747 case TRANS_CC:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100748 snprintf(buf, sizeof(buf), "%s %4u %4u",
749 gsm48_cc_state_name(trans->cc.state),
750 trans->cc.Tcurrent,
751 trans->cc.T308_second);
752 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100753 case TRANS_SMS:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700754 snprintf(buf, sizeof(buf), "CP:%s RP:%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100755 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
756 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
757 break;
758 default:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700759 return NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100760 }
761
762 return buf;
763}
764
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700765/* Prefix a given format string with a given amount of spaces */
766#define MSC_VTY_DUMP(vty, offset, fmt, args...) \
767 vty_out(vty, "%*s" fmt, offset, "", ##args)
768
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200769/* Print value of a named flag, prefixed with a given amount of spaces */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700770#define MSC_VTY_DUMP_FLAG(vty, offset, name, flag) \
771 MSC_VTY_DUMP(vty, offset + 2, "%s: %*s%s%s", \
772 name, 30 - (int)strlen(name), "", \
773 flag ? "true" : "false", \
774 VTY_NEWLINE)
775
776enum msc_vty_dump_flags {
777 MSC_VTY_DUMP_F_SUBSCR = (1 << 0),
778 MSC_VTY_DUMP_F_CONNECTION = (1 << 1),
779 MSC_VTY_DUMP_F_TRANSACTION = (1 << 2),
780};
781
782static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans,
783 int offset, uint8_t dump_flags)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100784{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700785 const char *proto_str;
786
787 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
788 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
789 vlr_subscr_name(msc_a_vsub(trans->msc_a)),
790 VTY_NEWLINE);
791 }
792
793 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200794 /* (If msc_a exists, there *must* be a non-null msc_a->c.msub) */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700795 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
796 trans->msc_a ? msub_ran_conn_name(trans->msc_a->c.msub)
797 : "(not established)",
798 VTY_NEWLINE);
799 }
800
801 MSC_VTY_DUMP(vty, offset, "Unique (global) identifier: 0x%08x%s",
802 trans->callref, VTY_NEWLINE);
803 MSC_VTY_DUMP(vty, offset, "GSM 04.07 identifier (%s): %u%s",
804 (trans->transaction_id & 0x08) ? "MO" : "MT",
805 trans->transaction_id,
806 VTY_NEWLINE);
807
808 MSC_VTY_DUMP(vty, offset, "Type: %s%s",
809 trans_type_name(trans->type),
810 VTY_NEWLINE);
811
812 if ((proto_str = get_trans_proto_str(trans))) {
813 MSC_VTY_DUMP(vty, offset, "Protocol specific: %s%s",
814 proto_str, VTY_NEWLINE);
815 }
816}
817
818static void vty_dump_one_conn(struct vty *vty, const struct msub *msub,
819 int offset, uint8_t dump_flags)
820{
821 struct vlr_subscr *vsub = msub_vsub(msub);
822 struct msc_a *msc_a = msub_msc_a(msub);
823 char buf[128];
824
825 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
826 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
827 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
828 vlr_subscr_name(vsub),
829 VTY_NEWLINE);
830 }
831
832 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
833 msub_ran_conn_name(msub),
834 VTY_NEWLINE);
835 MSC_VTY_DUMP(vty, offset, "RAN connection state: %s%s",
836 osmo_fsm_inst_state_name(msc_a->c.fi),
837 VTY_NEWLINE);
838
839 if (vsub) {
840 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
841 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
842 VTY_NEWLINE);
843 }
844
845 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
846 osmo_use_count_total(&msc_a->use_count),
847 VTY_NEWLINE);
848 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
849 osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count),
850 VTY_NEWLINE);
851
852 /* Transactions of this connection */
853 if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
854 struct gsm_trans *trans;
855 unsigned int i = 0;
856
857 /* Both subscriber and connection info is already printed */
858 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_CONNECTION;
859 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
860
861 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
862 if (trans->msc_a != msc_a)
863 continue;
864 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
865 i++, VTY_NEWLINE);
866 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
867 }
868 }
869}
870
871static void vty_dump_one_subscr(struct vty *vty, struct vlr_subscr *vsub,
872 int offset, uint8_t dump_flags)
873{
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700874 struct timespec now;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700875 char buf[128];
876
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700877 if (vsub->name[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700878 MSC_VTY_DUMP(vty, offset, "Name: '%s'%s",
879 vsub->name, VTY_NEWLINE);
880 }
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700881 if (vsub->msisdn[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700882 MSC_VTY_DUMP(vty, offset, "MSISDN: %s%s",
883 vsub->msisdn, VTY_NEWLINE);
884 }
885
886 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
887 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
888 VTY_NEWLINE);
889 MSC_VTY_DUMP(vty, offset, "RAN type: %s%s",
890 osmo_rat_type_name(vsub->cs.attached_via_ran),
891 VTY_NEWLINE);
892
893 MSC_VTY_DUMP(vty, offset, "IMSI: %s%s",
894 vsub->imsi, VTY_NEWLINE);
895 if (vsub->tmsi != GSM_RESERVED_TMSI) {
896 MSC_VTY_DUMP(vty, offset, "TMSI: %08X%s",
897 vsub->tmsi, VTY_NEWLINE);
898 }
899 if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
900 MSC_VTY_DUMP(vty, offset, "New TMSI: %08X%s",
901 vsub->tmsi_new, VTY_NEWLINE);
902 }
903 if (vsub->imei[0] != '\0') {
904 MSC_VTY_DUMP(vty, offset, "IMEI: %s%s",
905 vsub->imei, VTY_NEWLINE);
906 }
907 if (vsub->imeisv[0] != '\0') {
908 MSC_VTY_DUMP(vty, offset, "IMEISV: %s%s",
909 vsub->imeisv, VTY_NEWLINE);
910 }
911
912 MSC_VTY_DUMP(vty, offset, "Flags: %s", VTY_NEWLINE);
913 MSC_VTY_DUMP_FLAG(vty, offset, "IMSI detached",
914 vsub->imsi_detached_flag);
915 MSC_VTY_DUMP_FLAG(vty, offset, "Conf. by radio contact",
916 vsub->conf_by_radio_contact_ind);
917 MSC_VTY_DUMP_FLAG(vty, offset, "Subscr. data conf. by HLR",
918 vsub->sub_dataconf_by_hlr_ind);
919 MSC_VTY_DUMP_FLAG(vty, offset, "Location conf. in HLR",
920 vsub->loc_conf_in_hlr_ind);
921 MSC_VTY_DUMP_FLAG(vty, offset, "Subscriber dormant",
922 vsub->dormant_ind);
923 MSC_VTY_DUMP_FLAG(vty, offset, "Received cancel location",
924 vsub->cancel_loc_rx);
925 MSC_VTY_DUMP_FLAG(vty, offset, "MS not reachable",
926 vsub->ms_not_reachable_flag);
927 MSC_VTY_DUMP_FLAG(vty, offset, "LA allowed",
928 vsub->la_allowed);
929
930 if (vsub->last_tuple) {
931 struct vlr_auth_tuple *t = vsub->last_tuple;
932 MSC_VTY_DUMP(vty, offset, "A3A8 last tuple (used %d times): %s",
933 t->use_count, VTY_NEWLINE);
934 MSC_VTY_DUMP(vty, offset + 2, "seq # : %d%s",
935 t->key_seq, VTY_NEWLINE);
936 MSC_VTY_DUMP(vty, offset + 2, "RAND : %s%s",
937 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
938 VTY_NEWLINE);
939 MSC_VTY_DUMP(vty, offset + 2, "SRES : %s%s",
940 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
941 VTY_NEWLINE);
942 MSC_VTY_DUMP(vty, offset + 2, "Kc : %s%s",
943 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
944 VTY_NEWLINE);
945 }
946
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700947 if (!vlr_timer(vsub->vlr, 3212)) {
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700948 MSC_VTY_DUMP(vty, offset, "Expires: never (T3212 is disabled)%s",
949 VTY_NEWLINE);
950 } else if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) {
951 MSC_VTY_DUMP(vty, offset, "Expires: never%s",
952 VTY_NEWLINE);
953 } else if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
954 MSC_VTY_DUMP(vty, offset, "Expires: in %ld min %ld sec%s",
955 (vsub->expire_lu - now.tv_sec) / 60,
956 (vsub->expire_lu - now.tv_sec) % 60,
957 VTY_NEWLINE);
958 }
959
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700960 MSC_VTY_DUMP(vty, offset, "Paging: %s paging for %d requests%s",
961 vsub->cs.is_paging ? "is" : "not",
962 llist_count(&vsub->cs.requests),
963 VTY_NEWLINE);
964
965 /* SGs related */
966 MSC_VTY_DUMP(vty, offset, "SGs-state: %s%s",
967 osmo_fsm_inst_state_name(vsub->sgs_fsm),
968 VTY_NEWLINE);
969 MSC_VTY_DUMP(vty, offset, "SGs-MME: %s%s",
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700970 vsub->sgs.mme_name[0] != '\0' ? vsub->sgs.mme_name : "(none)",
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700971 VTY_NEWLINE);
972
973 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
974 osmo_use_count_total(&vsub->use_count),
975 VTY_NEWLINE);
976 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
977 osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count),
978 VTY_NEWLINE);
979
980 /* Connection(s) and/or transactions of this subscriber */
981 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
982 struct msub *msub = msub_for_vsub(vsub);
983 if (!msub)
984 return;
985
986 /* Subscriber info is already printed */
987 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
988
989 MSC_VTY_DUMP(vty, offset, "Connection: %s", VTY_NEWLINE);
990 vty_dump_one_conn(vty, msub, offset + 2, dump_flags);
991 } else if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
992 struct gsm_trans *trans;
993 unsigned int i = 0;
994
995 /* Subscriber info is already printed */
996 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
997 /* Do not print connection info, but mention it */
998 dump_flags |= MSC_VTY_DUMP_F_CONNECTION;
999
1000 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1001 if (trans->vsub != vsub)
1002 continue;
1003 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
1004 i++, VTY_NEWLINE);
1005 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
1006 }
1007 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001008}
1009
1010DEFUN(show_msc_transaction, show_msc_transaction_cmd,
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001011 "show transaction",
1012 SHOW_STR "Transactions\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001013{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001014 struct gsm_trans *trans;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001015 uint8_t flags = 0x00;
1016 unsigned int i = 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001017
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001018 flags |= MSC_VTY_DUMP_F_CONNECTION;
1019 flags |= MSC_VTY_DUMP_F_SUBSCR;
1020
1021 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1022 vty_out(vty, " Transaction #%02u: %s", i++, VTY_NEWLINE);
1023 vty_dump_one_trans(vty, trans, 4, flags);
1024 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001025
1026 return CMD_SUCCESS;
1027}
1028
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001029DEFUN(show_msc_conn, show_msc_conn_cmd,
1030 "show connection [trans]",
1031 SHOW_STR "Subscriber Connections\n"
1032 "Show child transactions of each connection\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001033{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001034 uint8_t flags = 0x00;
1035 unsigned int i = 0;
1036 struct msub *msub;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001037
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001038 if (argc > 0)
1039 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1040 flags |= MSC_VTY_DUMP_F_SUBSCR;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001041
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001042 llist_for_each_entry(msub, &msub_list, entry) {
1043 vty_out(vty, " Connection #%02u: %s", i++, VTY_NEWLINE);
1044 vty_dump_one_conn(vty, msub, 4, flags);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001045 }
1046
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001047 return CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001048}
1049
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001050#define SUBSCR_FLAGS "[(conn|trans|conn+trans)]"
1051#define SUBSCR_FLAGS_HELP \
1052 "Show child connections\n" \
1053 "Show child transactions\n" \
1054 "Show child connections and transactions\n"
1055
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001056/* Subscriber */
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001057DEFUN(show_subscr_cache, show_subscr_cache_cmd,
1058 "show subscriber cache " SUBSCR_FLAGS,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001059 SHOW_STR "Show information about subscribers\n"
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001060 "Display contents of subscriber cache\n"
1061 SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001062{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001063 struct vlr_subscr *vsub;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001064 unsigned int count = 0;
1065 uint8_t flags = 0x00;
1066 unsigned int i = 0;
1067
1068 if (argc && strcmp(argv[0], "conn") == 0)
1069 flags |= MSC_VTY_DUMP_F_CONNECTION;
1070 else if (argc && strcmp(argv[0], "trans") == 0)
1071 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1072 else if (argc && strcmp(argv[0], "conn+trans") == 0)
1073 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001074
1075 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
1076 if (++count > 100) {
1077 vty_out(vty, "%% More than %d subscribers in cache,"
1078 " stopping here.%s", count-1, VTY_NEWLINE);
1079 break;
1080 }
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001081 vty_out(vty, " Subscriber #%02u: %s", i++, VTY_NEWLINE);
1082 vty_dump_one_subscr(vty, vsub, 4, flags);
Harald Welte69c54a82018-02-09 20:41:14 +01001083 }
1084
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001085 return CMD_SUCCESS;
1086}
1087
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001088DEFUN(sms_send_pend,
1089 sms_send_pend_cmd,
1090 "sms send pending",
1091 "SMS related commands\n" "SMS Sending related commands\n"
1092 "Send all pending SMS")
1093{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001094 struct gsm_sms *sms;
1095 unsigned long long sms_id = 0;
1096
1097 while (1) {
1098 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1099 if (!sms)
1100 break;
1101
1102 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001103 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001104
1105 sms_id = sms->id + 1;
1106 }
1107
1108 return CMD_SUCCESS;
1109}
1110
1111DEFUN(sms_delete_expired,
1112 sms_delete_expired_cmd,
1113 "sms delete expired",
1114 "SMS related commands\n" "SMS Database related commands\n"
1115 "Delete all expired SMS")
1116{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001117 struct gsm_sms *sms;
1118 unsigned long long sms_id = 0;
1119 long long num_deleted = 0;
1120
1121 while (1) {
1122 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1123 if (!sms)
1124 break;
1125
1126 /* Skip SMS which are currently queued for sending. */
1127 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
1128 continue;
1129
1130 /* Expiration check is performed by the DB layer. */
1131 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
1132 num_deleted++;
1133
1134 sms_id = sms->id + 1;
1135 }
1136
1137 if (num_deleted == 0) {
1138 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
1139 return CMD_WARNING;
1140 }
1141
1142 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
1143 return CMD_SUCCESS;
1144}
1145
1146static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +02001147 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001148 char *str, uint8_t tp_pid)
1149{
1150 struct gsm_network *net = receiver->vlr->user_ctx;
1151 struct gsm_sms *sms;
1152
Harald Welte39b55482018-04-09 19:19:33 +02001153 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Vadim Yanitskiydb4839c2019-12-01 18:52:58 +07001154 if (!sms) {
1155 LOGP(DLSMS, LOGL_ERROR, "Failed to allocate SMS\n");
1156 return CMD_WARNING;
1157 }
1158
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001159 sms->protocol_id = tp_pid;
1160
1161 /* store in database for the queue */
1162 if (db_sms_store(sms) != 0) {
1163 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
1164 sms_free(sms);
1165 return CMD_WARNING;
1166 }
1167 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
1168
1169 sms_free(sms);
1170 sms_queue_trigger(net->sms_queue);
1171 return CMD_SUCCESS;
1172}
1173
1174static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
1175 const char *type,
1176 const char *id)
1177{
1178 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001179 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001180 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001181 return vlr_subscr_find_by_imsi(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001182 else if (!strcmp(type, "tmsi"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001183 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id), VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001184
1185 return NULL;
1186}
1187#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
1188#define SUBSCR_HELP "Operations on a Subscriber\n" \
1189 "Identify subscriber by MSISDN (phone number)\n" \
1190 "Legacy alias for 'msisdn'\n" \
1191 "Identify subscriber by IMSI\n" \
1192 "Identify subscriber by TMSI\n" \
Vadim Yanitskiy3ccd8232019-05-16 01:35:23 +07001193 "Legacy alias for 'imsi'\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001194 "Identifier for the subscriber\n"
1195
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001196DEFUN(show_subscr, show_subscr_cmd,
1197 "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
1198 SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001199{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001200 struct vlr_subscr *vsub;
1201 uint8_t flags = 0x00;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001202
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001203 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001204 if (!vsub) {
1205 vty_out(vty, "%% No subscriber found for %s %s%s",
1206 argv[0], argv[1], VTY_NEWLINE);
1207 return CMD_WARNING;
1208 }
1209
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001210 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
1211 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
1212 * 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 +01001213 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001214
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001215 if (argc > 2 && strcmp(argv[2], "conn") == 0)
1216 flags |= MSC_VTY_DUMP_F_CONNECTION;
1217 else if (argc > 2 && strcmp(argv[2], "trans") == 0)
1218 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1219 else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
1220 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
1221
1222 vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
1223 vty_dump_one_subscr(vty, vsub, 4, flags);
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001224
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001225 return CMD_SUCCESS;
1226}
1227
Vadim Yanitskiyb7ddbf32020-01-20 21:30:09 +07001228DEFUN_DEPRECATED(subscriber_create, subscriber_create_cmd,
1229 "subscriber create imsi ID",
1230 "Operations on a Subscriber\n"
1231 "Create new subscriber\n"
1232 "Identify the subscriber by his IMSI\n"
1233 "Identifier for the subscriber\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001234{
1235 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
1236 VTY_NEWLINE);
1237 return CMD_WARNING;
1238}
1239
1240DEFUN(subscriber_send_pending_sms,
1241 subscriber_send_pending_sms_cmd,
1242 "subscriber " SUBSCR_TYPES " ID sms pending-send",
1243 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
1244{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001245 struct vlr_subscr *vsub;
1246 struct gsm_sms *sms;
1247
1248 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1249 if (!vsub) {
1250 vty_out(vty, "%% No subscriber found for %s %s%s",
1251 argv[0], argv[1], VTY_NEWLINE);
1252 return CMD_WARNING;
1253 }
1254
1255 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
1256 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001257 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001258
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001259 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001260
1261 return CMD_SUCCESS;
1262}
1263
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001264DEFUN(subscriber_sms_delete_all,
1265 subscriber_sms_delete_all_cmd,
1266 "subscriber " SUBSCR_TYPES " ID sms delete-all",
1267 SUBSCR_HELP "SMS Operations\n"
1268 "Delete all SMS to be delivered to this subscriber"
1269 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
1270 " WILL BE LOST.\n")
1271{
1272 struct vlr_subscr *vsub;
1273
1274 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1275 if (!vsub) {
1276 vty_out(vty, "%% No subscriber found for %s %s%s",
1277 argv[0], argv[1], VTY_NEWLINE);
1278 return CMD_WARNING;
1279 }
1280
1281 db_sms_delete_by_msisdn(vsub->msisdn);
1282
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001283 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001284
1285 return CMD_SUCCESS;
1286}
1287
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001288DEFUN(subscriber_send_sms,
1289 subscriber_send_sms_cmd,
1290 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1291 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1292{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001293 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001294 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001295 char *str;
1296 int rc;
1297
1298 if (!vsub) {
1299 vty_out(vty, "%% No subscriber found for %s %s%s",
1300 argv[0], argv[1], VTY_NEWLINE);
1301 rc = CMD_WARNING;
1302 goto err;
1303 }
1304
Harald Welte39b55482018-04-09 19:19:33 +02001305 if (!strcmp(argv[2], "msisdn"))
1306 sender_msisdn = argv[3];
1307 else {
1308 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1309 if (!sender) {
1310 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1311 rc = CMD_WARNING;
1312 goto err;
1313 }
1314 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001315 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001316 }
1317
1318 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001319 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001320 talloc_free(str);
1321
1322err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001323 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001324 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001325
1326 return rc;
1327}
1328
1329DEFUN(subscriber_silent_sms,
1330 subscriber_silent_sms_cmd,
1331
1332 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1333 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1334{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001335 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001336 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001337 char *str;
1338 int rc;
1339
1340 if (!vsub) {
1341 vty_out(vty, "%% No subscriber found for %s %s%s",
1342 argv[0], argv[1], VTY_NEWLINE);
1343 rc = CMD_WARNING;
1344 goto err;
1345 }
1346
Harald Welte39b55482018-04-09 19:19:33 +02001347 if (!strcmp(argv[2], "msisdn")) {
1348 sender_msisdn = argv[3];
1349 } else {
1350 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1351 if (!sender) {
1352 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1353 rc = CMD_WARNING;
1354 goto err;
1355 }
1356 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001357 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001358 }
1359
1360 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001361 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001362 talloc_free(str);
1363
1364err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001365 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001366 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001367
1368 return rc;
1369}
1370
Sylvain Munaut93558302019-02-14 20:13:08 +01001371#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001372#define CHAN_TYPE_HELP \
1373 "Any channel\n" \
1374 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001375 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001376 "Any TCH channel\n" \
1377 "SDCCH channel\n"
1378
Sylvain Munaut93558302019-02-14 20:13:08 +01001379#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1380#define CHAN_MODE_HELP \
1381 "Signalling only\n" \
1382 "Speech with HR codec\n" \
1383 "Speech with FR codec\n" \
1384 "Speech with EFR codec\n" \
1385 "Speech with AMR codec\n"
1386
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001387DEFUN(subscriber_silent_call_start,
1388 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001389 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001390 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001391 CHAN_TYPE_HELP CHAN_MODE_HELP
1392 "Target IP for RTP traffic (default 127.0.0.1)\n"
1393 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001394{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001395 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001396 struct gsm0808_channel_type ct;
1397 const char *ip;
1398 uint16_t port;
1399 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001400
1401 if (!vsub) {
1402 vty_out(vty, "%% No subscriber found for %s %s%s",
1403 argv[0], argv[1], VTY_NEWLINE);
1404 return CMD_WARNING;
1405 }
1406
Sylvain Munaut93558302019-02-14 20:13:08 +01001407 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001408
Sylvain Munaut93558302019-02-14 20:13:08 +01001409 if (!strcmp(argv[3], "signalling")) {
1410 ct.ch_indctr = GSM0808_CHAN_SIGN;
1411 ct.perm_spch[0] = 0; /* Spare but required */
1412 ct.perm_spch_len = 1;
1413 } else if (!strcmp(argv[3], "speech-hr")) {
1414 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1415 ct.perm_spch[0] = GSM0808_PERM_HR1;
1416 ct.perm_spch_len = 1;
1417 } else if (!strcmp(argv[3], "speech-fr")) {
1418 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1419 ct.perm_spch[0] = GSM0808_PERM_FR1;
1420 ct.perm_spch_len = 1;
1421 } else if (!strcmp(argv[3], "speech-efr")) {
1422 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1423 ct.perm_spch[0] = GSM0808_PERM_FR2;
1424 ct.perm_spch_len = 1;
1425 } else if (!strcmp(argv[3], "speech-amr")) {
1426 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1427 ct.perm_spch[0] = GSM0808_PERM_FR3;
1428 ct.perm_spch[1] = GSM0808_PERM_HR3;
1429 ct.perm_spch_len = 2;
1430 }
1431
1432 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1433
1434 if (!strcmp(argv[2], "tch/f"))
1435 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1436 else if (!strcmp(argv[2], "tch/h"))
1437 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1438 else if (!strcmp(argv[2], "tch/any"))
1439 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1440 else if (!strcmp(argv[2], "sdcch")) {
1441 if (speech) {
1442 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1443 return CMD_WARNING;
1444 }
1445 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1446 } else
1447 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1448
1449 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1450 port = argc >= 6 ? atoi(argv[5]) : 4000;
1451
1452 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001453 switch (rc) {
1454 case -ENODEV:
1455 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1456 break;
1457 default:
1458 if (rc)
1459 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1460 else
1461 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1462 break;
1463 }
1464
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001465 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001466 return rc ? CMD_WARNING : CMD_SUCCESS;
1467}
1468
1469DEFUN(subscriber_silent_call_stop,
1470 subscriber_silent_call_stop_cmd,
1471 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1472 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1473 CHAN_TYPE_HELP)
1474{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001475 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1476 int rc;
1477
1478 if (!vsub) {
1479 vty_out(vty, "%% No subscriber found for %s %s%s",
1480 argv[0], argv[1], VTY_NEWLINE);
1481 return CMD_WARNING;
1482 }
1483
1484 rc = gsm_silent_call_stop(vsub);
1485 switch (rc) {
1486 case -ENODEV:
1487 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1488 break;
1489 case -ENOENT:
1490 vty_out(vty, "%% Subscriber has no silent call active%s",
1491 VTY_NEWLINE);
1492 break;
1493 default:
1494 if (rc)
1495 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1496 else
1497 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1498 break;
1499 }
1500
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001501 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001502 return rc ? CMD_WARNING : CMD_SUCCESS;
1503}
1504
1505DEFUN(subscriber_ussd_notify,
1506 subscriber_ussd_notify_cmd,
1507 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1508 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1509 "Alerting Level 0\n"
1510 "Alerting Level 1\n"
1511 "Alerting Level 2\n"
1512 "Text of USSD message to send\n")
1513{
1514 char *text;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001515 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001516 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1517 int level;
1518
1519 if (!vsub) {
1520 vty_out(vty, "%% No subscriber found for %s %s%s",
1521 argv[0], argv[1], VTY_NEWLINE);
1522 return CMD_WARNING;
1523 }
1524
1525 level = atoi(argv[2]);
1526 text = argv_concat(argv, argc, 3);
1527 if (!text) {
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001528 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001529 return CMD_WARNING;
1530 }
1531
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001532 msc_a = msc_a_for_vsub(vsub, true);
1533 if (!msc_a || msc_a->c.remote_to) {
1534 vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001535 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001536 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001537 talloc_free(text);
1538 return CMD_WARNING;
1539 }
1540
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001541 msc_send_ussd_notify(msc_a, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001542 /* FIXME: since we don't allocate a transaction here,
1543 * we use dummy GSM 04.07 transaction ID. */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001544 msc_send_ussd_release_complete(msc_a, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001545
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001546 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001547 talloc_free(text);
1548 return CMD_SUCCESS;
1549}
1550
1551DEFUN(subscriber_paging,
1552 subscriber_paging_cmd,
1553 "subscriber " SUBSCR_TYPES " ID paging",
1554 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1555{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001556 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001557 struct paging_request *req;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001558
1559 if (!vsub) {
1560 vty_out(vty, "%% No subscriber found for %s %s%s",
1561 argv[0], argv[1], VTY_NEWLINE);
1562 return CMD_WARNING;
1563 }
1564
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001565 req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL,
1566 NULL, NULL, "manual Paging from VTY");
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001567 if (req)
1568 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1569 else
1570 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1571
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001572 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001573 return req ? CMD_SUCCESS : CMD_WARNING;
1574}
1575
1576static int loop_by_char(uint8_t ch)
1577{
1578 switch (ch) {
1579 case 'a':
1580 return GSM414_LOOP_A;
1581 case 'b':
1582 return GSM414_LOOP_B;
1583 case 'c':
1584 return GSM414_LOOP_C;
1585 case 'd':
1586 return GSM414_LOOP_D;
1587 case 'e':
1588 return GSM414_LOOP_E;
1589 case 'f':
1590 return GSM414_LOOP_F;
1591 case 'i':
1592 return GSM414_LOOP_I;
1593 }
1594 return -1;
1595}
1596
1597DEFUN(subscriber_mstest_close,
1598 subscriber_mstest_close_cmd,
1599 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1600 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1601 "Close a TCH Loop inside the MS\n"
1602 "Loop Type A\n"
1603 "Loop Type B\n"
1604 "Loop Type C\n"
1605 "Loop Type D\n"
1606 "Loop Type E\n"
1607 "Loop Type F\n"
1608 "Loop Type I\n")
1609{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001610 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001611 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1612 const char *loop_str;
1613 int loop_mode;
1614
1615 if (!vsub) {
1616 vty_out(vty, "%% No subscriber found for %s %s%s",
1617 argv[0], argv[1], VTY_NEWLINE);
1618 return CMD_WARNING;
1619 }
1620
1621 loop_str = argv[2];
1622 loop_mode = loop_by_char(loop_str[0]);
1623
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001624 msc_a = msc_a_for_vsub(vsub, true);
1625 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001626 vty_out(vty, "%% An active connection is required for %s %s%s",
1627 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001628 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001629 return CMD_WARNING;
1630 }
1631
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001632 gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001633
1634 return CMD_SUCCESS;
1635}
1636
1637DEFUN(subscriber_mstest_open,
1638 subscriber_mstest_open_cmd,
1639 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1640 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1641 "Open a TCH Loop inside the MS\n")
1642{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001643 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001644 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1645
1646 if (!vsub) {
1647 vty_out(vty, "%% No subscriber found for %s %s%s",
1648 argv[0], argv[1], VTY_NEWLINE);
1649 return CMD_WARNING;
1650 }
1651
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001652 msc_a = msc_a_for_vsub(vsub, true);
1653 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001654 vty_out(vty, "%% An active connection is required for %s %s%s",
1655 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001656 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001657 return CMD_WARNING;
1658 }
1659
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001660 gsm0414_tx_open_loop_cmd(msc_a);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001661
1662 return CMD_SUCCESS;
1663}
1664
1665DEFUN(ena_subscr_expire,
1666 ena_subscr_expire_cmd,
1667 "subscriber " SUBSCR_TYPES " ID expire",
1668 SUBSCR_HELP "Expire the subscriber Now\n")
1669{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001670 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1671 argv[1]);
1672
1673 if (!vsub) {
1674 vty_out(vty, "%% No subscriber found for %s %s%s",
1675 argv[0], argv[1], VTY_NEWLINE);
1676 return CMD_WARNING;
1677 }
1678
1679 if (vlr_subscr_expire(vsub))
1680 vty_out(vty, "%% VLR released subscriber %s%s",
1681 vlr_subscr_name(vsub), VTY_NEWLINE);
1682
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001683 if (osmo_use_count_total(&vsub->use_count) > 1)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001684 vty_out(vty, "%% Subscriber %s is still in use,"
1685 " should be released soon%s",
1686 vlr_subscr_name(vsub), VTY_NEWLINE);
1687
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001688 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001689 return CMD_SUCCESS;
1690}
1691
1692static int scall_cbfn(unsigned int subsys, unsigned int signal,
1693 void *handler_data, void *signal_data)
1694{
1695 struct scall_signal_data *sigdata = signal_data;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001696 struct vty *vty = sigdata->vty;
1697
1698 if (!vty_is_active(vty))
1699 return 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001700
1701 switch (signal) {
1702 case S_SCALL_SUCCESS:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001703 vty_out(vty, "%% Silent call success%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001704 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001705 case S_SCALL_FAILED:
1706 vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE);
1707 break;
1708 case S_SCALL_DETACHED:
1709 vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001710 break;
1711 }
1712 return 0;
1713}
1714
1715DEFUN(show_stats,
1716 show_stats_cmd,
1717 "show statistics",
1718 SHOW_STR "Display network statistics\n")
1719{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001720 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001721 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1722 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1723 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001724 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001725 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001726 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001727 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001728 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001729 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1730 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001731 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001732 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001733 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1734 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001735 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001736 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001737 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1738 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1739 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001740 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001741 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001742 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1743 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001744 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001745 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001746 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1747 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001748 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001749 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001750 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current,
1751 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1752 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current
1753 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1754 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001755 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001756 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current,
1757 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1758 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current
1759 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1760 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001761 return CMD_SUCCESS;
1762}
1763
1764DEFUN(show_smsqueue,
1765 show_smsqueue_cmd,
1766 "show sms-queue",
1767 SHOW_STR "Display SMSqueue statistics\n")
1768{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001769 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001770 return CMD_SUCCESS;
1771}
1772
1773DEFUN(smsqueue_trigger,
1774 smsqueue_trigger_cmd,
1775 "sms-queue trigger",
1776 "SMS Queue\n" "Trigger sending messages\n")
1777{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001778 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001779 return CMD_SUCCESS;
1780}
1781
1782DEFUN(smsqueue_max,
1783 smsqueue_max_cmd,
1784 "sms-queue max-pending <1-500>",
1785 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1786{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001787 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001788 return CMD_SUCCESS;
1789}
1790
1791DEFUN(smsqueue_clear,
1792 smsqueue_clear_cmd,
1793 "sms-queue clear",
1794 "SMS Queue\n" "Clear the queue of pending SMS\n")
1795{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001796 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001797 return CMD_SUCCESS;
1798}
1799
1800DEFUN(smsqueue_fail,
1801 smsqueue_fail_cmd,
1802 "sms-queue max-failure <1-500>",
1803 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1804{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001805 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001806 return CMD_SUCCESS;
1807}
1808
1809
1810DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1811 "mncc-int", "Configure internal MNCC handler")
1812{
1813 vty->node = MNCC_INT_NODE;
1814
1815 return CMD_SUCCESS;
1816}
1817
1818static struct cmd_node mncc_int_node = {
1819 MNCC_INT_NODE,
1820 "%s(config-mncc-int)# ",
1821 1,
1822};
1823
1824static const struct value_string tchf_codec_names[] = {
1825 { GSM48_CMODE_SPEECH_V1, "fr" },
1826 { GSM48_CMODE_SPEECH_EFR, "efr" },
1827 { GSM48_CMODE_SPEECH_AMR, "amr" },
1828 { 0, NULL }
1829};
1830
1831static const struct value_string tchh_codec_names[] = {
1832 { GSM48_CMODE_SPEECH_V1, "hr" },
1833 { GSM48_CMODE_SPEECH_AMR, "amr" },
1834 { 0, NULL }
1835};
1836
1837static int config_write_mncc_int(struct vty *vty)
1838{
1839 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1840 vty_out(vty, " default-codec tch-f %s%s",
1841 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1842 VTY_NEWLINE);
1843 vty_out(vty, " default-codec tch-h %s%s",
1844 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1845 VTY_NEWLINE);
1846
1847 return CMD_SUCCESS;
1848}
1849
1850DEFUN(mnccint_def_codec_f,
1851 mnccint_def_codec_f_cmd,
1852 "default-codec tch-f (fr|efr|amr)",
1853 "Set default codec\n" "Codec for TCH/F\n"
1854 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1855{
1856 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1857
1858 return CMD_SUCCESS;
1859}
1860
1861DEFUN(mnccint_def_codec_h,
1862 mnccint_def_codec_h_cmd,
1863 "default-codec tch-h (hr|amr)",
1864 "Set default codec\n" "Codec for TCH/H\n"
1865 "Half-Rate\n" "Adaptive Multi-Rate\n")
1866{
1867 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1868
1869 return CMD_SUCCESS;
1870}
1871
1872
1873DEFUN(logging_fltr_imsi,
1874 logging_fltr_imsi_cmd,
1875 "logging filter imsi IMSI",
1876 LOGGING_STR FILTER_STR
1877 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1878{
1879 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001880 struct log_target *tgt = osmo_log_vty2tgt(vty);
1881 const char *imsi = argv[0];
1882
1883 if (!tgt)
1884 return CMD_WARNING;
1885
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001886 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001887
1888 if (!vlr_subscr) {
1889 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1890 argv[0], VTY_NEWLINE);
1891 return CMD_WARNING;
1892 }
1893
1894 log_set_filter_vlr_subscr(tgt, vlr_subscr);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001895 vlr_subscr_put(vlr_subscr, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001896 return CMD_SUCCESS;
1897}
1898
1899static struct cmd_node hlr_node = {
1900 HLR_NODE,
1901 "%s(config-hlr)# ",
1902 1,
1903};
1904
1905DEFUN(cfg_hlr, cfg_hlr_cmd,
1906 "hlr", "Configure connection to the HLR")
1907{
1908 vty->node = HLR_NODE;
1909 return CMD_SUCCESS;
1910}
1911
1912DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1913 "Remote GSUP address of the HLR\n"
1914 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1915{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001916 talloc_free((void*)gsmnet->gsup_server_addr_str);
1917 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1918 return CMD_SUCCESS;
1919}
1920
1921DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1922 "Remote GSUP port of the HLR\n"
1923 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1924{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001925 gsmnet->gsup_server_port = atoi(argv[0]);
1926 return CMD_SUCCESS;
1927}
1928
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001929DEFUN(cfg_hlr_ipa_name,
1930 cfg_hlr_ipa_name_cmd,
1931 "ipa-name NAME",
1932 "Set the IPA name of this MSC\n"
1933 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1934 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
1935 "The default is 'MSC-00-00-00-00-00-00'.\n")
1936{
1937 if (vty->type != VTY_FILE) {
1938 vty_out(vty, "The IPA name cannot be changed at run-time; "
Martin Hauke3f07dac2019-11-14 17:49:08 +01001939 "It can only be set in the configuration file.%s", VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001940 return CMD_WARNING;
1941 }
1942
1943 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
1944 return CMD_SUCCESS;
1945}
1946
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001947static int config_write_hlr(struct vty *vty)
1948{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001949 vty_out(vty, "hlr%s", VTY_NEWLINE);
1950 vty_out(vty, " remote-ip %s%s",
1951 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1952 vty_out(vty, " remote-port %u%s",
1953 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001954 if (gsmnet->msc_ipa_name)
1955 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001956 return CMD_SUCCESS;
1957}
1958
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001959void msc_vty_init(struct gsm_network *msc_network)
1960{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001961 OSMO_ASSERT(gsmnet == NULL);
1962 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001963
1964 osmo_stats_vty_add_cmds();
1965
1966 install_element(CONFIG_NODE, &cfg_net_cmd);
1967 install_node(&net_node, config_write_net);
1968 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1969 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1970 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1971 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1972 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +02001973 install_element(GSMNET_NODE, &cfg_net_encryption_uea_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001974 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1975 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1976 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1977 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1978 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1979 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1980 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1981 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Keith Whyte991bb422019-08-08 15:43:40 +02001982 install_element(GSMNET_NODE, &cfg_net_call_wait_cmd);
1983 install_element(GSMNET_NODE, &cfg_net_no_call_wait_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001984
1985 install_element(CONFIG_NODE, &cfg_msc_cmd);
1986 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001987 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01001988 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
1989 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02001990 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01001991 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07001992 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001993 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001994 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
1995 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01001996 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001997 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
1998 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01001999 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01002000 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07002001 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
2002 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +02002003 install_element(MSC_NODE, &cfg_msc_osmux_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002004 install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd);
2005
2006 neighbor_ident_vty_init(msc_network);
Philipp Maierfbf66102017-04-09 12:32:51 +02002007
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +07002008 /* Timer configuration commands (generic osmo_tdef API) */
2009 osmo_tdef_vty_groups_init(MSC_NODE, msc_tdef_group);
2010
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02002011 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002012#ifdef BUILD_IU
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002013 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 +02002014#endif
Harald Welte0df904d2018-12-03 11:00:04 +01002015 sgs_vty_init();
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002016
Stefan Sperling617ac802018-02-22 17:58:20 +01002017 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002018
2019 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
2020
2021 install_element_ve(&show_subscr_cmd);
2022 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01002023 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002024 install_element_ve(&show_msc_conn_cmd);
2025 install_element_ve(&show_msc_transaction_cmd);
2026
2027 install_element_ve(&sms_send_pend_cmd);
2028 install_element_ve(&sms_delete_expired_cmd);
2029
2030 install_element_ve(&subscriber_create_cmd);
2031 install_element_ve(&subscriber_send_sms_cmd);
2032 install_element_ve(&subscriber_silent_sms_cmd);
2033 install_element_ve(&subscriber_silent_call_start_cmd);
2034 install_element_ve(&subscriber_silent_call_stop_cmd);
2035 install_element_ve(&subscriber_ussd_notify_cmd);
2036 install_element_ve(&subscriber_mstest_close_cmd);
2037 install_element_ve(&subscriber_mstest_open_cmd);
2038 install_element_ve(&subscriber_paging_cmd);
2039 install_element_ve(&show_stats_cmd);
2040 install_element_ve(&show_smsqueue_cmd);
2041 install_element_ve(&logging_fltr_imsi_cmd);
2042
2043 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
2044 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
2045 install_element(ENABLE_NODE, &smsqueue_max_cmd);
2046 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
2047 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
2048 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01002049 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002050
2051 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
2052 install_node(&mncc_int_node, config_write_mncc_int);
2053 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
2054 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
2055
2056 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
2057
2058 install_element(CONFIG_NODE, &cfg_hlr_cmd);
2059 install_node(&hlr_node, config_write_hlr);
2060 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
2061 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002062 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002063}