blob: 8a976cb435633f5b521d5864fa261afc916f4da6 [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{
794 char buf[128];
795
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700796 if (vsub->name[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700797 MSC_VTY_DUMP(vty, offset, "Name: '%s'%s",
798 vsub->name, VTY_NEWLINE);
799 }
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700800 if (vsub->msisdn[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700801 MSC_VTY_DUMP(vty, offset, "MSISDN: %s%s",
802 vsub->msisdn, VTY_NEWLINE);
803 }
804
805 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
806 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
807 VTY_NEWLINE);
808 MSC_VTY_DUMP(vty, offset, "RAN type: %s%s",
809 osmo_rat_type_name(vsub->cs.attached_via_ran),
810 VTY_NEWLINE);
811
812 MSC_VTY_DUMP(vty, offset, "IMSI: %s%s",
813 vsub->imsi, VTY_NEWLINE);
814 if (vsub->tmsi != GSM_RESERVED_TMSI) {
815 MSC_VTY_DUMP(vty, offset, "TMSI: %08X%s",
816 vsub->tmsi, VTY_NEWLINE);
817 }
818 if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
819 MSC_VTY_DUMP(vty, offset, "New TMSI: %08X%s",
820 vsub->tmsi_new, VTY_NEWLINE);
821 }
822 if (vsub->imei[0] != '\0') {
823 MSC_VTY_DUMP(vty, offset, "IMEI: %s%s",
824 vsub->imei, VTY_NEWLINE);
825 }
826 if (vsub->imeisv[0] != '\0') {
827 MSC_VTY_DUMP(vty, offset, "IMEISV: %s%s",
828 vsub->imeisv, VTY_NEWLINE);
829 }
830
831 MSC_VTY_DUMP(vty, offset, "Flags: %s", VTY_NEWLINE);
832 MSC_VTY_DUMP_FLAG(vty, offset, "IMSI detached",
833 vsub->imsi_detached_flag);
834 MSC_VTY_DUMP_FLAG(vty, offset, "Conf. by radio contact",
835 vsub->conf_by_radio_contact_ind);
836 MSC_VTY_DUMP_FLAG(vty, offset, "Subscr. data conf. by HLR",
837 vsub->sub_dataconf_by_hlr_ind);
838 MSC_VTY_DUMP_FLAG(vty, offset, "Location conf. in HLR",
839 vsub->loc_conf_in_hlr_ind);
840 MSC_VTY_DUMP_FLAG(vty, offset, "Subscriber dormant",
841 vsub->dormant_ind);
842 MSC_VTY_DUMP_FLAG(vty, offset, "Received cancel location",
843 vsub->cancel_loc_rx);
844 MSC_VTY_DUMP_FLAG(vty, offset, "MS not reachable",
845 vsub->ms_not_reachable_flag);
846 MSC_VTY_DUMP_FLAG(vty, offset, "LA allowed",
847 vsub->la_allowed);
848
849 if (vsub->last_tuple) {
850 struct vlr_auth_tuple *t = vsub->last_tuple;
851 MSC_VTY_DUMP(vty, offset, "A3A8 last tuple (used %d times): %s",
852 t->use_count, VTY_NEWLINE);
853 MSC_VTY_DUMP(vty, offset + 2, "seq # : %d%s",
854 t->key_seq, VTY_NEWLINE);
855 MSC_VTY_DUMP(vty, offset + 2, "RAND : %s%s",
856 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
857 VTY_NEWLINE);
858 MSC_VTY_DUMP(vty, offset + 2, "SRES : %s%s",
859 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
860 VTY_NEWLINE);
861 MSC_VTY_DUMP(vty, offset + 2, "Kc : %s%s",
862 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
863 VTY_NEWLINE);
864 }
865
866 MSC_VTY_DUMP(vty, offset, "Paging: %s paging for %d requests%s",
867 vsub->cs.is_paging ? "is" : "not",
868 llist_count(&vsub->cs.requests),
869 VTY_NEWLINE);
870
871 /* SGs related */
872 MSC_VTY_DUMP(vty, offset, "SGs-state: %s%s",
873 osmo_fsm_inst_state_name(vsub->sgs_fsm),
874 VTY_NEWLINE);
875 MSC_VTY_DUMP(vty, offset, "SGs-MME: %s%s",
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700876 vsub->sgs.mme_name[0] != '\0' ? vsub->sgs.mme_name : "(none)",
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700877 VTY_NEWLINE);
878
879 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
880 osmo_use_count_total(&vsub->use_count),
881 VTY_NEWLINE);
882 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
883 osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count),
884 VTY_NEWLINE);
885
886 /* Connection(s) and/or transactions of this subscriber */
887 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
888 struct msub *msub = msub_for_vsub(vsub);
889 if (!msub)
890 return;
891
892 /* Subscriber info is already printed */
893 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
894
895 MSC_VTY_DUMP(vty, offset, "Connection: %s", VTY_NEWLINE);
896 vty_dump_one_conn(vty, msub, offset + 2, dump_flags);
897 } else if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
898 struct gsm_trans *trans;
899 unsigned int i = 0;
900
901 /* Subscriber info is already printed */
902 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
903 /* Do not print connection info, but mention it */
904 dump_flags |= MSC_VTY_DUMP_F_CONNECTION;
905
906 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
907 if (trans->vsub != vsub)
908 continue;
909 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
910 i++, VTY_NEWLINE);
911 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
912 }
913 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100914}
915
916DEFUN(show_msc_transaction, show_msc_transaction_cmd,
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700917 "show transaction",
918 SHOW_STR "Transactions\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100919{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100920 struct gsm_trans *trans;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700921 uint8_t flags = 0x00;
922 unsigned int i = 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100923
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700924 flags |= MSC_VTY_DUMP_F_CONNECTION;
925 flags |= MSC_VTY_DUMP_F_SUBSCR;
926
927 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
928 vty_out(vty, " Transaction #%02u: %s", i++, VTY_NEWLINE);
929 vty_dump_one_trans(vty, trans, 4, flags);
930 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100931
932 return CMD_SUCCESS;
933}
934
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700935DEFUN(show_msc_conn, show_msc_conn_cmd,
936 "show connection [trans]",
937 SHOW_STR "Subscriber Connections\n"
938 "Show child transactions of each connection\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100939{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700940 uint8_t flags = 0x00;
941 unsigned int i = 0;
942 struct msub *msub;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100943
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700944 if (argc > 0)
945 flags |= MSC_VTY_DUMP_F_TRANSACTION;
946 flags |= MSC_VTY_DUMP_F_SUBSCR;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100947
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700948 llist_for_each_entry(msub, &msub_list, entry) {
949 vty_out(vty, " Connection #%02u: %s", i++, VTY_NEWLINE);
950 vty_dump_one_conn(vty, msub, 4, flags);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100951 }
952
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700953 return CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100954}
955
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700956#define SUBSCR_FLAGS "[(conn|trans|conn+trans)]"
957#define SUBSCR_FLAGS_HELP \
958 "Show child connections\n" \
959 "Show child transactions\n" \
960 "Show child connections and transactions\n"
961
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100962/* Subscriber */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700963DEFUN(show_subscr_cache, show_subscr_cache_cmd,
964 "show subscriber cache " SUBSCR_FLAGS,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100965 SHOW_STR "Show information about subscribers\n"
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700966 "Display contents of subscriber cache\n"
967 SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100968{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100969 struct vlr_subscr *vsub;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700970 unsigned int count = 0;
971 uint8_t flags = 0x00;
972 unsigned int i = 0;
973
974 if (argc && strcmp(argv[0], "conn") == 0)
975 flags |= MSC_VTY_DUMP_F_CONNECTION;
976 else if (argc && strcmp(argv[0], "trans") == 0)
977 flags |= MSC_VTY_DUMP_F_TRANSACTION;
978 else if (argc && strcmp(argv[0], "conn+trans") == 0)
979 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100980
981 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
982 if (++count > 100) {
983 vty_out(vty, "%% More than %d subscribers in cache,"
984 " stopping here.%s", count-1, VTY_NEWLINE);
985 break;
986 }
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700987 vty_out(vty, " Subscriber #%02u: %s", i++, VTY_NEWLINE);
988 vty_dump_one_subscr(vty, vsub, 4, flags);
Harald Welte69c54a82018-02-09 20:41:14 +0100989 }
990
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200991 return CMD_SUCCESS;
992}
993
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100994DEFUN(sms_send_pend,
995 sms_send_pend_cmd,
996 "sms send pending",
997 "SMS related commands\n" "SMS Sending related commands\n"
998 "Send all pending SMS")
999{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001000 struct gsm_sms *sms;
1001 unsigned long long sms_id = 0;
1002
1003 while (1) {
1004 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1005 if (!sms)
1006 break;
1007
1008 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001009 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001010
1011 sms_id = sms->id + 1;
1012 }
1013
1014 return CMD_SUCCESS;
1015}
1016
1017DEFUN(sms_delete_expired,
1018 sms_delete_expired_cmd,
1019 "sms delete expired",
1020 "SMS related commands\n" "SMS Database related commands\n"
1021 "Delete all expired SMS")
1022{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001023 struct gsm_sms *sms;
1024 unsigned long long sms_id = 0;
1025 long long num_deleted = 0;
1026
1027 while (1) {
1028 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1029 if (!sms)
1030 break;
1031
1032 /* Skip SMS which are currently queued for sending. */
1033 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
1034 continue;
1035
1036 /* Expiration check is performed by the DB layer. */
1037 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
1038 num_deleted++;
1039
1040 sms_id = sms->id + 1;
1041 }
1042
1043 if (num_deleted == 0) {
1044 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
1045 return CMD_WARNING;
1046 }
1047
1048 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
1049 return CMD_SUCCESS;
1050}
1051
1052static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +02001053 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001054 char *str, uint8_t tp_pid)
1055{
1056 struct gsm_network *net = receiver->vlr->user_ctx;
1057 struct gsm_sms *sms;
1058
Harald Welte39b55482018-04-09 19:19:33 +02001059 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001060 sms->protocol_id = tp_pid;
1061
1062 /* store in database for the queue */
1063 if (db_sms_store(sms) != 0) {
1064 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
1065 sms_free(sms);
1066 return CMD_WARNING;
1067 }
1068 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
1069
1070 sms_free(sms);
1071 sms_queue_trigger(net->sms_queue);
1072 return CMD_SUCCESS;
1073}
1074
1075static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
1076 const char *type,
1077 const char *id)
1078{
1079 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001080 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001081 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001082 return vlr_subscr_find_by_imsi(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001083 else if (!strcmp(type, "tmsi"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001084 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id), VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001085
1086 return NULL;
1087}
1088#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
1089#define SUBSCR_HELP "Operations on a Subscriber\n" \
1090 "Identify subscriber by MSISDN (phone number)\n" \
1091 "Legacy alias for 'msisdn'\n" \
1092 "Identify subscriber by IMSI\n" \
1093 "Identify subscriber by TMSI\n" \
Vadim Yanitskiy3ccd8232019-05-16 01:35:23 +07001094 "Legacy alias for 'imsi'\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001095 "Identifier for the subscriber\n"
1096
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001097DEFUN(show_subscr, show_subscr_cmd,
1098 "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
1099 SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001100{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001101 struct vlr_subscr *vsub;
1102 uint8_t flags = 0x00;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001103
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001104 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001105 if (!vsub) {
1106 vty_out(vty, "%% No subscriber found for %s %s%s",
1107 argv[0], argv[1], VTY_NEWLINE);
1108 return CMD_WARNING;
1109 }
1110
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001111 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
1112 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
1113 * 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 +01001114 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001115
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001116 if (argc > 2 && strcmp(argv[2], "conn") == 0)
1117 flags |= MSC_VTY_DUMP_F_CONNECTION;
1118 else if (argc > 2 && strcmp(argv[2], "trans") == 0)
1119 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1120 else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
1121 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
1122
1123 vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
1124 vty_dump_one_subscr(vty, vsub, 4, flags);
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001125
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001126 return CMD_SUCCESS;
1127}
1128
1129DEFUN(subscriber_create,
1130 subscriber_create_cmd,
1131 "subscriber create imsi ID",
1132 "Operations on a Subscriber\n" \
1133 "Create new subscriber\n" \
1134 "Identify the subscriber by his IMSI\n" \
1135 "Identifier for the subscriber\n")
1136{
1137 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
1138 VTY_NEWLINE);
1139 return CMD_WARNING;
1140}
1141
1142DEFUN(subscriber_send_pending_sms,
1143 subscriber_send_pending_sms_cmd,
1144 "subscriber " SUBSCR_TYPES " ID sms pending-send",
1145 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
1146{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001147 struct vlr_subscr *vsub;
1148 struct gsm_sms *sms;
1149
1150 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1151 if (!vsub) {
1152 vty_out(vty, "%% No subscriber found for %s %s%s",
1153 argv[0], argv[1], VTY_NEWLINE);
1154 return CMD_WARNING;
1155 }
1156
1157 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
1158 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001159 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001160
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001161 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001162
1163 return CMD_SUCCESS;
1164}
1165
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001166DEFUN(subscriber_sms_delete_all,
1167 subscriber_sms_delete_all_cmd,
1168 "subscriber " SUBSCR_TYPES " ID sms delete-all",
1169 SUBSCR_HELP "SMS Operations\n"
1170 "Delete all SMS to be delivered to this subscriber"
1171 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
1172 " WILL BE LOST.\n")
1173{
1174 struct vlr_subscr *vsub;
1175
1176 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
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 db_sms_delete_by_msisdn(vsub->msisdn);
1184
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001185 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001186
1187 return CMD_SUCCESS;
1188}
1189
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001190DEFUN(subscriber_send_sms,
1191 subscriber_send_sms_cmd,
1192 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1193 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1194{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001195 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001196 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001197 char *str;
1198 int rc;
1199
1200 if (!vsub) {
1201 vty_out(vty, "%% No subscriber found for %s %s%s",
1202 argv[0], argv[1], VTY_NEWLINE);
1203 rc = CMD_WARNING;
1204 goto err;
1205 }
1206
Harald Welte39b55482018-04-09 19:19:33 +02001207 if (!strcmp(argv[2], "msisdn"))
1208 sender_msisdn = argv[3];
1209 else {
1210 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1211 if (!sender) {
1212 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1213 rc = CMD_WARNING;
1214 goto err;
1215 }
1216 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001217 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001218 }
1219
1220 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001221 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001222 talloc_free(str);
1223
1224err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001225 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001226 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001227
1228 return rc;
1229}
1230
1231DEFUN(subscriber_silent_sms,
1232 subscriber_silent_sms_cmd,
1233
1234 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1235 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1236{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001237 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001238 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001239 char *str;
1240 int rc;
1241
1242 if (!vsub) {
1243 vty_out(vty, "%% No subscriber found for %s %s%s",
1244 argv[0], argv[1], VTY_NEWLINE);
1245 rc = CMD_WARNING;
1246 goto err;
1247 }
1248
Harald Welte39b55482018-04-09 19:19:33 +02001249 if (!strcmp(argv[2], "msisdn")) {
1250 sender_msisdn = argv[3];
1251 } else {
1252 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1253 if (!sender) {
1254 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1255 rc = CMD_WARNING;
1256 goto err;
1257 }
1258 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001259 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001260 }
1261
1262 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001263 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001264 talloc_free(str);
1265
1266err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001267 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001268 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001269
1270 return rc;
1271}
1272
Sylvain Munaut93558302019-02-14 20:13:08 +01001273#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001274#define CHAN_TYPE_HELP \
1275 "Any channel\n" \
1276 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001277 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001278 "Any TCH channel\n" \
1279 "SDCCH channel\n"
1280
Sylvain Munaut93558302019-02-14 20:13:08 +01001281#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1282#define CHAN_MODE_HELP \
1283 "Signalling only\n" \
1284 "Speech with HR codec\n" \
1285 "Speech with FR codec\n" \
1286 "Speech with EFR codec\n" \
1287 "Speech with AMR codec\n"
1288
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001289DEFUN(subscriber_silent_call_start,
1290 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001291 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001292 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001293 CHAN_TYPE_HELP CHAN_MODE_HELP
1294 "Target IP for RTP traffic (default 127.0.0.1)\n"
1295 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001296{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001297 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001298 struct gsm0808_channel_type ct;
1299 const char *ip;
1300 uint16_t port;
1301 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001302
1303 if (!vsub) {
1304 vty_out(vty, "%% No subscriber found for %s %s%s",
1305 argv[0], argv[1], VTY_NEWLINE);
1306 return CMD_WARNING;
1307 }
1308
Sylvain Munaut93558302019-02-14 20:13:08 +01001309 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001310
Sylvain Munaut93558302019-02-14 20:13:08 +01001311 if (!strcmp(argv[3], "signalling")) {
1312 ct.ch_indctr = GSM0808_CHAN_SIGN;
1313 ct.perm_spch[0] = 0; /* Spare but required */
1314 ct.perm_spch_len = 1;
1315 } else if (!strcmp(argv[3], "speech-hr")) {
1316 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1317 ct.perm_spch[0] = GSM0808_PERM_HR1;
1318 ct.perm_spch_len = 1;
1319 } else if (!strcmp(argv[3], "speech-fr")) {
1320 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1321 ct.perm_spch[0] = GSM0808_PERM_FR1;
1322 ct.perm_spch_len = 1;
1323 } else if (!strcmp(argv[3], "speech-efr")) {
1324 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1325 ct.perm_spch[0] = GSM0808_PERM_FR2;
1326 ct.perm_spch_len = 1;
1327 } else if (!strcmp(argv[3], "speech-amr")) {
1328 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1329 ct.perm_spch[0] = GSM0808_PERM_FR3;
1330 ct.perm_spch[1] = GSM0808_PERM_HR3;
1331 ct.perm_spch_len = 2;
1332 }
1333
1334 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1335
1336 if (!strcmp(argv[2], "tch/f"))
1337 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1338 else if (!strcmp(argv[2], "tch/h"))
1339 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1340 else if (!strcmp(argv[2], "tch/any"))
1341 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1342 else if (!strcmp(argv[2], "sdcch")) {
1343 if (speech) {
1344 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1345 return CMD_WARNING;
1346 }
1347 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1348 } else
1349 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1350
1351 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1352 port = argc >= 6 ? atoi(argv[5]) : 4000;
1353
1354 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001355 switch (rc) {
1356 case -ENODEV:
1357 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1358 break;
1359 default:
1360 if (rc)
1361 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1362 else
1363 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1364 break;
1365 }
1366
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001367 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001368 return rc ? CMD_WARNING : CMD_SUCCESS;
1369}
1370
1371DEFUN(subscriber_silent_call_stop,
1372 subscriber_silent_call_stop_cmd,
1373 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1374 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1375 CHAN_TYPE_HELP)
1376{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001377 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1378 int rc;
1379
1380 if (!vsub) {
1381 vty_out(vty, "%% No subscriber found for %s %s%s",
1382 argv[0], argv[1], VTY_NEWLINE);
1383 return CMD_WARNING;
1384 }
1385
1386 rc = gsm_silent_call_stop(vsub);
1387 switch (rc) {
1388 case -ENODEV:
1389 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1390 break;
1391 case -ENOENT:
1392 vty_out(vty, "%% Subscriber has no silent call active%s",
1393 VTY_NEWLINE);
1394 break;
1395 default:
1396 if (rc)
1397 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1398 else
1399 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1400 break;
1401 }
1402
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001403 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001404 return rc ? CMD_WARNING : CMD_SUCCESS;
1405}
1406
1407DEFUN(subscriber_ussd_notify,
1408 subscriber_ussd_notify_cmd,
1409 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1410 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1411 "Alerting Level 0\n"
1412 "Alerting Level 1\n"
1413 "Alerting Level 2\n"
1414 "Text of USSD message to send\n")
1415{
1416 char *text;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001417 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001418 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1419 int level;
1420
1421 if (!vsub) {
1422 vty_out(vty, "%% No subscriber found for %s %s%s",
1423 argv[0], argv[1], VTY_NEWLINE);
1424 return CMD_WARNING;
1425 }
1426
1427 level = atoi(argv[2]);
1428 text = argv_concat(argv, argc, 3);
1429 if (!text) {
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001430 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001431 return CMD_WARNING;
1432 }
1433
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001434 msc_a = msc_a_for_vsub(vsub, true);
1435 if (!msc_a || msc_a->c.remote_to) {
1436 vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001437 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001438 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001439 talloc_free(text);
1440 return CMD_WARNING;
1441 }
1442
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001443 msc_send_ussd_notify(msc_a, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001444 /* FIXME: since we don't allocate a transaction here,
1445 * we use dummy GSM 04.07 transaction ID. */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001446 msc_send_ussd_release_complete(msc_a, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001447
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001448 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001449 talloc_free(text);
1450 return CMD_SUCCESS;
1451}
1452
1453DEFUN(subscriber_paging,
1454 subscriber_paging_cmd,
1455 "subscriber " SUBSCR_TYPES " ID paging",
1456 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1457{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001458 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001459 struct paging_request *req;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001460
1461 if (!vsub) {
1462 vty_out(vty, "%% No subscriber found for %s %s%s",
1463 argv[0], argv[1], VTY_NEWLINE);
1464 return CMD_WARNING;
1465 }
1466
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001467 req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL,
1468 NULL, NULL, "manual Paging from VTY");
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001469 if (req)
1470 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1471 else
1472 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1473
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001474 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001475 return req ? CMD_SUCCESS : CMD_WARNING;
1476}
1477
1478static int loop_by_char(uint8_t ch)
1479{
1480 switch (ch) {
1481 case 'a':
1482 return GSM414_LOOP_A;
1483 case 'b':
1484 return GSM414_LOOP_B;
1485 case 'c':
1486 return GSM414_LOOP_C;
1487 case 'd':
1488 return GSM414_LOOP_D;
1489 case 'e':
1490 return GSM414_LOOP_E;
1491 case 'f':
1492 return GSM414_LOOP_F;
1493 case 'i':
1494 return GSM414_LOOP_I;
1495 }
1496 return -1;
1497}
1498
1499DEFUN(subscriber_mstest_close,
1500 subscriber_mstest_close_cmd,
1501 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1502 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1503 "Close a TCH Loop inside the MS\n"
1504 "Loop Type A\n"
1505 "Loop Type B\n"
1506 "Loop Type C\n"
1507 "Loop Type D\n"
1508 "Loop Type E\n"
1509 "Loop Type F\n"
1510 "Loop Type I\n")
1511{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001512 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001513 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1514 const char *loop_str;
1515 int loop_mode;
1516
1517 if (!vsub) {
1518 vty_out(vty, "%% No subscriber found for %s %s%s",
1519 argv[0], argv[1], VTY_NEWLINE);
1520 return CMD_WARNING;
1521 }
1522
1523 loop_str = argv[2];
1524 loop_mode = loop_by_char(loop_str[0]);
1525
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001526 msc_a = msc_a_for_vsub(vsub, true);
1527 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001528 vty_out(vty, "%% An active connection is required for %s %s%s",
1529 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001530 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001531 return CMD_WARNING;
1532 }
1533
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001534 gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001535
1536 return CMD_SUCCESS;
1537}
1538
1539DEFUN(subscriber_mstest_open,
1540 subscriber_mstest_open_cmd,
1541 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1542 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1543 "Open a TCH Loop inside the MS\n")
1544{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001545 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001546 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1547
1548 if (!vsub) {
1549 vty_out(vty, "%% No subscriber found for %s %s%s",
1550 argv[0], argv[1], VTY_NEWLINE);
1551 return CMD_WARNING;
1552 }
1553
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001554 msc_a = msc_a_for_vsub(vsub, true);
1555 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001556 vty_out(vty, "%% An active connection is required for %s %s%s",
1557 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001558 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001559 return CMD_WARNING;
1560 }
1561
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001562 gsm0414_tx_open_loop_cmd(msc_a);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001563
1564 return CMD_SUCCESS;
1565}
1566
1567DEFUN(ena_subscr_expire,
1568 ena_subscr_expire_cmd,
1569 "subscriber " SUBSCR_TYPES " ID expire",
1570 SUBSCR_HELP "Expire the subscriber Now\n")
1571{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001572 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1573 argv[1]);
1574
1575 if (!vsub) {
1576 vty_out(vty, "%% No subscriber found for %s %s%s",
1577 argv[0], argv[1], VTY_NEWLINE);
1578 return CMD_WARNING;
1579 }
1580
1581 if (vlr_subscr_expire(vsub))
1582 vty_out(vty, "%% VLR released subscriber %s%s",
1583 vlr_subscr_name(vsub), VTY_NEWLINE);
1584
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001585 if (osmo_use_count_total(&vsub->use_count) > 1)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001586 vty_out(vty, "%% Subscriber %s is still in use,"
1587 " should be released soon%s",
1588 vlr_subscr_name(vsub), VTY_NEWLINE);
1589
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001590 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001591 return CMD_SUCCESS;
1592}
1593
1594static int scall_cbfn(unsigned int subsys, unsigned int signal,
1595 void *handler_data, void *signal_data)
1596{
1597 struct scall_signal_data *sigdata = signal_data;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001598 struct vty *vty = sigdata->vty;
1599
1600 if (!vty_is_active(vty))
1601 return 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001602
1603 switch (signal) {
1604 case S_SCALL_SUCCESS:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001605 vty_out(vty, "%% Silent call success%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001606 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001607 case S_SCALL_FAILED:
1608 vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE);
1609 break;
1610 case S_SCALL_DETACHED:
1611 vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001612 break;
1613 }
1614 return 0;
1615}
1616
1617DEFUN(show_stats,
1618 show_stats_cmd,
1619 "show statistics",
1620 SHOW_STR "Display network statistics\n")
1621{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001622 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001623 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1624 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1625 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001626 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001627 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001628 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001629 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001630 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001631 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1632 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001633 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001634 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001635 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1636 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001637 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001638 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001639 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1640 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1641 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001642 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001643 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001644 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1645 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001646 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001647 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001648 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1649 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001650 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001651 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001652 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current,
1653 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1654 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current
1655 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1656 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001657 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001658 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current,
1659 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1660 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current
1661 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1662 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001663 return CMD_SUCCESS;
1664}
1665
1666DEFUN(show_smsqueue,
1667 show_smsqueue_cmd,
1668 "show sms-queue",
1669 SHOW_STR "Display SMSqueue statistics\n")
1670{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001671 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001672 return CMD_SUCCESS;
1673}
1674
1675DEFUN(smsqueue_trigger,
1676 smsqueue_trigger_cmd,
1677 "sms-queue trigger",
1678 "SMS Queue\n" "Trigger sending messages\n")
1679{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001680 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001681 return CMD_SUCCESS;
1682}
1683
1684DEFUN(smsqueue_max,
1685 smsqueue_max_cmd,
1686 "sms-queue max-pending <1-500>",
1687 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1688{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001689 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001690 return CMD_SUCCESS;
1691}
1692
1693DEFUN(smsqueue_clear,
1694 smsqueue_clear_cmd,
1695 "sms-queue clear",
1696 "SMS Queue\n" "Clear the queue of pending SMS\n")
1697{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001698 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001699 return CMD_SUCCESS;
1700}
1701
1702DEFUN(smsqueue_fail,
1703 smsqueue_fail_cmd,
1704 "sms-queue max-failure <1-500>",
1705 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1706{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001707 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001708 return CMD_SUCCESS;
1709}
1710
1711
1712DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1713 "mncc-int", "Configure internal MNCC handler")
1714{
1715 vty->node = MNCC_INT_NODE;
1716
1717 return CMD_SUCCESS;
1718}
1719
1720static struct cmd_node mncc_int_node = {
1721 MNCC_INT_NODE,
1722 "%s(config-mncc-int)# ",
1723 1,
1724};
1725
1726static const struct value_string tchf_codec_names[] = {
1727 { GSM48_CMODE_SPEECH_V1, "fr" },
1728 { GSM48_CMODE_SPEECH_EFR, "efr" },
1729 { GSM48_CMODE_SPEECH_AMR, "amr" },
1730 { 0, NULL }
1731};
1732
1733static const struct value_string tchh_codec_names[] = {
1734 { GSM48_CMODE_SPEECH_V1, "hr" },
1735 { GSM48_CMODE_SPEECH_AMR, "amr" },
1736 { 0, NULL }
1737};
1738
1739static int config_write_mncc_int(struct vty *vty)
1740{
1741 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1742 vty_out(vty, " default-codec tch-f %s%s",
1743 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1744 VTY_NEWLINE);
1745 vty_out(vty, " default-codec tch-h %s%s",
1746 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1747 VTY_NEWLINE);
1748
1749 return CMD_SUCCESS;
1750}
1751
1752DEFUN(mnccint_def_codec_f,
1753 mnccint_def_codec_f_cmd,
1754 "default-codec tch-f (fr|efr|amr)",
1755 "Set default codec\n" "Codec for TCH/F\n"
1756 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1757{
1758 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1759
1760 return CMD_SUCCESS;
1761}
1762
1763DEFUN(mnccint_def_codec_h,
1764 mnccint_def_codec_h_cmd,
1765 "default-codec tch-h (hr|amr)",
1766 "Set default codec\n" "Codec for TCH/H\n"
1767 "Half-Rate\n" "Adaptive Multi-Rate\n")
1768{
1769 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1770
1771 return CMD_SUCCESS;
1772}
1773
1774
1775DEFUN(logging_fltr_imsi,
1776 logging_fltr_imsi_cmd,
1777 "logging filter imsi IMSI",
1778 LOGGING_STR FILTER_STR
1779 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1780{
1781 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001782 struct log_target *tgt = osmo_log_vty2tgt(vty);
1783 const char *imsi = argv[0];
1784
1785 if (!tgt)
1786 return CMD_WARNING;
1787
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001788 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001789
1790 if (!vlr_subscr) {
1791 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1792 argv[0], VTY_NEWLINE);
1793 return CMD_WARNING;
1794 }
1795
1796 log_set_filter_vlr_subscr(tgt, vlr_subscr);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001797 vlr_subscr_put(vlr_subscr, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001798 return CMD_SUCCESS;
1799}
1800
1801static struct cmd_node hlr_node = {
1802 HLR_NODE,
1803 "%s(config-hlr)# ",
1804 1,
1805};
1806
1807DEFUN(cfg_hlr, cfg_hlr_cmd,
1808 "hlr", "Configure connection to the HLR")
1809{
1810 vty->node = HLR_NODE;
1811 return CMD_SUCCESS;
1812}
1813
1814DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1815 "Remote GSUP address of the HLR\n"
1816 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1817{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001818 talloc_free((void*)gsmnet->gsup_server_addr_str);
1819 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1820 return CMD_SUCCESS;
1821}
1822
1823DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1824 "Remote GSUP port of the HLR\n"
1825 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1826{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001827 gsmnet->gsup_server_port = atoi(argv[0]);
1828 return CMD_SUCCESS;
1829}
1830
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001831DEFUN(cfg_hlr_ipa_name,
1832 cfg_hlr_ipa_name_cmd,
1833 "ipa-name NAME",
1834 "Set the IPA name of this MSC\n"
1835 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1836 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
1837 "The default is 'MSC-00-00-00-00-00-00'.\n")
1838{
1839 if (vty->type != VTY_FILE) {
1840 vty_out(vty, "The IPA name cannot be changed at run-time; "
1841 "It can only be set in the configuraton file.%s", VTY_NEWLINE);
1842 return CMD_WARNING;
1843 }
1844
1845 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
1846 return CMD_SUCCESS;
1847}
1848
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001849static int config_write_hlr(struct vty *vty)
1850{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001851 vty_out(vty, "hlr%s", VTY_NEWLINE);
1852 vty_out(vty, " remote-ip %s%s",
1853 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1854 vty_out(vty, " remote-port %u%s",
1855 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001856 if (gsmnet->msc_ipa_name)
1857 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001858 return CMD_SUCCESS;
1859}
1860
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001861void msc_vty_init(struct gsm_network *msc_network)
1862{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001863 OSMO_ASSERT(gsmnet == NULL);
1864 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001865
1866 osmo_stats_vty_add_cmds();
1867
1868 install_element(CONFIG_NODE, &cfg_net_cmd);
1869 install_node(&net_node, config_write_net);
1870 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1871 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1872 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1873 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1874 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
1875 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1876 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1877 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1878 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1879 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1880 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1881 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1882 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001883
1884 install_element(CONFIG_NODE, &cfg_msc_cmd);
1885 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001886 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01001887 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
1888 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02001889 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01001890 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07001891 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001892 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001893 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
1894 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01001895 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001896 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
1897 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01001898 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01001899 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07001900 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
1901 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +02001902 install_element(MSC_NODE, &cfg_msc_osmux_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001903 install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd);
1904
1905 neighbor_ident_vty_init(msc_network);
Philipp Maierfbf66102017-04-09 12:32:51 +02001906
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02001907 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001908#ifdef BUILD_IU
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001909 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 +02001910#endif
Harald Welte0df904d2018-12-03 11:00:04 +01001911 sgs_vty_init();
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001912
Stefan Sperling617ac802018-02-22 17:58:20 +01001913 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001914
1915 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
1916
1917 install_element_ve(&show_subscr_cmd);
1918 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01001919 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001920 install_element_ve(&show_msc_conn_cmd);
1921 install_element_ve(&show_msc_transaction_cmd);
1922
1923 install_element_ve(&sms_send_pend_cmd);
1924 install_element_ve(&sms_delete_expired_cmd);
1925
1926 install_element_ve(&subscriber_create_cmd);
1927 install_element_ve(&subscriber_send_sms_cmd);
1928 install_element_ve(&subscriber_silent_sms_cmd);
1929 install_element_ve(&subscriber_silent_call_start_cmd);
1930 install_element_ve(&subscriber_silent_call_stop_cmd);
1931 install_element_ve(&subscriber_ussd_notify_cmd);
1932 install_element_ve(&subscriber_mstest_close_cmd);
1933 install_element_ve(&subscriber_mstest_open_cmd);
1934 install_element_ve(&subscriber_paging_cmd);
1935 install_element_ve(&show_stats_cmd);
1936 install_element_ve(&show_smsqueue_cmd);
1937 install_element_ve(&logging_fltr_imsi_cmd);
1938
1939 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
1940 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
1941 install_element(ENABLE_NODE, &smsqueue_max_cmd);
1942 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
1943 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
1944 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001945 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001946
1947 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
1948 install_node(&mncc_int_node, config_write_mncc_int);
1949 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
1950 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
1951
1952 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
1953
1954 install_element(CONFIG_NODE, &cfg_hlr_cmd);
1955 install_node(&hlr_node, config_write_hlr);
1956 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
1957 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001958 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001959}