blob: a79f451fd6cfae9cc00ba3e6e6ea533d108809b0 [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>
Philipp Maier8fa2dbe2019-03-19 18:51:37 +010033#include <osmocom/gsm/protocol/gsm_08_08.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020034
Maxc51609a2018-11-09 17:13:00 +010035#include <osmocom/sigtran/sccp_helpers.h>
36
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020037#include <osmocom/vty/command.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010038#include <osmocom/vty/logging.h>
Stefan Sperling617ac802018-02-22 17:58:20 +010039#include <osmocom/vty/misc.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010040#include <osmocom/vty/stats.h>
41
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020042#ifdef BUILD_IU
43#include <osmocom/ranap/iu_client.h>
44#endif
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020045
Neels Hofmeyr90843962017-09-04 15:04:35 +020046#include <osmocom/msc/vty.h>
47#include <osmocom/msc/gsm_data.h>
48#include <osmocom/msc/gsm_subscriber.h>
49#include <osmocom/msc/vlr.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010050#include <osmocom/msc/transaction.h>
51#include <osmocom/msc/db.h>
Maxc51609a2018-11-09 17:13:00 +010052#include <osmocom/msc/a_iface.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010053#include <osmocom/msc/sms_queue.h>
54#include <osmocom/msc/silent_call.h>
55#include <osmocom/msc/gsm_04_80.h>
56#include <osmocom/msc/gsm_04_14.h>
57#include <osmocom/msc/signal.h>
58#include <osmocom/msc/mncc_int.h>
Vadim Yanitskiy1b891302018-08-04 01:33:08 +070059#include <osmocom/msc/rrlp.h>
Harald Welte0df904d2018-12-03 11:00:04 +010060#include <osmocom/msc/vlr_sgs.h>
61#include <osmocom/msc/sgs_vty.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010062
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010063static struct gsm_network *gsmnet = NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010064
65struct cmd_node net_node = {
66 GSMNET_NODE,
67 "%s(config-net)# ",
68 1,
69};
70
71#define NETWORK_STR "Configure the GSM network\n"
72#define CODE_CMD_STR "Code commands\n"
73#define NAME_CMD_STR "Name Commands\n"
74#define NAME_STR "Name to use\n"
75
76DEFUN(cfg_net,
77 cfg_net_cmd,
78 "network", NETWORK_STR)
79{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010080 vty->index = gsmnet;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010081 vty->node = GSMNET_NODE;
82
83 return CMD_SUCCESS;
84}
85
86DEFUN(cfg_net_ncc,
87 cfg_net_ncc_cmd,
88 "network country code <1-999>",
89 "Set the GSM network country code\n"
90 "Country commands\n"
91 CODE_CMD_STR
92 "Network Country Code to use\n")
93{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010094 gsmnet->plmn.mcc = atoi(argv[0]);
95
96 return CMD_SUCCESS;
97}
98
99DEFUN(cfg_net_mnc,
100 cfg_net_mnc_cmd,
101 "mobile network code <0-999>",
102 "Set the GSM mobile network code\n"
103 "Network Commands\n"
104 CODE_CMD_STR
105 "Mobile Network Code to use\n")
106{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100107 uint16_t mnc;
108 bool mnc_3_digits;
109
110 if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
111 vty_out(vty, "%% Error decoding MNC: %s%s", argv[0], VTY_NEWLINE);
112 return CMD_WARNING;
113 }
114
115 gsmnet->plmn.mnc = mnc;
116 gsmnet->plmn.mnc_3_digits = mnc_3_digits;
117
118 return CMD_SUCCESS;
119}
120
121DEFUN(cfg_net_name_short,
122 cfg_net_name_short_cmd,
123 "short name NAME",
124 "Set the short GSM network name\n" NAME_CMD_STR NAME_STR)
125{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100126 osmo_talloc_replace_string(gsmnet, &gsmnet->name_short, argv[0]);
127 return CMD_SUCCESS;
128}
129
130DEFUN(cfg_net_name_long,
131 cfg_net_name_long_cmd,
132 "long name NAME",
133 "Set the long GSM network name\n" NAME_CMD_STR NAME_STR)
134{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100135 osmo_talloc_replace_string(gsmnet, &gsmnet->name_long, argv[0]);
136 return CMD_SUCCESS;
137}
138
139DEFUN(cfg_net_encryption,
140 cfg_net_encryption_cmd,
141 "encryption a5 <0-3> [<0-3>] [<0-3>] [<0-3>]",
142 "Encryption options\n"
143 "GSM A5 Air Interface Encryption\n"
144 "A5/n Algorithm Number\n"
145 "A5/n Algorithm Number\n"
146 "A5/n Algorithm Number\n"
147 "A5/n Algorithm Number\n")
148{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100149 unsigned int i;
150
151 gsmnet->a5_encryption_mask = 0;
152 for (i = 0; i < argc; i++)
153 gsmnet->a5_encryption_mask |= (1 << atoi(argv[i]));
154
155 return CMD_SUCCESS;
156}
157
158DEFUN(cfg_net_authentication,
159 cfg_net_authentication_cmd,
160 "authentication (optional|required)",
161 "Whether to enforce MS authentication in 2G\n"
162 "Allow MS to attach via 2G BSC without authentication\n"
163 "Always do authentication\n")
164{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100165 gsmnet->authentication_required = (argv[0][0] == 'r') ? true : false;
166
167 return CMD_SUCCESS;
168}
169
170DEFUN(cfg_net_rrlp_mode, cfg_net_rrlp_mode_cmd,
171 "rrlp mode (none|ms-based|ms-preferred|ass-preferred)",
172 "Radio Resource Location Protocol\n"
173 "Set the Radio Resource Location Protocol Mode\n"
174 "Don't send RRLP request\n"
175 "Request MS-based location\n"
176 "Request any location, prefer MS-based\n"
177 "Request any location, prefer MS-assisted\n")
178{
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700179 gsmnet->rrlp.mode = msc_rrlp_mode_parse(argv[0]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100180
181 return CMD_SUCCESS;
182}
183
184DEFUN(cfg_net_mm_info, cfg_net_mm_info_cmd,
185 "mm info (0|1)",
186 "Mobility Management\n"
187 "Send MM INFO after LOC UPD ACCEPT\n"
188 "Disable\n" "Enable\n")
189{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100190 gsmnet->send_mm_info = atoi(argv[0]);
191
192 return CMD_SUCCESS;
193}
194
195DEFUN(cfg_net_timezone,
196 cfg_net_timezone_cmd,
197 "timezone <-19-19> (0|15|30|45)",
198 "Set the Timezone Offset of the network\n"
199 "Timezone offset (hours)\n"
200 "Timezone offset (00 minutes)\n"
201 "Timezone offset (15 minutes)\n"
202 "Timezone offset (30 minutes)\n"
203 "Timezone offset (45 minutes)\n"
204 )
205{
206 struct gsm_network *net = vty->index;
207 int tzhr = atoi(argv[0]);
208 int tzmn = atoi(argv[1]);
209
210 net->tz.hr = tzhr;
211 net->tz.mn = tzmn;
212 net->tz.dst = 0;
213 net->tz.override = 1;
214
215 return CMD_SUCCESS;
216}
217
218DEFUN(cfg_net_timezone_dst,
219 cfg_net_timezone_dst_cmd,
220 "timezone <-19-19> (0|15|30|45) <0-2>",
221 "Set the Timezone Offset of the network\n"
222 "Timezone offset (hours)\n"
223 "Timezone offset (00 minutes)\n"
224 "Timezone offset (15 minutes)\n"
225 "Timezone offset (30 minutes)\n"
226 "Timezone offset (45 minutes)\n"
227 "DST offset (hours)\n"
228 )
229{
230 struct gsm_network *net = vty->index;
231 int tzhr = atoi(argv[0]);
232 int tzmn = atoi(argv[1]);
233 int tzdst = atoi(argv[2]);
234
235 net->tz.hr = tzhr;
236 net->tz.mn = tzmn;
237 net->tz.dst = tzdst;
238 net->tz.override = 1;
239
240 return CMD_SUCCESS;
241}
242
243DEFUN(cfg_net_no_timezone,
244 cfg_net_no_timezone_cmd,
245 "no timezone",
246 NO_STR
247 "Disable network timezone override, use system tz\n")
248{
249 struct gsm_network *net = vty->index;
250
251 net->tz.override = 0;
252
253 return CMD_SUCCESS;
254}
255
256DEFUN(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
257 "periodic location update <6-1530>",
258 "Periodic Location Updating Interval\n"
259 "Periodic Location Updating Interval\n"
260 "Periodic Location Updating Interval\n"
261 "Periodic Location Updating Interval in Minutes\n")
262{
263 struct gsm_network *net = vty->index;
264
265 net->t3212 = atoi(argv[0]) / 6;
266
267 return CMD_SUCCESS;
268}
269
270DEFUN(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
271 "no periodic location update",
272 NO_STR
273 "Periodic Location Updating Interval\n"
274 "Periodic Location Updating Interval\n"
275 "Periodic Location Updating Interval\n")
276{
277 struct gsm_network *net = vty->index;
278
279 net->t3212 = 0;
280
281 return CMD_SUCCESS;
282}
283
284static int config_write_net(struct vty *vty)
285{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100286 int i;
287
288 vty_out(vty, "network%s", VTY_NEWLINE);
289 vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
290 vty_out(vty, " mobile network code %s%s",
291 osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
292 vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
293 vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
294 vty_out(vty, " encryption a5");
295 for (i = 0; i < 8; i++) {
296 if (gsmnet->a5_encryption_mask & (1 << i))
297 vty_out(vty, " %u", i);
298 }
299 vty_out(vty, "%s", VTY_NEWLINE);
300 vty_out(vty, " authentication %s%s",
301 gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE);
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700302 vty_out(vty, " rrlp mode %s%s", msc_rrlp_mode_name(gsmnet->rrlp.mode),
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100303 VTY_NEWLINE);
304 vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
305 if (gsmnet->tz.override != 0) {
306 if (gsmnet->tz.dst)
307 vty_out(vty, " timezone %d %d %d%s",
308 gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
309 VTY_NEWLINE);
310 else
311 vty_out(vty, " timezone %d %d%s",
312 gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
313 }
314 if (gsmnet->t3212 == 0)
315 vty_out(vty, " no periodic location update%s", VTY_NEWLINE);
316 else
317 vty_out(vty, " periodic location update %u%s",
318 gsmnet->t3212 * 6, VTY_NEWLINE);
319
320 if (gsmnet->emergency.route_to_msisdn) {
321 vty_out(vty, " emergency-call route-to-msisdn %s%s",
322 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
323 }
324
325 return CMD_SUCCESS;
326}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200327
328static struct cmd_node msc_node = {
329 MSC_NODE,
330 "%s(config-msc)# ",
331 1,
332};
333
334DEFUN(cfg_msc, cfg_msc_cmd,
335 "msc", "Configure MSC options")
336{
337 vty->node = MSC_NODE;
338 return CMD_SUCCESS;
339}
340
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100341#define MNCC_STR "Configure Mobile Network Call Control\n"
342#define MNCC_GUARD_TIMEOUT_STR "Set global guard timer for mncc interface activity\n"
343#define MNCC_GUARD_TIMEOUT_VALUE_STR "guard timer value (sec.)\n"
344
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100345DEFUN(cfg_msc_mncc_internal,
346 cfg_msc_mncc_internal_cmd,
347 "mncc internal",
348 MNCC_STR "Use internal MNCC handler (default; changes need a program restart)\n")
349{
350 gsm_network_set_mncc_sock_path(gsmnet, NULL);
351 return CMD_SUCCESS;
352}
353
354DEFUN(cfg_msc_mncc_external,
355 cfg_msc_mncc_external_cmd,
356 "mncc external MNCC_SOCKET_PATH",
357 MNCC_STR "Use external MNCC handler (changes need a program restart)\n"
358 "File system path to create the MNCC unix domain socket at\n")
359{
360 gsm_network_set_mncc_sock_path(gsmnet, argv[0]);
361 return CMD_SUCCESS;
362}
363
Philipp Maier9ca7b312018-10-10 17:00:49 +0200364DEFUN(cfg_msc_mncc_guard_timeout,
365 cfg_msc_mncc_guard_timeout_cmd,
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100366 "mncc guard-timeout <0-255>",
367 MNCC_STR
368 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR)
Philipp Maier9ca7b312018-10-10 17:00:49 +0200369{
370 gsmnet->mncc_guard_timeout = atoi(argv[0]);
371 return CMD_SUCCESS;
372}
373
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100374ALIAS_DEPRECATED(cfg_msc_mncc_guard_timeout,
375 cfg_msc_deprecated_mncc_guard_timeout_cmd,
376 "mncc-guard-timeout <0-255>",
377 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR);
378
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700379#define NCSS_STR "Configure call independent Supplementary Services\n"
380
381DEFUN(cfg_msc_ncss_guard_timeout,
382 cfg_msc_ncss_guard_timeout_cmd,
383 "ncss guard-timeout <0-255>",
384 NCSS_STR "Set guard timer for session activity\n"
385 "guard timer value (sec.), or 0 to disable\n")
386{
387 gsmnet->ncss_guard_timeout = atoi(argv[0]);
388 return CMD_SUCCESS;
389}
390
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200391DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
392 "assign-tmsi",
393 "Assign TMSI during Location Updating.\n")
394{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200395 gsmnet->vlr->cfg.assign_tmsi = true;
396 return CMD_SUCCESS;
397}
398
399DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
400 "no assign-tmsi",
401 NO_STR "Assign TMSI during Location Updating.\n")
402{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200403 gsmnet->vlr->cfg.assign_tmsi = false;
404 return CMD_SUCCESS;
405}
406
Philipp Maierfbf66102017-04-09 12:32:51 +0200407DEFUN(cfg_msc_cs7_instance_a,
408 cfg_msc_cs7_instance_a_cmd,
409 "cs7-instance-a <0-15>",
410 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
411{
Philipp Maierfbf66102017-04-09 12:32:51 +0200412 gsmnet->a.cs7_instance = atoi(argv[0]);
413 return CMD_SUCCESS;
414}
415
416DEFUN(cfg_msc_cs7_instance_iu,
417 cfg_msc_cs7_instance_iu_cmd,
418 "cs7-instance-iu <0-15>",
419 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
420{
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100421#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200422 gsmnet->iu.cs7_instance = atoi(argv[0]);
423 return CMD_SUCCESS;
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100424#else
425 vty_out(vty, "WARNING: 'cs7-instance-iu' without effect: built without Iu support%s",
426 VTY_NEWLINE);
427 return CMD_WARNING;
428#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200429}
430
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100431DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
432 "auth-tuple-max-reuse-count <-1-2147483647>",
433 "Configure authentication tuple re-use\n"
434 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
435{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100436 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
437 return CMD_SUCCESS;
438}
439
440DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
441 "auth-tuple-reuse-on-error (0|1)",
442 "Configure authentication tuple re-use when HLR is not responsive\n"
Oliver Smithd6e24fd2019-01-09 10:46:43 +0100443 "Never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
444 "If the HLR does not deliver new tuples, do re-use already available old ones.\n")
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100445{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100446 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
447 return CMD_SUCCESS;
448}
449
Oliver Smith0fec28a2018-12-14 10:52:52 +0100450DEFUN(cfg_msc_check_imei_rqd, cfg_msc_check_imei_rqd_cmd,
451 "check-imei-rqd (0|1)",
452 "Send each IMEI to the EIR to ask if it is permitted or not. The EIR is implemented as part of OsmoHLR, "
453 "and can optionally save the IMEI in the HLR.\n"
454 "Do not send IMEIs to the EIR\n"
455 "Send each IMEI to the EIR\n")
456{
457 gsmnet->vlr->cfg.check_imei_rqd = atoi(argv[0]) ? true : false;
458 return CMD_SUCCESS;
459}
460
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100461DEFUN(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
462 "paging response-timer (default|<1-65535>)",
463 "Configure Paging\n"
464 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
465 " BSS or RNC\n"
466 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
467 "Set paging timeout in seconds\n")
468{
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100469 if (!strcmp(argv[1], "default"))
470 gsmnet->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
471 else
472 gsmnet->paging_response_timer = atoi(argv[0]);
473 return CMD_SUCCESS;
474}
475
Harald Welte69c54a82018-02-09 20:41:14 +0100476DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
477 "emergency-call route-to-msisdn MSISDN",
478 "Configure Emergency Call Behaviour\n"
479 "MSISDN to which Emergency Calls are Dispatched\n"
480 "MSISDN (E.164 Phone Number)\n")
481{
Harald Welte69c54a82018-02-09 20:41:14 +0100482 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
483
484 return CMD_SUCCESS;
485}
486
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700487/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
488DEFUN(cfg_msc_sms_over_gsup, cfg_msc_sms_over_gsup_cmd,
489 "sms-over-gsup",
490 "Enable routing of SMS messages over GSUP\n")
491{
492 gsmnet->sms_over_gsup = true;
493 return CMD_SUCCESS;
494}
495
496/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
497DEFUN(cfg_msc_no_sms_over_gsup, cfg_msc_no_sms_over_gsup_cmd,
498 "no sms-over-gsup",
499 NO_STR "Disable routing of SMS messages over GSUP\n")
500{
501 gsmnet->sms_over_gsup = false;
502 return CMD_SUCCESS;
503}
504
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200505static int config_write_msc(struct vty *vty)
506{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200507 vty_out(vty, "msc%s", VTY_NEWLINE);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100508 if (gsmnet->mncc_sock_path)
509 vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE);
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100510 vty_out(vty, " mncc guard-timeout %i%s",
Philipp Maier9ca7b312018-10-10 17:00:49 +0200511 gsmnet->mncc_guard_timeout, VTY_NEWLINE);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700512 vty_out(vty, " ncss guard-timeout %i%s",
513 gsmnet->ncss_guard_timeout, VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200514 vty_out(vty, " %sassign-tmsi%s",
515 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
516
Philipp Maierfbf66102017-04-09 12:32:51 +0200517 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
518 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100519#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200520 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
521 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100522#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200523
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100524 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
525 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
526 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
527 VTY_NEWLINE);
528 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
529 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
530 VTY_NEWLINE);
531
Oliver Smith0fec28a2018-12-14 10:52:52 +0100532 if (gsmnet->vlr->cfg.check_imei_rqd)
533 vty_out(vty, " check-imei-rqd 1 %s",
534 VTY_NEWLINE);
535
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100536 if (gsmnet->paging_response_timer != MSC_PAGING_RESPONSE_TIMER_DEFAULT)
537 vty_out(vty, " paging response-timer %u%s", gsmnet->paging_response_timer, VTY_NEWLINE);
538
Harald Welte69c54a82018-02-09 20:41:14 +0100539 if (gsmnet->emergency.route_to_msisdn) {
540 vty_out(vty, " emergency-call route-to-msisdn %s%s",
541 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
542 }
543
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700544 if (gsmnet->sms_over_gsup)
545 vty_out(vty, " sms-over-gsup%s", VTY_NEWLINE);
546
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200547 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200548#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200549 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200550#endif
551
552 return CMD_SUCCESS;
553}
554
Maxc51609a2018-11-09 17:13:00 +0100555DEFUN(show_bsc, show_bsc_cmd,
556 "show bsc", SHOW_STR "BSC\n")
557{
558 struct bsc_context *bsc_ctx;
559 struct osmo_ss7_instance *ss7 = osmo_ss7_instance_find(gsmnet->a.cs7_instance);
560
561 llist_for_each_entry(bsc_ctx, &gsmnet->a.bscs, list) {
562 vty_out(vty, "BSC %s%s", osmo_sccp_addr_name(ss7, &bsc_ctx->bsc_addr), VTY_NEWLINE);
563 }
564
565 return CMD_SUCCESS;
566}
567
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100568static void vty_conn_hdr(struct vty *vty)
569{
Max45df98b2019-01-17 18:44:33 +0100570 unsigned lnum = 0;
571 struct ran_conn *conn;
572
573 llist_for_each_entry(conn, &gsmnet->ran_conns, entry)
574 lnum++;
575
576 if (lnum)
577 vty_out(vty, "--ConnId RAN --LAC Use --Tokens C A5 State ------------ Subscriber%s",
578 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100579}
580
Neels Hofmeyrc036b792018-11-29 22:37:51 +0100581static void vty_dump_one_conn(struct vty *vty, const struct ran_conn *conn)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100582{
Max45df98b2019-01-17 18:44:33 +0100583 vty_out(vty, "%08x %3s %5u %3u %08x %c /%1u %27s %22s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100584 conn->a.conn_id,
Harald Welte0df904d2018-12-03 11:00:04 +0100585 osmo_rat_type_name(conn->via_ran),
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100586 conn->lac,
587 conn->use_count,
588 conn->use_tokens,
589 conn->received_cm_service_request ? 'C' : '-',
Neels Hofmeyrf41658d2018-11-30 04:35:50 +0100590 conn->geran_encr.alg_id,
Neels Hofmeyr4d3a66b2018-03-31 18:45:59 +0200591 conn->fi ? osmo_fsm_inst_state_name(conn->fi) : "-",
Max45df98b2019-01-17 18:44:33 +0100592 conn->vsub ? vlr_subscr_name(conn->vsub) : "-",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100593 VTY_NEWLINE);
594}
595
596DEFUN(show_msc_conn, show_msc_conn_cmd,
597 "show connection", SHOW_STR "Subscriber Connections\n")
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200598{
Neels Hofmeyrc036b792018-11-29 22:37:51 +0100599 struct ran_conn *conn;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200600
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100601 vty_conn_hdr(vty);
Neels Hofmeyrc036b792018-11-29 22:37:51 +0100602 llist_for_each_entry(conn, &gsmnet->ran_conns, entry)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100603 vty_dump_one_conn(vty, conn);
604
605 return CMD_SUCCESS;
606}
607
608static void vty_trans_hdr(struct vty *vty)
609{
Max45df98b2019-01-17 18:44:33 +0100610 unsigned lnum = 0;
611 struct gsm_trans *trans;
612
613 llist_for_each_entry(trans, &gsmnet->trans_list, entry)
614 lnum++;
615
616 if (lnum)
617 vty_out(vty, "--ConnId -P TI -CallRef [--- Proto ---] ------------ Subscriber%s",
618 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100619}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200620
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100621static const char *get_trans_proto_str(const struct gsm_trans *trans)
622{
623 static char buf[256];
624
625 switch (trans->protocol) {
626 case GSM48_PDISC_CC:
627 snprintf(buf, sizeof(buf), "%s %4u %4u",
628 gsm48_cc_state_name(trans->cc.state),
629 trans->cc.Tcurrent,
630 trans->cc.T308_second);
631 break;
632 case GSM48_PDISC_SMS:
633 snprintf(buf, sizeof(buf), "%s %s",
634 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
635 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
636 break;
637 default:
638 buf[0] = '\0';
639 break;
640 }
641
642 return buf;
643}
644
645static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans)
646{
Max45df98b2019-01-17 18:44:33 +0100647 vty_out(vty, "%08x %s %02u %08x [%s] %22s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100648 trans->conn ? trans->conn->a.conn_id : 0,
649 gsm48_pdisc_name(trans->protocol),
650 trans->transaction_id,
651 trans->callref,
Max45df98b2019-01-17 18:44:33 +0100652 get_trans_proto_str(trans),
653 trans->vsub ? vlr_subscr_name(trans->vsub) : "-",
654 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100655}
656
657DEFUN(show_msc_transaction, show_msc_transaction_cmd,
658 "show transaction", SHOW_STR "Transactions\n")
659{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100660 struct gsm_trans *trans;
661
662 vty_trans_hdr(vty);
663 llist_for_each_entry(trans, &gsmnet->trans_list, entry)
664 vty_dump_one_trans(vty, trans);
665
666 return CMD_SUCCESS;
667}
668
669static void subscr_dump_full_vty(struct vty *vty, struct vlr_subscr *vsub)
670{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100671 struct gsm_trans *trans;
672 int reqs;
673 struct llist_head *entry;
674
675 if (strlen(vsub->name))
676 vty_out(vty, " Name: '%s'%s", vsub->name, VTY_NEWLINE);
677 if (strlen(vsub->msisdn))
678 vty_out(vty, " Extension: %s%s", vsub->msisdn,
679 VTY_NEWLINE);
680 vty_out(vty, " LAC: %d/0x%x%s",
Max7d41d872018-12-19 11:48:33 +0100681 vsub->cgi.lai.lac, vsub->cgi.lai.lac, VTY_NEWLINE);
Philipp Maier2a0ac3b2018-12-17 10:03:50 +0100682 vty_out(vty, " RAN: %s%s",
Neels Hofmeyr7814a832018-12-26 00:40:18 +0100683 osmo_rat_type_name(vsub->cs.attached_via_ran), VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100684 vty_out(vty, " IMSI: %s%s", vsub->imsi, VTY_NEWLINE);
685 if (vsub->tmsi != GSM_RESERVED_TMSI)
686 vty_out(vty, " TMSI: %08X%s", vsub->tmsi,
687 VTY_NEWLINE);
688 if (vsub->tmsi_new != GSM_RESERVED_TMSI)
689 vty_out(vty, " new TMSI: %08X%s", vsub->tmsi_new,
690 VTY_NEWLINE);
Philipp Maier6d71ccf2018-12-14 13:30:14 +0100691 if (vsub->imei[0] != '\0')
692 vty_out(vty, " IMEI: %s%s", vsub->imei, VTY_NEWLINE);
693 if (vsub->imeisv[0] != '\0')
694 vty_out(vty, " IMEISV: %s%s", vsub->imeisv, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100695
Philipp Maier89561bc2018-12-14 13:34:25 +0100696 vty_out(vty, " Flags: %s", VTY_NEWLINE);
697 vty_out(vty, " IMSI detached: %s%s",
698 vsub->imsi_detached_flag ? "true" : "false", VTY_NEWLINE);
699 vty_out(vty, " Conf. by radio contact: %s%s",
700 vsub->conf_by_radio_contact_ind ? "true" : "false",
701 VTY_NEWLINE);
702 vty_out(vty, " Subscr. data conf. by HLR: %s%s",
703 vsub->sub_dataconf_by_hlr_ind ? "true" : "false", VTY_NEWLINE);
704 vty_out(vty, " Location conf. in HLR: %s%s",
705 vsub->loc_conf_in_hlr_ind ? "true" : "false", VTY_NEWLINE);
706 vty_out(vty, " Subscriber dormant: %s%s",
707 vsub->dormant_ind ? "true" : "false", VTY_NEWLINE);
708 vty_out(vty, " Received cancel locataion: %s%s",
709 vsub->cancel_loc_rx ? "true" : "false", VTY_NEWLINE);
710 vty_out(vty, " MS not reachable: %s%s",
711 vsub->ms_not_reachable_flag ? "true" : "false", VTY_NEWLINE);
712 vty_out(vty, " LA allowed: %s%s",
713 vsub->la_allowed ? "true" : "false", VTY_NEWLINE);
714
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100715#if 0
716 /* TODO: add this to vlr_subscr? */
717 if (vsub->auth_info.auth_algo != AUTH_ALGO_NONE) {
718 struct gsm_auth_info *i = &vsub->auth_info;
719 vty_out(vty, " A3A8 algorithm id: %d%s",
720 i->auth_algo, VTY_NEWLINE);
721 vty_out(vty, " A3A8 Ki: %s%s",
722 osmo_hexdump(i->a3a8_ki, i->a3a8_ki_len),
723 VTY_NEWLINE);
724 }
725#endif
726
727 if (vsub->last_tuple) {
Neels Hofmeyr8b6e5362018-11-30 02:57:33 +0100728 struct vlr_auth_tuple *t = vsub->last_tuple;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100729 vty_out(vty, " A3A8 last tuple (used %d times):%s",
730 t->use_count, VTY_NEWLINE);
731 vty_out(vty, " seq # : %d%s",
732 t->key_seq, VTY_NEWLINE);
733 vty_out(vty, " RAND : %s%s",
734 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
735 VTY_NEWLINE);
736 vty_out(vty, " SRES : %s%s",
737 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
738 VTY_NEWLINE);
739 vty_out(vty, " Kc : %s%s",
740 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
741 VTY_NEWLINE);
742 }
743
744 reqs = 0;
745 llist_for_each(entry, &vsub->cs.requests)
746 reqs += 1;
747 vty_out(vty, " Paging: %s paging for %d requests%s",
748 vsub->cs.is_paging ? "is" : "not", reqs, VTY_NEWLINE);
Harald Welte0df904d2018-12-03 11:00:04 +0100749
750 /* SGs related */
751 vty_out(vty, " SGs-state: %s%s",
752 osmo_fsm_inst_state_name(vsub->sgs_fsm), VTY_NEWLINE);
Vadim Yanitskiy477cbc62019-02-23 16:59:16 +0700753 if (strlen(vsub->sgs.mme_name))
Harald Welte0df904d2018-12-03 11:00:04 +0100754 vty_out(vty, " SGs-MME: %s%s", vsub->sgs.mme_name, VTY_NEWLINE);
755 else
756 vty_out(vty, " SGs-MME: (none)%s", VTY_NEWLINE);
757
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100758 vty_out(vty, " Use count: %u%s", vsub->use_count, VTY_NEWLINE);
759
760 /* Connection */
761 if (vsub->msc_conn_ref) {
Neels Hofmeyrc036b792018-11-29 22:37:51 +0100762 struct ran_conn *conn = vsub->msc_conn_ref;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100763 vty_conn_hdr(vty);
764 vty_dump_one_conn(vty, conn);
765 }
766
767 /* Transactions */
768 vty_trans_hdr(vty);
769 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
770 if (trans->vsub != vsub)
771 continue;
772 vty_dump_one_trans(vty, trans);
773 }
774}
775
776/* Subscriber */
777DEFUN(show_subscr_cache,
778 show_subscr_cache_cmd,
779 "show subscriber cache",
780 SHOW_STR "Show information about subscribers\n"
781 "Display contents of subscriber cache\n")
782{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100783 struct vlr_subscr *vsub;
784 int count = 0;
785
786 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
787 if (++count > 100) {
788 vty_out(vty, "%% More than %d subscribers in cache,"
789 " stopping here.%s", count-1, VTY_NEWLINE);
790 break;
791 }
792 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
793 subscr_dump_full_vty(vty, vsub);
Harald Welte69c54a82018-02-09 20:41:14 +0100794 }
795
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200796 return CMD_SUCCESS;
797}
798
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100799DEFUN(sms_send_pend,
800 sms_send_pend_cmd,
801 "sms send pending",
802 "SMS related commands\n" "SMS Sending related commands\n"
803 "Send all pending SMS")
804{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100805 struct gsm_sms *sms;
806 unsigned long long sms_id = 0;
807
808 while (1) {
809 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
810 if (!sms)
811 break;
812
813 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +0700814 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100815
816 sms_id = sms->id + 1;
817 }
818
819 return CMD_SUCCESS;
820}
821
822DEFUN(sms_delete_expired,
823 sms_delete_expired_cmd,
824 "sms delete expired",
825 "SMS related commands\n" "SMS Database related commands\n"
826 "Delete all expired SMS")
827{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100828 struct gsm_sms *sms;
829 unsigned long long sms_id = 0;
830 long long num_deleted = 0;
831
832 while (1) {
833 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
834 if (!sms)
835 break;
836
837 /* Skip SMS which are currently queued for sending. */
838 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
839 continue;
840
841 /* Expiration check is performed by the DB layer. */
842 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
843 num_deleted++;
844
845 sms_id = sms->id + 1;
846 }
847
848 if (num_deleted == 0) {
849 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
850 return CMD_WARNING;
851 }
852
853 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
854 return CMD_SUCCESS;
855}
856
857static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +0200858 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100859 char *str, uint8_t tp_pid)
860{
861 struct gsm_network *net = receiver->vlr->user_ctx;
862 struct gsm_sms *sms;
863
Harald Welte39b55482018-04-09 19:19:33 +0200864 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100865 sms->protocol_id = tp_pid;
866
867 /* store in database for the queue */
868 if (db_sms_store(sms) != 0) {
869 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
870 sms_free(sms);
871 return CMD_WARNING;
872 }
873 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
874
875 sms_free(sms);
876 sms_queue_trigger(net->sms_queue);
877 return CMD_SUCCESS;
878}
879
880static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
881 const char *type,
882 const char *id)
883{
884 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
885 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id);
886 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
887 return vlr_subscr_find_by_imsi(gsmnet->vlr, id);
888 else if (!strcmp(type, "tmsi"))
889 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id));
890
891 return NULL;
892}
893#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
894#define SUBSCR_HELP "Operations on a Subscriber\n" \
895 "Identify subscriber by MSISDN (phone number)\n" \
896 "Legacy alias for 'msisdn'\n" \
897 "Identify subscriber by IMSI\n" \
898 "Identify subscriber by TMSI\n" \
899 "Identify subscriber by database ID\n" \
900 "Identifier for the subscriber\n"
901
902DEFUN(show_subscr,
903 show_subscr_cmd,
904 "show subscriber " SUBSCR_TYPES " ID",
905 SHOW_STR SUBSCR_HELP)
906{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100907 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
908 argv[1]);
909
910 if (!vsub) {
911 vty_out(vty, "%% No subscriber found for %s %s%s",
912 argv[0], argv[1], VTY_NEWLINE);
913 return CMD_WARNING;
914 }
915
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +0100916 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
917 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
918 * 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 +0100919 vlr_subscr_put(vsub);
920
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +0100921 subscr_dump_full_vty(vty, vsub);
922
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100923 return CMD_SUCCESS;
924}
925
926DEFUN(subscriber_create,
927 subscriber_create_cmd,
928 "subscriber create imsi ID",
929 "Operations on a Subscriber\n" \
930 "Create new subscriber\n" \
931 "Identify the subscriber by his IMSI\n" \
932 "Identifier for the subscriber\n")
933{
934 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
935 VTY_NEWLINE);
936 return CMD_WARNING;
937}
938
939DEFUN(subscriber_send_pending_sms,
940 subscriber_send_pending_sms_cmd,
941 "subscriber " SUBSCR_TYPES " ID sms pending-send",
942 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
943{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100944 struct vlr_subscr *vsub;
945 struct gsm_sms *sms;
946
947 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
948 if (!vsub) {
949 vty_out(vty, "%% No subscriber found for %s %s%s",
950 argv[0], argv[1], VTY_NEWLINE);
951 return CMD_WARNING;
952 }
953
954 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
955 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +0700956 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100957
958 vlr_subscr_put(vsub);
959
960 return CMD_SUCCESS;
961}
962
Neels Hofmeyrf90496f2019-03-06 16:19:50 +0100963DEFUN(subscriber_sms_delete_all,
964 subscriber_sms_delete_all_cmd,
965 "subscriber " SUBSCR_TYPES " ID sms delete-all",
966 SUBSCR_HELP "SMS Operations\n"
967 "Delete all SMS to be delivered to this subscriber"
968 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
969 " WILL BE LOST.\n")
970{
971 struct vlr_subscr *vsub;
972
973 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
974 if (!vsub) {
975 vty_out(vty, "%% No subscriber found for %s %s%s",
976 argv[0], argv[1], VTY_NEWLINE);
977 return CMD_WARNING;
978 }
979
980 db_sms_delete_by_msisdn(vsub->msisdn);
981
982 vlr_subscr_put(vsub);
983
984 return CMD_SUCCESS;
985}
986
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100987DEFUN(subscriber_send_sms,
988 subscriber_send_sms_cmd,
989 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
990 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
991{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100992 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +0200993 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100994 char *str;
995 int rc;
996
997 if (!vsub) {
998 vty_out(vty, "%% No subscriber found for %s %s%s",
999 argv[0], argv[1], VTY_NEWLINE);
1000 rc = CMD_WARNING;
1001 goto err;
1002 }
1003
Harald Welte39b55482018-04-09 19:19:33 +02001004 if (!strcmp(argv[2], "msisdn"))
1005 sender_msisdn = argv[3];
1006 else {
1007 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1008 if (!sender) {
1009 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1010 rc = CMD_WARNING;
1011 goto err;
1012 }
1013 sender_msisdn = sender->msisdn;
1014 vlr_subscr_put(sender);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001015 }
1016
1017 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001018 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001019 talloc_free(str);
1020
1021err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001022 if (vsub)
1023 vlr_subscr_put(vsub);
1024
1025 return rc;
1026}
1027
1028DEFUN(subscriber_silent_sms,
1029 subscriber_silent_sms_cmd,
1030
1031 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1032 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1033{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001034 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001035 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001036 char *str;
1037 int rc;
1038
1039 if (!vsub) {
1040 vty_out(vty, "%% No subscriber found for %s %s%s",
1041 argv[0], argv[1], VTY_NEWLINE);
1042 rc = CMD_WARNING;
1043 goto err;
1044 }
1045
Harald Welte39b55482018-04-09 19:19:33 +02001046 if (!strcmp(argv[2], "msisdn")) {
1047 sender_msisdn = argv[3];
1048 } else {
1049 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1050 if (!sender) {
1051 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1052 rc = CMD_WARNING;
1053 goto err;
1054 }
1055 sender_msisdn = sender->msisdn;
1056 vlr_subscr_put(sender);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001057 }
1058
1059 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001060 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001061 talloc_free(str);
1062
1063err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001064 if (vsub)
1065 vlr_subscr_put(vsub);
1066
1067 return rc;
1068}
1069
Sylvain Munaut93558302019-02-14 20:13:08 +01001070#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001071#define CHAN_TYPE_HELP \
1072 "Any channel\n" \
1073 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001074 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001075 "Any TCH channel\n" \
1076 "SDCCH channel\n"
1077
Sylvain Munaut93558302019-02-14 20:13:08 +01001078#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1079#define CHAN_MODE_HELP \
1080 "Signalling only\n" \
1081 "Speech with HR codec\n" \
1082 "Speech with FR codec\n" \
1083 "Speech with EFR codec\n" \
1084 "Speech with AMR codec\n"
1085
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001086DEFUN(subscriber_silent_call_start,
1087 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001088 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001089 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001090 CHAN_TYPE_HELP CHAN_MODE_HELP
1091 "Target IP for RTP traffic (default 127.0.0.1)\n"
1092 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001093{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001094 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001095 struct gsm0808_channel_type ct;
1096 const char *ip;
1097 uint16_t port;
1098 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001099
1100 if (!vsub) {
1101 vty_out(vty, "%% No subscriber found for %s %s%s",
1102 argv[0], argv[1], VTY_NEWLINE);
1103 return CMD_WARNING;
1104 }
1105
Sylvain Munaut93558302019-02-14 20:13:08 +01001106 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001107
Sylvain Munaut93558302019-02-14 20:13:08 +01001108 if (!strcmp(argv[3], "signalling")) {
1109 ct.ch_indctr = GSM0808_CHAN_SIGN;
1110 ct.perm_spch[0] = 0; /* Spare but required */
1111 ct.perm_spch_len = 1;
1112 } else if (!strcmp(argv[3], "speech-hr")) {
1113 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1114 ct.perm_spch[0] = GSM0808_PERM_HR1;
1115 ct.perm_spch_len = 1;
1116 } else if (!strcmp(argv[3], "speech-fr")) {
1117 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1118 ct.perm_spch[0] = GSM0808_PERM_FR1;
1119 ct.perm_spch_len = 1;
1120 } else if (!strcmp(argv[3], "speech-efr")) {
1121 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1122 ct.perm_spch[0] = GSM0808_PERM_FR2;
1123 ct.perm_spch_len = 1;
1124 } else if (!strcmp(argv[3], "speech-amr")) {
1125 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1126 ct.perm_spch[0] = GSM0808_PERM_FR3;
1127 ct.perm_spch[1] = GSM0808_PERM_HR3;
1128 ct.perm_spch_len = 2;
1129 }
1130
1131 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1132
1133 if (!strcmp(argv[2], "tch/f"))
1134 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1135 else if (!strcmp(argv[2], "tch/h"))
1136 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1137 else if (!strcmp(argv[2], "tch/any"))
1138 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1139 else if (!strcmp(argv[2], "sdcch")) {
1140 if (speech) {
1141 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1142 return CMD_WARNING;
1143 }
1144 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1145 } else
1146 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1147
1148 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1149 port = argc >= 6 ? atoi(argv[5]) : 4000;
1150
1151 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001152 switch (rc) {
1153 case -ENODEV:
1154 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1155 break;
1156 default:
1157 if (rc)
1158 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1159 else
1160 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1161 break;
1162 }
1163
1164 vlr_subscr_put(vsub);
1165 return rc ? CMD_WARNING : CMD_SUCCESS;
1166}
1167
1168DEFUN(subscriber_silent_call_stop,
1169 subscriber_silent_call_stop_cmd,
1170 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1171 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1172 CHAN_TYPE_HELP)
1173{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001174 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1175 int rc;
1176
1177 if (!vsub) {
1178 vty_out(vty, "%% No subscriber found for %s %s%s",
1179 argv[0], argv[1], VTY_NEWLINE);
1180 return CMD_WARNING;
1181 }
1182
1183 rc = gsm_silent_call_stop(vsub);
1184 switch (rc) {
1185 case -ENODEV:
1186 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1187 break;
1188 case -ENOENT:
1189 vty_out(vty, "%% Subscriber has no silent call active%s",
1190 VTY_NEWLINE);
1191 break;
1192 default:
1193 if (rc)
1194 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1195 else
1196 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1197 break;
1198 }
1199
1200 vlr_subscr_put(vsub);
1201 return rc ? CMD_WARNING : CMD_SUCCESS;
1202}
1203
1204DEFUN(subscriber_ussd_notify,
1205 subscriber_ussd_notify_cmd,
1206 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1207 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1208 "Alerting Level 0\n"
1209 "Alerting Level 1\n"
1210 "Alerting Level 2\n"
1211 "Text of USSD message to send\n")
1212{
1213 char *text;
Neels Hofmeyrc036b792018-11-29 22:37:51 +01001214 struct ran_conn *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001215 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1216 int level;
1217
1218 if (!vsub) {
1219 vty_out(vty, "%% No subscriber found for %s %s%s",
1220 argv[0], argv[1], VTY_NEWLINE);
1221 return CMD_WARNING;
1222 }
1223
1224 level = atoi(argv[2]);
1225 text = argv_concat(argv, argc, 3);
1226 if (!text) {
1227 vlr_subscr_put(vsub);
1228 return CMD_WARNING;
1229 }
1230
1231 conn = connection_for_subscr(vsub);
1232 if (!conn) {
1233 vty_out(vty, "%% An active connection is required for %s %s%s",
1234 argv[0], argv[1], VTY_NEWLINE);
1235 vlr_subscr_put(vsub);
1236 talloc_free(text);
1237 return CMD_WARNING;
1238 }
1239
1240 msc_send_ussd_notify(conn, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001241 /* FIXME: since we don't allocate a transaction here,
1242 * we use dummy GSM 04.07 transaction ID. */
1243 msc_send_ussd_release_complete(conn, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001244
1245 vlr_subscr_put(vsub);
1246 talloc_free(text);
1247 return CMD_SUCCESS;
1248}
1249
1250DEFUN(subscriber_paging,
1251 subscriber_paging_cmd,
1252 "subscriber " SUBSCR_TYPES " ID paging",
1253 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1254{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001255 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1256 struct subscr_request *req;
1257
1258 if (!vsub) {
1259 vty_out(vty, "%% No subscriber found for %s %s%s",
1260 argv[0], argv[1], VTY_NEWLINE);
1261 return CMD_WARNING;
1262 }
1263
Harald Welte0df904d2018-12-03 11:00:04 +01001264 req = subscr_request_conn(vsub, NULL, NULL, "manual Paging from VTY", SGSAP_SERV_IND_CS_CALL);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001265 if (req)
1266 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1267 else
1268 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1269
1270 vlr_subscr_put(vsub);
1271 return req ? CMD_SUCCESS : CMD_WARNING;
1272}
1273
1274static int loop_by_char(uint8_t ch)
1275{
1276 switch (ch) {
1277 case 'a':
1278 return GSM414_LOOP_A;
1279 case 'b':
1280 return GSM414_LOOP_B;
1281 case 'c':
1282 return GSM414_LOOP_C;
1283 case 'd':
1284 return GSM414_LOOP_D;
1285 case 'e':
1286 return GSM414_LOOP_E;
1287 case 'f':
1288 return GSM414_LOOP_F;
1289 case 'i':
1290 return GSM414_LOOP_I;
1291 }
1292 return -1;
1293}
1294
1295DEFUN(subscriber_mstest_close,
1296 subscriber_mstest_close_cmd,
1297 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1298 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1299 "Close a TCH Loop inside the MS\n"
1300 "Loop Type A\n"
1301 "Loop Type B\n"
1302 "Loop Type C\n"
1303 "Loop Type D\n"
1304 "Loop Type E\n"
1305 "Loop Type F\n"
1306 "Loop Type I\n")
1307{
Neels Hofmeyrc036b792018-11-29 22:37:51 +01001308 struct ran_conn *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001309 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1310 const char *loop_str;
1311 int loop_mode;
1312
1313 if (!vsub) {
1314 vty_out(vty, "%% No subscriber found for %s %s%s",
1315 argv[0], argv[1], VTY_NEWLINE);
1316 return CMD_WARNING;
1317 }
1318
1319 loop_str = argv[2];
1320 loop_mode = loop_by_char(loop_str[0]);
1321
1322 conn = connection_for_subscr(vsub);
1323 if (!conn) {
1324 vty_out(vty, "%% An active connection is required for %s %s%s",
1325 argv[0], argv[1], VTY_NEWLINE);
1326 vlr_subscr_put(vsub);
1327 return CMD_WARNING;
1328 }
1329
1330 gsm0414_tx_close_tch_loop_cmd(conn, loop_mode);
1331
1332 return CMD_SUCCESS;
1333}
1334
1335DEFUN(subscriber_mstest_open,
1336 subscriber_mstest_open_cmd,
1337 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1338 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1339 "Open a TCH Loop inside the MS\n")
1340{
Neels Hofmeyrc036b792018-11-29 22:37:51 +01001341 struct ran_conn *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001342 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1343
1344 if (!vsub) {
1345 vty_out(vty, "%% No subscriber found for %s %s%s",
1346 argv[0], argv[1], VTY_NEWLINE);
1347 return CMD_WARNING;
1348 }
1349
1350 conn = connection_for_subscr(vsub);
1351 if (!conn) {
1352 vty_out(vty, "%% An active connection is required for %s %s%s",
1353 argv[0], argv[1], VTY_NEWLINE);
1354 vlr_subscr_put(vsub);
1355 return CMD_WARNING;
1356 }
1357
1358 gsm0414_tx_open_loop_cmd(conn);
1359
1360 return CMD_SUCCESS;
1361}
1362
1363DEFUN(ena_subscr_expire,
1364 ena_subscr_expire_cmd,
1365 "subscriber " SUBSCR_TYPES " ID expire",
1366 SUBSCR_HELP "Expire the subscriber Now\n")
1367{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001368 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1369 argv[1]);
1370
1371 if (!vsub) {
1372 vty_out(vty, "%% No subscriber found for %s %s%s",
1373 argv[0], argv[1], VTY_NEWLINE);
1374 return CMD_WARNING;
1375 }
1376
1377 if (vlr_subscr_expire(vsub))
1378 vty_out(vty, "%% VLR released subscriber %s%s",
1379 vlr_subscr_name(vsub), VTY_NEWLINE);
1380
1381 if (vsub->use_count > 1)
1382 vty_out(vty, "%% Subscriber %s is still in use,"
1383 " should be released soon%s",
1384 vlr_subscr_name(vsub), VTY_NEWLINE);
1385
1386 vlr_subscr_put(vsub);
1387 return CMD_SUCCESS;
1388}
1389
1390static int scall_cbfn(unsigned int subsys, unsigned int signal,
1391 void *handler_data, void *signal_data)
1392{
1393 struct scall_signal_data *sigdata = signal_data;
1394 struct vty *vty = sigdata->data;
1395
1396 switch (signal) {
1397 case S_SCALL_SUCCESS:
1398 vty_out(vty, "%% silent call success%s", VTY_NEWLINE);
1399 break;
1400 case S_SCALL_EXPIRED:
1401 vty_out(vty, "%% silent call expired paging%s", VTY_NEWLINE);
1402 break;
1403 }
1404 return 0;
1405}
1406
1407DEFUN(show_stats,
1408 show_stats_cmd,
1409 "show statistics",
1410 SHOW_STR "Display network statistics\n")
1411{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001412 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001413 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1414 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1415 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001416 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001417 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001418 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001419 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001420 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001421 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1422 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001423 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001424 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001425 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1426 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001427 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001428 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001429 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1430 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1431 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001432 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001433 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001434 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1435 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001436 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001437 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001438 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1439 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001440 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001441 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001442 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current,
1443 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1444 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current
1445 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1446 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001447 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001448 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current,
1449 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1450 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current
1451 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1452 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001453 return CMD_SUCCESS;
1454}
1455
1456DEFUN(show_smsqueue,
1457 show_smsqueue_cmd,
1458 "show sms-queue",
1459 SHOW_STR "Display SMSqueue statistics\n")
1460{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001461 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001462 return CMD_SUCCESS;
1463}
1464
1465DEFUN(smsqueue_trigger,
1466 smsqueue_trigger_cmd,
1467 "sms-queue trigger",
1468 "SMS Queue\n" "Trigger sending messages\n")
1469{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001470 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001471 return CMD_SUCCESS;
1472}
1473
1474DEFUN(smsqueue_max,
1475 smsqueue_max_cmd,
1476 "sms-queue max-pending <1-500>",
1477 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1478{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001479 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001480 return CMD_SUCCESS;
1481}
1482
1483DEFUN(smsqueue_clear,
1484 smsqueue_clear_cmd,
1485 "sms-queue clear",
1486 "SMS Queue\n" "Clear the queue of pending SMS\n")
1487{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001488 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001489 return CMD_SUCCESS;
1490}
1491
1492DEFUN(smsqueue_fail,
1493 smsqueue_fail_cmd,
1494 "sms-queue max-failure <1-500>",
1495 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1496{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001497 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001498 return CMD_SUCCESS;
1499}
1500
1501
1502DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1503 "mncc-int", "Configure internal MNCC handler")
1504{
1505 vty->node = MNCC_INT_NODE;
1506
1507 return CMD_SUCCESS;
1508}
1509
1510static struct cmd_node mncc_int_node = {
1511 MNCC_INT_NODE,
1512 "%s(config-mncc-int)# ",
1513 1,
1514};
1515
1516static const struct value_string tchf_codec_names[] = {
1517 { GSM48_CMODE_SPEECH_V1, "fr" },
1518 { GSM48_CMODE_SPEECH_EFR, "efr" },
1519 { GSM48_CMODE_SPEECH_AMR, "amr" },
1520 { 0, NULL }
1521};
1522
1523static const struct value_string tchh_codec_names[] = {
1524 { GSM48_CMODE_SPEECH_V1, "hr" },
1525 { GSM48_CMODE_SPEECH_AMR, "amr" },
1526 { 0, NULL }
1527};
1528
1529static int config_write_mncc_int(struct vty *vty)
1530{
1531 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1532 vty_out(vty, " default-codec tch-f %s%s",
1533 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1534 VTY_NEWLINE);
1535 vty_out(vty, " default-codec tch-h %s%s",
1536 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1537 VTY_NEWLINE);
1538
1539 return CMD_SUCCESS;
1540}
1541
1542DEFUN(mnccint_def_codec_f,
1543 mnccint_def_codec_f_cmd,
1544 "default-codec tch-f (fr|efr|amr)",
1545 "Set default codec\n" "Codec for TCH/F\n"
1546 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1547{
1548 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1549
1550 return CMD_SUCCESS;
1551}
1552
1553DEFUN(mnccint_def_codec_h,
1554 mnccint_def_codec_h_cmd,
1555 "default-codec tch-h (hr|amr)",
1556 "Set default codec\n" "Codec for TCH/H\n"
1557 "Half-Rate\n" "Adaptive Multi-Rate\n")
1558{
1559 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1560
1561 return CMD_SUCCESS;
1562}
1563
1564
1565DEFUN(logging_fltr_imsi,
1566 logging_fltr_imsi_cmd,
1567 "logging filter imsi IMSI",
1568 LOGGING_STR FILTER_STR
1569 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1570{
1571 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001572 struct log_target *tgt = osmo_log_vty2tgt(vty);
1573 const char *imsi = argv[0];
1574
1575 if (!tgt)
1576 return CMD_WARNING;
1577
1578 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi);
1579
1580 if (!vlr_subscr) {
1581 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1582 argv[0], VTY_NEWLINE);
1583 return CMD_WARNING;
1584 }
1585
1586 log_set_filter_vlr_subscr(tgt, vlr_subscr);
1587 return CMD_SUCCESS;
1588}
1589
1590static struct cmd_node hlr_node = {
1591 HLR_NODE,
1592 "%s(config-hlr)# ",
1593 1,
1594};
1595
1596DEFUN(cfg_hlr, cfg_hlr_cmd,
1597 "hlr", "Configure connection to the HLR")
1598{
1599 vty->node = HLR_NODE;
1600 return CMD_SUCCESS;
1601}
1602
1603DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1604 "Remote GSUP address of the HLR\n"
1605 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1606{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001607 talloc_free((void*)gsmnet->gsup_server_addr_str);
1608 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1609 return CMD_SUCCESS;
1610}
1611
1612DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1613 "Remote GSUP port of the HLR\n"
1614 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1615{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001616 gsmnet->gsup_server_port = atoi(argv[0]);
1617 return CMD_SUCCESS;
1618}
1619
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001620DEFUN(cfg_hlr_ipa_name,
1621 cfg_hlr_ipa_name_cmd,
1622 "ipa-name NAME",
1623 "Set the IPA name of this MSC\n"
1624 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1625 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
1626 "The default is 'MSC-00-00-00-00-00-00'.\n")
1627{
1628 if (vty->type != VTY_FILE) {
1629 vty_out(vty, "The IPA name cannot be changed at run-time; "
1630 "It can only be set in the configuraton file.%s", VTY_NEWLINE);
1631 return CMD_WARNING;
1632 }
1633
1634 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
1635 return CMD_SUCCESS;
1636}
1637
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001638static int config_write_hlr(struct vty *vty)
1639{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001640 vty_out(vty, "hlr%s", VTY_NEWLINE);
1641 vty_out(vty, " remote-ip %s%s",
1642 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1643 vty_out(vty, " remote-port %u%s",
1644 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001645 if (gsmnet->msc_ipa_name)
1646 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001647 return CMD_SUCCESS;
1648}
1649
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001650void msc_vty_init(struct gsm_network *msc_network)
1651{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001652 OSMO_ASSERT(gsmnet == NULL);
1653 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001654
1655 osmo_stats_vty_add_cmds();
1656
1657 install_element(CONFIG_NODE, &cfg_net_cmd);
1658 install_node(&net_node, config_write_net);
1659 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1660 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1661 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1662 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1663 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
1664 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1665 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1666 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1667 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1668 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1669 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1670 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1671 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001672
1673 install_element(CONFIG_NODE, &cfg_msc_cmd);
1674 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001675 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01001676 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
1677 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02001678 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01001679 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07001680 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001681 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001682 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
1683 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01001684 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001685 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
1686 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01001687 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01001688 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07001689 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
1690 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001691
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02001692 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001693#ifdef BUILD_IU
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +01001694 ranap_iu_vty_init(MSC_NODE, &msc_network->iu.rab_assign_addr_enc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001695#endif
Harald Welte0df904d2018-12-03 11:00:04 +01001696 sgs_vty_init();
Stefan Sperling617ac802018-02-22 17:58:20 +01001697 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001698
1699 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
1700
1701 install_element_ve(&show_subscr_cmd);
1702 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01001703 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001704 install_element_ve(&show_msc_conn_cmd);
1705 install_element_ve(&show_msc_transaction_cmd);
1706
1707 install_element_ve(&sms_send_pend_cmd);
1708 install_element_ve(&sms_delete_expired_cmd);
1709
1710 install_element_ve(&subscriber_create_cmd);
1711 install_element_ve(&subscriber_send_sms_cmd);
1712 install_element_ve(&subscriber_silent_sms_cmd);
1713 install_element_ve(&subscriber_silent_call_start_cmd);
1714 install_element_ve(&subscriber_silent_call_stop_cmd);
1715 install_element_ve(&subscriber_ussd_notify_cmd);
1716 install_element_ve(&subscriber_mstest_close_cmd);
1717 install_element_ve(&subscriber_mstest_open_cmd);
1718 install_element_ve(&subscriber_paging_cmd);
1719 install_element_ve(&show_stats_cmd);
1720 install_element_ve(&show_smsqueue_cmd);
1721 install_element_ve(&logging_fltr_imsi_cmd);
1722
1723 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
1724 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
1725 install_element(ENABLE_NODE, &smsqueue_max_cmd);
1726 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
1727 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
1728 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001729 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001730
1731 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
1732 install_node(&mncc_int_node, config_write_mncc_int);
1733 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
1734 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
1735
1736 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
1737
1738 install_element(CONFIG_NODE, &cfg_hlr_cmd);
1739 install_node(&hlr_node, config_write_hlr);
1740 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
1741 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001742 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001743}