aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/bsc_api.h4
-rw-r--r--openbsc/src/libbsc/bsc_api.c42
-rw-r--r--openbsc/src/libmsc/gsm_04_08.c50
-rw-r--r--openbsc/src/libmsc/osmo_msc.c21
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_api.c14
5 files changed, 81 insertions, 50 deletions
diff --git a/openbsc/include/openbsc/bsc_api.h b/openbsc/include/openbsc/bsc_api.h
index ae700ee68..910ce9e00 100644
--- a/openbsc/include/openbsc/bsc_api.h
+++ b/openbsc/include/openbsc/bsc_api.h
@@ -30,6 +30,10 @@ struct bsc_api {
/*! \brief BSC->MSC: RR conn has been cleared */
int (*clear_request)(struct gsm_subscriber_connection *conn,
uint32_t cause);
+ /*! \brief BSC->MSC: Classmark Update */
+ void (*classmark_chg)(struct gsm_subscriber_connection *conn,
+ const uint8_t *cm2, uint8_t cm2_len,
+ const uint8_t *cm3, uint8_t cm3_len);
};
int bsc_api_init(struct gsm_network *network, struct bsc_api *api);
diff --git a/openbsc/src/libbsc/bsc_api.c b/openbsc/src/libbsc/bsc_api.c
index ad4391d1a..bb1374776 100644
--- a/openbsc/src/libbsc/bsc_api.c
+++ b/openbsc/src/libbsc/bsc_api.c
@@ -418,6 +418,44 @@ static void handle_ass_fail(struct gsm_subscriber_connection *conn,
rr_failure);
}
+static void handle_classmark_chg(struct gsm_subscriber_connection *conn,
+ struct msgb *msg)
+{
+ struct bsc_api *api = msg->lchan->ts->trx->bts->network->bsc_api;
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
+ uint8_t cm2_len, cm3_len = 0;
+ uint8_t *cm2, *cm3 = NULL;
+
+ DEBUGP(DRR, "CLASSMARK CHANGE ");
+
+ /* classmark 2 */
+ cm2_len = gh->data[0];
+ cm2 = &gh->data[1];
+ DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
+
+ if (payload_len > cm2_len + 1) {
+ /* we must have a classmark3 */
+ if (gh->data[cm2_len+1] != 0x20) {
+ DEBUGPC(DRR, "ERR CM3 TAG\n");
+ return -EINVAL;
+ }
+ if (cm2_len > 3) {
+ DEBUGPC(DRR, "CM2 too long!\n");
+ return -EINVAL;
+ }
+
+ cm3_len = gh->data[cm2_len+2];
+ cm3 = &gh->data[cm2_len+3];
+ if (cm3_len > 14) {
+ DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
+ return -EINVAL;
+ }
+ DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
+ }
+ api->classmark_chg(conn, cm2, cm2_len, cm3, cm3_len);
+}
+
static void dispatch_dtap(struct gsm_subscriber_connection *conn,
uint8_t link_id, struct msgb *msg)
{
@@ -462,6 +500,10 @@ static void dispatch_dtap(struct gsm_subscriber_connection *conn,
}
return;
break;
+ case GSM48_MT_RR_CLSM_CHG:
+ handle_classmark_chg(conn, msg);
+ return;
+ break;
}
break;
case GSM48_PDISC_MM:
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index 7c0d62895..a2a49aa9a 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -1101,53 +1101,6 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m
return rc;
}
-static int gsm48_rx_rr_classmark(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
- struct gsm48_hdr *gh = msgb_l3(msg);
- struct gsm_subscriber *subscr = conn->subscr;
- unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
- uint8_t cm2_len, cm3_len = 0;
- uint8_t *cm2, *cm3 = NULL;
-
- DEBUGP(DRR, "CLASSMARK CHANGE ");
-
- /* classmark 2 */
- cm2_len = gh->data[0];
- cm2 = &gh->data[1];
- DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
-
- if (payload_len > cm2_len + 1) {
- /* we must have a classmark3 */
- if (gh->data[cm2_len+1] != 0x20) {
- DEBUGPC(DRR, "ERR CM3 TAG\n");
- return -EINVAL;
- }
- if (cm2_len > 3) {
- DEBUGPC(DRR, "CM2 too long!\n");
- return -EINVAL;
- }
-
- cm3_len = gh->data[cm2_len+2];
- cm3 = &gh->data[cm2_len+3];
- if (cm3_len > 14) {
- DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
- return -EINVAL;
- }
- DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
- }
- if (subscr) {
- subscr->equipment.classmark2_len = cm2_len;
- memcpy(subscr->equipment.classmark2, cm2, cm2_len);
- if (cm3) {
- subscr->equipment.classmark3_len = cm3_len;
- memcpy(subscr->equipment.classmark3, cm3, cm3_len);
- }
- db_sync_equipment(&subscr->equipment);
- }
-
- return 0;
-}
-
static int gsm48_rx_rr_status(struct msgb *msg)
{
struct gsm48_hdr *gh = msgb_l3(msg);
@@ -1258,9 +1211,6 @@ static int gsm0408_rcv_rr(struct gsm_subscriber_connection *conn, struct msgb *m
int rc = 0;
switch (gh->msg_type) {
- case GSM48_MT_RR_CLSM_CHG:
- rc = gsm48_rx_rr_classmark(conn, msg);
- break;
case GSM48_MT_RR_GPRS_SUSP_REQ:
DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
break;
diff --git a/openbsc/src/libmsc/osmo_msc.c b/openbsc/src/libmsc/osmo_msc.c
index 154386b13..121de679c 100644
--- a/openbsc/src/libmsc/osmo_msc.c
+++ b/openbsc/src/libmsc/osmo_msc.c
@@ -24,6 +24,7 @@
#include <openbsc/bsc_api.h>
#include <openbsc/debug.h>
#include <openbsc/transaction.h>
+#include <openbsc/db.h>
#include <openbsc/gsm_04_11.h>
@@ -83,6 +84,25 @@ static void msc_assign_fail(struct gsm_subscriber_connection *conn,
"Assignment fail should not have been reached.\n");
}
+static 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_subscriber *subscr = conn->subscr;
+
+ if (subscr) {
+ subscr->equipment.classmark2_len = cm2_len;
+ memcpy(subscr->equipment.classmark2, cm2, cm2_len);
+ if (cm3) {
+ subscr->equipment.classmark3_len = cm3_len;
+ memcpy(subscr->equipment.classmark3, cm3, cm3_len);
+ }
+ db_sync_equipment(&subscr->equipment);
+ }
+}
+
+
+
static struct bsc_api msc_handler = {
.sapi_n_reject = msc_sapi_n_reject,
.compl_l3 = msc_compl_l3,
@@ -90,6 +110,7 @@ static struct bsc_api msc_handler = {
.clear_request = msc_clear_request,
.assign_compl = msc_assign_compl,
.assign_fail = msc_assign_fail,
+ .classmark_chg = msc_classmark_chg,
};
struct bsc_api *msc_bsc_api() {
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_api.c b/openbsc/src/osmo-bsc/osmo_bsc_api.c
index 2869f4756..72e7b9b78 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_api.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_api.c
@@ -183,6 +183,19 @@ static int bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t ca
return 1;
}
+static void bsc_cm_update(struct gsm_subscriber_connection *conn,
+ const uint8_t *cm2, uint8_t cm2_len,
+ const uint8_t *cm3, uint8_t cm3_len)
+{
+ struct osmo_bsc_sccp_con *sccp;
+ struct msgb *resp;
+ return_when_not_connected_val(conn, 1);
+
+ resp = gsm0808_create_classmark_update(cm2, cm2_len, cm3, cm3_len);
+
+ queue_msg_or_return(resp);
+}
+
static struct bsc_api bsc_handler = {
.sapi_n_reject = bsc_sapi_n_reject,
.cipher_mode_compl = bsc_cipher_mode_compl,
@@ -191,6 +204,7 @@ static struct bsc_api bsc_handler = {
.assign_compl = bsc_assign_compl,
.assign_fail = bsc_assign_fail,
.clear_request = bsc_clear_request,
+ .classmark_chg = bsc_cm_update,
};
struct bsc_api *osmo_bsc_api()