blob: 84d4d1416683f035e6103fcbd5d4583090a29a17 [file] [log] [blame]
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001/* MSC interface to quagga VTY */
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01002/* (C) 2016-2018 by sysmocom s.m.f.c. GmbH <info@sysmocom.de>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02003 * Based on OpenBSC interface to quagga VTY (libmsc/vty_interface_layer3.c)
Harald Welte7b222aa2017-12-23 19:30:32 +01004 * (C) 2009-2017 by Harald Welte <laforge@gnumonks.org>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02005 * (C) 2009-2011 by Holger Hans Peter Freyther
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23/* NOTE: I would have liked to call this the MSC_NODE instead of the MSC_NODE,
24 * but MSC_NODE already exists to configure a remote MSC for osmo-bsc. */
25
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020026#include "../../bscconfig.h"
27
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020028#include <inttypes.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010029#include <limits.h>
30
31#include <osmocom/gsm/protocol/gsm_08_58.h>
32#include <osmocom/gsm/protocol/gsm_04_14.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020033
34#include <osmocom/vty/command.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010035#include <osmocom/vty/logging.h>
Stefan Sperling617ac802018-02-22 17:58:20 +010036#include <osmocom/vty/misc.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010037#include <osmocom/vty/stats.h>
38
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020039#ifdef BUILD_IU
40#include <osmocom/ranap/iu_client.h>
41#endif
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020042
Neels Hofmeyr90843962017-09-04 15:04:35 +020043#include <osmocom/msc/vty.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010044#include <osmocom/msc/osmo_msc.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020045#include <osmocom/msc/gsm_data.h>
46#include <osmocom/msc/gsm_subscriber.h>
47#include <osmocom/msc/vlr.h>
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010048#include <osmocom/msc/transaction.h>
49#include <osmocom/msc/db.h>
50#include <osmocom/msc/sms_queue.h>
51#include <osmocom/msc/silent_call.h>
52#include <osmocom/msc/gsm_04_80.h>
53#include <osmocom/msc/gsm_04_14.h>
54#include <osmocom/msc/signal.h>
55#include <osmocom/msc/mncc_int.h>
56
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010057static struct gsm_network *gsmnet = NULL;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010058
59struct cmd_node net_node = {
60 GSMNET_NODE,
61 "%s(config-net)# ",
62 1,
63};
64
65#define NETWORK_STR "Configure the GSM network\n"
66#define CODE_CMD_STR "Code commands\n"
67#define NAME_CMD_STR "Name Commands\n"
68#define NAME_STR "Name to use\n"
69
70DEFUN(cfg_net,
71 cfg_net_cmd,
72 "network", NETWORK_STR)
73{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +010074 vty->index = gsmnet;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010075 vty->node = GSMNET_NODE;
76
77 return CMD_SUCCESS;
78}
79
80DEFUN(cfg_net_ncc,
81 cfg_net_ncc_cmd,
82 "network country code <1-999>",
83 "Set the GSM network country code\n"
84 "Country commands\n"
85 CODE_CMD_STR
86 "Network Country Code to use\n")
87{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +010088 gsmnet->plmn.mcc = atoi(argv[0]);
89
90 return CMD_SUCCESS;
91}
92
93DEFUN(cfg_net_mnc,
94 cfg_net_mnc_cmd,
95 "mobile network code <0-999>",
96 "Set the GSM mobile network code\n"
97 "Network Commands\n"
98 CODE_CMD_STR
99 "Mobile Network Code to use\n")
100{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100101 uint16_t mnc;
102 bool mnc_3_digits;
103
104 if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
105 vty_out(vty, "%% Error decoding MNC: %s%s", argv[0], VTY_NEWLINE);
106 return CMD_WARNING;
107 }
108
109 gsmnet->plmn.mnc = mnc;
110 gsmnet->plmn.mnc_3_digits = mnc_3_digits;
111
112 return CMD_SUCCESS;
113}
114
115DEFUN(cfg_net_name_short,
116 cfg_net_name_short_cmd,
117 "short name NAME",
118 "Set the short GSM network name\n" NAME_CMD_STR NAME_STR)
119{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100120 osmo_talloc_replace_string(gsmnet, &gsmnet->name_short, argv[0]);
121 return CMD_SUCCESS;
122}
123
124DEFUN(cfg_net_name_long,
125 cfg_net_name_long_cmd,
126 "long name NAME",
127 "Set the long GSM network name\n" NAME_CMD_STR NAME_STR)
128{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100129 osmo_talloc_replace_string(gsmnet, &gsmnet->name_long, argv[0]);
130 return CMD_SUCCESS;
131}
132
133DEFUN(cfg_net_encryption,
134 cfg_net_encryption_cmd,
135 "encryption a5 <0-3> [<0-3>] [<0-3>] [<0-3>]",
136 "Encryption options\n"
137 "GSM A5 Air Interface Encryption\n"
138 "A5/n Algorithm Number\n"
139 "A5/n Algorithm Number\n"
140 "A5/n Algorithm Number\n"
141 "A5/n Algorithm Number\n")
142{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100143 unsigned int i;
144
145 gsmnet->a5_encryption_mask = 0;
146 for (i = 0; i < argc; i++)
147 gsmnet->a5_encryption_mask |= (1 << atoi(argv[i]));
148
149 return CMD_SUCCESS;
150}
151
152DEFUN(cfg_net_authentication,
153 cfg_net_authentication_cmd,
154 "authentication (optional|required)",
155 "Whether to enforce MS authentication in 2G\n"
156 "Allow MS to attach via 2G BSC without authentication\n"
157 "Always do authentication\n")
158{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100159 gsmnet->authentication_required = (argv[0][0] == 'r') ? true : false;
160
161 return CMD_SUCCESS;
162}
163
Neels Hofmeyr9d744252018-03-22 16:09:50 +0100164static const struct value_string rrlp_mode_names[] = {
165 { RRLP_MODE_NONE, "none" },
166 { RRLP_MODE_MS_BASED, "ms-based" },
167 { RRLP_MODE_MS_PREF, "ms-preferred" },
168 { RRLP_MODE_ASS_PREF, "ass-preferred" },
169 { 0, NULL }
170};
171
172static enum rrlp_mode rrlp_mode_parse(const char *arg)
173{
174 return get_string_value(rrlp_mode_names, arg);
175}
176
177static const char *rrlp_mode_name(enum rrlp_mode mode)
178{
179 return get_value_string(rrlp_mode_names, mode);
180}
181
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100182DEFUN(cfg_net_rrlp_mode, cfg_net_rrlp_mode_cmd,
183 "rrlp mode (none|ms-based|ms-preferred|ass-preferred)",
184 "Radio Resource Location Protocol\n"
185 "Set the Radio Resource Location Protocol Mode\n"
186 "Don't send RRLP request\n"
187 "Request MS-based location\n"
188 "Request any location, prefer MS-based\n"
189 "Request any location, prefer MS-assisted\n")
190{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100191 gsmnet->rrlp.mode = rrlp_mode_parse(argv[0]);
192
193 return CMD_SUCCESS;
194}
195
196DEFUN(cfg_net_mm_info, cfg_net_mm_info_cmd,
197 "mm info (0|1)",
198 "Mobility Management\n"
199 "Send MM INFO after LOC UPD ACCEPT\n"
200 "Disable\n" "Enable\n")
201{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100202 gsmnet->send_mm_info = atoi(argv[0]);
203
204 return CMD_SUCCESS;
205}
206
207DEFUN(cfg_net_timezone,
208 cfg_net_timezone_cmd,
209 "timezone <-19-19> (0|15|30|45)",
210 "Set the Timezone Offset of the network\n"
211 "Timezone offset (hours)\n"
212 "Timezone offset (00 minutes)\n"
213 "Timezone offset (15 minutes)\n"
214 "Timezone offset (30 minutes)\n"
215 "Timezone offset (45 minutes)\n"
216 )
217{
218 struct gsm_network *net = vty->index;
219 int tzhr = atoi(argv[0]);
220 int tzmn = atoi(argv[1]);
221
222 net->tz.hr = tzhr;
223 net->tz.mn = tzmn;
224 net->tz.dst = 0;
225 net->tz.override = 1;
226
227 return CMD_SUCCESS;
228}
229
230DEFUN(cfg_net_timezone_dst,
231 cfg_net_timezone_dst_cmd,
232 "timezone <-19-19> (0|15|30|45) <0-2>",
233 "Set the Timezone Offset of the network\n"
234 "Timezone offset (hours)\n"
235 "Timezone offset (00 minutes)\n"
236 "Timezone offset (15 minutes)\n"
237 "Timezone offset (30 minutes)\n"
238 "Timezone offset (45 minutes)\n"
239 "DST offset (hours)\n"
240 )
241{
242 struct gsm_network *net = vty->index;
243 int tzhr = atoi(argv[0]);
244 int tzmn = atoi(argv[1]);
245 int tzdst = atoi(argv[2]);
246
247 net->tz.hr = tzhr;
248 net->tz.mn = tzmn;
249 net->tz.dst = tzdst;
250 net->tz.override = 1;
251
252 return CMD_SUCCESS;
253}
254
255DEFUN(cfg_net_no_timezone,
256 cfg_net_no_timezone_cmd,
257 "no timezone",
258 NO_STR
259 "Disable network timezone override, use system tz\n")
260{
261 struct gsm_network *net = vty->index;
262
263 net->tz.override = 0;
264
265 return CMD_SUCCESS;
266}
267
268DEFUN(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
269 "periodic location update <6-1530>",
270 "Periodic Location Updating Interval\n"
271 "Periodic Location Updating Interval\n"
272 "Periodic Location Updating Interval\n"
273 "Periodic Location Updating Interval in Minutes\n")
274{
275 struct gsm_network *net = vty->index;
276
277 net->t3212 = atoi(argv[0]) / 6;
278
279 return CMD_SUCCESS;
280}
281
282DEFUN(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
283 "no periodic location update",
284 NO_STR
285 "Periodic Location Updating Interval\n"
286 "Periodic Location Updating Interval\n"
287 "Periodic Location Updating Interval\n")
288{
289 struct gsm_network *net = vty->index;
290
291 net->t3212 = 0;
292
293 return CMD_SUCCESS;
294}
295
296static int config_write_net(struct vty *vty)
297{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100298 int i;
299
300 vty_out(vty, "network%s", VTY_NEWLINE);
301 vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
302 vty_out(vty, " mobile network code %s%s",
303 osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
304 vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
305 vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
306 vty_out(vty, " encryption a5");
307 for (i = 0; i < 8; i++) {
308 if (gsmnet->a5_encryption_mask & (1 << i))
309 vty_out(vty, " %u", i);
310 }
311 vty_out(vty, "%s", VTY_NEWLINE);
312 vty_out(vty, " authentication %s%s",
313 gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE);
314 vty_out(vty, " rrlp mode %s%s", rrlp_mode_name(gsmnet->rrlp.mode),
315 VTY_NEWLINE);
316 vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
317 if (gsmnet->tz.override != 0) {
318 if (gsmnet->tz.dst)
319 vty_out(vty, " timezone %d %d %d%s",
320 gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
321 VTY_NEWLINE);
322 else
323 vty_out(vty, " timezone %d %d%s",
324 gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
325 }
326 if (gsmnet->t3212 == 0)
327 vty_out(vty, " no periodic location update%s", VTY_NEWLINE);
328 else
329 vty_out(vty, " periodic location update %u%s",
330 gsmnet->t3212 * 6, VTY_NEWLINE);
331
332 if (gsmnet->emergency.route_to_msisdn) {
333 vty_out(vty, " emergency-call route-to-msisdn %s%s",
334 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
335 }
336
337 return CMD_SUCCESS;
338}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200339
340static struct cmd_node msc_node = {
341 MSC_NODE,
342 "%s(config-msc)# ",
343 1,
344};
345
346DEFUN(cfg_msc, cfg_msc_cmd,
347 "msc", "Configure MSC options")
348{
349 vty->node = MSC_NODE;
350 return CMD_SUCCESS;
351}
352
353DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
354 "assign-tmsi",
355 "Assign TMSI during Location Updating.\n")
356{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200357 gsmnet->vlr->cfg.assign_tmsi = true;
358 return CMD_SUCCESS;
359}
360
361DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
362 "no assign-tmsi",
363 NO_STR "Assign TMSI during Location Updating.\n")
364{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200365 gsmnet->vlr->cfg.assign_tmsi = false;
366 return CMD_SUCCESS;
367}
368
Philipp Maierfbf66102017-04-09 12:32:51 +0200369DEFUN(cfg_msc_cs7_instance_a,
370 cfg_msc_cs7_instance_a_cmd,
371 "cs7-instance-a <0-15>",
372 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
373{
Philipp Maierfbf66102017-04-09 12:32:51 +0200374 gsmnet->a.cs7_instance = atoi(argv[0]);
375 return CMD_SUCCESS;
376}
377
378DEFUN(cfg_msc_cs7_instance_iu,
379 cfg_msc_cs7_instance_iu_cmd,
380 "cs7-instance-iu <0-15>",
381 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
382{
Philipp Maierfbf66102017-04-09 12:32:51 +0200383 gsmnet->iu.cs7_instance = atoi(argv[0]);
384 return CMD_SUCCESS;
385}
386
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100387DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
388 "auth-tuple-max-reuse-count <-1-2147483647>",
389 "Configure authentication tuple re-use\n"
390 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
391{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100392 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
393 return CMD_SUCCESS;
394}
395
396DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
397 "auth-tuple-reuse-on-error (0|1)",
398 "Configure authentication tuple re-use when HLR is not responsive\n"
399 "0 = never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
400 "1 = if the HLR does not deliver new tuples, do re-use already available old ones.\n")
401{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100402 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
403 return CMD_SUCCESS;
404}
405
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100406DEFUN(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
407 "paging response-timer (default|<1-65535>)",
408 "Configure Paging\n"
409 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
410 " BSS or RNC\n"
411 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
412 "Set paging timeout in seconds\n")
413{
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100414 if (!strcmp(argv[1], "default"))
415 gsmnet->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
416 else
417 gsmnet->paging_response_timer = atoi(argv[0]);
418 return CMD_SUCCESS;
419}
420
Harald Welte69c54a82018-02-09 20:41:14 +0100421DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
422 "emergency-call route-to-msisdn MSISDN",
423 "Configure Emergency Call Behaviour\n"
424 "MSISDN to which Emergency Calls are Dispatched\n"
425 "MSISDN (E.164 Phone Number)\n")
426{
Harald Welte69c54a82018-02-09 20:41:14 +0100427 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
428
429 return CMD_SUCCESS;
430}
431
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200432static int config_write_msc(struct vty *vty)
433{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200434 vty_out(vty, "msc%s", VTY_NEWLINE);
435 vty_out(vty, " %sassign-tmsi%s",
436 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
437
Philipp Maierfbf66102017-04-09 12:32:51 +0200438 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
439 VTY_NEWLINE);
440 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
441 VTY_NEWLINE);
442
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100443 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
444 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
445 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
446 VTY_NEWLINE);
447 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
448 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
449 VTY_NEWLINE);
450
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100451 if (gsmnet->paging_response_timer != MSC_PAGING_RESPONSE_TIMER_DEFAULT)
452 vty_out(vty, " paging response-timer %u%s", gsmnet->paging_response_timer, VTY_NEWLINE);
453
Harald Welte69c54a82018-02-09 20:41:14 +0100454 if (gsmnet->emergency.route_to_msisdn) {
455 vty_out(vty, " emergency-call route-to-msisdn %s%s",
456 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
457 }
458
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200459 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200460#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200461 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200462#endif
463
464 return CMD_SUCCESS;
465}
466
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100467static void vty_conn_hdr(struct vty *vty)
468{
469 vty_out(vty, "--ConnId ------------Subscriber RAN --LAC Use --Tokens C A5 State%s",
470 VTY_NEWLINE);
471}
472
473static void vty_dump_one_conn(struct vty *vty, const struct gsm_subscriber_connection *conn)
474{
475 vty_out(vty, "%08x %22s %3s %5u %3u %08x %c /%1u %27s %s",
476 conn->a.conn_id,
477 conn->vsub ? vlr_subscr_name(conn->vsub) : "-",
478 conn->via_ran == RAN_UTRAN_IU ? "Iu" : "A",
479 conn->lac,
480 conn->use_count,
481 conn->use_tokens,
482 conn->received_cm_service_request ? 'C' : '-',
483 conn->encr.alg_id,
Neels Hofmeyr4d3a66b2018-03-31 18:45:59 +0200484 conn->fi ? osmo_fsm_inst_state_name(conn->fi) : "-",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100485 VTY_NEWLINE);
486}
487
488DEFUN(show_msc_conn, show_msc_conn_cmd,
489 "show connection", SHOW_STR "Subscriber Connections\n")
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200490{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100491 struct gsm_subscriber_connection *conn;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200492
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100493 vty_conn_hdr(vty);
494 llist_for_each_entry(conn, &gsmnet->subscr_conns, entry)
495 vty_dump_one_conn(vty, conn);
496
497 return CMD_SUCCESS;
498}
499
500static void vty_trans_hdr(struct vty *vty)
501{
502 vty_out(vty, "------------Subscriber --ConnId -P TI -CallRef Proto%s",
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200503 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100504}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200505
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100506static const char *get_trans_proto_str(const struct gsm_trans *trans)
507{
508 static char buf[256];
509
510 switch (trans->protocol) {
511 case GSM48_PDISC_CC:
512 snprintf(buf, sizeof(buf), "%s %4u %4u",
513 gsm48_cc_state_name(trans->cc.state),
514 trans->cc.Tcurrent,
515 trans->cc.T308_second);
516 break;
517 case GSM48_PDISC_SMS:
518 snprintf(buf, sizeof(buf), "%s %s",
519 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
520 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
521 break;
522 default:
523 buf[0] = '\0';
524 break;
525 }
526
527 return buf;
528}
529
530static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans)
531{
532 vty_out(vty, "%22s %08x %s %02u %08x %s%s",
533 trans->vsub ? vlr_subscr_name(trans->vsub) : "-",
534 trans->conn ? trans->conn->a.conn_id : 0,
535 gsm48_pdisc_name(trans->protocol),
536 trans->transaction_id,
537 trans->callref,
538 get_trans_proto_str(trans), VTY_NEWLINE);
539}
540
541DEFUN(show_msc_transaction, show_msc_transaction_cmd,
542 "show transaction", SHOW_STR "Transactions\n")
543{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100544 struct gsm_trans *trans;
545
546 vty_trans_hdr(vty);
547 llist_for_each_entry(trans, &gsmnet->trans_list, entry)
548 vty_dump_one_trans(vty, trans);
549
550 return CMD_SUCCESS;
551}
552
553static void subscr_dump_full_vty(struct vty *vty, struct vlr_subscr *vsub)
554{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100555 struct gsm_trans *trans;
556 int reqs;
557 struct llist_head *entry;
558
559 if (strlen(vsub->name))
560 vty_out(vty, " Name: '%s'%s", vsub->name, VTY_NEWLINE);
561 if (strlen(vsub->msisdn))
562 vty_out(vty, " Extension: %s%s", vsub->msisdn,
563 VTY_NEWLINE);
564 vty_out(vty, " LAC: %d/0x%x%s",
565 vsub->lac, vsub->lac, VTY_NEWLINE);
566 vty_out(vty, " IMSI: %s%s", vsub->imsi, VTY_NEWLINE);
567 if (vsub->tmsi != GSM_RESERVED_TMSI)
568 vty_out(vty, " TMSI: %08X%s", vsub->tmsi,
569 VTY_NEWLINE);
570 if (vsub->tmsi_new != GSM_RESERVED_TMSI)
571 vty_out(vty, " new TMSI: %08X%s", vsub->tmsi_new,
572 VTY_NEWLINE);
573
574#if 0
575 /* TODO: add this to vlr_subscr? */
576 if (vsub->auth_info.auth_algo != AUTH_ALGO_NONE) {
577 struct gsm_auth_info *i = &vsub->auth_info;
578 vty_out(vty, " A3A8 algorithm id: %d%s",
579 i->auth_algo, VTY_NEWLINE);
580 vty_out(vty, " A3A8 Ki: %s%s",
581 osmo_hexdump(i->a3a8_ki, i->a3a8_ki_len),
582 VTY_NEWLINE);
583 }
584#endif
585
586 if (vsub->last_tuple) {
587 struct gsm_auth_tuple *t = vsub->last_tuple;
588 vty_out(vty, " A3A8 last tuple (used %d times):%s",
589 t->use_count, VTY_NEWLINE);
590 vty_out(vty, " seq # : %d%s",
591 t->key_seq, VTY_NEWLINE);
592 vty_out(vty, " RAND : %s%s",
593 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
594 VTY_NEWLINE);
595 vty_out(vty, " SRES : %s%s",
596 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
597 VTY_NEWLINE);
598 vty_out(vty, " Kc : %s%s",
599 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
600 VTY_NEWLINE);
601 }
602
603 reqs = 0;
604 llist_for_each(entry, &vsub->cs.requests)
605 reqs += 1;
606 vty_out(vty, " Paging: %s paging for %d requests%s",
607 vsub->cs.is_paging ? "is" : "not", reqs, VTY_NEWLINE);
608 vty_out(vty, " Use count: %u%s", vsub->use_count, VTY_NEWLINE);
609
610 /* Connection */
611 if (vsub->msc_conn_ref) {
612 struct gsm_subscriber_connection *conn = vsub->msc_conn_ref;
613 vty_conn_hdr(vty);
614 vty_dump_one_conn(vty, conn);
615 }
616
617 /* Transactions */
618 vty_trans_hdr(vty);
619 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
620 if (trans->vsub != vsub)
621 continue;
622 vty_dump_one_trans(vty, trans);
623 }
624}
625
626/* Subscriber */
627DEFUN(show_subscr_cache,
628 show_subscr_cache_cmd,
629 "show subscriber cache",
630 SHOW_STR "Show information about subscribers\n"
631 "Display contents of subscriber cache\n")
632{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100633 struct vlr_subscr *vsub;
634 int count = 0;
635
636 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
637 if (++count > 100) {
638 vty_out(vty, "%% More than %d subscribers in cache,"
639 " stopping here.%s", count-1, VTY_NEWLINE);
640 break;
641 }
642 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
643 subscr_dump_full_vty(vty, vsub);
Harald Welte69c54a82018-02-09 20:41:14 +0100644 }
645
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200646 return CMD_SUCCESS;
647}
648
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100649DEFUN(sms_send_pend,
650 sms_send_pend_cmd,
651 "sms send pending",
652 "SMS related commands\n" "SMS Sending related commands\n"
653 "Send all pending SMS")
654{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100655 struct gsm_sms *sms;
656 unsigned long long sms_id = 0;
657
658 while (1) {
659 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
660 if (!sms)
661 break;
662
663 if (sms->receiver)
664 gsm411_send_sms_subscr(sms->receiver, sms);
665
666 sms_id = sms->id + 1;
667 }
668
669 return CMD_SUCCESS;
670}
671
672DEFUN(sms_delete_expired,
673 sms_delete_expired_cmd,
674 "sms delete expired",
675 "SMS related commands\n" "SMS Database related commands\n"
676 "Delete all expired SMS")
677{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100678 struct gsm_sms *sms;
679 unsigned long long sms_id = 0;
680 long long num_deleted = 0;
681
682 while (1) {
683 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
684 if (!sms)
685 break;
686
687 /* Skip SMS which are currently queued for sending. */
688 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
689 continue;
690
691 /* Expiration check is performed by the DB layer. */
692 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
693 num_deleted++;
694
695 sms_id = sms->id + 1;
696 }
697
698 if (num_deleted == 0) {
699 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
700 return CMD_WARNING;
701 }
702
703 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
704 return CMD_SUCCESS;
705}
706
707static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +0200708 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100709 char *str, uint8_t tp_pid)
710{
711 struct gsm_network *net = receiver->vlr->user_ctx;
712 struct gsm_sms *sms;
713
Harald Welte39b55482018-04-09 19:19:33 +0200714 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100715 sms->protocol_id = tp_pid;
716
717 /* store in database for the queue */
718 if (db_sms_store(sms) != 0) {
719 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
720 sms_free(sms);
721 return CMD_WARNING;
722 }
723 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
724
725 sms_free(sms);
726 sms_queue_trigger(net->sms_queue);
727 return CMD_SUCCESS;
728}
729
730static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
731 const char *type,
732 const char *id)
733{
734 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
735 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id);
736 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
737 return vlr_subscr_find_by_imsi(gsmnet->vlr, id);
738 else if (!strcmp(type, "tmsi"))
739 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id));
740
741 return NULL;
742}
743#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
744#define SUBSCR_HELP "Operations on a Subscriber\n" \
745 "Identify subscriber by MSISDN (phone number)\n" \
746 "Legacy alias for 'msisdn'\n" \
747 "Identify subscriber by IMSI\n" \
748 "Identify subscriber by TMSI\n" \
749 "Identify subscriber by database ID\n" \
750 "Identifier for the subscriber\n"
751
752DEFUN(show_subscr,
753 show_subscr_cmd,
754 "show subscriber " SUBSCR_TYPES " ID",
755 SHOW_STR SUBSCR_HELP)
756{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100757 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
758 argv[1]);
759
760 if (!vsub) {
761 vty_out(vty, "%% No subscriber found for %s %s%s",
762 argv[0], argv[1], VTY_NEWLINE);
763 return CMD_WARNING;
764 }
765
766 subscr_dump_full_vty(vty, vsub);
767
768 vlr_subscr_put(vsub);
769
770 return CMD_SUCCESS;
771}
772
773DEFUN(subscriber_create,
774 subscriber_create_cmd,
775 "subscriber create imsi ID",
776 "Operations on a Subscriber\n" \
777 "Create new subscriber\n" \
778 "Identify the subscriber by his IMSI\n" \
779 "Identifier for the subscriber\n")
780{
781 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
782 VTY_NEWLINE);
783 return CMD_WARNING;
784}
785
786DEFUN(subscriber_send_pending_sms,
787 subscriber_send_pending_sms_cmd,
788 "subscriber " SUBSCR_TYPES " ID sms pending-send",
789 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
790{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100791 struct vlr_subscr *vsub;
792 struct gsm_sms *sms;
793
794 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
795 if (!vsub) {
796 vty_out(vty, "%% No subscriber found for %s %s%s",
797 argv[0], argv[1], VTY_NEWLINE);
798 return CMD_WARNING;
799 }
800
801 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
802 if (sms)
803 gsm411_send_sms_subscr(sms->receiver, sms);
804
805 vlr_subscr_put(vsub);
806
807 return CMD_SUCCESS;
808}
809
810DEFUN(subscriber_send_sms,
811 subscriber_send_sms_cmd,
812 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
813 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
814{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100815 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +0200816 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100817 char *str;
818 int rc;
819
820 if (!vsub) {
821 vty_out(vty, "%% No subscriber found for %s %s%s",
822 argv[0], argv[1], VTY_NEWLINE);
823 rc = CMD_WARNING;
824 goto err;
825 }
826
Harald Welte39b55482018-04-09 19:19:33 +0200827 if (!strcmp(argv[2], "msisdn"))
828 sender_msisdn = argv[3];
829 else {
830 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
831 if (!sender) {
832 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
833 rc = CMD_WARNING;
834 goto err;
835 }
836 sender_msisdn = sender->msisdn;
837 vlr_subscr_put(sender);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100838 }
839
840 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +0200841 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100842 talloc_free(str);
843
844err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100845 if (vsub)
846 vlr_subscr_put(vsub);
847
848 return rc;
849}
850
851DEFUN(subscriber_silent_sms,
852 subscriber_silent_sms_cmd,
853
854 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
855 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
856{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100857 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +0200858 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100859 char *str;
860 int rc;
861
862 if (!vsub) {
863 vty_out(vty, "%% No subscriber found for %s %s%s",
864 argv[0], argv[1], VTY_NEWLINE);
865 rc = CMD_WARNING;
866 goto err;
867 }
868
Harald Welte39b55482018-04-09 19:19:33 +0200869 if (!strcmp(argv[2], "msisdn")) {
870 sender_msisdn = argv[3];
871 } else {
872 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
873 if (!sender) {
874 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
875 rc = CMD_WARNING;
876 goto err;
877 }
878 sender_msisdn = sender->msisdn;
879 vlr_subscr_put(sender);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100880 }
881
882 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +0200883 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100884 talloc_free(str);
885
886err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100887 if (vsub)
888 vlr_subscr_put(vsub);
889
890 return rc;
891}
892
893#define CHAN_TYPES "(any|tch/f|tch/any|sdcch)"
894#define CHAN_TYPE_HELP \
895 "Any channel\n" \
896 "TCH/F channel\n" \
897 "Any TCH channel\n" \
898 "SDCCH channel\n"
899
900DEFUN(subscriber_silent_call_start,
901 subscriber_silent_call_start_cmd,
902 "subscriber " SUBSCR_TYPES " ID silent-call start (any|tch/f|tch/any|sdcch)",
903 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
904 CHAN_TYPE_HELP)
905{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100906 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
907 int rc, type;
908
909 if (!vsub) {
910 vty_out(vty, "%% No subscriber found for %s %s%s",
911 argv[0], argv[1], VTY_NEWLINE);
912 return CMD_WARNING;
913 }
914
915 if (!strcmp(argv[2], "tch/f"))
916 type = RSL_CHANNEED_TCH_F;
917 else if (!strcmp(argv[2], "tch/any"))
918 type = RSL_CHANNEED_TCH_ForH;
919 else if (!strcmp(argv[2], "sdcch"))
920 type = RSL_CHANNEED_SDCCH;
921 else
922 type = RSL_CHANNEED_ANY; /* Defaults to ANY */
923
924 rc = gsm_silent_call_start(vsub, vty, type);
925 switch (rc) {
926 case -ENODEV:
927 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
928 break;
929 default:
930 if (rc)
931 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
932 else
933 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
934 break;
935 }
936
937 vlr_subscr_put(vsub);
938 return rc ? CMD_WARNING : CMD_SUCCESS;
939}
940
941DEFUN(subscriber_silent_call_stop,
942 subscriber_silent_call_stop_cmd,
943 "subscriber " SUBSCR_TYPES " ID silent-call stop",
944 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
945 CHAN_TYPE_HELP)
946{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100947 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
948 int rc;
949
950 if (!vsub) {
951 vty_out(vty, "%% No subscriber found for %s %s%s",
952 argv[0], argv[1], VTY_NEWLINE);
953 return CMD_WARNING;
954 }
955
956 rc = gsm_silent_call_stop(vsub);
957 switch (rc) {
958 case -ENODEV:
959 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
960 break;
961 case -ENOENT:
962 vty_out(vty, "%% Subscriber has no silent call active%s",
963 VTY_NEWLINE);
964 break;
965 default:
966 if (rc)
967 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
968 else
969 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
970 break;
971 }
972
973 vlr_subscr_put(vsub);
974 return rc ? CMD_WARNING : CMD_SUCCESS;
975}
976
977DEFUN(subscriber_ussd_notify,
978 subscriber_ussd_notify_cmd,
979 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
980 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
981 "Alerting Level 0\n"
982 "Alerting Level 1\n"
983 "Alerting Level 2\n"
984 "Text of USSD message to send\n")
985{
986 char *text;
987 struct gsm_subscriber_connection *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100988 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
989 int level;
990
991 if (!vsub) {
992 vty_out(vty, "%% No subscriber found for %s %s%s",
993 argv[0], argv[1], VTY_NEWLINE);
994 return CMD_WARNING;
995 }
996
997 level = atoi(argv[2]);
998 text = argv_concat(argv, argc, 3);
999 if (!text) {
1000 vlr_subscr_put(vsub);
1001 return CMD_WARNING;
1002 }
1003
1004 conn = connection_for_subscr(vsub);
1005 if (!conn) {
1006 vty_out(vty, "%% An active connection is required for %s %s%s",
1007 argv[0], argv[1], VTY_NEWLINE);
1008 vlr_subscr_put(vsub);
1009 talloc_free(text);
1010 return CMD_WARNING;
1011 }
1012
1013 msc_send_ussd_notify(conn, level, text);
1014 msc_send_ussd_release_complete(conn);
1015
1016 vlr_subscr_put(vsub);
1017 talloc_free(text);
1018 return CMD_SUCCESS;
1019}
1020
1021DEFUN(subscriber_paging,
1022 subscriber_paging_cmd,
1023 "subscriber " SUBSCR_TYPES " ID paging",
1024 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1025{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001026 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1027 struct subscr_request *req;
1028
1029 if (!vsub) {
1030 vty_out(vty, "%% No subscriber found for %s %s%s",
1031 argv[0], argv[1], VTY_NEWLINE);
1032 return CMD_WARNING;
1033 }
1034
1035 req = subscr_request_conn(vsub, NULL, NULL, "manual Paging from VTY");
1036 if (req)
1037 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1038 else
1039 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1040
1041 vlr_subscr_put(vsub);
1042 return req ? CMD_SUCCESS : CMD_WARNING;
1043}
1044
1045static int loop_by_char(uint8_t ch)
1046{
1047 switch (ch) {
1048 case 'a':
1049 return GSM414_LOOP_A;
1050 case 'b':
1051 return GSM414_LOOP_B;
1052 case 'c':
1053 return GSM414_LOOP_C;
1054 case 'd':
1055 return GSM414_LOOP_D;
1056 case 'e':
1057 return GSM414_LOOP_E;
1058 case 'f':
1059 return GSM414_LOOP_F;
1060 case 'i':
1061 return GSM414_LOOP_I;
1062 }
1063 return -1;
1064}
1065
1066DEFUN(subscriber_mstest_close,
1067 subscriber_mstest_close_cmd,
1068 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1069 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1070 "Close a TCH Loop inside the MS\n"
1071 "Loop Type A\n"
1072 "Loop Type B\n"
1073 "Loop Type C\n"
1074 "Loop Type D\n"
1075 "Loop Type E\n"
1076 "Loop Type F\n"
1077 "Loop Type I\n")
1078{
1079 struct gsm_subscriber_connection *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001080 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1081 const char *loop_str;
1082 int loop_mode;
1083
1084 if (!vsub) {
1085 vty_out(vty, "%% No subscriber found for %s %s%s",
1086 argv[0], argv[1], VTY_NEWLINE);
1087 return CMD_WARNING;
1088 }
1089
1090 loop_str = argv[2];
1091 loop_mode = loop_by_char(loop_str[0]);
1092
1093 conn = connection_for_subscr(vsub);
1094 if (!conn) {
1095 vty_out(vty, "%% An active connection is required for %s %s%s",
1096 argv[0], argv[1], VTY_NEWLINE);
1097 vlr_subscr_put(vsub);
1098 return CMD_WARNING;
1099 }
1100
1101 gsm0414_tx_close_tch_loop_cmd(conn, loop_mode);
1102
1103 return CMD_SUCCESS;
1104}
1105
1106DEFUN(subscriber_mstest_open,
1107 subscriber_mstest_open_cmd,
1108 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1109 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1110 "Open a TCH Loop inside the MS\n")
1111{
1112 struct gsm_subscriber_connection *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001113 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1114
1115 if (!vsub) {
1116 vty_out(vty, "%% No subscriber found for %s %s%s",
1117 argv[0], argv[1], VTY_NEWLINE);
1118 return CMD_WARNING;
1119 }
1120
1121 conn = connection_for_subscr(vsub);
1122 if (!conn) {
1123 vty_out(vty, "%% An active connection is required for %s %s%s",
1124 argv[0], argv[1], VTY_NEWLINE);
1125 vlr_subscr_put(vsub);
1126 return CMD_WARNING;
1127 }
1128
1129 gsm0414_tx_open_loop_cmd(conn);
1130
1131 return CMD_SUCCESS;
1132}
1133
1134DEFUN(ena_subscr_expire,
1135 ena_subscr_expire_cmd,
1136 "subscriber " SUBSCR_TYPES " ID expire",
1137 SUBSCR_HELP "Expire the subscriber Now\n")
1138{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001139 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1140 argv[1]);
1141
1142 if (!vsub) {
1143 vty_out(vty, "%% No subscriber found for %s %s%s",
1144 argv[0], argv[1], VTY_NEWLINE);
1145 return CMD_WARNING;
1146 }
1147
1148 if (vlr_subscr_expire(vsub))
1149 vty_out(vty, "%% VLR released subscriber %s%s",
1150 vlr_subscr_name(vsub), VTY_NEWLINE);
1151
1152 if (vsub->use_count > 1)
1153 vty_out(vty, "%% Subscriber %s is still in use,"
1154 " should be released soon%s",
1155 vlr_subscr_name(vsub), VTY_NEWLINE);
1156
1157 vlr_subscr_put(vsub);
1158 return CMD_SUCCESS;
1159}
1160
1161static int scall_cbfn(unsigned int subsys, unsigned int signal,
1162 void *handler_data, void *signal_data)
1163{
1164 struct scall_signal_data *sigdata = signal_data;
1165 struct vty *vty = sigdata->data;
1166
1167 switch (signal) {
1168 case S_SCALL_SUCCESS:
1169 vty_out(vty, "%% silent call success%s", VTY_NEWLINE);
1170 break;
1171 case S_SCALL_EXPIRED:
1172 vty_out(vty, "%% silent call expired paging%s", VTY_NEWLINE);
1173 break;
1174 }
1175 return 0;
1176}
1177
1178DEFUN(show_stats,
1179 show_stats_cmd,
1180 "show statistics",
1181 SHOW_STR "Display network statistics\n")
1182{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001183 vty_out(vty, "Location Update : %lu attach, %lu normal, %lu periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001184 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1185 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1186 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001187 VTY_NEWLINE);
1188 vty_out(vty, "IMSI Detach Indications : %lu%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001189 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001190 VTY_NEWLINE);
1191 vty_out(vty, "Location Updating Results: %lu completed, %lu failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001192 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1193 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001194 VTY_NEWLINE);
1195 vty_out(vty, "SMS MO : %lu submitted, %lu no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001196 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1197 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001198 VTY_NEWLINE);
1199 vty_out(vty, "SMS MT : %lu delivered, %lu no memory, %lu other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001200 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1201 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1202 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001203 VTY_NEWLINE);
1204 vty_out(vty, "MO Calls : %lu setup, %lu connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001205 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1206 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001207 VTY_NEWLINE);
1208 vty_out(vty, "MT Calls : %lu setup, %lu connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001209 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1210 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001211 VTY_NEWLINE);
1212 return CMD_SUCCESS;
1213}
1214
1215DEFUN(show_smsqueue,
1216 show_smsqueue_cmd,
1217 "show sms-queue",
1218 SHOW_STR "Display SMSqueue statistics\n")
1219{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001220 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001221 return CMD_SUCCESS;
1222}
1223
1224DEFUN(smsqueue_trigger,
1225 smsqueue_trigger_cmd,
1226 "sms-queue trigger",
1227 "SMS Queue\n" "Trigger sending messages\n")
1228{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001229 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001230 return CMD_SUCCESS;
1231}
1232
1233DEFUN(smsqueue_max,
1234 smsqueue_max_cmd,
1235 "sms-queue max-pending <1-500>",
1236 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1237{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001238 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001239 return CMD_SUCCESS;
1240}
1241
1242DEFUN(smsqueue_clear,
1243 smsqueue_clear_cmd,
1244 "sms-queue clear",
1245 "SMS Queue\n" "Clear the queue of pending SMS\n")
1246{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001247 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001248 return CMD_SUCCESS;
1249}
1250
1251DEFUN(smsqueue_fail,
1252 smsqueue_fail_cmd,
1253 "sms-queue max-failure <1-500>",
1254 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1255{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001256 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001257 return CMD_SUCCESS;
1258}
1259
1260
1261DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1262 "mncc-int", "Configure internal MNCC handler")
1263{
1264 vty->node = MNCC_INT_NODE;
1265
1266 return CMD_SUCCESS;
1267}
1268
1269static struct cmd_node mncc_int_node = {
1270 MNCC_INT_NODE,
1271 "%s(config-mncc-int)# ",
1272 1,
1273};
1274
1275static const struct value_string tchf_codec_names[] = {
1276 { GSM48_CMODE_SPEECH_V1, "fr" },
1277 { GSM48_CMODE_SPEECH_EFR, "efr" },
1278 { GSM48_CMODE_SPEECH_AMR, "amr" },
1279 { 0, NULL }
1280};
1281
1282static const struct value_string tchh_codec_names[] = {
1283 { GSM48_CMODE_SPEECH_V1, "hr" },
1284 { GSM48_CMODE_SPEECH_AMR, "amr" },
1285 { 0, NULL }
1286};
1287
1288static int config_write_mncc_int(struct vty *vty)
1289{
1290 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1291 vty_out(vty, " default-codec tch-f %s%s",
1292 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1293 VTY_NEWLINE);
1294 vty_out(vty, " default-codec tch-h %s%s",
1295 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1296 VTY_NEWLINE);
1297
1298 return CMD_SUCCESS;
1299}
1300
1301DEFUN(mnccint_def_codec_f,
1302 mnccint_def_codec_f_cmd,
1303 "default-codec tch-f (fr|efr|amr)",
1304 "Set default codec\n" "Codec for TCH/F\n"
1305 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1306{
1307 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1308
1309 return CMD_SUCCESS;
1310}
1311
1312DEFUN(mnccint_def_codec_h,
1313 mnccint_def_codec_h_cmd,
1314 "default-codec tch-h (hr|amr)",
1315 "Set default codec\n" "Codec for TCH/H\n"
1316 "Half-Rate\n" "Adaptive Multi-Rate\n")
1317{
1318 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1319
1320 return CMD_SUCCESS;
1321}
1322
1323
1324DEFUN(logging_fltr_imsi,
1325 logging_fltr_imsi_cmd,
1326 "logging filter imsi IMSI",
1327 LOGGING_STR FILTER_STR
1328 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1329{
1330 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001331 struct log_target *tgt = osmo_log_vty2tgt(vty);
1332 const char *imsi = argv[0];
1333
1334 if (!tgt)
1335 return CMD_WARNING;
1336
1337 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi);
1338
1339 if (!vlr_subscr) {
1340 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1341 argv[0], VTY_NEWLINE);
1342 return CMD_WARNING;
1343 }
1344
1345 log_set_filter_vlr_subscr(tgt, vlr_subscr);
1346 return CMD_SUCCESS;
1347}
1348
1349static struct cmd_node hlr_node = {
1350 HLR_NODE,
1351 "%s(config-hlr)# ",
1352 1,
1353};
1354
1355DEFUN(cfg_hlr, cfg_hlr_cmd,
1356 "hlr", "Configure connection to the HLR")
1357{
1358 vty->node = HLR_NODE;
1359 return CMD_SUCCESS;
1360}
1361
1362DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1363 "Remote GSUP address of the HLR\n"
1364 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1365{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001366 talloc_free((void*)gsmnet->gsup_server_addr_str);
1367 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1368 return CMD_SUCCESS;
1369}
1370
1371DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1372 "Remote GSUP port of the HLR\n"
1373 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1374{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001375 gsmnet->gsup_server_port = atoi(argv[0]);
1376 return CMD_SUCCESS;
1377}
1378
1379static int config_write_hlr(struct vty *vty)
1380{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001381 vty_out(vty, "hlr%s", VTY_NEWLINE);
1382 vty_out(vty, " remote-ip %s%s",
1383 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1384 vty_out(vty, " remote-port %u%s",
1385 gsmnet->gsup_server_port, VTY_NEWLINE);
1386 return CMD_SUCCESS;
1387}
1388
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001389void msc_vty_init(struct gsm_network *msc_network)
1390{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001391 OSMO_ASSERT(gsmnet == NULL);
1392 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001393
1394 osmo_stats_vty_add_cmds();
1395
1396 install_element(CONFIG_NODE, &cfg_net_cmd);
1397 install_node(&net_node, config_write_net);
1398 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1399 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1400 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1401 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1402 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
1403 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1404 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1405 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1406 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1407 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1408 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1409 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1410 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001411
1412 install_element(CONFIG_NODE, &cfg_msc_cmd);
1413 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001414 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
1415 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001416 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
1417 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001418 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
1419 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01001420 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01001421 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001422
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02001423 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001424#ifdef BUILD_IU
Pau Espin Pedrolb8c0cf82018-01-22 13:49:53 +01001425 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 +02001426#endif
Stefan Sperling617ac802018-02-22 17:58:20 +01001427 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001428
1429 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
1430
1431 install_element_ve(&show_subscr_cmd);
1432 install_element_ve(&show_subscr_cache_cmd);
1433 install_element_ve(&show_msc_conn_cmd);
1434 install_element_ve(&show_msc_transaction_cmd);
1435
1436 install_element_ve(&sms_send_pend_cmd);
1437 install_element_ve(&sms_delete_expired_cmd);
1438
1439 install_element_ve(&subscriber_create_cmd);
1440 install_element_ve(&subscriber_send_sms_cmd);
1441 install_element_ve(&subscriber_silent_sms_cmd);
1442 install_element_ve(&subscriber_silent_call_start_cmd);
1443 install_element_ve(&subscriber_silent_call_stop_cmd);
1444 install_element_ve(&subscriber_ussd_notify_cmd);
1445 install_element_ve(&subscriber_mstest_close_cmd);
1446 install_element_ve(&subscriber_mstest_open_cmd);
1447 install_element_ve(&subscriber_paging_cmd);
1448 install_element_ve(&show_stats_cmd);
1449 install_element_ve(&show_smsqueue_cmd);
1450 install_element_ve(&logging_fltr_imsi_cmd);
1451
1452 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
1453 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
1454 install_element(ENABLE_NODE, &smsqueue_max_cmd);
1455 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
1456 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
1457 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
1458
1459 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
1460 install_node(&mncc_int_node, config_write_mncc_int);
1461 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
1462 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
1463
1464 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
1465
1466 install_element(CONFIG_NODE, &cfg_hlr_cmd);
1467 install_node(&hlr_node, config_write_hlr);
1468 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
1469 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001470}