aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ctrl.c18
-rw-r--r--src/db.h4
-rw-r--r--src/db_hlr.c51
3 files changed, 58 insertions, 15 deletions
diff --git a/src/ctrl.c b/src/ctrl.c
index 74172c4..3bd4d8f 100644
--- a/src/ctrl.c
+++ b/src/ctrl.c
@@ -35,31 +35,19 @@
static int handle_cmd_ps(struct hlr *ctx, struct ctrl_cmd *cmd, bool enable)
{
- struct lu_operation *luop = NULL;
- struct osmo_gsup_conn *co;
+ struct hlr_subscriber subscr;
- if (db_subscr_get_by_imsi(ctx->dbc, cmd->value, NULL) < 0) {
+ if (db_subscr_get_by_imsi(ctx->dbc, cmd->value, &subscr) < 0) {
cmd->reply = "Subscriber Unknown in HLR";
return CTRL_CMD_ERROR;
}
- if (db_subscr_nam(ctx->dbc, cmd->value, enable, true) < 0) {
+ if (hlr_subscr_nam(ctx, &subscr, enable, true) < 0) {
cmd->reply = "Error updating DB";
return CTRL_CMD_ERROR;
}
- /* FIXME: only send to single SGSN where latest update for IMSI came from */
- if (!enable) {
- llist_for_each_entry(co, &ctx->gs->clients, list) {
- luop = lu_op_alloc_conn(co);
- lu_op_fill_subscr(luop, ctx->dbc, cmd->value);
- lu_op_tx_del_subscr_data(luop);
- lu_op_free(luop);
- }
- }
-
cmd->reply = "OK";
-
return CTRL_CMD_REPLY;
}
diff --git a/src/db.h b/src/db.h
index f6aaa58..35e4327 100644
--- a/src/db.h
+++ b/src/db.h
@@ -3,6 +3,8 @@
#include <stdbool.h>
#include <sqlite3.h>
+struct hlr;
+
enum stmt_idx {
DB_STMT_SEL_BY_IMSI,
DB_STMT_SEL_BY_MSISDN,
@@ -125,3 +127,5 @@ int db_subscr_lu(struct db_context *dbc, int64_t subscr_id,
int db_subscr_purge(struct db_context *dbc, const char *by_imsi,
bool purge_val, bool is_ps);
+
+int hlr_subscr_nam(struct hlr *hlr, struct hlr_subscriber *subscr, bool nam_val, bool is_ps);
diff --git a/src/db_hlr.c b/src/db_hlr.c
index cf6e4f8..e8db7d2 100644
--- a/src/db_hlr.c
+++ b/src/db_hlr.c
@@ -28,7 +28,10 @@
#include <sqlite3.h>
#include "logging.h"
+#include "hlr.h"
#include "db.h"
+#include "gsup_server.h"
+#include "luop.h"
#define LOGHLR(imsi, level, fmt, args ...) LOGP(DAUC, level, "IMSI='%s': " fmt, imsi, ## args)
@@ -609,3 +612,51 @@ out:
return ret;
}
+
+/*! Update nam_cs/nam_ps in the db and trigger notifications to GSUP clients.
+ * \param hlr Global hlr context.
+ * \param subscr Subscriber from a fresh db_subscr_get_by_*() call.
+ * \param nam_val True to enable CS/PS, false to disable.
+ * \param is_ps True to enable/disable PS, false for CS.
+ * \returns 0 on success, ENOEXEC if there is no need to change, a negative
+ * value on error.
+ */
+int hlr_subscr_nam(struct hlr *hlr, struct hlr_subscriber *subscr, bool nam_val, bool is_ps)
+{
+ int rc;
+ struct lu_operation *luop;
+ struct osmo_gsup_conn *co;
+ bool is_val = is_ps? subscr->nam_ps : subscr->nam_cs;
+
+ if (is_val == nam_val) {
+ LOGHLR(subscr->imsi, LOGL_DEBUG, "Already has the requested value when asked to %s %s\n",
+ nam_val ? "enable" : "disable", is_ps ? "PS" : "CS");
+ return ENOEXEC;
+ }
+
+ rc = db_subscr_nam(hlr->dbc, subscr->imsi, nam_val, is_ps);
+ if (rc)
+ return rc > 0? -rc : rc;
+
+ /* If we're disabling, send a notice out to the GSUP client that is
+ * responsible. Otherwise no need. */
+ if (nam_val)
+ return 0;
+
+ /* FIXME: only send to single SGSN where latest update for IMSI came from */
+ llist_for_each_entry(co, &hlr->gs->clients, list) {
+ luop = lu_op_alloc_conn(co);
+ if (!luop) {
+ LOGHLR(subscr->imsi, LOGL_ERROR,
+ "Cannot notify GSUP client, cannot allocate lu_operation,"
+ " for %s:%u\n",
+ co && co->conn && co->conn->server? co->conn->server->addr : "unset",
+ co && co->conn && co->conn->server? co->conn->server->port : 0);
+ continue;
+ }
+ luop->subscr = *subscr;
+ lu_op_tx_del_subscr_data(luop);
+ lu_op_free(luop);
+ }
+ return 0;
+}