blob: 5bf9701634e773ac1987c1a9be0ea42b3a715872 [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"
Neels Hofmeyra4d7a762019-07-31 15:21:19 +0200151 "GSM A5 Air Interface Encryption."
152 " NOTE: as long as OsmoMSC lacks distinct configuration for 3G encryption,"
153 " 3G encryption is enabled exactly when any 2G encryption is enabled."
154 " Hence configuring only A5/0 here switches off 3G encryption.\n"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100155 "A5/n Algorithm Number\n"
156 "A5/n Algorithm Number\n"
157 "A5/n Algorithm Number\n"
158 "A5/n Algorithm Number\n")
159{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100160 unsigned int i;
161
162 gsmnet->a5_encryption_mask = 0;
163 for (i = 0; i < argc; i++)
164 gsmnet->a5_encryption_mask |= (1 << atoi(argv[i]));
165
166 return CMD_SUCCESS;
167}
168
169DEFUN(cfg_net_authentication,
170 cfg_net_authentication_cmd,
171 "authentication (optional|required)",
172 "Whether to enforce MS authentication in 2G\n"
173 "Allow MS to attach via 2G BSC without authentication\n"
174 "Always do authentication\n")
175{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100176 gsmnet->authentication_required = (argv[0][0] == 'r') ? true : false;
177
178 return CMD_SUCCESS;
179}
180
181DEFUN(cfg_net_rrlp_mode, cfg_net_rrlp_mode_cmd,
182 "rrlp mode (none|ms-based|ms-preferred|ass-preferred)",
183 "Radio Resource Location Protocol\n"
184 "Set the Radio Resource Location Protocol Mode\n"
185 "Don't send RRLP request\n"
186 "Request MS-based location\n"
187 "Request any location, prefer MS-based\n"
188 "Request any location, prefer MS-assisted\n")
189{
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700190 gsmnet->rrlp.mode = msc_rrlp_mode_parse(argv[0]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100191
192 return CMD_SUCCESS;
193}
194
195DEFUN(cfg_net_mm_info, cfg_net_mm_info_cmd,
196 "mm info (0|1)",
197 "Mobility Management\n"
198 "Send MM INFO after LOC UPD ACCEPT\n"
199 "Disable\n" "Enable\n")
200{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100201 gsmnet->send_mm_info = atoi(argv[0]);
202
203 return CMD_SUCCESS;
204}
205
206DEFUN(cfg_net_timezone,
207 cfg_net_timezone_cmd,
208 "timezone <-19-19> (0|15|30|45)",
209 "Set the Timezone Offset of the network\n"
210 "Timezone offset (hours)\n"
211 "Timezone offset (00 minutes)\n"
212 "Timezone offset (15 minutes)\n"
213 "Timezone offset (30 minutes)\n"
214 "Timezone offset (45 minutes)\n"
215 )
216{
217 struct gsm_network *net = vty->index;
218 int tzhr = atoi(argv[0]);
219 int tzmn = atoi(argv[1]);
220
221 net->tz.hr = tzhr;
222 net->tz.mn = tzmn;
223 net->tz.dst = 0;
224 net->tz.override = 1;
225
226 return CMD_SUCCESS;
227}
228
229DEFUN(cfg_net_timezone_dst,
230 cfg_net_timezone_dst_cmd,
231 "timezone <-19-19> (0|15|30|45) <0-2>",
232 "Set the Timezone Offset of the network\n"
233 "Timezone offset (hours)\n"
234 "Timezone offset (00 minutes)\n"
235 "Timezone offset (15 minutes)\n"
236 "Timezone offset (30 minutes)\n"
237 "Timezone offset (45 minutes)\n"
238 "DST offset (hours)\n"
239 )
240{
241 struct gsm_network *net = vty->index;
242 int tzhr = atoi(argv[0]);
243 int tzmn = atoi(argv[1]);
244 int tzdst = atoi(argv[2]);
245
246 net->tz.hr = tzhr;
247 net->tz.mn = tzmn;
248 net->tz.dst = tzdst;
249 net->tz.override = 1;
250
251 return CMD_SUCCESS;
252}
253
254DEFUN(cfg_net_no_timezone,
255 cfg_net_no_timezone_cmd,
256 "no timezone",
257 NO_STR
258 "Disable network timezone override, use system tz\n")
259{
260 struct gsm_network *net = vty->index;
261
262 net->tz.override = 0;
263
264 return CMD_SUCCESS;
265}
266
267DEFUN(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
268 "periodic location update <6-1530>",
269 "Periodic Location Updating Interval\n"
270 "Periodic Location Updating Interval\n"
271 "Periodic Location Updating Interval\n"
272 "Periodic Location Updating Interval in Minutes\n")
273{
274 struct gsm_network *net = vty->index;
275
276 net->t3212 = atoi(argv[0]) / 6;
277
278 return CMD_SUCCESS;
279}
280
281DEFUN(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
282 "no periodic location update",
283 NO_STR
284 "Periodic Location Updating Interval\n"
285 "Periodic Location Updating Interval\n"
286 "Periodic Location Updating Interval\n")
287{
288 struct gsm_network *net = vty->index;
289
290 net->t3212 = 0;
291
292 return CMD_SUCCESS;
293}
294
295static int config_write_net(struct vty *vty)
296{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100297 int i;
298
299 vty_out(vty, "network%s", VTY_NEWLINE);
300 vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
301 vty_out(vty, " mobile network code %s%s",
302 osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
303 vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
304 vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
305 vty_out(vty, " encryption a5");
306 for (i = 0; i < 8; i++) {
307 if (gsmnet->a5_encryption_mask & (1 << i))
308 vty_out(vty, " %u", i);
309 }
310 vty_out(vty, "%s", VTY_NEWLINE);
311 vty_out(vty, " authentication %s%s",
312 gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE);
Vadim Yanitskiy1b891302018-08-04 01:33:08 +0700313 vty_out(vty, " rrlp mode %s%s", msc_rrlp_mode_name(gsmnet->rrlp.mode),
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100314 VTY_NEWLINE);
315 vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
316 if (gsmnet->tz.override != 0) {
317 if (gsmnet->tz.dst)
318 vty_out(vty, " timezone %d %d %d%s",
319 gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
320 VTY_NEWLINE);
321 else
322 vty_out(vty, " timezone %d %d%s",
323 gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
324 }
325 if (gsmnet->t3212 == 0)
326 vty_out(vty, " no periodic location update%s", VTY_NEWLINE);
327 else
328 vty_out(vty, " periodic location update %u%s",
329 gsmnet->t3212 * 6, VTY_NEWLINE);
330
331 if (gsmnet->emergency.route_to_msisdn) {
332 vty_out(vty, " emergency-call route-to-msisdn %s%s",
333 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
334 }
335
336 return CMD_SUCCESS;
337}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200338
339static struct cmd_node msc_node = {
340 MSC_NODE,
341 "%s(config-msc)# ",
342 1,
343};
344
345DEFUN(cfg_msc, cfg_msc_cmd,
346 "msc", "Configure MSC options")
347{
348 vty->node = MSC_NODE;
349 return CMD_SUCCESS;
350}
351
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100352#define MNCC_STR "Configure Mobile Network Call Control\n"
353#define MNCC_GUARD_TIMEOUT_STR "Set global guard timer for mncc interface activity\n"
354#define MNCC_GUARD_TIMEOUT_VALUE_STR "guard timer value (sec.)\n"
355
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100356DEFUN(cfg_msc_mncc_internal,
357 cfg_msc_mncc_internal_cmd,
358 "mncc internal",
359 MNCC_STR "Use internal MNCC handler (default; changes need a program restart)\n")
360{
361 gsm_network_set_mncc_sock_path(gsmnet, NULL);
362 return CMD_SUCCESS;
363}
364
365DEFUN(cfg_msc_mncc_external,
366 cfg_msc_mncc_external_cmd,
367 "mncc external MNCC_SOCKET_PATH",
368 MNCC_STR "Use external MNCC handler (changes need a program restart)\n"
369 "File system path to create the MNCC unix domain socket at\n")
370{
371 gsm_network_set_mncc_sock_path(gsmnet, argv[0]);
372 return CMD_SUCCESS;
373}
374
Philipp Maier9ca7b312018-10-10 17:00:49 +0200375DEFUN(cfg_msc_mncc_guard_timeout,
376 cfg_msc_mncc_guard_timeout_cmd,
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100377 "mncc guard-timeout <0-255>",
378 MNCC_STR
379 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR)
Philipp Maier9ca7b312018-10-10 17:00:49 +0200380{
381 gsmnet->mncc_guard_timeout = atoi(argv[0]);
382 return CMD_SUCCESS;
383}
384
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100385ALIAS_DEPRECATED(cfg_msc_mncc_guard_timeout,
386 cfg_msc_deprecated_mncc_guard_timeout_cmd,
387 "mncc-guard-timeout <0-255>",
388 MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR);
389
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700390#define NCSS_STR "Configure call independent Supplementary Services\n"
391
392DEFUN(cfg_msc_ncss_guard_timeout,
393 cfg_msc_ncss_guard_timeout_cmd,
394 "ncss guard-timeout <0-255>",
395 NCSS_STR "Set guard timer for session activity\n"
396 "guard timer value (sec.), or 0 to disable\n")
397{
398 gsmnet->ncss_guard_timeout = atoi(argv[0]);
399 return CMD_SUCCESS;
400}
401
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200402DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
403 "assign-tmsi",
404 "Assign TMSI during Location Updating.\n")
405{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200406 gsmnet->vlr->cfg.assign_tmsi = true;
407 return CMD_SUCCESS;
408}
409
410DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
411 "no assign-tmsi",
412 NO_STR "Assign TMSI during Location Updating.\n")
413{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200414 gsmnet->vlr->cfg.assign_tmsi = false;
415 return CMD_SUCCESS;
416}
417
Philipp Maierfbf66102017-04-09 12:32:51 +0200418DEFUN(cfg_msc_cs7_instance_a,
419 cfg_msc_cs7_instance_a_cmd,
420 "cs7-instance-a <0-15>",
421 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
422{
Philipp Maierfbf66102017-04-09 12:32:51 +0200423 gsmnet->a.cs7_instance = atoi(argv[0]);
424 return CMD_SUCCESS;
425}
426
427DEFUN(cfg_msc_cs7_instance_iu,
428 cfg_msc_cs7_instance_iu_cmd,
429 "cs7-instance-iu <0-15>",
430 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
431{
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100432#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200433 gsmnet->iu.cs7_instance = atoi(argv[0]);
434 return CMD_SUCCESS;
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100435#else
436 vty_out(vty, "WARNING: 'cs7-instance-iu' without effect: built without Iu support%s",
437 VTY_NEWLINE);
438 return CMD_WARNING;
439#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200440}
441
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100442DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
443 "auth-tuple-max-reuse-count <-1-2147483647>",
444 "Configure authentication tuple re-use\n"
445 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
446{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100447 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
448 return CMD_SUCCESS;
449}
450
451DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
452 "auth-tuple-reuse-on-error (0|1)",
453 "Configure authentication tuple re-use when HLR is not responsive\n"
Oliver Smithd6e24fd2019-01-09 10:46:43 +0100454 "Never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
455 "If the HLR does not deliver new tuples, do re-use already available old ones.\n")
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100456{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100457 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
458 return CMD_SUCCESS;
459}
460
Oliver Smith0fec28a2018-12-14 10:52:52 +0100461DEFUN(cfg_msc_check_imei_rqd, cfg_msc_check_imei_rqd_cmd,
Oliver Smith03ded912019-05-02 10:40:50 +0200462 "check-imei-rqd (0|1|early)",
Oliver Smith0fec28a2018-12-14 10:52:52 +0100463 "Send each IMEI to the EIR to ask if it is permitted or not. The EIR is implemented as part of OsmoHLR, "
464 "and can optionally save the IMEI in the HLR.\n"
465 "Do not send IMEIs to the EIR\n"
Oliver Smith03ded912019-05-02 10:40:50 +0200466 "Send each IMEI to the EIR\n"
467 "Send each IMEI to the EIR, and do it at the start of the location update. This allows the EIR to receive the"
468 " 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 +0100469{
Oliver Smith03ded912019-05-02 10:40:50 +0200470 if (strcmp(argv[0], "0") == 0) {
471 gsmnet->vlr->cfg.check_imei_rqd = false;
472 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
473 } else if (strcmp(argv[0], "1") == 0) {
474 gsmnet->vlr->cfg.check_imei_rqd = true;
475 gsmnet->vlr->cfg.retrieve_imeisv_early = false;
476 } else if (strcmp(argv[0], "early") == 0) {
477 gsmnet->vlr->cfg.check_imei_rqd = true;
478 gsmnet->vlr->cfg.retrieve_imeisv_early = true;
479 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100480 return CMD_SUCCESS;
481}
482
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100483DEFUN(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
484 "paging response-timer (default|<1-65535>)",
485 "Configure Paging\n"
486 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
487 " BSS or RNC\n"
488 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
489 "Set paging timeout in seconds\n")
490{
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100491 if (!strcmp(argv[1], "default"))
492 gsmnet->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
493 else
494 gsmnet->paging_response_timer = atoi(argv[0]);
495 return CMD_SUCCESS;
496}
497
Harald Welte69c54a82018-02-09 20:41:14 +0100498DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
499 "emergency-call route-to-msisdn MSISDN",
500 "Configure Emergency Call Behaviour\n"
501 "MSISDN to which Emergency Calls are Dispatched\n"
502 "MSISDN (E.164 Phone Number)\n")
503{
Harald Welte69c54a82018-02-09 20:41:14 +0100504 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
505
506 return CMD_SUCCESS;
507}
508
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700509/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
510DEFUN(cfg_msc_sms_over_gsup, cfg_msc_sms_over_gsup_cmd,
511 "sms-over-gsup",
512 "Enable routing of SMS messages over GSUP\n")
513{
514 gsmnet->sms_over_gsup = true;
515 return CMD_SUCCESS;
516}
517
518/* TODO: to be deprecated as soon as we rip SMS handling out (see OS#3587) */
519DEFUN(cfg_msc_no_sms_over_gsup, cfg_msc_no_sms_over_gsup_cmd,
520 "no sms-over-gsup",
521 NO_STR "Disable routing of SMS messages over GSUP\n")
522{
523 gsmnet->sms_over_gsup = false;
524 return CMD_SUCCESS;
525}
526
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100527/* FIXME: This should rather be in the form of
528 * handover-number range 001234xxx
529 * and
530 * handover-number range 001234xxx FIRST LAST
531 */
532DEFUN(cfg_msc_handover_number_range, cfg_msc_handover_number_range_cmd,
533 "handover-number range MSISDN_FIRST MSISDN_LAST",
534 "Configure a range of MSISDN to be assigned to incoming inter-MSC Handovers for call forwarding.\n"
535 "Configure a handover number range\n"
536 "First Handover Number MSISDN\n"
537 "Last Handover Number MSISDN\n")
538{
539 char *endp;
540 uint64_t range_start;
541 uint64_t range_end;
542
543 /* FIXME leading zeros?? */
544
545 errno = 0;
546 range_start = strtoull(argv[0], &endp, 10);
547 if (errno || *endp != '\0') {
548 vty_out(vty, "%% Error parsing handover-number range start: %s%s",
549 argv[0], VTY_NEWLINE);
550 return CMD_WARNING;
551 }
552
553 errno = 0;
554 range_end = strtoull(argv[1], &endp, 10);
555 if (errno || *endp != '\0') {
556 vty_out(vty, "%% Error parsing handover-number range end: %s%s",
557 argv[1], VTY_NEWLINE);
558 return CMD_WARNING;
559 }
560
561 if (range_start > range_end) {
562 vty_out(vty, "%% Error: handover-number range end must be > than the range start, but"
563 " %"PRIu64" > %"PRIu64"%s", range_start, range_end, VTY_NEWLINE);
564 return CMD_WARNING;
565 }
566
567 gsmnet->handover_number.range_start = range_start;
568 gsmnet->handover_number.range_end = range_end;
569 return CMD_SUCCESS;
570}
571
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200572#define OSMUX_STR "RTP multiplexing\n"
573DEFUN(cfg_msc_osmux,
574 cfg_msc_osmux_cmd,
575 "osmux (on|off|only)",
576 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
577{
578 if (strcmp(argv[0], "off") == 0)
579 gsmnet->use_osmux = OSMUX_USAGE_OFF;
580 else if (strcmp(argv[0], "on") == 0)
581 gsmnet->use_osmux = OSMUX_USAGE_ON;
582 else if (strcmp(argv[0], "only") == 0)
583 gsmnet->use_osmux = OSMUX_USAGE_ONLY;
584
585 return CMD_SUCCESS;
586}
587
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200588static int config_write_msc(struct vty *vty)
589{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200590 vty_out(vty, "msc%s", VTY_NEWLINE);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100591 if (gsmnet->mncc_sock_path)
592 vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE);
Neels Hofmeyr05c56802018-12-05 01:07:03 +0100593 vty_out(vty, " mncc guard-timeout %i%s",
Philipp Maier9ca7b312018-10-10 17:00:49 +0200594 gsmnet->mncc_guard_timeout, VTY_NEWLINE);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +0700595 vty_out(vty, " ncss guard-timeout %i%s",
596 gsmnet->ncss_guard_timeout, VTY_NEWLINE);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200597 vty_out(vty, " %sassign-tmsi%s",
598 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
599
Philipp Maierfbf66102017-04-09 12:32:51 +0200600 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
601 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100602#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200603 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
604 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100605#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200606
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100607 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
608 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
609 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
610 VTY_NEWLINE);
611 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
612 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
613 VTY_NEWLINE);
614
Oliver Smith03ded912019-05-02 10:40:50 +0200615 if (gsmnet->vlr->cfg.check_imei_rqd) {
616 if (gsmnet->vlr->cfg.retrieve_imeisv_early)
617 vty_out(vty, " check-imei-rqd early%s", VTY_NEWLINE);
618 else
619 vty_out(vty, " check-imei-rqd 1%s", VTY_NEWLINE);
620 }
Oliver Smith0fec28a2018-12-14 10:52:52 +0100621
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100622 if (gsmnet->paging_response_timer != MSC_PAGING_RESPONSE_TIMER_DEFAULT)
623 vty_out(vty, " paging response-timer %u%s", gsmnet->paging_response_timer, VTY_NEWLINE);
624
Harald Welte69c54a82018-02-09 20:41:14 +0100625 if (gsmnet->emergency.route_to_msisdn) {
626 vty_out(vty, " emergency-call route-to-msisdn %s%s",
627 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
628 }
629
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +0700630 if (gsmnet->sms_over_gsup)
631 vty_out(vty, " sms-over-gsup%s", VTY_NEWLINE);
632
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100633 if (gsmnet->handover_number.range_start || gsmnet->handover_number.range_end)
634 vty_out(vty, " handover-number range %"PRIu64" %"PRIu64"%s",
635 gsmnet->handover_number.range_start, gsmnet->handover_number.range_end,
636 VTY_NEWLINE);
637
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +0200638 if (gsmnet->use_osmux != OSMUX_USAGE_OFF) {
639 vty_out(vty, " osmux %s%s", gsmnet->use_osmux == OSMUX_USAGE_ON ? "on" : "only",
640 VTY_NEWLINE);
641 }
642
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200643 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200644#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200645 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200646#endif
647
Neels Hofmeyr880b9502019-05-09 02:01:55 +0200648 neighbor_ident_vty_write(vty);
649
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200650 return CMD_SUCCESS;
651}
652
Maxc51609a2018-11-09 17:13:00 +0100653DEFUN(show_bsc, show_bsc_cmd,
654 "show bsc", SHOW_STR "BSC\n")
655{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100656 struct ran_peer *rp;
657 llist_for_each_entry(rp, &gsmnet->a.sri->ran_peers, entry) {
658 vty_out(vty, "BSC %s %s%s",
659 osmo_sccp_inst_addr_name(gsmnet->a.sri->sccp, &rp->peer_addr),
660 osmo_fsm_inst_state_name(rp->fi),
661 VTY_NEWLINE);
Maxc51609a2018-11-09 17:13:00 +0100662 }
663
664 return CMD_SUCCESS;
665}
666
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100667static const char *get_trans_proto_str(const struct gsm_trans *trans)
668{
669 static char buf[256];
670
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100671 switch (trans->type) {
672 case TRANS_CC:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100673 snprintf(buf, sizeof(buf), "%s %4u %4u",
674 gsm48_cc_state_name(trans->cc.state),
675 trans->cc.Tcurrent,
676 trans->cc.T308_second);
677 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100678 case TRANS_SMS:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700679 snprintf(buf, sizeof(buf), "CP:%s RP:%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100680 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
681 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
682 break;
683 default:
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700684 return NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100685 }
686
687 return buf;
688}
689
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700690/* Prefix a given format string with a given amount of spaces */
691#define MSC_VTY_DUMP(vty, offset, fmt, args...) \
692 vty_out(vty, "%*s" fmt, offset, "", ##args)
693
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200694/* Print value of a named flag, prefixed with a given amount of spaces */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700695#define MSC_VTY_DUMP_FLAG(vty, offset, name, flag) \
696 MSC_VTY_DUMP(vty, offset + 2, "%s: %*s%s%s", \
697 name, 30 - (int)strlen(name), "", \
698 flag ? "true" : "false", \
699 VTY_NEWLINE)
700
701enum msc_vty_dump_flags {
702 MSC_VTY_DUMP_F_SUBSCR = (1 << 0),
703 MSC_VTY_DUMP_F_CONNECTION = (1 << 1),
704 MSC_VTY_DUMP_F_TRANSACTION = (1 << 2),
705};
706
707static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans,
708 int offset, uint8_t dump_flags)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100709{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700710 const char *proto_str;
711
712 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
713 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
714 vlr_subscr_name(msc_a_vsub(trans->msc_a)),
715 VTY_NEWLINE);
716 }
717
718 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
Neels Hofmeyr4014e482019-06-21 02:00:58 +0200719 /* (If msc_a exists, there *must* be a non-null msc_a->c.msub) */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700720 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
721 trans->msc_a ? msub_ran_conn_name(trans->msc_a->c.msub)
722 : "(not established)",
723 VTY_NEWLINE);
724 }
725
726 MSC_VTY_DUMP(vty, offset, "Unique (global) identifier: 0x%08x%s",
727 trans->callref, VTY_NEWLINE);
728 MSC_VTY_DUMP(vty, offset, "GSM 04.07 identifier (%s): %u%s",
729 (trans->transaction_id & 0x08) ? "MO" : "MT",
730 trans->transaction_id,
731 VTY_NEWLINE);
732
733 MSC_VTY_DUMP(vty, offset, "Type: %s%s",
734 trans_type_name(trans->type),
735 VTY_NEWLINE);
736
737 if ((proto_str = get_trans_proto_str(trans))) {
738 MSC_VTY_DUMP(vty, offset, "Protocol specific: %s%s",
739 proto_str, VTY_NEWLINE);
740 }
741}
742
743static void vty_dump_one_conn(struct vty *vty, const struct msub *msub,
744 int offset, uint8_t dump_flags)
745{
746 struct vlr_subscr *vsub = msub_vsub(msub);
747 struct msc_a *msc_a = msub_msc_a(msub);
748 char buf[128];
749
750 if (dump_flags & MSC_VTY_DUMP_F_SUBSCR) {
751 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
752 MSC_VTY_DUMP(vty, offset, "Subscriber: %s%s",
753 vlr_subscr_name(vsub),
754 VTY_NEWLINE);
755 }
756
757 MSC_VTY_DUMP(vty, offset, "RAN connection: %s%s",
758 msub_ran_conn_name(msub),
759 VTY_NEWLINE);
760 MSC_VTY_DUMP(vty, offset, "RAN connection state: %s%s",
761 osmo_fsm_inst_state_name(msc_a->c.fi),
762 VTY_NEWLINE);
763
764 if (vsub) {
765 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
766 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
767 VTY_NEWLINE);
768 }
769
770 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
771 osmo_use_count_total(&msc_a->use_count),
772 VTY_NEWLINE);
773 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
774 osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count),
775 VTY_NEWLINE);
776
777 /* Transactions of this connection */
778 if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
779 struct gsm_trans *trans;
780 unsigned int i = 0;
781
782 /* Both subscriber and connection info is already printed */
783 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_CONNECTION;
784 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
785
786 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
787 if (trans->msc_a != msc_a)
788 continue;
789 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
790 i++, VTY_NEWLINE);
791 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
792 }
793 }
794}
795
796static void vty_dump_one_subscr(struct vty *vty, struct vlr_subscr *vsub,
797 int offset, uint8_t dump_flags)
798{
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700799 struct gsm_network *net;
800 struct timespec now;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700801 char buf[128];
802
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700803 if (vsub->name[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700804 MSC_VTY_DUMP(vty, offset, "Name: '%s'%s",
805 vsub->name, VTY_NEWLINE);
806 }
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700807 if (vsub->msisdn[0] != '\0') {
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700808 MSC_VTY_DUMP(vty, offset, "MSISDN: %s%s",
809 vsub->msisdn, VTY_NEWLINE);
810 }
811
812 MSC_VTY_DUMP(vty, offset, "LAC / cell ID: %u / %u%s",
813 vsub->cgi.lai.lac, vsub->cgi.cell_identity,
814 VTY_NEWLINE);
815 MSC_VTY_DUMP(vty, offset, "RAN type: %s%s",
816 osmo_rat_type_name(vsub->cs.attached_via_ran),
817 VTY_NEWLINE);
818
819 MSC_VTY_DUMP(vty, offset, "IMSI: %s%s",
820 vsub->imsi, VTY_NEWLINE);
821 if (vsub->tmsi != GSM_RESERVED_TMSI) {
822 MSC_VTY_DUMP(vty, offset, "TMSI: %08X%s",
823 vsub->tmsi, VTY_NEWLINE);
824 }
825 if (vsub->tmsi_new != GSM_RESERVED_TMSI) {
826 MSC_VTY_DUMP(vty, offset, "New TMSI: %08X%s",
827 vsub->tmsi_new, VTY_NEWLINE);
828 }
829 if (vsub->imei[0] != '\0') {
830 MSC_VTY_DUMP(vty, offset, "IMEI: %s%s",
831 vsub->imei, VTY_NEWLINE);
832 }
833 if (vsub->imeisv[0] != '\0') {
834 MSC_VTY_DUMP(vty, offset, "IMEISV: %s%s",
835 vsub->imeisv, VTY_NEWLINE);
836 }
837
838 MSC_VTY_DUMP(vty, offset, "Flags: %s", VTY_NEWLINE);
839 MSC_VTY_DUMP_FLAG(vty, offset, "IMSI detached",
840 vsub->imsi_detached_flag);
841 MSC_VTY_DUMP_FLAG(vty, offset, "Conf. by radio contact",
842 vsub->conf_by_radio_contact_ind);
843 MSC_VTY_DUMP_FLAG(vty, offset, "Subscr. data conf. by HLR",
844 vsub->sub_dataconf_by_hlr_ind);
845 MSC_VTY_DUMP_FLAG(vty, offset, "Location conf. in HLR",
846 vsub->loc_conf_in_hlr_ind);
847 MSC_VTY_DUMP_FLAG(vty, offset, "Subscriber dormant",
848 vsub->dormant_ind);
849 MSC_VTY_DUMP_FLAG(vty, offset, "Received cancel location",
850 vsub->cancel_loc_rx);
851 MSC_VTY_DUMP_FLAG(vty, offset, "MS not reachable",
852 vsub->ms_not_reachable_flag);
853 MSC_VTY_DUMP_FLAG(vty, offset, "LA allowed",
854 vsub->la_allowed);
855
856 if (vsub->last_tuple) {
857 struct vlr_auth_tuple *t = vsub->last_tuple;
858 MSC_VTY_DUMP(vty, offset, "A3A8 last tuple (used %d times): %s",
859 t->use_count, VTY_NEWLINE);
860 MSC_VTY_DUMP(vty, offset + 2, "seq # : %d%s",
861 t->key_seq, VTY_NEWLINE);
862 MSC_VTY_DUMP(vty, offset + 2, "RAND : %s%s",
863 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
864 VTY_NEWLINE);
865 MSC_VTY_DUMP(vty, offset + 2, "SRES : %s%s",
866 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
867 VTY_NEWLINE);
868 MSC_VTY_DUMP(vty, offset + 2, "Kc : %s%s",
869 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
870 VTY_NEWLINE);
871 }
872
Vadim Yanitskiy09ce3dc2019-07-09 00:34:29 +0700873 /* XXX move t3212 into struct vlr_instance? */
874 net = vsub->vlr->user_ctx;
875 if (!net->t3212) {
876 MSC_VTY_DUMP(vty, offset, "Expires: never (T3212 is disabled)%s",
877 VTY_NEWLINE);
878 } else if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) {
879 MSC_VTY_DUMP(vty, offset, "Expires: never%s",
880 VTY_NEWLINE);
881 } else if (osmo_clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
882 MSC_VTY_DUMP(vty, offset, "Expires: in %ld min %ld sec%s",
883 (vsub->expire_lu - now.tv_sec) / 60,
884 (vsub->expire_lu - now.tv_sec) % 60,
885 VTY_NEWLINE);
886 }
887
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700888 MSC_VTY_DUMP(vty, offset, "Paging: %s paging for %d requests%s",
889 vsub->cs.is_paging ? "is" : "not",
890 llist_count(&vsub->cs.requests),
891 VTY_NEWLINE);
892
893 /* SGs related */
894 MSC_VTY_DUMP(vty, offset, "SGs-state: %s%s",
895 osmo_fsm_inst_state_name(vsub->sgs_fsm),
896 VTY_NEWLINE);
897 MSC_VTY_DUMP(vty, offset, "SGs-MME: %s%s",
Vadim Yanitskiydcf28682019-05-29 22:34:13 +0700898 vsub->sgs.mme_name[0] != '\0' ? vsub->sgs.mme_name : "(none)",
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700899 VTY_NEWLINE);
900
901 MSC_VTY_DUMP(vty, offset, "Use count total: %d%s",
902 osmo_use_count_total(&vsub->use_count),
903 VTY_NEWLINE);
904 MSC_VTY_DUMP(vty, offset, "Use count: %s%s",
905 osmo_use_count_name_buf(buf, sizeof(buf), &vsub->use_count),
906 VTY_NEWLINE);
907
908 /* Connection(s) and/or transactions of this subscriber */
909 if (dump_flags & MSC_VTY_DUMP_F_CONNECTION) {
910 struct msub *msub = msub_for_vsub(vsub);
911 if (!msub)
912 return;
913
914 /* Subscriber info is already printed */
915 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
916
917 MSC_VTY_DUMP(vty, offset, "Connection: %s", VTY_NEWLINE);
918 vty_dump_one_conn(vty, msub, offset + 2, dump_flags);
919 } else if (dump_flags & MSC_VTY_DUMP_F_TRANSACTION) {
920 struct gsm_trans *trans;
921 unsigned int i = 0;
922
923 /* Subscriber info is already printed */
924 dump_flags = dump_flags &~ MSC_VTY_DUMP_F_SUBSCR;
925 /* Do not print connection info, but mention it */
926 dump_flags |= MSC_VTY_DUMP_F_CONNECTION;
927
928 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
929 if (trans->vsub != vsub)
930 continue;
931 MSC_VTY_DUMP(vty, offset, "Transaction #%02u: %s",
932 i++, VTY_NEWLINE);
933 vty_dump_one_trans(vty, trans, offset + 2, dump_flags);
934 }
935 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100936}
937
938DEFUN(show_msc_transaction, show_msc_transaction_cmd,
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700939 "show transaction",
940 SHOW_STR "Transactions\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100941{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100942 struct gsm_trans *trans;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700943 uint8_t flags = 0x00;
944 unsigned int i = 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100945
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700946 flags |= MSC_VTY_DUMP_F_CONNECTION;
947 flags |= MSC_VTY_DUMP_F_SUBSCR;
948
949 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
950 vty_out(vty, " Transaction #%02u: %s", i++, VTY_NEWLINE);
951 vty_dump_one_trans(vty, trans, 4, flags);
952 }
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100953
954 return CMD_SUCCESS;
955}
956
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700957DEFUN(show_msc_conn, show_msc_conn_cmd,
958 "show connection [trans]",
959 SHOW_STR "Subscriber Connections\n"
960 "Show child transactions of each connection\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100961{
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700962 uint8_t flags = 0x00;
963 unsigned int i = 0;
964 struct msub *msub;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100965
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700966 if (argc > 0)
967 flags |= MSC_VTY_DUMP_F_TRANSACTION;
968 flags |= MSC_VTY_DUMP_F_SUBSCR;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100969
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700970 llist_for_each_entry(msub, &msub_list, entry) {
971 vty_out(vty, " Connection #%02u: %s", i++, VTY_NEWLINE);
972 vty_dump_one_conn(vty, msub, 4, flags);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100973 }
974
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700975 return CMD_SUCCESS;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100976}
977
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700978#define SUBSCR_FLAGS "[(conn|trans|conn+trans)]"
979#define SUBSCR_FLAGS_HELP \
980 "Show child connections\n" \
981 "Show child transactions\n" \
982 "Show child connections and transactions\n"
983
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100984/* Subscriber */
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700985DEFUN(show_subscr_cache, show_subscr_cache_cmd,
986 "show subscriber cache " SUBSCR_FLAGS,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100987 SHOW_STR "Show information about subscribers\n"
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700988 "Display contents of subscriber cache\n"
989 SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100990{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100991 struct vlr_subscr *vsub;
Vadim Yanitskiy80149172019-05-16 06:13:29 +0700992 unsigned int count = 0;
993 uint8_t flags = 0x00;
994 unsigned int i = 0;
995
996 if (argc && strcmp(argv[0], "conn") == 0)
997 flags |= MSC_VTY_DUMP_F_CONNECTION;
998 else if (argc && strcmp(argv[0], "trans") == 0)
999 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1000 else if (argc && strcmp(argv[0], "conn+trans") == 0)
1001 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001002
1003 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
1004 if (++count > 100) {
1005 vty_out(vty, "%% More than %d subscribers in cache,"
1006 " stopping here.%s", count-1, VTY_NEWLINE);
1007 break;
1008 }
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001009 vty_out(vty, " Subscriber #%02u: %s", i++, VTY_NEWLINE);
1010 vty_dump_one_subscr(vty, vsub, 4, flags);
Harald Welte69c54a82018-02-09 20:41:14 +01001011 }
1012
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001013 return CMD_SUCCESS;
1014}
1015
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001016DEFUN(sms_send_pend,
1017 sms_send_pend_cmd,
1018 "sms send pending",
1019 "SMS related commands\n" "SMS Sending related commands\n"
1020 "Send all pending SMS")
1021{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001022 struct gsm_sms *sms;
1023 unsigned long long sms_id = 0;
1024
1025 while (1) {
1026 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1027 if (!sms)
1028 break;
1029
1030 if (sms->receiver)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001031 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001032
1033 sms_id = sms->id + 1;
1034 }
1035
1036 return CMD_SUCCESS;
1037}
1038
1039DEFUN(sms_delete_expired,
1040 sms_delete_expired_cmd,
1041 "sms delete expired",
1042 "SMS related commands\n" "SMS Database related commands\n"
1043 "Delete all expired SMS")
1044{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001045 struct gsm_sms *sms;
1046 unsigned long long sms_id = 0;
1047 long long num_deleted = 0;
1048
1049 while (1) {
1050 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
1051 if (!sms)
1052 break;
1053
1054 /* Skip SMS which are currently queued for sending. */
1055 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
1056 continue;
1057
1058 /* Expiration check is performed by the DB layer. */
1059 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
1060 num_deleted++;
1061
1062 sms_id = sms->id + 1;
1063 }
1064
1065 if (num_deleted == 0) {
1066 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
1067 return CMD_WARNING;
1068 }
1069
1070 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
1071 return CMD_SUCCESS;
1072}
1073
1074static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +02001075 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001076 char *str, uint8_t tp_pid)
1077{
1078 struct gsm_network *net = receiver->vlr->user_ctx;
1079 struct gsm_sms *sms;
1080
Harald Welte39b55482018-04-09 19:19:33 +02001081 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001082 sms->protocol_id = tp_pid;
1083
1084 /* store in database for the queue */
1085 if (db_sms_store(sms) != 0) {
1086 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
1087 sms_free(sms);
1088 return CMD_WARNING;
1089 }
1090 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
1091
1092 sms_free(sms);
1093 sms_queue_trigger(net->sms_queue);
1094 return CMD_SUCCESS;
1095}
1096
1097static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
1098 const char *type,
1099 const char *id)
1100{
1101 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001102 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001103 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001104 return vlr_subscr_find_by_imsi(gsmnet->vlr, id, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001105 else if (!strcmp(type, "tmsi"))
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001106 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id), VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001107
1108 return NULL;
1109}
1110#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
1111#define SUBSCR_HELP "Operations on a Subscriber\n" \
1112 "Identify subscriber by MSISDN (phone number)\n" \
1113 "Legacy alias for 'msisdn'\n" \
1114 "Identify subscriber by IMSI\n" \
1115 "Identify subscriber by TMSI\n" \
Vadim Yanitskiy3ccd8232019-05-16 01:35:23 +07001116 "Legacy alias for 'imsi'\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001117 "Identifier for the subscriber\n"
1118
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001119DEFUN(show_subscr, show_subscr_cmd,
1120 "show subscriber " SUBSCR_TYPES " ID " SUBSCR_FLAGS,
1121 SHOW_STR SUBSCR_HELP SUBSCR_FLAGS_HELP)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001122{
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001123 struct vlr_subscr *vsub;
1124 uint8_t flags = 0x00;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001125
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001126 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001127 if (!vsub) {
1128 vty_out(vty, "%% No subscriber found for %s %s%s",
1129 argv[0], argv[1], VTY_NEWLINE);
1130 return CMD_WARNING;
1131 }
1132
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001133 /* In the vty output to the user, exclude this local use count added by vlr_subscr_get() in get_vsub_by_argv().
1134 * This works, because: for get_vsub_by_argv() to succeed, there *must* have been at least one use count before
1135 * 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 +01001136 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001137
Vadim Yanitskiy80149172019-05-16 06:13:29 +07001138 if (argc > 2 && strcmp(argv[2], "conn") == 0)
1139 flags |= MSC_VTY_DUMP_F_CONNECTION;
1140 else if (argc > 2 && strcmp(argv[2], "trans") == 0)
1141 flags |= MSC_VTY_DUMP_F_TRANSACTION;
1142 else if (argc > 2 && strcmp(argv[2], "conn+trans") == 0)
1143 flags |= MSC_VTY_DUMP_F_CONNECTION | MSC_VTY_DUMP_F_TRANSACTION;
1144
1145 vty_out(vty, " Subscriber: %s", VTY_NEWLINE);
1146 vty_dump_one_subscr(vty, vsub, 4, flags);
Neels Hofmeyr14c6f3e2018-12-12 04:02:29 +01001147
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001148 return CMD_SUCCESS;
1149}
1150
1151DEFUN(subscriber_create,
1152 subscriber_create_cmd,
1153 "subscriber create imsi ID",
1154 "Operations on a Subscriber\n" \
1155 "Create new subscriber\n" \
1156 "Identify the subscriber by his IMSI\n" \
1157 "Identifier for the subscriber\n")
1158{
1159 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
1160 VTY_NEWLINE);
1161 return CMD_WARNING;
1162}
1163
1164DEFUN(subscriber_send_pending_sms,
1165 subscriber_send_pending_sms_cmd,
1166 "subscriber " SUBSCR_TYPES " ID sms pending-send",
1167 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
1168{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001169 struct vlr_subscr *vsub;
1170 struct gsm_sms *sms;
1171
1172 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1173 if (!vsub) {
1174 vty_out(vty, "%% No subscriber found for %s %s%s",
1175 argv[0], argv[1], VTY_NEWLINE);
1176 return CMD_WARNING;
1177 }
1178
1179 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
1180 if (sms)
Vadim Yanitskiy24e025e2018-11-22 15:42:39 +07001181 gsm411_send_sms(gsmnet, sms->receiver, sms);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001182
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001183 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001184
1185 return CMD_SUCCESS;
1186}
1187
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001188DEFUN(subscriber_sms_delete_all,
1189 subscriber_sms_delete_all_cmd,
1190 "subscriber " SUBSCR_TYPES " ID sms delete-all",
1191 SUBSCR_HELP "SMS Operations\n"
1192 "Delete all SMS to be delivered to this subscriber"
1193 " -- WARNING: the SMS data for all unsent SMS for this subscriber"
1194 " WILL BE LOST.\n")
1195{
1196 struct vlr_subscr *vsub;
1197
1198 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1199 if (!vsub) {
1200 vty_out(vty, "%% No subscriber found for %s %s%s",
1201 argv[0], argv[1], VTY_NEWLINE);
1202 return CMD_WARNING;
1203 }
1204
1205 db_sms_delete_by_msisdn(vsub->msisdn);
1206
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001207 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001208
1209 return CMD_SUCCESS;
1210}
1211
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001212DEFUN(subscriber_send_sms,
1213 subscriber_send_sms_cmd,
1214 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1215 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1216{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001217 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001218 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001219 char *str;
1220 int rc;
1221
1222 if (!vsub) {
1223 vty_out(vty, "%% No subscriber found for %s %s%s",
1224 argv[0], argv[1], VTY_NEWLINE);
1225 rc = CMD_WARNING;
1226 goto err;
1227 }
1228
Harald Welte39b55482018-04-09 19:19:33 +02001229 if (!strcmp(argv[2], "msisdn"))
1230 sender_msisdn = argv[3];
1231 else {
1232 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1233 if (!sender) {
1234 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1235 rc = CMD_WARNING;
1236 goto err;
1237 }
1238 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001239 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001240 }
1241
1242 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001243 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001244 talloc_free(str);
1245
1246err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001247 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001248 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001249
1250 return rc;
1251}
1252
1253DEFUN(subscriber_silent_sms,
1254 subscriber_silent_sms_cmd,
1255
1256 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
1257 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
1258{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001259 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +02001260 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001261 char *str;
1262 int rc;
1263
1264 if (!vsub) {
1265 vty_out(vty, "%% No subscriber found for %s %s%s",
1266 argv[0], argv[1], VTY_NEWLINE);
1267 rc = CMD_WARNING;
1268 goto err;
1269 }
1270
Harald Welte39b55482018-04-09 19:19:33 +02001271 if (!strcmp(argv[2], "msisdn")) {
1272 sender_msisdn = argv[3];
1273 } else {
1274 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
1275 if (!sender) {
1276 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
1277 rc = CMD_WARNING;
1278 goto err;
1279 }
1280 sender_msisdn = sender->msisdn;
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001281 vlr_subscr_put(sender, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001282 }
1283
1284 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +02001285 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001286 talloc_free(str);
1287
1288err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001289 if (vsub)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001290 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001291
1292 return rc;
1293}
1294
Sylvain Munaut93558302019-02-14 20:13:08 +01001295#define CHAN_TYPES "(any|tch/f|tch/h|tch/any|sdcch)"
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001296#define CHAN_TYPE_HELP \
1297 "Any channel\n" \
1298 "TCH/F channel\n" \
Sylvain Munaut93558302019-02-14 20:13:08 +01001299 "TCH/H channel\n" \
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001300 "Any TCH channel\n" \
1301 "SDCCH channel\n"
1302
Sylvain Munaut93558302019-02-14 20:13:08 +01001303#define CHAN_MODES "(signalling|speech-hr|speech-fr|speech-efr|speech-amr)"
1304#define CHAN_MODE_HELP \
1305 "Signalling only\n" \
1306 "Speech with HR codec\n" \
1307 "Speech with FR codec\n" \
1308 "Speech with EFR codec\n" \
1309 "Speech with AMR codec\n"
1310
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001311DEFUN(subscriber_silent_call_start,
1312 subscriber_silent_call_start_cmd,
Sylvain Munaut93558302019-02-14 20:13:08 +01001313 "subscriber " SUBSCR_TYPES " ID silent-call start " CHAN_TYPES " " CHAN_MODES " [IP] [<0-65535>]",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001314 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
Sylvain Munaut93558302019-02-14 20:13:08 +01001315 CHAN_TYPE_HELP CHAN_MODE_HELP
1316 "Target IP for RTP traffic (default 127.0.0.1)\n"
1317 "Target port for RTP traffic (default: 4000)\n")
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001318{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001319 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Sylvain Munaut93558302019-02-14 20:13:08 +01001320 struct gsm0808_channel_type ct;
1321 const char *ip;
1322 uint16_t port;
1323 int rc, speech;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001324
1325 if (!vsub) {
1326 vty_out(vty, "%% No subscriber found for %s %s%s",
1327 argv[0], argv[1], VTY_NEWLINE);
1328 return CMD_WARNING;
1329 }
1330
Sylvain Munaut93558302019-02-14 20:13:08 +01001331 memset(&ct, 0x00, sizeof(ct));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001332
Sylvain Munaut93558302019-02-14 20:13:08 +01001333 if (!strcmp(argv[3], "signalling")) {
1334 ct.ch_indctr = GSM0808_CHAN_SIGN;
1335 ct.perm_spch[0] = 0; /* Spare but required */
1336 ct.perm_spch_len = 1;
1337 } else if (!strcmp(argv[3], "speech-hr")) {
1338 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1339 ct.perm_spch[0] = GSM0808_PERM_HR1;
1340 ct.perm_spch_len = 1;
1341 } else if (!strcmp(argv[3], "speech-fr")) {
1342 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1343 ct.perm_spch[0] = GSM0808_PERM_FR1;
1344 ct.perm_spch_len = 1;
1345 } else if (!strcmp(argv[3], "speech-efr")) {
1346 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1347 ct.perm_spch[0] = GSM0808_PERM_FR2;
1348 ct.perm_spch_len = 1;
1349 } else if (!strcmp(argv[3], "speech-amr")) {
1350 ct.ch_indctr = GSM0808_CHAN_SPEECH;
1351 ct.perm_spch[0] = GSM0808_PERM_FR3;
1352 ct.perm_spch[1] = GSM0808_PERM_HR3;
1353 ct.perm_spch_len = 2;
1354 }
1355
1356 speech = ct.ch_indctr == GSM0808_CHAN_SPEECH;
1357
1358 if (!strcmp(argv[2], "tch/f"))
1359 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_BM : GSM0808_SIGN_FULL_BM;
1360 else if (!strcmp(argv[2], "tch/h"))
1361 ct.ch_rate_type = speech ? GSM0808_SPEECH_HALF_LM : GSM0808_SIGN_HALF_LM;
1362 else if (!strcmp(argv[2], "tch/any"))
1363 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_FULL_PREF;
1364 else if (!strcmp(argv[2], "sdcch")) {
1365 if (speech) {
1366 vty_out(vty, "Can't request speech on SDCCH%s", VTY_NEWLINE);
1367 return CMD_WARNING;
1368 }
1369 ct.ch_rate_type = GSM0808_SIGN_SDCCH;
1370 } else
1371 ct.ch_rate_type = speech ? GSM0808_SPEECH_FULL_PREF : GSM0808_SIGN_ANY;
1372
1373 ip = argc >= 5 ? argv[4] : "127.0.0.1";
1374 port = argc >= 6 ? atoi(argv[5]) : 4000;
1375
1376 rc = gsm_silent_call_start(vsub, &ct, ip, port, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001377 switch (rc) {
1378 case -ENODEV:
1379 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
1380 break;
1381 default:
1382 if (rc)
1383 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
1384 else
1385 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
1386 break;
1387 }
1388
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001389 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001390 return rc ? CMD_WARNING : CMD_SUCCESS;
1391}
1392
1393DEFUN(subscriber_silent_call_stop,
1394 subscriber_silent_call_stop_cmd,
1395 "subscriber " SUBSCR_TYPES " ID silent-call stop",
1396 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
1397 CHAN_TYPE_HELP)
1398{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001399 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1400 int rc;
1401
1402 if (!vsub) {
1403 vty_out(vty, "%% No subscriber found for %s %s%s",
1404 argv[0], argv[1], VTY_NEWLINE);
1405 return CMD_WARNING;
1406 }
1407
1408 rc = gsm_silent_call_stop(vsub);
1409 switch (rc) {
1410 case -ENODEV:
1411 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
1412 break;
1413 case -ENOENT:
1414 vty_out(vty, "%% Subscriber has no silent call active%s",
1415 VTY_NEWLINE);
1416 break;
1417 default:
1418 if (rc)
1419 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
1420 else
1421 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
1422 break;
1423 }
1424
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001425 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001426 return rc ? CMD_WARNING : CMD_SUCCESS;
1427}
1428
1429DEFUN(subscriber_ussd_notify,
1430 subscriber_ussd_notify_cmd,
1431 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
1432 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
1433 "Alerting Level 0\n"
1434 "Alerting Level 1\n"
1435 "Alerting Level 2\n"
1436 "Text of USSD message to send\n")
1437{
1438 char *text;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001439 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001440 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1441 int level;
1442
1443 if (!vsub) {
1444 vty_out(vty, "%% No subscriber found for %s %s%s",
1445 argv[0], argv[1], VTY_NEWLINE);
1446 return CMD_WARNING;
1447 }
1448
1449 level = atoi(argv[2]);
1450 text = argv_concat(argv, argc, 3);
1451 if (!text) {
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001452 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001453 return CMD_WARNING;
1454 }
1455
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001456 msc_a = msc_a_for_vsub(vsub, true);
1457 if (!msc_a || msc_a->c.remote_to) {
1458 vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001459 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001460 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001461 talloc_free(text);
1462 return CMD_WARNING;
1463 }
1464
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001465 msc_send_ussd_notify(msc_a, level, text);
Vadim Yanitskiyf20c6b72018-11-29 01:20:58 +07001466 /* FIXME: since we don't allocate a transaction here,
1467 * we use dummy GSM 04.07 transaction ID. */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001468 msc_send_ussd_release_complete(msc_a, 0x00);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001469
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001470 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001471 talloc_free(text);
1472 return CMD_SUCCESS;
1473}
1474
1475DEFUN(subscriber_paging,
1476 subscriber_paging_cmd,
1477 "subscriber " SUBSCR_TYPES " ID paging",
1478 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1479{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001480 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001481 struct paging_request *req;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001482
1483 if (!vsub) {
1484 vty_out(vty, "%% No subscriber found for %s %s%s",
1485 argv[0], argv[1], VTY_NEWLINE);
1486 return CMD_WARNING;
1487 }
1488
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001489 req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL,
1490 NULL, NULL, "manual Paging from VTY");
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001491 if (req)
1492 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1493 else
1494 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1495
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001496 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001497 return req ? CMD_SUCCESS : CMD_WARNING;
1498}
1499
1500static int loop_by_char(uint8_t ch)
1501{
1502 switch (ch) {
1503 case 'a':
1504 return GSM414_LOOP_A;
1505 case 'b':
1506 return GSM414_LOOP_B;
1507 case 'c':
1508 return GSM414_LOOP_C;
1509 case 'd':
1510 return GSM414_LOOP_D;
1511 case 'e':
1512 return GSM414_LOOP_E;
1513 case 'f':
1514 return GSM414_LOOP_F;
1515 case 'i':
1516 return GSM414_LOOP_I;
1517 }
1518 return -1;
1519}
1520
1521DEFUN(subscriber_mstest_close,
1522 subscriber_mstest_close_cmd,
1523 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1524 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1525 "Close a TCH Loop inside the MS\n"
1526 "Loop Type A\n"
1527 "Loop Type B\n"
1528 "Loop Type C\n"
1529 "Loop Type D\n"
1530 "Loop Type E\n"
1531 "Loop Type F\n"
1532 "Loop Type I\n")
1533{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001534 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001535 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1536 const char *loop_str;
1537 int loop_mode;
1538
1539 if (!vsub) {
1540 vty_out(vty, "%% No subscriber found for %s %s%s",
1541 argv[0], argv[1], VTY_NEWLINE);
1542 return CMD_WARNING;
1543 }
1544
1545 loop_str = argv[2];
1546 loop_mode = loop_by_char(loop_str[0]);
1547
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001548 msc_a = msc_a_for_vsub(vsub, true);
1549 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001550 vty_out(vty, "%% An active connection is required for %s %s%s",
1551 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001552 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001553 return CMD_WARNING;
1554 }
1555
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001556 gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001557
1558 return CMD_SUCCESS;
1559}
1560
1561DEFUN(subscriber_mstest_open,
1562 subscriber_mstest_open_cmd,
1563 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1564 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1565 "Open a TCH Loop inside the MS\n")
1566{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001567 struct msc_a *msc_a;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001568 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1569
1570 if (!vsub) {
1571 vty_out(vty, "%% No subscriber found for %s %s%s",
1572 argv[0], argv[1], VTY_NEWLINE);
1573 return CMD_WARNING;
1574 }
1575
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001576 msc_a = msc_a_for_vsub(vsub, true);
1577 if (!msc_a) {
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001578 vty_out(vty, "%% An active connection is required for %s %s%s",
1579 argv[0], argv[1], VTY_NEWLINE);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001580 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001581 return CMD_WARNING;
1582 }
1583
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001584 gsm0414_tx_open_loop_cmd(msc_a);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001585
1586 return CMD_SUCCESS;
1587}
1588
1589DEFUN(ena_subscr_expire,
1590 ena_subscr_expire_cmd,
1591 "subscriber " SUBSCR_TYPES " ID expire",
1592 SUBSCR_HELP "Expire the subscriber Now\n")
1593{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001594 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1595 argv[1]);
1596
1597 if (!vsub) {
1598 vty_out(vty, "%% No subscriber found for %s %s%s",
1599 argv[0], argv[1], VTY_NEWLINE);
1600 return CMD_WARNING;
1601 }
1602
1603 if (vlr_subscr_expire(vsub))
1604 vty_out(vty, "%% VLR released subscriber %s%s",
1605 vlr_subscr_name(vsub), VTY_NEWLINE);
1606
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001607 if (osmo_use_count_total(&vsub->use_count) > 1)
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001608 vty_out(vty, "%% Subscriber %s is still in use,"
1609 " should be released soon%s",
1610 vlr_subscr_name(vsub), VTY_NEWLINE);
1611
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001612 vlr_subscr_put(vsub, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001613 return CMD_SUCCESS;
1614}
1615
1616static int scall_cbfn(unsigned int subsys, unsigned int signal,
1617 void *handler_data, void *signal_data)
1618{
1619 struct scall_signal_data *sigdata = signal_data;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001620 struct vty *vty = sigdata->vty;
1621
1622 if (!vty_is_active(vty))
1623 return 0;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001624
1625 switch (signal) {
1626 case S_SCALL_SUCCESS:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001627 vty_out(vty, "%% Silent call success%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001628 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001629 case S_SCALL_FAILED:
1630 vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE);
1631 break;
1632 case S_SCALL_DETACHED:
1633 vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001634 break;
1635 }
1636 return 0;
1637}
1638
1639DEFUN(show_stats,
1640 show_stats_cmd,
1641 "show statistics",
1642 SHOW_STR "Display network statistics\n")
1643{
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001644 vty_out(vty, "Location Update : %" PRIu64 " attach, %" PRIu64 " normal, %" PRIu64 " periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001645 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1646 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1647 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001648 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001649 vty_out(vty, "IMSI Detach Indications : %" PRIu64 "%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001650 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001651 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001652 vty_out(vty, "Location Updating Results: %" PRIu64 " completed, %" PRIu64 " failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001653 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1654 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001655 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001656 vty_out(vty, "SMS MO : %" PRIu64 " submitted, %" PRIu64 " no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001657 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1658 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001659 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001660 vty_out(vty, "SMS MT : %" PRIu64 " delivered, %" PRIu64 " no memory, %" PRIu64 " other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001661 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1662 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1663 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001664 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001665 vty_out(vty, "MO Calls : %" PRIu64 " setup, %" PRIu64 " connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001666 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1667 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001668 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001669 vty_out(vty, "MT Calls : %" PRIu64 " setup, %" PRIu64 " connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001670 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1671 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001672 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001673 vty_out(vty, "MO NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001674 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current,
1675 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1676 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_REQUESTS].current
1677 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MO_ESTABLISHED].current,
1678 VTY_NEWLINE);
Pau Espin Pedrol37106232018-11-19 11:10:37 +01001679 vty_out(vty, "MT NC SS/USSD : %" PRIu64 " requests, %" PRIu64 " established, %" PRIu64 " rejected%s",
Vadim Yanitskiy8e25cc52018-06-23 03:32:20 +07001680 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current,
1681 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1682 gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_REQUESTS].current
1683 - gsmnet->msc_ctrs->ctr[MSC_CTR_NC_SS_MT_ESTABLISHED].current,
1684 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001685 return CMD_SUCCESS;
1686}
1687
1688DEFUN(show_smsqueue,
1689 show_smsqueue_cmd,
1690 "show sms-queue",
1691 SHOW_STR "Display SMSqueue statistics\n")
1692{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001693 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001694 return CMD_SUCCESS;
1695}
1696
1697DEFUN(smsqueue_trigger,
1698 smsqueue_trigger_cmd,
1699 "sms-queue trigger",
1700 "SMS Queue\n" "Trigger sending messages\n")
1701{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001702 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001703 return CMD_SUCCESS;
1704}
1705
1706DEFUN(smsqueue_max,
1707 smsqueue_max_cmd,
1708 "sms-queue max-pending <1-500>",
1709 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1710{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001711 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001712 return CMD_SUCCESS;
1713}
1714
1715DEFUN(smsqueue_clear,
1716 smsqueue_clear_cmd,
1717 "sms-queue clear",
1718 "SMS Queue\n" "Clear the queue of pending SMS\n")
1719{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001720 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001721 return CMD_SUCCESS;
1722}
1723
1724DEFUN(smsqueue_fail,
1725 smsqueue_fail_cmd,
1726 "sms-queue max-failure <1-500>",
1727 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1728{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001729 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001730 return CMD_SUCCESS;
1731}
1732
1733
1734DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1735 "mncc-int", "Configure internal MNCC handler")
1736{
1737 vty->node = MNCC_INT_NODE;
1738
1739 return CMD_SUCCESS;
1740}
1741
1742static struct cmd_node mncc_int_node = {
1743 MNCC_INT_NODE,
1744 "%s(config-mncc-int)# ",
1745 1,
1746};
1747
1748static const struct value_string tchf_codec_names[] = {
1749 { GSM48_CMODE_SPEECH_V1, "fr" },
1750 { GSM48_CMODE_SPEECH_EFR, "efr" },
1751 { GSM48_CMODE_SPEECH_AMR, "amr" },
1752 { 0, NULL }
1753};
1754
1755static const struct value_string tchh_codec_names[] = {
1756 { GSM48_CMODE_SPEECH_V1, "hr" },
1757 { GSM48_CMODE_SPEECH_AMR, "amr" },
1758 { 0, NULL }
1759};
1760
1761static int config_write_mncc_int(struct vty *vty)
1762{
1763 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1764 vty_out(vty, " default-codec tch-f %s%s",
1765 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1766 VTY_NEWLINE);
1767 vty_out(vty, " default-codec tch-h %s%s",
1768 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1769 VTY_NEWLINE);
1770
1771 return CMD_SUCCESS;
1772}
1773
1774DEFUN(mnccint_def_codec_f,
1775 mnccint_def_codec_f_cmd,
1776 "default-codec tch-f (fr|efr|amr)",
1777 "Set default codec\n" "Codec for TCH/F\n"
1778 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1779{
1780 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1781
1782 return CMD_SUCCESS;
1783}
1784
1785DEFUN(mnccint_def_codec_h,
1786 mnccint_def_codec_h_cmd,
1787 "default-codec tch-h (hr|amr)",
1788 "Set default codec\n" "Codec for TCH/H\n"
1789 "Half-Rate\n" "Adaptive Multi-Rate\n")
1790{
1791 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1792
1793 return CMD_SUCCESS;
1794}
1795
1796
1797DEFUN(logging_fltr_imsi,
1798 logging_fltr_imsi_cmd,
1799 "logging filter imsi IMSI",
1800 LOGGING_STR FILTER_STR
1801 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1802{
1803 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001804 struct log_target *tgt = osmo_log_vty2tgt(vty);
1805 const char *imsi = argv[0];
1806
1807 if (!tgt)
1808 return CMD_WARNING;
1809
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001810 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001811
1812 if (!vlr_subscr) {
1813 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1814 argv[0], VTY_NEWLINE);
1815 return CMD_WARNING;
1816 }
1817
1818 log_set_filter_vlr_subscr(tgt, vlr_subscr);
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +01001819 vlr_subscr_put(vlr_subscr, VSUB_USE_VTY);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001820 return CMD_SUCCESS;
1821}
1822
1823static struct cmd_node hlr_node = {
1824 HLR_NODE,
1825 "%s(config-hlr)# ",
1826 1,
1827};
1828
1829DEFUN(cfg_hlr, cfg_hlr_cmd,
1830 "hlr", "Configure connection to the HLR")
1831{
1832 vty->node = HLR_NODE;
1833 return CMD_SUCCESS;
1834}
1835
1836DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1837 "Remote GSUP address of the HLR\n"
1838 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1839{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001840 talloc_free((void*)gsmnet->gsup_server_addr_str);
1841 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1842 return CMD_SUCCESS;
1843}
1844
1845DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1846 "Remote GSUP port of the HLR\n"
1847 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1848{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001849 gsmnet->gsup_server_port = atoi(argv[0]);
1850 return CMD_SUCCESS;
1851}
1852
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001853DEFUN(cfg_hlr_ipa_name,
1854 cfg_hlr_ipa_name_cmd,
1855 "ipa-name NAME",
1856 "Set the IPA name of this MSC\n"
1857 "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. "
1858 "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. "
1859 "The default is 'MSC-00-00-00-00-00-00'.\n")
1860{
1861 if (vty->type != VTY_FILE) {
1862 vty_out(vty, "The IPA name cannot be changed at run-time; "
1863 "It can only be set in the configuraton file.%s", VTY_NEWLINE);
1864 return CMD_WARNING;
1865 }
1866
1867 gsmnet->msc_ipa_name = talloc_strdup(gsmnet, argv[0]);
1868 return CMD_SUCCESS;
1869}
1870
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001871static int config_write_hlr(struct vty *vty)
1872{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001873 vty_out(vty, "hlr%s", VTY_NEWLINE);
1874 vty_out(vty, " remote-ip %s%s",
1875 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1876 vty_out(vty, " remote-port %u%s",
1877 gsmnet->gsup_server_port, VTY_NEWLINE);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001878 if (gsmnet->msc_ipa_name)
1879 vty_out(vty, " ipa-name %s%s", gsmnet->msc_ipa_name, VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001880 return CMD_SUCCESS;
1881}
1882
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001883void msc_vty_init(struct gsm_network *msc_network)
1884{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001885 OSMO_ASSERT(gsmnet == NULL);
1886 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001887
1888 osmo_stats_vty_add_cmds();
1889
1890 install_element(CONFIG_NODE, &cfg_net_cmd);
1891 install_node(&net_node, config_write_net);
1892 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1893 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1894 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1895 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1896 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
1897 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1898 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1899 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1900 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1901 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1902 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1903 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1904 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001905
1906 install_element(CONFIG_NODE, &cfg_msc_cmd);
1907 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001908 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
Neels Hofmeyr80447eb2018-12-05 01:11:28 +01001909 install_element(MSC_NODE, &cfg_msc_mncc_internal_cmd);
1910 install_element(MSC_NODE, &cfg_msc_mncc_external_cmd);
Philipp Maier9ca7b312018-10-10 17:00:49 +02001911 install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd);
Neels Hofmeyr05c56802018-12-05 01:07:03 +01001912 install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd);
Vadim Yanitskiy64623e12018-11-28 23:05:51 +07001913 install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001914 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001915 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
1916 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Oliver Smith0fec28a2018-12-14 10:52:52 +01001917 install_element(MSC_NODE, &cfg_msc_check_imei_rqd_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001918 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
1919 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01001920 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01001921 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Vadim Yanitskiyf40e46f2018-11-20 06:20:53 +07001922 install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd);
1923 install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd);
Pau Espin Pedrol4faff9e2019-05-06 19:29:11 +02001924 install_element(MSC_NODE, &cfg_msc_osmux_cmd);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001925 install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd);
1926
1927 neighbor_ident_vty_init(msc_network);
Philipp Maierfbf66102017-04-09 12:32:51 +02001928
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02001929 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001930#ifdef BUILD_IU
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001931 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 +02001932#endif
Harald Welte0df904d2018-12-03 11:00:04 +01001933 sgs_vty_init();
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001934
Stefan Sperling617ac802018-02-22 17:58:20 +01001935 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001936
1937 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
1938
1939 install_element_ve(&show_subscr_cmd);
1940 install_element_ve(&show_subscr_cache_cmd);
Maxc51609a2018-11-09 17:13:00 +01001941 install_element_ve(&show_bsc_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001942 install_element_ve(&show_msc_conn_cmd);
1943 install_element_ve(&show_msc_transaction_cmd);
1944
1945 install_element_ve(&sms_send_pend_cmd);
1946 install_element_ve(&sms_delete_expired_cmd);
1947
1948 install_element_ve(&subscriber_create_cmd);
1949 install_element_ve(&subscriber_send_sms_cmd);
1950 install_element_ve(&subscriber_silent_sms_cmd);
1951 install_element_ve(&subscriber_silent_call_start_cmd);
1952 install_element_ve(&subscriber_silent_call_stop_cmd);
1953 install_element_ve(&subscriber_ussd_notify_cmd);
1954 install_element_ve(&subscriber_mstest_close_cmd);
1955 install_element_ve(&subscriber_mstest_open_cmd);
1956 install_element_ve(&subscriber_paging_cmd);
1957 install_element_ve(&show_stats_cmd);
1958 install_element_ve(&show_smsqueue_cmd);
1959 install_element_ve(&logging_fltr_imsi_cmd);
1960
1961 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
1962 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
1963 install_element(ENABLE_NODE, &smsqueue_max_cmd);
1964 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
1965 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
1966 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
Neels Hofmeyrf90496f2019-03-06 16:19:50 +01001967 install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001968
1969 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
1970 install_node(&mncc_int_node, config_write_mncc_int);
1971 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
1972 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
1973
1974 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
1975
1976 install_element(CONFIG_NODE, &cfg_hlr_cmd);
1977 install_node(&hlr_node, config_write_hlr);
1978 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
1979 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr3a3ed9b2018-12-20 00:46:40 +01001980 install_element(HLR_NODE, &cfg_hlr_ipa_name_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001981}