Introduce logical updating request operation on the gsm_lchan
We are going to have logical operations like Phone Call, SMS, Paging, Updating Request on a logical channel and for each of these operations we might need to store state. For now pointers in gsm_lchan look like the best way of doing this and we start by introducing an operation for the location updating request. The new flow of things are: - We get the location updating request and update/create the subscriber and maybe send the identity requests to the mobile station - We start the updating timer, if it times out we will reject the mobile station. - Once we get the Identity Responses we have asked for and the reject timer did not fire yet we might accept the user.
This commit is contained in:
parent
41ed300aab
commit
73487a23da
|
@ -82,6 +82,19 @@ enum gsm_chreq_reason_t {
|
|||
GSM_CHREQ_REASON_OTHER,
|
||||
};
|
||||
|
||||
/*
|
||||
* LOCATION UPDATING REQUEST state
|
||||
*
|
||||
* Our current operation is:
|
||||
* - Get imei/tmsi
|
||||
* - Accept/Reject according to global policy
|
||||
*/
|
||||
struct gsm_loc_updating_operation {
|
||||
struct timer_list updating_timer;
|
||||
int waiting_for_imsi : 1;
|
||||
int waiting_for_imei : 1;
|
||||
};
|
||||
|
||||
struct gsm_lchan {
|
||||
/* The TS that we're part of */
|
||||
struct gsm_bts_trx_ts *ts;
|
||||
|
@ -94,7 +107,6 @@ struct gsm_lchan {
|
|||
|
||||
/* Timer started to release the channel */
|
||||
struct timer_list release_timer;
|
||||
struct timer_list updating_timer;
|
||||
|
||||
/* local end of a call, if any */
|
||||
struct gsm_call call;
|
||||
|
@ -102,9 +114,13 @@ struct gsm_lchan {
|
|||
/* temporary user data, to be removed... and merged into gsm_call */
|
||||
void *user_data;
|
||||
|
||||
/*
|
||||
* Operations that have a state and might be pending
|
||||
*/
|
||||
struct gsm_loc_updating_operation *loc_operation;
|
||||
|
||||
/* use count. how many users use this channel */
|
||||
unsigned int use_count;
|
||||
unsigned int pending_update_request : 1;
|
||||
};
|
||||
|
||||
#define BTS_TRX_F_ACTIVATED 0x0001
|
||||
|
|
|
@ -65,17 +65,44 @@ void gsm0408_set_reject_cause(int cause)
|
|||
reject_cause = cause;
|
||||
}
|
||||
|
||||
static int authorize_subscriber(struct gsm_subscriber *subscriber)
|
||||
static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
|
||||
struct gsm_subscriber *subscriber)
|
||||
{
|
||||
if (!subscriber)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Do not send accept yet as more information should arrive. Some
|
||||
* phones will not send us the information and we will have to check
|
||||
* what we want to do with that.
|
||||
*/
|
||||
if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
|
||||
return 0;
|
||||
|
||||
if (authorize_everonye)
|
||||
return 1;
|
||||
|
||||
return subscriber->authorized;
|
||||
}
|
||||
|
||||
static void release_loc_updating_req(struct gsm_lchan *lchan)
|
||||
{
|
||||
if (lchan->loc_operation)
|
||||
return;
|
||||
|
||||
del_timer(&lchan->loc_operation->updating_timer);
|
||||
free(lchan->loc_operation);
|
||||
lchan->loc_operation = 0;
|
||||
}
|
||||
|
||||
static void allocate_loc_updating_req(struct gsm_lchan *lchan)
|
||||
{
|
||||
release_loc_updating_req(lchan);
|
||||
|
||||
lchan->loc_operation = (struct gsm_loc_updating_operation *)
|
||||
malloc(sizeof(*lchan->loc_operation));
|
||||
memset(lchan->loc_operation, 0, sizeof(*lchan->loc_operation));
|
||||
}
|
||||
|
||||
static void parse_lai(struct gsm_lai *lai, const struct gsm48_loc_area_id *lai48)
|
||||
{
|
||||
|
@ -231,7 +258,6 @@ int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
|
|||
mid = msgb_put(msg, MID_TMSI_LEN);
|
||||
generate_mid_from_tmsi(mid, tmsi);
|
||||
|
||||
lchan->pending_update_request = 0;
|
||||
DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
|
||||
|
||||
/* inform the upper layer on the progress */
|
||||
|
@ -338,26 +364,27 @@ static int mm_rx_id_resp(struct msgb *msg)
|
|||
case GSM_MI_TYPE_IMSI:
|
||||
if (!lchan->subscr)
|
||||
lchan->subscr = db_create_subscriber(mi_string);
|
||||
|
||||
/* We have a pending UPDATING REQUEST handle it now */
|
||||
if (lchan->pending_update_request) {
|
||||
if (authorize_subscriber(lchan->subscr)) {
|
||||
db_subscriber_alloc_tmsi(lchan->subscr);
|
||||
tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
|
||||
del_timer(&lchan->updating_timer);
|
||||
return gsm0408_loc_upd_acc(msg->lchan, tmsi);
|
||||
} else {
|
||||
schedule_reject(lchan);
|
||||
}
|
||||
}
|
||||
if (lchan->loc_operation)
|
||||
lchan->loc_operation->waiting_for_imsi = 0;
|
||||
break;
|
||||
case GSM_MI_TYPE_IMEI:
|
||||
case GSM_MI_TYPE_IMEISV:
|
||||
/* update subscribe <-> IMEI mapping */
|
||||
if (lchan->subscr)
|
||||
db_subscriber_assoc_imei(lchan->subscr, mi_string);
|
||||
if (lchan->loc_operation)
|
||||
lchan->loc_operation->waiting_for_imei = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if we can let the mobile station enter */
|
||||
if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
|
||||
db_subscriber_alloc_tmsi(lchan->subscr);
|
||||
tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
|
||||
release_loc_updating_req(lchan);
|
||||
return gsm0408_loc_upd_acc(msg->lchan, tmsi);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -366,16 +393,16 @@ static void loc_upd_rej_cb(void *data)
|
|||
{
|
||||
struct gsm_lchan *lchan = data;
|
||||
|
||||
release_loc_updating_req(lchan);
|
||||
gsm0408_loc_upd_rej(lchan, reject_cause);
|
||||
rsl_chan_release(lchan);
|
||||
}
|
||||
|
||||
static void schedule_reject(struct gsm_lchan *lchan)
|
||||
{
|
||||
lchan->updating_timer.cb = loc_upd_rej_cb;
|
||||
lchan->updating_timer.data = lchan;
|
||||
lchan->pending_update_request = 0;
|
||||
schedule_timer(&lchan->updating_timer, 1, 0);
|
||||
lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
|
||||
lchan->loc_operation->updating_timer.data = lchan;
|
||||
schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
|
||||
}
|
||||
|
||||
#define MI_SIZE 32
|
||||
|
@ -399,11 +426,15 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
|
|||
mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
|
||||
|
||||
DEBUGP(DMM, "LUPDREQ: mi_type=0x%02x MI(%s)\n", mi_type, mi_string);
|
||||
|
||||
allocate_loc_updating_req(lchan);
|
||||
|
||||
switch (mi_type) {
|
||||
case GSM_MI_TYPE_IMSI:
|
||||
/* we always want the IMEI, too */
|
||||
use_lchan(lchan);
|
||||
rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEISV);
|
||||
lchan->loc_operation->waiting_for_imei = 1;
|
||||
|
||||
/* look up subscriber based on IMSI */
|
||||
subscr = db_create_subscriber(mi_string);
|
||||
|
@ -412,6 +443,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
|
|||
/* we always want the IMEI, too */
|
||||
use_lchan(lchan);
|
||||
rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEISV);
|
||||
lchan->loc_operation->waiting_for_imei = 1;
|
||||
|
||||
/* look up the subscriber based on TMSI, request IMSI if it fails */
|
||||
subscr = subscr_get_by_tmsi(lu->mi);
|
||||
|
@ -419,6 +451,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
|
|||
/* send IDENTITY REQUEST message to get IMSI */
|
||||
use_lchan(lchan);
|
||||
rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
|
||||
lchan->loc_operation->waiting_for_imsi = 1;
|
||||
}
|
||||
break;
|
||||
case GSM_MI_TYPE_IMEI:
|
||||
|
@ -433,23 +466,21 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
|
|||
|
||||
lchan->subscr = subscr;
|
||||
|
||||
/* we know who we deal with and don't want him */
|
||||
if (subscr && !authorize_subscriber(subscr)) {
|
||||
schedule_reject(lchan);
|
||||
return 0;
|
||||
} else if (!subscr) {
|
||||
/* we have asked for the imsi and should get a
|
||||
* IDENTITY RESPONSE */
|
||||
lchan->pending_update_request = 1;
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Schedule the reject timer and check if we can let the
|
||||
* subscriber into our network immediately or if we need to wait
|
||||
* for identity responses.
|
||||
*/
|
||||
schedule_reject(lchan);
|
||||
if (!authorize_subscriber(lchan->loc_operation, subscr))
|
||||
return;
|
||||
|
||||
db_subscriber_alloc_tmsi(subscr);
|
||||
subscr_update(subscr, bts);
|
||||
|
||||
tmsi = strtoul(subscr->tmsi, NULL, 10);
|
||||
|
||||
del_timer(&lchan->updating_timer);
|
||||
release_loc_updating_req(lchan);
|
||||
return gsm0408_loc_upd_acc(lchan, tmsi);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue