diff options
-rw-r--r-- | openbsc/include/openbsc/Makefile.am | 2 | ||||
-rw-r--r-- | openbsc/include/openbsc/bsc_api.h | 6 | ||||
-rw-r--r-- | openbsc/include/openbsc/gsm_04_11.h | 2 | ||||
-rw-r--r-- | openbsc/include/openbsc/gsm_data.h | 64 | ||||
-rw-r--r-- | openbsc/include/openbsc/transaction.h | 8 | ||||
-rw-r--r-- | openbsc/src/Makefile.am | 2 | ||||
-rw-r--r-- | openbsc/src/abis_rsl.c | 2 | ||||
-rw-r--r-- | openbsc/src/bsc_api.c | 33 | ||||
-rw-r--r-- | openbsc/src/bsc_rll.c | 9 | ||||
-rw-r--r-- | openbsc/src/chan_alloc.c | 39 | ||||
-rw-r--r-- | openbsc/src/gsm_04_08.c | 209 | ||||
-rw-r--r-- | openbsc/src/gsm_04_08_utils.c | 10 | ||||
-rw-r--r-- | openbsc/src/gsm_04_11.c | 77 | ||||
-rw-r--r-- | openbsc/src/gsm_subscriber_base.c | 7 | ||||
-rw-r--r-- | openbsc/src/handover_logic.c | 10 | ||||
-rw-r--r-- | openbsc/src/mncc.c | 6 | ||||
-rw-r--r-- | openbsc/src/silent_call.c | 15 | ||||
-rw-r--r-- | openbsc/src/transaction.c | 23 | ||||
-rw-r--r-- | openbsc/src/ussd.c | 2 | ||||
-rw-r--r-- | openbsc/src/vty_interface.c | 6 |
20 files changed, 306 insertions, 226 deletions
diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 483997a9d..6a8778231 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -7,5 +7,5 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \ silent_call.h mgcp.h meas_rep.h rest_octets.h \ system_information.h handover.h mgcp_internal.h -openbsc_HEADERS = gsm_04_08.h meas_rep.h +openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h openbscdir = $(includedir)/openbsc diff --git a/openbsc/include/openbsc/bsc_api.h b/openbsc/include/openbsc/bsc_api.h new file mode 100644 index 000000000..51e344f5a --- /dev/null +++ b/openbsc/include/openbsc/bsc_api.h @@ -0,0 +1,6 @@ +/* GSM 08.08 like API for OpenBSC */ + +#include "gsm_data.h" + + +int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id); diff --git a/openbsc/include/openbsc/gsm_04_11.h b/openbsc/include/openbsc/gsm_04_11.h index 9badd3659..8127af1ea 100644 --- a/openbsc/include/openbsc/gsm_04_11.h +++ b/openbsc/include/openbsc/gsm_04_11.h @@ -25,7 +25,7 @@ struct msgb; int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id); -int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms); +int gsm411_send_sms_lchan(struct gsm_subscriber_connection *conn, struct gsm_sms *sms); struct gsm_sms *sms_alloc(void); void sms_free(struct gsm_sms *sms); diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 88e7f16c3..f352711a2 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -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,30 @@ 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 pointers */ + struct gsm_lchan *lchan; + struct gsm_bts *bts; +}; + struct gsm_lchan { /* The TS that we're part of */ struct gsm_bts_trx_ts *ts; @@ -204,31 +228,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 +254,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 { diff --git a/openbsc/include/openbsc/transaction.h b/openbsc/include/openbsc/transaction.h index 50c3cc5da..90a008bdc 100644 --- a/openbsc/include/openbsc/transaction.h +++ b/openbsc/include/openbsc/transaction.h @@ -20,8 +20,8 @@ struct gsm_trans { /* To whom we belong, unique identifier of remote MM entity */ struct gsm_subscriber *subscr; - /* The LCHAN that we're currently using to transmit messages */ - struct gsm_lchan *lchan; + /* The associated connection we are using to transmit messages */ + struct gsm_subscriber_connection *conn; /* reference from MNCC or other application */ u_int32_t callref; @@ -71,6 +71,6 @@ int trans_assign_trans_id(struct gsm_subscriber *subscr, /* update all transactions to use a different LCHAN, e.g. * after handover has succeeded */ -int trans_lchan_change(struct gsm_lchan *lchan_old, - struct gsm_lchan *lchan_new); +int trans_lchan_change(struct gsm_subscriber_connection *conn_old, + struct gsm_subscriber_connection *conn_new); #endif diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am index 1d1847513..cbc809dc7 100644 --- a/openbsc/src/Makefile.am +++ b/openbsc/src/Makefile.am @@ -17,7 +17,7 @@ libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_data.c gsm_04_08_utils.c \ input/misdn.c input/ipaccess.c \ talloc_ctx.c system_information.c rest_octets.c \ rtp_proxy.c bts_siemens_bs11.c bts_ipaccess_nanobts.c \ - bts_unknown.c bsc_version.c + bts_unknown.c bsc_version.c bsc_api.c libmsc_a_SOURCES = gsm_subscriber.c db.c telnet_interface.c \ mncc.c gsm_04_08.c gsm_04_11.c transaction.c \ diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index e7844afd2..0c3b59741 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -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; } diff --git a/openbsc/src/bsc_api.c b/openbsc/src/bsc_api.c new file mode 100644 index 000000000..b504752e1 --- /dev/null +++ b/openbsc/src/bsc_api.c @@ -0,0 +1,33 @@ +/* GSM 08.08 like API for OpenBSC. The bridge from MSC to BSC */ + +/* (C) 2010 by Holger Hans Peter Freyther + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <openbsc/bsc_api.h> +#include <openbsc/abis_rsl.h> + + +int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, + struct msgb *msg, int link_id) +{ + msg->lchan = conn->lchan; + msg->trx = msg->lchan->ts->trx; + return rsl_data_request(msg, link_id); +} diff --git a/openbsc/src/bsc_rll.c b/openbsc/src/bsc_rll.c index 1551d948b..9a4f5aae4 100644 --- a/openbsc/src/bsc_rll.c +++ b/openbsc/src/bsc_rll.c @@ -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; diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c index 2e885241c..c8e358dc8 100644 --- a/openbsc/src/chan_alloc.c +++ b/openbsc/src/chan_alloc.c @@ -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,16 @@ 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.bts = lchan->ts->trx->bts; + 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 +280,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 +304,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 +313,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 +338,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 +350,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; } } diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index 2eda0bd99..2376c63b2 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -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,14 +159,14 @@ 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 * only set trans->lchan to NULL and wait for another lchan to be * established to the same MM entity (phone/subscriber) */ llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) { - if (trans->lchan == lchan) + if (trans->conn && trans->conn->lchan == lchan) trans_free(trans); } @@ -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 */ @@ -1062,12 +1071,12 @@ static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans, struct msgb *msg; if (trans) - if (trans->lchan) + if (trans->conn) DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) " "Sending '%s' to MNCC.\n", - trans->lchan->ts->trx->bts->nr, - trans->lchan->ts->trx->nr, - trans->lchan->ts->nr, trans->transaction_id, + trans->conn->lchan->ts->trx->bts->nr, + trans->conn->lchan->ts->trx->nr, + trans->conn->lchan->ts->nr, trans->transaction_id, (trans->subscr)?(trans->subscr->extension):"-", get_mncc_name(msg_type)); else @@ -1116,8 +1125,8 @@ void _gsm48_cc_trans_free(struct gsm_trans *trans) } if (trans->cc.state != GSM_CSTATE_NULL) new_cc_state(trans, GSM_CSTATE_NULL); - if (trans->lchan) - trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref); + if (trans->conn) + trau_mux_unmap(&trans->conn->lchan->ts->e1_link, trans->callref); } static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg); @@ -1144,7 +1153,7 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, /* check all tranactions (without lchan) for subscriber */ llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) { - if (transt->subscr != subscr || transt->lchan) + if (transt->subscr != subscr || transt->conn) continue; switch (event) { case GSM_PAGING_SUCCEEDED: @@ -1153,9 +1162,9 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, DEBUGP(DCC, "Paging subscr %s succeeded!\n", subscr->extension); /* Assign lchan */ - if (!transt->lchan) { - transt->lchan = lchan; - use_lchan(lchan); + if (!transt->conn) { + transt->conn = &lchan->conn; + use_subscr_con(transt->conn); } /* send SETUP request to called party */ gsm48_cc_tx_setup(transt, &transt->cc.msg); @@ -1200,7 +1209,7 @@ static int handle_abisip_signal(unsigned int subsys, unsigned int signal, * a tch_recv_mncc request pending */ net = lchan->ts->trx->bts->network; llist_for_each_entry(trans, &net->trans_list, entry) { - if (trans->lchan == lchan && trans->tch_recv) { + if (trans->conn && trans->conn->lchan == lchan && trans->tch_recv) { DEBUGP(DCC, "pending tch_recv_mncc request\n"); tch_recv_mncc(net, trans->callref, 1); } @@ -1273,11 +1282,11 @@ static int tch_bridge(struct gsm_network *net, u_int32_t *refs) if (!trans1 || !trans2) return -EIO; - if (!trans1->lchan || !trans2->lchan) + if (!trans1->conn || !trans2->conn) return -EIO; /* through-connect channel */ - return tch_map(trans1->lchan, trans2->lchan); + return tch_map(trans1->conn->lchan, trans2->conn->lchan); } /* enable receive of channels to MNCC upqueue */ @@ -1292,9 +1301,9 @@ static int tch_recv_mncc(struct gsm_network *net, u_int32_t callref, int enable) trans = trans_find_by_callref(net, callref); if (!trans) return -EIO; - if (!trans->lchan) + if (!trans->conn) return 0; - lchan = trans->lchan; + lchan = trans->conn->lchan; bts = lchan->ts->trx->bts; switch (bts->type) { @@ -2490,7 +2499,7 @@ static int _gsm48_lchan_modify(struct gsm_trans *trans, void *arg) { struct gsm_mncc *mode = arg; - return gsm48_lchan_modify(trans->lchan, mode->lchan_mode); + return gsm48_lchan_modify(trans->conn->lchan, mode->lchan_mode); } static struct downstate { @@ -2576,18 +2585,18 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) trans = trans_find_by_callref(net, data->callref); if (!trans) return -EIO; - if (!trans->lchan) + if (!trans->conn) return 0; - if (trans->lchan->type != GSM_LCHAN_TCH_F) + if (trans->conn->lchan->type != GSM_LCHAN_TCH_F) return 0; - bts = trans->lchan->ts->trx->bts; + bts = trans->conn->lchan->ts->trx->bts; switch (bts->type) { case GSM_BTS_TYPE_NANOBTS: - if (!trans->lchan->abis_ip.rtp_socket) + if (!trans->conn->lchan->abis_ip.rtp_socket) return 0; - return rtp_send_frame(trans->lchan->abis_ip.rtp_socket, arg); + return rtp_send_frame(trans->conn->lchan->abis_ip.rtp_socket, arg); case GSM_BTS_TYPE_BS11: - return trau_send_frame(trans->lchan, arg); + return trau_send_frame(trans->conn->lchan, arg); default: DEBUGP(DCC, "Unknown BTS type %u\n", bts->type); } @@ -2665,6 +2674,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 */ @@ -2692,11 +2702,13 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) return 0; } /* Assign lchan */ - trans->lchan = lchan; - use_lchan(lchan); + trans->conn = &lchan->conn; + use_subscr_con(trans->conn); subscr_put(subscr); } - lchan = trans->lchan; + + if (trans->conn) + lchan = trans->conn->lchan; /* if paging did not respond yet */ if (!lchan) { @@ -2719,7 +2731,7 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) "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):"-", + (trans->conn->subscr)?(trans->conn->subscr->extension):"-", get_mncc_name(msg_type), trans->cc.state, gsm48_cc_state_name(trans->cc.state)); @@ -2795,6 +2807,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 +2819,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 +2837,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"); @@ -2832,8 +2847,8 @@ static int gsm0408_rcv_cc(struct msgb *msg) return -ENOMEM; } /* Assign transaction */ - trans->lchan = lchan; - use_lchan(lchan); + trans->conn = &lchan->conn; + use_subscr_con(trans->conn); } /* find function for current state and message */ diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index 2472f12b0..ed3f9052f 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -57,7 +57,7 @@ int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans) * work that the caller no longer has to do */ if (trans) { gh->proto_discr = trans->protocol | (trans->transaction_id << 4); - msg->lchan = trans->lchan; + msg->lchan = trans->conn->lchan; } if (msg->lchan) { @@ -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; diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c index 881c3755a..e3f37f633 100644 --- a/openbsc/src/gsm_04_11.c +++ b/openbsc/src/gsm_04_11.c @@ -24,6 +24,7 @@ */ +#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -121,16 +122,11 @@ struct msgb *gsm411_msgb_alloc(void) "GSM 04.11"); } -static int gsm411_sendmsg(struct msgb *msg, u_int8_t link_id) +static int gsm411_sendmsg(struct gsm_subscriber_connection *conn, struct msgb *msg, u_int8_t link_id) { - if (msg->lchan) - msg->trx = msg->lchan->ts->trx; - - msg->l3h = msg->data; - DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len)); - - return rsl_data_request(msg, link_id); + msg->l3h = msg->data; + return gsm0808_submit_dtap(conn, msg, link_id); } /* SMC TC1* is expired */ @@ -154,9 +150,6 @@ static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans, gh->proto_discr = trans->protocol | (trans->transaction_id<<4); gh->msg_type = msg_type; - /* assign the outgoing lchan */ - msg->lchan = trans->lchan; - /* mobile originating */ switch (gh->msg_type) { case GSM411_MT_CP_DATA: @@ -179,7 +172,7 @@ static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans, DEBUGPC(DSMS, "trans=%x\n", trans->transaction_id); - return gsm411_sendmsg(msg, trans->sms.link_id); + return gsm411_sendmsg(trans->conn, msg, trans->sms.link_id); } /* Prefix msg with a RP-DATA header and send as CP-DATA */ @@ -511,9 +504,8 @@ static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms) /* process an incoming TPDU (called from RP-DATA) * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */ -static int gsm340_rx_tpdu(struct msgb *msg) +static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *msg) { - struct gsm_bts *bts = msg->lchan->ts->trx->bts; u_int8_t *smsp = msgb_sms(msg); struct gsm_sms *gsms; u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp; @@ -522,7 +514,7 @@ static int gsm340_rx_tpdu(struct msgb *msg) u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */ int rc = 0; - counter_inc(bts->network->stats.sms.submitted); + counter_inc(conn->bts->network->stats.sms.submitted); gsms = sms_alloc(); if (!gsms) @@ -594,7 +586,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, " @@ -610,10 +602,10 @@ static int gsm340_rx_tpdu(struct msgb *msg) dispatch_signal(SS_SMS, 0, gsms); /* determine gsms->receiver based on dialled number */ - gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr); + gsms->receiver = subscr_get_by_extension(conn->bts->network, gsms->dest_addr); if (!gsms->receiver) { rc = 1; /* cause 1: unknown subscriber */ - counter_inc(bts->network->stats.sms.no_receiver); + counter_inc(conn->bts->network->stats.sms.no_receiver); goto out; } @@ -687,7 +679,7 @@ static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans, DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len)); - rc = gsm340_rx_tpdu(msg); + rc = gsm340_rx_tpdu(trans->conn, msg); if (rc == 0) return gsm411_send_rp_ack(trans, rph->msg_ref); else if (rc > 0) @@ -753,14 +745,17 @@ 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); + assert(msg->lchan->conn.subscr == trans->subscr); + + sms = db_sms_get_unsent_for_subscr(trans->subscr); if (sms) - gsm411_send_sms_lchan(msg->lchan, sms); + gsm411_send_sms_lchan(trans->conn, sms); /* free the transaction here */ trans_free(trans); /* release channel if done */ +#warning "BROKEN. The SAPI will be released automatically by the BSC" if (!sms) rsl_release_request(msg->lchan, trans->sms.link_id); @@ -770,7 +765,7 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans, static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans, struct gsm411_rp_hdr *rph) { - struct gsm_network *net = trans->lchan->ts->trx->bts->network; + struct gsm_network *net = trans->conn->bts->network; struct gsm_sms *sms = trans->sms.sms; u_int8_t cause_len = rph->data[0]; u_int8_t cause = rph->data[1]; @@ -780,7 +775,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(trans->conn->subscr), cause_len, cause, get_value_string(rp_cause_strs, cause)); if (!trans->sms.is_mt) { @@ -833,11 +828,13 @@ 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); + assert(msg->lchan->conn.subscr == trans->subscr); + sms = db_sms_get_unsent_for_subscr(trans->subscr); if (sms) - gsm411_send_sms_lchan(msg->lchan, sms); + gsm411_send_sms_lchan(trans->conn, sms); else rsl_release_request(msg->lchan, trans->sms.link_id); +#warning "BROKEN: The SAPI=3 will be released automatically by the BSC" return rc; } @@ -920,16 +917,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"); @@ -941,8 +938,8 @@ int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id) trans->sms.is_mt = 0; trans->sms.link_id = link_id; - trans->lchan = lchan; - use_lchan(lchan); + trans->conn = &lchan->conn; + use_subscr_con(trans->conn); } switch(msg_type) { @@ -961,7 +958,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; @@ -1041,7 +1038,7 @@ static u_int8_t tpdu_test[] = { /* Take a SMS in gsm_sms structure and send it through an already * existing lchan. We also assume that the caller ensured this lchan already * has a SAPI3 RLL connection! */ -int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms) +int gsm411_send_sms_lchan(struct gsm_subscriber_connection *conn, struct gsm_sms *sms) { struct msgb *msg = gsm411_msgb_alloc(); struct gsm_trans *trans; @@ -1050,18 +1047,16 @@ 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(conn->subscr, GSM48_PDISC_SMS, 0); if (transaction_id == -1) { LOGP(DSMS, LOGL_ERROR, "No available transaction ids\n"); return -EBUSY; } - msg->lchan = lchan; - DEBUGP(DSMS, "send_sms_lchan()\n"); /* FIXME: allocate transaction with message reference */ - trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS, + trans = trans_alloc(conn->subscr, GSM48_PDISC_SMS, transaction_id, new_callref++); if (!trans) { LOGP(DSMS, LOGL_ERROR, "No memory for trans\n"); @@ -1074,8 +1069,8 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms) trans->sms.sms = sms; trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */ - trans->lchan = lchan; - use_lchan(lchan); + trans->conn = conn; + use_subscr_con(trans->conn); /* Hardcode SMSC Originating Address for now */ data = (u_int8_t *)msgb_put(msg, 8); @@ -1112,7 +1107,7 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms) DEBUGP(DSMS, "TX: SMS DELIVER\n"); - counter_inc(lchan->ts->trx->bts->network->stats.sms.delivered); + counter_inc(conn->bts->network->stats.sms.delivered); return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref); /* FIXME: enter 'wait for RP-ACK' state, start TR1N */ @@ -1130,11 +1125,13 @@ static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id, switch (type) { case BSC_RLLR_IND_EST_CONF: - gsm411_send_sms_lchan(lchan, sms); +#warning "BROKEN: The BSC will establish this transparently" + gsm411_send_sms_lchan(&lchan->conn, sms); break; case BSC_RLLR_IND_REL_IND: case BSC_RLLR_IND_ERR_IND: case BSC_RLLR_IND_TIMEOUT: +#warning "BROKEN: We will need to handle SAPI n Reject" sms_free(sms); break; } diff --git a/openbsc/src/gsm_subscriber_base.c b/openbsc/src/gsm_subscriber_base.c index dee89c0bc..40c3bbda3 100644 --- a/openbsc/src/gsm_subscriber_base.c +++ b/openbsc/src/gsm_subscriber_base.c @@ -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); } diff --git a/openbsc/src/handover_logic.c b/openbsc/src/handover_logic.c index bd4c563f0..7fb0b13e1 100644 --- a/openbsc/src/handover_logic.c +++ b/openbsc/src/handover_logic.c @@ -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); @@ -227,7 +227,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan) bsc_del_timer(&ho->T3103); /* update lchan pointer of transaction */ - trans_lchan_change(ho->old_lchan, new_lchan); + trans_lchan_change(&ho->old_lchan->conn, &new_lchan->conn); ho->old_lchan->state = LCHAN_S_INACTIVE; lchan_auto_release(ho->old_lchan); @@ -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; diff --git a/openbsc/src/mncc.c b/openbsc/src/mncc.c index 01d59aad1..afd53644e 100644 --- a/openbsc/src/mncc.c +++ b/openbsc/src/mncc.c @@ -332,16 +332,16 @@ static int mncc_rcv_tchf(struct gsm_call *call, int msg_type, remote_trans = trans_find_by_callref(call->net, call->remote_ref); /* this shouldn't really happen */ - if (!remote_trans || !remote_trans->lchan) { + if (!remote_trans || !remote_trans->conn) { LOGP(DMNCC, LOGL_ERROR, "No transaction or transaction without lchan?!?\n"); return -EIO; } /* RTP socket of remote end has meanwhile died */ - if (!remote_trans->lchan->abis_ip.rtp_socket) + if (!remote_trans->conn->lchan->abis_ip.rtp_socket) return -EIO; - return rtp_send_frame(remote_trans->lchan->abis_ip.rtp_socket, dfr); + return rtp_send_frame(remote_trans->conn->lchan->abis_ip.rtp_socket, dfr); } diff --git a/openbsc/src/silent_call.c b/openbsc/src/silent_call.c index cada24e66..8bd5341ec 100644 --- a/openbsc/src/silent_call.c +++ b/openbsc/src/silent_call.c @@ -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; } diff --git a/openbsc/src/transaction.c b/openbsc/src/transaction.c index 75a279ddc..5e0d50796 100644 --- a/openbsc/src/transaction.c +++ b/openbsc/src/transaction.c @@ -95,10 +95,10 @@ void trans_free(struct gsm_trans *trans) break; } - if (trans->lchan) - put_lchan(trans->lchan); + if (trans->conn) + put_subscr_con(trans->conn); - if (!trans->lchan && trans->subscr && trans->subscr->net) { + if (!trans->conn && trans->subscr && trans->subscr->net) { /* Stop paging on all bts' */ paging_request_stop(NULL, trans->subscr, NULL); } @@ -148,21 +148,22 @@ int trans_assign_trans_id(struct gsm_subscriber *subscr, /* update all transactions to use a different LCHAN, e.g. * after handover has succeeded */ -int trans_lchan_change(struct gsm_lchan *lchan_old, - struct gsm_lchan *lchan_new) +int trans_lchan_change(struct gsm_subscriber_connection *conn_old, + struct gsm_subscriber_connection *conn_new) { - struct gsm_network *net = lchan_old->ts->trx->bts->network; + struct gsm_network *net = conn_old->lchan->ts->trx->bts->network; struct gsm_trans *trans; int num = 0; llist_for_each_entry(trans, &net->trans_list, entry) { - if (trans->lchan == lchan_old) { - /* drop old channel use cound */ - put_lchan(trans->lchan); + if (trans->conn == conn_old) { + + /* drop old channel use count */ + put_subscr_con(conn_old); /* assign new channel */ - trans->lchan = lchan_new; + trans->conn = conn_new; /* bump new channel use count */ - use_lchan(trans->lchan); + use_subscr_con(conn_new); num++; } } diff --git a/openbsc/src/ussd.c b/openbsc/src/ussd.c index a3d11f080..547691965 100644 --- a/openbsc/src/ussd.c +++ b/openbsc/src/ussd.c @@ -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 */ diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index e8948697f..6dbae8c50 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -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)) { |