blob: e4cc4be7d1edc760a839b05b10fcc008843f0cb5 [file] [log] [blame]
Neels Hofmeyr7685a782017-01-30 23:30:26 +01001/* OsmoHLR VTY implementation */
2
3/* (C) 2016 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
Neels Hofmeyr7685a782017-01-30 23:30:26 +01004 * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
Harald Weltefa7ee332018-06-24 13:20:32 +02005 * (C) 2018 Harald Welte <laforge@gnumonks.org>
6 *
7 * All Rights Reserved
Neels Hofmeyr7685a782017-01-30 23:30:26 +01008 *
Harald Welte4956ae12018-06-15 22:04:28 +02009 * (C) 2018 Harald Welte <laforge@gnumonks.org>
10 *
11 * All Rights Reserved
12 *
Neels Hofmeyr7685a782017-01-30 23:30:26 +010013 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU Affero General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Affero General Public License for more details.
22 *
23 * You should have received a copy of the GNU Affero General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 *
26 */
27
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +020028#include <osmocom/core/talloc.h>
Neels Hofmeyr7685a782017-01-30 23:30:26 +010029#include <osmocom/vty/vty.h>
Max20ddfdb2019-02-18 13:12:27 +010030#include <osmocom/vty/stats.h>
Neels Hofmeyr7685a782017-01-30 23:30:26 +010031#include <osmocom/vty/command.h>
32#include <osmocom/vty/logging.h>
Harald Welte7ee6e552018-02-14 00:52:05 +010033#include <osmocom/vty/misc.h>
Harald Weltefa7ee332018-06-24 13:20:32 +020034#include <osmocom/abis/ipa.h>
Neels Hofmeyr7685a782017-01-30 23:30:26 +010035
Harald Weltedab544e2018-07-29 16:14:48 +020036#include "hlr.h"
Neels Hofmeyr7685a782017-01-30 23:30:26 +010037#include "hlr_vty.h"
Neels Hofmeyr183e7002017-10-06 02:59:54 +020038#include "hlr_vty_subscr.h"
Vadim Yanitskiyd157a562018-12-01 00:03:39 +070039#include "hlr_ussd.h"
Harald Weltefa7ee332018-06-24 13:20:32 +020040#include "gsup_server.h"
Neels Hofmeyr7685a782017-01-30 23:30:26 +010041
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +020042struct cmd_node hlr_node = {
43 HLR_NODE,
44 "%s(config-hlr)# ",
45 1,
46};
47
48DEFUN(cfg_hlr,
49 cfg_hlr_cmd,
50 "hlr",
51 "Configure the HLR")
52{
53 vty->node = HLR_NODE;
54 return CMD_SUCCESS;
55}
56
57struct cmd_node gsup_node = {
58 GSUP_NODE,
59 "%s(config-hlr-gsup)# ",
60 1,
61};
62
63DEFUN(cfg_gsup,
64 cfg_gsup_cmd,
65 "gsup",
66 "Configure GSUP options")
67{
68 vty->node = GSUP_NODE;
69 return CMD_SUCCESS;
70}
71
72static int config_write_hlr(struct vty *vty)
73{
74 vty_out(vty, "hlr%s", VTY_NEWLINE);
Oliver Smith851814a2019-01-11 15:30:21 +010075 if (g_hlr->store_imei)
76 vty_out(vty, " store-imei%s", VTY_NEWLINE);
Neels Hofmeyr5857c592019-04-02 04:24:49 +020077 if (g_hlr->db_file_path && strcmp(g_hlr->db_file_path, HLR_DEFAULT_DB_FILE_PATH))
78 vty_out(vty, " database %s%s", g_hlr->db_file_path, VTY_NEWLINE);
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +020079 return CMD_SUCCESS;
80}
81
82static int config_write_hlr_gsup(struct vty *vty)
83{
84 vty_out(vty, " gsup%s", VTY_NEWLINE);
85 if (g_hlr->gsup_bind_addr)
86 vty_out(vty, " bind ip %s%s", g_hlr->gsup_bind_addr, VTY_NEWLINE);
87 return CMD_SUCCESS;
88}
89
Harald Weltefa7ee332018-06-24 13:20:32 +020090static void show_one_conn(struct vty *vty, const struct osmo_gsup_conn *conn)
91{
92 const struct ipa_server_conn *isc = conn->conn;
93 char *name;
94 int rc;
95
96 rc = osmo_gsup_conn_ccm_get(conn, (uint8_t **) &name, IPAC_IDTAG_SERNR);
97 OSMO_ASSERT(rc);
98
99 vty_out(vty, " '%s' from %s:%5u, CS=%u, PS=%u, 3G_IND=%u%s",
100 name, isc->addr, isc->port, conn->supports_cs, conn->supports_ps, conn->auc_3g_ind,
101 VTY_NEWLINE);
102}
103
104DEFUN(show_gsup_conn, show_gsup_conn_cmd,
105 "show gsup-connections",
106 SHOW_STR "GSUP Connections from VLRs, SGSNs, EUSEs\n")
107{
108 struct osmo_gsup_server *gs = g_hlr->gs;
109 struct osmo_gsup_conn *conn;
110
111 llist_for_each_entry(conn, &gs->clients, list)
112 show_one_conn(vty, conn);
113
114 return CMD_SUCCESS;
115}
116
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200117DEFUN(cfg_hlr_gsup_bind_ip,
118 cfg_hlr_gsup_bind_ip_cmd,
119 "bind ip A.B.C.D",
120 "Listen/Bind related socket option\n"
121 IP_STR
122 "IPv4 Address to bind the GSUP interface to\n")
123{
124 if(g_hlr->gsup_bind_addr)
125 talloc_free(g_hlr->gsup_bind_addr);
126 g_hlr->gsup_bind_addr = talloc_strdup(g_hlr, argv[0]);
127
128 return CMD_SUCCESS;
129}
130
Harald Welte4956ae12018-06-15 22:04:28 +0200131/***********************************************************************
Harald Weltedab544e2018-07-29 16:14:48 +0200132 * USSD Entity
Harald Welte4956ae12018-06-15 22:04:28 +0200133 ***********************************************************************/
134
135#include "hlr_ussd.h"
136
Harald Weltedab544e2018-07-29 16:14:48 +0200137#define USSD_STR "USSD Configuration\n"
138#define UROUTE_STR "Routing Configuration\n"
139#define PREFIX_STR "Prefix-Matching Route\n" "USSD Prefix\n"
Harald Welte4956ae12018-06-15 22:04:28 +0200140
Harald Weltedab544e2018-07-29 16:14:48 +0200141#define INT_CHOICE "(own-msisdn|own-imsi)"
142#define INT_STR "Internal USSD Handler\n" \
143 "Respond with subscribers' own MSISDN\n" \
144 "Respond with subscribers' own IMSI\n"
145
146#define EXT_STR "External USSD Handler\n" \
147 "Name of External USSD Handler (IPA CCM ID)\n"
148
149DEFUN(cfg_ussd_route_pfx_int, cfg_ussd_route_pfx_int_cmd,
150 "ussd route prefix PREFIX internal " INT_CHOICE,
151 USSD_STR UROUTE_STR PREFIX_STR INT_STR)
152{
153 const struct hlr_iuse *iuse = iuse_find(argv[1]);
154 struct hlr_ussd_route *rt = ussd_route_find_prefix(g_hlr, argv[0]);
Harald Welte4956ae12018-06-15 22:04:28 +0200155 if (rt) {
156 vty_out(vty, "%% Cannot add [another?] route for prefix %s%s", argv[0], VTY_NEWLINE);
157 return CMD_WARNING;
158 }
Harald Weltedab544e2018-07-29 16:14:48 +0200159 ussd_route_prefix_alloc_int(g_hlr, argv[0], iuse);
Harald Welte4956ae12018-06-15 22:04:28 +0200160
161 return CMD_SUCCESS;
162}
163
Harald Weltedab544e2018-07-29 16:14:48 +0200164DEFUN(cfg_ussd_route_pfx_ext, cfg_ussd_route_pfx_ext_cmd,
165 "ussd route prefix PREFIX external EUSE",
166 USSD_STR UROUTE_STR PREFIX_STR EXT_STR)
Harald Welte4956ae12018-06-15 22:04:28 +0200167{
Harald Weltedab544e2018-07-29 16:14:48 +0200168 struct hlr_euse *euse = euse_find(g_hlr, argv[1]);
169 struct hlr_ussd_route *rt = ussd_route_find_prefix(g_hlr, argv[0]);
170 if (rt) {
171 vty_out(vty, "%% Cannot add [another?] route for prefix %s%s", argv[0], VTY_NEWLINE);
172 return CMD_WARNING;
173 }
174 if (!euse) {
175 vty_out(vty, "%% Cannot find euse '%s'%s", argv[1], VTY_NEWLINE);
176 return CMD_WARNING;
177 }
178 ussd_route_prefix_alloc_ext(g_hlr, argv[0], euse);
179
180 return CMD_SUCCESS;
181}
182
183DEFUN(cfg_ussd_no_route_pfx, cfg_ussd_no_route_pfx_cmd,
184 "no ussd route prefix PREFIX",
185 NO_STR USSD_STR UROUTE_STR PREFIX_STR)
186{
187 struct hlr_ussd_route *rt = ussd_route_find_prefix(g_hlr, argv[0]);
Harald Welte4956ae12018-06-15 22:04:28 +0200188 if (!rt) {
189 vty_out(vty, "%% Cannot find route for prefix %s%s", argv[0], VTY_NEWLINE);
190 return CMD_WARNING;
191 }
Harald Weltedab544e2018-07-29 16:14:48 +0200192 ussd_route_del(rt);
Harald Welte4956ae12018-06-15 22:04:28 +0200193
194 return CMD_SUCCESS;
195}
196
Harald Weltedab544e2018-07-29 16:14:48 +0200197DEFUN(cfg_ussd_defaultroute, cfg_ussd_defaultroute_cmd,
198 "ussd default-route external EUSE",
199 USSD_STR "Configure default-route for all USSD to unknown destinations\n"
200 EXT_STR)
Harald Welte4956ae12018-06-15 22:04:28 +0200201{
Vadim Yanitskiyb93c44f2018-08-02 23:37:51 +0700202 struct hlr_euse *euse;
203
204 euse = euse_find(g_hlr, argv[0]);
205 if (!euse) {
206 vty_out(vty, "%% Cannot find EUSE %s%s", argv[0], VTY_NEWLINE);
207 return CMD_WARNING;
208 }
Harald Welte4956ae12018-06-15 22:04:28 +0200209
210 if (g_hlr->euse_default != euse) {
211 vty_out(vty, "Switching default route from %s to %s%s",
Harald Welte55d32a12018-07-30 17:26:35 +0200212 g_hlr->euse_default ? g_hlr->euse_default->name : "<none>",
213 euse->name, VTY_NEWLINE);
Harald Welte4956ae12018-06-15 22:04:28 +0200214 g_hlr->euse_default = euse;
215 }
216
217 return CMD_SUCCESS;
218}
219
Harald Weltedab544e2018-07-29 16:14:48 +0200220DEFUN(cfg_ussd_no_defaultroute, cfg_ussd_no_defaultroute_cmd,
221 "no ussd default-route",
222 NO_STR USSD_STR "Remove the default-route for all USSD to unknown destinations\n")
Harald Welte4956ae12018-06-15 22:04:28 +0200223{
Harald Welte4956ae12018-06-15 22:04:28 +0200224 g_hlr->euse_default = NULL;
225
226 return CMD_SUCCESS;
227}
228
Neels Hofmeyr5857c592019-04-02 04:24:49 +0200229DEFUN(cfg_database, cfg_database_cmd,
230 "database PATH",
231 "Set the path to the HLR database file\n"
232 "Relative or absolute file system path to the database file (default is '" HLR_DEFAULT_DB_FILE_PATH "')\n")
233{
234 osmo_talloc_replace_string(g_hlr, &g_hlr->db_file_path, argv[0]);
235 return CMD_SUCCESS;
236}
237
Harald Welte4956ae12018-06-15 22:04:28 +0200238struct cmd_node euse_node = {
239 EUSE_NODE,
240 "%s(config-hlr-euse)# ",
241 1,
242};
243
244DEFUN(cfg_euse, cfg_euse_cmd,
245 "euse NAME",
246 "Configure a particular External USSD Entity\n"
247 "Alphanumeric name of the External USSD Entity\n")
248{
249 struct hlr_euse *euse;
250 const char *id = argv[0];
251
252 euse = euse_find(g_hlr, id);
253 if (!euse) {
254 euse = euse_alloc(g_hlr, id);
255 if (!euse)
256 return CMD_WARNING;
257 }
258 vty->index = euse;
259 vty->index_sub = &euse->description;
260 vty->node = EUSE_NODE;
261
262 return CMD_SUCCESS;
263}
264
265DEFUN(cfg_no_euse, cfg_no_euse_cmd,
266 "no euse NAME",
267 NO_STR "Remove a particular External USSD Entity\n"
268 "Alphanumeric name of the External USSD Entity\n")
269{
270 struct hlr_euse *euse = euse_find(g_hlr, argv[0]);
271 if (!euse) {
272 vty_out(vty, "%% Cannot remove non-existant EUSE %s%s", argv[0], VTY_NEWLINE);
273 return CMD_WARNING;
274 }
275 if (g_hlr->euse_default == euse) {
276 vty_out(vty, "%% Cannot remove EUSE %s, it is the default route%s", argv[0], VTY_NEWLINE);
277 return CMD_WARNING;
278 }
279 euse_del(euse);
280 return CMD_SUCCESS;
281}
282
283static void dump_one_euse(struct vty *vty, struct hlr_euse *euse)
284{
Harald Welte4956ae12018-06-15 22:04:28 +0200285 vty_out(vty, " euse %s%s", euse->name, VTY_NEWLINE);
Harald Welte4956ae12018-06-15 22:04:28 +0200286}
287
288static int config_write_euse(struct vty *vty)
289{
290 struct hlr_euse *euse;
Harald Weltedab544e2018-07-29 16:14:48 +0200291 struct hlr_ussd_route *rt;
Harald Welte4956ae12018-06-15 22:04:28 +0200292
293 llist_for_each_entry(euse, &g_hlr->euse_list, list)
294 dump_one_euse(vty, euse);
295
Harald Weltedab544e2018-07-29 16:14:48 +0200296 llist_for_each_entry(rt, &g_hlr->ussd_routes, list) {
297 vty_out(vty, " ussd route prefix %s %s %s%s", rt->prefix,
298 rt->is_external ? "external" : "internal",
299 rt->is_external ? rt->u.euse->name : rt->u.iuse->name,
300 VTY_NEWLINE);
301 }
302
303 if (g_hlr->euse_default)
304 vty_out(vty, " ussd default-route external %s%s", g_hlr->euse_default->name, VTY_NEWLINE);
305
Vadim Yanitskiyd157a562018-12-01 00:03:39 +0700306 if (g_hlr->ncss_guard_timeout != NCSS_GUARD_TIMEOUT_DEFAULT)
307 vty_out(vty, " ncss-guard-timeout %i%s",
308 g_hlr->ncss_guard_timeout, VTY_NEWLINE);
309
Harald Welte4956ae12018-06-15 22:04:28 +0200310 return 0;
311}
312
Vadim Yanitskiyd157a562018-12-01 00:03:39 +0700313DEFUN(cfg_ncss_guard_timeout, cfg_ncss_guard_timeout_cmd,
314 "ncss-guard-timeout <0-255>",
315 "Set guard timer for NCSS (call independent SS) session activity\n"
316 "Guard timer value (sec.), or 0 to disable")
317{
318 g_hlr->ncss_guard_timeout = atoi(argv[0]);
319 return CMD_SUCCESS;
320}
321
Oliver Smith851814a2019-01-11 15:30:21 +0100322DEFUN(cfg_store_imei, cfg_store_imei_cmd,
323 "store-imei",
324 "Save the IMEI in the database when receiving Check IMEI requests. Note that an MSC does not necessarily send"
325 " Check IMEI requests (for OsmoMSC, you may want to set 'check-imei-rqd 1').")
326{
327 g_hlr->store_imei = true;
328 return CMD_SUCCESS;
329}
330
331DEFUN(cfg_no_store_imei, cfg_no_store_imei_cmd,
332 "no store-imei",
333 "Do not save the IMEI in the database, when receiving Check IMEI requests.")
334{
335 g_hlr->store_imei = false;
336 return CMD_SUCCESS;
337}
338
Harald Welte4956ae12018-06-15 22:04:28 +0200339/***********************************************************************
340 * Common Code
341 ***********************************************************************/
342
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200343int hlr_vty_go_parent(struct vty *vty)
344{
345 switch (vty->node) {
346 case GSUP_NODE:
Harald Welte4956ae12018-06-15 22:04:28 +0200347 case EUSE_NODE:
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200348 vty->node = HLR_NODE;
349 vty->index = NULL;
Harald Welte4956ae12018-06-15 22:04:28 +0200350 vty->index_sub = NULL;
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200351 break;
352 default:
353 case HLR_NODE:
354 vty->node = CONFIG_NODE;
355 vty->index = NULL;
356 break;
357 case CONFIG_NODE:
358 vty->node = ENABLE_NODE;
359 vty->index = NULL;
360 break;
361 }
362
363 return vty->node;
364}
365
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100366int hlr_vty_is_config_node(struct vty *vty, int node)
367{
368 switch (node) {
369 /* add items that are not config */
370 case CONFIG_NODE:
371 return 0;
372
373 default:
374 return 1;
375 }
376}
377
Harald Welted5807b82018-07-29 12:27:41 +0200378void hlr_vty_init(const struct log_info *cat)
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100379{
380 logging_vty_add_cmds(cat);
Harald Welte7ee6e552018-02-14 00:52:05 +0100381 osmo_talloc_vty_add_cmds();
Max20ddfdb2019-02-18 13:12:27 +0100382 osmo_stats_vty_add_cmds();
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200383
Harald Weltefa7ee332018-06-24 13:20:32 +0200384 install_element_ve(&show_gsup_conn_cmd);
385
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200386 install_element(CONFIG_NODE, &cfg_hlr_cmd);
387 install_node(&hlr_node, config_write_hlr);
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200388
389 install_element(HLR_NODE, &cfg_gsup_cmd);
390 install_node(&gsup_node, config_write_hlr_gsup);
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200391
392 install_element(GSUP_NODE, &cfg_hlr_gsup_bind_ip_cmd);
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200393
Neels Hofmeyr5857c592019-04-02 04:24:49 +0200394 install_element(HLR_NODE, &cfg_database_cmd);
395
Harald Welte4956ae12018-06-15 22:04:28 +0200396 install_element(HLR_NODE, &cfg_euse_cmd);
397 install_element(HLR_NODE, &cfg_no_euse_cmd);
398 install_node(&euse_node, config_write_euse);
Harald Weltedab544e2018-07-29 16:14:48 +0200399 install_element(HLR_NODE, &cfg_ussd_route_pfx_int_cmd);
400 install_element(HLR_NODE, &cfg_ussd_route_pfx_ext_cmd);
401 install_element(HLR_NODE, &cfg_ussd_no_route_pfx_cmd);
402 install_element(HLR_NODE, &cfg_ussd_defaultroute_cmd);
403 install_element(HLR_NODE, &cfg_ussd_no_defaultroute_cmd);
Vadim Yanitskiyd157a562018-12-01 00:03:39 +0700404 install_element(HLR_NODE, &cfg_ncss_guard_timeout_cmd);
Oliver Smith851814a2019-01-11 15:30:21 +0100405 install_element(HLR_NODE, &cfg_store_imei_cmd);
406 install_element(HLR_NODE, &cfg_no_store_imei_cmd);
Harald Welte4956ae12018-06-15 22:04:28 +0200407
Harald Welted5807b82018-07-29 12:27:41 +0200408 hlr_vty_subscriber_init();
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100409}