diff --git a/openbsc/include/openbsc/db.h b/openbsc/include/openbsc/db.h index f1c2def92..6699a8600 100644 --- a/openbsc/include/openbsc/db.h +++ b/openbsc/include/openbsc/db.h @@ -47,6 +47,7 @@ int db_subscriber_assoc_imei(struct gsm_subscriber *subscriber, char *imei); int db_subscriber_delete(struct gsm_subscriber *subscriber); int db_sync_equipment(struct gsm_equipment *equip); int db_subscriber_update(struct gsm_subscriber *subscriber); +int db_subscriber_list_active(void (*list_cb)(struct gsm_subscriber*,void*), void*); /* auth info */ int db_get_authinfo_for_subscr(struct gsm_auth_info *ainfo, diff --git a/openbsc/src/libmsc/ctrl_commands.c b/openbsc/src/libmsc/ctrl_commands.c index b66cece8e..58558fd9f 100644 --- a/openbsc/src/libmsc/ctrl_commands.c +++ b/openbsc/src/libmsc/ctrl_commands.c @@ -140,11 +140,40 @@ static int set_subscriber_delete(struct ctrl_cmd *cmd, void *data) } CTRL_CMD_DEFINE(subscriber_delete, "subscriber-delete-v1"); +static int verify_subscriber_list(struct ctrl_cmd *cmd, const char *value, void *d) +{ + return 1; +} + +static int set_subscriber_list(struct ctrl_cmd *cmd, void *d) +{ + cmd->reply = "Get only attribute"; + return CTRL_CMD_ERROR; +} + +static void list_cb(struct gsm_subscriber *subscr, void *d) +{ + char **data = (char **) d; + *data = talloc_asprintf_append(*data, "%s,%s\n", + subscr->imsi, subscr->extension); +} + +static int get_subscriber_list(struct ctrl_cmd *cmd, void *d) +{ + cmd->reply = talloc_strdup(cmd, ""); + + db_subscriber_list_active(list_cb, &cmd->reply); + printf("%s\n", cmd->reply); + return CTRL_CMD_REPLY; +} +CTRL_CMD_DEFINE(subscriber_list, "subscriber-list-active-v1"); + int msc_ctrl_cmds_install(void) { int rc = 0; rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_subscriber_modify); rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_subscriber_delete); + rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_subscriber_list); return rc; } diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index a21258d14..bfa4e75a0 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -902,6 +902,39 @@ int db_subscriber_delete(struct gsm_subscriber *subscr) return 0; } +/** + * List all the authorized and non-expired subscribers. The callback will + * be called one by one. The subscr argument is not fully initialize and + * subscr_get/subscr_put must not be called. The passed in pointer will be + * deleted after the callback by the database call. + */ +int db_subscriber_list_active(void (*cb)(struct gsm_subscriber*,void*), void *closure) +{ + dbi_result result; + + result = dbi_conn_queryf(conn, + "SELECT * from Subscriber WHERE LAC != 0 AND authorized = 1"); + if (!result) { + LOGP(DDB, LOGL_ERROR, "Failed to list active subscribers\n"); + return -1; + } + + while (dbi_result_next_row(result)) { + struct gsm_subscriber *subscr; + + subscr = subscr_alloc(); + subscr->id = dbi_result_get_ulonglong(result, "id"); + db_set_from_query(subscr, result); + cb(subscr, closure); + OSMO_ASSERT(subscr->use_count == 1); + llist_del(&subscr->entry); + talloc_free(subscr); + } + + dbi_result_free(result); + return 0; +} + int db_sync_equipment(struct gsm_equipment *equip) { dbi_result result; diff --git a/openbsc/tests/ctrl_test_runner.py b/openbsc/tests/ctrl_test_runner.py index 56e95144a..60d90a7c1 100644 --- a/openbsc/tests/ctrl_test_runner.py +++ b/openbsc/tests/ctrl_test_runner.py @@ -341,6 +341,13 @@ class TestCtrlNITB(TestCtrlBase): self.assertEquals(r['mtype'], 'ERROR') self.assertEquals(r['error'], 'Failed to find subscriber') + def testSubscriberList(self): + # TODO. Add command to mark a subscriber as active + r = self.do_get('subscriber-list-active-v1') + self.assertEquals(r['mtype'], 'GET_REPLY') + self.assertEquals(r['var'], 'subscriber-list-active-v1') + self.assertEquals(r['value'], None) + class TestCtrlNAT(TestCtrlBase): def ctrl_command(self):