/** * dissect_messageid is a utility function which * calculates the ID of the message. * * @see dissect_packetid() * @see dissect_reliable_message_index_base() * @see dissect_content_length() * @see dissect_reliable_message_number() * @see dissect_payload() * @param buffer the buffer to the data * @param offset the offset where to start reading the data * @param tree the parent tree where the dissected data is going to be inserted * @return int returns the messageid * */ static int dissect_messageid(tvbuff_t *buffer, int *offset, proto_tree *tree, packet_info *pinfo, gboolean separator) { gint messageid_length; guint8 messageid; gboolean col_write; messageid = tvb_get_guint8(buffer, (*offset)); switch(messageid) { case DISCONNECT: case DISCONNECTACK: case CONNECTSYN: case CONNECTSYNACK: case CONNECTACK: messageid_length = 4; break; default: messageid_length = 1; break; } proto_tree_add_uint_format_value(tree, hf_knet_messageid, buffer, *offset, messageid_length, messageid, "%s (%d)", val_to_str_const(messageid, packettypenames, "AppData or Malformed Message ID"), messageid); /* XXX - TCP reassembly disables writing columns which prevents populating COL_INFO if multiple KNET messages appear in a single packet that needed to be reassembled. Force making columns writable. */ if (separator) { col_write = col_get_writable(pinfo->cinfo); col_set_writable(pinfo->cinfo, TRUE); col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s (%d)", val_to_str_const(messageid, packettypenames, "AppData"), messageid); col_set_writable(pinfo->cinfo, col_write); } else { col_append_fstr(pinfo->cinfo, COL_INFO, "%s (%d)", val_to_str_const(messageid, packettypenames, "AppData"), messageid); } *offset += messageid_length; return messageid; }
/* Parse Short Message, only if UDH present * (otherwise this function is not called). * Call WSP dissector if port matches WSP traffic. */ static void parse_gsm_sms_ud_message(proto_tree *sm_tree, tvbuff_t *tvb, packet_info *pinfo, proto_tree *top_tree) { tvbuff_t *sm_tvb = NULL; proto_item *subtree, *tree; guint8 udh_len, udh, len; guint sm_len = tvb_reported_length (tvb); guint sm_data_len; guint32 i = 0; /* Multiple Messages UDH */ gboolean is_fragmented = FALSE; fragment_data *fd_sm = NULL; guint16 sm_id = 0, frags = 0, frag = 0; gboolean save_fragmented = FALSE, try_gsm_sms_ud_reassemble = FALSE; /* SMS Message reassembly */ gboolean reassembled = FALSE; guint32 reassembled_in = 0; /* Port Number UDH */ guint16 p_src = 0, p_dst = 0; gboolean ports_available = FALSE; udh_len = tvb_get_guint8(tvb, i++); tree = proto_tree_add_uint(sm_tree, hf_gsm_sms_udh_length, tvb, 0, 1, udh_len); tree = proto_item_add_subtree(tree, ett_udh); while (i < udh_len) { udh = tvb_get_guint8(tvb, i++); len = tvb_get_guint8(tvb, i++); subtree = proto_tree_add_uint(tree, hf_gsm_sms_udh_iei, tvb, i-2, 2+len, udh); switch (udh) { case 0x00: /* Multiple messages - 8-bit message ID */ if (len == 3) { sm_id = tvb_get_guint8(tvb, i++); frags = tvb_get_guint8(tvb, i++); frag = tvb_get_guint8(tvb, i++); if (frags > 1) is_fragmented = TRUE; proto_item_append_text(subtree, ": message %u, part %u of %u", sm_id, frag, frags); subtree = proto_item_add_subtree(subtree, ett_udh_ie); proto_tree_add_uint (subtree, hf_gsm_sms_udh_multiple_messages_msg_id, tvb, i-3, 1, sm_id); proto_tree_add_uint (subtree, hf_gsm_sms_udh_multiple_messages_msg_parts, tvb, i-2, 1, frags); proto_tree_add_uint (subtree, hf_gsm_sms_udh_multiple_messages_msg_part, tvb, i-1, 1, frag); } else { proto_item_append_text(subtree, " - Invalid format!"); i += len; } break; case 0x08: /* Multiple messages - 16-bit message ID */ if (len == 4) { sm_id = tvb_get_ntohs(tvb, i); i += 2; frags = tvb_get_guint8(tvb, i++); frag = tvb_get_guint8(tvb, i++); if (frags > 1) is_fragmented = TRUE; proto_item_append_text(subtree, ": message %u, part %u of %u", sm_id, frag, frags); subtree = proto_item_add_subtree(subtree, ett_udh_ie); proto_tree_add_uint (subtree, hf_gsm_sms_udh_multiple_messages_msg_id, tvb, i-4, 2, sm_id); proto_tree_add_uint (subtree, hf_gsm_sms_udh_multiple_messages_msg_parts, tvb, i-2, 1, frags); proto_tree_add_uint (subtree, hf_gsm_sms_udh_multiple_messages_msg_part, tvb, i-1, 1, frag); } else { proto_item_append_text(subtree, " - Invalid format!"); i += len; } break; case 0x04: /* Port Number UDH - 8-bit address */ if (len == 2) { /* Port fields */ p_dst = tvb_get_guint8(tvb, i++); p_src = tvb_get_guint8(tvb, i++); proto_item_append_text(subtree, ": source port %u, destination port %u", p_src, p_dst); subtree = proto_item_add_subtree(subtree, ett_udh_ie); proto_tree_add_uint (subtree, hf_gsm_sms_udh_ports_dst, tvb, i-2, 1, p_dst); proto_tree_add_uint (subtree, hf_gsm_sms_udh_ports_src, tvb, i-1, 1, p_src); ports_available = TRUE; } else { proto_item_append_text(subtree, " - Invalid format!"); i += len; } break; case 0x05: /* Port Number UDH - 16-bit address */ if (len == 4) { /* Port fields */ p_dst = tvb_get_ntohs(tvb, i); i += 2; p_src = tvb_get_ntohs(tvb, i); i += 2; proto_item_append_text(subtree, ": source port %u, destination port %u", p_src, p_dst); subtree = proto_item_add_subtree(subtree, ett_udh_ie); proto_tree_add_uint (subtree, hf_gsm_sms_udh_ports_dst, tvb, i-4, 2, p_dst); proto_tree_add_uint (subtree, hf_gsm_sms_udh_ports_src, tvb, i-2, 2, p_src); ports_available = TRUE; } else { proto_item_append_text(subtree, " - Invalid format!"); i += len; } break; default: i += len; break; } } if (tvb_reported_length_remaining(tvb, i) <= 0) return; /* No more data */ /* * XXX - where does the "1" come from? If it weren't there, * "sm_data_len" would, I think, be the same as * "tvb_reported_length_remaining(tvb, i)". * * I think that the above check ensures that "sm_len" won't * be less than or equal to "udh_len", so it ensures that * "sm_len" won't be less than "1 + udh_len", so we don't * have to worry about "sm_data_len" being negative. */ sm_data_len = sm_len - (1 + udh_len); if (sm_data_len == 0) return; /* no more data */ /* * Try reassembling the packets. * XXX - fragment numbers are 1-origin, but the fragment number * field could be 0. * Should we flag a fragmented message with a fragment number field * of 0? * What if the fragment count is 0? Should we flag that as well? */ if ( is_fragmented && frag != 0 && frags != 0 && tvb_bytes_exist (tvb, i, sm_data_len) ) { try_gsm_sms_ud_reassemble = TRUE; save_fragmented = pinfo->fragmented; pinfo->fragmented = TRUE; fd_sm = fragment_add_seq_check (tvb, i, pinfo, sm_id, /* guint32 ID for fragments belonging together */ sm_fragment_table, /* list of message fragments */ sm_reassembled_table, /* list of reassembled messages */ frag-1, /* guint32 fragment sequence number */ sm_data_len, /* guint32 fragment length */ (frag != frags)); /* More fragments? */ if (fd_sm) { reassembled = TRUE; reassembled_in = fd_sm->reassembled_in; } sm_tvb = process_reassembled_data(tvb, i, pinfo, "Reassembled Short Message", fd_sm, &sm_frag_items, NULL, sm_tree); if (reassembled) { /* Reassembled */ col_append_str (pinfo->cinfo, COL_INFO, " (Short Message Reassembled)"); } else { /* Not last packet of reassembled Short Message */ col_append_fstr (pinfo->cinfo, COL_INFO, " (Short Message fragment %u of %u)", frag, frags); } } /* Else: not fragmented */ if (! sm_tvb) /* One single Short Message, or not reassembled */ sm_tvb = tvb_new_subset_remaining (tvb, i); /* Try calling a subdissector */ if (sm_tvb) { if ((reassembled && pinfo->fd->num == reassembled_in) || frag==0 || (frag==1 && try_dissect_1st_frag)) { /* Try calling a subdissector only if: * - the Short Message is reassembled in this very packet, * - the Short Message consists of only one "fragment", * - the preference "Always Try Dissection for 1st SM fragment" * is switched on, and this is the SM's 1st fragment. */ if ( ports_available ) { gboolean disallow_write = FALSE; /* TRUE if we changed writability of the columns of the summary */ if ( prevent_subdissectors_changing_columns && col_get_writable(pinfo->cinfo) ) { disallow_write = TRUE; col_set_writable(pinfo->cinfo, FALSE); } if ( port_number_udh_means_wsp ) { call_dissector (wsp_handle, sm_tvb, pinfo, top_tree); } else { if (! dissector_try_port(gsm_sms_dissector_table, p_src, sm_tvb, pinfo, top_tree)) { if (! dissector_try_port(gsm_sms_dissector_table, p_dst, sm_tvb, pinfo, top_tree)) { if (sm_tree) { /* Only display if needed */ proto_tree_add_text (sm_tree, sm_tvb, 0, -1, "Short Message body"); } } } } if ( disallow_write ) col_set_writable(pinfo->cinfo, TRUE); } else { /* No ports IE */ proto_tree_add_text (sm_tree, sm_tvb, 0, -1, "Short Message body"); } } else { /* The packet is not reassembled, * or it is reassembled in another packet */ proto_tree_add_text (sm_tree, sm_tvb, 0, -1, "Unreassembled Short Message fragment %u of %u", frag, frags); } } if (try_gsm_sms_ud_reassemble) /* Clean up defragmentation */ pinfo->fragmented = save_fragmented; return; }