aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith <keith@rhizomatica.org>2023-01-06 17:42:54 +0100
committerKeith Whyte <keith@rhizomatica.org>2023-11-22 19:56:48 +0000
commit193306896a312790b441c3650cc6ee16899da236 (patch)
tree63623026aa1fbdf57162532238683abf24f5b0f5
parent8e497448db844bcf9f3a4eca723ae1c3b7e5869e (diff)
DGSM: Add ignore-created-on-demand option
When a subscriber is create(d)-on-demand (assuming configuration does not grant CS/PS access by default), then the following will be true: * The subscriber will never have connected, and therefore have no vlr_number entry. * The msisdn length will be the length configured in create-on-demand. * The subscriber will have no CS/PS access. Let's use these three conditions to 'detect' subscribers than have beeen created on demand, and ignore them in both the case of an incoming mslookup, and a local GSUP request. Change-Id: I40d40467316c360bcbd50d50cb2e52a38e718eac
-rw-r--r--include/osmocom/hlr/db.h2
-rw-r--r--include/osmocom/hlr/hlr.h1
-rw-r--r--src/db.c3
-rw-r--r--src/db_hlr.c28
-rw-r--r--src/dgsm.c11
-rw-r--r--src/dgsm_vty.c22
-rw-r--r--src/mslookup_server.c21
7 files changed, 83 insertions, 5 deletions
diff --git a/include/osmocom/hlr/db.h b/include/osmocom/hlr/db.h
index 89b4fbc..af4a7df 100644
--- a/include/osmocom/hlr/db.h
+++ b/include/osmocom/hlr/db.h
@@ -41,6 +41,7 @@ enum stmt_idx {
DB_STMT_SET_LAST_LU_SEEN_PS,
DB_STMT_EXISTS_BY_IMSI,
DB_STMT_EXISTS_AUTHORIZED_BY_IMSI,
+ DB_STMT_IS_CREATED_ON_DEMAND_BY_IMSI,
DB_STMT_EXISTS_BY_MSISDN,
DB_STMT_IND_ADD,
DB_STMT_IND_SELECT,
@@ -159,6 +160,7 @@ int db_subscr_update_imei_by_imsi(struct db_context *dbc, const char* imsi, cons
int db_subscr_exists_by_imsi(struct db_context *dbc, const char *imsi);
int db_subscr_authorized_by_imsi(struct db_context *dbc, const char *imsi);
+int db_subscr_is_created_on_demand_by_imsi(struct db_context *dbc, const char *imsi, unsigned int msisdn_len);
int db_subscr_exists_by_msisdn(struct db_context *dbc, const char *msisdn);
int db_subscrs_get(struct db_context *dbc, const char *filter_type, const char *filter,
diff --git a/include/osmocom/hlr/hlr.h b/include/osmocom/hlr/hlr.h
index aa038df..badcf12 100644
--- a/include/osmocom/hlr/hlr.h
+++ b/include/osmocom/hlr/hlr.h
@@ -121,6 +121,7 @@ struct hlr {
} mdns;
} client;
bool auth_imsi_only;
+ bool ignore_created_on_demand;
} mslookup;
};
diff --git a/src/db.c b/src/db.c
index 1ed8e06..c2b4abe 100644
--- a/src/db.c
+++ b/src/db.c
@@ -93,6 +93,9 @@ static const char *stmt_sql[] = {
[DB_STMT_SET_LAST_LU_SEEN_PS] = "UPDATE subscriber SET last_lu_seen_ps = datetime($val, 'unixepoch') WHERE id = $subscriber_id",
[DB_STMT_EXISTS_BY_IMSI] = "SELECT 1 FROM subscriber WHERE imsi = $imsi",
[DB_STMT_EXISTS_AUTHORIZED_BY_IMSI] = "SELECT 1 FROM subscriber WHERE imsi = $imsi AND (nam_cs = 1 OR nam_ps = 1)",
+ [DB_STMT_IS_CREATED_ON_DEMAND_BY_IMSI] =
+ "SELECT 1 FROM subscriber WHERE imsi = $imsi AND length(msisdn) = $msisdn_len"
+ " AND nam_cs = 0 AND nam_ps = 0 AND vlr_number IS NULL",
[DB_STMT_EXISTS_BY_MSISDN] = "SELECT 1 FROM subscriber WHERE msisdn = $msisdn",
[DB_STMT_IND_ADD] = "INSERT INTO ind (vlr) VALUES ($vlr)",
[DB_STMT_IND_SELECT] = "SELECT ind FROM ind WHERE vlr = $vlr",
diff --git a/src/db_hlr.c b/src/db_hlr.c
index 3724797..7c22e2e 100644
--- a/src/db_hlr.c
+++ b/src/db_hlr.c
@@ -580,6 +580,34 @@ int db_subscr_authorized_by_imsi(struct db_context *dbc, const char *imsi) {
return rc;
}
+/*! Check if a subscriber exists and has ever been attached
+ * \param[in, out] dbc database context.
+ * \param[in] imsi ASCII string of IMSI digits.
+ * \returns 0 if has vlr_number, -ENOENT if not, -EIO on database error.
+ */
+int db_subscr_is_created_on_demand_by_imsi(struct db_context *dbc, const char *imsi, unsigned int msisdn_len) {
+ sqlite3_stmt *stmt = dbc->stmt[DB_STMT_IS_CREATED_ON_DEMAND_BY_IMSI];
+ const char *err;
+ int rc;
+
+ if (!db_bind_text(stmt, "$imsi", imsi))
+ return -EIO;
+
+ if (!db_bind_int(stmt, "$msisdn_len", msisdn_len))
+ return -EIO;
+
+ rc = sqlite3_step(stmt);
+ db_remove_reset(stmt);
+ if (rc == SQLITE_ROW)
+ return 0; /* exists */
+ if (rc == SQLITE_DONE)
+ return -ENOENT; /* does not exist */
+
+ err = sqlite3_errmsg(dbc->db);
+ LOGP(DAUC, LOGL_ERROR, "Failed to check for on demand subscriber by IMSI='%s': %s\n", imsi, err);
+ return rc;
+}
+
/*! Retrieve subscriber data from the HLR database.
* \param[in,out] dbc database context.
* \param[in] imsi ASCII string of IMSI digits.
diff --git a/src/dgsm.c b/src/dgsm.c
index 305020d..50b3773 100644
--- a/src/dgsm.c
+++ b/src/dgsm.c
@@ -91,14 +91,19 @@ bool dgsm_check_forward_gsup_msg(struct osmo_gsup_req *req)
struct osmo_mslookup_query_handling handling;
uint32_t request_handle;
- /* If the IMSI is authorized in the local HLR, then we won't proxy. */
+ /* If the IMSI is authorized in the local HLR, then we won't proxy */
if (db_subscr_authorized_by_imsi(g_hlr->dbc, req->gsup.imsi) == 0)
return false;
- /* If auth imsi is not set, then we won't proxy for ANY known IMSI */
- if (!g_hlr->mslookup.auth_imsi_only &&
+ /* unless configuration tells us to do otherwise. */
+ if (!g_hlr->mslookup.ignore_created_on_demand && !g_hlr->mslookup.auth_imsi_only &&
db_subscr_exists_by_imsi(g_hlr->dbc, req->gsup.imsi) == 0)
return false;
+ if (!g_hlr->mslookup.auth_imsi_only && !(g_hlr->mslookup.ignore_created_on_demand &&
+ db_subscr_is_created_on_demand_by_imsi(g_hlr->dbc, req->gsup.imsi,
+ g_hlr->subscr_create_on_demand_rand_msisdn_len) == 0))
+ return false;
+
/* Are we already forwarding this IMSI to a remote HLR? */
if (proxy_subscr_get_by_imsi(&proxy_subscr, proxy, req->gsup.imsi) == 0) {
proxy_subscr_forward_to_remote_hlr(proxy, &proxy_subscr, req);
diff --git a/src/dgsm_vty.c b/src/dgsm_vty.c
index 3e22023..6b0648d 100644
--- a/src/dgsm_vty.c
+++ b/src/dgsm_vty.c
@@ -206,6 +206,24 @@ DEFUN(cfg_mslookup_no_auth_imsi_only,
return CMD_SUCCESS;
}
+DEFUN(cfg_mslookup_cod,
+ cfg_mslookup_cod_cmd,
+ "ignore-created-on-demand",
+ "Ignore IMSIs that were created-on-demand")
+{
+ g_hlr->mslookup.ignore_created_on_demand = true;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mslookup_no_cod,
+ cfg_mslookup_no_cod_cmd,
+ "no ignore-created-on-demand",
+ NO_STR "Answer mslookup and local GSUP for created on demand IMSIs")
+{
+ g_hlr->mslookup.ignore_created_on_demand = false;
+ return CMD_SUCCESS;
+}
+
struct cmd_node mslookup_server_msc_node = {
MSLOOKUP_SERVER_MSC_NODE,
"%s(config-mslookup-server-msc)# ",
@@ -441,6 +459,8 @@ int config_write_mslookup(struct vty *vty)
if (g_hlr->mslookup.auth_imsi_only)
vty_out(vty, " authorized-imsi-only%s", VTY_NEWLINE);
+ if (g_hlr->mslookup.ignore_created_on_demand)
+ vty_out(vty, " ignore-created-on-demand%s", VTY_NEWLINE);
if (g_hlr->mslookup.server.enable || !llist_empty(&g_hlr->mslookup.server.local_site_services)) {
struct mslookup_server_msc_cfg *msc;
@@ -573,6 +593,8 @@ void dgsm_vty_init(void)
install_node(&mslookup_node, config_write_mslookup);
install_element(MSLOOKUP_NODE, &cfg_mslookup_auth_imsi_only_cmd);
install_element(MSLOOKUP_NODE, &cfg_mslookup_no_auth_imsi_only_cmd);
+ install_element(MSLOOKUP_NODE, &cfg_mslookup_cod_cmd);
+ install_element(MSLOOKUP_NODE, &cfg_mslookup_no_cod_cmd);
install_element(MSLOOKUP_NODE, &cfg_mslookup_mdns_cmd);
install_element(MSLOOKUP_NODE, &cfg_mslookup_mdns_domain_suffix_cmd);
install_element(MSLOOKUP_NODE, &cfg_mslookup_no_mdns_cmd);
diff --git a/src/mslookup_server.c b/src/mslookup_server.c
index 9610b49..38c4064 100644
--- a/src/mslookup_server.c
+++ b/src/mslookup_server.c
@@ -194,11 +194,25 @@ static void mslookup_server_rx_hlr_gsup(const struct osmo_mslookup_query *query,
int rc;
bool exists = false;
bool auth_imsi_only = false;
+ bool created_on_demand = false;
switch (query->id.type) {
case OSMO_MSLOOKUP_ID_IMSI_AUTHORIZED:
auth_imsi_only = true;
case OSMO_MSLOOKUP_ID_IMSI:
+ /* Entries that have been created by subscriber create on demand
+ will have default msisdn length. and will not have any vlr_number entry.
+ We should not answer for these, unless they have CS/PS service. */
+ if (g_hlr->mslookup.ignore_created_on_demand) {
+ rc = db_subscr_is_created_on_demand_by_imsi(g_hlr->dbc, query->id.imsi,
+ g_hlr->subscr_create_on_demand_rand_msisdn_len);
+ if (!rc) {
+ exists = true;
+ created_on_demand = true;
+ rc = -ENOENT;
+ break;
+ }
+ }
rc = db_subscr_exists_by_imsi(g_hlr->dbc, query->id.imsi);
if (g_hlr->mslookup.auth_imsi_only || auth_imsi_only) {
if (!rc)
@@ -208,6 +222,7 @@ static void mslookup_server_rx_hlr_gsup(const struct osmo_mslookup_query *query,
break;
case OSMO_MSLOOKUP_ID_MSISDN:
rc = db_subscr_exists_by_msisdn(g_hlr->dbc, query->id.msisdn);
+ /* FIXME: The log message below might not match */
break;
default:
LOGP(DMSLOOKUP, LOGL_ERROR, "Unknown mslookup ID type: %d\n", query->id.type);
@@ -216,9 +231,11 @@ static void mslookup_server_rx_hlr_gsup(const struct osmo_mslookup_query *query,
}
if (rc) {
- LOGP(DMSLOOKUP, LOGL_DEBUG, "%s: %s in local HLR\n",
+ LOGP(DMSLOOKUP, LOGL_DEBUG, "%s: %s%s%s in local HLR\n",
osmo_mslookup_result_name_c(OTC_SELECT, query, NULL),
- (exists) ? "exists but is not authorized" : "does not exist");
+ (exists) ? "exists but" : "does not exist",
+ (created_on_demand) ? " is created on demand and since untouched" : "",
+ (exists && !created_on_demand) ? " is not authorized" : "");
*result = not_found;
return;
}