aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gprs/gprs_subscriber.c
diff options
context:
space:
mode:
authorNeels Hofmeyr <nhofmeyr@sysmocom.de>2017-01-10 00:49:56 +0100
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2017-02-25 01:25:22 +0000
commit0e5d807297f4fd1222fafece864519c70f7965a3 (patch)
treee0842d19808a545e07ff8ce411f2a23739f0cf43 /openbsc/src/gprs/gprs_subscriber.c
parenta369e24cb9a583ef9906a8ef9125f6ca8c6f80bf (diff)
add struct gprs_subscr, separating gprs from gsm_subscriber
Prepare for replacing gsm_subscriber with vlr_subscriber. vlr_subscriber will not make sense to be used in gprs, so have a dedicated GPRS subscriber struct. (Could change if the gprs code were to use libvlr; is currently independent). Related: OS#1592 Change-Id: Ia8b391ee009c8545763cba04505be3947835120e
Diffstat (limited to 'openbsc/src/gprs/gprs_subscriber.c')
-rw-r--r--openbsc/src/gprs/gprs_subscriber.c159
1 files changed, 111 insertions, 48 deletions
diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c
index 57f73c5da..5f426f80c 100644
--- a/openbsc/src/gprs/gprs_subscriber.c
+++ b/openbsc/src/gprs/gprs_subscriber.c
@@ -23,7 +23,8 @@
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/gsm/gsup.h>
#include <osmocom/core/utils.h>
-#include <openbsc/gsm_subscriber.h>
+#include <osmocom/core/logging.h>
+#include <openbsc/gprs_subscriber.h>
#include <openbsc/gsup_client.h>
#include <openbsc/sgsn.h>
@@ -35,6 +36,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <limits.h>
#define SGSN_SUBSCR_MAX_RETRIES 3
#define SGSN_SUBSCR_RETRY_INTERVAL 10
@@ -46,6 +48,9 @@
extern void *tall_bsc_ctx;
+LLIST_HEAD(_gprs_subscribers);
+struct llist_head * const gprs_subscribers = &_gprs_subscribers;
+
static int gsup_read_cb(struct gsup_client *gsupc, struct msgb *msg);
/* TODO: Some functions are specific to the SGSN, but this file is more general
@@ -86,7 +91,7 @@ static int gsup_read_cb(struct gsup_client *gsupc, struct msgb *msg)
return rc;
}
-int gprs_subscr_purge(struct gsm_subscriber *subscr);
+int gprs_subscr_purge(struct gprs_subscr *subscr);
static struct sgsn_subscriber_data *sgsn_subscriber_data_alloc(void *ctx)
{
@@ -117,28 +122,53 @@ struct sgsn_subscriber_pdp_data* sgsn_subscriber_pdp_data_alloc(
return pdata;
}
-struct gsm_subscriber *gprs_subscr_get_or_create(const char *imsi)
+struct gprs_subscr *gprs_subscr_get_by_imsi(const char *imsi)
{
- struct gsm_subscriber *subscr;
+ struct gprs_subscr *gsub;
- subscr = subscr_get_or_create(NULL, imsi);
- if (!subscr)
+ if (!imsi || !*imsi)
return NULL;
- if (!subscr->sgsn_data)
- subscr->sgsn_data = sgsn_subscriber_data_alloc(subscr);
- return subscr;
+ llist_for_each_entry(gsub, gprs_subscribers, entry) {
+ if (!strcmp(gsub->imsi, imsi))
+ return gprs_subscr_get(gsub);
+ }
+ return NULL;
}
-struct gsm_subscriber *gprs_subscr_get_by_imsi(const char *imsi)
+static struct gprs_subscr *gprs_subscr_alloc(void)
{
- return subscr_active_by_imsi(NULL, imsi);
+ struct gprs_subscr *gsub;
+ gsub = talloc_zero(tall_bsc_ctx, struct gprs_subscr);
+ if (!gsub)
+ return NULL;
+ llist_add_tail(&gsub->entry, gprs_subscribers);
+ gsub->use_count = 1;
+ gsub->tmsi = GSM_RESERVED_TMSI;
+ return gsub;
+}
+
+struct gprs_subscr *gprs_subscr_get_or_create(const char *imsi)
+{
+ struct gprs_subscr *gsub;
+
+ gsub = gprs_subscr_get_by_imsi(imsi);
+ if (!gsub) {
+ gsub = gprs_subscr_alloc();
+ if (!gsub)
+ return NULL;
+ strncpy(gsub->imsi, imsi, sizeof(gsub->imsi));
+ }
+
+ if (!gsub->sgsn_data)
+ gsub->sgsn_data = sgsn_subscriber_data_alloc(gsub);
+ return gsub;
}
-void gprs_subscr_cleanup(struct gsm_subscriber *subscr)
+void gprs_subscr_cleanup(struct gprs_subscr *subscr)
{
if (subscr->sgsn_data->mm) {
- subscr_put(subscr->sgsn_data->mm->subscr);
+ gprs_subscr_put(subscr->sgsn_data->mm->subscr);
subscr->sgsn_data->mm->subscr = NULL;
subscr->sgsn_data->mm = NULL;
}
@@ -149,7 +179,7 @@ void gprs_subscr_cleanup(struct gsm_subscriber *subscr)
}
}
-void gprs_subscr_cancel(struct gsm_subscriber *subscr)
+void gprs_subscr_cancel(struct gprs_subscr *subscr)
{
subscr->authorized = 0;
subscr->flags |= GPRS_SUBSCRIBER_CANCELLED;
@@ -159,7 +189,7 @@ void gprs_subscr_cancel(struct gsm_subscriber *subscr)
gprs_subscr_cleanup(subscr);
}
-static int gprs_subscr_tx_gsup_message(struct gsm_subscriber *subscr,
+static int gprs_subscr_tx_gsup_message(struct gprs_subscr *subscr,
struct osmo_gsup_message *gsup_msg)
{
struct msgb *msg = gsup_client_msgb_alloc();
@@ -181,7 +211,7 @@ static int gprs_subscr_tx_gsup_message(struct gsm_subscriber *subscr,
return gsup_client_send(sgsn->gsup_client, msg);
}
-static int gprs_subscr_tx_gsup_error_reply(struct gsm_subscriber *subscr,
+static int gprs_subscr_tx_gsup_error_reply(struct gprs_subscr *subscr,
struct osmo_gsup_message *gsup_orig,
enum gsm48_gmm_cause cause)
{
@@ -196,7 +226,7 @@ static int gprs_subscr_tx_gsup_error_reply(struct gsm_subscriber *subscr,
return gprs_subscr_tx_gsup_message(subscr, &gsup_reply);
}
-static int gprs_subscr_handle_gsup_auth_res(struct gsm_subscriber *subscr,
+static int gprs_subscr_handle_gsup_auth_res(struct gprs_subscr *subscr,
struct osmo_gsup_message *gsup_msg)
{
unsigned idx;
@@ -235,7 +265,7 @@ static int gprs_subscr_handle_gsup_auth_res(struct gsm_subscriber *subscr,
return 0;
}
-static int gprs_subscr_pdp_data_clear(struct gsm_subscriber *subscr)
+static int gprs_subscr_pdp_data_clear(struct gprs_subscr *subscr)
{
struct sgsn_subscriber_pdp_data *pdp, *pdp2;
int count = 0;
@@ -250,7 +280,7 @@ static int gprs_subscr_pdp_data_clear(struct gsm_subscriber *subscr)
}
static struct sgsn_subscriber_pdp_data *gprs_subscr_pdp_data_get_by_id(
- struct gsm_subscriber *subscr, unsigned context_id)
+ struct gprs_subscr *subscr, unsigned context_id)
{
struct sgsn_subscriber_pdp_data *pdp;
@@ -263,7 +293,7 @@ static struct sgsn_subscriber_pdp_data *gprs_subscr_pdp_data_get_by_id(
}
-static void gprs_subscr_gsup_insert_data(struct gsm_subscriber *subscr,
+static void gprs_subscr_gsup_insert_data(struct gprs_subscr *subscr,
struct osmo_gsup_message *gsup_msg)
{
struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
@@ -340,7 +370,7 @@ static void gprs_subscr_gsup_insert_data(struct gsm_subscriber *subscr,
}
}
-static int gprs_subscr_handle_gsup_upd_loc_res(struct gsm_subscriber *subscr,
+static int gprs_subscr_handle_gsup_upd_loc_res(struct gprs_subscr *subscr,
struct osmo_gsup_message *gsup_msg)
{
/* contrary to MAP, we allow piggy-backing subscriber data onto
@@ -357,7 +387,7 @@ static int gprs_subscr_handle_gsup_upd_loc_res(struct gsm_subscriber *subscr,
return 0;
}
-static int gprs_subscr_handle_gsup_dsd_req(struct gsm_subscriber *subscr,
+static int gprs_subscr_handle_gsup_dsd_req(struct gprs_subscr *subscr,
struct osmo_gsup_message *gsup_msg)
{
struct osmo_gsup_message gsup_reply = {0};
@@ -377,7 +407,7 @@ static int gprs_subscr_handle_gsup_dsd_req(struct gsm_subscriber *subscr,
return gprs_subscr_tx_gsup_message(subscr, &gsup_reply);
}
-static int gprs_subscr_handle_gsup_isd_req(struct gsm_subscriber *subscr,
+static int gprs_subscr_handle_gsup_isd_req(struct gprs_subscr *subscr,
struct osmo_gsup_message *gsup_msg)
{
struct osmo_gsup_message gsup_reply = {0};
@@ -409,7 +439,7 @@ static int check_cause(int cause)
}
}
-static int gprs_subscr_handle_gsup_auth_err(struct gsm_subscriber *subscr,
+static int gprs_subscr_handle_gsup_auth_err(struct gprs_subscr *subscr,
struct osmo_gsup_message *gsup_msg)
{
unsigned idx;
@@ -462,7 +492,7 @@ static int gprs_subscr_handle_gsup_auth_err(struct gsm_subscriber *subscr,
return -gsup_msg->cause;
}
-static int gprs_subscr_handle_gsup_upd_loc_err(struct gsm_subscriber *subscr,
+static int gprs_subscr_handle_gsup_upd_loc_err(struct gprs_subscr *subscr,
struct osmo_gsup_message *gsup_msg)
{
int cause_err;
@@ -523,7 +553,7 @@ static int gprs_subscr_handle_gsup_purge_no_subscr(
return 0;
}
-static int gprs_subscr_handle_gsup_purge_res(struct gsm_subscriber *subscr,
+static int gprs_subscr_handle_gsup_purge_res(struct gprs_subscr *subscr,
struct osmo_gsup_message *gsup_msg)
{
LOGGSUBSCRP(LOGL_INFO, subscr, "Completing purge MS\n");
@@ -535,7 +565,7 @@ static int gprs_subscr_handle_gsup_purge_res(struct gsm_subscriber *subscr,
return 0;
}
-static int gprs_subscr_handle_gsup_purge_err(struct gsm_subscriber *subscr,
+static int gprs_subscr_handle_gsup_purge_err(struct gprs_subscr *subscr,
struct osmo_gsup_message *gsup_msg)
{
LOGGSUBSCRP(LOGL_NOTICE, subscr,
@@ -568,7 +598,7 @@ static int gprs_subscr_handle_gsup_purge_err(struct gsm_subscriber *subscr,
return -gsup_msg->cause;
}
-static int gprs_subscr_handle_loc_cancel_req(struct gsm_subscriber *subscr,
+static int gprs_subscr_handle_loc_cancel_req(struct gprs_subscr *subscr,
struct osmo_gsup_message *gsup_msg)
{
struct osmo_gsup_message gsup_reply = {0};
@@ -629,7 +659,7 @@ int gprs_subscr_rx_gsup_message(struct msgb *msg)
int rc = 0;
struct osmo_gsup_message gsup_msg = {0};
- struct gsm_subscriber *subscr;
+ struct gprs_subscr *subscr;
rc = osmo_gsup_decode(data, data_len, &gsup_msg);
if (rc < 0) {
@@ -715,12 +745,12 @@ int gprs_subscr_rx_gsup_message(struct msgb *msg)
break;
};
- subscr_put(subscr);
+ gprs_subscr_put(subscr);
return rc;
}
-int gprs_subscr_purge(struct gsm_subscriber *subscr)
+int gprs_subscr_purge(struct gprs_subscr *subscr)
{
struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
struct osmo_gsup_message gsup_msg = {0};
@@ -736,7 +766,7 @@ int gprs_subscr_purge(struct gsm_subscriber *subscr)
return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
}
-int gprs_subscr_query_auth_info(struct gsm_subscriber *subscr)
+int gprs_subscr_query_auth_info(struct gprs_subscr *subscr)
{
struct osmo_gsup_message gsup_msg = {0};
@@ -747,7 +777,7 @@ int gprs_subscr_query_auth_info(struct gsm_subscriber *subscr)
return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
}
-int gprs_subscr_location_update(struct gsm_subscriber *subscr)
+int gprs_subscr_location_update(struct gprs_subscr *subscr)
{
struct osmo_gsup_message gsup_msg = {0};
@@ -758,60 +788,59 @@ int gprs_subscr_location_update(struct gsm_subscriber *subscr)
return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
}
-void gprs_subscr_update(struct gsm_subscriber *subscr)
+void gprs_subscr_update(struct gprs_subscr *subscr)
{
LOGGSUBSCRP(LOGL_DEBUG, subscr, "Updating subscriber data\n");
subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
- subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
+ subscr->flags &= ~GPRS_SUBSCRIBER_FIRST_CONTACT;
if (subscr->sgsn_data->mm)
sgsn_update_subscriber_data(subscr->sgsn_data->mm);
}
-void gprs_subscr_update_auth_info(struct gsm_subscriber *subscr)
+void gprs_subscr_update_auth_info(struct gprs_subscr *subscr)
{
LOGGSUBSCRP(LOGL_DEBUG, subscr,
"Updating subscriber authentication info\n");
subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
- subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
+ subscr->flags &= ~GPRS_SUBSCRIBER_FIRST_CONTACT;
if (subscr->sgsn_data->mm)
sgsn_update_subscriber_data(subscr->sgsn_data->mm);
}
-struct gsm_subscriber *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mmctx)
+struct gprs_subscr *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mmctx)
{
- struct gsm_subscriber *subscr = NULL;
+ struct gprs_subscr *subscr = NULL;
if (mmctx->subscr)
- return subscr_get(mmctx->subscr);
+ return gprs_subscr_get(mmctx->subscr);
if (mmctx->imsi[0])
subscr = gprs_subscr_get_by_imsi(mmctx->imsi);
if (!subscr) {
subscr = gprs_subscr_get_or_create(mmctx->imsi);
- subscr->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
+ subscr->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
subscr->flags &= ~GPRS_SUBSCRIBER_ENABLE_PURGE;
}
- osmo_strlcpy(subscr->equipment.imei, mmctx->imei,
- sizeof(subscr->equipment.imei));
+ osmo_strlcpy(subscr->imei, mmctx->imei, sizeof(subscr->imei));
if (subscr->lac != mmctx->ra.lac)
subscr->lac = mmctx->ra.lac;
subscr->sgsn_data->mm = mmctx;
- mmctx->subscr = subscr_get(subscr);
+ mmctx->subscr = gprs_subscr_get(subscr);
return subscr;
}
int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
{
- struct gsm_subscriber *subscr = NULL;
+ struct gprs_subscr *subscr = NULL;
int rc;
LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber data update\n");
@@ -821,13 +850,13 @@ int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
subscr->flags |= GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
rc = gprs_subscr_location_update(subscr);
- subscr_put(subscr);
+ gprs_subscr_put(subscr);
return rc;
}
int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx)
{
- struct gsm_subscriber *subscr = NULL;
+ struct gprs_subscr *subscr = NULL;
int rc;
LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber authentication info\n");
@@ -837,6 +866,40 @@ int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx)
subscr->flags |= GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
rc = gprs_subscr_query_auth_info(subscr);
- subscr_put(subscr);
+ gprs_subscr_put(subscr);
return rc;
}
+
+static void gprs_subscr_free(struct gprs_subscr *gsub)
+{
+ llist_del(&gsub->entry);
+ talloc_free(gsub);
+}
+
+struct gprs_subscr *_gprs_subscr_get(struct gprs_subscr *gsub,
+ const char *file, int line)
+{
+ OSMO_ASSERT(gsub->use_count < INT_MAX);
+ gsub->use_count++;
+ LOGPSRC(DREF, LOGL_DEBUG, file, line,
+ "subscr %s usage increases to: %d\n",
+ gsub->imsi, gsub->use_count);
+ return gsub;
+}
+
+struct gprs_subscr *_gprs_subscr_put(struct gprs_subscr *gsub,
+ const char *file, int line)
+{
+ gsub->use_count--;
+ LOGPSRC(DREF, gsub->use_count >= 0? LOGL_DEBUG : LOGL_ERROR,
+ file, line,
+ "subscr %s usage decreases to: %d%s\n",
+ gsub->imsi, gsub->use_count,
+ gsub->keep_in_ram? ", keep-in-ram flag is set" : "");
+ if (gsub->use_count > 0)
+ return gsub;
+ if (gsub->keep_in_ram)
+ return gsub;
+ gprs_subscr_free(gsub);
+ return NULL;
+}