<p>keith has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-hlr/+/22311">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Add vty command to show summary of all or filtered subscribers<br><br>Adds the following commands:<br><br>show subscribers all - Display summary of all entries in HLR<br>show subscribers filter [....] As above but filter on<br>show subscribers last seen - Display only subscribers with<br>time since Last LU update seen entries and sorts by LU..<br><br>Change-Id: I7f0573381a6d0d13841ac6d42d50f0e8389decf4<br>---<br>M include/osmocom/hlr/db.h<br>M src/db.c<br>M src/db_hlr.c<br>M src/hlr_vty_subscr.c<br>4 files changed, 219 insertions(+), 5 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/11/22311/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/hlr/db.h b/include/osmocom/hlr/db.h</span><br><span>index ca336a0..d5e7612 100644</span><br><span>--- a/include/osmocom/hlr/db.h</span><br><span>+++ b/include/osmocom/hlr/db.h</span><br><span>@@ -8,6 +8,13 @@</span><br><span> struct hlr;</span><br><span> </span><br><span> enum stmt_idx {</span><br><span style="color: hsl(120, 100%, 40%);">+   DB_STMT_SEL_ALL,</span><br><span style="color: hsl(120, 100%, 40%);">+      DB_STMT_SEL_ALL_ORDER_LAST_SEEN,</span><br><span style="color: hsl(120, 100%, 40%);">+      DB_STMT_SEL_FILTER,</span><br><span style="color: hsl(120, 100%, 40%);">+   DB_STMT_SEL_FILTER_MSISDN,</span><br><span style="color: hsl(120, 100%, 40%);">+    DB_STMT_SEL_FILTER_IMSI,</span><br><span style="color: hsl(120, 100%, 40%);">+      DB_STMT_SEL_FILTER_CS,</span><br><span style="color: hsl(120, 100%, 40%);">+        DB_STMT_SEL_FILTER_PS,</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>@@ -148,6 +155,8 @@</span><br><span> int db_subscr_exists_by_imsi(struct db_context *dbc, const char *imsi);</span><br><span> int db_subscr_exists_by_msisdn(struct db_context *dbc, const char *msisdn);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int db_subscrs_get_print(struct vty *vty, struct db_context *dbc, const char *type, const char *filter,</span><br><span style="color: hsl(120, 100%, 40%);">+                     void (*dump_cb)(struct vty *, struct hlr_subscriber *subscr), int *count, const char **err);</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> int db_subscr_get_by_msisdn(struct db_context *dbc, const char *msisdn,</span><br><span>diff --git a/src/db.c b/src/db.c</span><br><span>index 5ec20e2..8cf0e50 100644</span><br><span>--- a/src/db.c</span><br><span>+++ b/src/db.c</span><br><span>@@ -51,6 +51,14 @@</span><br><span>       "sgsn_via_proxy"</span><br><span> </span><br><span> static const char *stmt_sql[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+   [DB_STMT_SEL_ALL] = "SELECT " SEL_COLUMNS " FROM subscriber;",</span><br><span style="color: hsl(120, 100%, 40%);">+    [DB_STMT_SEL_ALL_ORDER_LAST_SEEN] = "SELECT " SEL_COLUMNS " FROM subscriber "</span><br><span style="color: hsl(120, 100%, 40%);">+             "WHERE last_lu_seen IS NOT NULL ORDER BY last_lu_seen;",</span><br><span style="color: hsl(120, 100%, 40%);">+    [DB_STMT_SEL_FILTER] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE msisdn LIKE $search ORDER BY msisdn",</span><br><span style="color: hsl(120, 100%, 40%);">+        [DB_STMT_SEL_FILTER_MSISDN] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE msisdn LIKE $search ORDER BY msisdn",</span><br><span style="color: hsl(120, 100%, 40%);">+ [DB_STMT_SEL_FILTER_IMSI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imsi LIKE $search ORDER BY imsi",</span><br><span style="color: hsl(120, 100%, 40%);">+       [DB_STMT_SEL_FILTER_CS] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE nam_cs = $search ORDER BY last_lu_seen",</span><br><span style="color: hsl(120, 100%, 40%);">+  [DB_STMT_SEL_FILTER_PS] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE nam_ps = $search ORDER BY last_lu_seen",</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>diff --git a/src/db_hlr.c b/src/db_hlr.c</span><br><span>index 6ba43c2..6a2e115 100644</span><br><span>--- a/src/db_hlr.c</span><br><span>+++ b/src/db_hlr.c</span><br><span>@@ -624,6 +624,95 @@</span><br><span>                      msisdn, err);</span><br><span>   return rc;</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] vty  vty.</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] filter_type  ASCII string of identifier type to search.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] filter  ASCII string to search.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] dump_cb  pointer to vty print function.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in,out] count  counter for number of matched subscribers.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in,our] err</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 on success, -ENOENT if no 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_subscrs_get_print(struct vty *vty, struct db_context *dbc, const char *filter_type, const char *filter,</span><br><span style="color: hsl(120, 100%, 40%);">+                     void (*dump_cb)(struct vty *, struct hlr_subscriber *subscr), int *count, const char **err)</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%);">+   char search[256];</span><br><span style="color: hsl(120, 100%, 40%);">+     int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct hlr_subscriber sub, *subscr;</span><br><span style="color: hsl(120, 100%, 40%);">+   subscr = &sub;</span><br><span style="color: hsl(120, 100%, 40%);">+    bool show_ls = false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!filter_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+           stmt = dbc->stmt[DB_STMT_SEL_ALL];</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (strcmp(filter_type, "imsi") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              stmt = dbc->stmt[DB_STMT_SEL_FILTER_IMSI];</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (strcmp(filter_type, "msisdn") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+            stmt = dbc->stmt[DB_STMT_SEL_FILTER_MSISDN];</span><br><span style="color: hsl(120, 100%, 40%);">+       } else if (strcmp(filter_type, "cs") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                stmt = dbc->stmt[DB_STMT_SEL_FILTER_CS];</span><br><span style="color: hsl(120, 100%, 40%);">+   } else if (strcmp(filter_type, "ps") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                stmt = dbc->stmt[DB_STMT_SEL_FILTER_PS];</span><br><span style="color: hsl(120, 100%, 40%);">+   } else if (strcmp(filter_type, "last_lu_seen") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              show_ls = true;</span><br><span style="color: hsl(120, 100%, 40%);">+               stmt = dbc->stmt[DB_STMT_SEL_ALL_ORDER_LAST_SEEN];</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (filter && strcmp(filter_type, "last_lu_seen") != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+           if (strcmp(filter, "on") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    sprintf(search, "%s", "1");</span><br><span style="color: hsl(120, 100%, 40%);">+               } else if (strcmp(filter, "off") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    sprintf(search, "%s", "0");</span><br><span style="color: hsl(120, 100%, 40%);">+               } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      sprintf(search, "%%%s%%", filter);</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!db_bind_text(stmt, "$search", search)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       *err = sqlite3_errmsg(dbc->db);</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%);">+     }</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (rc == SQLITE_DONE) {</span><br><span style="color: hsl(120, 100%, 40%);">+              db_remove_reset(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+                *err = "No matching subscriber(s)";</span><br><span style="color: hsl(120, 100%, 40%);">+         return -ENOENT;</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%);">+   while (rc == SQLITE_ROW) {</span><br><span style="color: hsl(120, 100%, 40%);">+            *subscr = (struct hlr_subscriber){};</span><br><span style="color: hsl(120, 100%, 40%);">+          subscr->id = sqlite3_column_int64(stmt, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                copy_sqlite3_text_to_buf(subscr->imsi, stmt, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+           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 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%);">+             if (show_ls)</span><br><span style="color: hsl(120, 100%, 40%);">+                  parse_last_lu_seen(&subscr->last_lu_seen, (const char *)sqlite3_column_text(stmt, 14),</span><br><span style="color: hsl(120, 100%, 40%);">+                                    subscr->imsi, "CS");</span><br><span style="color: hsl(120, 100%, 40%);">+          dump_cb(vty, subscr);</span><br><span style="color: hsl(120, 100%, 40%);">+         rc = sqlite3_step(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+              (*count)++;</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_remove_reset(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (rc != SQLITE_DONE) {</span><br><span style="color: hsl(120, 100%, 40%);">+              *err = sqlite3_errmsg(dbc->db);</span><br><span style="color: hsl(120, 100%, 40%);">+            return -EIO;</span><br><span style="color: hsl(120, 100%, 40%);">+  } else if (rc == SQLITE_DONE) {</span><br><span style="color: hsl(120, 100%, 40%);">+               *err = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+          return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              *err = sqlite3_errmsg(dbc->db);</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGP(DAUC, LOGL_ERROR, "Cannot read subscribers from db:: %s\n", *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> </span><br><span> /*! Retrieve subscriber data from the HLR database.</span><br><span>  * \param[in,out] dbc  database context.</span><br><span>diff --git a/src/hlr_vty_subscr.c b/src/hlr_vty_subscr.c</span><br><span>index f5066c1..856586e 100644</span><br><span>--- a/src/hlr_vty_subscr.c</span><br><span>+++ b/src/hlr_vty_subscr.c</span><br><span>@@ -44,13 +44,14 @@</span><br><span>       return buf;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void dump_last_lu_seen(struct vty *vty, const char *domain_label, time_t last_lu_seen)</span><br><span style="color: hsl(120, 100%, 40%);">+static void dump_last_lu_seen(struct vty *vty, const char *domain_label, time_t last_lu_seen, bool only_age)</span><br><span> {</span><br><span>         uint32_t age;</span><br><span>        char datebuf[32];</span><br><span>    if (!last_lu_seen)</span><br><span>           return;</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, "    last LU seen on %s: %s", domain_label, get_datestr(&last_lu_seen, datebuf, sizeof(datebuf)));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!only_age)</span><br><span style="color: hsl(120, 100%, 40%);">+                vty_out(vty, "    last LU seen on %s: %s", domain_label, get_datestr(&last_lu_seen, datebuf, sizeof(datebuf)));</span><br><span>        if (!timestamp_age(&last_lu_seen, &age))</span><br><span>             vty_out(vty, " (invalid timestamp)%s", VTY_NEWLINE);</span><br><span>       else {</span><br><span>@@ -64,7 +65,10 @@</span><br><span>          UNIT_AGO("h", 60*60);</span><br><span>              UNIT_AGO("m", 60);</span><br><span>                 UNIT_AGO("s", 1);</span><br><span style="color: hsl(0, 100%, 40%);">-             vty_out(vty, " ago)%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!only_age)</span><br><span style="color: hsl(120, 100%, 40%);">+                        vty_out(vty, " ago)%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+               else</span><br><span style="color: hsl(120, 100%, 40%);">+                  vty_out(vty, " ago)");</span><br><span> #undef UNIT_AGO</span><br><span>  }</span><br><span> }</span><br><span>@@ -108,8 +112,8 @@</span><br><span>                 vty_out(vty, "    PS disabled%s", VTY_NEWLINE);</span><br><span>    if (subscr->ms_purged_ps)</span><br><span>                 vty_out(vty, "    PS purged%s", VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">- dump_last_lu_seen(vty, "CS", subscr->last_lu_seen);</span><br><span style="color: hsl(0, 100%, 40%);">-        dump_last_lu_seen(vty, "PS", subscr->last_lu_seen_ps);</span><br><span style="color: hsl(120, 100%, 40%);">+   dump_last_lu_seen(vty, "CS", subscr->last_lu_seen, false);</span><br><span style="color: hsl(120, 100%, 40%);">+       dump_last_lu_seen(vty, "PS", subscr->last_lu_seen_ps, false);</span><br><span> </span><br><span>       if (!*subscr->imsi)</span><br><span>               return;</span><br><span>@@ -159,6 +163,27 @@</span><br><span>       }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void subscr_dump_summary_vty(struct vty *vty, struct hlr_subscriber *subscr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    vty_out(vty, "%-5"PRIu64"  %-12s  %-16s", subscr->id,</span><br><span style="color: hsl(120, 100%, 40%);">+          *subscr->msisdn ? subscr->msisdn : "none",</span><br><span style="color: hsl(120, 100%, 40%);">+            *subscr->imsi ? subscr->imsi : "none");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (*subscr->imei) {</span><br><span style="color: hsl(120, 100%, 40%);">+               char checksum = osmo_luhn(subscr->imei, 14);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (checksum == -EINVAL)</span><br><span style="color: hsl(120, 100%, 40%);">+                      vty_out(vty, "  %-14s (INVALID LENGTH!)", subscr->imei);</span><br><span style="color: hsl(120, 100%, 40%);">+         else</span><br><span style="color: hsl(120, 100%, 40%);">+                  vty_out(vty, "  %-14s%c", subscr->imei, checksum);</span><br><span style="color: hsl(120, 100%, 40%);">+       } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              vty_out(vty,"   ------------- ");</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     vty_out(vty, "   %-2s%-2s  ", subscr->nam_cs ? "CS" : "", subscr->nam_ps ? "PS" : "");</span><br><span style="color: hsl(120, 100%, 40%);">+        if (subscr->last_lu_seen)</span><br><span style="color: hsl(120, 100%, 40%);">+          dump_last_lu_seen(vty, "CS", subscr->last_lu_seen, true);</span><br><span style="color: hsl(120, 100%, 40%);">+        vty_out_newline(vty);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int get_subscr_by_argv(struct vty *vty, const char *type, const char *id, struct hlr_subscriber *subscr)</span><br><span> {</span><br><span>   char imei_buf[GSM23003_IMEI_NUM_DIGITS_NO_CHK+1];</span><br><span>@@ -186,11 +211,48 @@</span><br><span>    return rc;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int get_subscrs(struct vty *vty, const char *filter_type, const char *filter)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  int rc = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+  int count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *err;</span><br><span style="color: hsl(120, 100%, 40%);">+      bool show_ls = (filter_type && strcmp(filter_type, "last_lu_seen") == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, "ID     MSISDN        IMSI              IMEI              NAM");</span><br><span style="color: hsl(120, 100%, 40%);">+       if (show_ls)</span><br><span style="color: hsl(120, 100%, 40%);">+          vty_out(vty, "    LAST SEEN");</span><br><span style="color: hsl(120, 100%, 40%);">+      vty_out_newline(vty);</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, "-----  ------------  ----------------  ----------------  -----");</span><br><span style="color: hsl(120, 100%, 40%);">+     if (show_ls)</span><br><span style="color: hsl(120, 100%, 40%);">+          vty_out(vty, "  ------------");</span><br><span style="color: hsl(120, 100%, 40%);">+     vty_out_newline(vty);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = db_subscrs_get_print(vty, g_hlr->dbc, filter_type, filter, subscr_dump_summary_vty, &count, &err);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (count > 40) {</span><br><span style="color: hsl(120, 100%, 40%);">+          vty_out(vty, "-----  ------------  ----------------  ----------------  -----");</span><br><span style="color: hsl(120, 100%, 40%);">+             if (show_ls)</span><br><span style="color: hsl(120, 100%, 40%);">+                  vty_out(vty, "  ------------");</span><br><span style="color: hsl(120, 100%, 40%);">+             vty_out_newline(vty);</span><br><span style="color: hsl(120, 100%, 40%);">+         vty_out(vty, "ID     MSISDN        IMSI              IMEI              NAM");</span><br><span style="color: hsl(120, 100%, 40%);">+               if (show_ls)</span><br><span style="color: hsl(120, 100%, 40%);">+                  vty_out(vty, "    LAST SEEN");</span><br><span style="color: hsl(120, 100%, 40%);">+              vty_out_newline(vty);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (count > 0)</span><br><span style="color: hsl(120, 100%, 40%);">+             vty_out(vty, " Subscribers Shown: %d%s", count, VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               vty_out(vty, "%% %s%s", err, VTY_NEWLINE);</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%);">+</span><br><span> #define SUBSCR_CMD "subscriber "</span><br><span> #define SUBSCR_CMD_HELP "Subscriber management commands\n"</span><br><span> #define SUBSCR_SHOW_HELP "Show subscriber information\n"</span><br><span style="color: hsl(120, 100%, 40%);">+#define SUBSCRS_SHOW_HELP "Show all subscribers (with filter possibility)\n"</span><br><span> </span><br><span> #define SUBSCR_ID "(imsi|msisdn|id|imei) IDENT"</span><br><span style="color: hsl(120, 100%, 40%);">+#define SUBSCR_FILTER "(imsi|msisdn) FILTER"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #define SUBSCR_ID_HELP \</span><br><span>         "Identify subscriber by IMSI\n" \</span><br><span>  "Identify subscriber by MSISDN (phone number)\n" \</span><br><span>@@ -225,6 +287,48 @@</span><br><span>       "show " SUBSCR_CMD SUBSCR_ID,</span><br><span>       SHOW_STR SUBSCR_SHOW_HELP SUBSCR_ID_HELP);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+DEFUN(subscriber_show_all,</span><br><span style="color: hsl(120, 100%, 40%);">+      subscriber_show_all_cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+      "show subscribers all",</span><br><span style="color: hsl(120, 100%, 40%);">+      SHOW_STR SUBSCRS_SHOW_HELP "Show summary of all subscribers\n")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (get_subscrs(vty, NULL, NULL))</span><br><span style="color: hsl(120, 100%, 40%);">+             return CMD_WARNING;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return CMD_SUCCESS;</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%);">+DEFUN(subscriber_show_filtered,</span><br><span style="color: hsl(120, 100%, 40%);">+      subscriber_show_filtered_cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+      "show subscribers filter " SUBSCR_FILTER,</span><br><span style="color: hsl(120, 100%, 40%);">+      SHOW_STR SUBSCRS_SHOW_HELP "Show summary of subscribers with filter\n"</span><br><span style="color: hsl(120, 100%, 40%);">+      "Filter by IMSI\n" "Filter by MSISDN\n" "String to match in msisdn or imsi\n")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      const char *filter_type = argv[0];</span><br><span style="color: hsl(120, 100%, 40%);">+    const char *filter = argv[1];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (get_subscrs(vty, filter_type, filter))</span><br><span style="color: hsl(120, 100%, 40%);">+            return CMD_WARNING;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return CMD_SUCCESS;</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%);">+ALIAS(subscriber_show_filtered, subscriber_show_filtered_cmd2,</span><br><span style="color: hsl(120, 100%, 40%);">+      "show subscribers filter (cs|ps) (on|off)",</span><br><span style="color: hsl(120, 100%, 40%);">+      SHOW_STR SUBSCR_SHOW_HELP "Show summary of all subscribers\n"</span><br><span style="color: hsl(120, 100%, 40%);">+      "Show Subscribers with NAM CS In/active\n" "Show Subscribers with NAM PS In/active\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+DEFUN(subscriber_show_order_last_seen, subscriber_show_order_last_seen_cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+      "show subscribers last seen",</span><br><span style="color: hsl(120, 100%, 40%);">+      SHOW_STR SUBSCR_SHOW_HELP "Show Subscribers Ordered by Last Seen Time\n"</span><br><span style="color: hsl(120, 100%, 40%);">+      "Show Subscribers Ordered by Last Seen Time\n")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   if (get_subscrs(vty, "last_lu_seen", NULL))</span><br><span style="color: hsl(120, 100%, 40%);">+         return CMD_WARNING;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return CMD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> DEFUN(subscriber_create,</span><br><span>       subscriber_create_cmd,</span><br><span>       SUBSCR_CMD "imsi IDENT create",</span><br><span>@@ -679,6 +783,10 @@</span><br><span> void hlr_vty_subscriber_init(void)</span><br><span> {</span><br><span>    install_element_ve(&subscriber_show_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+ install_element_ve(&subscriber_show_all_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+     install_element_ve(&subscriber_show_filtered_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+        install_element_ve(&subscriber_show_filtered_cmd2);</span><br><span style="color: hsl(120, 100%, 40%);">+       install_element_ve(&subscriber_show_order_last_seen_cmd);</span><br><span>        install_element_ve(&show_subscriber_cmd);</span><br><span>        install_element(ENABLE_NODE, &subscriber_create_cmd);</span><br><span>    install_element(ENABLE_NODE, &subscriber_delete_cmd);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-hlr/+/22311">change 22311</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/c/osmo-hlr/+/22311"/><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-Change-Id: I7f0573381a6d0d13841ac6d42d50f0e8389decf4 </div>
<div style="display:none"> Gerrit-Change-Number: 22311 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: keith <keith@rhizomatica.org> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>