[PATCH] osmo-hlr[master]: ctrl: completely replace all CTRL commands

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Neels Hofmeyr gerrit-no-reply at lists.osmocom.org
Thu Oct 19 01:20:23 UTC 2017


Hello Max, Jenkins Builder,

I'd like you to reexamine a change.  Please visit

    https://gerrit.osmocom.org/4311

to look at the new patch set (#3).

ctrl: completely replace all CTRL commands

The previous commands are not conforming to how the CTRL interface is intended
to work:

  SET enable-ps <IMSI>
  SET disable-ps <IMSI>
  SET status-ps <IMSI>

'status-ps' is a write-only command even though it returns the status.
'enable-ps' / 'disable-ps' indicate the value instead of a variable name of an
entity. The entity <IMSI> takes the place of the variable value.

See also https://lists.osmocom.org/pipermail/openbsc/2017-September/011236.html

Instead, replace with

  SET subscriber.by-imsi-123456.ps-enabled {0,1}
  GET subscriber.by-imsi-123456.ps-enabled

and also provide further CTRL functions while at it:

  {SET,GET} subscriber.by-{imsi,msisdn,id}-123456.{cs,ps}-enabled {0,1}
  GET subscriber.by-{imsi,msisdn,id}-123456.{info,info-aud,info-all}

Provide CTRL tests in the form of transcripts.

This is the first time an application uses CTRL_NODE ids that are defined
outside of libosmocore, see 'Depends' below.

Implementation choice: the first idea was to have a '.' between the 'by-xxx'
and the value, like:

  subscriber.by-xxx.123456.function

but the difficulty with subscribers is that they are not in RAM, and I can't
just point node_data at a struct instance that is always there (like, say, a
global bts[0] struct in osmo-bsc). Instead, I want to store the selector and
later decide whether to read from the DB or whatever. With a '.' separating
things, the only way in a ctrl function to obtain both 'by-xxx' and '123456'
for picking a subscriber record would be to parse the entire variable path
string elements, including 'subscriber' and 'function', which would then also
clumsily fix at which node level we hook these commands; there could have been
separate CTRL_NODE_SUBSCR_BY_{IMSI,MSISDN,ID} parent nodes, but we cannot
introspect the current parent node dynamically within a ctrl function handler
(plus I'm not sure whether it's possible and a good idea to have the same
command under multiple parent nodes).

Rather than that, I store the 'by-foo-123' token in the node_data pointer to
have both bits of information pointed at by a single pointer; I use the
incoming command parsing to get this token pre-separated from surrounding node
names, and no need to re-allocate it, since the vector of tokens lives until
after command execution is complete. Each leaf command obtains this token from
cmd->node (aka node_data), and feeds this token to a common static function to
parse selector and value from it and to retrieve a subscriber record as needed.

(BTW, I have mentioned on the mailing list that this way might be necessary to
avoid numeric-only CTRL node names, but we don't need to, and that is not at
all related to this choice of structure.)

Depends: libosmocore I1bd62ae0d4eefde7e1517db15a2155640a1bab58
         libosmocore Ic9dba0e4a1eb5a7dc3cee2f181b9024ed4fc7005
Change-Id: I98ee6a06b3aa6a67adb868e0b63b0e04eb42eb50
---
M src/ctrl.c
M src/ctrl.h
M src/hlr.c
M tests/test_subscriber.ctrl
M tests/test_subscriber.sql
M tests/test_subscriber.vty
A tests/test_subscriber_errors.ctrl
7 files changed, 871 insertions(+), 78 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-hlr refs/changes/11/4311/3

diff --git a/src/ctrl.c b/src/ctrl.c
index 3bd4d8f..6140a25 100644
--- a/src/ctrl.c
+++ b/src/ctrl.c
@@ -21,87 +21,382 @@
  */
 
 #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"
 
-static int handle_cmd_ps(struct hlr *ctx, struct ctrl_cmd *cmd, bool enable)
+#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-"
+
+#define hexdump_buf(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf))
+
+static bool startswith(const char *str, const char *start)
+{
+	return strncmp(str, start, strlen(start)) == 0;
+}
+
+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;
+}
+
+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 = NULL;
+		return false;
+	}
+}
+
+/* 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_OMIT_TRUE(name, val) \
+	val ? "" : "\n" name "\t0"
+#define ARG_BOOL_OMIT_FALSE(name, val) \
+	val ? "\n" name "\t1" : ""
+#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
+#if 0
+/* not used yet */
+		FMT_BOOL
+		FMT_BOOL
+		"\nperiodic_lu_timer\t%u"
+		"\nperiodic_rau_tau_timer\t%u"
+		"\nlmsi\t%08x"
+#endif
+		,
+		subscr->id,
+		ARG_S("imsi", subscr->imsi),
+		ARG_S("msisdn", subscr->msisdn),
+		ARG_BOOL_OMIT_TRUE("nam_cs", subscr->nam_cs),
+		ARG_BOOL_OMIT_TRUE("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)
+#if 0
+		,
+		ARG_BOOL_OMIT_FALSE("ms_purged_cs", subscr->ms_purged_cs),
+		ARG_BOOL_OMIT_FALSE("ms_purged_ps", subscr->ms_purged_ps),
+		subscr->periodic_lu_timer,
+		subscr->periodic_rau_tau_timer,
+		subscr->lmsi
+#endif
+		);
+}
+
+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));
+}
+
+static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data *aud)
+{
+	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_RO(subscr_info, "info");
+static int get_subscr_info(struct ctrl_cmd *cmd, void *data)
 {
 	struct hlr_subscriber subscr;
+	struct hlr *hlr = data;
+	const char *by_selector = cmd->node;
 
-	if (db_subscr_get_by_imsi(ctx->dbc, cmd->value, &subscr) < 0) {
-		cmd->reply = "Subscriber Unknown in HLR";
+	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_RO(subscr_info_aud, "info-aud");
+static int get_subscr_info_aud(struct ctrl_cmd *cmd, void *data)
+{
+	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) {
+		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 (hlr_subscr_nam(ctx, &subscr, enable, true) < 0) {
-		cmd->reply = "Error updating DB";
+	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) {
+		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;
 	}
 
+	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_WO_NOVRF(enable_ps, "enable-ps");
-static int set_enable_ps(struct ctrl_cmd *cmd, void *data)
+CTRL_CMD_DEFINE(subscr_ps_enabled, "ps-enabled");
+static int verify_subscr_ps_enabled(struct ctrl_cmd *cmd, const char *value, void *data)
 {
-	return handle_cmd_ps(data, cmd, true);
+	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_WO_NOVRF(disable_ps, "disable-ps");
-static int set_disable_ps(struct ctrl_cmd *cmd, void *data)
+CTRL_CMD_DEFINE(subscr_cs_enabled, "cs-enabled");
+static int verify_subscr_cs_enabled(struct ctrl_cmd *cmd, const char *value, void *data)
 {
-	return handle_cmd_ps(data, cmd, false);
+	return verify_subscr_cs_ps_enabled(cmd, value, data);
 }
-
-CTRL_CMD_DEFINE_WO_NOVRF(status_ps, "status-ps");
-static int set_status_ps(struct ctrl_cmd *cmd, void *data)
+static int get_subscr_cs_enabled(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";
-		return CTRL_CMD_ERROR;
-	}
-
-	if (!lu_op_fill_subscr(luop, ctx->dbc, cmd->value)) {
-		cmd->reply = "Subscriber Unknown in HLR";
-		return CTRL_CMD_ERROR;
-	}
-
-	cmd->reply = luop->subscr.nam_ps ? "1" : "0";
-
-	return CTRL_CMD_REPLY;
+	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;
 }
 
-struct ctrl_handle *hlr_controlif_setup(struct hlr *ctx,
-					struct osmo_gsup_server *gs)
+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_dynip(ctx,
-							     ctx->ctrl_bind_addr,
-							     OSMO_CTRL_PORT_HLR,
-							     NULL);
+	struct ctrl_handle *hdl;
+
+	hdl = ctrl_interface_setup_dynip2(hlr,
+					  hlr->ctrl_bind_addr,
+					  OSMO_CTRL_PORT_HLR,
+					  hlr_ctrl_node_lookup,
+					  _LAST_CTRL_NODE_HLR);
 	if (!hdl)
 		return NULL;
 
diff --git a/src/ctrl.h b/src/ctrl.h
index 663de30..3f9ba3f 100644
--- a/src/ctrl.h
+++ b/src/ctrl.h
@@ -24,8 +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 *ctx,
-					struct osmo_gsup_server *gs);
+struct ctrl_handle *hlr_controlif_setup(struct hlr *hlr);
diff --git a/src/hlr.c b/src/hlr.c
index b32f709..6310526 100644
--- a/src/hlr.c
+++ b/src/hlr.c
@@ -474,7 +474,7 @@
 	}
 
 	g_hlr->ctrl_bind_addr = ctrl_vty_get_bind_addr();
-	g_hlr->ctrl = hlr_controlif_setup(g_hlr, g_hlr->gs);
+	g_hlr->ctrl = hlr_controlif_setup(g_hlr);
 
 	osmo_init_ignore_signals();
 	signal(SIGINT, &signal_hdlr);
diff --git a/tests/test_subscriber.ctrl b/tests/test_subscriber.ctrl
index 3284ae5..30dae00 100644
--- a/tests/test_subscriber.ctrl
+++ b/tests/test_subscriber.ctrl
@@ -1,27 +1,414 @@
-GET 1 invalid
-ERROR 1 Command not found
-SET 2 invalid nonsense
-ERROR 2 Command not found
+GET 1 subscriber.by-imsi-901990000000001.info
+GET_REPLY 1 subscriber.by-imsi-901990000000001.info 
+id	1
+imsi	901990000000001
+msisdn	1
 
-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
+GET 2 subscriber.by-imsi-901990000000001.info-aud
+GET_REPLY 2 subscriber.by-imsi-901990000000001.info-aud 
+aud2g.algo	COMP128v1
+aud2g.ki	000102030405060708090a0b0c0d0e0f
 
-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
+GET 3 subscriber.by-imsi-901990000000001.info-all
+GET_REPLY 3 subscriber.by-imsi-901990000000001.info-all 
+id	1
+imsi	901990000000001
+msisdn	1
+aud2g.algo	COMP128v1
+aud2g.ki	000102030405060708090a0b0c0d0e0f
 
-SET 11 enable-ps 901990000000001
-SET_REPLY 11 enable-ps OK
-SET 12 status-ps 901990000000001
-SET_REPLY 12 status-ps 1
+GET 4 subscriber.by-imsi-901990000000002.info
+GET_REPLY 4 subscriber.by-imsi-901990000000002.info 
+id	2
+imsi	901990000000002
+
+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	0
+
+GET 6 subscriber.by-imsi-901990000000002.info-all
+GET_REPLY 6 subscriber.by-imsi-901990000000002.info-all 
+id	2
+imsi	901990000000002
+aud3g.algo	MILENAGE
+aud3g.k	000102030405060708090a0b0c0d0e0f
+aud3g.opc	101112131415161718191a1b1c1d1e1f
+aud3g.ind_bitlen	5
+aud3g.sqn	0
+
+GET 7 subscriber.by-imsi-901990000000003.info
+GET_REPLY 7 subscriber.by-imsi-901990000000003.info 
+id	3
+imsi	901990000000003
+msisdn	103
+
+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	0
+
+GET 9 subscriber.by-imsi-901990000000003.info-all
+GET_REPLY 9 subscriber.by-imsi-901990000000003.info-all 
+id	3
+imsi	901990000000003
+msisdn	103
+aud2g.algo	COMP128v1
+aud2g.ki	000102030405060708090a0b0c0d0e0f
+aud3g.algo	MILENAGE
+aud3g.k	000102030405060708090a0b0c0d0e0f
+aud3g.opc	101112131415161718191a1b1c1d1e1f
+aud3g.ind_bitlen	5
+aud3g.sqn	0
+
+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_ps	0
+
+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
+
+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
+
+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
+
+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
+
+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
+
+
+
+GET 38 subscriber.by-msisdn-103.info
+GET_REPLY 38 subscriber.by-msisdn-103.info 
+id	3
+imsi	901990000000003
+msisdn	103
+
+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	0
+
+GET 40 subscriber.by-msisdn-103.info-all
+GET_REPLY 40 subscriber.by-msisdn-103.info-all 
+id	3
+imsi	901990000000003
+msisdn	103
+aud2g.algo	COMP128v1
+aud2g.ki	000102030405060708090a0b0c0d0e0f
+aud3g.algo	MILENAGE
+aud3g.k	000102030405060708090a0b0c0d0e0f
+aud3g.opc	101112131415161718191a1b1c1d1e1f
+aud3g.ind_bitlen	5
+aud3g.sqn	0
+
+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_ps	0
+
+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
+
+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
+
+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
+
+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
+
+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
+
+
+
+GET 69 subscriber.by-id-3.info
+GET_REPLY 69 subscriber.by-id-3.info 
+id	3
+imsi	901990000000003
+msisdn	103
+
+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	0
+
+GET 71 subscriber.by-id-3.info-all
+GET_REPLY 71 subscriber.by-id-3.info-all 
+id	3
+imsi	901990000000003
+msisdn	103
+aud2g.algo	COMP128v1
+aud2g.ki	000102030405060708090a0b0c0d0e0f
+aud3g.algo	MILENAGE
+aud3g.k	000102030405060708090a0b0c0d0e0f
+aud3g.opc	101112131415161718191a1b1c1d1e1f
+aud3g.ind_bitlen	5
+aud3g.sqn	0
+
+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_ps	0
+
+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
+
+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
+
+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
+
+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
+
+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
diff --git a/tests/test_subscriber.sql b/tests/test_subscriber.sql
index 0767d48..decd7d2 100644
--- a/tests/test_subscriber.sql
+++ b/tests/test_subscriber.sql
@@ -1,6 +1,6 @@
 
 -- 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
@@ -8,6 +8,6 @@
 INSERT INTO auc_3g (subscriber_id, algo_id_3g, k, opc, sqn) VALUES (2, 5, '000102030405060708090a0b0c0d0e0f', '101112131415161718191a1b1c1d1e1f', 0);
 
 -- 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);
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 @@
              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 @@
     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 @@
              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.

-- 
To view, visit https://gerrit.osmocom.org/4311
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I98ee6a06b3aa6a67adb868e0b63b0e04eb42eb50
Gerrit-PatchSet: 3
Gerrit-Project: osmo-hlr
Gerrit-Branch: master
Gerrit-Owner: Neels Hofmeyr <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Max <msuraev at sysmocom.de>
Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr at sysmocom.de>



More information about the gerrit-log mailing list