blob: 6e7e8d91d92cf937bc61c4dbd314dd98091e7a8c [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
164DEFUN(cfg_net_rrlp_mode, cfg_net_rrlp_mode_cmd,
165 "rrlp mode (none|ms-based|ms-preferred|ass-preferred)",
166 "Radio Resource Location Protocol\n"
167 "Set the Radio Resource Location Protocol Mode\n"
168 "Don't send RRLP request\n"
169 "Request MS-based location\n"
170 "Request any location, prefer MS-based\n"
171 "Request any location, prefer MS-assisted\n")
172{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100173 gsmnet->rrlp.mode = rrlp_mode_parse(argv[0]);
174
175 return CMD_SUCCESS;
176}
177
178DEFUN(cfg_net_mm_info, cfg_net_mm_info_cmd,
179 "mm info (0|1)",
180 "Mobility Management\n"
181 "Send MM INFO after LOC UPD ACCEPT\n"
182 "Disable\n" "Enable\n")
183{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100184 gsmnet->send_mm_info = atoi(argv[0]);
185
186 return CMD_SUCCESS;
187}
188
189DEFUN(cfg_net_timezone,
190 cfg_net_timezone_cmd,
191 "timezone <-19-19> (0|15|30|45)",
192 "Set the Timezone Offset of the network\n"
193 "Timezone offset (hours)\n"
194 "Timezone offset (00 minutes)\n"
195 "Timezone offset (15 minutes)\n"
196 "Timezone offset (30 minutes)\n"
197 "Timezone offset (45 minutes)\n"
198 )
199{
200 struct gsm_network *net = vty->index;
201 int tzhr = atoi(argv[0]);
202 int tzmn = atoi(argv[1]);
203
204 net->tz.hr = tzhr;
205 net->tz.mn = tzmn;
206 net->tz.dst = 0;
207 net->tz.override = 1;
208
209 return CMD_SUCCESS;
210}
211
212DEFUN(cfg_net_timezone_dst,
213 cfg_net_timezone_dst_cmd,
214 "timezone <-19-19> (0|15|30|45) <0-2>",
215 "Set the Timezone Offset of the network\n"
216 "Timezone offset (hours)\n"
217 "Timezone offset (00 minutes)\n"
218 "Timezone offset (15 minutes)\n"
219 "Timezone offset (30 minutes)\n"
220 "Timezone offset (45 minutes)\n"
221 "DST offset (hours)\n"
222 )
223{
224 struct gsm_network *net = vty->index;
225 int tzhr = atoi(argv[0]);
226 int tzmn = atoi(argv[1]);
227 int tzdst = atoi(argv[2]);
228
229 net->tz.hr = tzhr;
230 net->tz.mn = tzmn;
231 net->tz.dst = tzdst;
232 net->tz.override = 1;
233
234 return CMD_SUCCESS;
235}
236
237DEFUN(cfg_net_no_timezone,
238 cfg_net_no_timezone_cmd,
239 "no timezone",
240 NO_STR
241 "Disable network timezone override, use system tz\n")
242{
243 struct gsm_network *net = vty->index;
244
245 net->tz.override = 0;
246
247 return CMD_SUCCESS;
248}
249
250DEFUN(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
251 "periodic location update <6-1530>",
252 "Periodic Location Updating Interval\n"
253 "Periodic Location Updating Interval\n"
254 "Periodic Location Updating Interval\n"
255 "Periodic Location Updating Interval in Minutes\n")
256{
257 struct gsm_network *net = vty->index;
258
259 net->t3212 = atoi(argv[0]) / 6;
260
261 return CMD_SUCCESS;
262}
263
264DEFUN(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
265 "no periodic location update",
266 NO_STR
267 "Periodic Location Updating Interval\n"
268 "Periodic Location Updating Interval\n"
269 "Periodic Location Updating Interval\n")
270{
271 struct gsm_network *net = vty->index;
272
273 net->t3212 = 0;
274
275 return CMD_SUCCESS;
276}
277
278static int config_write_net(struct vty *vty)
279{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100280 int i;
281
282 vty_out(vty, "network%s", VTY_NEWLINE);
283 vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
284 vty_out(vty, " mobile network code %s%s",
285 osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
286 vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
287 vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
288 vty_out(vty, " encryption a5");
289 for (i = 0; i < 8; i++) {
290 if (gsmnet->a5_encryption_mask & (1 << i))
291 vty_out(vty, " %u", i);
292 }
293 vty_out(vty, "%s", VTY_NEWLINE);
294 vty_out(vty, " authentication %s%s",
295 gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE);
296 vty_out(vty, " rrlp mode %s%s", rrlp_mode_name(gsmnet->rrlp.mode),
297 VTY_NEWLINE);
298 vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
299 if (gsmnet->tz.override != 0) {
300 if (gsmnet->tz.dst)
301 vty_out(vty, " timezone %d %d %d%s",
302 gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
303 VTY_NEWLINE);
304 else
305 vty_out(vty, " timezone %d %d%s",
306 gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
307 }
308 if (gsmnet->t3212 == 0)
309 vty_out(vty, " no periodic location update%s", VTY_NEWLINE);
310 else
311 vty_out(vty, " periodic location update %u%s",
312 gsmnet->t3212 * 6, VTY_NEWLINE);
313
314 if (gsmnet->emergency.route_to_msisdn) {
315 vty_out(vty, " emergency-call route-to-msisdn %s%s",
316 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
317 }
318
319 return CMD_SUCCESS;
320}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200321
322static struct cmd_node msc_node = {
323 MSC_NODE,
324 "%s(config-msc)# ",
325 1,
326};
327
328DEFUN(cfg_msc, cfg_msc_cmd,
329 "msc", "Configure MSC options")
330{
331 vty->node = MSC_NODE;
332 return CMD_SUCCESS;
333}
334
335DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
336 "assign-tmsi",
337 "Assign TMSI during Location Updating.\n")
338{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200339 gsmnet->vlr->cfg.assign_tmsi = true;
340 return CMD_SUCCESS;
341}
342
343DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
344 "no assign-tmsi",
345 NO_STR "Assign TMSI during Location Updating.\n")
346{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200347 gsmnet->vlr->cfg.assign_tmsi = false;
348 return CMD_SUCCESS;
349}
350
Philipp Maierfbf66102017-04-09 12:32:51 +0200351DEFUN(cfg_msc_cs7_instance_a,
352 cfg_msc_cs7_instance_a_cmd,
353 "cs7-instance-a <0-15>",
354 "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
355{
Philipp Maierfbf66102017-04-09 12:32:51 +0200356 gsmnet->a.cs7_instance = atoi(argv[0]);
357 return CMD_SUCCESS;
358}
359
360DEFUN(cfg_msc_cs7_instance_iu,
361 cfg_msc_cs7_instance_iu_cmd,
362 "cs7-instance-iu <0-15>",
363 "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
364{
Philipp Maierfbf66102017-04-09 12:32:51 +0200365 gsmnet->iu.cs7_instance = atoi(argv[0]);
366 return CMD_SUCCESS;
367}
368
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100369DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
370 "auth-tuple-max-reuse-count <-1-2147483647>",
371 "Configure authentication tuple re-use\n"
372 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
373{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100374 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
375 return CMD_SUCCESS;
376}
377
378DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
379 "auth-tuple-reuse-on-error (0|1)",
380 "Configure authentication tuple re-use when HLR is not responsive\n"
381 "0 = never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
382 "1 = if the HLR does not deliver new tuples, do re-use already available old ones.\n")
383{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100384 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
385 return CMD_SUCCESS;
386}
387
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100388DEFUN(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
389 "paging response-timer (default|<1-65535>)",
390 "Configure Paging\n"
391 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
392 " BSS or RNC\n"
393 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
394 "Set paging timeout in seconds\n")
395{
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100396 if (!strcmp(argv[1], "default"))
397 gsmnet->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
398 else
399 gsmnet->paging_response_timer = atoi(argv[0]);
400 return CMD_SUCCESS;
401}
402
Harald Welte69c54a82018-02-09 20:41:14 +0100403DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
404 "emergency-call route-to-msisdn MSISDN",
405 "Configure Emergency Call Behaviour\n"
406 "MSISDN to which Emergency Calls are Dispatched\n"
407 "MSISDN (E.164 Phone Number)\n")
408{
Harald Welte69c54a82018-02-09 20:41:14 +0100409 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
410
411 return CMD_SUCCESS;
412}
413
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200414static int config_write_msc(struct vty *vty)
415{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200416 vty_out(vty, "msc%s", VTY_NEWLINE);
417 vty_out(vty, " %sassign-tmsi%s",
418 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
419
Philipp Maierfbf66102017-04-09 12:32:51 +0200420 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
421 VTY_NEWLINE);
422 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
423 VTY_NEWLINE);
424
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100425 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
426 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
427 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
428 VTY_NEWLINE);
429 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
430 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
431 VTY_NEWLINE);
432
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100433 if (gsmnet->paging_response_timer != MSC_PAGING_RESPONSE_TIMER_DEFAULT)
434 vty_out(vty, " paging response-timer %u%s", gsmnet->paging_response_timer, VTY_NEWLINE);
435
Harald Welte69c54a82018-02-09 20:41:14 +0100436 if (gsmnet->emergency.route_to_msisdn) {
437 vty_out(vty, " emergency-call route-to-msisdn %s%s",
438 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
439 }
440
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200441 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200442#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200443 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200444#endif
445
446 return CMD_SUCCESS;
447}
448
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100449static void vty_conn_hdr(struct vty *vty)
450{
451 vty_out(vty, "--ConnId ------------Subscriber RAN --LAC Use --Tokens C A5 State%s",
452 VTY_NEWLINE);
453}
454
455static void vty_dump_one_conn(struct vty *vty, const struct gsm_subscriber_connection *conn)
456{
457 vty_out(vty, "%08x %22s %3s %5u %3u %08x %c /%1u %27s %s",
458 conn->a.conn_id,
459 conn->vsub ? vlr_subscr_name(conn->vsub) : "-",
460 conn->via_ran == RAN_UTRAN_IU ? "Iu" : "A",
461 conn->lac,
462 conn->use_count,
463 conn->use_tokens,
464 conn->received_cm_service_request ? 'C' : '-',
465 conn->encr.alg_id,
466 conn->conn_fsm ? osmo_fsm_inst_state_name(conn->conn_fsm) : "-",
467 VTY_NEWLINE);
468}
469
470DEFUN(show_msc_conn, show_msc_conn_cmd,
471 "show connection", SHOW_STR "Subscriber Connections\n")
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200472{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100473 struct gsm_subscriber_connection *conn;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200474
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100475 vty_conn_hdr(vty);
476 llist_for_each_entry(conn, &gsmnet->subscr_conns, entry)
477 vty_dump_one_conn(vty, conn);
478
479 return CMD_SUCCESS;
480}
481
482static void vty_trans_hdr(struct vty *vty)
483{
484 vty_out(vty, "------------Subscriber --ConnId -P TI -CallRef Proto%s",
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200485 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100486}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200487
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100488static const char *get_trans_proto_str(const struct gsm_trans *trans)
489{
490 static char buf[256];
491
492 switch (trans->protocol) {
493 case GSM48_PDISC_CC:
494 snprintf(buf, sizeof(buf), "%s %4u %4u",
495 gsm48_cc_state_name(trans->cc.state),
496 trans->cc.Tcurrent,
497 trans->cc.T308_second);
498 break;
499 case GSM48_PDISC_SMS:
500 snprintf(buf, sizeof(buf), "%s %s",
501 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
502 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
503 break;
504 default:
505 buf[0] = '\0';
506 break;
507 }
508
509 return buf;
510}
511
512static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans)
513{
514 vty_out(vty, "%22s %08x %s %02u %08x %s%s",
515 trans->vsub ? vlr_subscr_name(trans->vsub) : "-",
516 trans->conn ? trans->conn->a.conn_id : 0,
517 gsm48_pdisc_name(trans->protocol),
518 trans->transaction_id,
519 trans->callref,
520 get_trans_proto_str(trans), VTY_NEWLINE);
521}
522
523DEFUN(show_msc_transaction, show_msc_transaction_cmd,
524 "show transaction", SHOW_STR "Transactions\n")
525{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100526 struct gsm_trans *trans;
527
528 vty_trans_hdr(vty);
529 llist_for_each_entry(trans, &gsmnet->trans_list, entry)
530 vty_dump_one_trans(vty, trans);
531
532 return CMD_SUCCESS;
533}
534
535static void subscr_dump_full_vty(struct vty *vty, struct vlr_subscr *vsub)
536{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100537 struct gsm_trans *trans;
538 int reqs;
539 struct llist_head *entry;
540
541 if (strlen(vsub->name))
542 vty_out(vty, " Name: '%s'%s", vsub->name, VTY_NEWLINE);
543 if (strlen(vsub->msisdn))
544 vty_out(vty, " Extension: %s%s", vsub->msisdn,
545 VTY_NEWLINE);
546 vty_out(vty, " LAC: %d/0x%x%s",
547 vsub->lac, vsub->lac, VTY_NEWLINE);
548 vty_out(vty, " IMSI: %s%s", vsub->imsi, VTY_NEWLINE);
549 if (vsub->tmsi != GSM_RESERVED_TMSI)
550 vty_out(vty, " TMSI: %08X%s", vsub->tmsi,
551 VTY_NEWLINE);
552 if (vsub->tmsi_new != GSM_RESERVED_TMSI)
553 vty_out(vty, " new TMSI: %08X%s", vsub->tmsi_new,
554 VTY_NEWLINE);
555
556#if 0
557 /* TODO: add this to vlr_subscr? */
558 if (vsub->auth_info.auth_algo != AUTH_ALGO_NONE) {
559 struct gsm_auth_info *i = &vsub->auth_info;
560 vty_out(vty, " A3A8 algorithm id: %d%s",
561 i->auth_algo, VTY_NEWLINE);
562 vty_out(vty, " A3A8 Ki: %s%s",
563 osmo_hexdump(i->a3a8_ki, i->a3a8_ki_len),
564 VTY_NEWLINE);
565 }
566#endif
567
568 if (vsub->last_tuple) {
569 struct gsm_auth_tuple *t = vsub->last_tuple;
570 vty_out(vty, " A3A8 last tuple (used %d times):%s",
571 t->use_count, VTY_NEWLINE);
572 vty_out(vty, " seq # : %d%s",
573 t->key_seq, VTY_NEWLINE);
574 vty_out(vty, " RAND : %s%s",
575 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
576 VTY_NEWLINE);
577 vty_out(vty, " SRES : %s%s",
578 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
579 VTY_NEWLINE);
580 vty_out(vty, " Kc : %s%s",
581 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
582 VTY_NEWLINE);
583 }
584
585 reqs = 0;
586 llist_for_each(entry, &vsub->cs.requests)
587 reqs += 1;
588 vty_out(vty, " Paging: %s paging for %d requests%s",
589 vsub->cs.is_paging ? "is" : "not", reqs, VTY_NEWLINE);
590 vty_out(vty, " Use count: %u%s", vsub->use_count, VTY_NEWLINE);
591
592 /* Connection */
593 if (vsub->msc_conn_ref) {
594 struct gsm_subscriber_connection *conn = vsub->msc_conn_ref;
595 vty_conn_hdr(vty);
596 vty_dump_one_conn(vty, conn);
597 }
598
599 /* Transactions */
600 vty_trans_hdr(vty);
601 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
602 if (trans->vsub != vsub)
603 continue;
604 vty_dump_one_trans(vty, trans);
605 }
606}
607
608/* Subscriber */
609DEFUN(show_subscr_cache,
610 show_subscr_cache_cmd,
611 "show subscriber cache",
612 SHOW_STR "Show information about subscribers\n"
613 "Display contents of subscriber cache\n")
614{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100615 struct vlr_subscr *vsub;
616 int count = 0;
617
618 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
619 if (++count > 100) {
620 vty_out(vty, "%% More than %d subscribers in cache,"
621 " stopping here.%s", count-1, VTY_NEWLINE);
622 break;
623 }
624 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
625 subscr_dump_full_vty(vty, vsub);
Harald Welte69c54a82018-02-09 20:41:14 +0100626 }
627
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200628 return CMD_SUCCESS;
629}
630
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100631DEFUN(sms_send_pend,
632 sms_send_pend_cmd,
633 "sms send pending",
634 "SMS related commands\n" "SMS Sending related commands\n"
635 "Send all pending SMS")
636{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100637 struct gsm_sms *sms;
638 unsigned long long sms_id = 0;
639
640 while (1) {
641 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
642 if (!sms)
643 break;
644
645 if (sms->receiver)
646 gsm411_send_sms_subscr(sms->receiver, sms);
647
648 sms_id = sms->id + 1;
649 }
650
651 return CMD_SUCCESS;
652}
653
654DEFUN(sms_delete_expired,
655 sms_delete_expired_cmd,
656 "sms delete expired",
657 "SMS related commands\n" "SMS Database related commands\n"
658 "Delete all expired SMS")
659{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100660 struct gsm_sms *sms;
661 unsigned long long sms_id = 0;
662 long long num_deleted = 0;
663
664 while (1) {
665 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
666 if (!sms)
667 break;
668
669 /* Skip SMS which are currently queued for sending. */
670 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
671 continue;
672
673 /* Expiration check is performed by the DB layer. */
674 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
675 num_deleted++;
676
677 sms_id = sms->id + 1;
678 }
679
680 if (num_deleted == 0) {
681 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
682 return CMD_WARNING;
683 }
684
685 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
686 return CMD_SUCCESS;
687}
688
689static int _send_sms_str(struct vlr_subscr *receiver,
690 struct vlr_subscr *sender,
691 char *str, uint8_t tp_pid)
692{
693 struct gsm_network *net = receiver->vlr->user_ctx;
694 struct gsm_sms *sms;
695
696 sms = sms_from_text(receiver, sender, 0, str);
697 sms->protocol_id = tp_pid;
698
699 /* store in database for the queue */
700 if (db_sms_store(sms) != 0) {
701 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
702 sms_free(sms);
703 return CMD_WARNING;
704 }
705 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
706
707 sms_free(sms);
708 sms_queue_trigger(net->sms_queue);
709 return CMD_SUCCESS;
710}
711
712static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
713 const char *type,
714 const char *id)
715{
716 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
717 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id);
718 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
719 return vlr_subscr_find_by_imsi(gsmnet->vlr, id);
720 else if (!strcmp(type, "tmsi"))
721 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id));
722
723 return NULL;
724}
725#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
726#define SUBSCR_HELP "Operations on a Subscriber\n" \
727 "Identify subscriber by MSISDN (phone number)\n" \
728 "Legacy alias for 'msisdn'\n" \
729 "Identify subscriber by IMSI\n" \
730 "Identify subscriber by TMSI\n" \
731 "Identify subscriber by database ID\n" \
732 "Identifier for the subscriber\n"
733
734DEFUN(show_subscr,
735 show_subscr_cmd,
736 "show subscriber " SUBSCR_TYPES " ID",
737 SHOW_STR SUBSCR_HELP)
738{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100739 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
740 argv[1]);
741
742 if (!vsub) {
743 vty_out(vty, "%% No subscriber found for %s %s%s",
744 argv[0], argv[1], VTY_NEWLINE);
745 return CMD_WARNING;
746 }
747
748 subscr_dump_full_vty(vty, vsub);
749
750 vlr_subscr_put(vsub);
751
752 return CMD_SUCCESS;
753}
754
755DEFUN(subscriber_create,
756 subscriber_create_cmd,
757 "subscriber create imsi ID",
758 "Operations on a Subscriber\n" \
759 "Create new subscriber\n" \
760 "Identify the subscriber by his IMSI\n" \
761 "Identifier for the subscriber\n")
762{
763 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
764 VTY_NEWLINE);
765 return CMD_WARNING;
766}
767
768DEFUN(subscriber_send_pending_sms,
769 subscriber_send_pending_sms_cmd,
770 "subscriber " SUBSCR_TYPES " ID sms pending-send",
771 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
772{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100773 struct vlr_subscr *vsub;
774 struct gsm_sms *sms;
775
776 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
777 if (!vsub) {
778 vty_out(vty, "%% No subscriber found for %s %s%s",
779 argv[0], argv[1], VTY_NEWLINE);
780 return CMD_WARNING;
781 }
782
783 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
784 if (sms)
785 gsm411_send_sms_subscr(sms->receiver, sms);
786
787 vlr_subscr_put(vsub);
788
789 return CMD_SUCCESS;
790}
791
792DEFUN(subscriber_send_sms,
793 subscriber_send_sms_cmd,
794 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
795 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
796{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100797 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
798 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
799 char *str;
800 int rc;
801
802 if (!vsub) {
803 vty_out(vty, "%% No subscriber found for %s %s%s",
804 argv[0], argv[1], VTY_NEWLINE);
805 rc = CMD_WARNING;
806 goto err;
807 }
808
809 if (!sender) {
810 vty_out(vty, "%% No sender found for %s %s%s",
811 argv[2], argv[3], VTY_NEWLINE);
812 rc = CMD_WARNING;
813 goto err;
814 }
815
816 str = argv_concat(argv, argc, 4);
817 rc = _send_sms_str(vsub, sender, str, 0);
818 talloc_free(str);
819
820err:
821 if (sender)
822 vlr_subscr_put(sender);
823
824 if (vsub)
825 vlr_subscr_put(vsub);
826
827 return rc;
828}
829
830DEFUN(subscriber_silent_sms,
831 subscriber_silent_sms_cmd,
832
833 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
834 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
835{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100836 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
837 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
838 char *str;
839 int rc;
840
841 if (!vsub) {
842 vty_out(vty, "%% No subscriber found for %s %s%s",
843 argv[0], argv[1], VTY_NEWLINE);
844 rc = CMD_WARNING;
845 goto err;
846 }
847
848 if (!sender) {
849 vty_out(vty, "%% No sender found for %s %s%s",
850 argv[2], argv[3], VTY_NEWLINE);
851 rc = CMD_WARNING;
852 goto err;
853 }
854
855 str = argv_concat(argv, argc, 4);
856 rc = _send_sms_str(vsub, sender, str, 64);
857 talloc_free(str);
858
859err:
860 if (sender)
861 vlr_subscr_put(sender);
862
863 if (vsub)
864 vlr_subscr_put(vsub);
865
866 return rc;
867}
868
869#define CHAN_TYPES "(any|tch/f|tch/any|sdcch)"
870#define CHAN_TYPE_HELP \
871 "Any channel\n" \
872 "TCH/F channel\n" \
873 "Any TCH channel\n" \
874 "SDCCH channel\n"
875
876DEFUN(subscriber_silent_call_start,
877 subscriber_silent_call_start_cmd,
878 "subscriber " SUBSCR_TYPES " ID silent-call start (any|tch/f|tch/any|sdcch)",
879 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
880 CHAN_TYPE_HELP)
881{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100882 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
883 int rc, type;
884
885 if (!vsub) {
886 vty_out(vty, "%% No subscriber found for %s %s%s",
887 argv[0], argv[1], VTY_NEWLINE);
888 return CMD_WARNING;
889 }
890
891 if (!strcmp(argv[2], "tch/f"))
892 type = RSL_CHANNEED_TCH_F;
893 else if (!strcmp(argv[2], "tch/any"))
894 type = RSL_CHANNEED_TCH_ForH;
895 else if (!strcmp(argv[2], "sdcch"))
896 type = RSL_CHANNEED_SDCCH;
897 else
898 type = RSL_CHANNEED_ANY; /* Defaults to ANY */
899
900 rc = gsm_silent_call_start(vsub, vty, type);
901 switch (rc) {
902 case -ENODEV:
903 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
904 break;
905 default:
906 if (rc)
907 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
908 else
909 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
910 break;
911 }
912
913 vlr_subscr_put(vsub);
914 return rc ? CMD_WARNING : CMD_SUCCESS;
915}
916
917DEFUN(subscriber_silent_call_stop,
918 subscriber_silent_call_stop_cmd,
919 "subscriber " SUBSCR_TYPES " ID silent-call stop",
920 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
921 CHAN_TYPE_HELP)
922{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100923 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
924 int rc;
925
926 if (!vsub) {
927 vty_out(vty, "%% No subscriber found for %s %s%s",
928 argv[0], argv[1], VTY_NEWLINE);
929 return CMD_WARNING;
930 }
931
932 rc = gsm_silent_call_stop(vsub);
933 switch (rc) {
934 case -ENODEV:
935 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
936 break;
937 case -ENOENT:
938 vty_out(vty, "%% Subscriber has no silent call active%s",
939 VTY_NEWLINE);
940 break;
941 default:
942 if (rc)
943 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
944 else
945 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
946 break;
947 }
948
949 vlr_subscr_put(vsub);
950 return rc ? CMD_WARNING : CMD_SUCCESS;
951}
952
953DEFUN(subscriber_ussd_notify,
954 subscriber_ussd_notify_cmd,
955 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
956 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
957 "Alerting Level 0\n"
958 "Alerting Level 1\n"
959 "Alerting Level 2\n"
960 "Text of USSD message to send\n")
961{
962 char *text;
963 struct gsm_subscriber_connection *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100964 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
965 int level;
966
967 if (!vsub) {
968 vty_out(vty, "%% No subscriber found for %s %s%s",
969 argv[0], argv[1], VTY_NEWLINE);
970 return CMD_WARNING;
971 }
972
973 level = atoi(argv[2]);
974 text = argv_concat(argv, argc, 3);
975 if (!text) {
976 vlr_subscr_put(vsub);
977 return CMD_WARNING;
978 }
979
980 conn = connection_for_subscr(vsub);
981 if (!conn) {
982 vty_out(vty, "%% An active connection is required for %s %s%s",
983 argv[0], argv[1], VTY_NEWLINE);
984 vlr_subscr_put(vsub);
985 talloc_free(text);
986 return CMD_WARNING;
987 }
988
989 msc_send_ussd_notify(conn, level, text);
990 msc_send_ussd_release_complete(conn);
991
992 vlr_subscr_put(vsub);
993 talloc_free(text);
994 return CMD_SUCCESS;
995}
996
997DEFUN(subscriber_paging,
998 subscriber_paging_cmd,
999 "subscriber " SUBSCR_TYPES " ID paging",
1000 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1001{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001002 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1003 struct subscr_request *req;
1004
1005 if (!vsub) {
1006 vty_out(vty, "%% No subscriber found for %s %s%s",
1007 argv[0], argv[1], VTY_NEWLINE);
1008 return CMD_WARNING;
1009 }
1010
1011 req = subscr_request_conn(vsub, NULL, NULL, "manual Paging from VTY");
1012 if (req)
1013 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1014 else
1015 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1016
1017 vlr_subscr_put(vsub);
1018 return req ? CMD_SUCCESS : CMD_WARNING;
1019}
1020
1021static int loop_by_char(uint8_t ch)
1022{
1023 switch (ch) {
1024 case 'a':
1025 return GSM414_LOOP_A;
1026 case 'b':
1027 return GSM414_LOOP_B;
1028 case 'c':
1029 return GSM414_LOOP_C;
1030 case 'd':
1031 return GSM414_LOOP_D;
1032 case 'e':
1033 return GSM414_LOOP_E;
1034 case 'f':
1035 return GSM414_LOOP_F;
1036 case 'i':
1037 return GSM414_LOOP_I;
1038 }
1039 return -1;
1040}
1041
1042DEFUN(subscriber_mstest_close,
1043 subscriber_mstest_close_cmd,
1044 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1045 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1046 "Close a TCH Loop inside the MS\n"
1047 "Loop Type A\n"
1048 "Loop Type B\n"
1049 "Loop Type C\n"
1050 "Loop Type D\n"
1051 "Loop Type E\n"
1052 "Loop Type F\n"
1053 "Loop Type I\n")
1054{
1055 struct gsm_subscriber_connection *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001056 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1057 const char *loop_str;
1058 int loop_mode;
1059
1060 if (!vsub) {
1061 vty_out(vty, "%% No subscriber found for %s %s%s",
1062 argv[0], argv[1], VTY_NEWLINE);
1063 return CMD_WARNING;
1064 }
1065
1066 loop_str = argv[2];
1067 loop_mode = loop_by_char(loop_str[0]);
1068
1069 conn = connection_for_subscr(vsub);
1070 if (!conn) {
1071 vty_out(vty, "%% An active connection is required for %s %s%s",
1072 argv[0], argv[1], VTY_NEWLINE);
1073 vlr_subscr_put(vsub);
1074 return CMD_WARNING;
1075 }
1076
1077 gsm0414_tx_close_tch_loop_cmd(conn, loop_mode);
1078
1079 return CMD_SUCCESS;
1080}
1081
1082DEFUN(subscriber_mstest_open,
1083 subscriber_mstest_open_cmd,
1084 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1085 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1086 "Open a TCH Loop inside the MS\n")
1087{
1088 struct gsm_subscriber_connection *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001089 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1090
1091 if (!vsub) {
1092 vty_out(vty, "%% No subscriber found for %s %s%s",
1093 argv[0], argv[1], VTY_NEWLINE);
1094 return CMD_WARNING;
1095 }
1096
1097 conn = connection_for_subscr(vsub);
1098 if (!conn) {
1099 vty_out(vty, "%% An active connection is required for %s %s%s",
1100 argv[0], argv[1], VTY_NEWLINE);
1101 vlr_subscr_put(vsub);
1102 return CMD_WARNING;
1103 }
1104
1105 gsm0414_tx_open_loop_cmd(conn);
1106
1107 return CMD_SUCCESS;
1108}
1109
1110DEFUN(ena_subscr_expire,
1111 ena_subscr_expire_cmd,
1112 "subscriber " SUBSCR_TYPES " ID expire",
1113 SUBSCR_HELP "Expire the subscriber Now\n")
1114{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001115 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1116 argv[1]);
1117
1118 if (!vsub) {
1119 vty_out(vty, "%% No subscriber found for %s %s%s",
1120 argv[0], argv[1], VTY_NEWLINE);
1121 return CMD_WARNING;
1122 }
1123
1124 if (vlr_subscr_expire(vsub))
1125 vty_out(vty, "%% VLR released subscriber %s%s",
1126 vlr_subscr_name(vsub), VTY_NEWLINE);
1127
1128 if (vsub->use_count > 1)
1129 vty_out(vty, "%% Subscriber %s is still in use,"
1130 " should be released soon%s",
1131 vlr_subscr_name(vsub), VTY_NEWLINE);
1132
1133 vlr_subscr_put(vsub);
1134 return CMD_SUCCESS;
1135}
1136
1137static int scall_cbfn(unsigned int subsys, unsigned int signal,
1138 void *handler_data, void *signal_data)
1139{
1140 struct scall_signal_data *sigdata = signal_data;
1141 struct vty *vty = sigdata->data;
1142
1143 switch (signal) {
1144 case S_SCALL_SUCCESS:
1145 vty_out(vty, "%% silent call success%s", VTY_NEWLINE);
1146 break;
1147 case S_SCALL_EXPIRED:
1148 vty_out(vty, "%% silent call expired paging%s", VTY_NEWLINE);
1149 break;
1150 }
1151 return 0;
1152}
1153
1154DEFUN(show_stats,
1155 show_stats_cmd,
1156 "show statistics",
1157 SHOW_STR "Display network statistics\n")
1158{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001159 vty_out(vty, "Location Update : %lu attach, %lu normal, %lu periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001160 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1161 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1162 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001163 VTY_NEWLINE);
1164 vty_out(vty, "IMSI Detach Indications : %lu%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001165 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001166 VTY_NEWLINE);
1167 vty_out(vty, "Location Updating Results: %lu completed, %lu failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001168 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1169 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001170 VTY_NEWLINE);
1171 vty_out(vty, "SMS MO : %lu submitted, %lu no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001172 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1173 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001174 VTY_NEWLINE);
1175 vty_out(vty, "SMS MT : %lu delivered, %lu no memory, %lu other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001176 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1177 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1178 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001179 VTY_NEWLINE);
1180 vty_out(vty, "MO Calls : %lu setup, %lu connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001181 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1182 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001183 VTY_NEWLINE);
1184 vty_out(vty, "MT Calls : %lu setup, %lu connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001185 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1186 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001187 VTY_NEWLINE);
1188 return CMD_SUCCESS;
1189}
1190
1191DEFUN(show_smsqueue,
1192 show_smsqueue_cmd,
1193 "show sms-queue",
1194 SHOW_STR "Display SMSqueue statistics\n")
1195{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001196 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001197 return CMD_SUCCESS;
1198}
1199
1200DEFUN(smsqueue_trigger,
1201 smsqueue_trigger_cmd,
1202 "sms-queue trigger",
1203 "SMS Queue\n" "Trigger sending messages\n")
1204{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001205 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001206 return CMD_SUCCESS;
1207}
1208
1209DEFUN(smsqueue_max,
1210 smsqueue_max_cmd,
1211 "sms-queue max-pending <1-500>",
1212 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1213{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001214 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001215 return CMD_SUCCESS;
1216}
1217
1218DEFUN(smsqueue_clear,
1219 smsqueue_clear_cmd,
1220 "sms-queue clear",
1221 "SMS Queue\n" "Clear the queue of pending SMS\n")
1222{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001223 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001224 return CMD_SUCCESS;
1225}
1226
1227DEFUN(smsqueue_fail,
1228 smsqueue_fail_cmd,
1229 "sms-queue max-failure <1-500>",
1230 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1231{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001232 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001233 return CMD_SUCCESS;
1234}
1235
1236
1237DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1238 "mncc-int", "Configure internal MNCC handler")
1239{
1240 vty->node = MNCC_INT_NODE;
1241
1242 return CMD_SUCCESS;
1243}
1244
1245static struct cmd_node mncc_int_node = {
1246 MNCC_INT_NODE,
1247 "%s(config-mncc-int)# ",
1248 1,
1249};
1250
1251static const struct value_string tchf_codec_names[] = {
1252 { GSM48_CMODE_SPEECH_V1, "fr" },
1253 { GSM48_CMODE_SPEECH_EFR, "efr" },
1254 { GSM48_CMODE_SPEECH_AMR, "amr" },
1255 { 0, NULL }
1256};
1257
1258static const struct value_string tchh_codec_names[] = {
1259 { GSM48_CMODE_SPEECH_V1, "hr" },
1260 { GSM48_CMODE_SPEECH_AMR, "amr" },
1261 { 0, NULL }
1262};
1263
1264static int config_write_mncc_int(struct vty *vty)
1265{
1266 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1267 vty_out(vty, " default-codec tch-f %s%s",
1268 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1269 VTY_NEWLINE);
1270 vty_out(vty, " default-codec tch-h %s%s",
1271 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1272 VTY_NEWLINE);
1273
1274 return CMD_SUCCESS;
1275}
1276
1277DEFUN(mnccint_def_codec_f,
1278 mnccint_def_codec_f_cmd,
1279 "default-codec tch-f (fr|efr|amr)",
1280 "Set default codec\n" "Codec for TCH/F\n"
1281 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1282{
1283 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1284
1285 return CMD_SUCCESS;
1286}
1287
1288DEFUN(mnccint_def_codec_h,
1289 mnccint_def_codec_h_cmd,
1290 "default-codec tch-h (hr|amr)",
1291 "Set default codec\n" "Codec for TCH/H\n"
1292 "Half-Rate\n" "Adaptive Multi-Rate\n")
1293{
1294 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1295
1296 return CMD_SUCCESS;
1297}
1298
1299
1300DEFUN(logging_fltr_imsi,
1301 logging_fltr_imsi_cmd,
1302 "logging filter imsi IMSI",
1303 LOGGING_STR FILTER_STR
1304 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1305{
1306 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001307 struct log_target *tgt = osmo_log_vty2tgt(vty);
1308 const char *imsi = argv[0];
1309
1310 if (!tgt)
1311 return CMD_WARNING;
1312
1313 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi);
1314
1315 if (!vlr_subscr) {
1316 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1317 argv[0], VTY_NEWLINE);
1318 return CMD_WARNING;
1319 }
1320
1321 log_set_filter_vlr_subscr(tgt, vlr_subscr);
1322 return CMD_SUCCESS;
1323}
1324
1325static struct cmd_node hlr_node = {
1326 HLR_NODE,
1327 "%s(config-hlr)# ",
1328 1,
1329};
1330
1331DEFUN(cfg_hlr, cfg_hlr_cmd,
1332 "hlr", "Configure connection to the HLR")
1333{
1334 vty->node = HLR_NODE;
1335 return CMD_SUCCESS;
1336}
1337
1338DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1339 "Remote GSUP address of the HLR\n"
1340 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1341{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001342 talloc_free((void*)gsmnet->gsup_server_addr_str);
1343 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1344 return CMD_SUCCESS;
1345}
1346
1347DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1348 "Remote GSUP port of the HLR\n"
1349 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1350{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001351 gsmnet->gsup_server_port = atoi(argv[0]);
1352 return CMD_SUCCESS;
1353}
1354
1355static int config_write_hlr(struct vty *vty)
1356{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001357 vty_out(vty, "hlr%s", VTY_NEWLINE);
1358 vty_out(vty, " remote-ip %s%s",
1359 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1360 vty_out(vty, " remote-port %u%s",
1361 gsmnet->gsup_server_port, VTY_NEWLINE);
1362 return CMD_SUCCESS;
1363}
1364
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001365void msc_vty_init(struct gsm_network *msc_network)
1366{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001367 OSMO_ASSERT(gsmnet == NULL);
1368 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001369
1370 osmo_stats_vty_add_cmds();
1371
1372 install_element(CONFIG_NODE, &cfg_net_cmd);
1373 install_node(&net_node, config_write_net);
1374 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1375 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1376 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1377 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1378 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
1379 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1380 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1381 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1382 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1383 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1384 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1385 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1386 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001387
1388 install_element(CONFIG_NODE, &cfg_msc_cmd);
1389 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001390 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
1391 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001392 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
1393 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001394 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
1395 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01001396 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01001397 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001398
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02001399 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001400#ifdef BUILD_IU
Pau Espin Pedrolb8c0cf82018-01-22 13:49:53 +01001401 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 +02001402#endif
Stefan Sperling617ac802018-02-22 17:58:20 +01001403 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001404
1405 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
1406
1407 install_element_ve(&show_subscr_cmd);
1408 install_element_ve(&show_subscr_cache_cmd);
1409 install_element_ve(&show_msc_conn_cmd);
1410 install_element_ve(&show_msc_transaction_cmd);
1411
1412 install_element_ve(&sms_send_pend_cmd);
1413 install_element_ve(&sms_delete_expired_cmd);
1414
1415 install_element_ve(&subscriber_create_cmd);
1416 install_element_ve(&subscriber_send_sms_cmd);
1417 install_element_ve(&subscriber_silent_sms_cmd);
1418 install_element_ve(&subscriber_silent_call_start_cmd);
1419 install_element_ve(&subscriber_silent_call_stop_cmd);
1420 install_element_ve(&subscriber_ussd_notify_cmd);
1421 install_element_ve(&subscriber_mstest_close_cmd);
1422 install_element_ve(&subscriber_mstest_open_cmd);
1423 install_element_ve(&subscriber_paging_cmd);
1424 install_element_ve(&show_stats_cmd);
1425 install_element_ve(&show_smsqueue_cmd);
1426 install_element_ve(&logging_fltr_imsi_cmd);
1427
1428 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
1429 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
1430 install_element(ENABLE_NODE, &smsqueue_max_cmd);
1431 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
1432 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
1433 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
1434
1435 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
1436 install_node(&mncc_int_node, config_write_mncc_int);
1437 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
1438 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
1439
1440 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
1441
1442 install_element(CONFIG_NODE, &cfg_hlr_cmd);
1443 install_node(&hlr_node, config_write_hlr);
1444 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
1445 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001446}