Example #1
0
void
ethertype(guint16 etype, tvbuff_t *tvb, int offset_after_etype,
		packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree,
		int etype_id, int trailer_id, int fcs_len)
{
	const char		*description;
	tvbuff_t		*volatile next_tvb;
	guint			length_before;
	gint			captured_length, reported_length;
	volatile gboolean	dissector_found = FALSE;
	const char		*volatile saved_proto;

	/* Add the Ethernet type to the protocol tree */
	if (tree) {
		proto_tree_add_uint(fh_tree, etype_id, tvb,
		    offset_after_etype - 2, 2, etype);
	}

	/* Get the captured length and reported length of the data
	   after the Ethernet type. */
	captured_length = tvb_length_remaining(tvb, offset_after_etype);
	reported_length = tvb_reported_length_remaining(tvb,
	    offset_after_etype);

	/* Remember how much data there is after the Ethernet type,
	   including any trailer and FCS. */
	length_before = reported_length;

	/* Construct a tvbuff for the payload after the Ethernet type.
	   If the FCS length is positive, remove the FCS.
	   (If it's zero, there's no FCS; if it's negative,
	   we don't know whether there's an FCS, so we'll
	   guess based on the length of the trailer.) */
	if (fcs_len > 0) {
		if (captured_length >= 0 && reported_length >= 0) {
			if (reported_length >= fcs_len)
				reported_length -= fcs_len;
			if (captured_length > reported_length)
				captured_length = reported_length;
		}
	}
	next_tvb = tvb_new_subset(tvb, offset_after_etype, captured_length,
	    reported_length);

	pinfo->ethertype = etype;

	/* Look for sub-dissector, and call it if found.
	   Catch exceptions, so that if the reported length of "next_tvb"
	   was reduced by some dissector before an exception was thrown,
	   we can still put in an item for the trailer. */
	saved_proto = pinfo->current_proto;
	TRY {
		dissector_found = dissector_try_port(ethertype_dissector_table,
		    etype, next_tvb, pinfo, tree);
	}
	CATCH(BoundsError) {
		/* Somebody threw BoundsError, which means that:

		     1) a dissector was found, so we don't need to
		        dissect the payload as data or update the
		        protocol or info columns;

		     2) dissecting the payload found that the packet was
		        cut off by a snapshot length before the end of
		        the payload.  The trailer comes after the payload,
		        so *all* of the trailer is cut off, and we'll
		        just get another BoundsError if we add the trailer.

		   Therefore, we just rethrow the exception so it gets
		   reported; we don't dissect the trailer or do anything
		   else. */
		 RETHROW;
	}
	CATCH(OutOfMemoryError) {
		 RETHROW;
	}
	CATCH_ALL {
		/* Somebody threw an exception other than BoundsError, which
		   means that a dissector was found, so we don't need to
		   dissect the payload as data or update the protocol or info
		   columns.  We just show the exception and then drive on
		   to show the trailer, after noting that a dissector was
		   found and restoring the protocol value that was in effect
		   before we called the subdissector. */
		show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
		dissector_found = TRUE;
		pinfo->current_proto = saved_proto;
	}
	ENDTRY;

	if (!dissector_found) {
		/* No sub-dissector found.
		   Label rest of packet as "Data" */
		call_dissector(data_handle,next_tvb, pinfo, tree);

		/* Label protocol */
		if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
			col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x",
			    etype);
		}
		if (check_col(pinfo->cinfo, COL_INFO)) {
			description = match_strval(etype, etype_vals);
			if (description) {
				col_add_str(pinfo->cinfo, COL_INFO,
				    description);
			}
		}
	}

	add_dix_trailer(pinfo, fh_tree, trailer_id, tvb, next_tvb, offset_after_etype,
	    length_before, fcs_len);
}
Example #2
0
static int dissect_bat_batman_v5(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
{
	proto_item *tf, *tgw;
	proto_tree *bat_batman_tree = NULL, *flag_tree;
	struct batman_packet_v5 *batman_packeth;
	const guint8  *old_orig_addr, *orig_addr;
	guint32 old_orig, orig;
	gint i;

	tvbuff_t *next_tvb;

	batman_packeth = wmem_new(wmem_packet_scope(), struct batman_packet_v5);

	batman_packeth->version = tvb_get_guint8(tvb, offset+0);
	batman_packeth->flags = tvb_get_guint8(tvb, offset+1);
	batman_packeth->ttl = tvb_get_guint8(tvb, offset+2);
	batman_packeth->gwflags = tvb_get_guint8(tvb, offset+3);
	batman_packeth->seqno = tvb_get_ntohs(tvb, offset+4);
	batman_packeth->gwport = tvb_get_ntohs(tvb, offset+6);
	orig_addr = tvb_get_ptr(tvb, offset+8, 4);
	orig = tvb_get_ipv4(tvb, offset+8);
	SET_ADDRESS(&batman_packeth->orig, AT_IPv4, 4, orig_addr);
	old_orig_addr = tvb_get_ptr(tvb, offset+12, 4);
	old_orig = tvb_get_ipv4(tvb, offset+12);
	SET_ADDRESS(&batman_packeth->old_orig, AT_IPv4, 4, old_orig_addr);
	batman_packeth->tq = tvb_get_guint8(tvb, offset+16);
	batman_packeth->hna_len = tvb_get_guint8(tvb, offset+17);

	/* Set info column */
	col_add_fstr(pinfo->cinfo, COL_INFO, "Seq=%u", batman_packeth->seqno);

	/* Set tree info */
	if (tree) {
		proto_item *ti;

		if (PTREE_DATA(tree)->visible) {
			ti = proto_tree_add_protocol_format(tree, proto_bat_plugin, tvb, offset, BATMAN_PACKET_V5_SIZE,
							    "B.A.T.M.A.N., Orig: %s (%s)",
							    get_hostname(orig), ip_to_str((const guint8 *)batman_packeth->orig.data));
		} else {
			ti = proto_tree_add_item(tree, proto_bat_plugin, tvb, offset, BATMAN_PACKET_V5_SIZE, ENC_NA);
		}
		bat_batman_tree = proto_item_add_subtree(ti, ett_bat_batman);
	}

	/* items */
	proto_tree_add_item(bat_batman_tree, hf_bat_batman_version, tvb, offset, 1, ENC_BIG_ENDIAN);
	offset += 1;

	tf = proto_tree_add_item(bat_batman_tree, hf_bat_batman_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
	/* <flags> */
	flag_tree =  proto_item_add_subtree(tf, ett_bat_batman_flags);
	proto_tree_add_boolean(flag_tree, hf_bat_batman_flags_unidirectional, tvb, offset, 1, batman_packeth->flags);
	proto_tree_add_boolean(flag_tree, hf_bat_batman_flags_directlink, tvb, offset, 1, batman_packeth->flags);
	/* </flags> */
	offset += 1;

	proto_tree_add_item(bat_batman_tree, hf_bat_batman_ttl, tvb, offset, 1, ENC_BIG_ENDIAN);
	offset += 1;

	tgw = proto_tree_add_item(bat_batman_tree, hf_bat_batman_gwflags, tvb, offset, 1, ENC_BIG_ENDIAN);
	dissect_bat_gwflags(tvb, batman_packeth->gwflags, offset, tgw);
	offset += 1;

	proto_tree_add_item(bat_batman_tree, hf_bat_batman_seqno, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;

	proto_tree_add_item(bat_batman_tree, hf_bat_batman_gwport, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;

	proto_tree_add_ipv4(bat_batman_tree, hf_bat_batman_orig, tvb, offset, 4, orig);
	offset += 4;

	proto_tree_add_ipv4(bat_batman_tree, hf_bat_batman_old_orig, tvb, offset, 4,  old_orig);
	offset += 4;

	proto_tree_add_item(bat_batman_tree, hf_bat_batman_tq, tvb, offset, 1, ENC_BIG_ENDIAN);
	offset += 1;

	proto_tree_add_item(bat_batman_tree, hf_bat_batman_hna_len, tvb, offset, 1, ENC_BIG_ENDIAN);
	offset += 1;

	tap_queue_packet(bat_tap, pinfo, batman_packeth);

	for (i = 0; i < batman_packeth->hna_len; i++) {
		next_tvb = tvb_new_subset(tvb, offset, 5, 5);

		if (have_tap_listener(bat_follow_tap)) {
			tap_queue_packet(bat_follow_tap, pinfo, next_tvb);
		}

		dissect_bat_hna(next_tvb, pinfo, bat_batman_tree);
		offset += 5;
	}

	return offset;
}
/*FUNCTION:------------------------------------------------------
 *  NAME
 *      dissect_zbee_secure
 *  DESCRIPTION
 *      Dissects and decrypts secured ZigBee frames.
 *
 *      Will return a valid tvbuff only if security processing was
 *      successful. If processing fails, then this function will
 *      handle internally and return NULL.
 *  PARAMETERS
 *      tvbuff_t    *tvb    - pointer to buffer containing raw packet.
 *      packet_info *pinfo  - pointer to packet information fields
 *      proto_tree  *tree   - pointer to data tree Wireshark uses to display packet.
 *      guint       offset  - pointer to the start of the auxilliary security header.
 *      guint64     src64   - extended source address, or 0 if unknown.
 *  RETURNS
 *      tvbuff_t *
 *---------------------------------------------------------------
 */
tvbuff_t *
dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint offset)
{
    proto_tree     *sec_tree = NULL;
    proto_item     *sec_root;
    proto_tree     *field_tree;
    proto_item     *ti;

    zbee_security_packet    packet;
    guint           mic_len;
    gint            payload_len;
    tvbuff_t       *payload_tvb;

#ifdef HAVE_LIBGCRYPT
    guint8             *enc_buffer;
    guint8             *dec_buffer;
    gboolean            decrypted;
    GSList            **nwk_keyring;
    GSList             *GSList_i;
    key_record_t       *key_rec = NULL;
#endif
    zbee_nwk_hints_t   *nwk_hints;
    ieee802154_hints_t *ieee_hints;
    ieee802154_map_rec *map_rec = NULL;

    /* Init */
    memset(&packet, 0, sizeof(zbee_security_packet));

    /* Get pointers to any useful frame data from lower layers */
    nwk_hints = (zbee_nwk_hints_t *)p_get_proto_data(pinfo->fd,
        proto_get_id_by_filter_name(ZBEE_PROTOABBREV_NWK), 0);
    ieee_hints = (ieee802154_hints_t *)p_get_proto_data(pinfo->fd,
        proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);

    /* Create a subtree for the security information. */
    if (tree) {
        sec_root = proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset), "ZigBee Security Header");
        sec_tree = proto_item_add_subtree(sec_root, ett_zbee_sec);
    }

    /*  Get and display the Security control field */
    packet.control  = tvb_get_guint8(tvb, offset);

    /* Patch the security level. */
    packet.control &= ~ZBEE_SEC_CONTROL_LEVEL;
    packet.control |= (ZBEE_SEC_CONTROL_LEVEL & gPREF_zbee_sec_level);

    /*
     * Eww, I think I just threw up a little...  ZigBee requires this field
     * to be patched before computing the MIC, but we don't have write-access
     * to the tvbuff. So we need to allocate a copy of the whole thing just
     * so we can fix these 3 bits. Memory allocated by ep_tvb_memdup() is
     * automatically freed before the next packet is processed.
     */
#ifdef HAVE_LIBGCRYPT
    enc_buffer = (guint8 *)ep_tvb_memdup(tvb, 0, tvb_length(tvb));
    /*
     * Override the const qualifiers and patch the security level field, we
     * know it is safe to overide the const qualifiers because we just
     * allocated this memory via ep_tvb_memdup().
     */
    enc_buffer[offset] = packet.control;
#endif /* HAVE_LIBGCRYPT */
    packet.level    = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_LEVEL);
    packet.key_id   = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_KEY);
    packet.nonce    = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_NONCE);
    if (tree) {
        ti = proto_tree_add_text(sec_tree, tvb, offset, 1, "Security Control Field");
        field_tree = proto_item_add_subtree(ti, ett_zbee_sec_control);

        proto_tree_add_uint(field_tree, hf_zbee_sec_key_id, tvb, offset, 1,
                                packet.control & ZBEE_SEC_CONTROL_KEY);
        proto_tree_add_boolean(field_tree, hf_zbee_sec_nonce, tvb, offset, 1,
                                packet.control & ZBEE_SEC_CONTROL_NONCE);
    }
    offset += 1;

    /* Get and display the frame counter field. */
    packet.counter = tvb_get_letohl(tvb, offset);
    if (tree) {
        proto_tree_add_uint(sec_tree, hf_zbee_sec_counter, tvb, offset, 4, packet.counter);
    }
    offset += 4;

    if (packet.nonce) {
        /* Get and display the source address of the device that secured this payload. */
        packet.src64 = tvb_get_letoh64(tvb, offset);
        if (tree) {
            proto_tree_add_item(sec_tree, hf_zbee_sec_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
        }
#if 1
        if (!pinfo->fd->flags.visited) {
            switch ( packet.key_id ) {
                case ZBEE_SEC_KEY_LINK:
                if (nwk_hints && ieee_hints) {
                    /* Map this long address with the nwk layer short address. */
                    nwk_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, nwk_hints->src,
                            ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->fd->num);
                }
                break;

                case ZBEE_SEC_KEY_NWK:
                if (ieee_hints) {
                    /* Map this long address with the ieee short address. */
                    ieee_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, ieee_hints->src16,
                        ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->fd->num);
                }
                break;

                /* We ignore the extended source addresses used to encrypt payloads with these
                 * types of keys, because they can emerge from APS tunnels created by nodes whose
                 * short address is not recorded in the packet. */
                case ZBEE_SEC_KEY_TRANSPORT:
                case ZBEE_SEC_KEY_LOAD:
                break;
            }
        }
#endif
        offset += 8;
    }
    else {
        /* Look for a source address in hints */
        switch ( packet.key_id ) {
            case ZBEE_SEC_KEY_NWK:
                /* use the ieee extended source address for NWK decryption */
                if ( ieee_hints && (map_rec = ieee_hints->map_rec) )
                    packet.src64 = map_rec->addr64;
                else if (tree)
                    proto_tree_add_text(sec_tree, tvb, 0, 0, "[Extended Source: Unknown]");
                break;

            default:
                /* use the nwk extended source address for APS decryption */
                if ( nwk_hints && (map_rec = nwk_hints->map_rec) )
                    packet.src64 = map_rec->addr64;
                else if (tree)
                    proto_tree_add_text(sec_tree, tvb, 0, 0, "[Extended Source: Unknown]");
                break;
        }
    }

    if (packet.key_id == ZBEE_SEC_KEY_NWK) {
        /* Get and display the key sequence number. */
        packet.key_seqno = tvb_get_guint8(tvb, offset);
        if (tree) {
            proto_tree_add_uint(sec_tree, hf_zbee_sec_key_seqno, tvb, offset, 1, packet.key_seqno);
        }
        offset += 1;
    }

    /* Determine the length of the MIC. */
    switch (packet.level) {
        case ZBEE_SEC_ENC:
        case ZBEE_SEC_NONE:
        default:
            mic_len=0;
            break;

        case ZBEE_SEC_ENC_MIC32:
        case ZBEE_SEC_MIC32:
            mic_len=4;
            break;

        case ZBEE_SEC_ENC_MIC64:
        case ZBEE_SEC_MIC64:
            mic_len=8;
            break;

        case ZBEE_SEC_ENC_MIC128:
        case ZBEE_SEC_MIC128:
            mic_len=16;
            break;
    } /* switch */

    /* Get and display the MIC. */
    if (mic_len) {
        /* Display the MIC. */
        if (tree) {
            proto_tree_add_item(sec_tree, hf_zbee_sec_mic, tvb, (gint)(tvb_length(tvb)-mic_len),
                   mic_len, ENC_NA);
        }
    }

    /* Check for null payload. */
    if ( !(payload_len = tvb_reported_length_remaining(tvb, offset+mic_len)) ) {
        return NULL;
    } else if ( payload_len < 0 ) {
        THROW(ReportedBoundsError);
    }

    /**********************************************
     *  Perform Security Operations on the Frame  *
     **********************************************
     */
    if ((packet.level == ZBEE_SEC_NONE) ||
        (packet.level == ZBEE_SEC_MIC32) ||
        (packet.level == ZBEE_SEC_MIC64) ||
        (packet.level == ZBEE_SEC_MIC128)) {

        /* Payload is only integrity protected. Just return the sub-tvbuff. */
        return tvb_new_subset(tvb, offset, payload_len, payload_len);
    }

#ifdef HAVE_LIBGCRYPT
    /* Allocate memory to decrypt the payload into. */
    dec_buffer = (guint8 *)g_malloc(payload_len);

    decrypted = FALSE;
    if ( packet.src64 ) {
        if (pinfo->fd->flags.visited) {
            if ( nwk_hints ) {
                /* Use previously found key */
                switch ( packet.key_id ) {
                    case ZBEE_SEC_KEY_NWK:
                        if ( (key_rec = nwk_hints->nwk) ) {
                            decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                                payload_len, mic_len, nwk_hints->nwk->key);
                        }
                        break;

                    default:
                        if ( (key_rec = nwk_hints->link) ) {
                            decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                                payload_len, mic_len, nwk_hints->link->key);
                        }
                        break;
                }
            }
        } /* ( !pinfo->fd->flags.visited ) */
        else {
            /* We only search for sniffed keys in the first pass,
             * to save time, and because decrypting with keys
             * transported in future packets is cheating */

            /* Lookup NWK and link key in hash for this pan. */
            /* This overkill approach is a placeholder for a hash that looks up
             * a key ring for a link key associated with a pair of devices.
             */
            if ( nwk_hints ) {
                nwk_keyring = (GSList **)g_hash_table_lookup(zbee_table_nwk_keyring, &nwk_hints->src_pan);

                if ( nwk_keyring ) {
                    GSList_i = *nwk_keyring;
                    while ( GSList_i && !decrypted ) {
                        decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                                payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key);

                        if (decrypted) {
                            /* save pointer to the successful key record */
                            switch (packet.key_id) {
                                case ZBEE_SEC_KEY_NWK:
                                    key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data);
                                    break;

                                default:
                                    key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data);
                                    break;
                            }
                        } else {
                            GSList_i = g_slist_next(GSList_i);
                        }
                    }
                }

                /* Loop through user's password table for preconfigured keys, our last resort */
                GSList_i = zbee_pc_keyring;
                while ( GSList_i && !decrypted ) {
                    decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                            payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key);

                    if (decrypted) {
                        /* save pointer to the successful key record */
                        switch (packet.key_id) {
                            case ZBEE_SEC_KEY_NWK:
                                key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data);
                                break;

                            default:
                                key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data);
                                break;
                        }
                    } else {
                        GSList_i = g_slist_next(GSList_i);
                    }
                }
            }
        } /* ( ! pinfo->fd->flags.visited ) */
    } /* ( packet.src64 ) */

    if ( decrypted ) {
        if ( tree && key_rec ) {
            if ( key_rec->frame_num == ZBEE_SEC_PC_KEY ) {
                ti = proto_tree_add_text(sec_tree, tvb, 0, 0, "Decryption Key: %s", key_rec->label);
            } else {
                ti = proto_tree_add_uint(sec_tree, hf_zbee_sec_key_origin, tvb, 0, 0,
                        key_rec->frame_num);
            }
            PROTO_ITEM_SET_GENERATED(ti);
        }

        /* Found a key that worked, setup the new tvbuff_t and return */
        payload_tvb = tvb_new_child_real_data(tvb, dec_buffer, payload_len, payload_len);
        tvb_set_free_cb(payload_tvb, g_free); /* set up callback to free dec_buffer */
        add_new_data_source(pinfo, payload_tvb, "Decrypted ZigBee Payload");

        /* Done! */
        return payload_tvb;
    }

    g_free(dec_buffer);
#endif /* HAVE_LIBGCRYPT */

    /* Add expert info. */
    expert_add_info(pinfo, sec_tree, &ei_zbee_sec_encrypted_payload);
    /* Create a buffer for the undecrypted payload. */
    payload_tvb = tvb_new_subset(tvb, offset, payload_len, -1);
    /* Dump the payload to the data dissector. */
    call_dissector(data_handle, payload_tvb, pinfo, tree);
    /* Couldn't decrypt, so return NULL. */
    return NULL;
} /* dissect_zbee_secure */
Example #4
0
static void
dissect_fip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    guint       op;
    guint       sub;
    guint       rlen;
    proto_item *ti;
    proto_item *item;
    proto_tree *fip_tree;
    proto_tree *subtree;
    guint       dtype;
    guint       dlen;
    guint       desc_offset;
    guint       val;
    tvbuff_t   *desc_tvb;
    const char *info;
    const char *text;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "FIP");
    col_clear(pinfo->cinfo, COL_INFO);

    if (!tvb_bytes_exist(tvb, 0, FIP_HEADER_LEN)) {
        col_set_str(pinfo->cinfo, COL_INFO, "[packet too short]");
        if (tree)
            proto_tree_add_protocol_format(tree, proto_fip, tvb, 0,
                                            -1, "FIP [packet too short]");
        return;
    }

    op  = tvb_get_ntohs(tvb, 2);
    sub = tvb_get_guint8(tvb, 5);

    switch (op) {
    case FIP_OP_DISC:
        info = val_to_str(sub, fip_disc_subcodes, "Discovery 0x%x");
        break;
    case FIP_OP_LS:
        info = val_to_str(sub, fip_ls_subcodes, "Link Service 0x%x");
        break;
    case FIP_OP_CTRL:
        info = val_to_str(sub, fip_ctrl_subcodes, "Control 0x%x");
        break;
    case FIP_OP_VLAN:
        info = val_to_str(sub, fip_vlan_subcodes, "VLAN 0x%x");
        break;
    case FIP_OP_VN2VN:
        info = val_to_str(sub, fip_vn2vn_subcodes, "VN2VN 0x%x");
        break;
    default:
        info = val_to_str(op, fip_opcodes, "Unknown op 0x%x");
        break;
    }

    col_add_str(pinfo->cinfo, COL_INFO, info);

    rlen = tvb_get_ntohs(tvb, 6);

    ti = proto_tree_add_protocol_format(tree, proto_fip, tvb, 0,
                                        FIP_HEADER_LEN + rlen * FIP_BPW,
                                        "FIP %s", info);
    fip_tree = proto_item_add_subtree(ti, ett_fip);
    proto_tree_add_item(fip_tree, hf_fip_ver, tvb, 0, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(fip_tree, hf_fip_op, tvb, 2, 2, ENC_BIG_ENDIAN);
    switch (op) {
    case FIP_OP_DISC:
        proto_tree_add_item(fip_tree, hf_fip_disc_subcode, tvb, 5, 1, ENC_BIG_ENDIAN);
        break;
    case FIP_OP_LS:
        proto_tree_add_item(fip_tree, hf_fip_ls_subcode, tvb, 5, 1, ENC_BIG_ENDIAN);
        break;
    case FIP_OP_CTRL:
        proto_tree_add_item(fip_tree, hf_fip_ctrl_subcode, tvb, 5, 1, ENC_BIG_ENDIAN);
        break;
    case FIP_OP_VLAN:
        proto_tree_add_item(fip_tree, hf_fip_vlan_subcode, tvb, 5, 1, ENC_BIG_ENDIAN);
        break;
    case FIP_OP_VN2VN:
        proto_tree_add_item(fip_tree, hf_fip_vn2vn_subcode, tvb, 5, 1, ENC_BIG_ENDIAN);
        break;
    default:
        proto_tree_add_item(fip_tree, hf_fip_hex_subcode, tvb, 5, 1, ENC_BIG_ENDIAN);
        break;
    }
    proto_tree_add_item(fip_tree, hf_fip_dlen, tvb, 6, 2, ENC_BIG_ENDIAN);

    proto_tree_add_bitmask(fip_tree, tvb, 8, hf_fip_flags,
            ett_fip_flags, hf_fip_flags_fields, ENC_BIG_ENDIAN);

    desc_offset = FIP_HEADER_LEN;
    rlen *= FIP_BPW;
    proto_tree_add_bytes_format(fip_tree, hf_fip_descriptors, tvb, desc_offset, rlen, NULL, "Descriptors");

    while ((rlen > 0) && tvb_bytes_exist(tvb, desc_offset, 2)) {
        dlen = tvb_get_guint8(tvb, desc_offset + 1) * FIP_BPW;
        if (!dlen) {
            proto_tree_add_expert(fip_tree, pinfo, &ei_fip_descriptors, tvb, desc_offset, -1);
            break;
        }
        if (!tvb_bytes_exist(tvb, desc_offset, dlen) || dlen > rlen) {
            break;
        }
        desc_tvb = tvb_new_subset(tvb, desc_offset, dlen, -1);
        dtype = tvb_get_guint8(desc_tvb, 0);
        desc_offset += dlen;
        rlen -= dlen;

        switch (dtype) {
        case FIP_DT_PRI:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_pri, &item);
            proto_tree_add_item(subtree, hf_fip_desc_pri, desc_tvb,
                    3, 1, ENC_BIG_ENDIAN);
            proto_item_append_text(item, "%u", tvb_get_guint8(desc_tvb, 3));
            break;
        case FIP_DT_MAC:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_mac, &item);
            proto_tree_add_item(subtree, hf_fip_desc_mac, desc_tvb,
                    2, 6, ENC_NA);
            proto_item_append_text(item, "%s",
                    tvb_bytes_to_ep_str_punct(desc_tvb, 2, 6, ':'));
            break;
        case FIP_DT_MAP_OUI:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_map, &item);
            text = tvb_fc_to_str(desc_tvb, 5);
            proto_tree_add_string(subtree, hf_fip_desc_map, desc_tvb,
                    5, 3, text);
            proto_item_append_text(item, "%s", text);
            break;
        case FIP_DT_NAME:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_name, &item);
            text = tvb_fcwwn_to_str(desc_tvb, 4);
            proto_tree_add_string(subtree, hf_fip_desc_name,
                    desc_tvb, 4, 8, text);
            proto_item_append_text(item, "%s", text);
            break;
        case FIP_DT_FAB:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_fab, &item);
            proto_tree_add_item(subtree, hf_fip_desc_fab_vfid, desc_tvb,
                    2, 2, ENC_BIG_ENDIAN);
            text = tvb_fc_to_str(desc_tvb, 5);
            proto_tree_add_string(subtree, hf_fip_desc_fab_map, desc_tvb,
                    5, 3, text);
            text = tvb_fcwwn_to_str(desc_tvb, 8);
            proto_tree_add_string(subtree, hf_fip_desc_fab_name,
                    desc_tvb, 8, 8, text);
            proto_item_append_text(item, "%s", text);
            break;
        case FIP_DT_FCOE_SIZE:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_mdl, &item);
            proto_tree_add_item(subtree, hf_fip_desc_fcoe_size, desc_tvb,
                    2, 2, ENC_BIG_ENDIAN);
            proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2));
            break;
        case FIP_DT_FLOGI:
        case FIP_DT_FDISC:
        case FIP_DT_LOGO:
        case FIP_DT_ELP: {
            tvbuff_t *ls_tvb;
            fc_data_t fc_data = {ETHERTYPE_FIP, 0};

            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_caps, &item);
            ls_tvb = tvb_new_subset(desc_tvb, 4, dlen - 4, -1);
            call_dissector_with_data(fc_handle, ls_tvb, pinfo, subtree, &fc_data);
            proto_item_append_text(item, "%u bytes", dlen - 4);
        }
            break;
        case FIP_DT_VN:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_vn, &item);
            proto_tree_add_item(subtree, hf_fip_desc_vn_mac, desc_tvb,
                    2, 6, ENC_NA);
            proto_tree_add_item(subtree, hf_fip_desc_vn_fid, desc_tvb,
                    9, 3, ENC_BIG_ENDIAN);
            text = tvb_fcwwn_to_str(desc_tvb, 12);
            proto_tree_add_string(subtree, hf_fip_desc_vn_wwpn,
                    desc_tvb, 12, 8, text);
            proto_item_append_text(item, "MAC %s  FC_ID %6.6x",
                    tvb_bytes_to_ep_str_punct(desc_tvb, 2, 6, ':'),
                    tvb_get_ntoh24(desc_tvb, 9));
            break;
        case FIP_DT_FKA:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_fka, &item);
            val = tvb_get_ntohl(desc_tvb, 4);
            proto_tree_add_uint_format_value(subtree, hf_fip_desc_fka,
                    desc_tvb, 4, 4, val, "%u ms", val);
            proto_item_append_text(item, "%u ms", val);
            break;
        case FIP_DT_VEND:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_vend, &item);
            proto_tree_add_item(subtree, hf_fip_desc_vend, desc_tvb,
                    4, 8, ENC_NA);
            if (tvb_bytes_exist(desc_tvb, 9, -1)) {
                proto_tree_add_item(subtree, hf_fip_desc_vend_data,
                     desc_tvb, 9, -1, ENC_NA);
            }
            break;
        case FIP_DT_VLAN:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_vlan, &item);
            proto_tree_add_item(subtree, hf_fip_desc_vlan, desc_tvb,
                    2, 2, ENC_BIG_ENDIAN);
            proto_item_append_text(item, "%u", tvb_get_ntohs(desc_tvb, 2));
            break;
        case FIP_DT_FC4F:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_fc4f, &item);
            fip_desc_fc4f(desc_tvb, subtree, item);
            break;
        default:
            subtree = fip_desc_type_len(fip_tree, desc_tvb, dtype, ett_fip_dt_unk, &item);
            proto_tree_add_item(subtree, hf_fip_desc_unk, desc_tvb,
                    2, -1, ENC_NA);
            break;
        }
    }
}
Example #5
0
void
dissect_802_3(volatile int length, gboolean is_802_2, tvbuff_t *tvb,
	      int offset_after_length, packet_info *pinfo, proto_tree *tree,
	      proto_tree *fh_tree, int length_id, int trailer_id, expert_field* ei_len,
	      int fcs_len)
{
  proto_item		*length_it;
  tvbuff_t		*volatile next_tvb = NULL;
  tvbuff_t		*trailer_tvb = NULL;
  const char		*saved_proto;
  gint			captured_length, reported_length;
  void			*pd_save;

  length_it = proto_tree_add_uint(fh_tree, length_id, tvb,
                                  offset_after_length - 2, 2, length);

  /* Get the length of the payload.
     If the FCS length is positive, remove the FCS.
     (If it's zero, there's no FCS; if it's negative, we don't know whether
     there's an FCS, so we'll guess based on the length of the trailer.) */
  reported_length = tvb_reported_length_remaining(tvb, offset_after_length);
  if (fcs_len > 0) {
    if (reported_length >= fcs_len)
      reported_length -= fcs_len;
  }

  /* Make sure the length in the 802.3 header doesn't go past the end of
     the payload. */
  if (length > reported_length) {
    length = reported_length;
    expert_add_info(pinfo, length_it, ei_len);
  }

  /* Give the next dissector only 'length' number of bytes. */
  captured_length = tvb_length_remaining(tvb, offset_after_length);
  if (captured_length > length)
    captured_length = length;
  next_tvb = tvb_new_subset(tvb, offset_after_length, captured_length, length);

  /* Dissect the payload either as IPX or as an LLC frame.
     Catch non-fatal exceptions, so that if the reported length
     of "next_tvb" was reduced by some dissector before an
     exception was thrown, we can still put in an item for
     the trailer. */
  saved_proto = pinfo->current_proto;
  pd_save = pinfo->private_data;
  TRY {
    if (is_802_2)
      call_dissector(llc_handle, next_tvb, pinfo, tree);
    else {
      /* Check if first three bits of payload are 0x7.
         If so, then payload is IPX.  If not, then it's CCSDS.
         Refer to packet-eth.c for setting of is_802_2 variable. */
      if (tvb_get_bits8(next_tvb, 0, 3) == 7)
        call_dissector(ipx_handle, next_tvb, pinfo, tree);
      else
        call_dissector(ccsds_handle, next_tvb, pinfo, tree);
    }
  }
  CATCH_NONFATAL_ERRORS {
    /* Somebody threw an exception that means that there was a problem
       dissecting the payload; that means that a dissector was found,
       so we don't need to dissect the payload as data or update the
       protocol or info columns.

       Just show the exception and then drive on to show the trailer,
       after noting that a dissector was found and restoring the
       protocol value that was in effect before we called the subdissector. */
    pinfo->private_data = pd_save;

    show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
  }
  ENDTRY;

  /* Restore the protocol value, so that any exception thrown by
     tvb_new_subset_remaining() refers to the protocol for which
     this is a trailer, and restore the private_data structure in
     case one of the called dissectors modified it. */
  pinfo->private_data = pd_save;
  pinfo->current_proto = saved_proto;

  /* Construct a tvbuff for the trailer; if the trailer is past the
     end of the captured data, this will throw a BoundsError, which
     is what we want, as it'll report that the packet was cut short. */
  trailer_tvb = tvb_new_subset_remaining(tvb, offset_after_length + length);

  add_ethernet_trailer(pinfo, tree, fh_tree, trailer_id, tvb, trailer_tvb, fcs_len);
}
Example #6
0
static void
dissect_fcp_cmnd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, proto_tree *tree, conversation_t *conversation, fc_hdr *fchdr, fcp_conv_data_t *fcp_conv_data)
{
    int          offset  = 0;
    int          add_len = 0;
    guint8       flags, rwflags, lun0;
    guint16      lun     = 0xffff;
    tvbuff_t    *cdb_tvb;
    int          tvb_len, tvb_rlen;
    itl_nexus_t *itl     = NULL;
    proto_item  *hidden_item;

    /* Determine the length of the FCP part of the packet */
    flags = tvb_get_guint8(tvb, offset+10);
    if (flags) {
        add_len = tvb_get_guint8(tvb, offset+11) & 0x7C;
        add_len = add_len >> 2;
    }

    hidden_item = proto_tree_add_uint(tree, hf_fcp_type, tvb, offset, 0, 0);
    PROTO_ITEM_SET_HIDDEN(hidden_item);

    lun0 = tvb_get_guint8(tvb, offset);

    /* Display single-level LUNs in decimal for clarity */
    /* I'm taking a shortcut here by assuming that if the first byte of the
     * LUN field is 0, it is a single-level LUN. This is not true. For a
     * real single-level LUN, all 8 bytes except byte 1 must be 0.
     */
    if (lun0) {
      proto_tree_add_item(tree, hf_fcp_multilun, tvb, offset, 8, ENC_NA);
      lun = tvb_get_guint8(tvb, offset) & 0x3f;
      lun <<= 8;
      lun |= tvb_get_guint8(tvb, offset+1);
    } else {
      proto_tree_add_item(tree, hf_fcp_singlelun, tvb, offset+1,
                          1, ENC_BIG_ENDIAN);
      lun = tvb_get_guint8(tvb, offset+1);
    }

    if (fchdr->itlq)
        fchdr->itlq->lun = lun;

    itl = (itl_nexus_t *)se_tree_lookup32(fcp_conv_data->luns, lun);
    if (!itl) {
        itl = se_alloc(sizeof(itl_nexus_t));
        itl->cmdset = 0xff;
        itl->conversation = conversation;
        se_tree_insert32(fcp_conv_data->luns, lun, itl);
    }

    proto_tree_add_item(tree, hf_fcp_crn, tvb, offset+8, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(tree, hf_fcp_taskattr, tvb, offset+9, 1, ENC_BIG_ENDIAN);
    dissect_task_mgmt_flags(pinfo, tree, tvb, offset+10);
    proto_tree_add_item(tree, hf_fcp_addlcdblen, tvb, offset+11, 1, ENC_BIG_ENDIAN);
    rwflags = tvb_get_guint8(tvb, offset+11);
    if (fchdr->itlq) {
        if (rwflags & 0x02) {
            fchdr->itlq->task_flags |= SCSI_DATA_READ;
        }
        if (rwflags & 0x01) {
            fchdr->itlq->task_flags |= SCSI_DATA_WRITE;
        }
    }
    proto_tree_add_item(tree, hf_fcp_rddata, tvb, offset+11, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(tree, hf_fcp_wrdata, tvb, offset+11, 1, ENC_BIG_ENDIAN);

    tvb_len = tvb_length_remaining(tvb, offset+12);
    if (tvb_len > (16 + add_len))
      tvb_len = 16 + add_len;
    tvb_rlen = tvb_reported_length_remaining(tvb, offset+12);
    if (tvb_rlen > (16 + add_len))
      tvb_rlen = 16 + add_len;
    cdb_tvb = tvb_new_subset(tvb, offset+12, tvb_len, tvb_rlen);
    dissect_scsi_cdb(cdb_tvb, pinfo, parent_tree, SCSI_DEV_UNKNOWN, fchdr->itlq, itl);

    proto_tree_add_item(tree, hf_fcp_dl, tvb, offset+12+16+add_len,
                        4, ENC_BIG_ENDIAN);
    if (fchdr->itlq) {
        fchdr->itlq->data_length = tvb_get_ntohl(tvb, offset+12+16+add_len);
    }

    if ( ((rwflags & 0x03) == 0x03)
    &&  tvb_length_remaining(tvb, offset+12+16+add_len+4) >= 4) {
        proto_tree_add_item(tree, hf_fcp_bidir_dl, tvb, offset+12+16+add_len+4,
                            4, ENC_BIG_ENDIAN);
        if (fchdr->itlq) {
            fchdr->itlq->bidir_data_length = tvb_get_ntohl(tvb, offset+12+16+add_len+4);
        }

    }

}
Example #7
0
static void
dissect_wsmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    /* Set up structures needed to add the protocol subtree and manage it */
    proto_item *ti, *wsmdata_item;
    proto_tree *wsmp_tree, *wsmdata_tree;
    tvbuff_t   *wsmdata_tvb;
    guint16     wsmlength, offset;
    guint32     psidLen, psid;
    guint8      elemenId, elemenLen, msb, supLen;

    /* Make entries in Protocol column and Info column on summary display */
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "WSMP");

    col_set_str(pinfo->cinfo, COL_INFO, "WAVE Short Message Protocol IEEE P1609.3");

    /* create display subtree for the protocol */
    ti = proto_tree_add_item(tree, proto_wsmp, tvb, 0, -1, ENC_NA);

    wsmp_tree = proto_item_add_subtree(ti, ett_wsmp);

    offset = 0;
    proto_tree_add_item(wsmp_tree,
                        hf_wsmp_version, tvb, offset, 1, ENC_BIG_ENDIAN);
    offset++;

    psid    = tvb_get_guint8(tvb, offset);
    psidLen = (guint32)wme_getpsidlen((guint8*)&psid);


    if (psidLen == 2)
        psid = tvb_get_ntohs(tvb, offset);
    else if (psidLen == 3)
    {
        psid = tvb_get_ntohl(tvb, offset);
        psid = psid & 0x00FFFF; /* three bytes */

    }
    else if (psidLen == 4)
        psid = tvb_get_ntohl(tvb, offset);

    proto_tree_add_item(wsmp_tree,
                        hf_wsmp_psid, tvb, offset, psidLen, ENC_BIG_ENDIAN);
    offset += psidLen;


    elemenId = tvb_get_guint8(tvb, offset);
    while ((elemenId != WSMP) && (elemenId != WSMP_S) && (elemenId != WSMP_I))
    {
        offset++;
        if (elemenId == CHANNUM)
        {
            /* channel number */
            elemenLen = tvb_get_guint8(tvb, offset);
            offset++;
            proto_tree_add_item(wsmp_tree,
                                hf_wsmp_channel, tvb, offset, elemenLen, ENC_BIG_ENDIAN);
            offset += elemenLen;
        }
        else if (elemenId == DATARATE)
        {
            /* Data rate  */
            elemenLen = tvb_get_guint8(tvb, offset);
            offset++;
            proto_tree_add_item(wsmp_tree,
                                hf_wsmp_rate, tvb, offset, elemenLen, ENC_BIG_ENDIAN);
            offset += elemenLen;
        }
        else if (elemenId == TRANSMITPW)
        {
            /* Transmit power */
            elemenLen = tvb_get_guint8(tvb, offset);
            offset++;
            proto_tree_add_item(wsmp_tree,
                                hf_wsmp_txpower, tvb, offset, elemenLen, ENC_BIG_ENDIAN);
            offset += elemenLen;
        }
        elemenId  = tvb_get_guint8(tvb, offset);
    }

    proto_tree_add_item(wsmp_tree,
                        hf_wsmp_WAVEid, tvb, offset, 1, ENC_BIG_ENDIAN);
    offset++;

    wsmlength = tvb_get_letohs( tvb, offset);
    proto_tree_add_item(wsmp_tree,
                        hf_wsmp_wsmlength, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;

    if (elemenId == WSMP_S)
    {
        msb    = 1;
        supLen = 0;
        while (msb)
        {
            msb = tvb_get_guint8(tvb, offset + supLen);
            msb = msb & 0x80;
            supLen++;
        }
        proto_tree_add_item(wsmp_tree,
                            hf_wsmp_WSMP_S_data, tvb, offset, supLen, ENC_BIG_ENDIAN);
        wsmlength -= supLen;
        offset    += supLen;
    }

    wsmdata_item = proto_tree_add_text (wsmp_tree, tvb, offset, wsmlength,
                                        "Wave Short Message");
    wsmdata_tree = proto_item_add_subtree(wsmdata_item, ett_wsmdata);

    wsmdata_tvb  = tvb_new_subset(tvb, offset, -1, wsmlength);

    /* TODO: Branch on the application context and display accordingly
     * Default: call the data dissector
     */
    if (psid == 0xbff0)
    {
        call_dissector(data_handle, wsmdata_tvb, pinfo, wsmdata_tree);
    }
}
Example #8
0
/*
 * Function for AVP dissector.
 */
static void
dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree)
{

       gint    offset;
       guint16 avp_code;
       guint16 avp_flags;
       guint32 avp_length;
       guint16 avp_type;
       guint32 vendor_id;
       guint32 avp_hdr_length;
       guint32 avp_data_length;
       guint32 padding;

       gint32  buffer_length;

       tvbuff_t   *group_tvb;
       tvbuff_t   *eap_tvb;
       tvbuff_t   *encap_tvb;
       proto_item *single_avp_item;
       proto_tree *single_avp_tree;
       proto_item *avp_eap_item;
       proto_tree *avp_eap_tree;
       proto_item *avp_encap_item;
       proto_tree *avp_encap_tree;

       offset = 0;
       buffer_length = tvb_reported_length(tvb);

       /* Go through all AVPs */
       while (buffer_length > 0) {
               avp_code        = tvb_get_ntohs(tvb, offset);
               avp_flags       = tvb_get_ntohs(tvb, offset + 2);
               avp_data_length = tvb_get_ntohs(tvb, offset + 4);

               /* Check AVP flags for vendor specific AVP */
               if (avp_flags & PANA_AVP_FLAG_V) {
                       vendor_id      = tvb_get_ntohl(tvb, 8);
                       avp_hdr_length = 12;
               } else {
                       vendor_id = 0;
                       avp_hdr_length = 8;
               }

               avp_length = avp_hdr_length + avp_data_length;

               /* Check AVP type */
               avp_type = pana_avp_get_type(avp_code, vendor_id);


               /* Check padding */
               padding = (4 - (avp_length % 4)) % 4;

               single_avp_item = proto_tree_add_text(avp_tree, tvb, offset, avp_length + padding,
                                                               "%s (%s) length: %d bytes (%d padded bytes)",
                                                               val_to_str(avp_code, avp_code_names, "Unknown (%d)"),
                                                               val_to_str(avp_type, avp_type_names, "Unknown (%d)"),
                                                               avp_length,
                                                               avp_length + padding);

               single_avp_tree = proto_item_add_subtree(single_avp_item, ett_pana_avp_info);

               /* AVP Code */
               proto_tree_add_uint_format_value(single_avp_tree, hf_pana_avp_code, tvb,
                                                offset, 2, avp_code, "%s (%u)",
                                                val_to_str(avp_code, avp_code_names, "Unknown (%d)"),
                                                avp_code);
               offset += 2;

               /* AVP Flags */
               dissect_pana_avp_flags(single_avp_tree, tvb, offset, avp_flags);
               offset += 2;

               /* AVP Length */
               proto_tree_add_item(single_avp_tree, hf_pana_avp_data_length, tvb, offset, 2, ENC_BIG_ENDIAN);
               offset += 2;

               /* Reserved */
               proto_tree_add_item(single_avp_tree, hf_pana_avp_reserved, tvb, offset, 2, ENC_NA);
               offset += 2;

               if (avp_flags & PANA_AVP_FLAG_V) {
                       /* Vendor ID */
                       proto_tree_add_item(single_avp_tree, hf_pana_avp_vendorid, tvb, offset, 4, ENC_BIG_ENDIAN);
                       offset += 4;
               }
               if (! (avp_flags & PANA_AVP_FLAG_V)) {
                       /* AVP Value */
                       switch(avp_type) {
                               case PANA_GROUPED: {
                                       proto_item *avp_group_item;
                                       proto_tree *avp_group_tree;
                                       avp_group_item = proto_tree_add_text(single_avp_tree,
                                                                            tvb, offset, avp_data_length,
                                                                            "Grouped AVP");
                                       avp_group_tree = proto_item_add_subtree(avp_group_item, ett_pana_avp);
                                       group_tvb = tvb_new_subset(tvb, offset,
                                                                  MIN(avp_data_length, tvb_reported_length(tvb)-offset),
                                                                  avp_data_length);
                                       dissect_avps(group_tvb, pinfo, avp_group_tree);
                                       break;
                               }
                               case PANA_UTF8STRING: {
                                       const guint8 *data;
                                       data = tvb_get_ptr(tvb, offset, avp_data_length);
                                       proto_tree_add_string_format(single_avp_tree, hf_pana_avp_data_string, tvb,
                                                       offset, avp_data_length, data,
                                                       "UTF8String: %*.*s",
                                                       avp_data_length, avp_data_length, data);
                                       break;
                               }
                               case PANA_OCTET_STRING: {
                                       proto_tree_add_item(single_avp_tree, hf_pana_avp_data_bytes, tvb,
                                                           offset, avp_data_length, ENC_NA);
                                       break;
                               }
                               case PANA_INTEGER32: {
                                       proto_tree_add_item(single_avp_tree, hf_pana_avp_data_int32, tvb,
                                                           offset, 4, ENC_BIG_ENDIAN);
                                       break;
                               }
                               case PANA_UNSIGNED32: {
                                       proto_tree_add_item(single_avp_tree, hf_pana_avp_data_uint32, tvb,
                                                           offset, 4, ENC_BIG_ENDIAN);
                                       break;
                               }
                               case PANA_INTEGER64: {
                                       proto_tree_add_item(single_avp_tree, hf_pana_avp_data_int64, tvb,
                                                           offset, 8, ENC_BIG_ENDIAN);
                                       break;
                               }
                               case PANA_UNSIGNED64: {
                                       proto_tree_add_item(single_avp_tree, hf_pana_avp_data_uint64, tvb,
                                                           offset, 8, ENC_BIG_ENDIAN);
                                       break;
                               }
                               case PANA_ENUMERATED: {
                                       proto_tree_add_item(single_avp_tree, hf_pana_avp_data_enumerated, tvb,
                                                           offset, 4, ENC_BIG_ENDIAN);
                                       break;
                               }
                               case PANA_RESULT_CODE: {
                                       proto_tree_add_text(single_avp_tree, tvb, offset, avp_data_length,
                                                           "Value: %d (%s)",
                                                           tvb_get_ntohl(tvb, offset),
                                                           val_to_str(tvb_get_ntohs(tvb, offset), avp_code_names, "Unknown (%d)"));
                                       break;
                               }
                               case PANA_EAP: {
                                       avp_eap_item = proto_tree_add_text(single_avp_tree,
                                                                          tvb, offset, avp_data_length,
                                                                          "AVP Value (EAP packet)");
                                       avp_eap_tree = proto_item_add_subtree(avp_eap_item, ett_pana_avp);
                                       eap_tvb = tvb_new_subset(tvb, offset, avp_data_length, avp_data_length);
                                       if (eap_handle != NULL) {
                                               call_dissector(eap_handle, eap_tvb, pinfo, avp_eap_tree);
                                       }
                                       break;
                               }
                               case PANA_ENCAPSULATED: {
                                       avp_encap_item = proto_tree_add_text(single_avp_tree,
                                                                          tvb, offset, avp_data_length,
                                                                          "AVP Value (PANA packet)");
                                       avp_encap_tree = proto_item_add_subtree(avp_encap_item, ett_pana_avp);
                                       encap_tvb = tvb_new_subset(tvb, offset, avp_data_length, avp_data_length);
                                       dissect_pana_pdu(encap_tvb, pinfo, avp_encap_tree);
                                       break;
                               }
                       }
               }
               offset += avp_data_length + padding;

               /* Update the buffer length */
               buffer_length -=  avp_length + padding;
       }

}
Example #9
0
/*
 * Function for the PANA PDU dissector.
 */
static void
dissect_pana_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

       proto_tree        *pana_tree = NULL;
       guint16            flags;
       guint16            msg_type;
       guint32            msg_length;
       guint32            avp_length;
       guint32            seq_num;
       conversation_t     *conversation;
       pana_conv_info_t   *pana_info;
       pana_transaction_t *pana_trans;
       int offset = 0;

       col_set_str(pinfo->cinfo, COL_PROTOCOL, "PANA");
       col_clear(pinfo->cinfo,   COL_INFO);

       /* Get message length, type and flags */
       msg_length = tvb_get_ntohs(tvb, 2);
       flags      = tvb_get_ntohs(tvb, 4);
       msg_type   = tvb_get_ntohs(tvb, 6);
       seq_num    = tvb_get_ntohl(tvb, 12);
       avp_length = msg_length - 16;

       col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s-%s",
                            val_to_str(msg_type, msg_type_names, "Unknown (%d)"),
                            val_to_str(flags & PANA_FLAG_R, msg_subtype_names, "Unknown (%d)"));

       /* Make the protocol tree */
       if (tree) {
               proto_item *ti;
               ti = proto_tree_add_item(tree, proto_pana, tvb, 0, -1, ENC_NA);
               pana_tree = proto_item_add_subtree(ti, ett_pana);
       }


       /*
        * We need to track some state for this protocol on a per conversation
        * basis so we can do neat things like request/response tracking
        */
       conversation = find_or_create_conversation(pinfo);

       /*
        * Do we already have a state structure for this conv
        */
       pana_info = (pana_conv_info_t *)conversation_get_proto_data(conversation, proto_pana);
       if (!pana_info) {
               /* No.  Attach that information to the conversation, and add
                * it to the list of information structures.
                */
               pana_info = wmem_new(wmem_file_scope(), pana_conv_info_t);
               pana_info->pdus=wmem_tree_new(wmem_file_scope());

               conversation_add_proto_data(conversation, proto_pana, pana_info);
       }

       if(!pinfo->fd->flags.visited){
               if(flags&PANA_FLAG_R){
                      /* This is a request */
                      pana_trans=wmem_new(wmem_file_scope(), pana_transaction_t);
                      pana_trans->req_frame=pinfo->fd->num;
                      pana_trans->rep_frame=0;
                      pana_trans->req_time=pinfo->fd->abs_ts;
                      wmem_tree_insert32(pana_info->pdus, seq_num, (void *)pana_trans);
               } else {
                      pana_trans=(pana_transaction_t *)wmem_tree_lookup32(pana_info->pdus, seq_num);
                      if(pana_trans){
                              pana_trans->rep_frame=pinfo->fd->num;
                      }
               }
       } else {
               pana_trans=(pana_transaction_t *)wmem_tree_lookup32(pana_info->pdus, seq_num);
       }

       if(!pana_trans){
               /* create a "fake" pana_trans structure */
               pana_trans=wmem_new(wmem_packet_scope(), pana_transaction_t);
               pana_trans->req_frame=0;
               pana_trans->rep_frame=0;
               pana_trans->req_time=pinfo->fd->abs_ts;
       }

       /* print state tracking in the tree */
       if(flags&PANA_FLAG_R){
               /* This is a request */
               if(pana_trans->rep_frame){
                       proto_item *it;

                       it=proto_tree_add_uint(pana_tree, hf_pana_response_in, tvb, 0, 0, pana_trans->rep_frame);
                       PROTO_ITEM_SET_GENERATED(it);
               }
       } else {
               /* This is a reply */
               if(pana_trans->req_frame){
                       proto_item *it;
                       nstime_t ns;

                       it=proto_tree_add_uint(pana_tree, hf_pana_response_to, tvb, 0, 0, pana_trans->req_frame);
                       PROTO_ITEM_SET_GENERATED(it);

                       nstime_delta(&ns, &pinfo->fd->abs_ts, &pana_trans->req_time);
                       it=proto_tree_add_time(pana_tree, hf_pana_response_time, tvb, 0, 0, &ns);
                       PROTO_ITEM_SET_GENERATED(it);
               }
       }

       /* Reserved field */
       proto_tree_add_item(pana_tree, hf_pana_reserved_type, tvb, offset, 2, ENC_NA);
       offset += 2;

       /* Length */
       proto_tree_add_item(pana_tree, hf_pana_length_type, tvb, offset, 2, ENC_BIG_ENDIAN);
       offset += 2;

       /* Flags */
       dissect_pana_flags(pana_tree, tvb, offset, flags);
       offset += 2;

       /* Message Type */
       proto_tree_add_uint_format_value(pana_tree, hf_pana_msg_type, tvb,
                                        offset, 2, msg_type, "%s-%s (%d)",
                                        val_to_str(msg_type, msg_type_names, "Unknown (%d)"),
                                        val_to_str(flags & PANA_FLAG_R, msg_subtype_names, "Unknown (%d)"),
                                        msg_type);
       offset += 2;

       /* Session ID */
       proto_tree_add_item(pana_tree, hf_pana_session_id, tvb, offset, 4, ENC_BIG_ENDIAN);
       offset += 4;

       /* Sequence Number */
       proto_tree_add_item(pana_tree, hf_pana_seqnumber, tvb, offset, 4, ENC_BIG_ENDIAN);
       offset += 4;

       /* AVPs */
       if(avp_length != 0){
               tvbuff_t   *avp_tvb;
               proto_tree *avp_tree;
               proto_item *avp_item;
               avp_tvb  = tvb_new_subset(tvb, offset, avp_length, avp_length);
               avp_item = proto_tree_add_text(pana_tree, tvb, offset, avp_length, "Attribute Value Pairs");
               avp_tree = proto_item_add_subtree(avp_item, ett_pana_avp);

               if (avp_tree != NULL) {
                       dissect_avps(avp_tvb, pinfo, avp_tree);
               }
        }

}
Example #10
0
void
decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
                 proto_tree *tree, int uh_sport, int uh_dport, int uh_ulen)
{
    tvbuff_t *next_tvb;
    int low_port, high_port;
    gint len, reported_len;

    len = tvb_length_remaining(tvb, offset);
    reported_len = tvb_reported_length_remaining(tvb, offset);
    if (uh_ulen != -1) {
        /* This is the length from the UDP header; the payload should be cut
           off at that length.  (If our caller passed a value here, they
           are assumed to have checked that it's >= 8, and hence >= offset.)

           XXX - what if it's *greater* than the reported length? */
        if (uh_ulen - offset < reported_len)
            reported_len = uh_ulen - offset;
        if (len > reported_len)
            len = reported_len;
    }

    next_tvb = tvb_new_subset(tvb, offset, len, reported_len);

    /* If the user has a "Follow UDP Stream" window loading, pass a pointer
     * to the payload tvb through the tap system. */
    if(have_tap_listener(udp_follow_tap))
        tap_queue_packet(udp_follow_tap, pinfo, next_tvb);

    /* determine if this packet is part of a conversation and call dissector */
    /* for the conversation if available */

    if (try_conversation_dissector(&pinfo->dst, &pinfo->src, PT_UDP,
                                   uh_dport, uh_sport, next_tvb, pinfo, tree)) {
        return;
    }

    if (try_heuristic_first) {
        /* do lookup with the heuristic subdissector table */
        if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, NULL))
            return;
    }

    /* Do lookups with the subdissector table.
       We try the port number with the lower value first, followed by the
       port number with the higher value.  This means that, for packets
       where a dissector is registered for *both* port numbers:

    1) we pick the same dissector for traffic going in both directions;

    2) we prefer the port number that's more likely to be the right
       one (as that prefers well-known ports to reserved ports);

       although there is, of course, no guarantee that any such strategy
       will always pick the right port number.

       XXX - we ignore port numbers of 0, as some dissectors use a port
       number of 0 to disable the port, and as RFC 768 says that the source
       port in UDP datagrams is optional and is 0 if not used. */
    if (uh_sport > uh_dport) {
        low_port = uh_dport;
        high_port = uh_sport;
    } else {
        low_port = uh_sport;
        high_port = uh_dport;
    }
    if (low_port != 0 &&
            dissector_try_uint(udp_dissector_table, low_port, next_tvb, pinfo, tree))
        return;
    if (high_port != 0 &&
            dissector_try_uint(udp_dissector_table, high_port, next_tvb, pinfo, tree))
        return;

    if (!try_heuristic_first) {
        /* do lookup with the heuristic subdissector table */
        if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, NULL))
            return;
    }

    call_dissector(data_handle,next_tvb, pinfo, tree);
}
Example #11
0
static guint
dissect_eiss_descriptors(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
	proto_item *pi;
	proto_tree *sub_tree;
	guint       tag;

	tag = tvb_get_guint8(tvb, offset);

	if (0xe0 == tag) {
		guint total_length;

		total_length = tvb_get_guint8(tvb, offset+1);
		pi = proto_tree_add_text(tree, tvb, offset, (2+total_length),
					"ETV Application Information Descriptor");
		sub_tree = proto_item_add_subtree(pi, ett_eiss_desc);
		proto_tree_add_item(sub_tree, hf_eiss_descriptor_tag,
					tvb, offset, 1, ENC_BIG_ENDIAN);
		offset++;
		proto_tree_add_item(sub_tree, hf_eiss_descriptor_length, tvb,
					offset, 1, ENC_BIG_ENDIAN);
		offset++;
		proto_tree_add_item(sub_tree, hf_eiss_aid_app_control_code, tvb,
					offset, 1, ENC_BIG_ENDIAN);
		offset++;
		proto_tree_add_item(sub_tree, hf_eiss_aid_app_version_major, tvb,
					offset, 1, ENC_BIG_ENDIAN);
		offset++;
		proto_tree_add_item(sub_tree, hf_eiss_aid_app_version_minor, tvb,
					offset, 1, ENC_BIG_ENDIAN);
		offset++;
		proto_tree_add_item(sub_tree, hf_eiss_aid_max_proto_version_major,
					tvb, offset, 1, ENC_BIG_ENDIAN);
		offset++;
		proto_tree_add_item(sub_tree, hf_eiss_aid_max_proto_version_minor,
					tvb, offset, 1, ENC_BIG_ENDIAN);
		offset++;
		proto_tree_add_item(sub_tree, hf_eiss_aid_test_flag, tvb, offset,
					1, ENC_BIG_ENDIAN);
		offset++;
		proto_tree_add_item(sub_tree, hf_eiss_aid_reserved, tvb, offset,
					3, ENC_BIG_ENDIAN);
		offset += 3;
		proto_tree_add_item(sub_tree, hf_eiss_aid_priority, tvb, offset,
					1, ENC_BIG_ENDIAN);
		offset++;
		proto_tree_add_item(sub_tree, hf_eiss_irl_type, tvb, offset, 2,
					ENC_BIG_ENDIAN);
		proto_tree_add_item(sub_tree, hf_eiss_irl_length, tvb, offset,
					2, ENC_BIG_ENDIAN);
		offset += 2;
		proto_tree_add_item(sub_tree, hf_eiss_irl_string, tvb, offset, 2,
					ENC_ASCII|ENC_NA);
		return (2+total_length);
	} else if (0xe1 == tag) {
		pi = proto_tree_add_text(tree, tvb, offset, 6,
					"ETV Media Time Descriptor");
		sub_tree = proto_item_add_subtree(pi, ett_eiss_desc);
		proto_tree_add_item(sub_tree, hf_eiss_descriptor_tag,
					tvb, offset, 1, ENC_BIG_ENDIAN);
		offset++;
		proto_tree_add_item(sub_tree, hf_eiss_descriptor_length, tvb,
					offset, 1, ENC_BIG_ENDIAN);
		offset++;
		proto_tree_add_item(sub_tree, hf_eiss_mtd_time_value, tvb,
					offset, 4, ENC_BIG_ENDIAN);
		return 6;
	} else if (0xe2 == tag) {
		guint     tmp;
		tvbuff_t *payload;

		tmp = tvb_get_ntohs(tvb, offset+1);
		pi = proto_tree_add_text(tree, tvb, offset, (3+tmp),
					"ETV Stream Event Descriptor");
		sub_tree = proto_item_add_subtree(pi, ett_eiss_desc);
		proto_tree_add_item(sub_tree, hf_eiss_descriptor_tag,
					tvb, offset, 1, ENC_BIG_ENDIAN);
		offset++;
		proto_tree_add_item(sub_tree, hf_eiss_sed_reserved, tvb,
					offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(sub_tree, hf_eiss_sed_descriptor_length, tvb,
					offset, 2, ENC_BIG_ENDIAN);
		offset += 2;
		proto_tree_add_item(sub_tree, hf_eiss_sed_time_value, tvb,
					offset, 4, ENC_BIG_ENDIAN);
		offset += 4;

		payload = tvb_new_subset(tvb, offset, tmp-4, tmp-4);
		call_dissector(data_handle, payload, pinfo, sub_tree);

		return (3+tmp);
	} else {
		proto_tree_add_expert(tree, pinfo, &ei_eiss_unknown_descriptor, tvb, offset, -1);

		/* skip the rest of the section... for now */
		return 1000;
	}
}
static int
dissect_openais_a(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data)
{
    guint    length;
    int      offset;
    int      sub_length;

    gboolean little_endian;

    proto_tree *tree;
    proto_item *item;

    gint32 a_size;
    gint32 a_id;


    length = tvb_length(tvb);
    if (length < (corosync_totempg_dissect_mar_req_header_length))
        return 0;

    /* if (check_col(pinfo->cinfo, COL_PROTOCOL))
       col_set_str(pinfo->cinfo, COL_PROTOCOL, "OPENAIS/a"); */

    /* if (check_col(pinfo->cinfo, COL_INFO))
       col_clear(pinfo->cinfo, COL_INFO); */

    if (check_col(pinfo->cinfo, COL_INFO))
        col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "(a");

    if (!parent_tree)
        goto out;


    little_endian = corosync_totempg_is_little_endian(pinfo);
    offset = 0;

    item = proto_tree_add_item(parent_tree, proto_openais_a, tvb,
                               offset, -1, little_endian);
    tree = proto_item_add_subtree(item, ett_openais_a);

    offset += 0;
    {
        struct openais_a_info info;


        info.original_private_date = pinfo->private_data;
        pinfo->private_data        = &info;
        sub_length
            = corosync_totempg_dissect_mar_req_header(tvb,
                    pinfo,
                    tree,
                    length,
                    offset,
                    hf_openais_a_header, ett_openais_a_header,
                    hf_openais_a_header_size, hf_openais_a_header_size_padding,
                    hf_openais_a_header_id, hf_openais_a_header_id_padding,
                    little_endian,
                    &a_size, &a_id,
                    dissect_openais_a_id, pinfo->private_data);
        if (sub_length != corosync_totempg_dissect_mar_req_header_length)
            goto restore_pdata;
        info.size = a_size;


        offset += sub_length;
        {
            tvbuff_t *sub_tvb;
            sub_tvb = tvb_new_subset(tvb, offset,
                                     length - offset,
                                     length - offset);
            dissector_try_uint(subdissector_table, a_id >> 16, sub_tvb, pinfo, tree);
        }

restore_pdata:
        pinfo->private_data = info.original_private_date;

    }
out:
    if (check_col(pinfo->cinfo, COL_INFO))
        col_append_str(pinfo->cinfo, COL_INFO, ")");
    return tvb_length(tvb);
}
Example #13
0
static void dissect_tftp_message(tftp_conv_info_t *tftp_info,
                                 tvbuff_t *tvb, packet_info *pinfo,
                                 proto_tree *tree)
{
    proto_tree	 *tftp_tree = NULL;
    proto_item	 *ti;
    gint		 offset = 0;
    guint16		 opcode;
    guint16		 bytes;
    guint16		 blocknum;
    guint		 i1;
    guint16	         error;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "TFTP");

    opcode = tvb_get_ntohs(tvb, offset);

    col_add_str(pinfo->cinfo, COL_INFO,
                val_to_str(opcode, tftp_opcode_vals, "Unknown (0x%04x)"));

    if (tree) {
        ti = proto_tree_add_item(tree, proto_tftp, tvb, offset, -1, ENC_NA);
        tftp_tree = proto_item_add_subtree(ti, ett_tftp);

        if (tftp_info->source_file) {
            ti = proto_tree_add_string(tftp_tree, hf_tftp_source_file, tvb,
                                       0, 0, tftp_info->source_file);
            PROTO_ITEM_SET_GENERATED(ti);
        }

        if (tftp_info->destination_file) {
            ti = proto_tree_add_string(tftp_tree, hf_tftp_destination_file, tvb,
                                       0, 0, tftp_info->destination_file);
            PROTO_ITEM_SET_GENERATED(ti);
        }

        proto_tree_add_uint(tftp_tree, hf_tftp_opcode, tvb,
                            offset, 2, opcode);
    }
    offset += 2;

    switch (opcode) {

    case TFTP_RRQ:
        i1 = tvb_strsize(tvb, offset);
        proto_tree_add_item(tftp_tree, hf_tftp_source_file,
                            tvb, offset, i1, ENC_ASCII|ENC_NA);

        tftp_info->source_file = tvb_get_seasonal_string(tvb, offset, i1);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s",
                        tvb_format_stringzpad(tvb, offset, i1));

        offset += i1;

        i1 = tvb_strsize(tvb, offset);
        proto_tree_add_item(tftp_tree, hf_tftp_transfer_type,
                            tvb, offset, i1, ENC_ASCII|ENC_NA);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Transfer type: %s",
                        tvb_format_stringzpad(tvb, offset, i1));

        offset += i1;

        tftp_dissect_options(tvb, pinfo,  offset, tftp_tree,
                             opcode, tftp_info);
        break;

    case TFTP_WRQ:
        i1 = tvb_strsize(tvb, offset);
        proto_tree_add_item(tftp_tree, hf_tftp_destination_file,
                            tvb, offset, i1, ENC_ASCII|ENC_NA);

        tftp_info->destination_file =
            tvb_get_seasonal_string(tvb, offset, i1);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s",
                        tvb_format_stringzpad(tvb, offset, i1));

        offset += i1;

        i1 = tvb_strsize(tvb, offset);
        proto_tree_add_item(tftp_tree, hf_tftp_transfer_type,
                            tvb, offset, i1, ENC_ASCII|ENC_NA);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Transfer type: %s",
                        tvb_format_stringzpad(tvb, offset, i1));

        offset += i1;

        tftp_dissect_options(tvb, pinfo, offset, tftp_tree,
                             opcode,  tftp_info);
        break;

    case TFTP_INFO:
        tftp_dissect_options(tvb, pinfo, offset, tftp_tree,
                             opcode,  tftp_info);
        break;

    case TFTP_DATA:
        blocknum = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint(tftp_tree, hf_tftp_blocknum, tvb, offset, 2,
                            blocknum);

        offset += 2;

        bytes = tvb_reported_length_remaining(tvb, offset);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %i%s",
                        blocknum,
                        (bytes < tftp_info->blocksize)?" (last)":"" );

        if (bytes != 0) {
            tvbuff_t *data_tvb = tvb_new_subset(tvb, offset, -1, bytes);
            call_dissector(data_handle, data_tvb, pinfo, tree);
        }
        break;

    case TFTP_ACK:
        blocknum = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint(tftp_tree, hf_tftp_blocknum, tvb, offset, 2,
                            blocknum);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %i",
                        blocknum);
        break;

    case TFTP_ERROR:
        error = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint(tftp_tree, hf_tftp_error_code, tvb, offset, 2,
                            error);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Code: %s",
                        val_to_str(error, tftp_error_code_vals, "Unknown (%u)"));

        offset += 2;

        i1 = tvb_strsize(tvb, offset);
        proto_tree_add_item(tftp_tree, hf_tftp_error_string, tvb, offset,
                            i1, ENC_ASCII|ENC_NA);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Message: %s",
                        tvb_format_stringzpad(tvb, offset, i1));

        expert_add_info(pinfo, NULL, &ei_tftp_blocksize_range);
        break;

    case TFTP_OACK:
        tftp_dissect_options(tvb, pinfo, offset, tftp_tree,
                             opcode, tftp_info);
        break;

    default:
        proto_tree_add_text(tftp_tree, tvb, offset, -1,
                            "Data (%d bytes)", tvb_reported_length_remaining(tvb, offset));
        break;

    }

    return;
}
Example #14
0
/* Code to actually dissect the packets */
static void
dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    char *szInfo;
    int			offCur		= 0;   /* current offset from start of WTP data */
    gint		returned_length, str_index = 0;

    unsigned char	b0;

    /* continuation flag */
    unsigned char  	fCon;			/* Continue flag	*/
    unsigned char  	fRID;			/* Re-transmission indicator*/
    unsigned char  	fTTR = '\0';		/* Transmission trailer	*/
    guint 		cbHeader   	= 0;	/* Fixed header length	*/
    guint 		vHeader   	= 0;	/* Variable header length*/
    int 		abortType  	= 0;

    /* Set up structures we'll need to add the protocol subtree and manage it */
    proto_item		*ti = NULL;
    proto_tree		*wtp_tree = NULL;

    char		pdut;
    char		clsTransaction = 3;
    int			numMissing = 0;		/* Number of missing packets in a negative ack */
    int			i;
    tvbuff_t		*wsp_tvb = NULL;
    guint8		psn = 0;		/* Packet sequence number*/
    guint16		TID = 0;		/* Transaction-Id	*/
    int			dataOffset;
    gint		dataLen;

#define SZINFO_SIZE 256
    szInfo=ep_alloc(SZINFO_SIZE);

    b0 = tvb_get_guint8 (tvb, offCur + 0);
    /* Discover Concatenated PDUs */
    if (b0 == 0) {
	guint	c_fieldlen = 0;		/* Length of length-field	*/
	guint	c_pdulen = 0;		/* Length of conc. PDU	*/

	if (tree) {
	    ti = proto_tree_add_item(tree, proto_wtp,
				    tvb, offCur, 1, ENC_NA);
	    wtp_tree = proto_item_add_subtree(ti, ett_wtp_sub_pdu_tree);
		proto_item_append_text(ti, ", PDU concatenation");
	}
	offCur = 1;
	i = 1;
	while (offCur < (int) tvb_reported_length(tvb)) {
	    tvbuff_t *wtp_tvb;
	    /* The length of an embedded WTP PDU is coded as either:
	     *	- a 7-bit value contained in one octet with highest bit == 0.
	     *	- a 15-bit value contained in two octets (little endian)
	     *	  if the 1st octet has its highest bit == 1.
	     * This means that this is NOT encoded as an uintvar-integer!!!
	     */
	    b0 = tvb_get_guint8(tvb, offCur + 0);
	    if (b0 & 0x80) {
		c_fieldlen = 2;
		c_pdulen = ((b0 & 0x7f) << 8) | tvb_get_guint8(tvb, offCur + 1);
	    } else {
		c_fieldlen = 1;
		c_pdulen = b0;
	    }
	    if (tree) {
		proto_tree_add_uint(wtp_tree, hf_wtp_header_sub_pdu_size,
				    tvb, offCur, c_fieldlen, c_pdulen);
	    }
	    if (i > 1) {
		col_append_str(pinfo->cinfo, COL_INFO, ", ");
	    }
	    /* Skip the length field for the WTP sub-tvb */
	    wtp_tvb = tvb_new_subset(tvb, offCur + c_fieldlen, c_pdulen, c_pdulen);
	    dissect_wtp_common(wtp_tvb, pinfo, wtp_tree);
	    offCur += c_fieldlen + c_pdulen;
	    i++;
	}
	if (tree) {
		proto_item_append_text(ti, ", PDU count: %u", i);
	}
	return;
    }
    /* No concatenation */
    fCon = b0 & 0x80;
    fRID = retransmission_indicator(b0);
    pdut = pdu_type(b0);

#ifdef DEBUG
	printf("WTP packet %u: tree = %p, pdu = %s (%u) length: %u\n",
			pinfo->fd->num, tree,
			val_to_str(pdut, vals_wtp_pdu_type, "Unknown PDU type 0x%x"),
			pdut, tvb_length(tvb));
#endif

    /* Develop the string to put in the Info column */
    returned_length =  g_snprintf(szInfo, SZINFO_SIZE, "WTP %s",
		    val_to_str(pdut, vals_wtp_pdu_type, "Unknown PDU type 0x%x"));
    str_index += MIN(returned_length, SZINFO_SIZE-str_index);

    switch (pdut) {
	case INVOKE:
	    fTTR = transmission_trailer(b0);
	    TID = tvb_get_ntohs(tvb, offCur + 1);
	    psn = 0;
	    clsTransaction = transaction_class(tvb_get_guint8(tvb, offCur + 3));
	    returned_length = g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index,
		" Class %d", clsTransaction);
            str_index += MIN(returned_length, SZINFO_SIZE-str_index);
	    cbHeader = 4;
	    break;

	case SEGMENTED_INVOKE:
	case SEGMENTED_RESULT:
	    fTTR = transmission_trailer(b0);
	    TID = tvb_get_ntohs(tvb, offCur + 1);
	    psn = tvb_get_guint8(tvb, offCur + 3);
	    if (psn != 0) {
		returned_length = g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index,
			" (%u)", psn);
                str_index += MIN(returned_length, SZINFO_SIZE-str_index);
	    }
	    cbHeader = 4;
	    break;

	case ABORT:
	    cbHeader = 4;
	    break;

	case RESULT:
	    fTTR = transmission_trailer(b0);
	    TID = tvb_get_ntohs(tvb, offCur + 1);
	    psn = 0;
	    cbHeader = 3;
	    break;

	case ACK:
	    cbHeader = 3;
	    break;

	case NEGATIVE_ACK:
	    /* Variable number of missing packets */
	    numMissing = tvb_get_guint8(tvb, offCur + 3);
	    cbHeader = numMissing + 4;
	    break;

	default:
	    break;
    };
    if (fRID) {
	returned_length = g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index, " R" );
        str_index += MIN(returned_length, SZINFO_SIZE-str_index);
    };
    /* In the interest of speed, if "tree" is NULL, don't do any work not
       necessary to generate protocol tree items. */
    if (tree) {
#ifdef DEBUG
	fprintf(stderr, "dissect_wtp: cbHeader = %d\n", cbHeader);
#endif
	/* NOTE - Length will be set when we process the TPI */
	ti = proto_tree_add_item(tree, proto_wtp, tvb, offCur, 0, ENC_NA);
#ifdef DEBUG
	fprintf(stderr, "dissect_wtp: (7) Returned from proto_tree_add_item\n");
#endif
	wtp_tree = proto_item_add_subtree(ti, ett_wtp);

/* Code to process the packet goes here */
#ifdef DEBUG
	fprintf(stderr, "dissect_wtp: cbHeader = %d\n", cbHeader);
	fprintf(stderr, "dissect_wtp: offCur = %d\n", offCur);
#endif
	/* Add common items: only CON and PDU Type */
	proto_tree_add_item(
			wtp_tree,	 		/* tree */
			hf_wtp_header_flag_continue, 	/* id */
			tvb,
			offCur, 			/* start of highlight */
			1,				/* length of highlight*/
			b0				/* value */
	     );
	proto_tree_add_item(wtp_tree, hf_wtp_header_pdu_type, tvb, offCur, 1, ENC_LITTLE_ENDIAN);

	switch(pdut) {
	    case INVOKE:
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

		proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_version , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_flag_TIDNew, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_flag_UP, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_Reserved, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_TransactionClass, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
		proto_item_append_text(ti,
				", PDU: Invoke (%u)"
				", Transaction Class: %s (%u)",
				INVOKE,
				val_to_str(clsTransaction, vals_transaction_classes, "Undefined"),
				clsTransaction);
		break;

	    case RESULT:
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_item_append_text(ti, ", PDU: Result (%u)", RESULT);
		break;

	    case ACK:
		proto_tree_add_item(wtp_tree, hf_wtp_header_Ack_flag_TVETOK, tvb, offCur, 1, ENC_BIG_ENDIAN);

		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_item_append_text(ti, ", PDU: ACK (%u)", ACK);
		break;

	    case ABORT:
		abortType = tvb_get_guint8 (tvb, offCur) & 0x07;
		proto_tree_add_item(wtp_tree, hf_wtp_header_Abort_type , tvb, offCur , 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

		if (abortType == PROVIDER)
		{
			guint8 reason = tvb_get_guint8(tvb, offCur + 3);
		    proto_tree_add_item( wtp_tree, hf_wtp_header_Abort_reason_provider , tvb, offCur + 3 , 1, ENC_LITTLE_ENDIAN);
			proto_item_append_text(ti,
					", PDU: Abort (%u)"
					", Type: Provider (%u)"
					", Reason: %s (%u)",
					ABORT,
					PROVIDER,
					val_to_str(reason, vals_abort_reason_provider, "Undefined"),
					reason);
		}
		else if (abortType == USER)
		{
			guint8 reason = tvb_get_guint8(tvb, offCur + 3);
		    proto_tree_add_item(wtp_tree, hf_wtp_header_Abort_reason_user , tvb, offCur + 3 , 1, ENC_LITTLE_ENDIAN);
			proto_item_append_text(ti,
					", PDU: Abort (%u)"
					", Type: User (%u)"
					", Reason: %s (%u)",
					ABORT,
					PROVIDER,
					val_to_str_ext_const(reason, &vals_wsp_reason_codes_ext, "Undefined"),
					reason);
		}
		break;

	    case SEGMENTED_INVOKE:
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

		proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
		proto_item_append_text(ti,
				", PDU: Segmented Invoke (%u)"
				", Packet Sequence Number: %u",
				SEGMENTED_INVOKE, psn);
		break;

	    case SEGMENTED_RESULT:
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

		proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
		proto_item_append_text(ti,
				", PDU: Segmented Result (%u)"
				", Packet Sequence Number: %u",
				SEGMENTED_RESULT, psn);
		break;

	    case NEGATIVE_ACK:
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

		proto_tree_add_item(wtp_tree, hf_wtp_header_missing_packets , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
		/* Iterate through missing packets */
		for (i = 0; i < numMissing; i++)
		{
		    proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number, tvb, offCur + 4 + i, 1, ENC_LITTLE_ENDIAN);
		}
		proto_item_append_text(ti,
				", PDU: Negative Ack (%u)"
				", Missing Packets: %u",
				NEGATIVE_ACK, numMissing);
		break;

	    default:
		break;
	};
	if (fRID) {
		proto_item_append_text(ti, ", Retransmission");
	}
    } else { /* tree is NULL */
#ifdef DEBUG
	fprintf(stderr, "dissect_wtp: (4) tree was %p\n", tree);
#endif
    }
	/* Process the variable part */
	if (fCon) {			/* Now, analyze variable part	*/
	    unsigned char	 tCon;
	    unsigned char	 tByte;
	    unsigned char	 tpiLen;
	    tvbuff_t		*tmp_tvb;

	    vHeader = 0;		/* Start scan all over	*/

	    do {
		tByte = tvb_get_guint8(tvb, offCur + cbHeader + vHeader);
		tCon = tByte & 0x80;
		if (tByte & 0x04)	/* Long TPI	*/
		    tpiLen = 2 + tvb_get_guint8(tvb,
					    offCur + cbHeader + vHeader + 1);
		else
		    tpiLen = 1 + (tByte & 0x03);
		if (tree)
		{
		tmp_tvb = tvb_new_subset(tvb, offCur + cbHeader + vHeader,
					tpiLen, tpiLen);
		wtp_handle_tpi(wtp_tree, tmp_tvb);
		}
		vHeader += tpiLen;
	    } while (tCon);
	} else {
		/* There is no variable part */
	}	/* End of variable part of header */

	/* Set the length of the WTP protocol part now we know the length of the
	 * fixed and variable WTP headers */
	if (tree)
	proto_item_set_len(ti, cbHeader + vHeader);

#ifdef DEBUG
    fprintf( stderr, "dissect_wtp: cbHeader = %d\n", cbHeader );
#endif

    /*
     * Any remaining data ought to be WSP data (if not WTP ACK, NACK
     * or ABORT pdu), so, if we have any remaining data, and it's
     * not an ACK, NACK, or ABORT PDU, hand it off (defragmented) to the
     * WSP dissector.
     * Note that the last packet of a fragmented WTP message needn't
     * contain any data, so we allow payloadless packets to be
     * reassembled.  (XXX - does the reassembly code handle this
     * for packets other than the last packet?)
     *
	 * Try calling a subdissector only if:
	 *	- The WTP payload is ressembled in this very packet,
	 *	- The WTP payload is not fragmented across packets.
	 */
    dataOffset = offCur + cbHeader + vHeader;
    dataLen = tvb_reported_length_remaining(tvb, dataOffset);
    if ((dataLen >= 0) &&
			! ((pdut==ACK) || (pdut==NEGATIVE_ACK) || (pdut==ABORT)))
    {
		/* Try to reassemble if needed, and hand over to WSP
		 * A fragmented WTP packet is either:
		 *	- An INVOKE with fTTR (transmission trailer) not set,
		 *	- a SEGMENTED_INVOKE,
		 *	- A RESULT with fTTR (transmission trailer) not set,
		 *	- a SEGMENTED_RESULT.
		 */
		if ( ( (pdut == SEGMENTED_INVOKE) || (pdut == SEGMENTED_RESULT)
				|| ( ((pdut == INVOKE) || (pdut == RESULT)) && (!fTTR) )
			) && tvb_bytes_exist(tvb, dataOffset, dataLen) )
		{
			/* Try reassembling fragments */
			fragment_data *fd_wtp = NULL;
			guint32 reassembled_in = 0;
			gboolean save_fragmented = pinfo->fragmented;

			pinfo->fragmented = TRUE;
			fd_wtp = fragment_add_seq(tvb, dataOffset, pinfo, TID,
					wtp_fragment_table, psn, dataLen, !fTTR);
			/* XXX - fragment_add_seq() yields NULL unless Wireshark knows
			 * that the packet is part of a reassembled whole. This means
			 * that fd_wtp will be NULL as long as Wireshark did not encounter
			 * (and process) the packet containing the last fragment.
			 * This implies that Wireshark needs two passes over the data for
			 * correct reassembly. At the first pass, a capture containing
			 * three fragments plus a retransmssion of the last fragment
			 * will progressively show:
			 *
			 *		Packet 1: (Unreassembled fragment 1)
			 *		Packet 2: (Unreassembled fragment 2)
			 *		Packet 3: (Reassembled WTP)
			 *		Packet 4: (WTP payload reassembled in packet 3)
			 *
			 * However at subsequent evaluation (e.g., by applying a display
			 * filter) the packet summary will show:
			 *
			 *		Packet 1: (WTP payload reassembled in packet 3)
			 *		Packet 2: (WTP payload reassembled in packet 3)
			 *		Packet 3: (Reassembled WTP)
			 *		Packet 4: (WTP payload reassembled in packet 3)
			 *
			 * This is important to know, and also affects read filters!
			 */
			wsp_tvb = process_reassembled_data(tvb, dataOffset, pinfo,
					"Reassembled WTP", fd_wtp, &wtp_frag_items,
					NULL, wtp_tree);
#ifdef DEBUG
			printf("WTP: Packet %u %s -> %d: wsp_tvb = %p, fd_wtp = %p, frame = %u\n",
					pinfo->fd->num,
					fd_wtp ? "Reassembled" : "Not reassembled",
					fd_wtp ? fd_wtp->reassembled_in : -1,
					wsp_tvb,
					fd_wtp
					);
#endif
			if (fd_wtp) {
				/* Reassembled */
				reassembled_in = fd_wtp->reassembled_in;
				if (pinfo->fd->num == reassembled_in) {
					/* Reassembled in this very packet:
					 * We can safely hand the tvb to the WSP dissector */
					call_dissector(wsp_handle, wsp_tvb, pinfo, tree);
				} else {
					/* Not reassembled in this packet */
					if (check_col(pinfo->cinfo, COL_INFO)) {
						col_append_fstr(pinfo->cinfo, COL_INFO,
								"%s (WTP payload reassembled in packet %u)",
								szInfo, fd_wtp->reassembled_in);
					}
					if (tree) {
						proto_tree_add_text(wtp_tree, tvb, dataOffset, -1,
								"Payload");
					}
				}
			} else {
				/* Not reassembled yet, or not reassembled at all */
				if (check_col(pinfo->cinfo, COL_INFO)) {
					col_append_fstr(pinfo->cinfo, COL_INFO,
								"%s (Unreassembled fragment %u)",
								szInfo, psn);
				}
				if (tree) {
					proto_tree_add_text(wtp_tree, tvb, dataOffset, -1,
							"Payload");
				}
			}
			/* Now reset fragmentation information in pinfo */
			pinfo->fragmented = save_fragmented;
		}
		else if ( ((pdut == INVOKE) || (pdut == RESULT)) && (fTTR) )
		{
			/* Non-fragmented payload */
			wsp_tvb = tvb_new_subset_remaining(tvb, dataOffset);
			/* We can safely hand the tvb to the WSP dissector */
			call_dissector(wsp_handle, wsp_tvb, pinfo, tree);
		}
		else
		{
			/* Nothing to hand to subdissector */
			if (check_col(pinfo->cinfo, COL_INFO))
				col_append_str(pinfo->cinfo, COL_INFO, szInfo);
		}
	}
	else
	{
		/* Nothing to hand to subdissector */
		if (check_col(pinfo->cinfo, COL_INFO))
			col_append_str(pinfo->cinfo, COL_INFO, szInfo);
	}
}
    offset += 2;
    proto_tree_add_item(tree, hf_dsmcc_reserved2, tvb,
        offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(tree, hf_dsmcc_version_number, tvb,
        offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(tree, hf_dsmcc_current_next_indicator, tvb,
        offset, 1, ENC_BIG_ENDIAN);
    offset +=1;
    proto_tree_add_item(tree, hf_dsmcc_section_number, tvb,
        offset, 1, ENC_BIG_ENDIAN);
    offset +=1;
    proto_tree_add_item(tree, hf_dsmcc_last_section_number, tvb,
        offset, 1, ENC_BIG_ENDIAN);
    offset +=1;

    sub_tvb = tvb_new_subset(tvb, offset, sect_len-9, sect_len-9);
    switch (tid) {
        case DSMCC_TID_LLCSNAP:
            /* TODO: Add support */
            break;
        case DSMCC_TID_UN_MSG:
        case DSMCC_TID_DD_MSG:
            dissect_dsmcc_un(sub_tvb, pinfo, tree, tree_in);
            break;
        case DSMCC_TID_DESC_LIST:
            /* TODO: Add support */
            break;
        case DSMCC_TID_PRIVATE:
            /* TODO: Add support */
            break;
        default:
static void
dissect_cwids(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	tvbuff_t *wlan_tvb;
	proto_tree *ti, *cwids_tree;
	volatile int offset = 0;
	guint16 capturelen;
	void *pd_save;

	col_set_str(pinfo->cinfo, COL_PROTOCOL, "CWIDS");
	col_set_str(pinfo->cinfo, COL_INFO, "Cwids: ");
	/* FIXME: col_set_fence(pinfo->cinfo, all-cols, only addr-cols?); */

	cwids_tree = NULL;

	while(tvb_length_remaining(tvb, offset) > 0) {
		ti = proto_tree_add_item(tree, proto_cwids, tvb, offset, 28, ENC_NA);
		cwids_tree = proto_item_add_subtree(ti, ett_cwids);

		proto_tree_add_item(cwids_tree, hf_cwids_version, tvb, offset, 2, ENC_BIG_ENDIAN);
		offset += 2;
		proto_tree_add_item(cwids_tree, hf_cwids_unknown1, tvb, offset, 7, ENC_NA);
		offset += 7;
		proto_tree_add_item(cwids_tree, hf_cwids_channel, tvb, offset, 1, ENC_BIG_ENDIAN);
		offset += 1;
		proto_tree_add_item(cwids_tree, hf_cwids_unknown2, tvb, offset, 6, ENC_NA);
		offset += 6;
		proto_tree_add_item(cwids_tree, hf_cwids_reallength, tvb, offset, 2, ENC_BIG_ENDIAN);
		offset += 2;
		capturelen = tvb_get_ntohs(tvb, offset);
		proto_tree_add_item(cwids_tree, hf_cwids_capturelen, tvb, offset, 2, ENC_BIG_ENDIAN);
		offset += 2;
		proto_tree_add_item(cwids_tree, hf_cwids_unknown3, tvb, offset, 8, ENC_NA);
		offset += 8;

		wlan_tvb = tvb_new_subset(tvb, offset, capturelen, capturelen);
		/* Continue after ieee80211 dissection errors */
		pd_save = pinfo->private_data;
		TRY {
			call_dissector(ieee80211_handle, wlan_tvb, pinfo, tree);
		} CATCH_BOUNDS_ERRORS {
			show_exception(wlan_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);

			/*  Restore the private_data structure in case one of the
			 *  called dissectors modified it (and, due to the exception,
			 *  was unable to restore it).
			 */
			pinfo->private_data = pd_save;

#if 0
	wlan_tvb = tvb_new_subset(tvb, offset, capturelen, capturelen);
			/* FIXME: Why does this throw an exception? */
			proto_tree_add_text(cwids_tree, wlan_tvb, offset, capturelen,
				"[Malformed or short IEEE80211 subpacket]");
#else
			tvb_new_subset(tvb, offset, capturelen, capturelen);
#endif
	;
		} ENDTRY;

		offset += capturelen;
	}
}
static guint
dissect_dsmcc_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
            gboolean download_header)
{
    tvbuff_t   *sub_tvb;
    proto_item *pi;
    proto_tree *sub_tree;
    guint8		prot_disc;
    guint		reserved;
    guint8		adaptation_len;
    guint		len = 0;
    int			msg_id, tx_id;

    prot_disc = tvb_get_guint8(tvb, offset);
    reserved = tvb_get_guint8(tvb, 8+offset);
    adaptation_len = tvb_get_guint8(tvb, 9+offset);

    pi = proto_tree_add_text(tree, tvb, offset, 12+adaptation_len, "DSM-CC Header");
    sub_tree = proto_item_add_subtree(pi, ett_dsmcc_header);
    pi = proto_tree_add_item(sub_tree, hf_dsmcc_protocol_discriminator, tvb,
                 offset, 1, ENC_BIG_ENDIAN);
    if (0x11 != prot_disc) {
        expert_add_info_format_text(pinfo, pi, &ei_dsmcc_invalid_value,
                    "Invalid value - should be 0x11");
    }
    offset +=1;
    proto_tree_add_item(sub_tree, hf_dsmcc_type, tvb,
        offset, 1, ENC_BIG_ENDIAN);
    offset +=1;
    if (TRUE == download_header) {
        msg_id = hf_dsmcc_dd_message_id;
        tx_id = hf_dsmcc_dd_download_id;
    } else {
        msg_id = hf_dsmcc_message_id;
        tx_id = hf_dsmcc_transaction_id;
    }
    proto_tree_add_item(sub_tree, msg_id, tvb,
        offset, 2, ENC_BIG_ENDIAN);
    offset += 2;
    proto_tree_add_item(sub_tree, tx_id, tvb,
        offset, 4, ENC_BIG_ENDIAN);
    offset += 4;
    pi = proto_tree_add_item(sub_tree, hf_dsmcc_header_reserved, tvb,
        offset, 1, ENC_BIG_ENDIAN);
    if (0xff != reserved) {
        expert_add_info_format_text(pinfo, pi, &ei_dsmcc_invalid_value,
                    "Invalid value - should be 0xff");
    }
    offset +=1;

    proto_tree_add_item(sub_tree, hf_dsmcc_adaptation_length, tvb,
        offset, 1, ENC_BIG_ENDIAN);
    offset +=1;
    proto_tree_add_item(sub_tree, hf_dsmcc_message_length, tvb,
        offset, 2, ENC_BIG_ENDIAN);
    offset += 2;

    len = 12;
    if (0 < adaptation_len) {
        sub_tvb = tvb_new_subset(tvb, offset, adaptation_len, adaptation_len);
        dissect_dsmcc_adaptation_header(sub_tvb, pinfo, sub_tree);
        offset += adaptation_len;
    }

    return len;
}
Example #18
0
static void
dissect_payload_kink_isakmp(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
  proto_tree *payload_kink_isakmp_tree;
  proto_item *ti;
  guint8 next_payload;
  guint payload_length,isakmp_length;
  int length, reported_length;
  guint8 inner_next_pload;
  guint8 qm, qmmaj, qmmin;
  int start_payload_offset = 0;      /* Keep the beginning of the payload offset */
  tvbuff_t *isakmp_tvb;

  payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
  start_payload_offset = offset;

  /* Make the subtree. */
  ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_ISAKMP");
  payload_kink_isakmp_tree = proto_item_add_subtree(ti, ett_payload_kink_isakmp);

  next_payload = tvb_get_guint8(tvb, offset);
  proto_tree_add_uint(payload_kink_isakmp_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
  offset ++;

  proto_tree_add_item(payload_kink_isakmp_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
  offset ++;

  ti = proto_tree_add_uint(payload_kink_isakmp_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
  if(payload_length <= PAYLOAD_HEADER){
    expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "This Payload Length is too small");
  }
  offset += 2;

  inner_next_pload = tvb_get_guint8(tvb, offset);
  proto_tree_add_uint(payload_kink_isakmp_tree, hf_kink_inner_next_pload, tvb, offset, 1, inner_next_pload);
  offset += 1;

  /* The qmmaj is first half 4bit field of the octet. Therefore, the logical product
   * of the 1octet value and 0xf0 is performed, and performed 4bit right shift.
   * The qmmin is second half 4bit field of the octet. Therefore, the logical product
   * of the 1octet value and 0x0f is performed.
   */
  qm = tvb_get_guint8(tvb,offset);
  qmmaj = (qm & FRONT_FOUR_BIT) >> VERSION_BIT_SHIFT;
  qmmin = qm & SECOND_FOUR_BIT;

  proto_tree_add_text(payload_kink_isakmp_tree, tvb, offset, 1, "QMVersion: %u.%u", qmmaj, qmmin);
  offset += 1;

  proto_tree_add_item(payload_kink_isakmp_tree, hf_kink_reserved16, tvb, offset, 2, ENC_BIG_ENDIAN);
  offset += 2;

  if(payload_length > PAYLOAD_HEADER){
    isakmp_length = payload_length - PAYLOAD_HEADER;
    length = tvb_length_remaining(tvb, offset);
    if (length > (int)isakmp_length)
      length = isakmp_length;
    reported_length = tvb_reported_length_remaining(tvb, offset);
    if (reported_length > (int)isakmp_length)
      reported_length = isakmp_length;
    isakmp_tvb = tvb_new_subset(tvb, offset, length, reported_length);
    isakmp_dissect_payloads(isakmp_tvb, payload_kink_isakmp_tree, 1, inner_next_pload, 0, isakmp_length, pinfo);
  }

  /* This part consider the padding. Payload_length don't contain the padding. */
  if(payload_length % PADDING != 0){
    payload_length += (PADDING - (payload_length % PADDING));
  }
  offset = start_payload_offset + payload_length;

  if(payload_length > 0) {
    control_payload(pinfo, tvb, offset, next_payload, tree);  /* Recur control_payload() */
  }
}
Example #19
0
static int
dissect_bvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

	proto_item *ti;
	proto_item *ti_bdt;
	proto_item *ti_fdt;
	proto_tree *bvlc_tree;
	proto_tree *bdt_tree; /* Broadcast Distribution Table */
	proto_tree *fdt_tree; /* Foreign Device Table */

	gint offset;
	guint8 bvlc_type;
	guint8 bvlc_function;
	guint16 bvlc_length;
	guint16 packet_length;
	guint npdu_length;
	guint length_remaining;
	guint16 bvlc_result;
	tvbuff_t *next_tvb;

	offset = 0;

	bvlc_type =  tvb_get_guint8(tvb, offset);

	/*
	 * Simple sanity check - make sure the type is one we know about.
	 */
	if (match_strval(bvlc_type, bvlc_types) == NULL)
		return 0;

	col_set_str(pinfo->cinfo, COL_PROTOCOL, "BVLC");

	col_set_str(pinfo->cinfo, COL_INFO, "BACnet Virtual Link Control");

	bvlc_function = tvb_get_guint8(tvb, offset+1);
	packet_length = tvb_get_ntohs(tvb, offset+2);
	length_remaining = tvb_length_remaining(tvb, offset);
	if (bvlc_function > 0x08) {
		/*  We have a constant header length of BVLC of 4 in every
		 *  BVLC-packet forewarding an NPDU. Beware: Changes in the
		 *  BACnet-IP-standard may break this.
		 *  At the moment, no functions above 0x0b
		 *  exist (Addendum 135a to ANSI/ASHRAE 135-1995 - BACnet)
		 */
		bvlc_length = 4;
	} else if(bvlc_function == 0x04) {
		/* 4 Bytes + 6 Bytes for B/IP Address of Originating Device */
		bvlc_length = 10;
	} else {
		/*  BVLC-packets with function below 0x09 contain
		 *  routing-level data (e.g. Broadcast Distribution)
		 *  but no NPDU for BACnet, so bvlc_length goes up to the end
		 *  of the captured frame.
		 */
		bvlc_length = packet_length;
	}

	if (tree) {
		if (bvlc_length < 4) {
			proto_tree_add_text(tree, tvb, 2, 2,
				"Bogus length: %d", bvlc_length);
			return tvb_length(tvb);	/* XXX - reject? */
		}
		ti = proto_tree_add_item(tree, proto_bvlc, tvb, 0,
			bvlc_length, FALSE);
		bvlc_tree = proto_item_add_subtree(ti, ett_bvlc);
		proto_tree_add_uint(bvlc_tree, hf_bvlc_type, tvb, offset, 1,
			bvlc_type);
		offset ++;
		proto_tree_add_uint(bvlc_tree, hf_bvlc_function, tvb,
			offset, 1, bvlc_function);
		offset ++;
		if (length_remaining != packet_length)
			proto_tree_add_uint_format_value(bvlc_tree, hf_bvlc_length, tvb, offset,
				2, bvlc_length, 
				"%d of %d bytes (invalid length - expected %d bytes)",
				bvlc_length, packet_length, length_remaining);
		else		
			proto_tree_add_uint_format_value(bvlc_tree, hf_bvlc_length, tvb, offset,
				2, bvlc_length, "%d of %d bytes BACnet packet length",
				bvlc_length, packet_length);
		offset += 2;
		switch (bvlc_function) {
		case 0x00: /* BVLC-Result */
			bvlc_result = tvb_get_ntohs(tvb, offset);
			/* I dont know why the result code is encoded in 4 nibbles,
			 * but only using one: 0x00r0. Shifting left 4 bits.
			 */
			/* We should bitmask the result correctly when we have a
		 	* packet to dissect, see README.developer, 1.6.2, FID */
			proto_tree_add_uint_format_value(bvlc_tree, hf_bvlc_result, tvb,
				offset, 2, bvlc_result,"0x%04x (%s)",
				bvlc_result, val_to_str(bvlc_result,
					bvlc_result_names, "Unknown"));
			offset += 2;
			break;
		case 0x01: /* Write-Broadcast-Distribution-Table */
		case 0x03: /* Read-Broadcast-Distribution-Table-Ack */
			/* List of BDT Entries:	N*10-octet */
			ti_bdt = proto_tree_add_item(bvlc_tree, proto_bvlc, tvb,
				offset, bvlc_length-4, FALSE);
			bdt_tree = proto_item_add_subtree(ti_bdt, ett_bdt);
			/* List of BDT Entries:	N*10-octet */
			while ((bvlc_length - offset) > 9) {
				proto_tree_add_item(bdt_tree, hf_bvlc_bdt_ip,
					tvb, offset, 4, FALSE);
				offset += 4;
				proto_tree_add_item(bdt_tree, hf_bvlc_bdt_port,
					tvb, offset, 2, FALSE);
				offset += 2;
				proto_tree_add_item(bdt_tree,
					hf_bvlc_bdt_mask, tvb, offset, 4,
					FALSE);
				offset += 4;
			}
			/* We check this if we get a BDT-packet somewhere */
			break;
		case 0x02: /* Read-Broadcast-Distribution-Table */
			/* nothing to do here */
			break;
		case 0x05: /* Register-Foreign-Device */
			/* Time-to-Live	2-octets T, Time-to-Live T, in seconds */
			proto_tree_add_item(bvlc_tree, hf_bvlc_reg_ttl,
				tvb, offset, 2, FALSE);
			offset += 2;
			break;
		case 0x06: /* Read-Foreign-Device-Table */
			/* nothing to do here */
			break;
		case 0x07: /* Read-Foreign-Device-Table-Ack */
			/* List of FDT Entries:	N*10-octet */
			/* N indicates the number of entries in the FDT whose
			 * contents are being returned. Each returned entry
			 * consists of the 6-octet B/IP address of the registrant;
			 * the 2-octet Time-to-Live value supplied at the time of
			 * registration; and a 2-octet value representing the
			 * number of seconds remaining before the BBMD will purge
			 * the registrant's FDT entry if no re-registration occurs.
			 */
			ti_fdt = proto_tree_add_item(bvlc_tree, proto_bvlc, tvb,
				offset, bvlc_length -4, FALSE);
			fdt_tree = proto_item_add_subtree(ti_fdt, ett_fdt);
			/* List of FDT Entries:	N*10-octet */
			while ((bvlc_length - offset) > 9) {
				proto_tree_add_item(fdt_tree, hf_bvlc_fdt_ip,
					tvb, offset, 4, FALSE);
				offset += 4;
				proto_tree_add_item(fdt_tree, hf_bvlc_fdt_port,
					tvb, offset, 2, FALSE);
				offset += 2;
				proto_tree_add_item(fdt_tree,
					hf_bvlc_fdt_ttl, tvb, offset, 2,
					FALSE);
				offset += 2;
				proto_tree_add_item(fdt_tree,
					hf_bvlc_fdt_timeout, tvb, offset, 2,
					FALSE);
				offset += 2;
			}
			/* We check this if we get a FDT-packet somewhere */
			break;
		case 0x08: /* Delete-Foreign-Device-Table-Entry */
			/* FDT Entry:	6-octets */
			proto_tree_add_item(bvlc_tree, hf_bvlc_fdt_ip,
				tvb, offset, 4, FALSE);
			offset += 4;
			proto_tree_add_item(bvlc_tree, hf_bvlc_fdt_port,
				tvb, offset, 2, FALSE);
			offset += 2;
			break;
			/* We check this if we get a FDT-packet somewhere */
		case 0x04:	/* Forwarded-NPDU
				 * Why is this 0x04? It would have been a better
				 * idea to append all forewarded NPDUs at the
				 * end of the function table in the B/IP-standard!
				 */
			/* proto_tree_add_bytes_format(); */
			proto_tree_add_item(bvlc_tree, hf_bvlc_fwd_ip,
				tvb, offset, 4, FALSE);
			offset += 4;
			proto_tree_add_item(bvlc_tree, hf_bvlc_fwd_port,
				tvb, offset, 2, FALSE);
			offset += 2;
		default:/* Distribute-Broadcast-To-Network
			 * Original-Unicast-NPDU
			 * Original-Broadcast-NPDU
			 * Going to the next dissector...
			 */
			break;
		}

	}
/* Ok, no routing information BVLC packet. Dissect as
 * BACnet NPDU
 */
	npdu_length = packet_length - bvlc_length;
	next_tvb = tvb_new_subset(tvb,bvlc_length,-1,npdu_length);
	/* Code from Guy Harris */
	if (!dissector_try_port(bvlc_dissector_table,
	    bvlc_function, next_tvb, pinfo, tree)) {
		/* Unknown function - dissect the paylod as data */
		call_dissector(data_handle,next_tvb, pinfo, tree);
	}
	return tvb_length(tvb);
}
Example #20
0
static void
dissect_payload_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
  proto_tree *payload_kink_encrypt_tree;
  proto_item *ti;
  guint8 next_payload;
  guint payload_length;
#ifdef HAVE_KERBEROS
  gint encrypt_length;
#endif
  guint8 inner_next_pload;
  guint16 inner_payload_length;
  int start_payload_offset = 0;    /* Keep the beginning of the payload offset */

  payload_length = tvb_get_ntohs(tvb,offset + TO_PAYLOAD_LENGTH);
  start_payload_offset = offset;

#ifdef HAVE_KERBEROS
  encrypt_length = payload_length - FROM_NP_TO_PL;
#endif
  /* Make the subtree */
  ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_ENCRYPT");
  payload_kink_encrypt_tree = proto_item_add_subtree(ti, ett_payload_kink_encrypt);

  next_payload = tvb_get_guint8(tvb, offset);
  proto_tree_add_uint(payload_kink_encrypt_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
  offset ++;

  proto_tree_add_item(payload_kink_encrypt_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
  offset ++;

  ti = proto_tree_add_uint(payload_kink_encrypt_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
  if(payload_length <= PAYLOAD_HEADER){
    expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "This Payload Length is too small");
  }
  offset += 2;

  /* decrypt kink encrypt */

  if(keytype != 0){
#ifdef HAVE_KERBEROS
    tvbuff_t *next_tvb;
    guint8 *plaintext=NULL;

    next_tvb=tvb_new_subset(tvb, offset, MIN(tvb_length_remaining(tvb, offset), encrypt_length), encrypt_length);
    plaintext=decrypt_krb5_data(tree, pinfo, 0, next_tvb, keytype, NULL);
    if(plaintext){
      next_tvb=tvb_new_child_real_data(tvb, plaintext, encrypt_length, encrypt_length);
      tvb_set_free_cb(next_tvb, g_free);
      add_new_data_source(pinfo, next_tvb, "decrypted kink encrypt");
      dissect_decrypt_kink_encrypt(pinfo, next_tvb, tree, encrypt_length);
    }
#endif
  }
  else{
    inner_next_pload = tvb_get_guint8(tvb, offset);
    proto_tree_add_uint(payload_kink_encrypt_tree, hf_kink_inner_next_pload, tvb, offset, 1, inner_next_pload);
    offset += 1;

    proto_tree_add_item(payload_kink_encrypt_tree, hf_kink_reserved24, tvb, offset, 3, ENC_BIG_ENDIAN);
    offset += 3;

    if(payload_length > PAYLOAD_HEADER){
      inner_payload_length = payload_length - PAYLOAD_HEADER;
      proto_tree_add_text(payload_kink_encrypt_tree, tvb, offset, inner_payload_length, "Payload");
      offset += inner_payload_length;
    }
  }
  /* This part consider the padding. Payload_length don't contain the padding. */
  if(payload_length % PADDING !=0){
    payload_length += (PADDING - (payload_length % PADDING));
  }
  offset = start_payload_offset + payload_length;

  if(payload_length > 0) {
    control_payload(pinfo, tvb, offset, next_payload, tree);  /* Recur control_payload() */
  }
}
Example #21
0
static
void dissect_pw_cesopsn( tvbuff_t * tvb_original
						,packet_info * pinfo
						,proto_tree * tree
						,pwc_demux_type_t demux)
{
	const int encaps_size = 4; /*RTP header in encapsulation is not supported yet*/
	gint      packet_size;
	gint      payload_size;
	gint      padding_size;
	int properties;

	packet_size = tvb_reported_length_remaining(tvb_original, 0);

	/*
	 * FIXME
	 * "4" below should be replaced by something like "min_packet_size_this_dissector"
	 * Also call to dissect_try_cw_first_nibble() should be moved before this block
	 */
	if (packet_size < 4) /* 4 is smallest size which may be sensible (for PWACH dissector) */
	{
		proto_item  *item;
		item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA);
		expert_add_info_format(pinfo, item, &ei_packet_size_too_small,
				       "PW packet size (%d) is too small to carry sensible information"
				       ,(int)packet_size);
		col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname);
		col_set_str(pinfo->cinfo, COL_INFO, "Malformed: PW packet is too small");
		return;
	}

	switch (demux)
	{
	case PWC_DEMUX_MPLS:
		if (dissect_try_cw_first_nibble(tvb_original, pinfo, tree))
		{
			return;
		}
		break;
	case PWC_DEMUX_UDP:
		break;
	default:
		DISSECTOR_ASSERT_NOT_REACHED();
		return;
	}

	/* check how "good" is this packet */
	/* also decide payload length from packet size and CW */
	properties = PWC_PACKET_PROPERTIES_T_INITIALIZER;
	if (0 != (tvb_get_guint8(tvb_original, 0) & 0xf0 /*bits03*/))
	{
		properties |= PWC_CW_BAD_BITS03;
	}
	if (0 != (tvb_get_guint8(tvb_original, 1) & 0xc0 /*frag*/))
	{
		properties |= PWC_CW_BAD_FRAG;
	}
	{
		/* RFC5086:
		 * [LEN (bits (10 to 15) MAY be used to carry the length of the CESoPSN
		 * packet (defined as the size of the CESoPSN header + the payload size)
		 * if it is less than 64 bytes, and MUST be set to zero otherwise.
		 * Note:  If fixed RTP header is used in the encapsulation, it is
		 * considered part of the CESoPSN header.]
		 *
		 * Note that this differs from RFC4385's definition of length:
		 * [ If the MPLS payload is less than 64 bytes, the length field
		 * MUST be set to the length of the PW payload...]
		 *
		 * We will use RFC5086's definition here.
		 */
		int  cw_len;
		gint payload_size_from_packet;

		cw_len = tvb_get_guint8(tvb_original, 1) & 0x3f;
		payload_size_from_packet = packet_size - encaps_size;
		if (cw_len != 0)
		{
			gint payload_size_from_cw;
			payload_size_from_cw = cw_len - encaps_size;
			/*
			 * Assumptions for error case,
			 * will be overwritten if no errors found:
			 */
			payload_size = payload_size_from_packet;
			padding_size = 0;

			if (payload_size_from_cw < 0)
			{
				properties |= PWC_CW_BAD_PAYLEN_LT_0;
			}
			else if (payload_size_from_cw > payload_size_from_packet)
			{
				properties |= PWC_CW_BAD_PAYLEN_GT_PACKET;
			}
			else if (payload_size_from_packet >= 64)
			{
				properties |= PWC_CW_BAD_LEN_MUST_BE_0;
			}
			else /* ok */
			{
				payload_size = payload_size_from_cw;
				padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */
			}
		}
		else
		{
			payload_size = payload_size_from_packet;
			padding_size = 0;
		}
	}

	{
		guint8 cw_lm;
		cw_lm = tvb_get_guint8(tvb_original, 0) & 0x0b /*l+mod*/;
		if (NULL == try_val_to_str(cw_lm, vals_cw_lm))
		{
			properties |= PWC_CW_SUSPECT_LM;
		}

		{
			guint8 l_bit, m_bits;
			l_bit  = (cw_lm & 0x08) >> 3;
			m_bits = (cw_lm & 0x03) >> 0;
			if ((l_bit == 0 && m_bits == 0x0) /*CESoPSN data packet - normal situation*/
			    ||(l_bit == 0 && m_bits == 0x2) /*CESoPSN data packet - RDI on the AC*/ )
			{
				if ((payload_size == 0) || ((payload_size % 8) != 0))
				{
					properties |= PWC_PAY_SIZE_BAD;
				}
			}
			else if (l_bit == 1 && m_bits == 0x0) /*TDM data is invalid; payload MAY be omitted*/
			{
				/*allow any size of payload*/
			}
			else /*reserved combinations*/
			{
				/*allow any size of payload*/
			}
		}
	}

	/* fill up columns*/
	col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname);
	col_clear(pinfo->cinfo, COL_INFO);
	if (properties & PWC_ANYOF_CW_BAD)
	{
		col_set_str(pinfo->cinfo, COL_INFO, "CW:Bad, ");
	}
	else if (properties & PWC_ANYOF_CW_SUSPECT)
	{
		col_append_str(pinfo->cinfo, COL_INFO, "CW:Suspect, ");
	}

	if (properties & PWC_PAY_SIZE_BAD)
	{
		col_append_str(pinfo->cinfo, COL_INFO, "Payload size:Bad, ");
	}

	col_append_fstr(pinfo->cinfo, COL_INFO, "TDM octets:%d", (int)payload_size);

	if (padding_size != 0)
	{
		col_append_fstr(pinfo->cinfo, COL_INFO, ", Padding:%d", (int)padding_size);
	}

	{
		proto_item* item;
		item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA);
		pwc_item_append_cw(item,tvb_get_ntohl(tvb_original, 0),TRUE);
		pwc_item_append_text_n_items(item,(int)payload_size,"octet");
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				tvbuff_t* tvb;
				proto_item* item2;
				tvb = tvb_new_subset_length(tvb_original, 0, PWC_SIZEOF_CW);
				item2 = proto_tree_add_item(tree2, hf_cw, tvb, 0, -1, ENC_NA);
				pwc_item_append_cw(item2,tvb_get_ntohl(tvb, 0),FALSE);
				{
					proto_tree* tree3;
					tree3 = proto_item_add_subtree(item, ett);
					{
						proto_item* item3;
						if (properties & PWC_CW_BAD_BITS03) /*display only if value is wrong*/
						{
							item3 = proto_tree_add_item(tree3, hf_cw_bits03, tvb, 0, 1, ENC_BIG_ENDIAN);
							expert_add_info(pinfo, item3, &ei_cw_bits03);
						}

						item3 = proto_tree_add_item(tree3, hf_cw_lm,  tvb, 0, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_SUSPECT_LM)
						{
							expert_add_info(pinfo, item3, &ei_cw_lm);
						}

						proto_tree_add_item(tree3, hf_cw_r, tvb, 0, 1, ENC_BIG_ENDIAN);

						item3 = proto_tree_add_item(tree3, hf_cw_frg, tvb, 1, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_FRAG)
						{
							expert_add_info(pinfo, item3, &ei_cw_frg);
						}

						item3 = proto_tree_add_item(tree3, hf_cw_len, tvb, 1, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_PAYLEN_LT_0)
						{
							expert_add_info_format(pinfo, item3, &ei_pref_cw_len,
								"Bad Length: too small, must be > %d",
								(int)encaps_size);
						}
						if (properties & PWC_CW_BAD_PAYLEN_GT_PACKET)
						{
							expert_add_info_format(pinfo, item3, &ei_pref_cw_len,
								"Bad Length: must be <= than PSN packet size (%d)",
								(int)packet_size);
						}
						if (properties & PWC_CW_BAD_LEN_MUST_BE_0)
						{
							expert_add_info_format(pinfo, item3, &ei_pref_cw_len,
								"Bad Length: must be 0 if CESoPSN packet size (%d) is > 64",
								(int)packet_size);
						}

						proto_tree_add_item(tree3, hf_cw_seq, tvb, 2, 2, ENC_BIG_ENDIAN);

					}
				}
			}
		}

		/* payload */
		if (payload_size == 0)
		{
			if (properties & PWC_PAY_SIZE_BAD)
			{
				expert_add_info_format(pinfo, item, &ei_payload_size_invalid_error,
					"CESoPSN payload: none found. Size of payload must be <> 0");
			}
			else
			{
				expert_add_info_format(pinfo, item, &ei_payload_size_invalid_undecoded,
					"CESoPSN payload: omitted to conserve bandwidth");
			}
		}
		else
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				proto_item* item2;
				tvbuff_t* tvb;
				tvb = tvb_new_subset_length(tvb_original, PWC_SIZEOF_CW, payload_size);
				item2 = proto_tree_add_item(tree2, hf_payload, tvb, 0, -1, ENC_NA);
				pwc_item_append_text_n_items(item2,(int)payload_size,"octet");
				if (properties & PWC_PAY_SIZE_BAD)
				{
					expert_add_info_format(pinfo, item2, &ei_payload_size_invalid_error,
						"CESoPSN packet payload size must be multiple of 8");
				}
				tree2 = proto_item_add_subtree(item2, ett);
				call_data_dissector(tvb, pinfo, tree2);
				item2 = proto_tree_add_int(tree2, hf_payload_l, tvb, 0, 0
					,(int)payload_size); /* allow filtering */
				PROTO_ITEM_SET_HIDDEN(item2);
			}
		}

		/* padding */
		if (padding_size > 0)
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				tvbuff_t* tvb;
				tvb = tvb_new_subset(tvb_original, PWC_SIZEOF_CW + payload_size, padding_size, -1);
				call_dissector(pw_padding_handle, tvb, pinfo, tree2);
			}
		}
	}
	return;
}
Example #22
0
static void dissect_user(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree) {
    user_encap_t* encap = NULL;
    tvbuff_t* payload_tvb;
    proto_item* item;
    gint len, reported_len;
    guint i;

    for (i = 0; i < num_encaps; i++) {
        if (encaps[i].encap == pinfo->match_uint) {
            encap = &(encaps[i]);
            break;
        }
    }

    item = proto_tree_add_item(tree,proto_user_encap,tvb,0,-1,ENC_NA);
    if (!encap && pinfo->match_uint == WTAP_ENCAP_USER2) {
        /*
         * Special-case DLT_USER2 - Apple hijacked it for use as DLT_PKTAP.
         * The user hasn't assigned anything to it, so default it to
         * the PKTAP dissector.
         */
        encap = &user2_encap;
    }
    if (!encap) {
        char* msg = wmem_strdup_printf(wmem_packet_scope(),
                                     "User encapsulation not handled: DLT=%d, "
                                     "check your Preferences->Protocols->DLT_USER",
                         pinfo->match_uint + 147 - WTAP_ENCAP_USER0);
        proto_item_set_text(item,"%s",msg);
        expert_add_info_format(pinfo, item, &ei_user_encap_not_handled, "%s", msg);

        call_dissector(data_handle, tvb, pinfo, tree);
        return;
    }
    if (encap->payload_proto == NULL) {
        char* msg = wmem_strdup_printf(wmem_packet_scope(),
                                     "User encapsulation's protocol %s not found: "
                                     "DLT=%d, check your Preferences->Protocols->DLT_USER",
                                     encap->payload_proto_name,
                                     pinfo->match_uint + 147 - WTAP_ENCAP_USER0);
        proto_item_set_text(item,"%s",msg);
        expert_add_info_format(pinfo, item, &ei_user_encap_not_handled, "%s", msg);

        call_dissector(data_handle, tvb, pinfo, tree);
        return;
    }

    proto_item_set_text(item,"DLT: %d",pinfo->match_uint + 147 - WTAP_ENCAP_USER0);

    if (encap->header_size) {
        tvbuff_t* hdr_tvb = tvb_new_subset_length(tvb, 0, encap->header_size);
        call_dissector(encap->header_proto, hdr_tvb, pinfo, tree);
        if (encap->header_proto_name) {
            const char *proto_name = dissector_handle_get_long_name(find_dissector(encap->header_proto_name));
            if (proto_name) {
                proto_item_append_text(item, ", Header: %s (%s)", encap->header_proto_name, proto_name);
            }
        }
    }

    len = tvb_captured_length(tvb) - (encap->header_size + encap->trailer_size);
    reported_len = tvb_reported_length(tvb) - (encap->header_size + encap->trailer_size);

    payload_tvb = tvb_new_subset(tvb, encap->header_size, len, reported_len);
    call_dissector(encap->payload_proto, payload_tvb, pinfo, tree);
    if (encap->payload_proto_name) {
        const char *proto_name = dissector_handle_get_long_name(find_dissector(encap->payload_proto_name));
        if (proto_name) {
            proto_item_append_text(item, ", Payload: %s (%s)", encap->payload_proto_name, proto_name);
        }
    }

    if (encap->trailer_size) {
        tvbuff_t* trailer_tvb = tvb_new_subset_length(tvb, encap->header_size + len, encap->trailer_size);
        call_dissector(encap->trailer_proto, trailer_tvb, pinfo, tree);
        if (encap->trailer_proto_name) {
            const char *proto_name = dissector_handle_get_long_name(find_dissector(encap->trailer_proto_name));
            if (proto_name) {
                proto_item_append_text(item, ", Trailer: %s (%s)", encap->trailer_proto_name, proto_name);
            }
        }
    }
}
Example #23
0
static int
dissect_websocket_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *ws_tree, guint8 opcode, guint payload_length, guint8 mask, const guint8* masking_key)
{
  guint offset = 0;
  proto_item *ti_unmask, *ti;
  dissector_handle_t handle;
  proto_tree *pl_tree, *mask_tree = NULL;
  tvbuff_t *payload_tvb = NULL;

  /* Payload */
  ti = proto_tree_add_item(ws_tree, hf_ws_payload, tvb, offset, payload_length, ENC_NA);
  pl_tree = proto_item_add_subtree(ti, ett_ws_pl);
  if(mask){
    payload_tvb = tvb_unmasked(tvb, offset, payload_length, masking_key);
    tvb_set_child_real_data_tvbuff(tvb, payload_tvb);
    add_new_data_source(pinfo, payload_tvb, payload_length > tvb_length(payload_tvb) ? "Unmasked Data (truncated)" : "Unmasked Data");
    ti = proto_tree_add_item(ws_tree, hf_ws_payload_unmask, payload_tvb, offset, payload_length, ENC_NA);
    mask_tree = proto_item_add_subtree(ti, ett_ws_mask);
  }else{
    payload_tvb = tvb_new_subset(tvb, offset, payload_length, -1);
  }

  handle = dissector_get_uint_handle(port_subdissector_table, pinfo->match_uint);
  if(handle != NULL){
    call_dissector_only(handle, payload_tvb, pinfo, tree, NULL);
  }else{
    dissector_try_heuristic(heur_subdissector_list, payload_tvb, pinfo, tree, NULL);
  }

  /* Extension Data */
  /* TODO: Add dissector of Extension (not extension available for the moment...) */

  /* Application Data */
  switch(opcode){

    case WS_CONTINUE: /* Continue */
      proto_tree_add_item(pl_tree, hf_ws_payload_continue, tvb, offset, payload_length, ENC_NA);
      /* TODO: Add Fragmentation support... */
    break;

    case WS_TEXT: /* Text */
    if(mask){

      proto_tree_add_item(pl_tree, hf_ws_payload_text_mask, tvb, offset, payload_length, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_text_unmask, payload_tvb, offset, payload_length, ENC_UTF_8|ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_text, payload_tvb, offset, payload_length, ENC_UTF_8|ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      const gchar  *saved_match_string = pinfo->match_string;
      void *save_private_data = pinfo->private_data;

      pinfo->match_string = NULL;
      pinfo->private_data = NULL;
      switch(pref_text_type){
      case WEBSOCKET_TEXT:
          call_dissector(text_lines_handle, payload_tvb, pinfo, pl_tree);
          break;
      case WEBSOCKET_JSON:
          call_dissector(json_handle, payload_tvb, pinfo, pl_tree);
          break;
      case WEBSOCKET_NONE:
          /* falltrough */
      default:
          proto_tree_add_item(pl_tree, hf_ws_payload_text, tvb, offset, payload_length, ENC_UTF_8|ENC_NA);
          break;
      }
      pinfo->match_string = saved_match_string;
      pinfo->private_data = save_private_data;
    }
    offset += payload_length;
    break;

    case WS_BINARY: /* Binary */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_binary_mask, tvb, offset, payload_length, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_binary_unmask, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_binary, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_binary, tvb, offset, payload_length, ENC_NA);
    }
    offset += payload_length;
    break;

    case WS_CLOSE: /* Close */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_close_mask, tvb, offset, payload_length, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_unmask, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_status_code, payload_tvb, offset, 2, ENC_BIG_ENDIAN);
      PROTO_ITEM_SET_GENERATED(ti_unmask);

      if(payload_length > 2){
        ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_reason, payload_tvb, offset+2, payload_length-2, ENC_ASCII|ENC_NA);
        PROTO_ITEM_SET_GENERATED(ti_unmask);
      }
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_close, tvb, offset, payload_length, ENC_NA);
      proto_tree_add_item(pl_tree, hf_ws_payload_close_status_code, tvb, offset, 2, ENC_BIG_ENDIAN);
      if(payload_length > 2){
        proto_tree_add_item(pl_tree, hf_ws_payload_close_reason, tvb, offset+2, payload_length-2, ENC_ASCII|ENC_NA);
      }
    }
    offset += payload_length;
    break;

    case WS_PING: /* Ping */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_ping_mask, tvb, offset, payload_length, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_ping_unmask, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_ping, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_ping, tvb, offset, payload_length, ENC_NA);
    }
    offset += payload_length;
    break;

    case WS_PONG: /* Pong */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_pong_mask, tvb, offset, payload_length, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_pong_unmask, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_pong, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_pong, tvb, offset, payload_length, ENC_NA);
    }
    offset += payload_length;
    break;

    default: /* Unknown */
      ti = proto_tree_add_item(pl_tree, hf_ws_payload_unknown, tvb, offset, payload_length, ENC_NA);
      expert_add_info_format(pinfo, ti, &ei_ws_payload_unknown, "Dissector for Websocket Opcode (%d)"
        " code not implemented, Contact Wireshark developers"
        " if you want this supported", opcode);
    break;
  }
  return offset;
}
Example #24
0
/* Both Source-Active and Source-Active Response have the same format
 * with one exception. Encapsulated multicast data is not allowed in
 * SA Response.
 */
static void dissect_msdp_sa(tvbuff_t *tvb, packet_info *pinfo,
    proto_tree *tree, int *offset, int length)
{
        guint8 entries;

        if (length < 1)
                return;
        entries = tvb_get_guint8(tvb, *offset);
        proto_tree_add_uint(tree, hf_msdp_sa_entry_count, tvb, *offset, 1, entries);
        *offset += 1;
        length -= 1;

        if (length < 4) {
                *offset += length;
                return;
        }
        proto_tree_add_item(tree, hf_msdp_sa_rp_addr, tvb, *offset, 4, ENC_BIG_ENDIAN);
        *offset += 4;
        length -= 4;

        /* Put each of the (S,G) entries in their own subtree.
         * This is probably visually better.
         */
        while (entries-- > 0) {
                proto_item *ei;
                proto_tree *entry_tree;

                if (length < 12) {
                        *offset += length;
                        return;
                }
                ei = proto_tree_add_text(tree, tvb, *offset, 12, "(S,G) block: %s/%u -> %s",
                                         tvb_ip_to_str(tvb, *offset + 8),
                                         tvb_get_guint8(tvb, *offset + 3),
                                         tvb_ip_to_str(tvb, *offset + 4));
                entry_tree = proto_item_add_subtree(ei, ett_msdp_sa_entry);

                proto_tree_add_item(entry_tree, hf_msdp_sa_reserved, tvb, *offset, 3, ENC_BIG_ENDIAN);
                *offset += 3;
                length -= 3;
                proto_tree_add_item(entry_tree, hf_msdp_sa_sprefix_len, tvb, *offset, 1, ENC_BIG_ENDIAN);
                *offset += 1;
                length -= 1;
                proto_tree_add_item(entry_tree, hf_msdp_sa_group_addr, tvb, *offset, 4, ENC_BIG_ENDIAN);
                *offset += 4;
                length -= 4;
                proto_tree_add_item(entry_tree, hf_msdp_sa_src_addr, tvb, *offset, 4, ENC_BIG_ENDIAN);
                *offset += 4;
                length -= 4;
        }

        /*
         * Check if an encapsulated multicast IPv4 packet follows
         */
        if (length > 0) {
                proto_item *ei;
                proto_tree *enc_tree;
                gint available_length, reported_length;
                tvbuff_t *next_tvb;

                ei = proto_tree_add_text(tree, tvb, *offset, length,
                                         "Encapsulated IPv4 packet: %u bytes",
                                         length);
                enc_tree = proto_item_add_subtree(ei, ett_msdp_sa_enc_data);

                available_length = tvb_length_remaining(tvb, *offset);
                reported_length = tvb_reported_length_remaining(tvb, *offset);
                DISSECTOR_ASSERT(available_length >= 0);
                DISSECTOR_ASSERT(reported_length >= 0);
                if (available_length > reported_length)
                        available_length = reported_length;
                if (available_length > length)
                        available_length = length;
                if (reported_length > length)
                        reported_length = length;

                next_tvb = tvb_new_subset(tvb, *offset, available_length,
                                          reported_length);
                /* Set the information columns read-only so that they
                 * reflect the MSDP packet rather than the
                 * encapsulated packet.
                 */
                col_set_writable(pinfo->cinfo, FALSE);
                call_dissector(ip_handle, next_tvb, pinfo, enc_tree);
        }
        *offset += length;

        return;
}
Example #25
0
/*
 * Main dissection routine.
 */
static gboolean
dissect_iwarp_mpa(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	tvbuff_t *next_tvb = NULL;
	conversation_t *conversation = NULL;
	mpa_state_t *state = NULL;
	struct tcpinfo *tcpinfo = NULL;
	guint8 endpoint = 3;
	guint16 ulpdu_length = 0;

	/* FPDU */
	if (tvb_length(tvb) >= MPA_SMALLEST_FPDU_LEN && is_mpa_fpdu(pinfo)) {

		tcpinfo = pinfo->private_data;

		conversation = find_conversation(pinfo->fd->num, &pinfo->src,
				&pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);

		state = get_mpa_state(conversation);

		if (pinfo->srcport == state->minfo[MPA_INITIATOR].port) {
			endpoint = MPA_INITIATOR;
		} else if (pinfo->srcport == state->minfo[MPA_RESPONDER].port) {
			endpoint = MPA_RESPONDER;
		} else {
			REPORT_DISSECTOR_BUG("endpoint cannot be determined");
		}

		/* Markers are used by either the Initiator or the Responder or both. */
		if (state->ini_exp_m_res || state->res_exp_m_ini) {

			/* find the TCP sequence number of the first FPDU */
			if (!state->minfo[endpoint].valid) {
				state->minfo[endpoint].seq = tcpinfo->seq;
				state->minfo[endpoint].valid = TRUE;
			}
		}

		/* dissect FPDU */
		ulpdu_length = dissect_mpa_fpdu(tvb, pinfo, tree, state, tcpinfo,
				endpoint);

		/* an ulpdu_length of 0 should never happen */
		if (!ulpdu_length)
			return FALSE;

		/* removes Markers if any and prepares new tvbuff for next dissector */
		if (state->minfo[endpoint].valid
				&& number_of_markers(state, tcpinfo, endpoint) > 0) {
			next_tvb = tvb_new_subset(remove_markers(tvb, pinfo,
					get_first_marker_offset(state, tcpinfo, endpoint),
					number_of_markers(state, tcpinfo, endpoint),
					fpdu_total_length(tcpinfo)), MPA_ULPDU_LENGTH_LEN,
					ulpdu_length, ulpdu_length);
		} else {
			next_tvb = tvb_new_subset(tvb, MPA_ULPDU_LENGTH_LEN, ulpdu_length,
					ulpdu_length);
		}


		/* call subdissector */
		if (ddp_rdmap_handle) {
			call_dissector(ddp_rdmap_handle, next_tvb, pinfo, tree);
		} else {
			REPORT_DISSECTOR_BUG("ddp_handle was null");
		}

		return TRUE;
	}

	/* MPA REQUEST or MPA REPLY */
	if (tvb_length(tvb) >= MPA_REQ_REP_FRAME_HEADER_LEN) {
		if (is_mpa_req(tvb, pinfo))
			return dissect_mpa_req_rep(tvb, pinfo, tree, MPA_REQUEST_FRAME);
		else if (is_mpa_rep(tvb, pinfo))
			return dissect_mpa_req_rep(tvb, pinfo, tree, MPA_REPLY_FRAME);
	}
	return FALSE;
}
static void
dissect_drda(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*drda_tree = NULL;
	proto_tree	*drdaroot_tree = NULL;
	proto_item	*ti = NULL;
	gint offset = 0;
	static gint iPreviousFrameNumber = -1;

	guint16 iCommand;
	guint16 iLength;

	guint8 iFormatFlags;
	guint8 iDSSType;
	guint8 iDSSFlags;

	guint16 iParameterCP;
	proto_tree	*drda_tree_sub;
	gint iLengthParam;

	col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRDA");
	if (check_col(pinfo->cinfo, COL_INFO))
	{
		/* This is a trick to know whether this is the first PDU in this packet or not */
		if (iPreviousFrameNumber != (gint) pinfo->fd->num)
			col_clear(pinfo->cinfo, COL_INFO);
		else
			col_append_str(pinfo->cinfo, COL_INFO, " | ");
	}
	iPreviousFrameNumber = pinfo->fd->num;
	if (tvb_length(tvb) >= 10)
	{
		iCommand = tvb_get_ntohs(tvb, offset + 8);
		iLength = tvb_get_ntohs(tvb, offset + 0);

		if (check_col(pinfo->cinfo, COL_INFO))
		{
			col_append_str(pinfo->cinfo, COL_INFO, val_to_str(iCommand, drda_opcode_abbr, "Unknown (0x%02x)"));
		}

		if (tree)
		{
			ti = proto_tree_add_item(tree, proto_drda, tvb, offset, -1, FALSE);
			proto_item_append_text(ti, " (%s)", val_to_str(iCommand, drda_opcode_vals, "Unknown (0x%02x)"));
			drdaroot_tree = proto_item_add_subtree(ti, ett_drda);

			ti = proto_tree_add_text(drdaroot_tree, tvb, offset, 10, DRDA_TEXT_DDM);
			proto_item_append_text(ti, " (%s)", val_to_str(iCommand, drda_opcode_abbr, "Unknown (0x%02x)"));
			drda_tree = proto_item_add_subtree(ti, ett_drda_ddm);

			proto_tree_add_item(drda_tree, hf_drda_ddm_length, tvb, offset + 0, 2, FALSE);
			proto_tree_add_item(drda_tree, hf_drda_ddm_magic, tvb, offset + 2, 1, FALSE);

			{
				drda_tree_sub = NULL;
				iFormatFlags = tvb_get_guint8(tvb, offset + 3);
				iDSSType = iFormatFlags & 0x0F;
				iDSSFlags = iFormatFlags >> 4;

				ti = proto_tree_add_item(drda_tree, hf_drda_ddm_format, tvb, offset + 3, 1, FALSE);
				drda_tree_sub = proto_item_add_subtree(ti, ett_drda_ddm_format);

				proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_reserved, tvb, offset + 3, 1, iDSSFlags);
				proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_chained, tvb, offset + 3, 1, iDSSFlags);
				proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_errcont, tvb, offset + 3, 1, iDSSFlags);
				proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_samecorr, tvb, offset + 3, 1, iDSSFlags);
				proto_tree_add_uint(drda_tree_sub, hf_drda_ddm_fmt_dsstyp, tvb, offset + 3, 1, iDSSType);
			}

			proto_tree_add_item(drda_tree, hf_drda_ddm_rc, tvb, offset + 4, 2, FALSE);
			proto_tree_add_item(drda_tree, hf_drda_ddm_length2, tvb, offset + 6, 2, FALSE);
			proto_tree_add_item(drda_tree, hf_drda_ddm_codepoint, tvb, offset + 8, 2, FALSE);

			/* The number of attributes is variable */
			for (offset = 10; offset <= iLength; )
			{
				if (tvb_length_remaining(tvb, offset) >= 2)
				{
					iLengthParam = tvb_get_ntohs(tvb, offset + 0);
					if (iLengthParam == 0 || iLengthParam == 1) iLengthParam = iLength - 10;
					if (tvb_length_remaining(tvb, offset) >= iLengthParam)
					{
						drda_tree_sub = NULL;
						iParameterCP = tvb_get_ntohs(tvb, offset + 2);
						ti = proto_tree_add_text(drdaroot_tree, tvb, offset, iLengthParam, DRDA_TEXT_PARAM);
						proto_item_append_text(ti, " (%s)", val_to_str(iParameterCP, drda_opcode_vals, "Unknown (0x%02x)"));
						drda_tree_sub = proto_item_add_subtree(ti, ett_drda_param);
						proto_tree_add_item(drda_tree_sub, hf_drda_param_length, tvb, offset, 2, FALSE);
						proto_tree_add_item(drda_tree_sub, hf_drda_param_codepoint, tvb, offset + 2, 2, FALSE);
						proto_tree_add_item(drda_tree_sub, hf_drda_param_data, tvb, offset + 4, iLengthParam - 4, FALSE);
						proto_tree_add_item(drda_tree_sub, hf_drda_param_data_ebcdic, tvb, offset + 4, iLengthParam - 4, FALSE);
						if (iCommand == DRDA_CP_SQLSTT)
						{
							/* Extract SQL statement from packet */
							tvbuff_t* next_tvb = NULL;
							next_tvb = tvb_new_subset(tvb, offset + 4, iLengthParam - 4, iLengthParam - 4);
							add_new_data_source(pinfo, next_tvb, "SQL statement");
							proto_tree_add_item(drdaroot_tree, hf_drda_sqlstatement, next_tvb, 0, iLengthParam - 5, FALSE);
							proto_tree_add_item(drdaroot_tree, hf_drda_sqlstatement_ebcdic, next_tvb, 0, iLengthParam - 4, FALSE);
						}
					}
					offset += iLengthParam;
				}
				else
				{
					break;
				}
			}
		}
	}
Example #27
0
static void
dissect_dsi_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree      *dsi_tree;
	proto_item	*ti;
	guint8		dsi_flags,dsi_command;
	guint16		dsi_requestid;
	gint32		dsi_code;
	guint32		dsi_length;
	guint32		dsi_reserved;
	struct		aspinfo aspinfo;


	col_set_str(pinfo->cinfo, COL_PROTOCOL, "DSI");
	col_clear(pinfo->cinfo, COL_INFO);

	dsi_flags = tvb_get_guint8(tvb, 0);
	dsi_command = tvb_get_guint8(tvb, 1);
	dsi_requestid = tvb_get_ntohs(tvb, 2);
	dsi_code = tvb_get_ntohl(tvb, 4);
	dsi_length = tvb_get_ntohl(tvb, 8);
	dsi_reserved = tvb_get_ntohl(tvb, 12);

	col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s (%u)",
			val_to_str(dsi_flags, flag_vals,
				   "Unknown flag (0x%02x)"),
			val_to_str_ext(dsi_command, &func_vals_ext,
				   "Unknown function (0x%02x)"),
			dsi_requestid);

	if (tree) {
		ti = proto_tree_add_item(tree, proto_dsi, tvb, 0, -1, ENC_NA);
		dsi_tree = proto_item_add_subtree(ti, ett_dsi);

		proto_tree_add_uint(dsi_tree, hf_dsi_flags, tvb,
			0, 1, dsi_flags);
		proto_tree_add_uint(dsi_tree, hf_dsi_command, tvb,
			1, 1, dsi_command);
		proto_tree_add_uint(dsi_tree, hf_dsi_requestid, tvb,
			2, 2, dsi_requestid);
		switch (dsi_flags) {

		case DSIFL_REQUEST:
			proto_tree_add_int(dsi_tree, hf_dsi_offset, tvb,
				4, 4, dsi_code);
			break;

		case DSIFL_REPLY:
			proto_tree_add_int(dsi_tree, hf_dsi_error, tvb,
				4, 4, dsi_code);
			break;
		}
		proto_tree_add_uint_format(dsi_tree, hf_dsi_length, tvb,
			8, 4, dsi_length,
			"Length: %u bytes", dsi_length);
		proto_tree_add_uint(dsi_tree, hf_dsi_reserved, tvb,
			12, 4, dsi_reserved);
	}
	else
		dsi_tree = tree;
	switch (dsi_command) {
	case DSIFUNC_OPEN:
		if (tree) {
			dissect_dsi_open_session(tvb, dsi_tree, DSI_BLOCKSIZ, dsi_length);
		}
		break;
	case DSIFUNC_ATTN:
		if (tree) {
			dissect_dsi_attention(tvb, dsi_tree, DSI_BLOCKSIZ);
		}
		break;
	case DSIFUNC_STAT:
		if (tree && (dsi_flags == DSIFL_REPLY)) {
			dissect_dsi_reply_get_status(tvb, dsi_tree, DSI_BLOCKSIZ);
		}
		break;
	case DSIFUNC_CMD:
	case DSIFUNC_WRITE:
		{
			tvbuff_t   *new_tvb;
			void* pd_save;
			int len = tvb_reported_length_remaining(tvb,DSI_BLOCKSIZ);

			aspinfo.reply = (dsi_flags == DSIFL_REPLY);
			aspinfo.command = dsi_command;
			aspinfo.seq = dsi_requestid;
			aspinfo.code = dsi_code;
			pd_save = pinfo->private_data;
			pinfo->private_data = &aspinfo;
	  		proto_item_set_len(dsi_tree, DSI_BLOCKSIZ);

			new_tvb = tvb_new_subset(tvb, DSI_BLOCKSIZ,-1,len);
			call_dissector(afp_handle, new_tvb, pinfo, tree);
			pinfo->private_data = pd_save;
		}
		break;
	default:
		if (tree) {
			call_dissector(data_handle,
				       tvb_new_subset_remaining(tvb, DSI_BLOCKSIZ),
				       pinfo, dsi_tree);
		}
		break;
	}
}
Example #28
0
/*
 * Add an Ethernet trailer - which, for some captures, might be the FCS
 * rather than a pad-to-60-bytes trailer.
 *
 * If fcs_len is 0, we assume the frame has no FCS; if it's 4, we assume
 * it has an FCS; if it's anything else (such as -1, which means "maybe
 * it does, maybe it doesn't"), we try to infer whether it has an FCS.
 */
void
add_ethernet_trailer(packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree,
    int trailer_id, tvbuff_t *tvb, tvbuff_t *trailer_tvb, int fcs_len)
{
  /* If there're some bytes left over, it could be a combination of:
     - padding to meet the minimum 64 byte frame length
     - an FCS, if present (if fcs_len is 0, we know it's not present;
       if fcs_len is 4, we know it's present; if fcs_len is -1, we
       need some heuristics to determine whether it's present)
     - information inserted by TAPs or other network monitoring equipment.
    
     If we don't know whether the FCS is present, then, if we don't have a
     network monitoring trailer, and if the Ethernet frame was claimed to
     have had 64 or more bytes - i.e., it was at least an FCS worth of data
     longer than the minimum payload size - we could assume the last 4 bytes
     of the trailer are an FCS. */
  proto_item *item;
  proto_tree *checksum_tree;

  if (trailer_tvb && fh_tree) {
    guint trailer_length, trailer_reported_length;
    guint padding_length = 0;
    gboolean has_fcs = FALSE;
    tvbuff_t *real_trailer_tvb;

    trailer_length = tvb_length(trailer_tvb);
    trailer_reported_length = tvb_reported_length(trailer_tvb);

    /* There can not have been padding when the length of the frame (including the 
       trailer) is less than 60 bytes. */
    if (eth_assume_padding && pinfo->fd->pkt_len>=60) {
        /* Calculate the amount of padding needed for a minimum sized frame */
        if ( (pinfo->fd->pkt_len - trailer_reported_length) < 60 )
            padding_length = 60 - (pinfo->fd->pkt_len - trailer_reported_length);

        /* Add the padding to the tree, unless it should be treated as 
           part of the trailer and therefor be handed over to (one of) 
           the ethernet-trailer dissectors */
        if (padding_length > 0) {
            tvb_ensure_bytes_exist(tvb, 0, padding_length);
            proto_tree_add_item(fh_tree, hf_eth_padding, trailer_tvb, 0,
                padding_length, ENC_NA);
            trailer_length -= padding_length;
            trailer_reported_length -= padding_length;
        }
    }

    if (fcs_len != 0) {
      /* If fcs_len is 4, we assume we definitely have an FCS.
         Otherwise, then, if the frame is big enough that, if we
         have a trailer, it probably inclues an FCS, and we have
         enough space in the trailer for the FCS, we assume we
         have an FCS.

         "Big enough" means 64 bytes or more; any frame that big
         needs no trailer, as there's no need to pad an Ethernet
         packet past 60 bytes.

         The trailer must be at least 4 bytes long to have enough
         space for an FCS. */

      if (fcs_len == 4 || (tvb_reported_length(tvb) >= 64 &&
        trailer_reported_length >= 4)) {
        /* Either we know we have an FCS, or we believe we have an FCS. */
        if (trailer_length < trailer_reported_length) {
          /* The packet is claimed to have enough data for a 4-byte FCS,
             but we didn't capture all of the packet.
             Slice off the 4-byte FCS from the reported length, and
             trim the captured length so it's no more than the reported
             length; that will slice off what of the FCS, if any, is
             in the captured packet. */
          trailer_reported_length -= 4;
          if (trailer_length > trailer_reported_length)
            trailer_length = trailer_reported_length;
          has_fcs = TRUE;
        } else {
          /* We captured all of the packet, including what appears to
             be a 4-byte FCS.  Slice it off. */
          trailer_length -= 4;
          trailer_reported_length -= 4;
          has_fcs = TRUE;
        }
      }
    }

    /* Create a new tvb without the padding and/or the (assumed) fcs */
    if (fcs_len==4) 
      real_trailer_tvb = tvb_new_subset(trailer_tvb, padding_length,
                                trailer_length, trailer_reported_length);
    else
      real_trailer_tvb = tvb_new_subset_remaining(trailer_tvb, padding_length);

    /* Call all ethernet trailer dissectors to dissect the trailer if
       we actually have a trailer.  */
    if (tvb_reported_length(real_trailer_tvb) != 0) {
      if (dissector_try_heuristic(eth_trailer_subdissector_list, 
                                   real_trailer_tvb, pinfo, tree, NULL) ) {
        /* If we're not sure that there is a FCS, all trailer data
           has been given to the ethernet-trailer dissector, so 
           stop dissecting here */
        if (fcs_len!=4) 
            return;
      } else {
        /* No luck with the trailer dissectors, so just display the
           extra bytes as general trailer */
        if (trailer_length != 0) {
          tvb_ensure_bytes_exist(tvb, 0, trailer_length);
          proto_tree_add_item(fh_tree, trailer_id, real_trailer_tvb, 0,
            trailer_length, ENC_NA);
        }
      }
    }

    if (has_fcs) {
      guint32 sent_fcs = tvb_get_ntohl(trailer_tvb, padding_length+trailer_length);
      if(eth_check_fcs){
        guint32 fcs = crc32_802_tvb(tvb, tvb_length(tvb) - 4);
        if (fcs == sent_fcs) {
          item = proto_tree_add_uint_format(fh_tree, hf_eth_fcs, trailer_tvb,
                                            padding_length+trailer_length, 4, sent_fcs,
                                            "Frame check sequence: 0x%08x [correct]", sent_fcs);
          checksum_tree = proto_item_add_subtree(item, ett_eth_fcs);
          item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb,
                                        padding_length+trailer_length, 4, TRUE);
          PROTO_ITEM_SET_GENERATED(item);
          item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb,
                                        padding_length+trailer_length, 4, FALSE);
          PROTO_ITEM_SET_GENERATED(item);
        } else {
          item = proto_tree_add_uint_format(fh_tree, hf_eth_fcs, trailer_tvb,
                                            padding_length+trailer_length, 4, sent_fcs,
                                            "Frame check sequence: 0x%08x [incorrect, should be 0x%08x]",
                                            sent_fcs, fcs);
          checksum_tree = proto_item_add_subtree(item, ett_eth_fcs);
          item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb,
                                        padding_length+trailer_length, 4, FALSE);
          PROTO_ITEM_SET_GENERATED(item);
          item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb,
                                        padding_length+trailer_length, 4, TRUE);
          PROTO_ITEM_SET_GENERATED(item);
          expert_add_info(pinfo, item, &ei_eth_fcs_bad);
          col_append_str(pinfo->cinfo, COL_INFO, " [ETHERNET FRAME CHECK SEQUENCE INCORRECT]");
        }
      }else{
        item = proto_tree_add_uint_format(fh_tree, hf_eth_fcs, trailer_tvb,
                                          padding_length+trailer_length, 4, sent_fcs,
                                          "Frame check sequence: 0x%08x [validiation disabled]", sent_fcs);
        checksum_tree = proto_item_add_subtree(item, ett_eth_fcs);
        item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb,
                                      padding_length+trailer_length, 4, FALSE);
        PROTO_ITEM_SET_GENERATED(item);
        item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb,
                                      padding_length+trailer_length, 4, FALSE);
        PROTO_ITEM_SET_GENERATED(item);
      }
      trailer_length += 4;
    }
    proto_tree_set_appendix(fh_tree, tvb, tvb_length(tvb) - padding_length - trailer_length, padding_length + trailer_length);
  }
}
Example #29
0
/* Code to actually dissect the packets */
static int
dissect_lisp_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    gint offset = 0;
    guint8 flags;
    guint8 ip_ver;
    tvbuff_t *next_tvb;
    proto_item *ti;
    proto_item *tif;
    proto_tree *lisp_data_tree;
    proto_tree *lisp_data_flags_tree;

    /* Check that there's enough data */
    if (tvb_length(tvb) < LISP_DATA_HEADER_LEN)
        return 0;

    /* Make entries in Protocol column and Info column on summary display */
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "LISP");

    col_set_str(pinfo->cinfo, COL_INFO, "LISP Encapsulation Header");

    if (tree) {

        /* create display subtree for the protocol */
        ti = proto_tree_add_item(tree, proto_lisp_data, tvb, 0,
                LISP_DATA_HEADER_LEN, FALSE);

        lisp_data_tree = proto_item_add_subtree(ti, ett_lisp_data);

        tif = proto_tree_add_item(lisp_data_tree,
                hf_lisp_data_flags, tvb, offset, 1, FALSE);

        lisp_data_flags_tree = proto_item_add_subtree(tif, ett_lisp_data_flags);

        proto_tree_add_item(lisp_data_flags_tree,
                hf_lisp_data_flags_nonce, tvb, offset, 1, FALSE);
        proto_tree_add_item(lisp_data_flags_tree,
                hf_lisp_data_flags_lsb, tvb, offset, 1, FALSE);
        proto_tree_add_item(lisp_data_flags_tree,
                hf_lisp_data_flags_enr, tvb, offset, 1, FALSE);
        proto_tree_add_item(lisp_data_flags_tree,
                hf_lisp_data_flags_mv, tvb, offset, 1, FALSE);
        proto_tree_add_item(lisp_data_flags_tree,
                hf_lisp_data_flags_iid, tvb, offset, 1, FALSE);
        proto_tree_add_item(lisp_data_flags_tree,
                hf_lisp_data_flags_res, tvb, offset, 1, FALSE);

        flags = tvb_get_guint8(tvb, offset);
        offset += 1;

        if (flags&LISP_DATA_FLAG_E && !(flags&LISP_DATA_FLAG_N)) {
            proto_tree_add_text(lisp_data_tree, tvb, offset, 0,
                    "Invalid flag combination: if E is set, N MUST be set");
        }

        if (flags&LISP_DATA_FLAG_N) {
            if (flags&LISP_DATA_FLAG_V) {
                proto_tree_add_text(lisp_data_tree, tvb, offset, 0,
                        "Invalid flag combination: N and V can't be set both");
            }
            proto_tree_add_item(lisp_data_tree,
                    hf_lisp_data_nonce, tvb, offset, 3, FALSE);
        } else {
            if (flags&LISP_DATA_FLAG_V) {
                proto_item *tiv;
                proto_tree *lisp_data_mapver_tree;

                tiv = proto_tree_add_item(lisp_data_tree,
                        hf_lisp_data_mapver, tvb, offset, 3, FALSE);

                lisp_data_mapver_tree = proto_item_add_subtree(tiv, ett_lisp_data_mapver);

                proto_tree_add_item(lisp_data_mapver_tree,
                        hf_lisp_data_srcmapver, tvb, offset, 3, FALSE);
                proto_tree_add_item(lisp_data_mapver_tree,
                        hf_lisp_data_dstmapver, tvb, offset, 3, FALSE);
            }
        }
        offset += 3;

        if (flags&LISP_DATA_FLAG_I) {
            proto_tree_add_item(lisp_data_tree,
                    hf_lisp_data_iid, tvb, offset, 3, FALSE);
            offset += 3;
            if (flags&LISP_DATA_FLAG_L) {
                proto_tree_add_item(lisp_data_tree,
                        hf_lisp_data_lsb8, tvb, offset, 1, FALSE);
            }
            offset +=1;
        } else {
            if (flags&LISP_DATA_FLAG_L) {
                proto_tree_add_item(lisp_data_tree,
                        hf_lisp_data_lsb, tvb, offset, 4, FALSE);
                offset += 4;
            }
        }
    }

    /* Check if there is stuff left in the buffer, and return if not */

    /* Determine if encapsulated packet is IPv4 or IPv6, and call dissector */
    next_tvb = tvb_new_subset(tvb, LISP_DATA_HEADER_LEN, -1, -1);
    ip_ver = tvb_get_bits8(next_tvb, 0, 4);
    switch (ip_ver) {
        case 4:
            call_dissector(ipv4_handle, next_tvb, pinfo, tree);
            break;
        case 6:
            call_dissector(ipv6_handle, next_tvb, pinfo, tree);
            break;
        default:
            call_dissector(data_handle, next_tvb, pinfo, tree);
            break;
    }

    /* Return the amount of data this dissector was able to dissect */
    return tvb_length(tvb);
}
/* Code to actually dissect the packets */
static void dissect_t2sf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  tvbuff_t *next_tvb;
  int available_length;
  guint8 sf_payload_length = 0;
  guint8 sf_type;
  
  /* Set up structures needed to add the protocol subtree and manage it */
  proto_item *ti;
  proto_tree *t2sf_tree;
  
  /* check if this is sf packet is really sane. If length is incorrect this might be another packet */
  if (tvb_get_guint8(tvb, 0)+1 != tvb_length(tvb)) {
    call_dissector(data_handle, tvb, pinfo, tree);
    return;
  }
  
  sf_payload_length = tvb_get_guint8(tvb, T2_SF_HEADER_LENGTH_OFFSET)+1;
  sf_type = tvb_get_guint8(tvb, T2_SF_HEADER_TYPE_OFFSET);

  /* Make entries in Protocol column and Info column on summary display */
  if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "T2 SF");

  if (check_col(pinfo->cinfo, COL_INFO)) 
    col_set_str(pinfo->cinfo, COL_INFO, "TinyOS 2 SerialForwarder Packet");

  if (tree) {

    /* create display subtree for the protocol */
    ti = proto_tree_add_item(tree, proto_t2sf, tvb, 0, -1, FALSE);
    t2sf_tree = proto_item_add_subtree(ti, ett_t2sf);

    /* add items to the subtree */
    proto_tree_add_item(t2sf_tree, hf_t2sf_length, tvb, T2_SF_HEADER_LENGTH_OFFSET, T2_SF_LENGTH_NUM_BYTES, FALSE);
    proto_tree_add_item(t2sf_tree, hf_t2sf_type, tvb, T2_SF_HEADER_TYPE_OFFSET, T2_SF_TYPE_NUM_BYTES, FALSE);
 
    /*
      if (sf_length > 0) {
      proto_tree_add_item(t2sf_tree, hf_t2sf_data, tvb, SERIAL_AM_DATA_OFFSET, serial_am_payload_length, FALSE);
      }
    */
  }
  
  /* Calculate the available data in the packet, 
     set this to -1 to use all the data in the tv_buffer */
  available_length = tvb_length(tvb) - T2_SF_HEADER_LEN;

  /* Create the tvbuffer for the next dissector */
  next_tvb = tvb_new_subset(tvb, T2_SF_HEADER_LEN, MIN(available_length, sf_payload_length), sf_payload_length);
  
  /* check if message has type field */
  if (dissector_try_port(t2sf_type_dissector_table, sf_type, next_tvb, pinfo, tree)) {
    return;
  }

  /* try "heuristics */
  if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree)) {
    return;
  }
  
  /* call the next dissector */
  call_dissector(data_handle, next_tvb, pinfo, tree);
  return;
}