Example #1
0
static void
dissect_netrom_routing(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	tvbuff_t *next_tvb;

	col_set_str( pinfo->cinfo, COL_PROTOCOL, "NET/ROM");
	col_set_str( pinfo->cinfo, COL_INFO, "routing table frame");

	if (tree)
		{
		proto_item *ti;
		proto_tree *netrom_tree;
		ti = proto_tree_add_protocol_format( tree, proto_netrom, tvb, 0, -1,
			"NET/ROM, routing table frame, Node: %.6s",
			tvb_get_ptr( tvb,  1, 6 )
			 );

		netrom_tree = proto_item_add_subtree( ti, ett_netrom );

		proto_tree_add_item( netrom_tree, hf_netrom_mnemonic, tvb, 1, 6, ENC_ASCII|ENC_NA );
		}

	next_tvb = tvb_new_subset_remaining(tvb, 7);

	call_data_dissector(next_tvb, pinfo, tree );
}
Example #2
0
void
chdlctype(guint16 chdlc_type, tvbuff_t *tvb, int offset_after_chdlctype,
          packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree,
          int chdlctype_id)
{
  tvbuff_t *next_tvb;
  int       padbyte;

  proto_tree_add_uint(fh_tree, chdlctype_id, tvb,
                        offset_after_chdlctype - 2, 2, chdlc_type);

  padbyte = tvb_get_guint8(tvb, offset_after_chdlctype);
  if (chdlc_type == CHDLCTYPE_OSI &&
    !( padbyte == NLPID_ISO8473_CLNP || /* older Juniper SW does not send a padbyte */
       padbyte == NLPID_ISO9542_ESIS ||
       padbyte == NLPID_ISO10589_ISIS)) {
    /* There is a Padding Byte for CLNS protocols over Cisco HDLC */
    proto_tree_add_item(fh_tree, hf_chdlc_clns_padding, tvb, offset_after_chdlctype, 1, ENC_BIG_ENDIAN);
    next_tvb = tvb_new_subset_remaining(tvb, offset_after_chdlctype + 1);
  } else {
    next_tvb = tvb_new_subset_remaining(tvb, offset_after_chdlctype);
  }

  /* do lookup with the subdissector table */
  if (!dissector_try_uint(subdissector_table, chdlc_type, next_tvb, pinfo, tree)) {
    col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", chdlc_type);
    call_data_dissector(next_tvb, pinfo, tree);
  }
}
Example #3
0
static void
decode_pgm_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
		 proto_tree *tree, guint16 pgmhdr_sport, guint16 pgmhdr_dport)
{
	tvbuff_t *next_tvb;
	int       found = 0;
	heur_dtbl_entry_t *hdtbl_entry;

	next_tvb = tvb_new_subset_remaining(tvb, offset);

	/* do lookup with the subdissector table */
	found = dissector_try_uint(subdissector_table, pgmhdr_sport,
				   next_tvb, pinfo, tree);
	if (found)
		return;

	found = dissector_try_uint(subdissector_table, pgmhdr_dport,
				   next_tvb, pinfo, tree);
	if (found)
		return;

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

	/* Oh, well, we don't know this; dissect it as data. */
	call_data_dissector(next_tvb, pinfo, tree);
}
static void
dissect_quakeworld_server_commands(tvbuff_t *tvb, packet_info *pinfo,
	proto_tree *tree)
{
	/* If I have too much time at hand, I'll fill it with all
	   the information from my QWD specs:
		http://www.planetquake.com/demospecs/qwd/
	*/
	call_data_dissector(tvb, pinfo, tree);
}
Example #5
0
static void
dissect_netbios_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	heur_dtbl_entry_t *hdtbl_entry;

	/*
	 * Try the heuristic dissectors for NetBIOS; if none of them
	 * accept the packet, dissect it as data.
	 */
	if (!dissector_try_heuristic(netbios_heur_subdissector_list,
				    tvb, pinfo, tree, &hdtbl_entry, NULL))
		call_data_dissector(tvb, pinfo, tree);
}
Example #6
0
static int
dissect_vxlan_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int is_gpe)
{
    proto_tree *vxlan_tree;
    proto_item *ti;
    tvbuff_t *next_tvb;
    int offset = 0;
    guint32 vxlan_next_proto;

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


    ti = proto_tree_add_item(tree, proto_vxlan, tvb, offset, 8, ENC_NA);
    vxlan_tree = proto_item_add_subtree(ti, ett_vxlan);

    if(is_gpe) {
        proto_tree_add_bitmask(vxlan_tree, tvb, offset, hf_vxlan_gpe_flags, ett_vxlan_flags, gpe_flags_fields, ENC_BIG_ENDIAN);
        offset += 1;

        proto_tree_add_item(vxlan_tree, hf_vxlan_gpe_reserved_16, tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;

        proto_tree_add_item_ret_uint(vxlan_tree, hf_vxlan_next_proto, tvb, offset, 1, ENC_BIG_ENDIAN, &vxlan_next_proto);
        offset += 1;
    } else {
        proto_tree_add_bitmask(vxlan_tree, tvb, offset, hf_vxlan_flags, ett_vxlan_flags, flags_fields, ENC_BIG_ENDIAN);
        offset += 2;

        proto_tree_add_item(vxlan_tree, hf_vxlan_gbp, tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;
    }

    proto_tree_add_item(vxlan_tree, hf_vxlan_vni, tvb, offset, 3, ENC_BIG_ENDIAN);
    offset += 3;

    proto_tree_add_item(vxlan_tree, hf_vxlan_reserved_8, tvb, offset, 1, ENC_BIG_ENDIAN);
    offset += 1;

    next_tvb = tvb_new_subset_remaining(tvb, offset);

    if(is_gpe){
        if(!dissector_try_uint(vxlan_dissector_table, vxlan_next_proto, next_tvb, pinfo, tree)) {
            call_data_dissector(next_tvb, pinfo, vxlan_tree);
        }
    } else {
        call_dissector(eth_handle, next_tvb, pinfo, tree);
    }

    return tvb_captured_length(tvb);
}
Example #7
0
static void
dissect_protocol_data_parameter(tvbuff_t *parameter_tvb, proto_item *parameter_item, packet_info *pinfo, proto_tree *tree)
{
  guint16 protocol_data_length;
  tvbuff_t *protocol_data_tvb;

  protocol_data_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
  protocol_data_tvb    = tvb_new_subset_length(parameter_tvb, PROTOCOL_DATA_OFFSET, protocol_data_length);
  if(dpnss_handle){
    call_dissector(dpnss_handle, protocol_data_tvb, pinfo, tree);
    return;
  }

  call_data_dissector(protocol_data_tvb, pinfo, tree);

  proto_item_append_text(parameter_item, " (%u byte%s)", protocol_data_length, plurality(protocol_data_length, "", "s"));
}
Example #8
0
/*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 auxiliary 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;

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

#ifdef HAVE_LIBGCRYPT
    proto_item         *ti;
    proto_item         *key_item;
    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;

    static const int * sec_flags[] = {
        &hf_zbee_sec_key_id,
        &hf_zbee_sec_nonce,
        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(wmem_file_scope(), pinfo,
        proto_get_id_by_filter_name(ZBEE_PROTOABBREV_NWK), 0);
    ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
        proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);

    /* Create a subtree for the security information. */
    sec_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_zbee_sec, NULL, "ZigBee Security Header");

    /*  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 tvb_memdup(wmem_packet_scope(),...)
     * is automatically freed before the next packet is processed.
     */
#ifdef HAVE_LIBGCRYPT
    enc_buffer = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, 0, tvb_captured_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 tvb_memdup(wmem_packet_scope(),...).
     */
    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);

    proto_tree_add_bitmask(sec_tree, tvb, offset, hf_zbee_sec_field, ett_zbee_sec_control, sec_flags, ENC_NA);
    offset += 1;

    /* Get and display the frame counter field. */
    packet.counter = tvb_get_letohl(tvb, offset);
    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);
        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->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->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
                    proto_tree_add_expert(sec_tree, pinfo, &ei_zbee_sec_extended_source_unknown, tvb, 0, 0);
                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
                    proto_tree_add_expert(sec_tree, pinfo, &ei_zbee_sec_extended_source_unknown, tvb, 0, 0);
                break;
        }
    }

    if (packet.key_id == ZBEE_SEC_KEY_NWK) {
        /* Get and display the key sequence number. */
        packet.key_seqno = tvb_get_guint8(tvb, offset);
        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. */
        proto_tree_add_item(sec_tree, hf_zbee_sec_mic, tvb, (gint)(tvb_captured_length(tvb)-mic_len),
                mic_len, ENC_NA);
    }

    /* Check for null payload. */
    payload_len = tvb_reported_length_remaining(tvb, offset+mic_len);
    if (payload_len == 0)
        return NULL;

    /**********************************************
     *  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_length(tvb, offset, payload_len);
    }

#ifdef HAVE_LIBGCRYPT
    /* Have we captured all the payload? */
    if (tvb_captured_length_remaining(tvb, offset+mic_len) < payload_len) {
        /*
         * No - don't try to decrypt it.
         *
         * XXX - it looks as if the decryption code is assuming we have the
         * MIC, which won't be the case if the packet was cut short.  Is
         * that in fact that case, or can we still make this work with a
         * partially-captured packet?
         */
        /* Add expert info. */
        expert_add_info(pinfo, sec_tree, &ei_zbee_sec_encrypted_payload_sliced);
        /* Create a buffer for the undecrypted payload. */
        payload_tvb = tvb_new_subset_length(tvb, offset, payload_len);
        /* Dump the payload to the data dissector. */
        call_data_dissector(payload_tvb, pinfo, tree);
        /* Couldn't decrypt, so return NULL. */
        return NULL;
    }

    /* 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 ) {
            key_item = proto_tree_add_bytes(sec_tree, hf_zbee_sec_key, tvb, 0, ZBEE_SEC_CONST_KEYSIZE, key_rec->key);
            PROTO_ITEM_SET_GENERATED(key_item);

            if ( key_rec->frame_num == ZBEE_SEC_PC_KEY ) {
                ti = proto_tree_add_string(sec_tree, hf_zbee_sec_decryption_key, tvb, 0, 0, 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_length(tvb, offset, payload_len);
    /* Dump the payload to the data dissector. */
    call_data_dissector(payload_tvb, pinfo, tree);
    /* Couldn't decrypt, so return NULL. */
    return NULL;
} /* dissect_zbee_secure */
Example #9
0
static void
dissect_rpl_container(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint16 len, type, sublen, subtyp;
	proto_tree *rpl_container_tree;
	guint16 offset;
	gint ett_type;
	gint length, reported_length;

	len = tvb_get_ntohs(tvb, 0);
	proto_tree_add_item(tree, hf_rpl_len, tvb, 0, 2, ENC_BIG_ENDIAN);

	type = tvb_get_ntohs(tvb, 2);
	proto_tree_add_item(tree, hf_rpl_type, tvb, 2, 2, ENC_BIG_ENDIAN);
	offset = 4;

	switch (type) {
		case 1:
		case 2:
		case 4:
		case 8:
		case 0x10:
		case 0x20:
			while (len >= offset+4) {
				sublen = tvb_get_ntohs(tvb, offset);
				subtyp = tvb_get_ntohs(tvb, offset+2);
				ett_type = ett_rpl_unkn;
				if(subtyp == 0x0004) ett_type = ett_rpl_0004;
				if(subtyp == 0x0008) ett_type = ett_rpl_0008;
				if(subtyp == 0x4003) ett_type = ett_rpl_4003;
				if(subtyp == 0x4006) ett_type = ett_rpl_4006;
				if(subtyp == 0x4007) ett_type = ett_rpl_4007;
				if(subtyp == 0x4009) ett_type = ett_rpl_4009;
				if(subtyp == 0x400a) ett_type = ett_rpl_400a;
				if(subtyp == 0x400b) ett_type = ett_rpl_400b;
				if(subtyp == 0x400c) ett_type = ett_rpl_400c;
				if(subtyp == 0x4011) ett_type = ett_rpl_4011;
				if(subtyp == 0x4018) ett_type = ett_rpl_4018;
				if(subtyp == 0xc005) ett_type = ett_rpl_c005;
				if(subtyp == 0xc014) ett_type = ett_rpl_c014;
				rpl_container_tree = proto_tree_add_subtree(tree, tvb,
					offset, sublen, ett_type, NULL,
					val_to_str_const(subtyp,
						rpl_type_vals,
						"Unknown Type"));
				length = tvb_captured_length_remaining(tvb, offset);
				if (length > sublen)
					length = sublen;
				reported_length = tvb_reported_length_remaining(tvb, offset);
				if (reported_length > sublen)
					reported_length = sublen;
				if ( length > 0) {
				  dissect_rpl_container(tvb_new_subset_length_caplen(tvb,
					offset, length, reported_length),
					pinfo, rpl_container_tree);
				  offset += reported_length;
				} else {
				  /* no more data, exit the loop */
				  offset += reported_length;
				  break;
				}
			}
			break;

		case 0x4003:
			proto_tree_add_item(tree, hf_rpl_corrval,
				tvb, offset, 4, ENC_BIG_ENDIAN);
			offset += 4;
			break;

		case 0x4006:
			proto_tree_add_item(tree, hf_rpl_lmac,
				tvb, offset, 6, ENC_NA);
			offset += 6;
			break;

		case 0x4007:
			proto_tree_add_item(tree, hf_rpl_sap,
				tvb, offset, 1, ENC_BIG_ENDIAN);
			offset ++;
			break;

		case 0x4009:
			proto_tree_add_item(tree, hf_rpl_maxframe,
				tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
			break;

		case 0x400a:
			proto_tree_add_item(tree, hf_rpl_connclass,
				tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
			break;

		case 0x400b:
			proto_tree_add_item(tree, hf_rpl_respval,
				tvb, offset, 1, ENC_BIG_ENDIAN);
			offset ++;
			break;

		case 0x400c:
			proto_tree_add_item(tree, hf_rpl_smac,
				tvb, offset, 6, ENC_NA);
			offset += 6;
			break;

		case 0x4011:
			proto_tree_add_item(tree, hf_rpl_sequence,
				tvb, offset, 4, ENC_BIG_ENDIAN);
			offset += 4;
			break;

		case 0x4018:
			proto_tree_add_item(tree, hf_rpl_data,
				tvb, offset, len-4, ENC_NA);
			offset += len - 4;
			break;

		case 0xc005:
			proto_tree_add_item(tree, hf_rpl_config,
				tvb, offset, 8, ENC_NA);
			offset += 8;
			proto_tree_add_item(tree, hf_rpl_equipment,
				tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
			proto_tree_add_item(tree, hf_rpl_memsize,
				tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
			proto_tree_add_item(tree, hf_rpl_bsmversion,
				tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
			proto_tree_add_item(tree, hf_rpl_ec,
				tvb, offset, 6, ENC_NA);
			offset += 6;
			proto_tree_add_item(tree, hf_rpl_adapterid,
				tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
			proto_tree_add_item(tree, hf_rpl_shortname,
				tvb, offset, 10, ENC_NA);
			offset += 10;
			break;

		case 0xc014:
			proto_tree_add_item(tree, hf_rpl_laddress,
				tvb, offset, 4, ENC_BIG_ENDIAN);
			offset += 4;
			proto_tree_add_item(tree, hf_rpl_xaddress,
				tvb, offset, 4, ENC_BIG_ENDIAN);
			offset += 4;
			proto_tree_add_item(tree, hf_rpl_flags,
				tvb, offset, 1, ENC_BIG_ENDIAN);
			offset ++;
			break;

		default:
			call_data_dissector(tvb_new_subset_remaining(tvb, 4), pinfo,
				tree);
			break;
	}
	if (tvb_reported_length(tvb) > offset)
		call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
}
Example #10
0
static int
dissect_ipmi_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
		gint hf_parent_item, gint ett_tree, const ipmi_context_t * ctx)
{
	ipmi_packet_data_t * data;
	ipmi_netfn_t * cmd_list;
	ipmi_cmd_t * cmd;
	proto_item * ti;
	proto_tree * cmd_tree = NULL, * tmp_tree;
	guint8 prev_level, cc_val;
	guint offset, siglen, is_resp;
	const char * cc_str, * netfn_str;

	/* get packet data */
	data = get_packet_data(pinfo);
	if (!data) {
		return 0;
	}

	/* get prefix length */
	siglen = ipmi_getsiglen(ctx->hdr.netfn);

	/* get response flag */
	is_resp = ctx->hdr.netfn & 1;

	/* check message length */
	if (tvb_captured_length(tvb) < ctx->hdr_len + siglen + is_resp
			+ !(ctx->flags & IPMI_D_NO_CKS)) {
		/* don bother with anything */
		return call_data_dissector(tvb, pinfo, tree);
	}

	/* save nest level */
	prev_level = data->curr_level;

	/* assign next nest level */
	data->curr_level = data->next_level;

	/* increment next nest level */
	data->next_level++;

	/* check for the first invocation */
	if (!data->curr_level) {
		/* get current frame data */
		data->curr_frame = get_frame_data(data, pinfo->num);
		data->curr_frame_num = pinfo->num;

		/* copy frame timestamp */
		memcpy(&data->curr_frame->ts, &pinfo->abs_ts, sizeof(nstime_t));

		/* cache channel and direction */
		data->curr_channel = ctx->hdr.channel;
		data->curr_dir = ctx->hdr.dir;

		/* remove requests which are too old */
		remove_old_requests(data, &pinfo->abs_ts);
	}

	if (data->curr_level < MAX_NEST_LEVEL) {
		if (ctx->hdr.netfn & 1) {
			/* perform request/response matching */
			match_request_response(data, &ctx->hdr, ctx->flags);
		} else {
			/* add request to the list for later matching */
			add_request(data, &ctx->hdr);
		}
	}

	/* get command list by network function code */
	cmd_list = ipmi_getnetfn(ctx->hdr.netfn,
			tvb_get_ptr(tvb, ctx->hdr_len + is_resp, siglen));

	/* get command descriptor */
	cmd = ipmi_getcmd(cmd_list, ctx->hdr.cmd);

	/* check if response */
	if (is_resp) {
		/* get completion code */
		cc_val = tvb_get_guint8(tvb, ctx->hdr_len);

		/* get completion code desc */
		cc_str = ipmi_get_completion_code(cc_val, cmd);
	} else {
		cc_val = 0;
		cc_str = NULL;
	}

	/* check if not inside a message */
	if (!data->curr_level) {
		/* add packet info */
		add_command_info(pinfo, cmd, is_resp, cc_val, cc_str,
				ctx->flags & IPMI_D_BROADCAST ? TRUE : FALSE);
	}

	if (tree) {
		/* add parent node */
		if (!data->curr_level) {
			ti = proto_tree_add_item(tree, hf_parent_item, tvb, 0, -1, ENC_NA);
			cmd_tree = proto_item_add_subtree(ti, ett_tree);
		} else {
			char str[ITEM_LABEL_LENGTH];

			if (is_resp) {
				g_snprintf(str, ITEM_LABEL_LENGTH, "Rsp, %s, %s",
						cmd->desc, cc_str);
			} else {
				g_snprintf(str, ITEM_LABEL_LENGTH, "Req, %s", cmd->desc);
			}
			if (proto_registrar_get_ftype(hf_parent_item) == FT_STRING) {
				ti = proto_tree_add_string(tree, hf_parent_item, tvb, 0, -1, str);
				cmd_tree = proto_item_add_subtree(ti, ett_tree);
			}
			else
				cmd_tree = proto_tree_add_subtree(tree, tvb, 0, -1, ett_tree, NULL, str);
		}

		if (data->curr_level < MAX_NEST_LEVEL) {
			/* check if response */
			if (ctx->hdr.netfn & 1) {
				/* get current command data */
				ipmi_cmd_data_t * rs_data =
						data->curr_frame->cmd_data[data->curr_level];

				if (rs_data->matched_frame_num) {
					nstime_t ns;

					/* add "Request to:" field */
					ti = proto_tree_add_uint(cmd_tree, hf_ipmi_response_to,
							tvb, 0, 0, rs_data->matched_frame_num);

					/* mark field as a generated one */
					PROTO_ITEM_SET_GENERATED(ti);

					/* calculate delta time */
					nstime_delta(&ns, &pinfo->abs_ts,
							&get_frame_data(data,
									rs_data->matched_frame_num)->ts);

					/* add "Response time" field */
					ti = proto_tree_add_time(cmd_tree, hf_ipmi_response_time,
							tvb, 0, 0, &ns);

					/* mark field as a generated one */
					PROTO_ITEM_SET_GENERATED(ti);
					}
			} else {
				/* get current command data */
				ipmi_cmd_data_t * rq_data =
						data->curr_frame->cmd_data[data->curr_level];

				if (rq_data->matched_frame_num) {
					/* add "Response in:" field  */
					ti = proto_tree_add_uint(cmd_tree, hf_ipmi_response_in,
							tvb, 0, 0, rq_data->matched_frame_num);

					/* mark field as a generated one */
					PROTO_ITEM_SET_GENERATED(ti);
				}
			}
		}

		/* set starting offset */
		offset = 0;

		/* check if message is broadcast */
		if (ctx->flags & IPMI_D_BROADCAST) {
			/* skip first byte */
			offset++;
		}

		/* check if session handle is specified */
		if (ctx->flags & IPMI_D_SESSION_HANDLE) {
			/* add session handle field */
			proto_tree_add_item(cmd_tree, hf_ipmi_session_handle,
					tvb, offset++, 1, ENC_LITTLE_ENDIAN);
		}

		/* check if responder address is specified */
		if (ctx->flags & IPMI_D_TRG_SA) {
			/* add response address field */
			proto_tree_add_item(cmd_tree, hf_ipmi_header_trg, tvb,
					offset++, 1, ENC_LITTLE_ENDIAN);
		}

		/* get NetFn string */
		netfn_str = ipmi_getnetfnname(ctx->hdr.netfn, cmd_list);

		/* Network function + target LUN */
		tmp_tree = proto_tree_add_subtree_format(cmd_tree, tvb, offset, 1,
				ett_header_byte_1, NULL, "Target LUN: 0x%02x, NetFN: %s %s (0x%02x)",
				ctx->hdr.rs_lun, netfn_str,
				is_resp ? "Response" : "Request", ctx->hdr.netfn);

		/* add Net Fn */
		proto_tree_add_uint_format(tmp_tree, hf_ipmi_header_netfn, tvb,
				offset, 1, ctx->hdr.netfn << 2,
				"NetFn: %s %s (0x%02x)", netfn_str,
				is_resp ? "Response" : "Request", ctx->hdr.netfn);

		proto_tree_add_item(tmp_tree, hf_ipmi_header_trg_lun, tvb,
				offset++, 1, ENC_LITTLE_ENDIAN);

		/* check if cks1 is specified */
		if (!(ctx->flags & IPMI_D_NO_CKS)) {
			guint8 cks = tvb_get_guint8(tvb, offset);

			/* Header checksum */
			if (ctx->cks1) {
				guint8 correct = cks - ctx->cks1;

				proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_crc,
						tvb, offset++, 1, cks,
						"0x%02x (incorrect, expected 0x%02x)", cks, correct);
			} else {
				proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_crc,
						tvb, offset++, 1, cks,
						"0x%02x (correct)", cks);
			}
		}

		/* check if request address is specified */
		if (!(ctx->flags & IPMI_D_NO_RQ_SA)) {
			/* add request address field */
			proto_tree_add_item(cmd_tree, hf_ipmi_header_src, tvb,
					offset++, 1, ENC_LITTLE_ENDIAN);
		}

		/* check if request sequence is specified */
		if (!(ctx->flags & IPMI_D_NO_SEQ)) {
			/* Sequence number + source LUN */
			tmp_tree = proto_tree_add_subtree_format(cmd_tree, tvb, offset, 1,
					ett_header_byte_4, NULL, "%s: 0x%02x, SeqNo: 0x%02x",
					(ctx->flags & IPMI_D_TMODE) ? "Bridged" : "Source LUN",
							ctx->hdr.rq_lun, ctx->hdr.rq_seq);

			if (ctx->flags & IPMI_D_TMODE) {
				proto_tree_add_item(tmp_tree, hf_ipmi_header_bridged,
						tvb, offset, 1, ENC_LITTLE_ENDIAN);
			} else {
				proto_tree_add_item(tmp_tree, hf_ipmi_header_src_lun,
						tvb, offset, 1, ENC_LITTLE_ENDIAN);
			}

			/* print seq no */
			proto_tree_add_item(tmp_tree, hf_ipmi_header_sequence, tvb,
					offset++, 1, ENC_LITTLE_ENDIAN);
		}

		/* command code */
		proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_command,
				tvb, offset++, 1, ctx->hdr.cmd, "%s (0x%02x)",
				cmd->desc, ctx->hdr.cmd);

		if (is_resp) {
			/* completion code */
			proto_tree_add_uint_format_value(cmd_tree,
					hf_ipmi_header_completion, tvb, offset++, 1,
					cc_val, "%s (0x%02x)", cc_str, cc_val);
		}

		if (siglen) {
			/* command prefix (if present) */
			ti = proto_tree_add_item(cmd_tree, hf_ipmi_header_sig, tvb,
					offset, siglen, ENC_NA);
			proto_item_append_text(ti, " (%s)", netfn_str);
		}
	}

	if (tree || (cmd->flags & CMD_CALLRQ)) {
		/* calculate message data length */
		guint data_len = tvb_captured_length(tvb)
				- ctx->hdr_len
				- siglen
				- (is_resp ? 1 : 0)
				- !(ctx->flags & IPMI_D_NO_CKS);

		/* create data subset */
		tvbuff_t * data_tvb = tvb_new_subset_length(tvb,
				ctx->hdr_len + siglen + (is_resp ? 1 : 0), data_len);

		/* Select sub-handler */
		ipmi_cmd_handler_t hnd = is_resp ? cmd->parse_resp : cmd->parse_req;

		if (hnd && tvb_captured_length(data_tvb)) {
			/* create data field */
			tmp_tree = proto_tree_add_subtree(cmd_tree, data_tvb, 0, -1, ett_data, NULL, "Data");

			/* save current command */
			data->curr_hdr = &ctx->hdr;

			/* save current completion code */
			data->curr_ccode = cc_val;

			/* call command parser */
			hnd(data_tvb, pinfo, tmp_tree);
		}
	}

	/* check if cks2 is specified */
	if (tree && !(ctx->flags & IPMI_D_NO_CKS)) {
		guint8 cks;

		/* get cks2 offset */
		offset = tvb_captured_length(tvb) - 1;

		/* get cks2 */
		cks = tvb_get_guint8(tvb, offset);

		/* Header checksum */
		if (ctx->cks2) {
			guint8 correct = cks - ctx->cks2;

			proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_data_crc,
					tvb, offset, 1, cks,
					"0x%02x (incorrect, expected 0x%02x)", cks, correct);
		} else {
			proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_data_crc,
					tvb, offset, 1, cks,
					"0x%02x (correct)", cks);
		}
	}

	/* decrement next nest level */
	data->next_level = data->curr_level;

	/* restore previous nest level */
	data->curr_level = prev_level;

	return tvb_captured_length(tvb);
}
Example #11
0
static int dissect_packetlogger(tvbuff_t *tvb, packet_info *pinfo,
        proto_tree *tree, void *data)
{
  proto_tree        *packetlogger_tree = NULL;
  tvbuff_t          *next_tvb;
  proto_item        *ti = NULL;
  guint8             pl_type;
  gint               len;
  bluetooth_data_t  *bluetooth_data;
  struct bthci_phdr  bthci;

  bluetooth_data = (bluetooth_data_t *) data;

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

  ti = proto_tree_add_item (tree, proto_packetlogger, tvb, 0, -1, ENC_NA);
  packetlogger_tree = proto_item_add_subtree (ti, ett_packetlogger);

  pl_type = tvb_get_guint8 (tvb, 0);
  proto_tree_add_item (packetlogger_tree, hf_type, tvb, 0, 1, ENC_BIG_ENDIAN);
  proto_item_append_text (ti, " %s", val_to_str (pl_type, type_vals, "Unknown 0x%02x"));

  len = tvb_reported_length_remaining (tvb, 1);
  next_tvb = tvb_new_subset_remaining (tvb, 1);

  if (pl_type <= PKT_RECV_ACL_DATA) {
    /* HCI H1 packages */
    switch (pl_type) {
    case PKT_HCI_COMMAND:
      bthci.channel = BTHCI_CHANNEL_COMMAND;
      bthci.sent = P2P_DIR_SENT;
      pinfo->p2p_dir = P2P_DIR_SENT;
      break;
    case PKT_HCI_EVENT:
      bthci.channel = BTHCI_CHANNEL_EVENT;
      bthci.sent = P2P_DIR_RECV;
      pinfo->p2p_dir = P2P_DIR_RECV;
      break;
    case PKT_SENT_ACL_DATA:
      bthci.channel = BTHCI_CHANNEL_ACL;
      bthci.sent = P2P_DIR_SENT;
      pinfo->p2p_dir = P2P_DIR_SENT;
      break;
    case PKT_RECV_ACL_DATA:
      bthci.channel = BTHCI_CHANNEL_ACL;
      bthci.sent = P2P_DIR_RECV;
      pinfo->p2p_dir = P2P_DIR_RECV;
      break;
    default:
      bthci.channel = pl_type;
      bthci.sent = P2P_DIR_UNKNOWN;
      pinfo->p2p_dir = P2P_DIR_UNKNOWN;
      break;
    }
    bluetooth_data->previous_protocol_data.bthci = &bthci;
    proto_item_set_len (ti, 1);

    col_add_fstr (pinfo->cinfo, COL_INFO, "%s", val_to_str(pl_type, type_vals, "Unknown 0x%02x"));
    if (!dissector_try_uint_new(hci_h1_table, bthci.channel,
            next_tvb, pinfo, tree, TRUE, bluetooth_data)) {
      call_data_dissector(next_tvb, pinfo, tree);
    }
  } else {
    /* PacketLogger data */
    switch (pl_type) {
    case PKT_POWER:
    case PKT_NOTE:
    case PKT_NEW_CONTROLLER:
      proto_tree_add_item (packetlogger_tree, hf_info, next_tvb, 0, len, ENC_ASCII|ENC_NA);
      col_add_fstr (pinfo->cinfo, COL_INFO, "%s", tvb_format_stringzpad_wsp (next_tvb, 0, len));
      break;
    default:
      call_data_dissector(next_tvb, pinfo, tree);
      col_add_fstr (pinfo->cinfo, COL_INFO, "Unknown 0x%02x", pl_type);
      break;
    }
  }

  return tvb_captured_length(tvb);
}
Example #12
0
/* XXX - "packet comment" is passed into dissector as data, but currently doesn't have a use */
static int
dissect_file_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data)
{
	proto_item  *volatile ti = NULL;
	guint	     cap_len = 0, frame_len = 0;
	proto_tree  *volatile fh_tree = NULL;
	proto_tree  *volatile tree;
	proto_item  *item;
	const gchar *cap_plurality, *frame_plurality;
	const color_filter_t *color_filter;
	file_data_t *file_data = (file_data_t*)data;

	tree=parent_tree;

	pinfo->current_proto = "File";

	/* if FILE is not referenced from any filters we don't need to worry about
	   generating any tree items.  */
	if(!proto_field_is_referenced(tree, proto_file)) {
		tree=NULL;
	} else {
		/* Put in frame header information. */
		cap_len = tvb_captured_length(tvb);
		frame_len = tvb_reported_length(tvb);

		cap_plurality = plurality(cap_len, "", "s");
		frame_plurality = plurality(frame_len, "", "s");

		ti = proto_tree_add_protocol_format(tree, proto_file, tvb, 0, -1,
		    "File record %u: %u byte%s",
		    pinfo->num, frame_len, frame_plurality);
		proto_item_append_text(ti, ", %u byte%s",
		    cap_len, cap_plurality);

		fh_tree = proto_item_add_subtree(ti, ett_file);

		proto_tree_add_int(fh_tree, hf_file_ftap_encap, tvb, 0, 0, pinfo->pkt_encap);

		proto_tree_add_uint(fh_tree, hf_file_record_number, tvb, 0, 0, pinfo->num);

		proto_tree_add_uint_format(fh_tree, hf_file_record_len, tvb,
					   0, 0, frame_len, "Record Length: %u byte%s (%u bits)",
					   frame_len, frame_plurality, frame_len * 8);

		ti = proto_tree_add_boolean(fh_tree, hf_file_marked, tvb, 0, 0,pinfo->fd->flags.marked);
		PROTO_ITEM_SET_GENERATED(ti);

		ti = proto_tree_add_boolean(fh_tree, hf_file_ignored, tvb, 0, 0,pinfo->fd->flags.ignored);
		PROTO_ITEM_SET_GENERATED(ti);

		if(pinfo->fd->pfd != 0){
			proto_item *ppd_item;
			guint num_entries = g_slist_length(pinfo->fd->pfd);
			guint i;
			ppd_item = proto_tree_add_uint(fh_tree, hf_file_num_p_prot_data, tvb, 0, 0, num_entries);
			PROTO_ITEM_SET_GENERATED(ppd_item);
			for(i=0; i<num_entries; i++){
				gchar* str = p_get_proto_name_and_key(wmem_file_scope(), pinfo, i);
				proto_tree_add_string_format(fh_tree, hf_file_proto_name_and_key, tvb, 0, 0, str, "%s", str);
			}
		}

#if 0
		if (show_file_off) {
			proto_tree_add_int64_format_value(fh_tree, hf_frame_file_off, tvb,
						    0, 0, pinfo->fd->file_off,
						    "%" G_GINT64_MODIFIER "d (0x%" G_GINT64_MODIFIER "x)",
						    pinfo->fd->file_off, pinfo->fd->file_off);
		}
#endif
	}

	if (pinfo->fd->flags.ignored) {
		/* Ignored package, stop handling here */
		col_set_str(pinfo->cinfo, COL_INFO, "<Ignored>");
		proto_tree_add_boolean_format(tree, hf_file_ignored, tvb, 0, -1, TRUE, "This record is marked as ignored");
		return tvb_captured_length(tvb);
	}

	/* Portable Exception Handling to trap Wireshark specific exceptions like BoundsError exceptions */
	TRY {
#ifdef _MSC_VER
		/* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions
		   like memory access violations.
		   (a running debugger will be called before the except part below) */
		/* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling)
		   stack in an inconsistent state thus causing a crash at some point in the
		   handling of the exception.
		   See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html
		*/
		__try {
#endif
			if (!dissector_try_uint(file_encap_dissector_table, pinfo->pkt_encap,
						tvb, pinfo, parent_tree)) {

				col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
				col_add_fstr(pinfo->cinfo, COL_INFO, "FTAP_ENCAP = %d",
					     pinfo->pkt_encap);
				call_data_dissector(tvb, pinfo, parent_tree);
			}
#ifdef _MSC_VER
		} __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) {
			switch(GetExceptionCode()) {
			case(STATUS_ACCESS_VIOLATION):
				show_exception(tvb, pinfo, parent_tree, DissectorError,
					       "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address");
				break;
			case(STATUS_INTEGER_DIVIDE_BY_ZERO):
				show_exception(tvb, pinfo, parent_tree, DissectorError,
					       "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero");
				break;
			case(STATUS_STACK_OVERFLOW):
				show_exception(tvb, pinfo, parent_tree, DissectorError,
					       "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)");
				/* XXX - this will have probably corrupted the stack,
				   which makes problems later in the exception code */
				break;
				/* XXX - add other hardware exception codes as required */
			default:
				show_exception(tvb, pinfo, parent_tree, DissectorError,
					       g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode()));
			}
		}
#endif
	}
	CATCH_BOUNDS_AND_DISSECTOR_ERRORS {
		show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE);
	}
	ENDTRY;

	if(proto_field_is_referenced(tree, hf_file_protocols)) {
		wmem_strbuf_t *val = wmem_strbuf_new(wmem_packet_scope(), "");
		wmem_list_frame_t *frame;
		/* skip the first entry, it's always the "frame" protocol */
		frame = wmem_list_frame_next(wmem_list_head(pinfo->layers));
		if (frame) {
			wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame))));
			frame = wmem_list_frame_next(frame);
		}
		while (frame) {
			wmem_strbuf_append_c(val, ':');
			wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame))));
			frame = wmem_list_frame_next(frame);
		}
		ti = proto_tree_add_string(fh_tree, hf_file_protocols, tvb, 0, 0, wmem_strbuf_get_str(val));
		PROTO_ITEM_SET_GENERATED(ti);
	}

	/*  Call postdissectors if we have any (while trying to avoid another
	 *  TRY/CATCH)
	 */
	if (have_postdissector()) {
		TRY {
#ifdef _MSC_VER
			/* Win32: Visual-C Structured Exception Handling (SEH)
			   to trap hardware exceptions like memory access violations */
			/* (a running debugger will be called before the except part below) */
			/* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling)
			   stack in an inconsistent state thus causing a crash at some point in the
			   handling of the exception.
			   See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html
			*/
			__try {
#endif
				call_all_postdissectors(tvb, pinfo, parent_tree);
#ifdef _MSC_VER
			} __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) {
				switch(GetExceptionCode()) {
				case(STATUS_ACCESS_VIOLATION):
					show_exception(tvb, pinfo, parent_tree, DissectorError,
						       "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address");
					break;
				case(STATUS_INTEGER_DIVIDE_BY_ZERO):
					show_exception(tvb, pinfo, parent_tree, DissectorError,
						       "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero");
					break;
				case(STATUS_STACK_OVERFLOW):
					show_exception(tvb, pinfo, parent_tree, DissectorError,
						       "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)");
					/* XXX - this will have probably corrupted the stack,
					   which makes problems later in the exception code */
					break;
					/* XXX - add other hardware exception codes as required */
				default:
					show_exception(tvb, pinfo, parent_tree, DissectorError,
						       g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode()));
				}
			}
#endif
		}
		CATCH_BOUNDS_AND_DISSECTOR_ERRORS {
			show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE);
		}
		ENDTRY;
	}

	/* Attempt to (re-)calculate color filters (if any). */
	if (pinfo->fd->flags.need_colorize) {
		color_filter = color_filters_colorize_packet(file_data->color_edt);
		pinfo->fd->color_filter = color_filter;
		pinfo->fd->flags.need_colorize = 0;
	} else {
		color_filter = pinfo->fd->color_filter;
	}
	if (color_filter) {
		pinfo->fd->color_filter = color_filter;
		item = proto_tree_add_string(fh_tree, hf_file_color_filter_name, tvb,
					     0, 0, color_filter->filter_name);
		PROTO_ITEM_SET_GENERATED(item);
		item = proto_tree_add_string(fh_tree, hf_file_color_filter_text, tvb,
					     0, 0, color_filter->filter_text);
		PROTO_ITEM_SET_GENERATED(item);
	}

	tap_queue_packet(file_tap, pinfo, NULL);


	if (pinfo->frame_end_routines) {
		g_slist_foreach(pinfo->frame_end_routines, &call_file_record_end_routine, NULL);
		g_slist_free(pinfo->frame_end_routines);
		pinfo->frame_end_routines = NULL;
	}

	return tvb_captured_length(tvb);
}
Example #13
0
static void
dissect_netrom_proto(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_item   *ti;
	proto_tree   *netrom_tree;
	int           offset;
#if 0
	guint8        src_ssid;
	guint8        dst_ssid;
#endif
	guint8        op_code;
	guint8        cct_index;
	guint8        cct_id;
	tvbuff_t     *next_tvb;

	col_set_str( pinfo->cinfo, COL_PROTOCOL, "NET/ROM" );
	col_clear( pinfo->cinfo, COL_INFO );

	offset = 0;

	/* source */
	set_address_tvb(&pinfo->dl_src,	AT_AX25, AX25_ADDR_LEN, tvb, offset);
	set_address_tvb(&pinfo->src,	AT_AX25, AX25_ADDR_LEN, tvb, offset);
	/* src_ssid = tvb_get_guint8(tvb, offset+6); */
	offset += AX25_ADDR_LEN; /* step over src addr */

	/* destination */
	set_address_tvb(&pinfo->dl_dst,	AT_AX25, AX25_ADDR_LEN, tvb, offset);
	set_address_tvb(&pinfo->dst,	AT_AX25, AX25_ADDR_LEN, tvb, offset);
	/* dst_ssid = tvb_get_guint8(tvb, offset+6); */
	offset += AX25_ADDR_LEN; /* step over dst addr */

	offset += 1; /* step over ttl */
	cct_index =  tvb_get_guint8( tvb, offset );
	offset += 1; /* step over cct index*/
	cct_id =  tvb_get_guint8( tvb, offset );
	offset += 1; /* step over cct id */
	offset += 1; /* step over n_s */
	offset += 1; /* step over n_r */

	/* frame type */
	op_code =  tvb_get_guint8( tvb, offset ) & 0x0f;
	/*offset += 1;*/ /* step over op_code */

	col_add_fstr( pinfo->cinfo, COL_INFO, "%s", val_to_str_const( op_code, op_code_vals_text, "Unknown" ));

	/* if ( tree ) */
		{
		/* create display subtree for the protocol */

		ti = proto_tree_add_protocol_format( tree, proto_netrom, tvb, 0, NETROM_HEADER_SIZE,
			"NET/ROM, Src: %s, Dst: %s",
			address_to_str(wmem_packet_scope(), &pinfo->src),
			address_to_str(wmem_packet_scope(), &pinfo->dst));

		netrom_tree = proto_item_add_subtree( ti, ett_netrom );

		offset = 0;

		/* source */
		proto_tree_add_item( netrom_tree, hf_netrom_src, tvb, offset, AX25_ADDR_LEN, ENC_NA );
		offset += AX25_ADDR_LEN;

		/* destination */
		proto_tree_add_item( netrom_tree, hf_netrom_dst, tvb, offset, AX25_ADDR_LEN, ENC_NA );
		offset += AX25_ADDR_LEN;

		/* ttl */
		proto_tree_add_item( netrom_tree, hf_netrom_ttl, tvb, offset, 1, ENC_BIG_ENDIAN );
		offset += 1;

		switch ( op_code )
			{
			case NETROM_PROTOEXT	:
						/* cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* unused */
						offset += 1;

						/* unused */
						offset += 1;
						break;
			case NETROM_CONNREQ	:
						/* cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* unused */
						offset += 1;

						/* unused */
						offset += 1;

						break;
			case NETROM_CONNACK	:
						/* your cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* your cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* my cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* my cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						break;
			case NETROM_DISCREQ	:
						/* your cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* your cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* unused */
						offset += 1;

						/* unused */
						offset += 1;

						break;
			case NETROM_DISCACK	:
						/* your cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* your cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* unused */
						offset += 1;

						/* unused */
						offset += 1;

						break;
			case NETROM_INFO	:
						/* your cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* your cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* n_s */
						proto_tree_add_item( netrom_tree, hf_netrom_n_s, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* n_r */
						proto_tree_add_item( netrom_tree, hf_netrom_n_r, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						break;
			case NETROM_INFOACK	:
						/* your cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* your cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* unused */
						offset += 1;

						/* n_r */
						proto_tree_add_item( netrom_tree, hf_netrom_n_r, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						break;
			default			:
						offset += 1;
						offset += 1;
						offset += 1;
						offset += 1;

						break;
			}

		/* type */
		dissect_netrom_type(	tvb,
					offset,
					pinfo,
					netrom_tree,
					hf_netrom_type,
					ett_netrom_type,
					&netrom_type_items
					);
		offset += 1;

		switch ( op_code )
			{
			case NETROM_PROTOEXT	:
						break;
			case NETROM_CONNREQ	:
						/* proposed window size */
						proto_tree_add_item( netrom_tree, hf_netrom_pwindow, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						proto_tree_add_item( netrom_tree, hf_netrom_user, tvb, offset, AX25_ADDR_LEN, ENC_NA );
						offset += AX25_ADDR_LEN;

						proto_tree_add_item( netrom_tree, hf_netrom_node, tvb, offset, AX25_ADDR_LEN, ENC_NA );
						offset += AX25_ADDR_LEN;

						break;
			case NETROM_CONNACK	:
						/* accepted window size */
						proto_tree_add_item( netrom_tree, hf_netrom_awindow, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						break;
			case NETROM_DISCREQ	:
						break;
			case NETROM_DISCACK	:
						break;
			case NETROM_INFO	:
						break;
			case NETROM_INFOACK	:
						break;
			default			:
						break;
			}
		}

	/* Call sub-dissectors here */

	next_tvb = tvb_new_subset_remaining(tvb, offset);

	switch ( op_code )
		{
		case NETROM_PROTOEXT	:
					if ( cct_index == NETROM_PROTO_IP && cct_id == NETROM_PROTO_IP )
						call_dissector( ip_handle , next_tvb, pinfo, tree );
					else
						call_data_dissector(next_tvb, pinfo, tree );

					break;
		case NETROM_INFO	:
		default			:
					call_data_dissector(next_tvb, pinfo, tree );
					break;
		}
}
Example #14
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 #15
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;
  proto_item *ti;
  gint        offset    = 0;
  guint16     opcode;
  guint16     bytes;
  guint16     blocknum;
  guint       i1;
  guint16     error;
  tvbuff_t    *data_tvb = NULL;

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

  /* Protocol root */
  ti = proto_tree_add_item(tree, proto_tftp, tvb, offset, -1, ENC_NA);
  tftp_tree = proto_item_add_subtree(ti, ett_tftp);

  /* Opcode */
  opcode = tvb_get_ntohs(tvb, offset);
  proto_tree_add_uint(tftp_tree, hf_tftp_opcode, tvb, offset, 2, opcode);
  col_add_str(pinfo->cinfo, COL_INFO,
              val_to_str(opcode, tftp_opcode_vals, "Unknown (0x%04x)"));
  offset += 2;

  /* read and write requests contain file names
     for other messages, we add the filenames from the conversation */
  if (opcode!=TFTP_RRQ && opcode!=TFTP_WRQ) {
    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);
    }
  }

  switch (opcode) {

  case TFTP_RRQ:
    i1 = tvb_strsize(tvb, offset);
    proto_tree_add_item_ret_string(tftp_tree, hf_tftp_source_file,
                        tvb, offset, i1, ENC_ASCII|ENC_NA, wmem_file_scope(), &tftp_info->source_file);

    /* we either have a source file name (for read requests) or a
       destination file name (for write requests) 
       when we set one of the names, we clear the other */
    tftp_info->destination_file = NULL;

    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_ret_string(tftp_tree, hf_tftp_destination_file,
                        tvb, offset, i1, ENC_ASCII|ENC_NA, wmem_file_scope(), &tftp_info->destination_file);

    tftp_info->source_file = NULL; /* see above */

    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);

    /* Sequence analysis on blocknums (first pass only) */
    if (!pinfo->fd->flags.visited) {
      if (blocknum > tftp_info->next_block_num) {
        /* There is a gap.  Don't try to recover from this. */
        tftp_info->next_block_num = blocknum + 1;
        tftp_info->blocks_missing = TRUE;
        /* TODO: add info to a result table for showing expert info in later passes */
      }
      else if (blocknum == tftp_info->next_block_num) {
        /* OK, inc what we expect next */
        tftp_info->next_block_num++;
      }
    }
    offset += 2;

    /* Show number of bytes in this block, and whether it is the end of the file */
    bytes = tvb_reported_length_remaining(tvb, offset);
    col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %i%s",
                    blocknum,
                    (bytes < tftp_info->blocksize)?" (last)":"" );

    /* Show data in tree */
    if (bytes > 0) {
      data_tvb = tvb_new_subset(tvb, offset, -1, bytes);
      call_data_dissector(data_tvb, pinfo, tree);
    }

    /* If Export Object tap is listening, need to accumulate blocks info list
       to send to tap. But if already know there are blocks missing, there is no
       point in trying. */
    if (have_tap_listener(tftp_eo_tap) && !tftp_info->blocks_missing) {
      file_block_t *block;

      if (blocknum == 1) {
        /* Reset data for this conversation, freeing any accumulated blocks! */
        cleanup_tftp_blocks(tftp_info);
        tftp_info->next_tap_block_num = 1;
      }

      if (blocknum != tftp_info->next_tap_block_num) {
        /* Ignore.  Could be missing frames, or just clicking previous frame */
        return;
      }

      if (bytes > 0) {
        /* Create a block for this block */
        block = (file_block_t*)g_malloc(sizeof(file_block_t));
        block->length = bytes;
        block->data = tvb_memdup(NULL, data_tvb, 0, bytes);

        /* Add to the end of the list (does involve traversing whole list..) */
        tftp_info->block_list = g_slist_append(tftp_info->block_list, block);
        tftp_info->file_length += bytes;

        /* Look for next blocknum next time */
        tftp_info->next_tap_block_num++;
      }

      /* Tap export object only when reach end of file */
      if (bytes < tftp_info->blocksize) {
        tftp_eo_t        *eo_info;

        /* If don't have a filename, won't tap file info */
        if ((tftp_info->source_file == NULL) && (tftp_info->destination_file == NULL)) {
            cleanup_tftp_blocks(tftp_info);
            return;
        }

        /* Create the eo_info to pass to the listener */
        eo_info = wmem_new(wmem_packet_scope(), tftp_eo_t);

        /* Set filename */
        if (tftp_info->source_file) {
          eo_info->filename = g_strdup(tftp_info->source_file);
        }
        else if (tftp_info->destination_file) {
          eo_info->filename = g_strdup(tftp_info->destination_file);
        }

        /* Send block list, which will be combined and freed at tap. */
        eo_info->payload_len = tftp_info->file_length;
        eo_info->pkt_num = blocknum;
        eo_info->block_list = tftp_info->block_list;

        /* Send to tap */
        tap_queue_packet(tftp_eo_tap, pinfo, eo_info);

        /* Have sent, so forget list of blocks, and only pay attention if we
           get back to the first block again. */
        tftp_info->block_list = NULL;
        tftp_info->next_tap_block_num = 1;
      }
    }
    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_item(tftp_tree, hf_tftp_data, tvb, offset, -1, ENC_NA);
    break;

  }
}
Example #16
0
static void
dissect_itdm_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  tvbuff_t  *next_tvb;
  proto_item *itdm_ctl_item = NULL;
  proto_tree *itdm_ctl_tree = NULL;
  int offset;
  guint32 flowid;
  guint8 command;
  guint32 trans_id;
  guint32 paired_trans_id;
  guint32 allocd_flowid;

  col_set_str(pinfo->cinfo, COL_PROTOCOL, "ITDM-Control");

  flowid = tvb_get_ntoh24(tvb, ITDM_FLOWID_OFFSET);
  command = tvb_get_guint8(tvb, ITDM_CTL_CMD_OFFSET);
  allocd_flowid = tvb_get_ntoh24(tvb, ITDM_CTL_FLOWID_OFFSET);
  trans_id = tvb_get_ntohl(tvb, ITDM_CTL_TRANSID_OFFSET);
  paired_trans_id = tvb_get_ntohl(tvb, ITDM_CTL_PAIRED_TRANSID_OFFSET);

  col_add_fstr(pinfo->cinfo, COL_INFO,
      "Flow %d Command %s ",
      flowid, val_to_str_const(command, itdm_ctl_command_vals, "Reserved"));

  if (command != ITDM_CTL_CMD_AFI_REQ )
  {
    col_append_fstr(pinfo->cinfo, COL_INFO,
        " Alloc'd FlowID %d", allocd_flowid);
  }

  col_append_fstr(pinfo->cinfo, COL_INFO, " TransID 0x%x ", trans_id);

  if (command != ITDM_CTL_CMD_AFI_REQ )
  {
    col_append_fstr(pinfo->cinfo, COL_INFO,
        " Paired TransID 0x%x", paired_trans_id);
  }

  offset = 0;

  if (tree)
  {
  itdm_ctl_item = proto_tree_add_item(tree, proto_itdm, tvb, 0, -1, ENC_NA);
  itdm_ctl_tree = proto_item_add_subtree(itdm_ctl_item, ett_itdm_ctl);

  /* These eventually should go into a SFP.0 dissector... */
  proto_tree_add_item(itdm_ctl_tree, hf_itdm_timestamp, tvb, offset, 2, ENC_BIG_ENDIAN);
  offset += 2;
  proto_tree_add_item(itdm_ctl_tree, hf_itdm_seqnum, tvb, offset, 1, ENC_BIG_ENDIAN);
  offset += 1;
  proto_tree_add_item(itdm_ctl_tree, hf_itdm_sop_eop, tvb, offset, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(itdm_ctl_tree, hf_itdm_last_pack, tvb, offset, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(itdm_ctl_tree, hf_itdm_pktlen, tvb, offset, 2, ENC_BIG_ENDIAN);
  offset += 2;
  proto_tree_add_item(itdm_ctl_tree, hf_itdm_chksum, tvb, offset, 2, ENC_BIG_ENDIAN);
  offset += 2;
  proto_tree_add_item(itdm_ctl_tree, hf_itdm_uid, tvb, offset, 3, ENC_BIG_ENDIAN);
  offset += 3;

  proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_transid, tvb, offset, 4, ENC_BIG_ENDIAN);
  offset += 4;

  proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_command, tvb, offset, 1, ENC_BIG_ENDIAN);
  offset += 1;
  if (command != ITDM_CTL_CMD_AFI_REQ) {
    proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_flowid, tvb, offset, 3, ENC_BIG_ENDIAN);
  }
  offset += 3;
  proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_dm, tvb, offset, 1, ENC_BIG_ENDIAN);
  offset += 1;
  /* rsvd.. */
  offset += 1;
  proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_emts, tvb, offset, 2, ENC_BIG_ENDIAN);
  offset += 2;
  proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_pktrate, tvb, offset, 4, ENC_BIG_ENDIAN);
  offset += 4;
  if (command != ITDM_CTL_CMD_AFI_REQ) {
    proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_ptid, tvb, offset, 4, ENC_BIG_ENDIAN);
  }
  offset += 4;
  /* rsvd.. */
  offset += 2;
  proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_cksum, tvb, offset, 2, ENC_BIG_ENDIAN);
  offset += 2;
  }

  next_tvb = tvb_new_subset_remaining(tvb, offset);
  call_data_dissector(next_tvb, pinfo, tree);
}
Example #17
0
static void
dissect_itdm_125usec(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  tvbuff_t  *next_tvb;
  proto_item *itdm_item = NULL;
  proto_tree *itdm_tree = NULL;
  int offset;
  guint32 flowid;
  guint32 chanid;
  guint16 chloc1;
  guint16 chloc2;
  guint8 chcmd;
  guint8 actbit;
  guint8 ackbit;


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

  flowid = tvb_get_ntoh24(tvb, ITDM_FLOWID_OFFSET);
  chanid = tvb_get_ntoh24(tvb, ITDM_CHANID_OFFSET);
  chcmd  = tvb_get_guint8(tvb, ITDM_CHCMD_OFFSET);
  chloc1 = tvb_get_ntohs(tvb, ITDM_CHLOC1_OFFSET);
  actbit = (chcmd & 0x10) ? 1 : 0;
  ackbit = (chcmd & 0x20) ? 1 : 0;
  chcmd  = chcmd & 0x0f;

  col_add_fstr(pinfo->cinfo, COL_INFO,
      "Flow %d Chan %d ACT %d ACK %d %s",
      flowid, chanid, actbit, ackbit,
      val_to_str_const(chcmd, chcmd_vals, "Reserved"));
  if (chcmd == ITDM_CMD_NEW_CHAN ||
      chcmd == ITDM_CMD_CLOSE_CHAN ||
      chcmd == ITDM_CMD_CYCLIC_REAF)
  {
    col_append_fstr(pinfo->cinfo, COL_INFO,
        " Loc1 %d", chloc1);
  }
  else if (chcmd == ITDM_CMD_RELOC_CHAN)
  {
    chloc2 = tvb_get_ntohs(tvb, ITDM_CHLOC2_OFFSET);
    col_append_fstr(pinfo->cinfo, COL_INFO,
      " Loc1 %d Loc2 %d", chloc1, chloc2);
  }

  offset = 0;

  if (tree)
  {
  itdm_item = proto_tree_add_item(tree, proto_itdm, tvb, 0, -1, ENC_NA);
  itdm_tree = proto_item_add_subtree(itdm_item, ett_itdm);

  proto_tree_add_item(itdm_tree, hf_itdm_timestamp, tvb, offset, 2, ENC_BIG_ENDIAN);
  offset += 2;
  proto_tree_add_item(itdm_tree, hf_itdm_seqnum, tvb, offset, 1, ENC_BIG_ENDIAN);
  offset += 1;
  proto_tree_add_item(itdm_tree, hf_itdm_sop_eop, tvb, offset, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(itdm_tree, hf_itdm_last_pack, tvb, offset, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(itdm_tree, hf_itdm_pktlen, tvb, offset, 2, ENC_BIG_ENDIAN);
  offset += 2;
  proto_tree_add_item(itdm_tree, hf_itdm_chksum, tvb, offset, 2, ENC_BIG_ENDIAN);
  offset += 2;
  proto_tree_add_item(itdm_tree, hf_itdm_uid, tvb, offset, 3, ENC_BIG_ENDIAN);
  offset += 3;
  proto_tree_add_item(itdm_tree, hf_itdm_ack, tvb, offset, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(itdm_tree, hf_itdm_act, tvb, offset, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(itdm_tree, hf_itdm_chcmd, tvb, offset, 1, ENC_BIG_ENDIAN);
  offset += 1;
  proto_tree_add_item(itdm_tree, hf_itdm_chid, tvb, offset, 3, ENC_BIG_ENDIAN);
  offset += 3;
  if (chcmd == ITDM_CMD_PACKET_RATE)
  {
    proto_tree_add_item(itdm_tree, hf_itdm_pktrate, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset += 4;
  }
  else
  {
    proto_tree_add_item(itdm_tree, hf_itdm_chloc1, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;
    if (chcmd == ITDM_CMD_CYCLIC_REAF ||
        chcmd == ITDM_CMD_NEW_CHAN ||
        chcmd == ITDM_CMD_CLOSE_CHAN)
    {
      proto_tree_add_item(itdm_tree, hf_itdm_cxnsize, tvb, offset, 2, ENC_BIG_ENDIAN);
      offset += 2;
    }
    else
    {
      proto_tree_add_item(itdm_tree, hf_itdm_chloc2, tvb, offset, 2, ENC_BIG_ENDIAN);
      offset += 2;
    }
  }
  }

  next_tvb = tvb_new_subset_remaining(tvb, offset);
  call_data_dissector(next_tvb, pinfo, tree);
}
Example #18
0
static void
dissect_smb_direct_payload(tvbuff_t *tvb, packet_info *pinfo,
			   proto_tree *tree, guint32 remaining_length)
{
	gboolean save_fragmented = pinfo->fragmented;
	int save_visited = pinfo->fd->flags.visited;
	conversation_t *conversation = NULL;
	fragment_head *fd_head = NULL;
	tvbuff_t *payload_tvb = NULL;
	gboolean more_frags = FALSE;
	gboolean fd_head_not_cached = FALSE;
	heur_dtbl_entry_t *hdtbl_entry;

	if (!smb_direct_reassemble) {
		payload_tvb = tvb;
		goto dissect_payload;
	}

	conversation = find_or_create_conversation(pinfo);

	if (remaining_length > 0) {
		more_frags = TRUE;
	}

	fd_head = (fragment_head *)p_get_proto_data(wmem_file_scope(), pinfo, proto_smb_direct, 0);
	if (fd_head == NULL) {
		fd_head_not_cached = TRUE;

		pinfo->fd->flags.visited = 0;
		fd_head = fragment_add_seq_next(&smb_direct_reassembly_table,
						tvb, 0, pinfo,
						conversation->index,
						NULL, tvb_captured_length(tvb),
						more_frags);
	}

	if (fd_head == NULL) {
		/*
		 * We really want the fd_head and pass it to
		 * process_reassembled_data()
		 *
		 * So that individual fragments gets the
		 * reassembled in field.
		 */
		fd_head = fragment_get_reassembled_id(&smb_direct_reassembly_table,
						      pinfo,
						      conversation->index);
	}

	if (fd_head == NULL) {
		/*
		 * we need more data...
		 */
		goto done;
	}

	if (fd_head_not_cached) {
		p_add_proto_data(wmem_file_scope(), pinfo,
				 proto_smb_direct, 0, fd_head);
	}

	payload_tvb = process_reassembled_data(tvb, 0, pinfo,
					       "Reassembled SMB Direct",
					       fd_head,
					       &smb_direct_frag_items,
					       NULL, /* update_col_info*/
					       tree);
	if (payload_tvb == NULL) {
		/*
		 * we need more data...
		 */
		goto done;
	}

dissect_payload:
	pinfo->fragmented = FALSE;
	if (!dissector_try_heuristic(smb_direct_heur_subdissector_list,
				     payload_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
		call_data_dissector(payload_tvb, pinfo, tree);
	}
done:
	pinfo->fragmented = save_fragmented;
	pinfo->fd->flags.visited = save_visited;
	return;
}
Example #19
0
static
void dissect_pw_satop(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;

	enum {
		PAY_NO_IDEA = 0
		,PAY_LIKE_E1
		,PAY_LIKE_T1
		,PAY_LIKE_E3_T3
		,PAY_LIKE_OCTET_ALIGNED_T1
	} payload_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_cw_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 = 0;
	if (0 != (tvb_get_guint8(tvb_original, 0) & 0xf0 /*bits03*/))
	{
		properties |= PWC_CW_BAD_BITS03;
	}
	if (0 != (tvb_get_guint8(tvb_original, 0) & 0x03 /*rsv*/))
	{
		properties |= PWC_CW_BAD_RSV;
	}
	if (0 != (tvb_get_guint8(tvb_original, 1) & 0xc0 /*frag*/))
	{
		properties |= PWC_CW_BAD_FRAG;
	}
	{
		/* RFC4553:
		 * [...MAY be used to carry the length of the SAToP
		 * packet (defined as the size of the SAToP header + the payload
		 * size) if it is less than 64 bytes, and MUST be set to zero
		 * otherwise... ]
		 *
		 * 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 RFC4553'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;
		}
	}
	if (payload_size == 0)
	{
		/*
		 * As CW.L it indicates that PW payload is invalid, dissector should
		 * not blame packets with bad payload (including "bad" or "strange" SIZE of
		 * payload) when L bit is set.
		 */
		if (0 == (tvb_get_guint8(tvb_original, 0) & 0x08 /*L bit*/))
		{
			properties |= PWC_PAY_SIZE_BAD;
		}
	}

	/* guess about payload type */
	if (payload_size == 256)
	{
		payload_properties = PAY_LIKE_E1;
	}
	else if (payload_size == 192)
	{
		payload_properties = PAY_LIKE_T1;
	}
	else if (payload_size == 1024)
	{
		payload_properties = PAY_LIKE_E3_T3;
	}
	else if ((payload_size != 0) && (payload_size % 25 == 0))
	{
		payload_properties = PAY_LIKE_OCTET_ALIGNED_T1;
	}
	else
	{
		payload_properties = PAY_NO_IDEA; /*we do not have any ideas about payload type*/
	}

	/* 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, ");
	}

	if (properties & PWC_PAY_SIZE_BAD)
	{
		col_append_str(pinfo->cinfo, COL_INFO, "Payload size:0 (Bad)");
	}
	else
	{
		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(item2, 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);
						}

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

						item3 = proto_tree_add_item(tree3, hf_cw_rsv, tvb, 0, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_RSV)
						{
							expert_add_info(pinfo, item3, &ei_cw_rsv);
						}

						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_payload_size_invalid,
								"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_payload_size_invalid,
								"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_payload_size_invalid,
								"Bad Length: must be 0 if SAToP packet size (%d) is > 64",
								(int)packet_size);
						}

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

		/* payload */
		if (properties & PWC_PAY_SIZE_BAD)
		{
			expert_add_info_format(pinfo, item, &ei_payload_size_invalid,
				"SAToP payload: none found. Size of payload must be <> 0");
		}
		else if (payload_size == 0)
		{
			expert_add_info(pinfo, item, &ei_payload_size_invalid_undecoded);
		}
		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");
				{
					proto_tree* tree3;
					const char* s;
					switch(payload_properties)
					{
					case PAY_LIKE_E1:
						s = " (looks like E1)";
						break;
					case PAY_LIKE_T1:
						s = " (looks like T1)";
						break;
					case PAY_LIKE_E3_T3:
						s = " (looks like E3/T3)";
						break;
					case PAY_LIKE_OCTET_ALIGNED_T1:
						s = " (looks like octet-aligned T1)";
						break;
					case PAY_NO_IDEA:
					default:
						s = "";
						break;
					}
					proto_item_append_text(item2, "%s", s);
					tree3 = proto_item_add_subtree(item2, ett);
					call_data_dissector(tvb, pinfo, tree3);
					item2 = proto_tree_add_int(tree3, 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 #20
0
static void
display_xip_serval(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree *xip_serval_tree;
	proto_item *ti, *hl_ti;
	tvbuff_t *next_tvb;

	vec_t cksum_vec;
	gint offset;
	guint8 xsh_len, protocol, bytes_remaining;

	/* Get XIP Serval header length, stored as number of 32-bit words. */
	xsh_len = tvb_get_guint8(tvb, XSRVL_LEN) << 2;

	/* Create XIP Serval header tree. */
	ti = proto_tree_add_item(tree, proto_xip_serval, tvb,
		0, xsh_len, ENC_NA);
	xip_serval_tree = proto_item_add_subtree(ti, ett_xip_serval_tree);

	/* Add XIP Serval header length. */
	hl_ti = proto_tree_add_item(xip_serval_tree, hf_xip_serval_hl, tvb,
		XSRVL_LEN, 1, ENC_BIG_ENDIAN);
	proto_item_append_text(hl_ti, " bytes");
	if (tvb_captured_length(tvb) < xsh_len)
		expert_add_info_format(pinfo, hl_ti, &ei_xip_serval_bad_len,
			"Header Length field (%d bytes) cannot be greater than actual number of bytes left in packet (%d bytes)",
			xsh_len, tvb_captured_length(tvb));

	/* Add XIP Serval protocol. If it's not data, TCP, or UDP, the
	 * packet is malformed.
	 */
	proto_tree_add_item(xip_serval_tree, hf_xip_serval_proto, tvb,
		XSRVL_PRO, 1, ENC_BIG_ENDIAN);
	protocol = tvb_get_guint8(tvb, XSRVL_PRO);
	if (!try_val_to_str(protocol, xip_serval_proto_vals))
		expert_add_info_format(pinfo, ti, &ei_xip_serval_bad_proto,
			"Unrecognized protocol type: %d", protocol);

	/* Compute checksum. */
	SET_CKSUM_VEC_TVB(cksum_vec, tvb, 0, xsh_len);

	proto_tree_add_checksum(xip_serval_tree, tvb, XSRVL_CHK, hf_xip_serval_check, -1, &ei_xip_serval_bad_checksum, pinfo, in_cksum(&cksum_vec, 1),
							ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
	offset = XSRVL_EXT;

	/* If there's still more room, check for extension headers. */
	bytes_remaining = xsh_len - offset;
	while (bytes_remaining >= XIP_SERVAL_EXT_MIN_LEN) {
		gint8 bytes_displayed = display_xip_serval_ext(tvb, pinfo, ti,
			xip_serval_tree, offset);

		/* Extension headers are malformed, so we can't say
		 * what the rest of the packet holds. Stop dissecting.
		 */
		if (bytes_displayed <= 0)
			return;

		offset += bytes_displayed;
		bytes_remaining -= bytes_displayed;
	}

	switch (protocol) {
	case XIP_SERVAL_PROTO_DATA:
		next_tvb = tvb_new_subset_remaining(tvb, offset);
		call_data_dissector(next_tvb, pinfo, tree);
		break;
	case IP_PROTO_TCP: {
		/* Get the Data Offset field of the TCP header, which is
		 * the high nibble of the 12th octet and represents the
		 * size of the TCP header of 32-bit words.
		 */
		guint8 tcp_len = hi_nibble(tvb_get_guint8(tvb, offset + 12))*4;
		next_tvb = tvb_new_subset(tvb, offset, tcp_len, tcp_len);
		call_dissector(tcp_handle, next_tvb, pinfo, tree);
		break;
	}
	case IP_PROTO_UDP:
		/* The UDP header is always 8 bytes. */
		next_tvb = tvb_new_subset(tvb, offset, 8, 8);
		call_dissector(udp_handle, next_tvb, pinfo, tree);
		break;
	default:
		break;
	}
}
Example #21
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)
*/
static int
dissect_ethertype(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
	const char	  *description;
	tvbuff_t	  *volatile next_tvb;
	guint		   length_before;
	gint		   captured_length, reported_length;
	volatile int  dissector_found = 0;
	const char	  *volatile saved_proto;
	ethertype_data_t  *ethertype_data;

	/* Reject the packet if data is NULL */
	if (data == NULL)
		return 0;
	ethertype_data = (ethertype_data_t*)data;

	/* Add the Ethernet type to the protocol tree */
	proto_tree_add_uint(ethertype_data->fh_tree, ethertype_data->etype_id, tvb,
				    ethertype_data->offset_after_ethertype - 2, 2, ethertype_data->etype);

	/* Get the captured length and reported length of the data
	   after the Ethernet type. */
	captured_length = tvb_captured_length_remaining(tvb, ethertype_data->offset_after_ethertype);
	reported_length = tvb_reported_length_remaining(tvb,
							ethertype_data->offset_after_ethertype);

	/* 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 (ethertype_data->fcs_len > 0) {
		if (captured_length >= 0 && reported_length >= 0) {
			if (reported_length >= ethertype_data->fcs_len)
				reported_length -= ethertype_data->fcs_len;
			if (captured_length > reported_length)
				captured_length = reported_length;
		}
	}
	next_tvb = tvb_new_subset(tvb, ethertype_data->offset_after_ethertype, captured_length,
				  reported_length);

	p_add_proto_data(pinfo->pool, pinfo, proto_ethertype, 0, GUINT_TO_POINTER((guint)ethertype_data->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_uint(ethertype_dissector_table,
						     ethertype_data->etype, 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. */
		show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);

		dissector_found = 1;
		pinfo->current_proto = saved_proto;
	}
	ENDTRY;

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

		/* Label protocol */
		col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", ethertype_data->etype);

		description = try_val_to_str(ethertype_data->etype, etype_vals);
		if (description) {
			col_add_str(pinfo->cinfo, COL_INFO, description);
		}
	}

	add_dix_trailer(pinfo, tree, ethertype_data->fh_tree, ethertype_data->trailer_id, tvb, next_tvb, ethertype_data->offset_after_ethertype,
			length_before, ethertype_data->fcs_len);

	return tvb_captured_length(tvb);
}
Example #22
0
/* G.7041 6.1.2 GFP payload area */
static void
dissect_gfp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *gfp_tree, guint *offset, guint payload_len)
{
    tvbuff_t *payload_tvb;
    proto_item *type_ti = NULL;
    proto_item *fcs_ti;
    proto_tree *fcs_tree = NULL;
    guint pti, pfi, exi, upi;
    guint fcs, fcs_calc;
    guint fcs_len = 0;

    /* G.7041 6.1.2.3 Payload area scrambling
     * Note that payload when sent on the wire is scrambled as per ATM
     * with a 1 + x^43 multiplicative scrambler. Likely already removed by
     * the time we get a capture file (as with ATM). Could have a pref,
     * but if it's present we have to save state over subsequent frames,
     * always would fail to decode the first 43 payload bytes of a capture. */

    /* G.7041 6.1.2.1 Payload Header - at least 4 bytes */
    tvb_ensure_bytes_exist(tvb, *offset, 4);
    payload_len -= 4;

    /* G.7041 6.1.2.1.1 GFP type field - mandatory 2 bytes */
    pti = tvb_get_bits8(tvb, 8*(*offset), 3);
    pfi = tvb_get_bits8(tvb, 8*(*offset)+3, 1);
    exi = tvb_get_bits8(tvb, 8*(*offset)+4, 4);
    upi = tvb_get_guint8(tvb, *offset+1);
    p_add_proto_data(pinfo->pool, pinfo, proto_gfp, 0, GUINT_TO_POINTER(upi));

    col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pti, gfp_pti_vals, "Reserved PTI (%d)"));
    if (pti == GFP_USER_DATA ||
            pti == GFP_MANAGEMENT_COMMUNICATIONS) {
        /* G.7041 Table 6-3 - GFP_MANAGEMENT_COMMUNICATIONS
         * uses the same UPI table as USER_DATA, though
         * "not all of these UPI types are applicable" in that case. */
        type_ti = proto_tree_add_bitmask_with_flags(gfp_tree, tvb, *offset, hf_gfp_type,
                  ett_gfp_type, gfp_type_data_fields, ENC_BIG_ENDIAN, BMT_NO_FLAGS);
        col_append_sep_str(pinfo->cinfo, COL_INFO, ": ", rval_to_str(upi, gfp_upi_data_rvals, "Unknown 0x%02x"));
    } else if (pti == GFP_CLIENT_MANAGEMENT) {
        /* G.7041 Table 6-4 */
        type_ti = proto_tree_add_bitmask_with_flags(gfp_tree, tvb, *offset, hf_gfp_type,
                  ett_gfp_type, gfp_type_management_fields, ENC_BIG_ENDIAN, BMT_NO_FLAGS);
        col_append_sep_str(pinfo->cinfo, COL_INFO, ": ", rval_to_str(upi, gfp_upi_management_rvals, "Unknown 0x%02x"));
    }

    /* G.7041 6.1.2.1.2 Type HEC (tHEC) - mandatory 2 bytes */
    gfp_add_hec_tree(tvb, pinfo, gfp_tree, offset, 2, hf_gfp_thec, hf_gfp_thec_status, &ei_gfp_thec_bad);

    switch (exi) {
    case GFP_EXT_NULL:
        /* G.7041 6.1.2.1.3.1 Null extension header */
        break;

    case GFP_EXT_LINEAR:
        /* G.7041 6.1.2.1.3.2 Extension header for a linear frame */
        if (payload_len < 4) {
            expert_add_info(pinfo, type_ti, &ei_gfp_exi_short);
            payload_len = 0;
        }
        else {
            payload_len -= 4;
        }
        proto_tree_add_item(gfp_tree, hf_gfp_cid, tvb, *offset, 1, ENC_BIG_ENDIAN);
        /* Next byte spare field, reserved */

        /* 6.1.2.1.4 Extension HEC field */
        gfp_add_hec_tree(tvb, pinfo, gfp_tree, offset, 2, hf_gfp_ehec, hf_gfp_ehec_status, &ei_gfp_ehec_bad);
        break;
    case GFP_EXT_RING:
    /* 6.1.2.1.3.3 Extension header for a ring frame */
    /* "For further study." Undefined so fall through */
    default:
        /* Reserved */
        /* TODO: Mark as error / unhandled? */
        break;
    }

    proto_item_set_end(gfp_tree, tvb, *offset);

    if (pfi == 1) { /* 6.1.2.2.1 Payload FCS field present */
        if (payload_len < 4) {
            expert_add_info(pinfo, type_ti, &ei_gfp_pfi_short);
            fcs_len = payload_len;
            payload_len = 0;
        } else {
            fcs_len = 4;
            payload_len -= 4;
        }

        proto_tree_set_appendix(gfp_tree, tvb, *offset + payload_len, fcs_len);
        fcs = tvb_get_ntohl(tvb, *offset + payload_len);
        /* Same CRC32 as ATM */
        /* As with ATM, we can either compute the CRC as it would be
         * calculated and compare (last step involves taking the complement),
         * or we can include the passed CRC in the input and check to see
         * if the remainder is a known value. I like the first method
         * only because it lets us display what we should have received. */
        /* Method 1: */
        fcs_calc = crc32_mpeg2_tvb_offset(tvb, *offset, payload_len);
        if (fcs == ~fcs_calc) {
            fcs_ti = proto_tree_add_uint_format_value(gfp_tree, hf_gfp_fcs, tvb, *offset+payload_len, 4, fcs, "0x%08x [correct]", fcs);
            fcs_tree = proto_item_add_subtree(fcs_ti, ett_gfp_fcs);
            fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_good, tvb, *offset+payload_len, 4, TRUE);
            PROTO_ITEM_SET_GENERATED(fcs_ti);
            fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_bad, tvb, *offset+payload_len, 4, FALSE);
            PROTO_ITEM_SET_GENERATED(fcs_ti);
        } else {
            fcs_ti = proto_tree_add_uint_format_value(gfp_tree, hf_gfp_fcs, tvb, *offset+payload_len, 4, fcs, "0x%08x [incorrect, should be 0x%08x]", fcs, fcs_calc);
            fcs_tree = proto_item_add_subtree(fcs_ti, ett_gfp_fcs);
            fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_good, tvb, *offset+payload_len, 4, FALSE);
            PROTO_ITEM_SET_GENERATED(fcs_ti);
            fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_bad, tvb, *offset+payload_len, 4, TRUE);
            PROTO_ITEM_SET_GENERATED(fcs_ti);
            expert_add_info(pinfo, fcs_ti, &ei_gfp_fcs_bad);
        }
        /* Method 2: */
        /* fcs_calc = crc32_mpeg2_tvb_offset(tvb, *offset, payload_len+4);
        fcs_ti = proto_tree_add_uint(gfp_tree, hf_gfp_fcs, tvb, *offset+payload_len, 4, fcs);
        proto_item_append_text(fcs_ti, (fcs_calc == 0xC704DD7B) ? " [correct]" : " [incorrect]"); */
    }

    /* Some client frames we can do. Others are not implemented yet.
     * Transparent mode types are much trickier than frame-mapped,
     * since they requires reassembling streams across multiple GFP packets. */
    payload_tvb = tvb_new_subset_length(tvb, *offset, payload_len);
    switch (pti) {
    case GFP_USER_DATA:
    case GFP_MANAGEMENT_COMMUNICATIONS:
        if (!dissector_try_uint(gfp_dissector_table, upi, payload_tvb, pinfo, tree)) {
            expert_add_info_format(pinfo, type_ti, &ei_gfp_payload_undecoded, "Payload type 0x%02x (%s) unsupported", upi, rval_to_str_const(upi, gfp_upi_data_rvals, "UNKNOWN"));
            call_data_dissector(payload_tvb, pinfo, tree);
        }
        break;

    case GFP_CLIENT_MANAGEMENT:
        call_data_dissector(payload_tvb, pinfo, tree);
        break;

    default:
        break;
    }
    *offset += payload_len;
    *offset += fcs_len;
}