From 9597555a362cd28c02e9bbfe4f55c4b90ecdfa34 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Thu, 8 Aug 2013 12:38:53 +0200 Subject: Add special 7-bit encoding and decoding functions for USSD coding Handling 7-bit coding is a little different for USSD, as TS 03.38 states: To avoid the situation where the receiving entity confuses 7 binary zero pad bits as the @ character, the carriage return or character shall be used for padding in this situation [...]. If is intended to be the last character and the message (including the wanted ) ends on an octet boundary, then another must be added together with a padding bit 0. The receiving entity will perform the carriage return function twice, but this will not result in misoperation as the definition of [...] is identical to the definition of . The receiving entity shall remove the final character where the message ends on an octet boundary with as the last character. Jacob has verified the fix with fakeBTS and the wireshark dissector. Fixes: OW#947 Reviewed-by: Jacob Erlbeck --- src/gsm/gsm0480.c | 10 +++++----- src/gsm/gsm_utils.c | 31 +++++++++++++++++++++++++++++++ src/gsm/libosmogsm.map | 2 ++ 3 files changed, 38 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c index b9b3ed97..cc693feb 100644 --- a/src/gsm/gsm0480.c +++ b/src/gsm/gsm0480.c @@ -105,7 +105,7 @@ struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char * msgb_put_u8(msg, ASN1_OCTET_STRING_TAG); ussd_len_ptr = msgb_put(msg, 1); data = msgb_put(msg, 0); - len = gsm_7bit_encode(data, text); + gsm_7bit_encode_ussd(data, text, &len); msgb_put(msg, len); ussd_len_ptr[0] = len; /* USSD-String } */ @@ -172,7 +172,7 @@ struct msgb *gsm0480_create_notifySS(const char *text) msgb_put_u8(msg, 0x82); tmp_len = msgb_put(msg, 1); data = msgb_put(msg, 0); - len = gsm_7bit_encode(data, text); + gsm_7bit_encode_ussd(data, text, &len); tmp_len[0] = len; msgb_put(msg, len); @@ -401,8 +401,8 @@ static int parse_process_uss_req(const uint8_t *uss_req_data, uint16_t length, /* Prevent a mobile-originated buffer-overrun! */ if (num_chars > MAX_LEN_USSD_STRING) num_chars = MAX_LEN_USSD_STRING; - gsm_7bit_decode(req->text, - &(uss_req_data[7]), num_chars); + gsm_7bit_decode_ussd(req->text, + &(uss_req_data[7]), num_chars); rc = 1; } } @@ -423,7 +423,7 @@ struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const /* First put the payload text into the message */ ptr8 = msgb_put(msg, 0); - response_len = gsm_7bit_encode(ptr8, text); + gsm_7bit_encode_ussd(ptr8, text, &response_len); msgb_put(msg, response_len); /* Then wrap it as an Octet String */ diff --git a/src/gsm/gsm_utils.c b/src/gsm/gsm_utils.c index 54b965e2..3dd15375 100644 --- a/src/gsm/gsm_utils.c +++ b/src/gsm/gsm_utils.c @@ -172,6 +172,19 @@ int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l) return gsm_7bit_decode_hdr(text, user_data, septet_l, 0); } +int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length) +{ + int i; + + gsm_7bit_decode_hdr(text, user_data, length, 0); + i = strlen(text); + /* remove last , if it fits up to the end of last octet */ + if (i && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r') + text[--i] = '\0'; + + return i; +} + /* GSM 03.38 6.2.1 Prepare character packing */ int gsm_septet_encode(uint8_t *result, const char *data) { @@ -254,6 +267,24 @@ int gsm_7bit_encode(uint8_t *result, const char *data) return gsm_7bit_encode_oct(result, data, &out); } +int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets) +{ + int y; + + y = gsm_7bit_encode_oct(result, data, octets); + /* if last octet contains only one bit, add */ + if (((y * 7) & 7) == 1) + result[(*octets) - 1] |= ('\r' << 1); + /* if last character is and completely fills last octet, add + * another . */ + if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r') { + result[(*octets)++] = '\r'; + y++; + } + + return y; +} + int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets) { int y = 0; diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 8a020dbd..1b985e10 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -132,8 +132,10 @@ gsm48_parse_ra; gsm48_rr_att_tlvdef; gsm_7bit_decode; +gsm_7bit_decode_ussd; gsm_7bit_decode_hdr; gsm_7bit_encode; +gsm_7bit_encode_ussd; gsm_7bit_encode_oct; gsm_arfcn2band; -- cgit v1.2.3