osmo-hlr/src/ctrl.c

785 lines
20 KiB
C
Raw Normal View History

/* OsmoHLR Control Interface implementation */
/* (C) 2017 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
* All Rights Reserved
*
* Author: Max Suraev <msuraev@sysmocom.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdbool.h>
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
#include <errno.h>
#include <inttypes.h>
#include <string.h>
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
#include <osmocom/gsm/gsm23003.h>
#include <osmocom/ctrl/ports.h>
#include <osmocom/hlr/hlr.h>
#include <osmocom/hlr/ctrl.h>
#include <osmocom/hlr/db.h>
#include <osmocom/hlr/hlr_vty.h>
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
#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-"
extern bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
int *minlen, int *maxlen);
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
#define hexdump_buf(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf))
static bool startswith(const char *str, const char *start)
{
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
return strncmp(str, start, strlen(start)) == 0;
}
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
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);
}
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
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;
}
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
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 occurred during get_subscriber().";
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
return false;
}
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
}
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
/* 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
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
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: 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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data *aud)
{
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
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
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
,
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(subscr_create, "create");
static int set_subscr_create(struct ctrl_cmd *cmd, void *data)
{
struct hlr_subscriber subscr;
struct hlr *hlr = data;
const char *imsi = cmd->value;
int rc;
if (!osmo_imsi_str_valid(imsi)) {
cmd->reply = "Invalid IMSI value.";
return CTRL_CMD_ERROR;
}
/* Create the subscriber in the DB */
rc = db_subscr_create(g_hlr->dbc, imsi, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS);
if (rc) {
if (rc == -EEXIST)
cmd->reply = "Subscriber already exists.";
else
cmd->reply = "Cannot create subscriber.";
return CTRL_CMD_ERROR;
}
LOGP(DCTRL, LOGL_INFO, "Created subscriber IMSI='%s'\n",
imsi);
/* Retrieve data of newly created subscriber: */
rc = db_subscr_get_by_imsi(hlr->dbc, imsi, &subscr);
if (rc < 0) {
cmd->reply = "Failed retrieving ID of newly created subscriber.";
return CTRL_CMD_ERROR;
}
cmd->reply = talloc_asprintf(cmd, "%" PRIu64, subscr.id);
return CTRL_CMD_REPLY;
}
CTRL_CMD_DEFINE_WO_NOVRF(subscr_delete, "delete");
static int set_subscr_delete(struct ctrl_cmd *cmd, void *data)
{
struct hlr_subscriber subscr;
struct hlr *hlr = data;
const char *imsi = cmd->value;
int rc;
if (!osmo_imsi_str_valid(imsi)) {
cmd->reply = "Invalid IMSI value.";
return CTRL_CMD_ERROR;
}
/* Retrieve data of newly created subscriber: */
rc = db_subscr_get_by_imsi(hlr->dbc, imsi, &subscr);
if (rc < 0) {
cmd->reply = "Subscriber doesn't exist.";
return CTRL_CMD_ERROR;
}
/* Create the subscriber in the DB */
rc = db_subscr_delete_by_id(g_hlr->dbc, subscr.id);
if (rc) {
cmd->reply = "Cannot delete subscriber.";
return CTRL_CMD_ERROR;
}
LOGP(DCTRL, LOGL_INFO, "Deleted subscriber IMSI='%s'\n",
imsi);
cmd->reply = talloc_asprintf(cmd, "%" PRIu64, subscr.id);
return CTRL_CMD_REPLY;
}
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
CTRL_CMD_DEFINE_RO(subscr_info, "info");
static int get_subscr_info(struct ctrl_cmd *cmd, void *data)
{
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
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: 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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
CTRL_CMD_DEFINE_RO(subscr_info_aud, "info-aud");
static int get_subscr_info_aud(struct ctrl_cmd *cmd, void *data)
{
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
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);
switch (rc) {
case 0:
break;
case -ENOENT:
case -ENOKEY:
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
/* No auth data found, tell the print*() functions about it. */
aud2g.algo = OSMO_AUTH_ALG_NONE;
aud3g.algo = OSMO_AUTH_ALG_NONE;
break;
default:
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
cmd->reply = "Error retrieving authentication data.";
return CTRL_CMD_ERROR;
}
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
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);
switch (rc) {
case 0:
break;
case -ENOENT:
case -ENOKEY:
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
/* No auth data found, tell the print*() functions about it. */
aud2g.algo = OSMO_AUTH_ALG_NONE;
aud3g.algo = OSMO_AUTH_ALG_NONE;
break;
default:
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
cmd->reply = "Error retrieving authentication data.";
return CTRL_CMD_ERROR;
}
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
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;
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
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: 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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
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);
}
CTRL_CMD_DEFINE(subscr_msisdn, "msisdn");
static int verify_subscr_msisdn(struct ctrl_cmd *cmd, const char *value, void *data)
{
struct hlr_subscriber subscr;
if (!value)
return 1;
if (strlen(value) > sizeof(subscr.msisdn) - 1)
return 1;
if (strcmp(value, "none") != 0 && !osmo_msisdn_str_valid(value))
return 1;
return 0;
}
static int get_subscr_msisdn(struct ctrl_cmd *cmd, void *data)
{
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;
if (strlen(subscr.msisdn) == 0)
snprintf(subscr.msisdn, sizeof(subscr.msisdn), "none");
cmd->reply = talloc_asprintf(cmd, "%s", subscr.msisdn);
return CTRL_CMD_REPLY;
}
static int set_subscr_msisdn(struct ctrl_cmd *cmd, void *data)
{
struct hlr_subscriber subscr;
struct hlr *hlr = data;
const char *by_selector = cmd->node;
const char *msisdn;
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
return CTRL_CMD_ERROR;
if (strcmp(cmd->value, "none") == 0)
msisdn = NULL;
else
msisdn = cmd->value;
if (db_subscr_update_msisdn_by_imsi(g_hlr->dbc, subscr.imsi, msisdn)) {
cmd->reply = "Update MSISDN failed";
return CTRL_CMD_ERROR;
}
cmd->reply = "OK";
return CTRL_CMD_REPLY;
}
/* value format: <algo[,KI]> */
CTRL_CMD_DEFINE(subscr_aud2g, "aud2g");
static int verify_subscr_aud2g(struct ctrl_cmd *cmd, const char *value, void *data)
{
if (!value)
return 1;
if (strcasecmp(value, "none") != 0 && !strchr(value, ','))
return 1;
return 0;
}
static int get_subscr_aud2g(struct ctrl_cmd *cmd, void *data)
{
struct hlr_subscriber subscr;
struct hlr *hlr = data;
const char *by_selector = cmd->node;
struct osmo_sub_auth_data aud2g;
struct osmo_sub_auth_data aud3g_unused;
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_unused, NULL);
switch (rc) {
case 0:
break;
case -ENOENT:
case -ENOKEY:
aud2g.algo = OSMO_AUTH_ALG_NONE;
break;
default:
cmd->reply = "Error retrieving data from database.";
return CTRL_CMD_ERROR;
}
if (aud2g.algo == OSMO_AUTH_ALG_NONE) {
cmd->reply = "none";
return CTRL_CMD_REPLY;
}
cmd->reply = talloc_asprintf(cmd, "%s,%s", osmo_auth_alg_name(aud2g.algo),
hexdump_buf(aud2g.u.gsm.ki));
return CTRL_CMD_REPLY;
}
static int set_subscr_aud2g(struct ctrl_cmd *cmd, void *data)
{
struct hlr_subscriber subscr;
struct hlr *hlr = data;
const char *by_selector = cmd->node;
char *tmp = NULL, *tok, *saveptr;
int minlen = 0;
int maxlen = 0;
struct sub_auth_data_str aud2g = {
.type = OSMO_AUTH_TYPE_GSM
};
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
return CTRL_CMD_ERROR;
tmp = talloc_strdup(cmd, cmd->value);
if (!tmp) {
cmd->reply = "OOM";
return CTRL_CMD_ERROR;
}
/* Parse alg_type: */
tok = strtok_r(tmp, ",", &saveptr);
if (!tok) {
cmd->reply = "Invalid format";
return CTRL_CMD_ERROR;
}
if (strcmp(tok, "none") == 0) {
aud2g.algo = OSMO_AUTH_ALG_NONE;
} else if (!auth_algo_parse(tok, &aud2g.algo, &minlen, &maxlen)) {
cmd->reply = "Unknown auth algorithm.";
return CTRL_CMD_ERROR;
}
if (aud2g.algo != OSMO_AUTH_ALG_NONE) {
tok = strtok_r(NULL, "\0", &saveptr);
if (!tok) {
cmd->reply = "Invalid format.";
return CTRL_CMD_ERROR;
}
aud2g.u.gsm.ki = tok;
if (!osmo_is_hexstr(aud2g.u.gsm.ki, minlen * 2, maxlen * 2, true)) {
cmd->reply = "Invalid KI.";
return CTRL_CMD_ERROR;
}
}
if (db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud2g)) {
cmd->reply = "Update aud2g failed.";
return CTRL_CMD_ERROR;
}
cmd->reply = "OK";
return CTRL_CMD_REPLY;
}
/* value format: <algo[,KI,(op|opc),OP_C[,ind_bitlen]]> */
CTRL_CMD_DEFINE(subscr_aud3g, "aud3g");
static int verify_subscr_aud3g(struct ctrl_cmd *cmd, const char *value, void *data)
{
if (!value)
return 1;
if (strcasecmp(value, "none") != 0 && !strchr(value, ','))
return 1;
return 0;
}
static int get_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
{
struct hlr_subscriber subscr;
struct hlr *hlr = data;
const char *by_selector = cmd->node;
struct osmo_sub_auth_data aud2g_unused;
struct osmo_sub_auth_data aud3g;
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_unused, &aud3g, NULL);
switch (rc) {
case 0:
break;
case -ENOENT:
case -ENOKEY:
aud3g.algo = OSMO_AUTH_ALG_NONE;
break;
default:
cmd->reply = "Error retrieving data from database.";
return CTRL_CMD_ERROR;
}
if (aud3g.algo == OSMO_AUTH_ALG_NONE) {
cmd->reply = "none";
return CTRL_CMD_REPLY;
}
cmd->reply = talloc_asprintf(cmd, "%s,%s,%s,%s,%u", osmo_auth_alg_name(aud3g.algo),
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.k, sizeof(aud3g.u.umts.k)),
aud3g.u.umts.opc_is_op ? "OP" : "OPC",
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc)),
aud3g.u.umts.ind_bitlen);
return CTRL_CMD_REPLY;
}
static int set_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
{
struct hlr_subscriber subscr;
struct hlr *hlr = data;
const char *by_selector = cmd->node;
char *tmp = NULL, *tok, *saveptr;
int minlen = 0;
int maxlen = 0;
struct sub_auth_data_str aud3g = {
.type = OSMO_AUTH_TYPE_UMTS,
.u.umts = {
.ind_bitlen = 5,
},
};
bool ind_bitlen_present;
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
return CTRL_CMD_ERROR;
tmp = talloc_strdup(cmd, cmd->value);
if (!tmp) {
cmd->reply = "OOM";
return CTRL_CMD_ERROR;
}
/* Parse alg_type: */
tok = strtok_r(tmp, ",", &saveptr);
if (!tok) {
cmd->reply = "Invalid format.";
return CTRL_CMD_ERROR;
}
if (strcmp(tok, "none") == 0) {
aud3g.algo = OSMO_AUTH_ALG_NONE;
} else if (!auth_algo_parse(tok, &aud3g.algo, &minlen, &maxlen)) {
cmd->reply = "Unknown auth algorithm.";
return CTRL_CMD_ERROR;
}
if (aud3g.algo != OSMO_AUTH_ALG_NONE) {
/* Parse K */
tok = strtok_r(NULL, ",", &saveptr);
if (!tok) {
cmd->reply = "Invalid format.";
return CTRL_CMD_ERROR;
}
aud3g.u.umts.k = tok;
if (!osmo_is_hexstr(aud3g.u.umts.k, minlen * 2, maxlen * 2, true)) {
cmd->reply = "Invalid KI.";
return CTRL_CMD_ERROR;
}
/* Parse OP/OPC choice */
tok = strtok_r(NULL, ",", &saveptr);
if (!tok) {
cmd->reply = "Invalid format.";
return CTRL_CMD_ERROR;
}
if (strcasecmp(tok, "op") == 0) {
aud3g.u.umts.opc_is_op = true;
} else if (strcasecmp(tok, "opc") == 0) {
aud3g.u.umts.opc_is_op = false;
} else {
cmd->reply = "Invalid format.";
return CTRL_CMD_ERROR;
}
/* Parse OP/OPC value */
ind_bitlen_present = !!strchr(saveptr, ',');
tok = strtok_r(NULL, ind_bitlen_present ? "," : "\0", &saveptr);
if (!tok) {
cmd->reply = "Invalid format.";
return CTRL_CMD_ERROR;
}
aud3g.u.umts.opc = tok;
if (!osmo_is_hexstr(aud3g.u.umts.opc, MILENAGE_KEY_LEN * 2, MILENAGE_KEY_LEN * 2, true)) {
cmd->reply = talloc_asprintf(cmd, "Invalid OP/OPC.");
return CTRL_CMD_ERROR;
}
if (ind_bitlen_present) {
/* Parse bitlen_ind */
tok = strtok_r(NULL, "\0", &saveptr);
if (!tok || tok[0] == '\0') {
cmd->reply = "Invalid format.";
return CTRL_CMD_ERROR;
}
aud3g.u.umts.ind_bitlen = atoi(tok);
}
}
if (db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud3g)) {
cmd->reply = "Update aud3g failed.";
return CTRL_CMD_ERROR;
}
cmd->reply = "OK";
return CTRL_CMD_REPLY;
}
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. Adjust tests/test_subscriber.sql to feature nonzero SQN, to see some values for SQN in the CTRL transcript tests. (This does not affect the VTY tests, because that creates its own subscribers, and there's no VTY command to set the SQN.) 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
2017-10-16 23:58:24 +00:00
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;
}
static int hlr_ctrl_cmds_install(void)
{
int rc = 0;
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR, &cmd_subscr_create);
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR, &cmd_subscr_delete);
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);
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_msisdn);
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_aud2g);
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_aud3g);
return rc;
}
struct ctrl_handle *hlr_controlif_setup(struct hlr *hlr)
{
int rc;
struct ctrl_handle *hdl = ctrl_interface_setup2(hlr, OSMO_CTRL_PORT_HLR, hlr_ctrl_node_lookup,
_LAST_CTRL_NODE_HLR);
if (!hdl)
return NULL;
rc = hlr_ctrl_cmds_install();
if (rc) /* FIXME: close control interface? */
return NULL;
return hdl;
}