diff options
Diffstat (limited to 'openbsc/src/libmsc/gsm_04_08.c')
-rw-r--r-- | openbsc/src/libmsc/gsm_04_08.c | 594 |
1 files changed, 331 insertions, 263 deletions
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index f02f784fe..8c1cf9adb 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -28,6 +28,7 @@ #include <errno.h> #include <time.h> #include <netinet/in.h> +#include <openssl/rand.h> #include "bscconfig.h" @@ -63,14 +64,21 @@ #include <osmocom/core/msgb.h> #include <osmocom/core/talloc.h> #include <osmocom/gsm/tlv.h> +#include <osmocom/crypt/auth.h> + +#include <openbsc/msc_ifaces.h> +#include <openbsc/iu.h> #include <assert.h> + +/* These debug statements were removed during the BSC/MSC split. It may make + * sense to replace them with debug statements that do not access BTS data. */ +#define BEFORE_MSCSPLIT 0 + void *tall_locop_ctx; void *tall_authciphop_ctx; -static int tch_rtp_signal(struct gsm_lchan *lchan, int signal); - static int gsm0408_loc_upd_acc(struct gsm_subscriber_connection *conn); static int gsm48_tx_simple(struct gsm_subscriber_connection *conn, uint8_t pdisc, uint8_t msg_type); @@ -83,29 +91,6 @@ struct gsm_lai { uint16_t lac; }; -static int apply_codec_restrictions(struct gsm_bts *bts, - struct gsm_mncc_bearer_cap *bcap) -{ - int i, j; - - /* remove unsupported speech versions from list */ - for (i = 0, j = 0; bcap->speech_ver[i] >= 0; i++) { - if (bcap->speech_ver[i] == GSM48_BCAP_SV_FR) - bcap->speech_ver[j++] = GSM48_BCAP_SV_FR; - if (bcap->speech_ver[i] == GSM48_BCAP_SV_EFR && bts->codec.efr) - bcap->speech_ver[j++] = GSM48_BCAP_SV_EFR; - if (bcap->speech_ver[i] == GSM48_BCAP_SV_AMR_F && bts->codec.amr) - bcap->speech_ver[j++] = GSM48_BCAP_SV_AMR_F; - if (bcap->speech_ver[i] == GSM48_BCAP_SV_HR && bts->codec.hr) - bcap->speech_ver[j++] = GSM48_BCAP_SV_HR; - if (bcap->speech_ver[i] == GSM48_BCAP_SV_AMR_H && bts->codec.amr) - bcap->speech_ver[j++] = GSM48_BCAP_SV_AMR_H; - } - bcap->speech_ver[j] = -1; - - return 0; -} - static uint32_t new_callref = 0x80000001; void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg) @@ -122,30 +107,9 @@ static int gsm48_conn_sendmsg(struct msgb *msg, struct gsm_subscriber_connection * work that the caller no longer has to do */ if (trans) { gh->proto_discr = trans->protocol | (trans->transaction_id << 4); - msg->lchan = trans->conn->lchan; } - if (msg->lchan) { - struct e1inp_sign_link *sign_link = - msg->lchan->ts->trx->rsl_link; - - msg->dst = sign_link; - if (gsm48_hdr_pdisc(gh) == GSM48_PDISC_CC) - DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) " - "Sending '%s' to MS.\n", - sign_link->trx->bts->nr, - sign_link->trx->nr, msg->lchan->ts->nr, - gh->proto_discr & 0xf0, - gsm48_cc_msg_name(gh->msg_type)); - else - DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) " - "Sending 0x%02x to MS.\n", - sign_link->trx->bts->nr, - sign_link->trx->nr, msg->lchan->ts->nr, - gh->proto_discr, gh->msg_type); - } - - return gsm0808_submit_dtap(conn, msg, 0, 0); + return msc_tx_dtap(conn, msg); } int gsm48_cc_tx_notify_ss(struct gsm_trans *trans, const char *message) @@ -181,10 +145,33 @@ void allocate_security_operation(struct gsm_subscriber_connection *conn) struct gsm_security_operation); } +int iu_hack__get_hardcoded_auth_tuple(struct gsm_auth_tuple *atuple) +{ + unsigned char tmp_rand[16]; + /* Ki 000102030405060708090a0b0c0d0e0f */ + struct osmo_sub_auth_data auth = { + .type = OSMO_AUTH_TYPE_GSM, + .algo = OSMO_AUTH_ALG_COMP128v1, + .u.gsm.ki = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f + }, + }; + + RAND_bytes(tmp_rand, sizeof(tmp_rand)); + + memset(&atuple->vec, 0, sizeof(atuple->vec)); + osmo_auth_gen_vec(&atuple->vec, &auth, tmp_rand); + + atuple->key_seq = 0; + return AUTH_DO_AUTH; +} + int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq, gsm_cbfn *cb, void *cb_data) { - struct gsm_network *net = conn->bts->network; + struct gsm_network *net = conn->network; struct gsm_subscriber *subscr = conn->subscr; struct gsm_security_operation *op; struct gsm_auth_tuple atuple; @@ -196,8 +183,15 @@ int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq, * - Subscriber equipment doesn't support configured encryption */ if (!net->a5_encryption) { - status = GSM_SECURITY_NOAVAIL; - } else if (conn->lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) { + if (conn->via_iface == IFACE_IU) { + DEBUGP(DMM, "No A5 encryption configured, but doing" + " authentication as required by Iu\n"); + status = -1; + } else { + DEBUGP(DMM, "No A5 encryption configured\n"); + status = GSM_SECURITY_NOAVAIL; + } + } else if (conn->encr.alg_id > RSL_ENC_ALG_A5(0)) { DEBUGP(DMM, "Requesting to secure an already secure channel"); status = GSM_SECURITY_ALREADY; } else if (!ms_cm2_a5n_support(subscr->equipment.classmark2, @@ -208,20 +202,47 @@ int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq, /* If not done yet, try to get info for this user */ if (status < 0) { - rc = auth_get_tuple_for_subscr(&atuple, subscr, key_seq); - if (rc <= 0) - status = GSM_SECURITY_NOAVAIL; + /* DEV HACK: hardcode keys for Iu */ + if (conn->via_iface == IFACE_IU) + rc = iu_hack__get_hardcoded_auth_tuple(&atuple); + else + rc = auth_get_tuple_for_subscr(&atuple, subscr, key_seq); + DEBUGP(DMM, "auth_get_tuple_for_subscr(%s) == %d\n", + subscr_name(subscr), rc); + if (rc <= 0) { + if (conn->via_iface == IFACE_IU) { + LOGP(DMM, LOGL_ERROR, + "Iu requires authentication but no" + " retreivable Ki for subscriber %s\n", + subscr_name(subscr)); + status = GSM_SECURITY_AUTH_FAILED; + } else { + LOGP(DMM, LOGL_NOTICE, + "No retrievable Ki for subscriber," + " skipping auth\n"); + status = GSM_SECURITY_NOAVAIL; + } + } } /* Are we done yet ? */ - if (status >= 0) + if (status >= 0) { + DEBUGP(DMM, "gsm48_secure_channel(%s) returning with status %d\n", + subscr_name(subscr), status); return cb ? cb(GSM_HOOK_RR_SECURITY, status, NULL, conn, cb_data) : 0; + } /* Start an operation (can't have more than one pending !!!) */ - if (conn->sec_operation) + if (conn->sec_operation) { + DEBUGP(DMM, "gsm48_secure_channel(%s) error: attempt to start" + " second security operation\n", + subscr_name(subscr)); return -EBUSY; + } + DEBUGP(DMM, "gsm48_secure_channel(%s) starting security operation\n", + subscr_name(subscr)); allocate_security_operation(conn); op = conn->sec_operation; @@ -229,14 +250,18 @@ int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq, op->cb_data = cb_data; memcpy(&op->atuple, &atuple, sizeof(struct gsm_auth_tuple)); - /* FIXME: Should start a timer for completion ... */ + /* FIXME: Should start a timer for completion ... */ /* Then do whatever is needed ... */ - if (rc == AUTH_DO_AUTH_THEN_CIPH) { + if ((rc == AUTH_DO_AUTH_THEN_CIPH) || (rc == AUTH_DO_AUTH)) { /* Start authentication */ + DEBUGP(DMM, "gsm48_secure_channel(%s) starting authentication\n", + subscr_name(subscr)); return gsm48_tx_mm_auth_req(conn, op->atuple.vec.rand, op->atuple.key_seq); } else if (rc == AUTH_DO_CIPH) { /* Start ciphering directly */ + DEBUGP(DMM, "gsm48_secure_channel(%s) starting ciphering\n", + subscr_name(subscr)); return gsm0808_cipher_mode(conn, net->a5_encryption, op->atuple.vec.kc, 8, 0); } @@ -244,32 +269,29 @@ int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq, return -EINVAL; /* not reached */ } -static int authorize_subscriber(struct gsm_loc_updating_operation *loc, - struct gsm_subscriber *subscriber) +static bool authorize_subscriber(struct gsm_loc_updating_operation *loc, + struct gsm_subscriber *subscriber) { - if (!subscriber) - return 0; + if (!subscriber) { + LOGP(DMM, LOGL_DEBUG, "authorize_subscriber() on NULL subscriber\n"); + return false; + } /* * Do not send accept yet as more information should arrive. Some * phones will not send us the information and we will have to check * what we want to do with that. */ - if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei)) - return 0; - - switch (subscriber->group->net->auth_policy) { - case GSM_AUTH_POLICY_CLOSED: - return subscriber->authorized; - case GSM_AUTH_POLICY_TOKEN: - if (subscriber->authorized) - return subscriber->authorized; - return (subscriber->flags & GSM_SUBSCRIBER_FIRST_CONTACT); - case GSM_AUTH_POLICY_ACCEPT_ALL: - return 1; - default: - return 0; + if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei)) { + LOGP(DMM, LOGL_DEBUG, "authorize_subscriber() failed:" + " still waiting for%s%s of subscriber %s\n", + loc->waiting_for_imsi? " IMSI": "", + loc->waiting_for_imei? " IMEI": "", + subscr_name(subscriber)); + return false; } + + return subscr_authorized(subscriber); } static void release_loc_updating_req(struct gsm_subscriber_connection *conn, int release) @@ -300,7 +322,7 @@ static void allocate_loc_updating_req(struct gsm_subscriber_connection *conn) static int finish_lu(struct gsm_subscriber_connection *conn) { int rc = 0; - int avoid_tmsi = conn->bts->network->avoid_tmsi; + int avoid_tmsi = conn->network->avoid_tmsi; /* We're all good */ if (avoid_tmsi) { @@ -311,7 +333,7 @@ static int finish_lu(struct gsm_subscriber_connection *conn) } rc = gsm0408_loc_upd_acc(conn); - if (conn->bts->network->send_mm_info) { + if (conn->network->send_mm_info) { /* send MM INFO with network name */ rc = gsm48_tx_mm_info(conn); } @@ -319,7 +341,7 @@ static int finish_lu(struct gsm_subscriber_connection *conn) /* 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(conn->subscr, conn->bts, + subscr_update(conn->network, conn->subscr, conn->lac, GSM_SUBSCRIBER_UPDATE_ATTACHED); /* @@ -340,10 +362,6 @@ static int _gsm0408_authorize_sec_cb(unsigned int hooknum, unsigned int event, int rc = 0; switch (event) { - case GSM_SECURITY_AUTH_FAILED: - release_loc_updating_req(conn, 1); - break; - case GSM_SECURITY_ALREADY: LOGP(DMM, LOGL_ERROR, "We don't expect LOCATION " "UPDATING after CM SERVICE REQUEST\n"); @@ -354,22 +372,40 @@ static int _gsm0408_authorize_sec_cb(unsigned int hooknum, unsigned int event, rc = finish_lu(conn); break; + case GSM_SECURITY_AUTH_FAILED: + /* + * gsm48_secure_channel() will pass only + * GSM_SECURITY_NOAVAIL in case of failure. If future + * code should add a GSM_SECURITY_AUTH_FAILED status in + * this code path, letting the Location Update time out + * will do all necessary error messaging and logging, + * see loc_upd_rej_cb(). + */ + LOGP(DMM, LOGL_ERROR, + "Authorization failed for subscriber %s\n", + subscr_name(conn->subscr)); + rc = -1; + break; + default: + LOGP(DMM, LOGL_DEBUG, "invalid authorization event\n"); rc = -EINVAL; }; return rc; } -static int gsm0408_authorize(struct gsm_subscriber_connection *conn, struct msgb *msg) +int gsm0408_authorize(struct gsm_subscriber_connection *conn) { - if (!conn->loc_operation) + if (!conn->loc_operation) { + LOGP(DMM, LOGL_DEBUG, "gsm0408_authorize() failed:" + " no location update operation pending\n"); return 0; + } if (authorize_subscriber(conn->loc_operation, conn->subscr)) - return gsm48_secure_channel(conn, - conn->loc_operation->key_seq, - _gsm0408_authorize_sec_cb, NULL); + return gsm48_secure_channel(conn, conn->loc_operation->key_seq, + _gsm0408_authorize_sec_cb, NULL); return 0; } @@ -384,7 +420,7 @@ void gsm0408_clear_request(struct gsm_subscriber_connection *conn, uint32_t caus * Cancel any outstanding location updating request * operation taking place on the subscriber connection. */ - release_loc_updating_req(conn, 1); + release_loc_updating_req(conn, 0); /* We might need to cancel the paging response or such. */ if (conn->sec_operation && conn->sec_operation->cb) { @@ -408,12 +444,14 @@ void gsm0408_clear_request(struct gsm_subscriber_connection *conn, uint32_t caus * we have a subscriber connection. */ restart: - llist_for_each_entry_safe(trans, temp, &conn->bts->network->trans_list, entry) { + llist_for_each_entry_safe(trans, temp, &conn->network->trans_list, entry) { if (trans->conn == conn) { trans_free(trans); goto restart; } } + + msc_subscr_con_free(conn); } void gsm0408_clear_all_trans(struct gsm_network *net, int protocol) @@ -433,23 +471,24 @@ void gsm0408_clear_all_trans(struct gsm_network *net, int protocol) /* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */ int gsm0408_loc_upd_rej(struct gsm_subscriber_connection *conn, uint8_t cause) { - struct gsm_bts *bts = conn->bts; struct msgb *msg; - osmo_counter_inc(bts->network->stats.loc_upd_resp.reject); + osmo_counter_inc(conn->network->stats.loc_upd_resp.reject); msg = gsm48_create_loc_upd_rej(cause); if (!msg) { LOGP(DMM, LOGL_ERROR, "Failed to create msg for LOCATION UPDATING REJECT.\n"); return -1; } - - msg->lchan = conn->lchan; +#if BEFORE_MSCSPLIT LOGP(DMM, LOGL_INFO, "Subscriber %s: LOCATION UPDATING REJECT " - "LAC=%u BTS=%u\n", conn->subscr ? - subscr_name(conn->subscr) : "unknown", + "LAC=%u BTS=%u\n", subscr_name(conn->subscr), bts->location_area_code, bts->nr); +#else + LOGP(DMM, LOGL_INFO, "Subscriber %s: LOCATION UPDATING REJECT\n", + subscr_name(conn->subscr)); +#endif return gsm48_conn_sendmsg(msg, conn, NULL); } @@ -457,21 +496,18 @@ int gsm0408_loc_upd_rej(struct gsm_subscriber_connection *conn, uint8_t cause) /* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */ static int gsm0408_loc_upd_acc(struct gsm_subscriber_connection *conn) { - struct gsm_bts *bts = conn->bts; struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 LOC UPD ACC"); struct gsm48_hdr *gh; struct gsm48_loc_area_id *lai; uint8_t *mid; - - msg->lchan = conn->lchan; gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); gh->proto_discr = GSM48_PDISC_MM; gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT; lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai)); - gsm48_generate_lai(lai, bts->network->country_code, - bts->network->network_code, bts->location_area_code); + gsm48_generate_lai(lai, conn->network->country_code, + conn->network->network_code, conn->lac); if (conn->subscr->tmsi == GSM_RESERVED_TMSI) { uint8_t mi[10]; @@ -486,7 +522,7 @@ static int gsm0408_loc_upd_acc(struct gsm_subscriber_connection *conn) DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n"); - osmo_counter_inc(bts->network->stats.loc_upd_resp.accept); + osmo_counter_inc(conn->network->stats.loc_upd_resp.accept); return gsm48_conn_sendmsg(msg, conn, NULL); } @@ -497,8 +533,6 @@ static int mm_tx_identity_req(struct gsm_subscriber_connection *conn, uint8_t id struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ID REQ"); struct gsm48_hdr *gh; - msg->lchan = conn->lchan; - gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1); gh->proto_discr = GSM48_PDISC_MM; gh->msg_type = GSM48_MT_MM_ID_REQ; @@ -512,9 +546,7 @@ static int mm_tx_identity_req(struct gsm_subscriber_connection *conn, uint8_t id static int mm_rx_id_resp(struct gsm_subscriber_connection *conn, struct msgb *msg) { struct gsm48_hdr *gh = msgb_l3(msg); - struct gsm_lchan *lchan = msg->lchan; - struct gsm_bts *bts = lchan->ts->trx->bts; - struct gsm_network *net = bts->network; + struct gsm_network *net = conn->network; uint8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK; char mi_string[GSM48_MI_SIZE]; @@ -535,7 +567,7 @@ static int mm_rx_id_resp(struct gsm_subscriber_connection *conn, struct msgb *ms net->subscr_group, mi_string); } if (!conn->subscr && conn->loc_operation) { - gsm0408_loc_upd_rej(conn, bts->network->reject_cause); + gsm0408_loc_upd_rej(conn, net->reject_cause); release_loc_updating_req(conn, 1); return 0; } @@ -555,18 +587,16 @@ static int mm_rx_id_resp(struct gsm_subscriber_connection *conn, struct msgb *ms } /* Check if we can let the mobile station enter */ - return gsm0408_authorize(conn, msg); + return gsm0408_authorize(conn); } static void loc_upd_rej_cb(void *data) { struct gsm_subscriber_connection *conn = data; - struct gsm_lchan *lchan = conn->lchan; - struct gsm_bts *bts = lchan->ts->trx->bts; LOGP(DMM, LOGL_DEBUG, "Location Updating Request procedure timedout.\n"); - gsm0408_loc_upd_rej(conn, bts->network->reject_cause); + gsm0408_loc_upd_rej(conn, conn->network->reject_cause); release_loc_updating_req(conn, 1); } @@ -590,7 +620,6 @@ static int mm_rx_loc_upd_req(struct gsm_subscriber_connection *conn, struct msgb struct gsm48_hdr *gh = msgb_l3(msg); struct gsm48_loc_upd_req *lu; struct gsm_subscriber *subscr = NULL; - struct gsm_bts *bts = conn->bts; uint8_t mi_type; char mi_string[GSM48_MI_SIZE]; @@ -607,13 +636,13 @@ static int mm_rx_loc_upd_req(struct gsm_subscriber_connection *conn, struct msgb switch (lu->type) { case GSM48_LUPD_NORMAL: - osmo_counter_inc(bts->network->stats.loc_upd_type.normal); + osmo_counter_inc(conn->network->stats.loc_upd_type.normal); break; case GSM48_LUPD_IMSI_ATT: - osmo_counter_inc(bts->network->stats.loc_upd_type.attach); + osmo_counter_inc(conn->network->stats.loc_upd_type.attach); break; case GSM48_LUPD_PERIODIC: - osmo_counter_inc(bts->network->stats.loc_upd_type.periodic); + osmo_counter_inc(conn->network->stats.loc_upd_type.periodic); break; } @@ -640,13 +669,13 @@ static int mm_rx_loc_upd_req(struct gsm_subscriber_connection *conn, struct msgb conn->loc_operation->waiting_for_imei = 1; /* look up subscriber based on IMSI, create if not found */ - subscr = subscr_get_by_imsi(bts->network->subscr_group, mi_string); - if (!subscr && bts->network->create_subscriber) { + subscr = subscr_get_by_imsi(conn->network->subscr_group, mi_string); + if (!subscr && conn->network->create_subscriber) { subscr = subscr_create_subscriber( - bts->network->subscr_group, mi_string); + conn->network->subscr_group, mi_string); } if (!subscr) { - gsm0408_loc_upd_rej(conn, bts->network->reject_cause); + gsm0408_loc_upd_rej(conn, conn->network->reject_cause); release_loc_updating_req(conn, 0); return 0; } @@ -654,7 +683,7 @@ static int mm_rx_loc_upd_req(struct gsm_subscriber_connection *conn, struct msgb case GSM_MI_TYPE_TMSI: DEBUGPC(DMM, "\n"); /* look up the subscriber based on TMSI, request IMSI if it fails */ - subscr = subscr_get_by_tmsi(bts->network->subscr_group, + subscr = subscr_get_by_tmsi(conn->network->subscr_group, tmsi_from_string(mi_string)); if (!subscr) { /* send IDENTITY REQUEST message to get IMSI */ @@ -689,7 +718,7 @@ static int mm_rx_loc_upd_req(struct gsm_subscriber_connection *conn, struct msgb /* check if we can let the subscriber into our network immediately * or if we need to wait for identity responses. */ - return gsm0408_authorize(conn, msg); + return gsm0408_authorize(conn); } /* Turn int into semi-octet representation: 98 => 0x89 */ @@ -709,8 +738,7 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) { struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 MM INF"); struct gsm48_hdr *gh; - struct gsm_network *net = conn->bts->network; - struct gsm_bts *bts = conn->bts; + struct gsm_network *net = conn->network; uint8_t *ptr8; int name_len, name_pad; @@ -720,8 +748,6 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) int tzunits; int dst = 0; - msg->lchan = conn->lchan; - gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); gh->proto_discr = GSM48_PDISC_MM; gh->msg_type = GSM48_MT_MM_INFO; @@ -798,23 +824,24 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) ptr8[5] = bcdify(gmt_time->tm_min); ptr8[6] = bcdify(gmt_time->tm_sec); - if (bts->tz.override) { + // MSCSPLIT bts->tz move to BSC? + if (net->tz.override) { /* Convert tz.hr and tz.mn to units */ - if (bts->tz.hr < 0) { - tzunits = ((bts->tz.hr/-1)*4); - tzunits = tzunits + (bts->tz.mn/15); + if (net->tz.hr < 0) { + tzunits = ((net->tz.hr/-1)*4); + tzunits = tzunits + (net->tz.mn/15); ptr8[7] = bcdify(tzunits); /* Set negative time */ ptr8[7] |= 0x08; } else { - tzunits = bts->tz.hr*4; - tzunits = tzunits + (bts->tz.mn/15); + tzunits = net->tz.hr*4; + tzunits = tzunits + (net->tz.mn/15); ptr8[7] = bcdify(tzunits); } /* Convert DST value */ - if (bts->tz.dst >= 0 && bts->tz.dst <= 2) - dst = bts->tz.dst; + if (net->tz.dst >= 0 && net->tz.dst <= 2) + dst = net->tz.dst; } else { /* Need to get GSM offset and convert into 15 min units */ @@ -861,7 +888,6 @@ int gsm48_tx_mm_auth_req(struct gsm_subscriber_connection *conn, uint8_t *rand, DEBUGP(DMM, "-> AUTH REQ (rand = %s)\n", osmo_hexdump(rand, 16)); - msg->lchan = conn->lchan; gh->proto_discr = GSM48_PDISC_MM; gh->msg_type = GSM48_MT_MM_AUTH_REQ; @@ -891,7 +917,7 @@ static void implit_attach(struct gsm_subscriber_connection *conn) if (conn->subscr->lac != GSM_LAC_RESERVED_DETACHED) return; - subscr_update(conn->subscr, conn->bts, + subscr_update(conn->network, conn->subscr, conn->lac, GSM_SUBSCRIBER_UPDATE_ATTACHED); } @@ -937,14 +963,14 @@ static int _gsm48_rx_mm_serv_req_sec_cb( * b) Try to parse the TMSI. If we do not have one reject * c) Check that we know the subscriber with the TMSI otherwise reject * with a HLR cause - * d) Set the subscriber on the gsm_lchan and accept + * d) Set the subscriber on the conn and accept */ static int gsm48_rx_mm_serv_req(struct gsm_subscriber_connection *conn, struct msgb *msg) { uint8_t mi_type; char mi_string[GSM48_MI_SIZE]; - struct gsm_bts *bts = conn->bts; + struct gsm_network *network = conn->network; struct gsm_subscriber *subscr; struct gsm48_hdr *gh = msgb_l3(msg); struct gsm48_service_request *req = @@ -975,13 +1001,13 @@ static int gsm48_rx_mm_serv_req(struct gsm_subscriber_connection *conn, struct m DEBUGPC(DMM, "serv_type=0x%02x MI(%s)=%s\n", req->cm_service_type, gsm48_mi_type_name(mi_type), mi_string); - subscr = subscr_get_by_imsi(bts->network->subscr_group, + subscr = subscr_get_by_imsi(network->subscr_group, mi_string); } else if (mi_type == GSM_MI_TYPE_TMSI) { DEBUGPC(DMM, "serv_type=0x%02x MI(%s)=%s\n", req->cm_service_type, gsm48_mi_type_name(mi_type), mi_string); - subscr = subscr_get_by_tmsi(bts->network->subscr_group, + subscr = subscr_get_by_tmsi(network->subscr_group, tmsi_from_string(mi_string)); } else { DEBUGPC(DMM, "mi_type is not expected: %d\n", mi_type); @@ -991,8 +1017,11 @@ static int gsm48_rx_mm_serv_req(struct gsm_subscriber_connection *conn, struct m osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_IDENTITY, (classmark2 + classmark2_len)); +#if BEFORE_MSCSPLIT + /* see mail on openbsc@ 9 Feb 2016 22:30:15 +0100 */ if (is_siemens_bts(bts)) send_siemens_mrpci(msg->lchan, classmark2-1); +#endif /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */ @@ -1003,7 +1032,7 @@ static int gsm48_rx_mm_serv_req(struct gsm_subscriber_connection *conn, struct m if (!conn->subscr) conn->subscr = subscr; else if (conn->subscr == subscr) - subscr_put(subscr); /* lchan already has a ref, don't need another one */ + subscr_put(subscr); /* conn already has a ref, don't need another one */ else { DEBUGP(DMM, "<- CM Channel already owned by someone else?\n"); subscr_put(subscr); @@ -1022,7 +1051,7 @@ static int gsm48_rx_mm_serv_req(struct gsm_subscriber_connection *conn, struct m static int gsm48_rx_mm_imsi_detach_ind(struct gsm_subscriber_connection *conn, struct msgb *msg) { - struct gsm_bts *bts = conn->bts; + struct gsm_network *network = conn->network; struct gsm48_hdr *gh = msgb_l3(msg); struct gsm48_imsi_detach_ind *idi = (struct gsm48_imsi_detach_ind *) gh->data; @@ -1034,17 +1063,17 @@ static int gsm48_rx_mm_imsi_detach_ind(struct gsm_subscriber_connection *conn, s DEBUGP(DMM, "IMSI DETACH INDICATION: MI(%s)=%s", gsm48_mi_type_name(mi_type), mi_string); - osmo_counter_inc(bts->network->stats.loc_upd_type.detach); + osmo_counter_inc(network->stats.loc_upd_type.detach); switch (mi_type) { case GSM_MI_TYPE_TMSI: DEBUGPC(DMM, "\n"); - subscr = subscr_get_by_tmsi(bts->network->subscr_group, + subscr = subscr_get_by_tmsi(network->subscr_group, tmsi_from_string(mi_string)); break; case GSM_MI_TYPE_IMSI: DEBUGPC(DMM, "\n"); - subscr = subscr_get_by_imsi(bts->network->subscr_group, + subscr = subscr_get_by_imsi(network->subscr_group, mi_string); break; case GSM_MI_TYPE_IMEI: @@ -1058,7 +1087,7 @@ static int gsm48_rx_mm_imsi_detach_ind(struct gsm_subscriber_connection *conn, s } if (subscr) { - subscr_update(subscr, bts, + subscr_update(network, subscr, conn->lac, GSM_SUBSCRIBER_UPDATE_DETACHED); DEBUGP(DMM, "Subscriber: %s\n", subscr_name(subscr)); @@ -1090,7 +1119,8 @@ static int gsm48_rx_mm_auth_resp(struct gsm_subscriber_connection *conn, struct { struct gsm48_hdr *gh = msgb_l3(msg); struct gsm48_auth_resp *ar = (struct gsm48_auth_resp*) gh->data; - struct gsm_network *net = conn->bts->network; + struct gsm_network *net = conn->network; + gsm_cbfn *cb; DEBUGP(DMM, "MM AUTHENTICATION RESPONSE (sres = %s): ", osmo_hexdump(ar->sres, 4)); @@ -1101,11 +1131,11 @@ static int gsm48_rx_mm_auth_resp(struct gsm_subscriber_connection *conn, struct return -EIO; } + cb = conn->sec_operation->cb; + /* Validate SRES */ if (memcmp(conn->sec_operation->atuple.vec.sres, ar->sres,4)) { int rc; - gsm_cbfn *cb = conn->sec_operation->cb; - DEBUGPC(DMM, "Invalid (expected %s)\n", osmo_hexdump(conn->sec_operation->atuple.vec.sres, 4)); @@ -1120,9 +1150,34 @@ static int gsm48_rx_mm_auth_resp(struct gsm_subscriber_connection *conn, struct DEBUGPC(DMM, "OK\n"); - /* Start ciphering */ - return gsm0808_cipher_mode(conn, net->a5_encryption, - conn->sec_operation->atuple.vec.kc, 8, 0); + /* TODO separate enable flags and/or A5 algos for auth and encryption */ + if (net->a5_encryption) + /* Start ciphering */ + /* TODO gsm0808_cipher_mode() is still a dummy, and no code + * to receive a Ciphering Mode Complete exists in the MSC. + * As soon as such a receiver exists, it must call + * iu_tx_sec_mode_cmd() as below. */ + return gsm0808_cipher_mode(conn, net->a5_encryption, + conn->sec_operation->atuple.vec.kc, 8, 0); + + if (conn->via_iface == IFACE_IU + && !conn->iu.integrity_protection) { + LOGP(DIUCS, LOGL_DEBUG, + "Requesting integrity protection for %s\n", + subscr_name(conn->subscr)); + + /* send Security Mode Command (IK) to start integrity + * protection */ + return iu_tx_sec_mode_cmd(conn->iu.ue_ctx, + &conn->sec_operation->atuple, 0, 1); + } + + /* Only authentication requested, and we're done. */ + if (cb) + cb(GSM_HOOK_RR_SECURITY, GSM_SECURITY_SUCCEEDED, NULL, + conn, conn->sec_operation->cb_data); + release_security_operation(conn); + return 0; } /* Receive a GSM 04.08 Mobility Management (MM) message */ @@ -1147,9 +1202,7 @@ static int gsm0408_rcv_mm(struct gsm_subscriber_connection *conn, struct msgb *m break; case GSM48_MT_MM_TMSI_REALL_COMPL: DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n", - conn->subscr ? - subscr_name(conn->subscr) : - "unknown subscriber"); + subscr_name(conn->subscr)); release_loc_updating_req(conn, 1); break; case GSM48_MT_MM_IMSI_DETACH_IND: @@ -1170,17 +1223,37 @@ static int gsm0408_rcv_mm(struct gsm_subscriber_connection *conn, struct msgb *m return rc; } +static int handle_paging_resp(struct msgb *msg, + struct gsm_subscriber_connection *conn, + struct gsm_subscriber *subscr) +{ + if (!conn->subscr) { + conn->subscr = subscr; + } else if (conn->subscr != subscr) { + LOGP(DPAG, LOGL_ERROR, + "Connection already owned by another subscriber?\n"); + subscr_put(subscr); + return -EINVAL; + } else { + DEBUGP(DPAG, "Connection already owned by the subscriber\n"); + subscr_put(subscr); + subscr = conn->subscr; + } + + osmo_counter_inc(conn->network->stats.paging.completed); + + return subscr_rx_paging_response(msg, conn); +} + /* Receive a PAGING RESPONSE message from the MS */ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct msgb *msg) { - struct gsm_bts *bts = conn->bts; struct gsm48_hdr *gh = msgb_l3(msg); struct gsm48_pag_resp *resp; uint8_t *classmark2_lv = gh->data + 1; uint8_t mi_type; char mi_string[GSM48_MI_SIZE]; struct gsm_subscriber *subscr = NULL; - int rc = 0; resp = (struct gsm48_pag_resp *) &gh->data[0]; gsm48_paging_extract_mi(resp, msgb_l3len(msg) - sizeof(*gh), @@ -1190,11 +1263,11 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m switch (mi_type) { case GSM_MI_TYPE_TMSI: - subscr = subscr_get_by_tmsi(bts->network->subscr_group, + subscr = subscr_get_by_tmsi(conn->network->subscr_group, tmsi_from_string(mi_string)); break; case GSM_MI_TYPE_IMSI: - subscr = subscr_get_by_imsi(bts->network->subscr_group, + subscr = subscr_get_by_imsi(conn->network->subscr_group, mi_string); break; } @@ -1215,8 +1288,11 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m /* We received a paging */ conn->expire_timer_stopped = 1; - rc = gsm48_handle_paging_resp(conn, msg, subscr); - return rc; +#if BEFORE_MSCSPLIT + return gsm48_handle_paging_resp(conn, msg, subscr); +#else + return handle_paging_resp(msg, conn, subscr); +#endif } static int gsm48_rx_rr_app_info(struct gsm_subscriber_connection *conn, struct msgb *msg) @@ -1264,11 +1340,9 @@ int gsm48_send_rr_app_info(struct gsm_subscriber_connection *conn, uint8_t apdu_ struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 APP INF"); struct gsm48_hdr *gh; - msg->lchan = conn->lchan; - DEBUGP(DRR, "TX APPLICATION INFO id=0x%02x, len=%u\n", apdu_id, apdu_len); - + gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 2 + apdu_len); gh->proto_discr = GSM48_PDISC_RR; gh->msg_type = GSM48_MT_RR_APP_INFO; @@ -1323,8 +1397,6 @@ static int gsm48_tx_simple(struct gsm_subscriber_connection *conn, struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 TX SIMPLE"); struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); - msg->lchan = conn->lchan; - gh->proto_discr = pdisc; gh->msg_type = msg_type; @@ -1346,6 +1418,7 @@ static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans, struct msgb *msg; unsigned char *data; +#if BEFORE_MSCSPLIT if (trans) if (trans->conn && trans->conn->lchan) DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) " @@ -1363,6 +1436,7 @@ static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans, else DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) " "Sending '%s' to MNCC.\n", get_mncc_name(msg_type)); +#endif mncc->msg_type = msg_type; @@ -1406,8 +1480,10 @@ void _gsm48_cc_trans_free(struct gsm_trans *trans) } if (trans->cc.state != GSM_CSTATE_NULL) new_cc_state(trans, GSM_CSTATE_NULL); +#if BEFORE_MSCSPLIT if (trans->conn) trau_mux_unmap(&trans->conn->lchan->ts->e1_link, trans->callref); +#endif } static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg); @@ -1421,12 +1497,11 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, OSMO_ASSERT(!transt->conn); - /* check all tranactions (without lchan) for subscriber */ switch (event) { case GSM_PAGING_SUCCEEDED: DEBUGP(DCC, "Paging subscr %s succeeded!\n", transt->subscr->extension); OSMO_ASSERT(conn); - /* Assign lchan */ + /* Assign conn */ transt->conn = conn; /* send SETUP request to called party */ gsm48_cc_tx_setup(transt, &transt->cc.msg); @@ -1455,6 +1530,7 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable); +#if BEFORE_MSCSPLIT /* handle audio path for handover */ static int switch_for_handover(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan) @@ -1522,77 +1598,6 @@ static void maybe_switch_for_handover(struct gsm_lchan *lchan) switch_for_handover(old_lchan, lchan); } -/* some other part of the code sends us a signal */ -static int handle_abisip_signal(unsigned int subsys, unsigned int signal, - void *handler_data, void *signal_data) -{ - struct gsm_lchan *lchan = signal_data; - int rc; - struct gsm_network *net; - struct gsm_trans *trans; - - if (subsys != SS_ABISIP) - return 0; - - /* RTP bridge handling */ - if (lchan->conn && lchan->conn->mncc_rtp_bridge) - return tch_rtp_signal(lchan, signal); - - /* in case we use direct BTS-to-BTS RTP */ - if (ipacc_rtp_direct) - return 0; - - switch (signal) { - case S_ABISIP_CRCX_ACK: - /* in case we don't use direct BTS-to-BTS RTP */ - /* the BTS has successfully bound a TCH to a local ip/port, - * which means we can connect our UDP socket to it */ - if (lchan->abis_ip.rtp_socket) { - rtp_socket_free(lchan->abis_ip.rtp_socket); - lchan->abis_ip.rtp_socket = NULL; - } - - lchan->abis_ip.rtp_socket = rtp_socket_create(); - if (!lchan->abis_ip.rtp_socket) - return -EIO; - - rc = rtp_socket_connect(lchan->abis_ip.rtp_socket, - lchan->abis_ip.bound_ip, - lchan->abis_ip.bound_port); - if (rc < 0) - return -EIO; - - /* check if any transactions on this lchan still have - * a tch_recv_mncc request pending */ - net = lchan->ts->trx->bts->network; - llist_for_each_entry(trans, &net->trans_list, entry) { - 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); - } - } - - /* - * TODO: this appears to be too early? Why not until after - * the handover detect or the handover complete? - * - * Do we have a handover pending for this new lchan? In that - * case re-route the audio from the old channel to the new one. - */ - maybe_switch_for_handover(lchan); - break; - case S_ABISIP_DLCX_IND: - /* the BTS tells us a RTP stream has been disconnected */ - if (lchan->abis_ip.rtp_socket) { - rtp_socket_free(lchan->abis_ip.rtp_socket); - lchan->abis_ip.rtp_socket = NULL; - } - - break; - } - - return 0; -} /* map two ipaccess RTP streams onto each other */ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) @@ -1681,6 +1686,7 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) return 0; } +#endif /* bridge channels of two transactions */ static int tch_bridge(struct gsm_network *net, struct gsm_mncc_bridge *bridge) @@ -1697,13 +1703,19 @@ static int tch_bridge(struct gsm_network *net, struct gsm_mncc_bridge *bridge) /* Which subscriber do we want to track trans1 or trans2? */ log_set_context(BSC_CTX_SUBSCR, trans1->subscr); +#if BEFORE_MSCSPLIT /* through-connect channel */ return tch_map(trans1->conn->lchan, trans2->conn->lchan); +#else + /* not implemented yet! */ + return -1; +#endif } /* enable receive of channels to MNCC upqueue */ static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable) { +#if BEFORE_MSCSPLIT struct gsm_trans *trans; struct gsm_lchan *lchan; struct gsm_bts *bts; @@ -1772,6 +1784,10 @@ static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable) } return 0; +#else + /* not implemented yet! */ + return -1; +#endif } static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg) @@ -1912,7 +1928,11 @@ static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg) memset(&setup, 0, sizeof(struct gsm_mncc)); setup.callref = trans->callref; +#if BEFORE_MSCSPLIT setup.lchan_type = trans->conn->lchan->type; +#else + setup.lchan_type = GSM_LCHAN_NONE; +#endif tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0); /* emergency setup is identified by msg_type */ if (msg_type == GSM48_MT_CC_EMERG_SETUP) @@ -1930,7 +1950,6 @@ static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg) setup.fields |= MNCC_F_BEARER_CAP; gsm48_decode_bearer_cap(&setup.bearer_cap, TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - apply_codec_restrictions(trans->conn->bts, &setup.bearer_cap); } /* facility */ if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { @@ -2070,7 +2089,11 @@ static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg) memset(&call_conf, 0, sizeof(struct gsm_mncc)); call_conf.callref = trans->callref; +#if BEFORE_MSCSPLIT call_conf.lchan_type = trans->conn->lchan->type; +#else + call_conf.lchan_type = GSM_LCHAN_NONE; +#endif tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0); #if 0 /* repeat */ @@ -2084,7 +2107,6 @@ static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg) call_conf.fields |= MNCC_F_BEARER_CAP; gsm48_decode_bearer_cap(&call_conf.bearer_cap, TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - apply_codec_restrictions(trans->conn->bts, &call_conf.bearer_cap); } /* cause */ if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { @@ -2777,7 +2799,6 @@ static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg) modify.fields |= MNCC_F_BEARER_CAP; gsm48_decode_bearer_cap(&modify.bearer_cap, TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - apply_codec_restrictions(trans->conn->bts, &modify.bearer_cap); } new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY); @@ -2820,7 +2841,6 @@ static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg modify.fields |= MNCC_F_BEARER_CAP; gsm48_decode_bearer_cap(&modify.bearer_cap, TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - apply_codec_restrictions(trans->conn->bts, &modify.bearer_cap); } new_cc_state(trans, GSM_CSTATE_ACTIVE); @@ -2861,7 +2881,6 @@ static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg) modify.fields |= GSM48_IE_BEARER_CAP; gsm48_decode_bearer_cap(&modify.bearer_cap, TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - apply_codec_restrictions(trans->conn->bts, &modify.bearer_cap); } /* cause */ if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { @@ -2966,6 +2985,7 @@ static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg) static int _gsm48_lchan_modify(struct gsm_trans *trans, void *arg) { +#if BEFORE_MSCSPLIT struct gsm_mncc *mode = arg; struct gsm_lchan *lchan = trans->conn->lchan; @@ -2981,8 +3001,14 @@ static int _gsm48_lchan_modify(struct gsm_trans *trans, void *arg) return gsm0808_assign_req(trans->conn, mode->lchan_mode, trans->conn->lchan->type != GSM_LCHAN_TCH_H); +#else + /* not implemented yet! */ + return -1; +#endif + } +#if BEFORE_MSCSPLIT static void mncc_recv_rtp(struct gsm_network *net, uint32_t callref, int cmd, uint32_t addr, uint16_t port, uint32_t payload_type, uint32_t payload_msg_type) @@ -3039,9 +3065,11 @@ static void mncc_recv_rtp_err(struct gsm_network *net, uint32_t callref, int cmd { return mncc_recv_rtp(net, callref, cmd, 0, 0, 0, 0); } +#endif static int tch_rtp_create(struct gsm_network *net, uint32_t callref) { +#if BEFORE_MSCSPLIT struct gsm_bts *bts; struct gsm_lchan *lchan; struct gsm_trans *trans; @@ -3095,10 +3123,15 @@ static int tch_rtp_create(struct gsm_network *net, uint32_t callref) mncc_recv_rtp_sock(trans->net, trans, MNCC_RTP_CREATE); return 0; +#else + /* not implemented yet! */ + return -1; +#endif } static int tch_rtp_connect(struct gsm_network *net, void *arg) { +#if BEFORE_MSCSPLIT struct gsm_lchan *lchan; struct gsm_trans *trans; struct gsm_mncc_rtp *rtp = arg; @@ -3136,8 +3169,13 @@ static int tch_rtp_connect(struct gsm_network *net, void *arg) */ trans->conn->mncc_rtp_connect_pending = 1; return rsl_ipacc_mdcx(lchan, rtp->ip, rtp->port, 0); +#else + /* not implemented yet! */ + return -1; +#endif } +#if BEFORE_MSCSPLIT static int tch_rtp_signal(struct gsm_lchan *lchan, int signal) { struct gsm_network *net; @@ -3185,6 +3223,7 @@ static int tch_rtp_signal(struct gsm_lchan *lchan, int signal) return 0; } +#endif static struct downstate { @@ -3254,7 +3293,6 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg) int i, rc = 0; struct gsm_trans *trans = NULL, *transt; struct gsm_subscriber_connection *conn = NULL; - struct gsm_bts *bts = NULL; struct gsm_mncc *data = arg, rel; DEBUGP(DMNCC, "receive message %s\n", get_mncc_name(msg_type)); @@ -3292,6 +3330,7 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg) LOGP(DMNCC, LOGL_NOTICE, "TCH frame for trans without conn\n"); return 0; } +#if BEFORE_MSCSPLIT if (!trans->conn->lchan) { LOGP(DMNCC, LOGL_NOTICE, "TCH frame for trans without lchan\n"); return 0; @@ -3321,6 +3360,10 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg) LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type); } return -EINVAL; +#else + /* not implemented yet! */ + return -1; +#endif } memset(&rel, 0, sizeof(struct gsm_mncc)); @@ -3397,14 +3440,14 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg) GSM48_CC_CAUSE_RESOURCE_UNAVAIL); return -ENOMEM; } - /* Find lchan */ + /* Find conn */ conn = connection_for_subscr(subscr); - /* If subscriber has no lchan */ + /* If subscriber has no conn */ if (!conn) { /* find transaction with this subscriber already paging */ llist_for_each_entry(transt, &net->trans_list, entry) { - /* Transaction of our lchan? */ + /* Transaction of our conn? */ if (transt == trans || transt->subscr != subscr) continue; @@ -3418,12 +3461,12 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg) trans_free(trans); return 0; } - /* store setup informations until paging was successfull */ + /* store setup information until paging succeeds */ memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc)); /* Request a channel */ - trans->paging_request = subscr_request_channel(subscr, - RSL_CHANNEED_TCH_F, setup_trig_pag_evt, + trans->paging_request = subscr_request_conn(subscr, + setup_trig_pag_evt, trans); if (!trans->paging_request) { LOGP(DCC, LOGL_ERROR, "Failed to allocate paging token.\n"); @@ -3434,7 +3477,7 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg) subscr_put(subscr); return 0; } - /* Assign lchan */ + /* Assign conn */ trans->conn = conn; subscr_put(subscr); } else { @@ -3447,7 +3490,7 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg) /* if paging did not respond yet */ if (!conn) { - DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) " + DEBUGP(DCC, "(sub %s) " "Received '%s' from MNCC in paging state\n", (trans->subscr)?(trans->subscr->extension):"-", get_mncc_name(msg_type)); @@ -3462,9 +3505,8 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg) return rc; } - DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) " + DEBUGP(DCC, "(ti %02x sub %s) " "Received '%s' from MNCC in state %d (%s)\n", - conn->bts->nr, conn->lchan->ts->trx->nr, conn->lchan->ts->nr, trans->transaction_id, (trans->conn->subscr)?(trans->conn->subscr->extension):"-", get_mncc_name(msg_type), trans->cc.state, @@ -3556,19 +3598,21 @@ static int gsm0408_rcv_cc(struct gsm_subscriber_connection *conn, struct msgb *m /* Find transaction */ trans = trans_find_by_id(conn, GSM48_PDISC_CC, transaction_id); +#if BEFORE_MSCSPLIT DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) " "Received '%s' from MS in state %d (%s)\n", conn->bts->nr, conn->lchan->ts->trx->nr, conn->lchan->ts->nr, 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)); +#endif /* Create transaction */ if (!trans) { DEBUGP(DCC, "Unknown transaction ID %x, " "creating new trans.\n", transaction_id); /* Create transaction */ - trans = trans_alloc(conn->bts->network, conn->subscr, + trans = trans_alloc(conn->network, conn->subscr, GSM48_PDISC_CC, transaction_id, new_callref++); if (!trans) { @@ -3630,6 +3674,33 @@ int gsm0408_new_conn(struct gsm_subscriber_connection *conn) return 0; } +struct gsm_subscriber_connection *msc_subscr_con_allocate(struct gsm_network *network) +{ + struct gsm_subscriber_connection *conn; + + conn = talloc_zero(network, struct gsm_subscriber_connection); + if (!conn) + return NULL; + + conn->network = network; + llist_add_tail(&conn->entry, &network->subscr_conns); + return conn; +} + +void msc_subscr_con_free(struct gsm_subscriber_connection *conn) +{ + if (!conn) + return; + + if (conn->subscr) { + subscr_put(conn->subscr); + conn->subscr = NULL; + } + + llist_del(&conn->entry); + talloc_free(conn); +} + /* here we get data from the BSC level... */ int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg) { @@ -3637,6 +3708,9 @@ int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg) uint8_t pdisc = gsm48_hdr_pdisc(gh); int rc = 0; + OSMO_ASSERT(conn); + OSMO_ASSERT(msg); + LOGP(DRLL, LOGL_DEBUG, "Dispatching 04.08 message, pdisc=%d\n", pdisc); if (silent_call_reroute(conn, msg)) return silent_call_rx(conn, msg); @@ -3660,6 +3734,7 @@ int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg) case GSM48_PDISC_SM_GPRS: LOGP(DRLL, LOGL_NOTICE, "Unimplemented " "GSM 04.08 discriminator 0x%02x\n", pdisc); + rc = -1; break; case GSM48_PDISC_NC_SS: release_anchor(conn); @@ -3668,17 +3743,10 @@ int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg) default: LOGP(DRLL, LOGL_NOTICE, "Unknown " "GSM 04.08 discriminator 0x%02x\n", pdisc); + rc = -1; break; } return rc; } -/* - * This will be ran by the linker when loading the DSO. We use it to - * do system initialization, e.g. registration of signal handlers. - */ -static __attribute__((constructor)) void on_dso_load_0408(void) -{ - osmo_signal_register_handler(SS_ABISIP, handle_abisip_signal, NULL); -} |