diff options
author | Neels Hofmeyr <nhofmeyr@sysmocom.de> | 2017-03-02 02:37:39 +0100 |
---|---|---|
committer | Neels Hofmeyr <nhofmeyr@sysmocom.de> | 2017-03-16 15:32:33 +0100 |
commit | e48c9d13ae37545fecbd9ddde5f326c12ebb9f93 (patch) | |
tree | 9154286a8a3f558386a6792dc11790ed94022507 /openbsc/src | |
parent | 443a180a81ec7c592a5f754a7aec78db497f940f (diff) |
Make the code work so that the msc_vlr tests pass
Change-Id: Ie8814d856bbe4c111007a696a4d26576854c134f
Diffstat (limited to 'openbsc/src')
-rw-r--r-- | openbsc/src/libcommon/gsm_data.c | 7 | ||||
-rw-r--r-- | openbsc/src/libmsc/a_iface.c | 8 | ||||
-rw-r--r-- | openbsc/src/libmsc/gsm_04_08.c | 92 | ||||
-rw-r--r-- | openbsc/src/libmsc/gsm_04_11.c | 3 | ||||
-rw-r--r-- | openbsc/src/libmsc/gsm_subscriber.c | 148 | ||||
-rw-r--r-- | openbsc/src/libmsc/iucs.c | 7 | ||||
-rw-r--r-- | openbsc/src/libmsc/msc_ifaces.c | 14 | ||||
-rw-r--r-- | openbsc/src/libmsc/osmo_msc.c | 60 | ||||
-rw-r--r-- | openbsc/src/libmsc/silent_call.c | 2 | ||||
-rw-r--r-- | openbsc/src/libmsc/subscr_conn.c | 35 | ||||
-rw-r--r-- | openbsc/src/libmsc/transaction.c | 18 | ||||
-rw-r--r-- | openbsc/src/libmsc/vty_interface_layer3.c | 92 | ||||
-rw-r--r-- | openbsc/src/osmo-msc/iucs_ranap.c | 17 | ||||
-rw-r--r-- | openbsc/src/osmo-msc/msc_main.c | 31 |
14 files changed, 155 insertions, 379 deletions
diff --git a/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c index c522f1db5..968aa1be8 100644 --- a/openbsc/src/libcommon/gsm_data.c +++ b/openbsc/src/libcommon/gsm_data.c @@ -431,3 +431,10 @@ bool classmark_is_r99(struct gsm_classmark *cm) rev_lev = (cm->classmark2[0] >> 5) & 0x3; return rev_lev >= 2; } + +const struct value_string ran_type_names[] = { + OSMO_VALUE_STRING(RAN_UNKNOWN), + OSMO_VALUE_STRING(RAN_GERAN_A), + OSMO_VALUE_STRING(RAN_UTRAN_IU), + { 0, NULL } +}; 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); diff --git a/openbsc/src/osmo-msc/iucs_ranap.c b/openbsc/src/osmo-msc/iucs_ranap.c index 34f5bfe59..09b81489b 100644 --- a/openbsc/src/osmo-msc/iucs_ranap.c +++ b/openbsc/src/osmo-msc/iucs_ranap.c @@ -30,6 +30,7 @@ #include <openbsc/gsm_subscriber.h> #include <openbsc/iu.h> #include <openbsc/iucs.h> +#include <openbsc/vlr.h> #include "iucs_ranap.h" @@ -44,9 +45,9 @@ static int iucs_rx_rab_assign(struct gsm_subscriber_connection *conn, rab_id = item->rAB_ID.buf[0]; - LOGP(DIUCS, LOGL_NOTICE, "Received RAB assignment event for %s" - " rab_id=%hhd\n", subscr_name(conn->subscr), rab_id); - /* TODO do stuff like in sgsn_ranap_rab_ass_resp() */ + LOGP(DIUCS, LOGL_NOTICE, + "Received RAB assignment event for %s rab_id=%hhd\n", + vlr_subscr_name(conn->vsub), rab_id); return 0; } @@ -56,13 +57,13 @@ int iucs_rx_sec_mode_compl(struct gsm_subscriber_connection *conn, { gsm_cbfn *cb; - OSMO_ASSERT(conn->via_iface == IFACE_IU); + OSMO_ASSERT(conn->via_ran == RAN_UTRAN_IU); if (!conn->sec_operation) { LOGP(DIUCS, LOGL_ERROR, "Received Security Mode Complete message, but no" " authentication/cipher operation in progress" - " for subscr %s\n", subscr_name(conn->subscr)); + " for subscr %s\n", vlr_subscr_name(conn->vsub)); return -EINVAL; } @@ -71,7 +72,7 @@ int iucs_rx_sec_mode_compl(struct gsm_subscriber_connection *conn, if (conn->iu.integrity_protection) LOGP(DIUCS, LOGL_NOTICE, "Integrity Protection" " was already enabled for %s\n", - subscr_name(conn->subscr)); + vlr_subscr_name(conn->vsub)); conn->iu.integrity_protection = INTEGRITY_PROTECTION_IK; @@ -99,13 +100,13 @@ int iucs_rx_ranap_event(struct gsm_network *network, case IU_EVENT_IU_RELEASE: case IU_EVENT_LINK_INVALIDATED: LOGP(DIUCS, LOGL_INFO, "IuCS release for %s\n", - subscr_name(conn->subscr)); + vlr_subscr_name(conn->vsub)); gsm0408_clear_request(conn, 0); return 0; case IU_EVENT_SECURITY_MODE_COMPLETE: LOGP(DIUCS, LOGL_INFO, "IuCS security mode complete for %s\n", - subscr_name(conn->subscr)); + vlr_subscr_name(conn->vsub)); return iucs_rx_sec_mode_compl(conn, (RANAP_SecurityModeCompleteIEs_t*)data); case IU_EVENT_RAB_ASSIGN: diff --git a/openbsc/src/osmo-msc/msc_main.c b/openbsc/src/osmo-msc/msc_main.c index 9d3efd702..f4b3b363b 100644 --- a/openbsc/src/osmo-msc/msc_main.c +++ b/openbsc/src/osmo-msc/msc_main.c @@ -260,10 +260,6 @@ void msc_network_shutdown(struct gsm_network *net) static struct gsm_network *msc_network = NULL; -/* TODO this is here to satisfy linking during intermediate development. Once - * libbsc is not linked to osmo-msc, this should go away. */ -struct gsm_network *bsc_gsmnet = NULL; - extern void *tall_vty_ctx; static void signal_handler(int signal) { @@ -305,12 +301,6 @@ static void db_sync_timer_cb(void *data) osmo_timer_schedule(&db_sync_timer, DB_SYNC_INTERVAL); } -static void subscr_expire_cb(void *data) -{ - /* TODO expire vlr_subscrs? */ - osmo_timer_schedule(&bsc_gsmnet->subscr_expire_timer, EXPIRE_INTERVAL); -} - extern int bsc_vty_go_parent(struct vty *vty); static struct vty_app_info msc_vty_info = { @@ -370,6 +360,11 @@ int main(int argc, char **argv) if (!msc_network) return -ENOMEM; + if (msc_vlr_alloc(msc_network)) { + fprintf(stderr, "Failed to allocate VLR\n"); + exit(1); + } + ctrl_vty_init(tall_msc_ctx); logging_vty_add_cmds(&log_info); msc_vty_init(msc_network); @@ -426,7 +421,7 @@ int main(int argc, char **argv) * A third-party MSC may well be able to handle a TCH/H TCH/F * mismatch. */ - bsc_gsmnet->dyn_ts_allow_tch_f = false; + msc_network->dyn_ts_allow_tch_f = false; /* start control interface after reading config for * ctrl_vty_get_bind_addr() */ @@ -448,7 +443,7 @@ TODO: we probably want some of the _net_ ctrl commands from bsc_base_ctrl_cmds_i #endif #if 0 - if (msc_ctrl_cmds_install(bsc_gsmnet) != 0) { + if (msc_ctrl_cmds_install(msc_network) != 0) { printf("Failed to initialize the MSC control commands.\n"); return -1; } @@ -466,19 +461,13 @@ TODO: we probably want some of the _net_ ctrl commands from bsc_base_ctrl_cmds_i } osmo_fsm_log_addr(true); - if (msc_vlr_start(bsc_gsmnet)) { + if (msc_vlr_start(msc_network)) { fprintf(stderr, "Failed to start VLR\n"); exit(1); } msc_subscr_conn_init(); - if (db_init(database_name)) { - printf("DB: Failed to init database. Please check the option settings.\n"); - return -1; - } - printf("DB: Database initialized.\n"); - if (db_prepare()) { printf("DB: Failed to prepare database.\n"); return 5; @@ -489,10 +478,6 @@ TODO: we probably want some of the _net_ ctrl commands from bsc_base_ctrl_cmds_i if (msc_cmdline_config.use_db_counter) osmo_timer_schedule(&db_sync_timer, DB_SYNC_INTERVAL); - msc_network->subscr_expire_timer.cb = subscr_expire_cb; - msc_network->subscr_expire_timer.data = NULL; - osmo_timer_schedule(&msc_network->subscr_expire_timer, EXPIRE_INTERVAL); - signal(SIGINT, &signal_handler); signal(SIGABRT, &signal_handler); signal(SIGUSR1, &signal_handler); |