diff options
author | Pascal Quantin <pascal.quantin@gmail.com> | 2014-01-01 14:33:19 +0000 |
---|---|---|
committer | Pascal Quantin <pascal.quantin@gmail.com> | 2014-01-01 14:33:19 +0000 |
commit | 6ebc058f473085a2fa9884fe2fd7f4a9959be915 (patch) | |
tree | f514e3d9eadd1c89ad434cc00d5d20fda6168ef1 /epan | |
parent | e504cf945bb54c3c73efbaee51acaa968179586a (diff) | |
download | wireshark-6ebc058f473085a2fa9884fe2fd7f4a9959be915.tar.gz |
Add proto_tree_add_ts_23_038_7bits_item() / tvb_get_ts_23_038_7bits_string() functions and update dissectors to use it.
Remove gsm_sms_char_7bit_unpack() / gsm_sms_chars_to_utf8() functions.
Update documentation a bit.
svn path=/trunk/; revision=54534
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/packet-ansi_637.c | 8 | ||||
-rw-r--r-- | epan/dissectors/packet-cell_broadcast.c | 13 | ||||
-rw-r--r-- | epan/dissectors/packet-etsi_card_app_toolkit.c | 2 | ||||
-rw-r--r-- | epan/dissectors/packet-gmr1_rr.c | 16 | ||||
-rw-r--r-- | epan/dissectors/packet-gsm_a_dtap.c | 15 | ||||
-rw-r--r-- | epan/dissectors/packet-gsm_map.c | 2 | ||||
-rw-r--r-- | epan/dissectors/packet-gsm_sms.c | 193 | ||||
-rw-r--r-- | epan/dissectors/packet-gsm_sms.h | 25 | ||||
-rw-r--r-- | epan/dissectors/packet-mbim.c | 4 | ||||
-rw-r--r-- | epan/proto.c | 30 | ||||
-rw-r--r-- | epan/proto.h | 68 | ||||
-rw-r--r-- | epan/tvbuff.c | 37 | ||||
-rw-r--r-- | epan/tvbuff.h | 13 |
13 files changed, 134 insertions, 292 deletions
diff --git a/epan/dissectors/packet-ansi_637.c b/epan/dissectors/packet-ansi_637.c index ef5e3210dc..a4ed247c61 100644 --- a/epan/dissectors/packet-ansi_637.c +++ b/epan/dissectors/packet-ansi_637.c @@ -206,7 +206,6 @@ static dissector_handle_t ansi_637_trans_handle; static guint32 ansi_637_trans_tele_id; static char ansi_637_bigbuf[1024]; -static char gsm_637_bigbuf[1024]; static char ia5_637_bigbuf[1024]; static dissector_table_t tele_dissector_table; static proto_tree *g_tree; @@ -764,12 +763,7 @@ tele_param_user_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint dis_field_udh(tvb_out, tree, &offset, &required_octs, &num_fields, GSM_7BITS, &bit, &udh_fields); } - out_len = gsm_sms_char_7bit_unpack(bit, required_octs, num_fields, - tvb_get_ptr(tvb_out, offset, required_octs), gsm_637_bigbuf); - gsm_637_bigbuf[out_len] = '\0'; - - proto_tree_add_string(tree, hf_ansi_637_tele_user_data_text, tvb_out, offset, - required_octs, gsm_sms_chars_to_utf8(gsm_637_bigbuf, num_fields)); + proto_tree_add_ts_23_038_7bits_item(tree, hf_ansi_637_tele_user_data_text, tvb_out, (offset<<3)+bit, num_fields); } else if (encoding == 0x10)/* KSC5601 (Korean) */ { diff --git a/epan/dissectors/packet-cell_broadcast.c b/epan/dissectors/packet-cell_broadcast.c index c8490af2a0..9679b57f28 100644 --- a/epan/dissectors/packet-cell_broadcast.c +++ b/epan/dissectors/packet-cell_broadcast.c @@ -253,24 +253,18 @@ guint16 dissect_cbs_message_identifier(tvbuff_t *tvb, proto_tree *tree, guint16 tvbuff_t * dissect_cbs_data(guint8 sms_encoding, tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint16 offset ) { tvbuff_t * tvb_out = NULL; - guint8 out_len; int length = tvb_length(tvb) - offset; gchar *utf8_text = NULL, *utf8_out; - static unsigned char msgbuf[1024]; - guint8 * input_string = tvb_get_string(wmem_packet_scope(), tvb, offset, length); + guint8 * input_string; GIConv cd; GError *l_conv_error = NULL; switch(sms_encoding){ case SMS_ENCODING_7BIT: case SMS_ENCODING_7BIT_LANG: - out_len = gsm_sms_char_7bit_unpack(0, length, sizeof(msgbuf), - input_string, - msgbuf); - msgbuf[out_len] = '\0'; - utf8_text = gsm_sms_chars_to_utf8(msgbuf, out_len); + utf8_text = tvb_get_ts_23_038_7bits_string(wmem_packet_scope(), tvb, offset<<3, (length*8)/7); utf8_out = g_strdup(utf8_text); - tvb_out = tvb_new_child_real_data(tvb, utf8_out, out_len, out_len); + tvb_out = tvb_new_child_real_data(tvb, utf8_out, strlen(utf8_out), strlen(utf8_out)); tvb_set_free_cb(tvb_out, g_free); add_new_data_source(pinfo, tvb_out, "unpacked 7 bit data"); break; @@ -281,6 +275,7 @@ tvbuff_t * dissect_cbs_data(guint8 sms_encoding, tvbuff_t *tvb, proto_tree *tree case SMS_ENCODING_UCS2: case SMS_ENCODING_UCS2_LANG: + input_string = tvb_get_string(wmem_packet_scope(), tvb, offset, length); if ((cd = g_iconv_open("UTF-8","UCS-2BE")) != (GIConv) -1) { utf8_text = g_convert_with_iconv(input_string, length, cd, NULL, NULL, &l_conv_error); diff --git a/epan/dissectors/packet-etsi_card_app_toolkit.c b/epan/dissectors/packet-etsi_card_app_toolkit.c index 2270d6e1bc..1e4969dcdf 100644 --- a/epan/dissectors/packet-etsi_card_app_toolkit.c +++ b/epan/dissectors/packet-etsi_card_app_toolkit.c @@ -1065,7 +1065,7 @@ dissect_cat(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) } switch (g8) { case 0x00: /* 7bit */ - proto_tree_add_item(elem_tree, hf_ctlv_text_string, tvb, pos+1, len-1, ENC_3GPP_TS_23_038|ENC_NA); + proto_tree_add_item(elem_tree, hf_ctlv_text_string, tvb, pos+1, len-1, ENC_3GPP_TS_23_038_7BITS|ENC_NA); break; case 0x04: /* 8bit */ /* XXX - ASCII, or some extended ASCII? */ diff --git a/epan/dissectors/packet-gmr1_rr.c b/epan/dissectors/packet-gmr1_rr.c index ce530cc88f..28f110e911 100644 --- a/epan/dissectors/packet-gmr1_rr.c +++ b/epan/dissectors/packet-gmr1_rr.c @@ -649,25 +649,29 @@ static const value_string rr_pos_display_flag_vals[] = { GMR1_IE_FUNC(gmr1_ie_rr_pos_display) { const unsigned char *txt_raw; - unsigned char txt_packed[11], txt_unpacked[12]; - int out_len, i; + gchar *txt_packed, *txt_unpacked; + tvbuff_t *txt_packed_tvb; + int i; /* Flag */ proto_tree_add_item(tree, hf_rr_pos_display_flag, tvb, offset, 1, ENC_BIG_ENDIAN); - /* Unpack text */ + /* Get text in an aligned tvbuff */ txt_raw = tvb_get_ptr(tvb, offset, 11); - + txt_packed = (gchar*)wmem_alloc(wmem_packet_scope(), 11); for (i=0; i<10; i++) txt_packed[i] = (txt_raw[i] << 4) | (txt_raw[i+1] >> 4); txt_packed[10] = txt_raw[10]; + txt_packed_tvb = tvb_new_real_data(txt_packed, 11, 11); - out_len = gsm_sms_char_7bit_unpack(0, 11, 12, txt_packed, txt_unpacked); + /* Unpack text */ + txt_unpacked = tvb_get_ts_23_038_7bits_string(wmem_packet_scope(), txt_packed_tvb, 0, 12); + tvb_free(txt_packed_tvb); /* Display it */ proto_tree_add_string(tree, hf_rr_pos_display_text, tvb, offset, 11, - gsm_sms_chars_to_utf8(txt_unpacked, out_len)); + txt_unpacked); return 11; } diff --git a/epan/dissectors/packet-gsm_a_dtap.c b/epan/dissectors/packet-gsm_a_dtap.c index 1a3a08bd21..c2fa7729b2 100644 --- a/epan/dissectors/packet-gsm_a_dtap.c +++ b/epan/dissectors/packet-gsm_a_dtap.c @@ -788,7 +788,7 @@ de_network_name(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint32 off guint32 curr_offset; const gchar *str; guint8 coding_scheme, num_spare_bits; - guint32 num_chars, num_text_bits; + guint32 num_text_bits; gchar *net_name = NULL; proto_item *item; @@ -819,24 +819,13 @@ de_network_name(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, guint32 off switch(coding_scheme) { case 0: - num_chars = gsm_sms_char_7bit_unpack(0, len - 1, sizeof(a_bigbuf), - tvb_get_ptr(tvb, curr_offset, len - 1), a_bigbuf); - /* Check if there was a reasonable value for number of spare bits in last octet */ num_text_bits = ((len - 1) << 3) - num_spare_bits; if (num_spare_bits && (num_text_bits % 7)) { expert_add_info(pinfo, item, &ei_gsm_a_dtap_text_string_not_multiple_of_7); } - /* - * If the number of spare bits is 7, then we have unpacked one extra - * character. Disregard this character. - */ - if (num_spare_bits == 7) - num_chars--; - a_bigbuf[num_chars] = '\0'; - net_name = gsm_sms_chars_to_utf8(a_bigbuf, num_chars); - proto_tree_add_string(tree, hf_gsm_a_dtap_text_string, tvb, curr_offset, len - 1, net_name); + proto_tree_add_ts_23_038_7bits_item(tree, hf_gsm_a_dtap_text_string, tvb, curr_offset<<3, num_text_bits/7); break; case 1: net_name = tvb_get_string_enc(wmem_packet_scope(), tvb, curr_offset, (len - 1), ENC_UCS_2|ENC_BIG_ENDIAN); diff --git a/epan/dissectors/packet-gsm_map.c b/epan/dissectors/packet-gsm_map.c index dc283ba994..04948891cc 100644 --- a/epan/dissectors/packet-gsm_map.c +++ b/epan/dissectors/packet-gsm_map.c @@ -4891,7 +4891,7 @@ dissect_gsm_map_ss_USSD_String(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int switch(sms_encoding){ case SMS_ENCODING_7BIT: case SMS_ENCODING_7BIT_LANG: - proto_tree_add_text(tree, parameter_tvb , 0, length, "USSD String: %s", tvb_get_string_enc(wmem_packet_scope(), parameter_tvb, 0, length, ENC_3GPP_TS_23_038|ENC_NA)); + proto_tree_add_text(tree, parameter_tvb , 0, length, "USSD String: %s", tvb_get_string_enc(wmem_packet_scope(), parameter_tvb, 0, length, ENC_3GPP_TS_23_038_7BITS|ENC_NA)); break; case SMS_ENCODING_8BIT: /* XXX - ASCII, or some extended ASCII? */ diff --git a/epan/dissectors/packet-gsm_sms.c b/epan/dissectors/packet-gsm_sms.c index 2523ef4340..527f4a9ea4 100644 --- a/epan/dissectors/packet-gsm_sms.c +++ b/epan/dissectors/packet-gsm_sms.c @@ -338,7 +338,6 @@ dis_field_addr(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, const gchar * guint32 numdigocts; guint32 length, addrlength; guint32 i, j; - char addrbuf[MAX_ADDR_SIZE+1]; gchar *addrstr; offset = *offset_p; @@ -431,10 +430,8 @@ dis_field_addr(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, const gchar * { case 0x05: /* "Alphanumeric (coded according to 3GPP TS 23.038 GSM 7-bit default alphabet)" */ addrlength = (addrlength << 2) / 7; - i = gsm_sms_char_7bit_unpack(0, numdigocts, ((addrlength > MAX_ADDR_SIZE) ? MAX_ADDR_SIZE : addrlength), - tvb_get_ptr(tvb, offset, numdigocts), addrbuf); - addrbuf[i] = '\0'; - addrstr = gsm_sms_chars_to_utf8(addrbuf, i); + addrstr = tvb_get_ts_23_038_7bits_string(wmem_packet_scope(), tvb, offset << 3, + (addrlength > MAX_ADDR_SIZE) ? MAX_ADDR_SIZE : addrlength); break; default: addrstr = (gchar *)wmem_alloc(wmem_packet_scope(), numdigocts*2 + 1); @@ -1606,168 +1603,6 @@ dis_field_fcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct _U_) "The TP-UD field contains only the"); \ } -/* - * FROM GNOKII - * gsm-encoding.c - * gsm-sms.c - */ -#define GN_BYTE_MASK ((1 << bits) - 1) - -int -gsm_sms_char_7bit_unpack(unsigned int offset, unsigned int in_length, unsigned int out_length, - const guint8 *input, unsigned char *output) -{ - unsigned char *out_num = output; /* Current pointer to the output buffer */ - const guint8 *in_num = input; /* Current pointer to the input buffer */ - unsigned char rest = 0x00; - int bits; - - bits = offset ? offset : 7; - - while ((unsigned int)(in_num - input) < in_length) - { - *out_num = ((*in_num & GN_BYTE_MASK) << (7 - bits)) | rest; - rest = *in_num >> bits; - - /* If we don't start from 0th bit, we shouldn't go to the - next char. Under *out_num we have now 0 and under Rest - - _first_ part of the char. */ - if ((in_num != input) || (bits == 7)) out_num++; - in_num++; - - if ((unsigned int)(out_num - output) >= out_length) break; - - /* After reading 7 octets we have read 7 full characters but - we have 7 bits as well. This is the next character */ - if (bits == 1) - { - *out_num = rest; - out_num++; - bits = 7; - rest = 0x00; - } - else - { - bits--; - } - } - - return (int)(out_num - output); -} - -#define GN_CHAR_ALPHABET_SIZE 128 - -#define GN_CHAR_ESCAPE 0x1b - -static const gunichar gsm_default_alphabet[GN_CHAR_ALPHABET_SIZE] = { - - /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */ - /* Fixed to use unicode */ - /* Characters in hex position 10, [12 to 1a] and 24 are not present on - latin1 charset, so we cannot reproduce on the screen, however they are - greek symbol not present even on my Nokia */ - - '@', 0xa3, '$', 0xa5, 0xe8, 0xe9, 0xf9, 0xec, - 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5, - 0x394, '_', 0x3a6, 0x393, 0x39b, 0x3a9, 0x3a0, 0x3a8, - 0x3a3, 0x398, 0x39e, 0xa0, 0xc6, 0xe6, 0xdf, 0xc9, - ' ', '!', '\"', '#', 0xa4, '%', '&', '\'', - '(', ')', '*', '+', ',', '-', '.', '/', - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', ':', ';', '<', '=', '>', '?', - 0xa1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', 0xc4, 0xd6, 0xd1, 0xdc, 0xa7, - 0xbf, 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', - 'x', 'y', 'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0 -}; - -static gboolean -char_is_escape(unsigned char value) -{ - return (value == GN_CHAR_ESCAPE); -} - -static gunichar -char_def_alphabet_ext_decode(unsigned char value) -{ - switch (value) - { - case 0x0a: return 0x0c; /* form feed */ - case 0x14: return '^'; - case 0x28: return '{'; - case 0x29: return '}'; - case 0x2f: return '\\'; - case 0x3c: return '['; - case 0x3d: return '~'; - case 0x3e: return ']'; - case 0x40: return '|'; - case 0x65: return 0x20ac; /* euro */ - default: return '?'; /* invalid character */ - } -} - -static gunichar -char_def_alphabet_decode(unsigned char value) -{ - if (value < GN_CHAR_ALPHABET_SIZE) - { - return gsm_default_alphabet[value]; - } - else - { - return '?'; - } -} - -gchar * -gsm_sms_chars_to_utf8(const unsigned char* src, int len) -{ - gint outlen, i, j; - gunichar c; - gchar *outbuf; - - /* Scan the input string to see how long the output string will be */ - for (outlen = 0, j = 0; j < len; j++) - { - if (char_is_escape(src[j])) { - j++; - if (j == len) - c = '?'; /* escape with nothing following it - error */ - else - c = char_def_alphabet_ext_decode(src[j]); - } - else - c = char_def_alphabet_decode(src[j]); - outlen += g_unichar_to_utf8(c,NULL); - } - - /* Now allocate a buffer for the output string and fill it in */ - outbuf = (gchar *)wmem_alloc(wmem_packet_scope(), outlen + 1); - for (i = 0, j = 0; j < len; j++) - { - if (char_is_escape(src[j])) { - j++; - if (j == len) - c = '?'; /* escape with nothing following it - error */ - else - c = char_def_alphabet_ext_decode(src[j]); - } - else - c = char_def_alphabet_decode(src[j]); - i += g_unichar_to_utf8(c,&(outbuf[i])); - } - outbuf[i] = '\0'; - return outbuf; -} - -/* - * END FROM GNOKII - */ - /* 9.2.3.24.1 */ static void dis_iei_csm8(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length, gsm_sms_udh_fields_t *p_udh_fields) @@ -2645,7 +2480,6 @@ dis_field_udh(tvbuff_t *tvb, proto_tree *tree, guint32 *offset, guint32 *length, /* 9.2.3.24 */ #define SMS_MAX_MESSAGE_SIZE 160 -static char messagebuf[SMS_MAX_MESSAGE_SIZE+1]; static void dis_field_ud(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint32 length, gboolean udhi, guint8 udl, gboolean seven_bit, @@ -2656,7 +2490,7 @@ dis_field_ud(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset tvbuff_t *sm_tvb = NULL; fragment_head *fd_sm = NULL; guint8 fill_bits; - guint32 out_len, total_sms_len, len_sms, length_ucs2, i; + guint32 total_sms_len, len_sms, length_ucs2, i; proto_item *ucs2_item; gchar *utf8_text = NULL; gchar save_byte = 0, save_byte2 = 0; @@ -2782,13 +2616,8 @@ dis_field_ud(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset if(!(reassembled && pinfo->fd->num == reassembled_in)) { /* Show unassembled SMS */ - out_len = - gsm_sms_char_7bit_unpack(fill_bits, length , - (udl > SMS_MAX_MESSAGE_SIZE ? SMS_MAX_MESSAGE_SIZE : udl), - tvb_get_ptr(tvb , offset , length) , messagebuf); - messagebuf[out_len] = '\0'; - proto_tree_add_string(subtree, hf_gsm_sms_text, tvb, offset, length, - gsm_sms_chars_to_utf8(messagebuf, out_len)); + proto_tree_add_ts_23_038_7bits_item(subtree, hf_gsm_sms_text, tvb, (offset<<3)+fill_bits, + (udl > SMS_MAX_MESSAGE_SIZE ? SMS_MAX_MESSAGE_SIZE : udl)); } else { @@ -2803,15 +2632,9 @@ dis_field_ud(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset GUINT_TO_POINTER((guint)((udh_fields.sm_id<<16)|i))); if (p_frag_params) { - out_len = - gsm_sms_char_7bit_unpack(p_frag_params->fill_bits, p_frag_params->length, - (p_frag_params->udl > SMS_MAX_MESSAGE_SIZE ? SMS_MAX_MESSAGE_SIZE : p_frag_params->udl), - tvb_get_ptr(sm_tvb, total_sms_len, p_frag_params->length), messagebuf); - - messagebuf[out_len] = '\0'; - proto_tree_add_string(subtree, hf_gsm_sms_text, sm_tvb, - total_sms_len, p_frag_params->length, - gsm_sms_chars_to_utf8(messagebuf, out_len)); + proto_tree_add_ts_23_038_7bits_item(subtree, hf_gsm_sms_text, sm_tvb, + (total_sms_len<<3)+p_frag_params->fill_bits, + (p_frag_params->udl > SMS_MAX_MESSAGE_SIZE ? SMS_MAX_MESSAGE_SIZE : p_frag_params->udl)); total_sms_len += p_frag_params->length; } diff --git a/epan/dissectors/packet-gsm_sms.h b/epan/dissectors/packet-gsm_sms.h index f1e439c51f..99d5e10053 100644 --- a/epan/dissectors/packet-gsm_sms.h +++ b/epan/dissectors/packet-gsm_sms.h @@ -24,31 +24,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* Convert a 7-bit GSM SMS packed string into an unpacked string. - * - * @param offset Bit offset of the start of the string. - * @param in_length Length of the packed string in bytes. - * @param out_length Length of the output string in bytes. - * @param input The string to unpack - * @param output The buffer for the output string. This buffer must - * be pre-allocated and be at least out_length characters - * long, or out_length + 1 if you're planning on adding a - * terminating '\0'. - * @return The number of unpacked characters. - */ - -extern int gsm_sms_char_7bit_unpack(unsigned int offset, unsigned int in_length, unsigned int out_length, - const guint8 *input, unsigned char *output); - -/* Convert an unpacked SMS string to UTF-8. - * - * @param src The string to convert. - * @param len Length of the string to convert, in bytes. - * @return An ep_allocated UTF-8 string. - */ - -extern gchar *gsm_sms_chars_to_utf8(const unsigned char* src, int len); - enum character_set { OTHER, GSM_7BITS, diff --git a/epan/dissectors/packet-mbim.c b/epan/dissectors/packet-mbim.c index b1a6ec1963..fc00a3f2e3 100644 --- a/epan/dissectors/packet-mbim.c +++ b/epan/dissectors/packet-mbim.c @@ -3094,7 +3094,7 @@ mbim_dissect_set_ussd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint case SMS_ENCODING_7BIT: case SMS_ENCODING_7BIT_LANG: proto_tree_add_item(subtree, hf_mbim_set_ussd_ussd_payload_text, - ussd_tvb, 0, ussd_payload_length, ENC_3GPP_TS_23_038|ENC_NA); + ussd_tvb, 0, ussd_payload_length, ENC_3GPP_TS_23_038_7BITS|ENC_NA); break; case SMS_ENCODING_8BIT: /* XXX - ASCII, or some extended ASCII? */ @@ -3146,7 +3146,7 @@ mbim_dissect_ussd_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint case SMS_ENCODING_7BIT: case SMS_ENCODING_7BIT_LANG: proto_tree_add_item(subtree, hf_mbim_ussd_info_ussd_payload_text, - ussd_tvb, 0, ussd_payload_length, ENC_3GPP_TS_23_038|ENC_NA); + ussd_tvb, 0, ussd_payload_length, ENC_3GPP_TS_23_038_7BITS|ENC_NA); break; case SMS_ENCODING_8BIT: /* XXX - ASCII, or some extended ASCII? */ diff --git a/epan/proto.c b/epan/proto.c index 02f713277a..f8f86794a5 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -7821,6 +7821,36 @@ proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hfindex, return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst); } +proto_item * +proto_tree_add_ts_23_038_7bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb, + const guint bit_offset, const gint no_of_chars) +{ + proto_item *pi; + header_field_info *hfinfo; + gint byte_length; + gint byte_offset; + gchar *string; + + TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo); + + DISSECTOR_ASSERT(hfinfo->type == FT_STRING); + + byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3; + byte_offset = bit_offset >> 3; + + string = tvb_get_ts_23_038_7bits_string(wmem_packet_scope(), tvb, bit_offset, no_of_chars); + + if (hfinfo->display == STR_UNICODE) { + DISSECTOR_ASSERT(g_utf8_validate(string, -1, NULL)); + } + + pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length); + DISSECTOR_ASSERT(byte_length >= 0); + proto_tree_set_string(PNODE_FINFO(pi), string); + + return pi; +} + guchar proto_check_field_name(const gchar *field_name) { diff --git a/epan/proto.h b/epan/proto.h index d22c8c27e8..8128cf109c 100644 --- a/epan/proto.h +++ b/epan/proto.h @@ -274,31 +274,31 @@ WS_DLL_PUBLIC WS_MSVC_NORETURN void proto_report_dissector_bug(const char *messa * Unicode glyphs showing the name of the control character in small * caps, diagonally. (Unfortunately, those only exist for C0, not C1.) */ -#define ENC_CHARENCODING_MASK 0x7FFFFFFE /* mask out byte-order bits */ -#define ENC_ASCII 0x00000000 -#define ENC_UTF_8 0x00000002 -#define ENC_UTF_16 0x00000004 -#define ENC_UCS_2 0x00000006 -#define ENC_UCS_4 0x00000008 -#define ENC_ISO_8859_1 0x0000000A -#define ENC_ISO_8859_2 0x0000000C -#define ENC_ISO_8859_3 0x0000000E -#define ENC_ISO_8859_4 0x00000010 -#define ENC_ISO_8859_5 0x00000012 -#define ENC_ISO_8859_6 0x00000014 -#define ENC_ISO_8859_7 0x00000016 -#define ENC_ISO_8859_8 0x00000018 -#define ENC_ISO_8859_9 0x0000001A -#define ENC_ISO_8859_10 0x0000001C -#define ENC_ISO_8859_11 0x0000001E -/* #define ENC_ISO_8859_12 0x00000020 ISO 8859-12 was abandoned */ -#define ENC_ISO_8859_13 0x00000022 -#define ENC_ISO_8859_14 0x00000024 -#define ENC_ISO_8859_15 0x00000026 -#define ENC_ISO_8859_16 0x00000028 -#define ENC_WINDOWS_1250 0x0000002A -#define ENC_3GPP_TS_23_038 0x0000002C -#define ENC_EBCDIC 0x0000002E +#define ENC_CHARENCODING_MASK 0x7FFFFFFE /* mask out byte-order bits */ +#define ENC_ASCII 0x00000000 +#define ENC_UTF_8 0x00000002 +#define ENC_UTF_16 0x00000004 +#define ENC_UCS_2 0x00000006 +#define ENC_UCS_4 0x00000008 +#define ENC_ISO_8859_1 0x0000000A +#define ENC_ISO_8859_2 0x0000000C +#define ENC_ISO_8859_3 0x0000000E +#define ENC_ISO_8859_4 0x00000010 +#define ENC_ISO_8859_5 0x00000012 +#define ENC_ISO_8859_6 0x00000014 +#define ENC_ISO_8859_7 0x00000016 +#define ENC_ISO_8859_8 0x00000018 +#define ENC_ISO_8859_9 0x0000001A +#define ENC_ISO_8859_10 0x0000001C +#define ENC_ISO_8859_11 0x0000001E +/* #define ENC_ISO_8859_12 0x00000020 ISO 8859-12 was abandoned */ +#define ENC_ISO_8859_13 0x00000022 +#define ENC_ISO_8859_14 0x00000024 +#define ENC_ISO_8859_15 0x00000026 +#define ENC_ISO_8859_16 0x00000028 +#define ENC_WINDOWS_1250 0x0000002A +#define ENC_3GPP_TS_23_038_7BITS 0x0000002C +#define ENC_EBCDIC 0x0000002E /* * TODO: @@ -307,11 +307,7 @@ WS_DLL_PUBLIC WS_MSVC_NORETURN void proto_report_dissector_bug(const char *messa * * "IBM MS DBCS" * JIS C 6226 - * 7-bit encodings such as ETSI 03.38 (GSM SMS character set - - * used in some files, but packet-ansi_637.c, - * packet-cell_broadcast.c, packet-gmr1_rr.c, - * packet-gsm_a_dtap.c, and packet-gsm_sms.c need some - * work to use it) + * 7-bit encodings such as 7 bits ASCII used in packet-ansi_637.c * * As those are added, change code such as the code in packet-bacapp.c * to use them. @@ -2129,6 +2125,18 @@ proto_item * proto_tree_add_float_bits_format_value(proto_tree *tree, const int hf_index, tvbuff_t *tvb, const guint bit_offset, const gint no_of_bits, float value, const char *format, ...) G_GNUC_PRINTF(7,8); + +/** Add a FT_STRING with ENC_3GPP_TS_23_038_7BITS encoding to a proto_tree. + @param tree the tree to append this item to + @param hfindex field index + @param tvb the tv buffer of the current data + @param bit_offset start of data in tvb expressed in bits + @param no_of_chars number of 7bits characters to display + @return the newly created item */ +WS_DLL_PUBLIC proto_item * +proto_tree_add_ts_23_038_7bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb, + const guint bit_offset, const gint no_of_chars); + /** Check if given string is a valid field name @param field_name the field name to check @return 0 if valid, else first illegal character */ diff --git a/epan/tvbuff.c b/epan/tvbuff.c index 12b68968bb..e1610fa128 100644 --- a/epan/tvbuff.c +++ b/epan/tvbuff.c @@ -2251,21 +2251,25 @@ handle_ts_23_038_char(wmem_strbuf_t *strbuf, guint8 code_point, return saw_escape; } -static gchar * -tvb_get_ts_23_038_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint length) +gchar * +tvb_get_ts_23_038_7bits_string(wmem_allocator_t *scope, tvbuff_t *tvb, + const gint bit_offset, gint no_of_chars) { wmem_strbuf_t *strbuf; - gint i; /* Byte counter for tvbuff */ - gint in_offset = offset; /* Current pointer to the input buffer */ + gint char_count; /* character counter for tvbuff */ + gint in_offset = bit_offset >> 3; /* Current pointer to the input buffer */ guint8 in_byte, out_byte, rest = 0x00; gboolean saw_escape = FALSE; int bits; - bits = 7; + bits = bit_offset & 0x07; + if (!bits) { + bits = 7; + } - tvb_ensure_bytes_exist(tvb, offset, length); + tvb_ensure_bytes_exist(tvb, in_offset, ((no_of_chars + 1) * 7 + (bit_offset & 0x07)) >> 3); strbuf = wmem_strbuf_new(scope, NULL); - for(i = 0; i < length; i++) { + for(char_count = 0; char_count < no_of_chars;) { /* Get the next byte from the string. */ in_byte = tvb_get_guint8(tvb, in_offset); in_offset++; @@ -2286,17 +2290,20 @@ tvb_get_ts_23_038_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offs * next char. Under *out_num we have now 0 and under Rest - * _first_ part of the char. */ - if ((in_offset != offset) || (bits == 7)) + if (char_count || (bits == 7)) { saw_escape = handle_ts_23_038_char(strbuf, out_byte, saw_escape); + char_count++; + } /* * After reading 7 octets we have read 7 full characters * but we have 7 bits as well. This is the next character. */ - if (bits == 1) { + if ((bits == 1) && (char_count < no_of_chars)) { saw_escape = handle_ts_23_038_char(strbuf, rest, saw_escape); + char_count++; bits = 7; rest = 0x00; } else @@ -2452,8 +2459,12 @@ tvb_get_string_enc(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp1250); break; - case ENC_3GPP_TS_23_038: - strbuf = tvb_get_ts_23_038_string(scope, tvb, offset, length); + case ENC_3GPP_TS_23_038_7BITS: + { + gint bit_offset = offset << 3; + gint no_of_chars = (length << 3) / 7; + strbuf = tvb_get_ts_23_038_7bits_string(scope, tvb, bit_offset, no_of_chars); + } break; case ENC_EBCDIC: @@ -2748,8 +2759,8 @@ tvb_get_stringz_enc(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, g strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp1250); break; - case ENC_3GPP_TS_23_038: - REPORT_DISSECTOR_BUG("TS 23.038 has no null character and doesn't support null-terminated strings"); + case ENC_3GPP_TS_23_038_7BITS: + REPORT_DISSECTOR_BUG("TS 23.038 7bits has no null character and doesn't support null-terminated strings"); break; case ENC_EBCDIC: diff --git a/epan/tvbuff.h b/epan/tvbuff.h index 424469130c..97e38efb1a 100644 --- a/epan/tvbuff.h +++ b/epan/tvbuff.h @@ -499,6 +499,19 @@ WS_DLL_PUBLIC guint8 *tvb_get_string(wmem_allocator_t *scope, tvbuff_t *tvb, WS_DLL_PUBLIC guint8 *tvb_get_string_enc(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, const gint length, const guint encoding); +/** + * Given a tvbuff, a bit offset, and a number of characters, allocate + * a buffer big enough to hold a non-null-terminated string of no_of_chars + * encoded according to 3GPP TS 23.038 7bits encoding at that offset, + * plus a trailing zero, copy the string into it, and return a pointer + * to the string. + * + * If scope is set to NULL it is the user's responsibility to g_free() + * the memory allocated by tvb_memdup(). Otherwise memory is + * automatically freed when the scope lifetime is reached. + */ +WS_DLL_PUBLIC gchar *tvb_get_ts_23_038_7bits_string(wmem_allocator_t *scope, + tvbuff_t *tvb, const gint bit_offset, gint no_of_chars); /** * Given a tvbuff and an offset, with the offset assumed to refer to |