aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Sperling <ssperling@sysmocom.de>2018-12-07 12:30:21 +0100
committerStefan Sperling <stsp@stsp.name>2018-12-10 16:12:06 +0000
commit5c14c9ccca83563d07670eb8e9ed5867ca957112 (patch)
treeb36b740fa2a3f8b49cf42baa49eee7c6911e1a08
parent705b61bcb795490e265027d0b45499b87dd65e12 (diff)
display last location update timestamp in vty
Read the subscriber's last location update timestamp from the database and display it in the output of 'show subscriber'. For example: OsmoHLR> show subscriber id 1 ID: 1 IMSI: 123456789000000 MSISDN: 543210123456789 VLR number: 712 SGSN number: 5952 last LU seen: Fri Dec 7 11:30:51 2018 UTC While the database stores the timestamp as a string, we convert the timestamp into time_t for internal use. This allows for flexible potential use of the timestamp in contexts other than the VTY in the future. The timestamp displayed in the VTY is created with ctime_r(3). It does not match the format of the raw string in the database: sqlite> select id,last_lu_seen from subscriber; 1|2018-12-07 11:30:51 Related: OS#2838 Change-Id: Ie180c434f02ffec0d4b2f651a73258a8126b2e1a
-rw-r--r--src/db.h6
-rw-r--r--src/db_hlr.c21
-rw-r--r--src/hlr_vty_subscr.c17
3 files changed, 44 insertions, 0 deletions
diff --git a/src/db.h b/src/db.h
index 5129b8d..ae592fb 100644
--- a/src/db.h
+++ b/src/db.h
@@ -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;