blob: 2d9b92964af7e4442c1ace6827f9c6b8b328f46e [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"
Harald Weltefa7ee332018-06-24 13:20:32 +020038#include "gsup_server.h"
Neels Hofmeyr7685a782017-01-30 23:30:26 +010039
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +020040struct cmd_node hlr_node = {
41 HLR_NODE,
42 "%s(config-hlr)# ",
43 1,
44};
45
46DEFUN(cfg_hlr,
47 cfg_hlr_cmd,
48 "hlr",
49 "Configure the HLR")
50{
51 vty->node = HLR_NODE;
52 return CMD_SUCCESS;
53}
54
55struct cmd_node gsup_node = {
56 GSUP_NODE,
57 "%s(config-hlr-gsup)# ",
58 1,
59};
60
61DEFUN(cfg_gsup,
62 cfg_gsup_cmd,
63 "gsup",
64 "Configure GSUP options")
65{
66 vty->node = GSUP_NODE;
67 return CMD_SUCCESS;
68}
69
70static int config_write_hlr(struct vty *vty)
71{
72 vty_out(vty, "hlr%s", VTY_NEWLINE);
73 return CMD_SUCCESS;
74}
75
76static int config_write_hlr_gsup(struct vty *vty)
77{
78 vty_out(vty, " gsup%s", VTY_NEWLINE);
79 if (g_hlr->gsup_bind_addr)
80 vty_out(vty, " bind ip %s%s", g_hlr->gsup_bind_addr, VTY_NEWLINE);
81 return CMD_SUCCESS;
82}
83
Harald Weltefa7ee332018-06-24 13:20:32 +020084static void show_one_conn(struct vty *vty, const struct osmo_gsup_conn *conn)
85{
86 const struct ipa_server_conn *isc = conn->conn;
87 char *name;
88 int rc;
89
90 rc = osmo_gsup_conn_ccm_get(conn, (uint8_t **) &name, IPAC_IDTAG_SERNR);
91 OSMO_ASSERT(rc);
92
93 vty_out(vty, " '%s' from %s:%5u, CS=%u, PS=%u, 3G_IND=%u%s",
94 name, isc->addr, isc->port, conn->supports_cs, conn->supports_ps, conn->auc_3g_ind,
95 VTY_NEWLINE);
96}
97
98DEFUN(show_gsup_conn, show_gsup_conn_cmd,
99 "show gsup-connections",
100 SHOW_STR "GSUP Connections from VLRs, SGSNs, EUSEs\n")
101{
102 struct osmo_gsup_server *gs = g_hlr->gs;
103 struct osmo_gsup_conn *conn;
104
105 llist_for_each_entry(conn, &gs->clients, list)
106 show_one_conn(vty, conn);
107
108 return CMD_SUCCESS;
109}
110
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200111DEFUN(cfg_hlr_gsup_bind_ip,
112 cfg_hlr_gsup_bind_ip_cmd,
113 "bind ip A.B.C.D",
114 "Listen/Bind related socket option\n"
115 IP_STR
116 "IPv4 Address to bind the GSUP interface to\n")
117{
118 if(g_hlr->gsup_bind_addr)
119 talloc_free(g_hlr->gsup_bind_addr);
120 g_hlr->gsup_bind_addr = talloc_strdup(g_hlr, argv[0]);
121
122 return CMD_SUCCESS;
123}
124
Harald Welte4956ae12018-06-15 22:04:28 +0200125/***********************************************************************
Harald Weltedab544e2018-07-29 16:14:48 +0200126 * USSD Entity
Harald Welte4956ae12018-06-15 22:04:28 +0200127 ***********************************************************************/
128
129#include "hlr_ussd.h"
130
Harald Weltedab544e2018-07-29 16:14:48 +0200131#define USSD_STR "USSD Configuration\n"
132#define UROUTE_STR "Routing Configuration\n"
133#define PREFIX_STR "Prefix-Matching Route\n" "USSD Prefix\n"
Harald Welte4956ae12018-06-15 22:04:28 +0200134
Harald Weltedab544e2018-07-29 16:14:48 +0200135#define INT_CHOICE "(own-msisdn|own-imsi)"
136#define INT_STR "Internal USSD Handler\n" \
137 "Respond with subscribers' own MSISDN\n" \
138 "Respond with subscribers' own IMSI\n"
139
140#define EXT_STR "External USSD Handler\n" \
141 "Name of External USSD Handler (IPA CCM ID)\n"
142
143DEFUN(cfg_ussd_route_pfx_int, cfg_ussd_route_pfx_int_cmd,
144 "ussd route prefix PREFIX internal " INT_CHOICE,
145 USSD_STR UROUTE_STR PREFIX_STR INT_STR)
146{
147 const struct hlr_iuse *iuse = iuse_find(argv[1]);
148 struct hlr_ussd_route *rt = ussd_route_find_prefix(g_hlr, argv[0]);
Harald Welte4956ae12018-06-15 22:04:28 +0200149 if (rt) {
150 vty_out(vty, "%% Cannot add [another?] route for prefix %s%s", argv[0], VTY_NEWLINE);
151 return CMD_WARNING;
152 }
Harald Weltedab544e2018-07-29 16:14:48 +0200153 ussd_route_prefix_alloc_int(g_hlr, argv[0], iuse);
Harald Welte4956ae12018-06-15 22:04:28 +0200154
155 return CMD_SUCCESS;
156}
157
Harald Weltedab544e2018-07-29 16:14:48 +0200158DEFUN(cfg_ussd_route_pfx_ext, cfg_ussd_route_pfx_ext_cmd,
159 "ussd route prefix PREFIX external EUSE",
160 USSD_STR UROUTE_STR PREFIX_STR EXT_STR)
Harald Welte4956ae12018-06-15 22:04:28 +0200161{
Harald Weltedab544e2018-07-29 16:14:48 +0200162 struct hlr_euse *euse = euse_find(g_hlr, argv[1]);
163 struct hlr_ussd_route *rt = ussd_route_find_prefix(g_hlr, argv[0]);
164 if (rt) {
165 vty_out(vty, "%% Cannot add [another?] route for prefix %s%s", argv[0], VTY_NEWLINE);
166 return CMD_WARNING;
167 }
168 if (!euse) {
169 vty_out(vty, "%% Cannot find euse '%s'%s", argv[1], VTY_NEWLINE);
170 return CMD_WARNING;
171 }
172 ussd_route_prefix_alloc_ext(g_hlr, argv[0], euse);
173
174 return CMD_SUCCESS;
175}
176
177DEFUN(cfg_ussd_no_route_pfx, cfg_ussd_no_route_pfx_cmd,
178 "no ussd route prefix PREFIX",
179 NO_STR USSD_STR UROUTE_STR PREFIX_STR)
180{
181 struct hlr_ussd_route *rt = ussd_route_find_prefix(g_hlr, argv[0]);
Harald Welte4956ae12018-06-15 22:04:28 +0200182 if (!rt) {
183 vty_out(vty, "%% Cannot find route for prefix %s%s", argv[0], VTY_NEWLINE);
184 return CMD_WARNING;
185 }
Harald Weltedab544e2018-07-29 16:14:48 +0200186 ussd_route_del(rt);
Harald Welte4956ae12018-06-15 22:04:28 +0200187
188 return CMD_SUCCESS;
189}
190
Harald Weltedab544e2018-07-29 16:14:48 +0200191DEFUN(cfg_ussd_defaultroute, cfg_ussd_defaultroute_cmd,
192 "ussd default-route external EUSE",
193 USSD_STR "Configure default-route for all USSD to unknown destinations\n"
194 EXT_STR)
Harald Welte4956ae12018-06-15 22:04:28 +0200195{
Vadim Yanitskiyb93c44f2018-08-02 23:37:51 +0700196 struct hlr_euse *euse;
197
198 euse = euse_find(g_hlr, argv[0]);
199 if (!euse) {
200 vty_out(vty, "%% Cannot find EUSE %s%s", argv[0], VTY_NEWLINE);
201 return CMD_WARNING;
202 }
Harald Welte4956ae12018-06-15 22:04:28 +0200203
204 if (g_hlr->euse_default != euse) {
205 vty_out(vty, "Switching default route from %s to %s%s",
Harald Welte55d32a12018-07-30 17:26:35 +0200206 g_hlr->euse_default ? g_hlr->euse_default->name : "<none>",
207 euse->name, VTY_NEWLINE);
Harald Welte4956ae12018-06-15 22:04:28 +0200208 g_hlr->euse_default = euse;
209 }
210
211 return CMD_SUCCESS;
212}
213
Harald Weltedab544e2018-07-29 16:14:48 +0200214DEFUN(cfg_ussd_no_defaultroute, cfg_ussd_no_defaultroute_cmd,
215 "no ussd default-route",
216 NO_STR USSD_STR "Remove the default-route for all USSD to unknown destinations\n")
Harald Welte4956ae12018-06-15 22:04:28 +0200217{
Harald Welte4956ae12018-06-15 22:04:28 +0200218 g_hlr->euse_default = NULL;
219
220 return CMD_SUCCESS;
221}
222
223struct cmd_node euse_node = {
224 EUSE_NODE,
225 "%s(config-hlr-euse)# ",
226 1,
227};
228
229DEFUN(cfg_euse, cfg_euse_cmd,
230 "euse NAME",
231 "Configure a particular External USSD Entity\n"
232 "Alphanumeric name of the External USSD Entity\n")
233{
234 struct hlr_euse *euse;
235 const char *id = argv[0];
236
237 euse = euse_find(g_hlr, id);
238 if (!euse) {
239 euse = euse_alloc(g_hlr, id);
240 if (!euse)
241 return CMD_WARNING;
242 }
243 vty->index = euse;
244 vty->index_sub = &euse->description;
245 vty->node = EUSE_NODE;
246
247 return CMD_SUCCESS;
248}
249
250DEFUN(cfg_no_euse, cfg_no_euse_cmd,
251 "no euse NAME",
252 NO_STR "Remove a particular External USSD Entity\n"
253 "Alphanumeric name of the External USSD Entity\n")
254{
255 struct hlr_euse *euse = euse_find(g_hlr, argv[0]);
256 if (!euse) {
257 vty_out(vty, "%% Cannot remove non-existant EUSE %s%s", argv[0], VTY_NEWLINE);
258 return CMD_WARNING;
259 }
260 if (g_hlr->euse_default == euse) {
261 vty_out(vty, "%% Cannot remove EUSE %s, it is the default route%s", argv[0], VTY_NEWLINE);
262 return CMD_WARNING;
263 }
264 euse_del(euse);
265 return CMD_SUCCESS;
266}
267
268static void dump_one_euse(struct vty *vty, struct hlr_euse *euse)
269{
Harald Welte4956ae12018-06-15 22:04:28 +0200270 vty_out(vty, " euse %s%s", euse->name, VTY_NEWLINE);
Harald Welte4956ae12018-06-15 22:04:28 +0200271}
272
273static int config_write_euse(struct vty *vty)
274{
275 struct hlr_euse *euse;
Harald Weltedab544e2018-07-29 16:14:48 +0200276 struct hlr_ussd_route *rt;
Harald Welte4956ae12018-06-15 22:04:28 +0200277
278 llist_for_each_entry(euse, &g_hlr->euse_list, list)
279 dump_one_euse(vty, euse);
280
Harald Weltedab544e2018-07-29 16:14:48 +0200281 llist_for_each_entry(rt, &g_hlr->ussd_routes, list) {
282 vty_out(vty, " ussd route prefix %s %s %s%s", rt->prefix,
283 rt->is_external ? "external" : "internal",
284 rt->is_external ? rt->u.euse->name : rt->u.iuse->name,
285 VTY_NEWLINE);
286 }
287
288 if (g_hlr->euse_default)
289 vty_out(vty, " ussd default-route external %s%s", g_hlr->euse_default->name, VTY_NEWLINE);
290
Harald Welte4956ae12018-06-15 22:04:28 +0200291 return 0;
292}
293
294/***********************************************************************
295 * Common Code
296 ***********************************************************************/
297
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200298int hlr_vty_go_parent(struct vty *vty)
299{
300 switch (vty->node) {
301 case GSUP_NODE:
Harald Welte4956ae12018-06-15 22:04:28 +0200302 case EUSE_NODE:
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200303 vty->node = HLR_NODE;
304 vty->index = NULL;
Harald Welte4956ae12018-06-15 22:04:28 +0200305 vty->index_sub = NULL;
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200306 break;
307 default:
308 case HLR_NODE:
309 vty->node = CONFIG_NODE;
310 vty->index = NULL;
311 break;
312 case CONFIG_NODE:
313 vty->node = ENABLE_NODE;
314 vty->index = NULL;
315 break;
316 }
317
318 return vty->node;
319}
320
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100321int hlr_vty_is_config_node(struct vty *vty, int node)
322{
323 switch (node) {
324 /* add items that are not config */
325 case CONFIG_NODE:
326 return 0;
327
328 default:
329 return 1;
330 }
331}
332
Harald Welted5807b82018-07-29 12:27:41 +0200333void hlr_vty_init(const struct log_info *cat)
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100334{
335 logging_vty_add_cmds(cat);
Harald Welte7ee6e552018-02-14 00:52:05 +0100336 osmo_talloc_vty_add_cmds();
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200337
Harald Weltefa7ee332018-06-24 13:20:32 +0200338 install_element_ve(&show_gsup_conn_cmd);
339
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200340 install_element(CONFIG_NODE, &cfg_hlr_cmd);
341 install_node(&hlr_node, config_write_hlr);
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200342
343 install_element(HLR_NODE, &cfg_gsup_cmd);
344 install_node(&gsup_node, config_write_hlr_gsup);
Pau Espin Pedrolce9bc402017-05-31 13:19:22 +0200345
346 install_element(GSUP_NODE, &cfg_hlr_gsup_bind_ip_cmd);
Neels Hofmeyr183e7002017-10-06 02:59:54 +0200347
Harald Welte4956ae12018-06-15 22:04:28 +0200348 install_element(HLR_NODE, &cfg_euse_cmd);
349 install_element(HLR_NODE, &cfg_no_euse_cmd);
350 install_node(&euse_node, config_write_euse);
Harald Weltedab544e2018-07-29 16:14:48 +0200351 install_element(HLR_NODE, &cfg_ussd_route_pfx_int_cmd);
352 install_element(HLR_NODE, &cfg_ussd_route_pfx_ext_cmd);
353 install_element(HLR_NODE, &cfg_ussd_no_route_pfx_cmd);
354 install_element(HLR_NODE, &cfg_ussd_defaultroute_cmd);
355 install_element(HLR_NODE, &cfg_ussd_no_defaultroute_cmd);
Harald Welte4956ae12018-06-15 22:04:28 +0200356
Harald Welted5807b82018-07-29 12:27:41 +0200357 hlr_vty_subscriber_init();
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100358}