aboutsummaryrefslogtreecommitdiffstats
path: root/src/libmsc/subscr_conn.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libmsc/subscr_conn.c')
-rw-r--r--src/libmsc/subscr_conn.c74
1 files changed, 73 insertions, 1 deletions
diff --git a/src/libmsc/subscr_conn.c b/src/libmsc/subscr_conn.c
index 2040e369b..e6fa7e11f 100644
--- a/src/libmsc/subscr_conn.c
+++ b/src/libmsc/subscr_conn.c
@@ -45,6 +45,7 @@
static const struct value_string subscr_conn_fsm_event_names[] = {
OSMO_VALUE_STRING(SUBSCR_CONN_E_INVALID),
OSMO_VALUE_STRING(SUBSCR_CONN_E_COMPLETE_LAYER_3),
+ OSMO_VALUE_STRING(SUBSCR_CONN_E_CLASSMARK_UPDATE),
OSMO_VALUE_STRING(SUBSCR_CONN_E_ACCEPTED),
OSMO_VALUE_STRING(SUBSCR_CONN_E_COMMUNICATING),
OSMO_VALUE_STRING(SUBSCR_CONN_E_RELEASE_WHEN_UNUSED),
@@ -163,6 +164,66 @@ void subscr_conn_fsm_auth_ciph(struct osmo_fsm_inst *fi, uint32_t event, void *d
}
}
+int msc_classmark_request_then_cipher_mode_cmd(struct gsm_subscriber_connection *conn, bool umts_aka,
+ bool retrieve_imeisv)
+{
+ int rc;
+ conn->geran_set_cipher_mode.umts_aka = umts_aka;
+ conn->geran_set_cipher_mode.retrieve_imeisv = retrieve_imeisv;
+
+ rc = a_iface_tx_classmark_request(conn);
+ if (rc) {
+ LOGP(DMM, LOGL_ERROR, "%s: cannot send BSSMAP Classmark Request\n",
+ vlr_subscr_name(conn->vsub));
+ return -EIO;
+ }
+
+ osmo_fsm_inst_state_chg(conn->fi, SUBSCR_CONN_S_WAIT_CLASSMARK_UPDATE, SUBSCR_CONN_TIMEOUT, 0);
+ return 0;
+}
+
+static void subscr_conn_fsm_wait_classmark_update(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct gsm_subscriber_connection *conn = fi->priv;
+ switch (event) {
+ case SUBSCR_CONN_E_CLASSMARK_UPDATE:
+ /* Theoretically, this event can be used for requesting Classmark in various situations.
+ * So far though, the only time we send a Classmark Request is during Ciphering. As soon
+ * as more such situations arise, we need to add state to indicate what action should
+ * follow after a Classmark Update is received (e.g.
+ * msc_classmark_request_then_cipher_mode_cmd() sets an enum value to indicate that
+ * Ciphering should continue afterwards). But right now, it is accurate to always
+ * continue with Ciphering: */
+
+ /* During Ciphering, we needed Classmark information. The Classmark Update has come in,
+ * go back into the Set Ciphering Command procedure. */
+ osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_AUTH_CIPH, SUBSCR_CONN_TIMEOUT, 0);
+ if (msc_geran_set_cipher_mode(conn, conn->geran_set_cipher_mode.umts_aka,
+ conn->geran_set_cipher_mode.retrieve_imeisv)) {
+ LOGPFSML(fi, LOGL_ERROR,
+ "Sending Cipher Mode Command failed, aborting attach\n");
+ vlr_subscr_cancel_attach_fsm(conn->vsub, OSMO_FSM_TERM_ERROR,
+ GSM48_REJECT_NETWORK_FAILURE);
+ }
+ return;
+
+ case SUBSCR_CONN_E_UNUSED:
+ LOGPFSML(fi, LOGL_DEBUG, "Awaiting results for Auth+Ciph, overruling event %s\n",
+ osmo_fsm_event_name(fi->fsm, event));
+ return;
+
+ case SUBSCR_CONN_E_MO_CLOSE:
+ case SUBSCR_CONN_E_CN_CLOSE:
+ log_close_event(fi, event, data);
+ evaluate_acceptance_outcome(fi, false);
+ osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_RELEASING, SUBSCR_CONN_TIMEOUT, 0);
+ return;
+
+ default:
+ OSMO_ASSERT(false);
+ }
+}
+
static bool subscr_conn_fsm_has_active_transactions(struct osmo_fsm_inst *fi)
{
struct gsm_subscriber_connection *conn = fi->priv;
@@ -362,10 +423,21 @@ static const struct osmo_fsm_state subscr_conn_fsm_states[] = {
S(SUBSCR_CONN_E_MO_CLOSE) |
S(SUBSCR_CONN_E_CN_CLOSE) |
S(SUBSCR_CONN_E_UNUSED),
- .out_state_mask = S(SUBSCR_CONN_S_ACCEPTED) |
+ .out_state_mask = S(SUBSCR_CONN_S_WAIT_CLASSMARK_UPDATE) |
+ S(SUBSCR_CONN_S_ACCEPTED) |
S(SUBSCR_CONN_S_RELEASING),
.action = subscr_conn_fsm_auth_ciph,
},
+ [SUBSCR_CONN_S_WAIT_CLASSMARK_UPDATE] = {
+ .name = OSMO_STRINGIFY(SUBSCR_CONN_S_WAIT_CLASSMARK_UPDATE),
+ .in_event_mask = S(SUBSCR_CONN_E_CLASSMARK_UPDATE) |
+ S(SUBSCR_CONN_E_MO_CLOSE) |
+ S(SUBSCR_CONN_E_CN_CLOSE) |
+ S(SUBSCR_CONN_E_UNUSED),
+ .out_state_mask = S(SUBSCR_CONN_S_AUTH_CIPH) |
+ S(SUBSCR_CONN_S_RELEASING),
+ .action = subscr_conn_fsm_wait_classmark_update,
+ },
[SUBSCR_CONN_S_ACCEPTED] = {
.name = OSMO_STRINGIFY(SUBSCR_CONN_S_ACCEPTED),
/* allow everything to release for any odd behavior */