diff options
Diffstat (limited to 'openbsc/src/libmsc/gsm_subscriber.c')
-rw-r--r-- | openbsc/src/libmsc/gsm_subscriber.c | 265 |
1 files changed, 37 insertions, 228 deletions
diff --git a/openbsc/src/libmsc/gsm_subscriber.c b/openbsc/src/libmsc/gsm_subscriber.c index 1a03cf76e..20c02c6b3 100644 --- a/openbsc/src/libmsc/gsm_subscriber.c +++ b/openbsc/src/libmsc/gsm_subscriber.c @@ -39,11 +39,10 @@ #include <openbsc/signal.h> #include <openbsc/db.h> #include <openbsc/chan_alloc.h> +#include <openbsc/vlr.h> void *tall_sub_req_ctx; -extern struct llist_head *subscr_bsc_active_subscribers(void); - int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq, gsm_cbfn *cb, void *cb_data); @@ -62,31 +61,35 @@ struct subscr_request { void *param; }; -static struct gsm_subscriber *get_subscriber(struct gsm_subscriber_group *sgrp, - int type, const char *ident) +static struct bsc_subscr *vlr_subscr_to_bsc_sub(struct llist_head *bsc_subscribers, + struct vlr_subscr *vsub) { - struct gsm_subscriber *subscr = db_get_subscriber(type, ident); - if (subscr) - subscr->group = sgrp; - return subscr; + struct bsc_subscr *sub; + /* TODO MSC split -- creating a BSC subscriber directly from MSC data + * structures in RAM. At some point the MSC will send a message to the + * BSC instead. */ + sub = bsc_subscr_find_or_create_by_imsi(bsc_subscribers, vsub->imsi); + sub->tmsi = vsub->tmsi; + sub->lac = vsub->lac; + return sub; } /* * We got the channel assigned and can now hand this channel * over to one of our callbacks. */ -static int subscr_paging_dispatch(unsigned int hooknum, unsigned int event, - struct msgb *msg, void *data, void *param) +int subscr_paging_dispatch(unsigned int hooknum, unsigned int event, + struct msgb *msg, void *data, void *param) { struct subscr_request *request, *tmp; struct gsm_subscriber_connection *conn = data; - struct gsm_subscriber *subscr = param; + struct vlr_subscr *vsub = param; struct paging_signal_data sig_data; struct bsc_subscr *bsub; struct gsm_network *net; - OSMO_ASSERT(subscr && subscr->is_paging); - net = subscr->group->net; + OSMO_ASSERT(vsub && vsub->cs.is_paging); + net = vsub->vlr->user_ctx; /* * Stop paging on all other BTS. E.g. if this is @@ -95,18 +98,12 @@ static int subscr_paging_dispatch(unsigned int hooknum, unsigned int event, * and forget we wanted to page. */ - /* TODO MSC split -- creating a BSC subscriber directly from MSC data - * structures in RAM. At some point the MSC will send a message to the - * BSC instead. */ - bsub = bsc_subscr_find_or_create_by_imsi(net->bsc_subscribers, - subscr->imsi); - bsub->tmsi = subscr->tmsi; - bsub->lac = subscr->lac; + bsub = vlr_subscr_to_bsc_sub(conn->network->bsc_subscribers, vsub); paging_request_stop(&net->bts_list, NULL, bsub, NULL, NULL); bsc_subscr_put(bsub); /* Inform parts of the system we don't know */ - sig_data.subscr = subscr; + sig_data.vsub = vsub; sig_data.bts = conn ? conn->bts : NULL; sig_data.conn = conn; sig_data.paging_result = event; @@ -117,15 +114,15 @@ static int subscr_paging_dispatch(unsigned int hooknum, unsigned int event, &sig_data ); - llist_for_each_entry_safe(request, tmp, &subscr->requests, entry) { + llist_for_each_entry_safe(request, tmp, &vsub->cs.requests, entry) { llist_del(&request->entry); request->cbfn(hooknum, event, msg, data, request->param); talloc_free(request); } /* balanced with the moment we start paging */ - subscr->is_paging = 0; - subscr_put(subscr); + vsub->cs.is_paging = false; + vlr_subscr_put(vsub); return 0; } @@ -176,46 +173,41 @@ static int subscr_paging_cb(unsigned int hooknum, unsigned int event, return gsm48_secure_channel(conn, pr->key_seq, subscr_paging_sec_cb, param); } -struct subscr_request *subscr_request_channel(struct gsm_subscriber *subscr, - int channel_type, gsm_cbfn *cbfn, void *param) +struct subscr_request *subscr_request_channel(struct vlr_subscr *vsub, + int channel_type, + gsm_cbfn *cbfn, void *param) { int rc; struct subscr_request *request; struct bsc_subscr *bsub; - struct gsm_network *net = subscr->group->net; + struct gsm_network *net = vsub->vlr->user_ctx; /* Start paging.. we know it is async so we can do it before */ - if (!subscr->is_paging) { + if (!vsub->cs.is_paging) { LOGP(DMM, LOGL_DEBUG, "Subscriber %s not paged yet.\n", - subscr_name(subscr)); - /* TODO MSC split -- creating a BSC subscriber directly from - * MSC data structures in RAM. At some point the MSC will send - * a message to the BSC instead. */ - bsub = bsc_subscr_find_or_create_by_imsi(net->bsc_subscribers, - subscr->imsi); - bsub->tmsi = subscr->tmsi; - bsub->lac = subscr->lac; + vlr_subscr_name(vsub)); + bsub = vlr_subscr_to_bsc_sub(net->bsc_subscribers, vsub); rc = paging_request(net, bsub, channel_type, subscr_paging_cb, - subscr); + vsub); bsc_subscr_put(bsub); if (rc <= 0) { LOGP(DMM, LOGL_ERROR, "Subscriber %s paging failed: %d\n", - subscr_name(subscr), rc); + vlr_subscr_name(vsub), rc); return NULL; } /* reduced on the first paging callback */ - subscr_get(subscr); - subscr->is_paging = 1; + vlr_subscr_get(vsub); + vsub->cs.is_paging = true; } /* TODO: Stop paging in case of memory allocation failure */ - request = talloc_zero(subscr, struct subscr_request); + request = talloc_zero(vsub, struct subscr_request); if (!request) return NULL; request->cbfn = cbfn; request->param = param; - llist_add_tail(&request->entry, &subscr->requests); + llist_add_tail(&request->entry, &vsub->cs.requests); return request; } @@ -225,196 +217,13 @@ void subscr_remove_request(struct subscr_request *request) talloc_free(request); } -struct gsm_subscriber *subscr_create_subscriber(struct gsm_subscriber_group *sgrp, - const char *imsi) -{ - struct gsm_subscriber *subscr = db_create_subscriber(imsi, - sgrp->net->ext_min, - sgrp->net->ext_max, - sgrp->net->auto_assign_exten); - if (subscr) - subscr->group = sgrp; - return subscr; -} - -struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_subscriber_group *sgrp, - uint32_t tmsi) -{ - char tmsi_string[14]; - struct gsm_subscriber *subscr; - - /* we might have a record in memory already */ - llist_for_each_entry(subscr, subscr_bsc_active_subscribers(), entry) { - if (tmsi == subscr->tmsi) - return subscr_get(subscr); - } - - sprintf(tmsi_string, "%u", tmsi); - return get_subscriber(sgrp, GSM_SUBSCRIBER_TMSI, tmsi_string); -} - -struct gsm_subscriber *subscr_get_by_imsi(struct gsm_subscriber_group *sgrp, - const char *imsi) -{ - struct gsm_subscriber *subscr; - - llist_for_each_entry(subscr, subscr_bsc_active_subscribers(), entry) { - if (strcmp(subscr->imsi, imsi) == 0) - return subscr_get(subscr); - } - - return get_subscriber(sgrp, GSM_SUBSCRIBER_IMSI, imsi); -} - -struct gsm_subscriber *subscr_get_by_extension(struct gsm_subscriber_group *sgrp, - const char *ext) -{ - struct gsm_subscriber *subscr; - - llist_for_each_entry(subscr, subscr_bsc_active_subscribers(), entry) { - if (strcmp(subscr->extension, ext) == 0) - return subscr_get(subscr); - } - - return get_subscriber(sgrp, GSM_SUBSCRIBER_EXTENSION, ext); -} - -struct gsm_subscriber *subscr_get_by_id(struct gsm_subscriber_group *sgrp, - unsigned long long id) -{ - struct gsm_subscriber *subscr; - char buf[32]; - sprintf(buf, "%llu", id); - - llist_for_each_entry(subscr, subscr_bsc_active_subscribers(), entry) { - if (subscr->id == id) - return subscr_get(subscr); - } - - return get_subscriber(sgrp, GSM_SUBSCRIBER_ID, buf); -} - -int subscr_update_expire_lu(struct gsm_subscriber *s, struct gsm_bts *bts) -{ - int rc; - - if (!s) { - LOGP(DMM, LOGL_ERROR, "LU Expiration but NULL subscriber\n"); - return -1; - } - if (!bts) { - LOGP(DMM, LOGL_ERROR, "%s: LU Expiration but NULL bts\n", - subscr_name(s)); - return -1; - } - - /* Table 10.5.33: The T3212 timeout value field is coded as the - * binary representation of the timeout value for - * periodic updating in decihours. Mark the subscriber as - * inactive if it missed two consecutive location updates. - * Timeout is twice the t3212 value plus one minute */ - - /* Is expiration handling enabled? */ - if (bts->si_common.chan_desc.t3212 == 0) - s->expire_lu = GSM_SUBSCRIBER_NO_EXPIRATION; - else - s->expire_lu = time(NULL) + - (bts->si_common.chan_desc.t3212 * 60 * 6 * 2) + 60; - - rc = db_sync_subscriber(s); - db_subscriber_update(s); - return rc; -} - -int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason) -{ - int rc; - - /* FIXME: Migrate pending requests from one BSC to another */ - switch (reason) { - case GSM_SUBSCRIBER_UPDATE_ATTACHED: - s->group = bts->network->subscr_group; - /* Indicate "attached to LAC" */ - s->lac = bts->location_area_code; - - LOGP(DMM, LOGL_INFO, "Subscriber %s ATTACHED LAC=%u\n", - subscr_name(s), s->lac); - - /* - * The below will set a new expire_lu but as a side-effect - * the new lac will be saved in the database. - */ - rc = subscr_update_expire_lu(s, bts); - osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_ATTACHED, s); - break; - case GSM_SUBSCRIBER_UPDATE_DETACHED: - /* Only detach if we are currently in this area */ - if (bts->location_area_code == s->lac) - s->lac = GSM_LAC_RESERVED_DETACHED; - LOGP(DMM, LOGL_INFO, "Subscriber %s DETACHED\n", subscr_name(s)); - rc = db_sync_subscriber(s); - db_subscriber_update(s); - osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_DETACHED, s); - break; - default: - fprintf(stderr, "subscr_update with unknown reason: %d\n", - reason); - rc = db_sync_subscriber(s); - db_subscriber_update(s); - break; - }; - - return rc; -} - -void subscr_update_from_db(struct gsm_subscriber *sub) -{ - db_subscriber_update(sub); -} - -static void subscr_expire_callback(void *data, long long unsigned int id) -{ - struct gsm_network *net = data; - struct gsm_subscriber *s = subscr_get_by_id(net->subscr_group, id); - struct gsm_subscriber_connection *conn = connection_for_subscr(s); - - /* - * The subscriber is active and the phone stopped the timer. As - * we don't want to periodically update the database for active - * subscribers we will just do it when the subscriber was selected - * for expiration. This way on the next around another subscriber - * will be selected. - */ - if (conn && conn->expire_timer_stopped) { - LOGP(DMM, LOGL_DEBUG, "Not expiring subscriber %s (ID %llu)\n", - subscr_name(s), id); - subscr_update_expire_lu(s, conn->bts); - subscr_put(s); - return; - } - - - LOGP(DMM, LOGL_NOTICE, "Expiring inactive subscriber %s (ID %llu)\n", - subscr_name(s), id); - s->lac = GSM_LAC_RESERVED_DETACHED; - db_sync_subscriber(s); - - subscr_put(s); -} - -void subscr_expire(struct gsm_subscriber_group *sgrp) -{ - db_subscriber_expire(sgrp->net, subscr_expire_callback); -} - -struct gsm_subscriber_connection *connection_for_subscr(struct gsm_subscriber *subscr) +struct gsm_subscriber_connection *connection_for_subscr(struct vlr_subscr *vsub) { - /* FIXME: replace this with a backpointer in gsm_subscriber? */ - struct gsm_network *net = subscr->group->net; + struct gsm_network *net = vsub->vlr->user_ctx; struct gsm_subscriber_connection *conn; llist_for_each_entry(conn, &net->subscr_conns, entry) { - if (conn->subscr == subscr) + if (conn->vsub == vsub) return conn; } |