aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/libmsc
diff options
context:
space:
mode:
authorNeels Hofmeyr <nhofmeyr@sysmocom.de>2017-03-02 02:37:39 +0100
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2017-03-16 15:32:33 +0100
commite48c9d13ae37545fecbd9ddde5f326c12ebb9f93 (patch)
tree9154286a8a3f558386a6792dc11790ed94022507 /openbsc/src/libmsc
parent443a180a81ec7c592a5f754a7aec78db497f940f (diff)
Make the code work so that the msc_vlr tests pass
Diffstat (limited to 'openbsc/src/libmsc')
-rw-r--r--openbsc/src/libmsc/a_iface.c8
-rw-r--r--openbsc/src/libmsc/gsm_04_08.c92
-rw-r--r--openbsc/src/libmsc/gsm_04_11.c3
-rw-r--r--openbsc/src/libmsc/gsm_subscriber.c148
-rw-r--r--openbsc/src/libmsc/iucs.c7
-rw-r--r--openbsc/src/libmsc/msc_ifaces.c14
-rw-r--r--openbsc/src/libmsc/osmo_msc.c60
-rw-r--r--openbsc/src/libmsc/silent_call.c2
-rw-r--r--openbsc/src/libmsc/subscr_conn.c35
-rw-r--r--openbsc/src/libmsc/transaction.c18
-rw-r--r--openbsc/src/libmsc/vty_interface_layer3.c92
11 files changed, 131 insertions, 348 deletions
diff --git a/openbsc/src/libmsc/a_iface.c b/openbsc/src/libmsc/a_iface.c
index 1f471f97b..caf9d4b06 100644
--- a/openbsc/src/libmsc/a_iface.c
+++ b/openbsc/src/libmsc/a_iface.c
@@ -35,6 +35,14 @@ int a_tx(struct msgb *msg)
return -1;
}
+int a_page(const char *imsi, uint32_t tmsi, uint16_t lac)
+{
+ LOGP(DMSC, LOGL_ERROR, "Paging to be sent to BSC, but A-interface"
+ " not implemented: IMSI %s TMSI 0x%08x LAC %u\n",
+ imsi, tmsi, lac);
+ return -1;
+}
+
int msc_gsm0808_tx_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,
const uint8_t *key, int len, int include_imeisv)
{
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index e1e3107de..02e6fa1d2 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -188,47 +188,23 @@ int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq,
/* Clear Request was received from MSC, release all transactions */
void gsm0408_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
{
- struct gsm_trans *trans, *temp;
-
- /* avoid someone issuing a clear */
- conn->in_release = 1;
-
- /*
- * Cancel any outstanding location updating request
- * operation taking place on the subscriber connection.
- */
- loc_updating_failure(conn, 0);
-
- /* We might need to cancel the paging response or such. */
- if (conn->sec_operation && conn->sec_operation->cb) {
- conn->sec_operation->cb(GSM_HOOK_RR_SECURITY, GSM_SECURITY_AUTH_FAILED,
- NULL, conn, conn->sec_operation->cb_data);
+ if (!conn) {
+ LOGP(DMM, LOGL_ERROR,
+ "%s: Conn clear request on NULL conn\n",
+ vlr_subscr_name(conn->vsub));
+ return;
}
- release_security_operation(conn);
- msc_release_anchor(conn);
-
- /*
- * Free all transactions that are associated with the released
- * connection. The transaction code will inform the CC or SMS
- * facilities that will send the release indications. As part of
- * the CC REL_IND the remote leg might be released and this will
- * trigger the call to trans_free. This is something the llist
- * macro can not handle and we will need to re-iterate the list.
- *
- * TODO: Move the trans_list into the subscriber connection and
- * create a pending list for MT transactions. These exist before
- * we have a subscriber connection.
- */
-restart:
- llist_for_each_entry_safe(trans, temp, &conn->network->trans_list, entry) {
- if (trans->conn == conn) {
- trans_free(trans);
- goto restart;
- }
+ if (!conn->conn_fsm) {
+ LOGP(DMM, LOGL_ERROR,
+ "%s: Conn clear request on uninitialized conn\n",
+ vlr_subscr_name(conn->vsub));
+ msc_subscr_con_free(conn);
+ return;
}
- msc_subscr_con_free(conn);
+ /* TODO add cause item to msc_close_connection() */
+ osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_CN_CLOSE, &cause);
}
/* clear all transactions globally; used in case of MNCC socket disconnect */
@@ -913,7 +889,7 @@ static int gsm48_rx_mm_auth_resp(struct gsm_subscriber_connection *conn, struct
if (!conn->vsub) {
LOGP(DMM, LOGL_ERROR,
"MM AUTHENTICATION RESPONSE: invalid: no subscriber\n");
- msc_close_connection(conn);
+ gsm0408_clear_request(conn, GSM_CAUSE_AUTH_FAILED);
return -EINVAL;
}
@@ -927,7 +903,7 @@ static int gsm48_rx_mm_auth_resp(struct gsm_subscriber_connection *conn, struct
}
if (rc) {
- msc_close_connection(conn);
+ gsm0408_clear_request(conn, GSM_CAUSE_AUTH_FAILED);
return -EINVAL;
}
@@ -952,7 +928,7 @@ static int gsm48_rx_mm_auth_fail(struct gsm_subscriber_connection *conn, struct
if (!conn->vsub) {
LOGP(DMM, LOGL_ERROR,
"MM R99 AUTHENTICATION FAILURE: invalid: no subscriber\n");
- msc_close_connection(conn);
+ gsm0408_clear_request(conn, GSM_CAUSE_AUTH_FAILED);
return -EINVAL;
}
@@ -961,7 +937,7 @@ static int gsm48_rx_mm_auth_fail(struct gsm_subscriber_connection *conn, struct
"%s: MM R99 AUTHENTICATION FAILURE:"
" l3 length invalid: %u\n",
vlr_subscr_name(conn->vsub), msgb_l3len(msg));
- msc_close_connection(conn);
+ gsm0408_clear_request(conn, GSM_CAUSE_AUTH_FAILED);
return -EINVAL;
}
@@ -984,7 +960,7 @@ static int gsm48_rx_mm_auth_fail(struct gsm_subscriber_connection *conn, struct
"%s: MM R99 AUTHENTICATION FAILURE:"
" invalid Synch Failure: missing AUTS IE\n",
vlr_subscr_name(conn->vsub));
- msc_close_connection(conn);
+ gsm0408_clear_request(conn, GSM_CAUSE_AUTH_FAILED);
return -EINVAL;
}
@@ -1001,7 +977,7 @@ static int gsm48_rx_mm_auth_fail(struct gsm_subscriber_connection *conn, struct
" got IE 0x%02x of %u bytes\n",
vlr_subscr_name(conn->vsub),
GSM48_IE_AUTS, auts_tag, auts_len);
- msc_close_connection(conn);
+ gsm0408_clear_request(conn, GSM_CAUSE_AUTH_FAILED);
return -EINVAL;
}
@@ -1010,7 +986,7 @@ static int gsm48_rx_mm_auth_fail(struct gsm_subscriber_connection *conn, struct
"%s: MM R99 AUTHENTICATION FAILURE:"
" invalid Synch Failure msg: message truncated (%u)\n",
vlr_subscr_name(conn->vsub), msgb_l3len(msg));
- msc_close_connection(conn);
+ gsm0408_clear_request(conn, GSM_CAUSE_AUTH_FAILED);
return -EINVAL;
}
@@ -3358,7 +3334,8 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg)
memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
/* Request a channel */
- trans->paging_request = subscr_request_conn(subscr,
+ trans->paging_request = subscr_request_conn(
+ vsub,
setup_trig_pag_evt,
trans);
if (!trans->paging_request) {
@@ -3555,11 +3532,6 @@ void msc_release_anchor(struct gsm_subscriber_connection *conn)
subscr_con_put(conn);
}
-int gsm0408_new_conn(struct gsm_subscriber_connection *conn)
-{
- return 0;
-}
-
static bool msg_is_initially_permitted(const struct gsm48_hdr *hdr)
{
uint8_t pdisc = gsm48_hdr_pdisc(hdr);
@@ -3641,6 +3613,16 @@ int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg)
return -EACCES;
}
+ if (conn->vsub && conn->vsub->cs.attached_via_ran != conn->via_ran) {
+ LOGP(DMM, LOGL_ERROR,
+ "%s: Illegal situation: RAN type mismatch:"
+ " attached via %s, received message via %s\n",
+ vlr_subscr_name(conn->vsub),
+ ran_type_name(conn->vsub->cs.attached_via_ran),
+ ran_type_name(conn->via_ran));
+ return -EACCES;
+ }
+
#if 0
if (silent_call_reroute(conn, msg))
return silent_call_rx(conn, msg);
@@ -3736,7 +3718,7 @@ static int msc_vlr_tx_lu_rej(void *msc_conn_ref, uint8_t cause)
static int msc_vlr_tx_cm_serv_acc(void *msc_conn_ref)
{
struct gsm_subscriber_connection *conn = msc_conn_ref;
- return gsm48_tx_mm_serv_ack(conn);
+ return msc_gsm48_tx_mm_serv_ack(conn);
}
/* VLR asks us to transmit a CM Service Reject */
@@ -3769,7 +3751,7 @@ static int msc_vlr_tx_cm_serv_rej(void *msc_conn_ref, enum vlr_proc_arq_result r
break;
};
- return gsm48_tx_mm_serv_rej(conn, cause);
+ return msc_gsm48_tx_mm_serv_rej(conn, cause);
}
/* VLR asks us to start using ciphering */
@@ -3797,9 +3779,8 @@ static int msc_vlr_set_ciph_mode(void *msc_conn_ref,
return -EINVAL;
}
- /* TODO: MSCSPLIT: don't directly push BSC buttons */
- return gsm0808_cipher_mode(conn, ciph, tuple->vec.kc, 8,
- retrieve_imeisv);
+ return msc_gsm0808_tx_cipher_mode(conn, ciph, tuple->vec.kc, 8,
+ retrieve_imeisv);
}
/* VLR informs us that the subscriber data has somehow been modified */
@@ -3815,6 +3796,7 @@ static void msc_vlr_subscr_assoc(void *msc_conn_ref,
struct gsm_subscriber_connection *conn = msc_conn_ref;
OSMO_ASSERT(!conn->vsub);
conn->vsub = vlr_subscr_get(vsub);
+ conn->vsub->cs.attached_via_ran = conn->via_ran;
}
/* operations that we need to implement for libvlr */
diff --git a/openbsc/src/libmsc/gsm_04_11.c b/openbsc/src/libmsc/gsm_04_11.c
index 1556d58e8..d2a9723bf 100644
--- a/openbsc/src/libmsc/gsm_04_11.c
+++ b/openbsc/src/libmsc/gsm_04_11.c
@@ -1009,8 +1009,7 @@ int gsm411_send_sms_subscr(struct vlr_subscr *vsub,
/* if not, we have to start paging */
LOGP(DLSMS, LOGL_DEBUG, "Sending SMS: no connection open, start paging %s\n",
vlr_subscr_name(vsub));
- res = subscr_request_conn(vsub, RSL_CHANNEED_SDCCH, paging_cb_send_sms,
- sms);
+ res = subscr_request_conn(vsub, paging_cb_send_sms, sms);
if (!res) {
send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, GSM_PAGING_BUSY);
sms_free(sms);
diff --git a/openbsc/src/libmsc/gsm_subscriber.c b/openbsc/src/libmsc/gsm_subscriber.c
index ef7260660..09c5e5d71 100644
--- a/openbsc/src/libmsc/gsm_subscriber.c
+++ b/openbsc/src/libmsc/gsm_subscriber.c
@@ -41,25 +41,14 @@
#include <openbsc/chan_alloc.h>
#include <openbsc/vlr.h>
#include <openbsc/iu.h>
+#include <openbsc/osmo_msc.h>
+#include <openbsc/msc_ifaces.h>
void *tall_sub_req_ctx;
int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq,
gsm_cbfn *cb, void *cb_data);
-static struct bsc_subscr *vlr_subscr_to_bsc_sub(struct llist_head *bsc_subscribers,
- struct vlr_subscr *vsub)
-{
- struct bsc_subscr *sub;
- /* TODO MSC split -- creating a BSC subscriber directly from MSC data
- * structures in RAM. At some point the MSC will send a message to the
- * BSC instead. */
- sub = bsc_subscr_find_or_create_by_imsi(bsc_subscribers, vsub->imsi);
- sub->tmsi = vsub->tmsi;
- sub->lac = vsub->lac;
- return sub;
-}
-
/* A connection is established and the paging callbacks may run now. */
int subscr_paging_dispatch(unsigned int hooknum, unsigned int event,
struct msgb *msg, void *data, void *param)
@@ -68,36 +57,34 @@ int subscr_paging_dispatch(unsigned int hooknum, unsigned int event,
struct gsm_subscriber_connection *conn = data;
struct vlr_subscr *vsub = param;
struct paging_signal_data sig_data;
- struct bsc_subscr *bsub;
- struct gsm_network *net;
OSMO_ASSERT(vsub);
- net = vsub->vlr->user_ctx;
OSMO_ASSERT(hooknum == GSM_HOOK_RR_PAGING);
OSMO_ASSERT(!(conn && (conn->vsub != vsub)));
OSMO_ASSERT(!((event == GSM_PAGING_SUCCEEDED) && !conn));
LOGP(DPAG, LOGL_DEBUG, "Paging %s for %s (event=%d)\n",
event == GSM_PAGING_SUCCEEDED ? "success" : "failure",
- subscr_name(subscr), event);
+ vlr_subscr_name(vsub), event);
- if (!subscr->is_paging) {
+ if (!vsub->cs.is_paging) {
LOGP(DPAG, LOGL_ERROR,
"Paging Response received for subscriber"
" that is not paging.\n");
return -EINVAL;
}
+ if (event == GSM_PAGING_SUCCEEDED)
+ msc_stop_paging(vsub);
+
/* Inform parts of the system we don't know */
- sig_data.vsub = vsub;
- sig_data.conn = conn;
+ sig_data.vsub = vsub;
+ sig_data.conn = conn;
sig_data.paging_result = event;
- osmo_signal_dispatch(
- SS_PAGING,
- event == GSM_PAGING_SUCCEEDED ?
- S_PAGING_SUCCEEDED : S_PAGING_EXPIRED,
- &sig_data
- );
+ osmo_signal_dispatch(SS_PAGING,
+ event == GSM_PAGING_SUCCEEDED ?
+ S_PAGING_SUCCEEDED : S_PAGING_EXPIRED,
+ &sig_data);
llist_for_each_entry_safe(request, tmp, &vsub->cs.requests, entry) {
llist_del(&request->entry);
@@ -115,99 +102,28 @@ int subscr_paging_dispatch(unsigned int hooknum, unsigned int event,
return 0;
}
-static void paging_timeout_release(struct gsm_subscriber *subscr)
-{
- DEBUGP(DPAG, "Paging timeout released for %s\n", subscr_name(subscr));
- osmo_timer_del(&subscr->paging_timeout);
-}
-
-static void paging_timeout(void *data)
-{
- struct gsm_subscriber *subscr = data;
- DEBUGP(DPAG, "Paging timeout reached for %s\n", subscr_name(subscr));
- paging_timeout_release(subscr);
- subscr_paging_dispatch(GSM_HOOK_RR_PAGING, GSM_PAGING_EXPIRED,
- NULL, NULL, subscr);
-}
-
-static void paging_timeout_start(struct gsm_subscriber *subscr)
-{
- DEBUGP(DPAG, "Starting paging timeout for %s\n", subscr_name(subscr));
- subscr->paging_timeout.data = subscr;
- subscr->paging_timeout.cb = paging_timeout;
- osmo_timer_schedule(&subscr->paging_timeout, 10, 0);
- /* TODO: configurable timeout duration? */
-}
-
-
-static int subscr_paging_sec_cb(unsigned int hooknum, unsigned int event,
- struct msgb *msg, void *data, void *param)
-{
- int rc;
- struct gsm_subscriber_connection *conn = data;
- OSMO_ASSERT(conn);
-
- switch (event) {
- case GSM_SECURITY_AUTH_FAILED:
- LOGP(DPAG, LOGL_ERROR,
- "Dropping Paging Response:"
- " authorization failed for subscriber %s\n",
- subscr_name(conn->subscr));
- rc = subscr_paging_dispatch(
- GSM_HOOK_RR_PAGING, GSM_PAGING_EXPIRED,
- msg, conn, conn->subscr);
- break;
-
- case GSM_SECURITY_NOAVAIL:
- case GSM_SECURITY_SUCCEEDED:
- rc = subscr_paging_dispatch(
- GSM_HOOK_RR_PAGING, GSM_PAGING_SUCCEEDED,
- msg, conn, conn->subscr);
- break;
-
- default:
- LOGP(DPAG, LOGL_FATAL,
- "Invalid authorization event: %d\n", event);
- rc = -EINVAL;
- }
-
- return rc;
-}
-
-int subscr_rx_paging_response(struct msgb *msg,
- struct gsm_subscriber_connection *conn)
-{
- struct gsm48_hdr *gh;
- struct gsm48_pag_resp *pr;
-
- /* Get key_seq from Paging Response headers */
- gh = msgb_l3(msg);
- pr = (struct gsm48_pag_resp *)gh->data;
-
- paging_timeout_release(conn->subscr);
-
- /* Secure the connection */
- if (subscr_authorized(conn->subscr))
- return gsm48_secure_channel(conn, pr->key_seq,
- subscr_paging_sec_cb, NULL);
-
- /* Not authorized. Failure. */
- subscr_paging_sec_cb(GSM_HOOK_RR_SECURITY, GSM_SECURITY_AUTH_FAILED,
- msg, conn, NULL);
- return -1;
-}
-
-static int msc_paging_request(struct gsm_subscriber *subscr)
+int msc_paging_request(struct vlr_subscr *vsub)
{
/* The subscriber was last seen in subscr->lac. Find out which
* BSCs/RNCs are responsible and send them a paging request via open
* SCCP connections (if any). */
/* TODO Implementing only RNC paging, since this is code on the iu branch.
* Need to add BSC paging at some point. */
- return iu_page_cs(subscr->imsi,
- subscr->tmsi == GSM_RESERVED_TMSI?
- NULL : &subscr->tmsi,
- subscr->lac);
+ switch (vsub->cs.attached_via_ran) {
+ case RAN_GERAN_A:
+ return a_page(vsub->imsi, vsub->tmsi, vsub->lac);
+ case RAN_UTRAN_IU:
+ return iu_page_cs(vsub->imsi,
+ vsub->tmsi == GSM_RESERVED_TMSI?
+ NULL : &vsub->tmsi,
+ vsub->lac);
+ default:
+ break;
+ }
+
+ LOGP(DPAG, LOGL_ERROR, "%s: Cannot page, subscriber not attached\n",
+ vlr_subscr_name(vsub));
+ return -EINVAL;
}
struct subscr_request *subscr_request_conn(struct vlr_subscr *vsub,
@@ -215,11 +131,9 @@ struct subscr_request *subscr_request_conn(struct vlr_subscr *vsub,
{
int rc;
struct subscr_request *request;
- struct bsc_subscr *bsub;
- struct gsm_network *net = vsub->vlr->user_ctx;
/* Start paging.. we know it is async so we can do it before */
- if (!subscr->is_paging) {
+ if (!vsub->cs.is_paging) {
LOGP(DMM, LOGL_DEBUG, "Subscriber %s not paged yet, start paging.\n",
vlr_subscr_name(vsub));
rc = msc_paging_request(vsub);
@@ -233,7 +147,7 @@ struct subscr_request *subscr_request_conn(struct vlr_subscr *vsub,
vsub->cs.is_paging = true;
} else {
LOGP(DMM, LOGL_DEBUG, "Subscriber %s already paged.\n",
- subscr_name(subscr));
+ vlr_subscr_name(vsub));
}
/* TODO: Stop paging in case of memory allocation failure */
diff --git a/openbsc/src/libmsc/iucs.c b/openbsc/src/libmsc/iucs.c
index 469d3e0a7..8d763d223 100644
--- a/openbsc/src/libmsc/iucs.c
+++ b/openbsc/src/libmsc/iucs.c
@@ -185,13 +185,8 @@ int gsm0408_rcvmsg_iucs(struct gsm_network *network, struct msgb *msg,
if (!conn)
abort();
+ /* ownership of conn hereby goes to the MSC: */
rc = msc_compl_l3(conn, msg, 0);
- if (rc != MSC_CONN_ACCEPT) {
- gsm0408_clear_request(conn, 0);
- rc = -1;
- }
- else
- rc = 0;
}
return rc;
diff --git a/openbsc/src/libmsc/msc_ifaces.c b/openbsc/src/libmsc/msc_ifaces.c
index 71f27a318..8cc91c614 100644
--- a/openbsc/src/libmsc/msc_ifaces.c
+++ b/openbsc/src/libmsc/msc_ifaces.c
@@ -28,6 +28,7 @@
#include <openbsc/transaction.h>
#include <openbsc/mgcp.h>
#include <openbsc/mgcpgw_client.h>
+#include <openbsc/vlr.h>
#include "../../bscconfig.h"
@@ -38,6 +39,9 @@ extern struct msgb *ranap_new_msg_rab_assign_voice(uint8_t rab_id,
static int msc_tx(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
+ DEBUGP(DMSC, "msc_tx %u bytes to %s via %s\n",
+ msg->len, vlr_subscr_name(conn->vsub),
+ ran_type_name(conn->via_ran));
switch (conn->via_ran) {
case RAN_GERAN_A:
msg->dst = conn;
@@ -101,7 +105,7 @@ int msc_tx_common_id(struct gsm_subscriber_connection *conn)
return 0;
#ifdef BUILD_IU
- return iu_tx_common_id(conn->iu.ue_ctx, conn->subscr->imsi);
+ return iu_tx_common_id(conn->iu.ue_ctx, conn->vsub->imsi);
#else
LOGP(DMM, LOGL_ERROR,
"Cannot send CommonID: RAN_UTRAN_IU but IuCS support not built\n");
@@ -152,7 +156,7 @@ static void mgcp_response_rab_act_cs_crcx(struct mgcp_response *r, void *priv)
if (rc) {
LOGP(DMGCP, LOGL_ERROR,
"Cannot parse MGCP response, for %s\n",
- subscr_name(trans->subscr));
+ vlr_subscr_name(trans->vsub));
goto rab_act_cs_error;
}
@@ -250,7 +254,7 @@ static void mgcp_bridge(struct gsm_trans *from, struct gsm_trans *to,
if (mgcpgw_client_tx(mgcp, msg, mgcp_response_bridge_mdcx, from))
LOGP(DMGCP, LOGL_ERROR,
"Failed to send MDCX message for %s\n",
- subscr_name(from->subscr));
+ vlr_subscr_name(from->vsub));
}
static void mgcp_response_bridge_mdcx(struct mgcp_response *r, void *priv)
@@ -277,7 +281,7 @@ static void mgcp_response_bridge_mdcx(struct mgcp_response *r, void *priv)
default:
LOGP(DMGCP, LOGL_ERROR,
"Unexpected bridge state: %d for %s\n",
- trans->bridge.state, subscr_name(trans->subscr));
+ trans->bridge.state, vlr_subscr_name(trans->vsub));
break;
}
break;
@@ -289,7 +293,7 @@ static void mgcp_response_bridge_mdcx(struct mgcp_response *r, void *priv)
default:
LOGP(DMGCP, LOGL_ERROR,
"Unexpected bridge state: %d for %s\n",
- trans->bridge.state, subscr_name(trans->subscr));
+ trans->bridge.state, vlr_subscr_name(trans->vsub));
break;
}
}
diff --git a/openbsc/src/libmsc/osmo_msc.c b/openbsc/src/libmsc/osmo_msc.c
index 0511fc5dd..6ce837b8a 100644
--- a/openbsc/src/libmsc/osmo_msc.c
+++ b/openbsc/src/libmsc/osmo_msc.c
@@ -48,61 +48,17 @@ static int msc_clear_request(struct gsm_subscriber_connection *conn, uint32_t ca
return 1;
}
-static bool keep_conn(struct gsm_subscriber_connection *conn)
-{
- /* TODO: what about a silent call? */
-
- if (!conn->conn_fsm) {
- DEBUGP(DMM, "No conn_fsm, release conn\n");
- return false;
- }
-
- switch (conn->conn_fsm->state) {
- case SUBSCR_CONN_S_NEW:
- case SUBSCR_CONN_S_ACCEPTED:
- return true;
- default:
- return false;
- }
-}
-
/* receive a Level 3 Complete message and return MSC_CONN_ACCEPT or
* MSC_CONN_REJECT */
-enum msc_compl_l3_rc msc_compl_l3(struct gsm_subscriber_connection *conn,
- struct msgb *msg, uint16_t chosen_channel)
+int msc_compl_l3(struct gsm_subscriber_connection *conn,
+ struct msgb *msg, uint16_t chosen_channel)
{
- gsm0408_new_conn(conn);
gsm0408_dispatch(conn, msg);
- /* NOTE: after the MSC split, returning BSC_API_CONN_POL_REJECT shall
- * be replaced with a call to msc_subscr_con_free() */
-
- if (!keep_conn(conn)) {
- DEBUGP(DMM, "compl_l3: Discarding conn\n");
- return MSC_CONN_REJECT;
- }
- DEBUGP(DMM, "compl_l3: Keeping conn\n");
- conn->owned_by_msc = true;
- DEBUGP(DMM, "%s owned_by_msc = true\n",
- vlr_subscr_name(conn->vsub));
+ /* Always return acceptance, because even if the conn was not accepted,
+ * we assumed ownership of it and the caller shall not interfere with
+ * that. We may even already have discarded the conn. */
return MSC_CONN_ACCEPT;
-
-#if 0
- /*
- * If this is a silent call we want the channel to remain open as long as
- * possible and this is why we accept this connection regardless of any
- * pending transaction or ongoing operation.
- */
- if (conn->silent_call)
- return MSC_CONN_ACCEPT;
- if (conn->loc_operation || conn->sec_operation || conn->anch_operation)
- return MSC_CONN_ACCEPT;
- if (trans_has_conn(conn))
- return MSC_CONN_ACCEPT;
-
- LOGP(DRR, LOGL_INFO, "MSC Complete L3: Rejecting connection.\n");
- return MSC_CONN_REJECT;
-#endif
}
static void subscr_conn_bump(struct gsm_subscriber_connection *conn)
@@ -334,3 +290,9 @@ void _subscr_con_put(struct gsm_subscriber_connection *conn,
osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_MO_CLOSE, NULL);
#endif
}
+
+void msc_stop_paging(struct vlr_subscr *vsub)
+{
+ DEBUGP(DPAG, "Paging can stop for %s\n", vlr_subscr_name(vsub));
+ /* tell BSCs and RNCs to stop paging? How? */
+}
diff --git a/openbsc/src/libmsc/silent_call.c b/openbsc/src/libmsc/silent_call.c
index c04582e69..7027dce11 100644
--- a/openbsc/src/libmsc/silent_call.c
+++ b/openbsc/src/libmsc/silent_call.c
@@ -131,7 +131,7 @@ int gsm_silent_call_start(struct vlr_subscr *vsub, void *data, int type)
/* FIXME the VTY command allows selecting a silent call channel type.
* This doesn't apply to the situation after MSCSPLIT with an
* A-interface. */
- req = subscr_request_conn(vsub, type, paging_cb_silent, data);
+ req = subscr_request_conn(vsub, paging_cb_silent, data);
return req != NULL;
}
diff --git a/openbsc/src/libmsc/subscr_conn.c b/openbsc/src/libmsc/subscr_conn.c
index 9640c1ff2..6eeb2dba3 100644
--- a/openbsc/src/libmsc/subscr_conn.c
+++ b/openbsc/src/libmsc/subscr_conn.c
@@ -30,6 +30,7 @@
#include <openbsc/debug.h>
#include <openbsc/transaction.h>
#include <openbsc/signal.h>
+#include <openbsc/iu.h>
#define SUBSCR_CONN_TIMEOUT 5 /* seconds */
@@ -52,8 +53,8 @@ const struct value_string subscr_conn_from_names[] = {
{ 0, NULL }
};
-static void paging_resp(struct gsm_subscriber_connection *conn,
- enum gsm_paging_event pe)
+static void paging_event(struct gsm_subscriber_connection *conn,
+ enum gsm_paging_event pe)
{
subscr_paging_dispatch(GSM_HOOK_RR_PAGING, pe, NULL, conn, conn->vsub);
}
@@ -84,11 +85,17 @@ void subscr_conn_fsm_new(struct osmo_fsm_inst *fi, uint32_t event, void *data)
case SUBSCR_CONN_E_MO_CLOSE:
case SUBSCR_CONN_E_CN_CLOSE:
+ if (data)
+ LOGPFSM(fi, "Close event, cause %u\n",
+ *(uint32_t*)data);
+ /* will release further below, see
+ * 'if (fi->state != SUBSCR_CONN_S_ACCEPTED)' */
break;
default:
- LOGPFSM(fi, "Unexpected event: %d %s\n",
- event, osmo_fsm_event_name(fi->fsm, event));
+ LOGPFSML(fi, LOGL_ERROR,
+ "Unexpected event: %d %s\n", event,
+ osmo_fsm_event_name(fi->fsm, event));
break;
}
@@ -96,7 +103,7 @@ void subscr_conn_fsm_new(struct osmo_fsm_inst *fi, uint32_t event, void *data)
if (from == SUBSCR_CONN_FROM_PAGING_RESP) {
pe = (fi->state == SUBSCR_CONN_S_ACCEPTED)?
GSM_PAGING_SUCCEEDED : GSM_PAGING_EXPIRED;
- paging_resp(conn, pe);
+ paging_event(conn, pe);
}
/* FIXME rate counters */
@@ -105,13 +112,11 @@ void subscr_conn_fsm_new(struct osmo_fsm_inst *fi, uint32_t event, void *data)
/* On failure, discard the conn */
if (fi->state != SUBSCR_CONN_S_ACCEPTED) {
/* TODO: on MO_CLOSE or CN_CLOSE, first go to RELEASING and
- * await BSC confirmation? */
+ * await BSC/RNC confirmation? */
osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_RELEASED, 0, 0);
return;
}
- /* On success, handle pending requests and/or close conn */
-
if (from == SUBSCR_CONN_FROM_CM_SERVICE_REQ) {
conn->received_cm_service_request = true;
LOGPFSM(fi, "received_cm_service_request = true\n");
@@ -236,23 +241,13 @@ static void subscr_conn_fsm_cleanup(struct osmo_fsm_inst *fi,
LOGP(DMM, LOGL_ERROR, "%s: closing conn but still in use (%u)\n",
vlr_subscr_name(conn->vsub), conn->use_count);
- /* temporary hack, see owned_by_msc */
- if (!conn->owned_by_msc) {
- DEBUGP(DMM, "%s leaving bsc_subscr_con_free() to bsc_api.c, owned_by_msc = false\n",
- vlr_subscr_name(conn->vsub));
- return;
- }
-
- if (conn->via_iface == IFACE_IU)
+ if (conn->via_ran == RAN_UTRAN_IU)
iu_tx_release(conn->iu.ue_ctx, NULL);
/* FIXME: keep the conn until the Iu Release Outcome is
* received from the UE, or a timeout expires. For now, the log
* says "unknown UE" for each release outcome. */
- DEBUGP(DMM, "%s calling bsc_subscr_con_free(), owned_by_msc = true\n",
- vlr_subscr_name(conn->vsub));
- gsm0808_clear(conn);
- bsc_subscr_con_free(conn);
+ msc_subscr_con_free(conn);
}
int subscr_conn_fsm_timeout(struct osmo_fsm_inst *fi)
diff --git a/openbsc/src/libmsc/transaction.c b/openbsc/src/libmsc/transaction.c
index 071acbc36..af9b30003 100644
--- a/openbsc/src/libmsc/transaction.c
+++ b/openbsc/src/libmsc/transaction.c
@@ -192,12 +192,24 @@ int trans_has_conn(const struct gsm_subscriber_connection *conn)
return 0;
}
+/*
+ * Free all transactions that are associated with the released
+ * connection. The transaction code will inform the CC or SMS
+ * facilities that will send the release indications.
+ */
void trans_conn_closed(struct gsm_subscriber_connection *conn)
{
- struct gsm_trans *trans, *t2;
+ struct gsm_trans *trans;
- llist_for_each_entry_safe(trans, t2, &conn->network->trans_list, entry) {
- if (trans->conn == conn)
+ /* As part of the CC REL_IND the remote leg might be released and this
+ * will trigger the call to trans_free. This is something the llist
+ * macro can not handle and we will need to re-iterate the list.
+ */
+restart:
+ llist_for_each_entry(trans, &conn->network->trans_list, entry) {
+ if (trans->conn == conn) {
trans_free(trans);
+ goto restart;
+ }
}
}
diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c
index 804b5c70c..c783cf101 100644
--- a/openbsc/src/libmsc/vty_interface_layer3.c
+++ b/openbsc/src/libmsc/vty_interface_layer3.c
@@ -22,6 +22,7 @@
#include <limits.h>
#include <unistd.h>
#include <time.h>
+#include <inttypes.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/buffer.h>
@@ -900,7 +901,6 @@ DEFUN(logging_fltr_imsi,
"Filter log messages by IMSI\n" "IMSI to be used as filter\n")
{
struct vlr_subscr *vlr_subscr;
- struct bsc_subscr *bsc_subscr;
struct gsm_network *gsmnet = gsmnet_from_vty(vty);
struct log_target *tgt = osmo_log_vty2tgt(vty);
const char *imsi = argv[0];
@@ -909,16 +909,14 @@ DEFUN(logging_fltr_imsi,
return CMD_WARNING;
vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi);
- bsc_subscr = bsc_subscr_find_by_imsi(gsmnet->bsc_subscribers, imsi);
- if (!vlr_subscr && !bsc_subscr) {
+ if (!vlr_subscr) {
vty_out(vty, "%%no subscriber with IMSI(%s)%s",
argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
log_set_filter_vlr_subscr(tgt, vlr_subscr);
- log_set_filter_bsc_subscr(tgt, bsc_subscr);
return CMD_SUCCESS;
}
@@ -966,92 +964,6 @@ static int config_write_hlr(struct vty *vty)
return CMD_SUCCESS;
}
-static struct cmd_node nitb_node = {
- NITB_NODE,
- "%s(config-nitb)# ",
- 1,
-};
-
-DEFUN(cfg_nitb, cfg_nitb_cmd,
- "nitb", "Configure NITB options")
-{
- vty->node = NITB_NODE;
- return CMD_SUCCESS;
-}
-
-/* Note: limit on the parameter length is set by internal vty code limitations */
-DEFUN(cfg_nitb_subscr_random, cfg_nitb_subscr_random_cmd,
- "subscriber-create-on-demand random <1-9999999999> <2-9999999999>",
- "Set random parameters for a new record when a subscriber is first seen.\n"
- "Set random parameters for a new record when a subscriber is first seen.\n"
- "Minimum for subscriber extension\n""Maximum for subscriber extension\n")
-{
- vty_out(vty, "%% 'subscriber-create-on-demand' is no longer supported.%s"
- "%% This is now up to osmo-hlr.%s",
- VTY_NEWLINE, VTY_NEWLINE);
- return CMD_WARNING;
-}
-
-DEFUN(cfg_nitb_subscr_create, cfg_nitb_subscr_create_cmd,
- "subscriber-create-on-demand [no-extension]",
- "Make a new record when a subscriber is first seen.\n"
- "Do not automatically assign extension to created subscribers\n")
-{
- vty_out(vty, "%% 'subscriber-create-on-demand' is no longer supported.%s"
- "%% This is now up to osmo-hlr.%s",
- VTY_NEWLINE, VTY_NEWLINE);
- return CMD_WARNING;
-}
-
-DEFUN(cfg_nitb_no_subscr_create, cfg_nitb_no_subscr_create_cmd,
- "no subscriber-create-on-demand",
- NO_STR "Make a new record when a subscriber is first seen.\n")
-{
- vty_out(vty, "%% 'subscriber-create-on-demand' is no longer supported.%s"
- "%% This is now up to osmo-hlr.%s",
- VTY_NEWLINE, VTY_NEWLINE);
- return CMD_WARNING;
-}
-
-DEFUN(cfg_nitb_assign_tmsi, cfg_nitb_assign_tmsi_cmd,
- "assign-tmsi",
- "Assign TMSI during Location Updating.\n")
-{
- struct gsm_network *gsmnet = gsmnet_from_vty(vty);
- gsmnet->vlr->cfg.assign_tmsi = true;
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nitb_no_assign_tmsi, cfg_nitb_no_assign_tmsi_cmd,
- "no assign-tmsi",
- NO_STR "Assign TMSI during Location Updating.\n")
-{
- struct gsm_network *gsmnet = gsmnet_from_vty(vty);
- gsmnet->vlr->cfg.assign_tmsi = false;
- return CMD_SUCCESS;
-}
-
-static int config_write_nitb(struct vty *vty)
-{
- struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
- vty_out(vty, "nitb%s", VTY_NEWLINE);
- if (!gsmnet->auto_create_subscr)
- vty_out(vty, " no subscriber-create-on-demand%s", VTY_NEWLINE);
- else
- vty_out(vty, " subscriber-create-on-demand%s%s",
- gsmnet->auto_assign_exten ? "" : " no-extension",
- VTY_NEWLINE);
-
- if (gsmnet->ext_min != GSM_MIN_EXTEN || gsmnet->ext_max != GSM_MAX_EXTEN)
- vty_out(vty, " subscriber-create-on-demand random %"PRIu64" %"
- PRIu64"%s", gsmnet->ext_min, gsmnet->ext_max,
- VTY_NEWLINE);
- vty_out(vty, " %sassign-tmsi%s",
- gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
- return CMD_SUCCESS;
-}
-
int bsc_vty_init_extra(void)
{
osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);