blob: c75cd0eed733e57fb579d9d8cf5839421b9198d7 [file] [log] [blame]
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001/* MSC interface to quagga VTY */
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002/* (C) 2016-2018 by sysmocom s.m.f.c. GmbH <info@sysmocom.de>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02003 * Based on OpenBSC interface to quagga VTY (libmsc/vty_interface_layer3.c)
Harald Welte7b222aa2017-12-23 19:30:32 +01004 * (C) 2009-2017 by Harald Welte <laforge@gnumonks.org>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02005 * (C) 2009-2011 by Holger Hans Peter Freyther
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23/* NOTE: I would have liked to call this the MSC_NODE instead of the MSC_NODE,
24 * but MSC_NODE already exists to configure a remote MSC for osmo-bsc. */
25
Neels Hofmeyr4ac80092019-03-04 02:46:37 +010026#include "config.h"
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020027
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020028#include <inttypes.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010029#include <limits.h>
30
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010031#include <osmocom/core/use_count.h>
32
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010033#include <osmocom/gsm/protocol/gsm_08_58.h>
34#include <osmocom/gsm/protocol/gsm_04_14.h>
Philipp Maier8fa2dbe2019-03-19 18:51:37 +010035#include <osmocom/gsm/protocol/gsm_08_08.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020036
Maxc51609a2018-11-09 17:13:00 +010037#include <osmocom/sigtran/sccp_helpers.h>
38
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020039#include <osmocom/vty/command.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010040#include <osmocom/vty/logging.h>
Stefan Sperling617ac802018-02-22 17:58:20 +010041#include <osmocom/vty/misc.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010042#include <osmocom/vty/stats.h>
43
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020044#ifdef BUILD_IU
45#include <osmocom/ranap/iu_client.h>
46#endif
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020047
Neels Hofmeyr90843962017-09-04 15:04:35 +020048#include <osmocom/msc/vty.h>
49#include <osmocom/msc/gsm_data.h>
50#include <osmocom/msc/gsm_subscriber.h>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010051#include <osmocom/msc/msub.h>
52#include <osmocom/msc/msc_a.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020053#include <osmocom/msc/vlr.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010054#include <osmocom/msc/transaction.h>
55#include <osmocom/msc/db.h>
56#include <osmocom/msc/sms_queue.h>
57#include <osmocom/msc/silent_call.h>
58#include <osmocom/msc/gsm_04_80.h>
59#include <osmocom/msc/gsm_04_14.h>
60#include <osmocom/msc/signal.h>
61#include <osmocom/msc/mncc_int.h>
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +020062#include <osmocom/msc/osmux.h>
Vadim Yanitskiy1b891302018-08-04 01:33:08 +070063#include <osmocom/msc/rrlp.h>
Harald Welte0df904d2018-12-03 11:00:04 +010064#include <osmocom/msc/vlr_sgs.h>
65#include <osmocom/msc/sgs_vty.h>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010066#include <osmocom/msc/sccp_ran.h>
67#include <osmocom/msc/ran_peer.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010068
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010069static struct gsm_network *gsmnet = NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010070
71struct cmd_node net_node = {
72 GSMNET_NODE,
73 "%s(config-net)# ",
74 1,
75};
76
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +010077#define VSUB_USE_VTY "VTY"
78
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010079#define NETWORK_STR "Configure the GSM network\n"
80#define CODE_CMD_STR "Code commands\n"
81#define NAME_CMD_STR "Name Commands\n"
82#define NAME_STR "Name to use\n"
83
84DEFUN(cfg_net,
85 cfg_net_cmd,
86 "network", NETWORK_STR)
87{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010088 vty->index = gsmnet;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010089 vty->node = GSMNET_NODE;
90
91 return CMD_SUCCESS;
92}
93
94DEFUN(cfg_net_ncc,
95 cfg_net_ncc_cmd,
96 "network country code <1-999>",
97 "Set the GSM network country code\n"
98 "Country commands\n"
99 CODE_CMD_STR
100 "Network Country Code to use\n")
101{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100102 gsmnet->plmn.mcc = atoi(argv[0]);
103
104 return CMD_SUCCESS;
105}
106
107DEFUN(cfg_net_mnc,
108 cfg_net_mnc_cmd,
109 "mobile network code <0-999>",
110 "Set the GSM mobile network code\n"
111 "Network Commands\n"
112 CODE_CMD_STR
113 "Mobile Network Code to use\n")
114{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100115 uint16_t mnc;
116 bool mnc_3_digits;
117
118 if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
119 vty_out(vty, "%% Error decoding MNC: %s%s", argv[0], VTY_NEWLINE);
120 return CMD_WARNING;
121 }
122
123 gsmnet->plmn.mnc = mnc;
124 gsmnet->plmn.mnc_3_digits = mnc_3_digits;
125
126 return CMD_SUCCESS;
127}
128
129DEFUN(cfg_net_name_short,
130 cfg_net_name_short_cmd,
131 "short name NAME",
132 "Set the short GSM network name\n" NAME_CMD_STR NAME_STR)
133{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100134 osmo_talloc_replace_string(gsmnet, &gsmnet->name_short, argv[0]);
135 return CMD_SUCCESS;
136}
137
138DEFUN(cfg_net_name_long,
139 cfg_net_name_long_cmd,
140 "long name NAME",
141 "Set the long GSM network name\n" NAME_CMD_STR NAME_STR)
142{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100143 osmo_talloc_replace_string(gsmnet, &gsmnet->name_long, argv[0]);
144 return CMD_SUCCESS;
145}
146
147DEFUN(cfg_net_encryption,
148 cfg_net_encryption_cmd,
149 "encryption a5 <0-3> [<0-3>] [<0-3>] [<0-3>]",
150 "Encryption options\n"
151 "GSM A5 Air Interface Encryption\n"
152 "A5/n Algorithm Number\n"
153 "A5/n Algorithm Number\n"
154 "A5/n Algorithm Number\n"
155 "A5/n Algorithm Number\n")
156{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100157 unsigned int i;
158
159 gsmnet->a5_encryption_mask = 0;
160 for (i = 0; i < argc; i++)
161 gsmnet->a5_encryption_mask |= (1 << atoi(argv[i]));
162
163 return CMD_SUCCESS;
164}
165
166DEFUN(cfg_net_authentication,
167 cfg_net_authentication_cmd,
168 "authentication (optional|required)",
169 "Whether to enforce MS authentication in 2G\n"
170 "Allow MS to attach via 2G BSC without authentication\n"
171 "Always do authentication\n")
172{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100173 gsmnet->authentication_required = (argv[0][0] == 'r') ? true : false;
174
175 return CMD_SUCCESS;
176}
177
178DEFUN(cfg_net_rrlp_mode, cfg_net_rrlp_mode_cmd,
179 "rrlp mode (none|ms-based|ms-preferred|ass-preferred)",
180 "Radio Resource Location Protocol\n"
181 "Set the Radio Resource Location Protocol Mode\n"
182 "Don't send RRLP request\n"
183 "Request MS-based location\n"
184 "Request any location, prefer MS-based\n"
185 "Request any location, prefer MS-assisted\n")
186{
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700187 gsmnet->rrlp.mode = msc_rrlp_mode_parse(argv[0]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100188
189 return CMD_SUCCESS;
190}
191
192DEFUN(cfg_net_mm_info, cfg_net_mm_info_cmd,
193 "mm info (0|1)",
194 "Mobility Management\n"
195 "Send MM INFO after LOC UPD ACCEPT\n"
196 "Disable\n" "Enable\n")
197{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100198 gsmnet->send_mm_info = atoi(argv[0]);
199
200 return CMD_SUCCESS;
201}
202
203DEFUN(cfg_net_timezone,
204 cfg_net_timezone_cmd,
205 "timezone <-19-19> (0|15|30|45)",
206 "Set the Timezone Offset of the network\n"
207 "Timezone offset (hours)\n"
208 "Timezone offset (00 minutes)\n"
209 "Timezone offset (15 minutes)\n"
210 "Timezone offset (30 minutes)\n"
211 "Timezone offset (45 minutes)\n"
212 )
213{
214 struct gsm_network *net = vty->index;
215 int tzhr = atoi(argv[0]);
216 int tzmn = atoi(argv[1]);
217
218 net->tz.hr = tzhr;
219 net->tz.mn = tzmn;
220 net->tz.dst = 0;
221 net->tz.override = 1;
222
223 return CMD_SUCCESS;
224}
225
226DEFUN(cfg_net_timezone_dst,
227 cfg_net_timezone_dst_cmd,
228 "timezone <-19-19> (0|15|30|45) <0-2>",
229 "Set the Timezone Offset of the network\n"
230 "Timezone offset (hours)\n"
231 "Timezone offset (00 minutes)\n"
232 "Timezone offset (15 minutes)\n"
233 "Timezone offset (30 minutes)\n"
234 "Timezone offset (45 minutes)\n"
235 "DST offset (hours)\n"
236 )
237{
238 struct gsm_network *net = vty->index;
239 int tzhr = atoi(argv[0]);
240 int tzmn = atoi(argv[1]);
241 int tzdst = atoi(argv[2]);
242
243 net->tz.hr = tzhr;
244 net->tz.mn = tzmn;
245 net->tz.dst = tzdst;
246 net->tz.override = 1;
247
248 return CMD_SUCCESS;
249}
250
251DEFUN(cfg_net_no_timezone,
252 cfg_net_no_timezone_cmd,
253 "no timezone",
254 NO_STR
255 "Disable network timezone override, use system tz\n")
256{
257 struct gsm_network *net = vty->index;
258
259 net->tz.override = 0;
260
261 return CMD_SUCCESS;
262}
263
264DEFUN(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
265 "periodic location update <6-1530>",
266 "Periodic Location Updating Interval\n"
267 "Periodic Location Updating Interval\n"
268 "Periodic Location Updating Interval\n"
269 "Periodic Location Updating Interval in Minutes\n")
270{
271 struct gsm_network *net = vty->index;
272
273 net->t3212 = atoi(argv[0]) / 6;
274
275 return CMD_SUCCESS;
276}
277
278DEFUN(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
279 "no periodic location update",
280 NO_STR
281 "Periodic Location Updating Interval\n"
282 "Periodic Location Updating Interval\n"
283 "Periodic Location Updating Interval\n")
284{
285 struct gsm_network *net = vty->index;
286
287 net->t3212 = 0;
288
289 return CMD_SUCCESS;
290}
291
292static int config_write_net(struct vty *vty)
293{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100294 int i;
295
296 vty_out(vty, "network%s", VTY_NEWLINE);
297 vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
298 vty_out(vty, " mobile network code %s%s",
299 osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
300 vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
301 vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
302 vty_out(vty, " encryption a5");
303 for (i = 0; i < 8; i++) {
304 if (gsmnet->a5_encryption_mask & (1 << i))
305 vty_out(vty, " %u", i);
306 }
307 vty_out(vty, "%s", VTY_NEWLINE);
308 vty_out(vty, " authentication %s%s",
309 gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE);
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700310 vty_out(vty, " rrlp mode %s%s", msc_rrlp_mode_name(gsmnet->rrlp.mode),
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100311 VTY_NEWLINE);
312 vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
313 if (gsmnet->tz.override != 0) {
314 if (gsmnet->tz.dst)
315 vty_out(vty, " timezone %d %d %d%s",
316 gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
317 VTY_NEWLINE);
318 else
319 vty_out(vty, " timezone %d %d%s",
320 gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
321 }
322 if (gsmnet->t3212 == 0)
323 vty_out(vty, " no periodic location update%s", VTY_NEWLINE);
324 else
325 vty_out(vty, " periodic location update %u%s",
326 gsmnet->t3212 * 6, VTY_NEWLINE);
327
328 if (gsmnet->emergency.route_to_msisdn) {
329 vty_out(vty, " emergency-call route-to-msisdn %s%s",
330 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
331 }
332
333 return CMD_SUCCESS;
334}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200335
336static struct cmd_node msc_node = {
337 MSC_NODE,
338 "%s(config-msc)# ",
339 1,
340};
341
342DEFUN(cfg_msc, cfg_msc_cmd,
343 "msc", "Configure MSC options")
344{
345 vty->node = MSC_NODE;
346 return CMD_SUCCESS;
347}
348
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100349#define MNCC_STR "Configure Mobile Network Call Control\n"
350#define MNCC_GUARD_TIMEOUT_STR "Set global guard timer for mncc interface activity\n"
351#define MNCC_GUARD_TIMEOUT_VALUE_STR "guard timer value (sec.)\n"
352
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100353DEFUN(cfg_msc_mncc_internal,
354 cfg_msc_mncc_internal_cmd,
355 "mncc internal",
356 MNCC_STR "Use internal MNCC handler (default; changes need a program restart)\n")
357{
358 gsm_network_set_mncc_sock_path(gsmnet, NULL);
359 return CMD_SUCCESS;
360}
361
362DEFUN(cfg_msc_mncc_external,
363 cfg_msc_mncc_external_cmd,
364 "mncc external MNCC_SOCKET_PATH",
365 MNCC_STR "Use external MNCC handler (changes need a program restart)\n"
366 "File system path to create the MNCC unix domain socket at\n")
367{
368 gsm_network_set_mncc_sock_path(gsmnet, argv[0]);
369 return CMD_SUCCESS;
370}
371
Philipp Maier9ca7b312018-10-10 17:00:49 +0200372DEFUN(cfg_msc_mncc_guard_timeout,
373 cfg_msc_mncc_guard_timeout_cmd,
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100374 "mncc guard-timeout <0-255>",
375 MNCC_STR
376 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR)
Philipp Maier9ca7b312018-10-10 17:00:49 +0200377{
378 gsmnet->mncc_guard_timeout = atoi(argv[0]);
379 return CMD_SUCCESS;
380}
381
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100382ALIAS_DEPRECATED(cfg_msc_mncc_guard_timeout,
383 cfg_msc_deprecated_mncc_guard_timeout_cmd,
384 "mncc-guard-timeout <0-255>",
385 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR);
386
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700387#define NCSS_STR "Configure call independent Supplementary Services\n"
388
389DEFUN(cfg_msc_ncss_guard_timeout,
390 cfg_msc_ncss_guard_timeout_cmd,
391 "ncss guard-timeout <0-255>",
392 NCSS_STR "Set guard timer for session activity\n"
393 "guard timer value (sec.), or 0 to disable\n")
394{
395 gsmnet->ncss_guard_timeout = atoi(argv[0]);
396 return CMD_SUCCESS;
397}
398
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200399DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
400 "assign-tmsi",
401 "Assign TMSI during Location Updating.\n")
402{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200403 gsmnet->vlr->cfg.assign_tmsi = true;
404 return CMD_SUCCESS;
405}
406
407DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
408 "no assign-tmsi",
409 NO_STR "Assign TMSI during Location Updating.\n")
410{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200411 gsmnet->vlr->cfg.assign_tmsi = false;
412 return CMD_SUCCESS;
413}
414
Philipp Maierfbf66102017-04-09 12:32:51 +0200415DEFUN(cfg_msc_cs7_instance_a,
416 cfg_msc_cs7_instance_a_cmd,
417 "cs7-instance-a <0-15>",
418 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
419{
Philipp Maierfbf66102017-04-09 12:32:51 +0200420 gsmnet->a.cs7_instance = atoi(argv[0]);
421 return CMD_SUCCESS;
422}
423
424DEFUN(cfg_msc_cs7_instance_iu,
425 cfg_msc_cs7_instance_iu_cmd,
426 "cs7-instance-iu <0-15>",
427 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
428{
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100429#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200430 gsmnet->iu.cs7_instance = atoi(argv[0]);
431 return CMD_SUCCESS;
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100432#else
433 vty_out(vty, "WARNING: 'cs7-instance-iu' without effect: built without Iu support%s",
434 VTY_NEWLINE);
435 return CMD_WARNING;
436#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200437}
438
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100439DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
440 "auth-tuple-max-reuse-count <-1-2147483647>",
441 "Configure authentication tuple re-use\n"
442 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
443{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100444 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
445 return CMD_SUCCESS;
446}
447
448DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
449 "auth-tuple-reuse-on-error (0|1)",
450 "Configure authentication tuple re-use when HLR is not responsive\n"
Oliver Smithd6e24fd2019-01-09 10:46:43 +0100451 "Never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
452 "If the HLR does not deliver new tuples, do re-use already available old ones.\n")
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100453{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100454 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
455 return CMD_SUCCESS;
456}
457
Oliver Smith0fec28a2018-12-14 10:52:52 +0100458DEFUN(cfg_msc_check_imei_rqd, cfg_msc_check_imei_rqd_cmd,
Oliver Smith03ded912019-05-02 10:40:50 +0200459 "check-imei-rqd (0|1|early)",
Oliver Smith0fec28a2018-12-14 10:52:52 +0100460 "Send each IMEI to the EIR to ask if it is permitted or not. The EIR is implemented as part of OsmoHLR, "
461 "and can optionally save the IMEI in the HLR.\n"
462 "Do not send IMEIs to the EIR\n"
Oliver Smith03ded912019-05-02 10:40:50 +0200463 "Send each IMEI to the EIR\n"
464 "Send each IMEI to the EIR, and do it at the start of the location update. This allows the EIR to receive the"
465 " IMEI, even if the MS would get rejected when the MSC sends the location update request to the HLR.\n")
Oliver Smith0fec28a2018-12-14 10:52:52 +0100466{
Oliver Smith03ded912019-05-02 10:40:50 +0200467 if (strcmp(argv[0], "0") == 0) {
468 gsmnet->vlr->cfg.check_imei_rqd = false;
469 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
470 } else if (strcmp(argv[0], "1") == 0) {
471 gsmnet->vlr->cfg.check_imei_rqd = true;
472 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
473 } else if (strcmp(argv[0], "early") == 0) {
474 gsmnet->vlr->cfg.check_imei_rqd = true;
475 gsmnet->vlr->cfg.retrieve_imeisv_early = true;
476 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100477 return CMD_SUCCESS;
478}
479
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100480DEFUN(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
481 "paging response-timer (default|<1-65535>)",
482 "Configure Paging\n"
483 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
484 " BSS or RNC\n"
485 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
486 "Set paging timeout in seconds\n")
487{
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100488 if (!strcmp(argv[1], "default"))
489 gsmnet->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
490 else
491 gsmnet->paging_response_timer = atoi(argv[0]);
492 return CMD_SUCCESS;
493}
494
Harald Welte69c54a82018-02-09 20:41:14 +0100495DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
496 "emergency-call route-to-msisdn MSISDN",
497 "Configure Emergency Call Behaviour\n"
498 "MSISDN to which Emergency Calls are Dispatched\n"
499 "MSISDN (E.164 Phone Number)\n")
500{
Harald Welte69c54a82018-02-09 20:41:14 +0100501 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
502
503 return CMD_SUCCESS;
504}
505
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700506/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
507DEFUN(cfg_msc_sms_over_gsup, cfg_msc_sms_over_gsup_cmd,
508 "sms-over-gsup",
509 "Enable routing of SMS messages over GSUP\n")
510{
511 gsmnet->sms_over_gsup = true;
512 return CMD_SUCCESS;
513}
514
515/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
516DEFUN(cfg_msc_no_sms_over_gsup, cfg_msc_no_sms_over_gsup_cmd,
517 "no sms-over-gsup",
518 NO_STR "Disable routing of SMS messages over GSUP\n")
519{
520 gsmnet->sms_over_gsup = false;
521 return CMD_SUCCESS;
522}
523
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100524/* FIXME: This should rather be in the form of
525 * handover-number range 001234xxx
526 * and
527 * handover-number range 001234xxx FIRST LAST
528 */
529DEFUN(cfg_msc_handover_number_range, cfg_msc_handover_number_range_cmd,
530 "handover-number range MSISDN_FIRST MSISDN_LAST",
531 "Configure a range of MSISDN to be assigned to incoming inter-MSC Handovers for call forwarding.\n"
532 "Configure a handover number range\n"
533 "First Handover Number MSISDN\n"
534 "Last Handover Number MSISDN\n")
535{
536 char *endp;
537 uint64_t range_start;
538 uint64_t range_end;
539
540 /* FIXME leading zeros?? */
541
542 errno = 0;
543 range_start = strtoull(argv[0], &endp, 10);
544 if (errno || *endp != '\0') {
545 vty_out(vty, "%% Error parsing handover-number range start: %s%s",
546 argv[0], VTY_NEWLINE);
547 return CMD_WARNING;
548 }
549
550 errno = 0;
551 range_end = strtoull(argv[1], &endp, 10);
552 if (errno || *endp != '\0') {
553 vty_out(vty, "%% Error parsing handover-number range end: %s%s",
554 argv[1], VTY_NEWLINE);
555 return CMD_WARNING;
556 }
557
558 if (range_start > range_end) {
559 vty_out(vty, "%% Error: handover-number range end must be > than the range start, but"
560 " %"PRIu64" > %"PRIu64"%s", range_start, range_end, VTY_NEWLINE);
561 return CMD_WARNING;
562 }
563
564 gsmnet->handover_number.range_start = range_start;
565 gsmnet->handover_number.range_end = range_end;
566 return CMD_SUCCESS;
567}
568
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200569#define OSMUX_STR "RTP multiplexing\n"
570DEFUN(cfg_msc_osmux,
571 cfg_msc_osmux_cmd,
572 "osmux (on|off|only)",
573 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
574{
575 if (strcmp(argv[0], "off") == 0)
576 gsmnet->use_osmux = OSMUX_USAGE_OFF;
577 else if (strcmp(argv[0], "on") == 0)
578 gsmnet->use_osmux = OSMUX_USAGE_ON;
579 else if (strcmp(argv[0], "only") == 0)
580 gsmnet->use_osmux = OSMUX_USAGE_ONLY;
581
582 return CMD_SUCCESS;
583}
584
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200585static int config_write_msc(struct vty *vty)
586{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200587 vty_out(vty, "msc%s", VTY_NEWLINE);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100588 if (gsmnet->mncc_sock_path)
589 vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE);
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100590 vty_out(vty, " mncc guard-timeout %i%s",
Philipp Maier9ca7b312018-10-10 17:00:49 +0200591 gsmnet->mncc_guard_timeout, VTY_NEWLINE);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700592 vty_out(vty, " ncss guard-timeout %i%s",
593 gsmnet->ncss_guard_timeout, VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200594 vty_out(vty, " %sassign-tmsi%s",
595 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
596
Philipp Maierfbf66102017-04-09 12:32:51 +0200597 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
598 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100599#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200600 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
601 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100602#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200603
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100604 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
605 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
606 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
607 VTY_NEWLINE);
608 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
609 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
610 VTY_NEWLINE);
611
Oliver Smith03ded912019-05-02 10:40:50 +0200612 if (gsmnet->vlr->cfg.check_imei_rqd) {
613 if (gsmnet->vlr->cfg.retrieve_imeisv_early)
614 vty_out(vty, " check-imei-rqd early%s", VTY_NEWLINE);
615 else
616 vty_out(vty, " check-imei-rqd 1%s", VTY_NEWLINE);
617 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100618
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100619 if (gsmnet->paging_response_timer != MSC_PAGING_RESPONSE_TIMER_DEFAULT)
620 vty_out(vty, " paging response-timer %u%s", gsmnet->paging_response_timer, VTY_NEWLINE);
621
Harald Welte69c54a82018-02-09 20:41:14 +0100622 if (gsmnet->emergency.route_to_msisdn) {
623 vty_out(vty, " emergency-call route-to-msisdn %s%s",
624 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
625 }
626
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700627 if (gsmnet->sms_over_gsup)
628 vty_out(vty, " sms-over-gsup%s", VTY_NEWLINE);
629
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100630 if (gsmnet->handover_number.range_start || gsmnet->handover_number.range_end)
631 vty_out(vty, " handover-number range %"PRIu64" %"PRIu64"%s",
632 gsmnet->handover_number.range_start, gsmnet->handover_number.range_end,
633 VTY_NEWLINE);
634
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200635 if (gsmnet->use_osmux != OSMUX_USAGE_OFF) {
636 vty_out(vty, " osmux %s%s", gsmnet->use_osmux == OSMUX_USAGE_ON ? "on" : "only",
637 VTY_NEWLINE);
638 }
639
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200640 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200641#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200642 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200643#endif
644
Neels Hofmeyr880b9502019-05-09 02:01:55 +0200645 neighbor_ident_vty_write(vty);
646
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200647 return CMD_SUCCESS;
648}
649
Maxc51609a2018-11-09 17:13:00 +0100650DEFUN(show_bsc, show_bsc_cmd,
651 "show bsc", SHOW_STR "BSC\n")
652{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100653 struct ran_peer *rp;
654 llist_for_each_entry(rp, &gsmnet->a.sri->ran_peers, entry) {
655 vty_out(vty, "BSC %s %s%s",
656 osmo_sccp_inst_addr_name(gsmnet->a.sri->sccp, &rp->peer_addr),
657 osmo_fsm_inst_state_name(rp->fi),
658 VTY_NEWLINE);
Maxc51609a2018-11-09 17:13:00 +0100659 }
660
661 return CMD_SUCCESS;
662}
663
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100664static const char *get_trans_proto_str(const struct gsm_trans *trans)
665{
666 static char buf[256];
667
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100668 switch (trans->type) {
669 case TRANS_CC:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100670 snprintf(buf, sizeof(buf), "%s %4u %4u",
671 gsm48_cc_state_name(trans->cc.state),
672 trans->cc.Tcurrent,
673 trans->cc.T308_second);
674 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100675 case TRANS_SMS:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700676 snprintf(buf, sizeof(buf), "CP:%s RP:%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100677 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
678 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
679 break;
680 default:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700681 return NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100682 }
683
684 return buf;
685}
686
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700687/* Prefix a given format string with a given amount of spaces */
688#define MSC_VTY_DUMP(vty, offset, fmt, args...) \
689 vty_out(vty, "%*s" fmt, offset, "", ##args)
690
691#define MSC_VTY_DUMP_FLAG(vty, offset, name, flag) \
692 MSC_VTY_DUMP(vty, offset + 2, "%s: %*s%s%s", \
693 name, 30 - (int)strlen(name), "", \
694 flag ? "true" : "false", \
695 VTY_NEWLINE)
696
697enum msc_vty_dump_flags {
698 MSC_VTY_DUMP_F_SUBSCR = (1 << 0),
699 MSC_VTY_DUMP_F_CONNECTION = (1 << 1),
700 MSC_VTY_DUMP_F_TRANSACTION = (1 << 2),
701};
702
703static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans,
704 int offset, uint8_t dump_flags)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100705{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700706 const char *proto_str;
707
708 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
709 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
710 vlr_subscr_name(msc_a_vsub(trans->msc_a)),
711 VTY_NEWLINE);
712 }
713
714 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
715 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
716 trans->msc_a ? msub_ran_conn_name(trans->msc_a->c.msub)
717 : "(not established)",
718 VTY_NEWLINE);
719 }
720
721 MSC_VTY_DUMP(vty, offset, "Unique (global) identifier: 0x%08x%s",
722 trans->callref, VTY_NEWLINE);
723 MSC_VTY_DUMP(vty, offset, "GSM 04.07 identifier (%s): %u%s",
724 (trans->transaction_id & 0x08) ? "MO" : "MT",
725 trans->transaction_id,
726 VTY_NEWLINE);
727
728 MSC_VTY_DUMP(vty, offset, "Type: %s%s",
729 trans_type_name(trans->type),
730 VTY_NEWLINE);
731
732 if ((proto_str = get_trans_proto_str(trans))) {
733 MSC_VTY_DUMP(vty, offset, "Protocol specific: %s%s",
734 proto_str, VTY_NEWLINE);
735 }
736}
737
738static void vty_dump_one_conn(struct vty *vty, const struct msub *msub,
739 int offset, uint8_t dump_flags)
740{
741 struct vlr_subscr *vsub = msub_vsub(msub);
742 struct msc_a *msc_a = msub_msc_a(msub);
743 char buf[128];
744
745 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
746 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
747 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
748 vlr_subscr_name(vsub),
749 VTY_NEWLINE);
750 }
751
752 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
753 msub_ran_conn_name(msub),
754 VTY_NEWLINE);
755 MSC_VTY_DUMP(vty, offset, "RAN connection state: %s%s",
756 osmo_fsm_inst_state_name(msc_a->c.fi),
757 VTY_NEWLINE);
758
759 if (vsub) {
760 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
761 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
762 VTY_NEWLINE);
763 }
764
765 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
766 osmo_use_count_total(&msc_a->use_count),
767 VTY_NEWLINE);
768 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
769 osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count),
770 VTY_NEWLINE);
771
772 /* Transactions of this connection */
773 if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
774 struct gsm_trans *trans;
775 unsigned int i = 0;
776
777 /* Both subscriber and connection info is already printed */
778 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_CONNECTION;
779 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
780
781 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
782 if (trans->msc_a != msc_a)
783 continue;
784 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
785 i++, VTY_NEWLINE);
786 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
787 }
788 }
789}
790
791static void vty_dump_one_subscr(struct vty *vty, struct vlr_subscr *vsub,
792 int offset, uint8_t dump_flags)
793{
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700794 struct gsm_network *net;
795 struct timespec now;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700796 char buf[128];
797
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700798 if (vsub->name[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700799 MSC_VTY_DUMP(vty, offset, "Name: '%s'%s",
800 vsub->name, VTY_NEWLINE);
801 }
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700802 if (vsub->msisdn[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700803 MSC_VTY_DUMP(vty, offset, "MSISDN: %s%s",
804 vsub->msisdn, VTY_NEWLINE);
805 }
806
807 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
808 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
809 VTY_NEWLINE);
810 MSC_VTY_DUMP(vty, offset, "RAN type: %s%s",
811 osmo_rat_type_name(vsub->cs.attached_via_ran),
812 VTY_NEWLINE);
813
814 MSC_VTY_DUMP(vty, offset, "IMSI: %s%s",
815 vsub->imsi, VTY_NEWLINE);
816 if (vsub->tmsi != GSM_RESERVED_TMSI) {
817 MSC_VTY_DUMP(vty, offset, "TMSI: %08X%s",
818 vsub->tmsi, VTY_NEWLINE);
819 }
820 if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
821 MSC_VTY_DUMP(vty, offset, "New TMSI: %08X%s",
822 vsub->tmsi_new, VTY_NEWLINE);
823 }
824 if (vsub->imei[0] != '\0') {
825 MSC_VTY_DUMP(vty, offset, "IMEI: %s%s",
826 vsub->imei, VTY_NEWLINE);
827 }
828 if (vsub->imeisv[0] != '\0') {
829 MSC_VTY_DUMP(vty, offset, "IMEISV: %s%s",
830 vsub->imeisv, VTY_NEWLINE);
831 }
832
833 MSC_VTY_DUMP(vty, offset, "Flags: %s", VTY_NEWLINE);
834 MSC_VTY_DUMP_FLAG(vty, offset, "IMSI detached",
835 vsub->imsi_detached_flag);
836 MSC_VTY_DUMP_FLAG(vty, offset, "Conf. by radio contact",
837 vsub->conf_by_radio_contact_ind);
838 MSC_VTY_DUMP_FLAG(vty, offset, "Subscr. data conf. by HLR",
839 vsub->sub_dataconf_by_hlr_ind);
840 MSC_VTY_DUMP_FLAG(vty, offset, "Location conf. in HLR",
841 vsub->loc_conf_in_hlr_ind);
842 MSC_VTY_DUMP_FLAG(vty, offset, "Subscriber dormant",
843 vsub->dormant_ind);
844 MSC_VTY_DUMP_FLAG(vty, offset, "Received cancel location",
845 vsub->cancel_loc_rx);
846 MSC_VTY_DUMP_FLAG(vty, offset, "MS not reachable",
847 vsub->ms_not_reachable_flag);
848 MSC_VTY_DUMP_FLAG(vty, offset, "LA allowed",
849 vsub->la_allowed);
850
851 if (vsub->last_tuple) {
852 struct vlr_auth_tuple *t = vsub->last_tuple;
853 MSC_VTY_DUMP(vty, offset, "A3A8 last tuple (used %d times): %s",
854 t->use_count, VTY_NEWLINE);
855 MSC_VTY_DUMP(vty, offset + 2, "seq # : %d%s",
856 t->key_seq, VTY_NEWLINE);
857 MSC_VTY_DUMP(vty, offset + 2, "RAND : %s%s",
858 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
859 VTY_NEWLINE);
860 MSC_VTY_DUMP(vty, offset + 2, "SRES : %s%s",
861 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
862 VTY_NEWLINE);
863 MSC_VTY_DUMP(vty, offset + 2, "Kc : %s%s",
864 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
865 VTY_NEWLINE);
866 }
867
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700868 /* XXX move t3212 into struct vlr_instance? */
869 net = vsub->vlr->user_ctx;
870 if (!net->t3212) {
871 MSC_VTY_DUMP(vty, offset, "Expires: never (T3212 is disabled)%s",
872 VTY_NEWLINE);
873 } else if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) {
874 MSC_VTY_DUMP(vty, offset, "Expires: never%s",
875 VTY_NEWLINE);
876 } else if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
877 MSC_VTY_DUMP(vty, offset, "Expires: in %ld min %ld sec%s",
878 (vsub->expire_lu - now.tv_sec) / 60,
879 (vsub->expire_lu - now.tv_sec) % 60,
880 VTY_NEWLINE);
881 }
882
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700883 MSC_VTY_DUMP(vty, offset, "Paging: %s paging for %d requests%s",
884 vsub->cs.is_paging ? "is" : "not",
885 llist_count(&vsub->cs.requests),
886 VTY_NEWLINE);
887
888 /* SGs related */
889 MSC_VTY_DUMP(vty, offset, "SGs-state: %s%s",
890 osmo_fsm_inst_state_name(vsub->sgs_fsm),
891 VTY_NEWLINE);
892 MSC_VTY_DUMP(vty, offset, "SGs-MME: %s%s",
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700893 vsub->sgs.mme_name[0] != '\0' ? vsub->sgs.mme_name : "(none)",
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700894 VTY_NEWLINE);
895
896 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
897 osmo_use_count_total(&vsub->use_count),
898 VTY_NEWLINE);
899 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
900 osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count),
901 VTY_NEWLINE);
902
903 /* Connection(s) and/or transactions of this subscriber */
904 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
905 struct msub *msub = msub_for_vsub(vsub);
906 if (!msub)
907 return;
908
909 /* Subscriber info is already printed */
910 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
911
912 MSC_VTY_DUMP(vty, offset, "Connection: %s", VTY_NEWLINE);
913 vty_dump_one_conn(vty, msub, offset + 2, dump_flags);
914 } else if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
915 struct gsm_trans *trans;
916 unsigned int i = 0;
917
918 /* Subscriber info is already printed */
919 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
920 /* Do not print connection info, but mention it */
921 dump_flags |= MSC_VTY_DUMP_F_CONNECTION;
922
923 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
924 if (trans->vsub != vsub)
925 continue;
926 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
927 i++, VTY_NEWLINE);
928 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
929 }
930 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100931}
932
933DEFUN(show_msc_transaction, show_msc_transaction_cmd,
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700934 "show transaction",
935 SHOW_STR "Transactions\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100936{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100937 struct gsm_trans *trans;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700938 uint8_t flags = 0x00;
939 unsigned int i = 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100940
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700941 flags |= MSC_VTY_DUMP_F_CONNECTION;
942 flags |= MSC_VTY_DUMP_F_SUBSCR;
943
944 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
945 vty_out(vty, " Transaction #%02u: %s", i++, VTY_NEWLINE);
946 vty_dump_one_trans(vty, trans, 4, flags);
947 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100948
949 return CMD_SUCCESS;
950}
951
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700952DEFUN(show_msc_conn, show_msc_conn_cmd,
953 "show connection [trans]",
954 SHOW_STR "Subscriber Connections\n"
955 "Show child transactions of each connection\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100956{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700957 uint8_t flags = 0x00;
958 unsigned int i = 0;
959 struct msub *msub;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100960
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700961 if (argc > 0)
962 flags |= MSC_VTY_DUMP_F_TRANSACTION;
963 flags |= MSC_VTY_DUMP_F_SUBSCR;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100964
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700965 llist_for_each_entry(msub, &msub_list, entry) {
966 vty_out(vty, " Connection #%02u: %s", i++, VTY_NEWLINE);
967 vty_dump_one_conn(vty, msub, 4, flags);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100968 }
969
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700970 return CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100971}
972
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700973#define SUBSCR_FLAGS "[(conn|trans|conn+trans)]"
974#define SUBSCR_FLAGS_HELP \
975 "Show child connections\n" \
976 "Show child transactions\n" \
977 "Show child connections and transactions\n"
978
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100979/* Subscriber */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700980DEFUN(show_subscr_cache, show_subscr_cache_cmd,
981 "show subscriber cache " SUBSCR_FLAGS,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100982 SHOW_STR "Show information about subscribers\n"
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700983 "Display contents of subscriber cache\n"
984 SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100985{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100986 struct vlr_subscr *vsub;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700987 unsigned int count = 0;
988 uint8_t flags = 0x00;
989 unsigned int i = 0;
990
991 if (argc && strcmp(argv[0], "conn") == 0)
992 flags |= MSC_VTY_DUMP_F_CONNECTION;
993 else if (argc && strcmp(argv[0], "trans") == 0)
994 flags |= MSC_VTY_DUMP_F_TRANSACTION;
995 else if (argc && strcmp(argv[0], "conn+trans") == 0)
996 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100997
998 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
999 if (++count > 100) {
1000 vty_out(vty, "%% More than %d subscribers in cache,"
1001 " stopping here.%s", count-1, VTY_NEWLINE);
1002 break;
1003 }
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001004 vty_out(vty, " Subscriber #%02u: %s", i++, VTY_NEWLINE);
1005 vty_dump_one_subscr(vty, vsub, 4, flags);
Harald Welte69c54a82018-02-09 20:41:14 +01001006 }
1007
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001008 return CMD_SUCCESS;
1009}
1010
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001011DEFUN(sms_send_pend,
1012 sms_send_pend_cmd,
1013 "sms send pending",
1014 "SMS related commands\n" "SMS Sending related commands\n"
1015 "Send all pending SMS")
1016{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001017 struct gsm_sms *sms;
1018 unsigned long long sms_id = 0;
1019
1020 while (1) {
1021 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1022 if (!sms)
1023 break;
1024
1025 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001026 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001027
1028 sms_id = sms->id + 1;
1029 }
1030
1031 return CMD_SUCCESS;
1032}
1033
1034DEFUN(sms_delete_expired,
1035 sms_delete_expired_cmd,
1036 "sms delete expired",
1037 "SMS related commands\n" "SMS Database related commands\n"
1038 "Delete all expired SMS")
1039{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001040 struct gsm_sms *sms;
1041 unsigned long long sms_id = 0;
1042 long long num_deleted = 0;
1043
1044 while (1) {
1045 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1046 if (!sms)
1047 break;
1048
1049 /* Skip SMS which are currently queued for sending. */
1050 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
1051 continue;
1052
1053 /* Expiration check is performed by the DB layer. */
1054 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
1055 num_deleted++;
1056
1057 sms_id = sms->id + 1;
1058 }
1059
1060 if (num_deleted == 0) {
1061 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
1062 return CMD_WARNING;
1063 }
1064
1065 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
1066 return CMD_SUCCESS;
1067}
1068
1069static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +02001070 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001071 char *str, uint8_t tp_pid)
1072{
1073 struct gsm_network *net = receiver->vlr->user_ctx;
1074 struct gsm_sms *sms;
1075
Harald Welte39b55482018-04-09 19:19:33 +02001076 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001077 sms->protocol_id = tp_pid;
1078
1079 /* store in database for the queue */
1080 if (db_sms_store(sms) != 0) {
1081 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
1082 sms_free(sms);
1083 return CMD_WARNING;
1084 }
1085 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
1086
1087 sms_free(sms);
1088 sms_queue_trigger(net->sms_queue);
1089 return CMD_SUCCESS;
1090}
1091
1092static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
1093 const char *type,
1094 const char *id)
1095{
1096 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001097 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001098 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001099 return vlr_subscr_find_by_imsi(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001100 else if (!strcmp(type, "tmsi"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001101 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id), VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001102
1103 return NULL;
1104}
1105#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
1106#define SUBSCR_HELP "Operations on a Subscriber\n" \
1107 "Identify subscriber by MSISDN (phone number)\n" \
1108 "Legacy alias for 'msisdn'\n" \
1109 "Identify subscriber by IMSI\n" \
1110 "Identify subscriber by TMSI\n" \
Vadim Yanitskiy3ccd8232019-05-16 01:35:23 +07001111 "Legacy alias for 'imsi'\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001112 "Identifier for the subscriber\n"
1113
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001114DEFUN(show_subscr, show_subscr_cmd,
1115 "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
1116 SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001117{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001118 struct vlr_subscr *vsub;
1119 uint8_t flags = 0x00;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001120
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001121 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001122 if (!vsub) {
1123 vty_out(vty, "%% No subscriber found for %s %s%s",
1124 argv[0], argv[1], VTY_NEWLINE);
1125 return CMD_WARNING;
1126 }
1127
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001128 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
1129 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
1130 * this, and since this is not multi-threaded, this vlr_subscr_put() cannot possibly reach a count of 0. */
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001131 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001132
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001133 if (argc > 2 && strcmp(argv[2], "conn") == 0)
1134 flags |= MSC_VTY_DUMP_F_CONNECTION;
1135 else if (argc > 2 && strcmp(argv[2], "trans") == 0)
1136 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1137 else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
1138 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
1139
1140 vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
1141 vty_dump_one_subscr(vty, vsub, 4, flags);
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001142
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001143 return CMD_SUCCESS;
1144}
1145
1146DEFUN(subscriber_create,
1147 subscriber_create_cmd,
1148 "subscriber create imsi ID",
1149 "Operations on a Subscriber\n" \
1150 "Create new subscriber\n" \
1151 "Identify the subscriber by his IMSI\n" \
1152 "Identifier for the subscriber\n")
1153{
1154 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
1155 VTY_NEWLINE);
1156 return CMD_WARNING;
1157}
1158
1159DEFUN(subscriber_send_pending_sms,
1160 subscriber_send_pending_sms_cmd,
1161 "subscriber " SUBSCR_TYPES " ID sms pending-send",
1162 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
1163{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001164 struct vlr_subscr *vsub;
1165 struct gsm_sms *sms;
1166
1167 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1168 if (!vsub) {
1169 vty_out(vty, "%% No subscriber found for %s %s%s",
1170 argv[0], argv[1], VTY_NEWLINE);
1171 return CMD_WARNING;
1172 }
1173
1174 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
1175 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001176 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001177
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001178 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001179
1180 return CMD_SUCCESS;
1181}
1182
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001183DEFUN(subscriber_sms_delete_all,
1184 subscriber_sms_delete_all_cmd,
1185 "subscriber " SUBSCR_TYPES " ID sms delete-all",
1186 SUBSCR_HELP "SMS Operations\n"
1187 "Delete all SMS to be delivered to this subscriber"
1188 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
1189 " WILL BE LOST.\n")
1190{
1191 struct vlr_subscr *vsub;
1192
1193 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1194 if (!vsub) {
1195 vty_out(vty, "%% No subscriber found for %s %s%s",
1196 argv[0], argv[1], VTY_NEWLINE);
1197 return CMD_WARNING;
1198 }
1199
1200 db_sms_delete_by_msisdn(vsub->msisdn);
1201
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001202 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001203
1204 return CMD_SUCCESS;
1205}
1206
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001207DEFUN(subscriber_send_sms,
1208 subscriber_send_sms_cmd,
1209 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1210 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1211{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001212 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001213 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001214 char *str;
1215 int rc;
1216
1217 if (!vsub) {
1218 vty_out(vty, "%% No subscriber found for %s %s%s",
1219 argv[0], argv[1], VTY_NEWLINE);
1220 rc = CMD_WARNING;
1221 goto err;
1222 }
1223
Harald Welte39b55482018-04-09 19:19:33 +02001224 if (!strcmp(argv[2], "msisdn"))
1225 sender_msisdn = argv[3];
1226 else {
1227 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1228 if (!sender) {
1229 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1230 rc = CMD_WARNING;
1231 goto err;
1232 }
1233 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001234 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001235 }
1236
1237 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001238 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001239 talloc_free(str);
1240
1241err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001242 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001243 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001244
1245 return rc;
1246}
1247
1248DEFUN(subscriber_silent_sms,
1249 subscriber_silent_sms_cmd,
1250
1251 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1252 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1253{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001254 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001255 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001256 char *str;
1257 int rc;
1258
1259 if (!vsub) {
1260 vty_out(vty, "%% No subscriber found for %s %s%s",
1261 argv[0], argv[1], VTY_NEWLINE);
1262 rc = CMD_WARNING;
1263 goto err;
1264 }
1265
Harald Welte39b55482018-04-09 19:19:33 +02001266 if (!strcmp(argv[2], "msisdn")) {
1267 sender_msisdn = argv[3];
1268 } else {
1269 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1270 if (!sender) {
1271 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1272 rc = CMD_WARNING;
1273 goto err;
1274 }
1275 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001276 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001277 }
1278
1279 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001280 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001281 talloc_free(str);
1282
1283err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001284 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001285 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001286
1287 return rc;
1288}
1289
Sylvain Munaut93558302019-02-14 20:13:08 +01001290#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001291#define CHAN_TYPE_HELP \
1292 "Any channel\n" \
1293 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001294 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001295 "Any TCH channel\n" \
1296 "SDCCH channel\n"
1297
Sylvain Munaut93558302019-02-14 20:13:08 +01001298#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1299#define CHAN_MODE_HELP \
1300 "Signalling only\n" \
1301 "Speech with HR codec\n" \
1302 "Speech with FR codec\n" \
1303 "Speech with EFR codec\n" \
1304 "Speech with AMR codec\n"
1305
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001306DEFUN(subscriber_silent_call_start,
1307 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001308 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001309 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001310 CHAN_TYPE_HELP CHAN_MODE_HELP
1311 "Target IP for RTP traffic (default 127.0.0.1)\n"
1312 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001313{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001314 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001315 struct gsm0808_channel_type ct;
1316 const char *ip;
1317 uint16_t port;
1318 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001319
1320 if (!vsub) {
1321 vty_out(vty, "%% No subscriber found for %s %s%s",
1322 argv[0], argv[1], VTY_NEWLINE);
1323 return CMD_WARNING;
1324 }
1325
Sylvain Munaut93558302019-02-14 20:13:08 +01001326 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001327
Sylvain Munaut93558302019-02-14 20:13:08 +01001328 if (!strcmp(argv[3], "signalling")) {
1329 ct.ch_indctr = GSM0808_CHAN_SIGN;
1330 ct.perm_spch[0] = 0; /* Spare but required */
1331 ct.perm_spch_len = 1;
1332 } else if (!strcmp(argv[3], "speech-hr")) {
1333 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1334 ct.perm_spch[0] = GSM0808_PERM_HR1;
1335 ct.perm_spch_len = 1;
1336 } else if (!strcmp(argv[3], "speech-fr")) {
1337 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1338 ct.perm_spch[0] = GSM0808_PERM_FR1;
1339 ct.perm_spch_len = 1;
1340 } else if (!strcmp(argv[3], "speech-efr")) {
1341 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1342 ct.perm_spch[0] = GSM0808_PERM_FR2;
1343 ct.perm_spch_len = 1;
1344 } else if (!strcmp(argv[3], "speech-amr")) {
1345 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1346 ct.perm_spch[0] = GSM0808_PERM_FR3;
1347 ct.perm_spch[1] = GSM0808_PERM_HR3;
1348 ct.perm_spch_len = 2;
1349 }
1350
1351 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1352
1353 if (!strcmp(argv[2], "tch/f"))
1354 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1355 else if (!strcmp(argv[2], "tch/h"))
1356 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1357 else if (!strcmp(argv[2], "tch/any"))
1358 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1359 else if (!strcmp(argv[2], "sdcch")) {
1360 if (speech) {
1361 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1362 return CMD_WARNING;
1363 }
1364 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1365 } else
1366 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1367
1368 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1369 port = argc >= 6 ? atoi(argv[5]) : 4000;
1370
1371 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001372 switch (rc) {
1373 case -ENODEV:
1374 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1375 break;
1376 default:
1377 if (rc)
1378 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1379 else
1380 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1381 break;
1382 }
1383
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001384 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001385 return rc ? CMD_WARNING : CMD_SUCCESS;
1386}
1387
1388DEFUN(subscriber_silent_call_stop,
1389 subscriber_silent_call_stop_cmd,
1390 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1391 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1392 CHAN_TYPE_HELP)
1393{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001394 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1395 int rc;
1396
1397 if (!vsub) {
1398 vty_out(vty, "%% No subscriber found for %s %s%s",
1399 argv[0], argv[1], VTY_NEWLINE);
1400 return CMD_WARNING;
1401 }
1402
1403 rc = gsm_silent_call_stop(vsub);
1404 switch (rc) {
1405 case -ENODEV:
1406 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1407 break;
1408 case -ENOENT:
1409 vty_out(vty, "%% Subscriber has no silent call active%s",
1410 VTY_NEWLINE);
1411 break;
1412 default:
1413 if (rc)
1414 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1415 else
1416 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1417 break;
1418 }
1419
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001420 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001421 return rc ? CMD_WARNING : CMD_SUCCESS;
1422}
1423
1424DEFUN(subscriber_ussd_notify,
1425 subscriber_ussd_notify_cmd,
1426 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1427 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1428 "Alerting Level 0\n"
1429 "Alerting Level 1\n"
1430 "Alerting Level 2\n"
1431 "Text of USSD message to send\n")
1432{
1433 char *text;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001434 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001435 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1436 int level;
1437
1438 if (!vsub) {
1439 vty_out(vty, "%% No subscriber found for %s %s%s",
1440 argv[0], argv[1], VTY_NEWLINE);
1441 return CMD_WARNING;
1442 }
1443
1444 level = atoi(argv[2]);
1445 text = argv_concat(argv, argc, 3);
1446 if (!text) {
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001447 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001448 return CMD_WARNING;
1449 }
1450
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001451 msc_a = msc_a_for_vsub(vsub, true);
1452 if (!msc_a || msc_a->c.remote_to) {
1453 vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001454 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001455 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001456 talloc_free(text);
1457 return CMD_WARNING;
1458 }
1459
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001460 msc_send_ussd_notify(msc_a, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001461 /* FIXME: since we don't allocate a transaction here,
1462 * we use dummy GSM 04.07 transaction ID. */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001463 msc_send_ussd_release_complete(msc_a, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001464
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001465 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001466 talloc_free(text);
1467 return CMD_SUCCESS;
1468}
1469
1470DEFUN(subscriber_paging,
1471 subscriber_paging_cmd,
1472 "subscriber " SUBSCR_TYPES " ID paging",
1473 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1474{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001475 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001476 struct paging_request *req;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001477
1478 if (!vsub) {
1479 vty_out(vty, "%% No subscriber found for %s %s%s",
1480 argv[0], argv[1], VTY_NEWLINE);
1481 return CMD_WARNING;
1482 }
1483
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001484 req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL,
1485 NULL, NULL, "manual Paging from VTY");
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001486 if (req)
1487 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1488 else
1489 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1490
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001491 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001492 return req ? CMD_SUCCESS : CMD_WARNING;
1493}
1494
1495static int loop_by_char(uint8_t ch)
1496{
1497 switch (ch) {
1498 case 'a':
1499 return GSM414_LOOP_A;
1500 case 'b':
1501 return GSM414_LOOP_B;
1502 case 'c':
1503 return GSM414_LOOP_C;
1504 case 'd':
1505 return GSM414_LOOP_D;
1506 case 'e':
1507 return GSM414_LOOP_E;
1508 case 'f':
1509 return GSM414_LOOP_F;
1510 case 'i':
1511 return GSM414_LOOP_I;
1512 }
1513 return -1;
1514}
1515
1516DEFUN(subscriber_mstest_close,
1517 subscriber_mstest_close_cmd,
1518 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1519 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1520 "Close a TCH Loop inside the MS\n"
1521 "Loop Type A\n"
1522 "Loop Type B\n"
1523 "Loop Type C\n"
1524 "Loop Type D\n"
1525 "Loop Type E\n"
1526 "Loop Type F\n"
1527 "Loop Type I\n")
1528{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001529 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001530 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1531 const char *loop_str;
1532 int loop_mode;
1533
1534 if (!vsub) {
1535 vty_out(vty, "%% No subscriber found for %s %s%s",
1536 argv[0], argv[1], VTY_NEWLINE);
1537 return CMD_WARNING;
1538 }
1539
1540 loop_str = argv[2];
1541 loop_mode = loop_by_char(loop_str[0]);
1542
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001543 msc_a = msc_a_for_vsub(vsub, true);
1544 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001545 vty_out(vty, "%% An active connection is required for %s %s%s",
1546 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001547 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001548 return CMD_WARNING;
1549 }
1550
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001551 gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001552
1553 return CMD_SUCCESS;
1554}
1555
1556DEFUN(subscriber_mstest_open,
1557 subscriber_mstest_open_cmd,
1558 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1559 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1560 "Open a TCH Loop inside the MS\n")
1561{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001562 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001563 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1564
1565 if (!vsub) {
1566 vty_out(vty, "%% No subscriber found for %s %s%s",
1567 argv[0], argv[1], VTY_NEWLINE);
1568 return CMD_WARNING;
1569 }
1570
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001571 msc_a = msc_a_for_vsub(vsub, true);
1572 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001573 vty_out(vty, "%% An active connection is required for %s %s%s",
1574 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001575 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001576 return CMD_WARNING;
1577 }
1578
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001579 gsm0414_tx_open_loop_cmd(msc_a);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001580
1581 return CMD_SUCCESS;
1582}
1583
1584DEFUN(ena_subscr_expire,
1585 ena_subscr_expire_cmd,
1586 "subscriber " SUBSCR_TYPES " ID expire",
1587 SUBSCR_HELP "Expire the subscriber Now\n")
1588{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001589 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1590 argv[1]);
1591
1592 if (!vsub) {
1593 vty_out(vty, "%% No subscriber found for %s %s%s",
1594 argv[0], argv[1], VTY_NEWLINE);
1595 return CMD_WARNING;
1596 }
1597
1598 if (vlr_subscr_expire(vsub))
1599 vty_out(vty, "%% VLR released subscriber %s%s",
1600 vlr_subscr_name(vsub), VTY_NEWLINE);
1601
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001602 if (osmo_use_count_total(&vsub->use_count) > 1)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001603 vty_out(vty, "%% Subscriber %s is still in use,"
1604 " should be released soon%s",
1605 vlr_subscr_name(vsub), VTY_NEWLINE);
1606
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001607 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001608 return CMD_SUCCESS;
1609}
1610
1611static int scall_cbfn(unsigned int subsys, unsigned int signal,
1612 void *handler_data, void *signal_data)
1613{
1614 struct scall_signal_data *sigdata = signal_data;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001615 struct vty *vty = sigdata->vty;
1616
1617 if (!vty_is_active(vty))
1618 return 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001619
1620 switch (signal) {
1621 case S_SCALL_SUCCESS:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001622 vty_out(vty, "%% Silent call success%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001623 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001624 case S_SCALL_FAILED:
1625 vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE);
1626 break;
1627 case S_SCALL_DETACHED:
1628 vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001629 break;
1630 }
1631 return 0;
1632}
1633
1634DEFUN(show_stats,
1635 show_stats_cmd,
1636 "show statistics",
1637 SHOW_STR "Display network statistics\n")
1638{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001639 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001640 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1641 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1642 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001643 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001644 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001645 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001646 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001647 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001648 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1649 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001650 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001651 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001652 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1653 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001654 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001655 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001656 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1657 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1658 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001659 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001660 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001661 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1662 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001663 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001664 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001665 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1666 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001667 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001668 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001669 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current,
1670 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1671 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current
1672 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1673 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001674 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001675 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current,
1676 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1677 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current
1678 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1679 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001680 return CMD_SUCCESS;
1681}
1682
1683DEFUN(show_smsqueue,
1684 show_smsqueue_cmd,
1685 "show sms-queue",
1686 SHOW_STR "Display SMSqueue statistics\n")
1687{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001688 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001689 return CMD_SUCCESS;
1690}
1691
1692DEFUN(smsqueue_trigger,
1693 smsqueue_trigger_cmd,
1694 "sms-queue trigger",
1695 "SMS Queue\n" "Trigger sending messages\n")
1696{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001697 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001698 return CMD_SUCCESS;
1699}
1700
1701DEFUN(smsqueue_max,
1702 smsqueue_max_cmd,
1703 "sms-queue max-pending <1-500>",
1704 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1705{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001706 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001707 return CMD_SUCCESS;
1708}
1709
1710DEFUN(smsqueue_clear,
1711 smsqueue_clear_cmd,
1712 "sms-queue clear",
1713 "SMS Queue\n" "Clear the queue of pending SMS\n")
1714{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001715 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001716 return CMD_SUCCESS;
1717}
1718
1719DEFUN(smsqueue_fail,
1720 smsqueue_fail_cmd,
1721 "sms-queue max-failure <1-500>",
1722 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1723{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001724 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001725 return CMD_SUCCESS;
1726}
1727
1728
1729DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1730 "mncc-int", "Configure internal MNCC handler")
1731{
1732 vty->node = MNCC_INT_NODE;
1733
1734 return CMD_SUCCESS;
1735}
1736
1737static struct cmd_node mncc_int_node = {
1738 MNCC_INT_NODE,
1739 "%s(config-mncc-int)# ",
1740 1,
1741};
1742
1743static const struct value_string tchf_codec_names[] = {
1744 { GSM48_CMODE_SPEECH_V1, "fr" },
1745 { GSM48_CMODE_SPEECH_EFR, "efr" },
1746 { GSM48_CMODE_SPEECH_AMR, "amr" },
1747 { 0, NULL }
1748};
1749
1750static const struct value_string tchh_codec_names[] = {
1751 { GSM48_CMODE_SPEECH_V1, "hr" },
1752 { GSM48_CMODE_SPEECH_AMR, "amr" },
1753 { 0, NULL }
1754};
1755
1756static int config_write_mncc_int(struct vty *vty)
1757{
1758 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1759 vty_out(vty, " default-codec tch-f %s%s",
1760 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1761 VTY_NEWLINE);
1762 vty_out(vty, " default-codec tch-h %s%s",
1763 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1764 VTY_NEWLINE);
1765
1766 return CMD_SUCCESS;
1767}
1768
1769DEFUN(mnccint_def_codec_f,
1770 mnccint_def_codec_f_cmd,
1771 "default-codec tch-f (fr|efr|amr)",
1772 "Set default codec\n" "Codec for TCH/F\n"
1773 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1774{
1775 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1776
1777 return CMD_SUCCESS;
1778}
1779
1780DEFUN(mnccint_def_codec_h,
1781 mnccint_def_codec_h_cmd,
1782 "default-codec tch-h (hr|amr)",
1783 "Set default codec\n" "Codec for TCH/H\n"
1784 "Half-Rate\n" "Adaptive Multi-Rate\n")
1785{
1786 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1787
1788 return CMD_SUCCESS;
1789}
1790
1791
1792DEFUN(logging_fltr_imsi,
1793 logging_fltr_imsi_cmd,
1794 "logging filter imsi IMSI",
1795 LOGGING_STR FILTER_STR
1796 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1797{
1798 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001799 struct log_target *tgt = osmo_log_vty2tgt(vty);
1800 const char *imsi = argv[0];
1801
1802 if (!tgt)
1803 return CMD_WARNING;
1804
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001805 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001806
1807 if (!vlr_subscr) {
1808 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1809 argv[0], VTY_NEWLINE);
1810 return CMD_WARNING;
1811 }
1812
1813 log_set_filter_vlr_subscr(tgt, vlr_subscr);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001814 vlr_subscr_put(vlr_subscr, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001815 return CMD_SUCCESS;
1816}
1817
1818static struct cmd_node hlr_node = {
1819 HLR_NODE,
1820 "%s(config-hlr)# ",
1821 1,
1822};
1823
1824DEFUN(cfg_hlr, cfg_hlr_cmd,
1825 "hlr", "Configure connection to the HLR")
1826{
1827 vty->node = HLR_NODE;
1828 return CMD_SUCCESS;
1829}
1830
1831DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1832 "Remote GSUP address of the HLR\n"
1833 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1834{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001835 talloc_free((void*)gsmnet->gsup_server_addr_str);
1836 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1837 return CMD_SUCCESS;
1838}
1839
1840DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1841 "Remote GSUP port of the HLR\n"
1842 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1843{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001844 gsmnet->gsup_server_port = atoi(argv[0]);
1845 return CMD_SUCCESS;
1846}
1847
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001848DEFUN(cfg_hlr_ipa_name,
1849 cfg_hlr_ipa_name_cmd,
1850 "ipa-name NAME",
1851 "Set the IPA name of this MSC\n"
1852 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1853 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
1854 "The default is 'MSC-00-00-00-00-00-00'.\n")
1855{
1856 if (vty->type != VTY_FILE) {
1857 vty_out(vty, "The IPA name cannot be changed at run-time; "
1858 "It can only be set in the configuraton file.%s", VTY_NEWLINE);
1859 return CMD_WARNING;
1860 }
1861
1862 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
1863 return CMD_SUCCESS;
1864}
1865
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001866static int config_write_hlr(struct vty *vty)
1867{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001868 vty_out(vty, "hlr%s", VTY_NEWLINE);
1869 vty_out(vty, " remote-ip %s%s",
1870 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1871 vty_out(vty, " remote-port %u%s",
1872 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001873 if (gsmnet->msc_ipa_name)
1874 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001875 return CMD_SUCCESS;
1876}
1877
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001878void msc_vty_init(struct gsm_network *msc_network)
1879{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001880 OSMO_ASSERT(gsmnet == NULL);
1881 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001882
1883 osmo_stats_vty_add_cmds();
1884
1885 install_element(CONFIG_NODE, &cfg_net_cmd);
1886 install_node(&net_node, config_write_net);
1887 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1888 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1889 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1890 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1891 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
1892 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1893 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1894 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1895 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1896 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1897 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1898 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1899 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001900
1901 install_element(CONFIG_NODE, &cfg_msc_cmd);
1902 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001903 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01001904 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
1905 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02001906 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01001907 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07001908 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001909 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001910 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
1911 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01001912 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001913 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
1914 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01001915 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01001916 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07001917 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
1918 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +02001919 install_element(MSC_NODE, &cfg_msc_osmux_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001920 install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd);
1921
1922 neighbor_ident_vty_init(msc_network);
Philipp Maierfbf66102017-04-09 12:32:51 +02001923
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02001924 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001925#ifdef BUILD_IU
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001926 ranap_iu_vty_init(MSC_NODE, (enum ranap_nsap_addr_enc*)&msc_network->iu.rab_assign_addr_enc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001927#endif
Harald Welte0df904d2018-12-03 11:00:04 +01001928 sgs_vty_init();
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001929
Stefan Sperling617ac802018-02-22 17:58:20 +01001930 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001931
1932 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
1933
1934 install_element_ve(&show_subscr_cmd);
1935 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01001936 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001937 install_element_ve(&show_msc_conn_cmd);
1938 install_element_ve(&show_msc_transaction_cmd);
1939
1940 install_element_ve(&sms_send_pend_cmd);
1941 install_element_ve(&sms_delete_expired_cmd);
1942
1943 install_element_ve(&subscriber_create_cmd);
1944 install_element_ve(&subscriber_send_sms_cmd);
1945 install_element_ve(&subscriber_silent_sms_cmd);
1946 install_element_ve(&subscriber_silent_call_start_cmd);
1947 install_element_ve(&subscriber_silent_call_stop_cmd);
1948 install_element_ve(&subscriber_ussd_notify_cmd);
1949 install_element_ve(&subscriber_mstest_close_cmd);
1950 install_element_ve(&subscriber_mstest_open_cmd);
1951 install_element_ve(&subscriber_paging_cmd);
1952 install_element_ve(&show_stats_cmd);
1953 install_element_ve(&show_smsqueue_cmd);
1954 install_element_ve(&logging_fltr_imsi_cmd);
1955
1956 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
1957 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
1958 install_element(ENABLE_NODE, &smsqueue_max_cmd);
1959 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
1960 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
1961 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001962 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001963
1964 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
1965 install_node(&mncc_int_node, config_write_mncc_int);
1966 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
1967 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
1968
1969 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
1970
1971 install_element(CONFIG_NODE, &cfg_hlr_cmd);
1972 install_node(&hlr_node, config_write_hlr);
1973 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
1974 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001975 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001976}