aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/libmsc/gsm_sup.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/libmsc/gsm_sup.c')
-rw-r--r--openbsc/src/libmsc/gsm_sup.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/openbsc/src/libmsc/gsm_sup.c b/openbsc/src/libmsc/gsm_sup.c
index 9dc8f191e..2e0fe7201 100644
--- a/openbsc/src/libmsc/gsm_sup.c
+++ b/openbsc/src/libmsc/gsm_sup.c
@@ -31,6 +31,9 @@
#include <openbsc/osmo_msc.h>
#include <openbsc/gprs_utils.h>
#include <openbsc/ussd.h>
+#include <openbsc/gsm_04_11.h>
+#include <osmocom/gsm/protocol/gsm_04_11.h>
+#include <osmocom/gsm/gsm0411_utils.h>
#if 0
enum {
@@ -174,6 +177,74 @@ static int rx_uss_message(const uint8_t* data, size_t len)
}
#endif
+int subscr_tx_sms_message(struct gsm_subscriber *subscr,
+ struct gsm411_rp_hdr *rph)
+{
+ uint8_t *data;
+ struct msgb *msg = gprs_gsup_msgb_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+ msgb_put_u8(msg, GPRS_GSUP_MSGT_SMS);
+
+ if (subscr->extension) {
+ uint8_t bcd_buf[32];
+ int bcd_len = gsm48_encode_bcd_number(bcd_buf, sizeof(bcd_buf),
+ 0, subscr->extension);
+ msgb_tlv_put(msg, 0x82, bcd_len - 1, &bcd_buf[1]);
+ }
+ msgb_put_u8(msg, rph->msg_type);
+ msgb_put_u8(msg, rph->msg_ref);
+
+ data = msgb_put(msg, rph->len - 2);
+ memcpy(data, rph->data, rph->len - 2);
+
+ return gprs_gsup_client_send(subscr->group->net->sms_client, msg);
+}
+
+static int rx_sms_message(const uint8_t* data, size_t data_len)
+{
+
+ int rc;
+ char extension[15];
+ uint8_t *value;
+ size_t value_len;
+ int offset = 0;
+ uint8_t *rp_hdr = (uint8_t*)data + offset;
+
+ offset++;
+ rc = gprs_match_tlv(&rp_hdr, &data_len, 0x82, &value, &value_len);
+
+ if (rc <= 0)
+ return -GMM_CAUSE_INV_MAND_INFO;
+
+ if (value_len * 2 + 1 > ARRAY_SIZE(extension))
+ return -GMM_CAUSE_INV_MAND_INFO;
+
+ /* Note that gsm48_decode_bcd_number expects the number of encoded MSISDN
+ * octets in the first octet. By coincidence (the TLV encoding) the byte
+ * before the value part already contains this length so we can use it
+ * here.
+ */
+ OSMO_ASSERT(value[-1] == value_len);
+ gsm48_decode_bcd_number(extension, ARRAY_SIZE(extension), value - 1, 0);
+ offset += 2 + value_len;
+
+ struct msgb *msg = gsm411_msgb_alloc();
+ uint8_t *rp_msg;
+ rp_msg = (uint8_t *)msgb_put(msg, data_len - offset);
+ memcpy(rp_msg, data + offset, data_len - offset);
+
+ struct gsm_subscriber *subscr;
+ subscr = subscr_get_by_extension(NULL, extension);
+ if (!subscr) {
+ msgb_free(msg);
+ return -GMM_CAUSE_IMSI_UNKNOWN;
+ }
+
+ return gsm411_send_rp_msg_subscr(subscr, msg);
+}
+
static int subscr_tx_sup_message(struct gprs_gsup_client *sup_client,
struct gsm_subscriber *subscr,
struct gprs_gsup_message *gsup_msg)
@@ -442,6 +513,8 @@ static int subscr_rx_sup_message(struct gprs_gsup_client *sup_client, struct msg
#if 0
if (*data == GPRS_GSUP_MSGT_MAP) {
return rx_uss_message(data, data_len);
+ } else if (*data == GPRS_GSUP_MSGT_SMS) {
+ return rx_sms_message(data, data_len);
}
#endif
rc = gprs_gsup_decode(data, data_len, &gsup_msg);