diff options
-rw-r--r-- | src/db.h | 6 | ||||
-rw-r--r-- | src/db_hlr.c | 21 | ||||
-rw-r--r-- | src/hlr_vty_subscr.c | 17 |
3 files changed, 44 insertions, 0 deletions
@@ -84,8 +84,14 @@ struct hlr_subscriber { uint32_t lmsi; bool ms_purged_cs; bool ms_purged_ps; + time_t last_lu_seen; }; +/* 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(). */ +#define DB_LAST_LU_SEEN_FMT "%Y-%m-%d %H:%M:%S" + /* Like struct osmo_sub_auth_data, but the keys are in hexdump representation. * This is useful because SQLite requires them in hexdump format, and callers * like the VTY and CTRL interface also have them available as hexdump to begin diff --git a/src/db_hlr.c b/src/db_hlr.c index db31009..c97cd82 100644 --- a/src/db_hlr.c +++ b/src/db_hlr.c @@ -17,6 +17,11 @@ * */ +#define _POSIX_C_SOURCE 200809L /* for strptime(3) */ +/* These are needed as well due to the above _POSIX_C_SOURCE definition: */ +#define _DEFAULT_SOURCE /* for struct timezone */ +#define _XOPEN_SOURCE /* for clockid_t */ + #include <string.h> #include <errno.h> #include <inttypes.h> @@ -387,6 +392,8 @@ static int db_sel(struct db_context *dbc, sqlite3_stmt *stmt, struct hlr_subscri { int rc; int ret = 0; + const char *last_lu_seen_str; + struct tm tm; /* execute the statement */ rc = sqlite3_step(stmt); @@ -419,6 +426,20 @@ static int db_sel(struct db_context *dbc, sqlite3_stmt *stmt, struct hlr_subscri subscr->lmsi = sqlite3_column_int(stmt, 10); subscr->ms_purged_cs = sqlite3_column_int(stmt, 11); subscr->ms_purged_ps = sqlite3_column_int(stmt, 12); + last_lu_seen_str = (const char *)sqlite3_column_text(stmt, 13); + 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; + } + } + } out: db_remove_reset(stmt); diff --git a/src/hlr_vty_subscr.c b/src/hlr_vty_subscr.c index bc6f6a5..92cfa2a 100644 --- a/src/hlr_vty_subscr.c +++ b/src/hlr_vty_subscr.c @@ -20,6 +20,8 @@ #include <inttypes.h> #include <string.h> #include <errno.h> +#include <sys/types.h> +#include <time.h> #include <osmocom/gsm/gsm23003.h> #include <osmocom/vty/vty.h> @@ -33,11 +35,24 @@ struct vty; #define hexdump_buf(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf)) +static char * +get_datestr(const time_t *t, char *datebuf) +{ + char *p, *s = ctime_r(t, datebuf); + + /* Strip trailing newline. */ + p = strchr(s, '\n'); + if (p) + *p = '\0'; + return s; +} + 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); @@ -63,6 +78,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); if (!*subscr->imsi) return; |