blob: cd82a07a7156ad65c056f87f54ea841181057cf6 [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
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020039#include <osmocom/vty/command.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010040#include <osmocom/vty/logging.h>
Stefan Sperling617ac802018-02-22 17:58:20 +010041#include <osmocom/vty/misc.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010042#include <osmocom/vty/stats.h>
43
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020044#ifdef BUILD_IU
45#include <osmocom/ranap/iu_client.h>
46#endif
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020047
Neels Hofmeyr90843962017-09-04 15:04:35 +020048#include <osmocom/msc/vty.h>
49#include <osmocom/msc/gsm_data.h>
50#include <osmocom/msc/gsm_subscriber.h>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010051#include <osmocom/msc/msub.h>
52#include <osmocom/msc/msc_a.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020053#include <osmocom/msc/vlr.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010054#include <osmocom/msc/transaction.h>
55#include <osmocom/msc/db.h>
56#include <osmocom/msc/sms_queue.h>
57#include <osmocom/msc/silent_call.h>
58#include <osmocom/msc/gsm_04_80.h>
59#include <osmocom/msc/gsm_04_14.h>
60#include <osmocom/msc/signal.h>
61#include <osmocom/msc/mncc_int.h>
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +020062#include <osmocom/msc/osmux.h>
Vadim Yanitskiy1b891302018-08-04 01:33:08 +070063#include <osmocom/msc/rrlp.h>
Harald Welte0df904d2018-12-03 11:00:04 +010064#include <osmocom/msc/vlr_sgs.h>
65#include <osmocom/msc/sgs_vty.h>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010066#include <osmocom/msc/sccp_ran.h>
67#include <osmocom/msc/ran_peer.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010068
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010069static struct gsm_network *gsmnet = NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010070
71struct cmd_node net_node = {
72 GSMNET_NODE,
73 "%s(config-net)# ",
74 1,
75};
76
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +010077#define VSUB_USE_VTY "VTY"
78
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010079#define NETWORK_STR "Configure the GSM network\n"
80#define CODE_CMD_STR "Code commands\n"
81#define NAME_CMD_STR "Name Commands\n"
82#define NAME_STR "Name to use\n"
83
84DEFUN(cfg_net,
85 cfg_net_cmd,
86 "network", NETWORK_STR)
87{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010088 vty->index = gsmnet;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010089 vty->node = GSMNET_NODE;
90
91 return CMD_SUCCESS;
92}
93
94DEFUN(cfg_net_ncc,
95 cfg_net_ncc_cmd,
96 "network country code <1-999>",
97 "Set the GSM network country code\n"
98 "Country commands\n"
99 CODE_CMD_STR
100 "Network Country Code to use\n")
101{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100102 gsmnet->plmn.mcc = atoi(argv[0]);
103
104 return CMD_SUCCESS;
105}
106
107DEFUN(cfg_net_mnc,
108 cfg_net_mnc_cmd,
109 "mobile network code <0-999>",
110 "Set the GSM mobile network code\n"
111 "Network Commands\n"
112 CODE_CMD_STR
113 "Mobile Network Code to use\n")
114{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100115 uint16_t mnc;
116 bool mnc_3_digits;
117
118 if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
119 vty_out(vty, "%% Error decoding MNC: %s%s", argv[0], VTY_NEWLINE);
120 return CMD_WARNING;
121 }
122
123 gsmnet->plmn.mnc = mnc;
124 gsmnet->plmn.mnc_3_digits = mnc_3_digits;
125
126 return CMD_SUCCESS;
127}
128
129DEFUN(cfg_net_name_short,
130 cfg_net_name_short_cmd,
131 "short name NAME",
132 "Set the short GSM network name\n" NAME_CMD_STR NAME_STR)
133{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100134 osmo_talloc_replace_string(gsmnet, &gsmnet->name_short, argv[0]);
135 return CMD_SUCCESS;
136}
137
138DEFUN(cfg_net_name_long,
139 cfg_net_name_long_cmd,
140 "long name NAME",
141 "Set the long GSM network name\n" NAME_CMD_STR NAME_STR)
142{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100143 osmo_talloc_replace_string(gsmnet, &gsmnet->name_long, argv[0]);
144 return CMD_SUCCESS;
145}
146
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200147#define ENCRYPTION_STR "Encryption options\n"
148
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100149DEFUN(cfg_net_encryption,
150 cfg_net_encryption_cmd,
151 "encryption a5 <0-3> [<0-3>] [<0-3>] [<0-3>]",
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200152 ENCRYPTION_STR
153 "GSM A5 Air Interface Encryption.\n"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100154 "A5/n Algorithm Number\n"
155 "A5/n Algorithm Number\n"
156 "A5/n Algorithm Number\n"
157 "A5/n Algorithm Number\n")
158{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100159 unsigned int i;
160
161 gsmnet->a5_encryption_mask = 0;
162 for (i = 0; i < argc; i++)
163 gsmnet->a5_encryption_mask |= (1 << atoi(argv[i]));
164
165 return CMD_SUCCESS;
166}
167
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200168/* So far just a boolean switch, a future patch might add individual config for UEA1 and UEA2, see OS#4143 */
169DEFUN(cfg_net_encryption_uea,
170 cfg_net_encryption_uea_cmd,
171 "encryption uea <0-2> [<0-2>] [<0-2>]",
172 ENCRYPTION_STR
173 "UTRAN (3G) encryption algorithms to allow: 0 = UEA0 (no encryption), 1 = UEA1, 2 = UEA2."
174 " NOTE: the current implementation does not allow free choice of combining encryption algorithms yet."
175 " The only valid settings are either 'encryption uea 0' or 'encryption uea 1 2'.\n"
176 "UEAn Algorithm Number\n"
177 "UEAn Algorithm Number\n"
178 "UEAn Algorithm Number\n"
179 )
180{
181 unsigned int i;
182 uint8_t mask = 0;
183
184 for (i = 0; i < argc; i++)
185 mask |= (1 << atoi(argv[i]));
186
187 if (mask == (1 << 0)) {
188 /* UEA0. Disable encryption. */
189 gsmnet->uea_encryption = false;
190 } else if (mask == ((1 << 1) | (1 << 2))) {
191 /* UEA1 and UEA2. Enable encryption. */
192 gsmnet->uea_encryption = true;
193 } else {
194 vty_out(vty,
195 "%% Error: the current implementation does not allow free choice of combining%s"
196 "%% encryption algorithms yet. The only valid settings are either%s"
197 "%% encryption uea 0%s"
198 "%% or%s"
199 "%% encryption uea 1 2%s",
200 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
201 return CMD_WARNING;
202 }
203
204 return CMD_SUCCESS;
205}
206
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100207DEFUN(cfg_net_authentication,
208 cfg_net_authentication_cmd,
209 "authentication (optional|required)",
210 "Whether to enforce MS authentication in 2G\n"
211 "Allow MS to attach via 2G BSC without authentication\n"
212 "Always do authentication\n")
213{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100214 gsmnet->authentication_required = (argv[0][0] == 'r') ? true : false;
215
216 return CMD_SUCCESS;
217}
218
219DEFUN(cfg_net_rrlp_mode, cfg_net_rrlp_mode_cmd,
220 "rrlp mode (none|ms-based|ms-preferred|ass-preferred)",
221 "Radio Resource Location Protocol\n"
222 "Set the Radio Resource Location Protocol Mode\n"
223 "Don't send RRLP request\n"
224 "Request MS-based location\n"
225 "Request any location, prefer MS-based\n"
226 "Request any location, prefer MS-assisted\n")
227{
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700228 gsmnet->rrlp.mode = msc_rrlp_mode_parse(argv[0]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100229
230 return CMD_SUCCESS;
231}
232
233DEFUN(cfg_net_mm_info, cfg_net_mm_info_cmd,
234 "mm info (0|1)",
235 "Mobility Management\n"
236 "Send MM INFO after LOC UPD ACCEPT\n"
237 "Disable\n" "Enable\n")
238{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100239 gsmnet->send_mm_info = atoi(argv[0]);
240
241 return CMD_SUCCESS;
242}
243
244DEFUN(cfg_net_timezone,
245 cfg_net_timezone_cmd,
246 "timezone <-19-19> (0|15|30|45)",
247 "Set the Timezone Offset of the network\n"
248 "Timezone offset (hours)\n"
249 "Timezone offset (00 minutes)\n"
250 "Timezone offset (15 minutes)\n"
251 "Timezone offset (30 minutes)\n"
252 "Timezone offset (45 minutes)\n"
253 )
254{
255 struct gsm_network *net = vty->index;
256 int tzhr = atoi(argv[0]);
257 int tzmn = atoi(argv[1]);
258
259 net->tz.hr = tzhr;
260 net->tz.mn = tzmn;
261 net->tz.dst = 0;
262 net->tz.override = 1;
263
264 return CMD_SUCCESS;
265}
266
267DEFUN(cfg_net_timezone_dst,
268 cfg_net_timezone_dst_cmd,
269 "timezone <-19-19> (0|15|30|45) <0-2>",
270 "Set the Timezone Offset of the network\n"
271 "Timezone offset (hours)\n"
272 "Timezone offset (00 minutes)\n"
273 "Timezone offset (15 minutes)\n"
274 "Timezone offset (30 minutes)\n"
275 "Timezone offset (45 minutes)\n"
276 "DST offset (hours)\n"
277 )
278{
279 struct gsm_network *net = vty->index;
280 int tzhr = atoi(argv[0]);
281 int tzmn = atoi(argv[1]);
282 int tzdst = atoi(argv[2]);
283
284 net->tz.hr = tzhr;
285 net->tz.mn = tzmn;
286 net->tz.dst = tzdst;
287 net->tz.override = 1;
288
289 return CMD_SUCCESS;
290}
291
292DEFUN(cfg_net_no_timezone,
293 cfg_net_no_timezone_cmd,
294 "no timezone",
295 NO_STR
296 "Disable network timezone override, use system tz\n")
297{
298 struct gsm_network *net = vty->index;
299
300 net->tz.override = 0;
301
302 return CMD_SUCCESS;
303}
304
305DEFUN(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
306 "periodic location update <6-1530>",
307 "Periodic Location Updating Interval\n"
308 "Periodic Location Updating Interval\n"
309 "Periodic Location Updating Interval\n"
310 "Periodic Location Updating Interval in Minutes\n")
311{
312 struct gsm_network *net = vty->index;
313
314 net->t3212 = atoi(argv[0]) / 6;
315
316 return CMD_SUCCESS;
317}
318
319DEFUN(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
320 "no periodic location update",
321 NO_STR
322 "Periodic Location Updating Interval\n"
323 "Periodic Location Updating Interval\n"
324 "Periodic Location Updating Interval\n")
325{
326 struct gsm_network *net = vty->index;
327
328 net->t3212 = 0;
329
330 return CMD_SUCCESS;
331}
332
Keith Whyte991bb422019-08-08 15:43:40 +0200333DEFUN(cfg_net_call_wait, cfg_net_call_wait_cmd,
334 "call-waiting",
335 "Enable Call Waiting on the Network\n")
336{
337 struct gsm_network *net = vty->index;
338
339 net->call_waiting = true;
340
341 return CMD_SUCCESS;
342}
343
344DEFUN(cfg_net_no_call_wait, cfg_net_no_call_wait_cmd,
345 "no call-waiting",
346 NO_STR
347 "Disable Call Waiting on the Network\n")
348{
349 struct gsm_network *net = vty->index;
350
351 net->call_waiting = false;
352
353 return CMD_SUCCESS;
354}
355
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100356static int config_write_net(struct vty *vty)
357{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100358 int i;
359
360 vty_out(vty, "network%s", VTY_NEWLINE);
361 vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
362 vty_out(vty, " mobile network code %s%s",
363 osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
364 vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
365 vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
366 vty_out(vty, " encryption a5");
367 for (i = 0; i < 8; i++) {
368 if (gsmnet->a5_encryption_mask & (1 << i))
369 vty_out(vty, " %u", i);
370 }
371 vty_out(vty, "%s", VTY_NEWLINE);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +0200372
373 if (!gsmnet->uea_encryption)
374 vty_out(vty, " encryption uea 0%s", VTY_NEWLINE);
375 else
376 vty_out(vty, " encryption uea 1 2%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100377 vty_out(vty, " authentication %s%s",
378 gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE);
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700379 vty_out(vty, " rrlp mode %s%s", msc_rrlp_mode_name(gsmnet->rrlp.mode),
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100380 VTY_NEWLINE);
381 vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
382 if (gsmnet->tz.override != 0) {
383 if (gsmnet->tz.dst)
384 vty_out(vty, " timezone %d %d %d%s",
385 gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
386 VTY_NEWLINE);
387 else
388 vty_out(vty, " timezone %d %d%s",
389 gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
390 }
391 if (gsmnet->t3212 == 0)
392 vty_out(vty, " no periodic location update%s", VTY_NEWLINE);
393 else
394 vty_out(vty, " periodic location update %u%s",
395 gsmnet->t3212 * 6, VTY_NEWLINE);
396
397 if (gsmnet->emergency.route_to_msisdn) {
398 vty_out(vty, " emergency-call route-to-msisdn %s%s",
399 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
400 }
401
Keith Whyte991bb422019-08-08 15:43:40 +0200402 if (!gsmnet->call_waiting)
403 vty_out(vty, " no call-waiting%s", VTY_NEWLINE);
404
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100405 return CMD_SUCCESS;
406}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200407
408static struct cmd_node msc_node = {
409 MSC_NODE,
410 "%s(config-msc)# ",
411 1,
412};
413
414DEFUN(cfg_msc, cfg_msc_cmd,
415 "msc", "Configure MSC options")
416{
417 vty->node = MSC_NODE;
418 return CMD_SUCCESS;
419}
420
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100421#define MNCC_STR "Configure Mobile Network Call Control\n"
422#define MNCC_GUARD_TIMEOUT_STR "Set global guard timer for mncc interface activity\n"
423#define MNCC_GUARD_TIMEOUT_VALUE_STR "guard timer value (sec.)\n"
424
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100425DEFUN(cfg_msc_mncc_internal,
426 cfg_msc_mncc_internal_cmd,
427 "mncc internal",
428 MNCC_STR "Use internal MNCC handler (default; changes need a program restart)\n")
429{
430 gsm_network_set_mncc_sock_path(gsmnet, NULL);
431 return CMD_SUCCESS;
432}
433
434DEFUN(cfg_msc_mncc_external,
435 cfg_msc_mncc_external_cmd,
436 "mncc external MNCC_SOCKET_PATH",
437 MNCC_STR "Use external MNCC handler (changes need a program restart)\n"
438 "File system path to create the MNCC unix domain socket at\n")
439{
440 gsm_network_set_mncc_sock_path(gsmnet, argv[0]);
441 return CMD_SUCCESS;
442}
443
Philipp Maier9ca7b312018-10-10 17:00:49 +0200444DEFUN(cfg_msc_mncc_guard_timeout,
445 cfg_msc_mncc_guard_timeout_cmd,
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100446 "mncc guard-timeout <0-255>",
447 MNCC_STR
448 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR)
Philipp Maier9ca7b312018-10-10 17:00:49 +0200449{
450 gsmnet->mncc_guard_timeout = atoi(argv[0]);
451 return CMD_SUCCESS;
452}
453
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100454ALIAS_DEPRECATED(cfg_msc_mncc_guard_timeout,
455 cfg_msc_deprecated_mncc_guard_timeout_cmd,
456 "mncc-guard-timeout <0-255>",
457 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR);
458
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700459#define NCSS_STR "Configure call independent Supplementary Services\n"
460
461DEFUN(cfg_msc_ncss_guard_timeout,
462 cfg_msc_ncss_guard_timeout_cmd,
463 "ncss guard-timeout <0-255>",
464 NCSS_STR "Set guard timer for session activity\n"
465 "guard timer value (sec.), or 0 to disable\n")
466{
467 gsmnet->ncss_guard_timeout = atoi(argv[0]);
468 return CMD_SUCCESS;
469}
470
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200471DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
472 "assign-tmsi",
473 "Assign TMSI during Location Updating.\n")
474{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200475 gsmnet->vlr->cfg.assign_tmsi = true;
476 return CMD_SUCCESS;
477}
478
479DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
480 "no assign-tmsi",
481 NO_STR "Assign TMSI during Location Updating.\n")
482{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200483 gsmnet->vlr->cfg.assign_tmsi = false;
484 return CMD_SUCCESS;
485}
486
Philipp Maierfbf66102017-04-09 12:32:51 +0200487DEFUN(cfg_msc_cs7_instance_a,
488 cfg_msc_cs7_instance_a_cmd,
489 "cs7-instance-a <0-15>",
490 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
491{
Philipp Maierfbf66102017-04-09 12:32:51 +0200492 gsmnet->a.cs7_instance = atoi(argv[0]);
493 return CMD_SUCCESS;
494}
495
496DEFUN(cfg_msc_cs7_instance_iu,
497 cfg_msc_cs7_instance_iu_cmd,
498 "cs7-instance-iu <0-15>",
499 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
500{
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100501#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200502 gsmnet->iu.cs7_instance = atoi(argv[0]);
503 return CMD_SUCCESS;
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100504#else
505 vty_out(vty, "WARNING: 'cs7-instance-iu' without effect: built without Iu support%s",
506 VTY_NEWLINE);
507 return CMD_WARNING;
508#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200509}
510
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100511DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
512 "auth-tuple-max-reuse-count <-1-2147483647>",
513 "Configure authentication tuple re-use\n"
514 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
515{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100516 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
517 return CMD_SUCCESS;
518}
519
520DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
521 "auth-tuple-reuse-on-error (0|1)",
522 "Configure authentication tuple re-use when HLR is not responsive\n"
Oliver Smithd6e24fd2019-01-09 10:46:43 +0100523 "Never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
524 "If the HLR does not deliver new tuples, do re-use already available old ones.\n")
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100525{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100526 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
527 return CMD_SUCCESS;
528}
529
Oliver Smith0fec28a2018-12-14 10:52:52 +0100530DEFUN(cfg_msc_check_imei_rqd, cfg_msc_check_imei_rqd_cmd,
Oliver Smith03ded912019-05-02 10:40:50 +0200531 "check-imei-rqd (0|1|early)",
Oliver Smith0fec28a2018-12-14 10:52:52 +0100532 "Send each IMEI to the EIR to ask if it is permitted or not. The EIR is implemented as part of OsmoHLR, "
533 "and can optionally save the IMEI in the HLR.\n"
534 "Do not send IMEIs to the EIR\n"
Oliver Smith03ded912019-05-02 10:40:50 +0200535 "Send each IMEI to the EIR\n"
536 "Send each IMEI to the EIR, and do it at the start of the location update. This allows the EIR to receive the"
537 " 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 +0100538{
Oliver Smith03ded912019-05-02 10:40:50 +0200539 if (strcmp(argv[0], "0") == 0) {
540 gsmnet->vlr->cfg.check_imei_rqd = false;
541 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
542 } else if (strcmp(argv[0], "1") == 0) {
543 gsmnet->vlr->cfg.check_imei_rqd = true;
544 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
545 } else if (strcmp(argv[0], "early") == 0) {
546 gsmnet->vlr->cfg.check_imei_rqd = true;
547 gsmnet->vlr->cfg.retrieve_imeisv_early = true;
548 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100549 return CMD_SUCCESS;
550}
551
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100552DEFUN(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
553 "paging response-timer (default|<1-65535>)",
554 "Configure Paging\n"
555 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
556 " BSS or RNC\n"
557 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
558 "Set paging timeout in seconds\n")
559{
Pau Espin Pedrolb08a3802019-09-16 19:01:37 +0200560 if (!strcmp(argv[0], "default"))
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100561 gsmnet->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
562 else
563 gsmnet->paging_response_timer = atoi(argv[0]);
564 return CMD_SUCCESS;
565}
566
Harald Welte69c54a82018-02-09 20:41:14 +0100567DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
568 "emergency-call route-to-msisdn MSISDN",
569 "Configure Emergency Call Behaviour\n"
570 "MSISDN to which Emergency Calls are Dispatched\n"
571 "MSISDN (E.164 Phone Number)\n")
572{
Harald Welte69c54a82018-02-09 20:41:14 +0100573 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
574
575 return CMD_SUCCESS;
576}
577
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700578/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
579DEFUN(cfg_msc_sms_over_gsup, cfg_msc_sms_over_gsup_cmd,
580 "sms-over-gsup",
581 "Enable routing of SMS messages over GSUP\n")
582{
583 gsmnet->sms_over_gsup = true;
584 return CMD_SUCCESS;
585}
586
587/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
588DEFUN(cfg_msc_no_sms_over_gsup, cfg_msc_no_sms_over_gsup_cmd,
589 "no sms-over-gsup",
590 NO_STR "Disable routing of SMS messages over GSUP\n")
591{
592 gsmnet->sms_over_gsup = false;
593 return CMD_SUCCESS;
594}
595
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100596/* FIXME: This should rather be in the form of
597 * handover-number range 001234xxx
598 * and
599 * handover-number range 001234xxx FIRST LAST
600 */
601DEFUN(cfg_msc_handover_number_range, cfg_msc_handover_number_range_cmd,
602 "handover-number range MSISDN_FIRST MSISDN_LAST",
603 "Configure a range of MSISDN to be assigned to incoming inter-MSC Handovers for call forwarding.\n"
604 "Configure a handover number range\n"
605 "First Handover Number MSISDN\n"
606 "Last Handover Number MSISDN\n")
607{
608 char *endp;
609 uint64_t range_start;
610 uint64_t range_end;
611
612 /* FIXME leading zeros?? */
613
614 errno = 0;
615 range_start = strtoull(argv[0], &endp, 10);
616 if (errno || *endp != '\0') {
617 vty_out(vty, "%% Error parsing handover-number range start: %s%s",
618 argv[0], VTY_NEWLINE);
619 return CMD_WARNING;
620 }
621
622 errno = 0;
623 range_end = strtoull(argv[1], &endp, 10);
624 if (errno || *endp != '\0') {
625 vty_out(vty, "%% Error parsing handover-number range end: %s%s",
626 argv[1], VTY_NEWLINE);
627 return CMD_WARNING;
628 }
629
630 if (range_start > range_end) {
631 vty_out(vty, "%% Error: handover-number range end must be > than the range start, but"
632 " %"PRIu64" > %"PRIu64"%s", range_start, range_end, VTY_NEWLINE);
633 return CMD_WARNING;
634 }
635
636 gsmnet->handover_number.range_start = range_start;
637 gsmnet->handover_number.range_end = range_end;
638 return CMD_SUCCESS;
639}
640
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200641#define OSMUX_STR "RTP multiplexing\n"
642DEFUN(cfg_msc_osmux,
643 cfg_msc_osmux_cmd,
644 "osmux (on|off|only)",
645 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
646{
647 if (strcmp(argv[0], "off") == 0)
648 gsmnet->use_osmux = OSMUX_USAGE_OFF;
649 else if (strcmp(argv[0], "on") == 0)
650 gsmnet->use_osmux = OSMUX_USAGE_ON;
651 else if (strcmp(argv[0], "only") == 0)
652 gsmnet->use_osmux = OSMUX_USAGE_ONLY;
653
654 return CMD_SUCCESS;
655}
656
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200657static int config_write_msc(struct vty *vty)
658{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200659 vty_out(vty, "msc%s", VTY_NEWLINE);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100660 if (gsmnet->mncc_sock_path)
661 vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE);
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100662 vty_out(vty, " mncc guard-timeout %i%s",
Philipp Maier9ca7b312018-10-10 17:00:49 +0200663 gsmnet->mncc_guard_timeout, VTY_NEWLINE);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700664 vty_out(vty, " ncss guard-timeout %i%s",
665 gsmnet->ncss_guard_timeout, VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200666 vty_out(vty, " %sassign-tmsi%s",
667 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
668
Philipp Maierfbf66102017-04-09 12:32:51 +0200669 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
670 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100671#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200672 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
673 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100674#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200675
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100676 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
677 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
678 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
679 VTY_NEWLINE);
680 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
681 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
682 VTY_NEWLINE);
683
Oliver Smith03ded912019-05-02 10:40:50 +0200684 if (gsmnet->vlr->cfg.check_imei_rqd) {
685 if (gsmnet->vlr->cfg.retrieve_imeisv_early)
686 vty_out(vty, " check-imei-rqd early%s", VTY_NEWLINE);
687 else
688 vty_out(vty, " check-imei-rqd 1%s", VTY_NEWLINE);
689 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100690
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100691 if (gsmnet->paging_response_timer != MSC_PAGING_RESPONSE_TIMER_DEFAULT)
692 vty_out(vty, " paging response-timer %u%s", gsmnet->paging_response_timer, VTY_NEWLINE);
693
Harald Welte69c54a82018-02-09 20:41:14 +0100694 if (gsmnet->emergency.route_to_msisdn) {
695 vty_out(vty, " emergency-call route-to-msisdn %s%s",
696 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
697 }
698
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700699 if (gsmnet->sms_over_gsup)
700 vty_out(vty, " sms-over-gsup%s", VTY_NEWLINE);
701
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100702 if (gsmnet->handover_number.range_start || gsmnet->handover_number.range_end)
703 vty_out(vty, " handover-number range %"PRIu64" %"PRIu64"%s",
704 gsmnet->handover_number.range_start, gsmnet->handover_number.range_end,
705 VTY_NEWLINE);
706
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200707 if (gsmnet->use_osmux != OSMUX_USAGE_OFF) {
708 vty_out(vty, " osmux %s%s", gsmnet->use_osmux == OSMUX_USAGE_ON ? "on" : "only",
709 VTY_NEWLINE);
710 }
711
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200712 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200713#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200714 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200715#endif
716
Neels Hofmeyr880b9502019-05-09 02:01:55 +0200717 neighbor_ident_vty_write(vty);
718
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200719 return CMD_SUCCESS;
720}
721
Maxc51609a2018-11-09 17:13:00 +0100722DEFUN(show_bsc, show_bsc_cmd,
723 "show bsc", SHOW_STR "BSC\n")
724{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100725 struct ran_peer *rp;
726 llist_for_each_entry(rp, &gsmnet->a.sri->ran_peers, entry) {
727 vty_out(vty, "BSC %s %s%s",
728 osmo_sccp_inst_addr_name(gsmnet->a.sri->sccp, &rp->peer_addr),
729 osmo_fsm_inst_state_name(rp->fi),
730 VTY_NEWLINE);
Maxc51609a2018-11-09 17:13:00 +0100731 }
732
733 return CMD_SUCCESS;
734}
735
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100736static const char *get_trans_proto_str(const struct gsm_trans *trans)
737{
738 static char buf[256];
739
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100740 switch (trans->type) {
741 case TRANS_CC:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100742 snprintf(buf, sizeof(buf), "%s %4u %4u",
743 gsm48_cc_state_name(trans->cc.state),
744 trans->cc.Tcurrent,
745 trans->cc.T308_second);
746 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100747 case TRANS_SMS:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700748 snprintf(buf, sizeof(buf), "CP:%s RP:%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100749 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
750 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
751 break;
752 default:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700753 return NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100754 }
755
756 return buf;
757}
758
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700759/* Prefix a given format string with a given amount of spaces */
760#define MSC_VTY_DUMP(vty, offset, fmt, args...) \
761 vty_out(vty, "%*s" fmt, offset, "", ##args)
762
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200763/* Print value of a named flag, prefixed with a given amount of spaces */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700764#define MSC_VTY_DUMP_FLAG(vty, offset, name, flag) \
765 MSC_VTY_DUMP(vty, offset + 2, "%s: %*s%s%s", \
766 name, 30 - (int)strlen(name), "", \
767 flag ? "true" : "false", \
768 VTY_NEWLINE)
769
770enum msc_vty_dump_flags {
771 MSC_VTY_DUMP_F_SUBSCR = (1 << 0),
772 MSC_VTY_DUMP_F_CONNECTION = (1 << 1),
773 MSC_VTY_DUMP_F_TRANSACTION = (1 << 2),
774};
775
776static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans,
777 int offset, uint8_t dump_flags)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100778{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700779 const char *proto_str;
780
781 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
782 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
783 vlr_subscr_name(msc_a_vsub(trans->msc_a)),
784 VTY_NEWLINE);
785 }
786
787 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200788 /* (If msc_a exists, there *must* be a non-null msc_a->c.msub) */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700789 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
790 trans->msc_a ? msub_ran_conn_name(trans->msc_a->c.msub)
791 : "(not established)",
792 VTY_NEWLINE);
793 }
794
795 MSC_VTY_DUMP(vty, offset, "Unique (global) identifier: 0x%08x%s",
796 trans->callref, VTY_NEWLINE);
797 MSC_VTY_DUMP(vty, offset, "GSM 04.07 identifier (%s): %u%s",
798 (trans->transaction_id & 0x08) ? "MO" : "MT",
799 trans->transaction_id,
800 VTY_NEWLINE);
801
802 MSC_VTY_DUMP(vty, offset, "Type: %s%s",
803 trans_type_name(trans->type),
804 VTY_NEWLINE);
805
806 if ((proto_str = get_trans_proto_str(trans))) {
807 MSC_VTY_DUMP(vty, offset, "Protocol specific: %s%s",
808 proto_str, VTY_NEWLINE);
809 }
810}
811
812static void vty_dump_one_conn(struct vty *vty, const struct msub *msub,
813 int offset, uint8_t dump_flags)
814{
815 struct vlr_subscr *vsub = msub_vsub(msub);
816 struct msc_a *msc_a = msub_msc_a(msub);
817 char buf[128];
818
819 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
820 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
821 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
822 vlr_subscr_name(vsub),
823 VTY_NEWLINE);
824 }
825
826 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
827 msub_ran_conn_name(msub),
828 VTY_NEWLINE);
829 MSC_VTY_DUMP(vty, offset, "RAN connection state: %s%s",
830 osmo_fsm_inst_state_name(msc_a->c.fi),
831 VTY_NEWLINE);
832
833 if (vsub) {
834 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
835 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
836 VTY_NEWLINE);
837 }
838
839 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
840 osmo_use_count_total(&msc_a->use_count),
841 VTY_NEWLINE);
842 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
843 osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count),
844 VTY_NEWLINE);
845
846 /* Transactions of this connection */
847 if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
848 struct gsm_trans *trans;
849 unsigned int i = 0;
850
851 /* Both subscriber and connection info is already printed */
852 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_CONNECTION;
853 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
854
855 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
856 if (trans->msc_a != msc_a)
857 continue;
858 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
859 i++, VTY_NEWLINE);
860 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
861 }
862 }
863}
864
865static void vty_dump_one_subscr(struct vty *vty, struct vlr_subscr *vsub,
866 int offset, uint8_t dump_flags)
867{
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700868 struct gsm_network *net;
869 struct timespec now;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700870 char buf[128];
871
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700872 if (vsub->name[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700873 MSC_VTY_DUMP(vty, offset, "Name: '%s'%s",
874 vsub->name, VTY_NEWLINE);
875 }
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700876 if (vsub->msisdn[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700877 MSC_VTY_DUMP(vty, offset, "MSISDN: %s%s",
878 vsub->msisdn, VTY_NEWLINE);
879 }
880
881 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
882 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
883 VTY_NEWLINE);
884 MSC_VTY_DUMP(vty, offset, "RAN type: %s%s",
885 osmo_rat_type_name(vsub->cs.attached_via_ran),
886 VTY_NEWLINE);
887
888 MSC_VTY_DUMP(vty, offset, "IMSI: %s%s",
889 vsub->imsi, VTY_NEWLINE);
890 if (vsub->tmsi != GSM_RESERVED_TMSI) {
891 MSC_VTY_DUMP(vty, offset, "TMSI: %08X%s",
892 vsub->tmsi, VTY_NEWLINE);
893 }
894 if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
895 MSC_VTY_DUMP(vty, offset, "New TMSI: %08X%s",
896 vsub->tmsi_new, VTY_NEWLINE);
897 }
898 if (vsub->imei[0] != '\0') {
899 MSC_VTY_DUMP(vty, offset, "IMEI: %s%s",
900 vsub->imei, VTY_NEWLINE);
901 }
902 if (vsub->imeisv[0] != '\0') {
903 MSC_VTY_DUMP(vty, offset, "IMEISV: %s%s",
904 vsub->imeisv, VTY_NEWLINE);
905 }
906
907 MSC_VTY_DUMP(vty, offset, "Flags: %s", VTY_NEWLINE);
908 MSC_VTY_DUMP_FLAG(vty, offset, "IMSI detached",
909 vsub->imsi_detached_flag);
910 MSC_VTY_DUMP_FLAG(vty, offset, "Conf. by radio contact",
911 vsub->conf_by_radio_contact_ind);
912 MSC_VTY_DUMP_FLAG(vty, offset, "Subscr. data conf. by HLR",
913 vsub->sub_dataconf_by_hlr_ind);
914 MSC_VTY_DUMP_FLAG(vty, offset, "Location conf. in HLR",
915 vsub->loc_conf_in_hlr_ind);
916 MSC_VTY_DUMP_FLAG(vty, offset, "Subscriber dormant",
917 vsub->dormant_ind);
918 MSC_VTY_DUMP_FLAG(vty, offset, "Received cancel location",
919 vsub->cancel_loc_rx);
920 MSC_VTY_DUMP_FLAG(vty, offset, "MS not reachable",
921 vsub->ms_not_reachable_flag);
922 MSC_VTY_DUMP_FLAG(vty, offset, "LA allowed",
923 vsub->la_allowed);
924
925 if (vsub->last_tuple) {
926 struct vlr_auth_tuple *t = vsub->last_tuple;
927 MSC_VTY_DUMP(vty, offset, "A3A8 last tuple (used %d times): %s",
928 t->use_count, VTY_NEWLINE);
929 MSC_VTY_DUMP(vty, offset + 2, "seq # : %d%s",
930 t->key_seq, VTY_NEWLINE);
931 MSC_VTY_DUMP(vty, offset + 2, "RAND : %s%s",
932 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
933 VTY_NEWLINE);
934 MSC_VTY_DUMP(vty, offset + 2, "SRES : %s%s",
935 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
936 VTY_NEWLINE);
937 MSC_VTY_DUMP(vty, offset + 2, "Kc : %s%s",
938 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
939 VTY_NEWLINE);
940 }
941
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700942 /* XXX move t3212 into struct vlr_instance? */
943 net = vsub->vlr->user_ctx;
944 if (!net->t3212) {
945 MSC_VTY_DUMP(vty, offset, "Expires: never (T3212 is disabled)%s",
946 VTY_NEWLINE);
947 } else if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) {
948 MSC_VTY_DUMP(vty, offset, "Expires: never%s",
949 VTY_NEWLINE);
950 } else if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
951 MSC_VTY_DUMP(vty, offset, "Expires: in %ld min %ld sec%s",
952 (vsub->expire_lu - now.tv_sec) / 60,
953 (vsub->expire_lu - now.tv_sec) % 60,
954 VTY_NEWLINE);
955 }
956
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700957 MSC_VTY_DUMP(vty, offset, "Paging: %s paging for %d requests%s",
958 vsub->cs.is_paging ? "is" : "not",
959 llist_count(&vsub->cs.requests),
960 VTY_NEWLINE);
961
962 /* SGs related */
963 MSC_VTY_DUMP(vty, offset, "SGs-state: %s%s",
964 osmo_fsm_inst_state_name(vsub->sgs_fsm),
965 VTY_NEWLINE);
966 MSC_VTY_DUMP(vty, offset, "SGs-MME: %s%s",
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700967 vsub->sgs.mme_name[0] != '\0' ? vsub->sgs.mme_name : "(none)",
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700968 VTY_NEWLINE);
969
970 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
971 osmo_use_count_total(&vsub->use_count),
972 VTY_NEWLINE);
973 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
974 osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count),
975 VTY_NEWLINE);
976
977 /* Connection(s) and/or transactions of this subscriber */
978 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
979 struct msub *msub = msub_for_vsub(vsub);
980 if (!msub)
981 return;
982
983 /* Subscriber info is already printed */
984 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
985
986 MSC_VTY_DUMP(vty, offset, "Connection: %s", VTY_NEWLINE);
987 vty_dump_one_conn(vty, msub, offset + 2, dump_flags);
988 } else if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
989 struct gsm_trans *trans;
990 unsigned int i = 0;
991
992 /* Subscriber info is already printed */
993 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
994 /* Do not print connection info, but mention it */
995 dump_flags |= MSC_VTY_DUMP_F_CONNECTION;
996
997 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
998 if (trans->vsub != vsub)
999 continue;
1000 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
1001 i++, VTY_NEWLINE);
1002 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
1003 }
1004 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001005}
1006
1007DEFUN(show_msc_transaction, show_msc_transaction_cmd,
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001008 "show transaction",
1009 SHOW_STR "Transactions\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001010{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001011 struct gsm_trans *trans;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001012 uint8_t flags = 0x00;
1013 unsigned int i = 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001014
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001015 flags |= MSC_VTY_DUMP_F_CONNECTION;
1016 flags |= MSC_VTY_DUMP_F_SUBSCR;
1017
1018 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
1019 vty_out(vty, " Transaction #%02u: %s", i++, VTY_NEWLINE);
1020 vty_dump_one_trans(vty, trans, 4, flags);
1021 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001022
1023 return CMD_SUCCESS;
1024}
1025
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001026DEFUN(show_msc_conn, show_msc_conn_cmd,
1027 "show connection [trans]",
1028 SHOW_STR "Subscriber Connections\n"
1029 "Show child transactions of each connection\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001030{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001031 uint8_t flags = 0x00;
1032 unsigned int i = 0;
1033 struct msub *msub;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001034
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001035 if (argc > 0)
1036 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1037 flags |= MSC_VTY_DUMP_F_SUBSCR;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001038
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001039 llist_for_each_entry(msub, &msub_list, entry) {
1040 vty_out(vty, " Connection #%02u: %s", i++, VTY_NEWLINE);
1041 vty_dump_one_conn(vty, msub, 4, flags);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001042 }
1043
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001044 return CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001045}
1046
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001047#define SUBSCR_FLAGS "[(conn|trans|conn+trans)]"
1048#define SUBSCR_FLAGS_HELP \
1049 "Show child connections\n" \
1050 "Show child transactions\n" \
1051 "Show child connections and transactions\n"
1052
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001053/* Subscriber */
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001054DEFUN(show_subscr_cache, show_subscr_cache_cmd,
1055 "show subscriber cache " SUBSCR_FLAGS,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001056 SHOW_STR "Show information about subscribers\n"
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001057 "Display contents of subscriber cache\n"
1058 SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001059{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001060 struct vlr_subscr *vsub;
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001061 unsigned int count = 0;
1062 uint8_t flags = 0x00;
1063 unsigned int i = 0;
1064
1065 if (argc && strcmp(argv[0], "conn") == 0)
1066 flags |= MSC_VTY_DUMP_F_CONNECTION;
1067 else if (argc && strcmp(argv[0], "trans") == 0)
1068 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1069 else if (argc && strcmp(argv[0], "conn+trans") == 0)
1070 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001071
1072 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
1073 if (++count > 100) {
1074 vty_out(vty, "%% More than %d subscribers in cache,"
1075 " stopping here.%s", count-1, VTY_NEWLINE);
1076 break;
1077 }
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001078 vty_out(vty, " Subscriber #%02u: %s", i++, VTY_NEWLINE);
1079 vty_dump_one_subscr(vty, vsub, 4, flags);
Harald Welte69c54a82018-02-09 20:41:14 +01001080 }
1081
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001082 return CMD_SUCCESS;
1083}
1084
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001085DEFUN(sms_send_pend,
1086 sms_send_pend_cmd,
1087 "sms send pending",
1088 "SMS related commands\n" "SMS Sending related commands\n"
1089 "Send all pending SMS")
1090{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001091 struct gsm_sms *sms;
1092 unsigned long long sms_id = 0;
1093
1094 while (1) {
1095 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1096 if (!sms)
1097 break;
1098
1099 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001100 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001101
1102 sms_id = sms->id + 1;
1103 }
1104
1105 return CMD_SUCCESS;
1106}
1107
1108DEFUN(sms_delete_expired,
1109 sms_delete_expired_cmd,
1110 "sms delete expired",
1111 "SMS related commands\n" "SMS Database related commands\n"
1112 "Delete all expired SMS")
1113{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001114 struct gsm_sms *sms;
1115 unsigned long long sms_id = 0;
1116 long long num_deleted = 0;
1117
1118 while (1) {
1119 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1120 if (!sms)
1121 break;
1122
1123 /* Skip SMS which are currently queued for sending. */
1124 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
1125 continue;
1126
1127 /* Expiration check is performed by the DB layer. */
1128 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
1129 num_deleted++;
1130
1131 sms_id = sms->id + 1;
1132 }
1133
1134 if (num_deleted == 0) {
1135 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
1136 return CMD_WARNING;
1137 }
1138
1139 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
1140 return CMD_SUCCESS;
1141}
1142
1143static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +02001144 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001145 char *str, uint8_t tp_pid)
1146{
1147 struct gsm_network *net = receiver->vlr->user_ctx;
1148 struct gsm_sms *sms;
1149
Harald Welte39b55482018-04-09 19:19:33 +02001150 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Vadim Yanitskiydb4839c2019-12-01 18:52:58 +07001151 if (!sms) {
1152 LOGP(DLSMS, LOGL_ERROR, "Failed to allocate SMS\n");
1153 return CMD_WARNING;
1154 }
1155
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001156 sms->protocol_id = tp_pid;
1157
1158 /* store in database for the queue */
1159 if (db_sms_store(sms) != 0) {
1160 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
1161 sms_free(sms);
1162 return CMD_WARNING;
1163 }
1164 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
1165
1166 sms_free(sms);
1167 sms_queue_trigger(net->sms_queue);
1168 return CMD_SUCCESS;
1169}
1170
1171static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
1172 const char *type,
1173 const char *id)
1174{
1175 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001176 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001177 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001178 return vlr_subscr_find_by_imsi(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001179 else if (!strcmp(type, "tmsi"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001180 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id), VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001181
1182 return NULL;
1183}
1184#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
1185#define SUBSCR_HELP "Operations on a Subscriber\n" \
1186 "Identify subscriber by MSISDN (phone number)\n" \
1187 "Legacy alias for 'msisdn'\n" \
1188 "Identify subscriber by IMSI\n" \
1189 "Identify subscriber by TMSI\n" \
Vadim Yanitskiy3ccd8232019-05-16 01:35:23 +07001190 "Legacy alias for 'imsi'\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001191 "Identifier for the subscriber\n"
1192
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001193DEFUN(show_subscr, show_subscr_cmd,
1194 "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
1195 SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001196{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001197 struct vlr_subscr *vsub;
1198 uint8_t flags = 0x00;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001199
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001200 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001201 if (!vsub) {
1202 vty_out(vty, "%% No subscriber found for %s %s%s",
1203 argv[0], argv[1], VTY_NEWLINE);
1204 return CMD_WARNING;
1205 }
1206
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001207 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
1208 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
1209 * 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 +01001210 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001211
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001212 if (argc > 2 && strcmp(argv[2], "conn") == 0)
1213 flags |= MSC_VTY_DUMP_F_CONNECTION;
1214 else if (argc > 2 && strcmp(argv[2], "trans") == 0)
1215 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1216 else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
1217 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
1218
1219 vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
1220 vty_dump_one_subscr(vty, vsub, 4, flags);
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001221
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001222 return CMD_SUCCESS;
1223}
1224
1225DEFUN(subscriber_create,
1226 subscriber_create_cmd,
1227 "subscriber create imsi ID",
1228 "Operations on a Subscriber\n" \
1229 "Create new subscriber\n" \
1230 "Identify the subscriber by his IMSI\n" \
1231 "Identifier for the subscriber\n")
1232{
1233 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
1234 VTY_NEWLINE);
1235 return CMD_WARNING;
1236}
1237
1238DEFUN(subscriber_send_pending_sms,
1239 subscriber_send_pending_sms_cmd,
1240 "subscriber " SUBSCR_TYPES " ID sms pending-send",
1241 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
1242{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001243 struct vlr_subscr *vsub;
1244 struct gsm_sms *sms;
1245
1246 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1247 if (!vsub) {
1248 vty_out(vty, "%% No subscriber found for %s %s%s",
1249 argv[0], argv[1], VTY_NEWLINE);
1250 return CMD_WARNING;
1251 }
1252
1253 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
1254 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001255 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001256
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001257 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001258
1259 return CMD_SUCCESS;
1260}
1261
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001262DEFUN(subscriber_sms_delete_all,
1263 subscriber_sms_delete_all_cmd,
1264 "subscriber " SUBSCR_TYPES " ID sms delete-all",
1265 SUBSCR_HELP "SMS Operations\n"
1266 "Delete all SMS to be delivered to this subscriber"
1267 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
1268 " WILL BE LOST.\n")
1269{
1270 struct vlr_subscr *vsub;
1271
1272 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1273 if (!vsub) {
1274 vty_out(vty, "%% No subscriber found for %s %s%s",
1275 argv[0], argv[1], VTY_NEWLINE);
1276 return CMD_WARNING;
1277 }
1278
1279 db_sms_delete_by_msisdn(vsub->msisdn);
1280
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001281 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001282
1283 return CMD_SUCCESS;
1284}
1285
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001286DEFUN(subscriber_send_sms,
1287 subscriber_send_sms_cmd,
1288 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1289 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1290{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001291 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001292 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001293 char *str;
1294 int rc;
1295
1296 if (!vsub) {
1297 vty_out(vty, "%% No subscriber found for %s %s%s",
1298 argv[0], argv[1], VTY_NEWLINE);
1299 rc = CMD_WARNING;
1300 goto err;
1301 }
1302
Harald Welte39b55482018-04-09 19:19:33 +02001303 if (!strcmp(argv[2], "msisdn"))
1304 sender_msisdn = argv[3];
1305 else {
1306 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1307 if (!sender) {
1308 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1309 rc = CMD_WARNING;
1310 goto err;
1311 }
1312 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001313 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001314 }
1315
1316 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001317 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001318 talloc_free(str);
1319
1320err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001321 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001322 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001323
1324 return rc;
1325}
1326
1327DEFUN(subscriber_silent_sms,
1328 subscriber_silent_sms_cmd,
1329
1330 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1331 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1332{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001333 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001334 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001335 char *str;
1336 int rc;
1337
1338 if (!vsub) {
1339 vty_out(vty, "%% No subscriber found for %s %s%s",
1340 argv[0], argv[1], VTY_NEWLINE);
1341 rc = CMD_WARNING;
1342 goto err;
1343 }
1344
Harald Welte39b55482018-04-09 19:19:33 +02001345 if (!strcmp(argv[2], "msisdn")) {
1346 sender_msisdn = argv[3];
1347 } else {
1348 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1349 if (!sender) {
1350 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1351 rc = CMD_WARNING;
1352 goto err;
1353 }
1354 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001355 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001356 }
1357
1358 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001359 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001360 talloc_free(str);
1361
1362err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001363 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001364 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001365
1366 return rc;
1367}
1368
Sylvain Munaut93558302019-02-14 20:13:08 +01001369#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001370#define CHAN_TYPE_HELP \
1371 "Any channel\n" \
1372 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001373 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001374 "Any TCH channel\n" \
1375 "SDCCH channel\n"
1376
Sylvain Munaut93558302019-02-14 20:13:08 +01001377#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1378#define CHAN_MODE_HELP \
1379 "Signalling only\n" \
1380 "Speech with HR codec\n" \
1381 "Speech with FR codec\n" \
1382 "Speech with EFR codec\n" \
1383 "Speech with AMR codec\n"
1384
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001385DEFUN(subscriber_silent_call_start,
1386 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001387 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001388 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001389 CHAN_TYPE_HELP CHAN_MODE_HELP
1390 "Target IP for RTP traffic (default 127.0.0.1)\n"
1391 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001392{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001393 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001394 struct gsm0808_channel_type ct;
1395 const char *ip;
1396 uint16_t port;
1397 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001398
1399 if (!vsub) {
1400 vty_out(vty, "%% No subscriber found for %s %s%s",
1401 argv[0], argv[1], VTY_NEWLINE);
1402 return CMD_WARNING;
1403 }
1404
Sylvain Munaut93558302019-02-14 20:13:08 +01001405 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001406
Sylvain Munaut93558302019-02-14 20:13:08 +01001407 if (!strcmp(argv[3], "signalling")) {
1408 ct.ch_indctr = GSM0808_CHAN_SIGN;
1409 ct.perm_spch[0] = 0; /* Spare but required */
1410 ct.perm_spch_len = 1;
1411 } else if (!strcmp(argv[3], "speech-hr")) {
1412 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1413 ct.perm_spch[0] = GSM0808_PERM_HR1;
1414 ct.perm_spch_len = 1;
1415 } else if (!strcmp(argv[3], "speech-fr")) {
1416 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1417 ct.perm_spch[0] = GSM0808_PERM_FR1;
1418 ct.perm_spch_len = 1;
1419 } else if (!strcmp(argv[3], "speech-efr")) {
1420 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1421 ct.perm_spch[0] = GSM0808_PERM_FR2;
1422 ct.perm_spch_len = 1;
1423 } else if (!strcmp(argv[3], "speech-amr")) {
1424 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1425 ct.perm_spch[0] = GSM0808_PERM_FR3;
1426 ct.perm_spch[1] = GSM0808_PERM_HR3;
1427 ct.perm_spch_len = 2;
1428 }
1429
1430 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1431
1432 if (!strcmp(argv[2], "tch/f"))
1433 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1434 else if (!strcmp(argv[2], "tch/h"))
1435 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1436 else if (!strcmp(argv[2], "tch/any"))
1437 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1438 else if (!strcmp(argv[2], "sdcch")) {
1439 if (speech) {
1440 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1441 return CMD_WARNING;
1442 }
1443 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1444 } else
1445 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1446
1447 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1448 port = argc >= 6 ? atoi(argv[5]) : 4000;
1449
1450 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001451 switch (rc) {
1452 case -ENODEV:
1453 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1454 break;
1455 default:
1456 if (rc)
1457 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1458 else
1459 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1460 break;
1461 }
1462
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001463 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001464 return rc ? CMD_WARNING : CMD_SUCCESS;
1465}
1466
1467DEFUN(subscriber_silent_call_stop,
1468 subscriber_silent_call_stop_cmd,
1469 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1470 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1471 CHAN_TYPE_HELP)
1472{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001473 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1474 int rc;
1475
1476 if (!vsub) {
1477 vty_out(vty, "%% No subscriber found for %s %s%s",
1478 argv[0], argv[1], VTY_NEWLINE);
1479 return CMD_WARNING;
1480 }
1481
1482 rc = gsm_silent_call_stop(vsub);
1483 switch (rc) {
1484 case -ENODEV:
1485 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1486 break;
1487 case -ENOENT:
1488 vty_out(vty, "%% Subscriber has no silent call active%s",
1489 VTY_NEWLINE);
1490 break;
1491 default:
1492 if (rc)
1493 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1494 else
1495 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1496 break;
1497 }
1498
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001499 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001500 return rc ? CMD_WARNING : CMD_SUCCESS;
1501}
1502
1503DEFUN(subscriber_ussd_notify,
1504 subscriber_ussd_notify_cmd,
1505 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1506 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1507 "Alerting Level 0\n"
1508 "Alerting Level 1\n"
1509 "Alerting Level 2\n"
1510 "Text of USSD message to send\n")
1511{
1512 char *text;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001513 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001514 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1515 int level;
1516
1517 if (!vsub) {
1518 vty_out(vty, "%% No subscriber found for %s %s%s",
1519 argv[0], argv[1], VTY_NEWLINE);
1520 return CMD_WARNING;
1521 }
1522
1523 level = atoi(argv[2]);
1524 text = argv_concat(argv, argc, 3);
1525 if (!text) {
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001526 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001527 return CMD_WARNING;
1528 }
1529
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001530 msc_a = msc_a_for_vsub(vsub, true);
1531 if (!msc_a || msc_a->c.remote_to) {
1532 vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001533 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001534 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001535 talloc_free(text);
1536 return CMD_WARNING;
1537 }
1538
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001539 msc_send_ussd_notify(msc_a, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001540 /* FIXME: since we don't allocate a transaction here,
1541 * we use dummy GSM 04.07 transaction ID. */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001542 msc_send_ussd_release_complete(msc_a, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001543
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001544 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001545 talloc_free(text);
1546 return CMD_SUCCESS;
1547}
1548
1549DEFUN(subscriber_paging,
1550 subscriber_paging_cmd,
1551 "subscriber " SUBSCR_TYPES " ID paging",
1552 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1553{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001554 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001555 struct paging_request *req;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001556
1557 if (!vsub) {
1558 vty_out(vty, "%% No subscriber found for %s %s%s",
1559 argv[0], argv[1], VTY_NEWLINE);
1560 return CMD_WARNING;
1561 }
1562
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001563 req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL,
1564 NULL, NULL, "manual Paging from VTY");
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001565 if (req)
1566 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1567 else
1568 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1569
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001570 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001571 return req ? CMD_SUCCESS : CMD_WARNING;
1572}
1573
1574static int loop_by_char(uint8_t ch)
1575{
1576 switch (ch) {
1577 case 'a':
1578 return GSM414_LOOP_A;
1579 case 'b':
1580 return GSM414_LOOP_B;
1581 case 'c':
1582 return GSM414_LOOP_C;
1583 case 'd':
1584 return GSM414_LOOP_D;
1585 case 'e':
1586 return GSM414_LOOP_E;
1587 case 'f':
1588 return GSM414_LOOP_F;
1589 case 'i':
1590 return GSM414_LOOP_I;
1591 }
1592 return -1;
1593}
1594
1595DEFUN(subscriber_mstest_close,
1596 subscriber_mstest_close_cmd,
1597 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1598 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1599 "Close a TCH Loop inside the MS\n"
1600 "Loop Type A\n"
1601 "Loop Type B\n"
1602 "Loop Type C\n"
1603 "Loop Type D\n"
1604 "Loop Type E\n"
1605 "Loop Type F\n"
1606 "Loop Type I\n")
1607{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001608 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001609 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1610 const char *loop_str;
1611 int loop_mode;
1612
1613 if (!vsub) {
1614 vty_out(vty, "%% No subscriber found for %s %s%s",
1615 argv[0], argv[1], VTY_NEWLINE);
1616 return CMD_WARNING;
1617 }
1618
1619 loop_str = argv[2];
1620 loop_mode = loop_by_char(loop_str[0]);
1621
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001622 msc_a = msc_a_for_vsub(vsub, true);
1623 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001624 vty_out(vty, "%% An active connection is required for %s %s%s",
1625 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001626 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001627 return CMD_WARNING;
1628 }
1629
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001630 gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001631
1632 return CMD_SUCCESS;
1633}
1634
1635DEFUN(subscriber_mstest_open,
1636 subscriber_mstest_open_cmd,
1637 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1638 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1639 "Open a TCH Loop inside the MS\n")
1640{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001641 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001642 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1643
1644 if (!vsub) {
1645 vty_out(vty, "%% No subscriber found for %s %s%s",
1646 argv[0], argv[1], VTY_NEWLINE);
1647 return CMD_WARNING;
1648 }
1649
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001650 msc_a = msc_a_for_vsub(vsub, true);
1651 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001652 vty_out(vty, "%% An active connection is required for %s %s%s",
1653 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001654 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001655 return CMD_WARNING;
1656 }
1657
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001658 gsm0414_tx_open_loop_cmd(msc_a);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001659
1660 return CMD_SUCCESS;
1661}
1662
1663DEFUN(ena_subscr_expire,
1664 ena_subscr_expire_cmd,
1665 "subscriber " SUBSCR_TYPES " ID expire",
1666 SUBSCR_HELP "Expire the subscriber Now\n")
1667{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001668 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1669 argv[1]);
1670
1671 if (!vsub) {
1672 vty_out(vty, "%% No subscriber found for %s %s%s",
1673 argv[0], argv[1], VTY_NEWLINE);
1674 return CMD_WARNING;
1675 }
1676
1677 if (vlr_subscr_expire(vsub))
1678 vty_out(vty, "%% VLR released subscriber %s%s",
1679 vlr_subscr_name(vsub), VTY_NEWLINE);
1680
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001681 if (osmo_use_count_total(&vsub->use_count) > 1)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001682 vty_out(vty, "%% Subscriber %s is still in use,"
1683 " should be released soon%s",
1684 vlr_subscr_name(vsub), VTY_NEWLINE);
1685
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001686 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001687 return CMD_SUCCESS;
1688}
1689
1690static int scall_cbfn(unsigned int subsys, unsigned int signal,
1691 void *handler_data, void *signal_data)
1692{
1693 struct scall_signal_data *sigdata = signal_data;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001694 struct vty *vty = sigdata->vty;
1695
1696 if (!vty_is_active(vty))
1697 return 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001698
1699 switch (signal) {
1700 case S_SCALL_SUCCESS:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001701 vty_out(vty, "%% Silent call success%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001702 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001703 case S_SCALL_FAILED:
1704 vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE);
1705 break;
1706 case S_SCALL_DETACHED:
1707 vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001708 break;
1709 }
1710 return 0;
1711}
1712
1713DEFUN(show_stats,
1714 show_stats_cmd,
1715 "show statistics",
1716 SHOW_STR "Display network statistics\n")
1717{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001718 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001719 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1720 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1721 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001722 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001723 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001724 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001725 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001726 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001727 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1728 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001729 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001730 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001731 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1732 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001733 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001734 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001735 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1736 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1737 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001738 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001739 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001740 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1741 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001742 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001743 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001744 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1745 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001746 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001747 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001748 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current,
1749 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1750 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current
1751 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1752 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001753 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001754 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current,
1755 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1756 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current
1757 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1758 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001759 return CMD_SUCCESS;
1760}
1761
1762DEFUN(show_smsqueue,
1763 show_smsqueue_cmd,
1764 "show sms-queue",
1765 SHOW_STR "Display SMSqueue statistics\n")
1766{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001767 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001768 return CMD_SUCCESS;
1769}
1770
1771DEFUN(smsqueue_trigger,
1772 smsqueue_trigger_cmd,
1773 "sms-queue trigger",
1774 "SMS Queue\n" "Trigger sending messages\n")
1775{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001776 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001777 return CMD_SUCCESS;
1778}
1779
1780DEFUN(smsqueue_max,
1781 smsqueue_max_cmd,
1782 "sms-queue max-pending <1-500>",
1783 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1784{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001785 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001786 return CMD_SUCCESS;
1787}
1788
1789DEFUN(smsqueue_clear,
1790 smsqueue_clear_cmd,
1791 "sms-queue clear",
1792 "SMS Queue\n" "Clear the queue of pending SMS\n")
1793{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001794 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001795 return CMD_SUCCESS;
1796}
1797
1798DEFUN(smsqueue_fail,
1799 smsqueue_fail_cmd,
1800 "sms-queue max-failure <1-500>",
1801 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1802{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001803 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001804 return CMD_SUCCESS;
1805}
1806
1807
1808DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1809 "mncc-int", "Configure internal MNCC handler")
1810{
1811 vty->node = MNCC_INT_NODE;
1812
1813 return CMD_SUCCESS;
1814}
1815
1816static struct cmd_node mncc_int_node = {
1817 MNCC_INT_NODE,
1818 "%s(config-mncc-int)# ",
1819 1,
1820};
1821
1822static const struct value_string tchf_codec_names[] = {
1823 { GSM48_CMODE_SPEECH_V1, "fr" },
1824 { GSM48_CMODE_SPEECH_EFR, "efr" },
1825 { GSM48_CMODE_SPEECH_AMR, "amr" },
1826 { 0, NULL }
1827};
1828
1829static const struct value_string tchh_codec_names[] = {
1830 { GSM48_CMODE_SPEECH_V1, "hr" },
1831 { GSM48_CMODE_SPEECH_AMR, "amr" },
1832 { 0, NULL }
1833};
1834
1835static int config_write_mncc_int(struct vty *vty)
1836{
1837 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1838 vty_out(vty, " default-codec tch-f %s%s",
1839 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1840 VTY_NEWLINE);
1841 vty_out(vty, " default-codec tch-h %s%s",
1842 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1843 VTY_NEWLINE);
1844
1845 return CMD_SUCCESS;
1846}
1847
1848DEFUN(mnccint_def_codec_f,
1849 mnccint_def_codec_f_cmd,
1850 "default-codec tch-f (fr|efr|amr)",
1851 "Set default codec\n" "Codec for TCH/F\n"
1852 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1853{
1854 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1855
1856 return CMD_SUCCESS;
1857}
1858
1859DEFUN(mnccint_def_codec_h,
1860 mnccint_def_codec_h_cmd,
1861 "default-codec tch-h (hr|amr)",
1862 "Set default codec\n" "Codec for TCH/H\n"
1863 "Half-Rate\n" "Adaptive Multi-Rate\n")
1864{
1865 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1866
1867 return CMD_SUCCESS;
1868}
1869
1870
1871DEFUN(logging_fltr_imsi,
1872 logging_fltr_imsi_cmd,
1873 "logging filter imsi IMSI",
1874 LOGGING_STR FILTER_STR
1875 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1876{
1877 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001878 struct log_target *tgt = osmo_log_vty2tgt(vty);
1879 const char *imsi = argv[0];
1880
1881 if (!tgt)
1882 return CMD_WARNING;
1883
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001884 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001885
1886 if (!vlr_subscr) {
1887 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1888 argv[0], VTY_NEWLINE);
1889 return CMD_WARNING;
1890 }
1891
1892 log_set_filter_vlr_subscr(tgt, vlr_subscr);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001893 vlr_subscr_put(vlr_subscr, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001894 return CMD_SUCCESS;
1895}
1896
1897static struct cmd_node hlr_node = {
1898 HLR_NODE,
1899 "%s(config-hlr)# ",
1900 1,
1901};
1902
1903DEFUN(cfg_hlr, cfg_hlr_cmd,
1904 "hlr", "Configure connection to the HLR")
1905{
1906 vty->node = HLR_NODE;
1907 return CMD_SUCCESS;
1908}
1909
1910DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1911 "Remote GSUP address of the HLR\n"
1912 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1913{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001914 talloc_free((void*)gsmnet->gsup_server_addr_str);
1915 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1916 return CMD_SUCCESS;
1917}
1918
1919DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1920 "Remote GSUP port of the HLR\n"
1921 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1922{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001923 gsmnet->gsup_server_port = atoi(argv[0]);
1924 return CMD_SUCCESS;
1925}
1926
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001927DEFUN(cfg_hlr_ipa_name,
1928 cfg_hlr_ipa_name_cmd,
1929 "ipa-name NAME",
1930 "Set the IPA name of this MSC\n"
1931 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1932 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
1933 "The default is 'MSC-00-00-00-00-00-00'.\n")
1934{
1935 if (vty->type != VTY_FILE) {
1936 vty_out(vty, "The IPA name cannot be changed at run-time; "
Martin Hauke3f07dac2019-11-14 17:49:08 +01001937 "It can only be set in the configuration file.%s", VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001938 return CMD_WARNING;
1939 }
1940
1941 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
1942 return CMD_SUCCESS;
1943}
1944
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001945static int config_write_hlr(struct vty *vty)
1946{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001947 vty_out(vty, "hlr%s", VTY_NEWLINE);
1948 vty_out(vty, " remote-ip %s%s",
1949 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1950 vty_out(vty, " remote-port %u%s",
1951 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001952 if (gsmnet->msc_ipa_name)
1953 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001954 return CMD_SUCCESS;
1955}
1956
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001957void msc_vty_init(struct gsm_network *msc_network)
1958{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001959 OSMO_ASSERT(gsmnet == NULL);
1960 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001961
1962 osmo_stats_vty_add_cmds();
1963
1964 install_element(CONFIG_NODE, &cfg_net_cmd);
1965 install_node(&net_node, config_write_net);
1966 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1967 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1968 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1969 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1970 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +02001971 install_element(GSMNET_NODE, &cfg_net_encryption_uea_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001972 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1973 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1974 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1975 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1976 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1977 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1978 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1979 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Keith Whyte991bb422019-08-08 15:43:40 +02001980 install_element(GSMNET_NODE, &cfg_net_call_wait_cmd);
1981 install_element(GSMNET_NODE, &cfg_net_no_call_wait_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001982
1983 install_element(CONFIG_NODE, &cfg_msc_cmd);
1984 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001985 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01001986 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
1987 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02001988 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01001989 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07001990 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001991 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001992 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
1993 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01001994 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001995 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
1996 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01001997 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01001998 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07001999 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
2000 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +02002001 install_element(MSC_NODE, &cfg_msc_osmux_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002002 install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd);
2003
2004 neighbor_ident_vty_init(msc_network);
Philipp Maierfbf66102017-04-09 12:32:51 +02002005
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02002006 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002007#ifdef BUILD_IU
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002008 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 +02002009#endif
Harald Welte0df904d2018-12-03 11:00:04 +01002010 sgs_vty_init();
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002011
Stefan Sperling617ac802018-02-22 17:58:20 +01002012 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002013
2014 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
2015
2016 install_element_ve(&show_subscr_cmd);
2017 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01002018 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002019 install_element_ve(&show_msc_conn_cmd);
2020 install_element_ve(&show_msc_transaction_cmd);
2021
2022 install_element_ve(&sms_send_pend_cmd);
2023 install_element_ve(&sms_delete_expired_cmd);
2024
2025 install_element_ve(&subscriber_create_cmd);
2026 install_element_ve(&subscriber_send_sms_cmd);
2027 install_element_ve(&subscriber_silent_sms_cmd);
2028 install_element_ve(&subscriber_silent_call_start_cmd);
2029 install_element_ve(&subscriber_silent_call_stop_cmd);
2030 install_element_ve(&subscriber_ussd_notify_cmd);
2031 install_element_ve(&subscriber_mstest_close_cmd);
2032 install_element_ve(&subscriber_mstest_open_cmd);
2033 install_element_ve(&subscriber_paging_cmd);
2034 install_element_ve(&show_stats_cmd);
2035 install_element_ve(&show_smsqueue_cmd);
2036 install_element_ve(&logging_fltr_imsi_cmd);
2037
2038 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
2039 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
2040 install_element(ENABLE_NODE, &smsqueue_max_cmd);
2041 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
2042 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
2043 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01002044 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002045
2046 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
2047 install_node(&mncc_int_node, config_write_mncc_int);
2048 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
2049 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
2050
2051 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
2052
2053 install_element(CONFIG_NODE, &cfg_hlr_cmd);
2054 install_node(&hlr_node, config_write_hlr);
2055 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
2056 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002057 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002058}