diff options
Diffstat (limited to 'src/libvlr')
-rw-r--r-- | src/libvlr/vlr.c | 110 | ||||
-rw-r--r-- | src/libvlr/vlr_access_req_fsm.c | 10 | ||||
-rw-r--r-- | src/libvlr/vlr_lu_fsm.c | 16 | ||||
-rw-r--r-- | src/libvlr/vlr_sgs.c | 38 |
4 files changed, 94 insertions, 80 deletions
diff --git a/src/libvlr/vlr.c b/src/libvlr/vlr.c index cd4209d66..1afdbecc9 100644 --- a/src/libvlr/vlr.c +++ b/src/libvlr/vlr.c @@ -119,6 +119,7 @@ const char *vlr_subscr_msisdn_or_name(const struct vlr_subscr *vsub) struct vlr_subscr *_vlr_subscr_find_by_imsi(struct vlr_instance *vlr, const char *imsi, + const char *use, const char *file, int line) { struct vlr_subscr *vsub; @@ -127,14 +128,17 @@ struct vlr_subscr *_vlr_subscr_find_by_imsi(struct vlr_instance *vlr, return NULL; llist_for_each_entry(vsub, &vlr->subscribers, list) { - if (vlr_subscr_matches_imsi(vsub, imsi)) - return _vlr_subscr_get(vsub, file, line); + if (vlr_subscr_matches_imsi(vsub, imsi)) { + vlr_subscr_get_src(vsub, use, file, line); + return vsub; + } } return NULL; } struct vlr_subscr *_vlr_subscr_find_by_tmsi(struct vlr_instance *vlr, uint32_t tmsi, + const char *use, const char *file, int line) { struct vlr_subscr *vsub; @@ -143,14 +147,17 @@ struct vlr_subscr *_vlr_subscr_find_by_tmsi(struct vlr_instance *vlr, return NULL; llist_for_each_entry(vsub, &vlr->subscribers, list) { - if (vlr_subscr_matches_tmsi(vsub, tmsi)) - return _vlr_subscr_get(vsub, file, line); + if (vlr_subscr_matches_tmsi(vsub, tmsi)) { + vlr_subscr_get_src(vsub, use, file, line); + return vsub; + } } return NULL; } struct vlr_subscr *_vlr_subscr_find_by_msisdn(struct vlr_instance *vlr, const char *msisdn, + const char *use, const char *file, int line) { struct vlr_subscr *vsub; @@ -159,8 +166,10 @@ struct vlr_subscr *_vlr_subscr_find_by_msisdn(struct vlr_instance *vlr, return NULL; llist_for_each_entry(vsub, &vlr->subscribers, list) { - if (vlr_subscr_matches_msisdn(vsub, msisdn)) - return _vlr_subscr_get(vsub, file, line); + if (vlr_subscr_matches_msisdn(vsub, msisdn)) { + vlr_subscr_get_src(vsub, use, file, line); + return vsub; + } } return NULL; } @@ -217,30 +226,24 @@ static int vlr_tx_gsup_error_reply(const struct vlr_instance *vlr, return vlr_tx_gsup_message(vlr, &gsup_reply); } -struct vlr_subscr *_vlr_subscr_get(struct vlr_subscr *sub, const char *file, int line) +static int vlr_subscr_use_cb(struct osmo_use_count_entry *e, int32_t old_use_count, const char *file, int line) { - if (!sub) - return NULL; - OSMO_ASSERT(sub->use_count < INT_MAX); - sub->use_count++; - LOGPSRC(DREF, LOGL_DEBUG, file, line, - "VLR subscr %s usage increases to: %d\n", - vlr_subscr_name(sub), sub->use_count); - return sub; -} + struct vlr_subscr *vsub = e->use_count->talloc_object; + char buf[128]; -struct vlr_subscr *_vlr_subscr_put(struct vlr_subscr *sub, const char *file, int line) -{ - if (!sub) - return NULL; - sub->use_count--; - LOGPSRC(DREF, sub->use_count >= 0? LOGL_DEBUG : LOGL_ERROR, - file, line, - "VLR subscr %s usage decreases to: %d\n", - vlr_subscr_name(sub), sub->use_count); - if (sub->use_count <= 0) - vlr_subscr_free(sub); - return NULL; + if (!e->use) + return -EINVAL; + + LOGPSRC(DREF, LOGL_DEBUG, file, line, "VLR subscr %s %s %s: now used by %s\n", + vlr_subscr_name(vsub), (e->count - old_use_count) > 0? "+" : "-", e->use, + osmo_use_count_name_buf(buf, sizeof(buf), e->use_count)); + + if (e->count < 0) + return -ERANGE; + + if (osmo_use_count_total(e->use_count) <= 0) + vlr_subscr_free(vsub); + return 0; } /* Allocate a new subscriber and insert it into list */ @@ -250,9 +253,16 @@ static struct vlr_subscr *_vlr_subscr_alloc(struct vlr_instance *vlr) int i; vsub = talloc_zero(vlr, struct vlr_subscr); - vsub->vlr = vlr; - vsub->tmsi = GSM_RESERVED_TMSI; - vsub->tmsi_new = GSM_RESERVED_TMSI; + *vsub = (struct vlr_subscr){ + .vlr = vlr, + .tmsi = GSM_RESERVED_TMSI, + .tmsi_new = GSM_RESERVED_TMSI, + .use_count = (struct osmo_use_count){ + .talloc_object = vsub, + .use_cb = vlr_subscr_use_cb, + }, + }; + osmo_use_count_make_static_entries(&vsub->use_count, vsub->use_count_buf, ARRAY_SIZE(vsub->use_count_buf)); for (i = 0; i < ARRAY_SIZE(vsub->auth_tuples); i++) vsub->auth_tuples[i].key_seq = VLR_KEY_SEQ_INVAL; @@ -269,11 +279,6 @@ static struct vlr_subscr *_vlr_subscr_alloc(struct vlr_instance *vlr) return vsub; } -struct vlr_subscr *vlr_subscr_alloc(struct vlr_instance *vlr) -{ - return vlr_subscr_get(_vlr_subscr_alloc(vlr)); -} - /* Send a GSUP Purge MS request. * TODO: this should be sent to the *previous* VLR when this VLR is "taking" * this subscriber, not to the HLR? */ @@ -297,12 +302,12 @@ void vlr_subscr_cancel_attach_fsm(struct vlr_subscr *vsub, if (!vsub) return; - vlr_subscr_get(vsub); + vlr_subscr_get(vsub, __func__); if (vsub->lu_fsm) vlr_loc_update_cancel(vsub->lu_fsm, fsm_cause, gsm48_cause); if (vsub->proc_arq_fsm) vlr_parq_cancel(vsub->proc_arq_fsm, fsm_cause, gsm48_cause); - vlr_subscr_put(vsub); + vlr_subscr_put(vsub, __func__); } /* Call vlr_subscr_cancel(), then completely drop the entry from the VLR */ @@ -327,6 +332,7 @@ int vlr_subscr_alloc_tmsi(struct vlr_subscr *vsub) struct vlr_instance *vlr = vsub->vlr; uint32_t tmsi; int tried, rc; + struct vlr_subscr *other_vsub; for (tried = 0; tried < 100; tried++) { rc = osmo_get_rand_id((uint8_t *) &tmsi, sizeof(tmsi)); @@ -349,8 +355,10 @@ int vlr_subscr_alloc_tmsi(struct vlr_subscr *vsub) } /* If this TMSI is already in use, try another one. */ - if (vlr_subscr_find_by_tmsi(vlr, tmsi)) + if ((other_vsub = vlr_subscr_find_by_tmsi(vlr, tmsi, __func__))) { + vlr_subscr_put(other_vsub, __func__); continue; + } vsub->tmsi_new = tmsi; vsub->vlr->ops.subscr_update(vsub); @@ -368,21 +376,23 @@ int vlr_subscr_alloc_tmsi(struct vlr_subscr *vsub) * \param[out] created if non-NULL, returns whether a new entry was created. */ struct vlr_subscr *_vlr_subscr_find_or_create_by_imsi(struct vlr_instance *vlr, const char *imsi, + const char *use, bool *created, const char *file, int line) { struct vlr_subscr *vsub; - vsub = _vlr_subscr_find_by_imsi(vlr, imsi, file, line); + vsub = _vlr_subscr_find_by_imsi(vlr, imsi, use, file, line); if (vsub) { if (created) *created = false; return vsub; } - vsub = _vlr_subscr_get(_vlr_subscr_alloc(vlr), file, line); + vsub = _vlr_subscr_alloc(vlr); if (!vsub) return NULL; + vlr_subscr_get_src(vsub, use, file, line); vlr_subscr_set_imsi(vsub, imsi); LOGP(DVLR, LOGL_INFO, "New subscr, IMSI: %s\n", vsub->imsi); if (created) @@ -396,21 +406,23 @@ struct vlr_subscr *_vlr_subscr_find_or_create_by_imsi(struct vlr_instance *vlr, * \param[out] created if non-NULL, returns whether a new entry was created. */ struct vlr_subscr *_vlr_subscr_find_or_create_by_tmsi(struct vlr_instance *vlr, uint32_t tmsi, + const char *use, bool *created, const char *file, int line) { struct vlr_subscr *vsub; - vsub = _vlr_subscr_find_by_tmsi(vlr, tmsi, file, line); + vsub = _vlr_subscr_find_by_tmsi(vlr, tmsi, use, file, line); if (vsub) { if (created) *created = false; return vsub; } - vsub = _vlr_subscr_get(_vlr_subscr_alloc(vlr), file, line); + vsub = _vlr_subscr_alloc(vlr); if (!vsub) return NULL; + vlr_subscr_get_src(vsub, use, file, line); vsub->tmsi = tmsi; LOGP(DVLR, LOGL_INFO, "New subscr, TMSI: 0x%08x\n", vsub->tmsi); if (created) @@ -1098,7 +1110,7 @@ int vlr_gsupc_read_cb(struct osmo_gsup_client *gsupc, struct msgb *msg) goto msgb_free_and_return; } - vsub = vlr_subscr_find_by_imsi(vlr, gsup.imsi); + vsub = vlr_subscr_find_by_imsi(vlr, gsup.imsi, __func__); if (!vsub) { switch (gsup.message_type) { case OSMO_GSUP_MSGT_PURGE_MS_RESULT: @@ -1146,7 +1158,7 @@ int vlr_gsupc_read_cb(struct osmo_gsup_client *gsupc, struct msgb *msg) break; } - vlr_subscr_put(vsub); + vlr_subscr_put(vsub, __func__); msgb_free_and_return: msgb_free(msg); @@ -1239,7 +1251,7 @@ bool vlr_subscr_expire(struct vlr_subscr *vsub) if (vsub->lu_complete) { /* balancing the get from vlr_lu_compl_fsm_success() */ vsub->lu_complete = false; - vlr_subscr_put(vsub); + vlr_subscr_put(vsub, VSUB_USE_ATTACHED); return true; } @@ -1425,16 +1437,18 @@ void log_set_filter_vlr_subscr(struct log_target *target, struct vlr_subscr *vlr_subscr) { struct vlr_subscr **fsub = (void*)&target->filter_data[LOG_FLT_VLR_SUBSCR]; + const char *use = "logfilter"; /* free the old data */ if (*fsub) { - vlr_subscr_put(*fsub); + vlr_subscr_put(*fsub, use); *fsub = NULL; } if (vlr_subscr) { target->filter_map |= (1 << LOG_FLT_VLR_SUBSCR); - *fsub = vlr_subscr_get(vlr_subscr); + vlr_subscr_get(vlr_subscr, use); + *fsub = vlr_subscr; } else target->filter_map &= ~(1 << LOG_FLT_VLR_SUBSCR); } diff --git a/src/libvlr/vlr_access_req_fsm.c b/src/libvlr/vlr_access_req_fsm.c index 26db42cb3..3040158cf 100644 --- a/src/libvlr/vlr_access_req_fsm.c +++ b/src/libvlr/vlr_access_req_fsm.c @@ -356,10 +356,10 @@ static void proc_arq_vlr_fn_init(struct osmo_fsm_inst *fi, /* Obtain_Identity_VLR */ if (!par->by_tmsi) { /* IMSI was included */ - vsub = vlr_subscr_find_by_imsi(par->vlr, par->imsi); + vsub = vlr_subscr_find_by_imsi(par->vlr, par->imsi, __func__); } else { /* TMSI was included */ - vsub = vlr_subscr_find_by_tmsi(par->vlr, par->tmsi); + vsub = vlr_subscr_find_by_tmsi(par->vlr, par->tmsi, __func__); } if (vsub) { log_set_context(LOG_CTX_VLR_SUBSCR, vsub); @@ -377,7 +377,7 @@ static void proc_arq_vlr_fn_init(struct osmo_fsm_inst *fi, proc_arq_fsm_done(fi, GSM48_REJECT_NETWORK_FAILURE); else proc_arq_vlr_fn_post_imsi(fi); - vlr_subscr_put(vsub); + vlr_subscr_put(vsub, __func__); return; } /* No VSUB could be resolved. What now? */ @@ -412,7 +412,7 @@ static void proc_arq_vlr_fn_w_obt_imsi(struct osmo_fsm_inst *fi, OSMO_ASSERT(event == PR_ARQ_E_ID_IMSI); - vsub = vlr_subscr_find_by_imsi(vlr, par->imsi); + vsub = vlr_subscr_find_by_imsi(vlr, par->imsi, __func__); if (!vsub) { /* Set User Error: Unidentified Subscriber */ proc_arq_fsm_done(fi, GSM48_REJECT_IMSI_UNKNOWN_IN_VLR); @@ -422,7 +422,7 @@ static void proc_arq_vlr_fn_w_obt_imsi(struct osmo_fsm_inst *fi, proc_arq_fsm_done(fi, GSM48_REJECT_NETWORK_FAILURE); else proc_arq_vlr_fn_post_imsi(fi); - vlr_subscr_put(vsub); + vlr_subscr_put(vsub, __func__); } /* Authenticate_VLR has completed */ diff --git a/src/libvlr/vlr_lu_fsm.c b/src/libvlr/vlr_lu_fsm.c index 7ddf4558d..ecf96fad5 100644 --- a/src/libvlr/vlr_lu_fsm.c +++ b/src/libvlr/vlr_lu_fsm.c @@ -360,7 +360,7 @@ static void vlr_lu_compl_fsm_success(struct osmo_fsm_inst *fi) if (!vsub->lu_complete) { vsub->lu_complete = true; /* Balanced by vlr_subscr_expire() */ - vlr_subscr_get(vsub); + vlr_subscr_get(vsub, VSUB_USE_ATTACHED); } _vlr_lu_compl_fsm_done(fi, VLR_FSM_RESULT_SUCCESS, 0); vlr_sgs_fsm_update_id(vsub); @@ -982,7 +982,7 @@ static int _lu_fsm_associate_vsub(struct osmo_fsm_inst *fi) * someone else's TMSI. * TODO: Otherwise we can ask for the IMSI and verify that it * matches the IMSI on record. */ - vsub = vlr_subscr_find_or_create_by_tmsi(vlr, lfp->tmsi, NULL); + vsub = vlr_subscr_find_or_create_by_tmsi(vlr, lfp->tmsi, __func__, NULL); if (!vsub) { LOGPFSML(fi, LOGL_ERROR, "VLR subscriber allocation failed\n"); @@ -992,27 +992,27 @@ static int _lu_fsm_associate_vsub(struct osmo_fsm_inst *fi) vsub->sub_dataconf_by_hlr_ind = false; if (assoc_lfp_with_sub(fi, vsub)) { - vlr_subscr_put(vsub); + vlr_subscr_put(vsub, __func__); return -1; /* error, fsm failure invoked in assoc_lfp_with_sub() */ } - vlr_subscr_put(vsub); + vlr_subscr_put(vsub, __func__); } else { /* IMSI was used */ - vsub = vlr_subscr_find_or_create_by_imsi(vlr, lfp->imsi, NULL); + vsub = vlr_subscr_find_or_create_by_imsi(vlr, lfp->imsi, __func__, NULL); if (!vsub) { LOGPFSML(fi, LOGL_ERROR, "VLR subscriber allocation failed\n"); lu_fsm_failure(fi, GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER); - vlr_subscr_put(vsub); + vlr_subscr_put(vsub, __func__); return -1; } vsub->sub_dataconf_by_hlr_ind = false; if (assoc_lfp_with_sub(fi, vsub)) { - vlr_subscr_put(vsub); + vlr_subscr_put(vsub, __func__); return -1; /* error, fsm failure invoked in assoc_lfp_with_sub() */ } - vlr_subscr_put(vsub); + vlr_subscr_put(vsub, __func__); } return 0; } diff --git a/src/libvlr/vlr_sgs.c b/src/libvlr/vlr_sgs.c index 06737db46..3ee7799a8 100644 --- a/src/libvlr/vlr_sgs.c +++ b/src/libvlr/vlr_sgs.c @@ -80,7 +80,7 @@ int vlr_sgs_loc_update(struct vlr_instance *vlr, struct vlr_sgs_cfg *cfg, OSMO_ASSERT(cfg); OSMO_ASSERT(imsi); - vsub = vlr_subscr_find_or_create_by_imsi(vlr, imsi, NULL); + vsub = vlr_subscr_find_or_create_by_imsi(vlr, imsi, VSUB_USE_SGS, NULL); if (!vsub) { LOGP(DSGS, LOGL_ERROR, "VLR subscriber allocation failed\n"); return -EINVAL; @@ -137,7 +137,7 @@ void vlr_sgs_imsi_detach(struct vlr_instance *vlr, const char *imsi, enum sgsap_ struct vlr_subscr *vsub; enum sgs_ue_fsm_event evt; - vsub = vlr_subscr_find_by_imsi(vlr, imsi); + vsub = vlr_subscr_find_by_imsi(vlr, imsi, __func__); if (!vsub) return; @@ -164,12 +164,12 @@ void vlr_sgs_imsi_detach(struct vlr_instance *vlr, const char *imsi, enum sgsap_ } osmo_fsm_inst_dispatch(vsub->sgs_fsm, evt, NULL); - vlr_subscr_put(vsub); /* Detaching from non EPS services essentially means that the * subscriber is detached from 2G. In any case the VLR will * get rid of the subscriber. */ vlr_subscr_expire(vsub); + vlr_subscr_put(vsub, __func__); } /*! Perform an SGs EPS detach. @@ -180,7 +180,7 @@ void vlr_sgs_eps_detach(struct vlr_instance *vlr, const char *imsi, enum sgsap_i { struct vlr_subscr *vsub; enum sgs_ue_fsm_event evt; - vsub = vlr_subscr_find_by_imsi(vlr, imsi); + vsub = vlr_subscr_find_by_imsi(vlr, imsi, __func__); if (!vsub) return; @@ -211,7 +211,7 @@ void vlr_sgs_eps_detach(struct vlr_instance *vlr, const char *imsi, enum sgsap_i if (vsub->expire_lu == VLR_SUBSCRIBER_NO_EXPIRATION) vlr_subscr_enable_expire_lu(vsub); - vlr_subscr_put(vsub); + vlr_subscr_put(vsub, __func__); } /*! Perform an SGs TMSI reallocation complete. @@ -220,12 +220,12 @@ void vlr_sgs_eps_detach(struct vlr_instance *vlr, const char *imsi, enum sgsap_i void vlr_sgs_tmsi_reall_compl(struct vlr_instance *vlr, const char *imsi) { struct vlr_subscr *vsub; - vsub = vlr_subscr_find_by_imsi(vlr, imsi); + vsub = vlr_subscr_find_by_imsi(vlr, imsi, __func__); if (!vsub) return; osmo_fsm_inst_dispatch(vsub->sgs_fsm, SGS_UE_E_RX_TMSI_REALLOC, NULL); - vlr_subscr_put(vsub); + vlr_subscr_put(vsub, __func__); } /*! Notify that an SGs paging has been rejected by the MME. @@ -235,7 +235,7 @@ void vlr_sgs_tmsi_reall_compl(struct vlr_instance *vlr, const char *imsi) void vlr_sgs_pag_rej(struct vlr_instance *vlr, const char *imsi, enum sgsap_sgs_cause cause) { struct vlr_subscr *vsub; - vsub = vlr_subscr_find_by_imsi(vlr, imsi); + vsub = vlr_subscr_find_by_imsi(vlr, imsi, __func__); if (!vsub) return; @@ -246,10 +246,10 @@ void vlr_sgs_pag_rej(struct vlr_instance *vlr, const char *imsi, enum sgsap_sgs_ vlr_subscr_msisdn_or_name(vsub), vlr_sgs_state_timer_name(SGS_STATE_TS5), sgsap_sgs_cause_name(cause)); osmo_fsm_inst_dispatch(vsub->sgs_fsm, SGS_UE_E_RX_PAGING_FAILURE, &cause); - vlr_subscr_put(vsub); - /* Balance ref count increment from vlr_sgs_pag() */ - vlr_subscr_put(vsub); + vlr_subscr_put(vsub, VSUB_USE_SGS_PAGING); + + vlr_subscr_put(vsub, __func__); } /*! Notify that an SGs paging has been accepted by the MME. @@ -258,16 +258,16 @@ void vlr_sgs_pag_rej(struct vlr_instance *vlr, const char *imsi, enum sgsap_sgs_ void vlr_sgs_pag_ack(struct vlr_instance *vlr, const char *imsi) { struct vlr_subscr *vsub; - vsub = vlr_subscr_find_by_imsi(vlr, imsi); + vsub = vlr_subscr_find_by_imsi(vlr, imsi, __func__); if (!vsub) return; /* Stop Ts5 and and consider the paging as successful */ osmo_timer_del(&vsub->sgs.Ts5); - vlr_subscr_put(vsub); - /* Balance ref count increment from vlr_sgs_pag() */ - vlr_subscr_put(vsub); + vlr_subscr_put(vsub, VSUB_USE_SGS_PAGING); + + vlr_subscr_put(vsub, __func__); } /*! Notify that the UE has been marked as unreachable by the MME. @@ -277,7 +277,7 @@ void vlr_sgs_pag_ack(struct vlr_instance *vlr, const char *imsi) void vlr_sgs_ue_unr(struct vlr_instance *vlr, const char *imsi, enum sgsap_sgs_cause cause) { struct vlr_subscr *vsub; - vsub = vlr_subscr_find_by_imsi(vlr, imsi); + vsub = vlr_subscr_find_by_imsi(vlr, imsi, __func__); if (!vsub) return; @@ -289,7 +289,7 @@ void vlr_sgs_ue_unr(struct vlr_instance *vlr, const char *imsi, enum sgsap_sgs_c vlr_subscr_msisdn_or_name(vsub), vlr_sgs_state_timer_name(SGS_STATE_TS5), sgsap_sgs_cause_name(cause)); osmo_fsm_inst_dispatch(vsub->sgs_fsm, SGS_UE_E_RX_SGSAP_UE_UNREACHABLE, &cause); - vlr_subscr_put(vsub); + vlr_subscr_put(vsub, __func__); } /* Callback function that is called when an SGs paging request times out */ @@ -306,7 +306,7 @@ static void Ts5_timeout_cb(void *arg) vlr_subscr_msisdn_or_name(vsub), vlr_sgs_state_timer_name(SGS_STATE_TS5)); /* Balance ref count increment from vlr_sgs_pag() */ - vlr_subscr_put(vsub); + vlr_subscr_put(vsub, VSUB_USE_SGS_PAGING); return; } @@ -346,7 +346,7 @@ void vlr_sgs_pag(struct vlr_subscr *vsub, enum sgsap_service_ind serv_ind) /* Ensure that the reference count is increased by one while the * paging is happening. We will balance this again in vlr_sgs_pag_rej() * and vlr_sgs_pag_ack(); */ - vlr_subscr_get(vsub); + vlr_subscr_get(vsub, VSUB_USE_SGS_PAGING); } /*! Check if the SGs interface is currently paging |