aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/libmsc/gsm_04_08.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/libmsc/gsm_04_08.c')
-rw-r--r--openbsc/src/libmsc/gsm_04_08.c594
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);
-}