From 8db12e42638483adb2feaf42cfd163dfe1fa973c Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 18 Apr 2016 23:11:18 +0200 Subject: Add extra debug output with channel mode and type This provides helpful information for debugging internal MNCC handler. --- openbsc/src/libmsc/gsm_04_08.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'openbsc/src/libmsc/gsm_04_08.c') diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 1524ec44f..7b78d48e2 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -1598,11 +1599,15 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) { struct gsm_bts *bts = lchan->ts->trx->bts; struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts; + enum gsm_chan_t lt = lchan->type, rt = remote_lchan->type; int rc; - DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n", - bts->nr, lchan->ts->trx->nr, lchan->ts->nr, - remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr); + DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u,%s) and " + "(bts=%u,trx=%u,ts=%u,%s)\n", + bts->nr, lchan->ts->trx->nr, lchan->ts->nr, + get_value_string(gsm_chan_t_names, lt), + remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr, + get_value_string(gsm_chan_t_names, rt)); if (bts->type != remote_bts->type) { LOGP(DCC, LOGL_ERROR, "Cannot switch calls between different BTS types yet\n"); @@ -2999,6 +3004,7 @@ static int tch_rtp_create(struct gsm_network *net, uint32_t callref) struct gsm_bts *bts; struct gsm_lchan *lchan; struct gsm_trans *trans; + enum gsm48_chan_mode m; /* Find callref */ trans = trans_find_by_callref(net, callref); @@ -3038,8 +3044,11 @@ static int tch_rtp_create(struct gsm_network *net, uint32_t callref) */ if (lchan->tch_mode == GSM48_CMODE_SIGN) { trans->conn->mncc_rtp_create_pending = 1; - return gsm0808_assign_req(trans->conn, - mncc_codec_for_mode(lchan->type), + m = mncc_codec_for_mode(lchan->type); + LOGP(DMNCC, LOGL_DEBUG, "RTP create: codec=%s, chan_type=%s\n", + get_value_string(gsm48_chan_mode_names, m), + get_value_string(gsm_chan_t_names, lchan->type)); + return gsm0808_assign_req(trans->conn, m, lchan->type != GSM_LCHAN_TCH_H); } @@ -3068,6 +3077,10 @@ static int tch_rtp_connect(struct gsm_network *net, void *arg) } lchan = trans->conn->lchan; + LOGP(DMNCC, LOGL_DEBUG, "RTP connect: codec=%s, chan_type=%s\n", + get_value_string(gsm48_chan_mode_names, + mncc_codec_for_mode(lchan->type)), + get_value_string(gsm_chan_t_names, lchan->type)); /* TODO: Check if payload_msg_type is compatible with what we have */ if (rtp->payload_type != lchan->abis_ip.rtp_payload) { -- cgit v1.2.3 From 3ffce19cb4929c907460753d302e4720558cc6d2 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 25 Apr 2016 15:22:00 +0200 Subject: Disconnect calls with incompatible channel types / modes In case both TCH/H and TCH/F or different codecs are configured and internal MNCC handler is used we might end up in a situation where call legs with incompatible channel types or codecs would be connected resulting in a broken audio. Disconnect such calls with appropriate error message. Fixes: OS#1663 --- openbsc/src/libmsc/gsm_04_08.c | 46 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) (limited to 'openbsc/src/libmsc/gsm_04_08.c') diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 7b78d48e2..05cb88679 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -1600,6 +1600,7 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) struct gsm_bts *bts = lchan->ts->trx->bts; struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts; enum gsm_chan_t lt = lchan->type, rt = remote_lchan->type; + enum gsm48_chan_mode lm = lchan->tch_mode, rm = remote_lchan->tch_mode; int rc; DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u,%s) and " @@ -1614,6 +1615,22 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) return -EINVAL; } + if (lt != rt) { + LOGP(DCC, LOGL_ERROR, "Cannot patch through call with different" + " channel types: local = %s, remote = %s\n", + get_value_string(gsm_chan_t_names, lt), + get_value_string(gsm_chan_t_names, rt)); + return -EBADSLT; + } + + if (lm != rm) { + LOGP(DCC, LOGL_ERROR, "Cannot patch through call with different" + " channel modes: local = %s, remote = %s\n", + get_value_string(gsm48_chan_mode_names, lm), + get_value_string(gsm48_chan_mode_names, rm)); + return -EMEDIUMTYPE; + } + // todo: map between different bts types switch (bts->type) { case GSM_BTS_TYPE_NANOBTS: @@ -1851,6 +1868,30 @@ static void gsm48_cc_timeout(void *arg) } +/* disconnect both calls from the bridge */ +static inline void disconnect_bridge(struct gsm_network *net, + struct gsm_mncc_bridge *bridge, int err) +{ + struct gsm_trans *trans0 = trans_find_by_callref(net, bridge->callref[0]); + struct gsm_trans *trans1 = trans_find_by_callref(net, bridge->callref[1]); + struct gsm_mncc mx_rel; + if (!trans0 || !trans1) + return; + + DEBUGP(DCC, "Failed to bridge TCH for calls %x <-> %x :: %s \n", + trans0->callref, trans1->callref, strerror(err)); + + memset(&mx_rel, 0, sizeof(struct gsm_mncc)); + mncc_set_cause(&mx_rel, GSM48_CAUSE_LOC_INN_NET, + GSM48_CC_CAUSE_CHAN_UNACCEPT); + + mx_rel.callref = trans0->callref; + gsm48_cc_tx_disconnect(trans0, &mx_rel); + + mx_rel.callref = trans1->callref; + gsm48_cc_tx_disconnect(trans1, &mx_rel); +} + static void gsm48_start_cc_timer(struct gsm_trans *trans, int current, int sec, int micro) { @@ -3221,7 +3262,10 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg) /* handle special messages */ switch(msg_type) { case MNCC_BRIDGE: - return tch_bridge(net, arg); + rc = tch_bridge(net, arg); + if (rc < 0) + disconnect_bridge(net, arg, -rc); + return rc; case MNCC_FRAME_DROP: return tch_recv_mncc(net, data->callref, 0); case MNCC_FRAME_RECV: -- cgit v1.2.3 From 121e9a4164e65dfb68b2bf09297a8537a2f659c5 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 20 Apr 2016 13:13:19 +0200 Subject: Start to use struct osmo_auth_vector from gsm_auth_tuple Rather than having a 'private' structure for kc, sres and rand, we now finally (with 4 years delay) use osmo_auth_vector from libosmogsm, which encapsulates authentication vectors that can be either GSM triplets or UMTS quintuples or a combination of both. gsm_auth_tuple becomes a wrapper around osmo_auth_vector, adding use_count and key_seq to it. key_seq is no longer initialized inside gprs_gsup_messages.c, as there is no CKSN / key_seq inside the message anyway. If a usre of the code needs key_seq, they need to manage it themselves. --- openbsc/src/libmsc/gsm_04_08.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'openbsc/src/libmsc/gsm_04_08.c') diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 05cb88679..f02f784fe 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -234,11 +234,11 @@ int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq, /* Then do whatever is needed ... */ if (rc == AUTH_DO_AUTH_THEN_CIPH) { /* Start authentication */ - return gsm48_tx_mm_auth_req(conn, op->atuple.rand, op->atuple.key_seq); + return gsm48_tx_mm_auth_req(conn, op->atuple.vec.rand, op->atuple.key_seq); } else if (rc == AUTH_DO_CIPH) { /* Start ciphering directly */ return gsm0808_cipher_mode(conn, net->a5_encryption, - op->atuple.kc, 8, 0); + op->atuple.vec.kc, 8, 0); } return -EINVAL; /* not reached */ @@ -1102,12 +1102,12 @@ static int gsm48_rx_mm_auth_resp(struct gsm_subscriber_connection *conn, struct } /* Validate SRES */ - if (memcmp(conn->sec_operation->atuple.sres, ar->sres,4)) { + 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.sres, 4)); + osmo_hexdump(conn->sec_operation->atuple.vec.sres, 4)); if (cb) cb(GSM_HOOK_RR_SECURITY, GSM_SECURITY_AUTH_FAILED, @@ -1122,7 +1122,7 @@ static int gsm48_rx_mm_auth_resp(struct gsm_subscriber_connection *conn, struct /* Start ciphering */ return gsm0808_cipher_mode(conn, net->a5_encryption, - conn->sec_operation->atuple.kc, 8, 0); + conn->sec_operation->atuple.vec.kc, 8, 0); } /* Receive a GSM 04.08 Mobility Management (MM) message */ -- cgit v1.2.3