blob: 6404ee94abc1c79d7aa5d17571133cf65c9a6a6f [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 Hofmeyr00e82d62017-07-05 15:19:52 +020026#include "../../bscconfig.h"
27
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020028#include <inttypes.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010029#include <limits.h>
30
31#include <osmocom/gsm/protocol/gsm_08_58.h>
32#include <osmocom/gsm/protocol/gsm_04_14.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020033
Maxc51609a2018-11-09 17:13:00 +010034#include <osmocom/sigtran/sccp_helpers.h>
35
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020036#include <osmocom/vty/command.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010037#include <osmocom/vty/logging.h>
Stefan Sperling617ac802018-02-22 17:58:20 +010038#include <osmocom/vty/misc.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010039#include <osmocom/vty/stats.h>
40
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020041#ifdef BUILD_IU
42#include <osmocom/ranap/iu_client.h>
43#endif
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020044
Neels Hofmeyr90843962017-09-04 15:04:35 +020045#include <osmocom/msc/vty.h>
46#include <osmocom/msc/gsm_data.h>
47#include <osmocom/msc/gsm_subscriber.h>
48#include <osmocom/msc/vlr.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010049#include <osmocom/msc/transaction.h>
50#include <osmocom/msc/db.h>
Maxc51609a2018-11-09 17:13:00 +010051#include <osmocom/msc/a_iface.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010052#include <osmocom/msc/sms_queue.h>
53#include <osmocom/msc/silent_call.h>
54#include <osmocom/msc/gsm_04_80.h>
55#include <osmocom/msc/gsm_04_14.h>
56#include <osmocom/msc/signal.h>
57#include <osmocom/msc/mncc_int.h>
Vadim Yanitskiy1b891302018-08-04 01:33:08 +070058#include <osmocom/msc/rrlp.h>
Harald Welte0df904d2018-12-03 11:00:04 +010059#include <osmocom/msc/vlr_sgs.h>
60#include <osmocom/msc/sgs_vty.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010061
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010062static struct gsm_network *gsmnet = NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010063
64struct cmd_node net_node = {
65 GSMNET_NODE,
66 "%s(config-net)# ",
67 1,
68};
69
70#define NETWORK_STR "Configure the GSM network\n"
71#define CODE_CMD_STR "Code commands\n"
72#define NAME_CMD_STR "Name Commands\n"
73#define NAME_STR "Name to use\n"
74
75DEFUN(cfg_net,
76 cfg_net_cmd,
77 "network", NETWORK_STR)
78{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010079 vty->index = gsmnet;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010080 vty->node = GSMNET_NODE;
81
82 return CMD_SUCCESS;
83}
84
85DEFUN(cfg_net_ncc,
86 cfg_net_ncc_cmd,
87 "network country code <1-999>",
88 "Set the GSM network country code\n"
89 "Country commands\n"
90 CODE_CMD_STR
91 "Network Country Code to use\n")
92{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010093 gsmnet->plmn.mcc = atoi(argv[0]);
94
95 return CMD_SUCCESS;
96}
97
98DEFUN(cfg_net_mnc,
99 cfg_net_mnc_cmd,
100 "mobile network code <0-999>",
101 "Set the GSM mobile network code\n"
102 "Network Commands\n"
103 CODE_CMD_STR
104 "Mobile Network Code to use\n")
105{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100106 uint16_t mnc;
107 bool mnc_3_digits;
108
109 if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
110 vty_out(vty, "%% Error decoding MNC: %s%s", argv[0], VTY_NEWLINE);
111 return CMD_WARNING;
112 }
113
114 gsmnet->plmn.mnc = mnc;
115 gsmnet->plmn.mnc_3_digits = mnc_3_digits;
116
117 return CMD_SUCCESS;
118}
119
120DEFUN(cfg_net_name_short,
121 cfg_net_name_short_cmd,
122 "short name NAME",
123 "Set the short GSM network name\n" NAME_CMD_STR NAME_STR)
124{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100125 osmo_talloc_replace_string(gsmnet, &gsmnet->name_short, argv[0]);
126 return CMD_SUCCESS;
127}
128
129DEFUN(cfg_net_name_long,
130 cfg_net_name_long_cmd,
131 "long name NAME",
132 "Set the long 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_long, argv[0]);
135 return CMD_SUCCESS;
136}
137
138DEFUN(cfg_net_encryption,
139 cfg_net_encryption_cmd,
140 "encryption a5 <0-3> [<0-3>] [<0-3>] [<0-3>]",
141 "Encryption options\n"
142 "GSM A5 Air Interface Encryption\n"
143 "A5/n Algorithm Number\n"
144 "A5/n Algorithm Number\n"
145 "A5/n Algorithm Number\n"
146 "A5/n Algorithm Number\n")
147{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100148 unsigned int i;
149
150 gsmnet->a5_encryption_mask = 0;
151 for (i = 0; i < argc; i++)
152 gsmnet->a5_encryption_mask |= (1 << atoi(argv[i]));
153
154 return CMD_SUCCESS;
155}
156
157DEFUN(cfg_net_authentication,
158 cfg_net_authentication_cmd,
159 "authentication (optional|required)",
160 "Whether to enforce MS authentication in 2G\n"
161 "Allow MS to attach via 2G BSC without authentication\n"
162 "Always do authentication\n")
163{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100164 gsmnet->authentication_required = (argv[0][0] == 'r') ? true : false;
165
166 return CMD_SUCCESS;
167}
168
169DEFUN(cfg_net_rrlp_mode, cfg_net_rrlp_mode_cmd,
170 "rrlp mode (none|ms-based|ms-preferred|ass-preferred)",
171 "Radio Resource Location Protocol\n"
172 "Set the Radio Resource Location Protocol Mode\n"
173 "Don't send RRLP request\n"
174 "Request MS-based location\n"
175 "Request any location, prefer MS-based\n"
176 "Request any location, prefer MS-assisted\n")
177{
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700178 gsmnet->rrlp.mode = msc_rrlp_mode_parse(argv[0]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100179
180 return CMD_SUCCESS;
181}
182
183DEFUN(cfg_net_mm_info, cfg_net_mm_info_cmd,
184 "mm info (0|1)",
185 "Mobility Management\n"
186 "Send MM INFO after LOC UPD ACCEPT\n"
187 "Disable\n" "Enable\n")
188{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100189 gsmnet->send_mm_info = atoi(argv[0]);
190
191 return CMD_SUCCESS;
192}
193
194DEFUN(cfg_net_timezone,
195 cfg_net_timezone_cmd,
196 "timezone <-19-19> (0|15|30|45)",
197 "Set the Timezone Offset of the network\n"
198 "Timezone offset (hours)\n"
199 "Timezone offset (00 minutes)\n"
200 "Timezone offset (15 minutes)\n"
201 "Timezone offset (30 minutes)\n"
202 "Timezone offset (45 minutes)\n"
203 )
204{
205 struct gsm_network *net = vty->index;
206 int tzhr = atoi(argv[0]);
207 int tzmn = atoi(argv[1]);
208
209 net->tz.hr = tzhr;
210 net->tz.mn = tzmn;
211 net->tz.dst = 0;
212 net->tz.override = 1;
213
214 return CMD_SUCCESS;
215}
216
217DEFUN(cfg_net_timezone_dst,
218 cfg_net_timezone_dst_cmd,
219 "timezone <-19-19> (0|15|30|45) <0-2>",
220 "Set the Timezone Offset of the network\n"
221 "Timezone offset (hours)\n"
222 "Timezone offset (00 minutes)\n"
223 "Timezone offset (15 minutes)\n"
224 "Timezone offset (30 minutes)\n"
225 "Timezone offset (45 minutes)\n"
226 "DST offset (hours)\n"
227 )
228{
229 struct gsm_network *net = vty->index;
230 int tzhr = atoi(argv[0]);
231 int tzmn = atoi(argv[1]);
232 int tzdst = atoi(argv[2]);
233
234 net->tz.hr = tzhr;
235 net->tz.mn = tzmn;
236 net->tz.dst = tzdst;
237 net->tz.override = 1;
238
239 return CMD_SUCCESS;
240}
241
242DEFUN(cfg_net_no_timezone,
243 cfg_net_no_timezone_cmd,
244 "no timezone",
245 NO_STR
246 "Disable network timezone override, use system tz\n")
247{
248 struct gsm_network *net = vty->index;
249
250 net->tz.override = 0;
251
252 return CMD_SUCCESS;
253}
254
255DEFUN(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
256 "periodic location update <6-1530>",
257 "Periodic Location Updating Interval\n"
258 "Periodic Location Updating Interval\n"
259 "Periodic Location Updating Interval\n"
260 "Periodic Location Updating Interval in Minutes\n")
261{
262 struct gsm_network *net = vty->index;
263
264 net->t3212 = atoi(argv[0]) / 6;
265
266 return CMD_SUCCESS;
267}
268
269DEFUN(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
270 "no periodic location update",
271 NO_STR
272 "Periodic Location Updating Interval\n"
273 "Periodic Location Updating Interval\n"
274 "Periodic Location Updating Interval\n")
275{
276 struct gsm_network *net = vty->index;
277
278 net->t3212 = 0;
279
280 return CMD_SUCCESS;
281}
282
283static int config_write_net(struct vty *vty)
284{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100285 int i;
286
287 vty_out(vty, "network%s", VTY_NEWLINE);
288 vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
289 vty_out(vty, " mobile network code %s%s",
290 osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
291 vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
292 vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
293 vty_out(vty, " encryption a5");
294 for (i = 0; i < 8; i++) {
295 if (gsmnet->a5_encryption_mask & (1 << i))
296 vty_out(vty, " %u", i);
297 }
298 vty_out(vty, "%s", VTY_NEWLINE);
299 vty_out(vty, " authentication %s%s",
300 gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE);
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700301 vty_out(vty, " rrlp mode %s%s", msc_rrlp_mode_name(gsmnet->rrlp.mode),
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100302 VTY_NEWLINE);
303 vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
304 if (gsmnet->tz.override != 0) {
305 if (gsmnet->tz.dst)
306 vty_out(vty, " timezone %d %d %d%s",
307 gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
308 VTY_NEWLINE);
309 else
310 vty_out(vty, " timezone %d %d%s",
311 gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
312 }
313 if (gsmnet->t3212 == 0)
314 vty_out(vty, " no periodic location update%s", VTY_NEWLINE);
315 else
316 vty_out(vty, " periodic location update %u%s",
317 gsmnet->t3212 * 6, VTY_NEWLINE);
318
319 if (gsmnet->emergency.route_to_msisdn) {
320 vty_out(vty, " emergency-call route-to-msisdn %s%s",
321 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
322 }
323
324 return CMD_SUCCESS;
325}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200326
327static struct cmd_node msc_node = {
328 MSC_NODE,
329 "%s(config-msc)# ",
330 1,
331};
332
333DEFUN(cfg_msc, cfg_msc_cmd,
334 "msc", "Configure MSC options")
335{
336 vty->node = MSC_NODE;
337 return CMD_SUCCESS;
338}
339
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100340#define MNCC_STR "Configure Mobile Network Call Control\n"
341#define MNCC_GUARD_TIMEOUT_STR "Set global guard timer for mncc interface activity\n"
342#define MNCC_GUARD_TIMEOUT_VALUE_STR "guard timer value (sec.)\n"
343
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100344DEFUN(cfg_msc_mncc_internal,
345 cfg_msc_mncc_internal_cmd,
346 "mncc internal",
347 MNCC_STR "Use internal MNCC handler (default; changes need a program restart)\n")
348{
349 gsm_network_set_mncc_sock_path(gsmnet, NULL);
350 return CMD_SUCCESS;
351}
352
353DEFUN(cfg_msc_mncc_external,
354 cfg_msc_mncc_external_cmd,
355 "mncc external MNCC_SOCKET_PATH",
356 MNCC_STR "Use external MNCC handler (changes need a program restart)\n"
357 "File system path to create the MNCC unix domain socket at\n")
358{
359 gsm_network_set_mncc_sock_path(gsmnet, argv[0]);
360 return CMD_SUCCESS;
361}
362
Philipp Maier9ca7b312018-10-10 17:00:49 +0200363DEFUN(cfg_msc_mncc_guard_timeout,
364 cfg_msc_mncc_guard_timeout_cmd,
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100365 "mncc guard-timeout <0-255>",
366 MNCC_STR
367 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR)
Philipp Maier9ca7b312018-10-10 17:00:49 +0200368{
369 gsmnet->mncc_guard_timeout = atoi(argv[0]);
370 return CMD_SUCCESS;
371}
372
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100373ALIAS_DEPRECATED(cfg_msc_mncc_guard_timeout,
374 cfg_msc_deprecated_mncc_guard_timeout_cmd,
375 "mncc-guard-timeout <0-255>",
376 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR);
377
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700378#define NCSS_STR "Configure call independent Supplementary Services\n"
379
380DEFUN(cfg_msc_ncss_guard_timeout,
381 cfg_msc_ncss_guard_timeout_cmd,
382 "ncss guard-timeout <0-255>",
383 NCSS_STR "Set guard timer for session activity\n"
384 "guard timer value (sec.), or 0 to disable\n")
385{
386 gsmnet->ncss_guard_timeout = atoi(argv[0]);
387 return CMD_SUCCESS;
388}
389
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200390DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
391 "assign-tmsi",
392 "Assign TMSI during Location Updating.\n")
393{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200394 gsmnet->vlr->cfg.assign_tmsi = true;
395 return CMD_SUCCESS;
396}
397
398DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
399 "no assign-tmsi",
400 NO_STR "Assign TMSI during Location Updating.\n")
401{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200402 gsmnet->vlr->cfg.assign_tmsi = false;
403 return CMD_SUCCESS;
404}
405
Philipp Maierfbf66102017-04-09 12:32:51 +0200406DEFUN(cfg_msc_cs7_instance_a,
407 cfg_msc_cs7_instance_a_cmd,
408 "cs7-instance-a <0-15>",
409 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
410{
Philipp Maierfbf66102017-04-09 12:32:51 +0200411 gsmnet->a.cs7_instance = atoi(argv[0]);
412 return CMD_SUCCESS;
413}
414
415DEFUN(cfg_msc_cs7_instance_iu,
416 cfg_msc_cs7_instance_iu_cmd,
417 "cs7-instance-iu <0-15>",
418 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
419{
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100420#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200421 gsmnet->iu.cs7_instance = atoi(argv[0]);
422 return CMD_SUCCESS;
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100423#else
424 vty_out(vty, "WARNING: 'cs7-instance-iu' without effect: built without Iu support%s",
425 VTY_NEWLINE);
426 return CMD_WARNING;
427#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200428}
429
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100430DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
431 "auth-tuple-max-reuse-count <-1-2147483647>",
432 "Configure authentication tuple re-use\n"
433 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
434{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100435 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
436 return CMD_SUCCESS;
437}
438
439DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
440 "auth-tuple-reuse-on-error (0|1)",
441 "Configure authentication tuple re-use when HLR is not responsive\n"
Oliver Smithd6e24fd2019-01-09 10:46:43 +0100442 "Never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
443 "If the HLR does not deliver new tuples, do re-use already available old ones.\n")
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100444{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100445 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
446 return CMD_SUCCESS;
447}
448
Oliver Smith0fec28a2018-12-14 10:52:52 +0100449DEFUN(cfg_msc_check_imei_rqd, cfg_msc_check_imei_rqd_cmd,
450 "check-imei-rqd (0|1)",
451 "Send each IMEI to the EIR to ask if it is permitted or not. The EIR is implemented as part of OsmoHLR, "
452 "and can optionally save the IMEI in the HLR.\n"
453 "Do not send IMEIs to the EIR\n"
454 "Send each IMEI to the EIR\n")
455{
456 gsmnet->vlr->cfg.check_imei_rqd = atoi(argv[0]) ? true : false;
457 return CMD_SUCCESS;
458}
459
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100460DEFUN(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
461 "paging response-timer (default|<1-65535>)",
462 "Configure Paging\n"
463 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
464 " BSS or RNC\n"
465 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
466 "Set paging timeout in seconds\n")
467{
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100468 if (!strcmp(argv[1], "default"))
469 gsmnet->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
470 else
471 gsmnet->paging_response_timer = atoi(argv[0]);
472 return CMD_SUCCESS;
473}
474
Harald Welte69c54a82018-02-09 20:41:14 +0100475DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
476 "emergency-call route-to-msisdn MSISDN",
477 "Configure Emergency Call Behaviour\n"
478 "MSISDN to which Emergency Calls are Dispatched\n"
479 "MSISDN (E.164 Phone Number)\n")
480{
Harald Welte69c54a82018-02-09 20:41:14 +0100481 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
482
483 return CMD_SUCCESS;
484}
485
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700486/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
487DEFUN(cfg_msc_sms_over_gsup, cfg_msc_sms_over_gsup_cmd,
488 "sms-over-gsup",
489 "Enable routing of SMS messages over GSUP\n")
490{
491 gsmnet->sms_over_gsup = true;
492 return CMD_SUCCESS;
493}
494
495/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
496DEFUN(cfg_msc_no_sms_over_gsup, cfg_msc_no_sms_over_gsup_cmd,
497 "no sms-over-gsup",
498 NO_STR "Disable routing of SMS messages over GSUP\n")
499{
500 gsmnet->sms_over_gsup = false;
501 return CMD_SUCCESS;
502}
503
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200504static int config_write_msc(struct vty *vty)
505{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200506 vty_out(vty, "msc%s", VTY_NEWLINE);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100507 if (gsmnet->mncc_sock_path)
508 vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE);
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100509 vty_out(vty, " mncc guard-timeout %i%s",
Philipp Maier9ca7b312018-10-10 17:00:49 +0200510 gsmnet->mncc_guard_timeout, VTY_NEWLINE);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700511 vty_out(vty, " ncss guard-timeout %i%s",
512 gsmnet->ncss_guard_timeout, VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200513 vty_out(vty, " %sassign-tmsi%s",
514 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
515
Philipp Maierfbf66102017-04-09 12:32:51 +0200516 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
517 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100518#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200519 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
520 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100521#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200522
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100523 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
524 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
525 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
526 VTY_NEWLINE);
527 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
528 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
529 VTY_NEWLINE);
530
Oliver Smith0fec28a2018-12-14 10:52:52 +0100531 if (gsmnet->vlr->cfg.check_imei_rqd)
532 vty_out(vty, " check-imei-rqd 1 %s",
533 VTY_NEWLINE);
534
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100535 if (gsmnet->paging_response_timer != MSC_PAGING_RESPONSE_TIMER_DEFAULT)
536 vty_out(vty, " paging response-timer %u%s", gsmnet->paging_response_timer, VTY_NEWLINE);
537
Harald Welte69c54a82018-02-09 20:41:14 +0100538 if (gsmnet->emergency.route_to_msisdn) {
539 vty_out(vty, " emergency-call route-to-msisdn %s%s",
540 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
541 }
542
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700543 if (gsmnet->sms_over_gsup)
544 vty_out(vty, " sms-over-gsup%s", VTY_NEWLINE);
545
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200546 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200547#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200548 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200549#endif
550
551 return CMD_SUCCESS;
552}
553
Maxc51609a2018-11-09 17:13:00 +0100554DEFUN(show_bsc, show_bsc_cmd,
555 "show bsc", SHOW_STR "BSC\n")
556{
557 struct bsc_context *bsc_ctx;
558 struct osmo_ss7_instance *ss7 = osmo_ss7_instance_find(gsmnet->a.cs7_instance);
559
560 llist_for_each_entry(bsc_ctx, &gsmnet->a.bscs, list) {
561 vty_out(vty, "BSC %s%s", osmo_sccp_addr_name(ss7, &bsc_ctx->bsc_addr), VTY_NEWLINE);
562 }
563
564 return CMD_SUCCESS;
565}
566
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100567static void vty_conn_hdr(struct vty *vty)
568{
Max45df98b2019-01-17 18:44:33 +0100569 unsigned lnum = 0;
570 struct ran_conn *conn;
571
572 llist_for_each_entry(conn, &gsmnet->ran_conns, entry)
573 lnum++;
574
575 if (lnum)
576 vty_out(vty, "--ConnId RAN --LAC Use --Tokens C A5 State ------------ Subscriber%s",
577 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100578}
579
Neels Hofmeyrc036b792018-11-29 22:37:51 +0100580static void vty_dump_one_conn(struct vty *vty, const struct ran_conn *conn)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100581{
Max45df98b2019-01-17 18:44:33 +0100582 vty_out(vty, "%08x %3s %5u %3u %08x %c /%1u %27s %22s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100583 conn->a.conn_id,
Harald Welte0df904d2018-12-03 11:00:04 +0100584 osmo_rat_type_name(conn->via_ran),
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100585 conn->lac,
586 conn->use_count,
587 conn->use_tokens,
588 conn->received_cm_service_request ? 'C' : '-',
Neels Hofmeyrf41658d2018-11-30 04:35:50 +0100589 conn->geran_encr.alg_id,
Neels Hofmeyr4d3a66b2018-03-31 18:45:59 +0200590 conn->fi ? osmo_fsm_inst_state_name(conn->fi) : "-",
Max45df98b2019-01-17 18:44:33 +0100591 conn->vsub ? vlr_subscr_name(conn->vsub) : "-",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100592 VTY_NEWLINE);
593}
594
595DEFUN(show_msc_conn, show_msc_conn_cmd,
596 "show connection", SHOW_STR "Subscriber Connections\n")
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200597{
Neels Hofmeyrc036b792018-11-29 22:37:51 +0100598 struct ran_conn *conn;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200599
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100600 vty_conn_hdr(vty);
Neels Hofmeyrc036b792018-11-29 22:37:51 +0100601 llist_for_each_entry(conn, &gsmnet->ran_conns, entry)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100602 vty_dump_one_conn(vty, conn);
603
604 return CMD_SUCCESS;
605}
606
607static void vty_trans_hdr(struct vty *vty)
608{
Max45df98b2019-01-17 18:44:33 +0100609 unsigned lnum = 0;
610 struct gsm_trans *trans;
611
612 llist_for_each_entry(trans, &gsmnet->trans_list, entry)
613 lnum++;
614
615 if (lnum)
616 vty_out(vty, "--ConnId -P TI -CallRef [--- Proto ---] ------------ Subscriber%s",
617 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100618}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200619
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100620static const char *get_trans_proto_str(const struct gsm_trans *trans)
621{
622 static char buf[256];
623
624 switch (trans->protocol) {
625 case GSM48_PDISC_CC:
626 snprintf(buf, sizeof(buf), "%s %4u %4u",
627 gsm48_cc_state_name(trans->cc.state),
628 trans->cc.Tcurrent,
629 trans->cc.T308_second);
630 break;
631 case GSM48_PDISC_SMS:
632 snprintf(buf, sizeof(buf), "%s %s",
633 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
634 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
635 break;
636 default:
637 buf[0] = '\0';
638 break;
639 }
640
641 return buf;
642}
643
644static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans)
645{
Max45df98b2019-01-17 18:44:33 +0100646 vty_out(vty, "%08x %s %02u %08x [%s] %22s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100647 trans->conn ? trans->conn->a.conn_id : 0,
648 gsm48_pdisc_name(trans->protocol),
649 trans->transaction_id,
650 trans->callref,
Max45df98b2019-01-17 18:44:33 +0100651 get_trans_proto_str(trans),
652 trans->vsub ? vlr_subscr_name(trans->vsub) : "-",
653 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100654}
655
656DEFUN(show_msc_transaction, show_msc_transaction_cmd,
657 "show transaction", SHOW_STR "Transactions\n")
658{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100659 struct gsm_trans *trans;
660
661 vty_trans_hdr(vty);
662 llist_for_each_entry(trans, &gsmnet->trans_list, entry)
663 vty_dump_one_trans(vty, trans);
664
665 return CMD_SUCCESS;
666}
667
668static void subscr_dump_full_vty(struct vty *vty, struct vlr_subscr *vsub)
669{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100670 struct gsm_trans *trans;
671 int reqs;
672 struct llist_head *entry;
673
674 if (strlen(vsub->name))
675 vty_out(vty, " Name: '%s'%s", vsub->name, VTY_NEWLINE);
676 if (strlen(vsub->msisdn))
677 vty_out(vty, " Extension: %s%s", vsub->msisdn,
678 VTY_NEWLINE);
679 vty_out(vty, " LAC: %d/0x%x%s",
Max7d41d872018-12-19 11:48:33 +0100680 vsub->cgi.lai.lac, vsub->cgi.lai.lac, VTY_NEWLINE);
Philipp Maier2a0ac3b2018-12-17 10:03:50 +0100681 vty_out(vty, " RAN: %s%s",
Neels Hofmeyr7814a832018-12-26 00:40:18 +0100682 osmo_rat_type_name(vsub->cs.attached_via_ran), VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100683 vty_out(vty, " IMSI: %s%s", vsub->imsi, VTY_NEWLINE);
684 if (vsub->tmsi != GSM_RESERVED_TMSI)
685 vty_out(vty, " TMSI: %08X%s", vsub->tmsi,
686 VTY_NEWLINE);
687 if (vsub->tmsi_new != GSM_RESERVED_TMSI)
688 vty_out(vty, " new TMSI: %08X%s", vsub->tmsi_new,
689 VTY_NEWLINE);
Philipp Maier6d71ccf2018-12-14 13:30:14 +0100690 if (vsub->imei[0] != '\0')
691 vty_out(vty, " IMEI: %s%s", vsub->imei, VTY_NEWLINE);
692 if (vsub->imeisv[0] != '\0')
693 vty_out(vty, " IMEISV: %s%s", vsub->imeisv, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100694
Philipp Maier89561bc2018-12-14 13:34:25 +0100695 vty_out(vty, " Flags: %s", VTY_NEWLINE);
696 vty_out(vty, " IMSI detached: %s%s",
697 vsub->imsi_detached_flag ? "true" : "false", VTY_NEWLINE);
698 vty_out(vty, " Conf. by radio contact: %s%s",
699 vsub->conf_by_radio_contact_ind ? "true" : "false",
700 VTY_NEWLINE);
701 vty_out(vty, " Subscr. data conf. by HLR: %s%s",
702 vsub->sub_dataconf_by_hlr_ind ? "true" : "false", VTY_NEWLINE);
703 vty_out(vty, " Location conf. in HLR: %s%s",
704 vsub->loc_conf_in_hlr_ind ? "true" : "false", VTY_NEWLINE);
705 vty_out(vty, " Subscriber dormant: %s%s",
706 vsub->dormant_ind ? "true" : "false", VTY_NEWLINE);
707 vty_out(vty, " Received cancel locataion: %s%s",
708 vsub->cancel_loc_rx ? "true" : "false", VTY_NEWLINE);
709 vty_out(vty, " MS not reachable: %s%s",
710 vsub->ms_not_reachable_flag ? "true" : "false", VTY_NEWLINE);
711 vty_out(vty, " LA allowed: %s%s",
712 vsub->la_allowed ? "true" : "false", VTY_NEWLINE);
713
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100714#if 0
715 /* TODO: add this to vlr_subscr? */
716 if (vsub->auth_info.auth_algo != AUTH_ALGO_NONE) {
717 struct gsm_auth_info *i = &vsub->auth_info;
718 vty_out(vty, " A3A8 algorithm id: %d%s",
719 i->auth_algo, VTY_NEWLINE);
720 vty_out(vty, " A3A8 Ki: %s%s",
721 osmo_hexdump(i->a3a8_ki, i->a3a8_ki_len),
722 VTY_NEWLINE);
723 }
724#endif
725
726 if (vsub->last_tuple) {
Neels Hofmeyr8b6e5362018-11-30 02:57:33 +0100727 struct vlr_auth_tuple *t = vsub->last_tuple;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100728 vty_out(vty, " A3A8 last tuple (used %d times):%s",
729 t->use_count, VTY_NEWLINE);
730 vty_out(vty, " seq # : %d%s",
731 t->key_seq, VTY_NEWLINE);
732 vty_out(vty, " RAND : %s%s",
733 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
734 VTY_NEWLINE);
735 vty_out(vty, " SRES : %s%s",
736 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
737 VTY_NEWLINE);
738 vty_out(vty, " Kc : %s%s",
739 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
740 VTY_NEWLINE);
741 }
742
743 reqs = 0;
744 llist_for_each(entry, &vsub->cs.requests)
745 reqs += 1;
746 vty_out(vty, " Paging: %s paging for %d requests%s",
747 vsub->cs.is_paging ? "is" : "not", reqs, VTY_NEWLINE);
Harald Welte0df904d2018-12-03 11:00:04 +0100748
749 /* SGs related */
750 vty_out(vty, " SGs-state: %s%s",
751 osmo_fsm_inst_state_name(vsub->sgs_fsm), VTY_NEWLINE);
Vadim Yanitskiy477cbc62019-02-23 16:59:16 +0700752 if (strlen(vsub->sgs.mme_name))
Harald Welte0df904d2018-12-03 11:00:04 +0100753 vty_out(vty, " SGs-MME: %s%s", vsub->sgs.mme_name, VTY_NEWLINE);
754 else
755 vty_out(vty, " SGs-MME: (none)%s", VTY_NEWLINE);
756
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100757 vty_out(vty, " Use count: %u%s", vsub->use_count, VTY_NEWLINE);
758
759 /* Connection */
760 if (vsub->msc_conn_ref) {
Neels Hofmeyrc036b792018-11-29 22:37:51 +0100761 struct ran_conn *conn = vsub->msc_conn_ref;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100762 vty_conn_hdr(vty);
763 vty_dump_one_conn(vty, conn);
764 }
765
766 /* Transactions */
767 vty_trans_hdr(vty);
768 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
769 if (trans->vsub != vsub)
770 continue;
771 vty_dump_one_trans(vty, trans);
772 }
773}
774
775/* Subscriber */
776DEFUN(show_subscr_cache,
777 show_subscr_cache_cmd,
778 "show subscriber cache",
779 SHOW_STR "Show information about subscribers\n"
780 "Display contents of subscriber cache\n")
781{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100782 struct vlr_subscr *vsub;
783 int count = 0;
784
785 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
786 if (++count > 100) {
787 vty_out(vty, "%% More than %d subscribers in cache,"
788 " stopping here.%s", count-1, VTY_NEWLINE);
789 break;
790 }
791 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
792 subscr_dump_full_vty(vty, vsub);
Harald Welte69c54a82018-02-09 20:41:14 +0100793 }
794
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200795 return CMD_SUCCESS;
796}
797
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100798DEFUN(sms_send_pend,
799 sms_send_pend_cmd,
800 "sms send pending",
801 "SMS related commands\n" "SMS Sending related commands\n"
802 "Send all pending SMS")
803{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100804 struct gsm_sms *sms;
805 unsigned long long sms_id = 0;
806
807 while (1) {
808 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
809 if (!sms)
810 break;
811
812 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +0700813 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100814
815 sms_id = sms->id + 1;
816 }
817
818 return CMD_SUCCESS;
819}
820
821DEFUN(sms_delete_expired,
822 sms_delete_expired_cmd,
823 "sms delete expired",
824 "SMS related commands\n" "SMS Database related commands\n"
825 "Delete all expired SMS")
826{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100827 struct gsm_sms *sms;
828 unsigned long long sms_id = 0;
829 long long num_deleted = 0;
830
831 while (1) {
832 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
833 if (!sms)
834 break;
835
836 /* Skip SMS which are currently queued for sending. */
837 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
838 continue;
839
840 /* Expiration check is performed by the DB layer. */
841 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
842 num_deleted++;
843
844 sms_id = sms->id + 1;
845 }
846
847 if (num_deleted == 0) {
848 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
849 return CMD_WARNING;
850 }
851
852 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
853 return CMD_SUCCESS;
854}
855
856static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +0200857 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100858 char *str, uint8_t tp_pid)
859{
860 struct gsm_network *net = receiver->vlr->user_ctx;
861 struct gsm_sms *sms;
862
Harald Welte39b55482018-04-09 19:19:33 +0200863 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100864 sms->protocol_id = tp_pid;
865
866 /* store in database for the queue */
867 if (db_sms_store(sms) != 0) {
868 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
869 sms_free(sms);
870 return CMD_WARNING;
871 }
872 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
873
874 sms_free(sms);
875 sms_queue_trigger(net->sms_queue);
876 return CMD_SUCCESS;
877}
878
879static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
880 const char *type,
881 const char *id)
882{
883 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
884 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id);
885 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
886 return vlr_subscr_find_by_imsi(gsmnet->vlr, id);
887 else if (!strcmp(type, "tmsi"))
888 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id));
889
890 return NULL;
891}
892#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
893#define SUBSCR_HELP "Operations on a Subscriber\n" \
894 "Identify subscriber by MSISDN (phone number)\n" \
895 "Legacy alias for 'msisdn'\n" \
896 "Identify subscriber by IMSI\n" \
897 "Identify subscriber by TMSI\n" \
898 "Identify subscriber by database ID\n" \
899 "Identifier for the subscriber\n"
900
901DEFUN(show_subscr,
902 show_subscr_cmd,
903 "show subscriber " SUBSCR_TYPES " ID",
904 SHOW_STR SUBSCR_HELP)
905{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100906 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
907 argv[1]);
908
909 if (!vsub) {
910 vty_out(vty, "%% No subscriber found for %s %s%s",
911 argv[0], argv[1], VTY_NEWLINE);
912 return CMD_WARNING;
913 }
914
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +0100915 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
916 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
917 * this, and since this is not multi-threaded, this vlr_subscr_put() cannot possibly reach a count of 0. */
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100918 vlr_subscr_put(vsub);
919
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +0100920 subscr_dump_full_vty(vty, vsub);
921
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100922 return CMD_SUCCESS;
923}
924
925DEFUN(subscriber_create,
926 subscriber_create_cmd,
927 "subscriber create imsi ID",
928 "Operations on a Subscriber\n" \
929 "Create new subscriber\n" \
930 "Identify the subscriber by his IMSI\n" \
931 "Identifier for the subscriber\n")
932{
933 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
934 VTY_NEWLINE);
935 return CMD_WARNING;
936}
937
938DEFUN(subscriber_send_pending_sms,
939 subscriber_send_pending_sms_cmd,
940 "subscriber " SUBSCR_TYPES " ID sms pending-send",
941 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
942{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100943 struct vlr_subscr *vsub;
944 struct gsm_sms *sms;
945
946 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
947 if (!vsub) {
948 vty_out(vty, "%% No subscriber found for %s %s%s",
949 argv[0], argv[1], VTY_NEWLINE);
950 return CMD_WARNING;
951 }
952
953 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
954 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +0700955 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100956
957 vlr_subscr_put(vsub);
958
959 return CMD_SUCCESS;
960}
961
Neels Hofmeyrf90496f2019-03-06 16:19:50 +0100962DEFUN(subscriber_sms_delete_all,
963 subscriber_sms_delete_all_cmd,
964 "subscriber " SUBSCR_TYPES " ID sms delete-all",
965 SUBSCR_HELP "SMS Operations\n"
966 "Delete all SMS to be delivered to this subscriber"
967 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
968 " WILL BE LOST.\n")
969{
970 struct vlr_subscr *vsub;
971
972 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
973 if (!vsub) {
974 vty_out(vty, "%% No subscriber found for %s %s%s",
975 argv[0], argv[1], VTY_NEWLINE);
976 return CMD_WARNING;
977 }
978
979 db_sms_delete_by_msisdn(vsub->msisdn);
980
981 vlr_subscr_put(vsub);
982
983 return CMD_SUCCESS;
984}
985
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100986DEFUN(subscriber_send_sms,
987 subscriber_send_sms_cmd,
988 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
989 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
990{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100991 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +0200992 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100993 char *str;
994 int rc;
995
996 if (!vsub) {
997 vty_out(vty, "%% No subscriber found for %s %s%s",
998 argv[0], argv[1], VTY_NEWLINE);
999 rc = CMD_WARNING;
1000 goto err;
1001 }
1002
Harald Welte39b55482018-04-09 19:19:33 +02001003 if (!strcmp(argv[2], "msisdn"))
1004 sender_msisdn = argv[3];
1005 else {
1006 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1007 if (!sender) {
1008 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1009 rc = CMD_WARNING;
1010 goto err;
1011 }
1012 sender_msisdn = sender->msisdn;
1013 vlr_subscr_put(sender);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001014 }
1015
1016 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001017 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001018 talloc_free(str);
1019
1020err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001021 if (vsub)
1022 vlr_subscr_put(vsub);
1023
1024 return rc;
1025}
1026
1027DEFUN(subscriber_silent_sms,
1028 subscriber_silent_sms_cmd,
1029
1030 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1031 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1032{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001033 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001034 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001035 char *str;
1036 int rc;
1037
1038 if (!vsub) {
1039 vty_out(vty, "%% No subscriber found for %s %s%s",
1040 argv[0], argv[1], VTY_NEWLINE);
1041 rc = CMD_WARNING;
1042 goto err;
1043 }
1044
Harald Welte39b55482018-04-09 19:19:33 +02001045 if (!strcmp(argv[2], "msisdn")) {
1046 sender_msisdn = argv[3];
1047 } else {
1048 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1049 if (!sender) {
1050 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1051 rc = CMD_WARNING;
1052 goto err;
1053 }
1054 sender_msisdn = sender->msisdn;
1055 vlr_subscr_put(sender);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001056 }
1057
1058 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001059 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001060 talloc_free(str);
1061
1062err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001063 if (vsub)
1064 vlr_subscr_put(vsub);
1065
1066 return rc;
1067}
1068
Sylvain Munaut93558302019-02-14 20:13:08 +01001069#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001070#define CHAN_TYPE_HELP \
1071 "Any channel\n" \
1072 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001073 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001074 "Any TCH channel\n" \
1075 "SDCCH channel\n"
1076
Sylvain Munaut93558302019-02-14 20:13:08 +01001077#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1078#define CHAN_MODE_HELP \
1079 "Signalling only\n" \
1080 "Speech with HR codec\n" \
1081 "Speech with FR codec\n" \
1082 "Speech with EFR codec\n" \
1083 "Speech with AMR codec\n"
1084
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001085DEFUN(subscriber_silent_call_start,
1086 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001087 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001088 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001089 CHAN_TYPE_HELP CHAN_MODE_HELP
1090 "Target IP for RTP traffic (default 127.0.0.1)\n"
1091 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001092{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001093 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001094 struct gsm0808_channel_type ct;
1095 const char *ip;
1096 uint16_t port;
1097 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001098
1099 if (!vsub) {
1100 vty_out(vty, "%% No subscriber found for %s %s%s",
1101 argv[0], argv[1], VTY_NEWLINE);
1102 return CMD_WARNING;
1103 }
1104
Sylvain Munaut93558302019-02-14 20:13:08 +01001105 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001106
Sylvain Munaut93558302019-02-14 20:13:08 +01001107 if (!strcmp(argv[3], "signalling")) {
1108 ct.ch_indctr = GSM0808_CHAN_SIGN;
1109 ct.perm_spch[0] = 0; /* Spare but required */
1110 ct.perm_spch_len = 1;
1111 } else if (!strcmp(argv[3], "speech-hr")) {
1112 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1113 ct.perm_spch[0] = GSM0808_PERM_HR1;
1114 ct.perm_spch_len = 1;
1115 } else if (!strcmp(argv[3], "speech-fr")) {
1116 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1117 ct.perm_spch[0] = GSM0808_PERM_FR1;
1118 ct.perm_spch_len = 1;
1119 } else if (!strcmp(argv[3], "speech-efr")) {
1120 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1121 ct.perm_spch[0] = GSM0808_PERM_FR2;
1122 ct.perm_spch_len = 1;
1123 } else if (!strcmp(argv[3], "speech-amr")) {
1124 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1125 ct.perm_spch[0] = GSM0808_PERM_FR3;
1126 ct.perm_spch[1] = GSM0808_PERM_HR3;
1127 ct.perm_spch_len = 2;
1128 }
1129
1130 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1131
1132 if (!strcmp(argv[2], "tch/f"))
1133 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1134 else if (!strcmp(argv[2], "tch/h"))
1135 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1136 else if (!strcmp(argv[2], "tch/any"))
1137 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1138 else if (!strcmp(argv[2], "sdcch")) {
1139 if (speech) {
1140 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1141 return CMD_WARNING;
1142 }
1143 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1144 } else
1145 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1146
1147 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1148 port = argc >= 6 ? atoi(argv[5]) : 4000;
1149
1150 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001151 switch (rc) {
1152 case -ENODEV:
1153 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1154 break;
1155 default:
1156 if (rc)
1157 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1158 else
1159 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1160 break;
1161 }
1162
1163 vlr_subscr_put(vsub);
1164 return rc ? CMD_WARNING : CMD_SUCCESS;
1165}
1166
1167DEFUN(subscriber_silent_call_stop,
1168 subscriber_silent_call_stop_cmd,
1169 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1170 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1171 CHAN_TYPE_HELP)
1172{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001173 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1174 int rc;
1175
1176 if (!vsub) {
1177 vty_out(vty, "%% No subscriber found for %s %s%s",
1178 argv[0], argv[1], VTY_NEWLINE);
1179 return CMD_WARNING;
1180 }
1181
1182 rc = gsm_silent_call_stop(vsub);
1183 switch (rc) {
1184 case -ENODEV:
1185 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1186 break;
1187 case -ENOENT:
1188 vty_out(vty, "%% Subscriber has no silent call active%s",
1189 VTY_NEWLINE);
1190 break;
1191 default:
1192 if (rc)
1193 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1194 else
1195 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1196 break;
1197 }
1198
1199 vlr_subscr_put(vsub);
1200 return rc ? CMD_WARNING : CMD_SUCCESS;
1201}
1202
1203DEFUN(subscriber_ussd_notify,
1204 subscriber_ussd_notify_cmd,
1205 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1206 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1207 "Alerting Level 0\n"
1208 "Alerting Level 1\n"
1209 "Alerting Level 2\n"
1210 "Text of USSD message to send\n")
1211{
1212 char *text;
Neels Hofmeyrc036b792018-11-29 22:37:51 +01001213 struct ran_conn *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001214 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1215 int level;
1216
1217 if (!vsub) {
1218 vty_out(vty, "%% No subscriber found for %s %s%s",
1219 argv[0], argv[1], VTY_NEWLINE);
1220 return CMD_WARNING;
1221 }
1222
1223 level = atoi(argv[2]);
1224 text = argv_concat(argv, argc, 3);
1225 if (!text) {
1226 vlr_subscr_put(vsub);
1227 return CMD_WARNING;
1228 }
1229
1230 conn = connection_for_subscr(vsub);
1231 if (!conn) {
1232 vty_out(vty, "%% An active connection is required for %s %s%s",
1233 argv[0], argv[1], VTY_NEWLINE);
1234 vlr_subscr_put(vsub);
1235 talloc_free(text);
1236 return CMD_WARNING;
1237 }
1238
1239 msc_send_ussd_notify(conn, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001240 /* FIXME: since we don't allocate a transaction here,
1241 * we use dummy GSM 04.07 transaction ID. */
1242 msc_send_ussd_release_complete(conn, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001243
1244 vlr_subscr_put(vsub);
1245 talloc_free(text);
1246 return CMD_SUCCESS;
1247}
1248
1249DEFUN(subscriber_paging,
1250 subscriber_paging_cmd,
1251 "subscriber " SUBSCR_TYPES " ID paging",
1252 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1253{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001254 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1255 struct subscr_request *req;
1256
1257 if (!vsub) {
1258 vty_out(vty, "%% No subscriber found for %s %s%s",
1259 argv[0], argv[1], VTY_NEWLINE);
1260 return CMD_WARNING;
1261 }
1262
Harald Welte0df904d2018-12-03 11:00:04 +01001263 req = subscr_request_conn(vsub, NULL, NULL, "manual Paging from VTY", SGSAP_SERV_IND_CS_CALL);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001264 if (req)
1265 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1266 else
1267 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1268
1269 vlr_subscr_put(vsub);
1270 return req ? CMD_SUCCESS : CMD_WARNING;
1271}
1272
1273static int loop_by_char(uint8_t ch)
1274{
1275 switch (ch) {
1276 case 'a':
1277 return GSM414_LOOP_A;
1278 case 'b':
1279 return GSM414_LOOP_B;
1280 case 'c':
1281 return GSM414_LOOP_C;
1282 case 'd':
1283 return GSM414_LOOP_D;
1284 case 'e':
1285 return GSM414_LOOP_E;
1286 case 'f':
1287 return GSM414_LOOP_F;
1288 case 'i':
1289 return GSM414_LOOP_I;
1290 }
1291 return -1;
1292}
1293
1294DEFUN(subscriber_mstest_close,
1295 subscriber_mstest_close_cmd,
1296 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1297 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1298 "Close a TCH Loop inside the MS\n"
1299 "Loop Type A\n"
1300 "Loop Type B\n"
1301 "Loop Type C\n"
1302 "Loop Type D\n"
1303 "Loop Type E\n"
1304 "Loop Type F\n"
1305 "Loop Type I\n")
1306{
Neels Hofmeyrc036b792018-11-29 22:37:51 +01001307 struct ran_conn *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001308 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1309 const char *loop_str;
1310 int loop_mode;
1311
1312 if (!vsub) {
1313 vty_out(vty, "%% No subscriber found for %s %s%s",
1314 argv[0], argv[1], VTY_NEWLINE);
1315 return CMD_WARNING;
1316 }
1317
1318 loop_str = argv[2];
1319 loop_mode = loop_by_char(loop_str[0]);
1320
1321 conn = connection_for_subscr(vsub);
1322 if (!conn) {
1323 vty_out(vty, "%% An active connection is required for %s %s%s",
1324 argv[0], argv[1], VTY_NEWLINE);
1325 vlr_subscr_put(vsub);
1326 return CMD_WARNING;
1327 }
1328
1329 gsm0414_tx_close_tch_loop_cmd(conn, loop_mode);
1330
1331 return CMD_SUCCESS;
1332}
1333
1334DEFUN(subscriber_mstest_open,
1335 subscriber_mstest_open_cmd,
1336 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1337 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1338 "Open a TCH Loop inside the MS\n")
1339{
Neels Hofmeyrc036b792018-11-29 22:37:51 +01001340 struct ran_conn *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001341 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1342
1343 if (!vsub) {
1344 vty_out(vty, "%% No subscriber found for %s %s%s",
1345 argv[0], argv[1], VTY_NEWLINE);
1346 return CMD_WARNING;
1347 }
1348
1349 conn = connection_for_subscr(vsub);
1350 if (!conn) {
1351 vty_out(vty, "%% An active connection is required for %s %s%s",
1352 argv[0], argv[1], VTY_NEWLINE);
1353 vlr_subscr_put(vsub);
1354 return CMD_WARNING;
1355 }
1356
1357 gsm0414_tx_open_loop_cmd(conn);
1358
1359 return CMD_SUCCESS;
1360}
1361
1362DEFUN(ena_subscr_expire,
1363 ena_subscr_expire_cmd,
1364 "subscriber " SUBSCR_TYPES " ID expire",
1365 SUBSCR_HELP "Expire the subscriber Now\n")
1366{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001367 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1368 argv[1]);
1369
1370 if (!vsub) {
1371 vty_out(vty, "%% No subscriber found for %s %s%s",
1372 argv[0], argv[1], VTY_NEWLINE);
1373 return CMD_WARNING;
1374 }
1375
1376 if (vlr_subscr_expire(vsub))
1377 vty_out(vty, "%% VLR released subscriber %s%s",
1378 vlr_subscr_name(vsub), VTY_NEWLINE);
1379
1380 if (vsub->use_count > 1)
1381 vty_out(vty, "%% Subscriber %s is still in use,"
1382 " should be released soon%s",
1383 vlr_subscr_name(vsub), VTY_NEWLINE);
1384
1385 vlr_subscr_put(vsub);
1386 return CMD_SUCCESS;
1387}
1388
1389static int scall_cbfn(unsigned int subsys, unsigned int signal,
1390 void *handler_data, void *signal_data)
1391{
1392 struct scall_signal_data *sigdata = signal_data;
1393 struct vty *vty = sigdata->data;
1394
1395 switch (signal) {
1396 case S_SCALL_SUCCESS:
1397 vty_out(vty, "%% silent call success%s", VTY_NEWLINE);
1398 break;
1399 case S_SCALL_EXPIRED:
1400 vty_out(vty, "%% silent call expired paging%s", VTY_NEWLINE);
1401 break;
1402 }
1403 return 0;
1404}
1405
1406DEFUN(show_stats,
1407 show_stats_cmd,
1408 "show statistics",
1409 SHOW_STR "Display network statistics\n")
1410{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001411 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001412 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1413 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1414 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001415 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001416 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001417 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001418 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001419 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001420 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1421 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001422 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001423 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001424 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1425 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001426 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001427 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001428 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1429 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1430 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001431 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001432 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001433 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1434 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001435 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001436 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001437 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1438 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001439 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001440 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001441 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current,
1442 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1443 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current
1444 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1445 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001446 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001447 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current,
1448 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1449 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current
1450 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1451 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001452 return CMD_SUCCESS;
1453}
1454
1455DEFUN(show_smsqueue,
1456 show_smsqueue_cmd,
1457 "show sms-queue",
1458 SHOW_STR "Display SMSqueue statistics\n")
1459{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001460 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001461 return CMD_SUCCESS;
1462}
1463
1464DEFUN(smsqueue_trigger,
1465 smsqueue_trigger_cmd,
1466 "sms-queue trigger",
1467 "SMS Queue\n" "Trigger sending messages\n")
1468{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001469 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001470 return CMD_SUCCESS;
1471}
1472
1473DEFUN(smsqueue_max,
1474 smsqueue_max_cmd,
1475 "sms-queue max-pending <1-500>",
1476 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1477{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001478 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001479 return CMD_SUCCESS;
1480}
1481
1482DEFUN(smsqueue_clear,
1483 smsqueue_clear_cmd,
1484 "sms-queue clear",
1485 "SMS Queue\n" "Clear the queue of pending SMS\n")
1486{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001487 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001488 return CMD_SUCCESS;
1489}
1490
1491DEFUN(smsqueue_fail,
1492 smsqueue_fail_cmd,
1493 "sms-queue max-failure <1-500>",
1494 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1495{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001496 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001497 return CMD_SUCCESS;
1498}
1499
1500
1501DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1502 "mncc-int", "Configure internal MNCC handler")
1503{
1504 vty->node = MNCC_INT_NODE;
1505
1506 return CMD_SUCCESS;
1507}
1508
1509static struct cmd_node mncc_int_node = {
1510 MNCC_INT_NODE,
1511 "%s(config-mncc-int)# ",
1512 1,
1513};
1514
1515static const struct value_string tchf_codec_names[] = {
1516 { GSM48_CMODE_SPEECH_V1, "fr" },
1517 { GSM48_CMODE_SPEECH_EFR, "efr" },
1518 { GSM48_CMODE_SPEECH_AMR, "amr" },
1519 { 0, NULL }
1520};
1521
1522static const struct value_string tchh_codec_names[] = {
1523 { GSM48_CMODE_SPEECH_V1, "hr" },
1524 { GSM48_CMODE_SPEECH_AMR, "amr" },
1525 { 0, NULL }
1526};
1527
1528static int config_write_mncc_int(struct vty *vty)
1529{
1530 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1531 vty_out(vty, " default-codec tch-f %s%s",
1532 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1533 VTY_NEWLINE);
1534 vty_out(vty, " default-codec tch-h %s%s",
1535 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1536 VTY_NEWLINE);
1537
1538 return CMD_SUCCESS;
1539}
1540
1541DEFUN(mnccint_def_codec_f,
1542 mnccint_def_codec_f_cmd,
1543 "default-codec tch-f (fr|efr|amr)",
1544 "Set default codec\n" "Codec for TCH/F\n"
1545 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1546{
1547 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1548
1549 return CMD_SUCCESS;
1550}
1551
1552DEFUN(mnccint_def_codec_h,
1553 mnccint_def_codec_h_cmd,
1554 "default-codec tch-h (hr|amr)",
1555 "Set default codec\n" "Codec for TCH/H\n"
1556 "Half-Rate\n" "Adaptive Multi-Rate\n")
1557{
1558 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1559
1560 return CMD_SUCCESS;
1561}
1562
1563
1564DEFUN(logging_fltr_imsi,
1565 logging_fltr_imsi_cmd,
1566 "logging filter imsi IMSI",
1567 LOGGING_STR FILTER_STR
1568 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1569{
1570 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001571 struct log_target *tgt = osmo_log_vty2tgt(vty);
1572 const char *imsi = argv[0];
1573
1574 if (!tgt)
1575 return CMD_WARNING;
1576
1577 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi);
1578
1579 if (!vlr_subscr) {
1580 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1581 argv[0], VTY_NEWLINE);
1582 return CMD_WARNING;
1583 }
1584
1585 log_set_filter_vlr_subscr(tgt, vlr_subscr);
1586 return CMD_SUCCESS;
1587}
1588
1589static struct cmd_node hlr_node = {
1590 HLR_NODE,
1591 "%s(config-hlr)# ",
1592 1,
1593};
1594
1595DEFUN(cfg_hlr, cfg_hlr_cmd,
1596 "hlr", "Configure connection to the HLR")
1597{
1598 vty->node = HLR_NODE;
1599 return CMD_SUCCESS;
1600}
1601
1602DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1603 "Remote GSUP address of the HLR\n"
1604 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1605{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001606 talloc_free((void*)gsmnet->gsup_server_addr_str);
1607 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1608 return CMD_SUCCESS;
1609}
1610
1611DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1612 "Remote GSUP port of the HLR\n"
1613 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1614{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001615 gsmnet->gsup_server_port = atoi(argv[0]);
1616 return CMD_SUCCESS;
1617}
1618
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001619DEFUN(cfg_hlr_ipa_name,
1620 cfg_hlr_ipa_name_cmd,
1621 "ipa-name NAME",
1622 "Set the IPA name of this MSC\n"
1623 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1624 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
1625 "The default is 'MSC-00-00-00-00-00-00'.\n")
1626{
1627 if (vty->type != VTY_FILE) {
1628 vty_out(vty, "The IPA name cannot be changed at run-time; "
1629 "It can only be set in the configuraton file.%s", VTY_NEWLINE);
1630 return CMD_WARNING;
1631 }
1632
1633 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
1634 return CMD_SUCCESS;
1635}
1636
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001637static int config_write_hlr(struct vty *vty)
1638{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001639 vty_out(vty, "hlr%s", VTY_NEWLINE);
1640 vty_out(vty, " remote-ip %s%s",
1641 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1642 vty_out(vty, " remote-port %u%s",
1643 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001644 if (gsmnet->msc_ipa_name)
1645 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001646 return CMD_SUCCESS;
1647}
1648
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001649void msc_vty_init(struct gsm_network *msc_network)
1650{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001651 OSMO_ASSERT(gsmnet == NULL);
1652 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001653
1654 osmo_stats_vty_add_cmds();
1655
1656 install_element(CONFIG_NODE, &cfg_net_cmd);
1657 install_node(&net_node, config_write_net);
1658 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1659 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1660 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1661 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1662 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
1663 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1664 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1665 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1666 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1667 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1668 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1669 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1670 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001671
1672 install_element(CONFIG_NODE, &cfg_msc_cmd);
1673 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001674 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01001675 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
1676 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02001677 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01001678 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07001679 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001680 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001681 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
1682 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01001683 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001684 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
1685 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01001686 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01001687 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07001688 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
1689 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001690
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02001691 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001692#ifdef BUILD_IU
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +01001693 ranap_iu_vty_init(MSC_NODE, &msc_network->iu.rab_assign_addr_enc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001694#endif
Harald Welte0df904d2018-12-03 11:00:04 +01001695 sgs_vty_init();
Stefan Sperling617ac802018-02-22 17:58:20 +01001696 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001697
1698 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
1699
1700 install_element_ve(&show_subscr_cmd);
1701 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01001702 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001703 install_element_ve(&show_msc_conn_cmd);
1704 install_element_ve(&show_msc_transaction_cmd);
1705
1706 install_element_ve(&sms_send_pend_cmd);
1707 install_element_ve(&sms_delete_expired_cmd);
1708
1709 install_element_ve(&subscriber_create_cmd);
1710 install_element_ve(&subscriber_send_sms_cmd);
1711 install_element_ve(&subscriber_silent_sms_cmd);
1712 install_element_ve(&subscriber_silent_call_start_cmd);
1713 install_element_ve(&subscriber_silent_call_stop_cmd);
1714 install_element_ve(&subscriber_ussd_notify_cmd);
1715 install_element_ve(&subscriber_mstest_close_cmd);
1716 install_element_ve(&subscriber_mstest_open_cmd);
1717 install_element_ve(&subscriber_paging_cmd);
1718 install_element_ve(&show_stats_cmd);
1719 install_element_ve(&show_smsqueue_cmd);
1720 install_element_ve(&logging_fltr_imsi_cmd);
1721
1722 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
1723 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
1724 install_element(ENABLE_NODE, &smsqueue_max_cmd);
1725 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
1726 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
1727 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001728 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001729
1730 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
1731 install_node(&mncc_int_node, config_write_mncc_int);
1732 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
1733 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
1734
1735 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
1736
1737 install_element(CONFIG_NODE, &cfg_hlr_cmd);
1738 install_node(&hlr_node, config_write_hlr);
1739 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
1740 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001741 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001742}