<p>osmith has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/12525">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Add IMEI column to subscriber table<br><br>Extend the database scheme, add imei to the hlr_subscriber struct and<br>create db_subscr_update_imei_by_id() and db_subscr_get_by_imei(). The<br>new functions are used in db_test.<br><br>This change requires a HLR DB schema update. Existing databases<br>won't be upgraded automatically. However, osmo-hlr will refuse<br>to operate with databases which are not upgraded.<br><br>SQLite can only insert new columns at the end of the table, so this<br>happens when upgrading the database. In new databases, the column is<br>placed after the IMEISV column (where it makes more sense in my<br>opinion). This should not have any effect, as we never rely on the<br>order of the columns in the tables.<br><br>A follow-up commit will make use of this column to save the IMEI as<br>received from the MSC/VLR with the Check-IMEI Procedure. It was<br>decided to use Check-IMEI instead of the recent Automatic Device<br>Detection Procedure (which would send the IMEISV) in OS#3733, because<br>with Check-IMEI we don't need to rely on very recent releases of the<br>specification.<br><br>Depends: Id2d2a3a93b033bafc74c62e15297034bf4aafe61 (libosmocore)<br>Related: OS#2541<br>Change-Id: If232c80bea35d5c6864b889ae92d477eeaa3f45d<br>---<br>M sql/hlr.sql<br>M src/db.c<br>M src/db.h<br>M src/db_hlr.c<br>M tests/db/db_test.c<br>M tests/db/db_test.err<br>6 files changed, 212 insertions(+), 15 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-hlr refs/changes/25/12525/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/sql/hlr.sql b/sql/hlr.sql</span><br><span>index 9ff9867..10838f2 100644</span><br><span>--- a/sql/hlr.sql</span><br><span>+++ b/sql/hlr.sql</span><br><span>@@ -5,8 +5,10 @@</span><br><span>      imsi            VARCHAR(15) UNIQUE NOT NULL,</span><br><span>         -- Chapter 2.1.2</span><br><span>     msisdn          VARCHAR(15) UNIQUE,</span><br><span style="color: hsl(0, 100%, 40%);">-     -- Chapter 2.2.3: Most recent / current IMEI</span><br><span style="color: hsl(120, 100%, 40%);">+  -- Chapter 2.2.3: Most recent / current IMEISV</span><br><span>       imeisv          VARCHAR,</span><br><span style="color: hsl(120, 100%, 40%);">+      -- Chapter 2.1.9: Most recent / current IMEI</span><br><span style="color: hsl(120, 100%, 40%);">+  imei            VARCHAR(14),</span><br><span>         -- Chapter 2.4.5</span><br><span>     vlr_number      VARCHAR(15),</span><br><span>         -- Chapter 2.4.6</span><br><span>@@ -74,4 +76,4 @@</span><br><span> </span><br><span> -- Set HLR database schema version number</span><br><span> -- Note: This constant is currently duplicated in src/db.c and must be kept in sync!</span><br><span style="color: hsl(0, 100%, 40%);">-PRAGMA user_version = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+PRAGMA user_version = 2;</span><br><span>diff --git a/src/db.c b/src/db.c</span><br><span>index f7cbace..7e8ad69 100644</span><br><span>--- a/src/db.c</span><br><span>+++ b/src/db.c</span><br><span>@@ -28,12 +28,13 @@</span><br><span> #include "db_bootstrap.h"</span><br><span> </span><br><span> /* This constant is currently duplicated in sql/hlr.sql and must be kept in sync! */</span><br><span style="color: hsl(0, 100%, 40%);">-#define CURRENT_SCHEMA_VERSION     1</span><br><span style="color: hsl(120, 100%, 40%);">+#define CURRENT_SCHEMA_VERSION       2</span><br><span> </span><br><span> #define SEL_COLUMNS \</span><br><span>       "id," \</span><br><span>    "imsi," \</span><br><span>  "msisdn," \</span><br><span style="color: hsl(120, 100%, 40%);">+ "imei," \</span><br><span>  "vlr_number," \</span><br><span>    "sgsn_number," \</span><br><span>   "sgsn_address," \</span><br><span>@@ -50,8 +51,10 @@</span><br><span>     [DB_STMT_SEL_BY_IMSI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imsi = ?",</span><br><span>         [DB_STMT_SEL_BY_MSISDN] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE msisdn = ?",</span><br><span>     [DB_STMT_SEL_BY_ID] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE id = ?",</span><br><span style="color: hsl(120, 100%, 40%);">+      [DB_STMT_SEL_BY_IMEI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imei = ?",</span><br><span>         [DB_STMT_UPD_VLR_BY_ID] = "UPDATE subscriber SET vlr_number = $number WHERE id = $subscriber_id",</span><br><span>  [DB_STMT_UPD_SGSN_BY_ID] = "UPDATE subscriber SET sgsn_number = $number WHERE id = $subscriber_id",</span><br><span style="color: hsl(120, 100%, 40%);">+ [DB_STMT_UPD_IMEI_BY_ID] = "UPDATE subscriber SET imei = $imei WHERE id = $subscriber_id",</span><br><span>         [DB_STMT_AUC_BY_IMSI] =</span><br><span>              "SELECT id, algo_id_2g, ki, algo_id_3g, k, op, opc, sqn, ind_bitlen"</span><br><span>               " FROM subscriber"</span><br><span>@@ -290,6 +293,40 @@</span><br><span>  return rc;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int db_upgrade_v2(struct db_context *dbc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      sqlite3_stmt *stmt;</span><br><span style="color: hsl(120, 100%, 40%);">+   int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       const char *update_stmt_sql = "ALTER TABLE subscriber ADD COLUMN imei VARCHAR(14) default NULL";</span><br><span style="color: hsl(120, 100%, 40%);">+    const char *set_schema_version_sql = "PRAGMA user_version = 2";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   rc = sqlite3_prepare_v2(dbc->db, update_stmt_sql, -1, &stmt, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (rc != SQLITE_OK) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", update_stmt_sql);</span><br><span style="color: hsl(120, 100%, 40%);">+           return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     rc = sqlite3_step(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+      db_remove_reset(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+        sqlite3_finalize(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (rc != SQLITE_DONE) {</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version %d\n", 1);</span><br><span style="color: hsl(120, 100%, 40%);">+           return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   rc = sqlite3_prepare_v2(dbc->db, set_schema_version_sql, -1, &stmt, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (rc != SQLITE_OK) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", set_schema_version_sql);</span><br><span style="color: hsl(120, 100%, 40%);">+            return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     rc = sqlite3_step(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (rc != SQLITE_DONE)</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version %d\n", 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ db_remove_reset(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+        sqlite3_finalize(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+       return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int db_get_user_version(struct db_context *dbc)</span><br><span> {</span><br><span>       const char *user_version_sql = "PRAGMA user_version";</span><br><span>@@ -400,6 +437,15 @@</span><br><span>                       }</span><br><span>                    version = 1;</span><br><span>                         /* fall through */</span><br><span style="color: hsl(120, 100%, 40%);">+            case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+                       rc = db_upgrade_v2(dbc);</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (rc != SQLITE_DONE) {</span><br><span style="color: hsl(120, 100%, 40%);">+                              LOGP(DDB, LOGL_ERROR, "Failed to upgrade HLR DB schema to version 2: (rc=%d) %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                              rc, sqlite3_errmsg(dbc->db));</span><br><span style="color: hsl(120, 100%, 40%);">+                         goto out_free;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+                     version = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+                  /* fall through */</span><br><span>           /* case N: ... */</span><br><span>            default:</span><br><span>                     break;</span><br><span>diff --git a/src/db.h b/src/db.h</span><br><span>index ae592fb..fddda4f 100644</span><br><span>--- a/src/db.h</span><br><span>+++ b/src/db.h</span><br><span>@@ -9,8 +9,10 @@</span><br><span>       DB_STMT_SEL_BY_IMSI,</span><br><span>         DB_STMT_SEL_BY_MSISDN,</span><br><span>       DB_STMT_SEL_BY_ID,</span><br><span style="color: hsl(120, 100%, 40%);">+    DB_STMT_SEL_BY_IMEI,</span><br><span>         DB_STMT_UPD_VLR_BY_ID,</span><br><span>       DB_STMT_UPD_SGSN_BY_ID,</span><br><span style="color: hsl(120, 100%, 40%);">+       DB_STMT_UPD_IMEI_BY_ID,</span><br><span>      DB_STMT_AUC_BY_IMSI,</span><br><span>         DB_STMT_AUC_UPD_SQN,</span><br><span>         DB_STMT_UPD_PURGE_CS_BY_IMSI,</span><br><span>@@ -71,6 +73,7 @@</span><br><span>    char            imsi[GSM23003_IMSI_MAX_DIGITS+1];</span><br><span>    char            msisdn[GT_MAX_DIGITS+1];</span><br><span>     /* imeisv? */</span><br><span style="color: hsl(120, 100%, 40%);">+ char            imei[32];</span><br><span>    char            vlr_number[32];</span><br><span>      char            sgsn_number[32];</span><br><span>     char            sgsn_address[GT_MAX_DIGITS+1];</span><br><span>@@ -122,6 +125,7 @@</span><br><span>                                     const char *msisdn);</span><br><span> int db_subscr_update_aud_by_id(struct db_context *dbc, int64_t subscr_id,</span><br><span>                               const struct sub_auth_data_str *aud);</span><br><span style="color: hsl(120, 100%, 40%);">+int db_subscr_update_imei_by_id(struct db_context *dbc, int64_t subscr_id, const char *imei);</span><br><span> </span><br><span> int db_subscr_get_by_imsi(struct db_context *dbc, const char *imsi,</span><br><span>                         struct hlr_subscriber *subscr);</span><br><span>@@ -129,10 +133,10 @@</span><br><span>                        struct hlr_subscriber *subscr);</span><br><span> int db_subscr_get_by_id(struct db_context *dbc, int64_t id,</span><br><span>                   struct hlr_subscriber *subscr);</span><br><span style="color: hsl(120, 100%, 40%);">+int db_subscr_get_by_imei(struct db_context *dbc, const char *imei, struct hlr_subscriber *subscr);</span><br><span> int db_subscr_nam(struct db_context *dbc, const char *imsi, bool nam_val, bool is_ps);</span><br><span> int db_subscr_lu(struct db_context *dbc, int64_t subscr_id,</span><br><span>                 const char *vlr_or_sgsn_number, bool is_ps);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> int db_subscr_purge(struct db_context *dbc, const char *by_imsi,</span><br><span>                bool purge_val, bool is_ps);</span><br><span> </span><br><span>diff --git a/src/db_hlr.c b/src/db_hlr.c</span><br><span>index c97cd82..1c24e19 100644</span><br><span>--- a/src/db_hlr.c</span><br><span>+++ b/src/db_hlr.c</span><br><span>@@ -386,6 +386,55 @@</span><br><span>     return ret;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Set a subscriber's IMEI in the HLR database.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in,out] dbc  database context.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] subscr_id  ID of the subscriber in the HLR db.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] imei  ASCII string of identifier digits, or NULL to remove the IMEI.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 on success, -ENOENT when the given subscriber does not exist,</span><br><span style="color: hsl(120, 100%, 40%);">+ *         -EIO on database errors.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int db_subscr_update_imei_by_id(struct db_context *dbc, int64_t subscr_id, const char *imei)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int rc, ret = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      sqlite3_stmt *stmt = dbc->stmt[DB_STMT_UPD_IMEI_BY_ID];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (imei && !osmo_imei_str_valid(imei)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             LOGP(DAUC, LOGL_ERROR, "Cannot update subscriber ID=%" PRId64 ": invalid IMEI: '%s'\n", subscr_id,</span><br><span style="color: hsl(120, 100%, 40%);">+                     imei);</span><br><span style="color: hsl(120, 100%, 40%);">+           return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!db_bind_int64(stmt, "$subscriber_id", subscr_id))</span><br><span style="color: hsl(120, 100%, 40%);">+              return -EIO;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (imei && !db_bind_text(stmt, "$imei", imei))</span><br><span style="color: hsl(120, 100%, 40%);">+             return -EIO;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* execute the statement */</span><br><span style="color: hsl(120, 100%, 40%);">+   rc = sqlite3_step(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (rc != SQLITE_DONE) {</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGP(DAUC, LOGL_ERROR, "Update IMEI for subscriber ID=%" PRId64 ": SQL Error: %s\n", subscr_id,</span><br><span style="color: hsl(120, 100%, 40%);">+                sqlite3_errmsg(dbc->db));</span><br><span style="color: hsl(120, 100%, 40%);">+             ret = -EIO;</span><br><span style="color: hsl(120, 100%, 40%);">+           goto out;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* verify execution result */</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = sqlite3_changes(dbc->db);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGP(DAUC, LOGL_ERROR, "Cannot update IMEI for subscriber ID=%" PRId64 ": no such subscriber\n",</span><br><span style="color: hsl(120, 100%, 40%);">+               subscr_id);</span><br><span style="color: hsl(120, 100%, 40%);">+              ret = -ENOENT;</span><br><span style="color: hsl(120, 100%, 40%);">+        } else if (rc != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+         LOGP(DAUC, LOGL_ERROR, "Update IMEI for subscriber ID=%" PRId64 ": SQL modified %d rows (expected 1)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+               subscr_id, rc);</span><br><span style="color: hsl(120, 100%, 40%);">+          ret = -EIO;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+out:</span><br><span style="color: hsl(120, 100%, 40%);">+     db_remove_reset(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+        return ret;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Common code for db_subscr_get_by_*() functions. */</span><br><span> static int db_sel(struct db_context *dbc, sqlite3_stmt *stmt, struct hlr_subscriber *subscr,</span><br><span>              const char **err)</span><br><span>@@ -415,18 +464,19 @@</span><br><span>  subscr->id = sqlite3_column_int64(stmt, 0);</span><br><span>       copy_sqlite3_text_to_buf(subscr->imsi, stmt, 1);</span><br><span>  copy_sqlite3_text_to_buf(subscr->msisdn, stmt, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ copy_sqlite3_text_to_buf(subscr->imei, stmt, 3);</span><br><span>  /* FIXME: These should all be BLOBs as they might contain NUL */</span><br><span style="color: hsl(0, 100%, 40%);">-        copy_sqlite3_text_to_buf(subscr->vlr_number, stmt, 3);</span><br><span style="color: hsl(0, 100%, 40%);">-       copy_sqlite3_text_to_buf(subscr->sgsn_number, stmt, 4);</span><br><span style="color: hsl(0, 100%, 40%);">-      copy_sqlite3_text_to_buf(subscr->sgsn_address, stmt, 5);</span><br><span style="color: hsl(0, 100%, 40%);">-     subscr->periodic_lu_timer = sqlite3_column_int(stmt, 6);</span><br><span style="color: hsl(0, 100%, 40%);">-     subscr->periodic_rau_tau_timer = sqlite3_column_int(stmt, 7);</span><br><span style="color: hsl(0, 100%, 40%);">-        subscr->nam_cs = sqlite3_column_int(stmt, 8);</span><br><span style="color: hsl(0, 100%, 40%);">-        subscr->nam_ps = sqlite3_column_int(stmt, 9);</span><br><span style="color: hsl(0, 100%, 40%);">-        subscr->lmsi = sqlite3_column_int(stmt, 10);</span><br><span style="color: hsl(0, 100%, 40%);">- subscr->ms_purged_cs = sqlite3_column_int(stmt, 11);</span><br><span style="color: hsl(0, 100%, 40%);">- subscr->ms_purged_ps = sqlite3_column_int(stmt, 12);</span><br><span style="color: hsl(0, 100%, 40%);">- last_lu_seen_str = (const char *)sqlite3_column_text(stmt, 13);</span><br><span style="color: hsl(120, 100%, 40%);">+       copy_sqlite3_text_to_buf(subscr->vlr_number, stmt, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+     copy_sqlite3_text_to_buf(subscr->sgsn_number, stmt, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+    copy_sqlite3_text_to_buf(subscr->sgsn_address, stmt, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+   subscr->periodic_lu_timer = sqlite3_column_int(stmt, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+   subscr->periodic_rau_tau_timer = sqlite3_column_int(stmt, 8);</span><br><span style="color: hsl(120, 100%, 40%);">+      subscr->nam_cs = sqlite3_column_int(stmt, 9);</span><br><span style="color: hsl(120, 100%, 40%);">+      subscr->nam_ps = sqlite3_column_int(stmt, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+     subscr->lmsi = sqlite3_column_int(stmt, 11);</span><br><span style="color: hsl(120, 100%, 40%);">+       subscr->ms_purged_cs = sqlite3_column_int(stmt, 12);</span><br><span style="color: hsl(120, 100%, 40%);">+       subscr->ms_purged_ps = sqlite3_column_int(stmt, 13);</span><br><span style="color: hsl(120, 100%, 40%);">+       last_lu_seen_str = (const char *)sqlite3_column_text(stmt, 14);</span><br><span>      if (last_lu_seen_str && last_lu_seen_str[0] != '\0') {</span><br><span>               if (strptime(last_lu_seen_str, DB_LAST_LU_SEEN_FMT, &tm) == NULL) {</span><br><span>                      LOGP(DAUC, LOGL_ERROR, "Cannot parse last LU timestamp '%s' of subscriber with IMSI='%s': %s\n",</span><br><span>@@ -530,6 +580,28 @@</span><br><span>    return rc;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Retrieve subscriber data from the HLR database.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in,out] dbc  database context.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] imei  ASCII string of identifier digits</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] subscr  place retrieved data in this struct.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 on success, -ENOENT if no such subscriber was found, -EIO on</span><br><span style="color: hsl(120, 100%, 40%);">+ *          database error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int db_subscr_get_by_imei(struct db_context *dbc, const char *imei, struct hlr_subscriber *subscr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   sqlite3_stmt *stmt = dbc->stmt[DB_STMT_SEL_BY_IMEI];</span><br><span style="color: hsl(120, 100%, 40%);">+       const char *err;</span><br><span style="color: hsl(120, 100%, 40%);">+      int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!db_bind_text(stmt, NULL, imei))</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EIO;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = db_sel(dbc, stmt, subscr, &err);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               LOGP(DAUC, LOGL_ERROR, "Cannot read subscriber from db: IMEI=%s: %s\n", imei, err);</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! You should use hlr_subscr_nam() instead; enable or disable PS or CS for a</span><br><span>  * subscriber without notifying GSUP clients.</span><br><span>  * \param[in,out] dbc  database context.</span><br><span>diff --git a/tests/db/db_test.c b/tests/db/db_test.c</span><br><span>index c4ed6ed..cbc1a7d 100644</span><br><span>--- a/tests/db/db_test.c</span><br><span>+++ b/tests/db/db_test.c</span><br><span>@@ -148,6 +148,7 @@</span><br><span>     Pd(id);</span><br><span>      Ps(imsi);</span><br><span>    Ps(msisdn);</span><br><span style="color: hsl(120, 100%, 40%);">+   Ps(imei);</span><br><span>    Ps(vlr_number);</span><br><span>      Ps(sgsn_number);</span><br><span>     Ps(sgsn_address);</span><br><span>@@ -296,6 +297,15 @@</span><br><span>     ASSERT_RC(db_subscr_update_msisdn_by_imsi(dbc, "foobar", "99"), -ENOENT);</span><br><span>        ASSERT_SEL(msisdn, "99", -ENOENT);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+      comment("Set valid / invalid IMEI");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      ASSERT_RC(db_subscr_update_imei_by_id(dbc, id0, "12345678901234"), 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      ASSERT_SEL(imei, "12345678901234", 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    ASSERT_RC(db_subscr_update_imei_by_id(dbc, id0, "123456789012345"), -EINVAL); /* too long */</span><br><span style="color: hsl(120, 100%, 40%);">+        ASSERT_SEL(imei, "12345678901234", 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      ASSERT_SEL(imei, "123456789012345", -ENOENT);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>    comment("Set / unset nam_cs and nam_ps");</span><br><span> </span><br><span>      /*                                nam_val, is_ps */</span><br><span>diff --git a/tests/db/db_test.err b/tests/db/db_test.err</span><br><span>index 1d34045..2b8398f 100644</span><br><span>--- a/tests/db/db_test.err</span><br><span>+++ b/tests/db/db_test.err</span><br><span>@@ -227,6 +227,33 @@</span><br><span> DAUC Cannot read subscriber from db: MSISDN='99': No such subscriber</span><br><span> </span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+--- Set valid / invalid IMEI</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+db_subscr_update_imei_by_id(dbc, id0, "12345678901234") --> 0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+db_subscr_get_by_imei(dbc, "12345678901234", &g_subscr) --> 0</span><br><span style="color: hsl(120, 100%, 40%);">+struct hlr_subscriber {</span><br><span style="color: hsl(120, 100%, 40%);">+  .id = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+  .imsi = '123456789000000',</span><br><span style="color: hsl(120, 100%, 40%);">+  .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+db_subscr_update_imei_by_id(dbc, id0, "123456789012345") --> -EINVAL</span><br><span style="color: hsl(120, 100%, 40%);">+DAUC Cannot update subscriber ID=1: invalid IMEI: '123456789012345'</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+db_subscr_get_by_imei(dbc, "12345678901234", &g_subscr) --> 0</span><br><span style="color: hsl(120, 100%, 40%);">+struct hlr_subscriber {</span><br><span style="color: hsl(120, 100%, 40%);">+  .id = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+  .imsi = '123456789000000',</span><br><span style="color: hsl(120, 100%, 40%);">+  .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+db_subscr_get_by_imei(dbc, "123456789012345", &g_subscr) --> -ENOENT</span><br><span style="color: hsl(120, 100%, 40%);">+DAUC Cannot read subscriber from db: IMEI=123456789012345: No such subscriber</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> --- Set / unset nam_cs and nam_ps</span><br><span> </span><br><span> db_subscr_nam(dbc, imsi0, false, true) --> 0</span><br><span>@@ -236,6 +263,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .nam_ps = false,</span><br><span> }</span><br><span> </span><br><span>@@ -246,6 +274,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .nam_cs = false,</span><br><span>   .nam_ps = false,</span><br><span> }</span><br><span>@@ -257,6 +286,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .nam_ps = false,</span><br><span> }</span><br><span> </span><br><span>@@ -267,6 +297,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span> }</span><br><span> </span><br><span> </span><br><span>@@ -279,6 +310,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .nam_ps = false,</span><br><span> }</span><br><span> </span><br><span>@@ -289,6 +321,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .nam_ps = false,</span><br><span> }</span><br><span> </span><br><span>@@ -299,6 +332,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .nam_cs = false,</span><br><span>   .nam_ps = false,</span><br><span> }</span><br><span>@@ -310,6 +344,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .nam_cs = false,</span><br><span>   .nam_ps = false,</span><br><span> }</span><br><span>@@ -321,6 +356,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .nam_cs = false,</span><br><span> }</span><br><span> </span><br><span>@@ -331,6 +367,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .nam_cs = false,</span><br><span> }</span><br><span> </span><br><span>@@ -341,6 +378,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span> }</span><br><span> </span><br><span> db_subscr_nam(dbc, imsi0, true, false) --> 0</span><br><span>@@ -350,6 +388,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span> }</span><br><span> </span><br><span> </span><br><span>@@ -380,6 +419,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .sgsn_number = '5952',</span><br><span> }</span><br><span> </span><br><span>@@ -390,6 +430,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .vlr_number = '712',</span><br><span>   .sgsn_number = '5952',</span><br><span> }</span><br><span>@@ -404,6 +445,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .vlr_number = '712',</span><br><span>   .sgsn_number = '111',</span><br><span> }</span><br><span>@@ -415,6 +457,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .vlr_number = '712',</span><br><span>   .sgsn_number = '111',</span><br><span> }</span><br><span>@@ -426,6 +469,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .vlr_number = '222',</span><br><span>   .sgsn_number = '111',</span><br><span> }</span><br><span>@@ -437,6 +481,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .vlr_number = '222',</span><br><span>   .sgsn_number = '111',</span><br><span> }</span><br><span>@@ -451,6 +496,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .vlr_number = '222',</span><br><span> }</span><br><span> </span><br><span>@@ -461,6 +507,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span> }</span><br><span> </span><br><span> db_subscr_lu(dbc, id0, "111", true) --> 0</span><br><span>@@ -472,6 +519,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .vlr_number = '222',</span><br><span>   .sgsn_number = '111',</span><br><span> }</span><br><span>@@ -483,6 +531,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .vlr_number = '222',</span><br><span> }</span><br><span> </span><br><span>@@ -493,6 +542,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span> }</span><br><span> </span><br><span> </span><br><span>@@ -517,6 +567,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .ms_purged_ps = true,</span><br><span> }</span><br><span> </span><br><span>@@ -527,6 +578,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .ms_purged_cs = true,</span><br><span>   .ms_purged_ps = true,</span><br><span> }</span><br><span>@@ -538,6 +590,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .ms_purged_ps = true,</span><br><span> }</span><br><span> </span><br><span>@@ -548,6 +601,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span> }</span><br><span> </span><br><span> </span><br><span>@@ -560,6 +614,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .ms_purged_ps = true,</span><br><span> }</span><br><span> </span><br><span>@@ -570,6 +625,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .ms_purged_ps = true,</span><br><span> }</span><br><span> </span><br><span>@@ -580,6 +636,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span> }</span><br><span> </span><br><span> db_subscr_purge(dbc, imsi0, false, true) --> 0</span><br><span>@@ -589,6 +646,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span> }</span><br><span> </span><br><span> db_subscr_purge(dbc, imsi0, true, false) --> 0</span><br><span>@@ -598,6 +656,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .ms_purged_cs = true,</span><br><span> }</span><br><span> </span><br><span>@@ -608,6 +667,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span>   .ms_purged_cs = true,</span><br><span> }</span><br><span> </span><br><span>@@ -618,6 +678,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span> }</span><br><span> </span><br><span> db_subscr_purge(dbc, imsi0, false, false) --> 0</span><br><span>@@ -627,6 +688,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span> }</span><br><span> </span><br><span> </span><br><span>@@ -661,6 +723,7 @@</span><br><span>   .id = 1,</span><br><span>   .imsi = '123456789000000',</span><br><span>   .msisdn = '543210123456789',</span><br><span style="color: hsl(120, 100%, 40%);">+  .imei = '12345678901234',</span><br><span> }</span><br><span> </span><br><span> db_subscr_delete_by_id(dbc, id0) --> 0</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/12525">change 12525</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/12525"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-hlr </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: If232c80bea35d5c6864b889ae92d477eeaa3f45d </div>
<div style="display:none"> Gerrit-Change-Number: 12525 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: osmith <osmith@sysmocom.de> </div>