blob: f833585e381bf8ba3c5c5c8f11b34d10075289b8 [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);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001151 sms->protocol_id = tp_pid;
1152
1153 /* store in database for the queue */
1154 if (db_sms_store(sms) != 0) {
1155 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
1156 sms_free(sms);
1157 return CMD_WARNING;
1158 }
1159 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
1160
1161 sms_free(sms);
1162 sms_queue_trigger(net->sms_queue);
1163 return CMD_SUCCESS;
1164}
1165
1166static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
1167 const char *type,
1168 const char *id)
1169{
1170 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001171 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001172 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001173 return vlr_subscr_find_by_imsi(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001174 else if (!strcmp(type, "tmsi"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001175 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id), VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001176
1177 return NULL;
1178}
1179#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
1180#define SUBSCR_HELP "Operations on a Subscriber\n" \
1181 "Identify subscriber by MSISDN (phone number)\n" \
1182 "Legacy alias for 'msisdn'\n" \
1183 "Identify subscriber by IMSI\n" \
1184 "Identify subscriber by TMSI\n" \
Vadim Yanitskiy3ccd8232019-05-16 01:35:23 +07001185 "Legacy alias for 'imsi'\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001186 "Identifier for the subscriber\n"
1187
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001188DEFUN(show_subscr, show_subscr_cmd,
1189 "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
1190 SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001191{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001192 struct vlr_subscr *vsub;
1193 uint8_t flags = 0x00;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001194
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001195 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001196 if (!vsub) {
1197 vty_out(vty, "%% No subscriber found for %s %s%s",
1198 argv[0], argv[1], VTY_NEWLINE);
1199 return CMD_WARNING;
1200 }
1201
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001202 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
1203 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
1204 * 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 +01001205 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001206
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001207 if (argc > 2 && strcmp(argv[2], "conn") == 0)
1208 flags |= MSC_VTY_DUMP_F_CONNECTION;
1209 else if (argc > 2 && strcmp(argv[2], "trans") == 0)
1210 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1211 else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
1212 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
1213
1214 vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
1215 vty_dump_one_subscr(vty, vsub, 4, flags);
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001216
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001217 return CMD_SUCCESS;
1218}
1219
1220DEFUN(subscriber_create,
1221 subscriber_create_cmd,
1222 "subscriber create imsi ID",
1223 "Operations on a Subscriber\n" \
1224 "Create new subscriber\n" \
1225 "Identify the subscriber by his IMSI\n" \
1226 "Identifier for the subscriber\n")
1227{
1228 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
1229 VTY_NEWLINE);
1230 return CMD_WARNING;
1231}
1232
1233DEFUN(subscriber_send_pending_sms,
1234 subscriber_send_pending_sms_cmd,
1235 "subscriber " SUBSCR_TYPES " ID sms pending-send",
1236 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
1237{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001238 struct vlr_subscr *vsub;
1239 struct gsm_sms *sms;
1240
1241 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1242 if (!vsub) {
1243 vty_out(vty, "%% No subscriber found for %s %s%s",
1244 argv[0], argv[1], VTY_NEWLINE);
1245 return CMD_WARNING;
1246 }
1247
1248 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
1249 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001250 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001251
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001252 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001253
1254 return CMD_SUCCESS;
1255}
1256
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001257DEFUN(subscriber_sms_delete_all,
1258 subscriber_sms_delete_all_cmd,
1259 "subscriber " SUBSCR_TYPES " ID sms delete-all",
1260 SUBSCR_HELP "SMS Operations\n"
1261 "Delete all SMS to be delivered to this subscriber"
1262 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
1263 " WILL BE LOST.\n")
1264{
1265 struct vlr_subscr *vsub;
1266
1267 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1268 if (!vsub) {
1269 vty_out(vty, "%% No subscriber found for %s %s%s",
1270 argv[0], argv[1], VTY_NEWLINE);
1271 return CMD_WARNING;
1272 }
1273
1274 db_sms_delete_by_msisdn(vsub->msisdn);
1275
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001276 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001277
1278 return CMD_SUCCESS;
1279}
1280
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001281DEFUN(subscriber_send_sms,
1282 subscriber_send_sms_cmd,
1283 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1284 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1285{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001286 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001287 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001288 char *str;
1289 int rc;
1290
1291 if (!vsub) {
1292 vty_out(vty, "%% No subscriber found for %s %s%s",
1293 argv[0], argv[1], VTY_NEWLINE);
1294 rc = CMD_WARNING;
1295 goto err;
1296 }
1297
Harald Welte39b55482018-04-09 19:19:33 +02001298 if (!strcmp(argv[2], "msisdn"))
1299 sender_msisdn = argv[3];
1300 else {
1301 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1302 if (!sender) {
1303 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1304 rc = CMD_WARNING;
1305 goto err;
1306 }
1307 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001308 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001309 }
1310
1311 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001312 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001313 talloc_free(str);
1314
1315err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001316 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001317 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001318
1319 return rc;
1320}
1321
1322DEFUN(subscriber_silent_sms,
1323 subscriber_silent_sms_cmd,
1324
1325 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1326 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1327{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001328 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001329 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001330 char *str;
1331 int rc;
1332
1333 if (!vsub) {
1334 vty_out(vty, "%% No subscriber found for %s %s%s",
1335 argv[0], argv[1], VTY_NEWLINE);
1336 rc = CMD_WARNING;
1337 goto err;
1338 }
1339
Harald Welte39b55482018-04-09 19:19:33 +02001340 if (!strcmp(argv[2], "msisdn")) {
1341 sender_msisdn = argv[3];
1342 } else {
1343 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1344 if (!sender) {
1345 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1346 rc = CMD_WARNING;
1347 goto err;
1348 }
1349 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001350 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001351 }
1352
1353 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001354 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001355 talloc_free(str);
1356
1357err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001358 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001359 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001360
1361 return rc;
1362}
1363
Sylvain Munaut93558302019-02-14 20:13:08 +01001364#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001365#define CHAN_TYPE_HELP \
1366 "Any channel\n" \
1367 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001368 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001369 "Any TCH channel\n" \
1370 "SDCCH channel\n"
1371
Sylvain Munaut93558302019-02-14 20:13:08 +01001372#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1373#define CHAN_MODE_HELP \
1374 "Signalling only\n" \
1375 "Speech with HR codec\n" \
1376 "Speech with FR codec\n" \
1377 "Speech with EFR codec\n" \
1378 "Speech with AMR codec\n"
1379
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001380DEFUN(subscriber_silent_call_start,
1381 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001382 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001383 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001384 CHAN_TYPE_HELP CHAN_MODE_HELP
1385 "Target IP for RTP traffic (default 127.0.0.1)\n"
1386 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001387{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001388 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001389 struct gsm0808_channel_type ct;
1390 const char *ip;
1391 uint16_t port;
1392 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001393
1394 if (!vsub) {
1395 vty_out(vty, "%% No subscriber found for %s %s%s",
1396 argv[0], argv[1], VTY_NEWLINE);
1397 return CMD_WARNING;
1398 }
1399
Sylvain Munaut93558302019-02-14 20:13:08 +01001400 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001401
Sylvain Munaut93558302019-02-14 20:13:08 +01001402 if (!strcmp(argv[3], "signalling")) {
1403 ct.ch_indctr = GSM0808_CHAN_SIGN;
1404 ct.perm_spch[0] = 0; /* Spare but required */
1405 ct.perm_spch_len = 1;
1406 } else if (!strcmp(argv[3], "speech-hr")) {
1407 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1408 ct.perm_spch[0] = GSM0808_PERM_HR1;
1409 ct.perm_spch_len = 1;
1410 } else if (!strcmp(argv[3], "speech-fr")) {
1411 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1412 ct.perm_spch[0] = GSM0808_PERM_FR1;
1413 ct.perm_spch_len = 1;
1414 } else if (!strcmp(argv[3], "speech-efr")) {
1415 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1416 ct.perm_spch[0] = GSM0808_PERM_FR2;
1417 ct.perm_spch_len = 1;
1418 } else if (!strcmp(argv[3], "speech-amr")) {
1419 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1420 ct.perm_spch[0] = GSM0808_PERM_FR3;
1421 ct.perm_spch[1] = GSM0808_PERM_HR3;
1422 ct.perm_spch_len = 2;
1423 }
1424
1425 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1426
1427 if (!strcmp(argv[2], "tch/f"))
1428 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1429 else if (!strcmp(argv[2], "tch/h"))
1430 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1431 else if (!strcmp(argv[2], "tch/any"))
1432 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1433 else if (!strcmp(argv[2], "sdcch")) {
1434 if (speech) {
1435 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1436 return CMD_WARNING;
1437 }
1438 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1439 } else
1440 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1441
1442 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1443 port = argc >= 6 ? atoi(argv[5]) : 4000;
1444
1445 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001446 switch (rc) {
1447 case -ENODEV:
1448 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1449 break;
1450 default:
1451 if (rc)
1452 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1453 else
1454 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1455 break;
1456 }
1457
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001458 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001459 return rc ? CMD_WARNING : CMD_SUCCESS;
1460}
1461
1462DEFUN(subscriber_silent_call_stop,
1463 subscriber_silent_call_stop_cmd,
1464 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1465 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1466 CHAN_TYPE_HELP)
1467{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001468 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1469 int rc;
1470
1471 if (!vsub) {
1472 vty_out(vty, "%% No subscriber found for %s %s%s",
1473 argv[0], argv[1], VTY_NEWLINE);
1474 return CMD_WARNING;
1475 }
1476
1477 rc = gsm_silent_call_stop(vsub);
1478 switch (rc) {
1479 case -ENODEV:
1480 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1481 break;
1482 case -ENOENT:
1483 vty_out(vty, "%% Subscriber has no silent call active%s",
1484 VTY_NEWLINE);
1485 break;
1486 default:
1487 if (rc)
1488 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1489 else
1490 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1491 break;
1492 }
1493
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001494 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001495 return rc ? CMD_WARNING : CMD_SUCCESS;
1496}
1497
1498DEFUN(subscriber_ussd_notify,
1499 subscriber_ussd_notify_cmd,
1500 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1501 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1502 "Alerting Level 0\n"
1503 "Alerting Level 1\n"
1504 "Alerting Level 2\n"
1505 "Text of USSD message to send\n")
1506{
1507 char *text;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001508 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001509 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1510 int level;
1511
1512 if (!vsub) {
1513 vty_out(vty, "%% No subscriber found for %s %s%s",
1514 argv[0], argv[1], VTY_NEWLINE);
1515 return CMD_WARNING;
1516 }
1517
1518 level = atoi(argv[2]);
1519 text = argv_concat(argv, argc, 3);
1520 if (!text) {
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001521 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001522 return CMD_WARNING;
1523 }
1524
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001525 msc_a = msc_a_for_vsub(vsub, true);
1526 if (!msc_a || msc_a->c.remote_to) {
1527 vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001528 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001529 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001530 talloc_free(text);
1531 return CMD_WARNING;
1532 }
1533
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001534 msc_send_ussd_notify(msc_a, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001535 /* FIXME: since we don't allocate a transaction here,
1536 * we use dummy GSM 04.07 transaction ID. */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001537 msc_send_ussd_release_complete(msc_a, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001538
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001539 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001540 talloc_free(text);
1541 return CMD_SUCCESS;
1542}
1543
1544DEFUN(subscriber_paging,
1545 subscriber_paging_cmd,
1546 "subscriber " SUBSCR_TYPES " ID paging",
1547 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1548{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001549 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001550 struct paging_request *req;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001551
1552 if (!vsub) {
1553 vty_out(vty, "%% No subscriber found for %s %s%s",
1554 argv[0], argv[1], VTY_NEWLINE);
1555 return CMD_WARNING;
1556 }
1557
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001558 req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL,
1559 NULL, NULL, "manual Paging from VTY");
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001560 if (req)
1561 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1562 else
1563 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1564
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001565 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001566 return req ? CMD_SUCCESS : CMD_WARNING;
1567}
1568
1569static int loop_by_char(uint8_t ch)
1570{
1571 switch (ch) {
1572 case 'a':
1573 return GSM414_LOOP_A;
1574 case 'b':
1575 return GSM414_LOOP_B;
1576 case 'c':
1577 return GSM414_LOOP_C;
1578 case 'd':
1579 return GSM414_LOOP_D;
1580 case 'e':
1581 return GSM414_LOOP_E;
1582 case 'f':
1583 return GSM414_LOOP_F;
1584 case 'i':
1585 return GSM414_LOOP_I;
1586 }
1587 return -1;
1588}
1589
1590DEFUN(subscriber_mstest_close,
1591 subscriber_mstest_close_cmd,
1592 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1593 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1594 "Close a TCH Loop inside the MS\n"
1595 "Loop Type A\n"
1596 "Loop Type B\n"
1597 "Loop Type C\n"
1598 "Loop Type D\n"
1599 "Loop Type E\n"
1600 "Loop Type F\n"
1601 "Loop Type I\n")
1602{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001603 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001604 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1605 const char *loop_str;
1606 int loop_mode;
1607
1608 if (!vsub) {
1609 vty_out(vty, "%% No subscriber found for %s %s%s",
1610 argv[0], argv[1], VTY_NEWLINE);
1611 return CMD_WARNING;
1612 }
1613
1614 loop_str = argv[2];
1615 loop_mode = loop_by_char(loop_str[0]);
1616
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001617 msc_a = msc_a_for_vsub(vsub, true);
1618 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001619 vty_out(vty, "%% An active connection is required for %s %s%s",
1620 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001621 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001622 return CMD_WARNING;
1623 }
1624
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001625 gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001626
1627 return CMD_SUCCESS;
1628}
1629
1630DEFUN(subscriber_mstest_open,
1631 subscriber_mstest_open_cmd,
1632 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1633 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1634 "Open a TCH Loop inside the MS\n")
1635{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001636 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001637 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1638
1639 if (!vsub) {
1640 vty_out(vty, "%% No subscriber found for %s %s%s",
1641 argv[0], argv[1], VTY_NEWLINE);
1642 return CMD_WARNING;
1643 }
1644
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001645 msc_a = msc_a_for_vsub(vsub, true);
1646 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001647 vty_out(vty, "%% An active connection is required for %s %s%s",
1648 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001649 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001650 return CMD_WARNING;
1651 }
1652
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001653 gsm0414_tx_open_loop_cmd(msc_a);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001654
1655 return CMD_SUCCESS;
1656}
1657
1658DEFUN(ena_subscr_expire,
1659 ena_subscr_expire_cmd,
1660 "subscriber " SUBSCR_TYPES " ID expire",
1661 SUBSCR_HELP "Expire the subscriber Now\n")
1662{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001663 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1664 argv[1]);
1665
1666 if (!vsub) {
1667 vty_out(vty, "%% No subscriber found for %s %s%s",
1668 argv[0], argv[1], VTY_NEWLINE);
1669 return CMD_WARNING;
1670 }
1671
1672 if (vlr_subscr_expire(vsub))
1673 vty_out(vty, "%% VLR released subscriber %s%s",
1674 vlr_subscr_name(vsub), VTY_NEWLINE);
1675
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001676 if (osmo_use_count_total(&vsub->use_count) > 1)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001677 vty_out(vty, "%% Subscriber %s is still in use,"
1678 " should be released soon%s",
1679 vlr_subscr_name(vsub), VTY_NEWLINE);
1680
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001681 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001682 return CMD_SUCCESS;
1683}
1684
1685static int scall_cbfn(unsigned int subsys, unsigned int signal,
1686 void *handler_data, void *signal_data)
1687{
1688 struct scall_signal_data *sigdata = signal_data;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001689 struct vty *vty = sigdata->vty;
1690
1691 if (!vty_is_active(vty))
1692 return 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001693
1694 switch (signal) {
1695 case S_SCALL_SUCCESS:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001696 vty_out(vty, "%% Silent call success%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001697 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001698 case S_SCALL_FAILED:
1699 vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE);
1700 break;
1701 case S_SCALL_DETACHED:
1702 vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001703 break;
1704 }
1705 return 0;
1706}
1707
1708DEFUN(show_stats,
1709 show_stats_cmd,
1710 "show statistics",
1711 SHOW_STR "Display network statistics\n")
1712{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001713 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001714 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1715 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1716 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001717 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001718 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001719 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001720 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001721 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001722 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1723 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001724 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001725 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001726 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1727 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001728 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001729 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001730 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1731 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1732 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001733 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001734 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001735 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1736 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001737 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001738 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001739 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1740 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001741 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001742 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001743 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current,
1744 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1745 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current
1746 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1747 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001748 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001749 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current,
1750 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1751 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current
1752 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1753 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001754 return CMD_SUCCESS;
1755}
1756
1757DEFUN(show_smsqueue,
1758 show_smsqueue_cmd,
1759 "show sms-queue",
1760 SHOW_STR "Display SMSqueue statistics\n")
1761{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001762 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001763 return CMD_SUCCESS;
1764}
1765
1766DEFUN(smsqueue_trigger,
1767 smsqueue_trigger_cmd,
1768 "sms-queue trigger",
1769 "SMS Queue\n" "Trigger sending messages\n")
1770{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001771 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001772 return CMD_SUCCESS;
1773}
1774
1775DEFUN(smsqueue_max,
1776 smsqueue_max_cmd,
1777 "sms-queue max-pending <1-500>",
1778 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1779{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001780 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001781 return CMD_SUCCESS;
1782}
1783
1784DEFUN(smsqueue_clear,
1785 smsqueue_clear_cmd,
1786 "sms-queue clear",
1787 "SMS Queue\n" "Clear the queue of pending SMS\n")
1788{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001789 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001790 return CMD_SUCCESS;
1791}
1792
1793DEFUN(smsqueue_fail,
1794 smsqueue_fail_cmd,
1795 "sms-queue max-failure <1-500>",
1796 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1797{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001798 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001799 return CMD_SUCCESS;
1800}
1801
1802
1803DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1804 "mncc-int", "Configure internal MNCC handler")
1805{
1806 vty->node = MNCC_INT_NODE;
1807
1808 return CMD_SUCCESS;
1809}
1810
1811static struct cmd_node mncc_int_node = {
1812 MNCC_INT_NODE,
1813 "%s(config-mncc-int)# ",
1814 1,
1815};
1816
1817static const struct value_string tchf_codec_names[] = {
1818 { GSM48_CMODE_SPEECH_V1, "fr" },
1819 { GSM48_CMODE_SPEECH_EFR, "efr" },
1820 { GSM48_CMODE_SPEECH_AMR, "amr" },
1821 { 0, NULL }
1822};
1823
1824static const struct value_string tchh_codec_names[] = {
1825 { GSM48_CMODE_SPEECH_V1, "hr" },
1826 { GSM48_CMODE_SPEECH_AMR, "amr" },
1827 { 0, NULL }
1828};
1829
1830static int config_write_mncc_int(struct vty *vty)
1831{
1832 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1833 vty_out(vty, " default-codec tch-f %s%s",
1834 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1835 VTY_NEWLINE);
1836 vty_out(vty, " default-codec tch-h %s%s",
1837 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1838 VTY_NEWLINE);
1839
1840 return CMD_SUCCESS;
1841}
1842
1843DEFUN(mnccint_def_codec_f,
1844 mnccint_def_codec_f_cmd,
1845 "default-codec tch-f (fr|efr|amr)",
1846 "Set default codec\n" "Codec for TCH/F\n"
1847 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1848{
1849 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1850
1851 return CMD_SUCCESS;
1852}
1853
1854DEFUN(mnccint_def_codec_h,
1855 mnccint_def_codec_h_cmd,
1856 "default-codec tch-h (hr|amr)",
1857 "Set default codec\n" "Codec for TCH/H\n"
1858 "Half-Rate\n" "Adaptive Multi-Rate\n")
1859{
1860 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1861
1862 return CMD_SUCCESS;
1863}
1864
1865
1866DEFUN(logging_fltr_imsi,
1867 logging_fltr_imsi_cmd,
1868 "logging filter imsi IMSI",
1869 LOGGING_STR FILTER_STR
1870 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1871{
1872 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001873 struct log_target *tgt = osmo_log_vty2tgt(vty);
1874 const char *imsi = argv[0];
1875
1876 if (!tgt)
1877 return CMD_WARNING;
1878
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001879 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001880
1881 if (!vlr_subscr) {
1882 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1883 argv[0], VTY_NEWLINE);
1884 return CMD_WARNING;
1885 }
1886
1887 log_set_filter_vlr_subscr(tgt, vlr_subscr);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001888 vlr_subscr_put(vlr_subscr, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001889 return CMD_SUCCESS;
1890}
1891
1892static struct cmd_node hlr_node = {
1893 HLR_NODE,
1894 "%s(config-hlr)# ",
1895 1,
1896};
1897
1898DEFUN(cfg_hlr, cfg_hlr_cmd,
1899 "hlr", "Configure connection to the HLR")
1900{
1901 vty->node = HLR_NODE;
1902 return CMD_SUCCESS;
1903}
1904
1905DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1906 "Remote GSUP address of the HLR\n"
1907 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1908{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001909 talloc_free((void*)gsmnet->gsup_server_addr_str);
1910 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1911 return CMD_SUCCESS;
1912}
1913
1914DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1915 "Remote GSUP port of the HLR\n"
1916 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1917{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001918 gsmnet->gsup_server_port = atoi(argv[0]);
1919 return CMD_SUCCESS;
1920}
1921
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001922DEFUN(cfg_hlr_ipa_name,
1923 cfg_hlr_ipa_name_cmd,
1924 "ipa-name NAME",
1925 "Set the IPA name of this MSC\n"
1926 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1927 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
1928 "The default is 'MSC-00-00-00-00-00-00'.\n")
1929{
1930 if (vty->type != VTY_FILE) {
1931 vty_out(vty, "The IPA name cannot be changed at run-time; "
Martin Hauke3f07dac2019-11-14 17:49:08 +01001932 "It can only be set in the configuration file.%s", VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001933 return CMD_WARNING;
1934 }
1935
1936 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
1937 return CMD_SUCCESS;
1938}
1939
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001940static int config_write_hlr(struct vty *vty)
1941{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001942 vty_out(vty, "hlr%s", VTY_NEWLINE);
1943 vty_out(vty, " remote-ip %s%s",
1944 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1945 vty_out(vty, " remote-port %u%s",
1946 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001947 if (gsmnet->msc_ipa_name)
1948 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001949 return CMD_SUCCESS;
1950}
1951
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001952void msc_vty_init(struct gsm_network *msc_network)
1953{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001954 OSMO_ASSERT(gsmnet == NULL);
1955 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001956
1957 osmo_stats_vty_add_cmds();
1958
1959 install_element(CONFIG_NODE, &cfg_net_cmd);
1960 install_node(&net_node, config_write_net);
1961 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1962 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1963 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1964 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1965 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
Neels Hofmeyr4dfb2ba2019-08-13 16:00:37 +02001966 install_element(GSMNET_NODE, &cfg_net_encryption_uea_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001967 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1968 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1969 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1970 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1971 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1972 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1973 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1974 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Keith Whyte991bb422019-08-08 15:43:40 +02001975 install_element(GSMNET_NODE, &cfg_net_call_wait_cmd);
1976 install_element(GSMNET_NODE, &cfg_net_no_call_wait_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001977
1978 install_element(CONFIG_NODE, &cfg_msc_cmd);
1979 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001980 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01001981 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
1982 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02001983 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01001984 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07001985 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001986 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001987 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
1988 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01001989 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001990 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
1991 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01001992 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01001993 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07001994 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
1995 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +02001996 install_element(MSC_NODE, &cfg_msc_osmux_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001997 install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd);
1998
1999 neighbor_ident_vty_init(msc_network);
Philipp Maierfbf66102017-04-09 12:32:51 +02002000
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02002001 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002002#ifdef BUILD_IU
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002003 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 +02002004#endif
Harald Welte0df904d2018-12-03 11:00:04 +01002005 sgs_vty_init();
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01002006
Stefan Sperling617ac802018-02-22 17:58:20 +01002007 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002008
2009 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
2010
2011 install_element_ve(&show_subscr_cmd);
2012 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01002013 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002014 install_element_ve(&show_msc_conn_cmd);
2015 install_element_ve(&show_msc_transaction_cmd);
2016
2017 install_element_ve(&sms_send_pend_cmd);
2018 install_element_ve(&sms_delete_expired_cmd);
2019
2020 install_element_ve(&subscriber_create_cmd);
2021 install_element_ve(&subscriber_send_sms_cmd);
2022 install_element_ve(&subscriber_silent_sms_cmd);
2023 install_element_ve(&subscriber_silent_call_start_cmd);
2024 install_element_ve(&subscriber_silent_call_stop_cmd);
2025 install_element_ve(&subscriber_ussd_notify_cmd);
2026 install_element_ve(&subscriber_mstest_close_cmd);
2027 install_element_ve(&subscriber_mstest_open_cmd);
2028 install_element_ve(&subscriber_paging_cmd);
2029 install_element_ve(&show_stats_cmd);
2030 install_element_ve(&show_smsqueue_cmd);
2031 install_element_ve(&logging_fltr_imsi_cmd);
2032
2033 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
2034 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
2035 install_element(ENABLE_NODE, &smsqueue_max_cmd);
2036 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
2037 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
2038 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01002039 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002040
2041 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
2042 install_node(&mncc_int_node, config_write_mncc_int);
2043 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
2044 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
2045
2046 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
2047
2048 install_element(CONFIG_NODE, &cfg_hlr_cmd);
2049 install_node(&hlr_node, config_write_hlr);
2050 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
2051 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01002052 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02002053}