Introduce new callbacks, remember that we have LOC UPD REQ, reject things only once

gsm_data.h add new callbacks, add some parameters, update bsc_hack and
other call sites.

Remember that we need to ACCEPT/REJECT the LOCATION UPDATE REQUEST and
then send the ACCEPT or schedule the sending of the reject. Currently
it is possible that for a new subscriber that we do not have a !subscbr
yet, we will trigger an IDENTITY REQUEST and schedule the reject timer.
This may lead to rejecting AND accepting (a new subscriber). This issue
is triggered when allowing everyone to connect to the network.
This commit is contained in:
Holger Freyther 2008-12-29 17:44:08 +00:00
parent fad5d0db83
commit b7193e4e94
3 changed files with 64 additions and 28 deletions

View File

@ -87,6 +87,10 @@ struct gsm_lchan {
/* temporary user data, to be removed... and merged into gsm_call */
void *user_data;
/* use count. how many users use this channel */
unsigned int use_count;
unsigned int pending_update_request : 1;
};
#define BTS_TRX_F_ACTIVATED 0x0001
@ -148,10 +152,13 @@ struct gsm_network {
struct gsm_ms *ms;
struct gsm_subscriber *subscriber;
void (*update_request_accepted)(struct gsm_bts *, u_int32_t);
/* management of the lower layers to allow the bsc to hook into it */
void (*update_request)(struct gsm_bts *, u_int32_t tmsi, int accepted);
void (*channel_allocated)(struct gsm_lchan *bts, enum gsm_chreq_reason_t);
void (*channel_deallocated)(struct gsm_lchan *bts);
void (*channel_response)(struct gsm_lchan *, int acked);
void (*call_released)(struct gsm_lchan *);
void (*channel_subscriber_assigned)(struct gsm_lchan *);
void (*call_state_changed)(struct gsm_lchan *, enum gsm_call_state new_state);
};
struct gsm_network *gsm_network_init(unsigned int num_bts, u_int16_t country_code,

View File

@ -49,11 +49,13 @@ static int MNC = 1;
static const char *database_name = "hlr.sqlite3";
/* forward declarations */
static void bsc_hack_update_request_accepted(struct gsm_bts *bts, u_int32_t assigned_tmi);
static void bsc_hack_update_request(struct gsm_bts *bts,
u_int32_t assigned_tmi, int accepted);
static void bsc_hack_channel_allocated(struct gsm_lchan *chan,
enum gsm_chreq_reason_t reason);
static void bsc_hack_channel_response(struct gsm_lchan *chan, int acked);
static void bsc_hack_call_released(struct gsm_lchan *chan);
static void bsc_hack_call_state_changed(struct gsm_lchan *chan,
enum gsm_call_state new_state);
/* The following definitions are for OM and NM packets that we cannot yet
@ -643,10 +645,10 @@ static int bootstrap_network(void)
bts = &gsmnet->bts[0];
bts->location_area_code = 1;
bts->trx[0].arfcn = HARDCODED_ARFCN;
gsmnet->update_request_accepted = bsc_hack_update_request_accepted;
gsmnet->update_request = bsc_hack_update_request;
gsmnet->channel_allocated = bsc_hack_channel_allocated;
gsmnet->channel_response = bsc_hack_channel_response;
gsmnet->call_released = bsc_hack_call_released;
gsmnet->call_state_changed = bsc_hack_call_state_changed;
if (mi_setup(bts, 0, mi_cb) < 0)
return -EIO;
@ -807,10 +809,19 @@ static struct timer_list station_timer = {
/*
* schedule work
*/
static void bsc_hack_update_request_accepted(struct gsm_bts *bts, u_int32_t tmsi)
static void bsc_hack_update_request(struct gsm_bts *bts, u_int32_t tmsi, int accepted)
{
struct pending_registered_station *station =
(struct pending_registered_station*)malloc(sizeof(*station));
/*
* Only deal with LOCATION UPDATE REQUEST we have
* accepted.
*/
if (!accepted)
return;
station->tmsi = tmsi;
station->last_page_group = 0;
llist_add_tail(&station->entry, &pending_stations);
@ -877,9 +888,15 @@ static void bsc_hack_channel_response(struct gsm_lchan *lchan, int ack)
}
}
static void bsc_hack_call_released(struct gsm_lchan *lchan)
static void bsc_hack_call_state_changed(struct gsm_lchan *lchan,
enum gsm_call_state new_state)
{
DEBUGP(DPAG, "Call released jumping to the next...\n");
/* only handle the transition back to the NULL state */
if (new_state != GSM_CSTATE_NULL)
return;
rsl_chan_release(lchan);
/* next!!! */

View File

@ -43,6 +43,7 @@
static int gsm48_tx_simple(struct gsm_lchan *lchan,
u_int8_t pdisc, u_int8_t msg_type);
static void schedule_reject(struct gsm_lchan *lchan);
struct gsm_lai {
u_int16_t mcc;
@ -193,18 +194,13 @@ 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");
gsm48_sendmsg(msg);
gsm0411_send_sms(lchan, 0);
/* free the channel afterwards */
ret = rsl_chan_release(lchan);
/* inform the upper layer on the progress */
if (bts->network->update_request_accepted)
(*bts->network->update_request_accepted)(bts, tmsi);
if (bts->network->update_request)
(*bts->network->update_request)(bts, tmsi, 1);
return ret;
}
@ -293,11 +289,16 @@ static int mm_rx_id_resp(struct msgb *msg)
case GSM_MI_TYPE_IMSI:
if (!lchan->subscr)
lchan->subscr = db_create_subscriber(mi_string);
if (lchan->subscr && lchan->subscr->authorized) {
/* FIXME: check if we've recently received UPDATE REQUEST */
db_subscriber_alloc_tmsi(lchan->subscr);
tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
return gsm0408_loc_upd_acc(msg->lchan, tmsi);
/* We have a pending UPDATE REQUEST handle it now */
if (lchan->pending_update_request) {
if (lchan->subscr->authorized) {
db_subscriber_alloc_tmsi(lchan->subscr);
tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
return gsm0408_loc_upd_acc(msg->lchan, tmsi);
} else {
schedule_reject(lchan);
}
}
break;
case GSM_MI_TYPE_IMEI:
@ -319,6 +320,14 @@ static void loc_upd_rej_cb(void *data)
rsl_chan_release(lchan);
}
static void schedule_reject(struct gsm_lchan *lchan)
{
lchan->timer.cb = loc_upd_rej_cb;
lchan->timer.data = lchan;
lchan->pending_update_request = 0;
schedule_timer(&lchan->timer, 1, 0);
}
#define MI_SIZE 32
/* Chapter 9.2.15 */
static int mm_rx_loc_upd_req(struct msgb *msg)
@ -369,11 +378,14 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
lchan->subscr = subscr;
if (!subscr || !subscr->authorized) {
/* 0x16 is congestion */
lchan->timer.cb = loc_upd_rej_cb;
lchan->timer.data = lchan;
schedule_timer(&lchan->timer, 1, 0);
/* we know who we deal with and don't want him */
if (subscr && !subscr->authorized) {
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;
}
@ -550,9 +562,9 @@ static int gsm0408_rcv_cc(struct msgb *msg)
case GSM48_MT_CC_RELEASE_COMPL:
/* Answer from MS to RELEASE */
DEBUGP(DCC, "RELEASE COMPLETE (state->NULL)\n");
if (network->call_state_changed)
(*network->call_state_changed)(msg->lchan, call->state);
call->state = GSM_CSTATE_NULL;
if (network->call_released)
(*network->call_released)(msg->lchan);
break;
case GSM48_MT_CC_ALERTING:
DEBUGP(DCC, "ALERTING\n");