mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr.git
synced 2025-11-04 14:13:42 +00:00
Compare commits
2 Commits
osmith/aut
...
fixeria/us
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6f695e0e6 | ||
|
|
35d2342850 |
@@ -30,6 +30,7 @@ noinst_HEADERS = \
|
|||||||
ctrl.h \
|
ctrl.h \
|
||||||
hlr_vty.h \
|
hlr_vty.h \
|
||||||
hlr_vty_subscr.h \
|
hlr_vty_subscr.h \
|
||||||
|
hlr_ss_ussd.h \
|
||||||
db_bootstrap.h \
|
db_bootstrap.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
@@ -53,6 +54,7 @@ osmo_hlr_SOURCES = \
|
|||||||
hlr_vty.c \
|
hlr_vty.c \
|
||||||
hlr_vty_subscr.c \
|
hlr_vty_subscr.c \
|
||||||
gsup_send.c \
|
gsup_send.c \
|
||||||
|
hlr_ss_ussd.c \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
osmo_hlr_LDADD = \
|
osmo_hlr_LDADD = \
|
||||||
|
|||||||
14
src/hlr.c
14
src/hlr.c
@@ -42,6 +42,7 @@
|
|||||||
#include "rand.h"
|
#include "rand.h"
|
||||||
#include "luop.h"
|
#include "luop.h"
|
||||||
#include "hlr_vty.h"
|
#include "hlr_vty.h"
|
||||||
|
#include "hlr_ss_ussd.h"
|
||||||
|
|
||||||
static struct hlr *g_hlr;
|
static struct hlr *g_hlr;
|
||||||
|
|
||||||
@@ -296,10 +297,19 @@ static int rx_upd_loc_req(struct osmo_gsup_conn *conn,
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
uint8_t *addr;
|
||||||
|
rc = osmo_gsup_conn_ccm_get(conn, &addr, IPAC_IDTAG_SERNR);
|
||||||
|
if (rc <= 0) {
|
||||||
|
osmo_strlcpy(luop->subscr.imsi, gsup->imsi, sizeof(luop->subscr.imsi));
|
||||||
|
lu_op_tx_error(luop, GMM_CAUSE_NET_FAIL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
/* TODO: Subscriber allowed to roam in PLMN? */
|
/* TODO: Subscriber allowed to roam in PLMN? */
|
||||||
/* TODO: Update RoutingInfo */
|
/* TODO: Update RoutingInfo */
|
||||||
/* TODO: Reset Flag MS Purged (cs/ps) */
|
/* TODO: Reset Flag MS Purged (cs/ps) */
|
||||||
/* TODO: Control_Tracing_HLR / Control_Tracing_HLR_with_SGSN */
|
/* TODO: Control_Tracing_HLR / Control_Tracing_HLR_with_SGSN */
|
||||||
|
db_subscr_lu(g_hlr->dbc, luop->subscr.id, (char *)addr, luop->is_ps);
|
||||||
lu_op_tx_insert_subscr_data(luop);
|
lu_op_tx_insert_subscr_data(luop);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -524,6 +534,7 @@ static void signal_hdlr(int signal)
|
|||||||
case SIGINT:
|
case SIGINT:
|
||||||
LOGP(DMAIN, LOGL_NOTICE, "Terminating due to SIGINT\n");
|
LOGP(DMAIN, LOGL_NOTICE, "Terminating due to SIGINT\n");
|
||||||
osmo_gsup_server_destroy(g_hlr->gs);
|
osmo_gsup_server_destroy(g_hlr->gs);
|
||||||
|
hlr_usse_clean_up(g_hlr);
|
||||||
db_close(g_hlr->dbc);
|
db_close(g_hlr->dbc);
|
||||||
log_fini();
|
log_fini();
|
||||||
talloc_report_full(hlr_ctx, stderr);
|
talloc_report_full(hlr_ctx, stderr);
|
||||||
@@ -560,6 +571,9 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
g_hlr = talloc_zero(hlr_ctx, struct hlr);
|
g_hlr = talloc_zero(hlr_ctx, struct hlr);
|
||||||
|
|
||||||
|
INIT_LLIST_HEAD(&g_hlr->usse_list);
|
||||||
|
g_hlr->usse_default = NULL;
|
||||||
|
|
||||||
rc = osmo_init_logging2(hlr_ctx, &hlr_log_info);
|
rc = osmo_init_logging2(hlr_ctx, &hlr_log_info);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
fprintf(stderr, "Error initializing logging\n");
|
fprintf(stderr, "Error initializing logging\n");
|
||||||
|
|||||||
@@ -23,6 +23,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <osmocom/core/linuxlist.h>
|
||||||
|
|
||||||
|
struct hlr_usse;
|
||||||
|
|
||||||
struct hlr {
|
struct hlr {
|
||||||
/* GSUP server pointer */
|
/* GSUP server pointer */
|
||||||
@@ -37,6 +40,10 @@ struct hlr {
|
|||||||
|
|
||||||
/* Local bind addr */
|
/* Local bind addr */
|
||||||
char *gsup_bind_addr;
|
char *gsup_bind_addr;
|
||||||
|
|
||||||
|
/* SS/USSD processing entities */
|
||||||
|
struct llist_head usse_list;
|
||||||
|
struct hlr_usse *usse_default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hlr_subscriber;
|
struct hlr_subscriber;
|
||||||
|
|||||||
129
src/hlr_ss_ussd.c
Normal file
129
src/hlr_ss_ussd.c
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/* Supplementary Services signalling implementation */
|
||||||
|
|
||||||
|
/* (C) 2018 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
* (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com>
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/talloc.h>
|
||||||
|
#include <osmocom/core/linuxlist.h>
|
||||||
|
|
||||||
|
#include "hlr.h"
|
||||||
|
#include "hlr_ss_ussd.h"
|
||||||
|
|
||||||
|
struct hlr_usse *hlr_usse_find(struct hlr *hlr, const char *name)
|
||||||
|
{
|
||||||
|
struct hlr_usse *usse;
|
||||||
|
|
||||||
|
llist_for_each_entry(usse, &hlr->usse_list, list) {
|
||||||
|
if (!strcmp(usse->name, name))
|
||||||
|
return usse;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct hlr_usse *hlr_usse_alloc(struct hlr *hlr, const char *name)
|
||||||
|
{
|
||||||
|
struct hlr_usse *usse;
|
||||||
|
|
||||||
|
usse = hlr_usse_find(hlr, name);
|
||||||
|
if (usse)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
usse = talloc(hlr, struct hlr_usse);
|
||||||
|
usse->name = talloc_strdup(usse, name);
|
||||||
|
usse->description = NULL;
|
||||||
|
usse->hlr = hlr;
|
||||||
|
|
||||||
|
INIT_LLIST_HEAD(&usse->patterns);
|
||||||
|
llist_add_tail(&usse->list, &hlr->usse_list);
|
||||||
|
|
||||||
|
return usse;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hlr_usse_del(struct hlr_usse *usse)
|
||||||
|
{
|
||||||
|
struct hlr_usse_pattern *pt, *_pt;
|
||||||
|
|
||||||
|
/* Release linked patterns */
|
||||||
|
llist_for_each_entry_safe(pt, _pt, &usse->patterns, list)
|
||||||
|
hlr_usse_pattern_del(pt);
|
||||||
|
|
||||||
|
/* Unlink from the HLR's USSE list */
|
||||||
|
llist_del(&usse->list);
|
||||||
|
|
||||||
|
/* Release memory */
|
||||||
|
talloc_free(usse);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct hlr_usse_pattern *hlr_usse_pattern_find(struct hlr_usse *usse,
|
||||||
|
enum hlr_usse_pattern_type type, const char *pattern)
|
||||||
|
{
|
||||||
|
struct hlr_usse_pattern *pt;
|
||||||
|
|
||||||
|
llist_for_each_entry(pt, &usse->patterns, list) {
|
||||||
|
if (pt->type != type)
|
||||||
|
continue;
|
||||||
|
if (strcmp(pt->pattern, pattern))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct hlr_usse_pattern *hlr_usse_pattern_add(struct hlr_usse *usse,
|
||||||
|
enum hlr_usse_pattern_type type, const char *pattern)
|
||||||
|
{
|
||||||
|
struct hlr_usse_pattern *pt;
|
||||||
|
|
||||||
|
pt = hlr_usse_pattern_find(usse, type, pattern);
|
||||||
|
if (pt)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pt = talloc(usse, struct hlr_usse_pattern);
|
||||||
|
pt->pattern = talloc_strdup(pt, pattern);
|
||||||
|
pt->rsp_fmt = NULL;
|
||||||
|
pt->type = type;
|
||||||
|
pt->usse = usse;
|
||||||
|
|
||||||
|
llist_add_tail(&pt->list, &usse->patterns);
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hlr_usse_pattern_del(struct hlr_usse_pattern *pt)
|
||||||
|
{
|
||||||
|
/* Unlink from the USSE's list */
|
||||||
|
llist_del(&pt->list);
|
||||||
|
|
||||||
|
/* Release memory */
|
||||||
|
talloc_free(pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hlr_usse_clean_up(struct hlr *hlr)
|
||||||
|
{
|
||||||
|
struct hlr_usse *usse, *_usse;
|
||||||
|
|
||||||
|
llist_for_each_entry_safe(usse, _usse, &hlr->usse_list, list)
|
||||||
|
hlr_usse_del(usse);
|
||||||
|
}
|
||||||
51
src/hlr_ss_ussd.h
Normal file
51
src/hlr_ss_ussd.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <osmocom/core/linuxlist.h>
|
||||||
|
#include <osmocom/gsm/gsm0480.h>
|
||||||
|
|
||||||
|
/* Represents a single USSE (either the internal, or an external) */
|
||||||
|
struct hlr_usse {
|
||||||
|
/* list in the per-HLR list of USSEs */
|
||||||
|
struct llist_head list;
|
||||||
|
/* back-pointer to the HLR instance */
|
||||||
|
struct hlr *hlr;
|
||||||
|
/* human-readable description */
|
||||||
|
const char *description;
|
||||||
|
/* name (must match the IPA ID tag) */
|
||||||
|
const char *name;
|
||||||
|
/* list of USSD-code matching patterns */
|
||||||
|
struct llist_head patterns;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Matching pattern types sorted by priority */
|
||||||
|
enum hlr_usse_pattern_type {
|
||||||
|
HLR_USSE_PATTERN_CODE = 0, /* higher priority */
|
||||||
|
HLR_USSE_PATTERN_REGEXP,
|
||||||
|
HLR_USSE_PATTERN_PREFIX,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Represents a USSD-code matching pattern */
|
||||||
|
struct hlr_usse_pattern {
|
||||||
|
/* link to the parent USSE */
|
||||||
|
struct llist_head list;
|
||||||
|
/* back-pointer to the parent USSE */
|
||||||
|
struct hlr_usse *usse;
|
||||||
|
/* Patter type, e.g. code, regexp or prefix */
|
||||||
|
enum hlr_usse_pattern_type type;
|
||||||
|
/* Mathing pattern, e.g. '*110*' for prefix */
|
||||||
|
const char *pattern;
|
||||||
|
/* Response format string, e.g. 'Your MSISDN is %m' */
|
||||||
|
char *rsp_fmt;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hlr_usse *hlr_usse_find(struct hlr *hlr, const char *name);
|
||||||
|
struct hlr_usse *hlr_usse_alloc(struct hlr *hlr, const char *name);
|
||||||
|
void hlr_usse_del(struct hlr_usse *usse);
|
||||||
|
|
||||||
|
struct hlr_usse_pattern *hlr_usse_pattern_find(struct hlr_usse *usse,
|
||||||
|
enum hlr_usse_pattern_type type, const char *pattern);
|
||||||
|
struct hlr_usse_pattern *hlr_usse_pattern_add(struct hlr_usse *usse,
|
||||||
|
enum hlr_usse_pattern_type type, const char *pattern);
|
||||||
|
void hlr_usse_pattern_del(struct hlr_usse_pattern *pt);
|
||||||
|
|
||||||
|
void hlr_usse_clean_up(struct hlr *hlr);
|
||||||
293
src/hlr_vty.c
293
src/hlr_vty.c
@@ -3,6 +3,7 @@
|
|||||||
/* (C) 2016 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
/* (C) 2016 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||||
* Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
|
* Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
|
||||||
* (C) 2018 Harald Welte <laforge@gnumonks.org>
|
* (C) 2018 Harald Welte <laforge@gnumonks.org>
|
||||||
|
* (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com>
|
||||||
*
|
*
|
||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*
|
*
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
#include <osmocom/abis/ipa.h>
|
#include <osmocom/abis/ipa.h>
|
||||||
|
|
||||||
#include "hlr_vty.h"
|
#include "hlr_vty.h"
|
||||||
|
#include "hlr_ss_ussd.h"
|
||||||
#include "hlr_vty_subscr.h"
|
#include "hlr_vty_subscr.h"
|
||||||
#include "gsup_server.h"
|
#include "gsup_server.h"
|
||||||
|
|
||||||
@@ -94,7 +96,7 @@ static void show_one_conn(struct vty *vty, const struct osmo_gsup_conn *conn)
|
|||||||
|
|
||||||
DEFUN(show_gsup_conn, show_gsup_conn_cmd,
|
DEFUN(show_gsup_conn, show_gsup_conn_cmd,
|
||||||
"show gsup-connections",
|
"show gsup-connections",
|
||||||
SHOW_STR "GSUP Connections from VLRs, SGSNs, EUSEs\n")
|
SHOW_STR "GSUP Connections from VLRs, SGSNs, EUSSEs\n")
|
||||||
{
|
{
|
||||||
struct osmo_gsup_server *gs = g_hlr->gs;
|
struct osmo_gsup_server *gs = g_hlr->gs;
|
||||||
struct osmo_gsup_conn *conn;
|
struct osmo_gsup_conn *conn;
|
||||||
@@ -119,12 +121,290 @@ DEFUN(cfg_hlr_gsup_bind_ip,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* Unstructured Supplementary Services processing Entity configuration
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
static struct cmd_node iusse_node = {
|
||||||
|
IUSSE_NODE,
|
||||||
|
"%s(config-hlr-iusse)# ",
|
||||||
|
1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct cmd_node eusse_node = {
|
||||||
|
EUSSE_NODE,
|
||||||
|
"%s(config-hlr-eusse)# ",
|
||||||
|
1,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VTY_USSE_NAME_DESC \
|
||||||
|
"Internal USSD processing Entity\n" \
|
||||||
|
"Alphanumeric name of an External USSE\n"
|
||||||
|
|
||||||
|
DEFUN(cfg_usse, cfg_usse_cmd,
|
||||||
|
"usse (internal|NAME)",
|
||||||
|
"Configure a particular USSE (USSD processing Entity)\n"
|
||||||
|
VTY_USSE_NAME_DESC)
|
||||||
|
{
|
||||||
|
const char *name = argv[0];
|
||||||
|
struct hlr_usse *usse;
|
||||||
|
|
||||||
|
usse = hlr_usse_find(g_hlr, name);
|
||||||
|
if (!usse) {
|
||||||
|
usse = hlr_usse_alloc(g_hlr, name);
|
||||||
|
if (!usse)
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
vty->index_sub = &usse->description;
|
||||||
|
vty->index = usse;
|
||||||
|
|
||||||
|
/* IUSSE or EUSSE? */
|
||||||
|
if (!strcmp(usse->name, "internal"))
|
||||||
|
vty->node = IUSSE_NODE;
|
||||||
|
else
|
||||||
|
vty->node = EUSSE_NODE;
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(cfg_no_usse, cfg_no_usse_cmd,
|
||||||
|
"no usse (internal|NAME)",
|
||||||
|
NO_STR "Remove a particular USSE (USSD processing Entity)\n"
|
||||||
|
VTY_USSE_NAME_DESC)
|
||||||
|
{
|
||||||
|
const char *name = argv[0];
|
||||||
|
struct hlr_usse *usse;
|
||||||
|
|
||||||
|
usse = hlr_usse_find(g_hlr, name);
|
||||||
|
if (!usse) {
|
||||||
|
vty_out(vty, "%% Cannot remove non-existent "
|
||||||
|
"USSE '%s'%s", name, VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_hlr->usse_default == usse) {
|
||||||
|
vty_out(vty, "%% Cannot remove USSE '%s', "
|
||||||
|
"it is the default route%s", name, VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
hlr_usse_del(usse);
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(cfg_usse_default, cfg_usse_default_cmd,
|
||||||
|
"usse-default (internal|NAME)",
|
||||||
|
"Default USSD processing Entity\n"
|
||||||
|
VTY_USSE_NAME_DESC)
|
||||||
|
{
|
||||||
|
const char *name = argv[0];
|
||||||
|
struct hlr_usse *usse;
|
||||||
|
|
||||||
|
usse = hlr_usse_find(g_hlr, name);
|
||||||
|
if (!usse) {
|
||||||
|
vty_out(vty, "%% Cannot find USSE '%s'%s", name, VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_hlr->usse_default == usse) {
|
||||||
|
vty_out(vty, "%% USSE '%s' is already "
|
||||||
|
"used by default%s", usse->name, VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hlr->usse_default = usse;
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(cfg_no_usse_default, cfg_no_usse_default_cmd,
|
||||||
|
"no usse-default",
|
||||||
|
NO_STR "No default USSD processing Entity "
|
||||||
|
"(drop all unmatched requests)\n")
|
||||||
|
{
|
||||||
|
g_hlr->usse_default = NULL;
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VTY_USSE_PATTERN_CMD \
|
||||||
|
"pattern (code|regexp|prefix) PATTERN"
|
||||||
|
|
||||||
|
#define VTY_USSE_PATTERN_DESC \
|
||||||
|
"Match USSD-request codes by exact value (e.g. '*#100#')\n" \
|
||||||
|
"Match USSD-request codes by regular expression (e.g. '^\\*[5-7]+'\\*)\n" \
|
||||||
|
"Match USSD-request codes by prefix (e.g. '*#' or '*110*')\n" \
|
||||||
|
"Matching pattern\n"
|
||||||
|
|
||||||
|
static int _cfg_usse_pattern(struct vty *vty, int argc, const char **argv)
|
||||||
|
{
|
||||||
|
struct hlr_usse *usse = vty->index;
|
||||||
|
enum hlr_usse_pattern_type type;
|
||||||
|
struct hlr_usse_pattern *pt;
|
||||||
|
bool is_iusse;
|
||||||
|
|
||||||
|
/* Determine which kind of matching pattern required */
|
||||||
|
switch (argv[0][0]) {
|
||||||
|
case 'c':
|
||||||
|
type = HLR_USSE_PATTERN_CODE;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
type = HLR_USSE_PATTERN_REGEXP;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
type = HLR_USSE_PATTERN_PREFIX;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Shouldn't happen, but let's make sure */
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* IUSSE or EUSSE? */
|
||||||
|
is_iusse = !strcmp(usse->name, "internal");
|
||||||
|
|
||||||
|
/* Attempt to find pattern */
|
||||||
|
pt = hlr_usse_pattern_find(usse, type, argv[1]);
|
||||||
|
if (pt && !is_iusse) {
|
||||||
|
/* Response modification is only actual for IUSSE */
|
||||||
|
vty_out(vty, "%% Pattern already exists!%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate if required */
|
||||||
|
if (!pt) {
|
||||||
|
pt = hlr_usse_pattern_add(usse, type, argv[1]);
|
||||||
|
if (!pt) {
|
||||||
|
vty_out(vty, "%% Cannot add pattern '%s' of type '%s'%s",
|
||||||
|
argv[1], argv[0], VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Response string for IUSSE */
|
||||||
|
if (is_iusse) {
|
||||||
|
if (pt->rsp_fmt)
|
||||||
|
talloc_free(pt->rsp_fmt);
|
||||||
|
pt->rsp_fmt = talloc_strdup(pt, argv_concat(argv, argc, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(cfg_iusse_pattern, cfg_iusse_pattern_cmd,
|
||||||
|
VTY_USSE_PATTERN_CMD " response .RESPONSE",
|
||||||
|
"Add or modify a USSD-code matching pattern\n"
|
||||||
|
VTY_USSE_PATTERN_DESC
|
||||||
|
"Response format string (e.g. 'Your MSISDN is %m')\n")
|
||||||
|
{
|
||||||
|
return _cfg_usse_pattern(vty, argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(cfg_eusse_pattern, cfg_eusse_pattern_cmd,
|
||||||
|
VTY_USSE_PATTERN_CMD,
|
||||||
|
"Add a new USSD-code matching pattern\n"
|
||||||
|
VTY_USSE_PATTERN_DESC)
|
||||||
|
{
|
||||||
|
return _cfg_usse_pattern(vty, argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(cfg_usse_no_pattern, cfg_usse_no_pattern_cmd,
|
||||||
|
"no " VTY_USSE_PATTERN_CMD,
|
||||||
|
NO_STR "Remove an existing USSD-code matching pattern\n"
|
||||||
|
VTY_USSE_PATTERN_DESC)
|
||||||
|
{
|
||||||
|
struct hlr_usse *usse = vty->index;
|
||||||
|
enum hlr_usse_pattern_type type;
|
||||||
|
struct hlr_usse_pattern *pt;
|
||||||
|
|
||||||
|
/* Determine which kind of matching pattern required */
|
||||||
|
switch (argv[0][0]) {
|
||||||
|
case 'c':
|
||||||
|
type = HLR_USSE_PATTERN_CODE;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
type = HLR_USSE_PATTERN_REGEXP;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
type = HLR_USSE_PATTERN_PREFIX;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Shouldn't happen, but let's make sure */
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
pt = hlr_usse_pattern_find(usse, type, argv[1]);
|
||||||
|
if (!pt) {
|
||||||
|
vty_out(vty, "%% Cannot remove non-existent pattern '%s' "
|
||||||
|
"of type '%s'%s", argv[1], argv[0], VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
hlr_usse_pattern_del(pt);
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_one_usse(struct vty *vty, struct hlr_usse *usse)
|
||||||
|
{
|
||||||
|
struct hlr_usse_pattern *pt;
|
||||||
|
const char *pt_type;
|
||||||
|
|
||||||
|
vty_out(vty, " usse %s%s", usse->name, VTY_NEWLINE);
|
||||||
|
// FIXME: what about usse->description?
|
||||||
|
|
||||||
|
llist_for_each_entry(pt, &usse->patterns, list) {
|
||||||
|
/* Stringify pattern type */
|
||||||
|
switch (pt->type) {
|
||||||
|
case HLR_USSE_PATTERN_CODE:
|
||||||
|
pt_type = "code";
|
||||||
|
break;
|
||||||
|
case HLR_USSE_PATTERN_REGEXP:
|
||||||
|
pt_type = "regexp";
|
||||||
|
break;
|
||||||
|
case HLR_USSE_PATTERN_PREFIX:
|
||||||
|
pt_type = "prefix";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Should not happen */
|
||||||
|
OSMO_ASSERT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pt->rsp_fmt != NULL)
|
||||||
|
vty_out(vty, " pattern %s %s response %s%s", pt_type,
|
||||||
|
pt->pattern, pt->rsp_fmt, VTY_NEWLINE);
|
||||||
|
else
|
||||||
|
vty_out(vty, " pattern %s %s%s", pt_type,
|
||||||
|
pt->pattern, VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int config_write_usse(struct vty *vty)
|
||||||
|
{
|
||||||
|
struct hlr_usse *usse;
|
||||||
|
|
||||||
|
if (g_hlr->usse_default == NULL)
|
||||||
|
vty_out(vty, " no usse-default%s", VTY_NEWLINE);
|
||||||
|
else
|
||||||
|
vty_out(vty, " usse-default %s%s",
|
||||||
|
g_hlr->usse_default->name, VTY_NEWLINE);
|
||||||
|
|
||||||
|
llist_for_each_entry(usse, &g_hlr->usse_list, list)
|
||||||
|
dump_one_usse(vty, usse);
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* Common Code
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
int hlr_vty_go_parent(struct vty *vty)
|
int hlr_vty_go_parent(struct vty *vty)
|
||||||
{
|
{
|
||||||
switch (vty->node) {
|
switch (vty->node) {
|
||||||
case GSUP_NODE:
|
case GSUP_NODE:
|
||||||
|
case IUSSE_NODE:
|
||||||
|
case EUSSE_NODE:
|
||||||
vty->node = HLR_NODE;
|
vty->node = HLR_NODE;
|
||||||
vty->index = NULL;
|
vty->index = NULL;
|
||||||
|
vty->index_sub = NULL;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
case HLR_NODE:
|
case HLR_NODE:
|
||||||
@@ -169,5 +449,16 @@ void hlr_vty_init(struct hlr *hlr, const struct log_info *cat)
|
|||||||
|
|
||||||
install_element(GSUP_NODE, &cfg_hlr_gsup_bind_ip_cmd);
|
install_element(GSUP_NODE, &cfg_hlr_gsup_bind_ip_cmd);
|
||||||
|
|
||||||
|
install_element(HLR_NODE, &cfg_usse_cmd);
|
||||||
|
install_element(HLR_NODE, &cfg_no_usse_cmd);
|
||||||
|
install_element(HLR_NODE, &cfg_usse_default_cmd);
|
||||||
|
install_element(HLR_NODE, &cfg_no_usse_default_cmd);
|
||||||
|
install_node(&eusse_node, config_write_usse);
|
||||||
|
install_element(EUSSE_NODE, &cfg_eusse_pattern_cmd);
|
||||||
|
install_element(EUSSE_NODE, &cfg_usse_no_pattern_cmd);
|
||||||
|
install_node(&iusse_node, NULL);
|
||||||
|
install_element(IUSSE_NODE, &cfg_iusse_pattern_cmd);
|
||||||
|
install_element(IUSSE_NODE, &cfg_usse_no_pattern_cmd);
|
||||||
|
|
||||||
hlr_vty_subscriber_init(hlr);
|
hlr_vty_subscriber_init(hlr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
enum hlr_vty_node {
|
enum hlr_vty_node {
|
||||||
HLR_NODE = _LAST_OSMOVTY_NODE + 1,
|
HLR_NODE = _LAST_OSMOVTY_NODE + 1,
|
||||||
GSUP_NODE,
|
GSUP_NODE,
|
||||||
|
IUSSE_NODE,
|
||||||
|
EUSSE_NODE,
|
||||||
};
|
};
|
||||||
|
|
||||||
int hlr_vty_is_config_node(struct vty *vty, int node);
|
int hlr_vty_is_config_node(struct vty *vty, int node);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ EXTRA_DIST = \
|
|||||||
test_subscriber.vty \
|
test_subscriber.vty \
|
||||||
test_subscriber.sql \
|
test_subscriber.sql \
|
||||||
test_subscriber.ctrl \
|
test_subscriber.ctrl \
|
||||||
|
test_sse.vty \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
TESTSUITE = $(srcdir)/testsuite
|
TESTSUITE = $(srcdir)/testsuite
|
||||||
|
|||||||
@@ -70,6 +70,10 @@ OsmoHLR(config-hlr)# list
|
|||||||
exit
|
exit
|
||||||
end
|
end
|
||||||
gsup
|
gsup
|
||||||
|
usse (internal|NAME)
|
||||||
|
no usse (internal|NAME)
|
||||||
|
usse-default (internal|NAME)
|
||||||
|
no usse-default
|
||||||
|
|
||||||
OsmoHLR(config-hlr)# gsup
|
OsmoHLR(config-hlr)# gsup
|
||||||
OsmoHLR(config-hlr-gsup)# list
|
OsmoHLR(config-hlr-gsup)# list
|
||||||
@@ -85,6 +89,39 @@ OsmoHLR(config-hlr-gsup)# list
|
|||||||
bind ip A.B.C.D
|
bind ip A.B.C.D
|
||||||
|
|
||||||
OsmoHLR(config-hlr-gsup)# exit
|
OsmoHLR(config-hlr-gsup)# exit
|
||||||
|
OsmoHLR(config-hlr)# usse test
|
||||||
|
OsmoHLR(config-hlr-eusse)# list
|
||||||
|
help
|
||||||
|
list
|
||||||
|
write terminal
|
||||||
|
write file
|
||||||
|
write memory
|
||||||
|
write
|
||||||
|
show running-config
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
pattern (code|regexp|prefix) PATTERN
|
||||||
|
no pattern (code|regexp|prefix) PATTERN
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr-eusse)# exit
|
||||||
|
OsmoHLR(config-hlr)# usse internal
|
||||||
|
OsmoHLR(config-hlr-iusse)# list
|
||||||
|
help
|
||||||
|
list
|
||||||
|
write terminal
|
||||||
|
write file
|
||||||
|
write memory
|
||||||
|
write
|
||||||
|
show running-config
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
pattern (code|regexp|prefix) PATTERN response .RESPONSE
|
||||||
|
no pattern (code|regexp|prefix) PATTERN
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr-iusse)# exit
|
||||||
|
OsmoHLR(config-hlr)# no usse test
|
||||||
|
OsmoHLR(config-hlr)# no usse internal
|
||||||
|
|
||||||
OsmoHLR(config-hlr)# exit
|
OsmoHLR(config-hlr)# exit
|
||||||
OsmoHLR(config)# exit
|
OsmoHLR(config)# exit
|
||||||
OsmoHLR# configure terminal
|
OsmoHLR# configure terminal
|
||||||
@@ -119,4 +156,5 @@ ctrl
|
|||||||
hlr
|
hlr
|
||||||
gsup
|
gsup
|
||||||
bind ip 127.0.0.1
|
bind ip 127.0.0.1
|
||||||
|
no usse-default
|
||||||
end
|
end
|
||||||
|
|||||||
246
tests/test_usse.vty
Normal file
246
tests/test_usse.vty
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
OsmoHLR> enable
|
||||||
|
OsmoHLR# configure terminal
|
||||||
|
OsmoHLR(config)# show running-config
|
||||||
|
|
||||||
|
Current configuration:
|
||||||
|
!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging filter all 1
|
||||||
|
logging color 1
|
||||||
|
logging print category 1
|
||||||
|
logging print extended-timestamp 1
|
||||||
|
logging print file 1
|
||||||
|
logging level all debug
|
||||||
|
logging level main notice
|
||||||
|
logging level db notice
|
||||||
|
logging level auc notice
|
||||||
|
...
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
ctrl
|
||||||
|
bind 127.0.0.1
|
||||||
|
hlr
|
||||||
|
gsup
|
||||||
|
bind ip 127.0.0.1
|
||||||
|
no usse-default
|
||||||
|
end
|
||||||
|
|
||||||
|
OsmoHLR(config)# hlr
|
||||||
|
OsmoHLR(config-hlr)# no usse test
|
||||||
|
% Cannot remove non-existent USSE 'test'
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr)# usse gw1
|
||||||
|
OsmoHLR(config-hlr-eusse)# no pattern prefix *111*
|
||||||
|
% Cannot remove non-existent pattern '*111*' of type 'prefix'
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr-eusse)# pattern prefix *110*
|
||||||
|
OsmoHLR(config-hlr-eusse)# pattern prefix *181*
|
||||||
|
OsmoHLR(config-hlr-eusse)# pattern prefix *110*
|
||||||
|
% Pattern already exists!
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr-eusse)# pattern code *110*
|
||||||
|
OsmoHLR(config-hlr-eusse)# pattern code *888#
|
||||||
|
OsmoHLR(config-hlr-eusse)# pattern code *110*
|
||||||
|
% Pattern already exists!
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr-eusse)# pattern regexp ^*[1-3]{3}*[0-9]+#$
|
||||||
|
OsmoHLR(config-hlr-eusse)# pattern regexp ^*[5-7]{3}*[0-9]+#$
|
||||||
|
OsmoHLR(config-hlr-eusse)# pattern regexp ^*[1-3]{3}*[0-9]+#$
|
||||||
|
% Pattern already exists!
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr-eusse)# show running-config
|
||||||
|
|
||||||
|
Current configuration:
|
||||||
|
!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging filter all 1
|
||||||
|
logging color 1
|
||||||
|
logging print category 1
|
||||||
|
logging print extended-timestamp 1
|
||||||
|
logging print file 1
|
||||||
|
logging level all debug
|
||||||
|
logging level main notice
|
||||||
|
logging level db notice
|
||||||
|
logging level auc notice
|
||||||
|
...
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
ctrl
|
||||||
|
bind 127.0.0.1
|
||||||
|
hlr
|
||||||
|
gsup
|
||||||
|
bind ip 127.0.0.1
|
||||||
|
no usse-default
|
||||||
|
usse gw1
|
||||||
|
pattern prefix *110*
|
||||||
|
pattern prefix *181*
|
||||||
|
pattern code *110*
|
||||||
|
pattern code *888#
|
||||||
|
pattern regexp ^*[1-3]{3}*[0-9]+#$
|
||||||
|
pattern regexp ^*[5-7]{3}*[0-9]+#$
|
||||||
|
end
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr-eusse)# no pattern prefix *181*
|
||||||
|
OsmoHLR(config-hlr-eusse)# no pattern code *110*
|
||||||
|
OsmoHLR(config-hlr-eusse)# no pattern regexp ^*[1-3]{3}*[0-9]+#$
|
||||||
|
OsmoHLR(config-hlr-eusse)# show running-config
|
||||||
|
|
||||||
|
Current configuration:
|
||||||
|
!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging filter all 1
|
||||||
|
logging color 1
|
||||||
|
logging print category 1
|
||||||
|
logging print extended-timestamp 1
|
||||||
|
logging print file 1
|
||||||
|
logging level all debug
|
||||||
|
logging level main notice
|
||||||
|
logging level db notice
|
||||||
|
logging level auc notice
|
||||||
|
...
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
ctrl
|
||||||
|
bind 127.0.0.1
|
||||||
|
hlr
|
||||||
|
gsup
|
||||||
|
bind ip 127.0.0.1
|
||||||
|
no usse-default
|
||||||
|
usse gw1
|
||||||
|
pattern prefix *110*
|
||||||
|
pattern code *888#
|
||||||
|
pattern regexp ^*[5-7]{3}*[0-9]+#$
|
||||||
|
end
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr-eusse)# exit
|
||||||
|
OsmoHLR(config-hlr)# usse internal
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr-iusse)# pattern code *#100#
|
||||||
|
% Command incomplete.
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr-iusse)# pattern code *#100# response Your extension is %m
|
||||||
|
OsmoHLR(config-hlr-iusse)# pattern regexp ^*999*[0-3]+#$ response Mahlzeit!
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr-iusse)# no pattern code *888#
|
||||||
|
% Cannot remove non-existent pattern '*888#' of type 'code'
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr-iusse)# show running-config
|
||||||
|
|
||||||
|
Current configuration:
|
||||||
|
!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging filter all 1
|
||||||
|
logging color 1
|
||||||
|
logging print category 1
|
||||||
|
logging print extended-timestamp 1
|
||||||
|
logging print file 1
|
||||||
|
logging level all debug
|
||||||
|
logging level main notice
|
||||||
|
logging level db notice
|
||||||
|
logging level auc notice
|
||||||
|
...
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
ctrl
|
||||||
|
bind 127.0.0.1
|
||||||
|
hlr
|
||||||
|
gsup
|
||||||
|
bind ip 127.0.0.1
|
||||||
|
no usse-default
|
||||||
|
usse gw1
|
||||||
|
pattern prefix *110*
|
||||||
|
pattern code *888#
|
||||||
|
pattern regexp ^*[5-7]{3}*[0-9]+#$
|
||||||
|
usse internal
|
||||||
|
pattern code *#100# response Your extension is %m
|
||||||
|
pattern regexp ^*999*[0-3]+#$ response Mahlzeit!
|
||||||
|
end
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr-iusse)# exit
|
||||||
|
OsmoHLR(config-hlr)# usse-default test
|
||||||
|
% Cannot find USSE 'test'
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr)# usse-default internal
|
||||||
|
OsmoHLR(config-hlr)# usse-default gw1
|
||||||
|
OsmoHLR(config-hlr)# show running-config
|
||||||
|
|
||||||
|
Current configuration:
|
||||||
|
!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging filter all 1
|
||||||
|
logging color 1
|
||||||
|
logging print category 1
|
||||||
|
logging print extended-timestamp 1
|
||||||
|
logging print file 1
|
||||||
|
logging level all debug
|
||||||
|
logging level main notice
|
||||||
|
logging level db notice
|
||||||
|
logging level auc notice
|
||||||
|
...
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
ctrl
|
||||||
|
bind 127.0.0.1
|
||||||
|
hlr
|
||||||
|
gsup
|
||||||
|
bind ip 127.0.0.1
|
||||||
|
usse-default gw1
|
||||||
|
usse gw1
|
||||||
|
pattern prefix *110*
|
||||||
|
pattern code *888#
|
||||||
|
pattern regexp ^*[5-7]{3}*[0-9]+#$
|
||||||
|
usse internal
|
||||||
|
pattern code *#100# response Your extension is %m
|
||||||
|
pattern regexp ^*999*[0-3]+#$ response Mahlzeit!
|
||||||
|
end
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr)# no usse gw1
|
||||||
|
% Cannot remove USSE 'gw1', it is the default route
|
||||||
|
|
||||||
|
OsmoHLR(config-hlr)# no usse-default
|
||||||
|
OsmoHLR(config-hlr)# no usse gw1
|
||||||
|
OsmoHLR(config-hlr)# show running-config
|
||||||
|
|
||||||
|
Current configuration:
|
||||||
|
!
|
||||||
|
!
|
||||||
|
log stderr
|
||||||
|
logging filter all 1
|
||||||
|
logging color 1
|
||||||
|
logging print category 1
|
||||||
|
logging print extended-timestamp 1
|
||||||
|
logging print file 1
|
||||||
|
logging level all debug
|
||||||
|
logging level main notice
|
||||||
|
logging level db notice
|
||||||
|
logging level auc notice
|
||||||
|
...
|
||||||
|
!
|
||||||
|
line vty
|
||||||
|
no login
|
||||||
|
!
|
||||||
|
ctrl
|
||||||
|
bind 127.0.0.1
|
||||||
|
hlr
|
||||||
|
gsup
|
||||||
|
bind ip 127.0.0.1
|
||||||
|
no usse-default
|
||||||
|
usse internal
|
||||||
|
pattern code *#100# response Your extension is %m
|
||||||
|
pattern regexp ^*999*[0-3]+#$ response Mahlzeit!
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user