diff options
author | Keith <keith@rhizomatica.org> | 2023-01-06 17:42:54 +0100 |
---|---|---|
committer | Keith Whyte <keith@rhizomatica.org> | 2023-11-22 19:56:48 +0000 |
commit | 193306896a312790b441c3650cc6ee16899da236 (patch) | |
tree | 63623026aa1fbdf57162532238683abf24f5b0f5 | |
parent | 8e497448db844bcf9f3a4eca723ae1c3b7e5869e (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.h | 2 | ||||
-rw-r--r-- | include/osmocom/hlr/hlr.h | 1 | ||||
-rw-r--r-- | src/db.c | 3 | ||||
-rw-r--r-- | src/db_hlr.c | 28 | ||||
-rw-r--r-- | src/dgsm.c | 11 | ||||
-rw-r--r-- | src/dgsm_vty.c | 22 | ||||
-rw-r--r-- | src/mslookup_server.c | 21 |
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; }; @@ -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. @@ -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; } |