diff options
author | Stefan Sperling <ssperling@sysmocom.de> | 2018-05-15 14:48:04 +0200 |
---|---|---|
committer | Stefan Sperling <ssperling@sysmocom.de> | 2018-05-15 18:46:25 +0200 |
commit | 60af0c888fb69b8f8dc75e41a1bf96309b6f0ea6 (patch) | |
tree | 169fcfd9ac760635e217abf5def8e44289fa313d | |
parent | cb8c75bba030c7ab9f2e49b2f40292a1738f3220 (diff) |
add a test; set lu expiry timestampstsp/lu_expire
Change-Id: Iebdee8b12d22acfcfb265ee41e71cfc8d9eb3ba9
-rw-r--r-- | include/osmocom/msc/gsm_subscriber.h | 1 | ||||
-rw-r--r-- | include/osmocom/msc/vlr.h | 3 | ||||
-rw-r--r-- | src/libmsc/subscr_conn.c | 10 | ||||
-rw-r--r-- | src/libvlr/vlr.c | 59 | ||||
-rw-r--r-- | src/libvlr/vlr_lu_fsm.c | 2 | ||||
-rw-r--r-- | tests/msc_vlr/msc_vlr_test_no_authen.c | 65 |
6 files changed, 139 insertions, 1 deletions
diff --git a/include/osmocom/msc/gsm_subscriber.h b/include/osmocom/msc/gsm_subscriber.h index 16e1037c0..50b4a233b 100644 --- a/include/osmocom/msc/gsm_subscriber.h +++ b/include/osmocom/msc/gsm_subscriber.h @@ -18,6 +18,7 @@ /* gprs_sgsn.h defines additional flags including and above bit 16 (0x10000) */ #define GSM_SUBSCRIBER_NO_EXPIRATION 0x0 +#define GSM_SUBSCRIBER_LU_EXPIRATION_INTERVAL 60 /* in seconds */ enum gsm_subscriber_field { GSM_SUBSCRIBER_IMSI, diff --git a/include/osmocom/msc/vlr.h b/include/osmocom/msc/vlr.h index 0a9ef6fb5..c647ddc4c 100644 --- a/include/osmocom/msc/vlr.h +++ b/include/osmocom/msc/vlr.h @@ -148,6 +148,7 @@ struct vlr_subscr { struct osmo_fsm_inst *proc_arq_fsm; bool lu_complete; + time_t expire_lu; void *msc_conn_ref; @@ -237,6 +238,7 @@ struct vlr_instance { struct llist_head operations; struct gsup_client *gsup_client; struct vlr_ops ops; + struct osmo_timer_list lu_expire_timer; struct { bool retrieve_imeisv_early; bool retrieve_imeisv_ciphered; @@ -379,6 +381,7 @@ void vlr_subscr_cancel_attach_fsm(struct vlr_subscr *vsub, enum osmo_fsm_term_cause fsm_cause, uint8_t gsm48_cause); +void vlr_subscr_enable_expire_lu(struct vlr_subscr *vsub); /* Process Acccess Request FSM */ diff --git a/src/libmsc/subscr_conn.c b/src/libmsc/subscr_conn.c index 1b3b24042..50d7be649 100644 --- a/src/libmsc/subscr_conn.c +++ b/src/libmsc/subscr_conn.c @@ -202,6 +202,11 @@ static bool subscr_conn_fsm_has_active_transactions(struct osmo_fsm_inst *fi) static void subscr_conn_fsm_accepted_enter(struct osmo_fsm_inst *fi, uint32_t prev_state) { + struct gsm_subscriber_connection *conn = fi->priv; + + /* Stop location update expiry for this subscriber. */ + conn->vsub->expire_lu = GSM_SUBSCRIBER_NO_EXPIRATION; + if (!subscr_conn_fsm_has_active_transactions(fi)) osmo_fsm_inst_dispatch(fi, SUBSCR_CONN_E_UNUSED, NULL); } @@ -278,6 +283,11 @@ static void subscr_conn_fsm_releasing_onenter(struct osmo_fsm_inst *fi, uint32_t /* Cancel all VLR FSMs, if any */ vlr_subscr_cancel_attach_fsm(conn->vsub, OSMO_FSM_TERM_ERROR, GSM48_REJECT_CONGESTION); + if (conn->vsub) { + /* Restart LU expiry for this subscriber. */ + vlr_subscr_enable_expire_lu(conn->vsub); + } + /* If we're closing in a middle of a trans, we need to clean up */ trans_conn_closed(conn); diff --git a/src/libvlr/vlr.c b/src/libvlr/vlr.c index 2d232be74..5a908765d 100644 --- a/src/libvlr/vlr.c +++ b/src/libvlr/vlr.c @@ -22,6 +22,7 @@ #include <osmocom/core/linuxlist.h> #include <osmocom/core/fsm.h> #include <osmocom/core/utils.h> +#include <osmocom/core/timer.h> #include <osmocom/gsm/protocol/gsm_04_08_gprs.h> #include <osmocom/gsm/gsup.h> #include <osmocom/gsm/apn.h> @@ -460,6 +461,59 @@ int vlr_subscr_changed(struct vlr_subscr *vsub) return 0; } +void +vlr_subscr_enable_expire_lu(struct vlr_subscr *vsub) +{ + struct gsm_network *net = vsub->vlr->user_ctx; /* XXX move t3212 into struct vlr_instance? */ + struct timeval now; + + /* Table 10.5.33: The T3212 timeout value 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 */ + if (osmo_gettimeofday(&now, NULL) == 0) { + LOGP(DVLR, LOGL_DEBUG, "IMSI=%s id=%llu: current time is %llu\n", vsub->imsi, vsub->id, (unsigned long long)now.tv_sec); + vsub->expire_lu = now.tv_sec + (net->t3212 * 60 * 6 * 2) + 60; + LOGP(DVLR, LOGL_DEBUG, "IMSI=%s id=%llu: Location Update expiry at %llu\n", + vsub->imsi, vsub->id, (unsigned long long)vsub->expire_lu); + } else { + LOGP(DVLR, LOGL_ERROR, + "IMSI=%s id=%llu: Could not enable Location Update expiry: unable to read current time\n", + vsub->imsi, vsub->id); + vsub->expire_lu = GSM_SUBSCRIBER_NO_EXPIRATION; /* XXX */ + } +} + +void +vlr_subscr_expire_lu(void *data) +{ + struct vlr_instance *vlr = data; + struct vlr_subscr *vsub; + struct timeval now; + + LOGP(DVLR, LOGL_ERROR, "Hi"); + if (llist_empty(&vlr->subscribers)) + return; + + if (osmo_gettimeofday(&now, NULL) != 0) { + LOGP(DVLR, LOGL_ERROR, "Skipping Location Update expiry: Could not read current time\n"); + return; + } + + llist_for_each_entry(vsub, &vlr->subscribers, list) { + if (vsub->expire_lu == GSM_SUBSCRIBER_NO_EXPIRATION) + continue; + if (vsub->expire_lu < now.tv_sec) + continue; + + LOGP(DVLR, LOGL_DEBUG, "IMSI=%s id=%llu: Location Update expired\n", vsub->imsi, vsub->id); + vlr_subscr_rx_imsi_detach(vsub); + } + + osmo_timer_schedule(&vlr->lu_expire_timer, GSM_SUBSCRIBER_LU_EXPIRATION_INTERVAL, 0); +} + /*********************************************************************** * PDP context data ***********************************************************************/ @@ -1093,12 +1147,14 @@ bool vlr_subscr_expire(struct vlr_subscr *vsub) return false; } +/* See TS 32.012 version 9.10.0 4.3.2.1 "Process Detach_IMSI_VLR" */ int vlr_subscr_rx_imsi_detach(struct vlr_subscr *vsub) { /* paranoia: should any LU or PARQ FSMs still be running, stop them. */ vlr_subscr_cancel_attach_fsm(vsub, OSMO_FSM_TERM_ERROR, GSM48_REJECT_CONGESTION); vsub->imsi_detached_flag = true; + vsub->expire_lu = GSM_SUBSCRIBER_NO_EXPIRATION; /* balancing the get from vlr_lu_compl_fsm_success() */ vlr_subscr_expire(vsub); @@ -1139,6 +1195,8 @@ struct vlr_instance *vlr_alloc(void *ctx, const struct vlr_ops *ops) INIT_LLIST_HEAD(&vlr->operations); memcpy(&vlr->ops, ops, sizeof(vlr->ops)); + osmo_timer_setup(&vlr->lu_expire_timer, vlr_subscr_expire_lu, vlr); + /* defaults */ vlr->cfg.assign_tmsi = true; @@ -1165,6 +1223,7 @@ int vlr_start(const char *gsup_unit_name, struct vlr_instance *vlr, return -ENOMEM; vlr->gsup_client->data = vlr; + osmo_timer_schedule(&vlr->lu_expire_timer, GSM_SUBSCRIBER_LU_EXPIRATION_INTERVAL, 0); return 0; } diff --git a/src/libvlr/vlr_lu_fsm.c b/src/libvlr/vlr_lu_fsm.c index 3073bd6dc..a713fcbe1 100644 --- a/src/libvlr/vlr_lu_fsm.c +++ b/src/libvlr/vlr_lu_fsm.c @@ -356,7 +356,7 @@ static void vlr_lu_compl_fsm_success(struct osmo_fsm_inst *fi) struct vlr_subscr *vsub = lcvp->vsub; if (!vsub->lu_complete) { vsub->lu_complete = true; - /* Balanced by vlr_subscr_rx_imsi_detach() */ + /* Balanced by vlr_subscr_rx_imsi_detach() or Location Update expiry */ vlr_subscr_get(vsub); } _vlr_lu_compl_fsm_done(fi, VLR_FSM_RESULT_SUCCESS, 0); diff --git a/tests/msc_vlr/msc_vlr_test_no_authen.c b/tests/msc_vlr/msc_vlr_test_no_authen.c index cd61fa127..80492f0f9 100644 --- a/tests/msc_vlr/msc_vlr_test_no_authen.c +++ b/tests/msc_vlr/msc_vlr_test_no_authen.c @@ -917,6 +917,70 @@ static void test_no_authen_imeisv_tmsi_imei() comment_end(); } +static void test_no_authen_subscr_expire() +{ + struct vlr_subscr *vsub; + const char *imsi = "901700000004620"; + + /* No auth only works on GERAN */ + rx_from_ran = RAN_GERAN_A; + + comment_start(); + + fake_time_start(); + + /* The test framework has already started the VLR before fake time was active. + * Manually schedule this timeout in fake time. */ + osmo_timer_schedule(&net->vlr->lu_expire_timer, GSM_SUBSCRIBER_LU_EXPIRATION_INTERVAL, 0); + + /* Let the LU expiration timer tick once */ + fake_time_passes(GSM_SUBSCRIBER_LU_EXPIRATION_INTERVAL + 1, 0); + + btw("Location Update request causes a GSUP LU request to HLR"); + lu_result_sent = RES_NONE; + gsup_expect_tx("04010809710000004026f0"); + ms_sends_msg("050802008168000130089910070000006402"); + OSMO_ASSERT(gsup_tx_confirmed); + VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d"); + + btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT"); + gsup_rx("10010809710000004026f00804036470f1", + "12010809710000004026f0"); + VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d"); + + btw("having received subscriber data does not mean acceptance"); + EXPECT_ACCEPTED(false); + + thwart_rx_non_initial_requests(); + + VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d"); + + btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT"); + expect_bssap_clear(); + gsup_rx("06010809710000004026f0", NULL); + + btw("LU was successful, and the conn has already been closed"); + VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d"); + VERBOSE_ASSERT(bssap_clear_sent, == true, "%d"); + + bss_sends_clear_complete(); + EXPECT_CONN_COUNT(0); + + vsub = vlr_subscr_find_by_imsi(net->vlr, imsi); + OSMO_ASSERT(vsub); + vlr_subscr_put(vsub); + + /* Let T3212 (periodic Location update timer) expire */ + fake_time_passes((net->t3212 * 60 * 6 * 2) + 180, 0); + + /* The subscriber should now be gone. */ + vsub = vlr_subscr_find_by_imsi(net->vlr, imsi); + OSMO_ASSERT(vsub == NULL); + + EXPECT_CONN_COUNT(0); + clear_vlr(); + comment_end(); +} msc_vlr_test_func_t msc_vlr_tests[] = { test_no_authen, @@ -927,5 +991,6 @@ msc_vlr_test_func_t msc_vlr_tests[] = { test_no_authen_imeisv_imei, test_no_authen_imeisv_tmsi, test_no_authen_imeisv_tmsi_imei, + test_no_authen_subscr_expire, NULL }; |