aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2018-07-29 16:14:48 +0200
committerHarald Welte <laforge@gnumonks.org>2018-07-30 17:43:10 +0200
commitdab544e14bedb990a3cbcc0df53a97d1bb24e973 (patch)
tree5a892918ab5c4e1c001c2361f8957b63ac615082
parent7d29d59292c5357537665fdf3a1f2022c79ae604 (diff)
USSD: Add support for internal USSD handlers
There are some requests that are best served inside the HLR, as it has access to subscriber information such as MSISDN and IMSI. This unfortunately required quite some restructuring of the USSD related structures including the VTY syntax for adding routes. The default config file has been updated to replicate the *#100# built-in behavior of old OsmoNITB. Closes: OS#2566 Change-Id: I1d09fab810a6bb9ab02904de72dbc9e8a414f9f9
-rw-r--r--doc/examples/osmo-hlr.cfg1
-rw-r--r--src/hlr.c2
-rw-r--r--src/hlr.h3
-rw-r--r--src/hlr_ussd.c192
-rw-r--r--src/hlr_ussd.h35
-rw-r--r--src/hlr_vty.c105
-rw-r--r--tests/test_nodes.vty6
7 files changed, 256 insertions, 88 deletions
diff --git a/doc/examples/osmo-hlr.cfg b/doc/examples/osmo-hlr.cfg
index ebc22ec..35d942d 100644
--- a/doc/examples/osmo-hlr.cfg
+++ b/doc/examples/osmo-hlr.cfg
@@ -21,3 +21,4 @@ ctrl
hlr
gsup
bind ip 127.0.0.1
+ ussd route prefix *#100# internal own-msisdn
diff --git a/src/hlr.c b/src/hlr.c
index bcf620d..df48a99 100644
--- a/src/hlr.c
+++ b/src/hlr.c
@@ -568,7 +568,9 @@ int main(int argc, char **argv)
g_hlr = talloc_zero(hlr_ctx, struct hlr);
INIT_LLIST_HEAD(&g_hlr->euse_list);
+ INIT_LLIST_HEAD(&g_hlr->iuse_list);
INIT_LLIST_HEAD(&g_hlr->ss_sessions);
+ INIT_LLIST_HEAD(&g_hlr->ussd_routes);
rc = osmo_init_logging2(hlr_ctx, &hlr_log_info);
if (rc < 0) {
diff --git a/src/hlr.h b/src/hlr.h
index 7112352..315c3dd 100644
--- a/src/hlr.h
+++ b/src/hlr.h
@@ -43,6 +43,9 @@ struct hlr {
struct llist_head euse_list;
struct hlr_euse *euse_default;
+ struct llist_head iuse_list;
+
+ struct llist_head ussd_routes;
struct llist_head ss_sessions;
};
diff --git a/src/hlr_ussd.c b/src/hlr_ussd.c
index d23debf..f9399d2 100644
--- a/src/hlr_ussd.c
+++ b/src/hlr_ussd.c
@@ -27,6 +27,7 @@
#include <osmocom/gsm/protocol/gsm_04_80.h>
#include <stdint.h>
#include <string.h>
+#include <errno.h>
#include "hlr.h"
#include "hlr_ussd.h"
@@ -58,7 +59,6 @@ struct hlr_euse *euse_alloc(struct hlr *hlr, const char *name)
euse = talloc_zero(hlr, struct hlr_euse);
euse->name = talloc_strdup(euse, name);
euse->hlr = hlr;
- INIT_LLIST_HEAD(&euse->routes);
llist_add_tail(&euse->list, &hlr->euse_list);
return euse;
@@ -71,54 +71,68 @@ void euse_del(struct hlr_euse *euse)
}
-struct hlr_euse_route *euse_route_find(struct hlr_euse *euse, const char *prefix)
+struct hlr_ussd_route *ussd_route_find_prefix(struct hlr *hlr, const char *prefix)
{
- struct hlr_euse_route *rt;
+ struct hlr_ussd_route *rt;
- llist_for_each_entry(rt, &euse->routes, list) {
+ llist_for_each_entry(rt, &hlr->ussd_routes, list) {
if (!strcmp(rt->prefix, prefix))
return rt;
}
return NULL;
}
-struct hlr_euse_route *euse_route_prefix_alloc(struct hlr_euse *euse, const char *prefix)
+struct hlr_ussd_route *ussd_route_prefix_alloc_int(struct hlr *hlr, const char *prefix,
+ const struct hlr_iuse *iuse)
{
- struct hlr_euse_route *rt;
+ struct hlr_ussd_route *rt;
- if (euse_route_find(euse, prefix))
+ if (ussd_route_find_prefix(hlr, prefix))
return NULL;
- rt = talloc_zero(euse, struct hlr_euse_route);
+ rt = talloc_zero(hlr, struct hlr_ussd_route);
rt->prefix = talloc_strdup(rt, prefix);
- rt->euse = euse;
- llist_add_tail(&rt->list, &euse->routes);
+ rt->u.iuse = iuse;
+ llist_add_tail(&rt->list, &hlr->ussd_routes);
return rt;
}
-void euse_route_del(struct hlr_euse_route *rt)
+struct hlr_ussd_route *ussd_route_prefix_alloc_ext(struct hlr *hlr, const char *prefix,
+ struct hlr_euse *euse)
+{
+ struct hlr_ussd_route *rt;
+
+ if (ussd_route_find_prefix(hlr, prefix))
+ return NULL;
+
+ rt = talloc_zero(hlr, struct hlr_ussd_route);
+ rt->prefix = talloc_strdup(rt, prefix);
+ rt->is_external = true;
+ rt->u.euse = euse;
+ llist_add_tail(&rt->list, &hlr->ussd_routes);
+
+ return rt;
+}
+
+void ussd_route_del(struct hlr_ussd_route *rt)
{
llist_del(&rt->list);
talloc_free(rt);
}
-struct hlr_euse *ussd_euse_find_7bit_gsm(struct hlr *hlr, const char *ussd_code)
+static struct hlr_ussd_route *ussd_route_lookup_7bit(struct hlr *hlr, const char *ussd_code)
{
- struct hlr_euse *euse;
-
- llist_for_each_entry(euse, &hlr->euse_list, list) {
- struct hlr_euse_route *rt;
- llist_for_each_entry(rt, &euse->routes, list) {
- if (!strncmp(ussd_code, rt->prefix, strlen(rt->prefix))) {
- LOGP(DSS, LOGL_DEBUG, "Found EUSE %s (prefix %s) for USSD Code '%s'\n",
- rt->euse->name, rt->prefix, ussd_code);
- return rt->euse;
- }
+ struct hlr_ussd_route *rt;
+ llist_for_each_entry(rt, &hlr->ussd_routes, list) {
+ if (!strncmp(ussd_code, rt->prefix, strlen(rt->prefix))) {
+ LOGP(DSS, LOGL_DEBUG, "Found EUSE %s (prefix %s) for USSD Code '%s'\n",
+ rt->u.euse->name, rt->prefix, ussd_code);
+ return rt;
}
}
- LOGP(DSS, LOGL_DEBUG, "Could not find Route/EUSE for USSD Code '%s'\n", ussd_code);
+ LOGP(DSS, LOGL_DEBUG, "Could not find Route for USSD Code '%s'\n", ussd_code);
return NULL;
}
@@ -141,8 +155,15 @@ struct ss_session {
/* time-out when we will delete the session */
struct osmo_timer_list timeout;
- /* external USSD Entity responsible for this session */
- struct hlr_euse *euse;
+ /* is this USSD for an external handler (EUSE): true */
+ bool is_external;
+ union {
+ /* external USSD Entity responsible for this session */
+ struct hlr_euse *euse;
+ /* internal USSD Entity responsible for this session */
+ const struct hlr_iuse *iuse;
+ } u;
+
/* we don't keep a pointer to the osmo_gsup_{route,conn} towards the MSC/VLR here,
* as this might change during inter-VLR hand-over, and we simply look-up the serving MSC/VLR
* every time we receive an USSD component from the EUSE */
@@ -247,6 +268,79 @@ static int ss_tx_error(struct ss_session *ss, uint8_t invoke_id, uint8_t error_c
return ss_tx_to_ms(ss, OSMO_GSUP_MSGT_PROC_SS_RESULT, true, msg);
}
+static int ss_tx_ussd_7bit(struct ss_session *ss, bool final, uint8_t invoke_id, const char *text)
+{
+ struct msgb *msg = gsm0480_gen_ussd_resp_7bit(invoke_id, text);
+ LOGPSS(ss, LOGL_INFO, "Tx USSD '%s'\n", text);
+ OSMO_ASSERT(msg);
+ return ss_tx_to_ms(ss, OSMO_GSUP_MSGT_PROC_SS_RESULT, final, msg);
+}
+
+/***********************************************************************
+ * Internal USSD Handlers
+ ***********************************************************************/
+
+#include "db.h"
+
+static int handle_ussd_own_msisdn(struct osmo_gsup_conn *conn, struct ss_session *ss,
+ const struct osmo_gsup_message *gsup, const struct ss_request *req)
+{
+ struct hlr_subscriber subscr;
+ char buf[GSM0480_USSD_7BIT_STRING_LEN+1];
+ int rc;
+
+ rc = db_subscr_get_by_imsi(g_hlr->dbc, ss->imsi, &subscr);
+ switch (rc) {
+ case 0:
+ if (strlen(subscr.msisdn) == 0)
+ snprintf(buf, sizeof(buf), "You have no MSISDN!");
+ else
+ snprintf(buf, sizeof(buf), "Your extension is %s\r", subscr.msisdn);
+ ss_tx_ussd_7bit(ss, true, req->invoke_id, buf);
+ break;
+ case -ENOENT:
+ ss_tx_error(ss, true, GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER);
+ break;
+ case -EIO:
+ default:
+ ss_tx_error(ss, true, GSM0480_ERR_CODE_SYSTEM_FAILURE);
+ break;
+ }
+ return 0;
+}
+
+static int handle_ussd_own_imsi(struct osmo_gsup_conn *conn, struct ss_session *ss,
+ const struct osmo_gsup_message *gsup, const struct ss_request *req)
+{
+ char buf[GSM0480_USSD_7BIT_STRING_LEN+1];
+ snprintf(buf, sizeof(buf), "Your IMSI is %s!\n", ss->imsi);
+ ss_tx_ussd_7bit(ss, true, req->invoke_id, buf);
+ return 0;
+}
+
+
+static const struct hlr_iuse hlr_iuses[] = {
+ {
+ .name = "own-msisdn",
+ .handle_ussd = handle_ussd_own_msisdn,
+ },
+ {
+ .name = "own-imsi",
+ .handle_ussd = handle_ussd_own_imsi,
+ },
+};
+
+const struct hlr_iuse *iuse_find(const char *name)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(hlr_iuses); i++) {
+ const struct hlr_iuse *iuse = &hlr_iuses[i];
+ if (!strcmp(name, iuse->name))
+ return iuse;
+ }
+ return NULL;
+}
/***********************************************************************
@@ -307,6 +401,7 @@ static int handle_ss(struct ss_session *ss, const struct osmo_gsup_message *gsup
return 0;
}
+/* Handle a USSD GSUP message for a given SS Session received from VLR or EUSE */
static int handle_ussd(struct osmo_gsup_conn *conn, struct ss_session *ss,
const struct osmo_gsup_message *gsup, const struct ss_request *req)
{
@@ -318,8 +413,7 @@ static int handle_ussd(struct osmo_gsup_conn *conn, struct ss_session *ss,
gsm0480_comp_type_name(comp_type), gsm0480_op_code_name(req->opcode),
req->ussd_text);
-
- if (!ss->euse) {
+ if ((ss->is_external && !ss->u.euse) || !ss->u.iuse) {
LOGPSS(ss, LOGL_NOTICE, "USSD for unknown code '%s'\n", req->ussd_text);
ss_tx_error(ss, req->invoke_id, GSM0480_ERR_CODE_SS_NOT_AVAILABLE);
return 0;
@@ -333,19 +427,25 @@ static int handle_ussd(struct osmo_gsup_conn *conn, struct ss_session *ss,
/* FIXME: resolve this based on the database vlr_addr */
osmo_gsup_addr_send(conn->server, (uint8_t *)"MSC-00-00-00-00-00-00", 22, msg_out);
} else {
- /* Received from VLR, Forward to EUSE */
- char addr[128];
- strcpy(addr, "EUSE-");
- osmo_strlcpy(addr+5, ss->euse->name, sizeof(addr)-5);
- conn = gsup_route_find(conn->server, (uint8_t *)addr, strlen(addr)+1);
- if (!conn) {
- LOGPSS(ss, LOGL_ERROR, "Cannot find conn for EUSE %s\n", addr);
- ss_tx_error(ss, req->invoke_id, GSM0480_ERR_CODE_SYSTEM_FAILURE);
+ /* Received from VLR (MS) */
+ if (ss->is_external) {
+ /* Forward to EUSE */
+ char addr[128];
+ strcpy(addr, "EUSE-");
+ osmo_strlcpy(addr+5, ss->u.euse->name, sizeof(addr)-5);
+ conn = gsup_route_find(conn->server, (uint8_t *)addr, strlen(addr)+1);
+ if (!conn) {
+ LOGPSS(ss, LOGL_ERROR, "Cannot find conn for EUSE %s\n", addr);
+ ss_tx_error(ss, req->invoke_id, GSM0480_ERR_CODE_SYSTEM_FAILURE);
+ } else {
+ msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP USSD FW");
+ OSMO_ASSERT(msg_out);
+ osmo_gsup_encode(msg_out, gsup);
+ osmo_gsup_conn_send(conn, msg_out);
+ }
} else {
- msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP USSD FW");
- OSMO_ASSERT(msg_out);
- osmo_gsup_encode(msg_out, gsup);
- osmo_gsup_conn_send(conn, msg_out);
+ /* Handle internally */
+ ss->u.iuse->handle_ussd(conn, ss, gsup, req);
}
}
@@ -392,10 +492,20 @@ int rx_proc_ss_req(struct osmo_gsup_conn *conn, const struct osmo_gsup_message *
if (ss_op_is_ussd(req.opcode)) {
if (conn_is_euse(conn)) {
/* EUSE->VLR: MT USSD. EUSE is known ('conn'), VLR is to be resolved */
- ss->euse = euse_by_conn(conn);
+ ss->u.euse = euse_by_conn(conn);
} else {
/* VLR->EUSE: MO USSD. VLR is known ('conn'), EUSE is to be resolved */
- ss->euse = ussd_euse_find_7bit_gsm(hlr, (const char *) req.ussd_text);
+ struct hlr_ussd_route *rt;
+ rt = ussd_route_lookup_7bit(hlr, (const char *) req.ussd_text);
+ if (rt) {
+ if (rt->is_external) {
+ ss->is_external = true;
+ ss->u.euse = rt->u.euse;
+ } else if (rt) {
+ ss->is_external = false;
+ ss->u.iuse = rt->u.iuse;
+ }
+ }
}
/* dispatch unstructured SS to routing */
handle_ussd(conn, ss, gsup, &req);
diff --git a/src/hlr_ussd.h b/src/hlr_ussd.h
index 433a7f2..d1b9fe0 100644
--- a/src/hlr_ussd.h
+++ b/src/hlr_ussd.h
@@ -5,11 +5,15 @@
struct osmo_gsup_conn;
-struct hlr_euse_route {
- /* hlr_euse.routes */
+struct hlr_ussd_route {
+ /* g_hlr.routes */
struct llist_head list;
- struct hlr_euse *euse;
const char *prefix;
+ bool is_external;
+ union {
+ struct hlr_euse *euse;
+ const struct hlr_iuse *iuse;
+ } u;
};
struct hlr_euse {
@@ -20,21 +24,34 @@ struct hlr_euse {
const char *name;
/* human-readable description */
const char *description;
- /* list of hlr_euse_route */
- struct llist_head routes;
/* GSUP connection to the EUSE, if any */
struct osmo_gsup_conn *conn;
};
-
struct hlr_euse *euse_find(struct hlr *hlr, const char *name);
struct hlr_euse *euse_alloc(struct hlr *hlr, const char *name);
void euse_del(struct hlr_euse *euse);
-struct hlr_euse_route *euse_route_find(struct hlr_euse *euse, const char *prefix);
-struct hlr_euse_route *euse_route_prefix_alloc(struct hlr_euse *euse, const char *prefix);
-void euse_route_del(struct hlr_euse_route *rt);
+const struct hlr_iuse *iuse_find(const char *name);
+
+struct hlr_ussd_route *ussd_route_find_prefix(struct hlr *hlr, const char *prefix);
+struct hlr_ussd_route *ussd_route_prefix_alloc_int(struct hlr *hlr, const char *prefix,
+ const struct hlr_iuse *iuse);
+struct hlr_ussd_route *ussd_route_prefix_alloc_ext(struct hlr *hlr, const char *prefix,
+ struct hlr_euse *euse);
+void ussd_route_del(struct hlr_ussd_route *rt);
int rx_proc_ss_req(struct osmo_gsup_conn *conn, const struct osmo_gsup_message *gsup);
int rx_proc_ss_error(struct osmo_gsup_conn *conn, const struct osmo_gsup_message *gsup);
+
+struct ss_session;
+struct ss_request;
+
+/* Internal USSD Handler */
+struct hlr_iuse {
+ const char *name;
+ /* call-back to be called for any incoming USSD messages for this IUSE */
+ int (*handle_ussd)(struct osmo_gsup_conn *conn, struct ss_session *ss,
+ const struct osmo_gsup_message *gsup, const struct ss_request *req);
+};
diff --git a/src/hlr_vty.c b/src/hlr_vty.c
index 5c359b7..9532a03 100644
--- a/src/hlr_vty.c
+++ b/src/hlr_vty.c
@@ -32,6 +32,7 @@
#include <osmocom/vty/misc.h>
#include <osmocom/abis/ipa.h>
+#include "hlr.h"
#include "hlr_vty.h"
#include "hlr_vty_subscr.h"
#include "gsup_server.h"
@@ -122,47 +123,77 @@ DEFUN(cfg_hlr_gsup_bind_ip,
}
/***********************************************************************
- * External USSD Entity
+ * USSD Entity
***********************************************************************/
#include "hlr_ussd.h"
-DEFUN(cfg_euse_route_pfx, cfg_euse_route_pfx_cmd,
- "route prefix PREFIX",
- "")
+#define USSD_STR "USSD Configuration\n"
+#define UROUTE_STR "Routing Configuration\n"
+#define PREFIX_STR "Prefix-Matching Route\n" "USSD Prefix\n"
+
+#define INT_CHOICE "(own-msisdn|own-imsi)"
+#define INT_STR "Internal USSD Handler\n" \
+ "Respond with subscribers' own MSISDN\n" \
+ "Respond with subscribers' own IMSI\n"
+
+#define EXT_STR "External USSD Handler\n" \
+ "Name of External USSD Handler (IPA CCM ID)\n"
+
+DEFUN(cfg_ussd_route_pfx_int, cfg_ussd_route_pfx_int_cmd,
+ "ussd route prefix PREFIX internal " INT_CHOICE,
+ USSD_STR UROUTE_STR PREFIX_STR INT_STR)
{
- struct hlr_euse *euse = vty->index;
- struct hlr_euse_route *rt = euse_route_find(euse, argv[0]);
+ const struct hlr_iuse *iuse = iuse_find(argv[1]);
+ struct hlr_ussd_route *rt = ussd_route_find_prefix(g_hlr, argv[0]);
+ if (rt) {
+ vty_out(vty, "%% Cannot add [another?] route for prefix %s%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ ussd_route_prefix_alloc_int(g_hlr, argv[0], iuse);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_ussd_route_pfx_ext, cfg_ussd_route_pfx_ext_cmd,
+ "ussd route prefix PREFIX external EUSE",
+ USSD_STR UROUTE_STR PREFIX_STR EXT_STR)
+{
+ struct hlr_euse *euse = euse_find(g_hlr, argv[1]);
+ struct hlr_ussd_route *rt = ussd_route_find_prefix(g_hlr, argv[0]);
if (rt) {
vty_out(vty, "%% Cannot add [another?] route for prefix %s%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
- euse_route_prefix_alloc(euse, argv[0]);
+ if (!euse) {
+ vty_out(vty, "%% Cannot find euse '%s'%s", argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ ussd_route_prefix_alloc_ext(g_hlr, argv[0], euse);
return CMD_SUCCESS;
}
-DEFUN(cfg_euse_no_route_pfx, cfg_euse_no_route_pfx_cmd,
- "no route prefix PREFIX",
- NO_STR "")
+DEFUN(cfg_ussd_no_route_pfx, cfg_ussd_no_route_pfx_cmd,
+ "no ussd route prefix PREFIX",
+ NO_STR USSD_STR UROUTE_STR PREFIX_STR)
{
- struct hlr_euse *euse = vty->index;
- struct hlr_euse_route *rt = euse_route_find(euse, argv[0]);
+ struct hlr_ussd_route *rt = ussd_route_find_prefix(g_hlr, argv[0]);
if (!rt) {
vty_out(vty, "%% Cannot find route for prefix %s%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
- euse_route_del(rt);
+ ussd_route_del(rt);
return CMD_SUCCESS;
}
-DEFUN(cfg_euse_defaultroute, cfg_euse_defaultroute_cmd,
- "default-route",
- "Set this EUSE as default-route for all USSD to unknown destinations\n")
+DEFUN(cfg_ussd_defaultroute, cfg_ussd_defaultroute_cmd,
+ "ussd default-route external EUSE",
+ USSD_STR "Configure default-route for all USSD to unknown destinations\n"
+ EXT_STR)
{
- struct hlr_euse *euse = vty->index;
+ struct hlr_euse *euse = euse_find(g_hlr, argv[0]);
if (g_hlr->euse_default != euse) {
vty_out(vty, "Switching default route from %s to %s%s",
@@ -174,16 +205,10 @@ DEFUN(cfg_euse_defaultroute, cfg_euse_defaultroute_cmd,
return CMD_SUCCESS;
}
-DEFUN(cfg_euse_no_defaultroute, cfg_euse_no_defaultroute_cmd,
- "no default-route",
- NO_STR "Remove this EUSE as default-route for all USSD to unknown destinations\n")
+DEFUN(cfg_ussd_no_defaultroute, cfg_ussd_no_defaultroute_cmd,
+ "no ussd default-route",
+ NO_STR USSD_STR "Remove the default-route for all USSD to unknown destinations\n")
{
- struct hlr_euse *euse = vty->index;
-
- if (g_hlr->euse_default != euse) {
- vty_out(vty, "%% Current EUSE is no default route, cannot delete it%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
g_hlr->euse_default = NULL;
return CMD_SUCCESS;
@@ -236,24 +261,27 @@ DEFUN(cfg_no_euse, cfg_no_euse_cmd,
static void dump_one_euse(struct vty *vty, struct hlr_euse *euse)
{
- struct hlr_euse_route *er;
-
vty_out(vty, " euse %s%s", euse->name, VTY_NEWLINE);
-
- llist_for_each_entry(er, &euse->routes, list)
- vty_out(vty, " route prefix %s%s", er->prefix, VTY_NEWLINE);
-
- if (g_hlr->euse_default == euse)
- vty_out(vty, " default-route%s", VTY_NEWLINE);
}
static int config_write_euse(struct vty *vty)
{
struct hlr_euse *euse;
+ struct hlr_ussd_route *rt;
llist_for_each_entry(euse, &g_hlr->euse_list, list)
dump_one_euse(vty, euse);
+ llist_for_each_entry(rt, &g_hlr->ussd_routes, list) {
+ vty_out(vty, " ussd route prefix %s %s %s%s", rt->prefix,
+ rt->is_external ? "external" : "internal",
+ rt->is_external ? rt->u.euse->name : rt->u.iuse->name,
+ VTY_NEWLINE);
+ }
+
+ if (g_hlr->euse_default)
+ vty_out(vty, " ussd default-route external %s%s", g_hlr->euse_default->name, VTY_NEWLINE);
+
return 0;
}
@@ -314,10 +342,11 @@ void hlr_vty_init(const struct log_info *cat)
install_element(HLR_NODE, &cfg_euse_cmd);
install_element(HLR_NODE, &cfg_no_euse_cmd);
install_node(&euse_node, config_write_euse);
- install_element(EUSE_NODE, &cfg_euse_route_pfx_cmd);
- install_element(EUSE_NODE, &cfg_euse_no_route_pfx_cmd);
- install_element(EUSE_NODE, &cfg_euse_defaultroute_cmd);
- install_element(EUSE_NODE, &cfg_euse_no_defaultroute_cmd);
+ install_element(HLR_NODE, &cfg_ussd_route_pfx_int_cmd);
+ install_element(HLR_NODE, &cfg_ussd_route_pfx_ext_cmd);
+ install_element(HLR_NODE, &cfg_ussd_no_route_pfx_cmd);
+ install_element(HLR_NODE, &cfg_ussd_defaultroute_cmd);
+ install_element(HLR_NODE, &cfg_ussd_no_defaultroute_cmd);
hlr_vty_subscriber_init();
}
diff --git a/tests/test_nodes.vty b/tests/test_nodes.vty
index 4badad5..58f5c61 100644
--- a/tests/test_nodes.vty
+++ b/tests/test_nodes.vty
@@ -72,6 +72,11 @@ OsmoHLR(config-hlr)# list
gsup
euse NAME
no euse NAME
+ ussd route prefix PREFIX internal (own-msisdn|own-imsi)
+ ussd route prefix PREFIX external EUSE
+ no ussd route prefix PREFIX
+ ussd default-route external EUSE
+ no ussd default-route
OsmoHLR(config-hlr)# gsup
OsmoHLR(config-hlr-gsup)# list
@@ -122,4 +127,5 @@ ctrl
hlr
gsup
bind ip 127.0.0.1
+ ussd route prefix *#100# internal own-msisdn
end