Compare commits

...

2 Commits

Author SHA1 Message Date
Harald Welte
e6f695e0e6 SS/USSD: implement basic USSE routing configuration for VTY
This change introduces basic Unstructured Supplementary Services
processing Entity (USSE) configuration for VTY by analogy with
ESME and SMPP.

The configuration is done by allocating USSE nodes, so each one
is bound to a particular GSUP-connection, and represents a single
processing entity. Then, one or more USSD-code matching patterns
(e.g. code, prefix, regexp) can be assigned to a particular USSE
node, so all matched USSD-requests will be handled by this node.

Among all other USSE nodes, which are basically External USSEs,
there is a special one called IUSSE - internal USSD handler.
It can be optionally configured to handle and answer simple
requests, like *#100#.

Also, it's possible to set the default USSE, which will handle
all USSD-requests unmatched by other USSEs. Otherwise,
unmatched requests are being rejected.

Change-Id: I3cfd7cd401ea32b7e92f1124d129099d9f7dc6e6
2018-07-29 23:17:59 +07:00
Harald Welte
35d2342850 Store identity of VLR/SGSN in UpdateLocation
The HLR must store the least-recently used VLR and SGSN identities in
its database to ensure subsequent mobile-terminated transactions can
be routed accordingly.

Change-Id: Ib2611421f3638eadc361787af801fffe9a34bd8a
Closes: OS#2796
2018-07-06 06:50:23 +07:00
10 changed files with 782 additions and 1 deletions

View File

@@ -30,6 +30,7 @@ noinst_HEADERS = \
ctrl.h \
hlr_vty.h \
hlr_vty_subscr.h \
hlr_ss_ussd.h \
db_bootstrap.h \
$(NULL)
@@ -53,6 +54,7 @@ osmo_hlr_SOURCES = \
hlr_vty.c \
hlr_vty_subscr.c \
gsup_send.c \
hlr_ss_ussd.c \
$(NULL)
osmo_hlr_LDADD = \

View File

@@ -42,6 +42,7 @@
#include "rand.h"
#include "luop.h"
#include "hlr_vty.h"
#include "hlr_ss_ussd.h"
static struct hlr *g_hlr;
@@ -296,10 +297,19 @@ static int rx_upd_loc_req(struct osmo_gsup_conn *conn,
} else
#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: Update RoutingInfo */
/* TODO: Reset Flag MS Purged (cs/ps) */
/* 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);
}
return 0;
@@ -524,6 +534,7 @@ static void signal_hdlr(int signal)
case SIGINT:
LOGP(DMAIN, LOGL_NOTICE, "Terminating due to SIGINT\n");
osmo_gsup_server_destroy(g_hlr->gs);
hlr_usse_clean_up(g_hlr);
db_close(g_hlr->dbc);
log_fini();
talloc_report_full(hlr_ctx, stderr);
@@ -560,6 +571,9 @@ int main(int argc, char **argv)
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);
if (rc < 0) {
fprintf(stderr, "Error initializing logging\n");

View File

@@ -23,6 +23,9 @@
#pragma once
#include <stdbool.h>
#include <osmocom/core/linuxlist.h>
struct hlr_usse;
struct hlr {
/* GSUP server pointer */
@@ -37,6 +40,10 @@ struct hlr {
/* Local bind addr */
char *gsup_bind_addr;
/* SS/USSD processing entities */
struct llist_head usse_list;
struct hlr_usse *usse_default;
};
struct hlr_subscriber;

129
src/hlr_ss_ussd.c Normal file
View 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
View 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);

View File

@@ -3,6 +3,7 @@
/* (C) 2016 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
* Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
* (C) 2018 Harald Welte <laforge@gnumonks.org>
* (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com>
*
* All Rights Reserved
*
@@ -29,6 +30,7 @@
#include <osmocom/abis/ipa.h>
#include "hlr_vty.h"
#include "hlr_ss_ussd.h"
#include "hlr_vty_subscr.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,
"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_conn *conn;
@@ -119,12 +121,290 @@ DEFUN(cfg_hlr_gsup_bind_ip,
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)
{
switch (vty->node) {
case GSUP_NODE:
case IUSSE_NODE:
case EUSSE_NODE:
vty->node = HLR_NODE;
vty->index = NULL;
vty->index_sub = NULL;
break;
default:
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(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);
}

View File

@@ -30,6 +30,8 @@
enum hlr_vty_node {
HLR_NODE = _LAST_OSMOVTY_NODE + 1,
GSUP_NODE,
IUSSE_NODE,
EUSSE_NODE,
};
int hlr_vty_is_config_node(struct vty *vty, int node);

View File

@@ -31,6 +31,7 @@ EXTRA_DIST = \
test_subscriber.vty \
test_subscriber.sql \
test_subscriber.ctrl \
test_sse.vty \
$(NULL)
TESTSUITE = $(srcdir)/testsuite

View File

@@ -70,6 +70,10 @@ OsmoHLR(config-hlr)# list
exit
end
gsup
usse (internal|NAME)
no usse (internal|NAME)
usse-default (internal|NAME)
no usse-default
OsmoHLR(config-hlr)# gsup
OsmoHLR(config-hlr-gsup)# list
@@ -85,6 +89,39 @@ OsmoHLR(config-hlr-gsup)# list
bind ip A.B.C.D
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)# exit
OsmoHLR# configure terminal
@@ -119,4 +156,5 @@ ctrl
hlr
gsup
bind ip 127.0.0.1
no usse-default
end

246
tests/test_usse.vty Normal file
View 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