blob: b96f6cdbeabce5e8648710a3a42e369b2c7426ed [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,
484 conn->conn_fsm ? osmo_fsm_inst_state_name(conn->conn_fsm) : "-",
485 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,
708 struct vlr_subscr *sender,
709 char *str, uint8_t tp_pid)
710{
711 struct gsm_network *net = receiver->vlr->user_ctx;
712 struct gsm_sms *sms;
713
714 sms = sms_from_text(receiver, sender, 0, str);
715 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]);
816 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
817 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
827 if (!sender) {
828 vty_out(vty, "%% No sender found for %s %s%s",
829 argv[2], argv[3], VTY_NEWLINE);
830 rc = CMD_WARNING;
831 goto err;
832 }
833
834 str = argv_concat(argv, argc, 4);
835 rc = _send_sms_str(vsub, sender, str, 0);
836 talloc_free(str);
837
838err:
839 if (sender)
840 vlr_subscr_put(sender);
841
842 if (vsub)
843 vlr_subscr_put(vsub);
844
845 return rc;
846}
847
848DEFUN(subscriber_silent_sms,
849 subscriber_silent_sms_cmd,
850
851 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
852 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
853{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100854 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
855 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
856 char *str;
857 int rc;
858
859 if (!vsub) {
860 vty_out(vty, "%% No subscriber found for %s %s%s",
861 argv[0], argv[1], VTY_NEWLINE);
862 rc = CMD_WARNING;
863 goto err;
864 }
865
866 if (!sender) {
867 vty_out(vty, "%% No sender found for %s %s%s",
868 argv[2], argv[3], VTY_NEWLINE);
869 rc = CMD_WARNING;
870 goto err;
871 }
872
873 str = argv_concat(argv, argc, 4);
874 rc = _send_sms_str(vsub, sender, str, 64);
875 talloc_free(str);
876
877err:
878 if (sender)
879 vlr_subscr_put(sender);
880
881 if (vsub)
882 vlr_subscr_put(vsub);
883
884 return rc;
885}
886
887#define CHAN_TYPES "(any|tch/f|tch/any|sdcch)"
888#define CHAN_TYPE_HELP \
889 "Any channel\n" \
890 "TCH/F channel\n" \
891 "Any TCH channel\n" \
892 "SDCCH channel\n"
893
894DEFUN(subscriber_silent_call_start,
895 subscriber_silent_call_start_cmd,
896 "subscriber " SUBSCR_TYPES " ID silent-call start (any|tch/f|tch/any|sdcch)",
897 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
898 CHAN_TYPE_HELP)
899{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100900 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
901 int rc, type;
902
903 if (!vsub) {
904 vty_out(vty, "%% No subscriber found for %s %s%s",
905 argv[0], argv[1], VTY_NEWLINE);
906 return CMD_WARNING;
907 }
908
909 if (!strcmp(argv[2], "tch/f"))
910 type = RSL_CHANNEED_TCH_F;
911 else if (!strcmp(argv[2], "tch/any"))
912 type = RSL_CHANNEED_TCH_ForH;
913 else if (!strcmp(argv[2], "sdcch"))
914 type = RSL_CHANNEED_SDCCH;
915 else
916 type = RSL_CHANNEED_ANY; /* Defaults to ANY */
917
918 rc = gsm_silent_call_start(vsub, vty, type);
919 switch (rc) {
920 case -ENODEV:
921 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
922 break;
923 default:
924 if (rc)
925 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
926 else
927 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
928 break;
929 }
930
931 vlr_subscr_put(vsub);
932 return rc ? CMD_WARNING : CMD_SUCCESS;
933}
934
935DEFUN(subscriber_silent_call_stop,
936 subscriber_silent_call_stop_cmd,
937 "subscriber " SUBSCR_TYPES " ID silent-call stop",
938 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
939 CHAN_TYPE_HELP)
940{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100941 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
942 int rc;
943
944 if (!vsub) {
945 vty_out(vty, "%% No subscriber found for %s %s%s",
946 argv[0], argv[1], VTY_NEWLINE);
947 return CMD_WARNING;
948 }
949
950 rc = gsm_silent_call_stop(vsub);
951 switch (rc) {
952 case -ENODEV:
953 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
954 break;
955 case -ENOENT:
956 vty_out(vty, "%% Subscriber has no silent call active%s",
957 VTY_NEWLINE);
958 break;
959 default:
960 if (rc)
961 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
962 else
963 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
964 break;
965 }
966
967 vlr_subscr_put(vsub);
968 return rc ? CMD_WARNING : CMD_SUCCESS;
969}
970
971DEFUN(subscriber_ussd_notify,
972 subscriber_ussd_notify_cmd,
973 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
974 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
975 "Alerting Level 0\n"
976 "Alerting Level 1\n"
977 "Alerting Level 2\n"
978 "Text of USSD message to send\n")
979{
980 char *text;
981 struct gsm_subscriber_connection *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100982 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
983 int level;
984
985 if (!vsub) {
986 vty_out(vty, "%% No subscriber found for %s %s%s",
987 argv[0], argv[1], VTY_NEWLINE);
988 return CMD_WARNING;
989 }
990
991 level = atoi(argv[2]);
992 text = argv_concat(argv, argc, 3);
993 if (!text) {
994 vlr_subscr_put(vsub);
995 return CMD_WARNING;
996 }
997
998 conn = connection_for_subscr(vsub);
999 if (!conn) {
1000 vty_out(vty, "%% An active connection is required for %s %s%s",
1001 argv[0], argv[1], VTY_NEWLINE);
1002 vlr_subscr_put(vsub);
1003 talloc_free(text);
1004 return CMD_WARNING;
1005 }
1006
1007 msc_send_ussd_notify(conn, level, text);
1008 msc_send_ussd_release_complete(conn);
1009
1010 vlr_subscr_put(vsub);
1011 talloc_free(text);
1012 return CMD_SUCCESS;
1013}
1014
1015DEFUN(subscriber_paging,
1016 subscriber_paging_cmd,
1017 "subscriber " SUBSCR_TYPES " ID paging",
1018 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1019{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001020 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1021 struct subscr_request *req;
1022
1023 if (!vsub) {
1024 vty_out(vty, "%% No subscriber found for %s %s%s",
1025 argv[0], argv[1], VTY_NEWLINE);
1026 return CMD_WARNING;
1027 }
1028
1029 req = subscr_request_conn(vsub, NULL, NULL, "manual Paging from VTY");
1030 if (req)
1031 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1032 else
1033 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1034
1035 vlr_subscr_put(vsub);
1036 return req ? CMD_SUCCESS : CMD_WARNING;
1037}
1038
1039static int loop_by_char(uint8_t ch)
1040{
1041 switch (ch) {
1042 case 'a':
1043 return GSM414_LOOP_A;
1044 case 'b':
1045 return GSM414_LOOP_B;
1046 case 'c':
1047 return GSM414_LOOP_C;
1048 case 'd':
1049 return GSM414_LOOP_D;
1050 case 'e':
1051 return GSM414_LOOP_E;
1052 case 'f':
1053 return GSM414_LOOP_F;
1054 case 'i':
1055 return GSM414_LOOP_I;
1056 }
1057 return -1;
1058}
1059
1060DEFUN(subscriber_mstest_close,
1061 subscriber_mstest_close_cmd,
1062 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1063 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1064 "Close a TCH Loop inside the MS\n"
1065 "Loop Type A\n"
1066 "Loop Type B\n"
1067 "Loop Type C\n"
1068 "Loop Type D\n"
1069 "Loop Type E\n"
1070 "Loop Type F\n"
1071 "Loop Type I\n")
1072{
1073 struct gsm_subscriber_connection *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001074 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1075 const char *loop_str;
1076 int loop_mode;
1077
1078 if (!vsub) {
1079 vty_out(vty, "%% No subscriber found for %s %s%s",
1080 argv[0], argv[1], VTY_NEWLINE);
1081 return CMD_WARNING;
1082 }
1083
1084 loop_str = argv[2];
1085 loop_mode = loop_by_char(loop_str[0]);
1086
1087 conn = connection_for_subscr(vsub);
1088 if (!conn) {
1089 vty_out(vty, "%% An active connection is required for %s %s%s",
1090 argv[0], argv[1], VTY_NEWLINE);
1091 vlr_subscr_put(vsub);
1092 return CMD_WARNING;
1093 }
1094
1095 gsm0414_tx_close_tch_loop_cmd(conn, loop_mode);
1096
1097 return CMD_SUCCESS;
1098}
1099
1100DEFUN(subscriber_mstest_open,
1101 subscriber_mstest_open_cmd,
1102 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1103 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1104 "Open a TCH Loop inside the MS\n")
1105{
1106 struct gsm_subscriber_connection *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001107 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1108
1109 if (!vsub) {
1110 vty_out(vty, "%% No subscriber found for %s %s%s",
1111 argv[0], argv[1], VTY_NEWLINE);
1112 return CMD_WARNING;
1113 }
1114
1115 conn = connection_for_subscr(vsub);
1116 if (!conn) {
1117 vty_out(vty, "%% An active connection is required for %s %s%s",
1118 argv[0], argv[1], VTY_NEWLINE);
1119 vlr_subscr_put(vsub);
1120 return CMD_WARNING;
1121 }
1122
1123 gsm0414_tx_open_loop_cmd(conn);
1124
1125 return CMD_SUCCESS;
1126}
1127
1128DEFUN(ena_subscr_expire,
1129 ena_subscr_expire_cmd,
1130 "subscriber " SUBSCR_TYPES " ID expire",
1131 SUBSCR_HELP "Expire the subscriber Now\n")
1132{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001133 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1134 argv[1]);
1135
1136 if (!vsub) {
1137 vty_out(vty, "%% No subscriber found for %s %s%s",
1138 argv[0], argv[1], VTY_NEWLINE);
1139 return CMD_WARNING;
1140 }
1141
1142 if (vlr_subscr_expire(vsub))
1143 vty_out(vty, "%% VLR released subscriber %s%s",
1144 vlr_subscr_name(vsub), VTY_NEWLINE);
1145
1146 if (vsub->use_count > 1)
1147 vty_out(vty, "%% Subscriber %s is still in use,"
1148 " should be released soon%s",
1149 vlr_subscr_name(vsub), VTY_NEWLINE);
1150
1151 vlr_subscr_put(vsub);
1152 return CMD_SUCCESS;
1153}
1154
1155static int scall_cbfn(unsigned int subsys, unsigned int signal,
1156 void *handler_data, void *signal_data)
1157{
1158 struct scall_signal_data *sigdata = signal_data;
1159 struct vty *vty = sigdata->data;
1160
1161 switch (signal) {
1162 case S_SCALL_SUCCESS:
1163 vty_out(vty, "%% silent call success%s", VTY_NEWLINE);
1164 break;
1165 case S_SCALL_EXPIRED:
1166 vty_out(vty, "%% silent call expired paging%s", VTY_NEWLINE);
1167 break;
1168 }
1169 return 0;
1170}
1171
1172DEFUN(show_stats,
1173 show_stats_cmd,
1174 "show statistics",
1175 SHOW_STR "Display network statistics\n")
1176{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001177 vty_out(vty, "Location Update : %lu attach, %lu normal, %lu periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001178 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1179 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1180 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001181 VTY_NEWLINE);
1182 vty_out(vty, "IMSI Detach Indications : %lu%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001183 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001184 VTY_NEWLINE);
1185 vty_out(vty, "Location Updating Results: %lu completed, %lu failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001186 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1187 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001188 VTY_NEWLINE);
1189 vty_out(vty, "SMS MO : %lu submitted, %lu no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001190 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1191 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001192 VTY_NEWLINE);
1193 vty_out(vty, "SMS MT : %lu delivered, %lu no memory, %lu other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001194 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1195 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1196 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001197 VTY_NEWLINE);
1198 vty_out(vty, "MO Calls : %lu setup, %lu connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001199 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1200 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001201 VTY_NEWLINE);
1202 vty_out(vty, "MT Calls : %lu setup, %lu connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001203 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1204 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001205 VTY_NEWLINE);
1206 return CMD_SUCCESS;
1207}
1208
1209DEFUN(show_smsqueue,
1210 show_smsqueue_cmd,
1211 "show sms-queue",
1212 SHOW_STR "Display SMSqueue statistics\n")
1213{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001214 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001215 return CMD_SUCCESS;
1216}
1217
1218DEFUN(smsqueue_trigger,
1219 smsqueue_trigger_cmd,
1220 "sms-queue trigger",
1221 "SMS Queue\n" "Trigger sending messages\n")
1222{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001223 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001224 return CMD_SUCCESS;
1225}
1226
1227DEFUN(smsqueue_max,
1228 smsqueue_max_cmd,
1229 "sms-queue max-pending <1-500>",
1230 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1231{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001232 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001233 return CMD_SUCCESS;
1234}
1235
1236DEFUN(smsqueue_clear,
1237 smsqueue_clear_cmd,
1238 "sms-queue clear",
1239 "SMS Queue\n" "Clear the queue of pending SMS\n")
1240{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001241 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001242 return CMD_SUCCESS;
1243}
1244
1245DEFUN(smsqueue_fail,
1246 smsqueue_fail_cmd,
1247 "sms-queue max-failure <1-500>",
1248 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1249{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001250 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001251 return CMD_SUCCESS;
1252}
1253
1254
1255DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1256 "mncc-int", "Configure internal MNCC handler")
1257{
1258 vty->node = MNCC_INT_NODE;
1259
1260 return CMD_SUCCESS;
1261}
1262
1263static struct cmd_node mncc_int_node = {
1264 MNCC_INT_NODE,
1265 "%s(config-mncc-int)# ",
1266 1,
1267};
1268
1269static const struct value_string tchf_codec_names[] = {
1270 { GSM48_CMODE_SPEECH_V1, "fr" },
1271 { GSM48_CMODE_SPEECH_EFR, "efr" },
1272 { GSM48_CMODE_SPEECH_AMR, "amr" },
1273 { 0, NULL }
1274};
1275
1276static const struct value_string tchh_codec_names[] = {
1277 { GSM48_CMODE_SPEECH_V1, "hr" },
1278 { GSM48_CMODE_SPEECH_AMR, "amr" },
1279 { 0, NULL }
1280};
1281
1282static int config_write_mncc_int(struct vty *vty)
1283{
1284 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1285 vty_out(vty, " default-codec tch-f %s%s",
1286 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1287 VTY_NEWLINE);
1288 vty_out(vty, " default-codec tch-h %s%s",
1289 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1290 VTY_NEWLINE);
1291
1292 return CMD_SUCCESS;
1293}
1294
1295DEFUN(mnccint_def_codec_f,
1296 mnccint_def_codec_f_cmd,
1297 "default-codec tch-f (fr|efr|amr)",
1298 "Set default codec\n" "Codec for TCH/F\n"
1299 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1300{
1301 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1302
1303 return CMD_SUCCESS;
1304}
1305
1306DEFUN(mnccint_def_codec_h,
1307 mnccint_def_codec_h_cmd,
1308 "default-codec tch-h (hr|amr)",
1309 "Set default codec\n" "Codec for TCH/H\n"
1310 "Half-Rate\n" "Adaptive Multi-Rate\n")
1311{
1312 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1313
1314 return CMD_SUCCESS;
1315}
1316
1317
1318DEFUN(logging_fltr_imsi,
1319 logging_fltr_imsi_cmd,
1320 "logging filter imsi IMSI",
1321 LOGGING_STR FILTER_STR
1322 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1323{
1324 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001325 struct log_target *tgt = osmo_log_vty2tgt(vty);
1326 const char *imsi = argv[0];
1327
1328 if (!tgt)
1329 return CMD_WARNING;
1330
1331 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi);
1332
1333 if (!vlr_subscr) {
1334 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1335 argv[0], VTY_NEWLINE);
1336 return CMD_WARNING;
1337 }
1338
1339 log_set_filter_vlr_subscr(tgt, vlr_subscr);
1340 return CMD_SUCCESS;
1341}
1342
1343static struct cmd_node hlr_node = {
1344 HLR_NODE,
1345 "%s(config-hlr)# ",
1346 1,
1347};
1348
1349DEFUN(cfg_hlr, cfg_hlr_cmd,
1350 "hlr", "Configure connection to the HLR")
1351{
1352 vty->node = HLR_NODE;
1353 return CMD_SUCCESS;
1354}
1355
1356DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1357 "Remote GSUP address of the HLR\n"
1358 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1359{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001360 talloc_free((void*)gsmnet->gsup_server_addr_str);
1361 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1362 return CMD_SUCCESS;
1363}
1364
1365DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1366 "Remote GSUP port of the HLR\n"
1367 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1368{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001369 gsmnet->gsup_server_port = atoi(argv[0]);
1370 return CMD_SUCCESS;
1371}
1372
1373static int config_write_hlr(struct vty *vty)
1374{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001375 vty_out(vty, "hlr%s", VTY_NEWLINE);
1376 vty_out(vty, " remote-ip %s%s",
1377 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1378 vty_out(vty, " remote-port %u%s",
1379 gsmnet->gsup_server_port, VTY_NEWLINE);
1380 return CMD_SUCCESS;
1381}
1382
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001383void msc_vty_init(struct gsm_network *msc_network)
1384{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001385 OSMO_ASSERT(gsmnet == NULL);
1386 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001387
1388 osmo_stats_vty_add_cmds();
1389
1390 install_element(CONFIG_NODE, &cfg_net_cmd);
1391 install_node(&net_node, config_write_net);
1392 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1393 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1394 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1395 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1396 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
1397 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1398 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1399 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1400 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1401 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1402 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1403 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1404 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001405
1406 install_element(CONFIG_NODE, &cfg_msc_cmd);
1407 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001408 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
1409 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001410 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
1411 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001412 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
1413 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01001414 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01001415 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001416
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02001417 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001418#ifdef BUILD_IU
Pau Espin Pedrolb8c0cf82018-01-22 13:49:53 +01001419 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 +02001420#endif
Stefan Sperling617ac802018-02-22 17:58:20 +01001421 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001422
1423 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
1424
1425 install_element_ve(&show_subscr_cmd);
1426 install_element_ve(&show_subscr_cache_cmd);
1427 install_element_ve(&show_msc_conn_cmd);
1428 install_element_ve(&show_msc_transaction_cmd);
1429
1430 install_element_ve(&sms_send_pend_cmd);
1431 install_element_ve(&sms_delete_expired_cmd);
1432
1433 install_element_ve(&subscriber_create_cmd);
1434 install_element_ve(&subscriber_send_sms_cmd);
1435 install_element_ve(&subscriber_silent_sms_cmd);
1436 install_element_ve(&subscriber_silent_call_start_cmd);
1437 install_element_ve(&subscriber_silent_call_stop_cmd);
1438 install_element_ve(&subscriber_ussd_notify_cmd);
1439 install_element_ve(&subscriber_mstest_close_cmd);
1440 install_element_ve(&subscriber_mstest_open_cmd);
1441 install_element_ve(&subscriber_paging_cmd);
1442 install_element_ve(&show_stats_cmd);
1443 install_element_ve(&show_smsqueue_cmd);
1444 install_element_ve(&logging_fltr_imsi_cmd);
1445
1446 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
1447 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
1448 install_element(ENABLE_NODE, &smsqueue_max_cmd);
1449 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
1450 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
1451 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
1452
1453 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
1454 install_node(&mncc_int_node, config_write_mncc_int);
1455 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
1456 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
1457
1458 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
1459
1460 install_element(CONFIG_NODE, &cfg_hlr_cmd);
1461 install_node(&hlr_node, config_write_hlr);
1462 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
1463 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001464}