示例#1
0
/**
 * 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;
}