summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gsm/gsm0480.c11
-rw-r--r--src/gsm/gsm_utils.c145
-rw-r--r--src/gsm/libosmogsm.map7
3 files changed, 104 insertions, 59 deletions
diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c
index cc693feb..92a62dcf 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);
- gsm_7bit_encode_ussd(data, text, &len);
+ gsm_7bit_encode_n_ussd(data, msgb_tailroom(msg), 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);
- gsm_7bit_encode_ussd(data, text, &len);
+ gsm_7bit_encode_n_ussd(data, msgb_tailroom(msg), text, &len);
tmp_len[0] = len;
msgb_put(msg, len);
@@ -398,10 +398,7 @@ static int parse_process_uss_req(const uint8_t *uss_req_data, uint16_t length,
if ((dcs == 0x0F) &&
(uss_req_data[5] == ASN1_OCTET_STRING_TAG)) {
num_chars = (uss_req_data[6] * 8) / 7;
- /* Prevent a mobile-originated buffer-overrun! */
- if (num_chars > MAX_LEN_USSD_STRING)
- num_chars = MAX_LEN_USSD_STRING;
- gsm_7bit_decode_ussd(req->text,
+ gsm_7bit_decode_n_ussd(req->text, sizeof(req->text),
&(uss_req_data[7]), num_chars);
rc = 1;
}
@@ -423,7 +420,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);
- gsm_7bit_encode_ussd(ptr8, text, &response_len);
+ gsm_7bit_encode_n_ussd(ptr8, msgb_tailroom(msg), 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 3dd15375..e248078f 100644
--- a/src/gsm/gsm_utils.c
+++ b/src/gsm/gsm_utils.c
@@ -28,7 +28,7 @@
* This library is a collection of common code used in various
* GSM related sub-projects inside the Osmocom family of projects. It
* includes A5/1 and A5/2 ciphers, COMP128v1, a LAPDm implementation,
- * a GSM TLV parser, SMS utility routines as well as
+ * a GSM TLV parser, SMS utility routines as well as
* protocol definitions for a series of protocols:
* * Um L2 (04.06)
* * Um L3 (04.08)
@@ -123,12 +123,17 @@ uint8_t gsm_get_octet_len(const uint8_t sept_len){
}
/* GSM 03.38 6.2.1 Character unpacking */
-int gsm_7bit_decode_hdr(char *text, const uint8_t *user_data, uint8_t septet_l, uint8_t ud_hdr_ind)
+int gsm_7bit_decode_n_hdr(char *text, size_t n, const uint8_t *user_data, uint8_t septet_l, uint8_t ud_hdr_ind)
{
int i = 0;
int shift = 0;
- uint8_t c;
+ uint8_t c7, c8;
uint8_t next_is_ext = 0;
+ const char *text_buf_begin = text;
+ const char *text_buf_end = text + n;
+ int nchars;
+
+ OSMO_ASSERT (n > 0);
/* skip the user data header */
if (ud_hdr_ind) {
@@ -139,50 +144,49 @@ int gsm_7bit_decode_hdr(char *text, const uint8_t *user_data, uint8_t septet_l,
septet_l = septet_l - shift;
}
- for (i = 0; i < septet_l; i++) {
- c =
+ for (i = 0; i < septet_l && text != text_buf_end - 1; i++) {
+ c7 =
((user_data[((i + shift) * 7 + 7) >> 3] <<
(7 - (((i + shift) * 7 + 7) & 7))) |
(user_data[((i + shift) * 7) >> 3] >>
(((i + shift) * 7) & 7))) & 0x7f;
- /* this is an extension character */
if (next_is_ext) {
+ /* this is an extension character */
next_is_ext = 0;
- *(text++) = gsm_7bit_alphabet[0x7f + c];
- continue;
- }
-
- if (c == 0x1b && i + 1 < septet_l) {
+ c8 = gsm_7bit_alphabet[0x7f + c7];
+ } else if (c7 == 0x1b && i + 1 < septet_l) {
next_is_ext = 1;
+ continue;
} else {
- *(text++) = gsm_septet_lookup(c);
+ c8 = gsm_septet_lookup(c7);
}
+
+ *(text++) = c8;
}
- if (ud_hdr_ind)
- i += shift;
+ nchars = text - text_buf_begin;
+
*text = '\0';
- return i;
+ return nchars;
}
-int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
+int gsm_7bit_decode_n(char *text, size_t n, const uint8_t *user_data, uint8_t septet_l)
{
- return gsm_7bit_decode_hdr(text, user_data, septet_l, 0);
+ return gsm_7bit_decode_n_hdr(text, n, user_data, septet_l, 0);
}
-int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
+int gsm_7bit_decode_n_ussd(char *text, size_t n, const uint8_t *user_data, uint8_t length)
{
- int i;
+ int nchars;
- gsm_7bit_decode_hdr(text, user_data, length, 0);
- i = strlen(text);
+ nchars = gsm_7bit_decode_n_hdr(text, n, user_data, length, 0);
/* remove last <CR>, 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';
+ if (nchars && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r')
+ text[--nchars] = '\0';
- return i;
+ return nchars;
}
/* GSM 03.38 6.2.1 Prepare character packing */
@@ -261,38 +265,28 @@ int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len
}
/* GSM 03.38 6.2.1 Character packing */
-int gsm_7bit_encode(uint8_t *result, const char *data)
-{
- int out;
- 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 <CR> */
- if (((y * 7) & 7) == 1)
- result[(*octets) - 1] |= ('\r' << 1);
- /* if last character is <CR> and completely fills last octet, add
- * another <CR>. */
- 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 gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets)
{
int y = 0;
+ int o;
+ int max_septets = n * 8 / 7;
/* prepare for the worst case, every character expanding to two bytes */
uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t));
y = gsm_septet_encode(rdata, data);
- *octets = gsm_septets2octets(result, rdata, y, 0);
+
+ if (y > max_septets) {
+ /*
+ * Limit the number of septets to avoid the generation
+ * of more than n octets.
+ */
+ y = max_septets;
+ }
+
+ o = gsm_septets2octets(result, rdata, y, 0);
+
+ if (octets)
+ *octets = o;
free(rdata);
@@ -309,6 +303,24 @@ int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
return y;
}
+int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets)
+{
+ int y;
+
+ y = gsm_7bit_encode_n(result, n, data, octets);
+ /* if last octet contains only one bit, add <CR> */
+ if (((y * 7) & 7) == 1)
+ result[(*octets) - 1] |= ('\r' << 1);
+ /* if last character is <CR> and completely fills last octet, add
+ * another <CR>. */
+ if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r' && *octets < n - 1) {
+ result[(*octets)++] = '\r';
+ y++;
+ }
+
+ return y;
+}
+
/* convert power class to dBm according to GSM TS 05.05 */
unsigned int ms_class_gmsk_dbm(enum gsm_band band, int class)
{
@@ -373,7 +385,7 @@ int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
case GSM_BAND_1800:
if (dbm >= 36)
return 29;
- else if (dbm >= 34)
+ else if (dbm >= 34)
return 30;
else if (dbm >= 32)
return 31;
@@ -662,3 +674,34 @@ uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type)
}
return tlli;
}
+
+/* Wrappers for deprecated functions: */
+
+int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
+{
+ gsm_7bit_decode_n(text, SIZE_MAX, user_data, septet_l);
+
+ /* Mimic the original behaviour. */
+ return septet_l;
+}
+
+int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
+{
+ return gsm_7bit_decode_n_ussd(text, SIZE_MAX, user_data, length);
+}
+
+int gsm_7bit_encode(uint8_t *result, const char *data)
+{
+ int out;
+ return gsm_7bit_encode_n(result, SIZE_MAX, data, &out);
+}
+
+int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets)
+{
+ return gsm_7bit_encode_n_ussd(result, SIZE_MAX, data, octets);
+}
+
+int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
+{
+ return gsm_7bit_encode_n(result, SIZE_MAX, data, octets);
+}
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 1b985e10..9d15d668 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -133,11 +133,16 @@ 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_7bit_decode_n;
+gsm_7bit_decode_n_ussd;
+gsm_7bit_decode_n_hdr;
+gsm_7bit_encode_n;
+gsm_7bit_encode_n_ussd;
+
gsm_arfcn2band;
gsm_arfcn2freq10;
gsm_freq102arfcn;