aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeels Hofmeyr <nhofmeyr@sysmocom.de>2017-03-10 02:14:00 +0100
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2017-03-16 15:32:34 +0100
commit33513ae19a8aa5a800813fe464b4c5b4a474eb91 (patch)
treec1d69c35199e1a47290f6bc3391adc70f13680b4
parentc1ebe963f44006fe8b60304dcceeb22c5d14c2e3 (diff)
allow CM Service Request on already open connection
-rw-r--r--openbsc/src/libmsc/gsm_04_08.c63
-rw-r--r--openbsc/tests/msc_vlr/msc_vlr_test_reject_concurrency.c28
2 files changed, 78 insertions, 13 deletions
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index 68ac3cf86..8b7d3bdd1 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -598,6 +598,49 @@ int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn)
return gsm48_tx_simple(conn, GSM48_PDISC_MM, GSM48_MT_MM_AUTH_REJ);
}
+#define CONN_REUSE 1
+#if CONN_REUSE
+static int msc_vlr_tx_cm_serv_acc(void *msc_conn_ref);
+static int msc_vlr_tx_cm_serv_rej(void *msc_conn_ref, enum vlr_proc_arq_result result);
+
+int cm_serv_conn_reuse(struct gsm_subscriber_connection *conn,
+ const uint8_t *mi_lv)
+{
+ struct vlr_subscr *vsub;
+ uint8_t mi_type;
+ char mi_string[GSM48_MI_SIZE];
+ uint32_t tmsi;
+
+ gsm48_mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, mi_lv[0]);
+ mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
+
+ switch (mi_type) {
+ case GSM_MI_TYPE_IMSI:
+ vsub = vlr_subscr_find_by_imsi(conn->network->vlr, mi_string);
+ break;
+ case GSM_MI_TYPE_TMSI:
+ tmsi = osmo_load32be(mi_lv+2);
+ vsub = vlr_subscr_find_by_tmsi(conn->network->vlr, tmsi);
+ break;
+ case GSM_MI_TYPE_IMEI:
+ /* TODO: IMEI (emergency call) */
+ default:
+ vsub = NULL;
+ break;
+ }
+
+ if (!vsub) {
+ msc_vlr_tx_cm_serv_rej(conn, VLR_PR_ARQ_RES_ILLEGAL_SUBSCR);
+ return -EINVAL;
+ }
+
+ DEBUGP(DMM, "%s: re-using already accepted connection\n",
+ vlr_subscr_name(vsub));
+ conn->received_cm_service_request = true;
+ return conn->network->vlr->ops.tx_cm_serv_acc(conn);
+}
+#endif
+
/*
* Handle CM Service Requests
* a) Verify that the packet is long enough to contain the information
@@ -664,14 +707,26 @@ int gsm48_rx_mm_serv_req(struct gsm_subscriber_connection *conn, struct msgb *ms
}
osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_IDENTITY, (classmark2 + classmark2_len));
+ memcpy(conn->classmark.classmark2, classmark2, classmark2_len);
+ conn->classmark.classmark2_len = classmark2_len;
+
+#if CONN_REUSE
+ if (conn->conn_fsm) {
+ if (msc_subscr_conn_is_accepted(conn))
+ return cm_serv_conn_reuse(conn, mi-1);
+ LOGP(DMM, LOGL_ERROR, "%s: connection already in use\n",
+ vlr_subscr_name(conn->vsub));
+ msc_vlr_tx_cm_serv_rej(conn, VLR_PR_ARQ_RES_UNKNOWN_ERROR);
+ return -EINVAL;
+ }
+#endif
rc = msc_create_conn_fsm(conn, mi_string);
- if (rc)
+ if (rc) {
+ msc_vlr_tx_cm_serv_rej(conn, VLR_PR_ARQ_RES_UNKNOWN_ERROR);
/* logging already happened in msc_create_conn_fsm() */
return rc;
-
- memcpy(conn->classmark.classmark2, classmark2, classmark2_len);
- conn->classmark.classmark2_len = classmark2_len;
+ }
#if BEFORE_MSCSPLIT
/* see mail on openbsc@ 9 Feb 2016 22:30:15 +0100
diff --git a/openbsc/tests/msc_vlr/msc_vlr_test_reject_concurrency.c b/openbsc/tests/msc_vlr/msc_vlr_test_reject_concurrency.c
index 52757fea4..bace73ba3 100644
--- a/openbsc/tests/msc_vlr/msc_vlr_test_reject_concurrency.c
+++ b/openbsc/tests/msc_vlr/msc_vlr_test_reject_concurrency.c
@@ -164,7 +164,7 @@ void _paging_resp_part1()
EXPECT_CONN_COUNT(1);
}
-void _paging_resp_part2()
+void _paging_resp_part2(int expect_conn_count)
{
btw("MS replies with CP-ACK for received SMS");
ms_sends_msg("8904");
@@ -175,8 +175,8 @@ void _paging_resp_part2()
ms_sends_msg("890106020041020000");
VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
- btw("SMS is done, conn is gone");
- EXPECT_CONN_COUNT(0);
+ btw("SMS is done");
+ EXPECT_CONN_COUNT(expect_conn_count);
}
void test_reject_lu_during_lu()
@@ -242,10 +242,15 @@ void test_reject_lu_during_cm()
_normal_lu();
_normal_cm_service_req();
- btw("An erratic LU request on the same conn results in conn termination");
+ btw("A LU request on an open conn is dropped silently");
+ /* TODO: accept periodic LU on an already open conn? */
lu_result_sent = RES_NONE;
ms_sends_msg("050802008168000130089910070000006402");
VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
+ EXPECT_CONN_COUNT(1);
+
+ BTW("subscriber detaches");
+ ms_sends_msg("050130089910070000006402");
EXPECT_CONN_COUNT(0);
clear_vlr();
@@ -303,7 +308,7 @@ void test_reject_paging_resp_during_paging_resp()
BTW("MS sends another erratic Paging Response which is dropped silently");
ms_sends_msg("06270703305882089910070000006402");
- _paging_resp_part2();
+ _paging_resp_part2(0);
clear_vlr();
comment_end();
@@ -323,7 +328,7 @@ void test_reject_lu_during_paging_resp()
VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
EXPECT_CONN_COUNT(1);
- _paging_resp_part2();
+ _paging_resp_part2(0);
clear_vlr();
comment_end();
@@ -337,13 +342,18 @@ void test_reject_cm_during_paging_resp()
_page();
_paging_resp_part1();
- BTW("MS sends erratic CM Service Request, which is dropped silently");
+ BTW("CM Service Request during open connection is accepted");
cm_service_result_sent = RES_NONE;
ms_sends_msg("05247803305886089910070000006402");
- VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
+ VERBOSE_ASSERT(cm_service_result_sent, == RES_ACCEPT, "%d");
EXPECT_CONN_COUNT(1);
+ VERBOSE_ASSERT(g_conn->received_cm_service_request, == true, "%d");
+
+ _paging_resp_part2(1);
- _paging_resp_part2();
+ BTW("subscriber detaches");
+ ms_sends_msg("050130089910070000006402");
+ EXPECT_CONN_COUNT(0);
clear_vlr();
comment_end();