aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/msc/gsm_data.h4
-rw-r--r--src/libmsc/gsm_04_08.c21
-rw-r--r--src/libmsc/osmo_msc.c7
3 files changed, 31 insertions, 1 deletions
diff --git a/include/osmocom/msc/gsm_data.h b/include/osmocom/msc/gsm_data.h
index 70ac93440..54026f697 100644
--- a/include/osmocom/msc/gsm_data.h
+++ b/include/osmocom/msc/gsm_data.h
@@ -181,6 +181,10 @@ struct gsm_subscriber_connection {
bool waiting_for_clear_complete;
} a;
+
+ /* Temporary storage for Classmark Information for times when a connection has no VLR subscriber
+ * associated yet. It will get copied to the VLR subscriber upon msc_vlr_subscr_assoc(). */
+ struct gsm_classmark temporary_classmark;
};
diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c
index 564e90bff..0f52d0939 100644
--- a/src/libmsc/gsm_04_08.c
+++ b/src/libmsc/gsm_04_08.c
@@ -1739,6 +1739,22 @@ static void msc_vlr_subscr_update(struct vlr_subscr *subscr)
subscr->imsi, subscr->msisdn, subscr->use_count);
}
+static void update_classmark(const struct gsm_classmark *src, struct gsm_classmark *dst)
+{
+ if (src->classmark1_set) {
+ dst->classmark1 = src->classmark1;
+ dst->classmark1_set = true;
+ }
+ if (src->classmark2_len) {
+ dst->classmark2_len = src->classmark2_len;
+ memcpy(dst->classmark2, src->classmark2, sizeof(dst->classmark2));
+ }
+ if (src->classmark3_len) {
+ dst->classmark3_len = src->classmark3_len;
+ memcpy(dst->classmark3, src->classmark3, sizeof(dst->classmark3));
+ }
+}
+
/* VLR informs us that the subscriber has been associated with a conn */
static void msc_vlr_subscr_assoc(void *msc_conn_ref,
struct vlr_subscr *vsub)
@@ -1749,6 +1765,11 @@ static void msc_vlr_subscr_assoc(void *msc_conn_ref,
conn->vsub = vlr_subscr_get(vsub);
OSMO_ASSERT(conn->vsub);
conn->vsub->cs.attached_via_ran = conn->via_ran;
+
+ /* In case we have already received Classmark Information before the VLR Subscriber was
+ * associated with the conn: merge the new Classmark into vsub->classmark. Don't overwrite valid
+ * vsub->classmark with unset classmark, though. */
+ update_classmark(&conn->temporary_classmark, &conn->vsub->classmark);
}
static int msc_vlr_route_gsup_msg(struct vlr_subscr *vsub,
diff --git a/src/libmsc/osmo_msc.c b/src/libmsc/osmo_msc.c
index 8efa16ced..3965e9b90 100644
--- a/src/libmsc/osmo_msc.c
+++ b/src/libmsc/osmo_msc.c
@@ -147,7 +147,12 @@ void msc_classmark_chg(struct gsm_subscriber_connection *conn,
const uint8_t *cm2, uint8_t cm2_len,
const uint8_t *cm3, uint8_t cm3_len)
{
- struct gsm_classmark *cm = &conn->vsub->classmark;
+ struct gsm_classmark *cm;
+
+ if (!conn->vsub)
+ cm = &conn->temporary_classmark;
+ else
+ cm = &conn->vsub->classmark;
if (cm2 && cm2_len) {
if (cm2_len > sizeof(cm->classmark2)) {