blob: 8ef48ff511c37382ee0f456a62093bc4143f7d5f [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
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200691/* Print value of a named flag, prefixed with a given amount of spaces */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700692#define MSC_VTY_DUMP_FLAG(vty, offset, name, flag) \
693 MSC_VTY_DUMP(vty, offset + 2, "%s: %*s%s%s", \
694 name, 30 - (int)strlen(name), "", \
695 flag ? "true" : "false", \
696 VTY_NEWLINE)
697
698enum msc_vty_dump_flags {
699 MSC_VTY_DUMP_F_SUBSCR = (1 << 0),
700 MSC_VTY_DUMP_F_CONNECTION = (1 << 1),
701 MSC_VTY_DUMP_F_TRANSACTION = (1 << 2),
702};
703
704static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans,
705 int offset, uint8_t dump_flags)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100706{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700707 const char *proto_str;
708
709 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
710 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
711 vlr_subscr_name(msc_a_vsub(trans->msc_a)),
712 VTY_NEWLINE);
713 }
714
715 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200716 /* (If msc_a exists, there *must* be a non-null msc_a->c.msub) */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700717 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
718 trans->msc_a ? msub_ran_conn_name(trans->msc_a->c.msub)
719 : "(not established)",
720 VTY_NEWLINE);
721 }
722
723 MSC_VTY_DUMP(vty, offset, "Unique (global) identifier: 0x%08x%s",
724 trans->callref, VTY_NEWLINE);
725 MSC_VTY_DUMP(vty, offset, "GSM 04.07 identifier (%s): %u%s",
726 (trans->transaction_id & 0x08) ? "MO" : "MT",
727 trans->transaction_id,
728 VTY_NEWLINE);
729
730 MSC_VTY_DUMP(vty, offset, "Type: %s%s",
731 trans_type_name(trans->type),
732 VTY_NEWLINE);
733
734 if ((proto_str = get_trans_proto_str(trans))) {
735 MSC_VTY_DUMP(vty, offset, "Protocol specific: %s%s",
736 proto_str, VTY_NEWLINE);
737 }
738}
739
740static void vty_dump_one_conn(struct vty *vty, const struct msub *msub,
741 int offset, uint8_t dump_flags)
742{
743 struct vlr_subscr *vsub = msub_vsub(msub);
744 struct msc_a *msc_a = msub_msc_a(msub);
745 char buf[128];
746
747 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
748 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
749 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
750 vlr_subscr_name(vsub),
751 VTY_NEWLINE);
752 }
753
754 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
755 msub_ran_conn_name(msub),
756 VTY_NEWLINE);
757 MSC_VTY_DUMP(vty, offset, "RAN connection state: %s%s",
758 osmo_fsm_inst_state_name(msc_a->c.fi),
759 VTY_NEWLINE);
760
761 if (vsub) {
762 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
763 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
764 VTY_NEWLINE);
765 }
766
767 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
768 osmo_use_count_total(&msc_a->use_count),
769 VTY_NEWLINE);
770 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
771 osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count),
772 VTY_NEWLINE);
773
774 /* Transactions of this connection */
775 if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
776 struct gsm_trans *trans;
777 unsigned int i = 0;
778
779 /* Both subscriber and connection info is already printed */
780 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_CONNECTION;
781 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
782
783 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
784 if (trans->msc_a != msc_a)
785 continue;
786 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
787 i++, VTY_NEWLINE);
788 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
789 }
790 }
791}
792
793static void vty_dump_one_subscr(struct vty *vty, struct vlr_subscr *vsub,
794 int offset, uint8_t dump_flags)
795{
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700796 struct gsm_network *net;
797 struct timespec now;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700798 char buf[128];
799
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700800 if (vsub->name[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700801 MSC_VTY_DUMP(vty, offset, "Name: '%s'%s",
802 vsub->name, VTY_NEWLINE);
803 }
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700804 if (vsub->msisdn[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700805 MSC_VTY_DUMP(vty, offset, "MSISDN: %s%s",
806 vsub->msisdn, VTY_NEWLINE);
807 }
808
809 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
810 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
811 VTY_NEWLINE);
812 MSC_VTY_DUMP(vty, offset, "RAN type: %s%s",
813 osmo_rat_type_name(vsub->cs.attached_via_ran),
814 VTY_NEWLINE);
815
816 MSC_VTY_DUMP(vty, offset, "IMSI: %s%s",
817 vsub->imsi, VTY_NEWLINE);
818 if (vsub->tmsi != GSM_RESERVED_TMSI) {
819 MSC_VTY_DUMP(vty, offset, "TMSI: %08X%s",
820 vsub->tmsi, VTY_NEWLINE);
821 }
822 if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
823 MSC_VTY_DUMP(vty, offset, "New TMSI: %08X%s",
824 vsub->tmsi_new, VTY_NEWLINE);
825 }
826 if (vsub->imei[0] != '\0') {
827 MSC_VTY_DUMP(vty, offset, "IMEI: %s%s",
828 vsub->imei, VTY_NEWLINE);
829 }
830 if (vsub->imeisv[0] != '\0') {
831 MSC_VTY_DUMP(vty, offset, "IMEISV: %s%s",
832 vsub->imeisv, VTY_NEWLINE);
833 }
834
835 MSC_VTY_DUMP(vty, offset, "Flags: %s", VTY_NEWLINE);
836 MSC_VTY_DUMP_FLAG(vty, offset, "IMSI detached",
837 vsub->imsi_detached_flag);
838 MSC_VTY_DUMP_FLAG(vty, offset, "Conf. by radio contact",
839 vsub->conf_by_radio_contact_ind);
840 MSC_VTY_DUMP_FLAG(vty, offset, "Subscr. data conf. by HLR",
841 vsub->sub_dataconf_by_hlr_ind);
842 MSC_VTY_DUMP_FLAG(vty, offset, "Location conf. in HLR",
843 vsub->loc_conf_in_hlr_ind);
844 MSC_VTY_DUMP_FLAG(vty, offset, "Subscriber dormant",
845 vsub->dormant_ind);
846 MSC_VTY_DUMP_FLAG(vty, offset, "Received cancel location",
847 vsub->cancel_loc_rx);
848 MSC_VTY_DUMP_FLAG(vty, offset, "MS not reachable",
849 vsub->ms_not_reachable_flag);
850 MSC_VTY_DUMP_FLAG(vty, offset, "LA allowed",
851 vsub->la_allowed);
852
853 if (vsub->last_tuple) {
854 struct vlr_auth_tuple *t = vsub->last_tuple;
855 MSC_VTY_DUMP(vty, offset, "A3A8 last tuple (used %d times): %s",
856 t->use_count, VTY_NEWLINE);
857 MSC_VTY_DUMP(vty, offset + 2, "seq # : %d%s",
858 t->key_seq, VTY_NEWLINE);
859 MSC_VTY_DUMP(vty, offset + 2, "RAND : %s%s",
860 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
861 VTY_NEWLINE);
862 MSC_VTY_DUMP(vty, offset + 2, "SRES : %s%s",
863 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
864 VTY_NEWLINE);
865 MSC_VTY_DUMP(vty, offset + 2, "Kc : %s%s",
866 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
867 VTY_NEWLINE);
868 }
869
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700870 /* XXX move t3212 into struct vlr_instance? */
871 net = vsub->vlr->user_ctx;
872 if (!net->t3212) {
873 MSC_VTY_DUMP(vty, offset, "Expires: never (T3212 is disabled)%s",
874 VTY_NEWLINE);
875 } else if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) {
876 MSC_VTY_DUMP(vty, offset, "Expires: never%s",
877 VTY_NEWLINE);
878 } else if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
879 MSC_VTY_DUMP(vty, offset, "Expires: in %ld min %ld sec%s",
880 (vsub->expire_lu - now.tv_sec) / 60,
881 (vsub->expire_lu - now.tv_sec) % 60,
882 VTY_NEWLINE);
883 }
884
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700885 MSC_VTY_DUMP(vty, offset, "Paging: %s paging for %d requests%s",
886 vsub->cs.is_paging ? "is" : "not",
887 llist_count(&vsub->cs.requests),
888 VTY_NEWLINE);
889
890 /* SGs related */
891 MSC_VTY_DUMP(vty, offset, "SGs-state: %s%s",
892 osmo_fsm_inst_state_name(vsub->sgs_fsm),
893 VTY_NEWLINE);
894 MSC_VTY_DUMP(vty, offset, "SGs-MME: %s%s",
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700895 vsub->sgs.mme_name[0] != '\0' ? vsub->sgs.mme_name : "(none)",
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700896 VTY_NEWLINE);
897
898 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
899 osmo_use_count_total(&vsub->use_count),
900 VTY_NEWLINE);
901 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
902 osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count),
903 VTY_NEWLINE);
904
905 /* Connection(s) and/or transactions of this subscriber */
906 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
907 struct msub *msub = msub_for_vsub(vsub);
908 if (!msub)
909 return;
910
911 /* Subscriber info is already printed */
912 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
913
914 MSC_VTY_DUMP(vty, offset, "Connection: %s", VTY_NEWLINE);
915 vty_dump_one_conn(vty, msub, offset + 2, dump_flags);
916 } else if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
917 struct gsm_trans *trans;
918 unsigned int i = 0;
919
920 /* Subscriber info is already printed */
921 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
922 /* Do not print connection info, but mention it */
923 dump_flags |= MSC_VTY_DUMP_F_CONNECTION;
924
925 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
926 if (trans->vsub != vsub)
927 continue;
928 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
929 i++, VTY_NEWLINE);
930 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
931 }
932 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100933}
934
935DEFUN(show_msc_transaction, show_msc_transaction_cmd,
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700936 "show transaction",
937 SHOW_STR "Transactions\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100938{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100939 struct gsm_trans *trans;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700940 uint8_t flags = 0x00;
941 unsigned int i = 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100942
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700943 flags |= MSC_VTY_DUMP_F_CONNECTION;
944 flags |= MSC_VTY_DUMP_F_SUBSCR;
945
946 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
947 vty_out(vty, " Transaction #%02u: %s", i++, VTY_NEWLINE);
948 vty_dump_one_trans(vty, trans, 4, flags);
949 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100950
951 return CMD_SUCCESS;
952}
953
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700954DEFUN(show_msc_conn, show_msc_conn_cmd,
955 "show connection [trans]",
956 SHOW_STR "Subscriber Connections\n"
957 "Show child transactions of each connection\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100958{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700959 uint8_t flags = 0x00;
960 unsigned int i = 0;
961 struct msub *msub;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100962
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700963 if (argc > 0)
964 flags |= MSC_VTY_DUMP_F_TRANSACTION;
965 flags |= MSC_VTY_DUMP_F_SUBSCR;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100966
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700967 llist_for_each_entry(msub, &msub_list, entry) {
968 vty_out(vty, " Connection #%02u: %s", i++, VTY_NEWLINE);
969 vty_dump_one_conn(vty, msub, 4, flags);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100970 }
971
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700972 return CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100973}
974
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700975#define SUBSCR_FLAGS "[(conn|trans|conn+trans)]"
976#define SUBSCR_FLAGS_HELP \
977 "Show child connections\n" \
978 "Show child transactions\n" \
979 "Show child connections and transactions\n"
980
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100981/* Subscriber */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700982DEFUN(show_subscr_cache, show_subscr_cache_cmd,
983 "show subscriber cache " SUBSCR_FLAGS,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100984 SHOW_STR "Show information about subscribers\n"
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700985 "Display contents of subscriber cache\n"
986 SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100987{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100988 struct vlr_subscr *vsub;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700989 unsigned int count = 0;
990 uint8_t flags = 0x00;
991 unsigned int i = 0;
992
993 if (argc && strcmp(argv[0], "conn") == 0)
994 flags |= MSC_VTY_DUMP_F_CONNECTION;
995 else if (argc && strcmp(argv[0], "trans") == 0)
996 flags |= MSC_VTY_DUMP_F_TRANSACTION;
997 else if (argc && strcmp(argv[0], "conn+trans") == 0)
998 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100999
1000 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
1001 if (++count > 100) {
1002 vty_out(vty, "%% More than %d subscribers in cache,"
1003 " stopping here.%s", count-1, VTY_NEWLINE);
1004 break;
1005 }
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001006 vty_out(vty, " Subscriber #%02u: %s", i++, VTY_NEWLINE);
1007 vty_dump_one_subscr(vty, vsub, 4, flags);
Harald Welte69c54a82018-02-09 20:41:14 +01001008 }
1009
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001010 return CMD_SUCCESS;
1011}
1012
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001013DEFUN(sms_send_pend,
1014 sms_send_pend_cmd,
1015 "sms send pending",
1016 "SMS related commands\n" "SMS Sending related commands\n"
1017 "Send all pending SMS")
1018{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001019 struct gsm_sms *sms;
1020 unsigned long long sms_id = 0;
1021
1022 while (1) {
1023 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1024 if (!sms)
1025 break;
1026
1027 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001028 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001029
1030 sms_id = sms->id + 1;
1031 }
1032
1033 return CMD_SUCCESS;
1034}
1035
1036DEFUN(sms_delete_expired,
1037 sms_delete_expired_cmd,
1038 "sms delete expired",
1039 "SMS related commands\n" "SMS Database related commands\n"
1040 "Delete all expired SMS")
1041{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001042 struct gsm_sms *sms;
1043 unsigned long long sms_id = 0;
1044 long long num_deleted = 0;
1045
1046 while (1) {
1047 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1048 if (!sms)
1049 break;
1050
1051 /* Skip SMS which are currently queued for sending. */
1052 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
1053 continue;
1054
1055 /* Expiration check is performed by the DB layer. */
1056 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
1057 num_deleted++;
1058
1059 sms_id = sms->id + 1;
1060 }
1061
1062 if (num_deleted == 0) {
1063 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
1064 return CMD_WARNING;
1065 }
1066
1067 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
1068 return CMD_SUCCESS;
1069}
1070
1071static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +02001072 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001073 char *str, uint8_t tp_pid)
1074{
1075 struct gsm_network *net = receiver->vlr->user_ctx;
1076 struct gsm_sms *sms;
1077
Harald Welte39b55482018-04-09 19:19:33 +02001078 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001079 sms->protocol_id = tp_pid;
1080
1081 /* store in database for the queue */
1082 if (db_sms_store(sms) != 0) {
1083 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
1084 sms_free(sms);
1085 return CMD_WARNING;
1086 }
1087 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
1088
1089 sms_free(sms);
1090 sms_queue_trigger(net->sms_queue);
1091 return CMD_SUCCESS;
1092}
1093
1094static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
1095 const char *type,
1096 const char *id)
1097{
1098 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001099 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001100 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001101 return vlr_subscr_find_by_imsi(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001102 else if (!strcmp(type, "tmsi"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001103 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id), VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001104
1105 return NULL;
1106}
1107#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
1108#define SUBSCR_HELP "Operations on a Subscriber\n" \
1109 "Identify subscriber by MSISDN (phone number)\n" \
1110 "Legacy alias for 'msisdn'\n" \
1111 "Identify subscriber by IMSI\n" \
1112 "Identify subscriber by TMSI\n" \
Vadim Yanitskiy3ccd8232019-05-16 01:35:23 +07001113 "Legacy alias for 'imsi'\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001114 "Identifier for the subscriber\n"
1115
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001116DEFUN(show_subscr, show_subscr_cmd,
1117 "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
1118 SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001119{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001120 struct vlr_subscr *vsub;
1121 uint8_t flags = 0x00;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001122
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001123 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001124 if (!vsub) {
1125 vty_out(vty, "%% No subscriber found for %s %s%s",
1126 argv[0], argv[1], VTY_NEWLINE);
1127 return CMD_WARNING;
1128 }
1129
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001130 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
1131 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
1132 * 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 +01001133 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001134
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001135 if (argc > 2 && strcmp(argv[2], "conn") == 0)
1136 flags |= MSC_VTY_DUMP_F_CONNECTION;
1137 else if (argc > 2 && strcmp(argv[2], "trans") == 0)
1138 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1139 else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
1140 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
1141
1142 vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
1143 vty_dump_one_subscr(vty, vsub, 4, flags);
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001144
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001145 return CMD_SUCCESS;
1146}
1147
1148DEFUN(subscriber_create,
1149 subscriber_create_cmd,
1150 "subscriber create imsi ID",
1151 "Operations on a Subscriber\n" \
1152 "Create new subscriber\n" \
1153 "Identify the subscriber by his IMSI\n" \
1154 "Identifier for the subscriber\n")
1155{
1156 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
1157 VTY_NEWLINE);
1158 return CMD_WARNING;
1159}
1160
1161DEFUN(subscriber_send_pending_sms,
1162 subscriber_send_pending_sms_cmd,
1163 "subscriber " SUBSCR_TYPES " ID sms pending-send",
1164 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
1165{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001166 struct vlr_subscr *vsub;
1167 struct gsm_sms *sms;
1168
1169 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1170 if (!vsub) {
1171 vty_out(vty, "%% No subscriber found for %s %s%s",
1172 argv[0], argv[1], VTY_NEWLINE);
1173 return CMD_WARNING;
1174 }
1175
1176 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
1177 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001178 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001179
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001180 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001181
1182 return CMD_SUCCESS;
1183}
1184
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001185DEFUN(subscriber_sms_delete_all,
1186 subscriber_sms_delete_all_cmd,
1187 "subscriber " SUBSCR_TYPES " ID sms delete-all",
1188 SUBSCR_HELP "SMS Operations\n"
1189 "Delete all SMS to be delivered to this subscriber"
1190 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
1191 " WILL BE LOST.\n")
1192{
1193 struct vlr_subscr *vsub;
1194
1195 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1196 if (!vsub) {
1197 vty_out(vty, "%% No subscriber found for %s %s%s",
1198 argv[0], argv[1], VTY_NEWLINE);
1199 return CMD_WARNING;
1200 }
1201
1202 db_sms_delete_by_msisdn(vsub->msisdn);
1203
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001204 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001205
1206 return CMD_SUCCESS;
1207}
1208
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001209DEFUN(subscriber_send_sms,
1210 subscriber_send_sms_cmd,
1211 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1212 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1213{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001214 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001215 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001216 char *str;
1217 int rc;
1218
1219 if (!vsub) {
1220 vty_out(vty, "%% No subscriber found for %s %s%s",
1221 argv[0], argv[1], VTY_NEWLINE);
1222 rc = CMD_WARNING;
1223 goto err;
1224 }
1225
Harald Welte39b55482018-04-09 19:19:33 +02001226 if (!strcmp(argv[2], "msisdn"))
1227 sender_msisdn = argv[3];
1228 else {
1229 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1230 if (!sender) {
1231 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1232 rc = CMD_WARNING;
1233 goto err;
1234 }
1235 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001236 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001237 }
1238
1239 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001240 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001241 talloc_free(str);
1242
1243err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001244 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001245 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001246
1247 return rc;
1248}
1249
1250DEFUN(subscriber_silent_sms,
1251 subscriber_silent_sms_cmd,
1252
1253 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1254 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1255{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001256 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001257 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001258 char *str;
1259 int rc;
1260
1261 if (!vsub) {
1262 vty_out(vty, "%% No subscriber found for %s %s%s",
1263 argv[0], argv[1], VTY_NEWLINE);
1264 rc = CMD_WARNING;
1265 goto err;
1266 }
1267
Harald Welte39b55482018-04-09 19:19:33 +02001268 if (!strcmp(argv[2], "msisdn")) {
1269 sender_msisdn = argv[3];
1270 } else {
1271 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1272 if (!sender) {
1273 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1274 rc = CMD_WARNING;
1275 goto err;
1276 }
1277 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001278 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001279 }
1280
1281 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001282 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001283 talloc_free(str);
1284
1285err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001286 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001287 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001288
1289 return rc;
1290}
1291
Sylvain Munaut93558302019-02-14 20:13:08 +01001292#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001293#define CHAN_TYPE_HELP \
1294 "Any channel\n" \
1295 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001296 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001297 "Any TCH channel\n" \
1298 "SDCCH channel\n"
1299
Sylvain Munaut93558302019-02-14 20:13:08 +01001300#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1301#define CHAN_MODE_HELP \
1302 "Signalling only\n" \
1303 "Speech with HR codec\n" \
1304 "Speech with FR codec\n" \
1305 "Speech with EFR codec\n" \
1306 "Speech with AMR codec\n"
1307
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001308DEFUN(subscriber_silent_call_start,
1309 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001310 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001311 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001312 CHAN_TYPE_HELP CHAN_MODE_HELP
1313 "Target IP for RTP traffic (default 127.0.0.1)\n"
1314 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001315{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001316 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001317 struct gsm0808_channel_type ct;
1318 const char *ip;
1319 uint16_t port;
1320 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001321
1322 if (!vsub) {
1323 vty_out(vty, "%% No subscriber found for %s %s%s",
1324 argv[0], argv[1], VTY_NEWLINE);
1325 return CMD_WARNING;
1326 }
1327
Sylvain Munaut93558302019-02-14 20:13:08 +01001328 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001329
Sylvain Munaut93558302019-02-14 20:13:08 +01001330 if (!strcmp(argv[3], "signalling")) {
1331 ct.ch_indctr = GSM0808_CHAN_SIGN;
1332 ct.perm_spch[0] = 0; /* Spare but required */
1333 ct.perm_spch_len = 1;
1334 } else if (!strcmp(argv[3], "speech-hr")) {
1335 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1336 ct.perm_spch[0] = GSM0808_PERM_HR1;
1337 ct.perm_spch_len = 1;
1338 } else if (!strcmp(argv[3], "speech-fr")) {
1339 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1340 ct.perm_spch[0] = GSM0808_PERM_FR1;
1341 ct.perm_spch_len = 1;
1342 } else if (!strcmp(argv[3], "speech-efr")) {
1343 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1344 ct.perm_spch[0] = GSM0808_PERM_FR2;
1345 ct.perm_spch_len = 1;
1346 } else if (!strcmp(argv[3], "speech-amr")) {
1347 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1348 ct.perm_spch[0] = GSM0808_PERM_FR3;
1349 ct.perm_spch[1] = GSM0808_PERM_HR3;
1350 ct.perm_spch_len = 2;
1351 }
1352
1353 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1354
1355 if (!strcmp(argv[2], "tch/f"))
1356 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1357 else if (!strcmp(argv[2], "tch/h"))
1358 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1359 else if (!strcmp(argv[2], "tch/any"))
1360 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1361 else if (!strcmp(argv[2], "sdcch")) {
1362 if (speech) {
1363 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1364 return CMD_WARNING;
1365 }
1366 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1367 } else
1368 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1369
1370 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1371 port = argc >= 6 ? atoi(argv[5]) : 4000;
1372
1373 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001374 switch (rc) {
1375 case -ENODEV:
1376 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1377 break;
1378 default:
1379 if (rc)
1380 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1381 else
1382 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1383 break;
1384 }
1385
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001386 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001387 return rc ? CMD_WARNING : CMD_SUCCESS;
1388}
1389
1390DEFUN(subscriber_silent_call_stop,
1391 subscriber_silent_call_stop_cmd,
1392 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1393 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1394 CHAN_TYPE_HELP)
1395{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001396 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1397 int rc;
1398
1399 if (!vsub) {
1400 vty_out(vty, "%% No subscriber found for %s %s%s",
1401 argv[0], argv[1], VTY_NEWLINE);
1402 return CMD_WARNING;
1403 }
1404
1405 rc = gsm_silent_call_stop(vsub);
1406 switch (rc) {
1407 case -ENODEV:
1408 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1409 break;
1410 case -ENOENT:
1411 vty_out(vty, "%% Subscriber has no silent call active%s",
1412 VTY_NEWLINE);
1413 break;
1414 default:
1415 if (rc)
1416 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1417 else
1418 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1419 break;
1420 }
1421
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001422 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001423 return rc ? CMD_WARNING : CMD_SUCCESS;
1424}
1425
1426DEFUN(subscriber_ussd_notify,
1427 subscriber_ussd_notify_cmd,
1428 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1429 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1430 "Alerting Level 0\n"
1431 "Alerting Level 1\n"
1432 "Alerting Level 2\n"
1433 "Text of USSD message to send\n")
1434{
1435 char *text;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001436 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001437 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1438 int level;
1439
1440 if (!vsub) {
1441 vty_out(vty, "%% No subscriber found for %s %s%s",
1442 argv[0], argv[1], VTY_NEWLINE);
1443 return CMD_WARNING;
1444 }
1445
1446 level = atoi(argv[2]);
1447 text = argv_concat(argv, argc, 3);
1448 if (!text) {
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001449 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001450 return CMD_WARNING;
1451 }
1452
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001453 msc_a = msc_a_for_vsub(vsub, true);
1454 if (!msc_a || msc_a->c.remote_to) {
1455 vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001456 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001457 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001458 talloc_free(text);
1459 return CMD_WARNING;
1460 }
1461
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001462 msc_send_ussd_notify(msc_a, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001463 /* FIXME: since we don't allocate a transaction here,
1464 * we use dummy GSM 04.07 transaction ID. */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001465 msc_send_ussd_release_complete(msc_a, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001466
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001467 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001468 talloc_free(text);
1469 return CMD_SUCCESS;
1470}
1471
1472DEFUN(subscriber_paging,
1473 subscriber_paging_cmd,
1474 "subscriber " SUBSCR_TYPES " ID paging",
1475 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1476{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001477 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001478 struct paging_request *req;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001479
1480 if (!vsub) {
1481 vty_out(vty, "%% No subscriber found for %s %s%s",
1482 argv[0], argv[1], VTY_NEWLINE);
1483 return CMD_WARNING;
1484 }
1485
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001486 req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL,
1487 NULL, NULL, "manual Paging from VTY");
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001488 if (req)
1489 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1490 else
1491 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1492
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001493 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001494 return req ? CMD_SUCCESS : CMD_WARNING;
1495}
1496
1497static int loop_by_char(uint8_t ch)
1498{
1499 switch (ch) {
1500 case 'a':
1501 return GSM414_LOOP_A;
1502 case 'b':
1503 return GSM414_LOOP_B;
1504 case 'c':
1505 return GSM414_LOOP_C;
1506 case 'd':
1507 return GSM414_LOOP_D;
1508 case 'e':
1509 return GSM414_LOOP_E;
1510 case 'f':
1511 return GSM414_LOOP_F;
1512 case 'i':
1513 return GSM414_LOOP_I;
1514 }
1515 return -1;
1516}
1517
1518DEFUN(subscriber_mstest_close,
1519 subscriber_mstest_close_cmd,
1520 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1521 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1522 "Close a TCH Loop inside the MS\n"
1523 "Loop Type A\n"
1524 "Loop Type B\n"
1525 "Loop Type C\n"
1526 "Loop Type D\n"
1527 "Loop Type E\n"
1528 "Loop Type F\n"
1529 "Loop Type I\n")
1530{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001531 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001532 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1533 const char *loop_str;
1534 int loop_mode;
1535
1536 if (!vsub) {
1537 vty_out(vty, "%% No subscriber found for %s %s%s",
1538 argv[0], argv[1], VTY_NEWLINE);
1539 return CMD_WARNING;
1540 }
1541
1542 loop_str = argv[2];
1543 loop_mode = loop_by_char(loop_str[0]);
1544
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001545 msc_a = msc_a_for_vsub(vsub, true);
1546 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001547 vty_out(vty, "%% An active connection is required for %s %s%s",
1548 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001549 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001550 return CMD_WARNING;
1551 }
1552
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001553 gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001554
1555 return CMD_SUCCESS;
1556}
1557
1558DEFUN(subscriber_mstest_open,
1559 subscriber_mstest_open_cmd,
1560 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1561 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1562 "Open a TCH Loop inside the MS\n")
1563{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001564 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001565 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1566
1567 if (!vsub) {
1568 vty_out(vty, "%% No subscriber found for %s %s%s",
1569 argv[0], argv[1], VTY_NEWLINE);
1570 return CMD_WARNING;
1571 }
1572
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001573 msc_a = msc_a_for_vsub(vsub, true);
1574 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001575 vty_out(vty, "%% An active connection is required for %s %s%s",
1576 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001577 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001578 return CMD_WARNING;
1579 }
1580
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001581 gsm0414_tx_open_loop_cmd(msc_a);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001582
1583 return CMD_SUCCESS;
1584}
1585
1586DEFUN(ena_subscr_expire,
1587 ena_subscr_expire_cmd,
1588 "subscriber " SUBSCR_TYPES " ID expire",
1589 SUBSCR_HELP "Expire the subscriber Now\n")
1590{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001591 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1592 argv[1]);
1593
1594 if (!vsub) {
1595 vty_out(vty, "%% No subscriber found for %s %s%s",
1596 argv[0], argv[1], VTY_NEWLINE);
1597 return CMD_WARNING;
1598 }
1599
1600 if (vlr_subscr_expire(vsub))
1601 vty_out(vty, "%% VLR released subscriber %s%s",
1602 vlr_subscr_name(vsub), VTY_NEWLINE);
1603
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001604 if (osmo_use_count_total(&vsub->use_count) > 1)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001605 vty_out(vty, "%% Subscriber %s is still in use,"
1606 " should be released soon%s",
1607 vlr_subscr_name(vsub), VTY_NEWLINE);
1608
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001609 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001610 return CMD_SUCCESS;
1611}
1612
1613static int scall_cbfn(unsigned int subsys, unsigned int signal,
1614 void *handler_data, void *signal_data)
1615{
1616 struct scall_signal_data *sigdata = signal_data;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001617 struct vty *vty = sigdata->vty;
1618
1619 if (!vty_is_active(vty))
1620 return 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001621
1622 switch (signal) {
1623 case S_SCALL_SUCCESS:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001624 vty_out(vty, "%% Silent call success%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001625 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001626 case S_SCALL_FAILED:
1627 vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE);
1628 break;
1629 case S_SCALL_DETACHED:
1630 vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001631 break;
1632 }
1633 return 0;
1634}
1635
1636DEFUN(show_stats,
1637 show_stats_cmd,
1638 "show statistics",
1639 SHOW_STR "Display network statistics\n")
1640{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001641 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001642 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1643 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1644 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001645 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001646 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001647 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001648 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001649 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001650 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1651 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001652 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001653 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001654 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1655 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001656 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001657 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001658 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1659 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1660 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001661 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001662 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001663 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1664 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001665 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001666 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001667 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1668 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001669 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001670 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001671 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current,
1672 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1673 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current
1674 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1675 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001676 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001677 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current,
1678 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1679 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current
1680 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1681 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001682 return CMD_SUCCESS;
1683}
1684
1685DEFUN(show_smsqueue,
1686 show_smsqueue_cmd,
1687 "show sms-queue",
1688 SHOW_STR "Display SMSqueue statistics\n")
1689{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001690 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001691 return CMD_SUCCESS;
1692}
1693
1694DEFUN(smsqueue_trigger,
1695 smsqueue_trigger_cmd,
1696 "sms-queue trigger",
1697 "SMS Queue\n" "Trigger sending messages\n")
1698{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001699 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001700 return CMD_SUCCESS;
1701}
1702
1703DEFUN(smsqueue_max,
1704 smsqueue_max_cmd,
1705 "sms-queue max-pending <1-500>",
1706 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1707{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001708 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001709 return CMD_SUCCESS;
1710}
1711
1712DEFUN(smsqueue_clear,
1713 smsqueue_clear_cmd,
1714 "sms-queue clear",
1715 "SMS Queue\n" "Clear the queue of pending SMS\n")
1716{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001717 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001718 return CMD_SUCCESS;
1719}
1720
1721DEFUN(smsqueue_fail,
1722 smsqueue_fail_cmd,
1723 "sms-queue max-failure <1-500>",
1724 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1725{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001726 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001727 return CMD_SUCCESS;
1728}
1729
1730
1731DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1732 "mncc-int", "Configure internal MNCC handler")
1733{
1734 vty->node = MNCC_INT_NODE;
1735
1736 return CMD_SUCCESS;
1737}
1738
1739static struct cmd_node mncc_int_node = {
1740 MNCC_INT_NODE,
1741 "%s(config-mncc-int)# ",
1742 1,
1743};
1744
1745static const struct value_string tchf_codec_names[] = {
1746 { GSM48_CMODE_SPEECH_V1, "fr" },
1747 { GSM48_CMODE_SPEECH_EFR, "efr" },
1748 { GSM48_CMODE_SPEECH_AMR, "amr" },
1749 { 0, NULL }
1750};
1751
1752static const struct value_string tchh_codec_names[] = {
1753 { GSM48_CMODE_SPEECH_V1, "hr" },
1754 { GSM48_CMODE_SPEECH_AMR, "amr" },
1755 { 0, NULL }
1756};
1757
1758static int config_write_mncc_int(struct vty *vty)
1759{
1760 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1761 vty_out(vty, " default-codec tch-f %s%s",
1762 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1763 VTY_NEWLINE);
1764 vty_out(vty, " default-codec tch-h %s%s",
1765 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1766 VTY_NEWLINE);
1767
1768 return CMD_SUCCESS;
1769}
1770
1771DEFUN(mnccint_def_codec_f,
1772 mnccint_def_codec_f_cmd,
1773 "default-codec tch-f (fr|efr|amr)",
1774 "Set default codec\n" "Codec for TCH/F\n"
1775 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1776{
1777 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1778
1779 return CMD_SUCCESS;
1780}
1781
1782DEFUN(mnccint_def_codec_h,
1783 mnccint_def_codec_h_cmd,
1784 "default-codec tch-h (hr|amr)",
1785 "Set default codec\n" "Codec for TCH/H\n"
1786 "Half-Rate\n" "Adaptive Multi-Rate\n")
1787{
1788 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1789
1790 return CMD_SUCCESS;
1791}
1792
1793
1794DEFUN(logging_fltr_imsi,
1795 logging_fltr_imsi_cmd,
1796 "logging filter imsi IMSI",
1797 LOGGING_STR FILTER_STR
1798 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1799{
1800 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001801 struct log_target *tgt = osmo_log_vty2tgt(vty);
1802 const char *imsi = argv[0];
1803
1804 if (!tgt)
1805 return CMD_WARNING;
1806
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001807 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001808
1809 if (!vlr_subscr) {
1810 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1811 argv[0], VTY_NEWLINE);
1812 return CMD_WARNING;
1813 }
1814
1815 log_set_filter_vlr_subscr(tgt, vlr_subscr);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001816 vlr_subscr_put(vlr_subscr, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001817 return CMD_SUCCESS;
1818}
1819
1820static struct cmd_node hlr_node = {
1821 HLR_NODE,
1822 "%s(config-hlr)# ",
1823 1,
1824};
1825
1826DEFUN(cfg_hlr, cfg_hlr_cmd,
1827 "hlr", "Configure connection to the HLR")
1828{
1829 vty->node = HLR_NODE;
1830 return CMD_SUCCESS;
1831}
1832
1833DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1834 "Remote GSUP address of the HLR\n"
1835 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1836{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001837 talloc_free((void*)gsmnet->gsup_server_addr_str);
1838 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1839 return CMD_SUCCESS;
1840}
1841
1842DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1843 "Remote GSUP port of the HLR\n"
1844 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1845{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001846 gsmnet->gsup_server_port = atoi(argv[0]);
1847 return CMD_SUCCESS;
1848}
1849
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001850DEFUN(cfg_hlr_ipa_name,
1851 cfg_hlr_ipa_name_cmd,
1852 "ipa-name NAME",
1853 "Set the IPA name of this MSC\n"
1854 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1855 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
1856 "The default is 'MSC-00-00-00-00-00-00'.\n")
1857{
1858 if (vty->type != VTY_FILE) {
1859 vty_out(vty, "The IPA name cannot be changed at run-time; "
1860 "It can only be set in the configuraton file.%s", VTY_NEWLINE);
1861 return CMD_WARNING;
1862 }
1863
1864 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
1865 return CMD_SUCCESS;
1866}
1867
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001868static int config_write_hlr(struct vty *vty)
1869{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001870 vty_out(vty, "hlr%s", VTY_NEWLINE);
1871 vty_out(vty, " remote-ip %s%s",
1872 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1873 vty_out(vty, " remote-port %u%s",
1874 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001875 if (gsmnet->msc_ipa_name)
1876 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001877 return CMD_SUCCESS;
1878}
1879
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001880void msc_vty_init(struct gsm_network *msc_network)
1881{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001882 OSMO_ASSERT(gsmnet == NULL);
1883 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001884
1885 osmo_stats_vty_add_cmds();
1886
1887 install_element(CONFIG_NODE, &cfg_net_cmd);
1888 install_node(&net_node, config_write_net);
1889 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1890 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1891 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1892 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1893 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
1894 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1895 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1896 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1897 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1898 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1899 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1900 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1901 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001902
1903 install_element(CONFIG_NODE, &cfg_msc_cmd);
1904 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001905 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01001906 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
1907 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02001908 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01001909 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07001910 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001911 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001912 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
1913 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01001914 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001915 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
1916 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01001917 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01001918 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07001919 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
1920 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +02001921 install_element(MSC_NODE, &cfg_msc_osmux_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001922 install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd);
1923
1924 neighbor_ident_vty_init(msc_network);
Philipp Maierfbf66102017-04-09 12:32:51 +02001925
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02001926 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001927#ifdef BUILD_IU
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001928 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 +02001929#endif
Harald Welte0df904d2018-12-03 11:00:04 +01001930 sgs_vty_init();
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001931
Stefan Sperling617ac802018-02-22 17:58:20 +01001932 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001933
1934 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
1935
1936 install_element_ve(&show_subscr_cmd);
1937 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01001938 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001939 install_element_ve(&show_msc_conn_cmd);
1940 install_element_ve(&show_msc_transaction_cmd);
1941
1942 install_element_ve(&sms_send_pend_cmd);
1943 install_element_ve(&sms_delete_expired_cmd);
1944
1945 install_element_ve(&subscriber_create_cmd);
1946 install_element_ve(&subscriber_send_sms_cmd);
1947 install_element_ve(&subscriber_silent_sms_cmd);
1948 install_element_ve(&subscriber_silent_call_start_cmd);
1949 install_element_ve(&subscriber_silent_call_stop_cmd);
1950 install_element_ve(&subscriber_ussd_notify_cmd);
1951 install_element_ve(&subscriber_mstest_close_cmd);
1952 install_element_ve(&subscriber_mstest_open_cmd);
1953 install_element_ve(&subscriber_paging_cmd);
1954 install_element_ve(&show_stats_cmd);
1955 install_element_ve(&show_smsqueue_cmd);
1956 install_element_ve(&logging_fltr_imsi_cmd);
1957
1958 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
1959 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
1960 install_element(ENABLE_NODE, &smsqueue_max_cmd);
1961 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
1962 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
1963 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001964 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001965
1966 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
1967 install_node(&mncc_int_node, config_write_mncc_int);
1968 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
1969 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
1970
1971 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
1972
1973 install_element(CONFIG_NODE, &cfg_hlr_cmd);
1974 install_node(&hlr_node, config_write_hlr);
1975 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
1976 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001977 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001978}