mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr.git
synced 2025-11-02 13:13:29 +00:00
Compare commits
16 Commits
neels/sms-
...
36c3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f8f1b9777 | ||
|
|
a5ed663dea | ||
|
|
15031855bf | ||
|
|
83b909e4f3 | ||
|
|
fde8f64d1d | ||
|
|
d8e8a8425a | ||
|
|
c1d56fd2e9 | ||
|
|
6ac66ac3ad | ||
|
|
769a7f46f4 | ||
|
|
5bc457e19a | ||
|
|
e3c788d9a8 | ||
|
|
e6751dd207 | ||
|
|
e8b7b8634b | ||
|
|
ce172efc0b | ||
|
|
2f1049827b | ||
|
|
92d1c4a0de |
@@ -5,7 +5,7 @@ Documentation=https://osmocom.org/projects/osmo-hlr/wiki/OsmoHLR
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
ExecStart=/usr/bin/osmo-hlr -c /etc/osmocom/osmo-hlr.cfg -l /var/lib/osmocom/hlr.db
|
||||
ExecStart=/usr/bin/osmo-hlr -U -c /etc/osmocom/osmo-hlr.cfg -l /var/lib/osmocom/hlr.db
|
||||
RestartSec=2
|
||||
|
||||
[Install]
|
||||
|
||||
@@ -24,3 +24,10 @@ hlr
|
||||
bind ip 127.0.0.1
|
||||
ussd route prefix *#100# internal own-msisdn
|
||||
ussd route prefix *#101# internal own-imsi
|
||||
ussd route prefix *#102# internal get-ran
|
||||
ussd route prefix *#200# internal gsm-off
|
||||
ussd route prefix *#201# internal gsm-on
|
||||
ussd route prefix *#300# internal umts-off
|
||||
ussd route prefix *#301# internal umts-on
|
||||
ussd route prefix *#400# internal lte-off
|
||||
ussd route prefix *#401# internal lte-on
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <osmocom/gsupclient/gsup_peer_id.h>
|
||||
#include <osmocom/gsm/gsup.h>
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
|
||||
struct hlr;
|
||||
|
||||
@@ -37,6 +38,8 @@ enum stmt_idx {
|
||||
DB_STMT_IND_ADD,
|
||||
DB_STMT_IND_SELECT,
|
||||
DB_STMT_IND_DEL,
|
||||
DB_STMT_UPD_RAT_FLAG,
|
||||
DB_STMT_RAT_BY_ID,
|
||||
_NUM_DB_STMT
|
||||
};
|
||||
|
||||
@@ -104,11 +107,18 @@ struct hlr_subscriber {
|
||||
bool ms_purged_ps;
|
||||
time_t last_lu_seen;
|
||||
time_t last_lu_seen_ps;
|
||||
char last_lu_rat_cs[128];
|
||||
char last_lu_rat_ps[128];
|
||||
/* talloc'd IPA unit name */
|
||||
struct osmo_ipa_name vlr_via_proxy;
|
||||
struct osmo_ipa_name sgsn_via_proxy;
|
||||
bool rat_types[OSMO_RAT_COUNT];
|
||||
};
|
||||
|
||||
static const struct hlr_subscriber hlr_subscriber_empty = {
|
||||
.rat_types = { true, true, true },
|
||||
};
|
||||
|
||||
/* A format string for use with strptime(3). This format string is
|
||||
* used to parse the last_lu_seen column stored in the HLR database.
|
||||
* See https://sqlite.org/lang_datefunc.html, function datetime(). */
|
||||
@@ -162,7 +172,8 @@ int db_subscr_get_by_imei(struct db_context *dbc, const char *imei, struct hlr_s
|
||||
int db_subscr_nam(struct db_context *dbc, const char *imsi, bool nam_val, bool is_ps);
|
||||
int db_subscr_lu(struct db_context *dbc, int64_t subscr_id,
|
||||
const struct osmo_ipa_name *vlr_name, bool is_ps,
|
||||
const struct osmo_ipa_name *via_proxy);
|
||||
const struct osmo_ipa_name *via_proxy,
|
||||
const enum osmo_rat_type rat_types[], size_t rat_types_len);
|
||||
|
||||
int db_subscr_purge(struct db_context *dbc, const char *by_imsi,
|
||||
bool purge_val, bool is_ps);
|
||||
@@ -170,6 +181,10 @@ int db_subscr_purge(struct db_context *dbc, const char *by_imsi,
|
||||
int db_ind(struct db_context *dbc, const struct osmo_gsup_peer_id *vlr, unsigned int *ind);
|
||||
int db_ind_del(struct db_context *dbc, const struct osmo_gsup_peer_id *vlr);
|
||||
|
||||
int db_subscr_set_rat_type_flag(struct db_context *dbc, int64_t subscr_id, enum osmo_rat_type rat, bool allowed);
|
||||
int db_subscr_get_rat_types(struct db_context *dbc, struct hlr_subscriber *subscr);
|
||||
int hlr_subscr_rat_flag(struct hlr *hlr, struct hlr_subscriber *subscr, enum osmo_rat_type rat, bool allowed);
|
||||
|
||||
/*! Call sqlite3_column_text() and copy result to a char[].
|
||||
* \param[out] buf A char[] used as sizeof() arg(!) and osmo_strlcpy() target.
|
||||
* \param[in] stmt An sqlite3_stmt*.
|
||||
|
||||
18
sql/hlr.sql
18
sql/hlr.sql
@@ -45,6 +45,12 @@ CREATE TABLE subscriber (
|
||||
last_lu_seen TIMESTAMP default NULL,
|
||||
last_lu_seen_ps TIMESTAMP default NULL,
|
||||
|
||||
-- Last Radio Access Type list as sent during Location Updating Request.
|
||||
-- This is usually just one RAT name, but can be a comma separated list of strings
|
||||
-- of all the RAT types sent during Location Updating Request.
|
||||
last_lu_rat_cs TEXT default NULL,
|
||||
last_lu_rat_ps TEXT default NULL,
|
||||
|
||||
-- When a LU was received via a proxy, that proxy's hlr_number is stored here,
|
||||
-- while vlr_number reflects the MSC on the far side of that proxy.
|
||||
vlr_via_proxy VARCHAR,
|
||||
@@ -87,8 +93,18 @@ CREATE TABLE ind (
|
||||
UNIQUE (vlr)
|
||||
);
|
||||
|
||||
-- Optional: add subscriber entries to allow or disallow specific RATs (2G or 3G or ...).
|
||||
-- If a subscriber has no entry, that means that all RATs are allowed (backwards compat).
|
||||
CREATE TABLE subscriber_rat (
|
||||
subscriber_id INTEGER, -- subscriber.id
|
||||
rat TEXT CHECK(rat in ('GERAN-A', 'UTRAN-Iu','EUTRAN-SGs')) NOT NULL, -- Radio Access Technology, see enum ran_type
|
||||
allowed BOOLEAN CHECK(allowed in (0, 1)) NOT NULL DEFAULT 0,
|
||||
UNIQUE (subscriber_id, rat)
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX idx_subscr_imsi ON subscriber (imsi);
|
||||
CREATE UNIQUE INDEX idx_subscr_rat_flag ON subscriber_rat (subscriber_id, rat);
|
||||
|
||||
-- Set HLR database schema version number
|
||||
-- Note: This constant is currently duplicated in src/db.c and must be kept in sync!
|
||||
PRAGMA user_version = 6;
|
||||
PRAGMA user_version = 8;
|
||||
|
||||
8
sql/upgrade_v2_to_v3.sql
Normal file
8
sql/upgrade_v2_to_v3.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
CREATE TABLE subscriber_rat (
|
||||
subscriber_id INTEGER, -- subscriber.id
|
||||
rat TEXT CHECK(rat in ('GERAN-A', 'UTRAN-Iu')) NOT NULL, -- Radio Access Technology, see enum ran_type
|
||||
allowed BOOLEAN NOT NULL DEFAULT 0,
|
||||
);
|
||||
|
||||
PRAGMA user_version = 3;
|
||||
72
src/db.c
72
src/db.c
@@ -30,7 +30,7 @@
|
||||
#include "db_bootstrap.h"
|
||||
|
||||
/* This constant is currently duplicated in sql/hlr.sql and must be kept in sync! */
|
||||
#define CURRENT_SCHEMA_VERSION 6
|
||||
#define CURRENT_SCHEMA_VERSION 8
|
||||
|
||||
#define SEL_COLUMNS \
|
||||
"id," \
|
||||
@@ -49,6 +49,8 @@
|
||||
"ms_purged_ps," \
|
||||
"last_lu_seen," \
|
||||
"last_lu_seen_ps," \
|
||||
"last_lu_rat_cs," \
|
||||
"last_lu_rat_ps," \
|
||||
"vlr_via_proxy," \
|
||||
"sgsn_via_proxy"
|
||||
|
||||
@@ -83,13 +85,23 @@ static const char *stmt_sql[] = {
|
||||
"INSERT INTO auc_3g (subscriber_id, algo_id_3g, k, op, opc, ind_bitlen)"
|
||||
" VALUES($subscriber_id, $algo_id_3g, $k, $op, $opc, $ind_bitlen)",
|
||||
[DB_STMT_AUC_3G_DELETE] = "DELETE FROM auc_3g WHERE subscriber_id = $subscriber_id",
|
||||
[DB_STMT_SET_LAST_LU_SEEN] = "UPDATE subscriber SET last_lu_seen = datetime($val, 'unixepoch') WHERE id = $subscriber_id",
|
||||
[DB_STMT_SET_LAST_LU_SEEN_PS] = "UPDATE subscriber SET last_lu_seen_ps = datetime($val, 'unixepoch') WHERE id = $subscriber_id",
|
||||
[DB_STMT_SET_LAST_LU_SEEN] = "UPDATE subscriber SET last_lu_seen = datetime($val, 'unixepoch'),"
|
||||
" last_lu_rat_cs = $rat"
|
||||
" WHERE id = $subscriber_id",
|
||||
[DB_STMT_SET_LAST_LU_SEEN_PS] = "UPDATE subscriber SET last_lu_seen_ps = datetime($val, 'unixepoch'),"
|
||||
" last_lu_rat_ps = $rat"
|
||||
" WHERE id = $subscriber_id",
|
||||
[DB_STMT_EXISTS_BY_IMSI] = "SELECT 1 FROM subscriber WHERE imsi = $imsi",
|
||||
[DB_STMT_EXISTS_BY_MSISDN] = "SELECT 1 FROM subscriber WHERE msisdn = $msisdn",
|
||||
[DB_STMT_IND_ADD] = "INSERT INTO ind (vlr) VALUES ($vlr)",
|
||||
[DB_STMT_IND_SELECT] = "SELECT ind FROM ind WHERE vlr = $vlr",
|
||||
[DB_STMT_IND_DEL] = "DELETE FROM ind WHERE vlr = $vlr",
|
||||
[DB_STMT_UPD_RAT_FLAG] = "INSERT OR REPLACE INTO subscriber_rat (subscriber_id, rat, allowed)"
|
||||
" VALUES ($subscriber_id, $rat, $allowed)",
|
||||
[DB_STMT_RAT_BY_ID] =
|
||||
"SELECT rat, allowed"
|
||||
" FROM subscriber_rat"
|
||||
" WHERE subscriber_id = $subscriber_id",
|
||||
};
|
||||
|
||||
static void sql3_error_log_cb(void *arg, int err_code, const char *msg)
|
||||
@@ -335,7 +347,7 @@ static int db_upgrade_v3(struct db_context *dbc)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* A newer SQLite version would allow simply 'ATLER TABLE subscriber RENAME COLUMN hlr_number TO msc_number'.
|
||||
/* A newer SQLite version would allow simply 'ALTER TABLE subscriber RENAME COLUMN hlr_number TO msc_number'.
|
||||
* This is a really expensive workaround for that in order to cover earlier SQLite versions as well:
|
||||
* Create a new table with the new column name and copy the data over (https://www.sqlite.org/faq.html#q11).
|
||||
*/
|
||||
@@ -489,12 +501,11 @@ static int db_upgrade_v6(struct db_context *dbc)
|
||||
int rc;
|
||||
const char *statements[] = {
|
||||
"CREATE TABLE ind (\n"
|
||||
" cn_domain INTEGER NOT NULL,\n"
|
||||
" -- 3G auth IND bucket to be used for this VLR, where IND = (idx << 1) + cn_domain -1\n"
|
||||
" -- 3G auth IND pool to be used for this VLR\n"
|
||||
" ind INTEGER PRIMARY KEY,\n"
|
||||
" -- VLR identification, usually the GSUP source_name\n"
|
||||
" vlr TEXT NOT NULL,\n"
|
||||
" UNIQUE (cn_domain, vlr)\n"
|
||||
" UNIQUE (vlr)\n"
|
||||
")"
|
||||
,
|
||||
"PRAGMA user_version = 6",
|
||||
@@ -508,6 +519,47 @@ static int db_upgrade_v6(struct db_context *dbc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int db_upgrade_v7(struct db_context *dbc)
|
||||
{
|
||||
int rc;
|
||||
const char *statements[] = {
|
||||
"-- Optional: add subscriber entries to allow or disallow specific RATs (2G or 3G or ...).\n"
|
||||
"-- If a subscriber has no entry, that means that all RATs are allowed (backwards compat).\n"
|
||||
"CREATE TABLE subscriber_rat (\n"
|
||||
" subscriber_id INTEGER, -- subscriber.id\n"
|
||||
" rat TEXT CHECK(rat in ('GERAN-A', 'UTRAN-Iu')) NOT NULL, -- Radio Access Technology, see enum ran_type\n"
|
||||
" allowed BOOLEAN CHECK(allowed in (0, 1)) NOT NULL DEFAULT 0,\n"
|
||||
" UNIQUE (subscriber_id, rat)\n"
|
||||
")",
|
||||
"CREATE UNIQUE INDEX idx_subscr_rat_flag ON subscriber_rat (subscriber_id, rat)",
|
||||
"PRAGMA user_version = 7",
|
||||
};
|
||||
|
||||
rc = db_run_statements(dbc, statements, ARRAY_SIZE(statements));
|
||||
if (rc != SQLITE_DONE) {
|
||||
LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 7\n");
|
||||
return rc;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int db_upgrade_v8(struct db_context *dbc)
|
||||
{
|
||||
int rc;
|
||||
const char *statements[] = {
|
||||
"ALTER TABLE subscriber ADD COLUMN last_lu_rat_cs TEXT default NULL",
|
||||
"ALTER TABLE subscriber ADD COLUMN last_lu_rat_ps TEXT default NULL",
|
||||
"PRAGMA user_version = 8",
|
||||
};
|
||||
|
||||
rc = db_run_statements(dbc, statements, ARRAY_SIZE(statements));
|
||||
if (rc != SQLITE_DONE) {
|
||||
LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 7\n");
|
||||
return rc;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
typedef int (*db_upgrade_func_t)(struct db_context *dbc);
|
||||
static db_upgrade_func_t db_upgrade_path[] = {
|
||||
db_upgrade_v1,
|
||||
@@ -516,6 +568,8 @@ static db_upgrade_func_t db_upgrade_path[] = {
|
||||
db_upgrade_v4,
|
||||
db_upgrade_v5,
|
||||
db_upgrade_v6,
|
||||
db_upgrade_v7,
|
||||
db_upgrade_v8,
|
||||
};
|
||||
|
||||
static int db_get_user_version(struct db_context *dbc)
|
||||
@@ -644,9 +698,9 @@ struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite_logg
|
||||
if (version < CURRENT_SCHEMA_VERSION) {
|
||||
LOGP(DDB, LOGL_NOTICE, "HLR DB schema version %d is outdated\n", version);
|
||||
if (!allow_upgrade) {
|
||||
LOGP(DDB, LOGL_ERROR, "Not upgrading HLR database to schema version %d; "
|
||||
LOGP(DDB, LOGL_ERROR, "Not upgrading HLR database from schema version %d to %d; "
|
||||
"use the --db-upgrade option to allow HLR database upgrades\n",
|
||||
CURRENT_SCHEMA_VERSION);
|
||||
version, CURRENT_SCHEMA_VERSION);
|
||||
}
|
||||
} else
|
||||
LOGP(DDB, LOGL_ERROR, "HLR DB schema version %d is unknown\n", version);
|
||||
|
||||
147
src/db_hlr.c
147
src/db_hlr.c
@@ -483,7 +483,7 @@ static int db_sel(struct db_context *dbc, sqlite3_stmt *stmt, struct hlr_subscri
|
||||
if (!subscr)
|
||||
goto out;
|
||||
|
||||
*subscr = (struct hlr_subscriber){};
|
||||
*subscr = hlr_subscriber_empty;
|
||||
|
||||
/* obtain the various columns */
|
||||
subscr->id = sqlite3_column_int64(stmt, 0);
|
||||
@@ -505,12 +505,17 @@ static int db_sel(struct db_context *dbc, sqlite3_stmt *stmt, struct hlr_subscri
|
||||
subscr->imsi, "CS");
|
||||
parse_last_lu_seen(&subscr->last_lu_seen_ps, (const char *)sqlite3_column_text(stmt, 15),
|
||||
subscr->imsi, "PS");
|
||||
copy_sqlite3_text_to_ipa_name(&subscr->vlr_via_proxy, stmt, 16);
|
||||
copy_sqlite3_text_to_ipa_name(&subscr->sgsn_via_proxy, stmt, 17);
|
||||
copy_sqlite3_text_to_buf(subscr->last_lu_rat_cs, stmt, 16);
|
||||
copy_sqlite3_text_to_buf(subscr->last_lu_rat_ps, stmt, 17);
|
||||
copy_sqlite3_text_to_ipa_name(&subscr->vlr_via_proxy, stmt, 18);
|
||||
copy_sqlite3_text_to_ipa_name(&subscr->sgsn_via_proxy, stmt, 19);
|
||||
|
||||
out:
|
||||
db_remove_reset(stmt);
|
||||
|
||||
if (ret == 0)
|
||||
db_subscr_get_rat_types(dbc, subscr);
|
||||
|
||||
switch (ret) {
|
||||
case 0:
|
||||
*err = NULL;
|
||||
@@ -737,11 +742,14 @@ out:
|
||||
*/
|
||||
int db_subscr_lu(struct db_context *dbc, int64_t subscr_id,
|
||||
const struct osmo_ipa_name *vlr_name, bool is_ps,
|
||||
const struct osmo_ipa_name *via_proxy)
|
||||
const struct osmo_ipa_name *via_proxy,
|
||||
const enum osmo_rat_type rat_types[], size_t rat_types_len)
|
||||
{
|
||||
sqlite3_stmt *stmt;
|
||||
int rc, ret = 0;
|
||||
struct timespec localtime;
|
||||
char rat_types_str[128] = "";
|
||||
int i;
|
||||
|
||||
stmt = dbc->stmt[is_ps ? DB_STMT_UPD_SGSN_BY_ID
|
||||
: DB_STMT_UPD_VLR_BY_ID];
|
||||
@@ -803,6 +811,21 @@ int db_subscr_lu(struct db_context *dbc, int64_t subscr_id,
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < rat_types_len; i++) {
|
||||
char *pos = rat_types_str + strnlen(rat_types_str, sizeof(rat_types_str));
|
||||
int len = sizeof(rat_types_str) - (pos - rat_types_str);
|
||||
rc = snprintf(pos, len, "%s%s", pos == rat_types_str ? "" : ",", osmo_rat_type_name(rat_types[i]));
|
||||
if (rc > len) {
|
||||
osmo_strlcpy(rat_types_str + sizeof(rat_types_str) - 4, "...", 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!db_bind_text(stmt, "$rat", rat_types_str)) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = sqlite3_step(stmt);
|
||||
if (rc != SQLITE_DONE) {
|
||||
LOGP(DAUC, LOGL_ERROR,
|
||||
@@ -987,3 +1010,119 @@ int db_ind_del(struct db_context *dbc, const struct osmo_gsup_peer_id *vlr)
|
||||
{
|
||||
return _db_ind(dbc, vlr, NULL, true);
|
||||
}
|
||||
|
||||
int db_subscr_set_rat_type_flag(struct db_context *dbc, int64_t subscr_id, enum osmo_rat_type rat, bool allowed)
|
||||
{
|
||||
int rc;
|
||||
int ret = 0;
|
||||
sqlite3_stmt *stmt = dbc->stmt[DB_STMT_UPD_RAT_FLAG];
|
||||
|
||||
if (!db_bind_int64(stmt, "$subscriber_id", subscr_id))
|
||||
return -EIO;
|
||||
|
||||
OSMO_ASSERT(rat >= 0 && rat < OSMO_RAT_COUNT);
|
||||
if (!db_bind_text(stmt, "$rat", osmo_rat_type_name(rat)))
|
||||
return -EIO;
|
||||
|
||||
if (!db_bind_int(stmt, "$allowed", allowed ? 1 : 0))
|
||||
return -EIO;
|
||||
|
||||
/* execute the statement */
|
||||
rc = sqlite3_step(stmt);
|
||||
if (rc != SQLITE_DONE) {
|
||||
LOGP(DDB, LOGL_ERROR, "%s %s: SQL error: %s\n",
|
||||
allowed ? "enable" : "disable", osmo_rat_type_name(rat),
|
||||
sqlite3_errmsg(dbc->db));
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* verify execution result */
|
||||
rc = sqlite3_changes(dbc->db);
|
||||
if (!rc) {
|
||||
LOGP(DDB, LOGL_ERROR, "Cannot %s %s: no such subscriber: ID=%" PRIu64 "\n",
|
||||
allowed ? "enable" : "disable", osmo_rat_type_name(rat),
|
||||
subscr_id);
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
} else if (rc != 1) {
|
||||
LOGP(DDB, LOGL_ERROR, "%s %s: SQL modified %d rows (expected 1)\n",
|
||||
allowed ? "enable" : "disable", osmo_rat_type_name(rat),
|
||||
rc);
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
out:
|
||||
db_remove_reset(stmt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int db_subscr_get_rat_types(struct db_context *dbc, struct hlr_subscriber *subscr)
|
||||
{
|
||||
int rc;
|
||||
int ret = 0;
|
||||
int i;
|
||||
sqlite3_stmt *stmt = dbc->stmt[DB_STMT_RAT_BY_ID];
|
||||
|
||||
if (!db_bind_int64(stmt, "$subscriber_id", subscr->id))
|
||||
return -EIO;
|
||||
|
||||
for (i = 0; i < OSMO_RAT_COUNT; i++)
|
||||
subscr->rat_types[i] = true;
|
||||
|
||||
/* execute the statement */
|
||||
while (1) {
|
||||
enum osmo_rat_type rat;
|
||||
bool allowed;
|
||||
|
||||
rc = sqlite3_step(stmt);
|
||||
|
||||
if (rc == SQLITE_DONE)
|
||||
break;
|
||||
if (rc != SQLITE_ROW)
|
||||
return -rc;
|
||||
|
||||
rc = get_string_value(osmo_rat_type_names, (const char*)sqlite3_column_text(stmt, 0));
|
||||
if (rc == -EINVAL) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (rc <= 0 || rc >= OSMO_RAT_COUNT) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
rat = rc;
|
||||
|
||||
allowed = sqlite3_column_int(stmt, 1);
|
||||
|
||||
subscr->rat_types[rat] = allowed;
|
||||
LOGP(DAUC, LOGL_DEBUG, "db: imsi='%s' %s %s\n",
|
||||
subscr->imsi, osmo_rat_type_name(rat), allowed ? "allowed" : "forbidden");
|
||||
}
|
||||
|
||||
out:
|
||||
db_remove_reset(stmt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hlr_subscr_rat_flag(struct hlr *hlr, struct hlr_subscriber *subscr, enum osmo_rat_type rat, bool allowed)
|
||||
{
|
||||
int rc;
|
||||
OSMO_ASSERT(rat >= 0 && rat < OSMO_RAT_COUNT);
|
||||
|
||||
db_subscr_get_rat_types(hlr->dbc, subscr);
|
||||
|
||||
if (subscr->rat_types[rat] == allowed) {
|
||||
LOGHLR(subscr->imsi, LOGL_DEBUG, "Already has the requested value when asked to %s %s\n",
|
||||
allowed ? "enable" : "disable", osmo_rat_type_name(rat));
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
rc = db_subscr_set_rat_type_flag(hlr->dbc, subscr->id, rat, allowed);
|
||||
if (rc)
|
||||
return rc > 0? -rc : rc;
|
||||
|
||||
/* FIXME: If we're disabling, send message to VLR to detach subscriber */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ static int rx_send_auth_info(struct osmo_gsup_req *req)
|
||||
" Returning slightly inaccurate cause 'IMSI Unknown' via GSUP");
|
||||
return rc;
|
||||
case -ENOENT:
|
||||
osmo_gsup_req_respond_err(req, GMM_CAUSE_IMSI_UNKNOWN, "IMSI unknown");
|
||||
osmo_gsup_req_respond_err(req, GMM_CAUSE_ROAMING_NOTALLOWED, "IMSI unknown");
|
||||
return rc;
|
||||
default:
|
||||
osmo_gsup_req_respond_err(req, GMM_CAUSE_NET_FAIL, "failure to look up IMSI in db");
|
||||
@@ -372,7 +372,7 @@ static int rx_purge_ms_req(struct osmo_gsup_req *req)
|
||||
if (rc == 0)
|
||||
osmo_gsup_req_respond_msgt(req, OSMO_GSUP_MSGT_PURGE_MS_RESULT, true);
|
||||
else if (rc == -ENOENT)
|
||||
osmo_gsup_req_respond_err(req, GMM_CAUSE_IMSI_UNKNOWN, "IMSI unknown");
|
||||
osmo_gsup_req_respond_err(req, GMM_CAUSE_ROAMING_NOTALLOWED, "IMSI unknown");
|
||||
else
|
||||
osmo_gsup_req_respond_err(req, GMM_CAUSE_NET_FAIL, "db error");
|
||||
return rc;
|
||||
|
||||
228
src/hlr_ussd.c
228
src/hlr_ussd.c
@@ -373,6 +373,206 @@ static int handle_ussd_own_imsi(struct ss_session *ss,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_ussd_get_ran(struct ss_session *ss,
|
||||
const struct osmo_gsup_message *gsup,
|
||||
const struct ss_request *req)
|
||||
{
|
||||
struct hlr_subscriber subscr;
|
||||
char response[512];
|
||||
int rc;
|
||||
const char *rat;
|
||||
|
||||
rc = db_subscr_get_by_imsi(g_hlr->dbc, ss->imsi, &subscr);
|
||||
switch (rc) {
|
||||
case 0:
|
||||
if (!*subscr.last_lu_rat_cs)
|
||||
rat = "nothing, you don't exist";
|
||||
else if (!strcmp(subscr.last_lu_rat_cs, "GERAN-A"))
|
||||
rat = "2G";
|
||||
else if (!strcmp(subscr.last_lu_rat_cs, "UTRAN-Iu"))
|
||||
rat = "3G";
|
||||
else if (!strcmp(subscr.last_lu_rat_cs, "EUTRAN-SGs"))
|
||||
rat = "4G";
|
||||
else
|
||||
rat = subscr.last_lu_rat_cs;
|
||||
|
||||
snprintf(response, sizeof(response),
|
||||
"Now on %s. Available:%s%s%s.",
|
||||
rat,
|
||||
subscr.rat_types[OSMO_RAT_GERAN_A]? " 2G" : "",
|
||||
subscr.rat_types[OSMO_RAT_UTRAN_IU]? " 3G" : "",
|
||||
subscr.rat_types[OSMO_RAT_EUTRAN_SGS]? " 4G" : "");
|
||||
|
||||
rc = ss_tx_to_ms_ussd_7bit(ss, true, req->invoke_id, response);
|
||||
break;
|
||||
case -ENOENT:
|
||||
rc = ss_tx_to_ms_error(ss, true, GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER);
|
||||
break;
|
||||
case -EIO:
|
||||
default:
|
||||
rc = ss_tx_to_ms_error(ss, true, GSM0480_ERR_CODE_SYSTEM_FAILURE);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int handle_ussd_gsm_on(struct ss_session *ss,
|
||||
const struct osmo_gsup_message *gsup,
|
||||
const struct ss_request *req)
|
||||
{
|
||||
struct hlr_subscriber subscr;
|
||||
int rc;
|
||||
|
||||
rc = db_subscr_get_by_imsi(g_hlr->dbc, ss->imsi, &subscr);
|
||||
switch (rc) {
|
||||
case 0:
|
||||
hlr_subscr_rat_flag(g_hlr, &subscr, OSMO_RAT_GERAN_A, true);
|
||||
rc = ss_tx_to_ms_ussd_7bit(ss, true, req->invoke_id,
|
||||
"Enabled GERAN-A (2G)");
|
||||
break;
|
||||
case -ENOENT:
|
||||
rc = ss_tx_to_ms_error(ss, true, GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER);
|
||||
break;
|
||||
case -EIO:
|
||||
default:
|
||||
rc = ss_tx_to_ms_error(ss, true, GSM0480_ERR_CODE_SYSTEM_FAILURE);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int handle_ussd_gsm_off(struct ss_session *ss,
|
||||
const struct osmo_gsup_message *gsup,
|
||||
const struct ss_request *req)
|
||||
{
|
||||
struct hlr_subscriber subscr;
|
||||
int rc;
|
||||
|
||||
rc = db_subscr_get_by_imsi(g_hlr->dbc, ss->imsi, &subscr);
|
||||
switch (rc) {
|
||||
case 0:
|
||||
hlr_subscr_rat_flag(g_hlr, &subscr, OSMO_RAT_GERAN_A, false);
|
||||
rc = ss_tx_to_ms_ussd_7bit(ss, true, req->invoke_id,
|
||||
"Disabled GERAN-A (2G)");
|
||||
break;
|
||||
case -ENOENT:
|
||||
rc = ss_tx_to_ms_error(ss, true, GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER);
|
||||
break;
|
||||
case -EIO:
|
||||
default:
|
||||
rc = ss_tx_to_ms_error(ss, true, GSM0480_ERR_CODE_SYSTEM_FAILURE);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int handle_ussd_umts_on(struct ss_session *ss,
|
||||
const struct osmo_gsup_message *gsup,
|
||||
const struct ss_request *req)
|
||||
{
|
||||
struct hlr_subscriber subscr;
|
||||
int rc;
|
||||
|
||||
rc = db_subscr_get_by_imsi(g_hlr->dbc, ss->imsi, &subscr);
|
||||
switch (rc) {
|
||||
case 0:
|
||||
hlr_subscr_rat_flag(g_hlr, &subscr, OSMO_RAT_UTRAN_IU, true);
|
||||
rc = ss_tx_to_ms_ussd_7bit(ss, true, req->invoke_id,
|
||||
"Enabled UTRAN-Iu (3G)");
|
||||
break;
|
||||
case -ENOENT:
|
||||
rc = ss_tx_to_ms_error(ss, true, GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER);
|
||||
break;
|
||||
case -EIO:
|
||||
default:
|
||||
rc = ss_tx_to_ms_error(ss, true, GSM0480_ERR_CODE_SYSTEM_FAILURE);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int handle_ussd_umts_off(struct ss_session *ss,
|
||||
const struct osmo_gsup_message *gsup,
|
||||
const struct ss_request *req)
|
||||
{
|
||||
struct hlr_subscriber subscr;
|
||||
int rc;
|
||||
|
||||
rc = db_subscr_get_by_imsi(g_hlr->dbc, ss->imsi, &subscr);
|
||||
switch (rc) {
|
||||
case 0:
|
||||
hlr_subscr_rat_flag(g_hlr, &subscr, OSMO_RAT_UTRAN_IU, false);
|
||||
rc = ss_tx_to_ms_ussd_7bit(ss, true, req->invoke_id,
|
||||
"Disabled UTRAN-Iu (3G)");
|
||||
break;
|
||||
case -ENOENT:
|
||||
rc = ss_tx_to_ms_error(ss, true, GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER);
|
||||
break;
|
||||
case -EIO:
|
||||
default:
|
||||
rc = ss_tx_to_ms_error(ss, true, GSM0480_ERR_CODE_SYSTEM_FAILURE);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int handle_ussd_lte_on(struct ss_session *ss,
|
||||
const struct osmo_gsup_message *gsup,
|
||||
const struct ss_request *req)
|
||||
{
|
||||
struct hlr_subscriber subscr;
|
||||
int rc;
|
||||
|
||||
rc = db_subscr_get_by_imsi(g_hlr->dbc, ss->imsi, &subscr);
|
||||
switch (rc) {
|
||||
case 0:
|
||||
hlr_subscr_rat_flag(g_hlr, &subscr, OSMO_RAT_EUTRAN_SGS, true);
|
||||
rc = ss_tx_to_ms_ussd_7bit(ss, true, req->invoke_id,
|
||||
"Enabled EUTRAN-SGs (4G)");
|
||||
break;
|
||||
case -ENOENT:
|
||||
rc = ss_tx_to_ms_error(ss, true, GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER);
|
||||
break;
|
||||
case -EIO:
|
||||
default:
|
||||
rc = ss_tx_to_ms_error(ss, true, GSM0480_ERR_CODE_SYSTEM_FAILURE);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int handle_ussd_lte_off(struct ss_session *ss,
|
||||
const struct osmo_gsup_message *gsup,
|
||||
const struct ss_request *req)
|
||||
{
|
||||
struct hlr_subscriber subscr;
|
||||
int rc;
|
||||
|
||||
rc = db_subscr_get_by_imsi(g_hlr->dbc, ss->imsi, &subscr);
|
||||
switch (rc) {
|
||||
case 0:
|
||||
hlr_subscr_rat_flag(g_hlr, &subscr, OSMO_RAT_EUTRAN_SGS, false);
|
||||
rc = ss_tx_to_ms_ussd_7bit(ss, true, req->invoke_id,
|
||||
"Disabled EUTRAN-SGs (4G)");
|
||||
break;
|
||||
case -ENOENT:
|
||||
rc = ss_tx_to_ms_error(ss, true, GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER);
|
||||
break;
|
||||
case -EIO:
|
||||
default:
|
||||
rc = ss_tx_to_ms_error(ss, true, GSM0480_ERR_CODE_SYSTEM_FAILURE);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static const struct hlr_iuse hlr_iuses[] = {
|
||||
{
|
||||
@@ -383,6 +583,34 @@ static const struct hlr_iuse hlr_iuses[] = {
|
||||
.name = "own-imsi",
|
||||
.handle_ussd = handle_ussd_own_imsi,
|
||||
},
|
||||
{
|
||||
.name = "get-ran",
|
||||
.handle_ussd = handle_ussd_get_ran,
|
||||
},
|
||||
{
|
||||
.name = "gsm-on",
|
||||
.handle_ussd = handle_ussd_gsm_on,
|
||||
},
|
||||
{
|
||||
.name = "gsm-off",
|
||||
.handle_ussd = handle_ussd_gsm_off,
|
||||
},
|
||||
{
|
||||
.name = "umts-on",
|
||||
.handle_ussd = handle_ussd_umts_on,
|
||||
},
|
||||
{
|
||||
.name = "umts-off",
|
||||
.handle_ussd = handle_ussd_umts_off,
|
||||
},
|
||||
{
|
||||
.name = "lte-on",
|
||||
.handle_ussd = handle_ussd_lte_on,
|
||||
},
|
||||
{
|
||||
.name = "lte-off",
|
||||
.handle_ussd = handle_ussd_lte_off,
|
||||
},
|
||||
};
|
||||
|
||||
const struct hlr_iuse *iuse_find(const char *name)
|
||||
|
||||
@@ -174,10 +174,17 @@ DEFUN(cfg_hlr_gsup_ipa_name,
|
||||
#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_CHOICE "(own-msisdn|own-imsi|get-ran|gsm-on|gsm-off|umts-on|umts-off|lte-on|lte-off)"
|
||||
#define INT_STR "Internal USSD Handler\n" \
|
||||
"Respond with subscribers' own MSISDN\n" \
|
||||
"Respond with subscribers' own IMSI\n"
|
||||
"Respond with subscribers' own IMSI\n" \
|
||||
"Respond with available RAN types\n" \
|
||||
"Enable GSM service\n" \
|
||||
"Disable GSM service\n" \
|
||||
"Enable UMTS service\n" \
|
||||
"Disable UMTS service\n" \
|
||||
"Enable LTE service\n" \
|
||||
"Disable LTE service\n"
|
||||
|
||||
#define EXT_STR "External USSD Handler\n" \
|
||||
"Name of External USSD Handler (IPA CCM ID)\n"
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <osmocom/vty/vty.h>
|
||||
#include <osmocom/vty/command.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
|
||||
#include <osmocom/hlr/hlr.h>
|
||||
#include <osmocom/hlr/db.h>
|
||||
@@ -48,7 +49,7 @@ static char *get_datestr(const time_t *t, char *buf, size_t bufsize)
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void dump_last_lu_seen(struct vty *vty, const char *domain_label, time_t last_lu_seen)
|
||||
static void dump_last_lu_seen(struct vty *vty, const char *domain_label, time_t last_lu_seen, const char *last_lu_rat)
|
||||
{
|
||||
uint32_t age;
|
||||
char datebuf[32];
|
||||
@@ -56,7 +57,7 @@ static void dump_last_lu_seen(struct vty *vty, const char *domain_label, time_t
|
||||
return;
|
||||
vty_out(vty, " last LU seen on %s: %s", domain_label, get_datestr(&last_lu_seen, datebuf, sizeof(datebuf)));
|
||||
if (!timestamp_age(&last_lu_seen, &age))
|
||||
vty_out(vty, " (invalid timestamp)%s", VTY_NEWLINE);
|
||||
vty_out(vty, " (invalid timestamp)");
|
||||
else {
|
||||
vty_out(vty, " (");
|
||||
#define UNIT_AGO(UNITNAME, UNITVAL) \
|
||||
@@ -68,14 +69,18 @@ static void dump_last_lu_seen(struct vty *vty, const char *domain_label, time_t
|
||||
UNIT_AGO("h", 60*60);
|
||||
UNIT_AGO("m", 60);
|
||||
UNIT_AGO("s", 1);
|
||||
vty_out(vty, " ago)%s", VTY_NEWLINE);
|
||||
vty_out(vty, " ago)");
|
||||
#undef UNIT_AGO
|
||||
}
|
||||
if (last_lu_rat && *last_lu_rat != '\0')
|
||||
vty_out(vty, " on %s", last_lu_rat);
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
}
|
||||
|
||||
static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
|
||||
@@ -112,8 +117,12 @@ static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
|
||||
vty_out(vty, " PS disabled%s", VTY_NEWLINE);
|
||||
if (subscr->ms_purged_ps)
|
||||
vty_out(vty, " PS purged%s", VTY_NEWLINE);
|
||||
dump_last_lu_seen(vty, "CS", subscr->last_lu_seen);
|
||||
dump_last_lu_seen(vty, "PS", subscr->last_lu_seen_ps);
|
||||
dump_last_lu_seen(vty, "CS", subscr->last_lu_seen, subscr->last_lu_rat_cs);
|
||||
dump_last_lu_seen(vty, "PS", subscr->last_lu_seen_ps, subscr->last_lu_rat_ps);
|
||||
for (i = OSMO_RAT_UNKNOWN + 1; i < ARRAY_SIZE(subscr->rat_types); i++) {
|
||||
vty_out(vty, " %s: %s%s", osmo_rat_type_name(i), subscr->rat_types[i] ? "allowed" : "forbidden",
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
|
||||
if (!*subscr->imsi)
|
||||
return;
|
||||
@@ -630,6 +639,48 @@ DEFUN(subscriber_nam,
|
||||
}
|
||||
|
||||
|
||||
DEFUN(subscriber_rat,
|
||||
subscriber_rat_cmd,
|
||||
SUBSCR_UPDATE "rat (geran-a|utran-iu|eutran-sgs) (allowed|forbidden)",
|
||||
SUBSCR_UPDATE_HELP
|
||||
"Allow or forbid specific Radio Access Types\n"
|
||||
"Set access to GERAN-A\n"
|
||||
"Set access to UTRAN-Iu\n"
|
||||
"Set access to EUTRAN-SGs\n"
|
||||
"Allow access\n"
|
||||
"Forbid access\n")
|
||||
{
|
||||
struct hlr_subscriber subscr;
|
||||
const char *id_type = argv[0];
|
||||
const char *id = argv[1];
|
||||
const char *rat_str = argv[2];
|
||||
const char *allowed_forbidden = argv[3];
|
||||
enum osmo_rat_type rat = OSMO_RAT_UNKNOWN;
|
||||
bool allowed;
|
||||
int rc;
|
||||
|
||||
if (strcmp(rat_str, "geran-a") == 0)
|
||||
rat = OSMO_RAT_GERAN_A;
|
||||
else if (strcmp(rat_str, "utran-iu") == 0)
|
||||
rat = OSMO_RAT_UTRAN_IU;
|
||||
else if (strcmp(rat_str, "eutran-sgs") == 0)
|
||||
rat = OSMO_RAT_EUTRAN_SGS;
|
||||
|
||||
allowed = (strcmp(allowed_forbidden, "allowed") == 0);
|
||||
|
||||
if (get_subscr_by_argv(vty, id_type, id, &subscr))
|
||||
return CMD_WARNING;
|
||||
|
||||
rc = hlr_subscr_rat_flag(g_hlr, &subscr, rat, allowed);
|
||||
|
||||
if (rc && rc != -ENOEXEC) {
|
||||
vty_out(vty, "%% Error: cannot set %s to %s%s",
|
||||
osmo_rat_type_name(rat), allowed ? "allowed" : "forbidden", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void hlr_vty_subscriber_init(void)
|
||||
{
|
||||
install_element_ve(&subscriber_show_cmd);
|
||||
@@ -643,4 +694,5 @@ void hlr_vty_subscriber_init(void)
|
||||
install_element(ENABLE_NODE, &subscriber_aud3g_cmd);
|
||||
install_element(ENABLE_NODE, &subscriber_imei_cmd);
|
||||
install_element(ENABLE_NODE, &subscriber_nam_cmd);
|
||||
install_element(ENABLE_NODE, &subscriber_rat_cmd);
|
||||
}
|
||||
|
||||
29
src/lu_fsm.c
29
src/lu_fsm.c
@@ -108,6 +108,8 @@ static void lu_start(struct osmo_gsup_req *update_location_req)
|
||||
{
|
||||
struct osmo_fsm_inst *fi;
|
||||
struct lu *lu;
|
||||
bool any_rat_allowed;
|
||||
int i;
|
||||
|
||||
OSMO_ASSERT(update_location_req);
|
||||
OSMO_ASSERT(update_location_req->gsup.message_type == OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST);
|
||||
@@ -136,7 +138,7 @@ static void lu_start(struct osmo_gsup_req *update_location_req)
|
||||
}
|
||||
|
||||
if (db_subscr_get_by_imsi(g_hlr->dbc, update_location_req->gsup.imsi, &lu->subscr) < 0) {
|
||||
lu_failure(lu, GMM_CAUSE_IMSI_UNKNOWN, "Subscriber does not exist");
|
||||
lu_failure(lu, GMM_CAUSE_ROAMING_NOTALLOWED, "Subscriber does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -151,6 +153,28 @@ static void lu_start(struct osmo_gsup_req *update_location_req)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if any available RAT type is allowed. See 3GPP TS 29.010 3.2 'Routeing area updating' and 3.8 'Location
|
||||
* update' for the "No Suitable cells in location area" error code. */
|
||||
any_rat_allowed = false;
|
||||
for (i = 0; i < update_location_req->gsup.supported_rat_types_len; i++) {
|
||||
enum osmo_rat_type rat = update_location_req->gsup.supported_rat_types[i];
|
||||
if (rat <= 0 || rat >= OSMO_RAT_COUNT) {
|
||||
lu_failure(lu, GMM_CAUSE_COND_IE_ERR, "Invalid RAT type in GSUP request: %s",
|
||||
osmo_rat_type_name(rat));
|
||||
return;
|
||||
}
|
||||
if (lu->subscr.rat_types[rat]) {
|
||||
any_rat_allowed = true;
|
||||
LOG_LU(lu, LOGL_DEBUG, "subscriber allowed on %s\n", osmo_rat_type_name(rat));
|
||||
} else {
|
||||
LOG_LU(lu, LOGL_DEBUG, "subscriber not allowed on %s\n", osmo_rat_type_name(rat));
|
||||
}
|
||||
}
|
||||
if (!any_rat_allowed && update_location_req->gsup.supported_rat_types_len > 0) {
|
||||
lu_failure(lu, GMM_CAUSE_NO_SUIT_CELL_IN_LA, "subscriber not allowed on any available RAT type");
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: Set subscriber tracing = deactive in VLR/SGSN */
|
||||
|
||||
#if 0
|
||||
@@ -186,7 +210,8 @@ static void lu_start(struct osmo_gsup_req *update_location_req)
|
||||
return;
|
||||
}
|
||||
if (db_subscr_lu(g_hlr->dbc, lu->subscr.id, &lu->vlr_name.ipa_name, lu->is_ps,
|
||||
osmo_gsup_peer_id_is_empty(&lu->via_proxy)? NULL : &lu->via_proxy.ipa_name)) {
|
||||
osmo_gsup_peer_id_is_empty(&lu->via_proxy)? NULL : &lu->via_proxy.ipa_name,
|
||||
update_location_req->gsup.supported_rat_types, update_location_req->gsup.supported_rat_types_len)) {
|
||||
lu_failure(lu, GMM_CAUSE_NET_FAIL, "Cannot update %s in the database",
|
||||
lu->is_ps ? "SGSN number" : "VLR number");
|
||||
return;
|
||||
|
||||
@@ -80,7 +80,7 @@ static void proxy_deferred_gsup_req_add(struct proxy *proxy, struct osmo_gsup_re
|
||||
static void proxy_pending_req_remote_hlr_connect_result(struct osmo_gsup_req *req, struct remote_hlr *remote_hlr)
|
||||
{
|
||||
if (!remote_hlr || !remote_hlr_is_up(remote_hlr)) {
|
||||
osmo_gsup_req_respond_err(req, GMM_CAUSE_IMSI_UNKNOWN, "Proxy: Failed to connect to home HLR");
|
||||
osmo_gsup_req_respond_err(req, GMM_CAUSE_ROAMING_NOTALLOWED, "Proxy: Failed to connect to home HLR");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -173,6 +173,8 @@ void dump_subscr(struct hlr_subscriber *subscr)
|
||||
Pfo(lmsi, "0x%x", subscr);
|
||||
Pb(true, ms_purged_cs);
|
||||
Pb(true, ms_purged_ps);
|
||||
Ps(last_lu_rat_cs);
|
||||
Ps(last_lu_rat_ps);
|
||||
fprintf(stderr, "}\n");
|
||||
#undef Ps
|
||||
#undef Pd
|
||||
@@ -243,7 +245,7 @@ static int db_subscr_lu_str(struct db_context *dbc, int64_t subscr_id,
|
||||
{
|
||||
struct osmo_ipa_name vlr_nr;
|
||||
osmo_ipa_name_set_str(&vlr_nr, vlr_or_sgsn_number);
|
||||
return db_subscr_lu(dbc, subscr_id, &vlr_nr, is_ps, NULL);
|
||||
return db_subscr_lu(dbc, subscr_id, &vlr_nr, is_ps, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
static void test_subscr_create_update_sel_delete()
|
||||
|
||||
@@ -4,6 +4,9 @@ OsmoHLR# subscriber imsi 123456789012345 create
|
||||
ID: 1
|
||||
IMSI: 123456789012345
|
||||
MSISDN: none
|
||||
GERAN-A: allowed
|
||||
UTRAN-Iu: allowed
|
||||
EUTRAN-SGs: allowed
|
||||
OsmoHLR# subscriber imsi 123456789012345 update msisdn 098765432109876
|
||||
% Updated subscriber IMSI='123456789012345' to MSISDN='098765432109876'
|
||||
OsmoHLR# subscriber imsi 123456789012345 update aud2g comp128v1 ki BeefedCafeFaceAcedAddedDecadeFee
|
||||
@@ -13,11 +16,17 @@ OsmoHLR# subscriber imsi 111111111 create
|
||||
ID: 2
|
||||
IMSI: 111111111
|
||||
MSISDN: none
|
||||
GERAN-A: allowed
|
||||
UTRAN-Iu: allowed
|
||||
EUTRAN-SGs: allowed
|
||||
OsmoHLR# subscriber imsi 222222222 create
|
||||
% Created subscriber 222222222
|
||||
ID: 3
|
||||
IMSI: 222222222
|
||||
MSISDN: none
|
||||
GERAN-A: allowed
|
||||
UTRAN-Iu: allowed
|
||||
EUTRAN-SGs: allowed
|
||||
OsmoHLR# subscriber imsi 222222222 update msisdn 22222
|
||||
% Updated subscriber IMSI='222222222' to MSISDN='22222'
|
||||
OsmoHLR# subscriber imsi 333333 create
|
||||
@@ -25,6 +34,9 @@ OsmoHLR# subscriber imsi 333333 create
|
||||
ID: 4
|
||||
IMSI: 333333
|
||||
MSISDN: none
|
||||
GERAN-A: allowed
|
||||
UTRAN-Iu: allowed
|
||||
EUTRAN-SGs: allowed
|
||||
OsmoHLR# subscriber imsi 333333 update msisdn 3
|
||||
% Updated subscriber IMSI='333333' to MSISDN='3'
|
||||
OsmoHLR# subscriber imsi 333333 update aud2g comp128v2 ki 33333333333333333333333333333333
|
||||
@@ -33,6 +45,9 @@ OsmoHLR# subscriber imsi 444444444444444 create
|
||||
ID: 5
|
||||
IMSI: 444444444444444
|
||||
MSISDN: none
|
||||
GERAN-A: allowed
|
||||
UTRAN-Iu: allowed
|
||||
EUTRAN-SGs: allowed
|
||||
OsmoHLR# subscriber imsi 444444444444444 update msisdn 4444
|
||||
% Updated subscriber IMSI='444444444444444' to MSISDN='4444'
|
||||
OsmoHLR# subscriber imsi 444444444444444 update aud3g milenage k 44444444444444444444444444444444 op 44444444444444444444444444444444
|
||||
@@ -41,6 +56,9 @@ OsmoHLR# subscriber imsi 5555555 create
|
||||
ID: 6
|
||||
IMSI: 5555555
|
||||
MSISDN: none
|
||||
GERAN-A: allowed
|
||||
UTRAN-Iu: allowed
|
||||
EUTRAN-SGs: allowed
|
||||
OsmoHLR# subscriber imsi 5555555 update msisdn 55555555555555
|
||||
% Updated subscriber IMSI='5555555' to MSISDN='55555555555555'
|
||||
OsmoHLR# subscriber imsi 5555555 update aud2g xor ki 55555555555555555555555555555555
|
||||
|
||||
@@ -86,6 +86,8 @@ DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 3
|
||||
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 4
|
||||
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 5
|
||||
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 6
|
||||
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 7
|
||||
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 8
|
||||
DMAIN Cmdline option --db-check: Database was opened successfully, quitting.
|
||||
|
||||
Resulting db:
|
||||
@@ -120,7 +122,6 @@ algo_id_3g|ind_bitlen|k|op|opc|sqn|subscriber_id
|
||||
|
||||
Table: ind
|
||||
name|type|notnull|dflt_value|pk
|
||||
cn_domain|INTEGER|1||0
|
||||
ind|INTEGER|0||1
|
||||
vlr|TEXT|1||0
|
||||
|
||||
@@ -134,6 +135,8 @@ id|INTEGER|0||1
|
||||
imei|VARCHAR(14)|0||0
|
||||
imeisv|VARCHAR|0||0
|
||||
imsi|VARCHAR(15)|1||0
|
||||
last_lu_rat_cs|TEXT|0|NULL|0
|
||||
last_lu_rat_ps|TEXT|0|NULL|0
|
||||
last_lu_seen|TIMESTAMP|0|NULL|0
|
||||
last_lu_seen_ps|TIMESTAMP|0|NULL|0
|
||||
lmsi|INTEGER|0||0
|
||||
@@ -153,13 +156,13 @@ vlr_number|VARCHAR(15)|0||0
|
||||
vlr_via_proxy|VARCHAR|0||0
|
||||
|
||||
Table subscriber contents:
|
||||
ggsn_number|gmlc_number|id|imei|imeisv|imsi|last_lu_seen|last_lu_seen_ps|lmsi|ms_purged_cs|ms_purged_ps|msc_number|msisdn|nam_cs|nam_ps|periodic_lu_tmr|periodic_rau_tau_tmr|sgsn_address|sgsn_number|sgsn_via_proxy|smsc_number|vlr_number|vlr_via_proxy
|
||||
||1|||123456789012345||||0|0||098765432109876|1|1|||||||MSC-1|
|
||||
||2|||111111111||||1|0|||1|1||||||||
|
||||
||3|||222222222||||0|1||22222|1|1||||||||
|
||||
||4|||333333||||0|0||3|0|1||||||||
|
||||
||5|||444444444444444||||0|0||4444|1|0||||||||
|
||||
||6|||5555555||||0|0||55555555555555|0|0||||||||
|
||||
ggsn_number|gmlc_number|id|imei|imeisv|imsi|last_lu_rat_cs|last_lu_rat_ps|last_lu_seen|last_lu_seen_ps|lmsi|ms_purged_cs|ms_purged_ps|msc_number|msisdn|nam_cs|nam_ps|periodic_lu_tmr|periodic_rau_tau_tmr|sgsn_address|sgsn_number|sgsn_via_proxy|smsc_number|vlr_number|vlr_via_proxy
|
||||
||1|||123456789012345||||||0|0||098765432109876|1|1|||||||MSC-1|
|
||||
||2|||111111111||||||1|0|||1|1||||||||
|
||||
||3|||222222222||||||0|1||22222|1|1||||||||
|
||||
||4|||333333||||||0|0||3|0|1||||||||
|
||||
||5|||444444444444444||||||0|0||4444|1|0||||||||
|
||||
||6|||5555555||||||0|0||55555555555555|0|0||||||||
|
||||
|
||||
Table: subscriber_apn
|
||||
name|type|notnull|dflt_value|pk
|
||||
@@ -175,10 +178,18 @@ subscriber_id|INTEGER|0||0
|
||||
|
||||
Table subscriber_multi_msisdn contents:
|
||||
|
||||
Table: subscriber_rat
|
||||
name|type|notnull|dflt_value|pk
|
||||
allowed|BOOLEAN|1|0|0
|
||||
rat|TEXT|1||0
|
||||
subscriber_id|INTEGER|0||0
|
||||
|
||||
Table subscriber_rat contents:
|
||||
|
||||
Verify that osmo-hlr can open it:
|
||||
osmo-hlr --database $db --db-check --config-file $srcdir/osmo-hlr.cfg
|
||||
rc = 0
|
||||
DMAIN hlr starting
|
||||
DDB using database: <PATH>test.db
|
||||
DDB Database <PATH>test.db' has HLR DB schema version 6
|
||||
DDB Database <PATH>test.db' has HLR DB schema version 8
|
||||
DMAIN Cmdline option --db-check: Database was opened successfully, quitting.
|
||||
|
||||
Reference in New Issue
Block a user