From 82a583b6ba3f7d02d9c65eb735b8e57c22426fec Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 5 May 2016 21:03:03 +0200 Subject: implement PURGE-MS from VLR/SGSN to HLR Using this procedure, the VLR/SGSN can set the cs/ps purged flag for the subscriber. We might not even need to store this persistent in the database according to spec, but let's do it anyway, at least until it turns out to be a performance issue. --- osmo-gsup-hlr/sql/hlr.sql | 2 ++ osmo-gsup-hlr/src/db.h | 5 +++++ osmo-gsup-hlr/src/db_hlr.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ osmo-gsup-hlr/src/hlr.c | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+) diff --git a/osmo-gsup-hlr/sql/hlr.sql b/osmo-gsup-hlr/sql/hlr.sql index 9b8156e..041b42b 100644 --- a/osmo-gsup-hlr/sql/hlr.sql +++ b/osmo-gsup-hlr/sql/hlr.sql @@ -32,6 +32,8 @@ CREATE TABLE subscriber ( -- Chapter 2.1.8 lmsi INTEGER, + -- The below purged flags might not even be stored non-volatile, + -- refer to TS 23.012 Chapter 3.6.1.4 -- Chapter 2.7.5 ms_purged_cs BOOLEAN NOT NULL DEFAULT 0, -- Chapter 2.7.6 diff --git a/osmo-gsup-hlr/src/db.h b/osmo-gsup-hlr/src/db.h index a776099..d569fb0 100644 --- a/osmo-gsup-hlr/src/db.h +++ b/osmo-gsup-hlr/src/db.h @@ -9,6 +9,8 @@ enum stmt_idx { UPD_SGSN_BY_ID = 2, AUC_BY_IMSI = 3, AUC_UPD_SQN = 4, + UPD_PURGE_CS_BY_IMSI, + UPD_PURGE_PS_BY_IMSI, _NUM_STMT }; @@ -71,3 +73,6 @@ int db_subscr_lu(struct db_context *dbc, const struct hlr_subscriber *subscr, const char *vlr_or_sgsn_number, bool lu_is_ps); + +int db_subscr_purge(struct db_context *dbc, + const char *imsi, bool is_ps); diff --git a/osmo-gsup-hlr/src/db_hlr.c b/osmo-gsup-hlr/src/db_hlr.c index baa0456..ca44e8e 100644 --- a/osmo-gsup-hlr/src/db_hlr.c +++ b/osmo-gsup-hlr/src/db_hlr.c @@ -135,3 +135,48 @@ out: return ret; } + +int db_subscr_purge(struct db_context *dbc, const char *imsi, bool is_ps) +{ + sqlite3_stmt *stmt = dbc->stmt[UPD_VLR_BY_ID]; + int rc, ret = 1; + + if (is_ps) + stmt = dbc->stmt[UPD_PURGE_PS_BY_IMSI]; + else + stmt = dbc->stmt[UPD_PURGE_CS_BY_IMSI]; + + rc = sqlite3_bind_int(stmt, 1, 1); + if (rc != SQLITE_OK) { + LOGP(DAUC, LOGL_ERROR, "Error binding Purged: %d\n", rc); + return -1; + } + + rc = sqlite3_bind_text(stmt, 2, imsi, -1, SQLITE_STATIC); + if (rc != SQLITE_OK) { + LOGP(DAUC, LOGL_ERROR, "Error binding IMSI: %d\n", rc); + ret = -1; + goto out; + } + + /* execute the statement */ + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE) { + LOGP(DAUC, LOGL_ERROR, "Error setting Purged: %d\n", rc); + ret = -2; + goto out; + } + /* FIXME: return 0 in case IMSI not known */ +out: + /* remove bindings and reset statement to be re-executed */ + rc = sqlite3_clear_bindings(stmt); + if (rc != SQLITE_OK) { + LOGP(DAUC, LOGL_ERROR, "Error clearing bindings: %d\n", rc); + } + rc = sqlite3_reset(stmt); + if (rc != SQLITE_OK) { + LOGP(DAUC, LOGL_ERROR, "Error in sqlite3_reset: %d\n", rc); + } + + return ret; +} diff --git a/osmo-gsup-hlr/src/hlr.c b/osmo-gsup-hlr/src/hlr.c index 3b17708..0e31a43 100644 --- a/osmo-gsup-hlr/src/hlr.c +++ b/osmo-gsup-hlr/src/hlr.c @@ -406,6 +406,43 @@ static int rx_upd_loc_req(struct osmo_gsup_conn *conn, return 0; } +static int rx_purge_ms_req(struct osmo_gsup_conn *conn, + const struct osmo_gsup_message *gsup) +{ + struct osmo_gsup_message gsup_reply = {0}; + struct msgb *msg_out; + bool is_ps = false; + int rc; + + LOGP(DAUC, LOGL_INFO, "%s: Purge MS (%s)\n", gsup->imsi, + is_ps ? "PS" : "CS"); + + memcpy(gsup_reply.imsi, gsup->imsi, sizeof(gsup_reply.imsi)); + + if (gsup->cn_domain == OSMO_GSUP_CN_DOMAIN_PS) + is_ps = true; + + /* FIXME: check if the VLR that sends the purge is the same that + * we have on record. Only update if yes */ + + /* Perform the actual update of the DB */ + rc = db_subscr_purge(g_dbc, gsup->imsi, is_ps); + + if (rc == 1) + gsup_reply.message_type = OSMO_GSUP_MSGT_PURGE_MS_RESULT; + else if (rc == 0) { + gsup_reply.message_type = OSMO_GSUP_MSGT_PURGE_MS_ERROR; + gsup_reply.cause = GMM_CAUSE_IMSI_UNKNOWN; + } else { + gsup_reply.message_type = OSMO_GSUP_MSGT_PURGE_MS_ERROR; + gsup_reply.cause = GMM_CAUSE_NET_FAIL; + } + + msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP AUC response"); + osmo_gsup_encode(msg_out, &gsup_reply); + return osmo_gsup_conn_send(conn, msg_out); +} + static int read_cb(struct osmo_gsup_conn *conn, struct msgb *msg) { static struct osmo_gsup_message gsup; @@ -425,6 +462,9 @@ static int read_cb(struct osmo_gsup_conn *conn, struct msgb *msg) case OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: rx_upd_loc_req(conn, &gsup); break; + case OSMO_GSUP_MSGT_PURGE_MS_REQUEST: + rx_purge_ms_req(conn, &gsup); + break; /* responses to requests sent by us */ case OSMO_GSUP_MSGT_INSERT_DATA_ERROR: case OSMO_GSUP_MSGT_INSERT_DATA_RESULT: -- cgit v1.2.3