blob: 04e01917c78458e22b8ee37abf891d1891844346 [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>
30#include <osmocom/vty/command.h>
31#include <osmocom/vty/logging.h>
Harald Welte7ee6e552018-02-14 00:52:05 +010032#include <osmocom/vty/misc.h>
Harald Weltefa7ee332018-06-24 13:20:32 +020033#include <osmocom/abis/ipa.h>
Neels Hofmeyr7685a782017-01-30 23:30:26 +010034
Harald Weltedab544e2018-07-29 16:14:48 +020035#include "hlr.h"
Neels Hofmeyr7685a782017-01-30 23:30:26 +010036#include "hlr_vty.h"
Neels Hofmeyr183e7002017-10-06 02:59:54 +020037#include "hlr_vty_subscr.h"
Vadim Yanitskiyd157a562018-12-01 00:03:39 +070038#include "hlr_ussd.h"
Harald Weltefa7ee332018-06-24 13:20:32 +020039#include "gsup_server.h"
Neels Hofmeyr7685a782017-01-30 23:30:26 +010040
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +020041struct cmd_node hlr_node = {
42 HLR_NODE,
43 "%s(config-hlr)# ",
44 1,
45};
46
47DEFUN(cfg_hlr,
48 cfg_hlr_cmd,
49 "hlr",
50 "Configure the HLR")
51{
52 vty->node = HLR_NODE;
53 return CMD_SUCCESS;
54}
55
56struct cmd_node gsup_node = {
57 GSUP_NODE,
58 "%s(config-hlr-gsup)# ",
59 1,
60};
61
62DEFUN(cfg_gsup,
63 cfg_gsup_cmd,
64 "gsup",
65 "Configure GSUP options")
66{
67 vty->node = GSUP_NODE;
68 return CMD_SUCCESS;
69}
70
71static int config_write_hlr(struct vty *vty)
72{
73 vty_out(vty, "hlr%s", VTY_NEWLINE);
Oliver Smith851814a2019-01-11 15:30:21 +010074 if (g_hlr->store_imei)
75 vty_out(vty, " store-imei%s", VTY_NEWLINE);
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +020076 return CMD_SUCCESS;
77}
78
79static int config_write_hlr_gsup(struct vty *vty)
80{
81 vty_out(vty, " gsup%s", VTY_NEWLINE);
82 if (g_hlr->gsup_bind_addr)
83 vty_out(vty, " bind ip %s%s", g_hlr->gsup_bind_addr, VTY_NEWLINE);
84 return CMD_SUCCESS;
85}
86
Harald Weltefa7ee332018-06-24 13:20:32 +020087static void show_one_conn(struct vty *vty, const struct osmo_gsup_conn *conn)
88{
89 const struct ipa_server_conn *isc = conn->conn;
90 char *name;
91 int rc;
92
93 rc = osmo_gsup_conn_ccm_get(conn, (uint8_t **) &name, IPAC_IDTAG_SERNR);
94 OSMO_ASSERT(rc);
95
96 vty_out(vty, " '%s' from %s:%5u, CS=%u, PS=%u, 3G_IND=%u%s",
97 name, isc->addr, isc->port, conn->supports_cs, conn->supports_ps, conn->auc_3g_ind,
98 VTY_NEWLINE);
99}
100
101DEFUN(show_gsup_conn, show_gsup_conn_cmd,
102 "show gsup-connections",
103 SHOW_STR "GSUP Connections from VLRs, SGSNs, EUSEs\n")
104{
105 struct osmo_gsup_server *gs = g_hlr->gs;
106 struct osmo_gsup_conn *conn;
107
108 llist_for_each_entry(conn, &gs->clients, list)
109 show_one_conn(vty, conn);
110
111 return CMD_SUCCESS;
112}
113
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200114DEFUN(cfg_hlr_gsup_bind_ip,
115 cfg_hlr_gsup_bind_ip_cmd,
116 "bind ip A.B.C.D",
117 "Listen/Bind related socket option\n"
118 IP_STR
119 "IPv4 Address to bind the GSUP interface to\n")
120{
121 if(g_hlr->gsup_bind_addr)
122 talloc_free(g_hlr->gsup_bind_addr);
123 g_hlr->gsup_bind_addr = talloc_strdup(g_hlr, argv[0]);
124
125 return CMD_SUCCESS;
126}
127
Harald Welte4956ae12018-06-15 22:04:28 +0200128/***********************************************************************
Harald Weltedab544e2018-07-29 16:14:48 +0200129 * USSD Entity
Harald Welte4956ae12018-06-15 22:04:28 +0200130 ***********************************************************************/
131
132#include "hlr_ussd.h"
133
Harald Weltedab544e2018-07-29 16:14:48 +0200134#define USSD_STR "USSD Configuration\n"
135#define UROUTE_STR "Routing Configuration\n"
136#define PREFIX_STR "Prefix-Matching Route\n" "USSD Prefix\n"
Harald Welte4956ae12018-06-15 22:04:28 +0200137
Harald Weltedab544e2018-07-29 16:14:48 +0200138#define INT_CHOICE "(own-msisdn|own-imsi)"
139#define INT_STR "Internal USSD Handler\n" \
140 "Respond with subscribers' own MSISDN\n" \
141 "Respond with subscribers' own IMSI\n"
142
143#define EXT_STR "External USSD Handler\n" \
144 "Name of External USSD Handler (IPA CCM ID)\n"
145
146DEFUN(cfg_ussd_route_pfx_int, cfg_ussd_route_pfx_int_cmd,
147 "ussd route prefix PREFIX internal " INT_CHOICE,
148 USSD_STR UROUTE_STR PREFIX_STR INT_STR)
149{
150 const struct hlr_iuse *iuse = iuse_find(argv[1]);
151 struct hlr_ussd_route *rt = ussd_route_find_prefix(g_hlr, argv[0]);
Harald Welte4956ae12018-06-15 22:04:28 +0200152 if (rt) {
153 vty_out(vty, "%% Cannot add [another?] route for prefix %s%s", argv[0], VTY_NEWLINE);
154 return CMD_WARNING;
155 }
Harald Weltedab544e2018-07-29 16:14:48 +0200156 ussd_route_prefix_alloc_int(g_hlr, argv[0], iuse);
Harald Welte4956ae12018-06-15 22:04:28 +0200157
158 return CMD_SUCCESS;
159}
160
Harald Weltedab544e2018-07-29 16:14:48 +0200161DEFUN(cfg_ussd_route_pfx_ext, cfg_ussd_route_pfx_ext_cmd,
162 "ussd route prefix PREFIX external EUSE",
163 USSD_STR UROUTE_STR PREFIX_STR EXT_STR)
Harald Welte4956ae12018-06-15 22:04:28 +0200164{
Harald Weltedab544e2018-07-29 16:14:48 +0200165 struct hlr_euse *euse = euse_find(g_hlr, argv[1]);
166 struct hlr_ussd_route *rt = ussd_route_find_prefix(g_hlr, argv[0]);
167 if (rt) {
168 vty_out(vty, "%% Cannot add [another?] route for prefix %s%s", argv[0], VTY_NEWLINE);
169 return CMD_WARNING;
170 }
171 if (!euse) {
172 vty_out(vty, "%% Cannot find euse '%s'%s", argv[1], VTY_NEWLINE);
173 return CMD_WARNING;
174 }
175 ussd_route_prefix_alloc_ext(g_hlr, argv[0], euse);
176
177 return CMD_SUCCESS;
178}
179
180DEFUN(cfg_ussd_no_route_pfx, cfg_ussd_no_route_pfx_cmd,
181 "no ussd route prefix PREFIX",
182 NO_STR USSD_STR UROUTE_STR PREFIX_STR)
183{
184 struct hlr_ussd_route *rt = ussd_route_find_prefix(g_hlr, argv[0]);
Harald Welte4956ae12018-06-15 22:04:28 +0200185 if (!rt) {
186 vty_out(vty, "%% Cannot find route for prefix %s%s", argv[0], VTY_NEWLINE);
187 return CMD_WARNING;
188 }
Harald Weltedab544e2018-07-29 16:14:48 +0200189 ussd_route_del(rt);
Harald Welte4956ae12018-06-15 22:04:28 +0200190
191 return CMD_SUCCESS;
192}
193
Harald Weltedab544e2018-07-29 16:14:48 +0200194DEFUN(cfg_ussd_defaultroute, cfg_ussd_defaultroute_cmd,
195 "ussd default-route external EUSE",
196 USSD_STR "Configure default-route for all USSD to unknown destinations\n"
197 EXT_STR)
Harald Welte4956ae12018-06-15 22:04:28 +0200198{
Vadim Yanitskiyb93c44f2018-08-02 23:37:51 +0700199 struct hlr_euse *euse;
200
201 euse = euse_find(g_hlr, argv[0]);
202 if (!euse) {
203 vty_out(vty, "%% Cannot find EUSE %s%s", argv[0], VTY_NEWLINE);
204 return CMD_WARNING;
205 }
Harald Welte4956ae12018-06-15 22:04:28 +0200206
207 if (g_hlr->euse_default != euse) {
208 vty_out(vty, "Switching default route from %s to %s%s",
Harald Welte55d32a12018-07-30 17:26:35 +0200209 g_hlr->euse_default ? g_hlr->euse_default->name : "<none>",
210 euse->name, VTY_NEWLINE);
Harald Welte4956ae12018-06-15 22:04:28 +0200211 g_hlr->euse_default = euse;
212 }
213
214 return CMD_SUCCESS;
215}
216
Harald Weltedab544e2018-07-29 16:14:48 +0200217DEFUN(cfg_ussd_no_defaultroute, cfg_ussd_no_defaultroute_cmd,
218 "no ussd default-route",
219 NO_STR USSD_STR "Remove the default-route for all USSD to unknown destinations\n")
Harald Welte4956ae12018-06-15 22:04:28 +0200220{
Harald Welte4956ae12018-06-15 22:04:28 +0200221 g_hlr->euse_default = NULL;
222
223 return CMD_SUCCESS;
224}
225
226struct cmd_node euse_node = {
227 EUSE_NODE,
228 "%s(config-hlr-euse)# ",
229 1,
230};
231
232DEFUN(cfg_euse, cfg_euse_cmd,
233 "euse NAME",
234 "Configure a particular External USSD Entity\n"
235 "Alphanumeric name of the External USSD Entity\n")
236{
237 struct hlr_euse *euse;
238 const char *id = argv[0];
239
240 euse = euse_find(g_hlr, id);
241 if (!euse) {
242 euse = euse_alloc(g_hlr, id);
243 if (!euse)
244 return CMD_WARNING;
245 }
246 vty->index = euse;
247 vty->index_sub = &euse->description;
248 vty->node = EUSE_NODE;
249
250 return CMD_SUCCESS;
251}
252
253DEFUN(cfg_no_euse, cfg_no_euse_cmd,
254 "no euse NAME",
255 NO_STR "Remove a particular External USSD Entity\n"
256 "Alphanumeric name of the External USSD Entity\n")
257{
258 struct hlr_euse *euse = euse_find(g_hlr, argv[0]);
259 if (!euse) {
260 vty_out(vty, "%% Cannot remove non-existant EUSE %s%s", argv[0], VTY_NEWLINE);
261 return CMD_WARNING;
262 }
263 if (g_hlr->euse_default == euse) {
264 vty_out(vty, "%% Cannot remove EUSE %s, it is the default route%s", argv[0], VTY_NEWLINE);
265 return CMD_WARNING;
266 }
267 euse_del(euse);
268 return CMD_SUCCESS;
269}
270
271static void dump_one_euse(struct vty *vty, struct hlr_euse *euse)
272{
Harald Welte4956ae12018-06-15 22:04:28 +0200273 vty_out(vty, " euse %s%s", euse->name, VTY_NEWLINE);
Harald Welte4956ae12018-06-15 22:04:28 +0200274}
275
276static int config_write_euse(struct vty *vty)
277{
278 struct hlr_euse *euse;
Harald Weltedab544e2018-07-29 16:14:48 +0200279 struct hlr_ussd_route *rt;
Harald Welte4956ae12018-06-15 22:04:28 +0200280
281 llist_for_each_entry(euse, &g_hlr->euse_list, list)
282 dump_one_euse(vty, euse);
283
Harald Weltedab544e2018-07-29 16:14:48 +0200284 llist_for_each_entry(rt, &g_hlr->ussd_routes, list) {
285 vty_out(vty, " ussd route prefix %s %s %s%s", rt->prefix,
286 rt->is_external ? "external" : "internal",
287 rt->is_external ? rt->u.euse->name : rt->u.iuse->name,
288 VTY_NEWLINE);
289 }
290
291 if (g_hlr->euse_default)
292 vty_out(vty, " ussd default-route external %s%s", g_hlr->euse_default->name, VTY_NEWLINE);
293
Vadim Yanitskiyd157a562018-12-01 00:03:39 +0700294 if (g_hlr->ncss_guard_timeout != NCSS_GUARD_TIMEOUT_DEFAULT)
295 vty_out(vty, " ncss-guard-timeout %i%s",
296 g_hlr->ncss_guard_timeout, VTY_NEWLINE);
297
Harald Welte4956ae12018-06-15 22:04:28 +0200298 return 0;
299}
300
Vadim Yanitskiyd157a562018-12-01 00:03:39 +0700301DEFUN(cfg_ncss_guard_timeout, cfg_ncss_guard_timeout_cmd,
302 "ncss-guard-timeout <0-255>",
303 "Set guard timer for NCSS (call independent SS) session activity\n"
304 "Guard timer value (sec.), or 0 to disable")
305{
306 g_hlr->ncss_guard_timeout = atoi(argv[0]);
307 return CMD_SUCCESS;
308}
309
Oliver Smith851814a2019-01-11 15:30:21 +0100310DEFUN(cfg_store_imei, cfg_store_imei_cmd,
311 "store-imei",
312 "Save the IMEI in the database when receiving Check IMEI requests. Note that an MSC does not necessarily send"
313 " Check IMEI requests (for OsmoMSC, you may want to set 'check-imei-rqd 1').")
314{
315 g_hlr->store_imei = true;
316 return CMD_SUCCESS;
317}
318
319DEFUN(cfg_no_store_imei, cfg_no_store_imei_cmd,
320 "no store-imei",
321 "Do not save the IMEI in the database, when receiving Check IMEI requests.")
322{
323 g_hlr->store_imei = false;
324 return CMD_SUCCESS;
325}
326
Harald Welte4956ae12018-06-15 22:04:28 +0200327/***********************************************************************
328 * Common Code
329 ***********************************************************************/
330
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200331int hlr_vty_go_parent(struct vty *vty)
332{
333 switch (vty->node) {
334 case GSUP_NODE:
Harald Welte4956ae12018-06-15 22:04:28 +0200335 case EUSE_NODE:
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200336 vty->node = HLR_NODE;
337 vty->index = NULL;
Harald Welte4956ae12018-06-15 22:04:28 +0200338 vty->index_sub = NULL;
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200339 break;
340 default:
341 case HLR_NODE:
342 vty->node = CONFIG_NODE;
343 vty->index = NULL;
344 break;
345 case CONFIG_NODE:
346 vty->node = ENABLE_NODE;
347 vty->index = NULL;
348 break;
349 }
350
351 return vty->node;
352}
353
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100354int hlr_vty_is_config_node(struct vty *vty, int node)
355{
356 switch (node) {
357 /* add items that are not config */
358 case CONFIG_NODE:
359 return 0;
360
361 default:
362 return 1;
363 }
364}
365
Harald Welted5807b82018-07-29 12:27:41 +0200366void hlr_vty_init(const struct log_info *cat)
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100367{
368 logging_vty_add_cmds(cat);
Harald Welte7ee6e552018-02-14 00:52:05 +0100369 osmo_talloc_vty_add_cmds();
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200370
Harald Weltefa7ee332018-06-24 13:20:32 +0200371 install_element_ve(&show_gsup_conn_cmd);
372
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200373 install_element(CONFIG_NODE, &cfg_hlr_cmd);
374 install_node(&hlr_node, config_write_hlr);
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200375
376 install_element(HLR_NODE, &cfg_gsup_cmd);
377 install_node(&gsup_node, config_write_hlr_gsup);
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200378
379 install_element(GSUP_NODE, &cfg_hlr_gsup_bind_ip_cmd);
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200380
Harald Welte4956ae12018-06-15 22:04:28 +0200381 install_element(HLR_NODE, &cfg_euse_cmd);
382 install_element(HLR_NODE, &cfg_no_euse_cmd);
383 install_node(&euse_node, config_write_euse);
Harald Weltedab544e2018-07-29 16:14:48 +0200384 install_element(HLR_NODE, &cfg_ussd_route_pfx_int_cmd);
385 install_element(HLR_NODE, &cfg_ussd_route_pfx_ext_cmd);
386 install_element(HLR_NODE, &cfg_ussd_no_route_pfx_cmd);
387 install_element(HLR_NODE, &cfg_ussd_defaultroute_cmd);
388 install_element(HLR_NODE, &cfg_ussd_no_defaultroute_cmd);
Vadim Yanitskiyd157a562018-12-01 00:03:39 +0700389 install_element(HLR_NODE, &cfg_ncss_guard_timeout_cmd);
Oliver Smith851814a2019-01-11 15:30:21 +0100390 install_element(HLR_NODE, &cfg_store_imei_cmd);
391 install_element(HLR_NODE, &cfg_no_store_imei_cmd);
Harald Welte4956ae12018-06-15 22:04:28 +0200392
Harald Welted5807b82018-07-29 12:27:41 +0200393 hlr_vty_subscriber_init();
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100394}