lchan: Create a structure for MSC data of the lchan
Prepare to split the BSC and the MSC part by putting the MSC data for a connection into a "gsm_subscriber_connection" struct and renaming the macros.
This commit is contained in:
parent
9870099a9c
commit
065b8119d1
|
@ -84,18 +84,18 @@ typedef int gsm_cbfn(unsigned int hooknum,
|
|||
* will be started.
|
||||
*/
|
||||
#define LCHAN_RELEASE_TIMEOUT 20, 0
|
||||
#define use_lchan(lchan) \
|
||||
do { lchan->use_count++; \
|
||||
#define use_subscr_con(con) \
|
||||
do { (con)->use_count++; \
|
||||
DEBUGP(DREF, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) increases usage to: %d\n", \
|
||||
lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, \
|
||||
lchan->nr, lchan->use_count); \
|
||||
bsc_schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT); } while(0);
|
||||
(con)->lchan->ts->trx->bts->nr, (con)->lchan->ts->trx->nr, (con)->lchan->ts->nr, \
|
||||
(con)->lchan->nr, (con)->use_count); \
|
||||
bsc_schedule_timer(&(con)->release_timer, LCHAN_RELEASE_TIMEOUT); } while(0);
|
||||
|
||||
#define put_lchan(lchan) \
|
||||
do { lchan->use_count--; \
|
||||
#define put_subscr_con(con) \
|
||||
do { (con)->use_count--; \
|
||||
DEBUGP(DREF, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) decreases usage to: %d\n", \
|
||||
lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, \
|
||||
lchan->nr, lchan->use_count); \
|
||||
(con)->lchan->ts->trx->bts->nr, (con)->lchan->ts->trx->nr, (con)->lchan->ts->nr, \
|
||||
(con)->lchan->nr, (con)->use_count); \
|
||||
} while(0);
|
||||
|
||||
|
||||
|
@ -182,6 +182,29 @@ enum gsm_lchan_state {
|
|||
LCHAN_S_INACTIVE, /* channel is set inactive */
|
||||
};
|
||||
|
||||
/* the per subscriber data for lchan */
|
||||
struct gsm_subscriber_connection {
|
||||
/* To whom we are allocated at the moment */
|
||||
struct gsm_subscriber *subscr;
|
||||
|
||||
/* Timer started to release the channel */
|
||||
struct timer_list release_timer;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/* Are we part of a special "silent" call */
|
||||
int silent_call;
|
||||
|
||||
/* back pointer to the gsm_lchan */
|
||||
struct gsm_lchan *lchan;
|
||||
};
|
||||
|
||||
struct gsm_lchan {
|
||||
/* The TS that we're part of */
|
||||
struct gsm_bts_trx_ts *ts;
|
||||
|
@ -204,31 +227,15 @@ struct gsm_lchan {
|
|||
u_int8_t key_len;
|
||||
u_int8_t key[MAX_A5_KEY_LEN];
|
||||
} encr;
|
||||
/* Are we part of a special "silent" call */
|
||||
int silent_call;
|
||||
|
||||
struct timer_list T3101;
|
||||
|
||||
/* AMR bits */
|
||||
struct gsm48_multi_rate_conf mr_conf;
|
||||
|
||||
/* To whom we are allocated at the moment */
|
||||
struct gsm_subscriber *subscr;
|
||||
|
||||
/* Timer started to release the channel */
|
||||
struct timer_list release_timer;
|
||||
|
||||
struct timer_list T3101;
|
||||
|
||||
/* Established data link layer services */
|
||||
u_int8_t sapis[8];
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/* cache of last measurement reports on this lchan */
|
||||
struct gsm_meas_rep meas_rep[6];
|
||||
int meas_rep_idx;
|
||||
|
@ -246,6 +253,8 @@ struct gsm_lchan {
|
|||
u_int8_t speech_mode;
|
||||
struct rtp_socket *rtp_socket;
|
||||
} abis_ip;
|
||||
|
||||
struct gsm_subscriber_connection conn;
|
||||
};
|
||||
|
||||
struct gsm_e1_subslot {
|
||||
|
|
|
@ -119,7 +119,7 @@ struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, u_int8_t chan_nr)
|
|||
|
||||
lchan = &ts->lchan[lch_idx];
|
||||
debug_set_context(BSC_CTX_LCHAN, lchan);
|
||||
debug_set_context(BSC_CTX_SUBSCR, lchan->subscr);
|
||||
debug_set_context(BSC_CTX_SUBSCR, lchan->conn.subscr);
|
||||
|
||||
return lchan;
|
||||
}
|
||||
|
|
|
@ -51,8 +51,11 @@ static LLIST_HEAD(bsc_rll_reqs);
|
|||
|
||||
static void complete_rllr(struct bsc_rll_req *rllr, enum bsc_rllr_ind type)
|
||||
{
|
||||
struct gsm_subscriber_connection *conn;
|
||||
|
||||
conn = &rllr->lchan->conn;
|
||||
llist_del(&rllr->list);
|
||||
put_lchan(rllr->lchan);
|
||||
put_subscr_con(conn);
|
||||
rllr->cb(rllr->lchan, rllr->link_id, rllr->data, type);
|
||||
talloc_free(rllr);
|
||||
}
|
||||
|
@ -70,6 +73,7 @@ int rll_establish(struct gsm_lchan *lchan, u_int8_t sapi,
|
|||
enum bsc_rllr_ind),
|
||||
void *data)
|
||||
{
|
||||
struct gsm_subscriber_connection *conn;
|
||||
struct bsc_rll_req *rllr = talloc_zero(tall_bsc_ctx, struct bsc_rll_req);
|
||||
u_int8_t link_id;
|
||||
if (!rllr)
|
||||
|
@ -83,7 +87,8 @@ int rll_establish(struct gsm_lchan *lchan, u_int8_t sapi,
|
|||
lchan->type == GSM_LCHAN_TCH_H) && sapi != 0)
|
||||
link_id |= 0x40;
|
||||
|
||||
use_lchan(lchan);
|
||||
conn = &lchan->conn;
|
||||
use_subscr_con(conn);
|
||||
rllr->lchan = lchan;
|
||||
rllr->link_id = link_id;
|
||||
rllr->cb = cb;
|
||||
|
|
|
@ -252,7 +252,6 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type)
|
|||
|
||||
if (lchan) {
|
||||
lchan->type = type;
|
||||
lchan->use_count = 0;
|
||||
|
||||
/* clear sapis */
|
||||
memset(lchan->sapis, 0, ARRAY_SIZE(lchan->sapis));
|
||||
|
@ -260,10 +259,15 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type)
|
|||
/* clear multi rate config */
|
||||
memset(&lchan->mr_conf, 0, sizeof(lchan->mr_conf));
|
||||
|
||||
/* clear per MSC/BSC data */
|
||||
memset(&lchan->conn, 0, sizeof(lchan->conn));
|
||||
|
||||
/* Configure the time and start it so it will be closed */
|
||||
lchan->release_timer.cb = auto_release_channel;
|
||||
lchan->release_timer.data = lchan;
|
||||
bsc_schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT);
|
||||
lchan->conn.lchan = lchan;
|
||||
lchan->conn.release_timer.cb = auto_release_channel;
|
||||
lchan->conn.release_timer.data = lchan;
|
||||
bsc_schedule_timer(&lchan->conn.release_timer, LCHAN_RELEASE_TIMEOUT);
|
||||
|
||||
}
|
||||
|
||||
return lchan;
|
||||
|
@ -275,19 +279,19 @@ void lchan_free(struct gsm_lchan *lchan)
|
|||
int i;
|
||||
|
||||
lchan->type = GSM_LCHAN_NONE;
|
||||
if (lchan->subscr) {
|
||||
subscr_put(lchan->subscr);
|
||||
lchan->subscr = NULL;
|
||||
if (lchan->conn.subscr) {
|
||||
subscr_put(lchan->conn.subscr);
|
||||
lchan->conn.subscr = NULL;
|
||||
}
|
||||
|
||||
/* We might kill an active channel... */
|
||||
if (lchan->use_count != 0) {
|
||||
if (lchan->conn.use_count != 0) {
|
||||
dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, lchan);
|
||||
lchan->use_count = 0;
|
||||
lchan->conn.use_count = 0;
|
||||
}
|
||||
|
||||
/* stop the timer */
|
||||
bsc_del_timer(&lchan->release_timer);
|
||||
bsc_del_timer(&lchan->conn.release_timer);
|
||||
bsc_del_timer(&lchan->T3101);
|
||||
|
||||
/* clear cached measuement reports */
|
||||
|
@ -299,7 +303,7 @@ void lchan_free(struct gsm_lchan *lchan)
|
|||
for (i = 0; i < ARRAY_SIZE(lchan->neigh_meas); i++)
|
||||
lchan->neigh_meas[i].arfcn = 0;
|
||||
|
||||
lchan->silent_call = 0;
|
||||
lchan->conn.silent_call = 0;
|
||||
|
||||
/* FIXME: ts_free() the timeslot, if we're the last logical
|
||||
* channel using it */
|
||||
|
@ -308,19 +312,19 @@ void lchan_free(struct gsm_lchan *lchan)
|
|||
/* Consider releasing the channel now */
|
||||
int lchan_auto_release(struct gsm_lchan *lchan)
|
||||
{
|
||||
if (lchan->use_count > 0) {
|
||||
if (lchan->conn.use_count > 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Assume we have GSM04.08 running and send a release */
|
||||
if (lchan->subscr) {
|
||||
if (lchan->conn.subscr) {
|
||||
gsm48_send_rr_release(lchan);
|
||||
}
|
||||
|
||||
/* spoofed? message */
|
||||
if (lchan->use_count < 0)
|
||||
if (lchan->conn.use_count < 0)
|
||||
LOGP(DRLL, LOGL_ERROR, "Channel count is negative: %d\n",
|
||||
lchan->use_count);
|
||||
lchan->conn.use_count);
|
||||
|
||||
DEBUGP(DRLL, "%s Recycling Channel\n", gsm_lchan_name(lchan));
|
||||
rsl_release_request(lchan, 0);
|
||||
|
@ -333,7 +337,7 @@ static void auto_release_channel(void *_lchan)
|
|||
struct gsm_lchan *lchan = _lchan;
|
||||
|
||||
if (!lchan_auto_release(lchan))
|
||||
bsc_schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT);
|
||||
bsc_schedule_timer(&lchan->conn.release_timer, LCHAN_RELEASE_TIMEOUT);
|
||||
}
|
||||
|
||||
struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr) {
|
||||
|
@ -345,7 +349,7 @@ struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr)
|
|||
for (lchan_no = 0; lchan_no < TS_MAX_LCHAN; ++lchan_no) {
|
||||
struct gsm_lchan *lchan =
|
||||
&trx->ts[ts_no].lchan[lchan_no];
|
||||
if (subscr == lchan->subscr)
|
||||
if (subscr == lchan->conn.subscr)
|
||||
return lchan;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ void *tall_locop_ctx;
|
|||
int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
|
||||
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);
|
||||
static void schedule_reject(struct gsm_subscriber_connection *conn);
|
||||
|
||||
struct gsm_lai {
|
||||
u_int16_t mcc;
|
||||
|
@ -96,35 +96,35 @@ static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
|
|||
}
|
||||
}
|
||||
|
||||
static void release_loc_updating_req(struct gsm_lchan *lchan)
|
||||
static void release_loc_updating_req(struct gsm_subscriber_connection *conn)
|
||||
{
|
||||
if (!lchan->loc_operation)
|
||||
if (!conn->loc_operation)
|
||||
return;
|
||||
|
||||
bsc_del_timer(&lchan->loc_operation->updating_timer);
|
||||
talloc_free(lchan->loc_operation);
|
||||
lchan->loc_operation = 0;
|
||||
put_lchan(lchan);
|
||||
bsc_del_timer(&conn->loc_operation->updating_timer);
|
||||
talloc_free(conn->loc_operation);
|
||||
conn->loc_operation = 0;
|
||||
put_subscr_con(conn);
|
||||
}
|
||||
|
||||
static void allocate_loc_updating_req(struct gsm_lchan *lchan)
|
||||
static void allocate_loc_updating_req(struct gsm_subscriber_connection *conn)
|
||||
{
|
||||
use_lchan(lchan);
|
||||
release_loc_updating_req(lchan);
|
||||
use_subscr_con(conn)
|
||||
release_loc_updating_req(conn);
|
||||
|
||||
lchan->loc_operation = talloc_zero(tall_locop_ctx,
|
||||
conn->loc_operation = talloc_zero(tall_locop_ctx,
|
||||
struct gsm_loc_updating_operation);
|
||||
}
|
||||
|
||||
static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
|
||||
static int gsm0408_authorize(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
||||
{
|
||||
if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
|
||||
if (authorize_subscriber(conn->loc_operation, conn->subscr)) {
|
||||
int rc;
|
||||
|
||||
db_subscriber_alloc_tmsi(lchan->subscr);
|
||||
release_loc_updating_req(lchan);
|
||||
rc = gsm0408_loc_upd_acc(msg->lchan, lchan->subscr->tmsi);
|
||||
if (lchan->ts->trx->bts->network->send_mm_info) {
|
||||
db_subscriber_alloc_tmsi(conn->subscr);
|
||||
release_loc_updating_req(conn);
|
||||
rc = gsm0408_loc_upd_acc(msg->lchan, conn->subscr->tmsi);
|
||||
if (msg->lchan->ts->trx->bts->network->send_mm_info) {
|
||||
/* send MM INFO with network name */
|
||||
rc = gsm48_tx_mm_info(msg->lchan);
|
||||
}
|
||||
|
@ -132,10 +132,11 @@ static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
|
|||
/* call subscr_update after putting the loc_upd_acc
|
||||
* in the transmit queue, since S_SUBSCR_ATTACHED might
|
||||
* trigger further action like SMS delivery */
|
||||
subscr_update(lchan->subscr, msg->trx->bts,
|
||||
subscr_update(conn->subscr, msg->trx->bts,
|
||||
GSM_SUBSCRIBER_UPDATE_ATTACHED);
|
||||
|
||||
/* try to close channel ASAP */
|
||||
lchan_auto_release(lchan);
|
||||
lchan_auto_release(conn->lchan);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -158,7 +159,7 @@ static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
|
|||
if (!lchan)
|
||||
return 0;
|
||||
|
||||
release_loc_updating_req(lchan);
|
||||
release_loc_updating_req(&lchan->conn);
|
||||
|
||||
/* Free all transactions that are associated with the released lchan */
|
||||
/* FIXME: this is not neccessarily the right thing to do, we should
|
||||
|
@ -175,11 +176,13 @@ static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
|
|||
/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
|
||||
int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
|
||||
{
|
||||
struct gsm_subscriber_connection *conn;
|
||||
struct gsm_bts *bts = lchan->ts->trx->bts;
|
||||
struct msgb *msg = gsm48_msgb_alloc();
|
||||
struct gsm48_hdr *gh;
|
||||
|
||||
msg->lchan = lchan;
|
||||
conn = &lchan->conn;
|
||||
|
||||
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
|
||||
gh->proto_discr = GSM48_PDISC_MM;
|
||||
|
@ -187,8 +190,8 @@ int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
|
|||
gh->data[0] = cause;
|
||||
|
||||
LOGP(DMM, LOGL_INFO, "Subscriber %s: LOCATION UPDATING REJECT "
|
||||
"LAC=%u BTS=%u\n", lchan->subscr ?
|
||||
subscr_name(lchan->subscr) : "unknown",
|
||||
"LAC=%u BTS=%u\n", conn->subscr ?
|
||||
subscr_name(conn->subscr) : "unknown",
|
||||
lchan->ts->trx->bts->location_area_code, lchan->ts->trx->bts->nr);
|
||||
|
||||
counter_inc(bts->network->stats.loc_upd_resp.reject);
|
||||
|
@ -245,6 +248,7 @@ static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
|
|||
/* Parse Chapter 9.2.11 Identity Response */
|
||||
static int mm_rx_id_resp(struct msgb *msg)
|
||||
{
|
||||
struct gsm_subscriber_connection *conn;
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
struct gsm_lchan *lchan = msg->lchan;
|
||||
struct gsm_bts *bts = lchan->ts->trx->bts;
|
||||
|
@ -256,51 +260,54 @@ static int mm_rx_id_resp(struct msgb *msg)
|
|||
DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
|
||||
mi_type, mi_string);
|
||||
|
||||
conn = &lchan->conn;
|
||||
|
||||
dispatch_signal(SS_SUBSCR, S_SUBSCR_IDENTITY, gh->data);
|
||||
|
||||
switch (mi_type) {
|
||||
case GSM_MI_TYPE_IMSI:
|
||||
/* look up subscriber based on IMSI, create if not found */
|
||||
if (!lchan->subscr) {
|
||||
lchan->subscr = subscr_get_by_imsi(net, mi_string);
|
||||
if (!lchan->subscr)
|
||||
lchan->subscr = db_create_subscriber(net, mi_string);
|
||||
if (!conn->subscr) {
|
||||
conn->subscr = subscr_get_by_imsi(net, mi_string);
|
||||
if (!conn->subscr)
|
||||
conn->subscr = db_create_subscriber(net, mi_string);
|
||||
}
|
||||
if (lchan->loc_operation)
|
||||
lchan->loc_operation->waiting_for_imsi = 0;
|
||||
if (conn->loc_operation)
|
||||
conn->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);
|
||||
db_sync_equipment(&lchan->subscr->equipment);
|
||||
if (conn->subscr) {
|
||||
db_subscriber_assoc_imei(conn->subscr, mi_string);
|
||||
db_sync_equipment(&conn->subscr->equipment);
|
||||
}
|
||||
if (lchan->loc_operation)
|
||||
lchan->loc_operation->waiting_for_imei = 0;
|
||||
if (conn->loc_operation)
|
||||
conn->loc_operation->waiting_for_imei = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if we can let the mobile station enter */
|
||||
return gsm0408_authorize(lchan, msg);
|
||||
return gsm0408_authorize(conn, msg);
|
||||
}
|
||||
|
||||
|
||||
static void loc_upd_rej_cb(void *data)
|
||||
{
|
||||
struct gsm_lchan *lchan = data;
|
||||
struct gsm_subscriber_connection *conn = data;
|
||||
struct gsm_lchan *lchan = conn->lchan;
|
||||
struct gsm_bts *bts = lchan->ts->trx->bts;
|
||||
|
||||
release_loc_updating_req(lchan);
|
||||
release_loc_updating_req(conn);
|
||||
gsm0408_loc_upd_rej(lchan, bts->network->reject_cause);
|
||||
lchan_auto_release(lchan);
|
||||
}
|
||||
|
||||
static void schedule_reject(struct gsm_lchan *lchan)
|
||||
static void schedule_reject(struct gsm_subscriber_connection *conn)
|
||||
{
|
||||
lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
|
||||
lchan->loc_operation->updating_timer.data = lchan;
|
||||
bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
|
||||
conn->loc_operation->updating_timer.cb = loc_upd_rej_cb;
|
||||
conn->loc_operation->updating_timer.data = conn;
|
||||
bsc_schedule_timer(&conn->loc_operation->updating_timer, 5, 0);
|
||||
}
|
||||
|
||||
static const char *lupd_name(u_int8_t type)
|
||||
|
@ -320,6 +327,7 @@ static const char *lupd_name(u_int8_t type)
|
|||
/* Chapter 9.2.15: Receive Location Updating Request */
|
||||
static int mm_rx_loc_upd_req(struct msgb *msg)
|
||||
{
|
||||
struct gsm_subscriber_connection *conn;
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
struct gsm48_loc_upd_req *lu;
|
||||
struct gsm_subscriber *subscr = NULL;
|
||||
|
@ -330,6 +338,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
|
|||
int rc;
|
||||
|
||||
lu = (struct gsm48_loc_upd_req *) gh->data;
|
||||
conn = &lchan->conn;
|
||||
|
||||
mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
|
||||
|
||||
|
@ -356,21 +365,21 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
|
|||
* Pseudo Spoof detection: Just drop a second/concurrent
|
||||
* location updating request.
|
||||
*/
|
||||
if (lchan->loc_operation) {
|
||||
if (conn->loc_operation) {
|
||||
DEBUGPC(DMM, "ignoring request due an existing one: %p.\n",
|
||||
lchan->loc_operation);
|
||||
conn->loc_operation);
|
||||
gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
allocate_loc_updating_req(lchan);
|
||||
allocate_loc_updating_req(&lchan->conn);
|
||||
|
||||
switch (mi_type) {
|
||||
case GSM_MI_TYPE_IMSI:
|
||||
DEBUGPC(DMM, "\n");
|
||||
/* we always want the IMEI, too */
|
||||
rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
|
||||
lchan->loc_operation->waiting_for_imei = 1;
|
||||
conn->loc_operation->waiting_for_imei = 1;
|
||||
|
||||
/* look up subscriber based on IMSI, create if not found */
|
||||
subscr = subscr_get_by_imsi(bts->network, mi_string);
|
||||
|
@ -382,7 +391,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
|
|||
DEBUGPC(DMM, "\n");
|
||||
/* we always want the IMEI, too */
|
||||
rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
|
||||
lchan->loc_operation->waiting_for_imei = 1;
|
||||
conn->loc_operation->waiting_for_imei = 1;
|
||||
|
||||
/* look up the subscriber based on TMSI, request IMSI if it fails */
|
||||
subscr = subscr_get_by_tmsi(bts->network,
|
||||
|
@ -390,7 +399,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
|
|||
if (!subscr) {
|
||||
/* send IDENTITY REQUEST message to get IMSI */
|
||||
rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
|
||||
lchan->loc_operation->waiting_for_imsi = 1;
|
||||
conn->loc_operation->waiting_for_imsi = 1;
|
||||
}
|
||||
break;
|
||||
case GSM_MI_TYPE_IMEI:
|
||||
|
@ -404,7 +413,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
|
|||
}
|
||||
|
||||
/* schedule the reject timer */
|
||||
schedule_reject(lchan);
|
||||
schedule_reject(conn);
|
||||
|
||||
if (!subscr) {
|
||||
DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n");
|
||||
|
@ -412,12 +421,12 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
lchan->subscr = subscr;
|
||||
lchan->subscr->equipment.classmark1 = lu->classmark1;
|
||||
conn->subscr = subscr;
|
||||
conn->subscr->equipment.classmark1 = lu->classmark1;
|
||||
|
||||
/* check if we can let the subscriber into our network immediately
|
||||
* or if we need to wait for identity responses. */
|
||||
return gsm0408_authorize(lchan, msg);
|
||||
return gsm0408_authorize(conn, msg);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -566,7 +575,7 @@ static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
|
|||
}
|
||||
|
||||
/* 9.2.6 CM service reject */
|
||||
static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
|
||||
static int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
|
||||
enum gsm48_reject_value value)
|
||||
{
|
||||
struct msgb *msg = gsm48_msgb_alloc();
|
||||
|
@ -574,8 +583,8 @@ static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
|
|||
|
||||
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
|
||||
|
||||
msg->lchan = lchan;
|
||||
use_lchan(lchan);
|
||||
msg->lchan = conn->lchan;
|
||||
use_subscr_con(conn);
|
||||
|
||||
gh->proto_discr = GSM48_PDISC_MM;
|
||||
gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
|
||||
|
@ -613,20 +622,20 @@ static int gsm48_rx_mm_serv_req(struct msgb *msg)
|
|||
DEBUGP(DMM, "<- CM SERVICE REQUEST ");
|
||||
if (msg->data_len < sizeof(struct gsm48_service_request*)) {
|
||||
DEBUGPC(DMM, "wrong sized message\n");
|
||||
return gsm48_tx_mm_serv_rej(msg->lchan,
|
||||
return gsm48_tx_mm_serv_rej(&msg->lchan->conn,
|
||||
GSM48_REJECT_INCORRECT_MESSAGE);
|
||||
}
|
||||
|
||||
if (msg->data_len < req->mi_len + 6) {
|
||||
DEBUGPC(DMM, "does not fit in packet\n");
|
||||
return gsm48_tx_mm_serv_rej(msg->lchan,
|
||||
return gsm48_tx_mm_serv_rej(&msg->lchan->conn,
|
||||
GSM48_REJECT_INCORRECT_MESSAGE);
|
||||
}
|
||||
|
||||
mi_type = mi[0] & GSM_MI_TYPE_MASK;
|
||||
if (mi_type != GSM_MI_TYPE_TMSI) {
|
||||
DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type);
|
||||
return gsm48_tx_mm_serv_rej(msg->lchan,
|
||||
return gsm48_tx_mm_serv_rej(&msg->lchan->conn,
|
||||
GSM48_REJECT_INCORRECT_MESSAGE);
|
||||
}
|
||||
|
||||
|
@ -644,12 +653,12 @@ static int gsm48_rx_mm_serv_req(struct msgb *msg)
|
|||
|
||||
/* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
|
||||
if (!subscr)
|
||||
return gsm48_tx_mm_serv_rej(msg->lchan,
|
||||
return gsm48_tx_mm_serv_rej(&msg->lchan->conn,
|
||||
GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
|
||||
|
||||
if (!msg->lchan->subscr)
|
||||
msg->lchan->subscr = subscr;
|
||||
else if (msg->lchan->subscr == subscr)
|
||||
if (!msg->lchan->conn.subscr)
|
||||
msg->lchan->conn.subscr = subscr;
|
||||
else if (msg->lchan->conn.subscr == subscr)
|
||||
subscr_put(subscr); /* lchan already has a ref, don't need another one */
|
||||
else {
|
||||
DEBUGP(DMM, "<- CM Channel already owned by someone else?\n");
|
||||
|
@ -749,8 +758,8 @@ static int gsm0408_rcv_mm(struct msgb *msg)
|
|||
break;
|
||||
case GSM48_MT_MM_TMSI_REALL_COMPL:
|
||||
DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
|
||||
msg->lchan->subscr ?
|
||||
subscr_name(msg->lchan->subscr) :
|
||||
msg->lchan->conn.subscr ?
|
||||
subscr_name(msg->lchan->conn.subscr) :
|
||||
"unknown subscriber");
|
||||
break;
|
||||
case GSM48_MT_MM_IMSI_DETACH_IND:
|
||||
|
@ -815,7 +824,7 @@ static int gsm48_rx_rr_pag_resp(struct msgb *msg)
|
|||
static int gsm48_rx_rr_classmark(struct msgb *msg)
|
||||
{
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
struct gsm_subscriber *subscr = msg->lchan->subscr;
|
||||
struct gsm_subscriber *subscr = msg->lchan->conn.subscr;
|
||||
unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
|
||||
u_int8_t cm2_len, cm3_len = 0;
|
||||
u_int8_t *cm2, *cm3 = NULL;
|
||||
|
@ -896,7 +905,7 @@ static int gsm48_rx_rr_app_info(struct msgb *msg)
|
|||
DEBUGP(DNM, "RX APPLICATION INFO id/flags=0x%02x apdu_len=%u apdu=%s",
|
||||
apdu_id_flags, apdu_len, hexdump(apdu_data, apdu_len));
|
||||
|
||||
return db_apdu_blob_store(msg->lchan->subscr, apdu_id_flags, apdu_len, apdu_data);
|
||||
return db_apdu_blob_store(msg->lchan->conn.subscr, apdu_id_flags, apdu_len, apdu_data);
|
||||
}
|
||||
|
||||
/* Chapter 9.1.16 Handover complete */
|
||||
|
@ -1130,6 +1139,7 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
|
|||
struct gsm_subscriber *subscr = param;
|
||||
struct gsm_trans *transt, *tmp;
|
||||
struct gsm_network *net;
|
||||
struct gsm_subscriber_connection *conn;
|
||||
|
||||
if (hooknum != GSM_HOOK_RR_PAGING)
|
||||
return -EINVAL;
|
||||
|
@ -1142,6 +1152,8 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
conn = &lchan->conn;
|
||||
|
||||
/* check all tranactions (without lchan) for subscriber */
|
||||
llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
|
||||
if (transt->subscr != subscr || transt->lchan)
|
||||
|
@ -1155,7 +1167,7 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
|
|||
/* Assign lchan */
|
||||
if (!transt->lchan) {
|
||||
transt->lchan = lchan;
|
||||
use_lchan(lchan);
|
||||
use_subscr_con(conn);
|
||||
}
|
||||
/* send SETUP request to called party */
|
||||
gsm48_cc_tx_setup(transt, &transt->cc.msg);
|
||||
|
@ -2562,6 +2574,7 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg)
|
|||
struct gsm_lchan *lchan = NULL;
|
||||
struct gsm_bts *bts = NULL;
|
||||
struct gsm_mncc *data = arg, rel;
|
||||
struct gsm_subscriber_connection *conn;
|
||||
|
||||
/* handle special messages */
|
||||
switch(msg_type) {
|
||||
|
@ -2665,6 +2678,7 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg)
|
|||
}
|
||||
/* Find lchan */
|
||||
lchan = lchan_for_subscr(subscr);
|
||||
|
||||
/* If subscriber has no lchan */
|
||||
if (!lchan) {
|
||||
/* find transaction with this subscriber already paging */
|
||||
|
@ -2693,7 +2707,8 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg)
|
|||
}
|
||||
/* Assign lchan */
|
||||
trans->lchan = lchan;
|
||||
use_lchan(lchan);
|
||||
conn = &lchan->conn;
|
||||
use_subscr_con(conn);
|
||||
subscr_put(subscr);
|
||||
}
|
||||
lchan = trans->lchan;
|
||||
|
@ -2715,11 +2730,12 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg)
|
|||
return rc;
|
||||
}
|
||||
|
||||
conn = &lchan->conn;
|
||||
DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
|
||||
"Received '%s' from MNCC in state %d (%s)\n",
|
||||
lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
|
||||
trans->transaction_id,
|
||||
(lchan->subscr)?(lchan->subscr->extension):"-",
|
||||
(conn->subscr)?(conn->subscr->extension):"-",
|
||||
get_mncc_name(msg_type), trans->cc.state,
|
||||
gsm48_cc_state_name(trans->cc.state));
|
||||
|
||||
|
@ -2795,6 +2811,7 @@ static struct datastate {
|
|||
|
||||
static int gsm0408_rcv_cc(struct msgb *msg)
|
||||
{
|
||||
struct gsm_subscriber_connection *conn;
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
u_int8_t msg_type = gh->msg_type & 0xbf;
|
||||
u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
|
||||
|
@ -2806,14 +2823,16 @@ static int gsm0408_rcv_cc(struct msgb *msg)
|
|||
DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
conn = &lchan->conn;
|
||||
|
||||
/* Find transaction */
|
||||
trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_CC, transaction_id);
|
||||
trans = trans_find_by_id(conn->subscr, GSM48_PDISC_CC, transaction_id);
|
||||
|
||||
DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
|
||||
"Received '%s' from MS in state %d (%s)\n",
|
||||
lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
|
||||
transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
|
||||
transaction_id, (conn->subscr)?(conn->subscr->extension):"-",
|
||||
gsm48_cc_msg_name(msg_type), trans?(trans->cc.state):0,
|
||||
gsm48_cc_state_name(trans?(trans->cc.state):0));
|
||||
|
||||
|
@ -2822,7 +2841,7 @@ static int gsm0408_rcv_cc(struct msgb *msg)
|
|||
DEBUGP(DCC, "Unknown transaction ID %x, "
|
||||
"creating new trans.\n", transaction_id);
|
||||
/* Create transaction */
|
||||
trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
|
||||
trans = trans_alloc(conn->subscr, GSM48_PDISC_CC,
|
||||
transaction_id, new_callref++);
|
||||
if (!trans) {
|
||||
DEBUGP(DCC, "No memory for trans.\n");
|
||||
|
@ -2833,7 +2852,7 @@ static int gsm0408_rcv_cc(struct msgb *msg)
|
|||
}
|
||||
/* Assign transaction */
|
||||
trans->lchan = lchan;
|
||||
use_lchan(lchan);
|
||||
use_subscr_con(conn);
|
||||
}
|
||||
|
||||
/* find function for current state and message */
|
||||
|
|
|
@ -316,16 +316,16 @@ int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr)
|
|||
if (is_siemens_bts(bts))
|
||||
send_siemens_mrpci(msg->lchan, classmark2_lv);
|
||||
|
||||
if (!msg->lchan->subscr) {
|
||||
msg->lchan->subscr = subscr;
|
||||
} else if (msg->lchan->subscr != subscr) {
|
||||
if (!msg->lchan->conn.subscr) {
|
||||
msg->lchan->conn.subscr = subscr;
|
||||
} else if (msg->lchan->conn.subscr != subscr) {
|
||||
LOGP(DRR, LOGL_ERROR, "<- Channel already owned by someone else?\n");
|
||||
subscr_put(subscr);
|
||||
return -EINVAL;
|
||||
} else {
|
||||
DEBUGP(DRR, "<- Channel already owned by us\n");
|
||||
subscr_put(subscr);
|
||||
subscr = msg->lchan->subscr;
|
||||
subscr = msg->lchan->conn.subscr;
|
||||
}
|
||||
|
||||
sig_data.subscr = subscr;
|
||||
|
|
|
@ -594,7 +594,7 @@ static int gsm340_rx_tpdu(struct msgb *msg)
|
|||
}
|
||||
}
|
||||
|
||||
gsms->sender = subscr_get(msg->lchan->subscr);
|
||||
gsms->sender = subscr_get(msg->lchan->conn.subscr);
|
||||
|
||||
LOGP(DSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, "
|
||||
"MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, "
|
||||
|
@ -753,7 +753,7 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
|
|||
trans->sms.sms = NULL;
|
||||
|
||||
/* check for more messages for this subscriber */
|
||||
sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
|
||||
sms = db_sms_get_unsent_for_subscr(msg->lchan->conn.subscr);
|
||||
if (sms)
|
||||
gsm411_send_sms_lchan(msg->lchan, sms);
|
||||
|
||||
|
@ -780,7 +780,7 @@ static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
|
|||
* the cause and take action depending on it */
|
||||
|
||||
LOGP(DSMS, LOGL_NOTICE, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n",
|
||||
subscr_name(msg->lchan->subscr), cause_len, cause,
|
||||
subscr_name(msg->lchan->conn.subscr), cause_len, cause,
|
||||
get_value_string(rp_cause_strs, cause));
|
||||
|
||||
if (!trans->sms.is_mt) {
|
||||
|
@ -833,7 +833,7 @@ static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
|
|||
dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
|
||||
|
||||
/* check for more messages for this subscriber */
|
||||
sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
|
||||
sms = db_sms_get_unsent_for_subscr(msg->lchan->conn.subscr);
|
||||
if (sms)
|
||||
gsm411_send_sms_lchan(msg->lchan, sms);
|
||||
else
|
||||
|
@ -920,16 +920,16 @@ int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
|
|||
struct gsm_trans *trans;
|
||||
int rc = 0;
|
||||
|
||||
if (!lchan->subscr)
|
||||
if (!lchan->conn.subscr)
|
||||
return -EIO;
|
||||
/* FIXME: send some error message */
|
||||
|
||||
DEBUGP(DSMS, "trans_id=%x ", transaction_id);
|
||||
trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
|
||||
trans = trans_find_by_id(lchan->conn.subscr, GSM48_PDISC_SMS,
|
||||
transaction_id);
|
||||
if (!trans) {
|
||||
DEBUGPC(DSMS, "(new) ");
|
||||
trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
|
||||
trans = trans_alloc(lchan->conn.subscr, GSM48_PDISC_SMS,
|
||||
transaction_id, new_callref++);
|
||||
if (!trans) {
|
||||
DEBUGPC(DSMS, "No memory for trans\n");
|
||||
|
@ -942,7 +942,7 @@ int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
|
|||
trans->sms.link_id = link_id;
|
||||
|
||||
trans->lchan = lchan;
|
||||
use_lchan(lchan);
|
||||
use_subscr_con(&lchan->conn);
|
||||
}
|
||||
|
||||
switch(msg_type) {
|
||||
|
@ -961,7 +961,7 @@ int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
|
|||
if (i == transaction_id)
|
||||
continue;
|
||||
|
||||
ptrans = trans_find_by_id(lchan->subscr,
|
||||
ptrans = trans_find_by_id(lchan->conn.subscr,
|
||||
GSM48_PDISC_SMS, i);
|
||||
if (!ptrans)
|
||||
continue;
|
||||
|
@ -1050,7 +1050,7 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
|
|||
int transaction_id;
|
||||
int rc;
|
||||
|
||||
transaction_id = trans_assign_trans_id(lchan->subscr, GSM48_PDISC_SMS, 0);
|
||||
transaction_id = trans_assign_trans_id(lchan->conn.subscr, GSM48_PDISC_SMS, 0);
|
||||
if (transaction_id == -1) {
|
||||
LOGP(DSMS, LOGL_ERROR, "No available transaction ids\n");
|
||||
return -EBUSY;
|
||||
|
@ -1061,7 +1061,7 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
|
|||
DEBUGP(DSMS, "send_sms_lchan()\n");
|
||||
|
||||
/* FIXME: allocate transaction with message reference */
|
||||
trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
|
||||
trans = trans_alloc(lchan->conn.subscr, GSM48_PDISC_SMS,
|
||||
transaction_id, new_callref++);
|
||||
if (!trans) {
|
||||
LOGP(DSMS, LOGL_ERROR, "No memory for trans\n");
|
||||
|
@ -1075,7 +1075,7 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
|
|||
trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */
|
||||
|
||||
trans->lchan = lchan;
|
||||
use_lchan(lchan);
|
||||
use_subscr_con(&lchan->conn);
|
||||
|
||||
/* Hardcode SMSC Originating Address for now */
|
||||
data = (u_int8_t *)msgb_put(msg, 8);
|
||||
|
|
|
@ -187,6 +187,7 @@ void subscr_get_channel(struct gsm_subscriber *subscr,
|
|||
|
||||
void subscr_put_channel(struct gsm_lchan *lchan)
|
||||
{
|
||||
struct gsm_subscriber_connection *conn = &lchan->conn;
|
||||
/*
|
||||
* FIXME: Continue with other requests now... by checking
|
||||
* the gsm_subscriber inside the gsm_lchan. Drop the ref count
|
||||
|
@ -205,9 +206,9 @@ void subscr_put_channel(struct gsm_lchan *lchan)
|
|||
* will listen to the paging requests before we timeout
|
||||
*/
|
||||
|
||||
put_lchan(lchan);
|
||||
put_subscr_con(conn);
|
||||
|
||||
if (lchan->subscr && !llist_empty(&lchan->subscr->requests))
|
||||
subscr_send_paging_request(lchan->subscr);
|
||||
if (lchan->conn.subscr && !llist_empty(&lchan->conn.subscr->requests))
|
||||
subscr_send_paging_request(lchan->conn.subscr);
|
||||
}
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts)
|
|||
new_lchan->bs_power = old_lchan->bs_power;
|
||||
new_lchan->rsl_cmode = old_lchan->rsl_cmode;
|
||||
new_lchan->tch_mode = old_lchan->tch_mode;
|
||||
new_lchan->subscr = subscr_get(old_lchan->subscr);
|
||||
new_lchan->conn.subscr = subscr_get(old_lchan->conn.subscr);
|
||||
|
||||
/* FIXME: do we have a better idea of the timing advance? */
|
||||
rc = rsl_chan_activate_lchan(new_lchan, RSL_ACT_INTER_ASYNC, 0,
|
||||
|
@ -218,7 +218,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)
|
|||
}
|
||||
|
||||
LOGP(DHO, LOGL_INFO, "Subscriber %s HO from BTS %u->%u on ARFCN "
|
||||
"%u->%u\n", subscr_name(ho->old_lchan->subscr),
|
||||
"%u->%u\n", subscr_name(ho->old_lchan->conn.subscr),
|
||||
ho->old_lchan->ts->trx->bts->nr, new_lchan->ts->trx->bts->nr,
|
||||
ho->old_lchan->ts->trx->arfcn, new_lchan->ts->trx->arfcn);
|
||||
|
||||
|
@ -243,6 +243,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)
|
|||
/* GSM 04.08 HANDOVER FAIL has been received */
|
||||
static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan)
|
||||
{
|
||||
struct gsm_subscriber_connection *conn;
|
||||
struct gsm_network *net = old_lchan->ts->trx->bts->network;
|
||||
struct bsc_handover *ho;
|
||||
|
||||
|
@ -256,7 +257,8 @@ static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan)
|
|||
|
||||
bsc_del_timer(&ho->T3103);
|
||||
llist_del(&ho->list);
|
||||
put_lchan(ho->new_lchan);
|
||||
conn = &ho->new_lchan->conn;
|
||||
put_subscr_con(conn);
|
||||
talloc_free(ho);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
static int paging_cb_silent(unsigned int hooknum, unsigned int event,
|
||||
struct msgb *msg, void *_lchan, void *_data)
|
||||
{
|
||||
struct gsm_subscriber_connection *conn;
|
||||
struct gsm_lchan *lchan = _lchan;
|
||||
struct scall_signal_data sigdata;
|
||||
int rc;
|
||||
|
@ -47,6 +48,8 @@ static int paging_cb_silent(unsigned int hooknum, unsigned int event,
|
|||
|
||||
DEBUGP(DSMS, "paging_cb_silent: ");
|
||||
|
||||
conn = &lchan->conn;
|
||||
|
||||
sigdata.lchan = lchan;
|
||||
sigdata.data = _data;
|
||||
|
||||
|
@ -54,10 +57,10 @@ static int paging_cb_silent(unsigned int hooknum, unsigned int event,
|
|||
case GSM_PAGING_SUCCEEDED:
|
||||
DEBUGPC(DSMS, "success, using Timeslot %u on ARFCN %u\n",
|
||||
lchan->ts->nr, lchan->ts->trx->arfcn);
|
||||
lchan->silent_call = 1;
|
||||
conn->silent_call = 1;
|
||||
/* increment lchan reference count */
|
||||
dispatch_signal(SS_SCALL, S_SCALL_SUCCESS, &sigdata);
|
||||
use_lchan(lchan);
|
||||
use_subscr_con(conn);
|
||||
break;
|
||||
case GSM_PAGING_EXPIRED:
|
||||
DEBUGP(DSMS, "expired\n");
|
||||
|
@ -97,7 +100,7 @@ int silent_call_reroute(struct msgb *msg)
|
|||
int i;
|
||||
|
||||
/* if we're not part of a silent call, never reroute */
|
||||
if (!msg->lchan->silent_call)
|
||||
if (!msg->lchan->conn.silent_call)
|
||||
return 0;
|
||||
|
||||
/* check if we are a special message that is handled in openbsc */
|
||||
|
@ -126,16 +129,18 @@ int gsm_silent_call_start(struct gsm_subscriber *subscr, void *data, int type)
|
|||
int gsm_silent_call_stop(struct gsm_subscriber *subscr)
|
||||
{
|
||||
struct gsm_lchan *lchan;
|
||||
struct gsm_subscriber_connection *conn;
|
||||
|
||||
lchan = lchan_for_subscr(subscr);
|
||||
if (!lchan)
|
||||
return -EINVAL;
|
||||
|
||||
/* did we actually establish a silent call for this guy? */
|
||||
if (!lchan->silent_call)
|
||||
conn = &lchan->conn;
|
||||
if (!conn->silent_call)
|
||||
return -EINVAL;
|
||||
|
||||
put_lchan(lchan);
|
||||
put_subscr_con(conn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ void trans_free(struct gsm_trans *trans)
|
|||
}
|
||||
|
||||
if (trans->lchan)
|
||||
put_lchan(trans->lchan);
|
||||
put_subscr_con(&trans->lchan->conn);
|
||||
|
||||
if (!trans->lchan && trans->subscr && trans->subscr->net) {
|
||||
/* Stop paging on all bts' */
|
||||
|
@ -157,12 +157,16 @@ int trans_lchan_change(struct gsm_lchan *lchan_old,
|
|||
|
||||
llist_for_each_entry(trans, &net->trans_list, entry) {
|
||||
if (trans->lchan == lchan_old) {
|
||||
/* drop old channel use cound */
|
||||
put_lchan(trans->lchan);
|
||||
struct gsm_subscriber_connection *conn;
|
||||
|
||||
/* drop old channel use count */
|
||||
conn = &trans->lchan->conn;
|
||||
put_subscr_con(conn);
|
||||
/* assign new channel */
|
||||
trans->lchan = lchan_new;
|
||||
/* bump new channel use count */
|
||||
use_lchan(trans->lchan);
|
||||
conn = &trans->lchan->conn;
|
||||
use_subscr_con(conn);
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ int handle_rcv_ussd(struct msgb *msg)
|
|||
/* A network-specific handler function */
|
||||
static int send_own_number(const struct msgb *msg, const struct ussd_request *req)
|
||||
{
|
||||
char *own_number = msg->lchan->subscr->extension;
|
||||
char *own_number = msg->lchan->conn.subscr->extension;
|
||||
char response_string[GSM_EXTENSION_LENGTH + 20];
|
||||
|
||||
/* Need trailing CR as EOT character */
|
||||
|
|
|
@ -601,16 +601,16 @@ static void lchan_dump_vty(struct vty *vty, struct gsm_lchan *lchan)
|
|||
lchan->nr, lchan->ts->nr, lchan->ts->trx->nr,
|
||||
lchan->ts->trx->bts->nr, gsm_lchant_name(lchan->type),
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " Use Count: %u, State: %s%s", lchan->use_count,
|
||||
vty_out(vty, " Use Count: %u, State: %s%s", lchan->conn.use_count,
|
||||
gsm_lchans_name(lchan->state), VTY_NEWLINE);
|
||||
vty_out(vty, " BS Power: %u dBm, MS Power: %u dBm%s",
|
||||
lchan->ts->trx->nominal_power - lchan->ts->trx->max_power_red
|
||||
- lchan->bs_power*2,
|
||||
ms_pwr_dbm(lchan->ts->trx->bts->band, lchan->ms_power),
|
||||
VTY_NEWLINE);
|
||||
if (lchan->subscr) {
|
||||
if (lchan->conn.subscr) {
|
||||
vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
|
||||
subscr_dump_vty(vty, lchan->subscr);
|
||||
subscr_dump_vty(vty, lchan->conn.subscr);
|
||||
} else
|
||||
vty_out(vty, " No Subscriber%s", VTY_NEWLINE);
|
||||
if (is_ipaccess_bts(lchan->ts->trx->bts)) {
|
||||
|
|
Loading…
Reference in New Issue