summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ctrl.c357
-rw-r--r--src/ctrl.h6
-rw-r--r--tests/test_subscriber.ctrl625
-rw-r--r--tests/test_subscriber.sql8
-rw-r--r--tests/test_subscriber.vty9
-rw-r--r--tests/test_subscriber_errors.ctrl107
6 files changed, 1040 insertions, 72 deletions
diff --git a/src/ctrl.c b/src/ctrl.c
index b49765d..3e81661 100644
--- a/src/ctrl.c
+++ b/src/ctrl.c
@@ -21,87 +21,372 @@
*/
#include <stdbool.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <string.h>
-#include <osmocom/ctrl/control_cmd.h>
-#include <osmocom/ctrl/control_if.h>
+#include <osmocom/gsm/gsm23003.h>
#include <osmocom/ctrl/ports.h>
-#include "gsup_server.h"
-#include "logging.h"
-#include "db.h"
#include "hlr.h"
-#include "luop.h"
#include "ctrl.h"
+#include "db.h"
+
+#define SEL_BY "by-"
+#define SEL_BY_IMSI SEL_BY "imsi-"
+#define SEL_BY_MSISDN SEL_BY "msisdn-"
+#define SEL_BY_ID SEL_BY "id-"
-static int handle_cmd_ps(struct hlr *ctx, struct ctrl_cmd *cmd, bool enable)
+#define hexdump_buf(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf))
+
+static bool startswith(const char *str, const char *start)
{
- struct hlr_subscriber subscr;
+ return strncmp(str, start, strlen(start)) == 0;
+}
- if (db_subscr_get_by_imsi(ctx->dbc, cmd->value, &subscr) < 0) {
- cmd->reply = "Subscriber Unknown in HLR";
- return CTRL_CMD_ERROR;
+static int _get_subscriber(struct db_context *dbc,
+ const char *by_selector,
+ struct hlr_subscriber *subscr)
+{
+ const char *val;
+ if (startswith(by_selector, SEL_BY_IMSI)) {
+ val = by_selector + strlen(SEL_BY_IMSI);
+ if (!osmo_imsi_str_valid(val))
+ return -EINVAL;
+ return db_subscr_get_by_imsi(dbc, val, subscr);
+ }
+ if (startswith(by_selector, SEL_BY_MSISDN)) {
+ val = by_selector + strlen(SEL_BY_MSISDN);
+ if (!osmo_msisdn_str_valid(val))
+ return -EINVAL;
+ return db_subscr_get_by_msisdn(dbc, val, subscr);
}
+ if (startswith(by_selector, SEL_BY_ID)) {
+ int64_t id;
+ char *endptr;
+ val = by_selector + strlen(SEL_BY_ID);
+ if (*val == '+')
+ return -EINVAL;
+ errno = 0;
+ id = strtoll(val, &endptr, 10);
+ if (errno || *endptr)
+ return -EINVAL;
+ return db_subscr_get_by_id(dbc, id, subscr);
+ }
+ return -ENOTSUP;
+}
- if (hlr_subscr_nam(ctx, &subscr, enable, true) < 0) {
- cmd->reply = "Error updating DB";
- return CTRL_CMD_ERROR;
+static bool get_subscriber(struct db_context *dbc,
+ const char *by_selector,
+ struct hlr_subscriber *subscr,
+ struct ctrl_cmd *cmd)
+{
+ int rc = _get_subscriber(dbc, by_selector, subscr);
+ switch (rc) {
+ case 0:
+ return true;
+ case -ENOTSUP:
+ cmd->reply = "Not a known subscriber 'by-xxx-' selector.";
+ return false;
+ case -EINVAL:
+ cmd->reply = "Invalid value part of 'by-xxx-value' selector.";
+ return false;
+ case -ENOENT:
+ cmd->reply = "No such subscriber.";
+ return false;
+ default:
+ cmd->reply = "An unknown error has occured during get_subscriber().";
+ return false;
}
+}
- cmd->reply = "OK";
- return CTRL_CMD_REPLY;
+/* Optimization: if a subscriber operation is requested by-imsi, just return
+ * the IMSI right back. */
+static const char *get_subscriber_imsi(struct db_context *dbc,
+ const char *by_selector,
+ struct ctrl_cmd *cmd)
+{
+ static struct hlr_subscriber subscr;
+
+ if (startswith(by_selector, SEL_BY_IMSI))
+ return by_selector + strlen(SEL_BY_IMSI);
+ if (!get_subscriber(dbc, by_selector, &subscr, cmd))
+ return NULL;
+ return subscr.imsi;
+}
+
+/* printf fmt and arg to completely omit a string if it is empty. */
+#define FMT_S "%s%s%s%s"
+#define ARG_S(name, val) \
+ (val) && *(val) ? "\n" : "", \
+ (val) && *(val) ? name : "", \
+ (val) && *(val) ? "\t" : "", \
+ (val) && *(val) ? (val) : "" \
+
+/* printf fmt and arg to completely omit bool of given value. */
+#define FMT_BOOL "%s"
+#define ARG_BOOL(name, val) \
+ val ? "\n" name "\t1" : "\n" name "\t0"
+
+static void print_subscr_info(struct ctrl_cmd *cmd,
+ struct hlr_subscriber *subscr)
+{
+ ctrl_cmd_reply_printf(cmd,
+ "\nid\t%"PRIu64
+ FMT_S
+ FMT_S
+ FMT_BOOL
+ FMT_BOOL
+ FMT_S
+ FMT_S
+ FMT_S
+ FMT_BOOL
+ FMT_BOOL
+ "\nperiodic_lu_timer\t%u"
+ "\nperiodic_rau_tau_timer\t%u"
+ "\nlmsi\t%08x"
+ ,
+ subscr->id,
+ ARG_S("imsi", subscr->imsi),
+ ARG_S("msisdn", subscr->msisdn),
+ ARG_BOOL("nam_cs", subscr->nam_cs),
+ ARG_BOOL("nam_ps", subscr->nam_ps),
+ ARG_S("vlr_number", subscr->vlr_number),
+ ARG_S("sgsn_number", subscr->sgsn_number),
+ ARG_S("sgsn_address", subscr->sgsn_address),
+ ARG_BOOL("ms_purged_cs", subscr->ms_purged_cs),
+ ARG_BOOL("ms_purged_ps", subscr->ms_purged_ps),
+ subscr->periodic_lu_timer,
+ subscr->periodic_rau_tau_timer,
+ subscr->lmsi
+ );
+}
+
+static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data *aud)
+{
+ if (aud->algo == OSMO_AUTH_ALG_NONE)
+ return;
+ ctrl_cmd_reply_printf(cmd,
+ "\naud2g.algo\t%s"
+ "\naud2g.ki\t%s"
+ ,
+ osmo_auth_alg_name(aud->algo),
+ hexdump_buf(aud->u.gsm.ki));
}
-CTRL_CMD_DEFINE_WO_NOVRF(enable_ps, "enable-ps");
-static int set_enable_ps(struct ctrl_cmd *cmd, void *data)
+static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data *aud)
{
- return handle_cmd_ps(data, cmd, true);
+ if (aud->algo == OSMO_AUTH_ALG_NONE)
+ return;
+ ctrl_cmd_reply_printf(cmd,
+ "\naud3g.algo\t%s"
+ "\naud3g.k\t%s"
+ ,
+ osmo_auth_alg_name(aud->algo),
+ hexdump_buf(aud->u.umts.k));
+ /* hexdump uses a static string buffer, hence only one hexdump per
+ * printf(). */
+ ctrl_cmd_reply_printf(cmd,
+ "\naud3g.%s\t%s"
+ "\naud3g.ind_bitlen\t%u"
+ "\naud3g.sqn\t%"PRIu64
+ ,
+ aud->u.umts.opc_is_op? "op" : "opc",
+ hexdump_buf(aud->u.umts.opc),
+ aud->u.umts.ind_bitlen,
+ aud->u.umts.sqn);
}
-CTRL_CMD_DEFINE_WO_NOVRF(disable_ps, "disable-ps");
-static int set_disable_ps(struct ctrl_cmd *cmd, void *data)
+CTRL_CMD_DEFINE_RO(subscr_info, "info");
+static int get_subscr_info(struct ctrl_cmd *cmd, void *data)
{
- return handle_cmd_ps(data, cmd, false);
+ struct hlr_subscriber subscr;
+ struct hlr *hlr = data;
+ const char *by_selector = cmd->node;
+
+ if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
+ return CTRL_CMD_ERROR;
+
+ print_subscr_info(cmd, &subscr);
+
+ return CTRL_CMD_REPLY;
}
-CTRL_CMD_DEFINE_WO_NOVRF(status_ps, "status-ps");
-static int set_status_ps(struct ctrl_cmd *cmd, void *data)
+CTRL_CMD_DEFINE_RO(subscr_info_aud, "info-aud");
+static int get_subscr_info_aud(struct ctrl_cmd *cmd, void *data)
{
- struct hlr *ctx = data;
- struct lu_operation *luop = lu_op_alloc(ctx->gs);
- if (!luop) {
- cmd->reply = "Internal HLR error";
+ const char *imsi;
+ struct osmo_sub_auth_data aud2g;
+ struct osmo_sub_auth_data aud3g;
+ struct hlr *hlr = data;
+ const char *by_selector = cmd->node;
+ int rc;
+
+ imsi = get_subscriber_imsi(hlr->dbc, by_selector, cmd);
+ if (!imsi)
+ return CTRL_CMD_ERROR;
+
+ rc = db_get_auth_data(hlr->dbc, imsi, &aud2g, &aud3g, NULL);
+
+ if (rc == -ENOENT) {
+ /* No auth data found, tell the print*() functions about it. */
+ aud2g.algo = OSMO_AUTH_ALG_NONE;
+ aud3g.algo = OSMO_AUTH_ALG_NONE;
+ } else if (rc) {
+ cmd->reply = "Error retrieving authentication data.";
return CTRL_CMD_ERROR;
}
- if (!lu_op_fill_subscr(luop, ctx->dbc, cmd->value)) {
- cmd->reply = "Subscriber Unknown in HLR";
+ print_subscr_info_aud2g(cmd, &aud2g);
+ print_subscr_info_aud3g(cmd, &aud3g);
+
+ return CTRL_CMD_REPLY;
+}
+
+CTRL_CMD_DEFINE_RO(subscr_info_all, "info-all");
+static int get_subscr_info_all(struct ctrl_cmd *cmd, void *data)
+{
+ struct hlr_subscriber subscr;
+ struct osmo_sub_auth_data aud2g;
+ struct osmo_sub_auth_data aud3g;
+ struct hlr *hlr = data;
+ const char *by_selector = cmd->node;
+ int rc;
+
+ if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
+ return CTRL_CMD_ERROR;
+
+ rc = db_get_auth_data(hlr->dbc, subscr.imsi, &aud2g, &aud3g, NULL);
+
+ if (rc == -ENOENT) {
+ /* No auth data found, tell the print*() functions about it. */
+ aud2g.algo = OSMO_AUTH_ALG_NONE;
+ aud3g.algo = OSMO_AUTH_ALG_NONE;
+ } else if (rc) {
+ cmd->reply = "Error retrieving authentication data.";
return CTRL_CMD_ERROR;
}
- cmd->reply = luop->subscr.nam_ps ? "1" : "0";
+ print_subscr_info(cmd, &subscr);
+ print_subscr_info_aud2g(cmd, &aud2g);
+ print_subscr_info_aud3g(cmd, &aud3g);
+
+ return CTRL_CMD_REPLY;
+}
+
+static int verify_subscr_cs_ps_enabled(struct ctrl_cmd *cmd, const char *value, void *data)
+{
+ if (!value || !*value
+ || (strcmp(value, "0") && strcmp(value, "1")))
+ return 1;
+ return 0;
+}
+
+static int get_subscr_cs_ps_enabled(struct ctrl_cmd *cmd, void *data,
+ bool is_ps)
+{
+ struct hlr_subscriber subscr;
+ struct hlr *hlr = data;
+ const char *by_selector = cmd->node;
+
+ if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
+ return CTRL_CMD_ERROR;
+ cmd->reply = (is_ps ? subscr.nam_ps : subscr.nam_cs)
+ ? "1" : "0";
+ return CTRL_CMD_REPLY;
+}
+
+static int set_subscr_cs_ps_enabled(struct ctrl_cmd *cmd, void *data,
+ bool is_ps)
+{
+ const char *imsi;
+ struct hlr *hlr = data;
+ const char *by_selector = cmd->node;
+
+ imsi = get_subscriber_imsi(hlr->dbc, by_selector, cmd);
+ if (!imsi)
+ return CTRL_CMD_ERROR;
+ if (db_subscr_nam(hlr->dbc, imsi, strcmp(cmd->value, "1") == 0, is_ps))
+ return CTRL_CMD_ERROR;
+ cmd->reply = "OK";
return CTRL_CMD_REPLY;
}
+CTRL_CMD_DEFINE(subscr_ps_enabled, "ps-enabled");
+static int verify_subscr_ps_enabled(struct ctrl_cmd *cmd, const char *value, void *data)
+{
+ return verify_subscr_cs_ps_enabled(cmd, value, data);
+}
+static int get_subscr_ps_enabled(struct ctrl_cmd *cmd, void *data)
+{
+ return get_subscr_cs_ps_enabled(cmd, data, true);
+}
+static int set_subscr_ps_enabled(struct ctrl_cmd *cmd, void *data)
+{
+ return set_subscr_cs_ps_enabled(cmd, data, true);
+}
+
+CTRL_CMD_DEFINE(subscr_cs_enabled, "cs-enabled");
+static int verify_subscr_cs_enabled(struct ctrl_cmd *cmd, const char *value, void *data)
+{
+ return verify_subscr_cs_ps_enabled(cmd, value, data);
+}
+static int get_subscr_cs_enabled(struct ctrl_cmd *cmd, void *data)
+{
+ return get_subscr_cs_ps_enabled(cmd, data, false);
+}
+static int set_subscr_cs_enabled(struct ctrl_cmd *cmd, void *data)
+{
+ return set_subscr_cs_ps_enabled(cmd, data, false);
+}
+
int hlr_ctrl_cmds_install()
{
int rc = 0;
- rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_enable_ps);
- rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_disable_ps);
- rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_status_ps);
+ rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_info);
+ rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_info_aud);
+ rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_info_all);
+ rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_ps_enabled);
+ rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_cs_enabled);
return rc;
}
+static int hlr_ctrl_node_lookup(void *data, vector vline, int *node_type,
+ void **node_data, int *i)
+{
+ const char *token = vector_slot(vline, *i);
+
+ switch (*node_type) {
+ case CTRL_NODE_ROOT:
+ if (strcmp(token, "subscriber") != 0)
+ return 0;
+ *node_data = NULL;
+ *node_type = CTRL_NODE_SUBSCR;
+ break;
+ case CTRL_NODE_SUBSCR:
+ if (!startswith(token, "by-"))
+ return 0;
+ *node_data = (void*)token;
+ *node_type = CTRL_NODE_SUBSCR_BY;
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
struct ctrl_handle *hlr_controlif_setup(struct hlr *hlr)
{
int rc;
struct ctrl_handle *hdl = ctrl_interface_setup_dynip2(hlr,
hlr->ctrl_bind_addr,
OSMO_CTRL_PORT_HLR,
- NULL,
- 0);
+ hlr_ctrl_node_lookup,
+ _LAST_CTRL_NODE_HLR);
if (!hdl)
return NULL;
diff --git a/src/ctrl.h b/src/ctrl.h
index 239deea..3f9ba3f 100644
--- a/src/ctrl.h
+++ b/src/ctrl.h
@@ -24,7 +24,11 @@
#include <osmocom/ctrl/control_if.h>
-#include "gsup_server.h"
+enum hlr_ctrl_node {
+ CTRL_NODE_SUBSCR = _LAST_CTRL_NODE,
+ CTRL_NODE_SUBSCR_BY,
+ _LAST_CTRL_NODE_HLR
+};
int hlr_ctrl_cmds_install();
struct ctrl_handle *hlr_controlif_setup(struct hlr *hlr);
diff --git a/tests/test_subscriber.ctrl b/tests/test_subscriber.ctrl
index 3284ae5..b9be5fe 100644
--- a/tests/test_subscriber.ctrl
+++ b/tests/test_subscriber.ctrl
@@ -1,27 +1,598 @@
-GET 1 invalid
-ERROR 1 Command not found
-SET 2 invalid nonsense
-ERROR 2 Command not found
-
-SET 3 enable-ps 901990000000001
-SET_REPLY 3 enable-ps OK
-SET 4 status-ps 901990000000001
-SET_REPLY 4 status-ps 1
-SET 5 enable-ps 901990000000001
-SET_REPLY 5 enable-ps OK
-SET 6 status-ps 901990000000001
-SET_REPLY 6 status-ps 1
-
-SET 7 disable-ps 901990000000001
-SET_REPLY 7 disable-ps OK
-SET 8 status-ps 901990000000001
-SET_REPLY 8 status-ps 0
-SET 9 disable-ps 901990000000001
-SET_REPLY 9 disable-ps OK
-SET 10 status-ps 901990000000001
-SET_REPLY 10 status-ps 0
-
-SET 11 enable-ps 901990000000001
-SET_REPLY 11 enable-ps OK
-SET 12 status-ps 901990000000001
-SET_REPLY 12 status-ps 1
+GET 1 subscriber.by-imsi-901990000000001.info
+GET_REPLY 1 subscriber.by-imsi-901990000000001.info
+id 1
+imsi 901990000000001
+msisdn 1
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+GET 2 subscriber.by-imsi-901990000000001.info-aud
+GET_REPLY 2 subscriber.by-imsi-901990000000001.info-aud
+aud2g.algo COMP128v1
+aud2g.ki 000102030405060708090a0b0c0d0e0f
+
+GET 3 subscriber.by-imsi-901990000000001.info-all
+GET_REPLY 3 subscriber.by-imsi-901990000000001.info-all
+id 1
+imsi 901990000000001
+msisdn 1
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+aud2g.algo COMP128v1
+aud2g.ki 000102030405060708090a0b0c0d0e0f
+
+GET 4 subscriber.by-imsi-901990000000002.info
+GET_REPLY 4 subscriber.by-imsi-901990000000002.info
+id 2
+imsi 901990000000002
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+GET 5 subscriber.by-imsi-901990000000002.info-aud
+GET_REPLY 5 subscriber.by-imsi-901990000000002.info-aud
+aud3g.algo MILENAGE
+aud3g.k 000102030405060708090a0b0c0d0e0f
+aud3g.opc 101112131415161718191a1b1c1d1e1f
+aud3g.ind_bitlen 5
+aud3g.sqn 4223
+
+GET 6 subscriber.by-imsi-901990000000002.info-all
+GET_REPLY 6 subscriber.by-imsi-901990000000002.info-all
+id 2
+imsi 901990000000002
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+aud3g.algo MILENAGE
+aud3g.k 000102030405060708090a0b0c0d0e0f
+aud3g.opc 101112131415161718191a1b1c1d1e1f
+aud3g.ind_bitlen 5
+aud3g.sqn 4223
+
+GET 7 subscriber.by-imsi-901990000000003.info
+GET_REPLY 7 subscriber.by-imsi-901990000000003.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+GET 8 subscriber.by-imsi-901990000000003.info-aud
+GET_REPLY 8 subscriber.by-imsi-901990000000003.info-aud
+aud2g.algo COMP128v1
+aud2g.ki 000102030405060708090a0b0c0d0e0f
+aud3g.algo MILENAGE
+aud3g.k 000102030405060708090a0b0c0d0e0f
+aud3g.opc 101112131415161718191a1b1c1d1e1f
+aud3g.ind_bitlen 5
+aud3g.sqn 2342
+
+GET 9 subscriber.by-imsi-901990000000003.info-all
+GET_REPLY 9 subscriber.by-imsi-901990000000003.info-all
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+aud2g.algo COMP128v1
+aud2g.ki 000102030405060708090a0b0c0d0e0f
+aud3g.algo MILENAGE
+aud3g.k 000102030405060708090a0b0c0d0e0f
+aud3g.opc 101112131415161718191a1b1c1d1e1f
+aud3g.ind_bitlen 5
+aud3g.sqn 2342
+
+GET 10 subscriber.by-imsi-901990000000003.ps-enabled
+GET_REPLY 10 subscriber.by-imsi-901990000000003.ps-enabled 1
+
+SET 11 subscriber.by-imsi-901990000000003.ps-enabled 0
+SET_REPLY 11 subscriber.by-imsi-901990000000003.ps-enabled OK
+GET 12 subscriber.by-imsi-901990000000003.ps-enabled
+GET_REPLY 12 subscriber.by-imsi-901990000000003.ps-enabled 0
+
+GET 13 subscriber.by-imsi-901990000000003.info
+GET_REPLY 13 subscriber.by-imsi-901990000000003.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 0
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+SET 14 subscriber.by-imsi-901990000000003.ps-enabled 0
+SET_REPLY 14 subscriber.by-imsi-901990000000003.ps-enabled OK
+GET 15 subscriber.by-imsi-901990000000003.ps-enabled
+GET_REPLY 15 subscriber.by-imsi-901990000000003.ps-enabled 0
+
+SET 16 subscriber.by-imsi-901990000000003.ps-enabled 1
+SET_REPLY 16 subscriber.by-imsi-901990000000003.ps-enabled OK
+GET 17 subscriber.by-imsi-901990000000003.ps-enabled
+GET_REPLY 17 subscriber.by-imsi-901990000000003.ps-enabled 1
+
+GET 18 subscriber.by-imsi-901990000000003.info
+GET_REPLY 18 subscriber.by-imsi-901990000000003.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+SET 19 subscriber.by-imsi-901990000000003.ps-enabled 1
+SET_REPLY 19 subscriber.by-imsi-901990000000003.ps-enabled OK
+GET 20 subscriber.by-imsi-901990000000003.ps-enabled
+GET_REPLY 20 subscriber.by-imsi-901990000000003.ps-enabled 1
+
+GET 21 subscriber.by-imsi-901990000000003.cs-enabled
+GET_REPLY 21 subscriber.by-imsi-901990000000003.cs-enabled 1
+
+SET 22 subscriber.by-imsi-901990000000003.cs-enabled 0
+SET_REPLY 22 subscriber.by-imsi-901990000000003.cs-enabled OK
+GET 23 subscriber.by-imsi-901990000000003.cs-enabled
+GET_REPLY 23 subscriber.by-imsi-901990000000003.cs-enabled 0
+
+GET 24 subscriber.by-imsi-901990000000003.info
+GET_REPLY 24 subscriber.by-imsi-901990000000003.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 0
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+SET 25 subscriber.by-imsi-901990000000003.cs-enabled 0
+SET_REPLY 25 subscriber.by-imsi-901990000000003.cs-enabled OK
+GET 26 subscriber.by-imsi-901990000000003.cs-enabled
+GET_REPLY 26 subscriber.by-imsi-901990000000003.cs-enabled 0
+
+SET 27 subscriber.by-imsi-901990000000003.cs-enabled 1
+SET_REPLY 27 subscriber.by-imsi-901990000000003.cs-enabled OK
+GET 28 subscriber.by-imsi-901990000000003.cs-enabled
+GET_REPLY 28 subscriber.by-imsi-901990000000003.cs-enabled 1
+
+GET 29 subscriber.by-imsi-901990000000003.info
+GET_REPLY 29 subscriber.by-imsi-901990000000003.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+SET 30 subscriber.by-imsi-901990000000003.cs-enabled 1
+SET_REPLY 30 subscriber.by-imsi-901990000000003.cs-enabled OK
+GET 31 subscriber.by-imsi-901990000000003.cs-enabled
+GET_REPLY 31 subscriber.by-imsi-901990000000003.cs-enabled 1
+
+SET 32 subscriber.by-imsi-901990000000003.ps-enabled 0
+SET_REPLY 32 subscriber.by-imsi-901990000000003.ps-enabled OK
+SET 33 subscriber.by-imsi-901990000000003.cs-enabled 0
+SET_REPLY 33 subscriber.by-imsi-901990000000003.cs-enabled OK
+GET 34 subscriber.by-imsi-901990000000003.info
+GET_REPLY 34 subscriber.by-imsi-901990000000003.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 0
+nam_ps 0
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+SET 35 subscriber.by-imsi-901990000000003.ps-enabled 1
+SET_REPLY 35 subscriber.by-imsi-901990000000003.ps-enabled OK
+SET 36 subscriber.by-imsi-901990000000003.cs-enabled 1
+SET_REPLY 36 subscriber.by-imsi-901990000000003.cs-enabled OK
+GET 37 subscriber.by-imsi-901990000000003.info
+GET_REPLY 37 subscriber.by-imsi-901990000000003.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+
+
+GET 38 subscriber.by-msisdn-103.info
+GET_REPLY 38 subscriber.by-msisdn-103.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+GET 39 subscriber.by-msisdn-103.info-aud
+GET_REPLY 39 subscriber.by-msisdn-103.info-aud
+aud2g.algo COMP128v1
+aud2g.ki 000102030405060708090a0b0c0d0e0f
+aud3g.algo MILENAGE
+aud3g.k 000102030405060708090a0b0c0d0e0f
+aud3g.opc 101112131415161718191a1b1c1d1e1f
+aud3g.ind_bitlen 5
+aud3g.sqn 2342
+
+GET 40 subscriber.by-msisdn-103.info-all
+GET_REPLY 40 subscriber.by-msisdn-103.info-all
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+aud2g.algo COMP128v1
+aud2g.ki 000102030405060708090a0b0c0d0e0f
+aud3g.algo MILENAGE
+aud3g.k 000102030405060708090a0b0c0d0e0f
+aud3g.opc 101112131415161718191a1b1c1d1e1f
+aud3g.ind_bitlen 5
+aud3g.sqn 2342
+
+GET 41 subscriber.by-msisdn-103.ps-enabled
+GET_REPLY 41 subscriber.by-msisdn-103.ps-enabled 1
+
+SET 42 subscriber.by-msisdn-103.ps-enabled 0
+SET_REPLY 42 subscriber.by-msisdn-103.ps-enabled OK
+GET 43 subscriber.by-msisdn-103.ps-enabled
+GET_REPLY 43 subscriber.by-msisdn-103.ps-enabled 0
+
+GET 44 subscriber.by-msisdn-103.info
+GET_REPLY 44 subscriber.by-msisdn-103.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 0
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+SET 45 subscriber.by-msisdn-103.ps-enabled 0
+SET_REPLY 45 subscriber.by-msisdn-103.ps-enabled OK
+GET 46 subscriber.by-msisdn-103.ps-enabled
+GET_REPLY 46 subscriber.by-msisdn-103.ps-enabled 0
+
+SET 47 subscriber.by-msisdn-103.ps-enabled 1
+SET_REPLY 47 subscriber.by-msisdn-103.ps-enabled OK
+GET 48 subscriber.by-msisdn-103.ps-enabled
+GET_REPLY 48 subscriber.by-msisdn-103.ps-enabled 1
+
+GET 49 subscriber.by-msisdn-103.info
+GET_REPLY 49 subscriber.by-msisdn-103.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+SET 50 subscriber.by-msisdn-103.ps-enabled 1
+SET_REPLY 50 subscriber.by-msisdn-103.ps-enabled OK
+GET 51 subscriber.by-msisdn-103.ps-enabled
+GET_REPLY 51 subscriber.by-msisdn-103.ps-enabled 1
+
+GET 52 subscriber.by-msisdn-103.cs-enabled
+GET_REPLY 52 subscriber.by-msisdn-103.cs-enabled 1
+
+SET 53 subscriber.by-msisdn-103.cs-enabled 0
+SET_REPLY 53 subscriber.by-msisdn-103.cs-enabled OK
+GET 54 subscriber.by-msisdn-103.cs-enabled
+GET_REPLY 54 subscriber.by-msisdn-103.cs-enabled 0
+
+GET 55 subscriber.by-msisdn-103.info
+GET_REPLY 55 subscriber.by-msisdn-103.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 0
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+SET 56 subscriber.by-msisdn-103.cs-enabled 0
+SET_REPLY 56 subscriber.by-msisdn-103.cs-enabled OK
+GET 57 subscriber.by-msisdn-103.cs-enabled
+GET_REPLY 57 subscriber.by-msisdn-103.cs-enabled 0
+
+SET 58 subscriber.by-msisdn-103.cs-enabled 1
+SET_REPLY 58 subscriber.by-msisdn-103.cs-enabled OK
+GET 59 subscriber.by-msisdn-103.cs-enabled
+GET_REPLY 59 subscriber.by-msisdn-103.cs-enabled 1
+
+GET 60 subscriber.by-msisdn-103.info
+GET_REPLY 60 subscriber.by-msisdn-103.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+SET 61 subscriber.by-msisdn-103.cs-enabled 1
+SET_REPLY 61 subscriber.by-msisdn-103.cs-enabled OK
+GET 62 subscriber.by-msisdn-103.cs-enabled
+GET_REPLY 62 subscriber.by-msisdn-103.cs-enabled 1
+
+SET 63 subscriber.by-msisdn-103.ps-enabled 0
+SET_REPLY 63 subscriber.by-msisdn-103.ps-enabled OK
+SET 64 subscriber.by-msisdn-103.cs-enabled 0
+SET_REPLY 64 subscriber.by-msisdn-103.cs-enabled OK
+GET 65 subscriber.by-msisdn-103.info
+GET_REPLY 65 subscriber.by-msisdn-103.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 0
+nam_ps 0
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+SET 66 subscriber.by-msisdn-103.ps-enabled 1
+SET_REPLY 66 subscriber.by-msisdn-103.ps-enabled OK
+SET 67 subscriber.by-msisdn-103.cs-enabled 1
+SET_REPLY 67 subscriber.by-msisdn-103.cs-enabled OK
+GET 68 subscriber.by-msisdn-103.info
+GET_REPLY 68 subscriber.by-msisdn-103.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+
+
+GET 69 subscriber.by-id-3.info
+GET_REPLY 69 subscriber.by-id-3.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+GET 70 subscriber.by-id-3.info-aud
+GET_REPLY 70 subscriber.by-id-3.info-aud
+aud2g.algo COMP128v1
+aud2g.ki 000102030405060708090a0b0c0d0e0f
+aud3g.algo MILENAGE
+aud3g.k 000102030405060708090a0b0c0d0e0f
+aud3g.opc 101112131415161718191a1b1c1d1e1f
+aud3g.ind_bitlen 5
+aud3g.sqn 2342
+
+GET 71 subscriber.by-id-3.info-all
+GET_REPLY 71 subscriber.by-id-3.info-all
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+aud2g.algo COMP128v1
+aud2g.ki 000102030405060708090a0b0c0d0e0f
+aud3g.algo MILENAGE
+aud3g.k 000102030405060708090a0b0c0d0e0f
+aud3g.opc 101112131415161718191a1b1c1d1e1f
+aud3g.ind_bitlen 5
+aud3g.sqn 2342
+
+GET 72 subscriber.by-id-3.ps-enabled
+GET_REPLY 72 subscriber.by-id-3.ps-enabled 1
+
+SET 73 subscriber.by-id-3.ps-enabled 0
+SET_REPLY 73 subscriber.by-id-3.ps-enabled OK
+GET 74 subscriber.by-id-3.ps-enabled
+GET_REPLY 74 subscriber.by-id-3.ps-enabled 0
+
+GET 75 subscriber.by-id-3.info
+GET_REPLY 75 subscriber.by-id-3.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 0
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+SET 76 subscriber.by-id-3.ps-enabled 0
+SET_REPLY 76 subscriber.by-id-3.ps-enabled OK
+GET 77 subscriber.by-id-3.ps-enabled
+GET_REPLY 77 subscriber.by-id-3.ps-enabled 0
+
+SET 78 subscriber.by-id-3.ps-enabled 1
+SET_REPLY 78 subscriber.by-id-3.ps-enabled OK
+GET 79 subscriber.by-id-3.ps-enabled
+GET_REPLY 79 subscriber.by-id-3.ps-enabled 1
+
+GET 80 subscriber.by-id-3.info
+GET_REPLY 80 subscriber.by-id-3.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+SET 81 subscriber.by-id-3.ps-enabled 1
+SET_REPLY 81 subscriber.by-id-3.ps-enabled OK
+GET 82 subscriber.by-id-3.ps-enabled
+GET_REPLY 82 subscriber.by-id-3.ps-enabled 1
+
+GET 83 subscriber.by-id-3.cs-enabled
+GET_REPLY 83 subscriber.by-id-3.cs-enabled 1
+
+SET 84 subscriber.by-id-3.cs-enabled 0
+SET_REPLY 84 subscriber.by-id-3.cs-enabled OK
+GET 85 subscriber.by-id-3.cs-enabled
+GET_REPLY 85 subscriber.by-id-3.cs-enabled 0
+
+GET 86 subscriber.by-id-3.info
+GET_REPLY 86 subscriber.by-id-3.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 0
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+SET 87 subscriber.by-id-3.cs-enabled 0
+SET_REPLY 87 subscriber.by-id-3.cs-enabled OK
+GET 88 subscriber.by-id-3.cs-enabled
+GET_REPLY 88 subscriber.by-id-3.cs-enabled 0
+
+SET 89 subscriber.by-id-3.cs-enabled 1
+SET_REPLY 89 subscriber.by-id-3.cs-enabled OK
+GET 90 subscriber.by-id-3.cs-enabled
+GET_REPLY 90 subscriber.by-id-3.cs-enabled 1
+
+GET 91 subscriber.by-id-3.info
+GET_REPLY 91 subscriber.by-id-3.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+SET 92 subscriber.by-id-3.cs-enabled 1
+SET_REPLY 92 subscriber.by-id-3.cs-enabled OK
+GET 93 subscriber.by-id-3.cs-enabled
+GET_REPLY 93 subscriber.by-id-3.cs-enabled 1
+
+SET 94 subscriber.by-id-3.ps-enabled 0
+SET_REPLY 94 subscriber.by-id-3.ps-enabled OK
+SET 95 subscriber.by-id-3.cs-enabled 0
+SET_REPLY 95 subscriber.by-id-3.cs-enabled OK
+GET 96 subscriber.by-id-3.info
+GET_REPLY 96 subscriber.by-id-3.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 0
+nam_ps 0
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
+
+SET 97 subscriber.by-id-3.ps-enabled 1
+SET_REPLY 97 subscriber.by-id-3.ps-enabled OK
+SET 98 subscriber.by-id-3.cs-enabled 1
+SET_REPLY 98 subscriber.by-id-3.cs-enabled OK
+GET 99 subscriber.by-id-3.info
+GET_REPLY 99 subscriber.by-id-3.info
+id 3
+imsi 901990000000003
+msisdn 103
+nam_cs 1
+nam_ps 1
+ms_purged_cs 0
+ms_purged_ps 0
+periodic_lu_timer 0
+periodic_rau_tau_timer 0
+lmsi 00000000
diff --git a/tests/test_subscriber.sql b/tests/test_subscriber.sql
index 0767d48..bce0af2 100644
--- a/tests/test_subscriber.sql
+++ b/tests/test_subscriber.sql
@@ -1,13 +1,13 @@
-- 2G only subscriber
-INSERT INTO subscriber (id, imsi) VALUES (1, '901990000000001');
+INSERT INTO subscriber (id, imsi, msisdn) VALUES (1, '901990000000001', '1');
INSERT INTO auc_2g (subscriber_id, algo_id_2g, ki) VALUES (1, 1, '000102030405060708090a0b0c0d0e0f');
-- 3G only subscriber
INSERT INTO subscriber (id, imsi) VALUES (2, '901990000000002');
-INSERT INTO auc_3g (subscriber_id, algo_id_3g, k, opc, sqn) VALUES (2, 5, '000102030405060708090a0b0c0d0e0f', '101112131415161718191a1b1c1d1e1f', 0);
+INSERT INTO auc_3g (subscriber_id, algo_id_3g, k, opc, sqn) VALUES (2, 5, '000102030405060708090a0b0c0d0e0f', '101112131415161718191a1b1c1d1e1f', 4223);
-- 2G + 3G subscriber
-INSERT INTO subscriber (id, imsi) VALUES (3, '901990000000003');
+INSERT INTO subscriber (id, imsi, msisdn) VALUES (3, '901990000000003', '103');
INSERT INTO auc_2g (subscriber_id, algo_id_2g, ki) VALUES (3, 1, '000102030405060708090a0b0c0d0e0f');
-INSERT INTO auc_3g (subscriber_id, algo_id_3g, k, opc, sqn) VALUES (3, 5, '000102030405060708090a0b0c0d0e0f', '101112131415161718191a1b1c1d1e1f', 0);
+INSERT INTO auc_3g (subscriber_id, algo_id_3g, k, opc, sqn) VALUES (3, 5, '000102030405060708090a0b0c0d0e0f', '101112131415161718191a1b1c1d1e1f', 2342);
diff --git a/tests/test_subscriber.vty b/tests/test_subscriber.vty
index 2e0bdce..2da455f 100644
--- a/tests/test_subscriber.vty
+++ b/tests/test_subscriber.vty
@@ -305,6 +305,7 @@ OsmoHLR# subscriber imsi 123456789023000 show
OPC=cededeffacedacefacedbadfadedbeef
IND-bitlen=23
+OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d op C01ffedC1cadaeAc1d1f1edAcac1aB0a
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d op CoiffedCicadaeAcidifiedAcaciaBoa
% Invalid value for OP: 'CoiffedCicadaeAcidifiedAcaciaBoa'
OsmoHLR# subscriber imsi 123456789023000 show
@@ -313,8 +314,8 @@ OsmoHLR# subscriber imsi 123456789023000 show
MSISDN: 423
3G auth: MILENAGE
K=deaf0ff1ced0d0dabbedd1ced1cef00d
- OPC=cededeffacedacefacedbadfadedbeef
- IND-bitlen=23
+ OP=c01ffedc1cadaeac1d1f1edacac1ab0a
+ IND-bitlen=5
OsmoHLR# subscriber id 1 update aud2g comp128v2 ki CededEffacedAceFacedBadFadedBeef
OsmoHLR# subscriber id 1 show
@@ -325,8 +326,8 @@ OsmoHLR# subscriber id 1 show
KI=cededeffacedacefacedbadfadedbeef
3G auth: MILENAGE
K=deaf0ff1ced0d0dabbedd1ced1cef00d
- OPC=cededeffacedacefacedbadfadedbeef
- IND-bitlen=23
+ OP=c01ffedc1cadaeac1d1f1edacac1ab0a
+ IND-bitlen=5
OsmoHLR# subscriber imsi 123456789023000 delete
% Deleted subscriber for IMSI '123456789023000'
diff --git a/tests/test_subscriber_errors.ctrl b/tests/test_subscriber_errors.ctrl
new file mode 100644
index 0000000..2f64fdb
--- /dev/null
+++ b/tests/test_subscriber_errors.ctrl
@@ -0,0 +1,107 @@
+GET 1 invalid
+ERROR 1 Command not found
+SET 2 invalid nonsense
+ERROR 2 Command not found
+
+GET 3 subscriber.by-imsi-nonsense.info
+ERROR 3 Invalid value part of 'by-xxx-value' selector.
+GET 4 subscriber.by-msisdn-nonsense.info
+ERROR 4 Invalid value part of 'by-xxx-value' selector.
+GET 5 subscriber.by-id-nonsense.info
+ERROR 5 Invalid value part of 'by-xxx-value' selector.
+
+GET 6 subscriber
+ERROR 6 Command not present.
+GET 7 subscriber.
+ERROR 7 Command not present.
+GET 8 subscriber.by-nonsense
+ERROR 8 Command not present.
+GET 9 subscriber.by-nonsense-
+ERROR 9 Command not present.
+GET 10 subscriber.by-nonsense-123456
+ERROR 10 Command not present.
+GET 11 subscriber.by-nonsense-123456.
+ERROR 11 Command not present.
+GET 12 subscriber.by-imsi-
+ERROR 12 Command not present.
+GET 13 subscriber.by-imsi-.
+ERROR 13 Command not present.
+GET 14 subscriber.by-imsi-901990000000003
+ERROR 14 Command not present.
+GET 15 subscriber.by-imsi-901990000000003.
+ERROR 15 Command not present.
+
+GET 16 subscriber.by-nonsense-123456.info
+ERROR 16 Not a known subscriber 'by-xxx-' selector.
+GET 17 subscriber.by-123456.info
+ERROR 17 Not a known subscriber 'by-xxx-' selector.
+
+GET 18 subscriber.by-imsi-.info
+ERROR 18 Invalid value part of 'by-xxx-value' selector.
+GET 19 subscriber.by-imsi--.info
+ERROR 19 Invalid value part of 'by-xxx-value' selector.
+
+GET 20 subscriber.by-imsi-12345678901234567.info
+ERROR 20 Invalid value part of 'by-xxx-value' selector.
+GET 21 subscriber.by-imsi-12345.info
+ERROR 21 Invalid value part of 'by-xxx-value' selector.
+GET 22 subscriber.by-imsi-1234567890123456.info
+ERROR 22 Invalid value part of 'by-xxx-value' selector.
+
+GET 23 subscriber.by-id-99999999999999999999999999.info
+ERROR 23 Invalid value part of 'by-xxx-value' selector.
+GET 24 subscriber.by-id-9223372036854775807.info
+ERROR 24 No such subscriber.
+GET 25 subscriber.by-id-9223372036854775808.info
+ERROR 25 Invalid value part of 'by-xxx-value' selector.
+GET 26 subscriber.by-id--1.info
+ERROR 26 No such subscriber.
+GET 27 subscriber.by-id--9223372036854775808.info
+ERROR 27 No such subscriber.
+GET 28 subscriber.by-id--9223372036854775809.info
+ERROR 28 Invalid value part of 'by-xxx-value' selector.
+
+GET 29 subscriber.by-id-1+1.info
+ERROR 29 Invalid value part of 'by-xxx-value' selector.
+GET 30 subscriber.by-id--.info
+ERROR 30 Invalid value part of 'by-xxx-value' selector.
+GET 31 subscriber.by-id-+1.info
+ERROR 31 Invalid value part of 'by-xxx-value' selector.
+GET 32 subscriber.by-id-+-1.info
+ERROR 32 Invalid value part of 'by-xxx-value' selector.
+GET 33 subscriber.by-id--+1.info
+ERROR 33 Invalid value part of 'by-xxx-value' selector.
+GET 34 subscriber.by-id-++1.info
+ERROR 34 Invalid value part of 'by-xxx-value' selector.
+GET 35 subscriber.by-id---1.info
+ERROR 35 Invalid value part of 'by-xxx-value' selector.
+
+GET 36 subscriber.by-id- 1.info
+ERROR 36 Command not present.
+GET 37 subscriber.by-id-+ 1.info
+ERROR 37 Command not present.
+GET 38 subscriber.by-id-- 1.info
+ERROR 38 Command not present.
+
+
+SET 39 subscriber.by-imsi-901990000000001.info foo
+ERROR 39 Read Only attribute
+SET 40 subscriber.by-imsi-901990000000001.info-aud foo
+ERROR 40 Read Only attribute
+SET 41 subscriber.by-imsi-901990000000001.info-all foo
+ERROR 41 Read Only attribute
+
+SET 42 subscriber.by-imsi-901990000000001.ps-enabled nonsense
+ERROR 42 Value failed verification.
+SET 43 subscriber.by-imsi-901990000000001.cs-enabled nonsense
+ERROR 43 Value failed verification.
+
+SET 44 subscriber.by-imsi-901990000000001.ps-enabled
+ERROR err Command parser error.
+SET 45 subscriber.by-imsi-901990000000001.cs-enabled
+ERROR err Command parser error.
+
+GET 46 subscriber.by-imsi-1234567890123456.ps-enabled
+ERROR 46 Invalid value part of 'by-xxx-value' selector.
+GET 47 subscriber.by-imsi-1234567890123456.cs-enabled
+ERROR 47 Invalid value part of 'by-xxx-value' selector.