blob: a629b5cb7d15bc99f0a5a6789e50457d4bb47939 [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
405 if (gsmnet->emergency.route_to_msisdn) {
406 vty_out(vty, " emergency-call route-to-msisdn %s%s",
407 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
408 }
409
Keith Whyte991bb422019-08-08 15:43:40 +0200410 if (!gsmnet->call_waiting)
411 vty_out(vty, " no call-waiting%s", VTY_NEWLINE);
412
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100413 return CMD_SUCCESS;
414}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200415
416static struct cmd_node msc_node = {
417 MSC_NODE,
418 "%s(config-msc)# ",
419 1,
420};
421
422DEFUN(cfg_msc, cfg_msc_cmd,
423 "msc", "Configure MSC options")
424{
425 vty->node = MSC_NODE;
426 return CMD_SUCCESS;
427}
428
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100429#define MNCC_STR "Configure Mobile Network Call Control\n"
430#define MNCC_GUARD_TIMEOUT_STR "Set global guard timer for mncc interface activity\n"
431#define MNCC_GUARD_TIMEOUT_VALUE_STR "guard timer value (sec.)\n"
432
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100433DEFUN(cfg_msc_mncc_internal,
434 cfg_msc_mncc_internal_cmd,
435 "mncc internal",
436 MNCC_STR "Use internal MNCC handler (default; changes need a program restart)\n")
437{
438 gsm_network_set_mncc_sock_path(gsmnet, NULL);
439 return CMD_SUCCESS;
440}
441
442DEFUN(cfg_msc_mncc_external,
443 cfg_msc_mncc_external_cmd,
444 "mncc external MNCC_SOCKET_PATH",
445 MNCC_STR "Use external MNCC handler (changes need a program restart)\n"
446 "File system path to create the MNCC unix domain socket at\n")
447{
448 gsm_network_set_mncc_sock_path(gsmnet, argv[0]);
449 return CMD_SUCCESS;
450}
451
Philipp Maier9ca7b312018-10-10 17:00:49 +0200452DEFUN(cfg_msc_mncc_guard_timeout,
453 cfg_msc_mncc_guard_timeout_cmd,
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100454 "mncc guard-timeout <0-255>",
455 MNCC_STR
456 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR)
Philipp Maier9ca7b312018-10-10 17:00:49 +0200457{
458 gsmnet->mncc_guard_timeout = atoi(argv[0]);
459 return CMD_SUCCESS;
460}
461
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100462ALIAS_DEPRECATED(cfg_msc_mncc_guard_timeout,
463 cfg_msc_deprecated_mncc_guard_timeout_cmd,
464 "mncc-guard-timeout <0-255>",
465 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR);
466
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700467#define NCSS_STR "Configure call independent Supplementary Services\n"
468
469DEFUN(cfg_msc_ncss_guard_timeout,
470 cfg_msc_ncss_guard_timeout_cmd,
471 "ncss guard-timeout <0-255>",
472 NCSS_STR "Set guard timer for session activity\n"
473 "guard timer value (sec.), or 0 to disable\n")
474{
475 gsmnet->ncss_guard_timeout = atoi(argv[0]);
476 return CMD_SUCCESS;
477}
478
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200479DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
480 "assign-tmsi",
481 "Assign TMSI during Location Updating.\n")
482{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200483 gsmnet->vlr->cfg.assign_tmsi = true;
484 return CMD_SUCCESS;
485}
486
487DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
488 "no assign-tmsi",
489 NO_STR "Assign TMSI during Location Updating.\n")
490{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200491 gsmnet->vlr->cfg.assign_tmsi = false;
492 return CMD_SUCCESS;
493}
494
Philipp Maierfbf66102017-04-09 12:32:51 +0200495DEFUN(cfg_msc_cs7_instance_a,
496 cfg_msc_cs7_instance_a_cmd,
497 "cs7-instance-a <0-15>",
498 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
499{
Philipp Maierfbf66102017-04-09 12:32:51 +0200500 gsmnet->a.cs7_instance = atoi(argv[0]);
501 return CMD_SUCCESS;
502}
503
504DEFUN(cfg_msc_cs7_instance_iu,
505 cfg_msc_cs7_instance_iu_cmd,
506 "cs7-instance-iu <0-15>",
507 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
508{
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100509#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200510 gsmnet->iu.cs7_instance = atoi(argv[0]);
511 return CMD_SUCCESS;
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100512#else
513 vty_out(vty, "WARNING: 'cs7-instance-iu' without effect: built without Iu support%s",
514 VTY_NEWLINE);
515 return CMD_WARNING;
516#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200517}
518
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100519DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
520 "auth-tuple-max-reuse-count <-1-2147483647>",
521 "Configure authentication tuple re-use\n"
522 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
523{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100524 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
525 return CMD_SUCCESS;
526}
527
528DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
529 "auth-tuple-reuse-on-error (0|1)",
530 "Configure authentication tuple re-use when HLR is not responsive\n"
Oliver Smithd6e24fd2019-01-09 10:46:43 +0100531 "Never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
532 "If the HLR does not deliver new tuples, do re-use already available old ones.\n")
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100533{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100534 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
535 return CMD_SUCCESS;
536}
537
Oliver Smith0fec28a2018-12-14 10:52:52 +0100538DEFUN(cfg_msc_check_imei_rqd, cfg_msc_check_imei_rqd_cmd,
Oliver Smith03ded912019-05-02 10:40:50 +0200539 "check-imei-rqd (0|1|early)",
Oliver Smith0fec28a2018-12-14 10:52:52 +0100540 "Send each IMEI to the EIR to ask if it is permitted or not. The EIR is implemented as part of OsmoHLR, "
541 "and can optionally save the IMEI in the HLR.\n"
542 "Do not send IMEIs to the EIR\n"
Oliver Smith03ded912019-05-02 10:40:50 +0200543 "Send each IMEI to the EIR\n"
544 "Send each IMEI to the EIR, and do it at the start of the location update. This allows the EIR to receive the"
545 " 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 +0100546{
Oliver Smith03ded912019-05-02 10:40:50 +0200547 if (strcmp(argv[0], "0") == 0) {
548 gsmnet->vlr->cfg.check_imei_rqd = false;
549 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
550 } else if (strcmp(argv[0], "1") == 0) {
551 gsmnet->vlr->cfg.check_imei_rqd = true;
552 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
553 } else if (strcmp(argv[0], "early") == 0) {
554 gsmnet->vlr->cfg.check_imei_rqd = true;
555 gsmnet->vlr->cfg.retrieve_imeisv_early = true;
556 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100557 return CMD_SUCCESS;
558}
559
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100560DEFUN(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
561 "paging response-timer (default|<1-65535>)",
562 "Configure Paging\n"
563 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
564 " BSS or RNC\n"
565 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
566 "Set paging timeout in seconds\n")
567{
Pau Espin Pedrolb08a3802019-09-16 19:01:37 +0200568 if (!strcmp(argv[0], "default"))
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100569 gsmnet->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
570 else
571 gsmnet->paging_response_timer = atoi(argv[0]);
572 return CMD_SUCCESS;
573}
574
Harald Welte69c54a82018-02-09 20:41:14 +0100575DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
576 "emergency-call route-to-msisdn MSISDN",
577 "Configure Emergency Call Behaviour\n"
578 "MSISDN to which Emergency Calls are Dispatched\n"
579 "MSISDN (E.164 Phone Number)\n")
580{
Harald Welte69c54a82018-02-09 20:41:14 +0100581 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
582
583 return CMD_SUCCESS;
584}
585
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700586/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
587DEFUN(cfg_msc_sms_over_gsup, cfg_msc_sms_over_gsup_cmd,
588 "sms-over-gsup",
589 "Enable routing of SMS messages over GSUP\n")
590{
591 gsmnet->sms_over_gsup = true;
592 return CMD_SUCCESS;
593}
594
595/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
596DEFUN(cfg_msc_no_sms_over_gsup, cfg_msc_no_sms_over_gsup_cmd,
597 "no sms-over-gsup",
598 NO_STR "Disable routing of SMS messages over GSUP\n")
599{
600 gsmnet->sms_over_gsup = false;
601 return CMD_SUCCESS;
602}
603
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100604/* FIXME: This should rather be in the form of
605 * handover-number range 001234xxx
606 * and
607 * handover-number range 001234xxx FIRST LAST
608 */
609DEFUN(cfg_msc_handover_number_range, cfg_msc_handover_number_range_cmd,
610 "handover-number range MSISDN_FIRST MSISDN_LAST",
611 "Configure a range of MSISDN to be assigned to incoming inter-MSC Handovers for call forwarding.\n"
612 "Configure a handover number range\n"
613 "First Handover Number MSISDN\n"
614 "Last Handover Number MSISDN\n")
615{
616 char *endp;
617 uint64_t range_start;
618 uint64_t range_end;
619
620 /* FIXME leading zeros?? */
621
622 errno = 0;
623 range_start = strtoull(argv[0], &endp, 10);
624 if (errno || *endp != '\0') {
625 vty_out(vty, "%% Error parsing handover-number range start: %s%s",
626 argv[0], VTY_NEWLINE);
627 return CMD_WARNING;
628 }
629
630 errno = 0;
631 range_end = strtoull(argv[1], &endp, 10);
632 if (errno || *endp != '\0') {
633 vty_out(vty, "%% Error parsing handover-number range end: %s%s",
634 argv[1], VTY_NEWLINE);
635 return CMD_WARNING;
636 }
637
638 if (range_start > range_end) {
639 vty_out(vty, "%% Error: handover-number range end must be > than the range start, but"
640 " %"PRIu64" > %"PRIu64"%s", range_start, range_end, VTY_NEWLINE);
641 return CMD_WARNING;
642 }
643
644 gsmnet->handover_number.range_start = range_start;
645 gsmnet->handover_number.range_end = range_end;
646 return CMD_SUCCESS;
647}
648
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200649#define OSMUX_STR "RTP multiplexing\n"
650DEFUN(cfg_msc_osmux,
651 cfg_msc_osmux_cmd,
652 "osmux (on|off|only)",
653 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
654{
655 if (strcmp(argv[0], "off") == 0)
656 gsmnet->use_osmux = OSMUX_USAGE_OFF;
657 else if (strcmp(argv[0], "on") == 0)
658 gsmnet->use_osmux = OSMUX_USAGE_ON;
659 else if (strcmp(argv[0], "only") == 0)
660 gsmnet->use_osmux = OSMUX_USAGE_ONLY;
661
662 return CMD_SUCCESS;
663}
664
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200665static int config_write_msc(struct vty *vty)
666{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200667 vty_out(vty, "msc%s", VTY_NEWLINE);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100668 if (gsmnet->mncc_sock_path)
669 vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE);
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100670 vty_out(vty, " mncc guard-timeout %i%s",
Philipp Maier9ca7b312018-10-10 17:00:49 +0200671 gsmnet->mncc_guard_timeout, VTY_NEWLINE);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700672 vty_out(vty, " ncss guard-timeout %i%s",
673 gsmnet->ncss_guard_timeout, VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200674 vty_out(vty, " %sassign-tmsi%s",
675 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
676
Philipp Maierfbf66102017-04-09 12:32:51 +0200677 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
678 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100679#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200680 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
681 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100682#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200683
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100684 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
685 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
686 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
687 VTY_NEWLINE);
688 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
689 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
690 VTY_NEWLINE);
691
Oliver Smith03ded912019-05-02 10:40:50 +0200692 if (gsmnet->vlr->cfg.check_imei_rqd) {
693 if (gsmnet->vlr->cfg.retrieve_imeisv_early)
694 vty_out(vty, " check-imei-rqd early%s", VTY_NEWLINE);
695 else
696 vty_out(vty, " check-imei-rqd 1%s", VTY_NEWLINE);
697 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100698
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100699 if (gsmnet->paging_response_timer != MSC_PAGING_RESPONSE_TIMER_DEFAULT)
700 vty_out(vty, " paging response-timer %u%s", gsmnet->paging_response_timer, VTY_NEWLINE);
701
Harald Welte69c54a82018-02-09 20:41:14 +0100702 if (gsmnet->emergency.route_to_msisdn) {
703 vty_out(vty, " emergency-call route-to-msisdn %s%s",
704 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
705 }
706
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700707 if (gsmnet->sms_over_gsup)
708 vty_out(vty, " sms-over-gsup%s", VTY_NEWLINE);
709
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100710 if (gsmnet->handover_number.range_start || gsmnet->handover_number.range_end)
711 vty_out(vty, " handover-number range %"PRIu64" %"PRIu64"%s",
712 gsmnet->handover_number.range_start, gsmnet->handover_number.range_end,
713 VTY_NEWLINE);
714
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200715 if (gsmnet->use_osmux != OSMUX_USAGE_OFF) {
716 vty_out(vty, " osmux %s%s", gsmnet->use_osmux == OSMUX_USAGE_ON ? "on" : "only",
717 VTY_NEWLINE);
718 }
719
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200720 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200721#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200722 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200723#endif
724
Neels Hofmeyr880b9502019-05-09 02:01:55 +0200725 neighbor_ident_vty_write(vty);
726
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +0700727 /* Timer introspection commands (generic osmo_tdef API) */
728 osmo_tdef_vty_groups_write(vty, " ");
729
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200730 return CMD_SUCCESS;
731}
732
Maxc51609a2018-11-09 17:13:00 +0100733DEFUN(show_bsc, show_bsc_cmd,
734 "show bsc", SHOW_STR "BSC\n")
735{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100736 struct ran_peer *rp;
737 llist_for_each_entry(rp, &gsmnet->a.sri->ran_peers, entry) {
738 vty_out(vty, "BSC %s %s%s",
739 osmo_sccp_inst_addr_name(gsmnet->a.sri->sccp, &rp->peer_addr),
740 osmo_fsm_inst_state_name(rp->fi),
741 VTY_NEWLINE);
Maxc51609a2018-11-09 17:13:00 +0100742 }
743
744 return CMD_SUCCESS;
745}
746
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100747static const char *get_trans_proto_str(const struct gsm_trans *trans)
748{
749 static char buf[256];
750
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100751 switch (trans->type) {
752 case TRANS_CC:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100753 snprintf(buf, sizeof(buf), "%s %4u %4u",
754 gsm48_cc_state_name(trans->cc.state),
755 trans->cc.Tcurrent,
756 trans->cc.T308_second);
757 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100758 case TRANS_SMS:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700759 snprintf(buf, sizeof(buf), "CP:%s RP:%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100760 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
761 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
762 break;
763 default:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700764 return NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100765 }
766
767 return buf;
768}
769
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700770/* Prefix a given format string with a given amount of spaces */
771#define MSC_VTY_DUMP(vty, offset, fmt, args...) \
772 vty_out(vty, "%*s" fmt, offset, "", ##args)
773
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200774/* Print value of a named flag, prefixed with a given amount of spaces */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700775#define MSC_VTY_DUMP_FLAG(vty, offset, name, flag) \
776 MSC_VTY_DUMP(vty, offset + 2, "%s: %*s%s%s", \
777 name, 30 - (int)strlen(name), "", \
778 flag ? "true" : "false", \
779 VTY_NEWLINE)
780
781enum msc_vty_dump_flags {
782 MSC_VTY_DUMP_F_SUBSCR = (1 << 0),
783 MSC_VTY_DUMP_F_CONNECTION = (1 << 1),
784 MSC_VTY_DUMP_F_TRANSACTION = (1 << 2),
785};
786
787static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans,
788 int offset, uint8_t dump_flags)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100789{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700790 const char *proto_str;
791
792 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
793 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
794 vlr_subscr_name(msc_a_vsub(trans->msc_a)),
795 VTY_NEWLINE);
796 }
797
798 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200799 /* (If msc_a exists, there *must* be a non-null msc_a->c.msub) */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700800 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
801 trans->msc_a ? msub_ran_conn_name(trans->msc_a->c.msub)
802 : "(not established)",
803 VTY_NEWLINE);
804 }
805
806 MSC_VTY_DUMP(vty, offset, "Unique (global) identifier: 0x%08x%s",
807 trans->callref, VTY_NEWLINE);
808 MSC_VTY_DUMP(vty, offset, "GSM 04.07 identifier (%s): %u%s",
809 (trans->transaction_id & 0x08) ? "MO" : "MT",
810 trans->transaction_id,
811 VTY_NEWLINE);
812
813 MSC_VTY_DUMP(vty, offset, "Type: %s%s",
814 trans_type_name(trans->type),
815 VTY_NEWLINE);
816
817 if ((proto_str = get_trans_proto_str(trans))) {
818 MSC_VTY_DUMP(vty, offset, "Protocol specific: %s%s",
819 proto_str, VTY_NEWLINE);
820 }
821}
822
823static void vty_dump_one_conn(struct vty *vty, const struct msub *msub,
824 int offset, uint8_t dump_flags)
825{
826 struct vlr_subscr *vsub = msub_vsub(msub);
827 struct msc_a *msc_a = msub_msc_a(msub);
828 char buf[128];
829
830 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
831 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
832 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
833 vlr_subscr_name(vsub),
834 VTY_NEWLINE);
835 }
836
837 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
838 msub_ran_conn_name(msub),
839 VTY_NEWLINE);
840 MSC_VTY_DUMP(vty, offset, "RAN connection state: %s%s",
841 osmo_fsm_inst_state_name(msc_a->c.fi),
842 VTY_NEWLINE);
843
844 if (vsub) {
845 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
846 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
847 VTY_NEWLINE);
848 }
849
850 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
851 osmo_use_count_total(&msc_a->use_count),
852 VTY_NEWLINE);
853 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
854 osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count),
855 VTY_NEWLINE);
856
857 /* Transactions of this connection */
858 if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
859 struct gsm_trans *trans;
860 unsigned int i = 0;
861
862 /* Both subscriber and connection info is already printed */
863 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_CONNECTION;
864 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
865
866 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
867 if (trans->msc_a != msc_a)
868 continue;
869 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
870 i++, VTY_NEWLINE);
871 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
872 }
873 }
874}
875
876static void vty_dump_one_subscr(struct vty *vty, struct vlr_subscr *vsub,
877 int offset, uint8_t dump_flags)
878{
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700879 struct timespec now;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700880 char buf[128];
881
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700882 if (vsub->name[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700883 MSC_VTY_DUMP(vty, offset, "Name: '%s'%s",
884 vsub->name, VTY_NEWLINE);
885 }
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700886 if (vsub->msisdn[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700887 MSC_VTY_DUMP(vty, offset, "MSISDN: %s%s",
888 vsub->msisdn, VTY_NEWLINE);
889 }
890
891 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
892 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
893 VTY_NEWLINE);
894 MSC_VTY_DUMP(vty, offset, "RAN type: %s%s",
895 osmo_rat_type_name(vsub->cs.attached_via_ran),
896 VTY_NEWLINE);
897
898 MSC_VTY_DUMP(vty, offset, "IMSI: %s%s",
899 vsub->imsi, VTY_NEWLINE);
900 if (vsub->tmsi != GSM_RESERVED_TMSI) {
901 MSC_VTY_DUMP(vty, offset, "TMSI: %08X%s",
902 vsub->tmsi, VTY_NEWLINE);
903 }
904 if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
905 MSC_VTY_DUMP(vty, offset, "New TMSI: %08X%s",
906 vsub->tmsi_new, VTY_NEWLINE);
907 }
908 if (vsub->imei[0] != '\0') {
909 MSC_VTY_DUMP(vty, offset, "IMEI: %s%s",
910 vsub->imei, VTY_NEWLINE);
911 }
912 if (vsub->imeisv[0] != '\0') {
913 MSC_VTY_DUMP(vty, offset, "IMEISV: %s%s",
914 vsub->imeisv, VTY_NEWLINE);
915 }
916
917 MSC_VTY_DUMP(vty, offset, "Flags: %s", VTY_NEWLINE);
918 MSC_VTY_DUMP_FLAG(vty, offset, "IMSI detached",
919 vsub->imsi_detached_flag);
920 MSC_VTY_DUMP_FLAG(vty, offset, "Conf. by radio contact",
921 vsub->conf_by_radio_contact_ind);
922 MSC_VTY_DUMP_FLAG(vty, offset, "Subscr. data conf. by HLR",
923 vsub->sub_dataconf_by_hlr_ind);
924 MSC_VTY_DUMP_FLAG(vty, offset, "Location conf. in HLR",
925 vsub->loc_conf_in_hlr_ind);
926 MSC_VTY_DUMP_FLAG(vty, offset, "Subscriber dormant",
927 vsub->dormant_ind);
928 MSC_VTY_DUMP_FLAG(vty, offset, "Received cancel location",
929 vsub->cancel_loc_rx);
930 MSC_VTY_DUMP_FLAG(vty, offset, "MS not reachable",
931 vsub->ms_not_reachable_flag);
932 MSC_VTY_DUMP_FLAG(vty, offset, "LA allowed",
933 vsub->la_allowed);
934
935 if (vsub->last_tuple) {
936 struct vlr_auth_tuple *t = vsub->last_tuple;
937 MSC_VTY_DUMP(vty, offset, "A3A8 last tuple (used %d times): %s",
938 t->use_count, VTY_NEWLINE);
939 MSC_VTY_DUMP(vty, offset + 2, "seq # : %d%s",
940 t->key_seq, VTY_NEWLINE);
941 MSC_VTY_DUMP(vty, offset + 2, "RAND : %s%s",
942 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
943 VTY_NEWLINE);
944 MSC_VTY_DUMP(vty, offset + 2, "SRES : %s%s",
945 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
946 VTY_NEWLINE);
947 MSC_VTY_DUMP(vty, offset + 2, "Kc : %s%s",
948 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
949 VTY_NEWLINE);
950 }
951
Vadim Yanitskiyfc2b0192020-01-18 07:20:14 +0700952 if (!vlr_timer(vsub->vlr, 3212)) {
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700953 MSC_VTY_DUMP(vty, offset, "Expires: never (T3212 is disabled)%s",
954 VTY_NEWLINE);
955 } else if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) {
956 MSC_VTY_DUMP(vty, offset, "Expires: never%s",
957 VTY_NEWLINE);
958 } else if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
959 MSC_VTY_DUMP(vty, offset, "Expires: in %ld min %ld sec%s",
960 (vsub->expire_lu - now.tv_sec) / 60,
961 (vsub->expire_lu - now.tv_sec) % 60,
962 VTY_NEWLINE);
963 }
964
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700965 MSC_VTY_DUMP(vty, offset, "Paging: %s paging for %d requests%s",
966 vsub->cs.is_paging ? "is" : "not",
967 llist_count(&vsub->cs.requests),
968 VTY_NEWLINE);
969
970 /* SGs related */
971 MSC_VTY_DUMP(vty, offset, "SGs-state: %s%s",
972 osmo_fsm_inst_state_name(vsub->sgs_fsm),
973 VTY_NEWLINE);
974 MSC_VTY_DUMP(vty, offset, "SGs-MME: %s%s",
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700975 vsub->sgs.mme_name[0] != '\0' ? vsub->sgs.mme_name : "(none)",
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700976 VTY_NEWLINE);
977
978 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
979 osmo_use_count_total(&vsub->use_count),
980 VTY_NEWLINE);
981 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
982 osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count),
983 VTY_NEWLINE);
984
985 /* Connection(s) and/or transactions of this subscriber */
986 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
987 struct msub *msub = msub_for_vsub(vsub);
988 if (!msub)
989 return;
990
991 /* Subscriber info is already printed */
992 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
993
994 MSC_VTY_DUMP(vty, offset, "Connection: %s", VTY_NEWLINE);
995 vty_dump_one_conn(vty, msub, offset + 2, dump_flags);
996 } else if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
997 struct gsm_trans *trans;
998 unsigned int i = 0;
999
1000 /* Subscriber info is already printed */
1001 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
1002 /* Do not print connection info, but mention it */
1003 dump_flags |= MSC_VTY_DUMP_F_CONNECTION;
1004
1005 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1006 if (trans->vsub != vsub)
1007 continue;
1008 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
1009 i++, VTY_NEWLINE);
1010 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
1011 }
1012 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001013}
1014
1015DEFUN(show_msc_transaction, show_msc_transaction_cmd,
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001016 "show transaction",
1017 SHOW_STR "Transactions\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001018{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001019 struct gsm_trans *trans;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001020 uint8_t flags = 0x00;
1021 unsigned int i = 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001022
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001023 flags |= MSC_VTY_DUMP_F_CONNECTION;
1024 flags |= MSC_VTY_DUMP_F_SUBSCR;
1025
1026 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1027 vty_out(vty, " Transaction #%02u: %s", i++, VTY_NEWLINE);
1028 vty_dump_one_trans(vty, trans, 4, flags);
1029 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001030
1031 return CMD_SUCCESS;
1032}
1033
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001034DEFUN(show_msc_conn, show_msc_conn_cmd,
1035 "show connection [trans]",
1036 SHOW_STR "Subscriber Connections\n"
1037 "Show child transactions of each connection\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001038{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001039 uint8_t flags = 0x00;
1040 unsigned int i = 0;
1041 struct msub *msub;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001042
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001043 if (argc > 0)
1044 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1045 flags |= MSC_VTY_DUMP_F_SUBSCR;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001046
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001047 llist_for_each_entry(msub, &msub_list, entry) {
1048 vty_out(vty, " Connection #%02u: %s", i++, VTY_NEWLINE);
1049 vty_dump_one_conn(vty, msub, 4, flags);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001050 }
1051
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001052 return CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001053}
1054
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001055#define SUBSCR_FLAGS "[(conn|trans|conn+trans)]"
1056#define SUBSCR_FLAGS_HELP \
1057 "Show child connections\n" \
1058 "Show child transactions\n" \
1059 "Show child connections and transactions\n"
1060
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001061/* Subscriber */
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001062DEFUN(show_subscr_cache, show_subscr_cache_cmd,
1063 "show subscriber cache " SUBSCR_FLAGS,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001064 SHOW_STR "Show information about subscribers\n"
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001065 "Display contents of subscriber cache\n"
1066 SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001067{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001068 struct vlr_subscr *vsub;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001069 unsigned int count = 0;
1070 uint8_t flags = 0x00;
1071 unsigned int i = 0;
1072
1073 if (argc && strcmp(argv[0], "conn") == 0)
1074 flags |= MSC_VTY_DUMP_F_CONNECTION;
1075 else if (argc && strcmp(argv[0], "trans") == 0)
1076 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1077 else if (argc && strcmp(argv[0], "conn+trans") == 0)
1078 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001079
1080 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
1081 if (++count > 100) {
1082 vty_out(vty, "%% More than %d subscribers in cache,"
1083 " stopping here.%s", count-1, VTY_NEWLINE);
1084 break;
1085 }
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001086 vty_out(vty, " Subscriber #%02u: %s", i++, VTY_NEWLINE);
1087 vty_dump_one_subscr(vty, vsub, 4, flags);
Harald Welte69c54a82018-02-09 20:41:14 +01001088 }
1089
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001090 return CMD_SUCCESS;
1091}
1092
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001093DEFUN(sms_send_pend,
1094 sms_send_pend_cmd,
1095 "sms send pending",
1096 "SMS related commands\n" "SMS Sending related commands\n"
1097 "Send all pending SMS")
1098{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001099 struct gsm_sms *sms;
1100 unsigned long long sms_id = 0;
1101
1102 while (1) {
1103 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1104 if (!sms)
1105 break;
1106
1107 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001108 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001109
1110 sms_id = sms->id + 1;
1111 }
1112
1113 return CMD_SUCCESS;
1114}
1115
1116DEFUN(sms_delete_expired,
1117 sms_delete_expired_cmd,
1118 "sms delete expired",
1119 "SMS related commands\n" "SMS Database related commands\n"
1120 "Delete all expired SMS")
1121{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001122 struct gsm_sms *sms;
1123 unsigned long long sms_id = 0;
1124 long long num_deleted = 0;
1125
1126 while (1) {
1127 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1128 if (!sms)
1129 break;
1130
1131 /* Skip SMS which are currently queued for sending. */
1132 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
1133 continue;
1134
1135 /* Expiration check is performed by the DB layer. */
1136 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
1137 num_deleted++;
1138
1139 sms_id = sms->id + 1;
1140 }
1141
1142 if (num_deleted == 0) {
1143 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
1144 return CMD_WARNING;
1145 }
1146
1147 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
1148 return CMD_SUCCESS;
1149}
1150
1151static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +02001152 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001153 char *str, uint8_t tp_pid)
1154{
1155 struct gsm_network *net = receiver->vlr->user_ctx;
1156 struct gsm_sms *sms;
1157
Harald Welte39b55482018-04-09 19:19:33 +02001158 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Vadim Yanitskiydb4839c2019-12-01 18:52:58 +07001159 if (!sms) {
1160 LOGP(DLSMS, LOGL_ERROR, "Failed to allocate SMS\n");
1161 return CMD_WARNING;
1162 }
1163
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001164 sms->protocol_id = tp_pid;
1165
1166 /* store in database for the queue */
1167 if (db_sms_store(sms) != 0) {
1168 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
1169 sms_free(sms);
1170 return CMD_WARNING;
1171 }
1172 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
1173
1174 sms_free(sms);
1175 sms_queue_trigger(net->sms_queue);
1176 return CMD_SUCCESS;
1177}
1178
1179static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
1180 const char *type,
1181 const char *id)
1182{
1183 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001184 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001185 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001186 return vlr_subscr_find_by_imsi(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001187 else if (!strcmp(type, "tmsi"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001188 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id), VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001189
1190 return NULL;
1191}
1192#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
1193#define SUBSCR_HELP "Operations on a Subscriber\n" \
1194 "Identify subscriber by MSISDN (phone number)\n" \
1195 "Legacy alias for 'msisdn'\n" \
1196 "Identify subscriber by IMSI\n" \
1197 "Identify subscriber by TMSI\n" \
Vadim Yanitskiy3ccd8232019-05-16 01:35:23 +07001198 "Legacy alias for 'imsi'\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001199 "Identifier for the subscriber\n"
1200
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001201DEFUN(show_subscr, show_subscr_cmd,
1202 "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
1203 SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001204{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001205 struct vlr_subscr *vsub;
1206 uint8_t flags = 0x00;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001207
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001208 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001209 if (!vsub) {
1210 vty_out(vty, "%% No subscriber found for %s %s%s",
1211 argv[0], argv[1], VTY_NEWLINE);
1212 return CMD_WARNING;
1213 }
1214
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001215 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
1216 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
1217 * 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 +01001218 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001219
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001220 if (argc > 2 && strcmp(argv[2], "conn") == 0)
1221 flags |= MSC_VTY_DUMP_F_CONNECTION;
1222 else if (argc > 2 && strcmp(argv[2], "trans") == 0)
1223 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1224 else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
1225 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
1226
1227 vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
1228 vty_dump_one_subscr(vty, vsub, 4, flags);
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001229
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001230 return CMD_SUCCESS;
1231}
1232
Vadim Yanitskiyb7ddbf32020-01-20 21:30:09 +07001233DEFUN_DEPRECATED(subscriber_create, subscriber_create_cmd,
1234 "subscriber create imsi ID",
1235 "Operations on a Subscriber\n"
1236 "Create new subscriber\n"
1237 "Identify the subscriber by his IMSI\n"
1238 "Identifier for the subscriber\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001239{
1240 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
1241 VTY_NEWLINE);
1242 return CMD_WARNING;
1243}
1244
1245DEFUN(subscriber_send_pending_sms,
1246 subscriber_send_pending_sms_cmd,
1247 "subscriber " SUBSCR_TYPES " ID sms pending-send",
1248 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
1249{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001250 struct vlr_subscr *vsub;
1251 struct gsm_sms *sms;
1252
1253 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1254 if (!vsub) {
1255 vty_out(vty, "%% No subscriber found for %s %s%s",
1256 argv[0], argv[1], VTY_NEWLINE);
1257 return CMD_WARNING;
1258 }
1259
1260 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
1261 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001262 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001263
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001264 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001265
1266 return CMD_SUCCESS;
1267}
1268
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001269DEFUN(subscriber_sms_delete_all,
1270 subscriber_sms_delete_all_cmd,
1271 "subscriber " SUBSCR_TYPES " ID sms delete-all",
1272 SUBSCR_HELP "SMS Operations\n"
1273 "Delete all SMS to be delivered to this subscriber"
1274 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
1275 " WILL BE LOST.\n")
1276{
1277 struct vlr_subscr *vsub;
1278
1279 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1280 if (!vsub) {
1281 vty_out(vty, "%% No subscriber found for %s %s%s",
1282 argv[0], argv[1], VTY_NEWLINE);
1283 return CMD_WARNING;
1284 }
1285
1286 db_sms_delete_by_msisdn(vsub->msisdn);
1287
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001288 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001289
1290 return CMD_SUCCESS;
1291}
1292
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001293DEFUN(subscriber_send_sms,
1294 subscriber_send_sms_cmd,
1295 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1296 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1297{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001298 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001299 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001300 char *str;
1301 int rc;
1302
1303 if (!vsub) {
1304 vty_out(vty, "%% No subscriber found for %s %s%s",
1305 argv[0], argv[1], VTY_NEWLINE);
1306 rc = CMD_WARNING;
1307 goto err;
1308 }
1309
Harald Welte39b55482018-04-09 19:19:33 +02001310 if (!strcmp(argv[2], "msisdn"))
1311 sender_msisdn = argv[3];
1312 else {
1313 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1314 if (!sender) {
1315 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1316 rc = CMD_WARNING;
1317 goto err;
1318 }
1319 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001320 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001321 }
1322
1323 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001324 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001325 talloc_free(str);
1326
1327err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001328 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001329 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001330
1331 return rc;
1332}
1333
1334DEFUN(subscriber_silent_sms,
1335 subscriber_silent_sms_cmd,
1336
1337 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1338 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1339{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001340 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001341 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001342 char *str;
1343 int rc;
1344
1345 if (!vsub) {
1346 vty_out(vty, "%% No subscriber found for %s %s%s",
1347 argv[0], argv[1], VTY_NEWLINE);
1348 rc = CMD_WARNING;
1349 goto err;
1350 }
1351
Harald Welte39b55482018-04-09 19:19:33 +02001352 if (!strcmp(argv[2], "msisdn")) {
1353 sender_msisdn = argv[3];
1354 } else {
1355 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1356 if (!sender) {
1357 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1358 rc = CMD_WARNING;
1359 goto err;
1360 }
1361 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001362 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001363 }
1364
1365 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001366 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001367 talloc_free(str);
1368
1369err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001370 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001371 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001372
1373 return rc;
1374}
1375
Sylvain Munaut93558302019-02-14 20:13:08 +01001376#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001377#define CHAN_TYPE_HELP \
1378 "Any channel\n" \
1379 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001380 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001381 "Any TCH channel\n" \
1382 "SDCCH channel\n"
1383
Sylvain Munaut93558302019-02-14 20:13:08 +01001384#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1385#define CHAN_MODE_HELP \
1386 "Signalling only\n" \
1387 "Speech with HR codec\n" \
1388 "Speech with FR codec\n" \
1389 "Speech with EFR codec\n" \
1390 "Speech with AMR codec\n"
1391
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001392DEFUN(subscriber_silent_call_start,
1393 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001394 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001395 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001396 CHAN_TYPE_HELP CHAN_MODE_HELP
1397 "Target IP for RTP traffic (default 127.0.0.1)\n"
1398 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001399{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001400 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001401 struct gsm0808_channel_type ct;
1402 const char *ip;
1403 uint16_t port;
1404 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001405
1406 if (!vsub) {
1407 vty_out(vty, "%% No subscriber found for %s %s%s",
1408 argv[0], argv[1], VTY_NEWLINE);
1409 return CMD_WARNING;
1410 }
1411
Sylvain Munaut93558302019-02-14 20:13:08 +01001412 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001413
Sylvain Munaut93558302019-02-14 20:13:08 +01001414 if (!strcmp(argv[3], "signalling")) {
1415 ct.ch_indctr = GSM0808_CHAN_SIGN;
1416 ct.perm_spch[0] = 0; /* Spare but required */
1417 ct.perm_spch_len = 1;
1418 } else if (!strcmp(argv[3], "speech-hr")) {
1419 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1420 ct.perm_spch[0] = GSM0808_PERM_HR1;
1421 ct.perm_spch_len = 1;
1422 } else if (!strcmp(argv[3], "speech-fr")) {
1423 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1424 ct.perm_spch[0] = GSM0808_PERM_FR1;
1425 ct.perm_spch_len = 1;
1426 } else if (!strcmp(argv[3], "speech-efr")) {
1427 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1428 ct.perm_spch[0] = GSM0808_PERM_FR2;
1429 ct.perm_spch_len = 1;
1430 } else if (!strcmp(argv[3], "speech-amr")) {
1431 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1432 ct.perm_spch[0] = GSM0808_PERM_FR3;
1433 ct.perm_spch[1] = GSM0808_PERM_HR3;
1434 ct.perm_spch_len = 2;
1435 }
1436
1437 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1438
1439 if (!strcmp(argv[2], "tch/f"))
1440 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1441 else if (!strcmp(argv[2], "tch/h"))
1442 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1443 else if (!strcmp(argv[2], "tch/any"))
1444 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1445 else if (!strcmp(argv[2], "sdcch")) {
1446 if (speech) {
1447 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1448 return CMD_WARNING;
1449 }
1450 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1451 } else
1452 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1453
1454 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1455 port = argc >= 6 ? atoi(argv[5]) : 4000;
1456
1457 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001458 switch (rc) {
1459 case -ENODEV:
1460 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1461 break;
1462 default:
1463 if (rc)
1464 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1465 else
1466 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1467 break;
1468 }
1469
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001470 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001471 return rc ? CMD_WARNING : CMD_SUCCESS;
1472}
1473
1474DEFUN(subscriber_silent_call_stop,
1475 subscriber_silent_call_stop_cmd,
1476 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1477 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1478 CHAN_TYPE_HELP)
1479{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001480 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1481 int rc;
1482
1483 if (!vsub) {
1484 vty_out(vty, "%% No subscriber found for %s %s%s",
1485 argv[0], argv[1], VTY_NEWLINE);
1486 return CMD_WARNING;
1487 }
1488
1489 rc = gsm_silent_call_stop(vsub);
1490 switch (rc) {
1491 case -ENODEV:
1492 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1493 break;
1494 case -ENOENT:
1495 vty_out(vty, "%% Subscriber has no silent call active%s",
1496 VTY_NEWLINE);
1497 break;
1498 default:
1499 if (rc)
1500 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1501 else
1502 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1503 break;
1504 }
1505
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001506 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001507 return rc ? CMD_WARNING : CMD_SUCCESS;
1508}
1509
1510DEFUN(subscriber_ussd_notify,
1511 subscriber_ussd_notify_cmd,
1512 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1513 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1514 "Alerting Level 0\n"
1515 "Alerting Level 1\n"
1516 "Alerting Level 2\n"
1517 "Text of USSD message to send\n")
1518{
1519 char *text;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001520 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001521 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1522 int level;
1523
1524 if (!vsub) {
1525 vty_out(vty, "%% No subscriber found for %s %s%s",
1526 argv[0], argv[1], VTY_NEWLINE);
1527 return CMD_WARNING;
1528 }
1529
1530 level = atoi(argv[2]);
1531 text = argv_concat(argv, argc, 3);
1532 if (!text) {
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001533 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001534 return CMD_WARNING;
1535 }
1536
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001537 msc_a = msc_a_for_vsub(vsub, true);
1538 if (!msc_a || msc_a->c.remote_to) {
1539 vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001540 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001541 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001542 talloc_free(text);
1543 return CMD_WARNING;
1544 }
1545
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001546 msc_send_ussd_notify(msc_a, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001547 /* FIXME: since we don't allocate a transaction here,
1548 * we use dummy GSM 04.07 transaction ID. */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001549 msc_send_ussd_release_complete(msc_a, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001550
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001551 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001552 talloc_free(text);
1553 return CMD_SUCCESS;
1554}
1555
1556DEFUN(subscriber_paging,
1557 subscriber_paging_cmd,
1558 "subscriber " SUBSCR_TYPES " ID paging",
1559 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1560{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001561 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001562 struct paging_request *req;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001563
1564 if (!vsub) {
1565 vty_out(vty, "%% No subscriber found for %s %s%s",
1566 argv[0], argv[1], VTY_NEWLINE);
1567 return CMD_WARNING;
1568 }
1569
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001570 req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL,
1571 NULL, NULL, "manual Paging from VTY");
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001572 if (req)
1573 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1574 else
1575 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1576
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001577 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001578 return req ? CMD_SUCCESS : CMD_WARNING;
1579}
1580
1581static int loop_by_char(uint8_t ch)
1582{
1583 switch (ch) {
1584 case 'a':
1585 return GSM414_LOOP_A;
1586 case 'b':
1587 return GSM414_LOOP_B;
1588 case 'c':
1589 return GSM414_LOOP_C;
1590 case 'd':
1591 return GSM414_LOOP_D;
1592 case 'e':
1593 return GSM414_LOOP_E;
1594 case 'f':
1595 return GSM414_LOOP_F;
1596 case 'i':
1597 return GSM414_LOOP_I;
1598 }
1599 return -1;
1600}
1601
1602DEFUN(subscriber_mstest_close,
1603 subscriber_mstest_close_cmd,
1604 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1605 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1606 "Close a TCH Loop inside the MS\n"
1607 "Loop Type A\n"
1608 "Loop Type B\n"
1609 "Loop Type C\n"
1610 "Loop Type D\n"
1611 "Loop Type E\n"
1612 "Loop Type F\n"
1613 "Loop Type I\n")
1614{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001615 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001616 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1617 const char *loop_str;
1618 int loop_mode;
1619
1620 if (!vsub) {
1621 vty_out(vty, "%% No subscriber found for %s %s%s",
1622 argv[0], argv[1], VTY_NEWLINE);
1623 return CMD_WARNING;
1624 }
1625
1626 loop_str = argv[2];
1627 loop_mode = loop_by_char(loop_str[0]);
1628
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001629 msc_a = msc_a_for_vsub(vsub, true);
1630 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001631 vty_out(vty, "%% An active connection is required for %s %s%s",
1632 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001633 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001634 return CMD_WARNING;
1635 }
1636
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001637 gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001638
1639 return CMD_SUCCESS;
1640}
1641
1642DEFUN(subscriber_mstest_open,
1643 subscriber_mstest_open_cmd,
1644 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1645 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1646 "Open a TCH Loop inside the MS\n")
1647{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001648 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001649 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1650
1651 if (!vsub) {
1652 vty_out(vty, "%% No subscriber found for %s %s%s",
1653 argv[0], argv[1], VTY_NEWLINE);
1654 return CMD_WARNING;
1655 }
1656
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001657 msc_a = msc_a_for_vsub(vsub, true);
1658 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001659 vty_out(vty, "%% An active connection is required for %s %s%s",
1660 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001661 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001662 return CMD_WARNING;
1663 }
1664
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001665 gsm0414_tx_open_loop_cmd(msc_a);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001666
1667 return CMD_SUCCESS;
1668}
1669
1670DEFUN(ena_subscr_expire,
1671 ena_subscr_expire_cmd,
1672 "subscriber " SUBSCR_TYPES " ID expire",
1673 SUBSCR_HELP "Expire the subscriber Now\n")
1674{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001675 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1676 argv[1]);
1677
1678 if (!vsub) {
1679 vty_out(vty, "%% No subscriber found for %s %s%s",
1680 argv[0], argv[1], VTY_NEWLINE);
1681 return CMD_WARNING;
1682 }
1683
1684 if (vlr_subscr_expire(vsub))
1685 vty_out(vty, "%% VLR released subscriber %s%s",
1686 vlr_subscr_name(vsub), VTY_NEWLINE);
1687
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001688 if (osmo_use_count_total(&vsub->use_count) > 1)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001689 vty_out(vty, "%% Subscriber %s is still in use,"
1690 " should be released soon%s",
1691 vlr_subscr_name(vsub), VTY_NEWLINE);
1692
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001693 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001694 return CMD_SUCCESS;
1695}
1696
1697static int scall_cbfn(unsigned int subsys, unsigned int signal,
1698 void *handler_data, void *signal_data)
1699{
1700 struct scall_signal_data *sigdata = signal_data;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001701 struct vty *vty = sigdata->vty;
1702
1703 if (!vty_is_active(vty))
1704 return 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001705
1706 switch (signal) {
1707 case S_SCALL_SUCCESS:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001708 vty_out(vty, "%% Silent call success%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001709 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001710 case S_SCALL_FAILED:
1711 vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE);
1712 break;
1713 case S_SCALL_DETACHED:
1714 vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001715 break;
1716 }
1717 return 0;
1718}
1719
1720DEFUN(show_stats,
1721 show_stats_cmd,
1722 "show statistics",
1723 SHOW_STR "Display network statistics\n")
1724{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001725 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001726 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1727 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1728 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001729 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001730 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001731 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001732 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001733 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001734 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1735 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001736 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001737 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001738 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1739 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001740 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001741 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001742 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1743 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1744 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001745 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001746 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001747 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1748 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001749 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001750 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001751 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1752 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001753 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001754 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001755 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current,
1756 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1757 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current
1758 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1759 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001760 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001761 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current,
1762 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1763 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current
1764 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1765 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001766 return CMD_SUCCESS;
1767}
1768
1769DEFUN(show_smsqueue,
1770 show_smsqueue_cmd,
1771 "show sms-queue",
1772 SHOW_STR "Display SMSqueue statistics\n")
1773{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001774 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001775 return CMD_SUCCESS;
1776}
1777
1778DEFUN(smsqueue_trigger,
1779 smsqueue_trigger_cmd,
1780 "sms-queue trigger",
1781 "SMS Queue\n" "Trigger sending messages\n")
1782{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001783 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001784 return CMD_SUCCESS;
1785}
1786
1787DEFUN(smsqueue_max,
1788 smsqueue_max_cmd,
1789 "sms-queue max-pending <1-500>",
1790 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1791{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001792 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001793 return CMD_SUCCESS;
1794}
1795
1796DEFUN(smsqueue_clear,
1797 smsqueue_clear_cmd,
1798 "sms-queue clear",
1799 "SMS Queue\n" "Clear the queue of pending SMS\n")
1800{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001801 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001802 return CMD_SUCCESS;
1803}
1804
1805DEFUN(smsqueue_fail,
1806 smsqueue_fail_cmd,
1807 "sms-queue max-failure <1-500>",
1808 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1809{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001810 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001811 return CMD_SUCCESS;
1812}
1813
1814
1815DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1816 "mncc-int", "Configure internal MNCC handler")
1817{
1818 vty->node = MNCC_INT_NODE;
1819
1820 return CMD_SUCCESS;
1821}
1822
1823static struct cmd_node mncc_int_node = {
1824 MNCC_INT_NODE,
1825 "%s(config-mncc-int)# ",
1826 1,
1827};
1828
1829static const struct value_string tchf_codec_names[] = {
1830 { GSM48_CMODE_SPEECH_V1, "fr" },
1831 { GSM48_CMODE_SPEECH_EFR, "efr" },
1832 { GSM48_CMODE_SPEECH_AMR, "amr" },
1833 { 0, NULL }
1834};
1835
1836static const struct value_string tchh_codec_names[] = {
1837 { GSM48_CMODE_SPEECH_V1, "hr" },
1838 { GSM48_CMODE_SPEECH_AMR, "amr" },
1839 { 0, NULL }
1840};
1841
1842static int config_write_mncc_int(struct vty *vty)
1843{
1844 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1845 vty_out(vty, " default-codec tch-f %s%s",
1846 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1847 VTY_NEWLINE);
1848 vty_out(vty, " default-codec tch-h %s%s",
1849 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1850 VTY_NEWLINE);
1851
1852 return CMD_SUCCESS;
1853}
1854
1855DEFUN(mnccint_def_codec_f,
1856 mnccint_def_codec_f_cmd,
1857 "default-codec tch-f (fr|efr|amr)",
1858 "Set default codec\n" "Codec for TCH/F\n"
1859 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1860{
1861 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1862
1863 return CMD_SUCCESS;
1864}
1865
1866DEFUN(mnccint_def_codec_h,
1867 mnccint_def_codec_h_cmd,
1868 "default-codec tch-h (hr|amr)",
1869 "Set default codec\n" "Codec for TCH/H\n"
1870 "Half-Rate\n" "Adaptive Multi-Rate\n")
1871{
1872 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1873
1874 return CMD_SUCCESS;
1875}
1876
1877
1878DEFUN(logging_fltr_imsi,
1879 logging_fltr_imsi_cmd,
1880 "logging filter imsi IMSI",
1881 LOGGING_STR FILTER_STR
1882 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1883{
1884 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001885 struct log_target *tgt = osmo_log_vty2tgt(vty);
1886 const char *imsi = argv[0];
1887
1888 if (!tgt)
1889 return CMD_WARNING;
1890
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001891 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001892
1893 if (!vlr_subscr) {
1894 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1895 argv[0], VTY_NEWLINE);
1896 return CMD_WARNING;
1897 }
1898
1899 log_set_filter_vlr_subscr(tgt, vlr_subscr);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001900 vlr_subscr_put(vlr_subscr, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001901 return CMD_SUCCESS;
1902}
1903
1904static struct cmd_node hlr_node = {
1905 HLR_NODE,
1906 "%s(config-hlr)# ",
1907 1,
1908};
1909
1910DEFUN(cfg_hlr, cfg_hlr_cmd,
1911 "hlr", "Configure connection to the HLR")
1912{
1913 vty->node = HLR_NODE;
1914 return CMD_SUCCESS;
1915}
1916
1917DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1918 "Remote GSUP address of the HLR\n"
1919 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1920{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001921 talloc_free((void*)gsmnet->gsup_server_addr_str);
1922 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1923 return CMD_SUCCESS;
1924}
1925
1926DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1927 "Remote GSUP port of the HLR\n"
1928 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1929{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001930 gsmnet->gsup_server_port = atoi(argv[0]);
1931 return CMD_SUCCESS;
1932}
1933
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001934DEFUN(cfg_hlr_ipa_name,
1935 cfg_hlr_ipa_name_cmd,
1936 "ipa-name NAME",
1937 "Set the IPA name of this MSC\n"
1938 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1939 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
1940 "The default is 'MSC-00-00-00-00-00-00'.\n")
1941{
1942 if (vty->type != VTY_FILE) {
1943 vty_out(vty, "The IPA name cannot be changed at run-time; "
Martin Hauke3f07dac2019-11-14 17:49:08 +01001944 "It can only be set in the configuration file.%s", VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001945 return CMD_WARNING;
1946 }
1947
1948 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
1949 return CMD_SUCCESS;
1950}
1951
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001952static int config_write_hlr(struct vty *vty)
1953{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001954 vty_out(vty, "hlr%s", VTY_NEWLINE);
1955 vty_out(vty, " remote-ip %s%s",
1956 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1957 vty_out(vty, " remote-port %u%s",
1958 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001959 if (gsmnet->msc_ipa_name)
1960 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001961 return CMD_SUCCESS;
1962}
1963
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001964void msc_vty_init(struct gsm_network *msc_network)
1965{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001966 OSMO_ASSERT(gsmnet == NULL);
1967 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001968
1969 osmo_stats_vty_add_cmds();
1970
1971 install_element(CONFIG_NODE, &cfg_net_cmd);
1972 install_node(&net_node, config_write_net);
1973 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1974 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1975 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1976 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1977 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +02001978 install_element(GSMNET_NODE, &cfg_net_encryption_uea_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001979 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1980 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1981 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1982 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1983 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1984 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1985 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1986 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Keith Whyte991bb422019-08-08 15:43:40 +02001987 install_element(GSMNET_NODE, &cfg_net_call_wait_cmd);
1988 install_element(GSMNET_NODE, &cfg_net_no_call_wait_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001989
1990 install_element(CONFIG_NODE, &cfg_msc_cmd);
1991 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001992 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01001993 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
1994 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02001995 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01001996 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07001997 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001998 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001999 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
2000 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01002001 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02002002 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
2003 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01002004 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01002005 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07002006 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
2007 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +02002008 install_element(MSC_NODE, &cfg_msc_osmux_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002009 install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd);
2010
2011 neighbor_ident_vty_init(msc_network);
Philipp Maierfbf66102017-04-09 12:32:51 +02002012
Vadim Yanitskiyffc7f392020-01-18 18:39:41 +07002013 /* Timer configuration commands (generic osmo_tdef API) */
2014 osmo_tdef_vty_groups_init(MSC_NODE, msc_tdef_group);
2015
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02002016 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002017#ifdef BUILD_IU
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002018 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 +02002019#endif
Harald Welte0df904d2018-12-03 11:00:04 +01002020 sgs_vty_init();
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002021
Stefan Sperling617ac802018-02-22 17:58:20 +01002022 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002023
2024 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
2025
2026 install_element_ve(&show_subscr_cmd);
2027 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01002028 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002029 install_element_ve(&show_msc_conn_cmd);
2030 install_element_ve(&show_msc_transaction_cmd);
2031
2032 install_element_ve(&sms_send_pend_cmd);
2033 install_element_ve(&sms_delete_expired_cmd);
2034
2035 install_element_ve(&subscriber_create_cmd);
2036 install_element_ve(&subscriber_send_sms_cmd);
2037 install_element_ve(&subscriber_silent_sms_cmd);
2038 install_element_ve(&subscriber_silent_call_start_cmd);
2039 install_element_ve(&subscriber_silent_call_stop_cmd);
2040 install_element_ve(&subscriber_ussd_notify_cmd);
2041 install_element_ve(&subscriber_mstest_close_cmd);
2042 install_element_ve(&subscriber_mstest_open_cmd);
2043 install_element_ve(&subscriber_paging_cmd);
2044 install_element_ve(&show_stats_cmd);
2045 install_element_ve(&show_smsqueue_cmd);
2046 install_element_ve(&logging_fltr_imsi_cmd);
2047
2048 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
2049 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
2050 install_element(ENABLE_NODE, &smsqueue_max_cmd);
2051 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
2052 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
2053 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01002054 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002055
2056 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
2057 install_node(&mncc_int_node, config_write_mncc_int);
2058 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
2059 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
2060
2061 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
2062
2063 install_element(CONFIG_NODE, &cfg_hlr_cmd);
2064 install_node(&hlr_node, config_write_hlr);
2065 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
2066 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002067 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002068}