aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2019-11-20 02:36:35 +0100
committerNeels Hofmeyr <neels@hofmeyr.de>2019-11-27 03:19:06 +0100
commit07e1602d2dd13d0884ccd623d9f7955b921fa702 (patch)
tree02a08050da1f6a69bbae0b1571abc8cc6a7c205e /src
parentabdfdb8a4a58d36e8ac8e54736589df753225da7 (diff)
db v4: add column last_lu_seen_ps
Location Updating procedures from both CS and PS overwrite the same last_lu_seen field of a subscriber. For upcoming D-GSM it will be important to distinguish those, because only CS attaches qualify for MSISDN lookup. Add column last_lu_seen_ps, and upon PS LU, do not overwrite last_lu_seen, so that last_lu_seen now only reflects CS LU. In the VTY, dump both LU dates distinctively. Change-Id: Id7fc50567211a0870ac0524f6dee94d4513781ba
Diffstat (limited to 'src')
-rw-r--r--src/db.c23
-rw-r--r--src/db_hlr.c46
-rw-r--r--src/hlr_vty_subscr.c14
3 files changed, 61 insertions, 22 deletions
diff --git a/src/db.c b/src/db.c
index 992dbad..5e5ad35 100644
--- a/src/db.c
+++ b/src/db.c
@@ -28,7 +28,7 @@
#include "db_bootstrap.h"
/* This constant is currently duplicated in sql/hlr.sql and must be kept in sync! */
-#define CURRENT_SCHEMA_VERSION 3
+#define CURRENT_SCHEMA_VERSION 4
#define SEL_COLUMNS \
"id," \
@@ -45,7 +45,8 @@
"lmsi," \
"ms_purged_cs," \
"ms_purged_ps," \
- "last_lu_seen"
+ "last_lu_seen," \
+ "last_lu_seen_ps" \
static const char *stmt_sql[] = {
[DB_STMT_SEL_BY_IMSI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imsi = ?",
@@ -79,6 +80,7 @@ static const char *stmt_sql[] = {
" 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_EXISTS_BY_IMSI] = "SELECT 1 FROM subscriber WHERE imsi = $imsi",
[DB_STMT_EXISTS_BY_MSISDN] = "SELECT 1 FROM subscriber WHERE msisdn = $msisdn",
};
@@ -423,11 +425,28 @@ static int db_upgrade_v3(struct db_context *dbc)
return rc;
}
+static int db_upgrade_v4(struct db_context *dbc)
+{
+ int rc;
+ const char *statements[] = {
+ "ALTER TABLE subscriber ADD COLUMN last_lu_seen_ps TIMESTAMP default NULL",
+ "PRAGMA user_version = 4",
+ };
+
+ 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 4\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,
db_upgrade_v2,
db_upgrade_v3,
+ db_upgrade_v4,
};
static int db_get_user_version(struct db_context *dbc)
diff --git a/src/db_hlr.c b/src/db_hlr.c
index e52b5ed..b3e3887 100644
--- a/src/db_hlr.c
+++ b/src/db_hlr.c
@@ -438,14 +438,36 @@ out:
return ret;
}
+static void parse_last_lu_seen(time_t *dst, const char *last_lu_seen_str, const char *imsi, const char *label)
+{
+ struct tm tm = {0};
+ time_t val;
+ if (!last_lu_seen_str || last_lu_seen_str[0] == '\0')
+ return;
+
+ if (strptime(last_lu_seen_str, DB_LAST_LU_SEEN_FMT, &tm) == NULL) {
+ LOGP(DAUC, LOGL_ERROR, "IMSI-%s: Last LU Seen %s: Cannot parse timestamp '%s'\n",
+ imsi, label, last_lu_seen_str);
+ return;
+ }
+
+ errno = 0;
+ val = mktime(&tm);
+ if (val == -1) {
+ LOGP(DAUC, LOGL_ERROR, "IMSI-%s: Last LU Seen %s: Cannot convert timestamp '%s' to time_t: %s\n",
+ imsi, label, last_lu_seen_str, strerror(errno));
+ val = 0;
+ }
+
+ *dst = val;
+}
+
/* Common code for db_subscr_get_by_*() functions. */
static int db_sel(struct db_context *dbc, sqlite3_stmt *stmt, struct hlr_subscriber *subscr,
const char **err)
{
int rc;
int ret = 0;
- const char *last_lu_seen_str;
- struct tm tm = {0};
/* execute the statement */
rc = sqlite3_step(stmt);
@@ -479,20 +501,10 @@ static int db_sel(struct db_context *dbc, sqlite3_stmt *stmt, struct hlr_subscri
subscr->lmsi = sqlite3_column_int(stmt, 11);
subscr->ms_purged_cs = sqlite3_column_int(stmt, 12);
subscr->ms_purged_ps = sqlite3_column_int(stmt, 13);
- last_lu_seen_str = (const char *)sqlite3_column_text(stmt, 14);
- if (last_lu_seen_str && last_lu_seen_str[0] != '\0') {
- if (strptime(last_lu_seen_str, DB_LAST_LU_SEEN_FMT, &tm) == NULL) {
- LOGP(DAUC, LOGL_ERROR, "Cannot parse last LU timestamp '%s' of subscriber with IMSI='%s': %s\n",
- last_lu_seen_str, subscr->imsi, strerror(errno));
- } else {
- subscr->last_lu_seen = mktime(&tm);
- if (subscr->last_lu_seen == -1) {
- LOGP(DAUC, LOGL_ERROR, "Cannot convert LU timestamp '%s' to time_t: %s\n",
- last_lu_seen_str, strerror(errno));
- subscr->last_lu_seen = 0;
- }
- }
- }
+ parse_last_lu_seen(&subscr->last_lu_seen, (const char *)sqlite3_column_text(stmt, 14),
+ subscr->imsi, "CS");
+ parse_last_lu_seen(&subscr->last_lu_seen_ps, (const char *)sqlite3_column_text(stmt, 15),
+ subscr->imsi, "PS");
out:
db_remove_reset(stmt);
@@ -770,7 +782,7 @@ int db_subscr_lu(struct db_context *dbc, int64_t subscr_id,
goto out;
}
- stmt = dbc->stmt[DB_STMT_SET_LAST_LU_SEEN];
+ stmt = dbc->stmt[is_ps? DB_STMT_SET_LAST_LU_SEEN_PS : DB_STMT_SET_LAST_LU_SEEN];
if (!db_bind_int64(stmt, "$subscriber_id", subscr_id))
return -EIO;
diff --git a/src/hlr_vty_subscr.c b/src/hlr_vty_subscr.c
index d2c4c81..b561636 100644
--- a/src/hlr_vty_subscr.c
+++ b/src/hlr_vty_subscr.c
@@ -47,12 +47,20 @@ get_datestr(const time_t *t, char *datebuf)
return s;
}
+static void dump_last_lu_seen(struct vty *vty, const char *domain_label, time_t last_lu_seen)
+{
+ char datebuf[26]; /* for ctime_r(3) */
+ if (!last_lu_seen)
+ return;
+ vty_out(vty, " last LU seen on %s: %s UTC%s", domain_label, get_datestr(&last_lu_seen, datebuf),
+ VTY_NEWLINE);
+}
+
static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
{
int rc;
struct osmo_sub_auth_data aud2g;
struct osmo_sub_auth_data aud3g;
- char datebuf[26]; /* for ctime_r(3) */
vty_out(vty, " ID: %"PRIu64"%s", subscr->id, VTY_NEWLINE);
@@ -87,8 +95,8 @@ 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);
- if (subscr->last_lu_seen)
- vty_out(vty, " last LU seen: %s UTC%s", get_datestr(&subscr->last_lu_seen, datebuf), VTY_NEWLINE);
+ dump_last_lu_seen(vty, "CS", subscr->last_lu_seen);
+ dump_last_lu_seen(vty, "PS", subscr->last_lu_seen_ps);
if (!*subscr->imsi)
return;