blob: d10028eef6e0dfce2e02f39c7677382ddf627245 [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{
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100383#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200384 gsmnet->iu.cs7_instance = atoi(argv[0]);
385 return CMD_SUCCESS;
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100386#else
387 vty_out(vty, "WARNING: 'cs7-instance-iu' without effect: built without Iu support%s",
388 VTY_NEWLINE);
389 return CMD_WARNING;
390#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200391}
392
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100393DEFUN(cfg_msc_auth_tuple_max_reuse_count, cfg_msc_auth_tuple_max_reuse_count_cmd,
394 "auth-tuple-max-reuse-count <-1-2147483647>",
395 "Configure authentication tuple re-use\n"
396 "0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
397{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100398 gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
399 return CMD_SUCCESS;
400}
401
402DEFUN(cfg_msc_auth_tuple_reuse_on_error, cfg_msc_auth_tuple_reuse_on_error_cmd,
403 "auth-tuple-reuse-on-error (0|1)",
404 "Configure authentication tuple re-use when HLR is not responsive\n"
405 "0 = never re-use auth tuples beyond auth-tuple-max-reuse-count (default)\n"
406 "1 = if the HLR does not deliver new tuples, do re-use already available old ones.\n")
407{
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100408 gsmnet->vlr->cfg.auth_reuse_old_sets_on_error = atoi(argv[0]) ? true : false;
409 return CMD_SUCCESS;
410}
411
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100412DEFUN(cfg_msc_paging_response_timer, cfg_msc_paging_response_timer_cmd,
413 "paging response-timer (default|<1-65535>)",
414 "Configure Paging\n"
415 "Set Paging timeout, the minimum time to pass between (unsuccessful) Pagings sent towards"
416 " BSS or RNC\n"
417 "Set to default timeout (" OSMO_STRINGIFY_VAL(MSC_PAGING_RESPONSE_TIMER_DEFAULT) " seconds)\n"
418 "Set paging timeout in seconds\n")
419{
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100420 if (!strcmp(argv[1], "default"))
421 gsmnet->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT;
422 else
423 gsmnet->paging_response_timer = atoi(argv[0]);
424 return CMD_SUCCESS;
425}
426
Harald Welte69c54a82018-02-09 20:41:14 +0100427DEFUN(cfg_msc_emergency_msisdn, cfg_msc_emergency_msisdn_cmd,
428 "emergency-call route-to-msisdn MSISDN",
429 "Configure Emergency Call Behaviour\n"
430 "MSISDN to which Emergency Calls are Dispatched\n"
431 "MSISDN (E.164 Phone Number)\n")
432{
Harald Welte69c54a82018-02-09 20:41:14 +0100433 osmo_talloc_replace_string(gsmnet, &gsmnet->emergency.route_to_msisdn, argv[0]);
434
435 return CMD_SUCCESS;
436}
437
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200438static int config_write_msc(struct vty *vty)
439{
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200440 vty_out(vty, "msc%s", VTY_NEWLINE);
441 vty_out(vty, " %sassign-tmsi%s",
442 gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
443
Philipp Maierfbf66102017-04-09 12:32:51 +0200444 vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
445 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100446#if BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200447 vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
448 VTY_NEWLINE);
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +0100449#endif
Philipp Maierfbf66102017-04-09 12:32:51 +0200450
Neels Hofmeyr97ce0152017-10-29 02:10:38 +0100451 if (gsmnet->vlr->cfg.auth_tuple_max_reuse_count)
452 vty_out(vty, " auth-tuple-max-reuse-count %d%s",
453 OSMO_MAX(-1, gsmnet->vlr->cfg.auth_tuple_max_reuse_count),
454 VTY_NEWLINE);
455 if (gsmnet->vlr->cfg.auth_reuse_old_sets_on_error)
456 vty_out(vty, " auth-tuple-reuse-on-error 1%s",
457 VTY_NEWLINE);
458
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100459 if (gsmnet->paging_response_timer != MSC_PAGING_RESPONSE_TIMER_DEFAULT)
460 vty_out(vty, " paging response-timer %u%s", gsmnet->paging_response_timer, VTY_NEWLINE);
461
Harald Welte69c54a82018-02-09 20:41:14 +0100462 if (gsmnet->emergency.route_to_msisdn) {
463 vty_out(vty, " emergency-call route-to-msisdn %s%s",
464 gsmnet->emergency.route_to_msisdn, VTY_NEWLINE);
465 }
466
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200467 mgcp_client_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200468#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200469 ranap_iu_vty_config_write(vty, " ");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200470#endif
471
472 return CMD_SUCCESS;
473}
474
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100475static void vty_conn_hdr(struct vty *vty)
476{
477 vty_out(vty, "--ConnId ------------Subscriber RAN --LAC Use --Tokens C A5 State%s",
478 VTY_NEWLINE);
479}
480
481static void vty_dump_one_conn(struct vty *vty, const struct gsm_subscriber_connection *conn)
482{
483 vty_out(vty, "%08x %22s %3s %5u %3u %08x %c /%1u %27s %s",
484 conn->a.conn_id,
485 conn->vsub ? vlr_subscr_name(conn->vsub) : "-",
486 conn->via_ran == RAN_UTRAN_IU ? "Iu" : "A",
487 conn->lac,
488 conn->use_count,
489 conn->use_tokens,
490 conn->received_cm_service_request ? 'C' : '-',
491 conn->encr.alg_id,
Neels Hofmeyr4d3a66b2018-03-31 18:45:59 +0200492 conn->fi ? osmo_fsm_inst_state_name(conn->fi) : "-",
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100493 VTY_NEWLINE);
494}
495
496DEFUN(show_msc_conn, show_msc_conn_cmd,
497 "show connection", SHOW_STR "Subscriber Connections\n")
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200498{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100499 struct gsm_subscriber_connection *conn;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200500
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100501 vty_conn_hdr(vty);
502 llist_for_each_entry(conn, &gsmnet->subscr_conns, entry)
503 vty_dump_one_conn(vty, conn);
504
505 return CMD_SUCCESS;
506}
507
508static void vty_trans_hdr(struct vty *vty)
509{
510 vty_out(vty, "------------Subscriber --ConnId -P TI -CallRef Proto%s",
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200511 VTY_NEWLINE);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100512}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200513
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100514static const char *get_trans_proto_str(const struct gsm_trans *trans)
515{
516 static char buf[256];
517
518 switch (trans->protocol) {
519 case GSM48_PDISC_CC:
520 snprintf(buf, sizeof(buf), "%s %4u %4u",
521 gsm48_cc_state_name(trans->cc.state),
522 trans->cc.Tcurrent,
523 trans->cc.T308_second);
524 break;
525 case GSM48_PDISC_SMS:
526 snprintf(buf, sizeof(buf), "%s %s",
527 gsm411_cp_state_name(trans->sms.smc_inst.cp_state),
528 gsm411_rp_state_name(trans->sms.smr_inst.rp_state));
529 break;
530 default:
531 buf[0] = '\0';
532 break;
533 }
534
535 return buf;
536}
537
538static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans)
539{
540 vty_out(vty, "%22s %08x %s %02u %08x %s%s",
541 trans->vsub ? vlr_subscr_name(trans->vsub) : "-",
542 trans->conn ? trans->conn->a.conn_id : 0,
543 gsm48_pdisc_name(trans->protocol),
544 trans->transaction_id,
545 trans->callref,
546 get_trans_proto_str(trans), VTY_NEWLINE);
547}
548
549DEFUN(show_msc_transaction, show_msc_transaction_cmd,
550 "show transaction", SHOW_STR "Transactions\n")
551{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100552 struct gsm_trans *trans;
553
554 vty_trans_hdr(vty);
555 llist_for_each_entry(trans, &gsmnet->trans_list, entry)
556 vty_dump_one_trans(vty, trans);
557
558 return CMD_SUCCESS;
559}
560
561static void subscr_dump_full_vty(struct vty *vty, struct vlr_subscr *vsub)
562{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100563 struct gsm_trans *trans;
564 int reqs;
565 struct llist_head *entry;
566
567 if (strlen(vsub->name))
568 vty_out(vty, " Name: '%s'%s", vsub->name, VTY_NEWLINE);
569 if (strlen(vsub->msisdn))
570 vty_out(vty, " Extension: %s%s", vsub->msisdn,
571 VTY_NEWLINE);
572 vty_out(vty, " LAC: %d/0x%x%s",
573 vsub->lac, vsub->lac, VTY_NEWLINE);
574 vty_out(vty, " IMSI: %s%s", vsub->imsi, VTY_NEWLINE);
575 if (vsub->tmsi != GSM_RESERVED_TMSI)
576 vty_out(vty, " TMSI: %08X%s", vsub->tmsi,
577 VTY_NEWLINE);
578 if (vsub->tmsi_new != GSM_RESERVED_TMSI)
579 vty_out(vty, " new TMSI: %08X%s", vsub->tmsi_new,
580 VTY_NEWLINE);
581
582#if 0
583 /* TODO: add this to vlr_subscr? */
584 if (vsub->auth_info.auth_algo != AUTH_ALGO_NONE) {
585 struct gsm_auth_info *i = &vsub->auth_info;
586 vty_out(vty, " A3A8 algorithm id: %d%s",
587 i->auth_algo, VTY_NEWLINE);
588 vty_out(vty, " A3A8 Ki: %s%s",
589 osmo_hexdump(i->a3a8_ki, i->a3a8_ki_len),
590 VTY_NEWLINE);
591 }
592#endif
593
594 if (vsub->last_tuple) {
595 struct gsm_auth_tuple *t = vsub->last_tuple;
596 vty_out(vty, " A3A8 last tuple (used %d times):%s",
597 t->use_count, VTY_NEWLINE);
598 vty_out(vty, " seq # : %d%s",
599 t->key_seq, VTY_NEWLINE);
600 vty_out(vty, " RAND : %s%s",
601 osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
602 VTY_NEWLINE);
603 vty_out(vty, " SRES : %s%s",
604 osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
605 VTY_NEWLINE);
606 vty_out(vty, " Kc : %s%s",
607 osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
608 VTY_NEWLINE);
609 }
610
611 reqs = 0;
612 llist_for_each(entry, &vsub->cs.requests)
613 reqs += 1;
614 vty_out(vty, " Paging: %s paging for %d requests%s",
615 vsub->cs.is_paging ? "is" : "not", reqs, VTY_NEWLINE);
616 vty_out(vty, " Use count: %u%s", vsub->use_count, VTY_NEWLINE);
617
618 /* Connection */
619 if (vsub->msc_conn_ref) {
620 struct gsm_subscriber_connection *conn = vsub->msc_conn_ref;
621 vty_conn_hdr(vty);
622 vty_dump_one_conn(vty, conn);
623 }
624
625 /* Transactions */
626 vty_trans_hdr(vty);
627 llist_for_each_entry(trans, &gsmnet->trans_list, entry) {
628 if (trans->vsub != vsub)
629 continue;
630 vty_dump_one_trans(vty, trans);
631 }
632}
633
634/* Subscriber */
635DEFUN(show_subscr_cache,
636 show_subscr_cache_cmd,
637 "show subscriber cache",
638 SHOW_STR "Show information about subscribers\n"
639 "Display contents of subscriber cache\n")
640{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100641 struct vlr_subscr *vsub;
642 int count = 0;
643
644 llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
645 if (++count > 100) {
646 vty_out(vty, "%% More than %d subscribers in cache,"
647 " stopping here.%s", count-1, VTY_NEWLINE);
648 break;
649 }
650 vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
651 subscr_dump_full_vty(vty, vsub);
Harald Welte69c54a82018-02-09 20:41:14 +0100652 }
653
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200654 return CMD_SUCCESS;
655}
656
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100657DEFUN(sms_send_pend,
658 sms_send_pend_cmd,
659 "sms send pending",
660 "SMS related commands\n" "SMS Sending related commands\n"
661 "Send all pending SMS")
662{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100663 struct gsm_sms *sms;
664 unsigned long long sms_id = 0;
665
666 while (1) {
667 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
668 if (!sms)
669 break;
670
671 if (sms->receiver)
672 gsm411_send_sms_subscr(sms->receiver, sms);
673
674 sms_id = sms->id + 1;
675 }
676
677 return CMD_SUCCESS;
678}
679
680DEFUN(sms_delete_expired,
681 sms_delete_expired_cmd,
682 "sms delete expired",
683 "SMS related commands\n" "SMS Database related commands\n"
684 "Delete all expired SMS")
685{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100686 struct gsm_sms *sms;
687 unsigned long long sms_id = 0;
688 long long num_deleted = 0;
689
690 while (1) {
691 sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
692 if (!sms)
693 break;
694
695 /* Skip SMS which are currently queued for sending. */
696 if (sms_queue_sms_is_pending(gsmnet->sms_queue, sms->id))
697 continue;
698
699 /* Expiration check is performed by the DB layer. */
700 if (db_sms_delete_expired_message_by_id(sms->id) == 0)
701 num_deleted++;
702
703 sms_id = sms->id + 1;
704 }
705
706 if (num_deleted == 0) {
707 vty_out(vty, "No expired SMS in database%s", VTY_NEWLINE);
708 return CMD_WARNING;
709 }
710
711 vty_out(vty, "Deleted %llu expired SMS from database%s", num_deleted, VTY_NEWLINE);
712 return CMD_SUCCESS;
713}
714
715static int _send_sms_str(struct vlr_subscr *receiver,
Harald Welte39b55482018-04-09 19:19:33 +0200716 const char *sender_msisdn,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100717 char *str, uint8_t tp_pid)
718{
719 struct gsm_network *net = receiver->vlr->user_ctx;
720 struct gsm_sms *sms;
721
Harald Welte39b55482018-04-09 19:19:33 +0200722 sms = sms_from_text(receiver, sender_msisdn, 0, str);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100723 sms->protocol_id = tp_pid;
724
725 /* store in database for the queue */
726 if (db_sms_store(sms) != 0) {
727 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
728 sms_free(sms);
729 return CMD_WARNING;
730 }
731 LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
732
733 sms_free(sms);
734 sms_queue_trigger(net->sms_queue);
735 return CMD_SUCCESS;
736}
737
738static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
739 const char *type,
740 const char *id)
741{
742 if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
743 return vlr_subscr_find_by_msisdn(gsmnet->vlr, id);
744 else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
745 return vlr_subscr_find_by_imsi(gsmnet->vlr, id);
746 else if (!strcmp(type, "tmsi"))
747 return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id));
748
749 return NULL;
750}
751#define SUBSCR_TYPES "(msisdn|extension|imsi|tmsi|id)"
752#define SUBSCR_HELP "Operations on a Subscriber\n" \
753 "Identify subscriber by MSISDN (phone number)\n" \
754 "Legacy alias for 'msisdn'\n" \
755 "Identify subscriber by IMSI\n" \
756 "Identify subscriber by TMSI\n" \
757 "Identify subscriber by database ID\n" \
758 "Identifier for the subscriber\n"
759
760DEFUN(show_subscr,
761 show_subscr_cmd,
762 "show subscriber " SUBSCR_TYPES " ID",
763 SHOW_STR SUBSCR_HELP)
764{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100765 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
766 argv[1]);
767
768 if (!vsub) {
769 vty_out(vty, "%% No subscriber found for %s %s%s",
770 argv[0], argv[1], VTY_NEWLINE);
771 return CMD_WARNING;
772 }
773
774 subscr_dump_full_vty(vty, vsub);
775
776 vlr_subscr_put(vsub);
777
778 return CMD_SUCCESS;
779}
780
781DEFUN(subscriber_create,
782 subscriber_create_cmd,
783 "subscriber create imsi ID",
784 "Operations on a Subscriber\n" \
785 "Create new subscriber\n" \
786 "Identify the subscriber by his IMSI\n" \
787 "Identifier for the subscriber\n")
788{
789 vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
790 VTY_NEWLINE);
791 return CMD_WARNING;
792}
793
794DEFUN(subscriber_send_pending_sms,
795 subscriber_send_pending_sms_cmd,
796 "subscriber " SUBSCR_TYPES " ID sms pending-send",
797 SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
798{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100799 struct vlr_subscr *vsub;
800 struct gsm_sms *sms;
801
802 vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
803 if (!vsub) {
804 vty_out(vty, "%% No subscriber found for %s %s%s",
805 argv[0], argv[1], VTY_NEWLINE);
806 return CMD_WARNING;
807 }
808
809 sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
810 if (sms)
811 gsm411_send_sms_subscr(sms->receiver, sms);
812
813 vlr_subscr_put(vsub);
814
815 return CMD_SUCCESS;
816}
817
818DEFUN(subscriber_send_sms,
819 subscriber_send_sms_cmd,
820 "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
821 SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
822{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100823 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +0200824 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100825 char *str;
826 int rc;
827
828 if (!vsub) {
829 vty_out(vty, "%% No subscriber found for %s %s%s",
830 argv[0], argv[1], VTY_NEWLINE);
831 rc = CMD_WARNING;
832 goto err;
833 }
834
Harald Welte39b55482018-04-09 19:19:33 +0200835 if (!strcmp(argv[2], "msisdn"))
836 sender_msisdn = argv[3];
837 else {
838 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
839 if (!sender) {
840 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
841 rc = CMD_WARNING;
842 goto err;
843 }
844 sender_msisdn = sender->msisdn;
845 vlr_subscr_put(sender);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100846 }
847
848 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +0200849 rc = _send_sms_str(vsub, sender_msisdn, str, 0);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100850 talloc_free(str);
851
852err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100853 if (vsub)
854 vlr_subscr_put(vsub);
855
856 return rc;
857}
858
859DEFUN(subscriber_silent_sms,
860 subscriber_silent_sms_cmd,
861
862 "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
863 SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
864{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100865 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
Harald Welte39b55482018-04-09 19:19:33 +0200866 const char *sender_msisdn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100867 char *str;
868 int rc;
869
870 if (!vsub) {
871 vty_out(vty, "%% No subscriber found for %s %s%s",
872 argv[0], argv[1], VTY_NEWLINE);
873 rc = CMD_WARNING;
874 goto err;
875 }
876
Harald Welte39b55482018-04-09 19:19:33 +0200877 if (!strcmp(argv[2], "msisdn")) {
878 sender_msisdn = argv[3];
879 } else {
880 struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
881 if (!sender) {
882 vty_out(vty, "%% No sender found for %s %s%s", argv[2], argv[3], VTY_NEWLINE);
883 rc = CMD_WARNING;
884 goto err;
885 }
886 sender_msisdn = sender->msisdn;
887 vlr_subscr_put(sender);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100888 }
889
890 str = argv_concat(argv, argc, 4);
Harald Welte39b55482018-04-09 19:19:33 +0200891 rc = _send_sms_str(vsub, sender_msisdn, str, 64);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100892 talloc_free(str);
893
894err:
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100895 if (vsub)
896 vlr_subscr_put(vsub);
897
898 return rc;
899}
900
901#define CHAN_TYPES "(any|tch/f|tch/any|sdcch)"
902#define CHAN_TYPE_HELP \
903 "Any channel\n" \
904 "TCH/F channel\n" \
905 "Any TCH channel\n" \
906 "SDCCH channel\n"
907
908DEFUN(subscriber_silent_call_start,
909 subscriber_silent_call_start_cmd,
910 "subscriber " SUBSCR_TYPES " ID silent-call start (any|tch/f|tch/any|sdcch)",
911 SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
912 CHAN_TYPE_HELP)
913{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100914 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
915 int rc, type;
916
917 if (!vsub) {
918 vty_out(vty, "%% No subscriber found for %s %s%s",
919 argv[0], argv[1], VTY_NEWLINE);
920 return CMD_WARNING;
921 }
922
923 if (!strcmp(argv[2], "tch/f"))
924 type = RSL_CHANNEED_TCH_F;
925 else if (!strcmp(argv[2], "tch/any"))
926 type = RSL_CHANNEED_TCH_ForH;
927 else if (!strcmp(argv[2], "sdcch"))
928 type = RSL_CHANNEED_SDCCH;
929 else
930 type = RSL_CHANNEED_ANY; /* Defaults to ANY */
931
932 rc = gsm_silent_call_start(vsub, vty, type);
933 switch (rc) {
934 case -ENODEV:
935 vty_out(vty, "%% Subscriber not attached%s", VTY_NEWLINE);
936 break;
937 default:
938 if (rc)
939 vty_out(vty, "%% Cannot start silent call (rc=%d)%s", rc, VTY_NEWLINE);
940 else
941 vty_out(vty, "%% Silent call initiated%s", VTY_NEWLINE);
942 break;
943 }
944
945 vlr_subscr_put(vsub);
946 return rc ? CMD_WARNING : CMD_SUCCESS;
947}
948
949DEFUN(subscriber_silent_call_stop,
950 subscriber_silent_call_stop_cmd,
951 "subscriber " SUBSCR_TYPES " ID silent-call stop",
952 SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
953 CHAN_TYPE_HELP)
954{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100955 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
956 int rc;
957
958 if (!vsub) {
959 vty_out(vty, "%% No subscriber found for %s %s%s",
960 argv[0], argv[1], VTY_NEWLINE);
961 return CMD_WARNING;
962 }
963
964 rc = gsm_silent_call_stop(vsub);
965 switch (rc) {
966 case -ENODEV:
967 vty_out(vty, "%% No active connection for subscriber%s", VTY_NEWLINE);
968 break;
969 case -ENOENT:
970 vty_out(vty, "%% Subscriber has no silent call active%s",
971 VTY_NEWLINE);
972 break;
973 default:
974 if (rc)
975 vty_out(vty, "%% Cannot stop silent call (rc=%d)%s", rc, VTY_NEWLINE);
976 else
977 vty_out(vty, "%% Silent call stopped%s", VTY_NEWLINE);
978 break;
979 }
980
981 vlr_subscr_put(vsub);
982 return rc ? CMD_WARNING : CMD_SUCCESS;
983}
984
985DEFUN(subscriber_ussd_notify,
986 subscriber_ussd_notify_cmd,
987 "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
988 SUBSCR_HELP "Send a USSD notify to the subscriber\n"
989 "Alerting Level 0\n"
990 "Alerting Level 1\n"
991 "Alerting Level 2\n"
992 "Text of USSD message to send\n")
993{
994 char *text;
995 struct gsm_subscriber_connection *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100996 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
997 int level;
998
999 if (!vsub) {
1000 vty_out(vty, "%% No subscriber found for %s %s%s",
1001 argv[0], argv[1], VTY_NEWLINE);
1002 return CMD_WARNING;
1003 }
1004
1005 level = atoi(argv[2]);
1006 text = argv_concat(argv, argc, 3);
1007 if (!text) {
1008 vlr_subscr_put(vsub);
1009 return CMD_WARNING;
1010 }
1011
1012 conn = connection_for_subscr(vsub);
1013 if (!conn) {
1014 vty_out(vty, "%% An active connection is required for %s %s%s",
1015 argv[0], argv[1], VTY_NEWLINE);
1016 vlr_subscr_put(vsub);
1017 talloc_free(text);
1018 return CMD_WARNING;
1019 }
1020
1021 msc_send_ussd_notify(conn, level, text);
1022 msc_send_ussd_release_complete(conn);
1023
1024 vlr_subscr_put(vsub);
1025 talloc_free(text);
1026 return CMD_SUCCESS;
1027}
1028
1029DEFUN(subscriber_paging,
1030 subscriber_paging_cmd,
1031 "subscriber " SUBSCR_TYPES " ID paging",
1032 SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n")
1033{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001034 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1035 struct subscr_request *req;
1036
1037 if (!vsub) {
1038 vty_out(vty, "%% No subscriber found for %s %s%s",
1039 argv[0], argv[1], VTY_NEWLINE);
1040 return CMD_WARNING;
1041 }
1042
1043 req = subscr_request_conn(vsub, NULL, NULL, "manual Paging from VTY");
1044 if (req)
1045 vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE);
1046 else
1047 vty_out(vty, "%% paging subscriber failed%s", VTY_NEWLINE);
1048
1049 vlr_subscr_put(vsub);
1050 return req ? CMD_SUCCESS : CMD_WARNING;
1051}
1052
1053static int loop_by_char(uint8_t ch)
1054{
1055 switch (ch) {
1056 case 'a':
1057 return GSM414_LOOP_A;
1058 case 'b':
1059 return GSM414_LOOP_B;
1060 case 'c':
1061 return GSM414_LOOP_C;
1062 case 'd':
1063 return GSM414_LOOP_D;
1064 case 'e':
1065 return GSM414_LOOP_E;
1066 case 'f':
1067 return GSM414_LOOP_F;
1068 case 'i':
1069 return GSM414_LOOP_I;
1070 }
1071 return -1;
1072}
1073
1074DEFUN(subscriber_mstest_close,
1075 subscriber_mstest_close_cmd,
1076 "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
1077 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1078 "Close a TCH Loop inside the MS\n"
1079 "Loop Type A\n"
1080 "Loop Type B\n"
1081 "Loop Type C\n"
1082 "Loop Type D\n"
1083 "Loop Type E\n"
1084 "Loop Type F\n"
1085 "Loop Type I\n")
1086{
1087 struct gsm_subscriber_connection *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001088 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1089 const char *loop_str;
1090 int loop_mode;
1091
1092 if (!vsub) {
1093 vty_out(vty, "%% No subscriber found for %s %s%s",
1094 argv[0], argv[1], VTY_NEWLINE);
1095 return CMD_WARNING;
1096 }
1097
1098 loop_str = argv[2];
1099 loop_mode = loop_by_char(loop_str[0]);
1100
1101 conn = connection_for_subscr(vsub);
1102 if (!conn) {
1103 vty_out(vty, "%% An active connection is required for %s %s%s",
1104 argv[0], argv[1], VTY_NEWLINE);
1105 vlr_subscr_put(vsub);
1106 return CMD_WARNING;
1107 }
1108
1109 gsm0414_tx_close_tch_loop_cmd(conn, loop_mode);
1110
1111 return CMD_SUCCESS;
1112}
1113
1114DEFUN(subscriber_mstest_open,
1115 subscriber_mstest_open_cmd,
1116 "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
1117 SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
1118 "Open a TCH Loop inside the MS\n")
1119{
1120 struct gsm_subscriber_connection *conn;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001121 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
1122
1123 if (!vsub) {
1124 vty_out(vty, "%% No subscriber found for %s %s%s",
1125 argv[0], argv[1], VTY_NEWLINE);
1126 return CMD_WARNING;
1127 }
1128
1129 conn = connection_for_subscr(vsub);
1130 if (!conn) {
1131 vty_out(vty, "%% An active connection is required for %s %s%s",
1132 argv[0], argv[1], VTY_NEWLINE);
1133 vlr_subscr_put(vsub);
1134 return CMD_WARNING;
1135 }
1136
1137 gsm0414_tx_open_loop_cmd(conn);
1138
1139 return CMD_SUCCESS;
1140}
1141
1142DEFUN(ena_subscr_expire,
1143 ena_subscr_expire_cmd,
1144 "subscriber " SUBSCR_TYPES " ID expire",
1145 SUBSCR_HELP "Expire the subscriber Now\n")
1146{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001147 struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
1148 argv[1]);
1149
1150 if (!vsub) {
1151 vty_out(vty, "%% No subscriber found for %s %s%s",
1152 argv[0], argv[1], VTY_NEWLINE);
1153 return CMD_WARNING;
1154 }
1155
1156 if (vlr_subscr_expire(vsub))
1157 vty_out(vty, "%% VLR released subscriber %s%s",
1158 vlr_subscr_name(vsub), VTY_NEWLINE);
1159
1160 if (vsub->use_count > 1)
1161 vty_out(vty, "%% Subscriber %s is still in use,"
1162 " should be released soon%s",
1163 vlr_subscr_name(vsub), VTY_NEWLINE);
1164
1165 vlr_subscr_put(vsub);
1166 return CMD_SUCCESS;
1167}
1168
1169static int scall_cbfn(unsigned int subsys, unsigned int signal,
1170 void *handler_data, void *signal_data)
1171{
1172 struct scall_signal_data *sigdata = signal_data;
1173 struct vty *vty = sigdata->data;
1174
1175 switch (signal) {
1176 case S_SCALL_SUCCESS:
1177 vty_out(vty, "%% silent call success%s", VTY_NEWLINE);
1178 break;
1179 case S_SCALL_EXPIRED:
1180 vty_out(vty, "%% silent call expired paging%s", VTY_NEWLINE);
1181 break;
1182 }
1183 return 0;
1184}
1185
1186DEFUN(show_stats,
1187 show_stats_cmd,
1188 "show statistics",
1189 SHOW_STR "Display network statistics\n")
1190{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001191 vty_out(vty, "Location Update : %lu attach, %lu normal, %lu periodic%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001192 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
1193 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
1194 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001195 VTY_NEWLINE);
1196 vty_out(vty, "IMSI Detach Indications : %lu%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001197 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001198 VTY_NEWLINE);
1199 vty_out(vty, "Location Updating Results: %lu completed, %lu failed%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001200 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
1201 gsmnet->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001202 VTY_NEWLINE);
1203 vty_out(vty, "SMS MO : %lu submitted, %lu no receiver%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001204 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
1205 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001206 VTY_NEWLINE);
1207 vty_out(vty, "SMS MT : %lu delivered, %lu no memory, %lu other error%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001208 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
1209 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
1210 gsmnet->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001211 VTY_NEWLINE);
1212 vty_out(vty, "MO Calls : %lu setup, %lu connect ack%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001213 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
1214 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001215 VTY_NEWLINE);
1216 vty_out(vty, "MT Calls : %lu setup, %lu connect%s",
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001217 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
1218 gsmnet->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001219 VTY_NEWLINE);
1220 return CMD_SUCCESS;
1221}
1222
1223DEFUN(show_smsqueue,
1224 show_smsqueue_cmd,
1225 "show sms-queue",
1226 SHOW_STR "Display SMSqueue statistics\n")
1227{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001228 sms_queue_stats(gsmnet->sms_queue, vty);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001229 return CMD_SUCCESS;
1230}
1231
1232DEFUN(smsqueue_trigger,
1233 smsqueue_trigger_cmd,
1234 "sms-queue trigger",
1235 "SMS Queue\n" "Trigger sending messages\n")
1236{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001237 sms_queue_trigger(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001238 return CMD_SUCCESS;
1239}
1240
1241DEFUN(smsqueue_max,
1242 smsqueue_max_cmd,
1243 "sms-queue max-pending <1-500>",
1244 "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
1245{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001246 sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001247 return CMD_SUCCESS;
1248}
1249
1250DEFUN(smsqueue_clear,
1251 smsqueue_clear_cmd,
1252 "sms-queue clear",
1253 "SMS Queue\n" "Clear the queue of pending SMS\n")
1254{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001255 sms_queue_clear(gsmnet->sms_queue);
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001256 return CMD_SUCCESS;
1257}
1258
1259DEFUN(smsqueue_fail,
1260 smsqueue_fail_cmd,
1261 "sms-queue max-failure <1-500>",
1262 "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
1263{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001264 sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0]));
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001265 return CMD_SUCCESS;
1266}
1267
1268
1269DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
1270 "mncc-int", "Configure internal MNCC handler")
1271{
1272 vty->node = MNCC_INT_NODE;
1273
1274 return CMD_SUCCESS;
1275}
1276
1277static struct cmd_node mncc_int_node = {
1278 MNCC_INT_NODE,
1279 "%s(config-mncc-int)# ",
1280 1,
1281};
1282
1283static const struct value_string tchf_codec_names[] = {
1284 { GSM48_CMODE_SPEECH_V1, "fr" },
1285 { GSM48_CMODE_SPEECH_EFR, "efr" },
1286 { GSM48_CMODE_SPEECH_AMR, "amr" },
1287 { 0, NULL }
1288};
1289
1290static const struct value_string tchh_codec_names[] = {
1291 { GSM48_CMODE_SPEECH_V1, "hr" },
1292 { GSM48_CMODE_SPEECH_AMR, "amr" },
1293 { 0, NULL }
1294};
1295
1296static int config_write_mncc_int(struct vty *vty)
1297{
1298 vty_out(vty, "mncc-int%s", VTY_NEWLINE);
1299 vty_out(vty, " default-codec tch-f %s%s",
1300 get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
1301 VTY_NEWLINE);
1302 vty_out(vty, " default-codec tch-h %s%s",
1303 get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
1304 VTY_NEWLINE);
1305
1306 return CMD_SUCCESS;
1307}
1308
1309DEFUN(mnccint_def_codec_f,
1310 mnccint_def_codec_f_cmd,
1311 "default-codec tch-f (fr|efr|amr)",
1312 "Set default codec\n" "Codec for TCH/F\n"
1313 "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
1314{
1315 mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
1316
1317 return CMD_SUCCESS;
1318}
1319
1320DEFUN(mnccint_def_codec_h,
1321 mnccint_def_codec_h_cmd,
1322 "default-codec tch-h (hr|amr)",
1323 "Set default codec\n" "Codec for TCH/H\n"
1324 "Half-Rate\n" "Adaptive Multi-Rate\n")
1325{
1326 mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
1327
1328 return CMD_SUCCESS;
1329}
1330
1331
1332DEFUN(logging_fltr_imsi,
1333 logging_fltr_imsi_cmd,
1334 "logging filter imsi IMSI",
1335 LOGGING_STR FILTER_STR
1336 "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
1337{
1338 struct vlr_subscr *vlr_subscr;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001339 struct log_target *tgt = osmo_log_vty2tgt(vty);
1340 const char *imsi = argv[0];
1341
1342 if (!tgt)
1343 return CMD_WARNING;
1344
1345 vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi);
1346
1347 if (!vlr_subscr) {
1348 vty_out(vty, "%%no subscriber with IMSI(%s)%s",
1349 argv[0], VTY_NEWLINE);
1350 return CMD_WARNING;
1351 }
1352
1353 log_set_filter_vlr_subscr(tgt, vlr_subscr);
1354 return CMD_SUCCESS;
1355}
1356
1357static struct cmd_node hlr_node = {
1358 HLR_NODE,
1359 "%s(config-hlr)# ",
1360 1,
1361};
1362
1363DEFUN(cfg_hlr, cfg_hlr_cmd,
1364 "hlr", "Configure connection to the HLR")
1365{
1366 vty->node = HLR_NODE;
1367 return CMD_SUCCESS;
1368}
1369
1370DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
1371 "Remote GSUP address of the HLR\n"
1372 "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
1373{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001374 talloc_free((void*)gsmnet->gsup_server_addr_str);
1375 gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
1376 return CMD_SUCCESS;
1377}
1378
1379DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
1380 "Remote GSUP port of the HLR\n"
1381 "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
1382{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001383 gsmnet->gsup_server_port = atoi(argv[0]);
1384 return CMD_SUCCESS;
1385}
1386
1387static int config_write_hlr(struct vty *vty)
1388{
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001389 vty_out(vty, "hlr%s", VTY_NEWLINE);
1390 vty_out(vty, " remote-ip %s%s",
1391 gsmnet->gsup_server_addr_str, VTY_NEWLINE);
1392 vty_out(vty, " remote-port %u%s",
1393 gsmnet->gsup_server_port, VTY_NEWLINE);
1394 return CMD_SUCCESS;
1395}
1396
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001397void msc_vty_init(struct gsm_network *msc_network)
1398{
Neels Hofmeyr84a1f7a2018-03-22 15:33:12 +01001399 OSMO_ASSERT(gsmnet == NULL);
1400 gsmnet = msc_network;
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001401
1402 osmo_stats_vty_add_cmds();
1403
1404 install_element(CONFIG_NODE, &cfg_net_cmd);
1405 install_node(&net_node, config_write_net);
1406 install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
1407 install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
1408 install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
1409 install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
1410 install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
1411 install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
1412 install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
1413 install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
1414 install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
1415 install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
1416 install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
1417 install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
1418 install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001419
1420 install_element(CONFIG_NODE, &cfg_msc_cmd);
1421 install_node(&msc_node, config_write_msc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001422 install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
1423 install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
Neels Hofmeyr97ce0152017-10-29 02:10:38 +01001424 install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd);
1425 install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001426 install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
1427 install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +01001428 install_element(MSC_NODE, &cfg_msc_paging_response_timer_cmd);
Harald Welte69c54a82018-02-09 20:41:14 +01001429 install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd);
Philipp Maierfbf66102017-04-09 12:32:51 +02001430
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +02001431 mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001432#ifdef BUILD_IU
Neels Hofmeyr21adb2b2018-03-15 12:55:46 +01001433 ranap_iu_vty_init(MSC_NODE, &msc_network->iu.rab_assign_addr_enc);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001434#endif
Stefan Sperling617ac802018-02-22 17:58:20 +01001435 osmo_fsm_vty_add_cmds();
Neels Hofmeyr7c075a22018-03-22 14:50:20 +01001436
1437 osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
1438
1439 install_element_ve(&show_subscr_cmd);
1440 install_element_ve(&show_subscr_cache_cmd);
1441 install_element_ve(&show_msc_conn_cmd);
1442 install_element_ve(&show_msc_transaction_cmd);
1443
1444 install_element_ve(&sms_send_pend_cmd);
1445 install_element_ve(&sms_delete_expired_cmd);
1446
1447 install_element_ve(&subscriber_create_cmd);
1448 install_element_ve(&subscriber_send_sms_cmd);
1449 install_element_ve(&subscriber_silent_sms_cmd);
1450 install_element_ve(&subscriber_silent_call_start_cmd);
1451 install_element_ve(&subscriber_silent_call_stop_cmd);
1452 install_element_ve(&subscriber_ussd_notify_cmd);
1453 install_element_ve(&subscriber_mstest_close_cmd);
1454 install_element_ve(&subscriber_mstest_open_cmd);
1455 install_element_ve(&subscriber_paging_cmd);
1456 install_element_ve(&show_stats_cmd);
1457 install_element_ve(&show_smsqueue_cmd);
1458 install_element_ve(&logging_fltr_imsi_cmd);
1459
1460 install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
1461 install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
1462 install_element(ENABLE_NODE, &smsqueue_max_cmd);
1463 install_element(ENABLE_NODE, &smsqueue_clear_cmd);
1464 install_element(ENABLE_NODE, &smsqueue_fail_cmd);
1465 install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
1466
1467 install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
1468 install_node(&mncc_int_node, config_write_mncc_int);
1469 install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
1470 install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
1471
1472 install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
1473
1474 install_element(CONFIG_NODE, &cfg_hlr_cmd);
1475 install_node(&hlr_node, config_write_hlr);
1476 install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
1477 install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001478}