Change in osmo-msc[master]: implement CM Re-Establish for voice calls

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

laforge gerrit-no-reply at lists.osmocom.org
Mon Aug 2 09:15:45 UTC 2021


laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-msc/+/25076 )

Change subject: implement CM Re-Establish for voice calls
......................................................................

implement CM Re-Establish for voice calls

Related: SYS#5130
Change-Id: I6fa37d6ca9fcb1637742b40e37b68d67664c9b60
---
M include/osmocom/msc/gsm_data.h
M include/osmocom/msc/msc_common.h
M include/osmocom/msc/vlr.h
M src/libmsc/gsm_04_08.c
M src/libmsc/msc_a.c
5 files changed, 136 insertions(+), 2 deletions(-)

Approvals:
  Jenkins Builder: Verified
  pespin: Looks good to me, but someone else must approve
  osmith: Looks good to me, but someone else must approve
  laforge: Looks good to me, approved



diff --git a/include/osmocom/msc/gsm_data.h b/include/osmocom/msc/gsm_data.h
index 1870804..170d884 100644
--- a/include/osmocom/msc/gsm_data.h
+++ b/include/osmocom/msc/gsm_data.h
@@ -44,6 +44,8 @@
 	MSC_CTR_CM_SERVICE_REQUEST_ACCEPTED,
 	MSC_CTR_PAGING_RESP_REJECTED,
 	MSC_CTR_PAGING_RESP_ACCEPTED,
+	MSC_CTR_CM_RE_ESTABLISH_REQ_REJECTED,
+	MSC_CTR_CM_RE_ESTABLISH_REQ_ACCEPTED,
 	MSC_CTR_SMS_SUBMITTED,
 	MSC_CTR_SMS_NO_RECEIVER,
 	MSC_CTR_SMS_DELIVERED,
@@ -76,6 +78,8 @@
 	[MSC_CTR_CM_SERVICE_REQUEST_ACCEPTED] = {"cm_service_request:accepted", "Accepted CM Service Requests."},
 	[MSC_CTR_PAGING_RESP_REJECTED] = 	{"paging_resp:rejected", "Rejected Paging Responses."},
 	[MSC_CTR_PAGING_RESP_ACCEPTED] = 	{"paging_resp:accepted", "Accepted Paging Responses."},
+	[MSC_CTR_CM_RE_ESTABLISH_REQ_REJECTED] = {"cm_re_establish_request:rejected", "Rejected CM Re-Establishing Requests."},
+	[MSC_CTR_CM_RE_ESTABLISH_REQ_ACCEPTED] = {"cm_re_establish_request:accepted", "Accepted CM Re-Establishing Requests."},
 	[MSC_CTR_SMS_SUBMITTED] = 		{"sms:submitted", "Total MO SMS received from the MS."},
 	[MSC_CTR_SMS_NO_RECEIVER] = 		{"sms:no_receiver", "Failed MO SMS delivery attempts (no receiver found)."},
 	[MSC_CTR_SMS_DELIVER_UNKNOWN_ERROR] =	{"sms:deliver_unknown_error", "Failed MO SMS delivery attempts (other reason)."},
diff --git a/include/osmocom/msc/msc_common.h b/include/osmocom/msc/msc_common.h
index e7ac559..f3fb0e0 100644
--- a/include/osmocom/msc/msc_common.h
+++ b/include/osmocom/msc/msc_common.h
@@ -41,6 +41,7 @@
 	COMPLETE_LAYER3_LU,
 	COMPLETE_LAYER3_CM_SERVICE_REQ,
 	COMPLETE_LAYER3_PAGING_RESP,
+	COMPLETE_LAYER3_CM_RE_ESTABLISH_REQ,
 };
 
 extern const struct value_string complete_layer3_type_names[];
diff --git a/include/osmocom/msc/vlr.h b/include/osmocom/msc/vlr.h
index 3273333..f12e906 100644
--- a/include/osmocom/msc/vlr.h
+++ b/include/osmocom/msc/vlr.h
@@ -444,6 +444,7 @@
 	VLR_PR_ARQ_T_INVALID = 0, /* to guard against unset vars */
 	VLR_PR_ARQ_T_CM_SERV_REQ,
 	VLR_PR_ARQ_T_PAGING_RESP,
+	VLR_PR_ARQ_T_CM_RE_ESTABLISH_REQ,
 	/* FIXME: differentiate between services of 24.008 10.5.3.3 */
 };
 
diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c
index fb450e6..565e7ad 100644
--- a/src/libmsc/gsm_04_08.c
+++ b/src/libmsc/gsm_04_08.c
@@ -48,11 +48,13 @@
 #include <osmocom/core/talloc.h>
 #include <osmocom/core/utils.h>
 #include <osmocom/core/byteswap.h>
+#include <osmocom/core/fsm.h>
 #include <osmocom/gsm/tlv.h>
 #include <osmocom/crypt/auth.h>
 
 #include <osmocom/msc/msub.h>
 #include <osmocom/msc/msc_roles.h>
+#include <osmocom/msc/call_leg.h>
 
 #include <assert.h>
 
@@ -824,17 +826,128 @@
 /* Receive a CM Re-establish Request */
 static int gsm48_rx_cm_reest_req(struct msc_a *msc_a, struct msgb *msg)
 {
+	struct gsm_network *net = msc_a_net(msc_a);
+	struct gsm48_hdr *gh;
+	struct gsm48_service_request *req;
+	struct gsm48_classmark2 *cm2;
+	uint8_t *cm2_buf, cm2_len;
+	bool is_utran;
+	struct vlr_subscr *vsub;
 	struct osmo_mobile_identity mi;
+	struct msub *prev_msub;
+	struct msc_a *prev_msc_a;
+
 	int rc = osmo_mobile_identity_decode_from_l3(&mi, msg, false);
 	if (rc) {
 		LOGP(DMM, LOGL_ERROR, "CM RE-ESTABLISH REQUEST: cannot decode Mobile Identity\n");
 		return -EINVAL;
 	}
 
+	msc_a->complete_layer3_type = COMPLETE_LAYER3_CM_RE_ESTABLISH_REQ;
+	msub_update_id_from_mi(msc_a->c.msub, &mi);
+
 	DEBUGP(DMM, "<- CM RE-ESTABLISH REQUEST %s\n", osmo_mobile_identity_to_str_c(OTC_SELECT, &mi));
 
-	/* we don't support CM call re-establishment */
-	return msc_gsm48_tx_mm_serv_rej(msc_a, GSM48_REJECT_SRV_OPT_NOT_SUPPORTED);
+	gh = (struct gsm48_hdr *) msgb_l3(msg);
+	req = (struct gsm48_service_request *) gh->data;
+
+	/* Unfortunately in Phase1 the Classmark2 length is variable, so we cannot
+	 * just use gsm48_service_request struct, and need to parse it manually. */
+	cm2_len = gh->data[1];
+	cm2_buf = gh->data + 2;
+	cm2 = (struct gsm48_classmark2 *) cm2_buf;
+
+	/* Prevent buffer overrun: check the length of Classmark2 */
+	if (cm2_buf + cm2_len > msg->tail) {
+		LOG_MSC_A(msc_a, LOGL_ERROR, "Rx CM SERVICE REQUEST: Classmark2 "
+					     "length=%u is too big\n", cm2_len);
+		return msc_gsm48_tx_mm_serv_rej(msc_a, GSM48_REJECT_INCORRECT_MESSAGE);
+	}
+
+	/* Look up the other, previously active connection for this subscriber */
+	vsub = vlr_subscr_find_by_mi(net->vlr, &mi, __func__);
+	prev_msub = msub_for_vsub(vsub);
+	prev_msc_a = msub_msc_a(prev_msub);
+	if (!vsub || !prev_msub || !prev_msc_a) {
+		LOG_MSC_A(msc_a, LOGL_ERROR, "CM Re-Establish Request for unknown subscriber: %s\n",
+			  osmo_mobile_identity_to_str_c(OTC_SELECT, &mi));
+		if (vsub)
+			vlr_subscr_put(vsub, __func__);
+		return msc_gsm48_tx_mm_serv_rej(msc_a, GSM48_REJECT_CALL_CAN_NOT_BE_IDENTIFIED);
+	}
+
+	LOG_MSC_A(msc_a, LOGL_NOTICE, "New conn requesting Re-Establishment\n");
+	LOG_MSC_A(prev_msc_a, LOGL_NOTICE, "Old conn matching Re-Establishment request (%s)\n",
+		  osmo_use_count_to_str_c(OTC_SELECT, &prev_msc_a->use_count));
+
+	if (!prev_msc_a->cc.call_leg || !prev_msc_a->cc.active_trans) {
+		LOG_MSC_A(msc_a, LOGL_ERROR, "CM Re-Establish Request only supported for voice calls\n");
+		if (vsub)
+			vlr_subscr_put(vsub, __func__);
+		return msc_gsm48_tx_mm_serv_rej(msc_a, GSM48_REJECT_CALL_CAN_NOT_BE_IDENTIFIED);
+	}
+
+	msc_a_get(prev_msc_a, __func__);
+
+	/* Move the call_leg and active CC trans over to the new msc_a */
+	call_leg_reparent(prev_msc_a->cc.call_leg,
+			  msc_a->c.fi,
+			  MSC_EV_CALL_LEG_TERM,
+			  MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE,
+			  MSC_EV_CALL_LEG_RTP_COMPLETE);
+	msc_a->cc.call_leg = prev_msc_a->cc.call_leg;
+	prev_msc_a->cc.call_leg = NULL;
+
+	msc_a->cc.active_trans = prev_msc_a->cc.active_trans;
+	msc_a->cc.active_trans->msc_a = msc_a;
+	msc_a_get(msc_a, MSC_A_USE_CC);
+	prev_msc_a->cc.active_trans = NULL;
+	msc_a_put(prev_msc_a, MSC_A_USE_CC);
+
+	/* Dis-associate the VLR subscriber from the previous msc_a, so that we can start a new Process Access Request
+	 * on the new msc_a. */
+	if (vsub->proc_arq_fsm) {
+		osmo_fsm_inst_term(vsub->proc_arq_fsm, OSMO_FSM_TERM_REGULAR, NULL);
+		vsub->proc_arq_fsm = NULL;
+	}
+	if (prev_msub->vsub) {
+		vlr_subscr_put(prev_msub->vsub, VSUB_USE_MSUB);
+		prev_msub->vsub = NULL;
+	}
+
+	/* Clear the previous conn.
+	 * FIXME: we are clearing the previous conn before having authenticated the new conn. That means anyone can send
+	 * CM Re-Establishing requests with arbitrary mobile identities without having to authenticate, and can freely
+	 * Clear any connections at will. */
+	msc_a_release_cn(prev_msc_a);
+	msc_a_put(prev_msc_a, __func__);
+	prev_msc_a = NULL;
+
+	/* Kick off Authentication and Ciphering for the new conn. */
+	is_utran = (msc_a->c.ran->type == OSMO_RAT_UTRAN_IU);
+	vlr_proc_acc_req(msc_a->c.fi,
+			 MSC_A_EV_AUTHENTICATED, MSC_A_EV_CN_CLOSE, NULL,
+			 net->vlr, msc_a,
+			 VLR_PR_ARQ_T_CM_RE_ESTABLISH_REQ, 0,
+			 &mi, &msc_a->via_cell.lai,
+			 is_utran || net->authentication_required,
+			 is_utran ? net->uea_encryption : net->a5_encryption_mask > 0x01,
+			 req->cipher_key_seq,
+			 osmo_gsm48_classmark2_is_r99(cm2, cm2_len),
+			 is_utran);
+	vlr_subscr_put(vsub, __func__);
+
+	/* From vlr_proc_acc_req() we expect an implicit dispatch of PR_ARQ_E_START, and we expect
+	 * msc_vlr_subscr_assoc() to already have been called and completed. Has an error occurred? */
+	vsub = msc_a_vsub(msc_a);
+	if (!vsub) {
+		LOG_MSC_A(msc_a, LOGL_ERROR, "subscriber not allowed to do a CM Service Request\n");
+		return -EIO;
+	}
+
+	vsub->classmark.classmark2 = *cm2;
+	vsub->classmark.classmark2_len = cm2_len;
+	return 0;
 }
 
 static int gsm48_rx_mm_imsi_detach_ind(struct msc_a *msc_a, struct msgb *msg)
diff --git a/src/libmsc/msc_a.c b/src/libmsc/msc_a.c
index 0bc7b26..fa8e842 100644
--- a/src/libmsc/msc_a.c
+++ b/src/libmsc/msc_a.c
@@ -120,6 +120,11 @@
 	case COMPLETE_LAYER3_PAGING_RESP:
 		rate_ctr_inc(rate_ctr_group_get_ctr(net->msc_ctrs, conn_accepted ? MSC_CTR_PAGING_RESP_ACCEPTED : MSC_CTR_PAGING_RESP_REJECTED));
 		break;
+	case COMPLETE_LAYER3_CM_RE_ESTABLISH_REQ:
+		rate_ctr_inc(rate_ctr_group_get_ctr(net->msc_ctrs,
+						    conn_accepted ? MSC_CTR_CM_RE_ESTABLISH_REQ_ACCEPTED
+								  : MSC_CTR_CM_RE_ESTABLISH_REQ_REJECTED));
+		break;
 	default:
 		break;
 	}
@@ -151,6 +156,15 @@
 
 	if (msc_a->complete_layer3_type == COMPLETE_LAYER3_LU)
 		msc_a_put(msc_a, MSC_A_USE_LOCATION_UPDATING);
+
+	if (msc_a->complete_layer3_type == COMPLETE_LAYER3_CM_RE_ESTABLISH_REQ) {
+		/* Trigger new Assignment to recommence the voice call. A little dance here because normally we verify
+		 * that no CC trans is already active. */
+		struct gsm_trans *cc_trans = msc_a->cc.active_trans;
+		msc_a->cc.active_trans = NULL;
+		osmo_fsm_inst_dispatch(msc_a->c.fi, MSC_A_EV_TRANSACTION_ACCEPTED, cc_trans);
+		msc_a_try_call_assignment(cc_trans);
+	}
 }
 
 bool msc_a_is_accepted(const struct msc_a *msc_a)
@@ -1092,6 +1106,7 @@
 	{ COMPLETE_LAYER3_LU, "LU" },
 	{ COMPLETE_LAYER3_CM_SERVICE_REQ, "CM_SERVICE_REQ" },
 	{ COMPLETE_LAYER3_PAGING_RESP, "PAGING_RESP" },
+	{ COMPLETE_LAYER3_CM_RE_ESTABLISH_REQ, "CM_RE_ESTABLISH_REQ" },
 	{ 0, NULL }
 };
 

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-msc/+/25076
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Change-Id: I6fa37d6ca9fcb1637742b40e37b68d67664c9b60
Gerrit-Change-Number: 25076
Gerrit-PatchSet: 5
Gerrit-Owner: neels <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: dexter <pmaier at sysmocom.de>
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: osmith <osmith at sysmocom.de>
Gerrit-Reviewer: pespin <pespin at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210802/c5b56de8/attachment.htm>


More information about the gerrit-log mailing list