summaryrefslogtreecommitdiffstats
path: root/openbsc/src/libmsc/smpp_openbsc.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2012-11-24 01:37:39 +0100
committerHarald Welte <laforge@gnumonks.org>2012-11-24 11:09:21 +0100
commitb8a1f967c5a15d1f4efc9699775cacb75f378e89 (patch)
treec116a37bb0848bd25f19b96393a6c9c7ceadc12f /openbsc/src/libmsc/smpp_openbsc.c
parentc0de14da8f868de3a68b485ec382d8aa7dabbec9 (diff)
SMPP: fix handling of UDH / multi-part for 7-bit messages
... I would have never believed it is such a broken mindfuck.
Diffstat (limited to 'openbsc/src/libmsc/smpp_openbsc.c')
-rw-r--r--openbsc/src/libmsc/smpp_openbsc.c61
1 files changed, 47 insertions, 14 deletions
diff --git a/openbsc/src/libmsc/smpp_openbsc.c b/openbsc/src/libmsc/smpp_openbsc.c
index 378cbf63e..de8f36e99 100644
--- a/openbsc/src/libmsc/smpp_openbsc.c
+++ b/openbsc/src/libmsc/smpp_openbsc.c
@@ -142,7 +142,7 @@ static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net,
if (submit->data_coding == 0x00 || /* SMSC default */
submit->data_coding == 0x01 || /* GSM default alphabet */
(submit->data_coding & 0xFC) == 0xF0) { /* 03.38 DCS default */
- uint8_t ud_len = 0;
+ uint8_t ud_len = 0, padbits = 0;
sms->data_coding_scheme = GSM338_DCS_1111_7BIT;
if (sms->ud_hdr_ind) {
ud_len = *sms_msg + 1;
@@ -151,11 +151,12 @@ static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net,
OSMO_MIN(ud_len, sizeof(sms->user_data)));
sms_msg += ud_len;
sms_msg_len -= ud_len;
+ padbits = 7 - (ud_len % 7);
}
- strncpy(sms->text, (char *)sms_msg,
- OSMO_MIN(sizeof(sms->text)-1, sms_msg_len));
- printf("encoding 7bit to offset %u text(%s)\n", ud_len, sms->text);
- sms->user_data_len = gsm_7bit_encode(sms->user_data+ud_len, sms->text);
+ gsm_septets2octets(sms->user_data+ud_len, sms_msg,
+ sms_msg_len, padbits);
+ sms->user_data_len = (ud_len*8 + padbits)/7 + sms_msg_len;/* SEPTETS */
+ /* FIXME: sms->text */
} else if (submit->data_coding == 0x02 ||
submit->data_coding == 0x04 ||
(submit->data_coding & 0xFC) == 0xF4) { /* 03.38 DCS 8bit */
@@ -296,6 +297,38 @@ static int smpp_subscr_cb(unsigned int subsys, unsigned int signal,
return 0;
}
+/* GSM 03.38 6.2.1 Character expanding (no decode!) */
+static int gsm_7bit_expand(char *text, const uint8_t *user_data, uint8_t septet_l, uint8_t ud_hdr_ind)
+{
+ int i = 0;
+ int shift = 0;
+ uint8_t c;
+
+ /* skip the user data header */
+ if (ud_hdr_ind) {
+ /* get user data header length + 1 (for the 'user data header length'-field) */
+ shift = ((user_data[0] + 1) * 8) / 7;
+ if ((((user_data[0] + 1) * 8) % 7) != 0)
+ shift++;
+ septet_l = septet_l - shift;
+ }
+
+ for (i = 0; i < septet_l; i++) {
+ c =
+ ((user_data[((i + shift) * 7 + 7) >> 3] <<
+ (7 - (((i + shift) * 7 + 7) & 7))) |
+ (user_data[((i + shift) * 7) >> 3] >>
+ (((i + shift) * 7) & 7))) & 0x7f;
+
+ *(text++) = c;
+ }
+
+ *text = '\0';
+
+ return i;
+}
+
+
static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms)
{
struct deliver_sm_t deliver;
@@ -339,22 +372,22 @@ static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms)
dcs = sms->data_coding_scheme;
if (dcs == GSM338_DCS_1111_7BIT ||
((dcs & 0xE0000000) == 0 && (dcs & 0xC) == 0)) {
- uint8_t *src = sms->user_data;
uint8_t *dst = deliver.short_message;
- uint8_t src_byte_len = sms->user_data_len;
/* SMPP has this strange notion of putting 7bit SMS in
* an octet-aligned mode */
deliver.data_coding = 0x01;
if (sms->ud_hdr_ind) {
- uint8_t udh_len = sms->user_data[0];
- src += udh_len + 1;
- dst += udh_len + 1;
- src_byte_len -= udh_len + 1;
- memcpy(dst, sms->user_data, udh_len + 1);
- deliver.sm_length = udh_len + 1;
+ /* length (bytes) of UDH inside UD */
+ uint8_t udh_len = sms->user_data[0] + 1;
+
+ /* copy over the UDH */
+ memcpy(dst, sms->user_data, udh_len);
+ dst += udh_len;
+ deliver.sm_length = udh_len;
}
- deliver.sm_length += gsm_7bit_decode((char *)dst, src, src_byte_len);
+ /* add decoded text */
+ deliver.sm_length += gsm_7bit_expand((char *)dst, sms->user_data, sms->user_data_len, sms->ud_hdr_ind);
} else if (dcs == GSM338_DCS_1111_8BIT_DATA ||
((dcs & 0xE0000000) == 0 && (dcs & 0xC) == 4)) {
deliver.data_coding = 0x02;